diff --git a/GeometrizeVisualizer.cs b/Geometrize.cs similarity index 80% rename from GeometrizeVisualizer.cs rename to Geometrize.cs index 21ed700..28e921c 100644 --- a/GeometrizeVisualizer.cs +++ b/Geometrize.cs @@ -2,14 +2,64 @@ using System.Collections.Generic; using UnityEngine; using Newtonsoft.Json; +using UnityEditor; +using System; +using System.Net.Http; +using System.Threading.Tasks; -public class GeometrizeVisualizer : MonoBehaviour +public class Tag { - [HideInInspector] - public string versionString = "0.0.2 (CIRCLES ONLY)"; + public string Name { get; set; } +} +public class Geometrize : MonoBehaviour +{ + private static readonly HttpClient client = new HttpClient(); [HideInInspector] - public bool newVersionAvailable = false; + public string versionString = "2.20.0"; // Current version of the software + + public async Task newVersionAvailable() + { + try + { + string url = "https://api.github.com/repos/certbot/certbot/tags"; + if (!client.DefaultRequestHeaders.Contains("User-Agent")) + { + client.DefaultRequestHeaders.Add("User-Agent", "C# console program"); + } + + var response = await client.GetAsync(url); + response.EnsureSuccessStatusCode(); + + string jsonResponse = await response.Content.ReadAsStringAsync(); + var tags = JsonConvert.DeserializeObject>(jsonResponse); + string latestTag = tags[0].Name; + + Debug.Log($"Latest version from GitHub: {latestTag}"); + + return CompareVersions(latestTag, versionString); + } + catch (Exception ex) + { + Debug.LogError($"Error fetching latest version tag: {ex.Message}"); + return false; + } + } + + private bool CompareVersions(string fetchedVersion, string currentVersion) + { + // Removing 'v' prefix commonly used in version tags if present + fetchedVersion = fetchedVersion.TrimStart('v'); + currentVersion = currentVersion.TrimStart('v'); + + // Use System.Version to compare versions correctly + if (Version.TryParse(fetchedVersion, out Version fetched) && Version.TryParse(currentVersion, out Version current)) + { + return fetched > current; + } + Debug.LogError("Failed to parse versions for comparison."); + return false; + } // Input json file [Header("Input")] public TextAsset jsonFile; @@ -30,13 +80,12 @@ public class GeometrizeVisualizer : MonoBehaviour [HideInInspector] public GameObject spherePrefab; - public void Convert() + public void convert() { + cubePrefab = AssetDatabase.LoadAssetAtPath("Assets/Resources/Blocks/Primitives/Cube.prefab"); + spherePrefab = AssetDatabase.LoadAssetAtPath("Assets/Resources/Blocks/Primitives/Sphere.prefab"); - if (autoClear) - { - clearChildren(); - } + if (autoClear) clearChildren(); //This is an example JSON file /* @@ -71,8 +120,8 @@ public void Convert() return; } - var whichShape = 10; //inital distance from the canvas so that no clipping occurs - // Loop through each shape + var whichShape = 10; + foreach (var shape in shapeData.shapes) { // Now you can access shape properties as expected @@ -115,7 +164,7 @@ public void Convert() float globalSizeMultiplier; //the value by which to multiply so that the objects fit on the canvases new size - void createCanvas(List data, List color) + public void createCanvas(List data, List color) { //the canvas will have the height of 3. so we need to calculate the width and set the globalSizeMultiplier globalSizeMultiplier = (size * 3f) / data[3]; //when the height is 300 (pixels) the multiplier will be 0.01 @@ -138,7 +187,7 @@ void createCanvas(List data, List color) canvas = cube.transform; } - void createCube(List data, List color, int position) + private void createCube(List data, List color, int position) { // Create a new cube GameObject cube = Instantiate(cubePrefab, transform); @@ -163,7 +212,7 @@ void createCube(List data, List color, int position) cube.GetComponent().Collidable = collidable; } - void createRotatedCube(List data, List color, int position) + private void createRotatedCube(List data, List color, int position) { // Create a new cube GameObject cube = Instantiate(cubePrefab, transform); @@ -191,7 +240,7 @@ void createRotatedCube(List data, List color, int position) cube.GetComponent().Collidable = collidable; } - void createEllipse(List data, List color, int position) + private void createEllipse(List data, List color, int position) { // Create a new sphere GameObject sphere = Instantiate(spherePrefab, transform); @@ -209,7 +258,7 @@ void createEllipse(List data, List color, int position) sphere.GetComponent().Collidable = collidable; } - void createRotatedEllipse(List data, List color, int position) + private void createRotatedEllipse(List data, List color, int position) { // Create a new sphere GameObject sphere = Instantiate(spherePrefab, transform); @@ -227,7 +276,7 @@ void createRotatedEllipse(List data, List color, int position) sphere.GetComponent().Collidable = collidable; } - void createCircle(List data, List color, int position) + private void createCircle(List data, List color, int position) { // Create a new sphere GameObject sphere = Instantiate(spherePrefab, transform); @@ -263,13 +312,13 @@ public void clearChildren() } [System.Serializable] - public class ShapeData + private class ShapeData { public List shapes; } [System.Serializable] - public struct Shape + private struct Shape { public int type; public List data; diff --git a/GeometrizeVisualizer.cs.meta b/GeometrizeVisualizer.cs.meta deleted file mode 100644 index ad797e3..0000000 --- a/GeometrizeVisualizer.cs.meta +++ /dev/null @@ -1,14 +0,0 @@ -fileFormatVersion: 2 -guid: ebad2f610ab72094ebeea22add872f8d -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: - - jsonFile: {instanceID: 0} - - cubePrefab: {fileID: 254159507964864611, guid: cdaa42156eb4d754dba1641e72cb46f0, type: 3} - - spherePrefab: {fileID: 2978017100676394072, guid: 9ae7892a030f6874ebfc5a8bbdc3e4cd, type: 3} - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Misc/Scripts/FailedProjects.meta b/Misc/Scripts/FailedProjects.meta deleted file mode 100644 index e294e23..0000000 --- a/Misc/Scripts/FailedProjects.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: c509d2a482342924eba970bf097f66fb -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Misc/Scripts/FailedProjects/Geometrize.cs b/Misc/Scripts/FailedProjects/Geometrize.cs deleted file mode 100644 index da174a2..0000000 --- a/Misc/Scripts/FailedProjects/Geometrize.cs +++ /dev/null @@ -1,382 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using UnityEngine; -using UnityEditor; -using System; -using System.Threading.Tasks; -using System.Numerics; - -public class Geometrize : MonoBehaviour -{ - [HideInInspector] - public string versionString = "0.0.1"; - [HideInInspector] - public bool newVersionAvailable = false; - - [Header("Input")] - public Texture2D inputImage; // Assign the input image in the Inspector - - [Space(10)] - [Header("Settings")] - public int primitivesPerGeneration = 20; - public int generations = 10; - - - - [Header("Allowed primitives")] - public bool useCubes = true; - public GameObject cubePrefab; - public bool useSpheres = true; - public GameObject spherePrefab; - public bool useCylinders = true; - public GameObject cylinderPrefab; - public bool useCapsules = true; - public GameObject capsulePrefab; - // Start is called before the first frame update - void Start() - { - - } - - // Update is called once per frame - void Update() - { - - } - - private Color[] pixelsInInputImage; - private int pixelsInInputImageLength; - private float[] pixelsInInputImageGrayScale; - private int inputImageWidth; - private int inputImageHeight; - private Color averageColorOfInputImage; - - public void Generate() - { - - //Get the input image and geometrize it - //Geomentrization is the process of turning an image into a set of primitives - //The primitives are then used to recreate the image - //This is done by comparing the input image with the primitives and finding the best match - //The best match is then used to recreate the image - //This process is repeated until the image is fully recreated or the user stops the process - - //Fetch intial data that only needs to be fetched once - //Data about the input image - pixelsInInputImage = inputImage.GetPixels(); - pixelsInInputImageLength = pixelsInInputImage.Length; - - pixelsInInputImageGrayScale = new float[pixelsInInputImageLength]; - for (int i = 0; i < pixelsInInputImageLength; i++) - { - pixelsInInputImageGrayScale[i] = pixelsInInputImage[i].grayscale; - } - - inputImageWidth = inputImage.width; - inputImageHeight = inputImage.height; - - averageColorOfInputImage = new Color(0f, 0f, 0f, 0f); - for (int i = 0; i < pixelsInInputImageLength; i++) - { - averageColorOfInputImage += pixelsInInputImage[i]; - } - averageColorOfInputImage /= pixelsInInputImageLength; - - clearChildren(); - - PrepareRatingVariables(); - - DrawImage(inputImage); - } - - - private void DrawImage(Texture2D image) - { - //Create 100 version of the input image - //Each version will have 1 randomly shaped, placed and colored primitives - //The best version will be used to recreate the input image - float newWidth = image.width / image.height; - - //Create a canvas to draw the image on - GameObject canvas = Instantiate(cubePrefab); - canvas.transform.parent = transform; - - //Set the canvas's position, rotation and scale - canvas.transform.localPosition = UnityEngine.Vector3.zero; - canvas.transform.localScale = new UnityEngine.Vector3(newWidth, 1f, 0.01f); - - //Set the canvas's color - canvas.GetComponent().Color = averageColorOfInputImage; - canvas.GetComponent().material.color = averageColorOfInputImage; - - - //Create a camera right in front of the canvas - GameObject camera = new GameObject("Camera"); - camera.transform.parent = canvas.transform; - camera.transform.localPosition = new UnityEngine.Vector3(0f, 0f, 80f); - camera.transform.localRotation = UnityEngine.Quaternion.Euler(0f, -180f, 0f); - - //Attach a camera component to the camera - camera.AddComponent(); - camera.GetComponent().orthographic = true; - camera.GetComponent().aspect = newWidth; - camera.GetComponent().orthographicSize = 0.5f; - - //Create a new parent object for the primitives - Transform parent = transform; - - var watchALL = new System.Diagnostics.Stopwatch(); - - //Create a list of random numbers - int[] randomNum = new int[generations * primitivesPerGeneration]; - - List randomNumbersThatAreAllowed = new List(); - if (useCubes) randomNumbersThatAreAllowed.Add(0); - if (useSpheres) randomNumbersThatAreAllowed.Add(1); - if (useCylinders) randomNumbersThatAreAllowed.Add(2); - if (useCapsules) randomNumbersThatAreAllowed.Add(3); - - for (int i = 0; i < randomNum.Length; i++) - { - randomNum[i] = randomNumbersThatAreAllowed[UnityEngine.Random.Range(0, randomNumbersThatAreAllowed.Count)]; - } - - watchALL.Start(); - for (int g = 0; g < generations; g++) - { - GameObject generation = new GameObject("Generation " + g); - generation.transform.parent = parent.transform; - generation.transform.localPosition = UnityEngine.Vector3.zero; - - //create a list of all the versions - List versions = new List(); - List ratings = new List(); - - for (int i = 0; i < primitivesPerGeneration; i++) - { - var watchOne = new System.Diagnostics.Stopwatch(); - watchOne.Start(); - - //Create a new child object for the current version - GameObject version = new GameObject("Version " + i); - version.transform.parent = generation.transform; - version.transform.localPosition = UnityEngine.Vector3.zero; - - //Add the version to the list of versions - versions.Add(version); - - GameObject primitive = null; - - //Create a primitive based on its random number in the list of random numbers - switch (randomNum[(g * primitivesPerGeneration) + i]) - { - case 0: - primitive = Instantiate(cubePrefab); - break; - case 1: - primitive = Instantiate(spherePrefab); - break; - case 2: - primitive = Instantiate(cylinderPrefab); - break; - case 3: - primitive = Instantiate(capsulePrefab); - break; - } - - primitive.transform.parent = version.transform; - - //Set the primitive's position, rotation and scale - primitive.transform.localPosition = new UnityEngine.Vector3(UnityEngine.Random.Range(-(newWidth / 2f), newWidth / 2f), UnityEngine.Random.Range(-0.5f, 0.5f), 0.01f + (g * 0.001f)); - primitive.transform.rotation = UnityEngine.Quaternion.Euler(0, 0, UnityEngine.Random.Range(0f, 360f)); - primitive.transform.localScale = new UnityEngine.Vector3(UnityEngine.Random.Range(0.01f, 0.5f), UnityEngine.Random.Range(0.01f, 0.5f), 0.001f); - - - //Set the primitive's color - Color color = image.GetPixel(UnityEngine.Random.Range(0, image.width), UnityEngine.Random.Range(0, image.height)); - color.a = 0.5f; - primitive.GetComponent().Color = color; - primitive.GetComponent().material.color = color; - primitive.GetComponent().material.SetFloat("_Mode", 3); - primitive.GetComponent().material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha); - primitive.GetComponent().material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); - primitive.GetComponent().material.SetInt("_ZWrite", 0); - primitive.GetComponent().material.DisableKeyword("_ALPHATEST_ON"); - primitive.GetComponent().material.EnableKeyword("_ALPHABLEND_ON"); - primitive.GetComponent().material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); - primitive.GetComponent().material.renderQueue = 3000; - - //Get a rating for the current version - float rating = GetRating(image, camera.GetComponent()); - - //Add the rating to the list of ratings - ratings.Add(rating); - - //Make the primitive invisible - primitive.GetComponent().enabled = false; - - watchOne.Stop(); - //print("Time for one version: " + watchOne.ElapsedMilliseconds + "ms"); - } - - - //Find the best version - float bestRating = 0f; - float bestRatingPlace = 0f; - GameObject previousBestGameobject = new GameObject(); - for (int i = 0; i < ratings.Count; i++) - { - - if (ratings[i] > bestRating) - { - bestRating = ratings[i]; - bestRatingPlace = i; - - //Destroy previous best version - DestroyImmediate(previousBestGameobject); - - //Become the "previous best version" - previousBestGameobject = versions[(int)bestRatingPlace].transform.gameObject; - } - else - { - //Destroy the current version - DestroyImmediate(versions[i].transform.gameObject); - } - } - print("Best rating: " + bestRatingPlace + " with a rating of " + bestRating); - //Make the best version visible again - versions[(int)bestRatingPlace].transform.GetChild(0).GetComponent().enabled = true; - } - watchALL.Stop(); - - print("Total time: " + watchALL.ElapsedMilliseconds + "ms"); - } - - //Variables for the GetRating function that should only be allocated once - //we know the dimensions of the rendered image will always be the same so we can allocate the arrays once - - private RenderTexture renderTexture; - private Texture2D renderedImage; - private Rect defaultRect; - //private float rating = 0f; - private Color[] pixelsRenderedImage; - private int vectorSize = Vector.Count; - private float[] imageValues; - private float[] renderedValues; - private float maxDifference; - private float similarity; - private Vector vectorImage; - private Vector vectorRendered; - - - private void PrepareRatingVariables() - { - //Create a new render texture - renderTexture = new RenderTexture(inputImageWidth, inputImageHeight, 24); - renderTexture.Create(); - - //rect - defaultRect = new Rect(0, 0, inputImageWidth, inputImageHeight); - - //Create a new texture2D - renderedImage = new Texture2D(inputImageWidth, inputImageHeight, TextureFormat.RGB24, false); - - pixelsRenderedImage = new Color[pixelsInInputImageLength]; - - imageValues = new float[vectorSize]; - renderedValues = new float[vectorSize]; - - vectorImage = new Vector(vectorSize); - vectorRendered = new Vector(vectorSize); - } - - - private float GetRating(Texture2D image, Camera camera) - { - var stopwatch = new System.Diagnostics.Stopwatch(); - var compare = new System.Diagnostics.Stopwatch(); - stopwatch.Start(); - - //Render the image - camera.targetTexture = renderTexture; - camera.Render(); - - //Read the pixels from the image - RenderTexture.active = renderTexture; - renderedImage.ReadPixels(defaultRect, 0, 0); - renderedImage.Apply(); - - - compare.Start(); - //Compare the pixels from the input image and the rendered image - pixelsRenderedImage = renderedImage.GetPixels(); //3ms - - - - float rating = 0f; - - // Process pixel values in vectors of size vectorSize (e.g., 4 on typical platforms) - for (int i = 0; i < pixelsInInputImageLength; i += vectorSize) - { - - for (int j = 0; j < vectorSize; j++) - { - imageValues[j] = pixelsInInputImage[i + j].grayscale; - renderedValues[j] = pixelsRenderedImage[i + j].grayscale; - } - - - vectorImage = new Vector(imageValues); - vectorRendered = new Vector(renderedValues); - - var difference = Vector.Abs(Vector.Subtract(vectorImage, vectorRendered)); - rating += Vector.Dot(difference, Vector.One); - - } - - // Handle any remaining pixels that are not processed in vectors - for (int i = pixelsInInputImageLength - pixelsInInputImageLength % vectorSize; i < pixelsInInputImageLength; i++) - { - rating += Math.Abs(pixelsInInputImageGrayScale[i] - pixelsRenderedImage[i].grayscale); - } - - // Normalize the rating to a similarity value between 0 and 1 - maxDifference = pixelsInInputImageLength * 255f; - similarity = 1f - (rating / maxDifference); - compare.Stop(); - - - //Return the rating - //print("Rating: " + rating); - //print("Similarity: " + similarity); - stopwatch.Stop(); - - //print("Time for one compare: " + compare.ElapsedMilliseconds + "ms"); - //print("Time for one rating: " + stopwatch.ElapsedMilliseconds + "ms"); - return similarity; - } - - - - - - - public void clearChildren() - { - Transform parentTransform = transform; - // Copy the children into an array - Transform[] children = new Transform[parentTransform.childCount]; - for (int i = 0; i < parentTransform.childCount; i++) - { - children[i] = parentTransform.GetChild(i); - } - - - // Destroy the children from the copied array - foreach (Transform child in children) - { - DestroyImmediate(child.gameObject); - } - } -} diff --git a/Misc/Scripts/FailedProjects/Geometrize.cs.meta b/Misc/Scripts/FailedProjects/Geometrize.cs.meta deleted file mode 100644 index f195eb4..0000000 --- a/Misc/Scripts/FailedProjects/Geometrize.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 7a1f8128fdb6af64ea245e9d790f475a -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Misc/Scripts/FailedProjects/GeometrizeEditor.cs b/Misc/Scripts/FailedProjects/GeometrizeEditor.cs deleted file mode 100644 index 45a963b..0000000 --- a/Misc/Scripts/FailedProjects/GeometrizeEditor.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using UnityEngine; -using UnityEditor; - -[CustomEditor(typeof(Geometrize))] - -public class GeometrizeEditor : Editor -{ - public override void OnInspectorGUI() - { - Geometrize geo = (Geometrize)target; - - //Version info in BOLD and blue text - GUIStyle style = new GUIStyle(); - style.richText = true; - style.fontStyle = FontStyle.Bold; - style.normal.textColor = Color.yellow; - GUILayout.Label("Geometrizer - v" + geo.versionString + "", style); - - //If a new version is available, show a button to open the download page - if (geo.newVersionAvailable) - { - if (GUILayout.Button("Download new version")) - { - Application.OpenURL("https://github.com/AlexInABox/mer-mosaic-generator/releases/latest"); - } - } - - DrawDefaultInspector(); - - - if (GUILayout.Button("Generate Geometry")) - { - geo.Generate(); - } - - if (GUILayout.Button("Clear Geometry")) - { - geo.clearChildren(); - } - } -} diff --git a/Misc/Scripts/FailedProjects/GeometrizeEditor.cs.meta b/Misc/Scripts/FailedProjects/GeometrizeEditor.cs.meta deleted file mode 100644 index f5f1c80..0000000 --- a/Misc/Scripts/FailedProjects/GeometrizeEditor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 612d050774a018c45958dd03403cdd2b -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Misc/Scripts/GeometrizeVisualizerEditor.cs b/Misc/Scripts/GeometrizeEditor.cs similarity index 55% rename from Misc/Scripts/GeometrizeVisualizerEditor.cs rename to Misc/Scripts/GeometrizeEditor.cs index 499a0b7..b6a74dd 100644 --- a/Misc/Scripts/GeometrizeVisualizerEditor.cs +++ b/Misc/Scripts/GeometrizeEditor.cs @@ -2,24 +2,34 @@ using System.Collections.Generic; using UnityEngine; using UnityEditor; +using System.Threading.Tasks; -[CustomEditor(typeof(GeometrizeVisualizer))] +[CustomEditor(typeof(Geometrize))] -public class GeometrizeVisualizerEditor : Editor +public class GeometrizeEditor : Editor { + private bool? isNewVersionAvailable = null; + + void OnEnable() + { + // Start checking for a new version + var task = (target as Geometrize)?.newVersionAvailable(); + task.ContinueWith(t => isNewVersionAvailable = t.Result, TaskScheduler.FromCurrentSynchronizationContext()); + } + public override void OnInspectorGUI() { - GeometrizeVisualizer geo = (GeometrizeVisualizer)target; + Geometrize geo = (Geometrize)target; //Version info in BOLD and blue text GUIStyle style = new GUIStyle(); style.richText = true; style.fontStyle = FontStyle.Bold; - style.normal.textColor = Color.yellow; - GUILayout.Label("GeometrizeVisualizer - v" + geo.versionString + "", style); + style.normal.textColor = new Color(0.26f, 0.62f, 0.28f, 1f); + GUILayout.Label("Geometrize (v" + geo.versionString + ")", style); //If a new version is available, show a button to open the download page - if (geo.newVersionAvailable) + if (isNewVersionAvailable.HasValue && isNewVersionAvailable.Value) { if (GUILayout.Button("Download new version")) { @@ -32,7 +42,7 @@ public override void OnInspectorGUI() if (GUILayout.Button("Convert Geometry")) { - geo.Convert(); + geo.convert(); } if (GUILayout.Button("Clear Geometry")) diff --git a/Misc/Scripts/GeometrizeVisualizerEditor.cs.meta b/Misc/Scripts/GeometrizeVisualizerEditor.cs.meta deleted file mode 100644 index 23ead26..0000000 --- a/Misc/Scripts/GeometrizeVisualizerEditor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: cc1ed13c35a8e5746b70874360243424 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: