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 8451 additions and 171 deletions
......@@ -21,7 +21,6 @@
#include <string>
#include <stdexcept>
#include <GLFW/glfw3.h>
#include <spdlog/spdlog.h>
namespace fggl::display::glfw {
......@@ -34,37 +33,37 @@ namespace fggl::display::glfw {
fgglWindow->framesize(width, height);
}
static void fggl_input_cursor(GLFWwindow *window, double x, double y) {
static void fggl_input_cursor(GLFWwindow *window, double xPos, double yPos) {
auto &input = GlfwInputManager::instance();
auto *fgglWin = static_cast<Window *>(glfwGetWindowUserPointer(window));
#ifndef FGGL_INPUT_SCREEN_COORDS
// convert to nice ranges...
x = (x / fgglWin->width() * 2) - 1.0; // [-1, 1]
y = (y / fgglWin->height() * 2) - 1.0; // [-1, 1]
xPos = (xPos / fgglWin->width() * 2) - 1.0; // [-1, 1]
yPos = (yPos / fgglWin->height() * 2) - 1.0; // [-1, 1]
#endif
// inform the input system
input.onMouseMove(x, y);
input.onMouseMove(xPos, yPos);
}
static void fggl_input_scroll(GLFWwindow *window, double x, double y) {
static void fggl_input_scroll(GLFWwindow */*window*/, double xPos, double yPos) {
auto &input = GlfwInputManager::instance();
input.onMouseScroll(x, y);
input.onMouseScroll(xPos, yPos);
}
static void fggl_input_mouse_btn(GLFWwindow *window, int btn, int action, int mods) {
static void fggl_input_mouse_btn(GLFWwindow */*window*/, int btn, int action, int /*mods*/) {
auto &input = GlfwInputManager::instance();
input.onMouseButton(btn, action == GLFW_PRESS);
}
static void fggl_input_keyboard(GLFWwindow *window, int key, int scancode, int action, int mods) {
static void fggl_input_keyboard(GLFWwindow */*window*/, int /*key*/, int scancode, int action, int /*mods*/) {
auto &input = GlfwInputManager::instance();
input.onKeyEvent(scancode, action == GLFW_PRESS || action == GLFW_REPEAT);
}
static void fggl_update_joystick(fggl::input::GamepadInput &input, int jid) {
bool isGamepad = glfwJoystickIsGamepad(jid);
bool isGamepad = (glfwJoystickIsGamepad(jid) == GLFW_TRUE);
if (isGamepad) {
if (!input.present(jid)) {
......@@ -99,7 +98,7 @@ namespace fggl::display::glfw {
auto &gamepadCtl = input.gamepads();
for (int jid = 0; jid < GLFW_JOYSTICK_LAST; jid++) {
if (glfwJoystickPresent(jid)) {
if (glfwJoystickPresent(jid) == GLFW_TRUE) {
fggl_update_joystick(gamepadCtl, jid);
} else {
gamepadCtl.setActive(jid, false);
......@@ -144,7 +143,7 @@ namespace fggl::display::glfw {
GlfwContext::~GlfwContext() {
glfwTerminate();
spdlog::debug("[glfw] context terminated");
debug::trace("[glfw] context terminated");
}
void GlfwContext::pollEvents() {
......@@ -157,7 +156,9 @@ namespace fggl::display::glfw {
Window::Window(std::shared_ptr<GlfwContext> context, gfx::WindowGraphics *graphics)
: m_context(std::move(context)), m_window(nullptr), m_framesize() {
spdlog::debug("[glfw] creating window");
// don't iconify when focus is lost.
glfwWindowHint( GLFW_AUTO_ICONIFY, GLFW_FALSE );
// FIXME - this ties the graphics API before window creation
auto graphicsConfig = graphics->config();
......@@ -184,12 +185,15 @@ namespace fggl::display::glfw {
// bind the graphics API
glfwMakeContextCurrent(m_window);
m_graphics = std::unique_ptr<gfx::Graphics>(graphics->create(*this));
spdlog::debug("[glfw] window creation complete");
m_graphics = graphics->createMain(*this);
}
Window::~Window() {
if ( m_graphics != nullptr ) {
delete m_graphics;
m_graphics = nullptr;
}
if (m_window != nullptr) {
// prevent dangling pointers
glfwSetWindowUserPointer(m_window, nullptr);
......@@ -215,14 +219,14 @@ namespace fggl::display::glfw {
glfwMakeContextCurrent(m_window);
}
fggl::math::vec2i Window::frameSize() const {
auto Window::frameSize() const -> fggl::math::vec2i {
assert(m_window != nullptr);
math::vec2i size;
glfwGetFramebufferSize(m_window, &size.x, &size.y);
return size;
}
bool Window::wantClose() const {
auto Window::wantClose() const -> bool {
assert(m_window != nullptr);
return glfwWindowShouldClose(m_window) == GLFW_TRUE;
}
......
target_sources( fggl
PRIVATE
hexagon.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 10/12/22.
//
#include "fggl/grid/hexagon.hpp"
namespace fggl::grid {
std::vector<IntHex> lineTo(const IntHex& start, const IntHex& end) {
const int distance = start.distance(end);
std::vector<IntHex> line;
for (auto i=0; i < distance; ++i) {
line.push_back( round2(hexLerp(start, end, 1.0F/distance * i)) );
}
return line;
}
} // namespace fggl:grid
target_sources( ${PROJECT_NAME}
PRIVATE
widget.cpp
widgets.cpp
containers.cpp
fonts.cpp
model/parser.cpp
model/structure.cpp
renderer/renderer.cpp
)
find_package(Freetype)
target_link_libraries(${PROJECT_NAME} PUBLIC Freetype::Freetype)
......@@ -17,7 +17,7 @@
namespace fggl::gui {
Widget *Container::getChildAt(const math::vec2 &point) {
auto Container::getChildAt(const math::vec2 &point) -> Widget * {
for (auto &child : m_children) {
if (child->contains(point)) {
return child->getChildAt(point);
......@@ -27,7 +27,7 @@ namespace fggl::gui {
return nullptr;
}
bool Container::contains(const math::vec2 &point) {
auto Container::contains(const math::vec2 &point) -> bool {
return true;
}
......@@ -42,6 +42,84 @@ namespace fggl::gui {
m_dirty = true;
}
void Container::onMouseOver(math::vec2 pos) {
Widget::onMouseOver(pos);
auto* childHover = getChildAt(pos);
for ( auto& child : m_children) {
if ( child.get() != childHover ) {
child->onExit(pos);
}
}
if ( childHover != nullptr ) {
childHover->onMouseOver(pos);
}
}
void Container::onEnter(math::vec2i pos) {
Widget::onEnter(pos);
for ( auto& child : m_children ) {
if ( child->contains(pos)) {
child->onEnter(pos);
}
}
}
void Container::onExit(math::vec2i pos) {
Widget::onExit(pos);
for ( auto& child : m_children) {
child->onExit(pos);
}
}
GridBox::GridBox(uint32_t rows, uint32_t cols, uint32_t padx, uint32_t pady) : m_rows(rows), m_cols(cols), m_padding(padx, pady) {}
void GridBox::layout() {
assert( m_rows != 0 || m_cols != 0 );
if ( m_rows == 0 ) {
int rows = m_children.size() / m_cols;
// figure out the width and heights
auto* widths = new float[m_cols]{0.0F};
auto* heights = new float[rows]{0.0F};
for ( auto idx = 0U; idx < m_children.size(); ++idx) {
auto& child = m_children[idx];
int col = idx % m_cols;
int row = idx / m_cols;
widths[col] = std::max( child->size().x, widths[col] );
heights[row] = std::max( child->size().y, heights[row] );
}
// populate the grid
fggl::math::vec2i pos{0, 0};
unsigned int row = 0;
unsigned int col = 0;
for ( auto& child : m_children ) {
fggl::math::vec2i size{ widths[col], heights[row] };
child->size(pos, size);
child->layout();
// next iter
pos.x += size.x + m_padding.x;
col++;
if ( col == m_cols ) {
col = 0;
row++;
pos.x = 0;
pos.y += size.y + m_padding.y;
}
}
// cleanup variables
delete[] widths;
delete[] heights;
}
}
/*
Box::Box( LayoutAxis axis ) : m_axis( axis ) {}
......@@ -70,7 +148,7 @@ namespace fggl::gui {
void Panel::render(gfx::Paint &paint) {
// background painting time
gfx::Path2D background(topLeft());
background.colour(math::vec3(32.0f / 255.0f, 74.0F / 255.0F, 135.0F / 255.0F));
background.colour(math::vec3(32.0F / 255.0F, 74.0F / 255.0F, 135.0F / 255.0F));
draw_box(background, topLeft(), bottomRight());
paint.fill(background);
......
......@@ -25,19 +25,19 @@ namespace fggl::gui {
FontLibrary::FontLibrary(data::Storage *storage) : m_context(nullptr), m_storage(storage) {
FT_Init_FreeType(&m_context);
m_defaultFont = getFont(DEFAULT_FONT_NAME);
}
FontLibrary::~FontLibrary() {
// free all fonts
for (auto &face : m_cache) {
face.second = nullptr;
}
m_defaultFont = nullptr;
m_cache.clear();
// shut the library down
FT_Done_FreeType(m_context);
}
GlyphMetrics &FontFace::populateMetrics(char letter) {
auto FontFace::populateMetrics(char letter) -> GlyphMetrics & {
if (FT_Load_Char(m_face, letter, FT_LOAD_RENDER)) {
// something bad happened
return m_metrics['?'];
......@@ -54,7 +54,7 @@ namespace fggl::gui {
return it.first->second;
}
void FontFace::texture(char letter, int &width, int &height, void **buff) {
void FontFace::texture(char letter, int &width, int &height, unsigned char **buff) {
if (FT_Load_Char(m_face, letter, FT_LOAD_RENDER)) {
// something bad happened
return;
......
/*
* This file is part of FGGL.
*
* FGGL is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* FGGL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with FGGL.
* If not, see <https://www.gnu.org/licenses/>.
*/
//
// Created by webpigeon on 11/03/23.
//
#include "fggl/gui/model/parser.hpp"
#include <yaml-cpp/yaml.h>
namespace fggl::gui::model {
Widget* YamlToWidgetTree(WidgetFactory& factory, const YAML::Node& config) {
Widget* root;
if ( config["template"] ) {
root = factory.build( config["template"].as<std::string>());
} else {
root = factory.buildEmpty();
}
// deal with attrs
for ( auto attr : config["attrs"] ) {
root->set(attr.first.as<std::string>(), attr.second.as<std::string>());
}
// deal with child nodes
for ( auto child : config["children"] ) {
Widget* childWidget = YamlToWidgetTree(factory, child);
root->addChild(*childWidget);
}
// are we a template definition?
if ( config["define"] ) {
factory.push( config["define"].as<std::string>(), std::move(*root) );
return factory.getTemplate( config["define"].as<std::string>() );
}
return root;
}
inline Widget* parseFile(WidgetFactory& factory, const std::string& path) {
YAML::Node root = YAML::LoadFile(path);
if ( !root ){
return nullptr;
}
return YamlToWidgetTree(factory, root);
}
}
\ 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 11/03/23.
//
#include "fggl/gui/model/structure.hpp"
#include "fggl/gui/fonts.hpp"
#include <algorithm>
#include <utility>
#include <string>
namespace fggl::gui::model {
math::vec2 calcTextBounds(const std::string& value, std::shared_ptr<FontFace> face) {
if ( face == nullptr ){
debug::warning("No preferred font sent, cowardly refusing to process text");
return {};
}
math::vec2 max{0, 0};
for (auto letter : value) {
auto metrics = face->metrics(letter);
max.x += metrics.size.x + (metrics.advance >> 6);
max.y = std::max(max.y, metrics.size.y);
}
return max;
}
inline math::vec2 calcBoxContrib(const Widget& widget, const std::string& name) {
return math::vec2{
widget.get_or_default<float>( name + "::left") + widget.get_or_default<float>(name + "::right"),
widget.get_or_default<float>( name + "::top" ) + widget.get_or_default<float>( name + "::bottom" )
};
}
void Widget::calcPrefSize(std::shared_ptr<FontFace> face) {
if ( !m_dirty ){
return;
}
auto padding = calcBoxContrib( *this, "padding");
auto border = calcBoxContrib( *this, "border");
auto content = math::vec2{0,0};
if (hasAttr("text")) {
content += calcTextBounds( get<std::string>("text"), std::move(face) );
}
m_cachedSize = padding + content + content;
debug::info("my preferred size is: ({}, {})", m_cachedSize.x, m_cachedSize.y);
m_dirty = false;
}
}
\ 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 11/03/23.
//
#include "fggl/gui/renderer/renderer.hpp"
namespace fggl::gui::renderer {
constexpr int PADDING = 15;
void draw_box(gfx::Path2D &path, glm::vec2 topLeft, glm::vec2 bottomRight) {
path.moveTo({topLeft.x, topLeft.y});
path.pathTo({bottomRight.x, topLeft.y});
path.pathTo({bottomRight.x, bottomRight.y});
path.pathTo({topLeft.x, bottomRight.y});
path.pathTo({topLeft.x, topLeft.y});
}
void draw_border_patch(gfx::Paint& paint, Box& bounds, Box& size, math::vec3 colour) {
gfx::Path2D path({0,0});
path.colour(colour);
// draw edges
draw_box(path, {bounds.left + size.left, bounds.top}, {bounds.right - size.right, bounds.top + size.top} );
draw_box(path, {bounds.right - size.right, bounds.top + size.top}, {bounds.right, bounds.bottom - size.bottom} );
draw_box(path, {bounds.left + size.left, bounds.bottom - size.bottom}, {bounds.right - size.right, bounds.bottom} );
draw_box(path, {bounds.left, bounds.top + size.top}, {bounds.left + size.left, bounds.bottom - size.bottom} );
// draw-corners
draw_box(path, {bounds.left, bounds.top}, {bounds.left + size.left, bounds.top + size.top} );
draw_box(path, {bounds.right - size.right, bounds.top}, {bounds.right, bounds.top + size.top} );
draw_box(path, {bounds.left, bounds.bottom - size.bottom}, {bounds.left + size.left, bounds.bottom} );
draw_box(path, {bounds.right - size.right, bounds.bottom - size.bottom}, {bounds.right, bounds.bottom});
paint.fill(path);
}
void draw_border_solid(gfx::Paint& paint, Box& bounds, Box& size, math::vec3 colour) {
gfx::Path2D path({0,0});
path.colour(colour);
// draw edges
draw_box(path, {bounds.left, bounds.top}, {bounds.right, bounds.top + size.top} );
draw_box(path, {bounds.right - size.right, bounds.top + size.top}, {bounds.right, bounds.bottom - size.bottom} );
draw_box(path, {bounds.left, bounds.bottom - size.bottom}, {bounds.right, bounds.bottom} );
draw_box(path, {bounds.left, bounds.top + size.top}, {bounds.left + size.left, bounds.bottom - size.bottom} );
paint.fill(path);
}
void draw_background_solid(gfx::Paint& paint, Box& bounds, math::vec3 colour) {
gfx::Path2D path({0,0});
path.colour(colour);
draw_box(path, {bounds.left, bounds.top}, {bounds.right, bounds.bottom} );
paint.fill(path);
}
void layout(model::Widget& current) {
if ( current.isLeaf() ) {
// if the widget has a defined size, use that
if ( current.hasAttr("size") && !current.hasAttr("text") ) {
return;
}
// else, use the model's preferred size
auto preferred = current.preferredSize();
if ( preferred.has_value() ) {
current.set<math::vec2>("size", preferred.value() );
}
} else {
auto topPad = current.get_or_default<float>("border:top") + current.get_or_default<float>("padding::top");
auto leftPad = current.get_or_default<float>("border::left") + current.get_or_default<float>("padding::left");
math::vec2 size = {topPad, leftPad};
// layout all children
for ( auto& child : current ) {
layout(child);
auto childSize = child.get_or_default<math::vec2>("size");
size.x = std::max( childSize.x, size.x );
size.y += childSize.y;
child.set<math::vec2>("position", {leftPad, size.y});
}
// set our size based on that
current.set<math::vec2>("size", size );
}
}
void visit(const model::Widget& root, gfx::Paint& paint, Box offset) {
// get border size
auto border = get_box(root, "border");
// calculate box bounds
auto pos = get_vec2(root, "position");
auto size = get_vec2(root, "size");
auto bounds = getBounds(pos, size);
bounds.top += offset.top;
bounds.left += offset.left;
// deal with right hand size bounds
//bounds.right = std::min( size.x, offset.width() );
//bounds.right += offset.left;
// deal with bottom bounds
//bounds.bottom = std::min( size.y, offset.height() );
//bounds.bottom += offset.top;
auto background = bounds.trim(border);
draw_background_solid(paint, background, get_vec3_rgb(root, "colour"));
draw_border_patch(paint, bounds, border, get_vec3_rgb(root, "border::colour"));
auto padding = get_box(root, "padding");
background = background.trim(padding);
if ( root.hasAttr("text") ) {
auto text = root.get<std::string>("text");
paint.text(text, {background.left, background.top + PADDING});
}
for (const auto& child : root) {
visit(child, paint, background);
}
}
} // namespace fggl::gui:;renderer
\ No newline at end of file
......@@ -20,9 +20,9 @@
namespace fggl::gui {
void buttonBorder(gfx::Path2D &path, glm::vec2 pos, glm::vec2 size) {
void button_border(gfx::Path2D &path, glm::vec2 pos, glm::vec2 size) {
// outer box
path.colour({1.0f, 0.0f, 0.0f});
path.colour({1.0F, 0.0F, 0.0F});
path.pathTo({pos.x + size.x, pos.y});
path.pathTo({pos.x + size.x, pos.y + size.y});
path.pathTo({pos.x, pos.y + size.y});
......@@ -32,7 +32,7 @@ namespace fggl::gui {
math::vec2 innerTop{pos.x + 5, pos.y + 5};
math::vec2 innerBottom{pos.x + size.x - 5, pos.y + size.y - 5};
path.colour({1.0f, 1.0f, 0.0f});
path.colour({1.0F, 1.0F, 0.0F});
path.moveTo({innerTop.x, innerTop.y});
path.pathTo({innerBottom.x, innerTop.y});
path.pathTo({innerBottom.x, innerBottom.y});
......@@ -52,7 +52,7 @@ namespace fggl::gui {
const auto bottomRight{topLeft + size};
// background
path.colour({0.5f, 0.5f, 0.5f});
path.colour({0.5F, 0.5F, 0.5F});
draw_box(path, topLeft, bottomRight);
// fill
......@@ -65,13 +65,13 @@ namespace fggl::gui {
innerBottom.x = innerTop.x + barWidth;
// draw the bar
path.colour({0.8f, 0.0f, 0.0f});
path.colour({0.8F, 0.0F, 0.0F});
draw_box(path, innerTop, innerBottom);
// part of the bar that's not filled in
math::vec2 emptyTop{innerBottom.x, innerTop.y};
math::vec2 emptyBottom{trueBottom, innerBottom.y};
path.colour({0.4f, 0.0f, 0.0f});
path.colour({0.4F, 0.0F, 0.0F});
draw_box(path, emptyTop, emptyBottom);
}
......@@ -90,7 +90,7 @@ namespace fggl::gui {
math::vec2 selectorTop{innerTop.x + selectorValue - (selectorWidth / 2), topLeft.y};
math::vec2 selectorBottom{selectorTop.x + selectorWidth, bottomRight.y};
path.colour({1.0f, 1.0f, 1.0f});
path.colour({1.0F, 1.0F, 1.0F});
draw_box(path, selectorTop, selectorBottom);
}
......@@ -101,18 +101,18 @@ namespace fggl::gui {
math::vec2 innerTop{pos.x + 5, pos.y + 5};
math::vec2 innerBottom{pos.x + size.x - 5, pos.y + size.y - 5};
math::vec3 baseColour{0.5f, 0.5f, 0.5f};
math::vec3 baseColour{0.5F, 0.5F, 0.5F};
if (active) {
baseColour *= 1.2f;
baseColour *= 1.2F;
}
if (pressed) {
baseColour *= 0.8f;
baseColour *= 0.8F;
}
math::vec3 lightColour{baseColour * 1.2f};
math::vec3 darkColour{baseColour * 0.8f};
math::vec3 lightColour{baseColour * 1.2F};
math::vec3 darkColour{baseColour * 0.8F};
if (pressed) {
// flip light and dark for selected buttons
auto tmp = darkColour;
......
......@@ -23,8 +23,7 @@
namespace fggl::gui {
Button::Button(math::vec2 pos, math::vec2 size) : Widget(pos, size), m_label(pos, size), m_hover(false),
m_active(false) {}
Button::Button(math::vec2 pos, math::vec2 size) : Widget(pos, size), m_label(pos, size), m_active(false) {}
void Button::render(gfx::Paint &paint) {
gfx::Path2D path{topLeft()};
......@@ -39,19 +38,11 @@ namespace fggl::gui {
if (m_active) {
for (auto &callback : m_callbacks) {
callback();
m_active = false;
}
m_active = false;
}
}
void Button::onEnter() {
m_hover = true;
}
void Button::onExit() {
m_hover = false;
}
void Button::addCallback(Callback cb) {
m_callbacks.push_back(cb);
}
......@@ -60,7 +51,11 @@ namespace fggl::gui {
m_label.text(value);
}
std::string Button::label() const {
void Button::layout() {
m_label.size(topLeft(), size());
}
auto Button::label() const -> std::string {
return m_label.text();
}
......
......@@ -27,10 +27,10 @@ namespace fggl::input {
// see https://asliceofrendering.com/camera/2019/11/30/ArcballCamera/
auto &camTransform = ecs.get<fggl::math::Transform>(cam);
auto &camComp = ecs.get<fggl::gfx::Camera>(cam);
auto &mouse = input.mouse;
const auto &mouse = input.mouse;
glm::vec4 position(camTransform.origin(), 1.0f);
glm::vec4 pivot(camComp.target, 1.0f);
glm::vec4 position(camTransform.origin(), 1.0F);
glm::vec4 pivot(camComp.target, 1.0F);
glm::mat4 view = glm::lookAt(camTransform.origin(), camComp.target, camTransform.up());
glm::vec3 viewDir = -glm::transpose(view)[2];
glm::vec3 rightDir = glm::transpose(view)[0];
......@@ -41,12 +41,12 @@ namespace fggl::input {
float yAngle = (-mouse.axisDelta(fggl::input::MouseAxis::Y)) * deltaAngleY;
// rotate the camera around the pivot on the first axis
glm::mat4x4 rotationMatrixX(1.0f);
glm::mat4x4 rotationMatrixX(1.0F);
rotationMatrixX = glm::rotate(rotationMatrixX, xAngle, fggl::math::UP);
position = (rotationMatrixX * (position - pivot)) + pivot;
// rotate the camera aroud the pivot on the second axis
glm::mat4x4 rotationMatrixY(1.0f);
// rotate the camera around the pivot on the second axis
glm::mat4x4 rotationMatrixY(1.0F);
rotationMatrixY = glm::rotate(rotationMatrixY, yAngle, rightDir);
glm::vec3 finalPos = (rotationMatrixY * (position - pivot)) + pivot;
......@@ -66,17 +66,17 @@ namespace fggl::input {
glm::vec3 motion(0.0F);
float delta = input.mouse.axis(fggl::input::MouseAxis::SCROLL_Y);
if ((glm::length(dir) < maxZoom && delta < 0.0f) || (glm::length(dir) > minZoom && delta > 0.0f)) {
if ((glm::length(dir) < maxZoom && delta < 0.0F) || (glm::length(dir) > minZoom && delta > 0.0F)) {
motion -= (forward * delta);
camTransform.origin(camTransform.origin() + motion);
}
}
void process_freecam(entity::EntityManager &ecs, const Input &input, entity::EntityID cam) {
float rotationValue = 0.0f;
glm::vec3 translation(0.0f);
float rotationValue = 0.0F;
glm::vec3 translation(0.0F);
auto &keyboard = input.keyboard;
const auto &keyboard = input.keyboard;
auto &settings = ecs.get<FreeCamKeys>(cam);
// calculate rotation (user input)
......@@ -107,24 +107,24 @@ namespace fggl::input {
auto camTransform = ecs.get<fggl::math::Transform>(cam);
auto camComp = ecs.get<fggl::gfx::Camera>(cam);
glm::vec4 position(camTransform.origin(), 1.0f);
glm::vec4 pivot(camComp.target, 1.0f);
glm::vec4 position(camTransform.origin(), 1.0F);
glm::vec4 pivot(camComp.target, 1.0F);
// apply movement
if (translation != glm::vec3(0.0f)) {
if (translation != glm::vec3(0.0F)) {
const auto rotation = (position - pivot);
const float angle = atan2f(rotation.x, rotation.z);
const auto rotationMat = glm::rotate(MAT_IDENTITY, angle, fggl::math::UP);
auto deltaMove = (rotationMat * glm::vec4(translation, 1.0f)) * PAN_SPEED;
deltaMove.w = 0.0f;
auto deltaMove = (rotationMat * glm::vec4(translation, 1.0F)) * PAN_SPEED;
deltaMove.w = 0.0F;
position += deltaMove;
pivot += deltaMove;
}
// apply rotation
if (rotationValue != 0.0f) {
if (rotationValue != 0.0F) {
glm::mat4 rotation = glm::rotate(MAT_IDENTITY, rotationValue, fggl::math::UP);
position = (rotation * (position - pivot)) + pivot;
}
......@@ -134,24 +134,24 @@ namespace fggl::input {
}
void process_edgescroll(entity::EntityManager &ecs, const Input &input, entity::EntityID cam) {
glm::vec3 translation(0.0f);
glm::vec3 translation(0.0F);
auto &mouse = input.mouse;
const auto &mouse = input.mouse;
// calculate movement (user input)
if (mouse.axis(MouseAxis::Y) < 0.9f) {
if (mouse.axis(MouseAxis::Y) < 0.9F) {
translation -= fggl::math::RIGHT;
}
if (mouse.axis(MouseAxis::Y) > -0.9f) {
if (mouse.axis(MouseAxis::Y) > -0.9F) {
translation += fggl::math::RIGHT;
}
if (mouse.axis(MouseAxis::X) > -0.9f) {
if (mouse.axis(MouseAxis::X) > -0.9F) {
translation += fggl::math::FORWARD;
}
if (mouse.axis(MouseAxis::X) < 0.9f) {
if (mouse.axis(MouseAxis::X) < 0.9F) {
translation -= fggl::math::FORWARD;
}
......@@ -159,17 +159,17 @@ namespace fggl::input {
auto &camTransform = ecs.get<fggl::math::Transform>(cam);
auto &camComp = ecs.get<fggl::gfx::Camera>(cam);
glm::vec4 position(camTransform.origin(), 1.0f);
glm::vec4 pivot(camComp.target, 1.0f);
glm::vec4 position(camTransform.origin(), 1.0F);
glm::vec4 pivot(camComp.target, 1.0F);
// apply movement
if (translation != glm::vec3(0.0f)) {
if (translation != glm::vec3(0.0F)) {
const auto rotation = (position - pivot);
const float angle = atan2f(rotation.x, rotation.z);
const auto rotationMat = glm::rotate(MAT_IDENTITY, angle, fggl::math::UP);
auto deltaMove = (rotationMat * glm::vec4(translation, 1.0f)) * PAN_SPEED;
deltaMove.w = 0.0f;
auto deltaMove = (rotationMat * glm::vec4(translation, 1.0F)) * PAN_SPEED;
deltaMove.w = 0.0F;
position += deltaMove;
pivot += deltaMove;
......
......@@ -22,22 +22,12 @@ namespace fggl::math::phs3d {
max = {-FLT_MAX, -FLT_MAX, -FLT_MAX};
}
void AABB::add(const math::vec3 &p) {
if (p.x < min.x)
min.x = p.x;
if (p.x > max.x)
max.x = p.x;
if (p.y < min.y)
min.y = p.y;
if (p.y > min.y)
max.y = p.y;
if (p.z < min.z)
min.z = p.z;
if (p.z > max.z)
max.z = p.z;
void AABB::add(const math::vec3 &point) {
min = minElm(min, point);
max = maxElm(max, point);
}
AABB AABB::fromPoints(const std::vector<math::vec3> &points) {
auto AABB::fromPoints(const std::vector<math::vec3> &points) -> AABB {
AABB box;
for (const auto &point : points) {
box.add(point);
......@@ -52,7 +42,7 @@ namespace fggl::math::phs3d {
// 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) {
if (m[i][j] > 0.0F) {
min[j] += m[i][j] * other.min[j];
max[j] += m[i][j] * other.max[j];
} else {
......@@ -63,7 +53,7 @@ namespace fggl::math::phs3d {
}
}
Plane Plane::fromPoints(const math::vec3 p1, const math::vec3 p2, const math::vec3 p3) {
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));
......@@ -71,7 +61,7 @@ namespace fggl::math::phs3d {
return {normal, d};
}
static math::vec3 bestFitNormal(const std::vector<math::vec3> &points) {
static auto bestFitNormal(const std::vector<math::vec3> &points) -> math::vec3 {
assert(!points.empty());
math::vec3 result;
......@@ -90,9 +80,9 @@ namespace fggl::math::phs3d {
return glm::normalize(result);
};
static float bestFitD(const std::vector<math::vec3> &points, glm::vec3 normal) {
static auto bestFitD(const std::vector<math::vec3> &points, glm::vec3 normal) -> float {
math::vec3 sum;
for (auto &point : points) {
for (const auto &point : points) {
sum += point;
}
sum *= 1.0F / points.size();
......@@ -108,7 +98,7 @@ namespace fggl::math::phs3d {
const char b;
};
static bary_axis baryCalcAxis(const math::vec3 &normal) {
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};
......@@ -121,7 +111,7 @@ namespace fggl::math::phs3d {
}
}
bool Triangle::CartToBarycentric(const math::vec3 &cart, Barycentric &outVal) {
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];
......@@ -144,19 +134,19 @@ namespace fggl::math::phs3d {
const float v4 = cart[ax.b] - v[2][ax.b];
const float denom = v1 * u2 - v2 * u1;
if (denom == 0.0f) {
if (denom == 0.0F) {
return false;
}
// finally, we can work it out
const float oneOverDenom = 1.0f / denom;
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];
outVal.b[2] = 1.0F - outVal.b[0] - outVal.b[1];
return true;
}
bool Triangle::CartToBarycentric2(const math::vec3 &cart, Barycentric &outVal) {
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];
......@@ -167,7 +157,7 @@ namespace fggl::math::phs3d {
const auto normal = glm::normalize(glm::cross(e1, e2));
const auto denom = glm::dot(glm::cross(e1, e2), normal);
assert(denom != 0.0f);
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;
......
......@@ -13,7 +13,6 @@
*/
#include "fggl/math/triangulation.hpp"
#include <iostream>
namespace fggl::math {
......@@ -29,7 +28,7 @@ namespace fggl::math {
// deal with the indices
const auto nTris = polygon.size() - 2;
for (auto i = 0u; i < nTris; i++) {
for (auto i = 0U; i < nTris; i++) {
mesh.add_index(firstIdx);
mesh.add_index(prevIdx);
......
......@@ -20,7 +20,7 @@
namespace fggl::phys {
bool NullPhysics::factory(modules::ModuleService serviceName, modules::Services &serviceManager) {
auto NullPhysics::factory(modules::ServiceName serviceName, modules::Services &serviceManager) -> bool {
if (serviceName == phys::PhysicsProvider::service) {
serviceManager.bind<phys::PhysicsProvider, NullPhysicsProvider>();
return true;
......
......@@ -25,34 +25,36 @@
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};
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};
}
return {fallback};
}
static std::vector<std::filesystem::path> get_path_list(const char *env, const char *folderName) {
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();
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;
}
std::string path = pathListStr.substr(pos, nextPos - pos);
paths.push_back(std::filesystem::path(path) / folderName);
pos = nextPos + 1;
}
return paths;
}
return paths;
}
EnginePaths calc_engine_paths(const char *base) {
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) {
......@@ -76,7 +78,7 @@ namespace fggl::platform {
};
}
std::filesystem::path locate_data(const EnginePaths &paths, const std::filesystem::path &relPath) {
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;
......@@ -98,11 +100,11 @@ namespace fggl::platform {
return debugPath;
}
// if the file existed, it shoudl exist in the user space
// 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) {
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;
......@@ -120,7 +122,7 @@ namespace fggl::platform {
return userPath;
}
std::filesystem::path locate_cache(const EnginePaths &paths, const std::filesystem::path &relPath) {
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;
......
......@@ -28,7 +28,7 @@ namespace fggl::scenes {
m_input = app.service<input::Input>();
}
void GameBase::update(float dt) {
void GameBase::update(float /*dt*/) {
// detect the user quitting
if (m_input != nullptr) {
bool escapePressed = m_input->keyboard.pressed(glfwGetKeyScancode(GLFW_KEY_ESCAPE));
......@@ -59,7 +59,7 @@ namespace fggl::scenes {
m_world.reset();
}
void Game::update(float dt) {
void Game::update(float /*dt*/) {
assert(m_world && "called game update, but there was no world - was activate called?");
if (m_input != nullptr) {
......@@ -67,18 +67,23 @@ namespace fggl::scenes {
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);
gfx.drawScene(*m_world, m_debug);
}
}
......
......@@ -22,39 +22,27 @@ namespace fggl::scenes {
using fggl::input::MouseButton;
using fggl::input::MouseAxis;
BasicMenu::BasicMenu(fggl::App &app) : AppState(app), m_inputs(nullptr), m_active(), m_hover(nullptr) {
m_inputs = app.service<input::Input>();
constexpr float SCREEN_WIDTH = 1920.0F;
constexpr float SCREEN_HEIGHT = 1080.0F;
BasicMenu::BasicMenu(fggl::App &app) : AppState(app), m_inputs(app.service<input::Input>()), m_active(), m_cursorPos(), m_hover(nullptr) {
}
void BasicMenu::update(float dt) {
void BasicMenu::update(float /*dt*/) {
if (m_inputs != nullptr) {
m_cursorPos.x = m_inputs->mouse.axis(MouseAxis::X);
m_cursorPos.y = m_inputs->mouse.axis(MouseAxis::Y);
// in canvas space
math::vec2 projected;
projected.x = math::rescale_ndc(m_cursorPos.x, 0, 1920.f);
//projected.y = math::rescale_ndc(m_cursorPos.y, 1080.0f, 0);
projected.y = math::rescale_ndc(m_cursorPos.y, 0, 1080.0f);
auto *hoverWidget = m_canvas.getChildAt(projected);
if (hoverWidget != m_hover) {
if (m_hover != nullptr) {
m_hover->onExit();
}
m_hover = hoverWidget;
if (m_hover != nullptr) {
m_hover->onEnter();
}
}
projected.x = math::rescale_ndc(m_cursorPos.x, 0, SCREEN_WIDTH);
projected.y = math::rescale_ndc(m_cursorPos.y, 0, SCREEN_HEIGHT);
m_canvas.onMouseOver(projected);
if (m_inputs->mouse.pressed(MouseButton::LEFT)) {
spdlog::info("clicky clicky: ({}, {})", projected.x, projected.y);
auto widget = m_canvas.getChildAt(projected);
auto* widget = m_canvas.getChildAt(projected);
if (widget != nullptr) {
widget->activate();
spdlog::info("ooo! there is a thing there!");
}
}
}
......@@ -75,25 +63,23 @@ namespace fggl::scenes {
}
void BasicMenu::add(const std::string &name, callback cb) {
m_items[name] = cb;
void BasicMenu::add(const std::string &name, const Callback& callback) {
m_items[name] = callback;
const math::vec2 btnSize{150.0f, 30.0f};
const math::vec2 btnSize{150.0F, 30.0F};
const float spacing = 5;
const float padX = 50.0f;
const float padY = 50.0f;
const float padX = 50.0F;
const float padY = 50.0F;
// figure out the position based off the old logic
// FIXME should be the container's job
math::vec2 pos{1920.0f - (padX + btnSize.x), padY};
auto btnIdx = m_items.size() - 1;
pos.y += (btnIdx * (btnSize.y + spacing));
math::vec2 pos{SCREEN_WIDTH - (padX + btnSize.x), padY};
pos.y += ( (m_items.size()-1.0F) * (btnSize.y + spacing));
// build the button
auto btn = std::make_unique<gui::Button>(pos, btnSize);
btn->label(name);
btn->addCallback(cb);
btn->addCallback(callback);
m_canvas.add(std::move(btn));
}
......
source diff could not be displayed: it is too large. Options to address this: view the blob.
......@@ -27,7 +27,7 @@ namespace fggl::util {
std::map<GUID, std::string> guidTable;
}
GUID internString(const char *str) {
auto intern_string(const char *str) -> GUID {
assert(str != nullptr);
GUID guid = make_guid(str);
......@@ -40,7 +40,7 @@ namespace fggl::util {
return guid;
}
std::string guidToString(GUID guid) {
auto guid_to_string(GUID guid) -> std::string {
auto tableValue = guidTable.find(guid);
if (tableValue != guidTable.end()) {
return tableValue->second;
......@@ -51,12 +51,12 @@ namespace fggl::util {
}
fggl::util::GUID operator "" _fid(const char *str) {
fggl::util::internString(str);
auto operator "" _fid(const char *str) -> fggl::util::GUID {
fggl::util::intern_string(str);
return fggl::util::make_guid(str);
}
fggl::util::GUID operator "" _fid(const char *str, std::size_t) {
fggl::util::internString(str);
auto operator "" _fid(const char *str, std::size_t) -> fggl::util::GUID {
fggl::util::intern_string(str);
return fggl::util::make_guid(str);
}