NEW:add move and rotate gizmo in assemble view

Jira: STUDIO-6545
Change-Id: I30ab8155f5288953b36cd9a301ce3596d6edc0c6
This commit is contained in:
zhou.xu 2024-03-18 11:20:59 +08:00 committed by Lane.Wei
parent 0314576089
commit d9e47bd9a9
11 changed files with 105 additions and 49 deletions

View File

@ -1276,13 +1276,14 @@ public:
m_assemble_transformation.set_from_transform(transform);
}
void set_assemble_offset(const Vec3d& offset) { m_assemble_transformation.set_offset(offset); }
void set_assemble_rotation(const Vec3d &rotation) { m_assemble_transformation.set_rotation(rotation); }
void rotate_assemble(double angle, const Vec3d& axis) {
m_assemble_transformation.set_rotation(m_assemble_transformation.get_rotation() + Geometry::extract_euler_angles(Eigen::Quaterniond(Eigen::AngleAxisd(angle, axis)).toRotationMatrix()));
}
// BBS
void set_offset_to_assembly(const Vec3d& offset) { m_offset_to_assembly = offset; }
Vec3d get_offset_to_assembly() const { return m_offset_to_assembly; }
const Vec3d& get_offset_to_assembly() const { return m_offset_to_assembly; }
const Vec3d& get_offset() const { return m_transformation.get_offset(); }
double get_offset(Axis axis) const { return m_transformation.get_offset(axis); }

View File

@ -678,7 +678,7 @@ void GLVolume::set_range(double min_z, double max_z)
//BBS: add outline related logic
//static unsigned char stencil_data[1284][2944];
void GLVolume::render(bool with_outline) const
void GLVolume::render(bool with_outline, const std::array<float, 4>& body_color) const
{
if (!is_active)
return;
@ -880,7 +880,6 @@ void GLVolume::render(bool with_outline) const
glStencilFunc(GL_NOTEQUAL, 0xff, 0xFF);
glStencilMask(0x00);
float scale = 1.02f;
std::array<float, 4> body_color = { 1.0f, 1.0f, 1.0f, 1.0f }; //red
shader->set_uniform("uniform_color", body_color);
shader->set_uniform("is_outline", true);
@ -1336,8 +1335,13 @@ int GLVolumeCollection::get_selection_support_threshold_angle(bool &enable_suppo
}
//BBS: add outline drawing logic
void GLVolumeCollection::render(
GLVolumeCollection::ERenderType type, bool disable_cullface, const Transform3d &view_matrix, std::function<bool(const GLVolume &)> filter_func, bool with_outline) const
void GLVolumeCollection::render(GLVolumeCollection::ERenderType type,
bool disable_cullface,
const Transform3d & view_matrix,
std::function<bool(const GLVolume &)> filter_func,
bool with_outline,
const std::array<float, 4> & body_color,
bool partly_inside_enable) const
{
GLVolumeWithIdAndZList to_render = volumes_to_render(volumes, type, view_matrix, filter_func);
if (to_render.empty())
@ -1396,7 +1400,7 @@ void GLVolumeCollection::render(
//shader->set_uniform("print_volume.xy_data", m_render_volume.data);
//shader->set_uniform("print_volume.z_data", m_render_volume.zs);
if (volume.first->partly_inside) {
if (volume.first->partly_inside && partly_inside_enable) {
//only partly inside volume need to be painted with boundary check
shader->set_uniform("print_volume.type", static_cast<int>(m_print_volume.type));
shader->set_uniform("print_volume.xy_data", m_print_volume.data);
@ -1427,7 +1431,7 @@ void GLVolumeCollection::render(
glcheck();
//BBS: add outline related logic
volume.first->render(with_outline && volume.first->selected);
volume.first->render(with_outline && volume.first->selected, body_color);
#if ENABLE_ENVIRONMENT_MAP
if (use_environment_texture)

View File

@ -497,7 +497,7 @@ public:
void set_convex_hull(TriangleMesh &&convex_hull) { m_convex_hull = std::make_shared<const TriangleMesh>(std::move(convex_hull)); }
void set_offset_to_assembly(const Vec3d& offset) { m_offset_to_assembly = offset; set_bounding_boxes_as_dirty(); }
Vec3d get_offset_to_assembly() { return m_offset_to_assembly; }
const Vec3d& get_offset_to_assembly() { return m_offset_to_assembly; }
int object_idx() const { return this->composite_id.object_id; }
int volume_idx() const { return this->composite_id.volume_id; }
@ -523,7 +523,8 @@ public:
void set_range(double low, double high);
//BBS: add outline related logic and add virtual specifier
virtual void render(bool with_outline = false) const;
virtual void render(bool with_outline = false,
const std::array<float, 4> &body_color = {1.0f, 1.0f, 1.0f, 1.0f} ) const;
//BBS: add simple render function for thumbnail
void simple_render(GLShaderProgram* shader, ModelObjectPtrs& model_objects, std::vector<std::array<float, 4>>& extruder_colors) const;
@ -667,8 +668,11 @@ public:
void render(ERenderType type,
bool disable_cullface,
const Transform3d & view_matrix,
std::function<bool(const GLVolume &)> filter_func = std::function<bool(const GLVolume &)>(),
bool with_outline = true) const;
std::function<bool(const GLVolume &)> filter_func = std::function<bool(const GLVolume &)>(),
bool with_outline = true,
const std::array<float, 4>& body_color = {1.0f, 1.0f, 1.0f, 1.0f},
bool partly_inside_enable =true
) const;
// Finalize the initialization of the geometry & indices,
// upload the geometry and indices to OpenGL VBO objects

View File

@ -14,7 +14,7 @@
#include "libslic3r/Technologies.hpp"
#include "libslic3r/Tesselate.hpp"
#include "libslic3r/PresetBundle.hpp"
#include "slic3r/GUI/3DBed.hpp"
#include "slic3r/GUI/3DScene.hpp"
#include "slic3r/GUI/BackgroundSlicingProcess.hpp"
#include "slic3r/GUI/GLShader.hpp"
@ -1946,6 +1946,9 @@ void GLCanvas3D::render(bool only_init)
/* assemble render*/
else if (m_canvas_type == ECanvasType::CanvasAssembleView) {
//BBS: add outline logic
if (m_show_world_axes) {
m_axes.render();
}
_render_objects(GLVolumeCollection::ERenderType::Opaque, !m_gizmos.is_running());
//_render_bed(!camera.is_looking_downward(), show_axes);
_render_plane();
@ -4569,8 +4572,13 @@ void GLCanvas3D::do_move(const std::string& snapshot_type)
// Move instances/volumes
ModelObject* model_object = m_model->objects[object_idx];
if (model_object != nullptr) {
if (selection_mode == Selection::Instance)
model_object->instances[instance_idx]->set_offset(v->get_instance_offset());
if (selection_mode == Selection::Instance) {
if (m_canvas_type == GLCanvas3D::ECanvasType::CanvasAssembleView) {
model_object->instances[instance_idx]->set_assemble_offset(v->get_instance_offset());
} else {
model_object->instances[instance_idx]->set_offset(v->get_instance_offset());
}
}
else if (selection_mode == Selection::Volume) {
if (model_object->volumes[volume_idx]->get_offset() != v->get_volume_offset()) {
model_object->volumes[volume_idx]->set_offset(v->get_volume_offset());
@ -4677,8 +4685,13 @@ void GLCanvas3D::do_rotate(const std::string& snapshot_type)
ModelObject* model_object = m_model->objects[object_idx];
if (model_object != nullptr) {
if (selection_mode == Selection::Instance) {
model_object->instances[instance_idx]->set_rotation(v->get_instance_rotation());
model_object->instances[instance_idx]->set_offset(v->get_instance_offset());
if (m_canvas_type == GLCanvas3D::ECanvasType::CanvasAssembleView) {
model_object->instances[instance_idx]->set_assemble_rotation(v->get_instance_rotation());
model_object->instances[instance_idx]->set_assemble_offset(v->get_instance_offset());
} else {
model_object->instances[instance_idx]->set_rotation(v->get_instance_rotation());
model_object->instances[instance_idx]->set_offset(v->get_instance_offset());
}
}
else if (selection_mode == Selection::Volume) {
if (model_object->volumes[volume_idx]->get_rotation() != v->get_volume_rotation()) {
@ -6974,6 +6987,9 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with
GLShaderProgram* shader = wxGetApp().get_shader("gouraud");
ECanvasType canvas_type = this->m_canvas_type;
std::array<float, 4> body_color = canvas_type == ECanvasType::CanvasAssembleView ? std::array<float, 4>({1.0f, 1.0f, 0.0f, 1.0f}) ://yellow
std::array<float, 4>({1.0f, 1.0f, 1.0f, 1.0f});//white
bool partly_inside_enable = canvas_type == ECanvasType::CanvasAssembleView ? false : true;
if (shader != nullptr) {
shader->start_using();
@ -7009,7 +7025,8 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with
else {
return (m_render_sla_auxiliaries || volume.composite_id.volume_id >= 0);
}
}, with_outline);
},
with_outline, body_color, partly_inside_enable);
}
}
else {
@ -7042,7 +7059,8 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with
else {
return true;
}
}, with_outline);
},
with_outline, body_color, partly_inside_enable);
if (m_canvas_type == CanvasAssembleView && m_gizmos.m_assemble_view_data->model_objects_clipper()->get_position() > 0) {
const GLGizmosManager& gm = get_gizmos_manager();
shader->stop_using();
@ -7908,6 +7926,7 @@ void GLCanvas3D::_render_return_toolbar()
wxPostEvent(m_canvas, SimpleEvent(EVT_GLVIEWTOOLBAR_3D));
const_cast<GLGizmosManager *>(&m_gizmos)->reset_all_states();
wxGetApp().plater()->get_view3D_canvas3D()->get_gizmos_manager().reset_all_states();
wxGetApp().plater()->get_view3D_canvas3D()->reload_scene(true);
{
GLCanvas3D * view_3d = wxGetApp().plater()->get_view3D_canvas3D();
GLToolbarItem * assembly_item = view_3d->m_assemble_view_toolbar.get_item("assembly_view");

View File

@ -17,7 +17,7 @@
#include "GCodeViewer.hpp"
#include "Camera.hpp"
#include "IMToolbar.hpp"
#include "slic3r/GUI/3DBed.hpp"
#include "libslic3r/Slicing.hpp"
#include <float.h>
@ -53,7 +53,6 @@ namespace CustomGCode { struct Item; }
namespace GUI {
class Bed3D;
class PartPlateList;
#if ENABLE_RETINA_GL
@ -609,8 +608,8 @@ private:
PrinterTechnology current_printer_technology() const;
bool m_show_world_axes{false};
Bed3D::Axes m_axes;
//BBS:record key botton frequency
int auto_orient_count = 0;
int auto_arrange_count = 0;
@ -773,6 +772,7 @@ public:
void set_color_by(const std::string& value);
void set_show_world_axes(bool flag) { m_show_world_axes = flag; }
void refresh_camera_scene_box();
BoundingBoxf3 volumes_bounding_box() const;

View File

@ -811,10 +811,10 @@ bool AssembleView::init(wxWindow* parent, Bed3D& bed, Model* model, DynamicPrint
m_canvas->enable_assemble_view_toolbar(false);
m_canvas->enable_return_toolbar(true);
m_canvas->enable_separator_toolbar(false);
m_canvas->set_show_world_axes(true);
// BBS: set volume_selection_mode to Volume
m_canvas->get_selection().set_volume_selection_mode(Selection::Volume);
m_canvas->get_selection().lock_volume_selection_mode();
//same to 3d //m_canvas->get_selection().set_volume_selection_mode(Selection::Instance);
//m_canvas->get_selection().lock_volume_selection_mode();
wxBoxSizer* main_sizer = new wxBoxSizer(wxVERTICAL);
main_sizer->Add(m_canvas_widget, 1, wxALL | wxEXPAND, 0);

View File

@ -3,7 +3,7 @@
#include "slic3r/GUI/GUI_App.hpp"
#include "slic3r/GUI/Plater.hpp"
#include "slic3r/GUI/Gizmos/GizmoObjectManipulation.hpp"
#include "slic3r/Utils/UndoRedo.hpp"
#include "libslic3r/PresetBundle.hpp"
#include "libslic3r/MeasureUtils.hpp"
@ -1322,7 +1322,8 @@ void GLGizmoMeasure::render_dimensioning()
m_imgui->text(txt);
if (m_hit_different_volumes.size() < 2) {
ImGui::SameLine();
if (m_imgui->image_button(ImGui::SliderFloatEditBtnIcon, _L("Edit to scale"))) {
if (m_imgui->image_button(ImGui::SliderFloatEditBtnIcon, _L("Edit to scale")) &&
wxGetApp().plater()->canvas3D()->get_canvas_type() == GLCanvas3D::ECanvasType::CanvasView3D) {
m_editing_distance = true;
edit_value = curr_value;
m_imgui->requires_extra_frame();
@ -1345,7 +1346,7 @@ void GLGizmoMeasure::render_dimensioning()
return;
const double ratio = new_value / old_value;
wxGetApp().plater()->take_snapshot(_u8L("Scale"));
wxGetApp().plater()->take_snapshot(_u8L("Scale"), UndoRedo::SnapshotType::GizmoAction);
// apply scale
TransformationType type;
type.set_world();
@ -2024,7 +2025,7 @@ void GLGizmoMeasure::on_render_input_window(float x, float y, float bottom_limit
distance[2] = m_buffered_distance[2];
}
if (displacement.norm() > 0.0f) {
wxGetApp().plater()->take_snapshot(_u8L("MoveInMeasure"));// avoid storing another snapshot
wxGetApp().plater()->take_snapshot(_u8L("MoveInMeasure"), UndoRedo::SnapshotType::GizmoAction); // avoid storing another snapshot
selection->set_mode(same_model_object ? Selection::Volume : Selection::Instance);
auto llo = selection->get_mode();
if (same_model_object == false) {

View File

@ -59,7 +59,9 @@ std::vector<size_t> GLGizmosManager::get_selectable_idxs() const
std::vector<size_t> out;
if (m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView) {
for (size_t i = 0; i < m_gizmos.size(); ++i)
if (m_gizmos[i]->get_sprite_id() == (unsigned int)MmuSegmentation)
if (m_gizmos[i]->get_sprite_id() == (unsigned int) Move ||
m_gizmos[i]->get_sprite_id() == (unsigned int) Rotate ||
m_gizmos[i]->get_sprite_id() == (unsigned int) MmuSegmentation)
out.push_back(i);
}
else {
@ -877,9 +879,21 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt)
}
else if (is_dragging()) {
switch (m_current) {
case Move: { m_parent.do_move(("Tool-Move")); break; }
case Scale: { m_parent.do_scale(("Tool-Scale")); break; }
case Rotate: { m_parent.do_rotate(("Tool-Rotate")); break; }
case Move: {
wxGetApp().plater()->take_snapshot(_u8L("Tool-Move"), UndoRedo::SnapshotType::GizmoAction);
m_parent.do_move("");
break;
}
case Scale: {
wxGetApp().plater()->take_snapshot(_u8L("Tool-Scale"), UndoRedo::SnapshotType::GizmoAction);
m_parent.do_scale("");
break;
}
case Rotate: {
wxGetApp().plater()->take_snapshot(_u8L("Tool-Rotate"), UndoRedo::SnapshotType::GizmoAction);
m_parent.do_rotate("");
break;
}
default: break;
}

View File

@ -6,8 +6,8 @@
//#include "I18N.hpp"
#include "GLGizmosManager.hpp"
#include "slic3r/GUI/GLCanvas3D.hpp"
#include "slic3r/GUI/GUI_App.hpp"
#include "slic3r/Utils/UndoRedo.hpp"
#include "libslic3r/AppConfig.hpp"
#include "libslic3r/Model.hpp"
@ -275,7 +275,8 @@ void GizmoObjectManipulation::change_position_value(int axis, double value)
Selection& selection = m_glcanvas.get_selection();
selection.start_dragging();
selection.translate(position - m_cache.position, selection.requires_local_axes());
m_glcanvas.do_move(L("Set Position"));
wxGetApp().plater()->take_snapshot(_u8L("Set Position"), UndoRedo::SnapshotType::GizmoAction);
m_glcanvas.do_move("");
m_cache.position = position;
m_cache.position_rounded(axis) = DBL_MAX;
@ -303,9 +304,10 @@ void GizmoObjectManipulation::change_rotation_value(int axis, double value)
selection.start_dragging();
selection.rotate(
(M_PI / 180.0) * (transformation_type.absolute() ? rotation : rotation - m_cache.rotation),
(M_PI / 180.0) * (transformation_type.absolute() ? rotation : rotation - m_cache.rotation),
transformation_type);
m_glcanvas.do_rotate(L("Set Orientation"));
wxGetApp().plater()->take_snapshot(_u8L("Set Orientation"), UndoRedo::SnapshotType::GizmoAction);
m_glcanvas.do_rotate("");
m_cache.rotation = rotation;
m_cache.rotation_rounded(axis) = DBL_MAX;
@ -422,7 +424,8 @@ void GizmoObjectManipulation::reset_position_value()
return;
// Copy position values from GLVolumes into Model (ModelInstance / ModelVolume), trigger background processing.
m_glcanvas.do_move(L("Reset Position"));
wxGetApp().plater()->take_snapshot(_u8L("Reset Position"), UndoRedo::SnapshotType::GizmoAction);
m_glcanvas.do_move("");
UpdateAndShow(true);
}
@ -448,7 +451,8 @@ void GizmoObjectManipulation::reset_rotation_value()
selection.synchronize_unselected_instances(Selection::SYNC_ROTATION_GENERAL);
selection.synchronize_unselected_volumes();
// Copy rotation values from GLVolumes into Model (ModelInstance / ModelVolume), trigger background processing.
m_glcanvas.do_rotate(L("Reset Rotation"));
wxGetApp().plater()->take_snapshot(_u8L("Reset Rotation"), UndoRedo::SnapshotType::GizmoAction);
m_glcanvas.do_rotate("");
UpdateAndShow(true);
}

View File

@ -3137,11 +3137,13 @@ void Plater::priv::update(unsigned int flags)
// Update the SLAPrint from the current Model, so that the reload_scene()
// pulls the correct data.
update_status = this->update_background_process(false, flags & (unsigned int)UpdateParams::POSTPONE_VALIDATION_ERROR_MESSAGE);
//BBS TODO reload_scene
this->view3D->reload_scene(false, flags & (unsigned int)UpdateParams::FORCE_FULL_SCREEN_REFRESH);
this->preview->reload_print();
//BBS assemble view
this->assemble_view->reload_scene(false, flags);
//BBS reload_scene
if (wxGetApp().plater() && wxGetApp().plater()->canvas3D()->get_canvas_type() == GLCanvas3D::ECanvasType::CanvasAssembleView) { // BBS assemble view
this->assemble_view->reload_scene(false, flags);
} else {
this->view3D->reload_scene(false, flags & (unsigned int) UpdateParams::FORCE_FULL_SCREEN_REFRESH);
this->preview->reload_print();
}
if (current_panel && q->is_preview_shown()) {
q->force_update_all_plate_thumbnails();

View File

@ -1071,10 +1071,13 @@ void Selection::translate(const Vec3d &displacement, bool local)
else if (translation_type == Volume)
synchronize_unselected_volumes();
#endif // !DISABLE_INSTANCES_SYNCH
ensure_not_below_bed();
if (wxGetApp().plater()->canvas3D()->get_canvas_type() != GLCanvas3D::ECanvasType::CanvasAssembleView) {
ensure_not_below_bed();
}
set_bounding_boxes_dirty();
wxGetApp().plater()->canvas3D()->requires_check_outside_state();
if (wxGetApp().plater()->canvas3D()->get_canvas_type() != GLCanvas3D::ECanvasType::CanvasAssembleView) {
wxGetApp().plater()->canvas3D()->requires_check_outside_state();
}
}
// Rotate an object around one of the axes. Only one rotation component is expected to be changing.
@ -1188,7 +1191,9 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_
}
set_bounding_boxes_dirty();
wxGetApp().plater()->canvas3D()->requires_check_outside_state();
if (wxGetApp().plater()->canvas3D()->get_canvas_type() != GLCanvas3D::ECanvasType::CanvasAssembleView) {
wxGetApp().plater()->canvas3D()->requires_check_outside_state();
}
}
void Selection::flattening_rotate(const Vec3d& normal)
@ -1303,7 +1308,9 @@ void Selection::scale(const Vec3d& scale, TransformationType transformation_type
ensure_on_bed();
set_bounding_boxes_dirty();
wxGetApp().plater()->canvas3D()->requires_check_outside_state();
if (wxGetApp().plater()->canvas3D()->get_canvas_type() != GLCanvas3D::ECanvasType::CanvasAssembleView) {
wxGetApp().plater()->canvas3D()->requires_check_outside_state();
}
}
#if ENABLE_ENHANCED_PRINT_VOLUME_FIT