void OnSceneGUI()
    {
        ProceduralWormGear gear = (ProceduralWormGear)target;

        if (gear.points == null)
        {
            return;
        }

        Transform gearTransform = gear.transform;
        Vector3   baseRadius    = new Vector3(gear.df * gearTransform.localScale.x, 0f, 0f);
        Transform t             = gearTransform;
        float     handelScale   = t.localScale.x;

        while (t.parent != null)
        {
            t            = t.parent;
            handelScale *= t.localScale.x;
        }

        Undo.RecordObject(gear, "TM PointMove");

        Handles.Disc(Quaternion.identity, gearTransform.position, gearTransform.up, baseRadius.x, true, 0f);
        int partCount = gear.prefs.bodyParts + gear.prefs.teethParts;

        for (int i = 0; i < (symmetric ? partCount + 1 : gear.points.Length - 3); i++)
        {
            if (i != gear.prefs.bodyParts)
            {
                string  str      = "";
                Vector3 oldPoint = gearTransform.TransformPoint(baseRadius + gear.points[i].offset);
                if (i > partCount)
                {
                    Handles.color = colors[i - partCount + 1];
                    str           = (i - partCount).ToString();
                }
                else if (i > gear.prefs.bodyParts)
                {
                    Handles.color = colors[i - gear.prefs.bodyParts + 1];
                    str           = (i - gear.prefs.bodyParts).ToString();
                }
                else
                {
                    Handles.color = colors[i + 2];
                    str           = (i + 1).ToString();
                }

                Vector3 newPoint = Handles.FreeMoveHandle(oldPoint, Quaternion.identity, handelScale * 0.15f, pointSnap, Handles.DotCap);
                if (oldPoint != newPoint)
                {
                    gear.points[i].offset = gearTransform.InverseTransformPoint(newPoint - baseRadius);
                    if (GUI.changed)
                    {
                        gear.UpdateGear();
                    }
                }
                Handles.Label(oldPoint, new GUIContent(str), EditorStyles.boldLabel);
            }
        }
    }
    private void CreatePrefab(bool _delete, bool _inst)
    {
        ProceduralWormGear g      = (ProceduralWormGear)target;
        MeshFilter         filter = (MeshFilter)g.GetComponent(typeof(MeshFilter));
        GameObject         newGO  = new GameObject();

        newGO.name = g.name;
        newGO.AddComponent(typeof(MeshFilter));
        newGO.AddComponent(typeof(MeshRenderer));
        SaveMesh();
        MeshFilter f = (MeshFilter)newGO.GetComponent(typeof(MeshFilter));

        f.sharedMesh = Mesh.Instantiate(filter.sharedMesh) as Mesh;
        MeshRenderer r  = (MeshRenderer)newGO.GetComponent(typeof(MeshRenderer));
        MeshRenderer r2 = (MeshRenderer)g.GetComponent(typeof(MeshRenderer));

        r.sharedMaterials = r2.sharedMaterials;
                #pragma warning disable 618
        Object prefab = EditorUtility.CreateEmptyPrefab(path + "/" + g.name + ".prefab");
        EditorUtility.ReplacePrefab(g.gameObject, prefab, ReplacePrefabOptions.ConnectToPrefab);
                #pragma warning restore 618
        if (!_delete)
        {
            if (_inst)
            {
                GameObject go = (GameObject)Instantiate(g.gameObject, g.gameObject.transform.position, g.gameObject.transform.rotation);
                go.name = go.name.Replace("(Clone)", "");
            }
            DestroyImmediate(newGO, true);
        }
    }
 void OnEnable()
 {
     if (Selection.activeGameObject != null)
     {
         gears  = new SerializedObject(targets);
         points = gears.FindProperty("points");
         prefs  = gears.FindProperty("prefs");
         ProceduralWormGear g = (ProceduralWormGear)target;
         if (target != null)
         {
             if (g.points != null)
             {
                 colorPalette = g.points[g.prefs.bodyParts].uvOffX;
             }
         }
     }
     this.currentMenu = MenuPrefs;
     SetColorPalette();
 }
    private void SaveMesh()
    {
        ProceduralWormGear g = (ProceduralWormGear)target;
        string             meshPrefabPath = "";

        meshPrefabPath = path + bSlash + g.name + ".asset";
        MeshFilter filter = (MeshFilter)g.GetComponent(typeof(MeshFilter));

        filter.sharedMesh.hideFlags = HideFlags.None;
        Unwrapping.GenerateSecondaryUVSet(filter.sharedMesh);
        Mesh mesh = Mesh.Instantiate(filter.sharedMesh) as Mesh;

        if (!System.IO.File.Exists(Application.dataPath.Replace("Assets", path) + bSlash + g.name + ".asset"))
        {
            AssetDatabase.CreateAsset(mesh, meshPrefabPath);
        }
        else
        {
            AssetDatabase.SaveAssets();
        }
        filter.sharedMesh.hideFlags = HideFlags.HideAndDontSave;
    }
    private void MenuOpt()
    {
        Color gCol = GUI.color;

        MenuButtons(3);
        ProceduralWormGear g = (ProceduralWormGear)target;

        GUI.color = gCol;
        g.name    = EditorGUILayout.TextField("Name", g.name.Replace("(Clone)", ""), GUILayout.Width(300), GUILayout.Height(14));
        path      = EditorGUILayout.TextField("Path", path, GUILayout.Width(300), GUILayout.Height(14));
        EditorGUILayout.Separator();
        EditorGUILayout.BeginHorizontal();
        bool noPath = false;

        if (System.IO.File.Exists(Application.dataPath.Replace("Assets", path) + bSlash + g.name + ".asset"))
        {
            GUI.color = Color.red;
            InfoField("  File exist or mesh already saved.", Color.red, 205f);
            EditorGUILayout.Space();
        }
        else
        if (System.IO.Directory.Exists(Application.dataPath.Replace("Assets", path)) && path != "")
        {
            EditorGUILayout.LabelField("Save mesh to Asset folder");
        }
        else
        {
            GUI.color = Color.red;
            InfoField("  Path does not exist.", Color.red, 150f);
            EditorGUILayout.Space();
            noPath = true;
        }

        GUILayoutOption buttonWidth = GUILayout.Width(120);

        if (GUILayout.Button("Save Mesh", buttonWidth))
        {
            if (GUI.color != Color.red)
            {
                SaveMesh();
            }
        }
        EditorGUILayout.EndHorizontal();
        EditorGUILayout.Separator();
        if (GUI.color == Color.red)
        {
            EditorGUILayout.Separator();
        }
        if (!noPath)
        {
            GUI.color = gCol;
        }
        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Create a prefab in Assets folder");
        if (GUILayout.Button("Create Prefab", buttonWidth))
        {
            if (GUI.color != Color.red)
            {
                CreatePrefab(false, false);
            }
        }
        EditorGUILayout.EndHorizontal();
        EditorGUILayout.Separator();
        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Duplicate and make this to prefab");
        if (GUILayout.Button("Duplicate", buttonWidth))
        {
            if (GUI.color != Color.red)
            {
                CreatePrefab(false, true);
            }
        }
        EditorGUILayout.EndHorizontal();
        EditorGUILayout.Separator();
        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Copy as object and this to prefab");
        if (GUILayout.Button("Copy Object", buttonWidth))
        {
            if (GUI.color != Color.red)
            {
                CreatePrefab(true, true);
            }
        }
        EditorGUILayout.EndHorizontal();
        EditorGUILayout.Separator();
        EditorGUILayout.Separator();
        EditorGUILayout.LabelField("Preferences:");
        GUI.color = gCol;
        EditorGUILayout.Separator();
        if (targets.Length < 2)
        {
            GUI.color = Color.white;
            if (g.points[g.prefs.bodyParts].uvOffX == 0)
            {
                g.points[g.prefs.bodyParts].uvOffX = defaultColorPalette;
            }
            colorPalette = Mathf.Clamp(Mathf.FloorToInt(SliderFloatField("Color Palette", g.points[g.prefs.bodyParts].uvOffX, -1, 200f)), 1, 200);
            if (g.points[g.prefs.bodyParts].uvOffX != colorPalette)
            {
                SetColorPalette();
                g.points[g.prefs.bodyParts].uvOffX = colorPalette;
            }
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.Space();
            for (int i = 2; i < 20; i++)
            {
                InfoField("", newColor(i), 10f);
            }
            EditorGUILayout.Space();
            EditorGUILayout.EndHorizontal();
        }
        else
        {
            EditorGUILayout.LabelField("(Multi Object Editing not supported for preferences.)");
        }
        EditorGUILayout.BeginHorizontal();
        GUI.color = Color.gray;
        EditorGUILayout.Space();
        if (GUILayout.Button("?", GUILayout.Width(20)))
        {
            showOptInfo = !showOptInfo;
        }
        EditorGUILayout.EndHorizontal();
        if (showOptInfo)
        {
            ShowOptInfo();
        }
        EditorGUILayout.Separator();
    }
    private void MenuMat()
    {
        MenuButtons(1);
        ProceduralWormGear g = (ProceduralWormGear)target;
        SerializedProperty
            bodyParts        = prefs.FindPropertyRelative("bodyParts"),
            teethParts       = prefs.FindPropertyRelative("teethParts"),
            calculateTangens = prefs.FindPropertyRelative("tangens");

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.PropertyField(calculateTangens, new GUIContent("Calculate Tangens", "Check this, only if shader needs them.\nCalculate tangens needs more time on CPU."));
        EditorGUILayout.EndHorizontal();
        EditorGUILayout.LabelField("Textures in Renderer:");
        EditorGUILayout.BeginHorizontal();
        int matCount = 0;

        foreach (Material m in g.GetComponent <Renderer>().sharedMaterials)
        {
            GUILayout.Label(matCount.ToString(), GUILayout.MaxWidth(10f));
            if (m != null)
            {
                GUILayout.Label(m.mainTexture, GUILayout.Width(50f), GUILayout.Height(50f));
            }
            else
            {
                EditorGUILayout.EndHorizontal();
                EditorGUILayout.LabelField("There is something wrong in the Renderer.");
                EditorGUILayout.LabelField("Check if there is a Material missing or delete empty array elements.");
                return;
            }
            matCount++;
        }
        EditorGUILayout.EndHorizontal();
        MenuButtons_Parts(currenPartMenu);
        GUILayoutOption labelHeight = GUILayout.Height(40f);

        int[] indexes = GetStartEndPartIndex(bodyParts.intValue, teethParts.intValue, 0);
        for (int i = indexes[0]; i < indexes[1]; i++)
        {
            if (i == points.arraySize - 2)
            {
                EditorGUILayout.LabelField("Cap Body");
            }
            else
            if (i == points.arraySize - 1)
            {
                EditorGUILayout.LabelField("Cap Tooth");
            }
            SerializedProperty
                point = points.GetArrayElementAtIndex(i),
                mat   = point.FindPropertyRelative("mat");
            if (mat == null)
            {
                break;
            }
            if (mat.intValue > g.GetComponent <Renderer>().sharedMaterials.Length - 1)
            {
                mat.intValue = 0;
            }
            EditorGUILayout.BeginHorizontal();
            InfoField(" " + indexes[2].ToString(), colors[++indexes[2]], 15f);
            GUILayout.Label(g.GetComponent <Renderer>().sharedMaterials[mat.intValue].mainTexture, GUILayout.Width(40f), labelHeight);
            GUILayout.Label(g.GetComponent <Renderer>().sharedMaterials[mat.intValue].name, GUILayout.Width(120f), labelHeight);
            for (int j = 0; j < matCount; j++)
            {
                if (GUILayout.Button(j.ToString(), GUILayout.MaxWidth(35f)))
                {
                    mat.intValue = j;
                }
            }
            EditorGUILayout.LabelField(" ");
            EditorGUILayout.EndHorizontal();
        }
        EditorGUILayout.Separator(); EditorGUILayout.Separator();
        EditorGUILayout.BeginHorizontal();
        ShowInfoField();
        GUI.color = Color.gray;
        EditorGUILayout.LabelField(" ");
        if (GUILayout.Button("?", GUILayout.Width(20)))
        {
            showMatInfo = !showMatInfo;
        }
        EditorGUILayout.EndHorizontal();
        if (showMatInfo)
        {
            ShowMatInfo();
        }
        EditorGUILayout.Separator();
    }