mirror of
https://github.com/enduro2d/enduro2d.git
synced 2025-12-15 00:11:55 +07:00
window: add cursor shapes
This commit is contained in:
@@ -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 >
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user