Files
Fishing2/Assets/Procedural Worlds/GeNa/Scripts/Editor/GeNaManagerSceneEditor.cs
2026-02-28 12:43:44 +08:00

333 lines
11 KiB
C#

// Engine
using System.Collections.Generic;
using System.IO;
using System.Linq;
using PWCommon5;
using UnityEngine;
// Editor
using UnityEditor;
using UnityEditorInternal;
// Procedural Worlds
namespace GeNa.Core
{
[CustomEditor(typeof(GeNaManager))]
public class GeNaManagerSceneEditor : GeNaEditor
{
#region Variables
private GeNaManager m_manager;
private PhysicsSimulator m_physicsSimulator;
private ReorderableList m_objectsToIgnoreList;
#endregion
#region Properties
private List<Rigidbody> objectsToIgnore => m_physicsSimulator.m_objectsToIgnore;
#endregion
#region Methods
#region Unity
protected void OnEnable()
{
#region Initialization
// If there isn't any Editor Utils Initialized
if (m_editorUtils == null)
// Get editor utils for this
m_editorUtils = PWApp.GetEditorUtils(this, null, null, null);
// If there is no target associated with Editor Script
if (target == null)
// Exit the method
return;
// Get target Spline
m_manager = (GeNaManager)target;
m_manager.Initialize();
m_physicsSimulator = m_manager.PhysicsSimulator;
CreateExtensionList();
#endregion
}
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
m_editorUtils.GUINewsHeader();
#region Panel
m_editorUtils.Panel("GeneralPanel", ManagerPanel, true);
m_editorUtils.Panel("SpawnCallPanel", SpawnCallPanel, true);
m_editorUtils.Panel("PhysicsSimulatorPanel", PhysicsSimulatorPanel, true);
#endregion
m_editorUtils.GUINewsFooter(false);
}
private static int SPLINE_QUAD_SIZE = 25;
private static int SPLINE_STYLE_QUAD_SIZE = 15;
public static bool Button(Vector2 position, Texture2D texture2D, Color color)
{
Vector2 quadSize = new Vector2(SPLINE_QUAD_SIZE, SPLINE_QUAD_SIZE);
Vector2 halfQuadSize = quadSize * .5f;
Rect buttonRect = new Rect(position - halfQuadSize, quadSize);
Color oldColor = GUI.color;
GUI.color = color;
bool result = GUI.Button(buttonRect, texture2D, GUIStyle.none);
GUI.color = oldColor;
return result;
}
public static bool Button(Vector2 position, GUIStyle style, Color color)
{
Vector2 quadSize = new Vector2(SPLINE_STYLE_QUAD_SIZE, SPLINE_STYLE_QUAD_SIZE);
Vector2 halfQuadSize = quadSize * .5f;
Rect buttonRect = new Rect(position - halfQuadSize, quadSize);
Color oldColor = GUI.color;
GUI.color = color;
bool result = GUI.Button(buttonRect, GUIContent.none, style);
GUI.color = oldColor;
return result;
}
private SpawnCall m_selectedSpawnCall = null;
public override void OnSceneGUI()
{
Initialize();
if (m_selectedSpawnCall != null)
{
switch (Tools.current)
{
case Tool.Rotate:
{
Vector3 point = m_selectedSpawnCall.Location;
var rotation = Quaternion.Euler(m_selectedSpawnCall.Rotation);
var result = Handles.RotationHandle(rotation, point);
// place a handle on the node and manage m_position change
if (result != rotation)
{
m_selectedSpawnCall.Rotation = result.eulerAngles;
m_selectedSpawnCall.UpdateEntities();
}
break;
}
default:
{
var rotation = Quaternion.Euler(m_selectedSpawnCall.Rotation);
Vector3 point = m_selectedSpawnCall.Location;
Vector3 result = Handles.PositionHandle(point, rotation);
// place a handle on the node and manage m_position change
if (result != point)
{
m_selectedSpawnCall.Location = result;
m_selectedSpawnCall.UpdateEntities();
}
}
break;
}
}
Handles.BeginGUI();
var spawnCalls = m_manager.ActiveSpawnCalls;
foreach (var spawnCall in spawnCalls)
{
if (spawnCall == null)
continue;
Vector2 guiPos = HandleUtility.WorldToGUIPoint(spawnCall.Location);
if (Button(guiPos, Styles.knobTexture2D, Color.green))
{
m_selectedSpawnCall = spawnCall;
break;
}
}
Handles.EndGUI();
}
#endregion
#region Panel
private void ManagerPanel(bool helpEnabled)
{
// m_editorUtils.Text("WelcomeToGeNaManager");
if (m_editorUtils.Button("ShowGeNaManager"))
{
ShowGeNaManager();
}
}
private void SpawnCallPanel(bool helpEnabled)
{
if (m_editorUtils.Button("ClearEmptySpawnCalls"))
{
m_manager.ClearEmptySpawnCalls();
}
if (m_selectedSpawnCall == null)
return;
EditorGUILayout.LabelField(m_selectedSpawnCall.Location.ToString());
EditorGUI.BeginChangeCheck();
{
m_selectedSpawnCall.AlignChildrenToRotation = EditorGUILayout.Toggle("Align Children",
m_selectedSpawnCall.AlignChildrenToRotation);
m_selectedSpawnCall.ConformChildrenToSlope = EditorGUILayout.Toggle("Conform Children",
m_selectedSpawnCall.ConformChildrenToSlope);
m_selectedSpawnCall.SnapChildrenToGround =
EditorGUILayout.Toggle("Snap Children", m_selectedSpawnCall.SnapChildrenToGround);
}
if (EditorGUI.EndChangeCheck())
{
m_selectedSpawnCall.UpdateEntities();
}
}
private void PhysicsSimulatorPanel(bool helpEnabled)
{
if (DrawRigidGUI(out var rigidbodies))
{
objectsToIgnore.AddRange(rigidbodies);
}
GUILayout.Space(5f);
m_objectsToIgnoreList.DoLayoutList();
}
#endregion
#region Objects To Ignore List
private void CreateExtensionList()
{
m_objectsToIgnoreList = new ReorderableList(objectsToIgnore,
typeof(GeNaSplineExtension), true, true, true, true)
{
elementHeightCallback = OnElementHeightExtensionListEntry,
drawElementCallback = DrawExtensionListElement,
drawHeaderCallback = DrawExtensionListHeader,
onAddCallback = OnAddExtensionListEntry,
onRemoveCallback = OnRemoveExtensionListEntry,
onReorderCallback = OnReorderExtensionList
};
}
private void OnReorderExtensionList(ReorderableList reorderableList)
{
//Do nothing, changing the order does not immediately affect anything in the stamper
}
private void OnRemoveExtensionListEntry(ReorderableList reorderableList)
{
int indexToRemove = reorderableList.index;
objectsToIgnore.RemoveAt(indexToRemove);
if (indexToRemove >= objectsToIgnore.Count)
indexToRemove = objectsToIgnore.Count - 1;
reorderableList.index = indexToRemove;
}
private void OnAddExtensionListEntry(ReorderableList reorderableList)
{
objectsToIgnore.Add(null);
reorderableList.index = objectsToIgnore.Count - 1;
}
private void DrawExtensionListHeader(Rect rect)
{
int oldIndent = EditorGUI.indentLevel;
EditorGUI.indentLevel = 0;
EditorGUI.LabelField(rect, "Rigidbodies");
EditorGUI.indentLevel = oldIndent;
}
private void DrawExtensionListElement(Rect rect, int index, bool isActive, bool isFocused)
{
objectsToIgnore[index] = (Rigidbody)EditorGUI.ObjectField(
new Rect(rect.x, rect.y + 1f, rect.width, EditorGUIUtility.singleLineHeight),
objectsToIgnore[index], typeof(Rigidbody), true);
}
private float OnElementHeightExtensionListEntry(int index)
{
return OnElementHeight();
}
public float OnElementHeight()
{
return EditorGUIUtility.singleLineHeight + 4f;
}
#endregion
#region Utilities
private void ShowGeNaManager()
{
GeNaManagerEditor.MenuGeNaMainWindow();
}
/// <summary>
/// Handle drop area for new objects
/// </summary>
public bool DrawRigidGUI(out List<Rigidbody> result)
{
result = new List<Rigidbody>();
// Ok - set up for drag and drop
Event evt = Event.current;
Rect dropArea = GUILayoutUtility.GetRect(0.0f, 50.0f, GUILayout.ExpandWidth(true));
string dropMsg = "Drop Rigidbodies Here..."; //m_editorUtils.GetTextValue("Add proto drop box msg");
GUI.Box(dropArea, dropMsg, Styles.gpanel);
if (evt.type == EventType.DragPerform || evt.type == EventType.DragUpdated)
{
if (!dropArea.Contains(evt.mousePosition))
return false;
DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
if (evt.type == EventType.DragPerform)
{
DragAndDrop.AcceptDrag();
Dictionary<int, Rigidbody> rigidCollection = new Dictionary<int, Rigidbody>();
// Handle game objects / prefabs
foreach (Object draggedObject in DragAndDrop.objectReferences)
{
if (draggedObject is GameObject go)
{
var rigidbodies = go.GetComponentsInChildren<Rigidbody>();
foreach (var rigid in rigidbodies)
{
var instanceID = rigid.GetInstanceID();
if (rigidCollection.ContainsKey(instanceID))
continue;
rigidCollection.Add(instanceID, rigid);
}
}
}
if (rigidCollection.Count > 0)
{
result = rigidCollection.Values.ToList();
}
return true;
}
}
return false;
}
#endregion
#endregion
}
}