Skip to content

Commit

Permalink
Merge pull request #95 from shiena/feature/support-r3
Browse files Browse the repository at this point in the history
Support R3
  • Loading branch information
AnnulusGames authored Mar 16, 2024
2 parents f25af85 + cc31b16 commit 0f83da1
Show file tree
Hide file tree
Showing 23 changed files with 375 additions and 15 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ The full version of documentation can be found [here](https://annulusgames.githu
- Character animation for TextMeshPro text.
- Motion Tracker Window for monitoring motions in progress.
- Convert to Observables using UniRx.
- Convert to Observables using R3.
- Supports async/await via UniTask.
- Extend types using `IMotionOptions` and `IMotionAdapter`.

Expand Down
1 change: 1 addition & 0 deletions README_JA.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ LitMotionは[Magic Tween](https://github.com/AnnulusGames/MagicTween)に続い
- TextMeshProのテキストを文字ごとにアニメーション可能
- MotionTrackerウィンドウによる動作中のモーションの追跡
- UniRxを利用したObservableへの変換
- R3を利用したObservableへの変換
- UniTaskを利用したasync/await対応
- `IMotionOptions``IMotionAdapter`を用いた型の拡張

Expand Down
28 changes: 28 additions & 0 deletions docs/articles/en/integration-r3.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# R3

By integrating [R3](https://github.com/Cysharp/R3) into your project, it adds extension methods compatible with Reactive Extensions (Rx).

If you have installed R3 via the Package Manager, the following functionality will be automatically added. However, if you have imported UniRx via a unitypackage or similar method, you'll need to add `LITMOTION_SUPPORT_R3` to `Settings > Player > Scripting Define Symbols`.

### Creating Motion as an Observable

You can create motion as an `IObservable<T>` using the `ToObservable()` method:

```cs
var observable = LMotion.Create(0f, 5f, 2f).ToObservable();
observable.Subscribe(x =>
{
Debug.Log(x);
})
.AddTo(gameObject);
```

### Binding to ReactiveProperty

There's a provided extension method to bind the created motion to a `ReactiveProperty<T>`:

```cs
var reactiveProperty = new ReactiveProperty<float>();
LMotion.Create(0f, 10f, 2f)
.BindToReactiveProperty(reactiveProperty);
```
2 changes: 1 addition & 1 deletion docs/articles/en/integration-unirx.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

By integrating [UniRx](https://github.com/neuecc/UniRx) into your project, it adds extension methods compatible with Reactive Extensions (Rx).

If you have installed UniRx via the Package Manager, the following functionality will be automatically added. However, if you have imported UniRx via a unitypackage or similar method, you'll need to add `LITMOTION_UNIRX_SUPPORT` to `Settings > Player > Scripting Define Symbols`.
If you have installed UniRx via the Package Manager, the following functionality will be automatically added. However, if you have imported UniRx via a unitypackage or similar method, you'll need to add `LITMOTION_SUPPORT_UNIRX` to `Settings > Player > Scripting Define Symbols`.

### Creating Motion as an Observable

Expand Down
2 changes: 1 addition & 1 deletion docs/articles/en/integration-unitask.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Introducing [UniTask](https://github.com/Cysharp/UniTask) into your project adds extension methods that allow motion waiting to be compatible with async/await.

If you have installed UniTask via the Package Manager, the following functionality will be automatically added. However, if you have imported UniTask via a unitypackage or similar method, you'll need to add `LITMOTION_UNITASK_SUPPORT` to `Settings > Player > Scripting Define Symbols`.
If you have installed UniTask via the Package Manager, the following functionality will be automatically added. However, if you have imported UniTask via a unitypackage or similar method, you'll need to add `LITMOTION_SUPPORT_UNITASK` to `Settings > Player > Scripting Define Symbols`.

### Waiting for Motion

Expand Down
4 changes: 3 additions & 1 deletion docs/articles/en/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@
href: motion-tracker.md

- name: Integrations
- name: R3
href: integration-r3.md
- name: UniRx
href: integration-unirx.md
- name: UniTask
Expand All @@ -56,4 +58,4 @@

- name: Concepts
- name: Design Philosophy
href: design-philosophy.md
href: design-philosophy.md
28 changes: 28 additions & 0 deletions docs/articles/ja/integration-r3.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# R3

プロジェクトに[R3](https://github.com/Cysharp/R3)を導入することでReactive Extensions(Rx)に対応した拡張メソッドが追加されます。

R3をPackage Managerから導入した場合は自動で以下の機能が追加されます。unitypackage等で導入した場合は、`Project Settings > Player > Scripting Define Symbols``LITMOTION_SUPPORT_R3`を追加する必要があります。

### モーションをObservableとして作成

`ToObservable()`を使用することで、モーションを`IObservable<T>`として作成できます。

```cs
var observable = LMotion.Create(0f, 5f, 2f).ToObservable();
observable.Subscribe(x =>
{
Debug.Log(x);
})
.AddTo(gameObject);
```

### ReactivePropertyへバインド

作成したモーションを`ReactiveProperty<T>`にバインドする拡張メソッドが用意されています。

```cs
var reactiveProperty = new ReactiveProperty<float>();
LMotion.Create(0f, 10f, 2f)
.BindToReactiveProperty(reactiveProperty);
```
2 changes: 1 addition & 1 deletion docs/articles/ja/integration-unirx.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

プロジェクトに[UniRx](https://github.com/neuecc/UniRx)を導入することでReactive Extensions(Rx)に対応した拡張メソッドが追加されます。

UniRxをPackage Managerから導入した場合は自動で以下の機能が追加されます。unitypackage等で導入した場合は、`Project Settings > Player > Scripting Define Symbols``LITMOTION_UNIRX_SUPPORT`を追加する必要があります。
UniRxをPackage Managerから導入した場合は自動で以下の機能が追加されます。unitypackage等で導入した場合は、`Project Settings > Player > Scripting Define Symbols``LITMOTION_SUPPORT_UNIRX`を追加する必要があります。

### モーションをObservableとして作成

Expand Down
4 changes: 2 additions & 2 deletions docs/articles/ja/integration-unitask.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

プロジェクトに[UniTask](https://github.com/Cysharp/UniTask)を導入することで、モーションの待機をasync/awaitに対応させる拡張メソッドが追加されます。

UniTaskをPackage Managerから導入した場合は自動で以下の機能が追加されます。unitypackage等で導入した場合は、`Project Settings > Player > Scripting Define Symbols``LITMOTION_UNITASK_SUPPORT`を追加する必要があります。
UniTaskをPackage Managerから導入した場合は自動で以下の機能が追加されます。unitypackage等で導入した場合は、`Project Settings > Player > Scripting Define Symbols``LITMOTION_SUPPORT_UNITASK`を追加する必要があります。

### モーションの待機

Expand All @@ -20,4 +20,4 @@ await LMotion.Create(0f, 10f, 2f).Bind(x => Debug.Log(x))
.ToUniTask(cts.Token);
```

CancellationTokenを渡すと、非同期処理がキャンセルされた際に自動でモーションの再生もキャンセルされます。
CancellationTokenを渡すと、非同期処理がキャンセルされた際に自動でモーションの再生もキャンセルされます。
4 changes: 3 additions & 1 deletion docs/articles/ja/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@
href: motion-tracker.md

- name: Integrations
- name: R3
href: integration-r3.md
- name: UniRx
href: integration-unirx.md
- name: UniTask
Expand All @@ -56,4 +58,4 @@

- name: Concepts
- name: 設計思想
href: design-philosophy.md
href: design-philosophy.md
8 changes: 8 additions & 0 deletions src/LitMotion/Assets/LitMotion/Runtime/External/R3.meta

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#if LITMOTION_SUPPORT_R3
using R3;

namespace LitMotion
{
public static class LitMotionR3Extensions
{
/// <summary>
/// Create the motion as Observable.
/// </summary>
/// <typeparam name="TValue">The type of value to animate</typeparam>
/// <typeparam name="TOptions">The type of special parameters given to the motion data</typeparam>
/// <typeparam name="TAdapter">The type of adapter that support value animation</typeparam>
/// <param name="builder">This builder</param>
/// <returns>Observable of the created motion.</returns>
public static Observable<TValue> ToObservable<TValue, TOptions, TAdapter>(this MotionBuilder<TValue, TOptions, TAdapter> builder)
where TValue : unmanaged
where TOptions : unmanaged, IMotionOptions
where TAdapter : unmanaged, IMotionAdapter<TValue, TOptions>
{
var subject = new Subject<TValue>();
var callbacks = builder.BuildCallbackData(subject, static (x, subject) => subject.OnNext(x));
callbacks.OnCompleteAction += () => subject.OnCompleted();
callbacks.OnCancelAction += () => subject.OnCompleted();
var scheduler = builder.buffer.Scheduler;
var entity = builder.BuildMotionData();

builder.Schedule(scheduler, ref entity, ref callbacks);
return subject;
}

/// <summary>
/// Create a motion data and bind it to ReactiveProperty.
/// </summary>
/// <typeparam name="TValue">The type of value to animate</typeparam>
/// <typeparam name="TOptions">The type of special parameters given to the motion data</typeparam>
/// <typeparam name="TAdapter">The type of adapter that support value animation</typeparam>
/// <param name="builder">This builder</param>
/// <param name="progress">Target object that implements IProgress</param>
/// <returns>Handle of the created motion data.</returns>
public static MotionHandle BindToReactiveProperty<TValue, TOptions, TAdapter>(this MotionBuilder<TValue, TOptions, TAdapter> builder, ReactiveProperty<TValue> reactiveProperty)
where TValue : unmanaged
where TOptions : unmanaged, IMotionOptions
where TAdapter : unmanaged, IMotionAdapter<TValue, TOptions>
{
Error.IsNull(reactiveProperty);
return builder.BindWithState(reactiveProperty, static (x, target) =>
{
target.Value = x;
});
}
}
}
#endif

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

10 changes: 10 additions & 0 deletions src/LitMotion/Assets/LitMotion/Runtime/LitMotion.asmdef
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,16 @@
"name": "com.neuecc.unirx",
"expression": "",
"define": "LITMOTION_SUPPORT_UNIRX"
},
{
"name": "com.cysharp.r3",
"expression": "",
"define": "LITMOTION_SUPPORT_R3"
},
{
"name": "org.nuget.r3",
"expression": "",
"define": "LITMOTION_SUPPORT_R3"
}
],
"noEngineReferences": false
Expand Down
25 changes: 25 additions & 0 deletions src/LitMotion/Assets/LitMotion/Tests/Runtime/ExternalExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
namespace LitMotion.Tests.Runtime
{
static class ExternalExtensions
{
#if LITMOTION_TEST_R3
public static R3.Observable<TValue> ToR3Observable<TValue, TOptions, TAdapter>(this MotionBuilder<TValue, TOptions, TAdapter> builder)
where TValue : unmanaged
where TOptions : unmanaged, IMotionOptions
where TAdapter : unmanaged, IMotionAdapter<TValue, TOptions>
{
return LitMotionR3Extensions.ToObservable(builder);
}
#endif

#if LITMOTION_TEST_UNIRX
public static System.IObservable<TValue> ToRxObservable<TValue, TOptions, TAdapter>(this MotionBuilder<TValue, TOptions, TAdapter> builder)
where TValue : unmanaged
where TOptions : unmanaged, IMotionOptions
where TAdapter : unmanaged, IMotionAdapter<TValue, TOptions>
{
return LitMotionUniRxExtensions.ToObservable(builder);
}
#endif
}
}

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

Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
"allowUnsafeCode": false,
"overrideReferences": true,
"precompiledReferences": [
"nunit.framework.dll"
"nunit.framework.dll",
"R3.dll"
],
"autoReferenced": false,
"defineConstraints": [
Expand All @@ -31,6 +32,11 @@
"name": "com.neuecc.unirx",
"expression": "",
"define": "LITMOTION_TEST_UNIRX"
},
{
"name": "com.cysharp.r3",
"expression": "",
"define": "LITMOTION_TEST_R3"
}
],
"noEngineReferences": false
Expand Down
56 changes: 56 additions & 0 deletions src/LitMotion/Assets/LitMotion/Tests/Runtime/R3Test.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#if LITMOTION_TEST_R3
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.TestTools;
using R3;
using NUnit.Framework;

namespace LitMotion.Tests.Runtime
{
public class R3Test
{
readonly CompositeDisposable disposables = new();

[OneTimeTearDown]
public void OneTimeTearDown()
{
disposables.Dispose();
}

[UnityTest]
public IEnumerator Test_ToObservable()
{
bool completed = false;
LMotion.Create(0f, 10f, 2f)
.WithOnComplete(() => completed = true)
.ToR3Observable()
.Subscribe(x => Debug.Log(x))
.AddTo(disposables);
while (!completed) yield return null;
}

[UnityTest]
public IEnumerator Test_BindToReactiveProperty()
{
var reactiveProperty = new ReactiveProperty<float>();
reactiveProperty.AddTo(disposables);

bool completed = false;
LMotion.Create(0f, 10f, 2f)
.WithOnComplete(() => completed = true)
.BindToReactiveProperty(reactiveProperty)
.ToDisposable()
.AddTo(disposables);

reactiveProperty.Subscribe(x =>
{
Debug.Log(x);
})
.AddTo(disposables);

while (!completed) yield return null;
}
}
}
#endif
3 changes: 3 additions & 0 deletions src/LitMotion/Assets/LitMotion/Tests/Runtime/R3Test.cs.meta

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

4 changes: 2 additions & 2 deletions src/LitMotion/Assets/LitMotion/Tests/Runtime/UniRxTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ public IEnumerator Test_ToObservable()
{
bool completed = false;
LMotion.Create(0f, 10f, 2f)
.WithOnComplete(() => completed = true)
.ToObservable()
.WithOnComplete(() => completed = true)
.ToRxObservable()
.Subscribe(x => Debug.Log(x))
.AddTo(disposables);
while (!completed) yield return null;
Expand Down
Loading

0 comments on commit 0f83da1

Please sign in to comment.