hide cursor on canvas, add mouse focus event, brush preview solid when small

This commit is contained in:
2019-03-06 20:39:27 +01:00
parent 5eba9f1227
commit 3296de98cc
15 changed files with 194 additions and 24 deletions

View File

@@ -1474,14 +1474,14 @@ Here's a list of what's available in this release.
<border color="0 0 0 0.6" width="80" dir="col" pad="5" align="center" mouse-capture="true" shrink="1">
<node dir="row" pad="5" shrink="1" min-height="100" max-height="150">
<!--size-->
<node dir="col" margin="0 4 0 0" align="center">
<node dir="col" margin="0 4 0 0" height="100%" align="center">
<text text="Size" margin="0 0 10 0"/>
<slider-v id="quick-size" height="100%" width="30"/>
<slider-v id="quick-size" height="1" grow="1" width="30"/>
</node>
<!--flow-->
<node dir="col" align="center">
<node dir="col" align="center" height="100%">
<text text="Flow" margin="0 0 10 0"/>
<slider-v id="quick-flow" height="100%" width="30"/>
<slider-v id="quick-flow" height="1" grow="1" width="30"/>
</node>
</node>
<!--color-->

View File

@@ -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);
}
}

View File

@@ -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];

View File

@@ -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);

View File

@@ -7,6 +7,7 @@ void android_pick_file(android_app* mApplication, std::function<void(std::string
#elif _WIN32
std::string win32_open_file(const char* filter);
std::string win32_open_dir();
void win32_show_cursor(bool visible);
#endif
void App::crash_test()
@@ -37,6 +38,20 @@ void App::resize(float w, float h)
main->update(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");

View File

@@ -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<Brush>();

View File

@@ -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<Brush> 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;

View File

@@ -101,6 +101,8 @@ enum class kEventType : uint8_t
MouseLeave,
MouseScroll,
MouseCancel,
MouseFocus,
MouseUnfocus,
GestureStart,
GestureMove,
GestureEnd,

View File

@@ -40,6 +40,8 @@ std::condition_variable render_cv;
int gl_count = 0;
std::deque<std::packaged_task<void()>> tasklist;
std::mutex task_mutex;
std::deque<std::packaged_task<void()>> 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<std::mutex> 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<std::mutex> 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<std::packaged_task<void()>> working_list;
{
std::lock_guard<std::mutex> 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();
}

View File

@@ -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<MouseEvent*>(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<MouseEvent*>(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)

View File

@@ -104,6 +104,7 @@ public:
std::vector<std::shared_ptr<Node>> 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;

View File

@@ -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<CanvasModePen*>(m_canvas->modes[(int)m_canvas->m_current_mode][0]))
m->m_draw_tip = false;
if (auto m = dynamic_cast<CanvasModeLine*>(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);

View File

@@ -41,18 +41,36 @@ void NodePanelQuick::init_controls()
m_slider_size = find<NodeSliderV>("quick-size");
m_slider_size->on_value_changed = [this](Node* target, float value) {
auto m = static_cast<CanvasModePen*>(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<CanvasModePen*>(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<CanvasModeLine*>(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<NodeSliderV>("quick-flow");
m_slider_flow->on_value_changed = [this](Node* target, float value) {
auto m = static_cast<CanvasModePen*>(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<CanvasModePen*>(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<CanvasModeLine*>(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);

View File

@@ -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;

View File

@@ -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