Improved Selection from ObjectList side

This commit is contained in:
YuSanka 2019-03-29 14:36:09 +01:00
parent a71f05cdc0
commit 8631cb006b
6 changed files with 117 additions and 22 deletions

View File

@ -1639,16 +1639,20 @@ void ObjectList::part_selection_changed()
bool update_and_show_manipulations = false; bool update_and_show_manipulations = false;
bool update_and_show_settings = false; bool update_and_show_settings = false;
if (multiple_selection()) { const auto item = GetSelection();
if ( multiple_selection() || item && m_objects_model->GetItemType(item) == itInstanceRoot )
{
og_name = _(L("Group manipulation")); og_name = _(L("Group manipulation"));
update_and_show_manipulations = true;
const Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
// don't show manipulation panel for case of all Object's parts selection
update_and_show_manipulations = !selection.is_single_full_instance();
} }
else else
{ {
const auto item = GetSelection();
if (item) if (item)
{ {
bool is_part = false;
if (m_objects_model->GetParent(item) == wxDataViewItem(0)) { if (m_objects_model->GetParent(item) == wxDataViewItem(0)) {
obj_idx = m_objects_model->GetIdByItem(item); obj_idx = m_objects_model->GetIdByItem(item);
og_name = _(L("Object manipulation")); og_name = _(L("Object manipulation"));
@ -1666,7 +1670,6 @@ void ObjectList::part_selection_changed()
} }
else { else {
og_name = _(L("Part Settings to modify")); og_name = _(L("Part Settings to modify"));
is_part = true;
auto main_parent = m_objects_model->GetParent(parent); auto main_parent = m_objects_model->GetParent(parent);
obj_idx = m_objects_model->GetIdByItem(main_parent); obj_idx = m_objects_model->GetIdByItem(main_parent);
const auto volume_id = m_objects_model->GetVolumeIdByItem(parent); const auto volume_id = m_objects_model->GetVolumeIdByItem(parent);
@ -1676,7 +1679,6 @@ void ObjectList::part_selection_changed()
} }
else if (m_objects_model->GetItemType(item) == itVolume) { else if (m_objects_model->GetItemType(item) == itVolume) {
og_name = _(L("Part manipulation")); og_name = _(L("Part manipulation"));
is_part = true;
const auto volume_id = m_objects_model->GetVolumeIdByItem(item); const auto volume_id = m_objects_model->GetVolumeIdByItem(item);
m_config = &(*m_objects)[obj_idx]->volumes[volume_id]->config; m_config = &(*m_objects)[obj_idx]->volumes[volume_id]->config;
update_and_show_manipulations = true; update_and_show_manipulations = true;
@ -1924,6 +1926,15 @@ bool ObjectList::multiple_selection() const
return GetSelectedItemsCount() > 1; return GetSelectedItemsCount() > 1;
} }
bool ObjectList::is_selected(const ItemType type) const
{
const wxDataViewItem& item = GetSelection();
if (item)
return m_objects_model->GetItemType(item) == type;
return false;
}
void ObjectList::update_selections() void ObjectList::update_selections()
{ {
const Selection& selection = wxGetApp().plater()->canvas3D()->get_selection(); const Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
@ -1942,25 +1953,64 @@ void ObjectList::update_selections()
return; return;
} }
} }
// if (selection.is_single_full_object() && selection.get_instance_idx() != -1)
if (selection.is_single_full_object()) // {
// sels.Add(m_objects_model->GetItemById(selection.get_object_idx()));
// }
// else if (selection.is_single_volume() || selection.is_modifier() ||
// selection.is_multiple_volume() || selection.is_multiple_full_object())
// {
// for (auto idx : selection.get_volume_idxs()) {
// const auto gl_vol = selection.get_volume(idx);
// if (selection.is_multiple_full_object())
// sels.Add(m_objects_model->GetItemById(gl_vol->object_idx()));
// else if (gl_vol->volume_idx() >= 0)
// // Only add GLVolumes with non-negative volume_ids. GLVolumes with negative volume ids
// // are not associated with ModelVolumes, but they are temporarily generated by the backend
// // (for example, SLA supports or SLA pad).
// sels.Add(m_objects_model->GetItemByVolumeId(gl_vol->object_idx(), gl_vol->volume_idx()));
// }
// }
else if (selection.is_single_full_object() || selection.is_multiple_full_object())
{ {
sels.Add(m_objects_model->GetItemById(selection.get_object_idx())); const Selection::ObjectIdxsToInstanceIdxsMap& objects_content = selection.get_content();
for (const auto& object : objects_content) {
if (object.second.size() == 1) // object with 1 instance
sels.Add(m_objects_model->GetItemById(object.first));
else if (object.second.size() > 1) // object with several instances
{
wxDataViewItemArray current_sels;
GetSelections(current_sels);
const wxDataViewItem frst_inst_item = m_objects_model->GetItemByInstanceId(object.first, 0);
bool root_is_selected = false;
for (const auto& item:current_sels)
if (item == m_objects_model->GetParent(frst_inst_item)) {
root_is_selected = true;
break;
}
if (root_is_selected)
continue;
const Selection::InstanceIdxsList& instances = object.second;
for (const auto& inst : instances)
sels.Add(m_objects_model->GetItemByInstanceId(object.first, inst));
}
}
} }
else if (selection.is_single_volume() || selection.is_modifier() || else if (selection.is_single_volume() || selection.is_modifier() || selection.is_multiple_volume())
selection.is_multiple_volume() || selection.is_multiple_full_object()) { {
for (auto idx : selection.get_volume_idxs()) { for (auto idx : selection.get_volume_idxs()) {
const auto gl_vol = selection.get_volume(idx); const auto gl_vol = selection.get_volume(idx);
if (selection.is_multiple_full_object()) if (gl_vol->volume_idx() >= 0)
sels.Add(m_objects_model->GetItemById(gl_vol->object_idx()));
else if (gl_vol->volume_idx() >= 0)
// Only add GLVolumes with non-negative volume_ids. GLVolumes with negative volume ids // Only add GLVolumes with non-negative volume_ids. GLVolumes with negative volume ids
// are not associated with ModelVolumes, but they are temporarily generated by the backend // are not associated with ModelVolumes, but they are temporarily generated by the backend
// (for example, SLA supports or SLA pad). // (for example, SLA supports or SLA pad).
sels.Add(m_objects_model->GetItemByVolumeId(gl_vol->object_idx(), gl_vol->volume_idx())); sels.Add(m_objects_model->GetItemByVolumeId(gl_vol->object_idx(), gl_vol->volume_idx()));
} }
} }
else if (selection.is_single_full_instance() || selection.is_multiple_full_instance()) { else if (selection.is_single_full_instance() || selection.is_multiple_full_instance())
{
for (auto idx : selection.get_instance_idxs()) { for (auto idx : selection.get_instance_idxs()) {
sels.Add(m_objects_model->GetItemByInstanceId(selection.get_object_idx(), idx)); sels.Add(m_objects_model->GetItemByInstanceId(selection.get_object_idx(), idx));
} }
@ -2137,11 +2187,25 @@ void ObjectList::fix_multiselection_conflicts()
wxDataViewItemArray sels; wxDataViewItemArray sels;
GetSelections(sels); GetSelections(sels);
for (auto item : sels) { for (const auto item : sels) {
if (m_objects_model->GetItemType(item) & (itSettings|itInstanceRoot)) if (!IsSelected(item)) // if this item is unselected now (from previous actions)
continue;
if (m_objects_model->GetItemType(item) & itSettings) {
Unselect(item); Unselect(item);
else if (m_objects_model->GetParent(item) != wxDataViewItem(0)) continue;
Unselect(m_objects_model->GetParent(item)); }
const wxDataViewItem& parent = m_objects_model->GetParent(item);
if (parent != wxDataViewItem(0) && IsSelected(parent))
Unselect(parent);
else
{
wxDataViewItemArray unsels;
m_objects_model->GetAllChildren(item, unsels);
for (const auto unsel_item : unsels)
Unselect(unsel_item);
}
} }
m_prevent_list_events = false; m_prevent_list_events = false;

View File

@ -251,6 +251,7 @@ public:
void init_objects(); void init_objects();
bool multiple_selection() const ; bool multiple_selection() const ;
bool is_selected(const ItemType type) const;
void update_selections(); void update_selections();
void update_selections_on_canvas(); void update_selections_on_canvas();
void select_item(const wxDataViewItem& item); void select_item(const wxDataViewItem& item);

View File

@ -161,6 +161,8 @@ void ObjectManipulation::update_settings_value(const Selection& selection)
m_new_move_label_string = L("Position"); m_new_move_label_string = L("Position");
m_new_rotate_label_string = L("Rotation"); m_new_rotate_label_string = L("Rotation");
m_new_scale_label_string = L("Scale factors"); m_new_scale_label_string = L("Scale factors");
ObjectList* obj_list = wxGetApp().obj_list();
if (selection.is_single_full_instance()) if (selection.is_single_full_instance())
{ {
// all volumes in the selection belongs to the same instance, any of them contains the needed instance data, so we take the first one // all volumes in the selection belongs to the same instance, any of them contains the needed instance data, so we take the first one
@ -187,7 +189,7 @@ void ObjectManipulation::update_settings_value(const Selection& selection)
m_new_enabled = true; m_new_enabled = true;
} }
else if (selection.is_single_full_object()) else if (selection.is_single_full_object() && obj_list->is_selected(itObject))
{ {
m_cache.instance.reset(); m_cache.instance.reset();
@ -212,7 +214,7 @@ void ObjectManipulation::update_settings_value(const Selection& selection)
m_new_size = (volume->get_volume_transformation().get_matrix(true, true) * volume->bounding_box.size()).cwiseAbs(); m_new_size = (volume->get_volume_transformation().get_matrix(true, true) * volume->bounding_box.size()).cwiseAbs();
m_new_enabled = true; m_new_enabled = true;
} }
else if (wxGetApp().obj_list()->multiple_selection()) else if (obj_list->multiple_selection() || obj_list->is_selected(itInstanceRoot))
{ {
reset_settings_value(); reset_settings_value();
m_new_move_label_string = L("Translate"); m_new_move_label_string = L("Translate");

View File

@ -133,10 +133,12 @@ private:
const Transform3d& get_instance_full_matrix() const { return m_instance.full_matrix; } const Transform3d& get_instance_full_matrix() const { return m_instance.full_matrix; }
}; };
public:
typedef std::map<unsigned int, VolumeCache> VolumesCache; typedef std::map<unsigned int, VolumeCache> VolumesCache;
typedef std::set<int> InstanceIdxsList; typedef std::set<int> InstanceIdxsList;
typedef std::map<int, InstanceIdxsList> ObjectIdxsToInstanceIdxsMap; typedef std::map<int, InstanceIdxsList> ObjectIdxsToInstanceIdxsMap;
private:
struct Cache struct Cache
{ {
// Cache of GLVolume derived transformation matrices, valid during mouse dragging. // Cache of GLVolume derived transformation matrices, valid during mouse dragging.

View File

@ -1238,6 +1238,32 @@ unsigned int PrusaObjectDataViewModel::GetChildren(const wxDataViewItem &parent,
return count; return count;
} }
void PrusaObjectDataViewModel::GetAllChildren(const wxDataViewItem &parent, wxDataViewItemArray &array) const
{
PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)parent.GetID();
if (!node) {
for (auto object : m_objects)
array.Add(wxDataViewItem((void*)object));
}
else if (node->GetChildCount() == 0)
return;
else {
const size_t count = node->GetChildren().GetCount();
for (size_t pos = 0; pos < count; pos++) {
PrusaObjectDataViewModelNode *child = node->GetChildren().Item(pos);
array.Add(wxDataViewItem((void*)child));
}
}
wxDataViewItemArray new_array = array;
for (const auto item : new_array)
{
wxDataViewItemArray children;
GetAllChildren(item, children);
WX_APPEND_ARRAY(array, children);
}
}
ItemType PrusaObjectDataViewModel::GetItemType(const wxDataViewItem &item) const ItemType PrusaObjectDataViewModel::GetItemType(const wxDataViewItem &item) const
{ {
if (!item.IsOk()) if (!item.IsOk())

View File

@ -511,7 +511,7 @@ public:
virtual bool IsContainer(const wxDataViewItem &item) const override; virtual bool IsContainer(const wxDataViewItem &item) const override;
virtual unsigned int GetChildren(const wxDataViewItem &parent, virtual unsigned int GetChildren(const wxDataViewItem &parent,
wxDataViewItemArray &array) const override; wxDataViewItemArray &array) const override;
void GetAllChildren(const wxDataViewItem &parent,wxDataViewItemArray &array) const;
// Is the container just a header or an item with all columns // Is the container just a header or an item with all columns
// In our case it is an item with all columns // In our case it is an item with all columns
virtual bool HasContainerColumns(const wxDataViewItem& WXUNUSED(item)) const override { return true; } virtual bool HasContainerColumns(const wxDataViewItem& WXUNUSED(item)) const override { return true; }