#include "pch.h" #include "legacy_gl_mesh_dispatch.h" #include "legacy_ui_gl_dispatch.h" #include "node_colorwheel.h" #include "renderer_gl/opengl_capabilities.h" #include "shader.h" #include "log.h" #include "app.h" #include #include #include Node* NodeColorWheel::clone_instantiate() const { return new NodeColorWheel; } void NodeColorWheel::clone_finalize(Node* dest) const { NodeColorWheel* n = (NodeColorWheel*)dest; n->init_controls(); n->m_mouse_ignore = false; } void NodeColorWheel::init() { m_mouse_ignore = false; //init_template("color-picker"); init_controls(); } void NodeColorWheel::init_controls() { } void NodeColorWheel::loaded() { m_circle.create<64>(.5f, .4f, Circle::kUVMapping::Tube); m_cur_hue.create<16>(.05f, 0.04f); m_cur_quad.create<16>(.04f, 0.03f, Circle::kUVMapping::Tube); float quad_scale = glm::sin(glm::radians(45.f)) * 0.8f; m_quad.create<1>(quad_scale, quad_scale); struct vertex_t { glm::vec4 pos; glm::vec2 uvs; glm::vec4 col; }; std::vector vertices; float l = 0.4f; vertices.push_back({{glm::cos(4.f/3.f*glm::pi())*l,glm::sin(4.f/3.f*glm::pi())*l,0,1},{1,-1},{1,1,1,1}}); vertices.push_back({{glm::cos(2.f/3.f*glm::pi())*l,glm::sin(2.f/3.f*glm::pi())*l,0,1},{0,0},{0,0,0,1}}); vertices.push_back({{l,0,0,1},{1,1},{1,0,0,1}}); App::I->render_task([&] { const auto attribute_type = pp::renderer::gl::vertex_attribute_float_component_type(); const auto attribute_normalized = static_cast(pp::renderer::gl::vertex_attribute_not_normalized()); const std::array attributes { pp::renderer::gl::OpenGlVertexAttribute { .index = 0U, .component_count = 4, .component_type = attribute_type, .normalized = attribute_normalized, .stride = static_cast(sizeof(vertex_t)), .offset = 0U, }, pp::renderer::gl::OpenGlVertexAttribute { .index = 1U, .component_count = 2, .component_type = attribute_type, .normalized = attribute_normalized, .stride = static_cast(sizeof(vertex_t)), .offset = static_cast(offsetof(vertex_t, uvs)), }, pp::renderer::gl::OpenGlVertexAttribute { .index = 2U, .component_count = 4, .component_type = attribute_type, .normalized = attribute_normalized, .stride = static_cast(sizeof(vertex_t)), .offset = static_cast(offsetof(vertex_t, col)), }, }; const auto mesh = pp::legacy::gl_mesh::create_mesh_objects( pp::renderer::gl::OpenGlMeshUpload { .vertex_data = vertices.data(), .vertex_byte_count = static_cast(vertices.size() * sizeof(vertex_t)), .indexed = false, .vertex_array_count = 1U, .attributes = attributes, }, "NodeColorWheel::loaded"); buffers = static_cast(mesh.vertex_buffer); arrays = static_cast(mesh.vertex_arrays[0]); }); } void NodeColorWheel::draw() { pp::legacy::ui_gl::set_blend_enabled(false, "NodeColorWheel"); ShaderManager::use(kShader::ColorHue); ShaderManager::u_mat4(kShaderUniform::MVP, m_mvp * glm::eulerAngleZ(glm::radians(-90.f))); ShaderManager::u_int(kShaderUniform::Direction, 0); // set horizontal m_circle.draw_fill(); ShaderManager::use(kShader::Color); ShaderManager::u_mat4(kShaderUniform::MVP, m_mvp * glm::eulerAngleZ(glm::radians(-360.f * m_hsv.x)) * glm::translate(glm::vec3(.45f,0.f,0.f))); ShaderManager::u_vec4(kShaderUniform::Col, {convert_hsv2rgb({glm::fract(m_hsv.x + 0.5f), 1.f, 1.f}), 1.f}); m_cur_hue.draw_stroke(); ShaderManager::use(kShader::ColorQuad); ShaderManager::u_mat4(kShaderUniform::MVP, m_mvp); ShaderManager::u_vec4(kShaderUniform::Col, glm::vec4(m_hsv, 0.f)); m_quad.draw_fill(); float quad_scale = glm::sin(glm::radians(45.f)) * 0.8f; glm::vec3 pos = glm::vec3(glm::vec2(m_hsv.y, 1.f - m_hsv.z) - 0.5f, 0); ShaderManager::use(kShader::Color); ShaderManager::u_mat4(kShaderUniform::MVP, m_mvp * glm::translate(pos * quad_scale)); ShaderManager::u_vec4(kShaderUniform::Col, {convert_hsv2rgb({glm::fract(m_hsv.x + 0.5f), 1.f, 1.f}), 1.f}); m_cur_quad.draw_fill(); } glm::vec4 NodeColorWheel::get_quad_rect() const { float quad_scale = glm::sin(glm::radians(45.f)) * 0.8f; glm::vec2 size = m_size * quad_scale; glm::vec2 pos = (m_size - size) * 0.5f; return glm::vec4(pos, size); } bool NodeColorWheel::inside_quad(glm::vec2 pos, glm::vec2& out_coord) const { auto r = get_quad_rect(); out_coord = (pos - xy(r)) / zw(r); return point_in_rect(pos, r); } void NodeColorWheel::handle_color_change() { if (on_value_changed) on_value_changed(this, m_hsv); } kEventResult NodeColorWheel::handle_event(Event* e) { Node::handle_event(e); auto* me = static_cast(e); switch (e->m_type) { case kEventType::MouseDownL: { m_old_value = m_hsv; dragging = true; mouse_capture(); auto pos = (me->m_pos - m_pos - GetSize() * 0.5f) / GetSize(); float l = glm::length(pos); glm::vec2 quad_pos(0); if (inside_quad(me->m_pos - m_pos, quad_pos)) { mode = 2; m_hsv.y = glm::clamp(quad_pos.x, 0.f, 1.f); m_hsv.z = 1.f - glm::clamp(quad_pos.y, 0.f, 1.f); handle_color_change(); } else if (l >= 0.4f && l <= 0.5f) { mode = 1; auto normalized_pos = glm::normalize(me->m_pos - m_pos - GetSize() * 0.5f); m_hsv.x = (glm::atan(normalized_pos.y, -normalized_pos.x) + glm::pi()) / glm::two_pi(); handle_color_change(); } else { mode = 0; } } break; case kEventType::MouseUpL: mouse_release(); dragging = false; break; case kEventType::MouseMove: if (dragging) { if (mode == 1) { auto pos = glm::normalize(me->m_pos - m_pos - GetSize() * 0.5f); m_hsv.x = (glm::atan(pos.y, -pos.x) + glm::pi()) / glm::two_pi(); handle_color_change(); } else if (mode == 2) { glm::vec2 quad_pos(0); inside_quad(me->m_pos - m_pos, quad_pos); m_hsv.y = glm::clamp(quad_pos.x, 0.f, 1.f); m_hsv.z = 1.f - glm::clamp(quad_pos.y, 0.f, 1.f); handle_color_change(); } } break; case kEventType::MouseCancel: mouse_release(); dragging = false; m_hsv = m_old_value; handle_color_change(); break; default: return kEventResult::Available; break; } return kEventResult::Consumed; }