hide cursor on canvas, add mouse focus event, brush preview solid when small
This commit is contained in:
@@ -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-->
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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>();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -101,6 +101,8 @@ enum class kEventType : uint8_t
|
||||
MouseLeave,
|
||||
MouseScroll,
|
||||
MouseCancel,
|
||||
MouseFocus,
|
||||
MouseUnfocus,
|
||||
GestureStart,
|
||||
GestureMove,
|
||||
GestureEnd,
|
||||
|
||||
32
src/main.cpp
32
src/main.cpp
@@ -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();
|
||||
}
|
||||
|
||||
33
src/node.cpp
33
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<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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user