public IEnumerator OnlActiveTargetsFollowSourceNoOffsets()
        {
            UnityEventListenerMock preprocessedMock = new UnityEventListenerMock();
            UnityEventListenerMock processedMock    = new UnityEventListenerMock();

            subject.Preprocessed.AddListener(preprocessedMock.Listen);
            subject.Processed.AddListener(processedMock.Listen);

            GameObject source = new GameObject("playAreaAlias");

            GameObject target1 = new GameObject("SDK1PlayArea");
            GameObject target2 = new GameObject("SDK2PlayArea");
            GameObject target3 = new GameObject("SDK3PlayArea");

            subject.Sources = containingObject.AddComponent <GameObjectObservableList>();
            subject.Targets = containingObject.AddComponent <GameObjectObservableList>();
            yield return(null);

            source.transform.position = Vector3.one;

            target1.transform.position = Vector3.one * 2f;
            target2.transform.position = Vector3.one * 3f;
            target3.transform.position = Vector3.one * 4f;

            subject.Sources.Add(source);
            subject.Targets.Add(target1);
            subject.Targets.Add(target2);
            subject.Targets.Add(target3);

            subject.gameObject.AddComponent <RuleStub>();
            ActiveInHierarchyRule activeInHierarchyRule = subject.gameObject.AddComponent <ActiveInHierarchyRule>();

            subject.TargetValidity = new RuleContainer
            {
                Interface = activeInHierarchyRule
            };

            target1.SetActive(false);
            target2.SetActive(true);
            target3.SetActive(true);

            FollowModifierMock followModifierMock = containingObject.AddComponent <FollowModifierMock>();

            subject.FollowModifier = followModifierMock;

            subject.Process();

            Assert.IsTrue(preprocessedMock.Received);
            Assert.IsTrue(processedMock.Received);
            Assert.AreNotEqual(source.transform.position, target1.transform.position);
            Assert.AreEqual(source.transform.position, target2.transform.position);
            Assert.AreEqual(source.transform.position, target3.transform.position);

            Object.DestroyImmediate(source);
            Object.DestroyImmediate(target1);
            Object.DestroyImmediate(target2);
            Object.DestroyImmediate(target3);
        }
        public void TargetFollowsFirstActiveSourceNoOffsets()
        {
            /// The first active SDK HMD moves and the target HMD alias follows

            UnityEventListenerMock preprocessedMock = new UnityEventListenerMock();
            UnityEventListenerMock processedMock    = new UnityEventListenerMock();

            subject.Preprocessed.AddListener(preprocessedMock.Listen);
            subject.Processed.AddListener(processedMock.Listen);

            GameObject source1 = new GameObject("SDK1HMD");
            GameObject source2 = new GameObject("SDK2HMD");
            GameObject source3 = new GameObject("SDK3HMD");
            GameObject target  = new GameObject("HMDAlias");

            source1.transform.position = Vector3.one;
            source2.transform.position = Vector3.one * 2f;
            source3.transform.position = Vector3.one * 3f;

            target.transform.position = Vector3.zero;

            subject.AddSource(source1);
            subject.AddSource(source2);
            subject.AddSource(source3);
            subject.AddTarget(target);

            subject.ceaseAfterFirstSourceProcessed = true;
            subject.gameObject.AddComponent <RuleStub>();
            ActiveInHierarchyRule activeInHierarchyRule = subject.gameObject.AddComponent <ActiveInHierarchyRule>();

            subject.sourceValidity = new RuleContainer
            {
                Interface = activeInHierarchyRule
            };

            source1.SetActive(false);
            source2.SetActive(true);
            source3.SetActive(true);

            FollowModifierMock followModifierMock = containingObject.AddComponent <FollowModifierMock>();

            subject.followModifier = followModifierMock;

            subject.Process();

            Assert.IsTrue(preprocessedMock.Received);
            Assert.IsTrue(processedMock.Received);

            Assert.AreNotEqual(source1.transform.position, target.transform.position);
            Assert.AreEqual(source2.transform.position, target.transform.position);
            Assert.AreNotEqual(source3.transform.position, target.transform.position);

            Object.DestroyImmediate(source1);
            Object.DestroyImmediate(source2);
            Object.DestroyImmediate(source3);
            Object.DestroyImmediate(target);
        }
        public IEnumerator TargetOffsetNotChildException()
        {
            UnityEventListenerMock preprocessedMock = new UnityEventListenerMock();
            UnityEventListenerMock processedMock    = new UnityEventListenerMock();

            subject.Preprocessed.AddListener(preprocessedMock.Listen);
            subject.Processed.AddListener(processedMock.Listen);

            GameObject source = new GameObject("source");

            GameObject target1 = new GameObject("target1");
            GameObject target2 = new GameObject("target2");
            GameObject target3 = new GameObject("target3");

            GameObject targetOffset1 = new GameObject("targetOffset1");
            GameObject targetOffset2 = new GameObject("targetOffset2");
            GameObject targetOffset3 = new GameObject("targetOffset3");

            subject.Sources       = containingObject.AddComponent <GameObjectObservableList>();
            subject.Targets       = containingObject.AddComponent <GameObjectObservableList>();
            subject.TargetOffsets = containingObject.AddComponent <GameObjectObservableList>();
            yield return(null);

            subject.Sources.Add(source);
            subject.Targets.Add(target1);
            subject.Targets.Add(target2);
            subject.Targets.Add(target3);

            subject.TargetOffsets.Add(targetOffset1);
            subject.TargetOffsets.Add(targetOffset2);
            subject.TargetOffsets.Add(targetOffset3);

            FollowModifierMock followModifierMock = containingObject.AddComponent <FollowModifierMock>();

            subject.FollowModifier = followModifierMock;

            NUnit.Framework.Assert.Throws <System.ArgumentException>(() => subject.Process());

            Assert.IsTrue(preprocessedMock.Received);
            Assert.IsFalse(processedMock.Received);

            Object.DestroyImmediate(source);
            Object.DestroyImmediate(target1);
            Object.DestroyImmediate(target2);
            Object.DestroyImmediate(target3);
            Object.DestroyImmediate(targetOffset1);
            Object.DestroyImmediate(targetOffset2);
            Object.DestroyImmediate(targetOffset3);
        }
        public IEnumerator AllTargetsFollowSourceNoOffsets()
        {
            // The play area alias moves and all SDK play areas follow it.

            UnityEventListenerMock preprocessedMock = new UnityEventListenerMock();
            UnityEventListenerMock processedMock    = new UnityEventListenerMock();

            subject.Preprocessed.AddListener(preprocessedMock.Listen);
            subject.Processed.AddListener(processedMock.Listen);

            GameObject source = new GameObject("playAreaAlias");

            GameObject target1 = new GameObject("SDK1PlayArea");
            GameObject target2 = new GameObject("SDK2PlayArea");
            GameObject target3 = new GameObject("SDK3PlayArea");

            subject.Sources = containingObject.AddComponent <GameObjectObservableList>();
            subject.Targets = containingObject.AddComponent <GameObjectObservableList>();
            yield return(null);

            source.transform.position = Vector3.one;

            target1.transform.position = Vector3.one * 2f;
            target2.transform.position = Vector3.one * 3f;
            target3.transform.position = Vector3.one * 4f;

            subject.Sources.Add(source);
            subject.Targets.Add(target1);
            subject.Targets.Add(target2);
            subject.Targets.Add(target3);

            FollowModifierMock followModifierMock = containingObject.AddComponent <FollowModifierMock>();

            subject.FollowModifier = followModifierMock;

            subject.Process();

            Assert.IsTrue(preprocessedMock.Received);
            Assert.IsTrue(processedMock.Received);
            Assert.AreEqual(source.transform.position, target1.transform.position);
            Assert.AreEqual(source.transform.position, target2.transform.position);
            Assert.AreEqual(source.transform.position, target3.transform.position);

            Object.DestroyImmediate(source);
            Object.DestroyImmediate(target1);
            Object.DestroyImmediate(target2);
            Object.DestroyImmediate(target3);
        }
        public void ProcessFirstActiveTargetOnlyLastActive()
        {
            UnityEventListenerMock preprocessedMock = new UnityEventListenerMock();
            UnityEventListenerMock processedMock    = new UnityEventListenerMock();

            subject.Preprocessed.AddListener(preprocessedMock.Listen);
            subject.Processed.AddListener(processedMock.Listen);

            GameObject source = new GameObject("source");

            GameObject[] targets = new GameObject[]
            {
                new GameObject("target1"),
                new GameObject("target2"),
                new GameObject("target3")
            };

            subject.sourceComponent = source.transform;
            subject.targetComponents.Add(targets[0].transform);
            subject.targetComponents.Add(targets[1].transform);
            subject.targetComponents.Add(targets[2].transform);

            FollowModifierMock followModifierMock = containingObject.AddComponent <FollowModifierMock>();

            subject.modificationType = ObjectFollower.ModificationType.ModifySourceUsingTarget;
            subject.processTarget    = ObjectFollower.ProcessTarget.FirstActive;
            subject.followModifier   = followModifierMock;

            targets[0].SetActive(false);
            targets[1].SetActive(false);

            subject.Process();

            Assert.IsTrue(preprocessedMock.Received);
            Assert.IsTrue(processedMock.Received);
            Assert.AreEqual(targets[0].transform, targets[0].transform);
            Assert.AreEqual(targets[1].transform, targets[1].transform);
            Assert.AreEqual(targets[2].transform, source.transform);
            Assert.AreEqual(source, followModifierMock.finalTarget);

            Object.DestroyImmediate(source);
            foreach (GameObject target in targets)
            {
                Object.DestroyImmediate(target);
            }
        }
        public void ProcessInactiveComponent()
        {
            UnityEventListenerMock preprocessedMock = new UnityEventListenerMock();
            UnityEventListenerMock processedMock    = new UnityEventListenerMock();

            subject.Preprocessed.AddListener(preprocessedMock.Listen);
            subject.Processed.AddListener(processedMock.Listen);

            GameObject source = new GameObject("source");

            GameObject[] targets = new GameObject[]
            {
                new GameObject("target1"),
                new GameObject("target2"),
                new GameObject("target3")
            };

            subject.sourceComponent = source.transform;
            subject.targetComponents.Add(targets[0].transform);
            subject.targetComponents.Add(targets[1].transform);
            subject.targetComponents.Add(targets[2].transform);

            FollowModifierMock followModifierMock = containingObject.AddComponent <FollowModifierMock>();

            subject.modificationType = ObjectFollower.ModificationType.ModifyTargetUsingSource;
            subject.processTarget    = ObjectFollower.ProcessTarget.All;
            subject.followModifier   = followModifierMock;

            subject.enabled = false;
            subject.Process();

            Assert.IsFalse(preprocessedMock.Received);
            Assert.IsFalse(processedMock.Received);
            Assert.AreEqual(targets[0].transform, targets[0].transform);
            Assert.AreEqual(targets[2].transform, targets[1].transform);
            Assert.AreEqual(targets[2].transform, targets[2].transform);
            Assert.IsNull(followModifierMock.finalSource);
            Assert.IsNull(followModifierMock.finalTarget);

            Object.DestroyImmediate(source);
            foreach (GameObject target in targets)
            {
                Object.DestroyImmediate(target);
            }
        }
        public void TargetOffsetNotChildException()
        {
            UnityEventListenerMock preprocessedMock = new UnityEventListenerMock();
            UnityEventListenerMock processedMock    = new UnityEventListenerMock();

            subject.Preprocessed.AddListener(preprocessedMock.Listen);
            subject.Processed.AddListener(processedMock.Listen);

            GameObject source = new GameObject("source");

            GameObject target1 = new GameObject("target1");
            GameObject target2 = new GameObject("target2");
            GameObject target3 = new GameObject("target3");

            GameObject targetOffset1 = new GameObject("targetOffset1");
            GameObject targetOffset2 = new GameObject("targetOffset2");
            GameObject targetOffset3 = new GameObject("targetOffset3");

            subject.AddSource(source);
            subject.AddTarget(target1);
            subject.AddTarget(target2);
            subject.AddTarget(target3);
            subject.AddTargetOffset(targetOffset1);
            subject.AddTargetOffset(targetOffset2);
            subject.AddTargetOffset(targetOffset3);

            FollowModifierMock followModifierMock = containingObject.AddComponent <FollowModifierMock>();

            subject.followModifier = followModifierMock;

            Assert.Throws <System.ArgumentException>(() => subject.Process());

            Assert.IsTrue(preprocessedMock.Received);
            Assert.IsFalse(processedMock.Received);

            Object.DestroyImmediate(source);
            Object.DestroyImmediate(target1);
            Object.DestroyImmediate(target2);
            Object.DestroyImmediate(target3);
            Object.DestroyImmediate(targetOffset1);
            Object.DestroyImmediate(targetOffset2);
            Object.DestroyImmediate(targetOffset3);
        }
        public IEnumerator AllTargetsFollowSourceWithOffsets()
        {
            UnityEventListenerMock preprocessedMock = new UnityEventListenerMock();
            UnityEventListenerMock processedMock    = new UnityEventListenerMock();

            subject.Preprocessed.AddListener(preprocessedMock.Listen);
            subject.Processed.AddListener(processedMock.Listen);

            GameObject source = new GameObject("source");

            GameObject target1 = new GameObject("target1");
            GameObject target2 = new GameObject("target2");
            GameObject target3 = new GameObject("target3");

            GameObject targetOffset1 = new GameObject("targetOffset1");
            GameObject targetOffset2 = new GameObject("targetOffset2");
            GameObject targetOffset3 = new GameObject("targetOffset3");

            subject.Sources       = containingObject.AddComponent <GameObjectObservableList>();
            subject.Targets       = containingObject.AddComponent <GameObjectObservableList>();
            subject.TargetOffsets = containingObject.AddComponent <GameObjectObservableList>();
            yield return(null);

            targetOffset1.transform.SetParent(target1.transform);
            targetOffset2.transform.SetParent(target2.transform);
            targetOffset3.transform.SetParent(target3.transform);

            source.transform.position = Vector3.one * 10f;

            target1.transform.position = Vector3.one * 2f;
            target2.transform.position = Vector3.one * 3f;
            target3.transform.position = Vector3.one * 4f;

            targetOffset1.transform.localPosition = Vector3.one;
            targetOffset2.transform.localPosition = Vector3.one * 2f;
            targetOffset3.transform.localPosition = Vector3.one * 3f;

            subject.Sources.Add(source);
            subject.Targets.Add(target1);
            subject.Targets.Add(target2);
            subject.Targets.Add(target3);

            subject.TargetOffsets.Add(targetOffset1);
            subject.TargetOffsets.Add(targetOffset2);
            subject.TargetOffsets.Add(targetOffset3);

            FollowModifierMock followModifierMock = containingObject.AddComponent <FollowModifierMock>();

            subject.FollowModifier = followModifierMock;

            subject.Process();

            Assert.IsTrue(preprocessedMock.Received);
            Assert.IsTrue(processedMock.Received);

            Assert.AreEqual(source.transform.position - targetOffset1.transform.localPosition, target1.transform.position);
            Assert.AreEqual(source.transform.position - targetOffset2.transform.localPosition, target2.transform.position);
            Assert.AreEqual(source.transform.position - targetOffset3.transform.localPosition, target3.transform.position);

            Object.DestroyImmediate(source);
            Object.DestroyImmediate(target1);
            Object.DestroyImmediate(target2);
            Object.DestroyImmediate(target3);
            Object.DestroyImmediate(targetOffset1);
            Object.DestroyImmediate(targetOffset2);
            Object.DestroyImmediate(targetOffset3);
        }