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 735 additions and 183 deletions
......@@ -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
......@@ -127,7 +127,7 @@ namespace fggl::math {
}
static data::Vertex2D pointToVertex(const math::vec2 &point) {
return data::Vertex2D{point, {1.0f, 1.0f, 1.0f}};
return data::Vertex2D{point, {1.0F, 1.0F, 1.0F}, {0.0F, 0.0F}};
}
/**
......
......@@ -61,7 +61,7 @@ namespace fggl::math {
/**
* A 4D unsigned integer vector.
*/
using vec4ui = glm::ivec4;
using vec4ui = glm::uvec4;
/**
* A 3D floating-point vector.
......@@ -76,7 +76,7 @@ namespace fggl::math {
/**
* A 3D unsigned integer vector.
*/
using vec3ui = glm::ivec3;
using vec3ui = glm::uvec3;
/**
* A 2D floating-point vector
......@@ -91,7 +91,11 @@ namespace fggl::math {
/**
* a 2D unsigned integer vector
*/
using vec2ui = glm::ivec2;
using vec2ui = glm::uvec2;
using vec2b = glm::bvec2;
using vec3b = glm::bvec3;
using vec4b = glm::bvec4;
/**
* A 2x2 floating-point matrix.
......@@ -120,6 +124,22 @@ namespace fggl::math {
constexpr static const math::vec3 AXIS_Y{0.0F, 1.0F, 0.0F};
constexpr static const math::vec3 AXIS_Z{0.0F, 0.0F, 1.0F};
constexpr auto minElm(vec3 a, vec3 b) -> vec3{
return {
a.x < b.x ? a.x : b.x,
a.y < b.y ? a.y : b.y,
a.z < b.z ? a.z : b.z
};
}
constexpr auto maxElm(vec3 a, vec3 b) -> vec3 {
return {
a.x > b.x ? a.x : b.x,
a.y > b.y ? a.y : b.y,
a.z > b.z ? a.z : b.z
};
}
// fastFloor from OpenSimplex2
inline int fastFloor(double x) {
int xi = (int) x;
......
......@@ -20,6 +20,7 @@
#define FGGL_MATH_VECTOR_HPP
#include <ostream>
#include <tuple>
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/glm.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 22/10/22.
// FIXME HACKY IMPLEMENTATION DETAIL BECAUSE THE ASSET LOADING PIPELINE IS BAD
//
#include "fggl/mesh/mesh.hpp"
#ifndef FGGL_MESH_COMPONENTS_HPP
#define FGGL_MESH_COMPONENTS_HPP
namespace fggl::mesh {
struct StaticMesh3D {
constexpr static const char name[] = "StaticMesh3D";
constexpr static const util::GUID guid = util::make_guid(name);
util::GUID meshReference;
Mesh3D mesh;
std::string pipeline;
inline StaticMesh3D() = default;
inline StaticMesh3D(const Mesh3D &aMesh, std::string aPipeline) :
mesh(aMesh), pipeline(std::move(aPipeline)) {}
};
struct StaticMultiMesh3D {
constexpr static const char name[] = "StaticMultiMesh3D";
constexpr static const util::GUID guid = util::make_guid(name);
util::GUID meshReference;
MultiMesh3D mesh;
std::string pipeline;
inline StaticMultiMesh3D() = default;
inline StaticMultiMesh3D(const MultiMesh3D &aMesh, std::string aPipeline) :
mesh(aMesh), pipeline(std::move(aPipeline)) {}
};
}
#endif //FGGL_MESH_COMPONENTS// _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 18/10/22.
//
#ifndef FGGL_MESH_MESH_HPP
#define FGGL_MESH_MESH_HPP
#include "fggl/math/types.hpp"
#include "fggl/assets/types.hpp"
#include <vector>
#include <span>
namespace fggl::mesh {
struct Vertex3D {
math::vec3 position;
math::vec3 normal;
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 {
math::vec2 position;
math::vec2 colour;
math::vec2 texPos;
};
enum TextureType {
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<assets::AssetID> diffuseTextures{};
std::vector<assets::AssetID> normalTextures{};
std::vector<assets::AssetID> specularTextures{};
inline assets::AssetID getPrimaryDiffuse() {
assert( !diffuseTextures.empty() );
return diffuseTextures.empty() ? MISSING_TEXTURE : diffuseTextures[0];
}
inline assets::AssetID getPrimaryNormals() {
assert( !normalTextures.empty() );
return normalTextures.empty() ? MISSING_TEXTURE : normalTextures[0];
}
inline assets::AssetID getPrimarySpecular() {
assert( !specularTextures.empty() );
return specularTextures.empty() ? MISSING_TEXTURE : specularTextures[0];
}
};
template<typename VertexFormat>
struct Mesh {
std::vector<VertexFormat> data;
std::vector<uint32_t> indices;
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<assets::AssetID> materials;
MeshFormat& generate() {
return meshes.template emplace_back();
}
};
using Mesh2D = Mesh<Vertex2D>;
using MultiMesh2D = MultiMesh<Mesh2D>;
using Mesh3D = Mesh<Vertex3D>;
using MultiMesh3D = MultiMesh<Mesh3D>;
}
#endif //FGGL_MESH_MESH_HPP
......@@ -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;
}
......@@ -185,24 +103,32 @@ namespace fggl::modules {
debug::log(debug::Level::warning,
"{} depends on {}, but nothing provides it",
moduleItr.first,
service);
service.get());
// nothing can provide the service requested, setup is invalid.
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;
}
......@@ -222,7 +148,7 @@ namespace fggl::modules {
debug::log(debug::Level::warning,
"{} could not create service {}",
nextToInit,
service);
service.get());
}
}
} else {
......@@ -235,12 +161,16 @@ namespace fggl::modules {
m_locked = true;
}
inline Services& services() {
return m_services;
}
private:
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
......@@ -25,8 +25,12 @@
namespace fggl::phys {
inline void build_noop(const entity::ComponentSpec & /*config*/,
entity::EntityManager & /*manager*/,
const entity::EntityID & /*entity*/) {}
entity::EntityManager &manager,
const entity::EntityID &entity,
modules::Services &/*services*/) {
manager.add<fggl::phys::RigidBody>(entity);
manager.add<fggl::phys::Dynamics>(entity);
}
class NullPhysicsEngine : public PhysicsEngine {
public:
......@@ -66,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;
};
......
/*
* 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 19/09/22.
//
#ifndef FGGL_PLATFORM_FALLBACK_FILE_HPP
#define FGGL_PLATFORM_FALLBACK_FILE_HPP
#include <cstdio>
#include <cassert>
namespace fggl::platform {
class File {
public:
inline File(FILE* filePtr) : m_handle(filePtr) {
assert(filePtr != nullptr);
}
inline ~File() {
release();
}
template<typename T>
inline void write(const T* dataPtr) {
assert( m_handle != nullptr );
int status = fwrite(dataPtr, sizeof(T), 1, m_handle );
assert( status == 1);
}
template<typename T>
inline void writeArr(const T* dataPtr, std::size_t numElms) {
assert( m_handle != nullptr);
int status = fwrite(dataPtr, sizeof(T), numElms, m_handle );
assert( status == 1);
}
private:
std::FILE* m_handle;
inline void release() {
if ( m_handle != NULL) {
fclose(m_handle);
}
}
};
} // namespace fggl::platform
#endif //FGGL_PLATFORM_FALLBACK_FILE_HPP
......@@ -58,11 +58,12 @@ namespace fggl::scenes {
void update(float dt) override;
void render(fggl::gfx::Graphics &gfx) override;
protected:
inline auto world() -> entity::EntityManager & {
return *m_world;
}
protected:
bool hasPhys() const {
return m_phys != nullptr;
}
......@@ -76,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;
......
/*
* 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 15/10/22.
//
#ifndef FGGL_SCRIPT_ENGINE_H
#define FGGL_SCRIPT_ENGINE_H
#include "fggl/modules/module.hpp"
namespace fggl::script {
class ScriptEngine {
public:
virtual ~ScriptEngine() = default;
// TODO use protected virtual pattern
// scene callbacks
virtual void onActivate() = 0;
virtual void onDeactivate() = 0;
virtual void onUpdate() = 0;
// trigger callback
virtual void onEvent(const std::string& name) = 0;
// run code in engine
virtual bool run(const char* script) = 0;
virtual bool load(const char* filename) = 0;
virtual void setGlobal(const char* name, void* ptr) = 0;
};
class ScriptProvider {
public:
constexpr static const modules::ServiceName service = modules::make_service("fggl::script::service");
virtual ScriptEngine* create() = 0;
};
}
#endif //FGGL_SCRIPT_ENGINE_H
......@@ -24,6 +24,7 @@
#include <cassert>
#include "fggl/util/safety.hpp"
#include "fggl/debug/logging.hpp"
namespace fggl::util {
......@@ -66,26 +67,68 @@ 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) {
return GUID::make(hash_fnv1a_64(str));
return GUID(hash_fnv1a_64(str));
}
inline GUID make_guid_rt(const std::string &str) {
inline GUID make_guid_rt(const char* str) {
#ifndef NDEBUG
return internString(str.c_str());
return intern_string(str);
#else
return make_guid(str.c_str());
return make_guid(str);
#endif
}
inline GUID make_guid_rt(const std::string &str) {
return make_guid_rt(str.c_str());
}
} // namespace fggl::util
// formatter
template<> struct fmt::formatter<fggl::util::GUID> {
constexpr auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) {
return ctx.begin();
}
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[{}]", guid_to_string(guid));
#else
return fmt::format_to(ctx.out(), "GUID[{}]", guid.get());
#endif
}
};
fggl::util::GUID operator "" _fid(const char *str);
fggl::util::GUID operator "" _fid(const char *str, std::size_t);
......
......@@ -47,8 +47,6 @@ namespace fggl::util {
return m_value;
}
constexpr explicit operator std::string_view() const { return m_value; }
/**
* Check for equality of two handles.
*
......