Imgui: Implement keyboard input, fix #1797

This commit is contained in:
Vojtech Kral 2019-02-15 15:35:32 +01:00
parent 3901ac47d1
commit 2de814d478
5 changed files with 128 additions and 10 deletions

View file

@ -5161,7 +5161,8 @@ void GLCanvas3D::bind_event_handlers()
m_canvas->Bind(wxEVT_SIZE, &GLCanvas3D::on_size, this);
m_canvas->Bind(wxEVT_IDLE, &GLCanvas3D::on_idle, this);
m_canvas->Bind(wxEVT_CHAR, &GLCanvas3D::on_char, this);
m_canvas->Bind(wxEVT_KEY_UP, &GLCanvas3D::on_key_up, this);
m_canvas->Bind(wxEVT_KEY_DOWN, &GLCanvas3D::on_key, this);
m_canvas->Bind(wxEVT_KEY_UP, &GLCanvas3D::on_key, this);
m_canvas->Bind(wxEVT_MOUSEWHEEL, &GLCanvas3D::on_mouse_wheel, this);
m_canvas->Bind(wxEVT_TIMER, &GLCanvas3D::on_timer, this);
m_canvas->Bind(wxEVT_LEFT_DOWN, &GLCanvas3D::on_mouse, this);
@ -5187,7 +5188,8 @@ void GLCanvas3D::unbind_event_handlers()
m_canvas->Unbind(wxEVT_SIZE, &GLCanvas3D::on_size, this);
m_canvas->Unbind(wxEVT_IDLE, &GLCanvas3D::on_idle, this);
m_canvas->Unbind(wxEVT_CHAR, &GLCanvas3D::on_char, this);
m_canvas->Unbind(wxEVT_KEY_UP, &GLCanvas3D::on_key_up, this);
m_canvas->Unbind(wxEVT_KEY_DOWN, &GLCanvas3D::on_key, this);
m_canvas->Unbind(wxEVT_KEY_UP, &GLCanvas3D::on_key, this);
m_canvas->Unbind(wxEVT_MOUSEWHEEL, &GLCanvas3D::on_mouse_wheel, this);
m_canvas->Unbind(wxEVT_TIMER, &GLCanvas3D::on_timer, this);
m_canvas->Unbind(wxEVT_LEFT_DOWN, &GLCanvas3D::on_mouse, this);
@ -5224,6 +5226,17 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
// see include/wx/defs.h enum wxKeyCode
int keyCode = evt.GetKeyCode();
int ctrlMask = wxMOD_CONTROL;
#if ENABLE_IMGUI
auto imgui = wxGetApp().imgui();
if (imgui->update_key_data(evt)) {
render();
if (imgui->want_any_input()) {
return;
}
}
#endif // ENABLE_IMGUI
//#ifdef __APPLE__
// ctrlMask |= wxMOD_RAW_CONTROL;
//#endif /* __APPLE__ */
@ -5299,14 +5312,23 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
}
}
void GLCanvas3D::on_key_up(wxKeyEvent& evt)
void GLCanvas3D::on_key(wxKeyEvent& evt)
{
// see include/wx/defs.h enum wxKeyCode
int keyCode = evt.GetKeyCode();
#if ENABLE_IMGUI
auto imgui = wxGetApp().imgui();
if (imgui->update_key_data(evt)) {
render();
} else
#endif // ENABLE_IMGUI
if (evt.GetEventType() == wxEVT_KEY_UP) {
const int keyCode = evt.GetKeyCode();
// shift has been just released - SLA gizmo might want to close rectangular selection.
if (m_gizmos.get_current_type() == Gizmos::SlaSupports && keyCode == WXK_SHIFT && m_gizmos.mouse_event(SLAGizmoEventType::ShiftUp))
m_dirty = true;
}
// shift has been just released - SLA gizmo might want to close rectangular selection.
if (m_gizmos.get_current_type() == Gizmos::SlaSupports && keyCode == WXK_SHIFT && m_gizmos.mouse_event(SLAGizmoEventType::ShiftUp))
m_dirty = true;
evt.Skip(); // Needed to have EVT_CHAR generated as well
}
void GLCanvas3D::on_mouse_wheel(wxMouseEvent& evt)

View file

@ -1075,7 +1075,7 @@ public:
void on_size(wxSizeEvent& evt);
void on_idle(wxIdleEvent& evt);
void on_char(wxKeyEvent& evt);
void on_key_up(wxKeyEvent& evt);
void on_key(wxKeyEvent& evt);
void on_mouse_wheel(wxMouseEvent& evt);
void on_timer(wxTimerEvent& evt);
void on_mouse(wxMouseEvent& evt);

View file

@ -233,7 +233,7 @@ wxGLCanvas* GLCanvas3DManager::create_wxglcanvas(wxWindow *parent)
attribList[4] = 0;
}
return new wxGLCanvas(parent, wxID_ANY, attribList);
return new wxGLCanvas(parent, wxID_ANY, attribList, wxDefaultPosition, wxDefaultSize, wxWANTS_CHARS);
}
GLCanvas3DManager::CanvasesMap::iterator GLCanvas3DManager::_get_canvas(wxGLCanvas* canvas)

View file

@ -10,6 +10,7 @@
#include <wx/string.h>
#include <wx/event.h>
#include <wx/clipbrd.h>
#include <wx/debug.h>
#include <GL/glew.h>
@ -44,6 +45,7 @@ bool ImGuiWrapper::init()
ImGui::CreateContext();
init_default_font(m_style_scaling);
init_input();
ImGui::GetIO().IniFilename = nullptr;
@ -109,6 +111,28 @@ bool ImGuiWrapper::update_mouse_data(wxMouseEvent& evt)
return res;
}
bool ImGuiWrapper::update_key_data(wxKeyEvent &evt)
{
ImGuiIO& io = ImGui::GetIO();
if (evt.GetEventType() == wxEVT_CHAR) {
// Char event
io.AddInputCharacter(evt.GetUnicodeKey());
} else {
// Key up/down event
int key = evt.GetKeyCode();
wxCHECK_MSG(key >= 0 && key < IM_ARRAYSIZE(io.KeysDown), false, "Received invalid key code");
io.KeysDown[key] = evt.GetEventType() == wxEVT_KEY_DOWN;
io.KeyShift = evt.ShiftDown();
io.KeyCtrl = evt.ControlDown();
io.KeyAlt = evt.AltDown();
io.KeySuper = evt.MetaDown();
}
return true;
}
void ImGuiWrapper::new_frame()
{
if (m_font_texture == 0)
@ -307,6 +331,39 @@ void ImGuiWrapper::create_fonts_texture()
glBindTexture(GL_TEXTURE_2D, last_texture);
}
void ImGuiWrapper::init_input()
{
ImGuiIO& io = ImGui::GetIO();
// Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array.
io.KeyMap[ImGuiKey_Tab] = WXK_TAB;
io.KeyMap[ImGuiKey_LeftArrow] = WXK_LEFT;
io.KeyMap[ImGuiKey_RightArrow] = WXK_RIGHT;
io.KeyMap[ImGuiKey_UpArrow] = WXK_UP;
io.KeyMap[ImGuiKey_DownArrow] = WXK_DOWN;
io.KeyMap[ImGuiKey_PageUp] = WXK_PAGEUP;
io.KeyMap[ImGuiKey_PageDown] = WXK_PAGEDOWN;
io.KeyMap[ImGuiKey_Home] = WXK_HOME;
io.KeyMap[ImGuiKey_End] = WXK_END;
io.KeyMap[ImGuiKey_Insert] = WXK_INSERT;
io.KeyMap[ImGuiKey_Delete] = WXK_DELETE;
io.KeyMap[ImGuiKey_Backspace] = WXK_BACK;
io.KeyMap[ImGuiKey_Space] = WXK_SPACE;
io.KeyMap[ImGuiKey_Enter] = WXK_RETURN;
io.KeyMap[ImGuiKey_Escape] = WXK_ESCAPE;
io.KeyMap[ImGuiKey_A] = 'A';
io.KeyMap[ImGuiKey_C] = 'C';
io.KeyMap[ImGuiKey_V] = 'V';
io.KeyMap[ImGuiKey_X] = 'X';
io.KeyMap[ImGuiKey_Y] = 'Y';
io.KeyMap[ImGuiKey_Z] = 'Z';
// Setup clipboard interaction callbacks
io.SetClipboardTextFn = clipboard_set;
io.GetClipboardTextFn = clipboard_get;
io.ClipboardUserData = this;
}
void ImGuiWrapper::render_draw_data(ImDrawData *draw_data)
{
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
@ -420,6 +477,37 @@ void ImGuiWrapper::destroy_fonts_texture()
}
}
const char* ImGuiWrapper::clipboard_get(void* user_data)
{
ImGuiWrapper *self = reinterpret_cast<ImGuiWrapper*>(user_data);
const char* res = "";
if (wxTheClipboard->Open()) {
if (wxTheClipboard->IsSupported(wxDF_TEXT)) {
wxTextDataObject data;
wxTheClipboard->GetData(data);
if (data.GetTextLength() > 0) {
self->clipboard_text = into_u8(data.GetText());
res = self->clipboard_text.c_str();
}
}
wxTheClipboard->Close();
}
return res;
}
void ImGuiWrapper::clipboard_set(void* /* user_data */, const char* text)
{
if (wxTheClipboard->Open()) {
wxTheClipboard->SetData(new wxTextDataObject(wxString::FromUTF8(text))); // object owned by the clipboard
wxTheClipboard->Close();
}
}
} // namespace GUI
} // namespace Slic3r

View file

@ -10,6 +10,7 @@
class wxString;
class wxMouseEvent;
class wxKeyEvent;
namespace Slic3r {
@ -37,6 +38,7 @@ public:
void set_display_size(float w, float h);
void set_style_scaling(float scaling);
bool update_mouse_data(wxMouseEvent &evt);
bool update_key_data(wxKeyEvent &evt);
void new_frame();
void render();
@ -65,12 +67,18 @@ public:
bool want_any_input() const;
private:
std::string clipboard_text;
void init_default_font(float scaling);
void create_device_objects();
void create_fonts_texture();
void init_input();
void render_draw_data(ImDrawData *draw_data);
void destroy_device_objects();
void destroy_fonts_texture();
static const char* clipboard_get(void* user_data);
static void clipboard_set(void* user_data, const char* text);
};