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:
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user