mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-10 17:21:10 +00:00
194 lines
6.8 KiB
C++
194 lines
6.8 KiB
C++
#include "GLGizmoAssembly.hpp"
|
|
#include "slic3r/GUI/GLCanvas3D.hpp"
|
|
#include "slic3r/GUI/GUI_App.hpp"
|
|
#include "slic3r/GUI/Plater.hpp"
|
|
#include "slic3r/GUI/Gizmos/GizmoObjectManipulation.hpp"
|
|
#include "slic3r/Utils/UndoRedo.hpp"
|
|
#include "GLGizmoUtils.hpp"
|
|
|
|
#include "libslic3r/PresetBundle.hpp"
|
|
#include "libslic3r/MeasureUtils.hpp"
|
|
|
|
#include <imgui/imgui_internal.h>
|
|
|
|
#include <numeric>
|
|
|
|
#include <glad/gl.h>
|
|
|
|
#include <tbb/parallel_for.h>
|
|
#include <future>
|
|
#include <wx/clipbrd.h>
|
|
|
|
namespace Slic3r {
|
|
namespace GUI {
|
|
|
|
GLGizmoAssembly::GLGizmoAssembly(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) :
|
|
GLGizmoMeasure(parent, icon_filename, sprite_id)
|
|
{
|
|
m_measure_mode = EMeasureMode::ONLY_ASSEMBLY;
|
|
}
|
|
|
|
std::string GLGizmoAssembly::on_get_name() const
|
|
{
|
|
if (!on_is_activable() && m_state == EState::Off) {
|
|
if (wxGetApp().plater()->canvas3D()->get_canvas_type() == GLCanvas3D::ECanvasType::CanvasAssembleView) {
|
|
return _u8L_CONTEXT("Assemble", "Assembly tool") + ":\n" + _u8L("Please confirm explosion ratio = 1 and select at least two volumes.");
|
|
}
|
|
else {
|
|
return _u8L_CONTEXT("Assemble", "Assembly tool") + ":\n" + _u8L("Please select at least two volumes.");
|
|
}
|
|
} else {
|
|
return _u8L_CONTEXT("Assemble", "Assembly tool");
|
|
}
|
|
}
|
|
|
|
bool GLGizmoAssembly::on_init()
|
|
{
|
|
GLGizmoMeasure::on_init();
|
|
|
|
m_shortcut_key = WXK_CONTROL_Y;
|
|
return true;
|
|
}
|
|
|
|
bool GLGizmoAssembly::on_is_activable() const
|
|
{
|
|
const Selection& selection = m_parent.get_selection();
|
|
if (selection.is_wipe_tower()) {
|
|
return false;
|
|
}
|
|
const int selection_volumes_count = 2;
|
|
if (wxGetApp().plater()->canvas3D()->get_canvas_type() == GLCanvas3D::ECanvasType::CanvasAssembleView) {
|
|
if (abs(m_parent.get_explosion_ratio() - 1.0f) < 1e-2 && selection.volumes_count() >= selection_volumes_count) {
|
|
return true;
|
|
}
|
|
return false;
|
|
} else {
|
|
return selection.volumes_count() >= selection_volumes_count;
|
|
}
|
|
}
|
|
|
|
void GLGizmoAssembly::on_render_input_window(float x, float y, float bottom_limit)
|
|
{
|
|
static std::optional<Measure::SurfaceFeature> last_feature;
|
|
static EMode last_mode = EMode::FeatureSelection;
|
|
static SelectedFeatures last_selected_features;
|
|
|
|
static float last_y = 0.0f;
|
|
static float last_h = 0.0f;
|
|
|
|
if (m_editing_distance)
|
|
return;
|
|
m_current_active_imgui_id = ImGui::GetActiveID();
|
|
// adjust window position to avoid overlap the view toolbar
|
|
const float win_h = ImGui::GetWindowHeight();
|
|
y = std::min(y, bottom_limit - win_h);
|
|
GizmoImguiSetNextWIndowPos(x, y, ImGuiCond_Always, 0.0f, 0.0f);
|
|
if (last_h != win_h || last_y != y) {
|
|
// ask canvas for another frame to render the window in the correct position
|
|
m_imgui->set_requires_extra_frame();
|
|
if (last_h != win_h)
|
|
last_h = win_h;
|
|
if (last_y != y)
|
|
last_y = y;
|
|
}
|
|
// Orca
|
|
ImGuiWrapper::push_toolbar_style(m_parent.get_scale());
|
|
GizmoImguiBegin(get_name(), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar);
|
|
init_render_input_window();
|
|
|
|
float moving_size = m_imgui->calc_text_size(_L("(Moving)")).x;
|
|
float combox_content_size = m_imgui->calc_text_size(_L("Point and point assembly")).x*1.1 + ImGui::GetStyle().FramePadding.x * 18.0f;
|
|
float caption_size = moving_size + 2 * m_space_size;
|
|
if (render_assembly_mode_combo(caption_size + 0.5 * m_space_size, combox_content_size)) {
|
|
;
|
|
}
|
|
show_selection_ui();
|
|
show_face_face_assembly_common();
|
|
|
|
ImGui::Separator();
|
|
show_face_face_assembly_senior();
|
|
show_distance_xyz_ui();
|
|
|
|
ImGui::Separator();
|
|
float f_scale =m_parent.get_gizmos_manager().get_layout_scale();
|
|
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(6.0f, 4.0f * f_scale));
|
|
|
|
GLGizmoUtils::render_tooltip_button(m_imgui, m_parent, m_shortcuts, x, y);
|
|
|
|
ImGui::SameLine();
|
|
GLGizmoUtils::begin_right_aligned_buttons({ _L("Done") });
|
|
if (m_imgui->button(_L("Done"))) {
|
|
m_parent.reset_all_gizmos();
|
|
}
|
|
|
|
render_input_window_warning(m_same_model_object);
|
|
|
|
if (last_feature != m_curr_feature || last_mode != m_mode || last_selected_features != m_selected_features) {
|
|
// the dialog may have changed its size, ask for an extra frame to render it properly
|
|
last_feature = m_curr_feature;
|
|
last_mode = m_mode;
|
|
last_selected_features = m_selected_features;
|
|
m_imgui->set_requires_extra_frame();
|
|
}
|
|
m_last_active_item_imgui = m_current_active_imgui_id;
|
|
|
|
GizmoImguiEnd();
|
|
// Orca
|
|
ImGui::PopStyleVar(1); // ImGuiStyleVar_FramePadding
|
|
ImGuiWrapper::pop_toolbar_style();
|
|
}
|
|
|
|
void GLGizmoAssembly::render_input_window_warning(bool same_model_object)
|
|
{
|
|
const bool same_mesh_warning = m_hit_different_volumes.size() == 1;
|
|
const bool wrong_feature_warning = m_selected_wrong_feature_waring_tip;
|
|
const bool not_assembled_warning = m_hit_different_volumes.size() == 2 && same_model_object == false &&
|
|
wxGetApp().plater()->canvas3D()->get_canvas_type() == GLCanvas3D::ECanvasType::CanvasView3D;
|
|
|
|
if (same_mesh_warning || not_assembled_warning || wrong_feature_warning) {
|
|
ImGui::Separator();
|
|
}
|
|
|
|
if (same_mesh_warning) {
|
|
m_imgui->warning_text(_L("Warning: please select two different meshes."));
|
|
}
|
|
if (wrong_feature_warning) {
|
|
if (m_assembly_mode == AssemblyMode::FACE_FACE) {
|
|
m_imgui->warning_text(_L("Warning: please select Plane's feature."));
|
|
} else if (m_assembly_mode == AssemblyMode::POINT_POINT) {
|
|
m_imgui->warning_text(_L("Warning: please select Point's or Circle's feature."));
|
|
}
|
|
}
|
|
if (not_assembled_warning) {
|
|
m_imgui->warning_text(
|
|
_L("Warning") + ": " +
|
|
_L("It is recommended to assemble objects first,\nbecause they are restricted to the bed \nand only parts can be lifted.")
|
|
);
|
|
}
|
|
}
|
|
|
|
bool GLGizmoAssembly::render_assembly_mode_combo(double label_width, float item_width)
|
|
{
|
|
ImGui::AlignTextToFramePadding();
|
|
int selection_idx = int(m_assembly_mode);
|
|
std::vector<std::string> modes = {_u8L("Face and face assembly"), _u8L("Point and point assembly")};
|
|
bool is_changed = false;
|
|
|
|
ImGuiWrapper::push_combo_style(m_parent.get_scale());
|
|
if (render_combo(_u8L("Mode"), modes, selection_idx, label_width, item_width)) {
|
|
is_changed = true;
|
|
switch_to_mode((AssemblyMode) selection_idx);
|
|
}
|
|
ImGuiWrapper::pop_combo_style();
|
|
return is_changed;
|
|
}
|
|
|
|
void GLGizmoAssembly::switch_to_mode(AssemblyMode new_mode)
|
|
{
|
|
m_assembly_mode = new_mode;
|
|
reset_all_feature();
|
|
}
|
|
|
|
} // namespace GUI
|
|
} // namespace Slic3r
|