ougge/src-csharp/GameObject.cs

85 lines
2.3 KiB
C#

using System;
using System.Collections.Generic;
using System.Numerics;
using System.Runtime.InteropServices;
namespace Ougge;
[StructLayout(LayoutKind.Sequential)]
public struct Transform
{
Vector2 scale;
Vector2 position;
float rotation;
}
public class GameObject
{
// index in GameObjectPool
private ulong _id;
private uint _index;
private bool _isDestroyed;
public ulong Id => _id;
public bool IsDestroyed => _isDestroyed;
public Transform Transform { get; }
public GameObject? Parent;
public Dictionary<Type, Component> Components;
private GameObject(ulong id, uint nativePoolIndex)
{
_id = id;
_index = nativePoolIndex;
// Do not move this line or mono runtime will throw SEGFAULT.
// Mono runtime can't set values in field declaration, but initializing everything in constructor is OK.
Components = new();
}
static public GameObject Create()
{
NativeMethods.createGameObject(out ulong id, out uint index);
var o = new GameObject(id, index);
return o;
}
public void Destroy()
{
if(_isDestroyed)
return;
_isDestroyed = NativeMethods.destroyGameObject(_index);
if(!_isDestroyed)
throw new Exception($"Can't destroy GameObject({_id})");
}
/// <param name="t">type derived from Component</param>
/// <returns>true if new component instance was created, false if component of the same tipe is already added to GameObject</returns>
/// <exception cref="Exception"></exception>
public bool TryCreateComponent(Type t)
{
if(!t.IsSubclassOf(typeof(Component)))
throw new Exception($"type {t.FullName} is not a derived class of {typeof(Component).FullName}");
if(Components.ContainsKey(t))
return false;
Components.Add(t, (Component)Activator.CreateInstance(t, this));
return true;
}
private bool TryCreateComponent_internal(string fullName)
{
Type t = Type.GetType(fullName) ?? throw new Exception($"type not found '{fullName}'");
return TryCreateComponent(t);
}
private void InvokeUpdate(double deltaTime)
{
foreach(var p in Components)
{
p.Value.Update(deltaTime);
}
}
}