update slic3r

This commit is contained in:
QIDI TECH
2024-11-28 15:19:12 +08:00
parent a26696f35e
commit 7eb6543991
196 changed files with 18701 additions and 3803 deletions

View File

@@ -149,6 +149,10 @@ void Selection::set_model(Model* model)
update_valid();
}
void Selection::set_mode(EMode mode) {
m_mode = mode;
}
int Selection::query_real_volume_idx_from_other_view(unsigned int object_idx, unsigned int instance_idx, unsigned int model_volume_idx)
{
for (int i = 0; i < m_volumes->size(); i++) {
@@ -407,6 +411,55 @@ void Selection::remove_volumes(EMode mode, const std::vector<unsigned int>& volu
this->set_bounding_boxes_dirty();
}
ModelVolume *Selection::get_selected_single_volume(int &out_object_idx, int &out_volume_idx)
{
if (is_single_volume() || is_single_modifier()) {
const GLVolume *gl_volume = get_volume(*get_volume_idxs().begin());
out_object_idx = gl_volume->object_idx();
ModelObject *model_object = get_model()->objects[out_object_idx];
out_volume_idx = gl_volume->volume_idx();
if (out_volume_idx < model_object->volumes.size())
return model_object->volumes[out_volume_idx];
}
return nullptr;
}
ModelObject *Selection::get_selected_single_object(int &out_object_idx)
{
if (is_single_volume() || is_single_modifier() || is_single_full_object()) {
const GLVolume *gl_volume = get_volume(*get_volume_idxs().begin());
out_object_idx = gl_volume->object_idx();
return get_model()->objects[out_object_idx];
}
return nullptr;
}
const std::vector<Transform3d> &Selection::get_all_tran_of_selected_volumes()
{
m_trafo_matrices.clear();
int object_idx;
auto mo = get_selected_single_object(object_idx);
if (mo) {
const ModelInstance *mi = mo->instances[get_instance_idx()];
for (const ModelVolume *mv : mo->volumes) {
if (mv->is_model_part()) {
m_trafo_matrices.emplace_back(mi->get_transformation().get_matrix() * mv->get_matrix());
}
}
}
return m_trafo_matrices;
}
const ModelInstance *Selection::get_selected_single_intance()
{
int object_idx;
auto mo = get_selected_single_object(object_idx);
if (mo) {
return mo->instances[get_instance_idx()];
}
return nullptr;
}
void Selection::add_curr_plate()
{
if (!m_valid)
@@ -827,6 +880,10 @@ const GLVolume* Selection::get_volume(unsigned int volume_idx) const
return (m_valid && (volume_idx < (unsigned int)m_volumes->size())) ? (*m_volumes)[volume_idx] : nullptr;
}
GLVolume *Selection::get_volume(unsigned int volume_idx) {
return (m_valid && (volume_idx < (unsigned int) m_volumes->size())) ? (*m_volumes)[volume_idx] : nullptr;
}
const BoundingBoxf3& Selection::get_bounding_box() const
{
if (!m_bounding_box.has_value()) {
@@ -879,6 +936,63 @@ const BoundingBoxf3& Selection::get_scaled_instance_bounding_box() const
return *m_scaled_instance_bounding_box;
}
const BoundingBoxf3 &Selection::get_full_unscaled_instance_bounding_box() const
{
assert(is_single_full_instance());
if (!m_full_unscaled_instance_bounding_box.has_value()) {
std::optional<BoundingBoxf3> *bbox = const_cast<std::optional<BoundingBoxf3> *>(&m_full_unscaled_instance_bounding_box);
*bbox = BoundingBoxf3();
if (m_valid) {
for (unsigned int i : m_list) {
const GLVolume &volume = *(*m_volumes)[i];
Transform3d trafo = volume.get_instance_transformation().get_matrix_no_scaling_factor() * volume.get_volume_transformation().get_matrix();
trafo.translation().z() += volume.get_sla_shift_z();
(*bbox)->merge(volume.transformed_convex_hull_bounding_box(trafo));
}
}
}
return *m_full_unscaled_instance_bounding_box;
}
const BoundingBoxf3 &Selection::get_full_scaled_instance_bounding_box() const
{
assert(is_single_full_instance());
if (!m_full_scaled_instance_bounding_box.has_value()) {
std::optional<BoundingBoxf3> *bbox = const_cast<std::optional<BoundingBoxf3> *>(&m_full_scaled_instance_bounding_box);
*bbox = BoundingBoxf3();
if (m_valid) {
for (unsigned int i : m_list) {
const GLVolume &volume = *(*m_volumes)[i];
Transform3d trafo = volume.get_instance_transformation().get_matrix() * volume.get_volume_transformation().get_matrix();
trafo.translation().z() += volume.get_sla_shift_z();
(*bbox)->merge(volume.transformed_convex_hull_bounding_box(trafo));
}
}
}
return *m_full_scaled_instance_bounding_box;
}
const BoundingBoxf3 &Selection::get_full_unscaled_instance_local_bounding_box() const
{
assert(is_single_full_instance());
if (!m_full_unscaled_instance_local_bounding_box.has_value()) {
std::optional<BoundingBoxf3> *bbox = const_cast<std::optional<BoundingBoxf3> *>(&m_full_unscaled_instance_local_bounding_box);
*bbox = BoundingBoxf3();
if (m_valid) {
for (unsigned int i : m_list) {
const GLVolume &volume = *(*m_volumes)[i];
Transform3d trafo = volume.get_volume_transformation().get_matrix();
trafo.translation().z() += volume.get_sla_shift_z();
(*bbox)->merge(volume.transformed_convex_hull_bounding_box(trafo));
}
}
}
return *m_full_unscaled_instance_local_bounding_box;
}
const std::pair<BoundingBoxf3, Transform3d> &Selection::get_bounding_box_in_current_reference_system() const
{
static int last_coordinates_type = -1;
@@ -937,7 +1051,8 @@ std::pair<BoundingBoxf3, Transform3d> Selection::get_bounding_box_in_reference_s
const GLVolume & vol = *get_volume(id);
const Transform3d vol_world_rafo = vol.world_matrix();
const TriangleMesh *mesh = vol.convex_hull();
if (mesh == nullptr) mesh = &m_model->objects[vol.object_idx()]->volumes[vol.volume_idx()]->mesh();
if (mesh == nullptr)
mesh = &m_model->objects[vol.object_idx()]->volumes[vol.volume_idx()]->mesh();
assert(mesh != nullptr);
for (const stl_vertex &v : mesh->its.vertices) {
const Vec3d world_v = vol_world_rafo * v.cast<double>();
@@ -1057,66 +1172,65 @@ void Selection::setup_cache()
set_caches();
}
void Selection::translate(const Vec3d &displacement, bool local)
void Selection::translate(const Vec3d &displacement, TransformationType transformation_type)
{
if (!m_valid)
return;
EMode translation_type = m_mode;
//BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(": %1%, displacement {%2%, %3%, %4%}") % __LINE__ % displacement(X) % displacement(Y) % displacement(Z);
if (!m_valid) return;
for (unsigned int i : m_list) {
GLVolume& v = *(*m_volumes)[i];
if (v.is_wipe_tower) {
int plate_idx = v.object_idx() - 1000;
BoundingBoxf3 plate_bbox = wxGetApp().plater()->get_partplate_list().get_plate(plate_idx)->get_bounding_box();
Vec3d tower_size = v.bounding_box().size();
Vec3d tower_origin = m_cache.volumes_data[i].get_volume_position();
Vec3d actual_displacement = displacement;
const double margin = WIPE_TOWER_MARGIN;
GLVolume & v = *(*m_volumes)[i];
const VolumeCache &volume_data = m_cache.volumes_data[i];
if (m_mode == Instance && !is_wipe_tower()) {
assert(is_from_fully_selected_instance(i));
if (transformation_type.instance()) {
const Geometry::Transformation &inst_trafo = volume_data.get_instance_transform();
v.set_instance_offset(inst_trafo.get_offset() + inst_trafo.get_rotation_matrix() * displacement);
} else
transform_instance_relative(v, volume_data, transformation_type, Geometry::translation_transform(displacement), m_cache.dragging_center);
} else {
if (v.is_wipe_tower) {//in world cs
int plate_idx = v.object_idx() - 1000;
BoundingBoxf3 plate_bbox = wxGetApp().plater()->get_partplate_list().get_plate(plate_idx)->get_bounding_box();
Vec3d tower_size = v.bounding_box().size();
Vec3d tower_origin = m_cache.volumes_data[i].get_volume_position();
Vec3d actual_displacement = displacement;
const double margin = WIPE_TOWER_MARGIN;
if (!local)
actual_displacement = (m_cache.volumes_data[i].get_instance_rotation_matrix() * m_cache.volumes_data[i].get_instance_scale_matrix() * m_cache.volumes_data[i].get_instance_mirror_matrix()).inverse() * displacement;
actual_displacement = (m_cache.volumes_data[i].get_instance_rotation_matrix() * m_cache.volumes_data[i].get_instance_scale_matrix() *
m_cache.volumes_data[i].get_instance_mirror_matrix())
.inverse() *
displacement;
if (tower_origin(0) + actual_displacement(0) - margin < plate_bbox.min(0)) {
actual_displacement(0) = plate_bbox.min(0) - tower_origin(0) + margin;
} else if (tower_origin(0) + actual_displacement(0) + tower_size(0) + margin > plate_bbox.max(0)) {
actual_displacement(0) = plate_bbox.max(0) - tower_origin(0) - tower_size(0) - margin;
}
if (tower_origin(0) + actual_displacement(0) - margin < plate_bbox.min(0)) {
actual_displacement(0) = plate_bbox.min(0) - tower_origin(0) + margin;
}
else if (tower_origin(0) + actual_displacement(0) + tower_size(0) + margin > plate_bbox.max(0)) {
actual_displacement(0) = plate_bbox.max(0) - tower_origin(0) - tower_size(0) - margin;
}
if (tower_origin(1) + actual_displacement(1) - margin < plate_bbox.min(1)) {
actual_displacement(1) = plate_bbox.min(1) - tower_origin(1) + margin;
} else if (tower_origin(1) + actual_displacement(1) + tower_size(1) + margin > plate_bbox.max(1)) {
actual_displacement(1) = plate_bbox.max(1) - tower_origin(1) - tower_size(1) - margin;
}
if (tower_origin(1) + actual_displacement(1) - margin < plate_bbox.min(1)) {
actual_displacement(1) = plate_bbox.min(1) - tower_origin(1) + margin;
}
else if (tower_origin(1) + actual_displacement(1) + tower_size(1) + margin > plate_bbox.max(1)) {
actual_displacement(1) = plate_bbox.max(1) - tower_origin(1) - tower_size(1) - margin;
v.set_volume_offset(m_cache.volumes_data[i].get_volume_position() + actual_displacement);
}
else if (transformation_type.local() && transformation_type.absolute()) {
const Geometry::Transformation &vol_trafo = volume_data.get_volume_transform();
const Geometry::Transformation &inst_trafo = volume_data.get_instance_transform();
v.set_volume_offset(vol_trafo.get_offset() + inst_trafo.get_scaling_factor_matrix().inverse() * vol_trafo.get_rotation_matrix() * displacement);
} else {
Vec3d relative_disp = displacement;
if (transformation_type.world() && transformation_type.instance())
relative_disp = volume_data.get_instance_transform().get_scaling_factor_matrix().inverse() * relative_disp;
v.set_volume_offset(m_cache.volumes_data[i].get_volume_position() + actual_displacement);
}
else if (m_mode == Volume || v.is_wipe_tower) {
if (local)
v.set_volume_offset(m_cache.volumes_data[i].get_volume_position() + displacement);
else {
const Vec3d local_displacement = (m_cache.volumes_data[i].get_instance_rotation_matrix() * m_cache.volumes_data[i].get_instance_scale_matrix() * m_cache.volumes_data[i].get_instance_mirror_matrix()).inverse() * displacement;
v.set_volume_offset(m_cache.volumes_data[i].get_volume_position() + local_displacement);
}
}
else if (m_mode == Instance) {
if (is_from_fully_selected_instance(i))
v.set_instance_offset(m_cache.volumes_data[i].get_instance_position() + displacement);
else {
const Vec3d local_displacement = (m_cache.volumes_data[i].get_instance_rotation_matrix() * m_cache.volumes_data[i].get_instance_scale_matrix() * m_cache.volumes_data[i].get_instance_mirror_matrix()).inverse() * displacement;
v.set_volume_offset(m_cache.volumes_data[i].get_volume_position() + local_displacement);
translation_type = Volume;
transform_volume_relative(v, volume_data, transformation_type, Geometry::translation_transform(relative_disp), m_cache.dragging_center);
}
}
}
#if !DISABLE_INSTANCES_SYNCH
if (translation_type == Instance)
synchronize_unselected_instances(SYNC_ROTATION_NONE);
else if (translation_type == Volume)
if (m_mode == Instance)
synchronize_unselected_instances(SyncRotationType::NONE);
else if (m_mode == Volume)
synchronize_unselected_volumes();
#endif // !DISABLE_INSTANCES_SYNCH
if (wxGetApp().plater()->canvas3D()->get_canvas_type() != GLCanvas3D::ECanvasType::CanvasAssembleView) {
@@ -1127,7 +1241,6 @@ void Selection::translate(const Vec3d &displacement, bool local)
wxGetApp().plater()->canvas3D()->requires_check_outside_state();
}
}
// Rotate an object around one of the axes. Only one rotation component is expected to be changing.
void Selection::rotate(const Vec3d& rotation, TransformationType transformation_type)
{
@@ -1221,7 +1334,7 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_
else
{
if (transformation_type.instance()) {//in object Coordinate System
if (transformation_type.instance()) {//in object Coordinate System
// ensure that the volume rotates as a rigid body
const Transform3d inst_scale_matrix = inst_trafo.get_scaling_factor_matrix();
rotation_matrix = inst_scale_matrix.inverse() * rotation_matrix * inst_scale_matrix;
@@ -1249,7 +1362,7 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_
#if !DISABLE_INSTANCES_SYNCH
if (m_mode == Instance)
synchronize_unselected_instances((rot_axis_max == 2) ? SYNC_ROTATION_NONE : SYNC_ROTATION_GENERAL);
synchronize_unselected_instances((rot_axis_max == 2) ? SyncRotationType::NONE : SyncRotationType::GENERAL);
else if (m_mode == Volume)
synchronize_unselected_volumes();
#endif // !DISABLE_INSTANCES_SYNCH
@@ -1307,7 +1420,7 @@ void Selection::flattening_rotate(const Vec3d& normal)
// Apply the same transformation also to other instances,
// but respect their possibly diffrent z-rotation.
if (m_mode == Instance)
synchronize_unselected_instances(SYNC_ROTATION_GENERAL);
synchronize_unselected_instances(SyncRotationType::GENERAL);
#endif // !DISABLE_INSTANCES_SYNCH
this->set_bounding_boxes_dirty();
@@ -1315,77 +1428,7 @@ void Selection::flattening_rotate(const Vec3d& normal)
void Selection::scale(const Vec3d& scale, TransformationType transformation_type)
{
if (!m_valid)
return;
for (unsigned int i : m_list) {
GLVolume &v = *(*m_volumes)[i];
if (is_single_full_instance()) {
if (transformation_type.relative()) {
Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), Vec3d::Zero(), scale);
Eigen::Matrix<double, 3, 3, Eigen::DontAlign> new_matrix = (m * m_cache.volumes_data[i].get_instance_scale_matrix()).matrix().block(0, 0, 3, 3);
// extracts scaling factors from the composed transformation
Vec3d new_scale(new_matrix.col(0).norm(), new_matrix.col(1).norm(), new_matrix.col(2).norm());
if (transformation_type.joint())
v.set_instance_offset(m_cache.dragging_center + m * (m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center));
v.set_instance_scaling_factor(new_scale);
}
else {
if (transformation_type.world() && (std::abs(scale.x() - scale.y()) > EPSILON || std::abs(scale.x() - scale.z()) > EPSILON)) {
// Non-uniform scaling. Transform the scaling factors into the local coordinate system.
// This is only possible, if the instance rotation is mulitples of ninety degrees.
assert(Geometry::is_rotation_ninety_degrees(v.get_instance_rotation()));
v.set_instance_scaling_factor((v.get_instance_transformation().get_matrix(true, false, true, true).matrix().block<3, 3>(0, 0).transpose() * scale).cwiseAbs());
}
else
v.set_instance_scaling_factor(scale);
}
// update the instance assemble transform
ModelObject* object = m_model->objects[v.object_idx()];
Geometry::Transformation assemble_transform = object->instances[v.instance_idx()]->get_assemble_transformation();
assemble_transform.set_scaling_factor(v.get_instance_scaling_factor());
object->instances[v.instance_idx()]->set_assemble_transformation(assemble_transform);
}
else if (is_single_volume() || is_single_modifier())
v.set_volume_scaling_factor(scale);
else {
Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), Vec3d::Zero(), scale);
if (m_mode == Instance) {
Eigen::Matrix<double, 3, 3, Eigen::DontAlign> new_matrix = (m * m_cache.volumes_data[i].get_instance_scale_matrix()).matrix().block(0, 0, 3, 3);
// extracts scaling factors from the composed transformation
Vec3d new_scale(new_matrix.col(0).norm(), new_matrix.col(1).norm(), new_matrix.col(2).norm());
if (transformation_type.joint())
v.set_instance_offset(m_cache.dragging_center + m * (m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center));
v.set_instance_scaling_factor(new_scale);
}
else if (m_mode == Volume) {
Eigen::Matrix<double, 3, 3, Eigen::DontAlign> new_matrix = (m * m_cache.volumes_data[i].get_volume_scale_matrix()).matrix().block(0, 0, 3, 3);
// extracts scaling factors from the composed transformation
Vec3d new_scale(new_matrix.col(0).norm(), new_matrix.col(1).norm(), new_matrix.col(2).norm());
if (transformation_type.joint()) {
Vec3d offset = m * (m_cache.volumes_data[i].get_volume_position() + m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center);
v.set_volume_offset(m_cache.dragging_center - m_cache.volumes_data[i].get_instance_position() + offset);
}
v.set_volume_scaling_factor(new_scale);
}
}
}
#if !DISABLE_INSTANCES_SYNCH
if (m_mode == Instance)
synchronize_unselected_instances(SYNC_ROTATION_NONE);
else if (m_mode == Volume)
synchronize_unselected_volumes();
#endif // !DISABLE_INSTANCES_SYNCH
ensure_on_bed();
set_bounding_boxes_dirty();
if (wxGetApp().plater()->canvas3D()->get_canvas_type() != GLCanvas3D::ECanvasType::CanvasAssembleView) {
wxGetApp().plater()->canvas3D()->requires_check_outside_state();
}
scale_and_translate(scale, Vec3d::Zero(), transformation_type);
}
#if ENABLE_ENHANCED_PRINT_VOLUME_FIT
@@ -1410,7 +1453,9 @@ void Selection::scale_to_fit_print_volume(const BuildVolume& volume)
// center selection on print bed
start_dragging();
offset.z() = -get_bounding_box().min.z();
translate(offset);
TransformationType trafo_type;
trafo_type.set_relative();
translate(offset, trafo_type);
wxGetApp().plater()->canvas3D()->do_move(""); // avoid storing another snapshot
// QDS
@@ -1523,27 +1568,93 @@ void Selection::scale_to_fit_print_volume(const DynamicPrintConfig& config)
}
#endif // ENABLE_ENHANCED_PRINT_VOLUME_FIT
void Selection::mirror(Axis axis)
void Selection::scale_and_translate(const Vec3d &scale, const Vec3d &world_translation, TransformationType transformation_type)
{
if (!m_valid)
return;
if (!m_valid) return;
Vec3d relative_scale = scale;
if (transformation_type.absolute()) {
// converts to relative scale
if (m_mode == Instance) {
if (is_single_full_instance()) {
BoundingBoxf3 current_box = get_bounding_box_in_current_reference_system().first;
BoundingBoxf3 original_box;
if (transformation_type.world())
original_box = get_full_unscaled_instance_bounding_box();
else
original_box = get_full_unscaled_instance_local_bounding_box();
relative_scale = original_box.size().cwiseProduct(scale).cwiseQuotient(current_box.size());
}
}
transformation_type.set_relative();
}
for (unsigned int i : m_list) {
GLVolume& v = *(*m_volumes)[i];
if (is_single_full_instance())
v.set_instance_mirror(axis, -v.get_instance_mirror(axis));
else if (m_mode == Volume)
v.set_volume_mirror(axis, -v.get_volume_mirror(axis));
GLVolume & v = *(*m_volumes)[i];
const VolumeCache & volume_data = m_cache.volumes_data[i];
const Geometry::Transformation &inst_trafo = volume_data.get_instance_transform();
auto old_rotate = inst_trafo.get_rotation();
if (m_mode == Instance) {
if (transformation_type.instance()) {
const Vec3d world_inst_pivot = m_cache.dragging_center - inst_trafo.get_offset();
const Vec3d local_inst_pivot = inst_trafo.get_matrix_no_offset().inverse() * world_inst_pivot;
Matrix3d inst_rotation, inst_scale;
inst_trafo.get_matrix().computeRotationScaling(&inst_rotation, &inst_scale);
const Transform3d offset_trafo = Geometry::translation_transform(inst_trafo.get_offset() + world_translation);
const Transform3d scale_trafo = Transform3d(inst_scale) * Geometry::scale_transform(relative_scale);
v.set_instance_transformation(Geometry::translation_transform(world_inst_pivot) * offset_trafo * Transform3d(inst_rotation) * scale_trafo *
Geometry::translation_transform(-local_inst_pivot));
} else
transform_instance_relative(v, volume_data, transformation_type, Geometry::translation_transform(world_translation) * Geometry::scale_transform(relative_scale),
m_cache.dragging_center);
// update the instance assemble transform
ModelObject * object = m_model->objects[v.object_idx()];
Geometry::Transformation assemble_transform = object->instances[v.instance_idx()]->get_assemble_transformation();
assemble_transform.set_scaling_factor(v.get_instance_scaling_factor());
object->instances[v.instance_idx()]->set_assemble_transformation(assemble_transform);
} else {
if (!is_single_volume_or_modifier()) {
assert(transformation_type.world());
transform_volume_relative(v, volume_data, transformation_type, Geometry::translation_transform(world_translation) * Geometry::scale_transform(scale),
m_cache.dragging_center);
} else {
transformation_type.set_independent();
Vec3d translation;
if (transformation_type.local()) {
translation = volume_data.get_volume_transform().get_matrix_no_offset().inverse() * inst_trafo.get_matrix_no_offset().inverse() * world_translation;
}
else if (transformation_type.instance())
translation = inst_trafo.get_matrix_no_offset().inverse() * world_translation;
else
translation = world_translation;
transform_volume_relative(v, volume_data, transformation_type, Geometry::translation_transform(translation) * Geometry::scale_transform(scale),
m_cache.dragging_center);
}
}
}
#if !DISABLE_INSTANCES_SYNCH
if (m_mode == Instance)
synchronize_unselected_instances(SYNC_ROTATION_NONE);
// even if there is no rotation, we pass SyncRotationType::GENERAL to force
// synchronize_unselected_instances() to apply the scale to the other instances
synchronize_unselected_instances(SyncRotationType::GENERAL);
else if (m_mode == Volume)
synchronize_unselected_volumes();
#endif // !DISABLE_INSTANCES_SYNCH
ensure_on_bed();
set_bounding_boxes_dirty();
if (wxGetApp().plater()->canvas3D()->get_canvas_type() != GLCanvas3D::ECanvasType::CanvasAssembleView) {
wxGetApp().plater()->canvas3D()->requires_check_outside_state();
}
}
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);
}
void Selection::translate(unsigned int object_idx, const Vec3d& displacement)
@@ -1703,7 +1814,8 @@ void Selection::notify_instance_update(int object_idx, int instance_idx)
if (object_idx == -1)
{
std::set<std::pair<int, int>> notify_set;
for (unsigned int i : m_list)
auto list = m_list;
for (unsigned int i : list)
{
int obj_index = (*m_volumes)[i]->object_idx();
//-1 means all the instance in this object
@@ -1901,42 +2013,33 @@ void Selection::render_sidebar_hints(const std::string& sidebar_field, bool unif
glsafe(::glEnable(GL_DEPTH_TEST));
glsafe(::glPushMatrix());
Transform3d orient_matrix = Transform3d::Identity();
if (!boost::starts_with(sidebar_field, "layer")) {
const Vec3d& center = get_bounding_box().center();
Vec3d center = get_bounding_box().center();
const auto &[box, box_trafo] = get_bounding_box_in_current_reference_system();
// QDS
if (is_single_full_instance()/* && !wxGetApp().obj_manipul()->get_world_coordinates()*/) {
if (is_single_full_instance() && !wxGetApp().obj_manipul()->is_world_coordinates()) {
center = box_trafo.translation();
glsafe(::glTranslated(center(0), center(1), center(2)));
if (!boost::starts_with(sidebar_field, "position")) {
Transform3d orient_matrix = Transform3d::Identity();
if (boost::starts_with(sidebar_field, "scale") || boost::starts_with(sidebar_field, "size"))
orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true);
else if (boost::starts_with(sidebar_field, "rotation")) {
if (boost::ends_with(sidebar_field, "x"))
orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true);
else if (boost::ends_with(sidebar_field, "y")) {
const Vec3d& rotation = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_rotation();
if (rotation(0) == 0.0)
orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true);
else
orient_matrix.rotate(Eigen::AngleAxisd(rotation(2), Vec3d::UnitZ()));
}
orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_rotation_matrix();
glsafe(::glMultMatrixd(orient_matrix.data()));
} else if (is_single_volume_or_modifier()) {
if (!wxGetApp().obj_manipul()->is_world_coordinates()) {
if (wxGetApp().obj_manipul()->is_local_coordinates()) {
orient_matrix = get_bounding_box_in_current_reference_system().second;
orient_matrix.translation() = Vec3d::Zero();
} else {
orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_rotation_matrix();
center = box_trafo.translation();
}
glsafe(::glMultMatrixd(orient_matrix.data()));
}
} else if (is_single_volume() || is_single_modifier()) {
glsafe(::glTranslated(center(0), center(1), center(2)));
Transform3d orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true);
if (!boost::starts_with(sidebar_field, "position"))
orient_matrix = orient_matrix * (*m_volumes)[*m_list.begin()]->get_volume_transformation().get_matrix(true, false, true, true);
glsafe(::glMultMatrixd(orient_matrix.data()));
} else {
glsafe(::glTranslated(center(0), center(1), center(2)));
if (requires_local_axes()) {
const Transform3d orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true);
orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_rotation_matrix();
glsafe(::glMultMatrixd(orient_matrix.data()));
}
}
@@ -1993,6 +2096,7 @@ void Selection::copy_to_clipboard()
dst_object->sla_support_points = src_object->sla_support_points;
dst_object->sla_points_status = src_object->sla_points_status;
dst_object->sla_drain_holes = src_object->sla_drain_holes;
dst_object->brim_points = src_object->brim_points;
dst_object->layer_config_ranges = src_object->layer_config_ranges; // #ys_FIXME_experiment
dst_object->layer_height_profile.assign(src_object->layer_height_profile);
dst_object->origin_translation = src_object->origin_translation;
@@ -2613,7 +2717,9 @@ void Selection::render_sidebar_scale_hints(const std::string& sidebar_field, boo
void Selection::render_sidebar_layers_hints(const std::string& sidebar_field) const
{
static const double Margin = 10.0;
if (wxGetApp().plater()->canvas3D()->get_canvas_type() != GLCanvas3D::ECanvasType::CanvasView3D) {
return;
}
std::string field = sidebar_field;
// extract max_z
@@ -2669,6 +2775,7 @@ void Selection::render_sidebar_layers_hints(const std::string& sidebar_field) co
::glBegin(GL_QUADS);
if ((camera_on_top && type == 2) || (!camera_on_top && type == 1))
//y
::glColor4f(68.0f/255.0f , 121.0f / 255.0f, 251.0f / 255.0f, 1.0f);
else
::glColor4f(0.8f, 0.8f, 0.8f, 0.5f);
@@ -2752,7 +2859,7 @@ void Selection::synchronize_unselected_instances(SyncRotationType sync_rotation_
assert(is_rotation_xy_synchronized(m_cache.volumes_data[i].get_instance_rotation(), m_cache.volumes_data[j].get_instance_rotation()));
switch (sync_rotation_type) {
case SYNC_ROTATION_NONE: {
case SyncRotationType::NONE: {
// z only rotation -> synch instance z
// The X,Y rotations should be synchronized from start to end of the rotation.
assert(is_rotation_xy_synchronized(rotation, v->get_instance_rotation()));
@@ -2760,7 +2867,7 @@ void Selection::synchronize_unselected_instances(SyncRotationType sync_rotation_
v->set_instance_offset(Z, volume->get_instance_offset().z());
break;
}
case SYNC_ROTATION_GENERAL:
case SyncRotationType::GENERAL:
// generic rotation -> update instance z with the delta of the rotation.
const double z_diff = Geometry::rotation_diff_z(m_cache.volumes_data[i].get_instance_rotation(), m_cache.volumes_data[j].get_instance_rotation());
v->set_instance_rotation({ rotation.x(), rotation.y(), rotation.z() + z_diff });
@@ -2923,8 +3030,8 @@ void Selection::paste_volumes_from_clipboard()
{
ModelInstance* dst_instance = dst_object->instances[dst_inst_idx];
BoundingBoxf3 dst_instance_bb = dst_object->instance_bounding_box(dst_inst_idx);
Transform3d src_matrix = src_object->instances[0]->get_transformation().get_matrix(true);
Transform3d dst_matrix = dst_instance->get_transformation().get_matrix(true);
Transform3d src_matrix = src_object->instances[0]->get_transformation().get_matrix_no_offset();
Transform3d dst_matrix = dst_instance->get_transformation().get_matrix_no_offset();
bool from_same_object = (src_object->input_file == dst_object->input_file) && src_matrix.isApprox(dst_matrix);
// used to keep relative position of multivolume selections when pasting from another object
@@ -3008,14 +3115,14 @@ void Selection::paste_objects_from_clipboard()
Vec3d displacement;
bool in_current = plate->intersects(bbox);
auto start_point = in_current ? bbox.center() : plate->get_build_volume().center();
auto start_offset = in_current ? src_object->instances.front()->get_offset() : plate->get_build_volume().center();
if (shift_all(0) != 0 || shift_all(1) != 0) {
// QDS: if multiple objects are selected, move them as a whole after copy
if (i == 0) empty_cell_all = wxGetApp().plater()->canvas3D()->get_nearest_empty_cell({start_point(0), start_point(1)}, {bbox.size()(0)+1,bbox.size()(1)+1});
auto instance_shift = src_object->instances.front()->get_offset() - src_objects[0]->instances.front()->get_offset();
displacement = {shift_all.x() + empty_cell_all.x()+instance_shift.x(), shift_all.y() + empty_cell_all.y()+instance_shift.y(), start_point(2)};
displacement = {shift_all.x() + empty_cell_all.x() + instance_shift.x(), shift_all.y() + empty_cell_all.y() + instance_shift.y(), start_offset(2)};
} else {
// QDS: if only one object is copied, find an empty cell to put it
auto start_offset = in_current ? src_object->instances.front()->get_offset() : plate->get_build_volume().center();
auto point_offset = start_offset - start_point;
auto empty_cell = wxGetApp().plater()->canvas3D()->get_nearest_empty_cell({start_point(0), start_point(1)}, {bbox.size()(0)+1, bbox.size()(1)+1});
displacement = {empty_cell.x() + point_offset.x(), empty_cell.y() + point_offset.y(), start_offset(2)};
@@ -3082,5 +3189,52 @@ void Selection::transform_volume_relative(
assert(false);
}
ModelVolume *get_selected_volume(const Selection &selection)
{
const GLVolume *gl_volume = get_selected_gl_volume(selection);
if (gl_volume == nullptr) return nullptr;
const ModelObjectPtrs &objects = selection.get_model()->objects;
return get_model_volume(*gl_volume, objects);
}
const GLVolume *get_selected_gl_volume(const Selection &selection)
{
int object_idx = selection.get_object_idx();
// is more object selected?
if (object_idx == -1) return nullptr;
const auto &list = selection.get_volume_idxs();
// is more volumes selected?
if (list.size() != 1) return nullptr;
unsigned int volume_idx = *list.begin();
return selection.get_volume(volume_idx);
}
ModelVolume *get_selected_volume(const ObjectID &volume_id, const Selection &selection)
{
const Selection::IndicesList &volume_ids = selection.get_volume_idxs();
const ModelObjectPtrs & model_objects = selection.get_model()->objects;
for (auto id : volume_ids) {
const GLVolume * selected_volume = selection.get_volume(id);
const GLVolume::CompositeID &cid = selected_volume->composite_id;
ModelObject * obj = model_objects[cid.object_id];
ModelVolume * volume = obj->volumes[cid.volume_id];
if (volume_id == volume->id()) return volume;
}
return nullptr;
}
ModelVolume *get_volume(const ObjectID &volume_id, const Selection &selection)
{
const ModelObjectPtrs &objects = selection.get_model()->objects;
for (const ModelObject *object : objects) {
for (ModelVolume *volume : object->volumes) {
if (volume->id() == volume_id) return volume;
}
}
return nullptr;
}
} // namespace GUI
} // namespace Slic3r