diff --git a/GameData/RealSolarSystem/Plugins/RealSolarSystem.dll b/GameData/RealSolarSystem/Plugins/RealSolarSystem.dll index 82b7f2b6..c9ce7272 100644 Binary files a/GameData/RealSolarSystem/Plugins/RealSolarSystem.dll and b/GameData/RealSolarSystem/Plugins/RealSolarSystem.dll differ diff --git a/Source/KopernicusMods/MapSODemandLarge.cs b/Source/KopernicusMods/MapSODemandLarge.cs new file mode 100644 index 00000000..e3f14acb --- /dev/null +++ b/Source/KopernicusMods/MapSODemandLarge.cs @@ -0,0 +1,1029 @@ +/* + * This code is adapted from Kopernicus + * Available from https://github.com/Kopernicus/Kopernicus + */ + +using System; +using System.IO; +using DDSHeaders; +using Kopernicus.ConfigParser.Attributes; +using Kopernicus.ConfigParser.Enumerations; +using Kopernicus.ConfigParser.Interfaces; +using Kopernicus.Components; +using Kopernicus.OnDemand; +using UnityEngine; +using Kopernicus.Configuration.Parsing; +using Kopernicus; + +namespace RealSolarSystem +{ + /// + /// MapSO Replacement to support Texture streaming and textures larger than 16k + /// + public class MapSODemandLarge : MapSO, ILoadOnDemand + { + // Representation of the map + private NativeByteArray Image { get; set; } + + // States + public Boolean IsLoaded { get; set; } + public Boolean AutoLoad { get; set; } + + // Path of the Texture + public String Path { get; set; } + + // Name + String ILoadOnDemand.Name + { + get { return name; } + set { name = value; } + } + + // These textures are potentially too big to make a Texture2D of, so just load directly into the byte array + private void LoadTexture(String path) + { + path = KSPUtil.ApplicationRootPath + "GameData/" + path; + if (File.Exists(path)) + { + try + { + if (path.ToLower().EndsWith(".dds")) + { + // Borrowed from stock KSP 1.0 DDS loader (hi Mike!) + // Also borrowed the extra bits from Sarbian. + BinaryReader binaryReader = new BinaryReader(File.OpenRead(path)); + UInt32 num = binaryReader.ReadUInt32(); + if (num == DDSValues.uintMagic) + { + + DDSHeader ddsHeader = new DDSHeader(binaryReader); + + if (ddsHeader.ddspf.dwFourCC == DDSValues.uintDX10) + { + // ReSharper disable once ObjectCreationAsStatement + new DDSHeaderDX10(binaryReader); + } + + Boolean alpha = (ddsHeader.ddspf.dwFlags & 0x00000002) != 0; + Boolean fourcc = (ddsHeader.ddspf.dwFlags & 0x00000004) != 0; + Boolean rgb = (ddsHeader.ddspf.dwFlags & 0x00000040) != 0; + Boolean alphapixel = (ddsHeader.ddspf.dwFlags & 0x00000001) != 0; + Boolean luminance = (ddsHeader.ddspf.dwFlags & 0x00020000) != 0; + + Boolean mipmap = (ddsHeader.dwCaps & DDSPixelFormatCaps.MIPMAP) != 0u; + if (fourcc) + { + Debug.Log("[Kopernicus]: Compressed textures are not are supported for large maps."); + } + else + { + TextureFormat textureFormat = TextureFormat.ARGB32; + Boolean ok = true; + if (!rgb && alpha != luminance && (ddsHeader.ddspf.dwRGBBitCount == 8 || ddsHeader.ddspf.dwRGBBitCount == 16)) + { + if (ddsHeader.ddspf.dwRGBBitCount == 8) + { + // A8 format or Luminance 8 + if (alpha) + textureFormat = TextureFormat.Alpha8; + else + textureFormat = TextureFormat.R8; + } + else if (ddsHeader.ddspf.dwRGBBitCount == 16) + { + // R16 format + textureFormat = TextureFormat.R16; + } + } + else + { + ok = false; + Debug.Log("[Kopernicus]: Only A8, R8, and R16 are supported"); + } + + if (ok) + { + _name = name; + _width = (Int32)ddsHeader.dwWidth; + _height = (Int32)ddsHeader.dwHeight; + _isCompiled = false; + + if (textureFormat == TextureFormat.R16) + _bpp = (Int32)MapDepth.HeightAlpha; + else + _bpp = (Int32)MapDepth.Greyscale; + + _rowWidth = _width * _bpp; + + Int32 dataSize = _rowWidth * _height; + + Image = new NativeByteArray(dataSize); + byte[] ddsData = binaryReader.ReadBytes(dataSize); + + for (Int32 i = 0; i < dataSize; i++) + { + Image[i] = ddsData[i]; + } + + Debug.Log("[Kopernicus]: Loaded large map: " + path); + } + } + } + else + { + Debug.Log("[Kopernicus]: Bad DDS header."); + } + } + else + { + Debug.Log("[Kopernicus]: Only DDS is supported for large maps."); + } + } + catch (Exception ex) + { + Debug.Log("[Kopernicus]: failed to load " + path + " with exception " + ex.Message); + } + } + else + { + Debug.Log("[Kopernicus]: texture does not exist! " + path); + } + } + + /// + /// Load the Map + /// + public void Load() + { + // Check if the Map is already loaded + if (IsLoaded) + { + return; + } + + if (OnDemandStorage.UseManualMemoryManagement) + { + // Load the Map + LoadTexture(Path); + + IsLoaded = true; + + // Create a dummy map for firing events + MapSODemand eventMap = (MapSODemand)ScriptableObject.CreateInstance(typeof(MapSODemand)); + eventMap.name = name; + eventMap.Path = Path; + Events.OnMapSOLoad.Fire(eventMap); + + Debug.Log("[OD] ---> Map " + name + " enabling self. Path = " + Path); + return; + } + + // Return nothing + Debug.Log("[OD] ERROR: Failed to load map " + name + " at path " + Path); + } + + /// + /// Unload the map + /// + public void Unload() + { + // We can only destroy the map, if it is loaded + if (!IsLoaded) + { + return; + } + + // Nuke the map + if (OnDemandStorage.UseManualMemoryManagement) + { + Image.Free(); + } + + // Set flags + IsLoaded = false; + + // Create a dummy map for firing events + MapSODemand eventMap = (MapSODemand)ScriptableObject.CreateInstance(typeof(MapSODemand)); + eventMap.name = name; + eventMap.Path = Path; + Events.OnMapSOUnload.Fire(eventMap); + + // Log + Debug.Log("[OD] <--- Map " + name + " disabling self. Path = " + Path); + } + + // GetPixelByte + public override Byte GetPixelByte(Int32 x, Int32 y) + { + // If we aren't loaded.... + if (!IsLoaded) + { + if (OnDemandStorage.OnDemandLogOnMissing) + { + Debug.Log("[OD] ERROR: getting pixelbyte with unloaded map " + name + " of path " + Path + ", autoload = " + AutoLoad); + } + + if (AutoLoad) + { + Load(); + } + else + { + return 0; + } + } + + if (!OnDemandStorage.UseManualMemoryManagement) + { + return 0; + } + + if (x < 0) + { + x = Width - x; + } + else if (x >= Width) + { + x -= Width; + } + + if (y < 0) + { + y = Height - y; + } + else if (y >= Height) + { + y -= Height; + } + + return Image[PixelIndex(x, y)]; + } + + // GetPixelColor - Double + public override Color GetPixelColor(Double x, Double y) + { + if (IsLoaded) + { + return base.GetPixelColor(x, y); + } + + if (OnDemandStorage.OnDemandLogOnMissing) + { + Debug.Log("[OD] ERROR: getting pixelColD with unloaded map " + name + " of path " + Path + + ", autoload = " + AutoLoad); + } + + if (AutoLoad) + { + Load(); + } + else + { + return Color.black; + } + + return base.GetPixelColor(x, y); + } + + // GetPixelColor - Float + public override Color GetPixelColor(Single x, Single y) + { + if (IsLoaded) + { + return base.GetPixelColor(x, y); + } + + if (OnDemandStorage.OnDemandLogOnMissing) + { + Debug.Log("[OD] ERROR: getting pixelColF with unloaded map " + name + " of path " + Path + + ", autoload = " + AutoLoad); + } + + if (AutoLoad) + { + Load(); + } + else + { + return Color.black; + } + + return base.GetPixelColor(x, y); + } + + // GetPixelColor - Int + public override Color GetPixelColor(Int32 x, Int32 y) + { + if (!IsLoaded) + { + if (OnDemandStorage.OnDemandLogOnMissing) + { + Debug.Log("[OD] ERROR: getting pixelColI with unloaded map " + name + " of path " + Path + + ", autoload = " + AutoLoad); + } + + if (AutoLoad) + { + Load(); + } + else + { + return Color.black; + } + } + + if (!OnDemandStorage.UseManualMemoryManagement) + { + return new Color(); + } + + index = PixelIndex(x, y); + switch (_bpp) + { + case 3: + return new Color(Byte2Float * Image[index], Byte2Float * Image[index + 1], + Byte2Float * Image[index + 2], 1f); + case 4: + return new Color(Byte2Float * Image[index], Byte2Float * Image[index + 1], + Byte2Float * Image[index + 2], Byte2Float * Image[index + 3]); + } + + if (_bpp != 2) + { + retVal = Byte2Float * Image[index]; + return new Color(retVal, retVal, retVal, 1f); + } + + retVal = Byte2Float * Image[index]; + return new Color(retVal, retVal, retVal, Byte2Float * Image[index + 1]); + } + + // GetPixelColor32 - Double + public override Color GetPixelColor32(Double x, Double y) + { + if (IsLoaded) + { + return base.GetPixelColor32(x, y); + } + + if (OnDemandStorage.OnDemandLogOnMissing) + { + Debug.Log("[OD] ERROR: getting pixelCol32D with unloaded map " + name + " of path " + Path + + ", autoload = " + AutoLoad); + } + + if (AutoLoad) + { + Load(); + } + else + { + return Color.black; + } + + return base.GetPixelColor32(x, y); + } + + // GetPixelColor32 - Float - Honestly Squad, why are they named GetPixelColor32, but return normal Colors instead of Color32? + public override Color GetPixelColor32(Single x, Single y) + { + if (IsLoaded) + { + return base.GetPixelColor32(x, y); + } + + if (OnDemandStorage.OnDemandLogOnMissing) + { + Debug.Log("[OD] ERROR: getting pixelCol32F with unloaded map " + name + " of path " + Path + + ", autoload = " + AutoLoad); + } + + if (AutoLoad) + { + Load(); + } + else + { + return Color.black; + } + + return base.GetPixelColor32(x, y); + } + + // GetPixelColor32 - Int + public override Color32 GetPixelColor32(Int32 x, Int32 y) + { + if (!IsLoaded) + { + if (OnDemandStorage.OnDemandLogOnMissing) + { + Debug.Log("[OD] ERROR: getting pixelCol32I with unloaded map " + name + " of path " + Path + + ", autoload = " + AutoLoad); + } + + if (AutoLoad) + { + Load(); + } + else + { + return new Color32(); + } + } + + if (!OnDemandStorage.UseManualMemoryManagement) + { + return new Color32(); + } + + index = PixelIndex(x, y); + switch (_bpp) + { + case 3: + return new Color32(Image[index], Image[index + 1], Image[index + 2], 255); + case 4: + return new Color32(Image[index], Image[index + 1], Image[index + 2], Image[index + 3]); + } + + if (_bpp != 2) + { + val = Image[index]; + return new Color32(val, val, val, 255); + } + + val = Image[index]; + return new Color32(val, val, val, Image[index + 1]); + } + + // GetPixelFloat - Double + public override Single GetPixelFloat(Double x, Double y) + { + if (IsLoaded) + { + return base.GetPixelFloat(x, y); + } + + if (OnDemandStorage.OnDemandLogOnMissing) + { + Debug.Log("[OD] ERROR: getting pixelFloatD with unloaded map " + name + " of path " + Path + + ", autoload = " + AutoLoad); + } + + if (AutoLoad) + { + Load(); + } + else + { + return 0f; + } + + return base.GetPixelFloat(x, y); + } + + // GetPixelFloat - Float + public override Single GetPixelFloat(Single x, Single y) + { + if (IsLoaded) + { + return base.GetPixelFloat(x, y); + } + + if (OnDemandStorage.OnDemandLogOnMissing) + { + Debug.Log("[OD] ERROR: getting pixelFloatF with unloaded map " + name + " of path " + Path + + ", autoload = " + AutoLoad); + } + + if (AutoLoad) + { + Load(); + } + else + { + return 0f; + } + + return base.GetPixelFloat(x, y); + } + + // GetPixelFloat - Integer + public override Single GetPixelFloat(Int32 x, Int32 y) + { + if (!IsLoaded) + { + if (OnDemandStorage.OnDemandLogOnMissing) + { + Debug.Log("[OD] ERROR: getting pixelFloatI with unloaded map " + name + " of path " + Path + + ", autoload = " + AutoLoad); + } + + if (AutoLoad) + { + Load(); + } + else + { + return 0f; + } + } + + if (OnDemandStorage.UseManualMemoryManagement) + { + retVal = 0f; + index = PixelIndex(x, y); + for (Int32 i = 0; i < _bpp; i++) + { + retVal += Image[index + i]; + } + + retVal /= _bpp; + retVal *= Byte2Float; + return retVal; + } + + return 0f; + } + + // GetPixelHeightAlpha - Double + public override HeightAlpha GetPixelHeightAlpha(Double x, Double y) + { + if (IsLoaded) + { + return base.GetPixelHeightAlpha(x, y); + } + + if (OnDemandStorage.OnDemandLogOnMissing) + { + Debug.Log("[OD] ERROR: getting pixelHeightAlphaD with unloaded map " + name + " of path " + Path + + ", autoload = " + AutoLoad); + } + + if (AutoLoad) + { + Load(); + } + else + { + return new HeightAlpha(0f, 0f); + } + + return base.GetPixelHeightAlpha(x, y); + } + + // GetPixelHeightAlpha - Float + public override HeightAlpha GetPixelHeightAlpha(Single x, Single y) + { + if (IsLoaded) + { + return base.GetPixelHeightAlpha(x, y); + } + + if (OnDemandStorage.OnDemandLogOnMissing) + { + Debug.Log("[OD] ERROR: getting pixelHeightAlphaF with unloaded map " + name + " of path " + Path + + ", autoload = " + AutoLoad); + } + + if (AutoLoad) + { + Load(); + } + else + { + return new HeightAlpha(0f, 0f); + } + + return base.GetPixelHeightAlpha(x, y); + } + + // GetPixelHeightAlpha - Int + public override HeightAlpha GetPixelHeightAlpha(Int32 x, Int32 y) + { + if (!IsLoaded) + { + if (OnDemandStorage.OnDemandLogOnMissing) + { + Debug.Log("[OD] ERROR: getting pixelHeightAlphaI with unloaded map " + name + " of path " + + Path + ", autoload = " + AutoLoad); + } + + if (AutoLoad) + { + Load(); + } + else + { + return new HeightAlpha(0f, 0f); + } + } + + if (OnDemandStorage.UseManualMemoryManagement) + { + index = PixelIndex(x, y); + if (_bpp == 2) + { + return new HeightAlpha(Byte2Float * Image[index], Byte2Float * Image[index + 1]); + } + + if (_bpp != 4) + { + return new HeightAlpha(Byte2Float * Image[index], 1f); + } + + val = Image[index]; + return new HeightAlpha(Byte2Float * Image[index], Byte2Float * Image[index + 3]); + } + + return new HeightAlpha(0f, 0f); + } + + // GreyByte + public override Byte GreyByte(Int32 x, Int32 y) + { + if (!IsLoaded) + { + if (OnDemandStorage.OnDemandLogOnMissing) + { + Debug.Log("[OD] ERROR: getting GreyByteI with unloaded map " + name + " of path " + Path + + ", autoload = " + AutoLoad); + } + + if (AutoLoad) + { + Load(); + } + else + { + return 0; + } + } + + if (OnDemandStorage.UseManualMemoryManagement) + { + return Image[PixelIndex(x, y)]; + } + + return 0; + } + + // GreyFloat + public override Single GreyFloat(Int32 x, Int32 y) + { + if (!IsLoaded) + { + if (OnDemandStorage.OnDemandLogOnMissing) + { + Debug.Log("[OD] ERROR: getting GreyFloat with unloaded map " + name + " of path " + Path + + ", autoload = " + AutoLoad); + } + + if (AutoLoad) + { + Load(); + } + else + { + return 0f; + } + } + + if (OnDemandStorage.UseManualMemoryManagement) + { + return Byte2Float * Image[PixelIndex(x, y)]; + } + + return 0f; + } + + // PixelByte + public override Byte[] PixelByte(Int32 x, Int32 y) + { + if (!IsLoaded) + { + if (OnDemandStorage.OnDemandLogOnMissing) + { + Debug.Log("[OD] ERROR: getting pixelByte with unloaded map " + name + " of path " + Path + + ", autoload = " + AutoLoad); + } + + if (AutoLoad) + { + Load(); + } + else + { + return new Byte[_bpp]; + } + } + + if (OnDemandStorage.UseManualMemoryManagement) + { + Byte[] numArray = new Byte[_bpp]; + index = PixelIndex(x, y); + for (Int32 i = 0; i < _bpp; i++) + { + numArray[i] = Image[index + i]; + } + + return numArray; + } + + return new Byte[_bpp]; + } + + // CompileToTexture + public override Texture2D CompileToTexture(Byte filter) + { + if (!IsLoaded) + { + if (OnDemandStorage.OnDemandLogOnMissing) + { + Debug.Log("[OD] ERROR: compiling with unloaded map " + name + " of path " + Path + ", autoload = " + + AutoLoad); + } + + if (AutoLoad) + { + Load(); + } + else + { + return new Texture2D(_width, _height); + } + } + + if (OnDemandStorage.UseManualMemoryManagement) + { + Color32[] color32 = new Color32[Size]; + for (Int32 i = 0; i < Size; i++) + { + val = (Byte)((Image[i] & filter) == 0 ? 0 : 255); + color32[i] = new Color32(val, val, val, 255); + } + + Texture2D compiled = new Texture2D(Width, Height, TextureFormat.RGB24, false); + compiled.SetPixels32(color32); + compiled.Apply(false, true); + return compiled; + } + return new Texture2D(_width, _height); + } + + // Generate a greyscale texture from the stored data + public override Texture2D CompileGreyscale() + { + if (!IsLoaded) + { + if (OnDemandStorage.OnDemandLogOnMissing) + { + Debug.Log("[OD] ERROR: compiling with unloaded map " + name + " of path " + Path + ", autoload = " + + AutoLoad); + } + + if (AutoLoad) + { + Load(); + } + else + { + return new Texture2D(_width, _height); + } + } + + if (OnDemandStorage.UseManualMemoryManagement) + { + Color32[] color32 = new Color32[Size]; + for (Int32 i = 0; i < Size; i++) + { + val = Image[i]; + color32[i] = new Color32(val, val, val, 255); + } + + Texture2D compiled = new Texture2D(Width, Height, TextureFormat.RGB24, false); + compiled.SetPixels32(color32); + compiled.Apply(false, true); + return compiled; + } + return new Texture2D(_width, _height); + } + + // Generate a height/alpha texture from the stored data + public override Texture2D CompileHeightAlpha() + { + if (!IsLoaded) + { + if (OnDemandStorage.OnDemandLogOnMissing) + { + Debug.Log("[OD] ERROR: compiling with unloaded map " + name + " of path " + Path + ", autoload = " + + AutoLoad); + } + + if (AutoLoad) + { + Load(); + } + else + { + return new Texture2D(_width, _height); + } + } + + if (OnDemandStorage.UseManualMemoryManagement) + { + Color32[] color32 = new Color32[Width * Height]; + for (Int32 i = 0; i < Width * Height; i++) + { + val = Image[i * 2]; + color32[i] = new Color32(val, val, val, Image[i * 2 + 1]); + } + + Texture2D compiled = new Texture2D(Width, Height, TextureFormat.RGB24, false); + compiled.SetPixels32(color32); + compiled.Apply(false, true); + return compiled; + } + return new Texture2D(_width, _height); + } + + // Generate an RGB texture from the stored data + public override Texture2D CompileRGB() + { + if (!IsLoaded) + { + if (OnDemandStorage.OnDemandLogOnMissing) + { + Debug.Log("[OD] ERROR: compiling with unloaded map " + name + " of path " + Path + ", autoload = " + + AutoLoad); + } + + if (AutoLoad) + { + Load(); + } + else + { + return new Texture2D(_width, _height); + } + } + + if (OnDemandStorage.UseManualMemoryManagement) + { + Color32[] color32 = new Color32[Width * Height]; + for (Int32 i = 0; i < Width * Height; i++) + { + color32[i] = new Color32(Image[i * 3], Image[i * 3 + 1], Image[i * 3 + 2], 255); + } + + Texture2D compiled = new Texture2D(Width, Height, TextureFormat.RGB24, false); + compiled.SetPixels32(color32); + compiled.Apply(false, true); + return compiled; + } + return new Texture2D(_width, _height); + } + + // Generate an RGBA texture from the stored data + public override Texture2D CompileRGBA() + { + if (!IsLoaded) + { + if (OnDemandStorage.OnDemandLogOnMissing) + { + Debug.Log("[OD] ERROR: compiling with unloaded map " + name + " of path " + Path + ", autoload = " + + AutoLoad); + } + + if (AutoLoad) + { + Load(); + } + else + { + return new Texture2D(_width, _height); + } + } + + if (OnDemandStorage.UseManualMemoryManagement) + { + Color32[] color32 = new Color32[Width * Height]; + for (Int32 i = 0; i < Width * Height; i++) + { + color32[i] = new Color32(Image[i * 3], Image[i * 3 + 1], Image[i * 3 + 2], Image[i * 3 + 3]); + } + + Texture2D compiled = new Texture2D(Width, Height, TextureFormat.RGB24, false); + compiled.SetPixels32(color32); + compiled.Apply(false, true); + return compiled; + } + return new Texture2D(_width, _height); + } + } + + // Parser for a MapSO + [RequireConfigType(ConfigType.Value)] + public class MapSOParserLarge : BaseLoader, IParsable, ITypeParser where T : MapSO + { + /// + /// The value that is being parsed + /// + public T Value { get; set; } + + /// + /// Parse the Value from a string + /// + public void SetFromString(String s) + { + // Should we use OnDemand? + Boolean useOnDemand = OnDemandStorage.UseOnDemand; + + if (s.StartsWith("BUILTIN/")) + { + s = s.Substring(8); + Value = Utility.FindMapSO(s); + } + else + { + // are we on-demand? Don't load now. + if (useOnDemand && typeof(T) == typeof(MapSO)) + { + if (!Utility.TextureExists(s)) + { + return; + } + + + MapSODemandLarge map = ScriptableObject.CreateInstance(); + map.Path = s; + map.AutoLoad = OnDemandStorage.OnDemandLoadOnMissing; + OnDemandStorage.AddMap(generatedBody.name, map); + Value = map as T; + } + else // Load the texture + { + MapSODemandLarge map = ScriptableObject.CreateInstance(); + map.Path = s; + map.AutoLoad = false; + OnDemandStorage.AddMap(generatedBody.name, map); + Value = map as T; + } + } + + if (Value != null) + { + Value.name = s; + } + } + + /// + /// Convert the value to a parsable String + /// + public String ValueToString() + { + if (Value == null) + { + return null; + } + + if (GameDatabase.Instance.ExistsTexture(Value.name) || OnDemandStorage.TextureExists(Value.name)) + { + return Value.name; + } + + return "BUILTIN/" + Value.name; + } + + /// + /// Create a new MapSOParser_HeightAlpha + /// + public MapSOParserLarge() + { + + } + + /// + /// Create a new MapSOParser_HeightAlpha from an already existing Texture + /// + public MapSOParserLarge(T value) + { + Value = value; + } + + /// + /// Convert Parser to Value + /// + public static implicit operator T(MapSOParserLarge parser) + { + return parser.Value; + } + + /// + /// Convert Value to Parser + /// + public static implicit operator MapSOParserLarge(T value) + { + return new MapSOParserLarge(value); + } + } +} diff --git a/Source/KopernicusMods/PQSMod_VertexHeightMapRSS.cs b/Source/KopernicusMods/PQSMod_VertexHeightMapRSS.cs new file mode 100644 index 00000000..460b01da --- /dev/null +++ b/Source/KopernicusMods/PQSMod_VertexHeightMapRSS.cs @@ -0,0 +1,28 @@ +/* + * This code is adapted from KopernicusExpansion-Continued + * Available from https://github.com/StollD/KopernicusExpansion-Continued + */ + +using System; +using UnityEngine; + +namespace RealSolarSystem +{ + /// + /// A heightmap PQSMod that can parse encoded 16bpp textures + /// + public class PQSMod_VertexHeightMapRSS : PQSMod_VertexHeightMap + { + public override void OnVertexBuildHeight(PQS.VertexBuildData data) + { + // Get the HeightAlpha, not the Float-Value from the Map + MapSO.HeightAlpha ha = heightMap.GetPixelHeightAlpha(data.u, data.v); + + // Get the height data from the terrain + Double height = (ha.height + ha.alpha * (Double)Byte.MaxValue) / (Double)(Byte.MaxValue + 1); + + // Apply it + data.vertHeight += heightMapOffset + heightMapDeformity * height; + } + } +} diff --git a/Source/KopernicusMods/VertexHeightMapRSS.cs b/Source/KopernicusMods/VertexHeightMapRSS.cs new file mode 100644 index 00000000..c15ec173 --- /dev/null +++ b/Source/KopernicusMods/VertexHeightMapRSS.cs @@ -0,0 +1,47 @@ +/* + * This code is adapted from KopernicusExpansion-Continued + * Available from https://github.com/StollD/KopernicusExpansion-Continued + */ + +using System; +using Kopernicus.ConfigParser.Attributes; +using Kopernicus.ConfigParser.BuiltinTypeParsers; +using Kopernicus.Configuration.ModLoader; + +namespace RealSolarSystem +{ + public class VertexHeightMapRSS : ModLoader + { + // The map texture for the planet + [ParserTarget("map")] + public MapSOParserLarge heightMap + { + get { return Mod.heightMap; } + set { Mod.heightMap = value; } + } + + // Height map offset + [ParserTarget("offset")] + public NumericParser heightMapOffset + { + get { return Mod.heightMapOffset; } + set { Mod.heightMapOffset = value; } + } + + // Height map offset + [ParserTarget("deformity")] + public NumericParser heightMapDeformity + { + get { return Mod.heightMapDeformity; } + set { Mod.heightMapDeformity = value; } + } + + // Height map offset + [ParserTarget("scaleDeformityByRadius")] + public NumericParser scaleDeformityByRadius + { + get { return Mod.scaleDeformityByRadius; } + set { Mod.scaleDeformityByRadius = value; } + } + } +} \ No newline at end of file diff --git a/Source/Properties/AssemblyInfo.cs b/Source/Properties/AssemblyInfo.cs index d2dc38d3..caad8356 100644 --- a/Source/Properties/AssemblyInfo.cs +++ b/Source/Properties/AssemblyInfo.cs @@ -38,3 +38,6 @@ [assembly: AssemblyVersion("0.18.0.0")] [assembly: AssemblyFileVersion("0.18.0.0")] + +[assembly: KSPAssemblyDependency("Kopernicus", 1, 0)] +[assembly: KSPAssemblyDependency("Kopernicus.Parser", 1, 0)] \ No newline at end of file diff --git a/Source/RealSolarSystem.csproj b/Source/RealSolarSystem.csproj index 9701f01c..9e187f7d 100644 --- a/Source/RealSolarSystem.csproj +++ b/Source/RealSolarSystem.csproj @@ -11,7 +11,7 @@ Properties RealSolarSystem RealSolarSystem - v4.7.1 + v4.7.2 512 @@ -42,6 +42,9 @@ + + + @@ -51,12 +54,21 @@ False + + False + + + False + False False + + False + False @@ -71,9 +83,6 @@ - - del "System.Core.dll" -