Search Unity

  1. Unity 2018.3 is now released.
    Dismiss Notice
  2. The Unity Pro & Visual Studio Professional Bundle gives you the tools you need to develop faster & collaborate more efficiently. Learn more.
    Dismiss Notice
  3. Want more efficiency in your development work? Sign up to receive weekly tech and creative know-how from Unity experts.
    Dismiss Notice
  4. Build games and experiences that can load instantly and without install. Explore the Project Tiny Preview today!
    Dismiss Notice
  5. Want to provide direct feedback to the Unity team? Join the Unity Advisory Panel.
    Dismiss Notice
  6. Improve your Unity skills with a certified instructor in a private, interactive classroom. Watch the overview now.
    Dismiss Notice

Map Magic World Generator - a node based procedural and infinite game map tool

Discussion in 'Assets and Asset Store' started by Wright, Mar 10, 2016.

  1. Wright

    Wright

    Joined:
    Feb 26, 2013
    Posts:
    1,442
    Email me your order number and I will provide a GitLab access to beta for your email. It's kinda not automated.

    As far as I can see nothing happens when you press "Show Editor" button - is it really so or you just using a second display?

    I can see what I can do, but don't expect it soon - MM2 is in priority for me.
     
  2. Funkeys

    Funkeys

    Joined:
    Apr 16, 2017
    Posts:
    64
    Hi, tried it with english naumber and currency settings and it works fine. First changed just the number settings, and it did not do it. But having both changed to English Int. does the job :)!
     
  3. Harekelas

    Harekelas

    Joined:
    Feb 3, 2015
    Posts:
    669
    Hi Denis, can you refresh the discord invite or set the invite to be permenant? Really like to join the chat :)
     
  4. Stardog

    Stardog

    Joined:
    Jun 28, 2010
    Posts:
    1,140
    It didn't capture, but it was just an empty graph.
     
  5. Wright

    Wright

    Joined:
    Feb 26, 2013
    Posts:
    1,442
    Sure: discord link.

    So... is it working after all? Do I have to do something?

    Tried a combination of .net4 and comm symbol. Still can't reproduce, but will try to dig further. Will try to use the exact Unity version and Burst compiler.

    BTW MapMagic is on sale now! A good chance to take it for the half price!
     
  6. Kris392001

    Kris392001

    Joined:
    May 8, 2018
    Posts:
    62
    Hi. Is anyone successfully using Microsplat with Map Magic currently? I can get it to work in a round about way but am looking for a more efficient solution. I have the script that Syncs each new terrain and have the Microsplat component propagating to each generated terrain, no problem.

    My question is with the textures. I populate the Microsplat texture array with my PBR textures and Sync that to a locked terrain. I was under the assumption that the MM generic Texture node populated from the textures assigned to the terrain by MS but that doesn't seem to be the case. Do I need to also assign the MS material as a custom material in the MM component? Should I be using the Custom Shader node like Megasplat? Does MM Texture node read the textures from the terrain? Any help would be much appreciated.
     
    Last edited: Nov 27, 2018
  7. protopop

    protopop

    Joined:
    May 19, 2009
    Posts:
    876
    I dont know how to link directly to the post, but there is a script that syncs Microsplat to Mapmagic on this page: https://forum.unity.com/threads/fre...ding-system-for-unity-terrains.487458/page-19
     
  8. Kris392001

    Kris392001

    Joined:
    May 8, 2018
    Posts:
    62
    Thanks for the reply. I have the script and that seems to be working fine. It was more syncing the Microsplat texture array with the Map Magic Texture node.
     
  9. Wright

    Wright

    Joined:
    Feb 26, 2013
    Posts:
    1,442
    Can't promise it soon, but I will look into MicroSplat integration since there's pretty much demand for it.
     
  10. Kris392001

    Kris392001

    Joined:
    May 8, 2018
    Posts:
    62
    Thanks, much appreciated. :)
     
  11. malkere

    malkere

    Joined:
    Dec 6, 2013
    Posts:
    949
    I use mircosplat just fine. It's been a while, but I think one of the changes I had to make was to force textures to be the same and in the same order for every terrain. If I remember correctly MM cuts out any textures that aren't actually showing up on a terrain, for example if there are no beaches it won't both to add the sand texture to it. This confuses MicroSplat though as it wants them to be the same at all times.

    I commented out these lines at around 500 in OutputGenerators.cs:
    Code (CSharp):
    1.             /*
    2.             //optimizing matrices list if they are not used
    3.             for (int i = matrices.Count - 1; i >= 0; i--)
    4.                 if (opacities[i] < 0.001f || matrices[i].IsEmpty() || (biomeMasks[i] != null && biomeMasks[i].IsEmpty()))
    5.                 { prototypesList.RemoveAt(i); opacities.RemoveAt(i); matrices.RemoveAt(i); biomeMasks.RemoveAt(i); }
    6.             */
    That's really just to ensure that the right number is on there though and that they are in the right order. I don't think MicroSplat actual uses the textures on the terrain, nor from the MM output textures. Setting up the MM output node is step 1, but it's just for design purposes. Step 2 is to import to MS from a terrain to create a prototype or whatever they are called. Then you only need to assign that to your terrains in runtime with the script. I don't think it actually looks at the textures, it just assumes an order for example 1-4. So long as MM isn't mixing up that order and your MS assignment script is working properly it should work.
     
  12. ftejada

    ftejada

    Joined:
    Jul 1, 2015
    Posts:
    496
    Hi @Wright !!!
    The Integration with MegaSplat was already?

    Regards
     
  13. Kris392001

    Kris392001

    Joined:
    May 8, 2018
    Posts:
    62
    Thanks for the reply. That's pretty much the workflow I have in place at the moment. It gets hard to maintain, especially if you have multiple terrains, multiple biomes and 32 textures and you're prototyping with a lot of changes. Looking forward to a seamless integration. :)

    @Wright On that, it would be nice to be able to accommodate the Texture Clusters, Advanced Details and Global Texturing modules in the integration in some way. I may be asking too much. ;)
     
  14. Hazkin

    Hazkin

    Joined:
    Sep 11, 2012
    Posts:
    2
    I had the same issue. This will reproduce only on .Net 4.x and non-US locales, like German, Ukrainian etc. and I make some solution to fix that, maybe this will help someone.

    Main wail in a coma separator

    *EDIT: Source code taken from MM 1.9.4

    CustomSerialization:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using System.Reflection;
    5. using System.Xml.Serialization;
    6. using System.IO;
    7. using System;
    8. using System.Globalization;
    9.  
    10. namespace MapMagic
    11. {
    12.  
    13.     public static class CustomSerialization
    14.     {
    15.         public const char Separator = ';';
    16.         public interface IStruct
    17.         {
    18.             string Encode ();
    19.             void Decode (string[] lineMembers);
    20.         }
    21.  
    22.         public interface IStructLink
    23.         {
    24.             string Encode (Func<object,int> writeClass);
    25.             void Decode (string[] lineMembers, System.Func<int,object> readClass);
    26.         }
    27.  
    28.         public static Type GetStandardAssembliesType (string s)
    29.         {
    30.             if (s.StartsWith("Plugins.")) s = s.Replace("Plugins", typeof(CustomSerialization).Namespace);
    31.             Type type = Type.GetType(s);
    32.             if (type == null) type = Type.GetType(s + ", UnityEngine");
    33.             if (type == null) type = Type.GetType(s + ", Assembly-CSharp-Editor"); //trying to load from editor assembly
    34.             if (type == null) type = Type.GetType(s + ", Assembly-CSharp"); //or from non-editor
    35.  
    36.             if (type == null) //lastly trying to load type from plugins
    37.             {
    38.                 if (s.StartsWith("MapMagic")) s = s.Replace("MapMagic", "Plugins");
    39.                 if (s.StartsWith("Voxeland")) s = s.Replace("Voxeland", "Plugins");
    40.              
    41.                 type = Type.GetType(s);
    42.                 if (type == null) type = Type.GetType(s + ", UnityEngine");
    43.                 if (type == null) type = Type.GetType(s + ", Assembly-CSharp-Editor"); //trying to load from editor assembly
    44.                 if (type == null) type = Type.GetType(s + ", Assembly-CSharp"); //or from non-editor
    45.             }
    46.  
    47.             return type;
    48.         }
    49.  
    50.  
    51.         private struct Value
    52.         {
    53.             public string name;
    54.             public Type type;
    55.             public object obj;
    56.         }
    57.  
    58.         private static IEnumerable<Value> Values (object obj)
    59.         {
    60.             Type objType = obj.GetType();
    61.  
    62.             if (objType.IsArray)
    63.             {
    64.                 Type elementType = objType.GetElementType();
    65.                 Array array = (Array)obj;
    66.  
    67.                 //simple array
    68.                 if (elementType.IsPrimitive)
    69.                     yield return new Value() { name="items", type=objType, obj=array };
    70.  
    71.                 //class array
    72.         //        else if (elementType.IsClass && !elementType.IsValueType)
    73.         //            yield return new Value() { name="links", type=objType, obj=array, classArray=true };
    74.              
    75.                 //other arrays
    76.                 else
    77.                     for (int i=0; i<array.Length; i++) yield return new Value() { name="item"+i, type=elementType, obj=array.GetValue(i) };
    78.             }
    79.  
    80.             else if (objType.IsSubclassOf(typeof(UnityEngine.Object)))
    81.             {
    82.                 yield return new Value { name="Object", type=objType, obj=obj };
    83.             }
    84.  
    85.             else
    86.             {
    87.                 foreach (FieldInfo field in objType.UsableFields(includeStatic:true))
    88.                     yield return new Value { name=field.Name, type=field.FieldType, obj=field.GetValue(obj) };
    89.  
    90.                 foreach (PropertyInfo prop in objType.UsableProperties())
    91.                     yield return new Value { name=prop.Name, type=prop.PropertyType, obj=prop.GetValue(obj,null) };
    92.             }
    93.         }
    94.  
    95.  
    96.         public static int WriteClass (object obj, List<string> classes, List<UnityEngine.Object> objects, List<float> floats, List<object> references)
    97.         {
    98.             //cheking if this object was already saved
    99.             if (references.Contains(obj)) return references.IndexOf(obj);
    100.  
    101.             //obj type
    102.             System.Type objType = obj.GetType();
    103.             System.Type elementType = objType.IsArray? objType.GetElementType() : null;
    104.             string objTypeName = objType.ToString();
    105.  
    106.             //reserving a place in array
    107.             int slotNum = classes.Count;
    108.             classes.Add(null);
    109.  
    110.             //adding to references
    111.             for (int i=references.Count; i<classes.Count; i++) references.Add(null); //references count should be equal to classes length
    112.             references[slotNum] = obj;
    113.      
    114.             //writing
    115.             StringWriter writer = new StringWriter(CultureInfo.InvariantCulture);
    116.  
    117.             //header
    118.             writer.Write("<" + objTypeName);
    119.             if (objType.IsArray) writer.Write(" length=" + ((Array)obj).Length);
    120.             writer.WriteLine(">");
    121.  
    122.             //values
    123.             foreach (Value val in Values(obj))
    124.             {
    125.                 //primitive
    126.                 if (val.type.IsPrimitive)
    127.                 {
    128.                     if (val.type == typeof(float))
    129.                     {
    130.                         var f = (float)val.obj;
    131.                         var fValue = InvariantFloat(f);
    132.                         var line = string.Format("\t<{0} type={1} value={2}/>" ,val.name, val.type, fValue);
    133.                         writer.WriteLine(line);
    134.                     }
    135.                     else if (val.type == typeof(double))
    136.                     {
    137.                         var d = (double)val.obj;
    138.                         var dValue = InvariantDouble(d);
    139.                         var line = string.Format("\t<{0} type={1} value={2}/>", val.name, val.type, dValue);
    140.                         writer.WriteLine(line);
    141.                     }
    142.                     else
    143.                     {
    144.                         writer.WriteLine("\t<" + val.name + " type=" + val.type + " value=" + val.obj + "/>");
    145.                     }
    146.                 }
    147.  
    148.                 //null
    149.                 else if (val.obj == null)
    150.                     writer.WriteLine("\t<" + val.name + " type=" + val.type + " null/>");
    151.  
    152.                 //string
    153.                 else if (val.type==typeof(string))
    154.                 {
    155.                     string str = (string)val.obj;
    156.                     str = str.Replace("\n", "\\n");
    157.                     str = str.Replace(" ", "\\_");
    158.                     writer.WriteLine("\t<" + val.name + " type=" + val.type + " value=" + str + "/>"); //same as primitive, but after null
    159.                 }
    160.  
    161.                 //custom struct
    162.                 else if (typeof(IStruct).IsAssignableFrom(val.type))
    163.                     writer.WriteLine("\t<" + val.name + " type=" + val.type + " " + ((IStruct)val.obj).Encode() + "/>");
    164.  
    165.                 //custom struct with links
    166.                 else if (typeof(IStructLink).IsAssignableFrom(val.type))
    167.                 {
    168.                     Func<object, int> getLinkFn = delegate(object linkObj) { return WriteClass(linkObj, classes, objects, floats, references); };
    169.                     writer.WriteLine("\t<" + val.name + " type=" + val.type + " " + ((IStructLink)val.obj).Encode( getLinkFn ) + "/>");
    170.                 }
    171.  
    172.                 //float array
    173.                 else if (objType == typeof(float[])) //note that obj should be used here, not val.obj
    174.                 {
    175.                     float[] array = (float[])obj;
    176.                     writer.WriteLine("\t<items type=" + val.type + " start=" + floats.Count + " length=" + array.Length + "/>");
    177.                     floats.AddRange(array);
    178.                 }
    179.  
    180.                 //other primitive array
    181.                 else if (objType.IsArray && elementType.IsPrimitive)
    182.                 {
    183.                     writer.Write("\t<items type=" + val.type + " values=");
    184.  
    185.                     Array array = (Array)obj;
    186.                     for (int i=0; i<array.Length; i++)
    187.                     {
    188.                         writer.Write(array.GetValue(i));
    189.                         if (i!=array.Length-1) writer.Write(Separator);
    190.                     }
    191.  
    192.                     writer.WriteLine("/>");
    193.                 }
    194.  
    195.                 //class array
    196.                 /*else if (val.classArray)
    197.                 {
    198.                     writer.Write( string.Format("\t<items type=" +  + " links=", val.type) );
    199.  
    200.                     Array array = (Array)obj;
    201.                     for (int i=0; i<array.Length; i++)
    202.                     {
    203.                         writer.Write( WriteClass(val.obj, ref classes, ref objects, references) );
    204.                         if (i!=array.Length-1) writer.Write(Separator);
    205.                     }
    206.  
    207.                     writer.Write("/>\n");
    208.                 }*///doesnt deal with null and not tested properly.
    209.  
    210.                 //unity object
    211.                 else if (val.type.IsSubclassOf(typeof(UnityEngine.Object)))
    212.                 {
    213.                     //not a big deal if the object will be added to array twice
    214.                     writer.WriteLine("\t<" +  val.name + " type=" + val.type + " object=" + objects.Count + "/>");
    215.                     objects.Add((UnityEngine.Object)val.obj);
    216.                 }
    217.  
    218.                 //null
    219.                 else if (val.obj == null)
    220.                     writer.WriteLine("\t<" + val.name + " type=" + val.type + " link=-1/>");
    221.  
    222.                 //class
    223.                 else if (val.type.IsClass && !val.type.IsValueType)
    224.                     writer.WriteLine("\t<" + val.name + " type=" + val.type + " link=" + WriteClass(val.obj, classes, objects, floats, references) + "/>");
    225.  
    226.                 //Vector2
    227.                 else if (val.type == typeof(Vector2))
    228.                 {
    229.                     Vector2 v2 = (Vector2)val.obj;
    230.                     var x = InvariantFloat(v2.x);
    231.                     var y = InvariantFloat(v2.y);
    232.                     var line = string.Format("\t<{0} type={1} x={2} y={3}/>",val.name, val.type, x, y);
    233.                     writer.WriteLine(line);
    234.  
    235.                     //writer.WriteLine("\t<" + val.name + " type=" + val.type + " x=" + v2.x + " y=" + v2.y + "/>");
    236.                     //writer.WriteLine("\t<" + val.name + " type=" + val.type + " val=" + floats.Count + "/>");
    237.                     //floats.Add(v2.x); floats.Add(v2.y);
    238.                 }
    239.  
    240.                 //Vector3
    241.                 else if (val.type == typeof(Vector3))
    242.                 {
    243.                     Vector3 v3 = (Vector3)val.obj;
    244.                     var x = InvariantFloat(v3.x);
    245.                     var y = InvariantFloat(v3.y);
    246.                     var z = InvariantFloat(v3.z);
    247.                     var line = string.Format("\t<{0} type={1} x={2} y={3} z={4}/>",val.name, val.type, x,y,z);
    248.                     writer.WriteLine(line);
    249.  
    250.                     //writer.WriteLine("\t<" + val.name + " type=" + val.type + " x=" + v3.x + " y=" + v3.y + " z=" + v3.z + "/>");
    251.                     //writer.WriteLine("\t<" + val.name + " type=" + val.type + " val=" + floats.Count + "/>");
    252.                     //floats.Add(v3.x); floats.Add(v3.y); floats.Add(v3.z);
    253.                 }
    254.  
    255.                 //Rect
    256.                 else if (val.type == typeof(Rect))
    257.                 {
    258.                     Rect rect = (Rect)val.obj;
    259.                  
    260.                     var x = InvariantFloat(rect.x);
    261.                     var y = InvariantFloat(rect.y);
    262.                     var width = InvariantFloat(rect.width);
    263.                     var height = InvariantFloat(rect.height);
    264.  
    265.                     var line = string.Format("\t<{0} type={1} x={2} y={3} width={4} height={5}/>",val.name, val.type, x, y, width, height);
    266.                     writer.WriteLine(line);
    267.                     //("\t<" + val.name + " type=" + val.type + " x=" + rect.x + " y=" + rect.y + " width=" + rect.width + " height=" + rect.height + "/>");
    268.                     //writer.WriteLine("\t<" + val.name + " type=" + val.type + " val=" + floats.Count + "/>");
    269.                     //floats.Add(rect.x); floats.Add(rect.y); floats.Add(rect.width); floats.Add(rect.height);
    270.                 }
    271.  
    272.                 //Color
    273.                 else if (val.type == typeof(Color))
    274.                 {
    275.                     Color c = (Color)val.obj;
    276.                     var r = InvariantFloat(c.r);
    277.                     var g = InvariantFloat(c.g);
    278.                     var b = InvariantFloat(c.b);
    279.                     var a = InvariantFloat(c.a);
    280.                     var line = string.Format("\t<{0} type={1} r={2} g={3} b={4} a={5}/>",val.name, val.type, r,g,b,a);
    281.                     writer.WriteLine(line);
    282.                     //writer.WriteLine("\t<" + val.name + " type=" + val.type + " r=" + c.r + " g=" + c.g + " b=" + c.b + " a=" + c.a + "/>");
    283.                 }
    284.  
    285.                 //Vector4
    286.                 else if (val.type == typeof(Vector4))
    287.                 {
    288.                     Vector4 v4 = (Vector4)val.obj;
    289.                     var x = InvariantFloat(v4.x);
    290.                     var y = InvariantFloat(v4.y);
    291.                     var z = InvariantFloat(v4.z);
    292.                     var w = InvariantFloat(v4.w);
    293.                     var line = string.Format("\t<{0} type={1} x={2} y={3} z={4} w={5}/>",val.name, val.type, x,y,z,w);
    294.                     writer.WriteLine(line);
    295.                     //writer.WriteLine("\t<" + val.name + " type=" + val.type + " x=" + v4.x + " y=" + v4.y + " z=" + v4.z + " w=" + v4.w + "/>");
    296.                 }
    297.  
    298.                 //Quaternion
    299.                 else if (val.type == typeof(Quaternion))
    300.                 {
    301.                     Quaternion q = (Quaternion)val.obj;
    302.                     var x = InvariantFloat(q.x);
    303.                     var y = InvariantFloat(q.y);
    304.                     var z = InvariantFloat(q.z);
    305.                     var w = InvariantFloat(q.w);
    306.                     var line = string.Format("\t<{0} type={1} x={2} y={3} z={4} w={5}/>",val.name, val.type, x,y,z,w);
    307.                     writer.WriteLine(line);
    308.                     //writer.WriteLine("\t<" + val.name + " type=" + val.type + " x=" + q.x + " y=" + q.y + " z=" + q.z + " w=" + q.w + "/>");
    309.                 }
    310.  
    311.                 //enum
    312.                 else if (val.type.IsEnum)
    313.                     writer.WriteLine("\t<" + val.name + " type=" + val.type + " value=" + (int)val.obj + "/>");
    314.  
    315.                 //keyframe
    316.                 else if (val.type == typeof(Keyframe))
    317.                 {
    318.                     Keyframe k = (Keyframe)val.obj;
    319.  
    320.                     var time = InvariantFloat(k.time);
    321.                     var value = InvariantFloat(k.value);
    322.                     var inTan = InvariantFloat(k.inTangent);
    323.                     var outTan = InvariantFloat(k.outTangent);
    324.  
    325. #if UNITY_2018_2_OR_NEWER
    326.                     var inWeight = InvariantFloat(k.inWeight);
    327.                     var outWeight = InvariantFloat(k.outWeight);
    328.  
    329.                     var line = string.Format("\t<{0} type={1} time={2} value={3} in={4} out={5} mode={6} inWeight={7} outWeight={8}/>",
    330.                         val.name, val.type, time, value, inTan, outTan, 0, inWeight, outWeight);
    331.                     writer.WriteLine(line);
    332. #else
    333.                     var mode = InvariantFloat(k.tangentMode);
    334.                     var line = string.Format("\t<{0} type={1} time={2} value={3} in={4} out={5} mode={6}/>",val.name, val.type, time, value, inTan, outTan, mode);
    335.                     writer.WriteLine(line);
    336. #endif
    337.                 }
    338.  
    339.                 //any other struct (same as class)
    340.                 else
    341.                     writer.WriteLine("\t<" + val.name + " type=" + val.type + " link=" +  WriteClass(val.obj, classes, objects, floats, references) + "/>");
    342.             }
    343.  
    344.             //footer
    345.             writer.WriteLine("</" + objTypeName + ">");
    346.  
    347.             //writing obj
    348.             writer.Close();
    349.             classes[slotNum] = writer.ToString();
    350.  
    351.             return slotNum;
    352.         }
    353.  
    354.         private static string InvariantFloat(float value)
    355.         {
    356.             return value.ToString(CultureInfo.InvariantCulture.NumberFormat);
    357.         }
    358.  
    359.         private static string InvariantDouble(double value)
    360.         {
    361.             return value.ToString(CultureInfo.InvariantCulture.NumberFormat);
    362.         }
    363.  
    364.         public static object ReadClass (int slotNum, List<string> classes, List<UnityEngine.Object> objects, List<float> floats, List<object> references)
    365.         {
    366.             //cheking if this object was already loaded
    367.             for (int i=references.Count; i<classes.Count; i++) references.Add(null); //references count should be equal to classes length
    368.             if (references[slotNum]!=null) return references[slotNum];
    369.  
    370.             object obj = null;
    371.  
    372.             StringReader reader = new StringReader(classes[slotNum]);
    373.  
    374.             //reading header
    375.             string header = reader.ReadLine();
    376.             header = header.Substring(1,header.Length-2);
    377.  
    378.             //getting the array length
    379.             int arrayLength = 0;
    380.             if (header.Contains(" length="))
    381.             {
    382.                 string[] headerMembers = header.Split(' ');
    383.                 arrayLength = (int)headerMembers[1].Parse(typeof(int));
    384.                 header = headerMembers[0];
    385.             }
    386.  
    387.             //finding object type
    388.             System.Type objType = GetStandardAssembliesType(header);
    389.             if (objType == null) { Debug.Log("Could not load " + header + " as this type does not exists anymore"); return null; }
    390.             System.Type elementType = objType.IsArray? objType.GetElementType() : null;
    391.  
    392.             //creating object
    393.             if (objType.IsArray) obj = Activator.CreateInstance(objType, arrayLength);
    394.             else obj = Activator.CreateInstance(objType);
    395.             references[slotNum] = obj;
    396.  
    397.             //reading values
    398.             List<Value> values = new List<Value>();
    399.             while (true)
    400.             {
    401.                 string line = reader.ReadLine();
    402.                 if (line==null || line.StartsWith("</")) break;
    403.  
    404.                 //if (line.StartsWith("\t")) line = line.Remove(0,1); //removing tab if any
    405.                 line = line.Substring(2,line.Length-4); //removing < and />
    406.                 string[] lineMembers = line.Split(' ', Separator);
    407.  
    408.                 Value val = new Value();
    409.          
    410.                 //name
    411.                 val.name = lineMembers[0];
    412.          
    413.                 //type
    414.                 string typeName = lineMembers[1].Remove(0,5);
    415.                 val.type = GetStandardAssembliesType(typeName);
    416.                 if (val.type == null) { Debug.Log("Could not load " + typeName + " as this type does not exists anymore"); continue; }
    417.  
    418.                 //object: quick array
    419.                 if (val.type.IsArray && val.name=="items")
    420.                 {
    421.                     if (val.type == typeof(float[]))
    422.                     {
    423.                         int start = (int)lineMembers[2].Parse(typeof(int));
    424.                         for (int i=start; i<start+arrayLength; i++)
    425.                             values.Add( new Value() { name="item", type=elementType, obj=floats[i] } );
    426.                     }
    427.  
    428.                  
    429.                     //class
    430.                     /*if (lineMembers[2].StartsWith("link"))
    431.                     {
    432.                         for (int i=2; i<lineMembers.Length; i++)
    433.                             values.Add( new Value() { name="item", type=elementType, obj=ReadClass( (int)lineMembers[i].Parse(typeof(int)), classes, objects, floats, references) } );
    434.                     }*/
    435.  
    436.                     //primitives
    437.                     else
    438.                     {
    439.                         for (int i=2; i<lineMembers.Length; i++)
    440.                             values.Add( new Value() { name="item", type=elementType, obj=lineMembers[i].Parse(elementType) } );
    441.                     }
    442.                 }
    443.  
    444.                 //object: other
    445.                 else
    446.                 {
    447.                     //null
    448.                     if (lineMembers[2]=="null") val.obj = null;
    449.  
    450.                     //custom struct
    451.                     else if (typeof(IStruct).IsAssignableFrom(val.type))
    452.                     {
    453.                         val.obj = Activator.CreateInstance(val.type);
    454.                         ((IStruct)val.obj).Decode(lineMembers);
    455.                     }
    456.  
    457.                     //custom struct with links
    458.                     else if (typeof(IStructLink).IsAssignableFrom(val.type))
    459.                     {
    460.                         Func<int, object> readClassFn = delegate(int link) { return ReadClass(link, classes, objects, floats, references); };
    461.                         val.obj = Activator.CreateInstance(val.type);
    462.                         ((IStructLink)val.obj).Decode(lineMembers, readClassFn);
    463.                     }
    464.              
    465.                     //class
    466.                     else if (lineMembers[2].StartsWith("link"))
    467.                     {
    468.                         //val.obj = int.Parse(lineMembers[2].Remove(0,5)); //postporning reading the class until the object is created, storing link
    469.                         val.obj = ReadClass(int.Parse(lineMembers[2].Remove(0,5)), classes, objects, floats, references);
    470.                     }
    471.  
    472.                     //primitive
    473.                     else if (val.type.IsPrimitive)
    474.                         val.obj = lineMembers[2].Parse(val.type);
    475.  
    476.                     //unity Object
    477.                     else if (val.type.IsSubclassOf(typeof(UnityEngine.Object)))
    478.                     {
    479.                         val.obj = objects[ (int)lineMembers[2].Parse(typeof(int)) ];
    480.                     }
    481.  
    482.                     //string
    483.                     else if (val.type==typeof(string))
    484.                     {
    485.                         string str = (string)lineMembers[2].Parse(val.type);
    486.                         str = str.Replace("\\n", "\n");
    487.                         str = str.Replace("\\_", " ");
    488.                         val.obj = str;
    489.                     }
    490.  
    491.                     //Vector2
    492.                     else if (val.type == typeof(Vector2))
    493.                         val.obj = new Vector2( (float)lineMembers[2].Parse(typeof(float)), (float)lineMembers[3].Parse(typeof(float)) );
    494.                     //{
    495.                     //    int n = (int)lineMembers[2].Parse(typeof(int));
    496.                     //    val.obj = new Vector2(floats[n], floats[n+1]);
    497.                     //}
    498.  
    499.                     //Vector3
    500.                     else if (val.type == typeof(Vector3))
    501.                         val.obj = new Vector3( (float)lineMembers[2].Parse(typeof(float)), (float)lineMembers[3].Parse(typeof(float)), (float)lineMembers[4].Parse(typeof(float)) );
    502.                     //{
    503.                     //    int n = (int)lineMembers[2].Parse(typeof(int));
    504.                     //    val.obj = new Vector3(floats[n], floats[n+1], floats[n+2]);
    505.                     //}
    506.  
    507.                     //Rect
    508.                     else if (val.type == typeof(Rect))
    509.                         val.obj = new Rect( (float)lineMembers[2].Parse(typeof(float)), (float)lineMembers[3].Parse(typeof(float)), (float)lineMembers[4].Parse(typeof(float)), (float)lineMembers[5].Parse(typeof(float)) );
    510.                     //{
    511.                     //    int n = (int)lineMembers[2].Parse(typeof(int));
    512.                     //    val.obj = new Rect(floats[n], floats[n+1], floats[n+2], floats[n+3]);
    513.                     //}
    514.  
    515.                     //Color
    516.                     else if (val.type == typeof(Color))
    517.                         val.obj = new Color( (float)lineMembers[2].Parse(typeof(float)), (float)lineMembers[3].Parse(typeof(float)), (float)lineMembers[4].Parse(typeof(float)), (float)lineMembers[5].Parse(typeof(float)) );
    518.              
    519.                     //Vector4
    520.                     else if (val.type == typeof(Vector4))
    521.                         val.obj = new Vector4( (float)lineMembers[2].Parse(typeof(float)), (float)lineMembers[3].Parse(typeof(float)), (float)lineMembers[4].Parse(typeof(float)), (float)lineMembers[5].Parse(typeof(float)) );
    522.              
    523.                     //Quaternion
    524.                     else if (val.type == typeof(Quaternion))
    525.                         val.obj = new Quaternion( (float)lineMembers[2].Parse(typeof(float)), (float)lineMembers[3].Parse(typeof(float)), (float)lineMembers[4].Parse(typeof(float)), (float)lineMembers[5].Parse(typeof(float)) );
    526.                  
    527.                     //Keyframe
    528.                     else if (val.type == typeof(Keyframe))
    529.                     {
    530.                         Keyframe k = new Keyframe( (float)lineMembers[2].Parse(typeof(float)), (float)lineMembers[3].Parse(typeof(float)), (float)lineMembers[4].Parse(typeof(float)), (float)lineMembers[5].Parse(typeof(float)) );
    531.  
    532.                         #if UNITY_2018_2_OR_NEWER
    533.                         if (lineMembers.Length > 7)
    534.                         {
    535.                             k.inWeight = (float)lineMembers[7].Parse(typeof(float));
    536.                             k.outWeight = (float)lineMembers[8].Parse(typeof(float));
    537.                         }
    538.                         else
    539.                             k.tangentMode = (int)lineMembers[6].Parse(typeof(int));
    540.                         #else
    541.                         k.tangentMode = (int)lineMembers[6].Parse(typeof(int));
    542.                         #endif
    543.  
    544.                         val.obj = k;
    545.                     }
    546.              
    547.                     //enum
    548.                     else if (val.type.IsEnum)
    549.                         val.obj = Enum.ToObject(val.type, (int)lineMembers[2].Parse(typeof(int)));
    550.  
    551.                     values.Add(val);
    552.                 }
    553.             }
    554.  
    555.             //filling object
    556.             int valuesCount = values.Count;
    557.             if (objType.IsArray)
    558.             {
    559.                 Array array = (Array)obj;
    560.                 for (int i=0; i<array.Length; i++) array.SetValue(values[i].obj, i);
    561.             }
    562.             else
    563.             {
    564.                 //TODO: inline code here
    565.                 //TODO: use attributes
    566.                 foreach (FieldInfo field in objType.UsableFields(includeStatic:true))
    567.                 {
    568.                     string fieldName = field.Name;
    569.                     Type fieldType = field.FieldType;
    570.  
    571.                     for (int i=0; i<valuesCount; i++)
    572.                         try {
    573.                         if (values[i].name == fieldName  &&  values[i].type == fieldType) field.SetValue(obj, values[i].obj); }
    574.                         catch {}
    575.                 }
    576.                 foreach (PropertyInfo prop in objType.UsableProperties())
    577.                 {
    578.                     string propName = prop.Name;
    579.                     Type propType = prop.PropertyType;
    580.  
    581.                     for (int i=0; i<valuesCount; i++)
    582.                         if (values[i].name == propName  &&  values[i].type == propType) prop.SetValue(obj, values[i].obj, null);
    583.                 }
    584.             }
    585.  
    586.  
    587.             return obj;
    588.         }
    589.  
    590.  
    591.         public static object DeepCopy (object src)
    592.         {
    593.             List<string> classes = new List<string>();
    594.             List<UnityEngine.Object> objects = new List<UnityEngine.Object>();
    595.             List<float> floats = new List<float>();
    596.             List<object> saveReferences = new List<object>();
    597.             List<object> loadReferences = new List<object>();
    598.  
    599.             int num = CustomSerialization.WriteClass(src, classes, objects, floats, saveReferences);
    600.             return CustomSerialization.ReadClass(num, classes, objects, floats, loadReferences);
    601.         }
    602.  
    603.         public static string ExportXML (List<string> classes, List<UnityEngine.Object> objects, List<float> floats)
    604.         {
    605.             StringWriter writer = new StringWriter();
    606.  
    607.             for (int i=0; i<classes.Count; i++)
    608.                 writer.Write(classes[i]);
    609.  
    610.             #if UNITY_EDITOR
    611.             for (int i=0; i<objects.Count; i++)
    612.             {
    613.                 string path = UnityEditor.AssetDatabase.GetAssetPath(objects[i]);
    614.                 path = path.Replace(" ","*");
    615.                 writer.WriteLine("<Object type=" + objects[i].GetType() + " path=" + path + "/>");
    616.             }
    617.             #endif
    618.  
    619.             writer.Write("<Floats values=");
    620.             int floatsCount = floats.Count;
    621.             for (int i=0; i<floatsCount; i++)
    622.             {
    623.                  writer.Write(floats[i].ToString());
    624.                  if (i != floatsCount-1) writer.Write(Separator);
    625.             }
    626.             writer.WriteLine("/>");
    627.  
    628.             writer.Close();
    629.             return writer.ToString();
    630.         }
    631.  
    632.         public static void ImportXML (string xml, out List<string> classes, out List<UnityEngine.Object> objects, out List<float> floats)
    633.         {
    634.             StringReader reader = new StringReader(xml);
    635.          
    636.             classes = new List<string>();
    637.             objects = new List<UnityEngine.Object>();
    638.             floats = new List<float>();
    639.  
    640.             StringWriter writer = null;
    641.             while (true)
    642.             {
    643.                 string line = reader.ReadLine();
    644.                 if (line==null) break;
    645.  
    646.                 //objects
    647.                 if (line.StartsWith("<Object"))
    648.                 {
    649.                     #if UNITY_EDITOR
    650.                     line = line.Replace("/>","");
    651.                     string[] lineMemebers = line.Split(' ');
    652.  
    653.                     string path = lineMemebers[2].Replace("path=","");
    654.                     path = path.Replace("*", " ");
    655.                     objects.Add(UnityEditor.AssetDatabase.LoadMainAssetAtPath(path));
    656.  
    657.                     Type type = GetStandardAssembliesType( lineMemebers[1].Replace("type=","") );
    658.                     if (type==typeof(Transform) && objects[objects.Count-1]!=null) objects[objects.Count-1] = ((GameObject)objects[objects.Count-1]).transform; //converting to transform instead of gameobject
    659.                     #endif
    660.  
    661.                     continue;
    662.                 }
    663.  
    664.                 //floats
    665.                 if (line.StartsWith("<Floats"))
    666.                 {
    667.                     line = line.Replace("<Floats values=","");
    668.                     line = line.Replace("/>","");
    669.                     if (line.Length==0) continue;
    670.  
    671.                     string[] lineMemebers = line.Split(Separator);
    672.                     for (int i=0; i<lineMemebers.Length; i++) floats.Add(float.Parse(lineMemebers[i]));
    673.  
    674.                     continue;
    675.                 }
    676.  
    677.                 //classes
    678.                 if (!line.Contains("/>") && !line.Contains("</")) //class started
    679.                 {
    680.                     if (writer!=null) classes.Add(writer.ToString());
    681.                     writer = new StringWriter();
    682.                 }
    683.  
    684.                 writer.WriteLine(line);
    685.             }
    686.             classes.Add(writer.ToString()); //writing down what's left in writer
    687.         }
    688.     }
    689.  
    690. }
    691.  
    Extensions:

    Code (CSharp):
    1. using UnityEngine;
    2. using System;
    3. using System.Collections;
    4. using System.Collections.Generic;
    5. using System.Reflection; //to copy properties
    6. using System.Globalization;
    7.  
    8. namespace MapMagic
    9. {
    10.     public interface IFactory
    11.     {
    12.         void OnConstruct ();
    13.         void OnDeconstruct ();
    14.     }
    15.  
    16.     static public class Extensions
    17.     {
    18.         public enum VersionState { branch, alpha, beta, candidate, release };
    19.         public static string ToVersionString (this VersionState state)
    20.         {
    21.             switch (state)
    22.             {
    23.                 case VersionState.branch: return "special edition";
    24.                 case VersionState.alpha: return "development";
    25.                 case VersionState.beta: return "beta";
    26.                 case VersionState.candidate: return "release candidate";
    27.                 default: return "";
    28.             }
    29.         }
    30.         public static string ToVersionString (this int ver)
    31.         {
    32.             int val1 = ver/100;
    33.             int val2 = (ver - val1*100) / 10;
    34.             int val3 = ver - val1*100 - val2*10;
    35.             return ""+val1+"."+val2+"."+val3;
    36.         }
    37.  
    38.         public static bool InRange (this Rect rect, Vector2 pos)
    39.         {
    40.             return (rect.center - pos).sqrMagnitude < (rect.width/2f)*(rect.width/2f);
    41.             //return rect.Contains(pos);
    42.         }
    43.  
    44.         public static Vector3 ToDir (this float angle) { return new Vector3( Mathf.Sin(angle*Mathf.Deg2Rad), 0, Mathf.Cos(angle*Mathf.Deg2Rad) ); }
    45.         public static float ToAngle (this Vector3 dir) { return Mathf.Atan2(dir.x, dir.z) * Mathf.Rad2Deg; }
    46.  
    47.         public static Vector3 V3 (this Vector2 v2) { return new Vector3(v2.x, 0, v2.y); }
    48.         public static Vector2 V2 (this Vector3 v3) { return new Vector2(v3.x, v3.z); }
    49.         public static Vector3 ToV3 (this float f) { return new Vector3(f,f, f); }
    50.  
    51.         public static Quaternion EulerToQuat (this Vector3 v) { Quaternion rotation = Quaternion.identity; rotation.eulerAngles = v; return rotation; }
    52.         public static Quaternion EulerToQuat (this float f) { Quaternion rotation = Quaternion.identity; rotation.eulerAngles = new Vector3(0,f,0); return rotation; }
    53.  
    54.         public static Vector3 Direction (this float angle) { return new Vector3( Mathf.Sin(angle*Mathf.Deg2Rad), 0, Mathf.Cos(angle*Mathf.Deg2Rad) ); }
    55.         public static float Angle (this Vector3 dir) { return Mathf.Atan2(dir.x, dir.z) * Mathf.Rad2Deg; }
    56.  
    57.         public static Rect Clamp (this Rect r, float p) { return new Rect(r.x, r.y, r.width*p, r.height); }
    58.         public static Rect ClampFromLeft (this Rect r, float p) { return new Rect(r.x+r.width*(1f-p), r.y, r.width*p, r.height); }
    59.         public static Rect Clamp (this Rect r, int p) { return new Rect(r.x, r.y, p, r.height); }
    60.         public static Rect ClampFromLeft (this Rect r, int p) { return new Rect(r.x+(r.width-p), r.y, p, r.height); }
    61.  
    62.         public static Rect ToRect(this Vector3 center, float range) { return new Rect(center.x-range, center.z-range, range*2, range*2); }
    63.  
    64.         public static Vector3 Average (this Vector3[] vecs) { Vector3 result = Vector3.zero; for (int i=0; i<vecs.Length; i++) result+=vecs[i]; return result / vecs.Length; }
    65.  
    66.         public static bool Intersects (this Rect r1, Rect r2)
    67.         {
    68.             Vector2 r1min = r1.min; Vector2 r1max = r1.max;
    69.             Vector2 r2min = r2.min; Vector2 r2max = r2.max;
    70.             if (r2max.x < r1min.x || r2min.x > r1max.x || r2max.y < r1min.y || r2min.y > r1max.y) return false;
    71.             else return true;
    72.         }
    73.         public static bool Intersects (this Rect r1, Rect[] rects)
    74.         {
    75.             for (int i=0; i<rects.Length; i++)
    76.                 if (r1.Intersects(rects[i])) return true; //todo: remove fn call, use r1 min max
    77.             return false;
    78.         }
    79.  
    80.         public static bool Contains (this Rect r1, Rect r2)
    81.         {
    82.             Vector2 r1min = r1.min; Vector2 r1max = r1.max;
    83.             Vector2 r2min = r2.min; Vector2 r2max = r2.max;
    84.             if (r2min.x > r1min.x && r2max.x < r1max.x && r2min.y > r1min.y && r2max.y < r1max.y) return true;
    85.             else return false;
    86.         }
    87.  
    88.         public static Rect Extend (this Rect r, float f) { return new Rect(r.x-f, r.y-f, r.width+f*2, r.height+f*2); }
    89.  
    90.         public static float DistToRectCenter (this Vector3 pos, float offsetX, float offsetZ, float size)
    91.         {
    92.             //TODO: evaluating distance to center, should evaluate distance to rect edges isntead
    93.             //float posX = pos.x; float posZ = pos.z;
    94.             float deltaX = pos.x - (offsetX+size/2); float deltaZ = pos.z - (offsetZ+size/2); float dist = deltaX*deltaX + deltaZ*deltaZ;
    95.  
    96.             /*float deltaBX = pos.x - offsetX; float deltaBZ = pos.z - offsetZ; float distB = deltaBX*deltaBX + deltaBZ*deltaBZ;
    97.             float deltaCX = pos.x - (offsetX+size); float deltaCZ = pos.z - (offsetZ+size); float distC = deltaCX*deltaCX + deltaCZ*deltaCZ;
    98.             float deltaDX = pos.x - (offsetX+size); float deltaDZ = pos.z - (offsetZ+size); float distD = deltaDX*deltaDX + deltaDZ*deltaDZ;
    99.  
    100.             //zero dist if pos inside rect
    101.             if (deltaAX>0 && deltaAZ>0 &&
    102.  
    103.             float minAB = distA<distB? distA : distB;
    104.             float minCD = distC<distD? distC : distD;
    105.             float minABCD = minAB<minCD? minAB : minCD;*/
    106.  
    107.             return Mathf.Sqrt(dist);
    108.         }
    109.  
    110.         public static float DistToRectAxisAligned (this Vector3 pos, float offsetX, float offsetZ, float size) //not manhattan dist. offset and size are instead of UnityEngine.Rect
    111.         {
    112.             //finding x distance
    113.             float distPosX = offsetX - pos.x;
    114.             float distNegX = pos.x - offsetX - size;
    115.          
    116.             float distX;
    117.             if (distPosX >= 0) distX = distPosX;
    118.             else if (distNegX >= 0) distX = distNegX;
    119.             else distX = 0;
    120.  
    121.             //finding z distance
    122.             float distPosZ = offsetZ - pos.z;
    123.             float distNegZ = pos.z - offsetZ - size;
    124.          
    125.             float distZ;
    126.             if (distPosZ >= 0) distZ = distPosZ;
    127.             else if (distNegZ >= 0) distZ = distNegZ;
    128.             else distZ = 0;
    129.  
    130.             //returning the maximum(!) distance
    131.             if (distX > distZ) return distX;
    132.             else return distZ;
    133.         }
    134.  
    135.         public static float DistToRectCenter (this Vector3[] poses, float offsetX, float offsetZ, float size)
    136.         {
    137.             float minDist = 200000000;
    138.             for (int p=0; p<poses.Length; p++)
    139.             {
    140.                 float dist = poses[p].DistToRectCenter(offsetX, offsetZ, size);
    141.                 if (dist < minDist) minDist = dist;
    142.             }
    143.             return minDist;
    144.         }
    145.  
    146.         public static float DistToRectAxisAligned (this Vector3[] poses, float offsetX, float offsetZ, float size)
    147.         {
    148.             float minDist = 200000000;
    149.             for (int p=0; p<poses.Length; p++)
    150.             {
    151.                 float dist = poses[p].DistToRectAxisAligned(offsetX, offsetZ, size);
    152.                 if (dist < minDist) minDist = dist;
    153.             }
    154.             return minDist;
    155.         }
    156.  
    157.         public static float DistAxisAligned (this Vector3 center, Vector3 pos)
    158.         {
    159.             float distX = center.x - pos.x; if (distX<0) distX = -distX;
    160.             float distZ = center.z - pos.z; if (distZ<0) distZ = -distZ;
    161.  
    162.             //returning the maximum(!) distance
    163.             if (distX > distZ) return distX;
    164.             else return distZ;
    165.         }
    166.  
    167.  
    168.  
    169.         /*public static Coord ToCoord (this Vector3 pos, float cellSize, bool ceil=false) //to use in object grid
    170.         {
    171.             if (!ceil) return new Coord(
    172.                 Mathf.FloorToInt((pos.x) / cellSize),
    173.                 Mathf.FloorToInt((pos.z) / cellSize) );
    174.             else return new Coord(
    175.                 Mathf.CeilToInt((pos.x) / cellSize),
    176.                 Mathf.CeilToInt((pos.z) / cellSize) );
    177.         }*/
    178.  
    179.         public static Coord RoundToCoord (this Vector2 pos) //to use in spatial hash (when sphash and matrix sizes are equal)
    180.         {
    181.             int posX = (int)(pos.x + 0.5f); if (pos.x < 0) posX--; //snippet for RoundToInt
    182.             int posZ = (int)(pos.y + 0.5f); if (pos.y < 0) posZ--;
    183.             return new Coord(posX, posZ);
    184.         }
    185.  
    186.         public static Coord FloorToCoord (this Vector3 pos, float cellSize) { return new Coord( Mathf.FloorToInt(pos.x / cellSize),        Mathf.FloorToInt(pos.z / cellSize)  ); }
    187.         public static Coord CeilToCoord (this Vector3 pos, float cellSize) { return new Coord( Mathf.CeilToInt(pos.x / cellSize),        Mathf.CeilToInt(pos.z / cellSize)  ); }
    188.         public static Coord RoundToCoord (this Vector3 pos, float cellSize) { return new Coord( Mathf.RoundToInt(pos.x / cellSize),        Mathf.RoundToInt(pos.z / cellSize)  ); }
    189.         public static CoordRect ToCoordRect (this Vector3 pos, float range, float cellSize) //this one works with Terrain Sculptor
    190.         {
    191.             Coord min = new Coord( Mathf.FloorToInt((pos.x-range)/cellSize),    Mathf.FloorToInt((pos.z-range)/cellSize)  );
    192.             Coord max = new Coord( Mathf.FloorToInt((pos.x+range)/cellSize),    Mathf.FloorToInt((pos.z+range)/cellSize)  )  +  1;
    193.             return new CoordRect(min, max-min);
    194.         }
    195.  
    196.         public static CoordRect ToFixedSizeCoordRect (this Vector3 pos, float range, float cellSize)
    197.         {
    198.             Coord size = (Vector3.one*range*2).CeilToCoord(cellSize) + 1;
    199.             Coord offset = pos.RoundToCoord(cellSize) - size/2;
    200.             return new CoordRect (offset, size);
    201.         }
    202.  
    203.         public static CoordRect GetHeightRect (this Terrain terrain)
    204.         {
    205.             float pixelSize = terrain.terrainData.size.x / terrain.terrainData.heightmapResolution;
    206.  
    207.             int posX = (int)(terrain.transform.localPosition.x/pixelSize + 0.5f); if (terrain.transform.localPosition.x < 0) posX--;
    208.             int posZ = (int)(terrain.transform.localPosition.z/pixelSize + 0.5f); if (terrain.transform.localPosition.z < 0) posZ--;
    209.  
    210.             return new CoordRect(posX, posZ, terrain.terrainData.heightmapResolution, terrain.terrainData.heightmapResolution);
    211.         }
    212.  
    213.         public static CoordRect GetSplatRect (this Terrain terrain)
    214.         {
    215.             float pixelSize = terrain.terrainData.size.x / terrain.terrainData.alphamapResolution;
    216.  
    217.             int posX = (int)(terrain.transform.localPosition.x/pixelSize + 0.5f); if (terrain.transform.localPosition.x < 0) posX--;
    218.             int posZ = (int)(terrain.transform.localPosition.z/pixelSize + 0.5f); if (terrain.transform.localPosition.z < 0) posZ--;
    219.  
    220.             return new CoordRect(posX, posZ, terrain.terrainData.alphamapResolution, terrain.terrainData.alphamapResolution);
    221.         }
    222.  
    223.         public static float[,] SafeGetHeights (this TerrainData data, int offsetX, int offsetZ, int sizeX, int sizeZ)
    224.         {
    225.             if (offsetX<0) { sizeX += offsetX; offsetX=0; } if (offsetZ<0) { sizeZ += offsetZ; offsetZ=0; } //Not Tested!
    226.             int res = data.heightmapResolution;
    227.             if (sizeX+offsetX > res) sizeX = res-offsetX; if (sizeZ+offsetZ > res) sizeZ = res-offsetZ;
    228.             return data.GetHeights(offsetX, offsetZ, sizeX, sizeZ);
    229.         }
    230.  
    231.         public static float[,,] SafeGetAlphamaps (this TerrainData data, int offsetX, int offsetZ, int sizeX, int sizeZ)
    232.         {
    233.             if (offsetX<0) { sizeX += offsetX; offsetX=0; } if (offsetZ<0) { sizeZ += offsetZ; offsetZ=0; } //Not Tested!
    234.             int res = data.alphamapResolution;
    235.             if (sizeX+offsetX > res) sizeX = res-offsetX; if (sizeZ+offsetZ > res) sizeZ = res-offsetZ;
    236.             return data.GetAlphamaps(offsetX, offsetZ, sizeX, sizeZ);
    237.         }
    238.  
    239.         public static Texture2D ColorTexture (int width, int height, Color color)
    240.         {
    241.             Texture2D result = new Texture2D(width, height);
    242.             Color[] pixels = result.GetPixels(0,0,width,height);
    243.             for (int i=0;i<pixels.Length;i++) pixels[i] = color;
    244.             result.SetPixels(0,0,width,height, pixels);
    245.             result.Apply();
    246.             return result;
    247.         }
    248.  
    249.         public static bool Equal (Vector3 v1, Vector3 v2)
    250.         {
    251.             return Mathf.Approximately(v1.x, v2.x) &&
    252.                     Mathf.Approximately(v1.y, v2.y) &&
    253.                     Mathf.Approximately(v1.z, v2.z);
    254.         }
    255.      
    256.         public static bool Equal (Ray r1, Ray r2)
    257.         {
    258.             return Equal(r1.origin, r2.origin) && Equal(r1.direction, r2.direction);
    259.         }
    260.  
    261.         public static void RemoveChildren (this Transform tfm)
    262.         {
    263.             for (int i=tfm.childCount-1; i>=0; i--)
    264.             {
    265.                 Transform child = tfm.GetChild(i);
    266.                 GameObject.DestroyImmediate(child.gameObject);
    267.             }
    268.         }
    269.  
    270.         public static Transform FindChildRecursive (this Transform tfm, string name)
    271.         {
    272.             int numChildren = tfm.childCount;
    273.  
    274.             for (int i=0; i<numChildren; i++)
    275.                 if (tfm.GetChild(i).name == name) return tfm.GetChild(i);
    276.  
    277.             for (int i=0; i<numChildren; i++)
    278.             {
    279.                 Transform result = tfm.GetChild(i).FindChildRecursive(name);
    280.                 if (result != null) return result;
    281.             }
    282.  
    283.             return null;
    284.         }
    285.  
    286.         public static Vector3[] InverseTransformPoint (this Transform tfm, Vector3[] points)
    287.         {
    288.             for (int c=0; c<points.Length; c++) points[c] = tfm.InverseTransformPoint(points[c]);
    289.             return points;
    290.         }
    291.  
    292.         public static Vector3 GetCenter (this Vector3[] poses)
    293.         {
    294.             if (poses.Length == 0) return new Vector3();
    295.             if (poses.Length == 1) return poses[0];
    296.  
    297.             float x=0; float y=0; float z=0;
    298.             for (int i=0; i<poses.Length; i++)
    299.             {
    300.                 x+=poses[i].x;
    301.                 y+=poses[i].y;
    302.                 z+=poses[i].z;
    303.             }
    304.             return new Vector3(x/poses.Length, y/poses.Length, z/poses.Length);
    305.         }
    306.  
    307.         public static void ToggleDisplayWireframe (this Transform tfm, bool show)
    308.         {
    309.             #if UNITY_EDITOR
    310.             #if !UNITY_5_5_OR_NEWER
    311.                 UnityEditor.EditorUtility.SetSelectedWireframeHidden(tfm.GetComponent<Renderer>(), !show);
    312.                 int childCount = tfm.childCount;
    313.                 for (int c=0; c<childCount; c++) tfm.GetChild(c).ToggleDisplayWireframe(show);
    314.             #else
    315.                 UnityEditor.EditorUtility.SetSelectedRenderState(tfm.GetComponent<Renderer>(), show? UnityEditor.EditorSelectedRenderState.Highlight : UnityEditor.EditorSelectedRenderState.Hidden);
    316.                 int childCount = tfm.childCount;
    317.                 for (int c=0; c<childCount; c++) tfm.GetChild(c).ToggleDisplayWireframe(show);
    318.             #endif
    319.             #endif
    320.         }
    321.  
    322.         public static int ToInt (this Coord coord)
    323.         {
    324.             int absX = coord.x<0? -coord.x : coord.x;
    325.             int absZ = coord.z<0? -coord.z : coord.z;
    326.  
    327.             return ((coord.z<0? 1000000000 : 0) + absX*30000 + absZ) * (coord.x<0? -1 : 1);
    328.         }
    329.  
    330.         public static Coord ToCoord (this int hash)
    331.         {
    332.             int absHash = hash<0? -hash : hash;
    333.             int sign = (absHash/1000000000)*1000000000;
    334.  
    335.             int absX = (absHash - sign)/30000;
    336.             int absZ = absHash - sign - absX*30000;
    337.  
    338.             return new Coord(hash<0? -absX : absX, sign==0? absZ : -absZ);
    339.         }
    340.  
    341.         public static void CheckAdd<TKey,TValue> (this Dictionary<TKey,TValue> dict, TKey key, TValue value, bool replace=true)
    342.         {
    343.             if (dict.ContainsKey(key))
    344.                 { if (replace) dict[key] = value; }
    345.             else dict.Add(key, value);
    346.         }
    347.         public static void CheckRemove<TKey,TValue> (this Dictionary<TKey,TValue> dict, TKey key) { if (dict.ContainsKey(key)) dict.Remove(key); }
    348.         public static TValue CheckGet<TKey,TValue> (this Dictionary<TKey,TValue> dict, TKey key)
    349.         {
    350.             if (dict.ContainsKey(key)) return dict[key];
    351.             else return default(TValue);
    352.         }
    353.         public static TKey AnyKey<TKey,TValue> (this Dictionary<TKey,TValue> dict)
    354.         {
    355.             foreach (KeyValuePair<TKey,TValue> kvp in dict)
    356.                 return kvp.Key;
    357.             return default(TKey);
    358.         }
    359.         public static TValue AnyValue<TKey,TValue> (this Dictionary<TKey,TValue> dict)
    360.         {
    361.             foreach (KeyValuePair<TKey,TValue> kvp in dict)
    362.                 return kvp.Value;
    363.             return default(TValue);
    364.         }
    365.         public static T Any<T> (this HashSet<T> hashSet)
    366.         {
    367.             foreach (T val in hashSet)
    368.                 return val;
    369.             return default(T);
    370.         }
    371.  
    372.         public static void CheckAdd<T> (this HashSet<T> set, T obj) { if (!set.Contains(obj)) set.Add(obj); }
    373.         public static void CheckRemove<T> (this HashSet<T> set, T obj) { if (set.Contains(obj)) set.Remove(obj); }
    374.         public static void SetState<T> (this HashSet<T> set, T obj, bool state)
    375.         {
    376.             if (state && !set.Contains(obj)) set.Add(obj);
    377.             if (!state && set.Contains(obj)) set.Remove(obj);
    378.         }
    379.  
    380.         public static void Normalize (this float[,,] array, int pinnedLayer)
    381.         {
    382.             int maxX = array.GetLength(0); int maxZ = array.GetLength(1); int numLayers = array.GetLength(2);
    383.             for (int x=0; x<maxX; x++)
    384.                 for (int z=0; z<maxZ; z++)
    385.             {
    386.                 float othersSum = 0;
    387.  
    388.                 for (int i=0; i<numLayers; i++)
    389.                 {
    390.                     if (i==pinnedLayer) continue;
    391.                     othersSum += array[x,z,i];
    392.                 }
    393.  
    394.                 float pinnedValue = array[x,z,pinnedLayer];
    395.                 if (pinnedValue > 1) { pinnedValue = 1; array[x,z,pinnedLayer] = 1; }
    396.                 if (pinnedValue < 0) { pinnedValue = 0; array[x,z,pinnedLayer] = 0; }
    397.  
    398.                 float othersTargetSum = 1 - pinnedValue;
    399.                 float factor = othersSum>0? othersTargetSum / othersSum : 0;
    400.  
    401.                 for (int i=0; i<numLayers; i++)
    402.                 {
    403.                     if (i==pinnedLayer) continue;
    404.                      array[x,z,i] *= factor;
    405.                 }
    406.             }
    407.  
    408.         }
    409.  
    410.         public static void DrawDebug (this Vector3 pos, float range=1, Color color=new Color())
    411.         {
    412.             if (color.a<0.001f) color = Color.white;
    413.             Debug.DrawLine(pos + new Vector3(-1,0,1)*range, pos + new Vector3(1,0,1)*range, color);
    414.             Debug.DrawLine(pos + new Vector3(1,0,1)*range, pos + new Vector3(1,0,-1)*range, color);
    415.             Debug.DrawLine(pos + new Vector3(1,0,-1)*range, pos + new Vector3(-1,0,-1)*range, color);
    416.             Debug.DrawLine(pos + new Vector3(-1,0,-1)*range, pos + new Vector3(-1,0,1)*range, color);
    417.         }
    418.  
    419.         public static void DrawDebug (this Rect rect, Color color=new Color())
    420.         {
    421.             if (color.a<0.001f) color = Color.white;
    422.             Debug.DrawLine(    new Vector3(rect.x,0,rect.y),                            new Vector3(rect.x+rect.width,0,rect.y),                color);
    423.             Debug.DrawLine(    new Vector3(rect.x+rect.width,0,rect.y),                new Vector3(rect.x+rect.width,0,rect.y+rect.height),    color);
    424.             Debug.DrawLine(    new Vector3(rect.x+rect.width,0,rect.y+rect.height),    new Vector3(rect.x,0,rect.y+rect.height),                color);
    425.             Debug.DrawLine(    new Vector3(rect.x,0,rect.y+rect.height),                new Vector3(rect.x,0,rect.y),                            color);
    426.         }
    427.  
    428.         public static void Resize (this Terrain terrain, int resolution, Vector3 size)
    429.         {
    430.             //setting resolution and THEN terrain size is too laggy
    431.             //so making this trick to resize terrain or change res
    432.             if ((terrain.terrainData.size-size).sqrMagnitude > 0.01f || terrain.terrainData.heightmapResolution != resolution)
    433.             {
    434.                 if (resolution <= 64) //brute force
    435.                 {
    436.                     terrain.terrainData.heightmapResolution = resolution;
    437.                     terrain.terrainData.size = new Vector3(size.x, size.y, size.z);
    438.                 }
    439.  
    440.                 else //setting res 64, re-scaling to 1/64, and then changing res
    441.                 {
    442.                     terrain.terrainData.heightmapResolution = 65;
    443.                     terrain.Flush(); //otherwise unity crushes without an error
    444.                     int resFactor = (resolution-1) / 64;
    445.                     terrain.terrainData.size = new Vector3(size.x/resFactor, size.y, size.z/resFactor);
    446.                     terrain.terrainData.heightmapResolution = resolution;
    447.                 }
    448.             }
    449.         }
    450.  
    451.         public static Transform AddChild (this Transform tfm, string name="", Vector3 offset=new Vector3())
    452.         {
    453.             GameObject go = new GameObject();
    454.             go.name = name;
    455.             go.transform.parent = tfm;
    456.             go.transform.localPosition = offset;
    457.  
    458.             return go.transform;
    459.         }
    460.  
    461.         public static T CreateObjectWithComponent<T> (string name="", Transform parent=null, Vector3 offset=new Vector3()) where T : MonoBehaviour
    462.         {
    463.             GameObject go = new GameObject();
    464.             if (name != null)
    465.             if (parent != null) go.transform.parent = parent.transform;
    466.             go.transform.localPosition = offset;
    467.          
    468.             return go.AddComponent<T>();
    469.         }
    470.  
    471.         public static IEnumerable<Vector3> CircleAround (this Vector3 center, float radius, int numPoints, bool endWhereStart=false)
    472.         {
    473.             float radianStep = 2*Mathf.PI / numPoints;
    474.             if (endWhereStart) numPoints++;
    475.             for (int i=0; i<numPoints; i++)
    476.             {
    477.                 float angle = i*radianStep;
    478.                 Vector3 dir = new Vector3( Mathf.Sin(angle), 0, Mathf.Cos(angle) );
    479.                 yield return center + dir*radius;
    480.             }
    481.         }
    482.  
    483.         public static float EvaluateMultithreaded (this AnimationCurve curve, float time)
    484.         {
    485.             int keyCount = curve.keys.Length;
    486.          
    487.             if (time <= curve.keys[0].time) return curve.keys[0].value;
    488.             if (time >= curve.keys[keyCount-1].time) return curve.keys[keyCount-1].value;
    489.  
    490.             int keyNum = 0;
    491.             for (int k=0; k<keyCount-1; k++)
    492.             {
    493.                 if (curve.keys[keyNum+1].time > time) break;
    494.                 keyNum++;
    495.             }
    496.          
    497.             float delta = curve.keys[keyNum+1].time - curve.keys[keyNum].time;
    498.             float relativeTime = (time - curve.keys[keyNum].time) / delta;
    499.  
    500.             float timeSq = relativeTime * relativeTime;
    501.             float timeCu = timeSq * relativeTime;
    502.    
    503.             float a = 2*timeCu - 3*timeSq + 1;
    504.             float b = timeCu - 2*timeSq + relativeTime;
    505.             float c = timeCu - timeSq;
    506.             float d = -2*timeCu + 3*timeSq;
    507.  
    508.             return a*curve.keys[keyNum].value + b*curve.keys[keyNum].outTangent*delta + c*curve.keys[keyNum+1].inTangent*delta + d*curve.keys[keyNum+1].value;
    509.         }
    510.  
    511.         public static bool IdenticalTo (this AnimationCurve c1, AnimationCurve c2)
    512.         {
    513.             if (c1==null || c2==null) return false;
    514.             if (c1.keys.Length != c2.keys.Length) return false;
    515.          
    516.             int numKeys = c1.keys.Length;
    517.             for (int k=0; k<numKeys; k++)
    518.             {
    519.                 if (c1.keys[k].time != c2.keys[k].time ||
    520.                     c1.keys[k].value != c2.keys[k].value ||
    521.                     c1.keys[k].inTangent != c2.keys[k].inTangent ||
    522.                     c1.keys[k].outTangent != c2.keys[k].outTangent)
    523.                         return false;
    524.             }
    525.  
    526.             return true;
    527.         }
    528.  
    529.         public static Keyframe[] Copy (this Keyframe[] src)
    530.         {
    531.             Keyframe[] dst = new Keyframe[src.Length];
    532.             for (int k=0; k<src.Length; k++)
    533.             {
    534.                 dst[k].value = src[k].value;
    535.                 dst[k].time = src[k].time;
    536.                 dst[k].inTangent = src[k].inTangent;
    537.                 dst[k].outTangent = src[k].outTangent;
    538.             }
    539.             return dst;
    540.         }
    541.  
    542.         public static AnimationCurve Copy (this AnimationCurve src)
    543.         {
    544.             AnimationCurve dst = new AnimationCurve();
    545.             dst.keys = src.keys.Copy();
    546.             return dst;
    547.         }
    548.  
    549.  
    550.         public static object CallStaticMethodFrom (string assembly, string type, string method, object[] parameters)
    551.         {
    552.             // editor assembly is Assembly-CSharp-Editor
    553.             // main is Assembly-CSharp
    554.  
    555.             Assembly a = Assembly.Load(assembly);
    556.             Type t = a.GetType(type);
    557.             return t.GetMethod(method).Invoke(null, parameters);
    558.         }
    559.  
    560.         public static void GetPropertiesFrom<T1,T2> (this T1 dst, T2 src) where T1:class where T2:class
    561.         {
    562.             PropertyInfo[] srcProps = src.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty);
    563.             PropertyInfo[] dstProps = src.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty);
    564.        
    565.             for (int sp=0; sp<srcProps.Length; sp++)
    566.                 for (int dp=0; dp<dstProps.Length; dp++)
    567.             {
    568.                 if (srcProps[sp].Name==dstProps[dp].Name && dstProps[dp].CanWrite)
    569.                     dstProps[dp].SetValue(dst, srcProps[sp].GetValue(src, null), null);
    570.             }
    571.          }
    572.  
    573.  
    574.         public static IEnumerable<FieldInfo> UsableFields (this Type type, bool nonPublic=false, bool includeStatic=false)
    575.         {
    576.             BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
    577.             if (nonPublic) flags = flags | BindingFlags.NonPublic;
    578.             if (includeStatic) flags = flags | BindingFlags.Static;
    579.  
    580.             FieldInfo[] fields = type.GetFields(flags);
    581.             for (int i=0; i<fields.Length; i++)
    582.             {
    583.                 FieldInfo field = fields[i];
    584.                 if (field.IsLiteral) continue; //leaving constant fields blank
    585.                 if (field.FieldType.IsPointer) continue; //skipping pointers (they make unity crash. Maybe require unsafe)
    586.                 if (field.IsNotSerialized) continue;
    587.  
    588.                 yield return field;
    589.             }
    590.         }
    591.  
    592.         public static IEnumerable<PropertyInfo> UsableProperties (this Type type, bool nonPublic=false, bool skipItems=true)
    593.         {
    594.             BindingFlags flags;
    595.             if (nonPublic) flags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance;
    596.             else flags = BindingFlags.Public | BindingFlags.Instance;
    597.  
    598.             PropertyInfo[] properties = type.GetProperties(flags);
    599.             for (int i=0;i<properties.Length;i++)
    600.             {
    601.                 PropertyInfo prop = properties[i];
    602.                 if (!prop.CanWrite) continue;
    603.                 if (skipItems && prop.Name=="Item") continue; //ignoring this[x]
    604.  
    605.                 yield return prop;
    606.             }
    607.         }
    608.  
    609.         public static IEnumerable<MemberInfo> UsableMembers (this Type type, bool nonPublic=false, bool skipItems=true)
    610.         {
    611.             BindingFlags flags;
    612.             if (nonPublic) flags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance;
    613.             else flags = BindingFlags.Public | BindingFlags.Instance;
    614.  
    615.             FieldInfo[] fields = type.GetFields(flags);
    616.             for (int i=0; i<fields.Length; i++)
    617.             {
    618.                 FieldInfo field = fields[i];
    619.                 if (field.IsLiteral) continue; //leaving constant fields blank
    620.                 if (field.FieldType.IsPointer) continue; //skipping pointers (they make unity crash. Maybe require unsafe)
    621.                 if (field.IsNotSerialized) continue;
    622.  
    623.                 yield return field;
    624.             }
    625.  
    626.             PropertyInfo[] properties = type.GetProperties(flags);
    627.             for (int i=0;i<properties.Length;i++)
    628.             {
    629.                 PropertyInfo prop = properties[i];
    630.                 if (!prop.CanWrite) continue;
    631.                 if (skipItems && prop.Name=="Item") continue; //ignoring this[x]
    632.  
    633.                 yield return prop;
    634.             }
    635.         }
    636.  
    637.         public static Component CopyComponent (Component src, GameObject go)
    638.         {
    639.             System.Type type = src.GetType();
    640.          
    641.             Component dst = go.GetComponent(src.GetType());
    642.             if (dst==null) dst = go.AddComponent(type);
    643.  
    644.             foreach (FieldInfo field in type.UsableFields(nonPublic:true)) field.SetValue(dst, field.GetValue(src));
    645.             foreach (PropertyInfo prop in type.UsableProperties(nonPublic:true))
    646.             {
    647.                 if (prop.Name == "name") continue;
    648.                 try {prop.SetValue(dst, prop.GetValue(src, null), null); }
    649.                 catch { }
    650.             }
    651.  
    652.             return dst;
    653.         }
    654.  
    655.         /*public static List<Type> GetAllChildTypes (this Type type)
    656.         {
    657.             List<Type> result = new List<Type>();
    658.      
    659.             Assembly assembly = Assembly.GetAssembly(type);
    660.             Type[] allTypes = assembly.GetTypes();
    661.             for (int i=0; i<allTypes.Length; i++)
    662.                 if (allTypes[i].IsSubclassOf(type)) result.Add(allTypes[i]); //nb: IsAssignableFrom will return derived classes
    663.  
    664.             return result;
    665.         }*/
    666.  
    667.         public static IEnumerable<Type> Subtypes (this Type parent)
    668.         {
    669.             Assembly assembly = Assembly.GetAssembly(parent);  //Assembly[] assembleys = AppDomain.CurrentDomain.GetAssemblies();
    670.             Type[] types = assembly.GetTypes();
    671.             for (int t=0; t<types.Length; t++)
    672.             {
    673.                 Type type = types[t];
    674.                 if (type.IsSubclassOf(parent) && !type.IsInterface && !type.IsAbstract) yield return type;
    675.             }
    676.         }
    677.  
    678.         public static T GetAddComponent<T> (this GameObject go) where T:Component
    679.         {
    680.             T c = go.GetComponent<T>();
    681.             if (c==null) c = go.AddComponent<T>();
    682.             return c;
    683.         }
    684.  
    685.         public static void ReflectionReset<T> (this T obj)
    686.         {
    687.             Type type = obj.GetType();
    688.             T empty = (T)Activator.CreateInstance(type);
    689.          
    690.             foreach (FieldInfo field in type.UsableFields(nonPublic:true)) field.SetValue(obj, field.GetValue(empty));
    691.             foreach (PropertyInfo prop in type.UsableProperties(nonPublic:true)) prop.SetValue(obj, prop.GetValue(empty,null), null);
    692.         }
    693.  
    694.         public static T ReflectionCopy<T> (this T obj)
    695.         {
    696.             Type type = obj.GetType();
    697.             T copy = (T)Activator.CreateInstance(type);
    698.  
    699.             foreach (FieldInfo field in type.UsableFields(nonPublic:true)) field.SetValue(copy, field.GetValue(obj));
    700.             foreach (PropertyInfo prop in type.UsableProperties(nonPublic:true)) prop.SetValue(copy, prop.GetValue(obj,null), null);
    701.  
    702.             return copy;
    703.         }
    704.  
    705.         public static void ReflectionCopyFrom<T> (this T dst, object src)
    706.         {
    707.             Type dstType = dst.GetType();
    708.             Type srcType = src.GetType();
    709.  
    710.             foreach (FieldInfo dstField in dstType.UsableFields(nonPublic:true))
    711.             {
    712.                 FieldInfo srcField = srcType.GetField(dstField.Name);
    713.                 if (srcField != null && srcField.FieldType == dstField.FieldType) dstField.SetValue(dst, srcField.GetValue(src));
    714.             }
    715.  
    716.  
    717.             //foreach (PropertyInfo prop in type.UsableProperties(nonPublic:true)) prop.SetValue(copy, prop.GetValue(obj,null), null);
    718.         }
    719.  
    720.  
    721.         public static object Parse (this string s, Type t)
    722.         {
    723.             //better than creating xml serializer each time. Reverse to "ToString" function
    724.  
    725.             if (s.Contains("=")) s = s.Remove(0, s.IndexOf('=')+1); //removing everything before =
    726.  
    727.             object r = null;
    728.             try
    729.             {
    730.                 if (t == typeof(float))
    731.                 {
    732.                     float f;
    733.                     if (float.TryParse(s, NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture.NumberFormat, out f))
    734.                     {
    735.                         r = f;
    736.                     }
    737.                     else if (float.TryParse(s, out f))
    738.                     {
    739.                         r = f;
    740.                     }
    741.                     else if (float.TryParse(s, NumberStyles.Float, System.Globalization.CultureInfo.CurrentCulture.NumberFormat, out f))
    742.                     {
    743.                         r = f;
    744.                     }
    745.                 }
    746.                 else if (t == typeof(int))
    747.                 {
    748.                     r = int.Parse(s);
    749.                 }
    750.             else if (t == typeof(bool)) r = bool.Parse(s);
    751.             else if (t == typeof(string)) r = s;
    752.             else if (t == typeof(byte)) r = byte.Parse(s);
    753.             else if (t == typeof(short)) r = short.Parse(s);
    754.             else if (t == typeof(long)) r = long.Parse(s);
    755.             else if (t == typeof(double)) r = double.Parse(s);
    756.             else if (t == typeof(char)) r = char.Parse(s);
    757.             else if (t == typeof(decimal)) r = decimal.Parse(s);
    758.             else if (t == typeof(sbyte)) r = sbyte.Parse(s);
    759.             else if (t == typeof(uint)) r = uint.Parse(s);
    760.             else if (t == typeof(ulong)) r = ulong.Parse(s);
    761.             else return null;
    762.             }
    763.             catch(Exception x)
    764.             {
    765.                 Debug.LogError(x + ": " + s);
    766.             }
    767.             return r;
    768.         }
    769.  
    770.         public static float GetInterpolated (this float[,] array, float x, float z)
    771.         {
    772.             int sizeX = array.GetLength(0);
    773.             int sizeY = array.GetLength(1);
    774.          
    775.             int px = (int)x;
    776.             int nx = px+1; if (nx >= sizeX) nx = sizeX-1;
    777.  
    778.             int py = (int)z;
    779.             int ny = py+1; if (ny >= sizeY) ny = sizeY-1;
    780.  
    781.             float percentX = x-px;
    782.             float percentZ = z-py;
    783.  
    784.             float val_fy = array[px,py]*(1-percentX) + array[nx,py]*percentX;
    785.             float val_cy = array[px,ny]*(1-percentX) + array[nx,ny]*percentX;
    786.             float val = val_fy*(1-percentZ) + val_cy*percentZ;
    787.  
    788.             return val;
    789.         }
    790.  
    791.         public static bool isPlaying
    792.         {get{
    793.             #if UNITY_EDITOR
    794.                 return UnityEditor.EditorApplication.isPlaying; //if not playing
    795.             #else
    796.                 return true;
    797.             #endif
    798.         }}
    799.  
    800.         public static bool IsEditor ()
    801.         {
    802.             #if UNITY_EDITOR
    803.                 return
    804.                     !UnityEditor.EditorApplication.isPlaying; //if not playing
    805.                     //(UnityEditor.EditorWindow.focusedWindow != null && UnityEditor.EditorWindow.focusedWindow.GetType() == System.Type.GetType("UnityEditor.GameView,UnityEditor")) //if game view is focused
    806.                     //UnityEditor.SceneView.lastActiveSceneView == UnityEditor.EditorWindow.focusedWindow; //if scene view is focused
    807.             #else
    808.                 return false;
    809.             #endif
    810.         }
    811.  
    812.         public static bool IsSelected (Transform transform)
    813.         {
    814.             #if UNITY_EDITOR
    815.                 return UnityEditor.Selection.activeTransform == transform;
    816.             #else
    817.                 return false;
    818.             #endif
    819.         }
    820.  
    821.         public static Camera GetMainCamera ()
    822.         {
    823.             if (IsEditor())
    824.             {
    825.                 #if UNITY_EDITOR
    826.                 if (UnityEditor.SceneView.lastActiveSceneView==null) return null;
    827.                 else return UnityEditor.SceneView.lastActiveSceneView.camera;
    828.                 #else
    829.                 return null;
    830.                 #endif
    831.             }
    832.             else
    833.             {
    834.                 Camera mainCam = Camera.main;
    835.                 if (mainCam==null) mainCam = GameObject.FindObjectOfType<Camera>(); //in case it was destroyed or something
    836.                 return mainCam;
    837.             }
    838.         }
    839.  
    840.         public static Vector3[] GetCamPoses (bool genAroundMainCam=true, string genAroundTag=null, Vector3[] camPoses=null)
    841.         {
    842.             if (IsEditor())
    843.             {
    844.                 #if UNITY_EDITOR
    845.                 if (UnityEditor.SceneView.lastActiveSceneView==null || UnityEditor.SceneView.lastActiveSceneView.camera==null) return new Vector3[0]; //this happens right after script compile
    846.                 if (camPoses==null || camPoses.Length!=1) camPoses = new Vector3[1];
    847.                 camPoses[0] = UnityEditor.SceneView.lastActiveSceneView.camera.transform.position;
    848.                 #else
    849.                 camPoses = new Vector3[1];
    850.                 #endif
    851.             }
    852.             else
    853.             {
    854.                 //finding objects with tag
    855.                 GameObject[] taggedObjects = null;
    856.                 if (genAroundTag!=null && genAroundTag.Length!=0) taggedObjects = GameObject.FindGameObjectsWithTag(genAroundTag);
    857.  
    858.                 //calculating cams array length and rescaling it
    859.                 int camPosesLength = 0;
    860.                 if (genAroundMainCam) camPosesLength++;
    861.                 if (taggedObjects !=null) camPosesLength += taggedObjects.Length;
    862.              
    863.                 if (camPosesLength == 0) { Debug.LogError("No Main Camera to deploy"); return new Vector3[0]; }
    864.                 if (camPoses == null || camPosesLength != camPoses.Length) camPoses = new Vector3[camPosesLength];
    865.              
    866.                 //filling cams array
    867.                 int counter = 0;
    868.                 if (genAroundMainCam)
    869.                 {
    870.                     Camera mainCam = Camera.main;
    871.                     if (mainCam==null) mainCam = GameObject.FindObjectOfType<Camera>(); //in case it was destroyed or something
    872.                     camPoses[0] = mainCam.transform.position;
    873.                     counter++;
    874.                 }
    875.                 if (taggedObjects != null)
    876.                     for (int i=0; i<taggedObjects.Length; i++) camPoses[i+counter] = taggedObjects[i].transform.position;
    877.             }
    878.  
    879.             return camPoses;      
    880.         }
    881.  
    882.         public static Vector2 GetMousePosition ()
    883.         {
    884.             if (IsEditor())
    885.             {
    886.                 #if UNITY_EDITOR
    887.                 UnityEditor.SceneView sceneview = UnityEditor.SceneView.lastActiveSceneView;
    888.                 if (sceneview==null || sceneview.camera==null || Event.current==null) return Vector2.zero;
    889.                 Vector2 mousePos = Event.current.mousePosition;
    890.                 mousePos = new Vector2(mousePos.x/sceneview.camera.pixelWidth, mousePos.y/sceneview.camera.pixelHeight);
    891.                 #if UNITY_5_4_OR_NEWER  
    892.                 mousePos *= UnityEditor.EditorGUIUtility.pixelsPerPoint;
    893.                 #endif
    894.                 mousePos.y = 1 - mousePos.y;
    895.                 return mousePos;
    896.                 #else
    897.                 return Input.mousePosition;
    898.                 #endif
    899.             }
    900.             else return Input.mousePosition;
    901.         }
    902.  
    903.         public static void GizmosDrawFrame (Vector3 center, Vector3 size, int resolution, float level = 30)
    904.         {
    905.             Vector3 offset = center-size/2;
    906.          
    907.             Vector3 prevP1=Vector3.zero; Vector3 prevP2=Vector3.zero;
    908.             for (float x=0; x < size.x+0.0001f; x += 1f*size.x/resolution)
    909.             {
    910.                 RaycastHit hit = new RaycastHit();
    911.  
    912.                 Vector3 p1 = new Vector3(offset.x+x, 10000, offset.z);
    913.                 if (Physics.Raycast(new Ray(p1, Vector3.down*20000), out hit, 20000)) p1.y = hit.point.y;
    914.                 else if (Physics.Raycast(new Ray(p1+new Vector3(1,0,0), Vector3.down*20000), out hit, 20000)) p1.y = hit.point.y;
    915.                 else if (Physics.Raycast(new Ray(p1+new Vector3(-1,0,0), Vector3.down*20000), out hit, 20000)) p1.y = hit.point.y;
    916.                 else if (Physics.Raycast(new Ray(p1+new Vector3(0,0,1), Vector3.down*20000), out hit, 20000)) p1.y = hit.point.y;
    917.                 else if (Physics.Raycast(new Ray(p1+new Vector3(0,0,-1), Vector3.down*20000), out hit, 20000)) p1.y = hit.point.y;
    918.                 else p1.y = level;
    919.                 if (x>0.0001f) Gizmos.DrawLine(prevP1, p1);
    920.                 prevP1 = p1;
    921.  
    922.                 Vector3 p2 = new Vector3(offset.x+x, 10000, offset.z+size.z);
    923.                 if (Physics.Raycast(new Ray(p2, Vector3.down*20000), out hit, 20000)) p2.y = hit.point.y;
    924.                 else if (Physics.Raycast(new Ray(p2+new Vector3(1,0,0), Vector3.down*20000), out hit, 20000)) p2.y = hit.point.y;
    925.                 else if (Physics.Raycast(new Ray(p2+new Vector3(-1,0,0), Vector3.down*20000), out hit, 20000)) p2.y = hit.point.y;
    926.                 else if (Physics.Raycast(new Ray(p2+new Vector3(0,0,1), Vector3.down*20000), out hit, 20000)) p2.y = hit.point.y;
    927.                 else if (Physics.Raycast(new Ray(p2+new Vector3(0,0,-1), Vector3.down*20000), out hit, 20000)) p2.y = hit.point.y;
    928.                 else p2.y = level;
    929.                 if (x>0.0001f) Gizmos.DrawLine(prevP2, p2);
    930.                 prevP2 = p2;
    931.             }
    932.  
    933.             for (float z=0; z < size.z+0.0001f; z += 1f*size.z/resolution)
    934.             {
    935.                 RaycastHit hit = new RaycastHit();
    936.  
    937.                 Vector3 p1 = new Vector3(offset.x, 10000, offset.z+z);
    938.                 if (Physics.Raycast(new Ray(p1, Vector3.down*20000), out hit, 20000)) p1.y = hit.point.y;
    939.                 else if (Physics.Raycast(new Ray(p1+new Vector3(1,0,0), Vector3.down*20000), out hit, 20000)) p1.y = hit.point.y;
    940.                 else if (Physics.Raycast(new Ray(p1+new Vector3(-1,0,0), Vector3.down*20000), out hit, 20000)) p1.y = hit.point.y;
    941.                 else if (Physics.Raycast(new Ray(p1+new Vector3(0,0,1), Vector3.down*20000), out hit, 20000)) p1.y = hit.point.y;
    942.                 else if (Physics.Raycast(new Ray(p1+new Vector3(0,0,-1), Vector3.down*20000), out hit, 20000)) p1.y = hit.point.y;
    943.                 else p1.y = level;
    944.                 if (z>0.0001f) Gizmos.DrawLine(prevP1, p1);
    945.                 prevP1 = p1;
    946.  
    947.                 Vector3 p2 = new Vector3(offset.x+size.x, 10000, offset.z+z);
    948.                 if (Physics.Raycast(new Ray(p2, Vector3.down*20000), out hit, 20000)) p2.y = hit.point.y;
    949.                 else if (Physics.Raycast(new Ray(p2+new Vector3(1,0,0), Vector3.down*20000), out hit, 20000)) p2.y = hit.point.y;
    950.                 else if (Physics.Raycast(new Ray(p2+new Vector3(-1,0,0), Vector3.down*20000), out hit, 20000)) p2.y = hit.point.y;
    951.                 else if (Physics.Raycast(new Ray(p2+new Vector3(0,0,1), Vector3.down*20000), out hit, 20000)) p2.y = hit.point.y;
    952.                 else if (Physics.Raycast(new Ray(p2+new Vector3(0,0,-1), Vector3.down*20000), out hit, 20000)) p2.y = hit.point.y;
    953.                 else p2.y = level;
    954.                 if (z>0.0001f) Gizmos.DrawLine(prevP2, p2);
    955.                 prevP2 = p2;
    956.             }
    957.         }
    958.  
    959.         public static void Planar (this Mesh mesh, float size, int resolution)
    960.         {
    961.             float step = size / resolution;
    962.  
    963.             Vector3[] verts = new Vector3[(resolution+1)*(resolution+1)];
    964.             Vector2[] uvs = new Vector2[verts.Length];
    965.             int[] tris = new int[resolution*resolution*2*3];
    966.  
    967.             int vertCounter = 0;
    968.             int triCounter = 0;
    969.             for (float x=0; x<size+0.001f; x+=step) //including max
    970.                 for (float z=0; z<size+0.001f; z+=step)
    971.             {
    972.                 verts[vertCounter] = new Vector3(x,0,z);
    973.                 uvs[vertCounter] = new Vector2(x/size, z/size);
    974.  
    975.                 if (x>0.001f && z>0.001f)
    976.                 {
    977.                     tris[triCounter] = vertCounter-(resolution+1);        tris[triCounter+1] = vertCounter-1;                    tris[triCounter+2] = vertCounter-resolution-2;
    978.                     tris[triCounter+3] = vertCounter-1;                    tris[triCounter+4] = vertCounter-(resolution+1);    tris[triCounter+5] = vertCounter;
    979.                     triCounter += 6;
    980.                 }
    981.  
    982.                 vertCounter++;
    983.             }
    984.  
    985.             mesh.Clear();
    986.             mesh.vertices = verts;
    987.             mesh.uv = uvs;
    988.             mesh.triangles = tris;
    989.         }
    990.  
    991.  
    992.         public static T Save<T> (this T data, string label="Save Data as Unity Asset", string fileName="Data.asset", UnityEngine.Object undoObj=null, string undoName="Save Data") where T : ScriptableObject, ICloneable
    993.         {
    994.             #if UNITY_EDITOR
    995.             //finding path
    996.             string path= UnityEditor.EditorUtility.SaveFilePanel(label, "Assets", fileName, "asset");
    997.             if (path==null || path.Length==0) return data;
    998.  
    999.             //releasing data on re-save
    1000.             T newData = data;
    1001.             if (UnityEditor.AssetDatabase.Contains(data)) newData = (T)data.Clone();
    1002.  
    1003.             //saving
    1004.             path = path.Replace(Application.dataPath, "Assets");
    1005.             if (undoObj != null) UnityEditor.Undo.RecordObject(undoObj, undoName); //TODO: undo is actually not recordered because the new data is not assigned
    1006.             //undoObj.setDirty = !undoObj.setDirty;
    1007.             UnityEditor.AssetDatabase.CreateAsset(newData, path);
    1008.             if (undoObj != null) UnityEditor.EditorUtility.SetDirty(undoObj);
    1009.  
    1010.             return newData;
    1011.             #else
    1012.             return data;
    1013.             #endif
    1014.         }
    1015.  
    1016.         /*public static object Invoke (object target, string methodName, params object[] paramArray)
    1017.         {
    1018.             Type type = target.GetType();
    1019.             MethodInfo methodInfo = type.GetMethod(methodName);
    1020.             return methodInfo.Invoke(target, paramArray);
    1021.         }
    1022.  
    1023.         public static object StaticInvoke (string className, string methodName, params object[] paramArray)
    1024.         {
    1025.             Type type = Type.GetType(className);
    1026.             MethodInfo methodInfo = type.GetMethod(methodName, BindingFlags.Public | BindingFlags.Static);
    1027.             return methodInfo.Invoke(null, new object[] { paramArray });
    1028.         }*/
    1029.  
    1030.         public static string LogBinary (this int src)
    1031.         {
    1032.             string result = "";
    1033.             for (int i=0; i<32; i++)
    1034.             {
    1035.                 if (i%4==0) result=" "+result;
    1036.                 result = (src & 0x1) + result;
    1037.              
    1038.  
    1039.                 src = src >> 1;
    1040.             }
    1041.             return result;
    1042.         }
    1043.  
    1044.         public static string ToStringArray<T> (this T[] array)
    1045.         {
    1046.             string result = "";
    1047.             for (int i=0; i<array.Length; i++)
    1048.             {
    1049.                 result += array[i].ToString();
    1050.                 if (i!=array.Length-1) result += CustomSerialization.Separator;
    1051.             }
    1052.             return result;
    1053.         }
    1054.  
    1055.         public static Color[] ToColors (this Vector4[] src)
    1056.         {
    1057.             Color[] dst = new Color[src.Length];
    1058.             for (int i=0; i<src.Length; i++)
    1059.                 dst[i] = src[i];
    1060.             return dst;
    1061.         }
    1062.  
    1063.     }//extensions
    1064. }//namespace
    1065.  
     

    Attached Files:

    Funkeys likes this.
  15. Hazkin

    Hazkin

    Joined:
    Sep 11, 2012
    Posts:
    2
    Maybe my solution helps you (prev post)
     
  16. Wright

    Wright

    Joined:
    Feb 26, 2013
    Posts:
    1,442