From 3296de98ccf74cff9d83ffd82ad11958a8d6ee0c Mon Sep 17 00:00:00 2001 From: omigamedev Date: Wed, 6 Mar 2019 20:39:27 +0100 Subject: [PATCH] hide cursor on canvas, add mouse focus event, brush preview solid when small --- data/layout.xml | 8 +++--- data/shaders/stroke-preview.glsl | 33 ++++++++++++++--------- src/app.cpp | 2 +- src/app.h | 2 ++ src/app_events.cpp | 15 +++++++++++ src/canvas_modes.cpp | 45 +++++++++++++++++++++++++++++++- src/canvas_modes.h | 3 +++ src/event.h | 2 ++ src/main.cpp | 32 +++++++++++++++++++++++ src/node.cpp | 33 +++++++++++++++++++++++ src/node.h | 1 + src/node_canvas.cpp | 10 +++++++ src/node_panel_quick.cpp | 30 ++++++++++++++++----- src/shader.cpp | 1 + src/shader.h | 1 + 15 files changed, 194 insertions(+), 24 deletions(-) diff --git a/data/layout.xml b/data/layout.xml index c5e5a85..1ff969b 100644 --- a/data/layout.xml +++ b/data/layout.xml @@ -1474,14 +1474,14 @@ Here's a list of what's available in this release. - + - + - + - + diff --git a/data/shaders/stroke-preview.glsl b/data/shaders/stroke-preview.glsl index 6dfe995..057d456 100644 --- a/data/shaders/stroke-preview.glsl +++ b/data/shaders/stroke-preview.glsl @@ -16,6 +16,8 @@ void main() uniform sampler2D tex; uniform mediump vec4 col; +uniform mediump float alpha; +uniform bool draw_outline; in mediump vec2 uv; out mediump vec4 frag; @@ -23,16 +25,23 @@ out mediump vec4 frag; void main() { mediump float stroke = 1.0 - texture(tex, uv).r; - int zero_count = 0; - if (textureOffset(tex, uv, ivec2(-1, -1)).r > 0.99) zero_count++; - if (textureOffset(tex, uv, ivec2(-1, 0)).r > 0.99) zero_count++; - if (textureOffset(tex, uv, ivec2(-1, +1)).r > 0.99) zero_count++; - if (textureOffset(tex, uv, ivec2( 0, -1)).r > 0.99) zero_count++; - if (textureOffset(tex, uv, ivec2( 0, 0)).r > 0.99) zero_count++; - if (textureOffset(tex, uv, ivec2( 0, +1)).r > 0.99) zero_count++; - if (textureOffset(tex, uv, ivec2(+1, -1)).r > 0.99) zero_count++; - if (textureOffset(tex, uv, ivec2(+1, 0)).r > 0.99) zero_count++; - if (textureOffset(tex, uv, ivec2(+1, +1)).r > 0.99) zero_count++; - mediump float edge = (zero_count > 1 && zero_count < 9) ? 0.75 : 0.0; - frag = vec4(col.rgb, edge * (1.0 - float(zero_count) / 9.f)); + if (draw_outline) + { + int zero_count = 0; + if (textureOffset(tex, uv, ivec2(-1, -1)).r > 0.99) zero_count++; + if (textureOffset(tex, uv, ivec2(-1, 0)).r > 0.99) zero_count++; + if (textureOffset(tex, uv, ivec2(-1, +1)).r > 0.99) zero_count++; + if (textureOffset(tex, uv, ivec2( 0, -1)).r > 0.99) zero_count++; + if (textureOffset(tex, uv, ivec2( 0, 0)).r > 0.99) zero_count++; + if (textureOffset(tex, uv, ivec2( 0, +1)).r > 0.99) zero_count++; + if (textureOffset(tex, uv, ivec2(+1, -1)).r > 0.99) zero_count++; + if (textureOffset(tex, uv, ivec2(+1, 0)).r > 0.99) zero_count++; + if (textureOffset(tex, uv, ivec2(+1, +1)).r > 0.99) zero_count++; + mediump float edge = (zero_count > 1 && zero_count < 9) ? 0.75 : 0.0; + frag = vec4(col.rgb, edge * (1.0 - float(zero_count) / 9.f)); + } + else + { + frag = vec4(col.rgb, stroke * alpha); + } } diff --git a/src/app.cpp b/src/app.cpp index 0fb379f..bb409f0 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -87,7 +87,7 @@ bool App::request_close() m->btn_ok->on_click = [this](Node*) { #ifdef _WIN32 destroy_window(); - PostQuitMessage(0); + //PostQuitMessage(0); #endif #ifdef __OSX__ [osx_view close]; diff --git a/src/app.h b/src/app.h index d743057..528cf1c 100644 --- a/src/app.h +++ b/src/app.h @@ -140,6 +140,8 @@ public: void async_redraw(); void async_end(); void resize(float w, float h); + void show_cursor(); + void hide_cursor(); bool mouse_down(int button, float x, float y, float pressure, kEventSource source, bool eraser); bool mouse_move(float x, float y, float pressure, kEventSource source, bool eraser); bool mouse_up(int button, float x, float y, kEventSource source, bool eraser); diff --git a/src/app_events.cpp b/src/app_events.cpp index c9d9388..7c894d7 100644 --- a/src/app_events.cpp +++ b/src/app_events.cpp @@ -7,6 +7,7 @@ void android_pick_file(android_app* mApplication, std::functionupdate(w , h, zoom); } +void App::show_cursor() +{ +#ifdef _WIN32 + win32_show_cursor(true); +#endif +} + +void App::hide_cursor() +{ +#ifdef _WIN32 + win32_show_cursor(false); +#endif +} + void App::showKeyboard() { LOG("show keyboard"); diff --git a/src/canvas_modes.cpp b/src/canvas_modes.cpp index 4a975d9..aa3abb3 100644 --- a/src/canvas_modes.cpp +++ b/src/canvas_modes.cpp @@ -106,7 +106,8 @@ void CanvasModePen::on_MouseEvent(MouseEvent* me, glm::vec2& loc) m_draw_tip = (me->m_source == kEventSource::Mouse && me->m_type != kEventType::MouseUpL); #else m_draw_tip = (me->m_source == kEventSource::Mouse || me->m_source == kEventSource::Stylus); -#endif // _WIN32 +#endif + m_draw_outline = true; if (Canvas::I->m_touch_lock && me->m_source == kEventSource::Touch) return; @@ -217,6 +218,7 @@ void CanvasModePen::on_Draw(const glm::mat4& ortho, const glm::mat4& proj, const // pos.x = pos.x - brush->m_tip_size * .5f; ShaderManager::use(kShader::StrokePreview); ShaderManager::u_int(kShaderUniform::Tex, 0); + ShaderManager::u_float(kShaderUniform::Alpha, brush->m_tip_flow * brush->m_tip_opacity); float tip_scale_fix = 1.f / glm::tan(glm::radians(Canvas::I->m_cam_fov * 0.5f)); float tip_angle = brush->m_tip_angle * (float)(M_PI * 2.0); glm::vec2 tip_scale = App::I.zoom * brush->m_tip_scale * @@ -237,6 +239,7 @@ void CanvasModePen::on_Draw(const glm::mat4& ortho, const glm::mat4& proj, const tip_color = glm::vec4(s.col, s.flow); } } + ShaderManager::u_int(kShaderUniform::DrawOutline, glm::min(tip_scale.x, tip_scale.y) < 20 ? false : m_draw_outline); ShaderManager::u_vec4(kShaderUniform::Col, tip_color); ShaderManager::u_mat4(kShaderUniform::MVP, glm::scale(glm::vec3(1, -1, 1)) * @@ -279,6 +282,11 @@ void CanvasModePen::enter(kCanvasMode prev) void CanvasModeLine::on_MouseEvent(MouseEvent* me, glm::vec2& loc) { +#if defined(__IOS__) + m_draw_tip = (me->m_source == kEventSource::Mouse && me->m_type != kEventType::MouseUpL); +#else + m_draw_tip = (me->m_source == kEventSource::Mouse || me->m_source == kEventSource::Stylus); +#endif if (Canvas::I->m_touch_lock && me->m_source == kEventSource::Touch) return; switch (me->m_type) @@ -303,6 +311,7 @@ void CanvasModeLine::on_MouseEvent(MouseEvent* me, glm::vec2& loc) case kEventType::MouseMove: if (m_dragging) m_drag_pos = loc; + m_cur_pos = loc; break; case kEventType::MouseCancel: node->mouse_release(); @@ -328,6 +337,39 @@ void CanvasModeLine::on_Draw(const glm::mat4& ortho, const glm::mat4& proj, cons m_line.update_vertices(AB); m_line.draw_stroke(); } + else if (m_draw_tip) + { + const auto& brush = Canvas::I->m_current_brush; + ShaderManager::use(kShader::StrokePreview); + ShaderManager::u_int(kShaderUniform::Tex, 0); + ShaderManager::u_float(kShaderUniform::Alpha, brush->m_tip_flow * brush->m_tip_opacity); + float tip_scale_fix = 1.f / glm::tan(glm::radians(Canvas::I->m_cam_fov * 0.5f)); + float tip_angle = brush->m_tip_angle * (float)(M_PI * 2.0); + glm::vec2 tip_scale = App::I.zoom * brush->m_tip_scale * + glm::vec2(brush->m_tip_size * tip_scale_fix) * + glm::vec2(brush->m_tip_flipx ? -1 : 1, brush->m_tip_flipy ? -1.f : 1.f) * + glm::vec2((brush->m_tip_aspect <= 0.5 ? brush->m_tip_aspect * 2.f : 1.f), + (brush->m_tip_aspect > 0.5 ? 1.f - (brush->m_tip_aspect - .5f) * 2.f : 1.f)); + auto tip_color = glm::vec4(glm::vec3(brush->m_tip_color), 1.f); + ShaderManager::u_int(kShaderUniform::DrawOutline, false); + ShaderManager::u_vec4(kShaderUniform::Col, tip_color); + ShaderManager::u_mat4(kShaderUniform::MVP, + glm::scale(glm::vec3(1, -1, 1)) * + ortho * + glm::translate(glm::vec3(m_cur_pos, 0)) * + glm::eulerAngleZ(tip_angle) * + glm::scale(glm::vec3(tip_scale, 1)) + ); + bool blend = glIsEnabled(GL_BLEND); + glEnable(GL_BLEND); + glActiveTexture(GL_TEXTURE0); + auto& tex = *brush->m_tip_texture; + tex.bind(); + Canvas::I->m_sampler_brush.bind(0); + Canvas::I->m_plane.draw_fill(); + tex.unbind(); + if (!blend) glDisable(GL_BLEND); + } } void CanvasModeLine::init() @@ -337,6 +379,7 @@ void CanvasModeLine::init() void CanvasModeLine::enter(kCanvasMode prev) { + m_cur_pos = Canvas::I->m_cur_pos; if (!m_brush) { m_brush = std::make_shared(); diff --git a/src/canvas_modes.h b/src/canvas_modes.h index 9139079..08dfe2b 100644 --- a/src/canvas_modes.h +++ b/src/canvas_modes.h @@ -88,6 +88,7 @@ public: bool m_picking = false; glm::vec2 m_cur_pos; bool m_draw_tip = false; + bool m_draw_outline = true; }; class CanvasModeLine : public CanvasMode @@ -98,6 +99,8 @@ class CanvasModeLine : public CanvasMode glm::vec2 m_drag_pos; std::shared_ptr m_brush; public: + glm::vec2 m_cur_pos; + bool m_draw_tip = false; virtual void on_MouseEvent(MouseEvent* me, glm::vec2& loc) override; virtual void on_Draw(const glm::mat4& ortho, const glm::mat4& proj, const glm::mat4& camera) override; virtual void init() override; diff --git a/src/event.h b/src/event.h index 17519c9..6116d2f 100644 --- a/src/event.h +++ b/src/event.h @@ -101,6 +101,8 @@ enum class kEventType : uint8_t MouseLeave, MouseScroll, MouseCancel, + MouseFocus, + MouseUnfocus, GestureStart, GestureMove, GestureEnd, diff --git a/src/main.cpp b/src/main.cpp index 85819be..30546b1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -40,6 +40,8 @@ std::condition_variable render_cv; int gl_count = 0; std::deque> tasklist; std::mutex task_mutex; +std::deque> main_tasklist; +std::mutex main_task_mutex; float timer_stylus = 0; float timer_ink_touch = 0; float timer_ink_pen = 0; @@ -67,6 +69,10 @@ std::string GetLastErrorAsString() void destroy_window() { + std::lock_guard lock(main_task_mutex); + main_tasklist.emplace_back([=] { + SendMessage(hWnd, WM_USER_CLOSE, 0, 0); + }); SendMessage(hWnd, WM_USER_CLOSE, 0, 0); } @@ -122,6 +128,14 @@ void async_unlock() } } +void win32_show_cursor(bool visible) +{ + std::lock_guard lock(main_task_mutex); + main_tasklist.emplace_back([=] { + ShowCursor(visible); + }); +} + std::string win32_open_file(const char* filter) { OPENFILENAMEA ofn; @@ -810,6 +824,24 @@ int main(int argc, char** argv) TranslateMessage(&msg); } + // list of tasks for the main thread + { + std::deque> working_list; + { + std::lock_guard lock(main_task_mutex); + working_list = std::move(main_tasklist); + } + + if (!working_list.empty()) + { + while (!working_list.empty()) + { + working_list.front()(); + working_list.pop_front(); + } + } + } + if (!tasklist.empty()) render_cv.notify_all(); } diff --git a/src/node.cpp b/src/node.cpp index 12adb57..6dfa25c 100644 --- a/src/node.cpp +++ b/src/node.cpp @@ -93,7 +93,23 @@ kEventResult Node::on_event(Event* e) kEventResult ret = kEventResult::Available; if (current_mouse_capture) + { + if (e->m_cat == kEventCategory::MouseEvent && child_mouse_focus != current_mouse_capture) + { + MouseEvent* me = static_cast(e); + if (child_mouse_focus) + { + MouseEvent e2 = *me; + e2.m_type = kEventType::MouseUnfocus; + child_mouse_focus->handle_event(&e2); + } + MouseEvent e2 = *me; + e2.m_type = kEventType::MouseFocus; + current_mouse_capture->handle_event(&e2); + child_mouse_focus = current_mouse_capture; + } return current_mouse_capture->on_event(e); + } bool skip_children = false; skip_children |= (e->m_cat == kEventCategory::MouseEvent || e->m_cat == kEventCategory::GestureEvent) && @@ -114,6 +130,20 @@ kEventResult Node::on_event(Event* e) } else { + if (e->m_cat == kEventCategory::MouseEvent && child_mouse_focus != it->get()) + { + MouseEvent* me = static_cast(e); + if (child_mouse_focus) + { + MouseEvent e2 = *me; + e2.m_type = kEventType::MouseUnfocus; + child_mouse_focus->handle_event(&e2); + } + MouseEvent e2 = *me; + e2.m_type = kEventType::MouseFocus; + (*it)->handle_event(&e2); + child_mouse_focus = it->get(); + } ret = kEventResult::Consumed; break; } @@ -312,6 +342,8 @@ void Node::remove_child(Node* n) YGNodeRemoveChild(y_node, n->y_node); on_child_removed(n); m_children.erase(i); + if (child_mouse_focus == n) + child_mouse_focus = nullptr; } } @@ -324,6 +356,7 @@ void Node::remove_all_children() on_child_removed(n.get()); } m_children.clear(); + child_mouse_focus = nullptr; } void Node::move_child(Node* n, int index) diff --git a/src/node.h b/src/node.h index 6f1b02f..dcd260e 100644 --- a/src/node.h +++ b/src/node.h @@ -104,6 +104,7 @@ public: std::vector> m_children; Node* current_mouse_capture = nullptr; Node* current_key_capture = nullptr; + Node* child_mouse_focus = nullptr; bool m_mouse_captured = false; bool m_key_captured = false; diff --git a/src/node_canvas.cpp b/src/node_canvas.cpp index 2b06fa8..e2f0de2 100644 --- a/src/node_canvas.cpp +++ b/src/node_canvas.cpp @@ -456,6 +456,16 @@ kEventResult NodeCanvas::handle_event(Event* e) for (auto& mode : *m_canvas->m_mode) mode->on_MouseEvent(me, loc); break; + case kEventType::MouseUnfocus: + if (auto m = dynamic_cast(m_canvas->modes[(int)m_canvas->m_current_mode][0])) + m->m_draw_tip = false; + if (auto m = dynamic_cast(m_canvas->modes[(int)m_canvas->m_current_mode][0])) + m->m_draw_tip = false; + App::I.show_cursor(); + break; + case kEventType::MouseFocus: + App::I.hide_cursor(); + break; case kEventType::KeyDown: if (ke->m_key == kKey::KeyE) Canvas::set_mode(kCanvasMode::Erase); diff --git a/src/node_panel_quick.cpp b/src/node_panel_quick.cpp index 0a94370..254663c 100644 --- a/src/node_panel_quick.cpp +++ b/src/node_panel_quick.cpp @@ -41,18 +41,36 @@ void NodePanelQuick::init_controls() m_slider_size = find("quick-size"); m_slider_size->on_value_changed = [this](Node* target, float value) { - auto m = static_cast(Canvas::I->modes[(int)kCanvasMode::Draw][0]); - m->m_cur_pos = (m_slider_flow->m_pos + glm::vec2(100.f, m_slider_flow->m_size.y / 2.f)) * App::I.zoom; - m->m_draw_tip = true; + auto newpos = (m_slider_flow->m_pos + glm::vec2(100.f, m_slider_flow->m_size.y / 2.f)) * App::I.zoom; + if (auto m = dynamic_cast(Canvas::I->modes[(int)Canvas::I->m_current_mode][0])) + { + m->m_cur_pos = newpos; + m->m_draw_tip = true; + m->m_draw_outline = false; + } + if (auto m = dynamic_cast(Canvas::I->modes[(int)Canvas::I->m_current_mode][0])) + { + m->m_cur_pos = newpos; + m->m_draw_tip = true; + } m_button_brush_current_preview->draw_stroke(); if (on_size_change) on_size_change(target, value); }; m_slider_flow = find("quick-flow"); m_slider_flow->on_value_changed = [this](Node* target, float value) { - auto m = static_cast(Canvas::I->modes[(int)kCanvasMode::Draw][0]); - m->m_cur_pos = (m_slider_flow->m_pos + glm::vec2(100.f, m_slider_flow->m_size.y / 2.f)) * App::I.zoom; - m->m_draw_tip = true; + auto newpos = (m_slider_flow->m_pos + glm::vec2(100.f, m_slider_flow->m_size.y / 2.f)) * App::I.zoom; + if (auto m = dynamic_cast(Canvas::I->modes[(int)Canvas::I->m_current_mode][0])) + { + m->m_cur_pos = newpos; + m->m_draw_tip = true; + m->m_draw_outline = false; + } + if (auto m = dynamic_cast(Canvas::I->modes[(int)Canvas::I->m_current_mode][0])) + { + m->m_cur_pos = newpos; + m->m_draw_tip = true; + } m_button_brush_current_preview->draw_stroke(); if (on_flow_change) on_flow_change(target, value); diff --git a/src/shader.cpp b/src/shader.cpp index 55874b6..fec9bf5 100644 --- a/src/shader.cpp +++ b/src/shader.cpp @@ -440,6 +440,7 @@ bool check_uniform_uniqueness() const_hash("colorize"), const_hash("dual_alpha"), const_hash("use_fragcoord"), + const_hash("draw_outline"), }; std::sort(v.begin(), v.end()); int last = 0; diff --git a/src/shader.h b/src/shader.h index 648bd31..422bb83 100644 --- a/src/shader.h +++ b/src/shader.h @@ -47,6 +47,7 @@ enum class kShaderUniform : uint16_t Colorize = const_hash("colorize"), DualAlpha = const_hash("dual_alpha"), UseFragcoord = const_hash("use_fragcoord"), + DrawOutline = const_hash("draw_outline"), }; enum class kShader : uint16_t