Compare commits
4 Commits
0852a0028f
...
51259e72fe
| Author | SHA1 | Date | |
|---|---|---|---|
| 51259e72fe | |||
| 5c247ce032 | |||
| 5d84e744ce | |||
| 0863408bc5 |
@ -26,15 +26,15 @@ public class GameObject
|
|||||||
public Transform Transform { get; }
|
public Transform Transform { get; }
|
||||||
public GameObject? Parent;
|
public GameObject? Parent;
|
||||||
|
|
||||||
public Dictionary<Type, Component> Components = new();
|
public Dictionary<Type, Component> Components;
|
||||||
|
|
||||||
private GameObject(ulong id, uint nativePoolIndex)
|
private GameObject(ulong id, uint nativePoolIndex)
|
||||||
{
|
{
|
||||||
_id = id;
|
_id = id;
|
||||||
_index = nativePoolIndex;
|
_index = nativePoolIndex;
|
||||||
// constructor doesn't work without writing to console
|
// Do not move this line or mono runtime will throw SEGFAULT.
|
||||||
// TODO: FIX THIS BULLSHIT
|
// Mono runtime can't set values in field declaration, but initializing everything in constructor is OK.
|
||||||
Console.WriteLine($"GameObject(id: {id}, nativePoolIndex: {nativePoolIndex})");
|
Components = new();
|
||||||
}
|
}
|
||||||
|
|
||||||
static public GameObject Create()
|
static public GameObject Create()
|
||||||
|
|||||||
@ -7,23 +7,23 @@ std::ostream& operator<<(std::ostream& s, Transform& t){
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
GameObject::GameObject(Mono::Object managed_obj, GameObject *parent)
|
GameObject::GameObject(Mono::Object managed_obj)
|
||||||
: object_handle(managed_obj), parent(parent)
|
: object_handle(managed_obj)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
GameObject::GameObject(GameObject &&o) :
|
GameObject::GameObject(GameObject &&o) :
|
||||||
transform(o.transform),
|
|
||||||
components(std::move(o.components)),
|
|
||||||
object_handle(std::move(o.object_handle)),
|
object_handle(std::move(o.object_handle)),
|
||||||
parent(o.parent)
|
parent(o.parent),
|
||||||
|
transform(o.transform),
|
||||||
|
components(std::move(o.components))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
GameObject &GameObject::operator=(GameObject &&o){
|
GameObject& GameObject::operator=(GameObject &&o){
|
||||||
transform = o.transform;
|
|
||||||
components = std::move(o.components);
|
|
||||||
object_handle = std::move(o.object_handle);
|
object_handle = std::move(o.object_handle);
|
||||||
parent = o.parent;
|
parent = o.parent;
|
||||||
|
transform = o.transform;
|
||||||
|
components = std::move(o.components);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -26,12 +26,17 @@ std::ostream& operator<<(std::ostream& s, Transform& t);
|
|||||||
|
|
||||||
|
|
||||||
class GameObject {
|
class GameObject {
|
||||||
Transform transform;
|
|
||||||
std::map<std::u16string, Component> components;
|
|
||||||
Mono::ObjectHandle object_handle;
|
Mono::ObjectHandle object_handle;
|
||||||
GameObject* parent;
|
GameObject* parent;
|
||||||
|
Transform transform;
|
||||||
|
std::map<std::u16string, Component> components;
|
||||||
public:
|
public:
|
||||||
GameObject(Mono::Object managed_obj, GameObject* parent);
|
/// @warning Do not use this to create objects.
|
||||||
|
/// This constructor creates null values for GameObject arrays
|
||||||
|
/// GameObject* array = new GameObject[10];
|
||||||
|
/// array[0] = GameObject(initialized_mono_object_ptr)
|
||||||
|
GameObject() = default;
|
||||||
|
GameObject(Mono::Object managed_obj);
|
||||||
GameObject(const GameObject& o) = delete;
|
GameObject(const GameObject& o) = delete;
|
||||||
GameObject(GameObject&& o);
|
GameObject(GameObject&& o);
|
||||||
|
|
||||||
|
|||||||
@ -7,7 +7,7 @@ GameObjectPool::GameObjectPool(u32 size)
|
|||||||
useful_assert(size % 64 == 0, "size of GameObjectPool must be a multiple of 64");
|
useful_assert(size % 64 == 0, "size of GameObjectPool must be a multiple of 64");
|
||||||
this->size = size;
|
this->size = size;
|
||||||
first_unused_index = 0;
|
first_unused_index = 0;
|
||||||
buffer = new char[size*sizeof(GameObject)];
|
buffer = new GameObject[size];
|
||||||
used_indices = new u64[size/64];
|
used_indices = new u64[size/64];
|
||||||
// std::memset(buffer, 0, size*sizeof(GameObject));
|
// std::memset(buffer, 0, size*sizeof(GameObject));
|
||||||
std::memset(used_indices, 0, size/8);
|
std::memset(used_indices, 0, size/8);
|
||||||
@ -15,13 +15,8 @@ GameObjectPool::GameObjectPool(u32 size)
|
|||||||
|
|
||||||
GameObjectPool::~GameObjectPool()
|
GameObjectPool::~GameObjectPool()
|
||||||
{
|
{
|
||||||
// int i = 0;
|
delete[] buffer;
|
||||||
for(auto&& p : *this){
|
delete[] used_indices;
|
||||||
// std::cout<<"~GameObjectPool i="<<i++<<std::endl;
|
|
||||||
p.second.~GameObject();
|
|
||||||
}
|
|
||||||
delete (char*)buffer;
|
|
||||||
delete used_indices;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GameObjectPool::isIndexUsed(u32 index)
|
bool GameObjectPool::isIndexUsed(u32 index)
|
||||||
@ -81,7 +76,7 @@ GameObject& GameObjectPool::get(u32 index)
|
|||||||
throw UsefulException(format("index %i is out of size %i", index, size));
|
throw UsefulException(format("index %i is out of size %i", index, size));
|
||||||
if(!isIndexUsed(index))
|
if(!isIndexUsed(index))
|
||||||
throw UsefulException(format("there is no object at index %i", index));
|
throw UsefulException(format("there is no object at index %i", index));
|
||||||
return ((GameObject*)buffer)[index];
|
return buffer[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<u32, GameObject&> GameObjectPool::emplace(GameObject&& new_obj)
|
std::pair<u32, GameObject&> GameObjectPool::emplace(GameObject&& new_obj)
|
||||||
@ -89,7 +84,9 @@ std::pair<u32, GameObject&> GameObjectPool::emplace(GameObject&& new_obj)
|
|||||||
u32 i = first_unused_index;
|
u32 i = first_unused_index;
|
||||||
if(i == u32(-1))
|
if(i == u32(-1))
|
||||||
throw UsefulException("can't put new GameObject to GameObjectPool because it's full");
|
throw UsefulException("can't put new GameObject to GameObjectPool because it's full");
|
||||||
GameObject& r = ( ((GameObject*)buffer)[i] = std::move(new_obj) );
|
|
||||||
|
buffer[i] = std::move(new_obj);
|
||||||
|
GameObject& r = buffer[i];
|
||||||
used_indices[i/64] |= u64(1)<<(i%64); // mark index bit as used
|
used_indices[i/64] |= u64(1)<<(i%64); // mark index bit as used
|
||||||
first_unused_index = getNearestUnusedIndex(i+1);
|
first_unused_index = getNearestUnusedIndex(i+1);
|
||||||
return std::pair<u32, GameObject&>(i, r);
|
return std::pair<u32, GameObject&>(i, r);
|
||||||
@ -101,27 +98,29 @@ void GameObjectPool::erase(u32 index)
|
|||||||
throw UsefulException(format("index %i is out of size %i", index, size));
|
throw UsefulException(format("index %i is out of size %i", index, size));
|
||||||
if(!isIndexUsed(index))
|
if(!isIndexUsed(index))
|
||||||
throw UsefulException(format("there is no object at index %i", index));
|
throw UsefulException(format("there is no object at index %i", index));
|
||||||
((GameObject*)buffer)[index].~GameObject();
|
|
||||||
|
buffer[index] = GameObject();
|
||||||
used_indices[index/64] &= ~(u64(1)<<(index%64)); // mark index bit as unused
|
used_indices[index/64] &= ~(u64(1)<<(index%64)); // mark index bit as unused
|
||||||
if(index < first_unused_index)
|
if(index < first_unused_index)
|
||||||
first_unused_index = index;
|
first_unused_index = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
GameObjectPool::iterator::iterator(GameObjectPool* p, u32 index)
|
GameObjectPool::iterator::iterator(GameObjectPool* pool, u32 index)
|
||||||
: p(p), index(index)
|
: pool(pool), index(index)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<u32, GameObject&> GameObjectPool::iterator::operator*()
|
std::pair<u32, GameObject&> GameObjectPool::iterator::operator*()
|
||||||
{
|
{
|
||||||
if(index >= p->size)
|
if(index >= pool->size)
|
||||||
throw UsefulException("can't get value of end() iterator");
|
throw UsefulException("can't get value of end() iterator");
|
||||||
GameObject& r = ((GameObject*)p->buffer)[index];
|
|
||||||
|
GameObject& r = pool->buffer[index];
|
||||||
return std::pair<u32, GameObject&>(index, r);
|
return std::pair<u32, GameObject&>(index, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
GameObjectPool::iterator& GameObjectPool::iterator::operator++()
|
GameObjectPool::iterator& GameObjectPool::iterator::operator++()
|
||||||
{
|
{
|
||||||
index = p->getNearestUsedIndex(index+1);
|
index = pool->getNearestUsedIndex(index+1);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -28,7 +28,7 @@ operation 'forward_list::iterate' took 2.0823 ms
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
class GameObjectPool {
|
class GameObjectPool {
|
||||||
void* buffer;
|
GameObject* buffer;
|
||||||
u64* used_indices;
|
u64* used_indices;
|
||||||
u32 size;
|
u32 size;
|
||||||
u32 first_unused_index;
|
u32 first_unused_index;
|
||||||
@ -45,17 +45,19 @@ public:
|
|||||||
std::pair<u32, GameObject&> emplace(GameObject&& new_obj);
|
std::pair<u32, GameObject&> emplace(GameObject&& new_obj);
|
||||||
void erase(u32 index);
|
void erase(u32 index);
|
||||||
|
|
||||||
|
#pragma region iterator class
|
||||||
class iterator {
|
class iterator {
|
||||||
GameObjectPool* p;
|
GameObjectPool* pool;
|
||||||
u32 index = 0;
|
u32 index = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
iterator(GameObjectPool* p, u32 index);
|
iterator(GameObjectPool* pool, u32 index);
|
||||||
std::pair<u32, GameObject&> operator*();
|
std::pair<u32, GameObject&> operator*();
|
||||||
iterator& operator++();
|
iterator& operator++();
|
||||||
inline bool operator!=(const iterator& o) const { return index != o.index; };
|
inline bool operator!=(const iterator& o) const { return index != o.index; };
|
||||||
inline bool operator==(const iterator& o) const { return index == o.index; };
|
inline bool operator==(const iterator& o) const { return index == o.index; };
|
||||||
};
|
};
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
inline iterator begin() { return iterator(this, 0); }
|
inline iterator begin() { return iterator(this, 0); }
|
||||||
inline iterator end() { return iterator(this, -1); }
|
inline iterator end() { return iterator(this, -1); }
|
||||||
|
|||||||
@ -24,6 +24,8 @@ typedef f64 Double;
|
|||||||
typedef union { mono_bool wide_bool; } Bool; //USAGE: Bool t = {true};
|
typedef union { mono_bool wide_bool; } Bool; //USAGE: Bool t = {true};
|
||||||
typedef char16_t Char;
|
typedef char16_t Char;
|
||||||
typedef MonoString* String;
|
typedef MonoString* String;
|
||||||
|
/// @warning MonoObject can be moved in memory by GC in any time and raw pointer will be invalid.
|
||||||
|
/// Use ObjectHandle where it is possible.
|
||||||
typedef MonoObject* Object;
|
typedef MonoObject* Object;
|
||||||
typedef void Void;
|
typedef void Void;
|
||||||
|
|
||||||
@ -133,25 +135,39 @@ public:
|
|||||||
std::shared_ptr<Assembly> loadAssembly(const std::string& name);
|
std::shared_ptr<Assembly> loadAssembly(const std::string& name);
|
||||||
};
|
};
|
||||||
|
|
||||||
class ObjectHandle {
|
/// @brief ObjectHandle can be used to store reliable reference to MonoObject.
|
||||||
Object object;
|
/// MonoObject can be moved in memory by GC in any time and raw pointer will be invalid.
|
||||||
|
struct ObjectHandle {
|
||||||
u32 gc_handle;
|
u32 gc_handle;
|
||||||
public:
|
|
||||||
inline ObjectHandle() : object(nullptr), gc_handle(0) {}
|
inline ObjectHandle() : gc_handle(0) {}
|
||||||
inline ObjectHandle(Object obj) : object(obj) { gc_handle = mono_gchandle_new(obj, false); }
|
|
||||||
|
inline ObjectHandle(Object obj) {
|
||||||
|
gc_handle = mono_gchandle_new(obj, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// implicitly create new ObjectHandle instead
|
||||||
inline ObjectHandle(const ObjectHandle& o) = delete;
|
inline ObjectHandle(const ObjectHandle& o) = delete;
|
||||||
inline ObjectHandle(ObjectHandle&& o)
|
|
||||||
: object(o.object), gc_handle(o.gc_handle)
|
inline ObjectHandle(ObjectHandle&& o) {
|
||||||
{ o.gc_handle = 0; };
|
gc_handle = o.gc_handle;
|
||||||
|
o.gc_handle = 0;
|
||||||
|
}
|
||||||
|
|
||||||
inline ObjectHandle& operator=(ObjectHandle&& o) {
|
inline ObjectHandle& operator=(ObjectHandle&& o) {
|
||||||
object = o.object;
|
|
||||||
gc_handle = o.gc_handle;
|
gc_handle = o.gc_handle;
|
||||||
o.gc_handle = 0;
|
o.gc_handle = 0;
|
||||||
return *this;
|
return *this;
|
||||||
};
|
}
|
||||||
inline ~ObjectHandle() { if(gc_handle) mono_gchandle_free(gc_handle); }
|
|
||||||
inline Object getObject() const { return object; }
|
inline ~ObjectHandle() {
|
||||||
inline u32 getGCHandle() const { return gc_handle; }
|
if(gc_handle)
|
||||||
|
mono_gchandle_free(gc_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Object getObject() const {
|
||||||
|
return mono_gchandle_get_target(gc_handle);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
15
src/main.cpp
15
src/main.cpp
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
using namespace ougge;
|
using namespace ougge;
|
||||||
|
|
||||||
#define GAMEOBJECTPOOL_SIZE 64*1024
|
#define GAMEOBJECTPOOL_SIZE 64
|
||||||
|
|
||||||
#define optime(N, LABEL, CODE) {\
|
#define optime(N, LABEL, CODE) {\
|
||||||
nsec_t b = getMonotonicTimeNsec();\
|
nsec_t b = getMonotonicTimeNsec();\
|
||||||
@ -43,21 +43,20 @@ int main(int argc, const char** argv){
|
|||||||
|
|
||||||
auto a = mono.loadAssembly("Ougge.dll");
|
auto a = mono.loadAssembly("Ougge.dll");
|
||||||
MonoClass* gameObjectClass = a->getClass("Ougge", "GameObject");
|
MonoClass* gameObjectClass = a->getClass("Ougge", "GameObject");
|
||||||
MonoObject* exampleObjectManaged = mono_object_new(mono.getDomain(), gameObjectClass);
|
|
||||||
u64 obj_id = 0;
|
u64 obj_id = 0;
|
||||||
auto pair = p.emplace(GameObject(exampleObjectManaged, nullptr));
|
auto pair = p.emplace(GameObject(mono_object_new(mono.getDomain(), gameObjectClass)));
|
||||||
|
Mono::ObjectHandle& exampleObjectHandle = pair.second.getObjectHandle();
|
||||||
auto gameObjectCtor = Mono::Method<void(u64, u32)>(gameObjectClass, ".ctor");
|
auto gameObjectCtor = Mono::Method<void(u64, u32)>(gameObjectClass, ".ctor");
|
||||||
gameObjectCtor(exampleObjectManaged, obj_id++, pair.first);
|
gameObjectCtor(exampleObjectHandle.getObject(), obj_id++, pair.first);
|
||||||
|
|
||||||
auto exampleObjectUpdate = Mono::Method<void(f64)>(gameObjectClass, "InvokeUpdate");
|
auto exampleObjectUpdate = Mono::Method<void(f64)>(gameObjectClass, "InvokeUpdate");
|
||||||
updateCallbacks.push_back([exampleObjectManaged, exampleObjectUpdate](f64 deltaTime) -> void {
|
updateCallbacks.push_back([&exampleObjectHandle, exampleObjectUpdate](f64 deltaTime) -> void {
|
||||||
exampleObjectUpdate(exampleObjectManaged, deltaTime);
|
exampleObjectUpdate(exampleObjectHandle.getObject(), deltaTime);
|
||||||
});
|
});
|
||||||
|
|
||||||
auto tryCreateComponent = Mono::Method<Mono::Bool(Mono::String)>(gameObjectClass, "TryCreateComponent_internal");
|
auto tryCreateComponent = Mono::Method<Mono::Bool(Mono::String)>(gameObjectClass, "TryCreateComponent_internal");
|
||||||
Mono::String componentNameManaged = mono_string_new(mono.getDomain(), "Ougge.ExampleComponent");
|
Mono::String componentNameManaged = mono_string_new(mono.getDomain(), "Ougge.ExampleComponent");
|
||||||
// Mono::ObjectHandle componentNameObjectHandle((MonoObject*)(void*)componentNameManaged);
|
Mono::Bool created = tryCreateComponent(exampleObjectHandle.getObject(), componentNameManaged);
|
||||||
Mono::Bool created = tryCreateComponent(exampleObjectManaged, componentNameManaged);
|
|
||||||
if(!created.wide_bool)
|
if(!created.wide_bool)
|
||||||
throw UsefulException("couldn't create ExampleComponent");
|
throw UsefulException("couldn't create ExampleComponent");
|
||||||
|
|
||||||
|
|||||||
@ -33,10 +33,10 @@ case "$OS" in
|
|||||||
mv -v "$l" "dependencies/precompiled/mono-libs/$soname_without_version"
|
mv -v "$l" "dependencies/precompiled/mono-libs/$soname_without_version"
|
||||||
done
|
done
|
||||||
|
|
||||||
myprint "${BLUE}stripping debug symbols from mono shared libraries"
|
# myprint "${BLUE}stripping debug symbols from mono shared libraries"
|
||||||
for l in $(find "dependencies/precompiled/mono-libs" -name '*.so') ; do
|
# for l in $(find "dependencies/precompiled/mono-libs" -name '*.so') ; do
|
||||||
strip -g "$l"
|
# strip -g "$l"
|
||||||
done
|
# done
|
||||||
|
|
||||||
# copy mono c# libraries
|
# copy mono c# libraries
|
||||||
managed_libraries="mscorlib.dll"
|
managed_libraries="mscorlib.dll"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user