public IEnumerator CreateByName()
        {
            // Given two training scene objects and a duration,
            GameObject          movedGo = new GameObject(movedName);
            TrainingSceneObject moved   = movedGo.AddComponent <TrainingSceneObject>();

            moved.ChangeUniqueName(movedName);

            GameObject          targetGo         = new GameObject(positionProviderName);
            TrainingSceneObject positionProvider = targetGo.AddComponent <TrainingSceneObject>();

            positionProvider.ChangeUniqueName(positionProviderName);

            float duration = 0.25f;

            // When we create MoveObjectBehavior and pass training scene objects by their unique name,
            MoveObjectBehavior moveObjectBehavior = new MoveObjectBehavior(movedName, positionProviderName, duration);

            // Then all properties of the MoveObjectBehavior are properly assigned
            Assert.AreEqual(moved, moveObjectBehavior.Data.Target.Value);
            Assert.AreEqual(positionProvider, moveObjectBehavior.Data.PositionProvider.Value);
            Assert.AreEqual(moveObjectBehavior.Data.Duration, duration);

            // Cleanup created game objects.
            Object.DestroyImmediate(movedGo);
            Object.DestroyImmediate(targetGo);

            yield return(null);
        }
        public IEnumerator FastForwardInactiveBehaviorAndActivateIt()
        {
            // Given MoveObjectBehavior that takes two training scene objects with different positions and rotations, and positive transition duration,
            float duration = 0.05f;

            GameObject          movedGo = new GameObject(movedName);
            TrainingSceneObject moved   = movedGo.AddComponent <TrainingSceneObject>();

            moved.ChangeUniqueName(movedName);

            GameObject positionProviderGo = new GameObject(positionProviderName);

            positionProviderGo.transform.position = new Vector3(1, 2, 50);
            positionProviderGo.transform.rotation = Quaternion.Euler(57, 195, 188);
            TrainingSceneObject target = positionProviderGo.AddComponent <TrainingSceneObject>();

            target.ChangeUniqueName(positionProviderName);

            MoveObjectBehavior behavior = new MoveObjectBehavior(moved, target, duration);

            // When we mark it to fast-forward and activate it,
            behavior.LifeCycle.MarkToFastForward();
            behavior.LifeCycle.Activate();

            // Then it autocompletes immediately, and moved object position and rotation matches the ones of positionProvider.
            Assert.AreEqual(Stage.Active, behavior.LifeCycle.Stage);
            Assert.IsTrue((movedGo.transform.position - positionProviderGo.transform.position).sqrMagnitude < 0.001f);
            Assert.IsTrue(Quaternion.Dot(movedGo.transform.rotation, positionProviderGo.transform.rotation) > 0.999f);

            // Cleanup created game objects.
            Object.DestroyImmediate(movedGo);
            Object.DestroyImmediate(positionProviderGo);

            yield return(null);
        }
        public IEnumerator FastForwardInactiveBehavior()
        {
            // Given MoveObjectBehavior that takes two training scene objects with different positions and rotations, and positive transition duration,
            float duration = 0.05f;

            GameObject          movedGo = new GameObject(movedName);
            TrainingSceneObject moved   = movedGo.AddComponent <TrainingSceneObject>();

            moved.ChangeUniqueName(movedName);

            GameObject positionProviderGo = new GameObject(positionProviderName);

            positionProviderGo.transform.position = new Vector3(1, 2, 50);
            positionProviderGo.transform.rotation = Quaternion.Euler(57, 195, 188);
            TrainingSceneObject target = positionProviderGo.AddComponent <TrainingSceneObject>();

            target.ChangeUniqueName(positionProviderName);

            MoveObjectBehavior behavior = new MoveObjectBehavior(moved, target, duration);

            // When we mark it to fast-forward,
            behavior.LifeCycle.MarkToFastForward();

            // Then it doesn't autocomplete because it wasn't activated yet.
            Assert.AreEqual(Stage.Inactive, behavior.LifeCycle.Stage);

            // Cleanup created game objects.
            Object.DestroyImmediate(movedGo);
            Object.DestroyImmediate(positionProviderGo);

            yield return(null);
        }
        public IEnumerator SamePosition()
        {
            // Given MoveObjectBehavior that takes two training scene objects with the same position and rotation, and positive transition duration,
            float duration = 0.05f;

            GameObject          movedGo = new GameObject(movedName);
            TrainingSceneObject moved   = movedGo.AddComponent <TrainingSceneObject>();

            moved.ChangeUniqueName(movedName);

            GameObject          targetGo = new GameObject(positionProviderName);
            TrainingSceneObject target   = targetGo.AddComponent <TrainingSceneObject>();

            target.ChangeUniqueName(positionProviderName);

            MoveObjectBehavior behavior = new MoveObjectBehavior(moved, target, duration);

            behavior.Configure(RuntimeConfigurator.Configuration.Modes.CurrentMode);

            // When we activate the behavior,
            behavior.LifeCycle.Activate();

            yield return(null);

            behavior.Update();

            // Then it does not finish its activation immediately.
            Assert.IsTrue(behavior.LifeCycle.Stage == Stage.Activating);

            // Cleanup created game objects.
            Object.DestroyImmediate(movedGo);
            Object.DestroyImmediate(targetGo);

            yield return(null);
        }
        public IEnumerator MoveObjectBehavior()
        {
            // Given training with MoveObjectBehavior
            TrainingSceneObject moved            = TestingUtils.CreateSceneObject("moved");
            TrainingSceneObject positionProvider = TestingUtils.CreateSceneObject("positionprovider");
            ICourse             training1        = new LinearTrainingBuilder("Training")
                                                   .AddChapter(new LinearChapterBuilder("Chapter")
                                                               .AddStep(new BasicStepBuilder("Step")
                                                                        .AddBehavior(new MoveObjectBehavior(moved, positionProvider, 24.7f))))
                                                   .Build();

            // When that training is serialized and deserialzied
            ICourse training2 = Serializer.CourseFromByteArray(Serializer.CourseToByteArray(training1));

            // Then we should have two identical move object behaviors
            MoveObjectBehavior behavior1 = training1.Data.FirstChapter.Data.FirstStep.Data.Behaviors.Data.Behaviors.First() as MoveObjectBehavior;
            MoveObjectBehavior behavior2 = training2.Data.FirstChapter.Data.FirstStep.Data.Behaviors.Data.Behaviors.First() as MoveObjectBehavior;

            Assert.IsNotNull(behavior1);
            Assert.IsNotNull(behavior2);
            Assert.IsFalse(ReferenceEquals(behavior1, behavior2));
            Assert.AreEqual(behavior1.Data.Target.Value, behavior2.Data.Target.Value);
            Assert.AreEqual(behavior1.Data.PositionProvider.Value, behavior2.Data.PositionProvider.Value);
            Assert.AreEqual(behavior1.Data.Duration, behavior2.Data.Duration);

            // Cleanup created game objects.
            TestingUtils.DestroySceneObject(moved);
            TestingUtils.DestroySceneObject(positionProvider);

            return(null);
        }
        public IEnumerator PositiveDuration()
        {
            // Given MoveObjectBehavior that takes two training scene objects with different positions and rotations, and positive transition duration,
            float duration = 0.05f;

            GameObject          movedGo = new GameObject(movedName);
            TrainingSceneObject moved   = movedGo.AddComponent <TrainingSceneObject>();

            moved.ChangeUniqueName(movedName);

            GameObject positionProviderGo = new GameObject(positionProviderName);

            positionProviderGo.transform.position = new Vector3(1, 2, 50);
            positionProviderGo.transform.rotation = Quaternion.Euler(57, 195, 188);
            TrainingSceneObject target = positionProviderGo.AddComponent <TrainingSceneObject>();

            target.ChangeUniqueName(positionProviderName);

            MoveObjectBehavior behavior = new MoveObjectBehavior(moved, target, duration);

            behavior.Configure(RuntimeConfigurator.Configuration.Modes.CurrentMode);

            // When I activate that behavior and wait for transition duration,
            behavior.LifeCycle.Activate();

            float startTime = Time.time;

            while (Stage.Active != behavior.LifeCycle.Stage)
            {
                yield return(null);

                behavior.Update();
            }

            // Then behavior activation is completed, and moved object position and rotation matches positionProvider's.
            Assert.IsTrue(Time.time - startTime > duration);
            Assert.IsTrue((movedGo.transform.position - positionProviderGo.transform.position).sqrMagnitude < 0.001f);
            Assert.IsTrue(Quaternion.Dot(movedGo.transform.rotation, positionProviderGo.transform.rotation) > 0.999f);

            // Cleanup created game objects.
            Object.DestroyImmediate(movedGo);
            Object.DestroyImmediate(positionProviderGo);

            yield return(null);
        }
        public IEnumerator ZeroDuration()
        {
            // Given MoveObjectBehavior that takes two training scene objects with different positions and rotations, and transition duration that equals zero,
            float duration = 0f;

            GameObject          movedGo = new GameObject(movedName);
            TrainingSceneObject moved   = movedGo.AddComponent <TrainingSceneObject>();

            moved.ChangeUniqueName(movedName);

            GameObject targetGo = new GameObject(positionProviderName);

            targetGo.transform.position = new Vector3(1, 2, 50);
            targetGo.transform.rotation = Quaternion.Euler(123, 15, 8);
            TrainingSceneObject target = targetGo.AddComponent <TrainingSceneObject>();

            target.ChangeUniqueName(positionProviderName);

            MoveObjectBehavior behavior = new MoveObjectBehavior(moved, target, duration);

            behavior.Configure(RuntimeConfigurator.Configuration.Modes.CurrentMode);

            // When we activate that behavior,
            behavior.LifeCycle.Activate();

            yield return(null);

            behavior.Update();

            // Then it immediately completes its activation, and moved object position and rotation matches the ones of positionProvider.
            Assert.IsTrue(behavior.LifeCycle.Stage == Stage.Active);
            Assert.IsTrue((movedGo.transform.position - targetGo.transform.position).sqrMagnitude < 0.001f);
            Assert.IsTrue(Quaternion.Dot(movedGo.transform.rotation, targetGo.transform.rotation) > 0.999f);

            // Cleanup created game objects.
            Object.DestroyImmediate(movedGo);
            Object.DestroyImmediate(targetGo);

            yield return(null);
        }