Skip to content
Snippets Groups Projects
Commit a26abb73 authored by Joseph Walton-Rivers's avatar Joseph Walton-Rivers
Browse files

restructure to use virtual methods rather than compile-time modules

parent 9100ab4d
No related branches found
No related tags found
No related merge requests found
Showing
with 1093 additions and 28 deletions
cmake_minimum_required(VERSION 3.16)
cmake_minimum_required(VERSION 3.23)
set(namespace "fggl")
set(CMAKE_CXX_STANDARD 20)
......@@ -43,12 +43,13 @@ file(GLOB_RECURSE public_headers
${PROJECT_SOURCE_DIR}/include/fggl/*.hpp
)
add_subdirectory( components )
# engine sources, enable strict compiler warnings
add_subdirectory( fggl )
target_compile_options( fggl PRIVATE -Wall -Wpedantic -Wextra -Wodr -fno-strict-aliasing -fno-strict-overflow )
set_property(TARGET fggl PROPERTY INTERPROCEDURAL_OPTIMIZATION True)
add_subdirectory( components )
# Unit Tests
if (FGGL_TESTS)
......@@ -126,18 +127,18 @@ configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in
INSTALL_DESTINATION "${FGGL_CONFIG_PATH}"
)
# install config files
install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
DESTINATION "${FGGL_CONFIG_PATH}"
)
#install(FILES
# "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
# "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
# DESTINATION "${FGGL_CONFIG_PATH}"
#)
# generate the export targets for the build tree
install(TARGETS ${PROJECT_NAME}
EXPORT fgglTargets
DESTINATION "${CMAKE_INSTALL_LIBDIR}"
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)
#install(TARGETS ${PROJECT_NAME}
# EXPORT fgglTargets
# DESTINATION "${CMAKE_INSTALL_LIBDIR}"
# PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}
# INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
#)
export(EXPORT "${PROJECT_NAME}Targets"
FILE "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Targets.cmake"
......
add_subdirectory(core)
#add_subdirectory(assets)
add_subdirectory(physics)
\ No newline at end of file
add_library(fggl-assets)
target_link_libraries(fggl-assets fggl-core)
target_include_directories(fggl-assets PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/fggl>
$<INSTALL_INTERFACE:include/fggl>
)
add_library(fggl-core)
target_include_directories(fggl-core PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include/fggl>
)
target_sources(fggl-core
PUBLIC
FILE_SET core_headers
TYPE HEADERS
BASE_DIRS include
)
target_sources(fggl-core
PRIVATE
src/filesystem/finder.cpp
src/filesystem/reader.cpp
src/filesystem/module.cpp
src/services/factory.cpp
src/services/module.cpp
)
# platform integration tools
add_subdirectory(src/platform)
include(GNUInstallDirs)
install(TARGETS fggl-core FILE_SET core_headers)
/*
* 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 11/06/22.
//
#ifndef FGGL_DEBUG_IMPL_LOGGING_FMT_HPP
#define FGGL_DEBUG_IMPL_LOGGING_FMT_HPP
#include <fmt/format.h>
#include <fmt/color.h>
#include <iostream>
#include <string>
#include <string_view>
#include <cstdio>
constexpr std::string_view CERR_FMT{"[{}] {}\n"};
namespace fggl::debug {
using FmtType = const std::string_view;
/**
* Logging levels
*/
enum class Level {
critical = 0,
error = 1,
warning = 2,
info = 3,
debug = 4,
trace = 5
};
constexpr std::string_view level_to_string(Level level) {
switch (level) {
case Level::critical: return "CRITICAL";
case Level::error: return "ERROR";
case Level::warning: return "WARNING";
case Level::info: return "INFO";
case Level::debug: return "DEBUG";
case Level::trace: return "TRACE";
default: return "UNKNOWN";
}
}
inline void vlog(const char *file, int line, fmt::string_view format, fmt::format_args args) {
fmt::print("{}: {}", file, line);
fmt::vprint(format, args);
}
template<typename S, typename... Args>
void logf(const char *file, int line, const S &format, Args &&... args) {
vlog(file, line, format, fmt::make_format_args(format, args...));
}
#define info_va(format, ...) \
logf(__FILE__, __LINE__, FMT_STRING(format), __VA_ARGS__)
template<typename ...T>
void log(Level level, FmtType fmt, T &&...args) {
auto fmtStr = fmt::format(fmt::runtime(fmt), args...);
fmt::print(CERR_FMT, level_to_string(level), fmtStr);
}
// inlined, pre-set level versions of the log function above
template<typename ...T>
inline void error(FmtType fmt, T &&...args) {
auto fmtStr = fmt::format(fmt::runtime(fmt), args...);
fmt::print(fg(fmt::color::red), CERR_FMT, level_to_string(Level::error), fmtStr);
}
template<typename ...T>
inline void warning(FmtType fmt, T &&...args) {
auto fmtStr = fmt::format(fmt::runtime(fmt), args...);
fmt::print(fg(fmt::color::orange), CERR_FMT, level_to_string(Level::warning), fmtStr);
}
template<typename ...T>
inline void info(FmtType fmt, T &&...args) {
auto fmtStr = fmt::format(fmt::runtime(fmt), args...);
fmt::print(CERR_FMT, level_to_string(Level::info), fmtStr);
}
template<typename ...T>
inline void debug(FmtType fmt, T &&...args) {
auto fmtStr = fmt::format(fmt::runtime(fmt), args...);
fmt::print(CERR_FMT, level_to_string(Level::debug), fmtStr);
}
template<typename ...T>
inline void trace(FmtType fmt, T &&...args) {
auto fmtStr = fmt::format(fmt::runtime(fmt), args...);
fmt::print(CERR_FMT, level_to_string(Level::trace), fmtStr);
}
}
#endif //FGGL_DEBUG_IMPL_LOGGING_FMT_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 08/06/22.
//
#ifndef FGGL_DEBUG_IMPL_LOGGING_SPDLOG_HPP
#define FGGL_DEBUG_IMPL_LOGGING_SPDLOG_HPP
#include <string>
#include <iostream>
#include <memory>
#include <spdlog/spdlog.h>
#include <spdlog/sinks/stdout_color_sinks.h>
namespace fggl::debug {
using FmtType = const std::string_view;
/**
* Logging levels
*/
enum class Level {
critical = spdlog::level::critical,
error = spdlog::level::err,
warning = spdlog::level::warn,
info = spdlog::level::info,
debug = spdlog::level::debug,
trace = spdlog::level::trace
};
template<typename ...T>
void error(const FmtType &fmt, T &&...args) {
spdlog::error(fmt, args...);
}
template<typename ...T>
void warning(const FmtType &fmt, T &&...args) {
spdlog::warn(fmt, args...);
}
template<typename ...T>
void info(const FmtType &fmt, T &&...args) {
spdlog::info(fmt, args...);
}
template<typename ...T>
void debug(const FmtType &fmt, T &&...args) {
spdlog::debug(fmt, args...);
}
template<typename ...T>
void trace(const FmtType &fmt, T &&...args) {
spdlog::trace(fmt, args...);
}
template<typename ...T>
void log(const FmtType &fmt, T &&...args) {
spdlog::log(Level::info, fmt, args...);
}
template<typename ...T>
void log(Level level, const FmtType &fmt, T &&...args) {
spdlog::log(level, fmt, args...);
}
class Logger {
public:
Logger();
template<typename ...Args>
void log(Level level, const FmtType &fmt, Args &&...args) {
spdlog::log(level, fmt, args...);
}
};
}
#endif //FGGL_DEBUG_IMPL_LOGGING_SPDLOG_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 10/07/23.
//
#ifndef FGGL_COMPONENTS_CORE_DEBUG_LOGGING_HPP
#define FGGL_COMPONENTS_CORE_DEBUG_LOGGING_HPP
#include <string_view>
namespace fggl::debug {
std::string demangle(const char* name);
using FmtType = const std::string_view;
enum class Level;
template<typename ...T>
void error(FmtType fmt, T &&...args);
template<typename ...T>
void warning(FmtType fmt, T &&...args);
template<typename ...T>
void info(FmtType fmt, T &&...args);
template<typename ...T>
void debug(FmtType fmt, T &&...args);
template<typename ...T>
void trace(FmtType fmt, T &&...args);
template<typename ...T>
void log(FmtType fmt, T &&...args);
template<typename ...T>
void log(Level level, FmtType fmt, T &&...args);
}
#include "fggl/debug/impl/logging_fmt.hpp"
#endif //FGGL_COMPONENTS_CORE_DEBUG_LOGGING_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 10/07/23.
//
#ifndef FGGL_COMPONENTS_CORE_FILESYSTEM_FINDER_HPP
#define FGGL_COMPONENTS_CORE_FILESYSTEM_FINDER_HPP
#include <filesystem>
#include <optional>
#include <vector>
#include "fggl/services/service.hpp"
#include "fggl/services/module.hpp"
#include "fggl/platform/paths.hpp"
namespace fggl::filesystem {
constexpr unsigned char MASK_OWNER = 0b11110000;
constexpr unsigned char MASK_CONTEXT = 0b00001111;
enum class Owner : unsigned char {
GAME = 0b00010000,
DLC = 0b00100000,
MOD = 0b01000000,
USER = 0b10000000,
ANY = 0b11110000
};
enum class Context : unsigned char {
RESOURCE = 0b00000001,
CONFIG = 0b00000010,
CACHE = 0b00000100,
TMP = 0b00001000
};
/**
* Filesystem API contract.
*
* A module providing this contract must:
* * provide a Locator service (as defined below)
*/
FGGL_MODULE_CONTRACT(API, "fggl::filesystem::API")
class Locator {
public:
FGGL_DEFINE_SERVICE(fggl::filesystem::Locator)
using Path = std::filesystem::path;
Locator();
Path calculate(const char* name, Context context = Context::RESOURCE, Owner owner = Owner::ANY);
inline Path calculate(const std::string& name, Context context = Context::RESOURCE, Owner owner = Owner::ANY) {
return calculate(name.c_str(), context, owner);
}
std::optional<Path> find(const char* name, Context context = Context::RESOURCE, Owner owner = Owner::ANY);
inline std::optional<Path> find(const std::string& name, Context context = Context::RESOURCE, Owner owner = Owner::ANY) {
return find(name.c_str(), context, owner);
}
std::optional<Path> createUser(const char* name, Context context = Context::CONFIG);
inline std::optional<Path> createUser(const std::string& name, Context context = Context::CONFIG) {
return createUser(name.c_str(), context);
}
private:
fggl::platform::EnginePaths m_paths;
};
std::vector<Locator::Path> findAllMatching(Locator::Path root, const std::string& suffix);
void findAllMatching(Locator::Path root, const std::string& suffix, std::vector<Locator::Path>&);
} // namespace fggl::filesystem
#endif //FGGL_COMPONENTS_CORE_FILESYSTEM_FINDER_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 12/07/23.
//
#ifndef FGGL_COMPONENTS_CORE_FILESYSTEM_MODULE_HPP
#define FGGL_COMPONENTS_CORE_FILESYSTEM_MODULE_HPP
#include "fggl/services/module.hpp"
namespace fggl::filesystem {
class NativeBacked : public services::Module {
FGGL_MODULE(fggl::filesystem::Native)
auto getProvides() const -> Module::ServiceList override;
void wireServices(services::ModuleBinder& binder) override;
};
} // namespace fggl::filesystem
#endif //FGGL_COMPONENTS_CORE_FILESYSTEM_MODULE_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 12/07/23.
//
#ifndef FGGL_COMPONENTS_CORE_FILESYSTEM_READER_HPP
#define FGGL_COMPONENTS_CORE_FILESYSTEM_READER_HPP
#include <filesystem>
#include <optional>
#include <vector>
#include "fggl/services/service.hpp"
#include "fggl/services/module.hpp"
#include "fggl/platform/paths.hpp"
#include "Finder.hpp"
namespace fggl::filesystem {
class Reader {
public:
FGGL_DEFINE_SERVICE(fggl::filesystem::Reader)
using Path = std::filesystem::path;
inline explicit Reader(Locator* locator) : m_locator(locator){};
std::optional<std::string> readText(const char* name, Context context = Context::RESOURCE, Owner owner = Owner::ANY);
char* readBytes(const char* name, Context context = Context::RESOURCE, Owner owner = Owner::ANY);
template<typename T>
std::optional<T> readAs(const char* name, std::function<std::optional<T>(Path&)> converter, Context context = Context::RESOURCE, Owner owner = Owner::ANY) {
auto path = m_locator->find(name, context, owner);
if ( !path.has_value() ){
return {};
}
return converter(path);
}
private:
Locator* m_locator;
};
} // namespace fggl::filesystem
#endif //FGGL_COMPONENTS_CORE_FILESYSTEM_READER_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 10/07/23.
//
#ifndef FGGL_COMPONENTS_CORE_MATHS_COMMON_HPP
#define FGGL_COMPONENTS_CORE_MATHS_COMMON_HPP
#include <cmath>
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/glm.hpp>
namespace fggl::maths {
template<typename T>
struct Scale {
T start;
T end;
[[nodiscard]]
constexpr bool inRange(T value) const {
return start <= value && value <= end;
}
[[nodiscard]]
constexpr T lerp(T value) const {
assert(T(0) <= value && value <= T(1));
return (T(1) - value) * start + value * end;
}
[[nodiscard]]
constexpr T midpoint() const {
return (end + start) / T(2);
}
[[nodiscard]]
constexpr T range() const {
return end - start;
}
[[nodiscard]]
constexpr T wrap(float value) const {
value -= start;
return value - (range() * std::floor(value / range())) + start;
}
[[nodiscard]]
constexpr T clamp(T value) const {
const T valueOrMin = value < start ? start : value;
return valueOrMin > end ? end : valueOrMin;
}
[[nodiscard]]
constexpr T rescale(T input, Scale target) const {
return ((input - start) * target.range()) / range();
}
constexpr static Scale make(T minValue, T maxValue) {
assert( minValue < maxValue );
return {minValue, maxValue};
}
};
} // namespace fggl::maths
#endif //FGGL_COMPONENTS_CORE_MATHS_COMMON_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 10/07/23.
//
#ifndef FGGL_COMPONENTS_CORE_MATHS_FMATH_HPP
#define FGGL_COMPONENTS_CORE_MATHS_FMATH_HPP
#include "common.hpp"
#include <array>
namespace fggl::maths {
/**
* return the remainder (modulo) of value / maximum.
*
* This will return a value in the range [0, maximum), the result will always be positive, even if passed a negative
* input.
*
* @param value the value to wrap.
* @param max the maximum value that it can take.
* @return the wrapped value
*/
constexpr float wrap(float value, float max) {
return fmodf(max + fmodf(value, max), max);
}
/**
* wrap value in range [min, max)
*
* If the range overflows, return the modulo of the value.
*
* @param value the value to be tested.
* @param min the minimum allowable value
* @param max the maximum allowable value
*/
constexpr float wrap(float value, float min, float max) {
if (min > max) {
std::swap(min, max);
};
value -= min;
float rangeSize = max - min;
return value - (rangeSize * std::floor(value / rangeSize)) + min;
}
/**
* Ensure that value is wrapped in the range [min, max].
*
* If the value under or over flows, return the limit of the range.
* if the value is larger than max, return max.
* if the value is smaller than min, return min.
*
* @param value the value to be tested.
* @param min the minimum allowable value
* @param max the maximum allowable value
* @return value, if it is in the range [min, max], otherwise the bound that it is outside of.
*/
constexpr float clamp(float value, float min, float max) {
const float valueOrMin = value < min ? min : value;
return valueOrMin > max ? max : valueOrMin;
}
/**
* Free function form of linear interpolation.
*
* @param start the starting value for the range
* @param end the ending value for the range
* @param value value [0,1] along the range
* @return the linearly interpolated value from the provided range
*/
constexpr float lerp(float start, float end, float value) {
assert( 0.0F <= value && value <= 1.0F );
assert( start < end );
return (1 - value) * start + value * end;
}
/**
* Floating point scales
*/
using ScaleF = Scale<float>;
/**
* A scale where values are between 0 and 1, midpoint 0.5
*/
constexpr ScaleF SCALE01 = ScaleF::make(0.0F, 1.0F);
/**
* A scale where values are between -1 and 1, midpoint 0
*/
constexpr ScaleF SCALE11 = ScaleF::make(-1.0F, 1.0F);
} // namespace fggl::maths
#endif //FGGL_COMPONENTS_CORE_MATHS_FMATH_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 10/07/23.
//
#ifndef FGGL_COMPONENTS_CORE_MATHS_IMATH_HPP
#define FGGL_COMPONENTS_CORE_MATHS_IMATH_HPP
#include "common.hpp"
namespace fggl::maths {
/**
* Integer Scales
*/
using ScaleI = Scale<int64_t>;
using ScaleUI = Scale<uint64_t>;
} // namespace fggl::maths
#endif //FGGL_COMPONENTS_CORE_MATHS_IMATH_HPP
......@@ -21,8 +21,6 @@
#ifndef FGGL_PLATFORM_FALLBACK_PATHS_HPP
#define FGGL_PLATFORM_FALLBACK_PATHS_HPP
#include "fggl/platform/paths.hpp"
#include <filesystem>
#include <array>
......@@ -91,6 +89,6 @@ namespace fggl::platform {
std::filesystem::path locate_config(const EnginePaths &paths, const std::filesystem::path &relPath);
std::filesystem::path locate_cache(const EnginePaths &paths, const std::filesystem::path &relPath);
}
} // namespace fggl::platform
#endif //FGGL_PLATFORM_FALLBACK_PATHS_HPP
......@@ -21,8 +21,6 @@
#ifndef FGGL_PLATFORM_LINUX_PATHS_HPP
#define FGGL_PLATFORM_LINUX_PATHS_HPP
#include "fggl/platform/paths.hpp"
#include <filesystem>
#include <array>
......@@ -60,7 +58,8 @@ namespace fggl::platform {
std::filesystem::path locate_data(const EnginePaths &paths, const std::filesystem::path &relPath);
std::filesystem::path locate_config(const EnginePaths &paths, const std::filesystem::path &relPath);
std::filesystem::path locate_cache(const EnginePaths &paths, const std::filesystem::path &relPath);
std::filesystem::path locate_temp(const EnginePaths& paths, const std::filesystem::path &relPath);
}
} // namespace fggl::platform
#endif //FGGL_PLATFORM_LINUX_PATHS_HPP
......@@ -13,21 +13,18 @@
*/
//
// Created by webpigeon on 26/06/22.
// Created by webpigeon on 10/07/23.
//
#ifndef FGGL_PLATFORM_PATHS_HPP
#define FGGL_PLATFORM_PATHS_HPP
#include <filesystem>
#include <vector>
#ifndef FGGL_COMPONENTS_CORE_PLATFORM_PATHS_HPP
#define FGGL_COMPONENTS_CORE_PLATFORM_PATHS_HPP
#ifdef __linux__
#define FGGL_PLATFORM_PATHS linux
#include "fggl/platform/linux/paths.hpp"
#include "linux/paths.hpp"
#else
#define FGGL_PLATFORM_PATHS fallback
#include "fggl/platform/fallback/paths.hpp"
#include "fallback/paths.hpp"
#endif
#endif //FGGL_PLATFORM_PATHS_HPP
#endif //FGGL_COMPONENTS_CORE_PLATFORM_PATHS_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 10/07/23.
//
#ifndef FGGL_COMPONENTS_CORE_SERVICES_FACTORY_HPP
#define FGGL_COMPONENTS_CORE_SERVICES_FACTORY_HPP
#include <algorithm>
#include <functional>
#include <optional>
#include <cassert>
#include <memory>
#include "registry.hpp"
namespace fggl::services {
#ifdef NDEBUG
class Generator;
using GeneratorView = Generator;
#else
class GeneratorView;
#endif
class Generator;
struct ServiceBinding {
public:
virtual ~ServiceBinding() = default;
virtual std::shared_ptr<void> provide() = 0;
};
template<ServiceAPI T>
struct ServiceBindingT;
class Generator {
public:
Generator() = default;
// no copy
Generator(Generator&) = delete;
void operator=(Generator&) = delete;
template<ServiceAPI api>
Service<api> getLazy() {
assert( m_factories.find(api::SERVICE_ID) != m_factories.end() );
if ( m_registry.contains(api::SERVICE_ID) ) {
return m_registry.get<api>();
}
// does not exist, invoke factory
return buildAndStore<api>();
}
template<ServiceAPI api>
void bind(ServiceBinding&& binding) {
m_factories[ api::SERVICE_ID ] = binding;
}
template<ServiceAPI api>
ServiceBindingT<api>& createBinding() {
auto ptr = std::make_shared<ServiceBindingT<api>>(this);
m_factories[ api::SERVICE_ID ] = ptr;
return *(ptr.get());
}
template<ServiceAPI api>
Service<api> build() {
auto ptrRaw = invokeFactoryRaw(api::SERVICE_ID);
return Service( std::static_pointer_cast<api>(ptrRaw) );
}
template<ServiceAPI api>
std::optional<Service<api>> getFromCache() const {
if ( !m_registry.contains(api::SERVICE_ID) ) {
return {};
}
return m_registry.get<api>();
}
inline bool canBuild(ServiceName name) const {
return m_registry.contains(name) || m_factories.find(name) != m_factories.end();
}
private:
Registry m_registry;
std::map<ServiceName, std::shared_ptr<ServiceBinding>> m_factories;
std::shared_ptr<void> invokeFactoryRaw(ServiceName name);
template<ServiceAPI api>
Service<api> buildAndStore() {
auto ptr = invokeFactoryRaw(FGGL_SERVICE(api));
m_registry.provideUnsafe(FGGL_SERVICE(api), ptr);
return m_registry.get<api>();
}
};
template<ServiceAPI T>
struct ServiceBindingT : public ServiceBinding {
using Factory = std::function<std::shared_ptr<T>(Generator* generator)>;
inline explicit ServiceBindingT(Generator* generator) : m_generator(generator) {}
inline ServiceBindingT<T>& toFactory(Factory factory) {
m_instance = nullptr;
m_factory = factory;
return *this;
}
inline ServiceBindingT<T>& asSingleton() {
m_singleton = true;
return *this;
}
inline ServiceBindingT<T>& simply() {
m_instance = nullptr;
m_factory = [](const GeneratorView* /*generator*/) {
return std::make_shared<T>();
};
return *this;
}
template<ServiceAPI... Deps>
inline ServiceBindingT<T>& depends(){
m_instance = nullptr;
m_factory = [](Generator* generator) {
return std::make_shared<T>( generator->getLazy<Deps>().ptr()... );
};
return *this;
}
template<Subclass<T> Impl>
inline ServiceBindingT<T>& simplyTo(){
m_instance = nullptr;
m_factory = [](const GeneratorView* /*generator*/) {
return std::make_shared<Impl>();
};
return *this;
}
template<Subclass<T> Impl, ServiceAPI... Deps, typename... Args>
inline ServiceBindingT<T>& to(Args... args){
m_instance = nullptr;
m_factory = [args...](Generator* generator) {
return std::make_shared<Impl>( generator->getLazy<Deps>().ptr()..., args... );
};
return *this;
}
std::shared_ptr<void> provide() override {
return provideT();
}
inline std::shared_ptr<T> provideT() {
assert( m_generator != nullptr );
if ( m_instance != nullptr ){
return m_instance;
}
if ( m_factory != nullptr ) {
if ( m_singleton ) {
m_instance = m_factory(m_generator);
return m_instance;
}
return m_factory(m_generator);
}
return nullptr;
}
private:
Generator* m_generator = nullptr;
std::shared_ptr<T> m_instance = nullptr;
Factory m_factory = nullptr;
bool m_singleton = false;
};
#ifndef NDEBUG
struct GeneratorView {
public:
inline GeneratorView(Generator* generator, const std::vector<ServiceName>& depends) : m_generator(generator), m_declared(depends) {}
template<ServiceAPI api>
std::optional<Service<api>> get() const {
assert(std::find( m_declared.begin(), m_declared.end(), api::service ) != m_declared.end());
return m_generator->get<api>();
}
private:
Generator* m_generator;
std::vector<ServiceName> m_declared;
};
#endif
template<ServiceAPI impl, typename... Args>
std::shared_ptr<void> wire_func(GeneratorView* view) {
return std::make_shared<impl>( view->getLazy<Args...>() );
}
} // namespace fggl::services
#endif //FGGL_COMPONENTS_CORE_SERVICES_FACTORY_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/>.
*/
#ifndef FGGL_CORE_SERVICES_MODULE_HPP
#define FGGL_CORE_SERVICES_MODULE_HPP
#include "service.hpp"
#include "factory.hpp"
#include <iostream>
#define FGGL_MODULE(id, ...) constexpr static const char* MODULE_ID = #id; \
constexpr static const auto MODULE_DEPS = fggl::services::mod_extract_names<__VA_ARGS__>(); \
inline fggl::services::ModuleID getName() const override { return MODULE_ID; } \
inline fggl::services::Module::ServiceList getDepends() const override { return fggl::services::mod_svc_list( MODULE_DEPS ); }
#define FGGL_MODULE_CONTRACT(name, id) struct name { constexpr static const char* MODULE_ID = #id; };
#include <functional>
namespace fggl::services {
struct ModuleBinder {
public:
inline ModuleBinder(Generator* generator) : m_generator(generator) {}
template<ServiceAPI T>
ServiceBindingT<T>& bind() {
std::cerr << "generating binding for: " << T::SERVICE_ID.get() << std::endl;
return m_generator->createBinding<T>();
}
private:
Generator *m_generator;
};
using ModuleID = const char*;
template<typename T>
concept ModuleAPI = requires(T* type) {
{ T::MODULE_ID };
};
class Module {
public:
using ServiceList = std::vector<ModuleID>;
virtual ~Module() = default;
[[nodiscard]]
virtual ModuleID getName() const = 0;
virtual void wireServices(ModuleBinder& binder) = 0;
[[nodiscard]]
virtual ServiceList getProvides() const;
[[nodiscard]]
virtual ServiceList getDepends() const = 0;
// callback methods
virtual void setup(Generator* generator);
virtual void teardown();
};
template<ModuleAPI... T>
constexpr auto mod_extract_names() {
return std::array<ModuleID, sizeof...(T)>{ T::MODULE_ID... };
}
template<typename T>
inline Module::ServiceList mod_svc_list(T items) {
Module::ServiceList deps{};
for (auto& dep : items) {
deps.push_back(dep);
}
return deps;
}
} // namespace fggl::services
#endif
\ No newline at end of file
/*
* 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 10/07/23.
//
#ifndef FGGL_COMPONENTS_CORE_SERVICES_REGISTRY_HPP
#define FGGL_COMPONENTS_CORE_SERVICES_REGISTRY_HPP
#include "service.hpp"
#include <memory>
#include <map>
namespace fggl::services {
template<typename T, typename U>
concept Subclass = std::is_base_of<U, T>::value;
class Registry {
public:
void provideUnsafe(ServiceName api, std::shared_ptr<void> service) {
m_services[ api ] = service;
}
inline bool contains(ServiceName service) const {
return m_services.find(service) != m_services.end();
}
template<ServiceAPI svc>
Service<svc> get() const {
auto wrapper = m_services.at( svc::SERVICE_ID );
auto ptr = std::static_pointer_cast<svc>(wrapper);
return Service<svc>(ptr);
}
private:
std::map<ServiceName, std::shared_ptr<void>> m_services;
};
} // namespace fggl::services
#endif //FGGL_COMPONENTS_CORE_SERVICES_REGISTRY_HPP
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment