Compare commits
2 Commits
ec7a8de0cf
...
3df4361779
| Author | SHA1 | Date | |
|---|---|---|---|
| 3df4361779 | |||
| bff2182ff0 |
3
.vscode/c_cpp_properties.json
vendored
3
.vscode/c_cpp_properties.json
vendored
@ -11,7 +11,8 @@
|
|||||||
"dependencies/include/SDL2",
|
"dependencies/include/SDL2",
|
||||||
"dependencies/imgui",
|
"dependencies/imgui",
|
||||||
"${default}"
|
"${default}"
|
||||||
]
|
],
|
||||||
|
"cppStandard": "c++20"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"version": 4
|
"version": 4
|
||||||
|
|||||||
0
dependencies/compile_resources.sh
vendored
Normal file → Executable file
0
dependencies/compile_resources.sh
vendored
Normal file → Executable file
0
dependencies/imgui.config
vendored
Normal file → Executable file
0
dependencies/imgui.config
vendored
Normal file → Executable file
0
dependencies/imgui.project.config
vendored
Normal file → Executable file
0
dependencies/imgui.project.config
vendored
Normal file → Executable file
0
dependencies/precompiled.config
vendored
Normal file → Executable file
0
dependencies/precompiled.config
vendored
Normal file → Executable file
0
dependencies/resources.config
vendored
Normal file → Executable file
0
dependencies/resources.config
vendored
Normal file → Executable file
9
dependencies/src-csharp.config
vendored
Executable file
9
dependencies/src-csharp.config
vendored
Executable file
@ -0,0 +1,9 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
DEP_WORKING_DIR='src-csharp'
|
||||||
|
if [[ "$TASK" = *_dbg ]]; then
|
||||||
|
DEP_BUILD_COMMAND='dotnet build src-csharp.sln -o bin -c Debug'
|
||||||
|
else
|
||||||
|
DEP_BUILD_COMMAND='dotnet build src-csharp.sln -o bin -c Release'
|
||||||
|
fi
|
||||||
|
DEP_CLEAN_COMMAND='rm -rf bin obj'
|
||||||
|
DEP_OTHER_OUT_FILES='bin/Ougge.dll'
|
||||||
4
project.config
Normal file → Executable file
4
project.config
Normal file → Executable file
@ -6,7 +6,7 @@ PROJECT="ougge"
|
|||||||
CMP_C="gcc"
|
CMP_C="gcc"
|
||||||
CMP_CPP="g++"
|
CMP_CPP="g++"
|
||||||
STD_C="c11"
|
STD_C="c11"
|
||||||
STD_CPP="c++17"
|
STD_CPP="c++20"
|
||||||
WARN_C="-Wall -Wno-discarded-qualifiers -Wextra -Wno-unused-parameter"
|
WARN_C="-Wall -Wno-discarded-qualifiers -Wextra -Wno-unused-parameter"
|
||||||
WARN_CPP="-Wall -Wextra -Wno-unused-parameter"
|
WARN_CPP="-Wall -Wextra -Wno-unused-parameter"
|
||||||
SRC_C="$(find src -name '*.c')"
|
SRC_C="$(find src -name '*.c')"
|
||||||
@ -16,7 +16,7 @@ SRC_CPP="$(find src -name '*.cpp')"
|
|||||||
# See cbuild/example_dependency_configs
|
# See cbuild/example_dependency_configs
|
||||||
DEPENDENCY_CONFIGS_DIR='dependencies'
|
DEPENDENCY_CONFIGS_DIR='dependencies'
|
||||||
# List of dependency config files in DEPENDENCY_CONFIGS_DIR separated by space.
|
# List of dependency config files in DEPENDENCY_CONFIGS_DIR separated by space.
|
||||||
ENABLED_DEPENDENCIES='precompiled resources imgui'
|
ENABLED_DEPENDENCIES='precompiled resources imgui src-csharp'
|
||||||
|
|
||||||
# OBJDIR structure:
|
# OBJDIR structure:
|
||||||
# ├── objects/ - Compiled object files. Cleans on each call of build task
|
# ├── objects/ - Compiled object files. Cleans on each call of build task
|
||||||
|
|||||||
24
src-csharp/GameObject.cs
Normal file
24
src-csharp/GameObject.cs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
using System.Management.Instrumentation;
|
||||||
|
using System.Numerics;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace Ougge;
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct Transform
|
||||||
|
{
|
||||||
|
Vector2 scale;
|
||||||
|
Vector2 position;
|
||||||
|
float rotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Component
|
||||||
|
{
|
||||||
|
GameObject owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GameObject
|
||||||
|
{
|
||||||
|
Transform transform { get; }
|
||||||
|
GameObject? parent;
|
||||||
|
}
|
||||||
@ -1,5 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Data;
|
|
||||||
|
|
||||||
namespace Ougge;
|
namespace Ougge;
|
||||||
|
|
||||||
|
|||||||
29
src/Game/GameObject.cpp
Normal file
29
src/Game/GameObject.cpp
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#include "GameObject.hpp"
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& s, Transform& t){
|
||||||
|
s<<"{ position: {x: "<<t.position.x<<", y: "<<t.position.y;
|
||||||
|
s<<"}, rotation: "<<t.rotation;
|
||||||
|
s<<", scale {x: "<<t.scale.x<<", y: "<<t.scale.y<<"} }";
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
GameObject::GameObject(Mono::Object managed_obj, GameObject *parent)
|
||||||
|
: object_handle(managed_obj), parent(parent)
|
||||||
|
{}
|
||||||
|
|
||||||
|
GameObject &GameObject::operator=(GameObject &&o){
|
||||||
|
transform = o.transform;
|
||||||
|
components = std::move(o.components);
|
||||||
|
object_handle = std::move(o.object_handle);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GameObject::tryGetComponent(const std::u16string &name, Component **out_component)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GameObject::tryAddComponent(const std::u16string &name, Component &&component)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
@ -1,15 +1,41 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <iostream>
|
||||||
#include "../math.hpp"
|
#include "../math.hpp"
|
||||||
#include <set>
|
#include "../UsefulException.hpp"
|
||||||
|
#include "../Mono/Mono.hpp"
|
||||||
|
|
||||||
class GameObject {
|
class GameObject;
|
||||||
|
|
||||||
|
class Component {
|
||||||
|
Mono::ObjectHandle object_handle;
|
||||||
|
GameObject* owner;
|
||||||
public:
|
public:
|
||||||
Vec2 scale = { 1, 1 };
|
inline Component(Mono::Object managed_obj, GameObject* owner)
|
||||||
Vec2 position;
|
: object_handle(managed_obj), owner(owner) {}
|
||||||
angle_t rotation;
|
|
||||||
|
|
||||||
private:
|
|
||||||
// std::set<Component> components;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Transform {
|
||||||
|
Vec2 scale = { 1, 1 };
|
||||||
|
Vec2 position = { 0, 0 };
|
||||||
|
angle_t rotation = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& s, Transform& t);
|
||||||
|
|
||||||
|
|
||||||
|
class GameObject {
|
||||||
|
Transform transform;
|
||||||
|
std::map<std::u16string, Component> components;
|
||||||
|
Mono::ObjectHandle object_handle;
|
||||||
|
GameObject* parent;
|
||||||
|
public:
|
||||||
|
GameObject(Mono::Object managed_obj, GameObject* parent);
|
||||||
|
|
||||||
|
GameObject& operator=(GameObject&& o);
|
||||||
|
|
||||||
|
inline Transform& getTransform(){ return transform; }
|
||||||
|
bool tryGetComponent(const std::u16string& name, Component** out_component);
|
||||||
|
bool tryAddComponent(const std::u16string& name, Component&& component);
|
||||||
|
};
|
||||||
|
|||||||
127
src/Game/GameObjectPool.cpp
Normal file
127
src/Game/GameObjectPool.cpp
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
#include "GameObjectPool.hpp"
|
||||||
|
#include <bit>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
GameObjectPool::GameObjectPool(u32 size)
|
||||||
|
{
|
||||||
|
useful_assert(size % 64 == 0, "size of GameObjectPool must be a multiple of 64");
|
||||||
|
this->size = size;
|
||||||
|
first_unused_index = 0;
|
||||||
|
buffer = new char[size*sizeof(GameObject)];
|
||||||
|
used_indices = new u64[size/64];
|
||||||
|
std::memset(buffer, 0, size*sizeof(GameObject));
|
||||||
|
std::memset(used_indices, 0, size/8);
|
||||||
|
}
|
||||||
|
|
||||||
|
GameObjectPool::~GameObjectPool()
|
||||||
|
{
|
||||||
|
// int i = 0;
|
||||||
|
for(auto&& p : *this){
|
||||||
|
// std::cout<<"~GameObjectPool i="<<i++<<std::endl;
|
||||||
|
p.second.~GameObject();
|
||||||
|
}
|
||||||
|
delete (char*)buffer;
|
||||||
|
delete used_indices;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GameObjectPool::isIndexUsed(u32 index)
|
||||||
|
{
|
||||||
|
return ( used_indices[index/64] & (1<<(index%64)) ) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 GameObjectPool::getNearestUnusedIndex(u32 startIndex)
|
||||||
|
{
|
||||||
|
if(startIndex >= size)
|
||||||
|
return -1;
|
||||||
|
if(!isIndexUsed(startIndex))
|
||||||
|
return startIndex;
|
||||||
|
|
||||||
|
u32 i = startIndex/64;
|
||||||
|
// mark previous bits as used
|
||||||
|
u64 u = used_indices[i] | ( (1<<startIndex%64) -1 );
|
||||||
|
while(u == u64(-1)){
|
||||||
|
i++;
|
||||||
|
if(i == size/64)
|
||||||
|
return -1;
|
||||||
|
u = used_indices[i];
|
||||||
|
}
|
||||||
|
u32 bitpos = std::countr_one(u);
|
||||||
|
if(bitpos == 64)
|
||||||
|
return -1;
|
||||||
|
u32 index = i*64 + bitpos;
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 GameObjectPool::getNearestUsedIndex(u32 startIndex)
|
||||||
|
{
|
||||||
|
if(startIndex >= size)
|
||||||
|
return -1;
|
||||||
|
if(isIndexUsed(startIndex))
|
||||||
|
return startIndex;
|
||||||
|
|
||||||
|
u32 i = startIndex/64;
|
||||||
|
// mark previous bits as unused
|
||||||
|
u64 u = used_indices[i] & !( (1<<startIndex%64) -1 );
|
||||||
|
while(u == 0){
|
||||||
|
i++;
|
||||||
|
if(i == size/64)
|
||||||
|
return -1;
|
||||||
|
u = used_indices[i];
|
||||||
|
}
|
||||||
|
u32 bitpos = std::countr_zero(u);
|
||||||
|
if(bitpos == 64)
|
||||||
|
return -1;
|
||||||
|
u32 index = i*64 + bitpos;
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
GameObject& GameObjectPool::get(u32 index)
|
||||||
|
{
|
||||||
|
if(index >= size)
|
||||||
|
throw UsefulException(format("index %i is out of size %i", index, size));
|
||||||
|
if(!isIndexUsed(index))
|
||||||
|
throw UsefulException(format("there is no object at index %i", index));
|
||||||
|
return ((GameObject*)buffer)[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<u32, GameObject&> GameObjectPool::put_new(GameObject&& new_obj)
|
||||||
|
{
|
||||||
|
u32 i = first_unused_index;
|
||||||
|
if(i == (u32)-1)
|
||||||
|
throw UsefulException("can't put new GameObject to GameObjectPool because it's full");
|
||||||
|
GameObject& r = ( ((GameObject*)buffer)[i] = std::move(new_obj) );
|
||||||
|
used_indices[i] |= 1<<(i%64); // mark index bit as used
|
||||||
|
first_unused_index = getNearestUnusedIndex(i+1);
|
||||||
|
return std::pair<u32, GameObject&>(i, r);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameObjectPool::remove(u32 index)
|
||||||
|
{
|
||||||
|
if(index >= size)
|
||||||
|
throw UsefulException(format("index %i is out of size %i", index, size));
|
||||||
|
if(!isIndexUsed(index))
|
||||||
|
throw UsefulException(format("there is no object at index %i", index));
|
||||||
|
((GameObject*)buffer)[index].~GameObject();
|
||||||
|
used_indices[index/64] ^= ~(1<<(index%64)); // mark index bit as unused
|
||||||
|
if(index < first_unused_index)
|
||||||
|
first_unused_index = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
GameObjectPool::iterator::iterator(GameObjectPool* p, u32 index)
|
||||||
|
: p(p), index(index)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<u32, GameObject&> GameObjectPool::iterator::operator*()
|
||||||
|
{
|
||||||
|
if(index >= p->size)
|
||||||
|
throw UsefulException("can't get value of end() iterator");
|
||||||
|
GameObject& r = ((GameObject*)p->buffer)[index];
|
||||||
|
return std::pair<u32, GameObject&>(index, r);
|
||||||
|
}
|
||||||
|
|
||||||
|
GameObjectPool::iterator& GameObjectPool::iterator::operator++()
|
||||||
|
{
|
||||||
|
index = p->getNearestUsedIndex(index+1);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
37
src/Game/GameObjectPool.hpp
Normal file
37
src/Game/GameObjectPool.hpp
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#include "GameObject.hpp"
|
||||||
|
|
||||||
|
class GameObjectPool {
|
||||||
|
void* buffer;
|
||||||
|
u64* used_indices;
|
||||||
|
u32 size;
|
||||||
|
u32 first_unused_index;
|
||||||
|
|
||||||
|
bool isIndexUsed(u32 index);
|
||||||
|
u32 getNearestUnusedIndex(u32 startIndex);
|
||||||
|
u32 getNearestUsedIndex(u32 startIndex);
|
||||||
|
|
||||||
|
friend class iterator;
|
||||||
|
public:
|
||||||
|
|
||||||
|
///@param size must be a multiple of 64
|
||||||
|
GameObjectPool(u32 size);
|
||||||
|
~GameObjectPool();
|
||||||
|
GameObject& get(u32 index);
|
||||||
|
std::pair<u32, GameObject&> put_new(GameObject&& new_obj);
|
||||||
|
void remove(u32 index);
|
||||||
|
|
||||||
|
class iterator {
|
||||||
|
GameObjectPool* p;
|
||||||
|
u32 index = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
iterator(GameObjectPool* p, u32 index);
|
||||||
|
std::pair<u32, GameObject&> 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 iterator begin() { return iterator(this, 0); }
|
||||||
|
inline iterator end() { return iterator(this, -1); }
|
||||||
|
};
|
||||||
@ -124,4 +124,25 @@ public:
|
|||||||
std::shared_ptr<Assembly> loadAssembly(const std::string& name);
|
std::shared_ptr<Assembly> loadAssembly(const std::string& name);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ObjectHandle {
|
||||||
|
Object object;
|
||||||
|
u32 gc_handle;
|
||||||
|
public:
|
||||||
|
inline ObjectHandle(Object obj) : object(obj) { gc_handle = mono_gchandle_new(obj, false); }
|
||||||
|
inline ObjectHandle(const ObjectHandle& o) = delete;
|
||||||
|
inline ObjectHandle(ObjectHandle&& o) {
|
||||||
|
object = o.object;
|
||||||
|
gc_handle = o.gc_handle;
|
||||||
|
o.gc_handle = 0;
|
||||||
|
};
|
||||||
|
inline ObjectHandle& operator=(ObjectHandle&& o) {
|
||||||
|
object = o.object;
|
||||||
|
gc_handle = o.gc_handle;
|
||||||
|
o.gc_handle = 0;
|
||||||
|
return *this;
|
||||||
|
};
|
||||||
|
inline ~ObjectHandle() { if(gc_handle) mono_gchandle_free(gc_handle); }
|
||||||
|
inline Object getObject() { return object; }
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,4 +18,4 @@ public:
|
|||||||
virtual char const* what() const noexcept;
|
virtual char const* what() const noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define useful_assert(EXPR, ERRMSG) if(!EXPR) throw UsefulException(ERRMSG);
|
#define useful_assert(EXPR, ERRMSG) if(!(EXPR)) throw UsefulException(ERRMSG);
|
||||||
|
|||||||
27
src/main.cpp
27
src/main.cpp
@ -1,11 +1,15 @@
|
|||||||
#define SDL_MAIN_HANDLED
|
#define SDL_MAIN_HANDLED
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
#include "GUI/MainWindow.hpp"
|
#include "GUI/MainWindow.hpp"
|
||||||
#include "Resources/Resources.hpp"
|
#include "Resources/Resources.hpp"
|
||||||
#include "Game/Scene.hpp"
|
#include "Game/Scene.hpp"
|
||||||
#include "format.hpp"
|
#include "format.hpp"
|
||||||
#include "UsefulException.hpp"
|
#include "UsefulException.hpp"
|
||||||
#include "Mono/Mono.hpp"
|
#include "Mono/Mono.hpp"
|
||||||
|
#include "Game/GameObjectPool.hpp"
|
||||||
|
#include <bitset>
|
||||||
|
#include <bit>
|
||||||
|
|
||||||
using namespace ougge;
|
using namespace ougge;
|
||||||
|
|
||||||
@ -24,15 +28,24 @@ int main(int argc, const char** argv){
|
|||||||
|
|
||||||
Mono::RuntimeJIT mono;
|
Mono::RuntimeJIT mono;
|
||||||
std::cout<<"initialized mono jit runtime"<<std::endl;
|
std::cout<<"initialized mono jit runtime"<<std::endl;
|
||||||
|
GameObjectPool p(64*512);
|
||||||
|
|
||||||
auto a = mono.loadAssembly("Ougge.dll");
|
auto a = mono.loadAssembly("Ougge.dll");
|
||||||
auto c = a->getClass("Ougge", "ExampleScript");
|
auto gameObjectClass = a->getClass("Ougge", "GameObject");
|
||||||
auto scriptInstance = mono_object_new(mono.getDomain(), c);
|
for(int i = 0; i < 32*1024; i++){
|
||||||
mono_runtime_object_init(scriptInstance);
|
Mono::Object gameObjectManaged = mono_object_new(mono.getDomain(), gameObjectClass);
|
||||||
auto scriptUpdate = Mono::Method<void(f64)>(c, "Update");
|
p.put_new(GameObject(gameObjectManaged, nullptr));
|
||||||
updateCallbacks.push_back([scriptInstance, scriptUpdate](f64 deltaTime) -> void {
|
GameObject& o = p.get(0);
|
||||||
scriptUpdate(scriptInstance, deltaTime);
|
std::cout<<'['<<i<<"] "<<o.getTransform()<<std::endl;
|
||||||
});
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
|
||||||
|
// mono_runtime_object_init(scriptInstance);
|
||||||
|
// auto scriptUpdate = Mono::Method<void(f64)>(c, "Update");
|
||||||
|
// updateCallbacks.push_back([scriptInstance, scriptUpdate](f64 deltaTime) -> void {
|
||||||
|
// scriptUpdate(scriptInstance, deltaTime);
|
||||||
|
// });
|
||||||
|
|
||||||
GUI::MainWindow w;
|
GUI::MainWindow w;
|
||||||
w.open("ougge", update);
|
w.open("ougge", update);
|
||||||
|
|||||||
0
tasks/get_mono_files_from.sh
Normal file → Executable file
0
tasks/get_mono_files_from.sh
Normal file → Executable file
Loading…
Reference in New Issue
Block a user