- Adjustments to component system design.
- Added indexed parameters to format strings
This commit is contained in:
@@ -247,6 +247,7 @@ add_library(fennec STATIC
|
|||||||
# EXTRA SOURCES ========================================================================================================
|
# EXTRA SOURCES ========================================================================================================
|
||||||
|
|
||||||
${FENNEC_EXTRA_SOURCES}
|
${FENNEC_EXTRA_SOURCES}
|
||||||
|
include/fennec/gfx3d/mesh_instance.h
|
||||||
)
|
)
|
||||||
|
|
||||||
add_dependencies(fennec metaprogramming fennec-dependencies)
|
add_dependencies(fennec metaprogramming fennec-dependencies)
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
# this script sets flags and variables for gnu and gnu-like compilers
|
# this script sets flags and variables for gnu and gnu-like compilers
|
||||||
|
|
||||||
add_compile_options("-Wall" "-Wextra" "-pedantic" "-Werror")
|
add_compile_options("-Wall" "-Wextra" "-pedantic" "-Werror" "-fms-extensions")
|
||||||
|
|
||||||
fennec_add_link_options("-nostdlib" "-fno-exceptions" "-fno-rtti" "-fdiagnostics-all-candidates")
|
fennec_add_link_options("-nostdlib" "-fno-exceptions" "-fno-rtti" "-fdiagnostics-all-candidates")
|
||||||
|
|
||||||
|
|||||||
47
include/fennec/gfx3d/mesh_instance.h
Normal file
47
include/fennec/gfx3d/mesh_instance.h
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
// =====================================================================================================================
|
||||||
|
// 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 mesh_instance.h
|
||||||
|
/// \brief
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// \details
|
||||||
|
/// \author Medusa Slockbower
|
||||||
|
///
|
||||||
|
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
|
||||||
|
///
|
||||||
|
///
|
||||||
|
|
||||||
|
#ifndef FENNEC_GFX3D_MESH_INSTANCE_H
|
||||||
|
#define FENNEC_GFX3D_MESH_INSTANCE_H
|
||||||
|
#include <fennec/scene/component.h>
|
||||||
|
|
||||||
|
namespace fennec
|
||||||
|
{
|
||||||
|
|
||||||
|
class mesh_instance : component {
|
||||||
|
public:
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FENNEC_GFX3D_MESH_INSTANCE_H
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
#define FENNEC_LANG_STARTUP_H
|
#define FENNEC_LANG_STARTUP_H
|
||||||
|
|
||||||
// Helper for running a function before main()
|
// Helper for running a function before main()
|
||||||
#define STATIC_CONSTRUCTOR(f) \
|
#define FENNEC_STATIC_CONSTRUCTOR(f) \
|
||||||
inline static void f(void); \
|
inline static void f(void); \
|
||||||
struct f##_t_ { inline f##_t_(void) { f(); } }; inline static f##_t_ f##_; \
|
struct f##_t_ { inline f##_t_(void) { f(); } }; inline static f##_t_ f##_; \
|
||||||
inline static void f(void)
|
inline static void f(void)
|
||||||
|
|||||||
@@ -54,6 +54,11 @@ public:
|
|||||||
typed(TypeT*)
|
typed(TypeT*)
|
||||||
: type(typeuuid<TypeT, RootT>()) {
|
: type(typeuuid<TypeT, RootT>()) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename TypeT>
|
||||||
|
static uint64_t id() {
|
||||||
|
return typeuuid<TypeT, RootT>();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,12 +66,16 @@ struct format_string {
|
|||||||
private:
|
private:
|
||||||
static constexpr size_t npos = -1;
|
static constexpr size_t npos = -1;
|
||||||
|
|
||||||
enum token_ : uint8_t {
|
enum token_ : bool {
|
||||||
token_text = 0,
|
token_text = false,
|
||||||
token_param,
|
token_param = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
using token = pair<uint8_t, string_view>;
|
struct token {
|
||||||
|
uint8_t type;
|
||||||
|
string_view view;
|
||||||
|
size_t param;
|
||||||
|
};
|
||||||
|
|
||||||
constexpr const char* find(const char* start, char c) {
|
constexpr const char* find(const char* start, char c) {
|
||||||
while (*start != c && *start != '\0') {
|
while (*start != c && *start != '\0') {
|
||||||
@@ -80,47 +84,64 @@ private:
|
|||||||
return start;
|
return start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr size_t parse_index(const char* start, size_t n) {
|
||||||
|
size_t x = 0;
|
||||||
|
while (n-- > 0) {
|
||||||
|
x *= 10;
|
||||||
|
x += *start - '0';
|
||||||
|
}
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Constructors & Destructor ===========================================================================================
|
// Constructors & Destructor ===========================================================================================
|
||||||
public:
|
public:
|
||||||
format_string() = delete;
|
format_string() = delete;
|
||||||
|
|
||||||
format_string(const char (&str)[N])
|
constexpr format_string(const char (&str)[N])
|
||||||
: _tokens(), _num_tokens(0) {
|
: _tokens(), _num_tokens(0) {
|
||||||
static_assert(is_constant_evaluated(), "Runtime format strings are not supported.");
|
|
||||||
|
|
||||||
// TODO: Numbered Parameters
|
// TODO: Numbered Parameters
|
||||||
|
|
||||||
size_t params = 0;
|
size_t params = 0;
|
||||||
for (size_t i = 0; i < N; ++i) {
|
for (size_t i = 0; i < N - 1; ++i) {
|
||||||
size_t n = this->find(str + i, '{') - str;
|
size_t l = this->find(str + i, '{') - str;
|
||||||
|
|
||||||
// Push the current token
|
// Push the current token
|
||||||
if (n - i > 0) {
|
if (l - i > 0) {
|
||||||
_tokens[_num_tokens++] = { token_text, { &str[i], n - i } };
|
_tokens[_num_tokens++] = { token_text, { &str[i], l - i }, npos };
|
||||||
}
|
}
|
||||||
|
|
||||||
// no more braces, break
|
// no more braces, break
|
||||||
if (n >= N) {
|
if (l >= N) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// escaped brace
|
// escaped brace
|
||||||
if (str[n + 1] == '{') {
|
if (str[l + 1] == '{') {
|
||||||
_tokens[_num_tokens++] = { token_text, { &str[n], 1 } };
|
_tokens[_num_tokens++] = { token_text, { &str[l], 1 }, npos };
|
||||||
i = n + 1;
|
i = l + 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t e = this->find(str + n, '}') - str;
|
size_t e = this->find(str + l, '}') - str;
|
||||||
//static_assert(e >= N, "Malformed format string, mismatched brace");
|
assertd(e < N, "Malformed format string, mismatched brace");
|
||||||
|
|
||||||
_tokens[_num_tokens++] = { token_param, { &str[n], e - n + 1 } };
|
// Colon found
|
||||||
++params;
|
size_t c = this->find(str + l, ':') - str;
|
||||||
|
if (c < e) {
|
||||||
|
size_t n = c - l;
|
||||||
|
if (n > 1) { // Check if index is provided
|
||||||
|
params = this->parse_index(str + l + 1, n - 1);
|
||||||
|
}
|
||||||
|
l = c;
|
||||||
|
} else if (e - l > 1) { // check if index is provided
|
||||||
|
params = this->parse_index(str + l + 1, e - l - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
assertd(params < sizeof...(ArgsT), "Malformed format string, parameter count does not match argument count.");
|
||||||
|
_tokens[_num_tokens++] = { token_param, { &str[l + 1], e - l - 1 }, params++ };
|
||||||
i = e;
|
i = e;
|
||||||
}
|
}
|
||||||
|
|
||||||
//static_assert(params == sizeof...(ArgsT), "Malformed format string, parameter count does not match argument count.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr format_string(const format_string&) = default;
|
constexpr format_string(const format_string&) = default;
|
||||||
@@ -129,33 +150,48 @@ public:
|
|||||||
~format_string() = default;
|
~format_string() = default;
|
||||||
|
|
||||||
string format(ArgsT&&...args) const {
|
string format(ArgsT&&...args) const {
|
||||||
return this->_format(0, fennec::forward<ArgsT>(args)...);
|
string parts[N];
|
||||||
|
|
||||||
|
// Copy raw text tokens
|
||||||
|
size_t i = 0;
|
||||||
|
for (i = 0; i < _num_tokens; ++i) {
|
||||||
|
const token& tok = _tokens[i];
|
||||||
|
if (not tok.type) {
|
||||||
|
parts[i] = tok.view;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy arguments
|
||||||
|
this->_format(0, parts, fennec::forward<ArgsT>(args)...);
|
||||||
|
|
||||||
|
string res;
|
||||||
|
for (i = 0; i < _num_tokens; ++i) {
|
||||||
|
res += parts[i];
|
||||||
|
}
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
array<token, N> _tokens;
|
array<token, N> _tokens;
|
||||||
size_t _num_tokens;
|
size_t _num_tokens;
|
||||||
|
|
||||||
string _format(size_t) const {
|
void _format(size_t) const {
|
||||||
return string{""};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename HeadT, typename...RestT>
|
template<typename HeadT, typename...RestT>
|
||||||
string _format(size_t i, HeadT&& head, RestT&&...rest) const {
|
void _format(size_t p, string (&parts)[N], HeadT&& head, RestT&&...rest) const {
|
||||||
string res;
|
size_t i = 0;
|
||||||
for (; i < _num_tokens; ++i) {
|
for (const token& tok : _tokens) {
|
||||||
const auto& token = _tokens[i];
|
if (i >= _num_tokens) {
|
||||||
|
|
||||||
if (token.first == token_param) {
|
|
||||||
formatter<HeadT> fmt;
|
|
||||||
res += fmt(token.second, head);
|
|
||||||
res += this->_format(i + 1, fennec::forward<RestT>(rest)...);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (tok.param == p) {
|
||||||
res += token.second;
|
formatter<HeadT> fmt;
|
||||||
|
parts[i] = fmt(tok.view, head);
|
||||||
|
}
|
||||||
|
++i;
|
||||||
}
|
}
|
||||||
return res;
|
this->_format(p + 1, fennec::forward<RestT>(rest)...);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -55,9 +55,9 @@ private:
|
|||||||
GLenum res;
|
GLenum res;
|
||||||
|
|
||||||
// Set READ/DRAW/COPY
|
// Set READ/DRAW/COPY
|
||||||
if constexpr (read) {
|
if constexpr (map_read) {
|
||||||
res = GL_STREAM_READ;
|
res = GL_STREAM_READ;
|
||||||
} else if constexpr (write) {
|
} else if constexpr (map_write) {
|
||||||
res = GL_STREAM_DRAW;
|
res = GL_STREAM_DRAW;
|
||||||
} else {
|
} else {
|
||||||
res = GL_STREAM_COPY;
|
res = GL_STREAM_COPY;
|
||||||
|
|||||||
@@ -21,30 +21,27 @@
|
|||||||
|
|
||||||
#include <fennec/containers/dynarray.h>
|
#include <fennec/containers/dynarray.h>
|
||||||
#include <fennec/containers/map.h>
|
#include <fennec/containers/map.h>
|
||||||
#include <fennec/containers/object_pool.h>
|
|
||||||
#include <fennec/containers/optional.h>
|
#include <fennec/containers/optional.h>
|
||||||
#include <fennec/containers/rdtree.h>
|
#include <fennec/containers/rdtree.h>
|
||||||
|
#include <fennec/lang/startup.h>
|
||||||
#include <fennec/langproc/strings/string.h>
|
#include <fennec/langproc/strings/string.h>
|
||||||
#include <fennec/lang/typed.h>
|
#include <fennec/lang/typed.h>
|
||||||
#include <fennec/langproc/filesystem/path.h>
|
#include <fennec/langproc/filesystem/path.h>
|
||||||
|
|
||||||
|
#define FENNEC_REGISTER_COMPONENT(T, p) \
|
||||||
|
FENNEC_STATIC_CONSTRUCTOR(T) { \
|
||||||
|
component::register_type<T>(p) \
|
||||||
|
}
|
||||||
|
|
||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
|
|
||||||
struct component_t {
|
|
||||||
uint64_t type;
|
|
||||||
size_t id;
|
|
||||||
};
|
|
||||||
|
|
||||||
class component : public typed<component> {
|
class component : public typed<component> {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// TYPEDEFS & CONSTANTS ================================================================================================
|
// TYPEDEFS & CONSTANTS ================================================================================================
|
||||||
using component_create = size_t (*)(size_t, size_t);
|
using component_create = component* (*)(size_t, size_t);
|
||||||
using component_get = component* (*)(size_t);
|
using component_destroy = void (*)(component*);
|
||||||
using component_destroy = void (*)(size_t);
|
|
||||||
using component_tick = void (*)(size_t, double);
|
|
||||||
using component_frame = void (*)(size_t, uint64_t);
|
|
||||||
|
|
||||||
|
|
||||||
// TYPE OPERATIONS =====================================================================================================
|
// TYPE OPERATIONS =====================================================================================================
|
||||||
@@ -52,31 +49,22 @@ public:
|
|||||||
struct typeinfo {
|
struct typeinfo {
|
||||||
string name;
|
string name;
|
||||||
component_create create;
|
component_create create;
|
||||||
component_destroy destroy;
|
|
||||||
component_get get;
|
|
||||||
component_tick tick;
|
|
||||||
component_frame frame;
|
|
||||||
|
|
||||||
typeinfo()
|
typeinfo()
|
||||||
: name("")
|
: name("")
|
||||||
, create(nullptr), destroy(nullptr)
|
, create(nullptr) {
|
||||||
, get(nullptr)
|
|
||||||
, tick(nullptr), frame(nullptr) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
typeinfo(const string& name,
|
typeinfo(const string& name,
|
||||||
component_create create, component_destroy destroy,
|
component_create create)
|
||||||
component_get get,
|
|
||||||
component_tick tick, component_frame frame)
|
|
||||||
: name(name)
|
: name(name)
|
||||||
, create(create), destroy(destroy), get(get)
|
, create(create) {
|
||||||
, tick(tick), frame(frame) {
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct typeentry {
|
struct typeentry {
|
||||||
string name;
|
string name;
|
||||||
uint64_t id;
|
uint64_t type;
|
||||||
};
|
};
|
||||||
|
|
||||||
using typelist_t = dynarray<optional<typeinfo>>;
|
using typelist_t = dynarray<optional<typeinfo>>;
|
||||||
@@ -92,15 +80,13 @@ private:
|
|||||||
static constexpr size_t npos = typetree_t::npos;
|
static constexpr size_t npos = typetree_t::npos;
|
||||||
static constexpr size_t root = typetree_t::root;
|
static constexpr size_t root = typetree_t::root;
|
||||||
|
|
||||||
static void _register_type( uint64_t id, const path& path,
|
static void _register_type( uint64_t id, const path& path,
|
||||||
component_create create, component_destroy destroy,
|
component_create create) {
|
||||||
component_get get,
|
|
||||||
component_tick tick, component_frame frame) {
|
|
||||||
// Register the type
|
// Register the type
|
||||||
if (id > _typelist.size()) {
|
if (id > _typelist.size()) {
|
||||||
_typelist.resize(id + 1);
|
_typelist.resize(id + 1);
|
||||||
}
|
}
|
||||||
_typelist[id] = typeinfo{ path.filename(), create, destroy, get, tick, frame };
|
_typelist[id] = typeinfo{ path.filename(), create };
|
||||||
|
|
||||||
// Create tree entry
|
// Create tree entry
|
||||||
size_t node = root;
|
size_t node = root;
|
||||||
@@ -112,7 +98,7 @@ private:
|
|||||||
|
|
||||||
node = _typetree.child(parent);
|
node = _typetree.child(parent);
|
||||||
|
|
||||||
while (node != npos && _typetree[node].id != id) {
|
while (node != npos && _typetree[node].type != id) {
|
||||||
node = _typetree.next(node);
|
node = _typetree.next(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,33 +111,6 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
/// \brief Default creation function for a component
|
||||||
/// \tparam ComponentT Type of the component
|
/// \tparam ComponentT Type of the component
|
||||||
@@ -159,60 +118,39 @@ private:
|
|||||||
/// \returns The component created by this function
|
/// \returns The component created by this function
|
||||||
template<typename ComponentT>
|
template<typename ComponentT>
|
||||||
static constexpr component* default_create(size_t scene, size_t node) {
|
static constexpr component* default_create(size_t scene, size_t node) {
|
||||||
auto& storage = _type_storage<ComponentT>();
|
return new ComponentT(scene, node);
|
||||||
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 Registry =====================================================================================================
|
||||||
public:
|
public:
|
||||||
|
|
||||||
///
|
static constexpr const typetree_t& typelist() {
|
||||||
/// \brief Get an uuid for the specified component type
|
return _typetree;
|
||||||
/// \tparam ComponentT The component type
|
}
|
||||||
/// \returns An uuid that is associated with the type
|
|
||||||
template<typename ComponentT>
|
template<typename ComponentT>
|
||||||
static uint64_t uuid() {
|
static constexpr const typeinfo& type_info() {
|
||||||
return typeuuid<ComponentT, component>();
|
const auto& it = _typelist[id<ComponentT>()];
|
||||||
|
assert(it, "Unregistered type provided to component::type_info, see stacktrace for more info.");
|
||||||
|
return *it;
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr const typeinfo& type_info(uint64_t type) {
|
||||||
|
const auto& it = _typelist[type];
|
||||||
|
assert(it, "Unregistered type provided to component::type_info, see stacktrace for more info.");
|
||||||
|
return *it;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Register a type with the component system
|
/// \brief Register a type with the component system
|
||||||
/// \tparam ComponentT The component type
|
/// \tparam ComponentT The component type
|
||||||
/// \param name The name of the type
|
/// \param path The name of the type
|
||||||
/// \param create The function used to create a component, given a scene node. **MUST NOT BE NULL**
|
/// \param create The function used to create 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>
|
template<typename ComponentT>
|
||||||
static void register_type(const cstring& name,
|
static void register_type(const path& path,
|
||||||
component_tick tick, component_frame frame,
|
component_create create = default_create<ComponentT>) {
|
||||||
component_create create = default_create<ComponentT>,
|
component::_register_type(id<ComponentT>(), path, create);
|
||||||
component_get get = default_get<ComponentT>,
|
|
||||||
component_destroy destroy = default_destroy<ComponentT>) {
|
|
||||||
component::_register_type(uuid<ComponentT>(), name, create, destroy, get, tick, frame);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@@ -220,72 +158,25 @@ public:
|
|||||||
/// \param type The type to create
|
/// \param type The type to create
|
||||||
/// \param node The node to associate the component with
|
/// \param node The node to associate the component with
|
||||||
/// \returns The created component
|
/// \returns The created component
|
||||||
static size_t create(uint64_t type, size_t scene, size_t node) {
|
static component* create(uint64_t type, size_t scene, size_t node) {
|
||||||
auto& typei = _typelist[type];
|
auto& typei = _typelist[type];
|
||||||
return typei->create(scene, node);
|
return typei->create(scene, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief Create a component of type `ComponentT`
|
/// \brief Create a component of type `type`
|
||||||
/// \tparam ComponentT The type to create
|
/// \tparam ComponentT The type to create
|
||||||
/// \param node The node to associate the component with
|
/// \param node The node to associate the component with
|
||||||
/// \returns The created component
|
/// \returns The created component
|
||||||
template<typename ComponentT>
|
template<typename ComponentT>
|
||||||
static size_t create(size_t scene, size_t node) {
|
static component* create(size_t scene, size_t node) {
|
||||||
auto& typei = _typelist[uuid<ComponentT>()];
|
auto& typei = _typelist[id<ComponentT>()];
|
||||||
return typei->create(scene, node);
|
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(const component_t& c) {
|
|
||||||
auto& typei = _typelist[c.type];
|
|
||||||
return typei->get(c.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename ComponentT>
|
|
||||||
static component* get(size_t id) {
|
|
||||||
auto& typei = _typelist[uuid<ComponentT>()];
|
|
||||||
return typei->get(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
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 comp) {
|
|
||||||
auto& typei = _typelist[uuid<ComponentT>()];
|
|
||||||
return typei->destroy(comp);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void tick(size_t comp, double dT) {
|
|
||||||
for (auto& it : _typelist) {
|
|
||||||
if (it->tick) {
|
|
||||||
it->tick(comp, dT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 _typelist;
|
|
||||||
}
|
|
||||||
|
|
||||||
// MEMBERS =============================================================================================================
|
// MEMBERS =============================================================================================================
|
||||||
public:
|
public:
|
||||||
const size_t node;
|
const size_t node;
|
||||||
|
|
||||||
template<typename ComponentT>
|
template<typename ComponentT>
|
||||||
component(ComponentT* type, size_t node)
|
component(ComponentT* type, size_t node)
|
||||||
|
|||||||
@@ -35,20 +35,47 @@
|
|||||||
#include <fennec/langproc/strings/string.h>
|
#include <fennec/langproc/strings/string.h>
|
||||||
#include <fennec/scene/component.h>
|
#include <fennec/scene/component.h>
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
|
|
||||||
|
struct scene_node_ref {
|
||||||
|
size_t scene;
|
||||||
|
size_t id;
|
||||||
|
};
|
||||||
|
|
||||||
struct scene_node : typed<scene_node> {
|
struct scene_node : typed<scene_node> {
|
||||||
const size_t scene;
|
|
||||||
const size_t id;
|
// Public Members ======================================================================================================
|
||||||
|
public:
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
const size_t scene;
|
||||||
|
const size_t id;
|
||||||
|
};
|
||||||
|
const scene_node_ref ref;
|
||||||
|
};
|
||||||
string name;
|
string name;
|
||||||
|
|
||||||
scene_node(size_t id, size_t scene, const string& name)
|
scene_node(size_t scene, size_t id, string name)
|
||||||
: id(id), scene(scene), name(name) {
|
: scene(scene), id(id), name(std::move(name)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename ComponentT>
|
||||||
|
component* add_component() {
|
||||||
|
_components.push_back(component::create<ComponentT>(scene, id));
|
||||||
|
return _components.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
component* add_component(uint64_t type) {
|
||||||
|
_components.push_back(component::create(type, scene, id));
|
||||||
|
return _components.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
dynarray<component_t> _components;
|
dynarray<component*> _components;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
namespace fennec
|
namespace fennec
|
||||||
{
|
{
|
||||||
|
|
||||||
STATIC_CONSTRUCTOR(_init_linux) {
|
FENNEC_STATIC_CONSTRUCTOR(_init_linux) {
|
||||||
static linux_platform platform;
|
static linux_platform platform;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ int main(int, char **)
|
|||||||
fennec::test::fennec_test_math();
|
fennec::test::fennec_test_math();
|
||||||
fennec_test_spacer(3);
|
fennec_test_spacer(3);
|
||||||
|
|
||||||
fennec_test_header("format processing library");
|
fennec_test_header("language processing library");
|
||||||
fennec_test_spacer(2);
|
fennec_test_spacer(2);
|
||||||
fennec::test::fennec_test_langproc();
|
fennec::test::fennec_test_langproc();
|
||||||
fennec_test_spacer(3);
|
fennec_test_spacer(3);
|
||||||
|
|||||||
@@ -40,7 +40,8 @@ namespace test
|
|||||||
|
|
||||||
inline void fennec_test_langproc_format() {
|
inline void fennec_test_langproc_format() {
|
||||||
|
|
||||||
fennec_test_run(fennec::format("{}", "Hello World!"), string("Hello World!"));
|
fennec_test_run(fennec::format("{}", "Hello World!"), string("Hello World!"));
|
||||||
|
fennec_test_run(fennec::format("{0}", "Hello World!"), string("Hello World!"));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user