Fix rotation by gizmo of embossed text on reflected object

+ refactoring code to do same for svg and text
This commit is contained in:
Filip Sykala - NTB T15p 2023-11-03 10:34:09 +01:00
parent 371a3753f2
commit 73060ecee7
4 changed files with 99 additions and 89 deletions

View File

@ -424,7 +424,7 @@ bool GLGizmoEmboss::do_mirror(size_t axis)
selection.setup_cache(); selection.setup_cache();
auto selection_mirror_fnc = [&selection, &axis]() { selection.mirror((Axis) axis, get_drag_transformation_type(selection)); }; auto selection_mirror_fnc = [&selection, &axis]() { selection.mirror((Axis) axis, get_drag_transformation_type(selection)); };
selection_transform(selection, selection_mirror_fnc, m_volume); selection_transform(selection, selection_mirror_fnc);
m_parent.do_mirror(L("Set Mirror")); m_parent.do_mirror(L("Set Mirror"));
wxGetApp().obj_manipul()->UpdateAndShow(true); wxGetApp().obj_manipul()->UpdateAndShow(true);
@ -500,34 +500,13 @@ bool GLGizmoEmboss::on_mouse_for_rotation(const wxMouseEvent &mouse_event)
if (!m_dragging) return used; if (!m_dragging) return used;
if (mouse_event.Dragging()) { if (mouse_event.Dragging()) {
if (!m_rotate_start_angle.has_value()) { // check that style is activ
// when m_rotate_start_angle is not set mean it is not Dragging
// when angle_opt is not set than angle is Zero
const std::optional<float> &angle_opt = m_style_manager.get_style().angle;
m_rotate_start_angle = angle_opt.value_or(0.f);
}
double angle = m_rotate_gizmo.get_angle();
angle -= PI / 2; // Grabber is upward
// temporary rotation
Selection& selection = m_parent.get_selection();
selection.rotate(Vec3d(0., 0., angle), get_drag_transformation_type(selection));
angle += *m_rotate_start_angle;
// move to range <-M_PI, M_PI>
Geometry::to_range_pi_pi(angle);
// set into activ style
assert(m_style_manager.is_active_font()); assert(m_style_manager.is_active_font());
if (m_style_manager.is_active_font()) { if (!m_style_manager.is_active_font())
std::optional<float> angle_opt; return used;
if (!is_approx(angle, 0.))
angle_opt = angle;
m_style_manager.get_style().angle = angle_opt;
}
volume_transformation_changing(); std::optional<float> &angle_opt = m_style_manager.get_style().angle;
dragging_rotate_gizmo(m_rotate_gizmo.get_angle(), angle_opt, m_rotate_start_angle, m_parent.get_selection());
} }
return used; return used;
} }

View File

@ -239,39 +239,9 @@ bool GLGizmoSVG::on_mouse_for_rotation(const wxMouseEvent &mouse_event)
bool used = use_grabbers(mouse_event); bool used = use_grabbers(mouse_event);
if (!m_dragging) return used; if (!m_dragging) return used;
if (mouse_event.Dragging()) { if (mouse_event.Dragging())
if (!m_rotate_start_angle.has_value()) dragging_rotate_gizmo(m_rotate_gizmo.get_angle(), m_angle, m_rotate_start_angle, m_parent.get_selection());
m_rotate_start_angle = m_angle.value_or(0.f);
double angle = m_rotate_gizmo.get_angle();
angle -= PI / 2; // Grabber is upward
double new_angle = angle + *m_rotate_start_angle;
bool is_volume_mirrored = has_reflection(m_volume->get_matrix());
bool is_instance_mirrored = has_reflection(m_parent.get_selection().get_first_volume()->get_instance_transformation().get_matrix());
if (is_volume_mirrored != is_instance_mirrored)
new_angle = -angle + *m_rotate_start_angle;
// move to range <-M_PI, M_PI>
Geometry::to_range_pi_pi(new_angle);
double z_rotation = m_volume->emboss_shape->fix_3mf_tr.has_value()?
(new_angle - m_angle.value_or(0.f)) : // relative angle
angle; // relativity is keep by selection cache
Selection &selection = m_parent.get_selection();
auto selection_rotate_fnc = [z_rotation, &selection]() {
selection.rotate(Vec3d(0., 0., z_rotation), get_drag_transformation_type(selection));
};
selection_transform(selection, selection_rotate_fnc, m_volume);
// propagate angle into property
m_angle = static_cast<float>(new_angle);
// do not store zero
if (is_approx(*m_angle, 0.f))
m_angle.reset();
}
return used; return used;
} }
@ -1790,7 +1760,7 @@ void GLGizmoSVG::draw_size()
auto selection_scale_fnc = [&selection, rel_scale = *new_relative_scale]() { auto selection_scale_fnc = [&selection, rel_scale = *new_relative_scale]() {
selection.scale(rel_scale, get_drag_transformation_type(selection)); selection.scale(rel_scale, get_drag_transformation_type(selection));
}; };
selection_transform(selection, selection_scale_fnc, m_volume); selection_transform(selection, selection_scale_fnc);
m_parent.do_scale(L("Resize")); m_parent.do_scale(L("Resize"));
wxGetApp().obj_manipul()->set_dirty(); wxGetApp().obj_manipul()->set_dirty();
@ -1952,7 +1922,7 @@ void GLGizmoSVG::draw_mirroring()
auto selection_mirror_fnc = [&selection, &axis](){ auto selection_mirror_fnc = [&selection, &axis](){
selection.mirror(axis, get_drag_transformation_type(selection)); selection.mirror(axis, get_drag_transformation_type(selection));
}; };
selection_transform(selection, selection_mirror_fnc, m_volume); selection_transform(selection, selection_mirror_fnc);
m_parent.do_mirror(L("Set Mirror")); m_parent.do_mirror(L("Set Mirror"));
// Mirror is ignoring keep up !! // Mirror is ignoring keep up !!

View File

@ -61,6 +61,14 @@ Transform3d get_volume_transformation(
// distinguish between transformation of volume inside object // distinguish between transformation of volume inside object
// and object(single full instance with one volume) // and object(single full instance with one volume)
bool is_embossed_object(const Selection &selection); bool is_embossed_object(const Selection &selection);
/// <summary>
/// Get fix transformation for selected volume
/// Fix after store to 3mf
/// </summary>
/// <param name="selection">Select only wanted volume</param>
/// <returns>Pointer on fix transformation from ModelVolume when exists otherwise nullptr</returns>
const Transform3d *get_fix_transformation(const Selection &selection);
} }
namespace Slic3r::GUI { namespace Slic3r::GUI {
@ -278,27 +286,11 @@ Transform3d world_matrix_fixed(const Selection &selection)
return world_matrix_fixed(*gl_volume, selection.get_model()->objects); return world_matrix_fixed(*gl_volume, selection.get_model()->objects);
} }
void selection_transform(Selection &selection, const std::function<void()> &selection_transformation_fnc, const ModelVolume *volume) void selection_transform(Selection &selection, const std::function<void()> &selection_transformation_fnc)
{ {
GLVolume *gl_volume = selection.get_volume(*selection.get_volume_idxs().begin()); if (const Transform3d *fix = get_fix_transformation(selection); fix != nullptr) {
auto get_fix = [&selection, &volume, &gl_volume]() -> const Transform3d * { // NOTE: need editable gl volume .. can't use selection.get_first_volume()
if (gl_volume == nullptr) GLVolume *gl_volume = selection.get_volume(*selection.get_volume_idxs().begin());
return nullptr;
if (volume == nullptr) {
volume = get_model_volume(*gl_volume, selection.get_model()->objects);
if (volume == nullptr)
return nullptr;
}
const std::optional<EmbossShape> &es = volume->emboss_shape;
if (!volume->emboss_shape.has_value())
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(); Transform3d volume_tr = gl_volume->get_volume_transformation().get_matrix();
gl_volume->set_volume_transformation(volume_tr * fix->inverse()); gl_volume->set_volume_transformation(volume_tr * fix->inverse());
selection.setup_cache(); selection.setup_cache();
@ -460,6 +452,47 @@ TransformationType get_drag_transformation_type(const Selection &selection)
TransformationType::Instance_Relative_Joint : TransformationType::Instance_Relative_Joint :
TransformationType::Local_Relative_Joint; TransformationType::Local_Relative_Joint;
} }
void dragging_rotate_gizmo(double gizmo_angle, std::optional<float>& current_angle, std::optional<float> &start_angle, Selection &selection)
{
if (!start_angle.has_value())
// create cache for initial angle
start_angle = current_angle.value_or(0.f);
gizmo_angle -= PI / 2; // Grabber is upward
double new_angle = gizmo_angle + *start_angle;
const GLVolume *gl_volume = selection.get_first_volume();
assert(gl_volume != nullptr);
if (gl_volume == nullptr)
return;
bool is_volume_mirrored = has_reflection(gl_volume->get_volume_transformation().get_matrix());
bool is_instance_mirrored = has_reflection(gl_volume->get_instance_transformation().get_matrix());
if (is_volume_mirrored != is_instance_mirrored)
new_angle = -gizmo_angle + *start_angle;
// move to range <-M_PI, M_PI>
Geometry::to_range_pi_pi(new_angle);
const Transform3d* fix = get_fix_transformation(selection);
double z_rotation = (fix!=nullptr) ? (new_angle - current_angle.value_or(0.f)) : // relative angle
gizmo_angle; // relativity is keep by selection cache
auto selection_rotate_fnc = [z_rotation, &selection]() {
selection.rotate(Vec3d(0., 0., z_rotation), get_drag_transformation_type(selection));
};
selection_transform(selection, selection_rotate_fnc);
// propagate angle into property
current_angle = static_cast<float>(new_angle);
// do not store zero
if (is_approx(*current_angle, 0.f))
current_angle.reset();
}
} // namespace Slic3r::GUI } // namespace Slic3r::GUI
// private implementation // private implementation
@ -677,4 +710,23 @@ bool is_embossed_object(const Selection &selection)
return selection.is_single_full_object() || selection.is_single_full_instance(); return selection.is_single_full_object() || selection.is_single_full_instance();
} }
const Transform3d *get_fix_transformation(const Selection &selection) {
const GLVolume *gl_volume = get_selected_gl_volume(selection);
assert(gl_volume != nullptr);
if (gl_volume == nullptr)
return nullptr;
const ModelVolume *volume = get_model_volume(*gl_volume, selection.get_model()->objects);
assert(volume != nullptr);
if (volume == nullptr)
return nullptr;
const std::optional<EmbossShape> &es = volume->emboss_shape;
if (!volume->emboss_shape.has_value())
return nullptr;
if (!es->fix_3mf_tr.has_value())
return nullptr;
return &(*es->fix_3mf_tr);
}
} // namespace } // namespace

View File

@ -122,9 +122,7 @@ Transform3d world_matrix_fixed(const Selection &selection);
/// </summary> /// </summary>
/// <param name="selection">Selected gl volume will be modified</param> /// <param name="selection">Selected gl volume will be modified</param>
/// <param name="selection_transformation_fnc">Function modified Selection transformation</param> /// <param name="selection_transformation_fnc">Function modified Selection transformation</param>
/// <param name="volume">Same as selected GLVolume, volume may(or may not) contain fix matrix, void selection_transform(Selection &selection, const std::function<void()>& selection_transformation_fnc);
/// when nullptr it is gathered from selection</param>
void selection_transform(Selection &selection, const std::function<void()>& selection_transformation_fnc, const ModelVolume *volume = nullptr);
/// <summary> /// <summary>
/// Apply camera direction for emboss direction /// Apply camera direction for emboss direction
@ -150,11 +148,22 @@ void do_local_z_rotate(GLCanvas3D &canvas, double relative_angle);
void do_local_z_move(GLCanvas3D &canvas, double relative_move); void do_local_z_move(GLCanvas3D &canvas, double relative_move);
/// <summary> /// <summary>
/// /// Distiguish between object and volume
/// Differ in possible transformation type
/// </summary> /// </summary>
/// <param name="selection"></param> /// <param name="selection">Contain selected volume/object</param>
/// <returns></returns> /// <returns>Transformation to use</returns>
TransformationType get_drag_transformation_type(const Selection &selection); TransformationType get_drag_transformation_type(const Selection &selection);
/// <summary>
/// On dragging rotate gizmo func
/// Transform GLVolume from selection
/// </summary>
/// <param name="gizmo_angle">GLGizmoRotate::get_angle()</param>
/// <param name="current_angle">In/Out current angle visible in UI</param>
/// <param name="start_angle">Cache for start dragging angle</param>
/// <param name="selection">Selected only Actual embossed volume</param>
void dragging_rotate_gizmo(double gizmo_angle, std::optional<float>& current_angle, std::optional<float> &start_angle, Selection &selection);
} // namespace Slic3r::GUI } // namespace Slic3r::GUI
#endif // slic3r_SurfaceDrag_hpp_ #endif // slic3r_SurfaceDrag_hpp_