window: add cursor shapes

This commit is contained in:
2019-11-30 17:16:35 +07:00
parent 5cc9cd8dc5
commit a8abd27a31
4 changed files with 100 additions and 0 deletions

View File

@@ -19,6 +19,14 @@ namespace e2d
class window final : public module<window> {
public:
ENUM_HPP_CLASS_DECL(cursor_shapes, u8,
(arrow)
(ibeam)
(crosshair)
(hand)
(hresize)
(vresize))
class event_listener : private e2d::noncopyable {
public:
virtual ~event_listener() noexcept = default;
@@ -55,6 +63,9 @@ namespace e2d
void show_cursor() noexcept;
bool is_cursor_hidden() const noexcept;
cursor_shapes cursor_shape() const noexcept;
bool set_cursor_shape(cursor_shapes shape) noexcept;
v2u real_size() const noexcept;
v2u virtual_size() const noexcept;
v2u framebuffer_size() const noexcept;
@@ -96,6 +107,8 @@ namespace e2d
};
}
ENUM_HPP_REGISTER_TRAITS(e2d::window::cursor_shapes)
namespace e2d
{
template < typename T, typename... Args >

View File

@@ -10,6 +10,24 @@ namespace
{
using namespace e2d;
window::cursor_shapes convert_imgui_mouse_cursor(ImGuiMouseCursor mc) noexcept {
#define DEFINE_CASE(x,y) case x: return window::cursor_shapes::y
switch ( mc ) {
DEFINE_CASE(ImGuiMouseCursor_Arrow, arrow);
DEFINE_CASE(ImGuiMouseCursor_TextInput, ibeam);
DEFINE_CASE(ImGuiMouseCursor_ResizeAll, crosshair);
DEFINE_CASE(ImGuiMouseCursor_ResizeNS, vresize);
DEFINE_CASE(ImGuiMouseCursor_ResizeEW, hresize);
DEFINE_CASE(ImGuiMouseCursor_ResizeNESW, crosshair);
DEFINE_CASE(ImGuiMouseCursor_ResizeNWSE, crosshair);
DEFINE_CASE(ImGuiMouseCursor_Hand, hand);
default:
E2D_ASSERT_MSG(false, "unexpected imgui mouse cursor");
return window::cursor_shapes::arrow;
}
#undef DEFINE_CASE
}
class imgui_event_listener final : public window::event_listener {
public:
imgui_event_listener(ImGuiIO& io, window& w)
@@ -137,6 +155,10 @@ namespace e2d
window_.framebuffer_size().cast_to<f32>() /
window_.real_size().cast_to<f32>();
window_.set_cursor_shape(
convert_imgui_mouse_cursor(
ImGui::GetMouseCursor()));
if ( ImGui::GetFrameCount() > 0 ) {
ImGui::EndFrame();
}
@@ -250,6 +272,7 @@ namespace e2d
io.IniFilename = nullptr;
io.LogFilename = nullptr;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors;
}
void setup_internal_resources_(ImGuiIO& io) {

View File

@@ -241,6 +241,22 @@ namespace
return keyboard_key_action::unknown;
}
}
int convert_cursor_shape(window::cursor_shapes shape) noexcept {
#define DEFINE_CASE(x,y) case window::cursor_shapes::x: return y
switch ( shape ) {
DEFINE_CASE(arrow, GLFW_ARROW_CURSOR);
DEFINE_CASE(ibeam, GLFW_IBEAM_CURSOR);
DEFINE_CASE(crosshair, GLFW_CROSSHAIR_CURSOR);
DEFINE_CASE(hand, GLFW_HAND_CURSOR);
DEFINE_CASE(hresize, GLFW_HRESIZE_CURSOR);
DEFINE_CASE(vresize, GLFW_VRESIZE_CURSOR);
default:
E2D_ASSERT_MSG(false, "unexpected cursor shape");
return GLFW_ARROW_CURSOR;
}
#undef DEFINE_CASE
}
}
namespace e2d
@@ -249,11 +265,15 @@ namespace e2d
public:
using window_uptr = std::unique_ptr<
GLFWwindow, void(*)(GLFWwindow*)>;
using cursor_uptr = std::unique_ptr<
GLFWcursor, void(*)(GLFWcursor*)>;
using cursors_t = flat_map<cursor_shapes, cursor_uptr>;
using listeners_t = vector<event_listener_uptr>;
public:
listeners_t listeners;
std::recursive_mutex rmutex;
glfw_state_ptr shared_state;
cursors_t cursors;
window_uptr window;
v2u real_size;
v2u virtual_size;
@@ -263,9 +283,11 @@ namespace e2d
bool resizable = false;
bool fullscreen = false;
bool cursor_hidden = false;
cursor_shapes cursor_shape = cursor_shapes::arrow;
public:
state(const v2u& size, str_view ntitle, bool nvsync, bool nresizable, bool nfullscreen)
: shared_state(glfw_state::get_shared_state())
, cursors(create_cursors_())
, window(nullptr, glfwDestroyWindow)
, real_size(size)
, virtual_size(size)
@@ -344,6 +366,16 @@ namespace e2d
return listener;
}
private:
static cursors_t create_cursors_() {
cursors_t cursors;
for ( const cursor_shapes shape : enum_hpp::values<cursor_shapes>() ) {
cursors.emplace(shape, cursor_uptr{
glfwCreateStandardCursor(convert_cursor_shape(shape)),
glfwDestroyCursor});
}
return cursors;
}
static window_uptr open_window_(
const v2u& virtual_size,
const str& title,
@@ -593,6 +625,26 @@ namespace e2d
return state_->cursor_hidden;
}
window::cursor_shapes window::cursor_shape() const noexcept {
std::lock_guard<std::recursive_mutex> guard(state_->rmutex);
return state_->cursor_shape;
}
bool window::set_cursor_shape(cursor_shapes shape) noexcept {
std::lock_guard<std::recursive_mutex> guard(state_->rmutex);
E2D_ASSERT(state_->window);
if ( shape == state_->cursor_shape ) {
return true;
}
const auto cursor_iter = state_->cursors.find(shape);
if ( cursor_iter == state_->cursors.end() || !cursor_iter->second ) {
return false;
}
glfwSetCursor(state_->window.get(), cursor_iter->second.get());
state_->cursor_shape = shape;
return true;
}
v2u window::real_size() const noexcept {
std::lock_guard<std::recursive_mutex> guard(state_->rmutex);
return state_->real_size;

View File

@@ -22,6 +22,7 @@ namespace e2d
bool resizable = false;
bool fullscreen = false;
bool cursor_hidden = false;
cursor_shapes cursor_shape = cursor_shapes::arrow;
bool should_close = false;
bool enabled = true;
bool visible = true;
@@ -131,6 +132,17 @@ namespace e2d
return state_->cursor_hidden;
}
window::cursor_shapes window::cursor_shape() const noexcept {
std::lock_guard<std::recursive_mutex> guard(state_->rmutex);
return state_->cursor_shape;
}
bool window::set_cursor_shape(cursor_shapes shape) noexcept {
std::lock_guard<std::recursive_mutex> guard(state_->rmutex);
state_->cursor_shape = shape;
return true;
}
v2u window::real_size() const noexcept {
std::lock_guard<std::recursive_mutex> guard(state_->rmutex);
return state_->virtual_size;