using System.Collections.Generic; using System.Linq; using UnityEditor; using UnityEditorInternal; using UnityEngine; namespace Editor.Utilities { public class ComponentTransferWindow : EditorWindow { private GameObject sourceGameObject; private GameObject targetGameObject; private Vector2 scrollPosition; private Dictionary componentSelections = new Dictionary(); private bool selectAll = false; [MenuItem("Tools/Component Transfer Tool")] public static void ShowWindow() { ComponentTransferWindow window = GetWindow("Component Transfer"); window.minSize = new Vector2(400, 300); } private void OnGUI() { GUILayout.Label("Component Transfer Tool", EditorStyles.boldLabel); EditorGUILayout.Space(); DrawGameObjectSelectors(); EditorGUILayout.Space(); if (sourceGameObject != null) { DrawComponentSelectionArea(); EditorGUILayout.Space(); DrawOperationButtons(); } } private void DrawGameObjectSelectors() { EditorGUILayout.BeginHorizontal(); EditorGUILayout.BeginVertical(); EditorGUI.BeginChangeCheck(); GameObject newSource = EditorGUILayout.ObjectField("Source GameObject", sourceGameObject, typeof(GameObject), true) as GameObject; if (EditorGUI.EndChangeCheck()) { if (newSource != sourceGameObject) { sourceGameObject = newSource; RefreshComponentList(); } } EditorGUILayout.EndVertical(); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); EditorGUILayout.BeginVertical(); targetGameObject = EditorGUILayout.ObjectField("Target GameObject", targetGameObject, typeof(GameObject), true) as GameObject; EditorGUILayout.EndVertical(); EditorGUILayout.EndHorizontal(); // Error validation if (sourceGameObject == targetGameObject && sourceGameObject != null) { EditorGUILayout.HelpBox("Source and target cannot be the same GameObject.", MessageType.Error); } } private void DrawComponentSelectionArea() { if (componentSelections.Count == 0) { EditorGUILayout.LabelField("No components found on source GameObject."); return; } EditorGUILayout.LabelField("Select Components to Transfer:", EditorStyles.boldLabel); EditorGUI.BeginChangeCheck(); bool newSelectAll = EditorGUILayout.ToggleLeft("Select All", selectAll); if (EditorGUI.EndChangeCheck() && newSelectAll != selectAll) { selectAll = newSelectAll; foreach (var key in componentSelections.Keys.ToArray()) { componentSelections[key] = selectAll; } } scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition); foreach (var kvp in componentSelections.ToArray()) { Component component = kvp.Key; if (component != null) { string componentName = component.GetType().Name; componentSelections[component] = EditorGUILayout.ToggleLeft(componentName, componentSelections[component]); } } EditorGUILayout.EndScrollView(); } private void DrawOperationButtons() { bool isValid = sourceGameObject != null && targetGameObject != null && sourceGameObject != targetGameObject; bool hasSelection = HasSelectedComponents(); EditorGUI.BeginDisabledGroup(!isValid || !hasSelection); EditorGUILayout.BeginHorizontal(); if (GUILayout.Button("Copy Components")) { CopyComponents(false); } if (GUILayout.Button("Move Components")) { CopyComponents(true); } EditorGUILayout.EndHorizontal(); EditorGUI.EndDisabledGroup(); } private void RefreshComponentList() { componentSelections.Clear(); if (sourceGameObject != null) { Component[] components = sourceGameObject.GetComponents(); foreach (Component component in components) { // Skip Transform component as it's required and should not be transferred if (component is Transform) continue; componentSelections.Add(component, false); } } } private bool HasSelectedComponents() { foreach (bool selected in componentSelections.Values) { if (selected) return true; } return false; } private void CopyComponents(bool moveInsteadOfCopy) { if (sourceGameObject == null || targetGameObject == null) return; Undo.RegisterCompleteObjectUndo(targetGameObject, moveInsteadOfCopy ? "Move Components" : "Copy Components"); if (moveInsteadOfCopy) { Undo.RegisterCompleteObjectUndo(sourceGameObject, "Move Components (Source)"); } // Store references to components that need to be destroyed after copying List componentsToDestroy = new List(); // Copy each selected component foreach (var kvp in componentSelections) { if (kvp.Value) // If component is selected { Component sourceComponent = kvp.Key; if (sourceComponent != null) { // Skip Transform component as it's required if (sourceComponent is Transform) continue; // Add the component of the same type to the target ComponentUtility.CopyComponent(sourceComponent); ComponentUtility.PasteComponentAsNew(targetGameObject); // If we're moving components, mark this for destruction if (moveInsteadOfCopy) { componentsToDestroy.Add(sourceComponent); } } } } // Destroy components on source if needed (after copying all components) if (moveInsteadOfCopy) { foreach (Component component in componentsToDestroy) { Undo.DestroyObjectImmediate(component); } } RefreshComponentList(); } } }