diff --git a/NewHorizons/Builder/ShipLog/MapModeBuilder.cs b/NewHorizons/Builder/ShipLog/MapModeBuilder.cs index 4a351553..7d31418e 100644 --- a/NewHorizons/Builder/ShipLog/MapModeBuilder.cs +++ b/NewHorizons/Builder/ShipLog/MapModeBuilder.cs @@ -10,17 +10,19 @@ using UnityEngine; using UnityEngine.UI; using Logger = NewHorizons.Utility.Logger; using NewHorizons.Builder.Handlers; +using System; namespace NewHorizons.Builder.ShipLog { public static class MapModeBuilder { #region General - public static ShipLogAstroObject[][] ConstructMapMode(string systemName, GameObject transformParent, ShipLogAstroObject[][] currentNav, int layer) { Material greyScaleMaterial = GameObject.Find(ShipLogHandler.PAN_ROOT_PATH + "/TimberHearth/Sprite").GetComponent().material; - List bodies = Main.BodyDict[systemName].Where(b => (b.Config.ShipLog?.mapMode?.remove ?? false) == false).ToList(); + List bodies = Main.BodyDict[systemName].Where( + b => (b.Config.ShipLog?.mapMode?.remove ?? false) == false + ).ToList(); bool flagManualPositionUsed = systemName == "SolarSystem"; bool flagAutoPositionUsed = false; foreach (NewHorizonsBody body in bodies.Where(b => ShipLogHandler.IsVanillaBody(b) == false)) @@ -42,7 +44,7 @@ namespace NewHorizons.Builder.ShipLog } } - if (flagManualPositionUsed) + if(flagManualPositionUsed) { if (flagAutoPositionUsed && flagManualPositionUsed) Logger.LogWarning("Can't mix manual and automatic layout of ship log map mode, defaulting to manual"); @@ -61,7 +63,7 @@ namespace NewHorizons.Builder.ShipLog return ShipLogHandler.GetNameFromAstroID(id) ?? id; } - private static GameObject CreateImage(GameObject nodeGO, IModAssets assets, string imagePath, string name, int layer) + private static GameObject CreateImage(GameObject nodeGO, IModAssets assets, Texture2D texture, string name, int layer) { GameObject newImageGO = new GameObject(name); newImageGO.layer = layer; @@ -73,17 +75,10 @@ namespace NewHorizons.Builder.ShipLog transform.localScale = Vector3.one; Image newImage = newImageGO.AddComponent(); - if (imagePath == "DEFAULT") - { - newImage.sprite = Locator.GetShipLogManager()._shipLogLibrary.defaultEntrySprite; - } - else - { - Texture2D newTexture = assets.GetTexture(imagePath); - Rect rect = new Rect(0, 0, newTexture.width, newTexture.height); - Vector2 pivot = new Vector2(newTexture.width / 2, newTexture.height / 2); - newImage.sprite = Sprite.Create(newTexture, rect, pivot); - } + + Rect rect = new Rect(0, 0, texture.width, texture.height); + Vector2 pivot = new Vector2(texture.width / 2, texture.height / 2); + newImage.sprite = Sprite.Create(texture, rect, pivot); return newImageGO; } @@ -106,15 +101,26 @@ namespace NewHorizons.Builder.ShipLog private static ShipLogAstroObject AddShipLogAstroObject(GameObject gameObject, NewHorizonsBody body, Material greyScaleMaterial, int layer) { const float unviewedIconOffset = 15; - + GameObject unviewedReference = GameObject.Find(ShipLogHandler.PAN_ROOT_PATH + "/TimberHearth/UnviewedIcon"); - + ShipLogAstroObject astroObject = gameObject.AddComponent(); astroObject._id = ShipLogHandler.GetAstroObjectId(body); - string imagePath = body.Config.ShipLog?.mapMode?.revealedSprite ?? "DEFAULT"; - string outlinePath = body.Config.ShipLog?.mapMode?.outlineSprite ?? imagePath; - astroObject._imageObj = CreateImage(gameObject, body.Mod.Assets, imagePath, body.Config.Name + " Revealed", layer); + Texture2D image; + Texture2D outline; + + string imagePath = body.Config.ShipLog?.mapMode?.revealedSprite; + string outlinePath = body.Config.ShipLog?.mapMode?.outlineSprite; + + if (imagePath != null) image = body.Mod.Assets.GetTexture(imagePath); + else image = AutoGenerateMapModePicture(body); + + if (outlinePath != null) outline = body.Mod.Assets.GetTexture(outlinePath); + else outline = ImageUtilities.MakeOutline(image, Color.white, 10); + + astroObject._imageObj = CreateImage(gameObject, body.Mod.Assets, image, body.Config.Name + " Revealed", layer); + astroObject._outlineObj = CreateImage(gameObject, body.Mod.Assets, outline, body.Config.Name + " Outline", layer); if (ShipLogHandler.BodyHasEntries(body)) { Image revealedImage = astroObject._imageObj.GetComponent(); @@ -124,36 +130,41 @@ namespace NewHorizons.Builder.ShipLog astroObject._image = revealedImage; } - astroObject._outlineObj = CreateImage(gameObject, body.Mod.Assets, outlinePath, body.Config.Name + " Outline", layer); - - astroObject._unviewedObj = Object.Instantiate(unviewedReference, gameObject.transform, false); + astroObject._unviewedObj = GameObject.Instantiate(unviewedReference, gameObject.transform, false); astroObject._invisibleWhenHidden = body.Config.ShipLog?.mapMode?.invisibleWhenHidden ?? false; Rect imageRect = astroObject._imageObj.GetComponent().rect; astroObject._unviewedObj.transform.localPosition = new Vector3(imageRect.width / 2 + unviewedIconOffset, imageRect.height / 2 + unviewedIconOffset, 0); return astroObject; } - #endregion - + # region Details - - private static void MakeDetail(ShipLogModule.ShipLogDetailInfo info, Transform parent, IModAssets assets, Material greyScaleMaterial) + private static void MakeDetail(ShipLogModule.ShipLogDetailInfo info, Transform parent, NewHorizonsBody body, Material greyScaleMaterial) { GameObject detailGameObject = new GameObject("Detail"); detailGameObject.transform.SetParent(parent); detailGameObject.SetActive(false); RectTransform detailTransform = detailGameObject.AddComponent(); - detailTransform.localPosition = (Vector2) (info.position ?? new MVector2(0, 0)); + detailTransform.localPosition = (Vector2)(info.position ?? new MVector2(0, 0)); detailTransform.localRotation = Quaternion.Euler(0f, 0f, info.rotation); - detailTransform.localScale = (Vector2) (info.scale ?? new MVector2(0, 0)); + detailTransform.localScale = (Vector2)(info.scale ?? new MVector2(0, 0)); - string revealedPath = info.revealedSprite ?? "DEFAULT"; - string outlinePath = info.outlineSprite ?? revealedPath; + Texture2D image; + Texture2D outline; - Image revealedImage = CreateImage(detailGameObject, assets, revealedPath, "Detail Revealed", parent.gameObject.layer).GetComponent(); - Image outlineImage = CreateImage(detailGameObject, assets, outlinePath, "Detail Outline", parent.gameObject.layer).GetComponent(); + string imagePath = info.revealedSprite; + string outlinePath = info.outlineSprite; + + if (imagePath != null) image = body.Mod.Assets.GetTexture(imagePath); + else image = AutoGenerateMapModePicture(body); + + if (outlinePath != null) outline = body.Mod.Assets.GetTexture(outlinePath); + else outline = ImageUtilities.MakeOutline(image, Color.white, 10); + + Image revealedImage = CreateImage(detailGameObject, body.Mod.Assets, image, "Detail Revealed", parent.gameObject.layer).GetComponent(); + Image outlineImage = CreateImage(detailGameObject, body.Mod.Assets, outline, "Detail Outline", parent.gameObject.layer).GetComponent(); ShipLogDetail detail = detailGameObject.AddComponent(); detail.Init(info, revealedImage, outlineImage, greyScaleMaterial); @@ -175,17 +186,14 @@ namespace NewHorizons.Builder.ShipLog foreach (ShipLogModule.ShipLogDetailInfo detailInfo in body.Config.ShipLog.mapMode.details) { - MakeDetail(detailInfo, detailsTransform, body.Mod.Assets, greyScaleMaterial); + MakeDetail(detailInfo, detailsTransform, body, greyScaleMaterial); } - detailsParent.SetActive(true); } } - #endregion #region Manual Map Mode - private static ShipLogAstroObject[][] ConstructMapModeManual(List bodies, GameObject transformParent, Material greyScaleMaterial, ShipLogAstroObject[][] currentNav, int layer) { int maxAmount = bodies.Count + 20; @@ -199,17 +207,18 @@ namespace NewHorizons.Builder.ShipLog if (Main.Instance.CurrentStarSystem == "SolarSystem") { + for (int y = 0; y < currentNav.Length; y++) { for (int x = 0; x < currentNav[y].Length; x++) { navMatrix[y][x] = currentNav[y][x]; - astroIdToNavIndex.Add(currentNav[y][x].GetID(), new[] {y, x}); + astroIdToNavIndex.Add(currentNav[y][x].GetID(), new [] {y, x}); } - } + } } - foreach (NewHorizonsBody body in bodies) + foreach(NewHorizonsBody body in bodies) { if (body.Config.ShipLog?.mapMode?.manualNavigationPosition == null) continue; @@ -222,19 +231,16 @@ namespace NewHorizons.Builder.ShipLog if (astroName == AstroObject.Name.RingWorld) name = "InvisiblePlanet"; else if (astroName != AstroObject.Name.CustomString) name = astroName.ToString(); } - // Should probably also just fix the IsVanilla method var isVanilla = ShipLogHandler.IsVanillaBody(body); - Logger.Log($"The name: {name} is vanilla? {isVanilla}"); - if (!isVanilla) { GameObject newMapModeGO = CreateMapModeGameObject(body, transformParent, layer, body.Config.ShipLog?.mapMode?.manualPosition); ShipLogAstroObject newAstroObject = AddShipLogAstroObject(newMapModeGO, body, greyScaleMaterial, layer); MakeDetails(body, newMapModeGO.transform, greyScaleMaterial); Vector2 navigationPosition = body.Config.ShipLog?.mapMode?.manualNavigationPosition; - navMatrix[(int) navigationPosition.y][(int) navigationPosition.x] = newAstroObject; + navMatrix[(int)navigationPosition.y][(int)navigationPosition.x] = newAstroObject; } else if (Main.Instance.CurrentStarSystem == "SolarSystem") { @@ -255,22 +261,19 @@ namespace NewHorizons.Builder.ShipLog { GameObject.Find(ShipLogHandler.PAN_ROOT_PATH + "/" + "SandFunnel").SetActive(false); } - gameObject.SetActive(false); } else { if (body.Config.ShipLog?.mapMode?.manualPosition != null) { - gameObject.transform.localPosition = (Vector2) body.Config.ShipLog.mapMode.manualPosition; + gameObject.transform.localPosition = (Vector2)body.Config.ShipLog.mapMode.manualPosition; } - if (body.Config.ShipLog?.mapMode?.manualNavigationPosition != null) { Vector2 navigationPosition = body.Config.ShipLog?.mapMode?.manualNavigationPosition; - navMatrix[(int) navigationPosition.y][(int) navigationPosition.x] = gameObject.GetComponent(); + navMatrix[(int)navigationPosition.y][(int)navigationPosition.x] = gameObject.GetComponent(); } - if (body.Config.ShipLog?.mapMode?.scale != null) { gameObject.transform.localScale = Vector3.one * body.Config.ShipLog.mapMode.scale; @@ -287,11 +290,9 @@ namespace NewHorizons.Builder.ShipLog return navMatrix; } - #endregion - + #region Automatic Map Mode - private class MapModeObject { public int x; @@ -304,20 +305,18 @@ namespace NewHorizons.Builder.ShipLog public List children; public MapModeObject parent; public MapModeObject lastSibling; - public void Increment_width() { branch_width++; parent?.Increment_width(); } - public void Increment_height() { branch_height++; parent?.Increment_height(); } } - + private static ShipLogAstroObject[][] ConstructMapModeAuto(List bodies, GameObject transformParent, Material greyScaleMaterial, int layer) { MapModeObject rootObject = ConstructPrimaryNode(bodies); @@ -329,7 +328,7 @@ namespace NewHorizons.Builder.ShipLog int maxAmount = bodies.Count; ShipLogAstroObject[][] navMatrix = new ShipLogAstroObject[maxAmount][]; for (int i = 0; i < maxAmount; i++) - { + { navMatrix[i] = new ShipLogAstroObject[maxAmount]; } @@ -339,7 +338,6 @@ namespace NewHorizons.Builder.ShipLog { navMatrix[index] = navMatrix[index].Where(a => a != null).ToArray(); } - return navMatrix; } @@ -349,7 +347,6 @@ namespace NewHorizons.Builder.ShipLog { navMatrix[root.y][root.x] = root.astroObject; } - foreach (MapModeObject child in root.children) { CreateNavigationMatrix(child, ref navMatrix); @@ -366,7 +363,7 @@ namespace NewHorizons.Builder.ShipLog parentNode.children[i] = child; } } - + private static MapModeObject ConstructPrimaryNode(List bodies) { foreach (NewHorizonsBody body in bodies.Where(b => b.Config.Base.CenterOfSolarSystem)) @@ -382,60 +379,54 @@ namespace NewHorizons.Builder.ShipLog newNode.children = ConstructChildrenNodes(newNode, bodies); return newNode; } - Logger.LogError("Couldn't find center of system!"); return new MapModeObject(); } - private static List ConstructChildrenNodes(MapModeObject parent, List searchList, string secondaryName = "") + private static List ConstructChildrenNodes(MapModeObject parent, List searchList) { List children = new List(); int newX = parent.x; int newY = parent.y; int newLevel = parent.level + 1; MapModeObject lastSibling = parent; - foreach (NewHorizonsBody body in searchList.Where(b => b.Config.Orbit.PrimaryBody == parent.mainBody.Config.Name || b.Config.Name == secondaryName)) + + foreach (NewHorizonsBody body in searchList.Where(b => b.Config.Orbit.PrimaryBody == parent.mainBody.Config.Name)) { - bool even = newLevel % 2 == 0; - newX = even ? newX : newX + 1; - newY = even ? newY + 1 : newY; - MapModeObject newNode = new MapModeObject() + if (body.Config.Orbit.PrimaryBody == parent.mainBody.Config.Name) { - mainBody = body, - level = newLevel, - x = newX, - y = newY, - parent = parent, - lastSibling = lastSibling - }; - string newSecondaryName = ""; - if (body.Config.FocalPoint != null) - { - newNode.mainBody = Main.BodyDict[Main.Instance.CurrentStarSystem].Find(b => b.Config.Name == body.Config.FocalPoint.Primary); - newSecondaryName = Main.BodyDict[Main.Instance.CurrentStarSystem].Find(b => b.Config.Name == body.Config.FocalPoint.Secondary).Config.Name; + bool even = newLevel % 2 == 0; + newX = even ? newX : newX + 1; + newY = even ? newY + 1 : newY; + MapModeObject newNode = new MapModeObject() + { + mainBody = body, + level = newLevel, + x = newX, + y = newY, + parent = parent, + lastSibling = lastSibling + }; + newNode.children = ConstructChildrenNodes(newNode, searchList); + if (even) + { + newY += newNode.branch_height; + parent.Increment_height(); + newY += 1; + } + else + { + newX += newNode.branch_width; + parent.Increment_width(); + newX += 1; + } + lastSibling = newNode; + children.Add(newNode); } - - newNode.children = ConstructChildrenNodes(newNode, searchList, newSecondaryName); - if (even) - { - newY += newNode.branch_height; - parent.Increment_height(); - newY += 1; - } - else - { - newX += newNode.branch_width; - parent.Increment_width(); - newX += 1; - } - - lastSibling = newNode; - children.Add(newNode); } - return children; } - + private static void ConnectNodeToLastSibling(MapModeObject node, Material greyScaleMaterial) { Vector2 fromPosition = node.astroObject.transform.localPosition; @@ -452,7 +443,7 @@ namespace NewHorizons.Builder.ShipLog transform.localRotation = Quaternion.identity; transform.localScale = node.level % 2 == 0 ? new Vector3(node.astroObject.transform.localScale.x / 5f, Mathf.Abs(fromPosition.y - toPosition.y) / 100f, 1) : new Vector3(Mathf.Abs(fromPosition.x - toPosition.x) / 100f, node.astroObject.transform.localScale.y / 5f, 1); Image linkImage = newLink.AddComponent(); - linkImage.color = new Color(0.28f, 0.28f, 0.5f, 0.28f); + linkImage.color = new Color(0.28f, 0.28f, 0.5f, 0.12f); ShipLogModule.ShipLogDetailInfo linkDetailInfo = new ShipLogModule.ShipLogDetailInfo() { @@ -469,7 +460,7 @@ namespace NewHorizons.Builder.ShipLog private static void MakeNode(ref MapModeObject node, GameObject parent, Material greyScaleMaterial, int layer) { - const float padding = 250f; + const float padding = 50f; Vector2 position = Vector2.zero; if (node.lastSibling != null) { @@ -477,6 +468,9 @@ namespace NewHorizons.Builder.ShipLog Vector3 lastPosition = lastAstroObject.transform.localPosition; position = lastPosition; float extraDistance = (node.mainBody.Config.ShipLog?.mapMode?.offset ?? 0f) * 100; + if (node.x == 1) position.x += (int)padding; + if (node.y == 1) position.y += (int)padding; + if (node.level % 2 == 0) { position.y += padding * (node.y - node.lastSibling.y) + extraDistance; @@ -486,14 +480,66 @@ namespace NewHorizons.Builder.ShipLog position.x += padding * (node.x - node.lastSibling.x) + extraDistance; } } - GameObject newNodeGO = CreateMapModeGameObject(node.mainBody, parent, layer, position); ShipLogAstroObject astroObject = AddShipLogAstroObject(newNodeGO, node.mainBody, greyScaleMaterial, layer); + if (node.mainBody.Config.FocalPoint != null) + { + astroObject._imageObj.GetComponent().enabled = false; + astroObject._outlineObj.GetComponent().enabled = false; + astroObject._unviewedObj.GetComponent().enabled = false; + astroObject.transform.localScale = node.lastSibling.astroObject.transform.localScale; + } node.astroObject = astroObject; if (node.lastSibling != null) ConnectNodeToLastSibling(node, greyScaleMaterial); MakeDetails(node.mainBody, newNodeGO.transform, greyScaleMaterial); } - #endregion + + private static Texture2D AutoGenerateMapModePicture(NewHorizonsBody body) + { + Texture2D texture; + + if(body.Config.Star != null) texture = Main.Instance.ModHelper.Assets.GetTexture("AssetBundle/DefaultMapModeStar.png"); + else if(body.Config.Atmosphere != null) texture = Main.Instance.ModHelper.Assets.GetTexture("AssetBundle/DefaultMapModNoAtmo.png"); + else texture = Main.Instance.ModHelper.Assets.GetTexture("AssetBundle/DefaultMapModePlanet.png"); + + var color = GetDominantPlanetColor(body); + var darkColor = new Color(color.r / 3f, color.g / 3f, color.b / 3f); + + texture = ImageUtilities.LerpGreyscaleImage(texture, color, darkColor); + + return texture; + } + + private static Color GetDominantPlanetColor(NewHorizonsBody body) + { + var starColor = body.Config?.Star?.Tint; + if (starColor != null) return starColor.ToColor(); + + var atmoColor = body.Config.Atmosphere?.AtmosphereTint; + if (body.Config.Atmosphere?.Cloud != null) return atmoColor.ToColor(); + + if (body.Config?.HeightMap?.TextureMap != null) + { + try + { + var texture = body.Mod.Assets.GetTexture(body.Config.HeightMap.TextureMap); + var landColor = ImageUtilities.GetAverageColor(texture); + if (landColor != null) return landColor; + } + catch (Exception) { } + } + + var waterColor = body.Config.Water?.Tint; + if (waterColor != null) return waterColor.ToColor(); + + var lavaColor = body.Config.Lava?.Tint; + if (lavaColor != null) return lavaColor.ToColor(); + + var sandColor = body.Config.Sand?.Tint; + if (sandColor != null) return sandColor.ToColor(); + + return Color.white; + } } -} \ No newline at end of file +} diff --git a/NewHorizons/Builder/ShipLog/RumorModeBuilder.cs b/NewHorizons/Builder/ShipLog/RumorModeBuilder.cs index 489715c8..7117fb68 100644 --- a/NewHorizons/Builder/ShipLog/RumorModeBuilder.cs +++ b/NewHorizons/Builder/ShipLog/RumorModeBuilder.cs @@ -16,10 +16,18 @@ namespace NewHorizons.Builder.ShipLog { public static class RumorModeBuilder { - private static readonly Dictionary _curiosityColors = new Dictionary(); - private static readonly Dictionary _curiosityHighlightColors = new Dictionary(); - private static readonly Dictionary _rawNameToCuriosityName = new Dictionary(); - private static readonly Dictionary _entryIdToRawName = new Dictionary(); + private static Dictionary _curiosityColors; + private static Dictionary _curiosityHighlightColors; + private static Dictionary _rawNameToCuriosityName; + private static Dictionary _entryIdToRawName; + + public static void Init() + { + _curiosityColors = new Dictionary(); + _curiosityHighlightColors = new Dictionary(); + _rawNameToCuriosityName = new Dictionary(); + _entryIdToRawName = new Dictionary(); + } public static void AddCuriosityColors(ShipLogModule.CuriosityColorInfo[] newColors) { diff --git a/NewHorizons/External/PlanetConfig.cs b/NewHorizons/External/PlanetConfig.cs index f084011f..d23a58ab 100644 --- a/NewHorizons/External/PlanetConfig.cs +++ b/NewHorizons/External/PlanetConfig.cs @@ -37,6 +37,7 @@ namespace NewHorizons.External // Always have to have a base module Base = new BaseModule(); Orbit = new OrbitModule(); + ShipLog = new ShipLogModule(); if (dict == null) return; diff --git a/NewHorizons/External/ShipLogModule.cs b/NewHorizons/External/ShipLogModule.cs index 9b3be829..dfd17be1 100644 --- a/NewHorizons/External/ShipLogModule.cs +++ b/NewHorizons/External/ShipLogModule.cs @@ -7,7 +7,7 @@ namespace NewHorizons.External public string xmlFile; public string spriteFolder; public string[] initialReveal; - public MapModeInfo mapMode; + public MapModeInfo mapMode = new MapModeInfo(); public CuriosityColorInfo[] curiosities; public EntryPositionInfo[] entryPositions; diff --git a/NewHorizons/Main.cs b/NewHorizons/Main.cs index 23bb0e27..9751e6e3 100644 --- a/NewHorizons/Main.cs +++ b/NewHorizons/Main.cs @@ -4,6 +4,7 @@ using NewHorizons.Builder.Body; using NewHorizons.Builder.General; using NewHorizons.Builder.Orbital; using NewHorizons.Builder.Props; +using NewHorizons.Builder.ShipLog; using NewHorizons.Builder.Updater; using NewHorizons.Components; using NewHorizons.External; @@ -75,7 +76,7 @@ namespace NewHorizons Logger.LogWarning("Couldn't find planets folder"); } - UnityEngine.Random.InitState((int)DateTime.Now.Ticks); + //UnityEngine.Random.InitState((int)DateTime.Now.Ticks); Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => OnSceneLoaded(SceneManager.GetActiveScene(), LoadSceneMode.Single)); } diff --git a/NewHorizons/Tools/ShipLogPatches.cs b/NewHorizons/Tools/ShipLogPatches.cs index bbb7d064..2c25b921 100644 --- a/NewHorizons/Tools/ShipLogPatches.cs +++ b/NewHorizons/Tools/ShipLogPatches.cs @@ -33,6 +33,7 @@ namespace NewHorizons.Tools public static void OnShipLogManagerAwake(ShipLogManager __instance) { + RumorModeBuilder.Init(); ShipLogHandler.Init(); Logger.Log("Beginning Ship Log Generation For: " + Main.Instance.CurrentStarSystem, Logger.LogType.Log); if (Main.Instance.CurrentStarSystem != "SolarSystem") diff --git a/NewHorizons/Utility/ImageUtilities.cs b/NewHorizons/Utility/ImageUtilities.cs index 7877e218..d66f7469 100644 --- a/NewHorizons/Utility/ImageUtilities.cs +++ b/NewHorizons/Utility/ImageUtilities.cs @@ -1,10 +1,55 @@ -using System.IO; +using System; +using System.IO; using UnityEngine; namespace NewHorizons.Utility { static class ImageUtilities { + public static Texture2D MakeOutline(Texture2D texture, Color color, int thickness) + { + var outline = new Texture2D(texture.width, texture.height, TextureFormat.ARGB32, false); + var outlinePixels = new Color[texture.width * texture.height]; + var pixels = texture.GetPixels(); + + for (int x = 0; x < texture.width; x++) + { + for (int y = 0; y < texture.height; y++) + { + var fillColor = new Color(0, 0, 0, 0); + + if(pixels[x + y * texture.width].a == 1 && CloseToTransparent(pixels, texture.width, texture.height, x, y, thickness)) + { + fillColor = color; + } + outlinePixels[x + y * texture.width] = fillColor; + } + } + + outline.SetPixels(outlinePixels); + outline.Apply(); + + return outline; + } + + private static bool CloseToTransparent(Color[] pixels, int width, int height, int x, int y, int thickness) + { + // Check nearby + var minX = Math.Max(0, x - thickness/2); + var minY = Math.Max(0, y - thickness/2); + var maxX = Math.Min(width, x + thickness/2); + var maxY = Math.Min(height, y + thickness/2); + + for (int i = minX; i < maxX; i++) + { + for (int j = minY; j < maxY; j++) + { + if (pixels[i + j * width].a < 1) return true; + } + } + return false; + } + public static Texture2D TintImage(Texture2D image, Color tint) { var pixels = image.GetPixels(); @@ -74,49 +119,22 @@ namespace NewHorizons.Utility return tex; } - // Thank you PETERSVP - public static Texture2D Scaled(Texture2D src, int width, int height, FilterMode mode = FilterMode.Trilinear) + public static Color GetAverageColor(Texture2D src) { - Rect texR = new Rect(0, 0, width, height); - _gpu_scale(src, width, height, mode); + var pixels = src.GetPixels32(); + var r = 0f; + var g = 0f; + var b = 0f; + var length = pixels.Length; + for(int i = 0; i < pixels.Length; i++) + { + var color = pixels[i]; + r += (float)color.r / length; + g += (float)color.g / length; + b += (float)color.b / length; + } - //Get rendered data back to a new texture - Texture2D result = new Texture2D(width, height, TextureFormat.ARGB32, true); - result.Resize(width, height); - result.ReadPixels(texR, 0, 0, true); - return result; - } - - public static void Scale(Texture2D tex, int width, int height, FilterMode mode = FilterMode.Trilinear) - { - Rect texR = new Rect(0, 0, width, height); - _gpu_scale(tex, width, height, mode); - - // Update new texture - tex.Resize(width, height); - tex.ReadPixels(texR, 0, 0, true); - tex.Apply(true); //Remove this if you hate us applying textures for you :) - } - - // Internal unility that renders the source texture into the RTT - the scaling method itself. - static void _gpu_scale(Texture2D src, int width, int height, FilterMode fmode) - { - //We need the source texture in VRAM because we render with it - src.filterMode = fmode; - src.Apply(true); - - //Using RTT for best quality and performance. Thanks, Unity 5 - RenderTexture rtt = new RenderTexture(width, height, 32); - - //Set the RTT in order to render to it - Graphics.SetRenderTarget(rtt); - - //Setup 2D matrix in range 0..1, so nobody needs to care about sized - GL.LoadPixelMatrix(0, 1, 1, 0); - - //Then clear & draw the texture to fill the entire RTT. - GL.Clear(true, true, new Color(0, 0, 0, 0)); - Graphics.DrawTexture(new Rect(0, 0, 1, 1), src); + return new Color(r / 255, g / 255, b / 255); } } }