/* 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 . 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define STB_IMAGE_STATIC #define STB_IMAGE_IMPLEMENTATION #if defined(_MSC_VER) # pragma warning (disable: 4505) // don't warn about dead code in stb_image.h #elif defined(__GNUC__) # pragma GCC diagnostic ignored "-Wunused-function" #endif #include #include "grbl.h" #include #include #include "grbl_communication.h" #include "grbl_machine.h" #include "string_utils.h" #include "render.h" #include // glm::vec3 #include // glm::vec4 #include // glm::mat4 #include // glm::translate, glm::rotate, glm::scale #include // glm::perspective #include // glm::pi using namespace nanogui; grbl::machine cnc{}; class SenderApp : public Screen, public grbl::machine_listener { public: Window *window; grbl::jog_state jog; Label *m_pos_x, *m_pos_y, *m_pos_z; TextArea *lblStatus, *lblSubstatus; nanogui::Color colRed = nanogui::Color(255, 0, 0, 255); nanogui::Color colGreen = nanogui::Color(0, 255, 0, 255); nanogui::Color colBg; int last_alarm = 0; 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"); // 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); new Label(window, "Status", "sans-bold"); Widget *status_holder = new Widget(window); status_holder->set_layout(new GridLayout()); lblStatus = new TextArea(window); lblStatus->set_fixed_height(20); lblStatus->set_font("sans"); lblSubstatus = new TextArea(window); 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()); 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])); // buttons to change state new Label(window, "Actions", "sans-bold"); Widget *actions = new Widget(window); actions->set_layout(new BoxLayout(Orientation::Horizontal)); Button *btnUnlock = new Button(actions, "Unlock"); btnUnlock->set_callback([&] { cnc.request_unlock(); }); Button *btnHome = new Button(actions, "Home"); btnHome->set_callback([&] { cnc.request_home(); }); Button *btnReset = new Button(actions, "Reset"); btnReset->set_background_color(colRed); btnReset->set_callback([&] { cnc.request_reset(); }); Button *btnCycleStart = new Button(actions, "Cycle Start"); btnCycleStart->set_callback([&] { cnc.request_cycle_start(); }); Button *btnFeedHold = new Button(actions, "Feed Hold"); btnFeedHold->set_callback([&] { cnc.request_feed_hold(); }); // 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"); Widget *pgm_actions = new Widget(window); pgm_actions->set_layout(new BoxLayout(Orientation::Horizontal)); btnLoadProgram = new Button(pgm_actions, "Load"); btnLoadProgram->set_callback([&] { auto path = file_dialog( {{"gcode", "G-Code files"}, {"nc", "G-Code files"}, {"ngc", "G-Code files"}}, true); btnCheckProgram->set_background_color(colBg); btnRunProgram->set_background_color(colBg); 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); } }); btnLoadProgram->set_tooltip("Load program"); btnCheckProgram = new Button(pgm_actions, "Check"); btnCheckProgram->set_enabled(false); btnCheckProgram->set_callback([&] { cnc.check_program(pgm); }); btnCheckProgram->set_tooltip("Check program"); btnRunProgram = new Button(pgm_actions, "Run"); btnRunProgram->set_enabled(false); btnRunProgram->set_callback([&] { cnc.run_program(pgm); }); btnRunProgram->set_tooltip("Execute program"); // // Alternative construction notation using variadic template // btnLoadProgram = window->add