void OnEnable()
    {
        Enabling = true;

        /*foreach(Toggle tog in Toggles){
         *      tog.isOn = false;
         * }*/
        Toggles[PlayerPrefs.GetInt("Symmetry", 0)].isOn = true;
        AngleSlider.SetValue(SymmetryWindow.GetRotationSym());
        ToleranceInput.SetValue(GetTolerance());
        Enabling = false;
    }
    public void SliderChange()
    {
        if (AngleSlider.intValue != SymmetryWindow.GetRotationSym())
        {
            int value = AngleSlider.intValue;
            if (value < 2)
            {
                value = 2;
            }
            else if (value > 16)
            {
                value = 16;
            }

            PlayerPrefs.SetInt("SymmetryAngleCount", value);
            InvokeChange();
        }
    }
    public void GenerateSymmetry()
    {
        LastSym = SymmetryWindow.GetSymmetryType();
        //LastTolerance = SymmetryWindow.GetTolerance();

        for (int i = 0; i < PlacementSymmetry.Length; i++)
        {
            Destroy(PlacementSymmetry[i]);
        }

        switch (LastSym)
        {
        case 1:                 // X
            SymmetryMatrix    = new Matrix4x4[1];
            InvertRotation    = new bool[1];
            SymmetryMatrix[0] = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(-1, 1, 1));
            InvertRotation[0] = true;
            break;

        case 2:                 // Z
            SymmetryMatrix    = new Matrix4x4[1];
            InvertRotation    = new bool[1];
            SymmetryMatrix[0] = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(1, 1, -1));
            InvertRotation[0] = true;
            break;

        case 3:                 // XZ
            SymmetryMatrix    = new Matrix4x4[1];
            InvertRotation    = new bool[1];
            SymmetryMatrix[0] = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(-1, 1, -1));
            InvertRotation[0] = false;
            break;

        case 4:                 // X Z XZ
            SymmetryMatrix    = new Matrix4x4[3];
            InvertRotation    = new bool[3];
            SymmetryMatrix[0] = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(-1, 1, 1));
            InvertRotation[0] = true;

            SymmetryMatrix[1] = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(1, 1, -1));
            InvertRotation[1] = true;

            SymmetryMatrix[2] = SymmetryMatrix[0] * SymmetryMatrix[1];
            InvertRotation[2] = false;
            //SymmetryMatrix[2] = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(-1, 1, -1));
            break;

        case 5:                // Diagonal1
            SymmetryMatrix    = new Matrix4x4[1];
            InvertRotation    = new bool[1];
            SymmetryMatrix[0] = Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(Vector3.up * 90), new Vector3(-1, 1, 1));
            InvertRotation[0] = true;
            break;

        case 6:                 // Diagonal 2
            SymmetryMatrix    = new Matrix4x4[1];
            InvertRotation    = new bool[1];
            SymmetryMatrix[0] = Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(Vector3.down * 90), new Vector3(-1, 1, 1));
            InvertRotation[0] = true;
            break;

        case 7:                 // Diagonal 3
            SymmetryMatrix    = new Matrix4x4[3];
            InvertRotation    = new bool[3];
            SymmetryMatrix[0] = Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(Vector3.up * 90), new Vector3(-1, 1, 1));
            InvertRotation[0] = true;
            SymmetryMatrix[1] = Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(Vector3.down * 90), new Vector3(-1, 1, 1));
            InvertRotation[1] = true;
            SymmetryMatrix[2] = SymmetryMatrix[0] * SymmetryMatrix[1];
            InvertRotation[2] = false;
            break;

        case 8:                 // Rotation
            int   RotCount = SymmetryWindow.GetRotationSym() - 1;
            float angle    = 360.0f / (float)(RotCount + 1);
            SymmetryMatrix = new Matrix4x4[RotCount];
            InvertRotation = new bool[RotCount];

            for (int i = 0; i < RotCount; i++)
            {
                SymmetryMatrix[i] = Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(Vector3.up * (angle * (i + 1))), Vector3.one);
                InvertRotation[i] = false;
            }
            break;

        default:
            SymmetryMatrix = new Matrix4x4[0];
            break;
        }

        PlacementSymmetry = new GameObject[SymmetryMatrix.Length];

        for (int i = 0; i < PlacementSymmetry.Length; i++)
        {
            PlacementSymmetry[i] = Instantiate(PlacementObject) as GameObject;
            if (InstantiateAction != null)
            {
                InstantiateAction(PlacementSymmetry[i]);
            }
        }
    }
    // Generate brush textures for all symmetry - need to be done only once, when changing symmetry
    // It mirrors and rotate brush texture
    // Generating textures is slow and make lag when generating
    // Need to find something to speed it up
    void GeneratePaintBrushesh()
    {
        UpdateSymmetryType();

        switch (LastSym)
        {
        case 1:
            PaintImage    = new Texture2D[2];
            PaintImage[0] = RotatedBrush;
            PaintImage[1] = MirrorTexture(RotatedBrush, true, false);
            break;

        case 2:
            PaintImage    = new Texture2D[2];
            PaintImage[0] = RotatedBrush;
            PaintImage[1] = MirrorTexture(RotatedBrush, false, true);
            break;

        case 3:
            PaintImage    = new Texture2D[2];
            PaintImage[0] = RotatedBrush;
            PaintImage[1] = MirrorTexture(RotatedBrush, true, true);
            break;

        case 4:
            PaintImage    = new Texture2D[4];
            PaintImage[0] = RotatedBrush;
            PaintImage[1] = MirrorTexture(RotatedBrush, true, false);
            PaintImage[2] = MirrorTexture(RotatedBrush, false, true);
            PaintImage[3] = MirrorTexture(RotatedBrush, true, true);
            break;

        case 5:
            PaintImage    = new Texture2D[2];
            PaintImage[0] = RotatedBrush;
            PaintImage[1] = rotateTexture(RotatedBrush, 90);
            PaintImage[1] = MirrorTexture(PaintImage[1], true, false);
            break;

        case 6:
            PaintImage    = new Texture2D[2];
            PaintImage[0] = RotatedBrush;
            PaintImage[1] = rotateTexture(RotatedBrush, 90);
            PaintImage[1] = MirrorTexture(PaintImage[1], false, true);
            break;

        case 7:
            PaintImage    = new Texture2D[4];
            PaintImage[0] = RotatedBrush;
            PaintImage[1] = rotateTexture(RotatedBrush, 90);
            PaintImage[1] = MirrorTexture(PaintImage[1], true, false);
            PaintImage[2] = rotateTexture(RotatedBrush, 90);
            PaintImage[2] = MirrorTexture(PaintImage[2], false, true);

            PaintImage[3] = MirrorTexture(RotatedBrush, true, true);
            break;

        case 8:
            LastRot       = SymmetryWindow.GetRotationSym();
            PaintImage    = new Texture2D[LastRot];
            PaintImage[0] = RotatedBrush;
            float angle = 360.0f / (float)LastRot;
            for (int i = 1; i < LastRot; i++)
            {
                PaintImage[i] = rotateTexture(RotatedBrush, -angle * i);
            }
            break;

        default:
            PaintImage    = new Texture2D[1];
            PaintImage[0] = RotatedBrush;
            break;
        }

        PaintImageWidths  = new int[PaintImage.Length];
        PaintImageHeights = new int[PaintImage.Length];

        Pixels = new Color[PaintImage.Length][];
        Values = new float[PaintImage.Length][];
        for (int i = 0; i < PaintImage.Length; i++)
        {
            Pixels[i] = PaintImage[i].GetPixels();
            Values[i] = new float[Pixels[i].Length];
            for (int v = 0; v < Values[i].Length; v++)
            {
                Values[i][v] = Pixels[i][v].r;
            }
            PaintImageWidths[i]  = PaintImage[i].width;
            PaintImageHeights[i] = PaintImage[i].height;
        }
    }
 public static void RegeneratePaintBrushIfNeeded(bool BrushChanged = false)
 {
     if (BrushChanged || SymmetryWindow.GetSymmetryType() != Current.LastSym || (Current.LastSym == 8 && Current.LastRot != SymmetryWindow.GetRotationSym()))
     {
         Current.GeneratePaintBrushesh();
     }
 }
    public void GenerateRotationSymmetry(Quaternion Rotation)
    {
        Vector3 Euler = Rotation.eulerAngles;

        switch (LastSym)
        {
        case 1:
            PaintRotations    = new Quaternion[2];
            PaintRotations[0] = Rotation;
            PaintRotations[1] = Quaternion.Euler(new Vector3(Euler.x, 180 - Euler.y, Euler.z)) * Quaternion.Euler(Vector3.up * 180);                    //GetHorizonalSymetry();
            //PaintRotations[1] = MassMath.MirrorQuaternionZ(Rotation) * Quaternion.Euler(Vector3.up * 180);  //GetHorizonalSymetry();
            break;

        case 2:
            PaintRotations    = new Quaternion[2];
            PaintRotations[0] = Rotation;
            //PaintRotations[1] = MassMath.MirrorQuaternionZ(Rotation);  //GetVerticalSymetry();
            PaintRotations[1] = Quaternion.Euler(new Vector3(Euler.x, 180 - Euler.y, Euler.z));                      //GetHorizonalSymetry();
            break;

        case 3:
            PaintRotations    = new Quaternion[2];
            PaintRotations[0] = Rotation;
            PaintRotations[1] = Quaternion.Euler(new Vector3(Euler.x, 180 + Euler.y, Euler.z));                      //GetHorizontalVerticalSymetry();
            break;

        case 4:
            PaintRotations    = new Quaternion[4];
            PaintRotations[0] = Rotation;
            PaintRotations[1] = Quaternion.Euler(new Vector3(Euler.x, 180 - Euler.y, Euler.z)) * Quaternion.Euler(Vector3.up * 180); //GetHorizonalSymetry();
            PaintRotations[2] = Quaternion.Euler(new Vector3(Euler.x, 180 - Euler.y, Euler.z));                                      //GetVerticalSymetry();
            PaintRotations[3] = Quaternion.Euler(new Vector3(Euler.x, 180 + Euler.y, Euler.z));                                      //GetHorizontalVerticalSymetry();
            break;

        case 5:
            PaintRotations    = new Quaternion[2];
            PaintRotations[0] = Rotation;
            PaintRotations[1] = Quaternion.Euler(new Vector3(Euler.x, 180 - Euler.y, Euler.z)) * Quaternion.Euler(Vector3.up * 180);                      //GetHorizonalSymetry();
            break;

        case 6:
            PaintRotations    = new Quaternion[2];
            PaintRotations[0] = Rotation;
            PaintRotations[1] = Quaternion.Euler(new Vector3(Euler.x, 180 - Euler.y, Euler.z));                      //GetHorizonalSymetry();
            break;

        case 7:
            PaintRotations    = new Quaternion[4];
            PaintRotations[0] = Rotation;
            PaintRotations[1] = Quaternion.Euler(new Vector3(Euler.x, 180 - Euler.y, Euler.z)) * Quaternion.Euler(Vector3.up * 180); //GetHorizonalSymetry();
            PaintRotations[2] = Quaternion.Euler(new Vector3(Euler.x, 180 - Euler.y, Euler.z));                                      //GetVerticalSymetry();
            PaintRotations[3] = Quaternion.Euler(new Vector3(Euler.x, 180 + Euler.y, Euler.z));                                      //GetHorizontalVerticalSymetry();
            break;

        case 8:
            int Count = SymmetryWindow.GetRotationSym();
            PaintRotations    = new Quaternion[Count];
            PaintRotations[0] = Rotation;
            float angle = 360.0f / (float)Count;
            for (int i = 1; i < Count; i++)
            {
                PaintRotations[i] = Quaternion.Euler(Vector3.up * (angle * i)) * Rotation;
            }
            break;

        default:
            PaintRotations    = new Quaternion[1];
            PaintRotations[0] = Rotation;
            break;
        }
    }
    // Generate positions - need to be done before paint
    public void GenerateSymmetry(Vector3 Pos, float Size = 0, float Scatter = 0, float ScatterSize = 0)
    {
        BrushPos = Pos;

        AddScatter(ref BrushPos, Scatter, ScatterSize);

        if (Size > 0)
        {
            /*
             * BrushPos += (Quaternion.Euler(Vector3.up * Random.Range(0, 360)) * Vector3.forward *
             *      (Size * Mathf.Lerp(1, 0, Mathf.Pow(Random.Range(0f, 1f), 2f)))
             *      );
             */
            Vector2 BrushCircle = Random.insideUnitCircle * Size;
            BrushPos.x += BrushCircle.x;
            BrushPos.z += BrushCircle.y;
        }

        switch (LastSym)
        {
        case 1:
            PaintPositions    = new Vector3[2];
            PaintPositions[0] = BrushPos;
            PaintPositions[1] = GetHorizonalSymetry();
            break;

        case 2:
            PaintPositions    = new Vector3[2];
            PaintPositions[0] = BrushPos;
            PaintPositions[1] = GetVerticalSymetry();
            break;

        case 3:
            PaintPositions    = new Vector3[2];
            PaintPositions[0] = BrushPos;
            PaintPositions[1] = GetHorizontalVerticalSymetry();
            break;

        case 4:
            PaintPositions    = new Vector3[4];
            PaintPositions[0] = BrushPos;
            PaintPositions[1] = GetHorizonalSymetry();
            PaintPositions[2] = GetVerticalSymetry();
            PaintPositions[3] = GetHorizontalVerticalSymetry();
            break;

        case 5:
            PaintPositions    = new Vector3[2];
            PaintPositions[0] = BrushPos;
            PaintPositions[1] = GetDiagonal1Symetry();
            break;

        case 6:
            PaintPositions    = new Vector3[2];
            PaintPositions[0] = BrushPos;
            PaintPositions[1] = GetDiagonal2Symetry();
            break;

        case 7:
            PaintPositions    = new Vector3[4];
            PaintPositions[0] = BrushPos;
            PaintPositions[1] = GetDiagonal1Symetry();
            PaintPositions[2] = GetDiagonal2Symetry();
            PaintPositions[3] = GetDiagonal3Symetry();
            break;

        case 8:
            int Count = SymmetryWindow.GetRotationSym();
            PaintPositions    = new Vector3[Count];
            PaintPositions[0] = BrushPos;
            float angle = 360.0f / (float)Count;
            for (int i = 1; i < Count; i++)
            {
                PaintPositions[i] = GetRotationSymetry(angle * i);
            }
            break;

        default:
            PaintPositions    = new Vector3[1];
            PaintPositions[0] = BrushPos;
            break;
        }
    }
        void GenerateSymmetry()
        {
            LastSym = SymmetryWindow.GetSymmetryType();
            //if (LastSym > 8)
            //	LastSym = 8;

            LastTolerance = SymmetryWindow.GetTolerance();


            switch (LastSym)
            {
            case 1:                     // X
                SymetrySelection    = new SelectedObjects[1];
                SymetrySelection[0] = new SelectedObjects();
                SymetrySelection[0].SymmetryMatrix  = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(-1, 1, 1));
                SymetrySelection[0].InverseRotation = true;
                SymetrySelection[0].LoadSymetryIds();
                GenerateSymmetrySelectionRing(SymetrySelection[0]);
                break;

            case 2:                     // Z
                SymetrySelection    = new SelectedObjects[1];
                SymetrySelection[0] = new SelectedObjects();
                SymetrySelection[0].SymmetryMatrix  = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(1, 1, -1));
                SymetrySelection[0].InverseRotation = true;
                SymetrySelection[0].LoadSymetryIds();
                GenerateSymmetrySelectionRing(SymetrySelection[0]);
                break;

            case 3:                     // XZ
                SymetrySelection    = new SelectedObjects[1];
                SymetrySelection[0] = new SelectedObjects();
                SymetrySelection[0].SymmetryMatrix  = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(-1, 1, -1));
                SymetrySelection[0].InverseRotation = false;
                SymetrySelection[0].LoadSymetryIds();
                GenerateSymmetrySelectionRing(SymetrySelection[0]);
                break;

            case 4:                     // X Z XZ
                SymetrySelection    = new SelectedObjects[3];
                SymetrySelection[0] = new SelectedObjects();
                SymetrySelection[0].SymmetryMatrix  = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(-1, 1, 1));
                SymetrySelection[0].InverseRotation = true;
                SymetrySelection[0].LoadSymetryIds();
                GenerateSymmetrySelectionRing(SymetrySelection[0]);

                SymetrySelection[1] = new SelectedObjects();
                SymetrySelection[1].SymmetryMatrix  = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(1, 1, -1));
                SymetrySelection[1].InverseRotation = true;
                SymetrySelection[1].LoadSymetryIds();
                GenerateSymmetrySelectionRing(SymetrySelection[1]);

                SymetrySelection[2] = new SelectedObjects();
                SymetrySelection[2].SymmetryMatrix  = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(-1, 1, -1));
                SymetrySelection[2].InverseRotation = false;
                SymetrySelection[2].LoadSymetryIds();
                GenerateSymmetrySelectionRing(SymetrySelection[2]);
                break;

            case 5:                    // Diagonal1
                SymetrySelection    = new SelectedObjects[1];
                SymetrySelection[0] = new SelectedObjects();
                SymetrySelection[0].SymmetryMatrix  = Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(Vector3.up * 90), new Vector3(-1, 1, 1));
                SymetrySelection[0].InverseRotation = true;
                SymetrySelection[0].LoadSymetryIds();
                GenerateSymmetrySelectionRing(SymetrySelection[0]);
                break;

            case 6:                     // Diagonal 2
                SymetrySelection    = new SelectedObjects[1];
                SymetrySelection[0] = new SelectedObjects();
                SymetrySelection[0].SymmetryMatrix  = Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(Vector3.down * 90), new Vector3(-1, 1, 1));
                SymetrySelection[0].InverseRotation = true;
                SymetrySelection[0].LoadSymetryIds();
                GenerateSymmetrySelectionRing(SymetrySelection[0]);
                break;

            case 7:                     // Diagonal 3
                SymetrySelection    = new SelectedObjects[3];
                SymetrySelection[0] = new SelectedObjects();
                SymetrySelection[0].SymmetryMatrix  = Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(Vector3.up * 90), new Vector3(-1, 1, 1));
                SymetrySelection[0].InverseRotation = true;
                SymetrySelection[0].LoadSymetryIds();
                GenerateSymmetrySelectionRing(SymetrySelection[0]);

                SymetrySelection[1] = new SelectedObjects();
                SymetrySelection[1].SymmetryMatrix  = Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(Vector3.down * 90), new Vector3(-1, 1, 1));
                SymetrySelection[1].InverseRotation = true;
                SymetrySelection[1].LoadSymetryIds();
                GenerateSymmetrySelectionRing(SymetrySelection[1]);

                SymetrySelection[2] = new SelectedObjects();
                SymetrySelection[2].SymmetryMatrix = SymetrySelection[0].SymmetryMatrix * SymetrySelection[1].SymmetryMatrix;
                //SymetrySelection[2].SymmetryMatrix = Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(Vector3.down * 180), new Vector3(-1, 1, -1));
                SymetrySelection[2].InverseRotation = false;
                SymetrySelection[2].LoadSymetryIds();
                GenerateSymmetrySelectionRing(SymetrySelection[2]);

                break;

            case 8:                     // Rotation
                int   RotCount = SymmetryWindow.GetRotationSym() - 1;
                float angle    = 360.0f / (float)(RotCount + 1);
                SymetrySelection = new SelectedObjects[RotCount];

                for (int i = 0; i < RotCount; i++)
                {
                    SymetrySelection[i] = new SelectedObjects();
                    SymetrySelection[i].SymmetryMatrix  = Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(Vector3.up * (angle * (i + 1))), Vector3.one);
                    SymetrySelection[i].InverseRotation = false;
                    SymetrySelection[i].LoadSymetryIds();
                    GenerateSymmetrySelectionRing(SymetrySelection[i]);
                }
                break;

            default:
                SymetrySelection = new SelectedObjects[0];
                break;
            }
        }