Add X10D.Unity

This commit is contained in:
Oliver Booth 2020-07-15 14:33:40 +01:00
parent 600b37fe82
commit 5bc71bd426
9 changed files with 546 additions and 0 deletions

View File

@ -24,9 +24,11 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Unity3D.SDK" Version="2019.4.3.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\X10D.Unity\X10D.Unity.csproj" />
<ProjectReference Include="..\X10D\X10D.csproj" />
</ItemGroup>

View File

@ -0,0 +1,93 @@
namespace X10D.Tests.Unity
{
using Microsoft.VisualStudio.TestTools.UnitTesting;
using UnityEngine;
using X10D.Unity;
/// <summary>
/// Tests for <see cref="Vector3Extensions" />.
/// </summary>
[TestClass]
public class Vector3Tests
{
/// <summary>
/// Tests for <see cref="Vector3Extensions.Round" /> by rounding to the nearest 0.5.
/// </summary>
[TestMethod]
public void TestRoundHalf()
{
var vector = new Vector3(1.8f, 2.1f, 3.37f);
Assert.AreEqual(new Vector3(2, 2, 3.5f), vector.Round(0.5f));
}
/// <summary>
/// Tests for <see cref="Vector3Extensions.Round" /> by rounding to the nearest integer.
/// </summary>
[TestMethod]
public void TestRoundInteger()
{
var vector = new Vector3(1.8f, 2.1f, 3.37f);
Assert.AreEqual(new Vector3(2, 2, 3), vector.Round());
}
/// <summary>
/// Tests for <see cref="Vector3Extensions.WithX" />.
/// </summary>
[TestMethod]
public void TestWithX()
{
var vector = new Vector3(1, 2, 3);
Assert.AreEqual(new Vector3(4, 2, 3), vector.WithX(4));
}
/// <summary>
/// Tests for <see cref="Vector3Extensions.WithXY" />.
/// </summary>
[TestMethod]
public void TestWithXY()
{
var vector = new Vector3(1, 2, 3);
Assert.AreEqual(new Vector3(8, 10, 3), vector.WithXY(8, 10));
}
/// <summary>
/// Tests for <see cref="Vector3Extensions.WithXZ" />.
/// </summary>
[TestMethod]
public void TestWithXZ()
{
var vector = new Vector3(1, 2, 3);
Assert.AreEqual(new Vector3(8, 2, 10), vector.WithXZ(8, 10));
}
/// <summary>
/// Tests for <see cref="Vector3Extensions.WithY" />.
/// </summary>
[TestMethod]
public void TestWithY()
{
var vector = new Vector3(1, 2, 3);
Assert.AreEqual(new Vector3(1, 4, 3), vector.WithY(4));
}
/// <summary>
/// Tests for <see cref="Vector3Extensions.WithYZ" />.
/// </summary>
[TestMethod]
public void TestWithYZ()
{
var vector = new Vector3(1, 2, 3);
Assert.AreEqual(new Vector3(1, 8, 10), vector.WithYZ(8, 10));
}
/// <summary>
/// Tests for <see cref="Vector3Extensions.WithZ" />.
/// </summary>
[TestMethod]
public void TestWithZ()
{
var vector = new Vector3(1, 2, 3);
Assert.AreEqual(new Vector3(1, 2, 4), vector.WithZ(4));
}
}
}

View File

@ -0,0 +1,72 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>8.0</LangVersion>
<Authors>Oliver Booth</Authors>
<NeutralLanguage>en</NeutralLanguage>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<RepositoryUrl>https://github.com/oliverbooth/X10D</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<Description>Extension methods on crack.</Description>
<PackageLicenseFile>LICENSE.md</PackageLicenseFile>
<PackageIcon>icon.png</PackageIcon>
<PackageIconUrl />
<PackageTags>dotnet extension-methods unity</PackageTags>
<Version>2.2.0</Version>
<CodeAnalysisRuleSet>..\X10D.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisTreatWarningsAsErrors>true</CodeAnalysisTreatWarningsAsErrors>
<PackageVersion>2.4.0</PackageVersion>
<AssemblyVersion>2.4.0</AssemblyVersion>
<FileVersion>2.4.0</FileVersion>
</PropertyGroup>
<ItemGroup>
<None Include="..\icon.png">
<Pack>True</Pack>
<PackagePath></PackagePath>
</None>
<None Include="..\LICENSE.md">
<Pack>True</Pack>
<PackagePath></PackagePath>
</None>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.8">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Roslynator.Analyzers" Version="2.3.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.164">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Unity3D.SDK" Version="2019.4.3.1">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\X10D\X10D.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Update="Resource.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Resource.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Resource.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resource.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
</Project>

View File

@ -0,0 +1,107 @@
namespace X10D.Unity
{
using System.Diagnostics.CodeAnalysis;
using System.Threading.Tasks;
using UnityEngine;
/// <summary>
/// Represents a class which inherits <see cref="MonoBehaviour" /> to offer wider functionality.
/// </summary>
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global", Justification = "Unity property")]
[SuppressMessage("ReSharper", "UnusedAutoPropertyAccessor.Global", Justification = "Unity property")]
[SuppressMessage("ReSharper", "SA1300", Justification = "Unity API-compliant property")]
[SuppressMessage("ReSharper", "CA2007", Justification = "Unnecessary")]
[SuppressMessage("ReSharper", "RCS1090", Justification = "Unnecessary")]
[SuppressMessage("ReSharper", "RCS1213", Justification = "Unity method")]
[SuppressMessage("ReSharper", "UnusedParameter.Global", Justification = "Override method")]
public abstract class BetterBehavior : MonoBehaviour
{
/// <summary>
/// Gets the <see cref="Transform" /> component attached to this object.
/// </summary>
public new Transform transform { get; private set; }
/// <summary>
/// Awake is called when the script instance is being loaded.
/// </summary>
protected virtual void Awake()
{
this.transform = this.GetComponent<Transform>();
}
/// <summary>
/// Frame-rate independent messaging for physics calculations.
/// </summary>
/// <param name="gameTime">A snapshot of timing values.</param>
protected virtual void OnFixedUpdate(in GameTime gameTime)
{
}
/// <summary>
/// Frame-rate independent messaging for physics calculations.
/// </summary>
/// <param name="gameTime">A snapshot of timing values.</param>
/// <returns>Returns a task representing the result of the operation.</returns>
protected virtual Task OnFixedUpdateAsync(GameTime gameTime)
{
return Task.CompletedTask;
}
/// <summary>
/// Called once per frame, after all <c>Update</c> calls.
/// </summary>
/// <param name="gameTime">A snapshot of timing values.</param>
protected virtual void OnLateUpdate(in GameTime gameTime)
{
}
/// <summary>
/// Called once per frame, after all <c>Update</c> calls.
/// </summary>
/// <param name="gameTime">A snapshot of timing values.</param>
/// <returns>Returns a task representing the result of the operation.</returns>
protected virtual Task OnLateUpdateAsync(GameTime gameTime)
{
return Task.CompletedTask;
}
/// <summary>
/// Called once per frame.
/// </summary>
/// <param name="gameTime">A snapshot of timing values.</param>
protected virtual void OnUpdate(in GameTime gameTime)
{
}
/// <summary>
/// Called once per frame.
/// </summary>
/// <param name="gameTime">A snapshot of timing values.</param>
/// <returns>Returns a task representing the result of the operation.</returns>
protected virtual Task OnUpdateAsync(GameTime gameTime)
{
return Task.CompletedTask;
}
private async void FixedUpdate()
{
var time = GameTime.CreateFromCurrentTimes();
this.OnFixedUpdate(time);
await this.OnFixedUpdateAsync(time);
}
private async void LateUpdate()
{
var time = GameTime.CreateFromCurrentTimes();
this.OnLateUpdate(time);
await this.OnLateUpdateAsync(time);
}
private async void Update()
{
var time = GameTime.CreateFromCurrentTimes();
this.OnUpdate(time);
await this.OnUpdateAsync(time);
}
}
}

View File

@ -0,0 +1,64 @@
namespace X10D.Unity
{
using System;
using JetBrains.Annotations;
using UnityEngine;
/// <summary>
/// Extension methods for <see cref="GameObject" />.
/// </summary>
public static class GameObjectExtensions
{
/// <summary>
/// Rotates the <see cref="Transform" /> component on the current <see cref="GameObject" /> such that is is facing another
/// <see cref="GameObject" />.
/// </summary>
/// <param name="gameObject">The current game object.</param>
/// <param name="other">The target.</param>
/// <exception cref="ArgumentNullException">
/// <paramref name="gameObject" /> is null
/// - or -
/// <paramref name="other" /> is null.
/// </exception>
public static void LookAt([NotNull] this GameObject gameObject, [NotNull] GameObject other)
{
if (gameObject is null)
{
throw new ArgumentNullException(nameof(gameObject));
}
if (other is null)
{
throw new ArgumentNullException(nameof(other));
}
gameObject.LookAt(other.transform);
}
/// <summary>
/// Rotates the <see cref="Transform" /> component on the current <see cref="GameObject" /> such that is is facing another
/// <see cref="Transform" />.
/// </summary>
/// <param name="gameObject">The current game object.</param>
/// <param name="other">The target.</param>
/// <exception cref="ArgumentNullException">
/// <paramref name="gameObject" /> is null
/// - or -
/// <paramref name="other" /> is null.
/// </exception>
public static void LookAt([NotNull] this GameObject gameObject, [NotNull] Transform other)
{
if (gameObject is null)
{
throw new ArgumentNullException(nameof(gameObject));
}
if (other is null)
{
throw new ArgumentNullException(nameof(other));
}
gameObject.transform.LookAt(other);
}
}
}

View File

@ -0,0 +1,54 @@
namespace X10D.Unity
{
using System;
using UnityEngine;
/// <summary>
/// Represents a struct which contains game timing information.
/// </summary>
public readonly struct GameTime
{
private GameTime(float totalTime, float deltaTime, float fixedDeltaTime, int frameCount, float timeScale)
{
this.TotalTime = TimeSpan.FromSeconds(totalTime);
this.DeltaTime = TimeSpan.FromSeconds(deltaTime);
this.FixedDeltaTime = TimeSpan.FromSeconds(fixedDeltaTime);
this.FrameCount = frameCount;
this.TimeScale = timeScale;
}
/// <summary>
/// Gets the time since the last frame was rendered.
/// </summary>
public TimeSpan DeltaTime { get; }
/// <summary>
/// Gets the time since the last physics time step.
/// </summary>
public TimeSpan FixedDeltaTime { get; }
/// <summary>
/// Gets the total number of frames which have been rendered.
/// </summary>
public int FrameCount { get; }
/// <summary>
/// Gets the total time for which the game has been running.
/// </summary>
public TimeSpan TotalTime { get; }
/// <summary>
/// Gets the time scale.
/// </summary>
public float TimeScale { get; }
/// <summary>
/// Creates a new instance of the <see cref="GameTime" /> struct by creating a snapshot of values offered by <see cref="Time" />.
/// </summary>
/// <returns>An instance of <see cref="GameTime" />.</returns>
public static GameTime CreateFromCurrentTimes()
{
return new GameTime(Time.time, Time.deltaTime, Time.fixedDeltaTime, Time.frameCount, Time.timeScale);
}
}
}

View File

@ -0,0 +1,37 @@
namespace X10D.Unity
{
using System;
using JetBrains.Annotations;
using UnityEngine;
/// <summary>
/// Extension methods for <see cref="Transform" />.
/// </summary>
public static class TransformExtensions
{
/// <summary>
/// Rotates the current <see cref="Transform" /> such that is is facing another <see cref="GameObject" />.
/// </summary>
/// <param name="transform">The current transform.</param>
/// <param name="other">The target.</param>
/// <exception cref="ArgumentNullException">
/// <paramref name="transform" /> is null
/// - or -
/// <paramref name="other" /> is null.
/// </exception>
public static void LookAt([NotNull] this Transform transform, [NotNull] GameObject other)
{
if (transform is null)
{
throw new ArgumentNullException(nameof(transform));
}
if (other is null)
{
throw new ArgumentNullException(nameof(other));
}
transform.LookAt(other.transform);
}
}
}

View File

@ -0,0 +1,111 @@
namespace X10D.Unity
{
using UnityEngine;
/// <summary>
/// Extension methods for <see cref="Vector3" />.
/// </summary>
public static class Vector3Extensions
{
/// <summary>
/// Rounds a <see cref="Vector3" /> by calling <see cref="SingleExtensions.Round" /> on each of the components.
/// </summary>
/// <param name="vector">The vector to round.</param>
/// <param name="nearest">The nearest value.</param>
/// <returns><paramref name="vector" /> rounded to the nearest <paramref name="nearest" />.</returns>
public static Vector3 Round(this Vector3 vector, float nearest = 1)
{
return new Vector3(vector.x.Round(nearest), vector.y.Round(nearest), vector.z.Round(nearest));
}
/// <summary>
/// Returns a vector whose Y and Z components match that of a provided vector, and sets the X component to a provided value.
/// </summary>
/// <param name="vector">The input vector.</param>
/// <param name="x">The new X value.</param>
/// <returns>
/// Returns a <see cref="Vector3" /> whose Y and Z components match that of <paramref name="vector" />,
/// but with the <see cref="Vector3.x" /> component set to <paramref name="x" />.
/// </returns>
public static Vector3 WithX(this Vector3 vector, float x)
{
return new Vector3(x, vector.y, vector.z);
}
/// <summary>
/// Returns a vector whose Z component matches that of a provided vector, and sets the X and Y components to provided values.
/// </summary>
/// <param name="vector">The input vector.</param>
/// <param name="x">The new X value.</param>
/// <param name="y">The new Y value.</param>
/// <returns>
/// Returns a <see cref="Vector3" /> whose Z component matches that of <paramref name="vector" />,
/// but with the <see cref="Vector3.x" /> and <see cref="Vector3.y" /> components set to <paramref name="x" /> and
/// <paramref name="y" /> respectively.
/// </returns>
public static Vector3 WithXY(this Vector3 vector, float x, float y)
{
return new Vector3(x, y, vector.z);
}
/// <summary>
/// Returns a vector whose Y component matches that of a provided vector, and sets the X and Z components to provided values.
/// </summary>
/// <param name="vector">The input vector.</param>
/// <param name="x">The new X value.</param>
/// <param name="z">The new Z value.</param>
/// <returns>
/// Returns a <see cref="Vector3" /> whose Y component matches that of <paramref name="vector" />,
/// but with the <see cref="Vector3.x" /> and <see cref="Vector3.z" /> components set to <paramref name="x" /> and
/// <paramref name="z" /> respectively.
/// </returns>
public static Vector3 WithXZ(this Vector3 vector, float x, float z)
{
return new Vector3(x, vector.y, z);
}
/// <summary>
/// Returns a vector whose X and Z components match that of a provided vector, and sets the Y component to a provided value.
/// </summary>
/// <param name="vector">The input vector.</param>
/// <param name="y">The new Y value.</param>
/// <returns>
/// Returns a <see cref="Vector3" /> whose X and Z components match that of <paramref name="vector" />,
/// but with the <see cref="Vector3.y" /> component set to <paramref name="y" />.
/// </returns>
public static Vector3 WithY(this Vector3 vector, float y)
{
return new Vector3(vector.x, y, vector.z);
}
/// <summary>
/// Returns a vector whose X component matches that of a provided vector, and sets the Y and Z components to provided values.
/// </summary>
/// <param name="vector">The input vector.</param>
/// <param name="y">The new Y value.</param>
/// <param name="z">The new Z value.</param>
/// <returns>
/// Returns a <see cref="Vector3" /> whose X component matches that of <paramref name="vector" />,
/// but with the <see cref="Vector3.y" /> and <see cref="Vector3.z" /> components set to <paramref name="y" /> and
/// <paramref name="z" /> respectively.
/// </returns>
public static Vector3 WithYZ(this Vector3 vector, float y, float z)
{
return new Vector3(vector.x, y, z);
}
/// <summary>
/// Returns a vector whose X and Y components match that of a provided vector, and sets the Z component to a provided value.
/// </summary>
/// <param name="vector">The input vector.</param>
/// <param name="z">The new Z value.</param>
/// <returns>
/// Returns a <see cref="Vector3" /> whose X and Y components match that of <paramref name="vector" />,
/// but with the <see cref="Vector3.z" /> component set to <paramref name="z" />.
/// </returns>
public static Vector3 WithZ(this Vector3 vector, float z)
{
return new Vector3(vector.x, vector.y, z);
}
}
}

View File

@ -12,6 +12,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
.editorconfig = .editorconfig
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "X10D.Unity", "X10D.Unity\X10D.Unity.csproj", "{C21ABC58-68D6-4CA0-9CE6-A2E96C5E89AE}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -26,6 +28,10 @@ Global
{DF228EA2-D8EC-4A40-8917-E1E62E3B7D8E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DF228EA2-D8EC-4A40-8917-E1E62E3B7D8E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DF228EA2-D8EC-4A40-8917-E1E62E3B7D8E}.Release|Any CPU.Build.0 = Release|Any CPU
{C21ABC58-68D6-4CA0-9CE6-A2E96C5E89AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C21ABC58-68D6-4CA0-9CE6-A2E96C5E89AE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C21ABC58-68D6-4CA0-9CE6-A2E96C5E89AE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C21ABC58-68D6-4CA0-9CE6-A2E96C5E89AE}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE