Merge branch 'master' of https://github.com/prusa3d/PrusaSlicer into et_splitted_vbuffer

This commit is contained in:
enricoturri1966 2020-12-11 15:02:42 +01:00
commit 20c4b2c804
13 changed files with 119 additions and 19 deletions

View file

@ -465,8 +465,11 @@ void Model::convert_from_imperial_units()
{ {
double in_to_mm = 25.4; double in_to_mm = 25.4;
for (ModelObject* obj : this->objects) for (ModelObject* obj : this->objects)
if (obj->get_object_stl_stats().volume < 9.0) // 9 = 3*3*3; if (obj->get_object_stl_stats().volume < 9.0) { // 9 = 3*3*3;
obj->scale_mesh_after_creation(Vec3d(in_to_mm, in_to_mm, in_to_mm)); obj->scale_mesh_after_creation(Vec3d(in_to_mm, in_to_mm, in_to_mm));
for (ModelVolume* v : obj->volumes)
v->source.is_converted_from_inches = true;
}
} }
void Model::adjust_min_z() void Model::adjust_min_z()
@ -1053,12 +1056,16 @@ void ModelObject::convert_units(ModelObjectPtrs& new_objects, bool from_imperial
assert(vol->config.id().valid()); assert(vol->config.id().valid());
assert(vol->config.id() != volume->config.id()); assert(vol->config.id() != volume->config.id());
vol->set_material(volume->material_id(), *volume->material()); vol->set_material(volume->material_id(), *volume->material());
vol->source.input_file = volume->source.input_file;
vol->source.object_idx = (int)new_objects.size();
vol->source.volume_idx = vol_idx;
// Perform conversion // Perform conversion
if (volume_idxs.empty() || if (volume_idxs.empty() ||
std::find(volume_idxs.begin(), volume_idxs.end(), vol_idx) != volume_idxs.end()) { std::find(volume_idxs.begin(), volume_idxs.end(), vol_idx) != volume_idxs.end()) {
vol->scale_geometry_after_creation(versor); vol->scale_geometry_after_creation(versor);
vol->set_offset(versor.cwiseProduct(volume->get_offset())); vol->set_offset(versor.cwiseProduct(volume->get_offset()));
vol->source.is_converted_from_inches = from_imperial;
} }
else else
vol->set_offset(volume->get_offset()); vol->set_offset(volume->get_offset());
@ -1798,6 +1805,14 @@ void ModelVolume::transform_this_mesh(const Matrix3d &matrix, bool fix_left_hand
this->set_new_unique_id(); this->set_new_unique_id();
} }
void ModelVolume::convert_from_imperial_units()
{
double in_to_mm = 25.4;
this->scale_geometry_after_creation(Vec3d(in_to_mm, in_to_mm, in_to_mm));
this->set_offset(Vec3d(0, 0, 0));
this->source.is_converted_from_inches = true;
}
void ModelInstance::transform_mesh(TriangleMesh* mesh, bool dont_translate) const void ModelInstance::transform_mesh(TriangleMesh* mesh, bool dont_translate) const
{ {
mesh->transform(get_matrix(dont_translate)); mesh->transform(get_matrix(dont_translate));

View file

@ -552,11 +552,12 @@ public:
int volume_idx{ -1 }; int volume_idx{ -1 };
Vec3d mesh_offset{ Vec3d::Zero() }; Vec3d mesh_offset{ Vec3d::Zero() };
Geometry::Transformation transform; Geometry::Transformation transform;
bool is_converted_from_inches = false;
template<class Archive> void serialize(Archive& ar) { template<class Archive> void serialize(Archive& ar) {
//FIXME Vojtech: Serialize / deserialize only if the Source is set. //FIXME Vojtech: Serialize / deserialize only if the Source is set.
// likely testing input_file or object_idx would be sufficient. // likely testing input_file or object_idx would be sufficient.
ar(input_file, object_idx, volume_idx, mesh_offset, transform); ar(input_file, object_idx, volume_idx, mesh_offset, transform, is_converted_from_inches);
} }
}; };
Source source; Source source;
@ -655,6 +656,7 @@ public:
void set_mirror(const Vec3d& mirror) { m_transformation.set_mirror(mirror); } void set_mirror(const Vec3d& mirror) { m_transformation.set_mirror(mirror); }
void set_mirror(Axis axis, double mirror) { m_transformation.set_mirror(axis, mirror); } void set_mirror(Axis axis, double mirror) { m_transformation.set_mirror(axis, mirror); }
void convert_from_imperial_units();
const Transform3d& get_matrix(bool dont_translate = false, bool dont_rotate = false, bool dont_scale = false, bool dont_mirror = false) const { return m_transformation.get_matrix(dont_translate, dont_rotate, dont_scale, dont_mirror); } const Transform3d& get_matrix(bool dont_translate = false, bool dont_rotate = false, bool dont_scale = false, bool dont_mirror = false) const { return m_transformation.get_matrix(dont_translate, dont_rotate, dont_scale, dont_mirror); }

View file

@ -97,5 +97,6 @@
#define ENABLE_2_3_0_BETA3 1 #define ENABLE_2_3_0_BETA3 1
#define ENABLE_TOOLPATHS_WIDTH_HEIGHT_FROM_GCODE (1 && ENABLE_2_3_0_BETA3) #define ENABLE_TOOLPATHS_WIDTH_HEIGHT_FROM_GCODE (1 && ENABLE_2_3_0_BETA3)
#define ENABLE_RENDER_PATH_REFRESH_AFTER_OPTIONS_CHANGE (1 && ENABLE_2_3_0_BETA3)
#endif // _prusaslicer_technologies_h_ #endif // _prusaslicer_technologies_h_

View file

@ -429,11 +429,22 @@ void GCodeViewer::refresh(const GCodeProcessor::Result& gcode_result, const std:
#endif // ENABLE_GCODE_VIEWER_STATISTICS #endif // ENABLE_GCODE_VIEWER_STATISTICS
// update buffers' render paths // update buffers' render paths
#if ENABLE_RENDER_PATH_REFRESH_AFTER_OPTIONS_CHANGE
refresh_render_paths();
#else
refresh_render_paths(false, false); refresh_render_paths(false, false);
#endif // ENABLE_RENDER_PATH_REFRESH_AFTER_OPTIONS_CHANGE
log_memory_used("Refreshed G-code extrusion paths, "); log_memory_used("Refreshed G-code extrusion paths, ");
} }
#if ENABLE_RENDER_PATH_REFRESH_AFTER_OPTIONS_CHANGE
void GCodeViewer::refresh_render_paths()
{
refresh_render_paths(false, false);
}
#endif // ENABLE_RENDER_PATH_REFRESH_AFTER_OPTIONS_CHANGE
void GCodeViewer::reset() void GCodeViewer::reset()
{ {
m_initialized = false; m_initialized = false;

View file

@ -469,6 +469,9 @@ public:
void load(const GCodeProcessor::Result& gcode_result, const Print& print, bool initialized); void load(const GCodeProcessor::Result& gcode_result, const Print& print, bool initialized);
// recalculate ranges in dependence of what is visible and sets tool/print colors // recalculate ranges in dependence of what is visible and sets tool/print colors
void refresh(const GCodeProcessor::Result& gcode_result, const std::vector<std::string>& str_tool_colors); void refresh(const GCodeProcessor::Result& gcode_result, const std::vector<std::string>& str_tool_colors);
#if ENABLE_RENDER_PATH_REFRESH_AFTER_OPTIONS_CHANGE
void refresh_render_paths();
#endif // ENABLE_RENDER_PATH_REFRESH_AFTER_OPTIONS_CHANGE
void reset(); void reset();
void render() const; void render() const;

View file

@ -2287,6 +2287,15 @@ void GLCanvas3D::refresh_gcode_preview(const GCodeProcessor::Result& gcode_resul
request_extra_frame(); request_extra_frame();
} }
#if ENABLE_RENDER_PATH_REFRESH_AFTER_OPTIONS_CHANGE
void GLCanvas3D::refresh_gcode_preview_render_paths()
{
m_gcode_viewer.refresh_render_paths();
set_as_dirty();
request_extra_frame();
}
#endif // ENABLE_RENDER_PATH_REFRESH_AFTER_OPTIONS_CHANGE
void GLCanvas3D::load_sla_preview() void GLCanvas3D::load_sla_preview()
{ {
const SLAPrint* print = this->sla_print(); const SLAPrint* print = this->sla_print();

View file

@ -633,6 +633,9 @@ public:
void load_gcode_preview(const GCodeProcessor::Result& gcode_result); void load_gcode_preview(const GCodeProcessor::Result& gcode_result);
void refresh_gcode_preview(const GCodeProcessor::Result& gcode_result, const std::vector<std::string>& str_tool_colors); void refresh_gcode_preview(const GCodeProcessor::Result& gcode_result, const std::vector<std::string>& str_tool_colors);
#if ENABLE_RENDER_PATH_REFRESH_AFTER_OPTIONS_CHANGE
void refresh_gcode_preview_render_paths();
#endif // ENABLE_RENDER_PATH_REFRESH_AFTER_OPTIONS_CHANGE
void set_gcode_view_preview_type(GCodeViewer::EViewType type) { return m_gcode_viewer.set_view_type(type); } void set_gcode_view_preview_type(GCodeViewer::EViewType type) { return m_gcode_viewer.set_view_type(type); }
GCodeViewer::EViewType get_gcode_view_preview_type() const { return m_gcode_viewer.get_view_type(); } GCodeViewer::EViewType get_gcode_view_preview_type() const { return m_gcode_viewer.get_view_type(); }
void load_sla_preview(); void load_sla_preview();

View file

@ -1005,6 +1005,8 @@ void ObjectList::show_context_menu(const bool evt_context_menu)
m_objects_model->GetParent(item) != wxDataViewItem(nullptr) ? &m_menu_part : m_objects_model->GetParent(item) != wxDataViewItem(nullptr) ? &m_menu_part :
printer_technology() == ptFFF ? &m_menu_object : &m_menu_sla_object; printer_technology() == ptFFF ? &m_menu_object : &m_menu_sla_object;
if (type & (itObject | itVolume))
append_menu_item_convert_unit(menu);
if (!(type & itInstance)) if (!(type & itInstance))
append_menu_item_settings(menu); append_menu_item_settings(menu);
} }
@ -1883,13 +1885,57 @@ void ObjectList::append_menu_item_scale_selection_to_fit_print_volume(wxMenu* me
[](wxCommandEvent&) { wxGetApp().plater()->scale_selection_to_fit_print_volume(); }, "", menu); [](wxCommandEvent&) { wxGetApp().plater()->scale_selection_to_fit_print_volume(); }, "", menu);
} }
void ObjectList::append_menu_items_convert_unit(wxMenu* menu) void ObjectList::append_menu_item_convert_unit(wxMenu* menu, int insert_pos/* = 1*/)
{ {
append_menu_item(menu, wxID_ANY, _L("Convert from imperial units"), _L("Convert from imperial units"), std::vector<int> obj_idxs, vol_idxs;
[](wxCommandEvent&) { wxGetApp().plater()->convert_unit(true); }, "", menu); get_selection_indexes(obj_idxs, vol_idxs);
if (obj_idxs.empty() && vol_idxs.empty())
return;
append_menu_item(menu, wxID_ANY, _L("Revert conversion from imperial units"), _L("Revert conversion from imperial units"), auto can_append = [this, obj_idxs, vol_idxs](bool from_imperial_unit) {
[](wxCommandEvent&) { wxGetApp().plater()->convert_unit(false); }, "", menu); ModelObjectPtrs objects;
for (int obj_idx : obj_idxs) {
ModelObject* object = (*m_objects)[obj_idx];
if (vol_idxs.empty()) {
for (ModelVolume* volume : object->volumes)
if (volume->source.is_converted_from_inches == from_imperial_unit)
return false;
}
else {
for (int vol_idx : vol_idxs)
if (object->volumes[vol_idx]->source.is_converted_from_inches == from_imperial_unit)
return false;
}
}
return true;
};
wxString convert_menu_name = _L("Convert from imperial units");
int convert_menu_id = menu->FindItem(convert_menu_name);
wxString revert_menu_name = _L("Revert conversion from imperial units");
int revert_menu_id = menu->FindItem(revert_menu_name);
if (can_append(true)) {
// Delete revert menu item
if (revert_menu_id != wxNOT_FOUND)
menu->Destroy(revert_menu_id);
// Add convert menu item if it doesn't exist
if (convert_menu_id == wxNOT_FOUND)
append_menu_item(menu, wxID_ANY, convert_menu_name, convert_menu_name,
[](wxCommandEvent&) { wxGetApp().plater()->convert_unit(true); }, "", menu,
[]() {return true;}, nullptr, insert_pos);
}
if (can_append(false)) {
// Delete convert menu item
if (convert_menu_id != wxNOT_FOUND)
menu->Destroy(convert_menu_id);
// Add convert menu item if it doesn't exist
if (revert_menu_id == wxNOT_FOUND)
append_menu_item(menu, wxID_ANY, revert_menu_name, revert_menu_name,
[](wxCommandEvent&) { wxGetApp().plater()->convert_unit(false); }, "", menu,
[]() {return true;}, nullptr, insert_pos);
}
} }
void ObjectList::append_menu_item_merge_to_multipart_object(wxMenu* menu) void ObjectList::append_menu_item_merge_to_multipart_object(wxMenu* menu)
@ -1915,7 +1961,6 @@ void ObjectList::create_object_popupmenu(wxMenu *menu)
#endif // __WXOSX__ #endif // __WXOSX__
append_menu_item_reload_from_disk(menu); append_menu_item_reload_from_disk(menu);
append_menu_items_convert_unit(menu);
append_menu_item_export_stl(menu); append_menu_item_export_stl(menu);
append_menu_item_fix_through_netfabb(menu); append_menu_item_fix_through_netfabb(menu);
append_menu_item_scale_selection_to_fit_print_volume(menu); append_menu_item_scale_selection_to_fit_print_volume(menu);
@ -1944,7 +1989,6 @@ void ObjectList::create_sla_object_popupmenu(wxMenu *menu)
#endif // __WXOSX__ #endif // __WXOSX__
append_menu_item_reload_from_disk(menu); append_menu_item_reload_from_disk(menu);
append_menu_items_convert_unit(menu);
append_menu_item_export_stl(menu); append_menu_item_export_stl(menu);
append_menu_item_fix_through_netfabb(menu); append_menu_item_fix_through_netfabb(menu);
// rest of a object_sla_menu will be added later in: // rest of a object_sla_menu will be added later in:
@ -1958,7 +2002,6 @@ void ObjectList::create_part_popupmenu(wxMenu *menu)
#endif // __WXOSX__ #endif // __WXOSX__
append_menu_item_reload_from_disk(menu); append_menu_item_reload_from_disk(menu);
append_menu_items_convert_unit(menu);
append_menu_item_export_stl(menu); append_menu_item_export_stl(menu);
append_menu_item_fix_through_netfabb(menu); append_menu_item_fix_through_netfabb(menu);
@ -4526,7 +4569,7 @@ void ObjectList::show_multi_selection_menu()
return wxGetApp().plater()->can_reload_from_disk(); return wxGetApp().plater()->can_reload_from_disk();
}, wxGetApp().plater()); }, wxGetApp().plater());
append_menu_items_convert_unit(menu); append_menu_item_convert_unit(menu);
if (can_merge_to_multipart_object()) if (can_merge_to_multipart_object())
append_menu_item_merge_to_multipart_object(menu); append_menu_item_merge_to_multipart_object(menu);

View file

@ -281,7 +281,7 @@ public:
void append_menu_item_change_extruder(wxMenu* menu); void append_menu_item_change_extruder(wxMenu* menu);
void append_menu_item_delete(wxMenu* menu); void append_menu_item_delete(wxMenu* menu);
void append_menu_item_scale_selection_to_fit_print_volume(wxMenu* menu); void append_menu_item_scale_selection_to_fit_print_volume(wxMenu* menu);
void append_menu_items_convert_unit(wxMenu* menu); void append_menu_item_convert_unit(wxMenu* menu, int insert_pos = 1); // Add "Conver/Revert..." menu item after "Reload From Disk"
void append_menu_item_merge_to_multipart_object(wxMenu *menu); void append_menu_item_merge_to_multipart_object(wxMenu *menu);
void append_menu_item_merge_to_single_object(wxMenu *menu); void append_menu_item_merge_to_single_object(wxMenu *menu);
void create_object_popupmenu(wxMenu *menu); void create_object_popupmenu(wxMenu *menu);

View file

@ -507,6 +507,9 @@ void Preview::on_combochecklist_options(wxCommandEvent& evt)
m_canvas->set_gcode_options_visibility_from_flags(new_flags); m_canvas->set_gcode_options_visibility_from_flags(new_flags);
#if ENABLE_RENDER_PATH_REFRESH_AFTER_OPTIONS_CHANGE
m_canvas->refresh_gcode_preview_render_paths();
#else
bool skip_refresh = xored(curr_flags, new_flags, static_cast<unsigned int>(OptionType::Shells)) || bool skip_refresh = xored(curr_flags, new_flags, static_cast<unsigned int>(OptionType::Shells)) ||
xored(curr_flags, new_flags, static_cast<unsigned int>(OptionType::ToolMarker)); xored(curr_flags, new_flags, static_cast<unsigned int>(OptionType::ToolMarker));
@ -514,6 +517,7 @@ void Preview::on_combochecklist_options(wxCommandEvent& evt)
refresh_print(); refresh_print();
else else
m_canvas->set_as_dirty(); m_canvas->set_as_dirty();
#endif // ENABLE_RENDER_PATH_REFRESH_AFTER_OPTIONS_CHANGE
} }
#if !ENABLE_PREVIEW_TYPE_CHANGE #if !ENABLE_PREVIEW_TYPE_CHANGE

View file

@ -3297,6 +3297,8 @@ void Plater::priv::reload_from_disk()
new_volume->set_material_id(old_volume->material_id()); new_volume->set_material_id(old_volume->material_id());
new_volume->set_transformation(old_volume->get_transformation() * old_volume->source.transform); new_volume->set_transformation(old_volume->get_transformation() * old_volume->source.transform);
new_volume->translate(new_volume->get_transformation().get_matrix(true) * (new_volume->source.mesh_offset - old_volume->source.mesh_offset)); new_volume->translate(new_volume->get_transformation().get_matrix(true) * (new_volume->source.mesh_offset - old_volume->source.mesh_offset));
if (old_volume->source.is_converted_from_inches)
new_volume->convert_from_imperial_units();
std::swap(old_model_object->volumes[sel_v.volume_idx], old_model_object->volumes.back()); std::swap(old_model_object->volumes[sel_v.volume_idx], old_model_object->volumes.back());
old_model_object->delete_volume(old_model_object->volumes.size() - 1); old_model_object->delete_volume(old_model_object->volumes.size() - 1);
old_model_object->ensure_on_bed(); old_model_object->ensure_on_bed();
@ -3771,6 +3773,8 @@ void Plater::priv::on_right_click(RBtnEvent& evt)
if (evt.data.second) if (evt.data.second)
return; return;
int menu_item_convert_unit_position = 11;
if (printer_technology == ptSLA) if (printer_technology == ptSLA)
menu = &sla_object_menu; menu = &sla_object_menu;
else else
@ -3780,8 +3784,11 @@ void Plater::priv::on_right_click(RBtnEvent& evt)
get_selection().is_single_full_object() || get_selection().is_single_full_object() ||
get_selection().is_multiple_full_instance(); get_selection().is_multiple_full_instance();
menu = is_some_full_instances ? &object_menu : &part_menu; menu = is_some_full_instances ? &object_menu : &part_menu;
if (!is_some_full_instances)
menu_item_convert_unit_position = 2;
} }
sidebar->obj_list()->append_menu_item_convert_unit(menu, menu_item_convert_unit_position);
sidebar->obj_list()->append_menu_item_settings(menu); sidebar->obj_list()->append_menu_item_settings(menu);
if (printer_technology != ptSLA) if (printer_technology != ptSLA)
@ -3996,7 +4003,6 @@ bool Plater::priv::init_common_menu(wxMenu* menu, const bool is_part/* = false*/
}, menu_item_printable->GetId()); }, menu_item_printable->GetId());
} }
sidebar->obj_list()->append_menu_items_convert_unit(menu);
sidebar->obj_list()->append_menu_item_fix_through_netfabb(menu); sidebar->obj_list()->append_menu_item_fix_through_netfabb(menu);
wxMenu* mirror_menu = new wxMenu(); wxMenu* mirror_menu = new wxMenu();

View file

@ -63,7 +63,7 @@ void enable_menu_item(wxUpdateUIEvent& evt, std::function<bool()> const cb_condi
wxMenuItem* append_menu_item(wxMenu* menu, int id, const wxString& string, const wxString& description, wxMenuItem* append_menu_item(wxMenu* menu, int id, const wxString& string, const wxString& description,
std::function<void(wxCommandEvent& event)> cb, const wxBitmap& icon, wxEvtHandler* event_handler, std::function<void(wxCommandEvent& event)> cb, const wxBitmap& icon, wxEvtHandler* event_handler,
std::function<bool()> const cb_condition, wxWindow* parent) std::function<bool()> const cb_condition, wxWindow* parent, int insert_pos/* = wxNOT_FOUND*/)
{ {
if (id == wxID_ANY) if (id == wxID_ANY)
id = wxNewId(); id = wxNewId();
@ -72,7 +72,10 @@ wxMenuItem* append_menu_item(wxMenu* menu, int id, const wxString& string, const
if (icon.IsOk()) { if (icon.IsOk()) {
item->SetBitmap(icon); item->SetBitmap(icon);
} }
if (insert_pos == wxNOT_FOUND)
menu->Append(item); menu->Append(item);
else
menu->Insert(insert_pos, item);
#ifdef __WXMSW__ #ifdef __WXMSW__
if (event_handler != nullptr && event_handler != menu) if (event_handler != nullptr && event_handler != menu)
@ -91,7 +94,7 @@ wxMenuItem* append_menu_item(wxMenu* menu, int id, const wxString& string, const
wxMenuItem* append_menu_item(wxMenu* menu, int id, const wxString& string, const wxString& description, wxMenuItem* append_menu_item(wxMenu* menu, int id, const wxString& string, const wxString& description,
std::function<void(wxCommandEvent& event)> cb, const std::string& icon, wxEvtHandler* event_handler, std::function<void(wxCommandEvent& event)> cb, const std::string& icon, wxEvtHandler* event_handler,
std::function<bool()> const cb_condition, wxWindow* parent) std::function<bool()> const cb_condition, wxWindow* parent, int insert_pos/* = wxNOT_FOUND*/)
{ {
if (id == wxID_ANY) if (id == wxID_ANY)
id = wxNewId(); id = wxNewId();
@ -103,7 +106,7 @@ wxMenuItem* append_menu_item(wxMenu* menu, int id, const wxString& string, const
msw_menuitem_bitmaps[id] = icon; msw_menuitem_bitmaps[id] = icon;
#endif /* __WXMSW__ */ #endif /* __WXMSW__ */
return append_menu_item(menu, id, string, description, cb, bmp, event_handler, cb_condition, parent); return append_menu_item(menu, id, string, description, cb, bmp, event_handler, cb_condition, parent, insert_pos);
} }
wxMenuItem* append_submenu(wxMenu* menu, wxMenu* sub_menu, int id, const wxString& string, const wxString& description, const std::string& icon, wxMenuItem* append_submenu(wxMenu* menu, wxMenu* sub_menu, int id, const wxString& string, const wxString& description, const std::string& icon,

View file

@ -22,10 +22,10 @@ inline void msw_rescale_menu(wxMenu* /* menu */) {}
wxMenuItem* append_menu_item(wxMenu* menu, int id, const wxString& string, const wxString& description, wxMenuItem* append_menu_item(wxMenu* menu, int id, const wxString& string, const wxString& description,
std::function<void(wxCommandEvent& event)> cb, const wxBitmap& icon, wxEvtHandler* event_handler = nullptr, std::function<void(wxCommandEvent& event)> cb, const wxBitmap& icon, wxEvtHandler* event_handler = nullptr,
std::function<bool()> const cb_condition = []() { return true;}, wxWindow* parent = nullptr); std::function<bool()> const cb_condition = []() { return true;}, wxWindow* parent = nullptr, int insert_pos = wxNOT_FOUND);
wxMenuItem* append_menu_item(wxMenu* menu, int id, const wxString& string, const wxString& description, wxMenuItem* append_menu_item(wxMenu* menu, int id, const wxString& string, const wxString& description,
std::function<void(wxCommandEvent& event)> cb, const std::string& icon = "", wxEvtHandler* event_handler = nullptr, std::function<void(wxCommandEvent& event)> cb, const std::string& icon = "", wxEvtHandler* event_handler = nullptr,
std::function<bool()> const cb_condition = []() { return true; }, wxWindow* parent = nullptr); std::function<bool()> const cb_condition = []() { return true; }, wxWindow* parent = nullptr, int insert_pos = wxNOT_FOUND);
wxMenuItem* append_submenu(wxMenu* menu, wxMenu* sub_menu, int id, const wxString& string, const wxString& description, wxMenuItem* append_submenu(wxMenu* menu, wxMenu* sub_menu, int id, const wxString& string, const wxString& description,
const std::string& icon = "", const std::string& icon = "",