1st installment of object/instance labels in 3D scene
This commit is contained in:
parent
69549af9ac
commit
d5b258c267
7 changed files with 190 additions and 0 deletions
|
@ -62,5 +62,7 @@
|
||||||
// Enhance reload from disk to be able to work with 3mf/amf files saved with PrusaSlicer 2.1.0 and earlier
|
// Enhance reload from disk to be able to work with 3mf/amf files saved with PrusaSlicer 2.1.0 and earlier
|
||||||
#define ENABLE_BACKWARD_COMPATIBLE_RELOAD_FROM_DISK (1 && ENABLE_2_2_0_BETA1)
|
#define ENABLE_BACKWARD_COMPATIBLE_RELOAD_FROM_DISK (1 && ENABLE_2_2_0_BETA1)
|
||||||
|
|
||||||
|
// Enable showing object/instance info with labels into the 3D scene
|
||||||
|
#define ENABLE_SHOW_SCENE_LABELS (1 && ENABLE_2_2_0_BETA1)
|
||||||
|
|
||||||
#endif // _technologies_h_
|
#endif // _technologies_h_
|
||||||
|
|
|
@ -95,6 +95,11 @@ void AppConfig::set_defaults()
|
||||||
set("use_free_camera", "0");
|
set("use_free_camera", "0");
|
||||||
#endif // ENABLE_6DOF_CAMERA
|
#endif // ENABLE_6DOF_CAMERA
|
||||||
|
|
||||||
|
#if ENABLE_SHOW_SCENE_LABELS
|
||||||
|
if (get("show_labels").empty())
|
||||||
|
set("show_labels", "0");
|
||||||
|
#endif // ENABLE_SHOW_SCENE_LABELS
|
||||||
|
|
||||||
// Remove legacy window positions/sizes
|
// Remove legacy window positions/sizes
|
||||||
erase("", "main_frame_maximized");
|
erase("", "main_frame_maximized");
|
||||||
erase("", "main_frame_pos");
|
erase("", "main_frame_pos");
|
||||||
|
|
|
@ -65,6 +65,10 @@
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#endif // ENABLE_RENDER_STATISTICS
|
#endif // ENABLE_RENDER_STATISTICS
|
||||||
|
|
||||||
|
#if ENABLE_SHOW_SCENE_LABELS
|
||||||
|
#include <imgui/imgui_internal.h>
|
||||||
|
#endif // ENABLE_SHOW_SCENE_LABELS
|
||||||
|
|
||||||
static const float TRACKBALLSIZE = 0.8f;
|
static const float TRACKBALLSIZE = 0.8f;
|
||||||
|
|
||||||
static const float DEFAULT_BG_DARK_COLOR[3] = { 0.478f, 0.478f, 0.478f };
|
static const float DEFAULT_BG_DARK_COLOR[3] = { 0.478f, 0.478f, 0.478f };
|
||||||
|
@ -1230,6 +1234,136 @@ void GLCanvas3D::LegendTexture::render(const GLCanvas3D& canvas) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_SHOW_SCENE_LABELS
|
||||||
|
void GLCanvas3D::Labels::show(bool show)
|
||||||
|
{
|
||||||
|
bool shown = is_shown();
|
||||||
|
if (shown != show)
|
||||||
|
{
|
||||||
|
wxGetApp().app_config->set("show_labels", show ? "1" : "0");
|
||||||
|
wxGetApp().app_config->save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GLCanvas3D::Labels::is_shown() const
|
||||||
|
{
|
||||||
|
return wxGetApp().app_config->get("show_labels") == "1";
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLCanvas3D::Labels::render(const GLCanvas3D& canvas) const
|
||||||
|
{
|
||||||
|
if (!m_enabled || !is_shown())
|
||||||
|
return;
|
||||||
|
|
||||||
|
const Camera& camera = canvas.get_camera();
|
||||||
|
const Model* model = canvas.get_model();
|
||||||
|
if (model == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Transform3d world_to_eye = camera.get_view_matrix();
|
||||||
|
Transform3d world_to_screen = camera.get_projection_matrix() * world_to_eye;
|
||||||
|
const std::array<int, 4>& viewport = camera.get_viewport();
|
||||||
|
|
||||||
|
struct Owner
|
||||||
|
{
|
||||||
|
int obj_idx;
|
||||||
|
int inst_idx;
|
||||||
|
BoundingBoxf3 world_box;
|
||||||
|
double eye_center_z;
|
||||||
|
std::string id_str;
|
||||||
|
bool selected;
|
||||||
|
};
|
||||||
|
|
||||||
|
// collect world bounding boxes from volumes
|
||||||
|
std::vector<Owner> owners;
|
||||||
|
const GLVolumeCollection& volumes = canvas.get_volumes();
|
||||||
|
for (const GLVolume* volume : volumes.volumes)
|
||||||
|
{
|
||||||
|
int obj_idx = volume->object_idx();
|
||||||
|
if ((0 <= obj_idx) && (obj_idx < (int)model->objects.size()))
|
||||||
|
{
|
||||||
|
int inst_idx = volume->instance_idx();
|
||||||
|
std::vector<Owner>::iterator it = std::find_if(owners.begin(), owners.end(), [obj_idx, inst_idx](const Owner& owner) {
|
||||||
|
return (owner.obj_idx == obj_idx) && (owner.inst_idx == inst_idx);
|
||||||
|
});
|
||||||
|
if (it != owners.end())
|
||||||
|
{
|
||||||
|
it->world_box.merge(volume->transformed_bounding_box());
|
||||||
|
it->selected &= volume->selected;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Owner owner;
|
||||||
|
owner.obj_idx = obj_idx;
|
||||||
|
owner.inst_idx = inst_idx;
|
||||||
|
owner.world_box = volume->transformed_bounding_box();
|
||||||
|
owner.selected = volume->selected;
|
||||||
|
owner.id_str = "object" + std::to_string(obj_idx) + "_inst##" + std::to_string(inst_idx);
|
||||||
|
owners.push_back(owner);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// calculate eye bounding boxes center zs
|
||||||
|
for (Owner& owner : owners)
|
||||||
|
{
|
||||||
|
owner.eye_center_z = (world_to_eye * owner.world_box.center())(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// sort owners by center eye zs and selection
|
||||||
|
std::sort(owners.begin(), owners.end(), [](const Owner& owner1, const Owner& owner2) {
|
||||||
|
if (!owner1.selected && owner2.selected)
|
||||||
|
return true;
|
||||||
|
else if (owner1.selected && !owner2.selected)
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
return (owner1.eye_center_z < owner2.eye_center_z);
|
||||||
|
});
|
||||||
|
|
||||||
|
ImGuiWrapper& imgui = *wxGetApp().imgui();
|
||||||
|
|
||||||
|
// render info windows
|
||||||
|
for (const Owner& owner : owners)
|
||||||
|
{
|
||||||
|
Vec3d screen_box_center = world_to_screen * owner.world_box.center();
|
||||||
|
float x = 0.0f;
|
||||||
|
float y = 0.0f;
|
||||||
|
if (camera.get_type() == Camera::Perspective)
|
||||||
|
{
|
||||||
|
x = (0.5f + 0.001f * 0.5f * (float)screen_box_center(0)) * viewport[2];
|
||||||
|
y = (0.5f - 0.001f * 0.5f * (float)screen_box_center(1)) * viewport[3];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x = (0.5f + 0.5f * (float)screen_box_center(0)) * viewport[2];
|
||||||
|
y = (0.5f - 0.5f * (float)screen_box_center(1)) * viewport[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((x < 0.0f) || (viewport[2] < x) || (y < 0.0f) || (viewport[3] < y))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, owner.selected ? 3.0f : 1.5f);
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Border, owner.selected ? ImVec4(0.757f, 0.404f, 0.216f, 1.0f) : ImVec4(0.75f, 0.75f, 0.75f, 1.0f));
|
||||||
|
imgui.set_next_window_pos(x, y, ImGuiCond_Always, 0.5f, 0.5f);
|
||||||
|
imgui.begin(owner.id_str, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove);
|
||||||
|
ImGui::BringWindowToDisplayFront(ImGui::GetCurrentWindow());
|
||||||
|
float win_w = ImGui::GetWindowWidth();
|
||||||
|
std::string object_str = model->objects[owner.obj_idx]->name;
|
||||||
|
ImGui::SetCursorPosX(0.5f * (win_w - imgui.calc_text_size(object_str).x));
|
||||||
|
ImGui::AlignTextToFramePadding();
|
||||||
|
imgui.text(object_str);
|
||||||
|
std::string instance_str = _(L("Instance ")) + std::to_string(owner.inst_idx + 1);
|
||||||
|
ImGui::SetCursorPosX(0.5f * (win_w - imgui.calc_text_size(instance_str).x));
|
||||||
|
ImGui::AlignTextToFramePadding();
|
||||||
|
imgui.text(instance_str);
|
||||||
|
imgui.end();
|
||||||
|
ImGui::PopStyleColor();
|
||||||
|
ImGui::PopStyleVar(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // ENABLE_SHOW_SCENE_LABELS
|
||||||
|
|
||||||
wxDEFINE_EVENT(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS, SimpleEvent);
|
wxDEFINE_EVENT(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS, SimpleEvent);
|
||||||
wxDEFINE_EVENT(EVT_GLCANVAS_OBJECT_SELECT, SimpleEvent);
|
wxDEFINE_EVENT(EVT_GLCANVAS_OBJECT_SELECT, SimpleEvent);
|
||||||
wxDEFINE_EVENT(EVT_GLCANVAS_RIGHT_CLICK, RBtnEvent);
|
wxDEFINE_EVENT(EVT_GLCANVAS_RIGHT_CLICK, RBtnEvent);
|
||||||
|
@ -2646,6 +2780,10 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
|
||||||
case 'a': { post_event(SimpleEvent(EVT_GLCANVAS_ARRANGE)); break; }
|
case 'a': { post_event(SimpleEvent(EVT_GLCANVAS_ARRANGE)); break; }
|
||||||
case 'B':
|
case 'B':
|
||||||
case 'b': { zoom_to_bed(); break; }
|
case 'b': { zoom_to_bed(); break; }
|
||||||
|
#if ENABLE_SHOW_SCENE_LABELS
|
||||||
|
case 'E':
|
||||||
|
case 'e': { m_labels.show(!m_labels.is_shown()); m_dirty = true; break; }
|
||||||
|
#endif // ENABLE_SHOW_SCENE_LABELS
|
||||||
case 'I':
|
case 'I':
|
||||||
case 'i': { _update_camera_zoom(1.0); break; }
|
case 'i': { _update_camera_zoom(1.0); break; }
|
||||||
case 'K':
|
case 'K':
|
||||||
|
@ -4732,6 +4870,10 @@ void GLCanvas3D::_render_overlays() const
|
||||||
_render_undoredo_toolbar();
|
_render_undoredo_toolbar();
|
||||||
_render_view_toolbar();
|
_render_view_toolbar();
|
||||||
|
|
||||||
|
#if ENABLE_SHOW_SCENE_LABELS
|
||||||
|
m_labels.render(*this);
|
||||||
|
#endif // ENABLE_SHOW_SCENE_LABELS
|
||||||
|
|
||||||
if ((m_layers_editing.last_object_id >= 0) && (m_layers_editing.object_max_z() > 0.0f))
|
if ((m_layers_editing.last_object_id >= 0) && (m_layers_editing.object_max_z() > 0.0f))
|
||||||
m_layers_editing.render_overlay(*this);
|
m_layers_editing.render_overlay(*this);
|
||||||
|
|
||||||
|
|
|
@ -373,6 +373,19 @@ private:
|
||||||
};
|
};
|
||||||
#endif // ENABLE_RENDER_STATISTICS
|
#endif // ENABLE_RENDER_STATISTICS
|
||||||
|
|
||||||
|
#if ENABLE_SHOW_SCENE_LABELS
|
||||||
|
class Labels
|
||||||
|
{
|
||||||
|
bool m_enabled{ false };
|
||||||
|
|
||||||
|
public:
|
||||||
|
void enable(bool enable) { m_enabled = enable; }
|
||||||
|
void show(bool show);
|
||||||
|
bool is_shown() const;
|
||||||
|
void render(const GLCanvas3D& canvas) const;
|
||||||
|
};
|
||||||
|
#endif // ENABLE_SHOW_SCENE_LABELS
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum ECursorType : unsigned char
|
enum ECursorType : unsigned char
|
||||||
{
|
{
|
||||||
|
@ -450,6 +463,10 @@ private:
|
||||||
mutable int m_imgui_undo_redo_hovered_pos{ -1 };
|
mutable int m_imgui_undo_redo_hovered_pos{ -1 };
|
||||||
int m_selected_extruder;
|
int m_selected_extruder;
|
||||||
|
|
||||||
|
#if ENABLE_SHOW_SCENE_LABELS
|
||||||
|
Labels m_labels;
|
||||||
|
#endif // ENABLE_SHOW_SCENE_LABELS
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GLCanvas3D(wxGLCanvas* canvas, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar);
|
GLCanvas3D(wxGLCanvas* canvas, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar);
|
||||||
~GLCanvas3D();
|
~GLCanvas3D();
|
||||||
|
@ -465,6 +482,9 @@ public:
|
||||||
void set_as_dirty();
|
void set_as_dirty();
|
||||||
|
|
||||||
unsigned int get_volumes_count() const;
|
unsigned int get_volumes_count() const;
|
||||||
|
#if ENABLE_SHOW_SCENE_LABELS
|
||||||
|
const GLVolumeCollection& get_volumes() const { return m_volumes; }
|
||||||
|
#endif // ENABLE_SHOW_SCENE_LABELS
|
||||||
void reset_volumes();
|
void reset_volumes();
|
||||||
int check_volumes_outside_state() const;
|
int check_volumes_outside_state() const;
|
||||||
|
|
||||||
|
@ -476,6 +496,9 @@ public:
|
||||||
void set_config(const DynamicPrintConfig* config);
|
void set_config(const DynamicPrintConfig* config);
|
||||||
void set_process(BackgroundSlicingProcess* process);
|
void set_process(BackgroundSlicingProcess* process);
|
||||||
void set_model(Model* model);
|
void set_model(Model* model);
|
||||||
|
#if ENABLE_SHOW_SCENE_LABELS
|
||||||
|
const Model* get_model() const { return m_model; }
|
||||||
|
#endif // ENABLE_SHOW_SCENE_LABELS
|
||||||
|
|
||||||
const Selection& get_selection() const { return m_selection; }
|
const Selection& get_selection() const { return m_selection; }
|
||||||
Selection& get_selection() { return m_selection; }
|
Selection& get_selection() { return m_selection; }
|
||||||
|
@ -523,6 +546,9 @@ public:
|
||||||
void enable_main_toolbar(bool enable);
|
void enable_main_toolbar(bool enable);
|
||||||
void enable_undoredo_toolbar(bool enable);
|
void enable_undoredo_toolbar(bool enable);
|
||||||
void enable_dynamic_background(bool enable);
|
void enable_dynamic_background(bool enable);
|
||||||
|
#if ENABLE_SHOW_SCENE_LABELS
|
||||||
|
void enable_labels(bool enable) { m_labels.enable(enable); }
|
||||||
|
#endif // ENABLE_SHOW_SCENE_LABELS
|
||||||
void allow_multisample(bool allow);
|
void allow_multisample(bool allow);
|
||||||
|
|
||||||
void zoom_to_bed();
|
void zoom_to_bed();
|
||||||
|
|
|
@ -65,6 +65,9 @@ bool View3D::init(wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view_
|
||||||
m_canvas->enable_selection(true);
|
m_canvas->enable_selection(true);
|
||||||
m_canvas->enable_main_toolbar(true);
|
m_canvas->enable_main_toolbar(true);
|
||||||
m_canvas->enable_undoredo_toolbar(true);
|
m_canvas->enable_undoredo_toolbar(true);
|
||||||
|
#if ENABLE_SHOW_SCENE_LABELS
|
||||||
|
m_canvas->enable_labels(true);
|
||||||
|
#endif // ENABLE_SHOW_SCENE_LABELS
|
||||||
|
|
||||||
wxBoxSizer* main_sizer = new wxBoxSizer(wxVERTICAL);
|
wxBoxSizer* main_sizer = new wxBoxSizer(wxVERTICAL);
|
||||||
main_sizer->Add(m_canvas_widget, 1, wxALL | wxEXPAND, 0);
|
main_sizer->Add(m_canvas_widget, 1, wxALL | wxEXPAND, 0);
|
||||||
|
|
|
@ -157,6 +157,9 @@ void KBShortcutsDialog::fill_shortcuts()
|
||||||
plater_shortcuts.push_back(Shortcut("Z", L("Zoom to selected object")));
|
plater_shortcuts.push_back(Shortcut("Z", L("Zoom to selected object")));
|
||||||
plater_shortcuts.push_back(Shortcut("I", L("Zoom in")));
|
plater_shortcuts.push_back(Shortcut("I", L("Zoom in")));
|
||||||
plater_shortcuts.push_back(Shortcut("O", L("Zoom out")));
|
plater_shortcuts.push_back(Shortcut("O", L("Zoom out")));
|
||||||
|
#if ENABLE_SHOW_SCENE_LABELS
|
||||||
|
plater_shortcuts.push_back(Shortcut("E", L("Show/Hide object/instance labels")));
|
||||||
|
#endif // ENABLE_SHOW_SCENE_LABELS
|
||||||
plater_shortcuts.push_back(Shortcut(ctrl+"M", L("Show/Hide 3Dconnexion devices settings dialog")));
|
plater_shortcuts.push_back(Shortcut(ctrl+"M", L("Show/Hide 3Dconnexion devices settings dialog")));
|
||||||
plater_shortcuts.push_back(Shortcut("ESC", L("Unselect gizmo / Clear selection")));
|
plater_shortcuts.push_back(Shortcut("ESC", L("Unselect gizmo / Clear selection")));
|
||||||
#if ENABLE_RENDER_PICKING_PASS
|
#if ENABLE_RENDER_PICKING_PASS
|
||||||
|
|
|
@ -144,6 +144,15 @@ void PreferencesDialog::build()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if ENABLE_SHOW_SCENE_LABELS
|
||||||
|
def.label = L("Show object/instance labels in 3D scene");
|
||||||
|
def.type = coBool;
|
||||||
|
def.tooltip = L("If enabled, shows labels containing info about objects/instances.");
|
||||||
|
def.set_default_value(new ConfigOptionBool{ app_config->get("show_labels") == "1" });
|
||||||
|
option = Option(def, "show_labels");
|
||||||
|
m_optgroup_gui->append_single_option_line(option);
|
||||||
|
#endif // ENABLE_SHOW_SCENE_LABELS
|
||||||
|
|
||||||
def.label = L("Use custom size for toolbar icons");
|
def.label = L("Use custom size for toolbar icons");
|
||||||
def.type = coBool;
|
def.type = coBool;
|
||||||
def.tooltip = L("If enabled, you can change size of toolbar icons manually.");
|
def.tooltip = L("If enabled, you can change size of toolbar icons manually.");
|
||||||
|
|
Loading…
Add table
Reference in a new issue