示例#1
0
        /// <summary>
        /// GUI を描画する時に呼び出されます
        /// </summary>
        public override void OnGUI(string searchContext)
        {
            var settings = GameObjectDuplicationHookerSettings.LoadFromEditorPrefs();

            using (var checkScope = new EditorGUI.ChangeCheckScope())
            {
                settings.IsEnable             = EditorGUILayout.Toggle("Enabled", settings.IsEnable);
                settings.IsEnableSerialNumber = EditorGUILayout.Toggle("Enabled Serial Number", settings.IsEnableSerialNumber);

                if (checkScope.changed)
                {
                    GameObjectDuplicationHookerSettings.SaveToEditorPrefs(settings);
                }
            }
        }
        /// <summary>
        /// Hierarchy の項目を描画する時に呼び出されます
        /// </summary>
        private static void HierarchyWindowItemOnGui(int instanceID, Rect selectionRect)
        {
            // Preferences で有効になっているかどうかを確認する
            var settings = GameObjectDuplicationHookerSettings.LoadFromEditorPrefs();
            var isEnable = settings.IsEnable;

            if (!isEnable)
            {
                return;
            }

            // 複製コマンド以外のイベントは無視
            var current     = Event.current;
            var commandName = current.commandName;

            if (string.IsNullOrWhiteSpace(commandName))
            {
                return;
            }
            if (commandName != "Duplicate")
            {
                return;
            }

            var type = current.type;

            if (type != EventType.ExecuteCommand && type != EventType.ValidateCommand)
            {
                return;
            }

            // 独自の複製コマンドで処理を上書きするため、
            // Unity 通常の複製コマンドを検知したら使用済みにする
            current.Use();

            // commandName が Duplicate のイベントは1フレームの間に何回も来るため
            // すでに独自の複製処理を実行している場合はここから先には進めない
            if (m_isDuplicating)
            {
                return;
            }
            m_isDuplicating = true;

            var duplicatedGameObjectList = new List <GameObject>();

            // 現在選択中のゲームオブジェクトを順番に複製していく
            // Selection.gameObjects は順不同で毎回順番が変わってしまうため sibilingIndex でソート
            foreach (var original in Selection.gameObjects.OrderBy(x => x.transform.GetSiblingIndex()))
            {
                // 複製後に名前の末尾に数値を付けないようにするために名前をキャッシュ
                // スケーリング値などに誤差が生じないようにするために transform のプロパティもキャッシュ
                var name          = original.name;
                var localPosition = original.transform.localPosition;
                var localRotation = original.transform.localRotation;
                var localScale    = original.transform.localScale;

                GameObject clone;

                // プレハブのインスタンスかどうかで使用する Instantiate を切り替える
                if (PrefabUtility.GetPrefabAssetType(original) == PrefabAssetType.NotAPrefab)
                {
                    clone = Object.Instantiate(original, original.transform.parent);
                }
                else
                {
                    // プレハブのインスタンスの場合は元のプレハブから Instantiate する
                    var prefab = PrefabUtility.GetCorrespondingObjectFromSource(original);
                    clone = ( GameObject )PrefabUtility.InstantiatePrefab(prefab, original.transform.parent);
                }

                // 連番対応が有効になっている場合は
                // 名前の文字列末尾の数字をインクリメントします
                if (settings.IsEnableSerialNumber)
                {
                    name = GetNameWithSerialNumber(name);
                }

                // キャッシュしておいたパラメータを設定
                clone.name = name;
                clone.transform.localPosition = localPosition;
                clone.transform.localRotation = localRotation;
                clone.transform.localScale    = localScale;

                // 複製完了後に複製したゲームオブジェクトを
                // Hierarchy で選択状態にするために一時リストに保持
                duplicatedGameObjectList.Add(clone);

                // Undo できるように登録
                Undo.RegisterCreatedObjectUndo(clone, "Duplicate");
            }

            EditorApplication.delayCall += () =>
            {
                // 複製したゲームオブジェクトを Hierarchy で選択状態にする
                // この処理を1フレーム待たないと独自の複製コマンドが正常に動作しなかった
                Selection.instanceIDs = duplicatedGameObjectList
                                        .Select(x => x.GetInstanceID())
                                        .ToArray()
                ;

                duplicatedGameObjectList.Clear();
                m_isDuplicating = false;
            };
        }