public IEnumerator GameObjectIsEnabledAfterActivation()
        {
            // Given an active training scene object and a training with enable game object behavior,
            TrainingSceneObject toEnable = TestingUtils.CreateSceneObject("toEnable");

            toEnable.GameObject.SetActive(false);

            EndlessConditionMock trigger = new EndlessConditionMock();

            ICourse course = new LinearTrainingBuilder("Training")
                             .AddChapter(new LinearChapterBuilder("Chapter")
                                         .AddStep(new BasicCourseStepBuilder("Step")
                                                  .Enable(toEnable)
                                                  .AddCondition(trigger)))
                             .Build();

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

            CourseRunner.Initialize(course);
            CourseRunner.Run();

            // When the behavior is activated
            CourseRunner.Initialize(course);
            CourseRunner.Run();

            yield return(new WaitUntil(() => course.Data.FirstChapter.Data.Steps[0].LifeCycle.Stage == Stage.Active));

            // Then the training scene object is enabled.
            Assert.True(toEnable.GameObject.activeSelf);

            // Cleanup
            TestingUtils.DestroySceneObject(toEnable);

            yield break;
        }
        public IEnumerator NotExistingPrefab()
        {
            // Given the position provider training object, an invalid path to a not existing prefab, some valid default settings, and the activation mode = Activation,
            GameObject          target           = new GameObject(positionProviderName);
            TrainingSceneObject positionProvider = target.AddComponent <TrainingSceneObject>();

            positionProvider.ChangeUniqueName(positionProviderName);

            ConfettiBehavior behavior = new ConfettiBehavior(false, positionProvider, pathToMockPrefab, areaRadius, duration, BehaviorExecutionStages.Activation);

            behavior.Configure(defaultMode);

            // When I activate that behavior and wait for one update cycle,
            behavior.LifeCycle.Activate();

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

                behavior.Update();
            }

            yield return(null);

            behavior.Update();

            string     prefabName = "Behavior" + pathToMockPrefab.Substring(pathToMockPrefab.LastIndexOf("/", StringComparison.Ordinal) + 1);
            GameObject machine    = GameObject.Find(prefabName);

            // Then the activation state of the behavior is "active" and there is no confetti machine in the scene.
            Assert.AreEqual(Stage.Active, behavior.LifeCycle.Stage);
            Assert.AreEqual(null, machine);
        }
        public IEnumerator CreateByName()
        {
            // Given the path to the confetti machine prefab, the position provider name, the duration, the bool isAboveTrainee, the area radius, and the activation mode,
            GameObject          target           = new GameObject(positionProviderName);
            TrainingSceneObject positionProvider = target.AddComponent <TrainingSceneObject>();

            positionProvider.ChangeUniqueName(positionProviderName);

            BehaviorExecutionStages executionStages = BehaviorExecutionStages.ActivationAndDeactivation;

            // When we create ConfettiBehavior and pass training objects by their unique name,
            ConfettiBehavior confettiBehavior = new ConfettiBehavior(false, positionProviderName, pathToMockPrefab, areaRadius, duration, executionStages);

            confettiBehavior.Configure(defaultMode);

            // Then all properties of the MoveObjectBehavior are properly assigned.
            Assert.AreEqual(false, confettiBehavior.Data.IsAboveTrainee);
            Assert.AreEqual(positionProvider, confettiBehavior.Data.PositionProvider.Value);
            Assert.AreEqual(pathToMockPrefab, confettiBehavior.Data.ConfettiMachinePrefabPath);
            Assert.AreEqual(areaRadius, confettiBehavior.Data.AreaRadius);
            Assert.AreEqual(duration, confettiBehavior.Data.Duration);
            Assert.AreEqual(executionStages, confettiBehavior.Data.ExecutionStages);

            yield break;
        }
        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);
        }
Example #5
0
        public IEnumerator FastForwardActivatingBehavior()
        {
            // Given an UnlockObjectBehavior and a locked game object,
            GameObject          gameObject   = new GameObject("Test");
            TrainingSceneObject targetObject = gameObject.AddComponent <TrainingSceneObject>();

            UnlockObjectBehavior behavior = new UnlockObjectBehavior(targetObject);

            behavior.Configure(RuntimeConfigurator.Configuration.GetCurrentMode());

            targetObject.SetLocked(true);

            bool isLockedInitially = targetObject.IsLocked;

            behavior.LifeCycle.Activate();

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

            // Then it should work without any differences because the behavior is done immediately anyways.
            bool isLockedDuringStep = targetObject.IsLocked;

            behavior.LifeCycle.Deactivate();

            bool isLockedInEnd = targetObject.IsLocked;

            Assert.IsTrue(isLockedInitially, "Object should be locked initially");
            Assert.IsFalse(isLockedDuringStep, "Object should be unlocked during step");
            Assert.IsTrue(isLockedInEnd, "Object should be locked in the end");

            // Cleanup created game objects.
            Object.DestroyImmediate(gameObject);

            yield return(null);
        }
Example #6
0
        public IEnumerator BuildingSnapZonePutTest()
        {
            // Given a snap zone and snappable property and a builder for a training with a PutIntoSnapZone default step
            GameObject          snapZoneGo = new GameObject("SnapZone");
            TrainingSceneObject snapZone   = snapZoneGo.AddComponent <TrainingSceneObject>();

            snapZoneGo.AddComponent <DummySnapZoneProperty>();
            snapZone.ChangeUniqueName("SnapZone");

            GameObject          putGo       = new GameObject("Puttable");
            TrainingSceneObject objectToPut = putGo.AddComponent <TrainingSceneObject>();

            putGo.AddComponent <DummySnappableProperty>();
            objectToPut.ChangeUniqueName("ToPut");

            LinearTrainingBuilder builder = new LinearTrainingBuilder("TestTraining")
                                            .AddChapter(new LinearChapterBuilder("TestChapter")
                                                        .AddStep(InteractionDefaultSteps.PutIntoSnapZone("TestSnapZonePutStep", "SnapZone", "ToPut")));

            // When you build a training with it
            IStep step = builder.Build().Data.FirstChapter.Data.FirstStep;

            // Then it has a step with a SnappedCondition
            Assert.True(step != null);
            Assert.True(step.Data.Name == "TestSnapZonePutStep");
            Assert.True(step.Data.Transitions.Data.Transitions.First().Data.Conditions.Count == 1);
            Assert.True(step.Data.Transitions.Data.Transitions.First().Data.Conditions.First() is SnappedCondition);
            Assert.True(ReferenceEquals((step.Data.Transitions.Data.Transitions.First().Data.Conditions.First() as SnappedCondition).Data.Target.Value.SceneObject, objectToPut));

            // Cleanup
            Object.DestroyImmediate(snapZoneGo);
            Object.DestroyImmediate(putGo);

            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);
        }
Example #8
0
        public IEnumerator DisableGameObjectBehavior()
        {
            // Given DisableGameObjectBehavior,
            TrainingSceneObject trainingSceneObject = TestingUtils.CreateSceneObject("TestObject");

            ICourse training1 = new LinearTrainingBuilder("Training")
                                .AddChapter(new LinearChapterBuilder("Chapter")
                                            .AddStep(new BasicStepBuilder("Step")
                                                     .DisableAutomaticAudioHandling()
                                                     .Disable("TestObject")))
                                .Build();

            // When we serialize and deserialize a training with it
            string serialized = JsonTrainingSerializer.Serialize(training1);

            ICourse training2 = JsonTrainingSerializer.Deserialize(serialized);

            DisableGameObjectBehavior behavior1 = training1.Data.FirstChapter.Data.FirstStep.Data.Behaviors.Data.Behaviors.First() as DisableGameObjectBehavior;
            DisableGameObjectBehavior behavior2 = training2.Data.FirstChapter.Data.FirstStep.Data.Behaviors.Data.Behaviors.First() as DisableGameObjectBehavior;

            // Then it's target training scene object is still the same.
            Assert.IsNotNull(behavior1);
            Assert.IsNotNull(behavior2);
            Assert.AreEqual(behavior1.Data.Target.Value, behavior2.Data.Target.Value);

            TestingUtils.DestroySceneObject(trainingSceneObject);

            return(null);
        }
Example #9
0
        public IEnumerator LockObjectBehavior()
        {
            // Given a training with LockObjectBehavior
            TrainingSceneObject trainingSceneObject = TestingUtils.CreateSceneObject("TestObject");

            ICourse training1 = new LinearTrainingBuilder("Training")
                                .AddChapter(new LinearChapterBuilder("Chapter")
                                            .AddStep(new BasicStepBuilder("Step")
                                                     .DisableAutomaticAudioHandling()
                                                     .AddBehavior(new LockObjectBehavior(trainingSceneObject))))
                                .Build();

            // When we serialize and deserialize it
            ICourse training2 = JsonTrainingSerializer.Deserialize(JsonTrainingSerializer.Serialize(training1));

            // Then that's behavior target is still the same.
            LockObjectBehavior behavior1 = training1.Data.FirstChapter.Data.FirstStep.Data.Behaviors.Data.Behaviors.First() as LockObjectBehavior;
            LockObjectBehavior behavior2 = training2.Data.FirstChapter.Data.FirstStep.Data.Behaviors.Data.Behaviors.First() as LockObjectBehavior;

            Assert.IsNotNull(behavior1);
            Assert.IsNotNull(behavior2);
            Assert.AreEqual(behavior1.Data.Target.Value, behavior2.Data.Target.Value);

            // Cleanup
            TestingUtils.DestroySceneObject(trainingSceneObject);

            return(null);
        }
Example #10
0
        public IEnumerator HighlightTest()
        {
            // Given we have a training scene object and a builder for a training with a step with highlight that object
            GameObject          go            = new GameObject("Highlightable");
            TrainingSceneObject highlightable = go.AddComponent <TrainingSceneObject>();

            highlightable.ChangeUniqueName("Highlightable");

            LinearTrainingBuilder builder = new LinearTrainingBuilder("TestTraining")
                                            .AddChapter(new LinearChapterBuilder("TestChapter")
                                                        .AddStep(new BasicStepBuilder("TestHighlightStep")
                                                                 .Highlight("Highlightable")));

            // When we build a training from it
            IStep step = builder.Build().Data.FirstChapter.Data.FirstStep;

            // Then we have a step with VRTKObjectHighlight behavior.
            Assert.True(step != null);
            Assert.True(step.Data.Name == "TestHighlightStep");
            Assert.True(step.Data.Behaviors.Data.Behaviors.First() is VRTKObjectHighlight);
            Assert.True(ReferenceEquals((step.Data.Behaviors.Data.Behaviors.First() as VRTKObjectHighlight).Data.Target.Value, highlightable));

            // Cleanup
            Object.DestroyImmediate(go);

            return(null);
        }
        public IEnumerator DontCompleteWhenWrongObjectEntersRange()
        {
            // In addition to setup phase, also setup an additional object
            GameObject wrongObj = new GameObject("Wrong Object");

            wrongObj.transform.position = PositionFarFromTarget;
            TrainingSceneObject wrongTrainingSceneObject = wrongObj.AddComponent <TrainingSceneObject>();

            // Activate range condition
            ObjectInRangeCondition condition = new ObjectInRangeCondition(TrackedTrainingSceneObject, TargetTrainingSceneObject.GetProperty <TransformInRangeDetectorProperty>(), 5);

            condition.LifeCycle.Activate();

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

                condition.Update();
            }

            // Move wrong object to the target position
            wrongTrainingSceneObject.transform.position = TargetPositionObject.transform.position;

            float startTime = Time.time;

            while (Time.time < startTime + 0.1f)
            {
                yield return(null);

                condition.Update();
            }

            // Assert that condition is not completed
            UnityEngine.Assertions.Assert.IsFalse(condition.IsCompleted, "TargetInRangeCondition should not be completed!");
        }
Example #12
0
        public IEnumerator BuildingUseTest()
        {
            // Given a usable property and a builder for a training with Use default step
            GameObject          usableGo = new GameObject("Usable");
            TrainingSceneObject usable   = usableGo.AddComponent <TrainingSceneObject>();

            usableGo.AddComponent <UsableProperty>();
            usable.ChangeUniqueName("Usable");

            LinearTrainingBuilder builder = new LinearTrainingBuilder("TestTraining")
                                            .AddChapter(new LinearChapterBuilder("TestChapter")
                                                        .AddStep(DefaultSteps.Use("TestUseStep", "Usable")));

            // When you build a training with it
            IStep step = builder.Build().Data.FirstChapter.Data.FirstStep;

            // Then it has a step with an UsedCondition
            Assert.True(step != null);
            Assert.True(step.Data.Name == "TestUseStep");
            Assert.True(step.Data.Transitions.Data.Transitions.First().Data.Conditions.Count == 1);
            Assert.True(step.Data.Transitions.Data.Transitions.First().Data.Conditions.First() is UsedCondition);
            Assert.True(ReferenceEquals((step.Data.Transitions.Data.Transitions.First().Data.Conditions.First() as UsedCondition).Data.UsableProperty.Value.SceneObject, usable));

            // Cleanup
            Object.DestroyImmediate(usableGo);

            return(null);
        }
Example #13
0
        public IEnumerator BuildingGrabTest()
        {
            // Given a `GrabbableProperty` and a builder for a training with a Grab default step
            GameObject          go = new GameObject("TestGrabbable");
            TrainingSceneObject to = go.AddComponent <TrainingSceneObject>();

            go.AddComponent <GrabbableProperty>();
            to.ChangeUniqueName("Grabbable");


            LinearTrainingBuilder builder = new LinearTrainingBuilder("TestTraining")
                                            .AddChapter(new LinearChapterBuilder("TestChapter")
                                                        .AddStep(DefaultSteps.Grab("TestGrabStep", "Grabbable")));

            // When we build a training from it
            IStep step = builder.Build().Data.FirstChapter.Data.FirstStep;

            //Then it should has a stap with a GrabbedCondition which refers to the `GrabbableProperty`.
            Assert.True(step != null);
            Assert.True(step.Data.Name == "TestGrabStep");
            Assert.True(step.Data.Transitions.Data.Transitions.First().Data.Conditions.Count == 1);
            GrabbedCondition condition = step.Data.Transitions.Data.Transitions.First().Data.Conditions.First() as GrabbedCondition;

            Assert.True(ReferenceEquals(to, condition.Data.GrabbableProperty.Value.SceneObject));

            // Cleanup
            Object.DestroyImmediate(go);

            yield return(null);
        }
Example #14
0
        public override Rect Draw(Rect rect, object currentValue, Action <object> changeValueCallback, GUIContent label)
        {
            lockableCollection = (LockableObjectsCollection)currentValue;

            Rect currentPosition = new Rect(rect.x, rect.y, rect.width, EditorDrawingHelper.HeaderLineHeight);

            currentPosition.y += 10;

            GUI.Label(currentPosition, "Automatically unlocked objects in this step");

            for (int i = 0; i < lockableCollection.SceneObjects.Count; i++)
            {
                ISceneObject objectInScene = lockableCollection.SceneObjects[i];
                currentPosition    = DrawSceneObject(currentPosition, objectInScene);
                currentPosition.y += EditorDrawingHelper.SingleLineHeight;
            }

            currentPosition.y += EditorDrawingHelper.SingleLineHeight;
            EditorGUI.LabelField(currentPosition, "To add new TrainingSceneObject, drag it in here:");
            currentPosition.y += EditorDrawingHelper.SingleLineHeight + EditorDrawingHelper.VerticalSpacing;

            TrainingSceneObject newSceneObject = (TrainingSceneObject)EditorGUI.ObjectField(currentPosition, null, typeof(TrainingSceneObject), true);

            if (newSceneObject != null)
            {
                lockableCollection.AddSceneObject(newSceneObject);
            }
            // EditorDrawingHelper.HeaderLineHeight - 24f is just the magic number to make it properly fit...
            return(new Rect(rect.x, rect.y, rect.width, currentPosition.y - EditorDrawingHelper.HeaderLineHeight - 24f));
        }
Example #15
0
        public IEnumerator UnregisterAllowsToPlaceTest()
        {
            // Create reference
            GameObject          obj1       = new GameObject("MyObject");
            TrainingSceneObject reference1 = obj1.AddComponent <TrainingSceneObject>();

            reference1.ChangeUniqueName("Test");

            RuntimeConfigurator.Configuration.SceneObjectRegistry.Unregister(reference1);

            // Create reference
            GameObject          obj2       = new GameObject("MyObject");
            TrainingSceneObject reference2 = obj2.AddComponent <TrainingSceneObject>();

            reference2.ChangeUniqueName("Test");

            // Assert that new added reference can be found
            Assert.IsTrue(RuntimeConfigurator.Configuration.SceneObjectRegistry.ContainsGuid(reference2.Guid));
            Assert.IsTrue(RuntimeConfigurator.Configuration.SceneObjectRegistry.ContainsName(reference2.UniqueName));
            Assert.AreEqual(reference2, RuntimeConfigurator.Configuration.SceneObjectRegistry.GetByName(reference2.UniqueName));

            // Clean up
            Object.DestroyImmediate(obj1);
            Object.DestroyImmediate(obj2);

            yield return(null);
        }
        public IEnumerator ObjectInRangeCondition()
        {
            // Given a training with ObjectInRangeCondition,
            TrainingSceneObject testObjectToo         = TestingUtils.CreateSceneObject("TestObjectToo");
            TransformInRangeDetectorProperty detector = testObjectToo.gameObject.AddComponent <TransformInRangeDetectorProperty>();
            TrainingSceneObject testObject            = TestingUtils.CreateSceneObject("TestObject");

            ICourse training1 = new LinearTrainingBuilder("Training")
                                .AddChapter(new LinearChapterBuilder("Chapter")
                                            .AddStep(new BasicStepBuilder("Step")
                                                     .AddCondition(new ObjectInRangeCondition(testObject, detector, 1.5f))))
                                .Build();

            // When we serialize and deserialize it
            ICourse training2 = Serializer.CourseFromByteArray(Serializer.CourseToByteArray(training1));

            // Then that condition's target, detector and range should stay unchanged.
            ObjectInRangeCondition condition1 = training1.Data.FirstChapter.Data.FirstStep.Data.Transitions.Data.Transitions.First().Data.Conditions.First() as ObjectInRangeCondition;
            ObjectInRangeCondition condition2 = training2.Data.FirstChapter.Data.FirstStep.Data.Transitions.Data.Transitions.First().Data.Conditions.First() as ObjectInRangeCondition;

            Assert.IsNotNull(condition1);
            Assert.IsNotNull(condition2);
            Assert.AreEqual(condition1.Data.Range, condition2.Data.Range);
            Assert.AreEqual(condition1.Data.Target.Value, condition2.Data.Target.Value);
            Assert.AreEqual(condition1.Data.DistanceDetector.Value, condition2.Data.DistanceDetector.Value);

            // Cleanup
            TestingUtils.DestroySceneObject(testObjectToo);
            TestingUtils.DestroySceneObject(testObject);

            return(null);
        }
Example #17
0
        public IEnumerator ChangeNameBeforeAwakeTest()
        {
            // Create reference
            GameObject obj = new GameObject("MyObject");

            obj.SetActive(false);
            TrainingSceneObject reference = obj.AddComponent <TrainingSceneObject>();

            reference.ChangeUniqueName("Test");

            reference.ChangeUniqueName("Test2");
            obj.SetActive(true);

            // Assert that reference is now registered at the registry.
            Assert.IsTrue(RuntimeConfigurator.Configuration.SceneObjectRegistry.ContainsGuid(reference.Guid));
            Assert.AreEqual(reference, RuntimeConfigurator.Configuration.SceneObjectRegistry.GetByGuid(reference.Guid));
            Assert.IsFalse(RuntimeConfigurator.Configuration.SceneObjectRegistry.ContainsName("Test"));
            Assert.IsTrue(RuntimeConfigurator.Configuration.SceneObjectRegistry.ContainsName("Test2"));
            Assert.AreEqual(reference, RuntimeConfigurator.Configuration.SceneObjectRegistry.GetByName("Test2"));

            // Clean up
            Object.DestroyImmediate(obj);

            yield return(null);
        }
        public IEnumerator EnableGameObjectBehavior()
        {
            // Given EnableGameObjectBehavior,
            TrainingSceneObject trainingSceneObject = TestingUtils.CreateSceneObject("TestObject");

            ICourse training1 = new LinearTrainingBuilder("Training")
                                .AddChapter(new LinearChapterBuilder("Chapter")
                                            .AddStep(new BasicCourseStepBuilder("Step")
                                                     .Enable("TestObject")))
                                .Build();

            // When we serialize and deserialize a training course with it
            ICourse training2 = Serializer.CourseFromByteArray(Serializer.CourseToByteArray(training1));

            EnableGameObjectBehavior behavior1 = training1.Data.FirstChapter.Data.FirstStep.Data.Behaviors.Data.Behaviors.First() as EnableGameObjectBehavior;
            EnableGameObjectBehavior behavior2 = training2.Data.FirstChapter.Data.FirstStep.Data.Behaviors.Data.Behaviors.First() as EnableGameObjectBehavior;

            // Then it's target training scene object is still the same.
            Assert.IsNotNull(behavior1);
            Assert.IsNotNull(behavior2);
            Assert.AreEqual(behavior1.Data.Target.Value, behavior2.Data.Target.Value);

            TestingUtils.DestroySceneObject(trainingSceneObject);

            return(null);
        }
Example #19
0
        public IEnumerator BuildingTouchTest()
        {
            // Given you have a touchable property and a builder for a training with Touch default step
            GameObject          touchableGo = new GameObject("Touchable");
            TrainingSceneObject touchable   = touchableGo.AddComponent <TrainingSceneObject>();

            touchableGo.AddComponent <DummyTouchableProperty>();
            touchable.ChangeUniqueName("Touchable");

            LinearTrainingBuilder builder = new LinearTrainingBuilder("TestTraining")
                                            .AddChapter(new LinearChapterBuilder("TestChapter")
                                                        .AddStep(InteractionDefaultSteps.Touch("TestTouchStep", "Touchable")));

            // When you build a training with it
            IStep step = builder.Build().Data.FirstChapter.Data.FirstStep;

            // Then it has a step with a TouchCOndition
            Assert.True(step != null);
            Assert.True(step.Data.Name == "TestTouchStep");
            Assert.True(step.Data.Transitions.Data.Transitions.First().Data.Conditions.Count == 1);
            Assert.True(step.Data.Transitions.Data.Transitions.First().Data.Conditions.First() is TouchedCondition);
            Assert.True(ReferenceEquals((step.Data.Transitions.Data.Transitions.First().Data.Conditions.First() as TouchedCondition).Data.TouchableProperty.Value.SceneObject, touchable));

            // Cleanup
            Object.DestroyImmediate(touchableGo);

            return(null);
        }
        public IEnumerator UnlockObjectBehavior()
        {
            // Given a training with UnlockObjectBehavior
            TrainingSceneObject trainingSceneObject = TestingUtils.CreateSceneObject("TestObject");

            ICourse training1 = new LinearTrainingBuilder("Training")
                                .AddChapter(new LinearChapterBuilder("Chapter")
                                            .AddStep(new BasicStepBuilder("Step")
                                                     .AddBehavior(new UnlockObjectBehavior(trainingSceneObject))))
                                .Build();

            // When we serialize and deserialize it
            ICourse training2 = Serializer.CourseFromByteArray(Serializer.CourseToByteArray(training1));

            UnlockObjectBehavior behavior1 = training1.Data.FirstChapter.Data.FirstStep.Data.Behaviors.Data.Behaviors.First() as UnlockObjectBehavior;
            UnlockObjectBehavior behavior2 = training2.Data.FirstChapter.Data.FirstStep.Data.Behaviors.Data.Behaviors.First() as UnlockObjectBehavior;

            // Then that behavior's target should not change.
            Assert.IsNotNull(behavior1);
            Assert.IsNotNull(behavior2);
            Assert.AreEqual(behavior1.Data.Target.Value, behavior2.Data.Target.Value);

            // Cleanup
            TestingUtils.DestroySceneObject(trainingSceneObject);

            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 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 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);
        }
 /// <summary>
 /// Adds a new TrainingSceneObject to the list.
 /// </summary>
 public void AddTrainingSceneObject(TrainingSceneObject target)
 {
     if (acceptedTrainingSceneObjects.Contains(target) == false)
     {
         acceptedTrainingSceneObjects = acceptedTrainingSceneObjects.Append(target).ToArray();
     }
 }
        public IEnumerator StillActivatingWhenPositiveDurationNotFinished()
        {
            // Given the position provider training object, some valid default settings, and the activation mode = Activation,
            GameObject          target           = new GameObject(positionProviderName);
            TrainingSceneObject positionProvider = target.AddComponent <TrainingSceneObject>();

            positionProvider.ChangeUniqueName(positionProviderName);

            ConfettiBehavior behavior = new ConfettiBehavior(false, positionProvider, pathToPrefab, areaRadius, 2f, BehaviorExecutionStages.Activation);

            behavior.Configure(defaultMode);

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

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

                behavior.Update();
            }

            // And wait two update cycles,
            yield return(null);

            behavior.Update();

            yield return(null);

            behavior.Update();

            // Then the activation state of the behavior is "activating".
            Assert.AreEqual(Stage.Activating, behavior.LifeCycle.Stage);
        }
 /// <summary>
 /// Removes an existing training scene object from the list.
 /// </summary>
 public void RemoveTrainingSceneObject(TrainingSceneObject target)
 {
     if (acceptedTrainingSceneObjects.Contains(target))
     {
         acceptedTrainingSceneObjects = acceptedTrainingSceneObjects.Where((obj => obj != target)).ToArray();
     }
 }
        public IEnumerator FastForwardActivatingBehavior()
        {
            // Given an active ConfettiBehavior with activation mode "Activation",
            GameObject          target           = new GameObject(positionProviderName);
            TrainingSceneObject positionProvider = target.AddComponent <TrainingSceneObject>();

            positionProvider.ChangeUniqueName(positionProviderName);

            ConfettiBehavior behavior = new ConfettiBehavior(false, positionProvider, pathToPrefab, areaRadius, duration, BehaviorExecutionStages.Activation);

            behavior.Configure(defaultMode);

            behavior.LifeCycle.Activate();

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

                behavior.Update();
            }

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

            // Then it autocompletes immediately.
            Assert.AreEqual(Stage.Active, behavior.LifeCycle.Stage);
        }
        public IEnumerator GameObjectStaysDisabled()
        {
            // Given an active training scene object and a training course with disable game object behavior,
            TrainingSceneObject  toDisable = TestingUtils.CreateSceneObject("ToDisable");
            EndlessConditionMock trigger   = new EndlessConditionMock();

            ICourse course = new LinearTrainingBuilder("Course")
                             .AddChapter(new LinearChapterBuilder("Chapter")
                                         .AddStep(new BasicCourseStepBuilder("Step")
                                                  .Disable(toDisable))
                                         .AddStep(new BasicCourseStepBuilder("Step")
                                                  .AddCondition(trigger)))
                             .Build();

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

            // When the behavior is activated and after the step is completed
            CourseRunner.Initialize(course);
            CourseRunner.Run();

            yield return(new WaitUntil(() => course.Data.FirstChapter.Data.Steps[1].LifeCycle.Stage == Stage.Active));

            trigger.Autocomplete();

            yield return(new WaitUntil(() => course.Data.FirstChapter.Data.Steps[1].LifeCycle.Stage == Stage.Inactive));

            // Then the training scene object stays disabled.
            Assert.False(toDisable.GameObject.activeSelf);

            // Cleanup.
            TestingUtils.DestroySceneObject(toDisable);

            yield break;
        }
        public IEnumerator ActivationWithSpawnedMachine()
        {
            // Given a positive duration, a position provider, some valid default settings, and the activation mode = Activation,
            GameObject          target           = new GameObject(positionProviderName);
            TrainingSceneObject positionProvider = target.AddComponent <TrainingSceneObject>();

            positionProvider.ChangeUniqueName(positionProviderName);

            ConfettiBehavior behavior = new ConfettiBehavior(false, positionProvider, pathToPrefab, areaRadius, duration, BehaviorExecutionStages.Activation);

            behavior.Configure(defaultMode);

            // When I activate that behavior and wait until it's activating,
            behavior.LifeCycle.Activate();

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

                behavior.Update();
            }

            string     prefabName = "Behavior" + pathToPrefab.Substring(pathToPrefab.LastIndexOf("/", StringComparison.Ordinal) + 1);
            GameObject machine    = GameObject.Find(prefabName);

            // Then the activation state of the behavior is "activating" and the ConfettiMachine exists in the scene.
            Assert.AreEqual(Stage.Activating, behavior.LifeCycle.Stage);
            Assert.IsTrue(machine != null);
        }
        public IEnumerator RunsInstantlyWhenDelayTimeIsZero()
        {
            // Given a complete scaling behavior with duration time == 0,
            const float duration = 0f;

            GameObject          target           = new GameObject(targetName);
            TrainingSceneObject positionProvider = target.AddComponent <TrainingSceneObject>();

            positionProvider.ChangeUniqueName(targetName);

            Vector3 endScale = target.transform.localScale + newScale;

            IBehavior behavior = new ScalingBehavior(new SceneObjectReference(targetName), endScale, duration);

            behavior.Configure(defaultMode);

            // When we activate it and wait one update cycle,
            behavior.LifeCycle.Activate();

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

                behavior.Update();
            }

            yield return(null);

            behavior.Update();

            // Then the behavior is activated immediately and the object is scaled correctly.
            Assert.AreEqual(Stage.Active, behavior.LifeCycle.Stage);
            Assert.IsTrue(target.transform.localScale == endScale);
        }