mirror of
https://github.com/sampletext32/ParkanPlayground.git
synced 2026-08-15 02:57:49 +04:00
vibecoded inspector
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
using System.Numerics;
|
||||
using MshLib;
|
||||
|
||||
namespace NResUI.Rendering.Inspection;
|
||||
|
||||
/// <summary>
|
||||
/// CPU-документ меша: общая модель данных для viewport и inspector до загрузки в OpenGL.
|
||||
/// Здесь хранятся ссылки на исходные MSH-компоненты и уже удобные для UI metadata.
|
||||
/// </summary>
|
||||
public sealed class MeshDocument
|
||||
{
|
||||
/// <summary>Путь к MSH/NRes ресурсу, из которого построен документ.</summary>
|
||||
public required string SourcePath { get; init; }
|
||||
|
||||
/// <summary>Тип MSH по набору компонентов. Сейчас inspector поддерживает только обычный Model.</summary>
|
||||
public required MshType MeshType { get; init; }
|
||||
|
||||
/// <summary>Список pieces из 0x01. Каждый piece сам выбирает slot для state/LOD.</summary>
|
||||
public IReadOnlyList<MeshPieceInfo> Pieces { get; init; } = [];
|
||||
|
||||
/// <summary>Материалы, пришедшие из WEA. Текстуры резолвятся отдельно, потому что это уже UI/OpenGL слой.</summary>
|
||||
public IReadOnlyList<MeshMaterialInfo> Materials { get; init; } = [];
|
||||
|
||||
/// <summary>Нефатальные проблемы загрузки: отсутствующие optional-компоненты, WEA/material/texture misses.</summary>
|
||||
public IReadOnlyList<string> Warnings { get; init; } = [];
|
||||
|
||||
/// <summary>Количество известных model states в 0x01 таблице.</summary>
|
||||
public int ModelStateCount { get; init; } = Msh0x01.StateCount;
|
||||
|
||||
/// <summary>Количество LOD-уровней на каждый state в 0x01 таблице.</summary>
|
||||
public int LodCount { get; init; } = Msh0x01.MaxLodCount;
|
||||
|
||||
/// <summary>Сырые MSH-потоки, нужные для перестройки GPU-мешей при смене state/LOD.</summary>
|
||||
public MshModelGeometry? MshModelGeometry { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Информация об одном piece/node из 0x01.
|
||||
/// Важно: state/LOD не глобальны, поэтому этот объект хранит собственную slot-таблицу.
|
||||
/// </summary>
|
||||
public sealed class MeshPieceInfo
|
||||
{
|
||||
public required int Id { get; init; }
|
||||
public required string Name { get; init; }
|
||||
public required int ParentId { get; init; }
|
||||
public required NodeFlags Flags { get; init; }
|
||||
public required IReadOnlyList<ushort> GeometrySlotsByStateAndLod { get; init; }
|
||||
public required IReadOnlyList<MeshBatchInfo> Batches { get; init; }
|
||||
public required Matrix4x4 LocalTransform { get; init; }
|
||||
public required Matrix4x4 MeshSpaceTransform { get; init; }
|
||||
public required Vector3 BoundsMin { get; init; }
|
||||
public required Vector3 BoundsMax { get; init; }
|
||||
public int FallbackKeyframeIndex { get; init; } = -1;
|
||||
public bool HasRestPose { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Возвращает geometry slot 0x02 для пары state/LOD именно этого piece.
|
||||
/// 0xFFFF означает, что piece в такой комбинации не должен рендериться.
|
||||
/// </summary>
|
||||
public ushort ResolveSlotIndex(int state, int lod)
|
||||
{
|
||||
var index = state * Msh0x01.MaxLodCount + lod;
|
||||
return index >= 0 && index < GeometrySlotsByStateAndLod.Count
|
||||
? GeometrySlotsByStateAndLod[index]
|
||||
: ushort.MaxValue;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inspector metadata для batch 0x0D. Геометрия остается в MshModelGeometry, здесь только диапазоны и флаги.
|
||||
/// </summary>
|
||||
public sealed class MeshBatchInfo
|
||||
{
|
||||
public required int BatchIndex { get; init; }
|
||||
public required int MaterialId { get; init; }
|
||||
public string? MaterialName { get; init; }
|
||||
public required BatchFlags Flags { get; init; }
|
||||
public required uint IndexStart { get; init; }
|
||||
public required int IndexCount { get; init; }
|
||||
public required uint BaseVertex { get; init; }
|
||||
public required int VertexCount { get; init; }
|
||||
public required int TriangleCount { get; init; }
|
||||
public IReadOnlyList<string> Warnings { get; init; } = [];
|
||||
}
|
||||
|
||||
/// <summary>Материал из WEA по id. Это еще не ViewportMaterial и не OpenGL texture.</summary>
|
||||
public sealed class MeshMaterialInfo
|
||||
{
|
||||
public required int Id { get; init; }
|
||||
public required string Name { get; init; }
|
||||
public string? TextureName { get; init; }
|
||||
public bool HasTexture => TextureName != null;
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
namespace NResUI.Rendering.Inspection;
|
||||
|
||||
/// <summary>
|
||||
/// Состояние просмотра меша. State/LOD задаются только для конкретных pieces,
|
||||
/// потому что 0x01 хранит таблицу slot indices отдельно для каждого узла.
|
||||
/// </summary>
|
||||
public sealed class MeshRenderState
|
||||
{
|
||||
public bool UseStoredNormals { get; set; } = true;
|
||||
public bool ShowEmptyPieces { get; set; } = true;
|
||||
public int SelectedPieceId { get; set; } = -1;
|
||||
public int SelectedBatchIndex { get; set; } = -1;
|
||||
public bool IsolateSelectedPiece { get; set; }
|
||||
public bool IsolateSelectedBatch { get; set; }
|
||||
public HashSet<int> HiddenPieceIds { get; } = [];
|
||||
public Dictionary<int, int> PieceStateOverrides { get; } = [];
|
||||
public Dictionary<int, int> PieceLodOverrides { get; } = [];
|
||||
|
||||
public void ClearSelection()
|
||||
{
|
||||
SelectedPieceId = -1;
|
||||
SelectedBatchIndex = -1;
|
||||
IsolateSelectedPiece = false;
|
||||
IsolateSelectedBatch = false;
|
||||
}
|
||||
|
||||
public int GetPieceState(int pieceId)
|
||||
{
|
||||
return PieceStateOverrides.GetValueOrDefault(pieceId, 0);
|
||||
}
|
||||
|
||||
public int GetPieceLod(int pieceId)
|
||||
{
|
||||
return PieceLodOverrides.GetValueOrDefault(pieceId, 0);
|
||||
}
|
||||
|
||||
public void SetPieceStateOverride(int pieceId, int state)
|
||||
{
|
||||
PieceStateOverrides[pieceId] = state;
|
||||
}
|
||||
|
||||
public void SetPieceLodOverride(int pieceId, int lod)
|
||||
{
|
||||
PieceLodOverrides[pieceId] = lod;
|
||||
}
|
||||
|
||||
public void ClearPieceOverrides(int pieceId)
|
||||
{
|
||||
PieceStateOverrides.Remove(pieceId);
|
||||
PieceLodOverrides.Remove(pieceId);
|
||||
}
|
||||
|
||||
public void ClearAllPieceOverrides()
|
||||
{
|
||||
PieceStateOverrides.Clear();
|
||||
PieceLodOverrides.Clear();
|
||||
}
|
||||
|
||||
public bool IsPieceVisible(int pieceId)
|
||||
{
|
||||
if (HiddenPieceIds.Contains(pieceId))
|
||||
return false;
|
||||
|
||||
return !IsolateSelectedPiece || SelectedPieceId < 0 || pieceId == SelectedPieceId;
|
||||
}
|
||||
|
||||
public bool IsBatchVisible(int batchIndex)
|
||||
{
|
||||
return !IsolateSelectedBatch || SelectedBatchIndex < 0 || batchIndex == SelectedBatchIndex;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using MshLib;
|
||||
|
||||
namespace NResUI.Rendering.Inspection;
|
||||
|
||||
/// <summary>
|
||||
/// Parsed MSH component data retained so state/LOD changes can rebuild GPU meshes without reparsing the file.
|
||||
/// </summary>
|
||||
public sealed class MshModelGeometry
|
||||
{
|
||||
/// <summary>Таблица узлов 0x01: именно она связывает каждый piece с geometry slot для пары state/LOD.</summary>
|
||||
public required Msh0x01.Msh0x01Component Nodes { get; init; }
|
||||
|
||||
/// <summary>Слоты геометрии 0x02. Один piece выбирает один слот через 0x01.ResolveSlotIndex.</summary>
|
||||
public required Msh0x02.Msh0x02Component GeometrySlots { get; init; }
|
||||
|
||||
/// <summary>Позиции вершин из 0x03.</summary>
|
||||
public required IReadOnlyList<Common.Vector3> Positions { get; init; }
|
||||
|
||||
/// <summary>Нормали из 0x04. Компонент опционален, поэтому фабрика мешей обязана иметь fallback.</summary>
|
||||
public required IReadOnlyList<Msh04Normal> Normals { get; init; }
|
||||
|
||||
/// <summary>UV из 0x05. Компонент опционален для части ресурсов.</summary>
|
||||
public required IReadOnlyList<Msh05Uv> Uvs { get; init; }
|
||||
|
||||
/// <summary>Индексный буфер 0x06 для обычных моделей.</summary>
|
||||
public required IReadOnlyList<ushort> Indices { get; init; }
|
||||
|
||||
/// <summary>Render batches 0x0D: диапазоны индексов, material id и render flags.</summary>
|
||||
public required IReadOnlyList<Msh0x0D.Batch> Batches { get; init; }
|
||||
}
|
||||
Reference in New Issue
Block a user