Update shape string format.

This commit is contained in:
Ottermandias 2025-05-15 22:23:33 +02:00
parent 70295b7a6b
commit c0dcfdd835
4 changed files with 18 additions and 32 deletions

View file

@ -1,4 +1,3 @@
using Lumina.Models.Models;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using Penumbra.GameData.Data; using Penumbra.GameData.Data;
@ -61,34 +60,16 @@ public readonly record struct ShpIdentifier(HumanSlot Slot, PrimaryId? Id, Shape
return ValidateCustomShapeString(Shape); return ValidateCustomShapeString(Shape);
} }
public static bool ValidateCustomShapeString(ReadOnlySpan<byte> shape)
{
// "shp_xx_y"
if (shape.Length < 8)
return false;
if (shape[0] is not (byte)'s'
|| shape[1] is not (byte)'h'
|| shape[2] is not (byte)'p'
|| shape[3] is not (byte)'_'
|| shape[6] is not (byte)'_')
return false;
return true;
}
public static unsafe bool ValidateCustomShapeString(byte* shape) public static unsafe bool ValidateCustomShapeString(byte* shape)
{ {
// "shp_xx_y" // "shpx_*"
if (shape is null) if (shape is null)
return false; return false;
if (*shape++ is not (byte)'s' if (*shape++ is not (byte)'s'
|| *shape++ is not (byte)'h' || *shape++ is not (byte)'h'
|| *shape++ is not (byte)'p' || *shape++ is not (byte)'p'
|| *shape++ is not (byte)'_' || *shape++ is not (byte)'x'
|| *shape++ is 0
|| *shape++ is 0
|| *shape++ is not (byte)'_' || *shape++ is not (byte)'_'
|| *shape is 0) || *shape is 0)
return false; return false;
@ -98,16 +79,16 @@ public readonly record struct ShpIdentifier(HumanSlot Slot, PrimaryId? Id, Shape
public static bool ValidateCustomShapeString(in ShapeString shape) public static bool ValidateCustomShapeString(in ShapeString shape)
{ {
// "shp_xx_y" // "shpx_*"
if (shape.Length < 8) if (shape.Length < 6)
return false; return false;
var span = shape.AsSpan; var span = shape.AsSpan;
if (span[0] is not (byte)'s' if (span[0] is not (byte)'s'
|| span[1] is not (byte)'h' || span[1] is not (byte)'h'
|| span[2] is not (byte)'p' || span[2] is not (byte)'p'
|| span[3] is not (byte)'_' || span[3] is not (byte)'x'
|| span[6] is not (byte)'_') || span[4] is not (byte)'_')
return false; return false;
return true; return true;

View file

@ -93,13 +93,13 @@ public class ShapeManager : IRequiredService, IDisposable
{ {
foreach (var (shape, topIndex) in _temporaryIndices[1]) foreach (var (shape, topIndex) in _temporaryIndices[1])
{ {
if (shape[4] is (byte)'w' && shape[5] is (byte)'r' && _temporaryIndices[2].TryGetValue(shape, out var handIndex)) if (CheckCenter(shape, 'w', 'r') && _temporaryIndices[2].TryGetValue(shape, out var handIndex))
{ {
_temporaryValues[1] |= 1u << topIndex; _temporaryValues[1] |= 1u << topIndex;
_temporaryValues[2] |= 1u << handIndex; _temporaryValues[2] |= 1u << handIndex;
} }
if (shape[4] is (byte)'w' && shape[5] is (byte)'a' && _temporaryIndices[3].TryGetValue(shape, out var legIndex)) if (CheckCenter(shape, 'w', 'a') && _temporaryIndices[3].TryGetValue(shape, out var legIndex))
{ {
_temporaryValues[1] |= 1u << topIndex; _temporaryValues[1] |= 1u << topIndex;
_temporaryValues[3] |= 1u << legIndex; _temporaryValues[3] |= 1u << legIndex;
@ -108,11 +108,15 @@ public class ShapeManager : IRequiredService, IDisposable
foreach (var (shape, bottomIndex) in _temporaryIndices[3]) foreach (var (shape, bottomIndex) in _temporaryIndices[3])
{ {
if (shape[4] is (byte)'a' && shape[5] is (byte)'n' && _temporaryIndices[4].TryGetValue(shape, out var footIndex)) if (CheckCenter(shape, 'a', 'n') && _temporaryIndices[4].TryGetValue(shape, out var footIndex))
{ {
_temporaryValues[3] |= 1u << bottomIndex; _temporaryValues[3] |= 1u << bottomIndex;
_temporaryValues[4] |= 1u << footIndex; _temporaryValues[4] |= 1u << footIndex;
} }
} }
} }
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
private static bool CheckCenter(in ShapeString shape, char first, char second)
=> shape.Length > 8 && shape[4] == first && shape[5] == second && shape[6] is (byte)'_';
} }

View file

@ -19,7 +19,7 @@ public sealed class ShpMetaDrawer(ModMetaEditor editor, MetaFileManager metaFile
public override ReadOnlySpan<byte> Label public override ReadOnlySpan<byte> Label
=> "Shape Keys (SHP)###SHP"u8; => "Shape Keys (SHP)###SHP"u8;
private ShapeString _buffer = ShapeString.TryRead("shp_"u8, out var s) ? s : ShapeString.Empty; private ShapeString _buffer = ShapeString.TryRead("shpx_"u8, out var s) ? s : ShapeString.Empty;
private bool _identifierValid; private bool _identifierValid;
public override int NumColumns public override int NumColumns
@ -200,7 +200,7 @@ public sealed class ShpMetaDrawer(ModMetaEditor editor, MetaFileManager metaFile
} }
} }
ImUtf8.HoverTooltip("Supported shape keys need to have the format `shp_xx_*` and a maximum length of 30 characters."u8); ImUtf8.HoverTooltip("Supported shape keys need to have the format `shpx_*` and a maximum length of 30 characters."u8);
return ret; return ret;
} }

View file

@ -13,8 +13,9 @@
}, },
"Shape": { "Shape": {
"type": "string", "type": "string",
"minLength": 8, "minLength": 5,
"maxLength": 30 "maxLength": 30,
"pattern": "^shpx_"
} }
}, },
"required": [ "required": [