diff --git a/Assets/Editor.meta b/Assets/Editor.meta new file mode 100644 index 0000000..a423db7 --- /dev/null +++ b/Assets/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4003ff5bdb2acb244ba998df0cf217b7 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor/BigBinaryReader.cs b/Assets/Editor/BigBinaryReader.cs new file mode 100644 index 0000000..f308ace --- /dev/null +++ b/Assets/Editor/BigBinaryReader.cs @@ -0,0 +1,29 @@ +using System; +using System.IO; +using System.Text; + +namespace SourceFormatParser.BigEndian +{ + public class BigBinaryReader : BinaryReader + { + public BigBinaryReader(Stream stream, Encoding encoding) : base(stream, encoding) { } + + public override byte[] ReadBytes(int count) + { + byte[] data = base.ReadBytes(count); + Array.Reverse(data); + return data; + } + + public override short ReadInt16() => BitConverter.ToInt16(ReadBytes(2), 0); + public override ushort ReadUInt16() => BitConverter.ToUInt16(ReadBytes(2), 0); + + public override int ReadInt32() => BitConverter.ToInt32(ReadBytes(4), 0); + public override uint ReadUInt32() => BitConverter.ToUInt32(ReadBytes(4), 0); + + public override long ReadInt64() => BitConverter.ToInt64(ReadBytes(8), 0); + public override ulong ReadUInt64() => BitConverter.ToUInt64(ReadBytes(8), 0); + + public override float ReadSingle() => BitConverter.ToSingle(ReadBytes(4), 0); + } +} diff --git a/Assets/Editor/BigBinaryReader.cs.meta b/Assets/Editor/BigBinaryReader.cs.meta new file mode 100644 index 0000000..ad375b4 --- /dev/null +++ b/Assets/Editor/BigBinaryReader.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0ac89a3db3f134d43bcb4b46bc52c2d5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor/ConvertUtils.cs b/Assets/Editor/ConvertUtils.cs new file mode 100644 index 0000000..9f37b67 --- /dev/null +++ b/Assets/Editor/ConvertUtils.cs @@ -0,0 +1,125 @@ +using UnityEngine; +using System.Collections; +using System.IO; +using System.Globalization; + +namespace uSrcTools +{ + + public class ConvertUtils + { + public static Vector3 StringToVector(string input) + { + Vector3 origin = Vector3.zero; + string[] posStrings = input.Split(new char[]{' '}); + if(posStrings.Length<3) + Debug.LogError("String "+input+" is not Vector3"); + try{ + origin = new Vector3(floatParse(posStrings[0]),floatParse(posStrings[2]),floatParse(posStrings[1]))*SourceImportConfig.WorldScale; + } + catch(System.FormatException e) + { + Debug.LogError("StringToVector error "+e.Message); + origin = Vector3.zero; + } + return origin; + } + + public static Vector2 ReadVector2 (BinaryReader BR) + { + return new Vector2 (BR.ReadSingle(), BR.ReadSingle()); + } + + public static Vector3 ReadVector3 (BinaryReader BR) + { + return new Vector3 (BR.ReadSingle(), BR.ReadSingle(), BR.ReadSingle()); + } + + public static Vector4 ReadVector4 (BinaryReader BR) + { + return new Vector4 (BR.ReadSingle(), BR.ReadSingle(), BR.ReadSingle(), BR.ReadSingle()); + } + + public static Quaternion ReadQuat (BinaryReader BR) + { + return new Quaternion (BR.ReadSingle(), BR.ReadSingle(), BR.ReadSingle(), BR.ReadSingle()); + } + + public static void WriteVector3(BinaryWriter bw, Vector3 v) + { + bw.Write (v.x); + bw.Write (v.y); + bw.Write (v.z); + } + + public static void WriteVector2(BinaryWriter bw, Vector2 v) + { + bw.Write (v.x); + bw.Write (v.y); + } + + public static string ReadNullTerminatedString(BinaryReader br, int offset) + { + br.BaseStream.Seek (offset, SeekOrigin.Begin); + return ReadNullTerminatedString (br); + } + + public static string ReadNullTerminatedString(BinaryReader br) + { + string str = ""; + while (true) + { + char c=br.ReadChar(); + if(c=='\0')break; + str+=c; + } + return str; + } + + public static string GetNullTerminatedString(char[] src, int offs) + { + string str = ""; + for(int i=offs;i GetFaceVertexIds(SourceBSP bsp, dface_t face) + { + List faceVertexIds = new List(); + + for (int e = 0; e < face.numedges; ++e) { + var edgeId = bsp.SurfEdge[e + face.firstedge]; + + bool flipped = false; + if (edgeId < 0) { + edgeId = -edgeId; + flipped = true; + } + + var edge = bsp.Edges[edgeId]; + + short a; + short b; + if (flipped) { + a = edge.v.y; + b = edge.v.x; + } else { + a = edge.v.x; + b = edge.v.y; + } + + if (e == 0) { + faceVertexIds.Add(a); + faceVertexIds.Add(b); + } else { + if (a != faceVertexIds[faceVertexIds.Count - 1]) { + Debug.LogError("Unexpected vertex ID"); + } else { + if (e < face.numedges - 1) { + faceVertexIds.Add(b); + } + } + } + } + + return faceVertexIds; + } + + + GameObject CreateGameObject(string name, Transform parent = null) + { + GameObject g = new GameObject(name); + var mf = g.AddComponent(); + mf.sharedMesh = new Mesh(); + g.AddComponent(); + + if(parent != null) { + g.transform.parent = parent; + } + + g.transform.localPosition = Vector3.zero; + g.transform.localRotation = Quaternion.identity; + g.transform.localScale = Vector3.one; + + return g; + } + + GameObject CreateMeshGameObject(string name, Transform parent = null) + { + var result = CreateGameObject(name, parent); + + var mf = result.AddComponent(); + mf.sharedMesh = new Mesh(); + result.AddComponent(); + + return result; + } + + + struct surface { + public int index; + public int texFlags; + public int texID; + public short dispinfo; + + public Vector3[] points; + public Vector2[] uv; + public Vector2[] uv2; + public Color32[] cols; + public int[] triangles; + + public int lightMapW; + public int lightMapH; + + public Vector2 lightmapScale; + public Vector2 lightmapOffset; + } + + + static surface BuildDispFace(SourceBSP bsp, int faceIndex) + { + var curFace = bsp.Faces[faceIndex]; + var dispinfoId = curFace.dispinfo; + + Vector3[] vertices = new Vector3[4]; + List disp_verts = new List(); + List UVs = new List(); + List cols = new List(); + List indices = new List(); + + var curTexInfo = bsp.Texinfo[curFace.texinfo]; + var curTexData = bsp.Texdata[curTexInfo.texdata]; + + int fEdge = curFace.firstedge; + + for (int i = 0; i < curFace.numedges; i++) { + var sourceVector = (bsp.SurfEdge[fEdge + i] > 0 ? + bsp.Vertexes[bsp.Edges[Mathf.Abs(bsp.SurfEdge[fEdge + i])].v.x] : + bsp.Vertexes[bsp.Edges[Mathf.Abs(bsp.SurfEdge[fEdge + i])].v.y]); + vertices[i] = ToUnityVector(sourceVector); + } + + var curDisp = bsp.DispInfo[dispinfoId]; + Vector3 startPos = ToUnityVector(curDisp.startPosition); + + float dist; + float minDist = 0.1f; + int minIndex = 0; + + for (int i = 0; i < 4; i++) { + dist = Vector3.Distance(startPos, vertices[i]); + + if (dist < minDist) { + minDist = dist; + minIndex = i; + } + } + + Vector3 temp; + + for (int i = 0; i < minIndex; i++) { + temp = vertices[0]; + vertices[0] = vertices[1]; + vertices[1] = vertices[2]; + vertices[2] = vertices[3]; + vertices[3] = temp; + } + + Vector3 leftEdge = vertices[1] - vertices[0]; + Vector3 rightEdge = vertices[2] - vertices[3]; + + int numEdgeVertices = (1 << curDisp.power) + 1; + + float subdivideScale = 1.0f / (float)(numEdgeVertices - 1); + + Vector3 leftEdgeStep = leftEdge * subdivideScale; + Vector3 rightEdgeStep = rightEdge * subdivideScale; + + int firstVertex = 0; + + Vector3 leftEnd; + Vector3 rightEnd; + Vector3 leftRightSeg; + Vector3 leftRightStep; + + int dispVertIndex; + CDispVert dispVert; + + Vector3 flatVertex; + Vector3 dispVertex; + + float scaleU = (float)1f / curTexData.width; + float scaleV = (float)1f / curTexData.height; + + for (int i = 0; i < numEdgeVertices; i++) { + leftEnd = leftEdgeStep * (float)i; + leftEnd += vertices[0]; + rightEnd = rightEdgeStep * (float)i; + rightEnd += vertices[3]; + + leftRightSeg = rightEnd - leftEnd; + leftRightStep = leftRightSeg * subdivideScale; + + for (int j = 0; j < numEdgeVertices; j++) { + dispVertIndex = curDisp.m_iDispVertStart; + dispVertIndex += i * numEdgeVertices + j; + dispVert = bsp.DispVerts[dispVertIndex]; + + flatVertex = leftEnd + (leftRightStep * (float)j); + + dispVertex = ToUnityVector(dispVert.m_vVector) * (dispVert.m_flDist /* *scale*/ ); + dispVertex += flatVertex; + + disp_verts.Add(dispVertex); + + var tvi = curTexInfo.textureVecsTexelsPerWorldUnits; + + float tU = Vector3.Dot(flatVertex, new Vector3(tvi[0].x, tvi[0].z, tvi[0].y)) + (curTexInfo.textureVecsTexelsPerWorldUnits[0].w); + float tV = Vector3.Dot(flatVertex, new Vector3(tvi[1].x, tvi[1].z, tvi[1].y)) + (curTexInfo.textureVecsTexelsPerWorldUnits[1].w); + UVs.Add(new Vector2(tU * scaleU, tV * scaleV)); + + cols.Add(new Color32((byte)(dispVert.m_flAlpha), 0, 0, 0)); + } + } + + int curIndex; + + for (int i = 0; i < numEdgeVertices - 1; i++) { + for (int j = 0; j < numEdgeVertices - 1; j++) { + curIndex = i * numEdgeVertices + j; + + if ((curIndex % 2) == 1) { + curIndex += firstVertex; + + indices.Add(curIndex + 1); + indices.Add(curIndex); + indices.Add(curIndex + numEdgeVertices); + indices.Add(curIndex + numEdgeVertices + 1); + indices.Add(curIndex + 1); + indices.Add(curIndex + numEdgeVertices); + } else { + curIndex += firstVertex; + + indices.Add(curIndex); + indices.Add(curIndex + numEdgeVertices); + indices.Add(curIndex + numEdgeVertices + 1); + indices.Add(curIndex + 1); + indices.Add(curIndex); + indices.Add(curIndex + numEdgeVertices + 1); + } + } + } + + /*for (int i = 0; i < disp_verts.Count; i++) { + disp_verts[i] *= uSrcSettings.Inst.worldScale; + }*/ + + surface f = new surface(); + f.index = faceIndex; + //f.flags = flags; + + f.dispinfo = dispinfoId; + + f.points = disp_verts.ToArray(); + f.uv = UVs.ToArray(); + //f.uv2 = UV2s; + f.cols = cols.ToArray(); + f.triangles = indices.ToArray(); + + //f.lightMapW = lightmapW; + //f.lightMapH = lightmapH; + + return f; + } + + + + GameObject LoadModel(SourceBSP bsp, dmodel_t model, bool skipSky, Transform parent = null) + { + + var matPath = AssetDatabase.FindAssets("DefaultBspMaterial"); + var assetPath = AssetDatabase.GUIDToAssetPath(matPath[0]); + + var mat = AssetDatabase.LoadAssetAtPath(assetPath); + + var result = CreateGameObject("BspModel", parent); + var meshFilter = result.GetComponent(); + var meshRenderer = result.GetComponent(); + + var mesh = meshFilter.sharedMesh; + + List tex = new List(); + + List vertices = new List(); + List triangles = new List(); + + int dispCount = 0; + + for (int i = 0; i < model.numfaces; ++i) { + int faceId = i + model.firstface; + var face = bsp.Faces[faceId]; + + var faceTexInfo = bsp.Texinfo[face.texinfo]; + + if(skipSky && ((faceTexInfo.flags & SourceBSPStructs.SurfaceFlags.SURF_SKY) != 0)) { + continue; + } + + var vertexIndexOffset = vertices.Count; + if (face.dispinfo == -1) { + + if (face.numedges != 0) { + + var faceVertexIds = GetFaceVertexIds(bsp, face); + var verticesCount = faceVertexIds.Count; + + for (int v = 0; v < faceVertexIds.Count; ++v) { + var srcVertex = bsp.Vertexes[faceVertexIds[v]]; + vertices.Add(new Vector3(srcVertex.x, srcVertex.z, srcVertex.y)); + } + + int trianglesCount = verticesCount - 2; + int indicesCount = trianglesCount * 3; + + //int[] indices = new int[indicesCount]; + for (int t = 0; t < trianglesCount; ++t) { + triangles.Add(vertexIndexOffset + 0); + triangles.Add(vertexIndexOffset + (t + 1)); + triangles.Add(vertexIndexOffset + (t + 2)); + } + + + //Debug.Log($"Vertex IDs count: {faceVertexIds.Count} Edges count: {face.numedges}"); + // break; //TEST!!! Only first face + } else { + Debug.Log("Face without edges"); + } + } else { + var dispSurface = BuildDispFace(bsp, faceId); + + for(int t = 0; t< dispSurface.triangles.Length; ++t) { + dispSurface.triangles[t] += vertexIndexOffset; + } + triangles.AddRange(dispSurface.triangles); + + vertices.AddRange(dispSurface.points); + + dispCount++; + /* if (dispCount >= 800) { + break; + }*/ + + } + + + + } + + + Debug.Log("Index format: " + mesh.indexFormat); + mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; + + + vertices = vertices.Select(v => v * _worldScale).ToList(); + mesh.vertices = vertices.ToArray(); + mesh.triangles = triangles.ToArray(); + mesh.RecalculateBounds(); + mesh.RecalculateNormals(); + + meshRenderer.sharedMaterials = new Material[] { mat }; + + //Debug.Log($"Texinfos count: {tex.Count} Distinct: {tex.Distinct().Count()}") ; + + + return result; + } + + private bool SkipSky = true; + private bool LoadProps = true; + + void LoadProp() + { + + } + + private string _gameDir = @"C:\Program Files (x86)\Steam\steamapps\common\Counter-Strike Global Offensive\csgo"; + private string GameMapsDir => System.IO.Path.Combine(_gameDir, "maps"); + + private string MapFilePath(string mapName) + { + return System.IO.Path.Combine(GameMapsDir, mapName + ".bsp"); + } + + + GameObject CreateCubeGameObject(string name, Transform parent = null) + { + var result = GameObject.CreatePrimitive(PrimitiveType.Cube); + result.name = name; + if (parent != null) { + result.transform.parent = parent; + } + result.transform.localPosition = Vector3.zero; + result.transform.localRotation = Quaternion.identity; + result.transform.localScale = Vector3.one; + return result; + } + + + private void LoadStaticProp(StaticPropLumpV11_t prop, List tree, Transform propsRoot, dgamelumpheader_t game) + { + var propType = prop.m_PropType; + var propName = game.staticPropNames[propType]; + + GameObject propObject = CreateGameObject(propName.m_Name, propsRoot.transform); + + propObject.transform.localPosition = ToUnityVector(prop.m_Origin) * _worldScale; + propObject.transform.localRotation = Quaternion.Euler(-prop.m_Angles.z, -prop.m_Angles.y, -prop.m_Angles.x); + + + if (prop.m_UniformScale != 0.0f) { + propObject.transform.localScale = new Vector3(prop.m_UniformScale, prop.m_UniformScale, prop.m_UniformScale); + } + + + var fileRecord = VPKFile.FindFile(tree, propName.m_Name); + if (fileRecord != null) { + + + + + SourceStudioModel model = new SourceStudioModel(); + model.Load(propName.m_Name, (string path) => { + var fileRecord = VPKFile.FindFile(tree, path); + var propData = VPKFile.ReadFile(_gameDir, "pak01", fileRecord); + Debug.Log("Loading file: " + path + " Size: " + propData.Length); + + MemoryStream propDataStream = new MemoryStream(propData); + return propDataStream; + }); + + Debug.Log("Model loaded"); + + + model.GetInstance(propObject, false, 0); + // SourceMDL mdl = new SourceMDL(propDataStream, false); + + // mdl.Header. + + + } + } + + void OnGUI() + { + + + SkipSky = GUILayout.Toggle(SkipSky, "Skip sky"); + + LoadProps = GUILayout.Toggle(LoadProps, "Load props"); + + if (GUILayout.Button("Import")) { + + + + + string mapName = "de_inferno"; // "de_dust2"; //de_inferno + + + GameObject mapRoot = CreateGameObject(mapName); + + + SourceBSP bsp = new SourceBSP(MapFilePath(mapName)); + + LoadModel(bsp, bsp.Models[0], SkipSky, mapRoot.transform); + /*foreach(var model in bsp.Models) { + if(model.numfaces != 0) { + LoadModel(bsp, model, SkipSky); + } else { + Debug.Log("WTF"); + } + }*/ + + + var game = bsp.GameLump; + var tree = VPKFile.ReadDirTree(System.IO.Path.Combine(_gameDir, "pak01_dir.vpk")); + + + if (LoadProps) { + var staticProps = (SourceFormatParser.BSP.SourceBSPStructs.StaticPropLumpV11_t[])game.staticProps; + GameObject propsRoot = CreateGameObject("Props", mapRoot.transform); + foreach (var prop in staticProps) { + LoadStaticProp(prop, tree, propsRoot.transform, game); + } + } + + } + } +} diff --git a/Assets/Editor/ModelImporter.cs.meta b/Assets/Editor/ModelImporter.cs.meta new file mode 100644 index 0000000..751a90b --- /dev/null +++ b/Assets/Editor/ModelImporter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 780eef1b819a5064a99221cbdf1c1277 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor/SourceBSP.cs b/Assets/Editor/SourceBSP.cs new file mode 100644 index 0000000..e30e613 --- /dev/null +++ b/Assets/Editor/SourceBSP.cs @@ -0,0 +1,2817 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using static SourceFormatParser.BSP.SourceBSPStructs; +using static SourceFormatParser.Common.ParsingUtils; +using SourceFormatParser.BigEndian; +using SourceFormatParser.Common; + +namespace SourceFormatParser.BSP +{ + /// + /// Supported version: 17+ / + /// Tested on versions: 19-21 + /// + public class SourceBSP : IDisposable + { + #region Public variables + public dheader_t Header; + + public SourceGame Game; + + //both can be true, both can be false. + public bool isHDR => (MapFlags.m_LevelFlags & (uint)MAP_FLAGS.LVLFLAGS_BAKED_STATIC_PROP_LIGHTING_HDR) != 0; + public bool isLDR => (MapFlags.m_LevelFlags & (uint)MAP_FLAGS.LVLFLAGS_BAKED_STATIC_PROP_LIGHTING_NONHDR) != 0; + #endregion + #region Private variables + BinaryReader BR; + Stream stream; + #endregion + + #region enums + /// + /// this enum for games with modified structs, to parse them properly later + /// + public enum SourceGame + { + Unknown, + //==valve games + //TeamFortress2, + //Left4Dead, + Left4Dead2, + //Portal2, + //CounterStrikeGlobalOffensive, + CSGO_PS3, + //Dota2, + + //==idk + //ZenoClash, + //DarkMessiah, + //Vindictus, + //TheShip, + //BloodyGoodTime, + //BlackMesa, + //AlienSwarm, + //DearEsther, + //Titanfall + } + #endregion + + #region Init / Dispose + public SourceBSP(string path, SourceGame game = SourceGame.Unknown) + { + stream = File.OpenRead(path); + Init(stream, game); + } + public SourceBSP(Stream stream, SourceGame game = SourceGame.Unknown) => Init(stream, game); + + void Init(Stream stream, SourceGame game) + { + Game = game; + if (game == SourceGame.CSGO_PS3) + BR = new BigBinaryReader(stream, Encoding.ASCII); + else + BR = new BinaryReader(stream, Encoding.ASCII); + ParseHeader(); + } + + public void Dispose() + { + BR.Dispose(); + if (stream != null) + stream.Dispose(); + } + #endregion + + #region Private Methods + void ParseHeader() + { + BR.BaseStream.Seek(0, SeekOrigin.Begin); + int id = BR.ReadInt32(); + if (id != IDBSPHEADER) + throw new Exception("Not a BSP file! (wrong id)"); + + Header = new dheader_t + { + ident = id, + version = BR.ReadInt32(), + lumps = ParseLumps(), + mapRevision = BR.ReadInt32() + }; + } + + lump_t[] ParseLumps() + { + lump_t[] lumps = new lump_t[HEADER_LUMPS]; + for (int l = 0; l < HEADER_LUMPS; l++) + { + if (Game == SourceGame.Left4Dead2) + lumps[l] = new lump_t + { + version = BR.ReadInt32(), + + fileofs = BR.ReadInt32(), + filelen = BR.ReadInt32(), + uncompressedSize = BR.ReadInt32(), + + lumpNum = l + }; + else + lumps[l] = new lump_t + { + fileofs = BR.ReadInt32(), + filelen = BR.ReadInt32(), + version = BR.ReadInt32(), + uncompressedSize = BR.ReadInt32(), + + lumpNum = l + }; + } + return lumps; + } + #endregion + + #region Methods for lumps + private lump_t SetLump(int lumpNum) + { + lump_t lump = Header.lumps[lumpNum]; + BR.BaseStream.Seek(lump.fileofs, SeekOrigin.Begin); + return lump; + } + private byte[] ReadLump(int lumpNum) => BR.ReadBytes(SetLump(lumpNum).filelen); + + private int GetLumpCount(int lumpNum, int byteSize) => GetLumpCount(Header.lumps[lumpNum], byteSize); + private int GetLumpCount(lump_t lump, int byteSize) + { + //check if byteSize is correct + int c = lump.filelen / byteSize; + if (lump.filelen % byteSize != 0) + { + //trying to find nearest byteSizes + int nearMin=-1, nearMax=-1; + for(int s = 1; s < 100; s++) + { + if (byteSize - s <= 0) break; + if (lump.filelen % (byteSize - s) == 0) + { + nearMin = byteSize - s; + break; + } + } + for (int s = 1; s < 100; s++) + { + if (lump.filelen % (byteSize + s) == 0) + { + nearMax = byteSize + s; + break; + } + } + string debug_text = $"[Lump #{lump.lumpNum}:v{lump.version}] Wrong count" + (nearMin != -1 || nearMax != -1 ? $" ({nearMin}; {nearMax})" : ""); + DebugLog.Write(debug_text); + } + return c; + } + #endregion + + #region Lumps + + #region Lump #0: Entities + private List _entities; + /// + /// Lump #0. + /// + public List Entities + { + get + { + if (_entities == null) + { + string[] _ents = Encoding.ASCII.GetString(ReadLump(0)).Split('{', '}'); + + List ents = new List(); + foreach(string e in _ents) + { + if (e.Length > 2) + ents.Add(new SourceKV(e, true)); + } + + _entities = ents; + } + return _entities; + } + } + #endregion + + #region Lump #1: Planes + private dplane_t[] _planes; + /// + /// Lump #1. + /// Purpose: [not sure] Calculations for movement (if player can collide with walls?) + /// + public dplane_t[] Planes + { + get + { + if (_planes == null) + { + lump_t lump = SetLump(1); + int count = GetLumpCount(lump, 20); + _planes = new dplane_t[count]; + for (int p = 0; p < count; p++) + { + _planes[p] = new dplane_t + { + normal = BR.ReadVector(), + dist = BR.ReadSingle(), + type = BR.ReadInt32() + }; + } + } + return _planes; + } + } + #endregion + + #region Lump #2: Texture data (TEXDATA) + private dtexdata_t[] _texdata; + /// + /// Lump #2. + /// Purpose: texture referencing, texture preloading, lighting calculation (reflectivity) + /// + public dtexdata_t[] Texdata + { + get + { + if (_texdata == null) + { + lump_t lump = SetLump(2); + int count = GetLumpCount(lump, 32); + _texdata = new dtexdata_t[count]; + for (int t = 0; t < count; t++) + { + _texdata[t] = new dtexdata_t + { + reflectivity = BR.ReadVector(), + nameStringTableID = BR.ReadInt32(), + width = BR.ReadInt32(), + height = BR.ReadInt32(), + view_width = BR.ReadInt32(), + view_height = BR.ReadInt32() + }; + } + } + return _texdata; + } + } + #endregion + + #region Lump #3: Vertexes (vertices) + private SourceVector[] _vertexes; + /// + /// Lump #3. + /// Purpose: brush/displacement rendering + /// + public SourceVector[] Vertexes + { + get + { + if (_vertexes == null) + { + lump_t lump = SetLump(3); + int count = GetLumpCount(lump, 12); + _vertexes = new SourceVector[count]; + for (int v = 0; v < count; v++) + _vertexes[v] = BR.ReadVector(); + } + return _vertexes; + } + } + #endregion + + #region Lump #4: Visibility + private dvis_t _visibility; + private bool __visibility; + /// + /// Lump #4. + /// Purpose: visibility optimizing for brushes/displacements/props/entities. + /// WARNING: may use many of RAM + /// + public dvis_t Visibility + { + get + { + if (!__visibility) + { + lump_t lump = SetLump(4); + if(lump.filelen == 0) + { + __visibility = true; + return _visibility; + } + + int numclusters = BR.ReadInt32(); + int[][] bitofs = new int[numclusters][]; + for(int b = 0; b < numclusters; b++) + bitofs[b] = BR.ReadInt32Array(2); + + _visibility = new dvis_t + { + numclusters = numclusters, + bitofs = bitofs + }; + + //reading pvs + _visibility.pvs = new HashSet[numclusters]; + for (int i = 0; i < numclusters; i++) + { + var ofs = bitofs[i][0]; + BR.BaseStream.Seek(lump.fileofs + ofs, SeekOrigin.Begin); + _visibility.pvs[i] = new HashSet(); + int offset = 0; + while (offset < numclusters) + { + byte bits = BR.ReadByte(); + if (bits == 0) + { + offset += BR.ReadByte() * 8; + continue; + } + + for (var ii = 0; ii < 8 && offset + ii < numclusters; ++ii) + { + if ((bits & (1 << ii)) != 0) + _visibility.pvs[i].Add((byte)(offset + ii)); + } + + offset += 8; + } + } + + //reading pas + // === UNCOMMENT THIS IF ITS USEFUL FOR YOU === + // == i commented it because it uses additional RAM. + // == don't think it can be useful for someone + //_visibility.pas = new HashSet[numclusters]; + //for (int i = 0; i < numclusters; i++) + //{ + // var ofs = bitofs[i][1]; + // BR.BaseStream.Seek(lump.fileofs + ofs, SeekOrigin.Begin); + // _visibility.pas[i] = new HashSet(); + // int offset = 0; + // while (offset < numclusters) + // { + // byte bits = BR.ReadByte(); + // if (bits == 0) + // { + // offset += BR.ReadByte() * 8; + // continue; + // } + + // for (var ii = 0; ii < 8 && offset + ii < numclusters; ++ii) + // { + // if ((bits & (1 << ii)) != 0) + // _visibility.pas[i].Add((byte)(offset + ii)); + // } + + // offset += 8; + // } + //} + + __visibility = true; + } + return _visibility; + } + } + #endregion + + #region Lump #5: Nodes + private dnode_t[] _nodes; + /// + /// Lump #5. + /// Purpose: [not sure] to determine player's position for visibility optimisation? + /// + public dnode_t[] Nodes + { + get + { + if (_nodes == null) + { + lump_t lump = SetLump(5); + int count = GetLumpCount(lump, 32); + _nodes = new dnode_t[count]; + for (int n = 0; n < count; n++) + { + _nodes[n] = new dnode_t + { + planenum = BR.ReadInt32(), + children = BR.ReadInt32Array(2), + mins = BR.ReadVectorShort(), + maxs = BR.ReadVectorShort(), + firstface = BR.ReadUInt16(), + numfaces = BR.ReadUInt16(), + area = BR.ReadInt16(), + //unused = BR.ReadInt16() + }; + BR.BaseStream.Seek(2, SeekOrigin.Current); + } + } + return _nodes; + } + } + #endregion + + #region Lump #6: Texture info (TEXINFO) + private texinfo_t[] _texinfo; + /// + /// Lump #6. + /// Purpose: texture info. Flags, texture offset, lightmap [offset?], index for texdata. + /// + public texinfo_t[] Texinfo + { + get + { + if (_texinfo == null) + { + lump_t lump = SetLump(6); + int count = GetLumpCount(lump, 72); + _texinfo = new texinfo_t[count]; + for (int t = 0; t < count; t++) + { + _texinfo[t] = new texinfo_t + { + textureVecsTexelsPerWorldUnits = new SourceVector4[2] { BR.ReadVector4(), BR.ReadVector4() }, + lightmapVecsLuxelsPerWorldUnits = new SourceVector4[2] { BR.ReadVector4(), BR.ReadVector4() }, + flags = BR.ReadInt32(), + texdata = BR.ReadInt32() + }; + } + } + return _texinfo; + } + } + #endregion + + #region Lump #7: Faces (LDR) + private dface_t[] _faces; + /// + /// Lump #7. Version 1. + /// Purpose: datas for rendering. + /// Also: Check lump #58 for HDR faces. + /// + public dface_t[] Faces + { + get + { + if (_faces == null) + { + lump_t lump = SetLump(7); + int count = GetLumpCount(lump, 56); + _faces = new dface_t[count]; + for (int f = 0; f < count; f++) + { + _faces[f] = new dface_t + { + planenum = BR.ReadUInt16(), + side = BR.ReadByte(), + onNode = BR.ReadByte(), + firstedge = BR.ReadInt32(), + numedges = BR.ReadInt16(), + texinfo = BR.ReadInt16(), + dispinfo = BR.ReadInt16(), + surfaceFogVolumeID = BR.ReadInt16(), + styles = BR.ReadBytes(4), + lightofs = BR.ReadInt32(), + area = BR.ReadSingle(), + m_LightmapTextureMinsInLuxels = BR.ReadVector2Int(), + m_LightmapTextureSizeInLuxels = BR.ReadVector2Int(), + origFace = BR.ReadInt32(), + m_NumPrims = BR.ReadUInt16(), + firstPrimID = BR.ReadUInt16(), + smoothingGroups = BR.ReadUInt32() + }; + } + } + return _faces; + } + } + #endregion + + #region Lump #8: Lighting (LDR) + private ColorRGBExp32[] _lighting; + /// + /// Lump #8. Version 1. + /// Purpose: lightmap colors / shadows. + /// Also: Check lump #53 for HDR lighting. + /// + public ColorRGBExp32[] Lighting + { + get + { + if (_lighting == null) + { + lump_t lump = SetLump(8); + int count = GetLumpCount(lump, 4); + _lighting = new ColorRGBExp32[count]; + for (int f = 0; f < count; f++) + { + _lighting[f] = BR.ReadColorRGBExp32(); + } + } + return _lighting; + } + } + #endregion + + #region Lump #9: Occlusion + private doccluder_t _occlusion; + private bool __occlusion; + /// + /// Lump #9. Version 1/2. + /// Purpose: [not sure] func_occluder entity info for compilation. + /// Usage for data (depending on version): (doccluderdataV?_t[])bsp.Occlusion.data + /// + public doccluder_t Occlusion + { + get + { + if (!__occlusion) + { + lump_t lump = SetLump(9); + if(lump.filelen == 0) + { + __occlusion = true; + return _occlusion; + } + + _occlusion = new doccluder_t(); + _occlusion.count = BR.ReadInt32(); + switch (lump.version) + { + case 1: + doccluderdataV1_t[] _o_v1 = new doccluderdataV1_t[_occlusion.count]; + for (int o = 0; o < _occlusion.count; o++) + _o_v1[o] = new doccluderdataV1_t + { + flags = BR.ReadInt32(), + firstpoly = BR.ReadInt32(), + polycount = BR.ReadInt32(), + mins = BR.ReadVector(), + maxs = BR.ReadVector() + }; + _occlusion.data = _o_v1; + break; + case 2: + doccluderdataV2_t[] _o_v2 = new doccluderdataV2_t[_occlusion.count]; + for (int o = 0; o < _occlusion.count; o++) + _o_v2[o] = new doccluderdataV2_t + { + flags = BR.ReadInt32(), + firstpoly = BR.ReadInt32(), + polycount = BR.ReadInt32(), + mins = BR.ReadVector(), + maxs = BR.ReadVector(), + area = BR.ReadInt32() + }; + _occlusion.data = _o_v2; + break; + default: + __occlusion = true; + throw new NotImplementedException(); + } + + _occlusion.polyDataCount = BR.ReadInt32(); + _occlusion.polyData = new doccluderpolydata_t[_occlusion.polyDataCount]; + for (int p = 0; p < _occlusion.polyDataCount; p++) + { + _occlusion.polyData[p] = new doccluderpolydata_t + { + firstvertexindex = BR.ReadInt32(), + vertexcount = BR.ReadInt32(), + planenum = BR.ReadInt32() + }; + } + + _occlusion.vertexIndexCount = BR.ReadInt32(); + _occlusion.vertexIndices = BR.ReadInt32Array(_occlusion.vertexIndexCount); + + __occlusion = true; + } + return _occlusion; + } + } + #endregion + + #region Lump #10: Leafs + private object _leafs; + private bool __leafs; + /// + /// Lump #10. Version 0/1. + /// Purpose: [not sure] to determine player's position for visibility optimisation? + /// Usage (depending on version): (dleafV?_t[])bsp.Leafs + /// + public object Leafs + { + get + { + if (!__leafs) + { + lump_t lump = SetLump(10); + if (lump.filelen == 0) + { + __leafs = true; + return _leafs; + } + int count; + int contents; + short cluster; + uint packed; + + switch (lump.version) + { + case 0: + count = GetLumpCount(lump, 56); + dleafV0_t[] _l_0 = new dleafV0_t[count]; + for (int l = 0; l < count; l++) + { + contents = BR.ReadInt32(); + cluster = BR.ReadInt16(); + packed = BR.ReadUInt32(); //area:9 and flags:7 + _l_0[l] = new dleafV0_t + { + contents = contents, + cluster = cluster, + area = (short)((ushort)(packed << 7) >> 7), + flags = (short)(packed >> 9), + mins = BR.ReadVectorShort(), + maxs = BR.ReadVectorShort(), + firstleafface = BR.ReadUInt16(), + numleaffaces = BR.ReadUInt16(), + firstleafbrush = BR.ReadUInt16(), + numleafbrushes = BR.ReadUInt16(), + leafWaterDataID = BR.ReadInt16(), + m_AmbientLighting = BR.ReadCompressedLightCube() + }; + } + _leafs = _l_0; + break; + case 1: + count = GetLumpCount(lump, 32); + dleafV1_t[] _l_1 = new dleafV1_t[count]; + for (int l = 0; l < count; l++) + { + contents = BR.ReadInt32(); + cluster = BR.ReadInt16(); + packed = BR.ReadUInt32(); //area:9 and flags:7 + _l_1[l] = new dleafV1_t + { + contents = contents, + cluster = cluster, + area = (short)((ushort)(packed << 7) >> 7), + flags = (short)(packed >> 9), + mins = BR.ReadVectorShort(), + maxs = BR.ReadVectorShort(), + firstleafface = BR.ReadUInt16(), + numleaffaces = BR.ReadUInt16(), + firstleafbrush = BR.ReadUInt16(), + numleafbrushes = BR.ReadUInt16(), + leafWaterDataID = BR.ReadInt16() + }; + } + _leafs = _l_1; + break; + default: + __leafs = true; + throw new NotImplementedException(); + } + + + __leafs = true; + } + return _leafs; + } + } + #endregion + + #region Lump #11: Face IDs + private dfaceid_t[] _faceids; + /// + /// Lump #11. + /// Purpose: Face IDs from Valve Hammer Editor. Should equal Faces lump count. + /// + public dfaceid_t[] FaceIDs + { + get + { + if (_faceids == null) + { + lump_t lump = SetLump(11); + int count = GetLumpCount(lump, 2); + _faceids = new dfaceid_t[count]; + for (int f = 0; f < count; f++) + { + _faceids[f] = new dfaceid_t { hammerfaceid = BR.ReadUInt16() }; + } + } + return _faceids; + } + } + #endregion + + #region Lump #12: Edges + private dedge_t[] _edges; + /// + /// Lump #12. + /// Purpose: vertex indices for faces + /// + public dedge_t[] Edges + { + get + { + if (_edges == null) + { + lump_t lump = SetLump(12); + int count = GetLumpCount(lump, 4); + _edges = new dedge_t[count]; + for (int e = 0; e < count;e++) + { + _edges[e] = new dedge_t { v = BR.ReadVector2Short() }; + } + } + return _edges; + } + } + #endregion + + #region Lump #13: Surface edges (SURFEDGE) + private int[] _surfedge; + /// + /// Lump #13. + /// Purpose: Faces.firstedge/numedges (e) ->| Surfedge[e] (s) ->| Edges[s]. + /// + public int[] SurfEdge + { + get + { + if (_surfedge == null) + { + lump_t lump = SetLump(13); + int count = GetLumpCount(lump, 4); + _surfedge = BR.ReadInt32Array(count); + } + return _surfedge; + } + } + #endregion + + #region Lump #14: Models + private dmodel_t[] _models; + /// + /// Lump #14. + /// Purpose: Brushes for rendering (mostly). [0] is global, [1 and more] are entities (func_brush/func_detail) + /// + public dmodel_t[] Models + { + get + { + if (_models == null) + { + lump_t lump = SetLump(14); + int count = GetLumpCount(lump, 48); + _models = new dmodel_t[count]; + for (int m = 0; m < count; m++) + { + _models[m] = new dmodel_t + { + mins = BR.ReadVector(), + maxs = BR.ReadVector(), + origin = BR.ReadVector(), + headnode = BR.ReadInt32(), + firstface = BR.ReadInt32(), + numfaces = BR.ReadInt32() + }; + } + } + return _models; + } + } + #endregion + + #region Lump #15: World lights (LDR) + private object _worldlights; + /// + /// Lump #15. Version 0/1. + /// Purpose: Contains info about static lights (NOT LIGHTMAPS). + /// Usage (depending on version): (dworldlightV?_t[])bsp.WorldLights. + /// Also: Check lump #54 for HDR world lights. + /// + public object WorldLights + { + get + { + if (_worldlights == null) + { + lump_t lump = SetLump(15); + int count; + switch (lump.version) + { + case 0: + count = GetLumpCount(lump, 88); + dworldlightV0_t[] _wl_0 = new dworldlightV0_t[count]; + for (int wl = 0; wl < count; wl++) + { + _wl_0[wl] = new dworldlightV0_t + { + origin = BR.ReadVector(), + intensity = BR.ReadVector(), + normal = BR.ReadVector(), + cluster = BR.ReadInt32(), + type = (emittype_t)BR.ReadUInt32(), + style = BR.ReadInt32(), + stopdot = BR.ReadSingle(), + stopdot2 = BR.ReadSingle(), + exponent = BR.ReadSingle(), + radius = BR.ReadSingle(), + constant_attn = BR.ReadSingle(), + linear_attn = BR.ReadSingle(), + quadratic_attn = BR.ReadSingle(), + flags = BR.ReadInt32(), + texinfo = BR.ReadInt32(), + owner = BR.ReadInt32() + }; + } + _worldlights = _wl_0; + break; + case 1: + count = GetLumpCount(lump, 100); + dworldlightV1_t[] _wl_1 = new dworldlightV1_t[count]; + for (int wl = 0; wl < count; wl++) + { + _wl_1[wl] = new dworldlightV1_t + { + origin = BR.ReadVector(), + intensity = BR.ReadVector(), + normal = BR.ReadVector(), + shadow_cast_offset = BR.ReadVector(), + cluster = BR.ReadInt32(), + type = (emittype_t)BR.ReadUInt32(), + style = BR.ReadInt32(), + stopdot = BR.ReadSingle(), + stopdot2 = BR.ReadSingle(), + exponent = BR.ReadSingle(), + radius = BR.ReadSingle(), + constant_attn = BR.ReadSingle(), + linear_attn = BR.ReadSingle(), + quadratic_attn = BR.ReadSingle(), + flags = BR.ReadInt32(), + texinfo = BR.ReadInt32(), + owner = BR.ReadInt32() + }; + } + _worldlights = _wl_1; + break; + default: + throw new NotImplementedException(); + } + + } + return _worldlights; + } + } + #endregion + + #region Lump #16: Leaf faces + private ushort[] _leaffaces; + /// + /// Lump #16. + /// Purpose: "... which are used to map from faces referenced in the leaf structure to indices in the face array", from Valve Dev Wiki. + /// + public ushort[] LeafFaces + { + get + { + if (_leaffaces == null) + { + lump_t lump = SetLump(16); + int count = GetLumpCount(lump, 2); + _leaffaces = BR.ReadUInt16Array(count); + } + return _leaffaces; + } + } + #endregion + + #region Lump #17: Leaf brushes + private ushort[] _leafbrushes; + /// + /// Lump #17. + /// Purpose: "does the same thing [as lump 16 - leaf faces] for brushes referenced in leaves", from Valve Dev Wiki. + /// + public ushort[] LeafBrushes + { + get + { + if (_leafbrushes == null) + { + lump_t lump = SetLump(17); + int count = GetLumpCount(lump, 2); + _leafbrushes = BR.ReadUInt16Array(count); + } + return _leafbrushes; + } + } + #endregion + + #region Lump #18: Brushes + private dbrush_t[] _brushes; + /// + /// Lump #18. + /// Purpose: Brush info. + /// + public dbrush_t[] Brushes + { + get + { + if (_brushes == null) + { + lump_t lump = SetLump(18); + int count = GetLumpCount(lump, 12); + _brushes = new dbrush_t[count]; + for (int b = 0; b < count; b++) + { + _brushes[b] = new dbrush_t + { + firstside = BR.ReadInt32(), + numsides = BR.ReadInt32(), + contents = BR.ReadInt32() + }; + } + } + return _brushes; + } + } + #endregion + + #region Lump #19: Brush Sides + private dbrushside_t[] _brushsides; + /// + /// Lump #19. + /// Purpose: Brush side info. + /// + public dbrushside_t[] BrushSides + { + get + { + if (_brushsides == null) + { + lump_t lump = SetLump(19); + int count = GetLumpCount(lump, 8); + _brushsides = new dbrushside_t[count]; + for (int bs = 0; bs < count; bs++) + { + _brushsides[bs] = new dbrushside_t + { + planenum = BR.ReadUInt16(), + texinfo = BR.ReadInt16(), + dispinfo = BR.ReadInt16(), + bevel = BR.ReadInt16() + }; + } + } + return _brushsides; + } + } + #endregion + + #region Lump #20: Areas + private darea_t[] _areas; + /// + /// Lump #20. + /// Purpose: Areas that are used for switching of areaportals; visibility things. + /// + public darea_t[] Areas + { + get + { + if (_areas == null) + { + lump_t lump = SetLump(20); + int count = GetLumpCount(lump, 8); + _areas = new darea_t[count]; + for (int a = 0; a < count; a++) + { + _areas[a] = new darea_t + { + numareaportals = BR.ReadInt32(), + firstareaportal = BR.ReadInt32() + }; + } + } + return _areas; + } + } + #endregion + + #region Lump #21: Areaportals + private dareaportal_t[] _areaportals; + /// + /// Lump #21. + /// Purpose: "used with func_areaportal and func_areaportalwindow entities to define sections of the map that can be switched to render or not render", from Valve Dev Wiki. + /// + public dareaportal_t[] Areaportals + { + get + { + if (_areaportals == null) + { + lump_t lump = SetLump(21); + int count = GetLumpCount(lump, 12); + _areaportals = new dareaportal_t[count]; + for (int ap = 0; ap < count; ap++) + { + _areaportals[ap] = new dareaportal_t + { + m_PortalKey = BR.ReadUInt16(), + otherarea = BR.ReadUInt16(), + m_FirstClipPortalVert = BR.ReadUInt16(), + m_nClipPortalVerts = BR.ReadUInt16(), + planenum = BR.ReadInt32() + }; + } + } + return _areaportals; + } + } + #endregion + + #region Lump #22 : 2004/2009 + #region Lump #22/1: Portals [Source 2004] + private dportal_t[] _portals; + /// + /// Lump #22. + /// Purpose: [not sure] Used by VVIS and VRAD only. + /// + public dportal_t[] Portals + { + get + { + if (_portals == null) + { + lump_t lump = SetLump(22); + if(lump.filelen % 16 != 0) //This lump is not for portals + return null; + int count = GetLumpCount(lump, 16); + _portals = new dportal_t[count]; + for (int p = 0; p < count; p++) + { + _portals[p] = new dportal_t + { + firstportalvert = BR.ReadInt32(), + numportalverts = BR.ReadInt32(), + planenum = BR.ReadInt32(), + cluster = BR.ReadUInt16Array(2) + }; + } + } + return _portals; + } + } + #endregion + #region Lump #22/2: Prop collisions (PROPCOLLISION) [Source 2009] + private dpropcollision_t[] _propcollision; + /// + /// Lump #22. + /// Purpose: "Static props convex hull lists", from Valve Dev Wiki. + /// + public dpropcollision_t[] PropCollision + { + get + { + if (_propcollision == null) + { + lump_t lump = SetLump(22); + if (lump.filelen % 8 != 0) //This lump is not for prop collisions + return null; + + int count = GetLumpCount(lump, 8); + _propcollision = new dpropcollision_t[count]; + for (int p = 0; p < count; p++) + { + _propcollision[p] = new dpropcollision_t + { + m_nHullCount = BR.ReadInt32(), + m_nHullStart = BR.ReadInt32() + }; + } + } + return _propcollision; + } + } + #endregion + #endregion + + #region Lump #23 : 2004/2009 + #region Lump #23/1: Clusters [Source 2004] + private dcluster_t[] _clusters; + /// + /// Lump #23. + /// Purpose: [not sure] Used by VVIS and VRAD only. + /// + public dcluster_t[] Clusters + { + get + { + if (_clusters == null) + { + lump_t lump = SetLump(23); + if (lump.filelen % 8 != 0) //This lump is not for clusters + return null; + + int count = GetLumpCount(lump, 8); + _clusters = new dcluster_t[count]; + for (int c = 0; c < count; c++) + { + _clusters[c] = new dcluster_t + { + firstportal = BR.ReadInt32(), + numportals = BR.ReadInt32() + }; + } + } + return _clusters; + } + } + #endregion + #region Lump #23/2: Prop hulls (PROPHULLS) [Source 2009] + private dprophull_t[] _prophulls; + /// + /// Lump #23. + /// Purpose: "Static prop convex hulls", from Valve Dev Wiki. + /// + public dprophull_t[] PropHulls + { + get + { + if (_prophulls == null) + { + lump_t lump = SetLump(23); + if (lump.filelen % 16 != 0) //This lump is not for prophulls + return null; + + int count = GetLumpCount(lump, 16); + _prophulls = new dprophull_t[count]; + for (int p = 0; p < count; p++) + { + _prophulls[p] = new dprophull_t + { + m_nVertCount = BR.ReadInt32(), + m_nVertStart = BR.ReadInt32(), + m_nSurfaceProp = BR.ReadInt32(), + m_nContents = BR.ReadUInt32() + }; + } + } + return _prophulls; + } + } + #endregion + #endregion + + #region Lump #24 : 2004/2009 - not tested: can't find map with this lump + #region Lump #24/1: Portal Vertices (PORTALVERTS) [Source 2004] + private ushort[] _portalverts; + /// + /// Lump #24. + /// Purpose: [not sure] Used by VVIS and VRAD only. + /// + public ushort[] PortalVerts + { + get + { + if (_portalverts == null) + { + lump_t lump = SetLump(24); + int count = GetLumpCount(lump, 2); + _portalverts = BR.ReadUInt16Array(count); + } + return _portalverts; + } + } + #endregion + #region Lump #24/2: Prop hull vertices (PROPHULLVERTS) [Source 2009] + private SourceVector[] _prophullverts; + /// + /// Lump #24. + /// Purpose: "Static prop collision vertices", from Valve Dev Wiki. + /// + public SourceVector[] PropHullVerts + { + get + { + if (_prophullverts == null) + { + lump_t lump = SetLump(24); + int count = GetLumpCount(lump, 12); + _prophullverts = new SourceVector[count]; + for (int v = 0; v < count; v++) + { + _prophullverts[v] = BR.ReadVector(); + } + } + return _prophullverts; + } + } + #endregion + #endregion + + #region Lump #25 : 2004/2009 - not tested: can't find map with this lump + #region Lump #25/1: Cluster Portals [Source 2004] + private ushort[] _clusterportals; + /// + /// Lump #25. + /// Purpose: [not sure] Used by VVIS and VRAD only. + /// + public ushort[] ClusterPortals + { + get + { + if (_clusterportals == null) + { + lump_t lump = SetLump(25); + int count = GetLumpCount(lump, 2); + _clusterportals = BR.ReadUInt16Array(count); + } + return _clusterportals; + } + } + #endregion + #region Lump #25/2: Prop Triangles (PROPTRIS) [Source 2009] + private dprophulltris_t[] _proptris; + /// + /// Lump #25. + /// Purpose: "Static prop per hull triangle index start/count", from Valve Dev Wiki. + /// + public dprophulltris_t[] PropTris + { + get + { + if (_proptris == null) + { + lump_t lump = SetLump(25); + int count = GetLumpCount(lump, 8); + _proptris = new dprophulltris_t[count]; + for (int p = 0; p < count; p++) + { + _proptris[p] = new dprophulltris_t + { + m_nIndexStart = BR.ReadInt32(), + m_nIndexCount = BR.ReadInt32() + }; + } + } + return _proptris; + } + } + #endregion + #endregion + + #region Lump #26: Displacement infos (DISPINFO) - SKIPPED: m_EdgeNeighbors/m_CornerNeighbors/m_AllowedVerts/unknown + private ddispinfo_t[] _dispinfo; + /// + /// Lump #26. + /// Purpose: [not sure] Displacement infos that is used by map compilators? + /// + public ddispinfo_t[] DispInfo + { + get + { + if (_dispinfo == null) + { + lump_t lump = SetLump(26); + int count = GetLumpCount(lump, 176); + _dispinfo = new ddispinfo_t[count]; + for (int d = 0; d < count; d++) + { + _dispinfo[d] = new ddispinfo_t + { + startPosition=BR.ReadVector(), + m_iDispVertStart=BR.ReadInt32(), + m_iDispTriStart=BR.ReadInt32(), + power=BR.ReadInt32(), + minTess=BR.ReadInt32(), + smoothingAngle=BR.ReadSingle(), + contents=BR.ReadInt32(), + m_iMapFace=BR.ReadUInt16(), + m_iLightmapAlphaStart=BR.ReadInt32(), + m_iLightmapSamplePositionStart=BR.ReadInt32() + }; + + BR.BaseStream.Seek(130, SeekOrigin.Current); + } + } + return _dispinfo; + } + } + #endregion + + #region Lump #27: Original faces + private dface_t[] _originalfaces; + /// + /// Lump #27. Version 1. + /// Purpose: "Brush faces array before splitting", VDW. Probably, used by map compilators. + /// + public dface_t[] OriginalFaces + { + get + { + if (_originalfaces == null) + { + lump_t lump = SetLump(27); + int count = GetLumpCount(lump, 56); + _originalfaces = new dface_t[count]; + for (int f = 0; f < count; f++) + { + _originalfaces[f] = new dface_t + { + planenum = BR.ReadUInt16(), + side = BR.ReadByte(), + onNode = BR.ReadByte(), + firstedge = BR.ReadInt32(), + numedges = BR.ReadInt16(), + texinfo = BR.ReadInt16(), + dispinfo = BR.ReadInt16(), + surfaceFogVolumeID = BR.ReadInt16(), + styles = BR.ReadBytes(4), + lightofs = BR.ReadInt32(), + area = BR.ReadSingle(), + m_LightmapTextureMinsInLuxels = BR.ReadVector2Int(), + m_LightmapTextureSizeInLuxels = BR.ReadVector2Int(), + origFace = BR.ReadInt32(), + m_NumPrims = BR.ReadUInt16(), + firstPrimID = BR.ReadUInt16(), + smoothingGroups = BR.ReadUInt32() + }; + } + } + return _originalfaces; + } + } + #endregion + + #region Lump #28: Displacement Physics (PHYSDISP) - not full: SourcePHY parser needed (i guess) + private dphysdisp_t[] _physdisp; + /// + /// Lump #28. + /// Purpose: Displacement physics collision data. + /// + public dphysdisp_t[] PhysDisp + { + get + { + if (_physdisp == null) + { + lump_t lump = SetLump(28); + //int count = GetLumpCount(lump, 2); + List _physdisp_list = new List(); + while(BR.BaseStream.Position < lump.fileofs + lump.filelen - 1) + { + ushort numDisplacements = BR.ReadUInt16(); + ushort[] dataSize = BR.ReadUInt16Array(numDisplacements); + if (dataSize.Length >= 1 && dataSize[0] == 0) + break; + + long totalsize = 0; + foreach (ushort s in dataSize) totalsize += s; + + _physdisp_list.Add(new dphysdisp_t + { + numDisplacements = numDisplacements, + dataSize = dataSize + }); + } + + //if (lump.filelen > 0 && lump.filelen - (BR.BaseStream.Position - lump.fileofs) > 0) + // DebugLog.Write($"readen={BR.BaseStream.Position - lump.fileofs}; len={lump.filelen}; left={lump.filelen - (BR.BaseStream.Position - lump.fileofs)}"); + + // == There i should parse these displacements, but i dont know how (idk what is that format, mb PHY?). + // === g_pPhysDisp, g_PhysDispSize + + _physdisp = _physdisp_list.ToArray(); + } + return _physdisp; + } + } + #endregion + + #region Lump #29: Physics collision infos (PHYSCOLLIDE) - not full: SourcePHY parser needed + private dphysmodel_t[] _physcollide; + /// + /// Lump #29. + /// Purpose: Physics collision data. Used to calculate VPhysics (for prop_physics, i guess). + /// + public dphysmodel_t[] PhysCollide + { + get + { + if (_physcollide == null) + { + lump_t lump = SetLump(29); + //int count = GetLumpCount(lump, 2); + List _physcollide_list = new List(); + while (BR.BaseStream.Position < lump.fileofs + lump.filelen - 1) + { + var physmodel = new dphysmodel_t + { + modelIndex = BR.ReadInt32(), + dataSize = BR.ReadInt32(), + keydataSize = BR.ReadInt32(), + solidCount = BR.ReadInt32() + }; + + if (physmodel.modelIndex == -1) + break; + + int size; + for (int k = 0; k < physmodel.solidCount; k++) + { + size = BR.ReadInt32(); + byte[] collisionData = BR.ReadBytes(size); + //sourcephy solid = sourcephy.parsebody?(collisiondata); + // = or + //sourcephy solid = sourcephy.parsebody?(BR); // - to read bytes dynamically? + } + + physmodel.keydata = Encoding.ASCII.GetString(BR.ReadBytes(physmodel.keydataSize - 1)); //-1 because last is always \0 + BR.BaseStream.Seek(1, SeekOrigin.Current); //skip 1 byte because of prev line + + _physcollide_list.Add(physmodel); + } + + // == "The last two parts appear to be identical to the PHY file format, which means their exact contents are unknown." + // === - from Valve Dev Wiki. + // === Anchored link: https://developer.valvesoftware.com/wiki/Source_BSP_File_Format#Physics + + _physcollide = _physcollide_list.ToArray(); + } + return _physcollide; + } + } + #endregion + + #region Lump #30: Vertex Normals (VERTNORMALS) + private SourceVector[] _vertnormals; + /// + /// Lump #30. + /// Purpose: Face plane normals. "may be related to smoothing of lightmaps on faces", from Valve Dev Wiki. + /// + public SourceVector[] VertNormals + { + get + { + if (_vertnormals == null) + { + lump_t lump = SetLump(30); + int count = GetLumpCount(lump, 12); + + _vertnormals = new SourceVector[count]; + for (int i = 0; i < count; i++) + _vertnormals[i] = BR.ReadVector(); + } + return _vertnormals; + } + } + #endregion + + #region Lump #31: Vertex Normal Indices (VERTNORMALINDICES) + private ushort[] _vertnormalindices; + /// + /// Lump #31. + /// Purpose: Face plane normal index array. "may be related to smoothing of lightmaps on faces", from Valve Dev Wiki. + /// + public ushort[] VertNormalIndices + { + get + { + if (_vertnormalindices == null) + { + lump_t lump = SetLump(31); + int count = GetLumpCount(lump, 2); + _vertnormalindices = BR.ReadUInt16Array(count); + } + return _vertnormalindices; + } + } + #endregion + + #region Lump #32: Lightmap alphas for displacements (DISP_LIGHTMAP_ALPHAS) + private byte[] _disp_lightmap_alphas; + /// + /// Lump #32. + /// Purpose: "Displacement lightmap alphas (unused/empty since Source 2006)", from Valve Dev Wiki. + /// + public byte[] DispLightmapAlphas + { + get + { + if (_disp_lightmap_alphas == null) + { + lump_t lump = SetLump(32); + _disp_lightmap_alphas = BR.ReadBytes(lump.filelen); + } + return _disp_lightmap_alphas; + } + } + #endregion + + #region Lump #33: Displacement vertices (DISP_VERTS) + private CDispVert[] _dispverts; + /// + /// Lump #33. + /// Purpose: Info about vertices for displacements. + /// + public CDispVert[] DispVerts + { + get + { + if (_dispverts == null) + { + lump_t lump = SetLump(33); + int count = GetLumpCount(lump, 20); + _dispverts = new CDispVert[count]; + for (int v = 0; v < count; v++) + { + _dispverts[v] = new CDispVert + { + m_vVector = BR.ReadVector(), + m_flDist = BR.ReadSingle(), + m_flAlpha = BR.ReadSingle() + }; + } + } + return _dispverts; + } + } + #endregion + + #region Lump #34: Displacement Lightmap Sample Positions (DISP_LIGHTMAP_SAMPLE_POSITIONS) + private byte[] _displmsamplepos; + /// + /// Lump #34. + /// Purpose: supposed to be ColorRGBExp32, but its byte array in source code. + /// i dunno that's literally boxes on white background (as i can remember). it's useless because lightmaps for disps are in LUMP_LIGHTING. + /// + public byte[] DispLightmapSamplePositions + { + get + { + if (_displmsamplepos == null) + { + lump_t lump = SetLump(34); + _displmsamplepos = BR.ReadBytes(lump.filelen); + } + return _displmsamplepos; + } + } + #endregion + + #region Lump #35: Game lump + private dgamelumpheader_t _gamelump; + /// + /// Lump #35. + /// Purpose: Game-specific data lump. Contains info about static props and detail prop. + /// + public dgamelumpheader_t GameLump + { + get + { + if (_gamelump.lumps == null) + { + lump_t lump = SetLump(35); + + if (lump.filelen == 0) + { + _gamelump.lumps = new dgamelump_t[0]; + return _gamelump; + } + + // Read dictionary... + _gamelump = new dgamelumpheader_t { lumpCount = BR.ReadInt32() }; + _gamelump.lumps = new dgamelump_t[_gamelump.lumpCount]; + for (int l = 0; l < _gamelump.lumpCount; l++) + { + _gamelump.lumps[l] = new dgamelump_t + { + id = BR.ReadInt32(), + flags = BR.ReadUInt16(), + version = BR.ReadUInt16(), + fileofs = BR.ReadInt32(), + filelen = BR.ReadInt32() + }; + } + for (int l = 0; l < _gamelump.lumpCount; ++l) + { + dgamelump_t gamelump = _gamelump.lumps[l]; + long startofs = BR.BaseStream.Position; + long endofs = startofs + gamelump.filelen; + int count = 0; + switch (gamelump.id_code) + { + case GAMELUMP_CODES.GAMELUMP_STATIC_PROPS: + //read names + count = BR.ReadInt32(); + _gamelump.staticPropNames = new StaticPropDictLump_t[count]; + //Elapsed {00:00:00.0005491} {00:00:00.0005547} + for (int n = 0; n < count; n++) + { + string name = string.Empty; + + for (int b = 0; b < 128; b++) + { + byte _c = BR.ReadByte(); + if (_c == (byte)'\0') + { + BR.BaseStream.Seek(128 - b - 1, SeekOrigin.Current); + break; + } + name += Encoding.ASCII.GetString(new byte[1] { _c }); + } + + _gamelump.staticPropNames[n].m_Name = name; + } + + //read leafs + count = BR.ReadInt32(); + _gamelump.staticPropLeafs = new StaticPropLeafLump_t[count]; + for (int lf = 0; lf < count; lf++) + _gamelump.staticPropLeafs[lf].m_Leaf = BR.ReadUInt16(); + + + //read the models + count = BR.ReadInt32(); + switch (gamelump.version) + { + case 4: + StaticPropLumpV4_t[] sp_v4 = new StaticPropLumpV4_t[count]; + for (int sp = 0; sp < count; sp++) + { + sp_v4[sp] = new StaticPropLumpV4_t + { + m_Origin = BR.ReadVector(), + m_Angles = BR.ReadQAngle(), + m_PropType = BR.ReadUInt16(), + m_FirstLeaf = BR.ReadUInt16(), + m_LeafCount = BR.ReadUInt16(), + m_Solid = BR.ReadByte(), + m_Flags = BR.ReadByte(), + m_Skin = BR.ReadInt32(), + m_FadeMinDist = BR.ReadSingle(), + m_FadeMaxDist = BR.ReadSingle(), + m_LightingOrigin = BR.ReadVector() + }; + } + _gamelump.staticProps = sp_v4; + break; + case 5: + StaticPropLumpV5_t[] sp_v5 = new StaticPropLumpV5_t[count]; + for (int sp = 0; sp < count; sp++) + { + sp_v5[sp] = new StaticPropLumpV5_t + { + m_Origin = BR.ReadVector(), + m_Angles = BR.ReadQAngle(), + m_PropType = BR.ReadUInt16(), + m_FirstLeaf = BR.ReadUInt16(), + m_LeafCount = BR.ReadUInt16(), + m_Solid = BR.ReadByte(), + m_Flags = BR.ReadByte(), + m_Skin = BR.ReadInt32(), + m_FadeMinDist = BR.ReadSingle(), + m_FadeMaxDist = BR.ReadSingle(), + m_LightingOrigin = BR.ReadVector(), + m_flForcedFadeScale = BR.ReadSingle() + }; + } + _gamelump.staticProps = sp_v5; + break; + case 6: + StaticPropLumpV6_t[] sp_v6 = new StaticPropLumpV6_t[count]; + for (int sp = 0; sp < count; sp++) + { + sp_v6[sp] = new StaticPropLumpV6_t + { + m_Origin = BR.ReadVector(), + m_Angles = BR.ReadQAngle(), + m_PropType = BR.ReadUInt16(), + m_FirstLeaf = BR.ReadUInt16(), + m_LeafCount = BR.ReadUInt16(), + m_Solid = BR.ReadByte(), + m_Flags = BR.ReadByte(), + m_Skin = BR.ReadInt32(), + m_FadeMinDist = BR.ReadSingle(), + m_FadeMaxDist = BR.ReadSingle(), + m_LightingOrigin = BR.ReadVector(), + m_flForcedFadeScale = BR.ReadSingle(), + m_nMinDXLevel = BR.ReadUInt16(), + m_nMaxDXLevel = BR.ReadUInt16() + }; + } + _gamelump.staticProps = sp_v6; + break; + case 7: //not tested + StaticPropLumpV7_t[] sp_v7 = new StaticPropLumpV7_t[count]; + for (int sp = 0; sp < count; sp++) + { + sp_v7[sp] = new StaticPropLumpV7_t + { + m_Origin = BR.ReadVector(), + m_Angles = BR.ReadQAngle(), + m_PropType = BR.ReadUInt16(), + m_FirstLeaf = BR.ReadUInt16(), + m_LeafCount = BR.ReadUInt16(), + m_Solid = BR.ReadByte(), + m_Flags = BR.ReadByte(), + m_Skin = BR.ReadInt32(), + m_FadeMinDist = BR.ReadSingle(), + m_FadeMaxDist = BR.ReadSingle(), + m_LightingOrigin = BR.ReadVector(), + m_flForcedFadeScale = BR.ReadSingle(), + m_nMinDXLevel = BR.ReadUInt16(), + m_nMaxDXLevel = BR.ReadUInt16(), + m_DiffuseModulation = BR.ReadColor32() + }; + } + _gamelump.staticProps = sp_v7; + break; + case 8: + StaticPropLumpV8_t[] sp_v8 = new StaticPropLumpV8_t[count]; + for (int sp = 0; sp < count; sp++) + { + sp_v8[sp] = new StaticPropLumpV8_t + { + m_Origin = BR.ReadVector(), + m_Angles = BR.ReadQAngle(), + m_PropType = BR.ReadUInt16(), + m_FirstLeaf = BR.ReadUInt16(), + m_LeafCount = BR.ReadUInt16(), + m_Solid = BR.ReadByte(), + m_Flags = BR.ReadByte(), + m_Skin = BR.ReadInt32(), + m_FadeMinDist = BR.ReadSingle(), + m_FadeMaxDist = BR.ReadSingle(), + m_LightingOrigin = BR.ReadVector(), + m_flForcedFadeScale = BR.ReadSingle(), + m_nMinCPULevel = BR.ReadByte(), + m_nMaxCPULevel = BR.ReadByte(), + m_nMinGPULevel = BR.ReadByte(), + m_nMaxGPULevel = BR.ReadByte(), + m_DiffuseModulation = BR.ReadColor32() + }; + } + _gamelump.staticProps = sp_v8; + break; + case 9: + StaticPropLumpV9_t[] sp_v9 = new StaticPropLumpV9_t[count]; + for (int sp = 0; sp < count; sp++) + { + sp_v9[sp] = new StaticPropLumpV9_t + { + m_Origin = BR.ReadVector(), + m_Angles = BR.ReadQAngle(), + m_PropType = BR.ReadUInt16(), + m_FirstLeaf = BR.ReadUInt16(), + m_LeafCount = BR.ReadUInt16(), + m_Solid = BR.ReadByte(), + m_Flags = BR.ReadByte(), + m_Skin = BR.ReadInt32(), + m_FadeMinDist = BR.ReadSingle(), + m_FadeMaxDist = BR.ReadSingle(), + m_LightingOrigin = BR.ReadVector(), + m_flForcedFadeScale = BR.ReadSingle(), + m_nMinCPULevel = BR.ReadByte(), + m_nMaxCPULevel = BR.ReadByte(), + m_nMinGPULevel = BR.ReadByte(), + m_nMaxGPULevel = BR.ReadByte(), + m_DiffuseModulation = BR.ReadColor32(), + m_bDisableX360 = BR.ReadInt32() + }; + } + _gamelump.staticProps = sp_v9; + break; + case 10: + StaticPropLumpV10_t[] sp_v10 = new StaticPropLumpV10_t[count]; + for (int sp = 0; sp < count; sp++) + { + sp_v10[sp] = new StaticPropLumpV10_t + { + m_Origin = BR.ReadVector(), + m_Angles = BR.ReadQAngle(), + m_PropType = BR.ReadUInt16(), + m_FirstLeaf = BR.ReadUInt16(), + m_LeafCount = BR.ReadUInt16(), + m_Solid = BR.ReadByte(), + m_Flags = BR.ReadByte(), + m_Skin = BR.ReadInt32(), + m_FadeMinDist = BR.ReadSingle(), + m_FadeMaxDist = BR.ReadSingle(), + m_LightingOrigin = BR.ReadVector(), + m_flForcedFadeScale = BR.ReadSingle(), + m_nMinCPULevel = BR.ReadByte(), + m_nMaxCPULevel = BR.ReadByte(), + m_nMinGPULevel = BR.ReadByte(), + m_nMaxGPULevel = BR.ReadByte(), + m_DiffuseModulation = BR.ReadColor32(), + m_bDisableX360 = BR.ReadInt32(), + m_FlagsEx = BR.ReadUInt32() + }; + } + _gamelump.staticProps = sp_v10; + break; + case 11: + StaticPropLumpV11_t[] sp_v11 = new StaticPropLumpV11_t[count]; + for (int sp = 0; sp < count; sp++) + { + sp_v11[sp] = new StaticPropLumpV11_t + { + m_Origin = BR.ReadVector(), + m_Angles = BR.ReadQAngle(), + m_PropType = BR.ReadUInt16(), + m_FirstLeaf = BR.ReadUInt16(), + m_LeafCount = BR.ReadUInt16(), + m_Solid = BR.ReadByte(), + m_Flags = BR.ReadByte(), + m_Skin = BR.ReadInt32(), + m_FadeMinDist = BR.ReadSingle(), + m_FadeMaxDist = BR.ReadSingle(), + m_LightingOrigin = BR.ReadVector(), + m_flForcedFadeScale = BR.ReadSingle(), + m_nMinCPULevel = BR.ReadByte(), + m_nMaxCPULevel = BR.ReadByte(), + m_nMinGPULevel = BR.ReadByte(), + m_nMaxGPULevel = BR.ReadByte(), + m_DiffuseModulation = BR.ReadColor32(), + m_bDisableX360 = BR.ReadInt32(), + m_FlagsEx = BR.ReadUInt32(), + m_UniformScale = BR.ReadSingle() + }; + } + _gamelump.staticProps = sp_v11; + break; + default: + DebugLog.Write("Unsupported static prop version: " + gamelump.version); + break; + } + break; + + case GAMELUMP_CODES.GAMELUMP_DETAIL_PROPS: + //read names + count = BR.ReadInt32(); + _gamelump.detailPropNames = new DetailObjectDictLump_t[count]; + for (int n = 0; n < count; n++) + { + string name = string.Empty; + + for (int b = 0; b < 128; b++) + { + byte _c = BR.ReadByte(); + if (_c == (byte)'\0') + { + BR.BaseStream.Seek(128 - b - 1, SeekOrigin.Current); + break; + } + name += Encoding.ASCII.GetString(new byte[1] { _c }); + } + + _gamelump.detailPropNames[n].m_Name = name; + } + + if (gamelump.version == 4) + { + if (count > 0) + { + //read detail prop sprites + count = BR.ReadInt32(); + _gamelump.detailPropSprites = new DetailSpriteDictLump_t[count]; + for (int s = 0; s < count; s++) + { + _gamelump.detailPropSprites[s] = new DetailSpriteDictLump_t + { + m_UL = BR.ReadVector2(), + m_LR = BR.ReadVector2(), + m_TexUL = BR.ReadVector2(), + m_TexLR = BR.ReadVector2() + }; + } + //read detail props + count = BR.ReadInt32(); + + _gamelump.detailProps = new DetailObjectLump_t[count]; + for (int p = 0; p < count; p++) + { + _gamelump.detailProps[p] = new DetailObjectLump_t + { + m_Origin = BR.ReadVector(), + m_Angles = BR.ReadQAngle(), + m_DetailModel = BR.ReadUInt16(), + m_Leaf = BR.ReadUInt16(), + m_Lighting = BR.ReadColorRGBExp32(), + m_LightStyles = BR.ReadUInt32(), + m_LightStyleCount = BR.ReadByte(), + m_SwayAmount = BR.ReadByte(), + m_ShapeAngle = BR.ReadByte(), + m_ShapeSize = BR.ReadByte(), + m_Orientation = BR.ReadByte(), + m_Padding2 = BR.ReadBytes(3), + m_Type = BR.ReadByte(), + m_Padding3 = BR.ReadBytes(3), + m_flScale = BR.ReadSingle() + }; + } + } + } + else + DebugLog.Write("Unsupported detail prop version: " + gamelump.version); + break; + + case GAMELUMP_CODES.GAMELUMP_DETAIL_PROP_LIGHTING: + // read prop lightings info + count = BR.ReadInt32(); + _gamelump.detailPropLighting = new DetailPropLightstylesLump_t[count]; + for (int p = 0; p < count; p++) + { + _gamelump.detailPropLighting[p] = new DetailPropLightstylesLump_t + { + m_Lighting = BR.ReadColorRGBExp32(), + m_Style = BR.ReadByte() + }; + } + break; + + case GAMELUMP_CODES.GAMELUMP_DETAIL_PROP_LIGHTING_HDR: + // read prop lightings info + count = BR.ReadInt32(); + _gamelump.detailPropLightingHDR = new DetailPropLightstylesLump_t[count]; + for (int p = 0; p < count; p++) + { + _gamelump.detailPropLightingHDR[p] = new DetailPropLightstylesLump_t + { + m_Lighting = BR.ReadColorRGBExp32(), + m_Style = BR.ReadByte() + }; + } + break; + + default: + DebugLog.Write($"Unknown game lump '{gamelump.id}' ({gamelump.id_code}) didn't get swapped!"); + break; + } + BR.BaseStream.Seek(endofs, SeekOrigin.Begin); //for some [unknown for me] reasons we should place reader to the end of lump manually + } + } + return _gamelump; + } + } + #endregion + + #region Lump #36: Water leaf data (LEAFWATERDATA) + private dleafwaterdata_t[] _leafwaterdata; + /// + /// Lump #36. + /// Purpose: Data for leaf nodes that are inside water. + /// + public dleafwaterdata_t[] LeafWaterData + { + get + { + if (_leafwaterdata == null) + { + lump_t lump = SetLump(36); + int count = GetLumpCount(lump, 12); + + _leafwaterdata = new dleafwaterdata_t[count]; + for (int lw = 0; lw < count; lw++) + { + _leafwaterdata[lw] = new dleafwaterdata_t + { + surfaceZ = BR.ReadSingle(), + minZ = BR.ReadSingle(), + surfaceTexInfoID = BR.ReadInt16(), + unknown = BR.ReadInt16() + }; + } + } + return _leafwaterdata; + } + } + #endregion + + #region Lump #37: Primitives + private dprimitive_t[] _primitives; + /// + /// Lump #37. + /// Purpose: "are used in reference to /non-polygonal primitives/", from Valve Dev Wiki. + /// + public dprimitive_t[] Primitives + { + get + { + if (_primitives == null) + { + lump_t lump = SetLump(37); + int count = GetLumpCount(lump, 9); + + _primitives = new dprimitive_t[count]; + for (int p = 0; p < count; p++) + { + _primitives[p] = new dprimitive_t + { + type = BR.ReadByte(), + firstIndex = BR.ReadUInt16(), + indexCount = BR.ReadUInt16(), + firstVert = BR.ReadUInt16(), + vertCount = BR.ReadUInt16() + }; + } + } + return _primitives; + } + } + #endregion + + #region Lump #38: Primitive vertices - not tested: can't find bsp with this lump + private SourceVector[] _primverts; + /// + /// Lump #38. + /// Purpose: "are used in reference to /non-polygonal primitives/", from Valve Dev Wiki. + /// + public SourceVector[] PrimVerts + { + get + { + if (_primverts == null) + { + lump_t lump = SetLump(38); + int count = GetLumpCount(lump, 12); + + _primverts = new SourceVector[count]; + for (int p = 0; p < count; p++) + _primverts[p] = BR.ReadVector(); + } + return _primverts; + } + } + #endregion + + #region Lump #39: Primitive indices + private ushort[] _primindices; + /// + /// Lump #39. + /// Purpose: "are used in reference to /non-polygonal primitives/", from Valve Dev Wiki. + /// + public ushort[] Primindices + { + get + { + if (_primindices == null) + { + lump_t lump = SetLump(39); + int count = GetLumpCount(lump, 2); + _primindices = BR.ReadUInt16Array(count); + } + return _primindices; + } + } + #endregion + + #region Lump #40: PAK file + private byte[] _pak; + /// + /// Lump #40. + /// Purpose: Contains game files for map. + /// Note: not really sure if i should use something else (not byte[]) there. + /// + public byte[] PakFile + { + get + { + if (_pak == null) + { + lump_t lump = SetLump(40); + _pak = ReadLump(lump.lumpNum); + } + return _pak; + } + } + #endregion + + #region Lump #41: Clipping portal vertices + private SourceVector[] _clipportalverts; + /// + /// Lump #41. + /// Purpose: [not sure] Used by VVIS and VRAD only. + /// + public SourceVector[] ClipPortalVerts + { + get + { + if (_clipportalverts == null) + { + lump_t lump = SetLump(41); + int count = GetLumpCount(lump, 12); + + _clipportalverts = new SourceVector[count]; + for (int p = 0; p < count; p++) + _clipportalverts[p] = BR.ReadVector(); + } + return _clipportalverts; + } + } + #endregion + + #region Lump #42: Cubemaps + private dcubemapsample_t[] _cubemaps; + /// + /// Lump #42. + /// Purpose: env_cubemap entities info. + /// + public dcubemapsample_t[] Cubemaps + { + get + { + if (_cubemaps == null) + { + lump_t lump = SetLump(42); + int count = GetLumpCount(lump, 16); + + _cubemaps = new dcubemapsample_t[count]; + for (int p = 0; p < count; p++) + { + _cubemaps[p] = new dcubemapsample_t + { + origin = BR.ReadInt32Array(3), + size = BR.ReadByte(), + //unused = BR.ReadBytes(3) + }; + BR.BaseStream.Seek(3, SeekOrigin.Current); + } + } + return _cubemaps; + } + } + #endregion + + #region Lump #43/44: Texture data strings (TEXDATA_STRING_DATA / TEXDATA_STRING_TABLE) + private string[] _texdatastring; + /// + /// Lump #43/44. + /// Purpose: Paths to VMTs of textures. + /// + public string[] TexdataString + { + get + { + if (_texdatastring == null) + { + lump_t lump = SetLump(44); + int count = GetLumpCount(lump, 4); + int[] ofss = BR.ReadInt32Array(count); + _texdatastring = new string[count]; + + lump = SetLump(43); + for (int o = 0; o < count; o++) + { + int ofs = ofss[o]; + BR.BaseStream.Seek(lump.fileofs + ofs, SeekOrigin.Begin); + string tex = string.Empty; + char c; + while ((c = (char)BR.ReadByte()) != '\0') + tex += c; + _texdatastring[o] = tex; + } + } + return _texdatastring; + } + } + #endregion + + #region Lump #45: Overlays + private doverlay_t[] _overlays; + /// + /// Lump #45. + /// Purpose: infodecal entities - overlays. + /// + public doverlay_t[] Overlays + { + get + { + if (_overlays == null) + { + lump_t lump = SetLump(45); + int count = GetLumpCount(lump, 352); + + _overlays = new doverlay_t[count]; + for (int p = 0; p < count; p++) + { + _overlays[p] = new doverlay_t + { + nId = BR.ReadInt32(), + nTexInfo = BR.ReadInt16(), + m_nFaceCountAndRenderOrder = BR.ReadUInt16(), + aFaces = BR.ReadInt32Array(OVERLAY_BSP_FACE_COUNT), + flU = BR.ReadSingleArray(2), + flV = BR.ReadSingleArray(2), + vecUVPoints = new SourceVector[4] { BR.ReadVector(), BR.ReadVector(), BR.ReadVector(), BR.ReadVector() }, + vecOrigin = BR.ReadVector(), + vecBasisNormal = BR.ReadVector() + }; + } + } + return _overlays; + } + } + #endregion + + #region Lump #46: Minimal distance to water from leafs (LEAFMINDISTTOWATER) + private ushort[] _leafmindisttowater; + /// + /// Lump #46. + /// Purpose: Distance from leaf to water. + /// + public ushort[] LeafMinDistToWater + { + get + { + if (_leafmindisttowater == null) + { + lump_t lump = SetLump(46); + int count = GetLumpCount(lump, 2); + _leafmindisttowater = BR.ReadUInt16Array(count); + } + return _leafmindisttowater; + } + } + #endregion + + #region Lump #47: Face macro texinfo (FACE_MACRO_TEXTURE_INFO) + private ushort[] _facemacrotexinfo; + /// + /// Lump #47. + /// Purpose: Macro texture info for faces. + /// This looks up into g_TexDataStringTable, which looks up into g_TexDataStringData. + /// 0xFFFF if the face has no macro texture. + /// + public ushort[] FaceMacroTextureInfo + { + get + { + if (_facemacrotexinfo == null) + { + lump_t lump = SetLump(47); + int count = GetLumpCount(lump, 2); + _facemacrotexinfo = BR.ReadUInt16Array(count); + } + return _facemacrotexinfo; + } + } + #endregion + + #region Lump #48: Displacement triangles (DISP_TRIS) + private CDispTri[] _disptris; + /// + /// Lump #48. + /// Purpose: Displacement triangle tags. + /// + public CDispTri[] DispTris + { + get + { + if (_disptris == null) + { + lump_t lump = SetLump(48); + int count = GetLumpCount(lump, 2); + _disptris = new CDispTri[count]; + for (int d = 0; d < count; d++) + { + _disptris[d] = new CDispTri + { + m_uiTags = BR.ReadUInt16() + }; + } + } + return _disptris; + } + } + #endregion + + #region Lump #49 : 2004/2009 - not implemented: can't find structs for this lump + #region Lump #49/1: Compressed physics collision data (PHYSCOLLIDESURFACE) [Source 2004] + private object _physcollidesurface; + /// + /// Lump #49. + /// Purpose: "deprecated. We no longer use win32-specific havok compression on terrain", from Source 2013 code. + /// + public object PhysCollideSurface + { + get + { + if (_physcollidesurface == null) + { + //lump_t lump = SetLump(49); + //int count = GetLumpCount(lump, 2); + //_physcollidesurface = new ...[count]; + throw new NotImplementedException(); + } + return _physcollidesurface; + } + } + #endregion + #region Lump #49/2: (PROP_BLOB) [Source 2009] + private object _propblob; + /// + /// Lump #49. + /// Purpose: "static prop triangle & string data", from Source 20?? code. + /// + public object PropBlob + { + get + { + if (_propblob == null) + { + //lump_t lump = SetLump(49); + //int count = GetLumpCount(lump, 2); + //_propblob = new ...[count]; + throw new NotImplementedException(); + } + return _propblob; + } + } + #endregion + #endregion + + #region Lump #50: Water overlays - not tested: can't find map with this lump + private dwateroverlay_t[] _wateroverlays; + /// + /// Lump #50. + /// Purpose: [unknown]. + /// + public dwateroverlay_t[] WaterOverlays + { + get + { + if (_wateroverlays == null) + { + lump_t lump = SetLump(50); + int count = GetLumpCount(lump, 1120); + _wateroverlays = new dwateroverlay_t[count]; + for (int d = 0; d < count; d++) + { + _wateroverlays[d] = new dwateroverlay_t + { + nId = BR.ReadInt32(), + nTexInfo = BR.ReadInt16(), + m_nFaceCountAndRenderOrder = BR.ReadUInt16(), + aFaces = BR.ReadInt32Array(WATEROVERLAY_BSP_FACE_COUNT), + flU = BR.ReadSingleArray(2), + flV = BR.ReadSingleArray(2), + vecUVPoints = new SourceVector[4] { BR.ReadVector(), BR.ReadVector(), BR.ReadVector(), BR.ReadVector() }, + vecOrigin = BR.ReadVector(), + vecBasisNormal = BR.ReadVector() + }; + } + } + return _wateroverlays; + } + } + #endregion + + #region Lump #51 XBOX2006/2007 + #region Lump #51/1: Lightmap pages (LIGHTMAPPAGES) [Source 2006 for XBOX] - not tested: can't find map with this lump + private dlightmappage_t[] _lightmappages; + /// + /// Lump #51. + /// Purpose: Lightmaps for XBOX. + /// + public dlightmappage_t[] LightmapPages + { + get + { + if (_lightmappages == null) + { + lump_t lump = SetLump(51); + if (lump.filelen < 33792) //This lump is not for lightmap pages + return null; + int count = GetLumpCount(lump, 33792); + _lightmappages = new dlightmappage_t[count]; + for (int d = 0; d < count; d++) + { + _lightmappages[d] = new dlightmappage_t + { + data = BR.ReadBytes(MAX_LIGHTMAPPAGE_WIDTH * MAX_LIGHTMAPPAGE_HEIGHT) + }; + _lightmappages[d].palette = new ColorRGBExp32[256]; + for (int p = 0; p < 256; p++) + _lightmappages[d].palette[p] = BR.ReadColorRGBExp32(); + } + } + return _lightmappages; + } + } + #endregion + #region Lump #51/2: (LEAF_AMBIENT_INDEX_HDR) [Source 2007] + private dleafambientindex_t[] _leafambientindexhdr; + /// + /// Lump #51. + /// Purpose: "index of LUMP_LEAF_AMBIENT_LIGHTING_HDR", from Source 2013 code. + /// + public dleafambientindex_t[] LeafAmbientIndexHDR + { + get + { + if (_leafambientindexhdr == null) + { + lump_t lump = SetLump(51); + if (lump.filelen == 0 || lump.filelen % 4 != 0) //This lump is not for ... this + return null; + int count = GetLumpCount(lump, 4); + _leafambientindexhdr = new dleafambientindex_t[count]; + for (int d = 0; d < count; d++) + { + _leafambientindexhdr[d] = new dleafambientindex_t + { + ambientSampleCount = BR.ReadUInt16(), + firstAmbientSample = BR.ReadUInt16() + }; + } + } + return _leafambientindexhdr; + } + } + #endregion + #endregion + + #region Lump #52 XBOX2006/2007 + #region Lump #52/1: Lightmap page infos (LIGHTMAPPAGEINFOS) [Source 2006 for XBOX] - not tested: can't find map with this lump + private dlightmappageinfo_t[] _lightmappageinfos; + /// + /// Lump #52. + /// Purpose: Lightmaps for XBOX. + /// + public dlightmappageinfo_t[] LightmapPageInfos + { + get + { + if (_lightmappageinfos == null) + { + lump_t lump = SetLump(52); + if (lump.filelen == 0 || lump.filelen % 8 != 0) //This lump is not for lightmap page infos + return null; + int count = GetLumpCount(lump, 8); + _lightmappageinfos = new dlightmappageinfo_t[count]; + for (int d = 0; d < count; d++) + { + _lightmappageinfos[d] = new dlightmappageinfo_t + { + page = BR.ReadByte(), + offset = BR.ReadBytes(2), + pad = BR.ReadByte(), + avgColor = BR.ReadColorRGBExp32() + }; + } + } + return _lightmappageinfos; + } + } + #endregion + #region Lump #52/2: (LEAF_AMBIENT_INDEX) [Source 2007] + private dleafambientindex_t[] _leafambientindex; + /// + /// Lump #52. + /// Purpose: "index of LUMP_LEAF_AMBIENT_LIGHTING", from Source 2013 code. + /// + public dleafambientindex_t[] LeafAmbientIndex + { + get + { + if (_leafambientindex == null) + { + lump_t lump = SetLump(52); + if (lump.filelen == 0 || lump.filelen % 4 != 0) //This lump is not for ... this + return null; + int count = GetLumpCount(lump, 4); + _leafambientindex = new dleafambientindex_t[count]; + for (int d = 0; d < count; d++) + { + _leafambientindex[d] = new dleafambientindex_t + { + ambientSampleCount = BR.ReadUInt16(), + firstAmbientSample = BR.ReadUInt16() + }; + } + } + return _leafambientindex; + } + } + #endregion + #endregion + + #region Lump #53: Lighting (HDR) + private ColorRGBExp32[] _lightinghdr; + /// + /// Lump #53. Version 1. + /// Purpose: lightmap colors / shadows. + /// Also: Check lump #8 for LDR lighting. + /// + public ColorRGBExp32[] LightingHDR + { + get + { + if (_lightinghdr == null) + { + lump_t lump = SetLump(53); + int count = GetLumpCount(lump, 4); + _lightinghdr = new ColorRGBExp32[count]; + for (int f = 0; f < count; f++) + { + _lightinghdr[f] = BR.ReadColorRGBExp32(); + } + } + return _lightinghdr; + } + } + #endregion + + #region Lump #54: World lights (HDR) + private object _worldlightshdr; + /// + /// Lump #54. Version 0/1. + /// Purpose: Contains info about static lights (NOT LIGHTMAPS). + /// Usage (depending on version): (dworldlightV?_t[])bsp.WorldLightsHDR. + /// Also: Check lump #15 for LDR world lights. + /// + public object WorldLightsHDR + { + get + { + if (_worldlightshdr == null) + { + lump_t lump = SetLump(54); + int count; + switch (lump.version) + { + case 0: + count = GetLumpCount(lump, 88); + dworldlightV0_t[] _wl_0 = new dworldlightV0_t[count]; + for (int wl = 0; wl < count; wl++) + { + _wl_0[wl] = new dworldlightV0_t + { + origin = BR.ReadVector(), + intensity = BR.ReadVector(), + normal = BR.ReadVector(), + cluster = BR.ReadInt32(), + type = (emittype_t)BR.ReadUInt32(), + style = BR.ReadInt32(), + stopdot = BR.ReadSingle(), + stopdot2 = BR.ReadSingle(), + exponent = BR.ReadSingle(), + radius = BR.ReadSingle(), + constant_attn = BR.ReadSingle(), + linear_attn = BR.ReadSingle(), + quadratic_attn = BR.ReadSingle(), + flags = BR.ReadInt32(), + texinfo = BR.ReadInt32(), + owner = BR.ReadInt32() + }; + } + _worldlightshdr = _wl_0; + break; + case 1: + count = GetLumpCount(lump, 100); + dworldlightV1_t[] _wl_1 = new dworldlightV1_t[count]; + for (int wl = 0; wl < count; wl++) + { + _wl_1[wl] = new dworldlightV1_t + { + origin = BR.ReadVector(), + intensity = BR.ReadVector(), + normal = BR.ReadVector(), + shadow_cast_offset = BR.ReadVector(), + cluster = BR.ReadInt32(), + type = (emittype_t)BR.ReadUInt32(), + style = BR.ReadInt32(), + stopdot = BR.ReadSingle(), + stopdot2 = BR.ReadSingle(), + exponent = BR.ReadSingle(), + radius = BR.ReadSingle(), + constant_attn = BR.ReadSingle(), + linear_attn = BR.ReadSingle(), + quadratic_attn = BR.ReadSingle(), + flags = BR.ReadInt32(), + texinfo = BR.ReadInt32(), + owner = BR.ReadInt32() + }; + } + _worldlightshdr = _wl_1; + break; + default: + throw new NotImplementedException(); + } + + } + return _worldlightshdr; + } + } + #endregion + + #region Lump #55: Per-leaf ambient lighting (HDR) (LEAF_AMBIENT_LIGHTING_HDR) + private dleafambientlighting_t[] _leafambientlightinghdr; + /// + /// Lump #55. + /// Purpose: Stores volumetric ambient lighting information for each leaf. + /// Also: Check lump #56 for LDR ambient lighting. + /// + public dleafambientlighting_t[] LeafAmbientLightingHDR + { + get + { + if (_leafambientlightinghdr == null) + { + lump_t lump = SetLump(55); + int count = GetLumpCount(lump, 28); + _leafambientlightinghdr = new dleafambientlighting_t[count]; + for (int l = 0; l < count; l++) + { + _leafambientlightinghdr[l] = new dleafambientlighting_t + { + cube = BR.ReadCompressedLightCube(), + x = BR.ReadByte(), + y = BR.ReadByte(), + z = BR.ReadByte(), + pad = BR.ReadByte() + }; + } + } + return _leafambientlightinghdr; + } + } + #endregion + + #region Lump #56: Per-leaf ambient lighting (LDR) (LEAF_AMBIENT_LIGHTING) + private dleafambientlighting_t[] _leafambientlighting; + /// + /// Lump #56. + /// Purpose: Stores volumetric ambient lighting information for each leaf. + /// Also: Check lump #55 for HDR ambient lighting. + /// + public dleafambientlighting_t[] LeafAmbientLighting + { + get + { + if (_leafambientlighting == null) + { + lump_t lump = SetLump(56); + int count = GetLumpCount(lump, 28); + _leafambientlighting = new dleafambientlighting_t[count]; + for (int l = 0; l < count; l++) + { + _leafambientlighting[l] = new dleafambientlighting_t + { + cube = BR.ReadCompressedLightCube(), + x = BR.ReadByte(), + y = BR.ReadByte(), + z = BR.ReadByte(), + pad = BR.ReadByte() + }; + } + } + return _leafambientlighting; + } + } + #endregion + + #region Lump #57: XZIP PAK file (for XBOX) - not implemented: can't find structs for this lump (mb it's a byte array) + private object _xzippakfile; + /// + /// Lump #57. + /// Purpose: "XZip version of pak file for Xbox. Deprecated.", from Valve Dev Wiki. + /// + public object XZIPPAKFile + { + get + { + if (_xzippakfile == null) + { + //lump_t lump = SetLump(57); + //int count = GetLumpCount(lump, 28); + //_xzippakfile = new ...[count]; + throw new NotImplementedException(); + } + return _xzippakfile; + } + } + #endregion + + #region Lump #58: Faces (HDR) + private dface_t[] _faceshdr; + /// + /// Lump #58. Version 1. + /// Purpose: datas for rendering. + /// Also: Check lump #7 for LDR faces. + /// + public dface_t[] FacesHDR + { + get + { + if (_faceshdr == null) + { + lump_t lump = SetLump(58); + int count = GetLumpCount(lump, 56); + _faceshdr = new dface_t[count]; + for (int f = 0; f < count; f++) + { + _faceshdr[f] = new dface_t + { + planenum = BR.ReadUInt16(), + side = BR.ReadByte(), + onNode = BR.ReadByte(), + firstedge = BR.ReadInt32(), + numedges = BR.ReadInt16(), + texinfo = BR.ReadInt16(), + dispinfo = BR.ReadInt16(), + surfaceFogVolumeID = BR.ReadInt16(), + styles = BR.ReadBytes(4), + lightofs = BR.ReadInt32(), + area = BR.ReadSingle(), + m_LightmapTextureMinsInLuxels = BR.ReadVector2Int(), + m_LightmapTextureSizeInLuxels = BR.ReadVector2Int(), + origFace = BR.ReadInt32(), + m_NumPrims = BR.ReadUInt16(), + firstPrimID = BR.ReadUInt16(), + smoothingGroups = BR.ReadUInt32() + }; + } + } + return _faceshdr; + } + } + #endregion + + #region Lump #59: Map flags + private dflagslump_t _mapflags; + private bool __mapflags; + /// + /// Lump #59. + /// Purpose: Map compilation flags. + /// + public dflagslump_t MapFlags + { + get + { + if (!__mapflags) + { + lump_t lump = SetLump(59); + _mapflags = new dflagslump_t + { + m_LevelFlags = BR.ReadUInt32() + }; + + __mapflags = true; + } + return _mapflags; + } + } + #endregion + + #region Lump #60: Overlay fades + private doverlayfade_t[] _overlayfades; + /// + /// Lump #60. + /// Purpose: [not sure] fade distances for overlays? + /// + public doverlayfade_t[] OverlayFades + { + get + { + if (_overlayfades == null) + { + lump_t lump = SetLump(60); + int count = GetLumpCount(lump, 8); + _overlayfades = new doverlayfade_t[count]; + for (int of = 0; of < count; of++) + { + _overlayfades[of] = new doverlayfade_t + { + flFadeDistMinSq = BR.ReadSingle(), + flFadeDistMaxSq = BR.ReadSingle() + }; + } + } + return _overlayfades; + } + } + #endregion + + //not gonna try to do 61-63 lumps because i can't find any structs in google/github. Valve's secret? + + #endregion + } +} diff --git a/Assets/Editor/SourceBSP.cs.meta b/Assets/Editor/SourceBSP.cs.meta new file mode 100644 index 0000000..ad80498 --- /dev/null +++ b/Assets/Editor/SourceBSP.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 73c1f4408a54c8b45a06ca8f146c8a47 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor/SourceBSPStructs.cs b/Assets/Editor/SourceBSPStructs.cs new file mode 100644 index 0000000..70b119e --- /dev/null +++ b/Assets/Editor/SourceBSPStructs.cs @@ -0,0 +1,1301 @@ +using SourceFormatParser.Common; +using System; +using System.Collections.Generic; + +namespace SourceFormatParser.BSP +{ + /// + /// source2013: public/bspfile.h + /// dheader_t + /// lump_t + /// + public class SourceBSPStructs + { + public const byte HEADER_LUMPS = 64; + public const int IDBSPHEADER = ('P' << 24) + ('S' << 16) + ('B' << 8) + 'V'; + + public const ushort OVERLAY_BSP_FACE_COUNT = 64; + public const int OVERLAY_NUM_RENDER_ORDERS = (1 << OVERLAY_RENDER_ORDER_NUM_BITS); + public const byte OVERLAY_RENDER_ORDER_NUM_BITS = 2; + public const int OVERLAY_RENDER_ORDER_MASK = 0xC000; // top 2 bits set + + public const ushort WATEROVERLAY_BSP_FACE_COUNT = 256; + public const byte WATEROVERLAY_RENDER_ORDER_NUM_BITS = 2; + public const int WATEROVERLAY_NUM_RENDER_ORDERS = (1 << WATEROVERLAY_RENDER_ORDER_NUM_BITS); + public const int WATEROVERLAY_RENDER_ORDER_MASK = 0xC000; // top 2 bits set + + public const int MAX_LIGHTMAPPAGE_WIDTH = 256; + public const int MAX_LIGHTMAPPAGE_HEIGHT = 128; + + + public struct SurfaceFlags + { + public const int SURF_LIGHT = 0x0001; // value will hold the light strength + public const int SURF_SKY2D = 0x0002; // don't draw, indicates we should skylight + draw 2d sky but not draw the 3D skybox + public const int SURF_SKY = 0x0004; // don't draw, but add to skybox + public const int SURF_WARP = 0x0008; // turbulent water warp + public const int SURF_TRANS = 0x0010; + public const int SURF_NOPORTAL = 0x0020; // the surface can not have a portal placed on it + public const int SURF_TRIGGER = 0x0040; // FIXME: This is an xbox hack to work around elimination of trigger surfaces, which breaks occluders + public const int SURF_NODRAW = 0x0080; // don't bother referencing the texture + + public const int SURF_HINT = 0x0100; // make a primary bsp splitter + + public const int SURF_SKIP = 0x0200; // completely ignore, allowing non-closed brushes + public const int SURF_NOLIGHT = 0x0400; // Don't calculate light + public const int SURF_BUMPLIGHT = 0x0800; // calculate three lightmaps for the surface for bumpmapping + public const int SURF_NOSHADOWS = 0x1000; // Don't receive shadows + public const int SURF_NODECALS = 0x2000; // Don't receive decals + public const int SURF_NOCHOP = 0x4000; // Don't subdivide patches on this surface + public const int SURF_HITBOX = 0x8000; // surface is part of a hitbox + } + + + #region enums + [Flags] + public enum MAP_FLAGS + { + /// Map was processed by vrad with -staticproplighting, no hdr data + LVLFLAGS_BAKED_STATIC_PROP_LIGHTING_NONHDR = 0x00000001, + + /// Map was processed by vrad with -staticproplighting, in hdr + LVLFLAGS_BAKED_STATIC_PROP_LIGHTING_HDR = 0x00000002 + } + + [Flags] + public enum LEAF_FLAGS + { + // NOTE: Only 7-bits stored!!! + + /// This leaf has 3D sky in its PVS + LEAF_FLAGS_SKY = 0x01, + + /// This leaf culled away some portals due to radial vis + LEAF_FLAGS_RADIAL = 0x02, + + /// This leaf has 2D sky in its PVS + LEAF_FLAGS_SKY2D = 0x04 + } + + [Flags] + public enum WORLDLIGHT_FLAGS + { + /// This says that the light was put into the per-leaf ambient cubes. + DWL_FLAGS_INAMBIENTCUBE = 0x0001, + + /// This says that the light will cast shadows from entities. + DWL_FLAGS_CASTENTITYSHADOWS = 0x0002 + } + + [Flags] + public enum emittype_t + { + // lights that were used to illuminate the world + + /// 90 degree spotlight + emit_surface, + + /// simple point light source + emit_point, + + /// spotlight with penumbra + emit_spotlight, + + /// directional light with no falloff (surface must trace to SKY texture) + emit_skylight, + + /// linear falloff, non-lambertian + emit_quakelight, + + /// spherical light source with no falloff (surface must trace to SKY texture) + emit_skyambient, + } + + [Flags] + public enum Contents + { + // contents flags are seperate bits + // a given brush can contribute multiple content bits + // multiple brushes can be in a single leaf + + /// No contents + CONTENTS_EMPTY = 0, + + /// an eye is never valid in a solid + CONTENTS_SOLID = 0x1, + + /// translucent, but not watery (glass) + CONTENTS_WINDOW = 0x2, + + CONTENTS_AUX = 0x4, + + /// alpha-tested "grate" textures. Bullets/sight pass through, but solids don't + CONTENTS_GRATE = 0x8, + + CONTENTS_SLIME = 0x10, + CONTENTS_WATER = 0x20, + + /// block AI line of sight + CONTENTS_BLOCKLOS = 0x40, + + /// things that cannot be seen through (may be non-solid though) + CONTENTS_OPAQUE = 0x80, + + CONTENTS_TESTFOGVOLUME = 0x100, + CONTENTS_UNUSED = 0x200, + CONTENTS_UNUSED6 = 0x400, + + /// per team contents used to differentiate collisions between players and objects on different teams + CONTENTS_TEAM1 = 0x800, + /// per team contents used to differentiate collisions between players and objects on different teams + CONTENTS_TEAM2 = 0x1000, + + /// ignore CONTENTS_OPAQUE on surfaces that have SURF_NODRAW + CONTENTS_IGNORE_NODRAW_OPAQUE = 0x2000, + + /// hits entities which are MOVETYPE_PUSH (doors, plats, etc.) + CONTENTS_MOVEABLE = 0x4000, + + /// remaining contents are non-visible, and don't eat brushes + CONTENTS_AREAPORTAL = 0x8000, + + CONTENTS_PLAYERCLIP = 0x10000, + CONTENTS_MONSTERCLIP = 0x20000, + + /// can be added to any other contents, and may be mixed + CONTENTS_CURRENT_0 = 0x40000, + /// can be added to any other contents, and may be mixed + CONTENTS_CURRENT_90 = 0x80000, + /// can be added to any other contents, and may be mixed + CONTENTS_CURRENT_180 = 0x100000, + /// can be added to any other contents, and may be mixed + CONTENTS_CURRENT_270 = 0x200000, + /// can be added to any other contents, and may be mixed + CONTENTS_CURRENT_UP = 0x400000, + /// can be added to any other contents, and may be mixed + CONTENTS_CURRENT_DOWN = 0x800000, + + /// removed before bsping an entity + CONTENTS_ORIGIN = 0x1000000, + + /// should never be on a brush, only in game + CONTENTS_MONSTER = 0x2000000, + + CONTENTS_DEBRIS = 0x4000000, + + /// brushes to be added after vis leafs + CONTENTS_DETAIL = 0x8000000, + + /// auto set if any surface has trans + CONTENTS_TRANSLUCENT = 0x10000000, + + CONTENTS_LADDER = 0x20000000, + + /// use accurate hitboxes on trace + CONTENTS_HITBOX = 0x40000000 + } + + [Flags] + public enum Surfaces + { + // NOTE: These are stored in a short in the engine now. Don't use more than 16 bits + + /// value will hold the light strength + SURF_LIGHT = 0x0001, + + /// don't draw, indicates we should skylight + draw 2d sky but not draw the 3D skybox + SURF_SKY2D = 0x0002, + + /// don't draw, but add to skybox + SURF_SKY = 0x0004, + + /// turbulent water warp + SURF_WARP = 0x0008, + + SURF_TRANS = 0x0010, + + /// the surface can not have a portal placed on it + SURF_NOPORTAL = 0x0020, + + /// FIXME: This is an xbox hack to work around elimination of trigger surfaces, which breaks occluders + SURF_TRIGGER = 0x0040, + + /// don't bother referencing the texture + SURF_NODRAW = 0x0080, + + /// make a primary bsp splitter + SURF_HINT = 0x0100, + + /// completely ignore, allowing non-closed brushes + SURF_SKIP = 0x0200, + + /// Don't calculate light + SURF_NOLIGHT = 0x0400, + + /// calculate three lightmaps for the surface for bumpmapping + SURF_BUMPLIGHT = 0x0800, + + /// Don't receive shadows + SURF_NOSHADOWS = 0x1000, + + /// Don't receive decals + SURF_NODECALS = 0x2000, + + /// Don't subdivide patches on this surface + SURF_NOCHOP = 0x4000, + + /// surface is part of a hitbox + SURF_HITBOX = 0x8000 + } + + [Flags] + public enum NeighborSpan + { + // These denote where one dispinfo fits on another. + // Note: tables are generated based on these indices so make sure to update + // them if these indices are changed. + CORNER_TO_CORNER = 0, + CORNER_TO_MIDPOINT = 1, + MIDPOINT_TO_CORNER = 2 + } + + [Flags] + public enum NeighborOrientation + { + // These define relative orientations of displacement neighbors. + ORIENTATION_CCW_0 = 0, + ORIENTATION_CCW_90 = 1, + ORIENTATION_CCW_180 = 2, + ORIENTATION_CCW_270 = 3 + } + + public enum GAMELUMP_CODES + { + GAMELUMP_DETAIL_PROPS = ('d') << 24 | ('p') << 16 | ('r') << 8 | ('p') << 0, + GAMELUMP_DETAIL_PROP_LIGHTING = ('d') << 24 | ('p') << 16 | ('l') << 8 | ('t') << 0, + GAMELUMP_STATIC_PROPS = ('s') << 24 | ('p') << 16 | ('r') << 8 | ('p') << 0, + GAMELUMP_DETAIL_PROP_LIGHTING_HDR = ('d') << 24 | ('p') << 16 | ('l') << 8 | ('h') << 0, + Unknown + } + + [Flags] + public enum STATICPROP_FLAGS + { + /// automatically computed + STATIC_PROP_FLAG_FADES = 0x1, + /// automatically computed + STATIC_PROP_USE_LIGHTING_ORIGIN = 0x2, + /// automatically computed; computed at run time based on dx level + STATIC_PROP_NO_DRAW = 0x4, + + /// set in WC + STATIC_PROP_IGNORE_NORMALS = 0x8, + /// set in WC + STATIC_PROP_NO_SHADOW = 0x10, + /// set in WC + STATIC_PROP_UNUSED = 0x20, + + /// in vrad, compute lighting at lighting origin, not for each vertex + STATIC_PROP_NO_PER_VERTEX_LIGHTING = 0x40, + + /// disable self shadowing in vrad + STATIC_PROP_NO_SELF_SHADOWING = 0x80 + } + + [Flags] + public enum DetailPropType_t + { + DETAIL_PROP_TYPE_MODEL = 0, + DETAIL_PROP_TYPE_SPRITE, + DETAIL_PROP_TYPE_SHAPE_CROSS, + DETAIL_PROP_TYPE_SHAPE_TRI, + } + + [Flags] + public enum dprimitive_type + { + PRIM_TRILIST = 0, + PRIM_TRISTRIP = 1, + } + + [Flags] + public enum DISPTRI_TAGS + { + DISPTRI_TAG_SURFACE = 1 << 0, + DISPTRI_TAG_WALKABLE = 1 << 1, + DISPTRI_TAG_BUILDABLE = 1 << 2, + DISPTRI_FLAG_SURFPROP1 = 1 << 3, + DISPTRI_FLAG_SURFPROP2 = 1 << 4, + DISPTRI_TAG_REMOVE = 1 << 5 + } + #endregion + + #region structs + /// Header. Size: 780 bytes + public struct dheader_t + { + public int ident; + public int version; + public lump_t[] lumps;//[HEADER_LUMPS]; + public int mapRevision; // the map's revision (iteration, version) number (added BSPVERSION 6) + } + + /// Lump info. Size: 12 bytes + public struct lump_t + { + public int fileofs, filelen; + public int version; // default to zero + // this field was char fourCC[4] previously, but was unused, favoring the LUMP IDs above instead. It has been + // repurposed for compression. 0 implies the lump is not compressed. + public int uncompressedSize; // default to zero + + + //additional + public int lumpNum; + } + + /// Plane. Size: 20 bytes + public struct dplane_t + { + // planes (x) and (x)+1 are always opposites + public SourceVector normal; + public float dist; + public int type; // PLANE_X - PLANE_ANYZ ?remove? trivial to regenerate + +#if UNITY + public Plane toPlane() => new Plane(?, ?, ?); +#endif + } + + /// Texture data. Size: 32 bytes + public struct dtexdata_t + { + public SourceVector reflectivity; + public int nameStringTableID; // index into g_StringTable for the texture name + public int width, height; // source image + public int view_width, view_height; // + } + + /// Visibility. Size: ? bytes + public struct dvis_t + { + public int numclusters; + public int[][] bitofs;// bitofs[numclusters=8][2] + + public HashSet[] pvs; //potentially visible set + public HashSet[] pas; //potentially audible set + } + + /// Node. Size: 30 bytes + public struct dnode_t + { + public int planenum; + public int[] children;//[2]; // negative numbers are -(leafs+1), not nodes + public SourceVectorShort mins;//short[3]; // for frustom culling + public SourceVectorShort maxs;//short[3]; + public ushort firstface; + public ushort numfaces; // counting both sides + public short area; // If all leaves below this node are in the same area, then + // this is the area index. If not, this is -1. + + //additional + //public short unused; //is always 0 + } + + /// Texture info. v0. Size: 72 bytes + public struct texinfo_t + { + public SourceVector4[] textureVecsTexelsPerWorldUnits;//[2]; // [s/t][xyz offset] + public SourceVector4[] lightmapVecsLuxelsPerWorldUnits;//[2]; // [s/t][xyz offset] - length is in units of texels/area + public int flags; // miptex flags + overrides + public int texdata; // Pointer to texture name, size, etc. + } + + /// Face. Size: 56 bytes + public struct dface_t + { + public ushort planenum; + public byte side; // faces opposite to the node's plane direction + public byte onNode; // 1 of on node, 0 if in leaf + + public int firstedge; // we must support > 64k edges + public short numedges; + public short texinfo; + // This is a union under the assumption that a fog volume boundary (ie. water surface) + // isn't a displacement map. + // FIXME: These should be made a union with a flags or type field for which one it is + // if we can add more to this. + // union + // { + public short dispinfo; + // This is only for surfaces that are the boundaries of fog volumes + // (ie. water surfaces) + // All of the rest of the surfaces can look at their leaf to find out + // what fog volume they are in. + public short surfaceFogVolumeID; + // }; + + // lighting info + public byte[] styles;//[MAXLIGHTMAPS=4]; + public int lightofs; // start of [numstyles*surfsize] samples + public float area; + + // TODO: make these unsigned chars? + public SourceVector2Int m_LightmapTextureMinsInLuxels; + public SourceVector2Int m_LightmapTextureSizeInLuxels; + + public int origFace; // reference the original face this face was derived from + + // non-polygon primitives (strips and lists) + public ushort m_NumPrims; // Top bit, if set, disables shadows on this surface (this is why there are accessors). + public ushort firstPrimID; + public uint smoothingGroups; + + + public ushort GetNumPrims => (ushort)(m_NumPrims & 0x7FFF); + public void SetNumPrims(ushort nPrims) + { + //Assert((nPrims & 0x8000) == 0); + if ((nPrims & 0x8000) == 0) return; + m_NumPrims = (ushort)(m_NumPrims & ~0x7FFF); + m_NumPrims = (ushort)(m_NumPrims | (nPrims & 0x7FFF)); + } + public bool AreDynamicShadowsEnabled => (m_NumPrims & 0x8000) == 0; + public void SetDynamicShadowsEnabled(bool bEnabled) + { + if (bEnabled) + m_NumPrims = (ushort)(m_NumPrims & ~0x8000); + else + m_NumPrims |= 0x8000; + } + } + + /// Map flags. Size: 4 bytes + public struct dflagslump_t + { + /// + /// use enum MAP_FLAGS + /// + public uint m_LevelFlags; // LVLFLAGS_xxx + + //additional + public MAP_FLAGS[] getFlags => FlagsUtils.getFlags(m_LevelFlags); + + public override string ToString() + { + string s = string.Empty; + foreach (MAP_FLAGS f in getFlags) s += f.ToString() + " | "; + if (s.Length > 3) + s = s.Substring(0, s.Length - 3); + return s; + } + } + + /// Occluder. Size: ? bytes + public struct doccluder_t + { + //struct from valve dev wiki, can't find in source sdk 2013 + public int count; + public object data; //[count]; //"doccluderdataV1_t[]" or "doccluderdataV2_t[]" + public int polyDataCount; + public doccluderpolydata_t[] polyData;//[polyDataCount]; + public int vertexIndexCount; + public int[] vertexIndices;//[vertexIndexCount]; + } + + /// Occluder data. V1. Size: 36 bytes + public struct doccluderdataV1_t + { + public int flags; + public int firstpoly; // index into doccluderpolys + public int polycount; + public SourceVector mins; + public SourceVector maxs; + } + + /// Occluder data. V2. Size: 40 bytes + public struct doccluderdataV2_t + { + public int flags; + public int firstpoly; // index into doccluderpolys + public int polycount; + public SourceVector mins; + public SourceVector maxs; + public int area; + } + + /// Occluder polygons. Size: 12 bytes + public struct doccluderpolydata_t + { + public int firstvertexindex; // index into doccludervertindices + public int vertexcount; + public int planenum; + } + + /// Leaf. V0. Size: 56 bytes + public struct dleafV0_t + { + public int contents; // OR of all brushes (not needed?) + + public short cluster; + + //BEGIN_BITFIELD(bf ); + public short area;//:9; + public short flags;//:7; // Per leaf flags. + //END_BITFIELD(); + + public SourceVectorShort mins;//short[3]; // for frustum culling + public SourceVectorShort maxs;//short[3]; + + public ushort firstleafface; + public ushort numleaffaces; + + public ushort firstleafbrush; + public ushort numleafbrushes; + public short leafWaterDataID; // -1 for not in water + + // Precaculated light info for entities. + public CompressedLightCube m_AmbientLighting; + + //additional + public LEAF_FLAGS[] getFlags => FlagsUtils.getFlags(flags); + } + + /// Leaf. V1. Size: 32 bytes + public struct dleafV1_t + { + public int contents; // OR of all brushes (not needed?) + + public short cluster; + + //BEGIN_BITFIELD(bf ); + public short area;//:9; + public short flags;//:7; // Per leaf flags. + //END_BITFIELD(); + + public SourceVectorShort mins;//short[3]; // for frustum culling + public SourceVectorShort maxs;//short[3]; + + public ushort firstleafface; + public ushort numleaffaces; + + public ushort firstleafbrush; + public ushort numleafbrushes; + public short leafWaterDataID; // -1 for not in water + + // NOTE: removed this for version 1 and moved into separate lump "LUMP_LEAF_AMBIENT_LIGHTING" or "LUMP_LEAF_AMBIENT_LIGHTING_HDR" + // Precaculated light info for entities. + // CompressedLightCube m_AmbientLighting; + + //additional + public LEAF_FLAGS[] getFlags => FlagsUtils.getFlags(flags); + } + + /// Face ID. Size: 2 bytes + public struct dfaceid_t + { + public ushort hammerfaceid; + } + + /// Edge. Size: 4 bytes + public struct dedge_t + { + // note that edge 0 is never used, because negative edge nums are used for + // counterclockwise use of the edge in a face + public SourceVector2Short v;//short[2]; // vertex numbers + } + + /// Model. Size: 48 bytes + public struct dmodel_t + { + public SourceVector mins, maxs; + public SourceVector origin; // for sounds or lights + public int headnode; + public int firstface, numfaces; // submodels just draw faces without walking the bsp tree + } + + /// World light. V0. Size: 88 bytes + public struct dworldlightV0_t + { + public SourceVector origin; + public SourceVector intensity; + public SourceVector normal; // for surfaces and spotlights + public int cluster; + public emittype_t type; // is ushort? + public int style; + public float stopdot; // start of penumbra for emit_spotlight + public float stopdot2; // end of penumbra for emit_spotlight + public float exponent; // + public float radius; // cutoff distance + // falloff for emit_spotlight + emit_point: + // 1 / (constant_attn + linear_attn * dist + quadratic_attn * dist^2) + public float constant_attn; + public float linear_attn; + public float quadratic_attn; + public int flags; // Uses a combination of the DWL_FLAGS_ defines. + public int texinfo; // + public int owner; // entity that this light it relative to + + //additional + public WORLDLIGHT_FLAGS[] getFlags => FlagsUtils.getFlags(flags); + } + + /// World light. V1. Size: 100 bytes + public struct dworldlightV1_t + { + public SourceVector origin; + public SourceVector intensity; + public SourceVector normal; // for surfaces and spotlights + public SourceVector shadow_cast_offset; // gets added to the light origin when this light is used as a shadow caster (only if DWL_FLAGS_CASTENTITYSHADOWS flag is set) + public int cluster; + public emittype_t type; + public int style; + public float stopdot; // start of penumbra for emit_spotlight + public float stopdot2; // end of penumbra for emit_spotlight + public float exponent; // + public float radius; // cutoff distance + // falloff for emit_spotlight + emit_point: + // 1 / (constant_attn + linear_attn * dist + quadratic_attn * dist^2) + public float constant_attn; + public float linear_attn; + public float quadratic_attn; + public int flags; // Uses a combination of the DWL_FLAGS_ defines. + public int texinfo; // + public int owner; // entity that this light it relative to + + //additional + public WORLDLIGHT_FLAGS[] getFlags => FlagsUtils.getFlags(flags); + } + + /// Brush. Size: 12 bytes + public struct dbrush_t + { + public int firstside; + public int numsides; + public int contents; + + //additional + public Contents[] getContents => FlagsUtils.getFlags(contents); + } + + /// Brush side. Size: 8 bytes + public struct dbrushside_t + { + public ushort planenum; // facing out of the leaf + public short texinfo; + public short dispinfo; // displacement info (BSPVERSION 7) + public short bevel; // is the side a bevel plane? (BSPVERSION 7) + } + + /// Area. Size: 8 bytes + public struct darea_t + { + public int numareaportals, firstareaportal; + } + + /// Areaportal. Size: 12 bytes + public struct dareaportal_t + { + // each area has a list of portals that lead into other areas + // when portals are closed, other areas may not be visible or + // hearable even if the vis info says that it should be + public ushort m_PortalKey; // Entities have a key called portalnumber (and in vbsp a variable + // called areaportalnum) which is used + // to bind them to the area portals by comparing with this value. + + public ushort otherarea; // The area this portal looks into. + + public ushort m_FirstClipPortalVert; // Portal geometry. + public ushort m_nClipPortalVerts; + + public int planenum; + } + + /// Portal. Size: 16 bytes + public struct dportal_t + { + public int firstportalvert; + public int numportalverts; + public int planenum; + public ushort[] cluster;//[2]; + } + + /// Prop collision. Size: 8 bytes + public struct dpropcollision_t + { + public int m_nHullCount, m_nHullStart; + } + + /// Cluster. Size: 8 bytes + public struct dcluster_t + { + public int firstportal, numportals; + } + + /// Prop hull. Size: 16 bytes + public struct dprophull_t + { + public int m_nVertCount, m_nVertStart; + public int m_nSurfaceProp; + public uint m_nContents; + }; + + /// Prop hull triangle. Size: 8 bytes + public struct dprophulltris_t + { + public int m_nIndexStart, m_nIndexCount; + } + + /// Displacement. Size: 176 bytes + public struct ddispinfo_t + { + public SourceVector startPosition; // start position used for orientation -- (added BSPVERSION 6) + public int m_iDispVertStart; // Index into LUMP_DISP_VERTS. + public int m_iDispTriStart; // Index into LUMP_DISP_TRIS. + + public int power; // power - indicates size of map (2^power + 1) + public int minTess; // minimum tesselation allowed + public float smoothingAngle; // lighting smoothing angle + public int contents; // surface contents + + public ushort m_iMapFace; // Which map face this displacement comes from. + + public int m_iLightmapAlphaStart; // Index into ddisplightmapalpha. + // The count is m_pParent->lightmapTextureSizeInLuxels[0]*m_pParent->lightmapTextureSizeInLuxels[1]. + + public int m_iLightmapSamplePositionStart; // Index into LUMP_DISP_LIGHTMAP_SAMPLE_POSITIONS. + + //=^=46 bytes=^= + + public CDispNeighbor[] m_EdgeNeighbors;//[4]; // Indexed by NEIGHBOREDGE_ defines. + public CDispCornerNeighbors[] m_CornerNeighbors;//[4]; // Indexed by CORNER_ defines. + + //ALLOWEDVERTS_SIZE = PAD_NUMBER(MAX_DISPVERTS, 32) / 32 + public ulong[] m_AllowedVerts;//[ALLOWEDVERTS_SIZE=10];// This is built based on the layout and sizes of our neighbors + // and tells us which vertices are allowed to be active. + + //additional methods + public int NumVerts => ((1 << (power)) + 1) * ((1 << (power)) + 1); + public int NumTris => ((1 << (power)) * (1 << (power)) * 2); + } + + /// Displacement Subneighbor. Size: 5 bytes + public struct CDispSubNeighbor + { + public ushort m_iNeighbor; // This indexes into ddispinfos. + // 0xFFFF if there is no neighbor here. + + public byte m_NeighborOrientation; // (CCW) rotation of the neighbor wrt this displacement. + + // These use the NeighborSpan type. + public byte m_Span; // Where the neighbor fits onto this side of our displacement. + public byte m_NeighborSpan; // Where we fit onto our neighbor. + + + //additional + public ushort GetNeighborIndex => m_iNeighbor; + public NeighborSpan GetSpan => (NeighborSpan)m_Span; + public NeighborSpan GetNeighborSpan => (NeighborSpan)m_NeighborSpan; + public NeighborOrientation GetNeighborOrientation => (NeighborOrientation)m_NeighborOrientation; + + public bool IsValid => m_iNeighbor != 0xFFFF; + public void SetInvalid() { m_iNeighbor = 0xFFFF; } + } + + /// Displacement Neighbor. Size: 10 bytes + public struct CDispNeighbor + { + // Note: if there is a neighbor that fills the whole side (CORNER_TO_CORNER), + // then it will always be in CDispNeighbor::m_Neighbors[0] + public CDispSubNeighbor[] m_SubNeighbors;//[2]; + + + //additional methods + public void SetInvalid() { m_SubNeighbors[0].SetInvalid(); m_SubNeighbors[1].SetInvalid(); } + + // Returns false if there isn't anything touching this edge. + public bool IsValid => m_SubNeighbors[0].IsValid || m_SubNeighbors[1].IsValid; + } + + /// Displacement Corner Neighbors. Size: 9 bytes + public struct CDispCornerNeighbors + { + public ushort[] m_Neighbors;//[MAX_DISP_CORNER_NEIGHBORS=4]; // indices of neighbors. + public byte m_nNeighbors; + + //additional methods + public void SetInvalid() { m_nNeighbors = 0; } + } + + /// Displacement Physics. Size: 2 bytes + public struct dphysdisp_t + { + // contains the binary blob for each displacement surface's virtual hull + public ushort numDisplacements; + public ushort[] dataSize;//[numDisplacements]; + } + + /// Displacement Physics. Size: 8 bytes + public struct dphysmodel_t + { + public int modelIndex; + public int dataSize; + public int keydataSize; + public int solidCount; + + //additional + //public phy solid; + public string keydata; + } + + /// Displacement vertex. Size: 20 bytes + public class CDispVert + { + public SourceVector m_vVector; // Vector field defining displacement volume. + public float m_flDist; // Displacement distances. + public float m_flAlpha; // "per vertex" alpha values. + } + + /// Game lump header. Size: 4 bytes + public struct dgamelumpheader_t + { + public int lumpCount; + + //additional + public dgamelump_t[] lumps; + + //static props + public StaticPropDictLump_t[] staticPropNames; + public StaticPropLeafLump_t[] staticPropLeafs; + /// Usage (depending on lump version): (StaticPropLumpV?_t[])staticProps + public object staticProps; + + //detail props + public DetailObjectDictLump_t[] detailPropNames; + public DetailSpriteDictLump_t[] detailPropSprites; + public DetailObjectLump_t[] detailProps; + public DetailPropLightstylesLump_t[] detailPropLighting, detailPropLightingHDR; + } + + /// Game lump info. Size: 20 bytes + public struct dgamelump_t + { + public int id; // This is expected to be a four-CC code ('lump') + public ushort flags; + public ushort version; + public int fileofs; + public int filelen; + + //additional + public GAMELUMP_CODES id_code => (GAMELUMP_CODES)(id); + } + + /// Game lump: Static prop dictionary. Size: 128 bytes + public struct StaticPropDictLump_t + { + public string m_Name;//char[STATIC_PROP_NAME_LENGTH=128]; // model name + } + + /// Game lump: Static prop leaf. Size: 2 bytes + public struct StaticPropLeafLump_t + { + public ushort m_Leaf; + } + + /// Game lump: Static prop. V4. Size: 56 bytes + public struct StaticPropLumpV4_t + { + public SourceVector m_Origin; + public SourceQAngle m_Angles; + public ushort m_PropType; + public ushort m_FirstLeaf; + public ushort m_LeafCount; + public byte m_Solid; + public byte m_Flags; + public int m_Skin; + public float m_FadeMinDist; + public float m_FadeMaxDist; + public SourceVector m_LightingOrigin; + // int m_Lighting; // index into the GAMELUMP_STATIC_PROP_LIGHTING lump + + //additional + public STATICPROP_FLAGS[] getFlags => FlagsUtils.getFlags(m_Flags); + } + + /// Game lump: Static prop. V5. Size: 60 bytes + public struct StaticPropLumpV5_t + { + public SourceVector m_Origin; + public SourceQAngle m_Angles; + public ushort m_PropType; + public ushort m_FirstLeaf; + public ushort m_LeafCount; + public byte m_Solid; + public byte m_Flags; + public int m_Skin; + public float m_FadeMinDist; + public float m_FadeMaxDist; + public SourceVector m_LightingOrigin; + public float m_flForcedFadeScale; + // int m_Lighting; // index into the GAMELUMP_STATIC_PROP_LIGHTING lump + + //additional + public STATICPROP_FLAGS[] getFlags => FlagsUtils.getFlags(m_Flags); + } + + /// Game lump: Static prop. V6. Size: 64 bytes + public struct StaticPropLumpV6_t + { + public SourceVector m_Origin; + public SourceQAngle m_Angles; + public ushort m_PropType; + public ushort m_FirstLeaf; + public ushort m_LeafCount; + public byte m_Solid; + public byte m_Flags; + public int m_Skin; + public float m_FadeMinDist; + public float m_FadeMaxDist; + public SourceVector m_LightingOrigin; + public float m_flForcedFadeScale; + public ushort m_nMinDXLevel; + public ushort m_nMaxDXLevel; + // int m_Lighting; // index into the GAMELUMP_STATIC_PROP_LIGHTING lump + + //additional + public STATICPROP_FLAGS[] getFlags => FlagsUtils.getFlags(m_Flags); + } + + /// Game lump: Static prop. V7. Size: 68 bytes + public struct StaticPropLumpV7_t + { + public SourceVector m_Origin; + public SourceQAngle m_Angles; + public ushort m_PropType; + public ushort m_FirstLeaf; + public ushort m_LeafCount; + public byte m_Solid; + public byte m_Flags; + public int m_Skin; + public float m_FadeMinDist; + public float m_FadeMaxDist; + public SourceVector m_LightingOrigin; + public float m_flForcedFadeScale; + public ushort m_nMinDXLevel; + public ushort m_nMaxDXLevel; + // int m_Lighting; // index into the GAMELUMP_STATIC_PROP_LIGHTING lump + public SourceColor32 m_DiffuseModulation; // per instance color and alpha modulation + + //additional + public STATICPROP_FLAGS[] getFlags => FlagsUtils.getFlags(m_Flags); + } + + /// Game lump: Static prop. V8. Size: 68 bytes + public struct StaticPropLumpV8_t + { + public SourceVector m_Origin; + public SourceQAngle m_Angles; + public ushort m_PropType; + public ushort m_FirstLeaf; + public ushort m_LeafCount; + public byte m_Solid; + public byte m_Flags; + public int m_Skin; + public float m_FadeMinDist; + public float m_FadeMaxDist; + public SourceVector m_LightingOrigin; + public float m_flForcedFadeScale; + public byte m_nMinCPULevel; + public byte m_nMaxCPULevel; + public byte m_nMinGPULevel; + public byte m_nMaxGPULevel; + // int m_Lighting; // index into the GAMELUMP_STATIC_PROP_LIGHTING lump + public SourceColor32 m_DiffuseModulation; // per instance color and alpha modulation + + //additional + public STATICPROP_FLAGS[] getFlags => FlagsUtils.getFlags(m_Flags); + } + + /// Game lump: Static prop. V9. Size: 72 bytes + public struct StaticPropLumpV9_t + { + public SourceVector m_Origin; + public SourceQAngle m_Angles; + public ushort m_PropType; + public ushort m_FirstLeaf; + public ushort m_LeafCount; + public byte m_Solid; + public byte m_Flags; + public int m_Skin; + public float m_FadeMinDist; + public float m_FadeMaxDist; + public SourceVector m_LightingOrigin; + public float m_flForcedFadeScale; + public byte m_nMinCPULevel; + public byte m_nMaxCPULevel; + public byte m_nMinGPULevel; + public byte m_nMaxGPULevel; + // int m_Lighting; // index into the GAMELUMP_STATIC_PROP_LIGHTING lump + public SourceColor32 m_DiffuseModulation; // per instance color and alpha modulation + public int m_bDisableX360; + + //additional + public STATICPROP_FLAGS[] getFlags => FlagsUtils.getFlags(m_Flags); + } + + /// Game lump: Static prop. V10. Size: 76 bytes + public struct StaticPropLumpV10_t + { + public SourceVector m_Origin; + public SourceQAngle m_Angles; + public ushort m_PropType; + public ushort m_FirstLeaf; + public ushort m_LeafCount; + public byte m_Solid; + public byte m_Flags; + public int m_Skin; + public float m_FadeMinDist; + public float m_FadeMaxDist; + public SourceVector m_LightingOrigin; + public float m_flForcedFadeScale; + public byte m_nMinCPULevel; + public byte m_nMaxCPULevel; + public byte m_nMinGPULevel; + public byte m_nMaxGPULevel; + // int m_Lighting; // index into the GAMELUMP_STATIC_PROP_LIGHTING lump + public SourceColor32 m_DiffuseModulation; // per instance color and alpha modulation + public int m_bDisableX360; //??? + public uint m_FlagsEx; //??? + + //additional + public STATICPROP_FLAGS[] getFlags => FlagsUtils.getFlags(m_Flags); + //public STATICPROP_FLAGSEX[] getFlagsEx => FlagsUtils.getFlags(FlagsEx); + } + + /// Game lump: Static prop. V11. Size: 76 bytes + public struct StaticPropLumpV11_t + { + public SourceVector m_Origin; + public SourceQAngle m_Angles; + public ushort m_PropType; + public ushort m_FirstLeaf; + public ushort m_LeafCount; + public byte m_Solid; + public byte m_Flags; + public int m_Skin; + public float m_FadeMinDist; + public float m_FadeMaxDist; + public SourceVector m_LightingOrigin; + public float m_flForcedFadeScale; + public byte m_nMinCPULevel; + public byte m_nMaxCPULevel; + public byte m_nMinGPULevel; + public byte m_nMaxGPULevel; + // int m_Lighting; // index into the GAMELUMP_STATIC_PROP_LIGHTING lump + public SourceColor32 m_DiffuseModulation; // per instance color and alpha modulation + public int m_bDisableX360; //??? + public uint m_FlagsEx; //??? + public float m_UniformScale; + + //additional + public STATICPROP_FLAGS[] getFlags => FlagsUtils.getFlags(m_Flags); + //public STATICPROP_FLAGSEX[] getFlagsEx => FlagsUtils.getFlags(FlagsEx); + } + + /// Game lump: Detail prop dictionary. Size: 128 bytes + public struct DetailObjectDictLump_t + { + // Model index when using studiomdls for detail props + public string m_Name; //char[DETAIL_NAME_LENGTH=128]; // model name + } + + /// Game lump: Detail prop sprite info. Size: 8 bytes + public struct DetailSpriteDictLump_t + { + // Information about the sprite to render + + // NOTE: All detail prop sprites must lie in the material detail/detailsprites + public SourceVector2 m_UL; // Coordinate of upper left + public SourceVector2 m_LR; // Coordinate of lower right + public SourceVector2 m_TexUL; // Texcoords of upper left + public SourceVector2 m_TexLR; // Texcoords of lower left + } + + /// Game lump: Detail prop. Size: 52 bytes + public struct DetailObjectLump_t + { + public SourceVector m_Origin; + public SourceQAngle m_Angles; + public ushort m_DetailModel; // either index into DetailObjectDictLump_t or DetailPropSpriteLump_t + public ushort m_Leaf; + public ColorRGBExp32 m_Lighting; + public uint m_LightStyles; + public byte m_LightStyleCount; + public byte m_SwayAmount; // how much do the details sway + public byte m_ShapeAngle; // angle param for shaped sprites + public byte m_ShapeSize; // size param for shaped sprites + public byte m_Orientation; // See DetailPropOrientation_t + public byte[] m_Padding2;//[3]; // FIXME: Remove when we rev the detail lump again.. + public byte m_Type; // See DetailPropType_t + public byte[] m_Padding3;//[3]; // FIXME: Remove when we rev the detail lump again.. + public float m_flScale; // For sprites only currently + + //additional + public DetailPropType_t[] getDetailPropType => FlagsUtils.getFlags(m_Type); + } + + /// Game lump: Detail prop lighting info. Size: 5 bytes + public struct DetailPropLightstylesLump_t + { + public ColorRGBExp32 m_Lighting; + public byte m_Style; + } + + /// Water leaf. Size: 10 bytes + public struct dleafwaterdata_t + { + public float surfaceZ, minZ; + public short surfaceTexInfoID; + public short unknown; // is always zero? + // mb is a part of surfaceTexInfoID (that means it can be int32) + } + + /// Primitive. Size: 9 bytes + public struct dprimitive_t + { + public byte type; + public ushort firstIndex; + public ushort indexCount; + public ushort firstVert; + public ushort vertCount; + + //additional + public dprimitive_type[] getPrimType => FlagsUtils.getFlags(type); + } + + /// Cubemap. Size: 16 bytes + public struct dcubemapsample_t + { + public int[] origin;//[3] // position of light snapped to the nearest integer + // the filename for the vtf file is derived from the position + public byte size; // 0 - default + // otherwise, 1<<(size-1) + } + + /// Overlay. Size: 352 bytes + public struct doverlay_t + { + public int nId; + public short nTexInfo; + + public ushort m_nFaceCountAndRenderOrder; + + public int[] aFaces;//[OVERLAY_BSP_FACE_COUNT=64]; + public float[] flU;//[2]; + public float[] flV;//[2]; + public SourceVector[] vecUVPoints;//[4]; + public SourceVector vecOrigin; + public SourceVector vecBasisNormal; + + // Accessors.. + public void SetFaceCount(ushort count) + { + m_nFaceCountAndRenderOrder &= OVERLAY_RENDER_ORDER_MASK; + m_nFaceCountAndRenderOrder |= (ushort)(count & ~OVERLAY_RENDER_ORDER_MASK); + } + public ushort GetFaceCount() => (ushort)(m_nFaceCountAndRenderOrder & ~OVERLAY_RENDER_ORDER_MASK); + + public void SetRenderOrder(ushort order) + { + //m_nFaceCountAndRenderOrder &= ~OVERLAY_RENDER_ORDER_MASK; + //m_nFaceCountAndRenderOrder |= (ushort)(order << (16 - OVERLAY_RENDER_ORDER_NUM_BITS)); // leave 2 bits for render order. + throw new NotImplementedException(); + } + public ushort GetRenderOrder() => (ushort)(m_nFaceCountAndRenderOrder >> (16 - OVERLAY_RENDER_ORDER_NUM_BITS)); + } + + /// Displacement triangle. Size: 2 bytes + public struct CDispTri + { + public ushort m_uiTags; // Displacement triangle tags. + + //additional + public DISPTRI_TAGS[] getFlags => FlagsUtils.getFlags(m_uiTags); + } + + /// Water overlay. Size: 1120 bytes + public struct dwateroverlay_t + { + //i know its similar to doverlay_t, but it has different limitations. from antim. + public int nId; + public short nTexInfo; + + public ushort m_nFaceCountAndRenderOrder; + public int[] aFaces;//[WATEROVERLAY_BSP_FACE_COUNT=256]; + public float[] flU;//[2]; + public float[] flV;//[2]; + public SourceVector[] vecUVPoints;//[4]; + public SourceVector vecOrigin; + public SourceVector vecBasisNormal; + + // Accessors.. + public void SetFaceCount(ushort count) + { + m_nFaceCountAndRenderOrder &= WATEROVERLAY_RENDER_ORDER_MASK; + m_nFaceCountAndRenderOrder |= (ushort)(count & ~WATEROVERLAY_RENDER_ORDER_MASK); + } + public ushort GetFaceCount() => (ushort)(m_nFaceCountAndRenderOrder & ~WATEROVERLAY_RENDER_ORDER_MASK); + public void SetRenderOrder(ushort order) + { + //m_nFaceCountAndRenderOrder &= ~WATEROVERLAY_RENDER_ORDER_MASK; + //m_nFaceCountAndRenderOrder |= (order << (16 - WATEROVERLAY_RENDER_ORDER_NUM_BITS)); // leave 2 bits for render order. + throw new NotImplementedException(); + } + public ushort GetRenderOrder() => (ushort)(m_nFaceCountAndRenderOrder >> (16 - WATEROVERLAY_RENDER_ORDER_NUM_BITS)); + } + + /// Lightmap page. Size: 33792 bytes + public struct dlightmappage_t + { + public byte[] data; //[MAX_LIGHTMAPPAGE_WIDTH * MAX_LIGHTMAPPAGE_HEIGHT] + public ColorRGBExp32[] palette; //[256] + //originally 'palette' was an byte array and had [256*4] len + } + + /// Ambient lighting samples. Size: 4 bytes + public struct dleafambientindex_t + { + public ushort ambientSampleCount; + public ushort firstAmbientSample; + } + + /// Lightmap page info. Size: 8 bytes + public struct dlightmappageinfo_t + { + public byte page; // lightmap page [0..?] + public byte[] offset;//[2]; // offset into page (s,t) + public byte pad; // unused + public ColorRGBExp32 avgColor; // average used for runtime lighting calcs + } + + /// Ambient lighting sample. Size: 28 bytes + public struct dleafambientlighting_t + { + // each leaf contains N samples of the ambient lighting + // each sample contains a cube of ambient light projected on to each axis + // and a sampling position encoded as a 0.8 fraction (mins=0,maxs=255) of the leaf's bounding box + public CompressedLightCube cube; + public byte x; // fixed point fraction of leaf bounds + public byte y; // fixed point fraction of leaf bounds + public byte z; // fixed point fraction of leaf bounds + public byte pad; // unused + } + + /// Overlay fade. Size: 8 bytes + public struct doverlayfade_t + { + public float flFadeDistMinSq, flFadeDistMaxSq; + } + #endregion + } +} diff --git a/Assets/Editor/SourceBSPStructs.cs.meta b/Assets/Editor/SourceBSPStructs.cs.meta new file mode 100644 index 0000000..731975d --- /dev/null +++ b/Assets/Editor/SourceBSPStructs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b876072cd3c0f5349b4314fd16b1fc52 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor/SourceCommon.meta b/Assets/Editor/SourceCommon.meta new file mode 100644 index 0000000..94c8b99 --- /dev/null +++ b/Assets/Editor/SourceCommon.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b446da09838afa44097a99b1bff8acee +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor/SourceCommon/ColorConversion.cs b/Assets/Editor/SourceCommon/ColorConversion.cs new file mode 100644 index 0000000..0ce8999 --- /dev/null +++ b/Assets/Editor/SourceCommon/ColorConversion.cs @@ -0,0 +1,89 @@ +namespace SourceFormatParser.Common +{ + /// + /// mathlib/color_conversion.cpp. Not full ofc. + /// + public static class ColorConversion + { + // This is aligned to 16-byte boundaries so that we can load it + // onto SIMD registers easily if needed (used by SSE version of lightmaps) + // TODO: move this into the one DLL that actually uses it, instead of statically + // linking it everywhere via mathlib. + private static float[] power2_n = new float[256] // 2**(index - 128) / 255 + { + 1.152445441982634800E-041f, 2.304890883965269600E-041f, 4.609781767930539200E-041f, 9.219563535861078400E-041f, + 1.843912707172215700E-040f, 3.687825414344431300E-040f, 7.375650828688862700E-040f, 1.475130165737772500E-039f, + 2.950260331475545100E-039f, 5.900520662951090200E-039f, 1.180104132590218000E-038f, 2.360208265180436100E-038f, + 4.720416530360872100E-038f, 9.440833060721744200E-038f, 1.888166612144348800E-037f, 3.776333224288697700E-037f, + 7.552666448577395400E-037f, 1.510533289715479100E-036f, 3.021066579430958200E-036f, 6.042133158861916300E-036f, + 1.208426631772383300E-035f, 2.416853263544766500E-035f, 4.833706527089533100E-035f, 9.667413054179066100E-035f, + 1.933482610835813200E-034f, 3.866965221671626400E-034f, 7.733930443343252900E-034f, 1.546786088668650600E-033f, + 3.093572177337301200E-033f, 6.187144354674602300E-033f, 1.237428870934920500E-032f, 2.474857741869840900E-032f, + 4.949715483739681800E-032f, 9.899430967479363700E-032f, 1.979886193495872700E-031f, 3.959772386991745500E-031f, + 7.919544773983491000E-031f, 1.583908954796698200E-030f, 3.167817909593396400E-030f, 6.335635819186792800E-030f, + 1.267127163837358600E-029f, 2.534254327674717100E-029f, 5.068508655349434200E-029f, 1.013701731069886800E-028f, + 2.027403462139773700E-028f, 4.054806924279547400E-028f, 8.109613848559094700E-028f, 1.621922769711818900E-027f, + 3.243845539423637900E-027f, 6.487691078847275800E-027f, 1.297538215769455200E-026f, 2.595076431538910300E-026f, + 5.190152863077820600E-026f, 1.038030572615564100E-025f, 2.076061145231128300E-025f, 4.152122290462256500E-025f, + 8.304244580924513000E-025f, 1.660848916184902600E-024f, 3.321697832369805200E-024f, 6.643395664739610400E-024f, + 1.328679132947922100E-023f, 2.657358265895844200E-023f, 5.314716531791688300E-023f, 1.062943306358337700E-022f, + 2.125886612716675300E-022f, 4.251773225433350700E-022f, 8.503546450866701300E-022f, 1.700709290173340300E-021f, + 3.401418580346680500E-021f, 6.802837160693361100E-021f, 1.360567432138672200E-020f, 2.721134864277344400E-020f, + 5.442269728554688800E-020f, 1.088453945710937800E-019f, 2.176907891421875500E-019f, 4.353815782843751100E-019f, + 8.707631565687502200E-019f, 1.741526313137500400E-018f, 3.483052626275000900E-018f, 6.966105252550001700E-018f, + 1.393221050510000300E-017f, 2.786442101020000700E-017f, 5.572884202040001400E-017f, 1.114576840408000300E-016f, + 2.229153680816000600E-016f, 4.458307361632001100E-016f, 8.916614723264002200E-016f, 1.783322944652800400E-015f, + 3.566645889305600900E-015f, 7.133291778611201800E-015f, 1.426658355722240400E-014f, 2.853316711444480700E-014f, + 5.706633422888961400E-014f, 1.141326684577792300E-013f, 2.282653369155584600E-013f, 4.565306738311169100E-013f, + 9.130613476622338300E-013f, 1.826122695324467700E-012f, 3.652245390648935300E-012f, 7.304490781297870600E-012f, + 1.460898156259574100E-011f, 2.921796312519148200E-011f, 5.843592625038296500E-011f, 1.168718525007659300E-010f, + 2.337437050015318600E-010f, 4.674874100030637200E-010f, 9.349748200061274400E-010f, 1.869949640012254900E-009f, + 3.739899280024509800E-009f, 7.479798560049019500E-009f, 1.495959712009803900E-008f, 2.991919424019607800E-008f, + 5.983838848039215600E-008f, 1.196767769607843100E-007f, 2.393535539215686200E-007f, 4.787071078431372500E-007f, + 9.574142156862745000E-007f, 1.914828431372549000E-006f, 3.829656862745098000E-006f, 7.659313725490196000E-006f, + 1.531862745098039200E-005f, 3.063725490196078400E-005f, 6.127450980392156800E-005f, 1.225490196078431400E-004f, + 2.450980392156862700E-004f, 4.901960784313725400E-004f, 9.803921568627450800E-004f, 1.960784313725490200E-003f, + 3.921568627450980300E-003f, 7.843137254901960700E-003f, 1.568627450980392100E-002f, 3.137254901960784300E-002f, + 6.274509803921568500E-002f, 1.254901960784313700E-001f, 2.509803921568627400E-001f, 5.019607843137254800E-001f, + 1.003921568627451000E+000f, 2.007843137254901900E+000f, 4.015686274509803900E+000f, 8.031372549019607700E+000f, + 1.606274509803921500E+001f, 3.212549019607843100E+001f, 6.425098039215686200E+001f, 1.285019607843137200E+002f, + 2.570039215686274500E+002f, 5.140078431372548900E+002f, 1.028015686274509800E+003f, 2.056031372549019600E+003f, + 4.112062745098039200E+003f, 8.224125490196078300E+003f, 1.644825098039215700E+004f, 3.289650196078431300E+004f, + 6.579300392156862700E+004f, 1.315860078431372500E+005f, 2.631720156862745100E+005f, 5.263440313725490100E+005f, + 1.052688062745098000E+006f, 2.105376125490196000E+006f, 4.210752250980392100E+006f, 8.421504501960784200E+006f, + 1.684300900392156800E+007f, 3.368601800784313700E+007f, 6.737203601568627400E+007f, 1.347440720313725500E+008f, + 2.694881440627450900E+008f, 5.389762881254901900E+008f, 1.077952576250980400E+009f, 2.155905152501960800E+009f, + 4.311810305003921500E+009f, 8.623620610007843000E+009f, 1.724724122001568600E+010f, 3.449448244003137200E+010f, + 6.898896488006274400E+010f, 1.379779297601254900E+011f, 2.759558595202509800E+011f, 5.519117190405019500E+011f, + 1.103823438081003900E+012f, 2.207646876162007800E+012f, 4.415293752324015600E+012f, 8.830587504648031200E+012f, + 1.766117500929606200E+013f, 3.532235001859212500E+013f, 7.064470003718425000E+013f, 1.412894000743685000E+014f, + 2.825788001487370000E+014f, 5.651576002974740000E+014f, 1.130315200594948000E+015f, 2.260630401189896000E+015f, + 4.521260802379792000E+015f, 9.042521604759584000E+015f, 1.808504320951916800E+016f, 3.617008641903833600E+016f, + 7.234017283807667200E+016f, 1.446803456761533400E+017f, 2.893606913523066900E+017f, 5.787213827046133800E+017f, + 1.157442765409226800E+018f, 2.314885530818453500E+018f, 4.629771061636907000E+018f, 9.259542123273814000E+018f, + 1.851908424654762800E+019f, 3.703816849309525600E+019f, 7.407633698619051200E+019f, 1.481526739723810200E+020f, + 2.963053479447620500E+020f, 5.926106958895241000E+020f, 1.185221391779048200E+021f, 2.370442783558096400E+021f, + 4.740885567116192800E+021f, 9.481771134232385600E+021f, 1.896354226846477100E+022f, 3.792708453692954200E+022f, + 7.585416907385908400E+022f, 1.517083381477181700E+023f, 3.034166762954363400E+023f, 6.068333525908726800E+023f, + 1.213666705181745400E+024f, 2.427333410363490700E+024f, 4.854666820726981400E+024f, 9.709333641453962800E+024f, + 1.941866728290792600E+025f, 3.883733456581585100E+025f, 7.767466913163170200E+025f, 1.553493382632634000E+026f, + 3.106986765265268100E+026f, 6.213973530530536200E+026f, 1.242794706106107200E+027f, 2.485589412212214500E+027f, + 4.971178824424429000E+027f, 9.942357648848857900E+027f, 1.988471529769771600E+028f, 3.976943059539543200E+028f, + 7.953886119079086300E+028f, 1.590777223815817300E+029f, 3.181554447631634500E+029f, 6.363108895263269100E+029f, + 1.272621779052653800E+030f, 2.545243558105307600E+030f, 5.090487116210615300E+030f, 1.018097423242123100E+031f, + 2.036194846484246100E+031f, 4.072389692968492200E+031f, 8.144779385936984400E+031f, 1.628955877187396900E+032f, + 3.257911754374793800E+032f, 6.515823508749587500E+032f, 1.303164701749917500E+033f, 2.606329403499835000E+033f, + 5.212658806999670000E+033f, 1.042531761399934000E+034f, 2.085063522799868000E+034f, 4.170127045599736000E+034f, + 8.340254091199472000E+034f, 1.668050818239894400E+035f, 3.336101636479788800E+035f, 6.672203272959577600E+035f +}; + + // convert texture to linear 0..1 value + public static float TexLightToLinear(int c, int exponent) + { + //extern float power2_n[256]; + //Assert(exponent >= -128 && exponent <= 127 ); + if (exponent >= -128 && exponent <= 127) return float.NaN; + return (float)c * power2_n[exponent + 128]; + } + } +} diff --git a/Assets/Editor/SourceCommon/ColorConversion.cs.meta b/Assets/Editor/SourceCommon/ColorConversion.cs.meta new file mode 100644 index 0000000..eb7fee5 --- /dev/null +++ b/Assets/Editor/SourceCommon/ColorConversion.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c4dc652aadc78094298f72dd7ce75428 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor/SourceCommon/ColorRGBExp32.cs b/Assets/Editor/SourceCommon/ColorRGBExp32.cs new file mode 100644 index 0000000..f44a727 --- /dev/null +++ b/Assets/Editor/SourceCommon/ColorRGBExp32.cs @@ -0,0 +1,37 @@ +using System; + +namespace SourceFormatParser.Common +{ + /// + /// compressed color format. + /// Size: 4 bytes + /// + public struct ColorRGBExp32 + { + public byte r, g, b, exponent; + + public ColorRGBExp32(byte r, byte g, byte b, byte exponent) + { + this.r = r; + this.g = g; + this.b = b; + this.exponent = exponent; + } + + /// + /// Not implemented. mathlib/color_conversion.cpp - "VectorToColorRGBExp32" method if you want to. + /// + public static ColorRGBExp32 FromVector(SourceVector vin) => throw new NotImplementedException(); + public SourceVector ToVector() + { + // FIXME: Why is there a factor of 255 built into this? + return new SourceVector( + 255.0f * ColorConversion.TexLightToLinear(r, exponent), + 255.0f * ColorConversion.TexLightToLinear(g, exponent), + 255.0f * ColorConversion.TexLightToLinear(b, exponent) + ); + } + + public override string ToString() => $"{{{r}; {g}; {b}; exp={exponent}}}"; + } +} diff --git a/Assets/Editor/SourceCommon/ColorRGBExp32.cs.meta b/Assets/Editor/SourceCommon/ColorRGBExp32.cs.meta new file mode 100644 index 0000000..bb0f0e3 --- /dev/null +++ b/Assets/Editor/SourceCommon/ColorRGBExp32.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1ed879c18da020a448afe6576e15f627 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor/SourceCommon/CompressedLightCube.cs b/Assets/Editor/SourceCommon/CompressedLightCube.cs new file mode 100644 index 0000000..1908685 --- /dev/null +++ b/Assets/Editor/SourceCommon/CompressedLightCube.cs @@ -0,0 +1,11 @@ +namespace SourceFormatParser.Common +{ + /// + /// compressed light cube (6 sides = 6 colors). + /// Size: 24 bytes + /// + public struct CompressedLightCube + { + public ColorRGBExp32[] m_Color; //[6] + } +} diff --git a/Assets/Editor/SourceCommon/CompressedLightCube.cs.meta b/Assets/Editor/SourceCommon/CompressedLightCube.cs.meta new file mode 100644 index 0000000..fe59470 --- /dev/null +++ b/Assets/Editor/SourceCommon/CompressedLightCube.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6f0f3d55aab418b49872ce22a291ea26 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor/SourceCommon/DebugLog.cs b/Assets/Editor/SourceCommon/DebugLog.cs new file mode 100644 index 0000000..3e9dc4d --- /dev/null +++ b/Assets/Editor/SourceCommon/DebugLog.cs @@ -0,0 +1,14 @@ +namespace SourceFormatParser.Common +{ + public static class DebugLog + { + public static void Write(object obj) + { +#if UNITY + UnityEngine.Debug.Log(obj); +#else + System.Console.WriteLine(obj); +#endif + } + } +} diff --git a/Assets/Editor/SourceCommon/DebugLog.cs.meta b/Assets/Editor/SourceCommon/DebugLog.cs.meta new file mode 100644 index 0000000..3b764f3 --- /dev/null +++ b/Assets/Editor/SourceCommon/DebugLog.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9ca1a75353e50544d89d5c910794abea +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor/SourceCommon/Define.cs b/Assets/Editor/SourceCommon/Define.cs new file mode 100644 index 0000000..3ecaece --- /dev/null +++ b/Assets/Editor/SourceCommon/Define.cs @@ -0,0 +1,4 @@ +//not tested. +#if (UNITY_5_1 || UNITY_5_2 || UNITY_5_3_OR_NEWER) +#define UNITY +#endif \ No newline at end of file diff --git a/Assets/Editor/SourceCommon/Define.cs.meta b/Assets/Editor/SourceCommon/Define.cs.meta new file mode 100644 index 0000000..0cec028 --- /dev/null +++ b/Assets/Editor/SourceCommon/Define.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e368deb37419a294aba5cc8c1a97de60 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor/SourceCommon/FlagsUtils.cs b/Assets/Editor/SourceCommon/FlagsUtils.cs new file mode 100644 index 0000000..c3ade38 --- /dev/null +++ b/Assets/Editor/SourceCommon/FlagsUtils.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; + +namespace SourceFormatParser.Common +{ + public static class FlagsUtils + { + public static T[] getFlags(int f) where T : Enum + { + T flag = (T)Enum.Parse(typeof(T), f.ToString()); + var vals = Enum.GetValues(typeof(T)); + int vallen = vals.Length; + List ret = new List(); + for (int i = 0; i < vallen; i++) + { + if (f != 0 && (int)vals.GetValue(i) == 0) continue; + T val = (T)vals.GetValue(i); + if (flag.HasFlag(val)) ret.Add(val); + } + return ret.ToArray(); + } + + public static T[] getFlags(uint f) where T : Enum + { + T flag = (T)Enum.Parse(typeof(T), f.ToString()); + var vals = Enum.GetValues(typeof(T)); + int vallen = vals.Length; + List ret = new List(); + for (int i = 0; i < vallen; i++) + { + if (f != 0 && (int)vals.GetValue(i) == 0) continue; + T val = (T)vals.GetValue(i); + if (flag.HasFlag(val)) ret.Add(val); + } + return ret.ToArray(); + } + } +} diff --git a/Assets/Editor/SourceCommon/FlagsUtils.cs.meta b/Assets/Editor/SourceCommon/FlagsUtils.cs.meta new file mode 100644 index 0000000..21b3061 --- /dev/null +++ b/Assets/Editor/SourceCommon/FlagsUtils.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 214c5db74ff395549a83e17197713911 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor/SourceCommon/LightUtils.cs b/Assets/Editor/SourceCommon/LightUtils.cs new file mode 100644 index 0000000..e7a7522 --- /dev/null +++ b/Assets/Editor/SourceCommon/LightUtils.cs @@ -0,0 +1,8 @@ +namespace SourceFormatParser.Common +{ + public static class LightUtils + { + public static byte linearToTexLight(byte c, float exponent) => (byte)MathUtils.Clamp(c * exponent * 0.5f, 0, 255); + public static float linearToTexLightF(byte c, float exponent) => MathUtils.Clamp(c * exponent * 0.5f, 0, 255) / 255.0f; + } +} diff --git a/Assets/Editor/SourceCommon/LightUtils.cs.meta b/Assets/Editor/SourceCommon/LightUtils.cs.meta new file mode 100644 index 0000000..e908002 --- /dev/null +++ b/Assets/Editor/SourceCommon/LightUtils.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 57fe4cc545b25df43a52c0a728398c16 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor/SourceCommon/MathUtils.cs b/Assets/Editor/SourceCommon/MathUtils.cs new file mode 100644 index 0000000..b74349f --- /dev/null +++ b/Assets/Editor/SourceCommon/MathUtils.cs @@ -0,0 +1,526 @@ +using System; + +namespace SourceFormatParser.Common +{ + public static class MathUtils + { + public const float M_PI = 3.14159265358979323846f; // matches value in gcc v2 math.h + public const float M_PI_F = ((float)(M_PI)); + public static float RAD2DEG(float x) => ((float)(x) * (float)(180.0f / M_PI_F)); + public static float DEG2RAD(float x) => ((float)(x) * (float)(M_PI_F / 180.0f)); + + public static float Clamp(float val, float min, float max) + { + if (val <= min) return min; + if (val >= max) return max; + return val; + } + + public static float Avg(params float[] fs) + { + float avg = 0; + foreach (float f in fs) avg += f; + avg /= fs.Length; + return avg; + } + public static byte Avg(params byte[] bs) + { + int avg = 0; + foreach (byte b in bs) avg += b; + avg /= bs.Length; + return (byte)avg; + } + + public static SourceMatrix3x4 AngleMatrix(SourceQAngle angles) + { + //float sr, sp, sy, cr, cp, cy; + + //SinCos(DEG2RAD(angles[YAW]), &sy, &cy); + //SinCos(DEG2RAD(angles[PITCH]), &sp, &cp); + //SinCos(DEG2RAD(angles[ROLL]), &sr, &cr); + + //SourceMatrix3x4 matrix; + //// matrix = (YAW * PITCH) * ROLL + //matrix[0][0] = cp * cy; + //matrix[1][0] = cp * sy; + //matrix[2][0] = -sp; + + //// NOTE: Do not optimize this to reduce multiplies! optimizer bug will screw this up. + //matrix[0][1] = sr * sp * cy + cr * -sy; + //matrix[1][1] = sr * sp * sy + cr * cy; + //matrix[2][1] = sr * cp; + //matrix[0][2] = (cr * sp * cy + -sr * -sy); + //matrix[1][2] = (cr * sp * sy + -sr * cy); + //matrix[2][2] = cr * cp; + + //matrix[0][3] = 0.0f; + //matrix[1][3] = 0.0f; + //matrix[2][3] = 0.0f; + + //return matrix; + throw new NotImplementedException(); + } + + public static SourceQuaternion MatrixQuaternion(SourceMatrix3x4 mat) + { + SourceQuaternion tmp = new SourceQuaternion(); + MatrixQuaternion(mat, ref tmp); + return tmp; + } + + public static void MatrixQuaternion(SourceMatrix3x4 mat, ref SourceQuaternion q) + { + SourceQAngle angles = new SourceQAngle(); + MatrixAngles(mat, ref angles); + AngleQuaternion(angles, ref q); + } + + public static void MatrixAngles(SourceMatrix3x4 matrix, ref SourceQAngle angles) + { + //MatrixAngles(matrix, out angles.x); + throw new NotImplementedException(); + } + + public static void AngleQuaternion(SourceQAngle angles, ref SourceQuaternion outQuat) + { + float sr, sp, sy, cr, cp, cy; + + SinCos(DEG2RAD(angles.y) * 0.5f, out sy, out cy); + SinCos(DEG2RAD(angles.x) * 0.5f, out sp, out cp); + SinCos(DEG2RAD(angles.z) * 0.5f, out sr, out cr); + + // NJS: for some reason VC6 wasn't recognizing the common subexpressions: + float srXcp = sr * cp, crXsp = cr * sp; + outQuat.x = srXcp * cy - crXsp * sy; // X + outQuat.y = crXsp * cy + srXcp * sy; // Y + + float crXcp = cr * cp, srXsp = sr * sp; + outQuat.z = crXcp * sy - srXsp * cy; // Z + outQuat.w = crXcp * cy + srXsp * sy; // W (real component) + } + + public static void SinCos(float x, out float s, out float c) + { + c = (float)Math.Cos(x); + s = (float)Math.Sin(x); + } + + public static void AngleMatrix(SourceQAngle angles, SourceVector position, ref SourceMatrix3x4 matrix) + { + AngleMatrix(angles, ref matrix); + MatrixSetColumn(position, 3, ref matrix); + } + + public static void AngleMatrix(SourceQAngle angles, ref SourceMatrix3x4 matrix) + { + float sr, sp, sy, cr, cp, cy; + + SinCos(DEG2RAD(angles[1]), out sy, out cy); + SinCos(DEG2RAD(angles[0]), out sp, out cp); + SinCos(DEG2RAD(angles[2]), out sr, out cr); + + // matrix = (YAW * PITCH) * ROLL + matrix[0][0] = cp * cy; + matrix[1][0] = cp * sy; + matrix[2][0] = -sp; + + // NOTE: Do not optimize this to reduce multiplies! optimizer bug will screw this up. + matrix[0][1] = sr * sp * cy + cr * -sy; + matrix[1][1] = sr * sp * sy + cr * cy; + matrix[2][1] = sr * cp; + matrix[0][2] = (cr * sp * cy + -sr * -sy); + matrix[1][2] = (cr * sp * sy + -sr * cy); + matrix[2][2] = cr * cp; + + matrix[0][3] = 0.0f; + matrix[1][3] = 0.0f; + matrix[2][3] = 0.0f; + } + + public static void MatrixSetColumn(SourceVector _in, int column, ref SourceMatrix3x4 _out) + { + _out[0][column] = _in.x; + _out[1][column] = _in.y; + _out[2][column] = _in.z; + } + + public static void QuaternionAngles(SourceQuaternion q, ref SourceRadianEuler angles) + { + // FIXME: doing it this way calculates too much data, needs to do an optimized version... + SourceMatrix3x4 matrix = new SourceMatrix3x4(); + QuaternionMatrix(q, ref matrix); + MatrixAngles(matrix, ref angles); + } + + public static void QuaternionMatrix(SourceQuaternion q, ref SourceMatrix3x4 matrix) + { + // Original code + // This should produce the same code as below with optimization, but looking at the assmebly, + // it doesn't. There are 7 extra multiplies in the release build of this, go figure. + + matrix[0][0] = 1.0f - 2.0f * q.y * q.y - 2.0f * q.z * q.z; + matrix[1][0] = 2.0f * q.x * q.y + 2.0f * q.w * q.z; + matrix[2][0] = 2.0f * q.x * q.z - 2.0f * q.w * q.y; + + matrix[0][1] = 2.0f * q.x * q.y - 2.0f * q.w * q.z; + matrix[1][1] = 1.0f - 2.0f * q.x * q.x - 2.0f * q.z * q.z; + matrix[2][1] = 2.0f * q.y * q.z + 2.0f * q.w * q.x; + + matrix[0][2] = 2.0f * q.x * q.z + 2.0f * q.w * q.y; + matrix[1][2] = 2.0f * q.y * q.z - 2.0f * q.w * q.x; + matrix[2][2] = 1.0f - 2.0f * q.x * q.x - 2.0f * q.y * q.y; + + matrix[0][3] = 0.0f; + matrix[1][3] = 0.0f; + matrix[2][3] = 0.0f; + } + + public static void MatrixAngles(SourceMatrix3x4 matrix, ref SourceRadianEuler angles) + { + float[] a = new float[3]; + for (int i = 0; i < 3; i++) a[i] = angles[i]; + MatrixAngles(matrix, ref a); + for (int i = 0; i < 3; i++) angles[i] = a[i]; + } + + public static void MatrixAngles(SourceMatrix3x4 matrix, ref float[] angles) + { + float[] forward = new float[3]; + float[] left = new float[3]; + float[] up = new float[3]; + + // + // Extract the basis vectors from the matrix. Since we only need the Z + // component of the up vector, we don't get X and Y. + // + forward[0] = matrix[0][0]; + forward[1] = matrix[1][0]; + forward[2] = matrix[2][0]; + left[0] = matrix[0][1]; + left[1] = matrix[1][1]; + left[2] = matrix[2][1]; + up[2] = matrix[2][2]; + + float xyDist = (float)(Math.Sqrt(forward[0] * forward[0] + forward[1] * forward[1])); + + // enough here to get angles? + if (xyDist > 0.001f) + { + // (yaw) y = ATAN( forward.y, forward.x ); -- in our space, forward is the X axis + angles[1] = RAD2DEG((float)Math.Atan2(forward[1], forward[0])); + + // (pitch) x = ATAN( -forward.z, sqrt(forward.x*forward.x+forward.y*forward.y) ); + angles[0] = RAD2DEG((float)Math.Atan2(-forward[2], xyDist)); + + // (roll) z = ATAN( left.z, up.z ); + angles[2] = RAD2DEG((float)Math.Atan2(left[2], up[2])); + } + else // forward is mostly Z, gimbal lock- + { + // (yaw) y = ATAN( -left.x, left.y ); -- forward is mostly z, so use right for yaw + angles[1] = RAD2DEG((float)Math.Atan2(-left[0], left[1])); + + // (pitch) x = ATAN( -forward.z, sqrt(forward.x*forward.x+forward.y*forward.y) ); + angles[0] = RAD2DEG((float)Math.Atan2(-forward[2], xyDist)); + + // Assume no roll in this case as one degree of freedom has been lost (i.e. yaw == roll) + angles[2] = 0; + } + } + + public static void QuaternionAngles(SourceQuaternion q, ref SourceQAngle angles) + { + // FIXME: doing it this way calculates too much data, needs to do an optimized version... + SourceMatrix3x4 matrix = new SourceMatrix3x4(); + QuaternionMatrix(q, ref matrix); + MatrixAngles(matrix, ref angles); + } + + public static void AngleQuaternion(SourceRadianEuler angles, ref SourceQuaternion outQuat) + { + float sr, sp, sy, cr, cp, cy; + + SinCos(angles.z * 0.5f, out sy, out cy); + SinCos(angles.y * 0.5f, out sp, out cp); + SinCos(angles.x * 0.5f, out sr, out cr); + + // NJS: for some reason VC6 wasn't recognizing the common subexpressions: + float srXcp = sr * cp, crXsp = cr * sp; + outQuat.x = srXcp * cy - crXsp * sy; // X + outQuat.y = crXsp * cy + srXcp * sy; // Y + + float crXcp = cr * cp, srXsp = sr * sp; + outQuat.z = crXcp * sy - srXsp * cy; // Z + outQuat.w = crXcp * cy + srXsp * sy; // W (real component) + } + + public static SourceMatrix3x4 TransformMatrix(SourceCTransform _in) + { + SourceMatrix3x4 _out = new SourceMatrix3x4(); + TransformMatrix(_in, ref _out); + return _out; + } + + public static void TransformMatrix(SourceCTransform _in, ref SourceMatrix3x4 _out) + { + QuaternionMatrix(_in.m_orientation, _in.m_vPosition, ref _out); + } + + public static void QuaternionMatrix(SourceQuaternion q, SourceVector pos, ref SourceMatrix3x4 matrix) + { + QuaternionMatrix(q, ref matrix); + + matrix[0][3] = pos.x; + matrix[1][3] = pos.y; + matrix[2][3] = pos.z; + } + + public static void TransformVectorsFLU(SourceCTransform _in, ref SourceVector pForward, ref SourceVector pLeft, ref SourceVector pUp) + { + QuaternionVectorsFLU(_in.m_orientation, ref pForward, ref pLeft, ref pUp); + } + + public static void QuaternionVectorsFLU(SourceQuaternion q, ref SourceVector pForward, ref SourceVector pLeft, ref SourceVector pUp) + { + // Note: it's pretty much identical to just computing the quaternion matrix and assigning its columns to the vectors + pForward = q.GetForward(); + pLeft = q.GetLeft(); + pUp = q.GetUp(); + } + + public static void TransformVectorsForward(SourceCTransform _in, ref SourceVector pForward) + { + QuaternionVectorsForward(_in.m_orientation, ref pForward); + } + + public static void QuaternionVectorsForward(SourceQuaternion q, ref SourceVector pForward) + { + pForward = q.GetForward(); + } + + public static SourceVector TransformPoint(SourceCTransform tm, SourceVector p) + { + return new SourceVector( + tm.m_vPosition.x + (1.0f - 2.0f * tm.m_orientation.y * tm.m_orientation.y - 2.0f * tm.m_orientation.z * tm.m_orientation.z) * p.x + (2.0f * tm.m_orientation.x * tm.m_orientation.y - 2.0f * tm.m_orientation.w * tm.m_orientation.z) * p.y + (2.0f * tm.m_orientation.x * tm.m_orientation.z + 2.0f * tm.m_orientation.w * tm.m_orientation.y) * p.z, + tm.m_vPosition.y + (2.0f * tm.m_orientation.x * tm.m_orientation.y + 2.0f * tm.m_orientation.w * tm.m_orientation.z) * p.x + (1.0f - 2.0f * tm.m_orientation.x * tm.m_orientation.x - 2.0f * tm.m_orientation.z * tm.m_orientation.z) * p.y + (2.0f * tm.m_orientation.y * tm.m_orientation.z - 2.0f * tm.m_orientation.w * tm.m_orientation.x) * p.z, + tm.m_vPosition.z + (2.0f * tm.m_orientation.x * tm.m_orientation.z - 2.0f * tm.m_orientation.w * tm.m_orientation.y) * p.x + (2.0f * tm.m_orientation.y * tm.m_orientation.z + 2.0f * tm.m_orientation.w * tm.m_orientation.x) * p.y + (1.0f - 2.0f * tm.m_orientation.x * tm.m_orientation.x - 2.0f * tm.m_orientation.y * tm.m_orientation.y) * p.z + ); + } + + public static void RotatePoint(SourceCTransform tm, SourceVector p, ref SourceVector _out) + { + _out.x = (1.0f - 2.0f * tm.m_orientation.y * tm.m_orientation.y - 2.0f * tm.m_orientation.z * tm.m_orientation.z) * p.x + (2.0f * tm.m_orientation.x * tm.m_orientation.y - 2.0f * tm.m_orientation.w * tm.m_orientation.z) * p.y + (2.0f * tm.m_orientation.x * tm.m_orientation.z + 2.0f * tm.m_orientation.w * tm.m_orientation.y) * p.z; + _out.y = (2.0f * tm.m_orientation.x * tm.m_orientation.y + 2.0f * tm.m_orientation.w * tm.m_orientation.z) * p.x + (1.0f - 2.0f * tm.m_orientation.x * tm.m_orientation.x - 2.0f * tm.m_orientation.z * tm.m_orientation.z) * p.y + (2.0f * tm.m_orientation.y * tm.m_orientation.z - 2.0f * tm.m_orientation.w * tm.m_orientation.x) * p.z; + _out.z = (2.0f * tm.m_orientation.x * tm.m_orientation.z - 2.0f * tm.m_orientation.w * tm.m_orientation.y) * p.x + (2.0f * tm.m_orientation.y * tm.m_orientation.z + 2.0f * tm.m_orientation.w * tm.m_orientation.x) * p.y + (1.0f - 2.0f * tm.m_orientation.x * tm.m_orientation.x - 2.0f * tm.m_orientation.y * tm.m_orientation.y) * p.z; + } + + public static void VectorITransform(SourceVector v, SourceCTransform t, ref SourceVector _out) + { + // FIXME: Make work directly with the transform + SourceMatrix3x4 m = new SourceMatrix3x4(); + TransformMatrix(t, ref m); + VectorITransform(v, m, ref _out); + } + + public static void VectorITransform(SourceVector in1, SourceMatrix3x4 in2, ref SourceVector _out) + { + throw new NotImplementedException(); + //VectorITransform(in1.x, in2, ref _out.x); + } + + public static void VectorIRotate(SourceVector v, SourceCTransform t, ref SourceVector _out) + { + // FIXME: Make work directly with the transform + SourceMatrix3x4 m = new SourceMatrix3x4(); + TransformMatrix(t, ref m); + VectorIRotate(v, m, ref _out); + } + + public static void VectorIRotate(SourceVector in1, SourceMatrix3x4 in2, ref SourceVector _out) + { + throw new NotImplementedException(); + //VectorIRotate( in1.x, in2, ref _out.x ); + } + + public static void TransformAABB(SourceMatrix3x4 transform, SourceVector vecMinsIn, SourceVector vecMaxsIn, ref SourceVector vecMinsOut, ref SourceVector vecMaxsOut) + { + throw new NotImplementedException(); //can't find some of methods + + //SourceVector localCenter; + //VectorAdd(vecMinsIn, vecMaxsIn, localCenter); + //localCenter *= 0.5f; + + //SourceVector localExtents; + //VectorSubtract(vecMaxsIn, localCenter, localExtents); + + //SourceVector worldCenter; + //VectorTransform(localCenter, transform, worldCenter); + + //SourceVector worldExtents; + //worldExtents.x = DotProductAbs(localExtents, transform[0]); + //worldExtents.y = DotProductAbs(localExtents, transform[1]); + //worldExtents.z = DotProductAbs(localExtents, transform[2]); + + //VectorSubtract(worldCenter, worldExtents, vecMinsOut); + //VectorAdd(worldCenter, worldExtents, vecMaxsOut); + } + + public static void ITransformAABB(SourceMatrix3x4 transform, SourceVector vecMinsIn, SourceVector vecMaxsIn, ref SourceVector vecMinsOut, ref SourceVector vecMaxsOut) + { + throw new NotImplementedException(); //can't find some of methods + + // SourceVector worldCenter; + // VectorAdd(vecMinsIn, vecMaxsIn, worldCenter ); + // worldCenter *= 0.5f; + + // SourceVector worldExtents; + // VectorSubtract(vecMaxsIn, worldCenter, worldExtents ); + + // Vector localCenter; + // VectorITransform(worldCenter, transform, localCenter ); + + // Vector localExtents; + // localExtents.x = FloatMakePositive(worldExtents.x* transform[0][0] ) + + //FloatMakePositive(worldExtents.y* transform[1][0] ) + + //FloatMakePositive(worldExtents.z* transform[2][0] ); + // localExtents.y = FloatMakePositive(worldExtents.x* transform[0][1] ) + + //FloatMakePositive(worldExtents.y* transform[1][1] ) + + //FloatMakePositive(worldExtents.z* transform[2][1] ); + // localExtents.z = FloatMakePositive(worldExtents.x* transform[0][2] ) + + //FloatMakePositive(worldExtents.y* transform[1][2] ) + + //FloatMakePositive(worldExtents.z* transform[2][2] ); + + // VectorSubtract(localCenter, localExtents, vecMinsOut ); + // VectorAdd(localCenter, localExtents, vecMaxsOut ); + } + + public static void RotateAABB(SourceMatrix3x4 transform, SourceVector vecMinsIn, SourceVector vecMaxsIn, ref SourceVector vecMinsOut, ref SourceVector vecMaxsOut) + { + throw new NotImplementedException(); //can't find some of methods + + //SourceVector localCenter; + //VectorAdd(vecMinsIn, vecMaxsIn, localCenter); + //localCenter *= 0.5f; + + //SourceVector localExtents; + //VectorSubtract(vecMaxsIn, localCenter, localExtents); + + //SourceVector newCenter; + //VectorRotate(localCenter, transform, newCenter); + + //VecSourceVectortor newExtents; + //newExtents.x = DotProductAbs(localExtents, transform[0]); + //newExtents.y = DotProductAbs(localExtents, transform[1]); + //newExtents.z = DotProductAbs(localExtents, transform[2]); + + //VectorSubtract(newCenter, newExtents, vecMinsOut); + //VectorAdd(newCenter, newExtents, vecMaxsOut); + } + + public static void IRotateAABB(SourceMatrix3x4 transform, SourceVector vecMinsIn, SourceVector vecMaxsIn, ref SourceVector vecMinsOut, ref SourceVector vecMaxsOut) + { + throw new NotImplementedException(); //can't find some of methods + + //SourceVector oldCenter; + //VectorAdd(vecMinsIn, vecMaxsIn, oldCenter); + //oldCenter *= 0.5f; + + //SourceVector oldExtents; + //VectorSubtract(vecMaxsIn, oldCenter, oldExtents); + + //SourceVector newCenter; + //VectorIRotate(oldCenter, transform, newCenter); + + //SourceVector newExtents; + //newExtents.x = FloatMakePositive(oldExtents.x * transform[0][0]) + + // FloatMakePositive(oldExtents.y * transform[1][0]) + + // FloatMakePositive(oldExtents.z * transform[2][0]); + //newExtents.y = FloatMakePositive(oldExtents.x * transform[0][1]) + + // FloatMakePositive(oldExtents.y * transform[1][1]) + + // FloatMakePositive(oldExtents.z * transform[2][1]); + //newExtents.z = FloatMakePositive(oldExtents.x * transform[0][2]) + + // FloatMakePositive(oldExtents.y * transform[1][2]) + + // FloatMakePositive(oldExtents.z * transform[2][2]); + + //VectorSubtract(newCenter, newExtents, vecMinsOut); + //VectorAdd(newCenter, newExtents, vecMaxsOut); + } + + public static void MatrixInvert(SourceMatrix3x4 _in, ref SourceMatrix3x4 _out) + { + if (_in == _out) + { + V_swap(ref _out[0][1], ref _out[1][0]); + V_swap(ref _out[0][2], ref _out[2][0]); + V_swap(ref _out[1][2], ref _out[2][1]); + } + else + { + // transpose the matrix + _out[0][0] = _in[0][0]; + _out[0][1] = _in[1][0]; + _out[0][2] = _in[2][0]; + + _out[1][0] = _in[0][1]; + _out[1][1] = _in[1][1]; + _out[1][2] = _in[2][1]; + + _out[2][0] = _in[0][2]; + _out[2][1] = _in[1][2]; + _out[2][2] = _in[2][2]; + } + + // now fix up the translation to be in the other space + float[] tmp = new float[3]; + tmp[0] = _in[0][3]; + tmp[1] = _in[1][3]; + tmp[2] = _in[2][3]; + + _out[0][3] = -DotProduct(tmp, _out[0]); + _out[1][3] = -DotProduct(tmp, _out[1]); + _out[2][3] = -DotProduct(tmp, _out[2]); + } + + public static void V_swap(ref T x, ref T y) + { + T temp = x; + x = y; + y = temp; + } + + public static float DotProduct(float[] a, float[] b) => a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; + + public static void AngleMatrix(SourceRadianEuler angles, SourceVector position, ref SourceMatrix3x4 matrix) + { + AngleMatrix(angles, ref matrix); + MatrixSetColumn(position, 3, ref matrix); + } + + public static void AngleMatrix(SourceRadianEuler angles, ref SourceMatrix3x4 matrix) + { + SourceQAngle quakeEuler = new SourceQAngle(RAD2DEG(angles.y), RAD2DEG(angles.z), RAD2DEG(angles.x)); + + AngleMatrix(quakeEuler, ref matrix); + } + + public static SourceCTransform MatrixTransform(SourceMatrix3x4 _in) + { + SourceCTransform _out = new SourceCTransform(); + MatrixTransform(_in, ref _out); + return _out; + } + + public static void MatrixTransform(SourceMatrix3x4 _in, ref SourceCTransform _out) + { + MatrixQuaternion(_in, ref _out.m_orientation); + MatrixGetColumn(_in, 3, ref _out.m_vPosition); + } + + public static void MatrixGetColumn(SourceMatrix3x4 _in, int column, ref SourceVector _out) + { + _out.x = _in[0][column]; + _out.y = _in[1][column]; + _out.z = _in[2][column]; + } + } +} \ No newline at end of file diff --git a/Assets/Editor/SourceCommon/MathUtils.cs.meta b/Assets/Editor/SourceCommon/MathUtils.cs.meta new file mode 100644 index 0000000..ad9f561 --- /dev/null +++ b/Assets/Editor/SourceCommon/MathUtils.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b9c40dc28e7e1a7479f5461294fefd74 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor/SourceCommon/ParsingUtils.cs b/Assets/Editor/SourceCommon/ParsingUtils.cs new file mode 100644 index 0000000..0459c3f --- /dev/null +++ b/Assets/Editor/SourceCommon/ParsingUtils.cs @@ -0,0 +1,66 @@ +using System.IO; +using System.Text; + +namespace SourceFormatParser.Common +{ + public static class ParsingUtils + { + public static SourceVector ReadVector(this BinaryReader BR) => new SourceVector(BR.ReadSingle(), BR.ReadSingle(), BR.ReadSingle()); + public static SourceVectorShort ReadVectorShort(this BinaryReader BR) => new SourceVectorShort(BR.ReadInt16(), BR.ReadInt16(), BR.ReadInt16()); + public static SourceVector2 ReadVector2(this BinaryReader BR) => new SourceVector2(BR.ReadSingle(), BR.ReadSingle()); + public static SourceVector2Short ReadVector2Short(this BinaryReader BR) => new SourceVector2Short(BR.ReadInt16(), BR.ReadInt16()); + public static SourceVector2Int ReadVector2Int(this BinaryReader BR) => new SourceVector2Int(BR.ReadInt32(), BR.ReadInt32()); + public static SourceVector4 ReadVector4(this BinaryReader BR) => new SourceVector4(BR.ReadSingle(), BR.ReadSingle(), BR.ReadSingle(), BR.ReadSingle()); + + public static SourceQAngle ReadQAngle(this BinaryReader BR) => new SourceQAngle(BR.ReadSingle(), BR.ReadSingle(), BR.ReadSingle()); + public static SourceQuaternion ReadQuaternion(this BinaryReader BR) => new SourceQuaternion(BR.ReadSingle(), BR.ReadSingle(), BR.ReadSingle(), BR.ReadSingle()); + public static SourceRadianEuler ReadRadianEuler(this BinaryReader BR) => new SourceRadianEuler(BR.ReadSingle(), BR.ReadSingle(), BR.ReadSingle()); + + public static SourceMatrix3x4 ReadMatrix3x4(this BinaryReader BR) => new SourceMatrix3x4(BR.ReadVector(), BR.ReadVector(), BR.ReadVector(), BR.ReadVector()); + + public static SourceColor32 ReadColor32(this BinaryReader BR) => new SourceColor32(BR.ReadByte(), BR.ReadByte(), BR.ReadByte(), BR.ReadByte()); + public static ColorRGBExp32 ReadColorRGBExp32(this BinaryReader BR) => new ColorRGBExp32(BR.ReadByte(), BR.ReadByte(), BR.ReadByte(), BR.ReadByte()); + + public static CompressedLightCube ReadCompressedLightCube(this BinaryReader BR) => new CompressedLightCube { + m_Color = new ColorRGBExp32[6] { + ReadColorRGBExp32(BR), ReadColorRGBExp32(BR), ReadColorRGBExp32(BR), ReadColorRGBExp32(BR), ReadColorRGBExp32(BR), ReadColorRGBExp32(BR) + } + }; + + #region Read Array + public static ushort[] ReadUInt16Array(this BinaryReader BR, int count) + { + ushort[] ret = new ushort[count]; + for (int c = 0; c < count; c++) ret[c] = BR.ReadUInt16(); + return ret; + } + public static short[] ReadInt16Array(this BinaryReader BR, int count) + { + short[] ret = new short[count]; + for (int c = 0; c < count; c++) ret[c] = BR.ReadInt16(); + return ret; + } + public static uint[] ReadUInt32Array(this BinaryReader BR, int count) + { + uint[] ret = new uint[count]; + for (int c = 0; c < count; c++) ret[c] = BR.ReadUInt32(); + return ret; + } + public static int[] ReadInt32Array(this BinaryReader BR, int count) + { + int[] ret = new int[count]; + for (int c = 0; c < count; c++) ret[c] = BR.ReadInt32(); + return ret; + } + + public static float[] ReadSingleArray(this BinaryReader BR, int count) + { + float[] ret = new float[count]; + for (int c = 0; c < count; c++) ret[c] = BR.ReadSingle(); + return ret; + } + #endregion + + public static string ReadString(this BinaryReader BR, int count) => Encoding.ASCII.GetString(BR.ReadBytes(64)).Replace("\0", ""); + } +} diff --git a/Assets/Editor/SourceCommon/ParsingUtils.cs.meta b/Assets/Editor/SourceCommon/ParsingUtils.cs.meta new file mode 100644 index 0000000..31bf731 --- /dev/null +++ b/Assets/Editor/SourceCommon/ParsingUtils.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 60518559dfb0da7408790faa0dc034c3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor/SourceCommon/SourceColor32.cs b/Assets/Editor/SourceCommon/SourceColor32.cs new file mode 100644 index 0000000..f9730d5 --- /dev/null +++ b/Assets/Editor/SourceCommon/SourceColor32.cs @@ -0,0 +1,30 @@ +namespace SourceFormatParser.Common +{ + /// + /// compressed color rgba format. + /// Size: 4 bytes + /// + public struct SourceColor32 + { + public byte r, g, b, a; + + public SourceColor32(byte r, byte g, byte b, byte a) + { + this.r = r; + this.g = g; + this.b = b; + this.a = a; + } + public SourceColor32(float r, float g, float b, float a) + { + this.r = (byte)(r * 255); + this.g = (byte)(g * 255); + this.b = (byte)(b * 255); + this.a = (byte)(a * 255); + } + + public SourceVector toSVector() => new SourceVector(r * (1.0f / 255.0f), g * (1.0f / 255.0f), b * (1.0f / 255.0f)); + + public override string ToString() => $"{{{r}; {g}; {b}; {a}}}"; + } +} diff --git a/Assets/Editor/SourceCommon/SourceColor32.cs.meta b/Assets/Editor/SourceCommon/SourceColor32.cs.meta new file mode 100644 index 0000000..febdf79 --- /dev/null +++ b/Assets/Editor/SourceCommon/SourceColor32.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: aa45776704098ca46a06f71dbadadb98 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor/SourceCommon/Vectors.meta b/Assets/Editor/SourceCommon/Vectors.meta new file mode 100644 index 0000000..76fee70 --- /dev/null +++ b/Assets/Editor/SourceCommon/Vectors.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b5d883a90443a954aa51477cd9deff83 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor/SourceCommon/Vectors/SourceCTransform.cs b/Assets/Editor/SourceCommon/Vectors/SourceCTransform.cs new file mode 100644 index 0000000..29c1300 --- /dev/null +++ b/Assets/Editor/SourceCommon/Vectors/SourceCTransform.cs @@ -0,0 +1,126 @@ +using System; + +namespace SourceFormatParser.Common +{ + public class SourceCTransform + { + public SourceCTransform() { } + public SourceCTransform(SourceVector v, SourceQuaternion q) + { + m_vPosition = v; + m_orientation = q; + } + public SourceCTransform(SourceVector v, SourceQAngle a) + { + m_vPosition = v; + MathUtils.AngleQuaternion(a, ref m_orientation); + } + + public SourceVector m_vPosition; + public SourceQuaternion m_orientation; + + public bool IsValid() + { + //return m_vPosition.IsValid() && m_orientation.IsValid(); + throw new NotImplementedException(); + } + + public static bool operator ==(SourceCTransform c1, SourceCTransform c2) => c1.m_vPosition == c2.m_vPosition && c1.m_orientation == c2.m_orientation; //< exact equality check + public static bool operator !=(SourceCTransform c1, SourceCTransform c2) => !(c1 == c2); + + public override bool Equals(object obj) => this == (SourceCTransform)obj; + public override int GetHashCode() => base.GetHashCode(); + + // for API compatibility with matrix3x4_t + public void InitFromQAngles(SourceQAngle angles, SourceVector vPosition) + { + MathUtils.AngleQuaternion(angles, ref m_orientation); + m_vPosition = vPosition; + } + public void InitFromMatrix(SourceMatrix3x4 transform) + { + m_orientation = MathUtils.MatrixQuaternion(transform); + m_vPosition = transform.GetOrigin(); + } + public void InitFromQuaternion(SourceQuaternion orientation, SourceVector vPosition) + { + m_orientation = orientation; + m_vPosition = vPosition; + } + + public SourceQuaternion ToQuaternion() => m_orientation; + public SourceQAngle ToQAngle() + { + SourceQAngle angles = new SourceQAngle(); + MathUtils.QuaternionAngles(m_orientation, ref angles); + return angles; + } + public SourceMatrix3x4 ToMatrix() => MathUtils.TransformMatrix(this); + + public void SetToIdentity() + { + m_vPosition = SourceVector.Empty; + m_orientation = SourceQuaternion.Identity; + } + + public void SetOrigin(SourceVector vPos) { m_vPosition = vPos; } + public void SetAngles(SourceQAngle vAngles) { MathUtils.AngleQuaternion(vAngles, ref m_orientation); } + public SourceVector GetOrigin() { return m_vPosition; } + + public void GetBasisVectorsFLU(ref SourceVector pForward, ref SourceVector pLeft, ref SourceVector pUp) + { + MathUtils.TransformVectorsFLU(this, ref pForward, ref pLeft, ref pUp); + } + public SourceVector GetForward() + { + SourceVector vForward = new SourceVector(); + MathUtils.TransformVectorsForward(this, ref vForward); + return vForward; + } + public SourceVector TransformVector(SourceVector v0) => MathUtils.TransformPoint(this, v0); + public SourceVector RotateVector(SourceVector v0) + { + SourceVector vOut = new SourceVector(); + MathUtils.RotatePoint(this, v0, ref vOut); + return vOut; + } + public SourceVector TransformVectorByInverse(SourceVector v0) + { + SourceVector vOut = new SourceVector(); + MathUtils.VectorITransform(v0, this, ref vOut); + return vOut; + } + public SourceVector RotateVectorByInverse(SourceVector v0) + { + SourceVector vOut = new SourceVector(); + MathUtils.VectorIRotate(v0, this, ref vOut); + return vOut; + } + public SourceVector RotateExtents(SourceVector vBoxExtents) { throw new NotImplementedException(); } // these are extents and must remain positive/symmetric after rotation + public void TransformAABB(SourceVector vecMinsIn, SourceVector vecMaxsIn, ref SourceVector vecMinsOut, ref SourceVector vecMaxsOut) + { + ToMatrix().TransformAABB(vecMinsIn, vecMaxsIn, ref vecMinsOut, ref vecMaxsOut); + } + public void TransformAABBByInverse(SourceVector vecMinsIn, SourceVector vecMaxsIn, ref SourceVector vecMinsOut, ref SourceVector vecMaxsOut) + { + ToMatrix().TransformAABBByInverse(vecMinsIn, vecMaxsIn, ref vecMinsOut, ref vecMaxsOut); + } + public void RotateAABB(SourceVector vecMinsIn, SourceVector vecMaxsIn, ref SourceVector vecMinsOut, ref SourceVector vecMaxsOut) + { + ToMatrix().RotateAABB(vecMinsIn, vecMaxsIn, ref vecMinsOut, ref vecMaxsOut); + } + public void RotateAABBByInverse(SourceVector vecMinsIn, SourceVector vecMaxsIn, ref SourceVector vecMinsOut, ref SourceVector vecMaxsOut) + { + ToMatrix().RotateAABBByInverse(vecMinsIn, vecMaxsIn, ref vecMinsOut, ref vecMaxsOut); + } + //inline void TransformPlane( const cplane_t &inPlane, cplane_t &outPlane ) const; + //inline void InverseTransformPlane( const cplane_t &inPlane, cplane_t &outPlane ) const; + + /// Computes an inverse. Uses the 'TR' naming to be consistent with the same method in matrix3x4_t (which only works with orthonormal matrices) + public void InverseTR(ref SourceCTransform _out) + { + SourceMatrix3x4 xForm = ToMatrix(); + _out = xForm.InverseTR().ToCTransform(); + } + } +} diff --git a/Assets/Editor/SourceCommon/Vectors/SourceCTransform.cs.meta b/Assets/Editor/SourceCommon/Vectors/SourceCTransform.cs.meta new file mode 100644 index 0000000..93fa20f --- /dev/null +++ b/Assets/Editor/SourceCommon/Vectors/SourceCTransform.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6fe3919ba3838be48be45220405d6dcb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor/SourceCommon/Vectors/SourceDegreeEuler.cs b/Assets/Editor/SourceCommon/Vectors/SourceDegreeEuler.cs new file mode 100644 index 0000000..f8c73a3 --- /dev/null +++ b/Assets/Editor/SourceCommon/Vectors/SourceDegreeEuler.cs @@ -0,0 +1,69 @@ +using System; + +namespace SourceFormatParser.Common +{ + /// Degree Euler angle aligned to axis (NOT ROLL/PITCH/YAW) + public class SourceDegreeEuler + { + public SourceDegreeEuler() { } + public SourceDegreeEuler(float X, float Y, float Z) { x = X; y = Y; z = Z; } + public SourceDegreeEuler(SourceQuaternion q) + { + SourceRadianEuler radians = new SourceRadianEuler(q); + Init(MathUtils.RAD2DEG(radians.x), MathUtils.RAD2DEG(radians.y), MathUtils.RAD2DEG(radians.z)); + } + public SourceDegreeEuler(SourceQAngle angles) + { + Init(angles.z, angles.x, angles.y); + } + public SourceDegreeEuler(SourceRadianEuler angles) + { + Init(MathUtils.RAD2DEG(angles.x), MathUtils.RAD2DEG(angles.y), MathUtils.RAD2DEG(angles.z)); + } + + // Initialization + public void Init(float ix = 0.0f, float iy = 0.0f, float iz = 0.0f) { x = ix; y = iy; z = iz; } + + public SourceQAngle ToQAngle() => new SourceQAngle(y, z, x); + + // conversion to qangle + public bool IsValid() { throw new NotImplementedException(); } + public void Invalidate() { throw new NotImplementedException(); } + + public float Base() { return x; } + + // array access... + public float this[int i] + { + get + { + switch (i) + { + case 0: return x; + case 1: return y; + case 2: return z; + default: throw new Exception("wrong index [0..2]"); + } + } + set + { + switch (i) + { + case 0: + x = value; + break; + case 1: + y = value; + break; + case 2: + z = value; + break; + default: + throw new Exception("wrong index [0..2]"); + } + } + } + + public float x, y, z; + } +} diff --git a/Assets/Editor/SourceCommon/Vectors/SourceDegreeEuler.cs.meta b/Assets/Editor/SourceCommon/Vectors/SourceDegreeEuler.cs.meta new file mode 100644 index 0000000..120c819 --- /dev/null +++ b/Assets/Editor/SourceCommon/Vectors/SourceDegreeEuler.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 14e01e0782293504ebe7b80d0a29eed8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor/SourceCommon/Vectors/SourceMatrix3x4.cs b/Assets/Editor/SourceCommon/Vectors/SourceMatrix3x4.cs new file mode 100644 index 0000000..9a4c33f --- /dev/null +++ b/Assets/Editor/SourceCommon/Vectors/SourceMatrix3x4.cs @@ -0,0 +1,252 @@ +namespace SourceFormatParser.Common +{ + /// + /// Matrix 3x4 (float) + /// Size: 48 bytes (4 bytes per val) + /// + public class SourceMatrix3x4 + { + public SourceMatrix3x4() { } + public SourceMatrix3x4(float m00, float m01, float m02, float m03, + float m10, float m11, float m12, float m13, + float m20, float m21, float m22, float m23) + { + m_flMatVal[0][0] = m00; m_flMatVal[0][1] = m01; m_flMatVal[0][2] = m02; m_flMatVal[0][3] = m03; + m_flMatVal[1][0] = m10; m_flMatVal[1][1] = m11; m_flMatVal[1][2] = m12; m_flMatVal[1][3] = m13; + m_flMatVal[2][0] = m20; m_flMatVal[2][1] = m21; m_flMatVal[2][2] = m22; m_flMatVal[2][3] = m23; + } + + /// Creates a matrix where the X axis = forward the Y axis = left, and the Z axis = up + void InitXYZ(SourceVector xAxis, SourceVector yAxis, SourceVector zAxis, SourceVector vecOrigin) + { + m_flMatVal[0][0] = xAxis.x; m_flMatVal[0][1] = yAxis.x; m_flMatVal[0][2] = zAxis.x; m_flMatVal[0][3] = vecOrigin.x; + m_flMatVal[1][0] = xAxis.y; m_flMatVal[1][1] = yAxis.y; m_flMatVal[1][2] = zAxis.y; m_flMatVal[1][3] = vecOrigin.y; + m_flMatVal[2][0] = xAxis.z; m_flMatVal[2][1] = yAxis.z; m_flMatVal[2][2] = zAxis.z; m_flMatVal[2][3] = vecOrigin.z; + } + + //----------------------------------------------------------------------------- + // Creates a matrix where the X axis = forward + // the Y axis = left, and the Z axis = up + //----------------------------------------------------------------------------- + void Init(SourceVector xAxis, SourceVector yAxis, SourceVector zAxis, SourceVector vecOrigin) + { + m_flMatVal[0][0] = xAxis.x; m_flMatVal[0][1] = yAxis.x; m_flMatVal[0][2] = zAxis.x; m_flMatVal[0][3] = vecOrigin.x; + m_flMatVal[1][0] = xAxis.y; m_flMatVal[1][1] = yAxis.y; m_flMatVal[1][2] = zAxis.y; m_flMatVal[1][3] = vecOrigin.y; + m_flMatVal[2][0] = xAxis.z; m_flMatVal[2][1] = yAxis.z; m_flMatVal[2][2] = zAxis.z; m_flMatVal[2][3] = vecOrigin.z; + } + + //----------------------------------------------------------------------------- + // Creates a matrix where the X axis = forward + // the Y axis = left, and the Z axis = up + //----------------------------------------------------------------------------- + public SourceMatrix3x4(SourceVector xAxis, SourceVector yAxis, SourceVector zAxis, SourceVector vecOrigin) + { + Init(xAxis, yAxis, zAxis, vecOrigin); + } + + public void InitFromQAngles(SourceQAngle angles, SourceVector vPosition) + { + var t = this; + MathUtils.AngleMatrix(angles, vPosition, ref t); + this.m_flMatVal = t.m_flMatVal; + } + public void InitFromQAngles(SourceQAngle angles) { InitFromQAngles(angles, SourceVector.Empty); } + public void InitFromRadianEuler(SourceRadianEuler angles, SourceVector vPosition) + { + var t = this; + MathUtils.AngleMatrix(angles, vPosition, ref t); + this.m_flMatVal = t.m_flMatVal; + } + public void InitFromRadianEuler(SourceRadianEuler angles) { InitFromRadianEuler(angles, SourceVector.Empty); } + public void InitFromCTransform(SourceCTransform transform) + { + var t = this; + MathUtils.TransformMatrix(transform, ref t); + this.m_flMatVal = t.m_flMatVal; + } + public void InitFromQuaternion(SourceQuaternion orientation, SourceVector vPosition) + { + var t = this; + MathUtils.QuaternionMatrix(orientation, vPosition, ref t); + this.m_flMatVal = t.m_flMatVal; + } + public void InitFromQuaternion(SourceQuaternion orientation) { InitFromQuaternion(orientation, SourceVector.Empty); } + public void InitFromDiagonal(SourceVector vDiagonal) + { + SetToIdentity(); + m_flMatVal[0][0] = vDiagonal.x; + m_flMatVal[1][1] = vDiagonal.y; + m_flMatVal[2][2] = vDiagonal.z; + } + + public SourceQuaternion ToQuaternion() => MathUtils.MatrixQuaternion(this); + public SourceQAngle ToQAngle() + { + SourceQAngle tmp = new SourceQAngle(); + MathUtils.MatrixAngles(this, ref tmp); + return tmp; + } + public SourceCTransform ToCTransform() => MathUtils.MatrixTransform(this); + + public void SetToIdentity() + { + for (int i1 = 0; i1 < m_flMatVal.Length; i1++) + for (int i2 = 0; i2 < m_flMatVal[i1].Length; i2++) + m_flMatVal[i1][i2] = 0.0f; + m_flMatVal[0][0] = 1.0f; + m_flMatVal[1][1] = 1.0f; + m_flMatVal[2][2] = 1.0f; + } + + /// multiply the scale/rot part of the matrix by a constant. This doesn't init the matrix , + /// just scale in place. So if you want to construct a scaling matrix, init to identity and + /// then call this. + public void ScaleUpper3x3Matrix(float flScale) + { + for (int i = 0; i < 3; i++) + { + for (int j = 0; j < 3; j++) + { + m_flMatVal[i][j] *= flScale; + } + } + } + + /// modify the origin + public void SetOrigin(SourceVector p) + { + m_flMatVal[0][3] = p.x; + m_flMatVal[1][3] = p.y; + m_flMatVal[2][3] = p.z; + } + + /// return the origin + public SourceVector GetOrigin() + { + return new SourceVector(m_flMatVal[0][3], m_flMatVal[1][3], m_flMatVal[2][3]); + } + + void Invalidate() + { + for (int i = 0; i < 3; i++) + { + for (int j = 0; j < 4; j++) + { + m_flMatVal[i][j] = float.NaN; + } + } + } + + /// check all components for invalid floating point values + bool IsValid() + { + for (int i = 0; i < 3; i++) + { + for (int j = 0; j < 4; j++) + { + if (m_flMatVal[i][j] == float.NaN) + return false; + } + } + return true; + } + + public static bool operator ==(SourceMatrix3x4 m1, SourceMatrix3x4 m2) + { + bool equals = true; + for (int i1 = 0; i1 < 3; i1++) + { + if (!equals) break; + for (int i2 = 0; i2 < 4; i2++) + { + if (m1[i1][i2] != m2[i1][i2]) + { + equals = false; + break; + } + } + } + return equals; + } + public static bool operator !=(SourceMatrix3x4 m1, SourceMatrix3x4 m2) => !(m1 == m2); + + public override bool Equals(object obj) => this == (SourceMatrix3x4)obj; + public override int GetHashCode() => base.GetHashCode(); + + // bool IsEqualTo( const SourceMatrix3x4 &other, float flTolerance = 1e-5f) const; + + //void GetBasisVectorsFLU(Vector* pForward, Vector* pLeft, Vector* pUp) const; + //SourceVector TransformVector( const Vector &v0 ) const; + //SourceVector RotateVector( const Vector &v0 ) const; + //SourceVector TransformVectorByInverse( const Vector &v0 ) const; + //SourceVector RotateVectorByInverse( const Vector &v0 ) const; + //SourceVector RotateExtents( const Vector &vBoxExtents ) const; // these are extents and must remain positive/symmetric after rotation + public void TransformAABB(SourceVector vecMinsIn, SourceVector vecMaxsIn, ref SourceVector vecMinsOut, ref SourceVector vecMaxsOut) + { + MathUtils.TransformAABB(this, vecMinsIn, vecMaxsIn, ref vecMinsOut, ref vecMaxsOut); + } + public void TransformAABBByInverse(SourceVector vecMinsIn, SourceVector vecMaxsIn, ref SourceVector vecMinsOut, ref SourceVector vecMaxsOut) + { + MathUtils.ITransformAABB(this, vecMinsIn, vecMaxsIn, ref vecMinsOut, ref vecMaxsOut); + } + public void RotateAABB(SourceVector vecMinsIn, SourceVector vecMaxsIn, ref SourceVector vecMinsOut, ref SourceVector vecMaxsOut) + { + MathUtils.RotateAABB(this, vecMinsIn, vecMaxsIn, ref vecMinsOut, ref vecMaxsOut); + } + public void RotateAABBByInverse(SourceVector vecMinsIn, SourceVector vecMaxsIn, ref SourceVector vecMinsOut, ref SourceVector vecMaxsOut) + { + MathUtils.IRotateAABB(this, vecMinsIn, vecMaxsIn, ref vecMinsOut, ref vecMaxsOut); + } + //void TransformPlane( const cplane_t &inPlane, cplane_t &outPlane ) const; + //void TransformPlaneByInverse( const cplane_t &inPlane, cplane_t &outPlane ) const; + //float GetOrthogonalityError() const; + //float GetDeterminant()const; + //float GetSylvestersCriterion()const; // for symmetrical matrices only: should be >0 iff it's a positive definite matrix + + //SourceVector GetColumn(MatrixAxisType_t nColumn) const; + //void SetColumn( const Vector &vColumn, MatrixAxisType_t nColumn); + //SourceVector GetForward() const { return GetColumn(FORWARD_AXIS ); } + // SourceVector GetLeft() const { return GetColumn(LEFT_AXIS ); } + // SourceVector GetUp() const { return GetColumn(UP_AXIS ); } + // SourceVector GetRow(int nRow) const { return * (Vector*) (m_flMatVal[nRow]); } + // void SetRow(int nRow, const Vector &vRow ) { m_flMatVal[nRow][0] = vRow.x; m_flMatVal[nRow][1] = vRow.y; m_flMatVal[nRow][2] = vRow.z; } + + public void InverseTR(ref SourceMatrix3x4 _out) + { + MathUtils.MatrixInvert(this, ref _out); + } + public SourceMatrix3x4 InverseTR() + { + SourceMatrix3x4 _out = new SourceMatrix3x4(); + InverseTR(ref _out); + return _out; + } + + public float[] this[int i] + { + get => m_flMatVal[i]; + set => m_flMatVal[i] = value; + } + + public float Base() { return m_flMatVal[0][0]; } + + float[][] _m_flMatVal; + public float[][] m_flMatVal//[3][4]; + { + get + { + if (_m_flMatVal == null) + { + _m_flMatVal = new float[3][]; + for (int v = 0; v < 3; v++) + _m_flMatVal[v] = new float[4]; + } + return _m_flMatVal; + } + set + { + _m_flMatVal = value; + } + } + } +} diff --git a/Assets/Editor/SourceCommon/Vectors/SourceMatrix3x4.cs.meta b/Assets/Editor/SourceCommon/Vectors/SourceMatrix3x4.cs.meta new file mode 100644 index 0000000..79cf28e --- /dev/null +++ b/Assets/Editor/SourceCommon/Vectors/SourceMatrix3x4.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6a4f71b4e3573b54c9258fddae8a25e8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor/SourceCommon/Vectors/SourceQAngle.cs b/Assets/Editor/SourceCommon/Vectors/SourceQAngle.cs new file mode 100644 index 0000000..8e48ad1 --- /dev/null +++ b/Assets/Editor/SourceCommon/Vectors/SourceQAngle.cs @@ -0,0 +1,88 @@ +using System; + +namespace SourceFormatParser.Common +{ + /// + /// Vector x/y/z (float) + /// Size: 12 bytes (4 bytes per axis) + /// + public struct SourceQAngle + { + // Members + public float x, y, z; + + // Initialization + public SourceQAngle(float ix = 0.0f, float iy = 0.0f, float iz = 0.0f) + { + this.x = ix; + this.y = iy; + this.z = iz; + } + public static SourceQAngle Random(float minVal, float maxVal) + { + Random rand = new Random(); + return new SourceQAngle( + ix: minVal + ((float)rand.NextDouble()) * (float)(maxVal - minVal), + iy: minVal + ((float)rand.NextDouble()) * (float)(maxVal - minVal), + iz: minVal + ((float)rand.NextDouble()) * (float)(maxVal - minVal) + ); + } + + // equality + public static bool operator ==(SourceQAngle v1, SourceQAngle v2) => v1.x == v2.x && v1.y == v2.y && v1.z == v2.z; + public static bool operator !=(SourceQAngle v1, SourceQAngle v2) => !(v1 == v2); + + public override bool Equals(object obj) => this == (SourceQAngle)obj; + public override int GetHashCode() => base.GetHashCode(); + + // arithmetic operations + public static SourceQAngle operator +(SourceQAngle v1, SourceQAngle v2) => new SourceQAngle(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z); + public static SourceQAngle operator -(SourceQAngle v1, SourceQAngle v2) => new SourceQAngle(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z); + public static SourceQAngle operator *(SourceQAngle v, float s) => new SourceQAngle(v.x * s, v.y * s, v.z * s); + public static SourceQAngle operator /(SourceQAngle v, float fl) + { + if (fl == 0.0f) + return new SourceQAngle(); + float oofl = 1.0f / fl; + return new SourceQAngle(v.x * oofl, v.y * oofl, v.z * oofl); + } + + public float this[int i] + { + get + { + switch (i) + { + case 0: + return x; + case 1: + return y; + case 2: + return z; + } + throw new Exception("wrong index"); + } + set + { + switch (i) + { + case 0: + x = value; + break; + case 1: + y = value; + break; + case 2: + z = value; + break; + } + } + } + + // Get the vector's magnitude. + public float Length() => (float)Math.Sqrt(LengthSqr()); + public float LengthSqr() => x * x + y * y + z * z; + + public override string ToString() => $"{{{x}; {y}; {z}}}"; + } +} diff --git a/Assets/Editor/SourceCommon/Vectors/SourceQAngle.cs.meta b/Assets/Editor/SourceCommon/Vectors/SourceQAngle.cs.meta new file mode 100644 index 0000000..4822e5f --- /dev/null +++ b/Assets/Editor/SourceCommon/Vectors/SourceQAngle.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 42f5749be91a85846b5abe45d8eab4fb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor/SourceCommon/Vectors/SourceQuaternion.cs b/Assets/Editor/SourceCommon/Vectors/SourceQuaternion.cs new file mode 100644 index 0000000..b06d436 --- /dev/null +++ b/Assets/Editor/SourceCommon/Vectors/SourceQuaternion.cs @@ -0,0 +1,134 @@ +using System; + +namespace SourceFormatParser.Common +{ + /// + /// Quaternion x/y/z/w (float) + /// Size: 16 bytes (4 bytes per axis) + /// + public struct SourceQuaternion + { + // same data-layout as engine's vec4_t, + // which is a vec_t[4]=float[4] + + public float x, y, z, w; + + public SourceQuaternion(float ix, float iy, float iz, float iw) + { + //Init(ix, iy, iz, iw); + x = ix; y = iy; z = iz; w = iw; + } + public SourceQuaternion(SourceRadianEuler angle) + { + var t = new SourceQuaternion(); + MathUtils.AngleQuaternion(angle, ref t); + this.x = t.x; + this.y = t.y; + this.z = t.z; + this.w = t.w; + } + public SourceQuaternion(SourceDegreeEuler angle) + { + SourceRadianEuler radians = new SourceRadianEuler(angle); + var t = new SourceQuaternion(); + MathUtils.AngleQuaternion(radians, ref t); + this.x = t.x; + this.y = t.y; + this.z = t.z; + this.w = t.w; + } + + void Init(float ix = 0.0f, float iy = 0.0f, float iz = 0.0f, float iw = 0.0f) { x = ix; y = iy; z = iz; w = iw; } + void Init(SourceVector vImaginaryPart, float flRealPart) { x = vImaginaryPart.x; y = vImaginaryPart.y; z = vImaginaryPart.z; w = flRealPart; } + + + public static bool operator ==(SourceQuaternion v1, SourceQuaternion v2) => v1.x == v2.x && v1.y == v2.y && v1.z == v2.z && v1.w == v2.w; + public static bool operator !=(SourceQuaternion v1, SourceQuaternion v2) => !(v1 == v2); + + public override bool Equals(object obj) => this == (SourceQuaternion)obj; + public override int GetHashCode() => base.GetHashCode(); + + public SourceQuaternion Conjugate() { return new SourceQuaternion(-x, -y, -z, w); } + + public SourceVector GetForward() + { + SourceVector vAxisX; + vAxisX.x = 1.0f - 2.0f * y * y - 2.0f * z * z; + vAxisX.y = 2.0f * x * y + 2.0f * w * z; + vAxisX.z = 2.0f * x * z - 2.0f * w * y; + return vAxisX; + } + public SourceVector GetLeft() + { + SourceVector vAxisY; + vAxisY.x = 2.0f * x * y - 2.0f * w * z; + vAxisY.y = 1.0f - 2.0f * x * x - 2.0f * z * z; + vAxisY.z = 2.0f * y * z + 2.0f * w * x; + return vAxisY; + } + public SourceVector GetUp() + { + SourceVector vAxisZ; + vAxisZ.x = 2.0f * x * z + 2.0f * w * y; + vAxisZ.y = 2.0f * y * z - 2.0f * w * x; + vAxisZ.z = 1.0f - 2.0f * x * x - 2.0f * y * y; + return vAxisZ; + } + + + public float RealPart() { return w; } + public SourceQAngle ToQAngle() + { + SourceQAngle anglesOut = new SourceQAngle(); + MathUtils.QuaternionAngles(this, ref anglesOut); + return anglesOut; + } + public SourceMatrix3x4 ToMatrix() + { + SourceMatrix3x4 mat = new SourceMatrix3x4(); + mat.InitFromQuaternion(this); + return mat; + } + + // array access... + public float this[int i] + { + get + { + switch (i) + { + case 0: return x; + case 1: return y; + case 2: return z; + case 3: return w; + default: throw new Exception("wrong index [0..3]"); + } + } + set + { + switch (i) + { + case 0: + x = value; + break; + case 1: + y = value; + break; + case 2: + z = value; + break; + case 3: + w = value; + break; + default: + throw new Exception("wrong index [0..3]"); + } + } + } + + public static SourceQuaternion operator +(SourceQuaternion q1, SourceQuaternion q2) => new SourceQuaternion(q1.x + q2.x, q1.y + q2.y, q1.z + q2.z, q1.w + q2.w); + public static SourceQuaternion operator -(SourceQuaternion q1, SourceQuaternion q2) => new SourceQuaternion(q1.x - q2.x, q1.y - q2.y, q1.z - q2.z, q1.w - q2.w); + + public static SourceQuaternion Identity = new SourceQuaternion(); + } +} diff --git a/Assets/Editor/SourceCommon/Vectors/SourceQuaternion.cs.meta b/Assets/Editor/SourceCommon/Vectors/SourceQuaternion.cs.meta new file mode 100644 index 0000000..82044c0 --- /dev/null +++ b/Assets/Editor/SourceCommon/Vectors/SourceQuaternion.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f79c37491dea4d847806826d30312f7f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor/SourceCommon/Vectors/SourceRadianEuler.cs b/Assets/Editor/SourceCommon/Vectors/SourceRadianEuler.cs new file mode 100644 index 0000000..c933477 --- /dev/null +++ b/Assets/Editor/SourceCommon/Vectors/SourceRadianEuler.cs @@ -0,0 +1,76 @@ +using System; + +namespace SourceFormatParser.Common +{ + /// + /// RadianEuler x/y/z (float) + /// Size: 12 bytes (4 bytes per axis) + /// + public class SourceRadianEuler + { + public SourceRadianEuler() { } + public SourceRadianEuler(float X, float Y, float Z) { x = X; y = Y; z = Z; } + public SourceRadianEuler(SourceQuaternion q) + { + var t = this; + MathUtils.QuaternionAngles(q, ref t); + this.x = t.x; + this.y = t.y; + this.z = t.z; + } + public SourceRadianEuler(SourceQAngle angles) + { + Init(angles.z * 3.14159265358979323846f / 180.0f, + angles.x * 3.14159265358979323846f / 180.0f, + angles.y * 3.14159265358979323846f / 180.0f); + } + public SourceRadianEuler(SourceDegreeEuler angles) + { + Init(MathUtils.DEG2RAD(angles.x), MathUtils.DEG2RAD(angles.y), MathUtils.DEG2RAD(angles.z)); + } + + // Initialization + public void Init(float ix = 0.0f, float iy = 0.0f, float iz = 0.0f) { x = ix; y = iy; z = iz; } + + // conversion to qangle + public SourceQAngle ToQAngle() => new SourceQAngle(MathUtils.DEG2RAD(y), MathUtils.DEG2RAD(z), MathUtils.DEG2RAD(x)); + public bool IsValid() { throw new NotImplementedException(); } + public void Invalidate() { throw new NotImplementedException(); } + + public float Base() { return x; } + + // array access... + public float this[int i] + { + get + { + switch (i) + { + case 0: return x; + case 1: return y; + case 2: return z; + default: throw new Exception("wrong index [0..2]"); + } + } + set + { + switch (i) + { + case 0: + x = value; + break; + case 1: + y = value; + break; + case 2: + z = value; + break; + default: + throw new Exception("wrong index [0..2]"); + } + } + } + + public float x, y, z; + } +} diff --git a/Assets/Editor/SourceCommon/Vectors/SourceRadianEuler.cs.meta b/Assets/Editor/SourceCommon/Vectors/SourceRadianEuler.cs.meta new file mode 100644 index 0000000..87d6ede --- /dev/null +++ b/Assets/Editor/SourceCommon/Vectors/SourceRadianEuler.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b270d4664974df54fb6bd34c1e015b9e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor/SourceCommon/Vectors/SourceVector.cs b/Assets/Editor/SourceCommon/Vectors/SourceVector.cs new file mode 100644 index 0000000..4cd7004 --- /dev/null +++ b/Assets/Editor/SourceCommon/Vectors/SourceVector.cs @@ -0,0 +1,169 @@ +using System; + +namespace SourceFormatParser.Common +{ + /// + /// Vector x/y/z (float) + /// Size: 12 bytes (4 bytes per axis) + /// + public struct SourceVector + { + public float x, y, z; + + public SourceVector(float ix = 0.0f, float iy = 0.0f, float iz = 0.0f) + { + this.x = ix; + this.y = iy; + this.z = iz; + } + + // Initialization methods + public static SourceVector Random(float minVal, float maxVal) + { + Random rand = new Random(); + return new SourceVector( + ix: minVal + ((float)rand.NextDouble()) * (float)(maxVal - minVal), + iy: minVal + ((float)rand.NextDouble()) * (float)(maxVal - minVal), + iz: minVal + ((float)rand.NextDouble()) * (float)(maxVal - minVal) + ); + } + public void Zero() => x = y = z = 0.0f; ///< zero out a vector + + // equality + public static bool operator ==(SourceVector v1, SourceVector v2) => v1.x == v2.x && v1.y == v2.y && v1.z == v2.z; + public static bool operator !=(SourceVector v1, SourceVector v2) => !(v1 == v2); + + public override bool Equals(object obj) => this == (SourceVector)obj; + public override int GetHashCode() => base.GetHashCode(); + + // arithmetic operations + public static SourceVector operator +(SourceVector v1, SourceVector v2) => new SourceVector(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z); + public static SourceVector operator -(SourceVector v1, SourceVector v2) => new SourceVector(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z); + public static SourceVector operator *(SourceVector v1, SourceVector v2) => new SourceVector(v1.x * v2.x, v1.y * v2.y, v1.z * v2.z); + public static SourceVector operator *(SourceVector v, float s) => new SourceVector(v.x * s, v.y * s, v.z * s); + public static SourceVector operator /(SourceVector v1, SourceVector v2) + { + return new SourceVector( + ix: v2.x != 0.0f ? v1.x / v2.x : 0f, + iy: v2.y != 0.0f ? v1.y / v2.y : 0f, + iz: v2.z != 0.0f ? v1.z / v2.z : 0f + ); + } + public static SourceVector operator /(SourceVector v, float fl) + { + if (fl == 0.0f) + return new SourceVector(); + float oofl = 1.0f / fl; + return new SourceVector(v.x * oofl, v.y * oofl, v.z * oofl); + } + public static SourceVector operator +(SourceVector v, float s) => new SourceVector(v.x + s, v.y + s, v.z + s); //< broadcast add + public static SourceVector operator -(SourceVector v, float s) => new SourceVector(v.x - s, v.y - s, v.z - s); //< broadcast sub + + // negate the vector components + public void Negate() + { + x = -x; + y = -y; + z = -z; + } + + // Get the vector's magnitude. + public float Length() => (float)Math.Sqrt(x * x + y * y + z * z); + + // Get the vector's magnitude squared. + public float LengthSqr() => (x * x + y * y + z * z); + + // return true if this vector is (0,0,0) within tolerance + public bool IsZero(float tolerance = 0.01f) + { + return x > -tolerance && x < tolerance && + y > -tolerance && y < tolerance && + z > -tolerance && z < tolerance; + } + + public bool IsLengthGreaterThan(float val) => LengthSqr() > val * val; + public bool IsLengthLessThan(float val) => LengthSqr() < val * val; + + // check if a vector is within the box defined by two other vectors // check a point against a box + public bool WithinAABox(SourceVector boxmin, SourceVector boxmax) + { + return (x >= boxmin.x) && (x <= boxmax.x) && + (y >= boxmin.y) && (y <= boxmax.y) && + (z >= boxmin.z) && (z <= boxmax.z); + } + + // Get the distance from this vector to the other one. + public float DistTo(SourceVector vOther) + { + return new SourceVector( + ix: x - vOther.x, + iy: y - vOther.y, + iz: z - vOther.z + ).Length(); + } + + // Get the distance from this vector to the other one squared. + // NJS: note, VC wasn't inlining it correctly in several deeply nested inlines due to being an 'out of line' inline. + // may be able to tidy this up after switching to VC7 + public float DistToSqr(SourceVector vOther) + { + return new SourceVector( + ix: x - vOther.x, + iy: y - vOther.y, + iz: z - vOther.z + ).LengthSqr(); + } + + // Multiply, add, and assign to this (ie: *this = a + b * scalar). This + // is about 12% faster than the actual vector equation (because it's done per-component + // rather than per-vector). + public void MulAdd(SourceVector a, SourceVector b, float scalar) + { + x = a.x + b.x * scalar; + y = a.y + b.y * scalar; + z = a.z + b.z * scalar; + } + + // Dot product. + public float Dot(SourceVector vOther) => (x * vOther.x + y * vOther.y + z * vOther.z); + + + // 2d + public float Length2D() => (float)Math.Sqrt(Length2DSqr()); + public float Length2DSqr() => (x * x + y * y); + + + // Cross product between two vectors. + public SourceVector Cross(SourceVector vOther) + { + return new SourceVector( + ix: y * vOther.z - z * vOther.y, + iy: z * vOther.x - x * vOther.z, + iz: x * vOther.y - y * vOther.x + ); + } + + // Returns a vector with the min or max in X, Y, and Z. + public SourceVector Min(SourceVector vOther) + { + return new SourceVector(x < vOther.x ? x : vOther.x, + y < vOther.y ? y : vOther.y, + z < vOther.z ? z : vOther.z); + } + public SourceVector Max(SourceVector vOther) + { + return new SourceVector(x > vOther.x ? x : vOther.x, + y > vOther.y ? y : vOther.y, + z > vOther.z ? z : vOther.z); + } + + public override string ToString() => $"{{{x}; {y}; {z}}}"; + + public static SourceVector Empty => new SourceVector(); +#if (UNITY) + public UnityEngine.Vector3 toVector3() => new UnityEngine.Vector3(x, y, z); +#else + public System.Numerics.Vector3 toVector3() => new System.Numerics.Vector3(x, y, z); +#endif + } +} diff --git a/Assets/Editor/SourceCommon/Vectors/SourceVector.cs.meta b/Assets/Editor/SourceCommon/Vectors/SourceVector.cs.meta new file mode 100644 index 0000000..4c44821 --- /dev/null +++ b/Assets/Editor/SourceCommon/Vectors/SourceVector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cb2fb64018589c94bb555489a6bf3de0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor/SourceCommon/Vectors/SourceVector2.cs b/Assets/Editor/SourceCommon/Vectors/SourceVector2.cs new file mode 100644 index 0000000..06fa032 --- /dev/null +++ b/Assets/Editor/SourceCommon/Vectors/SourceVector2.cs @@ -0,0 +1,131 @@ +using System; + +namespace SourceFormatParser.Common +{ + /// + /// Vector x/y (float) + /// Size: 8 bytes (4 bytes per axis). + /// Is Vector2D in Source Engine. + /// + public struct SourceVector2 + { + public float x, y; + + public SourceVector2(float ix = 0.0f, float iy = 0.0f) + { + this.x = ix; + this.y = iy; + } + + // Initialization methods + public static SourceVector2 Random(float minVal, float maxVal) + { + Random rand = new Random(); + return new SourceVector2( + ix: minVal + ((float)rand.NextDouble()) * (float)(maxVal - minVal), + iy: minVal + ((float)rand.NextDouble()) * (float)(maxVal - minVal) + ); + } + + // equality + public static bool operator ==(SourceVector2 v1, SourceVector2 v2) => v1.x == v2.x && v1.y == v2.y; + public static bool operator !=(SourceVector2 v1, SourceVector2 v2) => !(v1 == v2); + + public override bool Equals(object obj) => this == (SourceVector2)obj; + public override int GetHashCode() => base.GetHashCode(); + + // arithmetic operations + public static SourceVector2 operator +(SourceVector2 v1, SourceVector2 v2) => new SourceVector2(v1.x + v2.x, v1.y + v2.y); + public static SourceVector2 operator -(SourceVector2 v1, SourceVector2 v2) => new SourceVector2(v1.x - v2.x, v1.y - v2.y); + public static SourceVector2 operator *(SourceVector2 v1, SourceVector2 v2) => new SourceVector2(v1.x * v2.x, v1.y * v2.y); + public static SourceVector2 operator *(SourceVector2 v, float s) => new SourceVector2(v.x * s, v.y * s); + public static SourceVector2 operator /(SourceVector2 v1, SourceVector2 v2) + { + return new SourceVector2( + ix: v2.x != 0.0f ? v1.x / v2.x : 0f, + iy: v2.y != 0.0f ? v1.y / v2.y : 0f + ); + } + public static SourceVector2 operator /(SourceVector2 v, float fl) + { + if (fl == 0.0f) + return new SourceVector2(); + float oofl = 1.0f / fl; + return new SourceVector2(v.x * oofl, v.y * oofl); + } + + // negate the Vector2D components + public void Negate() + { + x = -x; + y = -y; + } + + // Get the Vector2D's magnitude. + public float Length() => (float)Math.Sqrt(LengthSqr()); + + // Get the Vector2D's magnitude squared. + public float LengthSqr() => (x * x + y * y); + + // return true if this vector is (0,0) within tolerance + public bool IsZero(float tolerance = 0.01f) + { + return x > -tolerance && x < tolerance && + y > -tolerance && y < tolerance; + } + + // Compare length. + public bool IsLengthGreaterThan(float val) => LengthSqr() > val * val; + public bool IsLengthLessThan(float val) => LengthSqr() < val * val; + + // Get the distance from this Vector2D to the other one. + public float DistTo(SourceVector2 vOther) + { + return new SourceVector2( + ix: x - vOther.x, + iy: y - vOther.y + ).Length(); + } + + // Get the distance from this Vector2D to the other one squared. + public float DistToSqr(SourceVector2 vOther) + { + return new SourceVector2( + ix: x - vOther.x, + iy: y - vOther.y + ).LengthSqr(); + } + + // Multiply, add, and assign to this (ie: *this = a + b * scalar). This + // is about 12% faster than the actual Vector2D equation (because it's done per-component + // rather than per-Vector2D). + public void MulAdd(SourceVector2 a, SourceVector2 b, float scalar) + { + x = a.x + b.x * scalar; + y = a.y + b.y * scalar; + } + + // Dot product. + public float Dot(SourceVector2 vOther) => (x * vOther.x + y * vOther.y); + + // Returns a SourceVector2 with the min or max in X, Y, and Z. + public SourceVector2 Min(SourceVector2 vOther) + { + return new SourceVector2(x < vOther.x ? x : vOther.x, + y < vOther.y ? y : vOther.y); + } + public SourceVector2 Max(SourceVector2 vOther) + { + return new SourceVector2(x > vOther.x ? x : vOther.x, + y > vOther.y ? y : vOther.y); + } + + public override string ToString() => $"{{{x}; {y}}}"; + +#if (UNITY) + public UnityEngine.Vector2 toVector2() => new UnityEngine.Vector2(x, y); +#else + public System.Numerics.Vector2 toVector2() => new System.Numerics.Vector2(x, y); +#endif + } +} diff --git a/Assets/Editor/SourceCommon/Vectors/SourceVector2.cs.meta b/Assets/Editor/SourceCommon/Vectors/SourceVector2.cs.meta new file mode 100644 index 0000000..c4beac5 --- /dev/null +++ b/Assets/Editor/SourceCommon/Vectors/SourceVector2.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 01a389a372b218e4badb9aa349210a72 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor/SourceCommon/Vectors/SourceVector2Int.cs b/Assets/Editor/SourceCommon/Vectors/SourceVector2Int.cs new file mode 100644 index 0000000..24f25bb --- /dev/null +++ b/Assets/Editor/SourceCommon/Vectors/SourceVector2Int.cs @@ -0,0 +1,25 @@ +namespace SourceFormatParser.Common +{ + /// + /// Vector x/y (int) + /// Size: 8 bytes (4 bytes per axis) + /// + public struct SourceVector2Int + { + public int x, y; + + public SourceVector2Int(int x, int y) + { + this.x = x; + this.y = y; + } + + public override string ToString() => $"{{{x}; {y}}}"; + +#if (UNITY) + public UnityEngine.Vector2 toVector2() => new UnityEngine.Vector2(x, y); +#else + public System.Numerics.Vector2 toVector2() => new System.Numerics.Vector2(x, y); +#endif + } +} diff --git a/Assets/Editor/SourceCommon/Vectors/SourceVector2Int.cs.meta b/Assets/Editor/SourceCommon/Vectors/SourceVector2Int.cs.meta new file mode 100644 index 0000000..54ae577 --- /dev/null +++ b/Assets/Editor/SourceCommon/Vectors/SourceVector2Int.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ee4829acf0c1cc741af51994378390ae +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor/SourceCommon/Vectors/SourceVector2Short.cs b/Assets/Editor/SourceCommon/Vectors/SourceVector2Short.cs new file mode 100644 index 0000000..2b3b5bf --- /dev/null +++ b/Assets/Editor/SourceCommon/Vectors/SourceVector2Short.cs @@ -0,0 +1,25 @@ +namespace SourceFormatParser.Common +{ + /// + /// Vector x/y (short) + /// Size: 4 bytes (2 bytes per axis) + /// + public struct SourceVector2Short + { + public short x, y; + + public SourceVector2Short(short x, short y) + { + this.x = x; + this.y = y; + } + + public override string ToString() => $"{{{x}; {y}}}"; + +#if (UNITY) + public UnityEngine.Vector2 toVector2() => new UnityEngine.Vector2(x, y); +#else + public System.Numerics.Vector2 toVector2() => new System.Numerics.Vector2(x, y); +#endif + } +} diff --git a/Assets/Editor/SourceCommon/Vectors/SourceVector2Short.cs.meta b/Assets/Editor/SourceCommon/Vectors/SourceVector2Short.cs.meta new file mode 100644 index 0000000..c118c8d --- /dev/null +++ b/Assets/Editor/SourceCommon/Vectors/SourceVector2Short.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 885618187896fa349b2d688f7f4e562d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor/SourceCommon/Vectors/SourceVector4.cs b/Assets/Editor/SourceCommon/Vectors/SourceVector4.cs new file mode 100644 index 0000000..6d3b1d2 --- /dev/null +++ b/Assets/Editor/SourceCommon/Vectors/SourceVector4.cs @@ -0,0 +1,27 @@ +namespace SourceFormatParser.Common +{ + /// + /// Vector x/y/z/w (float) + /// Size: 16 bytes (4 bytes per axis) + /// + public struct SourceVector4 + { + public float x, y, z, w; + + public SourceVector4(float x, float y, float z, float w) + { + this.x = x; + this.y = y; + this.z = z; + this.w = w; + } + + public override string ToString() => $"{{{x}; {y}; {z}; {w}}}"; + +#if (UNITY) + public UnityEngine.Vector4 toVector4() => new UnityEngine.Vector4(x, y, z, w); +#else + public System.Numerics.Vector4 toVector4() => new System.Numerics.Vector4(x, y, z, w); +#endif + } +} diff --git a/Assets/Editor/SourceCommon/Vectors/SourceVector4.cs.meta b/Assets/Editor/SourceCommon/Vectors/SourceVector4.cs.meta new file mode 100644 index 0000000..890b7c2 --- /dev/null +++ b/Assets/Editor/SourceCommon/Vectors/SourceVector4.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 90caee6c805baba4c9e44f68259e1f98 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor/SourceCommon/Vectors/SourceVectorShort.cs b/Assets/Editor/SourceCommon/Vectors/SourceVectorShort.cs new file mode 100644 index 0000000..4610c13 --- /dev/null +++ b/Assets/Editor/SourceCommon/Vectors/SourceVectorShort.cs @@ -0,0 +1,26 @@ +namespace SourceFormatParser.Common +{ + /// + /// Vector x/y/z (short) + /// Size: 6 bytes (2 bytes per axis) + /// + public struct SourceVectorShort + { + public short x, y, z; + + public SourceVectorShort(short x, short y, short z) + { + this.x = x; + this.y = y; + this.z = z; + } + + public override string ToString() => $"{{{x}; {y}; {z}}}"; + +#if (UNITY) + public UnityEngine.Vector3 toVector3() => new UnityEngine.Vector3(x, y, z); +#else + public System.Numerics.Vector3 toVector3() => new System.Numerics.Vector3(x, y, z); +#endif + } +} diff --git a/Assets/Editor/SourceCommon/Vectors/SourceVectorShort.cs.meta b/Assets/Editor/SourceCommon/Vectors/SourceVectorShort.cs.meta new file mode 100644 index 0000000..dd1bdd9 --- /dev/null +++ b/Assets/Editor/SourceCommon/Vectors/SourceVectorShort.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d9246da7cb8798c4db4f0fef0e99ee3e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor/SourceCommon/packages.config b/Assets/Editor/SourceCommon/packages.config new file mode 100644 index 0000000..9458181 --- /dev/null +++ b/Assets/Editor/SourceCommon/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Assets/Editor/SourceCommon/packages.config.meta b/Assets/Editor/SourceCommon/packages.config.meta new file mode 100644 index 0000000..9bdd017 --- /dev/null +++ b/Assets/Editor/SourceCommon/packages.config.meta @@ -0,0 +1,32 @@ +fileFormatVersion: 2 +guid: 9c82ed86e9a503847b7746c3248a744f +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + Windows Store Apps: WindowsStoreApps + second: + enabled: 1 + settings: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor/SourceImportConfig.cs b/Assets/Editor/SourceImportConfig.cs new file mode 100644 index 0000000..67b2e37 --- /dev/null +++ b/Assets/Editor/SourceImportConfig.cs @@ -0,0 +1,8 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class SourceImportConfig +{ + public static float WorldScale = 0.0254f; +} diff --git a/Assets/Editor/SourceImportConfig.cs.meta b/Assets/Editor/SourceImportConfig.cs.meta new file mode 100644 index 0000000..e3b44c6 --- /dev/null +++ b/Assets/Editor/SourceImportConfig.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a8439989f1f3f154cb37486a7ba1fc3d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor/SourceKV.cs b/Assets/Editor/SourceKV.cs new file mode 100644 index 0000000..d89c474 --- /dev/null +++ b/Assets/Editor/SourceKV.cs @@ -0,0 +1,132 @@ +using System.Collections.Generic; + +namespace SourceFormatParser +{ + /// + /// Parses Valve's KV file. + /// Example of KV file: + /// { + /// "key" "value" + /// } + /// + public struct SourceKV + { + public string originalKV; + + private bool fullyParsed; + private Dictionary temp_kv; + private bool ignoreBranches; + private string[] lines; + + /// Ignore '{' and '}' + public SourceKV(string kv, bool ignoreBranches = false) + { + this.fullyParsed = false; + this.temp_kv = new Dictionary(); + this.originalKV = kv.ToLowerInvariant(); + if (originalKV.Contains("\n")) + this.lines = originalKV.Split('\n'); + else + this.lines = new string[1] { originalKV }; + this.ignoreBranches = ignoreBranches; + } + + public string getByKey(string key) + { + key = key.ToLowerInvariant(); + + //search in temp + if (temp_kv.ContainsKey(key)) + return temp_kv[key]; + + //parse kvs + if (!fullyParsed) + { + int lvl = 0; + bool isStarted = ignoreBranches; + foreach (string l in lines) + { + if (l.Length == 0) continue; + if (isStarted) + { + if (l[0] == '}') + { + if (lvl == 0) + { + fullyParsed = true; + break; + } + else + lvl--; + } + else if (l.Contains("\"")) + { + string _l = l; + if (_l.Contains("//")) + _l = _l.Split(new string[1] { "//" }, System.StringSplitOptions.None)[0]; + string[] _kvs = _l.Split('\"'); // 0 "1" 2 "3" 4 + if (_kvs.Length < 5) continue; + string k = _kvs[1], v = _kvs[3]; + if (key == _kvs[1]) + { + temp_kv.Add(k, v); + return v; + } + } + } + else + { + if (l[0] == '{') + isStarted = true; + } + } + } + return null; //not found key + } + + public Dictionary getAll() + { + //parse kvs + if (!fullyParsed) + { + int lvl = 0; + bool isStarted = ignoreBranches; + foreach (string l in lines) + { + if (l.Length == 0) continue; + if (isStarted) + { + if (l[0] == '}') + { + if (lvl == 0) + { + fullyParsed = true; + break; + } + else + lvl--; + } + else if (l[0] == '{') + lvl++; + else if (l.Contains("\"")) + { + + string[] _kvs = l.Split('\"'); // 0 "1" 2 "3" 4 + if (_kvs.Length < 5) continue; + string k = _kvs[1], v = _kvs[3]; + if (!temp_kv.ContainsKey(k)) + temp_kv.Add(k, v); + } + } + else + { + if (l[0] == '{') + isStarted = true; + } + } + } + return temp_kv; + } + + } +} diff --git a/Assets/Editor/SourceKV.cs.meta b/Assets/Editor/SourceKV.cs.meta new file mode 100644 index 0000000..5271c85 --- /dev/null +++ b/Assets/Editor/SourceKV.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3951dddaed08494488030967cfb392cb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor/SourceMDLStructs.cs b/Assets/Editor/SourceMDLStructs.cs new file mode 100644 index 0000000..b403c0a --- /dev/null +++ b/Assets/Editor/SourceMDLStructs.cs @@ -0,0 +1,574 @@ +using System; +using UnityEngine; + +namespace uSrcTools +{ +class SourceMDLStructs +{ + public const int MAX_NUM_BONES_PER_VERT = 3; +} + +[Serializable] +public struct studiohdr_t +{ + public char[] id;//4 + public int version; + + public int checksum; // this has to be the same in the phy and vtx files to load! + + public string Name;//64 + public int length; // Data size of MDL file in bytes. + + public Vector3 eyeposition; + public Vector3 illumposition; + public Vector3 hullmin; + public Vector3 hullmax; + public Vector3 view_bbmin; + public Vector3 view_bbmax; + + public int flags; + + public int bonesnum; + public int boneoffs; + + public int bonecontrollernum; + public int bonecontrolleroffs; + + public int hitboxnum; + public int hitboxoffs; + + public int localanimnum; + public int localanimoffs; + + public int localseqnum; + public int localseqoffs; + + public int activitylistversion; + public int eventsindexed; + + public int texturenum; + public int textureoffs; + + public int texturedirnum; + public int texturediroffs; + + public int skinrefnum; + public int skinfamilynum; + public int skinfamilyoffs; + + public int bodypartnum; + public int bodypartoffs; + + public int attachmentnum; + public int attachmentoffs; + + public int localnodenum; + public int localnodeoffs; + public int localnodenameoffs; + + public int flexdescnum; + public int flexdescoffs; + + public int flexcontrollernum; + public int flexcontrolleroffs; + + public int flexrulesnum; + public int flexrulesoffs; + + public int ikchainnum; + public int ikchainoffs; + + public int mouthsnum; + public int mouthsoffs; + + public int localposeparamnum; + public int localposeparamoffs; + + public int surfacepropoffs; + + public int keyvalueoffs; + public int keyvaluenum; + + public int iklocknum; + public int iklockoffs; + + public float mass; + public int contents; + + public int includemodelnum; + public int includemodeloffs; + + public int virtualModel; + + public int animblocksnameoffs; + public int animblocksnum; + public int animblocksoffs; + + public int animblockModel; + + public int bonetablenameoffs; + + public int vertex_base; + public int offset_base; + + public byte directionaldotproduct; + + public byte rootLod; + + public byte numAllowedRootLods; + + public byte unused; + + public int unused1; + + public int flexcontrolleruinum; + public int flexcontrolleruioffs; + + public long unused2; + + public int studiohdr2offs; + + public int unused3; +} + +struct studiohdr2_t +{ + public int srcbonetransformnum; + public int srcbonetransformoffs; + + public int illumpositionattachmentindex; + + public float flMaxEyeDeflection; + + public int linearbone_index; + + public int[] unknown;//64 +} + +[Serializable] +public struct studiobone_t +{ + public string pszName; + public int sznameindex; + //inline char * const pszName( void ) const { return ((char *)this) + sznameindex; } + public int parent; // parent bone + public int[] bonecontroller;//[6]; // bone controller index, -1 == none + + // default values + public Vector3 pos; + public Quaternion quat; + public /*RadianEuler*/Vector3 rot; + // compression scale + public Vector3 posscale; + public Vector3 rotscale; + + public /*matrix3x4_t*/float[] poseToBone; //12 + public Quaternion qAlignment; + public int flags; + public int proctype; + public int procindex; // procedural rule + public /*mutable*/ int physicsbone; // index into physically simulated bone + //inline void *pProcedure( ) const { if (procindex == 0) return NULL; else return (void *)(((byte *)this) + procindex); }; + public int surfacepropidx; // index into string tablefor property name + //inline char * const pszSurfaceProp( void ) const { return ((char *)this) + surfacepropidx; } + public int contents; // See BSPFlags.h for the contents flags + + //public int[] unused;//[8]; // remove as appropriate + + //public mstudiobone_t(){} +}; + +[Serializable] +public struct studiobodypart +{ + public string name; + // + public int nameindex; + public int nummodels; + public int base_; + public int modelindex; + + public studiomodel[] models; + + public studiobodypart(int nameindex,int nummodels,int base_,int modelindex) + { + this.nameindex=nameindex; + this.nummodels=nummodels; + this.base_=base_; + this.modelindex = modelindex; + + this.models = new studiomodel[nummodels]; + this.name = ""; + } +} + +[Serializable] +public struct studiomodel //148 byte +{ + public string name; //64 + public int type; + public float boundingradius; + public int meshnum; + public int meshoffs; + public int verticesnum; + public int verticesoffs; + public int tangentsoffs; + public int attachmentnum; + public int attachmentoffs; + public int eyeballnum; + public int eyeballoffs; + public mstudio_modelvertexdata_t vertexdata; + //skip 32 + + // + public studiomesh[] meshes; + // + + public studiomodel( string name,int type,float boundingradius,int meshnum,int meshoffs, + int verticesnum,int verticesoffs,int tangentsoffs,int attachmentnum, + int attachmentoffs,int eyeballnum,int eyeballoffs,mstudio_modelvertexdata_t vd) + { + this.name=name; + this.type=type; + this.boundingradius=boundingradius; + this.meshnum = meshnum; + this.meshoffs=meshoffs; + this.verticesnum=verticesnum; + this.verticesoffs=verticesoffs; + this.tangentsoffs=tangentsoffs; + this.attachmentnum=attachmentnum; + this.attachmentoffs=attachmentoffs; + this.eyeballnum=eyeballnum; + this.eyeballoffs=eyeballoffs; + this.vertexdata = vd; + + this.meshes = new studiomesh[meshnum]; + } +} + +public struct mstudio_modelvertexdata_t +{ + //Vector *Position( int i ) const; + //Vector *Normal( int i ) const; + //Vector4D *TangentS( int i ) const; + //Vector2D *Texcoord( int i ) const; + //mstudioboneweight_t *BoneWeights( int i ) const; + //mstudiovertex_t *Vertex( int i ) const; + //bool HasTangentData( void ) const; + //int GetGlobalVertexIndex( int i ) const; + //int GetGlobalTangentIndex( int i ) const; + + // base of external vertex data stores + //const void *pVertexData; + //const void *pTangentData; + public int pVertexData; + public int pTangentData; + + public mstudio_modelvertexdata_t(int vd,int td) + { + pVertexData = vd; + pTangentData = td; + } +} + +[Serializable] +public struct studiomesh +{ + public int material; + + public int modelindex; + + public int vertexnum; // number of unique vertices/normals/texcoords + public int vertexoffs; // vertex mstudiovertex_t + + public int flexenum; // vertex animation + public int flexoffs; + + // special codes for material operations + public int materialtype; + public int materialparam; + + // a unique ordinal for this mesh + public int meshid; + + public Vector3 center; + + public studio_meshvertexdata vertexdata; + + //public int[] unused;//8 // remove as appropriate + //32 skip + + public studiomesh(int material, int modelindex, int vertexnum, int vertexoffs, + int flexenum, int flexoffs, int materialtype, int materialparam, + int meshid, Vector3 center, studio_meshvertexdata vertexdata) + { + this.material=material; + this.modelindex=modelindex; + this.vertexnum=vertexnum; // number of unique vertices/normals/texcoords + this.vertexoffs=vertexoffs; // vertex mstudiovertex_t + this.flexenum=flexenum; // vertex animation + this.flexoffs=flexoffs; + this.materialtype=materialtype; + this.materialparam=materialparam; + this.meshid=meshid; + this.center=center; + this.vertexdata=vertexdata; + } +} + +[Serializable] +public struct studio_meshvertexdata +{ + public int skip; //4 + public int[] numLODVertexes;//8 + + public studio_meshvertexdata(int skip, int[] numLODVertices) + { + this.skip=skip; + this.numLODVertexes = numLODVertices; + } +} + +[Serializable] +public struct studiotexture_t +{ + public string textureName; + // + + public int name_offset; + public int flags; + public int used; + + public int unused; + + public int material; + public int client_material; + + public int[] unused2;//10 +}//64 + +public struct studioboneweight +{ + public float[] weight; //3 + public byte[] bone; //3 + public byte numbones; + + // byte material; + // short firstref; + // short lastref; +} + +struct studiovertex +{ + public studioboneweight BoneWeights; + public Vector3 vecPosition; + public Vector3 vecNormal; + public Vector2 vecTexCoord; +} + +struct studioiface +{ + public ushort a,b,c;// Indices to vertices +} + +//======================================================================= +//=======================VVD============================================= +//======================================================================= + +[Serializable] +public struct vvdheader +{ + public char[] id;//4 + public int version; + public int checksum; + public int numLODs; + public int[] numLODVertexes;//8 + public int numFixup; + public int fixupTableStart; + public int vertexDataStart; + public int tangentDataStart; +} + +public struct vertexFileFixup +{ + public int lod; // used to skip culled root lod + public int sourceVertexID; // absolute index from start of vertex/tangent blocks + public int numVertexes; + + public vertexFileFixup(int l, int s, int n) + { + lod = l; + sourceVertexID = s; + numVertexes = n; + } +} + +//=========================================================================== +//===========================VTX============================================= +//=========================================================================== + +[Serializable] +public struct vtxHeader +{ + public int version; + public int vertCacheSize; + public short maxBonePerStrip; + public short maxBonePerTri; + public int maxBonePerVert; + public int checksum; + public int numLODs; + public int materialReplacementListOffset; + public int numBobyParts; + public int bodyPartOffset; +} + +[Serializable] +public struct vtxBodypartHeader +{ + public int numModels; + public int modelsOffset; + + // + public vtxModelHeader[] models; + + public vtxBodypartHeader(int numModels, int modelsOffset) + { + this.numModels=numModels; + this.modelsOffset=modelsOffset; + + this.models=new vtxModelHeader[numModels]; + } +} + +[Serializable] +public struct vtxModelHeader +{ + public int numLODs; + public int LODOffset; + + // + public vtxModelLODheader[] lods; + + public vtxModelHeader(int numLODs, int LODOffset) + { + this.numLODs=numLODs; + this.LODOffset=LODOffset; + + this.lods=new vtxModelLODheader[numLODs]; + } +} + +[Serializable] +public struct vtxModelLODheader +{ + public int numMeshes; + public int meshOffset; + public float switchPoint; + + // + public vtxMeshHeader[] meshes; + + public vtxModelLODheader(int numMeshes, int meshOffset, float switchPoint) + { + this.numMeshes = numMeshes; + this.meshOffset = meshOffset; + this.switchPoint = switchPoint; + this.meshes = new vtxMeshHeader[numMeshes]; + } +} + +[Serializable] +public struct vtxMeshHeader +{ + public int numStripGroups; + public int stripGroupHeaderOffset; + public byte flags; + + // + public vtxStripGroupHeader[] stripGroups; + + public vtxMeshHeader(int numStripGroups, int stripGroupHeaderOffset, byte flags) + { + this.numStripGroups = numStripGroups; + this.stripGroupHeaderOffset = stripGroupHeaderOffset; + this.flags = flags; + this.stripGroups = new vtxStripGroupHeader[numStripGroups]; + } +} + +[Serializable] +public struct vtxStripGroupHeader +{ + public int numVerts; + public int vertOffset; + public int numIndices; + public int indexOffs; + public int numStrips; + public int stripOffset; + public byte flags; + + public vtxVertex[] verts; + public ushort[] indexArray; + public vtxStripHeader[] strips; + + public vtxStripGroupHeader(int numVerts, int vertOffset, int numIndices,int indexOffs, + int numStrips,int stripOffset,byte flags) + { + this.numVerts = numVerts; + this.vertOffset = vertOffset; + this.numIndices = numIndices; + this.indexOffs = indexOffs; + this.numStrips = numStrips; + this.flags = flags; + this.stripOffset = stripOffset; + + this.verts = new vtxVertex[numVerts]; + this.indexArray = new ushort[numIndices]; + this.strips = new vtxStripHeader[numStrips]; + } +} + +[Serializable] +public struct vtxVertex +{ + public byte[] boneWeightIndex;//3 + public byte numBones; + public int origMeshVertID; + public byte[] boneID;//3 + + public vtxVertex(byte[] boneWeightIndex, byte numBones, + ushort origMeshVertID, byte[] boneID) + { + this.boneWeightIndex = boneWeightIndex; + this.numBones = numBones; + this.origMeshVertID = (int)origMeshVertID; + this.boneID = boneID; + } +} + +[Serializable] +public struct vtxStripHeader +{ + public int numIndices; + public int indexOffset; + public int numVerts; + public int vertOffset; + public short numBones; + public byte flags; + public int numBoneStateChange; + public int boneStateChangeOffset; + + public vtxStripHeader(int numIndices, int indexOffset,int numVerts, int vertOffset, + short numBones, byte flags, int numBoneStateChange, int boneStateChangeOffset) + { + this.numIndices = numIndices; + this.indexOffset = indexOffset; + this.numVerts = numVerts; + this.vertOffset = vertOffset; + this.numBones = numBones; + this.flags = flags; + this.numBoneStateChange = numBoneStateChange; + this.boneStateChangeOffset = boneStateChangeOffset; + } +} +} \ No newline at end of file diff --git a/Assets/Editor/SourceMDLStructs.cs.meta b/Assets/Editor/SourceMDLStructs.cs.meta new file mode 100644 index 0000000..f80e588 --- /dev/null +++ b/Assets/Editor/SourceMDLStructs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e0993b0922766a842bf617b238479b21 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor/SourceStudioModel.cs b/Assets/Editor/SourceStudioModel.cs new file mode 100644 index 0000000..bbb2bd7 --- /dev/null +++ b/Assets/Editor/SourceStudioModel.cs @@ -0,0 +1,1436 @@ +using UnityEngine; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using UnityEditor; +using System; + +namespace uSrcTools +{ + + [System.Serializable] + public class SourceStudioModel// : MonoBehaviour + { + public string curModelName; + + public studiohdr_t mdlHeader; + public vvdheader vvdHeader; + public vtxHeader vtxHeader; + + public int lodLevel=0; + int skin; + int numSkinRefs; + public int submeshCount=0; + public Material tempMat; + + public int vertCount; + public Vector3[] vertArray; + public Vector3[] Normals; + public Vector2[] UV; + public BoneWeight[] boneWeights; + public int[] indexArray; + public Dictionary trisArrays; + + public studiobone_t[] mdlBones; + + public studiobodypart[] mdlBodyParts; + + public vtxBodypartHeader[] vtxBodyParts; + + public studiotexture_t[] mdlTextures; + public string[] mdlTexturePaths; + public short[] mdlSkinFamilies; + + public Transform[] Bones; + Mesh modelMesh; + bool used; + public bool loaded=false; + public bool drawArmature=false; + Material[] TempMats; + + public SourceStudioModel Load(string path, Func openFileCallback) + { + + curModelName = path; + //studiobodypart[] mdlBodyParts; + if (!ParseMdl (path, openFileCallback)) + { + return null; + } + + LoadSkin (0); + + //public int vertCount; + //Vector3[] vertArray; + //Vector3[] Normals; + //Vector2[] UV; + //int[] indexArray; + + + ParseVvd (path, openFileCallback); + + ParseVtx (path, openFileCallback); + + loaded = true; + + return this; + } +/* + public void GetInstance(GameObject go, bool skinned) + { + BuildMeshObject (curModelName, go,skinned); + } + + public void GetInstance(GameObject go) + { + BuildMeshObject (curModelName, go,false); + }*/ + + public void GetInstance(GameObject go, bool skinned,int bp) + { + BuildMeshObject (curModelName, go, skinned,bp); + } + + public void OnDrawGizmos() + { + /*for (int i=0; i=0) + { + bone.transform.SetParent(Bones[mdlBones[i].parent]); + } + else + { + bone.transform.SetParent(go.transform); + } + Vector3 temp=Vector3.zero; + //if(i==0) + temp=new Vector3(mdlBones[i].pos.x,mdlBones[i].pos.z,mdlBones[i].pos.y); + //else + // temp=new Vector3(mdlBones[i].pos.x,mdlBones[i].pos.y,-mdlBones[i].pos.z); + + bone.transform.localPosition=temp * SourceImportConfig.WorldScale; + Vector3 rot=new Vector3(-mdlBones[i].rot.x*Mathf.Rad2Deg,-mdlBones[i].rot.z*Mathf.Rad2Deg,-mdlBones[i].rot.y*Mathf.Rad2Deg); + bone.transform.localEulerAngles=rot; + Bones[i]=bone.transform; + } + + if (skinned) + { + go.AddComponent ().mesh = modelMesh; + SkinnedMeshRenderer smr = go.AddComponent (); + smr.material = tempMat; + smr.sharedMesh = modelMesh; + smr.bones=Bones; + smr.rootBone=Bones[0]; + smr.updateWhenOffscreen=true; + + } + else + { + go.AddComponent ().mesh = modelMesh; + go.AddComponent ().material = tempMat; + } + return; + } + + //========================================================== + Bones = new Transform[mdlHeader.bonesnum]; + for (int i=0; i=0) + { + bone.transform.SetParent(Bones[mdlBones[i].parent]); + } + else + { + bone.transform.SetParent(go.transform); + } + Vector3 temp=Vector3.zero; + //if(i==0) + temp=new Vector3(mdlBones[i].pos.x,mdlBones[i].pos.z,mdlBones[i].pos.y); + //else + // temp=new Vector3(mdlBones[i].pos.x,mdlBones[i].pos.y,-mdlBones[i].pos.z); + + bone.transform.localPosition=temp* SourceImportConfig.WorldScale; + Vector3 rot=new Vector3(-mdlBones[i].rot.x*Mathf.Rad2Deg,-mdlBones[i].rot.z*Mathf.Rad2Deg,-mdlBones[i].rot.y*Mathf.Rad2Deg); + bone.transform.localEulerAngles=rot; + Bones[i]=bone.transform; + } + //============================================================================================ + + string materialName=""; + + /*if(mdlTexturePaths.Length==1) + { + materialName += mdlTexturePaths[0]; + materialName += mdlTextures[mdlBodyParts[0].models[0].meshes[0].material].textureName; + } + else + { + string path = ResourceManager.GetPath ("materials/"+mdlTexturePaths[0] + +mdlTextures[mdlBodyParts[0].models[0].meshes[0].material].textureName+".vmt"); + + if(path==null) + { + Debug.Log ("Try second path"); + path = ResourceManager.GetPath ("materials/"+mdlTexturePaths[1] + +mdlTextures[mdlBodyParts[0].models[0].meshes[0].material].textureName+".vmt"); + if(path!=null) + { + materialName=mdlTexturePaths[1] + +mdlTextures[mdlBodyParts[0].models[0].meshes[0].material].textureName; + } + } + } + + if (uSrcSettings.Inst.textures) + tempMat = ResourceManager.Inst.GetMaterial (materialName); + else + tempMat = Test.Inst.testMaterial;*/ + + //TODO: restore mat system + var matPath = AssetDatabase.FindAssets("DefaultBspMaterial"); + var assetPath = AssetDatabase.GUIDToAssetPath(matPath[0]); + tempMat = AssetDatabase.LoadAssetAtPath(assetPath); + + //============================================================================================ + + //GameObject testMesh = new GameObject (curModelName); + //testMesh.transform.position = position; + modelMesh = new Mesh (); + modelMesh.name = curModelName; + + modelMesh.vertices = vertArray; + modelMesh.normals = Normals; + modelMesh.uv = UV; + modelMesh.boneWeights = boneWeights; + //====================================================== + Matrix4x4[] bindPoses = new Matrix4x4[Bones.Length]; + for (int i = 0; i < bindPoses.Length; i++) + { + //Bones[i].localPosition = Vector3.zero; + bindPoses[i] = Bones[i].worldToLocalMatrix * go.transform.localToWorldMatrix; + } + modelMesh.bindposes = bindPoses; + + //==================================================================== + //Debug.Log (indexArray.Length+" indices"); + + modelMesh.triangles = indexArray; + /* + int numMeshes = vtxBodyParts [0].models [0].lods [lodLevel].numMeshes; + modelMesh.subMeshCount = numMeshes; + int indexCount = 0; + int indexOffset = 0; + for(int i=0; i ().mesh = modelMesh; + SkinnedMeshRenderer smr = go.AddComponent (); + smr.material = tempMat; + smr.sharedMesh = modelMesh; + smr.bones=Bones; + smr.rootBone=Bones[0]; + smr.updateWhenOffscreen=true; + } else + { + go.AddComponent ().mesh = modelMesh; + go.AddComponent ().material = tempMat; + } + + for (int i=0; i ().mesh = mesh; + //meshObj.AddComponent ().material = tempMat; + } + } + }*/ + + used = true; + } + + void BuildMeshObject(string modelName, GameObject go, bool skinned,int bp) + { + if (!loaded) + { + Debug.LogWarning("Can't get Instance of model "+modelName+" because it's not loaded"); + return; + } + + if(skinned) + { + Bones = new Transform[mdlHeader.bonesnum]; + for (int i=0; i=0) + { + bone.transform.SetParent(Bones[mdlBones[i].parent]); + } + else + { + bone.transform.SetParent(go.transform); + } + Vector3 temp=Vector3.zero; + //if(i==0) + temp=new Vector3(mdlBones[i].pos.x,mdlBones[i].pos.z,mdlBones[i].pos.y); + //else + // temp=new Vector3(mdlBones[i].pos.x,mdlBones[i].pos.y,-mdlBones[i].pos.z); + + bone.transform.localPosition=temp*SourceImportConfig.WorldScale; + Vector3 rot=new Vector3(-mdlBones[i].rot.x*Mathf.Rad2Deg,-mdlBones[i].rot.z*Mathf.Rad2Deg,-mdlBones[i].rot.y*Mathf.Rad2Deg); + bone.transform.localEulerAngles=rot; + Bones[i]=bone.transform; + } + } + + if(!used) + { + modelMesh = new Mesh (); + modelMesh.name = curModelName; + + modelMesh.vertices = vertArray; + if(modelMesh.vertices.Length==0) + Debug.LogWarning ("Error with model "+modelName); + + modelMesh.normals = Normals; + modelMesh.uv = UV; + modelMesh.boneWeights = boneWeights; + + modelMesh.subMeshCount = submeshCount; + //Debug.Log ("submeshCount " + submeshCount); + //Debug.Log ("indexCount "+indexArray.Length); + //Debug.Log ("Bodypart count "+vtxBodyParts.Length); + int curmeshId=0; + int curIndexOffset = 0; + + + if(TempMats==null) + TempMats = new Material[submeshCount]; + + //for(int bpId=0; bpId(assetPath); + TempMats[curmeshId] = tempMat; + } + + for(int stripGroupId=0; stripGroupId(); + if(mf == null) { + mf = go.AddComponent(); + } + + mf.sharedMesh = modelMesh; + + + MeshRenderer mr = go.GetComponent (); + if(mr == null) { + mr = go.AddComponent(); + + } + mr.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.TwoSided; //Making model shadows two-sided for better quality. + + modelMesh.RecalculateBounds (); + mr.materials = TempMats; + mr.lightmapIndex = 255; + + used = true; + } + + + void LoadSkin(int skinId) + { + skin = skinId; + + int skinTableOffset=numSkinRefs * skinId; + for(int i=0; i openFileCallback) + { + BinaryReader BR = new BinaryReader (openFileCallback(name)); + + //studiohdr_t Header = ReadHeader (BR); + mdlHeader = ReadHeader (BR); + + if (new string(mdlHeader.id) != "IDST") + { + Debug.LogWarning ("Header id is not IDST"); + BR.BaseStream.Close (); + return false; + } + + + mdlBones = ReadStudioBones (BR,mdlHeader.boneoffs,mdlHeader.bonesnum); + + mdlTextures = ReadStudioTextures(BR,mdlHeader.textureoffs,mdlHeader.texturenum); + + mdlTexturePaths = ReadTexturePaths (BR, mdlHeader.texturediroffs, mdlHeader.texturedirnum); + + numSkinRefs = mdlHeader.skinrefnum; + mdlSkinFamilies = ReadSkinFamilies (BR,mdlHeader.skinfamilyoffs, mdlHeader.skinfamilynum,mdlHeader.skinrefnum); + + mdlBodyParts = ReadMdlBodyParts (BR, mdlHeader.bodypartoffs, mdlHeader.bodypartnum); + + //setRootLOD (mdlHeader, lodLevel); + + BR.BaseStream.Dispose (); + + return true; + } + + void setRootLOD(studiohdr_t hdr, int lod) + { + if (hdr.numAllowedRootLods > 0 && lod >= hdr.numAllowedRootLods) + { + lod=hdr.numAllowedRootLods-1; + } + + int vertexOffset=0; + + for (int bpId=0; bpId openFileCallback) + { + path = path.Replace (".mdl", ".vvd"); + + + //_vertArray = null; + //_Normals = null; + //_UV = null; + + BinaryReader BR = new BinaryReader (openFileCallback(path)); + + /*vvdheader */vvdHeader = ReadVvdHeader (BR); + + //VvdHeader = header; + + + vertexFileFixup[] fixupTable = null; + if (vvdHeader.numFixup > 0) + { + //Debug.Log ("VVD file have "+vvdHeader.numFixup +" fixups"); + BR.BaseStream.Seek(vvdHeader.fixupTableStart, SeekOrigin.Begin); + + fixupTable=new vertexFileFixup[vvdHeader.numFixup]; + + for (int i=0; i 0) + { + vertCount = vvdHeader.numLODVertexes [lodLevel]; + //int vertCount = vvdHeader.numLODVertexes [0]; + //_vertArray = ParseFixup (BR, vvdHeader.fixupTableStart, vvdHeader.numFixup, vvdHeader.vertexDataStart, vvdHeader.tangentDataStart, + // out _Normals, out _UV, vertCount); + ReadVvdVertexes(BR,vvdHeader.vertexDataStart,vertCount,fixupTable); +// Debug.Log("VertCount "+vertCount+" vertArrayLength "+vertArray.Length); + } + else + { + Debug.LogWarning("VVD file numLODs is 0"); + } + + BR.BaseStream.Dispose (); + } + + vvdheader ReadVvdHeader(BinaryReader br) + { + vvdheader hdr = new vvdheader (); + + hdr.id = br.ReadChars(4); + hdr.version = br.ReadInt32 (); + hdr.checksum = br.ReadInt32 (); + hdr.numLODs = br.ReadInt32 (); + // Debug.Log ("VDD header numLODs is "+hdr.numLODs); + hdr.numLODVertexes = new int[]{ br.ReadInt32 (),br.ReadInt32 (),br.ReadInt32 (),br.ReadInt32 (), + br.ReadInt32 (),br.ReadInt32 (),br.ReadInt32 (),br.ReadInt32 ()}; + hdr.numFixup = br.ReadInt32 (); + hdr.fixupTableStart = br.ReadInt32 (); + hdr.vertexDataStart = br.ReadInt32 (); + hdr.tangentDataStart = br.ReadInt32 (); + + return hdr; + } + + void ReadVvdVertexes(BinaryReader br, int vertOffs, int vertCount, vertexFileFixup[] fixupTable) + { + if (fixupTable == null) + { + boneWeights = new BoneWeight[vertCount]; + vertArray = new Vector3[vertCount]; + Normals = new Vector3[vertCount]; + UV = new Vector2[vertCount]; + + br.BaseStream.Seek (vertOffs, SeekOrigin.Begin); + for (int i=0; i VertexView = new List(); + List NormalView = new List(); + List UVView = new List(); + List _boneWeights = new List (); + //int target=0; + //int vertexArrayOffset=0; + + for (int i=0; i VertexView = new List(); + List NormalView = new List(); + List UVView = new List(); + List _boneWeights = new List (); + _Normals = null;//new Vector3[vertCount]; + _UV = null;//new Vector2[vertCount]; + int vertexArrayOffset=0; + vertexFileFixup[] fixupTable; + + if (fixupCount == 0) + { + BR.BaseStream.Seek(VertexOffs, SeekOrigin.Begin); + for (int i=0; i openFileCallback) + { + path = path.Replace (".mdl", ".dx90.vtx"); + + //_indexArray = null; + + BinaryReader BR = new BinaryReader (openFileCallback(path)); + + /*vtxheader*/ vtxHeader = ReadVtxHeader (BR); + + //VtxHeader = header; + + if (vtxHeader.numLODs > 0) + { + /*vtxBodypartHeader[]*/ vtxBodyParts = ReadVtxBodyParts (BR, vtxHeader.bodyPartOffset, vtxHeader.numBobyParts); + indexArray = BuildIndices (vtxBodyParts); + } + BR.BaseStream.Dispose (); + } + + vtxHeader ReadVtxHeader(BinaryReader BR) + { + vtxHeader hdr = new vtxHeader (); + + hdr.version = BR.ReadInt32 (); + hdr.vertCacheSize=BR.ReadInt32 (); + hdr.maxBonePerStrip=BR.ReadInt16 (); + hdr.maxBonePerTri=BR.ReadInt16 (); + hdr.maxBonePerVert=BR.ReadInt32 (); + hdr.checksum = BR.ReadInt32 (); + hdr.numLODs = BR.ReadInt32 (); + hdr.materialReplacementListOffset=BR.ReadInt32 (); + hdr.numBobyParts=BR.ReadInt32 (); + hdr.bodyPartOffset=BR.ReadInt32 (); + + return hdr; + } + + vtxBodypartHeader[] ReadVtxBodyParts (BinaryReader br, int offs,int count) + { + vtxBodypartHeader[] bp = new vtxBodypartHeader[count]; + + for (int i=0; i0) + { + bp[i].models = ReadVtxModels(br, offs+(i*8), bp[i]); + } + else + Debug.LogWarning("VTX Body part "+ i+" models count is 0"); + } + + return bp; + } + + vtxModelHeader[] ReadVtxModels(BinaryReader br, int offset, vtxBodypartHeader bodypart) + { + vtxModelHeader[] mh = new vtxModelHeader[bodypart.numModels]; + + for (int i=0; i0) + { + mh[i].lods = ReadVtxModelLods(br, bodypart.modelsOffset + offset + (i*8), mh[i],i); + } + else + Debug.LogWarning("VTX model "+ i+" LODs count is 0"); + } + return mh; + } + + vtxModelLODheader[] ReadVtxModelLods(BinaryReader br, int offset, vtxModelHeader model,int modelIndex) + { + vtxModelLODheader[] mlods = new vtxModelLODheader[model.numLODs]; + for (int i=0; i0) + { + mlods[i].meshes = ReadVtxMeshes(br, model.LODOffset+ offset + (i*12), mlods[i]); + } + else + Debug.LogWarning("VTX model "+modelIndex+" lod "+ i+" mesh count is 0"); + } + return mlods; + } + + vtxMeshHeader[] ReadVtxMeshes(BinaryReader br, int offset, vtxModelLODheader lod) + { + vtxMeshHeader[] ms = new vtxMeshHeader[lod.numMeshes]; + + for (int i=0; i0) + { + ms[i].stripGroups = ReadVtxStripGroups(br, lod.meshOffset+ offset + (i*9), ms[i]); + } + //else + // Debug.LogWarning("VTX mesh "+ i+" numStripGroups is 0"); + } + return ms; + } + + vtxStripGroupHeader[] ReadVtxStripGroups(BinaryReader br, int offset,vtxMeshHeader mesh) + { + vtxStripGroupHeader[] sg = new vtxStripGroupHeader[mesh.numStripGroups]; + + for (int i=0; i0) + { + sg[i].verts = ReadVtxVerts(br, mesh.stripGroupHeaderOffset+ offset + (i*25),sg[i]); + } + if(sg[i].numIndices>0) + { + br.BaseStream.Seek (mesh.stripGroupHeaderOffset + offset + (i*25)+sg[i].indexOffs,SeekOrigin.Begin); + for(int j=0; j0) + { + sg[i].strips = ReadVtxStrips(br, mesh.stripGroupHeaderOffset+ offset + (i*25), sg[i]); + } + //sg[i].strips = ReadStrips(br, mesh.stripGroupHeaderOffset+ offset + (i*25), sg[i]); + //sg[i].verts = ReadVtxVerts(br, mesh.stripGroupHeaderOffset+ offset + (i*25),sg[i]); + //br.BaseStream.Seek (mesh.stripGroupHeaderOffset + offset + (i*25)+sg[i].indexOffs,SeekOrigin.Begin); + //for(int j=0; j= vvdHeader.numLODs) + lodLevel = (vvdHeader.numLODs - 1); + int indexCount = IterateStripGroups (lodLevel, bodyParts[0]); +// Debug.Log ("indexCount "+indexCount); + int[] indices=new int[indexCount]; + int indexOffset=0; + submeshCount = 0; + + //for(int bpId=0; bpId= vvdHeader.numLODs) + lodLevel = (vvdHeader.numLODs - 1); + int indexCount = IterateStripGroups (lodLevel, vtxBodyPart); + //Debug.Log ("indexCount "+indexCount); + int[] indices=new int[indexCount]; + int indexOffset=0; + + //studiobodypart mdlBodypart = mdlBodyParts[bpId]; + for(int modelId=0; modelId0) + { + vtxModelLODheader lodheader=model.lods[lodID]; + foreach(vtxMeshHeader mesh in lodheader.meshes) + { + foreach(vtxStripGroupHeader stripGroup in mesh.stripGroups) + { + //Debug.Log ("Strip group num indices "+stripGroup.numIndices); + indices+=stripGroup.numIndices; + } + } + } + else + { + Debug.LogWarning ("model.lods.Length < 0 or lodID is -1"); + } + } + return indices; + } + } + +} diff --git a/Assets/Editor/SourceStudioModel.cs.meta b/Assets/Editor/SourceStudioModel.cs.meta new file mode 100644 index 0000000..c05554a --- /dev/null +++ b/Assets/Editor/SourceStudioModel.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0e71625a2c83d9d499a5942ad6eae0f9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor/VPKFile.cs b/Assets/Editor/VPKFile.cs new file mode 100644 index 0000000..b9b9978 --- /dev/null +++ b/Assets/Editor/VPKFile.cs @@ -0,0 +1,186 @@ +using SourceFormatParser.Common; +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using UnityEngine; + +public class VPKFile +{ + public struct Header { + public uint Magic; + public uint Version; + public uint TreeSizeInBytes; + public uint FileDataSectionSize; + public uint ArchiveMD5SectionSize; + public uint OtherMD5SectionSize; + public uint SignatureSectionSize; + //Assert(0x55aa1234 == Magic, "WTF"); + } + + public struct FileDescription { + public uint CRC; + public ushort PreloadBytes; + public ushort ArchiveId; + public uint EntryOffset; + public uint EntryLength; + public ushort ConstFooter; + } + + public class FileRecord { + public string Name; + public FileDescription Description; + public byte[] PreloadData; + } + + public class DirectoryRecord { + public string Name; + public List Files = new List(); + } + + public class ExtensionRecord + { + public string Name; + public List Directories = new List(); + } + + + public static string ReadSZString(BinaryReader reader) + { + var result = new StringBuilder(); + while (true) { + byte b = reader.ReadByte(); + if (0 == b) + break; + result.Append((char)b); + } + return result.ToString(); + } + + + + public static FileRecord FindFile(List tree, string path) + { + var fileNameSeparator = path.LastIndexOf('/'); + var dir = path.Substring(0, fileNameSeparator); + var fileNameWithExtension = path.Substring(fileNameSeparator + 1); + + var extSeparator = fileNameWithExtension.LastIndexOf('.'); + var fileName = fileNameWithExtension.Substring(0, extSeparator); + var ext = fileNameWithExtension.Substring(extSeparator + 1); + + var extRecord = tree.FirstOrDefault(x => x.Name == ext); + if (extRecord == null) { + return null; + } + + var dirRecord = extRecord.Directories.FirstOrDefault(x => x.Name == dir); + if (dirRecord == null) { + return null; + } + + var fileRecord = dirRecord.Files.FirstOrDefault(x => x.Name == fileName); + return fileRecord; + } + + public static byte[] ReadFile(string vpkDirectory, string pakNamePrefix, FileRecord record) + { + var archiveId = record.Description.ArchiveId; + var archiveFileName = pakNamePrefix + "_" + archiveId.ToString("D3") + ".vpk"; + + var archiveFilePath = System.IO.Path.Combine(vpkDirectory, archiveFileName); + + var stream = System.IO.File.OpenRead(archiveFilePath); + stream.Seek(record.Description.EntryOffset, SeekOrigin.Begin); + + var reader = new BinaryReader(stream); + var result = reader.ReadBytes((int)record.Description.EntryLength); + + reader.Close(); + return result; + } + + //pak01_dir.vpk + public static List ReadDirTree(string dirVpkFile) + { + var stream = File.OpenRead(dirVpkFile); + + BinaryReader br = new BinaryReader(stream, Encoding.ASCII, false); + + Header header = new Header(); + header.Magic = br.ReadUInt32(); + if(header.Magic != 0x55aa1234) { + throw new Exception("Invalid magic number"); + } + + header.Version = br.ReadUInt32(); + if(header.Version != 2) { + throw new Exception($"Version {header.Version} is not supported"); + } + + header.TreeSizeInBytes = br.ReadUInt32(); + header.FileDataSectionSize = br.ReadUInt32(); + header.ArchiveMD5SectionSize = br.ReadUInt32(); + header.OtherMD5SectionSize = br.ReadUInt32(); + header.SignatureSectionSize = br.ReadUInt32(); + + + List result = new List(); + + while (true) { + string extName = ReadSZString(br); + if (string.IsNullOrEmpty(extName)) { + break; + } + + ExtensionRecord extRecord = new ExtensionRecord(); + extRecord.Name = extName; + + while (true) { + string dirName = ReadSZString(br); + if (string.IsNullOrEmpty(dirName)) { + break; + } + + DirectoryRecord dirRecord = new DirectoryRecord(); + dirRecord.Name = dirName; + + while (true) { + string fileName = ReadSZString(br); + if (string.IsNullOrEmpty(fileName)) { + break; + } + + FileRecord fileRecord = new FileRecord(); + fileRecord.Name = fileName; + + //read file desc + FileDescription desc = new FileDescription(); + desc.CRC = br.ReadUInt32(); + desc.PreloadBytes = br.ReadUInt16(); + desc.ArchiveId = br.ReadUInt16(); + desc.EntryOffset = br.ReadUInt32(); + desc.EntryLength = br.ReadUInt32(); + desc.ConstFooter = br.ReadUInt16(); + + fileRecord.Description = desc; + + if(desc.PreloadBytes != 0) { + fileRecord.PreloadData = br.ReadBytes(desc.PreloadBytes); + } + + dirRecord.Files.Add(fileRecord); + } + + extRecord.Directories.Add(dirRecord); + } + + result.Add(extRecord); + } + + return result; + } + +} diff --git a/Assets/Editor/VPKFile.cs.meta b/Assets/Editor/VPKFile.cs.meta new file mode 100644 index 0000000..ba85cd5 --- /dev/null +++ b/Assets/Editor/VPKFile.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 389d878914ff28948bed0a0900d67937 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Main.unity b/Assets/Main.unity new file mode 100644 index 0000000..e33fabd --- /dev/null +++ b/Assets/Main.unity @@ -0,0 +1,416 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 0 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0.44795346, g: 0.49795347, b: 0.57549006, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 12 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 12 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_ExtractAmbientOcclusion: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 256 + m_ReflectionCompression: 2 + m_MixedBakeMode: 2 + m_BakeBackend: 1 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 512 + m_PVRBounces: 2 + m_PVREnvironmentSampleCount: 256 + m_PVREnvironmentReferencePointCount: 2048 + m_PVRFilteringMode: 1 + m_PVRDenoiserTypeDirect: 1 + m_PVRDenoiserTypeIndirect: 1 + m_PVRDenoiserTypeAO: 1 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVREnvironmentMIS: 1 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ExportTrainingData: 0 + m_TrainingDataDestination: TrainingData + m_LightProbeSampleCountMultiplier: 4 + m_LightingDataAsset: {fileID: 0} + m_LightingSettings: {fileID: 0} +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 3 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + buildHeightMesh: 0 + maxJobWorkers: 0 + preserveTilesOutsideBounds: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &7022119 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 7022121} + - component: {fileID: 7022120} + m_Layer: 0 + m_Name: Directional Light + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!108 &7022120 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7022119} + m_Enabled: 1 + serializedVersion: 10 + m_Type: 1 + m_Shape: 0 + m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} + m_Intensity: 1 + m_Range: 10 + m_SpotAngle: 30 + m_InnerSpotAngle: 21.80208 + m_CookieSize: 10 + m_Shadows: + m_Type: 2 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_CullingMatrixOverride: + e00: 1 + e01: 0 + e02: 0 + e03: 0 + e10: 0 + e11: 1 + e12: 0 + e13: 0 + e20: 0 + e21: 0 + e22: 1 + e23: 0 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + m_UseCullingMatrixOverride: 0 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingLayerMask: 1 + m_Lightmapping: 4 + m_LightShadowCasterMode: 0 + m_AreaSize: {x: 1, y: 1} + m_BounceIntensity: 1 + m_ColorTemperature: 6570 + m_UseColorTemperature: 0 + m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} + m_UseBoundingSphereOverride: 0 + m_UseViewFrustumForShadowCasterCull: 1 + m_ShadowRadius: 0 + m_ShadowAngle: 0 +--- !u!4 &7022121 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7022119} + m_LocalRotation: {x: 0.44452265, y: 0.08130852, z: 0.2554378, w: 0.85471636} + m_LocalPosition: {x: 0, y: 3, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 45.918, y: 31.751, z: 47.018} +--- !u!1 &720630586 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 720630590} + - component: {fileID: 720630589} + - component: {fileID: 720630588} + - component: {fileID: 720630587} + m_Layer: 0 + m_Name: Cube + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!65 &720630587 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 720630586} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!23 &720630588 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 720630586} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!33 &720630589 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 720630586} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &720630590 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 720630586} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 34.82, y: 0.69, z: 36.91} + m_LocalScale: {x: 0.7, y: 1.8, z: 0.5} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1670971759 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1670971762} + - component: {fileID: 1670971761} + - component: {fileID: 1670971760} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &1670971760 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1670971759} + m_Enabled: 1 +--- !u!20 &1670971761 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1670971759} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} + m_projectionMatrixMode: 1 + m_GateFitMode: 2 + m_FOVAxisMode: 0 + m_Iso: 200 + m_ShutterSpeed: 0.005 + m_Aperture: 16 + m_FocusDistance: 10 + m_FocalLength: 50 + m_BladeCount: 5 + m_Curvature: {x: 2, y: 11} + m_BarrelClipping: 0.25 + m_Anamorphism: 0 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 0 + orthographic size: 5 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 1 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &1670971762 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1670971759} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 1, z: -10} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} diff --git a/Assets/Main.unity.meta b/Assets/Main.unity.meta new file mode 100644 index 0000000..f1cf5e7 --- /dev/null +++ b/Assets/Main.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: f96508b8429a9d74e9e02cc8395493ef +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scenes.meta b/Assets/Scenes.meta new file mode 100644 index 0000000..f655335 --- /dev/null +++ b/Assets/Scenes.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 13de929330809cb458b76c4321da7208 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scenes/SampleScene.unity b/Assets/Scenes/SampleScene.unity new file mode 100644 index 0000000..66d3c2e Binary files /dev/null and b/Assets/Scenes/SampleScene.unity differ diff --git a/Assets/Scenes/SampleScene.unity.meta b/Assets/Scenes/SampleScene.unity.meta new file mode 100644 index 0000000..952bd1e --- /dev/null +++ b/Assets/Scenes/SampleScene.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 9fc0d4010bbf28b4594072e72b8655ab +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/manifest.json b/Packages/manifest.json new file mode 100644 index 0000000..f807444 --- /dev/null +++ b/Packages/manifest.json @@ -0,0 +1,41 @@ +{ + "dependencies": { + "com.unity.collab-proxy": "2.0.3", + "com.unity.feature.development": "1.0.1", + "com.unity.textmeshpro": "3.0.6", + "com.unity.timeline": "1.7.4", + "com.unity.ugui": "1.0.0", + "com.unity.visualscripting": "1.8.0", + "com.unity.modules.ai": "1.0.0", + "com.unity.modules.androidjni": "1.0.0", + "com.unity.modules.animation": "1.0.0", + "com.unity.modules.assetbundle": "1.0.0", + "com.unity.modules.audio": "1.0.0", + "com.unity.modules.cloth": "1.0.0", + "com.unity.modules.director": "1.0.0", + "com.unity.modules.imageconversion": "1.0.0", + "com.unity.modules.imgui": "1.0.0", + "com.unity.modules.jsonserialize": "1.0.0", + "com.unity.modules.particlesystem": "1.0.0", + "com.unity.modules.physics": "1.0.0", + "com.unity.modules.physics2d": "1.0.0", + "com.unity.modules.screencapture": "1.0.0", + "com.unity.modules.terrain": "1.0.0", + "com.unity.modules.terrainphysics": "1.0.0", + "com.unity.modules.tilemap": "1.0.0", + "com.unity.modules.ui": "1.0.0", + "com.unity.modules.uielements": "1.0.0", + "com.unity.modules.umbra": "1.0.0", + "com.unity.modules.unityanalytics": "1.0.0", + "com.unity.modules.unitywebrequest": "1.0.0", + "com.unity.modules.unitywebrequestassetbundle": "1.0.0", + "com.unity.modules.unitywebrequestaudio": "1.0.0", + "com.unity.modules.unitywebrequesttexture": "1.0.0", + "com.unity.modules.unitywebrequestwww": "1.0.0", + "com.unity.modules.vehicles": "1.0.0", + "com.unity.modules.video": "1.0.0", + "com.unity.modules.vr": "1.0.0", + "com.unity.modules.wind": "1.0.0", + "com.unity.modules.xr": "1.0.0" + } +} diff --git a/Packages/packages-lock.json b/Packages/packages-lock.json new file mode 100644 index 0000000..1dc814e --- /dev/null +++ b/Packages/packages-lock.json @@ -0,0 +1,382 @@ +{ + "dependencies": { + "com.unity.collab-proxy": { + "version": "2.0.3", + "depth": 0, + "source": "registry", + "dependencies": {}, + "url": "https://packages.unity.com" + }, + "com.unity.editorcoroutines": { + "version": "1.0.0", + "depth": 1, + "source": "registry", + "dependencies": {}, + "url": "https://packages.unity.com" + }, + "com.unity.ext.nunit": { + "version": "1.0.6", + "depth": 2, + "source": "registry", + "dependencies": {}, + "url": "https://packages.unity.com" + }, + "com.unity.feature.development": { + "version": "1.0.1", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.ide.visualstudio": "2.0.17", + "com.unity.ide.rider": "3.0.18", + "com.unity.ide.vscode": "1.2.5", + "com.unity.editorcoroutines": "1.0.0", + "com.unity.performance.profile-analyzer": "1.2.2", + "com.unity.test-framework": "1.1.33", + "com.unity.testtools.codecoverage": "1.2.2" + } + }, + "com.unity.ide.rider": { + "version": "3.0.18", + "depth": 1, + "source": "registry", + "dependencies": { + "com.unity.ext.nunit": "1.0.6" + }, + "url": "https://packages.unity.com" + }, + "com.unity.ide.visualstudio": { + "version": "2.0.17", + "depth": 1, + "source": "registry", + "dependencies": { + "com.unity.test-framework": "1.1.9" + }, + "url": "https://packages.unity.com" + }, + "com.unity.ide.vscode": { + "version": "1.2.5", + "depth": 1, + "source": "registry", + "dependencies": {}, + "url": "https://packages.unity.com" + }, + "com.unity.performance.profile-analyzer": { + "version": "1.2.2", + "depth": 1, + "source": "registry", + "dependencies": {}, + "url": "https://packages.unity.com" + }, + "com.unity.settings-manager": { + "version": "2.0.1", + "depth": 2, + "source": "registry", + "dependencies": {}, + "url": "https://packages.unity.com" + }, + "com.unity.test-framework": { + "version": "1.1.33", + "depth": 1, + "source": "registry", + "dependencies": { + "com.unity.ext.nunit": "1.0.6", + "com.unity.modules.imgui": "1.0.0", + "com.unity.modules.jsonserialize": "1.0.0" + }, + "url": "https://packages.unity.com" + }, + "com.unity.testtools.codecoverage": { + "version": "1.2.2", + "depth": 1, + "source": "registry", + "dependencies": { + "com.unity.test-framework": "1.0.16", + "com.unity.settings-manager": "1.0.1" + }, + "url": "https://packages.unity.com" + }, + "com.unity.textmeshpro": { + "version": "3.0.6", + "depth": 0, + "source": "registry", + "dependencies": { + "com.unity.ugui": "1.0.0" + }, + "url": "https://packages.unity.com" + }, + "com.unity.timeline": { + "version": "1.7.4", + "depth": 0, + "source": "registry", + "dependencies": { + "com.unity.modules.director": "1.0.0", + "com.unity.modules.animation": "1.0.0", + "com.unity.modules.audio": "1.0.0", + "com.unity.modules.particlesystem": "1.0.0" + }, + "url": "https://packages.unity.com" + }, + "com.unity.ugui": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.ui": "1.0.0", + "com.unity.modules.imgui": "1.0.0" + } + }, + "com.unity.visualscripting": { + "version": "1.8.0", + "depth": 0, + "source": "registry", + "dependencies": { + "com.unity.ugui": "1.0.0", + "com.unity.modules.jsonserialize": "1.0.0" + }, + "url": "https://packages.unity.com" + }, + "com.unity.modules.ai": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.androidjni": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.animation": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.assetbundle": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.audio": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.cloth": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.physics": "1.0.0" + } + }, + "com.unity.modules.director": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.audio": "1.0.0", + "com.unity.modules.animation": "1.0.0" + } + }, + "com.unity.modules.imageconversion": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.imgui": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.jsonserialize": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.particlesystem": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.physics": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.physics2d": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.screencapture": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.imageconversion": "1.0.0" + } + }, + "com.unity.modules.subsystems": { + "version": "1.0.0", + "depth": 1, + "source": "builtin", + "dependencies": { + "com.unity.modules.jsonserialize": "1.0.0" + } + }, + "com.unity.modules.terrain": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.terrainphysics": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.physics": "1.0.0", + "com.unity.modules.terrain": "1.0.0" + } + }, + "com.unity.modules.tilemap": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.physics2d": "1.0.0" + } + }, + "com.unity.modules.ui": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.uielements": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.ui": "1.0.0", + "com.unity.modules.imgui": "1.0.0", + "com.unity.modules.jsonserialize": "1.0.0" + } + }, + "com.unity.modules.umbra": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.unityanalytics": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.unitywebrequest": "1.0.0", + "com.unity.modules.jsonserialize": "1.0.0" + } + }, + "com.unity.modules.unitywebrequest": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.unitywebrequestassetbundle": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.assetbundle": "1.0.0", + "com.unity.modules.unitywebrequest": "1.0.0" + } + }, + "com.unity.modules.unitywebrequestaudio": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.unitywebrequest": "1.0.0", + "com.unity.modules.audio": "1.0.0" + } + }, + "com.unity.modules.unitywebrequesttexture": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.unitywebrequest": "1.0.0", + "com.unity.modules.imageconversion": "1.0.0" + } + }, + "com.unity.modules.unitywebrequestwww": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.unitywebrequest": "1.0.0", + "com.unity.modules.unitywebrequestassetbundle": "1.0.0", + "com.unity.modules.unitywebrequestaudio": "1.0.0", + "com.unity.modules.audio": "1.0.0", + "com.unity.modules.assetbundle": "1.0.0", + "com.unity.modules.imageconversion": "1.0.0" + } + }, + "com.unity.modules.vehicles": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.physics": "1.0.0" + } + }, + "com.unity.modules.video": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.audio": "1.0.0", + "com.unity.modules.ui": "1.0.0", + "com.unity.modules.unitywebrequest": "1.0.0" + } + }, + "com.unity.modules.vr": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.jsonserialize": "1.0.0", + "com.unity.modules.physics": "1.0.0", + "com.unity.modules.xr": "1.0.0" + } + }, + "com.unity.modules.wind": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.xr": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.physics": "1.0.0", + "com.unity.modules.jsonserialize": "1.0.0", + "com.unity.modules.subsystems": "1.0.0" + } + } + } +} diff --git a/ProjectSettings/AudioManager.asset b/ProjectSettings/AudioManager.asset new file mode 100644 index 0000000..07ebfb0 --- /dev/null +++ b/ProjectSettings/AudioManager.asset @@ -0,0 +1,19 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!11 &1 +AudioManager: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Volume: 1 + Rolloff Scale: 1 + Doppler Factor: 1 + Default Speaker Mode: 2 + m_SampleRate: 0 + m_DSPBufferSize: 1024 + m_VirtualVoiceCount: 512 + m_RealVoiceCount: 32 + m_SpatializerPlugin: + m_AmbisonicDecoderPlugin: + m_DisableAudio: 0 + m_VirtualizeEffects: 1 + m_RequestedDSPBufferSize: 1024 diff --git a/ProjectSettings/ClusterInputManager.asset b/ProjectSettings/ClusterInputManager.asset new file mode 100644 index 0000000..e7886b2 --- /dev/null +++ b/ProjectSettings/ClusterInputManager.asset @@ -0,0 +1,6 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!236 &1 +ClusterInputManager: + m_ObjectHideFlags: 0 + m_Inputs: [] diff --git a/ProjectSettings/DynamicsManager.asset b/ProjectSettings/DynamicsManager.asset new file mode 100644 index 0000000..cdc1f3e --- /dev/null +++ b/ProjectSettings/DynamicsManager.asset @@ -0,0 +1,34 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!55 &1 +PhysicsManager: + m_ObjectHideFlags: 0 + serializedVersion: 11 + m_Gravity: {x: 0, y: -9.81, z: 0} + m_DefaultMaterial: {fileID: 0} + m_BounceThreshold: 2 + m_SleepThreshold: 0.005 + m_DefaultContactOffset: 0.01 + m_DefaultSolverIterations: 6 + m_DefaultSolverVelocityIterations: 1 + m_QueriesHitBackfaces: 0 + m_QueriesHitTriggers: 1 + m_EnableAdaptiveForce: 0 + m_ClothInterCollisionDistance: 0 + m_ClothInterCollisionStiffness: 0 + m_ContactsGeneration: 1 + m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + m_AutoSimulation: 1 + m_AutoSyncTransforms: 0 + m_ReuseCollisionCallbacks: 1 + m_ClothInterCollisionSettingsToggle: 0 + m_ContactPairsMode: 0 + m_BroadphaseType: 0 + m_WorldBounds: + m_Center: {x: 0, y: 0, z: 0} + m_Extent: {x: 250, y: 250, z: 250} + m_WorldSubdivisions: 8 + m_FrictionType: 0 + m_EnableEnhancedDeterminism: 0 + m_EnableUnifiedHeightmaps: 1 + m_DefaultMaxAngluarSpeed: 7 diff --git a/ProjectSettings/EditorBuildSettings.asset b/ProjectSettings/EditorBuildSettings.asset new file mode 100644 index 0000000..0147887 --- /dev/null +++ b/ProjectSettings/EditorBuildSettings.asset @@ -0,0 +1,8 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1045 &1 +EditorBuildSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Scenes: [] + m_configObjects: {} diff --git a/ProjectSettings/EditorSettings.asset b/ProjectSettings/EditorSettings.asset new file mode 100644 index 0000000..1e44a0a --- /dev/null +++ b/ProjectSettings/EditorSettings.asset @@ -0,0 +1,30 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!159 &1 +EditorSettings: + m_ObjectHideFlags: 0 + serializedVersion: 11 + m_ExternalVersionControlSupport: Visible Meta Files + m_SerializationMode: 2 + m_LineEndingsForNewScripts: 0 + m_DefaultBehaviorMode: 0 + m_PrefabRegularEnvironment: {fileID: 0} + m_PrefabUIEnvironment: {fileID: 0} + m_SpritePackerMode: 0 + m_SpritePackerPaddingPower: 1 + m_EtcTextureCompressorBehavior: 1 + m_EtcTextureFastCompressor: 1 + m_EtcTextureNormalCompressor: 2 + m_EtcTextureBestCompressor: 4 + m_ProjectGenerationIncludedExtensions: txt;xml;fnt;cd;asmdef;rsp;asmref + m_ProjectGenerationRootNamespace: + m_CollabEditorSettings: + inProgressEnabled: 1 + m_EnableTextureStreamingInEditMode: 1 + m_EnableTextureStreamingInPlayMode: 1 + m_AsyncShaderCompilation: 1 + m_EnterPlayModeOptionsEnabled: 0 + m_EnterPlayModeOptions: 3 + m_ShowLightmapResolutionOverlay: 1 + m_UseLegacyProbeSampleCount: 0 + m_SerializeInlineMappingsOnOneLine: 1 diff --git a/ProjectSettings/GraphicsSettings.asset b/ProjectSettings/GraphicsSettings.asset new file mode 100644 index 0000000..43369e3 --- /dev/null +++ b/ProjectSettings/GraphicsSettings.asset @@ -0,0 +1,63 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!30 &1 +GraphicsSettings: + m_ObjectHideFlags: 0 + serializedVersion: 13 + m_Deferred: + m_Mode: 1 + m_Shader: {fileID: 69, guid: 0000000000000000f000000000000000, type: 0} + m_DeferredReflections: + m_Mode: 1 + m_Shader: {fileID: 74, guid: 0000000000000000f000000000000000, type: 0} + m_ScreenSpaceShadows: + m_Mode: 1 + m_Shader: {fileID: 64, guid: 0000000000000000f000000000000000, type: 0} + m_LegacyDeferred: + m_Mode: 1 + m_Shader: {fileID: 63, guid: 0000000000000000f000000000000000, type: 0} + m_DepthNormals: + m_Mode: 1 + m_Shader: {fileID: 62, guid: 0000000000000000f000000000000000, type: 0} + m_MotionVectors: + m_Mode: 1 + m_Shader: {fileID: 75, guid: 0000000000000000f000000000000000, type: 0} + m_LightHalo: + m_Mode: 1 + m_Shader: {fileID: 105, guid: 0000000000000000f000000000000000, type: 0} + m_LensFlare: + m_Mode: 1 + m_Shader: {fileID: 102, guid: 0000000000000000f000000000000000, type: 0} + m_AlwaysIncludedShaders: + - {fileID: 7, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 15104, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 15105, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 15106, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 10753, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0} + m_PreloadedShaders: [] + m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000, + type: 0} + m_CustomRenderPipeline: {fileID: 0} + m_TransparencySortMode: 0 + m_TransparencySortAxis: {x: 0, y: 0, z: 1} + m_DefaultRenderingPath: 1 + m_DefaultMobileRenderingPath: 1 + m_TierSettings: [] + m_LightmapStripping: 0 + m_FogStripping: 0 + m_InstancingStripping: 0 + m_LightmapKeepPlain: 1 + m_LightmapKeepDirCombined: 1 + m_LightmapKeepDynamicPlain: 1 + m_LightmapKeepDynamicDirCombined: 1 + m_LightmapKeepShadowMask: 1 + m_LightmapKeepSubtractive: 1 + m_FogKeepLinear: 1 + m_FogKeepExp: 1 + m_FogKeepExp2: 1 + m_AlbedoSwatchInfos: [] + m_LightsUseLinearIntensity: 0 + m_LightsUseColorTemperature: 0 + m_LogWhenShaderIsCompiled: 0 + m_AllowEnlightenSupportForUpgradedProject: 0 diff --git a/ProjectSettings/InputManager.asset b/ProjectSettings/InputManager.asset new file mode 100644 index 0000000..17c8f53 --- /dev/null +++ b/ProjectSettings/InputManager.asset @@ -0,0 +1,295 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!13 &1 +InputManager: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Axes: + - serializedVersion: 3 + m_Name: Horizontal + descriptiveName: + descriptiveNegativeName: + negativeButton: left + positiveButton: right + altNegativeButton: a + altPositiveButton: d + gravity: 3 + dead: 0.001 + sensitivity: 3 + snap: 1 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Vertical + descriptiveName: + descriptiveNegativeName: + negativeButton: down + positiveButton: up + altNegativeButton: s + altPositiveButton: w + gravity: 3 + dead: 0.001 + sensitivity: 3 + snap: 1 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire1 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: left ctrl + altNegativeButton: + altPositiveButton: mouse 0 + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire2 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: left alt + altNegativeButton: + altPositiveButton: mouse 1 + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire3 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: left shift + altNegativeButton: + altPositiveButton: mouse 2 + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Jump + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: space + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Mouse X + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: 0 + sensitivity: 0.1 + snap: 0 + invert: 0 + type: 1 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Mouse Y + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: 0 + sensitivity: 0.1 + snap: 0 + invert: 0 + type: 1 + axis: 1 + joyNum: 0 + - serializedVersion: 3 + m_Name: Mouse ScrollWheel + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: 0 + sensitivity: 0.1 + snap: 0 + invert: 0 + type: 1 + axis: 2 + joyNum: 0 + - serializedVersion: 3 + m_Name: Horizontal + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: 0.19 + sensitivity: 1 + snap: 0 + invert: 0 + type: 2 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Vertical + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: 0.19 + sensitivity: 1 + snap: 0 + invert: 1 + type: 2 + axis: 1 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire1 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: joystick button 0 + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire2 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: joystick button 1 + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire3 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: joystick button 2 + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Jump + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: joystick button 3 + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Submit + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: return + altNegativeButton: + altPositiveButton: joystick button 0 + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Submit + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: enter + altNegativeButton: + altPositiveButton: space + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Cancel + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: escape + altNegativeButton: + altPositiveButton: joystick button 1 + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 diff --git a/ProjectSettings/MemorySettings.asset b/ProjectSettings/MemorySettings.asset new file mode 100644 index 0000000..5b5face --- /dev/null +++ b/ProjectSettings/MemorySettings.asset @@ -0,0 +1,35 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!387306366 &1 +MemorySettings: + m_ObjectHideFlags: 0 + m_EditorMemorySettings: + m_MainAllocatorBlockSize: -1 + m_ThreadAllocatorBlockSize: -1 + m_MainGfxBlockSize: -1 + m_ThreadGfxBlockSize: -1 + m_CacheBlockSize: -1 + m_TypetreeBlockSize: -1 + m_ProfilerBlockSize: -1 + m_ProfilerEditorBlockSize: -1 + m_BucketAllocatorGranularity: -1 + m_BucketAllocatorBucketsCount: -1 + m_BucketAllocatorBlockSize: -1 + m_BucketAllocatorBlockCount: -1 + m_ProfilerBucketAllocatorGranularity: -1 + m_ProfilerBucketAllocatorBucketsCount: -1 + m_ProfilerBucketAllocatorBlockSize: -1 + m_ProfilerBucketAllocatorBlockCount: -1 + m_TempAllocatorSizeMain: -1 + m_JobTempAllocatorBlockSize: -1 + m_BackgroundJobTempAllocatorBlockSize: -1 + m_JobTempAllocatorReducedBlockSize: -1 + m_TempAllocatorSizeGIBakingWorker: -1 + m_TempAllocatorSizeNavMeshWorker: -1 + m_TempAllocatorSizeAudioWorker: -1 + m_TempAllocatorSizeCloudWorker: -1 + m_TempAllocatorSizeGfx: -1 + m_TempAllocatorSizeJobWorker: -1 + m_TempAllocatorSizeBackgroundWorker: -1 + m_TempAllocatorSizePreloadManager: -1 + m_PlatformMemorySettings: {} diff --git a/ProjectSettings/NavMeshAreas.asset b/ProjectSettings/NavMeshAreas.asset new file mode 100644 index 0000000..3b0b7c3 --- /dev/null +++ b/ProjectSettings/NavMeshAreas.asset @@ -0,0 +1,91 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!126 &1 +NavMeshProjectSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + areas: + - name: Walkable + cost: 1 + - name: Not Walkable + cost: 1 + - name: Jump + cost: 2 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + m_LastAgentTypeID: -887442657 + m_Settings: + - serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.75 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + debug: + m_Flags: 0 + m_SettingNames: + - Humanoid diff --git a/ProjectSettings/PackageManagerSettings.asset b/ProjectSettings/PackageManagerSettings.asset new file mode 100644 index 0000000..112a053 --- /dev/null +++ b/ProjectSettings/PackageManagerSettings.asset @@ -0,0 +1,35 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &1 +MonoBehaviour: + m_ObjectHideFlags: 61 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 13964, guid: 0000000000000000e000000000000000, type: 0} + m_Name: + m_EditorClassIdentifier: + m_EnablePreReleasePackages: 0 + m_EnablePackageDependencies: 0 + m_AdvancedSettingsExpanded: 1 + m_ScopedRegistriesSettingsExpanded: 1 + m_SeeAllPackageVersions: 0 + oneTimeWarningShown: 0 + m_Registries: + - m_Id: main + m_Name: + m_Url: https://packages.unity.com + m_Scopes: [] + m_IsDefault: 1 + m_Capabilities: 7 + m_UserSelectedRegistryName: + m_UserAddingNewScopedRegistry: 0 + m_RegistryInfoDraft: + m_Modified: 0 + m_ErrorMessage: + m_UserModificationsInstanceId: -830 + m_OriginalInstanceId: -832 + m_LoadAssets: 0 diff --git a/ProjectSettings/Packages/com.unity.testtools.codecoverage/Settings.json b/ProjectSettings/Packages/com.unity.testtools.codecoverage/Settings.json new file mode 100644 index 0000000..3c7b4c1 --- /dev/null +++ b/ProjectSettings/Packages/com.unity.testtools.codecoverage/Settings.json @@ -0,0 +1,5 @@ +{ + "m_Dictionary": { + "m_DictionaryValues": [] + } +} \ No newline at end of file diff --git a/ProjectSettings/Physics2DSettings.asset b/ProjectSettings/Physics2DSettings.asset new file mode 100644 index 0000000..47880b1 --- /dev/null +++ b/ProjectSettings/Physics2DSettings.asset @@ -0,0 +1,56 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!19 &1 +Physics2DSettings: + m_ObjectHideFlags: 0 + serializedVersion: 4 + m_Gravity: {x: 0, y: -9.81} + m_DefaultMaterial: {fileID: 0} + m_VelocityIterations: 8 + m_PositionIterations: 3 + m_VelocityThreshold: 1 + m_MaxLinearCorrection: 0.2 + m_MaxAngularCorrection: 8 + m_MaxTranslationSpeed: 100 + m_MaxRotationSpeed: 360 + m_BaumgarteScale: 0.2 + m_BaumgarteTimeOfImpactScale: 0.75 + m_TimeToSleep: 0.5 + m_LinearSleepTolerance: 0.01 + m_AngularSleepTolerance: 2 + m_DefaultContactOffset: 0.01 + m_JobOptions: + serializedVersion: 2 + useMultithreading: 0 + useConsistencySorting: 0 + m_InterpolationPosesPerJob: 100 + m_NewContactsPerJob: 30 + m_CollideContactsPerJob: 100 + m_ClearFlagsPerJob: 200 + m_ClearBodyForcesPerJob: 200 + m_SyncDiscreteFixturesPerJob: 50 + m_SyncContinuousFixturesPerJob: 50 + m_FindNearestContactsPerJob: 100 + m_UpdateTriggerContactsPerJob: 100 + m_IslandSolverCostThreshold: 100 + m_IslandSolverBodyCostScale: 1 + m_IslandSolverContactCostScale: 10 + m_IslandSolverJointCostScale: 10 + m_IslandSolverBodiesPerJob: 50 + m_IslandSolverContactsPerJob: 50 + m_AutoSimulation: 1 + m_QueriesHitTriggers: 1 + m_QueriesStartInColliders: 1 + m_CallbacksOnDisable: 1 + m_ReuseCollisionCallbacks: 1 + m_AutoSyncTransforms: 0 + m_AlwaysShowColliders: 0 + m_ShowColliderSleep: 1 + m_ShowColliderContacts: 0 + m_ShowColliderAABB: 0 + m_ContactArrowScale: 0.2 + m_ColliderAwakeColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.7529412} + m_ColliderAsleepColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.36078432} + m_ColliderContactColor: {r: 1, g: 0, b: 1, a: 0.6862745} + m_ColliderAABBColor: {r: 1, g: 1, b: 0, a: 0.2509804} + m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff diff --git a/ProjectSettings/PresetManager.asset b/ProjectSettings/PresetManager.asset new file mode 100644 index 0000000..67a94da --- /dev/null +++ b/ProjectSettings/PresetManager.asset @@ -0,0 +1,7 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1386491679 &1 +PresetManager: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_DefaultPresets: {} diff --git a/ProjectSettings/ProjectSettings.asset b/ProjectSettings/ProjectSettings.asset new file mode 100644 index 0000000..a496114 --- /dev/null +++ b/ProjectSettings/ProjectSettings.asset @@ -0,0 +1,753 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!129 &1 +PlayerSettings: + m_ObjectHideFlags: 0 + serializedVersion: 26 + productGUID: 7c056fa00f120ca4b9e8c145d323c5be + AndroidProfiler: 0 + AndroidFilterTouchesWhenObscured: 0 + AndroidEnableSustainedPerformanceMode: 0 + defaultScreenOrientation: 4 + targetDevice: 2 + useOnDemandResources: 0 + accelerometerFrequency: 60 + companyName: DefaultCompany + productName: FirstStrike + defaultCursor: {fileID: 0} + cursorHotspot: {x: 0, y: 0} + m_SplashScreenBackgroundColor: {r: 0.13725491, g: 0.12156863, b: 0.1254902, a: 1} + m_ShowUnitySplashScreen: 1 + m_ShowUnitySplashLogo: 1 + m_SplashScreenOverlayOpacity: 1 + m_SplashScreenAnimation: 1 + m_SplashScreenLogoStyle: 1 + m_SplashScreenDrawMode: 0 + m_SplashScreenBackgroundAnimationZoom: 1 + m_SplashScreenLogoAnimationZoom: 1 + m_SplashScreenBackgroundLandscapeAspect: 1 + m_SplashScreenBackgroundPortraitAspect: 1 + m_SplashScreenBackgroundLandscapeUvs: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + m_SplashScreenBackgroundPortraitUvs: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + m_SplashScreenLogos: [] + m_VirtualRealitySplashScreen: {fileID: 0} + m_HolographicTrackingLossScreen: {fileID: 0} + defaultScreenWidth: 1920 + defaultScreenHeight: 1080 + defaultScreenWidthWeb: 960 + defaultScreenHeightWeb: 600 + m_StereoRenderingPath: 0 + m_ActiveColorSpace: 0 + m_SpriteBatchVertexThreshold: 300 + m_MTRendering: 1 + mipStripping: 0 + numberOfMipsStripped: 0 + numberOfMipsStrippedPerMipmapLimitGroup: {} + m_StackTraceTypes: 010000000100000001000000010000000100000001000000 + iosShowActivityIndicatorOnLoading: -1 + androidShowActivityIndicatorOnLoading: -1 + iosUseCustomAppBackgroundBehavior: 0 + allowedAutorotateToPortrait: 1 + allowedAutorotateToPortraitUpsideDown: 1 + allowedAutorotateToLandscapeRight: 1 + allowedAutorotateToLandscapeLeft: 1 + useOSAutorotation: 1 + use32BitDisplayBuffer: 1 + preserveFramebufferAlpha: 0 + disableDepthAndStencilBuffers: 0 + androidStartInFullscreen: 1 + androidRenderOutsideSafeArea: 1 + androidUseSwappy: 1 + androidBlitType: 0 + androidResizableWindow: 0 + androidDefaultWindowWidth: 1920 + androidDefaultWindowHeight: 1080 + androidMinimumWindowWidth: 400 + androidMinimumWindowHeight: 300 + androidFullscreenMode: 1 + defaultIsNativeResolution: 1 + macRetinaSupport: 1 + runInBackground: 1 + captureSingleScreen: 0 + muteOtherAudioSources: 0 + Prepare IOS For Recording: 0 + Force IOS Speakers When Recording: 0 + deferSystemGesturesMode: 0 + hideHomeButton: 0 + submitAnalytics: 1 + usePlayerLog: 1 + bakeCollisionMeshes: 0 + forceSingleInstance: 0 + useFlipModelSwapchain: 1 + resizableWindow: 0 + useMacAppStoreValidation: 0 + macAppStoreCategory: public.app-category.games + gpuSkinning: 1 + xboxPIXTextureCapture: 0 + xboxEnableAvatar: 0 + xboxEnableKinect: 0 + xboxEnableKinectAutoTracking: 0 + xboxEnableFitness: 0 + visibleInBackground: 1 + allowFullscreenSwitch: 1 + fullscreenMode: 1 + xboxSpeechDB: 0 + xboxEnableHeadOrientation: 0 + xboxEnableGuest: 0 + xboxEnablePIXSampling: 0 + metalFramebufferOnly: 0 + xboxOneResolution: 0 + xboxOneSResolution: 0 + xboxOneXResolution: 3 + xboxOneMonoLoggingLevel: 0 + xboxOneLoggingLevel: 1 + xboxOneDisableEsram: 0 + xboxOneEnableTypeOptimization: 0 + xboxOnePresentImmediateThreshold: 0 + switchQueueCommandMemory: 0 + switchQueueControlMemory: 16384 + switchQueueComputeMemory: 262144 + switchNVNShaderPoolsGranularity: 33554432 + switchNVNDefaultPoolsGranularity: 16777216 + switchNVNOtherPoolsGranularity: 16777216 + switchGpuScratchPoolGranularity: 2097152 + switchAllowGpuScratchShrinking: 0 + switchNVNMaxPublicTextureIDCount: 0 + switchNVNMaxPublicSamplerIDCount: 0 + switchNVNGraphicsFirmwareMemory: 32 + stadiaPresentMode: 0 + stadiaTargetFramerate: 0 + vulkanNumSwapchainBuffers: 3 + vulkanEnableSetSRGBWrite: 0 + vulkanEnablePreTransform: 1 + vulkanEnableLateAcquireNextImage: 0 + vulkanEnableCommandBufferRecycling: 1 + loadStoreDebugModeEnabled: 0 + bundleVersion: 0.1 + preloadedAssets: [] + metroInputSource: 0 + wsaTransparentSwapchain: 0 + m_HolographicPauseOnTrackingLoss: 1 + xboxOneDisableKinectGpuReservation: 1 + xboxOneEnable7thCore: 1 + vrSettings: + enable360StereoCapture: 0 + isWsaHolographicRemotingEnabled: 0 + enableFrameTimingStats: 0 + enableOpenGLProfilerGPURecorders: 1 + useHDRDisplay: 0 + hdrBitDepth: 0 + m_ColorGamuts: 00000000 + targetPixelDensity: 30 + resolutionScalingMode: 0 + resetResolutionOnWindowResize: 0 + androidSupportedAspectRatio: 1 + androidMaxAspectRatio: 2.1 + applicationIdentifier: {} + buildNumber: + Standalone: 0 + iPhone: 0 + tvOS: 0 + overrideDefaultApplicationIdentifier: 0 + AndroidBundleVersionCode: 1 + AndroidMinSdkVersion: 22 + AndroidTargetSdkVersion: 0 + AndroidPreferredInstallLocation: 1 + aotOptions: + stripEngineCode: 1 + iPhoneStrippingLevel: 0 + iPhoneScriptCallOptimization: 0 + ForceInternetPermission: 0 + ForceSDCardPermission: 0 + CreateWallpaper: 0 + APKExpansionFiles: 0 + keepLoadedShadersAlive: 0 + StripUnusedMeshComponents: 1 + strictShaderVariantMatching: 0 + VertexChannelCompressionMask: 4054 + iPhoneSdkVersion: 988 + iOSTargetOSVersionString: 12.0 + tvOSSdkVersion: 0 + tvOSRequireExtendedGameController: 0 + tvOSTargetOSVersionString: 12.0 + uIPrerenderedIcon: 0 + uIRequiresPersistentWiFi: 0 + uIRequiresFullScreen: 1 + uIStatusBarHidden: 1 + uIExitOnSuspend: 0 + uIStatusBarStyle: 0 + appleTVSplashScreen: {fileID: 0} + appleTVSplashScreen2x: {fileID: 0} + tvOSSmallIconLayers: [] + tvOSSmallIconLayers2x: [] + tvOSLargeIconLayers: [] + tvOSLargeIconLayers2x: [] + tvOSTopShelfImageLayers: [] + tvOSTopShelfImageLayers2x: [] + tvOSTopShelfImageWideLayers: [] + tvOSTopShelfImageWideLayers2x: [] + iOSLaunchScreenType: 0 + iOSLaunchScreenPortrait: {fileID: 0} + iOSLaunchScreenLandscape: {fileID: 0} + iOSLaunchScreenBackgroundColor: + serializedVersion: 2 + rgba: 0 + iOSLaunchScreenFillPct: 100 + iOSLaunchScreenSize: 100 + iOSLaunchScreenCustomXibPath: + iOSLaunchScreeniPadType: 0 + iOSLaunchScreeniPadImage: {fileID: 0} + iOSLaunchScreeniPadBackgroundColor: + serializedVersion: 2 + rgba: 0 + iOSLaunchScreeniPadFillPct: 100 + iOSLaunchScreeniPadSize: 100 + iOSLaunchScreeniPadCustomXibPath: + iOSLaunchScreenCustomStoryboardPath: + iOSLaunchScreeniPadCustomStoryboardPath: + iOSDeviceRequirements: [] + iOSURLSchemes: [] + macOSURLSchemes: [] + iOSBackgroundModes: 0 + iOSMetalForceHardShadows: 0 + metalEditorSupport: 1 + metalAPIValidation: 1 + iOSRenderExtraFrameOnPause: 0 + iosCopyPluginsCodeInsteadOfSymlink: 0 + appleDeveloperTeamID: + iOSManualSigningProvisioningProfileID: + tvOSManualSigningProvisioningProfileID: + iOSManualSigningProvisioningProfileType: 0 + tvOSManualSigningProvisioningProfileType: 0 + appleEnableAutomaticSigning: 0 + iOSRequireARKit: 0 + iOSAutomaticallyDetectAndAddCapabilities: 1 + appleEnableProMotion: 0 + shaderPrecisionModel: 0 + clonedFromGUID: c0afd0d1d80e3634a9dac47e8a0426ea + templatePackageId: com.unity.template.3d@8.1.1 + templateDefaultScene: Assets/Scenes/SampleScene.unity + useCustomMainManifest: 0 + useCustomLauncherManifest: 0 + useCustomMainGradleTemplate: 0 + useCustomLauncherGradleManifest: 0 + useCustomBaseGradleTemplate: 0 + useCustomGradlePropertiesTemplate: 0 + useCustomGradleSettingsTemplate: 0 + useCustomProguardFile: 0 + AndroidTargetArchitectures: 1 + AndroidTargetDevices: 0 + AndroidSplashScreenScale: 0 + androidSplashScreen: {fileID: 0} + AndroidKeystoreName: + AndroidKeyaliasName: + AndroidEnableArmv9SecurityFeatures: 0 + AndroidBuildApkPerCpuArchitecture: 0 + AndroidTVCompatibility: 0 + AndroidIsGame: 1 + AndroidEnableTango: 0 + androidEnableBanner: 1 + androidUseLowAccuracyLocation: 0 + androidUseCustomKeystore: 0 + m_AndroidBanners: + - width: 320 + height: 180 + banner: {fileID: 0} + androidGamepadSupportLevel: 0 + chromeosInputEmulation: 1 + AndroidMinifyRelease: 0 + AndroidMinifyDebug: 0 + AndroidValidateAppBundleSize: 1 + AndroidAppBundleSizeToValidate: 150 + m_BuildTargetIcons: [] + m_BuildTargetPlatformIcons: [] + m_BuildTargetBatching: + - m_BuildTarget: Standalone + m_StaticBatching: 1 + m_DynamicBatching: 0 + - m_BuildTarget: tvOS + m_StaticBatching: 1 + m_DynamicBatching: 0 + - m_BuildTarget: Android + m_StaticBatching: 1 + m_DynamicBatching: 0 + - m_BuildTarget: iPhone + m_StaticBatching: 1 + m_DynamicBatching: 0 + - m_BuildTarget: WebGL + m_StaticBatching: 0 + m_DynamicBatching: 0 + m_BuildTargetShaderSettings: [] + m_BuildTargetGraphicsJobs: + - m_BuildTarget: MacStandaloneSupport + m_GraphicsJobs: 0 + - m_BuildTarget: Switch + m_GraphicsJobs: 1 + - m_BuildTarget: MetroSupport + m_GraphicsJobs: 1 + - m_BuildTarget: AppleTVSupport + m_GraphicsJobs: 0 + - m_BuildTarget: BJMSupport + m_GraphicsJobs: 1 + - m_BuildTarget: LinuxStandaloneSupport + m_GraphicsJobs: 1 + - m_BuildTarget: PS4Player + m_GraphicsJobs: 1 + - m_BuildTarget: iOSSupport + m_GraphicsJobs: 0 + - m_BuildTarget: WindowsStandaloneSupport + m_GraphicsJobs: 1 + - m_BuildTarget: XboxOnePlayer + m_GraphicsJobs: 1 + - m_BuildTarget: LuminSupport + m_GraphicsJobs: 0 + - m_BuildTarget: AndroidPlayer + m_GraphicsJobs: 0 + - m_BuildTarget: WebGLSupport + m_GraphicsJobs: 0 + m_BuildTargetGraphicsJobMode: + - m_BuildTarget: PS4Player + m_GraphicsJobMode: 0 + - m_BuildTarget: XboxOnePlayer + m_GraphicsJobMode: 0 + m_BuildTargetGraphicsAPIs: + - m_BuildTarget: AndroidPlayer + m_APIs: 150000000b000000 + m_Automatic: 1 + - m_BuildTarget: iOSSupport + m_APIs: 10000000 + m_Automatic: 1 + - m_BuildTarget: AppleTVSupport + m_APIs: 10000000 + m_Automatic: 1 + - m_BuildTarget: WebGLSupport + m_APIs: 0b000000 + m_Automatic: 1 + m_BuildTargetVRSettings: + - m_BuildTarget: Standalone + m_Enabled: 0 + m_Devices: + - Oculus + - OpenVR + m_DefaultShaderChunkSizeInMB: 16 + m_DefaultShaderChunkCount: 0 + openGLRequireES31: 0 + openGLRequireES31AEP: 0 + openGLRequireES32: 0 + m_TemplateCustomTags: {} + mobileMTRendering: + Android: 1 + iPhone: 1 + tvOS: 1 + m_BuildTargetGroupLightmapEncodingQuality: + - m_BuildTarget: Android + m_EncodingQuality: 1 + - m_BuildTarget: iPhone + m_EncodingQuality: 1 + - m_BuildTarget: tvOS + m_EncodingQuality: 1 + m_BuildTargetGroupHDRCubemapEncodingQuality: + - m_BuildTarget: Android + m_EncodingQuality: 1 + - m_BuildTarget: iPhone + m_EncodingQuality: 1 + - m_BuildTarget: tvOS + m_EncodingQuality: 1 + m_BuildTargetGroupLightmapSettings: [] + m_BuildTargetGroupLoadStoreDebugModeSettings: [] + m_BuildTargetNormalMapEncoding: + - m_BuildTarget: Android + m_Encoding: 1 + - m_BuildTarget: iPhone + m_Encoding: 1 + - m_BuildTarget: tvOS + m_Encoding: 1 + m_BuildTargetDefaultTextureCompressionFormat: + - m_BuildTarget: Android + m_Format: 3 + playModeTestRunnerEnabled: 0 + runPlayModeTestAsEditModeTest: 0 + actionOnDotNetUnhandledException: 1 + enableInternalProfiler: 0 + logObjCUncaughtExceptions: 1 + enableCrashReportAPI: 0 + cameraUsageDescription: + locationUsageDescription: + microphoneUsageDescription: + bluetoothUsageDescription: + macOSTargetOSVersion: 10.13.0 + switchNMETAOverride: + switchNetLibKey: + switchSocketMemoryPoolSize: 6144 + switchSocketAllocatorPoolSize: 128 + switchSocketConcurrencyLimit: 14 + switchScreenResolutionBehavior: 2 + switchUseCPUProfiler: 0 + switchUseGOLDLinker: 0 + switchLTOSetting: 0 + switchApplicationID: 0x01004b9000490000 + switchNSODependencies: + switchCompilerFlags: + switchTitleNames_0: + switchTitleNames_1: + switchTitleNames_2: + switchTitleNames_3: + switchTitleNames_4: + switchTitleNames_5: + switchTitleNames_6: + switchTitleNames_7: + switchTitleNames_8: + switchTitleNames_9: + switchTitleNames_10: + switchTitleNames_11: + switchTitleNames_12: + switchTitleNames_13: + switchTitleNames_14: + switchTitleNames_15: + switchPublisherNames_0: + switchPublisherNames_1: + switchPublisherNames_2: + switchPublisherNames_3: + switchPublisherNames_4: + switchPublisherNames_5: + switchPublisherNames_6: + switchPublisherNames_7: + switchPublisherNames_8: + switchPublisherNames_9: + switchPublisherNames_10: + switchPublisherNames_11: + switchPublisherNames_12: + switchPublisherNames_13: + switchPublisherNames_14: + switchPublisherNames_15: + switchIcons_0: {fileID: 0} + switchIcons_1: {fileID: 0} + switchIcons_2: {fileID: 0} + switchIcons_3: {fileID: 0} + switchIcons_4: {fileID: 0} + switchIcons_5: {fileID: 0} + switchIcons_6: {fileID: 0} + switchIcons_7: {fileID: 0} + switchIcons_8: {fileID: 0} + switchIcons_9: {fileID: 0} + switchIcons_10: {fileID: 0} + switchIcons_11: {fileID: 0} + switchIcons_12: {fileID: 0} + switchIcons_13: {fileID: 0} + switchIcons_14: {fileID: 0} + switchIcons_15: {fileID: 0} + switchSmallIcons_0: {fileID: 0} + switchSmallIcons_1: {fileID: 0} + switchSmallIcons_2: {fileID: 0} + switchSmallIcons_3: {fileID: 0} + switchSmallIcons_4: {fileID: 0} + switchSmallIcons_5: {fileID: 0} + switchSmallIcons_6: {fileID: 0} + switchSmallIcons_7: {fileID: 0} + switchSmallIcons_8: {fileID: 0} + switchSmallIcons_9: {fileID: 0} + switchSmallIcons_10: {fileID: 0} + switchSmallIcons_11: {fileID: 0} + switchSmallIcons_12: {fileID: 0} + switchSmallIcons_13: {fileID: 0} + switchSmallIcons_14: {fileID: 0} + switchSmallIcons_15: {fileID: 0} + switchManualHTML: + switchAccessibleURLs: + switchLegalInformation: + switchMainThreadStackSize: 1048576 + switchPresenceGroupId: + switchLogoHandling: 0 + switchReleaseVersion: 0 + switchDisplayVersion: 1.0.0 + switchStartupUserAccount: 0 + switchSupportedLanguagesMask: 0 + switchLogoType: 0 + switchApplicationErrorCodeCategory: + switchUserAccountSaveDataSize: 0 + switchUserAccountSaveDataJournalSize: 0 + switchApplicationAttribute: 0 + switchCardSpecSize: -1 + switchCardSpecClock: -1 + switchRatingsMask: 0 + switchRatingsInt_0: 0 + switchRatingsInt_1: 0 + switchRatingsInt_2: 0 + switchRatingsInt_3: 0 + switchRatingsInt_4: 0 + switchRatingsInt_5: 0 + switchRatingsInt_6: 0 + switchRatingsInt_7: 0 + switchRatingsInt_8: 0 + switchRatingsInt_9: 0 + switchRatingsInt_10: 0 + switchRatingsInt_11: 0 + switchRatingsInt_12: 0 + switchLocalCommunicationIds_0: + switchLocalCommunicationIds_1: + switchLocalCommunicationIds_2: + switchLocalCommunicationIds_3: + switchLocalCommunicationIds_4: + switchLocalCommunicationIds_5: + switchLocalCommunicationIds_6: + switchLocalCommunicationIds_7: + switchParentalControl: 0 + switchAllowsScreenshot: 1 + switchAllowsVideoCapturing: 1 + switchAllowsRuntimeAddOnContentInstall: 0 + switchDataLossConfirmation: 0 + switchUserAccountLockEnabled: 0 + switchSystemResourceMemory: 16777216 + switchSupportedNpadStyles: 22 + switchNativeFsCacheSize: 32 + switchIsHoldTypeHorizontal: 0 + switchSupportedNpadCount: 8 + switchEnableTouchScreen: 1 + switchSocketConfigEnabled: 0 + switchTcpInitialSendBufferSize: 32 + switchTcpInitialReceiveBufferSize: 64 + switchTcpAutoSendBufferSizeMax: 256 + switchTcpAutoReceiveBufferSizeMax: 256 + switchUdpSendBufferSize: 9 + switchUdpReceiveBufferSize: 42 + switchSocketBufferEfficiency: 4 + switchSocketInitializeEnabled: 1 + switchNetworkInterfaceManagerInitializeEnabled: 1 + switchPlayerConnectionEnabled: 1 + switchUseNewStyleFilepaths: 1 + switchUseLegacyFmodPriorities: 0 + switchUseMicroSleepForYield: 1 + switchEnableRamDiskSupport: 0 + switchMicroSleepForYieldTime: 25 + switchRamDiskSpaceSize: 12 + ps4NPAgeRating: 12 + ps4NPTitleSecret: + ps4NPTrophyPackPath: + ps4ParentalLevel: 11 + ps4ContentID: ED1633-NPXX51362_00-0000000000000000 + ps4Category: 0 + ps4MasterVersion: 01.00 + ps4AppVersion: 01.00 + ps4AppType: 0 + ps4ParamSfxPath: + ps4VideoOutPixelFormat: 0 + ps4VideoOutInitialWidth: 1920 + ps4VideoOutBaseModeInitialWidth: 1920 + ps4VideoOutReprojectionRate: 60 + ps4PronunciationXMLPath: + ps4PronunciationSIGPath: + ps4BackgroundImagePath: + ps4StartupImagePath: + ps4StartupImagesFolder: + ps4IconImagesFolder: + ps4SaveDataImagePath: + ps4SdkOverride: + ps4BGMPath: + ps4ShareFilePath: + ps4ShareOverlayImagePath: + ps4PrivacyGuardImagePath: + ps4ExtraSceSysFile: + ps4NPtitleDatPath: + ps4RemotePlayKeyAssignment: -1 + ps4RemotePlayKeyMappingDir: + ps4PlayTogetherPlayerCount: 0 + ps4EnterButtonAssignment: 1 + ps4ApplicationParam1: 0 + ps4ApplicationParam2: 0 + ps4ApplicationParam3: 0 + ps4ApplicationParam4: 0 + ps4DownloadDataSize: 0 + ps4GarlicHeapSize: 2048 + ps4ProGarlicHeapSize: 2560 + playerPrefsMaxSize: 32768 + ps4Passcode: frAQBc8Wsa1xVPfvJcrgRYwTiizs2trQ + ps4pnSessions: 1 + ps4pnPresence: 1 + ps4pnFriends: 1 + ps4pnGameCustomData: 1 + playerPrefsSupport: 0 + enableApplicationExit: 0 + resetTempFolder: 1 + restrictedAudioUsageRights: 0 + ps4UseResolutionFallback: 0 + ps4ReprojectionSupport: 0 + ps4UseAudio3dBackend: 0 + ps4UseLowGarlicFragmentationMode: 1 + ps4SocialScreenEnabled: 0 + ps4ScriptOptimizationLevel: 0 + ps4Audio3dVirtualSpeakerCount: 14 + ps4attribCpuUsage: 0 + ps4PatchPkgPath: + ps4PatchLatestPkgPath: + ps4PatchChangeinfoPath: + ps4PatchDayOne: 0 + ps4attribUserManagement: 0 + ps4attribMoveSupport: 0 + ps4attrib3DSupport: 0 + ps4attribShareSupport: 0 + ps4attribExclusiveVR: 0 + ps4disableAutoHideSplash: 0 + ps4videoRecordingFeaturesUsed: 0 + ps4contentSearchFeaturesUsed: 0 + ps4CompatibilityPS5: 0 + ps4AllowPS5Detection: 0 + ps4GPU800MHz: 1 + ps4attribEyeToEyeDistanceSettingVR: 0 + ps4IncludedModules: [] + ps4attribVROutputEnabled: 0 + monoEnv: + splashScreenBackgroundSourceLandscape: {fileID: 0} + splashScreenBackgroundSourcePortrait: {fileID: 0} + blurSplashScreenBackground: 1 + spritePackerPolicy: + webGLMemorySize: 16 + webGLExceptionSupport: 1 + webGLNameFilesAsHashes: 0 + webGLShowDiagnostics: 0 + webGLDataCaching: 1 + webGLDebugSymbols: 0 + webGLEmscriptenArgs: + webGLModulesDirectory: + webGLTemplate: APPLICATION:Default + webGLAnalyzeBuildSize: 0 + webGLUseEmbeddedResources: 0 + webGLCompressionFormat: 1 + webGLWasmArithmeticExceptions: 0 + webGLLinkerTarget: 1 + webGLThreadsSupport: 0 + webGLDecompressionFallback: 0 + webGLInitialMemorySize: 32 + webGLMaximumMemorySize: 2048 + webGLMemoryGrowthMode: 2 + webGLMemoryLinearGrowthStep: 16 + webGLMemoryGeometricGrowthStep: 0.2 + webGLMemoryGeometricGrowthCap: 96 + webGLPowerPreference: 2 + scriptingDefineSymbols: {} + additionalCompilerArguments: {} + platformArchitecture: {} + scriptingBackend: {} + il2cppCompilerConfiguration: {} + il2cppCodeGeneration: {} + managedStrippingLevel: + EmbeddedLinux: 1 + GameCoreScarlett: 1 + GameCoreXboxOne: 1 + Nintendo Switch: 1 + PS4: 1 + PS5: 1 + QNX: 1 + Stadia: 1 + WebGL: 1 + Windows Store Apps: 1 + XboxOne: 1 + iPhone: 1 + tvOS: 1 + incrementalIl2cppBuild: {} + suppressCommonWarnings: 1 + allowUnsafeCode: 0 + useDeterministicCompilation: 1 + selectedPlatform: 0 + additionalIl2CppArgs: + scriptingRuntimeVersion: 1 + gcIncremental: 1 + gcWBarrierValidation: 0 + apiCompatibilityLevelPerPlatform: {} + m_RenderingPath: 1 + m_MobileRenderingPath: 1 + metroPackageName: FirstStrike + metroPackageVersion: + metroCertificatePath: + metroCertificatePassword: + metroCertificateSubject: + metroCertificateIssuer: + metroCertificateNotAfter: 0000000000000000 + metroApplicationDescription: FirstStrike + wsaImages: {} + metroTileShortName: + metroTileShowName: 0 + metroMediumTileShowName: 0 + metroLargeTileShowName: 0 + metroWideTileShowName: 0 + metroSupportStreamingInstall: 0 + metroLastRequiredScene: 0 + metroDefaultTileSize: 1 + metroTileForegroundText: 2 + metroTileBackgroundColor: {r: 0.13333334, g: 0.17254902, b: 0.21568628, a: 0} + metroSplashScreenBackgroundColor: {r: 0.12941177, g: 0.17254902, b: 0.21568628, a: 1} + metroSplashScreenUseBackgroundColor: 0 + platformCapabilities: {} + metroTargetDeviceFamilies: {} + metroFTAName: + metroFTAFileTypes: [] + metroProtocolName: + vcxProjDefaultLanguage: + XboxOneProductId: + XboxOneUpdateKey: + XboxOneSandboxId: + XboxOneContentId: + XboxOneTitleId: + XboxOneSCId: + XboxOneGameOsOverridePath: + XboxOnePackagingOverridePath: + XboxOneAppManifestOverridePath: + XboxOneVersion: 1.0.0.0 + XboxOnePackageEncryption: 0 + XboxOnePackageUpdateGranularity: 2 + XboxOneDescription: + XboxOneLanguage: + - enus + XboxOneCapability: [] + XboxOneGameRating: {} + XboxOneIsContentPackage: 0 + XboxOneEnhancedXboxCompatibilityMode: 0 + XboxOneEnableGPUVariability: 1 + XboxOneSockets: {} + XboxOneSplashScreen: {fileID: 0} + XboxOneAllowedProductIds: [] + XboxOnePersistentLocalStorageSize: 0 + XboxOneXTitleMemory: 8 + XboxOneOverrideIdentityName: + XboxOneOverrideIdentityPublisher: + vrEditorSettings: {} + cloudServicesEnabled: + UNet: 1 + luminIcon: + m_Name: + m_ModelFolderPath: + m_PortalFolderPath: + luminCert: + m_CertPath: + m_SignPackage: 1 + luminIsChannelApp: 0 + luminVersion: + m_VersionCode: 1 + m_VersionName: + hmiPlayerDataPath: + hmiForceSRGBBlit: 1 + embeddedLinuxEnableGamepadInput: 1 + hmiLogStartupTiming: 0 + hmiCpuConfiguration: + apiCompatibilityLevel: 6 + activeInputHandler: 0 + windowsGamepadBackendHint: 0 + cloudProjectId: + framebufferDepthMemorylessMode: 0 + qualitySettingsNames: [] + projectName: + organizationId: + cloudEnabled: 0 + legacyClampBlendShapeWeights: 0 + hmiLoadingImage: {fileID: 0} + virtualTexturingSupportEnabled: 0 + insecureHttpOption: 0 diff --git a/ProjectSettings/ProjectVersion.txt b/ProjectSettings/ProjectVersion.txt new file mode 100644 index 0000000..e4e1acd --- /dev/null +++ b/ProjectSettings/ProjectVersion.txt @@ -0,0 +1,2 @@ +m_EditorVersion: 2022.2.15f1 +m_EditorVersionWithRevision: 2022.2.15f1 (30d813e1a2a9) diff --git a/ProjectSettings/QualitySettings.asset b/ProjectSettings/QualitySettings.asset new file mode 100644 index 0000000..7b7658d --- /dev/null +++ b/ProjectSettings/QualitySettings.asset @@ -0,0 +1,232 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!47 &1 +QualitySettings: + m_ObjectHideFlags: 0 + serializedVersion: 5 + m_CurrentQuality: 5 + m_QualitySettings: + - serializedVersion: 2 + name: Very Low + pixelLightCount: 0 + shadows: 0 + shadowResolution: 0 + shadowProjection: 1 + shadowCascades: 1 + shadowDistance: 15 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 0 + blendWeights: 1 + textureQuality: 1 + anisotropicTextures: 0 + antiAliasing: 0 + softParticles: 0 + softVegetation: 0 + realtimeReflectionProbes: 0 + billboardsFaceCameraPosition: 0 + vSyncCount: 0 + lodBias: 0.3 + maximumLODLevel: 0 + streamingMipmapsActive: 0 + streamingMipmapsAddAllCameras: 1 + streamingMipmapsMemoryBudget: 512 + streamingMipmapsRenderersPerFrame: 512 + streamingMipmapsMaxLevelReduction: 2 + streamingMipmapsMaxFileIORequests: 1024 + particleRaycastBudget: 4 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 16 + asyncUploadPersistentBuffer: 1 + resolutionScalingFixedDPIFactor: 1 + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: Low + pixelLightCount: 0 + shadows: 0 + shadowResolution: 0 + shadowProjection: 1 + shadowCascades: 1 + shadowDistance: 20 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 0 + blendWeights: 2 + textureQuality: 0 + anisotropicTextures: 0 + antiAliasing: 0 + softParticles: 0 + softVegetation: 0 + realtimeReflectionProbes: 0 + billboardsFaceCameraPosition: 0 + vSyncCount: 0 + lodBias: 0.4 + maximumLODLevel: 0 + streamingMipmapsActive: 0 + streamingMipmapsAddAllCameras: 1 + streamingMipmapsMemoryBudget: 512 + streamingMipmapsRenderersPerFrame: 512 + streamingMipmapsMaxLevelReduction: 2 + streamingMipmapsMaxFileIORequests: 1024 + particleRaycastBudget: 16 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 16 + asyncUploadPersistentBuffer: 1 + resolutionScalingFixedDPIFactor: 1 + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: Medium + pixelLightCount: 1 + shadows: 1 + shadowResolution: 0 + shadowProjection: 1 + shadowCascades: 1 + shadowDistance: 20 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 0 + blendWeights: 2 + textureQuality: 0 + anisotropicTextures: 1 + antiAliasing: 0 + softParticles: 0 + softVegetation: 0 + realtimeReflectionProbes: 0 + billboardsFaceCameraPosition: 0 + vSyncCount: 1 + lodBias: 0.7 + maximumLODLevel: 0 + streamingMipmapsActive: 0 + streamingMipmapsAddAllCameras: 1 + streamingMipmapsMemoryBudget: 512 + streamingMipmapsRenderersPerFrame: 512 + streamingMipmapsMaxLevelReduction: 2 + streamingMipmapsMaxFileIORequests: 1024 + particleRaycastBudget: 64 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 16 + asyncUploadPersistentBuffer: 1 + resolutionScalingFixedDPIFactor: 1 + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: High + pixelLightCount: 2 + shadows: 2 + shadowResolution: 1 + shadowProjection: 1 + shadowCascades: 2 + shadowDistance: 40 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 1 + blendWeights: 2 + textureQuality: 0 + anisotropicTextures: 1 + antiAliasing: 0 + softParticles: 0 + softVegetation: 1 + realtimeReflectionProbes: 1 + billboardsFaceCameraPosition: 1 + vSyncCount: 1 + lodBias: 1 + maximumLODLevel: 0 + streamingMipmapsActive: 0 + streamingMipmapsAddAllCameras: 1 + streamingMipmapsMemoryBudget: 512 + streamingMipmapsRenderersPerFrame: 512 + streamingMipmapsMaxLevelReduction: 2 + streamingMipmapsMaxFileIORequests: 1024 + particleRaycastBudget: 256 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 16 + asyncUploadPersistentBuffer: 1 + resolutionScalingFixedDPIFactor: 1 + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: Very High + pixelLightCount: 3 + shadows: 2 + shadowResolution: 2 + shadowProjection: 1 + shadowCascades: 2 + shadowDistance: 70 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 1 + blendWeights: 4 + textureQuality: 0 + anisotropicTextures: 2 + antiAliasing: 2 + softParticles: 1 + softVegetation: 1 + realtimeReflectionProbes: 1 + billboardsFaceCameraPosition: 1 + vSyncCount: 1 + lodBias: 1.5 + maximumLODLevel: 0 + streamingMipmapsActive: 0 + streamingMipmapsAddAllCameras: 1 + streamingMipmapsMemoryBudget: 512 + streamingMipmapsRenderersPerFrame: 512 + streamingMipmapsMaxLevelReduction: 2 + streamingMipmapsMaxFileIORequests: 1024 + particleRaycastBudget: 1024 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 16 + asyncUploadPersistentBuffer: 1 + resolutionScalingFixedDPIFactor: 1 + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: Ultra + pixelLightCount: 4 + shadows: 2 + shadowResolution: 2 + shadowProjection: 1 + shadowCascades: 4 + shadowDistance: 150 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 1 + blendWeights: 4 + textureQuality: 0 + anisotropicTextures: 2 + antiAliasing: 2 + softParticles: 1 + softVegetation: 1 + realtimeReflectionProbes: 1 + billboardsFaceCameraPosition: 1 + vSyncCount: 1 + lodBias: 2 + maximumLODLevel: 0 + streamingMipmapsActive: 0 + streamingMipmapsAddAllCameras: 1 + streamingMipmapsMemoryBudget: 512 + streamingMipmapsRenderersPerFrame: 512 + streamingMipmapsMaxLevelReduction: 2 + streamingMipmapsMaxFileIORequests: 1024 + particleRaycastBudget: 4096 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 16 + asyncUploadPersistentBuffer: 1 + resolutionScalingFixedDPIFactor: 1 + excludedTargetPlatforms: [] + m_PerPlatformDefaultQuality: + Android: 2 + Lumin: 5 + Nintendo 3DS: 5 + Nintendo Switch: 5 + PS4: 5 + PSP2: 2 + Stadia: 5 + Standalone: 5 + WebGL: 3 + Windows Store Apps: 5 + XboxOne: 5 + iPhone: 2 + tvOS: 2 diff --git a/ProjectSettings/SceneTemplateSettings.json b/ProjectSettings/SceneTemplateSettings.json new file mode 100644 index 0000000..6f3e60f --- /dev/null +++ b/ProjectSettings/SceneTemplateSettings.json @@ -0,0 +1,167 @@ +{ + "templatePinStates": [], + "dependencyTypeInfos": [ + { + "userAdded": false, + "type": "UnityEngine.AnimationClip", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEditor.Animations.AnimatorController", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.AnimatorOverrideController", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEditor.Audio.AudioMixerController", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.ComputeShader", + "ignore": true, + "defaultInstantiationMode": 1, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.Cubemap", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.GameObject", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEditor.LightingDataAsset", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": false + }, + { + "userAdded": false, + "type": "UnityEngine.LightingSettings", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.Material", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEditor.MonoScript", + "ignore": true, + "defaultInstantiationMode": 1, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.PhysicMaterial", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.PhysicsMaterial2D", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.Rendering.PostProcessing.PostProcessProfile", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.Rendering.PostProcessing.PostProcessResources", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.Rendering.VolumeProfile", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEditor.SceneAsset", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": false + }, + { + "userAdded": false, + "type": "UnityEngine.Shader", + "ignore": true, + "defaultInstantiationMode": 1, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.ShaderVariantCollection", + "ignore": true, + "defaultInstantiationMode": 1, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.Texture", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.Texture2D", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + }, + { + "userAdded": false, + "type": "UnityEngine.Timeline.TimelineAsset", + "ignore": false, + "defaultInstantiationMode": 0, + "supportsModification": true + } + ], + "defaultDependencyTypeInfo": { + "userAdded": false, + "type": "", + "ignore": false, + "defaultInstantiationMode": 1, + "supportsModification": true + }, + "newSceneOverride": 0 +} \ No newline at end of file diff --git a/ProjectSettings/TagManager.asset b/ProjectSettings/TagManager.asset new file mode 100644 index 0000000..1c92a78 --- /dev/null +++ b/ProjectSettings/TagManager.asset @@ -0,0 +1,43 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!78 &1 +TagManager: + serializedVersion: 2 + tags: [] + layers: + - Default + - TransparentFX + - Ignore Raycast + - + - Water + - UI + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + m_SortingLayers: + - name: Default + uniqueID: 0 + locked: 0 diff --git a/ProjectSettings/TimeManager.asset b/ProjectSettings/TimeManager.asset new file mode 100644 index 0000000..558a017 --- /dev/null +++ b/ProjectSettings/TimeManager.asset @@ -0,0 +1,9 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!5 &1 +TimeManager: + m_ObjectHideFlags: 0 + Fixed Timestep: 0.02 + Maximum Allowed Timestep: 0.33333334 + m_TimeScale: 1 + Maximum Particle Timestep: 0.03 diff --git a/ProjectSettings/UnityConnectSettings.asset b/ProjectSettings/UnityConnectSettings.asset new file mode 100644 index 0000000..a88bee0 --- /dev/null +++ b/ProjectSettings/UnityConnectSettings.asset @@ -0,0 +1,36 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!310 &1 +UnityConnectSettings: + m_ObjectHideFlags: 0 + serializedVersion: 1 + m_Enabled: 0 + m_TestMode: 0 + m_EventOldUrl: https://api.uca.cloud.unity3d.com/v1/events + m_EventUrl: https://cdp.cloud.unity3d.com/v1/events + m_ConfigUrl: https://config.uca.cloud.unity3d.com + m_DashboardUrl: https://dashboard.unity3d.com + m_TestInitMode: 0 + CrashReportingSettings: + m_EventUrl: https://perf-events.cloud.unity3d.com + m_Enabled: 0 + m_LogBufferSize: 10 + m_CaptureEditorExceptions: 1 + UnityPurchasingSettings: + m_Enabled: 0 + m_TestMode: 0 + UnityAnalyticsSettings: + m_Enabled: 0 + m_TestMode: 0 + m_InitializeOnStartup: 1 + m_PackageRequiringCoreStatsPresent: 0 + UnityAdsSettings: + m_Enabled: 0 + m_InitializeOnStartup: 1 + m_TestMode: 0 + m_IosGameId: + m_AndroidGameId: + m_GameIds: {} + m_GameId: + PerformanceReportingSettings: + m_Enabled: 0 diff --git a/ProjectSettings/VFXManager.asset b/ProjectSettings/VFXManager.asset new file mode 100644 index 0000000..3a95c98 --- /dev/null +++ b/ProjectSettings/VFXManager.asset @@ -0,0 +1,12 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!937362698 &1 +VFXManager: + m_ObjectHideFlags: 0 + m_IndirectShader: {fileID: 0} + m_CopyBufferShader: {fileID: 0} + m_SortShader: {fileID: 0} + m_StripUpdateShader: {fileID: 0} + m_RenderPipeSettingsPath: + m_FixedTimeStep: 0.016666668 + m_MaxDeltaTime: 0.05 diff --git a/ProjectSettings/VersionControlSettings.asset b/ProjectSettings/VersionControlSettings.asset new file mode 100644 index 0000000..dca2881 --- /dev/null +++ b/ProjectSettings/VersionControlSettings.asset @@ -0,0 +1,8 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!890905787 &1 +VersionControlSettings: + m_ObjectHideFlags: 0 + m_Mode: Visible Meta Files + m_CollabEditorSettings: + inProgressEnabled: 1 diff --git a/ProjectSettings/XRSettings.asset b/ProjectSettings/XRSettings.asset new file mode 100644 index 0000000..482590c --- /dev/null +++ b/ProjectSettings/XRSettings.asset @@ -0,0 +1,10 @@ +{ + "m_SettingKeys": [ + "VR Device Disabled", + "VR Device User Alert" + ], + "m_SettingValues": [ + "False", + "False" + ] +} \ No newline at end of file