229 lines
8.7 KiB
C#
229 lines
8.7 KiB
C#
using UnityEngine;
|
|
using UnityEditor;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Text.RegularExpressions;
|
|
|
|
namespace Editor
|
|
{
|
|
public class RemoveOldInteractableReferences : EditorWindow
|
|
{
|
|
private List<string> problematicPrefabs = new List<string>();
|
|
private Vector2 scrollPosition;
|
|
private bool hasScanned = false;
|
|
|
|
[MenuItem("AppleHills/Remove Old Interactable References")]
|
|
public static void ShowWindow()
|
|
{
|
|
var window = GetWindow<RemoveOldInteractableReferences>("Clean Old Interactables");
|
|
window.minSize = new Vector2(600, 400);
|
|
}
|
|
|
|
private void OnGUI()
|
|
{
|
|
GUILayout.Label("Remove Old Interactable/InteractableBase References", EditorStyles.boldLabel);
|
|
|
|
EditorGUILayout.HelpBox(
|
|
"This tool finds and removes references to:\n" +
|
|
"- Interactable (old script name)\n" +
|
|
"- InteractableBase (abstract class - not allowed on prefabs)\n\n" +
|
|
"These should be replaced by concrete types: Pickup, ItemSlot, or OneClickInteraction",
|
|
MessageType.Info);
|
|
|
|
EditorGUILayout.Space();
|
|
|
|
if (GUILayout.Button("Scan All Prefabs", GUILayout.Height(30)))
|
|
{
|
|
ScanPrefabs();
|
|
}
|
|
|
|
EditorGUILayout.Space();
|
|
|
|
if (hasScanned)
|
|
{
|
|
EditorGUILayout.LabelField($"Found {problematicPrefabs.Count} prefabs with old references", EditorStyles.boldLabel);
|
|
|
|
if (problematicPrefabs.Count > 0)
|
|
{
|
|
EditorGUILayout.Space();
|
|
|
|
if (GUILayout.Button("Clean All Prefabs", GUILayout.Height(30)))
|
|
{
|
|
CleanAllPrefabs();
|
|
}
|
|
|
|
EditorGUILayout.Space();
|
|
|
|
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
|
|
|
|
foreach (var prefabPath in problematicPrefabs)
|
|
{
|
|
EditorGUILayout.BeginHorizontal("box");
|
|
EditorGUILayout.LabelField(prefabPath);
|
|
if (GUILayout.Button("Clean This", GUILayout.Width(80)))
|
|
{
|
|
CleanSinglePrefab(prefabPath);
|
|
}
|
|
EditorGUILayout.EndHorizontal();
|
|
}
|
|
|
|
EditorGUILayout.EndScrollView();
|
|
}
|
|
else
|
|
{
|
|
EditorGUILayout.HelpBox("No problematic prefabs found! All clean.", MessageType.Info);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void ScanPrefabs()
|
|
{
|
|
problematicPrefabs.Clear();
|
|
hasScanned = true;
|
|
|
|
string[] prefabGuids = AssetDatabase.FindAssets("t:Prefab", new[] { "Assets" });
|
|
|
|
EditorUtility.DisplayProgressBar("Scanning Prefabs", "Starting...", 0f);
|
|
|
|
for (int i = 0; i < prefabGuids.Length; i++)
|
|
{
|
|
string path = AssetDatabase.GUIDToAssetPath(prefabGuids[i]);
|
|
|
|
EditorUtility.DisplayProgressBar("Scanning Prefabs",
|
|
$"Checking {i + 1}/{prefabGuids.Length}: {Path.GetFileName(path)}",
|
|
(float)i / prefabGuids.Length);
|
|
|
|
if (PrefabHasOldInteractableReference(path))
|
|
{
|
|
problematicPrefabs.Add(path);
|
|
}
|
|
}
|
|
|
|
EditorUtility.ClearProgressBar();
|
|
|
|
Debug.Log($"<color=cyan>[Scan Complete]</color> Found {problematicPrefabs.Count} prefabs with old Interactable/InteractableBase references.");
|
|
}
|
|
|
|
private bool PrefabHasOldInteractableReference(string assetPath)
|
|
{
|
|
try
|
|
{
|
|
string fullPath = Path.GetFullPath(assetPath);
|
|
string content = File.ReadAllText(fullPath);
|
|
|
|
// Look for GUID of Interactable script (11500000 is MonoBehaviour type)
|
|
// We're looking for the script reference pattern in YAML
|
|
// Pattern: m_Script: {fileID: 11500000, guid: SCRIPT_GUID, type: 3}
|
|
|
|
// Check if content contains "Interactable" class name references
|
|
// This is a simple text search - if the YAML contains these class names, it likely references them
|
|
if (content.Contains("InteractableBase") ||
|
|
(content.Contains("Interactable") && !content.Contains("OneClickInteraction")))
|
|
{
|
|
// Additional check: Look for MonoBehaviour blocks with missing scripts (fileID: 0)
|
|
if (Regex.IsMatch(content, @"m_Script:\s*\{fileID:\s*0\}"))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
// Check for direct class name matches in script references
|
|
if (Regex.IsMatch(content, @"m_Name:\s*(Interactable|InteractableBase)"))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
catch (System.Exception ex)
|
|
{
|
|
Debug.LogWarning($"Error scanning {assetPath}: {ex.Message}");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private void CleanAllPrefabs()
|
|
{
|
|
if (!EditorUtility.DisplayDialog("Confirm Cleanup",
|
|
$"This will remove old Interactable/InteractableBase references from {problematicPrefabs.Count} prefabs.\n\nThis cannot be undone (unless you use version control).\n\nContinue?",
|
|
"Yes, Clean", "Cancel"))
|
|
{
|
|
return;
|
|
}
|
|
|
|
int cleanedCount = 0;
|
|
|
|
for (int i = 0; i < problematicPrefabs.Count; i++)
|
|
{
|
|
string path = problematicPrefabs[i];
|
|
|
|
EditorUtility.DisplayProgressBar("Cleaning Prefabs",
|
|
$"Cleaning {i + 1}/{problematicPrefabs.Count}: {Path.GetFileName(path)}",
|
|
(float)i / problematicPrefabs.Count);
|
|
|
|
if (CleanPrefabFile(path))
|
|
{
|
|
cleanedCount++;
|
|
}
|
|
}
|
|
|
|
EditorUtility.ClearProgressBar();
|
|
AssetDatabase.Refresh();
|
|
|
|
Debug.Log($"<color=green>[Cleanup Complete]</color> Cleaned {cleanedCount} prefabs.");
|
|
|
|
// Re-scan to update the list
|
|
ScanPrefabs();
|
|
}
|
|
|
|
private void CleanSinglePrefab(string assetPath)
|
|
{
|
|
if (CleanPrefabFile(assetPath))
|
|
{
|
|
Debug.Log($"<color=green>[Cleaned]</color> {assetPath}");
|
|
AssetDatabase.Refresh();
|
|
|
|
// Re-scan to update the list
|
|
ScanPrefabs();
|
|
}
|
|
}
|
|
|
|
private bool CleanPrefabFile(string assetPath)
|
|
{
|
|
try
|
|
{
|
|
string fullPath = Path.GetFullPath(assetPath);
|
|
string content = File.ReadAllText(fullPath);
|
|
string originalContent = content;
|
|
|
|
// Pattern 1: Remove entire MonoBehaviour component blocks with missing scripts (fileID: 0)
|
|
// This removes the component header and all its properties until the next component or end
|
|
string missingScriptPattern = @"--- !u!114 &\d+\r?\nMonoBehaviour:(?:\r?\n(?!---).+)*?\r?\n m_Script: \{fileID: 0\}(?:\r?\n(?!---).+)*";
|
|
content = Regex.Replace(content, missingScriptPattern, "", RegexOptions.Multiline);
|
|
|
|
// Pattern 2: Remove MonoBehaviour blocks that explicitly reference InteractableBase or Interactable
|
|
// This is more aggressive and targets the class name directly
|
|
string interactablePattern = @"--- !u!114 &\d+\r?\nMonoBehaviour:(?:\r?\n(?!---).+)*?\r?\n m_Name: (?:Interactable|InteractableBase)(?:\r?\n(?!---).+)*";
|
|
content = Regex.Replace(content, interactablePattern, "", RegexOptions.Multiline);
|
|
|
|
if (content != originalContent)
|
|
{
|
|
// Clean up any double blank lines that might have been created
|
|
content = Regex.Replace(content, @"(\r?\n){3,}", "\n\n");
|
|
|
|
File.WriteAllText(fullPath, content);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
catch (System.Exception ex)
|
|
{
|
|
Debug.LogError($"Error cleaning {assetPath}: {ex.Message}");
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|