mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-20 14:08:20 +00:00
Merge branch 'main' into zaa
This commit is contained in:
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
|
||||
|
||||
@@ -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
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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. "
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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 });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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})
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
@@ -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
@@ -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()
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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"; }
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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"),
|
||||
|
||||
@@ -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 };
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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,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();
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in new issue
Block a user