Introduced machine state handlers (check and run still need work).

Added proper init handler, fetching settings and parameters and exposing them to UI.
Added spindle rendering.
This commit is contained in:
2023-05-04 14:15:33 +03:00
parent a63d58a1ec
commit cacbe1b8aa
5 changed files with 842 additions and 200 deletions
+173 -79
View File
@@ -1,16 +1,3 @@
/*
src/example1.cpp -- C++ version of an example application that shows
how to use the various widget classes. For a Python implementation, see
'../python/example1.py'.
NanoGUI was developed by Wenzel Jakob <wenzel.jakob@epfl.ch>.
The widget drawing code is based on the NanoVG demo application
by Mikko Mononen.
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE.txt file.
*/
#include <nanogui/opengl.h>
#include <nanogui/screen.h>
#include <nanogui/window.h>
@@ -22,6 +9,8 @@
#include <nanogui/messagedialog.h>
#include <nanogui/texture.h>
#include <nanogui/textarea.h>
#include <nanogui/textbox.h>
#include <nanogui/tabwidget.h>
#include <nanogui/shader.h>
#include <nanogui/renderpass.h>
#include <iostream>
@@ -43,6 +32,7 @@
#include "string_utils.h"
#include "render.h"
#include "glm/gtx/quaternion.hpp"
#include "nanogui/nanogui.h"
#include <glm/ext/quaternion_float.hpp>
#include <glm/ext/quaternion_trigonometric.hpp>
#include <glm/vec3.hpp> // glm::vec3
@@ -77,58 +67,152 @@ public:
float cam_zoom = 0;
glm::quat cam_src_rotation = glm::quat(1.0, 0.0, 0.0, 0.0); // identity quaternion
void init_program_geometry() {
renderer.update(pgm, cnc);
TabWidget *tab_widget;
VScrollPanel *settings_vscroll;
Widget *settings_layer;
auto max_pos = renderer.get_extents_max();
auto min_pos = renderer.get_extents_min();
VScrollPanel *parameters_vscroll;
Widget *parameters_layer;
TextBox *mpos_x_text, *mpos_y_text, *mpos_z_text;
cam_target = (max_pos - min_pos) / 2.0f;
cam_zoom = (max_pos.x - min_pos.x);
cam_src_rotation = glm::quat(1.0, 0.0, 0.0, 0.0);
void fill_in_settings() {
settings_vscroll = new VScrollPanel(tab_widget);
tab_widget->append_tab("Settings", settings_vscroll);
settings_layer = new Widget(settings_vscroll);
settings_layer->set_layout(new GridLayout(Orientation::Horizontal, 1, Alignment::Middle));
auto& settings = cnc.get_settings();
for (auto& s: settings) {
auto w = settings_layer->add<Widget>();
w->set_layout(new BoxLayout(Orientation::Horizontal, Alignment::Middle, 2, 2));
auto x = w->add<Label>(s.first, "sans-bold", 20);
x->set_fixed_width(40);
auto desc = grbl::setting_description(std::stoi(s.first.substr(1)));
auto y = w->add<TextBox>(s.second);
y->set_editable(true);
y->set_tooltip(desc);
y->set_fixed_width(200);
auto z = w->add<ToolButton>(FA_SAVE);
z->set_flags(Button::Flags::NormalButton); // no toggle, please
z->set_tooltip("save");
auto t = w->add<TextArea>();
t->set_fixed_width(200);
t->set_fixed_height(20);
t->clear();
t->append(desc.substr(0, desc.find_first_of('\n')));
}
}
void fill_in_parameters() {
parameters_vscroll = new VScrollPanel(tab_widget);
tab_widget->append_tab("Parameters", parameters_vscroll);
parameters_layer = new Widget(parameters_vscroll);
parameters_layer->set_layout(new GridLayout(Orientation::Horizontal, 1, Alignment::Middle));
auto& parameters = cnc.get_parameters();
for (auto& entry: parameters) {
auto w = parameters_layer->add<Widget>();
w->set_layout(new BoxLayout(Orientation::Horizontal, Alignment::Middle, 2, 2));
auto x = w->add<Label>(entry.first, "sans-bold", 20);
x->set_fixed_width(50);
auto y = w->add<TextBox>(entry.second);
y->set_editable(true);
y->set_fixed_width(200);
auto z = w->add<ToolButton>(FA_SAVE);
z->set_flags(Button::Flags::NormalButton); // no toggle, please
z->set_tooltip("save");
}
}
SenderApp() : Screen(Vector2i(1024, 768), "GRBL Sender") {
inc_ref();
window = new Window(this, "Machine status");
// window->set_fixed_height(Screen::size().y());
window->set_position(Vector2i(0, 0));
window->set_layout(new GroupLayout());
// window->set_size(Screen::size());
// save regular button color
auto b = new Button(this);
colBg = b->background_color();
b->set_visible(false);
colBg = theme()->m_button_gradient_bot_focused;
// create main window
window = new Window(this, "Machine status");
window->set_fixed_height((Screen::size().y() - 40) / 2);
window->set_position(Vector2i(0, 0));
window->set_layout(new BoxLayout(nanogui::Orientation::Vertical));
tab_widget = window->add<TabWidget>();
tab_widget->set_callback([&](int index) {
if (index == 1 || index == 2) {
perform_layout();
}
tab_widget->set_selected_index(index);
});
tab_widget->set_fixed_height((this->height() - 100) / 2);
Widget *layer = new Widget(tab_widget);
layer->set_layout(new GroupLayout());
tab_widget->append_tab("Info", layer);
// Widget *layer3 = new Widget(tab_widget);
// tab_widget->append_tab("Offsets", layer3);
// layer3->set_layout(new GroupLayout());
// layer3->add<Label>("Parameters");
// layer3->add<TextBox>();
new Label(window, "Status", "sans-bold");
Widget *status_holder = new Widget(window);
new Label(layer, "Status", "sans-bold");
Widget *status_holder = new Widget(layer);
status_holder->set_layout(new GridLayout());
lblStatus = new TextArea(window);
lblStatus = new TextArea(layer);
lblStatus->set_fixed_height(20);
lblStatus->set_font("sans");
lblSubstatus = new TextArea(window);
lblSubstatus = new TextArea(layer);
lblSubstatus->set_font("sans");
lblSubstatus->set_fixed_height(50);
// Machine pos
new Label(window, "Machine pos", "sans-bold");
Widget *mpos = new Widget(window);
mpos->set_layout(new GridLayout());
layer->add<Label>("Machine pos", "sans-bold");
Widget *mpos = new Widget(layer);
mpos->set_layout(new GridLayout(Orientation::Horizontal, 1, Alignment::Middle));
new Label(mpos, "X");
m_pos_x = new Label(mpos, std::to_string(cnc.get_status().machine_pos[0]));
new Label(mpos, "Y");
m_pos_y = new Label(mpos, std::to_string(cnc.get_status().machine_pos[1]));
new Label(mpos, "Z");
m_pos_z = new Label(mpos, std::to_string(cnc.get_status().machine_pos[2]));
auto x_holder = mpos->add<Widget>();
x_holder->set_layout(new BoxLayout(Orientation::Horizontal));
auto lbl = x_holder->add<Label>("X");
lbl->set_font_size(20);
lbl->set_fixed_width(50);
mpos_x_text = x_holder->add<TextBox>(std::to_string(cnc.get_status().work_pos[0]));
mpos_x_text->set_fixed_width(200);
auto y_holder = mpos->add<Widget>();
y_holder->set_layout(new BoxLayout(Orientation::Horizontal));
lbl = y_holder->add<Label>("Y");
lbl->set_font_size(20);
lbl->set_fixed_width(50);
mpos_y_text = y_holder->add<TextBox>(std::to_string(cnc.get_status().work_pos[1]));
mpos_y_text->set_fixed_width(200);
auto z_holder = mpos->add<Widget>();
z_holder->set_layout(new BoxLayout(Orientation::Horizontal));
lbl = z_holder->add<Label>("Z");
lbl->set_font_size(20);
lbl->set_fixed_width(50);
mpos_z_text = z_holder->add<TextBox>(std::to_string(cnc.get_status().work_pos[0]));
mpos_z_text->set_fixed_width(200);
// buttons to change state
new Label(window, "Actions", "sans-bold");
Widget *actions = new Widget(window);
new Label(layer, "Actions", "sans-bold");
Widget *actions = new Widget(layer);
actions->set_layout(new BoxLayout(Orientation::Horizontal));
Button *btnUnlock = new Button(actions, "Unlock");
@@ -155,9 +239,9 @@ public:
// No need to store a pointer, the data structure will be automatically
// freed when the parent window is deleted
new Label(window, "Program", "sans-bold");
new Label(layer, "Program", "sans-bold");
Widget *pgm_actions = new Widget(window);
Widget *pgm_actions = new Widget(layer);
pgm_actions->set_layout(new BoxLayout(Orientation::Horizontal));
@@ -196,6 +280,7 @@ 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));
@@ -257,6 +342,17 @@ public:
m_render_pass->set_cull_mode(RenderPass::CullMode::Disabled);
}
void init_program_geometry() {
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_zoom = (max_pos.x - min_pos.x);
cam_src_rotation = glm::quat(1.0, 0.0, 0.0, 0.0);
}
bool resize_event(const Vector2i& size) override {
return Screen::resize_event(size);
}
@@ -270,6 +366,11 @@ public:
grbl::realtime_status_report last_report;
void on_init_completed() override {
fill_in_settings();
fill_in_parameters();
}
void on_realtime_status_report(grbl::realtime_status_report report) override {
if (report == last_report) return;
@@ -285,9 +386,10 @@ public:
}
}
m_pos_x->set_caption(std::to_string(cnc.get_status().machine_pos[0]));
m_pos_y->set_caption(std::to_string(cnc.get_status().machine_pos[1]));
m_pos_z->set_caption(std::to_string(cnc.get_status().machine_pos[2]));
mpos_x_text->set_value(std::to_string(cnc.get_status().work_pos[0]));
mpos_y_text->set_value(std::to_string(cnc.get_status().work_pos[1]));
mpos_z_text->set_value(std::to_string(cnc.get_status().work_pos[2]));
last_report = report;
}
@@ -341,6 +443,11 @@ public:
// return true;
// }
if (key == GLFW_KEY_SPACE && action == GLFW_PRESS && !window->mouse_focused()) {
// reset trackball rotation
cam_src_rotation = glm::quat(1, 0, 0, 0);
}
auto new_jog = jog;
if (key == GLFW_KEY_LEFT_SHIFT) {
@@ -443,50 +550,37 @@ public:
return Widget::scroll_event(p, rel);
} else {
// std::cout << "Scroll event: p:" << p << ", rel:" << rel << std::endl;
cam_zoom -= rel.y() * cam_zoom/10.0f;
cam_zoom -= rel.y() * cam_zoom / 10.0f;
cam_zoom = std::max(cam_zoom, 0.1f);
return true;
}
}
virtual void draw(NVGcontext *ctx) {
// Animate the scrollbar
// m_progress->set_value(std::fmod((float) glfwGetTime() / 10, 1.0f));
// Draw the user interface
Screen::draw(ctx);
}
virtual void draw_contents() {
auto fb_size = framebuffer_size();
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::vec3 cam_src = cam_target + glm::vec3(glm::vec4(0, 0, cam_zoom, 1) * cam_src_rotation);
// glm::mat4 view = glm::lookAt(cam_src, cam_target, glm::vec3{0.0f, 1.0f, 0.0f});
// glm::mat4 view = glm::rotate(glm::mat4(1.0f), glm::pi<float>()/2.0f, glm::vec3(1, 0, 0));
// glm::mat4 view = glm::toMat4(cam_src_rotation) * glm::rotate(glm::mat4(1.0f), glm::pi<float>()/2.0f, glm::vec3(1, 0, 0)) * glm::translate(glm::mat4(1.0f), -cam_target);
// glm::mat4 view = glm::translate(glm::mat4(1.0f), glm::vec3(0, 0, -cam_zoom)) * glm::toMat4(cam_src_rotation) * glm::rotate(glm::mat4(1.0f), glm::pi<float>()/2.0f, glm::vec3(1, 0, 0)) * glm::translate(glm::mat4(1.0f), -cam_target);
glm::mat4 view = glm::translate(glm::mat4(1.0f), glm::vec3(0, 0, -cam_zoom)) *
glm::toMat4(cam_src_rotation) *
// glm::rotate(glm::mat4(1.0f), glm::pi<float>()/2.0f, glm::vec3(1, 0, 0)) *
glm::translate(glm::mat4(1.0f), -cam_target);
// glm::mat4 view = glm::rotate(glm::mat4(1.0f), -glm::pi<float>()/2.0f, glm::vec3(1, 0, 0)) * glm::translate(glm::mat4(1.0f), -cam_src);
glm::mat4 model = glm::mat4(1.0f);
auto mvp = projection * view * model;
// start rendering
m_render_pass->resize(framebuffer_size());
m_render_pass->begin();
renderer.render(mvp, glm::vec2(fb_size.x(), fb_size.y()));
if (pgm.is_loaded) {
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,
10000.f);
glm::mat4 view = glm::translate(glm::mat4(1.0f), glm::vec3(0, 0, -cam_zoom)) *
glm::toMat4(cam_src_rotation) *
glm::translate(glm::mat4(1.0f), -cam_target);
glm::mat4 model = glm::mat4(1.0f);
auto mvp = projection * view * model;
renderer.render(mvp, glm::vec2(fb_size.x(), fb_size.y()));
}
m_render_pass->end();
}