- Refactor on component system to support multiple scenes.
- node2d for 2d scenes
This commit is contained in:
@@ -92,6 +92,8 @@ add_library(fennec STATIC
|
||||
# SCENE ================================================================================================================
|
||||
include/fennec/scene/scene.h
|
||||
include/fennec/scene/component.h
|
||||
include/fennec/scene/scene_node.h
|
||||
include/fennec/scene/node2d.h
|
||||
|
||||
|
||||
# Renderers ============================================================================================================
|
||||
@@ -217,9 +219,10 @@ add_library(fennec STATIC
|
||||
# langproc ================================================================================================================
|
||||
|
||||
# Strings
|
||||
include/fennec/langproc/strings/cstring.h
|
||||
include/fennec/langproc/strings/locale.h
|
||||
include/fennec/langproc/strings/cstring.h
|
||||
include/fennec/langproc/strings/string.h
|
||||
include/fennec/langproc/strings/format.h
|
||||
|
||||
include/fennec/langproc/strings/detail/_ctype.h
|
||||
|
||||
@@ -244,8 +247,6 @@ add_library(fennec STATIC
|
||||
# EXTRA SOURCES ========================================================================================================
|
||||
|
||||
${FENNEC_EXTRA_SOURCES}
|
||||
include/fennec/langproc/strings/format.h
|
||||
include/fennec/scene/components/transform2d.h
|
||||
)
|
||||
|
||||
add_dependencies(fennec metaprogramming fennec-dependencies)
|
||||
|
||||
@@ -48,7 +48,8 @@ struct object_pool {
|
||||
// Definitions =========================================================================================================
|
||||
public:
|
||||
using value_t = TypeT;
|
||||
using table_t = allocation<value_t, AllocT>;
|
||||
using elem_t = optional<value_t>;
|
||||
using table_t = dynarray<elem_t, AllocT>;
|
||||
using freed_t = list<size_t, AllocT>;
|
||||
|
||||
|
||||
@@ -119,7 +120,8 @@ public:
|
||||
/// \returns a reference to the object with id `i`
|
||||
constexpr value_t& operator[](size_t i) {
|
||||
assert(i < capacity(), "Index out of Bounds!");
|
||||
return _table[i];
|
||||
assert(_table[i], "Attempted to access null object.")
|
||||
return *_table[i];
|
||||
}
|
||||
|
||||
///
|
||||
@@ -128,7 +130,8 @@ public:
|
||||
/// \returns a const-qualified reference to the object with id `i`
|
||||
constexpr const value_t& operator[](size_t i) const {
|
||||
assert(i < capacity(), "Index out of Bounds!");
|
||||
return _table[i];
|
||||
assert(_table[i], "Attempted to access null object.")
|
||||
return *_table[i];
|
||||
}
|
||||
|
||||
/// @}
|
||||
@@ -169,7 +172,7 @@ public:
|
||||
/// \brief Erase an object from the pool
|
||||
/// \param i The id of the object
|
||||
constexpr void erase(size_t i) {
|
||||
fennec::destruct(&_table[i]);
|
||||
_table[i] = nullopt;
|
||||
_freed.push_back(i);
|
||||
--_size;
|
||||
}
|
||||
@@ -177,8 +180,11 @@ public:
|
||||
///
|
||||
/// \brief Clear the object pool
|
||||
constexpr void clear() {
|
||||
dynarray<bool> free(capacity(), false);
|
||||
for (auto& it : _table) {
|
||||
it = nullopt;
|
||||
}
|
||||
_size = 0;
|
||||
_freed.clear();
|
||||
}
|
||||
|
||||
/// @}
|
||||
@@ -201,10 +207,10 @@ private:
|
||||
template<typename...ArgsT>
|
||||
size_t _insert(ArgsT&&...args) {
|
||||
size_t i = _next_free();
|
||||
if (i >= _table.capacity()) {
|
||||
_table.creallocate(fennec::max(_table.size() * 2, size_t(8)));
|
||||
if (i >= _table.size()) {
|
||||
_table.resize(fennec::max(_table.size() * 2, size_t(8)));
|
||||
}
|
||||
fennec::construct(&_table[i], fennec::forward<ArgsT>(args)...);
|
||||
_table[i].emplace(fennec::forward<ArgsT>(args)...);
|
||||
return i;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -58,7 +58,7 @@ public:
|
||||
|
||||
protected:
|
||||
struct node {
|
||||
optional<value_t> value;
|
||||
value_t value;
|
||||
size_t parent, child, prev, next;
|
||||
size_t depth, num_children;
|
||||
|
||||
@@ -315,25 +315,15 @@ public:
|
||||
///
|
||||
/// \param i The id of the node to access
|
||||
/// \returns A reference to the value of the node wrapped in an optional
|
||||
constexpr value_t* operator[](size_t i) {
|
||||
auto& it = _table[i].value;
|
||||
if (it) {
|
||||
return &*_table[i].value;
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
constexpr value_t& operator[](size_t i) {
|
||||
return _table[i].value;
|
||||
}
|
||||
|
||||
///
|
||||
/// \param i The id of the node to access
|
||||
/// \returns A const-qualified reference to the value of the node wrapped in an optional
|
||||
constexpr const value_t* operator[](size_t i) const {
|
||||
const auto& it = _table[i].value;
|
||||
if (it) {
|
||||
return &*_table[i].value;
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
constexpr const value_t& operator[](size_t i) const {
|
||||
return _table[i].value;
|
||||
}
|
||||
|
||||
|
||||
@@ -420,7 +410,7 @@ public:
|
||||
while (i != npos) {
|
||||
uint8_t mode = traversal_control_continue;
|
||||
if (_table[i].value) {
|
||||
mode = visit(*_table[i].value, i);
|
||||
mode = visit(_table[i].value, i);
|
||||
}
|
||||
if (mode == traversal_control_break) {
|
||||
break;
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
#define FENNEC_LANGPROC_FORMAT_TOKENIZER_H
|
||||
|
||||
#include <fennec/containers/list.h>
|
||||
#include <fennec/containers/map.h>
|
||||
#include <fennec/containers/priority_queue.h>
|
||||
#include <fennec/langproc/strings/string.h>
|
||||
|
||||
//
|
||||
@@ -55,7 +57,7 @@ namespace fennec
|
||||
{
|
||||
|
||||
struct escape_sequence {
|
||||
virtual size_t operator[](const std::string& str, size_t i) = 0;
|
||||
virtual size_t operator[](const string& str, size_t i) = 0;
|
||||
};
|
||||
|
||||
struct tokenizer {
|
||||
@@ -91,12 +93,12 @@ private:
|
||||
list<token> res;
|
||||
priority_queue<pair<size_t, uint8_t>> idx;
|
||||
|
||||
for (size_t i = 0; i < line.size(); ++i) {
|
||||
|
||||
for (char c : delimiter) {
|
||||
idx.emplace()
|
||||
size_t i = 0;
|
||||
while (i != line.size()) {
|
||||
size_t n = line.find(c, i);
|
||||
// TODO
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#ifndef FENNEC_LANGPROC_IO_PATH_H
|
||||
#define FENNEC_LANGPROC_IO_PATH_H
|
||||
|
||||
#include <fennec/langproc/filesystem/path.h>
|
||||
#include <fennec/langproc/strings/string.h>
|
||||
|
||||
namespace fennec
|
||||
@@ -32,6 +33,12 @@ namespace fennec
|
||||
struct path
|
||||
{
|
||||
public:
|
||||
// Definitions =========================================================================================================
|
||||
|
||||
class iterator;
|
||||
friend iterator;
|
||||
|
||||
|
||||
// Static Functions ====================================================================================================
|
||||
|
||||
/// \brief Get the current working directory
|
||||
@@ -154,6 +161,11 @@ public:
|
||||
return _str == p._str;
|
||||
}
|
||||
|
||||
string filename() const {
|
||||
size_t i = _str.rfind('/');
|
||||
return _str.substring(i + 1);
|
||||
}
|
||||
|
||||
const string& str() const { return _str; }
|
||||
const char* cstr() const { return _str.cstr(); }
|
||||
|
||||
@@ -238,6 +250,81 @@ public:
|
||||
return working;
|
||||
}
|
||||
|
||||
|
||||
// Iterator ============================================================================================================
|
||||
|
||||
iterator begin() const {
|
||||
return iterator(this, 0);
|
||||
}
|
||||
|
||||
iterator end() const {
|
||||
return iterator(this, _str.size());
|
||||
}
|
||||
|
||||
class iterator {
|
||||
public:
|
||||
constexpr iterator(const path* path, size_t p)
|
||||
: _str(&path->_str)
|
||||
, _pos(p) {
|
||||
|
||||
// Handle end()
|
||||
if (p == _str->size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle rooted paths
|
||||
#ifdef FENNEC_PLATFORM_WINDOWS
|
||||
if ((*_str)[1] == ':') {
|
||||
_pos = max(_pos, size_t(3));
|
||||
}
|
||||
#else
|
||||
if ((*_str)[0] == '/') {
|
||||
_pos = max(_pos, size_t(1));
|
||||
}
|
||||
#endif
|
||||
|
||||
// Ensure we are at the start of a directory/file name
|
||||
if (_pos != 0 && (*_str)[_pos - 1] != '/') {
|
||||
_pos = _str->find('/', _pos) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr iterator(const iterator&) = default;
|
||||
constexpr iterator(iterator&&) noexcept = default;
|
||||
|
||||
constexpr string operator*() const {
|
||||
if ((*_str)[_pos] == '/') {
|
||||
return string("");
|
||||
}
|
||||
|
||||
size_t e = _str->find('/', _pos);
|
||||
return _str->substring(_pos, e - _pos);
|
||||
}
|
||||
|
||||
constexpr iterator& operator++() {
|
||||
_pos = min(_str->find('/', _pos) + 1, _str->size());
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr iterator operator++(int) {
|
||||
iterator it = *this;
|
||||
this->operator++();
|
||||
return it;
|
||||
}
|
||||
|
||||
constexpr bool operator==(const iterator& rhs) const {
|
||||
return _str == rhs._str and _pos == rhs._pos;
|
||||
}
|
||||
|
||||
constexpr bool operator!=(const iterator& rhs) const {
|
||||
return _str != rhs._str or _pos != rhs._pos;
|
||||
}
|
||||
|
||||
private:
|
||||
const string* _str;
|
||||
size_t _pos;
|
||||
};
|
||||
|
||||
private:
|
||||
string _str;
|
||||
};
|
||||
|
||||
@@ -627,7 +627,7 @@ public:
|
||||
return _data;
|
||||
}
|
||||
|
||||
private:
|
||||
protected:
|
||||
alloc_t _alloc; // Allocator object
|
||||
value_t* _data; // Handle for the memory block
|
||||
size_t _capacity; // Capacity of the memory block in elements.
|
||||
|
||||
@@ -21,19 +21,27 @@
|
||||
|
||||
#include <fennec/containers/dynarray.h>
|
||||
#include <fennec/containers/map.h>
|
||||
#include <fennec/containers/object_pool.h>
|
||||
#include <fennec/containers/optional.h>
|
||||
#include <fennec/containers/rdtree.h>
|
||||
#include <fennec/langproc/strings/string.h>
|
||||
#include <fennec/lang/typed.h>
|
||||
#include <fennec/langproc/filesystem/path.h>
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
class component : typed<component> {
|
||||
struct component_t {
|
||||
uint64_t type;
|
||||
size_t id;
|
||||
};
|
||||
|
||||
class component : public typed<component> {
|
||||
public:
|
||||
|
||||
// TYPEDEFS & CONSTANTS ================================================================================================
|
||||
using component_create = component (*)(size_t);
|
||||
using component_find = component* (*)(size_t);
|
||||
using component_create = size_t (*)(size_t, size_t);
|
||||
using component_get = component* (*)(size_t);
|
||||
using component_destroy = void (*)(size_t);
|
||||
using component_tick = void (*)(size_t, double);
|
||||
using component_frame = void (*)(size_t, uint64_t);
|
||||
@@ -41,44 +49,146 @@ public:
|
||||
|
||||
// TYPE OPERATIONS =====================================================================================================
|
||||
|
||||
struct type_info {
|
||||
struct typeinfo {
|
||||
string name;
|
||||
component_create create;
|
||||
component_find find;
|
||||
component_destroy destroy;
|
||||
component_get get;
|
||||
component_tick tick;
|
||||
component_frame frame;
|
||||
|
||||
typeinfo()
|
||||
: name("")
|
||||
, create(nullptr), destroy(nullptr)
|
||||
, get(nullptr)
|
||||
, tick(nullptr), frame(nullptr) {
|
||||
}
|
||||
|
||||
typeinfo(const string& name,
|
||||
component_create create, component_destroy destroy,
|
||||
component_get get,
|
||||
component_tick tick, component_frame frame)
|
||||
: name(name)
|
||||
, create(create), destroy(destroy), get(get)
|
||||
, tick(tick), frame(frame) {
|
||||
}
|
||||
};
|
||||
|
||||
struct typeentry {
|
||||
string name;
|
||||
uint64_t id;
|
||||
};
|
||||
|
||||
using typelist_t = dynarray<optional<typeinfo>>;
|
||||
using typetree_t = rdtree<typeentry>;
|
||||
|
||||
|
||||
// Private Registry ====================================================================================================
|
||||
private:
|
||||
// Private Registry
|
||||
|
||||
static auto& _type_list() {
|
||||
static dynarray<optional<type_info>> type_list;
|
||||
return type_list;
|
||||
}
|
||||
static typelist_t _typelist; // Actual list of types
|
||||
static typetree_t _typetree; // Tree for displaying types under subfolders
|
||||
|
||||
static void _register_type( uint64_t id, const cstring& name,
|
||||
component_create create, component_find find, component_destroy destroy,
|
||||
static constexpr size_t npos = typetree_t::npos;
|
||||
static constexpr size_t root = typetree_t::root;
|
||||
|
||||
static void _register_type( uint64_t id, const path& path,
|
||||
component_create create, component_destroy destroy,
|
||||
component_get get,
|
||||
component_tick tick, component_frame frame) {
|
||||
auto& type_list = _type_list();
|
||||
if (id > type_list.size()) {
|
||||
type_list.resize(id + 1);
|
||||
// Register the type
|
||||
if (id > _typelist.size()) {
|
||||
_typelist.resize(id + 1);
|
||||
}
|
||||
type_list[id] = type_info{ name, create, find, destroy, tick, frame };
|
||||
_typelist[id] = typeinfo{ path.filename(), create, destroy, get, tick, frame };
|
||||
|
||||
// Create tree entry
|
||||
size_t node = root;
|
||||
path::iterator it = path.begin();
|
||||
while (it != path.end()) {
|
||||
string name = *it++;
|
||||
size_t parent = node;
|
||||
bool end = it == path.end();
|
||||
|
||||
node = _typetree.child(parent);
|
||||
|
||||
while (node != npos && _typetree[node].id != id) {
|
||||
node = _typetree.next(node);
|
||||
}
|
||||
|
||||
static void _unregister_type(uint64_t id) {
|
||||
_type_list()[id] = nullopt;
|
||||
if (node == npos) {
|
||||
node = _typetree.emplace(
|
||||
parent, npos,
|
||||
name, end ? id : nullid
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static auto& _default_storage() {
|
||||
static map<uint64_t, map<size_t, component*>> data;
|
||||
return data;
|
||||
struct noderef {
|
||||
size_t scene, node;
|
||||
};
|
||||
|
||||
using compstorage_t = object_pool<component*>; // Holds refs to default allocated components
|
||||
using defaultstorage_t = map<uint64_t, compstorage_t>; // Maps types to respective storage
|
||||
|
||||
inline static defaultstorage_t _default_storage;
|
||||
|
||||
static auto& _type_info(uint64_t type) {
|
||||
return _typelist[type];
|
||||
}
|
||||
|
||||
template<typename ComponentT>
|
||||
static auto& _type_info() {
|
||||
return _typelist[uuid<ComponentT>()];
|
||||
}
|
||||
|
||||
static auto& _type_storage(uint64_t type) {
|
||||
return *_default_storage[type];
|
||||
}
|
||||
|
||||
template<typename ComponentT>
|
||||
static auto& _type_storage() {
|
||||
return *_default_storage[uuid<ComponentT>()];
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Default creation function for a component
|
||||
/// \tparam ComponentT Type of the component
|
||||
/// \param node The node to associate the component with
|
||||
/// \returns The component created by this function
|
||||
template<typename ComponentT>
|
||||
static constexpr component* default_create(size_t scene, size_t node) {
|
||||
auto& storage = _type_storage<ComponentT>();
|
||||
return storage.insert(new ComponentT(scene, node));
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Default destruction function for a component
|
||||
/// \tparam ComponentT Type of the component
|
||||
/// \param node The node the component is associated with
|
||||
template<typename ComponentT>
|
||||
static constexpr void default_destroy(size_t comp) {
|
||||
auto& storage = _type_storage<ComponentT>();
|
||||
|
||||
delete storage[comp];
|
||||
storage.erase(comp);
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Default retrieval function for a component
|
||||
/// \tparam ComponentT Type of the component
|
||||
/// \param node The node the component is associated with
|
||||
/// \returns The component found by this function
|
||||
template<typename ComponentT>
|
||||
static constexpr component* default_get(size_t comp) {
|
||||
auto& storage = _type_storage<ComponentT>();
|
||||
return storage[comp];
|
||||
}
|
||||
|
||||
|
||||
// Public Registry =====================================================================================================
|
||||
public:
|
||||
// Public Registry
|
||||
|
||||
///
|
||||
/// \brief Get an uuid for the specified component type
|
||||
@@ -89,66 +199,30 @@ public:
|
||||
return typeuuid<ComponentT, component>();
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Default storage function for default creation, retrieval, and destruction
|
||||
template<typename ComponentT>
|
||||
static constexpr auto& default_storage() {
|
||||
auto& data = _default_storage();
|
||||
return data[uuid<ComponentT>()];
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Default creation function for a component
|
||||
/// \tparam ComponentT Type of the component
|
||||
/// \param node The node to associate the component with
|
||||
/// \returns The component created by this function
|
||||
template<typename ComponentT>
|
||||
static constexpr component* default_create(size_t node) {
|
||||
auto& storage = default_storage<ComponentT>();
|
||||
if (not storage[node]) {
|
||||
storage.emplace(node);
|
||||
}
|
||||
return storage[node];
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Default retrieval function for a component
|
||||
/// \tparam ComponentT Type of the component
|
||||
/// \param node The node the component is associated with
|
||||
/// \returns The component found by this function
|
||||
template<typename ComponentT>
|
||||
static constexpr component* default_find(size_t node) {
|
||||
auto& storage = default_storage<ComponentT>();
|
||||
return storage[node];
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Default destruction function for a component
|
||||
/// \tparam ComponentT Type of the component
|
||||
/// \param node The node the component is associated with
|
||||
template<typename ComponentT>
|
||||
static constexpr void default_destroy(size_t node) {
|
||||
default_storage<ComponentT>().erase(node);
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Register a type with the component system
|
||||
/// \tparam ComponentT The component type
|
||||
/// \param name The name of the type
|
||||
/// \param create The function used to create a component, given a scene node. **MUST NOT BE NULL**
|
||||
/// \param find The function used to find a component, given a scene node. **MUST NOT BE NULL**
|
||||
/// \param get The function used to find a component, given a scene node. **MUST NOT BE NULL**
|
||||
/// \param destroy The function used to destroy a component of a scene node. **MUST NOT BE NULL**
|
||||
template<typename ComponentT>
|
||||
static void register_type(const cstring& name, component_tick tick, component_frame frame,
|
||||
static void register_type(const cstring& name,
|
||||
component_tick tick, component_frame frame,
|
||||
component_create create = default_create<ComponentT>,
|
||||
component_find find = default_find<ComponentT>,
|
||||
component_get get = default_get<ComponentT>,
|
||||
component_destroy destroy = default_destroy<ComponentT>) {
|
||||
component::_register_type(uuid<ComponentT>(), name, create, find, destroy, tick, frame);
|
||||
component::_register_type(uuid<ComponentT>(), name, create, destroy, get, tick, frame);
|
||||
}
|
||||
|
||||
template<typename ComponentT>
|
||||
static void unregister_type() {
|
||||
component::_unregister_type(uuid<ComponentT>());
|
||||
///
|
||||
/// \brief Create a component of type `type`
|
||||
/// \param type The type to create
|
||||
/// \param node The node to associate the component with
|
||||
/// \returns The created component
|
||||
static size_t create(uint64_t type, size_t scene, size_t node) {
|
||||
auto& typei = _typelist[type];
|
||||
return typei->create(scene, node);
|
||||
}
|
||||
|
||||
///
|
||||
@@ -157,42 +231,60 @@ public:
|
||||
/// \param node The node to associate the component with
|
||||
/// \returns The created component
|
||||
template<typename ComponentT>
|
||||
static component* create(size_t node) {
|
||||
auto& type = _type_list()[uuid<ComponentT>()];
|
||||
return type ? *type->create(node) : nullptr;
|
||||
static size_t create(size_t scene, size_t node) {
|
||||
auto& typei = _typelist[uuid<ComponentT>()];
|
||||
return typei->create(scene, node);
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Get a component of type `type` from id `id`
|
||||
/// \param type The type of component
|
||||
/// \param id The id of the component instance
|
||||
/// \return
|
||||
static component* get(uint64_t type, size_t id) {
|
||||
auto& typei = _typelist[type];
|
||||
return typei->get(id);
|
||||
}
|
||||
|
||||
template<typename ComponentT>
|
||||
static component* find(size_t node) {
|
||||
auto& type = _type_list()[uuid<ComponentT>()];
|
||||
return type ? *type->find(node) : nullptr;
|
||||
static component* get(size_t comp) {
|
||||
auto& typei = _typelist[uuid<ComponentT>()];
|
||||
return typei->get(comp);
|
||||
}
|
||||
|
||||
static void destroy(size_t type, size_t comp) {
|
||||
auto& typei = _typelist[type];
|
||||
return typei->destroy(comp);
|
||||
}
|
||||
|
||||
template<typename ComponentT>
|
||||
static void destroy(size_t node) {
|
||||
auto& type = _type_list()[uuid<ComponentT>()];
|
||||
return type ? *type->destroy(node) : nullptr;
|
||||
static void destroy(size_t comp) {
|
||||
auto& typei = _typelist[uuid<ComponentT>()];
|
||||
return typei->destroy(comp);
|
||||
}
|
||||
|
||||
static void tick(size_t node, double dT) {
|
||||
for (auto& it : _type_list()) {
|
||||
it->tick(node, dT);
|
||||
static void tick(size_t comp, double dT) {
|
||||
for (auto& it : _typelist) {
|
||||
if (it->tick) {
|
||||
it->tick(comp, dT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void frame(size_t node, uint64_t f) {
|
||||
for (auto& it : _type_list()) {
|
||||
it->tick(node, f);
|
||||
static void frame(size_t comp, uint64_t f) {
|
||||
for (auto& it : _typelist) {
|
||||
if (it->frame) {
|
||||
it->frame(comp, f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const auto& type_list() {
|
||||
return _type_list();
|
||||
return _typelist;
|
||||
}
|
||||
|
||||
// MEMBERS =============================================================================================================
|
||||
public:
|
||||
const type_info* type;
|
||||
const size_t node;
|
||||
|
||||
template<typename ComponentT>
|
||||
|
||||
@@ -33,12 +33,12 @@
|
||||
|
||||
#include <fennec/math/matrix.h>
|
||||
#include <fennec/math/ext/transform.h>
|
||||
#include <fennec/scene/component.h>
|
||||
#include <fennec/scene/scene_node.h>
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
struct transform2d : component {
|
||||
struct node2d : scene_node {
|
||||
// Definitions =========================================================================================================
|
||||
|
||||
enum mobility_ : bool {
|
||||
@@ -52,34 +52,19 @@ public:
|
||||
|
||||
///
|
||||
/// \brief Default Constructor, initializes an identity matrix.
|
||||
transform2d(size_t node)
|
||||
: component(this, node)
|
||||
node2d(size_t id, size_t scene, const string& name)
|
||||
: scene_node(name, id, scene)
|
||||
, _mobility(mobility_free)
|
||||
, _position(0, 0)
|
||||
, _scale(1, 1)
|
||||
, _shear(0, 0)
|
||||
, _rotation(0) {
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Component Constructor, composes the internal matrix using the components.
|
||||
/// \param pos Position as vec2
|
||||
/// \param scl Scale as vec2
|
||||
/// \param rot Rotation as degrees
|
||||
/// \param skw Skew as vec2
|
||||
transform2d(size_t node, const vec2& pos, const vec2& scl, float rot, const vec2& skw = vec2(0, 0))
|
||||
: component(this, node)
|
||||
, _position(pos)
|
||||
, _scale(scl)
|
||||
, _shear(skw)
|
||||
, _rotation(rot)
|
||||
, _dirty(true)
|
||||
, _local(matrix()) {
|
||||
}
|
||||
node2d(const node2d&) = default;
|
||||
node2d(node2d&&) noexcept = default;
|
||||
|
||||
transform2d(const transform2d&) = default;
|
||||
transform2d(transform2d&&) noexcept = default;
|
||||
|
||||
~transform2d() = default;
|
||||
~node2d() = default;
|
||||
|
||||
// Access ==============================================================================================================
|
||||
|
||||
@@ -99,53 +84,79 @@ public:
|
||||
return _shear;
|
||||
}
|
||||
|
||||
constexpr bool mobility() const {
|
||||
return _mobility;
|
||||
}
|
||||
|
||||
|
||||
// Modifiers ===========================================================================================================
|
||||
|
||||
constexpr void translate(const vec2& x) {
|
||||
if (_mobility) {
|
||||
_position += x;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr void scale(const vec2& s) {
|
||||
if (_mobility) {
|
||||
_scale *= s;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr void rotate(float r) {
|
||||
if (_mobility) {
|
||||
_rotation += r;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr void shear(const vec2& s) {
|
||||
if (_mobility) {
|
||||
_shear += s;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr void commit() {
|
||||
if (not _dirty) {
|
||||
if (not _mobility) {
|
||||
return;
|
||||
}
|
||||
|
||||
_local = fennec::rotation(_rotation);
|
||||
_local *= fennec::shear(_shear);
|
||||
_local *= fennec::scaling(_scale);
|
||||
_local *= fennec::translation(_position);
|
||||
// Get parent
|
||||
|
||||
|
||||
_recalculate();
|
||||
|
||||
|
||||
// Propagate down
|
||||
|
||||
}
|
||||
|
||||
constexpr const mat3& local() {
|
||||
commit();
|
||||
return _local;
|
||||
}
|
||||
|
||||
constexpr const mat3& global() {
|
||||
|
||||
return _global;
|
||||
}
|
||||
|
||||
// Fields ==============================================================================================================
|
||||
private:
|
||||
bool _mobility;
|
||||
vec2 _position;
|
||||
vec2 _scale;
|
||||
vec2 _shear;
|
||||
float _rotation;
|
||||
bool _dirty;
|
||||
mat3 _local;
|
||||
mat3 _local, _global;
|
||||
|
||||
|
||||
// Helpers =============================================================================================================
|
||||
|
||||
constexpr void _recalculate(const mat3& parent) {
|
||||
_local = fennec::rotation(_rotation);
|
||||
_local *= fennec::shear(_shear);
|
||||
_local *= fennec::scaling(_scale);
|
||||
_local *= fennec::translation(_position);
|
||||
_global = parent * _local;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -20,7 +20,10 @@
|
||||
#define FENNEC_CORE_SCENE_H
|
||||
|
||||
#include <fennec/containers/rdtree.h>
|
||||
#include <fennec/lang/typed.h>
|
||||
#include <fennec/langproc/strings/string.h>
|
||||
#include <fennec/scene/scene_node.h>
|
||||
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
@@ -30,9 +33,10 @@ namespace fennec
|
||||
/// \details This structure only contains the names of nodes and defers storage for components to
|
||||
/// their respective systems. Simple components may be isolated, \see components.h for more info.
|
||||
/// The hierarchy should be displayed using pre-order traversal.
|
||||
class scene : public rdtree<string> {
|
||||
public:
|
||||
class scene : public rdtree<scene_node*> {
|
||||
|
||||
// Access ==============================================================================================================
|
||||
public:
|
||||
///
|
||||
/// \brief Find a node by name.
|
||||
/// \details If multiple nodes have the same name, finds the first one in pre-order traversal.
|
||||
@@ -42,13 +46,14 @@ public:
|
||||
list<size_t> parse;
|
||||
parse.push_back(root);
|
||||
while (not parse.empty()) {
|
||||
if (*_data[parse.front()].value == name) {
|
||||
return parse.front();
|
||||
size_t n = parse.front();
|
||||
if (_table[n].value->name == name) {
|
||||
return n;
|
||||
}
|
||||
|
||||
// Pre-Order traversal
|
||||
parse.push_front(next(parse.front()));
|
||||
parse.push_front(child(parse.front()));
|
||||
parse.push_front(next(n));
|
||||
parse.push_front(child(n));
|
||||
parse.pop_front();
|
||||
}
|
||||
return npos;
|
||||
@@ -63,13 +68,14 @@ public:
|
||||
list<size_t> parse;
|
||||
parse.push_back(root);
|
||||
while (not parse.empty()) {
|
||||
if (*_data[parse.front()].value == name) {
|
||||
return parse.front();
|
||||
size_t n = parse.front();
|
||||
if (_table[n].value->name == name) {
|
||||
return n;
|
||||
}
|
||||
|
||||
// Pre-Order traversal
|
||||
parse.push_front(next(parse.front()));
|
||||
parse.push_front(child(parse.front()));
|
||||
parse.push_front(next(n));
|
||||
parse.push_front(child(n));
|
||||
parse.pop_front();
|
||||
}
|
||||
return npos;
|
||||
|
||||
56
include/fennec/scene/scene_node.h
Normal file
56
include/fennec/scene/scene_node.h
Normal file
@@ -0,0 +1,56 @@
|
||||
// =====================================================================================================================
|
||||
// fennec, a free and open source game engine
|
||||
// Copyright © 2025 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
///
|
||||
/// \file node.h
|
||||
/// \brief
|
||||
///
|
||||
///
|
||||
/// \details
|
||||
/// \author Medusa Slockbower
|
||||
///
|
||||
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||
///
|
||||
///
|
||||
|
||||
#ifndef FENNEC_SCENE_NODE_H
|
||||
#define FENNEC_SCENE_NODE_H
|
||||
|
||||
#include <fennec/lang/typed.h>
|
||||
#include <fennec/langproc/strings/string.h>
|
||||
#include <fennec/scene/component.h>
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
struct scene_node : typed<scene_node> {
|
||||
const size_t scene;
|
||||
const size_t id;
|
||||
string name;
|
||||
|
||||
scene_node(size_t id, size_t scene, const string& name)
|
||||
: id(id), scene(scene), name(name) {
|
||||
}
|
||||
|
||||
private:
|
||||
dynarray<component_t> _components;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_SCENE_NODE_H
|
||||
Reference in New Issue
Block a user