Commit for 2020.09.28.7z
This commit is contained in:
parent
a97418d88e
commit
de44c37a44
8
Makefile
8
Makefile
@ -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)
|
||||
@ -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"
|
||||
45
engine/inc/uf/engine/behavior/macros.inl
Normal file
45
engine/inc/uf/engine/behavior/macros.inl
Normal 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 )\
|
||||
|
||||
5
engine/inc/uf/engine/entity/behavior.h
Normal file
5
engine/inc/uf/engine/entity/behavior.h
Normal file
@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
namespace uf {
|
||||
UF_BEHAVIOR_ENTITY_H(Entity)
|
||||
}
|
||||
@ -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"
|
||||
@ -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"
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
*/
|
||||
61
engine/inc/uf/engine/instantiator/macros.inl
Normal file
61
engine/inc/uf/engine/instantiator/macros.inl
Normal 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()\
|
||||
});\
|
||||
}
|
||||
5
engine/inc/uf/engine/object/behavior.h
Normal file
5
engine/inc/uf/engine/object/behavior.h
Normal file
@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
namespace uf {
|
||||
UF_BEHAVIOR_ENTITY_H(Object)
|
||||
}
|
||||
@ -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"
|
||||
5
engine/inc/uf/engine/scene/behavior.h
Normal file
5
engine/inc/uf/engine/scene/behavior.h
Normal file
@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
namespace uf {
|
||||
UF_BEHAVIOR_ENTITY_H(Scene)
|
||||
}
|
||||
@ -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"
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
35
engine/src/engine/entity/behavior.cpp
Normal file
35
engine/src/engine/entity/behavior.cpp
Normal 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)
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
112
engine/src/engine/object/behavior.cpp
Normal file
112
engine/src/engine/object/behavior.cpp
Normal 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)
|
||||
@ -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";
|
||||
|
||||
22
engine/src/engine/scene/behavior.cpp
Normal file
22
engine/src/engine/scene/behavior.cpp
Normal 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)
|
||||
@ -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
374
ext/behaviors/base/base.cpp
Normal 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
|
||||
@ -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& );
|
||||
210
ext/behaviors/scene_raytracing/behavior.cpp
Normal file
210
ext/behaviors/scene_raytracing/behavior.cpp
Normal 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
|
||||
17
ext/behaviors/scene_raytracing/behavior.h
Normal file
17
ext/behaviors/scene_raytracing/behavior.h
Normal 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& );
|
||||
};
|
||||
}
|
||||
@ -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
|
||||
@ -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() {
|
||||
|
||||
@ -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>();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user