Merge branch 'sidebar_fixes' of https://github.com/prusa3d/Slic3r
This commit is contained in:
commit
016507f4ef
@ -1182,8 +1182,6 @@ Vec3d extract_euler_angles(const Eigen::Matrix<double, 3, 3, Eigen::DontAlign>&
|
||||
{
|
||||
#if ENABLE_NEW_EULER_ANGLES
|
||||
// reference: http://www.gregslabaugh.net/publications/euler.pdf
|
||||
auto is_approx = [](double value, double test_value) -> bool { return std::abs(value - test_value) < EPSILON; };
|
||||
|
||||
Vec3d angles1 = Vec3d::Zero();
|
||||
Vec3d angles2 = Vec3d::Zero();
|
||||
if (is_approx(std::abs(rotation_matrix(2, 0)), 1.0))
|
||||
|
@ -32,8 +32,6 @@
|
||||
//====================
|
||||
#define ENABLE_1_42_0_ALPHA2 1
|
||||
|
||||
// Improves navigation between sidebar fields
|
||||
#define ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION (1 && ENABLE_1_42_0_ALPHA2)
|
||||
// Adds print bed models to 3D scene
|
||||
#define ENABLE_PRINT_BED_MODELS (1 && ENABLE_1_42_0_ALPHA2)
|
||||
#endif // _technologies_h_
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <stdarg.h>
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
|
||||
#include "Technologies.hpp"
|
||||
|
||||
@ -164,6 +165,12 @@ static inline T lerp(const T& a, const T& b, Number t)
|
||||
return (Number(1) - t) * a + t * b;
|
||||
}
|
||||
|
||||
template <typename Number>
|
||||
static inline bool is_approx(Number value, Number test_value)
|
||||
{
|
||||
return std::fabs(double(value) - double(test_value)) < double(EPSILON);
|
||||
};
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif
|
||||
|
@ -1617,6 +1617,9 @@ void GLCanvas3D::Selection::clear()
|
||||
|
||||
_update_type();
|
||||
m_bounding_box_dirty = true;
|
||||
|
||||
// resets the cache in the sidebar
|
||||
wxGetApp().obj_manipul()->reset_cache();
|
||||
}
|
||||
|
||||
// Update the selection based on the map from old indices to new indices after m_volumes changed.
|
||||
@ -1817,7 +1820,7 @@ void GLCanvas3D::Selection::rotate(const Vec3d& rotation, bool local)
|
||||
if (rot_axis_max != 2 && first_volume_idx != -1) {
|
||||
// Generic rotation, but no rotation around the Z axis.
|
||||
// Always do a local rotation (do not consider the selection to be a rigid body).
|
||||
assert(rotation.z() == 0);
|
||||
assert(is_approx(rotation.z(), 0.0));
|
||||
const GLVolume &first_volume = *(*m_volumes)[first_volume_idx];
|
||||
const Vec3d &rotation = first_volume.get_instance_rotation();
|
||||
double z_diff = rotation_diff_z(m_cache.volumes_data[first_volume_idx].get_instance_rotation(), m_cache.volumes_data[i].get_instance_rotation());
|
||||
@ -1842,7 +1845,7 @@ void GLCanvas3D::Selection::rotate(const Vec3d& rotation, bool local)
|
||||
else if (is_single_volume() || is_single_modifier())
|
||||
{
|
||||
if (local)
|
||||
volume.set_volume_rotation(rotation);
|
||||
volume.set_volume_rotation(volume.get_volume_rotation() + rotation);
|
||||
else
|
||||
{
|
||||
Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), rotation);
|
||||
@ -2259,7 +2262,7 @@ void GLCanvas3D::Selection::render_sidebar_hints(const std::string& sidebar_fiel
|
||||
}
|
||||
else if (is_single_volume() || is_single_modifier())
|
||||
{
|
||||
Transform3d orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true);
|
||||
Transform3d orient_matrix = (*m_volumes)[*m_list.begin()]->get_instance_transformation().get_matrix(true, false, true, true) * (*m_volumes)[*m_list.begin()]->get_volume_transformation().get_matrix(true, false, true, true);
|
||||
::glTranslated(center(0), center(1), center(2));
|
||||
::glMultMatrixd(orient_matrix.data());
|
||||
}
|
||||
@ -3995,10 +3998,8 @@ wxDEFINE_EVENT(EVT_GLCANVAS_ARRANGE, SimpleEvent);
|
||||
wxDEFINE_EVENT(EVT_GLCANVAS_QUESTION_MARK, SimpleEvent);
|
||||
wxDEFINE_EVENT(EVT_GLCANVAS_INCREASE_INSTANCES, Event<int>);
|
||||
wxDEFINE_EVENT(EVT_GLCANVAS_INSTANCE_MOVED, SimpleEvent);
|
||||
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
wxDEFINE_EVENT(EVT_GLCANVAS_INSTANCE_ROTATED, SimpleEvent);
|
||||
wxDEFINE_EVENT(EVT_GLCANVAS_INSTANCE_SCALED, SimpleEvent);
|
||||
#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
wxDEFINE_EVENT(EVT_GLCANVAS_WIPETOWER_MOVED, Vec3dEvent);
|
||||
wxDEFINE_EVENT(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, Event<bool>);
|
||||
wxDEFINE_EVENT(EVT_GLCANVAS_UPDATE_GEOMETRY, Vec3dsEvent<2>);
|
||||
@ -5361,9 +5362,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
bool already_selected = m_selection.contains_volume(m_hover_volume_id);
|
||||
bool shift_down = evt.ShiftDown();
|
||||
|
||||
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
Selection::IndicesList curr_idxs = m_selection.get_volume_idxs();
|
||||
#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
|
||||
if (already_selected && shift_down)
|
||||
m_selection.remove(m_hover_volume_id);
|
||||
@ -5380,21 +5379,14 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
#endif // ENABLE_MOVE_MIN_THRESHOLD
|
||||
}
|
||||
|
||||
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
if (curr_idxs != m_selection.get_volume_idxs())
|
||||
{
|
||||
#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
|
||||
m_gizmos.update_on_off_state(m_selection);
|
||||
_update_gizmos_data();
|
||||
#if !ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
wxGetApp().obj_manipul()->update_settings_value(m_selection);
|
||||
#endif // !ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT));
|
||||
m_dirty = true;
|
||||
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
}
|
||||
#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
}
|
||||
}
|
||||
|
||||
@ -5789,7 +5781,6 @@ void GLCanvas3D::do_move()
|
||||
ModelObject* model_object = m_model->objects[object_idx];
|
||||
if (model_object != nullptr)
|
||||
{
|
||||
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
if (selection_mode == Selection::Instance)
|
||||
model_object->instances[instance_idx]->set_offset(v->get_instance_offset());
|
||||
else if (selection_mode == Selection::Volume)
|
||||
@ -5797,20 +5788,6 @@ void GLCanvas3D::do_move()
|
||||
|
||||
object_moved = true;
|
||||
model_object->invalidate_bounding_box();
|
||||
#else
|
||||
if (selection_mode == Selection::Instance)
|
||||
{
|
||||
model_object->instances[instance_idx]->set_offset(v->get_instance_offset());
|
||||
object_moved = true;
|
||||
}
|
||||
else if (selection_mode == Selection::Volume)
|
||||
{
|
||||
model_object->volumes[volume_idx]->set_offset(v->get_volume_offset());
|
||||
object_moved = true;
|
||||
}
|
||||
if (object_moved)
|
||||
model_object->invalidate_bounding_box();
|
||||
#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
}
|
||||
}
|
||||
else if (object_idx == 1000)
|
||||
@ -5881,12 +5858,8 @@ void GLCanvas3D::do_rotate()
|
||||
m->translate_instance(i.second, shift);
|
||||
}
|
||||
|
||||
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
if (!done.empty())
|
||||
post_event(SimpleEvent(EVT_GLCANVAS_INSTANCE_ROTATED));
|
||||
#else
|
||||
post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
|
||||
#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
}
|
||||
|
||||
void GLCanvas3D::do_scale()
|
||||
@ -5937,12 +5910,8 @@ void GLCanvas3D::do_scale()
|
||||
m->translate_instance(i.second, shift);
|
||||
}
|
||||
|
||||
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
if (!done.empty())
|
||||
post_event(SimpleEvent(EVT_GLCANVAS_INSTANCE_ROTATED));
|
||||
#else
|
||||
post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
|
||||
#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
}
|
||||
|
||||
void GLCanvas3D::do_flatten()
|
||||
|
@ -125,10 +125,8 @@ wxDECLARE_EVENT(EVT_GLCANVAS_QUESTION_MARK, SimpleEvent);
|
||||
wxDECLARE_EVENT(EVT_GLCANVAS_INCREASE_INSTANCES, Event<int>); // data: +1 => increase, -1 => decrease
|
||||
wxDECLARE_EVENT(EVT_GLCANVAS_INSTANCE_MOVED, SimpleEvent);
|
||||
wxDECLARE_EVENT(EVT_GLCANVAS_WIPETOWER_MOVED, Vec3dEvent);
|
||||
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
wxDECLARE_EVENT(EVT_GLCANVAS_INSTANCE_ROTATED, SimpleEvent);
|
||||
wxDECLARE_EVENT(EVT_GLCANVAS_INSTANCE_SCALED, SimpleEvent);
|
||||
#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
wxDECLARE_EVENT(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, Event<bool>);
|
||||
wxDECLARE_EVENT(EVT_GLCANVAS_UPDATE_GEOMETRY, Vec3dsEvent<2>);
|
||||
wxDECLARE_EVENT(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED, SimpleEvent);
|
||||
|
@ -66,6 +66,12 @@ ObjectList::ObjectList(wxWindow* parent) :
|
||||
|
||||
// describe control behavior
|
||||
Bind(wxEVT_DATAVIEW_SELECTION_CHANGED, [this](wxEvent& event) {
|
||||
#ifndef __APPLE__
|
||||
// On Windows and Linux, forces a kill focus emulation on the object manipulator fields because this event handler is called
|
||||
// before the kill focus event handler on the object manipulator when changing selection in the list, invalidating the object
|
||||
// manipulator cache with the following call to selection_changed()
|
||||
wxGetApp().obj_manipul()->emulate_kill_focus();
|
||||
#endif // __APPLE__
|
||||
selection_changed();
|
||||
#ifndef __WXMSW__
|
||||
set_tooltip_for_item(get_mouse_position_in_control());
|
||||
|
@ -17,103 +17,24 @@ namespace GUI
|
||||
|
||||
ObjectManipulation::ObjectManipulation(wxWindow* parent) :
|
||||
OG_Settings(parent, true)
|
||||
#ifndef __APPLE__
|
||||
, m_focused_option("")
|
||||
#endif // __APPLE__
|
||||
{
|
||||
m_og->set_name(_(L("Object Manipulation")));
|
||||
m_og->label_width = 125;
|
||||
m_og->set_grid_vgap(5);
|
||||
|
||||
m_og->m_on_change = [this](const std::string& opt_key, const boost::any& value) {
|
||||
std::vector<std::string> axes{ "_x", "_y", "_z" };
|
||||
|
||||
std::string param;
|
||||
std::copy(opt_key.begin(), opt_key.end() - 2, std::back_inserter(param));
|
||||
|
||||
size_t i = 0;
|
||||
Vec3d new_value;
|
||||
for (auto axis : axes)
|
||||
new_value(i++) = boost::any_cast<double>(m_og->get_value(param+axis));
|
||||
|
||||
if (param == "position")
|
||||
change_position_value(new_value);
|
||||
else if (param == "rotation")
|
||||
change_rotation_value(new_value);
|
||||
else if (param == "scale")
|
||||
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
change_scale_value(new_value);
|
||||
#else
|
||||
change_scale_value(new_value);
|
||||
#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
else if (param == "size")
|
||||
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
change_size_value(new_value);
|
||||
#else
|
||||
change_size_value(new_value);
|
||||
#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
|
||||
wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event(opt_key, false);
|
||||
};
|
||||
|
||||
m_og->m_fill_empty_value = [this](const std::string& opt_key)
|
||||
{
|
||||
#if !ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
this->update_if_dirty();
|
||||
#endif // !ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
|
||||
std::string param;
|
||||
std::copy(opt_key.begin(), opt_key.end() - 2, std::back_inserter(param));
|
||||
|
||||
double value = 0.0;
|
||||
|
||||
if (param == "position") {
|
||||
int axis = opt_key.back() == 'x' ? 0 :
|
||||
opt_key.back() == 'y' ? 1 : 2;
|
||||
|
||||
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
value = m_cache.position(axis);
|
||||
#else
|
||||
value = m_cache_position(axis);
|
||||
#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
}
|
||||
else if (param == "rotation") {
|
||||
int axis = opt_key.back() == 'x' ? 0 :
|
||||
opt_key.back() == 'y' ? 1 : 2;
|
||||
|
||||
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
value = m_cache.rotation(axis);
|
||||
#else
|
||||
value = m_cache_rotation(axis);
|
||||
#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
}
|
||||
else if (param == "scale") {
|
||||
int axis = opt_key.back() == 'x' ? 0 :
|
||||
opt_key.back() == 'y' ? 1 : 2;
|
||||
|
||||
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
value = m_cache.scale(axis);
|
||||
#else
|
||||
value = m_cache_scale(axis);
|
||||
#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
}
|
||||
else if (param == "size") {
|
||||
int axis = opt_key.back() == 'x' ? 0 :
|
||||
opt_key.back() == 'y' ? 1 : 2;
|
||||
|
||||
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
value = m_cache.size(axis);
|
||||
#else
|
||||
value = m_cache_size(axis);
|
||||
#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
}
|
||||
|
||||
m_og->set_value(opt_key, double_to_string(value));
|
||||
wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event(opt_key, false);
|
||||
};
|
||||
m_og->m_on_change = std::bind(&ObjectManipulation::on_change, this, std::placeholders::_1, std::placeholders::_2);
|
||||
m_og->m_fill_empty_value = std::bind(&ObjectManipulation::on_fill_empty_value, this, std::placeholders::_1);
|
||||
|
||||
m_og->m_set_focus = [this](const std::string& opt_key)
|
||||
{
|
||||
#if !ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
this->update_if_dirty();
|
||||
#endif // !ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
#ifndef __APPLE__
|
||||
m_focused_option = opt_key;
|
||||
#endif // __APPLE__
|
||||
|
||||
// needed to show the visual hints in 3D scene
|
||||
wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event(opt_key, true);
|
||||
};
|
||||
|
||||
@ -233,9 +154,6 @@ void ObjectManipulation::UpdateAndShow(const bool show)
|
||||
{
|
||||
if (show) {
|
||||
update_settings_value(wxGetApp().plater()->canvas3D()->get_selection());
|
||||
#if !ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
update_if_dirty();
|
||||
#endif // !ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
}
|
||||
|
||||
OG_Settings::UpdateAndShow(show);
|
||||
@ -254,7 +172,6 @@ void ObjectManipulation::update_settings_value(const GLCanvas3D::Selection& sele
|
||||
m_new_rotation = volume->get_instance_rotation();
|
||||
m_new_scale = volume->get_instance_scaling_factor();
|
||||
int obj_idx = volume->object_idx();
|
||||
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
int instance_idx = volume->instance_idx();
|
||||
if ((0 <= obj_idx) && (obj_idx < (int)wxGetApp().model_objects()->size()))
|
||||
{
|
||||
@ -270,21 +187,12 @@ void ObjectManipulation::update_settings_value(const GLCanvas3D::Selection& sele
|
||||
else
|
||||
// this should never happen
|
||||
m_new_size = Vec3d::Zero();
|
||||
#else
|
||||
if ((0 <= obj_idx) && (obj_idx < (int)wxGetApp().model_objects()->size()))
|
||||
m_new_size = volume->get_instance_transformation().get_matrix(true, true) * (*wxGetApp().model_objects())[obj_idx]->raw_mesh_bounding_box().size();
|
||||
else
|
||||
// this should never happen
|
||||
m_new_size = Vec3d::Zero();
|
||||
#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
|
||||
m_new_enabled = true;
|
||||
}
|
||||
else if (selection.is_single_full_object())
|
||||
{
|
||||
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
m_cache.instance.reset();
|
||||
#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
|
||||
const BoundingBoxf3& box = selection.get_bounding_box();
|
||||
m_new_position = box.center();
|
||||
@ -297,9 +205,7 @@ void ObjectManipulation::update_settings_value(const GLCanvas3D::Selection& sele
|
||||
}
|
||||
else if (selection.is_single_modifier() || selection.is_single_volume())
|
||||
{
|
||||
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
m_cache.instance.reset();
|
||||
#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
|
||||
// the selection contains a single volume
|
||||
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
|
||||
@ -329,7 +235,6 @@ void ObjectManipulation::update_if_dirty()
|
||||
if (!m_dirty)
|
||||
return;
|
||||
|
||||
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
if (m_cache.move_label_string != _(m_new_move_label_string)+ ":")
|
||||
{
|
||||
m_cache.move_label_string = _(m_new_move_label_string)+ ":";
|
||||
@ -382,16 +287,22 @@ void ObjectManipulation::update_if_dirty()
|
||||
|
||||
m_cache.size = m_new_size;
|
||||
|
||||
Vec3d deg_rotation;
|
||||
for (size_t i = 0; i < 3; ++i)
|
||||
{
|
||||
deg_rotation(i) = Geometry::rad2deg(m_new_rotation(i));
|
||||
}
|
||||
|
||||
if (m_cache.rotation(0) != m_new_rotation(0))
|
||||
m_og->set_value("rotation_x", double_to_string(Geometry::rad2deg(m_new_rotation(0)), 2));
|
||||
m_og->set_value("rotation_x", double_to_string(deg_rotation(0), 2));
|
||||
|
||||
if (m_cache.rotation(1) != m_new_rotation(1))
|
||||
m_og->set_value("rotation_y", double_to_string(Geometry::rad2deg(m_new_rotation(1)), 2));
|
||||
m_og->set_value("rotation_y", double_to_string(deg_rotation(1), 2));
|
||||
|
||||
if (m_cache.rotation(2) != m_new_rotation(2))
|
||||
m_og->set_value("rotation_z", double_to_string(Geometry::rad2deg(m_new_rotation(2)), 2));
|
||||
m_og->set_value("rotation_z", double_to_string(deg_rotation(2), 2));
|
||||
|
||||
m_cache.rotation = m_new_rotation;
|
||||
m_cache.rotation = deg_rotation;
|
||||
|
||||
if (wxGetApp().plater()->canvas3D()->get_selection().requires_uniform_scale()) {
|
||||
m_lock_bnt->SetLock(true);
|
||||
@ -406,41 +317,27 @@ void ObjectManipulation::update_if_dirty()
|
||||
m_og->enable();
|
||||
else
|
||||
m_og->disable();
|
||||
#else
|
||||
m_move_Label->SetLabel(_(m_new_move_label_string));
|
||||
m_rotate_Label->SetLabel(_(m_new_rotate_label_string));
|
||||
m_scale_Label->SetLabel(_(m_new_scale_label_string));
|
||||
|
||||
m_og->set_value("position_x", double_to_string(m_new_position(0), 2));
|
||||
m_og->set_value("position_y", double_to_string(m_new_position(1), 2));
|
||||
m_og->set_value("position_z", double_to_string(m_new_position(2), 2));
|
||||
m_cache_position = m_new_position;
|
||||
|
||||
auto scale = m_new_scale * 100.0;
|
||||
m_og->set_value("scale_x", double_to_string(scale(0), 2));
|
||||
m_og->set_value("scale_y", double_to_string(scale(1), 2));
|
||||
m_og->set_value("scale_z", double_to_string(scale(2), 2));
|
||||
m_cache_scale = scale;
|
||||
|
||||
m_og->set_value("size_x", double_to_string(m_new_size(0), 2));
|
||||
m_og->set_value("size_y", double_to_string(m_new_size(1), 2));
|
||||
m_og->set_value("size_z", double_to_string(m_new_size(2), 2));
|
||||
m_cache_size = m_new_size;
|
||||
|
||||
m_og->set_value("rotation_x", double_to_string(round_nearest(Geometry::rad2deg(m_new_rotation(0)), 0), 2));
|
||||
m_og->set_value("rotation_y", double_to_string(round_nearest(Geometry::rad2deg(m_new_rotation(1)), 0), 2));
|
||||
m_og->set_value("rotation_z", double_to_string(round_nearest(Geometry::rad2deg(m_new_rotation(2)), 0), 2));
|
||||
m_cache_rotation = m_new_rotation;
|
||||
|
||||
if (m_new_enabled)
|
||||
m_og->enable();
|
||||
else
|
||||
m_og->disable();
|
||||
#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
|
||||
m_dirty = false;
|
||||
}
|
||||
|
||||
#ifndef __APPLE__
|
||||
void ObjectManipulation::emulate_kill_focus()
|
||||
{
|
||||
if (m_focused_option.empty())
|
||||
return;
|
||||
|
||||
// we need to use a copy because the value of m_focused_option is modified inside on_change() and on_fill_empty_value()
|
||||
std::string option = m_focused_option;
|
||||
|
||||
// see TextCtrl::propagate_value()
|
||||
if (static_cast<wxTextCtrl*>(m_og->get_fieldc(option, 0)->getWindow())->GetValue().empty())
|
||||
on_fill_empty_value(option);
|
||||
else
|
||||
on_change(option, 0);
|
||||
}
|
||||
#endif // __APPLE__
|
||||
|
||||
void ObjectManipulation::reset_settings_value()
|
||||
{
|
||||
m_new_position = Vec3d::Zero();
|
||||
@ -448,9 +345,7 @@ void ObjectManipulation::reset_settings_value()
|
||||
m_new_scale = Vec3d::Ones();
|
||||
m_new_size = Vec3d::Zero();
|
||||
m_new_enabled = false;
|
||||
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
m_cache.instance.reset();
|
||||
#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
m_dirty = true;
|
||||
}
|
||||
|
||||
@ -459,18 +354,10 @@ void ObjectManipulation::change_position_value(const Vec3d& position)
|
||||
auto canvas = wxGetApp().plater()->canvas3D();
|
||||
GLCanvas3D::Selection& selection = canvas->get_selection();
|
||||
selection.start_dragging();
|
||||
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
selection.translate(position - m_cache.position, selection.requires_local_axes());
|
||||
#else
|
||||
selection.translate(position - m_cache_position, selection.requires_local_axes());
|
||||
#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
canvas->do_move();
|
||||
|
||||
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
m_cache.position = position;
|
||||
#else
|
||||
m_cache_position = position;
|
||||
#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
}
|
||||
|
||||
void ObjectManipulation::change_rotation_value(const Vec3d& rotation)
|
||||
@ -478,23 +365,19 @@ void ObjectManipulation::change_rotation_value(const Vec3d& rotation)
|
||||
GLCanvas3D* canvas = wxGetApp().plater()->canvas3D();
|
||||
const GLCanvas3D::Selection& selection = canvas->get_selection();
|
||||
|
||||
Vec3d delta_rotation = rotation - m_cache.rotation;
|
||||
|
||||
Vec3d rad_rotation;
|
||||
for (size_t i = 0; i < 3; ++i)
|
||||
{
|
||||
rad_rotation(i) = Geometry::deg2rad(rotation(i));
|
||||
rad_rotation(i) = Geometry::deg2rad(delta_rotation(i));
|
||||
}
|
||||
|
||||
canvas->get_selection().start_dragging();
|
||||
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
canvas->get_selection().rotate(rad_rotation, selection.is_single_full_instance() || selection.requires_local_axes());
|
||||
#else
|
||||
canvas->get_selection().rotate(rad_rotation, selection.is_single_full_instance());
|
||||
#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
canvas->do_rotate();
|
||||
|
||||
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
m_cache.rotation = rotation;
|
||||
#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
}
|
||||
|
||||
void ObjectManipulation::change_scale_value(const Vec3d& scale)
|
||||
@ -503,11 +386,7 @@ void ObjectManipulation::change_scale_value(const Vec3d& scale)
|
||||
const GLCanvas3D::Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
|
||||
if (m_uniform_scale || selection.requires_uniform_scale())
|
||||
{
|
||||
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
Vec3d abs_scale_diff = (scale - m_cache.scale).cwiseAbs();
|
||||
#else
|
||||
Vec3d abs_scale_diff = (scale - m_cache_scale).cwiseAbs();
|
||||
#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
double max_diff = abs_scale_diff(X);
|
||||
Axis max_diff_axis = X;
|
||||
if (max_diff < abs_scale_diff(Y))
|
||||
@ -530,12 +409,10 @@ void ObjectManipulation::change_scale_value(const Vec3d& scale)
|
||||
canvas->get_selection().scale(scaling_factor, false);
|
||||
canvas->do_scale();
|
||||
|
||||
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
if (!m_cache.scale.isApprox(scale))
|
||||
m_cache.instance.instance_idx = -1;
|
||||
|
||||
m_cache.scale = scale;
|
||||
#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
}
|
||||
|
||||
void ObjectManipulation::change_size_value(const Vec3d& size)
|
||||
@ -543,7 +420,6 @@ void ObjectManipulation::change_size_value(const Vec3d& size)
|
||||
const GLCanvas3D::Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
|
||||
|
||||
Vec3d ref_size = m_cache.size;
|
||||
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
if (selection.is_single_volume() || selection.is_single_modifier())
|
||||
{
|
||||
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
|
||||
@ -581,15 +457,81 @@ void ObjectManipulation::change_size_value(const Vec3d& size)
|
||||
canvas->do_scale();
|
||||
|
||||
m_cache.size = size;
|
||||
#else
|
||||
if (selection.is_single_full_instance())
|
||||
{
|
||||
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
|
||||
ref_size = volume->bounding_box.size();
|
||||
}
|
||||
|
||||
void ObjectManipulation::on_change(const t_config_option_key& opt_key, const boost::any& value)
|
||||
{
|
||||
// needed to hide the visual hints in 3D scene
|
||||
wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event(opt_key, false);
|
||||
#ifndef __APPLE__
|
||||
m_focused_option = "";
|
||||
#endif // __APPLE__
|
||||
|
||||
if (!m_cache.is_valid())
|
||||
return;
|
||||
|
||||
std::vector<std::string> axes{ "_x", "_y", "_z" };
|
||||
|
||||
std::string param;
|
||||
std::copy(opt_key.begin(), opt_key.end() - 2, std::back_inserter(param));
|
||||
|
||||
size_t i = 0;
|
||||
Vec3d new_value;
|
||||
for (auto axis : axes)
|
||||
new_value(i++) = boost::any_cast<double>(m_og->get_value(param + axis));
|
||||
|
||||
if (param == "position")
|
||||
change_position_value(new_value);
|
||||
else if (param == "rotation")
|
||||
change_rotation_value(new_value);
|
||||
else if (param == "scale")
|
||||
change_scale_value(new_value);
|
||||
else if (param == "size")
|
||||
change_size_value(new_value);
|
||||
}
|
||||
|
||||
void ObjectManipulation::on_fill_empty_value(const std::string& opt_key)
|
||||
{
|
||||
// needed to hide the visual hints in 3D scene
|
||||
wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event(opt_key, false);
|
||||
#ifndef __APPLE__
|
||||
m_focused_option = "";
|
||||
#endif // __APPLE__
|
||||
|
||||
if (!m_cache.is_valid())
|
||||
return;
|
||||
|
||||
std::string param;
|
||||
std::copy(opt_key.begin(), opt_key.end() - 2, std::back_inserter(param));
|
||||
|
||||
double value = 0.0;
|
||||
|
||||
if (param == "position") {
|
||||
int axis = opt_key.back() == 'x' ? 0 :
|
||||
opt_key.back() == 'y' ? 1 : 2;
|
||||
|
||||
value = m_cache.position(axis);
|
||||
}
|
||||
else if (param == "rotation") {
|
||||
int axis = opt_key.back() == 'x' ? 0 :
|
||||
opt_key.back() == 'y' ? 1 : 2;
|
||||
|
||||
value = m_cache.rotation(axis);
|
||||
}
|
||||
else if (param == "scale") {
|
||||
int axis = opt_key.back() == 'x' ? 0 :
|
||||
opt_key.back() == 'y' ? 1 : 2;
|
||||
|
||||
value = m_cache.scale(axis);
|
||||
}
|
||||
else if (param == "size") {
|
||||
int axis = opt_key.back() == 'x' ? 0 :
|
||||
opt_key.back() == 'y' ? 1 : 2;
|
||||
|
||||
value = m_cache.size(axis);
|
||||
}
|
||||
|
||||
change_scale_value(100.0 * Vec3d(size(0) / ref_size(0), size(1) / ref_size(1), size(2) / ref_size(2)));
|
||||
#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
m_og->set_value(opt_key, double_to_string(value));
|
||||
}
|
||||
|
||||
} //namespace GUI
|
||||
|
@ -15,7 +15,6 @@ namespace GUI {
|
||||
|
||||
class ObjectManipulation : public OG_Settings
|
||||
{
|
||||
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
struct Cache
|
||||
{
|
||||
Vec3d position;
|
||||
@ -43,20 +42,22 @@ class ObjectManipulation : public OG_Settings
|
||||
|
||||
Instance instance;
|
||||
|
||||
Cache() : position(Vec3d(DBL_MAX, DBL_MAX, DBL_MAX)) , rotation(Vec3d(DBL_MAX, DBL_MAX, DBL_MAX))
|
||||
, scale(Vec3d(DBL_MAX, DBL_MAX, DBL_MAX)) , size(Vec3d(DBL_MAX, DBL_MAX, DBL_MAX))
|
||||
, move_label_string("") , rotate_label_string("") , scale_label_string("")
|
||||
Cache() { reset(); }
|
||||
void reset()
|
||||
{
|
||||
position = Vec3d(DBL_MAX, DBL_MAX, DBL_MAX);
|
||||
rotation = Vec3d(DBL_MAX, DBL_MAX, DBL_MAX);
|
||||
scale = Vec3d(DBL_MAX, DBL_MAX, DBL_MAX);
|
||||
size = Vec3d(DBL_MAX, DBL_MAX, DBL_MAX);
|
||||
move_label_string = "";
|
||||
rotate_label_string = "";
|
||||
scale_label_string = "";
|
||||
instance.reset();
|
||||
}
|
||||
bool is_valid() const { return position != Vec3d(DBL_MAX, DBL_MAX, DBL_MAX); }
|
||||
};
|
||||
|
||||
Cache m_cache;
|
||||
#else
|
||||
Vec3d m_cache_position{ 0., 0., 0. };
|
||||
Vec3d m_cache_rotation{ 0., 0., 0. };
|
||||
Vec3d m_cache_scale{ 100., 100., 100. };
|
||||
Vec3d m_cache_size{ 0., 0., 0. };
|
||||
#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
|
||||
wxStaticText* m_move_Label = nullptr;
|
||||
wxStaticText* m_scale_Label = nullptr;
|
||||
@ -76,6 +77,11 @@ class ObjectManipulation : public OG_Settings
|
||||
bool m_uniform_scale {true};
|
||||
PrusaLockButton* m_lock_bnt{ nullptr };
|
||||
|
||||
#ifndef __APPLE__
|
||||
// Currently focused option name (empty if none)
|
||||
std::string m_focused_option;
|
||||
#endif // __APPLE__
|
||||
|
||||
public:
|
||||
ObjectManipulation(wxWindow* parent);
|
||||
~ObjectManipulation() {}
|
||||
@ -92,6 +98,14 @@ public:
|
||||
void set_uniform_scaling(const bool uniform_scale) { m_uniform_scale = uniform_scale;}
|
||||
bool get_uniform_scaling() const { return m_uniform_scale; }
|
||||
|
||||
void reset_cache() { m_cache.reset(); }
|
||||
#ifndef __APPLE__
|
||||
// On Windows and Linux, emulates a kill focus event on the currently focused option (if any)
|
||||
// Used only in ObjectList wxEVT_DATAVIEW_SELECTION_CHANGED handler which is called before the regular kill focus event
|
||||
// bound to this class when changing selection in the objects list
|
||||
void emulate_kill_focus();
|
||||
#endif // __APPLE__
|
||||
|
||||
private:
|
||||
void reset_settings_value();
|
||||
|
||||
@ -105,6 +119,9 @@ private:
|
||||
void change_rotation_value(const Vec3d& rotation);
|
||||
void change_scale_value(const Vec3d& scale);
|
||||
void change_size_value(const Vec3d& size);
|
||||
|
||||
void on_change(const t_config_option_key& opt_key, const boost::any& value);
|
||||
void on_fill_empty_value(const std::string& opt_key);
|
||||
};
|
||||
|
||||
}}
|
||||
|
@ -1175,10 +1175,8 @@ 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(); });
|
||||
view3D_canvas->Bind(EVT_GLCANVAS_INSTANCE_MOVED, [this](SimpleEvent&) { update(); });
|
||||
view3D_canvas->Bind(EVT_GLCANVAS_WIPETOWER_MOVED, &priv::on_wipetower_moved, this);
|
||||
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
view3D_canvas->Bind(EVT_GLCANVAS_INSTANCE_ROTATED, [this](SimpleEvent&) { update(); });
|
||||
view3D_canvas->Bind(EVT_GLCANVAS_INSTANCE_SCALED, [this](SimpleEvent&) { update(); });
|
||||
#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||
view3D_canvas->Bind(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, [this](Event<bool> &evt) { this->sidebar->enable_buttons(evt.data); });
|
||||
view3D_canvas->Bind(EVT_GLCANVAS_UPDATE_GEOMETRY, &priv::on_update_geometry, this);
|
||||
view3D_canvas->Bind(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED, &priv::on_3dcanvas_mouse_dragging_finished, this);
|
||||
|
Loading…
Reference in New Issue
Block a user