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();
}
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)
{
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*/))
select_item_all_children();
else if (wxGetKeyState(wxKeyCode('C')) && wxGetKeyState(WXK_CONTROL))
wxPostEvent((wxEvtHandler*)wxGetApp().plater()->canvas3D()->get_wxglcanvas(), SimpleEvent(EVT_GLTOOLBAR_COPY));
else if (wxGetKeyState(wxKeyCode('V')) && wxGetKeyState(WXK_CONTROL))
wxPostEvent((wxEvtHandler*)wxGetApp().plater()->canvas3D()->get_wxglcanvas(), SimpleEvent(EVT_GLTOOLBAR_PASTE));
else if (wxGetKeyState(wxKeyCode('C')) && wxGetKeyState(WXK_CONTROL)) {
if (m_selection_mode & smLayer)
fill_layer_config_ranges_cache();
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
event.Skip();
}
@ -2104,6 +2162,9 @@ void ObjectList::add_object_to_list(size_t obj_idx)
Expand(item);
}
// Add layers if it has
add_layer_root_item(item);
#ifndef __WXOSX__
selection_changed();
#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)
{
const ItemType& type = m_objects_model->GetItemType(item);
if ( type == itLayerRoot || m_objects_model->GetParent(item) == wxDataViewItem(0) ) {
wxDataViewItem obj_item = type == itLayerRoot ? m_objects_model->GetParent(item) : item;
selection.add_object(m_objects_model->GetIdByItem(obj_item), as_single_selection);
return;
}
const int obj_idx = m_objects_model->GetObjectIdByItem(item);
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);
selection.add_volume(obj_idx, vol_idx, std::max(instance_idx, 0), as_single_selection);
}
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);
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
@ -2654,11 +2711,13 @@ void ObjectList::select_item_all_children()
}
else {
const auto item = GetSelection();
// Some volume(instance) is selected => select all volumes(instances) inside the current object
if (m_objects_model->GetItemType(item) & (itVolume | itInstance))
const ItemType item_type = m_objects_model->GetItemType(item);
// 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_selection_mode = m_objects_model->GetItemType(item)&itVolume ? smVolume : smInstance;
m_selection_mode = item_type&itVolume ? smVolume :
item_type&itLayer ? smLayer : smInstance;
}
SetSelections(sels);
@ -2677,8 +2736,9 @@ void ObjectList::update_selection_mode()
}
const ItemType type = m_objects_model->GetItemType(GetSelection());
m_selection_mode = type&itSettings ? smUndef :
type&itVolume ? smVolume : smInstance;
m_selection_mode = type & itSettings ? smUndef :
type & itLayer ? smLayer :
type & itVolume ? smVolume : smInstance;
}
// 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);
/* We can't mix Parts and Objects/Instances.
/* We can't mix Volumes, Layers and Objects/Instances.
* So, show information about it
*/
const ItemType type = m_objects_model->GetItemType(m_last_selected_item);
// check a case of a selection of the Parts from different Objects
bool impossible_multipart_selection = false;
if (type & itVolume && m_selection_mode == smVolume)
{
// check a case of a selection of the same type items from different Objects
auto impossible_multi_selection = [type, this](const ItemType item_type, const SELECTION_MODE selection_mode) {
if (!(type & item_type && m_selection_mode & selection_mode))
return false;
wxDataViewItemArray sels;
GetSelections(sels);
for (const auto& sel: sels)
if (sel != m_last_selected_item &&
m_objects_model->GetParent(sel) != m_objects_model->GetParent(m_last_selected_item))
{
impossible_multipart_selection = true;
break;
}
}
for (const auto& sel : sels)
if (sel != m_last_selected_item &&
m_objects_model->GetTopParent(sel) != m_objects_model->GetTopParent(m_last_selected_item))
return true;
if (impossible_multipart_selection ||
return false;
};
if (impossible_multi_selection(itVolume, smVolume) ||
impossible_multi_selection(itLayer, smLayer ) ||
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
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" +
_(L("You started your selection with %s Item.")) + "\n" +
@ -2752,7 +2816,7 @@ void ObjectList::fix_multiselection_conflicts()
wxDataViewItemArray sels;
GetSelections(sels);
if (m_selection_mode == smVolume)
if (m_selection_mode & (smVolume|smLayer))
{
// 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());
@ -2761,8 +2825,10 @@ void ObjectList::fix_multiselection_conflicts()
wxDataViewItemArray children; // selected volumes from current parent
m_objects_model->GetChildren(parent, children);
const ItemType item_type = m_selection_mode & smVolume ? itVolume : itLayer;
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);
// 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
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);
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) {
// 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
wxDataViewItemArray all_object_subitems;
@ -2964,7 +3030,7 @@ void ObjectList::update_object_list_by_printer_technology()
for (auto item : all_object_subitems)
if (m_objects_model->GetItemType(item) & itVolume)
// update settings for volume
update_settings_item_for_item(item, sel);
update_settings_item_and_selection(item, sel);
// Update Layers Items
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)
// 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 double coordf_t;
typedef std::pair<coordf_t, coordf_t> t_layer_height_range;
typedef double coordf_t;
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 {
@ -67,9 +68,10 @@ class ObjectList : public wxDataViewCtrl
{
enum SELECTION_MODE
{
smUndef,
smVolume,
smInstance
smUndef = 0,
smVolume = 1,
smInstance = 2,
smLayer = 4
} m_selection_mode {smUndef};
struct dragged_item_data
@ -130,7 +132,9 @@ class ObjectList : public wxDataViewCtrl
DynamicPrintConfig *m_config {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;
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);
bool has_multi_part_objects();
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_menu();
@ -319,6 +323,8 @@ public:
void fix_through_netfabb();
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_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
{
wxASSERT(item.IsOk());
if(!item.IsOk())
return -1;
ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID();
auto it = find(m_objects.begin(), m_objects.end(), node);