Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Develop v0.1.0 #38

Closed
wants to merge 23 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
f723682
:name_badge: Rename to UniFlow instead of EventConnector
monry Aug 9, 2019
db3b767
:name_badge: Rename menu name
monry Aug 9, 2019
b616085
:memo: Update README.md
monry Aug 9, 2019
d95b33b
:name_badge: Remove `Event` from Receivers
monry Aug 9, 2019
7d9c538
:name_badge: Rename Receivers
monry Aug 9, 2019
883ec3d
:name_badge: Rename to Connector from Publisher
monry Aug 9, 2019
4ccf0cf
:recycle: Split structs
monry Aug 9, 2019
b4dfe62
:name_badge: Rename base classes
monry Aug 9, 2019
011c593
:name_badge: Rename fields
monry Aug 9, 2019
8e4957f
:name_badge: Apply field name changes
monry Aug 9, 2019
ff978ea
:clipboard: Re-numbering version
monry Aug 9, 2019
186f7d9
:memo: Fix installation section
monry Aug 9, 2019
65db2b4
:memo: Update README.md
monry Aug 9, 2019
f3285df
:name_badge: Rename method
monry Aug 10, 2019
9d53d01
:sparkles: Automatic add SimpleAnimation and Animator
monry Aug 10, 2019
6ff52ab
:sparkles: Automatic add AudioSource
monry Aug 10, 2019
f56b0f5
:sparkles: Add setter for SerializeField
monry Aug 10, 2019
878078b
:sparkles: Add setter for Connector properties
monry Aug 11, 2019
8fa008e
:sparkles: Avoid ArgumentException
monry Aug 11, 2019
7c268d6
Merge pull request #39 from monry/topic/avoid_enumerable_error
monry Aug 11, 2019
4dad64d
Merge pull request #40 from monry/topic/automatic_add_component
monry Aug 11, 2019
48aac41
:sparkles: Add ConnectorType.Custom
monry Aug 11, 2019
daf680a
Merge pull request #41 from monry/topic/add_custom_type
monry Aug 11, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 45 additions & 3 deletions Assets/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,51 @@
# Changelog

## [1.0.0] - YYYY-MM-DD
## [0.0.4-preview.5] - 2019-08-06

* Initial version
Refactor code

### Features

*
* Add Interval event

### Improvements

* Refactor codes
* Reverses reference direction between Publishers

## [0.0.3-preview.4] - 2019-08-06

Fix minor bugs

### Fixes

* Avoid `CS0649` warning
* Fix version conflicts in UniRx

## [0.0.2-preview.3] - 2019-08-06

Support many events

### Features

* Support Lifecycle events
* Support Physics/Physics2D events
* Support Camera, Transform, RectTransform events
* Support Audio events

### Improvements

* Connect events correctly
* Refresh EventMessages on re-invoke event

### Supports

* Supported Unity version bumped up to 2019.2

## [0.0.1] - 2019-07-21

Initial version

### Features

* Implements simple events
39 changes: 20 additions & 19 deletions Assets/README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# Event Connector
# UniFlow

EventConnector is a library that can connect various Unity events including user interaction without writing any C# script.
UniFlow is a library that can connect various Unity components without writing any C# script.

Processes such as "Tutorial that accepts user interaction" and "Waiting for the end of playback of Animation, Audio, Timeline, etc." can be implemented easily.
You can implement easily processes such as "Tutorial that accepts user interaction" and "Waiting for the end of playback of Animation, Audio, Timeline, etc.".

## Installation

```bash
upm add package dev.monry.upm.eventconnector
upm add package dev.monry.uniflow
```

Please refer to [this repository](https://github.com/upm-packages/upm-cli) about the `upm` command.
Expand All @@ -16,37 +16,38 @@ Please refer to [this repository](https://github.com/upm-packages/upm-cli) about

### Basics

#### 1. Attach EventPublishers
#### 1. Attach Connectors

Attach one or more Components what implements `IEventConnectable` listed below into GameObject.
Attach one or more Components what implements `ConnectorBase` listed below into GameObject.

#### 2. Implement EventReceiver
#### 2. Connect Connectors

Implement Component what inherits `EventReceiver`.
Set *Next `ConnectorBase`* into **Target Instances** field for each Connectors.

Implement the process you want to execute when the event is received in the `OnReceive()` method that needs to override by `EventReceiver`.
It is also possible to solve with `Zenject.ResolveIdAll<T>()` by setting ID in **Target Ids** field

This method will be passed `EventMessages` what contains all propagated event informations.
#### 3. Implement Receiver

#### 3. Connect EventConnectors and EventReceiver
Implement Component what inherits `ReceiverBase`.

Set **Next IEventConnectable** into *Target Connector Instances* field for each EventPublisher.
Implement the process you want to execute when the event is received in the `OnReceive()` method that needs to override by `ReceiverBase`.

It is also possible to solve with `Zenject.ResolveIdAll<T>()` by setting ID in *Target Connector Ids* field
This method will be passed `EventMessages` what contains all propagated event informations.

### Inspector

<img width="317" alt="inspector" src="https://user-images.githubusercontent.com/838945/62629227-bf136480-b967-11e9-850e-e336c1e912db.png">

#### Target Connector Instances
#### Target Instances

Specify instances what inherits `EventPublisher` or `EventReceiver` into this field.
Specify instances what inherits `ConnectableBase` into this field.<br />
\* `ConnectorBase` and `ReceiverBase` are inherits `ConnectableBase`

Fire messages at the correct time for each component.

#### Target Connector Instances
#### Target Ids

Specify IDs what provides instances of `EventPublisher` or `EventReceiver` resolved by `Zenject.ResolveIdAll()` into this field.
Specify IDs what provides instances of `IConnectable` resolved by `Zenject.ResolveIdAll()` into this field.

Fire messages at the correct time for each component.

Expand All @@ -58,11 +59,11 @@ Set true to allow to act as the entry point of events.

Set true to allow to act as the receiver of events.

#### Other parameters for each Publisher
#### Other parameters for each Connector

Individual parameters can be specified for each component.

## Components what inherits `EventPublisher`
## Components what inherits `ConnectorBase`

### Messaging from traditional callback

Expand Down
8 changes: 8 additions & 0 deletions Assets/Scripts/ConnectableBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using UnityEngine;

namespace UniFlow
{
public abstract class ConnectableBase : MonoBehaviour, IConnectable
{
}
}
90 changes: 82 additions & 8 deletions Assets/Scripts/Connector/AnimationEvent.cs
Original file line number Diff line number Diff line change
@@ -1,21 +1,83 @@
using System;
using System.Linq;
using JetBrains.Annotations;
using UniRx;
using UnityEngine;

namespace EventConnector.Connector
namespace UniFlow.Connector
{
// AnimationEvent cannot fire to Component attaching to another GameObject
[RequireComponent(typeof(Animator))]
[AddComponentMenu("Event Connector/AnimationEvent", 301)]
public class AnimationEvent : EventPublisher
[AddComponentMenu("UniFlow/AnimationEvent", 302)]
public class AnimationEvent : ConnectorBase
{
[SerializeField]
[Tooltip("If you do not specify it will be used SimpleAnimation setting")]
private AnimationClip animationClip = default;
private AnimationClip AnimationClip
{
get => animationClip;
[UsedImplicitly]
set => animationClip = value;
}

[SerializeField] private AnimatorCullingMode cullingMode = AnimatorCullingMode.AlwaysAnimate;
private AnimatorCullingMode CullingMode
{
get => cullingMode;
[UsedImplicitly]
set => cullingMode = value;
}

[SerializeField] private AnimatorUpdateMode updateMode = AnimatorUpdateMode.Normal;
private AnimatorUpdateMode UpdateMode
{
get => updateMode;
[UsedImplicitly]
set => updateMode = value;
}

private Animator animator = default;
private Animator Animator
{
get =>
animator != default
? animator
: animator =
GetComponent<Animator>() != default
? GetComponent<Animator>()
: gameObject.AddComponent<Animator>();
[UsedImplicitly]
set => animator = value;
}

private SimpleAnimation simpleAnimation = default;
private SimpleAnimation SimpleAnimation
{
get =>
simpleAnimation != default
? simpleAnimation
: simpleAnimation =
GetComponent<SimpleAnimation>() != default
? GetComponent<SimpleAnimation>()
: gameObject.AddComponent<SimpleAnimation>()
;
[UsedImplicitly]
set => simpleAnimation = value;
}

private ISubject<UnityEngine.AnimationEvent> Subject { get; } = new Subject<UnityEngine.AnimationEvent>();

public override IObservable<EventMessage> OnPublishAsObservable() =>
Subject
public override IObservable<EventMessage> OnConnectAsObservable()
{
if (AnimationClip != default && GetComponent<Animator>() == default && SimpleAnimation.GetStates().All(x => x.clip != AnimationClip))
{
SimpleAnimation.AddClip(AnimationClip, AnimationClip.GetInstanceID().ToString());
}

return Subject
// Prevents the previous flow from being re-invoked when triggered multiple times
.Take(1)
.Select(x => EventMessage.Create(EventType.AnimationEvent, this, x));
.Select(x => EventMessage.Create(ConnectorType.AnimationEvent, this, x));
}

/// <summary>
/// Invoked from AnimationEvent
Expand All @@ -26,5 +88,17 @@ public void Dispatch(UnityEngine.AnimationEvent animationEvent)
{
Subject.OnNext(animationEvent);
}

private void Awake()
{
// ReSharper disable once InvertIf
// Automatic add components Animator and SimpleAnimation if AudioClip specified and Animator component does not exists.
if (AnimationClip != default && Animator == default && SimpleAnimation.GetStates().All(x => x.clip != AnimationClip))
{
SimpleAnimation.AddClip(AnimationClip, AnimationClip.GetInstanceID().ToString());
SimpleAnimation.cullingMode = CullingMode;
Animator.updateMode = UpdateMode;
}
}
}
}
27 changes: 18 additions & 9 deletions Assets/Scripts/Connector/AnimatorTrigger.cs
Original file line number Diff line number Diff line change
@@ -1,34 +1,43 @@
using System;
using EventConnector.Message;
using JetBrains.Annotations;
using UniFlow.Message;
using UniRx;
using UnityEngine;

namespace EventConnector.Connector
namespace UniFlow.Connector
{
[AddComponentMenu("Event Connector/AnimatorTrigger", 300)]
public class AnimatorTrigger : EventPublisher
[AddComponentMenu("UniFlow/AnimatorTrigger", 301)]
public class AnimatorTrigger : ConnectorBase
{
[SerializeField]
[Tooltip("If you do not specify it will be obtained by GameObject.GetComponent<Animator>()")]
private Animator animator = default;
private Animator Animator => animator ? animator : animator = GetComponent<Animator>();

[SerializeField] private string triggerName = default;
private string TriggerName
{
get => triggerName;
[UsedImplicitly]
set => triggerName = value;
}

private Animator Animator => animator ? animator : animator = GetComponent<Animator>();
private string TriggerName => triggerName;
private int TriggerId => Animator.StringToHash(TriggerName);

private IDisposable Disposable { get; } = new CompositeDisposable();

public override IObservable<EventMessage> OnPublishAsObservable() =>
Observable
public override IObservable<EventMessage> OnConnectAsObservable()
{
return Observable
.Create<EventMessage>(
observer =>
{
Animator.SetTrigger(TriggerId);
observer.OnNext(EventMessage.Create(EventType.AnimatorTrigger, Animator, AnimatorTriggerEventData.Create(TriggerName)));
observer.OnNext(EventMessage.Create(ConnectorType.AnimatorTrigger, Animator, AnimatorTriggerEventData.Create(TriggerName)));
return Disposable;
}
);
}

private void OnDestroy()
{
Expand Down
57 changes: 46 additions & 11 deletions Assets/Scripts/Connector/AudioController.cs
Original file line number Diff line number Diff line change
@@ -1,33 +1,68 @@
using System;
using EventConnector.Message;
using JetBrains.Annotations;
using UniFlow.Message;
using UniRx;
using UnityEngine;

namespace EventConnector.Connector
namespace UniFlow.Connector
{
[AddComponentMenu("Event Connector/AudioController", 302)]
public class AudioController : EventPublisher
[AddComponentMenu("UniFlow/AudioController", 303)]
public class AudioController : ConnectorBase
{
[SerializeField] private AudioControlMethod audioControlMethod = default;
private AudioControlMethod AudioControlMethod
{
get => audioControlMethod;
[UsedImplicitly]
set => audioControlMethod = value;
}

[SerializeField]
[Tooltip("If you do not specify it will be obtained by GameObject.GetComponent<AudioSource>()")]
private AudioSource audioSource = default;
[Tooltip("If you do not specify it will be obtained by AudioSource.clip")]
private AudioClip audioClip = default;
private AudioClip AudioClip
{
get => audioClip;
[UsedImplicitly]
set => audioClip = value;
}

private AudioControlMethod AudioControlMethod => audioControlMethod;
private AudioSource AudioSource => audioSource ? audioSource : audioSource = GetComponent<AudioSource>();
private AudioSource audioSource = default;
private AudioSource AudioSource
{
get =>
audioSource != default
? audioSource
: audioSource =
GetComponent<AudioSource>() != default
? GetComponent<AudioSource>()
: gameObject.AddComponent<AudioSource>();
[UsedImplicitly]
set => audioSource = value;
}

private IDisposable Disposable { get; } = new CompositeDisposable();

public override IObservable<EventMessage> OnPublishAsObservable() =>
Observable
public override IObservable<EventMessage> OnConnectAsObservable()
{
return Observable
.Create<EventMessage>(
observer =>
{
InvokeAudioSourceMethod();
observer.OnNext(EventMessage.Create(EventType.AudioController, AudioSource, AudioControllerEventData.Create(AudioControlMethod)));
observer.OnNext(EventMessage.Create(ConnectorType.AudioController, AudioSource, AudioControllerEventData.Create(AudioControlMethod)));
return Disposable;
}
);
}

private void Awake()
{
if (AudioClip != default)
{
AudioSource.clip = AudioClip;
}
}

private void InvokeAudioSourceMethod()
{
Expand Down
Loading