GameObject and Component

This commit is contained in:
Timerix 2025-04-18 18:24:02 +05:00
parent 47574e9b30
commit 04e4f63fd7
7 changed files with 136 additions and 41 deletions

16
src-csharp/Component.cs Normal file
View File

@ -0,0 +1,16 @@
using System;
namespace Ougge;
public abstract class Component {
private GameObject _gameObject;
internal Component(GameObject gameObject)
{
_gameObject = gameObject;
}
public GameObject Owner { get => _gameObject.IsDestroyed ? throw new Exception("GameObject") : _gameObject; }
public virtual void Update(double deltaTime) {}
}

View File

@ -0,0 +1,15 @@
using System;
namespace Ougge;
public class ExampleComponent : Component
{
public ExampleComponent(GameObject gameObject) : base(gameObject)
{
}
public override void Update(double deltaTime)
{
Console.WriteLine($"C# deltaTime {deltaTime} object id {Owner.Id}");
}
}

View File

@ -1,4 +1,5 @@
using System.Management.Instrumentation; using System;
using System.Collections.Generic;
using System.Numerics; using System.Numerics;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
@ -7,18 +8,75 @@ namespace Ougge;
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public struct Transform public struct Transform
{ {
Vector2 scale; Vector2 scale;
Vector2 position; Vector2 position;
float rotation; float rotation;
} }
public class Component
{
GameObject owner;
}
public class GameObject public class GameObject
{ {
Transform transform { get; } // index in GameObjectPool
GameObject? parent; 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 readonly Dictionary<Type, Component> Components = new();
private GameObject()
{
}
private void Init(ulong id, uint nativePoolIndex)
{
_id = id;
_index = nativePoolIndex;
}
static public GameObject Create()
{
NativeMethods.createGameObject(out ulong id, out uint index);
var o = new GameObject();
o.Init(id, index);
return o;
}
public void Destroy()
{
if(_isDestroyed)
return;
_isDestroyed = NativeMethods.destroyGameObject(_index);
if(!_isDestroyed)
throw new Exception($"Can't destroy GameObject({_id})");
}
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(string fullName)
{
return TryCreateComponent(Type.GetType(fullName));
}
private void UpdateComponents(double deltaTime)
{
foreach(var p in Components)
{
p.Value.Update(deltaTime);
}
}
}

View File

@ -0,0 +1,13 @@
using System;
using System.Runtime.InteropServices;
namespace Ougge;
internal static class NativeMethods
{
[DllImport("__Internal")]
internal extern static bool destroyGameObject(uint index);
[DllImport("__Internal")]
internal extern static void createGameObject(out ulong id, out uint index);
}

View File

@ -1,15 +0,0 @@
using System;
namespace Ougge;
public abstract class ScriptBase {
public virtual void Update(double deltaTime) {}
}
public class ExampleScript : ScriptBase
{
public override void Update(double deltaTime)
{
Console.WriteLine($"C# deltaTime {deltaTime}");
}
}

View File

@ -73,8 +73,11 @@ public:
void* arg_array[] = { valueToVoidPtr(args)..., nullptr }; void* arg_array[] = { valueToVoidPtr(args)..., nullptr };
MonoObject* ex = nullptr; MonoObject* ex = nullptr;
MonoObject* result = mono_runtime_invoke(method_ptr, class_instance, arg_array, &ex); MonoObject* result = mono_runtime_invoke(method_ptr, class_instance, arg_array, &ex);
if(ex) //TODO: call mono_trace_set_printerr_handler from mono/mono/utils/mono-logger.h if(ex){
//TODO: call mono_trace_set_printerr_handler from mono/mono/utils/mono-logger.h
mono_print_unhandled_exception(ex); mono_print_unhandled_exception(ex);
throw UsefulException("Some C# exception occured");
}
return valueFromMonoObject<ReturnT>(result); return valueFromMonoObject<ReturnT>(result);
}; };
template<typename RT = ReturnT> template<typename RT = ReturnT>
@ -107,6 +110,8 @@ public:
Assembly(const Assembly&) = delete; Assembly(const Assembly&) = delete;
MonoClass* getClass(const std::string& name_space, const std::string& name); MonoClass* getClass(const std::string& name_space, const std::string& name);
MonoAssembly* getMonoAssembly() const { return ptr; }
MonoImage* getMonoImage() const { return image; }
}; };

View File

@ -42,22 +42,25 @@ int main(int argc, const char** argv){
GameObjectPool p(GAMEOBJECTPOOL_SIZE); GameObjectPool p(GAMEOBJECTPOOL_SIZE);
auto a = mono.loadAssembly("Ougge.dll"); auto a = mono.loadAssembly("Ougge.dll");
auto gameObjectClass = a->getClass("Ougge", "GameObject"); MonoClass* gameObjectClass = a->getClass("Ougge", "GameObject");
for(int i = 0; i < GAMEOBJECTPOOL_SIZE; i++){ MonoObject* exampleObjectManaged = mono_object_new(mono.getDomain(), gameObjectClass);
Mono::Object gameObjectManaged = mono_object_new(mono.getDomain(), gameObjectClass); u64 obj_id = 0;
p.emplace(GameObject(gameObjectManaged, nullptr)); auto pair = p.emplace(GameObject(exampleObjectManaged, nullptr));
GameObject& o = p.get(0); mono_runtime_object_init(exampleObjectManaged);
if(i+1 % 8192 == 0) auto exampleObjectInit = Mono::Method<void(u64, u32)>(gameObjectClass, "Init");
std::cout<<'['<<i<<"] "<<o.getTransform()<<std::endl; exampleObjectInit(exampleObjectManaged, obj_id++, pair.first);
} auto exampleObjectUpdate = Mono::Method<void(f64)>(gameObjectClass, "UpdateComponents");
return 0;
// mono_runtime_object_init(scriptInstance); updateCallbacks.push_back([exampleObjectManaged, exampleObjectUpdate](f64 deltaTime) -> void {
// auto scriptUpdate = Mono::Method<void(f64)>(c, "Update"); exampleObjectUpdate(exampleObjectManaged, deltaTime);
// updateCallbacks.push_back([scriptInstance, scriptUpdate](f64 deltaTime) -> void { });
// scriptUpdate(scriptInstance, deltaTime);
// }); auto tryCreateComponent = Mono::Method<Mono::Bool(Mono::String)>(gameObjectClass, "TryCreateComponent");
Mono::String componentNameManaged = mono_string_new(mono.getDomain(), "ExampleComponent");
Mono::ObjectHandle componentNameObjectHandle((MonoObject*)(void*)componentNameManaged);
Mono::Bool created = tryCreateComponent(exampleObjectManaged, componentNameManaged);
if(!created.wide_bool)
throw UsefulException("couldn't create ExampleComponent");
GUI::MainWindow w; GUI::MainWindow w;
w.open("ougge", update); w.open("ougge", update);