Files
Echo/Assets/_Project/Scripts/Camera Control/Editor/CameraWaypointSwitcherEditor.cs
T

210 lines
5.9 KiB
C#
Raw Normal View History

2026-07-08 19:53:15 +08:00
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using Test_2022.CameraControl;
[CustomEditor(typeof(CameraWaypointSwitcher))]
[CanEditMultipleObjects]
public sealed class CameraWaypointSwitcherEditor : Editor
{
SerializedProperty targetProp;
SerializedProperty waypointsProp;
void OnEnable()
{
targetProp = serializedObject.FindProperty("target");
waypointsProp = serializedObject.FindProperty("waypoints");
}
public override void OnInspectorGUI()
{
serializedObject.Update();
DrawDefaultInspector();
serializedObject.ApplyModifiedProperties();
EditorGUILayout.Space(10);
using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox))
{
EditorGUILayout.LabelField("Tools", EditorStyles.boldLabel);
using (new EditorGUILayout.HorizontalScope())
{
if (GUILayout.Button("Use Main Camera"))
UseMainCamera();
if (GUILayout.Button("Create Point From Target"))
CreatePointFromTarget();
}
using (new EditorGUILayout.HorizontalScope())
{
if (GUILayout.Button("Add Selected"))
AddSelected(false);
if (GUILayout.Button("Add Selected (+Children)"))
AddSelected(true);
}
using (new EditorGUILayout.HorizontalScope())
{
if (GUILayout.Button("Remove Nulls"))
RemoveNulls();
if (GUILayout.Button("Clear Points"))
ClearPoints();
}
}
EditorGUILayout.Space(10);
using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox))
{
EditorGUILayout.LabelField("Runtime", EditorStyles.boldLabel);
if (!Application.isPlaying)
EditorGUILayout.HelpBox("进入 Play 模式后才会执行点位切换与摇晃。Transition Mode = Instant 为瞬切,Tween 为平滑移动。Shake Mode = Handheld 为手持式平滑摇晃。", MessageType.Info);
using (new EditorGUI.DisabledScope(!Application.isPlaying))
{
using (new EditorGUILayout.HorizontalScope())
{
if (GUILayout.Button("Start"))
StartPlayback();
if (GUILayout.Button("Stop (Restore)"))
StopPlayback(true);
if (GUILayout.Button("Stop (No Restore)"))
StopPlayback(false);
}
}
}
}
void UseMainCamera()
{
var cam = Camera.main;
if (cam == null)
return;
foreach (var t in targets)
{
Undo.RecordObject(t, "Assign Main Camera");
var sw = (CameraWaypointSwitcher)t;
var so = new SerializedObject(sw);
so.FindProperty("target").objectReferenceValue = cam.transform;
so.ApplyModifiedPropertiesWithoutUndo();
EditorUtility.SetDirty(sw);
MarkSceneDirty(sw);
}
serializedObject.Update();
}
void CreatePointFromTarget()
{
if (targetProp == null)
return;
var target = targetProp.objectReferenceValue as Transform;
if (target == null)
return;
var go = new GameObject("CamPoint");
Undo.RegisterCreatedObjectUndo(go, "Create Camera Point");
go.transform.SetPositionAndRotation(target.position, target.rotation);
AddPointToAll(go.transform, -1f);
Selection.activeGameObject = go;
}
void AddSelected(bool includeChildren)
{
var selected = Selection.gameObjects;
if (selected == null || selected.Length == 0)
return;
var points = new List<Transform>();
for (var i = 0; i < selected.Length; i++)
{
var go = selected[i];
if (go == null)
continue;
if (includeChildren)
points.AddRange(go.GetComponentsInChildren<Transform>(true));
else
points.Add(go.transform);
}
for (var i = 0; i < points.Count; i++)
AddPointToAll(points[i], -1f);
}
void AddPointToAll(Transform point, float holdSeconds)
{
if (point == null)
return;
foreach (var t in targets)
{
var sw = (CameraWaypointSwitcher)t;
Undo.RecordObject(sw, "Add Waypoint");
sw.AddWaypoint(point, holdSeconds);
EditorUtility.SetDirty(sw);
MarkSceneDirty(sw);
}
}
void RemoveNulls()
{
foreach (var t in targets)
{
var sw = (CameraWaypointSwitcher)t;
Undo.RecordObject(sw, "Remove Null Waypoints");
sw.RemoveNullWaypoints();
EditorUtility.SetDirty(sw);
MarkSceneDirty(sw);
}
}
void ClearPoints()
{
foreach (var t in targets)
{
var sw = (CameraWaypointSwitcher)t;
Undo.RecordObject(sw, "Clear Waypoints");
sw.ClearWaypoints();
EditorUtility.SetDirty(sw);
MarkSceneDirty(sw);
}
}
void StartPlayback()
{
foreach (var t in targets)
{
var sw = (CameraWaypointSwitcher)t;
sw.StartPlayback();
}
}
void StopPlayback(bool restore)
{
foreach (var t in targets)
{
var sw = (CameraWaypointSwitcher)t;
sw.StopPlayback(restore);
}
}
static void MarkSceneDirty(CameraWaypointSwitcher sw)
{
if (Application.isPlaying)
return;
if (!sw.gameObject.scene.IsValid())
return;
EditorSceneManager.MarkSceneDirty(sw.gameObject.scene);
}
}