Merge branch 'FlaxEngine:master' into material_import
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.InteropServices.Marshalling;
|
||||
|
||||
@@ -94,9 +93,11 @@ namespace FlaxEngine
|
||||
public AnimatedModel Instance;
|
||||
}
|
||||
|
||||
[HideInEditor]
|
||||
[CustomMarshaller(typeof(Context), MarshalMode.Default, typeof(ContextMarshaller))]
|
||||
internal static class ContextMarshaller
|
||||
{
|
||||
[HideInEditor]
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct ContextNative
|
||||
{
|
||||
@@ -116,7 +117,7 @@ namespace FlaxEngine
|
||||
|
||||
internal static Context ToManaged(ContextNative managed)
|
||||
{
|
||||
return new Context()
|
||||
return new Context
|
||||
{
|
||||
Graph = managed.Graph,
|
||||
GraphExecutor = managed.GraphExecutor,
|
||||
@@ -129,9 +130,10 @@ namespace FlaxEngine
|
||||
Instance = AnimatedModelMarshaller.ConvertToManaged(managed.Instance),
|
||||
};
|
||||
}
|
||||
|
||||
internal static ContextNative ToNative(Context managed)
|
||||
{
|
||||
return new ContextNative()
|
||||
return new ContextNative
|
||||
{
|
||||
Graph = managed.Graph,
|
||||
GraphExecutor = managed.GraphExecutor,
|
||||
@@ -144,6 +146,7 @@ namespace FlaxEngine
|
||||
Instance = AnimatedModelMarshaller.ConvertToUnmanaged(managed.Instance),
|
||||
};
|
||||
}
|
||||
|
||||
internal static void Free(ContextNative unmanaged)
|
||||
{
|
||||
}
|
||||
@@ -243,6 +246,12 @@ namespace FlaxEngine
|
||||
throw new ArgumentNullException(nameof(source));
|
||||
if (destination == null)
|
||||
throw new ArgumentNullException(nameof(destination));
|
||||
if (source->NodesCount <= 0 || source->NodesCount > 4096)
|
||||
throw new ArgumentOutOfRangeException(nameof(source));
|
||||
if (destination->NodesCount <= 0 || destination->NodesCount > 4096)
|
||||
throw new ArgumentOutOfRangeException(nameof(destination));
|
||||
if (source->NodesCount != destination->NodesCount)
|
||||
throw new ArgumentOutOfRangeException();
|
||||
destination->NodesCount = source->NodesCount;
|
||||
destination->Unused = source->Unused;
|
||||
Utils.MemoryCopy(new IntPtr(destination->Nodes), new IntPtr(source->Nodes), (ulong)(source->NodesCount * sizeof(Transform)));
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include "Engine/Scripting/Scripting.h"
|
||||
#include "Engine/Scripting/BinaryModule.h"
|
||||
#include "Engine/Scripting/ManagedCLR/MCore.h"
|
||||
#include "Engine/Scripting/ManagedCLR/MDomain.h"
|
||||
#include "Engine/Scripting/ManagedCLR/MMethod.h"
|
||||
#include "Engine/Scripting/ManagedCLR/MClass.h"
|
||||
#include "Engine/Scripting/ManagedCLR/MUtils.h"
|
||||
@@ -189,12 +188,8 @@ bool AnimGraph::InitCustomNode(Node* node)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create node values managed array
|
||||
// Initialization can happen on Content Thread so ensure to have runtime attached
|
||||
MCore::Thread::Attach();
|
||||
MArray* values = MCore::Array::New( MCore::TypeCache::Object, node->Values.Count());
|
||||
MObject** valuesPtr = MCore::Array::GetAddress<MObject*>(values);
|
||||
for (int32 i = 0; i < node->Values.Count(); i++)
|
||||
valuesPtr[i] = MUtils::BoxVariant(node->Values[i]);
|
||||
|
||||
// Allocate managed node object (create GC handle to prevent destruction)
|
||||
MObject* obj = type->CreateInstance();
|
||||
@@ -202,7 +197,7 @@ bool AnimGraph::InitCustomNode(Node* node)
|
||||
|
||||
// Initialize node
|
||||
InternalInitData initData;
|
||||
initData.Values = values;
|
||||
initData.Values = MUtils::ToArray(node->Values, MCore::TypeCache::Object);
|
||||
initData.BaseModel = BaseModel.GetManagedInstance();
|
||||
void* params[1];
|
||||
params[0] = &initData;
|
||||
@@ -211,7 +206,6 @@ bool AnimGraph::InitCustomNode(Node* node)
|
||||
if (exception)
|
||||
{
|
||||
MCore::GCHandle::Free(handleGC);
|
||||
|
||||
MException ex(exception);
|
||||
ex.Log(LogType::Warning, TEXT("AnimGraph"));
|
||||
return false;
|
||||
|
||||
@@ -235,8 +235,9 @@ void AnimGraphExecutor::ProcessAnimation(AnimGraphImpulse* nodes, AnimGraphNode*
|
||||
const float nestedAnimLength = nestedAnim.Anim->GetLength();
|
||||
const float nestedAnimDuration = nestedAnim.Anim->GetDuration();
|
||||
const float nestedAnimSpeed = nestedAnim.Speed * speed;
|
||||
nestedAnimPos = nestedAnimPos / nestedAnimDuration * nestedAnimSpeed;
|
||||
nestedAnimPrevPos = nestedAnimPrevPos / nestedAnimDuration * nestedAnimSpeed;
|
||||
const float frameRateMatchScale = (float)nestedAnim.Anim->Data.FramesPerSecond / (float)anim->Data.FramesPerSecond;
|
||||
nestedAnimPos = nestedAnimPos / nestedAnimDuration * nestedAnimSpeed * frameRateMatchScale;
|
||||
nestedAnimPrevPos = nestedAnimPrevPos / nestedAnimDuration * nestedAnimSpeed * frameRateMatchScale;
|
||||
GetAnimSamplePos(nestedAnim.Loop, nestedAnimLength, nestedAnim.StartTime, nestedAnimPrevPos, nestedAnimPos, nestedAnimPos, nestedAnimPrevPos);
|
||||
|
||||
ProcessAnimation(nodes, node, true, nestedAnimLength, nestedAnimPos, nestedAnimPrevPos, nestedAnim.Anim, 1.0f, weight, mode);
|
||||
|
||||
@@ -205,9 +205,6 @@ FlaxStorage::~FlaxStorage()
|
||||
{
|
||||
// Validate if has been disposed
|
||||
ASSERT(IsDisposed());
|
||||
|
||||
// Validate other fields
|
||||
// Note: disposed storage has no open files
|
||||
CHECK(_chunksLock == 0);
|
||||
CHECK(_refCount == 0);
|
||||
ASSERT(_chunks.IsEmpty());
|
||||
@@ -216,7 +213,6 @@ FlaxStorage::~FlaxStorage()
|
||||
// Ensure to close any outstanding file handles to prevent file locking in case it failed to load
|
||||
_file.DeleteAll();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
FlaxStorage::LockData FlaxStorage::LockSafe()
|
||||
@@ -550,11 +546,9 @@ bool FlaxStorage::Load()
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
LOG(Warning, "Unsupported storage format version: {1}. {0}", ToString(), _version);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Mark as loaded (version number describes 'isLoaded' state)
|
||||
_version = version;
|
||||
@@ -573,7 +567,7 @@ bool FlaxStorage::Reload()
|
||||
|
||||
// Perform clean reloading
|
||||
Dispose();
|
||||
bool failed = Load();
|
||||
const bool failed = Load();
|
||||
|
||||
OnReloaded(this, failed);
|
||||
|
||||
@@ -1434,10 +1428,8 @@ void FlaxFile::GetEntries(Array<Entry>& output) const
|
||||
|
||||
void FlaxFile::Dispose()
|
||||
{
|
||||
// Base
|
||||
FlaxStorage::Dispose();
|
||||
|
||||
// Clean
|
||||
_asset.ID = Guid::Empty;
|
||||
}
|
||||
|
||||
@@ -1482,7 +1474,7 @@ bool FlaxPackage::HasAsset(const Guid& id) const
|
||||
bool FlaxPackage::HasAsset(const AssetInfo& info) const
|
||||
{
|
||||
ASSERT(_path == info.Path);
|
||||
Entry* e = _entries.TryGet(info.ID);
|
||||
const Entry* e = _entries.TryGet(info.ID);
|
||||
return e && e->TypeName == info.TypeName;
|
||||
}
|
||||
|
||||
@@ -1511,10 +1503,8 @@ void FlaxPackage::GetEntries(Array<Entry>& output) const
|
||||
|
||||
void FlaxPackage::Dispose()
|
||||
{
|
||||
// Base
|
||||
FlaxStorage::Dispose();
|
||||
|
||||
// Clean
|
||||
_entries.Clear();
|
||||
}
|
||||
|
||||
|
||||
@@ -876,38 +876,54 @@ namespace FlaxEngine
|
||||
/// <summary>
|
||||
/// Given a heading which may be outside the +/- PI range, 'unwind' it back into that range.
|
||||
/// </summary>
|
||||
/// <remarks>Optimized version of <see cref="UnwindRadiansAccurate"/> that is it faster and has fixed cost but with large angle values (100 for example) starts to lose accuracy floating point problem.</remarks>
|
||||
/// <param name="angle">Angle in radians to unwind.</param>
|
||||
/// <returns>Valid angle in radians.</returns>
|
||||
public static double UnwindRadians(double angle)
|
||||
{
|
||||
// TODO: make it faster?
|
||||
var a = angle - Math.Floor(angle / TwoPi) * TwoPi; // Loop function between 0 and TwoPi
|
||||
return a > Pi ? a - TwoPi : a; // Change range so it become Pi and -Pi
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The same as <see cref="UnwindRadians"/> but is more computation intensive with large <see href="angle"/> and has better accuracy with large <see href="angle"/>.
|
||||
/// <br>cost of this function is <see href="angle"/> % <see cref="Pi"/></br>
|
||||
/// </summary>
|
||||
/// <param name="angle">Angle in radians to unwind.</param>
|
||||
/// <returns>Valid angle in radians.</returns>
|
||||
public static double UnwindRadiansAccurate(double angle)
|
||||
{
|
||||
while (angle > Pi)
|
||||
{
|
||||
angle -= TwoPi;
|
||||
}
|
||||
while (angle < -Pi)
|
||||
{
|
||||
angle += TwoPi;
|
||||
}
|
||||
return angle;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Utility to ensure angle is between +/- 180 degrees by unwinding
|
||||
/// Utility to ensure angle is between +/- 180 degrees by unwinding.
|
||||
/// </summary>
|
||||
/// <remarks>Optimized version of <see cref="UnwindDegreesAccurate"/> that is it faster and has fixed cost but with large angle values (100 for example) starts to lose accuracy floating point problem.</remarks>
|
||||
/// <param name="angle">Angle in degrees to unwind.</param>
|
||||
/// <returns>Valid angle in degrees.</returns>
|
||||
public static double UnwindDegrees(double angle)
|
||||
{
|
||||
// TODO: make it faster?
|
||||
while (angle > 180.0f)
|
||||
{
|
||||
angle -= 360.0f;
|
||||
}
|
||||
while (angle < -180.0f)
|
||||
{
|
||||
angle += 360.0f;
|
||||
}
|
||||
var a = angle - Math.Floor(angle / 360.0) * 360.0; // Loop function between 0 and 360
|
||||
return a > 180 ? a - 360.0 : a; // Change range so it become 180 and -180
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The same as <see cref="UnwindDegrees"/> but is more computation intensive with large <see href="angle"/> and has better accuracy with large <see href="angle"/>.
|
||||
/// <br>cost of this function is <see href="angle"/> % 180.0f</br>
|
||||
/// </summary>
|
||||
/// <param name="angle">Angle in radians to unwind.</param>
|
||||
/// <returns>Valid angle in radians.</returns>
|
||||
public static double UnwindDegreesAccurate(double angle)
|
||||
{
|
||||
while (angle > 180.0)
|
||||
angle -= 360.0;
|
||||
while (angle < -180.0)
|
||||
angle += 360.0;
|
||||
return angle;
|
||||
}
|
||||
|
||||
@@ -927,8 +943,9 @@ namespace FlaxEngine
|
||||
/// Interpolates between two values using a linear function by a given amount.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// See http://www.encyclopediaofmath.org/index.php/Linear_interpolation and
|
||||
/// http://fgiesen.wordpress.com/2012/08/15/linear-interpolation-past-present-and-future/
|
||||
/// See:
|
||||
/// <br><seealso href="http://www.encyclopediaofmath.org/index.php/Linear_interpolation"/></br>
|
||||
/// <br><seealso href="http://fgiesen.wordpress.com/2012/08/15/linear-interpolation-past-present-and-future/"/></br>
|
||||
/// </remarks>
|
||||
/// <param name="from">Value to interpolate from.</param>
|
||||
/// <param name="to">Value to interpolate to.</param>
|
||||
@@ -944,7 +961,8 @@ namespace FlaxEngine
|
||||
/// Performs smooth (cubic Hermite) interpolation between 0 and 1.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// See https://en.wikipedia.org/wiki/Smoothstep
|
||||
/// See:
|
||||
/// <br><seealso href="https://en.wikipedia.org/wiki/Smoothstep"/></br>
|
||||
/// </remarks>
|
||||
/// <param name="amount">Value between 0 and 1 indicating interpolation amount.</param>
|
||||
public static double SmoothStep(double amount)
|
||||
@@ -956,7 +974,8 @@ namespace FlaxEngine
|
||||
/// Performs a smooth(er) interpolation between 0 and 1 with 1st and 2nd order derivatives of zero at endpoints.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// See https://en.wikipedia.org/wiki/Smoothstep
|
||||
/// See:
|
||||
/// <br><seealso href="https://en.wikipedia.org/wiki/Smoothstep"/></br>
|
||||
/// </remarks>
|
||||
/// <param name="amount">Value between 0 and 1 indicating interpolation amount.</param>
|
||||
public static double SmootherStep(double amount)
|
||||
@@ -1013,7 +1032,7 @@ namespace FlaxEngine
|
||||
|
||||
/// <summary>
|
||||
/// Gauss function.
|
||||
/// http://en.wikipedia.org/wiki/Gaussian_function#Two-dimensional_Gaussian_function
|
||||
/// <br><seealso href="http://en.wikipedia.org/wiki/Gaussian_function#Two-dimensional_Gaussian_function"/></br>
|
||||
/// </summary>
|
||||
/// <param name="amplitude">Curve amplitude.</param>
|
||||
/// <param name="x">Position X.</param>
|
||||
|
||||
@@ -1176,38 +1176,54 @@ namespace FlaxEngine
|
||||
/// <summary>
|
||||
/// Given a heading which may be outside the +/- PI range, 'unwind' it back into that range.
|
||||
/// </summary>
|
||||
/// <remarks>Optimized version of <see cref="UnwindRadiansAccurate"/> that is it faster and has fixed cost but with large angle values (100 for example) starts to lose accuracy floating point problem.</remarks>
|
||||
/// <param name="angle">Angle in radians to unwind.</param>
|
||||
/// <returns>Valid angle in radians.</returns>
|
||||
public static float UnwindRadians(float angle)
|
||||
{
|
||||
// TODO: make it faster?
|
||||
var a = angle - (float)Math.Floor(angle / TwoPi) * TwoPi; // Loop function between 0 and TwoPi
|
||||
return a > Pi ? a - TwoPi : a; // Change range so it become Pi and -Pi
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The same as <see cref="UnwindRadians"/> but is more computation intensive with large <see href="angle"/> and has better accuracy with large <see href="angle"/>.
|
||||
/// <br>cost of this function is <see href="angle"/> % <see cref="Pi"/></br>
|
||||
/// </summary>
|
||||
/// <param name="angle">Angle in radians to unwind.</param>
|
||||
/// <returns>Valid angle in radians.</returns>
|
||||
public static float UnwindRadiansAccurate(float angle)
|
||||
{
|
||||
while (angle > Pi)
|
||||
{
|
||||
angle -= TwoPi;
|
||||
}
|
||||
while (angle < -Pi)
|
||||
{
|
||||
angle += TwoPi;
|
||||
}
|
||||
return angle;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Utility to ensure angle is between +/- 180 degrees by unwinding
|
||||
/// Utility to ensure angle is between +/- 180 degrees by unwinding.
|
||||
/// </summary>
|
||||
/// <remarks>Optimized version of <see cref="UnwindDegreesAccurate"/> that is it faster and has fixed cost but with large angle values (100 for example) starts to lose accuracy floating point problem.</remarks>
|
||||
/// <param name="angle">Angle in degrees to unwind.</param>
|
||||
/// <returns>Valid angle in degrees.</returns>
|
||||
public static float UnwindDegrees(float angle)
|
||||
{
|
||||
// TODO: make it faster?
|
||||
var a = angle - (float)Math.Floor(angle / 360.0f) * 360.0f; // Loop function between 0 and 360
|
||||
return a > 180 ? a - 360.0f : a; // Change range so it become 180 and -180
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The same as <see cref="UnwindDegrees"/> but is more computation intensive with large <see href="angle"/> and has better accuracy with large <see href="angle"/>.
|
||||
/// <br>cost of this function is <see href="angle"/> % 180.0f</br>
|
||||
/// </summary>
|
||||
/// <param name="angle">Angle in radians to unwind.</param>
|
||||
/// <returns>Valid angle in radians.</returns>
|
||||
public static float UnwindDegreesAccurate(float angle)
|
||||
{
|
||||
while (angle > 180.0f)
|
||||
{
|
||||
angle -= 360.0f;
|
||||
}
|
||||
while (angle < -180.0f)
|
||||
{
|
||||
angle += 360.0f;
|
||||
}
|
||||
return angle;
|
||||
}
|
||||
|
||||
@@ -1299,8 +1315,12 @@ namespace FlaxEngine
|
||||
/// <summary>
|
||||
/// Interpolates between two values using a linear function by a given amount.
|
||||
/// </summary>
|
||||
/// <remarks>See http://www.encyclopediaofmath.org/index.php/Linear_interpolation and http://fgiesen.wordpress.com/2012/08/15/linear-interpolation-past-present-and-future/</remarks>
|
||||
/// <param name="from">Value to interpolate from.</param>
|
||||
/// <remarks>
|
||||
/// See:
|
||||
/// <br><seealso href="http://www.encyclopediaofmath.org/index.php/Linear_interpolation"/></br>
|
||||
/// <br><seealso href="http://fgiesen.wordpress.com/2012/08/15/linear-interpolation-past-present-and-future/"/></br>
|
||||
/// </remarks>
|
||||
/// /// <param name="from">Value to interpolate from.</param>
|
||||
/// <param name="to">Value to interpolate to.</param>
|
||||
/// <param name="amount">Interpolation amount.</param>
|
||||
/// <returns>The result of linear interpolation of values based on the amount.</returns>
|
||||
@@ -1312,8 +1332,12 @@ namespace FlaxEngine
|
||||
/// <summary>
|
||||
/// Interpolates between two values using a linear function by a given amount.
|
||||
/// </summary>
|
||||
/// <remarks>See http://www.encyclopediaofmath.org/index.php/Linear_interpolation and http://fgiesen.wordpress.com/2012/08/15/linear-interpolation-past-present-and-future/</remarks>
|
||||
/// <param name="from">Value to interpolate from.</param>
|
||||
/// <remarks>
|
||||
/// See:
|
||||
/// <br><seealso href="http://www.encyclopediaofmath.org/index.php/Linear_interpolation"/></br>
|
||||
/// <br><seealso href="http://fgiesen.wordpress.com/2012/08/15/linear-interpolation-past-present-and-future/"/></br>
|
||||
/// </remarks>
|
||||
/// /// <param name="from">Value to interpolate from.</param>
|
||||
/// <param name="to">Value to interpolate to.</param>
|
||||
/// <param name="amount">Interpolation amount.</param>
|
||||
/// <returns>The result of linear interpolation of values based on the amount.</returns>
|
||||
@@ -1325,8 +1349,12 @@ namespace FlaxEngine
|
||||
/// <summary>
|
||||
/// Interpolates between two values using a linear function by a given amount.
|
||||
/// </summary>
|
||||
/// <remarks>See http://www.encyclopediaofmath.org/index.php/Linear_interpolation and http://fgiesen.wordpress.com/2012/08/15/linear-interpolation-past-present-and-future/</remarks>
|
||||
/// <param name="from">Value to interpolate from.</param>
|
||||
/// <remarks>
|
||||
/// See:
|
||||
/// <br><seealso href="http://www.encyclopediaofmath.org/index.php/Linear_interpolation"/></br>
|
||||
/// <br><seealso href="http://fgiesen.wordpress.com/2012/08/15/linear-interpolation-past-present-and-future/"/></br>
|
||||
/// </remarks>
|
||||
/// /// <param name="from">Value to interpolate from.</param>
|
||||
/// <param name="to">Value to interpolate to.</param>
|
||||
/// <param name="amount">Interpolation amount.</param>
|
||||
/// <returns>The result of linear interpolation of values based on the amount.</returns>
|
||||
@@ -1338,7 +1366,10 @@ namespace FlaxEngine
|
||||
/// <summary>
|
||||
/// Performs smooth (cubic Hermite) interpolation between 0 and 1.
|
||||
/// </summary>
|
||||
/// <remarks>See https://en.wikipedia.org/wiki/Smoothstep</remarks>
|
||||
/// <remarks>
|
||||
/// See:
|
||||
/// <br><seealso href="https://en.wikipedia.org/wiki/Smoothstep"/></br>
|
||||
/// </remarks>
|
||||
/// <param name="amount">Value between 0 and 1 indicating interpolation amount.</param>
|
||||
public static float SmoothStep(float amount)
|
||||
{
|
||||
@@ -1348,7 +1379,10 @@ namespace FlaxEngine
|
||||
/// <summary>
|
||||
/// Performs smooth (cubic Hermite) interpolation between 0 and 1.
|
||||
/// </summary>
|
||||
/// <remarks>See https://en.wikipedia.org/wiki/Smoothstep</remarks>
|
||||
/// <remarks>
|
||||
/// See:
|
||||
/// <br><seealso href="https://en.wikipedia.org/wiki/Smoothstep"/></br>
|
||||
/// </remarks>
|
||||
/// <param name="amount">Value between 0 and 1 indicating interpolation amount.</param>
|
||||
public static double SmoothStep(double amount)
|
||||
{
|
||||
@@ -1358,7 +1392,10 @@ namespace FlaxEngine
|
||||
/// <summary>
|
||||
/// Performs a smooth(er) interpolation between 0 and 1 with 1st and 2nd order derivatives of zero at endpoints.
|
||||
/// </summary>
|
||||
/// <remarks>See https://en.wikipedia.org/wiki/Smoothstep</remarks>
|
||||
/// <remarks>
|
||||
/// See:
|
||||
/// <br><seealso href="https://en.wikipedia.org/wiki/Smoothstep"/></br>
|
||||
/// </remarks>
|
||||
/// <param name="amount">Value between 0 and 1 indicating interpolation amount.</param>
|
||||
public static float SmootherStep(float amount)
|
||||
{
|
||||
@@ -1368,7 +1405,10 @@ namespace FlaxEngine
|
||||
/// <summary>
|
||||
/// Performs a smooth(er) interpolation between 0 and 1 with 1st and 2nd order derivatives of zero at endpoints.
|
||||
/// </summary>
|
||||
/// <remarks>See https://en.wikipedia.org/wiki/Smoothstep</remarks>
|
||||
/// <remarks>
|
||||
/// See:
|
||||
/// <br><seealso href="https://en.wikipedia.org/wiki/Smoothstep"/></br>
|
||||
/// </remarks>
|
||||
/// <param name="amount">Value between 0 and 1 indicating interpolation amount.</param>
|
||||
public static double SmootherStep(double amount)
|
||||
{
|
||||
@@ -1446,7 +1486,7 @@ namespace FlaxEngine
|
||||
|
||||
/// <summary>
|
||||
/// Gauss function.
|
||||
/// http://en.wikipedia.org/wiki/Gaussian_function#Two-dimensional_Gaussian_function
|
||||
/// <br><seealso href="http://en.wikipedia.org/wiki/Gaussian_function#Two-dimensional_Gaussian_function"/></br>
|
||||
/// </summary>
|
||||
/// <param name="amplitude">Curve amplitude.</param>
|
||||
/// <param name="x">Position X.</param>
|
||||
@@ -1463,7 +1503,7 @@ namespace FlaxEngine
|
||||
|
||||
/// <summary>
|
||||
/// Gauss function.
|
||||
/// http://en.wikipedia.org/wiki/Gaussian_function#Two-dimensional_Gaussian_function
|
||||
/// <br><seealso href="http://en.wikipedia.org/wiki/Gaussian_function#Two-dimensional_Gaussian_function"/></br>
|
||||
/// </summary>
|
||||
/// <param name="amplitude">Curve amplitude.</param>
|
||||
/// <param name="x">Position X.</param>
|
||||
|
||||
@@ -72,15 +72,6 @@ public:
|
||||
return _major;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the high 16 bits of the revision number.
|
||||
/// </summary>
|
||||
/// <returns>A 16-bit signed integer.</returns>
|
||||
FORCE_INLINE int16 MajorRevision() const
|
||||
{
|
||||
return static_cast<int16>(_revision >> 16);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the minor component of the version number for the current Version object.
|
||||
/// </summary>
|
||||
@@ -90,15 +81,6 @@ public:
|
||||
return _minor;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the low 16 bits of the revision number.
|
||||
/// </summary>
|
||||
/// <returns>A 16-bit signed integer.</returns>
|
||||
FORCE_INLINE int16 MinorRevision() const
|
||||
{
|
||||
return static_cast<int16>(_revision & 65535);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the revision component of the version number for the current Version object.
|
||||
/// </summary>
|
||||
@@ -126,61 +108,26 @@ public:
|
||||
return _major == obj._major && _minor == obj._minor && _build == obj._build && _revision == obj._revision;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether two specified Version objects are equal.
|
||||
/// </summary>
|
||||
/// <param name="other">The other Version object.</param>
|
||||
/// <returns>True if <paramref name="v1" /> equals <paramref name="v2" />; otherwise, false.</returns>
|
||||
FORCE_INLINE bool operator==(const Version& other) const
|
||||
{
|
||||
return Equals(other);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the first specified Version object is greater than the second specified Version object.
|
||||
/// </summary>
|
||||
/// <param name="other">The first Version object.</param>
|
||||
/// <returns>True if <paramref name="v1" /> is greater than <paramref name="v2" />; otherwise, false.</returns>
|
||||
FORCE_INLINE bool operator >(const Version& other) const
|
||||
FORCE_INLINE bool operator>(const Version& other) const
|
||||
{
|
||||
return other < *this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the first specified Version object is greater than or equal to the second specified Version object.
|
||||
/// /summary>
|
||||
/// <param name="other">The other Version object.</param>
|
||||
/// <returns>True if <paramref name="v1" /> is greater than or equal to <paramref name="v2" />; otherwise, false.</returns>
|
||||
FORCE_INLINE bool operator >=(const Version& other) const
|
||||
FORCE_INLINE bool operator>=(const Version& other) const
|
||||
{
|
||||
return other <= *this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether two specified Version objects are not equal.
|
||||
/// </summary>
|
||||
/// <param name="other">The other Version object.</param>
|
||||
/// <returns>True if <paramref name="v1" /> does not equal <paramref name="v2" />; otherwise, false.</returns>
|
||||
FORCE_INLINE bool operator!=(const Version& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the first specified Version object is less than the second specified Version object.
|
||||
/// </summary>
|
||||
/// <param name="other">The first other object.</param>
|
||||
/// <returns>True if <paramref name="v1" /> is less than <paramref name="v2" />; otherwise, false.</returns>
|
||||
FORCE_INLINE bool operator<(const Version& other) const
|
||||
{
|
||||
return CompareTo(other) < 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the first specified Version object is less than or equal to the second Version object.
|
||||
/// </summary>
|
||||
/// <param name="other">The other Version object.</param>
|
||||
/// <returns>True if <paramref name="v1" /> is less than or equal to <paramref name="v2" />; otherwise, false.</returns>
|
||||
FORCE_INLINE bool operator<=(const Version& other) const
|
||||
{
|
||||
return CompareTo(other) <= 0;
|
||||
|
||||
@@ -274,12 +274,12 @@ namespace FlaxEngine.Interop
|
||||
#if FLAX_EDITOR
|
||||
[HideInEditor]
|
||||
#endif
|
||||
internal static class ManagedString
|
||||
public static class ManagedString
|
||||
{
|
||||
internal static ManagedHandle EmptyStringHandle = ManagedHandle.Alloc(string.Empty);
|
||||
|
||||
[System.Diagnostics.DebuggerStepThrough]
|
||||
internal static unsafe IntPtr ToNative(string str)
|
||||
public static unsafe IntPtr ToNative(string str)
|
||||
{
|
||||
if (str == null)
|
||||
return IntPtr.Zero;
|
||||
@@ -290,7 +290,7 @@ namespace FlaxEngine.Interop
|
||||
}
|
||||
|
||||
[System.Diagnostics.DebuggerStepThrough]
|
||||
internal static unsafe IntPtr ToNativeWeak(string str)
|
||||
public static unsafe IntPtr ToNativeWeak(string str)
|
||||
{
|
||||
if (str == null)
|
||||
return IntPtr.Zero;
|
||||
@@ -301,7 +301,7 @@ namespace FlaxEngine.Interop
|
||||
}
|
||||
|
||||
[System.Diagnostics.DebuggerStepThrough]
|
||||
internal static string ToManaged(IntPtr ptr)
|
||||
public static string ToManaged(IntPtr ptr)
|
||||
{
|
||||
if (ptr == IntPtr.Zero)
|
||||
return null;
|
||||
@@ -309,7 +309,7 @@ namespace FlaxEngine.Interop
|
||||
}
|
||||
|
||||
[System.Diagnostics.DebuggerStepThrough]
|
||||
internal static void Free(IntPtr ptr)
|
||||
public static void Free(IntPtr ptr)
|
||||
{
|
||||
if (ptr == IntPtr.Zero)
|
||||
return;
|
||||
|
||||
@@ -444,7 +444,7 @@ namespace FlaxEngine.Interop
|
||||
}
|
||||
else
|
||||
{
|
||||
toManagedFieldMethod = typeof(MarshalHelper<>.ReferenceTypeField<>).MakeGenericType(type, fieldType).GetMethod(nameof(MarshalHelper<T>.ReferenceTypeField<ReferenceTypePlaceholder>.ToManagedField), bindingFlags);
|
||||
toManagedFieldMethod = typeof(MarshalHelper<>.ReferenceTypeField<>).MakeGenericType(type, arrayElementType).GetMethod(nameof(MarshalHelper<T>.ReferenceTypeField<ReferenceTypePlaceholder>.ToManagedFieldArray), bindingFlags);
|
||||
toNativeFieldMethod = typeof(MarshalHelper<>.ReferenceTypeField<>).MakeGenericType(type, fieldType).GetMethod(nameof(MarshalHelper<T>.ReferenceTypeField<ReferenceTypePlaceholder>.ToNativeField), bindingFlags);
|
||||
}
|
||||
}
|
||||
@@ -663,6 +663,17 @@ namespace FlaxEngine.Interop
|
||||
MarshalHelperReferenceType<TField>.ToManaged(ref fieldValueRef, Unsafe.Read<IntPtr>(fieldPtr.ToPointer()), false);
|
||||
}
|
||||
|
||||
internal static void ToManagedFieldArray(FieldInfo field, ref T fieldOwner, IntPtr fieldPtr, out int fieldOffset)
|
||||
{
|
||||
fieldOffset = Unsafe.SizeOf<IntPtr>();
|
||||
IntPtr fieldStartPtr = fieldPtr;
|
||||
fieldPtr = EnsureAlignment(fieldPtr, IntPtr.Size);
|
||||
fieldOffset += (fieldPtr - fieldStartPtr).ToInt32();
|
||||
|
||||
ref TField[] fieldValueRef = ref GetFieldReference<TField[]>(field, ref fieldOwner);
|
||||
MarshalHelperReferenceType<TField>.ToManagedArray(ref fieldValueRef, Unsafe.Read<IntPtr>(fieldPtr.ToPointer()), false);
|
||||
}
|
||||
|
||||
internal static void ToNativeField(FieldInfo field, ref T fieldOwner, IntPtr fieldPtr, out int fieldOffset)
|
||||
{
|
||||
fieldOffset = Unsafe.SizeOf<IntPtr>();
|
||||
@@ -691,14 +702,15 @@ namespace FlaxEngine.Interop
|
||||
internal static void ToManaged(ref T managedValue, IntPtr nativePtr, bool byRef)
|
||||
{
|
||||
Type type = typeof(T);
|
||||
if (type.IsByRef || byRef)
|
||||
byRef |= type.IsByRef;
|
||||
if (byRef)
|
||||
{
|
||||
if (type.IsByRef)
|
||||
type = type.GetElementType();
|
||||
Assert.IsTrue(type.IsValueType);
|
||||
}
|
||||
|
||||
if (type == typeof(IntPtr))
|
||||
if (type == typeof(IntPtr) && byRef)
|
||||
managedValue = (T)(object)nativePtr;
|
||||
else if (type == typeof(ManagedHandle))
|
||||
managedValue = (T)(object)ManagedHandle.FromIntPtr(nativePtr);
|
||||
@@ -778,10 +790,12 @@ namespace FlaxEngine.Interop
|
||||
|
||||
if (type == typeof(string))
|
||||
managedValue = Unsafe.As<T>(ManagedString.ToManaged(nativePtr));
|
||||
else if (nativePtr == IntPtr.Zero)
|
||||
managedValue = null;
|
||||
else if (type.IsClass)
|
||||
managedValue = nativePtr != IntPtr.Zero ? Unsafe.As<T>(ManagedHandle.FromIntPtr(nativePtr).Target) : null;
|
||||
managedValue = Unsafe.As<T>(ManagedHandle.FromIntPtr(nativePtr).Target);
|
||||
else if (type.IsInterface) // Dictionary
|
||||
managedValue = nativePtr != IntPtr.Zero ? Unsafe.As<T>(ManagedHandle.FromIntPtr(nativePtr).Target) : null;
|
||||
managedValue = Unsafe.As<T>(ManagedHandle.FromIntPtr(nativePtr).Target);
|
||||
else
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
@@ -788,7 +788,9 @@ void Actor::BreakPrefabLink()
|
||||
|
||||
void Actor::Initialize()
|
||||
{
|
||||
ASSERT(!IsDuringPlay());
|
||||
#if ENABLE_ASSERTION
|
||||
CHECK(!IsDuringPlay());
|
||||
#endif
|
||||
|
||||
// Cache
|
||||
if (_parent)
|
||||
@@ -802,7 +804,9 @@ void Actor::Initialize()
|
||||
|
||||
void Actor::BeginPlay(SceneBeginData* data)
|
||||
{
|
||||
ASSERT(!IsDuringPlay());
|
||||
#if ENABLE_ASSERTION
|
||||
CHECK(!IsDuringPlay());
|
||||
#endif
|
||||
|
||||
// Set flag
|
||||
Flags |= ObjectFlags::IsDuringPlay;
|
||||
@@ -832,7 +836,9 @@ void Actor::BeginPlay(SceneBeginData* data)
|
||||
|
||||
void Actor::EndPlay()
|
||||
{
|
||||
ASSERT(IsDuringPlay());
|
||||
#if ENABLE_ASSERTION
|
||||
CHECK(IsDuringPlay());
|
||||
#endif
|
||||
|
||||
// Fire event for scripting
|
||||
if (IsActiveInHierarchy() && GetScene())
|
||||
@@ -1059,7 +1065,9 @@ void Actor::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier)
|
||||
|
||||
void Actor::OnEnable()
|
||||
{
|
||||
ASSERT(!_isEnabled);
|
||||
#if ENABLE_ASSERTION
|
||||
CHECK(!_isEnabled);
|
||||
#endif
|
||||
_isEnabled = true;
|
||||
|
||||
for (int32 i = 0; i < Scripts.Count(); i++)
|
||||
@@ -1079,7 +1087,9 @@ void Actor::OnEnable()
|
||||
|
||||
void Actor::OnDisable()
|
||||
{
|
||||
ASSERT(_isEnabled);
|
||||
#if ENABLE_ASSERTION
|
||||
CHECK(_isEnabled);
|
||||
#endif
|
||||
_isEnabled = false;
|
||||
|
||||
for (int32 i = Scripts.Count() - 1; i >= 0; i--)
|
||||
|
||||
@@ -53,4 +53,23 @@ namespace FlaxEngine
|
||||
UseSmallPicker = useSmallPicker;
|
||||
}
|
||||
}
|
||||
|
||||
#if USE_NETCORE
|
||||
/// <summary>
|
||||
/// Specifies a options for an asset reference picker in the editor. Allows to customize view or provide custom value assign policy.
|
||||
/// </summary>
|
||||
/// <seealso cref="System.Attribute" />
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
|
||||
public class AssetReferenceAttribute<T> : AssetReferenceAttribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AssetReferenceAttribute"/> class for generic type T.
|
||||
/// </summary>
|
||||
/// <param name="useSmallPicker">True if use asset picker with a smaller height (single line), otherwise will use with full icon.</param>
|
||||
public AssetReferenceAttribute(bool useSmallPicker = false)
|
||||
: base(typeof(T), useSmallPicker)
|
||||
{
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -108,7 +108,7 @@ void ManagedSerialization::Deserialize(const StringAnsiView& data, MObject* obje
|
||||
// Prepare arguments
|
||||
void* args[3];
|
||||
args[0] = object;
|
||||
args[1] = (void*)str;
|
||||
args[1] = (void*)&str;
|
||||
args[2] = (void*)&len;
|
||||
|
||||
// Call serialization tool
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include "MUtils.h"
|
||||
#include "MClass.h"
|
||||
#include "MCore.h"
|
||||
#include "MDomain.h"
|
||||
#include "Engine/Core/Log.h"
|
||||
#include "Engine/Core/Types/DataContainer.h"
|
||||
#include "Engine/Core/Types/Version.h"
|
||||
@@ -449,7 +448,7 @@ Variant MUtils::UnboxVariant(MObject* value)
|
||||
{
|
||||
auto& a = array[i];
|
||||
a.SetType(elementType);
|
||||
Platform::MemoryCopy(&a.AsData,(byte*)ptr + elementSize * i, elementSize);
|
||||
Platform::MemoryCopy(&a.AsData, (byte*)ptr + elementSize * i, elementSize);
|
||||
}
|
||||
break;
|
||||
case VariantType::Transform:
|
||||
@@ -1004,11 +1003,11 @@ MClass* MUtils::GetClass(const Variant& value)
|
||||
case VariantType::Enum:
|
||||
return Scripting::FindClass(StringAnsiView(value.Type.TypeName));
|
||||
case VariantType::ManagedObject:
|
||||
{
|
||||
MObject* obj = (MObject*)value;
|
||||
if (obj)
|
||||
return MCore::Object::GetClass(obj);
|
||||
}
|
||||
{
|
||||
MObject* obj = (MObject*)value;
|
||||
if (obj)
|
||||
return MCore::Object::GetClass(obj);
|
||||
}
|
||||
default: ;
|
||||
}
|
||||
return GetClass(value.Type);
|
||||
@@ -1224,10 +1223,10 @@ MObject* MUtils::ToManaged(const Version& value)
|
||||
auto versionToManaged = scriptingClass->GetMethod("VersionToManaged", 4);
|
||||
CHECK_RETURN(versionToManaged, nullptr);
|
||||
|
||||
int major = value.Major();
|
||||
int minor = value.Minor();
|
||||
int build = value.Build();
|
||||
int revision = value.Revision();
|
||||
int32 major = value.Major();
|
||||
int32 minor = value.Minor();
|
||||
int32 build = value.Build();
|
||||
int32 revision = value.Revision();
|
||||
|
||||
void* params[4];
|
||||
params[0] = &major;
|
||||
@@ -1244,26 +1243,29 @@ MObject* MUtils::ToManaged(const Version& value)
|
||||
|
||||
Version MUtils::ToNative(MObject* value)
|
||||
{
|
||||
Version result;
|
||||
if (value)
|
||||
#if USE_NETCORE
|
||||
{
|
||||
auto ver = Version();
|
||||
|
||||
auto scriptingClass = Scripting::GetStaticClass();
|
||||
CHECK_RETURN(scriptingClass, ver);
|
||||
auto versionToNative = scriptingClass->GetMethod("VersionToNative", 2);
|
||||
CHECK_RETURN(versionToNative, ver);
|
||||
CHECK_RETURN(scriptingClass, result);
|
||||
auto versionToNative = scriptingClass->GetMethod("VersionToNative", 5);
|
||||
CHECK_RETURN(versionToNative, result);
|
||||
|
||||
void* params[2];
|
||||
void* params[5];
|
||||
params[0] = value;
|
||||
params[1] = &ver;
|
||||
params[1] = (byte*)&result;
|
||||
params[2] = (byte*)&result + sizeof(int32);
|
||||
params[3] = (byte*)&result + sizeof(int32) * 2;
|
||||
params[4] = (byte*)&result + sizeof(int32) * 3;
|
||||
versionToNative->Invoke(nullptr, params, nullptr);
|
||||
return ver;
|
||||
|
||||
return result;
|
||||
}
|
||||
#else
|
||||
return *(Version*)MCore::Object::Unbox(value);
|
||||
#endif
|
||||
return Version();
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -17,10 +17,29 @@ public class Scripting : EngineModule
|
||||
{
|
||||
if (EngineConfiguration.WithDotNet(options))
|
||||
{
|
||||
void AddFrameworkDefines(string template, int major, int latestMinor)
|
||||
{
|
||||
for (int minor = latestMinor; minor >= 0; minor--)
|
||||
{
|
||||
options.ScriptingAPI.Defines.Add(string.Format(template, major, minor));
|
||||
options.ScriptingAPI.Defines.Add(string.Format($"{template}_OR_GREATER", major, minor));
|
||||
}
|
||||
}
|
||||
|
||||
// .NET
|
||||
options.PrivateDependencies.Add("nethost");
|
||||
options.ScriptingAPI.Defines.Add("USE_NETCORE");
|
||||
|
||||
// .NET SDK
|
||||
AddFrameworkDefines("NET{0}_{1}", 7, 0); // "NET7_0" and "NET7_0_OR_GREATER"
|
||||
AddFrameworkDefines("NET{0}_{1}", 6, 0);
|
||||
AddFrameworkDefines("NET{0}_{1}", 5, 0);
|
||||
options.ScriptingAPI.Defines.Add("NET");
|
||||
AddFrameworkDefines("NETCOREAPP{0}_{1}", 3, 1); // "NETCOREAPP3_1" and "NETCOREAPP3_1_OR_GREATER"
|
||||
AddFrameworkDefines("NETCOREAPP{0}_{1}", 2, 2);
|
||||
AddFrameworkDefines("NETCOREAPP{0}_{1}", 1, 1);
|
||||
options.ScriptingAPI.Defines.Add("NETCOREAPP");
|
||||
|
||||
if (options.Target is EngineTarget engineTarget && engineTarget.UseSeparateMainExecutable(options))
|
||||
{
|
||||
// Build target doesn't support linking again main executable (eg. Linux) thus additional shared library is used for the engine (eg. libFlaxEditor.so)
|
||||
|
||||
@@ -229,22 +229,24 @@ namespace FlaxEngine
|
||||
return ManagedHandle.Alloc(new CultureInfo(lcid));
|
||||
}
|
||||
|
||||
internal static void VersionToNative(ManagedHandle versionHandle, IntPtr nativePtr)
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct VersionNative
|
||||
{
|
||||
public int Major;
|
||||
public int Minor;
|
||||
public int Build;
|
||||
public int Revision;
|
||||
}
|
||||
|
||||
internal static void VersionToNative(ManagedHandle versionHandle, ref int major, ref int minor, ref int build, ref int revision)
|
||||
{
|
||||
Version version = Unsafe.As<Version>(versionHandle.Target);
|
||||
if (version != null)
|
||||
{
|
||||
Marshal.WriteInt32(nativePtr, 0, version.Major);
|
||||
Marshal.WriteInt32(nativePtr, 4, version.Minor);
|
||||
Marshal.WriteInt32(nativePtr, 8, version.Build);
|
||||
Marshal.WriteInt32(nativePtr, 12, version.Revision);
|
||||
}
|
||||
else
|
||||
{
|
||||
Marshal.WriteInt32(nativePtr, 0, 0);
|
||||
Marshal.WriteInt32(nativePtr, 4, 0);
|
||||
Marshal.WriteInt32(nativePtr, 8, -1);
|
||||
Marshal.WriteInt32(nativePtr, 12, -1);
|
||||
major = version.Major;
|
||||
minor = version.Minor;
|
||||
build = version.Build;
|
||||
revision = version.Revision;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -151,6 +151,13 @@ void ShadowsOfMordor::Builder::onJobRender(GPUContext* context)
|
||||
auto patch = terrain->GetPatch(entry.AsTerrain.PatchIndex);
|
||||
auto chunk = &patch->Chunks[entry.AsTerrain.ChunkIndex];
|
||||
auto chunkSize = terrain->GetChunkSize();
|
||||
if (!patch->Heightmap)
|
||||
{
|
||||
LOG(Error, "Terrain actor {0} is missing heightmap for baking, skipping baking stage.", terrain->GetName());
|
||||
_wasStageDone = true;
|
||||
scene->EntriesLocker.Unlock();
|
||||
return;
|
||||
}
|
||||
const auto heightmap = patch->Heightmap.Get()->GetTexture();
|
||||
|
||||
Matrix world;
|
||||
@@ -171,7 +178,7 @@ void ShadowsOfMordor::Builder::onJobRender(GPUContext* context)
|
||||
|
||||
DrawCall drawCall;
|
||||
if (TerrainManager::GetChunkGeometry(drawCall, chunkSize, 0))
|
||||
return;
|
||||
break;
|
||||
|
||||
context->UpdateCB(cb, &shaderData);
|
||||
context->BindCB(0, cb);
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
||||
|
||||
#if FLAX_TESTS
|
||||
using System;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace FlaxEngine.Tests
|
||||
{
|
||||
/// <summary>
|
||||
/// Tests for <see cref="Mathf"/> and <see cref="Mathd"/>.
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public class TestMath
|
||||
{
|
||||
/// <summary>
|
||||
/// Test unwinding angles.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestUnwind()
|
||||
{
|
||||
Assert.AreEqual(0.0f, Mathf.UnwindDegreesAccurate(0.0f));
|
||||
Assert.AreEqual(45.0f, Mathf.UnwindDegreesAccurate(45.0f));
|
||||
Assert.AreEqual(90.0f, Mathf.UnwindDegreesAccurate(90.0f));
|
||||
Assert.AreEqual(180.0f, Mathf.UnwindDegreesAccurate(180.0f));
|
||||
Assert.AreEqual(0.0f, Mathf.UnwindDegreesAccurate(360.0f));
|
||||
Assert.AreEqual(0.0f, Mathf.UnwindDegrees(0.0f));
|
||||
Assert.AreEqual(45.0f, Mathf.UnwindDegrees(45.0f));
|
||||
Assert.AreEqual(90.0f, Mathf.UnwindDegrees(90.0f));
|
||||
Assert.AreEqual(180.0f, Mathf.UnwindDegrees(180.0f));
|
||||
Assert.AreEqual(0.0f, Mathf.UnwindDegrees(360.0f));
|
||||
var fError = 0.001f;
|
||||
var dError = 0.00001;
|
||||
for (float f = -400.0f; f <= 400.0f; f += 0.1f)
|
||||
{
|
||||
var f1 = Mathf.UnwindDegreesAccurate(f);
|
||||
var f2 = Mathf.UnwindDegrees(f);
|
||||
if (Mathf.Abs(f1 - f2) >= fError)
|
||||
throw new Exception($"Failed on angle={f}, {f1} != {f2}");
|
||||
var d = (double)f;
|
||||
var d1 = Mathd.UnwindDegreesAccurate(d);
|
||||
var d2 = Mathd.UnwindDegrees(d);
|
||||
if (Mathd.Abs(d1 - d2) >= dError)
|
||||
throw new Exception($"Failed on angle={d}, {d1} != {d2}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user