diff --git a/.gitignore b/.gitignore index 197a1a8fa..7489bd5bd 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,5 @@ obj/ GameData/SCANsat/Plugins/SCAN* GameData/SCANsat/PluginData/Settings.cfg GameData/SCANsat/Parts/@thumbs/ -Releases/ \ No newline at end of file +GameData/ +Releases/ diff --git a/GameData/SCANsat/Resources/scan_prefabs.scan b/GameData/SCANsat/Resources/scan_prefabs.scan index 929a24fc2..40434186e 100644 Binary files a/GameData/SCANsat/Resources/scan_prefabs.scan and b/GameData/SCANsat/Resources/scan_prefabs.scan differ diff --git a/GameData/SCANsat/SCANsat.version b/GameData/SCANsat/SCANsat.version index af2031d83..43785bdef 100644 --- a/GameData/SCANsat/SCANsat.version +++ b/GameData/SCANsat/SCANsat.version @@ -1,6 +1,9 @@ { "NAME": "SCANsat", "URL": "https://github.com/KSPModStewards/SCANsat/releases/latest/download/SCANsat.version", - "DOWNLOAD": "https://github.com/KSPModStewards/SCANsat/releases" - + "DOWNLOAD": "https://github.com/KSPModStewards/SCANsat/releases", + "VERSION": "1.0.0.0", + "KSP_VERSION": "1.12", + "KSP_VERSION_MIN": "1.12.3", + "KSP_VERSION_MAX": "'1.12'" } diff --git a/SCANsat.Unity/Interfaces/ISCAN_ZoomMap.cs b/SCANsat.Unity/Interfaces/ISCAN_ZoomMap.cs index 1e9b734f7..f1d215e7a 100644 --- a/SCANsat.Unity/Interfaces/ISCAN_ZoomMap.cs +++ b/SCANsat.Unity/Interfaces/ISCAN_ZoomMap.cs @@ -3,7 +3,7 @@ * S.C.A.N. Satellite * * ISCAN_ZoomMap - Interface for transfer of zoom map information - * + * * Copyright (c)2013 damny; * Copyright (c)2014 technogeeky ; * Copyright (c)2014 DMagic @@ -127,6 +127,8 @@ public interface ISCAN_ZoomMap void VesselSync(); + void ExportMap(); + void MoveMap(int i); void ZoomMap(bool zoom); diff --git a/SCANsat.Unity/Unity/SCAN_ZoomMap.cs b/SCANsat.Unity/Unity/SCAN_ZoomMap.cs index 4de4f31ed..f29a938dc 100644 --- a/SCANsat.Unity/Unity/SCAN_ZoomMap.cs +++ b/SCANsat.Unity/Unity/SCAN_ZoomMap.cs @@ -1,10 +1,10 @@ #region license -/* +/* * [Scientific Committee on Advanced Navigation] * S.C.A.N. Satellite * * SCAN_ZoomMap - Script for controlling the zoom map UI - * + * * Copyright (c)2014 David Grandy ; * Copyright (c)2014 technogeeky ; * Copyright (c)2014 (Your Name Here) ; see LICENSE.txt for licensing details. @@ -24,9 +24,9 @@ namespace SCANsat.Unity.Unity public class SCAN_ZoomMap : CanvasFader, IDragHandler, IBeginDragHandler, IEndDragHandler, IPointerDownHandler { [SerializeField] - private float m_MaxWidth = 520; + private float m_MaxWidth = 1100; [SerializeField] - private float m_MaxHeight = 440; + private float m_MaxHeight = 880; [SerializeField] private TextHandler m_Version = null; [SerializeField] @@ -1666,6 +1666,16 @@ public void RefreshMap() UpdateMapData(false); } + public void ExportMap() + { + if (zoomInterface == null) + { + return; + } + + zoomInterface.ExportMap(); + } + public void ToggleColor(bool isOn) { if (!loaded || zoomInterface == null) diff --git a/SCANsat/SCAN_Map/SCANmap.cs b/SCANsat/SCAN_Map/SCANmap.cs index cbf759314..3d23aeb6b 100644 --- a/SCANsat/SCAN_Map/SCANmap.cs +++ b/SCANsat/SCAN_Map/SCANmap.cs @@ -2,7 +2,7 @@ /* * [Scientific Committee on Advanced Navigation] * S.C.A.N. Satellite - * + * * SCANmap - makes maps from data * * Copyright (c)2013 damny; @@ -148,6 +148,16 @@ public MapProjection Projection get { return big_heightmap; } } + internal float[,] Big_SlopeMap + { + get { return big_slopemap; } + } + + internal float[,] ResourceCache + { + get { return resourceCache; } + } + public bool UseCustomRange { get { return useCustomRange; } @@ -174,6 +184,7 @@ public float CustomRange /* MAP: Big Map height map caching */ private float[,] big_heightmap; + private float[,] big_slopemap; private bool cache; private double centeredLong, centeredLat; @@ -464,6 +475,8 @@ internal void setSize(int w, int h, int interpolation = 2, int start = 0, int st resourceMapWidth = mapwidth; resourceMapHeight = mapheight; resourceCache = new float[resourceMapWidth, resourceMapHeight]; + big_heightmap = new float[mapwidth, mapheight]; + big_slopemap = new float[mapwidth, mapheight]; resourceInterpolation = interpolation; resourceMapScale = resourceMapWidth / 360; randomEdges = false; @@ -510,8 +523,9 @@ internal void setWidth(int w) mapheight = (int)(w / 2); startLine = 0; stopLine = mapheight - 1; - /* big map caching */ big_heightmap = new float[mapwidth, mapheight]; + big_slopemap = new float[mapwidth, mapheight]; + map = null; resetMap(resourceActive); } @@ -811,6 +825,7 @@ internal void exportPNG() if (exporter.Exporting) { + ScreenMessages.PostScreenMessage("SCANsat export already in progress; wait for CSV completion", 4, ScreenMessageStyle.UPPER_CENTER); return; } @@ -1017,6 +1032,7 @@ internal Texture2D getPartialMap(bool apply = true) else if (SCANUtil.isCovered(lon, lat, data, SCANtype.Altimetry)) { projVal = terrainElevation(lon, lat, mapwidth, mapheight, big_heightmap, cache, data, out nowColor); + big_heightmap[i, mapstep] = projVal; if (useCustomRange) { baseColor = palette.heightToColor(projVal, nowColor, data.TerrainConfig, customMin, customMax, customRange, true); @@ -1059,6 +1075,7 @@ internal Texture2D getPartialMap(bool apply = true) } float v = Mathf.Clamp((float)Math.Abs(projVal - v1) / (1000f / (float)mapscale), 0, 2f); + big_slopemap[i, mapstep] = v; if (!colorMap) { baseColor = palette.lerp(palette.Black, palette.White, v / 2f); @@ -1456,7 +1473,7 @@ public float terrainElevation(double Lon, double Lat, int W, int H, float[,] hei return terrainElevation(Lon, Lat, W, H, heightMap, true, Data, out c, export); } - private float getResoureCache(double Lon, double Lat) + internal float getResoureCache(double Lon, double Lat) { double resourceLat = fixUnscale(unScaleLatitude(Lat, resourceMapScale), resourceMapHeight); double resourceLon = fixUnscale(unScaleLongitude(Lon, resourceMapScale), resourceMapWidth); diff --git a/SCANsat/SCAN_Map/SCANmapExporter.cs b/SCANsat/SCAN_Map/SCANmapExporter.cs index 23eed94b7..e720f29b9 100644 --- a/SCANsat/SCAN_Map/SCANmapExporter.cs +++ b/SCANsat/SCAN_Map/SCANmapExporter.cs @@ -13,6 +13,8 @@ public class SCANmapExporter : SCAN_MBE { private bool exporting; private volatile bool threadRunning, threadFinished; + private volatile int exportedRows; + private volatile string threadError; public bool Exporting { @@ -21,14 +23,7 @@ public bool Exporting public void exportPNG(SCANmap map, SCANdata data) { - exporting = true; - - if (map == null) - { - return; - } - - if (data == null) + if (map == null || data == null) { return; } @@ -44,12 +39,12 @@ public void exportPNG(SCANmap map, SCANdata data) case mapType.Visual: mode = "visual"; break; } - if (map.ResourceActive && SCANconfigLoader.GlobalResource && !string.IsNullOrEmpty(SCANcontroller.controller.bigMapResource)) + if (map.ResourceActive && SCANconfigLoader.GlobalResource && map.Resource != null) { - mode += "-" + SCANcontroller.controller.bigMapResource; + mode += "-" + map.Resource.Name; } - if (!SCANcontroller.controller.bigMapColor) + if (!map.ColorMap) { mode += "-grey"; } @@ -61,9 +56,12 @@ public void exportPNG(SCANmap map, SCANdata data) baseFileName += "_" + map.Projection.ToString(); } - string filename = baseFileName; + if (map.MSource == mapSource.ZoomMap) + { + baseFileName += string.Format("_{0:F3}_{1:F3}_{2:F3}", map.CenteredLat, map.CenteredLong, map.MapScale); + } - filename += ".png"; + string filename = baseFileName + ".png"; string fullPath = Path.Combine(path, filename); @@ -73,9 +71,9 @@ public void exportPNG(SCANmap map, SCANdata data) SCANUtil.SCANlog("Map of [{0}] saved\nMap Size: {1} X {2}\nMinimum Altitude: {3:F0}m; Maximum Altitude: {4:F0}m\nPixel Width At Equator: {5:F6}m", map.Body.displayName.LocalizeBodyName(), map.Map.width, map.Map.height, data.TerrainConfig.MinTerrain, data.TerrainConfig.MaxTerrain, (map.Body.Radius * 2 * Math.PI) / (map.Map.width * 1f)); - if (SCAN_Settings_Config.Instance.ExportCSV && map.MType == mapType.Altimetry) + if (SCAN_Settings_Config.Instance.ExportCSV && map.MType != mapType.Visual) { - StartCoroutine(exportCSV(path, baseFileName, map, data)); + StartCoroutine(exportCSV(path, baseFileName, map, data, map.ResourceActive && SCANconfigLoader.GlobalResource && map.Resource != null)); } else { @@ -83,93 +81,196 @@ public void exportPNG(SCANmap map, SCANdata data) } } - private IEnumerator exportCSV(string filePath, string fileName, SCANmap map, SCANdata data) + private IEnumerator exportCSV(string filePath, string fileName, SCANmap map, SCANdata data, bool resourceActive) { int timer = 0; + double latitudeOffset = 0; + double longitudeOffset = 0; SCANdata copy = new SCANdata(data); - float[,] copyHeightMap = new float[map.MapWidth, map.MapHeight]; + float[,] copyHeightMap = null; + if (map.MType == mapType.Altimetry) + { + copyHeightMap = new float[map.MapWidth, map.MapHeight]; + Array.Copy(map.Big_HeightMap, copyHeightMap, map.MapWidth * map.MapHeight); + } + + float[,] copySlopeMap = null; + if (map.MType == mapType.Slope) + { + copySlopeMap = new float[map.MapWidth, map.MapHeight]; + Array.Copy(map.Big_SlopeMap, copySlopeMap, map.MapWidth * map.MapHeight); + } + + float[,] copyResourceMap = null; + if (resourceActive) + { + copyResourceMap = new float[map.MapWidth, map.MapHeight]; + + for (int y = 0; y < map.MapHeight; y++) + { + int resourceY = y * map.ResourceCache.GetLength(1) / map.MapHeight; - Array.Copy(map.Big_HeightMap, copyHeightMap, map.MapWidth * map.MapHeight); + for (int x = 0; x < map.MapWidth; x++) + { + int resourceX = x * map.ResourceCache.GetLength(0) / map.MapWidth; + copyResourceMap[x, y] = map.ResourceCache[resourceX, resourceY]; + } + } + } int width = map.MapWidth; int height = map.MapHeight; double scale = map.MapScale; + mapType mode = map.MType; - Thread t = new Thread(() => exportThread(filePath, fileName, width, height, scale, map, copy, copyHeightMap)); + if (map.MSource == mapSource.ZoomMap) + { + latitudeOffset = map.Lat_Offset; + longitudeOffset = map.Lon_Offset; + } + + exporting = true; + + Thread t = new Thread(() => exportThread(filePath, fileName, width, height, scale, latitudeOffset, longitudeOffset, map, copy, copyHeightMap, copySlopeMap, copyResourceMap, mode, resourceActive)); + exportedRows = 0; + threadError = null; threadFinished = false; threadRunning = true; t.Start(); - while (threadRunning && timer < 20000) + while (threadRunning && timer < 50000) { timer++; + + if (timer % 60 == 0) + { + int rows = exportedRows; + double percent = height > 0 ? rows * 100.0 / height : 0; + + ScreenMessages.PostScreenMessage(string.Format("SCANsat CSV export: {0:N0}/{1:N0} rows ({2:F1}%)", rows, height, percent), 1.1f, ScreenMessageStyle.UPPER_CENTER); + } + yield return null; } - SCANUtil.SCANlog(".csv data file export complete; exported over {0} frames\nFile saved to GameData/SCANsat/PluginData/{1}_data.csv", timer, fileName); + if (threadRunning) + { + Log.Error(string.Format("SCANsat CSV export timed out after {0} frames for [{1}_data.csv] at row {2} of {3}", timer, fileName, exportedRows, height)); - copy = null; - copyHeightMap = null; - exporting = false; + ScreenMessages.PostScreenMessage("SCANsat CSV export timed out; see KSP.log", 8, ScreenMessageStyle.UPPER_CENTER); - if (timer >= 20000) - { - Log.Error("Something went wrong while exporting .csv data file\nCanceling export thread..."); t.Abort(); - threadRunning = false; + while (threadRunning) + { + yield return null; + } + + exporting = false; yield break; } if (!threadFinished) { - Log.Error("Something went wrong while exporting .csv data file\nExport thread has been interrupted..."); + Log.Error(string.Format("SCANsat CSV export failed for [{0}_data.csv]\n{1}", fileName, threadError ?? "No error details")); + + ScreenMessages.PostScreenMessage("SCANsat CSV export failed; see KSP.log", 8, ScreenMessageStyle.UPPER_CENTER); + + exporting = false; yield break; } + + SCANUtil.SCANlog(".csv data file export complete; exported over {0} frames\nFile saved to GameData/SCANsat/PluginData/{1}_data.csv", timer, fileName); + + ScreenMessages.PostScreenMessage("SCANsat CSV saved: GameData/SCANsat/PluginData/" + fileName + "_data.csv", 8, ScreenMessageStyle.UPPER_CENTER); + + exporting = false; } - private void exportThread(string path, string fileName, int w, int h, double s, SCANmap map, SCANdata copyData, float[,] copyMap) + private void exportThread(string path, string fileName, int w, int h, double s, double latitudeOffset, double longitudeOffset, SCANmap map, SCANdata copyData, float[,] copyHeightMap, float[,] copySlopeMap, float[,] copyResourceMap, mapType mode, bool resourceActive) { try { using (StreamWriter writer = new StreamWriter(Path.Combine(path, fileName + "_data" + ".csv"))) { - string line = "Row,Column,Lat,Long,Height"; + string line = "Row,Column,Lat,Long"; + switch (mode) + { + case mapType.Altimetry: line += ",Height"; break; + case mapType.Slope: line += ",Slope"; break; + case mapType.Biome: line += ",Biome"; break; + } + + if (resourceActive) + { + line += ",ResourceAbundancePercent"; + } + writer.WriteLine(line); for (int i = 0; i < h; i++) { for (int j = 0; j < w; j++) { - double lat = (i * 1.0f / s) - 90f; - double lon = (j * 1.0f / s) - 180f; - double la = lat, lo = lon; - lat = map.unprojectLatitude(lo, la); - lon = map.unprojectLongitude(lo, la); + double lat = (i * 1.0d / s) - 90d + latitudeOffset; + double lon = (j * 1.0d / s) - 180d + longitudeOffset; + + lat = map.unprojectLatitude(lon, lat); + lon = map.unprojectLongitude(lon, lat); if (double.IsNaN(lat) || double.IsNaN(lon) || lat < -90 || lat > 90 || lon < -180 || lon > 180) { continue; } - if (!SCANUtil.isCovered(lon, lat, copyData, SCANtype.Altimetry)) + SCANtype coverage = mode == mapType.Biome ? SCANtype.Biome : SCANtype.Altimetry; + if (!SCANUtil.isCovered(lon, lat, copyData, coverage)) { continue; } - float terrain = map.terrainElevation(lon, lat, w, h, copyMap, copyData, true); + switch (mode) + { + case mapType.Altimetry: + float terrain = copyHeightMap[j, i]; + line = string.Format("{0},{1},{2:F3},{3:F3},{4:F3}", i, j, lat, lon, terrain); + break; + case mapType.Slope: + line = string.Format("{0},{1},{2:F3},{3:F3},{4:F6}", i, j, lat, lon, copySlopeMap[j, i]); + break; + case mapType.Biome: + string biome = SCANUtil.getBiomeName(map.Body, lon, lat).Replace("\"", "\"\""); + line = string.Format("{0},{1},{2:F3},{3:F3},\"{4}\"", i, j, lat, lon, biome); + break; + default: + continue; + } - line = string.Format("{0},{1},{2:F3},{3:F3},{4:F3}", i, j, lat, lon, terrain); + if (resourceActive) + { + if (SCANUtil.isCovered(lon, lat, copyData, SCANtype.ResourceHiRes) || + SCANUtil.isCovered(lon, lat, copyData, SCANtype.ResourceLoRes)) + { + line += string.Format(",{0:F3}", copyResourceMap[j, i]); + } + else + { + line += ","; + } + } writer.WriteLine(line); } writer.Flush(); + exportedRows = i + 1; } } + threadFinished = true; } - catch + catch (Exception ex) { + threadError = ex.ToString(); threadFinished = false; } finally diff --git a/SCANsat/SCAN_Reflection/SCANparallaxContinued.cs b/SCANsat/SCAN_Reflection/SCANparallaxContinued.cs index 803ef84fe..0e9dc0bc6 100644 --- a/SCANsat/SCAN_Reflection/SCANparallaxContinued.cs +++ b/SCANsat/SCAN_Reflection/SCANparallaxContinued.cs @@ -11,7 +11,7 @@ static class SCANparallaxContinued static MethodInfo x_ParallaxScaledBody_Load = null; static MethodInfo x_ParallaxScaledBody_SetScaledMaterialParams = null; static FieldInfo x_ParallaxScaledBody_scaledMaterial = null; - + static FieldInfo x_ConfigLoader_parallaxScaledBodies = null; internal static bool ParallaxContinuedLoaded = false; @@ -84,4 +84,4 @@ internal static void LoadParallax(CelestialBody body, ref Material material) } } } -} \ No newline at end of file +} diff --git a/SCANsat/SCAN_Unity/SCAN_UI_Settings.cs b/SCANsat/SCAN_Unity/SCAN_UI_Settings.cs index 25a80a872..f419b9dea 100644 --- a/SCANsat/SCAN_Unity/SCAN_UI_Settings.cs +++ b/SCANsat/SCAN_Unity/SCAN_UI_Settings.cs @@ -1,10 +1,10 @@ #region license -/* +/* * [Scientific Committee on Advanced Navigation] * S.C.A.N. Satellite * * SCAN_UI_Settings - UI control object for SCANsat settings window - * + * * Copyright (c)2014 David Grandy ; * Copyright (c)2014 technogeeky ; * Copyright (c)2014 (Your Name Here) ; see LICENSE.txt for licensing details. diff --git a/SCANsat/SCAN_Unity/SCAN_UI_ZoomMap.cs b/SCANsat/SCAN_Unity/SCAN_UI_ZoomMap.cs index 9b489ed88..87782ff38 100644 --- a/SCANsat/SCAN_Unity/SCAN_UI_ZoomMap.cs +++ b/SCANsat/SCAN_Unity/SCAN_UI_ZoomMap.cs @@ -1,10 +1,10 @@ #region license -/* +/* * [Scientific Committee on Advanced Navigation] * S.C.A.N. Satellite * * SCAN_UI_ZoomMap - UI control object for SCANsat zoom map - * + * * Copyright (c)2014 David Grandy ; * Copyright (c)2014 technogeeky ; * Copyright (c)2014 (Your Name Here) ; see LICENSE.txt for licensing details. @@ -408,6 +408,16 @@ public void resetMap(bool withCenter, double lat, double lon) spotmap.resetMap(ResourceToggle, narrowBand); } + public void ExportMap() + { + if (spotmap == null || spotmap.Map == null || rebuilding) + { + return; + } + + spotmap.exportPNG(); + } + public void resetMapToVessel() { vessel = FlightGlobals.ActiveVessel; @@ -704,7 +714,7 @@ public void Update() if (vesselChanged) { vesselChanged = false; - + if (uiElement != null) { uiElement.RefreshIcons(); diff --git a/Unity/SCANsat/Assets/Images/UI_Sprite.spriteatlas b/Unity/SCANsat/Assets/Images/UI_Sprite.spriteatlas index 2c555f51a..a2610a7d2 100644 Binary files a/Unity/SCANsat/Assets/Images/UI_Sprite.spriteatlas and b/Unity/SCANsat/Assets/Images/UI_Sprite.spriteatlas differ diff --git a/Unity/SCANsat/Assets/Plugins/SCANsat.Unity.dll b/Unity/SCANsat/Assets/Plugins/SCANsat.Unity.dll index 41540537a..b647589c3 100644 Binary files a/Unity/SCANsat/Assets/Plugins/SCANsat.Unity.dll and b/Unity/SCANsat/Assets/Plugins/SCANsat.Unity.dll differ diff --git a/Unity/SCANsat/Assets/Plugins/SPCANsat.Unity.dll b/Unity/SCANsat/Assets/Plugins/SPCANsat.Unity.dll new file mode 100644 index 000000000..7c591c6b0 Binary files /dev/null and b/Unity/SCANsat/Assets/Plugins/SPCANsat.Unity.dll differ diff --git a/Unity/SCANsat/Assets/Plugins/SPCANsat.Unity.dll.meta b/Unity/SCANsat/Assets/Plugins/SPCANsat.Unity.dll.meta new file mode 100644 index 000000000..09802eb20 --- /dev/null +++ b/Unity/SCANsat/Assets/Plugins/SPCANsat.Unity.dll.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 962166bd63b9ea842bf89e7650aa6423 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 1 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + Windows Store Apps: WindowsStoreApps + second: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/Unity/SCANsat/Assets/Prefabs/SCAN_BigMap.prefab b/Unity/SCANsat/Assets/Prefabs/SCAN_BigMap.prefab index 82a97b096..1c9f3a9c4 100644 Binary files a/Unity/SCANsat/Assets/Prefabs/SCAN_BigMap.prefab and b/Unity/SCANsat/Assets/Prefabs/SCAN_BigMap.prefab differ diff --git a/Unity/SCANsat/Assets/Prefabs/SCAN_ZoomMap.prefab b/Unity/SCANsat/Assets/Prefabs/SCAN_ZoomMap.prefab index 72e1eb20c..b2fd03cc5 100644 Binary files a/Unity/SCANsat/Assets/Prefabs/SCAN_ZoomMap.prefab and b/Unity/SCANsat/Assets/Prefabs/SCAN_ZoomMap.prefab differ diff --git a/Unity/SCANsat/ProjectSettings/EditorSettings.asset b/Unity/SCANsat/ProjectSettings/EditorSettings.asset index 0c0c80440..6426b1a35 100644 Binary files a/Unity/SCANsat/ProjectSettings/EditorSettings.asset and b/Unity/SCANsat/ProjectSettings/EditorSettings.asset differ