Files
Cielonos/Assets/Opsive/BehaviorDesigner/Add-Ons/SensesPack/Editor/DetectionModesAttributeControl.cs
SoulliesOfficial ef7b479712 initial
2025-11-25 08:19:33 -05:00

178 lines
8.3 KiB
C#

/// ---------------------------------------------
/// Movement Pack for Behavior Designer Pro
/// Copyright (c) Opsive. All Rights Reserved.
/// https://www.opsive.com
/// ---------------------------------------------
namespace Opsive.BehaviorDesigner.AddOns.SensesPack.Editor
{
using Opsive.BehaviorDesigner.AddOns.SensesPack.Runtime.Sensors;
using Opsive.BehaviorDesigner.Editor;
using Opsive.Shared.Editor.UIElements;
using Opsive.Shared.Editor.UIElements.Controls;
using Opsive.Shared.Editor.UIElements.Controls.Attributes;
using Opsive.Shared.Utility;
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
/// <summary>
/// Implements AttributeControlBase for the DetectionModeListAttribute type.
/// </summary>
[ControlType(typeof(DetectionModeListAttribute))]
public class DetectionModesAttributeControl : AttributeControlBase
{
/// <summary>
/// The DetectionModeView displays the contents of the DetectionMode.
/// </summary>
public class DetectionModeView : VisualElement
{
protected UnityEngine.Object m_UnityObject;
protected DetectionMode[] m_DetectionModes;
protected Func<object, bool> m_OnChangeEvent;
private List<Type> m_DetectionModeTypes = new List<Type>();
private List<string> m_DetectionModeTypeNames = new List<string>();
private ReorderableList m_ReorderableList;
private int m_SelectedIndex = 0;
private VisualElement m_DetectionModeContainer;
/// <summary>
/// DetectionModeView constructor.
/// </summary>
/// <param name="unityObject">A reference to the owning Unity Object.</param>
/// <param name="detectionModes">The DetectionModes being drawn.</param>
/// <param name="onChangeEvent">An event that is sent when the value changes. Returns false if the control cannot be changed.</param>
public DetectionModeView(UnityEngine.Object unityObject, DetectionMode[] detectionModes, Func<object, bool> onChangeEvent)
{
m_UnityObject = unityObject;
m_DetectionModes = detectionModes;
m_OnChangeEvent = onChangeEvent;
var graphWindow = BehaviorDesignerWindow.Instance;
m_ReorderableList = new ReorderableList(m_DetectionModes, (VisualElement parent, int index) =>
{
parent.Add(new Label());
}, (VisualElement parent, int index) =>
{
(parent.ElementAt(0) as Label).text = m_DetectionModes[index].GetType().Name;
}, (VisualElement parent) =>
{
parent.Add(new Label("Detection Modes"));
}, (int index) =>
{
ShowSelectedDetectionMode(index);
}, () => // Add.
{
FilterWindow.ShowFilterWindow(graphWindow, new SearchWindowContext(graphWindow.position.position + m_ReorderableList.AddButton.worldBound.position),
new Type[] { typeof(DetectionMode) }, FilterWindow.FilterType.Class, "Detection Mode",
false, null, OnAdd, (Type type) => { return typeof(DetectionMode).IsAssignableFrom(type); });
}, (int index) => // Remove.
{
ArrayUtility.RemoveAt(ref m_DetectionModes, index);
m_ReorderableList.EnableRemove = m_DetectionModes.Length > 1 && !Application.isPlaying;
m_ReorderableList.Refresh(m_DetectionModes);
m_OnChangeEvent(m_DetectionModes);
m_SelectedIndex = Mathf.Clamp(m_SelectedIndex - 1, 0, m_DetectionModes.Length - 1);
ShowSelectedDetectionMode(m_SelectedIndex);
}, (int fromIndex, int toIndex) => // Reorder.
{
m_OnChangeEvent(m_DetectionModes);
if (m_SelectedIndex == fromIndex) {
ShowSelectedDetectionMode(toIndex);
}
});
m_ReorderableList.EnableAdd = m_ReorderableList.EnableReorder = !Application.isPlaying;
m_ReorderableList.EnableRemove = (m_DetectionModes != null && m_DetectionModes.Length > 1) && !Application.isPlaying;
Add(m_ReorderableList);
// Show any detection mode fields.
m_DetectionModeContainer = new VisualElement();
m_DetectionModeContainer.style.marginBottom = 4;
m_DetectionModeContainer.style.display = DisplayStyle.Flex;
Add(m_DetectionModeContainer);
ShowSelectedDetectionMode(m_SelectedIndex);
if (m_DetectionModes != null && m_SelectedIndex < m_DetectionModes.Length) {
m_ReorderableList.SelectedIndex = m_SelectedIndex;
}
}
/// <summary>
/// Adds a new detection mode to the array.
/// </summary>
/// <param name="selectedObject">The selected task type.</param>
/// <param name="baseType">The base type that was used to find the element.</param>
/// <param name="windowPosition">The position of the FilterWindow.</param>
private void OnAdd(object selectedObject, Type baseType, Vector2 windowPosition)
{
if (selectedObject == null) {
return;
}
if (m_DetectionModes == null) {
m_DetectionModes = new DetectionMode[1];
} else {
Array.Resize(ref m_DetectionModes, m_DetectionModes.Length + 1);
}
m_DetectionModes[m_DetectionModes.Length - 1] = Activator.CreateInstance((Type)selectedObject) as DetectionMode;
m_ReorderableList.Refresh(m_DetectionModes);
m_ReorderableList.SelectedIndex = m_DetectionModes.Length - 1;
m_ReorderableList.EnableRemove = m_DetectionModes.Length > 1 && !Application.isPlaying;
m_OnChangeEvent(m_DetectionModes);
}
/// <summary>
/// Shows the selected detection mode.
/// </summary>
/// <param name="index">The index of the detection mode within the detection mode array.</param>
private void ShowSelectedDetectionMode(int index)
{
m_SelectedIndex = index;
m_DetectionModeContainer.Clear();
if (m_DetectionModes == null || m_DetectionModes.Length <= m_SelectedIndex) {
return;
}
var label = new Label();
label.enableRichText = true;
label.style.marginLeft = 3;
label.style.unityTextAlign = TextAnchor.MiddleCenter;
label.text = $"<font-weight=700><size=+2>{m_DetectionModes[index].GetType().Name}</size></font-weight>";
label.tooltip = m_DetectionModes[index].GetType().FullName;
m_DetectionModeContainer.Add(label);
FieldInspectorView.AddFields(m_UnityObject, m_DetectionModes[index], MemberVisibility.Public, m_DetectionModeContainer, (object obj) =>
{
m_DetectionModes[index] = obj as DetectionMode;
m_OnChangeEvent?.Invoke(m_DetectionModes);
});
}
}
/// <summary>
/// Does the control use a label?
/// </summary>
public override bool UseLabel { get { return false; } }
/// <summary>
/// Does the attribute override the type control?
/// </summary>
public override bool OverrideTypeControl => true;
/// <summary>
/// Returns the control that should be used for the specified AttributeControlType.
/// </summary>
/// <param name="input">The input to the control.</param>
/// <returns>The created control.</returns>
protected override VisualElement GetControl(AttributeControlInput input)
{
return new DetectionModeView(input.UnityObject, input.Value as DetectionMode[], input.OnChangeEvent);
}
}
}