UnitTests/Binder.cs
using Sandbox.MovieMaker.Compiled;
using Sandbox.MovieMaker.Properties;
namespace Sandbox.MovieMaker.Test;
#nullable enable
[TestClass]
public sealed class BinderTests : SceneTests
{
/// <summary>
/// Game object tracks without an explicit binding must auto-bind to root objects
/// in the current scene with a matching name.
/// </summary>
[TestMethod]
public void BindRootGameObjectMatchingName()
{
var exampleObject = new GameObject( true, "Example" );
var exampleTrack = MovieClip.RootGameObject( exampleObject.Name );
var target = TrackBinder.Default.Get( exampleTrack );
Assert.IsTrue( target.IsBound );
Assert.AreEqual( exampleObject, target.Value );
}
/// <summary>
/// Don't auto-bind to a root object with a different name.
/// </summary>
[TestMethod]
public void BindRootGameObjectNoMatchingName()
{
var exampleObject = new GameObject( true, "Examble" );
var exampleTrack = MovieClip.RootGameObject( "Example" );
var target = TrackBinder.Default.Get( exampleTrack );
Assert.IsFalse( target.IsBound );
}
/// <summary>
/// We can bind to a game object if it changes name to match the track.
/// </summary>
[TestMethod]
public void LateBindRootGameObjectMatchingName()
{
var exampleObject = new GameObject( true, "Examble" );
var exampleTrack = MovieClip.RootGameObject( "Example" );
var target = TrackBinder.Default.Get( exampleTrack );
Assert.IsFalse( target.IsBound );
exampleObject.Name = "Example";
Assert.IsTrue( target.IsBound );
Assert.AreEqual( exampleObject, target.Value );
}
/// <summary>
/// Bindings will persist, even if the bound object changes name.
/// </summary>
[TestMethod]
public void StickyBinding()
{
var exampleObject = new GameObject( true, "Example" );
var exampleTrack = MovieClip.RootGameObject( exampleObject.Name );
var target = TrackBinder.Default.Get( exampleTrack );
Assert.IsTrue( target.IsBound );
Assert.AreEqual( exampleObject, target.Value );
exampleObject.Name = "Examble";
Assert.IsTrue( target.IsBound );
Assert.AreEqual( exampleObject, target.Value );
target.Reset();
Assert.IsFalse( target.IsBound );
}
/// <summary>
/// We can manually bind a track to a particular object.
/// </summary>
[TestMethod]
public void ExplicitBinding()
{
var exampleObject = new GameObject( true, "Examble" );
var exampleTrack = MovieClip.RootGameObject( "Example" );
var target = TrackBinder.Default.Get( exampleTrack );
Assert.IsFalse( target.IsBound );
target.Bind( exampleObject );
Assert.IsTrue( target.IsBound );
Assert.AreEqual( exampleObject, target.Value );
}
/// <summary>
/// Properties are bound based on their parent track's binding.
/// </summary>
[TestMethod]
public void PropertyBinding()
{
var exampleTrack = MovieClip.RootGameObject( "Example" )
.Property<Vector3>( nameof(GameObject.LocalPosition) );
var target = TrackBinder.Default.Get( exampleTrack );
Assert.IsFalse( target.IsBound );
var exampleObject = new GameObject( true, "Example" );
Assert.IsTrue( target.IsBound );
target.Value = new Vector3( 100, 200, 300 );
Assert.AreEqual( new Vector3( 100, 200, 300 ), exampleObject.LocalPosition );
}
/// <summary>
/// Properties are bound based on their parent track's binding.
/// </summary>
[TestMethod]
public void SubPropertyBinding()
{
var exampleTrack = MovieClip.RootGameObject( "Example" )
.Property<Vector3>( nameof(GameObject.LocalPosition) )
.Property<float>( nameof(Vector3.y) );
var target = TrackBinder.Default.Get( exampleTrack );
Assert.IsFalse( target.IsBound );
var exampleObject = new GameObject( true, "Example" );
Assert.IsTrue( target.IsBound );
target.Value = 100f;
Assert.AreEqual( new Vector3( 0, 100, 0 ), exampleObject.LocalPosition );
}
/// <summary>
/// Support custom <see cref="ITrackPropertyFactory"/> implementations.
/// </summary>
[TestMethod]
public void CustomPropertyBinding()
{
var exampleObject = new GameObject( true, "Example" );
var exampleTrack = MovieClip.RootGameObject( "Example" )
.Property<Vector3>( "LookAt" );
var target = TrackBinder.Default.Get( exampleTrack );
Assert.IsTrue( target.IsBound );
target.Value = new Vector3( 100f, 0f, 0f );
Assert.IsTrue( new Vector3( 1f, 0f, 0f ).AlmostEqual( exampleObject.WorldRotation.Forward ) );
target.Value = new Vector3( 0f, -100f, 0f );
Assert.IsTrue( new Vector3( 0f, -1f, 0f ).AlmostEqual( exampleObject.WorldRotation.Forward ) );
}
}