Commit for 2020.09.28.7z

This commit is contained in:
mrq 2020-09-28 00:00:00 -05:00
parent a97418d88e
commit de44c37a44
27 changed files with 1254 additions and 381 deletions

View File

@ -110,3 +110,11 @@ clean-win64:
@-rm -f $(OBJS_WIN64_DLL)
@-rm -f $(OBJS_EXT_WIN64_DLL)
@-rm -f $(OBJS_WIN64)
clean-uf-win64:
@-rm $(EX_WIN64_DLL)
@-rm -f $(OBJS_WIN64_DLL)
clean-ext-win64:
@-rm $(EXT_EX_WIN64_DLL)
@-rm -f $(OBJS_EXT_WIN64_DLL)

View File

@ -6,13 +6,17 @@
#include <vector>
#include <typeindex>
namespace uf {
class UF_API Entity;
class UF_API Object;
}
namespace pod {
struct UF_API Behavior {
typedef std::type_index type_t;
typedef std::function<void()> function_t;
typedef std::function<void(uf::Object&)> function_t;
type_t type;
type_t type = std::type_index(typeid(pod::Behavior));
function_t initialize;
function_t tick;
function_t render;
@ -31,6 +35,15 @@ namespace uf {
void render();
void destroy();
bool hasBehavior( const pod::Behavior& );
template<typename T>
bool hasBehavior() {
for ( auto& behavior : this->m_behaviors ) {
if ( behavior.type == getType<T>() ) return true;
}
return false;
}
void addBehavior( const pod::Behavior& );
template<typename T>
@ -60,11 +73,4 @@ namespace uf {
}
#define UF_BEHAVIOR_ENTITY_HEADER( OBJ )\
class UF_API OBJ ## Behavior {\
public:\
void initialize();\
void tick();\
void render();\
void destroy();\
};
#include "macros.inl"

View File

@ -0,0 +1,45 @@
#pragma once
#define UF_BEHAVIOR_VIRTUAL 1
#define UF_BEHAVIOR_ENTITY_H( OBJ )\
class UF_API OBJ ## Behavior {\
public:\
static void attach( uf::Entity& );\
static void initialize( uf::Object& );\
static void tick( uf::Object& );\
static void render( uf::Object& );\
static void destroy( uf::Object& );\
};
#if UF_BEHAVIOR_VIRTUAL
#define UF_BEHAVIOR_VIRTUAL_H() \
virtual void initialize();\
virtual void destroy();\
virtual void tick();\
virtual void render();
#define UF_BEHAVIOR_ENTITY_CPP_VIRTUAL_DEFINITIONS( OBJ )\
void uf::OBJ::initialize(){ uf::Behaviors::initialize(); }\
void uf::OBJ::tick(){ uf::Behaviors::tick(); }\
void uf::OBJ::render(){ uf::Behaviors::render(); }\
void uf::OBJ::destroy(){ uf::Behaviors::destroy(); }
#else
#define UF_BEHAVIOR_VIRTUAL_H()
#define UF_BEHAVIOR_ENTITY_CPP_VIRTUAL_DEFINITIONS( OBJ )
#endif
#define UF_BEHAVIOR_ENTITY_CPP_BEGIN( OBJ )\
uf::OBJ::OBJ() { \
uf::OBJ ## Behavior::attach( *this );\
}\
UF_BEHAVIOR_ENTITY_CPP_VIRTUAL_DEFINITIONS( OBJ )\
void uf::OBJ ## Behavior::attach( uf::Entity& self ) {\
self.addBehavior(pod::Behavior{\
.type = uf::Behaviors::getType<uf::OBJ ## Behavior>(),\
.initialize = uf::OBJ ## Behavior::initialize,\
.tick = uf::OBJ ## Behavior::tick,\
.render = uf::OBJ ## Behavior::render,\
.destroy = uf::OBJ ## Behavior::destroy,\
});\
}
#define UF_BEHAVIOR_ENTITY_CPP_END( OBJ )\

View File

@ -0,0 +1,5 @@
#pragma once
namespace uf {
UF_BEHAVIOR_ENTITY_H(Entity)
}

View File

@ -9,16 +9,8 @@
#include <uf/utils/mempool/mempool.h>
namespace uf {
/*
class UF_API EntityBehavior {
public:
void initialize();
void destroy();
void tick();
void render();
};
*/
class UF_API Entity : public uf::Behaviors {
friend class EntityBehavior;
public:
typedef std::vector<uf::Entity*> container_t;
protected:
@ -30,9 +22,9 @@ namespace uf {
std::size_t m_uid = 0;
std::string m_name = "Entity";
public:
static uf::MemoryPool memoryPool;
Entity( bool = false );
virtual ~Entity();
// identifiers
const std::string& getName() const;
@ -65,11 +57,10 @@ namespace uf {
static uf::Entity* globalFindByUid( size_t id );
static uf::Entity* globalFindByName( const std::string& name );
// behavior
virtual void initialize();
virtual void destroy();
virtual void tick();
virtual void render();
Entity();
UF_BEHAVIOR_VIRTUAL_H()
};
}
#include "entity.inl"
#include "entity.inl"
#include "behavior.h"

View File

@ -7,37 +7,58 @@
#include <typeindex>
#include <functional>
#define NAMESPACE_CONCAT
#define UF_OBJECT_REGISTER_CPP( OBJ ) \
namespace {\
static uf::StaticInitialization REGISTER_UF_ ## OBJ( []{\
uf::instantiator::add<uf::OBJ>( #OBJ );\
});\
}
#define EXT_OBJECT_REGISTER_CPP( OBJ ) \
namespace {\
static uf::StaticInitialization REGISTER_EXT_ ## OBJ( []{\
uf::instantiator::add<ext::OBJ>( #OBJ );\
});\
namespace pod {
struct UF_API Instantiator {
typedef std::function<uf::Entity*()> function_t;
typedef std::vector<std::string> behaviors_t;
function_t function;
behaviors_t behaviors;
};
template<typename C>
struct UF_API NamedTypes {
typedef std::type_index type_t;
typedef std::unordered_map<type_t, std::string> container_t;
typedef std::unordered_map<std::string, C> map_t;
container_t names;
map_t map;
type_t getType( const std::string& name );
template<typename T> type_t getType();
template<typename T> std::string getName();
bool has( const std::string& name );
template<typename T> bool has();
template<typename T> void add( const std::string& name, const C& c );
C& get( const std::string& name );
template<typename T> C& get();
};
}
namespace uf {
namespace instantiator {
typedef std::function<uf::Entity*()> function_t;
extern UF_API std::unordered_map<std::type_index, std::string>* names;
extern UF_API std::unordered_map<std::string, function_t>* map;
extern UF_API pod::NamedTypes<pod::Instantiator>* objects;
extern UF_API pod::NamedTypes<pod::Behavior>* behaviors;
uf::Entity* UF_API alloc( size_t );
void UF_API free( uf::Entity* );
uf::Entity* UF_API instantiate( const std::string& );
template<typename T> void add( const std::string& name );
template<typename T> T* alloc();
template<typename T> T& instantiate( size_t size );
void UF_API free( uf::Entity* );
template<typename T> void registerObject( const std::string& name );
template<typename T> void registerBehavior( const std::string& name );
template<typename T> void registerBinding( const std::string& name );
void UF_API registerBinding( const std::string& object, const std::string& behavior );
uf::Entity& UF_API instantiate( const std::string& );
template<typename T> T& instantiate();
template<typename T> T* _instantiate();
void UF_API bind( const std::string&, uf::Entity& );
template<typename T> void bind( uf::Entity& );
};
}
#include "instantiator.inl"
#include "instantiator.inl"
#include "macros.inl"

View File

@ -1,32 +1,174 @@
template<typename C>
pod::NamedTypes<C>::type_t pod::NamedTypes<C>::getType( const std::string& name ) {
for ( auto pair : names ) if ( pair.second == name ) return pair.first;
return getType<void>();
}
template<typename C>
template<typename T> pod::NamedTypes<C>::type_t pod::NamedTypes<C>::getType() {
return std::type_index(typeid(T));
}
template<typename C>
template<typename T> std::string pod::NamedTypes<C>::getName() {
return names[getType<T>()];
}
template<typename C>
bool pod::NamedTypes<C>::has( const std::string& name ) {
return names.count(getType(name)) > 0;
}template<typename C>
template<typename T> bool pod::NamedTypes<C>::has() {
return names.count(getType<T>()) > 0;
}
template<typename C>
template<typename T> void pod::NamedTypes<C>::add( const std::string& name, const C& c ) {
names[getType<T>()] = name;
map[name] = c;
}
template<typename C>
C& pod::NamedTypes<C>::get( const std::string& name ) {
return map[name];
}
template<typename C>
template<typename T>
C& pod::NamedTypes<C>::get() {
return map[getName<T>()];
}
template<typename T>
T* uf::instantiator::alloc() {
return (T*) alloc( sizeof(T) );
// return new T;
}
template<typename T> void uf::instantiator::registerObject( const std::string& name ) {
if ( !objects ) objects = new pod::NamedTypes<pod::Instantiator>;
auto& container = *uf::instantiator::objects;
container.add<T>(name, {
.function = _instantiate<T>
});
std::cout << "Registered instantiation for " << name << std::endl;
}
template<typename T> void uf::instantiator::registerBehavior( const std::string& name ) {
if ( !behaviors ) behaviors = new pod::NamedTypes<pod::Behavior>;
auto& container = *uf::instantiator::behaviors;
container.add<T>(name, pod::Behavior{
.type = uf::Behaviors::getType<T>(),
.initialize = T::initialize,
.tick = T::tick,
.render = T::render,
.destroy = T::destroy,
});
std::cout << "Registered behavior for " << name << std::endl;
}
template<typename T> void uf::instantiator::registerBinding( const std::string& name ) {
if ( !objects ) objects = new pod::NamedTypes<pod::Instantiator>;
auto& container = *uf::instantiator::objects;
auto& instantiator = container.get<T>();
instantiator.behaviors.emplace_back(name);
std::cout << "Registered binding for " << name << std::endl;
}
template<typename T>
T& uf::instantiator::instantiate() {
T* entity = alloc<T>();
::new (entity) T();
T& object = *entity;
uf::instantiator::bind<T>( object );
return object;
}
template<typename T>
void uf::instantiator::add( const std::string& name ) {
if ( !names ) names = new std::unordered_map<std::type_index, std::string>;
if ( !map ) map = new std::unordered_map<std::string, function_t>;
T* uf::instantiator::_instantiate() {
return &instantiate<T>();
}
template<typename T>
void uf::instantiator::bind( uf::Entity& entity ) {
auto& instantiator = uf::instantiator::objects->get<T>();
for ( auto& name : instantiator.behaviors ) {
auto& behavior = uf::instantiator::behaviors->get( name );
entity.addBehavior(behavior);
}
}
/*
template<typename T>
T* uf::instantiator::alloc() {
return (T*) alloc( sizeof(T) );
}
template<typename T>
std::string uf::instantiator::getName() {
auto type = getType<T>();
auto& names = *uf::instantiator::names;
auto& map = *uf::instantiator::map;
return names[type];
}
names[std::type_index(typeid(T))] = name;
map[name] = _instantiate<T>;
template<typename T>
uf::instantiator::type_t uf::instantiator::getType() {
return std::type_index(typeid(T));
}
template<typename T>
T& uf::instantiator::instantiate() {
T* entity = alloc<T>();
::new (entity) T();
T& object = *entity;
uf::instantiator::bind<T>( object );
return object;
}
template<typename T>
T* uf::instantiator::_instantiate() {
return &instantiate<T>();
}
template<typename T>
void uf::instantiator::add( const std::string& name ) {
if ( !map ) map = new std::unordered_map<std::string, pod::Instantiator>;
if ( !names ) names = new std::unordered_map<uf::instantiator::type_t, std::string>;
auto& map = *uf::instantiator::map;
auto& names = *uf::instantiator::names;
auto type = getType<T>();
names[type] = name;
map[name] = {
.function = _instantiate<T>
};
std::cout << "Registered instantiation for " << name << std::endl;
}
template<typename T>
T& uf::instantiator::instantiate( size_t size ) {
T* entity = alloc<T>();
::new (entity) T();
return *entity;
void uf::instantiator::add( const pod::Behavior& behavior ) {
if ( !registered<T>() ) return;
auto type = getType<T>();
auto& map = *uf::instantiator::map;
auto& instantiator = map[getName<T>()];
instantiator.behaviors.emplace_back(behavior);
}
template<typename T>
T& uf::instantiator::instantiate() {
return instantiate<T>( sizeof(T) );
template<typename T, typename U>
void uf::instantiator::add() {
return uf::instantiator::add<T>(pod::Behavior{
.type = uf::Behaviors::getType<U>(),
.initialize = U::initialize,
.tick = U::tick,
.render = U::render,
.destroy = U::destroy,
});
}
template<typename T>
T* uf::instantiator::_instantiate() {
return &instantiate<T>( sizeof(T) );
}
bool uf::instantiator::registered() {
return uf::instantiator::map->count(getName<T>()) > 0;
}
template<typename T>
void uf::instantiator::bind( T& object ) {
if ( !registered<T>() ) return;
auto& map = *uf::instantiator::map;
auto& instantiator = map[getName<T>()];
for ( auto& behavior : instantiator.behaviors ) {
object.addBehavior(behavior);
}
}
*/

View File

@ -0,0 +1,61 @@
#pragma once
#define NAMESPACE_CONCAT
#define UF_OBJECT_REGISTER_CPP( OBJ ) \
namespace {\
static uf::StaticInitialization REGISTER_UF_ ## OBJ( []{\
uf::instantiator::registerObject<uf::OBJ>( #OBJ );\
});\
}
#define EXT_OBJECT_REGISTER_CPP( OBJ ) \
namespace {\
static uf::StaticInitialization REGISTER_EXT_ ## OBJ( []{\
uf::instantiator::registerObject<ext::OBJ>( #OBJ );\
});\
}
#define UF_BEHAVIOR_REGISTER_CPP( BEHAVIOR ) \
namespace {\
static uf::StaticInitialization REGISTER_UF_ ## BEHAVIOR( []{\
uf::instantiator::registerBehavior<uf::BEHAVIOR>( #BEHAVIOR );\
});\
}
#define EXT_BEHAVIOR_REGISTER_CPP( BEHAVIOR ) \
namespace {\
static uf::StaticInitialization REGISTER_EXT_ ## BEHAVIOR( []{\
uf::instantiator::registerBehavior<ext::BEHAVIOR>( #BEHAVIOR );\
});\
}
#define UF_OBJECT_REGISTER_BEGIN( OBJ )\
namespace {\
static uf::StaticInitialization REGISTER_EXT_ ## OBJ( []{\
std::string name = #OBJ;\
uf::instantiator::registerObject<uf::OBJ>( name );
#define UF_OBJECT_BIND_BEHAVIOR( BEHAVIOR )\
uf::instantiator::registerBinding( name, #BEHAVIOR );
#define UF_OBJECT_REGISTER_BEHAVIOR( BEHAVIOR )\
uf::instantiator::registerBehavior<uf::BEHAVIOR>( #BEHAVIOR );\
UF_OBJECT_BIND_BEHAVIOR( BEHAVIOR )
#define UF_OBJECT_REGISTER_END()\
});\
}
#define EXT_OBJECT_REGISTER_BEGIN( OBJ )\
namespace {\
static uf::StaticInitialization REGISTER_EXT_ ## OBJ( []{\
std::string name = #OBJ;\
uf::instantiator::registerObject<ext::OBJ>( name );
#define EXT_OBJECT_BIND_BEHAVIOR( BEHAVIOR )\
uf::instantiator::registerBinding( name, #BEHAVIOR );
#define EXT_OBJECT_REGISTER_BEHAVIOR( BEHAVIOR )\
uf::instantiator::registerBehavior<ext::BEHAVIOR>( #BEHAVIOR );\
EXT_OBJECT_BIND_BEHAVIOR( BEHAVIOR )
#define EXT_OBJECT_REGISTER_END()\
});\
}

View File

@ -0,0 +1,5 @@
#pragma once
namespace uf {
UF_BEHAVIOR_ENTITY_H(Object)
}

View File

@ -3,16 +3,15 @@
#include <uf/engine/entity/entity.h>
#include <uf/engine/instantiator/instantiator.h>
#include <uf/utils/hook/hook.h>
#include <uf/utils/time/time.h>
#include <typeindex>
#include <functional>
namespace uf {
class UF_API Object : public uf::Entity {
public:
virtual void initialize();
virtual void destroy();
virtual void tick();
virtual void render();
static uf::Timer<long long> timer;
bool reload( bool = false );
bool load( const std::string&, bool = false );
@ -23,5 +22,15 @@ namespace uf {
void queueHook( const std::string&, const std::string& = "", double = 0 );
std::vector<std::string> callHook( const std::string&, const std::string& = "" );
std::size_t addHook( const std::string&, const uf::HookHandler::Readable::function_t& );
Object();
#if UF_BEHAVIOR_VIRTUAL
virtual void initialize();
virtual void tick();
virtual void render();
virtual void destroy();
#endif
};
}
}
#include "behavior.h"

View File

@ -0,0 +1,5 @@
#pragma once
namespace uf {
UF_BEHAVIOR_ENTITY_H(Scene)
}

View File

@ -4,14 +4,7 @@
namespace uf {
class UF_API Scene : public uf::Object {
protected:
// void* m_graphics;
public:
virtual void initialize();
virtual void tick();
virtual void render();
virtual void destroy();
virtual uf::Entity& getController();
virtual const uf::Entity& getController() const;
@ -21,6 +14,14 @@ namespace uf {
template<typename T> const T& getController() const {
return *((const T*) &this->getController());
}
Scene();
#if UF_BEHAVIOR_VIRTUAL
virtual void initialize();
virtual void tick();
virtual void render();
virtual void destroy();
#endif
};
namespace scene {
@ -34,4 +35,6 @@ namespace uf {
void UF_API render();
void UF_API destroy();
}
}
}
#include "behavior.h"

View File

@ -1,27 +1,36 @@
#include <uf/engine/behavior/behavior.h>
#include <uf/engine/object/object.h>
bool uf::Behaviors::hasBehavior( const pod::Behavior& target ) {
for ( auto& behavior : this->m_behaviors ) {
if ( behavior.type == target.type ) return true;
}
return false;
}
void uf::Behaviors::addBehavior( const pod::Behavior& behavior ) {
std::cout << "[!!!] behavior attached" << std::endl;
if ( hasBehavior( behavior ) ) return;
this->m_behaviors.emplace_back(behavior);
}
void uf::Behaviors::initialize() {
for ( auto it = this->m_behaviors.rbegin(); it != this->m_behaviors.rend(); ++it ) {
std::cout << "[!!!] behavior called: initialize" << std::endl;
it->initialize();
}
uf::Object& self = *((uf::Object*) this);
for ( auto& behavior : this->m_behaviors ) behavior.initialize(self);
}
void uf::Behaviors::tick() {
for ( auto it = this->m_behaviors.rbegin(); it != this->m_behaviors.rend(); ++it )
it->tick();
uf::Object& self = *((uf::Object*) this);
for ( auto it = this->m_behaviors.rbegin(); it != this->m_behaviors.rend(); ++it ) {
it->tick(self);
}
}
void uf::Behaviors::render() {
for ( auto it = this->m_behaviors.rbegin(); it != this->m_behaviors.rend(); ++it )
it->render();
uf::Object& self = *((uf::Object*) this);
for ( auto it = this->m_behaviors.rbegin(); it != this->m_behaviors.rend(); ++it ) {
it->render(self);
}
}
void uf::Behaviors::destroy() {
uf::Object& self = *((uf::Object*) this);
for ( auto it = this->m_behaviors.rbegin(); it != this->m_behaviors.rend(); ++it ) {
std::cout << "[!!!] behavior called: destroy" << std::endl;
it->destroy();
it->destroy(self);
}
}

View File

@ -0,0 +1,35 @@
#include <uf/engine/entity/entity.h>
UF_BEHAVIOR_ENTITY_CPP_BEGIN(Entity)
#define this ((uf::Entity*) &self)
void uf::EntityBehavior::initialize( uf::Object& self ) {
if ( this->m_uid == 0 )
this->m_uid = ++uf::Entity::uids;
}
void uf::EntityBehavior::tick( uf::Object& self ) {
for ( uf::Entity* kv : this->m_children ) {
if ( !kv ) continue;
if ( kv->getUid() == 0 ) continue;
kv->tick();
}
}
void uf::EntityBehavior::render( uf::Object& self ) {
for ( uf::Entity* kv : this->m_children ) {
if ( !kv ) continue;
if ( kv->getUid() == 0 ) continue;
kv->render();
}
}
void uf::EntityBehavior::destroy( uf::Object& self ) {
for ( uf::Entity* kv : this->m_children ) {
if ( !kv ) continue;
if ( kv->getUid() == 0 ) continue;
kv->destroy();
kv->setParent();
delete kv;
}
this->m_children.clear();
this->m_uid = 0;
}
#undef this
UF_BEHAVIOR_ENTITY_CPP_END(Entity)

View File

@ -5,9 +5,6 @@
uf::Entity uf::Entity::null;
std::size_t uf::Entity::uids = 0;
uf::MemoryPool uf::Entity::memoryPool;
uf::Entity::Entity( bool shouldInitialize ){
if ( shouldInitialize ) this->initialize();
}
uf::Entity::~Entity(){
this->destroy();
}
@ -51,7 +48,7 @@ std::size_t uf::Entity::getUid() const {
}
void* uf::Entity::operator new(size_t size, const std::string& type ) {
return type != "" && size == sizeof(uf::Entity) ? uf::instantiator::instantiate( type ) : uf::instantiator::alloc( size );
return type != "" && size == sizeof(uf::Entity) ? &uf::instantiator::instantiate( type ) : uf::instantiator::alloc( size );
}
void uf::Entity::operator delete( void* pointer ) {
uf::instantiator::free( (uf::Entity*) pointer );
@ -119,73 +116,4 @@ uf::Entity* uf::Entity::globalFindByName( const std::string& name ) {
if ( entity->getName() == name ) return entity;
}
return NULL;
}
void uf::Entity::initialize( ){
if ( this->m_uid == 0 ) this->m_uid = ++uf::Entity::uids;
uf::Behaviors::initialize();
}
void uf::Entity::tick( ){
uf::Behaviors::tick();
for ( uf::Entity* kv : this->m_children ) {
if ( !kv ) continue;
if ( kv->getUid() == 0 ) continue;
kv->tick();
}
}
void uf::Entity::render( ){
uf::Behaviors::render();
for ( uf::Entity* kv : this->m_children ) {
if ( !kv ) continue;
if ( kv->getUid() == 0 ) continue;
kv->render();
}
}
void uf::Entity::destroy( ){
uf::Behaviors::destroy();
for ( uf::Entity* kv : this->m_children ) {
if ( !kv ) continue;
if ( kv->getUid() == 0 ) continue;
kv->destroy();
kv->setParent();
delete kv;
}
this->m_children.clear();
this->m_uid = 0;
}
/*
void uf::EntityBehavior::initialize( uf::Entity& base ){
if ( base.m_uid == 0 ) base.m_uid = ++uf::Entity::uids;
}
void uf::EntityBehavior::destroy( uf::Entity& entity ){
for ( uf::Entity* kv : base.m_children ) {
if ( !kv ) continue;
if ( kv->getUid() == 0 ) continue;
kv->destroy();
kv->setParent();
delete kv;
}
base.m_children.clear();
base.m_uid = 0;
}
void uf::EntityBehavior::tick( uf::Entity& entity ){
for ( uf::Entity* kv : base.m_children ) {
if ( !kv ) continue;
if ( kv->getUid() == 0 ) continue;
kv->tick();
}
}
void uf::EntityBehavior::render( uf::Entity& entity ){
for ( uf::Entity* kv : base.m_children ) {
if ( !kv ) continue;
if ( kv->getUid() == 0 ) continue;
kv->render();
}
}
*/
}

View File

@ -1,16 +1,11 @@
#include <uf/engine/instantiator/instantiator.h>
#include <uf/engine/object/object.h>
#include <assert.h>
std::unordered_map<std::type_index, std::string>* uf::instantiator::names = NULL;
std::unordered_map<std::string, uf::instantiator::function_t>* uf::instantiator::map = NULL;
pod::NamedTypes<pod::Instantiator>* uf::instantiator::objects = NULL;
pod::NamedTypes<pod::Behavior>* uf::instantiator::behaviors = NULL;
uf::Entity* uf::instantiator::alloc( size_t size ) {
/*
uf::Entity* pointer = (uf::Entity*) uf::Entity::memoryPool.alloc( NULL, size );
std::cout << "malloc uf::Entity: "<< pointer <<" (size: " << size << ")" << std::endl;
return pointer;
*/
// uf::MemoryPool& memoryPool = uf::MemoryPool::global.size() > 0 ? uf::MemoryPool::global : uf::Entity::memoryPool;
#if UF_MEMORYPOOL_INVALID_MALLOC
uf::MemoryPool& memoryPool = uf::Entity::memoryPool.size() > 0 ? uf::Entity::memoryPool : uf::MemoryPool::global;
return (uf::Entity*) memoryPool.alloc( NULL, size );
@ -25,19 +20,8 @@ uf::Entity* uf::instantiator::alloc( size_t size ) {
else pointer = (uf::Entity*) malloc( size );
return pointer;
#endif
/*
uf::Entity* pointer = ( memoryPool.size() <= 0 ) ? (uf::Entity*) ::malloc( size ) : (uf::Entity*) memoryPool.alloc( NULL, size );
// std::cout << "malloc uf::Entity: "<< pointer <<" (size: " << size << ")" << std::endl;
return pointer;
*/
/*
std::cout << "malloc uf::Entity (size: " << size << ")" << std::endl;
if ( memoryPool.size() <= 0 ) return (uf::Entity*) ::malloc( size );
return (uf::Entity*) memoryPool.alloc( NULL, size );
*/
}
void uf::instantiator::free( uf::Entity* pointer ) {
// uf::MemoryPool& memoryPool = uf::MemoryPool::global.size() > 0 ? uf::MemoryPool::global : uf::Entity::memoryPool;
#if UF_MEMORYPOOL_INVALID_FREE
uf::MemoryPool& memoryPool = uf::Entity::memoryPool.size() > 0 ? uf::Entity::memoryPool : uf::MemoryPool::global;
memoryPool.free( pointer );
@ -50,15 +34,39 @@ void uf::instantiator::free( uf::Entity* pointer ) {
if ( memoryPool ) memoryPool->free( pointer );
else ::free( pointer );
#endif
/*
// std::cout << "free uf::Entity: " << pointer << std::endl;
if ( !uf::Entity::memoryPool.free( pointer ) )
::free(pointer);
*/
}
uf::Entity* uf::instantiator::instantiate( const std::string& name ) {
// std::cout << "instantiating " << name << std::endl;
auto& map = *uf::instantiator::map;
assert( map.count(name) > 0 );
return map[name]();
void uf::instantiator::registerBinding( const std::string& object, const std::string& behavior ) {
if ( !objects ) objects = new pod::NamedTypes<pod::Instantiator>;
auto& instantiator = uf::instantiator::objects->get( object );
instantiator.behaviors.emplace_back( behavior );
std::cout << "Registered binding: " << object << " and " << behavior << std::endl;
}
uf::Entity& uf::instantiator::instantiate( const std::string& name ) {
if ( !uf::instantiator::objects->has( name ) ) {
auto& object = uf::instantiator::instantiate<uf::Object>();
return *((uf::Entity*) &object);
}
auto& instantiator = uf::instantiator::objects->get( name );
auto& entity = *instantiator.function();
bind( name, entity );
return entity;
}
void uf::instantiator::bind( const std::string& name, uf::Entity& entity ) {
// was actually a behavior name, single bind
if ( !uf::instantiator::objects->has( name ) ) {
if ( !uf::instantiator::behaviors->has( name ) ) return;
auto& behavior = uf::instantiator::behaviors->get( name );
entity.addBehavior(behavior);
return;
}
auto& instantiator = uf::instantiator::objects->get( name );
for ( auto& name : instantiator.behaviors ) {
auto& behavior = uf::instantiator::behaviors->get( name );
entity.addBehavior(behavior);
}
}

View File

@ -0,0 +1,112 @@
#include <uf/engine/object/object.h>
#include <uf/engine/asset/asset.h>
#include <uf/engine/scene/scene.h>
#include <uf/utils/time/time.h>
#include <uf/utils/math/transform.h>
#include <uf/utils/math/physics.h>
#include <uf/utils/graphic/graphic.h>
#include <uf/utils/camera/camera.h>
#include <uf/utils/graphic/mesh.h>
#include <uf/ext/gltf/gltf.h>
UF_BEHAVIOR_ENTITY_CPP_BEGIN(Object)
#define this (&self)
void uf::ObjectBehavior::initialize( uf::Object& self ) {
uf::Serializer& metadata = this->getComponent<uf::Serializer>();
if ( metadata["system"]["type"].isNull() || metadata["system"]["defaults"]["asset load"].asBool() ) {
// Default load: GLTF model
this->addHook( "asset:Load.%UID%", [&](const std::string& event)->std::string{
uf::Serializer json = event;
std::string filename = json["filename"].asString();
if ( uf::string::extension(filename) != "glb" ) return "false";
int8_t LOAD_FLAGS = 0;
if ( metadata["model"]["flags"]["GENERATE_NORMALS"].asBool() )
LOAD_FLAGS |= ext::gltf::LoadMode::GENERATE_NORMALS; // 0x1 << 0;
if ( metadata["model"]["flags"]["APPLY_TRANSFORMS"].asBool() )
LOAD_FLAGS |= ext::gltf::LoadMode::APPLY_TRANSFORMS; // 0x1 << 1;
if ( metadata["model"]["flags"]["SEPARATE_MESHES"].asBool() )
LOAD_FLAGS |= ext::gltf::LoadMode::SEPARATE_MESHES; // 0x1 << 2;
if ( metadata["model"]["flags"]["RENDER"].asBool() )
LOAD_FLAGS |= ext::gltf::LoadMode::RENDER; // 0x1 << 3;
if ( metadata["model"]["flags"]["COLLISION"].asBool() )
LOAD_FLAGS |= ext::gltf::LoadMode::COLLISION; // 0x1 << 4;
if ( metadata["model"]["flags"]["AABB"].asBool() )
LOAD_FLAGS |= ext::gltf::LoadMode::AABB; // 0x1 << 5;
ext::gltf::load( *this, filename, LOAD_FLAGS );
return "true";
});
}
}
void uf::ObjectBehavior::destroy( uf::Object& self ) {
uf::Serializer& metadata = this->getComponent<uf::Serializer>();
for( Json::Value::iterator it = metadata["system"]["hooks"]["alloc"].begin() ; it != metadata["system"]["hooks"]["alloc"].end() ; ++it ) {
std::string name = it.key().asString();
for ( size_t i = 0; i < metadata["system"]["hooks"]["alloc"][name].size(); ++i ) {
size_t id = metadata["system"]["hooks"]["alloc"][name][(int) i].asUInt();
uf::hooks.removeHook(name, id);
}
}
}
void uf::ObjectBehavior::tick( uf::Object& self ) {
// listen for metadata file changes
uf::Serializer& metadata = this->getComponent<uf::Serializer>();
if ( metadata["system"]["hot reload"]["enabled"].asBool() ) {
size_t mtime = uf::string::mtime( metadata["system"]["source"].asString() );
if ( metadata["system"]["hot reload"]["mtime"].asUInt64() < mtime ) {
std::cout << metadata["system"]["hot reload"]["mtime"] << ": " << mtime << std::endl;
metadata["system"]["hot reload"]["mtime"] = mtime;
this->reload();
//this->queueHook("metadata:Reload.%UID%");
}
}
// Call queued hooks
{
if ( !uf::Object::timer.running() ) uf::Object::timer.start();
float curTime = uf::Object::timer.elapsed().asDouble();
uf::Serializer newQueue = Json::Value(Json::arrayValue);
for ( auto& member : metadata["system"]["hooks"]["queue"] ) {
uf::Serializer payload = member["payload"];
std::string name = member["name"].asString();
float timeout = member["timeout"].asFloat();
if ( timeout < curTime ) {
this->callHook( name, payload );
} else {
newQueue.append(member);
}
}
if ( metadata.isObject() ) metadata["system"]["hooks"]["queue"] = newQueue;
}
}
void uf::ObjectBehavior::render( uf::Object& self ) {
auto& metadata = this->getComponent<uf::Serializer>();
if ( metadata["system"]["type"].isNull() || metadata["system"]["defaults"]["render"].asBool() ) {
/* Update uniforms */ if ( this->hasComponent<uf::Graphic>() ) {
auto& scene = uf::scene::getCurrentScene();
auto& graphic = this->getComponent<uf::Graphic>();
auto& transform = this->getComponent<pod::Transform<>>();
auto& controller = scene.getController();
auto& camera = controller.getComponent<uf::Camera>();
if ( !graphic.initialized ) return;
auto& uniforms = graphic.material.shaders.front().uniforms.front().get<uf::StereoMeshDescriptor>();
uniforms.matrices.model = uf::transform::model( transform );
for ( std::size_t i = 0; i < 2; ++i ) {
uniforms.matrices.view[i] = camera.getView( i );
uniforms.matrices.projection[i] = camera.getProjection( i );
}
uniforms.color[0] = 1;
uniforms.color[1] = 1;
uniforms.color[2] = 1;
uniforms.color[3] = 1;
graphic.material.shaders.front().updateBuffer( uniforms, 0, false );
};
}
}
#undef this
UF_BEHAVIOR_ENTITY_CPP_END(Entity)

View File

@ -9,9 +9,8 @@
#include <uf/utils/graphic/mesh.h>
#include <uf/ext/gltf/gltf.h>
uf::Timer<long long> uf::Object::timer(false);
namespace {
uf::Timer<long long> timer(false);
std::string grabURI( std::string filename, std::string root = "" ) {
if ( filename.substr(0,8) == "https://" ) return filename;
std::string extension = uf::string::extension(filename);
@ -26,116 +25,13 @@ namespace {
}
}
UF_OBJECT_REGISTER_CPP(Object)
void uf::Object::initialize() {
uf::Entity::initialize();
uf::Serializer& metadata = this->getComponent<uf::Serializer>();
if ( metadata["system"]["type"].isNull() || metadata["system"]["defaults"]["asset load"].asBool() ) {
// Default load: GLTF model
this->addHook( "asset:Load.%UID%", [&](const std::string& event)->std::string{
uf::Serializer json = event;
std::string filename = json["filename"].asString();
if ( uf::string::extension(filename) != "glb" ) return "false";
int8_t LOAD_FLAGS = 0;
if ( metadata["model"]["flags"]["GENERATE_NORMALS"].asBool() )
LOAD_FLAGS |= ext::gltf::LoadMode::GENERATE_NORMALS; // 0x1 << 0;
if ( metadata["model"]["flags"]["APPLY_TRANSFORMS"].asBool() )
LOAD_FLAGS |= ext::gltf::LoadMode::APPLY_TRANSFORMS; // 0x1 << 1;
if ( metadata["model"]["flags"]["SEPARATE_MESHES"].asBool() )
LOAD_FLAGS |= ext::gltf::LoadMode::SEPARATE_MESHES; // 0x1 << 2;
if ( metadata["model"]["flags"]["RENDER"].asBool() )
LOAD_FLAGS |= ext::gltf::LoadMode::RENDER; // 0x1 << 3;
if ( metadata["model"]["flags"]["COLLISION"].asBool() )
LOAD_FLAGS |= ext::gltf::LoadMode::COLLISION; // 0x1 << 4;
if ( metadata["model"]["flags"]["AABB"].asBool() )
LOAD_FLAGS |= ext::gltf::LoadMode::AABB; // 0x1 << 5;
ext::gltf::load( *this, filename, LOAD_FLAGS );
return "true";
});
}
}
void uf::Object::destroy() {
uf::Serializer& metadata = this->getComponent<uf::Serializer>();
for( Json::Value::iterator it = metadata["system"]["hooks"]["alloc"].begin() ; it != metadata["system"]["hooks"]["alloc"].end() ; ++it ) {
std::string name = it.key().asString();
for ( size_t i = 0; i < metadata["system"]["hooks"]["alloc"][name].size(); ++i ) {
size_t id = metadata["system"]["hooks"]["alloc"][name][(int) i].asUInt();
uf::hooks.removeHook(name, id);
}
}
uf::Entity::destroy();
}
void uf::Object::tick() {
uf::Entity::tick();
// listen for metadata file changes
uf::Serializer& metadata = this->getComponent<uf::Serializer>();
if ( metadata["system"]["hot reload"]["enabled"].asBool() ) {
size_t mtime = uf::string::mtime( metadata["system"]["source"].asString() );
if ( metadata["system"]["hot reload"]["mtime"].asUInt64() < mtime ) {
std::cout << metadata["system"]["hot reload"]["mtime"] << ": " << mtime << std::endl;
metadata["system"]["hot reload"]["mtime"] = mtime;
this->reload();
//this->queueHook("metadata:Reload.%UID%");
}
}
// Call queued hooks
{
if ( !timer.running() ) timer.start();
float curTime = timer.elapsed().asDouble();
uf::Serializer newQueue = Json::Value(Json::arrayValue);
for ( auto& member : metadata["system"]["hooks"]["queue"] ) {
uf::Serializer payload = member["payload"];
std::string name = member["name"].asString();
float timeout = member["timeout"].asFloat();
if ( timeout < curTime ) {
this->callHook( name, payload );
} else {
newQueue.append(member);
}
}
if ( metadata.isObject() ) metadata["system"]["hooks"]["queue"] = newQueue;
}
}
void uf::Object::render() {
uf::Entity::render();
auto& metadata = this->getComponent<uf::Serializer>();
if ( metadata["system"]["type"].isNull() || metadata["system"]["defaults"]["render"].asBool() ) {
/* Update uniforms */ if ( this->hasComponent<uf::Graphic>() ) {
auto& scene = uf::scene::getCurrentScene();
auto& graphic = this->getComponent<uf::Graphic>();
auto& transform = this->getComponent<pod::Transform<>>();
auto& controller = scene.getController();
auto& camera = controller.getComponent<uf::Camera>();
if ( !graphic.initialized ) return;
auto& uniforms = graphic.material.shaders.front().uniforms.front().get<uf::StereoMeshDescriptor>();
uniforms.matrices.model = uf::transform::model( transform );
for ( std::size_t i = 0; i < 2; ++i ) {
uniforms.matrices.view[i] = camera.getView( i );
uniforms.matrices.projection[i] = camera.getProjection( i );
}
uniforms.color[0] = 1;
uniforms.color[1] = 1;
uniforms.color[2] = 1;
uniforms.color[3] = 1;
graphic.material.shaders.front().updateBuffer( uniforms, 0, false );
};
}
}
UF_OBJECT_REGISTER_BEGIN(Object)
UF_OBJECT_REGISTER_BEHAVIOR(EntityBehavior)
UF_OBJECT_REGISTER_BEHAVIOR(ObjectBehavior)
UF_OBJECT_REGISTER_END()
void uf::Object::queueHook( const std::string& name, const std::string& payload, double timeout ) {
if ( !timer.running() ) timer.start();
float start = timer.elapsed().asDouble();
if ( !uf::Object::timer.running() ) uf::Object::timer.start();
float start = uf::Object::timer.elapsed().asDouble();
uf::Serializer queue;
queue["name"] = name;
queue["payload"] = uf::Serializer{payload};
@ -212,6 +108,21 @@ bool uf::Object::load( const uf::Serializer& json ) {
// Set name
this->m_name = json["name"].isString() ? json["name"].asString() : json["type"].asString();
}
// Bind behaviors
if ( json["type"].isString() ) {
uf::instantiator::bind( json["type"].asString(), *this );
}
{
uf::Serializer target;
if ( metadata["system"]["behaviors"].isArray() ) {
target = metadata["system"]["behaviors"];
} else if ( json["behaviors"].isArray() ) {
target = json["behaviors"];
}
for ( uint i = 0; i < target.size(); ++i ) {
uf::instantiator::bind( target[i].asString(), *this );
}
}
// Set transform
{
bool load = json["transform"].isObject();
@ -444,7 +355,7 @@ std::size_t uf::Object::loadChild( const uf::Serializer& json, bool initialize )
uf::Entity* entity;
std::string type = json["type"].asString();
if ( json["ignore"].asBool() ) return 0;
entity = uf::instantiator::instantiate(type);
entity = &uf::instantiator::instantiate(type);
if ( !((uf::Object*) entity)->load(json) ) {
uf::iostream << "Error @ " << __FILE__ << ":" << __LINE__ << " loading `" << json << "!" << "\n";

View File

@ -0,0 +1,22 @@
#include <uf/engine/scene/scene.h>
#include <uf/utils/string/ext.h>
#include <uf/utils/camera/camera.h>
#include <uf/utils/renderer/renderer.h>
UF_BEHAVIOR_ENTITY_CPP_BEGIN(Scene)
#define this ((uf::Scene*) &self)
void uf::SceneBehavior::initialize( uf::Object& self ) {
uf::renderer::scenes.push_back(this);
uf::renderer::rebuild = true;
}
void uf::SceneBehavior::tick( uf::Object& self ) {
}
void uf::SceneBehavior::render( uf::Object& self ) {
}
void uf::SceneBehavior::destroy( uf::Object& self ) {
auto it = std::find(uf::renderer::scenes.begin(), uf::renderer::scenes.end(), this);
if ( it != uf::renderer::scenes.end() ) uf::renderer::scenes.erase(it);
uf::renderer::rebuild = true;
}
#undef self
UF_BEHAVIOR_ENTITY_CPP_END(Scene)

View File

@ -3,31 +3,11 @@
#include <uf/utils/camera/camera.h>
#include <uf/utils/renderer/renderer.h>
UF_OBJECT_REGISTER_CPP(Scene)
void uf::Scene::initialize() {
uf::renderer::scenes.push_back(this);
uf::renderer::rebuild = true;
uf::Object::initialize();
}
void uf::Scene::tick() {
uf::Object::tick();
}
void uf::Scene::render() {
uf::Object::render();
}
void uf::Scene::destroy() {
uf::Object::destroy();
{
auto it = std::find(uf::renderer::scenes.begin(), uf::renderer::scenes.end(), this);
if ( it != uf::renderer::scenes.end() ) uf::renderer::scenes.erase(it);
uf::renderer::rebuild = true;
}
}
UF_OBJECT_REGISTER_BEGIN(Scene)
UF_OBJECT_REGISTER_BEHAVIOR(EntityBehavior)
UF_OBJECT_REGISTER_BEHAVIOR(ObjectBehavior)
UF_OBJECT_REGISTER_BEHAVIOR(SceneBehavior)
UF_OBJECT_REGISTER_END()
uf::Entity& uf::Scene::getController() {
static uf::Entity* cachedController = NULL;
if ( uf::renderer::currentRenderMode ) {
@ -58,7 +38,12 @@ const uf::Entity& uf::Scene::getController() const {
#include <regex>
std::vector<uf::Scene*> uf::scene::scenes;
uf::Scene& uf::scene::loadScene( const std::string& name, const std::string& filename ) {
uf::Scene* scene = (uf::Scene*) uf::instantiator::instantiate( name );
uf::Scene* scene;
if ( uf::instantiator::objects->has( name ) ) {
scene = (uf::Scene*) &uf::instantiator::instantiate( name );
} else {
scene = new uf::Scene;
}
uf::scene::scenes.push_back(scene);
std::string target = name;
@ -70,13 +55,17 @@ uf::Scene& uf::scene::loadScene( const std::string& name, const std::string& fil
target = match[2];
}
target = uf::string::lowercase( target );
scene->load(filename != "" ? filename : "./scenes/" + target + "/scene.json");
scene->initialize();
return *scene;
}
uf::Scene& uf::scene::loadScene( const std::string& name, const uf::Serializer& data ) {
uf::Scene* scene = (uf::Scene*) uf::instantiator::instantiate( name );
uf::Scene* scene;
if ( uf::instantiator::objects->has( name ) ) {
scene = (uf::Scene*) &uf::instantiator::instantiate( name );
} else {
scene = new uf::Scene;
}
uf::scene::scenes.push_back(scene);
if ( data != "" ) scene->load(data);
scene->initialize();

374
ext/behaviors/base/base.cpp Normal file
View File

@ -0,0 +1,374 @@
#include "base.h"
#include <uf/utils/time/time.h>
#include <uf/utils/io/iostream.h>
#include <uf/utils/math/vector.h>
#include <uf/utils/math/transform.h>
#include <uf/utils/window/window.h>
#include <uf/utils/graphic/graphic.h>
#include <uf/utils/audio/audio.h>
#include <uf/utils/thread/thread.h>
#include <uf/utils/camera/camera.h>
#include <uf/engine/asset/asset.h>
#include <uf/engine/asset/masterdata.h>
#include <uf/utils/renderer/renderer.h>
#include <uf/ext/gltf/gltf.h>
#include <uf/utils/math/collision.h>
#include "../../ext.h"
#include "../../gui/gui.h"
EXT_BEHAVIOR_REGISTER_CPP(SceneBehavior)
#define this ((uf::Scene*) &self)
void ext::SceneBehavior::initialize( uf::Object& self ) {
uf::Asset& assetLoader = this->getComponent<uf::Asset>();
uf::Serializer& metadata = this->getComponent<uf::Serializer>();
this->addHook( "system:Quit.%UID%", [&](const std::string& event)->std::string{
std::cout << event << std::endl;
ext::ready = false;
return "true";
});
this->addHook( "world:Music.LoadPrevious.%UID%", [&](const std::string& event)->std::string{
uf::Serializer json = event;
if ( metadata["previous bgm"]["filename"] == "" ) return "false";
std::string filename = metadata["previous bgm"]["filename"].asString();
float timestamp = metadata["previous bgm"]["timestamp"].asFloat();
// std::cout << metadata["previous bgm"] << std::endl;
uf::Audio& audio = this->getComponent<uf::Audio>();
if ( audio.playing() ) {
metadata["previous bgm"]["filename"] = audio.getFilename();
metadata["previous bgm"]["timestamp"] = audio.getTime();
audio.stop();
}
audio.load(filename);
audio.setVolume(metadata["volumes"]["bgm"].asFloat());
audio.setTime(timestamp);
audio.play();
return "true";
});
this->addHook( "asset:Load.%UID%", [&](const std::string& event)->std::string{
uf::Serializer json = event;
std::string filename = json["filename"].asString();
if ( uf::string::extension(filename) != "ogg" ) return "false";
const uf::Audio* audioPointer = NULL;
try { audioPointer = &assetLoader.get<uf::Audio>(filename); } catch ( ... ) {}
if ( !audioPointer ) return "false";
uf::Audio& audio = this->getComponent<uf::Audio>();
if ( audio.playing() ) audio.stop();
audio.load(filename);
audio.setVolume(metadata["volumes"]["bgm"].asFloat());
audio.play();
return "true";
});
this->addHook( "menu:Pause", [&](const std::string& event)->std::string{
static uf::Timer<long long> timer(false);
if ( !timer.running() ) timer.start();
if ( timer.elapsed().asDouble() < 1 ) return "false";
timer.reset();
uf::Serializer json = event;
ext::Gui* manager = (ext::Gui*) this->findByName("Gui Manager");
if ( !manager ) return "false";
uf::Serializer payload;
ext::Gui* gui = (ext::Gui*) manager->findByUid( (payload["uid"] = manager->loadChild("/scenes/worldscape/gui/pause/menu.json", false)).asUInt64() );
uf::Serializer& metadata = gui->getComponent<uf::Serializer>();
metadata["menu"] = json["menu"];
gui->initialize();
return payload;
});
this->addHook( "world:Entity.LoadAsset", [&](const std::string& event)->std::string{
uf::Serializer json = event;
std::string asset = json["asset"].asString();
std::string uid = json["uid"].asString();
assetLoader.load(asset, "asset:Load." + uid);
return "true";
});
/* store viewport size */ {
metadata["window"]["size"]["x"] = uf::renderer::width;
metadata["window"]["size"]["y"] = uf::renderer::height;
this->addHook( "window:Resized", [&](const std::string& event)->std::string{
uf::Serializer json = event;
pod::Vector2ui size; {
size.x = json["window"]["size"]["x"].asUInt64();
size.y = json["window"]["size"]["y"].asUInt64();
}
metadata["window"] = json["window"];
return "true";
});
}
// lock control
{
uf::Serializer payload;
payload["state"] = false;
uf::hooks.call("window:Mouse.CursorVisibility", payload);
uf::hooks.call("window:Mouse.Lock");
}
}
void ext::SceneBehavior::tick( uf::Object& self ) {
uf::Serializer& metadata = this->getComponent<uf::Serializer>();
uf::Asset& assetLoader = this->getComponent<uf::Asset>();
/* check if audio needs to loop */ try {
uf::Audio& bgm = this->getComponent<uf::Audio>();
float current = bgm.getTime();
float end = bgm.getDuration();
float epsilon = 0.005f;
if ( current + epsilon >= end || !bgm.playing() ) {
// intro to main transition
std::string filename = bgm.getFilename();
filename = assetLoader.getOriginal(filename);
if ( filename.find("_intro") != std::string::npos ) {
assetLoader.load(uf::string::replace( filename, "_intro", "" ), "asset:Load." + std::to_string(this->getUid()));
// loop
} else {
bgm.setTime(0);
if ( !bgm.playing() ) bgm.play();
}
}
} catch ( ... ) {
}
/* Regain control if nothing requests it */ {
ext::Gui* menu = (ext::Gui*) this->findByName("Gui: Menu");
if ( !menu ) {
uf::Serializer payload;
payload["state"] = false;
uf::hooks.call("window:Mouse.CursorVisibility", payload);
uf::hooks.call("window:Mouse.Lock");
}
}
/* Print Entity Information */ {
static uf::Timer<long long> timer(false);
if ( !timer.running() ) timer.start();
if ( uf::Window::isKeyPressed("U") && timer.elapsed().asDouble() >= 1 ) { timer.reset();
auto& allocations = uf::Entity::memoryPool.allocations();
uf::iostream << "Current size: " << allocations.size() << "\n"; //" | UIDs: " << uf::Entity::uids << "\n";
uint orphans = 0;
uint empty = 0;
for ( auto& allocation : allocations ) {
uf::Entity* e = (uf::Entity*) allocation.pointer;
if ( !e->hasParent() ) {
++orphans;
uf::iostream << "Orphan: " << e->getName() << ": " << e << "\n";
}
}
uf::iostream << "Orphans: " << orphans << "\n";
uf::iostream << "Empty: " << empty << "\n";
}
}
/* Updates Sound Listener */ {
auto& controller = this->getController();
auto& transform = controller.getComponent<pod::Transform<>>();
ext::oal.listener( "POSITION", { transform.position.x, transform.position.y, transform.position.z } );
ext::oal.listener( "VELOCITY", { 0, 0, 0 } );
ext::oal.listener( "ORIENTATION", { 0, 0, 1, 1, 0, 0 } );
}
if ( uf::scene::getCurrentScene().getUid() == this->getUid() ) {
/* Update lights */ if ( metadata["light"]["should"].asBool() ) {
// if ( !uf::renderer::currentRenderMode || uf::renderer::currentRenderMode->name != "" ) return;
auto& scene = uf::scene::getCurrentScene();
std::vector<uf::Graphic*> blitters;
auto& renderMode = uf::renderer::getRenderMode("", true);
bool hasCompute = uf::renderer::hasRenderMode("C:RT:" + std::to_string(this->getUid()), true);
if ( hasCompute ) {
// auto& renderMode = uf::renderer::getRenderMode("C:RT:" + std::to_string(this->getUid()), true);
// auto* renderModePointer = (uf::renderer::ComputeRenderMode*) &renderMode;
// if ( renderModePointer->compute.initialized ) {
// blitters.push_back(&renderModePointer->compute);
// } else {
// hasCompute = false;
// }
} else if ( renderMode.getType() == "Deferred (Stereoscopic)" ) {
auto* renderModePointer = (uf::renderer::StereoscopicDeferredRenderMode*) &renderMode;
blitters.push_back(&renderModePointer->blitters.left);
blitters.push_back(&renderModePointer->blitters.right);
} else if ( renderMode.getType() == "Deferred" ) {
auto* renderModePointer = (uf::renderer::DeferredRenderMode*) &renderMode;
blitters.push_back(&renderModePointer->blitter);
}
auto& controller = scene.getController();
auto& camera = controller.getComponent<uf::Camera>();
// auto& uniforms = blitter.uniforms;
struct UniformDescriptor {
struct Matrices {
alignas(16) pod::Matrix4f view[2];
alignas(16) pod::Matrix4f projection[2];
} matrices;
alignas(16) pod::Vector4f ambient;
struct {
alignas(8) pod::Vector2f range;
alignas(16) pod::Vector4f color;
} fog;
struct Light {
alignas(16) pod::Vector4f position;
alignas(16) pod::Vector4f color;
alignas(8) pod::Vector2i type;
alignas(16) pod::Matrix4f view;
alignas(16) pod::Matrix4f projection;
} lights;
};
struct SpecializationConstant {
int32_t maxLights = 32;
} specializationConstants;
for ( size_t _ = 0; _ < blitters.size(); ++_ ) {
auto& blitter = *blitters[_];
uint8_t* buffer;
size_t len;
auto* shader = &blitter.material.shaders.front();
for ( auto& _ : blitter.material.shaders ) {
if ( _.uniforms.empty() ) continue;
auto& userdata = _.uniforms.front();
buffer = (uint8_t*) (void*) userdata;
len = userdata.data().len;
shader = &_;
specializationConstants = _.specializationConstants.get<SpecializationConstant>();
}
if ( !buffer ) continue;
UniformDescriptor* uniforms = (UniformDescriptor*) buffer;
for ( std::size_t i = 0; i < 2; ++i ) {
uniforms->matrices.view[i] = camera.getView( i );
uniforms->matrices.projection[i] = camera.getProjection( i );
}
{
uniforms->ambient.x = metadata["light"]["ambient"][0].asFloat();
uniforms->ambient.y = metadata["light"]["ambient"][1].asFloat();
uniforms->ambient.z = metadata["light"]["ambient"][2].asFloat();
uniforms->ambient.w = metadata["light"]["kexp"].asFloat();
}
{
uniforms->fog.color.x = metadata["light"]["fog"]["color"][0].asFloat();
uniforms->fog.color.y = metadata["light"]["fog"]["color"][1].asFloat();
uniforms->fog.color.z = metadata["light"]["fog"]["color"][2].asFloat();
uniforms->fog.range.x = metadata["light"]["fog"]["range"][0].asFloat();
uniforms->fog.range.y = metadata["light"]["fog"]["range"][1].asFloat();
}
{
std::vector<uf::Entity*> entities;
std::function<void(uf::Entity*)> filter = [&]( uf::Entity* entity ) {
if ( !entity || entity->getName() != "Light" ) return;
entities.push_back(entity);
};
for ( uf::Scene* scene : uf::renderer::scenes ) { if ( !scene ) continue;
scene->process(filter);
}
{
const pod::Vector3& position = controller.getComponent<pod::Transform<>>().position;
std::sort( entities.begin(), entities.end(), [&]( const uf::Entity* l, const uf::Entity* r ){
if ( !l ) return false; if ( !r ) return true;
if ( !l->hasComponent<pod::Transform<>>() ) return false; if ( !r->hasComponent<pod::Transform<>>() ) return true;
return uf::vector::magnitude( uf::vector::subtract( l->getComponent<pod::Transform<>>().position, position ) ) < uf::vector::magnitude( uf::vector::subtract( r->getComponent<pod::Transform<>>().position, position ) );
} );
}
{
uf::Serializer& metadata = controller.getComponent<uf::Serializer>();
if ( metadata["light"]["should"].asBool() ) entities.push_back(&controller);
}
UniformDescriptor::Light* lights = (UniformDescriptor::Light*) &buffer[sizeof(UniformDescriptor) - sizeof(UniformDescriptor::Light)];
for ( size_t i = 0; i < specializationConstants.maxLights; ++i ) {
UniformDescriptor::Light& light = lights[i];
light.position = { 0, 0, 0, 0 };
light.color = { 0, 0, 0, 0 };
light.type = { 0, 0 };
}
blitter.material.textures.clear();
for ( size_t i = 0; i < specializationConstants.maxLights && i < entities.size(); ++i ) {
UniformDescriptor::Light& light = lights[i];
uf::Entity* entity = entities[i];
pod::Transform<>& transform = entity->getComponent<pod::Transform<>>();
uf::Serializer& metadata = entity->getComponent<uf::Serializer>();
uf::Camera& camera = entity->getComponent<uf::Camera>();
light.position.x = transform.position.x;
light.position.y = transform.position.y;
light.position.z = transform.position.z;
light.view = camera.getView();
light.projection = camera.getProjection();
if ( entity == &controller ) light.position.y += 2;
light.position.w = metadata["light"]["radius"][1].asFloat();
light.color.x = metadata["light"]["color"][0].asFloat();
light.color.y = metadata["light"]["color"][1].asFloat();
light.color.z = metadata["light"]["color"][2].asFloat();
light.color.w = metadata["light"]["power"].asFloat();
light.type.x = metadata["light"]["type"].asUInt64();
light.type.y = metadata["light"]["shadows"]["enabled"].asBool();
if ( !hasCompute && entity->hasComponent<uf::renderer::RenderTargetRenderMode>() ) {
auto& renderMode = entity->getComponent<uf::renderer::RenderTargetRenderMode>();
auto& renderTarget = renderMode.renderTarget;
uint8_t i = 0;
for ( auto& attachment : renderTarget.attachments ) {
if ( !(attachment.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ) continue;
// if ( (attachment.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ) continue;
if ( (attachment.layout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) ) continue;
auto& texture = blitter.material.textures.emplace_back();
texture.aliasAttachment(attachment);
light.type.y = true;
break;
}
} else {
light.type.y = false;
}
}
}
blitter.getPipeline().update( blitter );
shader->updateBuffer( (void*) buffer, len, 0, false );
}
}
}
}
void ext::SceneBehavior::render( uf::Object& self ) {
}
void ext::SceneBehavior::destroy( uf::Object& self ) {
}
#undef this

View File

@ -1,12 +1,14 @@
#pragma once
#include "../base.h"
#include <uf/config.h>
#include <uf/ext/ext.h>
#include <uf/engine/entity/entity.h>
#include <uf/engine/scene/scene.h>
namespace ext {
class EXT_API TestBehavior {
class EXT_API SceneBehavior {
public:
static void attach( uf::Object& );
static void initialize( uf::Object& );
static void tick( uf::Object& );
static void render( uf::Object& );

View File

@ -0,0 +1,210 @@
#include "behavior.h"
#include <uf/utils/time/time.h>
#include <uf/utils/io/iostream.h>
#include <uf/utils/math/vector.h>
#include <uf/utils/math/transform.h>
#include <uf/utils/window/window.h>
#include <uf/utils/graphic/graphic.h>
#include <uf/utils/audio/audio.h>
#include <uf/utils/thread/thread.h>
#include <uf/utils/camera/camera.h>
#include <uf/engine/asset/asset.h>
#include <uf/engine/asset/masterdata.h>
#include <uf/utils/renderer/renderer.h>
#include <uf/ext/gltf/gltf.h>
#include <uf/utils/math/collision.h>
#include "../../ext.h"
#include "../../gui/gui.h"
EXT_BEHAVIOR_REGISTER_CPP(RayTracingSceneBehavior)
#define this ((uf::Scene*) &self)
void ext::RayTracingSceneBehavior::initialize( uf::Object& self ) {
uf::Serializer& metadata = this->getComponent<uf::Serializer>();
uf::Asset& assetLoader = this->getComponent<uf::Asset>();
{
auto& renderMode = this->getComponent<uf::renderer::ComputeRenderMode>();
std::string name = "C:RT:" + std::to_string((int) this->getUid());
uf::renderer::addRenderMode( &renderMode, name );
if ( metadata["light"]["shadows"]["resolution"].isArray() ) {
renderMode.width = metadata["light"]["shadows"]["resolution"][0].asUInt64();
renderMode.height = metadata["light"]["shadows"]["resolution"][1].asUInt64();
} else {
renderMode.width = metadata["light"]["shadows"]["resolution"].asUInt64();
renderMode.height = metadata["light"]["shadows"]["resolution"].asUInt64();
}
{
struct Shape {
pod::Vector4f values;
pod::Vector3f diffuse;
float specular;
uint32_t id;
pod::Vector3ui _pad;
};
std::vector<Shape> shapes;
{
shapes.push_back( {{1.75f, -0.5f, 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f}, 32.0f, 1} );
shapes.push_back( {{0.0f, 1.0f, -0.5f, 1.0f }, {0.65f, 0.77f, 0.97f}, 32.0f, 1} );
shapes.push_back( {{-1.75f, -0.75f, -0.5f, 1.25f }, { 0.9f, 0.76f, 0.46f}, 32.0f, 1} );
}
{
float roomDim = 12.0f;
shapes.push_back( {{0.0f, 1.0f, 0.0f, roomDim}, {1.0f, 1.0f, 1.0f}, 32.0f, 2} );
shapes.push_back( {{0.0f, -1.0f, 0.0f, roomDim}, {1.0f, 1.0f, 1.0f}, 32.0f, 2} );
shapes.push_back( {{0.0f, 0.0f, 1.0f, roomDim}, {1.0f, 1.0f, 1.0f}, 32.0f, 2} );
shapes.push_back( {{0.0f, 0.0f, -1.0f, roomDim}, {0.0f, 0.0f, 0.0f}, 32.0f, 2} );
shapes.push_back( {{-1.0f, 0.0f, 0.0f, roomDim}, {1.0f, 0.0f, 0.0f}, 32.0f, 2} );
shapes.push_back( {{1.0f, 0.0f, 0.0f, roomDim}, {0.0f, 1.0f, 0.0f}, 32.0f, 2} );
}
renderMode.compute.device = &uf::renderer::device;
renderMode.compute.initializeBuffer(
(void*) shapes.data(),
shapes.size() * sizeof(Shape),
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
true
);
}
}
}
void ext::RayTracingSceneBehavior::tick( uf::Object& self ) {
uf::Serializer& metadata = this->getComponent<uf::Serializer>();
uf::Asset& assetLoader = this->getComponent<uf::Asset>();
#if 1
if ( this->hasComponent<uf::renderer::ComputeRenderMode>() ) {
auto& renderMode = this->getComponent<uf::renderer::ComputeRenderMode>();
/* Add lights to scene */ if ( renderMode.compute.initialized ) {
struct UniformDescriptor {
alignas(16) pod::Matrix4f matrices[2];
alignas(16) pod::Vector4f ambient;
struct {
alignas(8) pod::Vector2f range;
alignas(16) pod::Vector4f color;
} fog;
struct Light {
alignas(16) pod::Vector4f position;
alignas(16) pod::Vector4f color;
alignas(8) pod::Vector2i type;
alignas(16) pod::Matrix4f view;
alignas(16) pod::Matrix4f projection;
} lights;
};
struct SpecializationConstant {
int32_t eyes = 2;
int32_t maxLights = 16;
} specializationConstants;
auto& shader = renderMode.compute.material.shaders.front();
specializationConstants = shader.specializationConstants.get<SpecializationConstant>();
struct PushConstant {
uint32_t marchingSteps;
uint32_t rayBounces;
float shadowFactor;
float reflectionStrength;
float reflectionFalloff;
};
auto& pushConstant = shader.pushConstants.front().get<PushConstant>();
pushConstant.marchingSteps = metadata["rays"]["marching steps"].asUInt64();
pushConstant.rayBounces = metadata["rays"]["ray bounces"].asUInt64();
pushConstant.shadowFactor = metadata["rays"]["shadow factor"].asFloat();
pushConstant.reflectionStrength = metadata["rays"]["reflection"]["strength"].asFloat();
pushConstant.reflectionFalloff = metadata["rays"]["reflection"]["falloff"].asFloat();
auto& scene = uf::scene::getCurrentScene();
auto& controller = scene.getController();
auto& camera = controller.getComponent<uf::Camera>();
auto& transform = controller.getComponent<pod::Transform<>>();
auto& userdata = shader.uniforms.front();
size_t uniforms_len = userdata.data().len;
uint8_t* uniforms_buffer = (uint8_t*) (void*) userdata;
UniformDescriptor* uniforms = (UniformDescriptor*) uniforms_buffer;
for ( size_t i = 0; i < 2; ++i ) {
uniforms->matrices[i] = uf::matrix::inverse( camera.getProjection(i) * camera.getView(i) );
}
{
uniforms->ambient.x = metadata["light"]["ambient"][0].asFloat();
uniforms->ambient.y = metadata["light"]["ambient"][1].asFloat();
uniforms->ambient.z = metadata["light"]["ambient"][2].asFloat();
uniforms->ambient.w = metadata["light"]["kexp"].asFloat();
}
{
uniforms->fog.color.x = metadata["light"]["fog"]["color"][0].asFloat();
uniforms->fog.color.y = metadata["light"]["fog"]["color"][1].asFloat();
uniforms->fog.color.z = metadata["light"]["fog"]["color"][2].asFloat();
uniforms->fog.range.x = metadata["light"]["fog"]["range"][0].asFloat();
uniforms->fog.range.y = metadata["light"]["fog"]["range"][1].asFloat();
}
std::vector<uf::Entity*> entities;
std::function<void(uf::Entity*)> filter = [&]( uf::Entity* entity ) {
if ( !entity || entity->getName() != "Light" ) return;
entities.push_back(entity);
};
for ( uf::Scene* scene : uf::renderer::scenes ) { if ( !scene ) continue;
scene->process(filter);
}
{
const pod::Vector3& position = controller.getComponent<pod::Transform<>>().position;
std::sort( entities.begin(), entities.end(), [&]( const uf::Entity* l, const uf::Entity* r ){
if ( !l ) return false; if ( !r ) return true;
if ( !l->hasComponent<pod::Transform<>>() ) return false; if ( !r->hasComponent<pod::Transform<>>() ) return true;
return uf::vector::magnitude( uf::vector::subtract( l->getComponent<pod::Transform<>>().position, position ) ) < uf::vector::magnitude( uf::vector::subtract( r->getComponent<pod::Transform<>>().position, position ) );
} );
}
{
uf::Serializer& metadata = controller.getComponent<uf::Serializer>();
if ( metadata["light"]["should"].asBool() ) entities.push_back(&controller);
}
UniformDescriptor::Light* lights = (UniformDescriptor::Light*) &uniforms_buffer[sizeof(UniformDescriptor) - sizeof(UniformDescriptor::Light)];
for ( size_t i = 0; i < specializationConstants.maxLights && i < entities.size(); ++i ) {
UniformDescriptor::Light& light = lights[i];
uf::Entity* entity = entities[i];
pod::Transform<>& transform = entity->getComponent<pod::Transform<>>();
uf::Serializer& metadata = entity->getComponent<uf::Serializer>();
uf::Camera& camera = entity->getComponent<uf::Camera>();
light.position.x = transform.position.x;
light.position.y = transform.position.y;
light.position.z = transform.position.z;
if ( entity == &controller ) light.position.y += 2;
light.position.w = metadata["light"]["radius"][1].asFloat();
light.color.x = metadata["light"]["color"][0].asFloat();
light.color.y = metadata["light"]["color"][1].asFloat();
light.color.z = metadata["light"]["color"][2].asFloat();
light.color.w = metadata["light"]["power"].asFloat();
}
shader.updateBuffer( (void*) uniforms_buffer, uniforms_len, 0, false );
}
}
#endif
}
void ext::RayTracingSceneBehavior::render( uf::Object& self ) {
}
void ext::RayTracingSceneBehavior::destroy( uf::Object& self ) {
if ( this->hasComponent<uf::renderer::ComputeRenderMode>() ) {
auto& renderMode = this->getComponent<uf::renderer::ComputeRenderMode>();
uf::renderer::removeRenderMode( &renderMode, false );
}
}
#undef this

View File

@ -0,0 +1,17 @@
#pragma once
#include <uf/config.h>
#include <uf/ext/ext.h>
#include <uf/engine/entity/entity.h>
#include <uf/engine/scene/scene.h>
namespace ext {
class EXT_API RayTracingSceneBehavior {
public:
static void attach( uf::Object& );
static void initialize( uf::Object& );
static void tick( uf::Object& );
static void render( uf::Object& );
static void destroy( uf::Object& );
};
}

View File

@ -1,35 +0,0 @@
#include "behavior_test.h"
#include <iostream>
#define this (&self)
void ext::TestBehavior::attach( uf::Object& self ) {
self.addBehavior({
.type = uf::Behaviors::getType<ext::TestBehavior>(),
.initialize = [&]() {
ext::TestBehavior::initialize( self );
},
.tick = [&]() {
ext::TestBehavior::tick( self );
},
.render = [&]() {
ext::TestBehavior::render( self );
},
.destroy = [&]() {
ext::TestBehavior::destroy( self );
},
});
}
void ext::TestBehavior::initialize( uf::Object& self ) {
}
void ext::TestBehavior::tick( uf::Object& self ) {
}
void ext::TestBehavior::render( uf::Object& self ) {
}
void ext::TestBehavior::destroy( uf::Object& self ) {
}
#undef this

View File

@ -22,19 +22,9 @@
#include "../../ext.h"
#include "../../gui/gui.h"
#include "behavior_test.h"
EXT_OBJECT_REGISTER_CPP(TestScene_Map)
void ext::TestScene_Map::initialize() {
ext::Scene::initialize();
{
uf::Object* object = new uf::Object;
this->addChild(*object);
ext::TestBehavior::attach( *object );
object->initialize();
}
}
void ext::TestScene_Map::render() {

View File

@ -21,7 +21,7 @@
#include "../../ext.h"
#include "../../gui/gui.h"
EXT_OBJECT_REGISTER_CPP(TestScene_RayTracing)
// EXT_OBJECT_REGISTER_CPP(TestScene_RayTracing)
void ext::TestScene_RayTracing::initialize() {
ext::Scene::initialize();
uf::Serializer& metadata = this->getComponent<uf::Serializer>();