218 lines
7.2 KiB
C#
218 lines
7.2 KiB
C#
|
|
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<Component, bool> componentSelections = new Dictionary<Component, bool>();
|
|||
|
|
private bool selectAll = false;
|
|||
|
|
|
|||
|
|
[MenuItem("Tools/Component Transfer Tool")]
|
|||
|
|
public static void ShowWindow()
|
|||
|
|
{
|
|||
|
|
ComponentTransferWindow window = GetWindow<ComponentTransferWindow>("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<Component>();
|
|||
|
|
|
|||
|
|
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<Component> componentsToDestroy = new List<Component>();
|
|||
|
|
|
|||
|
|
// 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();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|