Skip to content

Commit

Permalink
feat(Cast): add points cast event proxy emitter
Browse files Browse the repository at this point in the history
The PointsCastEventProxyEmitter allows Points Cast data to be proxied.
  • Loading branch information
thestonefox committed Apr 30, 2023
1 parent d1d8c2e commit 24d5c1a
Show file tree
Hide file tree
Showing 8 changed files with 308 additions and 0 deletions.
8 changes: 8 additions & 0 deletions Runtime/Cast/Event.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions Runtime/Cast/Event/Proxy.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

73 changes: 73 additions & 0 deletions Runtime/Cast/Event/Proxy/PointsCastEventProxyEmitter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
namespace Zinnia.Cast.Event.Proxy
{
using System;
using UnityEngine;
using UnityEngine.Events;
using Zinnia.Event.Proxy;
using Zinnia.Extension;

/// <summary>
/// Emits a <see cref="UnityEvent"/> with a <see cref="PointsCast.EventData"/> payload whenever <see cref="SingleEventProxyEmitter{TValue,TEvent}.Receive"/> is called.
/// </summary>
public class PointsCastEventProxyEmitter : RestrictableSingleEventProxyEmitter<PointsCast.EventData, PointsCastEventProxyEmitter.UnityEvent>
{
/// <summary>
/// The types of <see cref="GameObject"/> that can be used for the rule source.
/// </summary>
public enum RuleSourceType
{
/// <summary>
/// Use the actual <see cref="Collider"/> hit as the source for the rule.
/// </summary>
Collider,
/// <summary>
/// Use the parent <see cref="Rigidbody"/> hit as the target for the rule.
/// </summary>
Rigidbody
}

[Tooltip("The source GameObject to apply to the RestrictableSingleEventProxyEmitter.ReceiveValidity.")]
[SerializeField]
private RuleSourceType ruleSource;
/// <summary>
/// The source <see cref="GameObject"/> to apply to the <see cref="RestrictableSingleEventProxyEmitter.ReceiveValidity"/>.
/// </summary>
public RuleSourceType RuleSource
{
get
{
return ruleSource;
}
set
{
ruleSource = value;
}
}

/// <summary>
/// Defines the event with the specified state.
/// </summary>
[Serializable]
public class UnityEvent : UnityEvent<PointsCast.EventData> { }

/// <inheritdoc />
protected override object GetTargetToCheck()
{
if (Payload == null || Payload.HitData == null)
{
return null;
}

RaycastHit hitData = (RaycastHit)Payload.HitData;
switch (RuleSource)
{
case RuleSourceType.Collider:
return hitData.collider.gameObject;
case RuleSourceType.Rigidbody:
return hitData.collider.GetContainingTransform().gameObject;
}

return null;
}
}
}
11 changes: 11 additions & 0 deletions Runtime/Cast/Event/Proxy/PointsCastEventProxyEmitter.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions Tests/Editor/Cast/Event.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions Tests/Editor/Cast/Event/Proxy.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

181 changes: 181 additions & 0 deletions Tests/Editor/Cast/Event/Proxy/PointsCastEventProxyEmitterTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
using Zinnia.Cast;
using Zinnia.Cast.Event.Proxy;
using Zinnia.Data.Collection.List;
using Zinnia.Rule;

namespace Test.Zinnia.Cast.Event.Proxy
{
using NUnit.Framework;
using Test.Zinnia.Utility.Helper;
using Test.Zinnia.Utility.Mock;
using UnityEngine;

public class PointsCastEventProxyEmitterTest
{
private GameObject containingObject;
private PointsCastEventProxyEmitter subject;

[SetUp]
public void SetUp()
{
containingObject = new GameObject("PointsCastEventProxyEmitterTest");
subject = containingObject.AddComponent<PointsCastEventProxyEmitter>();
}

[TearDown]
public void TearDown()
{
Object.DestroyImmediate(containingObject);
}

[Test]
public void Receive()
{
UnityEventListenerMock emittedMock = new UnityEventListenerMock();
subject.Emitted.AddListener(emittedMock.Listen);

PointsCast.EventData data = new PointsCast.EventData();
data.HitData = RaycastHitHelper.GetRaycastHit();
data.IsValid = true;

Assert.IsNull(subject.Payload);
Assert.IsFalse(emittedMock.Received);

subject.Receive(data);

Assert.AreEqual(data, subject.Payload);
Assert.IsTrue(emittedMock.Received);
}

[Test]
public void ReceiveWithRuleRestrictions()
{
UnityEventListenerMock emittedMock = new UnityEventListenerMock();
subject.Emitted.AddListener(emittedMock.Listen);

GameObject validBlockerParent = new GameObject("PointsCastEventProxyEmitterTest_validParent");
validBlockerParent.AddComponent<Rigidbody>().isKinematic = true;
GameObject validBlockerChild = GameObject.CreatePrimitive(PrimitiveType.Cube);
validBlockerChild.name = "PointsCastEventProxyEmitterTest_validChild";
validBlockerChild.transform.SetParent(validBlockerParent.transform);
validBlockerParent.transform.position = Vector3.left + Vector3.forward;

GameObject invalidBlockerParent = new GameObject("PointsCastEventProxyEmitterTest_invalidParent");
invalidBlockerParent.AddComponent<Rigidbody>().isKinematic = true;
GameObject invalidBlockerChild = GameObject.CreatePrimitive(PrimitiveType.Cube);
invalidBlockerChild.name = "PointsCastEventProxyEmitterTest_invalidChild";
invalidBlockerChild.transform.SetParent(invalidBlockerParent.transform);
invalidBlockerParent.transform.position = Vector3.right + Vector3.forward;

ListContainsRule rule = subject.gameObject.AddComponent<ListContainsRule>();
UnityObjectObservableList objects = containingObject.AddComponent<UnityObjectObservableList>();
rule.Objects = objects;

objects.Add(validBlockerChild);
subject.ReceiveValidity = new RuleContainer
{
Interface = rule
};

subject.RuleSource = PointsCastEventProxyEmitter.RuleSourceType.Collider;

PointsCast.EventData data = new PointsCast.EventData();
data.HitData = RaycastHitHelper.GetRaycastHit(validBlockerParent, false, Vector3.left, Vector3.forward);
data.IsValid = true;

Assert.IsNull(subject.Payload);
Assert.IsFalse(emittedMock.Received);

subject.Receive(data);

Assert.AreEqual(data, subject.Payload);
Assert.IsTrue(emittedMock.Received);

subject.Payload = null;
emittedMock.Reset();

subject.RuleSource = PointsCastEventProxyEmitter.RuleSourceType.Rigidbody;

subject.Receive(data);

Assert.IsNull(subject.Payload);
Assert.IsFalse(emittedMock.Received);

subject.Payload = null;
emittedMock.Reset();

objects.Add(validBlockerParent);

subject.Receive(data);

Assert.AreEqual(data, subject.Payload);
Assert.IsTrue(emittedMock.Received);

subject.Payload = null;
emittedMock.Reset();

subject.RuleSource = PointsCastEventProxyEmitter.RuleSourceType.Collider;

data.HitData = RaycastHitHelper.GetRaycastHit(invalidBlockerParent, false, Vector3.right, Vector3.forward);
data.IsValid = true;

subject.Receive(data);

Assert.IsNull(subject.Payload);
Assert.IsFalse(emittedMock.Received);

subject.Payload = null;
emittedMock.Reset();

subject.RuleSource = PointsCastEventProxyEmitter.RuleSourceType.Rigidbody;

subject.Receive(data);

Assert.IsNull(subject.Payload);
Assert.IsFalse(emittedMock.Received);

Object.DestroyImmediate(validBlockerParent);
Object.DestroyImmediate(invalidBlockerParent);
}

[Test]
public void ReceiveInactiveGameObject()
{
UnityEventListenerMock emittedMock = new UnityEventListenerMock();
subject.Emitted.AddListener(emittedMock.Listen);
PointsCast.EventData data = new PointsCast.EventData();
data.HitData = RaycastHitHelper.GetRaycastHit();
data.IsValid = true;

subject.gameObject.SetActive(false);

Assert.IsNull(subject.Payload);
Assert.IsFalse(emittedMock.Received);

subject.Receive(data);

Assert.IsNull(subject.Payload);
Assert.IsFalse(emittedMock.Received);
}

[Test]
public void ReceiveInactiveComponent()
{
UnityEventListenerMock emittedMock = new UnityEventListenerMock();
subject.Emitted.AddListener(emittedMock.Listen);
PointsCast.EventData data = new PointsCast.EventData();
data.HitData = RaycastHitHelper.GetRaycastHit();
data.IsValid = true;

subject.enabled = false;

Assert.IsNull(subject.Payload);
Assert.IsFalse(emittedMock.Received);

subject.Receive(data);

Assert.IsNull(subject.Payload);
Assert.IsFalse(emittedMock.Received);
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 24d5c1a

Please sign in to comment.