diff --git a/CodeWalker.Core/GameFiles/FileTypes/YndFile.cs b/CodeWalker.Core/GameFiles/FileTypes/YndFile.cs index e50366f..e862631 100644 --- a/CodeWalker.Core/GameFiles/FileTypes/YndFile.cs +++ b/CodeWalker.Core/GameFiles/FileTypes/YndFile.cs @@ -63,7 +63,7 @@ namespace CodeWalker.GameFiles { //direct load from a raw, compressed ynd file (openIV-compatible format) - RpfFile.LoadResourceFile(this, data, 2); + RpfFile.LoadResourceFile(this, data, 1); Loaded = true; LoadQueued = true; diff --git a/CodeWalker.Core/GameFiles/FileTypes/YnvFile.cs b/CodeWalker.Core/GameFiles/FileTypes/YnvFile.cs index 583942b..6923ce1 100644 --- a/CodeWalker.Core/GameFiles/FileTypes/YnvFile.cs +++ b/CodeWalker.Core/GameFiles/FileTypes/YnvFile.cs @@ -17,6 +17,7 @@ namespace CodeWalker.GameFiles public List Polys { get; set; } + public EditorVertex[] PathVertices { get; set; } public EditorVertex[] TriangleVerts { get; set; } public Vector4[] NodePositions { get; set; } @@ -33,7 +34,13 @@ namespace CodeWalker.GameFiles { return (int)(Nav?.AreaID ?? 0); } + set + { + if (Nav != null) Nav.AreaID = (uint)value; + } } + public int CellX { get { return AreaID % 100; } set { AreaID = (CellY * 100) + value; } } + public int CellY { get { return AreaID / 100; } set { AreaID = (value * 100) + CellX; } } @@ -45,6 +52,15 @@ namespace CodeWalker.GameFiles { } + public void Load(byte[] data) + { + //direct load from a raw, compressed ynv file (openIV-compatible format) + + RpfFile.LoadResourceFile(this, data, 2); + + Loaded = true; + } + public void Load(byte[] data, RpfFileEntry entry) { Name = entry.Name; @@ -135,8 +151,68 @@ namespace CodeWalker.GameFiles } + public byte[] Save() + { + BuildStructs(); + + byte[] data = ResourceBuilder.Build(Nav, 2); //ynv is version 2... + + return data; + } + + public void BuildStructs() + { + Vector3 posoffset = Nav.SectorTree?.AABBMin.XYZ() ?? Vector3.Zero; + Vector3 aabbsize = Nav.AABBSize; + Vector3 aabbsizeinv = 1.0f / aabbsize; + + var vertlist = new List(); + if (Vertices != null) + { + for (int i = 0; i < Vertices.Count; i++) + { + var ov = (Vertices[i] - posoffset) * aabbsizeinv; + vertlist.Add(NavMeshVertex.Create(ov)); + } + } + if (Nav.Vertices == null) + { + Nav.Vertices = new NavMeshList(); + Nav.Vertices.VFT = 1080158456; + } + Nav.Vertices.RebuildList(vertlist); + + if (Nav.Indices == null) + { + Nav.Indices = new NavMeshList(); + Nav.Indices.VFT = 1080158424; + } + Nav.Indices.RebuildList(Indices); + + var polylist = new List(); + if (Polys != null) + { + for (int i = 0; i < Polys.Count; i++) + { + polylist.Add(Polys[i].RawData); + } + } + if (Nav.Polys == null) + { + Nav.Polys = new NavMeshList(); + Nav.Polys.VFT = 1080158408; + } + Nav.Polys.RebuildList(polylist); + if (Nav.AdjPolys == null) + { + Nav.AdjPolys = new NavMeshList(); + Nav.AdjPolys.VFT = 1080158440; + } + //Nav.AdjPolys.RebuildList(...) + + } @@ -175,6 +251,62 @@ namespace CodeWalker.GameFiles np[i] = new Vector4(posoffset + pv * aabbsize, 1.0f); } NodePositions = np; + + + + int lcnt = Nav.PortalLinks?.Length ?? 0; + if (lcnt <= 0) + { + PathVertices = null; + return; + } + + //var lv = new EditorVertex[lcnt]; + //for (int i = 0; i < lcnt; i++) + //{ + // var pl = Nav.PortalLinks[i]; + // if (pl >= np.Length) lv[i] = new EditorVertex(); + // else + // { + // lv[i].Position = np[pl].XYZ(); + // lv[i].Colour = 0xFF0000FF; + // } + //} + //PathVertices = lv; + + EditorVertex v = new EditorVertex(); + v.Colour = 0xFF0000FF; + var lv = new List(); + //int cind = 0; + var plinks = Nav.PortalLinks; + for (int i = 0; i < cnt; i++) + { + var portal = Nav.Portals[i]; + + //var plcnt = 2; + + v.Position = posoffset + portal.Position1.ToVector3() * aabbsize; + lv.Add(v); + v.Position = posoffset + portal.Position2.ToVector3() * aabbsize; + lv.Add(v); + + + //var plcnt = portal.LinkCount; + //if (plcnt < 2) continue; + //var plink = (cind < plinks.Length) ? plinks[cind] : 0xFFFF; + //var ppos = (plink < np.Length) ? np[plink].XYZ() : Vector3.Zero; + //for (int pl = 1; pl < plcnt; pl++) + //{ + // var ind2 = cind + pl; + // var plink2 = (ind2 < plinks.Length) ? plinks[ind2] : 0xFFFF; + // var ppos2 = (plink2 < np.Length) ? np[plink2].XYZ() : Vector3.Zero; + // v.Position = ppos; lv.Add(v); + // v.Position = ppos2; lv.Add(v); + //} + //cind += plcnt; + } + PathVertices = lv.ToArray(); + } public void UpdateTriangleVertices() @@ -259,7 +391,7 @@ namespace CodeWalker.GameFiles public EditorVertex[] GetPathVertices() { - return null; + return PathVertices; } public EditorVertex[] GetTriangleVertices() { @@ -280,46 +412,52 @@ namespace CodeWalker.GameFiles public YnvFile Ynv { get; set; } public NavMeshPoly RawData { get { return _RawData; } set { _RawData = value; } } - public ushort AreaID { get { return _RawData.AreaID; } } - public bool B00_AvoidUnk { get { return (_RawData.Unknown_00h & 1) > 0; } } - public bool B01_AvoidUnk { get { return (_RawData.Unknown_00h & 2) > 0; } } - public bool B02_IsFootpath { get { return (_RawData.Unknown_00h & 4) > 0; } } - public bool B03_IsUnderground { get { return (_RawData.Unknown_00h & 8) > 0; } } - //public bool B04_Unused { get { return (_RawData.Unknown_00h & 16) > 0; } } - //public bool B05_Unused { get { return (_RawData.Unknown_00h & 32) > 0; } } - public bool B06_SteepSlope { get { return (_RawData.Unknown_00h & 64) > 0; } } - public bool B07_IsWater { get { return (_RawData.Unknown_00h & 128) > 0; } } - public bool B08_UndergroundUnk1 { get { return (_RawData.Unknown_24h.Value & 1) > 0; } } - public bool B09_UndergroundUnk2 { get { return (_RawData.Unknown_24h.Value & 2) > 0; } } - public bool B10_UndergroundUnk3 { get { return (_RawData.Unknown_24h.Value & 4) > 0; } } - public bool B11_UndergroundUnk4 { get { return (_RawData.Unknown_24h.Value & 8) > 0; } } - //public bool B12_Unused { get { return (_RawData.Unknown_24h.Value & 16) > 0; } } - public bool B13_HasPathNode { get { return (_RawData.Unknown_24h.Value & 32) > 0; } } - public bool B14_IsInterior { get { return (_RawData.Unknown_24h.Value & 64) > 0; } } - public bool B15_InteractionUnk { get { return (_RawData.Unknown_24h.Value & 128) > 0; } } - //public bool B16_Unused { get { return (_RawData.Unknown_24h.Value & 256) > 0; } } - public bool B17_IsFlatGround { get { return (_RawData.Unknown_24h.Value & 512) > 0; } } - public bool B18_IsRoad { get { return (_RawData.Unknown_24h.Value & 1024) > 0; } } - public bool B19_IsCellEdge { get { return (_RawData.Unknown_24h.Value & 2048) > 0; } } - public bool B20_IsTrainTrack { get { return (_RawData.Unknown_24h.Value & 4096) > 0; } } - public bool B21_IsShallowWater { get { return (_RawData.Unknown_24h.Value & 8192) > 0; } } - public bool B22_FootpathUnk1 { get { return (_RawData.Unknown_24h.Value & 16384) > 0; } } - public bool B23_FootpathUnk2 { get { return (_RawData.Unknown_24h.Value & 32768) > 0; } } - public bool B24_FootpathMall { get { return (_RawData.Unknown_24h.Value & 65536) > 0; } } - public bool B25_SlopeSouth { get { return (_RawData.Unknown_28h.Value & 65536) > 0; } } - public bool B26_SlopeSouthEast { get { return (_RawData.Unknown_28h.Value & 131072) > 0; } } - public bool B27_SlopeEast { get { return (_RawData.Unknown_28h.Value & 262144) > 0; } } - public bool B28_SlopeNorthEast { get { return (_RawData.Unknown_28h.Value & 524288) > 0; } } - public bool B29_SlopeNorth { get { return (_RawData.Unknown_28h.Value & 1048576) > 0; } } - public bool B30_SlopeNorthWest { get { return (_RawData.Unknown_28h.Value & 2097152) > 0; } } - public bool B31_SlopeWest { get { return (_RawData.Unknown_28h.Value & 4194304) > 0; } } - public bool B32_SlopeSouthWest { get { return (_RawData.Unknown_28h.Value & 8388608) > 0; } } - public bool B33_PortalUnk1 { get { return (_RawData.PartUnk2 & 1) > 0; } } - public bool B34_PortalUnk2 { get { return (_RawData.PartUnk2 & 2) > 0; } } - public bool B35_PortalUnk3 { get { return (_RawData.PartUnk2 & 4) > 0; } } - public bool B36_PortalUnk4 { get { return (_RawData.PartUnk2 & 8) > 0; } } - public byte HeuristicXUnk { get { return (byte)_RawData.Unknown_28h_8a; } } - public byte HeuristicYUnk { get { return (byte)_RawData.Unknown_28h_8b; } } + public ushort AreaID { get { return _RawData.AreaID; } set { _RawData.AreaID = value; } } + public ushort PartID { get { return _RawData.PartID; } set { _RawData.PartID = value; } } + public ushort PortalID { get { return _RawData.PortalID; } set { _RawData.PortalID = value; } } + public byte Flags1 { get { return (byte)(_RawData.Unknown_00h & 0xFF); } set { _RawData.Unknown_00h = (ushort)((_RawData.Unknown_00h & 0xFF00) | (value & 0xFF)); } } + public byte Flags2 { get { return (byte)((_RawData.Unknown_24h.Value >> 0) & 0xFF); } set { _RawData.Unknown_24h = ((_RawData.Unknown_24h.Value & 0xFFFFFF00u) | ((value & 0xFFu) << 0)); } } + public byte Flags3 { get { return (byte)((_RawData.Unknown_24h.Value >> 9) & 0xFF); } set { _RawData.Unknown_24h = ((_RawData.Unknown_24h.Value & 0xFFFE01FFu) | ((value & 0xFFu) << 9)); } } + public byte Flags4 { get { return (byte)((_RawData.Unknown_28h.Value >> 16) & 0xFF); } set { _RawData.Unknown_28h = ((_RawData.Unknown_28h.Value & 0x0000FFFFu) | ((value & 0xFFu) << 16)); } } + public bool B00_AvoidUnk { get { return (_RawData.Unknown_00h & 1) > 0; } set { _RawData.Unknown_00h = (ushort)BitUtil.UpdateBit(_RawData.Unknown_00h, 0, value); } } + public bool B01_AvoidUnk { get { return (_RawData.Unknown_00h & 2) > 0; } set { _RawData.Unknown_00h = (ushort)BitUtil.UpdateBit(_RawData.Unknown_00h, 1, value); } } + public bool B02_IsFootpath { get { return (_RawData.Unknown_00h & 4) > 0; } set { _RawData.Unknown_00h = (ushort)BitUtil.UpdateBit(_RawData.Unknown_00h, 2, value); } } + public bool B03_IsUnderground { get { return (_RawData.Unknown_00h & 8) > 0; } set { _RawData.Unknown_00h = (ushort)BitUtil.UpdateBit(_RawData.Unknown_00h, 3, value); } } + //public bool B04_Unused { get { return (_RawData.Unknown_00h & 16) > 0; } set { _RawData.Unknown_00h = (ushort)BitUtil.UpdateBit(_RawData.Unknown_00h, 4, value); } } + //public bool B05_Unused { get { return (_RawData.Unknown_00h & 32) > 0; } set { _RawData.Unknown_00h = (ushort)BitUtil.UpdateBit(_RawData.Unknown_00h, 5, value); } } + public bool B06_SteepSlope { get { return (_RawData.Unknown_00h & 64) > 0; } set { _RawData.Unknown_00h = (ushort)BitUtil.UpdateBit(_RawData.Unknown_00h, 6, value); } } + public bool B07_IsWater { get { return (_RawData.Unknown_00h & 128) > 0; } set { _RawData.Unknown_00h = (ushort)BitUtil.UpdateBit(_RawData.Unknown_00h, 7, value); } } + public bool B08_UndergroundUnk0 { get { return (_RawData.Unknown_24h.Value & 1) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 0, value); } } + public bool B09_UndergroundUnk1 { get { return (_RawData.Unknown_24h.Value & 2) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 1, value); } } + public bool B10_UndergroundUnk2 { get { return (_RawData.Unknown_24h.Value & 4) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 2, value); } } + public bool B11_UndergroundUnk3 { get { return (_RawData.Unknown_24h.Value & 8) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 3, value); } } + //public bool B12_Unused { get { return (_RawData.Unknown_24h.Value & 16) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 4, value); } } + public bool B13_HasPathNode { get { return (_RawData.Unknown_24h.Value & 32) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 5, value); } } + public bool B14_IsInterior { get { return (_RawData.Unknown_24h.Value & 64) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 6, value); } } + public bool B15_InteractionUnk { get { return (_RawData.Unknown_24h.Value & 128) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 7, value); } } + //public bool B16_Unused { get { return (_RawData.Unknown_24h.Value & 256) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 8, value); } } + public bool B17_IsFlatGround { get { return (_RawData.Unknown_24h.Value & 512) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 9, value); } } + public bool B18_IsRoad { get { return (_RawData.Unknown_24h.Value & 1024) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 10, value); } } + public bool B19_IsCellEdge { get { return (_RawData.Unknown_24h.Value & 2048) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 11, value); } } + public bool B20_IsTrainTrack { get { return (_RawData.Unknown_24h.Value & 4096) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 12, value); } } + public bool B21_IsShallowWater { get { return (_RawData.Unknown_24h.Value & 8192) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 13, value); } } + public bool B22_FootpathUnk1 { get { return (_RawData.Unknown_24h.Value & 16384) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 14, value); } } + public bool B23_FootpathUnk2 { get { return (_RawData.Unknown_24h.Value & 32768) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 15, value); } } + public bool B24_FootpathMall { get { return (_RawData.Unknown_24h.Value & 65536) > 0; } set { _RawData.Unknown_24h = BitUtil.UpdateBit(_RawData.Unknown_24h.Value, 16, value); } } + public bool B25_SlopeSouth { get { return (_RawData.Unknown_28h.Value & 65536) > 0; } set { _RawData.Unknown_28h = BitUtil.UpdateBit(_RawData.Unknown_28h.Value, 16, value); } } + public bool B26_SlopeSouthEast { get { return (_RawData.Unknown_28h.Value & 131072) > 0; } set { _RawData.Unknown_28h = BitUtil.UpdateBit(_RawData.Unknown_28h.Value, 17, value); } } + public bool B27_SlopeEast { get { return (_RawData.Unknown_28h.Value & 262144) > 0; } set { _RawData.Unknown_28h = BitUtil.UpdateBit(_RawData.Unknown_28h.Value, 18, value); } } + public bool B28_SlopeNorthEast { get { return (_RawData.Unknown_28h.Value & 524288) > 0; } set { _RawData.Unknown_28h = BitUtil.UpdateBit(_RawData.Unknown_28h.Value, 19, value); } } + public bool B29_SlopeNorth { get { return (_RawData.Unknown_28h.Value & 1048576) > 0; } set { _RawData.Unknown_28h = BitUtil.UpdateBit(_RawData.Unknown_28h.Value, 20, value); } } + public bool B30_SlopeNorthWest { get { return (_RawData.Unknown_28h.Value & 2097152) > 0; } set { _RawData.Unknown_28h = BitUtil.UpdateBit(_RawData.Unknown_28h.Value, 21, value); } } + public bool B31_SlopeWest { get { return (_RawData.Unknown_28h.Value & 4194304) > 0; } set { _RawData.Unknown_28h = BitUtil.UpdateBit(_RawData.Unknown_28h.Value, 22, value); } } + public bool B32_SlopeSouthWest { get { return (_RawData.Unknown_28h.Value & 8388608) > 0; } set { _RawData.Unknown_28h = BitUtil.UpdateBit(_RawData.Unknown_28h.Value, 23, value); } } + //public bool B33_PortalUnk1 { get { return (_RawData.PartUnk2 & 1) > 0; } } + //public bool B34_PortalUnk2 { get { return (_RawData.PartUnk2 & 2) > 0; } } + //public bool B35_PortalUnk3 { get { return (_RawData.PartUnk2 & 4) > 0; } } + //public bool B36_PortalUnk4 { get { return (_RawData.PartUnk2 & 8) > 0; } } + public byte UnkX { get { return _RawData.Unknown_28h_8a; } set { _RawData.Unknown_28h_8a = value; } } + public byte UnkY { get { return _RawData.Unknown_28h_8b; } set { _RawData.Unknown_28h_8b = value; } } public Vector3 Position { get; set; } @@ -346,6 +484,7 @@ namespace CodeWalker.GameFiles ////if ((u0 & 32) > 0) colour.Green += 1.0f;//not used? if ((u0 & 64) > 0) colour.Red += 0.25f; //steep slope if ((u0 & 128) > 0) colour.Blue += 0.25f; //water + //if (u0 >= 256) colour.Green += 1.0f;//other bits unused... var u2 = _RawData.Unknown_24h.Value; //colour.Green = (u2 & 15) / 15.0f; //maybe underground amount..? diff --git a/CodeWalker.Core/GameFiles/Resources/Nav.cs b/CodeWalker.Core/GameFiles/Resources/Nav.cs index b85c2a3..3eb3ebd 100644 --- a/CodeWalker.Core/GameFiles/Resources/Nav.cs +++ b/CodeWalker.Core/GameFiles/Resources/Nav.cs @@ -287,6 +287,42 @@ namespace CodeWalker.GameFiles } return vals; } + set + { + Count = (uint)value.Length; + v00 = (Count > 0) ? value[0] : 0; + v01 = (Count > 1) ? value[1] : 0; + v02 = (Count > 2) ? value[2] : 0; + v03 = (Count > 3) ? value[3] : 0; + v04 = (Count > 4) ? value[4] : 0; + v05 = (Count > 5) ? value[5] : 0; + v06 = (Count > 6) ? value[6] : 0; + v07 = (Count > 7) ? value[7] : 0; + v08 = (Count > 8) ? value[8] : 0; + v09 = (Count > 9) ? value[9] : 0; + v10 = (Count > 10) ? value[10] : 0; + v11 = (Count > 11) ? value[11] : 0; + v12 = (Count > 12) ? value[12] : 0; + v13 = (Count > 13) ? value[13] : 0; + v14 = (Count > 14) ? value[14] : 0; + v15 = (Count > 15) ? value[15] : 0; + v16 = (Count > 16) ? value[16] : 0; + v17 = (Count > 17) ? value[17] : 0; + v18 = (Count > 18) ? value[18] : 0; + v19 = (Count > 19) ? value[19] : 0; + v20 = (Count > 20) ? value[20] : 0; + v21 = (Count > 21) ? value[21] : 0; + v22 = (Count > 22) ? value[22] : 0; + v23 = (Count > 23) ? value[23] : 0; + v24 = (Count > 24) ? value[24] : 0; + v25 = (Count > 25) ? value[25] : 0; + v26 = (Count > 26) ? value[26] : 0; + v27 = (Count > 27) ? value[27] : 0; + v28 = (Count > 28) ? value[28] : 0; + v29 = (Count > 29) ? value[29] : 0; + v30 = (Count > 30) ? value[30] : 0; + v31 = (Count > 31) ? value[31] : 0; + } } @@ -319,7 +355,8 @@ namespace CodeWalker.GameFiles public uint[] ListOffsets { get; set; } private ResourceSystemStructBlock ListOffsetsBlock = null; - + public int ItemSize { get { return System.Runtime.InteropServices.Marshal.SizeOf(); } } + //public int BytesPerPart { get; private set; } public override void Read(ResourceDataReader reader, params object[] parameters) { @@ -337,6 +374,11 @@ namespace CodeWalker.GameFiles ListParts = reader.ReadBlockAt>>(ListPartsPointer, ListPartsCount); ListOffsets = reader.ReadUintsAt(ListOffsetsPointer, ListPartsCount); + //if (ListParts.Count > 0) + //{ + // BytesPerPart = (int)ListParts[0].Count * ItemSize; + //} + } public override void Write(ResourceDataWriter writer, params object[] parameters) @@ -392,6 +434,40 @@ namespace CodeWalker.GameFiles } + public void RebuildList(List items) + { + + //max bytes per part: 16384 + int maxpartbytes = 16384; //0x4000 + int itembytes = ItemSize; + int itemsperpart = maxpartbytes / itembytes; + int currentitem = 0; + + var parts = new ResourceSimpleArray>(); + var partitems = new List(); + var offsets = new List(); + + while (currentitem < items.Count) + { + partitems.Clear(); + int lastitem = currentitem + itemsperpart; + if (lastitem > items.Count) lastitem = items.Count; + for (int i = currentitem; i < lastitem; i++) + { + partitems.Add(items[i]); + } + var part = new NavMeshListPart(); + part.Items = partitems.ToArray(); + part.Unknown_0Ch = 0; + parts.Add(part); + offsets.Add((uint)currentitem); + currentitem = lastitem; + } + ListParts = parts; + ListOffsets = offsets.ToArray(); + + } + public override string ToString() { @@ -478,6 +554,13 @@ namespace CodeWalker.GameFiles Z = (ushort)(v.Z * usmax); } + public static NavMeshVertex Create(Vector3 v) + { + var nmv = new NavMeshVertex(); + nmv.FromVector3(v); + return nmv; + } + public override string ToString() { return X.ToString() + ", " + Y.ToString() + ", " + Z.ToString(); @@ -514,7 +597,7 @@ namespace CodeWalker.GameFiles public override string ToString() { - return Unknown_0h.Bin + " | " + Unknown_4h.Bin + " | " + + return //Unknown_0h.Bin + " | " + Unknown_4h.Bin + " | " + Unknown_0h.ToString() + " | " + Unknown_4h.ToString(); } } @@ -565,13 +648,13 @@ namespace CodeWalker.GameFiles public int IndexCount { get { return (IndexFlags >> 5); } } //public int PartUnk1 { get { return (PartFlags >> 0) & 0xF; } } //always 0 - public int PartID { get { return (PartFlags >> 4) & 0xFF; } } - public int PartUnk2 { get { return (PartFlags >> 12) & 0xF; } } + public ushort PartID { get { return (ushort)((PartFlags >> 4) & 0xFF); } set { PartFlags = (ushort)((PartFlags & 0xF00F) | ((value & 0xFF) << 4)); } } + public byte PartUnk2 { get { return (byte)((PartFlags >> 12) & 0xF); } set { PartFlags = (ushort)((PartFlags & 0x0FFF) | ((value & 0xF) << 12)); } } - public uint Unknown_28h_16 { get { return ((Unknown_28h.Value & 65535)); } } - public uint Unknown_28h_8a { get { return ((Unknown_28h.Value >> 0) & 255); } } - public uint Unknown_28h_8b { get { return ((Unknown_28h.Value >> 8) & 255); } } + public ushort Unknown_28h_16 { get { return (ushort)((Unknown_28h.Value & 0xFFFF)); } set { Unknown_28h = (Unknown_28h.Value & 0xFFFF0000) | (value & 0xFFFFu); } } + public byte Unknown_28h_8a { get { return (byte)((Unknown_28h.Value >> 0) & 0xFF); } set { Unknown_28h = (Unknown_28h.Value & 0xFFFFFF00) | ((value & 0xFFu)<<0); } } + public byte Unknown_28h_8b { get { return (byte)((Unknown_28h.Value >> 8) & 0xFF); } set { Unknown_28h = (Unknown_28h.Value & 0xFFFF00FF) | ((value & 0xFFu)<<8); } } public override string ToString() @@ -686,7 +769,7 @@ namespace CodeWalker.GameFiles get { return 32; } } - public uint UnkOffset { get; set; } + public uint UnkDataStartID { get; set; } public uint Unused_04h { get; set; } // 0x00000000 public ulong PolyIDsPointer { get; set; } public ulong UnkDataPointer { get; set; } @@ -702,7 +785,7 @@ namespace CodeWalker.GameFiles public override void Read(ResourceDataReader reader, params object[] parameters) { - UnkOffset = reader.ReadUInt32(); + UnkDataStartID = reader.ReadUInt32(); Unused_04h = reader.ReadUInt32(); PolyIDsPointer = reader.ReadUInt64(); UnkDataPointer = reader.ReadUInt64(); @@ -723,7 +806,7 @@ namespace CodeWalker.GameFiles UnkDataCount = (ushort)(UnkData?.Length ?? 0); - writer.Write(UnkOffset); + writer.Write(UnkDataStartID); writer.Write(Unused_04h); writer.Write(PolyIDsPointer); writer.Write(UnkDataPointer); @@ -753,7 +836,7 @@ namespace CodeWalker.GameFiles public override string ToString() { - return "(Polys: " + PolyIDsCount.ToString() + ", UnkOffset: " + UnkOffset.ToString() + ", UnkCount: " + UnkDataCount.ToString() + ")"; + return "(Polys: " + PolyIDsCount.ToString() + ", UnkOffset: " + UnkDataStartID.ToString() + ", UnkCount: " + UnkDataCount.ToString() + ")"; } } @@ -783,17 +866,22 @@ namespace CodeWalker.GameFiles public ushort Unknown_16h { get; set; } public ushort Unknown_18h { get; set; } public ushort Unknown_1Ah { get; set; } - //public NavMeshAABB AABB1 { get; set; } - //public NavMeshAABB AABB2 { get; set; } + //public NavMeshAABB AABB { get; set; } + + public uint Type1 { get { return Unknown_00h & 0xFF; } } + public uint Type2 { get { return (Unknown_00h >> 8) & 0xF; } } + public uint Type3 { get { return (Unknown_00h >> 12) & 0xF; } } + public uint Type4 { get { return (Unknown_00h >> 16) & 0xFFFF; } } public override string ToString() { - return Unknown_00h.ToString() + ", " + + return //Unknown_00h.ToString() + ", " + Unknown_01h.ToString() + ", " + Unknown_02h.ToString() + ", " + + Type1.ToString() + ", " + Type2.ToString() + ", " + Type3.ToString() + ", " + Type4.ToString() + ", " + Position1.ToString() + ", " + Position2.ToString() + ", " + Unknown_10h.ToString() + ", " + Unknown_12h.ToString() + ", " + Unknown_14h.ToString() + ", " + Unknown_16h.ToString() + ", " + Unknown_18h.ToString() + ", " + Unknown_1Ah.ToString(); - //AABB1.ToString() + ", " + AABB2.ToString(); + //AABB.ToString(); } } @@ -802,6 +890,7 @@ namespace CodeWalker.GameFiles [Flags] public enum NavMeshFlags : uint { + None = 0, Vertices = 1, Portals = 2, Vehicle = 4, diff --git a/Forms/ModelForm.cs b/Forms/ModelForm.cs index 7d75d3c..38ad89b 100644 --- a/Forms/ModelForm.cs +++ b/Forms/ModelForm.cs @@ -594,7 +594,7 @@ namespace CodeWalker.Forms FileName = ynv.Name; Ynv = ynv; - //UpdateModelsUI(ypt.Particles.Drawable); + UpdateNavmeshUI(ynv); } @@ -832,7 +832,7 @@ namespace CodeWalker.Forms } private void UpdateNavmeshUI(YnvFile ynv) { - DetailsPropertyGrid.SelectedObject = ynv.Nav; + DetailsPropertyGrid.SelectedObject = ynv; } diff --git a/Project/Panels/EditProjectManifestPanel.cs b/Project/Panels/EditProjectManifestPanel.cs index 27e99b5..d15cb87 100644 --- a/Project/Panels/EditProjectManifestPanel.cs +++ b/Project/Panels/EditProjectManifestPanel.cs @@ -57,8 +57,9 @@ namespace CodeWalker.Project.Panels private void GenerateProjectManifest() { - StringBuilder sb = new StringBuilder(); - Dictionary deps = new Dictionary(); + var sb = new StringBuilder(); + var mapdeps = new Dictionary(); + var typdeps = new Dictionary>(); sb.AppendLine(""); sb.AppendLine(""); @@ -67,6 +68,25 @@ namespace CodeWalker.Project.Panels sb.AppendLine(" "); + var getYtypName = new Func((ytyp) => + { + var ytypname = ytyp?.RpfFileEntry?.NameLower; + if (ytyp != null) + { + if (string.IsNullOrEmpty(ytypname)) + { + ytypname = ytyp.RpfFileEntry?.Name?.ToLowerInvariant(); + if (ytypname == null) ytypname = ""; + } + if (ytypname.EndsWith(".ytyp")) + { + ytypname = ytypname.Substring(0, ytypname.Length - 5); + } + } + return ytypname; + }); + + if ((CurrentProjectFile != null) && (CurrentProjectFile.YmapFiles.Count > 0)) { sb.AppendLine(" "); @@ -82,26 +102,40 @@ namespace CodeWalker.Project.Panels ymapname = ymapname.Substring(0, ymapname.Length - 5); } - deps.Clear(); + mapdeps.Clear(); if (ymap.AllEntities != null) { foreach (var ent in ymap.AllEntities) { var ytyp = ent.Archetype?.Ytyp; + var ytypname = getYtypName(ytyp); if (ytyp != null) { - var ytypname = ytyp.RpfFileEntry?.NameLower; - if (string.IsNullOrEmpty(ytypname)) - { - ytypname = ytyp.RpfFileEntry?.Name?.ToLowerInvariant(); - if (ytypname == null) ytypname = ""; - } - if (ytypname.EndsWith(".ytyp")) - { - ytypname = ytypname.Substring(0, ytypname.Length - 5); - } - deps[ytypname] = ytyp; + mapdeps[ytypname] = ytyp; } + + if (ent.IsMlo) + { + if (ent.MloInstance?.Entities != null) + { + Dictionary typdepdict; + if (!typdeps.TryGetValue(ytypname, out typdepdict)) + { + typdepdict = new Dictionary(); + typdeps[ytypname] = typdepdict; + } + foreach (var ient in ent.MloInstance.Entities) + { + var iytyp = ient.Archetype?.Ytyp; + var iytypname = getYtypName(iytyp); + if ((iytyp != null) && (iytypname != ytypname)) + { + typdepdict[iytypname] = iytyp; + } + } + } + } + } } @@ -109,7 +143,7 @@ namespace CodeWalker.Project.Panels sb.AppendLine(" " + ymapname + ""); sb.AppendLine(" "); sb.AppendLine(" "); - foreach (var kvp in deps) + foreach (var kvp in mapdeps) { sb.AppendLine(" " + kvp.Key + ""); } @@ -123,7 +157,29 @@ namespace CodeWalker.Project.Panels sb.AppendLine(" "); } - sb.AppendLine(" "); + if (typdeps.Count > 0) + { + sb.AppendLine(" "); + foreach (var kvp1 in typdeps) + { + sb.AppendLine(" "); + sb.AppendLine(" " + kvp1.Key + ""); + sb.AppendLine(" INTERIOR_DATA"); + sb.AppendLine(" "); + foreach (var kvp2 in kvp1.Value) + { + sb.AppendLine(" " + kvp2.Key + ""); + } + sb.AppendLine(" "); + sb.AppendLine(" "); + } + sb.AppendLine(" "); + } + else + { + sb.AppendLine(" "); + } + sb.AppendLine(" "); sb.AppendLine(""); diff --git a/Project/Panels/EditYndPanel.cs b/Project/Panels/EditYndPanel.cs index fa3299d..2df3fc9 100644 --- a/Project/Panels/EditYndPanel.cs +++ b/Project/Panels/EditYndPanel.cs @@ -110,6 +110,7 @@ namespace CodeWalker.Project.Panels ProjectForm.SetYndHasChanged(true); } } + UpdateFormTitleYndChanged(); } private void YndAreaIDXUpDown_ValueChanged(object sender, EventArgs e) @@ -136,6 +137,7 @@ namespace CodeWalker.Project.Panels ProjectForm.SetYndHasChanged(true); } } + UpdateFormTitleYndChanged(); } private void YndPedNodesUpDown_ValueChanged(object sender, EventArgs e) @@ -152,6 +154,7 @@ namespace CodeWalker.Project.Panels ProjectForm.SetYndHasChanged(true); } } + UpdateFormTitleYndChanged(); } } } diff --git a/Project/Panels/EditYnvPanel.Designer.cs b/Project/Panels/EditYnvPanel.Designer.cs index 5356664..fd95f08 100644 --- a/Project/Panels/EditYnvPanel.Designer.cs +++ b/Project/Panels/EditYnvPanel.Designer.cs @@ -37,21 +37,43 @@ this.YnvAreaIDXUpDown = new System.Windows.Forms.NumericUpDown(); this.YnvAreaIDInfoLabel = new System.Windows.Forms.Label(); this.label92 = new System.Windows.Forms.Label(); + this.YnvVertexCountLabel = new System.Windows.Forms.Label(); + this.YnvPolyCountLabel = new System.Windows.Forms.Label(); + this.YnvPortalCountLabel = new System.Windows.Forms.Label(); + this.YnvPortalLinkCountLabel = new System.Windows.Forms.Label(); + this.YnvSectorUnkCountLabel = new System.Windows.Forms.Label(); + this.YnvByteCountLabel = new System.Windows.Forms.Label(); + this.YnvFlagsGroupBox = new System.Windows.Forms.GroupBox(); + this.YnvFlagsVerticesCheckBox = new System.Windows.Forms.CheckBox(); + this.YnvFlagsPortalsCheckBox = new System.Windows.Forms.CheckBox(); + this.YnvFlagsVehicleCheckBox = new System.Windows.Forms.CheckBox(); + this.YnvFlagsUnknownCheckBox = new System.Windows.Forms.CheckBox(); + this.YnvVersionUnkHashTextBox = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.label78 = new System.Windows.Forms.Label(); + this.YnvAdjAreaIDsTextBox = new CodeWalker.WinForms.TextBoxFix(); + this.label48 = new System.Windows.Forms.Label(); + this.YnvProjectPathTextBox = new System.Windows.Forms.TextBox(); + this.label47 = new System.Windows.Forms.Label(); + this.YnvRpfPathTextBox = new System.Windows.Forms.TextBox(); ((System.ComponentModel.ISupportInitialize)(this.YnvAreaIDYUpDown)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.YnvAreaIDXUpDown)).BeginInit(); + this.YnvFlagsGroupBox.SuspendLayout(); this.SuspendLayout(); // // YnvAABBSizeTextBox // - this.YnvAABBSizeTextBox.Location = new System.Drawing.Point(110, 66); + this.YnvAABBSizeTextBox.Location = new System.Drawing.Point(91, 48); this.YnvAABBSizeTextBox.Name = "YnvAABBSizeTextBox"; this.YnvAABBSizeTextBox.Size = new System.Drawing.Size(138, 20); this.YnvAABBSizeTextBox.TabIndex = 37; + this.YnvAABBSizeTextBox.TextChanged += new System.EventHandler(this.YnvAABBSizeTextBox_TextChanged); // // label91 // this.label91.AutoSize = true; - this.label91.Location = new System.Drawing.Point(43, 69); + this.label91.Location = new System.Drawing.Point(24, 51); this.label91.Name = "label91"; this.label91.Size = new System.Drawing.Size(61, 13); this.label91.TabIndex = 38; @@ -60,7 +82,7 @@ // label89 // this.label89.AutoSize = true; - this.label89.Location = new System.Drawing.Point(169, 32); + this.label89.Location = new System.Drawing.Point(150, 14); this.label89.Name = "label89"; this.label89.Size = new System.Drawing.Size(17, 13); this.label89.TabIndex = 36; @@ -68,20 +90,21 @@ // // YnvAreaIDYUpDown // - this.YnvAreaIDYUpDown.Location = new System.Drawing.Point(192, 30); + this.YnvAreaIDYUpDown.Location = new System.Drawing.Point(173, 12); this.YnvAreaIDYUpDown.Maximum = new decimal(new int[] { - 31, + 99, 0, 0, 0}); this.YnvAreaIDYUpDown.Name = "YnvAreaIDYUpDown"; this.YnvAreaIDYUpDown.Size = new System.Drawing.Size(48, 20); this.YnvAreaIDYUpDown.TabIndex = 35; + this.YnvAreaIDYUpDown.ValueChanged += new System.EventHandler(this.YnvAreaIDYUpDown_ValueChanged); // // label90 // this.label90.AutoSize = true; - this.label90.Location = new System.Drawing.Point(87, 32); + this.label90.Location = new System.Drawing.Point(68, 14); this.label90.Name = "label90"; this.label90.Size = new System.Drawing.Size(17, 13); this.label90.TabIndex = 34; @@ -89,20 +112,21 @@ // // YnvAreaIDXUpDown // - this.YnvAreaIDXUpDown.Location = new System.Drawing.Point(110, 30); + this.YnvAreaIDXUpDown.Location = new System.Drawing.Point(91, 12); this.YnvAreaIDXUpDown.Maximum = new decimal(new int[] { - 31, + 99, 0, 0, 0}); this.YnvAreaIDXUpDown.Name = "YnvAreaIDXUpDown"; this.YnvAreaIDXUpDown.Size = new System.Drawing.Size(48, 20); this.YnvAreaIDXUpDown.TabIndex = 33; + this.YnvAreaIDXUpDown.ValueChanged += new System.EventHandler(this.YnvAreaIDXUpDown_ValueChanged); // // YnvAreaIDInfoLabel // this.YnvAreaIDInfoLabel.AutoSize = true; - this.YnvAreaIDInfoLabel.Location = new System.Drawing.Point(257, 32); + this.YnvAreaIDInfoLabel.Location = new System.Drawing.Point(238, 14); this.YnvAreaIDInfoLabel.Name = "YnvAreaIDInfoLabel"; this.YnvAreaIDInfoLabel.Size = new System.Drawing.Size(30, 13); this.YnvAreaIDInfoLabel.TabIndex = 32; @@ -111,17 +135,233 @@ // label92 // this.label92.AutoSize = true; - this.label92.Location = new System.Drawing.Point(31, 32); + this.label92.Location = new System.Drawing.Point(16, 14); this.label92.Name = "label92"; this.label92.Size = new System.Drawing.Size(46, 13); this.label92.TabIndex = 31; this.label92.Text = "Area ID:"; // + // YnvVertexCountLabel + // + this.YnvVertexCountLabel.AutoSize = true; + this.YnvVertexCountLabel.Location = new System.Drawing.Point(358, 55); + this.YnvVertexCountLabel.Name = "YnvVertexCountLabel"; + this.YnvVertexCountLabel.Size = new System.Drawing.Size(79, 13); + this.YnvVertexCountLabel.TabIndex = 39; + this.YnvVertexCountLabel.Text = "Vertex count: 0"; + // + // YnvPolyCountLabel + // + this.YnvPolyCountLabel.AutoSize = true; + this.YnvPolyCountLabel.Location = new System.Drawing.Point(358, 73); + this.YnvPolyCountLabel.Name = "YnvPolyCountLabel"; + this.YnvPolyCountLabel.Size = new System.Drawing.Size(69, 13); + this.YnvPolyCountLabel.TabIndex = 40; + this.YnvPolyCountLabel.Text = "Poly count: 0"; + // + // YnvPortalCountLabel + // + this.YnvPortalCountLabel.AutoSize = true; + this.YnvPortalCountLabel.Location = new System.Drawing.Point(358, 91); + this.YnvPortalCountLabel.Name = "YnvPortalCountLabel"; + this.YnvPortalCountLabel.Size = new System.Drawing.Size(76, 13); + this.YnvPortalCountLabel.TabIndex = 41; + this.YnvPortalCountLabel.Text = "Portal count: 0"; + // + // YnvPortalLinkCountLabel + // + this.YnvPortalLinkCountLabel.AutoSize = true; + this.YnvPortalLinkCountLabel.Location = new System.Drawing.Point(358, 109); + this.YnvPortalLinkCountLabel.Name = "YnvPortalLinkCountLabel"; + this.YnvPortalLinkCountLabel.Size = new System.Drawing.Size(95, 13); + this.YnvPortalLinkCountLabel.TabIndex = 42; + this.YnvPortalLinkCountLabel.Text = "Portal link count: 0"; + // + // YnvSectorUnkCountLabel + // + this.YnvSectorUnkCountLabel.AutoSize = true; + this.YnvSectorUnkCountLabel.Location = new System.Drawing.Point(358, 127); + this.YnvSectorUnkCountLabel.Name = "YnvSectorUnkCountLabel"; + this.YnvSectorUnkCountLabel.Size = new System.Drawing.Size(101, 13); + this.YnvSectorUnkCountLabel.TabIndex = 43; + this.YnvSectorUnkCountLabel.Text = "Sector unk count: 0"; + // + // YnvByteCountLabel + // + this.YnvByteCountLabel.AutoSize = true; + this.YnvByteCountLabel.Location = new System.Drawing.Point(358, 145); + this.YnvByteCountLabel.Name = "YnvByteCountLabel"; + this.YnvByteCountLabel.Size = new System.Drawing.Size(70, 13); + this.YnvByteCountLabel.TabIndex = 44; + this.YnvByteCountLabel.Text = "Byte count: 0"; + // + // YnvFlagsGroupBox + // + this.YnvFlagsGroupBox.Controls.Add(this.YnvFlagsUnknownCheckBox); + this.YnvFlagsGroupBox.Controls.Add(this.YnvFlagsVehicleCheckBox); + this.YnvFlagsGroupBox.Controls.Add(this.YnvFlagsPortalsCheckBox); + this.YnvFlagsGroupBox.Controls.Add(this.YnvFlagsVerticesCheckBox); + this.YnvFlagsGroupBox.Location = new System.Drawing.Point(247, 48); + this.YnvFlagsGroupBox.Name = "YnvFlagsGroupBox"; + this.YnvFlagsGroupBox.Size = new System.Drawing.Size(103, 115); + this.YnvFlagsGroupBox.TabIndex = 45; + this.YnvFlagsGroupBox.TabStop = false; + this.YnvFlagsGroupBox.Text = "Content flags"; + // + // YnvFlagsVerticesCheckBox + // + this.YnvFlagsVerticesCheckBox.AutoSize = true; + this.YnvFlagsVerticesCheckBox.Location = new System.Drawing.Point(12, 19); + this.YnvFlagsVerticesCheckBox.Name = "YnvFlagsVerticesCheckBox"; + this.YnvFlagsVerticesCheckBox.Size = new System.Drawing.Size(64, 17); + this.YnvFlagsVerticesCheckBox.TabIndex = 0; + this.YnvFlagsVerticesCheckBox.Text = "Vertices"; + this.YnvFlagsVerticesCheckBox.UseVisualStyleBackColor = true; + this.YnvFlagsVerticesCheckBox.CheckedChanged += new System.EventHandler(this.YnvFlagsVerticesCheckBox_CheckedChanged); + // + // YnvFlagsPortalsCheckBox + // + this.YnvFlagsPortalsCheckBox.AutoSize = true; + this.YnvFlagsPortalsCheckBox.Location = new System.Drawing.Point(12, 42); + this.YnvFlagsPortalsCheckBox.Name = "YnvFlagsPortalsCheckBox"; + this.YnvFlagsPortalsCheckBox.Size = new System.Drawing.Size(58, 17); + this.YnvFlagsPortalsCheckBox.TabIndex = 1; + this.YnvFlagsPortalsCheckBox.Text = "Portals"; + this.YnvFlagsPortalsCheckBox.UseVisualStyleBackColor = true; + this.YnvFlagsPortalsCheckBox.CheckedChanged += new System.EventHandler(this.YnvFlagsPortalsCheckBox_CheckedChanged); + // + // YnvFlagsVehicleCheckBox + // + this.YnvFlagsVehicleCheckBox.AutoSize = true; + this.YnvFlagsVehicleCheckBox.Location = new System.Drawing.Point(12, 65); + this.YnvFlagsVehicleCheckBox.Name = "YnvFlagsVehicleCheckBox"; + this.YnvFlagsVehicleCheckBox.Size = new System.Drawing.Size(61, 17); + this.YnvFlagsVehicleCheckBox.TabIndex = 2; + this.YnvFlagsVehicleCheckBox.Text = "Vehicle"; + this.YnvFlagsVehicleCheckBox.UseVisualStyleBackColor = true; + this.YnvFlagsVehicleCheckBox.CheckedChanged += new System.EventHandler(this.YnvFlagsVehicleCheckBox_CheckedChanged); + // + // YnvFlagsUnknownCheckBox + // + this.YnvFlagsUnknownCheckBox.AutoSize = true; + this.YnvFlagsUnknownCheckBox.Location = new System.Drawing.Point(12, 88); + this.YnvFlagsUnknownCheckBox.Name = "YnvFlagsUnknownCheckBox"; + this.YnvFlagsUnknownCheckBox.Size = new System.Drawing.Size(78, 17); + this.YnvFlagsUnknownCheckBox.TabIndex = 3; + this.YnvFlagsUnknownCheckBox.Text = "[Unknown]"; + this.YnvFlagsUnknownCheckBox.UseVisualStyleBackColor = true; + this.YnvFlagsUnknownCheckBox.CheckedChanged += new System.EventHandler(this.YnvFlagsUnknownCheckBox_CheckedChanged); + // + // YnvVersionUnkHashTextBox + // + this.YnvVersionUnkHashTextBox.Location = new System.Drawing.Point(91, 180); + this.YnvVersionUnkHashTextBox.Name = "YnvVersionUnkHashTextBox"; + this.YnvVersionUnkHashTextBox.Size = new System.Drawing.Size(138, 20); + this.YnvVersionUnkHashTextBox.TabIndex = 46; + this.YnvVersionUnkHashTextBox.TextChanged += new System.EventHandler(this.YnvVersionUnkHashTextBox_TextChanged); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(23, 183); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(62, 13); + this.label1.TabIndex = 47; + this.label1.Text = "Unk hash?:"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(235, 183); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(183, 13); + this.label2.TabIndex = 48; + this.label2.Text = "(2244687201 for global, 0 for vehicle)"; + // + // label78 + // + this.label78.AutoSize = true; + this.label78.Location = new System.Drawing.Point(16, 217); + this.label78.Name = "label78"; + this.label78.Size = new System.Drawing.Size(69, 13); + this.label78.TabIndex = 53; + this.label78.Text = "Adj Area IDs:"; + // + // YnvAdjAreaIDsTextBox + // + this.YnvAdjAreaIDsTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.YnvAdjAreaIDsTextBox.Location = new System.Drawing.Point(91, 214); + this.YnvAdjAreaIDsTextBox.Multiline = true; + this.YnvAdjAreaIDsTextBox.Name = "YnvAdjAreaIDsTextBox"; + this.YnvAdjAreaIDsTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Both; + this.YnvAdjAreaIDsTextBox.Size = new System.Drawing.Size(214, 139); + this.YnvAdjAreaIDsTextBox.TabIndex = 52; + this.YnvAdjAreaIDsTextBox.WordWrap = false; + this.YnvAdjAreaIDsTextBox.TextChanged += new System.EventHandler(this.YnvAdjAreaIDsTextBox_TextChanged); + // + // label48 + // + this.label48.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.label48.AutoSize = true; + this.label48.Location = new System.Drawing.Point(17, 398); + this.label48.Name = "label48"; + this.label48.Size = new System.Drawing.Size(68, 13); + this.label48.TabIndex = 57; + this.label48.Text = "Project Path:"; + // + // YnvProjectPathTextBox + // + this.YnvProjectPathTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.YnvProjectPathTextBox.Location = new System.Drawing.Point(91, 395); + this.YnvProjectPathTextBox.Name = "YnvProjectPathTextBox"; + this.YnvProjectPathTextBox.ReadOnly = true; + this.YnvProjectPathTextBox.Size = new System.Drawing.Size(470, 20); + this.YnvProjectPathTextBox.TabIndex = 56; + // + // label47 + // + this.label47.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.label47.AutoSize = true; + this.label47.Location = new System.Drawing.Point(33, 372); + this.label47.Name = "label47"; + this.label47.Size = new System.Drawing.Size(52, 13); + this.label47.TabIndex = 55; + this.label47.Text = "Rpf Path:"; + // + // YnvRpfPathTextBox + // + this.YnvRpfPathTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.YnvRpfPathTextBox.Location = new System.Drawing.Point(91, 369); + this.YnvRpfPathTextBox.Name = "YnvRpfPathTextBox"; + this.YnvRpfPathTextBox.ReadOnly = true; + this.YnvRpfPathTextBox.Size = new System.Drawing.Size(470, 20); + this.YnvRpfPathTextBox.TabIndex = 54; + // // EditYnvPanel // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(513, 427); + this.ClientSize = new System.Drawing.Size(581, 429); + this.Controls.Add(this.label48); + this.Controls.Add(this.YnvProjectPathTextBox); + this.Controls.Add(this.label47); + this.Controls.Add(this.YnvRpfPathTextBox); + this.Controls.Add(this.label78); + this.Controls.Add(this.YnvAdjAreaIDsTextBox); + this.Controls.Add(this.label2); + this.Controls.Add(this.YnvVersionUnkHashTextBox); + this.Controls.Add(this.label1); + this.Controls.Add(this.YnvFlagsGroupBox); + this.Controls.Add(this.YnvByteCountLabel); + this.Controls.Add(this.YnvSectorUnkCountLabel); + this.Controls.Add(this.YnvPortalLinkCountLabel); + this.Controls.Add(this.YnvPortalCountLabel); + this.Controls.Add(this.YnvPolyCountLabel); + this.Controls.Add(this.YnvVertexCountLabel); this.Controls.Add(this.YnvAABBSizeTextBox); this.Controls.Add(this.label91); this.Controls.Add(this.label89); @@ -135,6 +375,8 @@ this.Text = "Edit Ynv"; ((System.ComponentModel.ISupportInitialize)(this.YnvAreaIDYUpDown)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.YnvAreaIDXUpDown)).EndInit(); + this.YnvFlagsGroupBox.ResumeLayout(false); + this.YnvFlagsGroupBox.PerformLayout(); this.ResumeLayout(false); this.PerformLayout(); @@ -150,5 +392,25 @@ private System.Windows.Forms.NumericUpDown YnvAreaIDXUpDown; private System.Windows.Forms.Label YnvAreaIDInfoLabel; private System.Windows.Forms.Label label92; + private System.Windows.Forms.Label YnvVertexCountLabel; + private System.Windows.Forms.Label YnvPolyCountLabel; + private System.Windows.Forms.Label YnvPortalCountLabel; + private System.Windows.Forms.Label YnvPortalLinkCountLabel; + private System.Windows.Forms.Label YnvSectorUnkCountLabel; + private System.Windows.Forms.Label YnvByteCountLabel; + private System.Windows.Forms.GroupBox YnvFlagsGroupBox; + private System.Windows.Forms.CheckBox YnvFlagsUnknownCheckBox; + private System.Windows.Forms.CheckBox YnvFlagsVehicleCheckBox; + private System.Windows.Forms.CheckBox YnvFlagsPortalsCheckBox; + private System.Windows.Forms.CheckBox YnvFlagsVerticesCheckBox; + private System.Windows.Forms.TextBox YnvVersionUnkHashTextBox; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label78; + private WinForms.TextBoxFix YnvAdjAreaIDsTextBox; + private System.Windows.Forms.Label label48; + private System.Windows.Forms.TextBox YnvProjectPathTextBox; + private System.Windows.Forms.Label label47; + private System.Windows.Forms.TextBox YnvRpfPathTextBox; } } \ No newline at end of file diff --git a/Project/Panels/EditYnvPanel.cs b/Project/Panels/EditYnvPanel.cs index d4a4980..433f59f 100644 --- a/Project/Panels/EditYnvPanel.cs +++ b/Project/Panels/EditYnvPanel.cs @@ -1,4 +1,5 @@ using CodeWalker.GameFiles; +using SharpDX; using System; using System.Collections.Generic; using System.ComponentModel; @@ -16,7 +17,7 @@ namespace CodeWalker.Project.Panels public ProjectForm ProjectForm; public YnvFile Ynv { get; set; } - //private bool populatingui = false; + private bool populatingui = false; private bool waschanged = false; public EditYnvPanel(ProjectForm projectForm) @@ -58,7 +59,193 @@ namespace CodeWalker.Project.Panels public void UpdateYnvUI() { + if (Ynv?.Nav == null) + { + ////YnvPanel.Enabled = false; + YnvRpfPathTextBox.Text = string.Empty; + YnvProjectPathTextBox.Text = string.Empty; + YnvAreaIDXUpDown.Value = 0; + YnvAreaIDYUpDown.Value = 0; + YnvAreaIDInfoLabel.Text = "ID: -"; + YnvAABBSizeTextBox.Text = string.Empty; + YnvVertexCountLabel.Text = "Vertex count: -"; + YnvPolyCountLabel.Text = "Poly count: -"; + YnvPortalCountLabel.Text = "Portal count: -"; + YnvPortalLinkCountLabel.Text = "Portal link count: -"; + YnvSectorUnkCountLabel.Text = "Sector unk count: -"; + YnvByteCountLabel.Text = "Byte count: -"; + YnvVersionUnkHashTextBox.Text = string.Empty; + } + else + { + var nv = Ynv.Nav; + populatingui = true; + ////YnvPanel.Enabled = true; + YnvRpfPathTextBox.Text = Ynv.RpfFileEntry.Path; + YnvProjectPathTextBox.Text = (Ynv != null) ? ProjectForm.CurrentProjectFile.GetRelativePath(Ynv.FilePath) : Ynv.FilePath; + YnvAreaIDXUpDown.Value = Ynv.CellX; + YnvAreaIDYUpDown.Value = Ynv.CellY; + YnvAreaIDInfoLabel.Text = "ID: " + Ynv.AreaID.ToString(); + YnvAABBSizeTextBox.Text = FloatUtil.GetVector3String(nv.AABBSize); + YnvFlagsVerticesCheckBox.Checked = nv.ContentFlags.HasFlag(NavMeshFlags.Vertices); + YnvFlagsPortalsCheckBox.Checked = nv.ContentFlags.HasFlag(NavMeshFlags.Portals); + YnvFlagsVehicleCheckBox.Checked = nv.ContentFlags.HasFlag(NavMeshFlags.Vehicle); + YnvFlagsUnknownCheckBox.Checked = nv.ContentFlags.HasFlag(NavMeshFlags.Unknown8); + YnvVertexCountLabel.Text = "Vertex count: " + nv.VerticesCount.ToString(); + YnvPolyCountLabel.Text = "Poly count: " + nv.PolysCount.ToString(); + YnvPortalCountLabel.Text = "Portal count: " + nv.PortalsCount.ToString(); + YnvPortalLinkCountLabel.Text = "Portal link count: " + nv.PortalLinksCount.ToString(); + YnvSectorUnkCountLabel.Text = "Sector unk count: " + nv.SectorUnkCount.ToString(); + YnvByteCountLabel.Text = "Byte count: " + nv.TotalBytes.ToString(); + YnvVersionUnkHashTextBox.Text = nv.VersionUnk2.ToString(); + YnvAdjAreaIDsTextBox.Text = GetAdjAreaIDsString(nv.AdjAreaIDs.Values); + populatingui = false; + } } + + + private string GetAdjAreaIDsString(uint[] vals) + { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < vals.Length; i++) + { + var adjid = vals[i]; + sb.AppendLine(adjid.ToString()); + } + return sb.ToString(); + } + private uint[] GetAdjAreaIdsArray(string text) + { + var rsplit = new[] { '\n' }; + var csplit = new[] { ' ' }; + string[] rowstrs = text.Split(rsplit, StringSplitOptions.RemoveEmptyEntries); + uint[] vals = new uint[rowstrs.Length]; + for (int i = 0; i < rowstrs.Length; i++) + { + string rowstr = rowstrs[i].Trim(); + uint.TryParse(rowstr, out vals[i]); + } + return vals; + } + + + private void YnvAreaIDUpDownChange() + { + if (populatingui) return; + if (Ynv?.Nav == null) return; + int x = (int)YnvAreaIDXUpDown.Value; + int y = (int)YnvAreaIDYUpDown.Value; + lock (ProjectForm.ProjectSyncRoot) + { + var areaid = y * 100 + x; + if (Ynv.AreaID != areaid) + { + Ynv.AreaID = areaid; + //Ynv.Name = "nodes" + areaid.ToString() + ".ynd"; + YnvAreaIDInfoLabel.Text = "ID: " + areaid.ToString(); + ProjectForm.SetYnvHasChanged(true); + } + } + UpdateFormTitleYnvChanged(); + } + + private void YnvFlagsCheckBoxChange() + { + if (populatingui) return; + if (Ynv?.Nav == null) return; + var verts = YnvFlagsVerticesCheckBox.Checked ? NavMeshFlags.Vertices : NavMeshFlags.None; + var ports = YnvFlagsPortalsCheckBox.Checked ? NavMeshFlags.Portals : NavMeshFlags.None; + var vehcs = YnvFlagsVehicleCheckBox.Checked ? NavMeshFlags.Vehicle : NavMeshFlags.None; + var unk8s = YnvFlagsUnknownCheckBox.Checked ? NavMeshFlags.Unknown8 : NavMeshFlags.None; + var f = verts | ports | vehcs | unk8s; + lock (ProjectForm.ProjectSyncRoot) + { + if (Ynv.Nav.ContentFlags != f) + { + Ynv.Nav.ContentFlags = f; + ProjectForm.SetYnvHasChanged(true); + } + } + UpdateFormTitleYnvChanged(); + } + + + private void YnvAreaIDXUpDown_ValueChanged(object sender, EventArgs e) + { + YnvAreaIDUpDownChange(); + } + + private void YnvAreaIDYUpDown_ValueChanged(object sender, EventArgs e) + { + YnvAreaIDUpDownChange(); + } + + private void YnvAABBSizeTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (Ynv?.Nav == null) return; + Vector3 v = FloatUtil.ParseVector3String(YnvAABBSizeTextBox.Text); + lock (ProjectForm.ProjectSyncRoot) + { + if (Ynv.Nav.AABBSize != v) + { + Ynv.Nav.AABBSize = v; + ProjectForm.SetYnvHasChanged(true); + } + } + UpdateFormTitleYnvChanged(); + } + + private void YnvFlagsVerticesCheckBox_CheckedChanged(object sender, EventArgs e) + { + YnvFlagsCheckBoxChange(); + } + + private void YnvFlagsPortalsCheckBox_CheckedChanged(object sender, EventArgs e) + { + YnvFlagsCheckBoxChange(); + } + + private void YnvFlagsVehicleCheckBox_CheckedChanged(object sender, EventArgs e) + { + YnvFlagsCheckBoxChange(); + } + + private void YnvFlagsUnknownCheckBox_CheckedChanged(object sender, EventArgs e) + { + YnvFlagsCheckBoxChange(); + } + + private void YnvVersionUnkHashTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (Ynv?.Nav == null) return; + uint v = 0; + uint.TryParse(YnvVersionUnkHashTextBox.Text, out v); + lock (ProjectForm.ProjectSyncRoot) + { + if (Ynv.Nav.VersionUnk2 != v) + { + Ynv.Nav.VersionUnk2 = v; + ProjectForm.SetYnvHasChanged(true); + } + } + UpdateFormTitleYnvChanged(); + } + + private void YnvAdjAreaIDsTextBox_TextChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (Ynv?.Nav == null) return; + var areaids = new NavMeshUintArray(); + areaids.Values = GetAdjAreaIdsArray(YnvAdjAreaIDsTextBox.Text); + lock (ProjectForm.ProjectSyncRoot) + { + Ynv.Nav.AdjAreaIDs = areaids; + ProjectForm.SetYnvHasChanged(true); + } + UpdateFormTitleYnvChanged(); + } } } diff --git a/Project/Panels/EditYnvPolyPanel.Designer.cs b/Project/Panels/EditYnvPolyPanel.Designer.cs index 5c06460..992ad5d 100644 --- a/Project/Panels/EditYnvPolyPanel.Designer.cs +++ b/Project/Panels/EditYnvPolyPanel.Designer.cs @@ -29,27 +29,277 @@ private void InitializeComponent() { System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(EditYnvPolyPanel)); + this.AreaIDUpDown = new System.Windows.Forms.NumericUpDown(); + this.label92 = new System.Windows.Forms.Label(); + this.PartIDUpDown = new System.Windows.Forms.NumericUpDown(); this.label1 = new System.Windows.Forms.Label(); + this.PortalIDUpDown = new System.Windows.Forms.NumericUpDown(); + this.label2 = new System.Windows.Forms.Label(); + this.FlagsCheckedListBox1 = new System.Windows.Forms.CheckedListBox(); + this.FlagsCheckedListBox2 = new System.Windows.Forms.CheckedListBox(); + this.FlagsCheckedListBox3 = new System.Windows.Forms.CheckedListBox(); + this.label5 = new System.Windows.Forms.Label(); + this.FlagsCheckedListBox4 = new System.Windows.Forms.CheckedListBox(); + this.UnkXUpDown = new System.Windows.Forms.NumericUpDown(); + this.label3 = new System.Windows.Forms.Label(); + this.UnkYUpDown = new System.Windows.Forms.NumericUpDown(); + this.label4 = new System.Windows.Forms.Label(); + this.DeletePolyButton = new System.Windows.Forms.Button(); + this.AddToProjectButton = new System.Windows.Forms.Button(); + ((System.ComponentModel.ISupportInitialize)(this.AreaIDUpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.PartIDUpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.PortalIDUpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.UnkXUpDown)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.UnkYUpDown)).BeginInit(); this.SuspendLayout(); // + // AreaIDUpDown + // + this.AreaIDUpDown.Location = new System.Drawing.Point(59, 12); + this.AreaIDUpDown.Maximum = new decimal(new int[] { + 65535, + 0, + 0, + 0}); + this.AreaIDUpDown.Name = "AreaIDUpDown"; + this.AreaIDUpDown.Size = new System.Drawing.Size(71, 20); + this.AreaIDUpDown.TabIndex = 35; + this.AreaIDUpDown.ValueChanged += new System.EventHandler(this.AreaIDUpDown_ValueChanged); + // + // label92 + // + this.label92.AutoSize = true; + this.label92.Location = new System.Drawing.Point(7, 14); + this.label92.Name = "label92"; + this.label92.Size = new System.Drawing.Size(46, 13); + this.label92.TabIndex = 34; + this.label92.Text = "Area ID:"; + // + // PartIDUpDown + // + this.PartIDUpDown.Location = new System.Drawing.Point(193, 12); + this.PartIDUpDown.Maximum = new decimal(new int[] { + 65535, + 0, + 0, + 0}); + this.PartIDUpDown.Name = "PartIDUpDown"; + this.PartIDUpDown.Size = new System.Drawing.Size(71, 20); + this.PartIDUpDown.TabIndex = 37; + this.PartIDUpDown.ValueChanged += new System.EventHandler(this.PartIDUpDown_ValueChanged); + // // label1 // this.label1.AutoSize = true; - this.label1.Location = new System.Drawing.Point(48, 56); + this.label1.Location = new System.Drawing.Point(144, 14); this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(121, 13); - this.label1.TabIndex = 0; - this.label1.Text = "Nav Poly editing TODO!"; + this.label1.Size = new System.Drawing.Size(43, 13); + this.label1.TabIndex = 36; + this.label1.Text = "Part ID:"; + // + // PortalIDUpDown + // + this.PortalIDUpDown.Location = new System.Drawing.Point(338, 12); + this.PortalIDUpDown.Maximum = new decimal(new int[] { + 65535, + 0, + 0, + 0}); + this.PortalIDUpDown.Name = "PortalIDUpDown"; + this.PortalIDUpDown.Size = new System.Drawing.Size(71, 20); + this.PortalIDUpDown.TabIndex = 39; + this.PortalIDUpDown.ValueChanged += new System.EventHandler(this.PortalIDUpDown_ValueChanged); + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(281, 14); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(51, 13); + this.label2.TabIndex = 38; + this.label2.Text = "Portal ID:"; + // + // FlagsCheckedListBox1 + // + this.FlagsCheckedListBox1.CheckOnClick = true; + this.FlagsCheckedListBox1.FormattingEnabled = true; + this.FlagsCheckedListBox1.Items.AddRange(new object[] { + "0 - AvoidUnk0", + "1 - AvoidUnk1", + "2 - IsFootpath", + "3 - IsUnderground", + "4 - [Not used]", + "5 - [Not used]", + "6 - IsSteepSlope", + "7 - IsWater"}); + this.FlagsCheckedListBox1.Location = new System.Drawing.Point(10, 68); + this.FlagsCheckedListBox1.Name = "FlagsCheckedListBox1"; + this.FlagsCheckedListBox1.Size = new System.Drawing.Size(131, 124); + this.FlagsCheckedListBox1.TabIndex = 40; + this.FlagsCheckedListBox1.ItemCheck += new System.Windows.Forms.ItemCheckEventHandler(this.FlagsCheckedListBox1_ItemCheck); + // + // FlagsCheckedListBox2 + // + this.FlagsCheckedListBox2.CheckOnClick = true; + this.FlagsCheckedListBox2.FormattingEnabled = true; + this.FlagsCheckedListBox2.Items.AddRange(new object[] { + "0 - UndergroundUnk0", + "1 - UndergroundUnk1", + "2 - UndergroundUnk2", + "3 - UndergroundUnk3", + "4 - [Not used]", + "5 - HasPathNode", + "6 - IsInterior", + "7 - InteractionUnk"}); + this.FlagsCheckedListBox2.Location = new System.Drawing.Point(147, 68); + this.FlagsCheckedListBox2.Name = "FlagsCheckedListBox2"; + this.FlagsCheckedListBox2.Size = new System.Drawing.Size(131, 124); + this.FlagsCheckedListBox2.TabIndex = 42; + this.FlagsCheckedListBox2.ItemCheck += new System.Windows.Forms.ItemCheckEventHandler(this.FlagsCheckedListBox2_ItemCheck); + // + // FlagsCheckedListBox3 + // + this.FlagsCheckedListBox3.CheckOnClick = true; + this.FlagsCheckedListBox3.FormattingEnabled = true; + this.FlagsCheckedListBox3.Items.AddRange(new object[] { + "1 - IsFlatGround", + "2 - IsRoad", + "3 - IsCellEdge", + "4 - IsTrainTrack", + "5 - IsShallowWater", + "6 - FootpathUnk1", + "7 - FootpathUnk2", + "8 - FootpathMall"}); + this.FlagsCheckedListBox3.Location = new System.Drawing.Point(284, 68); + this.FlagsCheckedListBox3.Name = "FlagsCheckedListBox3"; + this.FlagsCheckedListBox3.Size = new System.Drawing.Size(131, 124); + this.FlagsCheckedListBox3.TabIndex = 44; + this.FlagsCheckedListBox3.ItemCheck += new System.Windows.Forms.ItemCheckEventHandler(this.FlagsCheckedListBox3_ItemCheck); + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(7, 52); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(35, 13); + this.label5.TabIndex = 45; + this.label5.Text = "Flags:"; + // + // FlagsCheckedListBox4 + // + this.FlagsCheckedListBox4.CheckOnClick = true; + this.FlagsCheckedListBox4.FormattingEnabled = true; + this.FlagsCheckedListBox4.Items.AddRange(new object[] { + "0 - SlopeSouth", + "1 - SlopeSouthEast", + "2 - SlopeEast", + "3 - SlopeNorthEast", + "4 - SlopeNorth", + "5 - SlopeNorthWest", + "6 - SlopeWest", + "7 - SlopeSouthWest"}); + this.FlagsCheckedListBox4.Location = new System.Drawing.Point(421, 68); + this.FlagsCheckedListBox4.Name = "FlagsCheckedListBox4"; + this.FlagsCheckedListBox4.Size = new System.Drawing.Size(131, 124); + this.FlagsCheckedListBox4.TabIndex = 46; + this.FlagsCheckedListBox4.ItemCheck += new System.Windows.Forms.ItemCheckEventHandler(this.FlagsCheckedListBox4_ItemCheck); + // + // UnkXUpDown + // + this.UnkXUpDown.Location = new System.Drawing.Point(82, 213); + this.UnkXUpDown.Maximum = new decimal(new int[] { + 255, + 0, + 0, + 0}); + this.UnkXUpDown.Name = "UnkXUpDown"; + this.UnkXUpDown.Size = new System.Drawing.Size(59, 20); + this.UnkXUpDown.TabIndex = 48; + this.UnkXUpDown.ValueChanged += new System.EventHandler(this.UnkXUpDown_ValueChanged); + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(13, 215); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(63, 13); + this.label3.TabIndex = 47; + this.label3.Text = "UnknownX:"; + // + // UnkYUpDown + // + this.UnkYUpDown.Location = new System.Drawing.Point(219, 213); + this.UnkYUpDown.Maximum = new decimal(new int[] { + 255, + 0, + 0, + 0}); + this.UnkYUpDown.Name = "UnkYUpDown"; + this.UnkYUpDown.Size = new System.Drawing.Size(59, 20); + this.UnkYUpDown.TabIndex = 50; + this.UnkYUpDown.ValueChanged += new System.EventHandler(this.UnkYUpDown_ValueChanged); + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(150, 215); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(63, 13); + this.label4.TabIndex = 49; + this.label4.Text = "UnknownY:"; + // + // DeletePolyButton + // + this.DeletePolyButton.Enabled = false; + this.DeletePolyButton.Location = new System.Drawing.Point(123, 263); + this.DeletePolyButton.Name = "DeletePolyButton"; + this.DeletePolyButton.Size = new System.Drawing.Size(90, 23); + this.DeletePolyButton.TabIndex = 52; + this.DeletePolyButton.Text = "Delete Polygon"; + this.DeletePolyButton.UseVisualStyleBackColor = true; + this.DeletePolyButton.Click += new System.EventHandler(this.DeletePolyButton_Click); + // + // AddToProjectButton + // + this.AddToProjectButton.Enabled = false; + this.AddToProjectButton.Location = new System.Drawing.Point(27, 263); + this.AddToProjectButton.Name = "AddToProjectButton"; + this.AddToProjectButton.Size = new System.Drawing.Size(90, 23); + this.AddToProjectButton.TabIndex = 51; + this.AddToProjectButton.Text = "Add to Project"; + this.AddToProjectButton.UseVisualStyleBackColor = true; + this.AddToProjectButton.Click += new System.EventHandler(this.AddToProjectButton_Click); // // EditYnvPolyPanel // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(557, 396); + this.ClientSize = new System.Drawing.Size(562, 404); + this.Controls.Add(this.DeletePolyButton); + this.Controls.Add(this.AddToProjectButton); + this.Controls.Add(this.UnkYUpDown); + this.Controls.Add(this.label4); + this.Controls.Add(this.UnkXUpDown); + this.Controls.Add(this.label3); + this.Controls.Add(this.FlagsCheckedListBox4); + this.Controls.Add(this.label5); + this.Controls.Add(this.FlagsCheckedListBox3); + this.Controls.Add(this.FlagsCheckedListBox2); + this.Controls.Add(this.FlagsCheckedListBox1); + this.Controls.Add(this.PortalIDUpDown); + this.Controls.Add(this.label2); + this.Controls.Add(this.PartIDUpDown); this.Controls.Add(this.label1); + this.Controls.Add(this.AreaIDUpDown); + this.Controls.Add(this.label92); this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); this.Name = "EditYnvPolyPanel"; this.Text = "Edit Ynv Poly"; + ((System.ComponentModel.ISupportInitialize)(this.AreaIDUpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.PartIDUpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.PortalIDUpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.UnkXUpDown)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.UnkYUpDown)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); @@ -57,6 +307,22 @@ #endregion + private System.Windows.Forms.NumericUpDown AreaIDUpDown; + private System.Windows.Forms.Label label92; + private System.Windows.Forms.NumericUpDown PartIDUpDown; private System.Windows.Forms.Label label1; + private System.Windows.Forms.NumericUpDown PortalIDUpDown; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.CheckedListBox FlagsCheckedListBox1; + private System.Windows.Forms.CheckedListBox FlagsCheckedListBox2; + private System.Windows.Forms.CheckedListBox FlagsCheckedListBox3; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.CheckedListBox FlagsCheckedListBox4; + private System.Windows.Forms.NumericUpDown UnkXUpDown; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.NumericUpDown UnkYUpDown; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Button DeletePolyButton; + private System.Windows.Forms.Button AddToProjectButton; } } \ No newline at end of file diff --git a/Project/Panels/EditYnvPolyPanel.cs b/Project/Panels/EditYnvPolyPanel.cs index b0eaf85..ad40591 100644 --- a/Project/Panels/EditYnvPolyPanel.cs +++ b/Project/Panels/EditYnvPolyPanel.cs @@ -16,7 +16,7 @@ namespace CodeWalker.Project.Panels public ProjectForm ProjectForm; public YnvPoly YnvPoly { get; set; } - //private bool populatingui = false; + private bool populatingui = false; public EditYnvPolyPanel(ProjectForm projectForm) { @@ -40,7 +40,216 @@ namespace CodeWalker.Project.Panels public void UpdateYnvUI() { + if (YnvPoly == null) + { + ////YnvPolyPanel.Enabled = false; + DeletePolyButton.Enabled = false; + AddToProjectButton.Enabled = false; + AreaIDUpDown.Value = 0; + PartIDUpDown.Value = 0; + PortalIDUpDown.Value = 0; + SetCheckedListBoxValues(FlagsCheckedListBox1, 0); + SetCheckedListBoxValues(FlagsCheckedListBox2, 0); + SetCheckedListBoxValues(FlagsCheckedListBox3, 0); + SetCheckedListBoxValues(FlagsCheckedListBox4, 0); + UnkXUpDown.Value = 0; + UnkYUpDown.Value = 0; + } + else + { + populatingui = true; + ////YnvPolyPanel.Enabled = true; + DeletePolyButton.Enabled = ProjectForm.YnvExistsInProject(YnvPoly.Ynv); + AddToProjectButton.Enabled = !DeletePolyButton.Enabled; + AreaIDUpDown.Value = YnvPoly.AreaID; + PartIDUpDown.Value = YnvPoly.PartID; + PortalIDUpDown.Value = YnvPoly.PortalID; + SetCheckedListBoxValues(FlagsCheckedListBox1, YnvPoly.Flags1); + SetCheckedListBoxValues(FlagsCheckedListBox2, YnvPoly.Flags2); + SetCheckedListBoxValues(FlagsCheckedListBox3, YnvPoly.Flags3); + SetCheckedListBoxValues(FlagsCheckedListBox4, YnvPoly.Flags4); + UnkXUpDown.Value = YnvPoly.UnkX; + UnkYUpDown.Value = YnvPoly.UnkY; + populatingui = false; + } } + + private void SetCheckedListBoxValues(CheckedListBox clb, byte flags) + { + for (int i = 0; i < clb.Items.Count; i++) + { + var c = ((flags & (1 << i)) > 0); + clb.SetItemCheckState(i, c ? CheckState.Checked : CheckState.Unchecked); + } + } + private byte GetCheckedListBoxValues(CheckedListBox clb, ItemCheckEventArgs e) + { + byte r = 0; + for (int i = 0; i < clb.Items.Count; i++) + { + if ((e != null) && (e.Index == i)) + { + if (e.NewValue == CheckState.Checked) + { + r += (byte)(1 << i); + } + } + else + { + bool v = clb.GetItemChecked(i);// == CheckState.Checked; + r = (byte)BitUtil.UpdateBit(r, i, v); + } + } + return r; + } + + + private void AreaIDUpDown_ValueChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (YnvPoly == null) return; + ushort areaid = (ushort)AreaIDUpDown.Value; + lock (ProjectForm.ProjectSyncRoot) + { + if (YnvPoly.AreaID != areaid) + { + YnvPoly.AreaID = areaid; + ProjectForm.SetYnvHasChanged(true); + } + } + } + + private void PartIDUpDown_ValueChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (YnvPoly == null) return; + ushort partid = (ushort)PartIDUpDown.Value; + lock (ProjectForm.ProjectSyncRoot) + { + if (YnvPoly.PartID != partid) + { + YnvPoly.PartID = partid; + ProjectForm.SetYnvHasChanged(true); + } + } + } + + private void PortalIDUpDown_ValueChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (YnvPoly == null) return; + ushort portalid = (ushort)PortalIDUpDown.Value; + lock (ProjectForm.ProjectSyncRoot) + { + if (YnvPoly.PortalID != portalid) + { + YnvPoly.PortalID = portalid; + ProjectForm.SetYnvHasChanged(true); + } + } + } + + private void FlagsCheckedListBox1_ItemCheck(object sender, ItemCheckEventArgs e) + { + if (populatingui) return; + if (YnvPoly == null) return; + byte flags = GetCheckedListBoxValues(FlagsCheckedListBox1, e); + lock (ProjectForm.ProjectSyncRoot) + { + if (YnvPoly.Flags1 != flags) + { + YnvPoly.Flags1 = flags; + ProjectForm.SetYnvHasChanged(true); + } + } + } + + private void FlagsCheckedListBox2_ItemCheck(object sender, ItemCheckEventArgs e) + { + if (populatingui) return; + if (YnvPoly == null) return; + byte flags = GetCheckedListBoxValues(FlagsCheckedListBox2, e); + lock (ProjectForm.ProjectSyncRoot) + { + if (YnvPoly.Flags2 != flags) + { + YnvPoly.Flags2 = flags; + ProjectForm.SetYnvHasChanged(true); + } + } + } + + private void FlagsCheckedListBox3_ItemCheck(object sender, ItemCheckEventArgs e) + { + if (populatingui) return; + if (YnvPoly == null) return; + byte flags = GetCheckedListBoxValues(FlagsCheckedListBox3, e); + lock (ProjectForm.ProjectSyncRoot) + { + if (YnvPoly.Flags3 != flags) + { + YnvPoly.Flags3 = flags; + ProjectForm.SetYnvHasChanged(true); + } + } + } + + private void FlagsCheckedListBox4_ItemCheck(object sender, ItemCheckEventArgs e) + { + if (populatingui) return; + if (YnvPoly == null) return; + byte flags = GetCheckedListBoxValues(FlagsCheckedListBox4, e); + lock (ProjectForm.ProjectSyncRoot) + { + if (YnvPoly.Flags4 != flags) + { + YnvPoly.Flags4 = flags; + ProjectForm.SetYnvHasChanged(true); + } + } + } + + private void UnkXUpDown_ValueChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (YnvPoly == null) return; + byte unkx = (byte)UnkXUpDown.Value; + lock (ProjectForm.ProjectSyncRoot) + { + if (YnvPoly.UnkX != unkx) + { + YnvPoly.UnkX = unkx; + ProjectForm.SetYnvHasChanged(true); + } + } + } + + private void UnkYUpDown_ValueChanged(object sender, EventArgs e) + { + if (populatingui) return; + if (YnvPoly == null) return; + byte unky = (byte)UnkYUpDown.Value; + lock (ProjectForm.ProjectSyncRoot) + { + if (YnvPoly.UnkY != unky) + { + YnvPoly.UnkY = unky; + ProjectForm.SetYnvHasChanged(true); + } + } + } + + private void AddToProjectButton_Click(object sender, EventArgs e) + { + if (YnvPoly == null) return; + ProjectForm.SetProjectItem(YnvPoly); + ProjectForm.AddYnvToProject(YnvPoly.Ynv); + } + + private void DeletePolyButton_Click(object sender, EventArgs e) + { + MessageBox.Show("Delete Polygon TODO!"); + } } } diff --git a/Project/Panels/ProjectExplorerPanel.cs b/Project/Panels/ProjectExplorerPanel.cs index 683a777..d1d3a87 100644 --- a/Project/Panels/ProjectExplorerPanel.cs +++ b/Project/Panels/ProjectExplorerPanel.cs @@ -258,6 +258,23 @@ namespace CodeWalker.Project.Panels } private void LoadYnvTreeNodes(YnvFile ynv, TreeNode node)//TODO! { + if (ynv == null) return; + + if (!string.IsNullOrEmpty(node.Name)) return; //named nodes are eg Polygons + + node.Nodes.Clear(); + + + TreeNode n; + n = node.Nodes.Add("Edit Polygon"); + n.Name = "EditPoly"; + n.Tag = ynv; //this tag should get updated with the selected poly! + + n = node.Nodes.Add("Edit Portal"); + n.Name = "EditPortal"; + n.Tag = ynv; //this tag should get updated with the selected portal! + + } private void LoadTrainTrackTreeNodes(TrainTrack track, TreeNode node) { @@ -440,8 +457,29 @@ namespace CodeWalker.Project.Panels } } } - public void SetYnvHasChanged(YnvFile ynv, bool changed)//TODO! + public void SetYnvHasChanged(YnvFile ynv, bool changed) { + if (ProjectTreeView.Nodes.Count > 0) + { + var pnode = ProjectTreeView.Nodes[0]; + var ynnode = GetChildTreeNode(pnode, "Ynv"); + if (ynnode == null) return; + string changestr = changed ? "*" : ""; + for (int i = 0; i < ynnode.Nodes.Count; i++) + { + var ynode = ynnode.Nodes[i]; + if (ynode.Tag == ynv) + { + string name = ynv.Name; + if (ynv.RpfFileEntry != null) + { + name = ynv.RpfFileEntry.Name; + } + ynode.Text = changestr + name; + break; + } + } + } } public void SetTrainTrackHasChanged(TrainTrack track, bool changed) { @@ -591,14 +629,16 @@ namespace CodeWalker.Project.Panels { if (p == null) return null; TreeNode ynvnode = FindYnvTreeNode(p.Ynv); - var polysnode = GetChildTreeNode(ynvnode, "Polygons"); - if (polysnode == null) return null; - for (int i = 0; i < polysnode.Nodes.Count; i++) - { - TreeNode pnode = polysnode.Nodes[i]; - if (pnode.Tag == p) return pnode; - } - return null; + var polynode = GetChildTreeNode(ynvnode, "EditPoly"); + if (polynode == null) return null; + polynode.Tag = p; + return polynode; + //for (int i = 0; i < polysnode.Nodes.Count; i++) + //{ + // TreeNode pnode = polysnode.Nodes[i]; + // if (pnode.Tag == p) return pnode; + //} + //return null; } public TreeNode FindTrainTrackTreeNode(TrainTrack track) { @@ -666,7 +706,14 @@ namespace CodeWalker.Project.Panels TreeNode entnode = FindEntityTreeNode(ent); if (entnode != null) { - ProjectTreeView.SelectedNode = entnode; + if (ProjectTreeView.SelectedNode == entnode) + { + OnItemSelected?.Invoke(ent); + } + else + { + ProjectTreeView.SelectedNode = entnode; + } } } public void TrySelectCarGenTreeNode(YmapCarGen cargen) @@ -674,7 +721,14 @@ namespace CodeWalker.Project.Panels TreeNode cargennode = FindCarGenTreeNode(cargen); if (cargennode != null) { - ProjectTreeView.SelectedNode = cargennode; + if (ProjectTreeView.SelectedNode == cargennode) + { + OnItemSelected?.Invoke(cargen); + } + else + { + ProjectTreeView.SelectedNode = cargennode; + } } } public void TrySelectPathNodeTreeNode(YndNode node) @@ -686,7 +740,14 @@ namespace CodeWalker.Project.Panels } if (tnode != null) { - ProjectTreeView.SelectedNode = tnode; + if (ProjectTreeView.SelectedNode == tnode) + { + OnItemSelected?.Invoke(node); + } + else + { + ProjectTreeView.SelectedNode = tnode; + } } } public void TrySelectNavPolyTreeNode(YnvPoly poly) @@ -698,7 +759,14 @@ namespace CodeWalker.Project.Panels } if (tnode != null) { - ProjectTreeView.SelectedNode = tnode; + if (ProjectTreeView.SelectedNode == tnode) + { + OnItemSelected?.Invoke(poly); + } + else + { + ProjectTreeView.SelectedNode = tnode; + } } } public void TrySelectTrainNodeTreeNode(TrainTrackNode node) @@ -710,7 +778,14 @@ namespace CodeWalker.Project.Panels } if (tnode != null) { - ProjectTreeView.SelectedNode = tnode; + if (ProjectTreeView.SelectedNode == tnode) + { + OnItemSelected?.Invoke(node); + } + else + { + ProjectTreeView.SelectedNode = tnode; + } } } public void TrySelectScenarioTreeNode(YmtFile scenario) @@ -718,7 +793,14 @@ namespace CodeWalker.Project.Panels TreeNode tnode = FindScenarioTreeNode(scenario); if (tnode != null) { - ProjectTreeView.SelectedNode = tnode; + if (ProjectTreeView.SelectedNode == tnode) + { + OnItemSelected?.Invoke(scenario); + } + else + { + ProjectTreeView.SelectedNode = tnode; + } } } public void TrySelectScenarioNodeTreeNode(ScenarioNode node) @@ -730,7 +812,14 @@ namespace CodeWalker.Project.Panels } if (tnode != null) { - ProjectTreeView.SelectedNode = tnode; + if (ProjectTreeView.SelectedNode == tnode) + { + OnItemSelected?.Invoke(node); + } + else + { + ProjectTreeView.SelectedNode = tnode; + } } } diff --git a/Project/ProjectForm.cs b/Project/ProjectForm.cs index f52ad4f..94e97fe 100644 --- a/Project/ProjectForm.cs +++ b/Project/ProjectForm.cs @@ -1985,14 +1985,136 @@ namespace CodeWalker.Project - public void NewYnv()//TODO! + public void NewYnv() { + if (CurrentProjectFile == null) + { + NewProject(); + } + if (CurrentProjectFile == null) return; + + int testi = 1; + string fname = string.Empty; + bool filenameok = false; + while (!filenameok) + { + fname = "navmesh" + testi.ToString() + ".ynv"; + filenameok = !CurrentProjectFile.ContainsYnv(fname); + testi++; + } + + lock (projectsyncroot) + { + YnvFile ynv = CurrentProjectFile.AddYnvFile(fname); + if (ynv != null) + { + ynv.Loaded = true; + ynv.HasChanged = true; //new ynd, flag as not saved + + //TODO: set new ynv default values... + ynv.Nav = new NavMesh(); + } + } + + CurrentProjectFile.HasChanged = true; + + LoadProjectTree(); } - public void OpenYnv()//TODO! + public void OpenYnv() { + string[] files = ShowOpenDialogMulti("Ynv files|*.ynv", string.Empty); + if (files == null) + { + return; + } + + if (CurrentProjectFile == null) + { + NewProject(); + } + + foreach (string file in files) + { + if (!File.Exists(file)) continue; + + var ynv = CurrentProjectFile.AddYnvFile(file); + + if (ynv != null) + { + SetProjectHasChanged(true); + + LoadYnvFromFile(ynv, file); + + LoadProjectTree(); + } + else + { + MessageBox.Show("Couldn't add\n" + file + "\n - the file already exists in the project."); + } + + } } - public void SaveYnv(bool saveas = false)//TODO! + public void SaveYnv(bool saveas = false) { + if ((CurrentYnvFile == null) && (CurrentNavPoly != null)) CurrentYnvFile = CurrentNavPoly.Ynv; + if (CurrentYnvFile == null) return; + string ynvname = CurrentYnvFile.Name; + string filepath = CurrentYnvFile.FilePath; + if (string.IsNullOrEmpty(filepath)) + { + filepath = ynvname; + } + string origfile = filepath; + if (!File.Exists(filepath)) + { + saveas = true; + } + + + byte[] data; + lock (projectsyncroot) //need to sync writes to ynv objects... + { + saveas = saveas || string.IsNullOrEmpty(filepath); + if (saveas) + { + filepath = ShowSaveDialog("Ynv files|*.ynv", filepath); + if (string.IsNullOrEmpty(filepath)) + { return; } + + string newname = Path.GetFileNameWithoutExtension(filepath); + JenkIndex.Ensure(newname); + CurrentYnvFile.FilePath = filepath; + CurrentYnvFile.RpfFileEntry.Name = new FileInfo(filepath).Name; + CurrentYnvFile.Name = CurrentYnvFile.RpfFileEntry.Name; + } + + + data = CurrentYnvFile.Save(); + } + + + if (data != null) + { + File.WriteAllBytes(filepath, data); + } + + SetYnvHasChanged(false); + + if (saveas) + { + //ShowEditYnvPanel(false); + if (CurrentProjectFile != null) + { + string origpath = CurrentProjectFile.GetRelativePath(origfile); + string newpath = CurrentProjectFile.GetRelativePath(CurrentYnvFile.FilePath); + if (!CurrentProjectFile.RenameYnv(origpath, newpath)) + { //couldn't rename it in the project? happens when project not saved yet... + //MessageBox.Show("Couldn't rename ynv in project! This shouldn't happen - check the project file XML."); + } + } + SetProjectHasChanged(true); + SetCurrentSaveItem(); + } } public void AddYnvToProject(YnvFile ynv) { @@ -2040,7 +2162,7 @@ namespace CodeWalker.Project } public bool IsCurrentNavPoly(YnvPoly poly) { - return false;// poly == CurrentNavPoly; + return poly == CurrentNavPoly; } @@ -4196,8 +4318,16 @@ namespace CodeWalker.Project //note: this is actually necessary to properly populate junctions data........ } } - private void LoadYnvFromFile(YnvFile ynv, string filename)//TODO! + private void LoadYnvFromFile(YnvFile ynv, string filename) { + byte[] data = File.ReadAllBytes(filename); + + ynv.Load(data); + + if (WorldForm != null) + { + WorldForm.UpdateNavYnvGraphics(ynv, true); //polys don't get drawn until something changes otherwise + } } private void LoadTrainTrackFromFile(TrainTrack track, string filename) { diff --git a/WorldForm.cs b/WorldForm.cs index 56143c1..a095f97 100644 --- a/WorldForm.cs +++ b/WorldForm.cs @@ -796,7 +796,7 @@ namespace CodeWalker if (ProjectForm != null) { - //ProjectForm.GetVisibleYnvs(camera, rendernavmeshynvs); + ProjectForm.GetVisibleYnvs(camera, rendernavmeshynvs); } Renderer.RenderNavMeshes(rendernavmeshynvs);