Face the camera allowed for instances

Refresh volume data in manipulation panel during drag over surface
This commit is contained in:
Filip Sykala - NTB T15p 2023-11-02 16:36:13 +01:00
parent bac6bd183c
commit b570944bfc
2 changed files with 65 additions and 46 deletions

View File

@ -377,13 +377,10 @@ bool GLGizmoSVG::on_init()
std::string GLGizmoSVG::on_get_name() const { return _u8L("SVG"); }
void GLGizmoSVG::on_render() {
// no volume selected
const Selection &selection = m_parent.get_selection();
if (m_volume == nullptr ||
get_model_volume(m_volume_id, selection.get_model()->objects) == nullptr)
return;
if (selection.volumes_count() != 1)
if (const Selection &selection = m_parent.get_selection();
selection.volumes_count() != 1 || // only one selected volume
m_volume == nullptr || // already selected volume in gizmo
get_model_volume(m_volume_id, selection.get_model()->objects) == nullptr) // still exist model
return;
bool is_surface_dragging = m_surface_drag.has_value();
@ -1380,17 +1377,12 @@ void GLGizmoSVG::draw_window()
}
void GLGizmoSVG::draw_face_the_camera(){
// multi instance has to have same rotation only world z rotation is allowed
bool disabled = m_parent.get_selection().is_single_full_instance();
m_imgui->disabled_begin(disabled);
if (ImGui::Button(_u8L("Face the camera").c_str())) {
const Camera &cam = wxGetApp().plater()->get_camera();
auto wanted_up_limit = (m_keep_up) ? std::optional<double>(UP_LIMIT) : std::optional<double>{};
if (face_selected_volume_to_camera(cam, m_parent, wanted_up_limit))
volume_transformation_changed();
}
m_imgui->disabled_end();
}
void GLGizmoSVG::draw_preview(){

View File

@ -4,13 +4,18 @@
///|/
#include "SurfaceDrag.hpp"
#include "libslic3r/Model.hpp" // ModelVolume
#include "GLCanvas3D.hpp"
#include <libslic3r/Model.hpp> // ModelVolume
#include <libslic3r/Emboss.hpp>
#include "slic3r/Utils/RaycastManager.hpp"
#include "slic3r/GUI/Camera.hpp"
#include "slic3r/GUI/CameraUtils.hpp"
#include "slic3r/GUI/I18N.hpp"
#include "libslic3r/Emboss.hpp"
#include "GLCanvas3D.hpp"
#include "Camera.hpp"
#include "CameraUtils.hpp"
#include "I18N.hpp"
#include "GUI_App.hpp"
#include "GUI_ObjectManipulation.hpp"
using namespace Slic3r;
using namespace Slic3r::GUI;
@ -83,6 +88,7 @@ bool on_mouse_surface_drag(const wxMouseEvent &mouse_event,
if (surface_drag.has_value() && !mouse_event.Dragging()) {
// write transformation from UI into model
canvas.do_move(L("Move over surface"));
wxGetApp().obj_manipul()->set_dirty();
// allow moving with object again
canvas.enable_moving(true);
@ -275,31 +281,39 @@ Transform3d world_matrix_fixed(const Selection &selection)
void selection_transform(Selection &selection, const std::function<void()> &selection_transformation_fnc, const ModelVolume *volume)
{
GLVolume *gl_volume = selection.get_volume(*selection.get_volume_idxs().begin());
auto get_fix = [&selection, &volume, &gl_volume]() -> const Transform3d * {
if (gl_volume == nullptr)
return selection_transformation_fnc();
return nullptr;
if (volume == nullptr) {
volume = get_model_volume(*gl_volume, selection.get_model()->objects);
if (volume == nullptr)
return selection_transformation_fnc();
return nullptr;
}
const std::optional<EmbossShape> &es = volume->emboss_shape;
if (!volume->emboss_shape.has_value())
return selection_transformation_fnc();
const std::optional<Transform3d> &fix_tr = volume->emboss_shape->fix_3mf_tr;
if (!fix_tr.has_value())
return selection_transformation_fnc();
return nullptr;
if (!es->fix_3mf_tr.has_value())
return nullptr;
return &(*es->fix_3mf_tr);
};
if (const Transform3d *fix = get_fix(); fix != nullptr) {
Transform3d volume_tr = gl_volume->get_volume_transformation().get_matrix();
gl_volume->set_volume_transformation(volume_tr * fix_tr->inverse());
gl_volume->set_volume_transformation(volume_tr * fix->inverse());
selection.setup_cache();
selection_transformation_fnc();
volume_tr = gl_volume->get_volume_transformation().get_matrix();
gl_volume->set_volume_transformation(volume_tr * (*fix_tr));
gl_volume->set_volume_transformation(volume_tr * (*fix));
selection.setup_cache();
} else {
selection_transformation_fnc();
}
if (selection.is_single_full_instance())
selection.synchronize_unselected_instances(Selection::SyncRotationType::GENERAL);
}
bool face_selected_volume_to_camera(const Camera &camera, GLCanvas3D &canvas, const std::optional<double> &wanted_up_limit)
@ -345,26 +359,37 @@ bool face_selected_volume_to_camera(const Camera &camera, GLCanvas3D &canvas, co
current_angle = Emboss::calc_up(world_tr, *wanted_up_limit);
Vec3d world_position = gl_volume.world_matrix()*Vec3d::Zero();
Vec3d wanted_direction = -camera.get_dir_forward();
assert(camera.get_type() == Camera::EType::Perspective ||
camera.get_type() == Camera::EType::Ortho);
Vec3d wanted_direction = (camera.get_type() == Camera::EType::Perspective) ?
Vec3d(camera.get_position() - world_position) :
(-camera.get_dir_forward());
Transform3d new_volume_tr = get_volume_transformation(world_tr, wanted_direction, world_position,
fix, instance_tr_inv, current_angle, wanted_up_limit);
if (is_embossed_object(canvas.get_selection())) {
Selection &selection = canvas.get_selection();
if (is_embossed_object(selection)) {
// transform instance instead of volume
Transform3d new_instance_tr = instance_tr * new_volume_tr * volume.get_matrix().inverse();
instance.set_transformation(Geometry::Transformation(new_instance_tr));
gl_volume.set_instance_transformation(new_instance_tr);
// set same transformation to other instances when instance is embossed object
if (selection.is_single_full_instance())
selection.synchronize_unselected_instances(Selection::SyncRotationType::GENERAL);
} else {
// write result transformation
gl_volume.set_volume_transformation(new_volume_tr);
volume.set_transformation(new_volume_tr);
}
if (volume.type() == ModelVolumeType::MODEL_PART) {
object.invalidate_bounding_box();
object.ensure_on_bed();
}
canvas.do_rotate(L("Face the camera"));
wxGetApp().obj_manipul()->set_dirty();
return true;
}
@ -638,6 +663,8 @@ bool dragging(const Vec2d &mouse_pos,
}
canvas.set_as_dirty();
// Show current position in manipulation panel
wxGetApp().obj_manipul()->set_dirty();
return true;
}