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 651 additions and 505 deletions
//
// Created by webpigeon on 20/11/2021.
//
#ifndef FGGL_CAMERA_INPUT_H
#define FGGL_CAMERA_INPUT_H
#include <fggl/ecs3/ecs.hpp>
#include <fggl/math/types.hpp>
namespace fggl::input {
constexpr float ROT_SPEED = 0.05f;
constexpr float PAN_SPEED = 0.05f;
constexpr math::mat4 MAT_IDENTITY(1.0f);
struct FreeCamKeys {
constexpr const static char name[] = "FreeCameraKeys";
scancode_t forward;
scancode_t backward;
scancode_t left;
scancode_t right;
scancode_t rotate_cw;
scancode_t rotate_ccw;
};
/**
* Process the camera based on rotation around a fixed point.
*
* @param ecs the world that contains the camera
* @param input the input module to read the mouse location from
* @param cam the ID of the camera entity
*/
void process_arcball(fggl::ecs3::World& ecs, const Input& input, fggl::ecs::entity_t cam);
/**
* Process free (floating) camera movement.
*
* @param ecs the world that contains the camera
* @param input the input module to read the mouse location from
* @param cam the ID of the camera entity
*/
void process_freecam(fggl::ecs3::World& ecs, const Input& input, fggl::ecs::entity_t cam);
/**
* Input processing for moving the camera when the mouse is close to the edge of the screen.
*
* This function deals with ensuring the camera moves if the user moves their mouse button close
* to the edge of the screen. It will apply this as movement to the camera entity passed in as
* an argument.
*
* @param ecs the world that contains the camera
* @param input the input module to read the mouse location from
* @param cam the ID of the camera entity
*/
void process_edgescroll(fggl::ecs3::World& ecs, const Input& input, fggl::ecs::entity_t cam);
}
#endif //FGGL_CAMERA_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/>.
*/
#include <fggl/input/input.hpp>
namespace fggl::input {
void Input::frame(float dt) {
keyboard.frame(dt);
mouse.frame(dt);
gamepads.frame(dt);
}
} // namespace fggl::input
#ifndef FGGL_INPUT_H
#define FGGL_INPUT_H
#include <memory>
#include <fggl/input/keyboard.hpp>
#include <fggl/input/mouse.hpp>
#include <fggl/input/gamepad.hpp>
namespace fggl::input {
class Input {
public:
inline Input() : keyboard(), mouse(), gamepads() {
}
inline void frame(float dt) {
keyboard.frame(dt);
mouse.frame(dt);
gamepads.frame(dt);
}
KeyboardInput keyboard;
MouseInput mouse;
GamepadInput gamepads;
};
}
#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/>.
*/
#include <fggl/input/mouse.hpp>
namespace fggl::input {
void MouseState::operator=(const MouseState &rhs) {
for (int i = 0; i < 4; i++) {
axis[i] = rhs.axis[i];
}
buttons = rhs.buttons;
}
} // namespace fggl::input
#ifndef FGGL_INPUT_MOUSE_H
#define FGGL_INPUT_MOUSE_H
#include <string>
#include <array>
#include <bitset>
namespace fggl::input {
enum class MouseButton {
LEFT,
MIDDLE,
RIGHT,
EXTRA_1,
EXTRA_2,
EXTRA_3,
EXTRA_4,
EXTRA_5
};
enum class MouseAxis {
X,
Y,
SCROLL_X,
SCROLL_Y
};
struct MouseButtonRecord {
MouseButton id;
char name[15];
};
struct MouseAxisRecord {
MouseAxis id;
char name[15];
};
constexpr std::array<MouseButtonRecord, 8> MouseButtons = {{
{MouseButton::LEFT, "Left"},
{MouseButton::MIDDLE, "Middle"},
{MouseButton::RIGHT, "Right"},
{MouseButton::EXTRA_1, "Extra 1"},
{MouseButton::EXTRA_2, "Extra 2"},
{MouseButton::EXTRA_3, "Extra 3"},
{MouseButton::EXTRA_4, "Extra 4"},
{MouseButton::EXTRA_5, "Extra 5"},
}};
constexpr std::array<MouseAxisRecord, 4> MouseAxes = {{
{MouseAxis::X, "Left/Right"},
{MouseAxis::Y, "Up/Down"},
{MouseAxis::SCROLL_X, "Scroll X"},
{MouseAxis::SCROLL_Y, "Scroll Y"}
}};
struct MouseState {
float axis[MouseAxes.size()];
std::bitset<MouseButtons.size()> buttons;
};
class MouseInput {
public:
inline void frame(float dt) {
m_prev = m_curr;
}
inline void axis(MouseAxis axis, float value) {
m_curr.axis[(int)axis] = value;
}
inline float axis(MouseAxis axis) const {
return m_curr.axis[(int)axis];
}
inline float axisDelta(MouseAxis axis) const {
return m_curr.axis[(int)axis] - m_prev.axis[(int)axis];
}
inline void button(MouseButton btn, bool state) {
m_curr.buttons[(int)btn] = state;
}
inline bool button(MouseButton btn) const {
return m_curr.buttons[(int)btn];
}
inline bool pressed(MouseButton btn) const {
return m_curr.buttons[(int)btn] && !m_prev.buttons[(int)btn];
}
inline bool released(MouseButton btn) const {
return !m_curr.buttons[(int)btn] && m_prev.buttons[(int)btn];
}
private:
MouseState m_curr;
MouseState m_prev;
};
};
#endif
# math
find_package(glm CONFIG REQUIRED)
target_link_libraries(fggl PUBLIC glm::glm)
target_sources(fggl
PRIVATE
shapes.cpp
triangulation.cpp
)
//
// Created by webpigeon on 12/12/2021.
//
#ifndef FGGL_UTILS_HPP
#define FGGL_UTILS_HPP
#include <fggl/math/types.hpp>
namespace fggl::math {
inline float lerp(float a, float b, float w) {
return (b - a) * w + a;
}
inline float scale(float in, float inMin, float inMax, float outMin, float outMax) {
return ( (in - inMin) * (outMax - outMin) ) / (inMax - inMin);
}
//
// Functions
//
using transformF = std::function<float(float)>;
inline float scaleFilter(float in, float inMin, float inMax, float outMin, float outMax, transformF filter) {
float out = in - inMin;
out /= (inMax - inMin);
out = f(out);
out *= (outEnd - outStart);
return out + outMin;
}
inline float mix(transformF a, transformF b, float weightB, float t) {
return ( (1 - weightB) * a(t) ) + ( weightB * b(t) );
}
inline float crossFade( transformF a, transformF b, float t) {
return ((1 - t) * a(t))+ (t * b);
}
//
// building blocks
//
inline float scale(transformF a, float t) {
return t * f(t);
}
inline float reverseScale(transformF a, float t) {
return (1 - t) * a(t);
}
inline float Arch2(float t) {
return t * (1 - t);
}
inline float BounceClampBottom( float t ){
return fabs(t);
}
inline float BounceClampTop( float t ) {
return 1.f - fabs( 1.f - t );
}
//
// Easing function library
// see Math for Game Programmers: Fast and Funky 1D Nonlinear Transformations, GDC 2015
//
inline float SmoothStart2(float t) {
return t * t;
}
inline float SmoothStart3(float t) {
return t * t * t;
}
inline float SmoothStart4(float t) {
return t * t * t * t;
}
inline float SmoothStart5(float t) {
return t * t * t * t * t;
}
inline float SmoothStop2(float t) {
constexpr tFlip = 1 - y;
return 1 - (tFlip * tFlip);
}
inline float SmoothStop3(float t) {
constexpr tFlip = 1 - y;
return 1 - (tFlip * tFlip);
}
inline float SmoothStop4(float t) {
constexpr tFlip = 1 - y;
return 1 - (tFlip * tFlip * tFlip * tFlip);
}
inline float SmoothStop5(float t) {
constexpr tFlip = 1 - y;
return 1 - (tFlip * tFlip * tFlip * tFlip * tFlip);
}
//
// Bezier curves
//
inline float NormalizedBezier3( float B, float C, float t) {
const float s = 1.f - t;
const float t2 = t * t;
const float s2 = s * s;
const float t3 = t2 * t;
return (3.f*B*s2*t) + (3.f*C*s*t2) + t3;
}
}
#endif //FGGL_UTILS_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/>.
*/
#include "fggl/math/shapes.hpp"
#include <vector>
namespace fggl::math::phs3d {
void AABB::emtpy() {
min = {FLT_MAX, FLT_MAX, FLT_MAX};
max = {-FLT_MAX, -FLT_MAX, -FLT_MAX};
}
void AABB::add(const math::vec3 &point) {
min = minElm(min, point);
max = maxElm(max, point);
}
auto AABB::fromPoints(const std::vector<math::vec3> &points) -> AABB {
AABB box;
for (const auto &point : points) {
box.add(point);
}
return box;
}
void AABB::set(const AABB &other, const math::mat4 &m) {
// TODO this needs testing, I'm not sure if our vectors are oriented the same as 9.4.4
min = max = m[3]; // should be the translation component of the matrix
// this feels like something that should be vectorizable...
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (m[i][j] > 0.0F) {
min[j] += m[i][j] * other.min[j];
max[j] += m[i][j] * other.max[j];
} else {
min[j] += m[i][j] * other.max[j];
max[j] += m[i][j] * other.min[j];
}
}
}
}
auto Plane::fromPoints(const math::vec3 p1, const math::vec3 p2, const math::vec3 p3) -> Plane {
const auto e3 = p2 - p1;
const auto e1 = p3 - p2;
auto normal = glm::normalize(glm::cross(e3, e1));
auto d = glm::dot(p2, normal);
return {normal, d};
}
static auto bestFitNormal(const std::vector<math::vec3> &points) -> math::vec3 {
assert(!points.empty());
math::vec3 result;
math::vec3 p = points.back();
for (std::size_t i = 0; i < points.size(); ++i) {
math::vec3 c = points[i];
result.x += (p.z + c.z) * (p.y - c.y);
result.y += (p.x + c.x) * (p.z - c.z);
result.z += (p.y + c.y) - (p.x - c.x);
p = c;
}
return glm::normalize(result);
};
static auto bestFitD(const std::vector<math::vec3> &points, glm::vec3 normal) -> float {
math::vec3 sum;
for (const auto &point : points) {
sum += point;
}
sum *= 1.0F / points.size();
return glm::dot(sum, normal);
}
const char X = 0;
const char Y = 1;
const char Z = 2;
struct bary_axis {
const char a;
const char b;
};
static auto baryCalcAxis(const math::vec3 &normal) -> bary_axis {
if ((fabs(normal.x) >= fabs(normal.y)) && (fabs(normal.x) >= fabs(normal.z))) {
// discard x
return {Y, Z};
} else if (fabs(normal.y) >= fabs(normal.z)) {
// discard y
return {Z, X};
} else {
// discard z
return {X, Y};
}
}
auto Triangle::CartToBarycentric(const math::vec3 &cart, Barycentric &outVal) -> bool {
// everything is const because I'm paying the compiler is smarter than me...
const auto d1 = v[1] - v[0];
const auto d2 = v[2] - v[1];
const auto n = glm::cross(d1, d2);
// 0 = x, 1 = y, 2 = z
const auto ax = baryCalcAxis(n);
// first axis
const float u1 = v[0][ax.a] - v[2][ax.a];
const float u2 = v[1][ax.a] - v[2][ax.a];
const float u3 = cart[ax.a] - v[0][ax.a];
const float u4 = cart[ax.a] - v[2][ax.a];
// second axis
const float v1 = v[0][ax.b] - v[2][ax.b];
const float v2 = v[1][ax.b] - v[2][ax.b];
const float v3 = cart[ax.b] - v[0][ax.b];
const float v4 = cart[ax.b] - v[2][ax.b];
const float denom = v1 * u2 - v2 * u1;
if (denom == 0.0F) {
return false;
}
// finally, we can work it out
const float oneOverDenom = 1.0F / denom;
outVal.b[0] = (v4 * u2 - v2 * u4) * oneOverDenom;
outVal.b[1] = (v1 * u3 - v3 * u1) * oneOverDenom;
outVal.b[2] = 1.0F - outVal.b[0] - outVal.b[1];
return true;
}
auto Triangle::CartToBarycentric2(const math::vec3 &cart, Barycentric &outVal) -> bool {
const auto e1 = v[2] - v[1];
const auto e2 = v[0] - v[2];
const auto e3 = v[1] - v[0];
const auto d1 = cart - v[0];
const auto d2 = cart - v[1];
const auto d3 = cart - v[2];
const auto normal = glm::normalize(glm::cross(e1, e2));
const auto denom = glm::dot(glm::cross(e1, e2), normal);
assert(denom != 0.0F);
outVal.b[0] = glm::dot(glm::cross(e1, d3), normal) / denom;
outVal.b[1] = glm::dot(glm::cross(e2, d1), normal) / denom;
outVal.b[2] = glm::dot(glm::cross(e3, d2), normal) / denom;
return true;
}
} // namespace fggl::math::phys3d
\ 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/>.
*/
#include "fggl/math/triangulation.hpp"
namespace fggl::math {
/**
* Fast Triangulation for convex polygons.
*/
void fan_triangulation(const PolygonVertex &polygon, data::Mesh2D &mesh) {
assert(polygon.size() >= 3);
// add the first two points to the mesh
auto firstIdx = mesh.add_vertex(polygon[0]);
auto prevIdx = mesh.add_vertex(polygon[1]);
// deal with the indices
const auto nTris = polygon.size() - 2;
for (auto i = 0U; i < nTris; i++) {
mesh.add_index(firstIdx);
mesh.add_index(prevIdx);
auto currIdx = mesh.add_vertex(polygon[i + 2]);
mesh.add_index(currIdx);
prevIdx = currIdx;
}
}
} // namespace fggl::math
#ifndef FGGL_MATH_TYPES_H
#define FGGL_MATH_TYPES_H
#include <tuple>
#include <glm/ext/matrix_transform.hpp>
#include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp>
#include <glm/gtx/quaternion.hpp>
namespace fggl::math {
// math types (aliased for ease of use)
using vec4 = glm::vec4;
using vec3 = glm::vec3;
using vec2 = glm::vec2;
using mat4 = glm::mat4;
using quat = glm::quat;
// fastFloor from OpenSimplex2
inline int fastFloor(double x) {
int xi = (int)x;
return x < xi ? xi - 1 : xi;
}
// reference vectors
constexpr vec3 UP { 0.0f, 1.0f, 0.0f };
constexpr vec3 FORWARD { 1.0f, 0.0f, 0.0f };
constexpr vec3 RIGHT { 0.0f, 0.0f, 1.0f };
inline glm::mat4 modelMatrix( const vec3 offset, const quat rotation ) {
return glm::translate( glm::mat4(1.0f), offset ) * glm::toMat4( rotation );
}
inline glm::mat4 modelMatrix( glm::vec3 offset, glm::vec3 eulerAngles ) {
return modelMatrix( offset, glm::quat( eulerAngles ) );
}
struct Transform {
constexpr static const char name[] = "Transform";
Transform() : m_local(1.0f), m_origin(0.0f), m_model(1.0f), m_rotation() {
}
// local reference vectors
[[nodiscard]]
inline vec3 up() const {
return vec4( UP, 1.0 ) * m_local;
}
[[nodiscard]]
inline vec3 forward() const {
return vec4( FORWARD, 1.0 ) * m_local;
}
[[nodiscard]]
inline vec3 right() const {
return vec4( RIGHT, 1.0 ) * m_local;
}
inline void translate(const vec3 change) {
m_origin += change;
update();
}
inline void origin(const vec3 pos) {
m_origin = pos;
update();
}
[[nodiscard]]
inline vec3 origin() const {
return m_origin;
}
inline void euler(vec3 angles) {
m_rotation = quat( angles );
update();
}
[[nodiscard]]
inline glm::vec3 euler() const {
return glm::eulerAngles(m_rotation);
}
inline mat4 model() const {
mat4 tmp(1.0f);
tmp = glm::translate(tmp, m_origin);
tmp = tmp * glm::toMat4(m_rotation);
return tmp;
}
private:
mat4 m_local; // us -> parent
mat4 m_model; // us -> world
vec3 m_origin;
quat m_rotation;
inline void update() {
mat4 t(1.0f);
t *= glm::toMat4(m_rotation);
t = glm::translate( t, m_origin );
m_local = t;
}
};
}
// feels a bit strange to be doing this...
namespace glm {
inline bool operator<(const vec3& lhs, const vec3& rhs) {
return std::tie( lhs.x, lhs.y, lhs.z )
< std::tie( rhs.x, rhs.y, rhs.z );
}
}
#endif
target_sources(fggl
PRIVATE
null.cpp
)
\ 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 20/08/22.
//
#include "fggl/phys/null.hpp"
namespace fggl::phys {
auto NullPhysics::factory(modules::ServiceName serviceName, modules::Services &serviceManager) -> bool {
if (serviceName == phys::PhysicsProvider::service) {
serviceManager.bind<phys::PhysicsProvider, NullPhysicsProvider>();
return true;
}
return false;
}
}
\ No newline at end of file
if (CMAKE_SYSTEM_NAME MATCHES "Linux")
add_subdirectory(linux)
else ()
add_subdirectory(fallback)
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 26/06/22.
//
#define FGGL_PLATFORM_PATHS fallback
#include <cstdlib>
#include "fggl/platform/fallback/paths.hpp"
namespace fggl::platform {
inline static std::filesystem::path get_user_path(const char *env, const char *fallback) {
const char *path = std::getenv(env);
if (path != nullptr) {
return {path};
}
return std::filesystem::current_path() / fallback;
}
EnginePaths calc_engine_paths(const char *base) {
return EnginePaths{
get_user_path(ENV_USER_CONFIG, DEFAULT_USER_CONFIG) / base,
get_user_path(ENV_USER_DATA, DEFAULT_USER_DATA) / base,
std::filesystem::temp_directory_path() / base
};
}
std::filesystem::path locate_data(const EnginePaths &paths, const std::filesystem::path &relPath) {
auto userPath = paths.userData / relPath;
if (std::filesystem::exists(userPath)) {
return userPath;
}
// if debug mode, try CWD as well.
auto debugPath = std::filesystem::current_path() / "data" / relPath;
if (std::filesystem::exists(debugPath)) {
return debugPath;
}
// if the file existed, it should exist in the user space
return userPath;
}
std::filesystem::path locate_config(const EnginePaths &paths, const std::filesystem::path &relPath) {
return paths.userConfig / relPath;
}
std::filesystem::path locate_cache(const EnginePaths &paths, const std::filesystem::path &relPath) {
return paths.userCache / relPath;
}
} // namespace fggl::platform
#find_package(Fontconfig)
#target_link_libraries(fggl PRIVATE Fontconfig::Fontconfig)
target_sources(fggl
PRIVATE
# fonts.cpp
paths.cpp
)
\ 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 23/06/22.
//
#include <fontconfig/fontconfig.h>
namespace fggl::platform::Linux {
void get_font() {
/* FcConfig *config = FcInitLoadConfigAndFonts();
FcPattern* pat = FcPatternCreate();
FcObjectSet* os = FcObjectSetBuild(FC_FAMILY, FC_STYLE, FC_WEIGHT, FC_SLANT, FC_PIXEL_SIZE, FC_SIZE, nullptr);
FcFontSet* fs = FcFontList(config, pat, os);
if ( fs ) {
FcFontSetDestroy(fs);
}*/
}
} // namespace fggl::platform::linux
\ 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 26/06/22.
//
#include <cstdlib>
#define FGGL_PLATFORM_PATHS linux
#include "fggl/platform/linux/paths.hpp"
#include "fggl/debug/logging.hpp"
namespace fggl::platform {
namespace {
inline auto get_user_path(const char *env, const char *fallback) -> std::filesystem::path {
const char *path = std::getenv(env);
if (path != nullptr) {
return {path};
}
return {fallback};
}
auto get_path_list(const char *env, const char *folderName) -> std::vector<std::filesystem::path> {
const char *pathList = std::getenv(env);
std::vector<std::filesystem::path> paths;
if (pathList) {
std::string pathListStr(pathList);
std::string::size_type pos = 0;
while (pos < pathListStr.size()) {
std::string::size_type nextPos = pathListStr.find(':', pos);
if (nextPos == std::string::npos) {
nextPos = pathListStr.size();
}
std::string path = pathListStr.substr(pos, nextPos - pos);
paths.push_back(std::filesystem::path(path) / folderName);
pos = nextPos + 1;
}
}
return paths;
}
}
auto calc_engine_paths(const char *base) -> EnginePaths {
auto dataDirs = get_path_list(ENV_DATA_DIRS, base);
if (dataDirs.empty()) {
for (const auto &defaultDir : DEFAULT_DATA_DIRS) {
dataDirs.push_back(std::filesystem::path(defaultDir) / base);
}
}
auto configDirs = get_path_list(ENV_CONFIG_DIRS, base);
if (configDirs.empty()) {
for (const auto &defaultDir : DEFAULT_CONFIG_DIRS) {
configDirs.push_back(std::filesystem::path(defaultDir) / base);
}
}
return EnginePaths{
get_user_path(ENV_USER_CONFIG, DEFAULT_USER_CONFIG) / base,
get_user_path(ENV_USER_DATA, DEFAULT_USER_DATA) / base,
get_user_path(ENV_USER_CACHE, DEFAULT_USER_CACHE) / base,
dataDirs,
configDirs
};
}
auto locate_data(const EnginePaths &paths, const std::filesystem::path &relPath) -> std::filesystem::path {
auto userPath = paths.userData / relPath;
if (std::filesystem::exists(userPath)) {
return userPath;
}
// check system paths
for (const auto &path : paths.dataDirs) {
auto fullPath = path / relPath;
debug::trace("Checking data path: {}, exists: {}", fullPath.c_str(), std::filesystem::exists(fullPath));
if (std::filesystem::exists(fullPath)) {
return fullPath;
}
}
// if debug mode, try CWD as well.
auto debugPath = std::filesystem::current_path() / "data" / relPath;
if (std::filesystem::exists(debugPath)) {
debug::trace("Checking debug path: {}, exists: {}", debugPath.c_str(), std::filesystem::exists(debugPath));
return debugPath;
}
// if the file existed, it should exist in the user space
return userPath;
}
auto locate_config(const EnginePaths &paths, const std::filesystem::path &relPath) -> std::filesystem::path {
auto userPath = paths.userConfig / relPath;
if (std::filesystem::exists(userPath)) {
return userPath;
}
// check system paths
for (const auto &path : paths.configDirs) {
auto fullPath = path / relPath;
if (std::filesystem::exists(fullPath)) {
return fullPath;
}
}
// if the file existed, it should exist in the user space
return userPath;
}
auto locate_cache(const EnginePaths &paths, const std::filesystem::path &relPath) -> std::filesystem::path {
auto userPath = paths.userCache / relPath;
if (std::filesystem::exists(userPath)) {
return userPath;
}
// check system paths
for (const auto &path : paths.configDirs) {
auto fullPath = path / relPath;
if (std::filesystem::exists(fullPath)) {
return fullPath;
}
}
// if the file existed, it should exist in the user space
return userPath;
}
} // namespace fggl::platform::linux
//
// Created by webpigeon on 20/11/2021.
//
#include "Scene.h"
#include <utility>
namespace fggl::scenes {
void SceneManager::create(const std::string &name, std::shared_ptr<Scene> scene) {
m_scenes[name] = std::move(scene);
}
void SceneManager::activate(const std::string &name) {
auto newScene = m_scenes.at(name);
if ( m_active != nullptr ) {
m_active->cleanup();
m_active = nullptr;
}
newScene->setup();
m_active = newScene;
}
}
\ No newline at end of file
//
// Created by webpigeon on 20/11/2021.
//
#ifndef FGGL_SCENE_H
#define FGGL_SCENE_H
#include <memory>
#include <string>
#include <unordered_map>
namespace fggl::scenes {
class Scene {
public:
virtual ~Scene() = default;
virtual void setup() = 0;
virtual void cleanup() = 0;
virtual void update() = 0;
virtual void render() = 0;
};
class SceneManager {
public:
SceneManager() = default;
void create(const std::string& name, std::shared_ptr<Scene> scene);
void activate(const std::string& name);
inline void update() {
if ( m_active == nullptr ) { return; }
m_active->update();
}
inline void render() {
if ( m_active == nullptr ) { return; }
m_active->render();
}
private:
std::shared_ptr<Scene> m_active;
std::unordered_map<std::string, std::shared_ptr<Scene>> m_scenes;
};
}
#endif //FGGL_SCENE_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/>.
*/
//
// Created by webpigeon on 23/04/22.
//
#include "fggl/scenes/game.hpp"
#if __has_include("fggl/phys/bullet/bullet.hpp")
#include "fggl/phys/bullet/bullet.hpp"
#endif
namespace fggl::scenes {
GameBase::GameBase(fggl::App& app) : AppState(app) {
m_input = app.service<input::Input>();
}
void GameBase::update(float /*dt*/) {
// detect the user quitting
if (m_input != nullptr) {
bool escapePressed = m_input->keyboard.pressed(glfwGetKeyScancode(GLFW_KEY_ESCAPE));
if (escapePressed) {
m_owner.change_state(m_previous);
}
}
}
Game::Game(fggl::App &app) : AppState(app) {
m_input = app.service<input::Input>();
}
void Game::activate() {
fggl::AppState::activate();
// setup the scene
m_world = std::make_unique<entity::EntityManager>();
#ifdef FGGL_MODULE_BULLET
// FIXME this ties bullet to the game state - which shouldn't be the case
m_phys = std::make_unique<fggl::phys::bullet::BulletPhysicsEngine>(m_world.get());
#endif
}
void Game::deactivate() {
m_phys.reset();
m_world.reset();
}
void Game::update(float /*dt*/) {
assert(m_world && "called game update, but there was no world - was activate called?");
if (m_input != nullptr) {
bool escapePressed = m_input->keyboard.pressed(glfwGetKeyScancode(GLFW_KEY_ESCAPE));
if (escapePressed) {
m_owner.change_state(m_previous);
}
if ( m_input->keyboard.pressed(glfwGetKeyScancode(GLFW_KEY_F2)) ) {
m_debug = !m_debug;
}
}
if (m_phys != nullptr) {
m_phys->step();
}
// debug render toggle
//m_world->reapEntities();
}
void Game::render(fggl::gfx::Graphics &gfx) {
if (m_world != nullptr) {
gfx.drawScene(*m_world, m_debug);
}
}
} // namespace demo