Implemented Copy/Paste for Layers.

+ improved selection (in respect to the Layers)
This commit is contained in:
YuSanka 2019-06-10 15:22:09 +02:00
parent 2fa87044be
commit 2b6e5a0a70
3 changed files with 120 additions and 47 deletions

View file

@ -581,6 +581,56 @@ void ObjectList::selection_changed()
part_selection_changed(); part_selection_changed();
} }
void ObjectList::fill_layer_config_ranges_cache()
{
wxDataViewItemArray sel_layers;
GetSelections(sel_layers);
const int obj_idx = m_objects_model->GetObjectIdByItem(sel_layers[0]);
if (obj_idx < 0 || (int)m_objects->size() <= obj_idx)
return;
const t_layer_config_ranges& ranges = object(obj_idx)->layer_config_ranges;
m_layer_config_ranges_cache.clear();
for (const auto layer_item : sel_layers)
if (m_objects_model->GetItemType(layer_item) & itLayer) {
auto range = m_objects_model->GetLayerRangeByItem(layer_item);
auto it = ranges.find(range);
if (it != ranges.end())
m_layer_config_ranges_cache[it->first] = it->second;
}
}
void ObjectList::paste_layers_into_list()
{
const int obj_idx = m_objects_model->GetObjectIdByItem(GetSelection());
if (obj_idx < 0 || (int)m_objects->size() <= obj_idx ||
m_layer_config_ranges_cache.empty() || printer_technology() == ptSLA)
return;
const wxDataViewItem object_item = m_objects_model->GetItemById(obj_idx);
wxDataViewItem layers_item = m_objects_model->GetLayerRootItem(object_item);
if (layers_item)
m_objects_model->Delete(layers_item);
t_layer_config_ranges& ranges = object(obj_idx)->layer_config_ranges;
// and create Layer item(s) according to the layer_config_ranges
for (const auto range : m_layer_config_ranges_cache)
ranges.emplace(range);
layers_item = add_layer_root_item(object_item);
changed_object(obj_idx);
select_item(layers_item);
#ifndef __WXOSX__
selection_changed();
#endif //no __WXOSX__
}
void ObjectList::paste_volumes_into_list(int obj_idx, const ModelVolumePtrs& volumes) void ObjectList::paste_volumes_into_list(int obj_idx, const ModelVolumePtrs& volumes)
{ {
if ((obj_idx < 0) || ((int)m_objects->size() <= obj_idx)) if ((obj_idx < 0) || ((int)m_objects->size() <= obj_idx))
@ -737,10 +787,18 @@ void ObjectList::key_event(wxKeyEvent& event)
} }
else if (wxGetKeyState(wxKeyCode('A')) && wxGetKeyState(WXK_CONTROL/*WXK_SHIFT*/)) else if (wxGetKeyState(wxKeyCode('A')) && wxGetKeyState(WXK_CONTROL/*WXK_SHIFT*/))
select_item_all_children(); select_item_all_children();
else if (wxGetKeyState(wxKeyCode('C')) && wxGetKeyState(WXK_CONTROL)) else if (wxGetKeyState(wxKeyCode('C')) && wxGetKeyState(WXK_CONTROL)) {
wxPostEvent((wxEvtHandler*)wxGetApp().plater()->canvas3D()->get_wxglcanvas(), SimpleEvent(EVT_GLTOOLBAR_COPY)); if (m_selection_mode & smLayer)
else if (wxGetKeyState(wxKeyCode('V')) && wxGetKeyState(WXK_CONTROL)) fill_layer_config_ranges_cache();
wxPostEvent((wxEvtHandler*)wxGetApp().plater()->canvas3D()->get_wxglcanvas(), SimpleEvent(EVT_GLTOOLBAR_PASTE)); else
wxPostEvent((wxEvtHandler*)wxGetApp().plater()->canvas3D()->get_wxglcanvas(), SimpleEvent(EVT_GLTOOLBAR_COPY));
}
else if (wxGetKeyState(wxKeyCode('V')) && wxGetKeyState(WXK_CONTROL)) {
if (!m_layer_config_ranges_cache.empty())
paste_layers_into_list();
else
wxPostEvent((wxEvtHandler*)wxGetApp().plater()->canvas3D()->get_wxglcanvas(), SimpleEvent(EVT_GLTOOLBAR_PASTE));
}
else else
event.Skip(); event.Skip();
} }
@ -2104,6 +2162,9 @@ void ObjectList::add_object_to_list(size_t obj_idx)
Expand(item); Expand(item);
} }
// Add layers if it has
add_layer_root_item(item);
#ifndef __WXOSX__ #ifndef __WXOSX__
selection_changed(); selection_changed();
#endif //__WXMSW__ #endif //__WXMSW__
@ -2568,22 +2629,18 @@ void ObjectList::update_selections_on_canvas()
auto add_to_selection = [this](const wxDataViewItem& item, Selection& selection, int instance_idx, bool as_single_selection) auto add_to_selection = [this](const wxDataViewItem& item, Selection& selection, int instance_idx, bool as_single_selection)
{ {
const ItemType& type = m_objects_model->GetItemType(item); const ItemType& type = m_objects_model->GetItemType(item);
if ( type == itLayerRoot || m_objects_model->GetParent(item) == wxDataViewItem(0) ) { const int obj_idx = m_objects_model->GetObjectIdByItem(item);
wxDataViewItem obj_item = type == itLayerRoot ? m_objects_model->GetParent(item) : item;
selection.add_object(m_objects_model->GetIdByItem(obj_item), as_single_selection);
return;
}
if (type == itVolume) { if (type == itVolume) {
const int obj_idx = m_objects_model->GetIdByItem(m_objects_model->GetParent(item));
const int vol_idx = m_objects_model->GetVolumeIdByItem(item); const int vol_idx = m_objects_model->GetVolumeIdByItem(item);
selection.add_volume(obj_idx, vol_idx, std::max(instance_idx, 0), as_single_selection); selection.add_volume(obj_idx, vol_idx, std::max(instance_idx, 0), as_single_selection);
} }
else if (type == itInstance) { else if (type == itInstance) {
const int obj_idx = m_objects_model->GetIdByItem(m_objects_model->GetTopParent(item));
const int inst_idx = m_objects_model->GetInstanceIdByItem(item); const int inst_idx = m_objects_model->GetInstanceIdByItem(item);
selection.add_instance(obj_idx, inst_idx, as_single_selection); selection.add_instance(obj_idx, inst_idx, as_single_selection);
} }
else
selection.add_object(obj_idx, as_single_selection);
}; };
// stores current instance idx before to clear the selection // stores current instance idx before to clear the selection
@ -2654,11 +2711,13 @@ void ObjectList::select_item_all_children()
} }
else { else {
const auto item = GetSelection(); const auto item = GetSelection();
// Some volume(instance) is selected => select all volumes(instances) inside the current object const ItemType item_type = m_objects_model->GetItemType(item);
if (m_objects_model->GetItemType(item) & (itVolume | itInstance)) // Some volume/layer/instance is selected => select all volumes/layers/instances inside the current object
if (item_type & (itVolume | itInstance | itLayer))
m_objects_model->GetChildren(m_objects_model->GetParent(item), sels); m_objects_model->GetChildren(m_objects_model->GetParent(item), sels);
m_selection_mode = m_objects_model->GetItemType(item)&itVolume ? smVolume : smInstance; m_selection_mode = item_type&itVolume ? smVolume :
item_type&itLayer ? smLayer : smInstance;
} }
SetSelections(sels); SetSelections(sels);
@ -2677,8 +2736,9 @@ void ObjectList::update_selection_mode()
} }
const ItemType type = m_objects_model->GetItemType(GetSelection()); const ItemType type = m_objects_model->GetItemType(GetSelection());
m_selection_mode = type&itSettings ? smUndef : m_selection_mode = type & itSettings ? smUndef :
type&itVolume ? smVolume : smInstance; type & itLayer ? smLayer :
type & itVolume ? smVolume : smInstance;
} }
// check last selected item. If is it possible to select it // check last selected item. If is it possible to select it
@ -2689,33 +2749,37 @@ bool ObjectList::check_last_selection(wxString& msg_str)
const bool is_shift_pressed = wxGetKeyState(WXK_SHIFT); const bool is_shift_pressed = wxGetKeyState(WXK_SHIFT);
/* We can't mix Parts and Objects/Instances. /* We can't mix Volumes, Layers and Objects/Instances.
* So, show information about it * So, show information about it
*/ */
const ItemType type = m_objects_model->GetItemType(m_last_selected_item); const ItemType type = m_objects_model->GetItemType(m_last_selected_item);
// check a case of a selection of the Parts from different Objects // check a case of a selection of the same type items from different Objects
bool impossible_multipart_selection = false; auto impossible_multi_selection = [type, this](const ItemType item_type, const SELECTION_MODE selection_mode) {
if (type & itVolume && m_selection_mode == smVolume) if (!(type & item_type && m_selection_mode & selection_mode))
{ return false;
wxDataViewItemArray sels; wxDataViewItemArray sels;
GetSelections(sels); GetSelections(sels);
for (const auto& sel: sels) for (const auto& sel : sels)
if (sel != m_last_selected_item && if (sel != m_last_selected_item &&
m_objects_model->GetParent(sel) != m_objects_model->GetParent(m_last_selected_item)) m_objects_model->GetTopParent(sel) != m_objects_model->GetTopParent(m_last_selected_item))
{ return true;
impossible_multipart_selection = true;
break;
}
}
if (impossible_multipart_selection || return false;
};
if (impossible_multi_selection(itVolume, smVolume) ||
impossible_multi_selection(itLayer, smLayer ) ||
type & itSettings || type & itSettings ||
type & itVolume && m_selection_mode == smInstance || type & itVolume && !(m_selection_mode & smVolume ) ||
!(type & itVolume) && m_selection_mode == smVolume) type & itLayer && !(m_selection_mode & smLayer ) ||
type & itInstance && !(m_selection_mode & smInstance)
)
{ {
// Inform user why selection isn't complited // Inform user why selection isn't complited
const wxString item_type = m_selection_mode == smInstance ? _(L("Object or Instance")) : _(L("Part")); const wxString item_type = m_selection_mode & smInstance ? _(L("Object or Instance")) :
m_selection_mode & smVolume ? _(L("Part")) : _(L("Layer"));
msg_str = wxString::Format( _(L("Unsupported selection")) + "\n\n" + msg_str = wxString::Format( _(L("Unsupported selection")) + "\n\n" +
_(L("You started your selection with %s Item.")) + "\n" + _(L("You started your selection with %s Item.")) + "\n" +
@ -2752,7 +2816,7 @@ void ObjectList::fix_multiselection_conflicts()
wxDataViewItemArray sels; wxDataViewItemArray sels;
GetSelections(sels); GetSelections(sels);
if (m_selection_mode == smVolume) if (m_selection_mode & (smVolume|smLayer))
{ {
// identify correct parent of the initial selected item // identify correct parent of the initial selected item
const wxDataViewItem& parent = m_objects_model->GetParent(m_last_selected_item == sels.front() ? sels.back() : sels.front()); const wxDataViewItem& parent = m_objects_model->GetParent(m_last_selected_item == sels.front() ? sels.back() : sels.front());
@ -2761,8 +2825,10 @@ void ObjectList::fix_multiselection_conflicts()
wxDataViewItemArray children; // selected volumes from current parent wxDataViewItemArray children; // selected volumes from current parent
m_objects_model->GetChildren(parent, children); m_objects_model->GetChildren(parent, children);
const ItemType item_type = m_selection_mode & smVolume ? itVolume : itLayer;
for (const auto child : children) for (const auto child : children)
if (IsSelected(child) && m_objects_model->GetItemType(child)&itVolume) if (IsSelected(child) && m_objects_model->GetItemType(child) & item_type)
sels.Add(child); sels.Add(child);
// If some part is selected, unselect all items except of selected parts of the current object // If some part is selected, unselect all items except of selected parts of the current object
@ -2928,7 +2994,7 @@ void ObjectList::update_settings_items()
} }
// Update settings item for item had it // Update settings item for item had it
void ObjectList::update_settings_item_for_item(wxDataViewItem item, wxDataViewItemArray& selections) void ObjectList::update_settings_item_and_selection(wxDataViewItem item, wxDataViewItemArray& selections)
{ {
const wxDataViewItem& settings_item = m_objects_model->GetSettingsItem(item); const wxDataViewItem& settings_item = m_objects_model->GetSettingsItem(item);
select_item(settings_item ? settings_item : m_objects_model->AddSettingsChild(item)); select_item(settings_item ? settings_item : m_objects_model->AddSettingsChild(item));
@ -2956,7 +3022,7 @@ void ObjectList::update_object_list_by_printer_technology()
for (auto& object_item : object_items) { for (auto& object_item : object_items) {
// Update Settings Item for object // Update Settings Item for object
update_settings_item_for_item(object_item, sel); update_settings_item_and_selection(object_item, sel);
// Update settings for Volumes // Update settings for Volumes
wxDataViewItemArray all_object_subitems; wxDataViewItemArray all_object_subitems;
@ -2964,7 +3030,7 @@ void ObjectList::update_object_list_by_printer_technology()
for (auto item : all_object_subitems) for (auto item : all_object_subitems)
if (m_objects_model->GetItemType(item) & itVolume) if (m_objects_model->GetItemType(item) & itVolume)
// update settings for volume // update settings for volume
update_settings_item_for_item(item, sel); update_settings_item_and_selection(item, sel);
// Update Layers Items // Update Layers Items
wxDataViewItem layers_item = m_objects_model->GetLayerRootItem(object_item); wxDataViewItem layers_item = m_objects_model->GetLayerRootItem(object_item);
@ -2999,7 +3065,7 @@ void ObjectList::update_object_list_by_printer_technology()
for (auto item : all_obj_layers) for (auto item : all_obj_layers)
// update settings for layer // update settings for layer
update_settings_item_for_item(item, sel); update_settings_item_and_selection(item, sel);
} }
} }

View file

@ -33,8 +33,9 @@ typedef std::map< std::string, std::vector< std::pair<std::string, std::string>
typedef std::vector<ModelVolume*> ModelVolumePtrs; typedef std::vector<ModelVolume*> ModelVolumePtrs;
typedef double coordf_t; typedef double coordf_t;
typedef std::pair<coordf_t, coordf_t> t_layer_height_range; typedef std::pair<coordf_t, coordf_t> t_layer_height_range;
typedef std::map<t_layer_height_range, DynamicPrintConfig> t_layer_config_ranges;
namespace GUI { namespace GUI {
@ -67,9 +68,10 @@ class ObjectList : public wxDataViewCtrl
{ {
enum SELECTION_MODE enum SELECTION_MODE
{ {
smUndef, smUndef = 0,
smVolume, smVolume = 1,
smInstance smInstance = 2,
smLayer = 4
} m_selection_mode {smUndef}; } m_selection_mode {smUndef};
struct dragged_item_data struct dragged_item_data
@ -130,7 +132,9 @@ class ObjectList : public wxDataViewCtrl
DynamicPrintConfig *m_config {nullptr}; DynamicPrintConfig *m_config {nullptr};
std::vector<ModelObject*> *m_objects{ nullptr }; std::vector<ModelObject*> *m_objects{ nullptr };
std::vector<wxBitmap*> m_bmp_vector; std::vector<wxBitmap*> m_bmp_vector;
t_layer_config_ranges m_layer_config_ranges_cache;
int m_selected_object_id = -1; int m_selected_object_id = -1;
bool m_prevent_list_events = false; // We use this flag to avoid circular event handling Select() bool m_prevent_list_events = false; // We use this flag to avoid circular event handling Select()
@ -308,7 +312,7 @@ public:
void last_volume_is_deleted(const int obj_idx); void last_volume_is_deleted(const int obj_idx);
bool has_multi_part_objects(); bool has_multi_part_objects();
void update_settings_items(); void update_settings_items();
void update_settings_item_for_item(wxDataViewItem item, wxDataViewItemArray& selections); void update_settings_item_and_selection(wxDataViewItem item, wxDataViewItemArray& selections);
void update_object_list_by_printer_technology(); void update_object_list_by_printer_technology();
void update_object_menu(); void update_object_menu();
@ -319,6 +323,8 @@ public:
void fix_through_netfabb(); void fix_through_netfabb();
void update_item_error_icon(const int obj_idx, int vol_idx) const ; void update_item_error_icon(const int obj_idx, int vol_idx) const ;
void fill_layer_config_ranges_cache();
void paste_layers_into_list();
void paste_volumes_into_list(int obj_idx, const ModelVolumePtrs& volumes); void paste_volumes_into_list(int obj_idx, const ModelVolumePtrs& volumes);
void paste_objects_into_list(const std::vector<size_t>& object_idxs); void paste_objects_into_list(const std::vector<size_t>& object_idxs);

View file

@ -1174,7 +1174,8 @@ int ObjectDataViewModel::GetItemIdByLayerRange(const int obj_idx, const t_layer
int ObjectDataViewModel::GetIdByItem(const wxDataViewItem& item) const int ObjectDataViewModel::GetIdByItem(const wxDataViewItem& item) const
{ {
wxASSERT(item.IsOk()); if(!item.IsOk())
return -1;
ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID(); ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID();
auto it = find(m_objects.begin(), m_objects.end(), node); auto it = find(m_objects.begin(), m_objects.end(), node);