imgui: Refactor, use in cut gizmo

This commit is contained in:
Vojtech Kral 2018-11-26 10:56:07 +01:00
parent 763b443459
commit c29493a41b
15 changed files with 315 additions and 157 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

@ -981,19 +981,25 @@ template<class T> static void cut_reset_transform(T *thing) {
thing->set_offset(offset);
}
ModelObjectPtrs ModelObject::cut(size_t instance, coordf_t z)
ModelObjectPtrs ModelObject::cut(size_t instance, coordf_t z, bool keep_upper, bool keep_lower, bool rotate_lower)
{
// Clone the object to duplicate instances, materials etc.
ModelObject* upper = ModelObject::new_clone(*this);
ModelObject* lower = ModelObject::new_clone(*this);
ModelObject* upper = keep_upper ? ModelObject::new_clone(*this) : nullptr;
ModelObject* lower = keep_lower ? ModelObject::new_clone(*this) : nullptr;
if (keep_upper) {
upper->set_model(nullptr);
lower->set_model(nullptr);
upper->sla_support_points.clear();
lower->sla_support_points.clear();
upper->clear_volumes();
lower->clear_volumes();
upper->input_file = "";
}
if (keep_lower) {
lower->set_model(nullptr);
lower->sla_support_points.clear();
lower->clear_volumes();
lower->input_file = "";
}
const auto instance_matrix = instances[instance]->get_matrix(true);
@ -1008,14 +1014,18 @@ ModelObjectPtrs ModelObject::cut(size_t instance, coordf_t z)
const auto bb = instance_bounding_box(instance, true);
z -= bb.min(2);
if (keep_upper) {
for (auto *instance : upper->instances) { cut_reset_transform(instance); }
}
if (keep_lower) {
for (auto *instance : lower->instances) { cut_reset_transform(instance); }
}
for (ModelVolume *volume : volumes) {
if (! volume->is_model_part()) {
// don't cut modifiers
upper->add_volume(*volume);
lower->add_volume(*volume);
if (keep_upper) { upper->add_volume(*volume); }
if (keep_lower) { lower->add_volume(*volume); }
} else {
TriangleMesh upper_mesh, lower_mesh;
@ -1026,18 +1036,22 @@ ModelObjectPtrs ModelObject::cut(size_t instance, coordf_t z)
TriangleMeshSlicer tms(&volume->mesh);
tms.cut(z, &upper_mesh, &lower_mesh);
if (keep_upper) {
upper_mesh.repair();
lower_mesh.repair();
upper_mesh.reset_repair_stats();
}
if (keep_lower) {
lower_mesh.repair();
lower_mesh.reset_repair_stats();
}
if (upper_mesh.facets_count() > 0) {
if (keep_upper && upper_mesh.facets_count() > 0) {
ModelVolume* vol = upper->add_volume(upper_mesh);
vol->name = volume->name;
vol->config = volume->config;
vol->set_material(volume->material_id(), *volume->material());
}
if (lower_mesh.facets_count() > 0) {
if (keep_lower && lower_mesh.facets_count() > 0) {
ModelVolume* vol = lower->add_volume(lower_mesh);
vol->name = volume->name;
vol->config = volume->config;
@ -1046,12 +1060,25 @@ ModelObjectPtrs ModelObject::cut(size_t instance, coordf_t z)
}
}
upper->invalidate_bounding_box();
lower->invalidate_bounding_box();
if (keep_lower && rotate_lower) {
for (auto *instance : lower->instances) {
Geometry::Transformation tr;
tr.set_offset(instance->get_offset());
tr.set_rotation({Geometry::deg2rad(180.0), 0.0, 0.0});
instance->set_transformation(tr);
}
}
ModelObjectPtrs res;
if (upper->volumes.size() > 0) { res.push_back(upper); }
if (lower->volumes.size() > 0) { res.push_back(lower); }
if (keep_upper && upper->volumes.size() > 0) {
upper->invalidate_bounding_box();
res.push_back(upper);
}
if (keep_lower && lower->volumes.size() > 0) {
lower->invalidate_bounding_box();
res.push_back(lower);
}
return res;
}

View File

@ -238,7 +238,7 @@ public:
size_t materials_count() const;
size_t facets_count() const;
bool needed_repair() const;
ModelObjectPtrs cut(size_t instance, coordf_t z);
ModelObjectPtrs cut(size_t instance, coordf_t z, bool keep_upper = true, bool keep_lower = true, bool rotate_lower = false);
void split(ModelObjectPtrs* new_objects);
void repair();

View File

@ -2893,7 +2893,7 @@ void GLCanvas3D::Gizmos::render_current_gizmo_for_picking_pass(const GLCanvas3D:
curr->render_for_picking(selection);
}
void GLCanvas3D::Gizmos::render_overlay(const GLCanvas3D& canvas) const
void GLCanvas3D::Gizmos::render_overlay(const GLCanvas3D& canvas, const GLCanvas3D::Selection& selection) const
{
if (!m_enabled)
return;
@ -2903,17 +2903,19 @@ void GLCanvas3D::Gizmos::render_overlay(const GLCanvas3D& canvas) const
::glPushMatrix();
::glLoadIdentity();
_render_overlay(canvas);
_render_overlay(canvas, selection);
::glPopMatrix();
}
#ifndef ENABLE_IMGUI
void GLCanvas3D::Gizmos::create_external_gizmo_widgets(wxWindow *parent)
{
for (auto &entry : m_gizmos) {
entry.second->create_external_gizmo_widgets(parent);
}
}
#endif // not ENABLE_IMGUI
void GLCanvas3D::Gizmos::_reset()
{
@ -2926,7 +2928,7 @@ void GLCanvas3D::Gizmos::_reset()
m_gizmos.clear();
}
void GLCanvas3D::Gizmos::_render_overlay(const GLCanvas3D& canvas) const
void GLCanvas3D::Gizmos::_render_overlay(const GLCanvas3D& canvas, const GLCanvas3D::Selection& selection) const
{
if (m_gizmos.empty())
return;
@ -3326,7 +3328,9 @@ GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas)
, m_moving(false)
, m_color_by("volume")
, m_reload_delayed(false)
#ifndef ENABLE_IMGUI
, m_external_gizmo_widgets_parent(nullptr)
#endif // not ENABLE_IMGUI
{
if (m_canvas != nullptr)
{
@ -3434,10 +3438,12 @@ bool GLCanvas3D::init(bool useVBOs, bool use_legacy_opengl)
return false;
}
#ifndef ENABLE_IMGUI
if (m_external_gizmo_widgets_parent != nullptr) {
m_gizmos.create_external_gizmo_widgets(m_external_gizmo_widgets_parent);
m_canvas->GetParent()->Layout();
}
#endif // not ENABLE_IMGUI
}
if (!_init_toolbar())
@ -3753,7 +3759,7 @@ void GLCanvas3D::render()
set_tooltip("");
#if ENABLE_IMGUI
wxGetApp().get_imgui().new_frame();
wxGetApp().imgui()->new_frame();
#endif // ENABLE_IMGUI
// picking pass
@ -3799,7 +3805,7 @@ void GLCanvas3D::render()
_render_layer_editing_overlay();
#if ENABLE_IMGUI
wxGetApp().get_imgui().render();
wxGetApp().imgui()->render();
#endif // ENABLE_IMGUI
m_canvas->SwapBuffers();
@ -4462,7 +4468,13 @@ void GLCanvas3D::on_timer(wxTimerEvent& evt)
void GLCanvas3D::on_mouse(wxMouseEvent& evt)
{
#if ENABLE_IMGUI
wxGetApp().get_imgui().update_mouse_data(evt);
auto imgui = wxGetApp().imgui();
if (imgui->update_mouse_data(evt)) {
render();
if (imgui->want_any_input()) {
return;
}
}
#endif // ENABLE_IMGUI
Point pos(evt.GetX(), evt.GetY());
@ -4957,10 +4969,12 @@ void GLCanvas3D::set_tooltip(const std::string& tooltip) const
}
}
#ifndef ENABLE_IMGUI
void GLCanvas3D::set_external_gizmo_widgets_parent(wxWindow *parent)
{
m_external_gizmo_widgets_parent = parent;
}
#endif // not ENABLE_IMGUI
void GLCanvas3D::do_move()
{
@ -5323,7 +5337,7 @@ void GLCanvas3D::_resize(unsigned int w, unsigned int h)
return;
#if ENABLE_IMGUI
wxGetApp().get_imgui().set_display_size((float)w, (float)h);
wxGetApp().imgui()->set_display_size((float)w, (float)h);
#endif // ENABLE_IMGUI
// ensures that this canvas is current
@ -5796,7 +5810,7 @@ void GLCanvas3D::_render_current_gizmo() const
void GLCanvas3D::_render_gizmos_overlay() const
{
m_gizmos.render_overlay(*this);
m_gizmos.render_overlay(*this, m_selection);
}
void GLCanvas3D::_render_toolbar() const

View File

@ -636,14 +636,16 @@ private:
void render_current_gizmo(const Selection& selection) const;
void render_current_gizmo_for_picking_pass(const Selection& selection) const;
void render_overlay(const GLCanvas3D& canvas) const;
void render_overlay(const GLCanvas3D& canvas, const Selection& selection) const;
#ifndef ENABLE_IMGUI
void create_external_gizmo_widgets(wxWindow *parent);
#endif // not ENABLE_IMGUI
private:
void _reset();
void _render_overlay(const GLCanvas3D& canvas) const;
void _render_overlay(const GLCanvas3D& canvas, const Selection& selection) const;
void _render_current_gizmo(const Selection& selection) const;
float _get_total_overlay_height() const;
@ -732,7 +734,9 @@ private:
GCodePreviewVolumeIndex m_gcode_preview_volume_index;
#ifndef ENABLE_IMGUI
wxWindow *m_external_gizmo_widgets_parent;
#endif // not ENABLE_IMGUI
void post_event(wxEvent &&event);
void viewport_changed();
@ -852,7 +856,9 @@ public:
void set_tooltip(const std::string& tooltip) const;
#ifndef ENABLE_IMGUI
void set_external_gizmo_widgets_parent(wxWindow *parent);
#endif // not ENABLE_IMGUI
void do_move();
void do_rotate();

View File

@ -170,6 +170,7 @@ GLGizmoBase::GLGizmoBase(GLCanvas3D& parent)
#endif // ENABLE_GIZMOS_SHORTCUT
, m_hover_id(-1)
, m_dragging(false)
, m_imgui(wxGetApp().imgui())
{
::memcpy((void*)m_base_color, (const void*)DEFAULT_BASE_COLOR, 3 * sizeof(float));
::memcpy((void*)m_drag_color, (const void*)DEFAULT_DRAG_COLOR, 3 * sizeof(float));
@ -273,7 +274,9 @@ void GLGizmoBase::render_grabbers_for_picking(const BoundingBoxf3& box) const
}
}
#ifndef ENABLE_IMGUI
void GLGizmoBase::create_external_gizmo_widgets(wxWindow *parent) {}
#endif // not ENABLE_IMGUI
void GLGizmoBase::set_tooltip(const std::string& tooltip) const
{
@ -687,16 +690,16 @@ void GLGizmoRotate3D::on_render(const GLCanvas3D::Selection& selection) const
}
#if ENABLE_IMGUI
void GLGizmoRotate3D::on_render_input_window(float x, float y, const GLCanvas3D::Selection& selection) const
void GLGizmoRotate3D::on_render_input_window(float x, float y, const GLCanvas3D::Selection& selection)
{
Vec3d rotation(Geometry::rad2deg(m_gizmos[0].get_angle()), Geometry::rad2deg(m_gizmos[1].get_angle()), Geometry::rad2deg(m_gizmos[2].get_angle()));
std::string label = _("Rotation (deg)");
wxString label = _(L("Rotation (deg)"));
wxGetApp().get_imgui().set_next_window_pos(x, y, ImGuiCond_Always);
wxGetApp().get_imgui().set_next_window_bg_alpha(0.5f);
wxGetApp().get_imgui().begin(label, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse);
wxGetApp().get_imgui().input_vec3("", rotation, 100.0f, "%.2f");
wxGetApp().get_imgui().end();
m_imgui->set_next_window_pos(x, y, ImGuiCond_Always);
m_imgui->set_next_window_bg_alpha(0.5f);
m_imgui->begin(label, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse);
m_imgui->input_vec3("", rotation, 100.0f, "%.2f");
m_imgui->end();
}
#endif // ENABLE_IMGUI
@ -987,17 +990,16 @@ void GLGizmoScale3D::on_render_for_picking(const GLCanvas3D::Selection& selectio
}
#if ENABLE_IMGUI
void GLGizmoScale3D::on_render_input_window(float x, float y, const GLCanvas3D::Selection& selection) const
void GLGizmoScale3D::on_render_input_window(float x, float y, const GLCanvas3D::Selection& selection)
{
bool single_instance = selection.is_single_full_instance();
Vec3d scale = single_instance ? 100.0 * selection.get_volume(*selection.get_volume_idxs().begin())->get_scaling_factor() : 100.0 * m_scale;
std::string label = _("Scale (%)");
wxString label = _(L("Scale (%)"));
wxGetApp().get_imgui().set_next_window_pos(x, y, ImGuiCond_Always);
wxGetApp().get_imgui().set_next_window_bg_alpha(0.5f);
wxGetApp().get_imgui().begin(label, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse);
wxGetApp().get_imgui().input_vec3("", scale, 100.0f, "%.2f");
wxGetApp().get_imgui().end();
m_imgui->set_next_window_pos(x, y, ImGuiCond_Always);
m_imgui->set_next_window_bg_alpha(0.5f);
m_imgui->begin(label, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse);
m_imgui->input_vec3("", m_scale, 100.0f, "%.2f");
m_imgui->end();
}
#endif // ENABLE_IMGUI
@ -1215,26 +1217,20 @@ void GLGizmoMove3D::on_render_for_picking(const GLCanvas3D::Selection& selection
}
#if ENABLE_IMGUI
void GLGizmoMove3D::on_render_input_window(float x, float y, const GLCanvas3D::Selection& selection) const
void GLGizmoMove3D::on_render_input_window(float x, float y, const GLCanvas3D::Selection& selection)
{
bool show_position = selection.is_single_full_instance();
const Vec3d& position = selection.get_bounding_box().center();
Vec3d displacement = show_position ? position : m_displacement;
std::string label = show_position ? _("Position (mm)") : _("Displacement (mm)");
wxString label = show_position ? _(L("Position (mm)")) : _(L("Displacement (mm)"));
wxGetApp().get_imgui().set_next_window_pos(x, y, ImGuiCond_Always);
wxGetApp().get_imgui().set_next_window_bg_alpha(0.5f);
wxGetApp().get_imgui().begin(label, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse);
wxGetApp().get_imgui().input_vec3("", displacement, 100.0f, "%.2f");
m_imgui->set_next_window_pos(x, y, ImGuiCond_Always);
m_imgui->set_next_window_bg_alpha(0.5f);
m_imgui->begin(label, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse);
m_imgui->input_vec3("", displacement, 100.0f, "%.2f");
if (ImGui::Button("Test"))
{
std::cout << "WOW" << std::endl;
}
wxGetApp().get_imgui().end();
m_imgui->end();
}
#endif // ENABLE_IMGUI
@ -1932,9 +1928,15 @@ const std::array<float, 3> GLGizmoCut::GrabberColor = { 1.0, 0.5, 0.0 };
GLGizmoCut::GLGizmoCut(GLCanvas3D& parent)
: GLGizmoBase(parent)
, m_cut_z(0.0)
#ifndef ENABLE_IMGUI
, m_panel(nullptr)
#endif // not ENABLE_IMGUI
, m_keep_upper(true)
, m_keep_lower(true)
, m_rotate_lower(false)
{}
#ifndef ENABLE_IMGUI
void GLGizmoCut::create_external_gizmo_widgets(wxWindow *parent)
{
wxASSERT(m_panel == nullptr);
@ -1949,9 +1951,10 @@ void GLGizmoCut::create_external_gizmo_widgets(wxWindow *parent)
m_panel->Hide();
m_panel->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) {
perform_cut();
perform_cut(m_parent.get_selection());
}, wxID_OK);
}
#endif // not ENABLE_IMGUI
bool GLGizmoCut::on_init()
{
@ -1992,10 +1995,12 @@ void GLGizmoCut::on_set_state()
m_cut_z = 0.0;
}
#ifndef ENABLE_IMGUI
// Display or hide the extra panel
if (m_panel != nullptr) {
m_panel->display(get_state() == On);
}
#endif // not ENABLE_IMGUI
}
bool GLGizmoCut::on_is_activable(const GLCanvas3D::Selection& selection) const
@ -2080,16 +2085,38 @@ void GLGizmoCut::on_render_for_picking(const GLCanvas3D::Selection& selection) c
render_grabbers_for_picking(selection.get_bounding_box());
}
void GLGizmoCut::perform_cut()
#if ENABLE_IMGUI
void GLGizmoCut::on_render_input_window(float x, float y, const GLCanvas3D::Selection& selection)
{
const auto &selection = m_parent.get_selection();
m_imgui->set_next_window_pos(x, y, ImGuiCond_Always);
m_imgui->set_next_window_bg_alpha(0.5f);
m_imgui->begin(_(L("Cut")), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse);
ImGui::PushItemWidth(100.0f);
bool _value_changed = ImGui::InputDouble("Z", &m_cut_z, 0.0f, 0.0f, "%.2f");
m_imgui->checkbox(_(L("Keep upper part")), m_keep_upper);
m_imgui->checkbox(_(L("Keep lower part")), m_keep_lower);
m_imgui->checkbox(_(L("Rotate lower part upwards")), m_rotate_lower);
const bool cut_clicked = m_imgui->button(_(L("Perform cut")));
m_imgui->end();
if (cut_clicked) {
perform_cut(selection);
}
}
#endif // ENABLE_IMGUI
void GLGizmoCut::perform_cut(const GLCanvas3D::Selection& selection)
{
const auto instance_idx = selection.get_instance_idx();
const auto object_idx = selection.get_object_idx();
wxCHECK_RET(instance_idx >= 0 && object_idx >= 0, "GLGizmoCut: Invalid object selection");
wxGetApp().plater()->cut(object_idx, instance_idx, m_cut_z);
wxGetApp().plater()->cut(object_idx, instance_idx, m_cut_z, m_keep_upper, m_keep_lower, m_rotate_lower);
}
double GLGizmoCut::calc_projection(const Linef3& mouse_ray) const

View File

@ -23,6 +23,7 @@ class ModelObject;
namespace GUI {
class GLCanvas3D;
class ImGuiWrapper;
class GLGizmoBase
{
@ -88,6 +89,7 @@ protected:
float m_drag_color[3];
float m_highlight_color[3];
mutable std::vector<Grabber> m_grabbers;
ImGuiWrapper* m_imgui;
public:
explicit GLGizmoBase(GLCanvas3D& parent);
@ -135,10 +137,12 @@ public:
void render(const GLCanvas3D::Selection& selection) const { on_render(selection); }
void render_for_picking(const GLCanvas3D::Selection& selection) const { on_render_for_picking(selection); }
#ifndef ENABLE_IMGUI
virtual void create_external_gizmo_widgets(wxWindow *parent);
#endif // not ENABLE_IMGUI
#if ENABLE_IMGUI
void render_input_window(float x, float y, const GLCanvas3D::Selection& selection) const { on_render_input_window(x, y, selection); }
void render_input_window(float x, float y, const GLCanvas3D::Selection& selection) { on_render_input_window(x, y, selection); }
#endif // ENABLE_IMGUI
protected:
@ -160,7 +164,7 @@ protected:
virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const = 0;
#if ENABLE_IMGUI
virtual void on_render_input_window(float x, float y, const GLCanvas3D::Selection& selection) const {}
virtual void on_render_input_window(float x, float y, const GLCanvas3D::Selection& selection) {}
#endif // ENABLE_IMGUI
float picking_color_component(unsigned int id) const;
@ -301,7 +305,7 @@ protected:
}
#if ENABLE_IMGUI
virtual void on_render_input_window(float x, float y, const GLCanvas3D::Selection& selection) const;
virtual void on_render_input_window(float x, float y, const GLCanvas3D::Selection& selection);
#endif // ENABLE_IMGUI
};
@ -341,7 +345,7 @@ protected:
virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const;
#if ENABLE_IMGUI
virtual void on_render_input_window(float x, float y, const GLCanvas3D::Selection& selection) const;
virtual void on_render_input_window(float x, float y, const GLCanvas3D::Selection& selection);
#endif // ENABLE_IMGUI
private:
@ -385,7 +389,7 @@ protected:
virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const;
#if ENABLE_IMGUI
virtual void on_render_input_window(float x, float y, const GLCanvas3D::Selection& selection) const;
virtual void on_render_input_window(float x, float y, const GLCanvas3D::Selection& selection);
#endif // ENABLE_IMGUI
private:
@ -494,7 +498,9 @@ protected:
};
#ifndef ENABLE_IMGUI
class GLGizmoCutPanel;
#endif // not ENABLE_IMGUI
class GLGizmoCut : public GLGizmoBase
{
@ -507,12 +513,21 @@ class GLGizmoCut : public GLGizmoBase
double m_max_z;
Vec3d m_drag_pos;
Vec3d m_drag_center;
bool m_keep_upper;
bool m_keep_lower;
bool m_rotate_lower;
#ifndef ENABLE_IMGUI
GLGizmoCutPanel *m_panel;
#endif // not ENABLE_IMGUI
public:
explicit GLGizmoCut(GLCanvas3D& parent);
#ifndef ENABLE_IMGUI
virtual void create_external_gizmo_widgets(wxWindow *parent);
#endif // not ENABLE_IMGUI
#ifndef ENABLE_IMGUI
#endif // not ENABLE_IMGUI
protected:
virtual bool on_init();
@ -524,8 +539,11 @@ protected:
virtual void on_render(const GLCanvas3D::Selection& selection) const;
virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const;
#if ENABLE_IMGUI
virtual void on_render_input_window(float x, float y, const GLCanvas3D::Selection& selection);
#endif // ENABLE_IMGUI
private:
void perform_cut();
void perform_cut(const GLCanvas3D::Selection& selection);
double calc_projection(const Linef3& mouse_ray) const;
};

View File

@ -32,9 +32,6 @@
#include <I18N.hpp>
#include <wx/wupdlock.h>
#include "SysInfoDialog.hpp"
#if ENABLE_IMGUI
#include <imgui\imgui.h>
#endif // ENABLE_IMGUI
namespace Slic3r {
namespace GUI {
@ -58,11 +55,16 @@ const wxString file_wildcards[FT_SIZE] = {
static std::string libslic3r_translate_callback(const char *s) { return wxGetTranslation(wxString(s, wxConvUTF8)).utf8_str().data(); }
IMPLEMENT_APP(GUI_App)
GUI_App::GUI_App()
: wxApp()
, m_imgui(new ImGuiWrapper())
{}
bool GUI_App::OnInit()
{
#if ENABLE_IMGUI
if (!m_imgui.init())
return false;
wxCHECK_MSG(m_imgui->init(), false, "Failed to initialize ImGui");
#endif // ENABLE_IMGUI
SetAppName("Slic3rPE-alpha");
@ -185,14 +187,6 @@ bool GUI_App::OnInit()
return true;
}
#if ENABLE_IMGUI
int GUI_App::OnExit()
{
m_imgui.shutdown();
return 0;
}
#endif // ENABLE_IMGUI
unsigned GUI_App::get_colour_approx_luma(const wxColour &colour)
{
double r = colour.Red();

View File

@ -1,6 +1,7 @@
#ifndef slic3r_GUI_App_hpp_
#define slic3r_GUI_App_hpp_
#include <memory>
#include <string>
#include "PrintConfig.hpp"
#include "MainFrame.hpp"
@ -86,15 +87,13 @@ class GUI_App : public wxApp
wxLocale* m_wxLocale{ nullptr };
#if ENABLE_IMGUI
ImGuiWrapper m_imgui;
std::unique_ptr<ImGuiWrapper> m_imgui;
#endif // ENABLE_IMGUI
public:
bool OnInit() override;
#if ENABLE_IMGUI
int OnExit() override;
#endif // ENABLE_IMGUI
GUI_App() : wxApp() {}
GUI_App();
unsigned get_colour_approx_luma(const wxColour &colour);
void init_label_colours();
@ -162,7 +161,7 @@ public:
std::vector<Tab *> tabs_list;
#if ENABLE_IMGUI
ImGuiWrapper& get_imgui() { return m_imgui; }
ImGuiWrapper* imgui() { return m_imgui.get(); }
#endif // ENABLE_IMGUI
};

View File

@ -1,13 +1,19 @@
#include "../../libslic3r/libslic3r.h"
#include "ImGuiWrapper.hpp"
#include "Utils.hpp"
#include <vector>
#include <boost/format.hpp>
#include <boost/log/trivial.hpp>
#include <wx/string.h>
#include <wx/event.h>
#include <wx/debug.h>
#include <GL/glew.h>
#include <imgui/imgui.h>
#include "libslic3r/libslic3r.h"
#include "GUI.hpp"
#include "Utils.hpp"
namespace Slic3r {
namespace GUI {
@ -26,9 +32,16 @@ ImGuiWrapper::ImGuiWrapper()
, m_attrib_location_position(0)
, m_attrib_location_uv(0)
, m_attrib_location_color(0)
, m_mouse_buttons(0)
{
}
ImGuiWrapper::~ImGuiWrapper()
{
destroy_device_objects();
ImGui::DestroyContext();
}
bool ImGuiWrapper::init()
{
// Store GLSL version string so we can refer to it later in case we recreate shaders. Note: GLSL version is NOT the same as GL version. Leave this to NULL if unsure.
@ -45,27 +58,21 @@ bool ImGuiWrapper::init()
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();
ImFont* font = io.Fonts->AddFontFromFileTTF((Slic3r::resources_dir() + "\\fonts\\NotoSans-Regular.ttf").c_str(), 18.0f);
if (font == nullptr)
{
ImFont* font = io.Fonts->AddFontFromFileTTF((Slic3r::resources_dir() + "/fonts/NotoSans-Regular.ttf").c_str(), 18.0f);
if (font == nullptr) {
font = io.Fonts->AddFontDefault();
if (font == nullptr)
return false;
}
else
else {
m_fonts.insert(FontsMap::value_type("Noto Sans Regular 18", font));
}
io.IniFilename = nullptr;
return true;
}
void ImGuiWrapper::shutdown()
{
destroy_device_objects();
ImGui::DestroyContext();
}
void ImGuiWrapper::set_display_size(float w, float h)
{
ImGuiIO& io = ImGui::GetIO();
@ -73,7 +80,7 @@ void ImGuiWrapper::set_display_size(float w, float h)
io.DisplayFramebufferScale = ImVec2(1.0f, 1.0f);
}
void ImGuiWrapper::update_mouse_data(wxMouseEvent& evt)
bool ImGuiWrapper::update_mouse_data(wxMouseEvent& evt)
{
ImGuiIO& io = ImGui::GetIO();
io.MousePos = ImVec2((float)evt.GetX(), (float)evt.GetY());
@ -81,10 +88,10 @@ void ImGuiWrapper::update_mouse_data(wxMouseEvent& evt)
io.MouseDown[1] = evt.RightDown();
io.MouseDown[2] = evt.MiddleDown();
if (io.MouseDown[0])
{
int a = 0;
}
unsigned buttons = evt.LeftDown() | evt.RightDown() << 1 | evt.MiddleDown() << 2;
bool res = buttons != m_mouse_buttons;
m_mouse_buttons = buttons;
return res;
}
void ImGuiWrapper::new_frame()
@ -97,9 +104,6 @@ void ImGuiWrapper::new_frame()
void ImGuiWrapper::render()
{
ImGuiIO& io = ImGui::GetIO();
ImGui::Render();
render_draw_data(ImGui::GetDrawData());
}
@ -114,22 +118,33 @@ void ImGuiWrapper::set_next_window_bg_alpha(float alpha)
ImGui::SetNextWindowBgAlpha(alpha);
}
bool ImGuiWrapper::begin(const std::string& name, int flags)
bool ImGuiWrapper::begin(const std::string &name, int flags)
{
return ImGui::Begin(name.c_str(), nullptr, (ImGuiWindowFlags)flags);
}
bool ImGuiWrapper::begin(const wxString &name, int flags)
{
return begin(into_u8(name), flags);
}
void ImGuiWrapper::end()
{
ImGui::End();
}
bool ImGuiWrapper::input_double(const std::string& label, double& value, const std::string& format)
bool ImGuiWrapper::button(const wxString &label)
{
return ImGui::InputDouble(label.c_str(), &value, 0.0f, 0.0f, format.c_str());
auto label_utf8 = into_u8(label);
return ImGui::Button(label_utf8.c_str());
}
bool ImGuiWrapper::input_vec3(const std::string& label, Vec3d& value, float width, const std::string& format)
bool ImGuiWrapper::input_double(const std::string &label, const double &value, const std::string &format)
{
return ImGui::InputDouble(label.c_str(), const_cast<double*>(&value), 0.0f, 0.0f, format.c_str());
}
bool ImGuiWrapper::input_vec3(const std::string &label, const Vec3d &value, float width, const std::string &format)
{
bool value_changed = false;
@ -140,7 +155,7 @@ bool ImGuiWrapper::input_vec3(const std::string& label, Vec3d& value, float widt
std::string item_label = (i == 0) ? "X" : ((i == 1) ? "Y" : "Z");
ImGui::PushID(i);
ImGui::PushItemWidth(width);
value_changed |= ImGui::InputDouble(item_label.c_str(), &value(i), 0.0f, 0.0f, format.c_str());
value_changed |= ImGui::InputDouble(item_label.c_str(), const_cast<double*>(&value(i)), 0.0f, 0.0f, format.c_str());
ImGui::PopID();
}
ImGui::EndGroup();
@ -148,6 +163,33 @@ bool ImGuiWrapper::input_vec3(const std::string& label, Vec3d& value, float widt
return value_changed;
}
bool ImGuiWrapper::checkbox(const wxString &label, bool &value)
{
auto label_utf8 = into_u8(label);
return ImGui::Checkbox(label_utf8.c_str(), &value);
}
bool ImGuiWrapper::want_mouse() const
{
return ImGui::GetIO().WantCaptureMouse;
}
bool ImGuiWrapper::want_keyboard() const
{
return ImGui::GetIO().WantCaptureKeyboard;
}
bool ImGuiWrapper::want_text_input() const
{
return ImGui::GetIO().WantTextInput;
}
bool ImGuiWrapper::want_any_input() const
{
const auto io = ImGui::GetIO();
return io.WantCaptureMouse || io.WantCaptureKeyboard || io.WantTextInput;
}
void ImGuiWrapper::create_device_objects()
{
// Backup GL state
@ -289,19 +331,19 @@ void ImGuiWrapper::create_device_objects()
m_vert_handle = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(m_vert_handle, 2, vertex_shader_with_version, nullptr);
glCompileShader(m_vert_handle);
check_shader(m_vert_handle, "vertex shader");
wxASSERT(check_shader(m_vert_handle, "vertex shader"));
const GLchar* fragment_shader_with_version[2] = { m_glsl_version_string.c_str(), fragment_shader };
m_frag_handle = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(m_frag_handle, 2, fragment_shader_with_version, nullptr);
glCompileShader(m_frag_handle);
check_shader(m_frag_handle, "fragment shader");
wxASSERT(check_shader(m_frag_handle, "fragment shader"));
m_shader_handle = glCreateProgram();
glAttachShader(m_shader_handle, m_vert_handle);
glAttachShader(m_shader_handle, m_frag_handle);
glLinkProgram(m_shader_handle);
check_program(m_shader_handle, "shader program");
wxASSERT(check_program(m_shader_handle, "shader program"));
m_attrib_location_tex = glGetUniformLocation(m_shader_handle, "Texture");
m_attrib_location_proj_mtx = glGetUniformLocation(m_shader_handle, "ProjMtx");
@ -351,36 +393,40 @@ bool ImGuiWrapper::check_program(unsigned int handle, const char* desc)
GLint status = 0, log_length = 0;
glGetProgramiv(handle, GL_LINK_STATUS, &status);
glGetProgramiv(handle, GL_INFO_LOG_LENGTH, &log_length);
if ((GLboolean)status == GL_FALSE)
fprintf(stderr, "ERROR: ImGuiWrapper::check_program(): failed to link %s! (with GLSL '%s')\n", desc, m_glsl_version_string);
if (log_length > 0)
{
ImVector<char> buf;
buf.resize((int)(log_length + 1));
glGetProgramInfoLog(handle, log_length, NULL, (GLchar*)buf.begin());
fprintf(stderr, "%s\n", buf.begin());
if (status == GL_FALSE) {
BOOST_LOG_TRIVIAL(error) << boost::format("ImGuiWrapper::check_program(): failed to link %1% (GLSL `%1%`)") % desc, m_glsl_version_string;
}
return (GLboolean)status == GL_TRUE;
if (log_length > 0) {
std::vector<GLchar> buf(log_length + 1, 0);
glGetProgramInfoLog(handle, log_length, nullptr, buf.data());
BOOST_LOG_TRIVIAL(error) << boost::format("ImGuiWrapper::check_program(): error log:\n%1%\n") % buf.data();
}
return status == GL_TRUE;
}
bool ImGuiWrapper::check_shader(unsigned int handle, const char* desc)
bool ImGuiWrapper::check_shader(unsigned int handle, const char *desc)
{
GLint status = 0, log_length = 0;
glGetShaderiv(handle, GL_COMPILE_STATUS, &status);
glGetShaderiv(handle, GL_INFO_LOG_LENGTH, &log_length);
if ((GLboolean)status == GL_FALSE)
fprintf(stderr, "ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to compile %s!\n", desc);
if (log_length > 0)
{
ImVector<char> buf;
buf.resize((int)(log_length + 1));
glGetShaderInfoLog(handle, log_length, NULL, (GLchar*)buf.begin());
fprintf(stderr, "%s\n", buf.begin());
if (status == GL_FALSE) {
BOOST_LOG_TRIVIAL(error) << boost::format("ImGuiWrapper::check_shader(): failed to compile %1%") % desc;
}
return (GLboolean)status == GL_TRUE;
if (log_length > 0) {
std::vector<GLchar> buf(log_length + 1, 0);
glGetProgramInfoLog(handle, log_length, nullptr, buf.data());
BOOST_LOG_TRIVIAL(error) << boost::format("ImGuiWrapper::check_program(): error log:\n%1%\n") % buf.data();
}
return status == GL_TRUE;
}
void ImGuiWrapper::render_draw_data(ImDrawData* draw_data)
void ImGuiWrapper::render_draw_data(ImDrawData *draw_data)
{
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
ImGuiIO& io = ImGui::GetIO();

View File

@ -4,9 +4,13 @@
#include <string>
#include <map>
#include <imgui/imgui.h>
#include "libslic3r/Point.hpp"
class wxString;
class wxMouseEvent;
class ImFont;
class ImDrawData;
namespace Slic3r {
namespace GUI {
@ -30,14 +34,16 @@ class ImGuiWrapper
FontsMap m_fonts;
unsigned int m_font_texture;
unsigned m_mouse_buttons;
public:
ImGuiWrapper();
~ImGuiWrapper();
bool init();
void shutdown();
void set_display_size(float w, float h);
void update_mouse_data(wxMouseEvent& evt);
bool update_mouse_data(wxMouseEvent &evt);
void new_frame();
void render();
@ -45,19 +51,25 @@ public:
void set_next_window_pos(float x, float y, int flag);
void set_next_window_bg_alpha(float alpha);
bool begin(const std::string& name, int flags = 0);
bool begin(const std::string &name, int flags = 0);
bool begin(const wxString &name, int flags = 0);
void end();
bool input_double(const std::string& label, double& value, const std::string& format = "%.3f");
bool input_vec3(const std::string& label, Vec3d& value, float width, const std::string& format = "%.3f");
bool button(const wxString &label);
bool input_double(const std::string &label, const double &value, const std::string &format = "%.3f");
bool input_vec3(const std::string &label, const Vec3d &value, float width, const std::string &format = "%.3f");
bool checkbox(const wxString &label, bool &value);
bool want_mouse() const;
bool want_keyboard() const;
bool want_text_input() const;
bool want_any_input() const;
private:
void create_device_objects();
void create_fonts_texture();
bool check_program(unsigned int handle, const char* desc);
bool check_shader(unsigned int handle, const char* desc);
void render_draw_data(ImDrawData* draw_data);
bool check_program(unsigned int handle, const char *desc);
bool check_shader(unsigned int handle, const char *desc);
void render_draw_data(ImDrawData *draw_data);
void destroy_device_objects();
void destroy_fonts_texture();
};

View File

@ -913,7 +913,9 @@ struct Plater::priv
// GUI elements
wxNotebook *notebook;
Sidebar *sidebar;
#ifndef ENABLE_IMGUI
wxPanel *panel3d;
#endif // not ENABLE_IMGUI
wxGLCanvas *canvas3Dwidget; // TODO: Use GLCanvas3D when we can
GLCanvas3D *canvas3D;
Preview *preview;
@ -1039,8 +1041,12 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
}))
, notebook(new wxNotebook(q, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_BOTTOM))
, sidebar(new Sidebar(q))
#ifdef ENABLE_IMGUI
, canvas3Dwidget(GLCanvas3DManager::create_wxglcanvas(notebook))
#else
, panel3d(new wxPanel(notebook, wxID_ANY))
, canvas3Dwidget(GLCanvas3DManager::create_wxglcanvas(panel3d))
#endif // ENABLE_IMGUI
, canvas3D(nullptr)
, delayed_scene_refresh(false)
#if ENABLE_NEW_MENU_LAYOUT
@ -1068,6 +1074,9 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
this->canvas3D = _3DScene::get_canvas(this->canvas3Dwidget);
this->canvas3D->allow_multisample(GLCanvas3DManager::can_multisample());
#ifdef ENABLE_IMGUI
notebook->AddPage(canvas3Dwidget, _(L("3D")));
#else
auto *panel3dsizer = new wxBoxSizer(wxVERTICAL);
panel3dsizer->Add(canvas3Dwidget, 1, wxEXPAND);
auto *panel_gizmo_widgets = new wxPanel(panel3d, wxID_ANY);
@ -1076,9 +1085,11 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
panel3d->SetSizer(panel3dsizer);
notebook->AddPage(panel3d, _(L("3D")));
preview = new GUI::Preview(notebook, config, &background_process, &gcode_preview_data, [this](){ schedule_background_process(); });
canvas3D->set_external_gizmo_widgets_parent(panel_gizmo_widgets);
#endif // ENABLE_IMGUI
preview = new GUI::Preview(notebook, config, &background_process, &gcode_preview_data, [this](){ schedule_background_process(); });
// XXX: If have OpenGL
this->canvas3D->enable_picking(true);
@ -1921,7 +1932,11 @@ void Plater::priv::fix_through_netfabb(const int obj_idx)
void Plater::priv::on_notebook_changed(wxBookCtrlEvent&)
{
const auto current_id = notebook->GetCurrentPage()->GetId();
#ifdef ENABLE_IMGUI
if (current_id == canvas3Dwidget->GetId()) {
#else
if (current_id == panel3d->GetId()) {
#endif // ENABLE_IMGUI
if (this->canvas3D->is_reload_delayed()) {
// Delayed loading of the 3D scene.
if (this->printer_technology == ptSLA) {
@ -2454,14 +2469,14 @@ bool Plater::is_selection_empty() const
return p->get_selection().is_empty();
}
void Plater::cut(size_t obj_idx, size_t instance_idx, coordf_t z)
void Plater::cut(size_t obj_idx, size_t instance_idx, coordf_t z, bool keep_upper, bool keep_lower, bool rotate_lower)
{
wxCHECK_RET(obj_idx < p->model.objects.size(), "obj_idx out of bounds");
auto *object = p->model.objects[obj_idx];
wxCHECK_RET(instance_idx < object->instances.size(), "instance_idx out of bounds");
const auto new_objects = object->cut(instance_idx, z);
const auto new_objects = object->cut(instance_idx, z, keep_upper, keep_lower, rotate_lower);
remove(obj_idx);
p->load_model_objects(new_objects);

View File

@ -139,7 +139,7 @@ public:
void set_number_of_copies(/*size_t num*/);
bool is_selection_empty() const;
void cut(size_t obj_idx, size_t instance_idx, coordf_t z);
void cut(size_t obj_idx, size_t instance_idx, coordf_t z, bool keep_upper = true, bool keep_lower = true, bool rotate_lower = false);
// Note: empty path means "use the default"
void export_gcode(boost::filesystem::path output_path = boost::filesystem::path());