public override void OnInspectorGUI()
    {
        if (!EditorApplication.isCompiling)
        {
            base.OnInspectorGUI();

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

            ChromaSDKAnimation2D 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 = (ChromaDevice2DEnum)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") ||
                Event.current.shift)
            {
                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 Down"))
            {
                OnClickShiftButton(1, 0);
            }
            if (GUILayout.Button("Shift Left"))
            {
                OnClickShiftButton(0, -1);
            }
            if (GUILayout.Button("Shift Right"))
            {
                OnClickShiftButton(0, 1);
            }
            if (GUILayout.Button("Shift Up"))
            {
                OnClickShiftButton(-1, 0);
            }
            GUILayout.EndHorizontal();

            // grid info

            int maxRow    = ChromaUtils.GetMaxRow(animation.Device);
            int maxColumn = ChromaUtils.GetMaxColumn(animation.Device);

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

            if (_mDevice == ChromaDevice2DEnum.Keyboard)
            {
                GUILayout.BeginHorizontal(GUILayout.Width(Screen.width));
                _sToggleLabels = EditorGUILayout.Toggle("Labels:", _sToggleLabels);
                _sLabelColor   = EditorGUILayout.ColorField("Label Color:", _sLabelColor);
                GUILayout.FlexibleSpace();
                GUILayout.EndHorizontal();
            }

            // Preview

            // the grid panel
            GUILayout.BeginHorizontal(GUILayout.Width(Screen.width - LAYOUT_PADDING));

            GUILayout.FlexibleSpace();

            // the left-part

            GUILayout.BeginVertical();
            if (GUILayout.Button(" ", GUILayout.Height(20)))
            {
                OnClickFillButton();
            }
            for (int i = 0; i < maxRow; ++i)
            {
                if (GUILayout.Button(" ", GUILayout.Height(20)))
                {
                    OnClickFillRow(i);
                }
            }
            GUILayout.EndVertical();

            // the right-part

            GUILayout.BeginVertical();

            int boxWidth = Screen.width / (maxColumn + 1) - 5;

            // the top-buttons
            GUILayout.BeginHorizontal(GUILayout.Width(Screen.width - LAYOUT_PADDING));
            for (int j = 0; j < maxColumn; ++j)
            {
                if (GUILayout.Button(" ", GUILayout.Width(boxWidth)))
                {
                    OnClickFillColumn(j);
                }
            }
            GUILayout.EndHorizontal();

            // the main-grid

            string    tooltip     = null;
            Rect      tooltipRect = new Rect(0, 0, 0, 0);
            Texture2D oldTexture  = GUI.skin.button.normal.background;
            SetupBlankTexture();
            if (_mCurrentFrame < frames.Count)
            {
                EffectArray2dInput frame = frames[_mCurrentFrame];
                for (int i = 0; i < maxRow && i < frame.Count; ++i)
                {
                    List <int> row = frame[i];
                    GUILayout.BeginHorizontal(GUILayout.Width(Screen.width - LAYOUT_PADDING));

                    for (int j = 0; j < maxColumn && j < row.Count; ++j)
                    {
                        int color = row[j];
                        GUI.backgroundColor = ChromaUtils.ToRGB(color);
                        // use a box instead of button so it looks better
                        GUILayout.Box("", GUILayout.Width(boxWidth));
                        Rect rect = GUILayoutUtility.GetLastRect();
                        // check for hovering box
                        if (Event.current.alt &&
                            rect.Contains(Event.current.mousePosition))
                        {
                            _mColor = ChromaUtils.ToRGB(color);
                        }
                        if (_mDevice == ChromaDevice2DEnum.Keyboard &&
                            !_sToggleLabels &&
                            rect.Contains(Event.current.mousePosition))
                        {
                            tooltip     = ChromaUtils.GetKeyString(i, j);
                            tooltipRect = rect;
                        }
                        // 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, j);
                        }
                        GUI.skin.button.normal.background = oldTexture;

                        if (_mDevice == ChromaDevice2DEnum.Keyboard &&
                            _sToggleLabels)
                        {
                            string keyString = ChromaUtils.GetKeyString(i, j);
                            Color  oldColor  = GUI.skin.label.normal.textColor;
                            GUI.skin.label.normal.textColor = _sLabelColor;
                            GUI.Label(rect, keyString);
                            GUI.skin.label.normal.textColor = oldColor;
                        }
                    }

                    GUILayout.EndHorizontal();
                }
            }
            GUI.SetNextControlName("");

            if (!string.IsNullOrEmpty(tooltip))
            {
                var     labelStyle = GUI.skin.GetStyle("Label");
                Vector2 size       = labelStyle.CalcSize(new GUIContent(tooltip));
                tooltipRect.y                 -= 20;
                tooltipRect.width              = size.x + 10;
                tooltipRect.height             = size.y + 10;
                GUI.skin.box.normal.background = _sTextureClear;
                GUI.Box(tooltipRect, " ");
                labelStyle.alignment = TextAnchor.MiddleCenter;
                GUI.Label(tooltipRect, tooltip);
            }

            // end of right-part

            GUILayout.EndVertical();

            GUILayout.FlexibleSpace();

            // end of grid panel
            GUILayout.EndHorizontal();

            // restore original color
            GUI.backgroundColor = oldBackgroundColor;

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

            // Key
            if (animation.Device == ChromaDevice2DEnum.Keyboard)
            {
                GUILayout.BeginHorizontal(GUILayout.Width(Screen.width - LAYOUT_PADDING));
                _mKey = (Keyboard.RZKEY)EditorGUILayout.EnumPopup("Select a key", _mKey);
                if (GUILayout.Button("Set key", GUILayout.Width(100)))
                {
                    OnClickColor(
                        ChromaUtils.GetHighByte((int)_mKey),
                        ChromaUtils.GetLowByte((int)_mKey));
                }
                GUILayout.EndHorizontal();
                GUILayout.BeginHorizontal(GUILayout.Width(Screen.width - LAYOUT_PADDING));
                if (GUILayout.Button("Set RZLED_LOGO"))
                {
                    OnClickColor(
                        ChromaUtils.GetHighByte((int)Keyboard.RZLED.RZLED_LOGO),
                        ChromaUtils.GetLowByte((int)Keyboard.RZLED.RZLED_LOGO));
                }
                GUILayout.EndHorizontal();
            }

            // Led
            if (animation.Device == ChromaDevice2DEnum.Mouse)
            {
                GUILayout.BeginHorizontal(GUILayout.Width(Screen.width - LAYOUT_PADDING));
                _mLed = (Mouse.RZLED2)EditorGUILayout.EnumPopup("Select an LED", _mLed);

                if (GUILayout.Button("Set LED", GUILayout.Width(100)))
                {
                    OnClickColor(
                        ChromaUtils.GetHighByte((int)_mLed),
                        ChromaUtils.GetLowByte((int)_mLed));
                }
                GUILayout.EndHorizontal();
            }

            // 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

            GUILayout.BeginHorizontal(GUILayout.Width(Screen.width - LAYOUT_PADDING));
            _mColor = EditorGUILayout.ColorField(_mColor, GUILayout.Width(40));
            _mColor = EditorGUILayout.ColorField("Brush color", _mColor);
            GUILayout.EndHorizontal();

            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();
                    }
                    else if (e.keyCode == KeyCode.Space)
                    {
                        OnClickPlayButton();
                        Repaint();
                    }
                }
            }
        }

        Repaint();
    }