Files
2026-03-26 09:34:19 -04:00

1032 lines
44 KiB
C#

using System.Text;
using SabreTools.Data.Extensions;
using SabreTools.Data.Models.BSP;
using SabreTools.Text.Extensions;
namespace SabreTools.Wrappers
{
public partial class VBSP : IPrintable
{
#if NETCOREAPP
/// <inheritdoc/>
public string ExportJSON() => System.Text.Json.JsonSerializer.Serialize(Model, _jsonSerializerOptions);
#endif
/// <inheritdoc/>
public void PrintInformation(StringBuilder builder)
{
builder.AppendLine("BSP Information:");
builder.AppendLine("-------------------------");
builder.AppendLine();
Print(builder, Model.Header);
PrintLumps(builder, Model);
}
private static void Print(StringBuilder builder, VbspHeader header)
{
builder.AppendLine(" Header Information:");
builder.AppendLine(" -------------------------");
builder.AppendLine(header.Signature, " Signature");
builder.AppendLine(header.Version, " Version");
builder.AppendLine(header.MapRevision, " Map revision");
builder.AppendLine();
}
private static void PrintLumps(StringBuilder builder, VbspFile model)
{
builder.AppendLine(" Lumps Information:");
builder.AppendLine(" -------------------------");
if (model.Header.Lumps.Length == 0)
{
builder.AppendLine(" No lumps");
builder.AppendLine();
return;
}
for (int i = 0; i < model.Header.Lumps.Length; i++)
{
var lump = model.Header.Lumps[i];
string specialLumpName = ((VbspLumpType)i).FromVbspLumpType();
builder.AppendLine($" Lump {i}{specialLumpName}");
builder.AppendLine(lump.Offset, " Offset");
builder.AppendLine(lump.Length, " Length");
switch ((VbspLumpType)i)
{
case VbspLumpType.LUMP_ENTITIES:
Print(builder, model.Entities);
break;
case VbspLumpType.LUMP_PLANES:
Print(builder, model.PlanesLump);
break;
case VbspLumpType.LUMP_TEXTURES:
Print(builder, model.TexdataLump);
break;
case VbspLumpType.LUMP_VERTICES:
Print(builder, model.VerticesLump);
break;
case VbspLumpType.LUMP_VISIBILITY:
Print(builder, model.VisibilityLump);
break;
case VbspLumpType.LUMP_NODES:
Print(builder, model.NodesLump);
break;
case VbspLumpType.LUMP_TEXINFO:
Print(builder, model.TexinfoLump);
break;
case VbspLumpType.LUMP_FACES:
Print(builder, model.FacesLump);
break;
case VbspLumpType.LUMP_LIGHTING:
Print(builder, model.LightmapLump);
break;
case VbspLumpType.LUMP_CLIPNODES:
Print(builder, model.OcclusionLump);
break;
case VbspLumpType.LUMP_LEAVES:
Print(builder, model.LeavesLump, lump.Version);
break;
case VbspLumpType.LUMP_MARKSURFACES:
Print(builder, model.MarksurfacesLump);
break;
case VbspLumpType.LUMP_EDGES:
Print(builder, model.EdgesLump);
break;
case VbspLumpType.LUMP_SURFEDGES:
Print(builder, model.SurfedgesLump);
break;
case VbspLumpType.LUMP_MODELS:
Print(builder, model.ModelsLump);
break;
case VbspLumpType.LUMP_WORLDLIGHTS:
Print(builder, model.LDRWorldLightsLump);
break;
case VbspLumpType.LUMP_LEAFFACES:
Print(builder, model.LeafFacesLump);
break;
case VbspLumpType.LUMP_LEAFBRUSHES:
Print(builder, model.LeafBrushesLump);
break;
case VbspLumpType.LUMP_BRUSHES:
Print(builder, model.BrushesLump);
break;
case VbspLumpType.LUMP_BRUSHSIDES:
Print(builder, model.BrushsidesLump);
break;
case VbspLumpType.LUMP_AREAS:
// TODO: Support LUMP_AREAS [20] when in Models
builder.AppendLine(" Data not parsed...");
break;
case VbspLumpType.LUMP_AREAPORTALS:
// TODO: Support LUMP_AREAPORTALS [21] when in Models
builder.AppendLine(" Data not parsed...");
break;
case VbspLumpType.LUMP_PORTALS:
// TODO: Support LUMP_PORTALS / LUMP_UNUSED0 / LUMP_PROPCOLLISION [22] when in Models
builder.AppendLine(" Data not parsed...");
break;
case VbspLumpType.LUMP_CLUSTERS:
// TODO: Support LUMP_CLUSTERS / LUMP_UNUSED1 / LUMP_PROPHULLS [23] when in Models
builder.AppendLine(" Data not parsed...");
break;
case VbspLumpType.LUMP_PORTALVERTS:
// TODO: Support LUMP_PORTALVERTS / LUMP_UNUSED2 / LUMP_FAKEENTITIES / LUMP_PROPHULLVERTS [24] when in Models
builder.AppendLine(" Data not parsed...");
break;
case VbspLumpType.LUMP_CLUSTERPORTALS:
// TODO: Support LUMP_CLUSTERPORTALS / LUMP_UNUSED3 / LUMP_PROPTRIS [25] when in Models
builder.AppendLine(" Data not parsed...");
break;
case VbspLumpType.LUMP_DISPINFO:
Print(builder, model.DispInfosLump);
break;
case VbspLumpType.LUMP_ORIGINALFACES:
Print(builder, model.OriginalFacesLump);
break;
case VbspLumpType.LUMP_PHYSDISP:
// TODO: Support LUMP_PHYSDISP [28] when in Models
builder.AppendLine(" Data not parsed...");
break;
case VbspLumpType.LUMP_PHYSCOLLIDE:
Print(builder, model.PhysCollideLump);
break;
case VbspLumpType.LUMP_VERTNORMALS:
// TODO: Support LUMP_VERTNORMALS [30] when in Models
builder.AppendLine(" Data not parsed...");
break;
case VbspLumpType.LUMP_VERTNORMALINDICES:
// TODO: Support LUMP_VERTNORMALINDICES [31] when in Models
builder.AppendLine(" Data not parsed...");
break;
case VbspLumpType.LUMP_DISP_LIGHTMAP_ALPHAS:
// TODO: Support LUMP_DISP_LIGHTMAP_ALPHAS [32] when in Models
builder.AppendLine(" Data not parsed...");
break;
case VbspLumpType.LUMP_DISP_VERTS:
Print(builder, model.DispVertsLump);
break;
case VbspLumpType.LUMP_DISP_LIGHTMAP_SAMPLE_POSITIONS:
// TODO: Support LUMP_DISP_LIGHTMAP_SAMPLE_POSITIONS [34] when in Models
builder.AppendLine(" Data not parsed...");
break;
case VbspLumpType.LUMP_GAME_LUMP:
Print(builder, model.GameLump);
break;
case VbspLumpType.LUMP_LEAFWATERDATA:
// TODO: Support LUMP_LEAFWATERDATA [36] when in Models
builder.AppendLine(" Data not parsed...");
break;
case VbspLumpType.LUMP_PRIMITIVES:
// TODO: Support LUMP_PRIMITIVES [37] when in Models
builder.AppendLine(" Data not parsed...");
break;
case VbspLumpType.LUMP_PRIMVERTS:
// TODO: Support LUMP_PRIMVERTS [38] when in Models
builder.AppendLine(" Data not parsed...");
break;
case VbspLumpType.LUMP_PRIMINDICES:
// TODO: Support LUMP_PRIMINDICES [39] when in Models
builder.AppendLine(" Data not parsed...");
break;
case VbspLumpType.LUMP_PAKFILE:
Print(builder, model.PakfileLump);
break;
case VbspLumpType.LUMP_CLIPPORTALVERTS:
// TODO: Support LUMP_CLIPPORTALVERTS [41] when in Models
builder.AppendLine(" Data not parsed...");
break;
case VbspLumpType.LUMP_CUBEMAPS:
Print(builder, model.CubemapsLump);
break;
case VbspLumpType.LUMP_TEXDATA_STRING_DATA:
Print(builder, model.TexdataStringData);
break;
case VbspLumpType.LUMP_TEXDATA_STRING_TABLE:
Print(builder, model.TexdataStringTable);
break;
case VbspLumpType.LUMP_OVERLAYS:
Print(builder, model.OverlaysLump);
break;
case VbspLumpType.LUMP_LEAFMINDISTTOWATER:
// TODO: Support LUMP_LEAFMINDISTTOWATER [46] when in Models
builder.AppendLine(" Data not parsed...");
break;
case VbspLumpType.LUMP_FACE_MACRO_TEXTURE_INFO:
// TODO: Support LUMP_FACE_MACRO_TEXTURE_INFO [47] when in Models
builder.AppendLine(" Data not parsed...");
break;
case VbspLumpType.LUMP_DISP_TRIS:
Print(builder, model.DispTrisLump);
break;
case VbspLumpType.LUMP_PHYSCOLLIDESURFACE:
// TODO: Support LUMP_PHYSCOLLIDESURFACE / LUMP_PROP_BLOB [49] when in Models
builder.AppendLine(" Data not parsed...");
break;
case VbspLumpType.LUMP_WATEROVERLAYS:
// TODO: Support LUMP_WATEROVERLAYS [50] when in Models
builder.AppendLine(" Data not parsed...");
break;
case VbspLumpType.LUMP_LIGHTMAPPAGES:
Print(builder, model.HDRAmbientIndexLump);
break;
case VbspLumpType.LUMP_LIGHTMAPPAGEINFOS:
Print(builder, model.LDRAmbientIndexLump);
break;
case VbspLumpType.LUMP_LIGHTING_HDR:
// TODO: Support LUMP_LIGHTING_HDR [53] when in Models
builder.AppendLine(" Data not parsed...");
break;
case VbspLumpType.LUMP_WORLDLIGHTS_HDR:
Print(builder, model.HDRWorldLightsLump);
break;
case VbspLumpType.LUMP_LEAF_AMBIENT_LIGHTING_HDR:
Print(builder, model.HDRAmbientLightingLump);
break;
case VbspLumpType.LUMP_LEAF_AMBIENT_LIGHTING:
Print(builder, model.LDRAmbientLightingLump);
break;
case VbspLumpType.LUMP_XZIPPAKFILE:
// TODO: Support LUMP_XZIPPAKFILE [57] when in Models
builder.AppendLine(" Data not parsed...");
break;
case VbspLumpType.LUMP_FACES_HDR:
// TODO: Support LUMP_FACES_HDR [58] when in Models
builder.AppendLine(" Data not parsed...");
break;
case VbspLumpType.LUMP_MAP_FLAGS:
// TODO: Support LUMP_MAP_FLAGS [59] when in Models
builder.AppendLine(" Data not parsed...");
break;
case VbspLumpType.LUMP_OVERLAY_FADES:
// TODO: Support LUMP_OVERLAY_FADES [60] when in Models
builder.AppendLine(" Data not parsed...");
break;
case VbspLumpType.LUMP_OVERLAY_SYSTEM_LEVELS:
// TODO: Support LUMP_OVERLAY_SYSTEM_LEVELS [61] when in Models
builder.AppendLine(" Data not parsed...");
break;
case VbspLumpType.LUMP_PHYSLEVEL:
// TODO: Support LUMP_PHYSLEVEL [62] when in Models
builder.AppendLine(" Data not parsed...");
break;
case VbspLumpType.LUMP_DISP_MULTIBLEND:
// TODO: Support LUMP_DISP_MULTIBLEND [63] when in Models
builder.AppendLine(" Data not parsed...");
break;
default:
builder.AppendLine($" Unsupported lump type: {(VbspLumpType)i} (0x{i:X4})");
break;
}
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, EntitiesLump lump)
{
if (lump.Entities.Length == 0)
{
builder.AppendLine(" No data");
return;
}
for (int i = 0; i < lump.Entities.Length; i++)
{
// TODO: Implement entity printing
//var entity = lump.Entities[i];
builder.AppendLine($" Entity {i}: Not printed yet");
}
}
private static void Print(StringBuilder builder, PlanesLump lump)
{
if (lump.Planes.Length == 0)
{
builder.AppendLine(" No data");
return;
}
for (int i = 0; i < lump.Planes.Length; i++)
{
var plane = lump.Planes[i];
builder.AppendLine($" Plane {i}");
builder.AppendLine($" Normal vector: ({plane.NormalVector.X}, {plane.NormalVector.Y}, {plane.NormalVector.Z})");
builder.AppendLine(plane.Distance, " Distance");
builder.AppendLine($" Plane type: {plane.PlaneType} (0x{plane.PlaneType:X})");
}
}
private static void Print(StringBuilder builder, TexdataLump lump)
{
if (lump.Texdatas.Length == 0)
{
builder.AppendLine(" No data");
return;
}
for (int i = 0; i < lump.Texdatas.Length; i++)
{
var texdata = lump.Texdatas[i];
builder.AppendLine($" Texture {i}");
builder.AppendLine($" Reflectivity: ({texdata.Reflectivity.X}, {texdata.Reflectivity.Y}, {texdata.Reflectivity.Z})");
builder.AppendLine(texdata.NameStringTableID, " Name string table ID");
builder.AppendLine(texdata.Width, " Width");
builder.AppendLine(texdata.Height, " Height");
builder.AppendLine(texdata.ViewWidth, " View width");
builder.AppendLine(texdata.ViewHeight, " View height");
}
}
private static void Print(StringBuilder builder, VerticesLump lump)
{
if (lump.Vertices.Length == 0)
{
builder.AppendLine(" No data");
return;
}
for (int i = 0; i < lump.Vertices.Length; i++)
{
var vertex = lump.Vertices[i];
builder.AppendLine($" Vertex {i}: ({vertex.X}, {vertex.Y}, {vertex.Z})");
}
}
private static void Print(StringBuilder builder, VisibilityLump lump)
{
builder.AppendLine(lump.NumClusters, " Cluster count");
builder.AppendLine(" Byte offsets skipped...");
}
private static void Print(StringBuilder builder, VbspNodesLump lump)
{
if (lump.Nodes.Length == 0)
{
builder.AppendLine(" No data");
return;
}
for (int i = 0; i < lump.Nodes.Length; i++)
{
var node = lump.Nodes[i];
builder.AppendLine($" Node {i}");
builder.AppendLine(node.Children, " Children");
builder.AppendLine(node.Mins, " Mins");
builder.AppendLine(node.Maxs, " Maxs");
builder.AppendLine(node.FirstFace, " First face index");
builder.AppendLine(node.FaceCount, " Count of faces");
builder.AppendLine(node.Area, " Area");
builder.AppendLine(node.Padding, " Padding");
}
}
private static void Print(StringBuilder builder, VbspTexinfoLump lump)
{
if (lump.Texinfos.Length == 0)
{
builder.AppendLine(" No data");
return;
}
for (int i = 0; i < lump.Texinfos.Length; i++)
{
var texinfo = lump.Texinfos[i];
builder.AppendLine($" Texinfo {i}");
builder.AppendLine($" Texture S-Vector: ({texinfo.TextureSVector.X}, {texinfo.TextureSVector.Y}, {texinfo.TextureSVector.Z})");
builder.AppendLine(texinfo.TextureSShift, " Texture shift in S direction");
builder.AppendLine($" Texture T-Vector: ({texinfo.TextureTVector.X}, {texinfo.TextureTVector.Y}, {texinfo.TextureTVector.Z})");
builder.AppendLine(texinfo.TextureTShift, " Texture shift in T direction");
builder.AppendLine($" Lightmap S-Vector: ({texinfo.LightmapSVector.X}, {texinfo.LightmapSVector.Y}, {texinfo.LightmapSVector.Z})");
builder.AppendLine(texinfo.TextureSShift, " Lightmap shift in S direction");
builder.AppendLine($" Lightmap T-Vector: ({texinfo.LightmapTVector.X}, {texinfo.LightmapTVector.Y}, {texinfo.LightmapTVector.Z})");
builder.AppendLine(texinfo.TextureTShift, " Lightmap shift in T direction");
builder.AppendLine($" Flags: {texinfo.Flags} (0x{texinfo.Flags:X})");
builder.AppendLine(texinfo.TexData, " Pointer to texdata");
}
}
private static void Print(StringBuilder builder, VbspFacesLump lump)
{
if (lump.Faces.Length == 0)
{
builder.AppendLine(" No data");
return;
}
for (int i = 0; i < lump.Faces.Length; i++)
{
var face = lump.Faces[i];
builder.AppendLine($" Face {i}");
builder.AppendLine(face.PlaneNum, " Plane number");
builder.AppendLine(face.Side, " Side");
builder.AppendLine(face.OnNode, " On node");
builder.AppendLine(face.FirstEdgeIndex, " First surfedge index");
builder.AppendLine(face.NumberOfEdges, " Surfedge count");
builder.AppendLine(face.TextureInfoIndex, " Texture info index");
builder.AppendLine(face.DisplacementInfoIndex, " Displacement info index");
builder.AppendLine(face.SurfaceFogVolumeID, " Surface fog volume ID");
builder.AppendLine(face.Styles, " Styles");
builder.AppendLine(face.LightmapOffset, " Lightmap offset");
builder.AppendLine(face.Area, " Area");
builder.AppendLine(face.LightmapTextureMinsInLuxels, " Lightmap texture mins in Luxels");
builder.AppendLine(face.LightmapTextureSizeInLuxels, " Lightmap texture size in Luxels");
builder.AppendLine(face.OrigFace, " Original face index");
builder.AppendLine(face.PrimitiveCount, " Primitive count");
builder.AppendLine(face.FirstPrimitiveID, " First primitive ID");
builder.AppendLine(face.SmoothingGroups, " Smoothing groups");
}
}
private static void Print(StringBuilder builder, PhysCollideLump lump)
{
if (lump.Models.Length == 0)
{
builder.AppendLine(" No data");
return;
}
for (int i = 0; i < lump.Models.Length; i++)
{
var model = lump.Models[i];
builder.AppendLine($" Model {i}");
builder.AppendLine(model.ModelIndex, " Model index");
builder.AppendLine(model.DataSize, " Data size");
builder.AppendLine(model.KeydataSize, " Keydata size");
builder.AppendLine(model.SolidCount, " Solid count");
if (model.Solids.Length == 0)
{
builder.AppendLine(" No solids");
}
else
{
for (int j = 0; j < model.Solids.Length; j++)
{
var solid = model.Solids[j];
builder.AppendLine($" Solid {j}");
builder.AppendLine(solid.Size, " Size");
builder.AppendLine(" Collision data skipped...");
}
}
builder.AppendLine(" Keydata skipped...");
}
}
private static void Print(StringBuilder builder, LightmapLump lump)
{
if (lump.Lightmap.Length == 0)
builder.AppendLine(" No data");
else
builder.AppendLine(" Lightmap data skipped...");
}
private static void Print(StringBuilder builder, OcclusionLump lump)
{
builder.AppendLine(lump.Count, " Count");
if (lump.Data.Length == 0)
{
builder.AppendLine(" No occluder data");
}
else
{
for (int i = 0; i < lump.Data.Length; i++)
{
var data = lump.Data[i];
builder.AppendLine($" Occluder Data {i}");
builder.AppendLine(data.Flags, " Flags");
builder.AppendLine(data.FirstPoly, " First poly");
builder.AppendLine(data.PolyCount, " Poly count");
builder.AppendLine($" Mins: {data.Mins.X}, {data.Mins.Y}, {data.Mins.Z}");
builder.AppendLine($" Maxs: {data.Maxs.X}, {data.Maxs.Y}, {data.Maxs.Z}");
builder.AppendLine(data.Area, " Area");
}
}
builder.AppendLine(lump.PolyDataCount, " Polydata count");
if (lump.PolyData.Length == 0)
{
builder.AppendLine(" No occluder polydata");
}
else
{
for (int i = 0; i < lump.PolyData.Length; i++)
{
var polydata = lump.PolyData[i];
builder.AppendLine($" Occluder Polydata {i}");
builder.AppendLine(polydata.FirstVertexIndex, " First vertex index");
builder.AppendLine(polydata.VertexCount, " Vertex count");
builder.AppendLine(polydata.PlanEnum, " Plan enum");
}
}
builder.AppendLine(lump.VertexIndexCount, " Vertex index count");
if (lump.VertexIndicies.Length == 0)
{
builder.AppendLine(" No vertex indicies");
}
else
{
for (int i = 0; i < lump.VertexIndicies.Length; i++)
{
builder.AppendLine($" Vertex Index {i}: {lump.VertexIndicies[i]}");
}
}
}
private static void Print(StringBuilder builder, VbspLeavesLump lump, uint version)
{
if (lump.Leaves.Length == 0)
{
builder.AppendLine(" No data");
return;
}
for (int i = 0; i < lump.Leaves.Length; i++)
{
var leaf = lump.Leaves[i];
builder.AppendLine($" Leaf {i}");
builder.AppendLine($" Contents: {leaf.Contents} (0x{leaf.Contents:X})");
builder.AppendLine(leaf.Cluster, " Cluster");
builder.AppendLine(leaf.AreaFlags, " AreaFlags");
builder.AppendLine(leaf.Mins, " Mins");
builder.AppendLine(leaf.Maxs, " Maxs");
builder.AppendLine(leaf.FirstLeafFace, " First leaf face");
builder.AppendLine(leaf.NumLeafFaces, " Leaf faces count");
builder.AppendLine(leaf.FirstLeafBrush, " First leaf brush");
builder.AppendLine(leaf.NumLeafBrushes, " Leaf brushes count");
builder.AppendLine(leaf.LeafWaterDataID, " Leaf water data ID");
if (version == 0)
{
if (leaf.AmbientLighting.Colors.Length == 0)
{
builder.AppendLine(" No ambient lighting colors");
}
else
{
for (int j = 0; j < leaf.AmbientLighting.Colors.Length; j++)
{
var color = leaf.AmbientLighting.Colors[j];
builder.AppendLine($" Ambient Lighting Color {j}");
builder.AppendLine(color.Red, " Red");
builder.AppendLine(color.Green, " Green");
builder.AppendLine(color.Blue, " Blue");
builder.AppendLine(color.Exponent, " Exponent");
}
}
}
else
{
builder.AppendLine(leaf.Padding, " Padding");
}
}
}
private static void Print(StringBuilder builder, MarksurfacesLump lump)
{
if (lump.Marksurfaces.Length == 0)
{
builder.AppendLine(" No data");
return;
}
for (int i = 0; i < lump.Marksurfaces.Length; i++)
{
var marksurface = lump.Marksurfaces[i];
builder.AppendLine(marksurface, $" Marksurface {i}");
}
}
private static void Print(StringBuilder builder, EdgesLump lump)
{
if (lump.Edges.Length == 0)
{
builder.AppendLine(" No data");
return;
}
for (int i = 0; i < lump.Edges.Length; i++)
{
var edge = lump.Edges[i];
builder.AppendLine($" Edge {i}");
builder.AppendLine(edge.VertexIndices, " Vertex indices");
}
}
private static void Print(StringBuilder builder, SurfedgesLump lump)
{
if (lump.Surfedges.Length == 0)
{
builder.AppendLine(" No data");
return;
}
for (int i = 0; i < lump.Surfedges.Length; i++)
{
var surfedge = lump.Surfedges[i];
builder.AppendLine(surfedge, $" Surfedge {i}");
}
}
private static void Print(StringBuilder builder, VbspModelsLump lump)
{
if (lump.Models.Length == 0)
{
builder.AppendLine(" No data");
return;
}
for (int i = 0; i < lump.Models.Length; i++)
{
var model = lump.Models[i];
builder.AppendLine($" Model {i}");
builder.AppendLine($" Mins: ({model.Mins.X}, {model.Mins.Y}, {model.Mins.Z})");
builder.AppendLine($" Maxs: ({model.Maxs.X}, {model.Maxs.Y}, {model.Maxs.Z})");
builder.AppendLine($" Origin vector: ({model.OriginVector.X}, {model.OriginVector.Y}, {model.OriginVector.Z})");
builder.AppendLine(model.HeadNode, " Headnode index");
builder.AppendLine(model.FirstFaceIndex, " First face index");
builder.AppendLine(model.FacesCount, " Faces count");
}
}
private static void Print(StringBuilder builder, WorldLightsLump lump)
{
if (lump.WorldLights.Length == 0)
{
builder.AppendLine(" No data");
return;
}
for (int j = 0; j < lump.WorldLights.Length; j++)
{
var worldlight = lump.WorldLights[j];
builder.AppendLine($" World Light {j}");
builder.AppendLine($" Origin: ({worldlight.Origin.X}, {worldlight.Origin.Y}, {worldlight.Origin.Z})");
builder.AppendLine($" Intensity: ({worldlight.Intensity.X}, {worldlight.Intensity.Y}, {worldlight.Intensity.Z})");
builder.AppendLine($" Normal: ({worldlight.Normal.X}, {worldlight.Normal.Y}, {worldlight.Normal.Z})");
builder.AppendLine(worldlight.Cluster, " Cluster");
builder.AppendLine($" Emit type: {worldlight.EmitType} (0x{worldlight.EmitType:X})");
builder.AppendLine(worldlight.Style, " Style");
builder.AppendLine(worldlight.StopDot, " Start of penumbra");
builder.AppendLine(worldlight.StopDot2, " End of penumbra");
builder.AppendLine(worldlight.Exponent, " Exponent");
builder.AppendLine(worldlight.Radius, " Radius");
builder.AppendLine(worldlight.ConstantAttn, " Constant attn.");
builder.AppendLine(worldlight.LinearAttn, " Linear attn.");
builder.AppendLine(worldlight.QuadraticAttn, " Quadratic attn.");
builder.AppendLine(worldlight.Flags, " Flags");
builder.AppendLine(worldlight.Texinfo, " Texinfo");
builder.AppendLine(worldlight.Owner, " Owner");
}
}
private static void Print(StringBuilder builder, LeafFacesLump lump)
{
if (lump.Map.Length == 0)
{
builder.AppendLine(" No data");
return;
}
for (int i = 0; i < lump.Map.Length; i++)
{
var entry = lump.Map[i];
builder.AppendLine($" Map entry {i}: {entry}");
}
}
private static void Print(StringBuilder builder, LeafBrushesLump lump)
{
if (lump.Map.Length == 0)
{
builder.AppendLine(" No data");
return;
}
for (int i = 0; i < lump.Map.Length; i++)
{
var entry = lump.Map[i];
builder.AppendLine($" Map entry {i}: {entry}");
}
}
private static void Print(StringBuilder builder, BrushesLump lump)
{
if (lump.Brushes.Length == 0)
{
builder.AppendLine(" No data");
return;
}
for (int i = 0; i < lump.Brushes.Length; i++)
{
var brush = lump.Brushes[i];
builder.AppendLine($" Brush {i}");
builder.AppendLine(brush.FirstSide, " First brushside");
builder.AppendLine(brush.NumSides, " Number of brushsides");
builder.AppendLine($" Contents: {brush.Contents} (0x{brush.Contents:X})");
}
}
private static void Print(StringBuilder builder, BrushsidesLump lump)
{
if (lump.Brushsides.Length == 0)
{
builder.AppendLine(" No data");
return;
}
for (int i = 0; i < lump.Brushsides.Length; i++)
{
var brushside = lump.Brushsides[i];
builder.AppendLine($" Brushside {i}");
builder.AppendLine(brushside.PlaneNum, " Plane number");
builder.AppendLine(brushside.TextureInfo, " Texture info");
builder.AppendLine(brushside.DisplacementInfo, " Displacement info");
builder.AppendLine(brushside.Bevel, " Bevel");
}
}
private static void Print(StringBuilder builder, DispInfosLump lump)
{
if (lump.Infos.Length == 0)
{
builder.AppendLine(" No data");
return;
}
for (int i = 0; i < lump.Infos.Length; i++)
{
var info = lump.Infos[i];
builder.AppendLine($" Disp Info {i}");
builder.AppendLine($" Start position: ({info.StartPosition.X}, {info.StartPosition.Y}, {info.StartPosition.Z})");
builder.AppendLine(info.DispVertStart, " Index into disp verts");
builder.AppendLine(info.DispTriStart, " Index into disp tris");
builder.AppendLine(info.Power, " Power");
builder.AppendLine(info.MinTess, " Minimum tesselation");
builder.AppendLine(info.SmoothingAngle, " Smoothing angle");
builder.AppendLine(info.Contents, " Contents");
builder.AppendLine(info.MapFace, " Map face");
builder.AppendLine(info.LightmapAlphaStart, " Lightmap alpha start");
builder.AppendLine(info.LightmapSamplePositionStart, " Lightmap sample position start");
builder.AppendLine($" Edge Neighbors:");
if (info.EdgeNeighbors.Length == 0)
{
builder.AppendLine(" No edge neighbors");
}
else
{
for (int j = 0; j < info.EdgeNeighbors.Length; j++)
{
var edgeNeighbor = info.EdgeNeighbors[j];
builder.AppendLine($" Edge Neighbor {j}");
if (edgeNeighbor.SubNeighbors.Length == 0)
{
builder.AppendLine(" No subneighbors");
}
else
{
for (int k = 0; k < edgeNeighbor.SubNeighbors.Length; k++)
{
var subNeighbor = edgeNeighbor.SubNeighbors[k];
builder.AppendLine($" Subneighbor {k}");
builder.AppendLine(subNeighbor.NeighborIndex, " Neighbor index");
builder.AppendLine(subNeighbor.NeighborOrientation, " Neighbor orientation");
builder.AppendLine(subNeighbor.Span, " Span");
builder.AppendLine(subNeighbor.NeighborSpan, " Neighbor span");
}
}
}
}
builder.AppendLine($" Corner Neighbors:");
if (info.CornerNeighbors.Length == 0)
{
builder.AppendLine(" No corner neighbors");
}
else
{
for (int j = 0; j < info.CornerNeighbors.Length; j++)
{
var cornerNeighbor = info.CornerNeighbors[j];
builder.AppendLine($" Corner Neighbor {j}");
builder.AppendLine(cornerNeighbor.Neighbors, " Neighbors");
builder.AppendLine(cornerNeighbor.NeighborCount, " Neighbor count");
}
}
builder.AppendLine(info.AllowedVerts, " Allowed verts");
}
}
private static void Print(StringBuilder builder, DispVertsLump lump)
{
if (lump.Verts.Length == 0)
{
builder.AppendLine(" No data");
return;
}
for (int i = 0; i < lump.Verts.Length; i++)
{
var vert = lump.Verts[i];
builder.AppendLine($" Disp Vert {i}");
builder.AppendLine($" Vec: ({vert.Vec.X}, {vert.Vec.Y}, {vert.Vec.Z})");
builder.AppendLine(vert.Dist, " Dist");
builder.AppendLine(vert.Alpha, " Alpha");
}
}
private static void Print(StringBuilder builder, GameLump lump)
{
builder.AppendLine(lump.LumpCount, " Lump count");
if (lump.Directories.Length == 0)
{
builder.AppendLine(" No directories");
return;
}
for (int i = 0; i < lump.Directories.Length; i++)
{
var dir = lump.Directories[i];
builder.AppendLine($" Game Lump Directory {i}");
builder.AppendLine(dir.Id, " Id");
builder.AppendLine(dir.Flags, " Flags");
builder.AppendLine(dir.Version, " Version");
builder.AppendLine(dir.FileOffset, " File offset");
builder.AppendLine(dir.FileLength, " File length");
}
}
private static void Print(StringBuilder builder, PakfileLump lump)
{
if (lump.Data.Length == 0)
{
builder.AppendLine(" No data");
return;
}
builder.AppendLine(" Data skipped...");
}
private static void Print(StringBuilder builder, CubemapsLump lump)
{
if (lump.Cubemaps.Length == 0)
{
builder.AppendLine(" No data");
return;
}
for (int i = 0; i < lump.Cubemaps.Length; i++)
{
var cubemap = lump.Cubemaps[i];
builder.AppendLine($" Cubemap {i}");
builder.AppendLine(cubemap.Origin, " Origin");
builder.AppendLine(cubemap.Size, " Size");
}
}
private static void Print(StringBuilder builder, TexdataStringData lump)
{
if (lump.Strings.Length == 0)
{
builder.AppendLine(" No data");
return;
}
for (int i = 0; i < lump.Strings.Length; i++)
{
var str = lump.Strings[i];
builder.AppendLine($" String {i}: {str}");
}
}
private static void Print(StringBuilder builder, TexdataStringTable lump)
{
if (lump.Offsets.Length == 0)
{
builder.AppendLine(" No data");
return;
}
for (int i = 0; i < lump.Offsets.Length; i++)
{
var offset = lump.Offsets[i];
builder.AppendLine($" Offset {i}: {offset}");
}
}
private static void Print(StringBuilder builder, OverlaysLump lump)
{
if (lump.Overlays.Length == 0)
{
builder.AppendLine(" No data");
return;
}
for (int i = 0; i < lump.Overlays.Length; i++)
{
var overlay = lump.Overlays[i];
builder.AppendLine($" Overlay {i}");
builder.AppendLine(overlay.Id, " Id");
builder.AppendLine(overlay.TexInfo, " Texinfo");
builder.AppendLine(overlay.FaceCountAndRenderOrder, " Face count and render order");
builder.AppendLine(overlay.Ofaces, " Ofaces");
builder.AppendLine(overlay.U, " U");
builder.AppendLine(overlay.V, " V");
if (overlay.UVPoints.Length == 0)
{
builder.AppendLine(" No UV points");
}
else
{
for (int j = 0; j < overlay.UVPoints.Length; j++)
{
var point = overlay.UVPoints[j];
builder.AppendLine($" UV Point {j}: ({point.X}, {point.Y}, {point.Z})");
}
}
builder.AppendLine($" Origin: ({overlay.Origin.X}, {overlay.Origin.Y}, {overlay.Origin.Z})");
builder.AppendLine($" Basis normal: ({overlay.BasisNormal.X}, {overlay.BasisNormal.Y}, {overlay.BasisNormal.Z})");
}
}
private static void Print(StringBuilder builder, DispTrisLump lump)
{
if (lump.Tris.Length == 0)
{
builder.AppendLine(" No data");
return;
}
for (int i = 0; i < lump.Tris.Length; i++)
{
var tri = lump.Tris[i];
builder.AppendLine($" Disp Tri {i}");
builder.AppendLine($" Tags: {tri.Tags} (0x{tri.Tags:X})");
}
}
private static void Print(StringBuilder builder, AmbientIndexLump lump)
{
if (lump.Indicies.Length == 0)
{
builder.AppendLine(" No data");
return;
}
for (int i = 0; i < lump.Indicies.Length; i++)
{
var index = lump.Indicies[i];
builder.AppendLine($" Index {i}");
builder.AppendLine(index.AmbientSampleCount, " Ambient sample count");
builder.AppendLine(index.FirstAmbientSample, " First ambient sample");
}
}
private static void Print(StringBuilder builder, AmbientLightingLump lump)
{
if (lump.Lightings.Length == 0)
{
builder.AppendLine(" No data");
return;
}
for (int i = 0; i < lump.Lightings.Length; i++)
{
var lighting = lump.Lightings[i];
builder.AppendLine($" Lighting {i}");
builder.AppendLine(" Colors array skipped...");
builder.AppendLine(lighting.X, " X");
builder.AppendLine(lighting.Y, " Y");
builder.AppendLine(lighting.Z, " Z");
builder.AppendLine(lighting.Pad, " Pad");
}
}
}
}