New selection -> rotation wip

This commit is contained in:
Enrico Turri 2018-10-09 15:56:34 +02:00
parent 1b93b952a2
commit 895bdf7918
5 changed files with 345 additions and 158 deletions

View File

@ -270,9 +270,26 @@ const Vec3d& GLVolume::get_rotation() const
void GLVolume::set_rotation(const Vec3d& rotation) void GLVolume::set_rotation(const Vec3d& rotation)
{ {
#if ENABLE_EXTENDED_SELECTION
static const double TWO_PI = 2.0 * (double)PI;
#endif // ENABLE_EXTENDED_SELECTION
if (m_rotation != rotation) if (m_rotation != rotation)
{ {
m_rotation = rotation; m_rotation = rotation;
#if ENABLE_EXTENDED_SELECTION
for (int i = 0; i < 3; ++i)
{
while (m_rotation(i) < 0.0)
{
m_rotation(i) += TWO_PI;
}
while (TWO_PI < m_rotation(i))
{
m_rotation(i) -= TWO_PI;
}
}
#endif // ENABLE_EXTENDED_SELECTION
m_world_matrix_dirty = true; m_world_matrix_dirty = true;
m_transformed_bounding_box_dirty = true; m_transformed_bounding_box_dirty = true;
m_transformed_convex_hull_bounding_box_dirty = true; m_transformed_convex_hull_bounding_box_dirty = true;

View File

@ -1131,28 +1131,29 @@ bool GLCanvas3D::Mouse::is_start_position_3D_defined() const
#if ENABLE_EXTENDED_SELECTION #if ENABLE_EXTENDED_SELECTION
GLCanvas3D::Selection::VolumeCache::VolumeCache() GLCanvas3D::Selection::VolumeCache::VolumeCache()
: position(Vec3d::Zero()) : m_position(Vec3d::Zero())
, rotation(Vec3d::Zero()) , m_rotation(Vec3d::Zero())
, scaling_factor(Vec3d::Ones()) , m_scaling_factor(Vec3d::Ones())
{ {
m_rotation_matrix = Transform3d::Identity(); m_rotation_matrix = Transform3d::Identity();
} }
GLCanvas3D::Selection::VolumeCache::VolumeCache(const Vec3d& position, const Vec3d& rotation, const Vec3d& scaling_factor) GLCanvas3D::Selection::VolumeCache::VolumeCache(const Vec3d& position, const Vec3d& rotation, const Vec3d& scaling_factor)
: position(position) : m_position(position)
, rotation(rotation) , m_rotation(rotation)
, scaling_factor(scaling_factor) , m_scaling_factor(scaling_factor)
{ {
m_rotation_matrix = Transform3d::Identity(); m_rotation_matrix = Transform3d::Identity();
m_rotation_matrix.rotate(Eigen::AngleAxisd(rotation(2), Vec3d::UnitZ())); m_rotation_matrix.rotate(Eigen::AngleAxisd(m_rotation(2), Vec3d::UnitZ()));
m_rotation_matrix.rotate(Eigen::AngleAxisd(rotation(1), Vec3d::UnitY())); m_rotation_matrix.rotate(Eigen::AngleAxisd(m_rotation(1), Vec3d::UnitY()));
m_rotation_matrix.rotate(Eigen::AngleAxisd(rotation(0), Vec3d::UnitX())); m_rotation_matrix.rotate(Eigen::AngleAxisd(m_rotation(0), Vec3d::UnitX()));
} }
GLCanvas3D::Selection::Selection() GLCanvas3D::Selection::Selection()
: m_volumes(nullptr) : m_volumes(nullptr)
, m_model(nullptr) , m_model(nullptr)
, m_mode(Instance) , m_mode(Instance)
, m_type(Invalid)
, m_valid(false) , m_valid(false)
, m_bounding_box_dirty(true) , m_bounding_box_dirty(true)
{ {
@ -1199,6 +1200,7 @@ void GLCanvas3D::Selection::add(unsigned int volume_idx, bool as_single_selectio
} }
} }
update_type();
m_bounding_box_dirty = true; m_bounding_box_dirty = true;
} }
@ -1226,6 +1228,7 @@ void GLCanvas3D::Selection::remove(unsigned int volume_idx)
} }
} }
update_type();
m_bounding_box_dirty = true; m_bounding_box_dirty = true;
} }
@ -1240,115 +1243,45 @@ void GLCanvas3D::Selection::clear()
} }
m_list.clear(); m_list.clear();
update_type();
m_bounding_box_dirty = true; m_bounding_box_dirty = true;
} }
bool GLCanvas3D::Selection::is_single_full_instance(int& object_idx_out, int& instance_idx_out) const bool GLCanvas3D::Selection::is_single_full_instance() const
{ {
if (!m_valid || is_empty() || is_wipe_tower()) if (m_type == SingleFullInstance)
{
object_idx_out = -1;
instance_idx_out = -1;
return false;
}
const GLVolume* first = (*m_volumes)[*m_list.begin()];
int object_idx = first->object_idx();
int instance_idx = first->instance_idx();
unsigned int count = 0;
for (unsigned int i : m_list)
{
const GLVolume* v = (*m_volumes)[i];
if ((v->object_idx() != object_idx) || (v->instance_idx() != instance_idx))
return false;
else
++count;
}
bool res = (count == (unsigned int)m_model->objects[object_idx]->volumes.size());
object_idx_out = res ? object_idx : -1;
instance_idx_out = res ? instance_idx : -1;
return res;
}
bool GLCanvas3D::Selection::is_single_full_object(int& object_idx_out) const
{
if (!m_valid || is_empty() || is_wipe_tower())
{
object_idx_out = -1;
return false;
}
int object_idx = (*m_volumes)[*m_list.begin()]->object_idx();
unsigned int count = 0;
for (unsigned int i : m_list)
{
const GLVolume* v = (*m_volumes)[i];
if (v->object_idx() != object_idx)
return false;
else
++count;
}
bool res = (count == (unsigned int)m_model->objects[object_idx]->volumes.size() * (unsigned int)m_model->objects[object_idx]->instances.size());
object_idx_out = res ? object_idx : -1;
return res;
}
bool GLCanvas3D::Selection::is_from_single_instance(int& object_idx_out, int& instance_idx_out) const
{
if (!m_valid || is_empty() || is_wipe_tower())
{
object_idx_out = -1;
instance_idx_out = -1;
return false;
}
const GLVolume* first = (*m_volumes)[*m_list.begin()];
int object_idx = first->object_idx();
int instance_idx = first->instance_idx();
for (unsigned int i : m_list)
{
const GLVolume* v = (*m_volumes)[i];
if ((v->object_idx() != object_idx) || (v->instance_idx() != instance_idx))
return false;
}
object_idx_out = object_idx;
instance_idx_out = instance_idx;
return true; return true;
int object_idx = m_valid ? get_object_idx() : -1;
if (object_idx != -1)
{
if (get_instance_idx() != -1)
return m_model->objects[object_idx]->volumes.size() == m_list.size();
} }
bool GLCanvas3D::Selection::is_from_single_object(int& object_idx_out) const
{
if (!m_valid || is_empty() || is_wipe_tower())
{
object_idx_out = -1;
return false; return false;
} }
int object_idx = (*m_volumes)[*m_list.begin()]->object_idx(); int GLCanvas3D::Selection::get_object_idx() const
for (unsigned int i : m_list)
{ {
const GLVolume* v = (*m_volumes)[i]; return (m_cache.content.size() == 1) ? m_cache.content.begin()->first : -1;
if (v->object_idx() != object_idx)
return false;
} }
object_idx_out = object_idx; int GLCanvas3D::Selection::get_instance_idx() const
return true; {
if (m_cache.content.size() == 1)
{
const InstanceIdxsList& idxs = m_cache.content.begin()->second;
if (idxs.size() == 1)
return *idxs.begin();
}
return -1;
} }
const GLVolume* GLCanvas3D::Selection::get_volume(unsigned int volume_idx) const const GLVolume* GLCanvas3D::Selection::get_volume(unsigned int volume_idx) const
{ {
if (!m_valid) return (m_valid && (volume_idx < (unsigned int)m_volumes->size())) ? (*m_volumes)[volume_idx] : nullptr;
return nullptr;
return (volume_idx < (unsigned int)m_volumes->size()) ? (*m_volumes)[volume_idx] : nullptr;
} }
const BoundingBoxf3& GLCanvas3D::Selection::get_bounding_box() const const BoundingBoxf3& GLCanvas3D::Selection::get_bounding_box() const
@ -1374,7 +1307,40 @@ void GLCanvas3D::Selection::translate(const Vec3d& displacement)
for (unsigned int i : m_list) for (unsigned int i : m_list)
{ {
(*m_volumes)[i]->set_offset(m_cache.volumes_data[i].position + displacement); (*m_volumes)[i]->set_offset(m_cache.volumes_data[i].get_position() + displacement);
}
m_bounding_box_dirty = true;
}
void GLCanvas3D::Selection::rotate(const Vec3d& rotation)
{
if (!m_valid)
return;
Transform3d m = Transform3d::Identity();
if (rotation(2) != 0.0f)
m.rotate(Eigen::AngleAxisd(rotation(2), Vec3d::UnitZ()));
else if (rotation(1) != 0.0f)
m.rotate(Eigen::AngleAxisd(rotation(1), Vec3d::UnitY()));
else if (rotation(0) != 0.0f)
m.rotate(Eigen::AngleAxisd(rotation(0), Vec3d::UnitX()));
bool single_full_instance = is_single_full_instance();
for (unsigned int i : m_list)
{
Vec3d radius = m * (m_cache.volumes_data[i].get_position() - m_cache.dragging_center);
(*m_volumes)[i]->set_offset(m_cache.dragging_center + radius);
if (single_full_instance)
(*m_volumes)[i]->set_rotation(rotation);
else
{
Eigen::Matrix<double, 3, 3, Eigen::DontAlign> new_rotation_matrix = (m * m_cache.volumes_data[i].get_rotation_matrix()).matrix().block(0, 0, 3, 3);
Vec3d angles = new_rotation_matrix.eulerAngles(2, 1, 0);
(*m_volumes)[i]->set_rotation(Vec3d(angles(2), angles(1), angles(0)));
}
} }
m_bounding_box_dirty = true; m_bounding_box_dirty = true;
@ -1394,6 +1360,102 @@ void GLCanvas3D::Selection::update_valid()
m_valid = (m_volumes != nullptr) && (m_model != nullptr); m_valid = (m_volumes != nullptr) && (m_model != nullptr);
} }
void GLCanvas3D::Selection::update_type()
{
m_cache.content.clear();
m_type = Mixed;
for (unsigned int i : m_list)
{
const GLVolume* volume = (*m_volumes)[i];
int obj_idx = volume->object_idx();
int inst_idx = volume->instance_idx();
ObjectIdxsToInstanceIdxsMap::iterator obj_it = m_cache.content.find(obj_idx);
if (obj_it == m_cache.content.end())
obj_it = m_cache.content.insert(ObjectIdxsToInstanceIdxsMap::value_type(obj_idx, InstanceIdxsList())).first;
obj_it->second.insert(inst_idx);
}
if (!m_valid)
m_type = Invalid;
else
{
if (m_list.empty())
m_type = Empty;
else if (m_list.size() == 1)
{
const GLVolume* first = (*m_volumes)[*m_list.begin()];
if (first->is_wipe_tower)
m_type = WipeTower;
else if (first->is_modifier)
m_type = Modifier;
else
{
const ModelObject* model_object = m_model->objects[first->object_idx()];
unsigned int volumes_count = (unsigned int)model_object->volumes.size();
unsigned int instances_count = (unsigned int)model_object->instances.size();
if (volumes_count * instances_count == 1)
m_type = SingleFullObject;
else if (volumes_count == 1) // instances_count > 1
m_type = SingleFullInstance;
}
}
else
{
if (m_cache.content.size() == 1) // single object
{
const ModelObject* model_object = m_model->objects[m_cache.content.begin()->first];
unsigned int volumes_count = (unsigned int)model_object->volumes.size();
unsigned int instances_count = (unsigned int)model_object->instances.size();
if (volumes_count * instances_count == (unsigned int)m_list.size())
m_type = SingleFullObject;
else if ((m_cache.content.begin()->second.size() == 1) && (volumes_count == (unsigned int)m_list.size()))
m_type = SingleFullInstance;
}
}
}
switch (m_type)
{
case Invalid:
{
std::cout << "selection type: Invalid" << std::endl;
break;
}
case Empty:
{
std::cout << "selection type: Empty" << std::endl;
break;
}
case WipeTower:
{
std::cout << "selection type: WipeTower" << std::endl;
break;
}
case Modifier:
{
std::cout << "selection type: Modifier" << std::endl;
break;
}
case SingleFullObject:
{
std::cout << "selection type: SingleFullObject" << std::endl;
break;
}
case SingleFullInstance:
{
std::cout << "selection type: SingleFullInstance" << std::endl;
break;
}
case Mixed:
{
std::cout << "selection type: Mixed" << std::endl;
break;
}
}
}
void GLCanvas3D::Selection::set_caches() void GLCanvas3D::Selection::set_caches()
{ {
m_cache.volumes_data.clear(); m_cache.volumes_data.clear();
@ -1753,25 +1815,20 @@ void GLCanvas3D::Gizmos::set_hover_id(int id)
} }
#if ENABLE_EXTENDED_SELECTION #if ENABLE_EXTENDED_SELECTION
void GLCanvas3D::Gizmos::enable_grabber(EType type, unsigned int id) void GLCanvas3D::Gizmos::enable_grabber(EType type, unsigned int id, bool enable)
{ {
if (!m_enabled) if (!m_enabled)
return; return;
GizmosMap::const_iterator it = m_gizmos.find(type); GizmosMap::const_iterator it = m_gizmos.find(type);
if (it != m_gizmos.end()) if (it != m_gizmos.end())
{
if (enable)
it->second->enable_grabber(id); it->second->enable_grabber(id);
} else
void GLCanvas3D::Gizmos::disable_grabber(EType type, unsigned int id)
{
if (!m_enabled)
return;
GizmosMap::const_iterator it = m_gizmos.find(type);
if (it != m_gizmos.end())
it->second->disable_grabber(id); it->second->disable_grabber(id);
} }
}
#endif // ENABLE_EXTENDED_SELECTION #endif // ENABLE_EXTENDED_SELECTION
bool GLCanvas3D::Gizmos::overlay_contains_mouse(const GLCanvas3D& canvas, const Vec2d& mouse_pos) const bool GLCanvas3D::Gizmos::overlay_contains_mouse(const GLCanvas3D& canvas, const Vec2d& mouse_pos) const
@ -2425,7 +2482,9 @@ 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_GIZMO_SCALE, Vec3dEvent); wxDEFINE_EVENT(EVT_GIZMO_SCALE, Vec3dEvent);
#if !ENABLE_EXTENDED_SELECTION
wxDEFINE_EVENT(EVT_GIZMO_ROTATE, Vec3dEvent); wxDEFINE_EVENT(EVT_GIZMO_ROTATE, Vec3dEvent);
#endif // !ENABLE_EXTENDED_SELECTION
wxDEFINE_EVENT(EVT_GIZMO_FLATTEN, Vec3dEvent); wxDEFINE_EVENT(EVT_GIZMO_FLATTEN, Vec3dEvent);
GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas) GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas)
@ -2977,20 +3036,21 @@ void GLCanvas3D::update_gizmos_data()
return; return;
#if ENABLE_EXTENDED_SELECTION #if ENABLE_EXTENDED_SELECTION
if (m_gizmos.get_current_type() == Gizmos::Move) bool enable_move_z = !m_selection.is_wipe_tower();
bool is_single_full_object = m_selection.is_single_full_object();
bool is_single_full_instance = m_selection.is_single_full_instance();
bool enable_rotate_xy = is_single_full_object && !is_single_full_instance;
m_gizmos.enable_grabber(Gizmos::Move, 2, enable_move_z);
for (int i = 0; i < 2; ++i)
{ {
if (m_selection.is_wipe_tower()) m_gizmos.enable_grabber(Gizmos::Rotate, i, enable_rotate_xy);
m_gizmos.disable_grabber(Gizmos::Move, 2);
else
m_gizmos.enable_grabber(Gizmos::Move, 2);
} }
int object_idx = -1; if (is_single_full_instance)
int instance_idx = -1;
if (m_selection.is_single_full_instance(object_idx, instance_idx))
{ {
ModelObject* model_object = m_model->objects[object_idx]; ModelObject* model_object = m_model->objects[m_selection.get_object_idx()];
ModelInstance* model_instance = model_object->instances[instance_idx]; ModelInstance* model_instance = model_object->instances[m_selection.get_instance_idx()];
m_gizmos.set_scale(model_instance->get_scaling_factor()); m_gizmos.set_scale(model_instance->get_scaling_factor());
m_gizmos.set_rotation(model_instance->get_rotation()); m_gizmos.set_rotation(model_instance->get_rotation());
m_gizmos.set_flattening_data(model_object); m_gizmos.set_flattening_data(model_object);
@ -3477,8 +3537,7 @@ void GLCanvas3D::on_mouse_wheel(wxMouseEvent& evt)
if (is_layers_editing_enabled()) if (is_layers_editing_enabled())
{ {
#if ENABLE_EXTENDED_SELECTION #if ENABLE_EXTENDED_SELECTION
int object_idx_selected = -1; int object_idx_selected = m_selection.get_object_idx();
m_selection.is_from_single_object(object_idx_selected);
#else #else
int object_idx_selected = _get_first_selected_object_id(); int object_idx_selected = _get_first_selected_object_id();
#endif // ENABLE_EXTENDED_SELECTION #endif // ENABLE_EXTENDED_SELECTION
@ -3526,8 +3585,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
Point pos(evt.GetX(), evt.GetY()); Point pos(evt.GetX(), evt.GetY());
#if ENABLE_EXTENDED_SELECTION #if ENABLE_EXTENDED_SELECTION
int selected_object_idx = -1; int selected_object_idx = m_selection.get_object_idx();
m_selection.is_from_single_object(selected_object_idx);
int layer_editing_object_idx = is_layers_editing_enabled() ? selected_object_idx : -1; int layer_editing_object_idx = is_layers_editing_enabled() ? selected_object_idx : -1;
#else #else
int selected_object_idx = _get_first_selected_object_id(); int selected_object_idx = _get_first_selected_object_id();
@ -3581,11 +3639,22 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
case Gizmos::Rotate: case Gizmos::Rotate:
{ {
#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM
#if ENABLE_EXTENDED_SELECTION
m_regenerate_volumes = false;
const Vec3d& rotation = m_gizmos.get_rotation();
m_selection.rotate(rotation);
_on_rotate();
#else
post_event(Vec3dEvent(EVT_GIZMO_ROTATE, std::move(m_gizmos.get_rotation()))); post_event(Vec3dEvent(EVT_GIZMO_ROTATE, std::move(m_gizmos.get_rotation())));
#endif // ENABLE_EXTENDED_SELECTION
#else #else
m_on_gizmo_rotate_callback.call((double)m_gizmos.get_angle_z()); m_on_gizmo_rotate_callback.call((double)m_gizmos.get_angle_z());
#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM #endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM
#if ENABLE_EXTENDED_SELECTION
wxGetApp().obj_manipul()->update_settings_value(m_selection);
#else
wxGetApp().obj_manipul()->update_rotation_values(); wxGetApp().obj_manipul()->update_rotation_values();
#endif // ENABLE_EXTENDED_SELECTION
m_dirty = true; m_dirty = true;
break; break;
} }
@ -3726,8 +3795,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
#if ENABLE_EXTENDED_SELECTION #if ENABLE_EXTENDED_SELECTION
if (m_picking_enabled && (m_hover_volume_id != -1)) if (m_picking_enabled && (m_hover_volume_id != -1))
{ {
int object_idx = -1; int object_idx = m_selection.get_object_idx();
m_selection.is_from_single_object(object_idx);
_on_select(m_hover_volume_id, object_idx); _on_select(m_hover_volume_id, object_idx);
} }
#else #else
@ -3849,7 +3917,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
v->set_offset(v->get_offset() + Vec3d(displacement(0), displacement(1), 0.0)); v->set_offset(v->get_offset() + Vec3d(displacement(0), displacement(1), 0.0));
} }
wxGetApp().obj_manipul()->update_position_values(volume->get_offset()); wxGetApp().obj_manipul()->update_position_value(volume->get_offset());
m_mouse.drag.start_position_3D = cur_pos; m_mouse.drag.start_position_3D = cur_pos;
#endif // ENABLE_EXTENDED_SELECTION #endif // ENABLE_EXTENDED_SELECTION
@ -3897,7 +3965,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
{ {
v->set_offset(v->get_offset() + offset); v->set_offset(v->get_offset() + offset);
} }
wxGetApp().obj_manipul()->update_position_values(volume->get_offset()); wxGetApp().obj_manipul()->update_position_value(volume->get_offset());
#endif // ENABLE_EXTENDED_SELECTION #endif // ENABLE_EXTENDED_SELECTION
break; break;
} }
@ -3929,6 +3997,8 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
{ {
#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM
#if ENABLE_EXTENDED_SELECTION #if ENABLE_EXTENDED_SELECTION
m_selection.rotate(m_gizmos.get_rotation());
wxGetApp().obj_manipul()->update_settings_value(m_selection);
#else #else
// Apply new temporary rotation // Apply new temporary rotation
const Vec3d& rotation = m_gizmos.get_rotation(); const Vec3d& rotation = m_gizmos.get_rotation();
@ -4121,7 +4191,12 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
case Gizmos::Rotate: case Gizmos::Rotate:
{ {
#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM
#if ENABLE_EXTENDED_SELECTION
m_regenerate_volumes = false;
_on_rotate();
#else
post_event(Vec3dEvent(EVT_GIZMO_ROTATE, m_gizmos.get_rotation())); post_event(Vec3dEvent(EVT_GIZMO_ROTATE, m_gizmos.get_rotation()));
#endif // ENABLE_EXTENDED_SELECTION
#else #else
m_on_gizmo_rotate_callback.call((double)m_gizmos.get_angle_z()); m_on_gizmo_rotate_callback.call((double)m_gizmos.get_angle_z());
#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM #endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM
@ -6178,7 +6253,7 @@ void GLCanvas3D::_on_move()
if (object_idx < 1000) if (object_idx < 1000)
{ {
// Move a regular object. // Move instances.
ModelObject* model_object = m_model->objects[object_idx]; ModelObject* model_object = m_model->objects[object_idx];
if (model_object != nullptr) if (model_object != nullptr)
{ {
@ -6198,6 +6273,41 @@ void GLCanvas3D::_on_move()
if (wipe_tower_origin != Vec3d::Zero()) if (wipe_tower_origin != Vec3d::Zero())
post_event(Vec3dEvent(EVT_GLCANVAS_WIPETOWER_MOVED, std::move(wipe_tower_origin))); post_event(Vec3dEvent(EVT_GLCANVAS_WIPETOWER_MOVED, std::move(wipe_tower_origin)));
} }
void GLCanvas3D::_on_rotate()
{
if (m_model == nullptr)
return;
std::set<std::string> done; // prevent rotating instances twice
const Selection::IndicesList& selection = m_selection.get_volume_idxs();
for (unsigned int i : selection)
{
const GLVolume* v = m_volumes.volumes[i];
int object_idx = v->object_idx();
int instance_idx = v->instance_idx();
// prevent rotating instances twice
char done_id[64];
::sprintf(done_id, "%d_%d", object_idx, instance_idx);
if (done.find(done_id) != done.end())
continue;
done.insert(done_id);
if (object_idx < 1000)
{
// Rotate instances.
ModelObject* model_object = m_model->objects[object_idx];
if (model_object != nullptr)
{
model_object->instances[instance_idx]->set_rotation(v->get_rotation());
model_object->invalidate_bounding_box();
}
}
}
}
#else #else
void GLCanvas3D::_on_move(const std::vector<int>& volume_idxs) void GLCanvas3D::_on_move(const std::vector<int>& volume_idxs)
{ {

View File

@ -116,7 +116,9 @@ 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_GIZMO_SCALE, Vec3dEvent); wxDECLARE_EVENT(EVT_GIZMO_SCALE, Vec3dEvent);
#if !ENABLE_EXTENDED_SELECTION
wxDECLARE_EVENT(EVT_GIZMO_ROTATE, Vec3dEvent); wxDECLARE_EVENT(EVT_GIZMO_ROTATE, Vec3dEvent);
#endif // !ENABLE_EXTENDED_SELECTION
wxDECLARE_EVENT(EVT_GIZMO_FLATTEN, Vec3dEvent); wxDECLARE_EVENT(EVT_GIZMO_FLATTEN, Vec3dEvent);
@ -390,29 +392,45 @@ public:
Object Object
}; };
enum EType : unsigned char
{
Invalid,
Empty,
WipeTower,
Modifier,
SingleFullObject,
SingleFullInstance,
Mixed
};
private: private:
struct VolumeCache struct VolumeCache
{ {
private: private:
Vec3d m_position;
Vec3d m_rotation;
Vec3d m_scaling_factor;
Transform3d m_rotation_matrix; Transform3d m_rotation_matrix;
public: public:
Vec3d position;
Vec3d rotation;
Vec3d scaling_factor;
VolumeCache(); VolumeCache();
VolumeCache(const Vec3d& position, const Vec3d& rotation, const Vec3d& scaling_factor); VolumeCache(const Vec3d& position, const Vec3d& rotation, const Vec3d& scaling_factor);
const Vec3d& get_position() const { return m_position; }
const Vec3d& get_rotation() const { return m_rotation; }
const Vec3d& get_scaling_factor() const { return m_scaling_factor; }
const Transform3d& get_rotation_matrix() const { return m_rotation_matrix; } const Transform3d& get_rotation_matrix() const { return m_rotation_matrix; }
}; };
typedef std::map<unsigned int, VolumeCache> VolumesCache; typedef std::map<unsigned int, VolumeCache> VolumesCache;
typedef std::set<int> InstanceIdxsList;
typedef std::map<int, InstanceIdxsList> ObjectIdxsToInstanceIdxsMap;
struct Cache struct Cache
{ {
VolumesCache volumes_data; VolumesCache volumes_data;
Vec3d dragging_center; Vec3d dragging_center;
ObjectIdxsToInstanceIdxsMap content;
}; };
GLVolumePtrs* m_volumes; GLVolumePtrs* m_volumes;
@ -420,6 +438,7 @@ public:
bool m_valid; bool m_valid;
EMode m_mode; EMode m_mode;
EType m_type;
IndicesList m_list; IndicesList m_list;
Cache m_cache; Cache m_cache;
mutable BoundingBoxf3 m_bounding_box; mutable BoundingBoxf3 m_bounding_box;
@ -438,13 +457,18 @@ public:
void remove(unsigned int volume_idx); void remove(unsigned int volume_idx);
void clear(); void clear();
bool is_empty() const { return m_list.empty(); } bool is_empty() const { return m_type == Empty; }
bool is_wipe_tower() const { return m_valid && (m_list.size() == 1) && (*m_volumes)[*m_list.begin()]->is_wipe_tower; } bool is_wipe_tower() const { return m_type == WipeTower; }
bool is_modifier() const { return m_valid && (m_list.size() == 1) && (*m_volumes)[*m_list.begin()]->is_modifier; } bool is_modifier() const { return m_type == Modifier; }
bool is_single_full_instance(int& object_idx_out, int& instance_idx_out) const; bool is_single_full_instance() const;
bool is_single_full_object(int& object_idx_out) const; bool is_single_full_object() const { return m_type == SingleFullObject; }
bool is_from_single_instance(int& object_idx_out, int& instance_idx_out) const; bool is_from_single_instance() const { return get_instance_idx() != -1; }
bool is_from_single_object(int& object_idx_out) const; bool is_from_single_object() const { return get_object_idx() != -1; }
// Returns the the object id if the selection is from a single object, otherwise is -1
int get_object_idx() const;
// Returns the instance id if the selection is from a single object and from a single instance, otherwise is -1
int get_instance_idx() const;
const IndicesList& get_volume_idxs() const { return m_list; } const IndicesList& get_volume_idxs() const { return m_list; }
const GLVolume* get_volume(unsigned int volume_idx) const; const GLVolume* get_volume(unsigned int volume_idx) const;
@ -455,11 +479,13 @@ public:
void start_dragging(); void start_dragging();
void translate(const Vec3d& displacement); void translate(const Vec3d& displacement);
void rotate(const Vec3d& rotation);
void render() const; void render() const;
private: private:
void update_valid(); void update_valid();
void update_type();
void set_caches(); void set_caches();
void add_volume(unsigned int volume_idx); void add_volume(unsigned int volume_idx);
void add_instance(unsigned int volume_idx); void add_instance(unsigned int volume_idx);
@ -517,8 +543,7 @@ private:
void set_hover_id(int id); void set_hover_id(int id);
#if ENABLE_EXTENDED_SELECTION #if ENABLE_EXTENDED_SELECTION
void enable_grabber(EType type, unsigned int id); void enable_grabber(EType type, unsigned int id, bool enable);
void disable_grabber(EType type, unsigned int id);
#endif // ENABLE_EXTENDED_SELECTION #endif // ENABLE_EXTENDED_SELECTION
bool overlay_contains_mouse(const GLCanvas3D& canvas, const Vec2d& mouse_pos) const; bool overlay_contains_mouse(const GLCanvas3D& canvas, const Vec2d& mouse_pos) const;
@ -898,6 +923,7 @@ private:
#if ENABLE_EXTENDED_SELECTION #if ENABLE_EXTENDED_SELECTION
void _on_move(); void _on_move();
void _on_rotate();
#else #else
void _on_move(const std::vector<int>& volume_idxs); void _on_move(const std::vector<int>& volume_idxs);
#endif // ENABLE_EXTENDED_SELECTION #endif // ENABLE_EXTENDED_SELECTION

View File

@ -265,27 +265,41 @@ void ObjectManipulation::update_settings_list()
#if ENABLE_EXTENDED_SELECTION #if ENABLE_EXTENDED_SELECTION
void ObjectManipulation::update_settings_value(const GLCanvas3D::Selection& selection) void ObjectManipulation::update_settings_value(const GLCanvas3D::Selection& selection)
{ {
int object_idx = -1; if (selection.is_single_full_object())
int instance_idx = -1; {
if (selection.is_single_full_instance(object_idx, instance_idx)) if (wxGetApp().mainframe->m_plater->model().objects[selection.get_object_idx()]->instances.size() == 1)
{ {
// all volumes in the selection belongs to the same instance, any of them contains the needed data, so we take the first // all volumes in the selection belongs to the same instance, any of them contains the needed data, so we take the first
const GLCanvas3D::Selection::IndicesList& idxs = selection.get_volume_idxs(); const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
update_position_values(selection.get_volume(*idxs.begin())->get_offset()); update_position_value(volume->get_offset());
update_rotation_value(volume->get_rotation());
m_og->enable();
}
else
reset_settings_value();
}
else if (selection.is_single_full_instance())
{
// all volumes in the selection belongs to the same instance, any of them contains the needed data, so we take the first
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
update_position_value(volume->get_offset());
update_rotation_value(volume->get_rotation());
m_og->enable(); m_og->enable();
} }
else if (selection.is_wipe_tower()) else if (selection.is_wipe_tower())
{ {
// the selection contains a single volume // the selection contains a single volume
const GLCanvas3D::Selection::IndicesList& idxs = selection.get_volume_idxs(); const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
update_position_values(selection.get_volume(*idxs.begin())->get_offset()); update_position_value(volume->get_offset());
update_rotation_value(volume->get_rotation());
m_og->enable(); m_og->enable();
} }
else if (selection.is_modifier()) else if (selection.is_modifier())
{ {
// the selection contains a single volume // the selection contains a single volume
const GLCanvas3D::Selection::IndicesList& idxs = selection.get_volume_idxs(); const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
update_position_values(selection.get_volume(*idxs.begin())->get_offset()); update_position_value(volume->get_offset());
update_rotation_value(volume->get_rotation());
m_og->enable(); m_og->enable();
} }
else else
@ -293,17 +307,34 @@ void ObjectManipulation::update_settings_value(const GLCanvas3D::Selection& sele
} }
void ObjectManipulation::reset_settings_value() void ObjectManipulation::reset_settings_value()
{
reset_position_value();
reset_rotation_value();
reset_scale_value();
m_og->disable();
}
void ObjectManipulation::reset_position_value()
{ {
m_og->set_value("position_x", 0); m_og->set_value("position_x", 0);
m_og->set_value("position_y", 0); m_og->set_value("position_y", 0);
m_og->set_value("position_z", 0); m_og->set_value("position_z", 0);
m_og->set_value("scale_x", 0); }
m_og->set_value("scale_y", 0);
m_og->set_value("scale_z", 0); void ObjectManipulation::reset_rotation_value()
{
m_og->set_value("rotation_x", 0); m_og->set_value("rotation_x", 0);
m_og->set_value("rotation_y", 0); m_og->set_value("rotation_y", 0);
m_og->set_value("rotation_z", 0); m_og->set_value("rotation_z", 0);
m_og->disable(); }
void ObjectManipulation::reset_scale_value()
{
m_is_percent_scale = true;
m_og->set_value("scale_unit", _("%"));
m_og->set_value("scale_x", 100);
m_og->set_value("scale_y", 100);
m_og->set_value("scale_z", 100);
} }
#endif // ENABLE_EXTENDED_SELECTION #endif // ENABLE_EXTENDED_SELECTION
@ -380,7 +411,7 @@ void ObjectManipulation::update_position_values()
#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM #endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM
} }
void ObjectManipulation::update_position_values(const Vec3d& position) void ObjectManipulation::update_position_value(const Vec3d& position)
{ {
m_og->set_value("position_x", int(position(0))); m_og->set_value("position_x", int(position(0)));
m_og->set_value("position_y", int(position(1))); m_og->set_value("position_y", int(position(1)));

View File

@ -50,12 +50,15 @@ public:
#if ENABLE_EXTENDED_SELECTION #if ENABLE_EXTENDED_SELECTION
void update_settings_value(const GLCanvas3D::Selection& selection); void update_settings_value(const GLCanvas3D::Selection& selection);
void reset_settings_value(); void reset_settings_value();
void reset_position_value();
void reset_rotation_value();
void reset_scale_value();
#endif // ENABLE_EXTENDED_SELECTION #endif // ENABLE_EXTENDED_SELECTION
void update_values(); void update_values();
// update position values displacements or "gizmos" // update position values displacements or "gizmos"
void update_position_values(); void update_position_values();
void update_position_values(const Vec3d& position); void update_position_value(const Vec3d& position);
// update scale values after scale unit changing or "gizmos" // update scale values after scale unit changing or "gizmos"
void update_scale_values(); void update_scale_values();
#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM