From ee03c55a80dd0541d1302a768e7379cb30672f82 Mon Sep 17 00:00:00 2001 From: extendreality Date: Sat, 6 Jun 2020 16:31:46 +0100 Subject: [PATCH 1/3] fix(Operation): suppress obsolete warning messages in cache tests The Cache operations have been deprecated but the tests still actively use the components to test them and therefore throws warning messages about the use of deprecated components. It's right to keep the tests but just suppress the warnings. --- Tests/Editor/Data/Operation/Cache/FloatCacheTest.cs | 4 ++++ Tests/Editor/Data/Operation/Cache/GameObjectCacheTest.cs | 4 ++++ Tests/Editor/Data/Operation/Cache/IntCacheTest.cs | 4 ++++ Tests/Editor/Data/Operation/Cache/StringCacheTest.cs | 4 ++++ Tests/Editor/Data/Operation/Cache/Vector2CacheTest.cs | 4 ++++ Tests/Editor/Data/Operation/Cache/Vector3CacheTest.cs | 4 ++++ 6 files changed, 24 insertions(+) diff --git a/Tests/Editor/Data/Operation/Cache/FloatCacheTest.cs b/Tests/Editor/Data/Operation/Cache/FloatCacheTest.cs index f1089c22..1f71498c 100644 --- a/Tests/Editor/Data/Operation/Cache/FloatCacheTest.cs +++ b/Tests/Editor/Data/Operation/Cache/FloatCacheTest.cs @@ -10,13 +10,17 @@ namespace Test.Zinnia.Data.Operation.Cache public class FloatCacheTest { private GameObject containingObject; +#pragma warning disable 0618 private FloatCache subject; +#pragma warning restore 0618 [SetUp] public void SetUp() { containingObject = new GameObject(); +#pragma warning disable 0618 subject = containingObject.AddComponent(); +#pragma warning restore 0618 } [TearDown] diff --git a/Tests/Editor/Data/Operation/Cache/GameObjectCacheTest.cs b/Tests/Editor/Data/Operation/Cache/GameObjectCacheTest.cs index 9f955730..2b173daf 100644 --- a/Tests/Editor/Data/Operation/Cache/GameObjectCacheTest.cs +++ b/Tests/Editor/Data/Operation/Cache/GameObjectCacheTest.cs @@ -10,13 +10,17 @@ namespace Test.Zinnia.Data.Operation.Cache public class GameObjectCacheTest { private GameObject containingObject; +#pragma warning disable 0618 private GameObjectCache subject; +#pragma warning restore 0618 [SetUp] public void SetUp() { containingObject = new GameObject(); +#pragma warning disable 0618 subject = containingObject.AddComponent(); +#pragma warning restore 0618 } [TearDown] diff --git a/Tests/Editor/Data/Operation/Cache/IntCacheTest.cs b/Tests/Editor/Data/Operation/Cache/IntCacheTest.cs index f73cc62e..7b421f25 100644 --- a/Tests/Editor/Data/Operation/Cache/IntCacheTest.cs +++ b/Tests/Editor/Data/Operation/Cache/IntCacheTest.cs @@ -10,13 +10,17 @@ namespace Test.Zinnia.Data.Operation.Cache public class IntCacheTest { private GameObject containingObject; +#pragma warning disable 0618 private IntCache subject; +#pragma warning restore 0618 [SetUp] public void SetUp() { containingObject = new GameObject(); +#pragma warning disable 0618 subject = containingObject.AddComponent(); +#pragma warning restore 0618 } [TearDown] diff --git a/Tests/Editor/Data/Operation/Cache/StringCacheTest.cs b/Tests/Editor/Data/Operation/Cache/StringCacheTest.cs index f7c35437..452ac591 100644 --- a/Tests/Editor/Data/Operation/Cache/StringCacheTest.cs +++ b/Tests/Editor/Data/Operation/Cache/StringCacheTest.cs @@ -10,13 +10,17 @@ namespace Test.Zinnia.Data.Operation.Cache public class StringCacheTest { private GameObject containingObject; +#pragma warning disable 0618 private StringCache subject; +#pragma warning restore 0618 [SetUp] public void SetUp() { containingObject = new GameObject(); +#pragma warning disable 0618 subject = containingObject.AddComponent(); +#pragma warning restore 0618 } [TearDown] diff --git a/Tests/Editor/Data/Operation/Cache/Vector2CacheTest.cs b/Tests/Editor/Data/Operation/Cache/Vector2CacheTest.cs index 4631ffd4..543d6910 100644 --- a/Tests/Editor/Data/Operation/Cache/Vector2CacheTest.cs +++ b/Tests/Editor/Data/Operation/Cache/Vector2CacheTest.cs @@ -10,13 +10,17 @@ namespace Test.Zinnia.Data.Operation.Cache public class Vector2CacheTest { private GameObject containingObject; +#pragma warning disable 0618 private Vector2Cache subject; +#pragma warning restore 0618 [SetUp] public void SetUp() { containingObject = new GameObject(); +#pragma warning disable 0618 subject = containingObject.AddComponent(); +#pragma warning restore 0618 } [TearDown] diff --git a/Tests/Editor/Data/Operation/Cache/Vector3CacheTest.cs b/Tests/Editor/Data/Operation/Cache/Vector3CacheTest.cs index 90421cf8..fbf75a59 100644 --- a/Tests/Editor/Data/Operation/Cache/Vector3CacheTest.cs +++ b/Tests/Editor/Data/Operation/Cache/Vector3CacheTest.cs @@ -10,13 +10,17 @@ namespace Test.Zinnia.Data.Operation.Cache public class Vector3CacheTest { private GameObject containingObject; +#pragma warning disable 0618 private Vector3Cache subject; +#pragma warning restore 0618 [SetUp] public void SetUp() { containingObject = new GameObject(); +#pragma warning disable 0618 subject = containingObject.AddComponent(); +#pragma warning restore 0618 } [TearDown] From 05c5e21c74d045b249a664144c2967c3c87e6e06 Mon Sep 17 00:00:00 2001 From: extendreality Date: Sat, 6 Jun 2020 16:37:08 +0100 Subject: [PATCH 2/3] feat(Process): emit event when SourceTragetProcessor source changes The SourceTargetProcessor now emits an event when the ActiveSource being used for the process changes. It also emits the initial value as ActiveSource starts as `null` and when it is first enabled and called then ActiveSource will be changed from `null` and therefore it will emit the event. --- .../GameObjectSourceTargetProcessor.cs | 10 +++++++- .../Component/SourceTargetProcessor.cs | 22 ++++++++++++++++- .../GameObjectSourceTargetProcessorTest.cs | 24 +++++++++++++++++++ 3 files changed, 54 insertions(+), 2 deletions(-) diff --git a/Runtime/Process/Component/GameObjectSourceTargetProcessor.cs b/Runtime/Process/Component/GameObjectSourceTargetProcessor.cs index 3bbd8e12..8846c42f 100644 --- a/Runtime/Process/Component/GameObjectSourceTargetProcessor.cs +++ b/Runtime/Process/Component/GameObjectSourceTargetProcessor.cs @@ -4,7 +4,9 @@ using Malimbe.MemberClearanceMethod; using Malimbe.PropertySerializationAttribute; using Malimbe.XmlDocumentationAttribute; + using System; using UnityEngine; + using UnityEngine.Events; using Zinnia.Data.Collection.List; using Zinnia.Extension; using Zinnia.Rule; @@ -12,8 +14,14 @@ /// /// A that specifically processes a . /// - public abstract class GameObjectSourceTargetProcessor : SourceTargetProcessor + public abstract class GameObjectSourceTargetProcessor : SourceTargetProcessor { + /// + /// Defines the event with the . + /// + [Serializable] + public class GameObjectUnityEvent : UnityEvent { } + #region Processor Settings /// /// A collection of sources to apply data from. diff --git a/Runtime/Process/Component/SourceTargetProcessor.cs b/Runtime/Process/Component/SourceTargetProcessor.cs index 6f37e7b3..cb92b53f 100644 --- a/Runtime/Process/Component/SourceTargetProcessor.cs +++ b/Runtime/Process/Component/SourceTargetProcessor.cs @@ -4,13 +4,20 @@ using Malimbe.XmlDocumentationAttribute; using System.Collections.Generic; using UnityEngine; + using UnityEngine.Events; using Zinnia.Data.Type; /// /// An that runs a set method on each (or the first active) source collection against a collection of targets. /// - public abstract class SourceTargetProcessor : MonoBehaviour, IProcessable + public abstract class SourceTargetProcessor : MonoBehaviour, IProcessable where TEvent : UnityEvent, new() { + /// + /// Emitted if the value is going to change with the new value as the payload. + /// + [DocumentedByXml] + public TEvent ActiveSourceChanging = new TEvent(); + /// /// Whether to cease the processing of the source collection after the first valid source is processed. /// @@ -73,6 +80,7 @@ protected virtual bool IsTargetValid(TTarget target) /// The targets to apply the data to. protected virtual void ApplySourcesToTargets(HeapAllocationFreeReadOnlyList sources, HeapAllocationFreeReadOnlyList targets) { + bool foundValidSource = false; for (int sourceIndex = 0; sourceIndex < sources.Count; sourceIndex++) { TSource currentSource = sources[sourceIndex]; @@ -93,12 +101,24 @@ protected virtual void ApplySourcesToTargets(HeapAllocationFreeReadOnlyList.Default.Equals(ActiveSource, currentSource)) + { + ActiveSourceChanging?.Invoke(currentSource); + } ActiveSource = currentSource; + foundValidSource = true; + if (CeaseAfterFirstSourceProcessed) { break; } } + + if (!foundValidSource && !EqualityComparer.Default.Equals(ActiveSource, default)) + { + ActiveSource = default; + ActiveSourceChanging?.Invoke(default); + } } } } \ No newline at end of file diff --git a/Tests/Editor/Process/Component/GameObjectSourceTargetProcessorTest.cs b/Tests/Editor/Process/Component/GameObjectSourceTargetProcessorTest.cs index 2152910f..826f48f7 100644 --- a/Tests/Editor/Process/Component/GameObjectSourceTargetProcessorTest.cs +++ b/Tests/Editor/Process/Component/GameObjectSourceTargetProcessorTest.cs @@ -6,6 +6,7 @@ namespace Test.Zinnia.Process.Component { using NUnit.Framework; using System.Collections; + using Test.Zinnia.Utility.Mock; using Test.Zinnia.Utility.Stub; using UnityEngine; using UnityEngine.TestTools; @@ -206,6 +207,8 @@ public IEnumerator ProcessAllTargetsAgainstSource() GameObject target3 = new GameObject("target3"); subject.Sources = containingObject.AddComponent(); subject.Targets = containingObject.AddComponent(); + UnityEventListenerMock activeSourceChangedListenerMock = new UnityEventListenerMock(); + subject.ActiveSourceChanging.AddListener(activeSourceChangedListenerMock.Listen); yield return null; subject.Sources.Add(source1); @@ -218,7 +221,11 @@ public IEnumerator ProcessAllTargetsAgainstSource() Assert.AreEqual("target2", target2.name); Assert.AreEqual("target3", target3.name); + Assert.IsNull(subject.ActiveSource); + Assert.IsFalse(activeSourceChangedListenerMock.Received); subject.Process(); + Assert.IsTrue(activeSourceChangedListenerMock.Received); + Assert.AreEqual("source1", subject.ActiveSource.name); Assert.AreEqual("source1", source1.name); Assert.AreEqual("source1", target1.name); @@ -240,6 +247,8 @@ public IEnumerator ProcessFirstActiveSourceAgainstTargetThenCease() GameObject target1 = new GameObject("target1"); subject.Sources = containingObject.AddComponent(); subject.Targets = containingObject.AddComponent(); + UnityEventListenerMock activeSourceChangedListenerMock = new UnityEventListenerMock(); + subject.ActiveSourceChanging.AddListener(activeSourceChangedListenerMock.Listen); yield return null; subject.CeaseAfterFirstSourceProcessed = true; @@ -265,7 +274,11 @@ public IEnumerator ProcessFirstActiveSourceAgainstTargetThenCease() source2.SetActive(true); source3.SetActive(true); + Assert.IsNull(subject.ActiveSource); + Assert.IsFalse(activeSourceChangedListenerMock.Received); subject.Process(); + Assert.IsTrue(activeSourceChangedListenerMock.Received); + Assert.AreEqual("source2", subject.ActiveSource.name); Assert.AreEqual("source1", source1.name); Assert.AreEqual("source2", source2.name); @@ -276,7 +289,10 @@ public IEnumerator ProcessFirstActiveSourceAgainstTargetThenCease() source2.SetActive(false); source3.SetActive(true); + activeSourceChangedListenerMock.Reset(); subject.Process(); + Assert.IsTrue(activeSourceChangedListenerMock.Received); + Assert.AreEqual("source3", subject.ActiveSource.name); Assert.AreEqual("source1", source1.name); Assert.AreEqual("source2", source2.name); @@ -287,13 +303,21 @@ public IEnumerator ProcessFirstActiveSourceAgainstTargetThenCease() source2.SetActive(true); source3.SetActive(true); + activeSourceChangedListenerMock.Reset(); subject.Process(); + Assert.IsTrue(activeSourceChangedListenerMock.Received); + Assert.AreEqual("source1", subject.ActiveSource.name); Assert.AreEqual("source1", source1.name); Assert.AreEqual("source2", source2.name); Assert.AreEqual("source3", source3.name); Assert.AreEqual("source1", target1.name); + activeSourceChangedListenerMock.Reset(); + subject.Process(); + Assert.IsFalse(activeSourceChangedListenerMock.Received); + Assert.AreEqual("source1", subject.ActiveSource.name); + Object.DestroyImmediate(source1); Object.DestroyImmediate(source2); Object.DestroyImmediate(source3); From 6f62f49d4fb81cd2bacbe35979e30496c0ea3022 Mon Sep 17 00:00:00 2001 From: extendreality Date: Sat, 6 Jun 2020 16:39:36 +0100 Subject: [PATCH 3/3] feat(Mutation): allow limiting axes on mutator offsets The TransformPositionMutator has a Facing Direction offset that can be provided which is used to offset the forward direction based on the rotation of this optional offset GameObject. It is now possible to determine which axes of that offset should be used when utilizing the rotation data as there are occurrences where not all of the offset rotations are wanted. The TransformEulerRotationMutator has an Origin offset that can be used to rotate around a different pivot point position. It is now possible to determine which axes of direction should be used from the optional pivot point as sometimes not all axes may be required. --- .../Mutation/RigidbodyPropertyMutator.cs | 2 +- .../Mutation/TransformEulerRotationMutator.cs | 38 +++++++++++++++++-- .../Mutation/TransformPositionMutator.cs | 28 +++++++++++++- .../Mutation/TransformPropertyMutator.cs | 4 +- .../TransformEulerRotationMutatorTest.cs | 29 ++++++++++++++ .../Mutation/TransformPositionMutatorTest.cs | 25 ++++++++++++ 6 files changed, 119 insertions(+), 7 deletions(-) diff --git a/Runtime/Data/Operation/Mutation/RigidbodyPropertyMutator.cs b/Runtime/Data/Operation/Mutation/RigidbodyPropertyMutator.cs index 9301e7b9..c55e8e45 100644 --- a/Runtime/Data/Operation/Mutation/RigidbodyPropertyMutator.cs +++ b/Runtime/Data/Operation/Mutation/RigidbodyPropertyMutator.cs @@ -14,7 +14,7 @@ public class RigidbodyPropertyMutator : MonoBehaviour { /// - /// The rigidbody to mutate. + /// The to mutate. /// [Serialized, Cleared] [field: DocumentedByXml] diff --git a/Runtime/Data/Operation/Mutation/TransformEulerRotationMutator.cs b/Runtime/Data/Operation/Mutation/TransformEulerRotationMutator.cs index b7db9ab1..76cac548 100644 --- a/Runtime/Data/Operation/Mutation/TransformEulerRotationMutator.cs +++ b/Runtime/Data/Operation/Mutation/TransformEulerRotationMutator.cs @@ -6,18 +6,28 @@ using Malimbe.XmlDocumentationAttribute; using System; using UnityEngine; + using Zinnia.Data.Type; + using Zinnia.Extension; /// /// Mutates the euler rotation of a transform with an optional custom rotation origin. /// public class TransformEulerRotationMutator : TransformPropertyMutator { + #region Rotation Settings /// /// An optional rotation origin to perform the rotation around. The origin must be a child of the . /// [Serialized, Cleared] - [field: DocumentedByXml] + [field: Header("Rotation Settings"), DocumentedByXml] public GameObject Origin { get; set; } + /// + /// Determines which axes to consider from the . + /// + [Serialized] + [field: DocumentedByXml] + public Vector3State ApplyOriginOnAxis { get; set; } = Vector3State.True; + #endregion /// protected override float GetGlobalAxisValue(int axis) @@ -82,7 +92,29 @@ protected virtual void OnEnable() /// The origin position. protected virtual Vector3 GetOriginPosition() { - return Origin != null ? Origin.transform.position : Vector3.zero; + if (Origin == null) + { + return Vector3.zero; + } + + Vector3 originAxesToApply = ApplyOriginOnAxis.ToVector3(); + Vector3? cachedOriginLocalPosition = null; + + if (!originAxesToApply.ApproxEquals(Vector3.one)) + { + cachedOriginLocalPosition = Origin.transform.localPosition; + originAxesToApply.Scale(Origin.transform.localPosition); + Origin.transform.localPosition = originAxesToApply; + } + + Vector3 returnValue = Origin.transform.position; + + if (cachedOriginLocalPosition != null) + { + Origin.transform.localPosition = cachedOriginLocalPosition.GetValueOrDefault(); + } + + return returnValue; } /// @@ -96,7 +128,7 @@ protected virtual void ApplyRotationOriginPosition(Vector3 originPosition) return; } - originPosition -= Origin.transform.position; + originPosition -= GetOriginPosition(); Target.transform.position += originPosition; } diff --git a/Runtime/Data/Operation/Mutation/TransformPositionMutator.cs b/Runtime/Data/Operation/Mutation/TransformPositionMutator.cs index 183d54df..6ad426b6 100644 --- a/Runtime/Data/Operation/Mutation/TransformPositionMutator.cs +++ b/Runtime/Data/Operation/Mutation/TransformPositionMutator.cs @@ -4,18 +4,28 @@ using Malimbe.PropertySerializationAttribute; using Malimbe.XmlDocumentationAttribute; using UnityEngine; + using Zinnia.Data.Type; + using Zinnia.Extension; /// /// Mutates the position of a transform with an optional facing direction. /// public class TransformPositionMutator : TransformPropertyMutator { + #region Position Settings /// /// Determines the facing direction when mutating the position. /// [Serialized, Cleared] - [field: DocumentedByXml] + [field: Header("Position Settings"), DocumentedByXml] public GameObject FacingDirection { get; set; } + /// + /// Determines which axes to take from the . + /// + [Serialized] + [field: DocumentedByXml] + public Vector3State ApplyFacingDirectionOnAxis { get; set; } = Vector3State.True; + #endregion /// protected override float GetGlobalAxisValue(int axis) @@ -59,7 +69,21 @@ protected override Vector3 SetLocal(Vector3 input) /// The facing direction. protected virtual Quaternion GetFacingDirection() { - return FacingDirection == null ? Quaternion.identity : (UseLocalValues ? FacingDirection.transform.localRotation : FacingDirection.transform.rotation); + if (FacingDirection == null) + { + return Quaternion.identity; + } + + Quaternion returnValue = UseLocalValues ? FacingDirection.transform.localRotation : FacingDirection.transform.rotation; + Vector3 facingAxesToApply = ApplyFacingDirectionOnAxis.ToVector3(); + + if (facingAxesToApply.ApproxEquals(Vector3.one)) + { + return returnValue; + } + + facingAxesToApply.Scale(returnValue.eulerAngles); + return Quaternion.Euler(facingAxesToApply); } } } \ No newline at end of file diff --git a/Runtime/Data/Operation/Mutation/TransformPropertyMutator.cs b/Runtime/Data/Operation/Mutation/TransformPropertyMutator.cs index 62653b42..9f96b46e 100644 --- a/Runtime/Data/Operation/Mutation/TransformPropertyMutator.cs +++ b/Runtime/Data/Operation/Mutation/TransformPropertyMutator.cs @@ -12,11 +12,12 @@ /// public abstract class TransformPropertyMutator : MonoBehaviour { + #region Target Settings /// /// The target to mutate. /// [Serialized, Cleared] - [field: DocumentedByXml] + [field: Header("Target Settings"), DocumentedByXml] public GameObject Target { get; set; } /// /// Determines whether to mutate the local or global values. @@ -30,6 +31,7 @@ public abstract class TransformPropertyMutator : MonoBehaviour [Serialized] [field: DocumentedByXml] public Vector3State MutateOnAxis { get; set; } = Vector3State.True; + #endregion /// /// Sets the property to the new value. diff --git a/Tests/Editor/Data/Operation/Mutation/TransformEulerRotationMutatorTest.cs b/Tests/Editor/Data/Operation/Mutation/TransformEulerRotationMutatorTest.cs index e64d4540..c7bf6f10 100644 --- a/Tests/Editor/Data/Operation/Mutation/TransformEulerRotationMutatorTest.cs +++ b/Tests/Editor/Data/Operation/Mutation/TransformEulerRotationMutatorTest.cs @@ -4,6 +4,7 @@ namespace Test.Zinnia.Data.Operation.Mutation { using NUnit.Framework; + using NUnit.Framework.Constraints; using UnityEngine; using Assert = UnityEngine.Assertions.Assert; @@ -133,6 +134,34 @@ public void SetPropertyWithOrigin() Object.DestroyImmediate(target); } + [Test] + public void SetPropertyWithOriginIgnoreZ() + { + GameObject target = new GameObject(); + GameObject origin = new GameObject(); + origin.transform.SetParent(target.transform); + + subject.Target = target; + subject.Origin = origin; + subject.MutateOnAxis = new Vector3State(false, true, false); + subject.ApplyOriginOnAxis = new Vector3State(true, true, false); + + origin.transform.position = new Vector3(1f, 0f, 1f); + + Assert.AreEqual(Vector3.zero, target.transform.eulerAngles); + + Vector3 inputRotation = new Vector3(10f, 20f, 30f); + Vector3 expectedRotation = new Vector3(0f, 20f, 0f); + Vector3 expectedPosition = new Vector3(0.1f, 0f, 0.3f); + + subject.SetProperty(inputRotation); + + Assert.AreEqual(expectedRotation.ToString(), target.transform.eulerAngles.ToString()); + Assert.AreEqual(expectedPosition.ToString(), target.transform.position.ToString()); + + Object.DestroyImmediate(target); + } + [Test] public void IncrementPropertyLocal() { diff --git a/Tests/Editor/Data/Operation/Mutation/TransformPositionMutatorTest.cs b/Tests/Editor/Data/Operation/Mutation/TransformPositionMutatorTest.cs index b9f8fdcb..534e7c6c 100644 --- a/Tests/Editor/Data/Operation/Mutation/TransformPositionMutatorTest.cs +++ b/Tests/Editor/Data/Operation/Mutation/TransformPositionMutatorTest.cs @@ -423,6 +423,31 @@ public void IncrementPropertyGlobalLockXZAxisWithOffset() Object.DestroyImmediate(offset); } + [Test] + public void SetPropertyLocalWithOffsetIgnoreY() + { + GameObject target = new GameObject(); + GameObject offset = new GameObject(); + offset.transform.eulerAngles = new Vector3(10f, 20f, 30f); + + subject.Target = target; + subject.UseLocalValues = true; + subject.MutateOnAxis = Vector3State.True; + subject.FacingDirection = offset; + subject.ApplyFacingDirectionOnAxis = new Vector3State(true, false, true); + + Assert.AreEqual(Vector3.zero, target.transform.localPosition); + + Vector3 input = new Vector3(10f, 20f, 30f); + Vector3 expected = new Vector3(-1.3f, 16.8f, 33.4f); + subject.SetProperty(input); + + Assert.AreEqual(expected.ToString(), target.transform.localPosition.ToString()); + + Object.DestroyImmediate(target); + Object.DestroyImmediate(offset); + } + [Test] public void SetPropertyInactiveGameObject() {