Improved Selection from ObjectList side
This commit is contained in:
parent
a71f05cdc0
commit
8631cb006b
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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");
|
||||||
|
@ -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.
|
||||||
|
@ -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())
|
||||||
|
@ -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; }
|
||||||
|
Loading…
Reference in New Issue
Block a user