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

View file

@ -93,13 +93,13 @@ public class ShapeManager : IRequiredService, IDisposable
{
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[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[3] |= 1u << legIndex;
@ -108,11 +108,15 @@ public class ShapeManager : IRequiredService, IDisposable
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[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
=> "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;
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;
}

View file

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