Allow wipe tower rotation by the rotation gizmo

This commit is contained in:
Lukas Matena 2019-04-26 15:34:26 +02:00
parent 045879f68a
commit 5f226c5d7f
7 changed files with 135 additions and 89 deletions

View file

@ -709,12 +709,15 @@ int GLVolumeCollection::load_wipe_tower_preview(
brim_mesh.translate(-brim_width, -brim_width, 0.f); brim_mesh.translate(-brim_width, -brim_width, 0.f);
mesh.merge(brim_mesh); mesh.merge(brim_mesh);
mesh.rotate(rotation_angle, &origin_of_rotation); // rotates the box according to the config rotation setting //mesh.rotate(rotation_angle, &origin_of_rotation); // rotates the box according to the config rotation setting
this->volumes.emplace_back(new GLVolume(color)); this->volumes.emplace_back(new GLVolume(color));
GLVolume &v = *this->volumes.back(); GLVolume &v = *this->volumes.back();
v.indexed_vertex_array.load_mesh(mesh, use_VBOs); v.indexed_vertex_array.load_mesh(mesh, use_VBOs);
v.set_volume_offset(Vec3d(pos_x, pos_y, 0.0)); v.set_volume_offset(Vec3d(pos_x, pos_y, 0.0));
v.set_volume_rotation(Vec3d(0., 0., (M_PI/180.) * rotation_angle));
// finalize_geometry() clears the vertex arrays, therefore the bounding box has to be computed before finalize_geometry(). // finalize_geometry() clears the vertex arrays, therefore the bounding box has to be computed before finalize_geometry().
v.bounding_box = v.indexed_vertex_array.bounding_box(); v.bounding_box = v.indexed_vertex_array.bounding_box();
v.indexed_vertex_array.finalize_geometry(use_VBOs); v.indexed_vertex_array.finalize_geometry(use_VBOs);

View file

@ -1201,6 +1201,7 @@ wxDEFINE_EVENT(EVT_GLCANVAS_INSTANCE_MOVED, SimpleEvent);
wxDEFINE_EVENT(EVT_GLCANVAS_INSTANCE_ROTATED, SimpleEvent); wxDEFINE_EVENT(EVT_GLCANVAS_INSTANCE_ROTATED, SimpleEvent);
wxDEFINE_EVENT(EVT_GLCANVAS_INSTANCE_SCALED, SimpleEvent); wxDEFINE_EVENT(EVT_GLCANVAS_INSTANCE_SCALED, SimpleEvent);
wxDEFINE_EVENT(EVT_GLCANVAS_WIPETOWER_MOVED, Vec3dEvent); wxDEFINE_EVENT(EVT_GLCANVAS_WIPETOWER_MOVED, Vec3dEvent);
wxDEFINE_EVENT(EVT_GLCANVAS_WIPETOWER_ROTATED, Vec3dEvent);
wxDEFINE_EVENT(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, Event<bool>); wxDEFINE_EVENT(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, Event<bool>);
wxDEFINE_EVENT(EVT_GLCANVAS_UPDATE_GEOMETRY, Vec3dsEvent<2>); wxDEFINE_EVENT(EVT_GLCANVAS_UPDATE_GEOMETRY, Vec3dsEvent<2>);
wxDEFINE_EVENT(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED, SimpleEvent); wxDEFINE_EVENT(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED, SimpleEvent);
@ -3090,6 +3091,10 @@ void GLCanvas3D::do_rotate()
for (const GLVolume* v : m_volumes.volumes) for (const GLVolume* v : m_volumes.volumes)
{ {
int object_idx = v->object_idx(); int object_idx = v->object_idx();
if (object_idx == 1000) { // the wipe tower
Vec3d offset = v->get_volume_offset();
post_event(Vec3dEvent(EVT_GLCANVAS_WIPETOWER_ROTATED, Vec3d(offset(0), offset(1), v->get_volume_rotation()(2))));
}
if ((object_idx < 0) || ((int)m_model->objects.size() <= object_idx)) if ((object_idx < 0) || ((int)m_model->objects.size() <= object_idx))
continue; continue;
@ -4289,6 +4294,7 @@ void GLCanvas3D::_render_selection_sidebar_hints() const
m_shader.stop_using(); m_shader.stop_using();
} }
void GLCanvas3D::_update_volumes_hover_state() const void GLCanvas3D::_update_volumes_hover_state() const
{ {
for (GLVolume* v : m_volumes.volumes) for (GLVolume* v : m_volumes.volumes)

View file

@ -116,6 +116,7 @@ wxDECLARE_EVENT(EVT_GLCANVAS_INSTANCE_MOVED, SimpleEvent);
wxDECLARE_EVENT(EVT_GLCANVAS_WIPETOWER_MOVED, Vec3dEvent); wxDECLARE_EVENT(EVT_GLCANVAS_WIPETOWER_MOVED, Vec3dEvent);
wxDECLARE_EVENT(EVT_GLCANVAS_INSTANCE_ROTATED, SimpleEvent); wxDECLARE_EVENT(EVT_GLCANVAS_INSTANCE_ROTATED, SimpleEvent);
wxDECLARE_EVENT(EVT_GLCANVAS_INSTANCE_SCALED, SimpleEvent); wxDECLARE_EVENT(EVT_GLCANVAS_INSTANCE_SCALED, SimpleEvent);
wxDECLARE_EVENT(EVT_GLCANVAS_WIPETOWER_ROTATED, Vec3dEvent);
wxDECLARE_EVENT(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, Event<bool>); wxDECLARE_EVENT(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, Event<bool>);
wxDECLARE_EVENT(EVT_GLCANVAS_UPDATE_GEOMETRY, Vec3dsEvent<2>); wxDECLARE_EVENT(EVT_GLCANVAS_UPDATE_GEOMETRY, Vec3dsEvent<2>);
wxDECLARE_EVENT(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED, SimpleEvent); wxDECLARE_EVENT(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED, SimpleEvent);

View file

@ -102,7 +102,7 @@ protected:
m_gizmos[i].set_hover_id((m_hover_id == i) ? 0 : -1); m_gizmos[i].set_hover_id((m_hover_id == i) ? 0 : -1);
} }
} }
virtual bool on_is_activable(const Selection& selection) const { return !selection.is_wipe_tower(); } virtual bool on_is_activable(const Selection& selection) const { return true; }
virtual void on_enable_grabber(unsigned int id) virtual void on_enable_grabber(unsigned int id)
{ {
if ((0 <= id) && (id < 3)) if ((0 <= id) && (id < 3))

View file

@ -4,6 +4,7 @@
#include "slic3r/GUI/3DScene.hpp" #include "slic3r/GUI/3DScene.hpp"
#include "slic3r/GUI/GUI_App.hpp" #include "slic3r/GUI/GUI_App.hpp"
#include "slic3r/GUI/GUI_ObjectManipulation.hpp" #include "slic3r/GUI/GUI_ObjectManipulation.hpp"
#include "slic3r/GUI/PresetBundle.hpp"
#include <GL/glew.h> #include <GL/glew.h>
#include <wx/glcanvas.h> #include <wx/glcanvas.h>
@ -264,8 +265,12 @@ void GLGizmosManager::update_data(GLCanvas3D& canvas)
const Selection& selection = canvas.get_selection(); const Selection& selection = canvas.get_selection();
bool enable_move_z = !selection.is_wipe_tower(); bool is_wipe_tower = selection.is_wipe_tower();
enable_grabber(Move, 2, enable_move_z); enable_grabber(Move, 2, !is_wipe_tower);
enable_grabber(Move, 2, !is_wipe_tower);
enable_grabber(Rotate, 0, !is_wipe_tower);
enable_grabber(Rotate, 1, !is_wipe_tower);
bool enable_scale_xyz = selection.is_single_full_instance() || selection.is_single_volume() || selection.is_single_modifier(); bool enable_scale_xyz = selection.is_single_full_instance() || selection.is_single_volume() || selection.is_single_modifier();
for (int i = 0; i < 6; ++i) for (int i = 0; i < 6; ++i)
{ {
@ -290,6 +295,14 @@ void GLGizmosManager::update_data(GLCanvas3D& canvas)
set_flattening_data(nullptr); set_flattening_data(nullptr);
set_sla_support_data(nullptr, selection); set_sla_support_data(nullptr, selection);
} }
else if (is_wipe_tower)
{
DynamicPrintConfig& config = wxGetApp().preset_bundle->prints.get_edited_preset().config;
set_scale(Vec3d::Ones());
set_rotation(Vec3d(0., 0., (M_PI/180.) * dynamic_cast<const ConfigOptionFloat*>(config.option("wipe_tower_rotation_angle"))->value));
set_flattening_data(nullptr);
set_sla_support_data(nullptr, selection);
}
else else
{ {
set_scale(Vec3d::Ones()); set_scale(Vec3d::Ones());

View file

@ -1307,6 +1307,7 @@ struct Plater::priv
void on_object_select(SimpleEvent&); void on_object_select(SimpleEvent&);
void on_right_click(Vec2dEvent&); void on_right_click(Vec2dEvent&);
void on_wipetower_moved(Vec3dEvent&); void on_wipetower_moved(Vec3dEvent&);
void on_wipetower_rotated(Vec3dEvent&);
void on_update_geometry(Vec3dsEvent<2>&); void on_update_geometry(Vec3dsEvent<2>&);
void on_3dcanvas_mouse_dragging_finished(SimpleEvent&); void on_3dcanvas_mouse_dragging_finished(SimpleEvent&);
@ -1437,6 +1438,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
{ if (evt.data == 1) this->q->increase_instances(); else if (this->can_decrease_instances()) this->q->decrease_instances(); }); { if (evt.data == 1) this->q->increase_instances(); else if (this->can_decrease_instances()) this->q->decrease_instances(); });
view3D_canvas->Bind(EVT_GLCANVAS_INSTANCE_MOVED, [this](SimpleEvent&) { update(); }); view3D_canvas->Bind(EVT_GLCANVAS_INSTANCE_MOVED, [this](SimpleEvent&) { update(); });
view3D_canvas->Bind(EVT_GLCANVAS_WIPETOWER_MOVED, &priv::on_wipetower_moved, this); view3D_canvas->Bind(EVT_GLCANVAS_WIPETOWER_MOVED, &priv::on_wipetower_moved, this);
view3D_canvas->Bind(EVT_GLCANVAS_WIPETOWER_ROTATED, &priv::on_wipetower_rotated, this);
view3D_canvas->Bind(EVT_GLCANVAS_INSTANCE_ROTATED, [this](SimpleEvent&) { update(); }); view3D_canvas->Bind(EVT_GLCANVAS_INSTANCE_ROTATED, [this](SimpleEvent&) { update(); });
view3D_canvas->Bind(EVT_GLCANVAS_INSTANCE_SCALED, [this](SimpleEvent&) { update(); }); view3D_canvas->Bind(EVT_GLCANVAS_INSTANCE_SCALED, [this](SimpleEvent&) { update(); });
view3D_canvas->Bind(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, [this](Event<bool> &evt) { this->sidebar->enable_buttons(evt.data); }); view3D_canvas->Bind(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, [this](Event<bool> &evt) { this->sidebar->enable_buttons(evt.data); });
@ -1444,6 +1446,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
view3D_canvas->Bind(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED, &priv::on_3dcanvas_mouse_dragging_finished, this); view3D_canvas->Bind(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED, &priv::on_3dcanvas_mouse_dragging_finished, this);
view3D_canvas->Bind(EVT_GLCANVAS_TAB, [this](SimpleEvent&) { select_next_view_3D(); }); view3D_canvas->Bind(EVT_GLCANVAS_TAB, [this](SimpleEvent&) { select_next_view_3D(); });
view3D_canvas->Bind(EVT_GLCANVAS_RESETGIZMOS, [this](SimpleEvent&) { reset_all_gizmos(); }); view3D_canvas->Bind(EVT_GLCANVAS_RESETGIZMOS, [this](SimpleEvent&) { reset_all_gizmos(); });
// 3DScene/Toolbar: // 3DScene/Toolbar:
view3D_canvas->Bind(EVT_GLTOOLBAR_ADD, &priv::on_action_add, this); view3D_canvas->Bind(EVT_GLTOOLBAR_ADD, &priv::on_action_add, this);
view3D_canvas->Bind(EVT_GLTOOLBAR_DELETE, [q](SimpleEvent&) { q->remove_selected(); }); view3D_canvas->Bind(EVT_GLTOOLBAR_DELETE, [q](SimpleEvent&) { q->remove_selected(); });
@ -2851,6 +2854,15 @@ void Plater::priv::on_wipetower_moved(Vec3dEvent &evt)
wxGetApp().get_tab(Preset::TYPE_PRINT)->load_config(cfg); wxGetApp().get_tab(Preset::TYPE_PRINT)->load_config(cfg);
} }
void Plater::priv::on_wipetower_rotated(Vec3dEvent& evt)
{
DynamicPrintConfig cfg;
cfg.opt<ConfigOptionFloat>("wipe_tower_x", true)->value = evt.data(0);
cfg.opt<ConfigOptionFloat>("wipe_tower_y", true)->value = evt.data(1);
cfg.opt<ConfigOptionFloat>("wipe_tower_rotation_angle", true)->value = Geometry::rad2deg(evt.data(2));
wxGetApp().get_tab(Preset::TYPE_PRINT)->load_config(cfg);
}
void Plater::priv::on_update_geometry(Vec3dsEvent<2>&) void Plater::priv::on_update_geometry(Vec3dsEvent<2>&)
{ {
// TODO // TODO

View file

@ -492,6 +492,7 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_
// Only relative rotation values are allowed in the world coordinate system. // Only relative rotation values are allowed in the world coordinate system.
assert(!transformation_type.world() || transformation_type.relative()); assert(!transformation_type.world() || transformation_type.relative());
if (!is_wipe_tower()) {
int rot_axis_max = 0; int rot_axis_max = 0;
if (rotation.isApprox(Vec3d::Zero())) if (rotation.isApprox(Vec3d::Zero()))
{ {
@ -510,8 +511,7 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_
} }
} }
} }
else else { // this is not the wipe tower
{
//FIXME this does not work for absolute rotations (transformation_type.absolute() is true) //FIXME this does not work for absolute rotations (transformation_type.absolute() is true)
rotation.cwiseAbs().maxCoeff(&rot_axis_max); rotation.cwiseAbs().maxCoeff(&rot_axis_max);
@ -580,12 +580,23 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_
} }
} }
#if !DISABLE_INSTANCES_SYNCH #if !DISABLE_INSTANCES_SYNCH
if (m_mode == Instance) if (m_mode == Instance)
synchronize_unselected_instances((rot_axis_max == 2) ? SYNC_ROTATION_NONE : SYNC_ROTATION_GENERAL); synchronize_unselected_instances((rot_axis_max == 2) ? SYNC_ROTATION_NONE : SYNC_ROTATION_GENERAL);
else if (m_mode == Volume) else if (m_mode == Volume)
synchronize_unselected_volumes(); synchronize_unselected_volumes();
#endif // !DISABLE_INSTANCES_SYNCH #endif // !DISABLE_INSTANCES_SYNCH
}
else { // it's the wipe tower that's selected and being rotated
GLVolume& volume = *((*m_volumes)[*m_list.begin()]); // the wipe tower is always alone in the selection
// make sure the wipe tower rotates around its center, not origin
// we can assume that only Z rotation changes
Vec3d center_local = volume.transformed_bounding_box().center() - volume.get_volume_offset();
Vec3d center_local_new = Eigen::AngleAxisd(rotation(2)-volume.get_volume_rotation()(2), Vec3d(0, 0, 1)) * center_local;
volume.set_volume_rotation(rotation);
volume.set_volume_offset(volume.get_volume_offset() + center_local - center_local_new);
}
m_bounding_box_dirty = true; m_bounding_box_dirty = true;
} }