Added glm. Updated widget to expose mouse focus. Added custom renderer with stippled line.

This commit is contained in:
2023-05-03 12:41:54 +03:00
parent d729454f8a
commit ad0a80eb85
9 changed files with 546 additions and 140 deletions
+122 -134
View File
@@ -51,9 +51,18 @@
#include <stb_image.h>
#include "grbl.h"
#include <gtest/gtest.h>
#include <regex>
#include "grbl_communication.h"
#include "grbl_machine.h"
#include "string_utils.h"
#include "render.h"
#include <glm/vec3.hpp> // glm::vec3
#include <glm/vec4.hpp> // glm::vec4
#include <glm/mat4x4.hpp> // glm::mat4
#include <glm/ext/matrix_transform.hpp> // glm::translate, glm::rotate, glm::scale
#include <glm/ext/matrix_clip_space.hpp> // glm::perspective
#include <glm/ext/scalar_constants.hpp> // glm::pi
using namespace nanogui;
@@ -74,6 +83,13 @@ public:
grbl::program pgm;
Button *btnLoadProgram, *btnCheckProgram, *btnRunProgram;
grbl::program_renderer renderer;
glm::vec3 cam_target = glm::vec3(0);
glm::vec3 cam_src = glm::vec3(0);
glm::vec2 cam_rotate = {0, 0};
SenderApp() : Screen(Vector2i(1024, 768), "GRBL Sender") {
inc_ref();
window = new Window(this, "Machine status");
@@ -150,8 +166,9 @@ public:
btnLoadProgram = new Button(pgm_actions, "Load");
btnLoadProgram->set_callback([&] {
auto path = file_dialog(
{{"nc", "G-Code files"},
{"ngc", "G-Code files"}}, false);
{{"gcode", "G-Code files"},
{"nc", "G-Code files"},
{"ngc", "G-Code files"}}, true);
btnCheckProgram->set_background_color(colBg);
btnRunProgram->set_background_color(colBg);
@@ -159,6 +176,16 @@ public:
if (pgm.load_from_file(path)) {
btnCheckProgram->set_enabled(true);
// btnRunProgram->set_enabled(true);
renderer.update(pgm, cnc);
auto max_pos = renderer.get_extents_max();
auto min_pos = renderer.get_extents_min();
cam_target = (max_pos - min_pos) / 2.0f;
cam_src = cam_target;
cam_src.z = (max_pos.x - min_pos.x);
cam_rotate = {0, 0};
} else {
btnCheckProgram->set_enabled(false);
btnRunProgram->set_enabled(false);
@@ -180,51 +207,51 @@ public:
});
btnRunProgram->set_tooltip("Execute program");
// Alternative construction notation using variadic template
btnLoadProgram = window->add<Button>("Styled", FA_ROCKET);
btnLoadProgram->set_background_color(Color(0, 0, 255, 25));
btnLoadProgram->set_callback([] { std::cout << "pushed!" << std::endl; });
btnLoadProgram->set_tooltip("This button has a fairly long tooltip. It is so long, in "
"fact, that the shown text will span several lines.");
new Label(window, "Toggle buttons", "sans-bold");
btnLoadProgram = new Button(window, "Toggle me");
btnLoadProgram->set_flags(Button::ToggleButton);
btnLoadProgram->set_change_callback([](bool state) { std::cout << "Toggle button state: " << state << std::endl; });
new Label(window, "Radio buttons", "sans-bold");
btnLoadProgram = new Button(window, "Radio button 1");
btnLoadProgram->set_flags(Button::RadioButton);
btnLoadProgram = new Button(window, "Radio button 2");
btnLoadProgram->set_flags(Button::RadioButton);
new Label(window, "A tool palette", "sans-bold");
Widget *tools = new Widget(window);
tools->set_layout(new BoxLayout(Orientation::Horizontal,
Alignment::Middle, 0, 6));
btnLoadProgram = new ToolButton(tools, FA_CLOUD);
btnLoadProgram = new ToolButton(tools, FA_FAST_FORWARD);
btnLoadProgram = new ToolButton(tools, FA_COMPASS);
btnLoadProgram = new ToolButton(tools, FA_UTENSILS);
new Label(window, "Popup buttons", "sans-bold");
PopupButton *popup_btn = new PopupButton(window, "Popup", FA_FLASK);
Popup *popup = popup_btn->popup();
popup->set_layout(new GroupLayout());
new Label(popup, "Arbitrary widgets can be placed here");
new CheckBox(popup, "A check box");
// popup right
popup_btn = new PopupButton(popup, "Recursive popup", FA_CHART_PIE);
Popup *popup_right = popup_btn->popup();
popup_right->set_layout(new GroupLayout());
new CheckBox(popup_right, "Another check box");
// popup left
popup_btn = new PopupButton(popup, "Recursive popup", FA_DNA);
popup_btn->set_side(Popup::Side::Left);
Popup *popup_left = popup_btn->popup();
popup_left->set_layout(new GroupLayout());
new CheckBox(popup_left, "Another check box");
// // Alternative construction notation using variadic template
// btnLoadProgram = window->add<Button>("Styled", FA_ROCKET);
// btnLoadProgram->set_background_color(Color(0, 0, 255, 25));
// btnLoadProgram->set_callback([] { std::cout << "pushed!" << std::endl; });
// btnLoadProgram->set_tooltip("This button has a fairly long tooltip. It is so long, in "
// "fact, that the shown text will span several lines.");
//
// new Label(window, "Toggle buttons", "sans-bold");
// btnLoadProgram = new Button(window, "Toggle me");
// btnLoadProgram->set_flags(Button::ToggleButton);
// btnLoadProgram->set_change_callback([](bool state) { std::cout << "Toggle button state: " << state << std::endl; });
//
// new Label(window, "Radio buttons", "sans-bold");
// btnLoadProgram = new Button(window, "Radio button 1");
// btnLoadProgram->set_flags(Button::RadioButton);
// btnLoadProgram = new Button(window, "Radio button 2");
// btnLoadProgram->set_flags(Button::RadioButton);
//
// new Label(window, "A tool palette", "sans-bold");
// Widget *tools = new Widget(window);
// tools->set_layout(new BoxLayout(Orientation::Horizontal,
// Alignment::Middle, 0, 6));
//
// btnLoadProgram = new ToolButton(tools, FA_CLOUD);
// btnLoadProgram = new ToolButton(tools, FA_FAST_FORWARD);
// btnLoadProgram = new ToolButton(tools, FA_COMPASS);
// btnLoadProgram = new ToolButton(tools, FA_UTENSILS);
//
// new Label(window, "Popup buttons", "sans-bold");
// PopupButton *popup_btn = new PopupButton(window, "Popup", FA_FLASK);
// Popup *popup = popup_btn->popup();
// popup->set_layout(new GroupLayout());
// new Label(popup, "Arbitrary widgets can be placed here");
// new CheckBox(popup, "A check box");
// // popup right
// popup_btn = new PopupButton(popup, "Recursive popup", FA_CHART_PIE);
// Popup *popup_right = popup_btn->popup();
// popup_right->set_layout(new GroupLayout());
// new CheckBox(popup_right, "Another check box");
// // popup left
// popup_btn = new PopupButton(popup, "Recursive popup", FA_DNA);
// popup_btn->set_side(Popup::Side::Left);
// Popup *popup_left = popup_btn->popup();
// popup_left->set_layout(new GroupLayout());
// new CheckBox(popup_left, "Another check box");
perform_layout();
@@ -237,81 +264,8 @@ public:
m_render_pass = new RenderPass({this});
m_render_pass->set_clear_color(0, Color(0.3f, 0.3f, 0.32f, 1.f));
m_shader = new Shader(
m_render_pass,
/* An identifying name */
"a_simple_shader",
#if defined(NANOGUI_USE_OPENGL)
R"(/* Vertex shader */
#version 330
uniform mat4 mvp;
in vec3 position;
void main() {
gl_Position = mvp * vec4(position, 1.0);
})",
/* Fragment shader */
R"(#version 330
out vec4 color;
uniform float intensity;
void main() {
color = vec4(vec3(intensity), 1.0);
})"
#elif defined(NANOGUI_USE_GLES)
R"(/* Vertex shader */
precision highp float;
uniform mat4 mvp;
attribute vec3 position;
void main() {
gl_Position = mvp * vec4(position, 1.0);
})",
/* Fragment shader */
R"(precision highp float;
uniform float intensity;
void main() {
gl_FragColor = vec4(vec3(intensity), 1.0);
})"
#elif defined(NANOGUI_USE_METAL)
R"(using namespace metal;
struct VertexOut {
float4 position [[position]];
};
vertex VertexOut vertex_main(const device packed_float3 *position,
constant float4x4 &mvp,
uint id [[vertex_id]]) {
VertexOut vert;
vert.position = mvp * float4(position[id], 1.f);
return vert;
})",
/* Fragment shader */
R"(using namespace metal;
fragment float4 fragment_main(const constant float &intensity) {
return float4(intensity);
})"
#endif
);
uint32_t indices[3 * 2] = {
0, 1, 2,
2, 3, 0
};
float positions[3 * 4] = {
-1.f, -1.f, 0.f,
1.f, -1.f, 0.f,
1.f, 1.f, 0.f,
-1.f, 1.f, 0.f
};
m_shader->set_buffer("indices", VariableType::UInt32, {3 * 2}, indices);
m_shader->set_buffer("position", VariableType::Float32, {4, 3}, positions);
m_shader->set_uniform("intensity", 0.5f);
m_render_pass->set_depth_test(RenderPass::DepthTest::Always, true);
m_render_pass->set_cull_mode(RenderPass::CullMode::Disabled);
}
bool resize_event(const Vector2i& size) override {
@@ -392,10 +346,11 @@ public:
bool keyboard_event(int key, int scancode, int action, int modifiers) override {
if (Screen::keyboard_event(key, scancode, action, modifiers))
return true;
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) {
set_visible(false);
return true;
}
// if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) {
// set_visible(false);
// return true;
// }
auto new_jog = jog;
@@ -471,6 +426,34 @@ public:
return false;
}
bool mouse_motion_event(const Vector2i& p, const Vector2i& rel, int button, int modifiers) override {
auto result = Widget::mouse_motion_event(p, rel, button, modifiers);
if (window->mouse_focused()) {
return result;
} else {
std::cout << "Mouse motion p:" << p << ", rel:" << rel << ", button:" << button << ", .modifiers:" << modifiers << std::endl;
if (button == 1) {
cam_rotate += glm::vec2((float) rel.x() / 100.0f, (float) rel.y() / 100.0f);
} else if (button == 2) {
cam_src.x += (float) rel.x() / 10.0f;
cam_src.y += (float) rel.y() / 10.0f;
}
return true;
}
}
bool scroll_event(const Vector2i& p, const Vector2f& rel) override {
if (window->mouse_focused()) {
return Widget::scroll_event(p, rel);
} else {
std::cout << "Scroll event: p:" << p << ", rel:" << rel << std::endl;
cam_src.z += rel.y();
cam_src.z = std::max(cam_src.z, 0.1f);
return true;
}
}
virtual void draw(NVGcontext *ctx) {
// Animate the scrollbar
// m_progress->set_value(std::fmod((float) glfwGetTime() / 10, 1.0f));
@@ -479,26 +462,31 @@ public:
Screen::draw(ctx);
}
virtual void draw_contents() {
Matrix4f mvp = Matrix4f::scale(Vector3f(
(float) m_size.y() / (float) m_size.x() * 0.25f, 0.25f, 0.25f)) *
Matrix4f::rotate(Vector3f(0, 0, 1), (float) glfwGetTime());
auto fb_size = framebuffer_size();
m_shader->set_uniform("mvp", mvp);
renderer.update(pgm, cnc);
// compute mvp
glm::mat4 projection = glm::perspective(45.0f * glm::pi<float>() / 180.0f, (float) fb_size.x() / (float) fb_size.y(), 0.1f, 1000.f);
glm::mat4 view = glm::lookAt(cam_src, cam_target, glm::vec3{0.0f, 1.0f, 0.0f});
view = glm::rotate(view, cam_rotate.y, glm::vec3(-1.0f, 0.0f, 0.0f));
view = glm::rotate(view, cam_rotate.x, glm::vec3(0.0f, 1.0f, 0.0f));
glm::mat4 model = glm::mat4(1.0f);
auto mvp = projection * view * model;
// start rendering
m_render_pass->resize(framebuffer_size());
m_render_pass->begin();
m_shader->begin();
m_shader->draw_array(Shader::PrimitiveType::Triangle, 0, 6, true);
m_shader->end();
renderer.render(mvp, glm::vec2(fb_size.x(), fb_size.y()));
m_render_pass->end();
}
private:
ProgressBar *m_progress;
ref<Shader> m_shader;
ref<RenderPass> m_render_pass;
using ImageHolder = std::unique_ptr<uint8_t[], void (*)(void *)>;