Skip to content

Commit

Permalink
Upgrade App.
Browse files Browse the repository at this point in the history
- Add `set_window_icon()`.
- Add `get_features()`.
- [DesktopApp] Add `DisplayMode`.
  • Loading branch information
karnkaul committed Jan 26, 2024
1 parent 923fcfc commit 65ce06a
Show file tree
Hide file tree
Showing 10 changed files with 102 additions and 14 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

set(project_prefix bave)
project(${project_prefix} VERSION 0.2.0)
project(${project_prefix} VERSION 0.3.0)

set(is_root_project FALSE)

Expand Down
2 changes: 1 addition & 1 deletion example/desktop/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ auto main(int argc, char** argv) -> int {
auto const create_info = bave::DesktopApp::CreateInfo{
.args = bave::make_args(argc, argv),
.title = "BaveExample",
.extent = {720, 1280},
.mode = bave::Windowed{.extent = {720, 1280}},
.assets_patterns = "assets,example/assets",
};

Expand Down
15 changes: 15 additions & 0 deletions lib/include/bave/app.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,16 @@ enum struct ErrCode : int { eSuccess = 0, eFailure = 1 };

class App : public PolyPinned {
public:
struct Feature {
static constexpr std::size_t resizeable{0};
static constexpr std::size_t has_title{1};
static constexpr std::size_t has_icon{2};
static constexpr std::size_t validation_layers{3};

static constexpr std::size_t count_v{8};
};
using FeatureFlags = std::bitset<Feature::count_v>;

using Bootloader = std::function<std::unique_ptr<class Driver>(App&)>;

explicit App(std::string tag = "App");
Expand All @@ -38,6 +48,9 @@ class App : public PolyPinned {

auto set_window_size(glm::ivec2 size) -> bool { return do_set_window_size(size); }
auto set_framebuffer_size(glm::ivec2 size) -> bool;
auto set_window_icon(std::span<BitmapView const> bitmaps) -> bool { return do_set_window_icon(bitmaps); }

[[nodiscard]] auto get_features() const -> FeatureFlags;

[[nodiscard]] auto get_data_store() const -> DataStore& { return *m_data_store; }
[[nodiscard]] auto get_render_device() const -> RenderDevice& { return do_get_render_device(); }
Expand Down Expand Up @@ -83,6 +96,7 @@ class App : public PolyPinned {

virtual void do_shutdown() = 0;

[[nodiscard]] virtual auto do_get_native_features() const -> FeatureFlags { return {}; }
[[nodiscard]] virtual auto do_get_window_size() const -> glm::ivec2 { return do_get_framebuffer_size(); }
[[nodiscard]] virtual auto do_get_framebuffer_size() const -> glm::ivec2 = 0;

Expand All @@ -92,6 +106,7 @@ class App : public PolyPinned {

virtual auto do_set_window_size(glm::ivec2 size) -> bool = 0;
virtual auto do_set_title(CString /*title*/) -> bool { return false; }
virtual auto do_set_window_icon(std::span<BitmapView const> /*bitmaps*/) -> bool { return false; }

void pre_tick();

Expand Down
17 changes: 17 additions & 0 deletions lib/include/bave/core/make_bitset.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#pragma once
#include <bitset>

namespace bave {
///! Create a std::bitset with bits set.
template <std::size_t Size, std::convertible_to<std::size_t>... I>
constexpr auto make_bitset(I const... bits) -> std::bitset<Size> {
auto ret = std::bitset<Size>{};
(ret.set(bits), ...);
return ret;
}
///! Create a std::bitset with bits set.
template <typename Ret, std::convertible_to<std::size_t>... I>
constexpr auto make_bitset(I const... bits) -> Ret {
return make_bitset<Ret{}.size()>(bits...);
}
} // namespace bave
15 changes: 13 additions & 2 deletions lib/include/bave/desktop_app.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,23 @@ struct GLFWwindow;
namespace bave {
[[nodiscard]] constexpr auto make_args(int argc, char const* const* argv) -> std::span<char const* const> { return {argv, static_cast<size_t>(argc)}; }

struct Windowed {
glm::ivec2 extent{1280, 720};
bool lock_aspect_ratio{true};
bool decoration{true};
};

struct BorderlessFullscreen {};

using DisplayMode = std::variant<Windowed, BorderlessFullscreen>;

class DesktopApp : public App, public detail::IWsi {
public:
struct CreateInfo {
std::span<char const* const> args{};
CString title{"BaveApp"};
glm::ivec2 extent{1280, 720};
DisplayMode mode{Windowed{}};
std::function<Gpu(std::span<Gpu const>)> select_gpu{};
bool lock_aspect_ratio{true};
std::string_view assets_patterns{"assets"};
bool validation_layers{debug_v};
};
Expand Down Expand Up @@ -58,6 +67,7 @@ class DesktopApp : public App, public detail::IWsi {

void do_shutdown() final;

[[nodiscard]] auto do_get_native_features() const -> FeatureFlags final;
[[nodiscard]] auto do_get_window_size() const -> glm::ivec2 final;
[[nodiscard]] auto do_get_framebuffer_size() const -> glm::ivec2 final;

Expand All @@ -72,6 +82,7 @@ class DesktopApp : public App, public detail::IWsi {

auto do_set_window_size(glm::ivec2 size) -> bool final;
auto do_set_title(CString title) -> bool final;
auto do_set_window_icon(std::span<BitmapView const> bitmaps) -> bool final;

void init_data_store();
void make_window();
Expand Down
2 changes: 2 additions & 0 deletions lib/include/bave/graphics/render_device.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ class RenderDevice {

explicit RenderDevice(NotNull<detail::IWsi*> wsi, CreateInfo create_info = {});

[[nodiscard]] auto validation_layers_enabled() const -> bool { return !!m_debug_messenger; }

[[nodiscard]] auto get_instance() const -> vk::Instance { return *m_instance; }
[[nodiscard]] auto get_surface() const -> vk::SurfaceKHR { return *m_surface; }
[[nodiscard]] auto get_gpu() const -> Gpu const& { return m_gpu; }
Expand Down
8 changes: 3 additions & 5 deletions lib/include/bave/input/mods.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#pragma once
#include <bitset>
#include <bave/core/make_bitset.hpp>

namespace bave {
namespace mod {
Expand All @@ -10,7 +10,7 @@ constexpr size_t alt{3};
constexpr size_t super{4};
constexpr size_t capslock{5};
constexpr size_t numlock{6};
constexpr size_t count_v{numlock};
constexpr size_t count_v{numlock + 1};
}; // namespace mod

///
Expand All @@ -21,8 +21,6 @@ using KeyMods = std::bitset<mod::count_v>;
///! Create KeyMods with mods set.
template <std::convertible_to<std::size_t>... I>
constexpr auto make_key_mods(I const... mods) -> KeyMods {
auto ret = KeyMods{};
(ret.set(mods), ...);
return ret;
return make_bitset<KeyMods>(mods...);
}
} // namespace bave
46 changes: 43 additions & 3 deletions lib/platform/desktop/desktop_app.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <GLFW/glfw3.h>

#include <bave/core/error.hpp>
#include <bave/core/visitor.hpp>
#include <bave/desktop_app.hpp>
#include <bave/file_io.hpp>
#include <platform/desktop/clap/clap.hpp>
Expand Down Expand Up @@ -189,6 +190,10 @@ void DesktopApp::render() {

void DesktopApp::do_shutdown() { glfwSetWindowShouldClose(m_window.get(), GLFW_TRUE); }

auto DesktopApp::do_get_native_features() const -> FeatureFlags {
return make_bitset<FeatureFlags>(Feature::resizeable, Feature::has_title, Feature::has_icon);
}

auto DesktopApp::do_get_window_size() const -> glm::ivec2 {
auto ret = glm::ivec2{};
glfwGetWindowSize(m_window.get(), &ret.x, &ret.y);
Expand Down Expand Up @@ -244,6 +249,22 @@ auto DesktopApp::do_set_title(CString title) -> bool {
return true;
}

auto DesktopApp::do_set_window_icon(std::span<BitmapView const> bitmaps) -> bool {
auto images = std::vector<GLFWimage>{};
images.reserve(bitmaps.size());
for (auto const& bitmap : bitmaps) {
if (bitmap.bytes.empty()) { continue; }
auto image = GLFWimage{
.width = bitmap.extent.x,
.height = bitmap.extent.y,
.pixels = reinterpret_cast<unsigned char*>(const_cast<std::byte*>(bitmap.bytes.data())), // NOLINT
};
images.push_back(image);
}
glfwSetWindowIcon(m_window.get(), static_cast<int>(images.size()), images.data());
return true;
}

auto DesktopApp::self(Ptr<GLFWwindow> window) -> DesktopApp& {
auto* ret = static_cast<DesktopApp*>(glfwGetWindowUserPointer(window));
if (ret == nullptr) { throw Error{"Dereferencing null GLFW Window User Pointer"}; }
Expand All @@ -265,14 +286,33 @@ void DesktopApp::init_data_store() {
void DesktopApp::make_window() {
if (glfwVulkanSupported() == GLFW_FALSE) { throw Error{"Vulkan not supported"}; }

auto display_mode = m_create_info.mode;
Ptr<GLFWmonitor> primary_monitor = glfwGetPrimaryMonitor();
Ptr<GLFWvidmode const> video_mode = glfwGetVideoMode(primary_monitor);
if (video_mode == nullptr && std::holds_alternative<BorderlessFullscreen>(display_mode)) { display_mode = Windowed{.extent = {1280, 720}}; }

glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
auto* window = glfwCreateWindow(m_create_info.extent.x, m_create_info.extent.y, m_create_info.title.c_str(), nullptr, nullptr);
auto create_window = Visitor{
[&](BorderlessFullscreen const&) {
glfwWindowHint(GLFW_RED_BITS, video_mode->redBits);
glfwWindowHint(GLFW_GREEN_BITS, video_mode->greenBits);
glfwWindowHint(GLFW_BLUE_BITS, video_mode->blueBits);
glfwWindowHint(GLFW_REFRESH_RATE, video_mode->refreshRate);
return glfwCreateWindow(video_mode->width, video_mode->height, m_create_info.title.c_str(), primary_monitor, nullptr);
},
[&](Windowed const& w) {
if (!w.decoration) { glfwWindowHint(GLFW_DECORATED, GLFW_FALSE); }
auto* ret = glfwCreateWindow(w.extent.x, w.extent.y, m_create_info.title.c_str(), nullptr, nullptr);
if (w.lock_aspect_ratio) { glfwSetWindowAspectRatio(ret, w.extent.x, w.extent.y); }
return ret;
},
};

auto* window = std::visit(create_window, m_create_info.mode);
m_window = std::unique_ptr<GLFWwindow, Glfw::Deleter>{window};
if (m_window == nullptr) { throw Error{"Failed to create Window"}; }
glfwSetWindowUserPointer(m_window.get(), this);

if (m_create_info.lock_aspect_ratio) { glfwSetWindowAspectRatio(m_window.get(), m_create_info.extent.x, m_create_info.extent.y); }

glfwSetWindowCloseCallback(m_window.get(), [](Ptr<GLFWwindow> window) { self(window).shutdown(); });
glfwSetWindowFocusCallback(m_window.get(), [](Ptr<GLFWwindow> window, int v) { push(window, FocusChange{.in_focus = v == GLFW_TRUE}); });
glfwSetWindowSizeCallback(m_window.get(), [](Ptr<GLFWwindow> window, int x, int y) { push(window, WindowResize{.extent = {x, y}}); });
Expand Down
6 changes: 6 additions & 0 deletions lib/src/app.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,12 @@ auto App::set_framebuffer_size(glm::ivec2 const size) -> bool {
return do_set_window_size(w_size);
}

auto App::get_features() const -> FeatureFlags {
auto ret = do_get_native_features();
if (get_render_device().validation_layers_enabled()) { ret.set(Feature::validation_layers); }
return ret;
}

auto App::get_display_ratio() const -> glm::vec2 {
auto const w_size = get_window_size();
auto const f_size = get_framebuffer_size();
Expand Down
3 changes: 1 addition & 2 deletions tools/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ auto main(int argc, char** argv) -> int {
auto const daci = bave::DesktopApp::CreateInfo{
.args = bave::make_args(argc, argv),
.title = "Bave Tools",
.extent = Applet::window_size_v,
.lock_aspect_ratio = false,
.mode = bave::Windowed{.extent = Applet::window_size_v, .lock_aspect_ratio = false},
.assets_patterns = "assets,example/assets",
};
auto app = bave::DesktopApp{daci};
Expand Down

0 comments on commit 65ce06a

Please sign in to comment.