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 1115 additions and 57 deletions
......@@ -22,19 +22,23 @@
#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::ModuleService, 1> provides = {
constexpr static const std::array<modules::ServiceName, 1> provides = {
EntityFactory::service
};
constexpr static const std::array<modules::ModuleService, 1> depends = {
assets::Loader::service
constexpr static const std::array<modules::ServiceName, 2> depends = {
assets::Loader::service,
assets::CheckinAdapted::service
};
static bool factory(modules::ModuleService name, modules::Services &serviceManager);
static bool factory(modules::ServiceName name, modules::Services &serviceManager);
};
void install_component_factories(EntityFactory *factory);
......
......@@ -23,6 +23,7 @@
#include "fggl/entity/entity.hpp"
#include "fggl/modules/module.hpp"
//! Classes responsible for rendering content
namespace fggl::gfx {
struct Bounds {
......@@ -34,7 +35,7 @@ namespace fggl::gfx {
class Graphics {
public:
constexpr static const modules::ModuleService service = modules::make_service("fggl::gfx::Graphics");
constexpr static const auto service = modules::make_service("fggl::gfx::Graphics");
virtual ~Graphics() = default;
virtual void clear() = 0;
......
......@@ -32,22 +32,6 @@ namespace fggl::gfx {
using GlFunctionLoader = GLADloadproc;
enum GlRenderType {
triangles = GL_TRIANGLES,
triangle_strip = GL_TRIANGLE_STRIP
};
struct GlRenderToken {
constexpr static const char name[] = "RenderToken";
GLuint vao;
GLuint buffs[2];
GLuint idxOffset;
GLsizei idxSize;
GLuint pipeline;
GLuint restartVertex;
GlRenderType renderType = triangles;
};
/**
* Class responsible for managing the OpenGL context.
*
......
......@@ -27,6 +27,7 @@
#include "fggl/gfx/ogl/common.hpp"
#include "fggl/math/types.hpp"
#include "fggl/data/texture.hpp"
namespace fggl::gfx::ogl {
......@@ -177,7 +178,7 @@ namespace fggl::gfx::ogl {
SHORT = GL_SHORT,
UNSIGNED_INT = GL_UNSIGNED_INT,
INT = GL_INT,
HALF_FLOAT = GL_HALF_FLOAT,
//HALF_FLOAT = GL_HALF_FLOAT,
FLOAT = GL_FLOAT,
/*
UNSIGNED_BYTE_3_3_2,
......@@ -221,11 +222,165 @@ namespace fggl::gfx::ogl {
DEPTH_STENCIL = GL_DEPTH_STENCIL
};
struct Image {
struct PixelDataArray {
PixelFormat type;
union {
unsigned char *uc;
char *c;
std::uint16_t *us;
std::int16_t *s;
float *f;
std::int32_t *i;
std::uint32_t *ui;
};
bool owning;
inline PixelDataArray(PixelFormat fmt, std::size_t size) : type(fmt), owning(true) {
switch (type) {
case PixelFormat::UNSIGNED_BYTE:
uc = new unsigned char[size];
break;
case PixelFormat::BYTE:
c = new char[size];
break;
case PixelFormat::UNSIGNED_SHORT:
us = new std::uint16_t[size];
break;
case PixelFormat::SHORT:
s = new std::int16_t[size];
break;
case PixelFormat::FLOAT:
f = new float[size];
break;
case PixelFormat::INT:
i = new std::int32_t[size];
break;
case PixelFormat::UNSIGNED_INT:
ui = new std::uint32_t[size];
break;
}
}
inline explicit PixelDataArray(unsigned char* data) : type(PixelFormat::UNSIGNED_BYTE), uc(data), owning(false) {}
inline explicit PixelDataArray(char* data) : type(PixelFormat::BYTE), c(data), owning(false) {}
// no copy
PixelDataArray(const PixelDataArray&) = delete;
PixelDataArray& operator=(const PixelDataArray&) = delete;
// move ok
PixelDataArray(PixelDataArray&& other) : type(other.type), owning(other.owning) {
switch (type) {
case PixelFormat::UNSIGNED_BYTE:
uc = other.uc;
other.uc = nullptr;
break;
case PixelFormat::BYTE:
c = other.c;
other.c = nullptr;
break;
case PixelFormat::UNSIGNED_SHORT:
us = other.us;
other.us = nullptr;
break;
case PixelFormat::SHORT:
s = other.s;
other.s = nullptr;
break;
case PixelFormat::FLOAT:
f = other.f;
other.f = nullptr;
break;
case PixelFormat::INT:
i = other.i;
other.i = nullptr;
break;
case PixelFormat::UNSIGNED_INT:
ui = other.ui;
other.ui = nullptr;
break;
}
}
inline ~PixelDataArray() {
if (owning) {
switch (type) {
case PixelFormat::UNSIGNED_BYTE: delete[] uc;
uc = nullptr;
break;
case PixelFormat::BYTE: delete[] c;
c = nullptr;
break;
case PixelFormat::UNSIGNED_SHORT: delete[] us;
us = nullptr;
break;
case PixelFormat::SHORT: delete[] s;
s = nullptr;
break;
case PixelFormat::FLOAT: delete[] f;
f = nullptr;
break;
case PixelFormat::INT: delete[] i;
i = nullptr;
break;
case PixelFormat::UNSIGNED_INT:
delete[] ui;
ui = nullptr;
break;
}
}
}
void* data() {
switch (type) {
case PixelFormat::UNSIGNED_BYTE:
return uc;
case PixelFormat::BYTE:
return c;
case PixelFormat::UNSIGNED_SHORT:
return us;
case PixelFormat::SHORT:
return s;
case PixelFormat::FLOAT:
return f;
case PixelFormat::INT:
return i;
case PixelFormat::UNSIGNED_INT:
return ui;
}
// unknown type?
return nullptr;
}
};
struct Image {
ImageFormat format;
math::vec2i size;
void *data;
PixelDataArray data;
//Image() = default;
inline Image(ImageFormat fmt, PixelFormat pxFmt, math::vec2i asize) :
format(fmt),
size(asize),
data(pxFmt, asize.x * asize.y){}
inline Image(ImageFormat fmt, math::vec2i asize, PixelDataArray&& adata) :
format(fmt),
size(asize),
data(std::move(adata)) {}
Image(const Image&) = delete;
inline PixelFormat type() const {
return data.type;
}
void* dataPtr() {
return data.data();
}
};
class Texture {
......@@ -257,6 +412,25 @@ namespace fggl::gfx::ogl {
}
}
void setData(InternalImageFormat iFmt, Image &image, PixelFormat extFormat) {
//bind();
glBindTexture((GLenum) m_type, m_obj);
glTexImage2D((GLenum) m_type,
0,
(GLint) iFmt,
image.size.x,
image.size.y,
0,
(GLenum) image.format,
(GLenum) extFormat,
image.dataPtr());
if ( m_type == TextureType::Tex2D ) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}
}
void setData(InternalImageFormat iFmt, Image &image) {
//bind();
glBindTexture((GLenum) m_type, m_obj);
......@@ -267,8 +441,42 @@ namespace fggl::gfx::ogl {
image.size.y,
0,
(GLenum) image.format,
(GLenum) image.type,
image.data);
(GLenum) image.type(),
image.dataPtr());
if ( m_type == TextureType::Tex2D ) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}
}
void setData(InternalImageFormat iFmt, const data::Texture2D *image) {
ImageFormat imageFormat;
if (image->channels == 1) {
imageFormat = ImageFormat::R;
} else if ( image->channels == 2) {
imageFormat = ImageFormat::RG;
} else if ( image->channels == 3) {
imageFormat = ImageFormat::RGB;
} else if ( image->channels == 4) {
imageFormat = ImageFormat::RGBA;
} else {
// unknown image format -> channels mapping, having a bad day!
return;
}
//bind();
glBindTexture((GLenum) m_type, m_obj);
glTexImage2D((GLenum) m_type,
0,
(GLint) iFmt,
image->size.x,
image->size.y,
0,
(GLenum) imageFormat,
GL_UNSIGNED_BYTE,
image->data);
if ( m_type == TextureType::Tex2D ) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
......@@ -284,8 +492,8 @@ namespace fggl::gfx::ogl {
image.size.x,
image.size.y,
(GLenum) image.format,
(GLenum) image.type,
image.data);
(GLenum) image.type(),
image.dataPtr());
}
void wrapMode(Wrapping wrap);
......
......@@ -19,6 +19,8 @@
#ifndef FGGL_GFX_OGL4_FALLBACK_HPP
#define FGGL_GFX_OGL4_FALLBACK_HPP
#include "fggl/assets/types.hpp"
/**
* Fallback shaders.
*
......@@ -58,9 +60,13 @@ namespace fggl::gfx::ogl4 {
fragColour = vec4(colour.xyz, texture(tex, texPos).r);
})glsl";
constexpr const std::array<uint32_t, 4> TEX_WHITE{ 0xFF, 0xFF, 0xFF, 0xFF };
constexpr const std::array<uint32_t, 4> TEX_CHECKER{ 0xFF, 0x00, 0x00, 0xFF };
constexpr const char* FALLBACK_TEX = "FALLBACK_TEX";
constexpr const GLuint TEX_CHECKER = 0x11FF11FF; //FIXME pixel order is reversed?!
constexpr const GLuint TEX_WHITE = 0xFF0000FF;
constexpr const assets::AssetID FALLBACK_TEX = assets::make_asset_id("fallback", "FALLBACK_TEX");
constexpr const assets::AssetID FALLBACK_MAT = assets::make_asset_id("fallback", "FALLBACK_MAT");
constexpr const assets::AssetID SOLID_TEX = assets::make_asset_id("fallback", "SOLID_TEX");
constexpr const math::vec3 FALLBACK_COLOUR {1.0F, 0.0F, 1.0F};
} // namespace fggl::gfx::ogl4
......
......@@ -37,8 +37,12 @@ namespace fggl::gfx::ogl4 {
};
struct Material {
math::vec3 m_diffCol{1.0F, 1.0F, 1.0F};
math::vec3 m_specCol{1.0F, 1.0F, 1.0F};
ogl::Texture* m_diffuse;
ogl::Texture* m_normals;
ogl::Texture* m_specular;
};
struct MeshData {
......@@ -76,6 +80,8 @@ namespace fggl::gfx::ogl4 {
void setup_material(const std::shared_ptr<ogl::Shader>& shader, const PhongMaterial* material);
void setup_lighting(const std::shared_ptr<ogl::Shader>& shader, const math::mat4& viewMatrix, const math::Transform& camTransform, const math::Transform& transform, math::vec3 lightPos);
void setup_lighting(const std::shared_ptr<ogl::Shader>& shader, const DirectionalLight* light);
template<typename T>
void forward_pass(const entity::EntityID& camera, const fggl::entity::EntityManager& world, const assets::AssetManager* assets) {
......@@ -89,6 +95,7 @@ namespace fggl::gfx::ogl4 {
// prep the fallback textures
auto *fallbackTex = assets->template get<ogl::Texture>(FALLBACK_TEX);
fallbackTex->bind(0);
fallbackTex->bind(1);
// set-up camera matrices
const auto &camTransform = world.get<fggl::math::Transform>(camera);
......@@ -97,15 +104,18 @@ namespace fggl::gfx::ogl4 {
const math::mat4 projectionMatrix = camComp.perspective();
const math::mat4 viewMatrix = glm::lookAt(camTransform.origin(), camComp.target, camTransform.up());
// TODO lighting needs to not be this...
math::vec3 lightPos{0.0F, 10.0F, 0.0F};
std::shared_ptr<ogl::Shader> shader = nullptr;
ogl::Location mvpMatrixUniform = 0;
ogl::Location mvMatrixUniform = 0;
auto entityView = world.find<T>();
debug::info("Triggering rendering pass for {} entities", entityView.size());
// find directional light in scene
const DirectionalLight* light = nullptr;
auto lightEnts = world.find<DirectionalLight>();
if ( !lightEnts.empty() ) {
light = world.tryGet<DirectionalLight>(lightEnts[0]);
}
for (const auto &entity : entityView) {
// ensure that the model pipeline actually exists...
......@@ -130,6 +140,10 @@ namespace fggl::gfx::ogl4 {
if ( shader->hasUniform("diffuseTexture") ) {
shader->setUniformI(shader->uniform("diffuseTexture"), 0);
}
if ( shader->hasUniform("specularTexture") ) {
shader->setUniformI(shader->uniform("specularTexture"), 1);
}
}
// set model transform
......@@ -137,13 +151,13 @@ namespace fggl::gfx::ogl4 {
shader->setUniformMtx(mvpMatrixUniform, projectionMatrix * viewMatrix * transform.model());
shader->setUniformMtx(mvMatrixUniform, viewMatrix * transform.model());
auto normalMatrix = glm::mat3(glm::transpose(inverse(transform.model())));
shader->setUniformMtx(shader->uniform("NormalMatrix"), normalMatrix);
// setup lighting mode
setup_lighting(shader, viewMatrix, camTransform, transform, lightPos);
if ( light != nullptr ) {
setup_lighting(shader, light);
}
setup_material(shader, world.tryGet<PhongMaterial>(entity, &DEFAULT_MATERIAL));
// actually draw it
model.draw();
}
}
......
......@@ -71,6 +71,7 @@ namespace fggl::gfx::ogl4 {
public:
inline StaticModelRenderer(gfx::ShaderCache *cache, assets::AssetManager *assets)
: m_assets(assets), m_shaders(cache), m_phong(nullptr), m_vao(), m_vertexList(), m_indexList() {
m_phong = cache->get("redbook/debug");
}
......@@ -82,8 +83,8 @@ namespace fggl::gfx::ogl4 {
StaticModelRenderer &operator=(const StaticModelRenderer &other) = delete;
StaticModelRenderer &operator=(StaticModelRenderer &&other) = delete;
StaticModel* uploadMesh(assets::AssetGUID guid, const data::Mesh& mesh, bool allowCache=true);
StaticModelGPU* uploadMesh2(const assets::AssetGUID& meshName, const data::Mesh& mesh);
StaticModel* uploadMesh(assets::AssetID guid, const data::Mesh& mesh, bool allowCache=true);
StaticModelGPU* uploadMesh2(const assets::AssetID& meshName, const data::Mesh& mesh);
void render(entity::EntityManager &world, bool debugMode = false) {
#ifdef FGGL_ALLOW_DEFERRED_UPLOAD
......
......@@ -24,6 +24,8 @@
#include "fggl/modules/module.hpp"
#include "fggl/assets/manager.hpp"
#include "fggl/assets/packed/module.hpp"
#include "fggl/entity/loader/loader.hpp"
#include "fggl/gfx/interfaces.hpp"
......@@ -36,17 +38,18 @@ namespace fggl::gfx {
struct OpenGL4 {
constexpr static const char *name = "fggl::gfx::OpenGL4";
constexpr static const std::array<modules::ModuleService, 1> provides = {
constexpr static const std::array<modules::ServiceName, 1> provides = {
WindowGraphics::service
};
constexpr static const std::array<modules::ModuleService, 4> depends = {
constexpr static const std::array<modules::ServiceName, 5> depends = {
data::Storage::service,
assets::AssetManager::service,
assets::CheckinAdapted::service,
gui::FontLibrary::service,
entity::EntityFactory::service
};
static bool factory(modules::ModuleService name, modules::Services &serviceManager);
static bool factory(modules::ServiceName name, modules::Services &serviceManager);
};
} //namespace fggl::gfx
......
......@@ -30,7 +30,15 @@ namespace fggl::gfx::ogl4 {
class WindowGraphics : public gfx::WindowGraphics {
public:
WindowGraphics(data::Storage *storage, gui::FontLibrary *fonts, assets::AssetManager* assets) : m_storage(storage), m_fonts(fonts), m_assets(assets) {};
virtual ~WindowGraphics() = default;
~WindowGraphics() override = default;
// no copy
WindowGraphics(WindowGraphics& gfx) = delete;
WindowGraphics& operator=(const WindowGraphics& gfx) = delete;
// no move
WindowGraphics(WindowGraphics&& gfx) = delete;
WindowGraphics& operator=(WindowGraphics&& gfx) = delete;
fggl::gfx::Graphics *create(display::Window &window) override;
......
......@@ -225,21 +225,22 @@ namespace fggl::gfx {
};
inline Path2D make_shape(math::vec2 center, float radius, int sides, math::vec3 colour = colours::WHITE, ShapeOpts opts = {}) {
double angle = (M_PI * 2.0) / sides;
float angle = ((math::PI * 2.0F) / sides);
fggl::gfx::Path2D tileGfx(center);
tileGfx.colour(colour);
for (int i=0; i < sides; ++i) {
float xPos = (float)(sin(i * angle + opts.angleOffset) * radius) + center.x;
float yPos = (float)(cos(i * angle + opts.angleOffset) * radius) + center.y;
if (!opts.sinFirst) {
std::swap(xPos, yPos);
}
math::vec2 pos (
(float)(cosf(i * angle + opts.angleOffset) * radius),
(float)(sinf(i * angle + opts.angleOffset) * radius)
);
pos += center;
if ( i == 0 ) {
tileGfx.moveTo( {xPos, yPos} );
tileGfx.moveTo( pos );
} else {
tileGfx.pathTo({xPos, yPos});
tileGfx.pathTo( pos );
}
}
tileGfx.close();
......
......@@ -50,6 +50,27 @@ namespace fggl::gfx {
};
struct Light {
math::vec3 position;
math::vec3 ambient;
math::vec3 specular;
math::vec3 diffuse;
};
struct DirectionalLight : public Light {
constexpr static const char *name = "gfx::phong::directional";
constexpr static const util::GUID guid = util::make_guid(name);
};
struct PointLight : public Light {
constexpr static const char *name = "gfx::phong::point";
constexpr static const util::GUID guid = util::make_guid(name);
float constant = 1.0F;
float linear;
float quadratic;
};
struct Light2 {
constexpr static const char *name = "gfx::light";
constexpr static const util::GUID guid = util::make_guid("gfx::light");
bool enabled;
......
......@@ -37,7 +37,7 @@ namespace fggl::gfx {
class WindowGraphics {
public:
constexpr const static modules::ModuleService service = modules::make_service("fggl::gfx::WindowGraphics");
constexpr const static auto service = modules::make_service("fggl::gfx::WindowGraphics");
WindowGraphics() = default;
virtual ~WindowGraphics() = default;
......
/*
* This file is part of FGGL.
*
* FGGL is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* FGGL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with FGGL.
* If not, see <https://www.gnu.org/licenses/>.
*/
//
// Created by webpigeon on 19/12/22.
//
#ifndef FGGL_GRID_ACTIONS_H
#define FGGL_GRID_ACTIONS_H
#include <cstdint>
#include <variant>
#include "fggl/grid/hexagon.hpp"
#include "fggl/grid/tokens.hpp"
#include "fggl/util/safety.hpp"
namespace fggl::grid {
template<typename State, typename Target>
class ActionType;
template<typename State, typename Target>
class Action {
public:
virtual void progress(State* state) = 0;
virtual bool isDone() = 0;
};
template<typename State, typename Target>
class InstantAction : public Action<State, Target> {
public:
void progress(State* state) final;
bool isDone() final;
private:
ActionType<State, Target>* m_action;
TokenIdentifer m_actor;
Target m_target;
};
template<typename State, typename Target>
class DurativeAction : public Action<State, Target> {
public:
void progress(State* state) final;
bool isDone() final;
private:
ActionType<State, Target>* m_action;
TokenIdentifer m_actor;
Target m_target;
uint64_t m_completionRound;
};
template<typename State, typename Target>
class ActionType {
public:
virtual bool canApply(const State* state, TokenIdentifer actor, Target target) = 0;
virtual void apply(State* state, TokenIdentifer actor, Target target) = 0;
virtual Action<State, Target> ground(TokenIdentifer actor, Target target) = 0;
};
} // namespace fggl::grid
#endif //FGGL_GRID_ACTIONS_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 27/11/22.
//
#ifndef FGGL_GRID_HEX_HPP
#define FGGL_GRID_HEX_HPP
#include <array>
#include <vector>
#include <cmath>
#include <compare>
#include <fggl/math/fmath.hpp>
/**
* Hexagonal Grid Implementation.
* Based largely off Amit's incredible grid documentation.
*/
namespace fggl::grid {
enum class HexDirPointy {
RIGHT = 0, TOP_RIGHT = 1, TOP_LEFT = 2, LEFT = 3, BOTTOM_LEFT = 4, BOTTOM_RIGHT = 5
};
enum class HexDirFlat {
BOTTOM_RIGHT = 0, TOP_RIGHT = 1, TOP = 2, TOP_LEFT = 3, BOTTOM_LEFT = 4, BOTTOM = 5
};
constexpr std::array< std::array<int, 2>, 6> HEX_DIRECTIONS {{
{1, 0}, {1, -1}, {0, 1},
{-1, 0}, {-1, 1}, {0, 1}
}};
constexpr std::array< std::array<int, 2>, 6> HEX_DIAGONALS {{
{2, -1}, {+1, -2}, {-1, -1},
{-2, 1}, {-1, 2}, {1, 1}
}};
template<typename T>
struct HexPointT {
constexpr HexPointT(T posQ, T posR) : m_pos({posQ, posR}) {}
constexpr explicit HexPointT(const std::array<int, 2>& pos) : m_pos(pos[0], pos[1]) {}
[[nodiscard]]
constexpr auto q() const -> T {
return m_pos[0];
}
[[nodiscard]]
constexpr auto r() const -> T{
return m_pos[1];
}
[[nodiscard]]
constexpr auto s() const -> T {
return -m_pos[0]-m_pos[1];
}
inline HexPointT neighbour(HexDirPointy dir) {
auto& offset = HEX_DIRECTIONS.at( (int)dir );
return { m_pos[0] + offset[0], m_pos[1] + offset[1] };
}
inline HexPointT neighbour(HexDirFlat dir) {
auto& offset = HEX_DIAGONALS.at( (int)dir );
return { m_pos[0] + offset[0], m_pos[1] + offset[1] };
}
HexPointT operator+(const HexPointT<T>& other) const {
return { m_pos[0] + other.m_pos[0], m_pos[1] + other.m_pos[1] };
}
HexPointT operator-(const HexPointT<T>& other) const {
return { m_pos[0] - other.m_pos[0], m_pos[1] - other.m_pos[1] };
}
bool operator==(const HexPointT<T>& other) const {
return m_pos[0] == other.m_pos[0] && m_pos[1] == m_pos[1];
}
auto operator<=>(const HexPointT<T>& other) const = default;
[[nodiscard]]
auto distance(const HexPointT& other) const -> T {
auto vec = *this - other;
return (
::abs(vec.q())
+ ::abs(vec.q() - vec.r())
+ ::abs(vec.r()) / 2
);
}
[[nodiscard]]
auto hexesInRange(int range) const -> std::vector<HexPointT<T>> {
std::vector<HexPointT<T>> results;
for ( auto q = -range; q <= range; ++q ) {
auto stopCount = std::min(range, -q+range);
for ( auto r = std::max(-range, -q-range); r <= stopCount; ++r ) {
results.push_back( *this + HexPointT<T>(q, r) );
}
}
return results;
}
private:
std::array<T, 2> m_pos;
};
using FloatHex = HexPointT<float>;
using IntHex = HexPointT<int>;
template<typename T>
constexpr FloatHex hexLerp(const HexPointT<T>& start, const HexPointT<T>& end, float t) {
return {
math::lerp(start.q(), end.q(), t),
math::lerp(start.r(), end.r(), t)
};
}
[[nodiscard]]
constexpr IntHex round2(const FloatHex& hex) {
auto q = std::round( hex.q() );
auto r = std::round( hex.r() );
auto s = std::round( hex.s() );
auto qDiff = std::abs( q - hex.q() );
auto rDiff = std::abs( r - hex.r() );
auto sDiff = std::abs( s - hex.r() );
if ( qDiff > rDiff && qDiff > sDiff) {
q = -r-s;
} else if ( rDiff > sDiff ) {
r = -q-s;
} else {
s = -q-r;
}
return {(int)q, (int)r};
}
std::vector<IntHex> lineTo(const IntHex& start, const IntHex& end);
} // namespace fggl::grid
#endif //FGGL_GRID_HEX_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/12/22.
//
#ifndef FGGL_GRID_HEXAGON_BOARD_HPP
#define FGGL_GRID_HEXAGON_BOARD_HPP
#include <map>
#include <set>
#include <optional>
#include <utility>
#include <variant>
#include "fggl/grid/hexagon.hpp"
#include "fggl/grid/tokens.hpp"
#include "fggl/grid/actions.hpp"
#include "fggl/math/types.hpp"
namespace fggl::grid {
class HexGrid;
using HexTarget = std::variant<TokenIdentifer, IntHex>;
using HexAction = Action<HexGrid, HexTarget>;
struct MaterialData {
std::string name;
math::vec3 colour;
};
struct TerrainType {
std::shared_ptr<MaterialData> data;
};
struct HexTile {
std::shared_ptr<MaterialData> terrain;
std::vector< std::shared_ptr<Token> > m_tokens;
[[nodiscard]]
inline std::optional<const MaterialData> data() const {
if (terrain == nullptr) {
{}
}
return *terrain;
}
};
class HexGrid {
public:
inline bool isValidPos(const IntHex& pos) const {
return m_tiles.contains(pos);
}
void setTerrain(const IntHex& pos, const TerrainType& terrain) {
auto& mapTile = m_tiles[pos];
mapTile.terrain = terrain.data;
}
std::optional<const MaterialData> getTerrain(const IntHex& pos) const {
const auto itr = m_tiles.find(pos);
if ( itr == m_tiles.end() ) {
return {};
}
return itr->second.data();
}
std::set<IntHex> getAllTiles() {
std::set<IntHex> posSet;
for ( auto& [pos,data] : m_tiles ) {
posSet.emplace( pos );
}
return posSet;
}
std::set<HexTile> tilesInRange(const IntHex& pos, int range) const;
std::set<HexTile> neighboursOf(const IntHex& pos) const;
private:
std::map<IntHex, HexTile> m_tiles;
std::map<uint64_t, std::shared_ptr<Token>> m_tokens;
};
} // namespace fggl::grid
#endif //FGGL_GRID_HEXAGON_BOARD_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/>.
*/
/*
* This file is part of FGGL.
*
* FGGL is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* FGGL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with FGGL.
* If not, see <https://www.gnu.org/licenses/>.
*/
//
// Created by webpigeon on 18/12/22.
//
#ifndef FGGL_FGGL_GRID_LAYOUT_HPP
#define FGGL_FGGL_GRID_LAYOUT_HPP
#include "fggl/math/types.hpp"
#include "fggl/grid/hexagon.hpp"
namespace fggl::grid {
// factor out the call to sqrt so the matrices can be constexpr
constexpr float M_SQRT_3 = 1.73205080757F;
constexpr float M_SQRT_3_OVER_2 = M_SQRT_3 / 2.0F;
constexpr math::mat2 MAT_HEX_POINTY{
M_SQRT_3, 0.0F,
M_SQRT_3_OVER_2, 3.F / 2.F
};
constexpr math::mat2 MAT_HEX_FLAT{
3.F / 2.F, M_SQRT_3_OVER_2,
0.0F, M_SQRT_3
};
struct Orientation {
math::mat2 m_forward;
math::mat2 m_backward;
int m_angle;
inline Orientation(int angle, math::mat2 forward) : m_forward(forward), m_backward(glm::inverse(forward)), m_angle(angle) {};
static inline Orientation make_pointy() {
return { 30, MAT_HEX_POINTY};
}
static inline Orientation make_flat() {
return { 0, MAT_HEX_FLAT };
}
};
constexpr int HEX_SIDES = 6;
constexpr int DEG_PER_HEX_SIDE = 360 / HEX_SIDES; // 60 degrees per side
struct Layout {
Orientation m_orientation;
math::vec2 m_size;
math::vec2 m_origin;
Layout(Orientation orientation, math::vec2 size, math::vec2 origin) : m_orientation(orientation), m_size(size), m_origin(origin){}
Layout(Orientation orientation, float size) : m_orientation(orientation), m_size(size, size), m_origin() {}
inline void translate(float dx, float dy){
m_origin.x += dx;
m_origin.y += dy;
}
[[nodiscard]]
inline math::vec2 origin() const {
return m_origin;
}
[[nodiscard]]
inline math::vec2 size() const {
return m_size;
}
[[nodiscard]]
inline math::vec2 toScreen(IntHex gridPos) const {
const math::vec2 hexPoint{gridPos.q(), gridPos.r()};
auto point = (m_orientation.m_forward * hexPoint) * m_size;
return point + m_origin;
}
[[nodiscard]]
inline FloatHex toGrid(math::vec2 screen) const {
auto point = (screen - m_origin) / m_size;
auto hexPos = m_orientation.m_backward * point;
return {hexPos.x, hexPos.y};
}
[[nodiscard]]
inline math::vec2 cornerOffset(int corner) const {
const int angInc = DEG_PER_HEX_SIDE * corner;
const float angle = (angInc + m_orientation.m_angle) * ( fggl::math::PI / 180.0F);
return {
m_size.x * cosf(angle),
m_size.y * sinf(angle)
};
}
void paintHex(fggl::gfx::Paint& paint, IntHex pos, math::vec3 colour, math::vec2 offset) const {
const auto hexScreenCenter = toScreen(pos);
gfx::Path2D path({0,0});
path.colour(colour);
for (int i=0; i < HEX_SIDES; ++i) {
auto cornerPos = hexScreenCenter + cornerOffset(i);
if ( i == 0) {
path.moveTo(cornerPos + offset);
} else {
path.pathTo(cornerPos + offset);
}
}
paint.stroke(path);
}
};
}
#endif //FGGL_FGGL_GRID_LAYOUT_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 19/12/22.
//
#ifndef FGGL_GRID_TOKENS_HPP
#define FGGL_GRID_TOKENS_HPP
#include <cstdint>
#include <map>
#include "fggl/util/guid.hpp"
namespace fggl::grid {
using TokenIdentifer = fggl::util::OpaqueName<uint64_t, struct Token>;
class TokenType {
public:
using PropType = int64_t;
inline void setProperty(util::GUID name, PropType newVal) {
m_properties[name] = newVal;
}
[[nodiscard]]
inline PropType getProperty(util::GUID name, PropType unsetVal=0) const {
try {
return m_properties.at(name);
} catch ( std::out_of_range& e ) {
return unsetVal;
}
}
private:
std::map<util::GUID, PropType> m_properties;
std::map<util::GUID, uint64_t> m_cost;
};
class Token {
public:
Token() = default;
explicit Token(std::shared_ptr<TokenType> type) : m_type(std::move(type)) {}
inline void setProperty(util::GUID name, TokenType::PropType newVal) {
m_properties[name] = newVal;
}
[[nodiscard]]
inline TokenType::PropType getProperty(util::GUID name, TokenType::PropType unsetVal=0) const {
try {
auto prop = m_properties.at(name);
return prop;
} catch ( std::out_of_range& ex) {
return m_type->getProperty(name, unsetVal);
}
}
[[nodiscard]]
inline TokenType::PropType getPropertyDirect(util::GUID name, TokenType::PropType unsetVal=0) const {
try {
auto prop = m_properties.at(name);
return prop;
} catch ( std::out_of_range& ex) {
return unsetVal;
}
}
private:
TokenIdentifer m_id;
std::shared_ptr<TokenType> m_type;
std::map<util::GUID, TokenType::PropType> m_properties;
};
} // namespace fggl::grid
#endif //FGGL_GRID_TOKENS_HPP
......@@ -30,7 +30,10 @@
#include <ft2build.h>
#include FT_FREETYPE_H
namespace fggl::gui {
constexpr const char* DEFAULT_FONT_NAME = "LiberationSans-Regular.ttf";
struct GlyphMetrics {
math::vec2 size;
......@@ -57,7 +60,7 @@ namespace fggl::gui {
}
math::vec2 stringSize(const std::string &text);
void texture(char letter, int &width, int &height, void **buff);
void texture(char letter, int &width, int &height, unsigned char **buff);
private:
FT_Face m_face;
......@@ -68,9 +71,9 @@ namespace fggl::gui {
class FontLibrary {
public:
constexpr static const modules::ModuleService service = modules::make_service("fggl::gui::font");
constexpr static const auto service = modules::make_service("fggl::gui::font");
FontLibrary(data::Storage *storage);
explicit FontLibrary(data::Storage *storage);
~FontLibrary();
// copy and moving not needed
......@@ -100,10 +103,18 @@ namespace fggl::gui {
return ptr;
}
inline void setDefaultFont(const std::string& name) {
m_defaultFont = getFont(name);
}
inline std::shared_ptr<FontFace> getDefaultFont() const {
return m_defaultFont;
}
private:
FT_Library m_context;
data::Storage *m_storage;
std::map<const std::string, std::shared_ptr<FontFace>> m_cache;
std::shared_ptr<FontFace> m_defaultFont;
};
} // nmespace fggl::gui
......
/*
* This file is part of FGGL.
*
* FGGL is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* FGGL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with FGGL.
* If not, see <https://www.gnu.org/licenses/>.
*/
//
// Created by webpigeon on 04/03/23.
//
#ifndef FGGL_GUI_MODEL_PARSER_HPP
#define FGGL_GUI_MODEL_PARSER_HPP
#include <fggl/gui/model/structure.hpp>
#include <fggl/gui/fonts.hpp>
#include <fggl/modules/module.hpp>
namespace fggl::gui::model {
constexpr auto WIDGET_FACTORY_SERVICE = modules::make_service("gui::WidgetService");
class WidgetFactory {
public:
constexpr static auto service = WIDGET_FACTORY_SERVICE;
inline WidgetFactory(FontLibrary* lib) : m_fontLibrary(lib) {}
inline Widget* build(std::string templateName) {
return new Widget(m_templates.at(templateName).get());
}
inline Widget* buildEmpty() {
return new Widget(m_fontLibrary);
}
inline void push(std::string name, const Widget&& definition) {
m_templates.emplace(name, std::make_unique<Widget>(definition));
}
Widget* getTemplate(const std::string& name) {
auto itr = m_templates.find(name);
if ( itr == m_templates.end() ){
return nullptr;
}
return itr->second.get();
}
private:
std::map<std::string, std::unique_ptr<Widget>> m_templates;
FontLibrary* m_fontLibrary;
};
Widget* parseFile(WidgetFactory& factory, const std::string& path);
} // namespace fggl::gui::model
#endif //FGGL_GUI_MODEL_PARSER_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 04/03/23.
//
#ifndef FGGL_GUI_MODEL_STRUCTURE_HPP
#define FGGL_GUI_MODEL_STRUCTURE_HPP
#include <map>
#include <variant>
#include <vector>
#include <string>
#include <optional>
#include <fggl/math/types.hpp>
#include <fggl/gui/fonts.hpp>
namespace fggl::gui::model {
using AttrKey = std::string;
using AttrValue = std::variant<bool, int, float, std::string, math::vec2, math::vec3>;
constexpr float UNDEFINED = INFINITY;
constexpr math::vec2 UNDEFINED_SIZE{INFINITY, INFINITY};
class Widget {
public:
using ChildItr = std::vector<Widget>::iterator;
using ChildItrConst = std::vector<Widget>::const_iterator;
inline Widget(FontLibrary* library) :
m_parent(nullptr),
m_children(),
m_fontLibrary(library),
m_attrs(),
m_cachedSize(),
m_dirty(true) {
}
explicit inline Widget(Widget* parent) :
m_parent(parent),
m_children(),
m_fontLibrary(parent->m_fontLibrary),
m_attrs(),
m_cachedSize(),
m_dirty(true) {
}
inline bool isRoot() const {
return m_parent == nullptr;
}
inline bool isLeaf() const {
return m_children.empty();
}
inline bool hasAttr(const AttrKey& key) const {
return m_attrs.contains(key);
}
inline std::map<AttrKey, AttrValue> attrs() {
return m_attrs;
}
template<typename type>
inline type get(const AttrKey& key) const {
return std::get<type>(m_attrs.at(key));
}
template<typename type>
type get_or_default(const AttrKey& key) const {
auto itr = m_attrs.find(key);
if ( itr == m_attrs.end() ) {
return type();
} else {
return std::get<type>(itr->second);
}
}
template<typename type>
inline void set(const AttrKey& key, type value) {
m_attrs[key] = value;
}
inline void addChild(const Widget& element) {
auto childItr = m_children.insert( m_children.cend(), element );
childItr->m_parent = this;
}
inline ChildItr begin() {
return m_children.begin();
}
inline ChildItrConst begin() const noexcept {
return m_children.begin();
}
inline ChildItrConst cbegin() const noexcept {
return m_children.cbegin();
}
inline ChildItr end() {
return m_children.end();
}
inline ChildItrConst end() const {
return m_children.end();
}
inline ChildItrConst cend() const {
return m_children.cend();
}
inline std::optional<math::vec2> preferredSize() {
calcPrefSize(m_fontLibrary->getDefaultFont());
return m_cachedSize;
}
private:
Widget *m_parent;
std::vector<Widget> m_children;
FontLibrary* m_fontLibrary;
std::map< AttrKey, AttrValue > m_attrs;
math::vec2 m_cachedSize;
bool m_dirty;
void calcPrefSize(std::shared_ptr<FontFace> face);
};
void attr_box_set(Widget& widget, const AttrKey& key, auto top, auto right, auto bottom, auto left) {
widget.set(key + "::top", top);
widget.set(key + "::right", right);
widget.set(key + "::bottom", bottom);
widget.set(key + "::left", left);
}
inline void attr_box_set(Widget& widget, const AttrKey& key, auto vert, auto horz) {
attr_box_set(widget, key, vert, horz, vert, horz);
}
inline void attr_box_set(Widget& widget, const AttrKey& key, auto value) {
attr_box_set(widget, key, value, value, value, value);
}
} // namespace fggl::gui::model
#endif //FGGL_GUI_MODEL_STRUCTURE_HPP