#if VISUALSCRIPTING_1_8_OR_NEWER
using System;
using System.Collections.Generic;
using System.Text;
using Unity.VisualScripting;
using UnityEngine.SubsystemsImplementation;
using UnityEngine.XR.ARSubsystems;
namespace UnityEngine.XR.ARFoundation.VisualScripting
{
///
/// Outputs all trackables managed by the input ARTrackableManager using its
/// property.
///
/// The AR Trackable Manager type.
/// The tracking subsystem type.
/// The subsystem descriptor type.
/// The subsystem provider type.
/// The session relative data type.
/// The AR Trackable type.
///
/// is not a serializable type, therefore we need a custom unit to
/// copy the contents into a serializable List to use this data in a visual scripting context.
///
public abstract class GetTrackablesUnit
: Unit
where TManager : ARTrackableManager
where TSubsystem : TrackingSubsystem, new()
where TSubsystemDescriptor : SubsystemDescriptorWithProvider
where TProvider : SubsystemProvider
where TSessionRelativeData : struct, ITrackable
where TTrackable : ARTrackable
{
const string k_ManagerInPortLabel = "Manager";
// Used by GetTrackablesUnitDescriptor in the Editor assembly
internal const string k_TrackablesInPortLabel = "List";
static bool s_IsFirstFrame = true;
StringBuilder m_LogBuilder = new();
///
/// Flow input.
///
[DoNotSerialize]
[PortLabelHidden]
public ControlInput flowIn { get; private set; }
///
/// Flow output.
///
[DoNotSerialize]
[PortLabelHidden]
public ControlOutput flowOut { get; private set; }
///
/// AR Trackable Manager input.
///
[DoNotSerialize]
[PortLabel(k_ManagerInPortLabel)]
public ValueInput managerIn { get; private set; }
[DoNotSerialize]
[PortLabel(k_TrackablesInPortLabel)]
public ValueInput trackablesIn { get; private set; }
///
/// Outputs a .
///
[DoNotSerialize]
[PortLabel(k_TrackablesInPortLabel)]
public ValueOutput trackablesOut { get; private set; }
protected override void Definition()
{
flowIn = ControlInput(nameof(flowIn), ProcessFlow);
flowOut = ControlOutput(nameof(flowOut));
managerIn = ValueInput(nameof(managerIn));
trackablesIn = ValueInput>(nameof(trackablesIn));
trackablesOut = ValueOutput>(nameof(trackablesOut));
Requirement(managerIn, flowIn);
Requirement(trackablesIn, flowIn);
Succession(flowIn, flowOut);
Assignment(flowIn, trackablesOut);
}
ControlOutput ProcessFlow(Flow flow)
{
var manager = flow.GetValue(managerIn) as ARTrackableManager;
if (manager == null)
{
manager = Object.FindAnyObjectByType>();
}
if (manager == null)
throw new InvalidOperationException(
$"Attempted to execute the {graph.title} Visual Scripting graph, which requires an active and enabled {typeof(TManager)} in your scene, but none was found.");
if (!managerIn.hasValidConnection && s_IsFirstFrame)
{
if (managerIn.hasAnyConnection)
m_LogBuilder.Append($"{k_ManagerInPortLabel} Input Port on {GetType().Name} in {graph.title} graph has an invalid connection.");
else
m_LogBuilder.Append($"{k_ManagerInPortLabel} Input Port on {GetType().Name} in {graph.title} graph is disconnected.");
m_LogBuilder.Append(" AR Foundation searched and found a valid manager in your scene to fill this dependency," +
" but for improved performance you should ensure that this port connection is valid.");
Debug.LogWarning(m_LogBuilder.ToString());
m_LogBuilder.Clear();
}
if (flow.GetValue(trackablesIn) is not List trackables)
{
trackables = new List();
if (s_IsFirstFrame)
{
if (trackablesIn.hasAnyConnection)
m_LogBuilder.Append($"{k_TrackablesInPortLabel} Input Port on {GetType().Name} in {graph.title} graph has an invalid connection.");
else
m_LogBuilder.Append($"{k_TrackablesInPortLabel} Input Port on {GetType().Name} in {graph.title} graph is disconnected.");
m_LogBuilder.Append(" AR Foundation allocated a new list to use as output, but this memory will require garbage collection." +
" For improved performance you should ensure that this port connection is valid.");
}
}
s_IsFirstFrame = false;
trackables.Clear();
foreach (var t in manager.trackables)
{
trackables.Add(t);
}
flow.SetValue(trackablesOut, trackables);
return flowOut;
}
}
}
#endif // VISUALSCRIPTING_1_8_OR_NEWER