Merge remote-tracking branch 'remote/master' into SoftFever

# Conflicts:
#	src/libslic3r/Preset.cpp
This commit is contained in:
SoftFever 2022-09-09 21:54:57 +08:00
commit bb74438f7c
132 changed files with 5737 additions and 3598 deletions

View file

@ -130,13 +130,7 @@ void AppConfig::set_defaults()
#endif
if (get("single_instance").empty())
set_bool("single_instance",
#ifdef __APPLE__
true
#else // __APPLE__
false
#endif // __APPLE__
);
set_bool("single_instance", false);
#ifdef SUPPORT_REMEMBER_OUTPUT_PATH
if (get("remember_output_path").empty())

View file

@ -454,10 +454,6 @@ set(OCCT_LIBS
TKernel
)
if(APPLE)
target_link_libraries(libslic3r freetype)
endif()
target_link_libraries(libslic3r
libnest2d
@ -480,6 +476,13 @@ target_link_libraries(libslic3r
${OCCT_LIBS}
)
if(NOT WIN32)
target_link_libraries(libslic3r freetype)
if (NOT APPLE)
target_link_libraries(libslic3r fontconfig)
endif()
endif()
if (TARGET OpenVDB::openvdb)
target_link_libraries(libslic3r OpenVDB::openvdb)
endif()

View file

@ -534,8 +534,10 @@ bool ConfigBase::set_deserialize_nothrow(const t_config_option_key &opt_key_src,
this->handle_legacy(opt_key, value);
if (opt_key.empty()) {
// Ignore the option.
//BBS: record these options
substitutions_ctxt.unrecogized_keys.push_back(opt_key_src);
//BBS: record these options, keep only one repeated opt_key
auto iter = std::find(substitutions_ctxt.unrecogized_keys.begin(), substitutions_ctxt.unrecogized_keys.end(), opt_key_src);
if (iter == substitutions_ctxt.unrecogized_keys.end())
substitutions_ctxt.unrecogized_keys.push_back(opt_key_src);
return true;
}
return this->set_deserialize_raw(opt_key, value, substitutions_ctxt, append);

View file

@ -2507,6 +2507,14 @@ GCode::LayerResult GCode::process_layer(
gcode += "; open powerlost recovery\n";
gcode += "M1003 S1\n";
}
// BBS: open first layer inspection at second layer
if (print.config().scan_first_layer.value) {
// BBS: retract first to avoid droping when scan model
gcode += this->retract();
gcode += "M976 S1 P1 ; scan model before printing 2nd layer\n";
gcode += "M400 P100\n";
gcode += this->unretract();
}
//BBS: reset acceleration at sencond layer
if (m_config.default_acceleration.value > 0 && m_config.initial_layer_acceleration.value > 0) {
@ -2661,7 +2669,29 @@ GCode::LayerResult GCode::process_layer(
}
}
if (support_dontcare || interface_dontcare) {
if (interface_dontcare) {
int extruder_override = wiping_extrusions.get_support_interface_extruder_overrides(&object);
if (extruder_override >= 0) {
interface_extruder = extruder_override;
interface_dontcare = false;
}
}
// BBS: try to print support base with a filament other than interface filament
if (support_dontcare && !interface_dontcare) {
unsigned int dontcare_extruder = first_extruder_id;
for (unsigned int extruder_id : layer_tools.extruders) {
if (print.config().filament_soluble.get_at(extruder_id)) continue;
if (extruder_id == interface_extruder) continue;
dontcare_extruder = extruder_id;
break;
}
if (support_dontcare) support_extruder = dontcare_extruder;
}
else if (support_dontcare || interface_dontcare) {
// Some support will be printed with "don't care" material, preferably non-soluble.
// Is the current extruder assigned a soluble filament?
unsigned int dontcare_extruder = first_extruder_id;
@ -3028,18 +3058,6 @@ GCode::LayerResult GCode::process_layer(
file.write(gcode);
#endif
// BBS: scan model after print first layer
// Note: for sequential printing, every object will have this
if (print.config().scan_first_layer.value) {
if (first_layer) {
//BBS: retract first to avoid droping when scan model
gcode += this->retract();
gcode += "M976 S1 P1 ; scan model after print first layer\n";
gcode += "M400 P100\n";
gcode += this->unretract();
}
}
BOOST_LOG_TRIVIAL(trace) << "Exported layer " << layer.id() << " print_z " << print_z <<
log_memory_info();
@ -3839,8 +3857,8 @@ std::string GCode::retract(bool toolchange, bool is_last_retraction)
if (m_writer.extruder() == nullptr)
return gcode;
// wipe (if it's enabled for this extruder and we have a stored wipe path)
if (EXTRUDER_CONFIG(wipe) && m_wipe.has_path()) {
// wipe (if it's enabled for this extruder and we have a stored wipe path and no-zero wipe distance)
if (EXTRUDER_CONFIG(wipe) && m_wipe.has_path() && scale_(EXTRUDER_CONFIG(wipe_distance)) > SCALED_EPSILON) {
gcode += toolchange ? m_writer.retract_for_toolchange(true) : m_writer.retract(true);
gcode += m_wipe.wipe(*this, toolchange, is_last_retraction);
}

View file

@ -83,7 +83,7 @@ public:
m_tool_change_idx(0),
m_plate_origin(plate_origin),
m_single_extruder_multi_material(print_config.single_extruder_multi_material),
m_enable_timelapse_print(print_config.timelapse_no_toolhead.value),
m_enable_timelapse_print(print_config.timelapse_type.value == TimelapseType::tlSmooth),
m_is_first_print(true)
{}

View file

@ -990,11 +990,22 @@ void GCodeProcessor::apply_config(const DynamicPrintConfig& config)
}
const ConfigOptionPoints* extruder_offset = config.option<ConfigOptionPoints>("extruder_offset");
const ConfigOptionBool* single_extruder_multi_material = config.option<ConfigOptionBool>("single_extruder_multi_material");
if (extruder_offset != nullptr) {
m_extruder_offsets.resize(extruder_offset->values.size());
for (size_t i = 0; i < extruder_offset->values.size(); ++i) {
Vec2f offset = extruder_offset->values[i].cast<float>();
m_extruder_offsets[i] = { offset(0), offset(1), 0.0f };
//BBS: for single extruder multi material, only use the offset of first extruder
if (single_extruder_multi_material != nullptr && single_extruder_multi_material->getBool()) {
Vec2f offset = extruder_offset->values[0].cast<float>();
m_extruder_offsets.resize(m_result.extruders_count);
for (size_t i = 0; i < m_result.extruders_count; ++i) {
m_extruder_offsets[i] = { offset(0), offset(1), 0.0f };
}
}
else {
m_extruder_offsets.resize(extruder_offset->values.size());
for (size_t i = 0; i < extruder_offset->values.size(); ++i) {
Vec2f offset = extruder_offset->values[i].cast<float>();
m_extruder_offsets[i] = { offset(0), offset(1), 0.0f };
}
}
}
@ -1192,6 +1203,7 @@ void GCodeProcessor::reset()
}
m_extruded_last_z = 0.0f;
m_zero_layer_height = 0.0f;
m_first_layer_height = 0.0f;
m_processing_start_custom_gcode = false;
m_g1_line_id = 0;
@ -2469,7 +2481,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
AxisCoords delta_pos;
for (unsigned char a = X; a <= E; ++a) {
delta_pos[a] = m_end_position[a] - m_start_position[a];
max_abs_delta = std::max(max_abs_delta, std::abs(delta_pos[a]));
max_abs_delta = std::max<float>(max_abs_delta, std::abs(delta_pos[a]));
}
// no displacement, return
@ -2575,7 +2587,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
minimum_feedrate(static_cast<PrintEstimatedStatistics::ETimeMode>(i), m_feedrate);
//BBS: calculeta enter and exit direction
curr.enter_direction = { delta_pos[X], delta_pos[Y], delta_pos[Z] };
curr.enter_direction = { static_cast<float>(delta_pos[X]), static_cast<float>(delta_pos[Y]), static_cast<float>(delta_pos[Z]) };
float norm = curr.enter_direction.norm();
if (!is_extrusion_only_move(delta_pos))
curr.enter_direction = curr.enter_direction / norm;
@ -2624,8 +2636,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
curr.abs_axis_feedrate[a] = std::abs(curr.axis_feedrate[a]);
if (curr.abs_axis_feedrate[a] != 0.0f) {
float axis_max_feedrate = get_axis_max_feedrate(static_cast<PrintEstimatedStatistics::ETimeMode>(i), static_cast<Axis>(a));
if (axis_max_feedrate != 0.0f)
min_feedrate_factor = std::min(min_feedrate_factor, axis_max_feedrate / curr.abs_axis_feedrate[a]);
if (axis_max_feedrate != 0.0f) min_feedrate_factor = std::min<float>(min_feedrate_factor, axis_max_feedrate / curr.abs_axis_feedrate[a]);
}
}
//BBS: update curr.feedrate
@ -2914,6 +2925,7 @@ void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line)
EMoveType type = move_type(delta_pos[E]);
float delta_xyz = std::sqrt(sqr(arc_length) + sqr(delta_pos[Z]));
if (type == EMoveType::Extrude) {
float volume_extruded_filament = area_filament_cross_section * delta_pos[E];
@ -3020,8 +3032,7 @@ void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line)
curr.abs_axis_feedrate[a] = std::abs(curr.axis_feedrate[a]);
if (curr.abs_axis_feedrate[a] != 0.0f) {
float axis_max_feedrate = get_axis_max_feedrate(static_cast<PrintEstimatedStatistics::ETimeMode>(i), static_cast<Axis>(a));
if (axis_max_feedrate != 0.0f)
min_feedrate_factor = std::min(min_feedrate_factor, axis_max_feedrate / curr.abs_axis_feedrate[a]);
if (axis_max_feedrate != 0.0f) min_feedrate_factor = std::min<float>(min_feedrate_factor, axis_max_feedrate / curr.abs_axis_feedrate[a]);
}
}
curr.feedrate *= min_feedrate_factor;
@ -3048,8 +3059,7 @@ void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line)
if (axis_acc[a] != 0.0f) {
float axis_max_acceleration = get_axis_max_acceleration(static_cast<PrintEstimatedStatistics::ETimeMode>(i), static_cast<Axis>(a));
if (axis_max_acceleration != 0.0f && axis_acc[a] > axis_max_acceleration)
min_acc_factor = std::min(min_acc_factor, axis_max_acceleration / axis_acc[a]);
if (axis_max_acceleration != 0.0f && axis_acc[a] > axis_max_acceleration) min_acc_factor = std::min<float>(min_acc_factor, axis_max_acceleration / axis_acc[a]);
}
}
block.acceleration = acceleration * min_acc_factor;
@ -3685,7 +3695,7 @@ void GCodeProcessor::store_move_vertex(EMoveType type, EMovePathType path_type)
m_interpolation_points[i] =
Vec3f(m_interpolation_points[i].x() + m_x_offset,
m_interpolation_points[i].y() + m_y_offset,
m_processing_start_custom_gcode ? m_first_layer_height : m_interpolation_points[i].z()) +
m_processing_start_custom_gcode ? m_zero_layer_height : m_interpolation_points[i].z()) +
m_extruder_offsets[m_extruder_id];
}
@ -3696,8 +3706,8 @@ void GCodeProcessor::store_move_vertex(EMoveType type, EMovePathType path_type)
m_extruder_id,
m_cp_color.current,
//BBS: add plate's offset to the rendering vertices
Vec3f(m_end_position[X] + m_x_offset, m_end_position[Y] + m_y_offset, m_processing_start_custom_gcode ? m_first_layer_height : m_end_position[Z]) + m_extruder_offsets[m_extruder_id],
m_end_position[E] - m_start_position[E],
Vec3f(m_end_position[X] + m_x_offset, m_end_position[Y] + m_y_offset, m_processing_start_custom_gcode ? m_zero_layer_height : m_end_position[Z]) + m_extruder_offsets[m_extruder_id],
static_cast<float>(m_end_position[E] - m_start_position[E]),
m_feedrate,
m_width,
m_height,

View file

@ -219,7 +219,7 @@ namespace Slic3r {
#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
private:
using AxisCoords = std::array<float, 4>;
using AxisCoords = std::array<double, 4>;
using ExtruderColors = std::vector<unsigned char>;
using ExtruderTemps = std::vector<float>;
@ -595,6 +595,7 @@ namespace Slic3r {
ExtruderTemps m_extruder_temps;
float m_extruded_last_z;
float m_first_layer_height; // mm
float m_zero_layer_height; // mm
bool m_processing_start_custom_gcode;
unsigned int m_g1_line_id;
unsigned int m_layer_id;

View file

@ -175,8 +175,13 @@ ToolOrdering::ToolOrdering(const Print &print, unsigned int first_extruder, bool
this->collect_extruders(*object, per_layer_extruder_switches);
// Reorder the extruders to minimize tool switches.
std::vector<unsigned int> first_layer_tool_order;
if (first_extruder == (unsigned int)-1) {
this->reorder_extruders(generate_first_layer_tool_order(print));
first_layer_tool_order = generate_first_layer_tool_order(print);
}
if (!first_layer_tool_order.empty()) {
this->reorder_extruders(first_layer_tool_order);
}
else {
this->reorder_extruders(first_extruder);

View file

@ -545,7 +545,7 @@ WipeTower::WipeTower(const PrintConfig& config, int plate_idx, Vec3d plate_origi
m_current_tool(initial_tool),
//wipe_volumes(flush_matrix)
m_wipe_volume(prime_volume),
m_enable_timelapse_print(config.timelapse_no_toolhead.value)
m_enable_timelapse_print(config.timelapse_type.value == TimelapseType::tlSmooth)
{
// Read absolute value of first layer speed, if given as percentage,
// it is taken over following default. Speeds from config are not

View file

@ -574,7 +574,7 @@ enum class EnforcerBlockerType : int8_t {
Extruder13,
Extruder14,
Extruder15,
ExtruderMax = Extruder15,
ExtruderMax
};
enum class ConversionType : int {

View file

@ -643,7 +643,7 @@ std::string Preset::get_filament_type(std::string &display_filament_type)
}
static std::vector<std::string> s_Preset_print_options {
"layer_height", "initial_layer_print_height", "wall_loops", "spiral_mode",
"layer_height", "initial_layer_print_height", "wall_loops", "slice_closing_radius", "spiral_mode",
"top_shell_layers", "top_shell_thickness", "bottom_shell_layers", "bottom_shell_thickness",
"reduce_crossing_wall", "detect_thin_wall", "detect_overhang_wall",
"seam_position", "wall_infill_order", "sparse_infill_density", "sparse_infill_pattern", "top_surface_pattern", "bottom_surface_pattern",
@ -683,7 +683,8 @@ static std::vector<std::string> s_Preset_print_options {
"gcode_add_line_number", "enable_arc_fitting", "infill_combination", "adaptive_layer_height",
"support_bottom_interface_spacing", "enable_overhang_speed", "overhang_1_4_speed", "overhang_2_4_speed", "overhang_3_4_speed", "overhang_4_4_speed",
"initial_layer_infill_speed", "only_one_wall_top", "only_one_wall_first_layer",
"timelapse_no_toolhead"
"timelapse_type"
};
static std::vector<std::string> s_Preset_filament_options {
@ -755,6 +756,7 @@ static std::vector<std::string> s_Preset_sla_print_options {
"support_object_elevation",
"support_points_density_relative",
"support_points_minimal_distance",
"slice_closing_radius",
"pad_enable",
"pad_wall_thickness",
"pad_wall_height",

View file

@ -1758,7 +1758,7 @@ const WipeTowerData& Print::wipe_tower_data(size_t filaments_cnt) const
bool Print::enable_timelapse_print() const
{
return m_config.timelapse_no_toolhead.value;
return m_config.timelapse_type.value == TimelapseType::tlSmooth;
}
void Print::_make_wipe_tower()
@ -1779,11 +1779,10 @@ void Print::_make_wipe_tower()
// BBS: priming logic is removed, so don't consider it in tool ordering
m_wipe_tower_data.tool_ordering = ToolOrdering(*this, (unsigned int)-1, false);
// if enable_timelapse_print(), update all layer_tools parameters(has_wipe_tower, wipe_tower_partitions)
// if enable_timelapse_print(), update all layer_tools parameters: wipe_tower_partitions
if (enable_timelapse_print()) {
std::vector<LayerTools>& layer_tools_array = m_wipe_tower_data.tool_ordering.layer_tools();
for (LayerTools& layer_tools : layer_tools_array) {
layer_tools.has_wipe_tower = true;
if (layer_tools.wipe_tower_partitions == 0) {
layer_tools.wipe_tower_partitions = 1;
}

View file

@ -12,6 +12,35 @@
#include <float.h>
namespace {
std::set<std::string> SplitStringAndRemoveDuplicateElement(const std::string &str, const std::string &separator)
{
std::set<std::string> result;
if (str.empty()) return result;
std::string strs = str + separator;
size_t pos;
size_t size = strs.size();
for (int i = 0; i < size; ++i) {
pos = strs.find(separator, i);
if (pos < size) {
std::string sub_str = strs.substr(i, pos - i);
result.insert(sub_str);
i = pos + separator.size() - 1;
}
}
return result;
}
void ReplaceString(std::string &resource_str, const std::string &old_str, const std::string &new_str)
{
std::string::size_type pos = 0;
while ((pos = resource_str.find(old_str)) != std::string::npos) { resource_str.replace(pos, old_str.length(), new_str); }
}
}
namespace Slic3r {
//! macro used to mark string used at localization,
@ -204,6 +233,14 @@ static const t_config_enum_values s_keys_map_BrimType = {
};
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(BrimType)
// using 0,1,2 to compatible with old files
static const t_config_enum_values s_keys_map_TimelapseType = {
{"0", tlNone},
{"1", tlSmooth},
{"2", tlTraditional}
};
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(TimelapseType)
static const t_config_enum_values s_keys_map_DraftShield = {
{ "disabled", dsDisabled },
{ "limited", dsLimited },
@ -571,7 +608,7 @@ void PrintConfigDef::init_fff_params()
def->sidetext = L("%");
def->min = 0;
def->max = 100;
def->mode = comDevelop;
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionInts { 100 });
def = this->add("overhang_fan_threshold", coEnums);
@ -580,7 +617,7 @@ void PrintConfigDef::init_fff_params()
"Expressed as percentage which indicides how much width of the line without support from lower layer");
def->sidetext = L("");
def->enum_keys_map = &s_keys_map_OverhangFanThreshold;
def->mode = comDevelop;
def->mode = comAdvanced;
def->enum_values.emplace_back("5%");
def->enum_values.emplace_back("25%");
def->enum_values.emplace_back("50%");
@ -2130,16 +2167,24 @@ void PrintConfigDef::init_fff_params()
def->mode = comSimple;
def->set_default_value(new ConfigOptionBool(false));
def = this->add("timelapse_no_toolhead", coBool);
def = this->add("timelapse_type", coEnum);
def->label = L("Timelapse");
def->tooltip = L("If enabled, a timelapse video will be generated for each print. "
"After each layer is printed, the toolhead will move to the excess chute, "
"and then a snapshot is taken with the chamber camera. "
def->tooltip = L("If smooth or traditional mode is selected, a timelapse video will be generated for each print. "
"After each layer is printed, a snapshot is taken with the chamber camera. "
"All of these snapshots are composed into a timelapse video when printing completes. "
"If smooth mode is selected, the toolhead will move to the excess chute after each layer is printed "
"and then take a snapshot. "
"Since the melt filament may leak from the nozzle during the process of taking a snapshot, "
"prime tower is required for nozzle priming.");
"prime tower is required for smooth mode to wipe nozzle.");
def->enum_keys_map = &ConfigOptionEnum<TimelapseType>::get_enum_values();
def->enum_values.emplace_back("0");
def->enum_values.emplace_back("1");
def->enum_values.emplace_back("2");
def->enum_labels.emplace_back(L("None"));
def->enum_labels.emplace_back(L("Smooth"));
def->enum_labels.emplace_back(L("Traditional"));
def->mode = comSimple;
def->set_default_value(new ConfigOptionBool(false));
def->set_default_value(new ConfigOptionEnum<TimelapseType>(tlNone));
def = this->add("standby_temperature_delta", coInt);
def->label = L("Temperature variation");
@ -2184,6 +2229,16 @@ void PrintConfigDef::init_fff_params()
def->mode = comDevelop;
def->set_default_value(new ConfigOptionBool(false));
def = this->add("slice_closing_radius", coFloat);
def->label = L("Slice gap closing radius");
def->category = L("Quality");
def->tooltip = L("Cracks smaller than 2x gap closing radius are being filled during the triangle mesh slicing. "
"The gap closing operation may reduce the final print resolution, therefore it is advisable to keep the value reasonably low.");
def->sidetext = L("mm");
def->min = 0;
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloat(0.049));
def = this->add("enable_support", coBool);
//BBS: remove material behind support
def->label = L("Enable support");
@ -2621,6 +2676,7 @@ void PrintConfigDef::init_fff_params()
def->label = L("Wipe Distance");
def->tooltip = L("Discribe how long the nozzle will move along the last path when retracting");
def->sidetext = L("mm");
def->min = 0;
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloats { 2. });
@ -3530,6 +3586,19 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va
opt_key = "compatible_process_expression_group";
} else if (opt_key == "cooling") {
opt_key = "slow_down_for_layer_cooling";
} else if (opt_key == "timelapse_no_toolhead") {
opt_key = "timelapse_type";
} else if (opt_key == "different_settings_to_system") {
std::string copy_value = value;
copy_value.erase(std::remove(copy_value.begin(), copy_value.end(), '\"'), copy_value.end()); // remove '"' in string
std::set<std::string> split_keys = SplitStringAndRemoveDuplicateElement(copy_value, ";");
for (std::string split_key : split_keys) {
std::string copy_key = split_key, copy_value = "";
handle_legacy(copy_key, copy_value);
if (copy_key != split_key) {
ReplaceString(value, split_key, copy_key);
}
}
}
// Ignore the following obsolete configuration keys:
@ -3544,7 +3613,7 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va
, "support_sharp_tails","remove_small_overhangs", "support_with_sheath",
"tree_support_branch_diameter_angle", "tree_support_collision_resolution",
"small_perimeter_speed", "max_volumetric_speed", "max_print_speed",
"support_bottom_z_distance", "support_closing_radius", "slicing_mode", "slice_closing_radius",
"support_bottom_z_distance", "support_closing_radius", "slicing_mode",
"remove_freq_sweep", "remove_bed_leveling", "remove_extrusion_calibration",
"support_transition_line_width", "support_transition_speed", "bed_temperature", "bed_temperature_initial_layer",
"can_switch_nozzle_type", "can_add_auxiliary_fan", "extra_flush_volume", "spaghetti_detector"
@ -3655,9 +3724,12 @@ void DynamicPrintConfig::normalize_fdm(int used_filaments)
ConfigOptionBool* islh_opt = this->option<ConfigOptionBool>("independent_support_layer_height", true);
ConfigOptionBool* alh_opt = this->option<ConfigOptionBool>("adaptive_layer_height");
ConfigOptionEnum<PrintSequence>* ps_opt = this->option<ConfigOptionEnum<PrintSequence>>("print_sequence");
if (used_filaments == 1 || ps_opt->value == PrintSequence::ByObject)
ept_opt->value = false;
ConfigOptionEnum<TimelapseType> *timelapse_opt = this->option<ConfigOptionEnum<TimelapseType>>("timelapse_type");
if (timelapse_opt && timelapse_opt->value == TimelapseType::tlSmooth) {
if (used_filaments == 1 || ps_opt->value == PrintSequence::ByObject)
ept_opt->value = false;
}
if (ept_opt->value) {
if (islh_opt)

View file

@ -142,6 +142,12 @@ enum BrimType {
btOuterAndInner,
};
enum TimelapseType {
tlNone,
tlSmooth,
tlTraditional
};
enum DraftShield {
dsDisabled, dsLimited, dsEnabled
};
@ -249,6 +255,7 @@ CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(SeamPosition)
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(SLADisplayOrientation)
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(SLAPillarConnectionMode)
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(BrimType)
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(TimelapseType)
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(BedType)
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(DraftShield)
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(ForwardCompatibilitySubstitutionRule)
@ -591,6 +598,7 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionFloat, raft_first_layer_expansion))
((ConfigOptionInt, raft_layers))
((ConfigOptionEnum<SeamPosition>, seam_position))
((ConfigOptionFloat, slice_closing_radius))
((ConfigOptionBool, enable_support))
// Automatic supports (generated based on support_threshold_angle).
((ConfigOptionEnum<SupportType>, support_type))
@ -874,7 +882,7 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE(
// BBS: not in any preset, calculated before slicing
((ConfigOptionBool, has_prime_tower))
((ConfigOptionFloat, nozzle_volume))
((ConfigOptionBool, timelapse_no_toolhead))
((ConfigOptionEnum<TimelapseType>, timelapse_type))
)
@ -900,6 +908,8 @@ PRINT_CONFIG_CLASS_DEFINE(
//Number of the layers needed for the exposure time fade [3;20]
((ConfigOptionInt, faded_layers))/*= 10*/
((ConfigOptionFloat, slice_closing_radius))
// Enabling or disabling support creation
((ConfigOptionBool, supports_enable))

View file

@ -680,7 +680,8 @@ bool PrintObject::invalidate_state_by_config_options(
//BBS
|| opt_key == "adaptive_layer_height"
|| opt_key == "raft_layers"
|| opt_key == "raft_contact_distance") {
|| opt_key == "raft_contact_distance"
|| opt_key == "slice_closing_radius") {
steps.emplace_back(posSlice);
} else if (
opt_key == "elefant_foot_compensation"

View file

@ -136,7 +136,7 @@ static std::vector<VolumeSlices> slice_volumes_inner(
slicing_ranges.reserve(layer_ranges.size());
MeshSlicingParamsEx params_base;
params_base.closing_radius = g_config_slice_closing_radius;
params_base.closing_radius = print_object_config.slice_closing_radius.value;
params_base.extra_offset = 0;
params_base.trafo = object_trafo;
//BBS: 0.0025mm is safe enough to simplify the data to speed slicing up for high-resolution model.
@ -1040,7 +1040,7 @@ void PrintObject::slice_volumes()
if (min_growth < 0.f || elfoot > 0.f) {
// Apply the negative XY compensation. (the ones that is <0)
ExPolygons trimming;
static const float eps = float(scale_(g_config_slice_closing_radius) * 1.5);
static const float eps = float(scale_(m_config.slice_closing_radius.value) * 1.5);
if (elfoot > 0.f) {
lslices_1st_layer = offset_ex(layer->merged(eps), -eps);
trimming = Slic3r::elephant_foot_compensation(lslices_1st_layer,

View file

@ -930,7 +930,8 @@ bool SLAPrintObject::invalidate_state_by_config_options(const std::vector<t_conf
|| opt_key == "supports_enable"
|| opt_key == "support_object_elevation"
|| opt_key == "pad_around_object"
|| opt_key == "pad_around_object_everywhere") {
|| opt_key == "pad_around_object_everywhere"
|| opt_key == "slice_closing_radius") {
steps.emplace_back(slaposObjectSlice);
} else if (
opt_key == "support_points_density_relative"

View file

@ -518,7 +518,7 @@ void SLAPrint::Steps::slice_model(SLAPrintObject &po)
po.m_model_slices.clear();
MeshSlicingParamsEx params;
params.closing_radius = float(g_config_slice_closing_radius);
params.closing_radius = float(po.config().slice_closing_radius.value);
//BBS: always regular mode
//switch (po.config().slicing_mode.value) {
//case SlicingMode::Regular: params.mode = MeshSlicingParams::SlicingMode::Regular; break;
@ -749,7 +749,7 @@ void SLAPrint::Steps::slice_supports(SLAPrintObject &po) {
for(auto& rec : po.m_slice_index) heights.emplace_back(rec.slice_level());
sd->support_slices = sd->support_tree_ptr->slice(
heights, float(g_config_slice_closing_radius));
heights, float(po.config().slice_closing_radius.value));
}
for (size_t i = 0; i < sd->support_slices.size() && i < po.m_slice_index.size(); ++i)

View file

@ -94,7 +94,6 @@ static constexpr bool RELATIVE_E_AXIS = 1;
static constexpr bool g_config_support_sharp_tails = true;
static constexpr bool g_config_remove_small_overhangs = true;
static constexpr float g_config_tree_support_collision_resolution = 0.2;
static constexpr float g_config_slice_closing_radius = 0.049;
// Write slices as SVG images into out directory during the 2D processing of the slices.
// #define SLIC3R_DEBUG_SLICE_PROCESSING

View file

@ -344,6 +344,8 @@ set(SLIC3R_GUI_SOURCES
GUI/DesktopIntegrationDialog.hpp
GUI/PublishDialog.cpp
GUI/PublishDialog.hpp
GUI/RecenterDialog.cpp
GUI/RecenterDialog.hpp
GUI/BindDialog.cpp
GUI/BindDialog.hpp
GUI/SelectMachine.hpp

View file

@ -12,7 +12,7 @@ static bool show_flag;
#define COMBOBOX_FILAMENT (m_comboBox_filament)
#endif
AMSMaterialsSetting::AMSMaterialsSetting(wxWindow *parent, wxWindowID id)
: DPIDialog(parent, id, _L("AMSMaterialsSetting"), wxDefaultPosition, wxDefaultSize, wxBORDER_NONE)
: DPIDialog(parent, id, _L("AMS Materials Setting"), wxDefaultPosition, wxDefaultSize, wxBORDER_NONE)
{
create();
}
@ -44,6 +44,16 @@ void AMSMaterialsSetting::create()
#endif
m_sizer_filament->Add(COMBOBOX_FILAMENT, 1, wxALIGN_CENTER, 0);
m_readonly_filament = new TextInput(this, wxEmptyString, "", "", wxDefaultPosition, AMS_MATERIALS_SETTING_COMBOX_WIDTH, wxTE_READONLY);
m_readonly_filament->SetBorderColor(StateColor(std::make_pair(0xDBDBDB, (int)StateColor::Focused), std::make_pair(0x00AE42, (int)StateColor::Hovered),
std::make_pair(0xDBDBDB, (int)StateColor::Normal)));
m_readonly_filament->GetTextCtrl()->Bind(wxEVT_SET_FOCUS, [](auto& e) {
;
});
m_sizer_filament->Add(m_readonly_filament, 1, wxALIGN_CENTER, 0);
m_readonly_filament->Hide();
wxBoxSizer *m_sizer_colour = new wxBoxSizer(wxHORIZONTAL);
m_title_colour = new wxStaticText(this, wxID_ANY, _L("Colour"), wxDefaultPosition, wxSize(AMS_MATERIALS_SETTING_LABEL_WIDTH, -1), 0);
@ -284,21 +294,12 @@ void AMSMaterialsSetting::update()
void AMSMaterialsSetting::enable_confirm_button(bool en)
{
if (m_is_third) m_button_confirm->Show(en);
//if (!en) {
// if (m_button_confirm->IsEnabled()) {
// m_button_confirm->Disable();
// m_button_confirm->SetBackgroundColor(wxColour(0x90, 0x90, 0x90));
// m_button_confirm->SetBorderColor(wxColour(0x90, 0x90, 0x90));
// }
//} else {
// if (!m_button_confirm->IsEnabled()) {
// m_button_confirm->Enable();
// m_button_confirm->SetBackgroundColor(m_btn_bg_green);
// m_button_confirm->SetBorderColor(m_btn_bg_green);
// }
//}
if (!m_is_third) return;
else {
m_button_confirm->Show(en);
COMBOBOX_FILAMENT->Show(en);
m_readonly_filament->Show(!en);
}
}
void AMSMaterialsSetting::on_select_ok(wxCommandEvent &event)
@ -351,7 +352,7 @@ void AMSMaterialsSetting::set_color(wxColour color)
void AMSMaterialsSetting::on_clr_picker(wxCommandEvent & event)
{
if(!m_is_third)
if(!m_is_third || obj->is_in_printing() || obj->can_resume())
return;
auto clr_dialog = new wxColourDialog(this, m_clrData);
show_flag = true;
@ -379,26 +380,23 @@ void AMSMaterialsSetting::Popup(wxString filament, wxString sn, wxString temp_mi
m_button_confirm->Hide();
m_sn_number->SetLabel(sn);
m_panel_SN->Show();
#ifdef __APPLE__
wxArrayString filament_only;
filament_only.push_back(filament);
COMBOBOX_FILAMENT->Set(filament_only);
#else
COMBOBOX_FILAMENT->Set(wxArrayString());
#endif
COMBOBOX_FILAMENT->SetValue(filament);
COMBOBOX_FILAMENT->Hide();
m_readonly_filament->Show();
m_readonly_filament->GetTextCtrl()->SetLabel("Bambu " + filament);
m_input_nozzle_min->GetTextCtrl()->SetValue(temp_min);
m_input_nozzle_max->GetTextCtrl()->SetValue(temp_max);
Layout();
Fit();
update();
ShowModal();
return;
}
m_button_confirm->Show();
m_panel_SN->Hide();
COMBOBOX_FILAMENT->Show();
m_readonly_filament->Hide();
Layout();
Fit();
@ -407,66 +405,68 @@ void AMSMaterialsSetting::Popup(wxString filament, wxString sn, wxString temp_mi
wxArrayString filament_items;
std::set<std::string> filament_id_set;
PresetBundle* preset_bundle = wxGetApp().preset_bundle;
if (preset_bundle) {
BOOST_LOG_TRIVIAL(trace) << "system_preset_bundle filament number=" << preset_bundle->filaments.size();
for (auto filament_it = preset_bundle->filaments.begin(); filament_it != preset_bundle->filaments.end(); filament_it++) {
PresetBundle* preset_bundle = wxGetApp().preset_bundle;
if (preset_bundle) {
BOOST_LOG_TRIVIAL(trace) << "system_preset_bundle filament number=" << preset_bundle->filaments.size();
for (auto filament_it = preset_bundle->filaments.begin(); filament_it != preset_bundle->filaments.end(); filament_it++) {
// filter by system preset
if (!filament_it->is_system) continue;
for (auto printer_it = preset_bundle->printers.begin(); printer_it != preset_bundle->printers.end(); printer_it++) {
// filter by system preset
if (!filament_it->is_system) continue;
if (!printer_it->is_system) continue;
// get printer_model
ConfigOption* printer_model_opt = printer_it->config.option("printer_model");
ConfigOptionString* printer_model_str = dynamic_cast<ConfigOptionString*>(printer_model_opt);
if (!printer_model_str || !obj)
continue;
for (auto printer_it = preset_bundle->printers.begin(); printer_it != preset_bundle->printers.end(); printer_it++) {
// filter by system preset
if (!printer_it->is_system) continue;
// get printer_model
ConfigOption* printer_model_opt = printer_it->config.option("printer_model");
ConfigOptionString* printer_model_str = dynamic_cast<ConfigOptionString*>(printer_model_opt);
if (!printer_model_str || !obj)
continue;
// use printer_model as printer type
if (printer_model_str->value != MachineObject::get_preset_printer_model_name(obj->printer_type))
continue;
ConfigOption* printer_opt = filament_it->config.option("compatible_printers");
ConfigOptionStrings* printer_strs = dynamic_cast<ConfigOptionStrings*>(printer_opt);
for (auto printer_str : printer_strs->values) {
if (printer_it->name == printer_str) {
if (filament_id_set.find(filament_it->filament_id) != filament_id_set.end()) {
continue;
}
else {
filament_id_set.insert(filament_it->filament_id);
// name matched
filament_items.push_back(filament_it->alias);
if (filament_it->filament_id == ams_filament_id) {
selection_idx = idx;
// use printer_model as printer type
if (printer_model_str->value != MachineObject::get_preset_printer_model_name(obj->printer_type))
continue;
ConfigOption* printer_opt = filament_it->config.option("compatible_printers");
ConfigOptionStrings* printer_strs = dynamic_cast<ConfigOptionStrings*>(printer_opt);
for (auto printer_str : printer_strs->values) {
if (printer_it->name == printer_str) {
if (filament_id_set.find(filament_it->filament_id) != filament_id_set.end()) {
continue;
} else {
filament_id_set.insert(filament_it->filament_id);
// name matched
filament_items.push_back(filament_it->alias);
if (filament_it->filament_id == ams_filament_id) {
selection_idx = idx;
// update if nozzle_temperature_range is found
ConfigOption* opt_min = filament_it->config.option("nozzle_temperature_range_low");
if(opt_min) {
ConfigOptionInts* opt_min_ints = dynamic_cast<ConfigOptionInts*>(opt_min);
if (opt_min_ints) {
wxString text_nozzle_temp_min = wxString::Format("%d", opt_min_ints->get_at(0));
m_input_nozzle_min->GetTextCtrl()->SetValue(text_nozzle_temp_min);
}
}
ConfigOption* opt_max = filament_it->config.option("nozzle_temperature_range_high");
if (opt_max) {
ConfigOptionInts* opt_max_ints = dynamic_cast<ConfigOptionInts*>(opt_max);
if (opt_max_ints) {
wxString text_nozzle_temp_max = wxString::Format("%d", opt_max_ints->get_at(0));
m_input_nozzle_max->GetTextCtrl()->SetValue(text_nozzle_temp_max);
}
// update if nozzle_temperature_range is found
ConfigOption* opt_min = filament_it->config.option("nozzle_temperature_range_low");
if (opt_min) {
ConfigOptionInts* opt_min_ints = dynamic_cast<ConfigOptionInts*>(opt_min);
if (opt_min_ints) {
wxString text_nozzle_temp_min = wxString::Format("%d", opt_min_ints->get_at(0));
m_input_nozzle_min->GetTextCtrl()->SetValue(text_nozzle_temp_min);
}
}
ConfigOption* opt_max = filament_it->config.option("nozzle_temperature_range_high");
if (opt_max) {
ConfigOptionInts* opt_max_ints = dynamic_cast<ConfigOptionInts*>(opt_max);
if (opt_max_ints) {
wxString text_nozzle_temp_max = wxString::Format("%d", opt_max_ints->get_at(0));
m_input_nozzle_max->GetTextCtrl()->SetValue(text_nozzle_temp_max);
}
}
idx++;
}
idx++;
}
}
}
}
}
COMBOBOX_FILAMENT->Set(filament_items);
COMBOBOX_FILAMENT->SetSelection(selection_idx);
post_select_event();
}
update();
ShowModal();
}

View file

@ -84,12 +84,12 @@ protected:
Button * m_button_close;
Button * m_clr_picker;
wxColourData * m_clrData;
#ifdef __APPLE__
wxComboBox *m_comboBox_filament_mac;
#else
ComboBox *m_comboBox_filament;
#endif
TextInput* m_readonly_filament;
};
}} // namespace Slic3r::GUI

View file

@ -253,6 +253,8 @@ void AMSSetting::on_insert_material_read(wxCommandEvent &event)
m_sizer_Insert_material_tip_inline->Layout();
Layout();
Fit();
event.Skip();
}
void AMSSetting::on_starting_read(wxCommandEvent &event)
@ -276,6 +278,8 @@ void AMSSetting::on_starting_read(wxCommandEvent &event)
m_sizer_starting_tip_inline->Layout();
Layout();
Fit();
event.Skip();
}
wxString AMSSetting::append_title(wxString text)

View file

@ -526,7 +526,7 @@ AmsMapingTipPopup::AmsMapingTipPopup(wxWindow *parent)
m_sizer_body->Add(0, 0, 0, wxEXPAND | wxLEFT, FromDIP(20));
m_panel_enable_ams = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(200, -1), wxTAB_TRAVERSAL);
m_panel_enable_ams = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(FromDIP(220), -1), wxTAB_TRAVERSAL);
m_panel_enable_ams->SetBackgroundColour(*wxWHITE);
wxBoxSizer *sizer_enable_ams = new wxBoxSizer(wxVERTICAL);
@ -536,8 +536,9 @@ AmsMapingTipPopup::AmsMapingTipPopup(wxWindow *parent)
sizer_enable_ams->Add(m_title_enable_ams, 0, 0, 0);
m_tip_enable_ams = new wxStaticText(m_panel_enable_ams, wxID_ANY, _L("Print with filaments in the AMS"), wxDefaultPosition, wxDefaultSize, 0);
m_tip_enable_ams->SetMinSize(wxSize(FromDIP(200), FromDIP(50)));
m_tip_enable_ams->Wrap(FromDIP(200));
m_tip_enable_ams->SetBackgroundColour(*wxWHITE);
m_tip_enable_ams->Wrap(-1);
sizer_enable_ams->Add(m_tip_enable_ams, 0, wxTOP, 8);
wxBoxSizer *sizer_enable_ams_img;
@ -558,7 +559,7 @@ AmsMapingTipPopup::AmsMapingTipPopup(wxWindow *parent)
m_sizer_body->Add(m_split_lines, 0, wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT, FromDIP(10));
m_panel_disable_ams = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(200, -1), wxTAB_TRAVERSAL);
m_panel_disable_ams = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(FromDIP(220), -1), wxTAB_TRAVERSAL);
m_panel_disable_ams->SetBackgroundColour(*wxWHITE);
wxBoxSizer *sizer_disable_ams;
sizer_disable_ams = new wxBoxSizer(wxVERTICAL);
@ -569,8 +570,9 @@ AmsMapingTipPopup::AmsMapingTipPopup(wxWindow *parent)
sizer_disable_ams->Add(m_title_disable_ams, 0, 0, 0);
m_tip_disable_ams = new wxStaticText(m_panel_disable_ams, wxID_ANY, _L("Print with the filament mounted on the back of chassis"), wxDefaultPosition, wxDefaultSize, 0);
m_tip_disable_ams->SetMinSize(wxSize(FromDIP(200), FromDIP(50)));
m_tip_disable_ams->Wrap(FromDIP(200));
m_tip_disable_ams->SetBackgroundColour(*wxWHITE);
m_tip_disable_ams->Wrap(-1);
sizer_disable_ams->Add(m_tip_disable_ams, 0, wxTOP, FromDIP(8));
wxBoxSizer *sizer_disable_ams_img;

View file

@ -356,6 +356,7 @@ MachineObject::MachineObject(NetworkAgent* agent, std::string name, std::string
mc_print_percent = 0;
mc_print_sub_stage = 0;
mc_left_time = 0;
home_flag = -1;
printing_speed_lvl = PrintingSpeedLevel::SPEED_LEVEL_INVALID;
}
@ -1026,6 +1027,22 @@ bool MachineObject::is_system_printing()
return false;
}
bool MachineObject::is_axis_at_home(std::string axis)
{
if (home_flag < 0)
return true;
if (axis == "X") {
return home_flag & 1 == 1;
} else if (axis == "Y") {
return home_flag >> 1 & 1 == 1;
} else if (axis == "Z") {
return home_flag >> 2 & 1 == 1;
} else {
return true;
}
}
wxString MachineObject::get_curr_stage()
{
if (stage_list_info.empty()) {
@ -1315,6 +1332,10 @@ int MachineObject::command_ams_user_settings(int ams_id, bool start_read_opt, bo
j["print"]["startup_read_option"] = start_read_opt;
j["print"]["tray_read_option"] = tray_read_opt;
ams_insert_flag = tray_read_opt;
ams_power_on_flag = start_read_opt;
ams_user_setting_hold_count = HOLD_COUNT_MAX;
return this->publish_json(j.dump());
}
@ -1399,11 +1420,11 @@ int MachineObject::command_set_printing_speed(PrintingSpeedLevel lvl)
int MachineObject::command_axis_control(std::string axis, double unit, double value, int speed)
{
char cmd[64];
char cmd[256];
if (axis.compare("X") == 0
|| axis.compare("Y") == 0
|| axis.compare("Z") == 0) {
sprintf(cmd, "G91 \nG0 %s%0.1f F%d\n", axis.c_str(), value * unit, speed);
sprintf(cmd, "M211 S \nM211 X1 Y1 Z1\nM1002 push_ref_mode\nG91 \nG1 %s%0.1f F%d\nM1002 pop_ref_mode\nM211 R\n", axis.c_str(), value * unit, speed);
}
else if (axis.compare("E") == 0) {
sprintf(cmd, "M83 \nG0 %s%0.1f F%d\n", axis.c_str(), value * unit, speed);
@ -1799,6 +1820,10 @@ int MachineObject::parse_json(std::string payload)
print_type = jj["print_type"].get<std::string>();
}
if (jj.contains("home_flag")) {
home_flag = jj["home_flag"].get<int>();
}
if (jj.contains("mc_remaining_time")) {
if (jj["mc_remaining_time"].is_string())
mc_left_time = stoi(j["print"]["mc_remaining_time"].get<std::string>()) * 60;
@ -2261,16 +2286,21 @@ int MachineObject::parse_json(std::string payload)
if (jj["ams"].contains("tray_tar")) {
m_tray_tar = jj["ams"]["tray_tar"].get<std::string>();
}
if (jj["ams"].contains("insert_flag")) {
ams_insert_flag = jj["ams"]["insert_flag"].get<bool>();
}
if (jj["ams"].contains("ams_rfid_status"))
ams_rfid_status = jj["ams"]["ams_rfid_status"].get<int>();
if (jj["ams"].contains("power_on_flag")) {
ams_power_on_flag = jj["ams"]["power_on_flag"].get<bool>();
if (jj["ams"].contains("insert_flag") || jj["ams"].contains("power_on_flag")) {
if (ams_user_setting_hold_count > 0) {
ams_user_setting_hold_count--;
} else {
if (jj["ams"].contains("insert_flag")) {
ams_insert_flag = jj["ams"]["insert_flag"].get<bool>();
}
if (jj["ams"].contains("power_on_flag")) {
ams_power_on_flag = jj["ams"]["power_on_flag"].get<bool>();
}
}
}
if (ams_exist_bits != last_ams_exist_bits
|| last_tray_exist_bits != last_tray_exist_bits
|| tray_is_bbl_bits != last_is_bbl_bits

View file

@ -364,6 +364,7 @@ public:
bool ams_insert_flag { false };
bool ams_power_on_flag { false };
bool ams_support_use_ams { false };
int ams_user_setting_hold_count = 0;
AmsStatusMain ams_status_main;
int ams_status_sub;
int ams_version = 0;
@ -459,6 +460,7 @@ public:
int mc_print_percent; /* left print progess in percent */
int mc_left_time; /* left time in seconds */
int last_mc_print_stage;
int home_flag;
bool is_system_printing();
int print_error;
@ -467,6 +469,8 @@ public:
int m_push_count = 0;
bool calibration_done { false };
bool is_axis_at_home(std::string axis);
wxString get_curr_stage();
// return curr stage index of stage list
int get_curr_stage_idx();

View file

@ -1932,8 +1932,8 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
auto co = dynamic_cast<const ConfigOptionEnum<PrintSequence>*>(m_config->option<ConfigOptionEnum<PrintSequence>>("print_sequence"));
const DynamicPrintConfig &dconfig = wxGetApp().preset_bundle->prints.get_edited_preset().config;
const ConfigOption * option = dconfig.option("timelapse_no_toolhead");
bool timelapse_enabled = option ? option->getBool() : false;
auto timelapse_type = dconfig.option<ConfigOptionEnum<TimelapseType>>("timelapse_type");
bool timelapse_enabled = timelapse_type ? (timelapse_type->value == TimelapseType::tlSmooth) : false;
if (timelapse_enabled || (filaments_count > 1 && wt && co != nullptr && co->value != PrintSequence::ByObject)) {
for (int plate_id = 0; plate_id < n_plates; plate_id++) {
@ -2264,6 +2264,12 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
return;
}
bool is_in_painting_mode = false;
GLGizmoPainterBase *current_gizmo_painter = dynamic_cast<GLGizmoPainterBase *>(get_gizmos_manager().get_current());
if (current_gizmo_painter != nullptr) {
is_in_painting_mode = true;
}
//BBS: add orient deactivate logic
if (keyCode == WXK_ESCAPE
&& (_deactivate_arrange_menu() || _deactivate_orient_menu()))
@ -2281,7 +2287,8 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
#else /* __APPLE__ */
case WXK_CONTROL_A:
#endif /* __APPLE__ */
post_event(SimpleEvent(EVT_GLCANVAS_SELECT_ALL));
if (!is_in_painting_mode)
post_event(SimpleEvent(EVT_GLCANVAS_SELECT_ALL));
break;
#ifdef __APPLE__
case 'c':
@ -2289,7 +2296,8 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
#else /* __APPLE__ */
case WXK_CONTROL_C:
#endif /* __APPLE__ */
post_event(SimpleEvent(EVT_GLTOOLBAR_COPY));
if (!is_in_painting_mode)
post_event(SimpleEvent(EVT_GLTOOLBAR_COPY));
break;
#ifdef __APPLE__
case 'm':
@ -2325,7 +2333,8 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
#else /* __APPLE__ */
case WXK_CONTROL_V:
#endif /* __APPLE__ */
post_event(SimpleEvent(EVT_GLTOOLBAR_PASTE));
if (!is_in_painting_mode)
post_event(SimpleEvent(EVT_GLTOOLBAR_PASTE));
break;
#ifdef __APPLE__
@ -2334,7 +2343,8 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
#else /* __APPLE__ */
case WXK_CONTROL_X:
#endif /* __APPLE__ */
post_event(SimpleEvent(EVT_GLTOOLBAR_CUT));
if (!is_in_painting_mode)
post_event(SimpleEvent(EVT_GLTOOLBAR_CUT));
break;
#ifdef __APPLE__
@ -5845,14 +5855,14 @@ void GLCanvas3D::_check_and_update_toolbar_icon_scale()
{
#if ENABLE_RETINA_GL
IMSlider *m_layers_slider = get_gcode_viewer().get_layers_slider();
IMSlider *m_moves_slider = get_gcode_viewer().get_moves_slider();
IMSlider* m_layers_slider = get_gcode_viewer().get_layers_slider();
IMSlider* m_moves_slider = get_gcode_viewer().get_moves_slider();
const float sc = m_retina_helper->get_scale_factor();
m_layers_slider->set_scale(sc);
m_moves_slider->set_scale(sc);
m_gcode_viewer.set_scale(sc);
auto *m_notification = wxGetApp().plater()->get_notification_manager();
auto* m_notification = wxGetApp().plater()->get_notification_manager();
m_notification->set_scale(sc);
#endif
@ -5877,7 +5887,7 @@ void GLCanvas3D::_check_and_update_toolbar_icon_scale()
collapse_toolbar.set_scale(sc);
size *= m_retina_helper->get_scale_factor();
auto *m_notification = wxGetApp().plater()->get_notification_manager();
auto* m_notification = wxGetApp().plater()->get_notification_manager();
m_notification->set_scale(sc);
#else
//BBS: GUI refactor: GLToolbar
@ -5892,12 +5902,20 @@ void GLCanvas3D::_check_and_update_toolbar_icon_scale()
float collapse_toolbar_width = collapse_toolbar.is_enabled() ? collapse_toolbar.get_width() : GLToolbar::Default_Icons_Size;
float top_tb_width = m_main_toolbar.get_width() + m_gizmos.get_scaled_total_width() + m_assemble_view_toolbar.get_width() + m_separator_toolbar.get_width() + collapse_toolbar_width;
int items_cnt = m_main_toolbar.get_visible_items_cnt() + m_gizmos.get_selectable_icons_cnt() + m_assemble_view_toolbar.get_visible_items_cnt() + m_separator_toolbar.get_visible_items_cnt() + collapse_toolbar.get_visible_items_cnt();
int items_cnt = m_main_toolbar.get_visible_items_cnt() + m_gizmos.get_selectable_icons_cnt() + m_assemble_view_toolbar.get_visible_items_cnt() + m_separator_toolbar.get_visible_items_cnt() + collapse_toolbar.get_visible_items_cnt();
float noitems_width = top_tb_width - size * items_cnt; // width of separators and borders in top toolbars
// calculate scale needed for items in all top toolbars
#ifdef __WINDOWS__
cnv_size.set_width(cnv_size.get_width() + m_separator_toolbar.get_width() + collapse_toolbar_width);
#endif
float new_h_scale = (cnv_size.get_width() - noitems_width) / (items_cnt * GLToolbar::Default_Icons_Size);
//for protect
if (new_h_scale <= 0) {
new_h_scale = 1;
}
//use the same value as horizon
float new_v_scale = new_h_scale;
#else

View file

@ -1590,7 +1590,7 @@ void GUI_App::init_networking_callbacks()
if (state == ConnectStatus::ConnectStatusOk) {
obj->command_request_push_all();
obj->command_get_version();
} else if (state == ConnectStatus::ConnectStatusFailed || ConnectStatus::ConnectStatusLost) {
} else if (state == ConnectStatus::ConnectStatusFailed) {
obj->set_access_code("");
wxString text;
if (msg == "5") {
@ -1600,6 +1600,9 @@ void GUI_App::init_networking_callbacks()
text = wxString::Format(_L("Connect %s failed! [SN:%s, code=%s]"), from_u8(obj->dev_name), obj->dev_id, msg);
wxGetApp().show_dialog(text);
}
} else if (state == ConnectStatus::ConnectStatusLost) {
m_device_manager->set_selected_machine("");
BOOST_LOG_TRIVIAL(info) << "set_on_local_connect_fn: state = lost";
} else {
BOOST_LOG_TRIVIAL(info) << "set_on_local_connect_fn: state = " << state;
}
@ -2007,19 +2010,36 @@ bool GUI_App::on_init_inner()
dialog.SetExtendedMessage(extmsg);*/
UpdateVersionDialog dialog(this->mainframe);
wxString extmsg = wxString::FromUTF8(version_info.description);
dialog.update_version_info(extmsg, version_info.version_str);
switch (dialog.ShowModal())
{
case wxID_YES:
wxLaunchDefaultBrowser(version_info.url);
break;
case wxID_NO:
break;
default:
;
}
std::string skip_version_str = this->app_config->get("app", "skip_version");
bool skip_this_version = false;
if (!skip_version_str.empty()) {
BOOST_LOG_TRIVIAL(info) << "new version = " << version_info.version_str << ", skip version = " << skip_version_str;
if (version_info.version_str <= skip_version_str) {
skip_this_version = true;
} else {
app_config->set("skip_version", "");
skip_this_version = false;
}
}
if (!skip_this_version
|| evt.GetInt() != 0) {
UpdateVersionDialog dialog(this->mainframe);
wxString extmsg = wxString::FromUTF8(version_info.description);
dialog.update_version_info(extmsg, version_info.version_str);
if (evt.GetInt() != 0) {
dialog.m_remind_choice->Hide();
}
switch (dialog.ShowModal())
{
case wxID_YES:
wxLaunchDefaultBrowser(version_info.url);
break;
case wxID_NO:
break;
default:
;
}
}
}
});
@ -3288,7 +3308,7 @@ void GUI_App::reset_to_active()
last_active_point = std::chrono::system_clock::now();
}
void GUI_App::check_update(bool show_tips)
void GUI_App::check_update(bool show_tips, int by_user)
{
if (version_info.version_str.empty()) return;
if (version_info.url.empty()) return;
@ -3305,7 +3325,7 @@ void GUI_App::check_update(bool show_tips)
GUI::wxGetApp().enter_force_upgrade();
}
else {
GUI::wxGetApp().request_new_version();
GUI::wxGetApp().request_new_version(by_user);
}
} else {
wxGetApp().app_config->set("upgrade", "force_upgrade", false);
@ -3314,7 +3334,7 @@ void GUI_App::check_update(bool show_tips)
}
}
void GUI_App::check_new_version(bool show_tips)
void GUI_App::check_new_version(bool show_tips, int by_user)
{
std::string platform = "windows";
@ -3337,7 +3357,7 @@ void GUI_App::check_new_version(bool show_tips)
http.header("accept", "application/json")
.timeout_max(10)
.on_complete([this, show_tips](std::string body, unsigned) {
.on_complete([this, show_tips, by_user](std::string body, unsigned) {
try {
json j = json::parse(body);
if (j.contains("message")) {
@ -3357,8 +3377,8 @@ void GUI_App::check_new_version(bool show_tips)
if (j["software"].contains("force_update")) {
version_info.force_upgrade = j["software"]["force_update"].get<bool>();
}
CallAfter([this, show_tips](){
this->check_update(show_tips);
CallAfter([this, show_tips, by_user](){
this->check_update(show_tips, by_user);
});
}
}
@ -3377,10 +3397,11 @@ void GUI_App::check_new_version(bool show_tips)
//BBS pop up a dialog and download files
void GUI_App::request_new_version()
void GUI_App::request_new_version(int by_user)
{
wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_VERSION_ONLINE);
evt->SetString(GUI::from_u8(version_info.version_str));
evt->SetInt(by_user);
GUI::wxGetApp().QueueEvent(evt);
}
@ -3390,6 +3411,16 @@ void GUI_App::enter_force_upgrade()
GUI::wxGetApp().QueueEvent(evt);
}
void GUI_App::set_skip_version(bool skip)
{
BOOST_LOG_TRIVIAL(info) << "set_skip_version, skip = " << skip << ", version = " <<version_info.version_str;
if (skip) {
app_config->set("skip_version", version_info.version_str);
}else {
app_config->set("skip_version", "");
}
}
void GUI_App::no_new_version()
{
wxCommandEvent* evt = new wxCommandEvent(EVT_SHOW_NO_NEW_VERSION);
@ -4516,6 +4547,12 @@ void GUI_App::OSXStoreOpenFiles(const wxArrayString &fileNames)
// wxWidgets override to get an event on open files.
void GUI_App::MacOpenFiles(const wxArrayString &fileNames)
{
if (m_post_initialized) {
std::vector<wxString> names;
for (auto & n : fileNames) names.push_back(n);
start_new_slicer(names);
return;
}
std::vector<std::string> files;
std::vector<wxString> gcode_files;
std::vector<wxString> non_gcode_files;

View file

@ -143,6 +143,7 @@ public:
ver_items[i] = 0;
}
force_upgrade = false;
version_str = "";
}
void parse_version_str(std::string str) {
@ -388,10 +389,11 @@ public:
bool m_studio_active = true;
std::chrono::system_clock::time_point last_active_point;
void check_update(bool show_tips);
void check_new_version(bool show_tips = false);
void request_new_version();
void check_update(bool show_tips, int by_user);
void check_new_version(bool show_tips = false, int by_user = 0);
void request_new_version(int by_user);
void enter_force_upgrade();
void set_skip_version(bool skip = true);
void no_new_version();
void show_dialog(wxString msg);
void reload_settings();

View file

@ -1271,7 +1271,7 @@ void MenuFactory::append_menu_item_simplify(wxMenu* menu)
void MenuFactory::append_menu_item_per_object_settings(wxMenu* menu)
{
const std::vector<wxString> names = { _L("Per object edit"), _L("Edit print parameters for a single object") };
const std::vector<wxString> names = { _L("Edit in Parameter Table"), _L("Edit print parameters for a single object") };
// Delete old menu item
for (const wxString& name : names) {
const int item_id = menu->FindItem(name);

View file

@ -5052,9 +5052,7 @@ void ObjectList::apply_object_instance_transfrom_to_all_volumes(ModelObject *mod
model_object->ensure_on_bed();
// keep new instance center the same as the original center
model_object->translate(-original_instance_center);
model_object->origin_translation += original_instance_center;
model_object->translate_instances(model_object->origin_translation);
model_object->origin_translation = Vec3d::Zero();
model_object->translate_instances(original_instance_center);
// update the cache data in selection to keep the data of ModelVolume and GLVolume are consistent
wxGetApp().plater()->update();

View file

@ -540,6 +540,29 @@ wxString GridCellSupportEditor::ms_stringValues[2] = { wxT(""), wxT("") };
void GridCellSupportEditor::DoActivate(int row, int col, wxGrid* grid)
{
ObjectGrid* local_table = dynamic_cast<ObjectGrid*>(grid);
wxGridBlocks cell_array = grid->GetSelectedBlocks();
auto left_col = cell_array.begin()->GetLeftCol();
auto right_col = cell_array.begin()->GetRightCol();
auto top_row = cell_array.begin()->GetTopRow();
auto bottom_row = cell_array.begin()->GetBottomRow();
if ((left_col == right_col) &&
(top_row == bottom_row)) {
wxGridCellBoolEditor::DoActivate(row, col, grid);
grid->SelectBlock(row, col, row, col, true);
return;
}
else if( (left_col == right_col) &&
(top_row != bottom_row)){
for (auto i = top_row; i <= bottom_row; i++) {
//grid->GetTable()->SetValueAsBool(i, left_col, false);
wxGridCellBoolEditor::DoActivate(i, left_col, grid);
}
}
wxGridCellBoolEditor::DoActivate(row, col, grid);
grid->SelectBlock(row, col, row, col, true);
}
@ -672,8 +695,6 @@ void GridCellSupportRenderer::Draw(wxGrid& grid,
#endif // __WXOSX_MAC__
dc.DrawBitmap(check_on, rect.x + offsetx, rect.y + offsety);
//dc.SetBrush(wxBrush(wxColour(0x00, 0xAE, 0x42)));
//dc.DrawBitmap(check_on, (width - check_on.GetSize().x) / 2, (height - check_on.GetSize().y) / 2);
} else {
auto check_off = create_scaled_bitmap("check_off_focused", nullptr, 18);
dc.SetPen(*wxTRANSPARENT_PEN);
@ -689,11 +710,7 @@ void GridCellSupportRenderer::Draw(wxGrid& grid,
offsety = (height - check_off.GetSize().y) / 2;
#endif // __WXOSX_MAC__
dc.DrawBitmap(check_off, rect.x + offsetx, rect.y + offsety);
//dc.SetBrush(wxBrush(wxColour(0x00, 0xAE, 0x42)));
//dc.DrawBitmap(check_off, (width - check_off.GetSize().x) / 2, (height - check_off.GetSize().y) / 2);
}
}
@ -730,10 +747,13 @@ wxBEGIN_EVENT_TABLE( ObjectGrid, wxGrid )
EVT_KEY_UP( ObjectGrid::OnKeyUp )
EVT_CHAR ( ObjectGrid::OnChar )
EVT_GRID_LABEL_LEFT_CLICK ( ObjectGrid::OnColHeadLeftClick )
EVT_GRID_RANGE_SELECTED(ObjectGrid::OnRangeSelected)
wxEND_EVENT_TABLE()
bool ObjectGrid::OnCellLeftClick(wxGridEvent& event, int row, int col, ConfigOptionType type)
{
input_string = wxEmptyString;
if (type != coBool)
return false;
@ -819,6 +839,11 @@ bool ObjectGrid::OnCellLeftClick(wxGridEvent& event, int row, int col, ConfigOpt
return consumed;
}
void ObjectGrid::OnRangeSelected(wxGridRangeSelectEvent& ev)
{
ev.Skip();
}
void ObjectGrid::OnColHeadLeftClick(wxGridEvent& event)
{
bool consumed = false;
@ -838,6 +863,87 @@ void ObjectGrid::OnColHeadLeftClick(wxGridEvent& event)
void ObjectGrid::OnKeyDown( wxKeyEvent& event )
{
// see include/wx/defs.h enum wxKeyCode
int keyCode = event.GetKeyCode();
int ctrlMask = wxMOD_CONTROL;
int shiftMask = wxMOD_SHIFT;
// Coordinates of the selected block to copy to clipboard.
wxGridBlockCoords selection;
wxTextDataObject text_data;
if ((event.GetModifiers() & ctrlMask) != 0) {
// CTRL is pressed
switch (keyCode) {
case 'c':
case 'C':
{
// Check if we have any selected blocks and if we don't
// have too many of them.
const wxGridBlocks blocks = GetSelectedBlocks();
wxGridBlocks::iterator iter = blocks.begin();
if (iter == blocks.end())
{
// No selection, copy just the current cell.
if (m_currentCellCoords == wxGridNoCellCoords)
{
// But we don't even have it -- nothing to do then.
event.Skip();
break;
}
selection = wxGridBlockCoords(GetGridCursorRow(),
GetGridCursorCol(),
GetGridCursorRow(),
GetGridCursorCol());
}
else // We do have at least one selected block.
{
selection = *blocks.begin();
}
m_selected_block = selection;
ObjectGridTable* table = dynamic_cast<ObjectGridTable*>(this->GetTable());
if (GetGridCursorCol() == ObjectGridTable::col_printable ||
GetGridCursorCol() == ObjectGridTable::col_enable_support) {
m_cell_data = table->GetValueAsBool(GetGridCursorRow(), GetGridCursorCol()) ? wxT("1") : wxT("0");
}
else if (GetGridCursorCol() == ObjectGridTable::col_filaments) {
m_cell_data = table->GetValue(GetGridCursorRow(), GetGridCursorCol());
}
else {
m_cell_data = table->GetValue(GetGridCursorRow(), GetGridCursorCol());
}
break;
}
case 'v':
case 'V': {
wxTheClipboard->GetData(text_data);
if (!m_cell_data.empty()) {
text_data.SetText(m_cell_data);
}
paste_data(text_data);
break;
}
case 'f':
case 'F':
//TODO: search
break;
case 'z':
case 'Z':
//TODO:
break;
default:
event.Skip();
}
}
event.Skip();
}
@ -942,20 +1048,21 @@ void ObjectGrid::paste_data( wxTextDataObject& text_data )
wxLogWarning(_L("one cell can only be copied to one or multiple cells in the same column"));
}
else {
split(buf, string_array);
wxString source_string = string_array[0];
if (string_array.GetCount() <= 0) {
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(", can not split pasted data %1%")%buf;
return;
}
for ( int i = 0; i < dst_row_cnt; i++ )
{
if (!this->IsReadOnly(dst_top_row+i, dst_left_col)) {
grid_table->SetValue(dst_top_row+i, dst_left_col, source_string);
grid_table->OnCellValueChanged(dst_top_row+i, dst_left_col);
}
}
split(buf, string_array);
wxString source_string = string_array[0];
if (string_array.GetCount() <= 0) {
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(", can not split pasted data %1%") % buf;
return;
}
for (int i = 0; i < dst_row_cnt; i++)
{
if (!this->IsReadOnly(dst_top_row + i, dst_left_col)) {
grid_table->SetValue(dst_top_row + i, dst_left_col, source_string);
grid_table->OnCellValueChanged(dst_top_row + i, dst_left_col);
}
}
}
}
else {
wxLogWarning(_L("multiple cells copy is not supported"));
@ -983,74 +1090,14 @@ void ObjectGrid::paste_data( wxTextDataObject& text_data )
void ObjectGrid::OnKeyUp( wxKeyEvent& event )
{
// see include/wx/defs.h enum wxKeyCode
int keyCode = event.GetKeyCode();
int ctrlMask = wxMOD_CONTROL;
int shiftMask = wxMOD_SHIFT;
// Coordinates of the selected block to copy to clipboard.
wxGridBlockCoords selection;
wxTextDataObject text_data;
if ((event.GetModifiers() & ctrlMask) != 0) {
// CTRL is pressed
switch (keyCode) {
case 'c':
case 'C':
{
// Check if we have any selected blocks and if we don't
// have too many of them.
const wxGridBlocks blocks = GetSelectedBlocks();
wxGridBlocks::iterator iter = blocks.begin();
if (iter == blocks.end())
{
// No selection, copy just the current cell.
if (m_currentCellCoords == wxGridNoCellCoords)
{
// But we don't even have it -- nothing to do then.
event.Skip();
break;
}
selection = wxGridBlockCoords(GetGridCursorRow(),
GetGridCursorCol(),
GetGridCursorRow(),
GetGridCursorCol());
}
else // We do have at least one selected block.
{
selection = *blocks.begin();
}
m_selected_block = selection;
break;
}
case 'v':
case 'V':
//
wxTheClipboard->GetData(text_data);
paste_data(text_data);
break;
case 'f':
case 'F':
//TODO: search
break;
case 'z':
case 'Z':
//TODO:
break;
default:
event.Skip();
}
}
event.Skip();
}
void ObjectGrid::OnChar( wxKeyEvent& event )
{
void ObjectGrid::OnChar( wxKeyEvent& event ) {
auto keycode = event.GetKeyCode();
if (keycode >= 0x20 && keycode <= 0x7F) {
input_string = event.GetUnicodeKey();
}
event.Skip();
}
@ -1387,7 +1434,7 @@ void ObjectGridTable::update_volume_values_from_object(int row, int col)
}
else
part_row->filaments = grid_row->filaments;
part_row->ori_filaments = grid_row->filaments;
//part_row->ori_filaments = grid_row->filaments;
}
else
reload_part_data(part_row, grid_row, m_col_data[col]->category, global_config);
@ -1725,7 +1772,7 @@ wxString ObjectGridTable::convert_filament_string(int index, wxString& filament_
else
result_str = filament_str;
result_str = "";
//result_str = "";
return result_str;
}
@ -1762,7 +1809,7 @@ void ObjectGridTable::init_cols(ObjectGrid *object_grid)
//3th column: for object/volume name
col = new ObjectGridCol(coString, "name", ObjectGridTable::category_all, false, false, true, false, wxALIGN_LEFT);
col->size = 200;
//col->size = 200;
m_col_data.push_back(col);
//object/volume extruder_id
@ -1774,11 +1821,11 @@ void ObjectGridTable::init_cols(ObjectGrid *object_grid)
m_col_data.push_back(col);
//reset icon for extruder_id
col = new ObjectGridCol(coEnum, "extruder_reset", ObjectGridTable::category_all, false, true, false, false, wxALIGN_CENTRE);
col = new ObjectGridCol(coString, "extruder_reset", ObjectGridTable::category_all, false, false, false, false, wxALIGN_CENTRE);
m_col_data.push_back(col);
//object layer height
col = new ObjectGridCol(coFloat, "layer_height", L("Quality"), true, false, true, true, wxALIGN_CENTRE);
col = new ObjectGridCol(coFloat, "layer_height", L("Quality"), true, false, true, true, wxALIGN_LEFT);
col->size = object_grid->GetTextExtent(L("Layer height")).x - 28;
m_col_data.push_back(col);
@ -1825,8 +1872,8 @@ void ObjectGridTable::init_cols(ObjectGrid *object_grid)
m_col_data.push_back(col);
//object/volume speed
col = new ObjectGridCol(coFloat, "inner_wall_speed", L("Speed"), false, false, true, true, wxALIGN_LEFT);
col->size = object_grid->GetTextExtent(L("Inner wall speed")).x;
col = new ObjectGridCol(coFloat, "outer_wall_speed", L("Speed"), false, false, true, true, wxALIGN_LEFT);
col->size = object_grid->GetTextExtent(L("Outer wall speed")).x;
m_col_data.push_back(col);
//reset icon for speed
@ -1886,7 +1933,7 @@ void ObjectGridTable::construct_object_configs(ObjectGrid *object_grid)
object_grid->filaments.value = 1;
object_grid->config->set_key_value(m_col_data[col_filaments]->key, object_grid->filaments.clone());
}
object_grid->ori_filaments.value = 1;
//object_grid->ori_filaments.value = 1;
object_grid->layer_height = *(get_object_config_value<ConfigOptionFloat>(global_config, object_grid->config, m_col_data[col_layer_height]->key));
object_grid->ori_layer_height = *(global_config.option<ConfigOptionFloat>(m_col_data[col_layer_height]->key));
@ -1936,7 +1983,7 @@ void ObjectGridTable::construct_object_configs(ObjectGrid *object_grid)
}
else
volume_grid->filaments = object_grid->filaments;
volume_grid->ori_filaments = object_grid->filaments;
//volume_grid->ori_filaments = object_grid->filaments;
volume_grid->layer_height = *(get_volume_config_value<ConfigOptionFloat>(global_config, object_grid->config, volume_grid->config, m_col_data[col_layer_height]->key));
volume_grid->ori_layer_height = object_grid->layer_height;
volume_grid->wall_loops = *(get_volume_config_value<ConfigOptionInt>(global_config, object_grid->config, volume_grid->config, m_col_data[col_wall_loops]->key));
@ -2179,10 +2226,17 @@ void ObjectGridTable::update_row_properties()
//new wxGridCellChoiceEditor(grid_col->choice_count, grid_col->choices));
}
break;
case coFloat:
grid_table->SetCellEditor(row, col, new GridCellTextEditor());
grid_table->SetCellRenderer(row, col, new wxGridCellFloatRenderer(6,1));
break;
case coFloat: {
grid_table->SetCellEditor(row, col, new GridCellTextEditor());
if (col == ObjectGridTable::col_speed_perimeter) {
grid_table->SetCellRenderer(row, col, new wxGridCellFloatRenderer(6, 0));
}
else {
grid_table->SetCellRenderer(row, col, new wxGridCellFloatRenderer(6, 2));
}
break;
}
case coPercent:
{
grid_table->SetCellEditor(row, col, new GridCellTextEditor());
@ -2195,7 +2249,7 @@ void ObjectGridTable::update_row_properties()
}
}
else if (col == ObjectGridTable::col_name) {
grid_table->SetCellFont(row, col, Label::Body_13);
grid_table->SetCellFont(row, col, Label::Body_12);
/*if (grid_row->row_type == ObjectGridTable::row_object)
grid_table->SetCellFont(row, col, Label::Head_14);
else
@ -2301,6 +2355,22 @@ void ObjectGridTable::sort_by_col(int col)
m_sort_col = col;
}
}
else if (col == col_filaments) {
if (m_sort_col == col) {
auto sort_func = [](ObjectGridRow* row1, ObjectGridRow* row2) {
return (std::to_string(row2->filaments.value).compare(std::to_string(row1->filaments.value)) < 0);
};
sort_row_data(sort_func);
m_sort_col = -1;
}
else {
auto sort_func = [](ObjectGridRow* row1, ObjectGridRow* row2) {
return (std::to_string(row1->filaments.value).compare(std::to_string(row2->filaments.value)) < 0);
};
sort_row_data(sort_func);
m_sort_col = col;
}
}
//else if (col == col_assemble_name) {
// if (m_sort_col == col) {
// compare_row_func sort_func = [](ObjectGridRow* row1, ObjectGridRow* row2) {
@ -2443,7 +2513,7 @@ void ObjectGridTable::OnSelectCell(int row, int col)
{
m_selected_cells.clear();
m_panel->m_side_window->Freeze();
if (row == 0) {
if (row == 0 || col == col_filaments) {
m_panel->m_object_settings->UpdateAndShow(row, false, false, false, nullptr, nullptr, std::string());
}
else {
@ -2762,13 +2832,13 @@ void ObjectTablePanel::load_data()
//m_object_grid->CreateGrid(rows, cols, wxGridSelectCells);
#if HAS_COL_HEADER
m_object_grid->SetColLabelAlignment(wxALIGN_LEFT, wxALIGN_CENTER);
m_object_grid->SetColLabelValue(ObjectGridTable::col_printable, _L("Printable"));
m_object_grid->SetColLabelValue(ObjectGridTable::col_printable_reset, "");
m_object_grid->SetColLabelValue(ObjectGridTable::col_plate_index, _L("Plate"));
m_object_grid->SetColLabelValue(ObjectGridTable::col_plate_index, wxString::Format("%S%S", _L("Plate"), wxString::FromUTF8("\u2191\u2193")));
/*m_object_grid->SetColLabelValue(ObjectGridTable::col_assemble_name, L("Module"));*/
m_object_grid->SetColLabelValue(ObjectGridTable::col_name, _L("Name"));
m_object_grid->SetColLabelValue(ObjectGridTable::col_filaments, _L("Filament"));
m_object_grid->SetColLabelValue(ObjectGridTable::col_name, wxString::Format("%S%S", _L("Name"), wxString::FromUTF8("\u2191\u2193")));
m_object_grid->SetColLabelValue(ObjectGridTable::col_filaments, wxString::Format("%S%S", _L("Filament"), wxString::FromUTF8("\u2191\u2193")));
m_object_grid->SetColLabelValue(ObjectGridTable::col_filaments_reset, "");
m_object_grid->SetColLabelValue(ObjectGridTable::col_layer_height, _L("Layer height"));
m_object_grid->SetColLabelValue(ObjectGridTable::col_layer_height_reset, "");
@ -2780,7 +2850,7 @@ void ObjectTablePanel::load_data()
m_object_grid->SetColLabelValue(ObjectGridTable::col_enable_support_reset, "");
m_object_grid->SetColLabelValue(ObjectGridTable::col_brim_type, _L("Brim"));
m_object_grid->SetColLabelValue(ObjectGridTable::col_brim_type_reset, "");
m_object_grid->SetColLabelValue(ObjectGridTable::col_speed_perimeter, _L("Inner wall speed"));
m_object_grid->SetColLabelValue(ObjectGridTable::col_speed_perimeter, _L("Outer wall speed"));
m_object_grid->SetColLabelValue(ObjectGridTable::col_speed_perimeter_reset, "");
m_object_grid->SetLabelFont(Label::Head_13);
m_object_grid->SetLabelTextColour(wxColour(0x30,0x3a,0x3c));
@ -2795,6 +2865,7 @@ void ObjectTablePanel::load_data()
m_object_grid->EnableDragGridSize(false);
m_object_grid->EnableDragRowSize(false);
/*set the first row as label*/
//format
wxGridCellAttr *attr;
@ -2878,10 +2949,17 @@ void ObjectTablePanel::load_data()
m_object_grid->SetCellRenderer(row, col, new wxGridCellChoiceRenderer());
}
break;
case coFloat:
m_object_grid->SetCellEditor(row, col, new GridCellTextEditor());
m_object_grid->SetCellRenderer(row, col, new wxGridCellFloatRenderer(6,1));
break;
case coFloat: {
m_object_grid->SetCellEditor(row, col, new GridCellTextEditor());
if (col == ObjectGridTable::col_speed_perimeter) {
m_object_grid->SetCellRenderer(row, col, new wxGridCellFloatRenderer(6, 0));
}
else {
m_object_grid->SetCellRenderer(row, col, new wxGridCellFloatRenderer(6, 2));
}
break;
}
case coPercent:
{
m_object_grid->SetCellEditor(row, col, new GridCellTextEditor());
@ -2914,25 +2992,25 @@ void ObjectTablePanel::load_data()
for (int i = 0; i < ObjectGridTable::col_max; i++) {
switch (i) {
case ObjectGridTable::col_printable: {
m_object_grid->SetColSize(i, m_object_grid->GetColSize(i) - FromDIP(28));
break;
}
/* case ObjectGridTable::col_printable: {
m_object_grid->SetColSize(i, m_object_grid->GetColSize(i) - FromDIP(28) - FromDIP(5));
break;
}*/
case ObjectGridTable::col_printable_reset:
m_object_grid->SetColSize(i, FromDIP(28));
break;
case ObjectGridTable::col_printable_reset:
m_object_grid->SetColSize(i, FromDIP(0));
break;
case ObjectGridTable::col_name:
m_object_grid->SetColSize(i, FromDIP(100));
m_object_grid->SetColSize(i, FromDIP(140));
break;
case ObjectGridTable::col_filaments:
m_object_grid->SetColSize(i, FromDIP(52));
break;
/* case ObjectGridTable::col_filaments:
m_object_grid->SetColSize(i, FromDIP(55));
break;*/
case ObjectGridTable::col_filaments_reset:
m_object_grid->SetColSize(i, FromDIP(28));
m_object_grid->SetColSize(i, FromDIP(0));
break;
case ObjectGridTable::col_layer_height: {
@ -2948,10 +3026,14 @@ void ObjectTablePanel::load_data()
m_object_grid->SetColSize(i, FromDIP(28));
break;
case ObjectGridTable::col_wall_loops:
m_object_grid->SetColSize(i, m_object_grid->GetColSize(i) - FromDIP(28));
case ObjectGridTable::col_wall_loops: {
auto width = m_object_grid->GetColSize(i) - FromDIP(28);
if (width < m_object_grid->GetTextExtent(("000.00")).x) {
width = m_object_grid->GetTextExtent(("000.00")).x;
}
m_object_grid->SetColSize(i, width);
break;
}
case ObjectGridTable::col_wall_loops_reset:
m_object_grid->SetColSize(i, FromDIP(28));
break;
@ -3021,17 +3103,17 @@ void ObjectTablePanel::OnCellLeftClick( wxGridEvent& ev )
int row = ev.GetRow();
int col = ev.GetCol();
ConfigOptionType type = coNone;
bool consumed = m_object_grid_table->OnCellLeftClick(row, col, type);
ConfigOptionType type = coNone;
bool consumed = m_object_grid_table->OnCellLeftClick(row, col, type);
if (consumed) {
//m_object_grid->ClearSelection();
//m_object_grid->SelectBlock(row, col-1, row, col-1, true);
return;
m_object_grid->ClearSelection();
m_object_grid->SelectBlock(row, col-1, row, col-1, true);
//return;
}
consumed = m_object_grid->OnCellLeftClick(ev, row, col, type);
if (!consumed)
ev.Skip();
m_object_grid->input_string = wxEmptyString;
ev.Skip();
//consumed = m_object_grid->OnCellLeftClick(ev, row, col, type);
//if (!consumed) ev.Skip();
}
void ObjectTablePanel::OnRowSize( wxGridSizeEvent& ev)
@ -3096,13 +3178,10 @@ void ObjectTablePanel::OnCellValueChanged( wxGridEvent& ev )
void ObjectTablePanel::OnRangeSelected( wxGridRangeSelectEvent& ev )
{
int left_col = ev.GetLeftCol();
int right_col = ev.GetRightCol();
int top_row = ev.GetTopRow();
int bottom_row = ev.GetBottomRow();
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format("cell from (%1%, %2%) to (%3%, %4%) selected") %top_row %left_col %bottom_row %right_col;
range_select_left_col = ev.GetLeftCol();
range_select_right_col = ev.GetRightCol();
range_select_top_row = ev.GetTopRow();
range_select_bottom_row = ev.GetBottomRow();
ev.Skip();
}
@ -3189,7 +3268,7 @@ ObjectTableDialog::ObjectTableDialog(wxWindow* parent, Plater* platerObj, Model
m_main_sizer->Add(m_line_top, 0, wxEXPAND, 0);
m_obj_panel = new ObjectTablePanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE, wxEmptyString, m_plater, m_model);
m_obj_panel->SetBackgroundColour(wxColour(0x00,0xAE,0x42));
m_obj_panel->SetBackgroundColour(*wxWHITE);
//m_top_sizer->Add(m_obj_panel, 1, wxALL | wxEXPAND, 5);
wxSize panel_size = m_obj_panel->get_init_size();
@ -3211,12 +3290,13 @@ ObjectTableDialog::ObjectTableDialog(wxWindow* parent, Plater* platerObj, Model
g_dialog_max_width = (panel_size.GetWidth() > g_max_size_from_parent.GetWidth())?g_max_size_from_parent.GetWidth():panel_size.GetWidth();
g_dialog_max_height = g_max_size_from_parent.GetHeight();
//g_dialog_max_height = (panel_size.GetHeight() > g_max_size_from_parent.GetHeight()) ? g_max_size_from_parent.GetHeight() : panel_size.GetHeight();
this->SetMaxSize(wxSize(g_dialog_max_width, g_dialog_max_height));
//this->SetMaxSize(wxSize(g_dialog_max_width, g_dialog_max_height));
//m_top_sizer->SetSizeHints(this);
//this->SetSizer(m_top_sizer);
//SetClientSize(m_panel->GetSize());
Bind(wxEVT_CLOSE_WINDOW, &ObjectTableDialog::OnClose, this);
Bind(wxEVT_SIZE, &ObjectTableDialog::OnSize, this);
Bind(wxEVT_CHAR_HOOK, &ObjectTableDialog::OnText, this);
//this->Layout();
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", created, this %1%, m_obj_panel %2%") %this % m_obj_panel;
@ -3283,19 +3363,22 @@ void ObjectTableDialog::OnClose(wxCloseEvent &evt)
#endif
}
void ObjectTableDialog::OnText(wxKeyEvent &evt)
{
if (evt.GetKeyCode() != WXK_ESCAPE) {
evt.Skip();
}
}
void ObjectTableDialog::OnSize(wxSizeEvent& event)
{
//SetSize(wxSize(-1, FromDIP(480)));
//SetMinSize(wxSize(-1, FromDIP(480)));
//SetMaxSize(wxSize(-1, FromDIP(480)));
//return;
//wxSize new_size = event.GetSize();
//if ((new_size.GetWidth() > g_dialog_max_width) || (new_size.GetHeight() > g_dialog_max_height)) {
// int width = (new_size.GetWidth() > g_dialog_max_width)?new_size.GetWidth():g_dialog_max_width;
// int height = (new_size.GetHeight() > g_dialog_max_height)?new_size.GetHeight():g_dialog_max_height;
// this->SetMaxSize(wxSize(width, height));
//}
//event.Skip();
wxSize new_size = event.GetSize();
if ((new_size.GetWidth() > g_dialog_max_width) || (new_size.GetHeight() > g_dialog_max_height)) {
int width = (new_size.GetWidth() > g_dialog_max_width) ? new_size.GetWidth() : g_dialog_max_width;
int height = (new_size.GetHeight() > g_dialog_max_height) ? new_size.GetHeight() : g_dialog_max_height;
this->SetMaxSize(wxSize(width, height));
}
event.Skip();
}
// ----------------------------------------------------------------------------
@ -3324,8 +3407,33 @@ void GridCellTextEditor::BeginEdit(int row, int col, wxGrid *grid)
ObjectGridTable::ObjectGridRow *grid_row = table->get_grid_row(row - 1);
auto val = table->GetValue(row, col);
Text()->GetTextCtrl()->SetValue(val);
Text()->SetFocus();
ObjectGrid* ogrid = dynamic_cast<ObjectGrid*>(grid);
if (!ogrid->input_string.empty()) {
Text()->GetTextCtrl()->SetValue(ogrid->input_string);
}
else {
Text()->GetTextCtrl()->SetValue(val);
}
Text()->SetFocus();
Text()->GetTextCtrl()->SetInsertionPointEnd();
m_control->Bind(wxEVT_TEXT_ENTER, [this, row, col, grid](wxCommandEvent &e) {
grid->HideCellEditControl();
grid->SaveEditControlValue();
e.Skip();
});
m_control->Bind(wxEVT_CHAR_HOOK, [this, row, col, grid](wxKeyEvent &e) {
if (e.GetKeyCode() == WXK_ESCAPE) {
grid->HideCellEditControl();
grid->SaveEditControlValue();
}
e.Skip();
});
}
bool GridCellTextEditor::EndEdit(int row, int col, const wxGrid *grid, const wxString &WXUNUSED(oldval), wxString *newval)

View file

@ -242,6 +242,7 @@ public:
}*/
bool OnCellLeftClick(wxGridEvent& event, int row, int col, ConfigOptionType type);
void OnRangeSelected(wxGridRangeSelectEvent& ev);
void OnColHeadLeftClick(wxGridEvent& event);
virtual void DrawColLabels( wxDC& dc, const wxArrayInt& cols );
@ -250,6 +251,9 @@ public:
//set ObjectGridTable and ObjectTablePanel as friend
friend class ObjectGridTable;
friend class ObjectTablePanel;
wxString input_string;
wxString m_cell_data;
protected:
//void OnSize( wxSizeEvent& );
void OnKeyDown( wxKeyEvent& );
@ -258,7 +262,6 @@ protected:
private:
wxDECLARE_EVENT_TABLE();
wxGridBlockCoords m_selected_block;
void paste_data( wxTextDataObject& text_data );
};
@ -519,8 +522,9 @@ public:
int m_icon_col_width{ 0 };
int m_icon_row_height{ 0 };
ObjectTablePanel* m_panel{ nullptr };
private:
ObjectTablePanel* m_panel{nullptr};
std::vector<ObjectGridRow*> m_grid_data;
std::vector<ObjectGridCol*> m_col_data;
bool m_data_valid{false};
@ -544,6 +548,12 @@ private:
//the main panel
class ObjectTablePanel : public wxPanel
{
public:
int range_select_left_col;
int range_select_right_col;
int range_select_top_row;
int range_select_bottom_row;
void OnCellLeftClick( wxGridEvent& );
void OnRowSize( wxGridSizeEvent& );
void OnColSize( wxGridSizeEvent& );
@ -628,6 +638,7 @@ public:
~ObjectTableDialog();
void Popup(int obj_idx = -1, int vol_idx = -1, wxPoint position = wxDefaultPosition);
void OnClose(wxCloseEvent &evt);
void OnText(wxKeyEvent &evt);
void OnSize(wxSizeEvent& event);
protected:

View file

@ -13,6 +13,14 @@ namespace GUI {
const float GLGizmoScale3D::Offset = 5.0f;
// get intersection of ray and plane
Vec3d GetIntersectionOfRayAndPlane(Vec3d ray_position, Vec3d ray_dir, Vec3d plane_position, Vec3d plane_normal)
{
double t = (plane_normal.dot(plane_position) - plane_normal.dot(ray_position)) / (plane_normal.dot(ray_dir));
Vec3d intersection = ray_position + t * ray_dir;
return intersection;
}
//BBS: GUI refactor: add obj manipulation
GLGizmoScale3D::GLGizmoScale3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id, GizmoObjectManipulation* obj_manipulation)
: GLGizmoBase(parent, icon_filename, sprite_id)
@ -95,6 +103,8 @@ void GLGizmoScale3D::on_start_dragging()
if (m_hover_id != -1)
{
m_starting.drag_position = m_grabbers[m_hover_id].center;
m_starting.plane_center = m_grabbers[4].center;
m_starting.plane_nromal = m_grabbers[5].center - m_grabbers[4].center;
m_starting.ctrl_down = wxGetKeyState(WXK_CONTROL);
m_starting.box = (m_starting.ctrl_down && (m_hover_id < 6)) ? m_box : m_parent.get_selection().get_bounding_box();
@ -303,19 +313,23 @@ double GLGizmoScale3D::calc_ratio(const UpdateData& data) const
{
double ratio = 0.0;
Vec3d pivot = (m_starting.ctrl_down && (m_hover_id < 6)) ? m_starting.pivots[m_hover_id] : m_starting.box.center();
Vec3d pivot = (m_starting.ctrl_down && (m_hover_id < 6)) ? m_starting.pivots[m_hover_id] : m_starting.plane_center;
Vec3d starting_vec = m_starting.drag_position - pivot;
double len_starting_vec = starting_vec.norm();
if (len_starting_vec != 0.0)
{
Vec3d mouse_dir = data.mouse_ray.unit_vector();
// finds the intersection of the mouse ray with the plane parallel to the camera viewport and passing throught the starting position
// use ray-plane intersection see i.e. https://en.wikipedia.org/wiki/Line%E2%80%93plane_intersection algebric form
// in our case plane normal and ray direction are the same (orthogonal view)
// when moving to perspective camera the negative z unit axis of the camera needs to be transformed in world space and used as plane normal
Vec3d inters = data.mouse_ray.a + (m_starting.drag_position - data.mouse_ray.a).dot(mouse_dir) / mouse_dir.squaredNorm() * mouse_dir;
// vector from the starting position to the found intersection
Vec3d plane_normal = m_starting.plane_nromal;
if (m_hover_id == 5) {
// get z-axis moving plane normal
Vec3d plane_vec = mouse_dir.cross(m_starting.plane_nromal);
plane_normal = plane_vec.cross(m_starting.plane_nromal);
}
// finds the intersection of the mouse ray with the plane that the drag point moves
// use ray-plane intersection see i.e. https://en.wikipedia.org/wiki/Line%E2%80%93plane_intersection
Vec3d inters = GetIntersectionOfRayAndPlane(data.mouse_ray.a, mouse_dir, m_starting.drag_position, plane_normal.normalized());
Vec3d inters_vec = inters - m_starting.drag_position;
// finds projection of the vector along the staring direction

View file

@ -19,6 +19,8 @@ class GLGizmoScale3D : public GLGizmoBase
{
Vec3d scale;
Vec3d drag_position;
Vec3d plane_center; // keep the relative center position for scale in the bottom plane
Vec3d plane_nromal; // keep the bottom plane
BoundingBoxf3 box;
Vec3d pivots[6];
bool ctrl_down;

View file

@ -824,12 +824,14 @@ void IMSlider::draw_colored_band(const ImRect& groove, const ImRect& slideable_r
//cover round corner
ImGui::RenderFrame(ImVec2(band_rc.Min.x, band_rc.Max.y - band_rc.GetWidth() * 0.5), band_rc.Max, clr, false);
};
//draw colored band
ImRect band_rect(main_band);
auto draw_main_band = [&main_band, this](const ImU32& clr) {
ImGui::RenderFrame(main_band.Min, main_band.Max, clr, false, main_band.GetWidth() * 0.5);
};
//draw main colored band
const int default_color_idx = m_mode == MultiAsSingle ? std::max<int>(m_only_extruder - 1, 0) : 0;
std::array<float, 4>rgba = decode_color_to_float_array(m_extruder_colors[default_color_idx]);
ImU32 band_clr = IM_COL32(rgba[0] * 255.0f, rgba[1] * 255.0f, rgba[2] * 255.0f, rgba[3] * 255.0f);
ImGui::RenderFrame(band_rect.Min, band_rect.Max, band_clr, false, band_rect.GetWidth() * 0.5);
draw_main_band(band_clr);
static float tick_pos;
std::set<TickCode>::const_iterator tick_it = m_ticks.ticks.begin();
@ -841,15 +843,17 @@ void IMSlider::draw_colored_band(const ImRect& groove, const ImRect& slideable_r
if (tick_it->type == ToolChange) {
if ((m_mode == SingleExtruder) || (m_mode == MultiAsSingle))
{
//TODO:band_rect width need to be ajusted
band_rect = ImRect(main_band.Min, ImVec2(main_band.Max.x, tick_pos));
ImRect band_rect = ImRect(main_band.Min, ImVec2(main_band.Max.x, tick_pos));
const std::string clr_str = m_mode == SingleExtruder ? tick_it->color : get_color_for_tool_change_tick(tick_it);
if (!clr_str.empty()) {
std::array<float, 4>rgba = decode_color_to_float_array(clr_str);
ImU32 band_clr = IM_COL32(rgba[0] * 255.0f, rgba[1] * 255.0f, rgba[2] * 255.0f, rgba[3] * 255.0f);
draw_band(band_clr, band_rect);
if (tick_it->tick == 0)
draw_main_band(band_clr);
else
draw_band(band_clr, band_rect);
}
}
}
@ -1255,7 +1259,15 @@ void IMSlider::render_menu()
ImGui::PushStyleVar(ImGuiStyleVar_::ImGuiStyleVar_ChildRounding, 4.0f * m_scale);
if (ImGui::BeginPopup("slider_menu_popup")) {
if(menu_item_with_icon(_u8L("Add Pause").c_str(), "")) { add_code_as_tick(PausePrint); }
if ((m_selection == ssLower && GetLowerValueD() == m_zero_layer_height) || (m_selection == ssHigher && GetHigherValueD() == m_zero_layer_height))
{
menu_item_with_icon(_u8L("Add Pause").c_str(), "", ImVec2(0, 0), 0, false, false);
}else
{
if (menu_item_with_icon(_u8L("Add Pause").c_str(), "")) {
add_code_as_tick(PausePrint);
}
}
//BBS render this menu item only when extruder_num > 1
if (extruder_num > 1) {
@ -1348,12 +1360,23 @@ std::string IMSlider::get_label(int tick, LabelType label_type)
}
char layer_height[64];
::sprintf(layer_height, "%.2f", m_values.empty() ? m_label_koef * value : m_values[value]);
m_values[value] == m_zero_layer_height ?
::sprintf(layer_height, "") :
::sprintf(layer_height, "%.2f", m_values.empty() ? m_label_koef * value : m_values[value]);
if (label_type == ltHeight) return std::string(layer_height);
if (label_type == ltHeightWithLayer) {
size_t layer_number = m_is_wipe_tower ? get_layer_number(value, label_type) + 1 : (m_values.empty() ? value : value + 1);
char buffer[64];
::sprintf(buffer, "%5s\n%5s", std::to_string(layer_number).c_str(), layer_height);
size_t layer_number;
if (m_values[GetMinValueD()] == m_zero_layer_height) {
layer_number = m_is_wipe_tower ? get_layer_number(value, label_type): (m_values.empty() ? value : value);
m_values[value] == m_zero_layer_height ?
::sprintf(buffer, "%5s", std::to_string(layer_number).c_str()) :
::sprintf(buffer, "%5s\n%5s", std::to_string(layer_number).c_str(), layer_height);
}
else {
layer_number = m_is_wipe_tower ? get_layer_number(value, label_type) + 1 : (m_values.empty() ? value : value + 1);
::sprintf(buffer, "%5s\n%5s", std::to_string(layer_number).c_str(), layer_height);
}
return std::string(buffer);
}
}

View file

@ -355,6 +355,7 @@ private:
long m_extra_style;
float m_label_koef{1.0};
float m_zero_layer_height = 0.0f;
std::vector<double> m_values;
TickCodeInfo m_ticks;
std::vector<double> m_layers_times;

View file

@ -1705,10 +1705,12 @@ void ImGuiWrapper::init_font(bool compress)
#endif
builder.BuildRanges(&ranges); // Build the final result (ordered ranges with all the unique characters submitted)
io.Fonts->Flags |= ImFontAtlasFlags_NoPowerOfTwoHeight;
ImFontConfig cfg = ImFontConfig();
cfg.OversampleH = cfg.OversampleV = 1;
//FIXME replace with io.Fonts->AddFontFromMemoryTTF(buf_decompressed_data, (int)buf_decompressed_size, m_font_size, nullptr, ranges.Data);
//https://github.com/ocornut/imgui/issues/220
ImFont* font = io.Fonts->AddFontFromFileTTF((Slic3r::resources_dir() + "/fonts/" + "HarmonyOS_Sans_SC_Regular.ttf").c_str(), m_font_size, nullptr, ranges.Data);
ImFont* font = io.Fonts->AddFontFromFileTTF((Slic3r::resources_dir() + "/fonts/" + "HarmonyOS_Sans_SC_Regular.ttf").c_str(), m_font_size, &cfg, io.Fonts->GetGlyphRangesChineseSimplifiedCommon());
if (font == nullptr) {
font = io.Fonts->AddFontDefault();
if (font == nullptr) {
@ -1716,10 +1718,7 @@ void ImGuiWrapper::init_font(bool compress)
}
}
ImFontConfig cfg = ImFontConfig();
cfg.OversampleH = 1;
bold_font = io.Fonts->AddFontFromFileTTF((Slic3r::resources_dir() + "/fonts/" + "HarmonyOS_Sans_SC_Bold.ttf").c_str(), m_font_size, &cfg);
bold_font = io.Fonts->AddFontFromFileTTF((Slic3r::resources_dir() + "/fonts/" + "HarmonyOS_Sans_SC_Bold.ttf").c_str(), m_font_size, &cfg, io.Fonts->GetGlyphRangesChineseSimplifiedCommon());
if (bold_font == nullptr) {
bold_font = io.Fonts->AddFontDefault();
if (bold_font == nullptr) { throw Slic3r::RuntimeError("ImGui: Could not load deafult font"); }

View file

@ -60,6 +60,9 @@ void ImageGrid::SetFileSystem(boost::shared_ptr<PrinterFileSystem> file_sys)
m_file_sys->Bind(EVT_THUMBNAIL, &ImageGrid::changedEvent, this);
m_file_sys->Bind(EVT_DOWNLOAD, &ImageGrid::changedEvent, this);
}
m_row_count = 0;
m_col_count = 1;
m_row_offset = 0;
UpdateFileSystem();
}
@ -109,12 +112,11 @@ void Slic3r::GUI::ImageGrid::Rescale()
{
UpdateFileSystem();
auto em = em_unit(this);
wxSize size1{256 * em / 10, 4 * em};
wxSize size1{384 * em / 10, 4 * em};
m_buttons_background = createAlphaBitmap(size1, *wxBLACK, 77, 77);
m_buttons_background_checked = createAlphaBitmap(size1, wxColor("#FF2002"), 77, 77);
//wxSize size2{128 * m_buttonBackgroundColor.count() * em_unit(this) / 10, 4 * em_unit(this)};
//m_button_background = createAlphaBitmap(size2, *wxBLACK, 77, 77);
wxSize size_p{8 * em, 8 * em};
m_progress_background = createCircleBitmap(size_p, em, m_background_progress, wxTransparentColour, *wxWHITE);
}
void Slic3r::GUI::ImageGrid::Select(size_t index)
@ -131,6 +133,7 @@ void Slic3r::GUI::ImageGrid::Select(size_t index)
m_row_offset = index / m_col_count * 4;
if (m_row_offset >= m_row_count)
m_row_offset = m_row_count == 0 ? 0 : m_row_count - 1;
Refresh();
}
void Slic3r::GUI::ImageGrid::DoAction(size_t index, int action)
@ -168,8 +171,8 @@ void Slic3r::GUI::ImageGrid::UpdateFileSystem()
if (!m_file_sys) return;
wxSize mask_size{0, 60};
if (m_file_sys->GetGroupMode() == PrinterFileSystem::G_NONE) {
m_image_size.Set(256, 144);
m_cell_size.Set(272, 160);
m_image_size.Set(384, 216);
m_cell_size.Set(396, 228);
}
else {
m_image_size.Set(480, 270);
@ -474,48 +477,33 @@ void ImageGrid::render(wxDC& dc)
pt + wxPoint{10, m_image_size.GetHeight() - m_checked_icon.GetBmpHeight() - 10});
// can' handle alpha
// dc.GradientFillLinear({pt.x, pt.y, m_image_size.GetWidth(), 60}, wxColour(0x6F, 0x6F, 0x6F, 0x99), wxColour(0x6F, 0x6F, 0x6F, 0), wxBOTTOM);
if (m_file_sys->GetGroupMode() == PrinterFileSystem::G_NONE) {
else if (m_file_sys->GetGroupMode() == PrinterFileSystem::G_NONE) {
wxString nonHoverText;
wxString secondAction = _L("Download");
int states = 0;
// Draw download progress
if (file.IsDownload()) {
if (file.progress == -1) {
secondAction = _L("Cancel");
dc.DrawText(_L("Waiting"), pt + wxPoint{24, m_image_size.GetHeight() - 64});
nonHoverText = _L("Download waiting...");
} else if (file.progress < 0) {
secondAction = _L("Retry");
dc.DrawText(_L("Failed"), pt + wxPoint{24, m_image_size.GetHeight() - 64});
nonHoverText = _L("Download failed");
states = StateColor::Checked;
} else if (file.progress >= 100) {
secondAction = _L("Open");
dc.DrawText(_L("Finished"), pt + wxPoint{24, m_image_size.GetHeight() - 64});
nonHoverText = _L("Download finished");
} else {
secondAction = _L("Cancel");
if (file.progress != m_background_progress) {
auto em = em_unit(this);
wxSize size_p{8 * em, 8 * em};
m_background_progress = file.progress;
m_progress_background = createCircleBitmap(size_p, em, m_background_progress, wxTransparentColour, *wxWHITE);
}
auto pos = (m_image_size - m_progress_background.GetSize()) / 2;
dc.DrawBitmap(m_progress_background, pt + wxPoint{pos.x, pos.y});
// draw progress text
auto p = wxString::Format("%d", m_background_progress);
dc.SetFont(Label::sysFont(30));
wxSize s1 = dc.GetTextExtent(p);
dc.SetFont(Label::sysFont(20));
wxSize s2 = dc.GetTextExtent(L"%");
wxRect rt = wxRect(0, 0, s1.x + s2.x, s1.y).CenterIn(wxRect(pt, m_image_size));
dc.SetTextForeground(*wxWHITE);
dc.SetFont(Label::sysFont(30));
dc.DrawText(p, rt.GetTopLeft());
dc.SetFont(Label::sysFont(20));
dc.DrawText(L"%", rt.GetTopLeft() + wxSize{s1.x, s1.y - s2.y});
dc.SetFont(GetFont());
nonHoverText = wxString::Format(_L("Downloading %d%%..."), file.progress);
}
}
// Draw buttons on hovered item
wxRect rect{pt.x, pt.y + m_image_size.y - m_buttons_background.GetHeight(), m_image_size.GetWidth(), m_buttons_background.GetHeight()};
if (hit_image == index) {
wxRect rect{pt.x, pt.y + m_image_size.y - m_buttons_background.GetHeight(), m_image_size.GetWidth(), m_buttons_background.GetHeight()};
renderButtons(dc, {_L("Delete"), (wxChar const*)secondAction, nullptr}, rect, m_hit_type == HIT_ACTION ? m_hit_item & 1 : -1);
renderButtons(dc, {_L("Delete"), (wxChar const *) secondAction, nullptr}, rect, m_hit_type == HIT_ACTION ? m_hit_item & 1 : -1, states);
} else if (!nonHoverText.IsEmpty()) {
renderButtons(dc, {(wxChar const *) nonHoverText, nullptr}, rect, -1, states);
}
} else {
auto date = wxDateTime((time_t) file.time).Format(_L(formats[m_file_sys->GetGroupMode()]));
@ -558,11 +546,13 @@ void ImageGrid::render(wxDC& dc)
}
}
void Slic3r::GUI::ImageGrid::renderButtons(wxDC &dc, wxStringList const &texts, wxRect const &rect2, size_t hit)
void Slic3r::GUI::ImageGrid::renderButtons(wxDC &dc, wxStringList const &texts, wxRect const &rect2, size_t hit, int states)
{
wxMemoryDC mdc(m_buttons_background);
// Draw background
dc.Blit(rect2.GetTopLeft(), rect2.GetSize(), &mdc, {0, 0});
{
wxMemoryDC mdc(states & StateColor::Checked ? m_buttons_background_checked : m_buttons_background);
dc.Blit(rect2.GetTopLeft(), rect2.GetSize(), &mdc, {0, 0});
}
// Draw buttons
wxRect rect(rect2);
rect.SetWidth(rect.GetWidth() / texts.size());
@ -570,7 +560,7 @@ void Slic3r::GUI::ImageGrid::renderButtons(wxDC &dc, wxStringList const &texts,
dc.SetFont(Label::Body_14);
//mdc.SelectObject(m_button_background);
for (size_t i = 0; i < texts.size(); ++i) {
int states = hit == i ? state : 0;
int states2 = hit == i ? state : 0;
// Draw button background
rect.Deflate(10, 5);
//dc.Blit(rect.GetTopLeft(), rect.GetSize(), &mdc, {m_buttonBackgroundColor.colorIndexForStates(states) * 128, 0});
@ -578,7 +568,7 @@ void Slic3r::GUI::ImageGrid::renderButtons(wxDC &dc, wxStringList const &texts,
// Draw button splitter
if (i > 0) dc.DrawLine(rect.GetLeftTop(), rect.GetLeftBottom());
// Draw button text
renderText(dc, texts[i], rect, states);
renderText(dc, texts[i], rect, states | states2);
rect.Inflate(10, 5);
rect.Offset(rect.GetWidth(), 0);
}

View file

@ -76,9 +76,9 @@ protected:
void render(wxDC &dc);
void renderButtons(wxDC &dc, wxStringList const &texts, wxRect const &rect, size_t hit);
void renderButtons(wxDC &dc, wxStringList const &texts, wxRect const &rect, size_t hit, int states);
void renderText(wxDC &dc, wxString const & text, wxRect const & rect, int state);
void renderText(wxDC &dc, wxString const & text, wxRect const & rect, int states);
// some useful events
void mouseMoved(wxMouseEvent& event);
@ -108,10 +108,9 @@ private:
wxTimer m_timer;
wxBitmap m_mask;
wxBitmap m_buttons_background;
wxBitmap m_buttons_background;
wxBitmap m_buttons_background_checked;
// wxBitmap m_button_background;
wxBitmap m_progress_background;
int m_background_progress = 0;
bool m_selecting = false;

View file

@ -197,6 +197,9 @@ void KBShortcutsDialog::fill_shortcuts()
m_full_shortcuts.push_back({{_L("Global shortcuts"), ""}, global_shortcuts});
Shortcuts plater_shortcuts = {
{ L("Left mouse button"), L("Rotate View") },
{ L("Right mouse button"), L("Pan View") },
{ L("Mouse wheel"), L("Zoom View") },
{ "A", L("Arrange all objects") },
{ "Shift+A", L("Arrange objects on selected plates") },

View file

@ -85,19 +85,18 @@ class BambuStudioTaskBarIcon : public wxTaskBarIcon
{
public:
BambuStudioTaskBarIcon(wxTaskBarIconType iconType = wxTBI_DEFAULT_TYPE) : wxTaskBarIcon(iconType) {}
//wxMenu *CreatePopupMenu() override {
//wxMenu *menu = new wxMenu;
//BBS do not support multi instances in mac
//if(wxGetApp().app_config->get("single_instance") == "0") {
// // Only allow opening a new PrusaSlicer instance on OSX if "single_instance" is disabled,
// // as starting new instances would interfere with the locking mechanism of "single_instance" support.
// append_menu_item(menu, wxID_ANY, _L("Open new instance"), _L("Open a new PrusaSlicer instance"),
// [](wxCommandEvent&) { start_new_slicer(); }, "", nullptr);
wxMenu *CreatePopupMenu() override {
wxMenu *menu = new wxMenu;
//if (wxGetApp().app_config->get("single_instance") == "false") {
// Only allow opening a new PrusaSlicer instance on OSX if "single_instance" is disabled,
// as starting new instances would interfere with the locking mechanism of "single_instance" support.
append_menu_item(menu, wxID_ANY, _L("New Window"), _L("Open a new window"),
[](wxCommandEvent&) { start_new_slicer(); }, "", nullptr);
//}
//append_menu_item(menu, wxID_ANY, _L("G-code Viewer") + dots, _L("Open G-code Viewer"),
// [](wxCommandEvent&) { start_new_gcodeviewer_open_file(); }, "", nullptr);
//return menu;
//}
// append_menu_item(menu, wxID_ANY, _L("G-code Viewer") + dots, _L("Open G-code Viewer"),
// [](wxCommandEvent&) { start_new_gcodeviewer_open_file(); }, "", nullptr);
return menu;
}
};
/*class GCodeViewerTaskBarIcon : public wxTaskBarIcon
{
@ -1671,7 +1670,7 @@ static wxMenu* generate_help_menu()
// Check New Version
append_menu_item(helpMenu, wxID_ANY, _L("Check for Update"), _L("Check for Update"),
[](wxCommandEvent&) {
wxGetApp().check_new_version(true);
wxGetApp().check_new_version(true, 1);
}, "", nullptr, []() {
return true;
});
@ -1725,6 +1724,12 @@ void MainFrame::init_menubar_as_editor()
// File menu
wxMenu* fileMenu = new wxMenu;
{
#ifdef __APPLE__
// New Window
append_menu_item(fileMenu, wxID_ANY, _L("New Window"), _L("Start a new window"),
[](wxCommandEvent&) { start_new_slicer(); }, "", nullptr,
[]{ return true; }, this);
#endif
// New Project
append_menu_item(fileMenu, wxID_ANY, _L("New Project") + "\tCtrl+N", _L("Start a new project"),
[this](wxCommandEvent&) { if (m_plater) m_plater->new_project(); }, "", nullptr,
@ -1980,6 +1985,12 @@ void MainFrame::init_menubar_as_editor()
viewMenu->Check(wxID_CAMERA_PERSPECTIVE + camera_id_base, true);
else
viewMenu->Check(wxID_CAMERA_ORTHOGONAL + camera_id_base, true);
viewMenu->AppendSeparator();
append_menu_check_item(viewMenu, wxID_ANY, _L("Show &Labels"), _L("Show object labels in 3D scene"),
[this](wxCommandEvent&) { m_plater->show_view3D_labels(!m_plater->are_view3D_labels_shown()); }, this,
[this]() { return m_plater->is_view3D_shown(); }, [this]() { return m_plater->are_view3D_labels_shown(); }, this);
//viewMenu->AppendSeparator();
////BBS orthogonal view
//append_menu_check_item(viewMenu, wxID_ANY, _L("Show Edges(TODO)"), _L("Show Edges"),

View file

@ -31,6 +31,7 @@ MediaFilePanel::MediaFilePanel(wxWindow * parent)
m_button_year = new ::Button(m_time_panel, _L("Year"), "", wxBORDER_NONE);
m_button_month = new ::Button(m_time_panel, _L("Month"), "", wxBORDER_NONE);
m_button_all = new ::Button(m_time_panel, _L("All Files"), "", wxBORDER_NONE);
m_button_all->SetFont(Label::Head_14); // sync with m_last_mode
for (auto b : {m_button_year, m_button_month, m_button_all}) {
b->SetBackgroundColor(StateColor());
b->SetTextColor(StateColor(
@ -67,10 +68,13 @@ MediaFilePanel::MediaFilePanel(wxWindow * parent)
m_manage_panel = new ::StaticBox(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
m_manage_panel->SetBackgroundColor(StateColor());
m_button_delete = new ::Button(m_manage_panel, _L("Delete"));
m_button_delete->SetBackgroundColor(StateColor());
m_button_delete->SetCanFocus(false);
m_button_download = new ::Button(m_manage_panel, _L("Download"));
m_button_download->SetBackgroundColor(StateColor());
m_button_download->SetCanFocus(false);
m_button_management = new ::Button(m_manage_panel, _L("Management"));
m_button_management->SetBackgroundColor(StateColor());
wxBoxSizer *manage_sizer = new wxBoxSizer(wxHORIZONTAL);
manage_sizer->AddStretchSpacer(1);
@ -243,9 +247,11 @@ void MediaFilePanel::modeChanged(wxCommandEvent& e1)
::Button* buttons[] = {m_button_all, m_button_month, m_button_year};
wxCommandEvent e(wxEVT_CHECKBOX);
auto b = buttons[m_last_mode];
b->SetFont(Label::Body_14);
e.SetEventObject(b);
b->GetEventHandler()->ProcessEvent(e);
b = buttons[mode];
b->SetFont(Label::Head_14);
e.SetEventObject(b);
b->GetEventHandler()->ProcessEvent(e);
m_last_mode = mode;

View file

@ -99,8 +99,9 @@ void MediaPlayCtrl::Play()
NetworkAgent* agent = wxGetApp().getAgent();
if (agent) {
agent->get_camera_url(m_machine, [this](std::string url) {
agent->get_camera_url(m_machine, [this, m = m_machine](std::string url) {
BOOST_LOG_TRIVIAL(info) << "camera_url: " << url;
if (m != m_machine) return;
CallAfter([this, url] {
m_url = url;
if (m_last_state == MEDIASTATE_INITIALIZING) {
@ -135,6 +136,8 @@ void MediaPlayCtrl::Stop()
m_cond.notify_all();
m_last_state = MEDIASTATE_IDLE;
SetStatus(_L("Stopped."));
if (m_failed_code >= 100) // not keep retry on local error
m_next_retry = wxDateTime();
}
++m_failed_retry;
if (m_next_retry.IsValid())

View file

@ -198,14 +198,16 @@ MonitorPanel::~MonitorPanel()
});
//m_status_add_machine_panel = new AddMachinePanel(m_tabpanel);
m_status_info_panel = new StatusPanel(m_tabpanel);
m_status_info_panel = new StatusPanel(m_tabpanel);
m_tabpanel->AddPage(m_status_info_panel, _L("Status"), "", true);
#if !BBL_RELEASE_TO_PUBLIC
m_media_file_panel = new MediaFilePanel(m_tabpanel);
m_tabpanel->AddPage(m_media_file_panel, _L("Media"), "", false);
m_upgrade_panel = new UpgradePanel(m_tabpanel);
m_tabpanel->AddPage(m_upgrade_panel, _L("Update"), "", false);
#endif
m_hms_panel = new HMSPanel(m_tabpanel);
m_tabpanel->AddPage(m_hms_panel, _L("HMS"),"", false);
@ -225,8 +227,10 @@ void MonitorPanel::set_default()
/* reset side tool*/
//m_bitmap_wifi_signal->SetBitmap(wxNullBitmap);
#if !BBL_RELEASE_TO_PUBLIC
/* reset time lapse panel */
m_media_file_panel->SetMachineObject(nullptr);
#endif
wxGetApp().sidebar().load_ams_list({});
}
@ -255,8 +259,10 @@ void MonitorPanel::msw_rescale()
m_tabpanel->Rescale();
//m_status_add_machine_panel->msw_rescale();
m_status_info_panel->msw_rescale();
#if !BBL_RELEASE_TO_PUBLIC
m_media_file_panel->Rescale();
m_upgrade_panel->msw_rescale();
#endif
m_hms_panel->msw_rescale();
m_connection_info->SetCornerRadius(0);
@ -399,11 +405,16 @@ void MonitorPanel::update_all()
}
m_status_info_panel->obj = obj;
#if !BBL_RELEASE_TO_PUBLIC
m_upgrade_panel->update(obj);
#endif
m_status_info_panel->m_media_play_ctrl->SetMachineObject(obj);
#if !BBL_RELEASE_TO_PUBLIC
m_media_file_panel->SetMachineObject(obj);
#endif
update_status(obj);
if (!obj) {
@ -436,9 +447,11 @@ void MonitorPanel::update_all()
if (m_hms_panel->IsShown()) {
m_hms_panel->update(obj);
}
#if !BBL_RELEASE_TO_PUBLIC
if (m_upgrade_panel->IsShown()) {
m_upgrade_panel->update(obj);
}
#endif
}
bool MonitorPanel::Show(bool show)
@ -505,6 +518,9 @@ void MonitorPanel::show_status(int status)
m_connection_info->Show();
m_connection_info->SetBackgroundColor(wxColour(255, 111, 0));
m_connection_info->SetBorderColor(wxColour(255, 111, 0));
#if !BBL_RELEASE_TO_PUBLIC
m_upgrade_panel->update(nullptr);
#endif
} else if ((status & (int) MonitorStatus::MONITOR_NORMAL) != 0) {
m_connection_info->Hide();
} else if ((status & (int) MonitorStatus::MONITOR_CONNECTING) != 0) {
@ -522,6 +538,9 @@ void MonitorPanel::show_status(int status)
m_status_info_panel->show_status(status);
m_tabpanel->Refresh();
m_tabpanel->Layout();
#if !BBL_RELEASE_TO_PUBLIC
m_upgrade_panel->update(nullptr);
#endif
} else if (((status & (int)MonitorStatus::MONITOR_NORMAL) != 0)
|| ((status & (int)MonitorStatus::MONITOR_DISCONNECTED) != 0)
|| ((status & (int) MonitorStatus::MONITOR_DISCONNECTED_SERVER) != 0)

View file

@ -232,11 +232,10 @@ ParamsPanel::ParamsPanel( wxWindow* parent, wxWindowID id, const wxPoint& pos, c
m_compare_btn = new ScalableButton(m_top_panel, wxID_ANY, "compare", wxEmptyString, wxDefaultSize, wxDefaultPosition, wxBU_EXACTFIT | wxNO_BORDER, true);
m_compare_btn->SetToolTip(_L("Compare presets"));
m_compare_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent e) { wxGetApp().mainframe->diff_dialog.show(); }));
#if !BBL_RELEASE_TO_PUBLIC
m_setting_btn = new ScalableButton(m_top_panel, wxID_ANY, "table", wxEmptyString, wxDefaultSize, wxDefaultPosition, wxBU_EXACTFIT | wxNO_BORDER, true);
m_setting_btn->SetToolTip(_L("View all object's settings"));
m_setting_btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent &) { wxGetApp().plater()->PopupObjectTable(-1, -1, {0, 0}); });
#endif
m_highlighter.set_timer_owner(this, 0);
this->Bind(wxEVT_TIMER, [this](wxTimerEvent &)
@ -331,10 +330,9 @@ void ParamsPanel::create_layout()
m_mode_sizer->Add( m_title_view, 0, wxALIGN_CENTER );
m_mode_sizer->AddSpacer(FromDIP(9));
m_mode_sizer->Add( m_mode_view, 0, wxALIGN_CENTER );
#if !BBL_RELEASE_TO_PUBLIC
m_mode_sizer->AddSpacer(FromDIP(16));
m_mode_sizer->Add( m_setting_btn, 0, wxALIGN_CENTER );
#endif
m_mode_sizer->AddSpacer(FromDIP(16));
m_mode_sizer->Add( m_compare_btn, 0, wxALIGN_CENTER );
@ -591,9 +589,7 @@ void ParamsPanel::update_mode()
void ParamsPanel::msw_rescale()
{
if (m_process_icon) m_process_icon->msw_rescale();
#if !BBL_RELEASE_TO_PUBLIC
if (m_setting_btn) m_setting_btn->msw_rescale();
#endif
if (m_search_btn) m_search_btn->msw_rescale();
if (m_compare_btn) m_compare_btn->msw_rescale();
m_left_sizer->SetMinSize(wxSize(40 * em_unit(this), -1));

View file

@ -1104,8 +1104,8 @@ Vec3d PartPlate::estimate_wipe_tower_size(const double w, const double wipe_volu
wipe_tower_size(2) = max_height;
const DynamicPrintConfig &dconfig = wxGetApp().preset_bundle->prints.get_edited_preset().config;
const ConfigOption* option = dconfig.option("timelapse_no_toolhead");
bool timelapse_enabled = option ? option->getBool() : false;
auto timelapse_type = dconfig.option<ConfigOptionEnum<TimelapseType>>("timelapse_type");
bool timelapse_enabled = timelapse_type ? (timelapse_type->value == TimelapseType::tlSmooth) : false;
double depth = wipe_volume * (plate_extruders.size() - 1) / (layer_height * w);
if (timelapse_enabled || depth > EPSILON) {

View file

@ -534,6 +534,24 @@ Sidebar::Sidebar(Plater *parent)
m_bed_type_list->AppendString(_L(item.first));
}
bed_type_title->Bind(wxEVT_ENTER_WINDOW, [bed_type_title, this](wxMouseEvent &e) {
e.Skip();
auto font = bed_type_title->GetFont();
font.SetUnderlined(true);
bed_type_title->SetFont(font);
SetCursor(wxCURSOR_HAND);
});
bed_type_title->Bind(wxEVT_LEAVE_WINDOW, [bed_type_title, this](wxMouseEvent &e) {
e.Skip();
auto font = bed_type_title->GetFont();
font.SetUnderlined(false);
bed_type_title->SetFont(font);
SetCursor(wxCURSOR_ARROW);
});
bed_type_title->Bind(wxEVT_LEFT_UP, [bed_type_title, this](wxMouseEvent &e) {
wxLaunchDefaultBrowser("https://wiki.bambulab.com/en/x1/manual/compatibility-and-parameter-settings-of-filaments");
});
m_bed_type_list->Select(0);
bed_type_sizer->Add(bed_type_title, 0, wxLEFT | wxRIGHT | wxALIGN_CENTER_VERTICAL, FromDIP(10));
bed_type_sizer->Add(m_bed_type_list, 1, wxLEFT | wxRIGHT | wxEXPAND, FromDIP(10));
@ -5307,9 +5325,9 @@ void Plater::priv::on_process_completed(SlicingProcessCompletedEvent &evt)
void Plater::priv::on_action_add(SimpleEvent&)
{
if (q != nullptr) {
//q->add_model();
q->add_model();
//BBS open file in toolbar add
q->add_file();
//q->add_file();
}
}

View file

@ -540,7 +540,10 @@ void PrinterFileSystem::SendChangedEvent(wxEventType type, size_t index, std::st
if (!str.empty())
event.SetString(wxString::FromUTF8(str.c_str()));
event.SetExtraLong(extra);
wxPostEvent(this, event);
if (wxThread::IsMain())
ProcessEventLocally(event);
else
wxPostEvent(this, event);
}
void PrinterFileSystem::DumpLog(Bambu_Session *session, int level, Bambu_Message const *msg)
@ -743,7 +746,7 @@ void PrinterFileSystem::Reconnect(boost::unique_lock<boost::mutex> &l, int resul
std::string url = m_messages.front();
m_messages.clear();
if (url.empty()) {
m_last_error = -100;
m_last_error = 1;
} else {
l.unlock();
m_status = Status::Connecting;

View file

@ -0,0 +1,186 @@
#include "RecenterDialog.hpp"
#include <slic3r/GUI/I18N.hpp>
#include <wx/dcgraph.h>
#include <wx/dcmemory.h>
#include <slic3r/GUI/Widgets/Label.hpp>
#define BORDER FromDIP(25)
#define DRAW_PANEL_SIZE wxSize(FromDIP(475), FromDIP(100))
const wxColour text_color(107, 107, 107);
wxString hint1 = _L("Please home all axes (click ");
wxString hint2 = _L(") to locate the toolhead's position. This prevents device moving beyond the printable boundary and causing equipment wear.");
namespace Slic3r { namespace GUI {
RecenterDialog::RecenterDialog(wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style)
: DPIDialog(parent, id, _L("Confirm"), pos, size, style)
{
std::string icon_path = (boost::format("%1%/images/BambuStudioTitle.ico") % resources_dir()).str();
SetIcon(wxIcon(encode_path(icon_path.c_str()), wxBITMAP_TYPE_ICO));
init_bitmap();
auto* main_sizer = new wxBoxSizer(wxVERTICAL);
auto* button_sizer = new wxBoxSizer(wxHORIZONTAL);
wxPanel* m_line_top = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(-1, 1), wxTAB_TRAVERSAL);
m_line_top->SetBackgroundColour(wxColour(166, 169, 170));
m_button_confirm = new Button(this, _L("Go Home"));
m_button_confirm->SetFont(Label::Body_14);
m_button_confirm->SetMinSize(wxSize(-1, FromDIP(24)));
m_button_confirm->SetCornerRadius(FromDIP(12));
StateColor confirm_btn_bg(std::pair<wxColour, int>(wxColour(61, 203, 115), StateColor::Hovered),
std::pair<wxColour, int>(wxColour(0, 174, 66), StateColor::Normal));
m_button_confirm->SetBackgroundColor(confirm_btn_bg);
m_button_confirm->SetBorderColor(wxColour(0, 174, 66));
m_button_confirm->SetTextColor(*wxWHITE);
m_button_close = new Button(this, _L("Close"));
m_button_close->SetFont(Label::Body_14);
m_button_close->SetMinSize(wxSize(-1, FromDIP(24)));
m_button_close->SetCornerRadius(FromDIP(12));
StateColor close_btn_bg(std::pair<wxColour, int>(wxColour(206, 206, 206), StateColor::Hovered),
std::pair<wxColour, int>(*wxWHITE, StateColor::Normal));
m_button_close->SetBackgroundColor(close_btn_bg);
m_button_close->SetBorderColor(wxColour(38, 46, 48));
m_button_close->SetTextColor(wxColour(38, 46, 48));
button_sizer->AddStretchSpacer();
button_sizer->Add(m_button_confirm);
button_sizer->AddSpacer(FromDIP(20));
button_sizer->Add(m_button_close);
main_sizer->Add(m_line_top, 0, wxEXPAND, 0);
main_sizer->AddSpacer(DRAW_PANEL_SIZE.y);
main_sizer->Add(button_sizer, 0, wxBOTTOM | wxRIGHT | wxEXPAND, BORDER);
SetSizer(main_sizer);
CenterOnParent();
this->SetSize(wxSize(DRAW_PANEL_SIZE.x, -1));
this->SetMinSize(wxSize(DRAW_PANEL_SIZE.x, -1));
Layout();
Fit();
this->Bind(wxEVT_PAINT, &RecenterDialog::OnPaint, this);
m_button_confirm->Bind(wxEVT_BUTTON, &RecenterDialog::on_button_confirm, this);
m_button_close->Bind(wxEVT_BUTTON, &RecenterDialog::on_button_close, this);
}
RecenterDialog::~RecenterDialog() {}
void RecenterDialog::init_bitmap() {
m_home_bmp = ScalableBitmap(this, "monitor_axis_home_icon", 24);
}
void RecenterDialog::OnPaint(wxPaintEvent& event){
wxPaintDC dc(this);
render(dc);
}
void RecenterDialog::render(wxDC& dc) {
wxSize size = GetSize();
dc.SetFont(Label::Body_14);
dc.SetTextForeground(text_color);
wxPoint pos_start = wxPoint(BORDER, BORDER);
wxSize hint1_size = dc.GetTextExtent(hint1);
wxPoint pos_hint1 = pos_start;
pos_hint1.y += (m_home_bmp.GetBmpWidth() - hint1_size.y) / 2;
dc.DrawText(hint1, pos_hint1);
wxPoint pos_bmp = pos_start;
pos_bmp.x += hint1_size.x;
dc.DrawBitmap(m_home_bmp.bmp(), pos_bmp);
wxSize hint2_size = dc.GetTextExtent(hint2);
wxPoint pos_hint2 = pos_hint1;
pos_hint2.x = pos_hint2.x + hint1_size.x + m_home_bmp.GetBmpWidth();
if (hint2_size.x + pos_hint2.x + BORDER > DRAW_PANEL_SIZE.x) {
bool is_ch = false;
if (hint2[0] > 0x80 && hint2[1] > 0x80)
is_ch = true;
wxString fisrt_line;
wxString remaining_line;
wxString count_txt;
int new_line_pos = 0;
for (int i = 0; i < hint2.length(); i++) {
count_txt += hint2[i];
auto text_size = dc.GetTextExtent(count_txt);
if (text_size.x + pos_hint2.x + BORDER < DRAW_PANEL_SIZE.x)
{
if (hint2[i] == ' ' || hint2[i] == '\n')
new_line_pos = i;
}
else {
if (!is_ch) {
fisrt_line = hint2.SubString(0, new_line_pos);
remaining_line = hint2.SubString(new_line_pos + 1, hint2.length());
break;
}
else {
fisrt_line = hint2.SubString(0, i);
remaining_line = hint2.SubString(i, hint2.length());
break;
}
count_txt = "";
}
}
dc.DrawText(fisrt_line, pos_hint2);
count_txt = "";
new_line_pos = 0;
for (int i = 0; i < remaining_line.length(); i++) {
count_txt += remaining_line[i];
auto text_size = dc.GetTextExtent(count_txt);
if (text_size.x + BORDER + BORDER < DRAW_PANEL_SIZE.x)
{
if (remaining_line[i] == ' ' || remaining_line[i] == '\n')
new_line_pos = i;
}
else {
if (!is_ch){
remaining_line[new_line_pos] = '\n';
}
else {
remaining_line.insert(i, '\n');
}
count_txt = "";
}
}
wxPoint pos_txt = pos_hint1;
pos_txt.y += dc.GetCharHeight();
dc.DrawText(remaining_line, pos_txt);
}
else
dc.DrawText(hint2, pos_hint2);
}
void RecenterDialog::on_button_confirm(wxCommandEvent& event) {
if (this->IsModal())
this->EndModal(wxID_OK);
else
this->Close();
}
void RecenterDialog::on_button_close(wxCommandEvent& event) {
this->Close();
}
void RecenterDialog::on_dpi_changed(const wxRect& suggested_rect) {
init_bitmap();
m_button_confirm->SetMinSize(wxSize(-1, FromDIP(24)));
m_button_confirm->SetCornerRadius(FromDIP(12));
m_button_close->SetMinSize(wxSize(-1, FromDIP(24)));
m_button_close->SetCornerRadius(FromDIP(12));
Layout();
}
}} // namespace Slic3r::GUI

View file

@ -0,0 +1,38 @@
#ifndef slic3r_GUI_RecenterDialog_hpp_
#define slic3r_GUI_RecenterDialog_hpp_
#include "GUI_Utils.hpp"
#include <wx/statbmp.h>
#include "Widgets/Button.hpp"
#include <wx/stattext.h>
namespace Slic3r { namespace GUI {
class RecenterDialog : public DPIDialog
{
private:
wxStaticText* m_staticText_hint;
Button* m_button_confirm;
Button* m_button_close;
wxStaticBitmap* m_bitmap_home;
ScalableBitmap m_home_bmp;
void init_bitmap();
void OnPaint(wxPaintEvent& event);
void render(wxDC& dc);
void on_button_confirm(wxCommandEvent& event);
void on_button_close(wxCommandEvent& event);
void on_dpi_changed(const wxRect& suggested_rect) override;
public:
RecenterDialog(wxWindow* parent,
wxWindowID id = wxID_ANY,
const wxString& title = wxEmptyString,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxCLOSE_BOX | wxCAPTION);
~RecenterDialog();
};
}} // namespace Slic3r::GUI
#endif

View file

@ -90,6 +90,10 @@ void ReleaseNoteDialog::update_release_note(wxString release_note, std::string v
m_scrollwindw_release_note->Layout();
}
void UpdateVersionDialog::alter_choice(wxCommandEvent& event)
{
wxGetApp().set_skip_version(m_remind_choice->GetValue());
}
UpdateVersionDialog::UpdateVersionDialog(wxWindow *parent)
: DPIDialog(parent, wxID_ANY, _L("New version of Bambu Studio"), wxDefaultPosition, wxDefaultSize, wxCAPTION | wxCLOSE_BOX)
@ -130,30 +134,33 @@ UpdateVersionDialog::UpdateVersionDialog(wxWindow *parent)
m_scrollwindw_release_note->SetBackgroundColour(wxColour(0xF8, 0xF8, 0xF8));
m_scrollwindw_release_note->SetMaxSize(wxSize(FromDIP(560), FromDIP(430)));
m_remind_choice = new wxCheckBox( this, wxID_ANY, _L("Don't remind me of this version again"), wxDefaultPosition, wxDefaultSize, 0 );
m_remind_choice->SetValue(false);
m_remind_choice->Bind(wxEVT_COMMAND_CHECKBOX_CLICKED, &UpdateVersionDialog::alter_choice,this);
auto sizer_button = new wxBoxSizer(wxHORIZONTAL);
StateColor btn_bg_green(std::pair<wxColour, int>(wxColour(27, 136, 68), StateColor::Pressed), std::pair<wxColour, int>(wxColour(61, 203, 115), StateColor::Hovered),
std::pair<wxColour, int>(AMS_CONTROL_BRAND_COLOUR, StateColor::Normal));
StateColor btn_bg_white(std::pair<wxColour, int>(wxColour(206, 206, 206), StateColor::Pressed), std::pair<wxColour, int>(wxColour(238, 238, 238), StateColor::Hovered),
std::pair<wxColour, int>(*wxWHITE, StateColor::Normal));
auto m_butto_ok = new Button(this, _L("OK"));
m_butto_ok->SetBackgroundColor(btn_bg_green);
m_butto_ok->SetBorderColor(*wxWHITE);
m_butto_ok->SetTextColor(*wxWHITE);
m_butto_ok->SetFont(Label::Body_12);
m_butto_ok->SetSize(wxSize(FromDIP(58), FromDIP(24)));
m_butto_ok->SetMinSize(wxSize(FromDIP(58), FromDIP(24)));
m_butto_ok->SetCornerRadius(FromDIP(12));
m_button_ok = new Button(this, _L("OK"));
m_button_ok->SetBackgroundColor(btn_bg_green);
m_button_ok->SetBorderColor(*wxWHITE);
m_button_ok->SetTextColor(*wxWHITE);
m_button_ok->SetFont(Label::Body_12);
m_button_ok->SetSize(wxSize(FromDIP(58), FromDIP(24)));
m_button_ok->SetMinSize(wxSize(FromDIP(58), FromDIP(24)));
m_button_ok->SetCornerRadius(FromDIP(12));
m_butto_ok->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent &e) {
m_button_ok->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent &e) {
EndModal(wxID_YES);
});
auto m_button_cancel = new Button(this, _L("Cancel"));
m_button_cancel = new Button(this, _L("Cancel"));
m_button_cancel->SetBackgroundColor(*wxWHITE);
m_button_cancel->SetBorderColor(wxColour(38, 46, 48));
m_button_cancel->SetFont(Label::Body_12);
@ -164,15 +171,18 @@ UpdateVersionDialog::UpdateVersionDialog(wxWindow *parent)
m_button_cancel->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent &e) {
EndModal(wxID_NO);
});
sizer_button->Add(0, 0, 1, wxEXPAND, 5);
sizer_button->Add(m_butto_ok, 0, wxALL, 5);
sizer_button->Add(m_button_cancel, 0, wxALL, 5);
sizer_button->Add(m_remind_choice, 0, wxALL | wxEXPAND, FromDIP(5));
sizer_button->AddStretchSpacer();
sizer_button->Add(m_button_ok, 0, wxALL, FromDIP(5));
sizer_button->Add(m_button_cancel, 0, wxALL, FromDIP(5));
m_sizer_right->Add(m_scrollwindw_release_note, 0, wxEXPAND | wxRIGHT, FromDIP(20));
m_sizer_right->Add(sizer_button, 0, wxEXPAND | wxRIGHT, FromDIP(20));
m_sizer_body->Add(m_sizer_right, 1, wxBOTTOM | wxEXPAND, FromDIP(8));
m_sizer_main->Add(m_sizer_body, 0, wxEXPAND, 0);
m_sizer_main->Add(sizer_button, 0, wxEXPAND, 0);
m_sizer_main->Add(0, 0, 0, wxBOTTOM, 10);
SetSizer(m_sizer_main);
@ -186,6 +196,8 @@ UpdateVersionDialog::~UpdateVersionDialog() {}
void UpdateVersionDialog::on_dpi_changed(const wxRect &suggested_rect) {
m_button_ok->Rescale();
m_button_cancel->Rescale();
}
void UpdateVersionDialog::update_version_info(wxString release_note, wxString version)
@ -199,5 +211,4 @@ void UpdateVersionDialog::update_version_info(wxString release_note, wxString ve
m_scrollwindw_release_note->Layout();
}
}} // namespace Slic3r::GUI

View file

@ -57,11 +57,15 @@ public:
void on_dpi_changed(const wxRect &suggested_rect) override;
void update_version_info(wxString release_note, wxString version);
void alter_choice(wxCommandEvent& event);
wxStaticText * m_text_up_info{nullptr};
wxScrolledWindow *m_scrollwindw_release_note{nullptr};
wxBoxSizer * sizer_text_release_note{nullptr};
wxStaticText * m_staticText_release_note{nullptr};
wxCheckBox* m_remind_choice;
Button* m_button_ok;
Button* m_button_cancel;
};
}} // namespace Slic3r::GUI

View file

@ -931,7 +931,7 @@ SelectMachineDialog::SelectMachineDialog(Plater *plater)
m_statictext_printer_msg->SetFont(::Label::Body_13);
m_statictext_printer_msg->Hide();
m_sizer_select = new wxGridSizer(1, 2, 0, 0);
m_sizer_select = new wxGridSizer(0, 2, 0, 0);
select_bed = create_item_checkbox(_L("Bed Leveling"), this, _L("Bed Leveling"), "bed_leveling");
select_flow = create_item_checkbox(_L("Flow Calibration"), this, _L("Flow Calibration"), "flow_cali");
select_use_ams = create_ams_checkbox(_L("Enable AMS"), this, _L("Enable AMS"));
@ -1081,13 +1081,20 @@ wxWindow *SelectMachineDialog::create_ams_checkbox(wxString title, wxWindow *par
img_ams_tip->Bind(wxEVT_ENTER_WINDOW, [this, img_ams_tip](auto &e) {
wxPoint pos = img_ams_tip->ClientToScreen(wxPoint(0, 0));
pos.y += img_ams_tip->GetRect().height;
m_mapping_tip_popup.Position(pos, wxSize(0, 0));
m_mapping_tip_popup.Position(pos, wxSize(0,0));
m_mapping_tip_popup.Popup();
});
img_ams_tip->Bind(wxEVT_LEAVE_WINDOW, [this, img_ams_tip](wxMouseEvent &e) {
auto region = m_mapping_tip_popup.GetClientRect();
img_ams_tip->Bind(wxEVT_LEAVE_WINDOW, [this, img_ams_tip](auto &e) {
m_mapping_tip_popup.Dismiss();
if(e.GetPosition().x > region.GetLeftTop().x && e.GetPosition().y > region.GetLeftTop().y && e.GetPosition().x < region.GetRightBottom().x && e.GetPosition().x < region.GetRightBottom().y)
;
else
m_mapping_tip_popup.Dismiss();
});
m_mapping_tip_popup.Bind(wxEVT_LEAVE_WINDOW, [this](auto& e) {
m_mapping_tip_popup.Dismiss();
});
checkbox->SetSizer(sizer_checkbox);
checkbox->Layout();
@ -1096,7 +1103,7 @@ wxWindow *SelectMachineDialog::create_ams_checkbox(wxString title, wxWindow *par
checkbox->SetToolTip(tooltip);
text->SetToolTip(tooltip);
text->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent &) {
text->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent & event) {
ams_check->SetValue(ams_check->GetValue() ? false : true);
});
return checkbox;
@ -1193,6 +1200,16 @@ void SelectMachineDialog::finish_mode()
void SelectMachineDialog::sync_ams_mapping_result(std::vector<FilamentInfo> &result)
{
if (result.empty()) {
BOOST_LOG_TRIVIAL(trace) << "ams_mapping result is empty";
for (auto it = m_materialList.begin(); it != m_materialList.end(); it++) {
wxString ams_id = "-";
wxColour ams_col = wxColour(0xCE, 0xCE, 0xCE);
it->second->item->set_ams_info(ams_col, ams_id);
}
return;
}
for (auto f = result.begin(); f != result.end(); f++) {
BOOST_LOG_TRIVIAL(trace) << "ams_mapping f id = " << f->id << ", tray_id = " << f->tray_id << ", color = " << f->color << ", type = " << f->type;
@ -1463,7 +1480,7 @@ void SelectMachineDialog::show_status(PrintDialogStatus status, std::vector<wxSt
Enable_Refresh_Button(true);
} else if (status == PrintDialogStatus::PrintStatusDisableAms) {
update_print_status_msg(wxEmptyString, false, false);
Enable_Send_Button(false);
Enable_Send_Button(true);
Enable_Refresh_Button(true);
} else if (status == PrintDialogStatus::PrintStatusNeedUpgradingAms) {
wxString msg_text;
@ -1680,6 +1697,8 @@ void SelectMachineDialog::on_ok(wxCommandEvent &event)
m_print_job->task_use_ams = false;
}
BOOST_LOG_TRIVIAL(info) << "print_job: use_ams = " << m_print_job->task_use_ams;
m_print_job->on_success([this]() { finish_mode(); });
wxCommandEvent evt(m_plater->get_print_finished_event());
@ -1909,9 +1928,9 @@ void SelectMachineDialog::on_selection_changed(wxCommandEvent &event)
void SelectMachineDialog::update_ams_check(MachineObject* obj)
{
if (obj && obj->ams_support_use_ams) {
ams_check->Show();
select_use_ams->Show();
} else {
ams_check->Hide();
select_use_ams->Hide();
}
}
@ -1956,6 +1975,8 @@ void SelectMachineDialog::update_show_status()
if (!obj_->is_info_ready()) {
if (is_timeout()) {
m_ams_mapping_result.clear();
sync_ams_mapping_result(m_ams_mapping_result);
show_status(PrintDialogStatus::PrintStatusReadingTimeout);
return;
}
@ -2001,6 +2022,7 @@ void SelectMachineDialog::update_show_status()
if (obj_->ams_support_use_ams) {
if (!ams_check->GetValue()) {
m_ams_mapping_result.clear();
sync_ams_mapping_result(m_ams_mapping_result);
show_status(PrintDialogStatus::PrintStatusDisableAms);
return;
}
@ -2252,7 +2274,7 @@ void SelectMachineDialog::set_default()
pos.y += item->GetRect().height;
m_mapping_popup.Position(pos, wxSize(0, 0));
if (obj_ && obj_->has_ams()) {
if (obj_ && obj_->has_ams() && ams_check->GetValue()) {
m_mapping_popup.set_current_filament_id(extruder);
m_mapping_popup.set_tag_texture(materials[extruder]);
m_mapping_popup.update_ams_data(obj_->amsList);

View file

@ -2615,20 +2615,45 @@ void Selection::paste_objects_from_clipboard()
std::vector<size_t> object_idxs;
const ModelObjectPtrs& src_objects = m_clipboard.get_objects();
PartPlate * plate = wxGetApp().plater()->get_partplate_list().get_curr_plate();
//BBS: if multiple objects are selected, move them as a whole after copy
Vec2d shift_all = {0, 0};
if (src_objects.size() > 1) {
BoundingBoxf3 bbox_all;
for (const ModelObject *src_object : src_objects) {
BoundingBoxf3 bbox = src_object->instance_convex_hull_bounding_box(0);
bbox_all.merge(bbox);
}
auto bsize = bbox_all.size();
if (bsize.x() < bsize.y())
shift_all = {bbox_all.size().x(), 0};
else
shift_all = {0, bbox_all.size().y()};
}
for (const ModelObject* src_object : src_objects)
{
ModelObject* dst_object = m_model->add_object(*src_object);
// BBS: find an empty cell to put the copied object
BoundingBoxf3 bbox = src_object->instance_convex_hull_bounding_box(0);
PartPlate* plate = wxGetApp().plater()->get_partplate_list().get_curr_plate();
bool in_current = plate->intersects(bbox);
auto start_offset = in_current?src_object->instances.front()->get_offset():plate->get_build_volume().center();
auto start_point = in_current?bbox.center():plate->get_build_volume().center();
auto point_offset = start_offset - start_point;
auto empty_cell = wxGetApp().plater()->canvas3D()->get_nearest_empty_cell({start_point(0), start_point(1)});
Vec3d displacement = { empty_cell.x() + point_offset.x(), empty_cell.y() + point_offset.y(), start_point(2) };
Vec3d displacement;
if (shift_all(0) != 0 || shift_all(1) != 0) {
// BBS: if multiple objects are selected, move them as a whole after copy
auto start_point = bbox.center();
displacement = {shift_all.x() + start_point.x(), shift_all.y() + start_point.y(), start_point(2)};
} else {
// BBS: if only one object is copied, find an empty cell to put it
bool in_current = plate->intersects(bbox);
auto start_point = in_current ? bbox.center() : plate->get_build_volume().center();
auto start_offset = in_current ? src_object->instances.front()->get_offset() : plate->get_build_volume().center();
auto point_offset = start_offset - start_point;
auto empty_cell = wxGetApp().plater()->canvas3D()->get_nearest_empty_cell({start_point(0), start_point(1)});
displacement = {empty_cell.x() + point_offset.x(), empty_cell.y() + point_offset.y(), start_point(2)};
}
for (ModelInstance* inst : dst_object->instances)
inst->set_offset(displacement);

View file

@ -9,7 +9,7 @@
#include "slic3r/Utils/Http.hpp"
#include "libslic3r/Thread.hpp"
#include "RecenterDialog.hpp"
namespace Slic3r { namespace GUI {
@ -1355,6 +1355,12 @@ void StatusPanel::update(MachineObject *obj)
m_machine_ctrl_panel->Thaw();
}
void StatusPanel::show_recenter_dialog() {
RecenterDialog dlg(this);
if (dlg.ShowModal() == wxID_OK)
obj->command_go_home();
}
void StatusPanel::show_error_message(wxString msg)
{
m_error_text->SetLabel(msg);
@ -1399,6 +1405,14 @@ void StatusPanel::show_printing_status(bool ctrl_area, bool temp_area)
m_bpButton_z_down_10->Enable(false);
m_bpButton_e_10->Enable(false);
m_bpButton_e_down_10->Enable(false);
m_bpButton_z_10->SetIcon("monitor_bed_up_disable");
m_bpButton_z_1->SetIcon("monitor_bed_up_disable");
m_bpButton_z_down_1->SetIcon("monitor_bed_down_disable");
m_bpButton_z_down_10->SetIcon("monitor_bed_down_disable");
m_bpButton_e_10->SetIcon("monitor_extruder_up_disable");
m_bpButton_e_down_10->SetIcon("monitor_extrduer_down_disable");
m_staticText_z_tip->SetForegroundColour(DISCONNECT_TEXT_COL);
m_staticText_e->SetForegroundColour(DISCONNECT_TEXT_COL);
m_button_unload->Enable(false);
@ -1416,6 +1430,14 @@ void StatusPanel::show_printing_status(bool ctrl_area, bool temp_area)
m_bpButton_z_down_10->Enable();
m_bpButton_e_10->Enable();
m_bpButton_e_down_10->Enable();
m_bpButton_z_10->SetIcon("monitor_bed_up");
m_bpButton_z_1->SetIcon("monitor_bed_up");
m_bpButton_z_down_1->SetIcon("monitor_bed_down");
m_bpButton_z_down_10->SetIcon("monitor_bed_down");
m_bpButton_e_10->SetIcon("monitor_extruder_up");
m_bpButton_e_down_10->SetIcon("monitor_extrduer_down");
m_staticText_z_tip->SetForegroundColour(TEXT_LIGHT_FONT_COL);
m_staticText_e->SetForegroundColour(TEXT_LIGHT_FONT_COL);
m_button_unload->Enable();
@ -1524,8 +1546,8 @@ void StatusPanel::update_misc_ctrl(MachineObject *obj)
else {
// update speed
this->speed_lvl = obj->printing_speed_lvl;
wxString text_speed = wxString::Format("%d%%", obj->printing_speed_mag);
m_switch_speed->SetLabels(text_speed, text_speed);
wxString text_speed = wxString::Format("%d%%", obj->printing_speed_mag);
m_switch_speed->SetLabels(text_speed, text_speed);
}
}
@ -1953,26 +1975,77 @@ void StatusPanel::on_axis_ctrl_xy(wxCommandEvent &event)
if (event.GetInt() == 6) { obj->command_axis_control("Y", 1.0, -1.0f, 3000); }
if (event.GetInt() == 7) { obj->command_axis_control("X", 1.0, 1.0f, 3000); }
if (event.GetInt() == 8) { obj->command_go_home(); }
//check is at home
if (event.GetInt() == 1
|| event.GetInt() == 3
|| event.GetInt() == 5
|| event.GetInt() == 7) {
if (!obj->is_axis_at_home("X")) {
BOOST_LOG_TRIVIAL(info) << "axis x is not at home";
show_recenter_dialog();
return;
}
}
else if (event.GetInt() == 0
|| event.GetInt() == 2
|| event.GetInt() == 4
|| event.GetInt() == 6) {
if (!obj->is_axis_at_home("Y")) {
BOOST_LOG_TRIVIAL(info) << "axis y is not at home";
show_recenter_dialog();
return;
}
}
}
bool StatusPanel::check_axis_z_at_home(MachineObject* obj)
{
if (obj) {
if (!obj->is_axis_at_home("Z")) {
BOOST_LOG_TRIVIAL(info) << "axis z is not at home";
show_recenter_dialog();
return false;
}
return true;
}
return false;
}
void StatusPanel::on_axis_ctrl_z_up_10(wxCommandEvent &event)
{
if (obj) obj->command_axis_control("Z", 1.0, -10.0f, 900);
if (obj) {
obj->command_axis_control("Z", 1.0, -10.0f, 900);
if (!check_axis_z_at_home(obj))
return;
}
}
void StatusPanel::on_axis_ctrl_z_up_1(wxCommandEvent &event)
{
if (obj) obj->command_axis_control("Z", 1.0, -1.0f, 900);
if (obj) {
obj->command_axis_control("Z", 1.0, -1.0f, 900);
if (!check_axis_z_at_home(obj))
return;
}
}
void StatusPanel::on_axis_ctrl_z_down_1(wxCommandEvent &event)
{
if (obj) obj->command_axis_control("Z", 1.0, 1.0f, 900);
if (obj) {
obj->command_axis_control("Z", 1.0, 1.0f, 900);
if (!check_axis_z_at_home(obj))
return;
}
}
void StatusPanel::on_axis_ctrl_z_down_10(wxCommandEvent &event)
{
if (obj) obj->command_axis_control("Z", 1.0, 10.0f, 900);
if (obj) {
obj->command_axis_control("Z", 1.0, 10.0f, 900);
if (!check_axis_z_at_home(obj))
return;
}
}
void StatusPanel::on_axis_ctrl_e_up_10(wxCommandEvent &event)
@ -2217,7 +2290,7 @@ void StatusPanel::on_switch_speed(wxCommandEvent &event)
popUp->SetSizer(sizer);
auto em = em_unit(this);
popUp->SetSize(em * 36, em * 8);
step->SetHint(_L("This only takes effect during printing"));
step->AppendItem(_L("Silent"), "");
step->AppendItem(_L("Standard"), "");
step->AppendItem(_L("Sport"), "");
@ -2233,6 +2306,11 @@ void StatusPanel::on_switch_speed(wxCommandEvent &event)
}
step->SelectItem(selected_item);
if (!obj->is_in_printing()) {
step->Bind(wxEVT_LEFT_DOWN, [](auto& e) {
return; });
}
step->Bind(EVT_STEP_CHANGED, [this](auto &e) {
this->speed_lvl = e.GetInt() + 1;
if (obj) {

View file

@ -277,8 +277,10 @@ protected:
void on_subtask_clean(wxCommandEvent &event);
void show_error_message(wxString msg);
void error_info_reset();
void show_recenter_dialog();
/* axis control */
bool check_axis_z_at_home(MachineObject* obj);
void on_axis_ctrl_xy(wxCommandEvent &event);
void on_axis_ctrl_z_up_10(wxCommandEvent &event);
void on_axis_ctrl_z_up_1(wxCommandEvent &event);

View file

@ -1376,13 +1376,14 @@ void Tab::on_value_change(const std::string& opt_key, const boost::any& value)
update_wiping_button_visibility();
if (opt_key == "enable_prime_tower") {
bool timelapse_enabled = m_config->option<ConfigOptionBool>("timelapse_no_toolhead")->value;
auto timelapse_type = m_config->option<ConfigOptionEnum<TimelapseType>>("timelapse_type");
bool timelapse_enabled = timelapse_type->value == TimelapseType::tlSmooth;
if (!boost::any_cast<bool>(value) && timelapse_enabled) {
MessageDialog dlg(wxGetApp().plater(), _L("Prime tower is required by timeplase. Are you sure you want to disable both of them?"),
_L("Warning"), wxICON_WARNING | wxYES | wxNO);
if (dlg.ShowModal() == wxID_YES) {
DynamicPrintConfig new_conf = *m_config;
new_conf.set_key_value("timelapse_no_toolhead", new ConfigOptionBool(false));
new_conf.set_key_value("timelapse_type", new ConfigOptionEnum<TimelapseType>(TimelapseType::tlNone));
m_config_manipulation.apply(m_config, &new_conf);
wxGetApp().plater()->update();
}
@ -1396,9 +1397,9 @@ void Tab::on_value_change(const std::string& opt_key, const boost::any& value)
}
// reload scene to update timelapse wipe tower
if (opt_key == "timelapse_no_toolhead") {
if (opt_key == "timelapse_type") {
bool wipe_tower_enabled = m_config->option<ConfigOptionBool>("enable_prime_tower")->value;
if (!wipe_tower_enabled && boost::any_cast<bool>(value)) {
if (!wipe_tower_enabled && boost::any_cast<int>(value) == int(TimelapseType::tlSmooth)) {
MessageDialog dlg(wxGetApp().plater(), _L("Prime tower is required by timelapse. Do you want to enable both of them?"),
_L("Warning"), wxICON_WARNING | wxYES | wxNO);
if (dlg.ShowModal() == wxID_YES) {
@ -1409,7 +1410,7 @@ void Tab::on_value_change(const std::string& opt_key, const boost::any& value)
}
else {
DynamicPrintConfig new_conf = *m_config;
new_conf.set_key_value("timelapse_no_toolhead", new ConfigOptionBool(false));
new_conf.set_key_value("timelapse_type", new ConfigOptionEnum<TimelapseType>(TimelapseType::tlNone));
m_config_manipulation.apply(m_config, &new_conf);
}
} else {
@ -1765,6 +1766,7 @@ void TabPrint::build()
optgroup->append_single_option_line("seam_position", "Seam");
optgroup = page->new_optgroup(L("Precision"));
optgroup->append_single_option_line("slice_closing_radius");
optgroup->append_single_option_line("resolution");
optgroup->append_single_option_line("enable_arc_fitting");
optgroup->append_single_option_line("xy_hole_compensation");
@ -1849,40 +1851,40 @@ void TabPrint::build()
page = add_options_page(L("Support"), "support");
optgroup = page->new_optgroup(L("Support"));
optgroup->append_single_option_line("enable_support", "support");
optgroup->append_single_option_line("support_type", "support");
optgroup->append_single_option_line("support_threshold_angle", "support");
optgroup->append_single_option_line("support_type", "support#support-types");
optgroup->append_single_option_line("support_threshold_angle", "support#threshold-angle");
optgroup->append_single_option_line("support_on_build_plate_only");
//optgroup->append_single_option_line("enforce_support_layers");
optgroup = page->new_optgroup(L("Support filament"));
optgroup->append_single_option_line("support_filament", "support");
optgroup->append_single_option_line("support_interface_filament", "support");
optgroup->append_single_option_line("support_filament", "support#support-filament");
optgroup->append_single_option_line("support_interface_filament", "support#support-filament");
//optgroup = page->new_optgroup(L("Options for support material and raft"));
//optgroup->append_single_option_line("support_style");
//BBS
optgroup = page->new_optgroup(L("Advanced"));
optgroup->append_single_option_line("tree_support_branch_distance", "support");
optgroup->append_single_option_line("tree_support_branch_diameter", "support");
optgroup->append_single_option_line("tree_support_branch_angle", "support");
optgroup->append_single_option_line("tree_support_branch_distance", "support#tree-support-only-options");
optgroup->append_single_option_line("tree_support_branch_diameter", "support#tree-support-only-options");
optgroup->append_single_option_line("tree_support_branch_angle", "support#tree-support-only-options");
optgroup->append_single_option_line("tree_support_wall_count");
optgroup->append_single_option_line("tree_support_with_infill");
optgroup->append_single_option_line("support_top_z_distance", "support");
optgroup->append_single_option_line("support_base_pattern", "support");
optgroup->append_single_option_line("support_base_pattern_spacing", "support");
optgroup->append_single_option_line("support_top_z_distance", "support#top-z-distance");
optgroup->append_single_option_line("support_base_pattern", "support#base-pattern");
optgroup->append_single_option_line("support_base_pattern_spacing", "support#base-pattern");
//optgroup->append_single_option_line("support_angle");
optgroup->append_single_option_line("support_interface_top_layers", "support");
optgroup->append_single_option_line("support_interface_bottom_layers", "support");
optgroup->append_single_option_line("support_interface_pattern", "support");
optgroup->append_single_option_line("support_interface_spacing", "support");
optgroup->append_single_option_line("support_interface_top_layers", "support#base-pattern");
optgroup->append_single_option_line("support_interface_bottom_layers", "support#base-pattern");
optgroup->append_single_option_line("support_interface_pattern", "support#base-pattern");
optgroup->append_single_option_line("support_interface_spacing", "support#base-pattern");
optgroup->append_single_option_line("support_bottom_interface_spacing");
//optgroup->append_single_option_line("support_interface_loop_pattern");
optgroup->append_single_option_line("support_object_xy_distance", "support");
optgroup->append_single_option_line("bridge_no_support", "support");
optgroup->append_single_option_line("max_bridge_length", "support");
optgroup->append_single_option_line("thick_bridges", "support");
optgroup->append_single_option_line("support_object_xy_distance", "support#supportobject-xy-distance");
optgroup->append_single_option_line("bridge_no_support", "support#base-pattern");
optgroup->append_single_option_line("max_bridge_length", "support#base-pattern");
optgroup->append_single_option_line("thick_bridges", "support#base-pattern");
//optgroup->append_single_option_line("independent_support_layer_height");
page = add_options_page(L("Others"), "advanced");
@ -1891,8 +1893,8 @@ void TabPrint::build()
optgroup->append_single_option_line("skirt_distance");
//optgroup->append_single_option_line("draft_shield");
optgroup->append_single_option_line("brim_type", "auto-brim");
optgroup->append_single_option_line("brim_width", "auto-brim");
optgroup->append_single_option_line("brim_object_gap", "auto-brim");
optgroup->append_single_option_line("brim_width", "auto-brim#manual");
optgroup->append_single_option_line("brim_object_gap", "auto-brim#brim-object-gap");
optgroup->append_single_option_line("raft_layers");
//optgroup->append_single_option_line("raft_first_layer_density");
//optgroup->append_single_option_line("raft_first_layer_expansion");
@ -1904,14 +1906,14 @@ void TabPrint::build()
optgroup->append_single_option_line("prime_tower_brim_width");
optgroup = page->new_optgroup(L("Flush options"));
optgroup->append_single_option_line("flush_into_infill", "reduce-wasting-during-filament-change");
optgroup->append_single_option_line("flush_into_objects", "reduce-wasting-during-filament-change");
optgroup->append_single_option_line("flush_into_support", "reduce-wasting-during-filament-change");
optgroup->append_single_option_line("flush_into_infill", "reduce-wasting-during-filament-change#wipe-into-infill");
optgroup->append_single_option_line("flush_into_objects", "reduce-wasting-during-filament-change#wipe-into-object");
optgroup->append_single_option_line("flush_into_support", "reduce-wasting-during-filament-change#wipe-into-support-enabled-by-default");
optgroup = page->new_optgroup(L("Special mode"));
optgroup->append_single_option_line("print_sequence");
optgroup->append_single_option_line("spiral_mode", "spiral-vase");
optgroup->append_single_option_line("timelapse_no_toolhead", "Timelapse");
optgroup->append_single_option_line("timelapse_type", "Timelapse");
//BBS: todo remove clearance to machine
#if 0
//line = { L("Extruder radius"), "" };
@ -3399,9 +3401,10 @@ void TabPrinter::toggle_options()
}
wxString extruder_number;
long val;
if (m_active_page->title().StartsWith("Extruder ", &extruder_number) && extruder_number.ToLong(&val) &&
val > 0 && (size_t)val <= m_extruders_count)
long val = 1;
if ( m_active_page->title().IsSameAs("Extruder") ||
(m_active_page->title().StartsWith("Extruder ", &extruder_number) && extruder_number.ToLong(&val) &&
val > 0 && (size_t)val <= m_extruders_count))
{
size_t i = size_t(val - 1);
bool have_retract_length = m_config->opt_float("retraction_length", i) > 0;
@ -3427,10 +3430,10 @@ void TabPrinter::toggle_options()
//BBS
toggle_option(el, retraction, i);
bool wipe = m_config->opt_bool("wipe", i);
bool wipe = retraction && m_config->opt_bool("wipe", i);
toggle_option("retract_before_wipe", wipe, i);
// BBS
toggle_option("wipe_distance", i);
toggle_option("wipe_distance", wipe, i);
toggle_option("retract_length_toolchange", have_multiple_extruders, i);

View file

@ -422,7 +422,7 @@ void DropDown::mouseMove(wxMouseEvent &event)
void DropDown::mouseWheelMoved(wxMouseEvent &event)
{
auto delta = (event.GetWheelRotation() < 0 == event.IsWheelInverted()) ? rowSize.y : -rowSize.y;
auto delta = event.GetWheelRotation() > 0 ? rowSize.y : -rowSize.y;
wxPoint pt2 = offset + wxPoint{0, delta};
if (pt2.y > 0)
pt2.y = 0;

View file

@ -169,7 +169,10 @@ void StaticBox::doRender(wxDC& dc)
} else {
dc.SetPen(wxPen(background_color.colorForStates(states)));
}
dc.SetBrush(wxBrush(background_color.colorForStates(states)));
if (background_color.count() > 0)
dc.SetBrush(wxBrush(background_color.colorForStates(states)));
else
dc.SetBrush(wxBrush(GetBackgroundColour()));
if (radius == 0) {
dc.DrawRectangle(rc);
}

View file

@ -58,6 +58,10 @@ bool StepCtrlBase::SetTipFont(wxFont const& font)
return true;
}
void StepCtrlBase::SetHint(wxString hint) {
this->hint = hint;
}
int StepCtrlBase::AppendItem(const wxString &item, wxString const & tip)
{
steps.push_back(item);
@ -144,7 +148,13 @@ void StepCtrl::mouseMove(wxMouseEvent &event)
wxPoint pt;
event.GetPosition(&pt.x, &pt.y);
pos_thumb.x = pt.x + drag_offset.x;
Refresh();
wxSize size = GetSize();
int itemWidth = size.x / steps.size();
int index = pos_thumb.x / itemWidth;
if (index != pos_thumb.y) {
pos_thumb.y = index;
Refresh();
}
}
void StepCtrl::mouseUp(wxMouseEvent &event)
@ -160,7 +170,6 @@ void StepCtrl::mouseUp(wxMouseEvent &event)
void StepCtrl::doRender(wxDC &dc)
{
if (steps.empty()) return;
StaticBox::doRender(dc);
wxSize size = GetSize();
@ -176,8 +185,14 @@ void StepCtrl::doRender(wxDC &dc)
int circleY = size.y / 2;
dc.SetPen(wxPen(clr_step.colorForStates(states)));
dc.SetBrush(wxBrush(clr_step.colorForStates(states)));
if (!hint.empty()) {
dc.SetFont(font_tip);
dc.SetTextForeground(clr_tip.colorForStates(states));
wxSize sz = dc.GetTextExtent(hint);
dc.DrawText(hint, dc.GetCharWidth(), circleY - FromDIP(20) - sz.y);
}
for (int i = 0; i < steps.size(); ++i) {
bool check = pos_thumb == wxPoint{0, 0} ? step == i : (pos_thumb.x >= circleX - itemWidth / 2 && pos_thumb.x < circleX + itemWidth / 2);
bool check = (pos_thumb == wxPoint{0, 0} ? step : pos_thumb.y) == i;
dc.DrawEllipse(circleX - radius, circleY - radius, radius * 2, radius * 2);
dc.SetFont(GetFont());
dc.SetTextForeground(clr_text.colorForStates(states | (check ? StateColor::Checked : 0)));

View file

@ -19,6 +19,7 @@ protected:
std::vector<wxString> steps;
std::vector<wxString> tips;
wxString hint;
int step = -1;
@ -35,6 +36,8 @@ public:
~StepCtrlBase();
public:
void SetHint(wxString hint);
bool SetTipFont(wxFont const & font);
public:

View file

@ -46,21 +46,32 @@ void wxMediaCtrl2::Load(wxURI url)
return;
}
{
wxRegKey key(wxRegKey::HKCR, "CLSID\\{233E64FB-2041-4A6C-AFAB-FF9BCF83E7AA}\\InProcServer32");
wxString path = key.QueryDefaultValue();
wxRegKey key1(wxRegKey::HKCR, "CLSID\\{233E64FB-2041-4A6C-AFAB-FF9BCF83E7AA}\\InProcServer32");
wxString path = key1.QueryDefaultValue();
wxRegKey key2(wxRegKey::HKCR, "bambu");
wxString clsid;
key2.QueryRawValue("Source Filter", clsid);
if (!wxFile::Exists(path) || clsid != L"{233E64FB-2041-4A6C-AFAB-FF9BCF83E7AA}") {
wxMessageBox(_L("Missing BambuSource component registered for media playing! Please re-install BambuStutio or seek after-sales help."), _L("Error"),
Slic3r::GUI::wxGetApp().CallAfter([] {
wxMessageBox(_L("Missing BambuSource component registered for media playing! Please re-install BambuStutio or seek after-sales help."), _L("Error"),
wxOK);
m_error = 3;
});
m_error = clsid.IsEmpty() ? 100 : clsid != L"{233E64FB-2041-4A6C-AFAB-FF9BCF83E7AA}" ? 101 : 102;
wxMediaEvent event(wxEVT_MEDIA_STATECHANGED);
event.SetId(GetId());
event.SetEventObject(this);
wxPostEvent(this, event);
return;
}
wxRegKey keyWmp(wxRegKey::HKCU, "SOFTWARE\\Microsoft\\MediaPlayer\\Player\\Extensions\\.");
keyWmp.Create();
long permissions = 0;
if (keyWmp.HasValue("Permissions"))
keyWmp.QueryValue("Permissions", &permissions);
if ((permissions & 32) == 0) {
permissions |= 32;
keyWmp.SetValue("Permissions", permissions);
}
}
url = wxURI(url.BuildURI().append("&hwnd=").append(
boost::lexical_cast<std::string>(GetHandle())));

View file

@ -286,7 +286,7 @@ namespace GUI {
void initGestures(void * view, wxEvtHandler * handler)
{
NSOpenGLView * glView = (NSOpenGLView *) view;
wxNSCustomOpenGLView * glView = (wxNSCustomOpenGLView *) view;
[glView initGesturesWithHandler: handler];
}

View file

@ -60,17 +60,19 @@ static void start_new_slicer_or_gcodeviewer(const NewSlicerInstanceType instance
boost::filesystem::path bin_path = into_path(wxStandardPaths::Get().GetExecutablePath());
#if defined(__APPLE__)
{
bin_path = bin_path.parent_path() / "BambuStudio";
//bin_path = bin_path.parent_path() / "BambuStudio";
bin_path = "/usr/bin/open";
// On Apple the wxExecute fails, thus we use boost::process instead.
BOOST_LOG_TRIVIAL(info) << "Trying to spawn a new slicer \"" << bin_path.string() << "\"";
try {
std::vector<std::string> args;
std::vector<std::string> args = { "-n", "-a", "/Applications/BambuStudio.app"};
if (!paths_to_open.empty()) {
for (const auto& file : paths_to_open)
args.emplace_back(into_u8(file));
}
args.emplace_back("--args");
if (instance_type == NewSlicerInstanceType::GCodeViewer)
args.emplace_back("--gcodeviewer");
if (!paths_to_open.empty()) {
for (const auto& file : paths_to_open)
args.emplace_back(into_u8(file));
}
if (instance_type == NewSlicerInstanceType::Slicer && single_instance)
args.emplace_back("--single-instance");
boost::process::spawn(bin_path, args);

View file

@ -36,7 +36,7 @@ namespace BBL {
#define BAMBU_NETWORK_LIBRARY "bambu_networking"
#define BAMBU_NETWORK_AGENT_NAME "bambu_network_agent"
#define BAMBU_NETWORK_AGENT_VERSION "01.02.00.01"
#define BAMBU_NETWORK_AGENT_VERSION "01.02.00.02"
//iot preset type strings