private void HandleHotKey()
        {
            Event e = Event.current;

//			DLog.Log("e.shift " + e.shift + " e.isKey " + e.isKey + " e.e.type == EventType.KeyDown " + (e.type == EventType.KeyDown) + " e.keyCode == KeyCode.D " + (e.keyCode == KeyCode.D));
            if (e.shift && e.isKey && e.type == EventType.KeyDown)
            {
                if (e.keyCode == KeyCode.D)
                {
                    DLog.Log("Shift + D -> Duplicate");
                    if (selectedObject != null && selectedObject is Challenge)
                    {
                        foreach (Stage stage in configObjectForEditor.stages)
                        {
                            foreach (Wave wave in stage.waves)
                            {
                                if (wave.challenges.Contains(selectedObject))
                                {
                                    Challenge newChallenge = new JsonDeserializationOperation(
                                        new JsonSerializationOperation(selectedObject).Act()
                                        ).Act <Challenge>();
                                    selectedObject = newChallenge;
                                    wave.challenges.Add(newChallenge);
                                    GUI.changed = true;
                                    e.Use();
                                }
                            }
                        }
                    }
                }
                if (e.keyCode == KeyCode.Delete)
                {
                    DLog.Log("Shift + DELETE -> Delete");
                    if (selectedObject != null && selectedObject is Challenge)
                    {
                        foreach (Stage stage in configObjectForEditor.stages)
                        {
                            foreach (Wave wave in stage.waves)
                            {
                                if (wave.challenges.Contains(selectedObject))
                                {
                                    wave.challenges.Remove((Challenge)selectedObject);
                                    selectedObject = null;
                                    GUI.changed    = true;
                                    e.Use();
                                }
                            }
                        }
                    }
                }
            }
        }
            private void DrawWaves()
            {
                foreach (Wave wave in waves)
                {
                    wave.SetStagePosition(position);
                }

                using (new EditorHelper.Indent(1))
                {
                    Wave removedWave = null;
                    for (int kIndex = 0; kIndex < waves.Count; kIndex++)
                    {
                        Wave wave = waves[kIndex];
                        wave.SetOrder(kIndex + 1);
                        wave.OnGUI();

                        if (wave.IsRemoved)
                        {
                            removedWave = wave;
                        }

                        if (wave.IsPasted && copiedWave != null)
                        {
                            waves[kIndex] = new JsonDeserializationOperation(
                                new JsonSerializationOperation(copiedWave).Act()
                                ).Act <Wave>();
                            GUI.changed = true;
                        }
                    }

                    if (removedWave != null)
                    {
                        waves.Remove(removedWave);
                        Config.ResetCacheRectData();
                    }
                }
            }
            public void OnGUI()
            {
                if (uid < 1)
                {
                    uid = Config.idBag.GenerateId();
                }

                if (Config.IsOutOfScreen(uid, out float height))
                {
                    GUILayout.Space(height);
                    return;
                }

                EditorGUILayout.Space();
                using (new EditorHelper.Box(true, 10))
                {
                    using (new EditorHelper.Indent(-2))
                        using (new EditorHelper.Horizontal())
                        {
                            enabled = EditorGUILayout.Toggle(enabled, GUILayout.ExpandWidth(false), GUILayout.Width(15));

                            bool existed = Config.waveFold.ContainsKey(this);
                            if (!existed)
                            {
                                Config.waveFold[this] = true;
                            }

                            bool     foldout = Config.waveFold[this];
                            GUIStyle gs      = new GUIStyle(EditorStyles.foldout);
                            gs.fontStyle = FontStyle.Bold;
                            gs.fontSize  = 13;
                            bool isChildSelected = false;
                            foreach (Challenge challenge in challenges)
                            {
                                if (challenge == selectedObject)
                                {
                                    isChildSelected = true;
                                }
                            }

                            if (isChildSelected)
                            {
                                gs.normal.textColor   = Color.green;
                                gs.onNormal.textColor = Color.green;
                                gs.onActive.textColor = Color.green;
                            }

                            string postfixCount = challenges.Count > 0 ? $"({challenges.Count})" : string.Empty;
                            foldout = GUILayout.Toggle(
                                foldout, $"WAVE #{waveOrder} {postfixCount}", gs,
                                GUILayout.ExpandWidth(false), GUILayout.Width(140)
                                );

                            if (Config.waveFold[this] != foldout)
                            {
                                Config.ResetCacheRectData();
                            }
                            Config.waveFold[this] = foldout;
                            if (!foldout)
                            {
                                return;
                            }

                            isRemoved = GUILayout.Button("Remove", GUILayout.Width(80));
                            if (GUILayout.Button("Add Challenge", GUILayout.Width(120)))
                            {
                                challenges.Add(new Challenge());
                            }

                            if (GUILayout.Button("Copy", GUILayout.Width(80)))
                            {
                                copiedWave = this;
                            }

                            isPasted = GUILayout.Button("Paste", GUILayout.Width(80));
                        }

                    using (new EditorHelper.Indent(-1))
                    {
                        relativePosition = EditorGUILayout.Vector2Field("Position", relativePosition);
                        foreach (Challenge challenge in challenges)
                        {
                            challenge.spawn.SetWavePosition(ShowWorldPosition());
                            challenge.spawn.SetChallenge(challenge);
                            if (challenge.trigger is DistanceTrigger)
                            {
                                ((DistanceTrigger)challenge.trigger).SetChallenge(challenge);
                            }
                        }

                        Challenge removedChallenge    = null;
                        Challenge duplicatedChallenge = null;
                        int       upIndex             = -1;
                        int       downIndex           = -1;

                        int count = challenges.Count;
                        for (int kIndex = 0; kIndex < challenges.Count; kIndex++)
                        {
                            Challenge c = challenges[kIndex];

                            c.SetOrder(kIndex + 1);
                            c.SetLastOrder(count);
                            if (c.OnPreGUI())
                            {
                                c.OnGUI();
                            }

                            if (c.IsRemoved)
                            {
                                removedChallenge = c;
                                break;
                            }

                            if (c.IsPasted)
                            {
                                challenges[kIndex] = new JsonDeserializationOperation(
                                    new JsonSerializationOperation(copiedChallenge).Act()
                                    ).Act <Challenge>();
                                GUI.changed = true;
                            }

                            if (c.IsDuplicated)
                            {
                                duplicatedChallenge = c;
                            }

                            if (c.IsMoveUp)
                            {
                                upIndex = kIndex;
                            }

                            if (c.IsMoveDown)
                            {
                                downIndex = kIndex;
                            }
                        }

                        if (removedChallenge != null)
                        {
                            challenges.Remove(removedChallenge);
                            Config.ResetCacheRectData();
                        }

                        if (duplicatedChallenge != null)
                        {
                            Challenge newChallenge = new JsonDeserializationOperation(
                                new JsonSerializationOperation(duplicatedChallenge).Act()
                                ).Act <Challenge>();
                            challenges.Add(newChallenge);
                            GUI.changed    = true;
                            selectedObject = newChallenge;
                        }

                        if (upIndex > 0)
                        {
                            challenges.Swap(upIndex, upIndex - 1);
                            Config.ResetCacheRectData();
                        }

                        if (downIndex >= 0)
                        {
                            challenges.Swap(downIndex, downIndex + 1);
                            Config.ResetCacheRectData();
                        }
                    }
                }

                if (Event.current.type == EventType.Repaint)
                {
                    Config.entryRects[uid] = GUILayoutUtility.GetLastRect();

                    /*if (GUILayoutUtility.GetLastRect().Contains(Event.current.mousePosition))
                     * {
                     *      DLog.Log("Mouse over!");
                     * }*/
                }
            }