Merge branch 'main' into zaa

This commit is contained in:
SoftFever authored and GitHub committed 2026-03-18 18:10:35 +08:00
commit 4314f5d804
235 files changed
+3182 -1591

No files matched your search

@@ -23,10 +23,11 @@ template<> struct hash<Slic3r::GridPoint3>
namespace Slic3r {
void InterlockingGenerator::generate_interlocking_structure(PrintObject* print_object)
void InterlockingGenerator::generate_interlocking_structure(PrintObject* print_object, const std::function<void()>& throw_on_cancel)
{
const auto& config = print_object->config();
if (!config.interlocking_beam) {
// Check if interlocking is enabled, and avoid errors like division by zero due to invalid configuration.
if (!config.interlocking_beam || config.interlocking_beam_layer_count < 1 || config.interlocking_depth < 1 || config.interlocking_beam_width < EPSILON ) {
return;
}
@@ -55,8 +56,10 @@ void InterlockingGenerator::generate_interlocking_structure(PrintObject* print_o
continue;
}
throw_on_cancel();
InterlockingGenerator gen(*print_object, region_a_index, region_b_index, beam_width, boundary_avoidance, rotation, cell_size, beam_layer_count,
interface_dilation, air_dilation, air_filtering);
interface_dilation, air_dilation, air_filtering, throw_on_cancel);
gen.generateInterlockingStructure();
}
}
@@ -108,12 +111,14 @@ void InterlockingGenerator::handleThinAreas(const std::unordered_set<GridPoint3>
}
}
for (auto& near_interlock : near_interlock_per_layer) {
throw_on_cancel();
near_interlock = offset(union_(closing(near_interlock, rounding_errors)), detect);
polygons_rotate(near_interlock, rotation);
}
// Only alter layers when they are present in both meshes, zip should take care if that.
for (size_t layer_nr = 0; layer_nr < print_object.layer_count(); layer_nr++){
throw_on_cancel();
auto layer = print_object.get_layer(layer_nr);
ExPolygons polys_a = to_expolygons(layer->get_region(region_a_index)->slices.surfaces);
ExPolygons polys_b = to_expolygons(layer->get_region(region_b_index)->slices.surfaces);
@@ -199,7 +204,8 @@ void InterlockingGenerator::addBoundaryCells(const std::vector<ExPolygons>& lay
const DilationKernel& kernel,
std::unordered_set<GridPoint3>& cells) const
{
auto voxel_emplacer = [&cells](GridPoint3 p) {
auto voxel_emplacer = [this, &cells](GridPoint3 p) {
this->throw_on_cancel();
if (p.z() < 0) {
return true;
}
@@ -313,6 +319,7 @@ void InterlockingGenerator::applyMicrostructureToOutlines(const std::unordered_s
for (size_t region_idx = 0; region_idx < 2; region_idx++) {
const size_t region = (region_idx == 0) ? region_a_index : region_b_index;
for (size_t layer_nr = 0; layer_nr < max_layer_count; layer_nr++) {
throw_on_cancel();
ExPolygons layer_outlines = layer_regions[layer_nr];
expolygons_rotate(layer_outlines, unapply_rotation);
@@ -45,7 +45,7 @@ public:
/*!
* Generate an interlocking structure between each two adjacent meshes.
*/
static void generate_interlocking_structure(PrintObject* print_object);
static void generate_interlocking_structure(PrintObject* print_object, const std::function<void()>& throw_on_cancel);
private:
/*!
@@ -75,7 +75,8 @@ private:
const coord_t beam_layer_count,
const DilationKernel& interface_dilation,
const DilationKernel& air_dilation,
const bool air_filtering)
const bool air_filtering,
const std::function<void()>& throw_on_cancel)
: print_object(print_object)
, region_a_index(region_a_index)
, region_b_index(region_b_index)
@@ -88,6 +89,7 @@ private:
, interface_dilation(interface_dilation)
, air_dilation(air_dilation)
, air_filtering(air_filtering)
, throw_on_cancel(throw_on_cancel)
{}
/*! Given two polygons, return the parts that border on air, and grow 'perpendicular' up to 'detect' distance.
@@ -165,6 +167,8 @@ private:
// Whether to fully remove all of the interlocking cells which would be visible on the outside. If no air filtering then those cells
// will be cut off midway in a beam.
const bool air_filtering;
const std::function<void()>& throw_on_cancel;
};
} // namespace Slic3r
+1
View File
@@ -882,6 +882,7 @@ std::vector<SurfaceFill> group_fills(const Layer &layer, LockRegionParam &lock_p
if (surface.is_top()) {
params.pattern = region_config.top_surface_pattern.value;
params.density = float(region_config.top_surface_density);
if (params.density <= 0.0f) continue;
} else { // Surface is bottom
params.pattern = region_config.bottom_surface_pattern.value;
params.density = float(region_config.bottom_surface_density);
+11 -11
View File
@@ -1458,7 +1458,7 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
std::string WipeTowerIntegration::prime(GCode &gcodegen)
{
std::string gcode;
if (!gcodegen.is_BBL_Printer() && !gcodegen.is_QIDI_Printer()) {
if (gcodegen.wipe_tower_type() == WipeTowerType::Type2) {
for (const WipeTower::ToolChangeResult &tcr : m_priming) {
if (!tcr.extrusions.empty())
gcode += append_tcr2(gcodegen, tcr, tcr.new_tool);
@@ -1474,7 +1474,7 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
assert(m_layer_idx >= 0);
if (m_layer_idx >= (int) m_tool_changes.size())
return gcode;
if (!gcodegen.is_BBL_Printer() && !gcodegen.is_QIDI_Printer()) {
if (gcodegen.wipe_tower_type() == WipeTowerType::Type2) {
if (gcodegen.writer().need_toolchange(extruder_id) || finish_layer) {
if (m_layer_idx < (int) m_tool_changes.size()) {
if (!(size_t(m_tool_change_idx) < m_tool_changes[m_layer_idx].size()))
@@ -1563,7 +1563,7 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
std::string WipeTowerIntegration::finalize(GCode &gcodegen)
{
std::string gcode;
if (!gcodegen.is_BBL_Printer() && !gcodegen.is_QIDI_Printer()) {
if (gcodegen.wipe_tower_type() == WipeTowerType::Type2) {
if (std::abs(gcodegen.writer().get_position().z() - m_final_purge.print_z) > EPSILON)
gcode += gcodegen.change_layer(m_final_purge.print_z);
gcode += append_tcr2(gcodegen, m_final_purge, -1);
@@ -1985,11 +1985,11 @@ bool GCode::is_BBL_Printer()
return false;
}
bool GCode::is_QIDI_Printer()
WipeTowerType GCode::wipe_tower_type()
{
if (m_curr_print)
return m_curr_print->is_QIDI_printer();
return false;
return m_curr_print->wipe_tower_type();
return WipeTowerType::Type2;
}
void GCode::do_export(Print* print, const char* path, GCodeProcessorResult* result, ThumbnailsGeneratorCallback thumbnail_cb)
@@ -2402,7 +2402,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
// modifies m_silent_time_estimator_enabled
DoExport::init_gcode_processor(print.config(), m_processor, m_silent_time_estimator_enabled);
const bool is_bbl_printers = print.is_BBL_printer();
const bool is_qidi_printers = print.is_QIDI_printer();
const WipeTowerType wipe_tower_type = print.wipe_tower_type();
m_calib_config.clear();
// resets analyzer's tracking data
m_last_height = 0.f;
@@ -2703,7 +2703,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
throw Slic3r::SlicingError(_(L("No object can be printed. Maybe too small")));
has_wipe_tower = print.has_wipe_tower() && tool_ordering.has_wipe_tower();
// Orca: support all extruder priming
initial_extruder_id = (!is_bbl_printers && has_wipe_tower && !print.config().single_extruder_multi_material_priming && !is_qidi_printers) ?
initial_extruder_id = (wipe_tower_type == WipeTowerType::Type2 && has_wipe_tower && !print.config().single_extruder_multi_material_priming) ?
// The priming towers will be skipped.
tool_ordering.all_extruders().back() :
// Don't skip the priming towers.
@@ -2816,7 +2816,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
this->placeholder_parser().set("current_object_idx", 0);
// For the start / end G-code to do the priming and final filament pull in case there is no wipe tower provided.
this->placeholder_parser().set("has_wipe_tower", has_wipe_tower);
this->placeholder_parser().set("has_single_extruder_multi_material_priming", !is_bbl_printers && has_wipe_tower && print.config().single_extruder_multi_material_priming);
this->placeholder_parser().set("has_single_extruder_multi_material_priming", wipe_tower_type == WipeTowerType::Type2 && has_wipe_tower && print.config().single_extruder_multi_material_priming);
this->placeholder_parser().set("total_toolchanges", std::max(0, print.wipe_tower_data().number_of_toolchanges)); // Check for negative toolchanges (single extruder mode) and set to 0 (no tool change).
this->placeholder_parser().set("num_extruders", int(print.config().nozzle_diameter.values.size()));
this->placeholder_parser().set("retract_length", new ConfigOptionFloats(print.config().retraction_length));
@@ -3136,7 +3136,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
}
// Orca: support extruder priming
if (is_bbl_printers || ! (has_wipe_tower && print.config().single_extruder_multi_material_priming))
if (wipe_tower_type != WipeTowerType::Type2 || ! (has_wipe_tower && print.config().single_extruder_multi_material_priming))
{
// Set initial extruder only after custom start G-code.
// Ugly hack: Do not set the initial extruder if the extruder is primed using the MMU priming towers at the edge of the print bed.
@@ -3292,7 +3292,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
//BBS
file.write(m_writer.travel_to_z(initial_layer_print_height + m_config.z_offset.value, "Move to the first layer height"));
if (!is_bbl_printers && print.config().single_extruder_multi_material_priming) {
if (wipe_tower_type == WipeTowerType::Type2 && print.config().single_extruder_multi_material_priming) {
file.write(m_wipe_tower->prime(*this));
// Verify, whether the print overaps the priming extrusions.
BoundingBoxf bbox_print(get_print_extrusions_extents(print));
+1 -1
View File
@@ -251,7 +251,7 @@ public:
std::string unretract() { return m_writer.unlift() + m_writer.unretract(); }
std::string set_extruder(unsigned int extruder_id, double print_z, bool by_object=false, int toolchange_temp_override = -1);
bool is_BBL_Printer();
bool is_QIDI_Printer();
WipeTowerType wipe_tower_type();
// SoftFever
std::string set_object_info(Print* print);
+7 -12
View File
@@ -381,7 +381,6 @@ void ToolOrdering::sort_and_build_data(const PrintObject& object , unsigned int
// (print->config().print_sequence == PrintSequence::ByObject is true).
ToolOrdering::ToolOrdering(const PrintObject &object, unsigned int first_extruder, bool prime_multi_material)
{
m_is_BBL_printer = object.print()->is_BBL_printer();
m_print_full_config = &object.print()->full_print_config();
m_print_object_ptr = &object;
m_print = const_cast<Print*>(object.print());
@@ -427,7 +426,6 @@ ToolOrdering::ToolOrdering(const PrintObject &object, unsigned int first_extrude
// (print->config().print_sequence == PrintSequence::ByObject is false).
ToolOrdering::ToolOrdering(const Print &print, unsigned int first_extruder, bool prime_multi_material)
{
m_is_BBL_printer = print.is_BBL_printer();
m_print_full_config = &print.full_print_config();
m_print = const_cast<Print *>(&print); // for update the context of print
m_print_config_ptr = &print.config();
@@ -1222,12 +1220,13 @@ void ToolOrdering::reorder_extruders_for_minimum_flush_volume(bool reorder_first
using FlushMatrix = std::vector<std::vector<float>>;
size_t nozzle_nums = print_config->nozzle_diameter.values.size();
const auto wipe_tower_type = m_print->wipe_tower_type();
std::vector<FlushMatrix> nozzle_flush_mtx;
for (size_t nozzle_id = 0; nozzle_id < nozzle_nums; ++nozzle_id) {
std::vector<float> flush_matrix(cast<float>(get_flush_volumes_matrix(print_config->flush_volumes_matrix.values, nozzle_id, nozzle_nums)));
std::vector<std::vector<float>> wipe_volumes;
if ((print_config->purge_in_prime_tower && print_config->single_extruder_multi_material) || m_is_BBL_printer) {
if ((print_config->purge_in_prime_tower && print_config->single_extruder_multi_material) || wipe_tower_type == WipeTowerType::Type1) {
for (unsigned int i = 0; i < number_of_extruders; ++i)
wipe_volumes.push_back(std::vector<float>(flush_matrix.begin() + i * number_of_extruders, flush_matrix.begin() + (i + 1) * number_of_extruders));
} else {
@@ -1321,19 +1320,18 @@ void ToolOrdering::reorder_extruders_for_minimum_flush_volume(bool reorder_first
return false;
};
if (m_print->is_BBL_printer() || number_of_extruders == 1){
auto maps_without_group = filament_maps;
for (auto& item : maps_without_group)
item = 0;
reorder_filaments_for_minimum_flush_volume(
filament_lists,
filament_maps,
m_print->is_BBL_printer() ? filament_maps : maps_without_group, // non-bbl printers do not support filament group yet
layer_filaments,
nozzle_flush_mtx,
get_custom_seq,
&filament_sequences
);
} else {
// For non-bbl multi-extruder printers we don't support filament group yet, so we keep the layer sequence because we don't flush based on order
filament_sequences = layer_filaments;
}
auto curr_flush_info = calc_filament_change_info_by_toolorder(print_config, filament_maps, nozzle_flush_mtx, filament_sequences);
if (nozzle_nums <= 1)
@@ -1349,9 +1347,6 @@ void ToolOrdering::reorder_extruders_for_minimum_flush_volume(bool reorder_first
// always calculate the info by one extruder
{
std::vector<std::vector<unsigned int>>filament_sequences_one_extruder;
auto maps_without_group = filament_maps;
for (auto& item : maps_without_group)
item = 0;
reorder_filaments_for_minimum_flush_volume(
filament_lists,
maps_without_group,
-1
View File
@@ -279,7 +279,6 @@ private:
const PrintObject* m_print_object_ptr = nullptr;
Print* m_print;
bool m_sorted = false;
bool m_is_BBL_printer = false;
FilamentChangeStats m_stats_by_single_extruder;
FilamentChangeStats m_stats_by_multi_extruder_curr;
+1 -1
View File
@@ -1030,7 +1030,7 @@ static std::vector<std::string> s_Preset_printer_options {
"use_relative_e_distances", "extruder_type", "use_firmware_retraction", "printer_notes",
"grab_length", "support_object_skip_flush", "physical_extruder_map",
"cooling_tube_retraction",
"cooling_tube_length", "high_current_on_filament_swap", "parking_pos_retraction", "extra_loading_move", "purge_in_prime_tower", "enable_filament_ramming",
"cooling_tube_length", "high_current_on_filament_swap", "parking_pos_retraction", "extra_loading_move", "wipe_tower_type", "purge_in_prime_tower", "enable_filament_ramming",
"z_offset",
"disable_m73", "preferred_orientation", "emit_machine_limits_to_gcode", "pellet_modded_printer", "support_multi_bed_types", "default_bed_type", "bed_mesh_min","bed_mesh_max","bed_mesh_probe_distance", "adaptive_bed_mesh_margin", "enable_long_retraction_when_cut","long_retractions_when_cut","retraction_distances_when_cut",
"bed_temperature_formula", "nozzle_flush_dataset"
-1
View File
@@ -145,7 +145,6 @@ public:
VendorType get_current_vendor_type();
// Vendor related handy functions
bool is_bbl_vendor() { return get_current_vendor_type() == VendorType::Marlin_BBL; }
bool is_qidi_vendor() { return get_current_vendor_type() == VendorType::Klipper_Qidi; }
// Whether using bbl network for print upload
bool use_bbl_network();
+20 -5
View File
@@ -315,6 +315,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|| opt_key == "prime_tower_enable_framework"
|| opt_key == "prime_tower_width"
|| opt_key == "prime_tower_brim_width"
|| opt_key == "wipe_tower_type"
|| opt_key == "prime_tower_skip_points"
|| opt_key == "prime_tower_flat_ironing"
|| opt_key == "enable_tower_interface_features"
@@ -1234,6 +1235,16 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons*
}
if (m_config.enable_prime_tower) {
for (const PrintObject* object : m_objects) {
if (object->config().precise_z_height.value && warning != nullptr) {
StringObjectException warningtemp;
warningtemp.string = L("Enabling both precise Z height and the prime tower may cause slicing errors.");
warningtemp.opt_key = "precise_z_height";
warningtemp.is_warning = true;
*warning = warningtemp;
break;
}
}
} else {
if (m_config.enable_wrapping_detection && warning!=nullptr) {
StringObjectException warningtemp;
@@ -1526,6 +1537,10 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons*
// Orca: check if the Lightning base pattern selected
warning->string = L("The Lightning base pattern is not supported by this support type; Rectilinear will be used instead.");
warning->opt_key = "support_base_pattern";
} else if (object->config().support_base_pattern == SupportMaterialPattern::smpNone && warning) {
// Orca: check if the Hollow base pattern selected
warning->string = L("The Hollow base pattern is not supported by this support type; Rectilinear will be used instead.");
warning->opt_key = "support_base_pattern";
}
}
@@ -3136,10 +3151,10 @@ void Print::_make_wipe_tower()
// BBS
const unsigned int number_of_extruders = (unsigned int)(m_config.filament_colour.values.size());
const auto bUseWipeTower2 = is_BBL_printer() || is_QIDI_printer() ? false : true;
const bool is_wipe_tower_type2 = this->wipe_tower_type() == WipeTowerType::Type2;
// Let the ToolOrdering class know there will be initial priming extrusions at the start of the print.
m_wipe_tower_data.tool_ordering = ToolOrdering(*this, (unsigned int) -1, bUseWipeTower2 ? true : false);
m_wipe_tower_data.tool_ordering.sort_and_build_data(*this, (unsigned int)-1, bUseWipeTower2 ? true : false);
m_wipe_tower_data.tool_ordering = ToolOrdering(*this, (unsigned int) -1, is_wipe_tower_type2);
m_wipe_tower_data.tool_ordering.sort_and_build_data(*this, (unsigned int)-1, is_wipe_tower_type2);
if (!m_wipe_tower_data.tool_ordering.has_wipe_tower())
// Don't generate any wipe tower.
@@ -3182,7 +3197,7 @@ void Print::_make_wipe_tower()
}
this->throw_if_canceled();
if (!bUseWipeTower2) {
if (!is_wipe_tower_type2) {
// in BBL machine, wipe tower is only use to prime extruder. So just use a global wipe volume.
WipeTower wipe_tower(m_config, m_plate_index, m_origin, m_wipe_tower_data.tool_ordering.first_extruder(),
m_wipe_tower_data.tool_ordering.empty() ? 0.f : m_wipe_tower_data.tool_ordering.back().print_z, m_wipe_tower_data.tool_ordering.all_extruders());
@@ -3320,7 +3335,7 @@ void Print::_make_wipe_tower()
wipe_volumes.push_back(std::vector<float>(flush_matrix.begin()+i*number_of_extruders, flush_matrix.begin()+(i+1)*number_of_extruders));
// Orca: itertate over wipe_volumes and change the non-zero values to the prime_volume
if ((!m_config.purge_in_prime_tower || !m_config.single_extruder_multi_material) && !is_BBL_printer() && !is_QIDI_printer()) {
if ((!m_config.purge_in_prime_tower || !m_config.single_extruder_multi_material) && is_wipe_tower_type2) {
for (unsigned int i = 0; i < number_of_extruders; ++i) {
for (unsigned int j = 0; j < number_of_extruders; ++j) {
if (wipe_volumes[i][j] > 0) {
+1 -3
View File
@@ -1067,8 +1067,7 @@ public:
//SoftFever
bool &is_BBL_printer() { return m_isBBLPrinter; }
const bool is_BBL_printer() const { return m_isBBLPrinter; }
bool &is_QIDI_printer() { return m_isQIDIPrinter; }
const bool is_QIDI_printer() const { return m_isQIDIPrinter; }
WipeTowerType wipe_tower_type() const { return is_BBL_printer() ? WipeTowerType::Type1 : m_config.wipe_tower_type.value; }
CalibMode& calib_mode() { return m_calib_params.mode; }
const CalibMode calib_mode() const { return m_calib_params.mode; }
void set_calib_params(const Calib_Params& params);
@@ -1136,7 +1135,6 @@ private:
//SoftFever
bool m_isBBLPrinter;
bool m_isQIDIPrinter;
// Ordered collections of extrusion paths to build skirt loops and brim.
ExtrusionEntityCollection m_skirt;
+24 -7
View File
@@ -187,6 +187,12 @@ static t_config_enum_values s_keys_map_NoiseType {
};
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(NoiseType)
static t_config_enum_values s_keys_map_WipeTowerType {
{ "type1", int(WipeTowerType::Type1) },
{ "type2", int(WipeTowerType::Type2) }
};
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(WipeTowerType)
static t_config_enum_values s_keys_map_FuzzySkinMode {
{ "displacement", int(FuzzySkinMode::Displacement) },
{ "extrusion", int(FuzzySkinMode::Extrusion) },
@@ -3973,7 +3979,7 @@ void PrintConfigDef::init_fff_params()
def->enum_labels.push_back(L("No ironing"));
def->enum_labels.push_back(L("Top surfaces"));
def->enum_labels.push_back(L("Topmost surface"));
def->enum_labels.push_back(L("All solid layer"));
def->enum_labels.push_back(L("All solid layers"));
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionEnum<IroningType>(IroningType::NoIroning));
@@ -4606,7 +4612,7 @@ void PrintConfigDef::init_fff_params()
def->set_default_value(new ConfigOptionFloat(0.));
def = this->add("detect_overhang_wall", coBool);
def->label = L("Detect overhang wall");
def->label = L("Detect overhang walls");
def->category = L("Quality");
def->tooltip = L("Detect the overhang percentage relative to line width and use different speed to print. "
"For 100%% overhang, bridge speed is used.");
@@ -5356,7 +5362,7 @@ void PrintConfigDef::init_fff_params()
def = this->add("minimum_sparse_infill_area", coFloat);
def->label = L("Minimum sparse infill threshold");
def->category = L("Strength");
def->tooltip = L("Sparse infill area which is smaller than threshold value is replaced by internal solid infill.");
def->tooltip = L("Sparse infill areas smaller than this threshold value are replaced by internal solid infill.");
def->sidetext = L(u8"mm²"); // square milimeters, CIS languages need translation
def->min = 0;
def->mode = comAdvanced;
@@ -5535,6 +5541,17 @@ void PrintConfigDef::init_fff_params()
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionBool(false));
def = this->add("wipe_tower_type", coEnum);
def->label = L("Wipe tower type");
def->tooltip = L("Choose the wipe tower implementation for multi-material prints. Type 1 is recommended for Bambu and Qidi printers with a filament cutter. Type 2 offers better compatibility with multi-tool and MMU printers and provide overall better compatibility.");
def->enum_keys_map = &ConfigOptionEnum<WipeTowerType>::get_enum_values();
def->enum_values.emplace_back("type1");
def->enum_values.emplace_back("type2");
def->enum_labels.emplace_back(L("Type 1"));
def->enum_labels.emplace_back(L("Type 2"));
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionEnum<WipeTowerType>(WipeTowerType::Type2));
def = this->add("purge_in_prime_tower", coBool);
def->label = L("Purge in prime tower");
def->tooltip = L("Purge remaining filament into prime tower.");
@@ -6197,10 +6214,10 @@ void PrintConfigDef::init_fff_params()
def->set_default_value(new ConfigOptionPoints{});
def = this->add("detect_thin_wall", coBool);
def->label = L("Detect thin wall");
def->label = L("Detect thin walls");
def->category = L("Strength");
def->tooltip = L("Detect thin wall which can't contain two line width. And use single line to print. "
"Maybe printed not very well, because it's not closed loop.");
def->tooltip = L("Detect thin walls which can't contain two line widths, and use single line to print. "
"Maybe not printed very well, because it's not a closed loop.");
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionBool(false));
@@ -6811,7 +6828,7 @@ void PrintConfigDef::init_fff_params()
}
def = this->add("detect_narrow_internal_solid_infill", coBool);
def->label = L("Detect narrow internal solid infill");
def->label = L("Detect narrow internal solid infills");
def->category = L("Strength");
def->tooltip = L("This option will auto-detect narrow internal solid infill areas. "
"If enabled, the concentric pattern will be used for the area to speed up printing. "
+7
View File
@@ -58,6 +58,11 @@ enum class NoiseType {
Voronoi,
};
enum class WipeTowerType {
Type1,
Type2,
};
enum PrintHostType {
htPrusaLink, htPrusaConnect, htOctoPrint, htDuet, htFlashAir, htAstroBox, htRepetier, htMKS, htESP3D, htCrealityPrint, htObico, htFlashforge, htSimplyPrint, htElegooLink
};
@@ -490,6 +495,7 @@ CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(PrinterTechnology)
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(GCodeFlavor)
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(FuzzySkinType)
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(FuzzySkinMode)
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(WipeTowerType)
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(NoiseType)
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(InfillPattern)
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(IroningType)
@@ -1398,6 +1404,7 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionFloats, filament_multitool_ramming_flow))
((ConfigOptionFloats, filament_stamping_loading_speed))
((ConfigOptionFloats, filament_stamping_distance))
((ConfigOptionEnum<WipeTowerType>, wipe_tower_type))
((ConfigOptionBool, purge_in_prime_tower))
((ConfigOptionBool, enable_filament_ramming))
((ConfigOptionBool, support_multi_bed_types))
+1 -1
View File
@@ -1220,7 +1220,7 @@ void PrintObject::slice_volumes()
apply_fuzzy_skin_segmentation(*this, [print]() { print->throw_if_canceled(); });
}
InterlockingGenerator::generate_interlocking_structure(this);
InterlockingGenerator::generate_interlocking_structure(this, [print]() { print->throw_if_canceled(); });
m_print->throw_if_canceled();
BOOST_LOG_TRIVIAL(debug) << "Slicing volumes - make_slices in parallel - begin";
+15 -3
View File
@@ -90,7 +90,10 @@ static const char* Segments_Vertex_Shader =
" );\n"
" int id = vertex_id < 4 ? id_a : id_b;\n"
" vec3 endpoint_pos = vertex_id < 4 ? pos_a : pos_b;\n"
" vec3 height_width_angle = texelFetch(height_width_angle_tex, id).xyz;\n"
" vec4 hwa = texelFetch(height_width_angle_tex, id);\n"
" vec3 height_width_angle = hwa.xyz;\n"
" // ORCA: Extract bias from w component\n"
" float bias = hwa.w;\n"
"#ifdef FIX_TWISTING\n"
" int closer_id = (dot(camera_position - pos_a, camera_position - pos_a) < dot(camera_position - pos_b, camera_position - pos_b)) ? id_a : id_b;\n"
" vec3 closer_pos = (closer_id == id_a) ? pos_a : pos_b;\n"
@@ -131,6 +134,8 @@ static const char* Segments_Vertex_Shader =
" }\n"
" }\n"
" vec3 eye_position = (view_matrix * vec4(pos, 1.0)).xyz;\n"
" // ORCA: Apply bias to z-position to avoid z-fighting\n"
" eye_position.z += bias;\n"
" vec3 eye_normal = (view_matrix * vec4(normalize(pos - endpoint_pos), 0.0)).xyz;\n"
" vec3 color_base = decode_color(texelFetch(color_tex, id).r);\n"
" color = color_base * lighting(eye_position, eye_normal);\n"
@@ -155,9 +160,11 @@ static const char* Options_Vertex_Shader =
"const float light_front_diffuse = 0.6 * 0.3;\n"
"const float ambient = 0.3;\n"
"const float emission = 0.25;\n"
#ifndef _WIN32
#ifdef __APPLE__
// ORCA: Use smaller scaling factor for macOS
"const float scaling_factor = 0.75;\n"
#else
// ORCA: Increase seam marker size to 1.5 for Windows and Linux
"const float scaling_factor = 1.5;\n"
#endif
"uniform mat4 view_matrix;\n"
@@ -185,7 +192,10 @@ static const char* Options_Vertex_Shader =
"}\n"
"void main() {\n"
" int id = int(texelFetch(segment_index_tex, gl_InstanceID).r);\n"
" vec2 height_width = texelFetch(height_width_angle_tex, id).xy;\n"
" vec4 hwa = texelFetch(height_width_angle_tex, id);\n"
" vec2 height_width = hwa.xy;\n"
" // ORCA: Extract bias from w component\n"
" float bias = hwa.w;\n"
" vec3 offset = texelFetch(position_tex, id).xyz - vec3(0.0, 0.0, 0.5 * height_width.x);\n"
" height_width *= scaling_factor;\n"
" mat3 scale_matrix = mat3(\n"
@@ -193,6 +203,8 @@ static const char* Options_Vertex_Shader =
" 0.0, height_width.y, 0.0,\n"
" 0.0, 0.0, height_width.x);\n"
" vec3 eye_position = (view_matrix * vec4(scale_matrix * in_position + offset, 1.0)).xyz;\n"
" // ORCA: Apply bias to z-position to avoid z-fighting\n"
" eye_position.z += bias;\n"
" vec3 eye_normal = (view_matrix * vec4(in_normal, 0.0)).xyz;\n"
" vec3 color_base = decode_color(texelFetch(color_tex, id).r);\n"
" color = color_base * lighting(eye_position, eye_normal);\n"
+10 -1
View File
@@ -966,9 +966,18 @@ static void extract_pos_and_or_hwa(const std::vector<PathVertex>& vertices, floa
height = v.height;
width = v.width;
}
// ORCA: Set bias for wipes and options to avoid z-fighting
float bias = 0.0f;
if (v.is_wipe())
bias = 0.05f;
else if (v.is_option())
bias = 0.1f;
// the last component is a dummy float to comply with GL_RGBA32F format
// ORCA: Pass bias to shader
heights_widths_angles->push_back({ height, width,
std::atan2(prev_line[0] * this_line[1] - prev_line[1] * this_line[0], dot(prev_line, this_line)), 0.0f });
std::atan2(prev_line[0] * this_line[1] - prev_line[1] * this_line[0], dot(prev_line, this_line)), bias });
}
}
}
+1 -2
View File
@@ -791,9 +791,8 @@ if (UNIX AND NOT APPLE)
# I don't know why this is needed, but for whatever reason slic3r isn't
# linking to X11 and webkit2gtk. force it.
find_package(X11 REQUIRED)
find_package(PkgConfig REQUIRED)
pkg_check_modules(webkit2gtk REQUIRED webkit2gtk-4.1)
target_link_libraries (libslic3r_gui ${X11_LIBRARIES} ${webkit2gtk_LIBRARIES})
target_link_libraries(libslic3r_gui ${X11_LIBRARIES} ${webkit2gtk_LIBRARIES})
endif()
target_include_directories(libslic3r_gui SYSTEM PRIVATE ${GTK${SLIC3R_GTK}_INCLUDE_DIRS} ${LIBSECRET_INCLUDE_DIRS})
target_link_libraries(libslic3r_gui ${GTK${SLIC3R_GTK}_LIBRARIES} fontconfig ${LIBSECRET_LIBRARIES})
+85 -61
View File
@@ -36,42 +36,67 @@ enum CUSTOM_ID
ID_AMS_NOTEBOOK,
};
CenteredTitle::CenteredTitle(wxWindow* parent)
: wxControl()
{
SetBackgroundStyle(wxBG_STYLE_PAINT);
Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
Bind(wxEVT_PAINT, [this](wxPaintEvent&) {
wxBufferedPaintDC dc(this);
dc.SetBackground(wxBrush(wxColour(38, 46, 48)));
dc.Clear();
dc.SetTextForeground(*wxWHITE);
wxFontMetrics fm = dc.GetFontMetrics();
int textHeight = fm.ascent + fm.descent;
wxRect rect = GetClientRect();
wxString ellipsized = wxControl::Ellipsize(m_title, dc, wxELLIPSIZE_END, wxMax(0, rect.GetWidth() - FromDIP(8)));
int y = rect.y + (rect.height - textHeight) / 2;
int x = rect.x + (ellipsized != m_title) // is ellipsized
? FromDIP(4) // align to left when clipped
: (rect.width - dc.GetTextExtent(m_title).GetWidth()) / 2; // centered when has available space
dc.DrawText(ellipsized, x, y);
});
// repaint for Ellipsize
Bind(wxEVT_SIZE, [this](wxSizeEvent& e) {
Refresh();
e.Skip();
});
auto forwardMouseEvent = [this](wxMouseEvent& e) {
if (e.LeftDown() && e.GetClickCount() > 1) return; // prevent duplicate event
e.SetPosition(GetParent()->ScreenToClient(ClientToScreen(e.GetPosition())));
GetParent()->GetEventHandler()->ProcessEvent(e);
};
Bind(wxEVT_LEFT_DOWN, forwardMouseEvent);
Bind(wxEVT_LEFT_DCLICK, forwardMouseEvent);
}
void CenteredTitle::SetTitle(const wxString& title) {
m_title = title;
Refresh();
}
// required for proper height
wxSize CenteredTitle::DoGetBestSize() const
{
return wxSize(10, FromDIP(30));
}
class BBLTopbarArt : public wxAuiDefaultToolBarArt
{
public:
virtual void DrawLabel(wxDC& dc, wxWindow* wnd, const wxAuiToolBarItem& item, const wxRect& rect) wxOVERRIDE;
virtual void DrawBackground(wxDC& dc, wxWindow* wnd, const wxRect& rect) wxOVERRIDE;
virtual void DrawButton(wxDC& dc, wxWindow* wnd, const wxAuiToolBarItem& item, const wxRect& rect) wxOVERRIDE;
};
void BBLTopbarArt::DrawLabel(wxDC& dc, wxWindow* wnd, const wxAuiToolBarItem& item, const wxRect& rect)
{
dc.SetFont(m_font);
#ifdef __WINDOWS__
dc.SetTextForeground(wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT));
#else
dc.SetTextForeground(*wxWHITE);
#endif
int textWidth = 0, textHeight = 0;
dc.GetTextExtent(item.GetLabel(), &textWidth, &textHeight);
wxRect clipRect = rect;
clipRect.width -= 1;
dc.SetClippingRegion(clipRect);
int textX, textY;
if (textWidth < rect.GetWidth()) {
textX = rect.x + 1 + (rect.width - textWidth) / 2;
}
else {
textX = rect.x + 1;
}
textY = rect.y + (rect.height - textHeight) / 2;
dc.DrawText(item.GetLabel(), textX, textY);
dc.DestroyClippingRegion();
}
void BBLTopbarArt::DrawBackground(wxDC& dc, wxWindow* wnd, const wxRect& rect)
{
dc.SetBrush(wxBrush(wxColour(38, 46, 48)));
@@ -257,21 +282,22 @@ void BBLTopbar::Init(wxFrame* parent)
m_calib_item = this->AddTool(ID_CALIB, _L("Calibration"), calib_bitmap);
m_calib_item->SetDisabledBitmap(calib_bitmap_inactive);
this->AddSpacer(FromDIP(10));
this->AddStretchSpacer(1);
this->AddSpacer(FromDIP(25));
//this->AddStretchSpacer(1);
m_title_item = this->AddLabel(ID_TITLE, "", FromDIP(TOPBAR_TITLE_WIDTH));
m_title_item->SetAlignment(wxALIGN_CENTRE);
m_title_ctrl = new CenteredTitle(this);
wxAuiToolBarItem* title_item = this->AddControl(m_title_ctrl, "");
title_item->SetProportion(1);
this->AddSpacer(FromDIP(10));
this->AddStretchSpacer(1);
this->AddSpacer(FromDIP(25));
//this->AddStretchSpacer(1);
m_publish_bitmap = create_scaled_bitmap("topbar_publish", nullptr, TOPBAR_ICON_SIZE);
m_publish_item = this->AddTool(ID_PUBLISH, "", m_publish_bitmap);
m_publish_disable_bitmap = create_scaled_bitmap("topbar_publish_disable", nullptr, TOPBAR_ICON_SIZE);
m_publish_item->SetDisabledBitmap(m_publish_disable_bitmap);
this->EnableTool(m_publish_item->GetId(), false);
this->AddSpacer(FromDIP(4));
//m_publish_bitmap = create_scaled_bitmap("topbar_publish", nullptr, TOPBAR_ICON_SIZE);
//m_publish_item = this->AddTool(ID_PUBLISH, "", m_publish_bitmap);
//m_publish_disable_bitmap = create_scaled_bitmap("topbar_publish_disable", nullptr, TOPBAR_ICON_SIZE);
//m_publish_item->SetDisabledBitmap(m_publish_disable_bitmap);
//this->EnableTool(m_publish_item->GetId(), false);
//this->AddSpacer(FromDIP(4));
/*wxBitmap model_store_bitmap = create_scaled_bitmap("topbar_store", nullptr, TOPBAR_ICON_SIZE);
m_model_store_item = this->AddTool(ID_MODEL_STORE, "", model_store_bitmap);
@@ -279,7 +305,7 @@ void BBLTopbar::Init(wxFrame* parent)
*/
//this->AddSeparator();
this->AddSpacer(FromDIP(4));
//this->AddSpacer(FromDIP(4));
wxBitmap iconize_bitmap = create_scaled_bitmap("topbar_min", nullptr, TOPBAR_ICON_SIZE);
wxAuiToolBarItem* iconize_btn = this->AddTool(wxID_ICONIZE_FRAME, "", iconize_bitmap);
@@ -324,7 +350,7 @@ void BBLTopbar::Init(wxFrame* parent)
this->Bind(wxEVT_AUITOOLBAR_TOOL_DROPDOWN, &BBLTopbar::OnRedo, this, wxID_REDO);
this->Bind(wxEVT_AUITOOLBAR_TOOL_DROPDOWN, &BBLTopbar::OnUndo, this, wxID_UNDO);
//this->Bind(wxEVT_AUITOOLBAR_TOOL_DROPDOWN, &BBLTopbar::OnModelStoreClicked, this, ID_MODEL_STORE);
this->Bind(wxEVT_AUITOOLBAR_TOOL_DROPDOWN, &BBLTopbar::OnPublishClicked, this, ID_PUBLISH);
//this->Bind(wxEVT_AUITOOLBAR_TOOL_DROPDOWN, &BBLTopbar::OnPublishClicked, this, ID_PUBLISH);
}
BBLTopbar::~BBLTopbar()
@@ -341,11 +367,11 @@ void BBLTopbar::OnOpenProject(wxAuiToolBarEvent& event)
plater->load_project();
}
void BBLTopbar::show_publish_button(bool show)
{
this->EnableTool(m_publish_item->GetId(), show);
Refresh();
}
//void BBLTopbar::show_publish_button(bool show)
//{
// this->EnableTool(m_publish_item->GetId(), show);
// Refresh();
//}
void BBLTopbar::OnSaveProject(wxAuiToolBarEvent& event)
{
@@ -446,12 +472,9 @@ wxMenu* BBLTopbar::GetCalibMenu()
void BBLTopbar::SetTitle(wxString title)
{
wxGCDC dc(this);
title = wxControl::Ellipsize(title, dc, wxELLIPSIZE_END, FromDIP(TOPBAR_TITLE_WIDTH));
m_title_item->SetLabel(title);
m_title_item->SetAlignment(wxALIGN_CENTRE);
this->Refresh();
m_titleText = title;
if (m_title_ctrl)
m_title_ctrl->SetTitle(title);
}
void BBLTopbar::SetMaximizedSize()
@@ -500,7 +523,8 @@ void BBLTopbar::Rescale() {
item->SetBitmap(create_scaled_bitmap("calib_sf", this, TOPBAR_ICON_SIZE));
item->SetDisabledBitmap(create_scaled_bitmap("calib_sf_inactive", this, TOPBAR_ICON_SIZE));
item = this->FindTool(ID_TITLE);
if (m_title_ctrl)
m_title_ctrl->SetTitle(m_titleText);
/*item = this->FindTool(ID_PUBLISH);
item->SetBitmap(create_scaled_bitmap("topbar_publish", this, TOPBAR_ICON_SIZE));
@@ -565,9 +589,9 @@ void BBLTopbar::OnCloseFrame(wxAuiToolBarEvent& event)
void BBLTopbar::OnMouseLeftDClock(wxMouseEvent& mouse)
{
wxPoint mouse_pos = ::wxGetMousePosition();
wxAuiToolBarItem* item = this->FindToolByCurrentPosition();
// check whether mouse is not on any tool item
if (this->FindToolByCurrentPosition() != NULL &&
this->FindToolByCurrentPosition() != m_title_item) {
if (item != NULL && item->GetWindow() != m_title_ctrl) {
mouse.Skip();
return;
}
@@ -635,10 +659,10 @@ void BBLTopbar::OnMouseLeftDown(wxMouseEvent& event)
{
wxPoint mouse_pos = ::wxGetMousePosition();
wxPoint frame_pos = m_frame->GetScreenPosition();
wxAuiToolBarItem* item = this->FindToolByCurrentPosition();
m_delta = mouse_pos - frame_pos;
if (FindToolByCurrentPosition() == NULL
|| this->FindToolByCurrentPosition() == m_title_item)
if (item == NULL || item->GetWindow() == m_title_ctrl)
{
#ifdef __WXMSW__
CaptureMouse();
@@ -728,8 +752,8 @@ WXLRESULT BBLTopbar::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam
{
switch (nMsg) {
case WM_NCHITTEST: {
const wxAuiToolBarItem* current_item = this->FindToolByCurrentPosition();
if (current_item != nullptr && current_item != m_title_item) {
wxAuiToolBarItem* item = this->FindToolByCurrentPosition();
if (item != NULL && item->GetWindow() != m_title_ctrl) {
break;
}
+19 -3
View File
@@ -6,9 +6,22 @@
#include "SelectMachine.hpp"
#include "DeviceManager.hpp"
#include <wx/control.h>
using namespace Slic3r::GUI;
class CenteredTitle : public wxControl
{
public:
CenteredTitle(wxWindow* parent);
void SetTitle(const wxString& title);
wxSize DoGetBestSize() const override;
private:
wxString m_title;
};
class BBLTopbar : public wxAuiToolBar
{
public:
@@ -31,7 +44,7 @@ public:
void OnMouseCaptureLost(wxMouseCaptureLostEvent& event);
void OnMenuClose(wxMenuEvent& event);
void OnOpenProject(wxAuiToolBarEvent& event);
void show_publish_button(bool show);
//void show_publish_button(bool show);
void OnSaveProject(wxAuiToolBarEvent& event);
void OnUndo(wxAuiToolBarEvent& event);
void OnRedo(wxAuiToolBarEvent& event);
@@ -70,11 +83,14 @@ private:
wxMenu m_top_menu;
wxMenu* m_file_menu;
wxMenu m_calib_menu;
wxAuiToolBarItem* m_title_item;
CenteredTitle* m_title_ctrl { nullptr };
wxString m_titleText;
wxAuiToolBarItem* m_account_item;
wxAuiToolBarItem* m_model_store_item;
wxAuiToolBarItem *m_publish_item;
//wxAuiToolBarItem *m_publish_item;
wxAuiToolBarItem* m_undo_item;
wxAuiToolBarItem* m_redo_item;
wxAuiToolBarItem* m_calib_item;
@@ -681,7 +681,6 @@ StringObjectException BackgroundSlicingProcess::validate(StringObjectException *
assert(m_print == m_fff_print);
m_fff_print->is_BBL_printer() = wxGetApp().preset_bundle->is_bbl_vendor();
m_fff_print->is_QIDI_printer() = wxGetApp().preset_bundle->is_qidi_vendor();
return m_print->validate(warning, collison_polygons, height_polygons);
}
+5 -4
View File
@@ -807,6 +807,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
toggle_field("single_extruder_multi_material", !is_BBL_Printer);
auto bSEMM = preset_bundle->printers.get_edited_preset().config.opt_bool("single_extruder_multi_material");
const bool supports_wipe_tower_2 = !is_BBL_Printer && preset_bundle->printers.get_edited_preset().config.opt_enum<WipeTowerType>("wipe_tower_type") == WipeTowerType::Type2;
toggle_field("ooze_prevention", !bSEMM);
bool have_ooze_prevention = config->opt_bool("ooze_prevention");
@@ -831,17 +832,17 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
"wipe_tower_extra_spacing", "wipe_tower_max_purge_speed",
"wipe_tower_bridging", "wipe_tower_extra_flow",
"wipe_tower_no_sparse_layers"})
toggle_line(el, have_prime_tower && !is_BBL_Printer);
toggle_line(el, have_prime_tower && supports_wipe_tower_2);
WipeTowerWallType wipe_tower_wall_type = config->opt_enum<WipeTowerWallType>("wipe_tower_wall_type");
bool have_rib_wall = (wipe_tower_wall_type == WipeTowerWallType::wtwRib)&&have_prime_tower;
toggle_line("wipe_tower_cone_angle", have_prime_tower && !is_BBL_Printer && wipe_tower_wall_type == WipeTowerWallType::wtwCone);
toggle_line("wipe_tower_cone_angle", have_prime_tower && supports_wipe_tower_2 && wipe_tower_wall_type == WipeTowerWallType::wtwCone);
toggle_line("wipe_tower_extra_rib_length", have_rib_wall);
toggle_line("wipe_tower_rib_width", have_rib_wall);
toggle_line("wipe_tower_fillet_wall", have_rib_wall);
toggle_field("prime_tower_width", have_prime_tower && !(is_BBL_Printer && have_rib_wall));
toggle_field("prime_tower_width", have_prime_tower && (supports_wipe_tower_2 || have_rib_wall));
toggle_line("single_extruder_multi_material_priming", !bSEMM && have_prime_tower && !is_BBL_Printer);
toggle_line("single_extruder_multi_material_priming", !bSEMM && have_prime_tower && supports_wipe_tower_2);
toggle_line("prime_volume",have_prime_tower && (!purge_in_primetower || !bSEMM));
+1 -1
View File
@@ -103,7 +103,7 @@ static const std::unordered_map<std::string, std::vector<std::string>> printer_m
"Creality Hi"}},
{"DeltaMaker", {"DeltaMaker 2", "DeltaMaker 2T", "DeltaMaker 2XT"}},
{"Dremel", {"Dremel 3D20", "Dremel 3D40", "Dremel 3D45"}},
{"Elegoo", {"Elegoo Centauri Carbon", "Elegoo Centauri", "Elegoo Neptune", "Elegoo Neptune X", "Elegoo Neptune 2",
{"Elegoo", {"Elegoo Centauri Carbon 2", "Elegoo Centauri Carbon", "Elegoo Centauri", "Elegoo Neptune", "Elegoo Neptune X", "Elegoo Neptune 2",
"Elegoo Neptune 2S", "Elegoo Neptune 2D", "Elegoo Neptune 3", "Elegoo Neptune 3 Pro", "Elegoo Neptune 3 Plus",
"Elegoo Neptune 3 Max", "Elegoo Neptune 4 Pro", "Elegoo Neptune 4", "Elegoo Neptune 4 Max", "Elegoo Neptune 4 Plus",
"Elegoo OrangeStorm Giga"}},
+54 -18
View File
@@ -101,43 +101,79 @@ ThumbnailErrors validate_thumbnails_string(wxString& str, const wxString& def_ex
return errors;
}
// Orca
wxString get_formatted_tooltip_text(const ConfigOptionDef& opt, const t_config_option_key& id)
{
wxString tooltip = _(opt.tooltip);
if (tooltip.length() > 0) {
edit_tooltip(tooltip);
std::string opt_id = id;
auto hash_pos = opt_id.find("#");
if (hash_pos != std::string::npos) {
opt_id.replace(hash_pos, 1,"[");
opt_id += "]";
}
std::string opt_id = id;
auto hash_pos = opt_id.find("#");
if (hash_pos != std::string::npos) {
opt_id.replace(hash_pos, 1,"[");
opt_id += "]";
}
tooltip += (tooltip.empty() ? "" : "\n\n") + _(L("parameter name")) + ": " + opt_id;
tooltip += "\n\n" + _(L("parameter name")) + ": " + opt_id;
// Orca:
// We can't use Orca's default values as-is because they sometimes depend on other values.
// Parent preset configuration values will be used instead.
if (const Preset* print_parent_preset = wxGetApp().preset_bundle->prints.get_selected_preset_parent()) {
const DynamicPrintConfig& parent_config = print_parent_preset->config;
if (opt.type == coFloat || opt.type == coInt) {
if (!parent_config.has(opt_id))
return tooltip;
wxString side_text = from_u8(opt.sidetext);
// Orca: a small hack for `layers` side text: adding a space before it for better looking text
if (opt.sidetext == L("layers"))
side_text = " " + _(side_text);
if (opt.type == coFloat || opt.type == coInt || opt.type == coPercent || opt.type == coFloatOrPercent) {
double default_value = 0.;
if (opt.type == coFloat)
default_value = opt.get_default_value<ConfigOptionFloat>()->value;
default_value = parent_config.option<ConfigOptionFloat>(opt_id)->value;
else if (opt.type == coInt)
default_value = opt.get_default_value<ConfigOptionInt>()->value;
default_value = parent_config.option<ConfigOptionInt>(opt_id)->value;
else if (opt.type == coPercent)
default_value = parent_config.option<ConfigOptionPercent>(opt_id)->value;
else if (opt.type == coFloatOrPercent) {
default_value = parent_config.option<ConfigOptionFloatOrPercent>(opt_id)->value;
if (parent_config.option<ConfigOptionFloatOrPercent>(opt_id)->percent)
side_text = "%";
else if (!side_text.empty()) {
static std::string postfix = " or %";
auto postfix_pos = side_text.find(postfix);
if (postfix_pos != std::string::npos)
side_text.erase(postfix_pos, postfix.length());
}
}
tooltip += "\n\n" + _(L("Default")) + ": " + _(double_to_string(default_value));
tooltip += "\n\n" + _(L("Default")) + ": " + _(double_to_string(default_value)) + _(side_text);
if (opt.min > -FLT_MAX && opt.max < FLT_MAX) {
tooltip += "\n" + _(L("Range")) + ": [" +
_(double_to_string(opt.min)) + ", " +
_(double_to_string(opt.max)) + "]";
_(double_to_string(opt.min)) + _(side_text) + ", " +
_(double_to_string(opt.max)) + _(side_text) + "]";
}
}
} else if (opt.type == coBool || opt.type == coString) {
std::string default_value = "";
return tooltip;
if (opt.type == coString)
default_value = parent_config.option<ConfigOptionString>(opt_id)->value;
else if (opt.type == coBool)
default_value = parent_config.option<ConfigOptionBool>(opt_id)->value ? "true" : "false";
tooltip += "\n\n" + _(L("Default")) + ": " +
(default_value.empty() ? _(L("Empty string")) : _(default_value) + _(side_text));
}
}
return "";
edit_tooltip(tooltip);
return tooltip;
}
Field::~Field()
+23 -1
View File
@@ -1629,7 +1629,29 @@ void GCodeViewer::update_sequential_view_current(unsigned int first, unsigned in
levels.push_back(std::make_pair(value, libvgcode::convert(color_range.get_color_at(value))));
levels.back().second.a(0.5f);
}
m_sequential_view.marker.set_actual_speed_data(actual_speed_data);
// ORCA Compress consecutive duplicate speeds with 0.1 precision
auto sameSpeed = [](float a, float b) {
return static_cast<int>(std::roundf(a * 10.0f)) == static_cast<int>(std::roundf(b * 10.0f));
};
std::vector<SequentialView::ActualSpeedImguiWidget::Item> compressed;
if (!actual_speed_data.empty()) {
compressed.push_back(actual_speed_data[0]);
for (int i = 1; i < (int)actual_speed_data.size(); ++i) {
const bool same_as_prev = sameSpeed(actual_speed_data[i].speed, actual_speed_data[i - 1].speed);
const bool same_as_next = (i + 1 < (int)actual_speed_data.size()) && sameSpeed(actual_speed_data[i].speed, actual_speed_data[i + 1].speed);
if (!same_as_prev) {
if (!sameSpeed(compressed.back().speed, actual_speed_data[i - 1].speed))
compressed.push_back(actual_speed_data[i - 1]);
compressed.push_back(actual_speed_data[i]);
} else if (!same_as_next)
compressed.push_back(actual_speed_data[i]);
}
if (compressed.back().pos != actual_speed_data.back().pos)
compressed.push_back(actual_speed_data.back());
}
m_sequential_view.marker.set_actual_speed_data(compressed);
m_sequential_view.marker.set_actual_speed_y_range(std::make_pair(interval[0], interval[1]));
m_sequential_view.marker.set_actual_speed_levels(levels);
}
+9 -30
View File
@@ -38,7 +38,6 @@
#include "slic3r/Utils/UndoRedo.hpp"
#include "slic3r/Utils/MacDarkMode.hpp"
#include <libslic3r/BoundingBox.hpp>
#include <slic3r/GUI/GUI_Utils.hpp>
#if ENABLE_RETINA_GL
@@ -2837,7 +2836,6 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
float y = dynamic_cast<const ConfigOptionFloats*>(proj_cfg.option("wipe_tower_y"))->get_at(plate_id);
float w = dynamic_cast<const ConfigOptionFloat*>(m_config->option("prime_tower_width"))->value;
float a = dynamic_cast<const ConfigOptionFloat*>(proj_cfg.option("wipe_tower_rotation_angle"))->value;
// BBS
float v = dynamic_cast<const ConfigOptionFloat*>(m_config->option("prime_volume"))->value;
Vec3d plate_origin = ppl.get_plate(plate_id)->get_origin();
@@ -2864,29 +2862,9 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
}
coordf_t plate_bbox_x_min_local_coord = plate_bbox_2d.min(0) - plate_origin(0);
coordf_t plate_bbox_y_min_local_coord = plate_bbox_2d.min(1) - plate_origin(1);
coordf_t plate_bbox_x_max_local_coord = plate_bbox_2d.max(0) - plate_origin(0);
coordf_t plate_bbox_y_max_local_coord = plate_bbox_2d.max(1) - plate_origin(1);
const float tower_w = (float) wipe_tower_size(0);
const float tower_h = (float) wipe_tower_size(1);
const float min_x = (float) plate_bbox_x_min_local_coord + margin;
const float max_x = (float) plate_bbox_x_max_local_coord - margin;
const float min_y = (float) plate_bbox_y_min_local_coord + margin;
const float max_y = (float) plate_bbox_y_max_local_coord - margin;
// snap wipe tower back to nearest edge if it was initially loaded outside the plate boundary
float new_x = (x < min_x) ? min_x : ((x + tower_w > max_x) ? (max_x - tower_w) : x);
float new_y = (y < min_y) ? min_y : ((y + tower_h > max_y) ? (max_y - tower_h) : y);
if (new_x != x || new_y != y) {
// do notification
_set_warning_notification(EWarning::PreviewPrimeTowerOutside, true);
x = new_x;
y = new_y;
}
if (!current_print->is_step_done(psWipeTower) || !current_print->wipe_tower_data().wipe_tower_mesh_data) {
// update for wipe tower position
{
@@ -4277,15 +4255,16 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
m_canvas->SetFocus();
if (evt.Entering()) {
//#if defined(__WXMSW__) || defined(__linux__)
// // On Windows and Linux needs focus in order to catch key events
// Set focus in order to remove it from sidebar fields
// Set focus in order to remove it from sidebar fields and ensure hotkeys work
if (m_canvas != nullptr) {
// Only set focus, if the top level window of this canvas is active.
// Only set focus if the top level window of this canvas is active.
auto p = dynamic_cast<wxWindow*>(evt.GetEventObject());
while (p->GetParent())
p = p->GetParent();
auto *top_level_wnd = dynamic_cast<wxTopLevelWindow*>(p);
//Orca: Set focus so hotkeys like 'tab' work when a notification is shown.
if (top_level_wnd != nullptr && top_level_wnd->IsActive())
m_canvas->SetFocus();
m_mouse.position = pos.cast<double>();
m_tooltip_enabled = false;
// 1) forces a frame render to ensure that m_hover_volume_idxs is updated even when the user right clicks while
@@ -4297,7 +4276,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
m_tooltip_enabled = true;
}
m_mouse.set_start_position_2D_as_invalid();
//#endif
}
else if (evt.Leaving()) {
// to remove hover on objects when the mouse goes out of this canvas
@@ -9665,9 +9643,6 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state)
case EWarning::PrimeTowerOutside:
text = _u8L("The prime tower extends beyond the plate boundary.");
break;
case EWarning::PreviewPrimeTowerOutside:
text = _u8L("Prime tower position exceeded build plate boundaries and was repositioned to the nearest valid edge.");
break;
case EWarning::NozzleFilamentIncompatible: {
text = _u8L(get_nozzle_filament_incompatible_text());
break;
@@ -9822,6 +9797,10 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state)
bool GLCanvas3D::is_flushing_matrix_error() {
// Flushing volumes only apply to single-extruder multi-material (SEMM) and BBL printers
if (!Sidebar::should_show_SEMM_buttons())
return false;
const auto &project_config = wxGetApp().preset_bundle->project_config;
const std::vector<double> &config_matrix = (project_config.option<ConfigOptionFloats>("flush_volumes_matrix"))->values;
const std::vector<double> &config_multiplier = (project_config.option<ConfigOptionFloats>("flush_multiplier"))->values;
+5 -6
View File
@@ -381,14 +381,13 @@ class GLCanvas3D
ToolHeightOutside,
TPUPrintableError,
FilamentPrintableError,
LeftExtruderPrintableError, // before slice
RightExtruderPrintableError, // before slice
MultiExtruderPrintableError, // after slice
MultiExtruderHeightOutside, // after slice
LeftExtruderPrintableError, // before slice
RightExtruderPrintableError, // before slice
MultiExtruderPrintableError, // after slice
MultiExtruderHeightOutside, // after slice
FilamentUnPrintableOnFirstLayer,
MixUsePLAAndPETG,
PrimeTowerOutside, // after slice
PreviewPrimeTowerOutside, // before slice
PrimeTowerOutside,
NozzleFilamentIncompatible,
MixtureFilamentIncompatible,
FlushingVolumeZero
+82 -50
View File
@@ -6199,7 +6199,7 @@ static const wxLanguageInfo* linux_get_existing_locale_language(const wxLanguage
if (! it->empty()) {
const std::string &locale = *it;
const wxLanguageInfo* lang = wxLocale::FindLanguageInfo(from_u8(locale));
if (wxLocale::IsAvailable(lang->Language))
if (lang != nullptr && wxLocale::IsAvailable(lang->Language))
return lang;
}
return language;
@@ -6241,7 +6241,10 @@ bool GUI_App::select_language()
names.Alloc(language_infos.size());
// Some valid language should be selected since the application start up.
const wxLanguage current_language = wxLanguage(m_wxLocale->GetLanguage());
const wxString active_language_code = current_language_code();
const wxLanguageInfo* active_language_info = wxLocale::FindLanguageInfo(active_language_code);
const wxLanguage current_language = active_language_info != nullptr ? wxLanguage(active_language_info->Language) : wxLanguage(m_wxLocale->GetLanguage());
const wxString active_lang_prefix = active_language_code.BeforeFirst('_');
int init_selection = -1;
int init_selection_alt = -1;
int init_selection_default = -1;
@@ -6249,9 +6252,9 @@ bool GUI_App::select_language()
if (wxLanguage(language_infos[i]->Language) == current_language)
// The dictionary matches the active language and country.
init_selection = i;
else if ((language_infos[i]->CanonicalName.BeforeFirst('_') == m_wxLocale->GetCanonicalName().BeforeFirst('_')) ||
else if ((language_infos[i]->CanonicalName.BeforeFirst('_') == active_lang_prefix) ||
// if the active language is Slovak, mark the Czech language as active.
(language_infos[i]->CanonicalName.BeforeFirst('_') == "cs" && m_wxLocale->GetCanonicalName().BeforeFirst('_') == "sk"))
(language_infos[i]->CanonicalName.BeforeFirst('_') == "cs" && active_lang_prefix == "sk"))
// The dictionary matches the active language, it does not necessarily match the country.
init_selection_alt = i;
if (language_infos[i]->CanonicalName.BeforeFirst('_') == "en")
@@ -6369,7 +6372,10 @@ bool GUI_App::load_language(wxString language, bool initial)
language_info = wxLocale::GetLanguageInfo(wxLANGUAGE_ENGLISH_US);
}
BOOST_LOG_TRIVIAL(trace) << boost::format("Switching wxLocales to %1%") % language_info->CanonicalName.ToUTF8().data();
const wxLanguageInfo *translation_language_info = language_info;
const wxString requested_language_code = translation_language_info->CanonicalName;
const wxLanguageInfo *locale_language_info = translation_language_info;
BOOST_LOG_TRIVIAL(trace) << boost::format("Requested translation language %1%") % requested_language_code.ToUTF8().data();
// Select language for locales. This language may be different from the language of the dictionary.
//if (language_info == m_language_info_best || language_info == m_language_info_system) {
@@ -6382,8 +6388,8 @@ bool GUI_App::load_language(wxString language, bool initial)
// language_info = m_language_info_system;
// Alternate language code.
wxLanguage language_dict = wxLanguage(language_info->Language);
if (language_info->CanonicalName.BeforeFirst('_') == "sk") {
wxLanguage language_dict = wxLanguage(translation_language_info->Language);
if (translation_language_info->CanonicalName.BeforeFirst('_') == "sk") {
// Slovaks understand Czech well. Give them the Czech translation.
language_dict = wxLANGUAGE_CZECH;
BOOST_LOG_TRIVIAL(info) << "Using Czech dictionaries for Slovak language";
@@ -6392,19 +6398,34 @@ bool GUI_App::load_language(wxString language, bool initial)
#ifdef __linux__
// If we can't find this locale , try to use different one for the language
// instead of just reporting that it is impossible to switch.
if (! wxLocale::IsAvailable(language_info->Language) && m_language_info_system) {
std::string original_lang = into_u8(language_info->CanonicalName);
language_info = linux_get_existing_locale_language(language_info, m_language_info_system);
BOOST_LOG_TRIVIAL(info) << boost::format("Can't switch language to %1% (missing locales). Using %2% instead.")
% original_lang % language_info->CanonicalName.ToUTF8().data();
if (!wxLocale::IsAvailable(locale_language_info->Language) && m_language_info_system) {
std::string original_lang = into_u8(locale_language_info->CanonicalName);
locale_language_info = linux_get_existing_locale_language(locale_language_info, m_language_info_system);
if (locale_language_info != nullptr && locale_language_info != translation_language_info) {
BOOST_LOG_TRIVIAL(info) << boost::format("Can't use locale %1% directly (missing locales). Using locale %2% instead.")
% original_lang % locale_language_info->CanonicalName.ToUTF8().data();
}
}
if (locale_language_info == nullptr || !wxLocale::IsAvailable(locale_language_info->Language)) {
auto try_locale = [](const wxLanguageInfo* candidate) -> const wxLanguageInfo* {
return (candidate && wxLocale::IsAvailable(candidate->Language)) ? candidate : nullptr;
};
const wxLanguageInfo* fallback_locale_info =
try_locale(m_wxLocale ? wxLocale::GetLanguageInfo(wxLanguage(m_wxLocale->GetLanguage())) : nullptr);
if (!fallback_locale_info) fallback_locale_info = try_locale(m_language_info_system);
if (!fallback_locale_info) fallback_locale_info = try_locale(m_language_info_best);
if (!fallback_locale_info) fallback_locale_info = try_locale(wxLocale::GetLanguageInfo(wxLANGUAGE_ENGLISH_US));
if (!fallback_locale_info) fallback_locale_info = try_locale(wxLocale::GetLanguageInfo(wxLANGUAGE_ENGLISH_UK));
if (fallback_locale_info != nullptr) {
BOOST_LOG_TRIVIAL(info) << boost::format("Using fallback locale %1% while keeping translation dictionary %2%.")
% fallback_locale_info->CanonicalName.ToUTF8().data() % requested_language_code.ToUTF8().data();
locale_language_info = fallback_locale_info;
}
}
#endif
if (! wxLocale::IsAvailable(language_info->Language)&&initial) {
language_info = wxLocale::GetLanguageInfo(wxLANGUAGE_ENGLISH_UK);
app_config->set("language", language_info->CanonicalName.ToUTF8().data());
}
else if (initial) {
if (initial) {
// bbs supported languages
//TODO: use a global one with Preference
//wxLanguage supported_languages[]{
@@ -6438,9 +6459,11 @@ bool GUI_App::load_language(wxString language, bool initial)
//}
}
if (! wxLocale::IsAvailable(language_info->Language)) {
BOOST_LOG_TRIVIAL(trace) << boost::format("Switching wxLocales to %1%") % locale_language_info->CanonicalName.ToUTF8().data();
if (!wxLocale::IsAvailable(locale_language_info->Language)) {
// Loading the language dictionary failed.
wxString message = "Switching Orca Slicer to language " + language_info->CanonicalName + " failed.";
wxString message = "Switching Orca Slicer to language " + requested_language_code + " failed.";
#if !defined(_WIN32) && !defined(__APPLE__)
// likely some linux system
message += "\nYou may need to reconfigure the missing locales, likely by running the \"locale-gen\" and \"dpkg-reconfigure locales\" commands.\n";
@@ -6458,12 +6481,13 @@ bool GUI_App::load_language(wxString language, bool initial)
//FIXME wxWidgets cause havoc if the current locale is deleted. We just forget it causing memory leaks for now.
m_wxLocale.release();
m_wxLocale = Slic3r::make_unique<wxLocale>();
m_wxLocale->Init(language_info->Language);
m_wxLocale->Init(locale_language_info->Language);
// Override language at the active wxTranslations class (which is stored in the active m_wxLocale)
// to load possibly different dictionary, for example, load Czech dictionary for Slovak language.
wxTranslations::Get()->SetLanguage(language_dict);
m_wxLocale->AddCatalog(SLIC3R_APP_KEY);
m_imgui->set_language(into_u8(language_info->CanonicalName));
m_active_language_code = requested_language_code;
m_imgui->set_language(into_u8(requested_language_code));
//FIXME This is a temporary workaround, the correct solution is to switch to "C" locale during file import / export only.
//wxSetlocale(LC_NUMERIC, "C");
@@ -6751,49 +6775,57 @@ void GUI_App::show_ip_address_enter_dialog_handler(wxCommandEvent& evt)
void GUI_App::open_preferences(size_t open_on_tab, const std::string& highlight_option)
{
bool app_layout_changed = false;
bool need_recreate_gui = false;
std::string pending_language;
{
// the dialog needs to be destroyed before the call to recreate_GUI()
// or sometimes the application crashes into wxDialogBase() destructor
// so we put it into an inner scope
PreferencesDialog dlg(mainframe, open_on_tab, highlight_option);
dlg.ShowModal();
this->plater_->get_current_canvas3D()->force_set_focus();
// BBS
//app_layout_changed = dlg.settings_layout_changed();
need_recreate_gui = dlg.recreate_GUI();
pending_language = dlg.pending_language();
if (!need_recreate_gui) {
this->plater_->get_current_canvas3D()->force_set_focus();
#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER
if (dlg.seq_top_layer_only_changed() || dlg.seq_seq_top_gcode_indices_changed())
if (dlg.seq_top_layer_only_changed() || dlg.seq_seq_top_gcode_indices_changed())
#else
if (dlg.seq_top_layer_only_changed())
if (dlg.seq_top_layer_only_changed())
#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER
this->plater_->reload_print();
this->plater_->reload_print();
#ifdef _WIN32
if (is_editor()) {
if (app_config->get("associate_3mf") == "true")
associate_files(L"3mf");
if (app_config->get("associate_stl") == "true")
associate_files(L"stl");
if (app_config->get("associate_step") == "true") {
associate_files(L"step");
associate_files(L"stp");
if (is_editor()) {
if (app_config->get("associate_3mf") == "true")
associate_files(L"3mf");
if (app_config->get("associate_stl") == "true")
associate_files(L"stl");
if (app_config->get("associate_step") == "true") {
associate_files(L"step");
associate_files(L"stp");
}
associate_url(L"orcaslicer");
}
else {
if (app_config->get("associate_gcode") == "true")
associate_files(L"gcode");
}
associate_url(L"orcaslicer");
}
else {
if (app_config->get("associate_gcode") == "true")
associate_files(L"gcode");
}
#endif // _WIN32
}
}
// BBS
/*
if (app_layout_changed) {
// hide full main_sizer for mainFrame
mainframe->GetSizer()->Show(false);
mainframe->update_layout();
mainframe->select_tab(size_t(0));
}*/
if (!pending_language.empty()) {
const std::string previous_language = app_config->get("language");
app_config->set("language", pending_language);
if (!load_language(wxString::FromUTF8(pending_language), false)) {
app_config->set("language", previous_language);
if (this->plater_)
this->plater_->get_current_canvas3D()->force_set_focus();
return;
}
}
if (need_recreate_gui)
recreate_GUI(_L("Changing application language"));
}
bool GUI_App::has_unsaved_preset_changes() const
+2 -1
View File
@@ -273,6 +273,7 @@ private:
const wxLanguageInfo *m_language_info_system = nullptr;
// Best translation language, provided by Windows or OSX, owned by wxWidgets.
const wxLanguageInfo *m_language_info_best = nullptr;
wxString m_active_language_code;
OpenGLManager m_opengl_mgr;
std::unique_ptr<RemovableDriveManager> m_removable_drive_manager;
@@ -563,7 +564,7 @@ public:
void preset_deleted_from_cloud(std::string setting_id);
wxString filter_string(wxString str);
wxString current_language_code() const { return m_wxLocale->GetCanonicalName(); }
wxString current_language_code() const { return m_active_language_code.empty() && m_wxLocale ? m_wxLocale->GetCanonicalName() : m_active_language_code; }
// Translate the language code to a code, for which Prusa Research maintains translations. Defaults to "en_US".
wxString current_language_code_safe() const;
bool is_localized() const { return m_wxLocale->GetLocale() != "English"; }
+1 -1
View File
@@ -678,7 +678,7 @@ void GLGizmoMeasure::on_render()
m_mesh_raycaster_map[m_last_hit_volume]->get_transform(), m_only_select_plane) :
std::nullopt;
}
if (m_measure_mode == EMeasureMode::ONLY_ASSEMBLY) {
if (m_measure_mode == EMeasureMode::ONLY_ASSEMBLY && curr_feature.has_value()) {
if (m_assembly_mode == AssemblyMode::FACE_FACE) {
if (curr_feature->get_type() != Measure::SurfaceFeatureType::Plane) {
curr_feature.reset();
+59 -21
View File
@@ -475,7 +475,9 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, BORDERLESS_FRAME_
update_edge_panels();
#endif
wxQueueEvent(wxGetApp().plater(), new SimpleEvent(EVT_NOTICE_CHILDE_SIZE_CHANGED));
});
fit_tab_labels(); // ORCA on resize
});
//BBS
Bind(EVT_SELECT_TAB, [this](wxCommandEvent&evt) {
@@ -1242,6 +1244,7 @@ void MainFrame::init_tabpanel() {
wxPostEvent(m_plater, SimpleEvent(EVT_GLVIEWTOOLBAR_PREVIEW));
m_param_panel->OnActivate();
}
fit_tab_labels(); // ORCA on switching prepare / preview
}
//else if (panel == m_param_panel)
// m_param_panel->OnActivate();
@@ -1345,8 +1348,10 @@ void MainFrame::init_tabpanel() {
void MainFrame::show_device(bool bBBLPrinter) {
auto idx = -1;
if (bBBLPrinter) {
if (m_tabpanel->FindPage(m_monitor) != wxNOT_FOUND)
if (m_tabpanel->FindPage(m_monitor) != wxNOT_FOUND) {
fit_tab_labels(); // ORCA on printer change - same button layout
return;
}
// Remove printer view
if ((idx = m_tabpanel->FindPage(m_printer_view)) != wxNOT_FOUND) {
m_printer_view->Show(false);
@@ -1386,9 +1391,10 @@ void MainFrame::show_device(bool bBBLPrinter) {
#endif // _MSW_DARK_MODE
} else {
if (m_tabpanel->FindPage(m_printer_view) != wxNOT_FOUND)
if (m_tabpanel->FindPage(m_printer_view) != wxNOT_FOUND) {
fit_tab_labels(); // ORCA on printer change - same button layout
return;
}
if ((idx = m_tabpanel->FindPage(m_calibration)) != wxNOT_FOUND) {
m_calibration->Show(false);
m_tabpanel->RemovePage(idx);
@@ -1414,6 +1420,33 @@ void MainFrame::show_device(bool bBBLPrinter) {
m_tabpanel->InsertPage(tpMonitor, m_printer_view, _L("Device"), std::string("tab_monitor_active"),
std::string("tab_monitor_active"));
}
fit_tab_labels(); // ORCA on printer change
}
void MainFrame::fit_tab_labels()
{
if (!m_tabpanel || !m_slice_option_btn) // ignore layout change while slice/print buttons not visible
return;
auto* ctrl = m_tabpanel->GetBtnsListCtrl();
auto* sizer = ctrl->GetBtnsSizer();
int count = sizer->GetItemCount();
// Restore all
for (size_t i = 1; i < count; ++i)
ctrl->SetCompact(i, false);
m_tabpanel->Refresh();
Layout();
// Compact (last to first)
for (size_t i = count - 1; i >= 1; --i) {
int right = ScreenToClient(m_slice_option_btn->ClientToScreen({})).x;
int left = sizer->GetSize().GetWidth();
if (right - left - FromDIP(15) > 0) return;
ctrl->SetCompact(i, true);
m_tabpanel->Refresh();
Layout();
}
}
bool MainFrame::preview_only_hint()
@@ -1790,7 +1823,7 @@ wxBoxSizer* MainFrame::create_side_tools()
update_side_button_style();
m_slice_option_btn->Enable();
m_print_option_btn->Enable();
sizer->Add(FromDIP(15), 0, 0, 0, 0);
//sizer->Add(FromDIP(15), 0, 0, 0, 0);
sizer->Add(slice_panel);
sizer->Add(FromDIP(15), 0, 0, 0, 0);
sizer->Add(print_panel);
@@ -1915,6 +1948,7 @@ wxBoxSizer* MainFrame::create_side_tools()
m_slice_enable = get_enable_slice_status();
m_slice_btn->Enable(m_slice_enable);
this->Layout();
fit_tab_labels(); // ORCA on label change
if(m_slice_option_pop_up)
m_slice_option_pop_up->Dismiss();
});
@@ -1925,6 +1959,7 @@ wxBoxSizer* MainFrame::create_side_tools()
m_slice_enable = get_enable_slice_status();
m_slice_btn->Enable(m_slice_enable);
this->Layout();
fit_tab_labels(); // ORCA on label change
if(m_slice_option_pop_up)
m_slice_option_pop_up->Dismiss();
});
@@ -1949,6 +1984,7 @@ wxBoxSizer* MainFrame::create_side_tools()
m_print_enable = get_enable_print_status();
m_print_btn->Enable(m_print_enable);
this->Layout();
fit_tab_labels(); // ORCA on label change
p->Dismiss();
});
@@ -1961,6 +1997,7 @@ wxBoxSizer* MainFrame::create_side_tools()
m_print_enable = get_enable_print_status();
m_print_btn->Enable(m_print_enable);
this->Layout();
fit_tab_labels(); // ORCA on label change
p->Dismiss();
});
@@ -1987,6 +2024,7 @@ wxBoxSizer* MainFrame::create_side_tools()
m_print_enable = get_enable_print_status();
m_print_btn->Enable(m_print_enable);
this->Layout();
fit_tab_labels(); // ORCA on label change
p->Dismiss();
});
@@ -1998,6 +2036,7 @@ wxBoxSizer* MainFrame::create_side_tools()
m_print_enable = get_enable_print_status();
m_print_btn->Enable(m_print_enable);
this->Layout();
fit_tab_labels(); // ORCA on label change
p->Dismiss();
});
@@ -2007,6 +2046,7 @@ wxBoxSizer* MainFrame::create_side_tools()
m_print_enable = get_enable_print_status();
m_print_btn->Enable(m_print_enable);
this->Layout();
fit_tab_labels(); // ORCA on label change
p->Dismiss();
});
@@ -2018,6 +2058,7 @@ wxBoxSizer* MainFrame::create_side_tools()
m_print_enable = get_enable_print_status();
m_print_btn->Enable(m_print_enable);
this->Layout();
fit_tab_labels(); // ORCA on label change
p->Dismiss();
});
@@ -2027,6 +2068,7 @@ wxBoxSizer* MainFrame::create_side_tools()
m_print_enable = get_enable_print_status();
m_print_btn->Enable(m_print_enable);
this->Layout();
fit_tab_labels(); // ORCA on label change
p->Dismiss();
});
@@ -2036,6 +2078,7 @@ wxBoxSizer* MainFrame::create_side_tools()
m_print_enable = get_enable_print_status();
m_print_btn->Enable(m_print_enable);
this->Layout();
fit_tab_labels(); // ORCA on label change
p->Dismiss();
});
@@ -2074,6 +2117,7 @@ wxBoxSizer* MainFrame::create_side_tools()
m_print_enable = get_enable_print_status();
m_print_btn->Enable(m_print_enable);
this->Layout();
fit_tab_labels(); // ORCA on label change
p->Dismiss();
});
p->append_button(print_multi_machine_btn);
@@ -2088,6 +2132,7 @@ wxBoxSizer* MainFrame::create_side_tools()
m_print_enable = get_enable_print_status();
m_print_btn->Enable(m_print_enable);
this->Layout();
fit_tab_labels(); // ORCA on label change
p->Dismiss();
});
p->append_button(export_gcode_btn);
@@ -2400,6 +2445,8 @@ void MainFrame::on_dpi_changed(const wxRect& suggested_rect)
this->SetSize(sz);
this->Maximize(is_maximized);
fit_tab_labels(); // ORCA
}
void MainFrame::on_sys_color_changed()
@@ -2485,7 +2532,7 @@ static wxMenu* generate_help_menu()
// //TODO
// });
// Check New Version
append_menu_item(helpMenu, wxID_ANY, _L("Check for Update"), _L("Check for Update"),
append_menu_item(helpMenu, wxID_ANY, _L("Check for Updates"), _L("Check for Updates"),
[](wxCommandEvent&) {
wxGetApp().check_new_version_sf(true, 1);
}, "", nullptr, []() {
@@ -3145,15 +3192,7 @@ void MainFrame::init_menubar_as_editor()
append_menu_item(
parent_menu, wxID_ANY, _L("Preferences") + "\t" + ctrl + ",", "",
[this](wxCommandEvent &) {
PreferencesDialog dlg(this);
dlg.ShowModal();
plater()->get_current_canvas3D()->force_set_focus();
#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER
if (dlg.seq_top_layer_only_changed() || dlg.seq_seq_top_gcode_indices_changed())
#else
if (dlg.seq_top_layer_only_changed())
#endif
plater()->reload_print();
wxGetApp().open_preferences();
},
"", nullptr, []() { return true; }, this, 1);
//parent_menu->Insert(1, preference_item);
@@ -3174,7 +3213,6 @@ void MainFrame::init_menubar_as_editor()
[this](wxCommandEvent &) {
// Orca: Use GUI_App::open_preferences instead of direct call so windows associations are updated on exit
wxGetApp().open_preferences();
plater()->get_current_canvas3D()->force_set_focus();
},
"", nullptr, []() { return true; }, this);
//m_topbar->AddDropDownMenuItem(preference_item);
@@ -3215,20 +3253,20 @@ void MainFrame::init_menubar_as_editor()
// Flow rate (with submenu)
auto flowrate_menu = new wxMenu();
append_menu_item(
flowrate_menu, wxID_ANY, _L("Pass 1"), _L("Flow rate test - Pass 1"),
flowrate_menu, wxID_ANY, _L("Pass 1"), _L("Flow ratio test - Pass 1"),
[this](wxCommandEvent&) { if (m_plater) m_plater->calib_flowrate(false, 1); }, "", nullptr,
[this]() {return m_plater->is_view3D_shown();; }, this);
append_menu_item(flowrate_menu, wxID_ANY, _L("Pass 2"), _L("Flow rate test - Pass 2"),
append_menu_item(flowrate_menu, wxID_ANY, _L("Pass 2"), _L("Flow ratio test - Pass 2"),
[this](wxCommandEvent&) { if (m_plater) m_plater->calib_flowrate(false, 2); }, "", nullptr,
[this]() {return m_plater->is_view3D_shown();; }, this);
flowrate_menu->AppendSeparator();
append_menu_item(flowrate_menu, wxID_ANY, _L("YOLO (Recommended)"), _L("Orca YOLO flowrate calibration, 0.01 step"),
append_menu_item(flowrate_menu, wxID_ANY, _L("YOLO (Recommended)"), _L("Orca YOLO flowratio calibration, 0.01 step"),
[this](wxCommandEvent&) { if (m_plater) m_plater->calib_flowrate(true, 1); }, "", nullptr,
[this]() {return m_plater->is_view3D_shown();; }, this);
append_menu_item(flowrate_menu, wxID_ANY, _L("YOLO (perfectionist version)"), _L("Orca YOLO flowrate calibration, 0.005 step"),
append_menu_item(flowrate_menu, wxID_ANY, _L("YOLO (perfectionist version)"), _L("Orca YOLO flowratio calibration, 0.005 step"),
[this](wxCommandEvent&) { if (m_plater) m_plater->calib_flowrate(true, 2); }, "", nullptr,
[this]() {return m_plater->is_view3D_shown();; }, this);
m_topbar->GetCalibMenu()->AppendSubMenu(flowrate_menu, _L("Flow rate"));
m_topbar->GetCalibMenu()->AppendSubMenu(flowrate_menu, _L("Flow ratio"));
// Retraction test
append_menu_item(m_topbar->GetCalibMenu(), wxID_ANY, _L("Retraction test"), _L("Retraction test"),
+1
View File
@@ -359,6 +359,7 @@ public:
//SoftFever
void show_device(bool bBBLPrinter);
void fit_tab_labels(); // ORCA
PA_Calibration_Dlg* m_pa_calib_dlg{ nullptr };
Temp_Calibration_Dlg* m_temp_calib_dlg{ nullptr };
+4 -4
View File
@@ -67,10 +67,10 @@ private:
static bool get_stream_url(std::string *url = nullptr);
private:
static const wxMediaState MEDIASTATE_IDLE = (wxMediaState) 3;
static const wxMediaState MEDIASTATE_INITIALIZING = (wxMediaState) 4;
static const wxMediaState MEDIASTATE_LOADING = (wxMediaState) 5;
static const wxMediaState MEDIASTATE_BUFFERING = (wxMediaState) 6;
static inline const wxMediaState MEDIASTATE_IDLE = static_cast<wxMediaState>(3);
static inline const wxMediaState MEDIASTATE_INITIALIZING = static_cast<wxMediaState>(4);
static inline const wxMediaState MEDIASTATE_LOADING = static_cast<wxMediaState>(5);
static inline const wxMediaState MEDIASTATE_BUFFERING = static_cast<wxMediaState>(6);
// token
std::shared_ptr<int> m_token = std::make_shared<int>(0);
+13
View File
@@ -202,6 +202,7 @@ bool ButtonsListCtrl::InsertPage(size_t n, const wxString &text, bool bSelect /*
});
Slic3r::GUI::wxGetApp().UpdateDarkUI(btn);
m_pageButtons.insert(m_pageButtons.begin() + n, btn);
m_pageLabels.insert(m_pageLabels.begin() + n, text); // ORCA
m_buttons_sizer->Insert(n, new wxSizerItem(btn));
m_buttons_sizer->SetCols(m_buttons_sizer->GetCols() + 1);
m_sizer->Layout();
@@ -212,6 +213,7 @@ void ButtonsListCtrl::RemovePage(size_t n)
{
Button* btn = m_pageButtons[n];
m_pageButtons.erase(m_pageButtons.begin() + n);
m_pageLabels.erase(m_pageLabels.begin() + n); // ORCA
m_buttons_sizer->Remove(n);
#if __WXOSX__
RemoveChild(btn);
@@ -238,6 +240,17 @@ void ButtonsListCtrl::SetPageText(size_t n, const wxString& strText)
{
Button* btn = m_pageButtons[n];
btn->SetLabel(strText);
if(!strText.empty()) // ORCA
m_pageLabels[n] = strText;
}
// ORCA
void ButtonsListCtrl::SetCompact(size_t n, bool compact)
{
int em = em_unit(this);
Button* btn = m_pageButtons[n];
btn->SetMinSize({(compact ? 40 : 136) * em / 10, 36 * em / 10});
btn->SetLabel(compact ? "" : (" " + m_pageLabels[n]));
}
wxString ButtonsListCtrl::GetPageText(size_t n) const
+3
View File
@@ -28,7 +28,9 @@ public:
void RemovePage(size_t n);
bool SetPageImage(size_t n, const std::string& bmp_name) const;
void SetPageText(size_t n, const wxString& strText);
void SetCompact(size_t n, bool compact); // ORCA
wxString GetPageText(size_t n) const;
wxFlexGridSizer* GetBtnsSizer(){return m_buttons_sizer;}; // ORCA
private:
wxFlexGridSizer* m_buttons_sizer;
@@ -39,6 +41,7 @@ private:
int m_btn_margin;
int m_line_margin;
//ModeSizer* m_mode_sizer {nullptr};
std::vector<wxString> m_pageLabels; // ORCA
};
class Notebook: public wxBookCtrlBase
+98 -52
View File
@@ -3079,53 +3079,42 @@ bool PartPlate::set_shape(const Pointfs& shape, const Pointfs& exclude_areas, co
calc_bounding_boxes();
ExPolygon logo_poly;
generate_logo_polygon(logo_poly);
m_logo_triangles.reset();
if (!init_model_from_poly(m_logo_triangles, logo_poly, GROUND_Z + 0.02f))
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ":Unable to create logo triangles\n";
if (m_plater != nullptr) { // render data, skip in CLI mode where m_plater is null
ExPolygon logo_poly;
generate_logo_polygon(logo_poly);
m_logo_triangles.reset();
if (!init_model_from_poly(m_logo_triangles, logo_poly, GROUND_Z + 0.02f))
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ":Unable to create logo triangles\n";
ExPolygon poly;
/*for (const Vec2d& p : m_shape) {
poly.contour.append({ scale_(p(0)), scale_(p(1)) });
}*/
generate_print_polygon(poly);
calc_triangles(poly);
ExPolygon poly;
generate_print_polygon(poly);
calc_triangles(poly);
// reset m_wrapping_detection_triangles when change printer
m_print_polygon = poly;
m_wrapping_detection_triangles.reset();
init_raycaster_from_model(m_triangles);
// reset m_wrapping_detection_triangles when change printer
m_print_polygon = poly;
m_wrapping_detection_triangles.reset();
init_raycaster_from_model(m_triangles);
ExPolygon exclude_poly;
/*for (const Vec2d& p : m_exclude_area) {
exclude_poly.contour.append({ scale_(p(0)), scale_(p(1)) });
}*/
generate_exclude_polygon(exclude_poly);
calc_exclude_triangles(exclude_poly);
ExPolygon exclude_poly;
generate_exclude_polygon(exclude_poly);
calc_exclude_triangles(exclude_poly);
const BoundingBox& pp_bbox = poly.contour.bounding_box();
calc_gridlines(poly, pp_bbox);
const BoundingBox& pp_bbox = poly.contour.bounding_box();
calc_gridlines(poly, pp_bbox);
//calc_vertex_for_icons_background(5, m_del_and_background_icon);
//calc_vertex_for_icons(4, m_del_icon);
calc_vertex_for_icons(0, m_del_icon);
calc_vertex_for_icons(1, m_orient_icon);
calc_vertex_for_icons(2, m_arrange_icon);
calc_vertex_for_icons(3, m_lock_icon);
calc_vertex_for_icons(4, m_plate_settings_icon);
// ORCA also change bed_icon_count number in calc_vertex_for_icons() after adding or removing icons for circular shaped beds that uses vertical alingment for icons
bool dual_bbl = false;
if (m_plater) {
PresetBundle* preset = wxGetApp().preset_bundle;
dual_bbl = (preset->is_bbl_vendor() && preset->get_printer_extruder_count() == 2);
}
calc_vertex_for_icons(dual_bbl ? 5 : 6, m_plate_filament_map_icon);
calc_vertex_for_icons(dual_bbl ? 6 : 5, m_move_front_icon);
calc_vertex_for_icons(0, m_del_icon);
calc_vertex_for_icons(1, m_orient_icon);
calc_vertex_for_icons(2, m_arrange_icon);
calc_vertex_for_icons(3, m_lock_icon);
calc_vertex_for_icons(4, m_plate_settings_icon);
// ORCA also change bed_icon_count number in calc_vertex_for_icons() after adding or removing icons for circular shaped beds that uses vertical alingment for icons
bool dual_bbl = false;
PresetBundle* preset = wxGetApp().preset_bundle;
dual_bbl = (preset->is_bbl_vendor() && preset->get_printer_extruder_count() == 2);
calc_vertex_for_icons(dual_bbl ? 5 : 6, m_plate_filament_map_icon);
calc_vertex_for_icons(dual_bbl ? 6 : 5, m_move_front_icon);
//calc_vertex_for_number(0, (m_plate_index < 9), m_plate_idx_icon);
calc_vertex_for_number(0, false, m_plate_idx_icon);
if (m_plater) {
calc_vertex_for_number(0, false, m_plate_idx_icon);
// calc vertex for plate name
generate_plate_name_texture();
}
@@ -3766,11 +3755,6 @@ void PartPlateList::init()
m_plate_cols = 1;
m_current_plate = 0;
if (m_plater) {
// In GUI mode
set_default_wipe_tower_pos_for_plate(0);
}
select_plate(0);
unprintable_plate.set_index(1);
@@ -4069,7 +4053,7 @@ void PartPlateList::release_icon_textures()
}
}
void PartPlateList::set_default_wipe_tower_pos_for_plate(int plate_idx)
void PartPlateList::set_default_wipe_tower_pos_for_plate(int plate_idx, bool init_pos)
{
DynamicConfig & proj_cfg = wxGetApp().preset_bundle->project_config;
ConfigOptionFloats *wipe_tower_x = proj_cfg.opt<ConfigOptionFloats>("wipe_tower_x");
@@ -4079,12 +4063,69 @@ void PartPlateList::set_default_wipe_tower_pos_for_plate(int plate_idx)
auto printer_structure_opt = wxGetApp().preset_bundle->printers.get_edited_preset().config.option<ConfigOptionEnum<PrinterStructure>>("printer_structure");
// set the default position, the same with print config(left top)
ConfigOptionFloat wt_x_opt(WIPE_TOWER_DEFAULT_X_POS);
ConfigOptionFloat wt_y_opt(WIPE_TOWER_DEFAULT_Y_POS);
float x = WIPE_TOWER_DEFAULT_X_POS;
float y = WIPE_TOWER_DEFAULT_Y_POS;
if (printer_structure_opt && printer_structure_opt->value == PrinterStructure::psI3) {
wt_x_opt = ConfigOptionFloat(I3_WIPE_TOWER_DEFAULT_X_POS);
wt_y_opt = ConfigOptionFloat(I3_WIPE_TOWER_DEFAULT_Y_POS);
x = I3_WIPE_TOWER_DEFAULT_X_POS;
y = I3_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();
BoundingBoxf plate_bbox_2d(Vec2d(plate_bbox.min(0), plate_bbox.min(1)), Vec2d(plate_bbox.max(0), plate_bbox.max(1)));
const std::vector<Pointfs> &extruder_areas = part_plate->get_extruder_areas();
for (const Pointfs &points : extruder_areas) {
BoundingBoxf bboxf(points);
plate_bbox_2d.min = plate_bbox_2d.min(0) >= bboxf.min(0) ? plate_bbox_2d.min : bboxf.min;
plate_bbox_2d.max = plate_bbox_2d.max(0) <= bboxf.max(0) ? plate_bbox_2d.max : bboxf.max;
}
coordf_t plate_bbox_x_min_local_coord = plate_bbox_2d.min(0) - plate_origin(0);
coordf_t plate_bbox_x_max_local_coord = plate_bbox_2d.max(0) - plate_origin(0);
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);
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;
bool enable_wrapping = false;
const ConfigOptionBool *wrapping_opt = dynamic_cast<const ConfigOptionBool *>(full_config.option("enable_wrapping_detection"));
if (wrapping_opt) enable_wrapping = wrapping_opt->value;
int nozzle_nums = wxGetApp().preset_bundle->get_printer_extruder_count();
Vec3d wipe_tower_size = part_plate->estimate_wipe_tower_size(print_cfg, w, v, nozzle_nums, init_pos ? 2 : 0, false, enable_wrapping);
if (!init_pos && (is_approx(wipe_tower_size(0), 0.0) || is_approx(wipe_tower_size(1), 0.0))) {
wipe_tower_size = part_plate->estimate_wipe_tower_size(print_cfg, w, v, nozzle_nums, 2, false, enable_wrapping);
}
// Compute brim-aware margin: brim extends outward from tower position
float brim_width = 0.f;
const ConfigOptionFloat *brim_opt = print_cfg.option<ConfigOptionFloat>("prime_tower_brim_width");
if (brim_opt) {
brim_width = brim_opt->value;
if (brim_width < 0) brim_width = WipeTower::get_auto_brim_by_height((float) wipe_tower_size.z());
}
const float margin = WIPE_TOWER_MARGIN + brim_width;
// clamp wipe tower position within plate boundaries
{
if (x + margin + wipe_tower_size(0) > plate_bbox_x_max_local_coord) {
x = plate_bbox_x_max_local_coord - wipe_tower_size(0) - margin;
} else if (x < margin + plate_bbox_x_min_local_coord) {
x = margin + plate_bbox_x_min_local_coord;
}
if (y + margin + wipe_tower_size(1) > plate_bbox_y_max_local_coord) {
y = plate_bbox_y_max_local_coord - wipe_tower_size(1) - margin;
} else if (y < margin) {
y = margin;
}
}
ConfigOptionFloat wt_x_opt(x);
ConfigOptionFloat wt_y_opt(y);
dynamic_cast<ConfigOptionFloats *>(proj_cfg.option("wipe_tower_x"))->set_at(&wt_x_opt, plate_idx, 0);
dynamic_cast<ConfigOptionFloats *>(proj_cfg.option("wipe_tower_y"))->set_at(&wt_y_opt, plate_idx, 0);
}
@@ -4195,6 +4236,11 @@ void PartPlateList::reinit()
//re-calc the bounding boxes
calc_bounding_boxes();
if (m_plater) {
// In GUI mode
set_default_wipe_tower_pos_for_plate(0, true);
}
return;
}
@@ -4266,7 +4312,7 @@ int PartPlateList::create_plate(bool adjust_position)
// update wipe tower config
if (m_plater) {
// In GUI mode
set_default_wipe_tower_pos_for_plate(new_index);
set_default_wipe_tower_pos_for_plate(new_index, true);
}
unprintable_plate.set_index(new_index+1);
+1 -2
View File
@@ -628,13 +628,12 @@ class PartPlateList : public ObjectBase
void generate_icon_textures();
void release_icon_textures();
void set_default_wipe_tower_pos_for_plate(int plate_idx);
friend class cereal::access;
friend class UndoRedo::StackImpl;
friend class PartPlate;
public:
void set_default_wipe_tower_pos_for_plate(int plate_idx, bool init_pos = false);
class BedTextureInfo {
public:
class TexturePart {
+34 -24
View File
@@ -469,7 +469,6 @@ struct Sidebar::priv
ScalableButton * m_bpButton_ams_filament;
ScalableButton * m_bpButton_set_filament;
int m_menu_filament_id = -1;
int filament_area_height;
wxScrolledWindow* m_panel_filament_content;
wxScrolledWindow* m_scrolledWindow_filament_content;
wxStaticLine* m_staticline2;
@@ -2106,14 +2105,10 @@ Sidebar::Sidebar(Plater *parent)
bSizer39->AddSpacer(FromDIP(SidebarProps::TitlebarMargin()));
// add filament content
// ORCA use a height with user preference
int filament_count_user = std::stoi(wxGetApp().app_config->get("filaments_area_preferred_count"));
p->filament_area_height = std::ceil(filament_count_user * 0.5) * (30 + SidebarProps::ElementSpacing()) - SidebarProps::ElementSpacing();
p->m_panel_filament_content = new wxScrolledWindow( p->scrolled, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
p->m_panel_filament_content->SetScrollbars(0, 100, 1, 2);
p->m_panel_filament_content->SetScrollRate(0, 5);
p->m_panel_filament_content->SetMaxSize(wxSize{-1, FromDIP(p->filament_area_height)}); // ORCA
//p->m_panel_filament_content->SetMaxSize(wxSize{-1, FromDIP(174)});
p->m_panel_filament_content->SetBackgroundColour(wxColour(255, 255, 255));
//wxBoxSizer* bSizer_filament_content;
@@ -2135,10 +2130,9 @@ Sidebar::Sidebar(Plater *parent)
sizer_filaments2->Add(p->sizer_filaments, 0, wxEXPAND, 0);
p->m_panel_filament_content->SetSizer(sizer_filaments2);
p->m_panel_filament_content->Layout();
auto min_size = sizer_filaments2->GetMinSize();
if (min_size.y > p->m_panel_filament_content->GetMaxHeight())
min_size.y = p->m_panel_filament_content->GetMaxHeight();
p->m_panel_filament_content->SetMinSize(min_size);
update_filaments_area_height(); // ORCA
scrolled_sizer->Add(p->m_panel_filament_content, 0, wxEXPAND | wxTOP | wxBOTTOM, FromDIP(SidebarProps::ContentMarginV())); // ORCA use vertical margin on parent otherwise it shows scrollbar even on 1 filament
}
@@ -2776,6 +2770,23 @@ void Sidebar::change_top_border_for_mode_sizer(bool increase_border)
#endif
}
void Sidebar::update_filaments_area_height()
// ORCA
{
// ORCA use a height with user preference
auto left_sizer = p->sizer_filaments->GetItem((size_t) 0)->GetSizer();
auto combo_sizer = left_sizer->GetItem((size_t) 0)->GetSizer();
int preferred_rows = std::ceil(0.5 * std::stoi(wxGetApp().app_config->get("filaments_area_preferred_count")));
auto height_with_borders = combo_sizer->GetSize().GetHeight(); // gets height from sizer instead static numbers
p->m_panel_filament_content->SetMaxSize(wxSize{-1, preferred_rows * height_with_borders});
// fixes wxScrolledWindow not shrinks its height to content size
auto min_size = p->m_panel_filament_content->GetSizer()->GetMinSize();
if (min_size.y > p->m_panel_filament_content->GetMaxHeight())
min_size.y = p->m_panel_filament_content->GetMaxHeight();
p->m_panel_filament_content->SetMinSize({-1, min_size.y});
}
void Sidebar::msw_rescale()
{
SetMinSize(wxSize(42 * wxGetApp().em_unit(), -1));
@@ -2846,6 +2857,9 @@ void Sidebar::msw_rescale()
for (PlaterPresetComboBox* combo : p->combos_filament)
combo->msw_rescale();
p->m_panel_filament_content->Layout();
update_filaments_area_height(); // ORCA resize after combos scaled
// BBS
//p->frequently_changed_parameters->msw_rescale();
//obj_list()->msw_rescale();
@@ -3024,10 +3038,7 @@ void Sidebar::on_filament_count_change(size_t num_filaments)
}
}
auto min_size = p->m_panel_filament_content->GetSizer()->GetMinSize();
if (min_size.y > p->m_panel_filament_content->GetMaxHeight())
min_size.y = p->m_panel_filament_content->GetMaxHeight();
p->m_panel_filament_content->SetMinSize(min_size);
update_filaments_area_height(); // ORCA
Layout();
p->m_panel_filament_title->Refresh();
@@ -3087,10 +3098,7 @@ void Sidebar::on_filaments_delete(size_t filament_id)
p->combos_filament[idx]->update();
}
auto min_size = p->m_panel_filament_content->GetSizer()->GetMinSize();
if (min_size.y > p->m_panel_filament_content->GetMaxHeight())
min_size.y = p->m_panel_filament_content->GetMaxHeight();
p->m_panel_filament_content->SetMinSize(min_size);
update_filaments_area_height(); // ORCA
Layout();
p->m_panel_filament_title->Refresh();
@@ -3524,11 +3532,8 @@ void Sidebar::sync_ams_list(bool is_from_big_sync_btn)
for (auto& c : p->combos_filament)
c->update();
// Expand filament list
p->m_panel_filament_content->SetMaxSize({-1, FromDIP(p->filament_area_height)}); // ORCA
auto min_size = p->m_panel_filament_content->GetSizer()->GetMinSize();
if (min_size.y > p->m_panel_filament_content->GetMaxHeight())
min_size.y = p->m_panel_filament_content->GetMaxHeight();
p->m_panel_filament_content->SetMinSize({-1, min_size.y});
update_filaments_area_height(); // ORCA
// BBS:Synchronized consumables information
// auto calculation of flushing volumes
for (int i = 0; i < p->combos_filament.size(); ++i) {
@@ -10500,11 +10505,16 @@ void Plater::priv::init_notification_manager()
void Plater::priv::update_objects_position_when_select_preset(const std::function<void()> &select_prest)
{
// TODO: Orca hack
select_prest();
wxGetApp().obj_list()->update_object_list_by_printer_technology();
// Re-clamp wipe tower positions to new bed boundaries after preset change
PartPlateList &cur_plate_list = this->partplate_list;
for (size_t plate_id = 0; plate_id < cur_plate_list.get_plate_list().size(); ++plate_id) {
cur_plate_list.set_default_wipe_tower_pos_for_plate(plate_id);
}
update();
}
+1
View File
@@ -172,6 +172,7 @@ public:
void set_bed_type_accord_combox(BedType bed_type);
bool reset_bed_type_combox_choices(bool is_sidebar_init = false);
void change_top_border_for_mode_sizer(bool increase_border);
void update_filaments_area_height();
void msw_rescale();
void sys_color_changed();
void search();
+37 -8
View File
@@ -318,13 +318,10 @@ wxBoxSizer *PreferencesDialog::create_item_language_combobox(wxString title, wxS
m_current_language_selected = combobox->GetSelection();
if (m_current_language_selected >= 0 && m_current_language_selected < vlist.size()) {
app_config->set(param, vlist[m_current_language_selected]->CanonicalName.ToUTF8().data());
wxGetApp().load_language(vlist[m_current_language_selected]->CanonicalName, false);
Close();
// Reparent(nullptr);
GetParent()->RemoveChild(this);
wxGetApp().recreate_GUI(_L("Changing application language"));
m_pending_language = vlist[m_current_language_selected]->CanonicalName.ToUTF8().data();
m_recreate_GUI = true;
EndModal(wxID_OK);
return;
}
}
@@ -592,6 +589,14 @@ wxBoxSizer *PreferencesDialog::create_item_spinctrl(wxString title, wxString tit
e.Skip();
});
input->Bind(wxEVT_SPINCTRL, [this, param, input, onchange](wxCommandEvent& e) {
auto value = input->GetValue();
app_config->set(param, std::to_string(value));
app_config->save();
if (onchange != nullptr) onchange(value);
e.Skip();
});
input->Bind(wxEVT_KILL_FOCUS, [this, param, input, onchange](wxFocusEvent &e) {
auto value = input->GetValue();
app_config->set(param, std::to_string(value));
@@ -1398,7 +1403,13 @@ void PreferencesDialog::create_items()
"group_filament_presets", {_L("All"), _L("None"), _L("By type"), _L("By vendor")}, [](wxString value) {wxGetApp().plater()->sidebar().update_presets(Preset::TYPE_FILAMENT);});
g_sizer->Add(item_filament_preset_grouping);
auto item_filament_area_height = create_item_spinctrl(_L("Optimize filaments area height for..."), _L("(Requires restart)"), _L("filaments"), _L("Optimizes filament area maximum height by chosen filament count."), "filaments_area_preferred_count", 8, 99);
// prevent burst calling on keyboard / spin events
m_filament_height_timer.Bind(wxEVT_TIMER, [this](wxTimerEvent&) {
wxGetApp().plater()->sidebar().update_filaments_area_height();
UpdateSidebarLayout();
});
auto item_filament_area_height = create_item_spinctrl(_L("Optimize filaments area height for..."), "", _L("filaments"), _L("Optimizes filament area maximum height by chosen filament count."),
"filaments_area_preferred_count", 8, 99, [this](int value) {m_filament_height_timer.StartOnce(500);});
g_sizer->Add(item_filament_area_height);
//// GENERAL > Features
@@ -1950,4 +1961,22 @@ wxBoxSizer* PreferencesDialog::create_debug_page()
return bSizer;
}
void PreferencesDialog::UpdateSidebarLayout()
{
Plater* plater = wxGetApp().plater();
if (!plater) return;
Sidebar& sidebar = plater->sidebar();
sidebar.Freeze();
sidebar.Layout();
//plater->Layout();
//wxGetApp().mainframe->Layout();
sidebar.Thaw();
plater->PostSizeEvent();
}
}} // namespace Slic3r::GUI
+6
View File
@@ -6,6 +6,7 @@
#include <wx/dialog.h>
#include <wx/timer.h>
#include <string>
#include <vector>
#include <list>
#include <map>
@@ -43,10 +44,12 @@ protected:
// bool m_settings_layout_changed {false};
bool m_seq_top_layer_only_changed{false};
bool m_recreate_GUI{false};
std::string m_pending_language;
public:
bool seq_top_layer_only_changed() const { return m_seq_top_layer_only_changed; }
bool recreate_GUI() const { return m_recreate_GUI; }
const std::string& pending_language() const { return m_pending_language; }
void on_dpi_changed(const wxRect &suggested_rect) override;
public:
@@ -60,6 +63,7 @@ public:
~PreferencesDialog();
wxString m_backup_interval_time;
wxTimer m_filament_height_timer;
void create();
@@ -106,6 +110,8 @@ public:
void create_shortcuts_page();
wxBoxSizer* create_debug_page();
void UpdateSidebarLayout();
// BBS
void create_select_domain_widget();
+1 -1
View File
@@ -639,7 +639,7 @@ wxBoxSizer* PrintOptionsDialog::create_settings_group(wxWindow* parent)
ai_refine_sizer->Add(line_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(18));
line_sizer = new wxBoxSizer(wxHORIZONTAL);
text_spaghetti_detection_caption0 = new Label(ai_refine_panel, _L("Detect spaghetti failure(scattered lose filament)."));
text_spaghetti_detection_caption0 = new Label(ai_refine_panel, _L("Detect spaghetti failures (scattered lose filament)."));
text_spaghetti_detection_caption0->SetFont(Label::Body_12);
text_spaghetti_detection_caption0->SetForegroundColour(STATIC_TEXT_CAPTION_COL);
text_spaghetti_detection_caption0->Wrap(-1);
+7 -9
View File
@@ -1589,7 +1589,7 @@ void Tab::on_value_change(const std::string& opt_key, const boost::any& value)
}
bool is_precise_z_height = m_config->option<ConfigOptionBool>("precise_z_height")->value;
if (boost::any_cast<bool>(value) && is_precise_z_height) {
MessageDialog dlg(wxGetApp().plater(), _L("Enabling both precise Z height and the prime tower may cause the size of prime tower to increase. Do you still want to enable?"),
MessageDialog dlg(wxGetApp().plater(), _L("Enabling both precise Z height and the prime tower may cause slicing errors. Do you still want to enable?"),
_L("Warning"), wxICON_WARNING | wxYES | wxNO);
if (dlg.ShowModal() == wxID_NO) {
DynamicPrintConfig new_conf = *m_config;
@@ -1631,7 +1631,7 @@ void Tab::on_value_change(const std::string& opt_key, const boost::any& value)
if (opt_key == "precise_z_height") {
bool wipe_tower_enabled = m_config->option<ConfigOptionBool>("enable_prime_tower")->value;
if (boost::any_cast<bool>(value) && wipe_tower_enabled) {
MessageDialog dlg(wxGetApp().plater(), _L("Enabling both precise Z height and the prime tower may cause the size of prime tower to increase. Do you still want to enable?"),
MessageDialog dlg(wxGetApp().plater(), _L("Enabling both precise Z height and the prime tower may cause slicing errors. Do you still want to enable precise Z height?"),
_L("Warning"), wxICON_WARNING | wxYES | wxNO);
if (dlg.ShowModal() == wxID_NO) {
DynamicPrintConfig new_conf = *m_config;
@@ -4919,6 +4919,7 @@ if (is_marlin_flavor)
optgroup->append_single_option_line("bed_temperature_formula", "printer_basic_information_advanced#bed-temperature-type");
optgroup = page->new_optgroup(L("Wipe tower"), "param_tower");
optgroup->append_single_option_line("wipe_tower_type", "printer_multimaterial_wipe_tower");
optgroup->append_single_option_line("purge_in_prime_tower", "printer_multimaterial_wipe_tower#purge-in-prime-tower");
optgroup->append_single_option_line("enable_filament_ramming", "printer_multimaterial_wipe_tower#enable-filament-ramming");
@@ -5212,11 +5213,6 @@ void TabPrinter::toggle_options()
is_BBL_printer = wxGetApp().preset_bundle->is_bbl_vendor();
}
bool is_QIDI_printer = false;
if (m_preset_bundle) {
is_QIDI_printer = wxGetApp().preset_bundle->is_qidi_vendor();
}
bool have_multiple_extruders = true;
//m_extruders_count > 1;
//if (m_active_page->title() == "Custom G-code") {
@@ -5244,6 +5240,8 @@ void TabPrinter::toggle_options()
}
if (m_active_page->title() == L("Multimaterial")) {
const bool supports_wipe_tower_2 = !is_BBL_printer && m_config->opt_enum<WipeTowerType>("wipe_tower_type") == WipeTowerType::Type2;
toggle_line("wipe_tower_type", !is_BBL_printer);
// SoftFever: hide specific settings for BBL printer
for (auto el : {
"enable_filament_ramming",
@@ -5253,7 +5251,7 @@ void TabPrinter::toggle_options()
"extra_loading_move",
"high_current_on_filament_swap",
})
toggle_option(el, !is_BBL_printer && !is_QIDI_printer);
toggle_option(el, supports_wipe_tower_2);
auto bSEMM = m_config->opt_bool("single_extruder_multi_material");
if (!bSEMM && m_config->opt_bool("manual_filament_change")) {
@@ -5263,7 +5261,7 @@ void TabPrinter::toggle_options()
}
toggle_option("extruders_count", !bSEMM);
toggle_option("manual_filament_change", bSEMM);
toggle_option("purge_in_prime_tower", bSEMM && (!is_BBL_printer && !is_QIDI_printer));
toggle_option("purge_in_prime_tower", bSEMM && supports_wipe_tower_2);
}
wxString extruder_number;
long val = 1;
+9 -4
View File
@@ -1668,7 +1668,7 @@ void UnsavedChangesDialog::update_tree(Preset::Type type, PresetCollection* pres
// process changes of extruders count
if (type == Preset::TYPE_PRINTER && old_pt == ptFFF &&
old_config.opt<ConfigOptionFloats>("nozzle_diameter")->values.size() != new_config.opt<ConfigOptionFloats>("nozzle_diameter")->values.size()) {
wxString local_label = _L("Extruders count");
wxString local_label = _L("Extruder count");
wxString old_val = from_u8((boost::format("%1%") % old_config.opt<ConfigOptionFloats>("nozzle_diameter")->values.size()).str());
wxString new_val = from_u8((boost::format("%1%") % new_config.opt<ConfigOptionFloats>("nozzle_diameter")->values.size()).str());
@@ -2220,15 +2220,20 @@ void DiffPresetDialog::update_tree()
m_tree->model->AddPreset(type, "\"" + from_u8(left_preset->name) + "\" vs \"" + from_u8(right_preset->name) + "\"", left_pt);
const std::map<wxString, std::string>& category_icon_map = wxGetApp().get_tab(type)->get_category_icon_map();
auto get_category_icon = [&category_icon_map](const wxString& key) {
auto it = category_icon_map.find(key);
return it != category_icon_map.end() ? it->second : std::string();
};
// process changes of extruders count
if (type == Preset::TYPE_PRINTER && left_pt == ptFFF &&
left_config.opt<ConfigOptionStrings>("extruder_colour")->values.size() != right_congig.opt<ConfigOptionStrings>("extruder_colour")->values.size()) {
wxString local_label = _L("Extruders count");
wxString local_label = _L("Extruder count");
wxString left_val = from_u8((boost::format("%1%") % left_config.opt<ConfigOptionStrings>("extruder_colour")->values.size()).str());
wxString right_val = from_u8((boost::format("%1%") % right_congig.opt<ConfigOptionStrings>("extruder_colour")->values.size()).str());
m_tree->Append("extruders_count", type, "General", "Capabilities", local_label, left_val, right_val, category_icon_map.at("Basic information"));
m_tree->Append("extruders_count", type, "General", "Capabilities", local_label, left_val, right_val,
get_category_icon("Basic information"));
}
for (const std::string& opt_key : dirty_options) {
@@ -2247,7 +2252,7 @@ void DiffPresetDialog::update_tree()
continue;
}
m_tree->Append(opt_key, type, option.category_local, option.group_local, option.label_local,
left_val, right_val, category_icon_map.at(option.category));
left_val, right_val, get_category_icon(option.category));
}
}
+40 -18
View File
@@ -5,6 +5,9 @@
#include <wx/dcclient.h>
#include <wx/settings.h>
#include <boost/log/trivial.hpp>
#ifdef __linux__
#include <fontconfig/fontconfig.h>
#endif
wxFont Label::sysFont(int size, bool bold)
@@ -58,27 +61,46 @@ wxFont Label::Body_10;
wxFont Label::Body_9;
wxFont Label::Body_8;
// Check if a font family is already available via fontconfig.
#ifdef __linux__
static bool fc_font_available(const char *family_name)
{
FcPattern *pat = FcPatternCreate();
if (!pat)
return false;
FcPatternAddString(pat, FC_FAMILY, (const FcChar8 *) family_name);
FcResult res;
FcPattern *match = FcFontMatch(nullptr, pat, &res);
bool available = false;
if (match) {
FcChar8 *matched_family = nullptr;
if (FcPatternGetString(match, FC_FAMILY, 0, &matched_family) == FcResultMatch && matched_family)
available = (strcasecmp((const char *) matched_family, family_name) == 0);
FcPatternDestroy(match);
}
FcPatternDestroy(pat);
return available;
}
#endif
void Label::initSysFont()
{
#if defined(__linux__) || defined(_WIN32)
const std::string &resource_path = Slic3r::resources_dir();
wxString font_path = wxString::FromUTF8(resource_path + "/fonts/HarmonyOS_Sans_SC_Bold.ttf");
bool result = wxFont::AddPrivateFont(font_path);
// BOOST_LOG_TRIVIAL(info) << boost::format("add font of HarmonyOS_Sans_SC_Bold returns %1%")%result;
// printf("add font of HarmonyOS_Sans_SC_Bold returns %d\n", result);
font_path = wxString::FromUTF8(resource_path + "/fonts/HarmonyOS_Sans_SC_Regular.ttf");
result = wxFont::AddPrivateFont(font_path);
// BOOST_LOG_TRIVIAL(info) << boost::format("add font of HarmonyOS_Sans_SC_Regular returns %1%")%result;
// printf("add font of HarmonyOS_Sans_SC_Regular returns %d\n", result);
// Adding NanumGothic Regular and Bold
font_path = wxString::FromUTF8(resource_path + "/fonts/NanumGothic-Regular.ttf");
result = wxFont::AddPrivateFont(font_path);
// BOOST_LOG_TRIVIAL(info) << boost::format("add font of NanumGothic-Regular returns %1%")%result;
// printf("add font of NanumGothic-Regular returns %d\n", result);
font_path = wxString::FromUTF8(resource_path + "/fonts/NanumGothic-Bold.ttf");
result = wxFont::AddPrivateFont(font_path);
// BOOST_LOG_TRIVIAL(info) << boost::format("add font of NanumGothic-Bold returns %1%")%result;
// printf("add font of NanumGothic-Bold returns %d\n", result);
// On Linux, skip AddPrivateFont for fonts already known to fontconfig
// (e.g. installed system-wide in a Flatpak). Calling AddPrivateFont
// triggers a Pango crash in ensure_faces() on Pango >= 1.48 (GNOME 49+),
// because FcConfigAppFontAddFile invalidates Pango's cached font map.
bool load_fonts = true;
#ifdef __linux__
load_fonts = !fc_font_available("HarmonyOS Sans SC") || !fc_font_available("NanumGothic");
#endif
if (load_fonts) {
const std::string &resource_path = Slic3r::resources_dir();
wxFont::AddPrivateFont(wxString::FromUTF8(resource_path + "/fonts/HarmonyOS_Sans_SC_Bold.ttf"));
wxFont::AddPrivateFont(wxString::FromUTF8(resource_path + "/fonts/HarmonyOS_Sans_SC_Regular.ttf"));
wxFont::AddPrivateFont(wxString::FromUTF8(resource_path + "/fonts/NanumGothic-Regular.ttf"));
wxFont::AddPrivateFont(wxString::FromUTF8(resource_path + "/fonts/NanumGothic-Bold.ttf"));
}
#endif
Head_48 = Label::sysFont(48, true);
Head_32 = Label::sysFont(32, true);
+59 -47
View File
@@ -67,7 +67,7 @@ std::vector<wxString> make_shaper_type_labels()
}
PA_Calibration_Dlg::PA_Calibration_Dlg(wxWindow* parent, wxWindowID id, Plater* plater)
: DPIDialog(parent, id, _L("PA Calibration"), wxDefaultPosition, parent->FromDIP(wxSize(-1, 280)), wxDEFAULT_DIALOG_STYLE), m_plater(plater)
: DPIDialog(parent, id, _L("PA Calibration"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE), m_plater(plater)
{
SetBackgroundColour(*wxWHITE); // make sure background color set for dialog
SetForegroundColour(wxColour("#363636"));
@@ -102,7 +102,7 @@ PA_Calibration_Dlg::PA_Calibration_Dlg(wxWindow* parent, wxWindowID id, Plater*
int text_max = GetTextMax(this, std::vector<wxString>{start_pa_str, end_pa_str, PA_step_str, sp_accel_str, sp_speed_str, cb_print_no_str});
auto st_size = FromDIP(wxSize(text_max, -1));
auto st_size = wxSize(text_max, -1);
auto ti_size = FromDIP(wxSize(120, -1));
LabeledStaticBox* stb = new LabeledStaticBox(this, _L("Settings"));
@@ -123,7 +123,7 @@ PA_Calibration_Dlg::PA_Calibration_Dlg(wxWindow* parent, wxWindowID id, Plater*
auto end_PA_sizer = new wxBoxSizer(wxHORIZONTAL);
auto end_pa_text = new wxStaticText(this, wxID_ANY, end_pa_str, wxDefaultPosition, st_size, wxALIGN_LEFT);
m_tiEndPA = new TextInput(this, "", "", "", wxDefaultPosition, ti_size, wxTE_PROCESS_ENTER);
m_tiStartPA->GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
m_tiEndPA->GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
end_PA_sizer->Add(end_pa_text, 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(2));
end_PA_sizer->Add(m_tiEndPA , 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(2));
settings_sizer->Add(end_PA_sizer, 0, wxLEFT, FromDIP(3));
@@ -132,7 +132,7 @@ PA_Calibration_Dlg::PA_Calibration_Dlg(wxWindow* parent, wxWindowID id, Plater*
auto PA_step_sizer = new wxBoxSizer(wxHORIZONTAL);
auto PA_step_text = new wxStaticText(this, wxID_ANY, PA_step_str, wxDefaultPosition, st_size, wxALIGN_LEFT);
m_tiPAStep = new TextInput(this, "", "", "", wxDefaultPosition, ti_size, wxTE_PROCESS_ENTER);
m_tiStartPA->GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
m_tiPAStep->GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
PA_step_sizer->Add(PA_step_text, 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(2));
PA_step_sizer->Add(m_tiPAStep , 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(2));
settings_sizer->Add(PA_step_sizer, 0, wxLEFT, FromDIP(3));
@@ -196,6 +196,7 @@ PA_Calibration_Dlg::PA_Calibration_Dlg(wxWindow* parent, wxWindowID id, Plater*
Layout();
Fit();
v_sizer->SetSizeHints(this);
}
PA_Calibration_Dlg::~PA_Calibration_Dlg() {
@@ -328,7 +329,7 @@ enum FILAMENT_TYPE : int
};
Temp_Calibration_Dlg::Temp_Calibration_Dlg(wxWindow* parent, wxWindowID id, Plater* plater)
: DPIDialog(parent, id, _L("Temperature calibration"), wxDefaultPosition, parent->FromDIP(wxSize(-1, 280)), wxDEFAULT_DIALOG_STYLE), m_plater(plater)
: DPIDialog(parent, id, _L("Temperature calibration"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE), m_plater(plater)
{
SetBackgroundColour(*wxWHITE); // make sure background color set for dialog
SetForegroundColour(wxColour("#363636"));
@@ -351,7 +352,7 @@ Temp_Calibration_Dlg::Temp_Calibration_Dlg(wxWindow* parent, wxWindowID id, Plat
wxString temp_step_str = _L("Temp step: ");
int text_max = GetTextMax(this, std::vector<wxString>{start_temp_str, end_temp_str, temp_step_str});
auto st_size = FromDIP(wxSize(text_max, -1));
auto st_size = wxSize(text_max, -1);
auto ti_size = FromDIP(wxSize(120, -1));
LabeledStaticBox* stb = new LabeledStaticBox(this, _L("Settings"));
@@ -372,7 +373,7 @@ Temp_Calibration_Dlg::Temp_Calibration_Dlg(wxWindow* parent, wxWindowID id, Plat
auto end_temp_sizer = new wxBoxSizer(wxHORIZONTAL);
auto end_temp_text = new wxStaticText(this, wxID_ANY, end_temp_str, wxDefaultPosition, st_size, wxALIGN_LEFT);
m_tiEnd = new TextInput(this, std::to_string(190), _L("\u2103" /* °C */), "", wxDefaultPosition, ti_size);
m_tiStart->GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
m_tiEnd->GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
end_temp_sizer->Add(end_temp_text, 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(2));
end_temp_sizer->Add(m_tiEnd , 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(2));
settings_sizer->Add(end_temp_sizer, 0, wxLEFT, FromDIP(3));
@@ -381,7 +382,7 @@ Temp_Calibration_Dlg::Temp_Calibration_Dlg(wxWindow* parent, wxWindowID id, Plat
auto temp_step_sizer = new wxBoxSizer(wxHORIZONTAL);
auto temp_step_text = new wxStaticText(this, wxID_ANY, temp_step_str, wxDefaultPosition, st_size, wxALIGN_LEFT);
m_tiStep = new TextInput(this, wxString::FromDouble(5), _L("\u2103" /* °C */), "", wxDefaultPosition, ti_size);
m_tiStart->GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
m_tiStep->GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
m_tiStep->Enable(false);
temp_step_sizer->Add(temp_step_text, 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(2));
temp_step_sizer->Add(m_tiStep , 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(2));
@@ -409,6 +410,7 @@ Temp_Calibration_Dlg::Temp_Calibration_Dlg(wxWindow* parent, wxWindowID id, Plat
Layout();
Fit();
v_sizer->SetSizeHints(this);
auto validate_text = [](TextInput* ti){
unsigned long t = 0;
@@ -518,7 +520,7 @@ void Temp_Calibration_Dlg::on_dpi_changed(const wxRect& suggested_rect) {
//
MaxVolumetricSpeed_Test_Dlg::MaxVolumetricSpeed_Test_Dlg(wxWindow* parent, wxWindowID id, Plater* plater)
: DPIDialog(parent, id, _L("Max volumetric speed test"), wxDefaultPosition, parent->FromDIP(wxSize(-1, 280)), wxDEFAULT_DIALOG_STYLE), m_plater(plater)
: DPIDialog(parent, id, _L("Max volumetric speed test"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE), m_plater(plater)
{
SetBackgroundColour(*wxWHITE); // make sure background color set for dialog
SetForegroundColour(wxColour("#363636"));
@@ -533,7 +535,7 @@ MaxVolumetricSpeed_Test_Dlg::MaxVolumetricSpeed_Test_Dlg(wxWindow* parent, wxWin
wxString vol_step_str = _L("Step") + ": ";
int text_max = GetTextMax(this, std::vector<wxString>{start_vol_str, end_vol_str, vol_step_str});
auto st_size = FromDIP(wxSize(text_max, -1));
auto st_size = wxSize(text_max, -1);
auto ti_size = FromDIP(wxSize(120, -1));
LabeledStaticBox* stb = new LabeledStaticBox(this, _L("Settings"));
@@ -555,7 +557,7 @@ MaxVolumetricSpeed_Test_Dlg::MaxVolumetricSpeed_Test_Dlg(wxWindow* parent, wxWin
auto end_vol_sizer = new wxBoxSizer(wxHORIZONTAL);
auto end_vol_text = new wxStaticText(this, wxID_ANY, end_vol_str, wxDefaultPosition, st_size, wxALIGN_LEFT);
m_tiEnd = new TextInput(this, std::to_string(20), _L(u8"mm³/s"), "", wxDefaultPosition, ti_size);
m_tiStart->GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
m_tiEnd->GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
end_vol_sizer->Add(end_vol_text, 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(2));
end_vol_sizer->Add(m_tiEnd , 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(2));
settings_sizer->Add(end_vol_sizer, 0, wxLEFT, FromDIP(3));
@@ -564,7 +566,7 @@ MaxVolumetricSpeed_Test_Dlg::MaxVolumetricSpeed_Test_Dlg(wxWindow* parent, wxWin
auto vol_step_sizer = new wxBoxSizer(wxHORIZONTAL);
auto vol_step_text = new wxStaticText(this, wxID_ANY, vol_step_str, wxDefaultPosition, st_size, wxALIGN_LEFT);
m_tiStep = new TextInput(this, wxString::FromDouble(0.5), _L(u8"mm³/s"), "", wxDefaultPosition, ti_size);
m_tiStart->GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
m_tiStep->GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
vol_step_sizer->Add(vol_step_text, 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(2));
vol_step_sizer->Add(m_tiStep , 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(2));
settings_sizer->Add(vol_step_sizer, 0, wxLEFT, FromDIP(3));
@@ -587,6 +589,7 @@ MaxVolumetricSpeed_Test_Dlg::MaxVolumetricSpeed_Test_Dlg(wxWindow* parent, wxWin
Layout();
Fit();
v_sizer->SetSizeHints(this);
}
MaxVolumetricSpeed_Test_Dlg::~MaxVolumetricSpeed_Test_Dlg() {
@@ -622,7 +625,7 @@ void MaxVolumetricSpeed_Test_Dlg::on_dpi_changed(const wxRect& suggested_rect) {
//
VFA_Test_Dlg::VFA_Test_Dlg(wxWindow* parent, wxWindowID id, Plater* plater)
: DPIDialog(parent, id, _L("VFA test"), wxDefaultPosition, parent->FromDIP(wxSize(-1, 280)), wxDEFAULT_DIALOG_STYLE)
: DPIDialog(parent, id, _L("VFA test"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE)
, m_plater(plater)
{
SetBackgroundColour(*wxWHITE); // make sure background color set for dialog
@@ -638,7 +641,7 @@ VFA_Test_Dlg::VFA_Test_Dlg(wxWindow* parent, wxWindowID id, Plater* plater)
wxString vol_step_str = _L("Step") + ": ";
int text_max = GetTextMax(this, std::vector<wxString>{start_str, end_vol_str, vol_step_str});
auto st_size = FromDIP(wxSize(text_max, -1));
auto st_size = wxSize(text_max, -1);
auto ti_size = FromDIP(wxSize(120, -1));
LabeledStaticBox* stb = new LabeledStaticBox(this, _L("Settings"));
@@ -660,7 +663,7 @@ VFA_Test_Dlg::VFA_Test_Dlg(wxWindow* parent, wxWindowID id, Plater* plater)
auto end_vol_sizer = new wxBoxSizer(wxHORIZONTAL);
auto end_vol_text = new wxStaticText(this, wxID_ANY, end_vol_str, wxDefaultPosition, st_size, wxALIGN_LEFT);
m_tiEnd = new TextInput(this, std::to_string(200), _L("mm/s"), "", wxDefaultPosition, ti_size);
m_tiStart->GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
m_tiEnd->GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
end_vol_sizer->Add(end_vol_text, 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(2));
end_vol_sizer->Add(m_tiEnd , 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(2));
settings_sizer->Add(end_vol_sizer, 0, wxLEFT, FromDIP(3));
@@ -669,7 +672,7 @@ VFA_Test_Dlg::VFA_Test_Dlg(wxWindow* parent, wxWindowID id, Plater* plater)
auto vol_step_sizer = new wxBoxSizer(wxHORIZONTAL);
auto vol_step_text = new wxStaticText(this, wxID_ANY, vol_step_str, wxDefaultPosition, st_size, wxALIGN_LEFT);
m_tiStep = new TextInput(this, wxString::FromDouble(10), _L("mm/s"), "", wxDefaultPosition, ti_size);
m_tiStart->GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
m_tiStep->GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
vol_step_sizer->Add(vol_step_text, 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(2));
vol_step_sizer->Add(m_tiStep , 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(2));
settings_sizer->Add(vol_step_sizer, 0, wxLEFT, FromDIP(3));
@@ -694,6 +697,7 @@ VFA_Test_Dlg::VFA_Test_Dlg(wxWindow* parent, wxWindowID id, Plater* plater)
Layout();
Fit();
v_sizer->SetSizeHints(this);
}
VFA_Test_Dlg::~VFA_Test_Dlg()
@@ -731,7 +735,7 @@ void VFA_Test_Dlg::on_dpi_changed(const wxRect& suggested_rect)
//
Retraction_Test_Dlg::Retraction_Test_Dlg(wxWindow* parent, wxWindowID id, Plater* plater)
: DPIDialog(parent, id, _L("Retraction test"), wxDefaultPosition, parent->FromDIP(wxSize(-1, 280)), wxDEFAULT_DIALOG_STYLE), m_plater(plater)
: DPIDialog(parent, id, _L("Retraction test"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE), m_plater(plater)
{
SetBackgroundColour(*wxWHITE); // make sure background color set for dialog
SetForegroundColour(wxColour("#363636"));
@@ -746,7 +750,7 @@ Retraction_Test_Dlg::Retraction_Test_Dlg(wxWindow* parent, wxWindowID id, Plater
wxString length_step_str = _L("Step") + ": ";
int text_max = GetTextMax(this, std::vector<wxString>{start_length_str, end_length_str, length_step_str});
auto st_size = FromDIP(wxSize(text_max, -1));
auto st_size = wxSize(text_max, -1);
auto ti_size = FromDIP(wxSize(120, -1));
LabeledStaticBox* stb = new LabeledStaticBox(this, _L("Settings"));
@@ -768,7 +772,7 @@ Retraction_Test_Dlg::Retraction_Test_Dlg(wxWindow* parent, wxWindowID id, Plater
auto end_length_sizer = new wxBoxSizer(wxHORIZONTAL);
auto end_length_text = new wxStaticText(this, wxID_ANY, end_length_str, wxDefaultPosition, st_size, wxALIGN_LEFT);
m_tiEnd = new TextInput(this, std::to_string(2), _L("mm"), "", wxDefaultPosition, ti_size);
m_tiStart->GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
m_tiEnd->GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
end_length_sizer->Add(end_length_text, 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(2));
end_length_sizer->Add(m_tiEnd , 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(2));
settings_sizer->Add(end_length_sizer, 0, wxLEFT, FromDIP(3));
@@ -777,7 +781,7 @@ Retraction_Test_Dlg::Retraction_Test_Dlg(wxWindow* parent, wxWindowID id, Plater
auto length_step_sizer = new wxBoxSizer(wxHORIZONTAL);
auto length_step_text = new wxStaticText(this, wxID_ANY, length_step_str, wxDefaultPosition, st_size, wxALIGN_LEFT);
m_tiStep = new TextInput(this, wxString::FromDouble(0.1), _L("mm"), "", wxDefaultPosition, ti_size);
m_tiStart->GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
m_tiStep->GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
length_step_sizer->Add(length_step_text, 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(2));
length_step_sizer->Add(m_tiStep , 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(2));
settings_sizer->Add(length_step_sizer, 0, wxLEFT, FromDIP(3));
@@ -802,6 +806,7 @@ Retraction_Test_Dlg::Retraction_Test_Dlg(wxWindow* parent, wxWindowID id, Plater
Layout();
Fit();
v_sizer->SetSizeHints(this);
}
Retraction_Test_Dlg::~Retraction_Test_Dlg() {
@@ -836,7 +841,7 @@ void Retraction_Test_Dlg::on_dpi_changed(const wxRect& suggested_rect) {
//
Input_Shaping_Freq_Test_Dlg::Input_Shaping_Freq_Test_Dlg(wxWindow* parent, wxWindowID id, Plater* plater)
: DPIDialog(parent, id, _L("Input shaping Frequency test"), wxDefaultPosition, parent->FromDIP(wxSize(-1, 280)), wxDEFAULT_DIALOG_STYLE), m_plater(plater)
: DPIDialog(parent, id, _L("Input shaping Frequency test"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE), m_plater(plater)
{
SetBackgroundColour(*wxWHITE); // make sure background color set for dialog
SetForegroundColour(wxColour("#363636"));
@@ -855,7 +860,7 @@ Input_Shaping_Freq_Test_Dlg::Input_Shaping_Freq_Test_Dlg(wxWindow* parent, wxWin
auto labeled_box_model = new LabeledStaticBox(this, _L("Test model"));
auto model_box = new wxStaticBoxSizer(labeled_box_model, wxHORIZONTAL);
m_rbModel = new RadioGroup(this, { _L("Ringing Tower"), _L("Fast Tower") }, wxHORIZONTAL);
m_rbModel = new RadioGroup(this, { _L("Ringing Tower"), _L("Fast Tower") }, wxVERTICAL);
model_box->Add(m_rbModel, 0, wxALL | wxEXPAND, FromDIP(4));
v_sizer->Add(model_box, 0, wxTOP | wxRIGHT | wxLEFT | wxEXPAND, FromDIP(10));
@@ -897,7 +902,7 @@ Input_Shaping_Freq_Test_Dlg::Input_Shaping_Freq_Test_Dlg(wxWindow* parent, wxWin
wxString y_axis_str = "Y " + _L("Start / End") + ": ";
int text_max = GetTextMax(this, std::vector<wxString>{x_axis_str, y_axis_str});
auto st_size = FromDIP(wxSize(text_max, -1));
auto st_size = wxSize(text_max, -1);
auto ti_size = FromDIP(wxSize(120, -1));
LabeledStaticBox* stb = new LabeledStaticBox(this, _L("Frequency settings"));
@@ -958,6 +963,7 @@ Input_Shaping_Freq_Test_Dlg::Input_Shaping_Freq_Test_Dlg(wxWindow* parent, wxWin
auto note_text = new wxStaticText(this, wxID_ANY, _L("Recommended: Set Damp to 0.\nThis will use the printer's default or saved value."), wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
note_text->SetForegroundColour(wxColour(128, 128, 128));
note_text->Wrap(FromDIP(350));
settings_sizer->Add(note_text, 0, wxALL, FromDIP(5));
settings_sizer->AddSpacer(FromDIP(5));
@@ -980,6 +986,7 @@ Input_Shaping_Freq_Test_Dlg::Input_Shaping_Freq_Test_Dlg(wxWindow* parent, wxWin
Layout();
Fit();
v_sizer->SetSizeHints(this);
}
Input_Shaping_Freq_Test_Dlg::~Input_Shaping_Freq_Test_Dlg() {
@@ -1052,7 +1059,7 @@ void Input_Shaping_Freq_Test_Dlg::on_dpi_changed(const wxRect& suggested_rect) {
//
Input_Shaping_Damp_Test_Dlg::Input_Shaping_Damp_Test_Dlg(wxWindow* parent, wxWindowID id, Plater* plater)
: DPIDialog(parent, id, _L("Input shaping Damp test"), wxDefaultPosition, parent->FromDIP(wxSize(-1, 280)), wxDEFAULT_DIALOG_STYLE), m_plater(plater)
: DPIDialog(parent, id, _L("Input shaping Damp test"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE), m_plater(plater)
{
SetBackgroundColour(*wxWHITE); // make sure background color set for dialog
SetForegroundColour(wxColour("#363636"));
@@ -1071,7 +1078,7 @@ Input_Shaping_Damp_Test_Dlg::Input_Shaping_Damp_Test_Dlg(wxWindow* parent, wxWin
auto labeled_box_model = new LabeledStaticBox(this, _L("Test model"));
auto model_box = new wxStaticBoxSizer(labeled_box_model, wxHORIZONTAL);
m_rbModel = new RadioGroup(this, { _L("Ringing Tower"), _L("Fast Tower") }, wxHORIZONTAL);
m_rbModel = new RadioGroup(this, { _L("Ringing Tower"), _L("Fast Tower") }, wxVERTICAL);
model_box->Add(m_rbModel, 0, wxALL | wxEXPAND, FromDIP(4));
v_sizer->Add(model_box, 0, wxTOP | wxRIGHT | wxLEFT | wxEXPAND, FromDIP(10));
@@ -1113,7 +1120,7 @@ Input_Shaping_Damp_Test_Dlg::Input_Shaping_Damp_Test_Dlg(wxWindow* parent, wxWin
wxString damp_str = _L("Damp") + " " + _L("Start / End") + ": ";
int text_max = GetTextMax(this, std::vector<wxString>{freq_str, damp_str});
auto st_size = FromDIP(wxSize(text_max, -1));
auto st_size = wxSize(text_max, -1);
auto ti_size = FromDIP(wxSize(120, -1));
LabeledStaticBox* stb = new LabeledStaticBox(this, _L("Frequency settings"));
@@ -1178,6 +1185,7 @@ Input_Shaping_Damp_Test_Dlg::Input_Shaping_Damp_Test_Dlg(wxWindow* parent, wxWin
Layout();
Fit();
v_sizer->SetSizeHints(this);
}
Input_Shaping_Damp_Test_Dlg::~Input_Shaping_Damp_Test_Dlg() {
@@ -1245,7 +1253,7 @@ void Input_Shaping_Damp_Test_Dlg::on_dpi_changed(const wxRect& suggested_rect) {
//
Cornering_Test_Dlg::Cornering_Test_Dlg(wxWindow* parent, wxWindowID id, Plater* plater)
: DPIDialog(parent, id, _L("Cornering test"), wxDefaultPosition, parent->FromDIP(wxSize(-1, 280)), wxDEFAULT_DIALOG_STYLE), m_plater(plater)
: DPIDialog(parent, id, _L("Cornering test"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE), m_plater(plater)
{
SetBackgroundColour(*wxWHITE); // make sure background color set for dialog
SetForegroundColour(wxColour("#363636"));
@@ -1258,13 +1266,14 @@ Cornering_Test_Dlg::Cornering_Test_Dlg(wxWindow* parent, wxWindowID id, Plater*
auto labeled_box_model = new LabeledStaticBox(this, _L("Test model"));
auto model_box = new wxStaticBoxSizer(labeled_box_model, wxHORIZONTAL);
m_rbModel = new RadioGroup(this, { _L("Ringing Tower"), _L("Fast Tower"), _L("SCV-V2") }, wxHORIZONTAL);
m_rbModel = new RadioGroup(this, { _L("Ringing Tower"), _L("Fast Tower"), _L("SCV-V2") }, wxVERTICAL);
model_box->Add(m_rbModel, 0, wxALL | wxEXPAND, FromDIP(4));
v_sizer->Add(model_box, 0, wxTOP | wxRIGHT | wxLEFT | wxEXPAND, FromDIP(10));
// Settings
wxString start_jd_str = _L("Start: ");
wxString end_jd_str = _L("End: ");
int text_max = GetTextMax(this, std::vector<wxString>{start_jd_str, end_jd_str});
LabeledStaticBox* stb = new LabeledStaticBox(this, _L("Cornering settings"));
wxStaticBoxSizer* settings_sizer = new wxStaticBoxSizer(stb, wxVERTICAL);
@@ -1297,61 +1306,63 @@ Cornering_Test_Dlg::Cornering_Test_Dlg(wxWindow* parent, wxWindowID id, Plater*
units_str = "mm/s";
}
auto st_size = wxSize(text_max, -1);
auto ti_size = FromDIP(wxSize(120, -1));
// Start and End cornering on same row
auto cornering_row_sizer = new wxBoxSizer(wxHORIZONTAL);
// Start cornering
auto start_jd_sizer = new wxBoxSizer(wxHORIZONTAL);
auto start_jd_text = new wxStaticText(this, wxID_ANY, start_jd_str, wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
auto start_jd_text = new wxStaticText(this, wxID_ANY, start_jd_str, wxDefaultPosition, st_size, wxALIGN_LEFT);
m_tiJDStart = new TextInput(this, start_value_str, units_str, "", wxDefaultPosition, ti_size);
m_tiJDStart->GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
start_jd_sizer->Add(start_jd_text, 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(2));
start_jd_sizer->Add(m_tiJDStart , 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(2));
cornering_row_sizer->Add(start_jd_sizer, 0, wxLEFT, FromDIP(3));
settings_sizer->Add(start_jd_sizer, 0, wxLEFT, FromDIP(3));
// End cornering
auto end_jd_sizer = new wxBoxSizer(wxHORIZONTAL);
auto end_jd_text = new wxStaticText(this, wxID_ANY, end_jd_str, wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
auto end_jd_text = new wxStaticText(this, wxID_ANY, end_jd_str, wxDefaultPosition, st_size, wxALIGN_LEFT);
m_tiJDEnd = new TextInput(this, end_value_str, units_str, "", wxDefaultPosition, ti_size);
m_tiJDEnd->GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
end_jd_sizer->Add(end_jd_text, 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(2));
end_jd_sizer->Add(m_tiJDEnd , 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(2));
cornering_row_sizer->Add(end_jd_sizer, 0, wxLEFT, FromDIP(3));
settings_sizer->Add(cornering_row_sizer, 0, wxLEFT, FromDIP(3));
settings_sizer->Add(end_jd_sizer, 0, wxLEFT, FromDIP(3));
settings_sizer->AddSpacer(FromDIP(5));
// Add note about cornering based on GCode Flavor
wxString note_msg = _L("Note: Lower values = sharper corners but slower speeds.\n");
wxString note_msg = _L("Note: Lower values = sharper corners but slower speeds.");
auto note_text = new wxStaticText(this, wxID_ANY, note_msg, wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
note_text->SetForegroundColour(wxColour(128, 128, 128));
note_text->Wrap(FromDIP(300));
settings_sizer->Add(note_text, 0, wxALL, FromDIP(5));
if (gcode_flavor_option) {
wxString note_msg_2;
switch (gcode_flavor_option->value) {
case GCodeFlavor::gcfMarlinFirmware: {
// Check if machine_max_junction_deviation is set and > 0
const auto* max_jd_option = preset_bundle->printers.get_edited_preset().config.option<ConfigOptionFloats>("machine_max_junction_deviation");
if (max_jd_option && !max_jd_option->values.empty() && max_jd_option->values[0] > 0) {
note_msg += _L("Marlin 2 Junction Deviation detected:\nTo test Classic Jerk, set 'Maximum Junction Deviation' in Motion ability to 0.");
note_msg_2 += _L("Marlin 2 Junction Deviation detected:\nTo test Classic Jerk, set 'Maximum Junction Deviation' in Motion ability to 0.");
} else {
note_msg += _L("Marlin 2 Classic Jerk detected:\nTo test Junction Deviation, set 'Maximum Junction Deviation' in Motion ability to a value > 0.");
note_msg_2 += _L("Marlin 2 Classic Jerk detected:\nTo test Junction Deviation, set 'Maximum Junction Deviation' in Motion ability to a value > 0.");
}
break;
}
case GCodeFlavor::gcfRepRapFirmware:
note_msg += _L("RepRap detected: Jerk in mm/s.\nOrcaSlicer will convert the values to mm/min when necessary.");
note_msg_2 += _L("RepRap detected: Jerk in mm/s.\nOrcaSlicer will convert the values to mm/min when necessary.");
break;
default:
break;
}
if(!note_msg_2.empty()){
auto note_text_2 = new wxStaticText(this, wxID_ANY, note_msg_2, wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
note_text_2->SetForegroundColour(wxColour(128, 128, 128));
note_text_2->Wrap(FromDIP(300));
settings_sizer->Add(note_text_2, 0, wxALL, FromDIP(5));
}
}
auto note_text = new wxStaticText(this, wxID_ANY, note_msg,
wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
note_text->SetForegroundColour(wxColour(128, 128, 128));
note_text->Wrap(FromDIP(300));
settings_sizer->Add(note_text, 0, wxALL, FromDIP(5));
v_sizer->Add(settings_sizer, 0, wxTOP | wxRIGHT | wxLEFT | wxEXPAND, FromDIP(10));
v_sizer->AddSpacer(FromDIP(5));
@@ -1370,6 +1381,7 @@ Cornering_Test_Dlg::Cornering_Test_Dlg(wxWindow* parent, wxWindowID id, Plater*
Layout();
Fit();
v_sizer->SetSizeHints(this);
}
Cornering_Test_Dlg::~Cornering_Test_Dlg() {
+20 -18
View File
@@ -571,7 +571,18 @@ bool MoonrakerPrinterAgent::fetch_filament_info(std::string dev_id)
std::vector<AmsTrayData> trays;
int max_lane_index = 0;
// Try Happy Hare first (more widely adopted, supports more filament changers)
// Try Moonraker filament data (more generic, supports any filament changer
// software that reports lane data to Moonraker like AFC and recent Happy
// Hare as of Feb 15, 2026)
if (fetch_moonraker_filament_data(trays, max_lane_index)) {
BOOST_LOG_TRIVIAL(info) << "MoonrakerPrinterAgent::fetch_filament_info: Detected Moonraker filament system with "
<< (max_lane_index + 1) << " lanes";
int ams_count = (max_lane_index + 4) / 4;
build_ams_payload(ams_count, max_lane_index, trays);
return true;
}
// Attempt Happy Hare first (more widely adopted, supports more filament changers)
if (fetch_hh_filament_info(trays, max_lane_index)) {
BOOST_LOG_TRIVIAL(info) << "MoonrakerPrinterAgent::fetch_filament_info: Detected Happy Hare MMU with "
<< (max_lane_index + 1) << " gates";
@@ -580,17 +591,8 @@ bool MoonrakerPrinterAgent::fetch_filament_info(std::string dev_id)
return true;
}
// Fallback to AFC
if (fetch_afc_filament_info(trays, max_lane_index)) {
BOOST_LOG_TRIVIAL(info) << "MoonrakerPrinterAgent::fetch_filament_info: Detected AFC with "
<< (max_lane_index + 1) << " lanes";
int ams_count = (max_lane_index + 4) / 4;
build_ams_payload(ams_count, max_lane_index, trays);
return true;
}
// No MMU detected - this is normal for printers without MMU, not an error
BOOST_LOG_TRIVIAL(info) << "MoonrakerPrinterAgent::fetch_filament_info: No MMU system detected (neither HH nor AFC)";
BOOST_LOG_TRIVIAL(info) << "MoonrakerPrinterAgent::fetch_filament_info: No MMU system detected (neither HH nor Moonraker)";
return false;
}
@@ -721,10 +723,10 @@ std::string MoonrakerPrinterAgent::normalize_color_value(const std::string& colo
return normalized;
}
// Fetch filament info from Armored Turtle AFC
bool MoonrakerPrinterAgent::fetch_afc_filament_info(std::vector<AmsTrayData>& trays, int& max_lane_index)
// Fetch filament info from moonraker database
bool MoonrakerPrinterAgent::fetch_moonraker_filament_data(std::vector<AmsTrayData>& trays, int& max_lane_index)
{
// Fetch AFC lane data from Moonraker database
// Fetch lane data from Moonraker database
std::string url = join_url(device_info.base_url, "/server/database/item?namespace=lane_data");
std::string response_body;
@@ -754,19 +756,19 @@ bool MoonrakerPrinterAgent::fetch_afc_filament_info(std::vector<AmsTrayData>& tr
.perform_sync();
if (!success) {
BOOST_LOG_TRIVIAL(warning) << "MoonrakerPrinterAgent::fetch_afc_filament_info: Failed to fetch lane data: " << http_error;
BOOST_LOG_TRIVIAL(warning) << "MoonrakerPrinterAgent::fetch_moonraker_filament_data: Failed to fetch lane data: " << http_error;
return false;
}
auto json = nlohmann::json::parse(response_body, nullptr, false, true);
if (json.is_discarded()) {
BOOST_LOG_TRIVIAL(warning) << "MoonrakerPrinterAgent::fetch_afc_filament_info: Invalid JSON response";
BOOST_LOG_TRIVIAL(warning) << "MoonrakerPrinterAgent::fetch_moonraker_filament_data: Invalid JSON response";
return false;
}
// Expected structure: { "result": { "namespace": "lane_data", "value": { "lane1": {...}, ... } } }
if (!json.contains("result") || !json["result"].contains("value") || !json["result"]["value"].is_object()) {
BOOST_LOG_TRIVIAL(warning) << "MoonrakerPrinterAgent::fetch_afc_filament_info: Unexpected JSON structure or no lane_data found";
BOOST_LOG_TRIVIAL(warning) << "MoonrakerPrinterAgent::fetch_moonraker_filament_data: Unexpected JSON structure or no lane_data found";
return false;
}
@@ -812,7 +814,7 @@ bool MoonrakerPrinterAgent::fetch_afc_filament_info(std::vector<AmsTrayData>& tr
}
if (trays.empty()) {
BOOST_LOG_TRIVIAL(info) << "MoonrakerPrinterAgent::fetch_afc_filament_info: No AFC lanes found";
BOOST_LOG_TRIVIAL(info) << "MoonrakerPrinterAgent::fetch_moonraker_filament_data: No lanes found";
return false;
}
+1 -1
View File
@@ -162,7 +162,7 @@ private:
// System-specific filament fetch methods
bool fetch_hh_filament_info(std::vector<AmsTrayData>& trays, int& max_lane_index);
bool fetch_afc_filament_info(std::vector<AmsTrayData>& trays, int& max_lane_index);
bool fetch_moonraker_filament_data(std::vector<AmsTrayData>& trays, int& max_lane_index);
// JSON helper methods
static std::string safe_json_string(const nlohmann::json& obj, const char* key);