DotNet script changes transform

This commit is contained in:
Simon Lübeß
2022-04-27 23:58:50 +02:00
parent 2bac6a8d05
commit 63b9270710
11 changed files with 444 additions and 22 deletions
+29 -8
View File
@@ -297,12 +297,13 @@ namespace GlitchyEngine.World
private String TypeName = null;
typealias CreateInstanceDelegate = function Instance(void* typeNamePtr, int32 typeNameLength, EcsEntity entity);
typealias InstanceDelegate = function void(Instance instance);
typealias CreateInstanceDelegate = function Instance(void* typeNamePtr, int32 typeNameLength, EcsEntity entity, void* scene);
typealias UpdateInstanceDelegate = function void(Instance instance, uint64 frameCount, TimeSpan totalTime, TimeSpan frameTime);
typealias DestroyInstanceDelegate = function void(Instance instance);
public static CreateInstanceDelegate CreateInstanceFn;
public static InstanceDelegate UpdateInstanceFn;
public static InstanceDelegate DestroyInstanceFn;
public static UpdateInstanceDelegate UpdateInstanceFn;
public static DestroyInstanceDelegate DestroyInstanceFn;
public const Self ss = Self();
@@ -311,14 +312,16 @@ namespace GlitchyEngine.World
TypeName = new String(dotNetAssemblyQualifiedTypeName);
}
internal void CreateInstance(EcsEntity entity) mut
internal void CreateInstance(EcsEntity entity, Scene scene) mut
{
InstanceHandlePtr = CreateInstanceFn(TypeName.Ptr, (int32)TypeName.Length, entity);
void* scenePtr = Internal.UnsafeCastToPtr(scene);
InstanceHandlePtr = CreateInstanceFn(TypeName.Ptr, (int32)TypeName.Length, entity, scenePtr);
}
internal void UpdateInstance()
internal void UpdateInstance(GameTime gameTime)
{
UpdateInstanceFn(InstanceHandlePtr);
UpdateInstanceFn(InstanceHandlePtr, gameTime.FrameCount, gameTime.TotalTime, gameTime.FrameTime);
}
internal void DestroyInstance()
@@ -330,5 +333,23 @@ namespace GlitchyEngine.World
{
delete TypeName;
}
[Export(), LinkName("GE_DoStuff")]
public static int32 DoStuff()
{
return 69;
}
[Export, LinkName("GE_DotNetScript_GetComponent")]
private static void* GetComponent(EcsEntity entity, void* scenePtr)
{
Scene scene = (Scene)Internal.UnsafeCastToObject(scenePtr);
Entity e = .(entity, scene);
TransformComponent* ptr = e.GetComponent<TransformComponent>();
return ptr;
}
}
}
+2 -2
View File
@@ -59,10 +59,10 @@ namespace GlitchyEngine.World
{
if (script.InstanceHandlePtr == 0)
{
script.[Friend]CreateInstance(entity);
script.[Friend]CreateInstance(entity, this);
}
script.[Friend]UpdateInstance(); // TODO: Gametime
script.[Friend]UpdateInstance(gameTime);
}
Camera* primaryCamera = null;
@@ -1,7 +1,9 @@
using System;
using GlitchyEngine.Math;
namespace GlitchyEngine.World
{
[Ordered]
public struct TransformComponent
{
EcsEntity _parent = .InvalidEntity;
@@ -0,0 +1,229 @@
using System.Numerics;
using System.Runtime.InteropServices;
namespace DotNetScriptingHelper.Components;
[GameComponent, StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct LameTransformComponent
{
private EcsEntity _parent;
private Vector3 _position;
private Quaternion _rotation;
private Vector3 _scale;
private Vector3 _editorRotationEuler;
private Matrix4x4 _localTransform;
private bool _isDirty;
private Matrix4x4 _worldTransform;
private UIntPtr _frame;
public EcsEntity Parent
{
get => _parent;
set
{
if (_parent == value)
return;
_parent = value;
_isDirty = true;
}
}
public Matrix4x4 LocalTransform
{
get => _localTransform;
set
{
if (_localTransform == value)
return;
_localTransform = value;
Matrix4x4.Decompose(_localTransform, out _position, out _rotation, out _scale);
_isDirty = true;
}
}
// Todo: WorldTransform?
public Vector3 Position
{
get => _position;
set
{
if (_position == value)
return;
_position = value;
_isDirty = true;
}
}
public Quaternion Rotation
{
get => _rotation;
set
{
if (_rotation == value)
return;
_rotation = value;
_isDirty = true;
}
}
public (Vector3 Axis, float Angle) RotationAxisAngle
{
get => _rotation.ToAxisAngle();
set
{
Quaternion quat = Quaternion.CreateFromAxisAngle(value.Axis, value.Angle);
if (_rotation == quat)
return;
_rotation = quat;
_isDirty = true;
}
}
public Vector3 RotationEuler
{
get => _rotation.ToEulerAngles();
set => Rotation = Quaternion.CreateFromYawPitchRoll(value.Y, value.X, value.Z);
}
public Vector3 Scale
{
get => _scale;
set
{
if (_scale == value)
return;
_scale = value;
_isDirty = true;
}
}
}
public unsafe struct TransformComponent
{
[GameComponent, StructLayout(LayoutKind.Sequential, Pack = 1)]
internal struct TransformComponentData
{
internal EcsEntity _parent;
internal Vector3 _position;
internal Quaternion _rotation;
internal Vector3 _scale;
internal Vector3 _editorRotationEuler;
internal Matrix4x4 _localTransform;
internal bool _isDirty;
internal Matrix4x4 _worldTransform;
internal UIntPtr _frame;
}
private TransformComponentData* _component;
internal TransformComponent(IntPtr component)
{
_component = (TransformComponentData*)component;
}
public EcsEntity Parent
{
get => _component->_parent;
set
{
if (_component->_parent == value)
return;
_component->_parent = value;
_component->_isDirty = true;
}
}
public Matrix4x4 LocalTransform
{
get => _component->_localTransform;
set
{
if (_component->_localTransform == value)
return;
_component->_localTransform = value;
Matrix4x4.Decompose(_component->_localTransform,
out _component->_position, out _component->_rotation, out _component->_scale);
_component->_isDirty = true;
}
}
// Todo: WorldTransform?
public Vector3 Position
{
get => _component->_position;
set
{
if (_component->_position == value)
return;
_component->_position = value;
_component->_isDirty = true;
}
}
public Quaternion Rotation
{
get => _component->_rotation;
set
{
if (_component->_rotation == value)
return;
_component->_rotation = value;
_component->_isDirty = true;
}
}
public (Vector3 Axis, float Angle) RotationAxisAngle
{
get => _component->_rotation.ToAxisAngle();
set
{
Quaternion quat = Quaternion.CreateFromAxisAngle(value.Axis, value.Angle);
if (_component->_rotation == quat)
return;
_component->_rotation = quat;
_component->_isDirty = true;
}
}
public Vector3 RotationEuler
{
get => _component->_rotation.ToEulerAngles();
set => Rotation = Quaternion.CreateFromYawPitchRoll(value.Y, value.X, value.Z);
}
public Vector3 Scale
{
get => _component->_scale;
set
{
if (_component->_scale == value)
return;
_component->_scale = value;
_component->_isDirty = true;
}
}
}
@@ -20,4 +20,14 @@ public readonly struct EcsEntity
public bool IsValid => Index != InvalidEntity.Index;
public static readonly EcsEntity InvalidEntity = new(uint.MaxValue, 0);
public static bool operator ==(EcsEntity left, EcsEntity right)
{
return left._id == right._id;
}
public static bool operator !=(EcsEntity left, EcsEntity right)
{
return left._id != right._id;
}
}
@@ -2,14 +2,15 @@
public struct Entity
{
public EcsEntity Handle { get; private set; }
// TODO: Scene
public EcsEntity Handle { get; }
public IntPtr Scene { get; }
public bool IsValid => Handle.IsValid;
public Entity(EcsEntity handle)
public Entity(EcsEntity handle, IntPtr scene)
{
Handle = handle;
Scene = scene;
}
// TODO: Get Parent, Children
@@ -0,0 +1,23 @@
namespace DotNetScriptingHelper;
public class GameTime
{
private ulong _frameCount;
private TimeSpan _totalTime;
private TimeSpan _frameTime;
public ulong FrameCount => _frameCount;
public TimeSpan TotalTime => _totalTime;
public TimeSpan FrameTime => _frameTime;
public float DeltaTime => (float)_frameTime.TotalSeconds;
public float TotalSeconds => (float)_totalTime.TotalSeconds;
internal GameTime(ulong frameCount, TimeSpan totalTime, TimeSpan frameTime)
{
_frameCount = frameCount;
_totalTime = totalTime;
_frameTime = frameTime;
}
}
@@ -0,0 +1,14 @@
namespace DotNetScriptingHelper;
public interface IGameComponent
{
static int I { get; }
}
public class GameComponentAttribute : Attribute
{
public GameComponentAttribute()
{
}
}
@@ -0,0 +1,68 @@
using System.Numerics;
namespace DotNetScriptingHelper;
public static class QuaternionExtensions
{
public static (Vector3 Axis, float Angle) ToAxisAngle(this Quaternion quat)
{
// scalar part = cos(θ/2)
// So, we can extract the angle directly.
float angle = 2.0f * MathF.Acos(quat.W);
// vector part = axis * sin(θ/2)
// In other words, the vector part is the axis, but with length of sin(θ/2).
// We assume quaternion is unit length, so subtracting w^2 gives us length of just vector part (aka sin(θ/2)).
float length = MathF.Sqrt(1.0f - (quat.W * quat.W));
Vector3 axis;
// Normalize vector part to get the axis!
if (length == 0)
{
axis = Vector3.Zero;
}
else
{
length = 1.0f / length;
axis.X = quat.X * length;
axis.Y = quat.Y * length;
axis.Z = quat.Z * length;
}
return (axis, angle);
}
public static Vector3 ToEulerAngles(this Quaternion q)
{
// http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/
Vector3 result;
float sqw = q.W * q.W;
float sqx = q.X * q.X;
float sqy = q.Y * q.Y;
float sqz = q.Z * q.Z;
float unit = sqx + sqy + sqz + sqw; // if normalised is one, otherwise is correction factor
float test = q.X * q.Y + q.Z * q.W;
if (test > 0.4999f * unit)
{ // singularity at north pole
result.Y = 2.0f * MathF.Atan2(q.X, q.W);
result.Z = MathF.PI / 2.0f;
result.X = 0.0f;
return result;
}
if (test < -0.4999f * unit)
{ // singularity at south pole
result.Y = -2.0f * MathF.Atan2(q.X, q.W);
result.Z = -MathF.PI / 2.0f;
result.X = 0.0f;
return result;
}
result.Y = MathF.Atan2(2 * q.Y * q.W - 2 * q.X * q.Z, sqx - sqy - sqz + sqw);
result.Z = MathF.Asin(2 * test / unit);
result.X = MathF.Atan2(2 * q.X * q.W - 2 * q.Y * q.Z, -sqx + sqy - sqz + sqw);
return result;
}
}
@@ -1,5 +1,7 @@
using System.Diagnostics;
using System.Reflection;
using System.Runtime.InteropServices;
using DotNetScriptingHelper.Components;
namespace DotNetScriptingHelper;
@@ -9,10 +11,10 @@ public abstract class ScriptableEntity
public virtual void OnCreate() { }
protected virtual void OnDestroy() { }
protected virtual void OnUpdate() { }
protected virtual void OnUpdate(GameTime gameTime) { }
[UnmanagedCallersOnly]
public static IntPtr CreateInstance(IntPtr typeNamePtr, int typeNameLength, EcsEntity entity)
public static IntPtr CreateInstance(IntPtr typeNamePtr, int typeNameLength, EcsEntity entity, IntPtr scene)
{
try
{
@@ -31,7 +33,7 @@ public abstract class ScriptableEntity
if (instance is not ScriptableEntity scriptableEntity)
return IntPtr.Zero;
scriptableEntity.Entity = new Entity(entity);
scriptableEntity.Entity = new Entity(entity, scene);
scriptableEntity.OnCreate();
GCHandle handle = GCHandle.Alloc(instance);
@@ -58,13 +60,39 @@ public abstract class ScriptableEntity
}
[UnmanagedCallersOnly]
public static void UpdateEntity(IntPtr entityPtr)
public static void UpdateEntity(IntPtr entityPtr, ulong frameCount, TimeSpan totalTime, TimeSpan frameTime)
{
GCHandle entityHandle = GCHandle.FromIntPtr(entityPtr);
if (entityHandle.Target is ScriptableEntity entity)
{
entity.OnUpdate();
GameTime gameTime = new GameTime(frameCount, totalTime, frameTime);
entity.OnUpdate(gameTime);
}
}
[DllImport("GlitchyEditor.exe", EntryPoint = "GE_DoStuff")]
static extern int DoStuff();
[DllImport("GlitchyEditor.exe", EntryPoint = "GE_DotNetScript_GetComponent")]
private static extern IntPtr GetComponent(EcsEntity entity, IntPtr scenePtr);
protected TransformComponent GetTransform()// where T : struct
{
IntPtr component = GetComponent(Entity.Handle, Entity.Scene);
return new TransformComponent(component);
//unsafe
//{
// TransformComponent* transform = (TransformComponent*)component;
// return ref *transform;
//}
//GameComponentAttribute? attribute = typeof(T).GetCustomAttribute<GameComponentAttribute>();
//Debug.Assert(attribute != null, $"Requested type {typeof(T)} is not a component.");
}
}
@@ -1,13 +1,39 @@
using System.Diagnostics;
using System.Numerics;
using DotNetScriptingHelper.Components;
namespace DotNetScriptingHelper;
public class TestEntityScript : ScriptableEntity
{
public int Inty = 1337;
private TransformComponent _transform;
protected override void OnUpdate()
public override void OnCreate()
{
Debug.WriteLine($"My Number is {Inty++}");
_transform = GetTransform();
}
protected override void OnUpdate(GameTime gameTime)
{
float f = (float)Math.Sin(gameTime.TotalSeconds);
Vector3 pos = _transform.Position;
pos.Y = f;
_transform.Position = pos;
float fx = MathF.Sin(gameTime.TotalSeconds * 2) / 2 + 1;
float fy = MathF.Cos(gameTime.TotalSeconds * 2) / 2 + 1;
Vector3 scl = _transform.Scale;
scl.X = fx;
scl.Y = fy;
_transform.Scale = scl;
float fr = MathF.Cos(gameTime.TotalSeconds / 4) * MathF.PI * 10;
_transform.Rotation = Quaternion.CreateFromYawPitchRoll(0, 0, fr);
}
}