From 6b9f77dbc9fb802d36f4af8270f38128e8c460aa Mon Sep 17 00:00:00 2001
From: lcy <1459594991@qq.com>
Date: 星期五, 23 五月 2025 11:50:29 +0800
Subject: [PATCH] 1111 摘取QHierarchy插件

---
 Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QRendererComponent.cs                       |  183 +
 Assets/Plugins/QHierarchy/Editor/Scripts/pdata/QSettingsObjectAsset.asset.meta                  |    8 
 Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QVerticesAndTrianglesCountComponent.cs.meta |   12 
 Assets/Plugins/QHierarchy/Attribute/QHierarchyNullable.asmdef                                   |    8 
 Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/pbase.meta                                  |   10 
 Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QPrefabComponent.cs                         |   92 
 Assets/Plugins/QHierarchy/Editor/QHierarchyEditor.asmdef                                        |   13 
 Assets/Plugins/QHierarchy/Editor/Scripts/phelper/QColorPickerWindow.cs                          |   68 
 Assets/Plugins/QHierarchy/Scripts/QHierarchyRuntime.asmdef                                      |    8 
 Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QGameObjectIconComponent.cs.meta            |   12 
 Assets/Plugins/QHierarchy/Editor/Scripts/pdata/QResources.cs.meta                               |   12 
 Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QTagLayerComponent.cs.meta                  |   12 
 Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QLockComponent.cs                           |  188 +
 Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QMonoBehaviorIconComponent.cs               |  102 +
 Assets/Plugins/QHierarchy.meta                                                                  |    8 
 Assets/Plugins/QHierarchy/Editor/Scripts/pdata/QSettings.cs.meta                                |   12 
 Assets/Plugins/QHierarchy/Editor/Scripts/phierarchy/QHierarchy.cs                               |  184 +
 Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QErrorComponent.cs.meta                     |   12 
 Assets/Plugins/QHierarchy/Scripts.meta                                                          |   10 
 Assets/Plugins/QHierarchy/Editor/Scripts/QHierarchyInitializer.cs                               |   61 
 Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QGameObjectIconComponent.cs                 |   79 
 Assets/Plugins/QHierarchy/Editor/Scripts/phelper/QComponentsOrderList.cs                        |  138 +
 Assets/Plugins/QHierarchy/Scripts/QObjectList.cs.meta                                           |   12 
 Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QSeparatorComponent.cs.meta                 |   12 
 Assets/Plugins/QHierarchy/Editor/Scripts/pdata/QSettingsObject.cs.meta                          |   12 
 Assets/Plugins/QHierarchy/Editor/Scripts/phierarchy/QHierarchySettingsWindow.cs.meta            |   12 
 Assets/Plugins/QHierarchy/Editor.meta                                                           |   10 
 Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QComponentsComponent.cs.meta                |   12 
 Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QRendererComponent.cs.meta                  |   12 
 Assets/Plugins/QHierarchy/Editor/Scripts/phierarchy/QHierarchy.cs.meta                          |   12 
 Assets/Plugins/QHierarchy/Attribute.meta                                                        |    8 
 Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QTagIconComponent.cs.meta                   |   12 
 Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QTreeMapComponent.cs.meta                   |   12 
 Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QLayerIconComponent.cs                      |   68 
 Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QVerticesAndTrianglesCountComponent.cs      |  151 +
 Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/pbase/QBaseComponent.cs.meta                |   12 
 Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QStaticComponent.cs.meta                    |   12 
 Assets/Plugins/QHierarchy/Editor/Scripts/phelper/QColorUtils.cs                                 |   63 
 Assets/Plugins/QHierarchy/Editor/Scripts/phelper/QComponentsOrderList.cs.meta                   |   12 
 Assets/Plugins/QHierarchy/Editor/Scripts/phelper/QObjectListInspector.cs                        |   35 
 Assets/Plugins/QHierarchy/Editor/Scripts/phelper/QColorPickerWindow.cs.meta                     |   12 
 Assets/Plugins/QHierarchy/Editor/Scripts/phelper/QObjectListManager.cs.meta                     |   12 
 Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent.meta                                        |   10 
 Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QVisibilityComponent.cs                     |  292 ++
 Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QMonoBehaviorIconComponent.cs.meta          |   12 
 Assets/Plugins/QHierarchy/Editor/Scripts/pdata/QSettings.cs                                     |  525 +++++
 Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QComponentsComponent.cs                     |  180 +
 Assets/Plugins/QHierarchy/Scripts/QHierarchyRuntime.asmdef.meta                                 |    7 
 Assets/Plugins/QHierarchy/Manual.pdf.meta                                                       |    8 
 Assets/Plugins/QHierarchy/Editor/Scripts/QHierarchyInitializer.cs.meta                          |   12 
 Assets/Plugins/QHierarchy/Editor/QHierarchyEditor.asmdef.meta                                   |    7 
 Assets/Plugins/QHierarchy/Editor/Scripts/phierarchy/QHierarchySettingsWindow.cs                 |  827 ++++++++
 Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QColorComponent.cs                          |  127 +
 Assets/Plugins/QHierarchy/Attribute/QHierarchyNullable.cs                                       |    6 
 Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QErrorComponent.cs                          |  441 ++++
 Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QLayerIconComponent.cs.meta                 |   12 
 Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QStaticComponent.cs                         |  150 +
 Assets/Plugins/QHierarchy/Scripts/QObjectList.cs                                                |  158 +
 Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/pbase/QBaseComponent.cs                     |   81 
 Assets/Plugins/QHierarchy/Editor/Scripts/phelper/QColorUtils.cs.meta                            |   12 
 Assets/Plugins/QHierarchy/Editor/Scripts/pdata.meta                                             |   10 
 Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QTagLayerComponent.cs                       |  250 ++
 Assets/Plugins/QHierarchy/Editor/Scripts/phelper/QObjectListInspector.cs.meta                   |   12 
 Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QSeparatorComponent.cs                      |   64 
 Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QVisibilityComponent.cs.meta                |   12 
 Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QLockComponent.cs.meta                      |   12 
 Assets/Plugins/QHierarchy/Editor/Scripts/phelper.meta                                           |   10 
 Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QChildrenCountComponent.cs                  |   71 
 Assets/Plugins/QHierarchy/Attribute/QHierarchyNullable.cs.meta                                  |   11 
 Assets/Plugins/QHierarchy/Manual.pdf                                                            |    0 
 Assets/Plugins/QHierarchy/Attribute/QHierarchyNullable.asmdef.meta                              |    7 
 Assets/Plugins/QHierarchy/Editor/Scripts/pdata/QResources.cs                                    |  140 +
 Assets/Plugins/QHierarchy/Editor/Scripts/pdata/QSettingsObjectAsset.asset                       |  158 +
 Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QChildrenCountComponent.cs.meta             |   12 
 Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QTagIconComponent.cs                        |   70 
 Assets/Plugins/QHierarchy/Editor/Scripts/phelper/QObjectListManager.cs                          |  268 ++
 Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QColorComponent.cs.meta                     |   12 
 Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QTreeMapComponent.cs                        |  173 +
 Assets/Plugins/QHierarchy/Editor/Scripts.meta                                                   |   10 
 Assets/Plugins/QHierarchy/Editor/Scripts/pdata/QSettingsObject.cs                               |  135 +
 Assets/Plugins/QHierarchy/Editor/Scripts/phierarchy.meta                                        |   10 
 Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QPrefabComponent.cs.meta                    |   12 
 82 files changed, 6,061 insertions(+), 0 deletions(-)

diff --git a/Assets/Plugins/QHierarchy.meta b/Assets/Plugins/QHierarchy.meta
new file mode 100644
index 0000000..2056925
--- /dev/null
+++ b/Assets/Plugins/QHierarchy.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 18522f6686dce6648a73d22d421c94ac
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Plugins/QHierarchy/Attribute.meta b/Assets/Plugins/QHierarchy/Attribute.meta
new file mode 100644
index 0000000..a81aab3
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Attribute.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 602672b16b2911c47892de4f436d5894
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Plugins/QHierarchy/Attribute/QHierarchyNullable.asmdef b/Assets/Plugins/QHierarchy/Attribute/QHierarchyNullable.asmdef
new file mode 100644
index 0000000..dc547a2
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Attribute/QHierarchyNullable.asmdef
@@ -0,0 +1,8 @@
+{
+    "name": "QHierarchyNullable",
+    "references": [],
+    "optionalUnityReferences": [],
+    "includePlatforms": [],
+    "excludePlatforms": [],
+    "allowUnsafeCode": false
+}
\ No newline at end of file
diff --git a/Assets/Plugins/QHierarchy/Attribute/QHierarchyNullable.asmdef.meta b/Assets/Plugins/QHierarchy/Attribute/QHierarchyNullable.asmdef.meta
new file mode 100644
index 0000000..a3d4739
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Attribute/QHierarchyNullable.asmdef.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 784c1df74834cb743a426a6126f1064d
+AssemblyDefinitionImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Plugins/QHierarchy/Attribute/QHierarchyNullable.cs b/Assets/Plugins/QHierarchy/Attribute/QHierarchyNullable.cs
new file mode 100644
index 0000000..01f8640
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Attribute/QHierarchyNullable.cs
@@ -0,0 +1,6 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+public class QHierarchyNullableAttribute: PropertyAttribute {
+}
\ No newline at end of file
diff --git a/Assets/Plugins/QHierarchy/Attribute/QHierarchyNullable.cs.meta b/Assets/Plugins/QHierarchy/Attribute/QHierarchyNullable.cs.meta
new file mode 100644
index 0000000..cc8aec6
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Attribute/QHierarchyNullable.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 15892d7337a046e43b2c6bad21242c1a
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Plugins/QHierarchy/Editor.meta b/Assets/Plugins/QHierarchy/Editor.meta
new file mode 100644
index 0000000..b3deb24
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor.meta
@@ -0,0 +1,10 @@
+fileFormatVersion: 2
+guid: 325ffd836cb52054d9f615250b95398d
+folderAsset: yes
+timeCreated: 1515657177
+licenseType: Store
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Plugins/QHierarchy/Editor/QHierarchyEditor.asmdef b/Assets/Plugins/QHierarchy/Editor/QHierarchyEditor.asmdef
new file mode 100644
index 0000000..1f301c1
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/QHierarchyEditor.asmdef
@@ -0,0 +1,13 @@
+{
+    "name": "QHierarchyEditor",
+    "references": [
+        "QHierarchyNullable",
+        "QHierarchyRuntime"
+    ],
+    "optionalUnityReferences": [],
+    "includePlatforms": [
+        "Editor"
+    ],
+    "excludePlatforms": [],
+    "allowUnsafeCode": false
+}
\ No newline at end of file
diff --git a/Assets/Plugins/QHierarchy/Editor/QHierarchyEditor.asmdef.meta b/Assets/Plugins/QHierarchy/Editor/QHierarchyEditor.asmdef.meta
new file mode 100644
index 0000000..3c0d4b8
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/QHierarchyEditor.asmdef.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 49674d15b25185649b7ec8ac5d378747
+AssemblyDefinitionImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts.meta b/Assets/Plugins/QHierarchy/Editor/Scripts.meta
new file mode 100644
index 0000000..9902f40
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts.meta
@@ -0,0 +1,10 @@
+fileFormatVersion: 2
+guid: a37008235cb5c0c4b9ca8932a016d63c
+folderAsset: yes
+timeCreated: 1515657177
+licenseType: Store
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/QHierarchyInitializer.cs b/Assets/Plugins/QHierarchy/Editor/Scripts/QHierarchyInitializer.cs
new file mode 100644
index 0000000..1024763
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/QHierarchyInitializer.cs
@@ -0,0 +1,61 @@
+using UnityEngine;
+using UnityEditor;
+using System;
+using System.Collections.Generic;
+using qtools.qhierarchy.pdata;
+using qtools.qhierarchy.phierarchy;
+using UnityEditor.Callbacks;
+using qtools.qhierarchy.phelper;
+
+namespace qtools.qhierarchy
+{
+    [InitializeOnLoad]
+    public class QHierarchyInitializer
+    {
+        private static QHierarchy hierarchy;
+
+        static QHierarchyInitializer()
+        {
+            EditorApplication.update -= update;
+            EditorApplication.update += update;
+
+            EditorApplication.hierarchyWindowItemOnGUI -= hierarchyWindowItemOnGUIHandler;
+            EditorApplication.hierarchyWindowItemOnGUI += hierarchyWindowItemOnGUIHandler;
+            
+            EditorApplication.hierarchyChanged -= hierarchyWindowChanged;
+            EditorApplication.hierarchyChanged += hierarchyWindowChanged;
+
+            Undo.undoRedoPerformed -= undoRedoPerformed;
+            Undo.undoRedoPerformed += undoRedoPerformed;
+        }
+
+        static void undoRedoPerformed()
+        {
+            EditorApplication.RepaintHierarchyWindow();          
+        }
+
+        static void init()
+        {       
+            hierarchy = new QHierarchy();
+        } 
+
+        static void update()
+        {
+            if (hierarchy == null) init();
+            QObjectListManager.getInstance().update();
+        }
+
+        static void hierarchyWindowItemOnGUIHandler(int instanceId, Rect selectionRect)
+        {
+            if (hierarchy == null) init();
+             hierarchy.hierarchyWindowItemOnGUIHandler(instanceId, selectionRect);
+        }
+
+        static void hierarchyWindowChanged()
+        {
+            if (hierarchy == null) init();
+            QObjectListManager.getInstance().validate();
+        }
+    }
+}
+
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/QHierarchyInitializer.cs.meta b/Assets/Plugins/QHierarchy/Editor/Scripts/QHierarchyInitializer.cs.meta
new file mode 100644
index 0000000..0ad0eca
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/QHierarchyInitializer.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 91dfc025140434846819647cecf3bd95
+timeCreated: 1474889436
+licenseType: Store
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent.meta b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent.meta
new file mode 100644
index 0000000..d54e350
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent.meta
@@ -0,0 +1,10 @@
+fileFormatVersion: 2
+guid: 745985dd54264b14faabbb60338e354e
+folderAsset: yes
+timeCreated: 1515657177
+licenseType: Store
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QChildrenCountComponent.cs b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QChildrenCountComponent.cs
new file mode 100644
index 0000000..12c04cc
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QChildrenCountComponent.cs
@@ -0,0 +1,71 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEditor;
+using qtools.qhierarchy.pcomponent.pbase;
+using qtools.qhierarchy.phierarchy;
+using qtools.qhierarchy.phelper;
+using qtools.qhierarchy.pdata;
+
+namespace qtools.qhierarchy.pcomponent
+{
+    public class QChildrenCountComponent: QBaseComponent 
+    {
+        // PRIVATE
+        private GUIStyle labelStyle;
+
+        // CONSTRUCTOR
+        public QChildrenCountComponent ()
+        {
+            labelStyle = new GUIStyle();
+            labelStyle.fontSize = 9;
+            labelStyle.clipping = TextClipping.Clip;  
+            labelStyle.alignment = TextAnchor.MiddleRight;
+
+            rect.width = 22;
+            rect.height = 16;
+
+            QSettings.getInstance().addEventListener(QSetting.ChildrenCountShow              , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.ChildrenCountShowDuringPlayMode, settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.ChildrenCountLabelSize         , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.ChildrenCountLabelColor        , settingsChanged);
+            settingsChanged();
+        }
+
+        // PRIVATE
+        private void settingsChanged()
+        {
+            enabled = QSettings.getInstance().get<bool>(QSetting.ChildrenCountShow);
+            showComponentDuringPlayMode = QSettings.getInstance().get<bool>(QSetting.ChildrenCountShowDuringPlayMode);
+            QHierarchySize labelSize = (QHierarchySize)QSettings.getInstance().get<int>(QSetting.ChildrenCountLabelSize);
+            labelStyle.normal.textColor = QSettings.getInstance().getColor(QSetting.ChildrenCountLabelColor);
+            labelStyle.fontSize = labelSize == QHierarchySize.Normal ? 8 : 9;
+            rect.width = labelSize == QHierarchySize.Normal ? 17 : 22;
+        }
+
+        // DRAW
+        public override QLayoutStatus layout(GameObject gameObject, QObjectList objectList, Rect selectionRect, ref Rect curRect, float maxWidth)
+        {
+            if (maxWidth < rect.width)
+            {
+                return QLayoutStatus.Failed;
+            }
+            else
+            {
+                curRect.x -= rect.width + 2;
+                rect.x = curRect.x;
+                rect.y = curRect.y;
+                rect.y += (EditorGUIUtility.singleLineHeight - rect.height) * 0.5f;
+                rect.height = EditorGUIUtility.singleLineHeight;
+                return QLayoutStatus.Success;
+            }
+        }
+        
+        public override void draw(GameObject gameObject, QObjectList objectList, Rect selectionRect)
+        {  
+            int childrenCount = gameObject.transform.childCount;
+            if (childrenCount > 0) GUI.Label(rect, childrenCount.ToString(), labelStyle);
+        }
+    }
+}
+
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QChildrenCountComponent.cs.meta b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QChildrenCountComponent.cs.meta
new file mode 100644
index 0000000..15e5cf0
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QChildrenCountComponent.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 3a751e5b6a52db74383e8cf84b464a37
+timeCreated: 1475158786
+licenseType: Store
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QColorComponent.cs b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QColorComponent.cs
new file mode 100644
index 0000000..f848257
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QColorComponent.cs
@@ -0,0 +1,127 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEditor;
+using qtools.qhierarchy.pcomponent.pbase;
+using qtools.qhierarchy.pdata;
+using qtools.qhierarchy.phelper;
+
+namespace qtools.qhierarchy.pcomponent
+{
+    public class QColorComponent: QBaseComponent
+    {
+        // PRIVATE
+        private Color inactiveColor;
+        private Texture2D colorTexture;
+        private Rect colorRect = new Rect();
+
+        // CONSTRUCTOR
+        public QColorComponent()
+        {
+            colorTexture = QResources.getInstance().getTexture(QTexture.QColorButton);
+
+            rect.width = 8;
+            rect.height = 16;
+
+            QSettings.getInstance().addEventListener(QSetting.ColorShow              , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.ColorShowDuringPlayMode, settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.AdditionalInactiveColor, settingsChanged);
+            settingsChanged();
+        }
+
+        // PRIVATE
+        private void settingsChanged()
+        {
+            enabled                     = QSettings.getInstance().get<bool>(QSetting.ColorShow);
+            showComponentDuringPlayMode = QSettings.getInstance().get<bool>(QSetting.ColorShowDuringPlayMode);
+            inactiveColor               = QSettings.getInstance().getColor(QSetting.AdditionalInactiveColor);
+        }
+
+        // LAYOUT
+        public override QLayoutStatus layout(GameObject gameObject, QObjectList objectList, Rect selectionRect, ref Rect curRect, float maxWidth)
+        {
+            if (maxWidth < 8)
+            {
+                return QLayoutStatus.Failed;
+            }
+            else
+            {
+                curRect.x -= 8;
+                rect.x = curRect.x;
+                rect.y = curRect.y;
+                return QLayoutStatus.Success;
+            }
+        }
+
+        // DRAW
+        public override void draw(GameObject gameObject, QObjectList objectList, Rect selectionRect)
+        {
+            if (objectList != null)
+            {
+                Color newColor;
+                if (objectList.gameObjectColor.TryGetValue(gameObject, out newColor))
+                {
+                    colorRect.Set(rect.x + 1, rect.y + 1, 5, rect.height - 1);
+                    EditorGUI.DrawRect(colorRect, newColor);
+                    return;
+                }
+            }
+
+            QColorUtils.setColor(inactiveColor);
+            GUI.DrawTexture(rect, colorTexture, ScaleMode.StretchToFill, true, 1);
+            QColorUtils.clearColor();
+        }
+
+        // EVENTS
+        public override void eventHandler(GameObject gameObject, QObjectList objectList, Event currentEvent)
+        {
+            if (currentEvent.isMouse && currentEvent.type == EventType.MouseDown && currentEvent.button == 0 && rect.Contains(currentEvent.mousePosition))
+            {
+                if (currentEvent.type == EventType.MouseDown)
+                {
+                    try {
+                        PopupWindow.Show(rect, new QColorPickerWindow(Selection.Contains(gameObject) ? Selection.gameObjects : new GameObject[] { gameObject }, colorSelectedHandler, colorRemovedHandler));
+                    } 
+                    catch {}
+                }
+                currentEvent.Use();
+            }
+        }
+
+        // PRIVATE
+        private void colorSelectedHandler(GameObject[] gameObjects, Color color)
+        {
+            for (int i = gameObjects.Length - 1; i >= 0; i--)
+            {
+                GameObject gameObject = gameObjects[i];
+                QObjectList objectList = QObjectListManager.getInstance().getObjectList(gameObjects[i], true);
+                Undo.RecordObject(objectList, "Color Changed");
+                if (objectList.gameObjectColor.ContainsKey(gameObject))
+                {
+                    objectList.gameObjectColor[gameObject] = color;
+                }
+                else
+                {
+                    objectList.gameObjectColor.Add(gameObject, color);
+                }                
+            }
+            EditorApplication.RepaintHierarchyWindow();
+        }
+
+        private void colorRemovedHandler(GameObject[] gameObjects)
+        {
+            for (int i = gameObjects.Length - 1; i >= 0; i--)
+            {
+                GameObject gameObject = gameObjects[i];
+                QObjectList objectList = QObjectListManager.getInstance().getObjectList(gameObjects[i], true);
+                if (objectList.gameObjectColor.ContainsKey(gameObject))                
+                {
+                    Undo.RecordObject(objectList, "Color Changed");
+                    objectList.gameObjectColor.Remove(gameObject);                          
+                }
+            }
+            EditorApplication.RepaintHierarchyWindow();
+        }
+    }
+}
+
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QColorComponent.cs.meta b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QColorComponent.cs.meta
new file mode 100644
index 0000000..8770196
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QColorComponent.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 80272015235c35e4eaa83bc0ae9c98f6
+timeCreated: 1475047533
+licenseType: Store
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QComponentsComponent.cs b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QComponentsComponent.cs
new file mode 100644
index 0000000..fd4bb0e
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QComponentsComponent.cs
@@ -0,0 +1,180 @@
+using System;
+using System.Reflection;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEditor;
+using qtools.qhierarchy.pcomponent.pbase;
+using qtools.qhierarchy.pdata;
+using qtools.qhierarchy.phelper;
+
+namespace qtools.qhierarchy.pcomponent
+{
+    public class QComponentsComponent: QBaseComponent
+    {
+        // PRIVATE
+        private GUIStyle hintLabelStyle;
+        private Color grayColor;
+        private Color backgroundDarkColor;
+        private Texture2D componentIcon;
+        private List<Component> components = new List<Component>();   
+        private Rect eventRect = new Rect(0, 0, 16, 16);
+        private int componentsToDraw;
+        private List<string> ignoreScripts;
+
+        // CONSTRUCTOR
+        public QComponentsComponent ()
+        {
+            this.backgroundDarkColor = QResources.getInstance().getColor(QColor.BackgroundDark);
+            this.grayColor           = QResources.getInstance().getColor(QColor.Gray);
+            this.componentIcon       = QResources.getInstance().getTexture(QTexture.QComponentUnknownIcon);
+
+            hintLabelStyle = new GUIStyle();
+            hintLabelStyle.normal.textColor = grayColor;
+            hintLabelStyle.fontSize = 11;
+            hintLabelStyle.clipping = TextClipping.Clip;  
+
+            QSettings.getInstance().addEventListener(QSetting.ComponentsShow              , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.ComponentsShowDuringPlayMode, settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.ComponentsIconSize          , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.ComponentsIgnore            , settingsChanged);
+            settingsChanged();
+        }
+
+        // PRIVATE
+        private void settingsChanged()
+        {
+            enabled                     = QSettings.getInstance().get<bool>(QSetting.ComponentsShow);
+            showComponentDuringPlayMode = QSettings.getInstance().get<bool>(QSetting.ComponentsShowDuringPlayMode);
+            QHierarchySizeAll size = (QHierarchySizeAll)QSettings.getInstance().get<int>(QSetting.ComponentsIconSize);
+            rect.width = rect.height = (size == QHierarchySizeAll.Normal ? 15 : (size == QHierarchySizeAll.Big ? 16 : 13));       
+
+            string ignoreString = QSettings.getInstance().get<string>(QSetting.ComponentsIgnore);
+            if (ignoreString != "") 
+            {
+                ignoreScripts = new List<string>(ignoreString.Split(new char[] { ',', ';', '.', ' ' }));
+                ignoreScripts.RemoveAll(item => item == "");
+            }
+            else ignoreScripts = null;
+        }
+
+        // DRAW
+        public override QLayoutStatus layout(GameObject gameObject, QObjectList objectList, Rect selectionRect, ref Rect curRect, float maxWidth)
+        {
+            Component[] currentComponents = gameObject.GetComponents<Component>();
+
+            components.Clear();
+            if (ignoreScripts != null)
+            {
+                for (int i = 0; i < currentComponents.Length; i++)
+                {
+                    string componentName = currentComponents[i].GetType().FullName;
+                    bool ignore = false;
+                    for (int j = ignoreScripts.Count - 1; j >= 0; j--)
+                    {
+                        if (componentName.Contains(ignoreScripts[j]))
+                        {
+                            ignore = true;
+                            break;
+                        } 
+                    }
+                    if (!ignore) components.Add(currentComponents[i]);
+                }
+            }
+            else
+            {
+                components.AddRange(currentComponents);
+            }
+
+            int maxComponentsCount = Mathf.FloorToInt((maxWidth - 2) / rect.width);
+            componentsToDraw = Math.Min(maxComponentsCount, components.Count - 1);
+
+            float totalWidth = 2 + rect.width * componentsToDraw;
+    
+            curRect.x -= totalWidth;
+
+            rect.x = curRect.x;
+            rect.y = curRect.y - (rect.height - 16) / 2;
+
+            eventRect.width = totalWidth;
+            eventRect.x = rect.x;
+            eventRect.y = rect.y;
+
+            if (maxComponentsCount >= components.Count - 1) return QLayoutStatus.Success;
+            else if (maxComponentsCount == 0) return QLayoutStatus.Failed;
+            else return QLayoutStatus.Partly;
+        }
+
+        public override void draw(GameObject gameObject, QObjectList objectList, Rect selectionRect)
+        {
+            for (int i = components.Count - componentsToDraw, n = components.Count; i < n; i++)
+            {
+                Component component = components[i];
+                if (component is Transform) continue;
+                                
+                GUIContent content = EditorGUIUtility.ObjectContent(component, null);
+
+                bool enabled = true;
+                try
+                {
+                    PropertyInfo propertyInfo = component.GetType().GetProperty("enabled");
+                    enabled = (bool)propertyInfo.GetGetMethod().Invoke(component, null);
+                }
+                catch {}
+
+                Color color = GUI.color;
+                color.a = enabled ? 1f : 0.3f;
+                GUI.color = color;
+                GUI.DrawTexture(rect, content.image == null ? componentIcon : content.image, ScaleMode.ScaleToFit);
+                color.a = 1;
+                GUI.color = color;
+
+                if (rect.Contains(Event.current.mousePosition))
+                {        
+                    string componentName = "Missing script";
+                    if (component != null) componentName = component.GetType().Name;
+
+                    int labelWidth = Mathf.CeilToInt(hintLabelStyle.CalcSize(new GUIContent(componentName)).x);                    
+                    selectionRect.x = rect.x - labelWidth / 2 - 4;
+                    selectionRect.width = labelWidth + 8;
+                    selectionRect.height -= 1;
+
+                    if (selectionRect.y > 16) selectionRect.y -= 16;
+                    else selectionRect.x += labelWidth / 2 + 18;
+
+                    EditorGUI.DrawRect(selectionRect, backgroundDarkColor);
+                    selectionRect.x += 4;
+                    selectionRect.y += (EditorGUIUtility.singleLineHeight - rect.height) * 0.5f;
+                    selectionRect.height = EditorGUIUtility.singleLineHeight;
+
+                    EditorGUI.LabelField(selectionRect, componentName, hintLabelStyle);
+                }
+
+                rect.x += rect.width;
+            }
+        }
+
+        public override void eventHandler(GameObject gameObject, QObjectList objectList, Event currentEvent)
+        {
+            if (currentEvent.isMouse && currentEvent.button == 0 && eventRect.Contains(currentEvent.mousePosition))
+            {
+                if (currentEvent.type == EventType.MouseDown)
+                {
+                    int id = Mathf.FloorToInt((currentEvent.mousePosition.x - eventRect.x) / rect.width) + components.Count - 1 - componentsToDraw + 1;
+
+                    try
+                    {
+                        PropertyInfo propertyInfo = components[id].GetType().GetProperty("enabled");
+                        bool enabled = (bool)propertyInfo.GetGetMethod().Invoke(components[id], null);
+                        Undo.RecordObject(components[id], enabled ? "Disable Component" : "Enable Component");
+                        propertyInfo.GetSetMethod().Invoke(components[id], new object[] { !enabled });
+                    }
+                    catch {}
+
+                    EditorUtility.SetDirty(gameObject);
+                }
+                currentEvent.Use();
+            }
+        }
+    }
+}
+
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QComponentsComponent.cs.meta b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QComponentsComponent.cs.meta
new file mode 100644
index 0000000..23b0ba9
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QComponentsComponent.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: cab84ea181377234dbcf62f89639b9b3
+timeCreated: 1475067899
+licenseType: Store
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QErrorComponent.cs b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QErrorComponent.cs
new file mode 100644
index 0000000..115661d
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QErrorComponent.cs
@@ -0,0 +1,441 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEditor;
+using UnityEngine.Events;
+using qtools.qhierarchy.pcomponent.pbase;
+using qtools.qhierarchy.phierarchy;
+using qtools.qhierarchy.phelper;
+using qtools.qhierarchy.pdata;
+using System.Reflection;
+using System.Collections;
+using UnityEditorInternal;
+using System.Text;
+
+namespace qtools.qhierarchy.pcomponent
+{
+    public class QErrorComponent: QBaseComponent
+    {
+        // PRIVATE
+        private Color activeColor;
+        private Color inactiveColor;
+        private Texture2D errorIconTexture;
+        private bool showErrorOfChildren;
+        private bool showErrorTypeReferenceIsNull;
+        private bool showErrorTypeReferenceIsMissing;
+        private bool showErrorTypeStringIsEmpty;
+        private bool showErrorIconScriptIsMissing;
+        private bool showErrorIconWhenTagIsUndefined;
+        private bool showErrorForDisabledComponents;
+        private bool showErrorIconMissingEventMethod;
+        private bool showErrorForDisabledGameObjects;
+        private List<string> ignoreErrorOfMonoBehaviours;
+        private StringBuilder errorStringBuilder;
+        private int errorCount;
+
+        // CONSTRUCTOR
+        public QErrorComponent ()
+        {
+            rect.width = 7; 
+
+            errorIconTexture = QResources.getInstance().getTexture(QTexture.QErrorIcon);
+
+            QSettings.getInstance().addEventListener(QSetting.ErrorShowIconOnParent             , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.ErrorShowReferenceIsNull          , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.ErrorShowReferenceIsMissing       , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.ErrorShowStringIsEmpty            , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.ErrorShowScriptIsMissing          , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.ErrorShowForDisabledComponents    , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.ErrorShowForDisabledGameObjects   , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.ErrorShowMissingEventMethod       , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.ErrorShowWhenTagOrLayerIsUndefined, settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.ErrorShow                         , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.ErrorShowDuringPlayMode           , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.ErrorIgnoreString                 , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.AdditionalActiveColor             , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.AdditionalInactiveColor           , settingsChanged);
+            settingsChanged();
+        }
+
+        // PRIVATE
+        private void settingsChanged()
+        {
+            showErrorOfChildren             = QSettings.getInstance().get<bool>(QSetting.ErrorShowIconOnParent);
+            showErrorTypeReferenceIsNull    = QSettings.getInstance().get<bool>(QSetting.ErrorShowReferenceIsNull);
+            showErrorTypeReferenceIsMissing = QSettings.getInstance().get<bool>(QSetting.ErrorShowReferenceIsMissing);
+            showErrorTypeStringIsEmpty      = QSettings.getInstance().get<bool>(QSetting.ErrorShowStringIsEmpty);
+            showErrorIconScriptIsMissing    = QSettings.getInstance().get<bool>(QSetting.ErrorShowScriptIsMissing);
+            showErrorForDisabledComponents  = QSettings.getInstance().get<bool>(QSetting.ErrorShowForDisabledComponents);
+            showErrorForDisabledGameObjects = QSettings.getInstance().get<bool>(QSetting.ErrorShowForDisabledGameObjects);
+            showErrorIconMissingEventMethod = QSettings.getInstance().get<bool>(QSetting.ErrorShowMissingEventMethod);
+            showErrorIconWhenTagIsUndefined = QSettings.getInstance().get<bool>(QSetting.ErrorShowWhenTagOrLayerIsUndefined);
+            activeColor                     = QSettings.getInstance().getColor(QSetting.AdditionalActiveColor);
+            inactiveColor                   = QSettings.getInstance().getColor(QSetting.AdditionalInactiveColor);
+            enabled                         = QSettings.getInstance().get<bool>(QSetting.ErrorShow);
+            showComponentDuringPlayMode     = QSettings.getInstance().get<bool>(QSetting.ErrorShowDuringPlayMode);
+
+            string ignoreErrorOfMonoBehavioursString = QSettings.getInstance().get<string>(QSetting.ErrorIgnoreString);
+            if (ignoreErrorOfMonoBehavioursString != "") 
+            {
+                ignoreErrorOfMonoBehaviours = new List<string>(ignoreErrorOfMonoBehavioursString.Split(new char[] { ',', ';', '.', ' ' }));
+                ignoreErrorOfMonoBehaviours.RemoveAll(item => item == "");
+            }
+            else ignoreErrorOfMonoBehaviours = null;
+        }
+
+        // DRAW
+        public override QLayoutStatus layout(GameObject gameObject, QObjectList objectList, Rect selectionRect, ref Rect curRect, float maxWidth)
+        {
+            if (maxWidth < 7) 
+            {
+                return QLayoutStatus.Failed;
+            }
+            else
+            {
+                curRect.x -= 7;
+                rect.x = curRect.x;
+                rect.y = curRect.y;
+                return QLayoutStatus.Success;
+            }
+        }
+
+        public override void draw(GameObject gameObject, QObjectList objectList, Rect selectionRect)
+        {
+            bool errorFound = findError(gameObject, gameObject.GetComponents<MonoBehaviour>());
+
+            if (errorFound)
+            {           
+                QColorUtils.setColor(activeColor);
+                GUI.DrawTexture(rect, errorIconTexture);
+                QColorUtils.clearColor();
+            }
+            else if (showErrorOfChildren) 
+            {
+                errorFound = findError(gameObject, gameObject.GetComponentsInChildren<MonoBehaviour>(true));
+                if (errorFound) 
+                {
+                    QColorUtils.setColor(inactiveColor);
+                    GUI.DrawTexture(rect, errorIconTexture);
+                    QColorUtils.clearColor();
+                }
+            }            
+        }
+
+        public override void eventHandler(GameObject gameObject, QObjectList objectList, Event currentEvent)
+        {
+            if (currentEvent.isMouse && currentEvent.type == EventType.MouseDown && currentEvent.button == 0 && rect.Contains(currentEvent.mousePosition))
+            {
+                currentEvent.Use();
+
+                errorCount = 0;
+                errorStringBuilder = new StringBuilder();
+                findError(gameObject, gameObject.GetComponents<MonoBehaviour>(), true);
+
+                if (errorCount > 0)
+                {
+                    EditorUtility.DisplayDialog(errorCount + (errorCount == 1 ? " error was found" : " errors were found"), errorStringBuilder.ToString(), "OK");
+                }
+            }
+        }
+
+        // PRIVATE
+        private bool findError(GameObject gameObject, MonoBehaviour[] components, bool printError = false)
+        {
+            if (showErrorIconWhenTagIsUndefined)
+            {
+                try
+                { 
+                    gameObject.tag.CompareTo(null); 
+                }
+                catch 
+                {
+                    if (printError)
+                    {
+                        appendErrorLine("Tag is undefined");
+                    }
+                    else
+                    {
+                        return true;
+                    }
+                }
+
+                if (LayerMask.LayerToName(gameObject.layer).Equals("")) 
+                {
+                    if (printError)
+                    {
+                        appendErrorLine("Layer is undefined");
+                    }
+                    else
+                    {
+                        return true;
+                    }
+                }
+            }
+
+            for (int i = 0; i < components.Length; i++)
+            {
+                MonoBehaviour monoBehaviour = components[i];
+                if (monoBehaviour == null)
+                {
+                    if (showErrorIconScriptIsMissing)
+                    {
+                        if (printError)
+                        {
+                            appendErrorLine("Component #" + i + " is missing");
+                        }
+                        else
+                        {
+                            return true;
+                        }
+                    }
+                }
+                else
+                {
+                    if (ignoreErrorOfMonoBehaviours != null)
+                    {
+                        for (int j = ignoreErrorOfMonoBehaviours.Count - 1; j >= 0; j--)
+                        {
+                            if (monoBehaviour.GetType().FullName.Contains(ignoreErrorOfMonoBehaviours[j]))
+                            {
+                                return false;
+                            } 
+                        }
+                    }
+
+                    if (showErrorIconMissingEventMethod)
+                    {
+                        if (monoBehaviour.gameObject.activeSelf || showErrorForDisabledComponents)
+                        {
+                            try
+                            {
+                                if (isUnityEventsNullOrMissing(monoBehaviour, printError))
+                                {
+                                    if (!printError)
+                                    {
+                                        return true;
+                                    }
+                                }
+                            }
+                            catch
+                            {
+                            }
+                        }
+                    }
+
+                    if (showErrorTypeReferenceIsNull || showErrorTypeStringIsEmpty || showErrorTypeReferenceIsMissing)
+                    {                       
+                        if (!monoBehaviour.enabled && !showErrorForDisabledComponents) continue;
+                        if (!monoBehaviour.gameObject.activeSelf && !showErrorForDisabledGameObjects) continue;
+
+						Type type = monoBehaviour.GetType();
+
+                        while (type != null) {
+							
+							BindingFlags bf = BindingFlags.Instance | BindingFlags.Public;
+							if (!type.FullName.Contains("UnityEngine")) 
+								bf |= BindingFlags.NonPublic;
+							FieldInfo[] fieldArray = type.GetFields(bf);
+
+							for (int j = 0; j < fieldArray.Length; j++)
+							{
+								FieldInfo field = fieldArray[j];
+
+                                if (System.Attribute.IsDefined(field, typeof(HideInInspector)) || 
+                                    System.Attribute.IsDefined(field, typeof(QHierarchyNullableAttribute)) ||									
+                                    System.Attribute.IsDefined(field, typeof(NonSerializedAttribute)) ||
+									field.IsStatic) continue;     
+
+								if (field.IsPrivate || !field.IsPublic) 
+								{
+									if (!Attribute.IsDefined(field, typeof(SerializeField)))
+									{
+										continue;
+									}
+								}
+
+								object value = field.GetValue(monoBehaviour);
+
+								try
+								{
+									if (showErrorTypeStringIsEmpty && field.FieldType == typeof(string) && value != null && ((string)value).Equals(""))
+									{                                
+										if (printError)
+										{
+											appendErrorLine(monoBehaviour.GetType().Name + "." + field.Name + ": String value is empty");
+											continue;
+										}
+										else
+										{
+											return true;                                 
+										}
+									}
+								}
+								catch
+								{
+								}
+
+								try
+								{
+									if (showErrorTypeReferenceIsMissing && value != null && value is Component && (Component)value == null)
+									{
+										if (printError)
+										{
+											appendErrorLine(monoBehaviour.GetType().Name + "." + field.Name + ": Reference is missing");
+											continue;
+										}
+										else
+										{
+											return true;
+										}
+									}
+								}
+								catch
+								{
+								}
+
+								try
+								{
+									if (showErrorTypeReferenceIsNull && (value == null || value.Equals(null)))
+									{           
+										if (printError)
+										{
+											appendErrorLine(monoBehaviour.GetType().Name + "." + field.Name + ": Reference is null");
+											continue;
+										}
+										else
+										{
+											return true;
+										}
+									}
+								}
+								catch
+								{
+								}
+										  
+								try
+								{
+									if (showErrorTypeReferenceIsNull && value != null && (value is IEnumerable))
+									{
+										foreach (var item in (IEnumerable)value)
+										{
+											if (item == null || item.Equals(null))
+											{
+												if (printError)
+												{
+													appendErrorLine(monoBehaviour.GetType().Name + "." + field.Name + ": IEnumerable has value with null reference");
+													continue;
+												}
+												else
+												{
+													return true;
+												}
+											}
+										}
+									}
+								}
+								catch
+								{
+								}                            
+							}
+                            type = type.BaseType;
+						}
+                    }
+                }
+            }
+            return false;
+        }
+
+        private List<string> targetPropertiesNames = new List<string>(10);
+        
+        private bool isUnityEventsNullOrMissing(MonoBehaviour monoBehaviour, bool printError) 
+        {
+            targetPropertiesNames.Clear();
+            FieldInfo[] fieldArray = monoBehaviour.GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); 
+   
+            for (int i = fieldArray.Length - 1; i >= 0; i--) 
+            {
+                FieldInfo field = fieldArray[i];                    
+                if (field.FieldType == typeof(UnityEventBase) || field.FieldType.IsSubclassOf(typeof(UnityEventBase))) 
+                {
+                    targetPropertiesNames.Add(field.Name);
+                }
+            }
+            
+            if (targetPropertiesNames.Count > 0) 
+            {
+                SerializedObject serializedMonoBehaviour = new SerializedObject(monoBehaviour); 
+                for (int i = targetPropertiesNames.Count - 1; i >= 0; i--) 
+                {
+                    string targetProperty = targetPropertiesNames[i];
+
+                    SerializedProperty property = serializedMonoBehaviour.FindProperty(targetProperty);
+                    SerializedProperty propertyRelativeArrray = property.FindPropertyRelative("m_PersistentCalls.m_Calls");
+                    
+                    for (int j = propertyRelativeArrray.arraySize - 1; j >= 0; j--)
+                    {
+                        SerializedProperty arrayElementAtIndex = propertyRelativeArrray.GetArrayElementAtIndex(j);
+
+                        SerializedProperty propertyTarget       = arrayElementAtIndex.FindPropertyRelative("m_Target");
+                        if (propertyTarget.objectReferenceValue == null)
+                        {
+                            if (printError)
+                            {
+                                appendErrorLine(monoBehaviour.GetType().Name + ": Event object reference is null");
+                            }
+                            else
+                            {
+                                return true;
+                            }
+                        }
+
+                        SerializedProperty propertyMethodName   = arrayElementAtIndex.FindPropertyRelative("m_MethodName");
+                        if (string.IsNullOrEmpty(propertyMethodName.stringValue)) 
+                        {
+                            if (printError)
+                            {
+                                appendErrorLine(monoBehaviour.GetType().Name + ": Event handler function is not selected");
+                                continue;
+                            }
+                            else
+                            {
+                                return true;
+                            }
+                        }
+                         
+                        string argumentAssemblyTypeName = arrayElementAtIndex.FindPropertyRelative("m_Arguments").FindPropertyRelative("m_ObjectArgumentAssemblyTypeName").stringValue;
+                        System.Type argumentAssemblyType;
+                        if (!string.IsNullOrEmpty(argumentAssemblyTypeName)) argumentAssemblyType = System.Type.GetType(argumentAssemblyTypeName, false) ?? typeof(UnityEngine.Object);
+                        else argumentAssemblyType = typeof(UnityEngine.Object);
+
+                        UnityEventBase dummyEvent;
+                        System.Type propertyTypeName = System.Type.GetType(property.FindPropertyRelative("m_TypeName").stringValue, false);
+                        if (propertyTypeName == null) dummyEvent = (UnityEventBase) new UnityEvent();
+                        else dummyEvent = Activator.CreateInstance(propertyTypeName) as UnityEventBase;
+
+                        if (!UnityEventDrawer.IsPersistantListenerValid(dummyEvent, propertyMethodName.stringValue, propertyTarget.objectReferenceValue, (PersistentListenerMode)arrayElementAtIndex.FindPropertyRelative("m_Mode").enumValueIndex, argumentAssemblyType))
+                        { 
+                            if (printError)
+                            {
+                                appendErrorLine(monoBehaviour.GetType().Name + ": Event handler function is missing");
+                            }
+                            else
+                            {
+                                return true;
+                            }
+                        }
+                    }
+                }   
+            }            
+            return false;
+        }
+
+        private void appendErrorLine(string error)
+        {
+            errorCount++;
+            errorStringBuilder.Append(errorCount.ToString());
+            errorStringBuilder.Append(") ");
+            errorStringBuilder.AppendLine(error);
+        }
+    }
+}
+
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QErrorComponent.cs.meta b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QErrorComponent.cs.meta
new file mode 100644
index 0000000..1969301
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QErrorComponent.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: d4efcdb4112365b44ab49909e160565a
+timeCreated: 1474964198
+licenseType: Store
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QGameObjectIconComponent.cs b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QGameObjectIconComponent.cs
new file mode 100644
index 0000000..425a07a
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QGameObjectIconComponent.cs
@@ -0,0 +1,79 @@
+using System;
+using UnityEngine;
+using UnityEditor;
+using qtools.qhierarchy.pcomponent.pbase;
+using qtools.qhierarchy.phierarchy;
+using qtools.qhierarchy.phelper;
+using qtools.qhierarchy.pdata;
+using System.Reflection;
+
+namespace qtools.qhierarchy.pcomponent
+{
+    public class QGameObjectIconComponent: QBaseComponent
+    {
+        // PRIVATE
+        private MethodInfo getIconMethodInfo;
+        private object[] getIconMethodParams;
+
+        // CONSTRUCTOR
+        public QGameObjectIconComponent ()
+        {
+            rect.width = 14;
+            rect.height = 14;
+
+            getIconMethodInfo   = typeof(EditorGUIUtility).GetMethod("GetIconForObject", BindingFlags.NonPublic | BindingFlags.Static );
+            getIconMethodParams = new object[1];
+
+            QSettings.getInstance().addEventListener(QSetting.GameObjectIconShow                 , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.GameObjectIconShowDuringPlayMode   , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.GameObjectIconSize                          , settingsChanged);
+            settingsChanged();
+        }
+        
+        // PRIVATE
+        private void settingsChanged()
+        {
+            enabled = QSettings.getInstance().get<bool>(QSetting.GameObjectIconShow);
+            showComponentDuringPlayMode = QSettings.getInstance().get<bool>(QSetting.GameObjectIconShowDuringPlayMode);
+            QHierarchySizeAll size = (QHierarchySizeAll)QSettings.getInstance().get<int>(QSetting.GameObjectIconSize);
+            rect.width = rect.height = (size == QHierarchySizeAll.Normal ? 15 : (size == QHierarchySizeAll.Big ? 16 : 13));     
+        }
+
+        // DRAW
+        public override QLayoutStatus layout(GameObject gameObject, QObjectList objectList, Rect selectionRect, ref Rect curRect, float maxWidth)
+        {
+            if (maxWidth < rect.width + 2)
+            {
+                return QLayoutStatus.Failed;
+            }
+            else
+            {
+                curRect.x -= rect.width + 2;
+                rect.x = curRect.x;
+                rect.y = curRect.y - (rect.height - 16) / 2;
+                return QLayoutStatus.Success;
+            }
+        }
+
+        public override void draw(GameObject gameObject, QObjectList objectList, Rect selectionRect)
+        {                      
+            getIconMethodParams[0] = gameObject;
+            Texture2D icon = (Texture2D)getIconMethodInfo.Invoke(null, getIconMethodParams );    
+            if (icon != null) 
+                GUI.DrawTexture(rect, icon, ScaleMode.ScaleToFit, true);
+        }
+                
+        public override void eventHandler(GameObject gameObject, QObjectList objectList, Event currentEvent)
+        {
+            if (currentEvent.isMouse && currentEvent.type == EventType.MouseDown && currentEvent.button == 0 && rect.Contains(currentEvent.mousePosition))
+            {
+                currentEvent.Use();
+
+                Type iconSelectorType = Assembly.Load("UnityEditor").GetType("UnityEditor.IconSelector");
+                MethodInfo showIconSelectorMethodInfo = iconSelectorType.GetMethod("ShowAtPosition", BindingFlags.Static | BindingFlags.NonPublic);
+                showIconSelectorMethodInfo.Invoke(null, new object[] { gameObject, rect, true });
+            }
+        }
+    }
+}
+
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QGameObjectIconComponent.cs.meta b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QGameObjectIconComponent.cs.meta
new file mode 100644
index 0000000..c269599
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QGameObjectIconComponent.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 50cf04889723dbc4e8f2d788d89196cb
+timeCreated: 1474963752
+licenseType: Store
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QLayerIconComponent.cs b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QLayerIconComponent.cs
new file mode 100644
index 0000000..d621940
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QLayerIconComponent.cs
@@ -0,0 +1,68 @@
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using UnityEngine;
+using UnityEditor;
+using qtools.qhierarchy.pcomponent.pbase;
+using qtools.qhierarchy.phierarchy;
+using qtools.qhierarchy.phelper;
+using qtools.qhierarchy.pdata;
+
+namespace qtools.qhierarchy.pcomponent
+{
+    public class QLayerIconComponent: QBaseComponent
+    {
+        private List<QLayerTexture> layerTextureList;
+
+        // CONSTRUCTOR
+        public QLayerIconComponent()
+        {
+            rect.width  = 14;
+            rect.height = 14;
+
+            QSettings.getInstance().addEventListener(QSetting.LayerIconShow              , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.LayerIconShowDuringPlayMode, settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.LayerIconSize              , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.LayerIconList              , settingsChanged);
+            settingsChanged();
+        }
+        
+        // PRIVATE
+        private void settingsChanged()
+        {
+            enabled                     = QSettings.getInstance().get<bool>(QSetting.LayerIconShow);
+            showComponentDuringPlayMode = QSettings.getInstance().get<bool>(QSetting.LayerIconShowDuringPlayMode);
+            QHierarchySizeAll size      = (QHierarchySizeAll)QSettings.getInstance().get<int>(QSetting.LayerIconSize);
+            rect.width = rect.height    = (size == QHierarchySizeAll.Normal ? 15 : (size == QHierarchySizeAll.Big ? 16 : 13));        
+            this.layerTextureList = QLayerTexture.loadLayerTextureList();
+        }
+
+        // DRAW
+        public override QLayoutStatus layout(GameObject gameObject, QObjectList objectList, Rect selectionRect, ref Rect curRect, float maxWidth)
+        {
+            if (maxWidth < rect.width)
+            {
+                return QLayoutStatus.Failed;
+            }
+            else
+            {
+                curRect.x -= rect.width + 2;
+                rect.x = curRect.x;
+                rect.y = curRect.y - (rect.height - 16) / 2;
+                return QLayoutStatus.Success;
+            }
+        }
+
+        public override void draw(GameObject gameObject, QObjectList objectList, Rect selectionRect)
+        {                       
+            string gameObjectLayerName = LayerMask.LayerToName(gameObject.layer);
+
+            QLayerTexture layerTexture = layerTextureList.Find(t => t.layer == gameObjectLayerName);
+            if (layerTexture != null && layerTexture.texture != null)
+            {
+                GUI.DrawTexture(rect, layerTexture.texture, ScaleMode.ScaleToFit, true);
+            }
+        }
+    }
+}
+
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QLayerIconComponent.cs.meta b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QLayerIconComponent.cs.meta
new file mode 100644
index 0000000..c8c3936
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QLayerIconComponent.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: eafd6a45f889eba4db47aeb06b3e50bb
+timeCreated: 1478619761
+licenseType: Store
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QLockComponent.cs b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QLockComponent.cs
new file mode 100644
index 0000000..b44074b
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QLockComponent.cs
@@ -0,0 +1,188 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEditor;
+using qtools.qhierarchy.pcomponent.pbase;
+using qtools.qhierarchy.phierarchy;
+using qtools.qhierarchy.phelper;
+using qtools.qhierarchy.pdata;
+
+namespace qtools.qhierarchy.pcomponent
+{
+    public class QLockComponent: QBaseComponent
+    {
+        // PRIVATE
+        private Color activeColor;
+        private Color inactiveColor;
+        private Texture2D lockButtonTexture;
+        private bool showModifierWarning;
+        private int targetLockState = -1;
+
+        // CONSTRUCTOR
+        public QLockComponent()
+        {
+            rect.width = 13;
+
+            lockButtonTexture = QResources.getInstance().getTexture(QTexture.QLockButton);
+
+            QSettings.getInstance().addEventListener(QSetting.AdditionalShowModifierWarning , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.LockShow                      , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.LockShowDuringPlayMode        , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.AdditionalActiveColor         , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.AdditionalInactiveColor       , settingsChanged);
+            settingsChanged();
+        }
+
+        // PRIVATE
+        private void settingsChanged()
+        {
+            showModifierWarning         = QSettings.getInstance().get<bool>(QSetting.AdditionalShowModifierWarning);
+            enabled                     = QSettings.getInstance().get<bool>(QSetting.LockShow);
+            showComponentDuringPlayMode = QSettings.getInstance().get<bool>(QSetting.LockShowDuringPlayMode);
+            activeColor                 = QSettings.getInstance().getColor(QSetting.AdditionalActiveColor);
+            inactiveColor               = QSettings.getInstance().getColor(QSetting.AdditionalInactiveColor);
+        }
+
+        // DRAW
+        public override QLayoutStatus layout(GameObject gameObject, QObjectList objectList, Rect selectionRect, ref Rect curRect, float maxWidth)
+        {
+            if (maxWidth < 13)
+            {
+                return QLayoutStatus.Failed;
+            }
+            else
+            {
+                curRect.x -= 13;
+                rect.x = curRect.x;
+                rect.y = curRect.y;
+                return QLayoutStatus.Success;
+            }
+        }
+
+        public override void draw(GameObject gameObject, QObjectList objectList, Rect selectionRect)
+        {  
+            bool isLock = isGameObjectLock(gameObject, objectList);
+
+            if (isLock == true && (gameObject.hideFlags & HideFlags.NotEditable) != HideFlags.NotEditable)
+            {
+                gameObject.hideFlags |= HideFlags.NotEditable;
+                EditorUtility.SetDirty(gameObject);
+            }
+            else if (isLock == false && (gameObject.hideFlags & HideFlags.NotEditable) == HideFlags.NotEditable)
+            {
+                gameObject.hideFlags ^= HideFlags.NotEditable;
+                EditorUtility.SetDirty(gameObject);
+            }
+
+            QColorUtils.setColor(isLock ? activeColor : inactiveColor);
+            GUI.DrawTexture(rect, lockButtonTexture);
+            QColorUtils.clearColor();
+        }
+
+        public override void eventHandler(GameObject gameObject, QObjectList objectList, Event currentEvent)
+        {
+            if (currentEvent.isMouse && currentEvent.button == 0 && rect.Contains(currentEvent.mousePosition))
+            {
+                bool isLock = isGameObjectLock(gameObject, objectList);
+
+                if (currentEvent.type == EventType.MouseDown)
+                {
+                    targetLockState = ((!isLock) == true ? 1 : 0);
+                }
+                else if (currentEvent.type == EventType.MouseDrag && targetLockState != -1)
+                {
+                    if (targetLockState == (isLock == true ? 1 : 0)) return;
+                } 
+                else
+                {
+                    targetLockState = -1;
+                    return;
+                }
+
+                List<GameObject> targetGameObjects = new List<GameObject>();
+                if (currentEvent.shift) 
+                {
+                    if (!showModifierWarning || EditorUtility.DisplayDialog("Change locking", "Are you sure you want to " + (isLock ? "unlock" : "lock") + " this GameObject and all its children? (You can disable this warning in the settings)", "Yes", "Cancel"))
+                    {
+                        getGameObjectListRecursive(gameObject, ref targetGameObjects);           
+                    }
+                }
+                else if (currentEvent.alt)
+                {
+                    if (gameObject.transform.parent != null)
+                    {
+                        if (!showModifierWarning || EditorUtility.DisplayDialog("Change locking", "Are you sure you want to " + (isLock ? "unlock" : "lock") + " this GameObject and its siblings? (You can disable this warning in the settings)", "Yes", "Cancel"))
+                        {
+                            getGameObjectListRecursive(gameObject.transform.parent.gameObject, ref targetGameObjects, 1);
+                            targetGameObjects.Remove(gameObject.transform.parent.gameObject);
+                        }
+                    }
+                    else
+                    {
+                        Debug.Log("This action for root objects is supported only for Unity3d 5.3.3 and above");
+                        return;
+                    }
+                }
+                else 
+                {
+                    if (Selection.Contains(gameObject))
+                    {
+                        targetGameObjects.AddRange(Selection.gameObjects);
+                    }
+                    else
+                    {
+                        getGameObjectListRecursive(gameObject, ref targetGameObjects, 0);
+                    };
+                }
+                
+                setLock(targetGameObjects, objectList, !isLock);
+                currentEvent.Use();
+            }
+        } 
+
+        public override void disabledHandler(GameObject gameObject, QObjectList objectList)
+        {	
+            if (objectList != null && objectList.lockedObjects.Contains(gameObject))
+            {
+                objectList.lockedObjects.Remove(gameObject);
+                gameObject.hideFlags &= ~HideFlags.NotEditable;
+                EditorUtility.SetDirty(gameObject);
+            }
+        }
+
+        // PRIVATE
+        private bool isGameObjectLock(GameObject gameObject, QObjectList objectList)
+        {
+            return objectList == null ? false : objectList.lockedObjects.Contains(gameObject);
+        }
+        
+        private void setLock(List<GameObject> gameObjects, QObjectList objectList, bool targetLock)
+        {
+            if (gameObjects.Count == 0) return;
+
+            if (objectList == null) objectList = QObjectListManager.getInstance().getObjectList(gameObjects[0], true);
+            Undo.RecordObject(objectList, targetLock ? "Lock" : "Unlock");   
+            
+            for (int i = gameObjects.Count - 1; i >= 0; i--)
+            {     
+                GameObject curGameObject = gameObjects[i];
+                Undo.RecordObject(curGameObject, targetLock ? "Lock" : "Unlock");
+                
+                if (targetLock)
+                {
+                    curGameObject.hideFlags |= HideFlags.NotEditable;
+                    if (!objectList.lockedObjects.Contains(curGameObject))
+                        objectList.lockedObjects.Add(curGameObject);
+                }
+                else
+                {
+                    curGameObject.hideFlags &= ~HideFlags.NotEditable;
+                    objectList.lockedObjects.Remove(curGameObject);
+                }
+                
+                EditorUtility.SetDirty(curGameObject);
+            }
+        }
+    }
+}
+
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QLockComponent.cs.meta b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QLockComponent.cs.meta
new file mode 100644
index 0000000..bf9aef9
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QLockComponent.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: b0502ab6ed39a3d40ab31c7622d9914f
+timeCreated: 1474901945
+licenseType: Store
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QMonoBehaviorIconComponent.cs b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QMonoBehaviorIconComponent.cs
new file mode 100644
index 0000000..6d9f191
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QMonoBehaviorIconComponent.cs
@@ -0,0 +1,102 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEditor;
+using qtools.qhierarchy.pcomponent.pbase;
+using qtools.qhierarchy.pdata;
+using qtools.qhierarchy.phelper;
+
+namespace qtools.qhierarchy.pcomponent
+{
+    public class QMonoBehaviorIconComponent: QBaseComponent
+    {
+        // CONST
+        private const float TREE_STEP_WIDTH  = 14.0f;
+        private const float TREE_STEP_HEIGHT = 16.0f;
+
+        // PRIVATE
+        private Texture2D monoBehaviourIconTexture;   
+        private Texture2D monoBehaviourIconObjectTexture; 
+        private bool ignoreUnityMonobehaviour;
+        private Color iconColor;
+        private bool showTreeMap;
+
+        // CONSTRUCTOR 
+        public QMonoBehaviorIconComponent()
+        {
+            rect.width  = 14;
+            rect.height = 16;
+            
+            monoBehaviourIconTexture = QResources.getInstance().getTexture(QTexture.QMonoBehaviourIcon);
+            monoBehaviourIconObjectTexture  = QResources.getInstance().getTexture(QTexture.QTreeMapObject);
+
+            QSettings.getInstance().addEventListener(QSetting.MonoBehaviourIconIgnoreUnityMonobehaviour , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.MonoBehaviourIconShow                     , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.MonoBehaviourIconShowDuringPlayMode       , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.MonoBehaviourIconColor                    , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.TreeMapShow                               , settingsChanged);
+            settingsChanged();
+        }
+
+        // PRIVATE
+        private void settingsChanged()
+        {
+            ignoreUnityMonobehaviour    = QSettings.getInstance().get<bool>(QSetting.MonoBehaviourIconIgnoreUnityMonobehaviour);
+            enabled                     = QSettings.getInstance().get<bool>(QSetting.MonoBehaviourIconShow);
+            showComponentDuringPlayMode = QSettings.getInstance().get<bool>(QSetting.MonoBehaviourIconShowDuringPlayMode);
+            iconColor                   = QSettings.getInstance().getColor(QSetting.MonoBehaviourIconColor);
+            showTreeMap                 = QSettings.getInstance().get<bool>(QSetting.TreeMapShow);
+            EditorApplication.RepaintHierarchyWindow();  
+        }
+
+        public override void draw(GameObject gameObject, QObjectList objectList, Rect selectionRect)
+        {
+            bool foundCustomComponent = false;   
+            if (ignoreUnityMonobehaviour)
+            {
+                Component[] components = gameObject.GetComponents<MonoBehaviour>();                
+                for (int i = components.Length - 1; i >= 0; i--)
+                {
+                    if (components[i] != null && !components[i].GetType().FullName.Contains("UnityEngine")) 
+                    {
+                        foundCustomComponent = true;
+                        break;
+                    }
+                }                
+            }
+            else
+            {
+                foundCustomComponent = gameObject.GetComponent<MonoBehaviour>() != null;
+            }
+
+            if (foundCustomComponent)
+            {
+                int ident = Mathf.FloorToInt(selectionRect.x / TREE_STEP_WIDTH) - 1;
+
+                rect.x = ident * TREE_STEP_WIDTH;
+                rect.y = selectionRect.y;
+                rect.width = 16;
+
+                #if UNITY_2018_3_OR_NEWER
+                    rect.x += TREE_STEP_WIDTH + 1;
+                    rect.width += 1;
+                #elif UNITY_5_6_OR_NEWER
+                    
+                #elif UNITY_5_3_OR_NEWER
+                    rect.x += TREE_STEP_WIDTH;
+                #endif                
+
+                QColorUtils.setColor(iconColor);
+                GUI.DrawTexture(rect, monoBehaviourIconTexture);
+                QColorUtils.clearColor();
+
+                if (!showTreeMap && gameObject.transform.childCount == 0)
+                {
+                    rect.width = 14;
+                    GUI.DrawTexture(rect, monoBehaviourIconObjectTexture);
+                }
+            }
+        }
+    }
+}
+
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QMonoBehaviorIconComponent.cs.meta b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QMonoBehaviorIconComponent.cs.meta
new file mode 100644
index 0000000..20b9899
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QMonoBehaviorIconComponent.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: b88f8470c7bcc944c925e9d7e8b72661
+timeCreated: 1475059927
+licenseType: Store
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QPrefabComponent.cs b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QPrefabComponent.cs
new file mode 100644
index 0000000..9e97530
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QPrefabComponent.cs
@@ -0,0 +1,92 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEditor;
+using qtools.qhierarchy.pcomponent.pbase;
+using qtools.qhierarchy.pdata;
+using qtools.qhierarchy.phelper;
+
+namespace qtools.qhierarchy.pcomponent
+{
+    public class QPrefabComponent: QBaseComponent
+    {
+        // PRIVATE
+        private Color activeColor;
+        private Color inactiveColor;
+        private Texture2D prefabTexture;
+        private bool showPrefabConnectedIcon;
+
+        // CONSTRUCTOR
+        public QPrefabComponent()
+        {
+            rect.width = 9;
+
+            prefabTexture = QResources.getInstance().getTexture(QTexture.QPrefabIcon);
+
+            QSettings.getInstance().addEventListener(QSetting.PrefabShowBreakedPrefabsOnly  , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.PrefabShow                    , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.AdditionalActiveColor         , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.AdditionalInactiveColor       , settingsChanged);
+            settingsChanged();
+        }
+        
+        // PRIVATE
+        private void settingsChanged()
+        {
+            showPrefabConnectedIcon = QSettings.getInstance().get<bool>(QSetting.PrefabShowBreakedPrefabsOnly);
+            enabled                 = QSettings.getInstance().get<bool>(QSetting.PrefabShow);
+            activeColor             = QSettings.getInstance().getColor(QSetting.AdditionalActiveColor);
+            inactiveColor           = QSettings.getInstance().getColor(QSetting.AdditionalInactiveColor);
+        }
+
+        // DRAW
+        public override QLayoutStatus layout(GameObject gameObject, QObjectList objectList, Rect selectionRect, ref Rect curRect, float maxWidth)
+        {
+            if (maxWidth < 9)
+            {
+                return QLayoutStatus.Failed;
+            }
+            else
+            {
+                curRect.x -= 9;
+                rect.x = curRect.x;
+                rect.y = curRect.y;
+                return QLayoutStatus.Success;
+            }
+        }
+        
+        public override void draw(GameObject gameObject, QObjectList objectList, Rect selectionRect)
+        {
+            #if UNITY_2018_3_OR_NEWER
+                PrefabInstanceStatus prefabStatus = PrefabUtility.GetPrefabInstanceStatus(gameObject);
+                if (prefabStatus == PrefabInstanceStatus.MissingAsset ||
+                    prefabStatus == PrefabInstanceStatus.Disconnected) {
+                    QColorUtils.setColor(inactiveColor);
+                    GUI.DrawTexture(rect, prefabTexture);
+                    QColorUtils.clearColor();
+                } else if (!showPrefabConnectedIcon && prefabStatus != PrefabInstanceStatus.NotAPrefab) {
+                    QColorUtils.setColor(activeColor);
+                    GUI.DrawTexture(rect, prefabTexture);
+                    QColorUtils.clearColor();
+                }
+            #else
+                PrefabType prefabType = PrefabUtility.GetPrefabType(gameObject);
+                if (prefabType == PrefabType.MissingPrefabInstance || 
+                    prefabType == PrefabType.DisconnectedPrefabInstance ||
+                    prefabType == PrefabType.DisconnectedModelPrefabInstance)
+                {
+                    QColorUtils.setColor(inactiveColor);
+                    GUI.DrawTexture(rect, prefabTexture);
+                    QColorUtils.clearColor();
+                }
+                else if (!showPrefabConnectedIcon && prefabType != PrefabType.None)
+                {
+                    QColorUtils.setColor(activeColor);
+                    GUI.DrawTexture(rect, prefabTexture);
+                    QColorUtils.clearColor();
+                }
+            #endif
+        }
+    }
+}
+
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QPrefabComponent.cs.meta b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QPrefabComponent.cs.meta
new file mode 100644
index 0000000..63e5e0f
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QPrefabComponent.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: befe75d5b11883641ae9d52aca55d62d
+timeCreated: 1475230799
+licenseType: Store
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QRendererComponent.cs b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QRendererComponent.cs
new file mode 100644
index 0000000..199c666
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QRendererComponent.cs
@@ -0,0 +1,183 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEditor;
+using qtools.qhierarchy.pcomponent.pbase;
+using qtools.qhierarchy.phierarchy;
+using qtools.qhierarchy.pdata;
+using qtools.qhierarchy.phelper;
+
+namespace qtools.qhierarchy.pcomponent
+{
+    public class QRendererComponent: QBaseComponent
+    {
+        // PRIVATE
+        private Color activeColor;
+        private Color inactiveColor;
+        private Color specialColor;
+        private Texture2D rendererButtonTexture;
+        private int targetRendererMode = -1; 
+
+        // CONSTRUCTOR
+        public QRendererComponent()
+        {
+            rect.width = 12;
+
+            rendererButtonTexture = QResources.getInstance().getTexture(QTexture.QRendererButton);
+
+            QSettings.getInstance().addEventListener(QSetting.RendererShow              , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.RendererShowDuringPlayMode, settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.AdditionalActiveColor     , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.AdditionalInactiveColor   , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.AdditionalSpecialColor    , settingsChanged);
+            settingsChanged();
+        }
+
+        // PRIVATE
+        private void settingsChanged()
+        {
+            enabled                     = QSettings.getInstance().get<bool>(QSetting.RendererShow);
+            showComponentDuringPlayMode = QSettings.getInstance().get<bool>(QSetting.RendererShowDuringPlayMode);
+            activeColor                 = QSettings.getInstance().getColor(QSetting.AdditionalActiveColor);
+            inactiveColor               = QSettings.getInstance().getColor(QSetting.AdditionalInactiveColor);
+            specialColor                = QSettings.getInstance().getColor(QSetting.AdditionalSpecialColor);
+        }
+
+        // DRAW
+        public override QLayoutStatus layout(GameObject gameObject, QObjectList objectList, Rect selectionRect, ref Rect curRect, float maxWidth)
+        {
+            if (maxWidth < 12)
+            {
+                return QLayoutStatus.Failed;
+            }
+            else
+            {
+                curRect.x -= 12;
+                rect.x = curRect.x;
+                rect.y = curRect.y;
+                return QLayoutStatus.Success;
+            }
+        }
+
+        public override void disabledHandler(GameObject gameObject, QObjectList objectList)
+        {
+            if (objectList != null && objectList.wireframeHiddenObjects.Contains(gameObject))
+            {      
+                objectList.wireframeHiddenObjects.Remove(gameObject);
+                Renderer renderer = gameObject.GetComponent<Renderer>();
+                if (renderer != null) setSelectedRenderState(renderer, false);
+            }
+        }
+
+        public override void draw(GameObject gameObject, QObjectList objectList, Rect selectionRect)
+        {
+            Renderer renderer = gameObject.GetComponent<Renderer>();
+            if (renderer != null)
+            {
+                bool wireframeHiddenObjectsContains = isWireframeHidden(gameObject, objectList);
+                if (wireframeHiddenObjectsContains)
+                {
+                    QColorUtils.setColor(specialColor);
+                    GUI.DrawTexture(rect, rendererButtonTexture);
+                    QColorUtils.clearColor();
+                }
+                else if (renderer.enabled)
+                {
+                    QColorUtils.setColor(activeColor);
+                    GUI.DrawTexture(rect, rendererButtonTexture);
+                    QColorUtils.clearColor();
+                }
+                else
+                {
+                    QColorUtils.setColor(inactiveColor);
+                    GUI.DrawTexture(rect, rendererButtonTexture);
+                    QColorUtils.clearColor();
+                }
+            }
+        }
+
+        public override void eventHandler(GameObject gameObject, QObjectList objectList, Event currentEvent)
+        {
+            if (currentEvent.isMouse && currentEvent.button == 0 && rect.Contains(currentEvent.mousePosition))
+            {
+                Renderer renderer = gameObject.GetComponent<Renderer>();
+                if (renderer != null)
+                {
+                    bool wireframeHiddenObjectsContains = isWireframeHidden(gameObject, objectList);
+                    bool isEnabled = renderer.enabled;
+                    
+                    if (currentEvent.type == EventType.MouseDown)
+                    {
+                        targetRendererMode = ((!isEnabled) == true ? 1 : 0);
+                    }
+                    else if (currentEvent.type == EventType.MouseDrag && targetRendererMode != -1)
+                    {
+                        if (targetRendererMode == (isEnabled == true ? 1 : 0)) return;
+                    } 
+                    else
+                    {
+                        targetRendererMode = -1;
+                        return;
+                    }
+
+                    Undo.RecordObject(renderer, "renderer visibility change");                    
+                    
+                    if (currentEvent.control || currentEvent.command)
+                    {
+                        if (!wireframeHiddenObjectsContains)
+                        {
+                            setSelectedRenderState(renderer, true);
+                            SceneView.RepaintAll();
+                            setWireframeMode(gameObject, objectList, true);
+                        }
+                    }
+                    else
+                    {
+                        if (wireframeHiddenObjectsContains)
+                        {
+                            setSelectedRenderState(renderer, false);
+                            SceneView.RepaintAll();
+                            setWireframeMode(gameObject, objectList, false);
+                        }
+                        else
+                        {
+                            Undo.RecordObject(renderer, isEnabled ? "Disable Component" : "Enable Component");
+                            renderer.enabled = !isEnabled;
+                        }
+                    }
+                    
+                    EditorUtility.SetDirty(gameObject);
+                }
+                currentEvent.Use();
+            }
+        }
+
+        // PRIVATE
+        public bool isWireframeHidden(GameObject gameObject, QObjectList objectList)
+        {
+            return objectList == null ? false : objectList.wireframeHiddenObjects.Contains(gameObject);
+        }
+        
+        public void setWireframeMode(GameObject gameObject, QObjectList objectList, bool targetWireframe)
+        {
+            if (objectList == null && targetWireframe) objectList = QObjectListManager.getInstance().getObjectList(gameObject, true);
+            if (objectList != null)
+            {
+                Undo.RecordObject(objectList, "Renderer Visibility Change");
+                if (targetWireframe) objectList.wireframeHiddenObjects.Add(gameObject);
+                else objectList.wireframeHiddenObjects.Remove(gameObject);
+                EditorUtility.SetDirty(objectList);
+            }
+        }
+
+        static public void setSelectedRenderState(Renderer renderer, bool visible)
+        {
+            #if UNITY_5_5_OR_NEWER
+            EditorUtility.SetSelectedRenderState(renderer, visible ? EditorSelectedRenderState.Wireframe : EditorSelectedRenderState.Hidden);
+            #else
+            EditorUtility.SetSelectedWireframeHidden(renderer, visible);
+            #endif
+        }
+    }
+}
+
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QRendererComponent.cs.meta b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QRendererComponent.cs.meta
new file mode 100644
index 0000000..2d16dfa
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QRendererComponent.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 09ef5e33b4710ed439a07e2ce9b29ce7
+timeCreated: 1474969413
+licenseType: Store
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QSeparatorComponent.cs b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QSeparatorComponent.cs
new file mode 100644
index 0000000..65c5a65
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QSeparatorComponent.cs
@@ -0,0 +1,64 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEditor;
+using qtools.qhierarchy.pcomponent.pbase;
+using qtools.qhierarchy.pdata;
+using qtools.qhierarchy.phelper;
+
+namespace qtools.qhierarchy.pcomponent
+{
+    public class QSeparatorComponent: QBaseComponent
+    {
+        // PRIVATE
+        private Color separatorColor;
+        private Color evenShadingColor;
+        private Color oddShadingColor;
+        private bool showRowShading;
+
+        // CONSTRUCTOR
+        public QSeparatorComponent ()
+        {
+            showComponentDuringPlayMode = true;
+
+            QSettings.getInstance().addEventListener(QSetting.SeparatorShowRowShading   , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.SeparatorShow             , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.SeparatorColor                , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.SeparatorEvenRowShadingColor  , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.SeparatorOddRowShadingColor , settingsChanged);
+
+            settingsChanged();
+        }
+        
+        // PRIVATE
+        private void settingsChanged()
+        {
+            showRowShading   = QSettings.getInstance().get<bool>(QSetting.SeparatorShowRowShading);
+            enabled          = QSettings.getInstance().get<bool>(QSetting.SeparatorShow);
+            evenShadingColor = QSettings.getInstance().getColor(QSetting.SeparatorEvenRowShadingColor);
+            oddShadingColor  = QSettings.getInstance().getColor(QSetting.SeparatorOddRowShadingColor);
+            separatorColor   = QSettings.getInstance().getColor(QSetting.SeparatorColor);
+        }
+
+        // DRAW
+        public override void draw(GameObject gameObject, QObjectList objectList, Rect selectionRect)
+        {
+            rect.y = selectionRect.y;
+            rect.width = selectionRect.width + selectionRect.x;
+            rect.height = 1;
+            rect.x = 0;
+
+            EditorGUI.DrawRect(rect, separatorColor);
+
+            if (showRowShading)
+            {
+                selectionRect.width += selectionRect.x;
+                selectionRect.x = 0;
+                selectionRect.height -=1;
+                selectionRect.y += 1;
+                EditorGUI.DrawRect(selectionRect, ((Mathf.FloorToInt(((selectionRect.y - 4) / 16) % 2) == 0)) ? evenShadingColor : oddShadingColor);
+            }
+        }
+    }
+}
+
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QSeparatorComponent.cs.meta b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QSeparatorComponent.cs.meta
new file mode 100644
index 0000000..1e246e4
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QSeparatorComponent.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: ca885fb4759669a46bd80ee31287ea93
+timeCreated: 1475062806
+licenseType: Store
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QStaticComponent.cs b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QStaticComponent.cs
new file mode 100644
index 0000000..9645658
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QStaticComponent.cs
@@ -0,0 +1,150 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEditor;
+using qtools.qhierarchy.pcomponent.pbase;
+using qtools.qhierarchy.pdata;
+using qtools.qhierarchy.phierarchy;
+using qtools.qhierarchy.phelper;
+
+namespace qtools.qhierarchy.pcomponent
+{
+    public class QStaticComponent: QBaseComponent
+    {
+        // PRIVATE
+        private Color activeColor;
+        private Color inactiveColor;
+        private StaticEditorFlags staticFlags;
+        private GameObject[] gameObjects;
+        private Texture2D staticButton;
+        private Color32[] staticButtonColors;
+
+        // CONSTRUCTOR
+        public QStaticComponent()
+        {
+            rect.width = 11;
+            rect.height = 10;
+
+            QSettings.getInstance().addEventListener(QSetting.StaticShow                , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.StaticShowDuringPlayMode  , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.AdditionalActiveColor     , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.AdditionalInactiveColor   , settingsChanged);
+
+            settingsChanged();
+        }
+
+        // PRIVATE
+        private void settingsChanged()
+        {
+            enabled                     = QSettings.getInstance().get<bool>(QSetting.StaticShow);
+            showComponentDuringPlayMode = QSettings.getInstance().get<bool>(QSetting.StaticShowDuringPlayMode);
+            activeColor                 = QSettings.getInstance().getColor(QSetting.AdditionalActiveColor);
+            inactiveColor               = QSettings.getInstance().getColor(QSetting.AdditionalInactiveColor);
+        }
+
+        // DRAW
+        public override QLayoutStatus layout(GameObject gameObject, QObjectList objectList, Rect selectionRect, ref Rect curRect, float maxWidth)
+        {
+            if (maxWidth < 13)
+            {
+                return QLayoutStatus.Failed;
+            }
+            else
+            {
+                curRect.x -= 13;
+                rect.x = curRect.x;
+                rect.y = curRect.y + 4;
+                staticFlags = GameObjectUtility.GetStaticEditorFlags(gameObject);
+                return QLayoutStatus.Success;
+            }
+        }
+
+        public override void draw(GameObject gameObject, QObjectList objectList, Rect selectionRect)
+        {
+            if (staticButton == null)
+            {
+                staticButton = new Texture2D(11, 10, TextureFormat.ARGB32, false, true);
+                staticButtonColors = new Color32[11 * 10];
+            }
+
+            #if UNITY_4_6 || UNITY_4_7
+            drawQuad(39, 5, 4, ((staticFlags & StaticEditorFlags.LightmapStatic       ) > 0));
+            drawQuad(33, 5, 4, ((staticFlags & StaticEditorFlags.BatchingStatic       ) > 0));
+            #else   
+            drawQuad(37, 3, 4, ((staticFlags & StaticEditorFlags.ContributeGI       ) > 0));
+            drawQuad(33, 3, 4, ((staticFlags & StaticEditorFlags.BatchingStatic       ) > 0));
+            drawQuad(41, 3, 4, ((staticFlags & StaticEditorFlags.ReflectionProbeStatic) > 0));
+            #endif
+            drawQuad( 0, 5, 2, ((staticFlags & StaticEditorFlags.OccludeeStatic       ) > 0));
+            drawQuad( 6, 5, 2, ((staticFlags & StaticEditorFlags.OccluderStatic       ) > 0));
+            drawQuad(88, 5, 2, ((staticFlags & StaticEditorFlags.NavigationStatic     ) > 0));
+            drawQuad(94, 5, 2, ((staticFlags & StaticEditorFlags.OffMeshLinkGeneration) > 0));
+
+            staticButton.SetPixels32(staticButtonColors);
+            staticButton.Apply();
+            GUI.DrawTexture(rect, staticButton);
+        }
+
+        public override void eventHandler(GameObject gameObject, QObjectList objectList, Event currentEvent)
+        {
+            if (currentEvent.isMouse && currentEvent.type == EventType.MouseDown && currentEvent.button == 0 && rect.Contains(currentEvent.mousePosition))
+            {
+                currentEvent.Use();
+
+                int intStaticFlags = (int)staticFlags;
+                gameObjects = Selection.Contains(gameObject) ? Selection.gameObjects : new GameObject[] { gameObject };
+
+                GenericMenu menu = new GenericMenu();
+                menu.AddItem(new GUIContent("Nothing"                   ), intStaticFlags == 0, staticChangeHandler, 0);
+                menu.AddItem(new GUIContent("Everything"                ), intStaticFlags == -1, staticChangeHandler, -1);
+                menu.AddItem(new GUIContent("Lightmap Static"           ), (intStaticFlags & (int)StaticEditorFlags.ContributeGI) > 0, staticChangeHandler, (int)StaticEditorFlags.ContributeGI);
+                menu.AddItem(new GUIContent("Occluder Static"           ), (intStaticFlags & (int)StaticEditorFlags.OccluderStatic) > 0, staticChangeHandler, (int)StaticEditorFlags.OccluderStatic);
+                menu.AddItem(new GUIContent("Batching Static"           ), (intStaticFlags & (int)StaticEditorFlags.BatchingStatic) > 0, staticChangeHandler, (int)StaticEditorFlags.BatchingStatic);
+                menu.AddItem(new GUIContent("Navigation Static"         ), (intStaticFlags & (int)StaticEditorFlags.NavigationStatic) > 0, staticChangeHandler, (int)StaticEditorFlags.NavigationStatic);
+                menu.AddItem(new GUIContent("Occludee Static"           ), (intStaticFlags & (int)StaticEditorFlags.OccludeeStatic) > 0, staticChangeHandler, (int)StaticEditorFlags.OccludeeStatic);
+                menu.AddItem(new GUIContent("Off Mesh Link Generation"  ), (intStaticFlags & (int)StaticEditorFlags.OffMeshLinkGeneration) > 0, staticChangeHandler, (int)StaticEditorFlags.OffMeshLinkGeneration);
+                #if UNITY_4_6 || UNITY_4_7
+                #else
+                menu.AddItem(new GUIContent("Reflection Probe Static"   ), (intStaticFlags & (int)StaticEditorFlags.ReflectionProbeStatic) > 0, staticChangeHandler, (int)StaticEditorFlags.ReflectionProbeStatic);
+                #endif
+                menu.ShowAsContext();
+            }
+        }
+
+        // PRIVATE
+        private void staticChangeHandler(object result)
+        {
+            int intResult = (int)result;
+            StaticEditorFlags resultStaticFlags = (StaticEditorFlags)result;
+            if (intResult != 0 && intResult != -1)
+            {
+                resultStaticFlags = staticFlags ^ resultStaticFlags;
+            }
+
+            for (int i = gameObjects.Length - 1; i >= 0; i--)
+            {
+                GameObject gameObject = gameObjects[i];
+                Undo.RecordObject(gameObject, "Change Static Flags");            
+                GameObjectUtility.SetStaticEditorFlags(gameObject, resultStaticFlags);
+                EditorUtility.SetDirty(gameObject);
+            }
+        }
+
+        private void drawQuad(int startPosition, int width, int height, bool isActiveColor)
+        {
+            Color32 color = isActiveColor ? activeColor : inactiveColor;
+            for (int iy = 0; iy < height; iy++)
+            {
+                for (int ix = 0; ix < width; ix++)
+                {
+                    int pos = startPosition + ix + iy * 11;
+                    staticButtonColors[pos].r = color.r;
+                    staticButtonColors[pos].g = color.g;
+                    staticButtonColors[pos].b = color.b;
+                    staticButtonColors[pos].a = color.a;
+                }
+            }
+        }
+    }
+}
+
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QStaticComponent.cs.meta b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QStaticComponent.cs.meta
new file mode 100644
index 0000000..02c635d
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QStaticComponent.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 36e29ad1ef3ae3b4587ddd3bdb2067f1
+timeCreated: 1474961733
+licenseType: Store
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QTagIconComponent.cs b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QTagIconComponent.cs
new file mode 100644
index 0000000..7beec33
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QTagIconComponent.cs
@@ -0,0 +1,70 @@
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using UnityEngine;
+using UnityEditor;
+using qtools.qhierarchy.pcomponent.pbase;
+using qtools.qhierarchy.phierarchy;
+using qtools.qhierarchy.phelper;
+using qtools.qhierarchy.pdata;
+
+namespace qtools.qhierarchy.pcomponent
+{
+    public class QTagIconComponent: QBaseComponent
+    {
+        private List<QTagTexture> tagTextureList;
+
+        // CONSTRUCTOR
+        public QTagIconComponent()
+        {
+            rect.width  = 14;
+            rect.height = 14;
+
+            QSettings.getInstance().addEventListener(QSetting.TagIconShow              , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.TagIconShowDuringPlayMode, settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.TagIconSize              , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.TagIconList              , settingsChanged);
+            settingsChanged();
+        }
+        
+        // PRIVATE
+        private void settingsChanged()
+        {
+            enabled = QSettings.getInstance().get<bool>(QSetting.TagIconShow);
+            showComponentDuringPlayMode = QSettings.getInstance().get<bool>(QSetting.TagIconShowDuringPlayMode);
+            QHierarchySizeAll size = (QHierarchySizeAll)QSettings.getInstance().get<int>(QSetting.TagIconSize);
+            rect.width = rect.height = (size == QHierarchySizeAll.Normal ? 15 : (size == QHierarchySizeAll.Big ? 16 : 13));        
+            this.tagTextureList = QTagTexture.loadTagTextureList();
+        }
+
+        // DRAW
+        public override QLayoutStatus layout(GameObject gameObject, QObjectList objectList, Rect selectionRect, ref Rect curRect, float maxWidth)
+        {
+            if (maxWidth < rect.width)
+            {
+                return QLayoutStatus.Failed;
+            }
+            else
+            {
+                curRect.x -= rect.width + 2;
+                rect.x = curRect.x;
+                rect.y = curRect.y - (rect.height - 16) / 2;
+                return QLayoutStatus.Success;
+            }
+        }
+
+        public override void draw(GameObject gameObject, QObjectList objectList, Rect selectionRect)
+        {                       
+            string gameObjectTag = "";
+            try { gameObjectTag = gameObject.tag; }
+            catch {}
+
+            QTagTexture tagTexture = tagTextureList.Find(t => t.tag == gameObjectTag);
+            if (tagTexture != null && tagTexture.texture != null)
+            {
+                GUI.DrawTexture(rect, tagTexture.texture, ScaleMode.ScaleToFit, true);
+            }
+        }
+    }
+}
+
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QTagIconComponent.cs.meta b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QTagIconComponent.cs.meta
new file mode 100644
index 0000000..854001b
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QTagIconComponent.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: d09d5d602911a7c4f9ceb14fecd22ed1
+timeCreated: 1474973109
+licenseType: Store
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QTagLayerComponent.cs b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QTagLayerComponent.cs
new file mode 100644
index 0000000..8f5feb4
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QTagLayerComponent.cs
@@ -0,0 +1,250 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEditor;
+using qtools.qhierarchy.pcomponent.pbase;
+using qtools.qhierarchy.pdata;
+using System.Reflection;
+
+namespace qtools.qhierarchy.pcomponent
+{
+    public class QTagLayerComponent: QBaseComponent
+    {
+        // PRIVATE
+        private GUIStyle labelStyle;
+        private QHierarchyTagAndLayerShowType showType;
+        private Color layerColor;
+        private Color tagColor;       
+        private bool showAlways;
+        private bool sizeIsPixel;
+        private int pixelSize;
+        private float percentSize;
+        private GameObject[] gameObjects;
+        private float labelAlpha;
+        private QHierarchyTagAndLayerLabelSize labelSize;
+        private Rect tagRect = new Rect();
+        private Rect layerRect = new Rect();
+        private bool needDrawTag;
+        private bool needDrawLayer;
+        private int layer;
+        private string tag;
+
+        // CONSTRUCTOR
+        public QTagLayerComponent()
+        {
+            labelStyle = new GUIStyle();
+            labelStyle.fontSize = 8;
+            labelStyle.clipping = TextClipping.Clip;  
+            labelStyle.alignment = TextAnchor.MiddleLeft;
+
+            QSettings.getInstance().addEventListener(QSetting.TagAndLayerSizeShowType       , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.TagAndLayerType               , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.TagAndLayerSizeValueType      , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.TagAndLayerSizeValuePixel     , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.TagAndLayerSizeValuePercent   , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.TagAndLayerLabelSize          , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.TagAndLayerShow               , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.TagAndLayerShowDuringPlayMode , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.TagAndLayerTagLabelColor      , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.TagAndLayerLayerLabelColor    , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.TagAndLayerAligment           , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.TagAndLayerLabelAlpha         , settingsChanged);
+            settingsChanged();
+        }
+
+        // PRIVATE
+        private void settingsChanged()
+        {
+            showAlways  = QSettings.getInstance().get<int>(QSetting.TagAndLayerType) == (int)QHierarchyTagAndLayerType.Always;
+            showType    = (QHierarchyTagAndLayerShowType)QSettings.getInstance().get<int>(QSetting.TagAndLayerSizeShowType);
+            sizeIsPixel = QSettings.getInstance().get<int>(QSetting.TagAndLayerSizeValueType) == (int)QHierarchyTagAndLayerSizeType.Pixel;
+            pixelSize   = QSettings.getInstance().get<int>(QSetting.TagAndLayerSizeValuePixel);
+            percentSize = QSettings.getInstance().get<float>(QSetting.TagAndLayerSizeValuePercent);
+            labelSize   = (QHierarchyTagAndLayerLabelSize)QSettings.getInstance().get<int>(QSetting.TagAndLayerLabelSize);
+            enabled     = QSettings.getInstance().get<bool>(QSetting.TagAndLayerShow);
+            tagColor    = QSettings.getInstance().getColor(QSetting.TagAndLayerTagLabelColor);
+            layerColor  = QSettings.getInstance().getColor(QSetting.TagAndLayerLayerLabelColor);
+            labelAlpha  = QSettings.getInstance().get<float>(QSetting.TagAndLayerLabelAlpha);
+            showComponentDuringPlayMode = QSettings.getInstance().get<bool>(QSetting.TagAndLayerShowDuringPlayMode);
+
+            QHierarchyTagAndLayerAligment aligment = (QHierarchyTagAndLayerAligment)QSettings.getInstance().get<int>(QSetting.TagAndLayerAligment);
+            switch (aligment)
+            {
+                case QHierarchyTagAndLayerAligment.Left  : labelStyle.alignment = TextAnchor.MiddleLeft;   break;
+                case QHierarchyTagAndLayerAligment.Center: labelStyle.alignment = TextAnchor.MiddleCenter; break;
+                case QHierarchyTagAndLayerAligment.Right : labelStyle.alignment = TextAnchor.MiddleRight;  break;
+            }
+        }
+
+        // DRAW
+        public override QLayoutStatus layout(GameObject gameObject, QObjectList objectList, Rect selectionRect, ref Rect curRect, float maxWidth)
+        {
+            float textWidth = sizeIsPixel ? pixelSize : percentSize * rect.x;
+            rect.width = textWidth + 4;
+
+            if (maxWidth < rect.width)
+            {
+                return QLayoutStatus.Failed;
+            }
+            else
+            {
+                curRect.x -= rect.width + 2;
+                rect.x = curRect.x;
+                rect.y = curRect.y;
+                rect.y += (EditorGUIUtility.singleLineHeight - rect.height) * 0.5f;
+                //rect.height = EditorGUIUtility.singleLineHeight;
+
+                layer  = gameObject.layer; 
+                tag = getTagName(gameObject);             
+                
+                needDrawTag   = (showType != QHierarchyTagAndLayerShowType.Layer) && ((showAlways || tag   != "Untagged"));
+                needDrawLayer = (showType != QHierarchyTagAndLayerShowType.Tag  ) && ((showAlways || layer != 0         ));
+
+                #if UNITY_2019_1_OR_NEWER
+                    if (labelSize == QHierarchyTagAndLayerLabelSize.Big || (labelSize == QHierarchyTagAndLayerLabelSize.BigIfSpecifiedOnlyTagOrLayer && needDrawTag != needDrawLayer)) 
+                        labelStyle.fontSize = 8;
+                    else 
+                        labelStyle.fontSize = 7;
+                #else
+                    if (labelSize == QHierarchyTagAndLayerLabelSize.Big || (labelSize == QHierarchyTagAndLayerLabelSize.BigIfSpecifiedOnlyTagOrLayer && needDrawTag != needDrawLayer)) 
+                        labelStyle.fontSize = 9;
+                    else 
+                        labelStyle.fontSize = 8;
+                #endif
+
+                if (needDrawTag) tagRect.Set(rect.x, rect.y - (needDrawLayer ? 4 : 0), rect.width, rect.height);                                                   
+                if (needDrawLayer) layerRect.Set(rect.x, rect.y + (needDrawTag ? 4 : 0), rect.width, rect.height);                    
+
+                return QLayoutStatus.Success;
+            }
+        }
+
+        public override void draw(GameObject gameObject, QObjectList objectList, Rect selectionRect)
+        {
+            if (needDrawTag ) 
+            {
+                tagColor.a = (tag == "Untagged" ? labelAlpha : 1.0f);
+                labelStyle.normal.textColor = tagColor;
+                EditorGUI.LabelField(tagRect, tag, labelStyle);
+            }
+
+            if (needDrawLayer) 
+            {
+                layerColor.a = (layer == 0 ? labelAlpha : 1.0f);
+                labelStyle.normal.textColor = layerColor;
+                EditorGUI.LabelField(layerRect, getLayerName(layer), labelStyle);
+            }
+        }
+
+        public override void eventHandler(GameObject gameObject, QObjectList objectList, Event currentEvent)
+        {                       
+            if (Event.current.isMouse && currentEvent.type == EventType.MouseDown && Event.current.button == 0)
+            {
+                if (needDrawTag && needDrawLayer)
+                {
+                    tagRect.height = 8;
+                    layerRect.height = 8;
+                    tagRect.y += 4;
+                    layerRect.y += 4;
+                }
+
+                if (needDrawTag && tagRect.Contains(Event.current.mousePosition))
+                {
+                    gameObjects = Selection.Contains(gameObject) ? Selection.gameObjects : new GameObject[] { gameObject };
+                    showTagsContextMenu(tag);
+                    Event.current.Use();
+                }
+                else if (needDrawLayer && layerRect.Contains(Event.current.mousePosition))
+                {
+                    gameObjects = Selection.Contains(gameObject) ? Selection.gameObjects : new GameObject[] { gameObject };
+                    showLayersContextMenu(LayerMask.LayerToName(layer));
+                    Event.current.Use();
+                }
+            }
+        }
+
+        private string getTagName(GameObject gameObject)
+        {
+            string tag = "Undefined";
+            try { tag = gameObject.tag; }
+            catch {}
+            return tag;
+        }
+
+        public string getLayerName(int layer)
+        {
+            string layerName = LayerMask.LayerToName(layer);
+            if (layerName.Equals("")) layerName = "Undefined";
+            return layerName;
+        }
+
+        // PRIVATE
+        private void showTagsContextMenu(string tag)
+        {
+            List<string> tags = new List<string>(UnityEditorInternal.InternalEditorUtility.tags);
+            
+            GenericMenu menu = new GenericMenu();
+            menu.AddItem(new GUIContent("Untagged"  ), false, tagChangedHandler, "Untagged");
+            
+            for (int i = 0, n = tags.Count; i < n; i++)
+            {
+                string curTag = tags[i];
+                menu.AddItem(new GUIContent(curTag), tag == curTag, tagChangedHandler, curTag);
+            }
+            
+            menu.AddSeparator("");
+            menu.AddItem(new GUIContent("Add Tag..."  ), false, addTagOrLayerHandler, "Tags");
+            menu.ShowAsContext();
+        }
+
+        private void showLayersContextMenu(string layer)
+        {
+            List<string> layers = new List<string>(UnityEditorInternal.InternalEditorUtility.layers);
+            
+            GenericMenu menu = new GenericMenu();
+            menu.AddItem(new GUIContent("Default"  ), false, layerChangedHandler, "Default");
+            
+            for (int i = 0, n = layers.Count; i < n; i++)
+            {
+                string curLayer = layers[i];
+                menu.AddItem(new GUIContent(curLayer), layer == curLayer, layerChangedHandler, curLayer);
+            }
+            
+            menu.AddSeparator("");
+            menu.AddItem(new GUIContent("Add Layer..."  ), false, addTagOrLayerHandler, "Layers");
+            menu.ShowAsContext();
+        }
+
+        private void tagChangedHandler(object newTag)
+        {
+            for (int i = gameObjects.Length - 1; i >= 0; i--)
+            {
+                GameObject gameObject = gameObjects[i];
+                Undo.RecordObject(gameObject, "Change Tag");
+                gameObject.tag = (string)newTag;
+                EditorUtility.SetDirty(gameObject);
+            }
+        }
+
+        private void layerChangedHandler(object newLayer)
+        {
+            int newLayerId = LayerMask.NameToLayer((string)newLayer);
+            for (int i = gameObjects.Length - 1; i >= 0; i--)
+            {
+                GameObject gameObject = gameObjects[i];
+                Undo.RecordObject(gameObject, "Change Layer");
+                gameObject.layer = newLayerId;
+                EditorUtility.SetDirty(gameObject);
+            }
+        }
+
+        private void addTagOrLayerHandler(object value)
+        {
+            PropertyInfo propertyInfo = typeof(EditorApplication).GetProperty("tagManager", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.GetProperty);
+            UnityEngine.Object obj = (UnityEngine.Object)(propertyInfo.GetValue(null, null));
+            obj.GetType().GetField("m_DefaultExpandedFoldout").SetValue(obj, value);
+            Selection.activeObject = obj;
+        }
+    }
+}
+
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QTagLayerComponent.cs.meta b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QTagLayerComponent.cs.meta
new file mode 100644
index 0000000..819356c
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QTagLayerComponent.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 4932a596a527d4248b5c3ea4458bcf12
+timeCreated: 1477898839
+licenseType: Store
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QTreeMapComponent.cs b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QTreeMapComponent.cs
new file mode 100644
index 0000000..28ffb6f
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QTreeMapComponent.cs
@@ -0,0 +1,173 @@
+using UnityEngine;
+using UnityEditor;
+using System;
+using qtools.qhierarchy.pcomponent.pbase;
+using qtools.qhierarchy.pdata;
+using qtools.qhierarchy.phierarchy;
+using qtools.qhierarchy.phelper;
+using System.Collections.Generic;
+using System.Collections;
+
+namespace qtools.qhierarchy.pcomponent
+{
+    public class QTreeMapComponent: QBaseComponent
+    {
+        // CONST
+        private const float TREE_STEP_WIDTH  = 14.0f;
+        
+        // PRIVATE
+        private Texture2D treeMapLevelTexture;       
+        private Texture2D treeMapLevel4Texture;       
+        private Texture2D treeMapCurrentTexture;   
+        private Texture2D treeMapLastTexture;
+        private Texture2D treeMapObjectTexture;    
+        private bool enhanced;
+        private bool transparentBackground;
+        private Color backgroundColor;
+        private Color treeMapColor;
+        
+        // CONSTRUCTOR
+        public QTreeMapComponent()
+        { 
+
+            treeMapLevelTexture   = QResources.getInstance().getTexture(QTexture.QTreeMapLevel);
+            treeMapLevel4Texture  = QResources.getInstance().getTexture(QTexture.QTreeMapLevel4);
+            treeMapCurrentTexture = QResources.getInstance().getTexture(QTexture.QTreeMapCurrent);
+            #if UNITY_2018_3_OR_NEWER
+                treeMapObjectTexture = QResources.getInstance().getTexture(QTexture.QTreeMapLine);
+            #else
+                treeMapObjectTexture  = QResources.getInstance().getTexture(QTexture.QTreeMapObject);
+            #endif
+            treeMapLastTexture    = QResources.getInstance().getTexture(QTexture.QTreeMapLast);
+            
+            rect.width  = 14;
+            rect.height = 16;
+            
+            showComponentDuringPlayMode = true;
+
+            QSettings.getInstance().addEventListener(QSetting.AdditionalBackgroundColor, settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.TreeMapShow           , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.TreeMapColor          , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.TreeMapEnhanced       , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.TreeMapTransparentBackground, settingsChanged);
+            settingsChanged();
+        }
+        
+        // PRIVATE
+        private void settingsChanged() {
+            backgroundColor     = QSettings.getInstance().getColor(QSetting.AdditionalBackgroundColor);
+            enabled             = QSettings.getInstance().get<bool>(QSetting.TreeMapShow);
+            treeMapColor        = QSettings.getInstance().getColor(QSetting.TreeMapColor);
+            enhanced            = QSettings.getInstance().get<bool>(QSetting.TreeMapEnhanced);
+            transparentBackground = QSettings.getInstance().get<bool>(QSetting.TreeMapTransparentBackground);
+        }
+        
+        // DRAW
+        public override QLayoutStatus layout(GameObject gameObject, QObjectList objectList, Rect selectionRect, ref Rect curRect, float maxWidth)
+        {
+            rect.y = selectionRect.y;
+            
+            if (!transparentBackground) 
+            {
+                rect.x = 0;
+                
+                rect.width = selectionRect.x - 14;
+                EditorGUI.DrawRect(rect, backgroundColor);
+                rect.width = 14;
+            }
+
+            return QLayoutStatus.Success;
+        }
+
+        public override void draw(GameObject gameObject, QObjectList objectList, Rect selectionRect)
+        {
+            int childCount = gameObject.transform.childCount;
+            int level = Mathf.RoundToInt(selectionRect.x / 14.0f);
+
+            if (enhanced)
+            {
+                Transform gameObjectTransform = gameObject.transform;
+                Transform parentTransform = null;
+
+                for (int i = 0, j = level - 1; j >= 0; i++, j--)
+                {
+                    rect.x = 14 * j;
+                    if (i == 0)
+                    {
+                        if (childCount == 0) {
+                            #if UNITY_2018_3_OR_NEWER
+                                QColorUtils.setColor(treeMapColor);
+                            #endif
+                            GUI.DrawTexture(rect, treeMapObjectTexture);
+                        }
+                        gameObjectTransform = gameObject.transform;
+                    }
+                    else if (i == 1)
+                    {
+                        QColorUtils.setColor(treeMapColor);
+                        if (parentTransform == null) {
+                            if (gameObjectTransform.GetSiblingIndex() == gameObject.scene.rootCount - 1) {
+                                GUI.DrawTexture(rect, treeMapLastTexture);
+                            } else {
+                                GUI.DrawTexture(rect, treeMapCurrentTexture);
+                            }
+                        } else if (gameObjectTransform.GetSiblingIndex() == parentTransform.childCount - 1) {
+                            GUI.DrawTexture(rect, treeMapLastTexture);
+                        } else {
+                            GUI.DrawTexture(rect, treeMapCurrentTexture);
+                        }
+                        gameObjectTransform = parentTransform;
+                    }
+                    else
+                    {
+                        if (parentTransform == null) {
+                            if (gameObjectTransform.GetSiblingIndex() != gameObject.scene.rootCount - 1)
+                                GUI.DrawTexture(rect, treeMapLevelTexture);
+                        } else if (gameObjectTransform.GetSiblingIndex() != parentTransform.childCount - 1)
+                            GUI.DrawTexture(rect, treeMapLevelTexture);
+
+                        gameObjectTransform = parentTransform;                       
+                    }
+                    if (gameObjectTransform != null) 
+						parentTransform = gameObjectTransform.parent;
+					else
+                        break;
+                }
+                QColorUtils.clearColor();
+            }
+            else
+            {
+                for (int i = 0, j = level - 1; j >= 0; i++, j--)
+                {
+                    rect.x = 14 * j;
+                    if (i == 0)
+                    {
+                        if (childCount > 0)
+                            continue;
+                        else {
+                            #if UNITY_2018_3_OR_NEWER
+                                QColorUtils.setColor(treeMapColor);
+                            #endif
+                            GUI.DrawTexture(rect, treeMapObjectTexture);
+                        }
+                    }
+                    else if (i == 1)
+                    {
+                        QColorUtils.setColor(treeMapColor);
+                        GUI.DrawTexture(rect, treeMapCurrentTexture);
+                    }
+                    else
+                    {
+                        rect.width = 14 * 4;
+                        rect.x -= 14 * 3;
+                        j -= 3;
+                        GUI.DrawTexture(rect, treeMapLevel4Texture);
+                        rect.width = 14;
+                    }
+                }
+                QColorUtils.clearColor();
+            }
+        }
+    }
+}
+
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QTreeMapComponent.cs.meta b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QTreeMapComponent.cs.meta
new file mode 100644
index 0000000..31eeff3
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QTreeMapComponent.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 7b244e6664a14574aa2e6641e341e305
+timeCreated: 1474890066
+licenseType: Store
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QVerticesAndTrianglesCountComponent.cs b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QVerticesAndTrianglesCountComponent.cs
new file mode 100644
index 0000000..d8223e9
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QVerticesAndTrianglesCountComponent.cs
@@ -0,0 +1,151 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEditor;
+using qtools.qhierarchy.pcomponent.pbase;
+using qtools.qhierarchy.pdata;
+
+namespace qtools.qhierarchy.pcomponent
+{
+    public class QVerticesAndTrianglesCountComponent: QBaseComponent
+    {
+        // PRIVATE
+        private GUIStyle labelStyle;
+        private Color verticesLabelColor;
+        private Color trianglesLabelColor;
+        private bool calculateTotalCount;
+        private bool showTrianglesCount;
+        private bool showVerticesCount;
+        private QHierarchySize labelSize;
+
+        // CONSTRUCTOR
+        public QVerticesAndTrianglesCountComponent ()
+        {
+            labelStyle = new GUIStyle();            
+            labelStyle.clipping = TextClipping.Clip;  
+            labelStyle.alignment = TextAnchor.MiddleRight;
+
+            QSettings.getInstance().addEventListener(QSetting.VerticesAndTrianglesShow                  , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.VerticesAndTrianglesShowDuringPlayMode    , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.VerticesAndTrianglesCalculateTotalCount   , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.VerticesAndTrianglesShowTriangles         , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.VerticesAndTrianglesShowVertices          , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.VerticesAndTrianglesLabelSize             , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.VerticesAndTrianglesVerticesLabelColor    , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.VerticesAndTrianglesTrianglesLabelColor   , settingsChanged);
+
+            settingsChanged();
+        }
+
+        // PRIVATE
+        private void settingsChanged()
+        {
+            enabled                     = QSettings.getInstance().get<bool>(QSetting.VerticesAndTrianglesShow);
+            showComponentDuringPlayMode = QSettings.getInstance().get<bool>(QSetting.VerticesAndTrianglesShowDuringPlayMode);
+            calculateTotalCount         = QSettings.getInstance().get<bool>(QSetting.VerticesAndTrianglesCalculateTotalCount);
+            showTrianglesCount          = QSettings.getInstance().get<bool>(QSetting.VerticesAndTrianglesShowTriangles);
+            showVerticesCount           = QSettings.getInstance().get<bool>(QSetting.VerticesAndTrianglesShowVertices);
+            verticesLabelColor          = QSettings.getInstance().getColor(QSetting.VerticesAndTrianglesVerticesLabelColor);
+            trianglesLabelColor         = QSettings.getInstance().getColor(QSetting.VerticesAndTrianglesTrianglesLabelColor);
+            labelSize                   = (QHierarchySize)QSettings.getInstance().get<int>(QSetting.VerticesAndTrianglesLabelSize);
+
+            #if UNITY_2019_1_OR_NEWER
+                labelStyle.fontSize = labelSize == QHierarchySize.Big ? 7 : 6;
+                rect.width = labelSize == QHierarchySize.Big ? 24 : 22;
+            #else
+                labelStyle.fontSize = labelSize == QHierarchySize.Big ? 9 : 8;
+                rect.width = labelSize == QHierarchySize.Big ? 33 : 25;
+            #endif
+        }   
+
+        // DRAW
+        public override QLayoutStatus layout(GameObject gameObject, QObjectList objectList, Rect selectionRect, ref Rect curRect, float maxWidth)
+        {
+            if (maxWidth < rect.width)
+            {
+                return QLayoutStatus.Failed;
+            }
+            else
+            {
+                curRect.x -= rect.width + 2;
+                rect.x = curRect.x;
+                rect.y = curRect.y;
+                #if UNITY_2019_1_OR_NEWER                
+                    rect.y += labelSize == QHierarchySize.Big ? 2 : 1;
+                #endif
+                return QLayoutStatus.Success;
+            }
+        }
+        
+        public override void draw(GameObject gameObject, QObjectList objectList, Rect selectionRect)
+        {  
+            int vertexCount = 0;
+            int triangleCount = 0;
+
+            MeshFilter[] meshFilterArray = calculateTotalCount ? gameObject.GetComponentsInChildren<MeshFilter>(true) : gameObject.GetComponents<MeshFilter>();
+            for (int i = 0; i < meshFilterArray.Length; i++)
+            {
+                Mesh sharedMesh = meshFilterArray[i].sharedMesh;
+                if (sharedMesh != null)
+                {
+                    if (showVerticesCount) vertexCount += sharedMesh.vertexCount;
+                    if (showTrianglesCount) triangleCount += sharedMesh.triangles.Length;
+                }
+            }
+
+            SkinnedMeshRenderer[] skinnedMeshRendererArray = calculateTotalCount ? gameObject.GetComponentsInChildren<SkinnedMeshRenderer>(true) : gameObject.GetComponents<SkinnedMeshRenderer>();
+            for (int i = 0; i < skinnedMeshRendererArray.Length; i++)
+            {
+                Mesh sharedMesh = skinnedMeshRendererArray[i].sharedMesh;
+                if (sharedMesh != null)
+                {   
+                    if (showVerticesCount) vertexCount += sharedMesh.vertexCount;
+                    if (showTrianglesCount) triangleCount += sharedMesh.triangles.Length;
+                }
+            }
+
+            triangleCount /= 3;
+
+            if (vertexCount > 0 || triangleCount > 0)
+            {
+                if (showTrianglesCount && showVerticesCount) 
+                {
+                    rect.y -= 4;
+                    labelStyle.normal.textColor = verticesLabelColor;
+                    EditorGUI.LabelField(rect, getCountString(vertexCount), labelStyle);
+
+                    rect.y += 8;
+                    labelStyle.normal.textColor = trianglesLabelColor;
+                    EditorGUI.LabelField(rect, getCountString(triangleCount), labelStyle);
+                }
+                else if (showVerticesCount)
+                {
+                    labelStyle.normal.textColor = verticesLabelColor;
+                    EditorGUI.LabelField(rect, getCountString(vertexCount), labelStyle);
+                }
+                else
+                {
+                    labelStyle.normal.textColor = trianglesLabelColor;
+                    EditorGUI.LabelField(rect, getCountString(triangleCount), labelStyle);
+                }
+            }
+        }
+
+        // PRIVATE
+        private string getCountString(int count)
+        {
+            if (count < 1000) return count.ToString();
+            else if (count < 1000000) 
+            {
+                if (count > 100000) return (count / 1000.0f).ToString("0") + "k";
+                else return (count / 1000.0f).ToString("0.0") + "k";
+            }
+            else 
+            {
+                if (count > 10000000) return (count / 1000.0f).ToString("0") + "M";
+                else return (count / 1000000.0f).ToString("0.0") + "M";
+            }
+        }
+    }
+}
+
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QVerticesAndTrianglesCountComponent.cs.meta b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QVerticesAndTrianglesCountComponent.cs.meta
new file mode 100644
index 0000000..49fe307
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QVerticesAndTrianglesCountComponent.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: acd2f57f3f7434a4dbd2ca175601410d
+timeCreated: 1477899140
+licenseType: Store
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QVisibilityComponent.cs b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QVisibilityComponent.cs
new file mode 100644
index 0000000..3953c71
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QVisibilityComponent.cs
@@ -0,0 +1,292 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEditor;
+using qtools.qhierarchy.pcomponent.pbase;
+using qtools.qhierarchy.phierarchy;
+using qtools.qhierarchy.phelper;
+using qtools.qhierarchy.pdata;
+
+namespace qtools.qhierarchy.pcomponent
+{
+    public class QVisibilityComponent: QBaseComponent
+    {
+        // PRIVATE
+        private Color activeColor;
+        private Color inactiveColor;
+        private Color specialColor;
+        private Texture2D visibilityButtonTexture;
+        private Texture2D visibilityOffButtonTexture;
+        private int targetVisibilityState = -1;
+
+        // CONSTRUCTOR
+        public QVisibilityComponent()
+        {
+            rect.width = 18;
+
+            visibilityButtonTexture    = QResources.getInstance().getTexture(QTexture.QVisibilityButton);
+            visibilityOffButtonTexture = QResources.getInstance().getTexture(QTexture.QVisibilityOffButton);
+
+            QSettings.getInstance().addEventListener(QSetting.VisibilityShow                , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.VisibilityShowDuringPlayMode  , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.AdditionalActiveColor         , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.AdditionalInactiveColor       , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.AdditionalSpecialColor        , settingsChanged);
+            settingsChanged();
+        }
+
+        private void settingsChanged()
+        {
+            enabled                     = QSettings.getInstance().get<bool>(QSetting.VisibilityShow);
+            showComponentDuringPlayMode = QSettings.getInstance().get<bool>(QSetting.VisibilityShowDuringPlayMode);
+            activeColor                 = QSettings.getInstance().getColor(QSetting.AdditionalActiveColor);
+            inactiveColor               = QSettings.getInstance().getColor(QSetting.AdditionalInactiveColor);
+            specialColor                = QSettings.getInstance().getColor(QSetting.AdditionalSpecialColor);
+        }
+
+        // DRAW
+        public override QLayoutStatus layout(GameObject gameObject, QObjectList objectList, Rect selectionRect, ref Rect curRect, float maxWidth)
+        {
+            if (maxWidth < 18)
+            {
+                return QLayoutStatus.Failed;
+            }
+            else
+            {
+                curRect.x -= 18;
+                rect.x = curRect.x;
+                rect.y = curRect.y;
+                return QLayoutStatus.Success;
+            }
+        }
+
+        public override void disabledHandler(GameObject gameObject, QObjectList objectList)
+        {
+            if (objectList != null)
+            {
+                if (gameObject.activeSelf && objectList.editModeVisibileObjects.Contains(gameObject))
+                {
+                    objectList.editModeVisibileObjects.Remove(gameObject);
+                    gameObject.SetActive(false);
+                    EditorUtility.SetDirty(gameObject);
+                }
+                else if (!gameObject.activeSelf && objectList.editModeInvisibleObjects.Contains(gameObject))
+                {
+                    objectList.editModeInvisibleObjects.Remove(gameObject);
+                    gameObject.SetActive(true);
+                    EditorUtility.SetDirty(gameObject);
+                }
+            }
+        }
+
+        public override void draw(GameObject gameObject, QObjectList objectList, Rect selectionRect)
+        {
+            int visibility = gameObject.activeSelf ? 1 : 0;
+            
+            bool editModeVisibleObjectsContains = isEditModeVisibile(gameObject, objectList);
+            bool editModeInvisibleObjectsContains = isEditModeInvisibile(gameObject, objectList);
+            
+            if (!EditorApplication.isPlayingOrWillChangePlaymode && ((!gameObject.activeSelf && editModeVisibleObjectsContains) || (gameObject.activeSelf && editModeInvisibleObjectsContains)))
+                gameObject.SetActive(!gameObject.activeSelf);
+                        
+
+            Transform transform = gameObject.transform;
+            while (transform.parent != null)
+            {
+                transform = transform.parent;
+                if (!transform.gameObject.activeSelf) 
+                {
+                    visibility = 2;
+                    break;
+                }
+            }
+                       
+            if (!EditorApplication.isPlayingOrWillChangePlaymode && (editModeVisibleObjectsContains || editModeInvisibleObjectsContains))
+            {
+                if (visibility == 0)
+                {
+                    QColorUtils.setColor(specialColor);
+                    GUI.DrawTexture(rect, visibilityOffButtonTexture);
+                }
+                else if (visibility == 1)
+                {
+                    QColorUtils.setColor(specialColor);
+                    GUI.DrawTexture(rect, visibilityButtonTexture);
+                }
+                else
+                {
+                    QColorUtils.setColor(specialColor, 1.0f, 0.4f);
+                    GUI.DrawTexture(rect, editModeVisibleObjectsContains ? visibilityButtonTexture : visibilityOffButtonTexture);
+                }
+            }
+            else
+            {
+                if (visibility == 0)
+                {
+                    QColorUtils.setColor(inactiveColor);
+                    GUI.DrawTexture(rect, visibilityOffButtonTexture);
+                }
+                else if (visibility == 1)
+                {
+                    QColorUtils.setColor(activeColor);
+                    GUI.DrawTexture(rect, visibilityButtonTexture);
+                }
+                else
+                {
+                    if (gameObject.activeSelf)
+                    {
+                        QColorUtils.setColor(activeColor, 0.65f, 0.65f);
+                        GUI.DrawTexture(rect, visibilityButtonTexture);                    
+                    }
+                    else
+                    {
+                        QColorUtils.setColor(inactiveColor, 0.85f, 0.85f);
+                        GUI.DrawTexture(rect, visibilityOffButtonTexture);                    
+                    }
+                }
+            }
+            QColorUtils.clearColor();
+        }
+
+        public override void eventHandler(GameObject gameObject, QObjectList objectList, Event currentEvent)
+        {
+            if (currentEvent.isMouse && currentEvent.button == 0 && rect.Contains(currentEvent.mousePosition))
+            {
+                if (currentEvent.type == EventType.MouseDown)
+                {
+                    targetVisibilityState = ((!gameObject.activeSelf) == true ? 1 : 0);
+                }
+                else if (currentEvent.type == EventType.MouseDrag && targetVisibilityState != -1)
+                {
+                    if (targetVisibilityState == (gameObject.activeSelf == true ? 1 : 0)) return;
+                } 
+                else
+                {
+                    targetVisibilityState = -1;
+                    return;
+                }
+                                                            
+                bool showWarning = QSettings.getInstance().get<bool>(QSetting.AdditionalShowModifierWarning);
+                
+                List<GameObject> targetGameObjects = new List<GameObject>();
+                if (currentEvent.control || currentEvent.command) 
+                {
+                    if (currentEvent.shift)
+                    {
+                        if (!showWarning || EditorUtility.DisplayDialog("Change edit-time visibility", "Are you sure you want to turn " + (gameObject.activeSelf ? "off" : "on") + " the edit-time visibility of this GameObject and all its children? (You can disable this warning in the settings)", "Yes", "Cancel"))
+                        {
+                            getGameObjectListRecursive(gameObject, ref targetGameObjects);
+                        }
+                    }
+                    else if (currentEvent.alt)
+                    {
+                        if (gameObject.transform.parent != null)
+                        {
+                            if (!showWarning || EditorUtility.DisplayDialog("Change edit-time visibility", "Are you sure you want to turn " + (gameObject.activeSelf ? "off" : "on") + " the edit-time visibility this GameObject and its siblings? (You can disable this warning in the settings)", "Yes", "Cancel"))
+                            {
+                                getGameObjectListRecursive(gameObject.transform.parent.gameObject, ref targetGameObjects, 1);
+                                targetGameObjects.Remove(gameObject.transform.parent.gameObject);
+                            }
+                        }
+                        else
+                        {
+                            Debug.Log("This action for root objects is supported for Unity3d 5.3.3 and above");
+                            return;
+                        }
+                    }
+                    else
+                    {
+                        getGameObjectListRecursive(gameObject, ref targetGameObjects, 0);
+                    }
+                }
+                else if (currentEvent.shift)
+                {
+                    if (!showWarning || EditorUtility.DisplayDialog("Change visibility", "Are you sure you want to turn " + (gameObject.activeSelf ? "off" : "on") + " the visibility of this GameObject and all its children? (You can disable this warning in the settings)", "Yes", "Cancel"))
+                    {
+                        getGameObjectListRecursive(gameObject, ref targetGameObjects);           
+                    }
+                }
+                else if (currentEvent.alt) 
+                {
+                    if (gameObject.transform.parent != null)
+                    {
+                        if (!showWarning || EditorUtility.DisplayDialog("Change visibility", "Are you sure you want to turn " + (gameObject.activeSelf ? "off" : "on") + " the visibility this GameObject and its siblings? (You can disable this warning in the settings)", "Yes", "Cancel"))
+                        {
+                            getGameObjectListRecursive(gameObject.transform.parent.gameObject, ref targetGameObjects, 1);
+                            targetGameObjects.Remove(gameObject.transform.parent.gameObject);
+                        }
+                    }
+                    else
+                    {
+                        Debug.Log("This action for root objects is supported for Unity3d 5.3.3 and above");
+                        return;
+                    }
+                }
+                else 
+                {
+                    if (Selection.Contains(gameObject))
+                    {
+                        targetGameObjects.AddRange(Selection.gameObjects);
+                    }
+                    else
+                    {
+                        getGameObjectListRecursive(gameObject, ref targetGameObjects, 0);
+                    };
+                }
+                
+                setVisibility(targetGameObjects, objectList, !gameObject.activeSelf, currentEvent.control || currentEvent.command);
+                currentEvent.Use();  
+            } 
+        }
+
+        // PRIVATE
+        private bool isEditModeVisibile(GameObject gameObject, QObjectList objectList)
+        {
+            return objectList == null ? false : objectList.editModeVisibileObjects.Contains(gameObject);
+        }
+        
+        private bool isEditModeInvisibile(GameObject gameObject, QObjectList objectList)
+        {
+            return objectList == null ? false : objectList.editModeInvisibleObjects.Contains(gameObject);
+        }
+        
+        private void setVisibility(List<GameObject> gameObjects, QObjectList objectList, bool targetVisibility, bool editMode)
+        {
+            if (gameObjects.Count == 0) return;
+
+            if (objectList == null && editMode) objectList = QObjectListManager.getInstance().getObjectList(gameObjects[0], true);
+            if (objectList != null) Undo.RecordObject(objectList, "visibility change");
+            
+            for (int i = gameObjects.Count - 1; i >= 0; i--)
+            {        
+                GameObject curGameObject = gameObjects[i];
+                Undo.RecordObject(curGameObject, "visibility change");
+                
+                if (editMode)
+                {
+                    if (!targetVisibility)
+                    {
+                        objectList.editModeVisibileObjects.Remove(curGameObject);        
+                        if (!objectList.editModeInvisibleObjects.Contains(curGameObject))
+                            objectList.editModeInvisibleObjects.Add(curGameObject);
+                    }
+                    else
+                    {
+                        objectList.editModeInvisibleObjects.Remove(curGameObject);                            
+                        if (!objectList.editModeVisibileObjects.Contains(curGameObject))
+                            objectList.editModeVisibileObjects.Add(curGameObject);
+                    }
+                }
+                else if (objectList != null)
+                {
+                    objectList.editModeVisibileObjects.Remove(curGameObject);
+                    objectList.editModeInvisibleObjects.Remove(curGameObject);
+                }
+                
+                curGameObject.SetActive(targetVisibility);
+                EditorUtility.SetDirty(curGameObject);
+            }
+        }
+    }
+}
+
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QVisibilityComponent.cs.meta b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QVisibilityComponent.cs.meta
new file mode 100644
index 0000000..af79966
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/QVisibilityComponent.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 29ed13b1fdfce9c4abe6efeee4611f51
+timeCreated: 1474961304
+licenseType: Store
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/pbase.meta b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/pbase.meta
new file mode 100644
index 0000000..064bfd0
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/pbase.meta
@@ -0,0 +1,10 @@
+fileFormatVersion: 2
+guid: bf7b2f59a50ea694b898adc34d520d86
+folderAsset: yes
+timeCreated: 1515657177
+licenseType: Store
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/pbase/QBaseComponent.cs b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/pbase/QBaseComponent.cs
new file mode 100644
index 0000000..0fa9288
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/pbase/QBaseComponent.cs
@@ -0,0 +1,81 @@
+using UnityEngine;
+using System;
+using System.Collections.Generic;
+using qtools.qhierarchy.phierarchy;
+
+namespace qtools.qhierarchy.pcomponent.pbase
+{
+    public enum QLayoutStatus
+    {
+        Success,
+        Partly,
+        Failed,
+    }
+
+    public class QBaseComponent
+    {
+        // PUBLIC
+        public Rect rect = new Rect(0, 0, 16, 16);
+
+        // PRIVATE
+        protected bool enabled = false;
+        protected bool showComponentDuringPlayMode = false;
+
+        // CONSTRUCTOR
+        public QBaseComponent()
+        {
+        }
+
+        // PUBLIC
+        public virtual QLayoutStatus layout(GameObject gameObject, QObjectList objectList, Rect selectionRect, ref Rect curRect, float maxWidth)
+        {
+            return QLayoutStatus.Success;
+        }
+
+        public virtual void draw(GameObject gameObject, QObjectList objectList, Rect selectionRect)
+        {
+
+        }
+
+        public virtual void eventHandler(GameObject gameObject, QObjectList objectList, Event currentEvent)
+        {
+
+        }
+
+        public virtual void disabledHandler(GameObject gameObject, QObjectList objectList)
+        {
+
+        }
+
+        public virtual void setEnabled(bool value)
+        {
+            this.enabled = value;
+        }       
+
+        public virtual bool isEnabled()
+        {
+            if (!enabled) 
+            {
+                return false;
+            }
+            else 
+            {
+                if (Application.isPlaying) return showComponentDuringPlayMode;            
+                else return true;
+            }
+        }
+
+        // PROTECTED
+        protected void getGameObjectListRecursive(GameObject gameObject, ref List<GameObject>result, int maxDepth = int.MaxValue)
+        {
+            result.Add(gameObject);
+            if (maxDepth > 0)
+            {
+                Transform transform = gameObject.transform;
+                for (int i = transform.childCount - 1; i >= 0; i--)      
+                    getGameObjectListRecursive(transform.GetChild(i).gameObject, ref result, maxDepth - 1);     
+            }
+        }
+    }
+}
+
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/pbase/QBaseComponent.cs.meta b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/pbase/QBaseComponent.cs.meta
new file mode 100644
index 0000000..634d5e2
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/pcomponent/pbase/QBaseComponent.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 620cabcf0b368b54e82f999917adaa5e
+timeCreated: 1474890066
+licenseType: Store
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/pdata.meta b/Assets/Plugins/QHierarchy/Editor/Scripts/pdata.meta
new file mode 100644
index 0000000..5824bda
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/pdata.meta
@@ -0,0 +1,10 @@
+fileFormatVersion: 2
+guid: 288b7c4405cbf0a42a20f65be49ee978
+folderAsset: yes
+timeCreated: 1515657177
+licenseType: Store
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/pdata/QResources.cs b/Assets/Plugins/QHierarchy/Editor/Scripts/pdata/QResources.cs
new file mode 100644
index 0000000..0f3123e
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/pdata/QResources.cs
@@ -0,0 +1,140 @@
+using UnityEngine;
+using UnityEditor;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace qtools.qhierarchy.pdata
+{
+	public enum QTexture
+	{
+		QCheckBoxChecked = 0,
+		QCheckBoxUnchecked = 1,
+		QColorButton = 2,
+		QColorPalette = 3,
+		QComponentUnknownIcon = 4,
+		QDragButton = 5,
+		QErrorIcon = 6,
+		QLockButton = 7,
+		QMonoBehaviourIcon = 8,
+		QPrefabIcon = 9,
+		QRendererButton = 10,
+		QRestoreButton = 11,
+		QTreeMapCurrent = 12,
+		QTreeMapLast = 13,
+		QTreeMapLevel = 14,
+		QTreeMapLevel4 = 15,
+		QTreeMapObject = 16,
+		QTrimIcon = 17,
+		QVisibilityButton = 18,
+		QVisibilityOffButton = 19,
+        QTreeMapLine = 20,
+    };
+
+	public enum QColor
+	{
+		BackgroundDark,
+		Background,
+		Gray,
+		GrayLight,
+		GrayDark
+	}
+
+	public class QResources
+	{
+		// SINGLETON
+		private static QResources instance;
+		public static QResources getInstance()
+		{
+			if (instance == null) instance = new QResources();
+			return instance;
+		}
+
+		// PRIVATE
+		private Dictionary<QTexture, Texture2D> textures;
+		private Dictionary<QTexture, string> resourcesCommon = new Dictionary<QTexture, string>()
+		{
+			{ QTexture.QColorButton, "iVBORw0KGgoAAAANSUhEUgAAAAgAAAAQCAYAAAArij59AAAAWUlEQVQoFWP8//8/Az7AhE8SJDcYFLBAHakLpIOB2AGIDwDxWiC+DMQMMAUgSR+QABDAaLACmC8cwFIIAs6HKTiAkAOz4HyYFSA7QcABiA8AMYzPwDgUghoAHO8PN+sTbZ4AAAAASUVORK5CYII=" },
+			{ QTexture.QColorPalette, "iVBORw0KGgoAAAANSUhEUgAAAJYAAAA8CAYAAACEhkNqAAADBklEQVR4Ae2dT2sTQRyGZ5uALZaqhxJvevTixasHJR9Mqgc/gDfvkoP4IeqfowcVFPSSBDwYsCBpTY20jTuxC+a3dvKblzk+e1lm5n2n5eFhdguhqRb1FcTrd7cSm3Wtr1d/PdySy092b8ndp7NncnfrzTW5G/b16uN3evdueCGXN+QmRQgkCCBWAg5LOgHE0tnRTBBoiXX6aC+cvdxfqcRxnOeCgJdAS6zq3v2wqEVq5Ir3OI7zXBDwEuja4EYt0Fk9uZRrNAqL8WgpVZzngoCXQOvEisUoUXXj5l+p6jtSeXGSawj8V6zl4y+eVOdyNY/FpsQdAusItB6F/75TLR+L5+9Y8fHIybUOJ+sNgdaJ1byoNxLFe/NC35S4Q2AdgdaJ1Xmw1+osJePlvcWFiYsJtE6si6OsQMBPALH8rEhmEECsDFhE/QS6w+HQnzbJ+ellM5MxnPzMCK9GO5/i36ja9bE31Yp16/jwi9w9GW/L3XCgVz8f6t2rYSyXObFkdBRTBBArRYc1mQBiyegopgggVooOazIBxJLRUUwRQKwUHdZkAoglo6OYIoBYKTqsyQQQS0ZHMUUAsVJ0WJMJIJaMjmKKAGKl6LAmE0AsGR3FFAHEStFhTSbQHQwGcnm7uiR3w7eZ3N15dSJ33+/+kLuzo9dytzNsfQrcv9dXf9Qm3x7ZGf94Gj74wybJiWWAMCxDALHKcGQXQwCxDBCGZQggVhmO7GIIIJYBwrAMAcQqw5FdDAHEMkAYliGAWGU4soshgFgGCMMyBBCrDEd2MQQQywBhWIYAYpXhyC6GAGIZIAzLEECsMhzZxRCoer2e/CVN/cncbJcx3NQ/vrJzR/9yqOdXNjN+ydXodN5fncgYVQf6f8gJk4wfZKK3v5uJjOH1oH9ehxMrAzRRPwHE8rMimUEAsTJgEfUTQCw/K5IZBBArAxZRPwHE8rMimUEAsTJgEfUTQCw/K5IZBBArAxZRPwHE8rMimUEAsTJgEfUTQCw/K5IZBBArAxZRPwHE8rMimUHgD7Cif5j2Lp5yAAAAAElFTkSuQmCC" },
+			{ QTexture.QComponentUnknownIcon, "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABGElEQVQ4EWNgoBAwQvVLAWk1Isy6BVTzDFkdC5Sj9ujZy/3IEsjsD5+/MixdtJChs7XRESoON4QJWSEuNgc7K0NwRBRDbVMbyBKQS0EuBgPiDGBjYxDg4WLwDQxmqG/tghmC24CP334yZM3fziCfN4nBp3sFw+XHrxg42CGGOLt7Qu3G44Jlx64wHLn5iGFpdiCDnAg/Q9a87WDVIEPEhPhRDIAFIoqgjbosg66sGAOIBtkOMgwGuDjYYUwwjdUAkGYQePT2I8P0PWcYMl1MwHxsBN5ArFyxD+ySTBdjbHrBYngNAKnAZztIHq8BNupyIDV4AV4DOjYdBQciPhOwBiJMw8NJeTAmThqvC3DqQpIgNTfCtMJzJQDmf0F9Rh99OwAAAABJRU5ErkJggg==" },
+			{ QTexture.QErrorIcon, "iVBORw0KGgoAAAANSUhEUgAAAAcAAAAQCAYAAADagWXwAAAANklEQVQYGWP8/fs3Ay7AhEsCJE605H+gYhCGA6J1wnXAGAOhkwVmOZBmRGKDmUQ7iLRAIN9OAA9DBxP0TyMiAAAAAElFTkSuQmCC" },
+			{ QTexture.QLockButton, "iVBORw0KGgoAAAANSUhEUgAAAA0AAAAQCAYAAADNo/U5AAAAtklEQVQoFb2QsQ0CMQxFY6Cgp+EmYA4WgDVYhtuFLViBCagoKY/wXxRHXJDCQcGXvuxvf599sRhj+BaLaqCT3osr8SaexKs4Bpsyd4p38RVo6u5J0UWnBoazuBGXOaKp03dv8OSgImDAa0Q0oF/qs3zsOsfL+Pjg2vup7UOV94PU2l4cxBbo40snmpJB352y8SHfnBswvw2Y2ZZmheIrSWVoyv8N/fwQR/0AL9gCfXwJbPJ8cnwCewTKXVfaQ3EAAAAASUVORK5CYII=" },
+			{ QTexture.QMonoBehaviourIcon, "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAMUlEQVQ4EWP8//8/AyWABagZZEIhuYYwkasRpm/UAAaG0TAYDQNQfgClgz+wjEEODQAZqgWLOZX9TgAAAABJRU5ErkJggg==" },
+			{ QTexture.QPrefabIcon, "iVBORw0KGgoAAAANSUhEUgAAAAkAAAAQCAYAAADESFVDAAAAd0lEQVQoFY2RUQqAMAxDV/GeHkU8ijfzHv3QphIJm7AWtpbtkWTM3L3NapkBuC9Ba4D3j5rpGSDU8bbcd5lzLNmVINpBdhMb5sxsvdIZ4BVLMzYqMayqfcKAUjI6LKA0VG83ADgoQSYfzBepWkZhcFwwm0I5l+weLU0O7oJcg0oAAAAASUVORK5CYII=" },
+			{ QTexture.QRendererButton, "iVBORw0KGgoAAAANSUhEUgAAAAwAAAAQCAYAAAAiYZ4HAAAAdElEQVQoFWP8/v07AwsLCwOxgIlYhTB1JGsAuUUFiGVgJhCgDwCdz3KbgCKYtCOIAXYSKyurIxAzggRwsUFyIIDsBwewCITAxWZg/P37938khfiYICcdGHUSviD68+ePKlD+DihpgCMMn2JkOeSIQxbHyQYAcE0cpIy04qQAAAAASUVORK5CYII=" },
+			{ QTexture.QRestoreButton, "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAA3klEQVQ4Ec1RMQ7CMAxMUtj4CSPiATyADzB2QWx8gAlF4geIpTO/YEZIbAz8gxWFuyip3KRR2cDS1fad7dSJttaqkjnnvKS1LpUoU1S+FP53wBobXIFXAGNymfWtwMIdcDfGLAjGgcuGjCC0xlvHjR9AnIFNKyh1C3ENfxJ89gpbihj0DN7X8hmBBvyUh0jIFd6onkEc0wPMB02uUOGU2LRCJ3M/gCfCauQPT4iP/APSVdCiZzoHjsASaICOyT+Igm+Oe4K8hJP3iDsXyIa+AeSlTWSSxukKqT6Y/37AB6sOP8hny1/VAAAAAElFTkSuQmCC" },
+			{ QTexture.QTreeMapCurrent, "iVBORw0KGgoAAAANSUhEUgAAAA4AAAAQCAYAAAAmlE46AAAAQ0lEQVQoFWNgwA+E/wMBUIkwujImdAFi+aMa8YQUCx45dCmUKCFKIzAq36CbQpRGRkZGEbI0QjW9RdY8mgCQQwONDQApiglJmB+fmgAAAABJRU5ErkJggg==" },
+			{ QTexture.QTreeMapLast, "iVBORw0KGgoAAAANSUhEUgAAAA4AAAAQCAYAAAAmlE46AAAAPUlEQVQoFWNgwA+E/wMBUIkwujImdAFi+aMa8YQUCx45dCmUKCFKIzAq36CbwogugMbnBvI50MRGuTQLAQD/rQhHffk54gAAAABJRU5ErkJggg==" },
+			{ QTexture.QTreeMapLevel, "iVBORw0KGgoAAAANSUhEUgAAAA4AAAAQCAYAAAAmlE46AAAAJElEQVQoFWNgwA8k/wMBUIkkujImdAFi+aMa8YTUaOCM8MABAI00BE1+cZ4yAAAAAElFTkSuQmCC" },
+			{ QTexture.QTreeMapLevel4, "iVBORw0KGgoAAAANSUhEUgAAADgAAAAQCAYAAABDebxFAAAATklEQVRIDe2SMQoAMAgDpV/w/29t3QWzpnKOGiHmjJgrb1VJcpa1qc3eadaWNTjwd6AQhKB5AryoOSBpD4IyInMBBM0BSXsQlBGZC9YTfL7XEKcUdfHdAAAAAElFTkSuQmCC" },
+			{ QTexture.QTreeMapObject, "iVBORw0KGgoAAAANSUhEUgAAAA4AAAAQCAYAAAAmlE46AAABnUlEQVQoFdVSTW/aQBR83vX6K9iOkAqmQVUQyoUrUg7cg/qLkTjliDggVfTKZ9rKiT9Q2hjLLsTprMWBWL311Lcar/12Z+fN8xL9N6FUKlXxbQHOCTZmBqTAM/Dr9H6QG8+jPhgM7hqNxnW73b7wPK8mhGBxGKfbb9uX1WoVxnH8FfO8SrwaDoe3rusatu2Srovy0I+e53Zvum6v1/uw2Ww+gfhUJV4WRWEsl0uyrBp1Oh0yTUE/fJ+iICKs6a1Wq8BpTpXIuMLfsEEJgoCiKICqTsfjkegN5i8syrIMH8Sk8feBjFAFFA1KkoTDkyaYIKEByHPOy4ZWFQtd1RSmgA0FNIZIFoZgGCpXybAMKXaoKv5M0v1vprKSxFBQgcEEQwUWCTRrNpvtQNxxedpZvMa72K3X67ZpmTq8gcuY4zivh+Mhm0wm36fT6TjP822VmIdh+LBerxN4cZvNpq1pGvd9/3E0Gn1ZLBbjNE2XEMqrN0eKy5wJf91+v/8ZHbbw3+6jKJojL29O6fpvRKyVoeFZA2Qf9kAGoGX/GH8AjXiXWwSceRAAAAAASUVORK5CYII=" },
+			{ QTexture.QTrimIcon, "iVBORw0KGgoAAAANSUhEUgAAAAcAAAAQCAYAAADagWXwAAAAOUlEQVQYGWP8//8/Ay7AhEsCJD5YJOHOR3cQXALdtSgS6JKMIAFkgG4sigJ0SZBGuAJsknCTaSQJAGHZBh0Iaq7CAAAAAElFTkSuQmCC" },
+			{ QTexture.QVisibilityButton, "iVBORw0KGgoAAAANSUhEUgAAABIAAAAQCAYAAAAbBi9cAAABBklEQVQ4EdWTuw4BURCGXRqXXkmvoBXeg5dRU1MpNlHwBBoKUai1GhQKQkmDKKzv3+zIuhQk2/iTz4yZs+PMzIq6rhsJQ7EwiqjGfxQqctM2zOEEF1iCAxX4LA3bJ45twhWkEwxhAAeQbuBAGuw5z9qXKIk+mGY4GVBeuRSMwDTGUcyej5hTtxNY3SQLFVjDHmqQgA2YOjjqwquhjzwEf23iJ1dYk1rT2a4FsFMogVdI6w/njfQrvraWI26t7fCrkIQtmN5a09U00J6dwAaHrfzXw9ZhDa4Btv4zvman9R9BsvU/bYz4Y2vewBSAArRgDtrgBRbgQBmCZx++Wvr8pv4YDe1PeweSfPysEmODwwAAAABJRU5ErkJggg==" },
+			{ QTexture.QVisibilityOffButton, "iVBORw0KGgoAAAANSUhEUgAAABIAAAAQCAYAAAAbBi9cAAABdUlEQVQ4Ea3TvS8EQRjH8dvLHZGoLvQqQaKReKlEp6RA7Q9QafwDGp1EIgqRy3mJhASJSiMaCi4Roj2rOAonkmtEgvX9ze6zVrKh2Sf5zPPM7Mxkd+bOC4Igl0Xks9hEe2S+0TibVlLersCY/Bv2Rs/MnMR2tGKAfIkafJxjET1IDx12pI+sKCOPLdzhAu9QKC+hCFvncrKzzEOLfQp71kJdwpk9JB+hFTYnZ8VCYtIrdR2H0cQ58iza8QSLFQoPbg+dkb57LPHhV9RDmMAe1tCNN5zAop9C81zoRoqRcCRs66R7TEG/2BkovDC5Vi+htS7UucV12HXtIG0J82hiGmUodLsWjxRV69gZ6UCP7ePJp2iDzqAXTVSg+Zu4gS7A1seHrQHdwiq+oNCh72AdDSh2oZ+GDj7eRPWvTvRwmKzFNXxC8YAN+NDVx7dF7fZI28jGCkzqQCf06RrvwgsOor7N/fN/9MFBNuLDDAufNILRsPvTfgP0LsP1SIPKHwAAAABJRU5ErkJggg==" },
+            { QTexture.QTreeMapLine, "iVBORw0KGgoAAAANSUhEUgAAAA4AAAAQCAMAAAARSr4IAAAACVBMVEX///8AAAD///9+749PAAAAAnRSTlMAE/ItjOYAAAAWSURBVHgBY6AbYEQAEJcJDhjRZWkJABQbACw6WoebAAAAAElFTkSuQmCC" },
+        };
+		private Dictionary<QTexture, string> resourcesDark = new Dictionary<QTexture, string>()
+		{
+			{ QTexture.QCheckBoxChecked, "iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAABV0lEQVQoFWO0sLD4zwAETEyMDECEF/wDqvwHIoCABUS42wkwlKRKM3CwM4G4OMGPn/8YemY/Zdh56APQIqA1JSnSDDxczAwszIx4MUgNSC3YdSDncXDgtundhz8Mdx7+hLsCpBakB7cOqNJpS18zpFY9ZFi26R1cM4iBofHM5W/AAICouXzzO8PeY5/BHE1lDogglETROHf1G4bSjicMC9e/Zfjz5z9D9+yXYGXOVrwMhtpcKBrBoQoT0dfgYljG9I5h0bq3DM9f/WZ4/PwXAyfQTxlRojAlcBrFRhNdLoaMSIiiPUc/gRUlhwoziAiimA8WR9EIEgn1EmTQVOFg+A+MZxV5doZAN0GwQnQC0yigimmNcgy7jnxikBZnA8YZuhYInwWUgn78+MfAw82MosLNhg+FD+OA1IL0MIHSXs+cpwxfvv1l+PP3P14MUgNSC9LDSG4iBwCgfYRJ3KYMwgAAAABJRU5ErkJggg==" },
+			{ QTexture.QCheckBoxUnchecked, "iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAgElEQVQoFe2SywkAIQxE46cHO/Bu/53YgdaguPsCgpd1hb1uIBjxDSNhTEppyF3GGI7XGkNx8ZAhBIkxinNuK+y9S85ZSilicULkvVdX7k8NA8u7xeLNaf3GZFW4PpzOv3CzqW/LIRGnNVlL9ohRa02Ydw0DC6NZJXu11iNTRNQFcsdGKGm8LNQAAAAASUVORK5CYII=" },
+			{ QTexture.QDragButton, "iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAAfElEQVQ4EWM0NjZmoCZgoqZhILNGoIEsaGFoDuRroIkR4t4AKjgJU4RuoMb///8XwCSJoRkZGROA6nAaeMPBwYEYc+BqDh48CHIhHGC48MCBA3BJYhhAF4KCaNSFiMDSoHoYQpMBwgrCLLyxDIoteIwRNgtTxQgsHAa/lwH5tiOYn8m38AAAAABJRU5ErkJggg==" },
+		};
+		private Dictionary<QTexture, string> resourcesLight = new Dictionary<QTexture, string>()
+		{
+			{ QTexture.QCheckBoxChecked, "iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAABOUlEQVQoFY2Sva6CQBCFz4XVQGFjgiZQGKiJnYmFBQVPAo9l7RvQUZAgvAChpqAiGkNDpQLX2bjkkhuMW+zM7pwv85P58X2/x+swxiBJErmTp+s6PJ9PHmd0Hw4HrFYrzGazSYgCj8cDl8sFSZJQIgZN06AoykeIgrIsc+27Ognz+XwSapoGVVUNcdJSS5+besnDMMTxeESapgNMzj+wKArQEOiUZYk8z7mv6zq34hqBURThdDrhfD6jbVsEQcB1tm3DNE3BcMunKn42mw0vKY5j1HWN2+3G+3ddV0gGO8poWRaESJToOA4Wi8UACGcE0ud+v4dhGOj7Huv1GrvdTmhHdlSqiHiehyzLsFwuJ7eJ0QTv9ztUVRUct9vtdvQWD9ISw2j3rtfr1ytHWmJ4qe/dmyxLZPu75L/vGnGpeAWI1gAAAABJRU5ErkJggg==" },
+			{ QTexture.QCheckBoxUnchecked, "iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAjklEQVQoFe2STRJDERCEOwzlApzGbVzVabwboCRp9ezeT5J1ZmGU+Roz1Y+U0hPvEBEopbg9jTEGeu+zLlxjjAghwBhzKmKhtYZSCnLOfEjgvYdz7lLEotZ6svvvFKy1t6IFkGVL100t+iD/hQdDWUe/D4c2qrWui24zWWqE3tu27WPLkaVmenX33lcmfwFMazT7V5IT7wAAAABJRU5ErkJggg==" },
+			{ QTexture.QDragButton, "iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAATklEQVQ4EWM8ceIEAzUBEzUNA5k1aiDlIcqCxYj/WMTwCTEiS7Js27oVmU8xmxFLOhx1IWnBSv0wxGI/SjLAIo9XaDQv4w0eoiQHfxgCAGQPE/BDNfMZAAAAAElFTkSuQmCC" },
+		};
+
+		private Dictionary<QColor, Color> colors;
+		private Dictionary<QColor, Color> colorsDark = new Dictionary<QColor, Color>()
+		{
+			{ QColor.BackgroundDark, new Color(0.15f, 0.15f, 0.15f) },
+			{ QColor.Background , new Color(0.22f, 0.22f, 0.22f) },
+			{ QColor.Gray       , new Color(0.6f, 0.6f, 0.6f) },
+			{ QColor.GrayLight  , new Color(0.8f, 0.8f, 0.8f) },
+			{ QColor.GrayDark  , new Color(0.4f, 0.4f, 0.4f) },
+		};
+		private Dictionary<QColor, Color> colorsLight = new Dictionary<QColor, Color>()
+		{
+			{ QColor.BackgroundDark, new Color(0.88f, 0.88f, 0.88f) },
+			{ QColor.Background , new Color(0.761f, 0.761f, 0.761f) },
+			{ QColor.Gray       , new Color(0.3f, 0.3f, 0.3f) },
+			{ QColor.GrayLight  , new Color(0.1f, 0.1f, 0.1f) },
+			{ QColor.GrayDark  , new Color(0.55f, 0.55f, 0.55f) },
+		};
+
+		// CONSTRUCTOR
+		private QResources()
+		{
+			textures = new Dictionary<QTexture, Texture2D>();
+			foreach (KeyValuePair<QTexture, string> resourcePair in resourcesCommon)
+			{
+				Texture2D texture = new Texture2D(1,1, TextureFormat.ARGB32, false, false);
+				texture.hideFlags = HideFlags.HideAndDontSave;
+				texture.LoadImage(Convert.FromBase64String(resourcePair.Value));
+				textures.Add(resourcePair.Key, texture);
+			}
+			Dictionary<QTexture, string> resources = EditorGUIUtility.isProSkin ? resourcesDark : resourcesLight;
+			foreach (KeyValuePair<QTexture, string> resourcePair in resources)
+			{
+				Texture2D texture = new Texture2D(1,1, TextureFormat.ARGB32, false, false);
+				texture.hideFlags = HideFlags.HideAndDontSave;
+				texture.LoadImage(Convert.FromBase64String(resourcePair.Value));
+				textures.Add(resourcePair.Key, texture);
+			}
+			colors = EditorGUIUtility.isProSkin ? colorsDark : colorsLight;
+		} 
+
+		// PUBLIC
+		public Texture2D getTexture(QTexture textureName) 
+		{
+			return textures[textureName];
+		}
+
+		public Color getColor(QColor color)
+		{
+			return colors[color];
+		}
+	}
+}
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/pdata/QResources.cs.meta b/Assets/Plugins/QHierarchy/Editor/Scripts/pdata/QResources.cs.meta
new file mode 100644
index 0000000..2e30082
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/pdata/QResources.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 387ed2783d685b048a858216512aa0c3
+timeCreated: 1474883135
+licenseType: Store
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/pdata/QSettings.cs b/Assets/Plugins/QHierarchy/Editor/Scripts/pdata/QSettings.cs
new file mode 100644
index 0000000..c50c73a
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/pdata/QSettings.cs
@@ -0,0 +1,525 @@
+using UnityEngine;
+using UnityEditor;
+using System.Collections;
+using System.Collections.Generic;
+using qtools.qhierarchy.phierarchy;
+using qtools.qhierarchy.phelper;
+using System.Text;
+
+namespace qtools.qhierarchy.pdata
+{
+	public enum QSetting
+	{
+		TreeMapShow                                 = 0,
+        TreeMapColor                                = 77,
+        TreeMapEnhanced                             = 78,
+        TreeMapTransparentBackground                = 60,
+
+        MonoBehaviourIconShow                       = 4,
+        MonoBehaviourIconShowDuringPlayMode         = 18,
+        MonoBehaviourIconIgnoreUnityMonobehaviour   = 45,
+        MonoBehaviourIconColor                      = 82,
+
+        SeparatorShow                               = 8,
+        SeparatorShowRowShading                     = 50,
+        SeparatorColor                              = 80,
+        SeparatorEvenRowShadingColor                = 79,       
+        SeparatorOddRowShadingColor                 = 81,       
+
+		VisibilityShow                              = 1,
+        VisibilityShowDuringPlayMode                = 15,
+
+		LockShow                                    = 2,
+        LockShowDuringPlayMode                      = 16,
+        LockPreventSelectionOfLockedObjects         = 41,
+
+        StaticShow                                  = 12,
+        StaticShowDuringPlayMode                    = 25,
+
+        ErrorShow                                   = 6,
+        ErrorShowDuringPlayMode                     = 20,
+        ErrorShowIconOnParent                       = 27,
+        ErrorShowScriptIsMissing                    = 28,
+        ErrorShowReferenceIsNull                    = 29,
+        ErrorShowReferenceIsMissing                 = 58,
+        ErrorShowStringIsEmpty                      = 30,
+        ErrorShowMissingEventMethod                 = 31,
+        ErrorShowWhenTagOrLayerIsUndefined          = 32,
+        ErrorIgnoreString                           = 33,
+        ErrorShowForDisabledComponents              = 44,
+        ErrorShowForDisabledGameObjects             = 59,
+
+        RendererShow                                = 7,
+        RendererShowDuringPlayMode                  = 21,
+
+        PrefabShow                                  = 13,
+        PrefabShowBreakedPrefabsOnly                = 51,
+
+		TagAndLayerShow                             = 5,
+        TagAndLayerShowDuringPlayMode               = 19,
+        TagAndLayerSizeShowType                     = 68,
+        TagAndLayerType                             = 34,
+        TagAndLayerSizeType                         = 35,
+        TagAndLayerSizeValuePixel                   = 36,
+        TagAndLayerAligment                         = 37,
+        TagAndLayerSizeValueType                    = 46,
+        TagAndLayerSizeValuePercent                 = 47,
+        TagAndLayerLabelSize                        = 48,
+        TagAndLayerTagLabelColor                    = 66,
+        TagAndLayerLayerLabelColor                  = 67,
+        TagAndLayerLabelAlpha                       = 69,
+
+        ColorShow                                   = 9,
+        ColorShowDuringPlayMode                     = 22,
+
+        GameObjectIconShow                          = 3,
+        GameObjectIconShowDuringPlayMode            = 17,
+        GameObjectIconSize                          = 63,
+
+        TagIconShow                                 = 14,
+        TagIconShowDuringPlayMode                   = 26,
+        TagIconListFoldout                          = 84,
+        TagIconList                                 = 40,
+        TagIconSize                                 = 62,
+
+        LayerIconShow                               = 85,
+        LayerIconShowDuringPlayMode                 = 86,
+        LayerIconListFoldout                        = 87,
+        LayerIconList                               = 88,
+        LayerIconSize                               = 89,
+
+        ChildrenCountShow                           = 11,
+        ChildrenCountShowDuringPlayMode             = 24,
+        ChildrenCountLabelSize                      = 61,
+        ChildrenCountLabelColor                     = 70,
+
+        VerticesAndTrianglesShow                    = 53,
+        VerticesAndTrianglesShowDuringPlayMode      = 54,
+        VerticesAndTrianglesCalculateTotalCount     = 55,
+        VerticesAndTrianglesShowTriangles           = 56, 
+        VerticesAndTrianglesShowVertices            = 64, 
+        VerticesAndTrianglesLabelSize               = 57,
+        VerticesAndTrianglesVerticesLabelColor      = 71,
+        VerticesAndTrianglesTrianglesLabelColor     = 72,
+
+        ComponentsShow                              = 10,
+        ComponentsShowDuringPlayMode                = 23,
+        ComponentsIconSize                          = 65,
+        ComponentsIgnore                            = 90,
+
+		ComponentsOrder                             = 38,
+
+        AdditionalIdentation                        = 39,
+        AdditionalShowHiddenQHierarchyObjectList    = 42,
+        AdditionalShowModifierWarning               = 43,
+        AdditionalShowObjectListContent             = 49,
+        AdditionalHideIconsIfNotFit                 = 52,  
+        AdditionalBackgroundColor                   = 73,
+        AdditionalActiveColor                       = 74,
+        AdditionalInactiveColor                     = 75,
+        AdditionalSpecialColor                      = 76,
+	}
+	
+	public enum QHierarchyTagAndLayerType
+	{
+		Always           = 0,
+		OnlyIfNotDefault = 1
+	}
+
+    public enum QHierarchyTagAndLayerShowType
+    {
+        TagAndLayer = 0,
+        Tag         = 1,
+        Layer       = 2
+    }
+
+    public enum QHierarchyTagAndLayerAligment
+    {
+        Left   = 0,
+        Center = 1,
+        Right  = 2
+    }
+
+    public enum QHierarchyTagAndLayerSizeType
+    {
+        Pixel   = 0,
+        Percent = 1
+    }
+
+    public enum QHierarchyTagAndLayerLabelSize
+    {
+        Normal                          = 0,
+        Big                             = 1,
+        BigIfSpecifiedOnlyTagOrLayer    = 2
+    }
+
+    public enum QHierarchySize
+    {
+        Normal  = 0,
+        Big     = 1
+    }
+        
+    public enum QHierarchySizeAll
+    {
+        Small   = 0,
+        Normal  = 1,
+        Big     = 2
+    }
+
+	public enum QHierarchyComponentEnum
+	{
+        LockComponent               = 0,
+        VisibilityComponent         = 1,
+        StaticComponent             = 2,
+        ColorComponent              = 3,
+        ErrorComponent              = 4,
+        RendererComponent           = 5,
+        PrefabComponent             = 6,
+        TagAndLayerComponent        = 7,
+        GameObjectIconComponent     = 8,
+        TagIconComponent            = 9,
+        LayerIconComponent          = 10,
+        ChildrenCountComponent      = 11,
+        VerticesAndTrianglesCount   = 12,
+        SeparatorComponent          = 1000,
+        TreeMapComponent            = 1001,
+        MonoBehaviourIconComponent  = 1002,
+        ComponentsComponent         = 1003
+	}
+
+    public class QTagTexture
+    {
+        public string tag;
+        public Texture2D texture;
+        
+        public QTagTexture(string tag, Texture2D texture)
+        {
+            this.tag = tag;
+            this.texture = texture;
+        }
+
+        public static List<QTagTexture> loadTagTextureList()
+        {
+            List<QTagTexture> tagTextureList = new List<QTagTexture>();
+            string customTagIcon = QSettings.getInstance().get<string>(QSetting.TagIconList);
+            string[] customTagIconArray = customTagIcon.Split(new char[]{';'});
+            List<string> tags = new List<string>(UnityEditorInternal.InternalEditorUtility.tags);
+            for (int i = 0; i < customTagIconArray.Length - 1; i+=2)
+            {
+                string tag = customTagIconArray[i];
+                if (!tags.Contains(tag)) continue;
+                string texturePath = customTagIconArray[i+1];
+                
+                Texture2D texture = (Texture2D)AssetDatabase.LoadAssetAtPath(texturePath, typeof(Texture2D));
+                if (texture != null) 
+                { 
+                    QTagTexture tagTexture = new QTagTexture(tag, texture);
+                    tagTextureList.Add(tagTexture);
+                }  
+            }
+            return tagTextureList;
+        }
+
+        public static void saveTagTextureList(QSetting setting, List<QTagTexture> tagTextureList)
+        { 
+            string result = "";
+            for (int i = 0; i < tagTextureList.Count; i++)            
+                result += tagTextureList[i].tag + ";" + AssetDatabase.GetAssetPath(tagTextureList[i].texture.GetInstanceID()) + ";";
+            QSettings.getInstance().set(setting, result);
+        }
+    }
+
+    public class QLayerTexture
+    {
+        public string layer;
+        public Texture2D texture;
+        
+        public QLayerTexture(string layer, Texture2D texture)
+        {
+            this.layer = layer;
+            this.texture = texture;
+        }
+        
+        public static List<QLayerTexture> loadLayerTextureList()
+        {
+            List<QLayerTexture> layerTextureList = new List<QLayerTexture>();
+            string customTagIcon = QSettings.getInstance().get<string>(QSetting.LayerIconList);
+            string[] customLayerIconArray = customTagIcon.Split(new char[]{';'});
+            List<string> layers = new List<string>(UnityEditorInternal.InternalEditorUtility.layers);
+            for (int i = 0; i < customLayerIconArray.Length - 1; i+=2)
+            {
+                string layer = customLayerIconArray[i];
+                if (!layers.Contains(layer)) continue;
+                string texturePath = customLayerIconArray[i+1];
+                
+                Texture2D texture = (Texture2D)AssetDatabase.LoadAssetAtPath(texturePath, typeof(Texture2D));
+                if (texture != null) 
+                { 
+                    QLayerTexture tagTexture = new QLayerTexture(layer, texture);
+                    layerTextureList.Add(tagTexture);
+                }  
+            }
+            return layerTextureList;
+        }
+        
+        public static void saveLayerTextureList(QSetting setting, List<QLayerTexture> layerTextureList)
+        { 
+            string result = "";
+            for (int i = 0; i < layerTextureList.Count; i++)            
+                result += layerTextureList[i].layer + ";" + AssetDatabase.GetAssetPath(layerTextureList[i].texture.GetInstanceID()) + ";";
+            QSettings.getInstance().set(setting, result);
+        }
+    }
+
+    public delegate void QSettingChangedHandler();
+
+	public class QSettings 
+	{
+        // CONST
+		private const string PREFS_PREFIX = "QTools.QHierarchy_";
+        private const string PREFS_DARK = "Dark_";
+        private const string PREFS_LIGHT = "Light_";
+        public const string DEFAULT_ORDER = "0;1;2;3;4;5;6;7;8;9;10;11;12";
+        public const int DEFAULT_ORDER_COUNT = 13;
+        private const string SETTINGS_FILE_NAME = "QSettingsObjectAsset";
+
+        // PRIVATE
+        private QSettingsObject settingsObject;
+        private Dictionary<int, object> defaultSettings = new Dictionary<int, object>();
+        private HashSet<int> skinDependedSettings = new HashSet<int>();
+        private Dictionary<int, QSettingChangedHandler> settingChangedHandlerList = new Dictionary<int, QSettingChangedHandler>();
+
+        // SINGLETON
+        private static QSettings instance;
+        public static QSettings getInstance()
+        {
+            if (instance == null) instance = new QSettings();
+            return instance;
+        }
+
+        // CONSTRUCTOR
+		private QSettings()
+		{ 
+            string[] paths = AssetDatabase.FindAssets(SETTINGS_FILE_NAME); 
+            for (int i = 0; i < paths.Length; i++)
+            {
+                settingsObject = (QSettingsObject)AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(paths[i]), typeof(QSettingsObject));
+                if (settingsObject != null) break;
+            }
+            if (settingsObject == null) 
+            {
+                settingsObject = ScriptableObject.CreateInstance<QSettingsObject>();
+                string path = AssetDatabase.GetAssetPath(MonoScript.FromScriptableObject(settingsObject));
+                path = path.Substring(0, path.LastIndexOf("/"));
+                AssetDatabase.CreateAsset(settingsObject, path + "/" + SETTINGS_FILE_NAME + ".asset");
+                AssetDatabase.SaveAssets();
+            }  
+
+            initSetting(QSetting.TreeMapShow                                , true);
+            initSetting(QSetting.TreeMapColor                               , "39FFFFFF", "905D5D5D");
+            initSetting(QSetting.TreeMapEnhanced                            , true);
+            initSetting(QSetting.TreeMapTransparentBackground               , true);
+
+            initSetting(QSetting.MonoBehaviourIconShow                      , true);
+            initSetting(QSetting.MonoBehaviourIconShowDuringPlayMode        , true);
+            initSetting(QSetting.MonoBehaviourIconIgnoreUnityMonobehaviour  , true);
+            initSetting(QSetting.MonoBehaviourIconColor                     , "A01B6DBB");
+
+            initSetting(QSetting.SeparatorShow                              , true);
+            initSetting(QSetting.SeparatorShowRowShading                    , true);
+            initSetting(QSetting.SeparatorColor                             , "FF303030", "48666666");
+            initSetting(QSetting.SeparatorEvenRowShadingColor               , "13000000", "08000000");
+            initSetting(QSetting.SeparatorOddRowShadingColor                , "00000000", "00FFFFFF");
+
+            initSetting(QSetting.VisibilityShow                             , true);
+            initSetting(QSetting.VisibilityShowDuringPlayMode               , true);
+
+            initSetting(QSetting.LockShow                                   , true);
+            initSetting(QSetting.LockShowDuringPlayMode                     , false);
+            initSetting(QSetting.LockPreventSelectionOfLockedObjects        , false);
+
+            initSetting(QSetting.StaticShow                                 , true); 
+            initSetting(QSetting.StaticShowDuringPlayMode                   , false);
+
+            initSetting(QSetting.ErrorShow                                  , true);
+            initSetting(QSetting.ErrorShowDuringPlayMode                    , false);
+            initSetting(QSetting.ErrorShowIconOnParent                      , false);
+            initSetting(QSetting.ErrorShowScriptIsMissing                   , true);
+            initSetting(QSetting.ErrorShowReferenceIsNull                   , false);
+            initSetting(QSetting.ErrorShowReferenceIsMissing                , true);
+            initSetting(QSetting.ErrorShowStringIsEmpty                     , false);
+            initSetting(QSetting.ErrorShowMissingEventMethod                , true);
+            initSetting(QSetting.ErrorShowWhenTagOrLayerIsUndefined         , true);
+            initSetting(QSetting.ErrorIgnoreString                          , "");
+            initSetting(QSetting.ErrorShowForDisabledComponents             , true);
+            initSetting(QSetting.ErrorShowForDisabledGameObjects            , true);
+
+            initSetting(QSetting.RendererShow                               , false);
+            initSetting(QSetting.RendererShowDuringPlayMode                 , false);
+
+            initSetting(QSetting.PrefabShow                                 , false);
+            initSetting(QSetting.PrefabShowBreakedPrefabsOnly               , true);
+
+            initSetting(QSetting.TagAndLayerShow                            , true);
+            initSetting(QSetting.TagAndLayerShowDuringPlayMode              , true);
+            initSetting(QSetting.TagAndLayerSizeShowType                    , (int)QHierarchyTagAndLayerShowType.TagAndLayer);
+            initSetting(QSetting.TagAndLayerType                            , (int)QHierarchyTagAndLayerType.OnlyIfNotDefault);
+            initSetting(QSetting.TagAndLayerAligment                        , (int)QHierarchyTagAndLayerAligment.Left);
+            initSetting(QSetting.TagAndLayerSizeValueType                   , (int)QHierarchyTagAndLayerSizeType.Pixel);
+            initSetting(QSetting.TagAndLayerSizeValuePercent                , 0.25f);
+            initSetting(QSetting.TagAndLayerSizeValuePixel                  , 75);
+            initSetting(QSetting.TagAndLayerLabelSize                       , (int)QHierarchyTagAndLayerLabelSize.Normal);
+            initSetting(QSetting.TagAndLayerTagLabelColor                   , "FFCCCCCC", "FF333333");
+            initSetting(QSetting.TagAndLayerLayerLabelColor                 , "FFCCCCCC", "FF333333");
+            initSetting(QSetting.TagAndLayerLabelAlpha                      , 0.35f);
+
+            initSetting(QSetting.ColorShow                                  , true);
+            initSetting(QSetting.ColorShowDuringPlayMode                    , true);
+
+            initSetting(QSetting.GameObjectIconShow                         , false);
+            initSetting(QSetting.GameObjectIconShowDuringPlayMode           , true);
+            initSetting(QSetting.GameObjectIconSize                         , (int)QHierarchySizeAll.Small);
+
+            initSetting(QSetting.TagIconShow                                , false);
+            initSetting(QSetting.TagIconShowDuringPlayMode                  , true);
+            initSetting(QSetting.TagIconListFoldout                         , false);
+            initSetting(QSetting.TagIconList                                , "");
+            initSetting(QSetting.TagIconSize                                , (int)QHierarchySizeAll.Small);
+
+            initSetting(QSetting.LayerIconShow                              , false);
+            initSetting(QSetting.LayerIconShowDuringPlayMode                , true);
+            initSetting(QSetting.LayerIconListFoldout                       , false);
+            initSetting(QSetting.LayerIconList                              , "");
+            initSetting(QSetting.LayerIconSize                              , (int)QHierarchySizeAll.Small);
+
+            initSetting(QSetting.ChildrenCountShow                          , false);     
+            initSetting(QSetting.ChildrenCountShowDuringPlayMode            , true);
+            initSetting(QSetting.ChildrenCountLabelSize                     , (int)QHierarchySize.Normal);
+            initSetting(QSetting.ChildrenCountLabelColor                    , "FFCCCCCC", "FF333333");
+
+            initSetting(QSetting.VerticesAndTrianglesShow                   , false);
+            initSetting(QSetting.VerticesAndTrianglesShowDuringPlayMode     , false);
+            initSetting(QSetting.VerticesAndTrianglesCalculateTotalCount    , false);
+            initSetting(QSetting.VerticesAndTrianglesShowTriangles          , false);
+            initSetting(QSetting.VerticesAndTrianglesShowVertices           , true);
+            initSetting(QSetting.VerticesAndTrianglesLabelSize              , (int)QHierarchySize.Normal);
+            initSetting(QSetting.VerticesAndTrianglesVerticesLabelColor     , "FFCCCCCC", "FF333333");
+            initSetting(QSetting.VerticesAndTrianglesTrianglesLabelColor    , "FFCCCCCC", "FF333333");
+
+            initSetting(QSetting.ComponentsShow                             , false);
+            initSetting(QSetting.ComponentsShowDuringPlayMode               , false);
+            initSetting(QSetting.ComponentsIconSize                         , (int)QHierarchySizeAll.Small);
+            initSetting(QSetting.ComponentsIgnore                           , "");
+
+            initSetting(QSetting.ComponentsOrder                            , DEFAULT_ORDER);
+
+            initSetting(QSetting.AdditionalShowObjectListContent            , false);
+            initSetting(QSetting.AdditionalShowHiddenQHierarchyObjectList   , true);
+            initSetting(QSetting.AdditionalHideIconsIfNotFit                , true);
+            initSetting(QSetting.AdditionalIdentation                       , 0);
+            initSetting(QSetting.AdditionalShowModifierWarning              , true);
+
+            #if UNITY_2019_1_OR_NEWER
+            initSetting(QSetting.AdditionalBackgroundColor                  , "00383838", "00CFCFCF");
+            #else
+            initSetting(QSetting.AdditionalBackgroundColor                  , "00383838", "00C2C2C2");
+            #endif
+            initSetting(QSetting.AdditionalActiveColor                      , "FFFFFF80", "CF363636");
+            initSetting(QSetting.AdditionalInactiveColor                    , "FF4F4F4F", "1E000000");
+            initSetting(QSetting.AdditionalSpecialColor                     , "FF2CA8CA", "FF1D78D5");
+		} 
+
+        // DESTRUCTOR
+        public void OnDestroy()
+        {
+            skinDependedSettings = null;
+            defaultSettings = null;
+            settingsObject = null;
+            settingChangedHandlerList = null;
+            instance = null;
+        }
+
+        // PUBLIC
+        public T get<T>(QSetting setting)
+        {
+            return (T)settingsObject.get<T>(getSettingName(setting));
+        }
+
+        public Color getColor(QSetting setting)
+        {
+            string stringColor = (string)settingsObject.get<string>(getSettingName(setting));
+            return QColorUtils.fromString(stringColor);
+        }
+
+        public void setColor(QSetting setting, Color color)
+        {
+            string stringColor = QColorUtils.toString(color);
+            set(setting, stringColor);
+        }
+
+        public void set<T>(QSetting setting, T value, bool invokeChanger = true)
+        {
+            int settingId = (int)setting;
+            settingsObject.set(getSettingName(setting), value);
+
+            if (invokeChanger && settingChangedHandlerList.ContainsKey(settingId) && settingChangedHandlerList[settingId] != null)            
+                settingChangedHandlerList[settingId].Invoke();
+            
+            EditorApplication.RepaintHierarchyWindow();
+        }
+
+        public void addEventListener(QSetting setting, QSettingChangedHandler handler)
+        {
+            int settingId = (int)setting;
+            
+            if (!settingChangedHandlerList.ContainsKey(settingId))          
+                settingChangedHandlerList.Add(settingId, null);
+            
+            if (settingChangedHandlerList[settingId] == null)           
+                settingChangedHandlerList[settingId] = handler;
+            else            
+                settingChangedHandlerList[settingId] += handler;
+        }
+        
+        public void removeEventListener(QSetting setting, QSettingChangedHandler handler)
+        {
+            int settingId = (int)setting;
+            
+            if (settingChangedHandlerList.ContainsKey(settingId) && settingChangedHandlerList[settingId] != null)       
+                settingChangedHandlerList[settingId] -= handler;
+        }
+        
+        public void restore(QSetting setting)
+        {
+            set(setting, defaultSettings[(int)setting]);
+        }
+
+        // PRIVATE
+        private void initSetting(QSetting setting, object defaultValueDark, object defaultValueLight)
+        {
+            skinDependedSettings.Add((int)setting);
+            initSetting(setting, EditorGUIUtility.isProSkin ? defaultValueDark : defaultValueLight);
+        }
+        
+        private void initSetting(QSetting setting, object defaultValue)
+        {
+            string settingName = getSettingName(setting);
+            defaultSettings.Add((int)setting, defaultValue);
+            object value = settingsObject.get(settingName, defaultValue);
+            if (value == null || value.GetType() != defaultValue.GetType())
+            {
+                settingsObject.set(settingName, defaultValue);
+            }        
+        }
+
+        private string getSettingName(QSetting setting)
+        {
+            int settingId = (int)setting;
+            string settingName = PREFS_PREFIX;
+            if (skinDependedSettings.Contains(settingId))            
+                settingName += EditorGUIUtility.isProSkin ? PREFS_DARK : PREFS_LIGHT;            
+            settingName += setting.ToString("G");
+            return settingName.ToString();
+        }
+	}
+}
\ No newline at end of file
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/pdata/QSettings.cs.meta b/Assets/Plugins/QHierarchy/Editor/Scripts/pdata/QSettings.cs.meta
new file mode 100644
index 0000000..64a96ca
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/pdata/QSettings.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 22eaacdc264c5a84b9f790ff6b99896a
+timeCreated: 1477924880
+licenseType: Store
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/pdata/QSettingsObject.cs b/Assets/Plugins/QHierarchy/Editor/Scripts/pdata/QSettingsObject.cs
new file mode 100644
index 0000000..592faf4
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/pdata/QSettingsObject.cs
@@ -0,0 +1,135 @@
+using UnityEngine;
+using UnityEditor;
+using System;
+using System.Collections.Generic;
+
+namespace qtools.qhierarchy.pdata
+{
+    [System.Serializable]
+    class QSettingsObject: ScriptableObject
+    {
+        [SerializeField] private List<string> settingStringNames  = new List<string>();
+        [SerializeField] private List<string> settingStringValues = new List<string>();
+
+        [SerializeField] private List<string> settingFloatNames   = new List<string>();
+        [SerializeField] private List<float>  settingFloatValues  = new List<float>();
+
+        [SerializeField] private List<string> settingIntNames     = new List<string>();
+        [SerializeField] private List<int>    settingIntValues    = new List<int>();
+
+        [SerializeField] private List<string> settingBoolNames   = new List<string>();
+        [SerializeField] private List<bool>   settingBoolValues  = new List<bool>();
+
+        public void clear()
+        {
+            settingStringNames.Clear();
+            settingStringValues.Clear();
+            settingFloatNames.Clear();
+            settingFloatValues.Clear();
+            settingIntNames.Clear();
+            settingIntValues.Clear();
+            settingBoolNames.Clear();
+            settingBoolValues.Clear();
+        }
+
+        public void set(string settingName, object value)
+        {
+            if (value is bool)
+            {
+                settingBoolValues[settingBoolNames.IndexOf(settingName)] = (bool)value;
+            }
+            else if (value is string)
+            {
+                settingStringValues[settingStringNames.IndexOf(settingName)] = (string)value;
+            }
+            else if (value is float)
+            {
+                settingFloatValues[settingFloatNames.IndexOf(settingName)] = (float)value;
+            }
+            else if (value is int)
+            {
+                settingIntValues[settingIntNames.IndexOf(settingName)] = (int)value;
+            }
+            EditorUtility.SetDirty(this);
+        }
+
+        public object get(string settingName, object defaultValue)
+        {
+            if (defaultValue is bool)
+            {
+                int id = settingBoolNames.IndexOf(settingName);
+                if (id == -1) 
+                {
+                    settingBoolNames.Add(settingName);
+                    settingBoolValues.Add((bool)defaultValue);
+                    return defaultValue;
+                }
+                else return settingBoolValues[id];
+            }
+            else if (defaultValue is string)
+            {
+                int id = settingStringNames.IndexOf(settingName);
+                if (id == -1) 
+                {
+                    settingStringNames.Add(settingName);
+                    settingStringValues.Add((string)defaultValue);
+                    return defaultValue;
+                }
+                else return settingStringValues[id];
+            }
+            else if (defaultValue is float)
+            {
+                int id = settingFloatNames.IndexOf(settingName);
+                if (id == -1) 
+                {
+                    settingFloatNames.Add(settingName);
+                    settingFloatValues.Add((float)defaultValue);
+                    return defaultValue;
+                }
+                else return settingFloatValues[id];
+            }
+            else if (defaultValue is int)
+            {
+                int id = settingIntNames.IndexOf(settingName);
+                if (id == -1) 
+                {
+                    settingIntNames.Add(settingName);
+                    settingIntValues.Add((int)defaultValue);
+                    return defaultValue;
+                }
+                else return settingIntValues[id];
+            }
+            return null;
+        }
+        
+        public object get<T>(string settingName)
+        {
+            if (typeof(T) == typeof(bool))
+            {
+                int id = settingBoolNames.IndexOf(settingName);
+                if (id == -1) return null;
+                else return settingBoolValues[id];
+            }
+            else if (typeof(T) == typeof(string))
+            {
+                int id = settingStringNames.IndexOf(settingName);
+                if (id == -1) return null;
+                else return settingStringValues[id];
+            }
+            else if (typeof(T) == typeof(float))
+            {
+                int id = settingFloatNames.IndexOf(settingName);
+                if (id == -1) return null;
+                else return settingFloatValues[id];
+            }
+            else if (typeof(T) == typeof(int))
+            {
+                int id = settingIntNames.IndexOf(settingName);
+                if (id == -1) return null;
+                else return settingIntValues[id];
+            }
+            return null;
+        }
+    }
+}
+
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/pdata/QSettingsObject.cs.meta b/Assets/Plugins/QHierarchy/Editor/Scripts/pdata/QSettingsObject.cs.meta
new file mode 100644
index 0000000..f4905fa
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/pdata/QSettingsObject.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: b9eba1ecab4c43c41869985e270bbe09
+timeCreated: 1478592157
+licenseType: Store
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/pdata/QSettingsObjectAsset.asset b/Assets/Plugins/QHierarchy/Editor/Scripts/pdata/QSettingsObjectAsset.asset
new file mode 100644
index 0000000..e1c1316
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/pdata/QSettingsObjectAsset.asset
@@ -0,0 +1,158 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!114 &11400000
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 0}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: b9eba1ecab4c43c41869985e270bbe09, type: 3}
+  m_Name: QSettingsObjectAsset
+  m_EditorClassIdentifier: 
+  settingStringNames:
+  - QTools.QHierarchy_Light_TreeMapColor
+  - QTools.QHierarchy_MonoBehaviourIconColor
+  - QTools.QHierarchy_Light_SeparatorColor
+  - QTools.QHierarchy_Light_SeparatorEvenRowShadingColor
+  - QTools.QHierarchy_Light_SeparatorOddRowShadingColor
+  - QTools.QHierarchy_ErrorIgnoreString
+  - QTools.QHierarchy_Light_TagAndLayerTagLabelColor
+  - QTools.QHierarchy_Light_TagAndLayerLayerLabelColor
+  - QTools.QHierarchy_TagIconList
+  - QTools.QHierarchy_LayerIconList
+  - QTools.QHierarchy_Light_ChildrenCountLabelColor
+  - QTools.QHierarchy_Light_VerticesAndTrianglesVerticesLabelColor
+  - QTools.QHierarchy_Light_VerticesAndTrianglesTrianglesLabelColor
+  - QTools.QHierarchy_ComponentsIgnore
+  - QTools.QHierarchy_ComponentsOrder
+  - QTools.QHierarchy_Light_AdditionalBackgroundColor
+  - QTools.QHierarchy_Light_AdditionalActiveColor
+  - QTools.QHierarchy_Light_AdditionalInactiveColor
+  - QTools.QHierarchy_Light_AdditionalSpecialColor
+  - QTools.QHierarchy_Dark_TreeMapColor
+  - QTools.QHierarchy_Dark_SeparatorColor
+  - QTools.QHierarchy_Dark_SeparatorEvenRowShadingColor
+  - QTools.QHierarchy_Dark_SeparatorOddRowShadingColor
+  - QTools.QHierarchy_Dark_TagAndLayerTagLabelColor
+  - QTools.QHierarchy_Dark_TagAndLayerLayerLabelColor
+  - QTools.QHierarchy_Dark_ChildrenCountLabelColor
+  - QTools.QHierarchy_Dark_VerticesAndTrianglesVerticesLabelColor
+  - QTools.QHierarchy_Dark_VerticesAndTrianglesTrianglesLabelColor
+  - QTools.QHierarchy_Dark_AdditionalBackgroundColor
+  - QTools.QHierarchy_Dark_AdditionalActiveColor
+  - QTools.QHierarchy_Dark_AdditionalInactiveColor
+  - QTools.QHierarchy_Dark_AdditionalSpecialColor
+  settingStringValues:
+  - 905D5D5D
+  - A01B6DBB
+  - 48666666
+  - 08000000
+  - 00FFFFFF
+  - 
+  - FF333333
+  - FF333333
+  - 
+  - 
+  - FF333333
+  - FF333333
+  - FF333333
+  - 
+  - 0;1;2;3;4;5;6;7;8;9;10;11;12
+  - 00C2C2C2
+  - CF363636
+  - 1E000000
+  - FF1D78D5
+  - 39FFFFFF
+  - FF303030
+  - 13000000
+  - 00000000
+  - FFCCCCCC
+  - FFCCCCCC
+  - FFCCCCCC
+  - FFCCCCCC
+  - FFCCCCCC
+  - 00383838
+  - FFFFFF80
+  - FF4F4F4F
+  - FF2CA8CA
+  settingFloatNames:
+  - QTools.QHierarchy_TagAndLayerSizeValuePercent
+  - QTools.QHierarchy_TagAndLayerLabelAlpha
+  settingFloatValues:
+  - 0.25
+  - 0.35
+  settingIntNames:
+  - QTools.QHierarchy_TagAndLayerSizeShowType
+  - QTools.QHierarchy_TagAndLayerType
+  - QTools.QHierarchy_TagAndLayerAligment
+  - QTools.QHierarchy_TagAndLayerSizeValueType
+  - QTools.QHierarchy_TagAndLayerSizeValuePixel
+  - QTools.QHierarchy_TagAndLayerLabelSize
+  - QTools.QHierarchy_GameObjectIconSize
+  - QTools.QHierarchy_TagIconSize
+  - QTools.QHierarchy_LayerIconSize
+  - QTools.QHierarchy_ChildrenCountLabelSize
+  - QTools.QHierarchy_VerticesAndTrianglesLabelSize
+  - QTools.QHierarchy_ComponentsIconSize
+  - QTools.QHierarchy_AdditionalIdentation
+  settingIntValues: 000000000100000000000000000000003d0000000000000000000000000000000000000000000000000000000000000000000000
+  settingBoolNames:
+  - QTools.QHierarchy_TreeMapShow
+  - QTools.QHierarchy_TreeMapEnhanced
+  - QTools.QHierarchy_TreeMapTransparentBackground
+  - QTools.QHierarchy_MonoBehaviourIconShow
+  - QTools.QHierarchy_MonoBehaviourIconShowDuringPlayMode
+  - QTools.QHierarchy_MonoBehaviourIconIgnoreUnityMonobehaviour
+  - QTools.QHierarchy_SeparatorShow
+  - QTools.QHierarchy_SeparatorShowRowShading
+  - QTools.QHierarchy_VisibilityShow
+  - QTools.QHierarchy_VisibilityShowDuringPlayMode
+  - QTools.QHierarchy_LockShow
+  - QTools.QHierarchy_LockShowDuringPlayMode
+  - QTools.QHierarchy_LockPreventSelectionOfLockedObjects
+  - QTools.QHierarchy_StaticShow
+  - QTools.QHierarchy_StaticShowDuringPlayMode
+  - QTools.QHierarchy_ErrorShow
+  - QTools.QHierarchy_ErrorShowDuringPlayMode
+  - QTools.QHierarchy_ErrorShowIconOnParent
+  - QTools.QHierarchy_ErrorShowScriptIsMissing
+  - QTools.QHierarchy_ErrorShowReferenceIsNull
+  - QTools.QHierarchy_ErrorShowReferenceIsMissing
+  - QTools.QHierarchy_ErrorShowStringIsEmpty
+  - QTools.QHierarchy_ErrorShowMissingEventMethod
+  - QTools.QHierarchy_ErrorShowWhenTagOrLayerIsUndefined
+  - QTools.QHierarchy_ErrorShowForDisabledComponents
+  - QTools.QHierarchy_ErrorShowForDisabledGameObjects
+  - QTools.QHierarchy_RendererShow
+  - QTools.QHierarchy_RendererShowDuringPlayMode
+  - QTools.QHierarchy_PrefabShow
+  - QTools.QHierarchy_PrefabShowBreakedPrefabsOnly
+  - QTools.QHierarchy_TagAndLayerShow
+  - QTools.QHierarchy_TagAndLayerShowDuringPlayMode
+  - QTools.QHierarchy_ColorShow
+  - QTools.QHierarchy_ColorShowDuringPlayMode
+  - QTools.QHierarchy_GameObjectIconShow
+  - QTools.QHierarchy_GameObjectIconShowDuringPlayMode
+  - QTools.QHierarchy_TagIconShow
+  - QTools.QHierarchy_TagIconShowDuringPlayMode
+  - QTools.QHierarchy_TagIconListFoldout
+  - QTools.QHierarchy_LayerIconShow
+  - QTools.QHierarchy_LayerIconShowDuringPlayMode
+  - QTools.QHierarchy_LayerIconListFoldout
+  - QTools.QHierarchy_ChildrenCountShow
+  - QTools.QHierarchy_ChildrenCountShowDuringPlayMode
+  - QTools.QHierarchy_VerticesAndTrianglesShow
+  - QTools.QHierarchy_VerticesAndTrianglesShowDuringPlayMode
+  - QTools.QHierarchy_VerticesAndTrianglesCalculateTotalCount
+  - QTools.QHierarchy_VerticesAndTrianglesShowTriangles
+  - QTools.QHierarchy_VerticesAndTrianglesShowVertices
+  - QTools.QHierarchy_ComponentsShow
+  - QTools.QHierarchy_ComponentsShowDuringPlayMode
+  - QTools.QHierarchy_AdditionalShowObjectListContent
+  - QTools.QHierarchy_AdditionalShowHiddenQHierarchyObjectList
+  - QTools.QHierarchy_AdditionalHideIconsIfNotFit
+  - QTools.QHierarchy_AdditionalShowModifierWarning
+  settingBoolValues: 01010101010101010101010000010001000101010101010101010000000001010001000100010000010000010000010101010000010101
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/pdata/QSettingsObjectAsset.asset.meta b/Assets/Plugins/QHierarchy/Editor/Scripts/pdata/QSettingsObjectAsset.asset.meta
new file mode 100644
index 0000000..f5b200a
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/pdata/QSettingsObjectAsset.asset.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 3425b17243bd5c64393e28f9bd687fcb
+NativeFormatImporter:
+  externalObjects: {}
+  mainObjectFileID: 11400000
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/phelper.meta b/Assets/Plugins/QHierarchy/Editor/Scripts/phelper.meta
new file mode 100644
index 0000000..c7feac8
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/phelper.meta
@@ -0,0 +1,10 @@
+fileFormatVersion: 2
+guid: 4874c05321df8604d93643d0c4918324
+folderAsset: yes
+timeCreated: 1515657177
+licenseType: Store
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/phelper/QColorPickerWindow.cs b/Assets/Plugins/QHierarchy/Editor/Scripts/phelper/QColorPickerWindow.cs
new file mode 100644
index 0000000..9bbbcc8
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/phelper/QColorPickerWindow.cs
@@ -0,0 +1,68 @@
+using UnityEngine;
+using UnityEditor;
+using System.Collections;
+using System.Collections.Generic;
+using System.Text;
+using qtools.qhierarchy.pdata;
+
+namespace qtools.qhierarchy.phelper
+{
+    public delegate void QColorSelectedHandler(GameObject[] gameObjects, Color color);
+    public delegate void QColorRemovedHandler(GameObject[] gameObjects);
+
+    public class QColorPickerWindow: PopupWindowContent 
+    {
+        // PRIVATE
+        private GameObject[] gameObjects;
+        private QColorSelectedHandler colorSelectedHandler;
+        private QColorRemovedHandler colorRemovedHandler;
+        private Texture2D colorPaletteTexture;
+        private Rect paletteRect;
+
+        // CONSTRUCTOR
+        public QColorPickerWindow(GameObject[] gameObjects, QColorSelectedHandler colorSelectedHandler, QColorRemovedHandler colorRemovedHandler)
+        {
+            this.gameObjects = gameObjects;
+            this.colorSelectedHandler = colorSelectedHandler;
+            this.colorRemovedHandler = colorRemovedHandler;
+
+            colorPaletteTexture = QResources.getInstance().getTexture(QTexture.QColorPalette);
+            paletteRect = new Rect(0, 0, colorPaletteTexture.width, colorPaletteTexture.height);
+        }
+
+        // DESTRUCTOR
+        public override void OnClose()
+        {
+            gameObjects = null;
+            colorSelectedHandler = null;
+            colorRemovedHandler = null; 
+        }
+
+        // GUI
+        public override Vector2 GetWindowSize()
+        {
+            return new Vector2(paletteRect.width, paletteRect.height);
+        }
+
+        public override void OnGUI(Rect rect)
+        {
+            GUI.DrawTexture(paletteRect, colorPaletteTexture);
+
+            Vector2 mousePosition = Event.current.mousePosition;
+            if (Event.current.isMouse && Event.current.button == 0 && Event.current.type == EventType.MouseUp && paletteRect.Contains(mousePosition))
+            {
+                Event.current.Use();
+                if (mousePosition.x < 15 && mousePosition.y < 15)
+                {
+                    colorRemovedHandler(gameObjects);
+                }
+                else
+                {
+                    colorSelectedHandler(gameObjects, colorPaletteTexture.GetPixel((int)mousePosition.x, colorPaletteTexture.height - (int)mousePosition.y));
+                }
+                this.editorWindow.Close();
+            }
+        }
+    }
+}
+
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/phelper/QColorPickerWindow.cs.meta b/Assets/Plugins/QHierarchy/Editor/Scripts/phelper/QColorPickerWindow.cs.meta
new file mode 100644
index 0000000..10186ed
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/phelper/QColorPickerWindow.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: a7b2618f38024e943bb04bab606dc06e
+timeCreated: 1475051433
+licenseType: Store
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/phelper/QColorUtils.cs b/Assets/Plugins/QHierarchy/Editor/Scripts/phelper/QColorUtils.cs
new file mode 100644
index 0000000..d8f982e
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/phelper/QColorUtils.cs
@@ -0,0 +1,63 @@
+using System;
+using UnityEngine;
+using UnityEditor;
+
+namespace qtools.qhierarchy.phelper
+{
+    public class QColorUtils
+    {
+        private static Color defaultColor = new Color(1.0f, 1.0f, 1.0f, 1.0f);
+
+        public static void setDefaultColor(Color defaultColor)
+        {
+            QColorUtils.defaultColor = defaultColor;
+        }
+
+        public static void setColor(Color newColor)
+        {
+            GUI.color = newColor;
+        }
+
+        public static void setColor(Color newColor, float multiColor, float multiAlpha)
+        {
+            newColor.r *= multiColor;
+            newColor.g *= multiColor;
+            newColor.b *= multiColor;
+            newColor.a *= multiAlpha;
+            GUI.color = newColor;
+        }
+
+        public static void clearColor()
+        {
+            GUI.color = defaultColor;
+        }
+
+        public static Color fromString(string color)
+        {
+            return fromInt(Convert.ToUInt32(color,16));
+        }
+        
+        public static string toString(Color color)
+        {
+            uint intColor = toInt(color);
+            return intColor.ToString("X8");
+        }
+
+        public static Color fromInt(uint color)
+        {
+            return new Color(((color >> 16) & 0xFF) / 255.0f,
+                             ((color >>  8) & 0xFF) / 255.0f,
+                             ((color >>  0) & 0xFF) / 255.0f,
+                             ((color >> 24) & 0xFF) / 255.0f);
+        }
+        
+        public static uint toInt(Color color)
+        {
+            return  (uint)((byte)(color.r * 255) << 16) + 
+                    (uint)((byte)(color.g * 255) << 8) + 
+                    (uint)((byte)(color.b * 255) << 0) + 
+                    (uint)((byte)(color.a * 255) << 24);
+        }
+    }
+}
+
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/phelper/QColorUtils.cs.meta b/Assets/Plugins/QHierarchy/Editor/Scripts/phelper/QColorUtils.cs.meta
new file mode 100644
index 0000000..fd05217
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/phelper/QColorUtils.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 70e4d942740a91e45b468c65bbeb78aa
+timeCreated: 1478071980
+licenseType: Store
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/phelper/QComponentsOrderList.cs b/Assets/Plugins/QHierarchy/Editor/Scripts/phelper/QComponentsOrderList.cs
new file mode 100644
index 0000000..845f214
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/phelper/QComponentsOrderList.cs
@@ -0,0 +1,138 @@
+using UnityEditor;
+using UnityEngine;
+using System;
+using qtools.qhierarchy.pdata;
+using System.Text;
+
+namespace qtools.qhierarchy.phelper
+{
+    public class QComponentsOrderList
+    {
+        // PRIVATE
+        private EditorWindow window;
+        private Texture2D dragButton;
+        private bool dragAndDrop = false;
+        private float dragOffset;
+        private int originalDragIndex;
+        private Color backgroundColor;
+
+        // CONSTRUCTOR
+        public QComponentsOrderList (EditorWindow window)
+        {            
+            this.window = window;
+            dragButton = QResources.getInstance().getTexture(QTexture.QDragButton);
+            backgroundColor = QResources.getInstance().getColor(QColor.BackgroundDark);
+        }
+        
+        // PUBLIC
+        public void draw(Rect rect, string[] componentIds)
+        {
+            Event currentEvent = Event.current;
+
+            int currentMouseIndex = Mathf.Clamp(Mathf.RoundToInt((currentEvent.mousePosition.y - dragOffset - rect.y) / 18), 0, componentIds.Length - 1);
+
+            if (dragAndDrop && currentEvent.type == EventType.MouseUp)      
+            {
+                dragAndDrop = false;
+                window.Repaint();
+
+                if (currentMouseIndex != originalDragIndex)
+                {
+                    string newIconOrder = "";
+                    for (int j = 0; j < componentIds.Length; j++)
+                    {
+                        if (j == currentMouseIndex) 
+                        {
+                            if (j > originalDragIndex)
+                            {
+                                newIconOrder += componentIds[j] + ";";
+                                newIconOrder += componentIds[originalDragIndex] + ";";
+                            }
+                            else
+                            {
+                                newIconOrder += componentIds[originalDragIndex] + ";";
+                                newIconOrder += componentIds[j] + ";";
+                            }
+                        }
+                        else if (j != originalDragIndex) 
+                        {
+                            newIconOrder += componentIds[j] + ";";
+                        }
+                    }
+                    newIconOrder = newIconOrder.TrimEnd(';');
+                    QSettings.getInstance().set(QSetting.ComponentsOrder, newIconOrder);
+                    componentIds = newIconOrder.Split(';');
+                }
+            }
+            else if (dragAndDrop && currentEvent.type == EventType.MouseDrag)
+            {
+                window.Repaint();
+            }
+
+            for (int i = 0; i < componentIds.Length; i++)
+            {
+                QHierarchyComponentEnum type = (QHierarchyComponentEnum)int.Parse(componentIds[i]);
+                
+                Rect curRect = new Rect(rect.x, rect.y + 18 * i, rect.width, 16);
+                
+                if (!dragAndDrop && currentEvent.type == EventType.MouseDown && curRect.Contains(currentEvent.mousePosition))
+                {
+                    dragAndDrop = true;
+                    originalDragIndex = i;
+                    dragOffset = currentEvent.mousePosition.y - curRect.y;
+                    Event.current.Use();
+                }
+
+                if (dragAndDrop)
+                {
+                    if (originalDragIndex != i)
+                    {
+                             if (i < originalDragIndex && currentMouseIndex <= i) curRect.y += 18;
+                        else if (i > originalDragIndex && currentMouseIndex >= i) curRect.y -= 18;
+
+                        drawComponentLabel(curRect, type);                
+                    }
+                }
+                else
+                {
+                    drawComponentLabel(curRect, type);                    
+                }
+            }
+
+            if (dragAndDrop)
+            {
+                float curY = currentEvent.mousePosition.y - dragOffset;
+                curY = Mathf.Clamp(curY, rect.y, rect.y + rect.height - 16);
+                drawComponentLabel(new Rect(rect.x, curY, rect.width, rect.height), (QHierarchyComponentEnum)int.Parse(componentIds[originalDragIndex]), true);
+            }
+        }
+        
+        // PRIVATE
+        private void drawComponentLabel(Rect rect, QHierarchyComponentEnum type, bool withBackground = false)
+        {
+            if (withBackground)
+            {
+                EditorGUI.DrawRect(new Rect(rect.x, rect.y - 2, rect.width, 20), backgroundColor);
+            }
+            GUI.DrawTexture(new Rect(rect.x, rect.y - 2, 20, 20), dragButton);
+            Rect labelRect = new Rect(rect.x + 31, rect.y, rect.width - 20, 16);
+            labelRect.y -= (EditorGUIUtility.singleLineHeight - labelRect.height) * 0.5f;
+            EditorGUI.LabelField(labelRect, getTextWithSpaces(type.ToString()));
+        }
+        
+        private string getTextWithSpaces(string text)
+        {
+            StringBuilder newText = new StringBuilder(text.Length * 2);
+            newText.Append(text[0]);
+            for (int i = 1; i < text.Length; i++)
+            {
+                if (char.IsUpper(text[i]) && text[i - 1] != ' ')                
+                    newText.Append(' ');                
+                newText.Append(text[i]);                
+            }
+            newText.Replace(" Component", "");
+            return newText.ToString();
+        }
+    }
+}
+
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/phelper/QComponentsOrderList.cs.meta b/Assets/Plugins/QHierarchy/Editor/Scripts/phelper/QComponentsOrderList.cs.meta
new file mode 100644
index 0000000..5af728c
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/phelper/QComponentsOrderList.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: bd122316ceb5c1a469ec2d5e9ea9377f
+timeCreated: 1478011862
+licenseType: Store
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/phelper/QObjectListInspector.cs b/Assets/Plugins/QHierarchy/Editor/Scripts/phelper/QObjectListInspector.cs
new file mode 100644
index 0000000..991c9ec
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/phelper/QObjectListInspector.cs
@@ -0,0 +1,35 @@
+using UnityEngine;
+using UnityEditor;
+using qtools.qhierarchy.pdata;
+
+namespace qtools.qhierarchy.phelper
+{
+    [CustomEditor(typeof(QObjectList))]
+    public class QObjectListInspector : Editor
+    {
+    	public override void OnInspectorGUI()
+    	{
+    		EditorGUILayout.HelpBox("\nThis is an auto created GameObject that managed by QHierarchy.\n\n" + 
+                                    "It stores references to some GameObjects in the current scene. This object will not be included in the application build.\n\n" + 
+                                    "You can safely remove it, but lock / unlock / visible / etc. states will be reset. Delete this object if you want to remove the QHierarchy.\n\n" +
+                                    "This object can be hidden if you uncheck \"Show QHierarchy GameObject\" in the settings of the QHierarchy.\n"
+                                    , MessageType.Info, true);
+
+            if (QSettings.getInstance().get<bool>(QSetting.AdditionalShowObjectListContent))
+            {
+                if (GUI.Button(EditorGUILayout.GetControlRect(GUILayout.ExpandWidth(true), GUILayout.Height(20)), "Hide content"))
+                {
+                    QSettings.getInstance().set(QSetting.AdditionalShowObjectListContent, false);
+                }
+                base.OnInspectorGUI();
+            }
+            else
+            {
+                if (GUI.Button(EditorGUILayout.GetControlRect(GUILayout.ExpandWidth(true), GUILayout.Height(20)), "Show content"))
+                {
+                    QSettings.getInstance().set(QSetting.AdditionalShowObjectListContent, true);
+                }
+            }
+    	}
+    }
+}
\ No newline at end of file
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/phelper/QObjectListInspector.cs.meta b/Assets/Plugins/QHierarchy/Editor/Scripts/phelper/QObjectListInspector.cs.meta
new file mode 100644
index 0000000..f195703
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/phelper/QObjectListInspector.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 1182108d9515cea4aa965206552f3c33
+timeCreated: 1475228494
+licenseType: Store
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/phelper/QObjectListManager.cs b/Assets/Plugins/QHierarchy/Editor/Scripts/phelper/QObjectListManager.cs
new file mode 100644
index 0000000..a8100d2
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/phelper/QObjectListManager.cs
@@ -0,0 +1,268 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEditor;
+using qtools.qhierarchy.pdata;
+#if UNITY_5_3_OR_NEWER
+using UnityEngine.SceneManagement;
+using UnityEditor.SceneManagement;
+#endif
+
+namespace qtools.qhierarchy.phelper
+{
+    public class QObjectListManager
+    {
+        // CONST
+        private const string QObjectListName = "QHierarchyObjectList";
+
+        // SINGLETON
+        private static QObjectListManager instance;
+        public static QObjectListManager getInstance()
+        {
+            if (instance == null) instance = new QObjectListManager();
+            return instance;
+        }
+
+        // PRIVATE
+        private bool showObjectList;
+        private bool preventSelectionOfLockedObjects;
+        private bool preventSelectionOfLockedObjectsDuringPlayMode;
+        private GameObject lastSelectionGameObject = null;
+        private int lastSelectionCount = 0;
+
+        // CONSTRUCTOR
+        private QObjectListManager()
+        {
+            QSettings.getInstance().addEventListener(QSetting.AdditionalShowHiddenQHierarchyObjectList , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.LockPreventSelectionOfLockedObjects, settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.LockShow              , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.LockShowDuringPlayMode, settingsChanged);
+            settingsChanged();
+        }
+
+        private void settingsChanged()
+        {
+            showObjectList = QSettings.getInstance().get<bool>(QSetting.AdditionalShowHiddenQHierarchyObjectList);
+            preventSelectionOfLockedObjects = QSettings.getInstance().get<bool>(QSetting.LockShow) && QSettings.getInstance().get<bool>(QSetting.LockPreventSelectionOfLockedObjects);
+            preventSelectionOfLockedObjectsDuringPlayMode = preventSelectionOfLockedObjects && QSettings.getInstance().get<bool>(QSetting.LockShowDuringPlayMode);
+        }
+
+        private bool isSelectionChanged()
+        {
+            if (lastSelectionGameObject != Selection.activeGameObject || lastSelectionCount  != Selection.gameObjects.Length)
+            {
+                lastSelectionGameObject = Selection.activeGameObject;
+                lastSelectionCount = Selection.gameObjects.Length;
+                return true;
+            }
+            return false;
+        }
+
+        public void validate()
+        {
+            QObjectList.instances.RemoveAll(item => item == null);
+            foreach (QObjectList objectList in QObjectList.instances)
+                objectList.checkIntegrity();
+            #if UNITY_5_3_OR_NEWER
+            objectListDictionary.Clear();
+            foreach (QObjectList objectList in QObjectList.instances)            
+                objectListDictionary.Add(objectList.gameObject.scene, objectList);
+            #endif
+        }
+
+        #if UNITY_5_3_OR_NEWER
+        private Dictionary<Scene, QObjectList> objectListDictionary = new Dictionary<Scene, QObjectList>();
+        private Scene lastActiveScene;
+        private int lastSceneCount = 0;
+
+        public void update()
+        {
+            try
+            {     
+                List<QObjectList> objectListList = QObjectList.instances;
+                int objectListCount = objectListList.Count;
+                if (objectListCount > 0) 
+                {
+                    for (int i = objectListCount - 1; i >= 0; i--)
+                    {
+                        QObjectList objectList = objectListList[i];
+                        Scene objectListScene = objectList.gameObject.scene;
+						
+						if (objectListDictionary.ContainsKey(objectListScene) && objectListDictionary[objectListScene] == null)
+                            objectListDictionary.Remove(objectListScene);
+							
+                        if (objectListDictionary.ContainsKey(objectListScene))
+                        {
+                            if (objectListDictionary[objectListScene] != objectList)
+                            {
+                                objectListDictionary[objectListScene].merge(objectList);
+                                GameObject.DestroyImmediate(objectList.gameObject);
+                            }
+                        }
+                        else
+                        {
+                            objectListDictionary.Add(objectListScene, objectList);
+                        }
+                    }
+
+                    foreach (KeyValuePair<Scene, QObjectList> objectListKeyValue in objectListDictionary)
+                    {
+                        QObjectList objectList = objectListKeyValue.Value;
+                        setupObjectList(objectList);
+                        if (( showObjectList && ((objectList.gameObject.hideFlags & HideFlags.HideInHierarchy)  > 0)) ||
+                            (!showObjectList && ((objectList.gameObject.hideFlags & HideFlags.HideInHierarchy) == 0)))
+                        {
+                            objectList.gameObject.hideFlags ^= HideFlags.HideInHierarchy;      
+                            EditorApplication.DirtyHierarchyWindowSorting();
+                        }
+                    }
+                    
+                    if ((!Application.isPlaying && preventSelectionOfLockedObjects) || 
+                        ((Application.isPlaying && preventSelectionOfLockedObjectsDuringPlayMode)) && 
+                        isSelectionChanged())
+                    {
+                        GameObject[] selections = Selection.gameObjects;
+                        List<GameObject> actual = new List<GameObject>(selections.Length);
+                        bool found = false;
+                        for (int i = selections.Length - 1; i >= 0; i--)
+                        {
+                            GameObject gameObject = selections[i];
+                            
+                            if (objectListDictionary.ContainsKey(gameObject.scene))
+                            {
+                                bool isLock = objectListDictionary[gameObject.scene].lockedObjects.Contains(selections[i]);
+                                if (!isLock) actual.Add(selections[i]);
+                                else found = true;
+                            }
+                        }
+                        if (found) Selection.objects = actual.ToArray();
+                    }   
+
+                    lastActiveScene = EditorSceneManager.GetActiveScene();
+                    lastSceneCount = SceneManager.loadedSceneCount;
+                }
+            }
+            catch 
+            {
+            }
+        }
+
+        public QObjectList getObjectList(GameObject gameObject, bool createIfNotExist = true)
+        { 
+            QObjectList objectList = null;
+            objectListDictionary.TryGetValue(gameObject.scene, out objectList);
+            
+            if (objectList == null && createIfNotExist)
+            {         
+                objectList = createObjectList(gameObject);
+                if (gameObject.scene != objectList.gameObject.scene) EditorSceneManager.MoveGameObjectToScene(objectList.gameObject, gameObject.scene);
+                objectListDictionary.Add(gameObject.scene, objectList);
+            }
+
+            return objectList;
+        }
+
+        public bool isSceneChanged()
+        {
+            if (lastActiveScene != EditorSceneManager.GetActiveScene() || lastSceneCount != SceneManager.loadedSceneCount)
+                return true;
+            else 
+                return false;
+        }
+
+        #else
+
+        public void update()
+        {
+            try
+            {  
+                List<QObjectList> objectListList = QObjectList.instances;
+                int objectListCount = objectListList.Count;
+                if (objectListCount > 0) 
+                {
+                    if (objectListCount > 1)
+                    {
+                        for (int i = objectListCount - 1; i > 0; i--)
+                        {
+                            objectListList[0].merge(objectListList[i]);
+                            GameObject.DestroyImmediate(objectListList[i].gameObject);
+                        }
+                    }
+
+                    QObjectList objectList = QObjectList.instances[0];
+                    setupObjectList(objectList);
+
+                    if (( showObjectList && ((objectList.gameObject.hideFlags & HideFlags.HideInHierarchy)  > 0)) ||
+                        (!showObjectList && ((objectList.gameObject.hideFlags & HideFlags.HideInHierarchy) == 0)))
+                    {
+                        objectList.gameObject.hideFlags ^= HideFlags.HideInHierarchy; 
+                        EditorApplication.DirtyHierarchyWindowSorting();
+                    }
+
+                    if ((!Application.isPlaying && preventSelectionOfLockedObjects) || 
+                        ((Application.isPlaying && preventSelectionOfLockedObjectsDuringPlayMode))
+                        && isSelectionChanged())
+                    {
+                        GameObject[] selections = Selection.gameObjects;
+                        List<GameObject> actual = new List<GameObject>(selections.Length);
+                        bool found = false;
+                        for (int i = selections.Length - 1; i >= 0; i--)
+                        {
+                            GameObject gameObject = selections[i];
+                            
+                            bool isLock = objectList.lockedObjects.Contains(gameObject);                        
+                            if (!isLock) actual.Add(selections[i]);
+                            else found = true;
+                        }
+                        if (found) Selection.objects = actual.ToArray();
+                    }   
+                }
+            }
+            catch 
+            {
+            }
+        }
+
+        public QObjectList getObjectList(GameObject gameObject, bool createIfNotExists = false)
+        { 
+            List<QObjectList> objectListList = QObjectList.instances;
+            int objectListCount = objectListList.Count;
+            if (objectListCount != 1)
+            {
+                if (objectListCount == 0) 
+                {
+                    if (createIfNotExists)
+                    {
+                        createObjectList(gameObject);
+                    }
+                    else
+                    {
+                        return null;
+                    }
+                }
+            }
+                
+            return QObjectList.instances[0];
+        }
+
+        #endif
+
+        private QObjectList createObjectList(GameObject gameObject)
+        {
+            GameObject gameObjectList = new GameObject();
+            gameObjectList.name = QObjectListName;
+            QObjectList objectList = gameObjectList.AddComponent<QObjectList>();
+            setupObjectList(objectList);
+            return objectList;
+        }
+
+        private void setupObjectList(QObjectList objectList)
+        {
+            if (objectList.tag == "EditorOnly") objectList.tag = "Untagged";
+            MonoScript monoScript = MonoScript.FromMonoBehaviour(objectList);
+            if (MonoImporter.GetExecutionOrder(monoScript) != -10000)                    
+                MonoImporter.SetExecutionOrder(monoScript, -10000);
+        }
+    }
+}
+
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/phelper/QObjectListManager.cs.meta b/Assets/Plugins/QHierarchy/Editor/Scripts/phelper/QObjectListManager.cs.meta
new file mode 100644
index 0000000..8ce38c9
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/phelper/QObjectListManager.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: dac6048cde5fd4d4399d16cc2ffba265
+timeCreated: 1475228494
+licenseType: Store
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/phierarchy.meta b/Assets/Plugins/QHierarchy/Editor/Scripts/phierarchy.meta
new file mode 100644
index 0000000..9246f02
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/phierarchy.meta
@@ -0,0 +1,10 @@
+fileFormatVersion: 2
+guid: cc4f43cb5bd4bf546a9edf40a361f0f5
+folderAsset: yes
+timeCreated: 1515657177
+licenseType: Store
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/phierarchy/QHierarchy.cs b/Assets/Plugins/QHierarchy/Editor/Scripts/phierarchy/QHierarchy.cs
new file mode 100644
index 0000000..9e6491a
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/phierarchy/QHierarchy.cs
@@ -0,0 +1,184 @@
+using UnityEngine;
+using UnityEditor;
+using System;
+using System.Collections.Generic;
+using qtools.qhierarchy.pcomponent;
+using qtools.qhierarchy.pcomponent.pbase;
+using qtools.qhierarchy.pdata;
+using qtools.qhierarchy.phelper;
+using System.Reflection;
+
+namespace qtools.qhierarchy.phierarchy
+{
+    public class QHierarchy
+    {
+        // PRIVATE
+        private HashSet<int> errorHandled = new HashSet<int>();      
+        private Dictionary<int, QBaseComponent> componentDictionary;          
+        private List<QBaseComponent> preComponents;
+        private List<QBaseComponent> orderedComponents;
+        private bool hideIconsIfThereIsNoFreeSpace;
+        private int indentation;
+        private Texture2D trimIcon;
+        private Color backgroundColor;
+        private Color inactiveColor;
+
+        // CONSTRUCTOR
+        public QHierarchy ()
+        {           
+            componentDictionary = new Dictionary<int, QBaseComponent>();
+            componentDictionary.Add((int)QHierarchyComponentEnum.LockComponent             , new QLockComponent());
+            componentDictionary.Add((int)QHierarchyComponentEnum.VisibilityComponent       , new QVisibilityComponent());
+            componentDictionary.Add((int)QHierarchyComponentEnum.StaticComponent           , new QStaticComponent());
+            componentDictionary.Add((int)QHierarchyComponentEnum.RendererComponent         , new QRendererComponent());
+            componentDictionary.Add((int)QHierarchyComponentEnum.TagAndLayerComponent      , new QTagLayerComponent());
+            componentDictionary.Add((int)QHierarchyComponentEnum.GameObjectIconComponent   , new QGameObjectIconComponent());
+            componentDictionary.Add((int)QHierarchyComponentEnum.ErrorComponent            , new QErrorComponent());
+            componentDictionary.Add((int)QHierarchyComponentEnum.TagIconComponent          , new QTagIconComponent());
+            componentDictionary.Add((int)QHierarchyComponentEnum.LayerIconComponent        , new QLayerIconComponent());
+            componentDictionary.Add((int)QHierarchyComponentEnum.ColorComponent            , new QColorComponent());
+            componentDictionary.Add((int)QHierarchyComponentEnum.ComponentsComponent       , new QComponentsComponent());
+            componentDictionary.Add((int)QHierarchyComponentEnum.ChildrenCountComponent    , new QChildrenCountComponent());
+            componentDictionary.Add((int)QHierarchyComponentEnum.PrefabComponent           , new QPrefabComponent());
+            componentDictionary.Add((int)QHierarchyComponentEnum.VerticesAndTrianglesCount , new QVerticesAndTrianglesCountComponent());
+
+            preComponents = new List<QBaseComponent>();
+            preComponents.Add(new QMonoBehaviorIconComponent());
+            preComponents.Add(new QTreeMapComponent());
+            preComponents.Add(new QSeparatorComponent());
+
+            orderedComponents = new List<QBaseComponent>();
+
+            trimIcon = QResources.getInstance().getTexture(QTexture.QTrimIcon);
+
+            QSettings.getInstance().addEventListener(QSetting.AdditionalIdentation             , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.ComponentsOrder                  , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.AdditionalHideIconsIfNotFit      , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.AdditionalBackgroundColor        , settingsChanged);
+            QSettings.getInstance().addEventListener(QSetting.AdditionalInactiveColor          , settingsChanged);
+            settingsChanged();
+        }
+         
+        // PRIVATE
+        private void settingsChanged()
+        {
+            string componentOrder = QSettings.getInstance().get<string>(QSetting.ComponentsOrder);
+            string[] componentIds = componentOrder.Split(';');
+            if (componentIds.Length != QSettings.DEFAULT_ORDER_COUNT) 
+            {
+                QSettings.getInstance().set(QSetting.ComponentsOrder, QSettings.DEFAULT_ORDER, false);
+                componentIds = QSettings.DEFAULT_ORDER.Split(';');
+            }
+
+            orderedComponents.Clear(); 
+            for (int i = 0; i < componentIds.Length; i++)                
+                orderedComponents.Add(componentDictionary[int.Parse(componentIds[i])]);
+            orderedComponents.Add(componentDictionary[(int)QHierarchyComponentEnum.ComponentsComponent]);
+
+            indentation                     = QSettings.getInstance().get<int>(QSetting.AdditionalIdentation);
+            hideIconsIfThereIsNoFreeSpace   = QSettings.getInstance().get<bool>(QSetting.AdditionalHideIconsIfNotFit);
+            backgroundColor                 = QSettings.getInstance().getColor(QSetting.AdditionalBackgroundColor);
+            inactiveColor                   = QSettings.getInstance().getColor(QSetting.AdditionalInactiveColor);
+        } 
+
+        public void hierarchyWindowItemOnGUIHandler(int instanceId, Rect selectionRect)
+        {
+            try
+            {
+                QColorUtils.setDefaultColor(GUI.color);
+
+                GameObject gameObject = (GameObject)EditorUtility.InstanceIDToObject(instanceId);
+                if (gameObject == null) return;
+
+                Rect curRect = new Rect(selectionRect);
+                curRect.width = 16;
+                curRect.x += selectionRect.width - indentation;
+
+                float gameObjectNameWidth = hideIconsIfThereIsNoFreeSpace ? GUI.skin.label.CalcSize(new GUIContent(gameObject.name)).x : 0;
+
+                QObjectList objectList = QObjectListManager.getInstance().getObjectList(gameObject, false);
+
+                drawComponents(orderedComponents, selectionRect, ref curRect, gameObject, objectList, true, hideIconsIfThereIsNoFreeSpace ? selectionRect.x + gameObjectNameWidth + 7 : 0);    
+
+                errorHandled.Remove(instanceId);
+            }
+            catch (Exception exception)
+            {
+                if (errorHandled.Add(instanceId))
+                {
+                    Debug.LogError(exception.ToString());
+                }
+            }
+        }
+
+        private void drawComponents(List<QBaseComponent> components, Rect selectionRect, ref Rect rect, GameObject gameObject, QObjectList objectList, bool drawBackground = false, float minX = 50)
+        {
+            if (Event.current.type == EventType.Repaint)
+            {
+                int toComponent = components.Count;
+                QLayoutStatus layoutStatus = QLayoutStatus.Success;
+                for (int i = 0, n = toComponent; i < n; i++)
+                {
+                    QBaseComponent component = components[i];
+                    if (component.isEnabled())
+                    {
+                        layoutStatus = component.layout(gameObject, objectList, selectionRect, ref rect, rect.x - minX);
+                        if (layoutStatus != QLayoutStatus.Success)
+                        {
+                            toComponent = layoutStatus == QLayoutStatus.Failed ? i : i + 1;
+                            rect.x -= 7;
+
+                            break;
+                        }
+                    }
+                    else
+                    {
+                        component.disabledHandler(gameObject, objectList);
+                    }
+                } 
+
+                if (drawBackground)
+                {
+                    if (backgroundColor.a != 0)
+                    {
+                        rect.width = selectionRect.x + selectionRect.width - rect.x /*- indentation*/;
+                        EditorGUI.DrawRect(rect, backgroundColor);
+                    }
+                    drawComponents(preComponents    , selectionRect, ref rect, gameObject, objectList);
+                }
+
+                for (int i = 0, n = toComponent; i < n; i++)
+                {
+                    QBaseComponent component = components[i];
+                    if (component.isEnabled())
+                    {
+                        component.draw(gameObject, objectList, selectionRect);
+                    }
+                }
+
+                if (layoutStatus != QLayoutStatus.Success)
+                {
+                    rect.width = 7;
+                    QColorUtils.setColor(inactiveColor);
+                    GUI.DrawTexture(rect, trimIcon);
+                    QColorUtils.clearColor();
+                }
+            }
+            else if (Event.current.isMouse)
+            {
+                for (int i = 0, n = components.Count; i < n; i++)
+                {
+                    QBaseComponent component = components[i];
+                    if (component.isEnabled())
+                    {
+                        if (component.layout(gameObject, objectList, selectionRect, ref rect, rect.x - minX) != QLayoutStatus.Failed)
+                        {
+                            component.eventHandler(gameObject, objectList, Event.current);
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/phierarchy/QHierarchy.cs.meta b/Assets/Plugins/QHierarchy/Editor/Scripts/phierarchy/QHierarchy.cs.meta
new file mode 100644
index 0000000..5568924
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/phierarchy/QHierarchy.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 4b7e0353599820d438074ea45a106853
+timeCreated: 1474888198
+licenseType: Store
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/phierarchy/QHierarchySettingsWindow.cs b/Assets/Plugins/QHierarchy/Editor/Scripts/phierarchy/QHierarchySettingsWindow.cs
new file mode 100644
index 0000000..d0c0ffd
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/phierarchy/QHierarchySettingsWindow.cs
@@ -0,0 +1,827 @@
+using UnityEngine;
+using UnityEditor;
+using System.Collections;
+using System.Collections.Generic;
+using System.Text;
+using qtools.qhierarchy.pdata;
+using System;
+using qtools.qhierarchy.phelper;
+using qtools.qhierarchy.pcomponent;
+
+namespace qtools.qhierarchy.phierarchy
+{
+	public class QHierarchySettingsWindow : EditorWindow 
+	{	
+        // STATIC
+		[MenuItem ("Tools/QHierarchy/Settings")]	
+		public static void ShowWindow () 
+		{ 
+			EditorWindow window = EditorWindow.GetWindow(typeof(QHierarchySettingsWindow));           
+            window.minSize = new Vector2(350, 50);
+
+            #if UNITY_4_6 || UNITY_4_7 || UNITY_5_0
+                window.title = "QHierarchy";
+            #else
+                window.titleContent = new GUIContent("QHierarchy");
+            #endif
+		}
+
+        // PRIVATE
+        private bool inited = false;
+        private Rect lastRect;
+        private bool isProSkin;
+        private int indentLevel;
+        private Texture2D checkBoxChecked;
+        private Texture2D checkBoxUnchecked;
+        private Texture2D restoreButtonTexture;
+        private Vector2 scrollPosition = new Vector2();
+        private Color separatorColor;
+        private Color yellowColor;
+        private float totalWidth;
+        private QComponentsOrderList componentsOrderList;
+
+        // INIT
+        private void init() 
+        { 
+            inited            = true;
+            isProSkin         = EditorGUIUtility.isProSkin;
+            separatorColor    = isProSkin ? new Color(0.18f, 0.18f, 0.18f) : new Color(0.59f, 0.59f, 0.59f);
+            yellowColor       = isProSkin ? new Color(1.00f, 0.90f, 0.40f) : new Color(0.31f, 0.31f, 0.31f);
+            checkBoxChecked   = QResources.getInstance().getTexture(QTexture.QCheckBoxChecked);
+            checkBoxUnchecked = QResources.getInstance().getTexture(QTexture.QCheckBoxUnchecked);
+            restoreButtonTexture = QResources.getInstance().getTexture(QTexture.QRestoreButton);
+            componentsOrderList = new QComponentsOrderList(this);
+        } 
+         
+        // GUI
+		void OnGUI()
+		{
+            if (!inited || isProSkin != EditorGUIUtility.isProSkin)  
+                init();
+
+            indentLevel = 8;
+            scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
+            {
+                Rect targetRect = EditorGUILayout.GetControlRect(GUILayout.Height(0));
+                if (Event.current.type == EventType.Repaint) totalWidth = targetRect.width + 8;
+
+                this.lastRect = new Rect(0, 1, 0, 0);
+
+                // COMPONENTS
+                drawSection("COMPONENTS SETTINGS");
+                float sectionStartY = lastRect.y + lastRect.height;
+
+                drawTreeMapComponentSettings();
+                drawSeparator();
+                drawMonoBehaviourIconComponentSettings();
+                drawSeparator();
+                drawSeparatorComponentSettings();
+                drawSeparator();
+                drawVisibilityComponentSettings();
+                drawSeparator();
+                drawLockComponentSettings();
+                drawSeparator();
+                drawStaticComponentSettings();
+                drawSeparator();
+                drawErrorComponentSettings();
+                drawSeparator();
+                drawRendererComponentSettings();
+                drawSeparator();
+                drawPrefabComponentSettings();
+                drawSeparator();
+                drawTagLayerComponentSettings();
+                drawSeparator();
+                drawColorComponentSettings();
+                drawSeparator();
+                drawGameObjectIconComponentSettings();
+                drawSeparator();
+                drawTagIconComponentSettings();
+                drawSeparator();
+                drawLayerIconComponentSettings();
+                drawSeparator();
+                drawChildrenCountComponentSettings();
+                drawSeparator();
+                drawVerticesAndTrianglesCountComponentSettings();
+                drawSeparator();
+                drawComponentsComponentSettings();
+                drawLeftLine(sectionStartY, lastRect.y + lastRect.height, separatorColor);
+
+                // ORDER
+                drawSection("ORDER OF COMPONENTS");         
+                sectionStartY = lastRect.y + lastRect.height;
+                drawSpace(8);  
+                drawOrderSettings();
+                drawSpace(6);      
+                drawLeftLine(sectionStartY, lastRect.y + lastRect.height, separatorColor);
+
+                // ADDITIONAL
+                drawSection("ADDITIONAL SETTINGS");             
+                sectionStartY = lastRect.y + lastRect.height;
+                drawSpace(3);  
+                drawAdditionalSettings();
+                drawLeftLine(sectionStartY, lastRect.y + lastRect.height + 4, separatorColor);
+
+                indentLevel -= 1;
+            }
+
+            EditorGUILayout.EndScrollView();
+        }
+
+        // COMPONENTS
+        private void drawTreeMapComponentSettings() 
+        {
+            if (drawComponentCheckBox("Hierarchy Tree", QSetting.TreeMapShow))
+            {
+                Rect rect = getControlRect(0, 0);
+                if (drawRestore())
+                {
+                    QSettings.getInstance().restore(QSetting.TreeMapColor);
+                    QSettings.getInstance().restore(QSetting.TreeMapEnhanced);
+                    QSettings.getInstance().restore(QSetting.TreeMapTransparentBackground);
+                }
+                drawBackground(rect.x, rect.y, rect.width, 18 * 3 + 5);
+                drawSpace(4);
+                drawColorPicker("Tree color", QSetting.TreeMapColor);
+                drawCheckBoxRight("Transparent background", QSetting.TreeMapTransparentBackground);
+                drawCheckBoxRight("Enhanced (\"Transform Sort\" only)", QSetting.TreeMapEnhanced);
+                drawSpace(1);
+            }
+        }
+        
+        private void drawMonoBehaviourIconComponentSettings() 
+        {
+            if (drawComponentCheckBox("MonoBehaviour Icon", QSetting.MonoBehaviourIconShow))
+            {
+                Rect rect = getControlRect(0, 0);
+                if (drawRestore())
+                {
+                    QSettings.getInstance().restore(QSetting.MonoBehaviourIconShowDuringPlayMode);
+                    QSettings.getInstance().restore(QSetting.MonoBehaviourIconColor);
+                    QSettings.getInstance().restore(QSetting.MonoBehaviourIconIgnoreUnityMonobehaviour);
+                }
+                drawBackground(rect.x, rect.y, rect.width, 18 * 3 + 5);
+                drawSpace(4);
+                drawCheckBoxRight("Show component during play mode", QSetting.MonoBehaviourIconShowDuringPlayMode);
+                drawColorPicker("Icon color", QSetting.MonoBehaviourIconColor);
+                drawCheckBoxRight("Ignore Unity MonoBehaviours", QSetting.MonoBehaviourIconIgnoreUnityMonobehaviour);
+                drawSpace(1);
+            }
+        }
+
+        private void drawSeparatorComponentSettings() 
+        {
+            if (drawComponentCheckBox("Separator", QSetting.SeparatorShow))
+            {
+                Rect rect = getControlRect(0, 0);
+                if (drawRestore())
+                {
+                    QSettings.getInstance().restore(QSetting.SeparatorColor);
+                    QSettings.getInstance().restore(QSetting.SeparatorShowRowShading);
+                    QSettings.getInstance().restore(QSetting.SeparatorOddRowShadingColor);
+                    QSettings.getInstance().restore(QSetting.SeparatorEvenRowShadingColor);
+                }
+                bool rowShading = QSettings.getInstance().get<bool>(QSetting.SeparatorShowRowShading);
+
+                drawBackground(rect.x, rect.y, rect.width, 18 * (rowShading ? 4 : 2) + 5);
+                drawSpace(4);
+                drawColorPicker("Separator Color", QSetting.SeparatorColor);
+                drawCheckBoxRight("Row shading", QSetting.SeparatorShowRowShading);
+                if (rowShading)                
+                {
+                    drawColorPicker("Even row shading color", QSetting.SeparatorEvenRowShadingColor);
+                    drawColorPicker("Odd row shading color" , QSetting.SeparatorOddRowShadingColor);
+                }
+                drawSpace(1);
+            }
+        }
+
+        private void drawVisibilityComponentSettings() 
+        {
+            if (drawComponentCheckBox("Visibility", QSetting.VisibilityShow))
+            {
+                Rect rect = getControlRect(0, 0);
+                if (drawRestore())
+                {
+                    QSettings.getInstance().restore(QSetting.VisibilityShowDuringPlayMode);
+                }
+                drawBackground(rect.x, rect.y, rect.width, 18 + 5);
+                drawSpace(4);
+                drawCheckBoxRight("Show component during play mode", QSetting.VisibilityShowDuringPlayMode);
+                drawSpace(1);
+            }
+        }
+
+        private void drawLockComponentSettings() 
+        {
+            if (drawComponentCheckBox("Lock", QSetting.LockShow))
+            {   
+                Rect rect = getControlRect(0, 0);
+                if (drawRestore())
+                {
+                    QSettings.getInstance().restore(QSetting.LockShowDuringPlayMode);
+                    QSettings.getInstance().restore(QSetting.LockPreventSelectionOfLockedObjects);
+                }
+                drawBackground(rect.x, rect.y, rect.width, 18 * 2 + 5);
+                drawSpace(4);
+                drawCheckBoxRight("Show component during play mode", QSetting.LockShowDuringPlayMode);
+                drawCheckBoxRight("Prevent selection of locked objects", QSetting.LockPreventSelectionOfLockedObjects);
+                drawSpace(1);
+            }
+        }
+
+        private void drawStaticComponentSettings() 
+        {
+            if (drawComponentCheckBox("Static", QSetting.StaticShow))
+            {
+                Rect rect = getControlRect(0, 0);
+                if (drawRestore())
+                {
+                    QSettings.getInstance().restore(QSetting.StaticShowDuringPlayMode);
+                }
+                drawBackground(rect.x, rect.y, rect.width, 18 + 5);
+                drawSpace(4);
+                drawCheckBoxRight("Show component during play mode", QSetting.StaticShowDuringPlayMode);
+                drawSpace(1);
+            }        
+        }
+
+        private void drawErrorComponentSettings() 
+        {
+            if (drawComponentCheckBox("Error", QSetting.ErrorShow))
+            {
+                Rect rect = getControlRect(0, 0);
+                if (drawRestore())
+                {
+                    QSettings.getInstance().restore(QSetting.ErrorShowDuringPlayMode);
+                    QSettings.getInstance().restore(QSetting.ErrorShowIconOnParent);
+                    QSettings.getInstance().restore(QSetting.ErrorShowForDisabledComponents);
+                    QSettings.getInstance().restore(QSetting.ErrorShowForDisabledGameObjects);
+                    QSettings.getInstance().restore(QSetting.ErrorShowScriptIsMissing);
+                    QSettings.getInstance().restore(QSetting.ErrorShowReferenceIsMissing);
+                    QSettings.getInstance().restore(QSetting.ErrorShowReferenceIsNull);
+                    QSettings.getInstance().restore(QSetting.ErrorShowStringIsEmpty);
+                    QSettings.getInstance().restore(QSetting.ErrorShowMissingEventMethod);
+                    QSettings.getInstance().restore(QSetting.ErrorShowWhenTagOrLayerIsUndefined);
+                    QSettings.getInstance().restore(QSetting.ErrorIgnoreString);
+                }
+                drawBackground(rect.x, rect.y, rect.width, 18 * 12 + 5);
+                drawSpace(4);
+                drawCheckBoxRight("Show component during play mode", QSetting.ErrorShowDuringPlayMode);
+                drawCheckBoxRight("Show error icon up of hierarchy (very slow)", QSetting.ErrorShowIconOnParent);
+                drawCheckBoxRight("Show error icon for disabled components", QSetting.ErrorShowForDisabledComponents);
+                drawCheckBoxRight("Show error icon for disabled GameObjects", QSetting.ErrorShowForDisabledGameObjects);
+                drawLabel("Show error icon for the following:");
+                indentLevel += 16;
+                drawCheckBoxRight("- script is missing", QSetting.ErrorShowScriptIsMissing);
+                drawCheckBoxRight("- reference is missing", QSetting.ErrorShowReferenceIsMissing);
+                drawCheckBoxRight("- reference is null", QSetting.ErrorShowReferenceIsNull);
+                drawCheckBoxRight("- string is empty", QSetting.ErrorShowStringIsEmpty);
+                drawCheckBoxRight("- callback of event is missing (very slow)", QSetting.ErrorShowMissingEventMethod);
+                drawCheckBoxRight("- tag or layer is undefined", QSetting.ErrorShowWhenTagOrLayerIsUndefined);
+                indentLevel -= 16;
+                drawTextField("Ignore packages/classes", QSetting.ErrorIgnoreString);
+                drawSpace(1);
+            }
+        }
+
+        private void drawRendererComponentSettings() 
+        {
+            if (drawComponentCheckBox("Renderer", QSetting.RendererShow))
+            {
+                Rect rect = getControlRect(0, 0);
+                if (drawRestore())
+                {
+                    QSettings.getInstance().restore(QSetting.RendererShowDuringPlayMode);
+                }
+                drawBackground(rect.x, rect.y, rect.width, 18 + 5);
+                drawSpace(4);
+                drawCheckBoxRight("Show component during play mode", QSetting.RendererShowDuringPlayMode);
+                drawSpace(1);
+            }
+        }
+
+        private void drawPrefabComponentSettings() 
+        {
+            if (drawComponentCheckBox("Prefab", QSetting.PrefabShow))
+            {
+                Rect rect = getControlRect(0, 0);
+                if (drawRestore())
+                {
+                    QSettings.getInstance().restore(QSetting.PrefabShowBreakedPrefabsOnly);
+                }
+                drawBackground(rect.x, rect.y, rect.width, 18 + 5);
+                drawSpace(4);
+                drawCheckBoxRight("Show icon for broken prefabs only", QSetting.PrefabShowBreakedPrefabsOnly);
+                drawSpace(1);
+            }
+        }
+
+        private void drawTagLayerComponentSettings()
+        {
+            if (drawComponentCheckBox("Tag And Layer", QSetting.TagAndLayerShow))
+            {
+                Rect rect = getControlRect(0, 0);
+                if (drawRestore())
+                {
+                    QSettings.getInstance().restore(QSetting.TagAndLayerShowDuringPlayMode);
+                    QSettings.getInstance().restore(QSetting.TagAndLayerSizeShowType);
+                    QSettings.getInstance().restore(QSetting.TagAndLayerType);
+                    QSettings.getInstance().restore(QSetting.TagAndLayerSizeValueType);
+                    QSettings.getInstance().restore(QSetting.TagAndLayerSizeValuePixel);
+                    QSettings.getInstance().restore(QSetting.TagAndLayerSizeValuePercent);
+                    QSettings.getInstance().restore(QSetting.TagAndLayerAligment);
+                    QSettings.getInstance().restore(QSetting.TagAndLayerLabelSize);
+                    QSettings.getInstance().restore(QSetting.TagAndLayerLabelAlpha);
+                    QSettings.getInstance().restore(QSetting.TagAndLayerTagLabelColor);
+                    QSettings.getInstance().restore(QSetting.TagAndLayerLayerLabelColor);
+                }
+                drawBackground(rect.x, rect.y, rect.width, 18 * 10 + 5);
+                drawSpace(4);
+                drawCheckBoxRight("Show component during play mode", QSetting.TagAndLayerShowDuringPlayMode);  
+                drawEnum("Show", QSetting.TagAndLayerSizeShowType, typeof(QHierarchyTagAndLayerShowType));
+                drawEnum("Show tag and layer", QSetting.TagAndLayerType, typeof(QHierarchyTagAndLayerType));
+
+                QHierarchyTagAndLayerSizeType newTagAndLayerSizeValueType = (QHierarchyTagAndLayerSizeType)drawEnum("Unit of width", QSetting.TagAndLayerSizeValueType, typeof(QHierarchyTagAndLayerSizeType));               
+
+                if (newTagAndLayerSizeValueType == QHierarchyTagAndLayerSizeType.Pixel)                
+                    drawIntSlider("Width in pixels", QSetting.TagAndLayerSizeValuePixel, 5, 250);                
+                else                
+                    drawFloatSlider("Percentage width", QSetting.TagAndLayerSizeValuePercent, 0, 0.5f);
+                           
+                drawEnum("Alignment", QSetting.TagAndLayerAligment, typeof(QHierarchyTagAndLayerAligment));
+                drawEnum("Label size", QSetting.TagAndLayerLabelSize, typeof(QHierarchyTagAndLayerLabelSize));
+                drawFloatSlider("Label alpha if default", QSetting.TagAndLayerLabelAlpha, 0, 1.0f);
+                drawColorPicker("Tag label color", QSetting.TagAndLayerTagLabelColor);
+                drawColorPicker("Layer label color", QSetting.TagAndLayerLayerLabelColor);
+                drawSpace(1);
+            }
+        }
+
+        private void drawColorComponentSettings() 
+        {
+            if (drawComponentCheckBox("Color", QSetting.ColorShow))
+            {
+                Rect rect = getControlRect(0, 0);
+                if (drawRestore())
+                {
+                    QSettings.getInstance().restore(QSetting.ColorShowDuringPlayMode);
+                }
+                drawBackground(rect.x, rect.y, rect.width, 18 + 5);
+                drawSpace(4);
+                drawCheckBoxRight("Show component during play mode", QSetting.ColorShowDuringPlayMode);
+                drawSpace(1);
+            }
+        }
+
+        private void drawGameObjectIconComponentSettings() 
+        {
+            if (drawComponentCheckBox("GameObject Icon", QSetting.GameObjectIconShow))
+            {
+                Rect rect = getControlRect(0, 0);
+                if (drawRestore())
+                {
+                    QSettings.getInstance().restore(QSetting.GameObjectIconShowDuringPlayMode);
+                    QSettings.getInstance().restore(QSetting.GameObjectIconSize);
+                }
+                drawBackground(rect.x, rect.y, rect.width, 18 * 2 + 5);
+                drawSpace(4);
+                drawCheckBoxRight("Show component during play mode", QSetting.GameObjectIconShowDuringPlayMode);
+                drawEnum("Icon size", QSetting.GameObjectIconSize, typeof(QHierarchySizeAll));
+                drawSpace(1);
+            }
+        }
+
+        private void drawTagIconComponentSettings() 
+        {
+            if (drawComponentCheckBox("Tag Icon", QSetting.TagIconShow))
+            {     
+                string[] tags = UnityEditorInternal.InternalEditorUtility.tags;
+
+                bool showTagIconList = QSettings.getInstance().get<bool>(QSetting.TagIconListFoldout);
+
+                Rect rect = getControlRect(0, 0);
+                if (drawRestore())
+                {
+                    QSettings.getInstance().restore(QSetting.TagIconShowDuringPlayMode);
+                    QSettings.getInstance().restore(QSetting.TagIconSize);
+                }
+                drawBackground(rect.x, rect.y, rect.width, 18 * 3 + (showTagIconList ? 18 * tags.Length : 0) + 4 + 5);    
+
+                drawSpace(4);
+                drawCheckBoxRight("Show component during play mode", QSetting.TagIconShowDuringPlayMode);
+                drawEnum("Icon size", QSetting.TagIconSize, typeof(QHierarchySizeAll));
+                if (drawFoldout("Tag icon list", QSetting.TagIconListFoldout))
+                {
+                    List<QTagTexture> tagTextureList = QTagTexture.loadTagTextureList();
+                
+                    bool changed = false;
+                    for (int i = 0; i < tags.Length; i++) 
+                    {
+                        string tag = tags[i];
+                        QTagTexture tagTexture = tagTextureList.Find(t => t.tag == tag);
+                        Texture2D newTexture = (Texture2D)EditorGUI.ObjectField(getControlRect(0, 16, 34 + 16, 6), 
+                                                                                tag, tagTexture == null ? null : tagTexture.texture, typeof(Texture2D), false);
+                        if (newTexture != null && tagTexture == null)
+                        {
+                            QTagTexture newTagTexture = new QTagTexture(tag, newTexture);
+                            tagTextureList.Add(newTagTexture);
+                            
+                            changed = true;
+                        }
+                        else if (newTexture == null && tagTexture != null)
+                        {
+                            tagTextureList.Remove(tagTexture);                            
+                            changed = true;
+                        }
+                        else if (tagTexture != null && tagTexture.texture != newTexture)
+                        {
+                            tagTexture.texture = newTexture;
+                            changed = true;
+                        }
+
+                        drawSpace(i == tags.Length - 1 ? 2 : 2);
+                    }                 
+
+                    if (changed) 
+                    {     
+                        QTagTexture.saveTagTextureList(QSetting.TagIconList, tagTextureList);
+                        EditorApplication.RepaintHierarchyWindow();
+                    }
+                }
+
+                drawSpace(1);
+            }
+        }
+
+        private void drawLayerIconComponentSettings() 
+        {
+            if (drawComponentCheckBox("Layer Icon", QSetting.LayerIconShow))
+            {     
+                string[] layers = UnityEditorInternal.InternalEditorUtility.layers;
+                
+                bool showLayerIconList = QSettings.getInstance().get<bool>(QSetting.LayerIconListFoldout);
+                
+                Rect rect = getControlRect(0, 0);
+                if (drawRestore())
+                {
+                    QSettings.getInstance().restore(QSetting.LayerIconShowDuringPlayMode);
+                    QSettings.getInstance().restore(QSetting.LayerIconSize);
+                }
+                drawBackground(rect.x, rect.y, rect.width, 18 * 3 + (showLayerIconList ? 18 * layers.Length : 0) + 4 + 5);    
+                
+                drawSpace(4);
+                drawCheckBoxRight("Show component during play mode", QSetting.LayerIconShowDuringPlayMode);
+                drawEnum("Icon size", QSetting.LayerIconSize, typeof(QHierarchySizeAll));
+                if (drawFoldout("Layer icon list", QSetting.LayerIconListFoldout))
+                {
+                    List<QLayerTexture> layerTextureList = QLayerTexture.loadLayerTextureList();
+                    
+                    bool changed = false;
+                    for (int i = 0; i < layers.Length; i++) 
+                    {
+                        string layer = layers[i];
+                        QLayerTexture layerTexture = layerTextureList.Find(t => t.layer == layer);
+                        Texture2D newTexture = (Texture2D)EditorGUI.ObjectField(getControlRect(0, 16, 34 + 16, 6), 
+                                                                                layer, layerTexture == null ? null : layerTexture.texture, typeof(Texture2D), false);
+                        if (newTexture != null && layerTexture == null)
+                        {
+                            QLayerTexture newLayerTexture = new QLayerTexture(layer, newTexture);
+                            layerTextureList.Add(newLayerTexture);
+                            
+                            changed = true;
+                        }
+                        else if (newTexture == null && layerTexture != null)
+                        {
+                            layerTextureList.Remove(layerTexture);                            
+                            changed = true;
+                        }
+                        else if (layerTexture != null && layerTexture.texture != newTexture)
+                        {
+                            layerTexture.texture = newTexture;
+                            changed = true;
+                        }
+                        
+                        drawSpace(i == layers.Length - 1 ? 2 : 2);
+                    }                 
+                    
+                    if (changed) 
+                    {     
+                        QLayerTexture.saveLayerTextureList(QSetting.LayerIconList, layerTextureList);
+                        EditorApplication.RepaintHierarchyWindow();
+                    }
+                }
+                
+                drawSpace(1);
+            }
+        }
+
+        private void drawChildrenCountComponentSettings() 
+        {
+            if (drawComponentCheckBox("Children Count", QSetting.ChildrenCountShow))
+            {
+                Rect rect = getControlRect(0, 0);
+                if (drawRestore())
+                {
+                    QSettings.getInstance().restore(QSetting.ChildrenCountShowDuringPlayMode);
+                    QSettings.getInstance().restore(QSetting.ChildrenCountLabelSize);
+                    QSettings.getInstance().restore(QSetting.ChildrenCountLabelColor);
+                }
+                drawBackground(rect.x, rect.y, rect.width, 18 * 3 + 5);
+                drawSpace(4);
+                drawCheckBoxRight("Show component during play mode", QSetting.ChildrenCountShowDuringPlayMode);
+                drawEnum("Label size", QSetting.ChildrenCountLabelSize, typeof(QHierarchySize));
+                drawColorPicker("Label color", QSetting.ChildrenCountLabelColor);
+                drawSpace(1);
+            }
+        }
+        
+        private void drawVerticesAndTrianglesCountComponentSettings()
+        {
+            if (drawComponentCheckBox("Vertices And Triangles Count", QSetting.VerticesAndTrianglesShow))
+            {
+                Rect rect = getControlRect(0, 0);
+                if (drawRestore())
+                {
+                    QSettings.getInstance().restore(QSetting.VerticesAndTrianglesShowDuringPlayMode);
+                    QSettings.getInstance().restore(QSetting.VerticesAndTrianglesShowVertices);
+                    QSettings.getInstance().restore(QSetting.VerticesAndTrianglesShowTriangles);
+                    QSettings.getInstance().restore(QSetting.VerticesAndTrianglesCalculateTotalCount);
+                    QSettings.getInstance().restore(QSetting.VerticesAndTrianglesLabelSize);
+                    QSettings.getInstance().restore(QSetting.VerticesAndTrianglesVerticesLabelColor);
+                    QSettings.getInstance().restore(QSetting.VerticesAndTrianglesTrianglesLabelColor);
+                }
+                drawBackground(rect.x, rect.y, rect.width, 18 * 7 + 5);
+                drawSpace(4);
+                drawCheckBoxRight("Show component during play mode", QSetting.VerticesAndTrianglesShowDuringPlayMode);                   
+                if (drawCheckBoxRight("Show vertices count", QSetting.VerticesAndTrianglesShowVertices))
+                {
+                    if (QSettings.getInstance().get<bool>(QSetting.VerticesAndTrianglesShowVertices) == false &&
+                        QSettings.getInstance().get<bool>(QSetting.VerticesAndTrianglesShowTriangles) == false)                    
+                        QSettings.getInstance().set(QSetting.VerticesAndTrianglesShowTriangles, true);
+                }
+                if (drawCheckBoxRight("Show triangles count (very slow)", QSetting.VerticesAndTrianglesShowTriangles))
+                {
+                    if (QSettings.getInstance().get<bool>(QSetting.VerticesAndTrianglesShowVertices) == false &&
+                        QSettings.getInstance().get<bool>(QSetting.VerticesAndTrianglesShowTriangles) == false)                 
+                        QSettings.getInstance().set(QSetting.VerticesAndTrianglesShowVertices, true);
+                }
+                drawCheckBoxRight("Calculate the count including children (very slow)", QSetting.VerticesAndTrianglesCalculateTotalCount);
+                drawEnum("Label size", QSetting.VerticesAndTrianglesLabelSize, typeof(QHierarchySize));
+                drawColorPicker("Vertices label color", QSetting.VerticesAndTrianglesVerticesLabelColor);
+                drawColorPicker("Triangles label color", QSetting.VerticesAndTrianglesTrianglesLabelColor);
+                drawSpace(1);
+            }
+        }
+
+        private void drawComponentsComponentSettings() 
+        {
+            if (drawComponentCheckBox("Components", QSetting.ComponentsShow))
+            {
+                Rect rect = getControlRect(0, 0);
+                if (drawRestore())
+                {
+                    QSettings.getInstance().restore(QSetting.ComponentsShowDuringPlayMode);
+                    QSettings.getInstance().restore(QSetting.ComponentsIconSize);
+                }
+                drawBackground(rect.x, rect.y, rect.width, 18 * 3 + 6);
+                drawSpace(4);
+                drawCheckBoxRight("Show component during play mode", QSetting.ComponentsShowDuringPlayMode);
+                drawEnum("Icon size", QSetting.ComponentsIconSize, typeof(QHierarchySizeAll));
+                drawTextField("Ignore packages/classes", QSetting.ComponentsIgnore);
+                drawSpace(2);
+            }
+        }
+
+        // COMPONENTS ORDER
+        private void drawOrderSettings()
+        {
+            if (drawRestore())
+            {
+                QSettings.getInstance().restore(QSetting.ComponentsOrder);
+            }
+
+            indentLevel += 4;
+            
+            string componentOrder = QSettings.getInstance().get<string>(QSetting.ComponentsOrder);
+            string[] componentIds = componentOrder.Split(';');
+            
+            Rect rect = getControlRect(position.width, 17 * componentIds.Length + 10, 0, 0);
+            if (componentsOrderList == null) 
+                componentsOrderList = new QComponentsOrderList(this);
+            componentsOrderList.draw(rect, componentIds);
+            
+            indentLevel -= 4;
+        }  
+
+        // ADDITIONAL SETTINGS
+        private void drawAdditionalSettings()
+        {
+            if (drawRestore())
+            {
+                QSettings.getInstance().restore(QSetting.AdditionalShowHiddenQHierarchyObjectList);
+                QSettings.getInstance().restore(QSetting.AdditionalHideIconsIfNotFit);
+                QSettings.getInstance().restore(QSetting.AdditionalIdentation);
+                QSettings.getInstance().restore(QSetting.AdditionalShowModifierWarning);
+                QSettings.getInstance().restore(QSetting.AdditionalBackgroundColor);
+                QSettings.getInstance().restore(QSetting.AdditionalActiveColor);
+                QSettings.getInstance().restore(QSetting.AdditionalInactiveColor);
+                QSettings.getInstance().restore(QSetting.AdditionalSpecialColor);
+            }
+            drawSpace(4);
+            drawCheckBoxRight("Show QHierarchyObjectList GameObject", QSetting.AdditionalShowHiddenQHierarchyObjectList);
+            drawCheckBoxRight("Hide icons if not fit", QSetting.AdditionalHideIconsIfNotFit);
+            drawIntSlider("Right indent", QSetting.AdditionalIdentation, 0, 500);      
+            drawCheckBoxRight("Show warning when using modifiers + click", QSetting.AdditionalShowModifierWarning);
+            drawColorPicker("Background color", QSetting.AdditionalBackgroundColor);
+            drawColorPicker("Active color", QSetting.AdditionalActiveColor);
+            drawColorPicker("Inactive color", QSetting.AdditionalInactiveColor);
+            drawColorPicker("Special color", QSetting.AdditionalSpecialColor);
+            drawSpace(1);
+        }
+
+        // PRIVATE
+        private void drawSection(string title)
+        {
+            Rect rect = getControlRect(0, 24, -3, 0);
+            rect.width *= 2;
+            rect.x = 0;
+            GUI.Box(rect, "");             
+            
+            drawLeftLine(rect.y, rect.y + 24, yellowColor);
+            
+            rect.x = lastRect.x + 8;
+            rect.y += 4;
+            EditorGUI.LabelField(rect, title);
+        }
+
+        private void drawSeparator(int spaceBefore = 0, int spaceAfter = 0, int height = 1)
+        {
+            if (spaceBefore > 0) drawSpace(spaceBefore);
+            Rect rect = getControlRect(0, height, 0, 0);
+            rect.width += 8;
+            EditorGUI.DrawRect(rect, separatorColor);
+            if (spaceAfter > 0) drawSpace(spaceAfter);
+        }
+
+        private bool drawComponentCheckBox(string label, QSetting setting)
+        {
+            indentLevel += 8;
+
+            Rect rect = getControlRect(0, 28, 0, 0);
+
+            float rectWidth = rect.width;
+            bool isChecked = QSettings.getInstance().get<bool>(setting);
+
+            rect.x -= 1;
+            rect.y += 7;
+            rect.width  = 14;
+            rect.height = 14;
+
+            if (GUI.Button(rect, isChecked ? checkBoxChecked : checkBoxUnchecked, GUIStyle.none))
+            {
+                QSettings.getInstance().set(setting, !isChecked);
+            }
+
+            rect.x += 14 + 10;
+            rect.width = rectWidth - 14 - 8;
+            rect.y -= (EditorGUIUtility.singleLineHeight - rect.height) * 0.5f;
+            rect.height = EditorGUIUtility.singleLineHeight;
+
+            EditorGUI.LabelField(rect, label);
+
+            indentLevel -= 8;
+
+            return isChecked;
+        }
+
+        private bool drawCheckBoxRight(string label, QSetting setting)
+        {
+            Rect rect = getControlRect(0, 18, 34, 6);
+            bool result = false;
+            bool isChecked = QSettings.getInstance().get<bool>(setting);
+
+            float tempX = rect.x;
+            rect.x += rect.width - 14;
+            rect.y += 1;
+            rect.width  = 14;
+            rect.height = 14;
+            
+            if (GUI.Button(rect, isChecked ? checkBoxChecked : checkBoxUnchecked, GUIStyle.none))
+            {
+                QSettings.getInstance().set(setting, !isChecked);
+                result = true;
+            }
+
+            rect.width = rect.x - tempX - 4;
+            rect.x = tempX;
+            rect.y -= (EditorGUIUtility.singleLineHeight - rect.height) * 0.5f;
+            rect.height = EditorGUIUtility.singleLineHeight;
+            
+            EditorGUI.LabelField(rect, label);
+
+            return result;
+        }
+
+        private void drawSpace(int value)
+        {
+            getControlRect(0, value, 0, 0);
+        }
+
+        private void drawBackground(float x, float y, float width, float height)
+        {
+            EditorGUI.DrawRect(new Rect(x, y, width, height), separatorColor);
+        }
+        
+        private void drawLeftLine(float fromY, float toY, Color color, float width = 0)
+        {
+            EditorGUI.DrawRect(new Rect(0, fromY, width == 0 ? indentLevel : width, toY - fromY), color);
+        }
+        
+        private Rect getControlRect(float width, float height, float addIndent = 0, float remWidth = 0)
+        { 
+            EditorGUILayout.GetControlRect(false, height, GUIStyle.none, GUILayout.ExpandWidth(true));
+            Rect rect = new Rect(indentLevel + addIndent, lastRect.y + lastRect.height, (width == 0 ? totalWidth - indentLevel - addIndent - remWidth: width), height);
+            lastRect = rect;
+            return rect;
+        }
+
+        private bool drawRestore()
+        {
+            if (GUI.Button(new Rect(lastRect.x + lastRect.width - 16 - 5, lastRect.y - 20, 16, 16), restoreButtonTexture, GUIStyle.none))
+            {
+                if (EditorUtility.DisplayDialog("Restore", "Restore default settings?", "Ok", "Cancel"))
+                {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        // GUI COMPONENTS
+        private void drawLabel(string label)
+        {
+            Rect rect = getControlRect(0, 16, 34, 6);
+            rect.y -= (EditorGUIUtility.singleLineHeight - rect.height) * 0.5f;
+            EditorGUI.LabelField(rect, label);
+            drawSpace(2);
+        }
+
+        private void drawTextField(string label, QSetting setting)
+        {
+            string currentValue = QSettings.getInstance().get<string>(setting);
+            string newValue     = EditorGUI.TextField(getControlRect(0, 16, 34, 6), label, currentValue);
+            if (!currentValue.Equals(newValue)) QSettings.getInstance().set(setting, newValue);
+            drawSpace(2);
+        }
+
+        private bool drawFoldout(string label, QSetting setting)
+        {
+            #if UNITY_2019_1_OR_NEWER
+                Rect foldoutRect = getControlRect(0, 16, 19, 6);
+            #else
+                Rect foldoutRect = getControlRect(0, 16, 22, 6);
+            #endif
+            bool foldoutValue = QSettings.getInstance().get<bool>(setting);
+            bool newFoldoutValue = EditorGUI.Foldout(foldoutRect, foldoutValue, label);
+            if (foldoutValue != newFoldoutValue) QSettings.getInstance().set(setting, newFoldoutValue);
+            drawSpace(2);
+            return newFoldoutValue;
+        }
+
+        private void drawColorPicker(string label, QSetting setting)
+        {
+            Color currentColor = QSettings.getInstance().getColor(setting);
+            Color newColor = EditorGUI.ColorField(getControlRect(0, 16, 34, 6), label, currentColor);
+            if (!currentColor.Equals(newColor)) QSettings.getInstance().setColor(setting, newColor);
+            drawSpace(2);
+        }
+
+        private Enum drawEnum(string label, QSetting setting, Type enumType)
+        {
+            Enum currentEnum = (Enum)Enum.ToObject(enumType, QSettings.getInstance().get<int>(setting));
+            Enum newEnumValue;                      
+            if (!(newEnumValue = EditorGUI.EnumPopup(getControlRect(0, 16, 34, 6), label, currentEnum)).Equals(currentEnum))                
+                QSettings.getInstance().set(setting, (int)(object)newEnumValue);                  
+            drawSpace(2);
+            return newEnumValue;
+        }
+
+        private void drawIntSlider(string label, QSetting setting, int minValue, int maxValue)
+        {
+            Rect rect = getControlRect(0, 16, 34, 4);
+            int currentValue = QSettings.getInstance().get<int>(setting);
+            int newValue = EditorGUI.IntSlider(rect, label, currentValue, minValue, maxValue);
+            if (currentValue != newValue) QSettings.getInstance().set(setting, newValue);
+            drawSpace(2);
+        }
+
+        private void drawFloatSlider(string label, QSetting setting, float minValue, float maxValue)
+        {
+            Rect rect = getControlRect(0, 16, 34, 4);
+            float currentValue = QSettings.getInstance().get<float>(setting);
+            float newValue = EditorGUI.Slider(rect, label, currentValue, minValue, maxValue);
+            if (currentValue != newValue) QSettings.getInstance().set(setting, newValue);
+            drawSpace(2);
+        }
+	}
+}
\ No newline at end of file
diff --git a/Assets/Plugins/QHierarchy/Editor/Scripts/phierarchy/QHierarchySettingsWindow.cs.meta b/Assets/Plugins/QHierarchy/Editor/Scripts/phierarchy/QHierarchySettingsWindow.cs.meta
new file mode 100644
index 0000000..e92c0a6
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Editor/Scripts/phierarchy/QHierarchySettingsWindow.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 311dd60af7f888a4ea46d48565c35ed1
+timeCreated: 1474888502
+licenseType: Store
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Plugins/QHierarchy/Manual.pdf b/Assets/Plugins/QHierarchy/Manual.pdf
new file mode 100644
index 0000000..090ce5f
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Manual.pdf
Binary files differ
diff --git a/Assets/Plugins/QHierarchy/Manual.pdf.meta b/Assets/Plugins/QHierarchy/Manual.pdf.meta
new file mode 100644
index 0000000..da685ed
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Manual.pdf.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: e70abd53bc685854c862668bc2c3fef1
+timeCreated: 1475573212
+licenseType: Store
+DefaultImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Plugins/QHierarchy/Scripts.meta b/Assets/Plugins/QHierarchy/Scripts.meta
new file mode 100644
index 0000000..cafbd6b
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Scripts.meta
@@ -0,0 +1,10 @@
+fileFormatVersion: 2
+guid: 7de9a0dec5e15f64fa8b3c79974355f0
+folderAsset: yes
+timeCreated: 1515657177
+licenseType: Store
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Plugins/QHierarchy/Scripts/QHierarchyRuntime.asmdef b/Assets/Plugins/QHierarchy/Scripts/QHierarchyRuntime.asmdef
new file mode 100644
index 0000000..4ffa4d2
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Scripts/QHierarchyRuntime.asmdef
@@ -0,0 +1,8 @@
+{
+    "name": "QHierarchyRuntime",
+    "references": [],
+    "optionalUnityReferences": [],
+    "includePlatforms": [],
+    "excludePlatforms": [],
+    "allowUnsafeCode": false
+}
\ No newline at end of file
diff --git a/Assets/Plugins/QHierarchy/Scripts/QHierarchyRuntime.asmdef.meta b/Assets/Plugins/QHierarchy/Scripts/QHierarchyRuntime.asmdef.meta
new file mode 100644
index 0000000..fae1912
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Scripts/QHierarchyRuntime.asmdef.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 211f9e8f16a5ff644946a29c81bedf42
+AssemblyDefinitionImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Plugins/QHierarchy/Scripts/QObjectList.cs b/Assets/Plugins/QHierarchy/Scripts/QObjectList.cs
new file mode 100644
index 0000000..8f086ed
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Scripts/QObjectList.cs
@@ -0,0 +1,158 @@
+锘縰sing UnityEngine;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+#if UNITY_EDITOR
+using UnityEditor;
+#endif
+
+namespace qtools.qhierarchy
+{	
+	[ExecuteInEditMode]
+	[AddComponentMenu("")]
+	public class QObjectList: MonoBehaviour, ISerializationCallbackReceiver
+	{
+		public static List<QObjectList> instances = new List<QObjectList>();
+
+		public List<GameObject> lockedObjects = new List<GameObject>();
+		public List<GameObject> editModeVisibileObjects = new List<GameObject>();
+		public List<GameObject> editModeInvisibleObjects = new List<GameObject>();
+		public List<GameObject> wireframeHiddenObjects = new List<GameObject>();		
+		public Dictionary<GameObject, Color> gameObjectColor = new Dictionary<GameObject, Color>();
+		public List<GameObject> gameObjectColorKeys   = new List<GameObject>();		
+		public List<Color> 		gameObjectColorValues = new List<Color>();
+
+		public void Awake() 
+		{
+			checkIntegrity(); 
+			
+			foreach (GameObject editModeGameObject in editModeVisibileObjects)               
+				editModeGameObject.SetActive(!Application.isPlaying);                
+			
+			foreach (GameObject editModeGameObject in editModeInvisibleObjects)                
+				editModeGameObject.SetActive(Application.isPlaying);
+
+			if (!Application.isEditor && Application.isPlaying)		
+			{
+				instances.Remove(this);
+				DestroyImmediate(gameObject);
+				return;
+			}
+
+			instances.RemoveAll(item => item == null);
+			if (!instances.Contains(this)) instances.Add(this);
+		}
+
+		public void OnEnable() 
+		{  
+			if (!instances.Contains(this)) instances.Add(this);
+
+			#if UNITY_EDITOR
+			foreach (GameObject wireframeGameObject in wireframeHiddenObjects)
+			{
+				Renderer renderer = wireframeGameObject.GetComponent<Renderer>();
+				if (renderer != null) 
+                {
+                    #if UNITY_5_5_OR_NEWER
+                    EditorUtility.SetSelectedRenderState(renderer, EditorSelectedRenderState.Hidden);
+                    #else
+                    EditorUtility.SetSelectedWireframeHidden(renderer, true);
+                    #endif
+                }
+			}
+			#endif
+		}
+
+		public void OnDestroy()
+		{
+			if (!Application.isPlaying)
+			{
+				checkIntegrity();
+				
+				foreach (GameObject gameObject in editModeVisibileObjects)               
+					gameObject.SetActive(false);                
+				
+				foreach (GameObject gameObject in editModeInvisibleObjects)                
+					gameObject.SetActive(true);
+				
+				foreach (GameObject gameObject in lockedObjects)   			
+					gameObject.hideFlags &= ~HideFlags.NotEditable;
+
+				instances.Remove(this);
+			}
+		}
+
+		public void merge(QObjectList anotherInstance)
+		{ 
+			for (int i = anotherInstance.lockedObjects.Count - 1; i >= 0; i--)
+			{
+				if (!lockedObjects.Contains(anotherInstance.lockedObjects[i]))
+					lockedObjects.Add(anotherInstance.lockedObjects[i]);
+			}
+
+			for (int i = anotherInstance.editModeVisibileObjects.Count - 1; i >= 0; i--)
+			{
+				if (!editModeVisibileObjects.Contains(anotherInstance.editModeVisibileObjects[i]))
+					editModeVisibileObjects.Add(anotherInstance.editModeVisibileObjects[i]);
+			}
+
+			for (int i = anotherInstance.editModeInvisibleObjects.Count - 1; i >= 0; i--)
+			{
+				if (!editModeInvisibleObjects.Contains(anotherInstance.editModeInvisibleObjects[i]))
+					editModeInvisibleObjects.Add(anotherInstance.editModeInvisibleObjects[i]);
+			}
+
+			for (int i = anotherInstance.wireframeHiddenObjects.Count - 1; i >= 0; i--)
+			{
+				if (!wireframeHiddenObjects.Contains(anotherInstance.wireframeHiddenObjects[i]))
+					wireframeHiddenObjects.Add(anotherInstance.wireframeHiddenObjects[i]);
+			}
+
+			for (int i = anotherInstance.gameObjectColorKeys.Count - 1; i >= 0; i--)
+			{
+				if (!gameObjectColorKeys.Contains(anotherInstance.gameObjectColorKeys[i]))
+				{
+					gameObjectColorKeys.Add(anotherInstance.gameObjectColorKeys[i]);
+					gameObjectColorValues.Add(anotherInstance.gameObjectColorValues[i]);
+					gameObjectColor.Add(anotherInstance.gameObjectColorKeys[i], anotherInstance.gameObjectColorValues[i]);
+				}
+			}
+        } 
+        
+		public void checkIntegrity()
+		{
+			lockedObjects.RemoveAll(item => item == null);
+			editModeVisibileObjects.RemoveAll(item => item == null);
+			editModeInvisibleObjects.RemoveAll(item => item == null);
+			wireframeHiddenObjects.RemoveAll(item => item == null);
+
+			for (int i = gameObjectColorKeys.Count - 1; i >= 0; i--)
+			{
+				if (gameObjectColorKeys[i] == null)
+				{
+					gameObjectColorKeys.RemoveAt(i);
+					gameObjectColorValues.RemoveAt(i);
+				}
+			}
+			OnAfterDeserialize();
+		}          
+
+		public void OnBeforeSerialize()
+		{  
+			gameObjectColorKeys.Clear();
+			gameObjectColorValues.Clear();
+			foreach(KeyValuePair<GameObject, Color> pair in gameObjectColor)
+			{
+				gameObjectColorKeys.Add(pair.Key);
+				gameObjectColorValues.Add(pair.Value);
+			}
+		}
+		
+		public void OnAfterDeserialize()
+		{
+			gameObjectColor.Clear();			
+			for(int i = 0; i < gameObjectColorKeys.Count; i++)
+				gameObjectColor.Add(gameObjectColorKeys[i], gameObjectColorValues[i]);
+		}
+	}
+}
\ No newline at end of file
diff --git a/Assets/Plugins/QHierarchy/Scripts/QObjectList.cs.meta b/Assets/Plugins/QHierarchy/Scripts/QObjectList.cs.meta
new file mode 100644
index 0000000..ec3dfd5
--- /dev/null
+++ b/Assets/Plugins/QHierarchy/Scripts/QObjectList.cs.meta
@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 845e8bd83609e3549af5a311ad811681
+timeCreated: 1475506195
+licenseType: Store
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: -10000
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

--
Gitblit v1.8.0