Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorenricoturri1966 <enricoturri@seznam.cz>2021-09-10 10:07:55 +0300
committerenricoturri1966 <enricoturri@seznam.cz>2021-09-10 10:07:55 +0300
commit638fc5a869acc15b42cbec094b19d07bf12600f1 (patch)
tree89b6a20ad7236c6ef70716fd2ee70826d8ed1f26 /src/slic3r
parent3369e1b599c66d6abe86ce316cecdc38732d7017 (diff)
parent8f4a6b3b7c90f618d99e294e3567156263cf9936 (diff)
Merge branch 'master' of https://github.com/prusa3d/PrusaSlicer into et_reload_from_disk_changes
Diffstat (limited to 'src/slic3r')
-rw-r--r--src/slic3r/GUI/3DScene.cpp68
-rw-r--r--src/slic3r/GUI/3DScene.hpp1
-rw-r--r--src/slic3r/GUI/GLCanvas3D.cpp17
-rw-r--r--src/slic3r/GUI/GLCanvas3D.hpp2
-rw-r--r--src/slic3r/GUI/GUI_ObjectList.cpp6
-rw-r--r--src/slic3r/GUI/GUI_Preview.cpp5
-rw-r--r--src/slic3r/GUI/GUI_Preview.hpp2
-rw-r--r--src/slic3r/GUI/Notebook.cpp24
-rw-r--r--src/slic3r/GUI/ObjectDataViewModel.cpp68
-rw-r--r--src/slic3r/GUI/ObjectDataViewModel.hpp1
-rw-r--r--src/slic3r/GUI/Plater.cpp4
-rw-r--r--src/slic3r/GUI/wxExtensions.cpp3
-rw-r--r--src/slic3r/GUI/wxExtensions.hpp2
13 files changed, 92 insertions, 111 deletions
diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp
index 7a9fdc388..2d49a8bf3 100644
--- a/src/slic3r/GUI/3DScene.cpp
+++ b/src/slic3r/GUI/3DScene.cpp
@@ -827,6 +827,12 @@ GLVolumeWithIdAndZList volumes_to_render(const GLVolumePtrs& volumes, GLVolumeCo
void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disable_cullface, const Transform3d& view_matrix, std::function<bool(const GLVolume&)> filter_func) const
{
+#if ENABLE_SINKING_CONTOURS
+ GLVolumeWithIdAndZList to_render = volumes_to_render(volumes, type, view_matrix, filter_func);
+ if (to_render.empty())
+ return;
+#endif // ENABLE_SINKING_CONTOURS
+
GLShaderProgram* shader = GUI::wxGetApp().get_current_shader();
if (shader == nullptr)
return;
@@ -841,7 +847,6 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disab
glsafe(::glDisable(GL_CULL_FACE));
#if ENABLE_SINKING_CONTOURS
- GLVolumeWithIdAndZList to_render = volumes_to_render(volumes, type, view_matrix, filter_func);
for (GLVolumeWithIdAndZ& volume : to_render) {
volume.first->set_render_color();
@@ -961,8 +966,10 @@ bool GLVolumeCollection::check_outside_state(const DynamicPrintConfig* config, M
if (opt == nullptr)
return false;
- BoundingBox bed_box_2D = get_extents(Polygon::new_scale(opt->values));
- BoundingBoxf3 print_volume({ unscale<double>(bed_box_2D.min(0)), unscale<double>(bed_box_2D.min(1)), 0.0 }, { unscale<double>(bed_box_2D.max(0)), unscale<double>(bed_box_2D.max(1)), config->opt_float("max_print_height") });
+ const BoundingBox bed_box_2D = get_extents(Polygon::new_scale(opt->values));
+ BoundingBoxf3 print_volume({ unscale<double>(bed_box_2D.min.x()), unscale<double>(bed_box_2D.min.y()), 0.0 },
+ { unscale<double>(bed_box_2D.max.x()), unscale<double>(bed_box_2D.max.y()),
+ config->opt_float("max_print_height") });
// Allow the objects to protrude below the print bed
print_volume.min(2) = -1e10;
print_volume.min(0) -= BedEpsilon;
@@ -975,7 +982,7 @@ bool GLVolumeCollection::check_outside_state(const DynamicPrintConfig* config, M
bool contained_min_one = false;
for (GLVolume* volume : this->volumes) {
- if (volume == nullptr || volume->is_modifier || (volume->is_wipe_tower && !volume->shader_outside_printer_detection_enabled) || (volume->composite_id.volume_id < 0 && !volume->shader_outside_printer_detection_enabled))
+ if (volume->is_modifier || (!volume->shader_outside_printer_detection_enabled && (volume->is_wipe_tower || volume->composite_id.volume_id < 0)))
continue;
const BoundingBoxf3& bb = volume->transformed_convex_hull_bounding_box();
@@ -985,8 +992,7 @@ bool GLVolumeCollection::check_outside_state(const DynamicPrintConfig* config, M
if (!volume->printable)
continue;
- if (contained)
- contained_min_one = true;
+ contained_min_one |= contained;
if (state == ModelInstancePVS_Inside && volume->is_outside)
state = ModelInstancePVS_Fully_Outside;
@@ -1001,56 +1007,6 @@ bool GLVolumeCollection::check_outside_state(const DynamicPrintConfig* config, M
return contained_min_one;
}
-bool GLVolumeCollection::check_outside_state(const DynamicPrintConfig* config, bool& partlyOut, bool& fullyOut) const
-{
- if (config == nullptr)
- return false;
-
- const ConfigOptionPoints* opt = dynamic_cast<const ConfigOptionPoints*>(config->option("bed_shape"));
- if (opt == nullptr)
- return false;
-
- const BoundingBox bed_box_2D = get_extents(Polygon::new_scale(opt->values));
- BoundingBoxf3 print_volume(Vec3d(unscale<double>(bed_box_2D.min.x()), unscale<double>(bed_box_2D.min.y()), 0.0), Vec3d(unscale<double>(bed_box_2D.max.x()), unscale<double>(bed_box_2D.max.y()), config->opt_float("max_print_height")));
- // Allow the objects to protrude below the print bed
- print_volume.min(2) = -1e10;
- print_volume.min(0) -= BedEpsilon;
- print_volume.min(1) -= BedEpsilon;
- print_volume.max(0) += BedEpsilon;
- print_volume.max(1) += BedEpsilon;
-
- bool contained_min_one = false;
-
- partlyOut = false;
- fullyOut = false;
- for (GLVolume* volume : this->volumes) {
- if (volume == nullptr || volume->is_modifier || (volume->is_wipe_tower && !volume->shader_outside_printer_detection_enabled) || (volume->composite_id.volume_id < 0 && !volume->shader_outside_printer_detection_enabled))
- continue;
-
- const BoundingBoxf3& bb = volume->transformed_convex_hull_bounding_box();
- bool contained = print_volume.contains(bb);
-
- volume->is_outside = !contained;
- if (!volume->printable)
- continue;
-
- if (contained)
- contained_min_one = true;
-
- if (volume->is_outside) {
- if (print_volume.intersects(bb))
- partlyOut = true;
- else
- fullyOut = true;
- }
- }
- /*
- if (out_state != nullptr)
- *out_state = state;
- */
- return contained_min_one;
-}
-
void GLVolumeCollection::reset_outside_state()
{
for (GLVolume* volume : this->volumes)
diff --git a/src/slic3r/GUI/3DScene.hpp b/src/slic3r/GUI/3DScene.hpp
index e5298ca93..35abe8bd4 100644
--- a/src/slic3r/GUI/3DScene.hpp
+++ b/src/slic3r/GUI/3DScene.hpp
@@ -614,7 +614,6 @@ public:
// returns true if all the volumes are completely contained in the print volume
// returns the containment state in the given out_state, if non-null
bool check_outside_state(const DynamicPrintConfig* config, ModelInstanceEPrintVolumeState* out_state) const;
- bool check_outside_state(const DynamicPrintConfig* config, bool& partlyOut, bool& fullyOut) const;
void reset_outside_state();
void update_colors_by_extruder(const DynamicPrintConfig* config);
diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp
index f50c7fe25..d790e937c 100644
--- a/src/slic3r/GUI/GLCanvas3D.cpp
+++ b/src/slic3r/GUI/GLCanvas3D.cpp
@@ -1107,11 +1107,11 @@ void GLCanvas3D::reset_volumes()
_set_warning_notification(EWarning::ObjectOutside, false);
}
-int GLCanvas3D::check_volumes_outside_state() const
+ModelInstanceEPrintVolumeState GLCanvas3D::check_volumes_outside_state() const
{
ModelInstanceEPrintVolumeState state;
m_volumes.check_outside_state(m_config, &state);
- return (int)state;
+ return state;
}
void GLCanvas3D::toggle_sla_auxiliaries_visibility(bool visible, const ModelObject* mo, int instance_idx)
@@ -2039,9 +2039,10 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
// checks for geometry outside the print volume to render it accordingly
if (!m_volumes.empty()) {
- bool partlyOut = false;
- bool fullyOut = false;
- const bool contained_min_one = m_volumes.check_outside_state(m_config, partlyOut, fullyOut);
+ ModelInstanceEPrintVolumeState state;
+ const bool contained_min_one = m_volumes.check_outside_state(m_config, &state);
+ const bool partlyOut = (state == ModelInstanceEPrintVolumeState::ModelInstancePVS_Partly_Outside);
+ const bool fullyOut = (state == ModelInstanceEPrintVolumeState::ModelInstancePVS_Fully_Outside);
_set_warning_notification(EWarning::ObjectClashed, partlyOut);
_set_warning_notification(EWarning::ObjectOutside, fullyOut);
@@ -2117,12 +2118,14 @@ void GLCanvas3D::refresh_gcode_preview_render_paths()
void GLCanvas3D::load_sla_preview()
{
- const SLAPrint* print = this->sla_print();
+ const SLAPrint* print = sla_print();
if (m_canvas != nullptr && print != nullptr) {
_set_current();
// Release OpenGL data before generating new data.
- this->reset_volumes();
+ reset_volumes();
_load_sla_shells();
+ const BoundingBoxf3& bed_bb = wxGetApp().plater()->get_bed().get_bounding_box(false);
+ m_volumes.set_print_box(float(bed_bb.min.x()) - BedEpsilon, float(bed_bb.min.y()) - BedEpsilon, 0.0f, float(bed_bb.max.x()) + BedEpsilon, float(bed_bb.max.y()) + BedEpsilon, (float)m_config->opt_float("max_print_height"));
_update_sla_shells_outside_state();
_set_warning_notification_if_needed(EWarning::SlaSupportsOutside);
}
diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp
index 799fa11c7..eb0220cd4 100644
--- a/src/slic3r/GUI/GLCanvas3D.hpp
+++ b/src/slic3r/GUI/GLCanvas3D.hpp
@@ -615,7 +615,7 @@ public:
unsigned int get_volumes_count() const;
const GLVolumeCollection& get_volumes() const { return m_volumes; }
void reset_volumes();
- int check_volumes_outside_state() const;
+ ModelInstanceEPrintVolumeState check_volumes_outside_state() const;
void reset_gcode_toolpaths() { m_gcode_viewer.reset(); }
const GCodeViewer::SequentialView& get_gcode_sequential_view() const { return m_gcode_viewer.get_sequential_view(); }
diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp
index bf174cbf1..378f91cbc 100644
--- a/src/slic3r/GUI/GUI_ObjectList.cpp
+++ b/src/slic3r/GUI/GUI_ObjectList.cpp
@@ -3465,7 +3465,11 @@ void ObjectList::update_selections_on_canvas()
else
{
// add
- volume_idxs = selection.get_unselected_volume_idxs_from(volume_idxs);
+ // to avoid lost of some volumes in selection
+ // check non-selected volumes only if selection mode wasn't changed
+ // OR there is no single selection
+ if (selection.get_mode() == mode || !single_selection)
+ volume_idxs = selection.get_unselected_volume_idxs_from(volume_idxs);
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("Selection-Add from list")));
selection.add_volumes(mode, volume_idxs, single_selection);
}
diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp
index 8c10fb157..45da928f5 100644
--- a/src/slic3r/GUI/GUI_Preview.cpp
+++ b/src/slic3r/GUI/GUI_Preview.cpp
@@ -128,11 +128,6 @@ void View3D::mirror_selection(Axis axis)
m_canvas->mirror_selection(axis);
}
-int View3D::check_volumes_outside_state() const
-{
- return (m_canvas != nullptr) ? m_canvas->check_volumes_outside_state() : false;
-}
-
bool View3D::is_layers_editing_enabled() const
{
return (m_canvas != nullptr) ? m_canvas->is_layers_editing_enabled() : false;
diff --git a/src/slic3r/GUI/GUI_Preview.hpp b/src/slic3r/GUI/GUI_Preview.hpp
index f8a41fd92..97ced0a1e 100644
--- a/src/slic3r/GUI/GUI_Preview.hpp
+++ b/src/slic3r/GUI/GUI_Preview.hpp
@@ -59,8 +59,6 @@ public:
void delete_selected();
void mirror_selection(Axis axis);
- int check_volumes_outside_state() const;
-
bool is_layers_editing_enabled() const;
bool is_layers_editing_allowed() const;
void enable_layers_editing(bool enable);
diff --git a/src/slic3r/GUI/Notebook.cpp b/src/slic3r/GUI/Notebook.cpp
index b328fc583..9c5ccb834 100644
--- a/src/slic3r/GUI/Notebook.cpp
+++ b/src/slic3r/GUI/Notebook.cpp
@@ -45,11 +45,12 @@ void ButtonsListCtrl::OnPaint(wxPaintEvent&)
if (m_selection < 0 || m_selection >= (int)m_pageButtons.size())
return;
- // highlight selected button
-
const wxColour& selected_btn_bg = Slic3r::GUI::wxGetApp().get_color_selected_btn_bg();
const wxColour& default_btn_bg = Slic3r::GUI::wxGetApp().get_highlight_default_clr();
const wxColour& btn_marker_color = Slic3r::GUI::wxGetApp().get_color_hovered_btn_label();
+
+ // highlight selected notebook button
+
for (int idx = 0; idx < int(m_pageButtons.size()); idx++) {
wxButton* btn = m_pageButtons[idx];
@@ -63,6 +64,25 @@ void ButtonsListCtrl::OnPaint(wxPaintEvent&)
dc.DrawRectangle(pos.x, pos.y + size.y, size.x, sz.y - size.y);
}
+ // highlight selected mode button
+
+ if (m_mode_sizer) {
+ const std::vector<ModeButton*>& mode_btns = m_mode_sizer->get_btns();
+ for (int idx = 0; idx < int(mode_btns.size()); idx++) {
+ ModeButton* btn = mode_btns[idx];
+ btn->SetBackgroundColour(btn->is_selected() ? selected_btn_bg : default_btn_bg);
+
+ //wxPoint pos = btn->GetPosition();
+ //wxSize size = btn->GetSize();
+ //const wxColour& clr = btn->is_selected() ? btn_marker_color : default_btn_bg;
+ //dc.SetPen(clr);
+ //dc.SetBrush(clr);
+ //dc.DrawRectangle(pos.x, pos.y + size.y, size.x, sz.y - size.y);
+ }
+ }
+
+ // Draw orange bottom line
+
dc.SetPen(btn_marker_color);
dc.SetBrush(btn_marker_color);
dc.DrawRectangle(1, sz.y - m_line_margin, sz.x, m_line_margin);
diff --git a/src/slic3r/GUI/ObjectDataViewModel.cpp b/src/slic3r/GUI/ObjectDataViewModel.cpp
index 88527e9fd..928249e5b 100644
--- a/src/slic3r/GUI/ObjectDataViewModel.cpp
+++ b/src/slic3r/GUI/ObjectDataViewModel.cpp
@@ -406,8 +406,10 @@ wxDataViewItem ObjectDataViewModel::AddInfoChild(const wxDataViewItem &parent_it
// The new item should be added according to its order in InfoItemType.
// Find last info item with lower index and append after it.
const auto& children = root->GetChildren();
- int idx = -1;
- for (int i=0; i<int(children.size()); ++i) {
+ // If SettingsItem exists, it have to be on the first position always
+ bool is_settings_item = children.size() > 0 && children[0]->GetType() == itSettings;
+ int idx = is_settings_item ? 0 : -1;
+ for (size_t i = is_settings_item ? 1 : 0; i < children.size(); ++i) {
if (children[i]->GetType() == itInfo && int(children[i]->GetInfoItemType()) < int(info_type) )
idx = i;
}
@@ -619,6 +621,15 @@ wxDataViewItem ObjectDataViewModel::AddLayersChild(const wxDataViewItem &parent_
return layer_item;
}
+size_t ObjectDataViewModel::GetItemIndexForFirstVolume(ObjectDataViewModelNode* node_parent)
+{
+ assert(node_parent->m_volumes_cnt > 0);
+ for (size_t vol_idx = 0; vol_idx < node_parent->GetChildCount(); vol_idx++)
+ if (node_parent->GetNthChild(vol_idx)->GetType() == itVolume)
+ return vol_idx;
+ return -1;
+}
+
wxDataViewItem ObjectDataViewModel::Delete(const wxDataViewItem &item)
{
auto ret_item = wxDataViewItem(0);
@@ -714,44 +725,34 @@ wxDataViewItem ObjectDataViewModel::Delete(const wxDataViewItem &item)
}
// if there is last volume item after deleting, delete this last volume too
- if (node_parent->GetChildCount() <= 3) // 3??? #ys_FIXME
+ if (node_parent->m_volumes_cnt == 1)
{
- int vol_cnt = 0;
- int vol_idx = 0;
- for (size_t i = 0; i < node_parent->GetChildCount(); ++i) {
- if (node_parent->GetNthChild(i)->GetType() == itVolume) {
- vol_idx = i;
- vol_cnt++;
- }
- if (vol_cnt > 1)
- break;
- }
+ // delete selected (penult) volume
+ delete node;
+ ItemDeleted(parent, item);
- if (vol_cnt == 1) {
- delete node;
- ItemDeleted(parent, item);
+ // get index of the last VolumeItem in CildrenList
+ size_t vol_idx = GetItemIndexForFirstVolume(node_parent);
- ObjectDataViewModelNode *last_child_node = node_parent->GetNthChild(vol_idx);
- DeleteSettings(wxDataViewItem(last_child_node));
- node_parent->GetChildren().Remove(last_child_node);
- node_parent->m_volumes_cnt = 0;
- delete last_child_node;
+ // delete this last volume
+ ObjectDataViewModelNode *last_child_node = node_parent->GetNthChild(vol_idx);
+ DeleteSettings(wxDataViewItem(last_child_node));
+ node_parent->GetChildren().Remove(last_child_node);
+ node_parent->m_volumes_cnt = 0;
+ delete last_child_node;
#ifndef __WXGTK__
- if (node_parent->GetChildCount() == 0)
- node_parent->m_container = false;
+ if (node_parent->GetChildCount() == 0)
+ node_parent->m_container = false;
#endif //__WXGTK__
- ItemDeleted(parent, wxDataViewItem(last_child_node));
-
- wxCommandEvent event(wxCUSTOMEVT_LAST_VOLUME_IS_DELETED);
- auto it = find(m_objects.begin(), m_objects.end(), node_parent);
- event.SetInt(it == m_objects.end() ? -1 : it - m_objects.begin());
- wxPostEvent(m_ctrl, event);
+ ItemDeleted(parent, wxDataViewItem(last_child_node));
- ret_item = parent;
+ wxCommandEvent event(wxCUSTOMEVT_LAST_VOLUME_IS_DELETED);
+ auto it = find(m_objects.begin(), m_objects.end(), node_parent);
+ event.SetInt(it == m_objects.end() ? -1 : it - m_objects.begin());
+ wxPostEvent(m_ctrl, event);
- return ret_item;
- }
+ return parent;
}
}
else
@@ -1361,8 +1362,7 @@ wxDataViewItem ObjectDataViewModel::ReorganizeChildren( const int current_volume
if (!node_parent) // happens if item.IsOk()==false
return ret_item;
- size_t shift;
- for (shift = 0; shift < node_parent->GetChildCount() && node_parent->GetNthChild(shift)->GetType() != itVolume; shift ++);
+ size_t shift = GetItemIndexForFirstVolume(node_parent);
ObjectDataViewModelNode *deleted_node = node_parent->GetNthChild(current_volume_id+shift);
node_parent->GetChildren().Remove(deleted_node);
diff --git a/src/slic3r/GUI/ObjectDataViewModel.hpp b/src/slic3r/GUI/ObjectDataViewModel.hpp
index 86e64a854..f65f829f4 100644
--- a/src/slic3r/GUI/ObjectDataViewModel.hpp
+++ b/src/slic3r/GUI/ObjectDataViewModel.hpp
@@ -279,6 +279,7 @@ public:
const t_layer_height_range& layer_range,
const int extruder = 0,
const int index = -1);
+ size_t GetItemIndexForFirstVolume(ObjectDataViewModelNode* node_parent);
wxDataViewItem Delete(const wxDataViewItem &item);
wxDataViewItem DeleteLastInstance(const wxDataViewItem &parent_item, size_t num);
void DeleteAll();
diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp
index 2c3e15d67..9a436c1f0 100644
--- a/src/slic3r/GUI/Plater.cpp
+++ b/src/slic3r/GUI/Plater.cpp
@@ -2727,7 +2727,7 @@ void Plater::priv::object_list_changed()
{
const bool export_in_progress = this->background_process.is_export_scheduled(); // || ! send_gcode_file.empty());
// XXX: is this right?
- const bool model_fits = view3D->check_volumes_outside_state() == ModelInstancePVS_Inside;
+ const bool model_fits = view3D->get_canvas3d()->check_volumes_outside_state() == ModelInstancePVS_Inside;
sidebar->enable_buttons(!model.objects.empty() && !export_in_progress && model_fits);
}
@@ -3772,7 +3772,7 @@ void Plater::priv::set_current_panel(wxPanel* panel)
// see: Plater::priv::object_list_changed()
// FIXME: it may be better to have a single function making this check and let it be called wherever needed
bool export_in_progress = this->background_process.is_export_scheduled();
- bool model_fits = view3D->check_volumes_outside_state() != ModelInstancePVS_Partly_Outside;
+ bool model_fits = view3D->get_canvas3d()->check_volumes_outside_state() != ModelInstancePVS_Partly_Outside;
if (!model.objects.empty() && !export_in_progress && model_fits)
this->q->reslice();
// keeps current gcode preview, if any
diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp
index 8903f3b30..a3d6384e0 100644
--- a/src/slic3r/GUI/wxExtensions.cpp
+++ b/src/slic3r/GUI/wxExtensions.cpp
@@ -672,6 +672,9 @@ void ModeButton::focus_button(const bool focus)
Slic3r::GUI::wxGetApp().normal_font();
SetFont(new_font);
+//#ifdef _WIN32
+// GetParent()->Refresh();
+//#else
#ifndef _WIN32
SetForegroundColour(wxSystemSettings::GetColour(focus ? wxSYS_COLOUR_BTNTEXT :
#if defined (__linux__) && defined (__WXGTK3__)
diff --git a/src/slic3r/GUI/wxExtensions.hpp b/src/slic3r/GUI/wxExtensions.hpp
index 1462e8aa0..25876bd23 100644
--- a/src/slic3r/GUI/wxExtensions.hpp
+++ b/src/slic3r/GUI/wxExtensions.hpp
@@ -283,6 +283,7 @@ public:
void OnLeaveBtn(wxMouseEvent& event) { focus_button(m_is_selected); event.Skip(); }
void SetState(const bool state);
+ bool is_selected() { return m_is_selected; }
protected:
void focus_button(const bool focus);
@@ -312,6 +313,7 @@ public:
void set_items_border(int border);
void msw_rescale();
+ const std::vector<ModeButton*>& get_btns() { return m_mode_btns; }
private:
std::vector<ModeButton*> m_mode_btns;