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 1838 additions and 13 deletions
/*
* 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/06/22.
// see https://youtrack.jetbrains.com/issue/CPP-5059
#ifndef FGGL_DEBUG_PRAGMAS_HPP
#define FGGL_DEBUG_PRAGMAS_HPP
#if defined(__clang__)
#define PRAGMA_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push")
#elif defined(__GNUC__)
#define PRAGMA_DIAGNOSTIC_PUSH _Pragma("gcc diagnostic push")
#else
#define PRAGMA_DIAGNOSTIC_PUSH
#endif
#if defined(__clang__)
#define PRAGMA_DIAGNOSTIC_POP _Pragma("clang diagnostic pop")
#elif defined(__GNUC__)
#define PRAGMA_DIAGNOSTIC_POP _Pragma("gcc diagnostic pop")
#else
#define PRAGMA_DIAGNOSTIC_POP
#endif
#if defined(__JETBRAINS_IDE__)
#define PRAGMA_CLION_IGNORED(x) _Pragma("ide diagnostic ignored \"" x "\"")
#else
#define PRAGMA_CLION_IGNORED
#endif
#endif //FGGL_DEBUG_PRAGMAS_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/06/22.
//
#ifndef FGGL_DISPLAY_GLFW_MODULE_HPP
#define FGGL_DISPLAY_GLFW_MODULE_HPP
#include "fggl/display/window.hpp"
#include "fggl/input/module.hpp"
#include "fggl/display/glfw/window.hpp"
#include "fggl/display/glfw/services.hpp"
namespace fggl::display {
struct GLFW {
constexpr static const char *name = "fggl::display::glfw";
constexpr static const std::array<modules::ServiceName, 1> provides = {
WindowService::service
};
constexpr static const std::array<modules::ServiceName, 2> depends = {
fggl::input::Input::service,
fggl::gfx::WindowGraphics::service
};
static bool factory(modules::ServiceName name, modules::Services &serviceManager);
};
bool GLFW::factory(modules::ServiceName service, modules::Services &services) {
if (service == WindowService::service) {
auto input = services.get<input::Input>();
auto graphics = services.get<gfx::WindowGraphics>();
auto context = std::make_shared<glfw::GlfwContext>(input);
services.bind<WindowService, glfw::WindowService>(context, graphics);
return true;
}
return false;
}
} // namespace fggl::display
#endif //FGGL_DISPLAY_GLFW_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 27/06/22.
//
#ifndef FGGL_DISPLAY_GLFW_SERVICES_HPP
#define FGGL_DISPLAY_GLFW_SERVICES_HPP
#include "fggl/display/window.hpp"
#include "fggl/gfx/setup.hpp"
#include <memory>
#include <utility>
#include <vector>
namespace fggl::display::glfw {
class WindowService : public display::WindowService {
public:
explicit WindowService(std::shared_ptr<GlfwContext> context, gfx::WindowGraphics *gfx)
: m_context(std::move(context)), m_gfx(gfx), m_windows() {}
virtual ~WindowService() = default;
display::Window *create() override {
m_windows.push_back(std::make_unique<Window>(m_context, m_gfx));
return m_windows.back().get();
}
void pollEvents() override {
m_context->pollEvents();
}
private:
std::shared_ptr<GlfwContext> m_context;
gfx::WindowGraphics *m_gfx;
std::vector<std::unique_ptr<Window>> m_windows;
};
} // namespace fggl::display
#endif //FGGL_DISPLAY_GLFW_SERVICES_HPP
#ifndef FGGL_GFX_H
#define FGGL_GFX_H
/*
* 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/>.
*/
/*
* 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_GFX_WINDOW_HPP
#define FGGL_GFX_WINDOW_HPP
#include <cassert>
#include <string>
#include <memory>
#include <fggl/input/input.hpp>
#include <fggl/gfx/common.hpp>
#include <fggl/math/types.hpp>
#include <fggl/gfx/input.hpp>
#include "fggl/input/input.hpp"
#include "fggl/gfx/common.hpp"
#include "fggl/math/types.hpp"
#include "fggl/display/window.hpp"
#include "fggl/gfx/setup.hpp"
namespace fggl::gfx {
namespace fggl::display::glfw {
class Window;
class GlfwContext {
public:
explicit GlfwContext(std::shared_ptr<fggl::input::Input> input);
explicit GlfwContext(fggl::input::Input *input);
~GlfwContext();
void pollEvents();
private:
std::vector<std::unique_ptr<Window>> m_windows;
};
enum MutWindowHint {
......@@ -27,6 +61,7 @@ namespace fggl::gfx {
AutoIconify = GLFW_AUTO_ICONIFY,
FocusOnShow = GLFW_FOCUS_ON_SHOW
};
enum WindowHint {
Focused = GLFW_FOCUSED,
Iconified = GLFW_ICONIFIED,
......@@ -39,15 +74,26 @@ namespace fggl::gfx {
GlDebugContext = GLFW_OPENGL_DEBUG_CONTEXT,
NoError = GLFW_CONTEXT_NO_ERROR
};
class Window {
class Window : public display::Window {
public:
Window();
~Window();
Window(Window&) = delete;
explicit Window(std::shared_ptr<GlfwContext> context, gfx::WindowGraphics *);
~Window() override;
Window(Window &) = delete;
Window(Window &&) = delete;
[[nodiscard]]
math::vec2i frameSize() const override;
[[nodiscard]]
bool wantClose() const override;
// window <-> opengl stuff
void activate() const;
void swap();
void activate() const override;
void frameStart() override;
void frameEnd() override;
inline float width() const {
return m_framesize.x;
......@@ -58,40 +104,43 @@ namespace fggl::gfx {
}
inline void framesize(int width, int height) {
m_framesize = math::vec2( width, height );
m_framesize = math::vec2(width, height);
if (m_graphics != nullptr) {
m_graphics->resize(width, height);
}
}
// window manager stuff
[[nodiscard]]
inline bool closeRequested() const {
assert( m_window != nullptr );
assert(m_window != nullptr);
return glfwWindowShouldClose(m_window);
}
inline void title(const std::string& title) {
assert( m_window != nullptr );
glfwSetWindowTitle( m_window, title.c_str() );
inline void setTitle(const char *title) override {
assert(m_window != nullptr);
glfwSetWindowTitle(m_window, title);
}
[[nodiscard]]
inline bool fullscreen() const {
assert( m_window != nullptr );
return glfwGetWindowMonitor( m_window ) != nullptr;
inline bool isFullscreen() const override {
assert(m_window != nullptr);
return glfwGetWindowMonitor(m_window) != nullptr;
}
inline void fullscreen(bool state) {
assert( m_window != nullptr );
if ( state ) {
inline void setFullscreen(bool state) override {
assert(m_window != nullptr);
if (state) {
auto monitor = glfwGetPrimaryMonitor();
const auto mode = glfwGetVideoMode( monitor );
glfwSetWindowMonitor( m_window, monitor,
0, 0,
mode->width, mode->height,
mode->refreshRate);
const auto mode = glfwGetVideoMode(monitor);
glfwSetWindowMonitor(m_window, monitor,
0, 0,
mode->width, mode->height,
mode->refreshRate);
} else {
glfwSetWindowMonitor( m_window, nullptr,
0, 0,
800, 600, 0);
glfwSetWindowMonitor(m_window, nullptr,
0, 0,
800, 600, 0);
}
}
......@@ -110,32 +159,33 @@ namespace fggl::gfx {
}
inline void visible(bool state) {
assert( m_window != nullptr );
if ( state ) {
glfwShowWindow( m_window );
assert(m_window != nullptr);
if (state) {
glfwShowWindow(m_window);
} else {
glfwHideWindow( m_window );
glfwHideWindow(m_window);
}
}
inline GLFWwindow* handle() {
assert( m_window != nullptr );
inline GLFWwindow *handle() {
assert(m_window != nullptr);
return m_window;
}
private:
GLFWwindow* m_window;
std::shared_ptr<GlfwContext> m_context;
GLFWwindow *m_window;
math::vec2 m_framesize;
inline void set_hint(int hint, bool state) const {
assert( m_window != nullptr );
glfwSetWindowAttrib( m_window, hint, state );
assert(m_window != nullptr);
glfwSetWindowAttrib(m_window, hint, state);
}
[[nodiscard]]
inline bool check_hint(int hint) const {
assert( m_window != nullptr );
return glfwGetWindowAttrib( m_window, hint) == GLFW_TRUE;
assert(m_window != nullptr);
return glfwGetWindowAttrib(m_window, hint) == GLFW_TRUE;
}
};
......
#ifndef FGGL_GFX_GLFW_INPUT_H
#define FGGL_GFX_GLFW_INPUT_H
/*
* 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/>.
*/
/*
* 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_GFX_WINDOW_INPUT_HPP
#define FGGL_GFX_WINDOW_INPUT_HPP
#include <memory>
#include <string>
#include <fggl/gfx/window.hpp>
#include <fggl/input/input.hpp>
#include "fggl/display/glfw/window.hpp"
#include "fggl/input/input.hpp"
namespace fggl::gfx {
namespace fggl::display::glfw {
class GlfwInputManager {
public:
static GlfwInputManager& instance() {
static GlfwInputManager &instance() {
static GlfwInputManager *instance = new GlfwInputManager();
return *instance;
}
inline void setup(std::shared_ptr<input::Input> input) {
inline void setup(input::Input *input) {
m_inputs = input;
}
inline void frame() {
m_inputs->frame(0.0f);
}
inline bool alive() {
return m_inputs != nullptr;
}
inline input::MouseInput& mouse() {
inline input::MouseInput &mouse() {
return m_inputs->mouse;
}
inline input::KeyboardInput& keyboard() {
inline input::KeyboardInput &keyboard() {
return m_inputs->keyboard;
}
inline input::GamepadInput& gamepads() {
inline input::GamepadInput &gamepads() {
return m_inputs->gamepads;
}
inline void onMouseMove(float x, float y) {
if (m_inputs != nullptr ) {
if (m_inputs != nullptr) {
m_inputs->mouse.axis(input::MouseAxis::X, x);
m_inputs->mouse.axis(input::MouseAxis::Y, y);
}
......@@ -52,19 +83,19 @@ namespace fggl::gfx {
}
inline void onMouseButton(int btn, bool state) {
if ( m_inputs != nullptr ) {
m_inputs->mouse.button((fggl::input::MouseButton)btn, state);
if (m_inputs != nullptr) {
m_inputs->mouse.button((fggl::input::MouseButton) btn, state);
}
}
inline void onKeyEvent(int scancode, bool state) {
if ( m_inputs != nullptr ) {
if (m_inputs != nullptr) {
m_inputs->keyboard.set(scancode, state);
}
}
private:
std::shared_ptr<input::Input> m_inputs;
input::Input *m_inputs;
};
......
/*
* 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/06/22.
//
#ifndef FGGL_DISPLAY_WINDOW_HPP
#define FGGL_DISPLAY_WINDOW_HPP
#include "fggl/modules/module.hpp"
#include "fggl/math/types.hpp"
#include "fggl/gfx/interfaces.hpp"
//! Classes responsible for interacting with display managers
namespace fggl::display {
class Window {
public:
virtual ~Window() = default;
virtual void activate() const = 0;
// window-related getters
[[nodiscard]]
virtual math::vec2i frameSize() const = 0;
[[nodiscard]]
virtual bool wantClose() const = 0;
// window callbacks
virtual void frameStart() = 0;
virtual void frameEnd() = 0;
gfx::Graphics &graphics() {
return *m_graphics;
}
virtual void setTitle(const char *title) = 0;
virtual void setFullscreen(bool state) = 0;
[[nodiscard]]
virtual bool isFullscreen() const = 0;
protected:
gfx::Graphics* m_graphics;
};
class WindowService {
public:
constexpr static const auto
service = modules::make_service("fggl::display::WindowService");
virtual Window *create() = 0;
virtual void pollEvents() = 0;
};
} // namespace fggl::display
#endif //FGGL_DISPLAY_WINDOW_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 25/03/23.
//
#ifndef FGGL_DS_GRAPH_HPP
#define FGGL_DS_GRAPH_HPP
#include <map>
#include <vector>
#include <queue>
#include <stack>
#include <set>
namespace fggl::ds {
template<typename T>
class DirectedGraph {
public:
/**
* Add a single edge 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 start the entry which depends something else
* @param end the thing it depends on
*/
inline void addEdge(const T start, const T end) {
m_edges[start].push_back(end);
m_edges[end];
}
/**
* Add a single vertex to the graph.
*/
inline void addVertex(const T vertex) {
m_edges[vertex];
}
/**
* 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 addEdges(const T name, const std::vector<T> &dependencies) {
auto existing = m_edges.find(name);
if (existing == m_edges.end()) {
m_edges[name] = dependencies;
} else {
existing->second.insert(existing->second.end(), dependencies.begin(), dependencies.end());
}
}
/**
* Clear all currently stored dependencies.
*
* This method will result in the dependency graph being empty, with no known modules.
*/
inline void clear() {
m_edges.clear();
}
inline auto begin() const {
return m_edges.begin();
}
inline auto end() const {
return m_edges.end();
}
bool getOrder(std::stack<T> &stack) {
std::set<T> visited{};
for (const auto &module : m_edges) {
if (!visited.contains(module.first)) {
sortUtil(module.first, visited, stack);
}
}
return true;
}
bool getOrderPartial(T first, std::stack<T> &stack) {
std::set<T> visited{};
sortUtil(first, visited, stack);
return true;
}
bool getOrderRev(std::queue<T> &stack) {
std::set<T> visited{};
for (const auto &module : m_edges) {
if (!visited.contains(module.first)) {
sortUtilRev(module.first, visited, stack);
}
}
return true;
}
bool getOrderPartialRev(T first, std::queue<T>& queue) {
std::set<T> visited{};
sortUtilRev(first, visited, queue);
return true;
}
private:
std::map<T, std::vector<T>> m_edges;
void sortUtil(T idx, std::set<T> &visited, std::stack<T> &stack) {
visited.emplace(idx);
for (auto dep : m_edges.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_edges.at(idx)) {
if (!visited.contains(dep))
sortUtilRev(dep, visited, stack);
}
stack.push(idx);
}
};
} // namespace fggl::ds
#endif //FGGL_DS_GRAPH_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/>.
*/
//
// Wrappers for types that probably should be implemented, but can be faked for now.
// These are placeholders for the more advanced/specialist data structures we should be using, but mocked out using
// more basic ones.
//
#ifndef FGGL_DS_PLACEHOLDER_HPP
#define FGGL_DS_PLACEHOLDER_HPP
#include <map>
#include <cassert>
namespace fggl::ds {
template<typename T, std::size_t N>
class FakeSlotMap {
public:
using WeakRef = std::size_t;
constexpr static WeakRef BAD_INDEX = 0;
inline bool valid(WeakRef idx) const {
return m_data.find(idx) != m_data.end();
}
WeakRef allocate() {
if (N <= m_data.size()) {
assert(0 && "Fake slot map emulated out of space");
return BAD_INDEX;
}
auto myIdx = m_nextIdx++;
m_data[myIdx] = T();
}
void free(WeakRef idx) {
m_data.erase(idx);
}
T &get(WeakRef idx) const {
assert(valid(idx));
return m_data[idx];
}
T *tryGet(WeakRef idx) const {
if (valid(idx)) {
return &m_data[idx];
}
return nullptr;
}
private:
std::map<WeakRef, T> m_data;
std::size_t m_nextIdx = 1;
};
} // namespace fggl::ds
#endif //FGGL_DS_PLACEHOLDER_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 23/07/22.
//
#ifndef FGGL_DS_SLOT_MAP_HPP
#define FGGL_DS_SLOT_MAP_HPP
#include "fggl/ds/placeholder.hpp"
namespace fggl::ds {
template<typename T, std::size_t N>
using SlotMap = FakeSlotMap<T, N>;
} // namespace fggl::ds
#endif //FGGL_DS_SLOT_MAP_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 24/07/22.
//
#ifndef FGGL_ENTITY_ENTITY_HPP
#define FGGL_ENTITY_ENTITY_HPP
#include <cstdint>
#include <map>
#include <vector>
#include "fggl/debug/logging.hpp"
#include "fggl/vendor/entt.hpp"
namespace fggl::entity {
using EntityID = entt::entity;
constexpr EntityID INVALID = entt::null;
class EntityManager {
public:
inline EntityID create() {
return m_registry.create();
}
inline void destroy(EntityID entity) {
m_registry.destroy(entity);
}
template<typename Component, typename... Args>
inline Component &add(EntityID entity, Args &&... args) {
return m_registry.get_or_emplace<Component>(entity, std::forward<Args>(args)...);
}
template<typename Component>
Component &get(EntityID entity) {
#ifndef NDEBUG
if (!has<Component>(entity)) {
debug::error("Entity {} has no component of type {}", (uint64_t) entity, debug::demangle(typeid(Component).name()));
assert(false && "Entity was missing component - use tryGet or fix definition");
}
#endif
return m_registry.get<Component>(entity);
}
template<typename Component>
const Component &get(EntityID entity) const {
return m_registry.get<Component>(entity);
}
template<typename Component>
Component *tryGet(EntityID entity) {
return m_registry.try_get<Component>(entity);
}
template<typename Component>
const Component *tryGet(EntityID entity, const Component* defaultValue = nullptr) const {
auto* comp = m_registry.try_get<Component>(entity);
return comp == nullptr ? defaultValue : comp;
}
template<typename ...Components>
auto find() const {
return m_registry.view<Components...>();
}
EntityID findByName(const std::string& name) const {
auto itr = m_names.find(name);
if ( itr == m_names.end() ){
return INVALID;
}
return m_registry.valid(itr->second) ? itr->second : INVALID;
}
inline void setName(const std::string& name, EntityID eid ) {
if ( eid == INVALID ) {
m_names.erase(name);
} else {
assert(m_registry.valid(eid));
m_names[name] = eid;
}
}
template<typename ...Components>
bool has(EntityID idx) const {
return m_registry.template all_of<Components...>(idx);
}
bool hasTag(EntityID entity, fggl::util::GUID tag) {
const auto mapItr = m_tags.find( tag );
if ( mapItr == m_tags.end() || !m_registry.valid(entity) ) {
return false;
}
return std::find(mapItr->second.begin(), mapItr->second.end(), entity) != mapItr->second.end();
}
void addTag(const EntityID entity, const fggl::util::GUID tag) {
assert( m_registry.valid(entity) );
auto& tagged = m_tags[ tag ];
tagged.push_back( entity );
}
void removeTag(const EntityID entity, const fggl::util::GUID tag) {
auto mapItr = m_tags.find(tag);
if ( mapItr == m_tags.end() ) {
return;
}
std::remove_if( mapItr->second.begin(), mapItr->second.end(), [entity](auto other) { return other == entity;} );
}
inline std::vector<EntityID> findByTag(const char* tag) {
return findByTag( util::make_guid_rt(tag) );
}
std::vector<EntityID> findByTag(const fggl::util::GUID tag){
auto mapItr = m_tags.find(tag);
if ( mapItr == m_tags.end() ) {
return {};
}
return mapItr->second;
}
inline bool exists(EntityID idx) const {
return m_registry.valid(idx);
}
inline bool alive(EntityID idx) const {
return m_registry.valid(idx);
}
private:
entt::registry m_registry;
std::map<std::string, EntityID> m_names;
std::map<fggl::util::GUID, std::vector<EntityID>> m_tags;
};
struct Entity {
static Entity make(EntityManager &manager, EntityID idx) {
return Entity{idx, manager};
}
EntityID id;
EntityManager &manager;
template<typename Component>
Component &get() {
return manager.get<Component>(id);
}
template<typename Component>
const Component &get() const {
return manager.get<Component>(id);
}
};
} // namespace fggl::entity
#endif //FGGL_ENTITY_ENTITY_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 20/08/22.
//
#ifndef FGGL_ENTITY_GRIDWORLD_ZONE_HPP
#define FGGL_ENTITY_GRIDWORLD_ZONE_HPP
#include <array>
#include <vector>
#include "fggl/math/types.hpp"
#include "fggl/assets/types.hpp"
#include "fggl/entity/entity.hpp"
namespace fggl::entity::grid {
using GridPos = math::vec2i;
constexpr auto ASSET_TILESET = assets::AssetType::make("tileset");
template<typename T, uint32_t width, uint32_t height>
struct Grid {
public:
Grid() = default;
inline T& get(GridPos pos) {
assert(inBounds(pos));
return m_cells[getCellIndex(pos)];
}
const T& get(GridPos pos) const {
assert(inBounds(pos));
return m_cells[getCellIndex(pos)];
}
inline void set(GridPos pos, T value) {
assert(inBounds(pos));
m_cells[getCellIndex(pos)] = value;
}
inline bool inBounds(GridPos pos) const {
return 0 <= pos.x && pos.x <= size.x &&
0 <= pos.y && pos.y <= size.y;
}
private:
constexpr static math::vec2i size = math::vec2ui(width, height);
std::array<T, size.x * size.y> m_cells;
inline uint32_t getCellIndex(GridPos pos) const {
assert( inBounds(pos));
return pos.y * size.x + pos.x;
}
};
struct FloorTile {
constexpr static uint8_t IMPOSSIBLE = 0;
uint8_t moveCost = IMPOSSIBLE;
math::vec3 colour = gfx::colours::CYAN;
};
struct WallTile {
bool render = false;
math::vec3 colour = gfx::colours::CYAN;
};
struct WallState {
uint32_t north = 0;
uint32_t west = 0;
};
struct TileSet {
std::vector<FloorTile> m_floors;
std::vector<WallTile> m_walls;
};
/**
* A 2D representation of a space.
*
* @tparam width the grid width in units
* @tparam height the grid height in units
*/
template<uint32_t width, uint32_t height>
struct Area2D {
public:
constexpr static std::array<math::vec2i, 4> DIRECTIONS{{ {-1, 0}, {0, -1}, {1, 0}, {0, 1} }};
inline explicit Area2D(TileSet& tiles) : m_tiles(tiles) {
clear();
}
[[nodiscard]]
inline bool inBounds(GridPos pos) const {
return 0 <= pos.x && pos.x <= width
&& 0 <= pos.y && pos.y <= height;
}
void clear() {
WallState noWall;
for (auto xPos = 0U; xPos<width; ++xPos) {
for (auto yPos=0U; yPos<height; ++yPos) {
m_floors.set({xPos, yPos}, 0);
m_walls.set({xPos, yPos}, noWall);
}
}
}
inline FloorTile& floorAt(uint32_t xPos, uint32_t yPos) {
return m_tiles.m_floors.at( m_floors.get({xPos, yPos}) );
}
inline void setFloorAt(uint32_t xPos, uint32_t yPos, uint32_t floor) {
m_floors.set({xPos, yPos}, floor);
}
inline WallTile& wallAt(uint32_t xPos, uint32_t yPos, bool north) {
if (north) {
return m_tiles.m_walls.at(m_walls.get({xPos, yPos}).north);
} else {
return m_tiles.m_walls.at(m_walls.get({xPos, yPos}).west);
}
}
inline void setWallAt(uint32_t xPos, uint32_t yPos, bool north, uint32_t wall) {
auto& state = m_walls.get({xPos, yPos});
if (north) {
state.north = wall;
} else {
state.west = wall;
}
}
inline bool canMove(GridPos pos) const {
if ( !inBounds(pos) ) {
return false;
}
return m_tiles.m_floors[m_floors.get(pos)].moveCost != FloorTile::IMPOSSIBLE;
}
inline bool canMove(GridPos pos, math::vec2i dir) const {
return canMove(pos + dir) && !blocked(pos, dir);
}
inline bool blocked(GridPos pos, math::vec2i dir) const;
EntityManager& entities() {
return m_entities;
}
inline void neighbours(math::vec2i pos, std::vector<math::vec2i> &neighbours) const {
for (auto direction : DIRECTIONS) {
if ( canMove(pos, direction) ) {
auto result = pos + direction;
neighbours.push_back(result);
}
}
}
private:
TileSet& m_tiles;
Grid<uint32_t, width, height> m_floors;
Grid<WallState, width + 1, height + 1> m_walls;
EntityManager m_entities;
};
template<uint32_t width, uint32_t height>
bool Area2D<width, height>::blocked(GridPos pos, math::vec2i dir) const {
auto targetPos = pos;
if ( dir.x == 1 || dir.y == 1 ) {
targetPos = pos + dir;
}
if ( !inBounds(targetPos) ) {
return true;
}
auto& wallObj = m_walls.get(targetPos);
if ( dir.y != 0 ) {
return wallObj.north != 0;
}
if (dir.x != 0) {
return wallObj.west != 0;
}
return true;
}
} // namespace fggl::entity::gridworld
#endif //FGGL_ENTITY_GRIDWORLD_ZONE_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 23/07/22.
//
#ifndef FGGL_ENTITY_LOADER_LOADER_HPP
#define FGGL_ENTITY_LOADER_LOADER_HPP
#include <functional>
#include <map>
#include <utility>
#include "fggl/util/guid.hpp"
#include "fggl/modules/module.hpp"
#include "fggl/entity/entity.hpp"
#include "fggl/entity/loader/spec.hpp"
#include "fggl/assets/loader.hpp"
namespace fggl::entity {
constexpr auto ENTITY_PROTOTYPE = assets::make_asset_type("entity/prototype");
constexpr auto ENTITY_SCENE = assets::make_asset_type("entity/scene");
using FactoryFunc = std::function<void(const ComponentSpec &config, EntityManager &, const EntityID &, modules::Services &svc)>;
using CustomiseFunc = std::function<void(EntityManager &, const EntityID &)>;
struct FactoryInfo {
FactoryFunc factory;
CustomiseFunc finalise = nullptr;
};
class EntityFactory {
public:
constexpr static const modules::ServiceName service = modules::make_service("fggl::entity:Factory");
inline EntityFactory(modules::Services &services) : m_services(services) {}
EntityID create(const EntityType &spec, EntityManager &manager, const CustomiseFunc &customise = nullptr) {
std::vector<CustomiseFunc> finishers;
// build the setup
auto entity = setupComponents(spec, manager, finishers);
if ( entity == entity::INVALID ) {
debug::error("EntityFactory: failed to build from prototype {}", std::to_string(spec.get()));
return entity::INVALID;
}
// if requested, allow the user to customize the creation
if ( customise != nullptr ) {
customise(manager, entity);
}
// run finishers for components
for ( auto& finisher : finishers ) {
finisher( manager, entity );
}
// use metadata to finalise
processTags(manager, entity, spec);
return entity;
}
void processTags(EntityManager& manager, EntityID id, EntityType spec) {
auto type = m_prototypes.at(spec);
for ( auto& tag : type.tags ) {
manager.addTag(id, tag);
}
}
void log_known_types() const {
debug::debug("dumping known types:");
for(const auto& [k,v] : m_factories) {
debug::debug("\ttype: {}", k);
}
}
void define(EntityType type, const EntitySpec &spec) {
m_prototypes[type] = spec;
}
// ability to set and unset factory functions
inline void bind(const ComponentID &configNode, FactoryFunc factory, CustomiseFunc finalise = nullptr) {
m_factories[configNode].factory = std::move(factory);
m_factories[configNode].finalise = std::move(finalise);
}
inline void unbind(const ComponentID &configNode) {
m_factories.erase(configNode);
}
inline FactoryInfo& getInfo(ComponentID comp) {
return m_factories.at(comp);
}
private:
modules::Services m_services;
std::map<ComponentID, FactoryInfo> m_factories;
std::map<EntityType, EntitySpec> m_prototypes;
entity::EntityID setupComponents(EntityType entityType,
EntityManager &manager,
std::vector<CustomiseFunc> &finishers) {
assert(entityType != NO_PARENT && "setup components called with NO_PARENT?!");
auto entity = manager.create();
std::vector<ComponentID> loadedComps;
auto currentType = entityType;
while (currentType != NO_PARENT) {
const auto& specEntry = m_prototypes.find( currentType );
if ( specEntry == m_prototypes.end() ) {
debug::warning("Asked to setup {}, for {} but was not a known prototype", specEntry->first, entityType);
return entity::INVALID;
}
auto entitySpec = specEntry->second;
debug::debug("constructing {} for {} ({} comps)", currentType, entityType, entitySpec.components.size());
assert( entitySpec.ordering.size() == entitySpec.components.size() && "ordering incorrect size, bad things happend!" );
for (auto &component : entitySpec.ordering) {
// skip comps loaded by children
if (std::find(loadedComps.begin(), loadedComps.end(), component) != loadedComps.end()) {
continue;
}
try {
auto &data = getComponent(entitySpec, component);
loadedComps.push_back(component);
auto &info = m_factories.at(component);
info.factory(data, manager, entity, m_services);
if (info.finalise != nullptr) {
finishers.push_back(info.finalise);
}
} catch (std::out_of_range &ex) {
debug::error( "EntityFactory: Unknown component factory type '{}'", component );
log_known_types();
manager.destroy(entity);
return entity::INVALID;
}
}
currentType = entitySpec.parent;
}
return entity;
}
ComponentSpec &getComponent(EntitySpec &prototype, util::GUID compToken) {
auto compItr = prototype.components.find(compToken);
if (compItr != prototype.components.end()) {
return compItr->second;
}
if (prototype.parent == NO_PARENT) {
throw std::out_of_range("EntityFactory: no such component!");
}
return getComponent(m_prototypes.at(prototype.parent), compToken);
}
};
assets::AssetRefRaw load_prototype(assets::Loader* loader, const assets::AssetID &guid, const assets::LoaderContext& data, EntityFactory* factory);
assets::AssetRefRaw load_scene(assets::Loader* loader, const assets::AssetID& asset, const assets::LoaderContext& data, void* ptr);
} // namespace fggl::entity
#endif //FGGL_ENTITY_LOADER_LOADER_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 24/07/22.
//
#ifndef FGGL_ENTITY_LOADER_SERIALISE_HPP
#define FGGL_ENTITY_LOADER_SERIALISE_HPP
#include "yaml-cpp/yaml.h"
#include "fggl/math/types.hpp"
#include "fggl/data/model.hpp"
#include "fggl/phys/types.hpp"
namespace YAML {
template<>
struct convert<fggl::math::vec3> {
static Node encode(const fggl::math::vec3 &rhs) {
Node node;
node.push_back(rhs.x);
node.push_back(rhs.y);
node.push_back(rhs.z);
return node;
}
static bool decode(const Node &node, fggl::math::vec3 &rhs) {
if (!node.IsSequence() || node.size() != 3) {
return false;
}
rhs.x = node[0].as<float>();
rhs.y = node[1].as<float>();
rhs.z = node[2].as<float>();
return true;
}
};
template<>
struct convert<fggl::math::vec2> {
static Node encode(const fggl::math::vec2 &rhs) {
Node node;
node.push_back(rhs.x);
node.push_back(rhs.y);
return node;
}
static bool decode(const Node &node, fggl::math::vec2 &rhs) {
if (!node.IsSequence() || node.size() != 2) {
return false;
}
rhs.x = node[0].as<float>();
rhs.y = node[1].as<float>();
return true;
}
};
template<>
struct convert<fggl::data::Vertex> {
static Node encode(const fggl::data::Vertex &rhs) {
Node node;
node["position"] = rhs.posititon;
node["normal"] = rhs.normal;
node["colour"] = rhs.colour;
node["texPos"] = rhs.texPos;
return node;
}
static bool decode(const Node &node, fggl::data::Vertex &rhs) {
if (!node.IsSequence() || node.size() != 2) {
return false;
}
rhs.posititon = node["position"].as<fggl::math::vec3>();
rhs.normal = node["normal"].as<fggl::math::vec3>();
rhs.colour = node["colour"].as<fggl::math::vec3>();
rhs.texPos = node["texPos"].as<fggl::math::vec2>();
return true;
}
};
template<>
struct convert<fggl::phys::BodyType> {
static Node encode(const fggl::phys::BodyType &rhs) {
Node node;
if (rhs == fggl::phys::BodyType::STATIC) {
node = "static";
} else if (rhs == fggl::phys::BodyType::DYNAMIC) {
node = "dynamic";
} else if (rhs == fggl::phys::BodyType::KINEMATIC) {
node = "kinematic";
}
return node;
}
static bool decode(const Node &node, fggl::phys::BodyType &rhs) {
auto strVal = node.as<std::string>();
if (strVal == "static") {
rhs = fggl::phys::BodyType::STATIC;
return true;
}
if (strVal == "dynamic") {
rhs = fggl::phys::BodyType::DYNAMIC;
return true;
}
if (strVal == "kinematic") {
rhs = fggl::phys::BodyType::KINEMATIC;
return true;
}
return false;
}
};
template<>
struct convert<fggl::util::GUID> {
static Node encode(const fggl::util::GUID &rhs) {
Node node;
node = rhs.get();
return node;
}
static bool decode(const Node &node, fggl::util::GUID &rhs) {
auto longVal = node.as<uint64_t>(0);
if (longVal == 0) {
// probably meant to hash it...
auto stringVal = node.as<std::string>();
rhs = fggl::util::make_guid_rt(stringVal);
return true;
}
// it's probably pre-hashed...
rhs = fggl::util::GUID::make(longVal);
return true;
}
};
}
#endif //FGGL_ENTITY_LOADER_SERIALISE_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 23/07/22.
//
#ifndef FGGL_ENTITY_LOADER_SPEC_HPP
#define FGGL_ENTITY_LOADER_SPEC_HPP
#include "fggl/util/guid.hpp"
#include "fggl/entity/loader/serialise.hpp"
#include <map>
namespace fggl::entity {
using ComponentID = util::GUID;
using EntityType = util::GUID;
constexpr EntityType NO_PARENT = util::make_guid("FGGL_NULL_PARENT");
struct ComponentSpec {
template<typename T>
T get(const std::string &key, const T &fallback) const {
return config[key].template as<T>(fallback);
}
template<typename T>
void set(const std::string &key, const T &value) {
config[key] = value;
}
inline bool has(const std::string &key) const {
return (bool) (config[key]);
}
YAML::Node config;
};
struct EntitySpec {
EntityType parent = NO_PARENT;
std::vector<util::GUID> tags;
std::vector<ComponentID> ordering;
std::map<ComponentID, ComponentSpec> components;
inline void addComp(ComponentID cmp, const ComponentSpec& spec) {
components[cmp] = spec;
ordering.push_back(cmp);
}
};
} // namespace fggl::entity
#endif //FGGL_ENTITY_LOADER_SPEC_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 24/07/22.
//
#ifndef FGGL_ENTITY_MODULE_HPP
#define FGGL_ENTITY_MODULE_HPP
#include "fggl/modules/module.hpp"
#include "fggl/assets/loader.hpp"
#include "fggl/assets/packed/adapter.hpp"
#include "fggl/entity/loader/loader.hpp"
namespace fggl::entity {
constexpr auto MIME_SCENE = assets::from_mime("x-fggl/scene");
struct ECS {
constexpr static const char *name = "fggl::entity::ECS";
constexpr static const std::array<modules::ServiceName, 1> provides = {
EntityFactory::service
};
constexpr static const std::array<modules::ServiceName, 2> depends = {
assets::Loader::service,
assets::CheckinAdapted::service
};
static bool factory(modules::ServiceName name, modules::Services &serviceManager);
};
void install_component_factories(EntityFactory *factory);
} // namespace fggl::entity
#endif //FGGL_ENTITY_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/>.
*/
#ifndef FGGL_HPP
#define FGGL_HPP
#include "fggl/app.hpp"
// module system
#include "fggl/modules/manager.hpp"
#include "fggl/data/module.hpp"
#include "fggl/input/module.hpp"
#include "fggl/gui/module.hpp"
#include "fggl/display/glfw/module.hpp"
#include "fggl/gfx/ogl4/module.hpp"
#include "fggl/audio/null_audio.hpp"
#include "fggl/audio/openal/module.hpp"
//! Root namespace
namespace fggl {
}
#endif
/*
* 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_GFX_ATLAS_HPP
#define FGGL_GFX_ATLAS_HPP
#include <fggl/math/types.hpp>
#include <vector>
namespace fggl::gfx {
struct Bounds2D {
glm::ivec2 pos;
glm::ivec2 size;
};
bool pack(std::vector<Bounds2D> &bounds);
template<typename T>
class ImageAtlas {
public:
struct SubImage {
const T name;
Bounds2D bounds;
};
SubImage &locate(int id) const;
SubImage &locate(const T &name) const;
static ImageAtlas<T> *pack(std::vector<SubImage> &images) {
// extract bounds
std::vector<Bounds2D> bounds;
for (auto &image : images) {
bounds.push_back(image.bounds);
}
// allocate the bounds back
auto result = gfx::pack(bounds);
for (std::size_t i = 0; i < images.size(); i++) {
images[i].bounds = bounds[i];
}
return new ImageAtlas<T>(images);
}
private:
ImageAtlas(const std::vector<SubImage> &images) : m_images(images) {
}
std::vector<SubImage> m_images;
};
};
#endif
/*
* 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_GFX_CAMERA_HPP
#define FGGL_GFX_CAMERA_HPP
#include "fggl/math/types.hpp"
#include "fggl/entity/entity.hpp"
namespace fggl::gfx {
struct Camera {
constexpr const static char name[] = "Camera";
math::vec3 target = math::vec3(0.0f, 0.0f, 0.0f);
float aspectRatio = 1280.0f / 720.0f;
float fov = glm::radians(45.0f);
float nearPlane = 0.1f;
float farPlane = 100.0f;
inline math::mat4 perspective() const {
return glm::perspective(fov, aspectRatio, nearPlane, farPlane);
}
};
inline math::mat4 calc_proj_matrix(const Camera &camera) {
return glm::perspective(camera.fov, camera.aspectRatio, camera.nearPlane, camera.farPlane);
}
inline math::Ray get_camera_ray(const entity::EntityManager &world,
const entity::EntityID camera,
math::vec2 position) {
auto &camTransform = world.get<fggl::math::Transform>(camera);
auto &camComp = world.get<fggl::gfx::Camera>(camera);
const auto projMatrix = fggl::gfx::calc_proj_matrix(camComp);
const auto viewMatrix = fggl::math::calc_view_matrix(camTransform);
glm::vec4 startNDC{
position.x,
position.y,
-1.0f,
1.0f
};
glm::vec4 endNDC{
position.x,
position.y,
0.0f,
1.0f
};
fggl::math::mat4 M = glm::inverse(projMatrix * viewMatrix);
glm::vec3 start = M * startNDC;
glm::vec3 end = M * endNDC;
return {start, glm::normalize(end - start)};
}
};
#endif
/*
* 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_GFX_COMMON_HPP
#define FGGL_GFX_COMMON_HPP
//
// This file exists to ensure that dependencies are loaded in the correct order.
// Code should NOT directly include things in this file (glfw, opengl) as the order MUST be correct or things go boom.
//
// load the correct rendering backend (only opengl for now)
#include <fggl/gfx/ogl/common.hpp>
// now it's safe to load the windowing system
#include <GLFW/glfw3.h>
#endif
#ifndef FGGL_GFX_INPUT_H
#define FGGL_GFX_INPUT_H
/*
* 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_GFX_INPUT_HPP
#define FGGL_GFX_INPUT_HPP
#include <array>
#include <bitset>
......@@ -83,7 +97,7 @@ namespace fggl::gfx {
TRIGGER_LEFT,
TRIGGER_RIGHT
};
constexpr std::array<PadAxis,6> PadAxes = {
constexpr std::array<PadAxis, 6> PadAxes = {
PadAxis::LEFT_X,
PadAxis::LEFT_Y,
PadAxis::RIGHT_X,
......@@ -107,10 +121,10 @@ namespace fggl::gfx {
};
struct Joystick {
const char* name = nullptr;
const float* axes = nullptr;
const unsigned char* buttons = nullptr;
const unsigned char* hats = nullptr;
const char *name = nullptr;
const float *axes = nullptr;
const unsigned char *buttons = nullptr;
const unsigned char *hats = nullptr;
int hatCount = 0;
int axisCount = 0;
int buttonCount = 0;
......@@ -120,7 +134,7 @@ namespace fggl::gfx {
class Input {
public:
// this is a neccerry evil due to glfw's design :'(
static Input& instance() {
static Input &instance() {
static Input *instance = new Input();
return *instance;
}
......@@ -134,12 +148,12 @@ namespace fggl::gfx {
void mouseBtn(const MouseButton btn, bool state);
// mouse position
const double* mousePos() const;
const double *mousePos() const;
double cursorDeltaX() const;
double cursorDeltaY() const;
// mouse scroll
const double* mouseScroll() const;
const double *mouseScroll() const;
double scrollDeltaX() const;
double scrollDeltaY() const;
......@@ -165,14 +179,14 @@ namespace fggl::gfx {
bool mouseReleased(const MouseButton btn) const;
// joysticks
void joystickConnect(int id, Joystick& data);
void joystickConnect(int id, Joystick &data);
void joystickDisconnect(int id);
bool hasJoystick(int id) const;
const Joystick& joystick(int id) const;
const Joystick &joystick(int id) const;
// gamepads
void padState(int id, const PadState& state);
void padState(int id, const PadState &state);
bool padDown(int id, PadButton btn);
bool padPressed(int id, PadButton btn);
......