// ReSharper disable once UnusedMember.Local
        // ReSharper disable once InconsistentNaming
        private void OnGUI()
        {
            EditorContent.BeginObjectChanged();
            _sourceGameObject = EditorContent.ObjectPicker <GameObject>("Source GameObject", _sourceGameObject, true);

            if (EditorContent.IsObjectChanged())
            {
                _projections.Clear();
            }

            if (_sourceGameObject == null)
            {
                EditorContent.Label("Select the GameObject that you want to project the Component.");
                return;
            }

            _components = _sourceGameObject.GetComponents <Component>();

            EditorContent.Label("Components:");
            foreach (var component in _components)
            {
                var instanceId = component.GetInstanceID();
                if (!_projections.ContainsKey(instanceId))
                {
                    _projections.Add(instanceId, false);
                }
                _projections[instanceId] = EditorContent.Checkbox(ObjectNames.GetInspectorTitle(component), _projections[instanceId]);
            }

            EditorContent.Space();

            _destinationGameObject = EditorContent.ObjectPicker <GameObject>("Destination GameObject", _destinationGameObject, true);

            using (EditorContent.DisabledGroup(_destinationGameObject == null || _projections.All(w => !w.Value)))
            {
                if (EditorContent.Button("Projection"))
                {
                    foreach (var sourceComponent in _components.Where(w => _projections[w.GetInstanceID()]))
                    {
                        // ReSharper disable once PossibleNullReferenceException
                        var destComponent = _destinationGameObject.AddComponent(sourceComponent.GetType());

                        using (var sourceProperties = new SerializedObject(sourceComponent))
                            using (var destProperties = new SerializedObject(destComponent))
                            {
                                var iterator = sourceProperties.GetIterator();
                                while (iterator.NextVisible(true))
                                {
                                    destProperties.CopyFromSerializedProperty(iterator);
                                }
                                destProperties.ApplyModifiedProperties();
                            }
                    }
                }
            }
        }
        private void CreatePresetLayout()
        {
            EditorContent.Label("Create DynamicBone preset from existing GameObject tree.");
            EditorGUIUtility.labelWidth = 200;
            _gameObject = EditorContent.ObjectPicker<GameObject>("Root GameObject", _gameObject, true);
            if (ReferenceEquals(_gameObject, null))
                return;

            var components = new List<Component>();
            components.AddRange(_gameObject.GetComponentsInChildren(TypeFinder.GetType(DynamicBoneFullName)));
            components.AddRange(_gameObject.GetComponentsInChildren(TypeFinder.GetType(DynamicBoneColliderFullName)));
            components.AddRange(_gameObject.GetComponentsInChildren(TypeFinder.GetType(DynamicBonePlaneColliderFullName)));

            if (components.Count == 0)
                return;

            // differ
            {
                var added = components.Where(w => !_enabledComponents.ContainsKey(w.GetInstanceID())).ToList();
                var removed = _enabledComponents.Where(w => ReferenceEquals(components.SingleOrDefault(v => v.GetInstanceID() == w.Key), null)).ToList();

                foreach (var component in added)
                    _enabledComponents.Add(component.GetInstanceID(), false);
                foreach (var instanceId in removed.Select(w => w.Key))
                    _enabledComponents.Remove(instanceId);
            }

            EditorContent.Space();
            EditorContent.Label("Enabled Components:");
            foreach (var component in components)
            {
                var instanceId = component.GetInstanceID();
                _enabledComponents[instanceId] = EditorContent.Checkbox(component.ToString(), _enabledComponents[instanceId]);
            }

            if (_enabledComponents.Any(w => w.Value))
            {
                EditorContent.Space();
                EditorContent.Label("Naming Conventions:");
            }

            foreach (var component in _enabledComponents.Where(w => w.Value).Select(w => components.Single(v => v.GetInstanceID() == w.Key)))
            {
                var convention = PropertyTransformer.TransformToStringPath(component);
                var instance = _configurations.SingleOrDefault(w => w.OriginalInstanceId == component.GetInstanceID());
                if (ReferenceEquals(instance, null))
                {
                    instance = new DynamicBoneConfiguration();
                    instance.Name = instance.NamingConvention = convention;
                    instance.Component = component;
                    instance.OriginalInstanceId = component.GetInstanceID();
                    _configurations.Add(instance);
                }

                instance.NamingConvention = EditorContent.TextField(component.ToString(), instance.NamingConvention);
            }

            // cleanup instances
            foreach (var configuration in _enabledComponents.Where(w => !w.Value).Select(w => _configurations.SingleOrDefault(v => w.Key == v.OriginalInstanceId)).Where(w => !ReferenceEquals(w, null)).ToList())
                _configurations.Remove(configuration);

            EditorContent.Space();
            EditorContent.Label("DynamicBone Preset Manager convert hierarchy tree to the below name:");
            EditorContent.Label("Avatar → Armature → Hips → ... to Avatar/Armature/Hips/...");
            EditorContent.Label("If you want to preserve the tree structure, use `/` and `[^/]*?` in the naming convention.");

            using (EditorContent.DisabledGroup(_configurations.Count == 0))
                _name = EditorContent.TextField("Preset Name", _name);

            using (EditorContent.DisabledGroup(string.IsNullOrEmpty(_name) || _configurations.Count == 0))
                if (EditorContent.Button("Create DynamicBone Preset")) CreatePreset();
        }