From 80ceb088ff9af68cd13e993fee9c6092890de6f5 Mon Sep 17 00:00:00 2001 From: cmarNYC Date: Fri, 29 Jun 2018 16:07:53 -0400 Subject: [PATCH] Added TerrainMeshResource --- s4pi Extras/Extensions/Extensions.txt | 1 + .../Properties/AssemblyInfo.cs | 40 ++ .../TerrainMeshResource.cs | 435 ++++++++++++++++++ .../TerrainMeshResource.csproj | 69 +++ sims4tools.sln | 19 +- 5 files changed, 561 insertions(+), 3 deletions(-) create mode 100644 s4pi Wrappers/TerrainMeshResource/Properties/AssemblyInfo.cs create mode 100644 s4pi Wrappers/TerrainMeshResource/TerrainMeshResource.cs create mode 100644 s4pi Wrappers/TerrainMeshResource/TerrainMeshResource.csproj diff --git a/s4pi Extras/Extensions/Extensions.txt b/s4pi Extras/Extensions/Extensions.txt index 585f657..8971e1b 100755 --- a/s4pi Extras/Extensions/Extensions.txt +++ b/s4pi Extras/Extensions/Extensions.txt @@ -197,6 +197,7 @@ 0xAD366F95 THUM .png 0xAD366F96 THUM .png 0xAD6FDF1F _XML .xml +0xAE39399F TMSH .terrainmesh 0xAFADAC48 _XML .xml 0xB0118C15 TMLT .bnry 0xB0311D0F CRTR .rooftrim diff --git a/s4pi Wrappers/TerrainMeshResource/Properties/AssemblyInfo.cs b/s4pi Wrappers/TerrainMeshResource/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..9ac269d --- /dev/null +++ b/s4pi Wrappers/TerrainMeshResource/Properties/AssemblyInfo.cs @@ -0,0 +1,40 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Terrain Mesh Resource wrapper")] +[assembly: AssemblyDescription("Wrapper for Sims4 Terrain Mesh resources.")] +#if DEBUG +[assembly: AssemblyConfiguration("[DEBUG]")] +#else +[assembly: AssemblyConfiguration("")] +#endif +[assembly: AssemblyCompany("Peter L Jones")] +[assembly: AssemblyProduct("sims4tools")] +[assembly: AssemblyCopyright("Copyright © 2017 Peter L Jones. Released under GPL 3. See gpl-3.0.txt")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("3392691f-2547-45a8-8e54-fbc9e455555c")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +//[assembly: AssemblyVersion("1.0.0.0")] +//[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/s4pi Wrappers/TerrainMeshResource/TerrainMeshResource.cs b/s4pi Wrappers/TerrainMeshResource/TerrainMeshResource.cs new file mode 100644 index 0000000..bef9e11 --- /dev/null +++ b/s4pi Wrappers/TerrainMeshResource/TerrainMeshResource.cs @@ -0,0 +1,435 @@ +/*************************************************************************** + * Copyright (C) 2014, 2016 by the Sims 4 Tools development team * + * * + * Contributors: * + * Peter Jones * + * Keyi Zhang * + * CmarNYC * + * Buzzler * + * * + * This file is part of the Sims 4 Package Interface (s4pi) * + * * + * s4pi is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * s4pi is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with s4pi. If not, see . * + ***************************************************************************/ +using System.IO; +using System; +using System.Collections.Generic; +using System.Text; +using System.Linq; +using System.Collections; +using s4pi.Interfaces; +using s4pi.Settings; + +namespace TerrainMeshResource +{ + public class TerrainMeshResource : AResource + { + static bool checking = s4pi.Settings.Settings.Checking; + const Int32 recommendedApiVersion = 1; + + #region Attributes + UInt32 version; + + UInt32 layerIndexCount; + + UInt16[] min = new UInt16[3]; + UInt16[] max = new UInt16[3]; + + TerrainVertexList verts; + + UInt16[] indices; + + PassList passes; + + #endregion + + #region Constructors + /// + /// Create a new instance of the resource + /// + /// Requested API version + /// Data stream to use, or null to create from scratch + public TerrainMeshResource(int APIversion, Stream s) : base(APIversion, s) { if (stream == null) { stream = UnParse(); dirty = true; } stream.Position = 0; Parse(stream); } + #endregion + + #region AApiVersionedFields + public override int RecommendedApiVersion { get { return recommendedApiVersion; } } + + public override List ContentFields { get { return GetContentFields(requestedApiVersion, this.GetType()); } } + #endregion + + #region Data I/O + void Parse(Stream s) + { + BinaryReader br = new BinaryReader(s); + + version = br.ReadUInt32(); + if (checking) if (version != 0x200) + throw new InvalidDataException(String.Format("{0}: unsupported 'version'. Read '0x{1:X8}', supported: '0x00000008'", this.GetType().Name, version)); + + UInt32 vertCount = br.ReadUInt32(); + UInt32 indexCount = br.ReadUInt32(); + layerIndexCount = br.ReadUInt32(); + UInt32 passCount = br.ReadUInt32(); + + for (int i = 0; i < 3; i++) { this.min[i] = br.ReadUInt16(); } + for (int i = 0; i < 3; i++) { this.max[i] = br.ReadUInt16(); } + + this.verts = new TerrainVertexList(this.OnResourceChanged, s, vertCount); + + this.indices = new UInt16[indexCount]; + for (int i = 0; i < indexCount; i++) { this.indices[i] = br.ReadUInt16(); } + + passes = new PassList(this.OnResourceChanged, s, passCount); + } + + protected override Stream UnParse() + { + MemoryStream ms = new MemoryStream(); + BinaryWriter bw = new BinaryWriter(ms); + bw.Write(version); + + bw.Write((UInt32)verts.LongCount()); + bw.Write((UInt32)indices.LongLength); + bw.Write(layerIndexCount); + bw.Write((UInt32)passes.LongCount()); + + for (int i = 0; i < 3; i++) { bw.Write(this.min[i]); } + for (int i = 0; i < 3; i++) { bw.Write(this.max[i]); } + + this.verts.UnParse(ms); + + for (int i = 0; i < this.indices.Length; i++) { bw.Write(this.indices[i]); } + + this.passes.UnParse(ms); + + bw.Flush(); + return ms; + } + #endregion + + public string Value { get { return this.ValueBuilder; } } + + #region Content Fields + [MinimumVersion(1)] + [MaximumVersion(recommendedApiVersion)] + + [ElementPriority(0)] + public UInt32 Version { get { return version; } set { if (version != value) { version = value; OnResourceChanged(this, EventArgs.Empty); } } } + [ElementPriority(1)] + public UInt32 LayerIndexCount { get { return layerIndexCount; } set { if (layerIndexCount != value) { layerIndexCount = value; OnResourceChanged(this, EventArgs.Empty); } } } + [ElementPriority(2)] + public UInt16[] Min { get { return min; } set { if (min != value) { min = value; OnResourceChanged(this, EventArgs.Empty); } } } + [ElementPriority(3)] + public UInt16[] Max { get { return max; } set { if (max != value) { max = value; OnResourceChanged(this, EventArgs.Empty); } } } + [ElementPriority(4)] + public TerrainVertexList Vertices { get { return verts; } set { if (verts != value) { verts = value; OnResourceChanged(this, EventArgs.Empty); } } } + [ElementPriority(5)] + public UInt16[] Indices { get { return indices; } set { if (indices != value) { indices = value; OnResourceChanged(this, EventArgs.Empty); } } } + [ElementPriority(6)] + public PassList Passes { get { return passes; } set { if (passes != value) { passes = value; OnResourceChanged(this, EventArgs.Empty); } } } + + #endregion + + public class TerrainVertexList : DependentList + { + #region Constructors + public TerrainVertexList(EventHandler handler) : base(handler) { } + public TerrainVertexList(EventHandler handler, Stream s) : base(handler, s) { } + public TerrainVertexList(EventHandler handler, Stream s, UInt32 count) : base(handler) { this.Parse(s, count); } + public TerrainVertexList(EventHandler handler, IEnumerable le) : base(handler, le) { } + #endregion + #region Data I/O + + protected void Parse(Stream s, UInt32 count) + { + var r = new BinaryReader(s); + for (var i = 0; i < count; i++) + { + this.Add(new TerrainVertex(1, handler, s)); + } + } + + public override void UnParse(Stream s) + { + var w = new BinaryWriter(s); + foreach (TerrainVertex vert in this) + { + vert.UnParse(s); + } + } + #endregion + protected override TerrainVertex CreateElement(Stream s) { return new TerrainVertex(1, elementHandler, s); } + protected override void WriteElement(Stream s, TerrainVertex element) { element.UnParse(s); } + } + + public class TerrainVertex : AHandlerElement, IEquatable + { + private const int recommendedApiVersion = 1; + + private Int16 x; + private Int16 y; + private Int16 z; + private Int16 morphY; + + public TerrainVertex(int apiVersion, EventHandler handler) + : base(apiVersion, handler) + { + } + + public TerrainVertex(int apiVersion, EventHandler handler, Stream s) + : base(apiVersion, handler) + { + this.Parse(s); + } + + public void Parse(Stream s) + { + var r = new BinaryReader(s); + this.x = r.ReadInt16(); + this.y = r.ReadInt16(); + this.z = r.ReadInt16(); + this.morphY = r.ReadInt16(); + } + + public void UnParse(Stream s) + { + var w = new BinaryWriter(s); + w.Write(this.x); + w.Write(this.y); + w.Write(this.z); + w.Write(this.morphY); + } + + #region AHandlerElement Members + + public override int RecommendedApiVersion + { + get { return recommendedApiVersion; } + } + + public override List ContentFields + { + get { return GetContentFields(this.requestedApiVersion, this.GetType()); } + } + + #endregion + + #region Content Fields + + [ElementPriority(0)] + public Int16 X + { get { return this.x; } + set { if (!value.Equals(this.x)) { this.x = value; this.OnElementChanged(); } } + } + + [ElementPriority(1)] + public Int16 Y + { + get { return this.y; } + set { if (!value.Equals(this.y)) { this.y = value; this.OnElementChanged(); } } + } + + [ElementPriority(2)] + public Int16 Z + { + get { return this.z; } + set { if (!value.Equals(this.z)) { this.z = value; this.OnElementChanged(); } } + } + + [ElementPriority(3)] + public Int16 MorphY + { + get { return this.morphY; } + set { if (!value.Equals(this.morphY)) { this.morphY = value; this.OnElementChanged(); } } + } + + public string Value + { + get { return this.ValueBuilder; } + } + + #endregion + + #region IEquatable + + public bool Equals(TerrainVertex other) + { + return this.x == other.x && this.y == other.y && this.z == other.z && this.morphY == other.morphY; + } + + #endregion + } + + public class PassList : DependentList + { + #region Constructors + public PassList(EventHandler handler) : base(handler) { } + public PassList(EventHandler handler, Stream s) : base(handler, s) { } + public PassList(EventHandler handler, Stream s, UInt32 count) : base(handler) { this.Parse(s, count); } + public PassList(EventHandler handler, IEnumerable le) : base(handler, le) { } + #endregion + #region Data I/O + + protected void Parse(Stream s, UInt32 count) + { + var r = new BinaryReader(s); + for (var i = 0; i < count; i++) + { + this.Add(new Pass(1, handler, s)); + } + } + + public override void UnParse(Stream s) + { + var w = new BinaryWriter(s); + foreach (Pass pass in this) + { + pass.UnParse(s); + } + } + #endregion + + protected override Pass CreateElement(Stream s) { return new Pass(1, elementHandler, s); } + protected override void WriteElement(Stream s, Pass element) { element.UnParse(s); } + } + + public class Pass : AHandlerElement, IEquatable + { + private const int recommendedApiVersion = 1; + + private UInt16[] bounds = new UInt16[6]; + private byte isOpaque; + private byte isLighting; + byte[] layers; + UInt32[] triangles; + + public Pass(int apiVersion, EventHandler handler) + : base(apiVersion, handler) + { + } + + public Pass(int apiVersion, EventHandler handler, Stream s) + : base(apiVersion, handler) + { + this.Parse(s); + } + + public void Parse(Stream s) + { + var r = new BinaryReader(s); + for (int i = 0; i < 6; i++) { this.bounds[i] = r.ReadUInt16(); } + this.isOpaque = r.ReadByte(); + this.isLighting = r.ReadByte(); + byte layerCount = r.ReadByte(); + layers = new byte[layerCount]; + for (int i = 0; i < layerCount; i++) { layers[i] = r.ReadByte(); } + UInt32 triCount = r.ReadUInt32(); + triangles = new UInt32[triCount]; + for (uint i = 0; i < triCount; i++) { triangles[i] = r.ReadUInt32(); } + } + + public void UnParse(Stream s) + { + var w = new BinaryWriter(s); + for (int i = 0; i < 6; i++) { w.Write(this.bounds[i]); } + w.Write(this.isOpaque); + w.Write(this.isLighting); + w.Write((byte)this.layers.Length); + for (int i = 0; i < layers.Length; i++) { w.Write(layers[i]); } + w.Write((UInt32)this.triangles.LongLength); + for (uint i = 0; i < this.triangles.LongLength; i++) { w.Write(triangles[i]); } + } + + #region AHandlerElement Members + + public override int RecommendedApiVersion + { + get { return recommendedApiVersion; } + } + + public override List ContentFields + { + get { return GetContentFields(this.requestedApiVersion, this.GetType()); } + } + + #endregion + + #region Content Fields + + [ElementPriority(0)] + public UInt16[] Bounds + { + get { return this.bounds; } + set { if (!value.Equals(this.bounds)) { this.bounds = value; this.OnElementChanged(); } } + } + + [ElementPriority(1)] + public byte IsOpaque + { + get { return this.isOpaque; } + set { if (!value.Equals(this.isOpaque)) { this.isOpaque = value; this.OnElementChanged(); } } + } + + [ElementPriority(2)] + public byte IsLighting + { + get { return this.isLighting; } + set { if (!value.Equals(this.isLighting)) { this.isLighting = value; this.OnElementChanged(); } } + } + + [ElementPriority(3)] + public byte[] Layers + { + get { return this.layers; } + set { if (!value.Equals(this.layers)) { this.layers = value; this.OnElementChanged(); } } + } + + [ElementPriority(4)] + public UInt32[] Triangles + { + get { return this.triangles; } + set { if (!value.Equals(this.triangles)) { this.triangles = value; this.OnElementChanged(); } } + } + + public string Value + { + get { return this.ValueBuilder; } + } + + #endregion + + #region IEquatable + + public bool Equals(Pass other) + { + return this.bounds.SequenceEqual(other.bounds) && this.isOpaque == other.isOpaque && this.isLighting == other.isLighting && + this.layers.SequenceEqual(other.layers) && this.triangles.SequenceEqual(other.triangles); + } + + #endregion + } + } + + public class TerrainMeshResourceHandler : AResourceHandler + { + /// + /// Create the content of the Dictionary. + /// + public TerrainMeshResourceHandler() + { + this.Add(typeof(TerrainMeshResource), new List(new string[] { "0xAE39399F", })); + } + } +} diff --git a/s4pi Wrappers/TerrainMeshResource/TerrainMeshResource.csproj b/s4pi Wrappers/TerrainMeshResource/TerrainMeshResource.csproj new file mode 100644 index 0000000..ceb33ee --- /dev/null +++ b/s4pi Wrappers/TerrainMeshResource/TerrainMeshResource.csproj @@ -0,0 +1,69 @@ + + + + + Debug + AnyCPU + {27F9106B-6B9D-4718-8BDC-83EC70A76179} + Library + Properties + TerrainMeshResource + s4pi.TerrainMeshResource + v4.0 + 512 + + + + true + full + false + ..\..\bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + ..\..\bin\Release\ + TRACE + prompt + 4 + + + + + False + ..\..\bin\Debug\System.Custom.dll + + + + + + + + + + {51023bd2-9139-438d-b794-95e5ec023537} + Interfaces + + + {374f37cf-1f27-4613-96fd-9b956a3d82b1} + Settings + + + + + + + + "$(SolutionDir)s4pi\CreateAssemblyVersion\bin\Debug\CreateAssemblyVersion" "$(ProjectDir)\" + + + \ No newline at end of file diff --git a/sims4tools.sln b/sims4tools.sln index fbdb1ef..1926881 100755 --- a/sims4tools.sln +++ b/sims4tools.sln @@ -1,7 +1,5 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Express 2013 for Windows Desktop -VisualStudioVersion = 12.0.40629.0 -MinimumVisualStudioVersion = 10.0.40219.1 +# Visual C# Express 2010 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CreateAssemblyVersion", "s4pi\CreateAssemblyVersion\CreateAssemblyVersion.csproj", "{114622FB-D6BF-4EA7-9BB9-FB06B5A01212}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CS System Classes", "CS System Classes\CS System Classes.csproj", "{00200E76-C245-42A7-B567-5C30EDBCE977}" @@ -142,6 +140,11 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TerrainBlendMapResource", " EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThumbnailCacheResource", "s4pi Wrappers\ThumbnailCacheTableResource\ThumbnailCacheResource.csproj", "{B8796317-C2C8-4315-9F4F-0130DD78646B}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TerrainMeshResource", "s4pi Wrappers\TerrainMeshResource\TerrainMeshResource.csproj", "{27F9106B-6B9D-4718-8BDC-83EC70A76179}" + ProjectSection(ProjectDependencies) = postProject + {00200E76-C245-42A7-B567-5C30EDBCE977} = {00200E76-C245-42A7-B567-5C30EDBCE977} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -632,6 +635,16 @@ Global {B8796317-C2C8-4315-9F4F-0130DD78646B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU {B8796317-C2C8-4315-9F4F-0130DD78646B}.Release|Mixed Platforms.Build.0 = Release|Any CPU {B8796317-C2C8-4315-9F4F-0130DD78646B}.Release|x86.ActiveCfg = Release|Any CPU + {27F9106B-6B9D-4718-8BDC-83EC70A76179}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {27F9106B-6B9D-4718-8BDC-83EC70A76179}.Debug|Any CPU.Build.0 = Debug|Any CPU + {27F9106B-6B9D-4718-8BDC-83EC70A76179}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {27F9106B-6B9D-4718-8BDC-83EC70A76179}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {27F9106B-6B9D-4718-8BDC-83EC70A76179}.Debug|x86.ActiveCfg = Debug|Any CPU + {27F9106B-6B9D-4718-8BDC-83EC70A76179}.Release|Any CPU.ActiveCfg = Release|Any CPU + {27F9106B-6B9D-4718-8BDC-83EC70A76179}.Release|Any CPU.Build.0 = Release|Any CPU + {27F9106B-6B9D-4718-8BDC-83EC70A76179}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {27F9106B-6B9D-4718-8BDC-83EC70A76179}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {27F9106B-6B9D-4718-8BDC-83EC70A76179}.Release|x86.ActiveCfg = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE