Skip to content

Commit

Permalink
Merge remote-tracking branch 'Exter-N/material-editor-adjustments'
Browse files Browse the repository at this point in the history
  • Loading branch information
Ottermandias committed Sep 2, 2023
2 parents 0741ce0 + 1b49051 commit 0528110
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 46 deletions.
37 changes: 11 additions & 26 deletions Penumbra/Interop/MaterialPreview/LiveColorSetPreviewer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using FFXIVClientStructs.FFXIV.Client.Graphics.Kernel;
using FFXIVClientStructs.FFXIV.Client.Graphics.Render;
using Penumbra.GameData.Files;
using Penumbra.Interop.SafeHandles;

namespace Penumbra.Interop.MaterialPreview;

Expand All @@ -16,8 +17,8 @@ public sealed unsafe class LiveColorSetPreviewer : LiveMaterialPreviewerBase

private readonly Framework _framework;

private readonly Texture** _colorSetTexture;
private readonly Texture* _originalColorSetTexture;
private readonly Texture** _colorSetTexture;
private readonly SafeTextureHandle _originalColorSetTexture;

private Half[] _colorSet;
private bool _updatePending;
Expand All @@ -40,12 +41,10 @@ public LiveColorSetPreviewer(IObjectTable objects, Framework framework, Material

_colorSetTexture = colorSetTextures + (MaterialInfo.ModelSlot * 4 + MaterialInfo.MaterialSlot);

_originalColorSetTexture = *_colorSetTexture;
_originalColorSetTexture = new SafeTextureHandle(*_colorSetTexture, true);
if (_originalColorSetTexture == null)
throw new InvalidOperationException("Material doesn't have a color set");

Structs.TextureUtility.IncRef(_originalColorSetTexture);

_colorSet = new Half[TextureLength];
_updatePending = true;

Expand All @@ -59,15 +58,9 @@ protected override void Clear(bool disposing, bool reset)
base.Clear(disposing, reset);

if (reset)
{
var oldTexture = (Texture*)Interlocked.Exchange(ref *(nint*)_colorSetTexture, (nint)_originalColorSetTexture);
if (oldTexture != null)
Structs.TextureUtility.DecRef(oldTexture);
}
else
{
Structs.TextureUtility.DecRef(_originalColorSetTexture);
}
_originalColorSetTexture.Exchange(ref *(nint*)_colorSetTexture);

_originalColorSetTexture.Dispose();
}

public void ScheduleUpdate()
Expand All @@ -89,29 +82,21 @@ private void OnFrameworkUpdate(Framework _)
textureSize[0] = TextureWidth;
textureSize[1] = TextureHeight;

var newTexture = Structs.TextureUtility.Create2D(Device.Instance(), textureSize, 1, 0x2460, 0x80000804, 7);
if (newTexture == null)
using var texture = new SafeTextureHandle(Structs.TextureUtility.Create2D(Device.Instance(), textureSize, 1, 0x2460, 0x80000804, 7), false);
if (texture.IsInvalid)
return;

bool success;
lock (_colorSet)
{
fixed (Half* colorSet = _colorSet)
{
success = Structs.TextureUtility.InitializeContents(newTexture, colorSet);
success = Structs.TextureUtility.InitializeContents(texture.Texture, colorSet);
}
}

if (success)
{
var oldTexture = (Texture*)Interlocked.Exchange(ref *(nint*)_colorSetTexture, (nint)newTexture);
if (oldTexture != null)
Structs.TextureUtility.DecRef(oldTexture);
}
else
{
Structs.TextureUtility.DecRef(newTexture);
}
texture.Exchange(ref *(nint*)_colorSetTexture);
}

protected override bool IsStillValid()
Expand Down
48 changes: 48 additions & 0 deletions Penumbra/Interop/SafeHandles/SafeTextureHandle.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using System;
using System.Runtime.InteropServices;
using System.Threading;
using FFXIVClientStructs.FFXIV.Client.Graphics.Render;
using Penumbra.Interop.Structs;

namespace Penumbra.Interop.SafeHandles;

public unsafe class SafeTextureHandle : SafeHandle
{
public Texture* Texture => (Texture*)handle;

public override bool IsInvalid => handle == 0;

public SafeTextureHandle(Texture* handle, bool incRef, bool ownsHandle = true) : base(0, ownsHandle)
{
if (incRef && !ownsHandle)
throw new ArgumentException("Non-owning SafeTextureHandle with IncRef is unsupported");
if (incRef && handle != null)
TextureUtility.IncRef(handle);
SetHandle((nint)handle);
}

public void Exchange(ref nint ppTexture)
{
lock (this)
{
handle = Interlocked.Exchange(ref ppTexture, handle);
}
}

public static SafeTextureHandle CreateInvalid()
=> new(null, incRef: false);

protected override bool ReleaseHandle()
{
nint handle;
lock (this)
{
handle = this.handle;
this.handle = 0;
}
if (handle != 0)
TextureUtility.DecRef((Texture*)handle);

return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public partial class ModEditWindow
{
private interface IConstantEditor
{
bool Draw(Span<float> values, bool disabled, float editorWidth);
bool Draw(Span<float> values, bool disabled);
}

private sealed class FloatConstantEditor : IConstantEditor
Expand Down Expand Up @@ -42,16 +42,18 @@ public FloatConstantEditor(float? minimum, float? maximum, float speed, float re
_format = $"{_format} {unit.Replace("%", "%%")}";
}

public bool Draw(Span<float> values, bool disabled, float editorWidth)
public bool Draw(Span<float> values, bool disabled)
{
var fieldWidth = (editorWidth - (values.Length - 1) * ImGui.GetStyle().ItemSpacing.X) / values.Length;
var spacing = ImGui.GetStyle().ItemInnerSpacing.X;
var fieldWidth = (ImGui.CalcItemWidth() - (values.Length - 1) * spacing) / values.Length;

var ret = false;

// Not using DragScalarN because of _relativeSpeed and other points of lost flexibility.
for (var valueIdx = 0; valueIdx < values.Length; ++valueIdx)
{
if (valueIdx > 0)
ImGui.SameLine();
ImGui.SameLine(0.0f, spacing);

ImGui.SetNextItemWidth(MathF.Round(fieldWidth * (valueIdx + 1)) - MathF.Round(fieldWidth * valueIdx));

Expand Down Expand Up @@ -101,16 +103,18 @@ public IntConstantEditor(int? minimum, int? maximum, float speed, float relative
_format = $"{_format} {unit.Replace("%", "%%")}";
}

public bool Draw(Span<float> values, bool disabled, float editorWidth)
public bool Draw(Span<float> values, bool disabled)
{
var fieldWidth = (editorWidth - (values.Length - 1) * ImGui.GetStyle().ItemSpacing.X) / values.Length;
var spacing = ImGui.GetStyle().ItemInnerSpacing.X;
var fieldWidth = (ImGui.CalcItemWidth() - (values.Length - 1) * spacing) / values.Length;

var ret = false;

// Not using DragScalarN because of _relativeSpeed and other points of lost flexibility.
for (var valueIdx = 0; valueIdx < values.Length; ++valueIdx)
{
if (valueIdx > 0)
ImGui.SameLine();
ImGui.SameLine(0.0f, spacing);

ImGui.SetNextItemWidth(MathF.Round(fieldWidth * (valueIdx + 1)) - MathF.Round(fieldWidth * valueIdx));

Expand Down Expand Up @@ -148,13 +152,12 @@ public ColorConstantEditor(bool squaredRgb, bool clamped)
_clamped = clamped;
}

public bool Draw(Span<float> values, bool disabled, float editorWidth)
public bool Draw(Span<float> values, bool disabled)
{
switch (values.Length)
{
case 3:
{
ImGui.SetNextItemWidth(editorWidth);
var value = new Vector3(values);
if (_squaredRgb)
value = PseudoSqrtRgb(value);
Expand All @@ -170,7 +173,6 @@ public bool Draw(Span<float> values, bool disabled, float editorWidth)
}
case 4:
{
ImGui.SetNextItemWidth(editorWidth);
var value = new Vector4(values);
if (_squaredRgb)
value = PseudoSqrtRgb(value);
Expand All @@ -186,7 +188,7 @@ public bool Draw(Span<float> values, bool disabled, float editorWidth)
value.CopyTo(values);
return true;
}
default: return FloatConstantEditor.Default.Draw(values, disabled, editorWidth);
default: return FloatConstantEditor.Default.Draw(values, disabled);
}
}
}
Expand All @@ -198,17 +200,18 @@ private sealed class EnumConstantEditor : IConstantEditor
public EnumConstantEditor(IReadOnlyList<(string Label, float Value, string Description)> values)
=> _values = values;

public bool Draw(Span<float> values, bool disabled, float editorWidth)
public bool Draw(Span<float> values, bool disabled)
{
var fieldWidth = (editorWidth - (values.Length - 1) * ImGui.GetStyle().ItemSpacing.X) / values.Length;
var spacing = ImGui.GetStyle().ItemInnerSpacing.X;
var fieldWidth = (ImGui.CalcItemWidth() - (values.Length - 1) * spacing) / values.Length;

var ret = false;

for (var valueIdx = 0; valueIdx < values.Length; ++valueIdx)
{
using var id = ImRaii.PushId(valueIdx);
if (valueIdx > 0)
ImGui.SameLine();
ImGui.SameLine(0.0f, spacing);

ImGui.SetNextItemWidth(MathF.Round(fieldWidth * (valueIdx + 1)) - MathF.Round(fieldWidth * valueIdx));

Expand Down
10 changes: 6 additions & 4 deletions Penumbra/UI/AdvancedWindow/ModEditWindow.Materials.MtrlTab.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
using Penumbra.Interop.MaterialPreview;
using Penumbra.String;
using Penumbra.String.Classes;
using Penumbra.UI.Classes;
using static Penumbra.GameData.Files.ShpkFile;

namespace Penumbra.UI.AdvancedWindow;
Expand Down Expand Up @@ -177,7 +178,7 @@ public void LoadShpk(FullPath path)

if (mayVary && (data as JObject)?["Vary"] != null)
{
var selector = BuildSelector(data["Vary"]!
var selector = BuildSelector(data!["Vary"]!
.Select(key => (uint)key)
.Select(key => Mtrl.GetShaderKey(key)?.Value ?? AssociatedShpk!.GetMaterialKeyById(key)!.Value.DefaultValue));
var index = (int)data["Selectors"]![selector.ToString()]!;
Expand Down Expand Up @@ -668,12 +669,13 @@ public void UpdateColorSetPreview()

private static void ApplyHighlight(ref MtrlFile.ColorSet.Row row, float time)
{
var level = Math.Sin(time * 2.0 * Math.PI) * 0.25 + 0.5;
var levelSq = (float)(level * level);
var level = (MathF.Sin(time * 2.0f * MathF.PI) + 2.0f) / 3.0f / 255.0f;
var baseColor = ColorId.InGameHighlight.Value();
var color = level * new Vector3(baseColor & 0xFF, (baseColor >> 8) & 0xFF, (baseColor >> 16) & 0xFF);

row.Diffuse = Vector3.Zero;
row.Specular = Vector3.Zero;
row.Emissive = new Vector3(levelSq);
row.Emissive = color * color;
}

public void Update()
Expand Down
3 changes: 2 additions & 1 deletion Penumbra/UI/AdvancedWindow/ModEditWindow.Materials.Shpk.cs
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,8 @@ private static bool DrawMaterialConstants(MtrlTab tab, bool disabled)
if (buffer.Length > 0)
{
using var id = ImRaii.PushId($"##{constant.Id:X8}:{slice.Start}");
if (editor.Draw(buffer[slice], disabled, 250.0f))
ImGui.SetNextItemWidth(250.0f);
if (editor.Draw(buffer[slice], disabled))
{
ret = true;
tab.SetMaterialParameter(constant.Id, slice.Start, buffer[slice]);
Expand Down
4 changes: 3 additions & 1 deletion Penumbra/UI/Classes/Colors.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ public enum ColorId
RedundantAssignment,
NoModsAssignment,
NoAssignment,
SelectorPriority,
SelectorPriority,
InGameHighlight,
}

public static class Colors
Expand Down Expand Up @@ -64,6 +65,7 @@ public static (uint DefaultColor, string Name, string Description) Data(this Col
ColorId.NoModsAssignment => ( 0x50000080, "'Use No Mods' Collection Assignment", "A collection assignment set to not use any mods at all."),
ColorId.NoAssignment => ( 0x00000000, "Unassigned Collection Assignment", "A collection assignment that is not configured to any collection and thus just has no specific treatment."),
ColorId.SelectorPriority => ( 0xFF808080, "Mod Selector Priority", "The priority displayed for non-zero priority mods in the mod selector."),
ColorId.InGameHighlight => ( 0xFFEBCF89, "In-Game Highlight", "An in-game element that has been highlighted for ease of editing."),
_ => throw new ArgumentOutOfRangeException( nameof( color ), color, null ),
// @formatter:on
};
Expand Down

0 comments on commit 0528110

Please sign in to comment.