using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace Unity.VisualScripting
{
public sealed class Assignment
{
public Assignment(Member assigner, Type assigneeType)
{
Ensure.That(nameof(assigneeType)).IsNotNull(assigneeType);
this.assigner = assigner;
var assignsAttribute = assigner.info.GetAttribute<AssignsAttribute>();
assignee = new Member(assigneeType, assignsAttribute?.memberName ?? assigner.name.FirstCharacterToLower());
requiresAPI = assigner.info.HasAttribute<RequiresUnityAPIAttribute>();
cache = assignsAttribute?.cache ?? true;
assigner.Prewarm();
assignee.Prewarm();
}
public Member assigner { get; }
public Member assignee { get; }
public bool requiresAPI { get; }
public bool cache { get; }
public void Run(object assigner, object assignee)
{
if (requiresAPI)
{
UnityAPI.Async(() => _Run(assigner, assignee));
}
else
{
_Run(assigner, assignee);
}
}
private void _Run(object assigner, object assignee)
{
var oldValue = this.assignee.Get(assignee);
var newValue = ConversionUtility.Convert(this.assigner.Invoke(assigner), this.assignee.type);
this.assignee.Set(assignee, newValue);
if (!Equals(oldValue, newValue))
{
if (assigner is IAssigner _assigner)
{
_assigner.ValueChanged();
}
}
}
public static IEnumerable<Assignment> Fetch(Type descriptorType, Type descriptionType)
{
var bindingFlags = BindingFlags.Instance |
BindingFlags.Public |
BindingFlags.NonPublic;
return descriptorType.GetMethods(bindingFlags)
.Where(m => m.HasAttribute<AssignsAttribute>())
.Select(m => new Assignment(m.ToManipulator(descriptorType), descriptionType));
}
}
}