mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-07-13 00:01:51 +08:00
Tech ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES - 1st installment: introduction of instance reference system in part manipulation
Fixed conflicts during rebase with master
This commit is contained in:
parent
679f8b0111
commit
79bdcefbde
@ -73,6 +73,8 @@
|
||||
#define ENABLE_WORLD_COORDINATE (1 && ENABLE_2_5_0_ALPHA1)
|
||||
// Enable showing world coordinates of volumes' offset relative to the instance containing them
|
||||
#define ENABLE_WORLD_COORDINATE_VOLUMES_LOCAL_OFFSET (1 && ENABLE_WORLD_COORDINATE)
|
||||
// Enable editing instance coordinates of volumes
|
||||
#define ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES (1 && ENABLE_WORLD_COORDINATE)
|
||||
// Enable modified camera control using mouse
|
||||
#define ENABLE_NEW_CAMERA_MOVEMENTS (1 && ENABLE_2_5_0_ALPHA1)
|
||||
// Enable modified rectangle selection
|
||||
|
@ -3269,7 +3269,11 @@ void ObjectList::update_selections()
|
||||
return;
|
||||
sels.Add(m_objects_model->GetItemById(selection.get_object_idx()));
|
||||
}
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
else if (selection.is_single_volume_or_modifier()) {
|
||||
#else
|
||||
else if (selection.is_single_volume() || selection.is_any_modifier()) {
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
const auto gl_vol = selection.get_volume(*selection.get_volume_idxs().begin());
|
||||
if (m_objects_model->GetVolumeIdByItem(m_objects_model->GetParent(item)) == gl_vol->volume_idx())
|
||||
return;
|
||||
|
@ -52,10 +52,17 @@ static choice_ctrl* create_word_local_combo(wxWindow *parent)
|
||||
temp->SetFont(Slic3r::GUI::wxGetApp().normal_font());
|
||||
if (!wxOSX) temp->SetBackgroundStyle(wxBG_STYLE_PAINT);
|
||||
|
||||
#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
temp->Append(ObjectManipulation::coordinate_type_str(ObjectManipulation::ECoordinatesType::World));
|
||||
temp->Append(ObjectManipulation::coordinate_type_str(ObjectManipulation::ECoordinatesType::Instance));
|
||||
temp->Append(ObjectManipulation::coordinate_type_str(ObjectManipulation::ECoordinatesType::Local));
|
||||
temp->Select((int)ObjectManipulation::ECoordinatesType::World);
|
||||
#else
|
||||
temp->Append(_L("World coordinates"));
|
||||
temp->Append(_L("Local coordinates"));
|
||||
temp->SetSelection(0);
|
||||
temp->SetValue(temp->GetString(0));
|
||||
#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
|
||||
temp->SetToolTip(_L("Select coordinate space, in which the transformation will be performed."));
|
||||
return temp;
|
||||
@ -81,8 +88,14 @@ void msw_rescale_word_local_combo(choice_ctrl* combo)
|
||||
// Set rescaled size
|
||||
combo->SetSize(size);
|
||||
|
||||
#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
combo->Append(ObjectManipulation::coordinate_type_str(ObjectManipulation::ECoordinatesType::World));
|
||||
combo->Append(ObjectManipulation::coordinate_type_str(ObjectManipulation::ECoordinatesType::Instance));
|
||||
combo->Append(ObjectManipulation::coordinate_type_str(ObjectManipulation::ECoordinatesType::Local));
|
||||
#else
|
||||
combo->Append(_L("World coordinates"));
|
||||
combo->Append(_L("Local coordinates"));
|
||||
#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
|
||||
combo->SetValue(selection);
|
||||
#else
|
||||
@ -101,6 +114,7 @@ static void set_font_and_background_style(wxWindow* win, const wxFont& font)
|
||||
|
||||
static const wxString axes_color_text[] = { "#990000", "#009900", "#000099" };
|
||||
static const wxString axes_color_back[] = { "#f5dcdc", "#dcf5dc", "#dcdcf5" };
|
||||
|
||||
ObjectManipulation::ObjectManipulation(wxWindow* parent) :
|
||||
OG_Settings(parent, true)
|
||||
{
|
||||
@ -157,7 +171,11 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
|
||||
// Add world local combobox
|
||||
m_word_local_combo = create_word_local_combo(parent);
|
||||
m_word_local_combo->Bind(wxEVT_COMBOBOX, ([this](wxCommandEvent& evt) {
|
||||
#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
this->set_coordinates_type(evt.GetString());
|
||||
#else
|
||||
this->set_world_coordinates(evt.GetSelection() != 1);
|
||||
#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
}), m_word_local_combo->GetId());
|
||||
|
||||
// Small trick to correct layouting in different view_mode :
|
||||
@ -264,7 +282,11 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
|
||||
GLCanvas3D* canvas = wxGetApp().plater()->canvas3D();
|
||||
Selection& selection = canvas->get_selection();
|
||||
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
if (selection.is_single_volume_or_modifier()) {
|
||||
#else
|
||||
if (selection.is_single_volume() || selection.is_single_modifier()) {
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
GLVolume* volume = const_cast<GLVolume*>(selection.get_volume(*selection.get_volume_idxs().begin()));
|
||||
volume->set_volume_mirror(axis, -volume->get_volume_mirror(axis));
|
||||
}
|
||||
@ -327,11 +349,15 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
|
||||
GLCanvas3D* canvas = wxGetApp().plater()->canvas3D();
|
||||
Selection& selection = canvas->get_selection();
|
||||
|
||||
if (selection.is_single_volume() || selection.is_single_modifier()) {
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
|
||||
if (selection.is_single_volume_or_modifier()) {
|
||||
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
|
||||
const double min_z = get_volume_min_z(*volume);
|
||||
#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
if (!is_world_coordinates()) {
|
||||
#else
|
||||
if (!m_world_coordinates) {
|
||||
#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
const Vec3d diff = m_cache.position - volume->get_instance_transformation().get_matrix(true).inverse() * (min_z * Vec3d::UnitZ());
|
||||
|
||||
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Drop to bed"));
|
||||
@ -344,6 +370,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
|
||||
change_position_value(2, m_cache.position.z() - min_z);
|
||||
}
|
||||
#else
|
||||
if (selection.is_single_volume() || selection.is_single_modifier()) {
|
||||
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
|
||||
const Vec3d diff = m_cache.position - volume->get_instance_transformation().get_matrix(true).inverse() * (get_volume_min_z(*volume) * Vec3d::UnitZ());
|
||||
|
||||
@ -356,7 +383,11 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
|
||||
else if (selection.is_single_full_instance()) {
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
const double min_z = selection.get_scaled_instance_bounding_box().min.z();
|
||||
#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
if (!is_world_coordinates()) {
|
||||
#else
|
||||
if (!m_world_coordinates) {
|
||||
#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
|
||||
const Vec3d diff = m_cache.position - volume->get_instance_transformation().get_matrix(true).inverse() * (min_z * Vec3d::UnitZ());
|
||||
|
||||
@ -396,7 +427,11 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
|
||||
GLCanvas3D* canvas = wxGetApp().plater()->canvas3D();
|
||||
Selection& selection = canvas->get_selection();
|
||||
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
if (selection.is_single_volume_or_modifier()) {
|
||||
#else
|
||||
if (selection.is_single_volume() || selection.is_single_modifier()) {
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
GLVolume* volume = const_cast<GLVolume*>(selection.get_volume(*selection.get_volume_idxs().begin()));
|
||||
volume->set_volume_rotation(Vec3d::Zero());
|
||||
}
|
||||
@ -477,7 +512,19 @@ void ObjectManipulation::Show(const bool show)
|
||||
// Show the "World Coordinates" / "Local Coordintes" Combo in Advanced / Expert mode only.
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
const Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
|
||||
bool show_world_local_combo = wxGetApp().get_mode() != comSimple && (selection.is_single_full_instance() || selection.is_single_volume() || selection.is_single_modifier());
|
||||
bool show_world_local_combo = wxGetApp().get_mode() != comSimple && (selection.is_single_full_instance() || selection.is_single_volume_or_modifier());
|
||||
#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
if (selection.is_single_volume_or_modifier() && m_word_local_combo->GetCount() < 3) {
|
||||
m_word_local_combo->Insert(coordinate_type_str(ECoordinatesType::Instance), wxNullBitmap, 1);
|
||||
m_word_local_combo->Select((int)ECoordinatesType::World);
|
||||
this->set_coordinates_type(m_word_local_combo->GetStringSelection());
|
||||
}
|
||||
else if (selection.is_single_full_instance() && m_word_local_combo->GetCount() > 2) {
|
||||
m_word_local_combo->Delete(1);
|
||||
m_word_local_combo->Select((int)ECoordinatesType::World);
|
||||
this->set_coordinates_type(m_word_local_combo->GetStringSelection());
|
||||
}
|
||||
#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
#else
|
||||
bool show_world_local_combo = wxGetApp().plater()->canvas3D()->get_selection().is_single_full_instance() && wxGetApp().get_mode() != comSimple;
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
@ -558,8 +605,10 @@ void ObjectManipulation::update_settings_value(const Selection& selection)
|
||||
m_new_rotate_label_string = L("Rotation");
|
||||
m_new_scale_label_string = L("Scale factors");
|
||||
|
||||
#if !ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
if (wxGetApp().get_mode() == comSimple)
|
||||
m_world_coordinates = true;
|
||||
#endif // !ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
|
||||
ObjectList* obj_list = wxGetApp().obj_list();
|
||||
if (selection.is_single_full_instance()) {
|
||||
@ -570,14 +619,22 @@ void ObjectManipulation::update_settings_value(const Selection& selection)
|
||||
#endif // !ENABLE_WORLD_COORDINATE
|
||||
|
||||
// Verify whether the instance rotation is multiples of 90 degrees, so that the scaling in world coordinates is possible.
|
||||
if (m_world_coordinates && ! m_uniform_scale &&
|
||||
#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
if (is_world_coordinates() && !m_uniform_scale &&
|
||||
#else
|
||||
if (m_world_coordinates && ! m_uniform_scale &&
|
||||
#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
! Geometry::is_rotation_ninety_degrees(volume->get_instance_rotation())) {
|
||||
// Manipulating an instance in the world coordinate system, rotation is not multiples of ninety degrees, therefore enforce uniform scaling.
|
||||
m_uniform_scale = true;
|
||||
m_lock_bnt->SetLock(true);
|
||||
}
|
||||
|
||||
#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
if (is_world_coordinates()) {
|
||||
#else
|
||||
if (m_world_coordinates) {
|
||||
#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
m_new_position = volume->get_instance_offset();
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
@ -613,11 +670,19 @@ void ObjectManipulation::update_settings_value(const Selection& selection)
|
||||
m_new_scale_label_string = L("Scale");
|
||||
m_new_enabled = true;
|
||||
}
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
else if (selection.is_single_volume_or_modifier()) {
|
||||
#else
|
||||
else if (selection.is_single_modifier() || selection.is_single_volume()) {
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
// the selection contains a single volume
|
||||
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
if (is_world_coordinates()) {
|
||||
#else
|
||||
if (m_world_coordinates) {
|
||||
#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
const Geometry::Transformation trafo(volume->world_matrix());
|
||||
|
||||
#if ENABLE_WORLD_COORDINATE_VOLUMES_LOCAL_OFFSET
|
||||
@ -722,11 +787,13 @@ void ObjectManipulation::update_if_dirty()
|
||||
m_lock_bnt->enable();
|
||||
}
|
||||
|
||||
{
|
||||
#if !ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
{
|
||||
int new_selection = m_world_coordinates ? 0 : 1;
|
||||
if (m_word_local_combo->GetSelection() != new_selection)
|
||||
m_word_local_combo->SetSelection(new_selection);
|
||||
}
|
||||
#endif // !ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
|
||||
if (m_new_enabled)
|
||||
m_og->enable();
|
||||
@ -754,12 +821,14 @@ void ObjectManipulation::update_reset_buttons_visibility()
|
||||
bool show_scale = false;
|
||||
bool show_drop_to_bed = false;
|
||||
|
||||
if (selection.is_single_full_instance() || selection.is_single_modifier() || selection.is_single_volume()) {
|
||||
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
if (selection.is_single_full_instance() || selection.is_single_volume_or_modifier()) {
|
||||
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
|
||||
Vec3d rotation = Vec3d::Zero();
|
||||
Vec3d scale = Vec3d::Ones();
|
||||
#else
|
||||
if (selection.is_single_full_instance() || selection.is_single_modifier() || selection.is_single_volume()) {
|
||||
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
|
||||
Vec3d rotation;
|
||||
Vec3d scale;
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
@ -811,8 +880,16 @@ void ObjectManipulation::update_mirror_buttons_visibility()
|
||||
Selection& selection = canvas->get_selection();
|
||||
std::array<MirrorButtonState, 3> new_states = {mbHidden, mbHidden, mbHidden};
|
||||
|
||||
#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
if (!is_world_coordinates()) {
|
||||
#else
|
||||
if (!m_world_coordinates) {
|
||||
#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
if (selection.is_single_full_instance() || selection.is_single_volume_or_modifier()) {
|
||||
#else
|
||||
if (selection.is_single_full_instance() || selection.is_single_modifier() || selection.is_single_volume()) {
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
|
||||
Vec3d mirror;
|
||||
|
||||
@ -877,6 +954,19 @@ void ObjectManipulation::update_warning_icon_state(const MeshErrorsInfo& warning
|
||||
m_fix_throught_netfab_bitmap->SetToolTip(tooltip);
|
||||
}
|
||||
|
||||
#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
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"); }
|
||||
default: { assert(false); break; }
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
|
||||
void ObjectManipulation::reset_settings_value()
|
||||
{
|
||||
m_new_position = Vec3d::Zero();
|
||||
@ -901,7 +991,11 @@ void ObjectManipulation::change_position_value(int axis, double value)
|
||||
Selection& selection = canvas->get_selection();
|
||||
selection.setup_cache();
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
selection.translate(position - m_cache.position, !is_world_coordinates());
|
||||
#else
|
||||
selection.translate(position - m_cache.position, !m_world_coordinates);
|
||||
#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
#else
|
||||
selection.translate(position - m_cache.position, selection.requires_local_axes());
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
@ -928,7 +1022,11 @@ void ObjectManipulation::change_rotation_value(int axis, double value)
|
||||
if (selection.is_single_full_instance())
|
||||
transformation_type.set_independent();
|
||||
|
||||
#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
if (!is_world_coordinates()) {
|
||||
#else
|
||||
if (!m_world_coordinates) {
|
||||
#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
//FIXME Selection::rotate() does not process absolute rotations correctly: It does not recognize the axis index, which was changed.
|
||||
// transformation_type.set_absolute();
|
||||
transformation_type.set_local();
|
||||
@ -987,7 +1085,11 @@ void ObjectManipulation::change_size_value(int axis, double value)
|
||||
const Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
|
||||
|
||||
Vec3d ref_size = m_cache.size;
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
if (selection.is_single_volume_or_modifier()) {
|
||||
#else
|
||||
if (selection.is_single_volume() || selection.is_single_modifier()) {
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
const GLVolume* v = selection.get_volume(*selection.get_volume_idxs().begin());
|
||||
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());
|
||||
@ -997,7 +1099,11 @@ void ObjectManipulation::change_size_value(int axis, double value)
|
||||
ref_size = Vec3d::Ones();
|
||||
}
|
||||
else if (selection.is_single_full_instance())
|
||||
ref_size = m_world_coordinates ?
|
||||
#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
ref_size = is_world_coordinates() ?
|
||||
#else
|
||||
ref_size = m_world_coordinates ?
|
||||
#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
selection.get_unscaled_instance_bounding_box().size() :
|
||||
wxGetApp().model().objects[selection.get_volume(*selection.get_volume_idxs().begin())->object_idx()]->raw_mesh_bounding_box().size();
|
||||
|
||||
@ -1017,16 +1123,24 @@ void ObjectManipulation::do_scale(int axis, const Vec3d &scale) const
|
||||
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
TransformationType transformation_type;
|
||||
#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
if (!is_world_coordinates())
|
||||
#else
|
||||
if (!m_world_coordinates)
|
||||
#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
transformation_type.set_local();
|
||||
|
||||
bool uniform_scale = m_uniform_scale || selection.requires_uniform_scale();
|
||||
Vec3d scaling_factor = uniform_scale ? scale(axis) * Vec3d::Ones() : scale;
|
||||
|
||||
#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
if (!uniform_scale && is_world_coordinates()) {
|
||||
#else
|
||||
if (!uniform_scale && m_world_coordinates) {
|
||||
#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
if (selection.is_single_full_instance())
|
||||
scaling_factor = (Geometry::assemble_transform(Vec3d::Zero(), selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_rotation()).inverse() * scaling_factor).cwiseAbs();
|
||||
else if (selection.is_single_volume() || selection.is_single_modifier()) {
|
||||
else if (selection.is_single_volume_or_modifier()) {
|
||||
const Transform3d mi = Geometry::assemble_transform(Vec3d::Zero(), selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_rotation()).inverse();
|
||||
const Transform3d mv = Geometry::assemble_transform(Vec3d::Zero(), selection.get_volume(*selection.get_volume_idxs().begin())->get_volume_rotation()).inverse();
|
||||
scaling_factor = (mv * mi * scaling_factor).cwiseAbs();
|
||||
@ -1086,7 +1200,11 @@ void ObjectManipulation::on_change(const std::string& opt_key, int axis, double
|
||||
void ObjectManipulation::set_uniform_scaling(const bool new_value)
|
||||
{
|
||||
const Selection &selection = wxGetApp().plater()->canvas3D()->get_selection();
|
||||
if (selection.is_single_full_instance() && m_world_coordinates && !new_value) {
|
||||
#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
if (selection.is_single_full_instance() && is_world_coordinates() && !new_value) {
|
||||
#else
|
||||
if (selection.is_single_full_instance() && m_world_coordinates && !new_value) {
|
||||
#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
// Verify whether the instance rotation is multiples of 90 degrees, so that the scaling in world coordinates is possible.
|
||||
// all volumes in the selection belongs to the same instance, any of them contains the needed instance data, so we take the first one
|
||||
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
|
||||
@ -1119,6 +1237,23 @@ void ObjectManipulation::set_uniform_scaling(const bool new_value)
|
||||
}
|
||||
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
void ObjectManipulation::set_coordinates_type(ECoordinatesType type)
|
||||
{
|
||||
if (wxGetApp().get_mode() == comSimple)
|
||||
type = ECoordinatesType::World;
|
||||
|
||||
if (m_coordinates_type == type)
|
||||
return;
|
||||
|
||||
m_coordinates_type = type;
|
||||
this->UpdateAndShow(true);
|
||||
GLCanvas3D* canvas = wxGetApp().plater()->canvas3D();
|
||||
canvas->get_gizmos_manager().update_data();
|
||||
canvas->set_as_dirty();
|
||||
canvas->request_extra_frame();
|
||||
}
|
||||
#else
|
||||
void ObjectManipulation::set_world_coordinates(const bool world_coordinates)
|
||||
{
|
||||
m_world_coordinates = world_coordinates;
|
||||
@ -1135,6 +1270,7 @@ bool ObjectManipulation::get_world_coordinates() const
|
||||
return wxGetApp().get_mode() != comSimple && (selection.is_single_full_instance() || selection.is_single_volume() || selection.is_single_modifier()) ?
|
||||
m_world_coordinates : true;
|
||||
}
|
||||
#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
|
||||
void ObjectManipulation::msw_rescale()
|
||||
@ -1200,6 +1336,19 @@ void ObjectManipulation::sys_color_changed()
|
||||
m_mirror_buttons[id].first->msw_rescale();
|
||||
}
|
||||
|
||||
#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
void ObjectManipulation::set_coordinates_type(const wxString& type_string)
|
||||
{
|
||||
ECoordinatesType type = ECoordinatesType::World;
|
||||
if (type_string == coordinate_type_str(ECoordinatesType::Instance))
|
||||
type = ECoordinatesType::Instance;
|
||||
else if (type_string == coordinate_type_str(ECoordinatesType::Local))
|
||||
type = ECoordinatesType::Local;
|
||||
|
||||
this->set_coordinates_type(type);
|
||||
}
|
||||
#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
|
||||
static const char axes[] = { 'x', 'y', 'z' };
|
||||
ManipulationEditor::ManipulationEditor(ObjectManipulation* parent,
|
||||
const std::string& opt_key,
|
||||
|
@ -72,6 +72,15 @@ public:
|
||||
static const double in_to_mm;
|
||||
static const double mm_to_in;
|
||||
|
||||
#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
enum class ECoordinatesType : unsigned char
|
||||
{
|
||||
World,
|
||||
Instance,
|
||||
Local
|
||||
};
|
||||
#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
|
||||
private:
|
||||
struct Cache
|
||||
{
|
||||
@ -148,8 +157,12 @@ private:
|
||||
Vec3d m_new_size;
|
||||
bool m_new_enabled {true};
|
||||
bool m_uniform_scale {true};
|
||||
#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
ECoordinatesType m_coordinates_type{ ECoordinatesType::World };
|
||||
#else
|
||||
// Does the object manipulation panel work in World or Local coordinates?
|
||||
bool m_world_coordinates = true;
|
||||
#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
LockButton* m_lock_bnt{ nullptr };
|
||||
choice_ctrl* m_word_local_combo { nullptr };
|
||||
|
||||
@ -191,11 +204,20 @@ public:
|
||||
|
||||
void set_uniform_scaling(const bool uniform_scale);
|
||||
bool get_uniform_scaling() const { return m_uniform_scale; }
|
||||
// Does the object manipulation panel work in World or Local coordinates?
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
void set_coordinates_type(ECoordinatesType type);
|
||||
ECoordinatesType get_coordinates_type() const { return m_coordinates_type; }
|
||||
bool is_world_coordinates() const { return m_coordinates_type == ECoordinatesType::World; }
|
||||
bool is_instance_coordinates() const { return m_coordinates_type == ECoordinatesType::Instance; }
|
||||
bool is_local_coordinates() const { return m_coordinates_type == ECoordinatesType::Local; }
|
||||
#else
|
||||
// Does the object manipulation panel work in World or Local coordinates?
|
||||
void set_world_coordinates(const bool world_coordinates);
|
||||
bool get_world_coordinates() const;
|
||||
#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
#else
|
||||
// Does the object manipulation panel work in World or Local coordinates?
|
||||
void set_world_coordinates(const bool world_coordinates) { m_world_coordinates = world_coordinates; this->UpdateAndShow(true); }
|
||||
bool get_world_coordinates() const { return m_world_coordinates; }
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
@ -227,6 +249,10 @@ public:
|
||||
ManipulationEditor* get_focused_editor() { return m_focused_editor; }
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
|
||||
#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
static wxString coordinate_type_str(ECoordinatesType type);
|
||||
#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
|
||||
private:
|
||||
void reset_settings_value();
|
||||
void update_settings_value(const Selection& selection);
|
||||
@ -242,6 +268,10 @@ private:
|
||||
void change_scale_value(int axis, double value);
|
||||
void change_size_value(int axis, double value);
|
||||
void do_scale(int axis, const Vec3d &scale) const;
|
||||
|
||||
#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
void set_coordinates_type(const wxString& type_string);
|
||||
#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
};
|
||||
|
||||
}}
|
||||
|
@ -93,7 +93,11 @@ void GLGizmoMove3D::on_start_dragging()
|
||||
if (m_hover_id != -1) {
|
||||
m_displacement = Vec3d::Zero();
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
if (wxGetApp().obj_manipul()->is_world_coordinates())
|
||||
#else
|
||||
if (wxGetApp().obj_manipul()->get_world_coordinates())
|
||||
#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
m_starting_drag_position = m_center + m_grabbers[m_hover_id].center;
|
||||
else {
|
||||
const Selection& selection = m_parent.get_selection();
|
||||
@ -455,7 +459,11 @@ void GLGizmoMove3D::transform_to_local(const Selection& selection) const
|
||||
{
|
||||
glsafe(::glTranslated(m_center.x(), m_center.y(), m_center.z()));
|
||||
|
||||
#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
if (!wxGetApp().obj_manipul()->is_world_coordinates()) {
|
||||
#else
|
||||
if (!wxGetApp().obj_manipul()->get_world_coordinates()) {
|
||||
#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
const Transform3d orient_matrix = selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix(true, false, true, true);
|
||||
glsafe(::glMultMatrixd(orient_matrix.data()));
|
||||
}
|
||||
@ -464,7 +472,11 @@ void GLGizmoMove3D::transform_to_local(const Selection& selection) const
|
||||
void GLGizmoMove3D::calc_selection_box_and_center()
|
||||
{
|
||||
const Selection& selection = m_parent.get_selection();
|
||||
#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
if (wxGetApp().obj_manipul()->is_world_coordinates()) {
|
||||
#else
|
||||
if (wxGetApp().obj_manipul()->get_world_coordinates()) {
|
||||
#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
m_bounding_box = selection.get_bounding_box();
|
||||
m_center = m_bounding_box.center();
|
||||
}
|
||||
|
@ -287,7 +287,11 @@ void GLGizmoRotate::on_render_for_picking()
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
void GLGizmoRotate::init_data_from_selection(const Selection& selection)
|
||||
{
|
||||
#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
if (wxGetApp().obj_manipul()->is_world_coordinates()) {
|
||||
#else
|
||||
if (wxGetApp().obj_manipul()->get_world_coordinates()) {
|
||||
#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
m_bounding_box = selection.get_bounding_box();
|
||||
m_center = m_bounding_box.center();
|
||||
}
|
||||
@ -307,7 +311,11 @@ void GLGizmoRotate::init_data_from_selection(const Selection& selection)
|
||||
m_snap_fine_in_radius = m_radius;
|
||||
m_snap_fine_out_radius = m_snap_fine_in_radius + m_radius * ScaleLongTooth;
|
||||
|
||||
#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
if (wxGetApp().obj_manipul()->is_world_coordinates())
|
||||
#else
|
||||
if (wxGetApp().obj_manipul()->get_world_coordinates())
|
||||
#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
m_orient_matrix = Transform3d::Identity();
|
||||
else
|
||||
m_orient_matrix = selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix(true, false, true, true);
|
||||
|
@ -46,7 +46,11 @@ std::string GLGizmoScale3D::get_tooltip() const
|
||||
Vec3d scale = 100.0 * Vec3d::Ones();
|
||||
if (selection.is_single_full_instance())
|
||||
scale = 100.0 * selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_scaling_factor();
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
else if (selection.is_single_volume_or_modifier())
|
||||
#else
|
||||
else if (selection.is_single_modifier() || selection.is_single_volume())
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
scale = 100.0 * selection.get_volume(*selection.get_volume_idxs().begin())->get_volume_scaling_factor();
|
||||
|
||||
if (m_hover_id == 0 || m_hover_id == 1 || m_grabbers[0].dragging || m_grabbers[1].dragging)
|
||||
@ -193,7 +197,11 @@ void GLGizmoScale3D::on_render()
|
||||
m_grabbers_transform = Transform3d::Identity();
|
||||
m_center = Vec3d::Zero();
|
||||
m_instance_center = Vec3d::Zero();
|
||||
#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
bool world_coordinates = wxGetApp().obj_manipul()->is_world_coordinates();
|
||||
#else
|
||||
bool world_coordinates = wxGetApp().obj_manipul()->get_world_coordinates();
|
||||
#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
if (selection.is_single_full_instance() && !world_coordinates) {
|
||||
#else
|
||||
m_transform = Transform3d::Identity();
|
||||
@ -236,7 +244,7 @@ void GLGizmoScale3D::on_render()
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
}
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
else if ((selection.is_single_modifier() || selection.is_single_volume()) && !world_coordinates) {
|
||||
else if (selection.is_single_volume_or_modifier() && !world_coordinates) {
|
||||
#else
|
||||
else if (selection.is_single_modifier() || selection.is_single_volume()) {
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
@ -276,7 +284,7 @@ void GLGizmoScale3D::on_render()
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
// x axis
|
||||
const Vec3d box_half_size = 0.5 * m_bounding_box.size();
|
||||
bool use_constrain = wxGetKeyState(WXK_CONTROL) && (selection.is_single_full_instance() || selection.is_single_volume() || selection.is_single_modifier());
|
||||
bool use_constrain = wxGetKeyState(WXK_CONTROL) && (selection.is_single_full_instance() || selection.is_single_volume_or_modifier());
|
||||
|
||||
m_grabbers[0].center = { -(box_half_size.x() + Offset), 0.0, 0.0 };
|
||||
m_grabbers[0].color = (use_constrain && m_hover_id == 1) ? CONSTRAINED_COLOR : AXES_COLOR[0];
|
||||
@ -617,14 +625,18 @@ void GLGizmoScale3D::do_scale_along_axis(Axis axis, const UpdateData& data)
|
||||
Vec3d curr_scale = m_scale;
|
||||
Vec3d starting_scale = m_starting.scale;
|
||||
const Selection& selection = m_parent.get_selection();
|
||||
#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
const bool world_coordinates = wxGetApp().obj_manipul()->is_world_coordinates();
|
||||
#else
|
||||
const bool world_coordinates = wxGetApp().obj_manipul()->get_world_coordinates();
|
||||
#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
if (world_coordinates) {
|
||||
if (selection.is_single_full_instance()) {
|
||||
const Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_rotation());
|
||||
curr_scale = (m * curr_scale).cwiseAbs();
|
||||
starting_scale = (m * starting_scale).cwiseAbs();
|
||||
}
|
||||
else if (selection.is_single_volume() || selection.is_single_modifier()) {
|
||||
else if (selection.is_single_volume_or_modifier()) {
|
||||
const Transform3d mi = Geometry::assemble_transform(Vec3d::Zero(), selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_rotation());
|
||||
const Transform3d mv = Geometry::assemble_transform(Vec3d::Zero(), selection.get_volume(*selection.get_volume_idxs().begin())->get_volume_rotation());
|
||||
const Transform3d m = mi * mv;
|
||||
@ -638,7 +650,7 @@ void GLGizmoScale3D::do_scale_along_axis(Axis axis, const UpdateData& data)
|
||||
if (world_coordinates) {
|
||||
if (selection.is_single_full_instance())
|
||||
m_scale = (Geometry::assemble_transform(Vec3d::Zero(), selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_rotation()).inverse() * curr_scale).cwiseAbs();
|
||||
else if (selection.is_single_volume() || selection.is_single_modifier()) {
|
||||
else if (selection.is_single_volume_or_modifier()) {
|
||||
const Transform3d mi = Geometry::assemble_transform(Vec3d::Zero(), selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_rotation()).inverse();
|
||||
const Transform3d mv = Geometry::assemble_transform(Vec3d::Zero(), selection.get_volume(*selection.get_volume_idxs().begin())->get_volume_rotation()).inverse();
|
||||
m_scale = (mv * mi * curr_scale).cwiseAbs();
|
||||
@ -680,7 +692,7 @@ void GLGizmoScale3D::do_scale_along_axis(Axis axis, const UpdateData& data)
|
||||
default: { m_offset = Vec3d::Zero(); break; }
|
||||
}
|
||||
|
||||
if ((selection.is_single_volume() || selection.is_single_modifier()) && !world_coordinates) {
|
||||
if (selection.is_single_volume_or_modifier() && !world_coordinates) {
|
||||
const Transform3d mv = Geometry::assemble_transform(Vec3d::Zero(), selection.get_volume(*selection.get_volume_idxs().begin())->get_volume_rotation());
|
||||
const Transform3d mi = Geometry::assemble_transform(Vec3d::Zero(), Vec3d::Zero(), selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_scaling_factor()).inverse();
|
||||
m_offset = mv * mi * m_offset;
|
||||
@ -718,7 +730,11 @@ void GLGizmoScale3D::do_scale_uniform(const UpdateData& data)
|
||||
m_offset.y() *= -1.0;
|
||||
|
||||
const Selection& selection = m_parent.get_selection();
|
||||
#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
const bool world_coordinates = wxGetApp().obj_manipul()->is_world_coordinates();
|
||||
#else
|
||||
const bool world_coordinates = wxGetApp().obj_manipul()->get_world_coordinates();
|
||||
#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
Vec3d center_offset = m_starting.instance_center - m_starting.center;
|
||||
|
||||
if (selection.is_single_full_instance() && !world_coordinates) {
|
||||
@ -728,7 +744,7 @@ void GLGizmoScale3D::do_scale_uniform(const UpdateData& data)
|
||||
|
||||
m_offset += (ratio - 1.0) * center_offset;
|
||||
|
||||
if ((selection.is_single_volume() || selection.is_single_modifier()) && !world_coordinates) {
|
||||
if (selection.is_single_volume_or_modifier() && !world_coordinates) {
|
||||
const Transform3d mv = Geometry::assemble_transform(Vec3d::Zero(), selection.get_volume(*selection.get_volume_idxs().begin())->get_volume_rotation());
|
||||
const Transform3d mi = Geometry::assemble_transform(Vec3d::Zero(), Vec3d::Zero(), selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_scaling_factor()).inverse();
|
||||
m_offset = mv * mi * m_offset;
|
||||
@ -780,9 +796,13 @@ void GLGizmoScale3D::transform_to_local(const Selection& selection) const
|
||||
{
|
||||
glsafe(::glTranslated(m_center.x(), m_center.y(), m_center.z()));
|
||||
|
||||
#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
if (!wxGetApp().obj_manipul()->is_world_coordinates()) {
|
||||
#else
|
||||
if (!wxGetApp().obj_manipul()->get_world_coordinates()) {
|
||||
#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
Transform3d orient_matrix = selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix(true, false, true, true);
|
||||
if (selection.is_single_volume() || selection.is_single_modifier())
|
||||
if (selection.is_single_volume_or_modifier())
|
||||
orient_matrix = orient_matrix * selection.get_volume(*selection.get_volume_idxs().begin())->get_volume_transformation().get_matrix(true, false, true, true);
|
||||
glsafe(::glMultMatrixd(orient_matrix.data()));
|
||||
}
|
||||
|
@ -4448,8 +4448,12 @@ void Plater::priv::on_right_click(RBtnEvent& evt)
|
||||
const bool is_some_full_instances = selection.is_single_full_instance() ||
|
||||
selection.is_single_full_object() ||
|
||||
selection.is_multiple_full_instance();
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
const bool is_part = selection.is_single_volume_or_modifier();
|
||||
#else
|
||||
const bool is_part = selection.is_single_volume() || selection.is_single_modifier();
|
||||
menu = is_some_full_instances ? menus.object_menu() :
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
menu = is_some_full_instances ? menus.object_menu() :
|
||||
is_part ? menus.part_menu() : menus.multi_selection_menu();
|
||||
}
|
||||
}
|
||||
|
@ -594,10 +594,14 @@ bool Selection::matches(const std::vector<unsigned int>& volume_idxs) const
|
||||
bool Selection::requires_uniform_scale() const
|
||||
{
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
if (is_single_modifier() || is_single_volume())
|
||||
if (is_single_volume_or_modifier())
|
||||
return !Geometry::is_rotation_ninety_degrees(Geometry::Transformation(get_volume(*m_list.begin())->world_matrix()).get_rotation());
|
||||
else if (is_single_full_instance())
|
||||
#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
return wxGetApp().obj_manipul()->is_world_coordinates() ?
|
||||
#else
|
||||
return wxGetApp().obj_manipul()->get_world_coordinates() ?
|
||||
#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
!Geometry::is_rotation_ninety_degrees(get_volume(*m_list.begin())->get_instance_rotation()) : false;
|
||||
|
||||
return true;
|
||||
@ -972,7 +976,11 @@ void Selection::scale(const Vec3d& scale, TransformationType transformation_type
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
}
|
||||
}
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
else if (is_single_volume_or_modifier())
|
||||
#else
|
||||
else if (is_single_volume() || is_single_modifier())
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
v.set_volume_scaling_factor(scale);
|
||||
else {
|
||||
const Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), Vec3d::Zero(), scale);
|
||||
@ -1424,7 +1432,11 @@ void Selection::render_sidebar_hints(const std::string& sidebar_field)
|
||||
#else
|
||||
const Vec3d& center = get_bounding_box().center();
|
||||
#endif // ENABLE_GL_SHADERS_ATTRIBUTES
|
||||
#if ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
if (is_single_full_instance() && !wxGetApp().obj_manipul()->is_world_coordinates()) {
|
||||
#else
|
||||
if (is_single_full_instance() && !wxGetApp().obj_manipul()->get_world_coordinates()) {
|
||||
#endif // ENABLE_INSTANCE_COORDINATES_FOR_VOLUMES
|
||||
#if !ENABLE_GL_SHADERS_ATTRIBUTES
|
||||
glsafe(::glTranslated(center.x(), center.y(), center.z()));
|
||||
#endif // !ENABLE_GL_SHADERS_ATTRIBUTES
|
||||
|
@ -290,6 +290,9 @@ public:
|
||||
bool is_from_single_object() const;
|
||||
bool is_sla_compliant() const;
|
||||
bool is_instance_mode() const { return m_mode == Instance; }
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
bool is_single_volume_or_modifier() const { return is_single_volume() || is_single_modifier(); }
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
|
||||
bool contains_volume(unsigned int volume_idx) const { return m_list.find(volume_idx) != m_list.end(); }
|
||||
// returns true if the selection contains all the given indices
|
||||
|
Loading…
x
Reference in New Issue
Block a user