Compare commits

..
Author SHA1 Message Date
Hanif Koh 138fa26847 Support the 02.08.04 Bambu Network Plug-in Series
The 02.08.02 series appended queue_plate_id to PrintParams and nothing
after it changed the ABI OrcaSlicer calls, so adding the field brings
the current layout up to 02.08.04. Make 02.08.04 the latest series and
drop 02.08.01 from the whitelist: its PrintParams no longer matches, and
its malformed bind table is refused by dyld on macOS 27, so it cannot
load there. A stored 02.08.01 falls back to the latest series through
the existing unsupported-version path.
2026-10-06 17:20:11 +08:00
7 changed files with 73 additions and 76 deletions
-5
View File
@@ -4,10 +4,5 @@
<dict>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
<!-- The Bambu network plug-in's code protector rewrites one of its own signed code pages
after loading. Under the hardened runtime macOS kills the process when that page is
paged back in; this lets it run, as Bambu Studio's signature does. -->
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
</dict>
</plist>
@@ -5,10 +5,5 @@
<!-- for dynamic loading of libraries without signature validation. Used for 3dconnection drivers.-->
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
<!-- The Bambu network plug-in's code protector rewrites one of its own signed code pages
after loading. Under the hardened runtime macOS kills the process when that page is
paged back in; this lets it run, as Bambu Studio's signature does. -->
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
</dict>
</plist>
+27 -26
View File
@@ -41,20 +41,19 @@ namespace GUI
ObjectLayers::ObjectLayers(wxWindow* parent) :
OG_Settings(parent, true)
{
m_grid_sizer = new wxFlexGridSizer(5, parent ? parent->FromDIP(2) : 2, wxGetApp().em_unit()); // Title, Min Z, "to", Max Z, buttons sizer
m_grid_sizer = new wxFlexGridSizer(5, 0, wxGetApp().em_unit()); // Title, Min Z, "to", Max Z, unit & buttons sizer
m_grid_sizer->SetFlexibleDirection(wxHORIZONTAL);
m_grid_sizer->AddGrowableCol(1);
m_grid_sizer->AddGrowableCol(3);
m_og->activate();
m_og->sizer->Clear(true);
m_og->sizer->Add(m_grid_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, parent ? parent->FromDIP(2) : 2);
m_og->sizer->Add(m_grid_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, 5);
if (auto stb = dynamic_cast<LabeledStaticBox*>(m_og->stb))
stb->SetCornerRadius(0);
m_bmp_delete = ScalableBitmap(parent, "delete");
m_bmp_add = ScalableBitmap(parent, "add");
m_bmp_layer = ScalableBitmap(parent, "height_range_layer");
}
void ObjectLayers::select_editor(LayerRangeEditor* editor, const bool is_last_edited_range)
@@ -96,14 +95,10 @@ wxSizer* ObjectLayers::create_layer(const t_layer_height_range& range, PlusMinus
};
// Add text
auto title_sizer = new wxBoxSizer(wxHORIZONTAL);
auto head_text = new wxStaticText(m_og->ctrl_parent(), wxID_ANY, _L("Range"));
auto head_text = new wxStaticText(m_og->ctrl_parent(), wxID_ANY, _L("Height Range"), wxDefaultPosition, wxDefaultSize, wxST_ELLIPSIZE_END);
head_text->SetBackgroundStyle(wxBG_STYLE_PAINT);
head_text->SetFont(wxGetApp().normal_font());
auto icon = new wxStaticBitmap(m_og->ctrl_parent(), wxID_ANY, m_bmp_layer.bmp());
title_sizer->Add(icon, 0, wxALIGN_CENTER_VERTICAL);
title_sizer->Add(head_text, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, m_og->ctrl_parent()->FromDIP(5));
m_grid_sizer->Add(title_sizer, 0, wxALIGN_CENTER_VERTICAL);
m_grid_sizer->Add(head_text, 0, wxALIGN_CENTER_VERTICAL);
// Add control for the "Min Z"
@@ -131,7 +126,7 @@ wxSizer* ObjectLayers::create_layer(const t_layer_height_range& range, PlusMinus
m_grid_sizer->Add(editor, 1, wxEXPAND);
auto middle_text = new wxStaticText(m_og->ctrl_parent(), wxID_ANY, "-");
auto middle_text = new wxStaticText(m_og->ctrl_parent(), wxID_ANY, _L("to"), wxDefaultPosition, wxDefaultSize, wxST_ELLIPSIZE_END);
middle_text->SetBackgroundStyle(wxBG_STYLE_PAINT);
middle_text->SetFont(wxGetApp().normal_font());
m_grid_sizer->Add(middle_text, 0, wxALIGN_CENTER_VERTICAL);
@@ -161,6 +156,11 @@ wxSizer* ObjectLayers::create_layer(const t_layer_height_range& range, PlusMinus
m_grid_sizer->Add(editor, 1, wxEXPAND);
auto sizer2 = new wxBoxSizer(wxHORIZONTAL);
auto unit_text = new wxStaticText(m_og->ctrl_parent(), wxID_ANY, _L("mm"), wxDefaultPosition, wxDefaultSize, wxST_ELLIPSIZE_END);
unit_text->SetBackgroundStyle(wxBG_STYLE_PAINT);
unit_text->SetFont(wxGetApp().normal_font());
sizer2->Add(unit_text, 0, wxALIGN_CENTER_VERTICAL);
m_grid_sizer->Add(sizer2, 0, wxALIGN_CENTER_VERTICAL);
// BBS
@@ -205,9 +205,8 @@ void ObjectLayers::create_layers_list()
auto sizer = create_layer(range, del_btn, add_btn);
auto b_sizer = new wxBoxSizer(wxHORIZONTAL);
b_sizer->Add(del_btn, 0, wxLEFT, m_og->ctrl_parent()->FromDIP(5));
b_sizer->AddSpacer(m_og->ctrl_parent()->FromDIP(15));
b_sizer->Add(add_btn, 0, wxRIGHT, m_og->ctrl_parent()->FromDIP(5));
b_sizer->Add(del_btn, 0, wxRIGHT | wxLEFT, em_unit(m_parent));
b_sizer->Add(add_btn);
sizer->Add(b_sizer, 0, wxALIGN_CENTER_HORIZONTAL | wxTOP, m_parent->FromDIP(1)); // aligns +/- buttons vertically since we got 1px gap on bottom of icons
del_btn->Bind(wxEVT_BUTTON, [del_btn](wxEvent &) {
@@ -278,7 +277,6 @@ void ObjectLayers::msw_rescale()
{
m_bmp_delete.msw_rescale();
m_bmp_add.msw_rescale();
m_bmp_layer.msw_rescale();
m_grid_sizer->SetHGap(wxGetApp().em_unit());
@@ -369,17 +367,20 @@ LayerRangeEditor::LayerRangeEditor( ObjectLayers* parent,
m_valid_value(value),
m_type(type),
m_set_focus_data(set_focus_data_fn),
TextInput(parent->m_og->ctrl_parent(), value, _L("mm"), "", wxDefaultPosition, wxSize(em_unit(parent->m_parent), wxDefaultCoord), wxTE_PROCESS_ENTER)
wxTextCtrl(parent->m_og->ctrl_parent(), wxID_ANY, value, wxDefaultPosition,
wxSize(em_unit(parent->m_parent), wxDefaultCoord), wxTE_PROCESS_ENTER
#ifdef _WIN32
| wxBORDER_SIMPLE
#endif
)
{
this->SetFont(wxGetApp().normal_font());
wxGetApp().UpdateDarkUI(this);
wxTextCtrl* ctrl = GetTextCtrl();
// Reset m_enter_pressed flag to _false_, when value is editing
ctrl->Bind(wxEVT_TEXT, [this](wxEvent&) { m_enter_pressed = false; }, ctrl->GetId());
this->Bind(wxEVT_TEXT, [this](wxEvent&) { m_enter_pressed = false; }, this->GetId());
ctrl->Bind(wxEVT_TEXT_ENTER, [this, edit_fn](wxCommandEvent& e)
this->Bind(wxEVT_TEXT_ENTER, [this, edit_fn](wxEvent&)
{
m_enter_pressed = true;
// If LayersList wasn't updated/recreated, we can call wxEVT_KILL_FOCUS.Skip()
@@ -394,9 +395,9 @@ LayerRangeEditor::LayerRangeEditor( ObjectLayers* parent,
SetValue(m_valid_value);
m_call_kill_focus = true;
}
}, ctrl->GetId());
}, this->GetId());
ctrl->Bind(wxEVT_KILL_FOCUS, [this, edit_fn](wxFocusEvent& e)
this->Bind(wxEVT_KILL_FOCUS, [this, edit_fn](wxFocusEvent& e)
{
if (!m_enter_pressed) {
#ifndef __WXGTK__
@@ -425,14 +426,14 @@ LayerRangeEditor::LayerRangeEditor( ObjectLayers* parent,
m_call_kill_focus = false;
e.Skip();
}
}, ctrl->GetId());
}, this->GetId());
ctrl->Bind(wxEVT_SET_FOCUS, [this, parent](wxFocusEvent& e)
this->Bind(wxEVT_SET_FOCUS, [this, parent](wxFocusEvent& e)
{
set_focus_data();
parent->update_scene_from_editor_selection();
e.Skip();
}, ctrl->GetId());
}, this->GetId());
#ifdef __WXGTK__ // Workaround! To take information about selectable range
this->Bind(wxEVT_LEFT_DOWN, [this](wxEvent& e)
@@ -446,7 +447,7 @@ LayerRangeEditor::LayerRangeEditor( ObjectLayers* parent,
{
// select all text using Ctrl+A
if (wxGetKeyState(wxKeyCode('A')) && wxGetKeyState(WXK_CONTROL))
GetTextCtrl()->SetSelection(-1, -1); //select all
this->SetSelection(-1, -1); //select all
event.Skip();
}));
}
@@ -476,7 +477,7 @@ coordf_t LayerRangeEditor::get_value()
void LayerRangeEditor::msw_rescale()
{
Rescale();
SetMinSize(wxSize(wxGetApp().em_unit(), wxDefaultCoord));
}
} //namespace GUI
+1 -6
View File
@@ -9,8 +9,6 @@
#include <wx/sizer.h>
#include <wx/event.h>
#include <slic3r/GUI/Widgets/TextInput.hpp>
#ifdef __WXOSX__
#include "libslic3r/PrintConfig.hpp"
#endif
@@ -36,7 +34,7 @@ enum EditorType
etLayerHeight = 4,
};
class LayerRangeEditor : public TextInput
class LayerRangeEditor : public wxTextCtrl
{
bool m_enter_pressed { false };
bool m_call_kill_focus { false };
@@ -57,8 +55,6 @@ public:
EditorType type() const {return m_type;}
void set_focus_data() const { m_set_focus_data(m_type);}
void SetValue(const wxString& value) {GetTextCtrl()->SetValue(value);}
wxString GetValue() {return GetTextCtrl()->GetValue();}
void msw_rescale();
private:
@@ -69,7 +65,6 @@ class ObjectLayers : public OG_Settings
{
ScalableBitmap m_bmp_delete;
ScalableBitmap m_bmp_add;
ScalableBitmap m_bmp_layer;
ModelObject* m_object {nullptr};
wxFlexGridSizer* m_grid_sizer;
+2 -1
View File
@@ -596,7 +596,8 @@ PrintParams_Legacy BBLNetworkPlugin::as_legacy(PrintParams& param)
}
// Every PrintParams field except the four the 02.08.01 series added
// (task_timelapse_use_internal, extruder_cali_manual_mode, svc_context, slicer_uid).
// (task_timelapse_use_internal, extruder_cali_manual_mode, svc_context, slicer_uid) and the
// queue_plate_id 02.08.02 appended.
PrintParams_0203 BBLNetworkPlugin::as_0203(PrintParams& param)
{
PrintParams_0203 p;
+7 -4
View File
@@ -336,6 +336,7 @@ struct PrintParams {
bool try_emmc_print;
std::string svc_context;
std::string slicer_uid;
std::string queue_plate_id;
};
struct TaskQueryParams
@@ -412,7 +413,7 @@ enum class NetworkAbi {
Unsupported, // no generation in this build can call it - never dispatch through it
Legacy, // 01.10.01: PrintParams_Legacy; send_message/send_message_to_printer take no flag
V0203, // 02.03.00: PrintParams_0203; bind takes no dev_model
Current, // 02.08.01: the layouts and signatures this build declares directly
Current, // 02.08.04: the layouts and signatures this build declares directly
};
struct NetworkLibraryVersion {
@@ -425,10 +426,12 @@ struct NetworkLibraryVersion {
};
// Every row names the generation that can call it, so a series can never be offered without a
// host-side ABI for it. Series with no generation - 02.01.01, 02.00.02 and older - must stay out;
// is_supported_network_version() is the gate that keeps them from loading.
// host-side ABI for it. Series with no generation - 02.08.01 (whose PrintParams lacks the
// queue_plate_id that 02.08.02 appended, and whose malformed bind table macOS 27 refuses to
// load), 02.01.01, 02.00.02 and older - must stay out; is_supported_network_version() is the
// gate that keeps them from loading.
static const NetworkLibraryVersion AVAILABLE_NETWORK_VERSIONS[] = {
{"02.08.01", "02.08.01", nullptr, true, nullptr, NetworkAbi::Current},
{"02.08.04", "02.08.04", nullptr, true, nullptr, NetworkAbi::Current},
{"02.03.00", "02.03.00", nullptr, false,
"An older plug-in series. Features that need newer plug-in support, such as print-failure "
"snapshots in the device error dialog, are unavailable.", NetworkAbi::V0203},
+36 -29
View File
@@ -78,31 +78,34 @@ TEST_CASE("Series and managed classification", "[NetworkVersions]")
TEST_CASE_METHOD(PluginFolderFixture, "Managed builds fold into the series; customs are surfaced", "[NetworkVersions]")
{
add_plugin("02.08.01.55"); // managed, same series -> folded into the 02.08.01 row
add_plugin("02.08.04.60"); // managed, same series -> folded into the 02.08.04 row
add_plugin("02.09.00.10"); // managed, unknown series -> not listed
add_plugin("02.08.01.55"); // managed, series this build no longer has an ABI for -> not listed
add_plugin("02.03.00.62"); // managed, older whitelisted series -> folded into 02.03.00
add_plugin("02.01.01.52"); // managed, series with no ABI in this build -> not listed
add_plugin("02.08.01_custom"); // custom, whitelisted series -> listed under it
add_plugin("02.08.01.52-dev"); // custom (dash-suffixed), whitelisted series -> listed
add_plugin("02.08.04_custom"); // custom, whitelisted series -> listed under it
add_plugin("02.08.04.52-dev"); // custom (dash-suffixed), whitelisted series -> listed
auto versions = get_all_available_versions();
// The specific managed build never gets its own row - the series represents it.
REQUIRE(count_version(versions, "02.08.01.55") == 0);
REQUIRE(count_version(versions, "02.08.01") == 1);
REQUIRE(count_version(versions, "02.08.04.60") == 0);
REQUIRE(count_version(versions, "02.08.04") == 1);
REQUIRE(count_version(versions, "02.09.00.10") == 0);
REQUIRE(count_version(versions, "02.08.01.55") == 0);
REQUIRE(count_version(versions, "02.08.01") == 0);
REQUIRE(count_version(versions, "02.03.00.62") == 0);
REQUIRE(count_version(versions, "02.03.00") == 1);
REQUIRE(count_version(versions, "02.01.01.52") == 0);
// Custom-named builds are distinct files kept under their own name.
REQUIRE(count_version(versions, "02.08.01_custom") == 1);
REQUIRE(count_version(versions, "02.08.01.52-dev") == 1);
REQUIRE(count_version(versions, "02.08.04_custom") == 1);
REQUIRE(count_version(versions, "02.08.04.52-dev") == 1);
// Newest series first, its customs nested under it (suffix sort: "" < ".52-dev" < "_custom"),
// then older series, legacy last.
REQUIRE(versions[0].version == "02.08.01");
REQUIRE(versions[1].version == "02.08.01.52-dev");
REQUIRE(versions[2].version == "02.08.01_custom");
REQUIRE(versions[0].version == "02.08.04");
REQUIRE(versions[1].version == "02.08.04.52-dev");
REQUIRE(versions[2].version == "02.08.04_custom");
REQUIRE(versions[3].version == "02.03.00");
REQUIRE(versions.back().version == BAMBU_NETWORK_AGENT_VERSION_LEGACY);
@@ -111,9 +114,9 @@ TEST_CASE_METHOD(PluginFolderFixture, "Managed builds fold into the series; cust
REQUIRE_FALSE(versions[3].is_latest);
// Customs sort/render nested under their series (non-empty suffix, base = the series).
REQUIRE(versions[1].base_version == "02.08.01");
REQUIRE(versions[1].base_version == "02.08.04");
REQUIRE_FALSE(versions[1].suffix.empty());
REQUIRE(versions[2].base_version == "02.08.01");
REQUIRE(versions[2].base_version == "02.08.04");
REQUIRE_FALSE(versions[2].suffix.empty());
// "(Latest)" is the series row, never a nested custom build.
@@ -123,20 +126,20 @@ TEST_CASE_METHOD(PluginFolderFixture, "Managed builds fold into the series; cust
REQUIRE_FALSE(versions[2].is_latest);
// The stored default that drives download and update-check decisions is now the series.
REQUIRE(std::string(get_latest_network_version()) == "02.08.01");
REQUIRE(std::string(get_latest_network_version()) == "02.08.04");
}
TEST_CASE_METHOD(PluginFolderFixture, "Only the loaded series is marked installed", "[NetworkVersions]")
{
add_plugin("02.08.01.55");
add_plugin("02.08.01_custom");
add_plugin("02.08.04.60");
add_plugin("02.08.04_custom");
// The loaded plug-in reports its full build (02.08.01.55); the series row is what gets marked.
// The loaded plug-in reports its full build (02.08.04.60); the series row is what gets marked.
{
auto versions = get_all_available_versions("02.08.01.55");
auto versions = get_all_available_versions("02.08.04.60");
int marked = 0;
for (const auto& info : versions)
if (info.is_loaded) { ++marked; REQUIRE(info.version == "02.08.01"); }
if (info.is_loaded) { ++marked; REQUIRE(info.version == "02.08.04"); }
REQUIRE(marked == 1);
}
@@ -152,10 +155,10 @@ TEST_CASE_METHOD(PluginFolderFixture, "Only the loaded series is marked installe
// A loaded custom build matches its own row, never the bare series.
{
auto versions = get_all_available_versions("02.08.01_custom");
auto versions = get_all_available_versions("02.08.04_custom");
int marked = 0;
for (const auto& info : versions)
if (info.is_loaded) { ++marked; REQUIRE(info.version == "02.08.01_custom"); }
if (info.is_loaded) { ++marked; REQUIRE(info.version == "02.08.04_custom"); }
REQUIRE(marked == 1);
}
@@ -167,11 +170,11 @@ TEST_CASE_METHOD(PluginFolderFixture, "Only the loaded series is marked installe
TEST_CASE("Only whitelisted series pass the load gate", "[NetworkVersions]")
{
// Each whitelisted series, its builds, and custom-named builds of that series.
REQUIRE(is_supported_network_version("02.08.01"));
REQUIRE(is_supported_network_version("02.08.01.52"));
REQUIRE(is_supported_network_version("02.08.01.55"));
REQUIRE(is_supported_network_version("02.08.01_custom"));
REQUIRE(is_supported_network_version("02.08.01.52-dev"));
REQUIRE(is_supported_network_version("02.08.04"));
REQUIRE(is_supported_network_version("02.08.04.52"));
REQUIRE(is_supported_network_version("02.08.04.60"));
REQUIRE(is_supported_network_version("02.08.04_custom"));
REQUIRE(is_supported_network_version("02.08.04.52-dev"));
REQUIRE(is_supported_network_version("02.03.00"));
REQUIRE(is_supported_network_version("02.03.00.62"));
REQUIRE(is_supported_network_version("02.03.00.70"));
@@ -179,6 +182,9 @@ TEST_CASE("Only whitelisted series pass the load gate", "[NetworkVersions]")
REQUIRE(is_supported_network_version(BAMBU_NETWORK_AGENT_VERSION_LEGACY));
// Series whitelisted by previous Orca releases that no generation here can call.
REQUIRE_FALSE(is_supported_network_version("02.08.01"));
REQUIRE_FALSE(is_supported_network_version("02.08.01.55"));
REQUIRE_FALSE(is_supported_network_version("02.08.01_custom"));
REQUIRE_FALSE(is_supported_network_version("02.01.01.52"));
REQUIRE_FALSE(is_supported_network_version("02.00.02.50"));
@@ -198,9 +204,9 @@ TEST_CASE("Each version resolves to the ABI generation that can call it", "[Netw
{
// The generation is keyed on the series, so every build of a series - including the
// custom-named ones - resolves to the same one.
CHECK(network_plugin_abi("02.08.01") == NetworkAbi::Current);
CHECK(network_plugin_abi("02.08.01.55") == NetworkAbi::Current);
CHECK(network_plugin_abi("02.08.01.52-dev") == NetworkAbi::Current);
CHECK(network_plugin_abi("02.08.04") == NetworkAbi::Current);
CHECK(network_plugin_abi("02.08.04.60") == NetworkAbi::Current);
CHECK(network_plugin_abi("02.08.04.52-dev") == NetworkAbi::Current);
CHECK(network_plugin_abi("02.03.00") == NetworkAbi::V0203);
CHECK(network_plugin_abi("02.03.00.62") == NetworkAbi::V0203);
CHECK(network_plugin_abi("02.03.00_custom") == NetworkAbi::V0203);
@@ -208,6 +214,7 @@ TEST_CASE("Each version resolves to the ABI generation that can call it", "[Netw
// Anything the load gate rejects must dispatch through nothing at all, rather than
// defaulting to a layout it does not share.
CHECK(network_plugin_abi("02.08.01.55") == NetworkAbi::Unsupported);
CHECK(network_plugin_abi("02.01.01.52") == NetworkAbi::Unsupported);
CHECK(network_plugin_abi("02.00.02.50") == NetworkAbi::Unsupported);
CHECK(network_plugin_abi("02.09.00.10") == NetworkAbi::Unsupported);
@@ -234,7 +241,7 @@ TEST_CASE_METHOD(PluginFolderFixture, "Legacy series never adopts discovered bui
// With nothing else on disk, the series holds "(Latest)" even though its library is
// not installed.
for (const auto& info : versions) {
if (info.version == "02.08.01") {
if (info.version == "02.08.04") {
REQUIRE(info.is_latest);
REQUIRE_FALSE(info.is_loaded);
}