Skip to content

Commit

Permalink
Add EnumFlags, replace all raw bitsets.
Browse files Browse the repository at this point in the history
  • Loading branch information
karnkaul committed Feb 1, 2024
1 parent 4f220f2 commit 1fab6d6
Show file tree
Hide file tree
Showing 12 changed files with 70 additions and 79 deletions.
4 changes: 2 additions & 2 deletions lib/docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
- Added bave::Gamepad support, queried through bave::App::get_gamepad() and bave::App::get_gamepads().
- Not yet supported on Android.
- Added bave::KeyState and bave::App::get_key_state().
- Added bave::EnumFlags.

### Changes

- Replaced `bave::mod::*` with bave::Mod.
- Refactored bave::ParticleEmitter::Modifier into an enum.
- Unified all bit flags to be bave::EnumFlags.
15 changes: 7 additions & 8 deletions lib/include/bave/app.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,15 @@ enum struct ErrCode : int { eSuccess = EXIT_SUCCESS, eFailure = EXIT_FAILURE };
class App : public PolyPinned {
public:
/// \brief Individual feature flags.
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};
enum class Feature : int {
eResizeable,
eHasTitle,
eHasIcon,
eValidationLayers,
eCOUNT_,
};
/// \brief Bitset of feature flags.
using FeatureFlags = std::bitset<Feature::count_v>;
using FeatureFlags = EnumFlags<Feature>;

/// \brief Driver Factory.
using Bootloader = std::function<std::unique_ptr<class Driver>(App&)>;
Expand Down
33 changes: 33 additions & 0 deletions lib/include/bave/core/enum_flags.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#pragma once
#include <bave/core/enum_t.hpp>
#include <bitset>

namespace bave {
/// \brief Enum-indexed wrapper around std::bitset.
template <EnumT E, std::size_t Size = std::size_t(E::eCOUNT_)>
class EnumFlags : public std::bitset<Size> {
public:
using std::bitset<Size>::bitset;

/// \brief Constructor taking multiple flags.
/// \param to_set flags to set.
template <std::same_as<E>... T>
EnumFlags(T const... to_set) {
(this->set(to_set), ...);
}

/// \brief Test if a flag is set.
/// \param e Flag to test for.
/// \returns true if set.
[[nodiscard]] auto test(E const e) const -> bool { return std::bitset<Size>::test(static_cast<std::size_t>(e)); }
/// \brief Set a flag.
/// \param e Flag to set.
void set(E const e) { std::bitset<Size>::set(static_cast<std::size_t>(e)); }
/// \brief Reset a flag.
/// \param e Flag to reset.
void reset(E const e) { std::bitset<Size>::reset(static_cast<std::size_t>(e)); }

[[nodiscard]] auto operator[](E const e) -> decltype(auto) { return std::bitset<Size>::operator[](static_cast<std::size_t>(e)); }
[[nodiscard]] auto operator[](E const e) const -> decltype(auto) { return std::bitset<Size>::operator[](static_cast<std::size_t>(e)); }
};
} // namespace bave
31 changes: 0 additions & 31 deletions lib/include/bave/core/make_bitset.hpp

This file was deleted.

6 changes: 3 additions & 3 deletions lib/include/bave/graphics/particle_emitter.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#pragma once
#include <bave/core/enum_flags.hpp>
#include <bave/core/inclusive_range.hpp>
#include <bave/core/make_bitset.hpp>
#include <bave/core/time.hpp>
#include <bave/graphics/shape.hpp>

Expand Down Expand Up @@ -35,9 +35,9 @@ struct ParticleConfig {
class ParticleEmitter : public QuadShape {
public:
enum class Modifier : int { eTranslate, eRotate, eScale, eTint, eCOUNT_ };
using Modifiers = std::bitset<static_cast<std::size_t>(Modifier::eCOUNT_)>;
using Modifiers = EnumFlags<Modifier>;

inline static auto const all_modifiers_v = make_bitset<Modifiers>(Modifier::eTranslate, Modifier::eRotate, Modifier::eScale, Modifier::eTint);
inline static auto const all_modifiers_v = Modifiers{Modifier::eTranslate, Modifier::eRotate, Modifier::eScale, Modifier::eTint};

using Config = ParticleConfig;

Expand Down
6 changes: 3 additions & 3 deletions lib/include/bave/input/gamepad.hpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#pragma once
#include <bave/core/c_string.hpp>
#include <bave/core/enum_flags.hpp>
#include <bave/input/action.hpp>
#include <array>
#include <bitset>

namespace bave {
/// \brief Set of gamepad IDs.
Expand Down Expand Up @@ -66,7 +66,7 @@ struct Gamepad {
/// \brief ID of gamepad.
Id id{};
/// \brief Button states.
std::bitset<buttons_v> button_states{};
EnumFlags<Button> button_states{};
/// \brief Axis values.
std::array<float, axes_v> axes{};
/// \brief Reported name of gamepad.
Expand All @@ -77,7 +77,7 @@ struct Gamepad {
/// \brief Check if a button is pressed.
/// \param button Button to test for.
/// \returns true if pressed.
[[nodiscard]] auto is_pressed(Button const button) const -> bool { return button_states.test(static_cast<std::size_t>(button)); }
[[nodiscard]] auto is_pressed(Button const button) const -> bool { return button_states.test(button); }

/// \brief Obtain an axis value.
/// \param axis Axis to obtain value of.
Expand Down
8 changes: 4 additions & 4 deletions lib/include/bave/input/key_state.hpp
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
#pragma once
#include <bave/core/enum_flags.hpp>
#include <bave/input/key.hpp>
#include <bitset>

namespace bave {
/// \brief Stateful wrapper for keys held down over multiple frames.
struct KeyState {
static constexpr auto max_keys_v = static_cast<std::size_t>(Key::eCOUNT_);

std::bitset<max_keys_v> held_keys{};
EnumFlags<Key> held_keys{};

/// \brief Check if a key is held down (pressed).
/// \brief Check if a key is pressed (held down).
/// \param key The key to check for.
/// \returns true if key has been pressed but not yet released.
/// \pre key must be non-negative and less than Key::eCOUNT_.
[[nodiscard]] auto is_held(Key const key) const -> bool { return held_keys.test(static_cast<std::size_t>(key)); }
[[nodiscard]] auto is_pressed(Key const key) const -> bool { return held_keys.test(key); }
};
} // namespace bave
12 changes: 2 additions & 10 deletions lib/include/bave/input/mods.hpp
Original file line number Diff line number Diff line change
@@ -1,17 +1,9 @@
#pragma once
#include <bave/core/make_bitset.hpp>
#include <bave/core/enum_flags.hpp>

namespace bave {
enum class Mod : int { eShift, eCtrl, eAlt, eSuper, eCapsLock, eNumLock, eCOUNT_ };

/// \brief Bit flags for modifier keys.
using KeyMods = std::bitset<static_cast<std::size_t>(Mod::eCOUNT_)>;

/// \brief Create KeyMods with mods set.
/// \param mods mods to set.
/// \returns KeyMods with mods set.
template <std::same_as<Mod>... I>
auto make_key_mods(I const... mods) -> KeyMods {
return make_bitset<KeyMods>(mods...);
}
using KeyMods = EnumFlags<Mod>;
} // namespace bave
20 changes: 9 additions & 11 deletions lib/platform/desktop/desktop_app.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,13 +111,13 @@ constexpr auto to_action(int const glfw_action) {

constexpr auto to_mods(int const glfw_mods) {
auto ret = KeyMods{};
if ((glfw_mods & GLFW_MOD_SHIFT) != 0) { ret.set(static_cast<std::size_t>(Mod::eShift)); }
if ((glfw_mods & GLFW_MOD_CONTROL) != 0) { ret.set(static_cast<std::size_t>(Mod::eCtrl)); }
if ((glfw_mods & GLFW_MOD_CONTROL) != 0) { ret.set(static_cast<std::size_t>(Mod::eCtrl)); }
if ((glfw_mods & GLFW_MOD_ALT) != 0) { ret.set(static_cast<std::size_t>(Mod::eAlt)); }
if ((glfw_mods & GLFW_MOD_SUPER) != 0) { ret.set(static_cast<std::size_t>(Mod::eSuper)); }
if ((glfw_mods & GLFW_MOD_CAPS_LOCK) != 0) { ret.set(static_cast<std::size_t>(Mod::eCapsLock)); }
if ((glfw_mods & GLFW_MOD_NUM_LOCK) != 0) { ret.set(static_cast<std::size_t>(Mod::eNumLock)); }
if ((glfw_mods & GLFW_MOD_SHIFT) != 0) { ret.set(Mod::eShift); }
if ((glfw_mods & GLFW_MOD_CONTROL) != 0) { ret.set(Mod::eCtrl); }
if ((glfw_mods & GLFW_MOD_CONTROL) != 0) { ret.set(Mod::eCtrl); }
if ((glfw_mods & GLFW_MOD_ALT) != 0) { ret.set(Mod::eAlt); }
if ((glfw_mods & GLFW_MOD_SUPER) != 0) { ret.set(Mod::eSuper); }
if ((glfw_mods & GLFW_MOD_CAPS_LOCK) != 0) { ret.set(Mod::eCapsLock); }
if ((glfw_mods & GLFW_MOD_NUM_LOCK) != 0) { ret.set(Mod::eNumLock); }
return ret;
}
} // namespace
Expand Down Expand Up @@ -184,9 +184,7 @@ 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_native_features() const -> FeatureFlags { return FeatureFlags{Feature::eResizeable, Feature::eHasTitle, Feature::eHasIcon}; }

auto DesktopApp::do_get_window_size() const -> glm::ivec2 {
auto ret = glm::ivec2{};
Expand Down Expand Up @@ -357,7 +355,7 @@ void DesktopApp::update_gamepads() {
project_trigger(gamepad.axes.at(static_cast<std::size_t>(GamepadAxis::eRightTrigger)));
gamepad.button_states = {};
for (std::size_t b = 0; b < buttons.size(); ++b) {
if (buttons[b] == 0x1) { gamepad.button_states.set(b); }
if (buttons[b] == 0x1) { gamepad.button_states.set(static_cast<GamepadButton>(b)); }
}

static constexpr auto active_axis = [](float const value) { return value > 0.2f; };
Expand Down
4 changes: 2 additions & 2 deletions lib/src/app.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ auto App::change_mount_point(std::string_view const directory) -> bool {

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

Expand Down Expand Up @@ -118,7 +118,7 @@ void App::push_event(Event event) {
if (auto const* pointer_tap = std::get_if<PointerTap>(&event)) {
m_gesture_recognizer.on_tap(*pointer_tap);
} else if (auto const* key_input = std::get_if<KeyInput>(&event)) {
auto key_state = m_key_state.held_keys[static_cast<std::size_t>(key_input->key)];
auto key_state = m_key_state.held_keys[key_input->key];
switch (key_input->action) {
case Action::ePress: key_state = true; break;
case Action::eRelease: key_state = false; break;
Expand Down
8 changes: 4 additions & 4 deletions lib/src/graphics/particle_emitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,10 @@ void ParticleEmitter::tick(Seconds dt) {
while (m_particles.size() < config.count) { m_particles.push_back(make_particle()); }
}

auto const do_translate = modifiers.test(static_cast<std::size_t>(Modifier::eTranslate));
auto const do_rotate = modifiers.test(static_cast<std::size_t>(Modifier::eRotate));
auto const do_scale = modifiers.test(static_cast<std::size_t>(Modifier::eScale));
auto const do_tint = modifiers.test(static_cast<std::size_t>(Modifier::eTint));
auto const do_translate = modifiers.test(Modifier::eTranslate);
auto const do_rotate = modifiers.test(Modifier::eRotate);
auto const do_scale = modifiers.test(Modifier::eScale);
auto const do_tint = modifiers.test(Modifier::eTint);

instances.resize(m_particles.size());
for (std::size_t index = 0; index < m_particles.size(); ++index) {
Expand Down
2 changes: 1 addition & 1 deletion tools/src/tools/runner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ void Runner::tick() {
void Runner::render() const { m_active->render(); }

void Runner::on_key(KeyInput const& key_input) {
if (key_input.action == Action::ePress && key_input.key == Key::eW && key_input.mods == make_key_mods(Mod::eCtrl)) { get_app().shutdown(); }
if (key_input.action == Action::ePress && key_input.key == Key::eW && key_input.mods == KeyMods(Mod::eCtrl)) { get_app().shutdown(); }
m_active->on_key(key_input);
}

Expand Down

0 comments on commit 1fab6d6

Please sign in to comment.