Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • gamedev/fggl
  • onuralpsezer/fggl
2 results
Show changes
Showing
with 570 additions and 194 deletions
......@@ -20,27 +20,53 @@
#define FGGL_GUI_MODULE_HPP
#include "fggl/gui/fonts.hpp"
#include "fggl/gui/model/parser.hpp"
#include "fggl/data/module.hpp"
#include "fggl/assets/packed/module.hpp"
namespace fggl::gui {
constexpr auto MIME_TTF = assets::from_mime("font/ttf");
constexpr auto ASSET_FONT_TTF = assets::make_asset_type("font/ttf");
static assets::AssetTypeID is_font(std::filesystem::path path) {
if ( path.extension() == ".ttf" ){
return ASSET_FONT_TTF;
}
return assets::INVALID_ASSET_TYPE;
}
struct FreeType {
constexpr static const char *name = "fggl::gui::FreeType";
constexpr static const std::array<modules::ModuleService, 1> provides = {
FontLibrary::service
constexpr static const std::array<modules::ServiceName, 2> provides = {
FontLibrary::service,
model::WidgetFactory::service
};
constexpr static const std::array<modules::ModuleService, 1> depends = {
data::Storage::service
constexpr static const std::array<modules::ServiceName, 2> depends = {
data::Storage::service,
assets::CheckinAdapted::service
};
static bool factory(modules::ModuleService name, modules::Services &serviceManager);
static bool factory(modules::ServiceName name, modules::Services &serviceManager);
};
bool FreeType::factory(modules::ModuleService service, modules::Services &services) {
bool FreeType::factory(modules::ServiceName service, modules::Services &services) {
if (service == FontLibrary::service) {
auto storage = services.get<data::Storage>();
services.create<FontLibrary>(storage);
auto* checkin = services.get<assets::CheckinAdapted>();
checkin->setLoader( MIME_TTF, assets::NEEDS_CHECKIN, is_font );
return true;
}
if ( service == model::WidgetFactory::service ) {
auto fonts = services.get<FontLibrary>();
services.create<model::WidgetFactory>(fonts);
return true;
}
return false;
}
}
......
/*
* This file is part of FGGL.
*
* FGGL is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* FGGL 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with FGGL.
* If not, see <https://www.gnu.org/licenses/>.
*/
//
// Created by webpigeon on 04/03/23.
//
#ifndef FGGL_GUI_RENDERER_RENDERER_HPP
#define FGGL_GUI_RENDERER_RENDERER_HPP
#include <fggl/gui/model/structure.hpp>
#include <fggl/gfx/paint.hpp>
namespace fggl::gui::renderer {
struct Box {
float top;
float right;
float bottom;
float left;
inline Box trim(Box border) const {
return {
top + border.top,
right - border.right,
bottom - border.bottom,
left + border.left
};
}
inline Box expand(Box border) const {
return {
top - border.top,
right + border.right,
bottom + border.bottom,
left - border.left
};
}
inline float width() const {
return right - left;
}
inline float height() const {
return bottom - top;
}
};
inline math::vec2 get_vec2(const model::Widget& root, const std::string& name) {
if ( !root.hasAttr(name) ) {
return {};
}
return root.get<math::vec2>(name);
}
inline math::vec3 get_vec3_rgb(const model::Widget& root, const std::string& name) {
if ( !root.hasAttr(name) ) {
return {};
}
return root.get<math::vec3>(name);
}
inline Box get_box(const model::Widget& root, const std::string& name) {
return {
root.get_or_default<float>(name + "::top"),
root.get_or_default<float>(name + "::right"),
root.get_or_default<float>(name + "::bottom"),
root.get_or_default<float>(name + "::left")
};
}
inline Box getBounds(math::vec2 pos, math::vec2 size) {
return {
pos.y,
pos.x + size.x,
pos.y + size.y,
pos.x
};
}
void draw_box(gfx::Path2D &path, glm::vec2 topLeft, glm::vec2 bottomRight);
void draw_border_patch(gfx::Paint& paint, Box& bounds, Box& size, math::vec3 colour);
void draw_border_solid(gfx::Paint& paint, Box& bounds, Box& size, math::vec3 colour);
void draw_background_solid(gfx::Paint& paint, Box& bounds, math::vec3 colour);
void layout(model::Widget& root);
void visit(const model::Widget& root, gfx::Paint& paint, Box offset = {0.0F, 1024.0F, 768.0F, 0.0F});
} // namespace fggl::gui::renderer
#endif //FGGL_GUI_RENDERER_RENDERER_HPP
......@@ -61,7 +61,7 @@ namespace fggl::gui {
}
void layout() override;
inline void update(float deltaTime) override {}
inline void update(float /*deltaTime*/) override {}
private:
std::shared_ptr<gui::FontFace> m_font;
......@@ -83,7 +83,7 @@ namespace fggl::gui {
[[nodiscard]]
std::string label() const;
inline void update(float deltaTime) override {}
inline void update(float /*deltaTime*/) override {}
void addCallback(Callback callback);
void layout() override;
......
......@@ -24,11 +24,11 @@
namespace fggl::input {
constexpr const modules::ModuleService SERVICE_INPUT = modules::make_service("fggl::input::Input");
constexpr const auto SERVICE_INPUT = modules::make_service("fggl::input::Input");
class Input {
public:
constexpr static const modules::ModuleService service = SERVICE_INPUT;
constexpr static const auto service = SERVICE_INPUT;
Input() = default;
void frame(float dt);
......
......@@ -27,14 +27,14 @@ namespace fggl::input {
struct Generic {
constexpr static const char *name = "fggl::input::Generic";
constexpr static const std::array<modules::ModuleService, 1> provides = {
constexpr static const std::array<modules::ServiceName, 1> provides = {
SERVICE_INPUT
};
constexpr static const std::array<modules::ModuleService, 0> depends = {};
static bool factory(modules::ModuleService service, modules::Services &services);
constexpr static const std::array<modules::ServiceName, 0> depends = {};
static bool factory(modules::ServiceName service, modules::Services &services);
};
bool Generic::factory(modules::ModuleService service, modules::Services &services) {
bool Generic::factory(modules::ServiceName service, modules::Services &services) {
if (service == SERVICE_INPUT) {
services.create<input::Input>();
return true;
......
......@@ -19,17 +19,19 @@
#include <array>
#include <bitset>
#include "fggl/math/types.hpp"
namespace fggl::input {
enum class MouseButton {
LEFT,
MIDDLE,
RIGHT,
EXTRA_1,
EXTRA_2,
EXTRA_3,
EXTRA_4,
EXTRA_5
LEFT = 0,
MIDDLE = 2,
RIGHT = 1,
EXTRA_1 = 3,
EXTRA_2 = 4,
EXTRA_3 = 5,
EXTRA_4 = 6,
EXTRA_5 = 7
};
enum class MouseAxis {
......@@ -74,6 +76,7 @@ namespace fggl::input {
void operator=(const MouseState &rhs);
};
class MouseInput {
public:
MouseInput() = default;
......@@ -121,6 +124,15 @@ namespace fggl::input {
MouseState m_prev;
};
// helpers
inline math::vec2 mouse_axis(const MouseInput& input) {
return { input.axis(MouseAxis::X), input.axis(MouseAxis::Y) };
}
inline math::vec2 mouse_axis_delta(const MouseInput& input) {
return { input.axisDelta(MouseAxis::X), input.axisDelta(MouseAxis::Y) };
}
};
#endif
......@@ -84,6 +84,21 @@ namespace fggl::math {
return valueOrMin > max ? max : valueOrMin;
}
constexpr float lerpImprecise(float start, float end, float t) {
return start + t * (end - start);
}
constexpr float lerp(float start, float end, float t) {
return (1 - t) * start + t * end;
}
template<typename T>
[[nodiscard]]
constexpr T smooth_add(T first, T second, const float weight) {
const float other = 1 - weight;
return (first * other) + (second * weight);
}
} // namespace fggl::math
......
......@@ -19,10 +19,12 @@
#ifndef FGGL_MATH_IMATH_HPP
#define FGGL_MATH_IMATH_HPP
#include <cstdint>
namespace fggl::math {
// wrap value in range [0, max)
inline int wrap(int value, int max) {
constexpr int wrap(int value, int max) {
if (value < 0)
return (value - 1) - (-1 - value) % value;
if (value >= max)
......@@ -31,7 +33,7 @@ namespace fggl::math {
}
// wrap value in range [min, max)
inline int wrap(int value, int const min, int const max) {
constexpr int wrap(int value, int const min, int const max) {
int range = max - min + 1;
if (value < min) {
value += range * ((min - value) / range + 1);
......@@ -39,19 +41,47 @@ namespace fggl::math {
return min + (value - min) % range;
}
inline
int clamp(int value, int min, int max) {
constexpr int clamp(int value, int min, int max) {
const int i = value > max ? max : value;
return i < min ? min : value;
}
template<typename T>
inline
T clampT(T value, T min, T max) {
constexpr T clampT(T value, T min, T max) {
const T i = value > max ? max : value;
return i < min ? min : value;
}
/**
* Calculate the sum of the first N positive integers.
*
* @param n the number to stop at
* @return sum(0 ... N)
*/
constexpr uint64_t calcSum(uint64_t n) {
return (n * (n + 1)) / 2;
}
/**
* Calculate the squared sum of the first N positive integers.
*
* @param n the number to stop at
* @return sum(0 ... N) * sum(0 ... N)
*/
constexpr uint64_t calcSumSquared(uint64_t n) {
return (n * (n + 1) * (2*n + 1)) / 6;
}
/**
* Calculate the cubed sum of the first N positive integers.
*
* @param n the number to stop at
* @return sum(0 ... N) * sum(0 ... N) * sum(0 ... N)
*/
constexpr uint64_t calcSumCubed(uint64_t n) {
return ((n * n) * ((n + 1) * (n + 1))) / 4;
}
} // namespace fggl::math
#endif //FGGL_MATH_IMATH_HPP
/*
* This file is part of FGGL.
*
* FGGL is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* FGGL 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with FGGL.
* If not, see <https://www.gnu.org/licenses/>.
*/
//
// Created by webpigeon on 27/11/22.
//
#ifndef FGGL_MATH_STATS_HPP
#define FGGL_MATH_STATS_HPP
#include <cstdint>
#include <cmath>
namespace fggl::math {
class CumulativeAverage {
public:
inline void add(float item) {
m_current = ( item + (m_count * m_current) ) / (m_count + 1);
m_count++;
}
inline float average() {
return m_current;
}
private:
float m_current;
std::size_t m_count;
};
/**
* Useful Statistics class.
* ported to C++ from Piers' Java implementation.
*
* @tparam T
*/
template<typename T>
class Statistics {
public:
void add(T observation) {
m_count++;
m_sum += observation;
m_sumSquared += (observation * observation);
m_min = std::min(m_min, observation);
m_max = std::max(m_max, observation);
m_dirty = true;
}
inline T average() {
compute();
return m_average;
}
inline T average() const {
if ( m_dirty ) {
return m_sum / m_count;
}
return m_average;
}
inline T standardDeviation() {
compute();
return m_standardDiv;
}
inline T standardDeviation() const {
if ( !m_dirty ) {
return m_standardDiv;
}
T avg = average();
T num = m_sumSquared - (m_count * avg * avg);
return num < 0 ? 0 : sqrt( num / (m_count-1));
}
inline T standardError() {
compute();
return m_standardDiv / sqrt(m_count);
}
inline T standardError() const {
if ( !m_dirty ) {
return m_standardDiv / sqrt(m_count);
}
return standardDeviation() / sqrt(m_count);
}
inline T squareSum () const {
return m_sumSquared;
}
inline std::size_t count() const {
return m_count;
}
inline T sum() const {
return m_sum;
}
inline T min() const {
return m_min;
}
inline T max() const {
return m_max;
}
private:
T m_average{0};
T m_sum{0};
T m_sumSquared{0};
T m_standardDiv{0};
T m_min{0};
T m_max{0};
std::size_t m_count{0};
bool m_dirty{false};
void compute() {
if ( !m_dirty ) {
return;
}
m_average = m_sum / m_count;
T num = m_sumSquared - (m_count * m_average * m_average);
if ( num < 0 ) {
num = 0;
}
m_standardDiv = sqrt( num / (m_count-1) );
m_dirty = false;
}
};
using StatisticsF = Statistics<float>;
using StatisticsD = Statistics<double>;
} // namespace fggl::math
#endif //FGGL_MATH_STATS_HPP
......@@ -20,6 +20,7 @@
#define FGGL_MATH_VECTOR_HPP
#include <ostream>
#include <tuple>
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/glm.hpp>
......
......@@ -20,6 +20,7 @@
#define FGGL_MESH_MESH_HPP
#include "fggl/math/types.hpp"
#include "fggl/assets/types.hpp"
#include <vector>
#include <span>
......@@ -29,8 +30,17 @@ namespace fggl::mesh {
struct Vertex3D {
math::vec3 position;
math::vec3 normal;
math::vec3 colour{ 1.0F, 1.0F, 1.0f };
math::vec3 colour{ 1.0F, 1.0F, 1.0F };
math::vec2 texPos{ NAN, NAN };
static Vertex3D from_pos(math::vec3 pos) {
return {
.position = pos,
.normal {NAN, NAN, NAN},
.colour {1.0F, 1.0F, 1.0F},
.texPos { pos.x, pos.z }
};
}
};
struct Vertex2D {
......@@ -43,22 +53,29 @@ namespace fggl::mesh {
DIFFUSE, NORMAL
};
constexpr auto MISSING_TEXTURE = assets::AssetID::make(0);
struct Material {
std::string name;
math::vec3 ambient;
math::vec3 diffuse;
math::vec3 specular;
std::vector<std::string> diffuseTextures{};
std::vector<std::string> normalTextures{};
std::vector<assets::AssetID> diffuseTextures{};
std::vector<assets::AssetID> normalTextures{};
std::vector<assets::AssetID> specularTextures{};
inline std::string getPrimaryDiffuse() {
inline assets::AssetID getPrimaryDiffuse() {
assert( !diffuseTextures.empty() );
return diffuseTextures.empty() ? "" : diffuseTextures[0];
return diffuseTextures.empty() ? MISSING_TEXTURE : diffuseTextures[0];
}
inline std::string getPrimaryNormals() {
inline assets::AssetID getPrimaryNormals() {
assert( !normalTextures.empty() );
return normalTextures.empty() ? "" : normalTextures[0];
return normalTextures.empty() ? MISSING_TEXTURE : normalTextures[0];
}
inline assets::AssetID getPrimarySpecular() {
assert( !specularTextures.empty() );
return specularTextures.empty() ? MISSING_TEXTURE : specularTextures[0];
}
};
......@@ -66,13 +83,23 @@ namespace fggl::mesh {
struct Mesh {
std::vector<VertexFormat> data;
std::vector<uint32_t> indices;
std::string material;
assets::AssetID material;
inline uint32_t append(const VertexFormat& vert) {
auto nextIdx = data.size();
data.push_back(vert);
return nextIdx;
}
};
template<typename MeshFormat>
struct MultiMesh {
std::vector<MeshFormat> meshes;
std::vector<std::string> materials;
std::vector<assets::AssetID> materials;
MeshFormat& generate() {
return meshes.template emplace_back();
}
};
using Mesh2D = Mesh<Vertex2D>;
......
......@@ -21,7 +21,9 @@
#include "fggl/modules/module.hpp"
#include "fggl/debug/logging.hpp"
#include "fggl/ds/graph.hpp"
#include <cassert>
#include <queue>
#include <vector>
#include <map>
......@@ -31,108 +33,6 @@
namespace fggl::modules {
/**
* A class used for representing a Directed Acyclic Graph.
*
* This class is mostly used for establishing the loading order of classes for module loading.
*
* @tparam T the type being represented
*/
template<typename T>
class DependencyGraph {
public:
DependencyGraph() = default;
/**
* Clear all currently stored dependencies.
*
* This method will result in the dependency graph being empty, with no known modules.
*/
void clear() {
m_dependencies.clear();
}
/**
* Add a series of dependencies for an entry.
*
* If the entry does not already exist, this will create the entry before adding the dependencies to it.
* If the entry already exists, this will append the provided dependencies to its existing list.
*
* @param name the entry having dependencies added
* @param dependencies the things it depends on
*/
void addAll(const T &name, const std::vector<T> &dependencies) {
auto existing = m_dependencies.find(name);
if (existing == m_dependencies.end()) {
m_dependencies[name] = dependencies;
} else {
existing->second.insert(existing->second.end(), dependencies.begin(), dependencies.end());
}
}
/**
* Add a single dependency to the graph.
*
* If the entry does not already exist, this will create the entry before adding the dependencies to it.
* If the entry already exists, this will append the provided dependencies to its existing list.
*
* @param name the entry which depends something else
* @param depends the thing it depends on
*/
void add(const T &name, const T &depends) {
m_dependencies[name].push_back(depends);
}
bool getOrder(std::stack<T> &stack) {
std::set<T> visited{};
for (const auto &module : m_dependencies) {
if (!visited.contains(module.first)) {
sortUtil(module.first, visited, stack);
}
}
return true;
}
bool getOrderRev(std::queue<T> &stack) {
std::set<T> visited{};
for (const auto &module : m_dependencies) {
if (!visited.contains(module.first)) {
sortUtilRev(module.first, visited, stack);
}
}
return true;
}
private:
std::map<T, std::vector<T>> m_dependencies;
void sortUtil(T idx, std::set<T> &visited, std::stack<T> &stack) {
visited.emplace(idx);
for (auto dep : m_dependencies.at(idx)) {
if (!visited.contains(dep))
sortUtil(dep, visited, stack);
}
stack.push(idx);
}
void sortUtilRev(T idx, std::set<T> &visited, std::queue<T> &stack) {
visited.emplace(idx);
for (auto dep : m_dependencies.at(idx)) {
if (!visited.contains(dep))
sortUtilRev(dep, visited, stack);
}
stack.push(idx);
}
};
/**
* Store and initialise modules present in the engine.
*
......@@ -144,6 +44,23 @@ namespace fggl::modules {
public:
Manager() = default;
template<ServiceType T>
class Service {
public:
inline Service(Manager* manager) : m_manager(manager) {}
inline T* operator->() {
if ( m_ptr == nullptr ) {
m_ptr = m_manager->get<T>();
}
return m_ptr;
}
private:
Manager* m_manager;
std::shared_ptr<T> m_ptr;
};
inline void addVirtual(const Config &config) {
assert(!m_locked);
......@@ -153,7 +70,7 @@ namespace fggl::modules {
}
}
template<typename T>
template<ModuleType T>
void use() {
assert(!m_locked);
......@@ -170,11 +87,12 @@ namespace fggl::modules {
addVirtual(config);
}
// FIXME this should be in cpp file
bool buildGraph() {
// resolve links between modules
for (auto &moduleItr : m_modules) {
if (moduleItr.second.depends.empty()) {
m_dependencies.addAll(moduleItr.first, {});
m_dependencies.addVertex(moduleItr.first);
continue;
}
......@@ -190,19 +108,27 @@ namespace fggl::modules {
return false;
}
m_dependencies.add(moduleItr.first, provider->second);
m_dependencies.addEdge(moduleItr.first, provider->second);
}
}
return true;
}
template<typename T>
template<ServiceType T>
T *get() const {
assert(m_locked);
return m_services.template get<T>();
}
template<ServiceType T>
Service<T> getLazy() const {
assert(m_locked);
return { this };
}
//FIXME this should be in cpp file!
void resolve() {
assert( !m_locked );
if (!buildGraph()) {
return;
}
......@@ -243,8 +169,8 @@ namespace fggl::modules {
bool m_locked = false;
Services m_services;
std::map<ModuleIdentifier, Config> m_modules;
DependencyGraph<ModuleIdentifier> m_dependencies;
std::map<ModuleService, ModuleIdentifier> m_serviceProviders;
ds::DirectedGraph<ModuleIdentifier> m_dependencies;
std::map<ServiceName, ModuleIdentifier> m_serviceProviders;
};
......
......@@ -26,53 +26,39 @@
#include <memory>
#include "fggl/util/safety.hpp"
#include "service.hpp"
namespace fggl::modules {
template<typename T>
concept ModuleType = requires(T type) {
{ T::provides };
{ T::depends };
};
using ModuleIdentifier = std::string;
using ModuleService = util::OpaqueName<std::string_view, struct ModuleServiceTag>;
constexpr ModuleService make_service(const std::string_view name) {
return ModuleService::make(name);
}
using ServiceFactory = std::function<bool(ServiceName , Services &)>;
struct Config {
ModuleIdentifier name;
std::vector<ServiceName> provides;
std::vector<ServiceName> depends;
ServiceFactory factory = nullptr;
};
class Services {
class Module {
public:
template<typename Svc, typename Impl, typename ...Args>
void bind(Args... args) {
static_assert(std::is_base_of_v<Svc, Impl>, "Service type must be assignable from implementation type");
m_services[Svc::service] = std::make_shared<Impl>(args...);
}
virtual ~Module() = default;
template<typename Svc, typename ...Args>
Svc *create(Args... args) {
auto svc = std::make_shared<Svc>(args...);
m_services[Svc::service] = svc;
return svc.get();
}
// copying modules is bad
Module(const Module&) = delete;
Module& operator=(const Module&) = delete;
template<typename Svc>
void provide(std::shared_ptr<Svc> service) {
m_services[Svc::service] = service;
}
// moving modules is bad
Module(Module&&) = delete;
Module& operator=(Module&&) = delete;
template<typename S>
S *get() const {
auto serviceWrapper = m_services.at(S::service);
auto ptr = std::static_pointer_cast<S>(serviceWrapper);
return ptr.get();
}
private:
std::map<ModuleService, std::shared_ptr<void>> m_services;
};
using ServiceFactory = std::function<bool(ModuleService, Services &)>;
struct Config {
ModuleIdentifier name;
std::vector<ModuleService> provides;
std::vector<ModuleService> depends;
ServiceFactory factory = nullptr;
virtual auto create(ServiceName, Services&) -> bool = 0;
};
} // namespace fggl::modules
......
/*
* This file is part of FGGL.
*
* FGGL is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* FGGL 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with FGGL.
* If not, see <https://www.gnu.org/licenses/>.
*/
//
// Created by webpigeon on 25/03/23.
//
#ifndef FGGL_MODULES_SERVICE_HPP
#define FGGL_MODULES_SERVICE_HPP
#include <map>
#include <memory>
#include "fggl/util/safety.hpp"
namespace fggl::modules {
using ServiceName = util::OpaqueName<std::string_view, struct ModuleServiceTag>;
constexpr ServiceName make_service(const std::string_view name) {
return ServiceName::make(name);
}
template<typename T>
concept ServiceType = requires(T* type) {
{ T::service };
};
template<typename T, typename U>
concept Derived = std::is_base_of<U, T>::value;
class Services {
public:
template<ServiceType Svc, Derived<Svc> Impl, typename ...Args>
void bind(Args... args) {
m_services[Svc::service] = std::make_shared<Impl>(args...);
}
template<ServiceType Svc, typename ...Args>
Svc *create(Args... args) {
auto svc = std::make_shared<Svc>(args...);
m_services[Svc::service] = svc;
return svc.get();
}
template<ServiceType Svc>
void provide(std::shared_ptr<Svc> service) {
m_services[Svc::service] = service;
}
template<ServiceType S>
S *get() const {
auto serviceWrapper = m_services.at(S::service);
auto ptr = std::static_pointer_cast<S>(serviceWrapper);
return ptr.get();
}
private:
std::map<ServiceName, std::shared_ptr<void>> m_services;
};
} // namespace fggl::modules
#endif //FGGL_MODULES_SERVICE_HPP
......@@ -70,13 +70,13 @@ namespace fggl::phys {
struct NullPhysics {
constexpr static const char *name = "fggl::phys::null";
constexpr static const std::array<modules::ModuleService, 1> provides = {
constexpr static const std::array<modules::ServiceName, 1> provides = {
phys::PhysicsProvider::service
};
constexpr static const std::array<modules::ModuleService, 1> depends = {
constexpr static const std::array<modules::ServiceName, 1> depends = {
entity::EntityFactory::service
};
static bool factory(modules::ModuleService serviceName, modules::Services &serviceManager);
static bool factory(modules::ServiceName serviceName, modules::Services &serviceManager);
};
} // namespace fggl::phys
......
......@@ -27,7 +27,7 @@ namespace fggl::phys {
class PhysicsProvider {
public:
constexpr static const modules::ModuleService service = modules::make_service("fggl::phys::service");
constexpr static const auto service = modules::make_service("fggl::phys::service");
virtual ~PhysicsProvider() = default;
virtual PhysicsEngine *create(entity::EntityManager *entityManager, entity::EntityFactory *factory) = 0;
};
......
......@@ -77,6 +77,8 @@ namespace fggl::scenes {
return *m_input;
}
bool m_debug;
private:
input::Input *m_input;
std::unique_ptr<entity::EntityManager> m_world;
......
......@@ -26,7 +26,7 @@
namespace fggl::scenes {
using callback = std::function<void(void)>;
using Callback = std::function<void(void)>;
class BasicMenu : public AppState {
public:
......@@ -38,11 +38,11 @@ namespace fggl::scenes {
void activate() override;
void deactivate() override;
void add(const std::string &label, callback cb);
void add(const std::string &label, const Callback& /*cb*/);
private:
input::Input *m_inputs;
std::map<const std::string, callback> m_items;
std::map<const std::string, Callback> m_items;
// menu state
std::string m_active;
......
......@@ -46,7 +46,7 @@ namespace fggl::script {
class ScriptProvider {
public:
constexpr static const modules::ModuleService service = modules::make_service("fggl::script::service");
constexpr static const modules::ServiceName service = modules::make_service("fggl::script::service");
virtual ScriptEngine* create() = 0;
};
......
......@@ -67,10 +67,31 @@ namespace fggl::util {
return hash;
}
template<unsigned N>
struct FString {
char c[N];
};
// https://stackoverflow.com/a/65440575
template<unsigned ...Len>
constexpr auto cat(const char (&...strings)[Len]) {
constexpr unsigned N = (... + Len) - sizeof...(Len);
FString<N + 1> result = {};
result.c[N] = '\0';
char* dst = result.c;
for (const char* src : {strings...}) {
for (; *src != '\0'; src++, dst++) {
*dst = *src;
}
}
return result;
}
// debug-only functions
#ifndef NDEBUG
GUID internString(const char *str);
std::string guidToString(GUID guid);
GUID intern_string(const char *str);
std::string guid_to_string(GUID guid);
#endif
constexpr GUID make_guid(const char *str) {
......@@ -79,7 +100,7 @@ namespace fggl::util {
inline GUID make_guid_rt(const char* str) {
#ifndef NDEBUG
return internString(str);
return intern_string(str);
#else
return make_guid(str);
#endif
......@@ -100,7 +121,7 @@ template<> struct fmt::formatter<fggl::util::GUID> {
template <typename FormatContext>
auto format(const fggl::util::GUID& guid, FormatContext& ctx) const -> decltype(ctx.out()) {
#ifndef NDEBUG
return fmt::format_to(ctx.out(), "GUID[{}]", guidToString(guid));
return fmt::format_to(ctx.out(), "GUID[{}]", guid_to_string(guid));
#else
return fmt::format_to(ctx.out(), "GUID[{}]", guid.get());
#endif
......