Implemented LayerItem for ObjectList
This commit is contained in:
parent
bf9740188a
commit
dd70dd6e10
7 changed files with 156 additions and 40 deletions
BIN
resources/icons/row.png
Normal file
BIN
resources/icons/row.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.9 KiB |
BIN
resources/icons/table.png
Normal file
BIN
resources/icons/table.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 465 B |
|
@ -1137,6 +1137,12 @@ wxMenuItem* ObjectList::append_menu_item_split(wxMenu* menu)
|
||||||
[this]() { return is_splittable(); }, wxGetApp().plater());
|
[this]() { return is_splittable(); }, wxGetApp().plater());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wxMenuItem* ObjectList::append_menu_item_layers_editing(wxMenu* menu)
|
||||||
|
{
|
||||||
|
return append_menu_item(menu, wxID_ANY, _(L("Edit Layers")), "",
|
||||||
|
[this](wxCommandEvent&) { layers_editing(); }, "table.png", menu);
|
||||||
|
}
|
||||||
|
|
||||||
wxMenuItem* ObjectList::append_menu_item_settings(wxMenu* menu_)
|
wxMenuItem* ObjectList::append_menu_item_settings(wxMenu* menu_)
|
||||||
{
|
{
|
||||||
MenuWithSeparators* menu = dynamic_cast<MenuWithSeparators*>(menu_);
|
MenuWithSeparators* menu = dynamic_cast<MenuWithSeparators*>(menu_);
|
||||||
|
@ -1301,7 +1307,11 @@ void ObjectList::create_object_popupmenu(wxMenu *menu)
|
||||||
append_menu_item_scale_selection_to_fit_print_volume(menu);
|
append_menu_item_scale_selection_to_fit_print_volume(menu);
|
||||||
|
|
||||||
// Split object to parts
|
// Split object to parts
|
||||||
m_menu_item_split = append_menu_item_split(menu);
|
append_menu_item_split(menu);
|
||||||
|
menu->AppendSeparator();
|
||||||
|
|
||||||
|
// Layers Editing for object
|
||||||
|
append_menu_item_layers_editing(menu);
|
||||||
menu->AppendSeparator();
|
menu->AppendSeparator();
|
||||||
|
|
||||||
// rest of a object_menu will be added later in:
|
// rest of a object_menu will be added later in:
|
||||||
|
@ -1330,7 +1340,7 @@ void ObjectList::create_part_popupmenu(wxMenu *menu)
|
||||||
append_menu_item_fix_through_netfabb(menu);
|
append_menu_item_fix_through_netfabb(menu);
|
||||||
append_menu_item_export_stl(menu);
|
append_menu_item_export_stl(menu);
|
||||||
|
|
||||||
m_menu_item_split_part = append_menu_item_split(menu);
|
append_menu_item_split(menu);
|
||||||
|
|
||||||
// Append change part type
|
// Append change part type
|
||||||
menu->AppendSeparator();
|
menu->AppendSeparator();
|
||||||
|
@ -1774,6 +1784,20 @@ void ObjectList::split()
|
||||||
changed_object(obj_idx);
|
changed_object(obj_idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ObjectList::layers_editing()
|
||||||
|
{
|
||||||
|
const auto item = GetSelection();
|
||||||
|
const int obj_idx = get_selected_obj_idx();
|
||||||
|
if (!item || obj_idx < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
wxDataViewItem layers_item = m_objects_model->GetItemByType(item, itLayerRoot);
|
||||||
|
if (!layers_item.IsOk())
|
||||||
|
layers_item = m_objects_model->AddLayersRoot(item);
|
||||||
|
|
||||||
|
select_item(layers_item);
|
||||||
|
}
|
||||||
|
|
||||||
bool ObjectList::get_volume_by_item(const wxDataViewItem& item, ModelVolume*& volume)
|
bool ObjectList::get_volume_by_item(const wxDataViewItem& item, ModelVolume*& volume)
|
||||||
{
|
{
|
||||||
auto obj_idx = get_selected_obj_idx();
|
auto obj_idx = get_selected_obj_idx();
|
||||||
|
|
|
@ -119,8 +119,6 @@ class ObjectList : public wxDataViewCtrl
|
||||||
MenuWithSeparators m_menu_part;
|
MenuWithSeparators m_menu_part;
|
||||||
MenuWithSeparators m_menu_sla_object;
|
MenuWithSeparators m_menu_sla_object;
|
||||||
MenuWithSeparators m_menu_instance;
|
MenuWithSeparators m_menu_instance;
|
||||||
wxMenuItem* m_menu_item_split { nullptr };
|
|
||||||
wxMenuItem* m_menu_item_split_part { nullptr };
|
|
||||||
wxMenuItem* m_menu_item_settings { nullptr };
|
wxMenuItem* m_menu_item_settings { nullptr };
|
||||||
wxMenuItem* m_menu_item_split_instances { nullptr };
|
wxMenuItem* m_menu_item_split_instances { nullptr };
|
||||||
|
|
||||||
|
@ -199,6 +197,7 @@ public:
|
||||||
wxMenu* append_submenu_add_generic(wxMenu* menu, const ModelVolumeType type);
|
wxMenu* append_submenu_add_generic(wxMenu* menu, const ModelVolumeType type);
|
||||||
void append_menu_items_add_volume(wxMenu* menu);
|
void append_menu_items_add_volume(wxMenu* menu);
|
||||||
wxMenuItem* append_menu_item_split(wxMenu* menu);
|
wxMenuItem* append_menu_item_split(wxMenu* menu);
|
||||||
|
wxMenuItem* append_menu_item_layers_editing(wxMenu* menu);
|
||||||
wxMenuItem* append_menu_item_settings(wxMenu* menu);
|
wxMenuItem* append_menu_item_settings(wxMenu* menu);
|
||||||
wxMenuItem* append_menu_item_change_type(wxMenu* menu);
|
wxMenuItem* append_menu_item_change_type(wxMenu* menu);
|
||||||
wxMenuItem* append_menu_item_instance_to_object(wxMenu* menu, wxWindow* parent);
|
wxMenuItem* append_menu_item_instance_to_object(wxMenu* menu, wxWindow* parent);
|
||||||
|
@ -226,6 +225,7 @@ public:
|
||||||
void del_instances_from_object(const int obj_idx);
|
void del_instances_from_object(const int obj_idx);
|
||||||
bool del_subobject_from_object(const int obj_idx, const int idx, const int type);
|
bool del_subobject_from_object(const int obj_idx, const int idx, const int type);
|
||||||
void split();
|
void split();
|
||||||
|
void layers_editing();
|
||||||
bool get_volume_by_item(const wxDataViewItem& item, ModelVolume*& volume);
|
bool get_volume_by_item(const wxDataViewItem& item, ModelVolume*& volume);
|
||||||
bool is_splittable();
|
bool is_splittable();
|
||||||
bool selected_instances_of_same_object();
|
bool selected_instances_of_same_object();
|
||||||
|
|
|
@ -3066,6 +3066,10 @@ bool Plater::priv::complit_init_object_menu()
|
||||||
[this]() { return can_split() && wxGetApp().get_mode() > comSimple; }, q);
|
[this]() { return can_split() && wxGetApp().get_mode() > comSimple; }, q);
|
||||||
object_menu.AppendSeparator();
|
object_menu.AppendSeparator();
|
||||||
|
|
||||||
|
// Layers Editing for object
|
||||||
|
sidebar->obj_list()->append_menu_item_layers_editing(&object_menu);
|
||||||
|
object_menu.AppendSeparator();
|
||||||
|
|
||||||
// "Add (volumes)" popupmenu will be added later in append_menu_items_add_volume()
|
// "Add (volumes)" popupmenu will be added later in append_menu_items_add_volume()
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -437,27 +437,44 @@ ObjectDataViewModelNode::ObjectDataViewModelNode(ObjectDataViewModelNode* parent
|
||||||
m_type(type),
|
m_type(type),
|
||||||
m_extruder(wxEmptyString)
|
m_extruder(wxEmptyString)
|
||||||
{
|
{
|
||||||
if (type == itSettings) {
|
if (type == itSettings)
|
||||||
m_name = "Settings to modified";
|
m_name = "Settings to modified";
|
||||||
}
|
else if (type == itInstanceRoot)
|
||||||
else if (type == itInstanceRoot) {
|
|
||||||
m_name = _(L("Instances"));
|
m_name = _(L("Instances"));
|
||||||
#ifdef __WXGTK__
|
else if (type == itInstance)
|
||||||
m_container = true;
|
{
|
||||||
#endif //__WXGTK__
|
|
||||||
}
|
|
||||||
else if (type == itInstance) {
|
|
||||||
m_idx = parent->GetChildCount();
|
m_idx = parent->GetChildCount();
|
||||||
m_name = wxString::Format(_(L("Instance %d")), m_idx + 1);
|
m_name = wxString::Format(_(L("Instance %d")), m_idx + 1);
|
||||||
|
|
||||||
set_action_icon();
|
set_action_icon();
|
||||||
}
|
}
|
||||||
|
else if (type == itLayerRoot)
|
||||||
|
{
|
||||||
|
m_bmp = create_scaled_bitmap(nullptr, "table.png"); // FIXME: pass window ptr
|
||||||
|
m_name = _(L("Layers"));
|
||||||
|
}
|
||||||
|
else if (type == itLayer)
|
||||||
|
{
|
||||||
|
m_idx = parent->GetChildCount();
|
||||||
|
m_name = wxString::Format(_(L("Layer %d")), m_idx + 1);
|
||||||
|
m_bmp = create_scaled_bitmap(nullptr, "row.png"); // FIXME: pass window ptr
|
||||||
|
|
||||||
|
set_action_icon();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __WXGTK__
|
||||||
|
// it's necessary on GTK because of control have to know if this item will be container
|
||||||
|
// in another case you couldn't to add subitem for this item
|
||||||
|
// it will be produce "segmentation fault"
|
||||||
|
if (type & (itInstanceRoot | itLayerRoot | itLayer))
|
||||||
|
m_container = true;
|
||||||
|
#endif //__WXGTK__
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjectDataViewModelNode::set_action_icon()
|
void ObjectDataViewModelNode::set_action_icon()
|
||||||
{
|
{
|
||||||
m_action_icon_name = m_type == itObject ? "advanced_plus" :
|
m_action_icon_name = m_type & itObject ? "advanced_plus" :
|
||||||
m_type == itVolume ? "cog" : "set_separate_obj";
|
m_type & (itVolume | itLayer) ? "cog" : /*m_type & itInstance*/ "set_separate_obj";
|
||||||
m_action_icon = create_scaled_bitmap(nullptr, m_action_icon_name); // FIXME: pass window ptr
|
m_action_icon = create_scaled_bitmap(nullptr, m_action_icon_name); // FIXME: pass window ptr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -619,36 +636,62 @@ wxDataViewItem ObjectDataViewModel::AddSettingsChild(const wxDataViewItem &paren
|
||||||
return child;
|
return child;
|
||||||
}
|
}
|
||||||
|
|
||||||
int get_istances_root_idx(ObjectDataViewModelNode *parent_node)
|
static int get_root_idx(ObjectDataViewModelNode *parent_node, const ItemType root_type)
|
||||||
{
|
{
|
||||||
// because of istance_root is a last item of the object
|
// because of istance_root and layers_root are at the end of the list, so
|
||||||
const int inst_root_idx = parent_node->GetChildCount()-1;
|
// start locking from the end
|
||||||
|
for (int root_idx = parent_node->GetChildCount() - 1; root_idx >= 0; root_idx--)
|
||||||
if (inst_root_idx < 0 || parent_node->GetNthChild(inst_root_idx)->GetType() == itInstanceRoot)
|
{
|
||||||
return inst_root_idx;
|
// if there is SettingsItem or VolumeItem, then RootItems don't exist in current ObjectItem
|
||||||
|
if (parent_node->GetNthChild(root_idx)->GetType() & (itSettings | itVolume))
|
||||||
|
break;
|
||||||
|
if (parent_node->GetNthChild(root_idx)->GetType() & root_type)
|
||||||
|
return root_idx;
|
||||||
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* return values:
|
||||||
|
* true => root_node is created and added to the parent_root
|
||||||
|
* false => root node alredy exists
|
||||||
|
*/
|
||||||
|
static bool append_root_node(ObjectDataViewModelNode *parent_node,
|
||||||
|
ObjectDataViewModelNode **root_node,
|
||||||
|
const ItemType root_type)
|
||||||
|
{
|
||||||
|
const int inst_root_id = get_root_idx(parent_node, root_type);
|
||||||
|
|
||||||
|
*root_node = inst_root_id < 0 ?
|
||||||
|
new ObjectDataViewModelNode(parent_node, root_type) :
|
||||||
|
parent_node->GetNthChild(inst_root_id);
|
||||||
|
|
||||||
|
if (inst_root_id < 0) {
|
||||||
|
if ((root_type&itInstanceRoot) ||
|
||||||
|
(root_type&itLayerRoot) && get_root_idx(parent_node, itInstanceRoot)<0)
|
||||||
|
parent_node->Append(*root_node);
|
||||||
|
else if (root_type&itLayerRoot)
|
||||||
|
parent_node->Insert(*root_node, unsigned int(get_root_idx(parent_node, itInstanceRoot)));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
wxDataViewItem ObjectDataViewModel::AddInstanceChild(const wxDataViewItem &parent_item, size_t num)
|
wxDataViewItem ObjectDataViewModel::AddInstanceChild(const wxDataViewItem &parent_item, size_t num)
|
||||||
{
|
{
|
||||||
ObjectDataViewModelNode *parent_node = (ObjectDataViewModelNode*)parent_item.GetID();
|
ObjectDataViewModelNode *parent_node = (ObjectDataViewModelNode*)parent_item.GetID();
|
||||||
if (!parent_node) return wxDataViewItem(0);
|
if (!parent_node) return wxDataViewItem(0);
|
||||||
|
|
||||||
// Check and create/get instances root node
|
// get InstanceRoot node
|
||||||
const int inst_root_id = get_istances_root_idx(parent_node);
|
ObjectDataViewModelNode *inst_root_node { nullptr };
|
||||||
|
|
||||||
ObjectDataViewModelNode *inst_root_node = inst_root_id < 0 ?
|
const bool appended = append_root_node(parent_node, &inst_root_node, itInstanceRoot);
|
||||||
new ObjectDataViewModelNode(parent_node, itInstanceRoot) :
|
|
||||||
parent_node->GetNthChild(inst_root_id);
|
|
||||||
const wxDataViewItem inst_root_item((void*)inst_root_node);
|
const wxDataViewItem inst_root_item((void*)inst_root_node);
|
||||||
|
if (!inst_root_node) return wxDataViewItem(0);
|
||||||
|
|
||||||
if (inst_root_id < 0) {
|
if (appended)
|
||||||
parent_node->Append(inst_root_node);
|
ItemAdded(parent_item, inst_root_item);// notify control
|
||||||
// notify control
|
|
||||||
ItemAdded(parent_item, inst_root_item);
|
|
||||||
// if (num == 1) num++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add instance nodes
|
// Add instance nodes
|
||||||
ObjectDataViewModelNode *instance_node = nullptr;
|
ObjectDataViewModelNode *instance_node = nullptr;
|
||||||
|
@ -665,6 +708,47 @@ wxDataViewItem ObjectDataViewModel::AddInstanceChild(const wxDataViewItem &paren
|
||||||
return wxDataViewItem((void*)instance_node);
|
return wxDataViewItem((void*)instance_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wxDataViewItem ObjectDataViewModel::AddLayersRoot(const wxDataViewItem &parent_item)
|
||||||
|
{
|
||||||
|
ObjectDataViewModelNode *parent_node = (ObjectDataViewModelNode*)parent_item.GetID();
|
||||||
|
if (!parent_node) return wxDataViewItem(0);
|
||||||
|
|
||||||
|
// get LayerRoot node
|
||||||
|
ObjectDataViewModelNode *layer_root_node{ nullptr };
|
||||||
|
const bool appended = append_root_node(parent_node, &layer_root_node, itLayerRoot);
|
||||||
|
if (!layer_root_node) return wxDataViewItem(0);
|
||||||
|
|
||||||
|
const wxDataViewItem layer_root_item((void*)layer_root_node);
|
||||||
|
|
||||||
|
if (appended)
|
||||||
|
ItemAdded(parent_item, layer_root_item);// notify control
|
||||||
|
|
||||||
|
return wxDataViewItem((void*)layer_root_item);
|
||||||
|
}
|
||||||
|
|
||||||
|
wxDataViewItem ObjectDataViewModel::AddLayersChild(const wxDataViewItem &parent_item)
|
||||||
|
{
|
||||||
|
ObjectDataViewModelNode *parent_node = (ObjectDataViewModelNode*)parent_item.GetID();
|
||||||
|
if (!parent_node) return wxDataViewItem(0);
|
||||||
|
|
||||||
|
// get LayerRoot node
|
||||||
|
const int root_idx = get_root_idx(parent_node, itLayerRoot);
|
||||||
|
if (root_idx < 0) return wxDataViewItem(0);
|
||||||
|
ObjectDataViewModelNode *layer_root_node = parent_node->GetNthChild(root_idx);
|
||||||
|
|
||||||
|
const wxDataViewItem layer_root_item((void*)layer_root_node);
|
||||||
|
|
||||||
|
// Add layer node
|
||||||
|
ObjectDataViewModelNode *layer_node = new ObjectDataViewModelNode(layer_root_node, itLayer);
|
||||||
|
layer_root_node->Append(layer_node);
|
||||||
|
|
||||||
|
// notify control
|
||||||
|
const wxDataViewItem instance_item((void*)layer_node);
|
||||||
|
ItemAdded(layer_root_item, instance_item);
|
||||||
|
|
||||||
|
return wxDataViewItem((void*)layer_node);
|
||||||
|
}
|
||||||
|
|
||||||
wxDataViewItem ObjectDataViewModel::Delete(const wxDataViewItem &item)
|
wxDataViewItem ObjectDataViewModel::Delete(const wxDataViewItem &item)
|
||||||
{
|
{
|
||||||
auto ret_item = wxDataViewItem(0);
|
auto ret_item = wxDataViewItem(0);
|
||||||
|
@ -817,7 +901,7 @@ wxDataViewItem ObjectDataViewModel::DeleteLastInstance(const wxDataViewItem &par
|
||||||
ObjectDataViewModelNode *parent_node = (ObjectDataViewModelNode*)parent_item.GetID();
|
ObjectDataViewModelNode *parent_node = (ObjectDataViewModelNode*)parent_item.GetID();
|
||||||
if (!parent_node) return ret_item;
|
if (!parent_node) return ret_item;
|
||||||
|
|
||||||
const int inst_root_id = get_istances_root_idx(parent_node);
|
const int inst_root_id = get_root_idx(parent_node, itInstanceRoot);
|
||||||
if (inst_root_id < 0) return ret_item;
|
if (inst_root_id < 0) return ret_item;
|
||||||
|
|
||||||
wxDataViewItemArray items;
|
wxDataViewItemArray items;
|
||||||
|
@ -2573,7 +2657,7 @@ ModeSizer::ModeSizer(wxWindow *parent, int hgap/* = 10*/) :
|
||||||
m_mode_btns.push_back(new ModeButton(parent, wxID_ANY, button.second, button.first));;
|
m_mode_btns.push_back(new ModeButton(parent, wxID_ANY, button.second, button.first));;
|
||||||
#endif // __WXOSX__
|
#endif // __WXOSX__
|
||||||
|
|
||||||
m_mode_btns.back()->Bind(wxEVT_BUTTON, std::bind(modebtnfn, std::placeholders::_1, m_mode_btns.size() - 1));
|
m_mode_btns.back()->Bind(wxEVT_BUTTON, std::bind(modebtnfn, std::placeholders::_1, int(m_mode_btns.size() - 1)));
|
||||||
Add(m_mode_btns.back());
|
Add(m_mode_btns.back());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -164,7 +164,9 @@ enum ItemType {
|
||||||
itVolume = 2,
|
itVolume = 2,
|
||||||
itInstanceRoot = 4,
|
itInstanceRoot = 4,
|
||||||
itInstance = 8,
|
itInstance = 8,
|
||||||
itSettings = 16
|
itSettings = 16,
|
||||||
|
itLayerRoot = 32,
|
||||||
|
itLayer = 64,
|
||||||
};
|
};
|
||||||
|
|
||||||
class ObjectDataViewModelNode;
|
class ObjectDataViewModelNode;
|
||||||
|
@ -388,6 +390,8 @@ public:
|
||||||
const bool create_frst_child = true);
|
const bool create_frst_child = true);
|
||||||
wxDataViewItem AddSettingsChild(const wxDataViewItem &parent_item);
|
wxDataViewItem AddSettingsChild(const wxDataViewItem &parent_item);
|
||||||
wxDataViewItem AddInstanceChild(const wxDataViewItem &parent_item, size_t num);
|
wxDataViewItem AddInstanceChild(const wxDataViewItem &parent_item, size_t num);
|
||||||
|
wxDataViewItem AddLayersRoot(const wxDataViewItem &parent_item);
|
||||||
|
wxDataViewItem AddLayersChild(const wxDataViewItem &parent_item);
|
||||||
wxDataViewItem Delete(const wxDataViewItem &item);
|
wxDataViewItem Delete(const wxDataViewItem &item);
|
||||||
wxDataViewItem DeleteLastInstance(const wxDataViewItem &parent_item, size_t num);
|
wxDataViewItem DeleteLastInstance(const wxDataViewItem &parent_item, size_t num);
|
||||||
void DeleteAll();
|
void DeleteAll();
|
||||||
|
|
Loading…
Reference in a new issue