This commit is contained in:
Filip Sykala - NTB T15p 2022-12-19 10:54:28 +01:00
commit cc9aba8474
14 changed files with 302 additions and 135 deletions

View file

@ -3,11 +3,10 @@
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g id="expand">
<g><line fill="none" stroke="#FFFFFF" stroke-width="1" stroke-linecap="round" stroke-miterlimit="10" x1="4" y1="8" x2="8" y2="4"/></g>
<g><line fill="none" stroke="#FFFFFF" stroke-width="1" stroke-linecap="round" stroke-miterlimit="10" x1="8" y1="4" x2="12" y2="8"/></g>
<g><line fill="none" stroke="#FFFFFF" stroke-width="1" stroke-linecap="round" stroke-miterlimit="10" x1="4" y1="12" x2="8" y2="8"/></g>
<g><line fill="none" stroke="#FFFFFF" stroke-width="1" stroke-linecap="round" stroke-miterlimit="10" x1="8" y1="8" x2="12" y2="12"/></g>
<g><line fill="none" stroke="#FFFFFF" stroke-width="1" stroke-linecap="round" stroke-miterlimit="10" x1="4" y1="4" x2="8" y2="8"/></g>
<g><line fill="none" stroke="#FFFFFF" stroke-width="1" stroke-linecap="round" stroke-miterlimit="10" x1="8" y1="8" x2="12" y2="4"/></g>
<g><line fill="none" stroke="#FFFFFF" stroke-width="1" stroke-linecap="round" stroke-miterlimit="10" x1="4" y1="8" x2="8" y2="12"/></g>
<g><line fill="none" stroke="#FFFFFF" stroke-width="1" stroke-linecap="round" stroke-miterlimit="10" x1="8" y1="12" x2="12" y2="8"/></g>
</g>
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 919 B

After

Width:  |  Height:  |  Size: 915 B

View file

@ -3,10 +3,11 @@
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g id="expand">
<g><line fill="none" stroke="#FFFFFF" stroke-width="1" stroke-linecap="round" stroke-miterlimit="10" x1="4" y1="4" x2="8" y2="8"/></g>
<g><line fill="none" stroke="#FFFFFF" stroke-width="1" stroke-linecap="round" stroke-miterlimit="10" x1="8" y1="8" x2="12" y2="4"/></g>
<g><line fill="none" stroke="#FFFFFF" stroke-width="1" stroke-linecap="round" stroke-miterlimit="10" x1="4" y1="8" x2="8" y2="12"/></g>
<g><line fill="none" stroke="#FFFFFF" stroke-width="1" stroke-linecap="round" stroke-miterlimit="10" x1="8" y1="12" x2="12" y2="8"/></g>
<g><line fill="none" stroke="#FFFFFF" stroke-width="1" stroke-linecap="round" stroke-miterlimit="10" x1="4" y1="8" x2="8" y2="4"/></g>
<g><line fill="none" stroke="#FFFFFF" stroke-width="1" stroke-linecap="round" stroke-miterlimit="10" x1="8" y1="4" x2="12" y2="8"/></g>
<g><line fill="none" stroke="#FFFFFF" stroke-width="1" stroke-linecap="round" stroke-miterlimit="10" x1="4" y1="12" x2="8" y2="8"/></g>
<g><line fill="none" stroke="#FFFFFF" stroke-width="1" stroke-linecap="round" stroke-miterlimit="10" x1="8" y1="8" x2="12" y2="12"/></g>
</g>
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 915 B

After

Width:  |  Height:  |  Size: 919 B

View file

@ -1154,7 +1154,7 @@ indexed_triangle_set its_make_frustum_dowel(double radius, double h, int sectorC
else
for (int j = 0; j < sectorCount; ++j) {
// from 0 to 2pi
double sectorAngle = sectorStep * j;
double sectorAngle = sectorStep * j + 0.25 * M_PI;
vertices.emplace_back(Vec3d(xy * std::cos(sectorAngle), xy * std::sin(sectorAngle), z).cast<float>());
}
}

View file

@ -1755,7 +1755,20 @@ std::vector<int> GLCanvas3D::load_object(const Model& model, int obj_idx)
void GLCanvas3D::mirror_selection(Axis axis)
{
#if ENABLE_WORLD_COORDINATE
TransformationType transformation_type;
if (wxGetApp().obj_manipul()->is_local_coordinates())
transformation_type.set_local();
else if (wxGetApp().obj_manipul()->is_instance_coordinates())
transformation_type.set_instance();
transformation_type.set_relative();
m_selection.setup_cache();
m_selection.mirror(axis, transformation_type);
#else
m_selection.mirror(axis);
#endif // ENABLE_WORLD_COORDINATE
do_mirror(L("Mirror Object"));
wxGetApp().obj_manipul()->set_dirty();
}
@ -3646,7 +3659,13 @@ void GLCanvas3D::do_rotate(const std::string& snapshot_type)
for (const GLVolume* v : m_volumes.volumes) {
if (v->is_wipe_tower) {
const Vec3d offset = v->get_volume_offset();
#if ENABLE_WORLD_COORDINATE
Vec3d rot_unit_x = v->get_volume_transformation().get_matrix().linear() * Vec3d::UnitX();
double z_rot = std::atan2(rot_unit_x.y(), rot_unit_x.x());
post_event(Vec3dEvent(EVT_GLCANVAS_WIPETOWER_ROTATED, Vec3d(offset.x(), offset.y(), z_rot)));
#else
post_event(Vec3dEvent(EVT_GLCANVAS_WIPETOWER_ROTATED, Vec3d(offset.x(), offset.y(), v->get_volume_rotation().z())));
#endif // ENABLE_WORLD_COORDINATE
}
const int object_idx = v->object_idx();
if (object_idx < 0 || (int)m_model->objects.size() <= object_idx)
@ -5096,9 +5115,17 @@ void GLCanvas3D::_refresh_if_shown_on_screen()
const Size& cnv_size = get_canvas_size();
_resize((unsigned int)cnv_size.get_width(), (unsigned int)cnv_size.get_height());
// When the application starts the following call to render() triggers the opengl initialization.
// We need to ask for an extra call to reload_scene() to force the generation of the model for wipe tower
// for printers using it, which is skipped by all the previous calls to reload_scene() because m_initialized == false
const bool requires_reload_scene = !m_initialized;
// Because of performance problems on macOS, where PaintEvents are not delivered
// frequently enough, we call render() here directly when we can.
render();
assert(m_initialized);
if (requires_reload_scene)
reload_scene(true);
}
}

View file

@ -2216,6 +2216,17 @@ bool GUI_App::load_language(wxString language, bool initial)
// Override language at the active wxTranslations class (which is stored in the active m_wxLocale)
// to load possibly different dictionary, for example, load Czech dictionary for Slovak language.
wxTranslations::Get()->SetLanguage(language_dict);
{
// UKR Localization specific workaround till the wxWidgets doesn't fixed:
// From wxWidgets 3.1.6 calls setlocation(0, wxInfoLanguage->LocaleTag), see (https://github.com/prusa3d/wxWidgets/commit/deef116a09748796711d1e3509965ee208dcdf0b#diff-7de25e9a71c4dce61bbf76492c589623d5b93fd1bb105ceaf0662075d15f4472),
// where LocaleTag is a Tag of locale in BCP 47 - like notation.
// For Ukrainian Language LocaleTag == "uk".
// But setlocale(0, "uk") returns "English_United Kingdom.1252" instead of "uk",
// and, as a result, locales are set to English_United Kingdom
if (language_info->CanonicalName == "uk")
setlocale(0, language_info->GetCanonicalWithRegion().data());
}
m_wxLocale->AddCatalog(SLIC3R_APP_KEY);
m_imgui->set_language(into_u8(language_info->CanonicalName));
//FIXME This is a temporary workaround, the correct solution is to switch to "C" locale during file import / export only.

View file

@ -2825,8 +2825,12 @@ void ObjectList::part_selection_changed()
panel.Freeze();
#if ENABLE_WORLD_COORDINATE
const ManipulationEditor* const editor = wxGetApp().obj_manipul()->get_focused_editor();
const std::string opt_key = (editor != nullptr) ? editor->get_full_opt_name() : "";
std::string opt_key;
if (m_selected_object_id >= 0) {
const ManipulationEditor* const editor = wxGetApp().obj_manipul()->get_focused_editor();
if (editor != nullptr)
opt_key = editor->get_full_opt_name();
}
wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event(opt_key, !opt_key.empty());
#else
wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event("", false);

View file

@ -125,8 +125,10 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
// Load bitmaps to be used for the mirroring buttons:
m_mirror_bitmap_on = ScalableBitmap(parent, "mirroring_on");
#if !ENABLE_WORLD_COORDINATE
m_mirror_bitmap_off = ScalableBitmap(parent, "mirroring_off");
m_mirror_bitmap_hidden = ScalableBitmap(parent, "mirroring_transparent");
#endif // !ENABLE_WORLD_COORDINATE
const int border = wxOSX ? 0 : 4;
const int em = wxGetApp().em_unit();
@ -265,28 +267,44 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
// We will add a button to toggle mirroring to each axis:
auto btn = new ScalableButton(parent, wxID_ANY, "mirroring_off", wxEmptyString, wxDefaultSize, wxDefaultPosition, wxBU_EXACTFIT | wxNO_BORDER | wxTRANSPARENT_WINDOW);
#if ENABLE_WORLD_COORDINATE
btn->SetToolTip(_L("Mirror along") + wxString::Format(_L(" %c "), (int)label) + _L("axis"));
m_mirror_buttons[axis_idx] = btn;
#else
btn->SetToolTip(wxString::Format(_L("Toggle %c axis mirroring"), (int)label));
btn->SetBitmapDisabled_(m_mirror_bitmap_hidden);
m_mirror_buttons[axis_idx].first = btn;
m_mirror_buttons[axis_idx].second = mbShown;
#endif // ENABLE_WORLD_COORDINATE
sizer->AddStretchSpacer(2);
sizer->Add(btn, 0, wxALIGN_CENTER_VERTICAL);
btn->Bind(wxEVT_BUTTON, [this, axis_idx](wxCommandEvent&) {
#if !ENABLE_WORLD_COORDINATE
Axis axis = (Axis)(axis_idx + X);
if (m_mirror_buttons[axis_idx].second == mbHidden)
return;
return;
#endif // !ENABLE_WORLD_COORDINATE
GLCanvas3D* canvas = wxGetApp().plater()->canvas3D();
Selection& selection = canvas->get_selection();
#if ENABLE_WORLD_COORDINATE
if (selection.is_single_volume_or_modifier()) {
TransformationType transformation_type;
if (is_local_coordinates())
transformation_type.set_local();
else if (is_instance_coordinates())
transformation_type.set_instance();
transformation_type.set_relative();
selection.setup_cache();
selection.mirror((Axis)axis_idx, transformation_type);
#else
if (selection.is_single_volume() || selection.is_single_modifier()) {
#endif // ENABLE_WORLD_COORDINATE
GLVolume* volume = const_cast<GLVolume*>(selection.get_first_volume());
volume->set_volume_mirror(axis, -volume->get_volume_mirror(axis));
}
@ -302,6 +320,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
// Update mirroring at the GLVolumes.
selection.synchronize_unselected_instances(Selection::SyncRotationType::GENERAL);
selection.synchronize_unselected_volumes();
#endif // ENABLE_WORLD_COORDINATE
// Copy mirroring values from GLVolumes into Model (ModelInstance / ModelVolume), trigger background processing.
canvas->do_mirror(L("Set Mirror"));
UpdateAndShow(true);
@ -310,7 +329,12 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
editors_grid_sizer->Add(sizer, 0, wxALIGN_CENTER_HORIZONTAL);
}
#if ENABLE_WORLD_COORDINATE
m_mirror_warning_bitmap = new wxStaticBitmap(parent, wxID_ANY, wxNullBitmap);
editors_grid_sizer->Add(m_mirror_warning_bitmap, 0, wxALIGN_CENTER_VERTICAL);
#else
editors_grid_sizer->AddStretchSpacer(1);
#endif // ENABLE_WORLD_COORDINATE
editors_grid_sizer->AddStretchSpacer(1);
// add EditBoxes
@ -541,15 +565,15 @@ void ObjectManipulation::Show(const bool show)
bool show_world_local_combo = wxGetApp().get_mode() != comSimple && (selection.is_single_full_instance() || selection.is_single_volume_or_modifier());
if (selection.is_single_volume_or_modifier() && m_word_local_combo->GetCount() < 3) {
#ifdef __linux__
m_word_local_combo->Insert(coordinate_type_str(ECoordinatesType::Instance), 1);
m_word_local_combo->Insert(coordinate_type_str(ECoordinatesType::Local), 2);
#else
m_word_local_combo->Insert(coordinate_type_str(ECoordinatesType::Instance), wxNullBitmap, 1);
m_word_local_combo->Insert(coordinate_type_str(ECoordinatesType::Local), wxNullBitmap, 2);
#endif // __linux__
m_word_local_combo->Select((int)ECoordinatesType::World);
this->set_coordinates_type(m_word_local_combo->GetString(m_word_local_combo->GetSelection()));
}
else if (selection.is_single_full_instance() && m_word_local_combo->GetCount() > 2) {
m_word_local_combo->Delete(1);
m_word_local_combo->Delete(2);
m_word_local_combo->Select((int)ECoordinatesType::World);
this->set_coordinates_type(m_word_local_combo->GetString(m_word_local_combo->GetSelection()));
}
@ -660,7 +684,7 @@ void ObjectManipulation::update_ui_from_settings()
void ObjectManipulation::update_settings_value(const Selection& selection)
{
m_new_move_label_string = L("Position");
m_new_move_label_string = L("Position");
m_new_rotate_label_string = L("Rotation");
m_new_scale_label_string = L("Scale factors");
@ -688,13 +712,15 @@ void ObjectManipulation::update_settings_value(const Selection& selection)
#if ENABLE_WORLD_COORDINATE
if (is_world_coordinates()) {
m_new_position = volume->get_instance_offset();
m_new_scale_label_string = L("Scale");
m_new_scale = Vec3d(100.0, 100.0, 100.0);
#else
if (m_world_coordinates) {
m_new_scale = m_new_size.cwiseQuotient(selection.get_unscaled_instance_bounding_box().size()) * 100.0;
#endif // ENABLE_WORLD_COORDINATE
m_new_rotate_label_string = L("Rotate");
m_new_rotation = Vec3d::Zero();
m_new_size = selection.get_scaled_instance_bounding_box().size();
m_new_scale = m_new_size.cwiseQuotient(selection.get_unscaled_instance_bounding_box().size()) * 100.0;
}
else {
#if ENABLE_WORLD_COORDINATE
@ -702,12 +728,13 @@ void ObjectManipulation::update_settings_value(const Selection& selection)
m_new_rotate_label_string = L("Rotate");
m_new_position = Vec3d::Zero();
m_new_rotation = Vec3d::Zero();
m_new_scale = Vec3d(100.0, 100.0, 100.0);
#else
m_new_rotation = volume->get_instance_rotation() * (180.0 / M_PI);
#endif // ENABLE_WORLD_COORDINATE
m_new_scale = volume->get_instance_scaling_factor() * 100.0;
m_new_size = volume->get_instance_scaling_factor().cwiseProduct(wxGetApp().model().objects[volume->object_idx()]->raw_mesh_bounding_box().size());
m_new_scale = volume->get_instance_scaling_factor() * 100.0;
}
}
m_new_enabled = true;
}
@ -718,7 +745,7 @@ void ObjectManipulation::update_settings_value(const Selection& selection)
m_new_scale = Vec3d(100.0, 100.0, 100.0);
m_new_size = box.size();
m_new_rotate_label_string = L("Rotate");
m_new_scale_label_string = L("Scale");
m_new_scale_label_string = L("Scale");
m_new_enabled = true;
}
#if ENABLE_WORLD_COORDINATE
@ -736,9 +763,10 @@ void ObjectManipulation::update_settings_value(const Selection& selection)
m_new_position = offset;
m_new_rotate_label_string = L("Rotate");
m_new_scale_label_string = L("Scale");
m_new_scale = Vec3d(100.0, 100.0, 100.0);
m_new_rotation = Vec3d::Zero();
m_new_size = volume->transformed_convex_hull_bounding_box(trafo.get_matrix()).size();
m_new_scale = m_new_size.cwiseQuotient(volume->transformed_convex_hull_bounding_box(volume->get_instance_transformation().get_matrix() * volume->get_volume_transformation().get_matrix_no_scaling_factor()).size()) * 100.0;
}
else if (is_local_coordinates()) {
m_new_move_label_string = L("Translate");
@ -750,12 +778,13 @@ void ObjectManipulation::update_settings_value(const Selection& selection)
}
else {
#endif // ENABLE_WORLD_COORDINATE
m_new_position = volume->get_volume_offset();
m_new_rotate_label_string = L("Rotate");
m_new_rotation = Vec3d::Zero();
m_new_position = volume->get_volume_offset();
m_new_rotate_label_string = L("Rotate");
m_new_rotation = Vec3d::Zero();
#if ENABLE_WORLD_COORDINATE
m_new_scale_label_string = L("Scale");
m_new_size = volume->transformed_convex_hull_bounding_box(volume->get_volume_transformation().get_matrix()).size();
m_new_scale = m_new_size.cwiseQuotient(volume->transformed_convex_hull_bounding_box(volume->get_volume_transformation().get_matrix_no_scaling_factor()).size()) * 100.0;
m_new_scale = Vec3d(100.0, 100.0, 100.0);
}
#else
m_new_scale = volume->get_volume_scaling_factor() * 100.0;
@ -765,17 +794,17 @@ void ObjectManipulation::update_settings_value(const Selection& selection)
}
else if (obj_list->is_connectors_item_selected() || obj_list->multiple_selection() || obj_list->is_selected(itInstanceRoot)) {
reset_settings_value();
m_new_move_label_string = L("Translate");
m_new_rotate_label_string = L("Rotate");
m_new_scale_label_string = L("Scale");
m_new_move_label_string = L("Translate");
m_new_rotate_label_string = L("Rotate");
m_new_scale_label_string = L("Scale");
m_new_size = selection.get_bounding_box().size();
m_new_enabled = true;
}
else {
else {
// No selection, reset the cache.
// assert(selection.is_empty());
reset_settings_value();
}
reset_settings_value();
}
}
void ObjectManipulation::update_if_dirty()
@ -882,6 +911,7 @@ void ObjectManipulation::update_reset_buttons_visibility()
bool show_drop_to_bed = false;
#if ENABLE_WORLD_COORDINATE
bool show_skew = false;
bool show_mirror_warning = false;
if (selection.is_single_full_instance() || selection.is_single_volume_or_modifier()) {
const double min_z = selection.is_single_full_instance() ? selection.get_scaled_instance_bounding_box().min.z() :
@ -891,7 +921,6 @@ void ObjectManipulation::update_reset_buttons_visibility()
const GLVolume* volume = selection.get_first_volume();
Transform3d rotation = Transform3d::Identity();
Transform3d scale = Transform3d::Identity();
Geometry::Transformation skew;
#else
if (selection.is_single_full_instance() || selection.is_single_modifier() || selection.is_single_volume()) {
const GLVolume* volume = selection.get_first_volume();
@ -907,11 +936,9 @@ void ObjectManipulation::update_reset_buttons_visibility()
scale = trafo.get_scaling_factor_matrix();
const Selection::IndicesList& idxs = selection.get_volume_idxs();
for (unsigned int id : idxs) {
const Geometry::Transformation world_trafo(selection.get_volume(id)->world_matrix());
if (world_trafo.has_skew()) {
skew = world_trafo;
break;
}
const Geometry::Transformation world_trafo(selection.get_volume(id)->world_matrix());
show_skew |= world_trafo.has_skew();
show_mirror_warning |= world_trafo.get_matrix().matrix().determinant() < 0.0;
}
#else
rotation = volume->get_instance_rotation();
@ -925,8 +952,8 @@ void ObjectManipulation::update_reset_buttons_visibility()
rotation = trafo.get_rotation_matrix();
scale = trafo.get_scaling_factor_matrix();
const Geometry::Transformation world_trafo(volume->world_matrix());
if (world_trafo.has_skew())
skew = world_trafo;
show_skew |= world_trafo.has_skew();
show_mirror_warning |= world_trafo.get_matrix().matrix().determinant() < 0.0;
#else
rotation = volume->get_volume_rotation();
scale = volume->get_volume_scaling_factor();
@ -936,7 +963,6 @@ void ObjectManipulation::update_reset_buttons_visibility()
#if ENABLE_WORLD_COORDINATE
show_rotation = !rotation.isApprox(Transform3d::Identity());
show_scale = !scale.isApprox(Transform3d::Identity());
show_skew = skew.has_skew();
#else
show_rotation = !rotation.isApprox(Vec3d::Zero());
show_scale = !scale.isApprox(Vec3d::Ones());
@ -945,7 +971,7 @@ void ObjectManipulation::update_reset_buttons_visibility()
}
#if ENABLE_WORLD_COORDINATE
wxGetApp().CallAfter([this, show_rotation, show_scale, show_drop_to_bed, show_skew] {
wxGetApp().CallAfter([this, show_rotation, show_scale, show_drop_to_bed, show_skew, show_mirror_warning] {
#else
wxGetApp().CallAfter([this, show_rotation, show_scale, show_drop_to_bed] {
#endif // ENABLE_WORLD_COORDINATE
@ -959,6 +985,9 @@ void ObjectManipulation::update_reset_buttons_visibility()
#if ENABLE_WORLD_COORDINATE
m_reset_skew_button->Show(show_skew);
m_skew_label->Show(show_skew);
m_mirror_warning_bitmap->SetBitmap(show_mirror_warning ? m_manifold_warning_bmp.bmp() : wxNullBitmap);
m_mirror_warning_bitmap->SetMinSize(show_mirror_warning ? m_manifold_warning_bmp.GetSize() : wxSize(0, 0));
m_mirror_warning_bitmap->SetToolTip(show_mirror_warning ? _L("Left handed") : "");
#endif // ENABLE_WORLD_COORDINATE
// Because of CallAfter we need to layout sidebar after Show/hide of reset buttons one more time
@ -977,16 +1006,14 @@ void ObjectManipulation::update_mirror_buttons_visibility()
{
GLCanvas3D* canvas = wxGetApp().plater()->canvas3D();
Selection& selection = canvas->get_selection();
std::array<MirrorButtonState, 3> new_states = {mbHidden, mbHidden, mbHidden};
#if ENABLE_WORLD_COORDINATE
if (is_local_coordinates()) {
#else
if (!m_world_coordinates) {
#endif // ENABLE_WORLD_COORDINATE
#if ENABLE_WORLD_COORDINATE
if (selection.is_single_full_instance() || selection.is_single_volume_or_modifier()) {
#else
std::array<MirrorButtonState, 3> new_states = { mbHidden, mbHidden, mbHidden };
if (!m_world_coordinates) {
if (selection.is_single_full_instance() || selection.is_single_modifier() || selection.is_single_volume()) {
#endif // ENABLE_WORLD_COORDINATE
const GLVolume* volume = selection.get_first_volume();
@ -997,10 +1024,13 @@ void ObjectManipulation::update_mirror_buttons_visibility()
else
mirror = volume->get_volume_mirror();
#if !ENABLE_WORLD_COORDINATE
for (unsigned char i=0; i<3; ++i)
new_states[i] = (mirror[i] < 0. ? mbActive : mbShown);
#endif // !ENABLE_WORLD_COORDINATE
}
}
#if !ENABLE_WORLD_COORDINATE
else {
// the mirroring buttons should be hidden in world coordinates,
// unless we make it actually mirror in world coords.
@ -1022,6 +1052,7 @@ void ObjectManipulation::update_mirror_buttons_visibility()
}
}
});
#endif // !ENABLE_WORLD_COORDINATE
}
@ -1059,8 +1090,8 @@ wxString ObjectManipulation::coordinate_type_str(ECoordinatesType type)
switch (type)
{
case ECoordinatesType::World: { return _L("World coordinates"); }
case ECoordinatesType::Instance: { return _L("Instance coordinates"); }
case ECoordinatesType::Local: { return _L("Local coordinates"); }
case ECoordinatesType::Instance: { return _L("Object coordinates"); }
case ECoordinatesType::Local: { return _L("Part coordinates"); }
default: { assert(false); return _L("Unknown"); }
}
}
@ -1162,13 +1193,24 @@ void ObjectManipulation::change_scale_value(int axis, double value)
return;
Vec3d scale = m_cache.scale;
scale(axis) = value;
scale(axis) = value;
#if ENABLE_WORLD_COORDINATE
const Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
Vec3d ref_scale = m_cache.scale;
if (selection.is_single_full_instance()) {
scale = scale.cwiseQuotient(ref_scale);
ref_scale = Vec3d::Ones();
}
this->do_scale(axis, scale.cwiseQuotient(ref_scale));
#else
this->do_scale(axis, 0.01 * scale);
#endif // ENABLE_WORLD_COORDINATE
m_cache.scale = scale;
m_cache.scale_rounded(axis) = DBL_MAX;
this->UpdateAndShow(true);
m_cache.scale_rounded(axis) = DBL_MAX;
this->UpdateAndShow(true);
}
@ -1195,9 +1237,12 @@ void ObjectManipulation::change_size_value(int axis, double value)
Vec3d ref_size = m_cache.size;
#if ENABLE_WORLD_COORDINATE
if (selection.is_single_volume_or_modifier()) {
if (is_local_coordinates())
ref_size = selection.get_first_volume()->bounding_box().size();
size = size.cwiseQuotient(ref_size);
ref_size = Vec3d::Ones();
#else
if (selection.is_single_volume() || selection.is_single_modifier()) {
#endif // ENABLE_WORLD_COORDINATE
const GLVolume* v = selection.get_first_volume();
const Vec3d local_size = size.cwiseQuotient(v->get_instance_scaling_factor());
const Vec3d local_ref_size = v->bounding_box().size().cwiseProduct(v->get_volume_scaling_factor());
@ -1205,15 +1250,20 @@ void ObjectManipulation::change_size_value(int axis, double value)
size = local_change.cwiseProduct(v->get_volume_scaling_factor());
ref_size = Vec3d::Ones();
#endif // ENABLE_WORLD_COORDINATE
}
else if (selection.is_single_full_instance())
else if (selection.is_single_full_instance()) {
#if ENABLE_WORLD_COORDINATE
ref_size = is_world_coordinates() ?
if (is_world_coordinates())
ref_size = selection.get_unscaled_instance_bounding_box().size();
size = size.cwiseQuotient(ref_size);
ref_size = Vec3d::Ones();
#else
ref_size = m_world_coordinates ?
#endif // ENABLE_WORLD_COORDINATE
selection.get_unscaled_instance_bounding_box().size() :
wxGetApp().model().objects[selection.get_first_volume()->object_idx()]->raw_mesh_bounding_box().size();
#endif // ENABLE_WORLD_COORDINATE
}
#if ENABLE_WORLD_COORDINATE
this->do_size(axis, size.cwiseQuotient(ref_size));
@ -1222,8 +1272,8 @@ void ObjectManipulation::change_size_value(int axis, double value)
#endif // ENABLE_WORLD_COORDINATE
m_cache.size = size;
m_cache.size_rounded(axis) = DBL_MAX;
this->UpdateAndShow(true);
m_cache.size_rounded(axis) = DBL_MAX;
this->UpdateAndShow(true);
}
void ObjectManipulation::do_scale(int axis, const Vec3d &scale) const
@ -1240,7 +1290,8 @@ void ObjectManipulation::do_scale(int axis, const Vec3d &scale) const
else if (is_instance_coordinates())
transformation_type.set_instance();
if (!selection.is_single_full_instance() && !selection.is_single_volume_or_modifier())
if (!(selection.is_single_volume_or_modifier() && is_local_coordinates()) &&
!(selection.is_single_full_instance() && is_instance_coordinates()))
transformation_type.set_relative();
const Vec3d scaling_factor = m_uniform_scale ? scale(axis) * Vec3d::Ones() : scale;
@ -1425,15 +1476,23 @@ void ObjectManipulation::sys_color_changed()
editor->sys_color_changed(this);
m_mirror_bitmap_on.sys_color_changed();
#if !ENABLE_WORLD_COORDINATE
m_mirror_bitmap_off.sys_color_changed();
m_mirror_bitmap_hidden.sys_color_changed();
#endif // !ENABLE_WORLD_COORDINATE
m_reset_scale_button->sys_color_changed();
m_reset_rotation_button->sys_color_changed();
m_drop_to_bed_button->sys_color_changed();
m_lock_bnt->sys_color_changed();
#if ENABLE_WORLD_COORDINATE
for (int id = 0; id < 3; ++id) {
m_mirror_buttons[id]->sys_color_changed();
}
#else
for (int id = 0; id < 3; ++id)
m_mirror_buttons[id].first->sys_color_changed();
#endif // ENABLE_WORLD_COORDINATE
}
#if ENABLE_WORLD_COORDINATE

View file

@ -132,6 +132,9 @@ private:
wxCheckBox* m_check_inch {nullptr};
#if ENABLE_WORLD_COORDINATE
std::array<ScalableButton*, 3> m_mirror_buttons;
#else
// Mirroring buttons and their current state
enum MirrorButtonState {
mbHidden,
@ -139,18 +142,21 @@ private:
mbActive
};
std::array<std::pair<ScalableButton*, MirrorButtonState>, 3> m_mirror_buttons;
#endif // ENABLE_WORLD_COORDINATE
// Bitmaps for the mirroring buttons.
ScalableBitmap m_mirror_bitmap_on;
#if !ENABLE_WORLD_COORDINATE
ScalableBitmap m_mirror_bitmap_off;
ScalableBitmap m_mirror_bitmap_hidden;
#endif // !ENABLE_WORLD_COORDINATE
// Needs to be updated from OnIdle?
bool m_dirty = false;
// Cached labels for the delayed update, not localized!
std::string m_new_move_label_string;
std::string m_new_rotate_label_string;
std::string m_new_scale_label_string;
std::string m_new_rotate_label_string;
std::string m_new_scale_label_string;
Vec3d m_new_position;
Vec3d m_new_rotation;
Vec3d m_new_scale;
@ -167,7 +173,10 @@ private:
choice_ctrl* m_word_local_combo { nullptr };
ScalableBitmap m_manifold_warning_bmp;
wxStaticBitmap* m_fix_throught_netfab_bitmap;
wxStaticBitmap* m_fix_throught_netfab_bitmap{ nullptr };
#if ENABLE_WORLD_COORDINATE
wxStaticBitmap* m_mirror_warning_bitmap{ nullptr };
#endif // ENABLE_WORLD_COORDINATE
#if ENABLE_WORLD_COORDINATE
// Currently focused editor (nullptr if none)

View file

@ -15,6 +15,7 @@
#include "libslic3r/TriangleMeshSlicer.hpp"
#include "imgui/imgui_internal.h"
#include "slic3r/GUI/MsgDialog.hpp"
namespace Slic3r {
namespace GUI {
@ -913,7 +914,7 @@ void GLGizmoCut3D::on_register_raycasters_for_picking()
m_raycasters.emplace_back(m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, i + m_connectors_group_id, *(m_shapes[connectors[i].attribs]).mesh_raycaster, Transform3d::Identity()));
}
}
else {
else if (!cut_line_processing()) {
m_raycasters.emplace_back(m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, X, *m_cone.mesh_raycaster, Transform3d::Identity()));
m_raycasters.emplace_back(m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, X, *m_cone.mesh_raycaster, Transform3d::Identity()));
@ -991,7 +992,7 @@ void GLGizmoCut3D::update_raycasters_for_picking_transform()
m_raycasters[i]->set_transform(translation_transform(pos) * m_rotation_m * scale_trafo);
}
}
else {
else if (!cut_line_processing()){
const Transform3d trafo = translation_transform(m_plane_center) * m_rotation_m;
const BoundingBoxf3 box = bounding_box();
@ -1376,10 +1377,14 @@ void GLGizmoCut3D::init_rendering_items()
init_from_angle_arc(m_angle_arc, m_angle, m_grabber_connection_len);
if (!m_plane.is_initialized() && !m_hide_cut_plane && !m_connectors_editing) {
#if 1
m_plane.init_from(its_make_frustum_dowel((double)m_cut_plane_radius_koef * m_radius, 0.3, m_cut_plane_as_circle ? 180 : 4));
#else
if (m_cut_plane_as_circle)
m_plane.init_from(its_make_frustum_dowel(2. * m_radius, 0.3, 180));
else
m_plane.init_from(its_make_square_plane(float(m_radius)));
#endif
}
}
@ -1419,9 +1424,13 @@ void GLGizmoCut3D::on_render()
m_selection_rectangle.render(m_parent);
}
void GLGizmoCut3D::render_debug_input_window()
void GLGizmoCut3D::render_debug_input_window(float x)
{
m_imgui->begin(wxString("DEBUG"));
ImVec2 pos = ImGui::GetWindowPos();
pos.x = x;
ImGui::SetWindowPos(pos, ImGuiCond_Always);
/*
static bool hide_clipped = false;
static bool fill_cut = false;
@ -1434,12 +1443,20 @@ void GLGizmoCut3D::render_debug_input_window()
m_imgui->slider_float("contour_width", &contour_width, 0.f, 3.f);
if (auto oc = m_c->object_clipper())
oc->set_behavior(hide_clipped || m_connectors_editing, fill_cut || m_connectors_editing, double(contour_width));
*/
ImGui::PushItemWidth(0.5f * m_label_width);
if (auto oc = m_c->object_clipper(); oc && m_imgui->slider_float("contour_width", &m_contour_width, 0.f, 3.f))
oc->set_behavior(m_connectors_editing, m_connectors_editing, double(m_contour_width));
ImGui::Separator();
*/
if (m_imgui->checkbox(_L("Render cut plane as circle"), m_cut_plane_as_circle))
m_plane.reset();
ImGui::PushItemWidth(0.5f * m_label_width);
if (m_imgui->slider_float("cut_plane_radius_koef", &m_cut_plane_radius_koef, 1.f, 2.f))
m_plane.reset();
m_imgui->end();
}
@ -1481,10 +1498,19 @@ void GLGizmoCut3D::render_shortcuts()
if (m_imgui->button("? " + (m_show_shortcuts ? wxString(ImGui::CollapseBtn) : wxString(ImGui::ExpandBtn))))
m_show_shortcuts = !m_show_shortcuts;
if (m_shortcut_label_width < 0.f) {
for (const auto& shortcut : m_shortcuts) {
const float width = m_imgui->calc_text_size(shortcut.first).x;
if (m_shortcut_label_width < width)
m_shortcut_label_width = width;
}
m_shortcut_label_width += +m_imgui->scaled(1.f);
}
if (m_show_shortcuts)
for (const auto&shortcut : m_shortcuts ){
m_imgui->text_colored(ImGuiWrapper::COL_ORANGE_LIGHT, shortcut.first);
ImGui::SameLine(m_label_width);
ImGui::SameLine(m_shortcut_label_width);
m_imgui->text(shortcut.second);
}
}
@ -1624,8 +1650,8 @@ void GLGizmoCut3D::render_cut_plane_input_window(CutConnectors &connectors)
ImGui::AlignTextToFramePadding();
m_imgui->text(wxString(ImGui::InfoMarkerSmall));
ImGui::SameLine();
m_imgui->text_colored(ImGuiWrapper::COL_ORANGE_LIGHT, _L("Hold SHIFT key and connect some two points of an object to cut by line"));
m_imgui->text_colored(ImGuiWrapper::COL_ORANGE_LIGHT,
get_wraped_wxString(_L("Hold SHIFT key and connect some two points of an object to cut by line"), 40));
ImGui::Separator();
render_build_size();
@ -1642,13 +1668,6 @@ void GLGizmoCut3D::render_cut_plane_input_window(CutConnectors &connectors)
reset_cut_plane();
m_imgui->disabled_end();
ImGui::SameLine(2.25f * m_label_width);
ImGui::PushItemWidth(0.75f * m_label_width);
m_is_contour_changed = m_imgui->slider_float("contour width", &m_contour_width, 0.f, 3.f);
if (auto oc = m_c->object_clipper(); oc && m_is_contour_changed)
oc->set_behavior(m_connectors_editing, m_connectors_editing, double(m_contour_width));
if (wxGetApp().plater()->printer_technology() == ptFFF) {
m_imgui->disabled_begin(!m_keep_upper || !m_keep_lower);
if (m_imgui->button(_L("Add/Edit connectors")))
@ -1658,18 +1677,25 @@ void GLGizmoCut3D::render_cut_plane_input_window(CutConnectors &connectors)
ImGui::Separator();
auto render_part_action_line = [this, connectors](const wxString& label, const wxString& suffix, bool& keep_part, bool& place_on_cut_part, bool& rotate_part) {
float label_width = 0;
for (const wxString& label : {_L("Upper part"), _L("Lower part")}) {
const float width = m_imgui->calc_text_size(label).x + m_imgui->scaled(1.5f);
if (label_width < width)
label_width = width;
}
auto render_part_action_line = [this, label_width, connectors](const wxString& label, const wxString& suffix, bool& keep_part, bool& place_on_cut_part, bool& rotate_part) {
bool keep = true;
ImGui::AlignTextToFramePadding();
m_imgui->text(label);
ImGui::SameLine(m_label_width);
ImGui::SameLine(label_width);
m_imgui->disabled_begin(!connectors.empty());
m_imgui->checkbox(_L("Keep") + suffix, connectors.empty() ? keep_part : keep);
m_imgui->disabled_end();
ImGui::SameLine(2 * m_label_width);
ImGui::SameLine();
m_imgui->disabled_begin(!keep_part);
if (m_imgui->checkbox(_L("Place on cut") + suffix, place_on_cut_part))
@ -1813,7 +1839,8 @@ void GLGizmoCut3D::on_render_input_window(float x, float y, float bottom_limit)
m_imgui->end();
render_debug_input_window();
if (!m_connectors_editing) // connectors mode
render_debug_input_window(x);
}
// get volume transformation regarding to the "border". Border is related from the size of connectors

View file

@ -111,7 +111,9 @@ class GLGizmoCut3D : public GLGizmoBase
bool force_update_clipper_on_render{false};
float m_contour_width{ 0.4f };
float m_cut_plane_radius_koef{ 1.5f };
bool m_is_contour_changed{ false };
float m_shortcut_label_width{ -1.f };
mutable std::vector<bool> m_selected; // which pins are currently selected
int m_selected_count{ 0 };
@ -199,7 +201,7 @@ protected:
void on_stop_dragging() override;
void on_render() override;
void render_debug_input_window();
void render_debug_input_window(float x);
void adjust_window_position(float x, float y, float bottom_limit);
void unselect_all_connectors();
void select_all_connectors();

View file

@ -1359,10 +1359,10 @@ void GLGizmoMeasure::render_dimensioning()
action_exit();
ImGui::SameLine();
if (m_imgui->button(_u8L("Scale")))
if (m_imgui->button(_CTX(L_CONTEXT("Scale", "Verb"), "Verb")))
action_scale(edit_value, curr_value);
ImGui::SameLine();
if (m_imgui->button(_u8L("Cancel")))
if (m_imgui->button(_L("Cancel")))
action_exit();
ImGui::EndPopup();
}
@ -1991,7 +1991,7 @@ void GLGizmoMeasure::on_render_input_window(float x, float y, float bottom_limit
radius = (on_circle - center).norm();
if (use_inches)
radius = ObjectManipulation::mm_to_in * radius;
text += " (" + _u8L("Diameter:") + " " + format_double(2.0 * radius) + units + ")";
text += " (" + _u8L("Diameter") + ": " + format_double(2.0 * radius) + units + ")";
}
return text;
};
@ -2004,7 +2004,7 @@ void GLGizmoMeasure::on_render_input_window(float x, float y, float bottom_limit
}
m_imgui->disabled_begin(!m_selected_features.first.feature.has_value());
if (m_imgui->button(_u8L("Restart selection"))) {
if (m_imgui->button(_L("Restart selection"))) {
m_selected_features.reset();
m_selected_sphere_raycasters.clear();
m_imgui->set_requires_extra_frame();

View file

@ -614,7 +614,7 @@ bool GLGizmoRotate3D::on_mouse(const wxMouseEvent &mouse_event)
#if ENABLE_WORLD_COORDINATE
TransformationType transformation_type;
if (m_parent.get_selection().is_wipe_tower())
transformation_type = TransformationType::Instance_Relative_Joint;
transformation_type = TransformationType::World_Relative_Joint;
else {
switch (wxGetApp().obj_manipul()->get_coordinates_type())
{

View file

@ -119,10 +119,10 @@ Selection::Selection()
{
this->set_bounding_boxes_dirty();
#if ENABLE_WORLD_COORDINATE
m_axes.set_stem_radius(0.15f);
m_axes.set_stem_length(3.0f);
m_axes.set_tip_radius(0.45f);
m_axes.set_tip_length(1.5f);
m_axes.set_stem_radius(0.5f);
m_axes.set_stem_length(20.0f);
m_axes.set_tip_radius(1.5f);
m_axes.set_tip_length(5.0f);
#endif // ENABLE_WORLD_COORDINATE
}
@ -828,18 +828,15 @@ void Selection::translate(const Vec3d& displacement, TransformationType transfor
assert(is_from_fully_selected_instance(i));
if (transformation_type.world())
v.set_instance_transformation(Geometry::translation_transform(displacement) * volume_data.get_instance_full_matrix());
else if (transformation_type.local()) {
else if (transformation_type.instance()) {
const Vec3d world_displacement = volume_data.get_instance_rotation_matrix() * displacement;
v.set_instance_transformation(Geometry::translation_transform(world_displacement) * volume_data.get_instance_full_matrix());
}
else
assert(false);
}
else {
const Vec3d offset = transformation_type.local() ?
(Vec3d)(volume_data.get_volume_transform().get_rotation_matrix() * displacement) : displacement;
transform_volume_relative(v, volume_data, transformation_type, Geometry::translation_transform(offset));
}
else
transform_volume_relative(v, volume_data, transformation_type, Geometry::translation_transform(displacement), m_cache.dragging_center);
}
#if !DISABLE_INSTANCES_SYNCH
@ -918,7 +915,7 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_
else {
if (transformation_type.world())
new_rotation_matrix = rotation_matrix * inst_trafo.get_rotation_matrix();
else if (transformation_type.local())
else if (transformation_type.instance())
new_rotation_matrix = inst_trafo.get_rotation_matrix() * rotation_matrix;
else
assert(false);
@ -931,13 +928,14 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_
inst_trafo.get_scaling_factor_matrix(), inst_trafo.get_mirror_matrix()));
}
else {
if (transformation_type.absolute()) {
const Geometry::Transformation& volume_trafo = volume_data.get_volume_transform();
v.set_volume_transformation(Geometry::assemble_transform(volume_trafo.get_offset_matrix(), Geometry::rotation_transform(rotation),
volume_trafo.get_scaling_factor_matrix(), volume_trafo.get_mirror_matrix()));
if (!is_single_volume_or_modifier()) {
assert(transformation_type.world());
transform_volume_relative(v, volume_data, transformation_type, rotation_matrix, m_cache.dragging_center);
}
else {
transformation_type.set_independent();
transform_volume_relative(v, volume_data, transformation_type, rotation_matrix, m_cache.dragging_center);
}
else
transform_volume_relative(v, volume_data, transformation_type, Geometry::rotation_transform(rotation));
}
}
@ -948,7 +946,7 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_
SyncRotationType synch;
if (transformation_type.world() && rot_axis_max == 2)
synch = SyncRotationType::NONE;
else if (transformation_type.local())
else if (transformation_type.instance())
synch = SyncRotationType::FULL;
else
synch = SyncRotationType::GENERAL;
@ -1283,6 +1281,13 @@ void Selection::scale_to_fit_print_volume(const BuildVolume& volume)
}
}
#if ENABLE_WORLD_COORDINATE
void Selection::mirror(Axis axis, TransformationType transformation_type)
{
const Vec3d mirror((axis == X) ? -1.0 : 1.0, (axis == Y) ? -1.0 : 1.0, (axis == Z) ? -1.0 : 1.0);
scale_and_translate(mirror, Vec3d::Zero(), transformation_type);
}
#else
void Selection::mirror(Axis axis)
{
if (!m_valid)
@ -1305,6 +1310,7 @@ void Selection::mirror(Axis axis)
set_bounding_boxes_dirty();
}
#endif // ENABLE_WORLD_COORDINATE
#if ENABLE_WORLD_COORDINATE
void Selection::scale_and_translate(const Vec3d& scale, const Vec3d& translation, TransformationType transformation_type)
@ -1322,24 +1328,32 @@ void Selection::scale_and_translate(const Vec3d& scale, const Vec3d& translation
if (transformation_type.absolute()) {
// convert from absolute scaling to relative scaling
BoundingBoxf3 original_box;
BoundingBoxf3 reference_box = m_box.get_bounding_box();
if (m_mode == Instance) {
assert(is_from_fully_selected_instance(i));
if (is_single_full_instance()) {
if (transformation_type.world())
original_box = get_full_unscaled_instance_bounding_box();
else
original_box = get_full_unscaled_instance_local_bounding_box();
}
else
original_box = get_bounding_box();
}
else {
if (transformation_type.world())
original_box = v.transformed_convex_hull_bounding_box((volume_data.get_instance_transform() *
volume_data.get_volume_transform()).get_matrix_no_scaling_factor());
if (!is_single_volume_or_modifier())
original_box = get_bounding_box();
else if (transformation_type.world())
original_box = get_bounding_box();
else if (transformation_type.instance())
original_box = v.transformed_convex_hull_bounding_box(volume_data.get_volume_transform().get_matrix_no_scaling_factor());
else
original_box = v.transformed_convex_hull_bounding_box(volume_data.get_volume_transform().get_matrix());
else {
original_box = v.bounding_box();
reference_box = v.bounding_box().transformed(volume_data.get_volume_transform().get_scaling_factor_matrix());
}
transformation_type.set_relative();
}
relative_scale = original_box.size().cwiseProduct(scale).cwiseQuotient(m_box.get_bounding_box().size());
relative_scale = original_box.size().cwiseProduct(scale).cwiseQuotient(reference_box.size());
}
if (m_mode == Instance) {
@ -1353,7 +1367,7 @@ void Selection::scale_and_translate(const Vec3d& scale, const Vec3d& translation
Geometry::translation_transform(translation) * inst_trafo.get_offset_matrix();
v.set_instance_transformation(offset_matrix * scale_matrix * inst_trafo.get_matrix_no_offset());
}
else if (transformation_type.local()) {
else if (transformation_type.instance()) {
const Transform3d scale_matrix = Geometry::scale_transform(relative_scale);
Vec3d offset;
if (transformation_type.joint() && translation.isApprox(Vec3d::Zero())) {
@ -1370,8 +1384,16 @@ void Selection::scale_and_translate(const Vec3d& scale, const Vec3d& translation
else
assert(false);
}
else
transform_volume_relative(v, volume_data, transformation_type, Geometry::translation_transform(translation) * Geometry::scale_transform(relative_scale));
else {
if (!is_single_volume_or_modifier()) {
assert(transformation_type.world());
transform_volume_relative(v, volume_data, transformation_type, Geometry::translation_transform(translation) * Geometry::scale_transform(relative_scale), m_cache.dragging_center);
}
else {
transformation_type.set_independent();
transform_volume_relative(v, volume_data, transformation_type, Geometry::translation_transform(translation) * Geometry::scale_transform(relative_scale), m_cache.dragging_center);
}
}
}
#if !DISABLE_INSTANCES_SYNCH
@ -1707,8 +1729,8 @@ void Selection::render(float scale_factor)
}
else if (coordinates_type == ECoordinatesType::Local && is_single_volume_or_modifier()) {
const GLVolume& v = *get_first_volume();
box = v.transformed_convex_hull_bounding_box(v.get_volume_transformation().get_scaling_factor_matrix());
trafo = v.get_instance_transformation().get_matrix() * v.get_volume_transformation().get_matrix_no_scaling_factor();
box = v.bounding_box();
trafo = v.world_matrix();
}
else {
const Selection::IndicesList& ids = get_volume_idxs();
@ -1716,9 +1738,7 @@ void Selection::render(float scale_factor)
const GLVolume& v = *get_volume(id);
box.merge(v.transformed_convex_hull_bounding_box(v.get_volume_transformation().get_matrix()));
}
const Geometry::Transformation inst_trafo = get_first_volume()->get_instance_transformation();
box = box.transformed(inst_trafo.get_scaling_factor_matrix());
trafo = inst_trafo.get_matrix_no_scaling_factor();
trafo = get_first_volume()->get_instance_transformation().get_matrix();
}
render_bounding_box(box, trafo, ColorRGB::WHITE());
@ -1856,7 +1876,7 @@ void Selection::render_sidebar_hints(const std::string& sidebar_field)
#if ENABLE_WORLD_COORDINATE
if (!boost::starts_with(sidebar_field, "layer")) {
if (!wxGetApp().obj_manipul()->is_world_coordinates())
if (wxGetApp().obj_manipul()->is_instance_coordinates())
m_axes.render(Geometry::translation_transform(axes_center) * orient_matrix, 0.25f);
}
#endif // ENABLE_WORLD_COORDINATE
@ -3021,17 +3041,24 @@ void Selection::paste_objects_from_clipboard()
#if ENABLE_WORLD_COORDINATE
void Selection::transform_volume_relative(GLVolume& volume, const VolumeCache& volume_data, TransformationType transformation_type,
const Transform3d& transform)
const Transform3d& transform, const Vec3d& world_pivot)
{
const Geometry::Transformation& inst_trafo = volume_data.get_instance_transform();
assert(transformation_type.relative());
const Geometry::Transformation& volume_trafo = volume_data.get_volume_transform();
const Geometry::Transformation& inst_trafo = volume_data.get_instance_transform();
if (transformation_type.world()) {
const Vec3d inst_pivot = transformation_type.independent() ? volume_trafo.get_offset() : (Vec3d)(inst_trafo.get_matrix().inverse() * world_pivot);
const Transform3d inst_matrix_no_offset = inst_trafo.get_matrix_no_offset();
const Transform3d new_volume_matrix = inst_matrix_no_offset.inverse() * transform * inst_matrix_no_offset;
volume.set_volume_transformation(volume_trafo.get_offset_matrix() * new_volume_matrix * volume_trafo.get_matrix_no_offset());
const Transform3d trafo = Geometry::translation_transform(inst_pivot) * inst_matrix_no_offset.inverse() * transform * inst_matrix_no_offset * Geometry::translation_transform(-inst_pivot);
volume.set_volume_transformation(trafo * volume_trafo.get_matrix());
}
else if (transformation_type.instance()) {
const Vec3d inst_pivot = transformation_type.independent() ? volume_trafo.get_offset() : (Vec3d)(inst_trafo.get_matrix().inverse() * world_pivot);
const Transform3d trafo = Geometry::translation_transform(inst_pivot) * transform * Geometry::translation_transform(-inst_pivot);
volume.set_volume_transformation(trafo * volume_trafo.get_matrix());
}
else if (transformation_type.instance())
volume.set_volume_transformation(volume_trafo.get_offset_matrix() * transform * volume_trafo.get_matrix_no_offset());
else if (transformation_type.local()) {
const Geometry::Transformation trafo(transform);
volume.set_volume_transformation(trafo.get_offset_matrix() * volume_trafo.get_matrix() * trafo.get_matrix_no_offset());

View file

@ -300,7 +300,7 @@ public:
void set_deserialized(EMode mode, const std::vector<std::pair<size_t, size_t>> &volumes_and_instances);
// Update the selection based on the new instance IDs.
void instances_changed(const std::vector<size_t> &instance_ids_selected);
void instances_changed(const std::vector<size_t> &instance_ids_selected);
// Update the selection based on the map from old indices to new indices after m_volumes changed.
// If the current selection is by instance, this call may select newly added volumes, if they belong to already selected instances.
void volumes_changed(const std::vector<size_t> &map_volume_old_to_new);
@ -402,11 +402,12 @@ public:
void flattening_rotate(const Vec3d& normal);
void scale(const Vec3d& scale, TransformationType transformation_type);
void scale_to_fit_print_volume(const BuildVolume& volume);
void mirror(Axis axis);
#if ENABLE_WORLD_COORDINATE
void scale_and_translate(const Vec3d& scale, const Vec3d& translation, TransformationType transformation_type);
void mirror(Axis axis, TransformationType transformation_type);
void reset_skew();
#else
void mirror(Axis axis);
void translate(unsigned int object_idx, const Vec3d& displacement);
#endif // ENABLE_WORLD_COORDINATE
void translate(unsigned int object_idx, unsigned int instance_idx, const Vec3d& displacement);
@ -501,7 +502,7 @@ private:
#if ENABLE_WORLD_COORDINATE
void transform_volume_relative(GLVolume& volume, const VolumeCache& volume_data, TransformationType transformation_type,
const Transform3d& transform);
const Transform3d& transform, const Vec3d& world_pivot);
#endif // ENABLE_WORLD_COORDINATE
};