mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-26 10:21:00 +00:00
Merge upstream/main into cad-mainline (530 commits)
Catches the fork up from449a4cf9fc(2026-06-28) tod6cb667b89(2026-07-24). Upstream touched 2326 files; 17 of them overlap the 164 this branch touches. 16 of the 17 auto-merged, including all three CMakeLists.txt, the build_all.yml CI workflow, and every GUI file. The CAD core never conflicts: CadDocument, SketchEngine, SketchSolver, McpControl and test_caddocument are files this fork adds, so upstream does not touch them. The one conflict, tests/libslic3r/test_3mf.cpp, was purely additive in all three hunks and is resolved as a union: our test pinning that store_bbs_3mf embeds the CAD recipe as Metadata/SnapOrca_cad.bin, upstream's multi-nozzle plate-metadata round-trip tests, and both sets of includes. All three were verified present after resolution rather than assumed. NOT BUILD-VERIFIED, for a reason that predates this merge and is not caused by it: this fork cannot be configured on nativedev at all. Its CMakeLists has required Eigen3 5.0.1 since before the merge (line 592 pre-merge), while the only deps image on the machine is snaporca-deps, built for snaporca's find_package(Eigen3 3.3). CMake fails at configure, so nothing compiles. That means this fork's Catch2 suite has never run. Every "suite green" figure recorded for M1-M8 was snaporca's suite; the ports were verified by patch-apply plus the CAD sources being byte-identical to snaporca's. Building an orca_cad deps image with Eigen 5.0.1 is what would finally close that gap. Pre-merge state is preserved at branch cad-mainline-pre-upstream-2026-07-25 (30d54f0074). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+224
-12
@@ -3,7 +3,9 @@
|
||||
#include <numeric>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <regex>
|
||||
#include "libslic3r/MultiNozzleUtils.hpp"
|
||||
#include <future>
|
||||
#include <glad/gl.h>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
@@ -66,6 +68,8 @@ static const int PARTPLATE_PLATENAME_OFFSET_Y = 10;
|
||||
const float WIPE_TOWER_DEFAULT_X_POS = 165.;
|
||||
const float WIPE_TOWER_DEFAULT_Y_POS = 250.; // Max y
|
||||
|
||||
const float N9_WIPE_TOWER_DEFAULT_Y_POS = 160.;
|
||||
|
||||
const float I3_WIPE_TOWER_DEFAULT_X_POS = 0.;
|
||||
const float I3_WIPE_TOWER_DEFAULT_Y_POS = 250.; // Max y
|
||||
|
||||
@@ -315,6 +319,18 @@ std::vector<int> PartPlate::get_real_filament_maps(const DynamicConfig& g_config
|
||||
return g_maps;
|
||||
}
|
||||
|
||||
std::vector<int> PartPlate::get_real_filament_volume_maps(const DynamicConfig& g_config, bool* use_global_param) const
|
||||
{
|
||||
auto maps = get_filament_volume_maps();
|
||||
if (!maps.empty()) {
|
||||
if (use_global_param) { *use_global_param = false; }
|
||||
return maps;
|
||||
}
|
||||
auto g_maps = g_config.option<ConfigOptionInts>("filament_volume_map")->values;
|
||||
if (use_global_param) { *use_global_param = true; }
|
||||
return g_maps;
|
||||
}
|
||||
|
||||
FilamentMapMode PartPlate::get_real_filament_map_mode(const DynamicConfig& g_config, bool* use_global_param) const
|
||||
{
|
||||
auto mode = get_filament_map_mode();
|
||||
@@ -385,7 +401,7 @@ void PartPlate::set_spiral_vase_mode(bool spiral_mode, bool as_global)
|
||||
}
|
||||
}
|
||||
|
||||
bool PartPlate::valid_instance(int obj_id, int instance_id)
|
||||
bool PartPlate::valid_instance(int obj_id, int instance_id) const
|
||||
{
|
||||
if ((obj_id >= 0) && (obj_id < m_model->objects.size()))
|
||||
{
|
||||
@@ -1688,7 +1704,7 @@ std::vector<int> PartPlate::get_extruders_under_cli(bool conside_custom_gcode, D
|
||||
int obj_id = it->first;
|
||||
int instance_id = it->second;
|
||||
|
||||
if ((obj_id >= 0) && (obj_id < m_model->objects.size()))
|
||||
if (valid_instance(obj_id, instance_id))
|
||||
{
|
||||
ModelObject* object = m_model->objects[obj_id];
|
||||
ModelInstance* instance = object->instances[instance_id];
|
||||
@@ -1903,6 +1919,17 @@ int PartPlate::get_physical_extruder_by_filament_id(const DynamicConfig& g_confi
|
||||
return the_map->values[zero_base_logical_idx];
|
||||
}
|
||||
|
||||
int PartPlate::get_logical_extruder_by_filament_id(const DynamicConfig& g_config, int idx) const
|
||||
{
|
||||
const std::vector<int>& filament_map = get_real_filament_maps(g_config);
|
||||
if (idx <= 0 || idx > (int)filament_map.size())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return filament_map[idx - 1] - 1;
|
||||
}
|
||||
|
||||
std::vector<int> PartPlate::get_used_filaments()
|
||||
{
|
||||
std::vector<int> used_filaments;
|
||||
@@ -2359,6 +2386,9 @@ void PartPlate::set_pos_and_size(Vec3d& origin, int width, int depth, int height
|
||||
for (std::set<std::pair<int, int>>::iterator it = obj_to_instance_set.begin(); it != obj_to_instance_set.end(); ++it) {
|
||||
int obj_id = it->first;
|
||||
int instance_id = it->second;
|
||||
if (!valid_instance(obj_id, instance_id))
|
||||
continue;
|
||||
|
||||
ModelObject* object = m_model->objects[obj_id];
|
||||
ModelInstance* instance = object->instances[instance_id];
|
||||
|
||||
@@ -2403,6 +2433,9 @@ void PartPlate::set_pos_and_size(Vec3d& origin, int width, int depth, int height
|
||||
m_depth = depth;
|
||||
m_height = height;
|
||||
|
||||
if (with_instance_move && m_plater)
|
||||
m_plater->mark_plate_toolbar_image_dirty();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2629,7 +2662,8 @@ bool PartPlate::check_outside(int obj_id, int instance_id, BoundingBoxf3* boundi
|
||||
|
||||
if (instance_box.min.z() < SINKING_Z_THRESHOLD) {
|
||||
// Orca: For sinking object, we use a more expensive algorithm so part below build plate won't be considered
|
||||
if (plate_box.intersects(instance_box)) {
|
||||
// m_plater is null in CLI mode.
|
||||
if (m_plater && plate_box.intersects(instance_box)) {
|
||||
// TODO: FIXME: this does not take exclusion area into account
|
||||
const BuildVolume build_volume(get_shape(), m_plater->build_volume().printable_height(), m_extruder_areas, m_extruder_heights);
|
||||
const auto state = instance->calc_print_volume_state(build_volume);
|
||||
@@ -2750,6 +2784,8 @@ int PartPlate::add_instance(int obj_id, int instance_id, bool move_position, Bou
|
||||
}
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": plate %1% , m_ready_for_slice changes to %2%") % m_plate_index %m_ready_for_slice;
|
||||
if (m_plater)
|
||||
m_plater->mark_plate_toolbar_image_dirty();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2833,7 +2869,7 @@ void PartPlate::duplicate_all_instance(unsigned int dup_count, bool need_skip, s
|
||||
int obj_id = it->first;
|
||||
int instance_id = it->second;
|
||||
|
||||
if ((obj_id >= 0) && (obj_id < m_model->objects.size()))
|
||||
if (valid_instance(obj_id, instance_id))
|
||||
{
|
||||
ModelObject* object = m_model->objects[obj_id];
|
||||
ModelInstance* instance = object->instances[instance_id];
|
||||
@@ -2866,7 +2902,7 @@ void PartPlate::duplicate_all_instance(unsigned int dup_count, bool need_skip, s
|
||||
int obj_id = it->first;
|
||||
int instance_id = it->second;
|
||||
|
||||
if ((obj_id >= 0) && (obj_id < m_model->objects.size()))
|
||||
if (valid_instance(obj_id, instance_id))
|
||||
{
|
||||
ModelObject* object = m_model->objects[obj_id];
|
||||
ModelInstance* instance = object->instances[instance_id];
|
||||
@@ -2983,8 +3019,8 @@ int PartPlate::printable_instance_size()
|
||||
int obj_id = it->first;
|
||||
int instance_id = it->second;
|
||||
|
||||
if (obj_id >= m_model->objects.size())
|
||||
continue;
|
||||
if (!valid_instance(obj_id, instance_id))
|
||||
continue;
|
||||
|
||||
ModelObject * object = m_model->objects[obj_id];
|
||||
ModelInstance *instance = object->instances[instance_id];
|
||||
@@ -3006,7 +3042,7 @@ bool PartPlate::has_printable_instances()
|
||||
int obj_id = it->first;
|
||||
int instance_id = it->second;
|
||||
|
||||
if (obj_id >= m_model->objects.size())
|
||||
if (!valid_instance(obj_id, instance_id))
|
||||
continue;
|
||||
|
||||
ModelObject* object = m_model->objects[obj_id];
|
||||
@@ -3030,7 +3066,8 @@ bool PartPlate::is_all_instances_unprintable()
|
||||
int obj_id = it->first;
|
||||
int instance_id = it->second;
|
||||
|
||||
if (obj_id >= m_model->objects.size()) continue;
|
||||
if (!valid_instance(obj_id, instance_id))
|
||||
continue;
|
||||
|
||||
ModelObject * object = m_model->objects[obj_id];
|
||||
ModelInstance *instance = object->instances[instance_id];
|
||||
@@ -3506,8 +3543,16 @@ int PartPlate::load_gcode_from_file(const std::string& filename)
|
||||
int ret = 0;
|
||||
|
||||
// process gcode
|
||||
auto& preset_bundle = wxGetApp().preset_bundle;
|
||||
std::vector<int> filament_maps = this->get_filament_maps();
|
||||
DynamicPrintConfig full_config = wxGetApp().preset_bundle->full_config(false, filament_maps);
|
||||
// Inject the plate's volume map (or the per-extruder defaults) exactly like the apply-time
|
||||
// composition, so the config applied over the loaded slice result matches the next
|
||||
// background-process apply and does not invalidate the embedded g-code.
|
||||
std::vector<int> f_volume_maps = this->get_filament_volume_maps();
|
||||
if (f_volume_maps.empty()) {
|
||||
f_volume_maps = preset_bundle->get_default_nozzle_volume_types_for_filaments(filament_maps);
|
||||
}
|
||||
DynamicPrintConfig full_config = preset_bundle->full_config(false, filament_maps, f_volume_maps);
|
||||
full_config.apply(m_config, true);
|
||||
m_print->apply(*m_model, full_config, false);
|
||||
//BBS: need to apply two times, for after the first apply, the m_print got its object,
|
||||
@@ -3814,6 +3859,40 @@ void PartPlate::clear_filament_map()
|
||||
m_config.erase("filament_map");
|
||||
}
|
||||
|
||||
std::vector<int> PartPlate::get_filament_volume_maps() const
|
||||
{
|
||||
std::string key = "filament_volume_map";
|
||||
if (m_config.has(key))
|
||||
return m_config.option<ConfigOptionInts>(key)->values;
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void PartPlate::set_filament_volume_maps(const std::vector<int>& f_maps)
|
||||
{
|
||||
m_config.option<ConfigOptionInts>("filament_volume_map", true)->values = f_maps;
|
||||
}
|
||||
|
||||
void PartPlate::clear_filament_volume_map()
|
||||
{
|
||||
if (m_config.has("filament_volume_map"))
|
||||
m_config.erase("filament_volume_map");
|
||||
}
|
||||
|
||||
std::vector<int> PartPlate::get_filament_nozzle_maps() const
|
||||
{
|
||||
std::string key = "filament_nozzle_map";
|
||||
if (m_config.has(key))
|
||||
return m_config.option<ConfigOptionInts>(key)->values;
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void PartPlate::set_filament_nozzle_maps(const std::vector<int>& f_maps)
|
||||
{
|
||||
m_config.option<ConfigOptionInts>("filament_nozzle_map", true)->values = f_maps;
|
||||
}
|
||||
|
||||
void PartPlate::clear_filament_map_mode()
|
||||
{
|
||||
if (m_config.has("filament_map_mode"))
|
||||
@@ -3840,6 +3919,16 @@ void PartPlate::set_filament_count(int filament_count)
|
||||
std::vector<int>& filament_maps = m_config.option<ConfigOptionInts>("filament_map")->values;
|
||||
filament_maps.resize(filament_count, 1);
|
||||
}
|
||||
|
||||
if (m_config.has("filament_nozzle_map")) {
|
||||
std::vector<int>& filament_nozzle_map = m_config.option<ConfigOptionInts>("filament_nozzle_map")->values;
|
||||
filament_nozzle_map.resize(filament_count, 0);
|
||||
}
|
||||
|
||||
if (m_config.has("filament_volume_map")) {
|
||||
std::vector<int>& filament_volume_map = m_config.option<ConfigOptionInts>("filament_volume_map")->values;
|
||||
filament_volume_map.resize(filament_count, static_cast<int>(NozzleVolumeType::nvtStandard));
|
||||
}
|
||||
}
|
||||
|
||||
void PartPlate::on_filament_added()
|
||||
@@ -3848,6 +3937,27 @@ void PartPlate::on_filament_added()
|
||||
std::vector<int>& filament_maps = m_config.option<ConfigOptionInts>("filament_map")->values;
|
||||
filament_maps.push_back(1);
|
||||
}
|
||||
|
||||
if (m_config.has("filament_nozzle_map")) {
|
||||
std::vector<int>& filament_nozzle_map = m_config.option<ConfigOptionInts>("filament_nozzle_map")->values;
|
||||
filament_nozzle_map.push_back(0);
|
||||
}
|
||||
|
||||
if (m_config.has("filament_volume_map")) {
|
||||
std::vector<int>& filament_volume_map = m_config.option<ConfigOptionInts>("filament_volume_map")->values;
|
||||
// A new filament defaults onto the first extruder, so seed its volume value from
|
||||
// that extruder's flow type.
|
||||
int volume_type = static_cast<int>(NozzleVolumeType::nvtStandard);
|
||||
auto nozzle_volumes = wxGetApp().preset_bundle->project_config.option<ConfigOptionEnumsGeneric>("nozzle_volume_type");
|
||||
if (nozzle_volumes && !nozzle_volumes->values.empty())
|
||||
volume_type = nozzle_volumes->values[0];
|
||||
// Orca: never store the Hybrid marker as a per-filament value; on a Hybrid extruder
|
||||
// each filament still prints with a concrete flow, defaulting to Standard.
|
||||
if (volume_type == static_cast<int>(NozzleVolumeType::nvtHybrid))
|
||||
volume_type = static_cast<int>(NozzleVolumeType::nvtStandard);
|
||||
|
||||
filament_volume_map.push_back(volume_type);
|
||||
}
|
||||
}
|
||||
|
||||
void PartPlate::on_filament_deleted(int filament_count, int filament_id)
|
||||
@@ -3860,6 +3970,19 @@ void PartPlate::on_filament_deleted(int filament_count, int filament_id)
|
||||
if (filament_id >= 0 && filament_id < (int) filament_maps.size())
|
||||
filament_maps.erase(filament_maps.begin() + filament_id);
|
||||
}
|
||||
|
||||
if (m_config.has("filament_nozzle_map")) {
|
||||
std::vector<int>& filament_nozzle_map = m_config.option<ConfigOptionInts>("filament_nozzle_map")->values;
|
||||
if (filament_id >= 0 && filament_id < (int) filament_nozzle_map.size())
|
||||
filament_nozzle_map.erase(filament_nozzle_map.begin() + filament_id);
|
||||
}
|
||||
|
||||
if (m_config.has("filament_volume_map")) {
|
||||
std::vector<int>& filament_volume_map = m_config.option<ConfigOptionInts>("filament_volume_map")->values;
|
||||
if (filament_id >= 0 && filament_id < (int) filament_volume_map.size())
|
||||
filament_volume_map.erase(filament_volume_map.begin() + filament_id);
|
||||
}
|
||||
|
||||
update_first_layer_print_sequence_when_delete_filament(filament_id);
|
||||
}
|
||||
|
||||
@@ -4225,6 +4348,12 @@ void PartPlateList::set_default_wipe_tower_pos_for_plate(int plate_idx, bool ini
|
||||
y = I3_WIPE_TOWER_DEFAULT_Y_POS;
|
||||
}
|
||||
|
||||
std::string printer_type = wxGetApp().preset_bundle->printers.get_edited_preset().get_printer_type(wxGetApp().preset_bundle);
|
||||
// Note: printer_type == "N9" and printer_structure_opt->value == PrinterStructure::psI3 can both be true
|
||||
if (printer_type == "N9") {
|
||||
y = N9_WIPE_TOWER_DEFAULT_Y_POS;
|
||||
}
|
||||
|
||||
PartPlate *part_plate = get_plate(plate_idx);
|
||||
Vec3d plate_origin = part_plate->get_origin();
|
||||
BoundingBoxf3 plate_bbox = part_plate->get_bounding_box();
|
||||
@@ -4241,7 +4370,14 @@ void PartPlateList::set_default_wipe_tower_pos_for_plate(int plate_idx, bool ini
|
||||
coordf_t plate_bbox_y_max_local_coord = plate_bbox_2d.max(1) - plate_origin(1);
|
||||
|
||||
std::vector<int> filament_maps = part_plate->get_real_filament_maps(proj_cfg);
|
||||
DynamicPrintConfig full_config = wxGetApp().preset_bundle->full_config(false, filament_maps);
|
||||
// Keep this composition consistent with the apply-time injection (plate volume map, else
|
||||
// per-extruder defaults); the config below currently only feeds scalar reads, but a
|
||||
// divergent volume map would silently mis-resolve any future per-filament read here.
|
||||
std::vector<int> f_volume_maps = part_plate->get_filament_volume_maps();
|
||||
if (f_volume_maps.empty()) {
|
||||
f_volume_maps = wxGetApp().preset_bundle->get_default_nozzle_volume_types_for_filaments(filament_maps);
|
||||
}
|
||||
DynamicPrintConfig full_config = wxGetApp().preset_bundle->full_config(false, filament_maps, f_volume_maps);
|
||||
const DynamicPrintConfig &print_cfg = wxGetApp().preset_bundle->prints.get_edited_preset().config;
|
||||
float w = dynamic_cast<const ConfigOptionFloat *>(print_cfg.option("prime_tower_width"))->value;
|
||||
float v = dynamic_cast<const ConfigOptionFloat *>(full_config.option("prime_volume"))->value;
|
||||
@@ -5218,6 +5354,9 @@ int PartPlateList::notify_instance_removed(int obj_id, int instance_id)
|
||||
unprintable_plate.update_object_index(obj_id, m_model->objects.size());
|
||||
}
|
||||
|
||||
if (m_plater)
|
||||
m_plater->mark_plate_toolbar_image_dirty();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -6139,6 +6278,9 @@ int PartPlateList::rebuild_plates_after_arrangement(bool recycle_plates, bool ex
|
||||
}
|
||||
#endif
|
||||
|
||||
if (m_plater)
|
||||
m_plater->mark_plate_toolbar_image_dirty();
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(":after rebuild, plates count %1%") % m_plate_list.size();
|
||||
return ret;
|
||||
}
|
||||
@@ -6283,6 +6425,58 @@ int PartPlateList::load_from_3mf_structure(PlateDataPtrs& plate_data_list, int f
|
||||
m_plate_list[index]->slice_filaments_info = plate_data_list[i]->slice_filaments_info;
|
||||
gcode_result->warnings = plate_data_list[i]->warnings;
|
||||
gcode_result->filament_maps = plate_data_list[i]->filament_maps;
|
||||
|
||||
// Reconstruct the device-side nozzle grouping from the loaded 3mf so
|
||||
// the monitor/preview can map filaments to physical nozzles.
|
||||
// load_nozzle_infos_with_compatibility handles older single-nozzle 3mf (no <nozzle> tags) by
|
||||
// falling back to the per-filament group_id, then to the extruder volume types / nozzle diameters.
|
||||
{
|
||||
// nozzle_volume_types is space-separated ints; nozzle_diameters is comma/space-separated floats.
|
||||
auto parse_int_tokens = [](const std::string& str) -> std::vector<int> {
|
||||
std::vector<int> out;
|
||||
std::istringstream iss(str);
|
||||
std::string tok;
|
||||
while (iss >> tok) { try { out.push_back(std::stoi(tok)); } catch (...) {} }
|
||||
return out;
|
||||
};
|
||||
auto parse_double_tokens = [](const std::string& str) -> std::vector<double> {
|
||||
std::vector<double> out;
|
||||
std::string s = str;
|
||||
std::replace(s.begin(), s.end(), ',', ' ');
|
||||
std::istringstream iss(s);
|
||||
std::string tok;
|
||||
while (iss >> tok) { try { out.push_back(std::stod(tok)); } catch (...) {} }
|
||||
return out;
|
||||
};
|
||||
|
||||
std::vector<int> nozzle_volume_type_values = parse_int_tokens(plate_data_list[i]->nozzle_volume_types);
|
||||
std::vector<double> nozzle_diameter_values = parse_double_tokens(plate_data_list[i]->nozzle_diameters);
|
||||
|
||||
std::vector<NozzleVolumeType> extruder_volume_types(nozzle_volume_type_values.size(), NozzleVolumeType::nvtStandard);
|
||||
for (size_t idx = 0; idx < nozzle_volume_type_values.size(); ++idx)
|
||||
if (nozzle_volume_type_values[idx] >= 0 && nozzle_volume_type_values[idx] <= nvtMaxNozzleVolumeType)
|
||||
extruder_volume_types[idx] = static_cast<NozzleVolumeType>(nozzle_volume_type_values[idx]);
|
||||
|
||||
auto nozzle_infos = MultiNozzleUtils::load_nozzle_infos_with_compatibility(
|
||||
plate_data_list[i]->nozzles_info,
|
||||
plate_data_list[i]->slice_filaments_info,
|
||||
plate_data_list[i]->filament_maps,
|
||||
extruder_volume_types,
|
||||
nozzle_diameter_values);
|
||||
|
||||
std::vector<int> fil_seq(plate_data_list[i]->filament_change_sequence.begin(), plate_data_list[i]->filament_change_sequence.end());
|
||||
std::vector<int> noz_seq(plate_data_list[i]->nozzle_change_sequence.begin(), plate_data_list[i]->nozzle_change_sequence.end());
|
||||
bool enable_filament_dynamic_map = false;
|
||||
if (plate_data_list[i]->config.has("enable_filament_dynamic_map"))
|
||||
enable_filament_dynamic_map = plate_data_list[i]->config.option<ConfigOptionBool>("enable_filament_dynamic_map")->value;
|
||||
|
||||
auto group_result = MultiNozzleUtils::StaticNozzleGroupResult::create(
|
||||
plate_data_list[i]->slice_filaments_info, nozzle_infos, fil_seq, noz_seq, enable_filament_dynamic_map);
|
||||
if (group_result)
|
||||
gcode_result->nozzle_group_result = std::make_shared<MultiNozzleUtils::StaticNozzleGroupResult>(group_result.value());
|
||||
else
|
||||
gcode_result->nozzle_group_result = nullptr;
|
||||
}
|
||||
if (m_plater && !plate_data_list[i]->thumbnail_file.empty()) {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": plate %1%, load thumbnail from %2%.")%(i+1) %plate_data_list[i]->thumbnail_file;
|
||||
if (boost::filesystem::exists(plate_data_list[i]->thumbnail_file)) {
|
||||
@@ -6442,9 +6636,10 @@ void PartPlateList::init_bed_type_info()
|
||||
auto bed_texture_maps = wxGetApp().plater()->get_bed_texture_maps();
|
||||
std::string bottom_texture_end_name = bed_texture_maps.find("bottom_texture_end_name") != bed_texture_maps.end() ? bed_texture_maps["bottom_texture_end_name"] : "";
|
||||
std::string bottom_texture_rect_str = bed_texture_maps.find("bottom_texture_rect") != bed_texture_maps.end() ? bed_texture_maps["bottom_texture_rect"] : "";
|
||||
std::string bottom_texture_rect_longer_str = bed_texture_maps.find("bottom_texture_rect_longer") != bed_texture_maps.end() ? bed_texture_maps["bottom_texture_rect_longer"] : "";
|
||||
std::string middle_texture_rect_str = bed_texture_maps.find("middle_texture_rect") != bed_texture_maps.end() ? bed_texture_maps["middle_texture_rect"] : "";
|
||||
std::string use_double_extruder_default_texture = bed_texture_maps.find("use_double_extruder_default_texture") != bed_texture_maps.end() ? bed_texture_maps["use_double_extruder_default_texture"] : "";
|
||||
std::array<float, 4> bottom_texture_rect = {0, 0, 0, 0}, middle_texture_rect = {0, 0, 0, 0};
|
||||
std::array<float, 4> bottom_texture_rect = {0, 0, 0, 0}, bottom_texture_rect_longer = {0, 0, 0, 0}, middle_texture_rect = {0, 0, 0, 0};
|
||||
if (bottom_texture_rect_str.size() > 0) {
|
||||
std::vector<std::string> items;
|
||||
boost::algorithm::erase_all(bottom_texture_rect_str, " ");
|
||||
@@ -6455,6 +6650,16 @@ void PartPlateList::init_bed_type_info()
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bottom_texture_rect_longer_str.size() > 0) {
|
||||
std::vector<std::string> items;
|
||||
boost::algorithm::erase_all(bottom_texture_rect_longer_str, " ");
|
||||
boost::split(items, bottom_texture_rect_longer_str, boost::is_any_of(","));
|
||||
if (items.size() == 4) {
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
bottom_texture_rect_longer[i] = std::atof(items[i].c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (middle_texture_rect_str.size() > 0) {
|
||||
std::vector<std::string> items;
|
||||
boost::algorithm::erase_all(middle_texture_rect_str, " ");
|
||||
@@ -6475,6 +6680,7 @@ void PartPlateList::init_bed_type_info()
|
||||
}
|
||||
pte_part2 = BedTextureInfo::TexturePart(45, -14.5, 70, 8, "bbl_bed_pte_left_bottom.svg");
|
||||
auto &bottom_rect = bottom_texture_rect;
|
||||
auto &bottom_rect_longer = bottom_texture_rect_longer;
|
||||
if (bottom_texture_end_name.size() > 0 && bottom_rect[2] > 0.f) {
|
||||
std::string pte_part2_name = "bbl_bed_pte_bottom_" + bottom_texture_end_name + ".svg";
|
||||
pte_part2 = BedTextureInfo::TexturePart(bottom_rect[0], bottom_rect[1], bottom_rect[2], bottom_rect[3], pte_part2_name);
|
||||
@@ -6498,6 +6704,9 @@ void PartPlateList::init_bed_type_info()
|
||||
if (bottom_texture_end_name.size() > 0 && bottom_rect[2] > 0.f) {
|
||||
std::string st_part2_name = "bbl_bed_st_bottom_" + bottom_texture_end_name + ".svg";
|
||||
st_part2 = BedTextureInfo::TexturePart(bottom_rect[0], bottom_rect[1], bottom_rect[2], bottom_rect[3], st_part2_name);
|
||||
} else if (bottom_rect_longer[2] > 0.f) {
|
||||
// SuperTack bottom strip uses the wider "longer" rect.
|
||||
st_part2.update_pos(bottom_rect_longer[0], bottom_rect_longer[1], bottom_rect_longer[2], bottom_rect_longer[3]);
|
||||
}
|
||||
|
||||
ep_part1 = BedTextureInfo::TexturePart(57, 300, 236.12f, 10.f, "bbl_bed_ep_middle.svg");
|
||||
@@ -6508,6 +6717,9 @@ void PartPlateList::init_bed_type_info()
|
||||
if (bottom_texture_end_name.size() > 0 && bottom_rect[2] > 0.f) {
|
||||
std::string ep_part2_name = "bbl_bed_ep_bottom_" + bottom_texture_end_name + ".svg";
|
||||
ep_part2 = BedTextureInfo::TexturePart(bottom_rect[0], bottom_rect[1], bottom_rect[2], bottom_rect[3], ep_part2_name);
|
||||
} else if (bottom_rect_longer[2] > 0.f) {
|
||||
// Engineering-plate bottom strip uses the wider "longer" rect.
|
||||
ep_part2.update_pos(bottom_rect_longer[0], bottom_rect_longer[1], bottom_rect_longer[2], bottom_rect_longer[3]);
|
||||
}
|
||||
|
||||
pc_part1 = BedTextureInfo::TexturePart(57, 300, 236.12f, 10.f, "bbl_bed_pc_middle.svg");
|
||||
|
||||
Reference in New Issue
Block a user