Example #1
0
    private void OnClickShiftButton(int x)
    {
        ChromaSDKAnimation1D animation = GetAnimation();

        EditorUtility.SetDirty(animation);
        var frames = animation.Frames; //copy

        Unload();

        if (_mCurrentFrame >= 0 &&
            _mCurrentFrame < frames.Count)
        {
            ChromaDevice1DEnum device = animation.Device;
            int maxLeds  = ChromaUtils.GetMaxLeds(device);
            int offsetX  = maxLeds - x;
            var oldFrame = frames[_mCurrentFrame];
            var newFrame = ChromaUtils.CreateColors1D(device);
            for (int i = 0; i < maxLeds; ++i)
            {
                int color = (int)oldFrame[(i + offsetX) % maxLeds];
                newFrame[i] = color;
            }
            frames[_mCurrentFrame] = newFrame;
        }
        animation.Frames = frames;
    }
Example #2
0
    private void OnClickSaturateButton()
    {
        ChromaSDKAnimation1D animation = GetAnimation();

        EditorUtility.SetDirty(animation);
        var frames = animation.Frames; //copy

        Unload();

        if (_mCurrentFrame >= 0 &&
            _mCurrentFrame < frames.Count)
        {
            ChromaDevice1DEnum device = animation.Device;
            int maxLeds = ChromaUtils.GetMaxLeds(device);
            var frame   = frames[_mCurrentFrame];
            for (int i = 0; i < maxLeds; ++i)
            {
                Color color = ChromaUtils.ToRGB((int)frame[i]);
                float max   = Mathf.Max(Mathf.Max(color.r, color.g), color.b);
                color    = Color.Lerp(Color.black, _mColor, max);
                frame[i] = ChromaUtils.ToBGR(color);
            }
        }
        animation.Frames = frames;
    }
Example #3
0
    private void OnClickPasteButton()
    {
        ChromaSDKAnimation1D animation = GetAnimation();

        EditorUtility.SetDirty(animation);
        var frames = animation.Frames; //copy

        Unload();

        if (_mCurrentFrame >= 0 &&
            _mCurrentFrame < frames.Count)
        {
            ChromaDevice1DEnum device = animation.Device;
            int maxLeds = ChromaUtils.GetMaxLeds(device);
            if (_mColors.Count == maxLeds)
            {
                var frame = ChromaUtils.CreateColors1D(device);
                for (int i = 0; i < maxLeds; ++i)
                {
                    frame[i] = _mColors[i];
                }
                frames[_mCurrentFrame] = frame;
            }
        }
        animation.Frames = frames;
    }
Example #4
0
    private void OnClickDarkenButton()
    {
        ChromaSDKAnimation1D animation = GetAnimation();

        EditorUtility.SetDirty(animation);
        var frames = animation.Frames; //copy

        Unload();

        if (_mCurrentFrame >= 0 &&
            _mCurrentFrame < frames.Count)
        {
            ChromaDevice1DEnum device = animation.Device;
            int maxLeds = ChromaUtils.GetMaxLeds(device);
            var frame   = frames[_mCurrentFrame];
            for (int i = 0; i < maxLeds; ++i)
            {
                Color color = ChromaUtils.ToRGB((int)frame[i]);
                color.r *= 0.75f;
                color.g *= 0.75f;
                color.b *= 0.75f;
                frame[i] = ChromaUtils.ToBGR(color);
            }
        }
        animation.Frames = frames;
    }
Example #5
0
    public void ClearFrames()
    {
        int maxLeds = ChromaUtils.GetMaxLeds(this.Device);

        this._mFrames = new ChromaSDKBaseAnimation.ColorArray[1];
        ChromaSDKBaseAnimation.ColorArray colorArray = new ChromaSDKBaseAnimation.ColorArray();
        int[] array = new int[maxLeds];
        for (int i = 0; i < maxLeds; i++)
        {
            array[i] = 0;
        }
        colorArray.Colors = array;
        this._mFrames[0]  = colorArray;
    }
Example #6
0
    private void OnClickInsertButton()
    {
        ChromaSDKAnimation1D animation = GetAnimation();

        EditorUtility.SetDirty(animation);
        var frames = animation.Frames; //copy

        Unload();

        if (_mCurrentFrame < 0 ||
            _mCurrentFrame >= frames.Count)
        {
            _mCurrentFrame = 0;
        }
        EffectArray1dInput oldFrame;

        if (frames.Count > 0)
        {
            oldFrame = frames[_mCurrentFrame];
        }
        else
        {
            oldFrame = ChromaUtils.CreateColors1D(animation.Device);
        }
        EffectArray1dInput frame = ChromaUtils.CreateColors1D(animation.Device);

        if (frames.Count == 0)
        {
            frames.Add(frame);
            _mCurrentFrame = frames.Count - 1;
        }
        else
        {
            frames.Insert(_mCurrentFrame, frame);
        }
        // copy colors
        if (_mCurrentFrame >= 0 &&
            _mCurrentFrame < frames.Count)
        {
            ChromaDevice1DEnum device = animation.Device;
            int maxLeds = ChromaUtils.GetMaxLeds(device);
            for (int i = 0; i < maxLeds; ++i)
            {
                frame[i] = oldFrame[i];
            }
        }
        animation.Frames = frames;
        animation.RefreshCurve();
    }
    /// <summary>
    /// Set frames to the default state
    /// </summary>
    public void ClearFrames()
    {
        int maxLeds = ChromaUtils.GetMaxLeds(Device);

        _mFrames = new ColorArray[1];
        var frame    = new ColorArray();
        var elements = new int[maxLeds];

        for (int i = 0; i < maxLeds; ++i)
        {
            elements[i] = 0;
        }
        frame.Colors = elements;
        _mFrames[0]  = frame;
    }
Example #8
0
    private void OnClickFillButton()
    {
        ChromaSDKAnimation1D animation = GetAnimation();

        EditorUtility.SetDirty(animation);
        var frames = animation.Frames; //copy

        Unload();

        if (_mCurrentFrame >= 0 &&
            _mCurrentFrame < frames.Count)
        {
            ChromaDevice1DEnum device = animation.Device;
            int maxLeds  = ChromaUtils.GetMaxLeds(device);
            var elements = ChromaUtils.CreateColors1D(device);
            for (int i = 0; i < maxLeds; ++i)
            {
                elements[i] = ChromaUtils.ToBGR(_mColor);
            }
            frames[_mCurrentFrame] = elements;
        }
        animation.Frames = frames;
    }
Example #9
0
    private void OnClickContrastButton()
    {
        ChromaSDKAnimation1D animation = GetAnimation();

        EditorUtility.SetDirty(animation);
        var frames = animation.Frames; //copy

        Unload();

        if (_mCurrentFrame >= 0 &&
            _mCurrentFrame < frames.Count)
        {
            ChromaDevice1DEnum device = animation.Device;
            int maxLeds = ChromaUtils.GetMaxLeds(device);
            var frame   = frames[_mCurrentFrame];
            for (int i = 0; i < maxLeds; ++i)
            {
                Color color = ChromaUtils.ToRGB((int)frame[i]);
                float avg   = (color.r + color.g + color.b) / 3f;
                if (avg < 0.5f)
                {
                    color.r *= 0.75f;
                    color.g *= 0.75f;
                    color.b *= 0.75f;
                }
                else if (avg > 0.5f)
                {
                    color.r = Mathf.Min(1f, color.r * 1.25f);
                    color.g = Mathf.Min(1f, color.g * 1.25f);
                    color.b = Mathf.Min(1f, color.b * 1.25f);
                }
                frame[i] = ChromaUtils.ToBGR(color);
            }
        }
        animation.Frames = frames;
    }
    private void OnGUI()
    {
        if (_mCapturing)
        {
            if (_mTimerCapture < DateTime.Now)
            {
                _mTimerCapture = DateTime.Now + TimeSpan.FromSeconds(_mInterval);
                CaptureFrame();
            }
        }

        GameObject activeGameObject = Selection.activeGameObject;
        Object     activeObject     = Selection.activeObject;

        if (activeGameObject)
        {
            ParticleSystem particleSystem = activeGameObject.GetComponent <ParticleSystem>();
            if (particleSystem)
            {
                _mParticleSystem = particleSystem;
            }
        }

#if SHOW_TEMP_TEXTURE
        _mTempTexture = (Texture2D)EditorGUILayout.ObjectField("TempTexture", _mTempTexture, typeof(Texture2D), true);
#endif

        _mAnimation = (ChromaSDKBaseAnimation)EditorGUILayout.ObjectField("Animation", _mAnimation, typeof(ChromaSDKBaseAnimation), true);

        _mRenderCamera = (Camera)EditorGUILayout.ObjectField("RenderCamera", _mRenderCamera, typeof(Camera), true);

        GUILayout.BeginHorizontal(GUILayout.Width(position.width));
        GUILayout.Label("Select:");
        GUI.enabled = null != _mAnimation;
        if (GUILayout.Button("Animation"))
        {
            Selection.activeGameObject = null;
            Selection.activeObject     = _mAnimation;
        }
        GUI.enabled = null != _mRenderCamera;
        if (GUILayout.Button("Camera"))
        {
            Selection.activeObject     = null;
            Selection.activeGameObject = _mRenderCamera.gameObject;
        }
        GUI.enabled = null != _mParticleSystem;
        if (GUILayout.Button("ParticleSystem"))
        {
            Selection.activeGameObject = null;
            Selection.activeObject     = _mParticleSystem;
        }
        GUI.enabled = true;
        GUILayout.EndHorizontal();

        GUILayout.BeginHorizontal(GUILayout.Width(position.width));
        GUILayout.Label("Camera:");
        GUI.enabled = null != _mRenderCamera;
        if (GUILayout.Button("Align With View"))
        {
            Selection.activeGameObject = _mRenderCamera.gameObject;
            EditorApplication.ExecuteMenuItem("GameObject/Align With View");
            Selection.activeObject     = activeObject;
            Selection.activeGameObject = activeGameObject;
        }
        GUI.enabled = true;
        GUILayout.EndHorizontal();

        GUILayout.BeginHorizontal(GUILayout.Width(position.width));
        GUILayout.Label("Animation:");
        if (_mAnimation)
        {
            GUI.enabled = ChromaConnectionManager.Instance.Connected;
            if (GUILayout.Button("Play"))
            {
                _mAnimation.Play();
            }
            GUI.enabled = IsAnimationSelected() && !_mAnimation.IsPlaying();
            if (GUILayout.Button("First"))
            {
                ChromaSDKAnimationBaseEditor.GoToFirstFrame();
            }
            if (GUILayout.Button("Last"))
            {
                ChromaSDKAnimationBaseEditor.GoToLastFrame();
            }
            if (GUILayout.Button("Delete"))
            {
                DeleteFrame();
            }
            GUI.enabled = !_mAnimation.IsPlaying();
            if (GUILayout.Button("Reset"))
            {
                ResetAnimation();
            }
            GUI.enabled = true;
        }
        GUILayout.EndHorizontal();

        GUILayout.BeginHorizontal(GUILayout.Width(position.width));
        float interval = EditorGUILayout.FloatField("Capture Interval", _mInterval);
        if (interval >= 0.1f)
        {
            _mInterval = interval;
        }
        int frameCount = 0;
        if (_mAnimation)
        {
            frameCount = _mAnimation.GetFrameCount();
        }
        GUILayout.Label(string.Format("{0} frames", frameCount));
        GUILayout.EndHorizontal();

        GUILayout.BeginHorizontal(GUILayout.Width(position.width));
        GUILayout.Label("Capture:");
        GUI.enabled = null != _mRenderCamera && null != _mAnimation && !_mAnimation.IsPlaying();
        if (GUILayout.Button("1 Frame"))
        {
            CaptureFrame();
        }
        if (GUILayout.Button(_mCapturing ? "Stop" : "Start"))
        {
            _mCapturing = !_mCapturing;
            if (!_mCapturing)
            {
                AutoOverrideTime();
            }
        }
        GUI.enabled = true;
        GUILayout.EndHorizontal();

        Rect rect = GUILayoutUtility.GetLastRect();
        if (_mRenderCamera)
        {
            if (null == _mRenderTexture)
            {
                _mRenderTexture = new RenderTexture(RENDER_TEXTURE_SIZE, RENDER_TEXTURE_SIZE, 24, RenderTextureFormat.ARGB32);
                _mRenderCamera.targetTexture = _mRenderTexture;
            }
            _mRenderCamera.Render();
            rect.y += 30;
            DisplayRenderTexture((int)rect.y, RENDER_TEXTURE_SIZE, RENDER_TEXTURE_SIZE);
            if (_mAnimation)
            {
                rect.y += 300;
                const int padding = 8;
                if (_mAnimation is ChromaSDKAnimation1D)
                {
                    int maxLeds = ChromaUtils.GetMaxLeds((_mAnimation as ChromaSDKAnimation1D).Device);
                    for (int k = 1; (k * maxLeds) < position.width && (rect.y + rect.height) <= position.height; k *= 2)
                    {
                        DisplayRenderTexture((int)rect.y, maxLeds * k, k);
                        rect.y += k + padding;
                    }
                }
                else if (_mAnimation is ChromaSDKAnimation2D)
                {
                    int maxRow    = ChromaUtils.GetMaxRow((_mAnimation as ChromaSDKAnimation2D).Device);
                    int maxColumn = ChromaUtils.GetMaxColumn((_mAnimation as ChromaSDKAnimation2D).Device);
                    DisplayRenderTexture((int)rect.y, maxColumn, maxRow);
                    for (int k = 1; (k * maxColumn) < position.width && (rect.y + rect.height) <= position.height; k *= 2)
                    {
                        DisplayRenderTexture((int)rect.y, maxColumn * k, maxRow * k);
                        rect.y += maxRow * k + padding;
                    }
                }
            }
        }

        Repaint();
    }
    private void CaptureFrame()
    {
        if (_mAnimation && _mRenderTexture && _mRenderCamera)
        {
            if (_mAnimation is ChromaSDKAnimation1D)
            {
                ChromaSDKAnimation1D animation = (ChromaSDKAnimation1D)_mAnimation;
                animation.Unload();
                int maxLeds = ChromaUtils.GetMaxLeds(animation.Device);

                _mTempTexture        = new Texture2D(RENDER_TEXTURE_SIZE, RENDER_TEXTURE_SIZE, TextureFormat.RGB24, false);
                RenderTexture.active = _mRenderTexture;
                _mRenderCamera.Render();
                DisplayRenderTexture(0, maxLeds, 1);
                _mTempTexture.ReadPixels(new Rect(0, 0, _mTempTexture.width, _mTempTexture.height), 0, 0, false);
                _mTempTexture.Apply();
                TextureScale.Bilinear(_mTempTexture, maxLeds, 1);
                _mTempTexture.Apply();
                RenderTexture.active = null;
                Color[] pixels = _mTempTexture.GetPixels();
                List <EffectArray1dInput> frames = animation.Frames;
                EffectArray1dInput        frame  = ChromaUtils.CreateColors1D(animation.Device);
                int index = 0;
                if (frame.Count > 0)
                {
                    for (int i = 0; i < maxLeds; ++i)
                    {
                        Color color = pixels[index];
                        frame[i] = ChromaUtils.ToBGR(color);
                        ++index;
                    }
                }
#if !SHOW_TEMP_TEXTURE
                DestroyImmediate(_mTempTexture);
#endif
                frames.Add(frame);
                animation.Frames = frames;
                ChromaSDKAnimationBaseEditor.GoToLastFrame();
            }
            else if (_mAnimation is ChromaSDKAnimation2D)
            {
                ChromaSDKAnimation2D animation = (ChromaSDKAnimation2D)_mAnimation;
                animation.Unload();
                int maxRow    = ChromaUtils.GetMaxRow(animation.Device);
                int maxColumn = ChromaUtils.GetMaxColumn(animation.Device);

                _mTempTexture        = new Texture2D(RENDER_TEXTURE_SIZE, RENDER_TEXTURE_SIZE, TextureFormat.RGB24, false);
                RenderTexture.active = _mRenderTexture;
                _mRenderCamera.Render();
                DisplayRenderTexture(0, maxColumn, maxRow);
                _mTempTexture.ReadPixels(new Rect(0, 0, _mTempTexture.width, _mTempTexture.height), 0, 0, false);
                _mTempTexture.Apply();
                TextureScale.Bilinear(_mTempTexture, maxColumn, maxRow);
                _mTempTexture.Apply();
                RenderTexture.active = null;
                Color[] pixels = _mTempTexture.GetPixels();
                List <EffectArray2dInput> frames = animation.Frames;
                EffectArray2dInput        frame  = ChromaUtils.CreateColors2D(animation.Device);
                int index = 0;
                for (int i = maxRow - 1; i >= 0; --i)
                {
                    List <int> row = frame[i];
                    for (int j = 0; j < maxColumn; ++j)
                    {
                        Color color = pixels[index];
                        row[j] = ChromaUtils.ToBGR(color);
                        ++index;
                    }
                }
#if !SHOW_TEMP_TEXTURE
                DestroyImmediate(_mTempTexture);
#endif
                frames.Add(frame);
                animation.Frames = frames;
                ChromaSDKAnimationBaseEditor.GoToLastFrame();
            }
        }
    }
Example #12
0
    private void OnClickExportButton()
    {
        ChromaSDKAnimation1D animation = GetAnimation();

        if (animation)
        {
            string initialFileName = string.Format("{0}.chroma", animation.name);
            string path            = EditorUtility.SaveFilePanel("Save Chroma", GetChromaFolder(), initialFileName, GetChromaExtensions());
            if (!string.IsNullOrEmpty(path))
            {
                EditorPrefs.SetString(KEY_FOLDER_CHROMA, Path.GetDirectoryName(path));
                using (FileStream fs = File.Open(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite))
                {
                    using (BinaryWriter bw = new BinaryWriter(fs))
                    {
                        //version
                        bw.Write((int)ANIMATION_VERSION);

                        //device type
                        bw.Write((byte)ChromaDeviceTypeEnum.Type_1D);

                        //device
                        bw.Write((byte)animation.Device);

                        List <EffectArray1dInput> frames = animation.Frames;

                        //frame count
                        bw.Write(frames.Count);

                        //frames
                        for (int index = 0; index < frames.Count; ++index)
                        {
                            EffectArray1dInput frame = frames[index];

                            //duration
                            float duration = 0.0f;
                            if (index < frames.Count &&
                                index < animation.Curve.keys.Length)
                            {
                                if (index == 0)
                                {
                                    duration = animation.Curve.keys[index].time;
                                }
                                else
                                {
                                    duration =
                                        animation.Curve.keys[index].time -
                                        animation.Curve.keys[index - 1].time;
                                }
                            }
                            bw.Write((float)duration);
                            // colors
                            int maxLeds = ChromaUtils.GetMaxLeds(animation.Device);
                            for (int i = 0; i < maxLeds; ++i)
                            {
                                int color = (int)frame[i];
                                bw.Write((int)color);
                            }
                        }
                        bw.Flush();
                        AssetDatabase.Refresh();
                    }
                }
            }
        }
    }
Example #13
0
    private void OnClickImportButton()
    {
        ChromaSDKAnimation1D animation = GetAnimation();

        if (animation)
        {
            //string initialPath = string.Format("{0}/{1}.chroma", GetChromaFolder(), animation.name);
            string path = EditorUtility.OpenFilePanel("Open Chroma", GetChromaFolder(), GetChromaExtensions());
            if (!string.IsNullOrEmpty(path))
            {
                EditorPrefs.SetString(KEY_FOLDER_CHROMA, Path.GetDirectoryName(path));
                using (FileStream fs = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                {
                    using (BinaryReader br = new BinaryReader(fs))
                    {
                        //version
                        int version = br.ReadInt32();
                        if (version != ANIMATION_VERSION)
                        {
                            Debug.LogError("Unexpected file version!");
                            return;
                        }

                        //device type
                        if (br.ReadByte() != (byte)ChromaDeviceTypeEnum.Type_1D)
                        {
                            Debug.LogError("Unexpected device type!");
                            return;
                        }

                        //device
                        switch ((ChromaDevice1DEnum)br.ReadByte())
                        {
                        case ChromaDevice1DEnum.ChromaLink:
                            animation.Device = ChromaDevice1DEnum.ChromaLink;
                            break;

                        case ChromaDevice1DEnum.Headset:
                            animation.Device = ChromaDevice1DEnum.Headset;
                            break;

                        case ChromaDevice1DEnum.Mousepad:
                            animation.Device = ChromaDevice1DEnum.Mousepad;
                            break;

                        default:
                            Debug.LogError("Unexpected device!");
                            return;
                        }

                        List <EffectArray1dInput> frames = new List <EffectArray1dInput>();

                        // reset curve
                        while (animation.Curve.keys.Length > 0)
                        {
                            animation.Curve.RemoveKey(0);
                        }

                        //frame count
                        int frameCount = br.ReadInt32();

                        float time = 0f;

                        //frames
                        for (int index = 0; index < frameCount; ++index)
                        {
                            EffectArray1dInput frame = new EffectArray1dInput();

                            //duration
                            float duration = br.ReadSingle();
                            time += duration;
                            animation.Curve.AddKey(time, 0f);
                            // colors
                            int maxLeds = ChromaUtils.GetMaxLeds(animation.Device);
                            for (int i = 0; i < maxLeds; ++i)
                            {
                                int color = br.ReadInt32();
                                frame.Add(color);
                            }
                            frames.Add(frame);
                        }

                        animation.Frames = frames;
                    }
                }
            }
        }
    }
Example #14
0
    public override void OnInspectorGUI()
    {
        if (!EditorApplication.isCompiling)
        {
            base.OnInspectorGUI();

            // backup original color
            Color oldBackgroundColor = GUI.backgroundColor;

            ChromaSDKAnimation1D animation = GetAnimation();

            if (_mLastTarget != animation)
            {
                _mLastTarget = animation;
                _mDevice     = animation.Device;
            }

            var frames = animation.Frames; //copy

            if (frames.Count == 0)
            {
                OnClickAddButton();
            }

            // Device
            GUILayout.BeginHorizontal(GUILayout.Width(Screen.width - LAYOUT_PADDING));
            GUILayout.Label("Device:");
            _mDevice = (ChromaDevice1DEnum)EditorGUILayout.EnumPopup(_mDevice, GUILayout.Width(150));
            if (GUILayout.Button("Set", GUILayout.Width(100)))
            {
                OnClickSetDevice();
            }
            GUILayout.FlexibleSpace();
            GUILayout.Label(ChromaUtils.VERSION);
            GUILayout.EndHorizontal();

            bool connected = ChromaConnectionManager.Instance.Connected;

            GUI.enabled = connected;

            GUILayout.BeginHorizontal(GUILayout.Width(Screen.width - LAYOUT_PADDING));

            if (GUILayout.Button("Play"))
            {
                OnClickPlayButton();
            }

            if (GUILayout.Button("Stop"))
            {
                OnClickStopButton();
            }

            GUI.enabled = connected && !animation.IsLoaded();
            if (GUILayout.Button("Load"))
            {
                OnClickLoadButton();
            }

            GUI.enabled = connected && animation.IsLoaded();
            if (GUILayout.Button("Unload"))
            {
                OnClickUnloadButton();
            }

            GUI.enabled = true;

            if (GUILayout.Button("Preview"))
            {
                OnClickPreviewButton();
            }

            GUILayout.EndHorizontal();

            // Import

            GUILayout.BeginHorizontal(GUILayout.Width(Screen.width - LAYOUT_PADDING));
            GUILayout.FlexibleSpace();
            if (GUILayout.Button("Import"))
            {
                OnClickImportButton();
            }
            if (GUILayout.Button("Export"))
            {
                OnClickExportButton();
            }
            if (GUILayout.Button("Import Image"))
            {
                OnClickImportImageButton();
            }
            if (GUILayout.Button("Import Animation"))
            {
                OnClickImportAnimationButton();
            }
            if (GUILayout.Button("Reverse Animation"))
            {
                OnClickReverseAnimationButton();
            }
            GUILayout.FlexibleSpace();
            GUILayout.EndHorizontal();

            // Apply
            GUILayout.BeginHorizontal(GUILayout.Width(Screen.width - LAYOUT_PADDING));

            if (GUILayout.Button("Clear"))
            {
                OnClickClearButton();
            }

            if (GUILayout.Button("Fill"))
            {
                OnClickFillButton();
            }

            if (GUILayout.Button("Random"))
            {
                OnClickRandomButton();
            }

            if (GUILayout.Button("Copy"))
            {
                OnClickCopyButton();
            }

            if (GUILayout.Button("Paste"))
            {
                OnClickPasteButton();
            }

            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal(GUILayout.Width(Screen.width - LAYOUT_PADDING));
            if (GUILayout.Button("Contrast"))
            {
                OnClickContrastButton();
            }
            if (GUILayout.Button("Saturate"))
            {
                OnClickSaturateButton();
            }
            if (GUILayout.Button("Desaturate"))
            {
                OnClickDesaturateButton();
            }
            if (GUILayout.Button("Darken"))
            {
                OnClickDarkenButton();
            }
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal(GUILayout.Width(Screen.width - LAYOUT_PADDING));
            if (GUILayout.Button("Shift Left"))
            {
                OnClickShiftButton(-1);
            }
            if (GUILayout.Button("Shift Right"))
            {
                OnClickShiftButton(1);
            }
            GUILayout.EndHorizontal();

            int maxLeds = ChromaUtils.GetMaxLeds(animation.Device);

            GUILayout.Label(string.Format("1 x {0}", maxLeds));

            // Preview
            Texture2D oldTexture = GUI.skin.button.normal.background;
            SetupBlankTexture();
            if (_mCurrentFrame < frames.Count)
            {
                GUILayout.BeginHorizontal(GUILayout.Width(Screen.width - LAYOUT_PADDING));
                EffectArray1dInput frame = frames[_mCurrentFrame];
                for (int i = 0; i < frame.Count; ++i)
                {
                    int color = (int)frame[i];

                    GUI.backgroundColor = ChromaUtils.ToRGB(color);
                    // use a box instead of button so it looks better
                    GUILayout.Box("", GUILayout.Width(12));
                    Rect rect = GUILayoutUtility.GetLastRect();
                    // use the box location to use a button to catch the click event
                    GUI.skin.button.normal.background = _sTextureClear;
                    if (GUI.Button(rect, ""))
                    {
                        OnClickColor(i);
                    }
                    GUI.skin.button.normal.background = oldTexture;
                }
                GUILayout.EndHorizontal();
            }
            GUI.SetNextControlName("");

            // restore original color
            GUI.backgroundColor = oldBackgroundColor;

            // show separator
            EditorGUILayout.LabelField("", GUI.skin.horizontalSlider);

            // preset colors

            GUILayout.BeginHorizontal(GUILayout.Width(Screen.width - LAYOUT_PADDING));
            const float k       = 0.5f;
            Color[]     palette =
            {
                Color.red,    Color.red *k,
                ORANGE,       ORANGE *k,
                Color.yellow, Color.yellow *k,
                Color.green,  Color.green *k,
                Color.blue,   Color.blue *k,
                Color.cyan,   Color.cyan *k,
                PURPLE,       PURPLE *k,
                Color.white,  Color.gray,     Color.black,
            };
            foreach (Color color in palette)
            {
                Color newColor = color;
                newColor.a          = 1f;
                GUI.backgroundColor = newColor;
                // use a box instead of button so it looks better
                GUILayout.Box("", GUILayout.Width(12));
                Rect rect = GUILayoutUtility.GetLastRect();
                // use the box location to use a button to catch the click event
                GUI.skin.button.normal.background = _sTextureClear;
                if (GUI.Button(rect, ""))
                {
                    _mColor = newColor;
                }
                GUI.skin.button.normal.background = oldTexture;
            }
            GUILayout.EndHorizontal();

            // restore original color
            GUI.backgroundColor = oldBackgroundColor;

            // Set the color

            _mColor = EditorGUILayout.ColorField("Brush color", _mColor);

            GUILayout.BeginHorizontal(GUILayout.Width(Screen.width - LAYOUT_PADDING));
            GUI.SetNextControlName(CONTROL_OVERRIDE);
            GUILayout.Label("Override Time (ALL frames)");
            _mOverrideFrameTime = EditorGUILayout.FloatField(_mOverrideFrameTime, GUILayout.Width(100));
            GUI.SetNextControlName(string.Empty);
            if (GUILayout.Button("Override", GUILayout.Width(100)))
            {
                OnClickOverrideButton();
            }
            GUILayout.FlexibleSpace();
            GUILayout.EndHorizontal();

            EditorGUILayout.LabelField("Frame:", string.Format("{0} of {1}",
                                                               _mCurrentFrame + 1,
                                                               null == frames ? 0 : frames.Count));

            float duration = 0.0f;
            if (_mCurrentFrame < frames.Count &&
                _mCurrentFrame < animation.Curve.keys.Length)
            {
                if (_mCurrentFrame == 0)
                {
                    duration = animation.Curve.keys[_mCurrentFrame].time;
                }
                else
                {
                    duration =
                        animation.Curve.keys[_mCurrentFrame].time -
                        animation.Curve.keys[_mCurrentFrame - 1].time;
                }
            }

            GUI.SetNextControlName(CONTROL_DURATION);
            GUILayout.BeginHorizontal(GUILayout.Width(Screen.width - LAYOUT_PADDING));
            float newDuration = EditorGUILayout.FloatField("Duration:", duration);
            if (duration != newDuration &&
                newDuration > 0f)
            {
                if (_mCurrentFrame < frames.Count &&
                    _mCurrentFrame < animation.Curve.keys.Length)
                {
                    float time;
                    if (_mCurrentFrame == 0)
                    {
                        time = newDuration;
                    }
                    else
                    {
                        time = animation.Curve.keys[_mCurrentFrame - 1].time + newDuration;
                    }
                    animation.Curve.RemoveKey(_mCurrentFrame);
                    animation.Curve.AddKey(time, 0f);
                }
            }
            GUILayout.Label("seconds(s)");
            GUILayout.EndHorizontal();
            GUI.SetNextControlName(string.Empty);

            GUILayout.BeginHorizontal(GUILayout.Width(Screen.width - LAYOUT_PADDING));

            if (GUILayout.Button("First"))
            {
                OnClickFirstButton();
            }

            if (GUILayout.Button("Previous"))
            {
                OnClickPreviousButton();
            }

            if (GUILayout.Button("Next"))
            {
                OnClickNextButton();
            }

            if (GUILayout.Button("Last"))
            {
                OnClickLastButton();
            }

            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal(GUILayout.Width(Screen.width - LAYOUT_PADDING));

            if (GUILayout.Button("Add"))
            {
                OnClickAddButton();
            }

            if (GUILayout.Button("Insert"))
            {
                OnClickInsertButton();
            }

            if (GUILayout.Button("Delete"))
            {
                OnClickDeleteButton();
            }

            if (GUILayout.Button("Reset"))
            {
                OnClickResetButton();
            }

            GUILayout.EndHorizontal();


            // Custom Curve
            animation.Curve = EditorGUILayout.CurveField("Edit Curve:", animation.Curve);

            //Debug.Log(GUI.GetNameOfFocusedControl());
            if (string.IsNullOrEmpty(GUI.GetNameOfFocusedControl()))
            {
                Event e = Event.current;
                if (e.type == EventType.keyUp)
                {
                    if (e.keyCode == KeyCode.Delete)
                    {
                        OnClickClearButton();
                        Repaint();
                    }
                    else if (e.keyCode == KeyCode.C &&
                             e.modifiers == EventModifiers.Control)
                    {
                        OnClickCopyButton();
                    }
                    else if (e.keyCode == KeyCode.V &&
                             e.modifiers == EventModifiers.Control)
                    {
                        OnClickPasteButton();
                        Repaint();
                    }
                    else if (e.keyCode == KeyCode.P)
                    {
                        OnClickPlayButton();
                    }
                    else if (e.keyCode == KeyCode.LeftArrow)
                    {
                        OnClickPreviousButton();
                        Repaint();
                    }
                    else if (e.keyCode == KeyCode.RightArrow)
                    {
                        OnClickNextButton();
                        Repaint();
                    }
                    else if (e.keyCode == KeyCode.Plus ||
                             e.keyCode == KeyCode.KeypadPlus)
                    {
                        OnClickAddButton();
                        Repaint();
                    }
                    else if (e.keyCode == KeyCode.Minus ||
                             e.keyCode == KeyCode.KeypadMinus)
                    {
                        OnClickDeleteButton();
                        Repaint();
                    }
                }
            }
        }

        Repaint();
    }