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
Commits on Source (22)
Showing
with 369 additions and 32 deletions
......@@ -82,9 +82,7 @@ endif()
# Demo project
if (FGGL_EXAMPLES)
add_subdirectory(demo)
target_compile_options( demo PRIVATE -Wall -Wextra -Wodr -Wdouble-promotion -fno-strict-aliasing -fno-strict-overflow )
set_property(TARGET demo PROPERTY INTERPROCEDURAL_OPTIMIZATION True)
add_subdirectory(demo EXCLUDE_FROM_ALL)
endif()
##
......
......@@ -12,6 +12,10 @@ On Ubuntu:
sudo apt install build-essential cmake
sudo apt install -y libglm-dev libglfw3-dev libopenal-dev libspdlog-dev libfreetype-dev libyaml-cpp-dev libassimp-dev libbullet-dev
```
On Fedora:
```bash
sudo dnf install -y glm-devel glfw-devel openal-soft-devel spdlog-devel freetype-devel yaml-cpp-devel assimp-devel bullet-devel gcc gcc-c++ cmake gtest-devel doxygen lua lua-devel gmock gmock-devel
```
### Building
It's designed to be a fairly standard cmake project, so the standard cmake steps should work:
......
......@@ -11,8 +11,13 @@ add_executable(demo
demo/robot/programmer.cpp
demo/models/viewer.cpp
demo/hexboard/board.cpp
demo/hexboard/camera.cpp
)
# set build flags
target_compile_options( demo PRIVATE -Wall -Wextra -Wodr -Wdouble-promotion -fno-strict-aliasing -fno-strict-overflow )
set_property(TARGET demo PROPERTY INTERPROCEDURAL_OPTIMIZATION True)
target_include_directories(demo
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include
......
---
- define: label
attrs:
value: """
- define: button
children:
- template: label
- define: textinput
children:
- template: label
- define: checkbox
attrs:
state: False
- define: radio
attrs:
state: False
- define: frame
......@@ -21,6 +21,9 @@
#include "fggl/assets/loader.hpp"
#include "fggl/entity/gridworld/zone.hpp"
#include "fggl/gui/model/parser.hpp"
#include "fggl/gui/renderer/renderer.hpp"
using namespace fggl::gfx::colours;
namespace demo {
......@@ -94,8 +97,8 @@ namespace demo {
auto& manager = area->entities();
{
player = manager.create();
auto& cellPos = manager.add<CellPos>(player);
auto& robotState = manager.add<RobotState>(player);
manager.add<CellPos>(player);
manager.add<RobotState>(player);
}
return player;
......@@ -123,7 +126,7 @@ namespace demo {
fggl::math::vec2i size{32, 32};
auto btn = std::make_unique<fggl::gui::Button>(pos, size);
btn->label(action.name);
btn->addCallback([=](){
btn->addCallback([=, this](){
this->m_program.m_instructions.push_back({action.name, action.callback});
});
btnGrid->add(std::move(btn));
......@@ -195,7 +198,7 @@ namespace demo {
constexpr float DRAW_HALF = DRAW_SIZE / 2.0F;
constexpr float WALL_HALF = 2.5F;
static void render_grid(fggl::gfx::Paint& paint, fggl::entity::grid::Area2D<255, 255>& grid) {
static void render_grid(fggl::gfx::Paint& paint, fggl::entity::grid::Area2D<255, 255>& grid, fggl::App& app) {
const fggl::math::vec2 wallOffsetNorth {0, -DRAW_HALF};
const fggl::math::vec2 wallOffsetWest {-DRAW_HALF, 0};
......@@ -223,6 +226,35 @@ namespace demo {
}
}
}
// UI test
auto widgetFactory = app.service<fggl::gui::model::WidgetFactory>();
auto widget = widgetFactory->buildEmpty();
widget->set("position", fggl::math::vec2{200.0F, 100.F});
widget->set("size", fggl::math::vec2{500.0F, 300.F});
widget->set("colour", fggl::gfx::colours::BLANCHED_ALMOND);
fggl::gui::model::attr_box_set(*widget, "padding", 5.0F);
auto handle = widgetFactory->buildEmpty();
handle->set("border::bottom",5.0F);
handle->set("position", fggl::math::vec2{0.0F, 0.0F});
//handle->set("size", fggl::math::vec2{INFINITY, 50.0F});
handle->set("text", "hello, world!");
handle->set("colour", fggl::gfx::colours::ORANGE);
fggl::gui::model::attr_box_set(*handle, "padding", 5.0F);
widget->addChild(*handle);
delete handle;
auto content = widgetFactory->buildEmpty();
content->set("position", fggl::math::vec2{0.0F, 50.0F});
//content->set("size", fggl::gui::model::UNDEFINED_SIZE);
content->set("colour", fggl::gfx::colours::BURLYWOOD);
widget->addChild(*content);
delete content;
fggl::gui::renderer::layout(*widget);
fggl::gui::renderer::visit(*widget, paint);
}
......@@ -325,7 +357,7 @@ namespace demo {
void GridScene::render(fggl::gfx::Graphics &gfx) {
fggl::gfx::Paint paint;
render_grid(paint, *m_grid);
render_grid(paint, *m_grid, owner());
render_objects(paint, *m_grid);
m_canvas.render(paint);
......
......@@ -19,16 +19,47 @@
#include "hexboard/scene.hpp"
namespace demo::hexboard {
constexpr float SCROLL_SPEED = 0.01F;
constexpr float HEX_SIZE = 64.0F;
constexpr std::array<fggl::grid::IntHex, 4> ISLAND_CENTERS {{
{2, 3},
{6, 7},
{9, 10},
{6, 3}
}};
Scene::Scene(fggl::App &app) : GameBase(app), m_board(nullptr) {
Scene::Scene(fggl::App &app) : GameBase(app), m_board(nullptr), m_screen(1920.F, 1080.F) {
}
void Scene::activate() {
m_board = std::make_unique<fggl::grid::HexGrid>();
m_layout = std::make_unique<fggl::grid::Layout>( fggl::grid::Orientation::make_pointy(), HEX_SIZE );
//m_layout->m_origin = { 1920.0F * -0.5F, 1080.0F * -0.5F};
m_selections = std::make_unique<SelectionModel>();
const fggl::grid::TerrainType grass{
.data = std::make_shared<fggl::grid::MaterialData>()
};
grass.data->name = "grass";
grass.data->colour = {0.0F, 1.0F, 0.0};
for (auto islandPoint : ISLAND_CENTERS){
auto island = islandPoint.hexesInRange(2);
for (auto &hex : island) {
m_board->setTerrain(hex, grass);
}
}
m_camera = std::make_unique<Camera2D>();
}
void Scene::deactivate() {
m_board = nullptr;
m_selections = nullptr;
m_layout = nullptr;
}
void Scene::update(float delta) {
......@@ -38,6 +69,65 @@ namespace demo::hexboard {
if ( m_board == nullptr ){
return;
}
// check if a button was pressed
auto& input = this->input();
{
const auto mouseNdc = fggl::input::mouse_axis(input.mouse);
const auto screenPos = ndc_to_screen(mouseNdc, m_screen);
// calculate what the user clicked on
auto worldPx = m_camera->unproject(screenPos);
m_selections->hover = fggl::grid::round2( m_layout->toGrid(worldPx) );
if (input.mouse.pressed(fggl::input::MouseButton::LEFT)) {
m_selections->selected = m_selections->hover;
m_camera->moveBy(mouseNdc * (m_screen * 0.5F) );
}
if ( input.mouse.down(fggl::input::MouseButton::RIGHT) ) {
if (input.mouse.pressed( fggl::input::MouseButton::RIGHT )) {
m_dragging = screenPos;
}
auto offset = screenPos - m_dragging.value();
m_camera->teleportBy(offset * SCROLL_SPEED);
} else if ( input.mouse.released(fggl::input::MouseButton::RIGHT) ) {
m_dragging = {};
}
}
m_camera->update(delta);
// flip y, because reasons
//auto offset = m_camera->getFocusLocation();
//m_layout->m_origin = -offset;
}
void Scene::drawGrid(fggl::gfx::Paint& paint) {
auto tiles = m_board->getAllTiles();
for ( const auto& tile : tiles ) {
auto terrain = m_board->getTerrain(tile);
if ( terrain.has_value() ) {
const auto& terrainData = terrain.value();
m_layout->paintHex(paint, tile, terrainData.colour, m_camera->getFocusLocation());
}
}
}
void Scene::drawSelections(fggl::gfx::Paint& paint) {
if ( m_selections == nullptr || m_dragging.has_value() ) {
return;
}
if ( m_selections->selected.has_value() ) {
m_layout->paintHex( paint, m_selections->selected.value(), fggl::gfx::colours::YELLOW, m_camera->getFocusLocation());
}
if ( m_selections->hover.has_value() ) {
m_layout->paintHex( paint, m_selections->hover.value(), fggl::gfx::colours::BLANCHED_ALMOND, m_camera->getFocusLocation());
}
}
void Scene::render(fggl::gfx::Graphics &gfx) {
......@@ -47,8 +137,13 @@ namespace demo::hexboard {
}
// draw the grid
// FIXME don't hard-code the screen size
fggl::gfx::Paint paint;
drawGrid(paint);
drawSelections(paint);
gfx.draw2D(paint);
}
} // namespace demo::hexboard
\ 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 02/01/23.
//
#include "hexboard/camera.hpp"
#include "fggl/math/fmath.hpp"
#include <cmath>
namespace demo::hexboard {
void Camera2D::update(float delta) {
m_location = fggl::math::smooth_add( m_location, m_target, m_scale );
if ( m_trauma > 0 ) {
m_trauma = std::max( m_trauma - TRAUMA_DECAY, 0.0F );
}
}
}
\ No newline at end of file
......@@ -46,7 +46,7 @@ namespace demo {
mesh.pipeline = "redbook/debug";
}
auto& material = manager.add<fggl::gfx::PhongMaterial>(model);
manager.add<fggl::gfx::PhongMaterial>(model);
return model;
}
......@@ -93,7 +93,7 @@ namespace demo {
static void setup_lighting(fggl::entity::EntityManager& ecs) {
auto light = ecs.create();
auto& transform = ecs.add<fggl::math::Transform>(light);
ecs.add<fggl::math::Transform>(light);
auto& lightComp = ecs.add<fggl::gfx::DirectionalLight>(light);
lightComp.position = fggl::math::vec3( 10.0F, 5.0F, 0.0F );
......@@ -149,7 +149,7 @@ namespace demo {
}
}
void Viewer::cycleAsset(uint64_t idx) {
void Viewer::cycleAsset(uint64_t /*idx*/) {
auto *loader = owner().service<fggl::assets::Loader>();
auto *manager = owner().service<fggl::assets::AssetManager>();
......
......@@ -48,7 +48,7 @@ static void setup_camera(fggl::entity::EntityManager& world) {
world.add<fggl::gfx::Camera>(prototype);
}
static fggl::entity::EntityID setup_environment(fggl::entity::EntityManager& world, fggl::entity::EntityFactory* factory, const fggl::math::vec2& size, demo::RollState& state) {
static fggl::entity::EntityID setup_environment(fggl::entity::EntityManager& world, fggl::entity::EntityFactory* /*factory*/, const fggl::math::vec2& /*size*/, demo::RollState& state) {
// ensure the state is clean
state.closestPickup = fggl::entity::INVALID;
state.mode = demo::DebugMode::NORMAL;
......
......@@ -54,7 +54,7 @@ namespace demo {
static void setup_lighting(fggl::entity::EntityManager& ecs) {
auto light = ecs.create();
auto& transform = ecs.add<fggl::math::Transform>(light);
ecs.add<fggl::math::Transform>(light);
auto& lightComp = ecs.add<fggl::gfx::DirectionalLight>(light);
lightComp.position = fggl::math::vec3( 10.0F, 5.0F, 0.0F );
......
/*
* 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 02/01/23.
//
#ifndef FGGL_DEMO_INCLUDE_HEXBOARD_CAMERA_HPP
#define FGGL_DEMO_INCLUDE_HEXBOARD_CAMERA_HPP
#include "fggl/math/types.hpp"
namespace demo::hexboard {
constexpr float TRAUMA_DECAY = 0.01F;
constexpr float TRAUMA_LARGE = 0.5F;
constexpr float TRAUMA_SMALL = 0.1F;
constexpr float SPEED_SLOW = 0.01F;
constexpr float SPEED_MEDIUM = 0.1F;
constexpr float SPEED_FAST = 0.5F;
constexpr fggl::math::vec2 ndc_to_screen(fggl::math::vec2 ndcPos, fggl::math::vec2 screenSize) {
return fggl::math::vec2(
fggl::math::rescale_ndc(ndcPos.x, 0, screenSize.x),
fggl::math::rescale_ndc(ndcPos.y, 0, screenSize.y)
);
}
/**
* A 2D 'juiced' camera for grid worlds.
*
* This camera is based on HexBoard, and the GDC talk around this concept. Many of the ideas implemented here
* come from that source.
*
* @see https://www.youtube.com/watch?v=tu-Qe66AvtY
*/
class Camera2D {
public:
using Point = fggl::math::vec2;
/**
* Apply active camera effects.
*
* This method must be called once per frame of the camera's visual effects are to be animated.
*
* @param delta the amount of time that has passed
*/
void update(float delta);
inline fggl::math::vec2 unproject(fggl::math::vec2 screenPos) const {
auto location = screenPos;
location.x += 1920/2.0F;
location.y += 1080/2.0F;
return location + m_location;
// return screenPos + m_location;
}
inline fggl::math::vec2 project(fggl::math::vec2 worldPos) const {
return worldPos - m_location;
}
/**
* Move the camera to a new location.
*
* This will apply any movement effects the camera has applied to it. As a result movement to the location
* will not be instantaneous.
*
* @param newTarget the new target location
*/
inline void moveTo(Point newTarget) {
m_target = newTarget;
}
/**
* Move the camera by a defined amount.
*
* This will apply any movement effects the camera has applied to it. As a result movement to the location
* will not be instantaneous.
*
* @param delta the amount to add to the target, negative values will subject from the target location
*/
inline void moveBy(Point delta) {
m_target += delta;
}
/**
* Instantaneously move the camera to a new location.
*
* @param the new camera location
*/
inline void teleportTo(Point newTarget) {
m_location = newTarget;
m_target = newTarget;
}
/**
* Instantaneously adjust the camera location.
*
* @param delta the amount to adjust the camera location by
*/
inline void teleportBy(Point delta) {
m_location += delta;
m_target = m_location;
}
/**
* Get the current view offset of this camera.
*
* @return the current location this camera is pointing at
*/
inline Point getFocusLocation() const {
auto offset = m_location;
offset.x += 1920/2.0F;
offset.y += 1080/2.0F;
return -offset;
}
private:
Point m_location;
Point m_target;
float m_trauma;
float m_scale = SPEED_MEDIUM;
};
}
#endif //FGGL_DEMO_INCLUDE_HEXBOARD_CAMERA_HPP
......@@ -20,12 +20,21 @@
#define FGGL_DEMO_INCLUDE_HEXBOARD_SCENE_H
#include <memory>
#include <optional>
#include "fggl/scenes/game.hpp"
#include "fggl/grid/hexgrid.hpp"
#include "fggl/grid/layout.hpp"
#include "camera.hpp"
namespace demo::hexboard {
struct SelectionModel {
std::optional<fggl::grid::IntHex> selected;
std::optional<fggl::grid::IntHex> hover;
};
class Scene : public fggl::scenes::GameBase {
public:
explicit Scene(fggl::App& app);
......@@ -38,6 +47,15 @@ namespace demo::hexboard {
private:
std::unique_ptr<fggl::grid::HexGrid> m_board;
std::unique_ptr<fggl::grid::Layout> m_layout;
std::unique_ptr<SelectionModel> m_selections;
std::unique_ptr<Camera2D> m_camera;
fggl::math::vec2 m_screen;
std::optional<fggl::math::vec2> m_dragging;
void drawGrid(fggl::gfx::Paint&);
void drawSelections(fggl::gfx::Paint&);
};
} // namespace demo::hexboard
......
......@@ -56,12 +56,10 @@ target_sources(${PROJECT_NAME}
input/input.cpp
input/mouse.cpp
input/camera_input.cpp
)
gui/widget.cpp
gui/widgets.cpp
gui/containers.cpp
gui/fonts.cpp
)
# GUI support
add_subdirectory(gui)
# yaml-cpp for configs and storage
find_package(yaml-cpp)
......@@ -70,9 +68,6 @@ target_link_libraries(fggl PUBLIC yaml-cpp)
# model loading
add_subdirectory(data/assimp)
find_package(Freetype)
target_link_libraries(${PROJECT_NAME} PUBLIC Freetype::Freetype)
# Graphics backend
add_subdirectory(gfx)
add_subdirectory(audio)
......
......@@ -20,7 +20,7 @@
namespace fggl::assets {
auto AssetFolders::factory(modules::ModuleService service, modules::Services &services) -> bool {
auto AssetFolders::factory(modules::ServiceName service, modules::Services &services) -> bool {
if (service == Loader::service) {
auto *storage = services.get<data::Storage>();
auto *checkin = services.get<CheckinAdapted>();
......
......@@ -20,7 +20,7 @@
namespace fggl::assets {
auto PackedAssets::factory(modules::ModuleService service, modules::Services &services) -> bool {
auto PackedAssets::factory(modules::ServiceName service, modules::Services &services) -> bool {
if (service == RawCheckin::service) {
services.create<RawCheckin>();
return true;
......
......@@ -26,7 +26,7 @@ namespace fggl::audio {
void NullAudioService::play(const fggl::audio::AudioClipShort &, bool) {
}
auto NullAudio::factory(modules::ModuleService service, modules::Services &services) -> bool{
auto NullAudio::factory(modules::ServiceName service, modules::Services &services) -> bool{
if (service == SERVICE_AUDIO_PLAYBACK) {
services.bind<audio::AudioService, audio::NullAudioService>();
return true;
......
......@@ -51,7 +51,7 @@ namespace fggl::audio::openal {
return nullptr;
}
auto load_vorbis_short(std::filesystem::path path, assets::MemoryBlock& block) -> bool {
auto load_vorbis_short(std::filesystem::path path, assets::MemoryBlock& /*block*/) -> bool {
// vorbis
auto* clip = new AudioClipShort();
clip->sampleCount = stb_vorbis_decode_filename( path.c_str(), &clip->channels, &clip->sampleRate, &clip->data);
......
......@@ -20,7 +20,7 @@
namespace fggl::audio {
auto OpenAL::factory(modules::ModuleService service, modules::Services &services) -> bool {
auto OpenAL::factory(modules::ServiceName service, modules::Services &services) -> bool {
if (service == SERVICE_AUDIO_PLAYBACK) {
auto* assets = services.get<assets::AssetManager>();
......
......@@ -17,7 +17,6 @@
//
#include "fggl/data/assimp/module.hpp"
#include "fggl/data/model.hpp"
#include "fggl/debug/logging.hpp"
#include "fggl/assets/manager.hpp"
#include "fggl/mesh/mesh.hpp"
......@@ -212,7 +211,7 @@ namespace fggl::data::models {
return nullptr;
}
auto load_assimp_texture(assets::Loader* loader, const assets::AssetID& guid, const assets::LoaderContext& data, void* userPtr) -> assets::AssetRefRaw {
auto load_assimp_texture(assets::Loader* /*loader*/, const assets::AssetID& guid, const assets::LoaderContext& data, void* userPtr) -> assets::AssetRefRaw {
auto* manager = (assets::AssetManager*)userPtr;
if ( manager->has(guid) ) {
......@@ -232,7 +231,7 @@ namespace fggl::data::models {
return nullptr;
} else {
debug::info("image reports it loaded correctly, adding {} to database", guid);
manager->set(guid, image);
manager->set(guid, image );
}
return nullptr;
......@@ -314,7 +313,7 @@ namespace fggl::data::models {
return true;
}
auto AssimpModule::factory(modules::ModuleService service, modules::Services &serviceManager) -> bool {
auto AssimpModule::factory(modules::ServiceName service, modules::Services &serviceManager) -> bool {
if ( service == MODEL_PROVIDER ) {
auto* assetLoader = serviceManager.get<assets::Loader>();
assetLoader->setFactory( MODEL_MULTI3D, load_assimp_model, assets::LoadType::PATH );
......
......@@ -20,7 +20,7 @@
namespace fggl::data {
auto LocalStorage::factory(modules::ModuleService service, modules::Services &data) -> bool {
auto LocalStorage::factory(modules::ServiceName service, modules::Services &data) -> bool {
if (service == SERVICE_STORAGE) {
// FIXME: no easy way to set the application name
auto pathConfig = fggl::platform::calc_engine_paths("fggl-demo");
......