#if CINEMACHINE_PHYSICS || CINEMACHINE_PHYSICS_2D
using UnityEngine;
using UnityEditor;
using UnityEngine.Playables;
using UnityEditor.UIElements;
using UnityEngine.UIElements;
namespace Unity.Cinemachine.Editor
{
[CustomEditor(typeof(CinemachineTriggerAction))]
class CinemachineTriggerActionEditor : UnityEditor.Editor
{
CinemachineTriggerAction Target => target as CinemachineTriggerAction;
public override VisualElement CreateInspectorGUI()
{
var ux = new VisualElement();
ux.Add(new PropertyField(serializedObject.FindProperty(() => Target.LayerMask)));
ux.Add(new PropertyField(serializedObject.FindProperty(() => Target.WithTag)));
ux.Add(new PropertyField(serializedObject.FindProperty(() => Target.WithoutTag)));
var row = ux.AddChild(InspectorUtility.PropertyRow(serializedObject.FindProperty(() => Target.SkipFirst), out _));
var repeatingProp = serializedObject.FindProperty(() => Target.Repeating);
row.Contents.AddChild(new Toggle { text = repeatingProp.displayName, style = { marginLeft = 5 }}).BindProperty(repeatingProp);
AddActionSettings(ux, serializedObject.FindProperty(() => Target.OnObjectEnter));
AddActionSettings(ux, serializedObject.FindProperty(() => Target.OnObjectExit));
return ux;
}
void AddActionSettings(VisualElement ux, SerializedProperty property)
{
CinemachineTriggerAction.ActionSettings def = new(); // to access name strings
ux.AddSpace();
var foldout = ux.AddChild(new Foldout { text = $"{property.displayName}" });
foldout.BindProperty(property);
var actionProp = property.FindPropertyRelative(() => def.Action);
foldout.Add(new PropertyField(actionProp));
var targetProp = property.FindPropertyRelative(() => def.Target);
var target = foldout.AddChild(new PropertyField(targetProp));
var boostAmount = foldout.AddChild(new PropertyField(property.FindPropertyRelative(() => def.BoostAmount)));
#if CINEMACHINE_TIMELINE
var timelineRow = foldout.AddChild(InspectorUtility.PropertyRow(property.FindPropertyRelative(() => def.StartTime), out _));
timelineRow.Contents.AddChild(new Label { text = " s", tooltip = "Seconds", style = { alignSelf = Align.Center }});
timelineRow.Contents.AddChild(new PropertyField(
property.FindPropertyRelative(() => def.Mode), "") { style = { flexGrow = 1 }});
#endif
var row = foldout.AddChild(new InspectorUtility.LeftRightRow());
var helpMessage = row.Right.AddChild(new HelpBox("Help text", HelpBoxMessageType.Warning));
foldout.Add(new PropertyField(property.FindPropertyRelative(() => def.Event)) { style = { marginTop = 5 }});
foldout.TrackAnyUserActivity(() =>
{
if (Target == null)
return; // object deleted
var targetObject = targetProp.objectReferenceValue;
var action = (CinemachineTriggerAction.ActionSettings.ActionModes)actionProp.intValue;
bool isEventOnly = action == CinemachineTriggerAction.ActionSettings.ActionModes.EventOnly;
target.SetVisible(!isEventOnly);
string helpText = isEventOnly || targetObject != null
? string.Empty : "No action will be taken because target is not valid";
boostAmount.SetVisible(action == CinemachineTriggerAction.ActionSettings.ActionModes.PriorityBoost);
#if CINEMACHINE_TIMELINE
bool isTimeline = action == CinemachineTriggerAction.ActionSettings.ActionModes.Play
|| action == CinemachineTriggerAction.ActionSettings.ActionModes.Stop;
timelineRow.SetVisible(isTimeline);
if (isTimeline && !HasComponent(targetObject) && !HasComponent(targetObject))
helpText = "Target must have a PlayableDirector or Animator in order to Play/Stop";
#endif
if (string.IsNullOrEmpty(helpText))
{
switch (action)
{
default: break;
case CinemachineTriggerAction.ActionSettings.ActionModes.PriorityBoost:
if (!HasComponent(targetObject))
helpText = "Target must be a Cinemachine Camera in order to boost priority";
break;
case CinemachineTriggerAction.ActionSettings.ActionModes.Enable:
case CinemachineTriggerAction.ActionSettings.ActionModes.Disable:
if (targetObject is not Behaviour)
helpText = "Target must be a Behaviour in order to Enable/Disable";
break;
}
}
helpMessage.text = helpText;
helpMessage.SetVisible(!string.IsNullOrEmpty(helpText));
});
static bool HasComponent(Object obj) where T : Component
{
if (obj is T)
return true;
var go = obj as GameObject;
if (go == null && obj is Component c)
go = c.gameObject;
if (go != null)
return go.TryGetComponent(out _);
return false;
}
}
}
}
#endif