Fix rotation Text relative around Z axis

This commit is contained in:
Filip Sykala - NTB T15p 2022-09-13 15:41:21 +02:00
parent 78f002cee8
commit d0ffe16964
2 changed files with 52 additions and 27 deletions

View File

@ -109,6 +109,16 @@ static bool is_text_empty(const std::string &text){
return text.empty() || return text.empty() ||
text.find_first_not_of(" \n\t\r") == std::string::npos; text.find_first_not_of(" \n\t\r") == std::string::npos;
} }
// Normalize radian angle from -PI to PI
template<typename T> void to_range_pi_pi(T& angle)
{
if (angle > PI || angle < -PI) {
int count = static_cast<int>(std::round(angle / (2 * PI)));
angle -= static_cast<T>(count * 2 * PI);
}
}
} // namespace } // namespace
GLGizmoEmboss::GLGizmoEmboss(GLCanvas3D &parent) GLGizmoEmboss::GLGizmoEmboss(GLCanvas3D &parent)
@ -195,37 +205,36 @@ bool GLGizmoEmboss::on_mouse_for_rotation(const wxMouseEvent &mouse_event)
assert(m_volume != nullptr); assert(m_volume != nullptr);
assert(m_volume->text_configuration.has_value()); assert(m_volume->text_configuration.has_value());
if (m_volume == nullptr || !m_volume->text_configuration.has_value())
return false;
static std::optional<float> start_angle;
if (mouse_event.Dragging()) { if (mouse_event.Dragging()) {
auto &angle_opt = m_volume->text_configuration->style.prop.angle; auto &angle_opt = m_volume->text_configuration->style.prop.angle;
if (!start_angle.has_value()) { float prev_angle = angle_opt.has_value() ? *angle_opt : 0.f;
start_angle = angle_opt.has_value() ? *angle_opt : 0.f; if (!m_rotate_start_angle.has_value())
} m_rotate_start_angle = angle_opt.has_value() ? *angle_opt : 0.f;
// temporary rotation
TransformationType transformation_type(TransformationType::Local);
double angle = m_rotate_gizmo.get_angle(); double angle = m_rotate_gizmo.get_angle();
angle -= PI / 2; // Grabber is upward
// temporary rotation
TransformationType transformation_type = TransformationType::Local_Relative_Joint;
m_parent.get_selection().rotate(Vec3d(0., 0., angle), transformation_type); m_parent.get_selection().rotate(Vec3d(0., 0., angle), transformation_type);
// propagate angle into property angle += *m_rotate_start_angle;
angle_opt = static_cast<float>(*start_angle + angle);
// move to range <-M_PI, M_PI> // move to range <-M_PI, M_PI>
if (*angle_opt > M_PI || *angle_opt < -M_PI) { to_range_pi_pi(angle);
int count = static_cast<int>(std::round(*angle_opt / (2 * M_PI))); // propagate angle into property
*angle_opt -= static_cast<float>(count * 2 * M_PI); angle_opt = static_cast<float>(angle);
}
// do not store zero // do not store zero
if (is_approx(*angle_opt, 0.f)) if (is_approx(*angle_opt, 0.f))
angle_opt.reset(); angle_opt.reset();
// set into activ style // set into activ style
if (m_style_manager.is_activ_font()) { assert(m_style_manager.is_activ_font());
if (m_style_manager.is_activ_font())
m_style_manager.get_font_prop().angle = angle_opt; m_style_manager.get_font_prop().angle = angle_opt;
}
} else if (mouse_event.LeftUp()) {
// apply rotation
m_parent.do_rotate(L("Text-Rotate"));
start_angle.reset();
} }
return used; return used;
} }
@ -462,9 +471,11 @@ void GLGizmoEmboss::on_render() {
#endif // !ENABLE_LEGACY_OPENGL_REMOVAL #endif // !ENABLE_LEGACY_OPENGL_REMOVAL
} }
bool is_surface_dragging = m_temp_transformation.has_value();
// Do NOT render rotation grabbers when dragging object // Do NOT render rotation grabbers when dragging object
bool is_rotate_by_grabbers = m_dragging; bool is_rotate_by_grabbers = m_dragging;
if (!m_parent.is_dragging() || is_rotate_by_grabbers) { if (!is_surface_dragging &&
(!m_parent.is_dragging() || is_rotate_by_grabbers)) {
glsafe(::glClear(GL_DEPTH_BUFFER_BIT)); glsafe(::glClear(GL_DEPTH_BUFFER_BIT));
m_rotate_gizmo.render(); m_rotate_gizmo.render();
} }
@ -640,7 +651,16 @@ void GLGizmoEmboss::on_stop_dragging()
// TODO: when start second rotatiton previous rotation rotate draggers // TODO: when start second rotatiton previous rotation rotate draggers
// This is fast fix for second try to rotate // This is fast fix for second try to rotate
// When fixing, move grabber above text (not on side) // When fixing, move grabber above text (not on side)
m_rotate_gizmo.set_angle(0); m_rotate_gizmo.set_angle(PI/2);
// apply rotation
m_parent.do_rotate(L("Text-Rotate"));
m_rotate_start_angle.reset();
// recalculate for surface cut
const FontProp &font_prop = m_style_manager.get_style().prop;
if (font_prop.use_surface) process();
} }
void GLGizmoEmboss::on_dragging(const UpdateData &data) { m_rotate_gizmo.dragging(data); } void GLGizmoEmboss::on_dragging(const UpdateData &data) { m_rotate_gizmo.dragging(data); }
@ -737,6 +757,9 @@ void GLGizmoEmboss::initialize()
// initialize text styles // initialize text styles
m_style_manager.init(wxGetApp().app_config, create_default_styles()); m_style_manager.init(wxGetApp().app_config, create_default_styles());
set_default_text(); set_default_text();
// Set rotation gizmo upwardrotate
m_rotate_gizmo.set_angle(PI/2);
} }
EmbossStyles GLGizmoEmboss::create_default_styles() EmbossStyles GLGizmoEmboss::create_default_styles()
@ -2263,7 +2286,8 @@ void GLGizmoEmboss::do_rotate(float relative_z_angle)
Selection &selection = m_parent.get_selection(); Selection &selection = m_parent.get_selection();
assert(!selection.is_empty()); assert(!selection.is_empty());
selection.setup_cache(); selection.setup_cache();
selection.rotate(Vec3d(0., 0., relative_z_angle), TransformationType::Local); TransformationType transformation_type = TransformationType::Local_Relative_Joint;
selection.rotate(Vec3d(0., 0., relative_z_angle), transformation_type);
std::string snapshot_name; // empty meand no store undo / redo std::string snapshot_name; // empty meand no store undo / redo
// NOTE: it use L instead of _L macro because prefix _ is appended // NOTE: it use L instead of _L macro because prefix _ is appended
@ -2433,10 +2457,7 @@ void GLGizmoEmboss::draw_advanced()
_L("Rotate text Clock-wise."))) { _L("Rotate text Clock-wise."))) {
// convert back to radians and CCW // convert back to radians and CCW
angle = -angle_deg * M_PI / 180.0; angle = -angle_deg * M_PI / 180.0;
if (angle < M_PI || angle > M_PI) { to_range_pi_pi(*angle);
int count = std::round(*angle / 2 * M_PI);
angle = *angle - count * (2 * M_PI);
}
if (is_approx(*angle, 0.f)) if (is_approx(*angle, 0.f))
angle.reset(); angle.reset();
@ -2444,6 +2465,8 @@ void GLGizmoEmboss::draw_advanced()
m_volume->text_configuration->style.prop.angle = angle; m_volume->text_configuration->style.prop.angle = angle;
float act_angle = angle.has_value() ? *angle : .0f; float act_angle = angle.has_value() ? *angle : .0f;
do_rotate(act_angle - prev_angle); do_rotate(act_angle - prev_angle);
// recalculate for surface cut
if (font_prop.use_surface) process();
} }
} }

View File

@ -254,6 +254,8 @@ private:
// Rotation gizmo // Rotation gizmo
GLGizmoRotate m_rotate_gizmo; GLGizmoRotate m_rotate_gizmo;
// Value is set only when dragging rotation to calculate actual angle
std::optional<float> m_rotate_start_angle;
// when draging with text object hold screen offset of cursor from object center // when draging with text object hold screen offset of cursor from object center
std::optional<Vec2d> m_dragging_mouse_offset; std::optional<Vec2d> m_dragging_mouse_offset;