#include "pch.h" #include "canvas_modes.h" #include "app.h" #include "canvas.h" #include "legacy_canvas_mode_helpers.h" #include "legacy_canvas_stroke_preview_services.h" #include "legacy_ui_overlay_services.h" #include "legacy_ui_gl_dispatch.h" #include "renderer_gl/opengl_capabilities.h" using pp::legacy_canvas_mode::apply_canvas_mode_capability; using pp::legacy_canvas_mode::query_canvas_mode_capability; using pp::legacy_canvas_mode::read_canvas_mode_pixel; using pp::legacy_canvas_mode::set_canvas_mode_active_texture_unit; void CanvasModePen::on_GestureEvent(GestureEvent* ge) { m_draw_tip = false; } void CanvasModePen::on_MouseEvent(MouseEvent* me, glm::vec2& loc) { m_draw_tip = App::I->draws_canvas_tip_for_input(me->m_source, me->m_type); m_draw_outline = true; if (Canvas::I->m_touch_lock && me->m_source == kEventSource::Touch) return; me->m_pressure = App::I->adjust_canvas_input_pressure(me->m_pressure); switch (me->m_type) { case kEventType::MouseDownL: if (!App::I->keys[(int)kKey::KeySpacebar]) { if (App::I->keys[(int)kKey::KeyAlt] || m_picking) { m_picking = true; Canvas::I->pick_start(); glm::vec4 pix = Canvas::I->pick_get(loc); Canvas::I->m_current_brush->m_tip_color = pix; App::I->brush_update(true, false); } else { App::I->render_task_async([loc, pr = me->m_pressure] { Canvas::I->stroke_start({ loc, 0 }, pr); }); m_drawing = true; } m_dragging = true; node->mouse_capture(); } break; case kEventType::MouseUpL: if (m_dragging && !m_picking) { pp::panopainter::release_legacy_mouse_capture(*node); App::I->render_task_async([] { Canvas::I->stroke_end(); }); } if (m_dragging && m_picking) { pp::panopainter::release_legacy_mouse_capture(*node); glm::vec4 pix = Canvas::I->pick_get(loc); Canvas::I->m_current_brush->m_tip_color = pix; App::I->brush_update(true, false); Canvas::I->pick_end(); } m_drawing = false; m_dragging = false; m_picking = false; break; case kEventType::MouseDownR: if (App::I->keys[(int)kKey::KeyAlt]) { m_resizing = true; m_dragging = true; m_size_pos_start = m_cur_pos; auto curve = App::I->stroke->m_curves[App::I->stroke->m_tip_size]; m_size_value_start = curve.to_slider(Canvas::I->m_current_brush->m_tip_size); node->mouse_capture(); } break; case kEventType::MouseUpR: if (m_dragging && m_resizing) { pp::panopainter::release_legacy_mouse_capture(*node); m_dragging = false; m_resizing = false; } break; case kEventType::MouseMove: if (m_dragging && !m_picking && !m_resizing) { App::I->render_task_async([loc, pr=me->m_pressure] { Canvas::I->stroke_update({ loc, 0 }, pr); }); } if (m_dragging && m_picking) { glm::vec4 pix = Canvas::I->pick_get(loc); Canvas::I->m_current_brush->m_tip_color = pix; App::I->brush_update(true, false); } if (m_dragging && m_resizing) { auto diff = m_cur_pos - m_size_pos_start; auto curve = App::I->stroke->m_curves[App::I->stroke->m_tip_size]; Canvas::I->m_current_brush->m_tip_size = glm::max(curve.to_value(m_size_value_start + diff.x * 0.001f), 0.001f); App::I->brush_update(true, true); } m_cur_pos = loc; break; case kEventType::MouseCancel: if (m_dragging) { App::I->render_task_async([] { Canvas::I->stroke_cancel(); }); m_dragging = false; pp::panopainter::release_legacy_mouse_capture(*node); } if (m_picking) m_picking = false; if (m_resizing) m_resizing = false; break; default: break; } } void CanvasModePen::on_Draw(const glm::mat4& ortho, const glm::mat4& proj, const glm::mat4& camera) { if (m_draw_tip) { const auto& brush = Canvas::I->m_current_brush; auto pos = m_resizing ? m_size_pos_start : m_cur_pos; //if (App::I->keys[(int)kKey::KeyAlt] && !m_resizing) // pos.x = pos.x - brush->m_tip_size * .5f; 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)); glm::vec2 tip_offset = glm::vec2(0); auto tip_color = glm::vec4(glm::vec3(brush->m_tip_color), 1.f); if (Canvas::I->m_current_stroke) { const auto& s = Canvas::I->m_current_stroke->m_prev_sample; if (s.size > 0.f) { tip_scale = App::I->zoom * (brush->m_tip_size * tip_scale_fix) * s.scale; tip_angle = s.angle; tip_offset = s.pos - s.origin; tip_color = glm::vec4(s.col, s.flow); } } glm::u8vec4 pixel; std::int32_t fb_width = static_cast(App::I->width); std::int32_t fb_height = static_cast(App::I->height); if (node->m_density != 1.f) { fb_width = node->m_rtt.getWidth(); fb_height = node->m_rtt.getHeight(); } read_canvas_mode_pixel( static_cast((pos.x / App::I->width) * fb_width), static_cast(((App::I->height - pos.y - 1) / App::I->height) * fb_height), pixel); bool outline = glm::min(tip_scale.x, tip_scale.y) < 20 || m_resizing ? false : m_draw_outline; pp::panopainter::setup_legacy_vr_stroke_preview_shader({ .texture_slot = 0, .alpha = brush->m_tip_flow * brush->m_tip_opacity, .draw_outline = outline, .color = outline ? glm::vec4(1.f - glm::vec3(pixel) / 255.f, 1.f) : tip_color, .mvp = glm::scale(glm::vec3(1, -1, 1)) * ortho * glm::translate(glm::vec3(pos + tip_offset, 0)) * glm::eulerAngleZ(tip_angle) * glm::scale(glm::vec3(tip_scale, 1)), }); const bool blend = query_canvas_mode_capability(pp::renderer::gl::blend_state()); apply_canvas_mode_capability(pp::renderer::gl::blend_state(), true); set_canvas_mode_active_texture_unit(0); 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) apply_canvas_mode_capability(pp::renderer::gl::blend_state(), false); } } void CanvasModePen::leave(kCanvasMode next) { } void CanvasModePen::enter(kCanvasMode prev) { m_cur_pos = Canvas::I->m_cur_pos; } void CanvasModeLine::on_MouseEvent(MouseEvent* me, glm::vec2& loc) { m_draw_tip = App::I->draws_canvas_tip_for_input(me->m_source, me->m_type); if (Canvas::I->m_touch_lock && me->m_source == kEventSource::Touch) return; switch (me->m_type) { case kEventType::MouseDownL: node->mouse_capture(); m_dragging = true; m_drag_start = loc; m_drag_pos = loc; break; case kEventType::MouseUpL: pp::panopainter::release_legacy_mouse_capture(*node); if (m_dragging) { App::I->render_task_async([=] { Canvas::I->stroke_start({ m_drag_start, 0 }, 1.f); Canvas::I->stroke_update({ m_drag_pos, 0 }, 1.f); Canvas::I->stroke_draw(); Canvas::I->stroke_end(); }); } m_dragging = false; break; case kEventType::MouseMove: if (m_dragging) m_drag_pos = loc; m_cur_pos = loc; break; case kEventType::MouseCancel: pp::panopainter::release_legacy_mouse_capture(*node); m_dragging = false; break; default: break; } } void CanvasModeLine::on_Draw(const glm::mat4& ortho, const glm::mat4& proj, const glm::mat4& camera) { if (m_dragging) { pp::panopainter::setup_legacy_vr_color_shader({ .color = Canvas::I->m_current_brush->m_tip_color, .mvp = ortho, }); static glm::vec4 AB[2]; AB[0] = { m_drag_start, 0, 1 }; AB[1] = { m_drag_pos, 0, 1 }; AB[0].y = Canvas::I->m_box.w - AB[0].y - 1; // invert Y AB[1].y = Canvas::I->m_box.w - AB[1].y - 1; // invert Y m_line.update_vertices(AB); m_line.draw_stroke(); } else if (m_draw_tip) { const auto& brush = Canvas::I->m_current_brush; 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); pp::panopainter::setup_legacy_vr_stroke_preview_shader({ .texture_slot = 0, .alpha = brush->m_tip_flow * brush->m_tip_opacity, .draw_outline = false, .color = tip_color, .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)), }); const bool blend = query_canvas_mode_capability(pp::renderer::gl::blend_state()); apply_canvas_mode_capability(pp::renderer::gl::blend_state(), true); set_canvas_mode_active_texture_unit(0); 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) apply_canvas_mode_capability(pp::renderer::gl::blend_state(), false); } } void CanvasModeLine::init() { m_line.create(); } void CanvasModeLine::enter(kCanvasMode prev) { m_cur_pos = Canvas::I->m_cur_pos; } void CanvasModeLine::leave(kCanvasMode next) { }