ENH: Gizmo panning & scalling

jira: STUDIO-10777 / STUDIO-8274

Change-Id: I89166b441a606d2cd05a0c2d4569cb1de73a657b
This commit is contained in:
jun.zhang 2025-03-11 17:39:57 +08:00 committed by lane.wei
parent a7207bef35
commit 33230fd688
8 changed files with 88 additions and 26 deletions

View File

@ -192,7 +192,7 @@ bool GLGizmoAdvancedCut::gizmo_event(SLAGizmoEventType action, const Vec2d &mous
return false;
}
bool GLGizmoAdvancedCut::on_key(wxKeyEvent &evt)
bool GLGizmoAdvancedCut::on_key(const wxKeyEvent& evt)
{
bool ctrl_down = evt.GetModifiers() & wxMOD_CONTROL;

View File

@ -211,7 +211,7 @@ public:
GLGizmoAdvancedCut(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
bool gizmo_event(SLAGizmoEventType action, const Vec2d &mouse_position, bool shift_down, bool alt_down, bool control_down);
bool on_key(wxKeyEvent &evt);
bool on_key(const wxKeyEvent &evt) override;
double get_movement() const { return m_movement; }
void finish_rotation();

View File

@ -355,6 +355,11 @@ void GLGizmoBase::set_icon_filename(const std::string &filename) {
m_icon_filename = filename;
}
bool GLGizmoBase::on_key(const wxKeyEvent& key_event)
{
return false;
}
void GLGizmoBase::set_hover_id(int id)
{
if (m_grabbers.empty() || (id < (int)m_grabbers.size()))

View File

@ -214,6 +214,7 @@ public:
virtual bool apply_clipping_plane() { return true; }
virtual bool on_mouse(const wxMouseEvent &mouse_event) { return false; }
virtual bool on_key(const wxKeyEvent& key_event);
unsigned int get_sprite_id() const { return m_sprite_id; }
int get_hover_id() const { return m_hover_id; }

View File

@ -351,8 +351,10 @@ double GLGizmoMove3D::calc_projection(const UpdateData& data) const
// vector from the starting position to the found intersection
Vec3d inters_vec = inters - m_starting_drag_position;
// finds projection of the vector along the staring direction
projection = inters_vec.dot(starting_vec.normalized());
projection = inters_vec.norm();
const double sign = inters_vec.dot(starting_vec) > 1e-6f ? 1.0f : -1.0f;
projection = projection * sign;
}
if (wxGetKeyState(WXK_SHIFT))

View File

@ -118,6 +118,27 @@ BoundingBoxf3 GLGizmoScale3D::get_bounding_box() const
return t_aabb;
}
bool GLGizmoScale3D::on_key(const wxKeyEvent& key_event)
{
bool b_processed = false;
if (key_event.GetEventType() == wxEVT_KEY_DOWN) {
if (key_event.GetKeyCode() == WXK_CONTROL) {
if (!is_scalling_mode_locked()) {
set_asymmetric_scalling_enable(!is_asymmetric_scalling_enabled());
lock_scalling_mode(true);
b_processed = true;
}
}
}
else if (key_event.GetEventType() == wxEVT_KEY_UP) {
if (key_event.GetKeyCode() == WXK_CONTROL) {
lock_scalling_mode(false);
b_processed = true;
}
}
return b_processed;
}
bool GLGizmoScale3D::on_init()
{
for (int i = 0; i < 10; ++i)
@ -219,7 +240,7 @@ void GLGizmoScale3D::update_grabbers_data()
m_instance_center = (selection.is_single_full_instance() || selection.is_single_volume_or_modifier()) ? selection.get_first_volume()->get_instance_offset() : m_center;
const Vec3d box_half_size = 0.5 * m_bounding_box.size();
bool ctrl_down = wxGetKeyState(WXK_CONTROL);
bool b_asymmetric_scalling = is_asymmetric_scalling_enabled();
bool single_instance = selection.is_single_full_instance();
@ -227,29 +248,29 @@ void GLGizmoScale3D::update_grabbers_data()
// x axis
m_grabbers[0].center = Vec3d(-(box_half_size.x()), 0.0, -box_half_size.z());
m_grabbers[0].color = (ctrl_down && m_hover_id == 1) ? CONSTRAINED_COLOR : AXES_COLOR[0];
m_grabbers[0].color = (b_asymmetric_scalling && m_hover_id == 1) ? CONSTRAINED_COLOR : AXES_COLOR[0];
m_grabbers[1].center = Vec3d(box_half_size.x(), 0.0, -box_half_size.z());
m_grabbers[1].color = (ctrl_down && m_hover_id == 0) ? CONSTRAINED_COLOR : AXES_COLOR[0];
m_grabbers[1].color = (b_asymmetric_scalling && m_hover_id == 0) ? CONSTRAINED_COLOR : AXES_COLOR[0];
// y axis
m_grabbers[2].center = Vec3d(0.0, -(box_half_size.y()), -box_half_size.z());
m_grabbers[2].color = (ctrl_down && m_hover_id == 3) ? CONSTRAINED_COLOR : AXES_COLOR[1];
m_grabbers[2].color = (b_asymmetric_scalling && m_hover_id == 3) ? CONSTRAINED_COLOR : AXES_COLOR[1];
m_grabbers[3].center = Vec3d(0.0, box_half_size.y(), -box_half_size.z());
m_grabbers[3].color = (ctrl_down && m_hover_id == 2) ? CONSTRAINED_COLOR : AXES_COLOR[1];
m_grabbers[3].color = (b_asymmetric_scalling && m_hover_id == 2) ? CONSTRAINED_COLOR : AXES_COLOR[1];
// z axis do not show 4
m_grabbers[4].center = Vec3d(0.0, 0.0, -(box_half_size.z()));
m_grabbers[4].enabled = false;
m_grabbers[5].center = Vec3d(0.0, 0.0, box_half_size.z());
m_grabbers[5].color = (ctrl_down && m_hover_id == 4) ? CONSTRAINED_COLOR : AXES_COLOR[2];
m_grabbers[5].color = (b_asymmetric_scalling && m_hover_id == 4) ? CONSTRAINED_COLOR : AXES_COLOR[2];
// uniform
m_grabbers[6].center = Vec3d(-box_half_size.x(), -box_half_size.y(), -box_half_size.z());
m_grabbers[6].color = (ctrl_down && m_hover_id == 8) ? CONSTRAINED_COLOR : GRABBER_UNIFORM_COL;
m_grabbers[6].color = (b_asymmetric_scalling && m_hover_id == 8) ? CONSTRAINED_COLOR : GRABBER_UNIFORM_COL;
m_grabbers[7].center = Vec3d(box_half_size.x(), -box_half_size.y(), -box_half_size.z());
m_grabbers[7].color = (ctrl_down && m_hover_id == 9) ? CONSTRAINED_COLOR : GRABBER_UNIFORM_COL;
m_grabbers[7].color = (b_asymmetric_scalling && m_hover_id == 9) ? CONSTRAINED_COLOR : GRABBER_UNIFORM_COL;
m_grabbers[8].center = Vec3d(box_half_size.x(), box_half_size.y(), -box_half_size.z());
m_grabbers[8].color = (ctrl_down && m_hover_id == 6) ? CONSTRAINED_COLOR : GRABBER_UNIFORM_COL;
m_grabbers[8].color = (b_asymmetric_scalling && m_hover_id == 6) ? CONSTRAINED_COLOR : GRABBER_UNIFORM_COL;
m_grabbers[9].center = Vec3d(-box_half_size.x(), box_half_size.y(), -box_half_size.z());
m_grabbers[9].color = (ctrl_down && m_hover_id == 7) ? CONSTRAINED_COLOR : GRABBER_UNIFORM_COL;
m_grabbers[9].color = (b_asymmetric_scalling && m_hover_id == 7) ? CONSTRAINED_COLOR : GRABBER_UNIFORM_COL;
Transform3d t_model_matrix{ Transform3d::Identity() };
const auto t_fullsize = get_grabber_size();
@ -279,6 +300,26 @@ void GLGizmoScale3D::change_cs_by_selection() {
}
}
void GLGizmoScale3D::set_asymmetric_scalling_enable(bool is_enabled)
{
m_b_asymmetric_scalling = is_enabled;
}
bool GLGizmoScale3D::is_asymmetric_scalling_enabled() const
{
return m_b_asymmetric_scalling;
}
void GLGizmoScale3D::lock_scalling_mode(bool is_locked)
{
m_b_scalling_mode_locked = is_locked;
}
bool GLGizmoScale3D::is_scalling_mode_locked() const
{
return m_b_scalling_mode_locked;
}
void GLGizmoScale3D::on_render()
{
const Selection& selection = m_parent.get_selection();
@ -289,6 +330,11 @@ void GLGizmoScale3D::on_render()
glsafe(::glClear(GL_DEPTH_BUFFER_BIT));
glsafe(::glEnable(GL_DEPTH_TEST));
if (m_hover_id == -1) {
lock_scalling_mode(false);
set_asymmetric_scalling_enable(false);
}
update_grabbers_data();
const auto& p_ogl_manager = wxGetApp().get_opengl_manager();
@ -393,8 +439,7 @@ void GLGizmoScale3D::do_scale_along_axis(Axis axis, const UpdateData& data)
if (ratio > 0.0)
{
m_scale(axis) = m_starting.scale(axis) * ratio;
const bool ctrl_down = wxGetKeyState(WXK_CONTROL);
if (ctrl_down && abs(ratio-1.0f)>0.001) {
if (is_asymmetric_scalling_enabled() && abs(ratio - 1.0f)>0.001) {
double local_offset = 0.5 * (m_scale(axis) - m_starting.scale(axis)) * m_starting.box.size()(axis);
if (m_hover_id == 2 * axis) {
local_offset *= -1.0;
@ -433,8 +478,7 @@ double GLGizmoScale3D::calc_ratio(const UpdateData& data) const
{
double ratio = 0.0;
const bool ctrl_down = wxGetKeyState(WXK_CONTROL);
Vec3d pivot = (ctrl_down && (m_hover_id < 6)) ? m_starting.constraint_position : m_starting.plane_center; // plane_center = bottom center
Vec3d pivot = (is_asymmetric_scalling_enabled() && (m_hover_id < 6)) ? m_starting.constraint_position : m_starting.plane_center; // plane_center = bottom center
Vec3d starting_vec = m_starting.drag_position - pivot;
double len_starting_vec = starting_vec.norm();
if (len_starting_vec != 0.0)
@ -444,10 +488,10 @@ double GLGizmoScale3D::calc_ratio(const UpdateData& data) const
// vector from the starting position to the found intersection
Vec3d inters_vec = inters - m_starting.drag_position;
// finds projection of the vector along the staring direction
double proj = inters_vec.dot(starting_vec.normalized());
double proj = inters_vec.norm();
const double sign = inters_vec.dot(starting_vec) > 1e-6f ? 1.0f : -1.0f;
ratio = (len_starting_vec + proj) / len_starting_vec;
ratio = (len_starting_vec + proj * sign) / len_starting_vec;
}
if (wxGetKeyState(WXK_SHIFT))

View File

@ -69,6 +69,8 @@ public:
void data_changed(bool is_serializing) override;
void enable_ununiversal_scale(bool enable);
BoundingBoxf3 get_bounding_box() const override;
bool on_key(const wxKeyEvent& key_event) override;
protected:
virtual bool on_init() override;
virtual std::string on_get_name() const override;
@ -91,8 +93,14 @@ private:
double calc_ratio(const UpdateData& data) const;
void update_grabbers_data();
void change_cs_by_selection(); // cs mean Coordinate System
void set_asymmetric_scalling_enable(bool is_enabled);
bool is_asymmetric_scalling_enabled() const;
void lock_scalling_mode(bool is_locked);
bool is_scalling_mode_locked() const;
private:
int m_last_selected_obejct_idx, m_last_selected_volume_idx;
bool m_b_asymmetric_scalling{ false };
bool m_b_scalling_mode_locked{ false };
};

View File

@ -1395,11 +1395,13 @@ bool GLGizmosManager::on_key(wxKeyEvent& evt)
int keyCode = evt.GetKeyCode();
bool processed = false;
// todo: zhimin Each gizmo should handle key event in it own on_key() function
if (m_current == Cut) {
if (GLGizmoAdvancedCut *gizmo_cut = dynamic_cast<GLGizmoAdvancedCut *>(get_current())) {
return gizmo_cut->on_key(evt);
auto p_current_gizmo = get_current();
if (p_current_gizmo) {
processed = p_current_gizmo->on_key(evt);
}
if (processed) {
m_parent.set_as_dirty();
return processed;
}
if (evt.GetEventType() == wxEVT_KEY_UP)