diff --git a/docs/HLSD/design-tab.md b/docs/HLSD/design-tab.md
index 58bab4bfcb..f7d48e0ee6 100644
--- a/docs/HLSD/design-tab.md
+++ b/docs/HLSD/design-tab.md
@@ -175,11 +175,11 @@ handle or a press that draws takes it first, as a gizmo does in Prepare; a whole
with a rectangle on plain left-drag only while no camera action is assigned to the left button,
and with Shift+left-drag otherwise — Prepare's own rectangle selection.
-Entering a sketch changes three things at once so the mode is legible: a banner above the
+Entering a sketch changes two things at once so the mode is legible: a banner above the
canvas (a sibling of the canvas, not a child over it — on GTK a child window over a
-`wxGLCanvas` is a native window and does not reliably stack over GL), the printer bed muted so
-a plate grid is never read as a sketch grid, and `N` to look normal to the plane. Code that
-changes any of the three belongs with a change to this section.
+`wxGLCanvas` is a native window and does not reliably stack over GL), and `N` to look normal to
+the plane. The printer bed stays: there is no sketch grid, so the plate grid is the only ground
+reference a sketch has. Code that changes either belongs with a change to this section.
Sketch mode is never entered without a plane under it, so the banner, the sketch keys and the
sketch offer always have a session to act on. Sketch on a picked flat face or reference plane opens
@@ -200,6 +200,10 @@ bases, and nothing for the other methods, where a click on a plane would rewrite
references. The `P` and `A` keys are a separate, unpickable view helper and do not follow the
Origin row.
+The Bed row, pinned under the Origin row, is the printer bed's switch in the same way: it draws or
+hides the bed and its plate grid in every mode, and `Ctrl+Shift+B` flips it from the keyboard. It
+is a view preference in AppConfig too, and the bed is shown until it is turned off.
+
## Rendering the bodies
The tab draws its bodies through the same `GLCanvas3D` object path as Prepare, so how they look
@@ -273,7 +277,7 @@ The tab is a page of Orca's main window and answers to the same settings as Prep
hover background on macOS. The Feature tree and Bodies lists are a custom-drawn
`DesignRowList` rather than a `wxTreeCtrl`, so each row carries its own actions — Edit,
Show/hide and Delete on a feature, Move, Show/hide and Delete on a body, and only Show/hide on
- the Origin row above the features — and the eye shows whether that row is hidden.
+ the Origin and Bed rows above the features — and the eye shows whether that row is hidden.
- **Plates.** This is the one thing the tab does not follow. The canvas has a bed of its own at
the printer bed's home position, whichever plate Prepare has current, and a new document's
modeling origin is that bed's centre. A bed that followed the current plate would slide out
diff --git a/resources/images/design_bed.svg b/resources/images/design_bed.svg
new file mode 100644
index 0000000000..a9441e7b5d
--- /dev/null
+++ b/resources/images/design_bed.svg
@@ -0,0 +1 @@
+
diff --git a/scripts/CAD/check-gui-click-edit.py b/scripts/CAD/check-gui-click-edit.py
index b0ee63dee9..5eb9b3c4f2 100755
--- a/scripts/CAD/check-gui-click-edit.py
+++ b/scripts/CAD/check-gui-click-edit.py
@@ -147,6 +147,7 @@ def seed_datadir(datadir):
# ~90% case expects. A ladder whose result depends on the developer's own preferences is not
# a gate.
app["auto_close_sketch_loops"] = True
+ app["design_show_bed"] = True
# SILENCE THE NETWORK PLUGIN PROMPT. Without this, GUI_App::post_init() re-raises "Bambu
# Network Plug-in Required" from an IDLE event — after any modal sweep this driver does at
# startup — and ShowModal() then runs a nested event loop. The app is alive, its window is
diff --git a/scripts/CAD/check-gui-sketching.py b/scripts/CAD/check-gui-sketching.py
index 9d8729c49f..b3c4514499 100644
--- a/scripts/CAD/check-gui-sketching.py
+++ b/scripts/CAD/check-gui-sketching.py
@@ -229,9 +229,18 @@ CHROME_DY = int(os.environ.get("ORCA_CAD_CHROME_DY", "26"))
DESIGN_TAB = (128, 29 + CHROME_DY)
+# The ribbon's document group lost its Bed checkbox and label when the bed toggle moved to the
+# Feature tree, and every group to its right moved left by their width: wxLEFT 6 + the 18 px
+# CheckBox + wxLEFT 4 + the "Bed" label (~24 px) + wxRIGHT 4, about 56 px. The x of
+# CONSTRUCTION_CHECKBOX, CON_BTN and CON_BTN_SKETCH below is the one measured before that, plus
+# this. DERIVED, NOT MEASURED: re-measure on the rig and fold it in. CONFIRM_BTN sits after the
+# ribbon's stretch spacer and did not move.
+RIBBON_DX = -56
+
# Feature-tree rows, measured on the rig at 1920x1080: the list's first row is centred at y=215,
-# then 23 px apart. That first row is the Origin, pinned above the features and never deleted, so
-# the first FEATURE row is the second one: Delete on the Origin does nothing.
+# then 23 px apart. The first two rows are the Origin and the Bed, pinned above the features and
+# never deleted, so the first FEATURE row is the third one. Delete and double-click do nothing on
+# a pinned row, and reset_document and the reopening double-click both need a feature.
# x=300, not the label: a second click ON the label opens the inline rename, and Delete then
# edits the text instead of removing the feature.
#
@@ -239,7 +248,7 @@ DESIGN_TAB = (128, 29 + CHROME_DY)
# unshifted click lands 26 px BELOW the first row -- just past its 23 px height -- so the row is
# never selected, Delete does nothing, and reset_document spends 40 rounds on it before dying
# with "could not empty the feature tree". That names the feature tree, which is not the fault.
-TREE_ROW0 = (300, 215 + 23 + CHROME_DY)
+TREE_ROW0 = (300, 215 + 2 * 23 + CHROME_DY)
def go_design():
@@ -742,7 +751,7 @@ def corner_pair(ents):
die("no adjacent pair in what should be a rectangle")
-CONSTRUCTION_CHECKBOX = (419, 75 + CHROME_DY)
+CONSTRUCTION_CHECKBOX = (419 + RIBBON_DX, 75 + CHROME_DY)
def draw_line(x0, y0, x1, y1, length, angle):
@@ -871,7 +880,7 @@ def rung_extend():
# because the ladder only ever clicks "perpendicular" (3) and "equal" (5), both of which sit
# before the first insertion. The next rung to use "tangent" would have clicked "collinear".
CON_BTN_Y = 76 + CHROME_DY
-CON_BTN = {n: (449 + 42 * i, CON_BTN_Y) for i, n in enumerate(
+CON_BTN = {n: (449 + RIBBON_DX + 42 * i, CON_BTN_Y) for i, n in enumerate(
["horizontal", "vertical", "parallel", "perpendicular", "coincident", "equal",
"equal_radius", "collinear", "concentric", "tangent", "midpoint", "symmetric",
"sym_v", "sym_h", "angle", "radius", "diameter", "fix", "dist_x", "dist_y"])}
@@ -885,7 +894,7 @@ CON_BTN = {n: (449 + 42 * i, CON_BTN_Y) for i, n in enumerate(
# which already carries CHROME_DY), but the X start depends on how wide the sketch toolbar to the
# left of this group renders, and this fork keeps mainline's top row. Re-measure before trusting
# D11 here: screenshot in sketch mode and detect the icon columns, do not derive it by offset.
-CON_BTN_SKETCH = {n: (677 + 42 * i, CON_BTN_Y) for i, n in enumerate(
+CON_BTN_SKETCH = {n: (677 + RIBBON_DX + 42 * i, CON_BTN_Y) for i, n in enumerate(
["horizontal", "vertical", "parallel", "perpendicular", "coincident", "equal",
"equal_radius", "collinear", "concentric", "tangent", "midpoint", "symmetric",
"sym_v", "sym_h", "angle", "radius", "diameter", "fix", "dist_x", "dist_y"])}
diff --git a/src/libslic3r/AppConfig.cpp b/src/libslic3r/AppConfig.cpp
index 663072d866..31cc17b97d 100644
--- a/src/libslic3r/AppConfig.cpp
+++ b/src/libslic3r/AppConfig.cpp
@@ -367,6 +367,10 @@ void AppConfig::set_defaults()
// restores the conventional CAD representation for users who expect it (x0kd).
if (get("design_connector_face_glyph").empty())
set_bool("design_connector_face_glyph", true);
+
+ // Design tab: draw the printer bed and its plate grid (the Feature tree's Bed row).
+ if (get("design_show_bed").empty())
+ set_bool("design_show_bed", true);
#endif
//#ifdef SUPPORT_SHOW_HINTS
diff --git a/src/slic3r/GUI/CAD/DesignPanel.cpp b/src/slic3r/GUI/CAD/DesignPanel.cpp
index ac9b5d59d6..964e1f23ca 100644
--- a/src/slic3r/GUI/CAD/DesignPanel.cpp
+++ b/src/slic3r/GUI/CAD/DesignPanel.cpp
@@ -285,9 +285,10 @@ static std::string commit_icon(bool bodies)
// The icons on each Feature tree and Bodies row (DesignRowList::Action::id).
enum RowAction { RowEdit, RowMove, RowVisibility, RowDelete };
-// The Feature tree's first row is the Origin, pinned above the features: feature i is row i + 1.
-static constexpr int kFeatureRow0 = 1;
-// The feature a Feature tree row shows, or wxNOT_FOUND for the Origin row (and for no row).
+// The Feature tree's first two rows are the Origin and the Bed, pinned above the features:
+// feature i is row i + kFeatureRow0.
+static constexpr int kOriginRow = 0, kBedRow = 1, kFeatureRow0 = 2;
+// The feature a Feature tree row shows, or wxNOT_FOUND for a pinned row (and for no row).
static int feature_of_row(int row) { return row >= kFeatureRow0 ? row - kFeatureRow0 : wxNOT_FOUND; }
// A row's eye shows the state the row is in; its tip names what a click does.
@@ -302,6 +303,13 @@ static wxString origin_toggle_text(bool shown)
return shown ? _L("Hide reference planes and axes") : _L("Show reference planes and axes");
}
+// What the Bed row's eye and its menu item do.
+static wxString bed_toggle_text(bool shown)
+{
+ return shown ? _L("Hide the printer bed and its plate grid")
+ : _L("Show the printer bed and its plate grid");
+}
+
// What Sketch asks for while it waits for a plane (DesignPanel::start_sketch).
static wxString sketch_plane_prompt()
{
@@ -611,17 +619,14 @@ DesignPanel::DesignPanel(wxWindow* parent)
set_status(_L("Axonometric view, fitted"));
};
- // Commit to Plate and the bed toggle were mouse-only: a toolbar button and a checkbox with
- // no accelerator between them, so neither could be reached from the keyboard at all, nor by
- // anything driving the keyboard. Ctrl+Shift+P is Plate, Ctrl+Shift+B is Bed; neither
+ // Commit to Plate and the bed toggle are mouse targets — a toolbar button and the Feature
+ // tree's Bed row — so without an accelerator neither could be reached from the keyboard, nor
+ // by anything driving the keyboard. Ctrl+Shift+P is Plate, Ctrl+Shift+B is Bed; neither
// collides with Orca's own Ctrl+Shift+S (Save as) or Ctrl+Shift+G (Print plate).
m_keys_feature['P' | SC_SHIFT | SC_CTRL] = [this] { on_commit(); };
m_keys_feature['B' | SC_SHIFT | SC_CTRL] = [this] {
- if (!m_show_bed) return;
- const bool show = !m_show_bed->GetValue();
- m_show_bed->SetValue(show);
- if (m_viewport) m_viewport->set_show_bed(show);
- set_status(show ? _L("Bed shown") : _L("Bed hidden"));
+ toggle_bed();
+ set_status(m_show_bed ? _L("Bed shown") : _L("Bed hidden"));
};
// Flyout rows show the design_* glyphs as they are: drawn in Orca's icon grey (#949494), which
@@ -1518,10 +1523,10 @@ DesignPanel::DesignPanel(wxWindow* parent)
}
m_viewport->set_sketch_construction(m_construction->GetValue()); });
// STAYS on the bar. Construction is not a tool, it is a persistent MODE — the same kind
- // of thing as the Bed checkbox — and the sketch bar is already shown only in Sketch mode,
- // so it appears exactly while it can apply. Hiding it left Q and the offer's Construction
- // row still toggling a checkbox nobody could see: you could not tell whether the next
- // line would be construction geometry. A stateful toggle has to show its state.
+ // of thing as the Feature tree's Bed row — and the sketch bar is already shown only in
+ // Sketch mode, so it appears exactly while it can apply. Hiding it left Q and the offer's
+ // Construction row still toggling a checkbox nobody could see: you could not tell whether
+ // the next line would be construction geometry. A stateful toggle has to show its state.
sadd_bar(m_construction);
add_sep(m_tb_sketch);
auto* b_del = icon_btn("design_delete", _L("Delete selected"));
@@ -1629,23 +1634,6 @@ DesignPanel::DesignPanel(wxWindow* parent)
b_export->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { on_export_step(); });
add_doc(b_export);
- // View option, not a document action: hide the printer bed to model without it. Lives in
- // this row because it must stay reachable with no tool open — a card would come and go.
- m_show_bed = new CheckBox(m_toolbar);
- m_show_bed->SetValue(true); // bed visible by default, as the tab opens today
- m_show_bed->SetToolTip(_L("Show the printer bed and its plate grid"));
- // wxEVT_TOGGLEBUTTON, NOT wxEVT_CHECKBOX: Orca's CheckBox derives from
- // wxBitmapToggleButton (Widgets/CheckBox.hpp), so a wxEVT_CHECKBOX handler never fires.
- // Read the control rather than the event so the state cannot disagree with the glyph.
- m_show_bed->Bind(wxEVT_TOGGLEBUTTON, [this](wxCommandEvent& e) {
- if (m_viewport) m_viewport->set_show_bed(m_show_bed->GetValue());
- e.Skip();
- });
- auto* bed_lbl = new wxStaticText(m_toolbar, wxID_ANY, _L("Bed"));
- bed_lbl->SetForegroundColour(dp_sec_text());
- m_tb_doc->Add(m_show_bed, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, 6);
- m_tb_doc->Add(bed_lbl, 0, wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT, 4);
-
// These act on bodies / the view, so they ride in the feature group, in the slots
// the user assigned them (9, 11bis, 16).
auto* b_place = doc_btn("toolbar_flatten", _L("Place on Face (F) — lay the picked face on the bed"),
@@ -3155,7 +3143,7 @@ DesignPanel::DesignPanel(wxWindow* parent)
// "the target" — but ONLY when this tree has a selection. Each list notifies on every
// change, so clicking a body row runs apply_body_row, whose m_tree->unselect() fires
// THIS handler, which would otherwise clear the body row the user had just clicked. The
- // Origin row counts: it is a selected row like any other.
+ // pinned Origin and Bed rows count: they are selected rows like any other.
if (m_parts && m_tree->selection() != wxNOT_FOUND) m_parts->unselect();
const int sel = tree_selection();
// Likewise a viewport pick, which would be drawn just like the feature's faces. Not while
@@ -3178,17 +3166,18 @@ DesignPanel::DesignPanel(wxWindow* parent)
};
// Double-click a row = Edit, the same gesture that re-opens a committed sketch on the canvas.
- // The Origin row has nothing to edit.
+ // The pinned rows have nothing to edit.
m_tree->on_activate = [this] {
if (tree_selection() != wxNOT_FOUND) on_edit_feature();
};
// The row's own Edit / Show-hide / Delete, on the row the click selected. The body list is
// cleared here too, not left to on_select, which re-clicking the selected row does not run:
- // a body row still selected would be what on_toggle_visibility acts on. The Origin row's one
+ // a body row still selected would be what on_toggle_visibility acts on. A pinned row's one
// icon is its eye.
m_tree->on_action = [this](int row, int id) {
- if (feature_of_row(row) == wxNOT_FOUND) { toggle_origin(); return; }
+ if (row == kOriginRow) { toggle_origin(); return; }
+ if (row == kBedRow) { toggle_bed(); return; }
if (m_parts) m_parts->unselect();
switch (id) {
case RowEdit: on_edit_feature(); break;
@@ -3202,13 +3191,14 @@ DesignPanel::DesignPanel(wxWindow* parent)
// a sketch tries the row, and the row answers.
m_tree->on_menu = [this](int row, const wxPoint& screen) {
wxMenu menu;
- // The Origin row is no feature: it cannot be renamed, edited, moved or deleted, and its
+ // A pinned row is no feature: it cannot be renamed, edited, moved or deleted, and its
// menu holds exactly what its eye does.
const int feat = feature_of_row(row);
if (feat == wxNOT_FOUND) {
- const int id_origin = wxWindow::NewControlId();
- menu.Append(id_origin, origin_toggle_text(m_show_origin));
- menu.Bind(wxEVT_MENU, [this](wxCommandEvent&) { toggle_origin(); }, id_origin);
+ const bool bed = (row == kBedRow);
+ const int id_toggle = wxWindow::NewControlId();
+ menu.Append(id_toggle, bed ? bed_toggle_text(m_show_bed) : origin_toggle_text(m_show_origin));
+ menu.Bind(wxEVT_MENU, [this, bed](wxCommandEvent&) { bed ? toggle_bed() : toggle_origin(); }, id_toggle);
m_tree->PopupMenu(&menu, m_tree->ScreenToClient(screen));
return;
}
@@ -4431,8 +4421,10 @@ DesignPanel::DesignPanel(wxWindow* parent)
}
m_show_origin = wxGetApp().app_config->get_bool("design_show_origin");
+ m_show_bed = wxGetApp().app_config->get_bool("design_show_bed");
+ if (m_viewport) m_viewport->set_show_bed(m_show_bed);
set_ui_mode(UiMode::Feature);
- // The Origin row from the first paint: nothing else builds the rows before the first edit,
+ // The pinned rows from the first paint: nothing else builds the rows before the first edit,
// project load or theme switch.
refresh_tree();
build_phase("wiring");
@@ -4542,8 +4534,8 @@ void DesignPanel::set_ui_mode(UiMode m)
// Seen on the rig: pick XY, arm Line, and the viewport is an empty grey field — no bed, no
// grid, no origin, nothing to judge a length or a direction against. The plate grid was
// carrying the ground reference for the whole tab. The banner already says where you are;
- // taking the floor away as well only made the sketch harder to draw. The Bed checkbox is the
- // one thing that governs the bed, in every mode.
+ // taking the floor away as well only made the sketch harder to draw. The Feature tree's Bed
+ // row is the one thing that governs the bed, in every mode.
if (m_sketch_banner != nullptr) {
const bool sketching = (m == UiMode::Sketch);
if (sketching && m_sketch_banner_txt != nullptr)
@@ -7532,7 +7524,7 @@ void DesignPanel::refresh_tree()
// Preserve the selected row across the rebuild — set_rows() drops the selection, which made
// every edit/add feel like it "lost" the selection (and broke Edit/Move/Delete on the
- // just-touched feature). By row, so a selected Origin row stays selected too.
+ // just-touched feature). By row, so a selected pinned row stays selected too.
const int keep = m_tree->selection();
// Datum/reference planes carry no solid; feed them to the viewport so they render as
@@ -7541,10 +7533,15 @@ void DesignPanel::refresh_tree()
update_reference_planes();
std::vector rows;
rows.reserve(m_doc.features.size() + kFeatureRow0);
- // Always first and never removable: the reference planes' own switch, and nothing else.
- DesignRowList::Action origin_eye = eye_action(m_show_origin);
- origin_eye.tip = origin_toggle_text(m_show_origin);
- rows.push_back({ "design_plane", _L("Origin"), {}, dp_item_text(), { origin_eye } });
+ // Always first, in kOriginRow / kBedRow order, and never removable: the reference planes' and
+ // the printer bed's own switches, and nothing else.
+ auto add_pinned = [&rows](const char* icon, const wxString& label, bool shown, const wxString& tip) {
+ DesignRowList::Action eye = eye_action(shown);
+ eye.tip = tip;
+ rows.push_back({ icon, label, {}, dp_item_text(), { eye } });
+ };
+ add_pinned("design_plane", _L("Origin"), m_show_origin, origin_toggle_text(m_show_origin));
+ add_pinned("design_bed", _L("Bed"), m_show_bed, bed_toggle_text(m_show_bed));
for (size_t fi = 0; fi < m_doc.features.size(); ++fi) {
const CadFeature& f = m_doc.features[fi];
DesignRowList::Row row;
@@ -11128,6 +11125,14 @@ void DesignPanel::toggle_origin()
refresh_tree(); // the Origin row's eye, and update_reference_planes(), which repaints
}
+void DesignPanel::toggle_bed()
+{
+ m_show_bed = !m_show_bed;
+ wxGetApp().app_config->set_bool("design_show_bed", m_show_bed);
+ if (m_viewport) m_viewport->set_show_bed(m_show_bed); // repaints
+ refresh_tree(); // the Bed row's eye
+}
+
void DesignPanel::start_sketch()
{
if (m_ui_mode != UiMode::Feature) return; // already sketching or constraining
diff --git a/src/slic3r/GUI/CAD/DesignPanel.hpp b/src/slic3r/GUI/CAD/DesignPanel.hpp
index 5f31d0fbeb..013de06fc8 100644
--- a/src/slic3r/GUI/CAD/DesignPanel.hpp
+++ b/src/slic3r/GUI/CAD/DesignPanel.hpp
@@ -385,6 +385,7 @@ private:
void refresh_mate_connectors(); // push connector frames so verse + polarity are visible
void update_reference_planes(); // the XY/XZ/YZ planes + axes: Origin row, plane choice, Plane tool
void toggle_origin(); // the Origin row's eye: keep the reference planes up, or not
+ void toggle_bed(); // the Bed row's eye (and Ctrl+Shift+B): draw the printer bed, or not
// Sketch: open a session on the picked face or plane, or with none picked, put the planes up
// and wait for one (m_choosing_sketch_plane).
void start_sketch();
@@ -420,7 +421,6 @@ private:
ScalableButton* m_commit_btn{nullptr}; // main face: runs the current commit mode
DropDown* m_commit_drop{nullptr}; // commit-mode choices, owned via m_flyout_keepalive
wxSizer* m_tb_doc{nullptr}; // toolbar document/view actions (new, commit, export, section, place)
- CheckBox* m_show_bed{nullptr}; // view option: draw the printer bed + plate grid, or not
wxSizer* m_box_move{nullptr}; // Move/Rotate numeric options (distance, axis, angle)
wxSizer* m_box_sketch{nullptr};
wxSizer* m_box_extrude{nullptr};
@@ -589,6 +589,9 @@ private:
// (update_reference_planes). A view preference (AppConfig "design_show_origin"), not part of
// the recipe.
bool m_show_origin{false};
+ // The Feature tree's Bed row: draws the printer bed and its plate grid. A view preference
+ // (AppConfig "design_show_bed"), not part of the recipe.
+ bool m_show_bed{true};
ComboBox* m_shape{nullptr};
ComboBox* m_mode{nullptr};
wxSpinCtrlDouble* m_width{nullptr};
@@ -929,9 +932,10 @@ private:
std::function m_value_cont; // deferred apply, run on Confirm
std::function m_value_cancel; // optional action when the card is cancelled
- // Feature tree: the Origin row, then one row per feature, in feature order, with a per-type
- // icon and the row's own Edit / Show-hide / Delete icons. Feature i is row i + 1; callers use
- // feature indices via tree_selection()/set_tree_selection(); refresh_tree() rebuilds the rows.
+ // Feature tree: the pinned Origin and Bed rows, then one row per feature, in feature order,
+ // with a per-type icon and the row's own Edit / Show-hide / Delete icons. Feature i is row
+ // i + 2; callers use feature indices via tree_selection()/set_tree_selection();
+ // refresh_tree() rebuilds the rows.
DesignRowList* m_tree{nullptr};
// The faces the selected feature row made (CadDocument::faces_made_by), drawn as selected.
// Finding them replays the history, so they are kept per row and topology generation.
@@ -986,7 +990,7 @@ private:
void arm_transform_gizmo(); // arm the move gizmo on the Transform card's body (add mode only)
void on_set_body_color(); // Color tool: pick a per-body display colour override
void on_boolean_tool(); // Boolean (combine bodies): needs two solids, then opens the tool
- int tree_selection() const; // selected feature's index, or wxNOT_FOUND (none, or the Origin row)
+ int tree_selection() const; // selected feature's index, or wxNOT_FOUND (none, or a pinned row)
int tree_body_selection() const; // selected Parts-list body index, or -1
void refresh_parts(); // rebuild the Bodies list under the feature tree
void set_tree_selection(int feature);