mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-28 11:21:30 +00:00
Merge remote-tracking branch 'remote/master' into SoftFever
# Conflicts: # resources/profiles/BBL/filament/Bambu PC @BBL X1C.json # resources/profiles/BBL/filament/Bambu TPU 95A @BBL X1C.json
This commit is contained in:
+2
-2
@@ -1220,7 +1220,7 @@ int CLI::run(int argc, char **argv)
|
||||
|
||||
for (int i = 0; i < plate_data_list.size(); i++) {
|
||||
PlateData *plate_data = plate_data_list[i];
|
||||
for (auto it = plate_data->slice_flaments_info.begin(); it != plate_data->slice_flaments_info.end(); it++) {
|
||||
for (auto it = plate_data->slice_filaments_info.begin(); it != plate_data->slice_filaments_info.end(); it++) {
|
||||
it->type = filament_types?filament_types->get_at(it->id):"PLA";
|
||||
it->color = filament_color?filament_color->get_at(it->id):"#FFFFFF";
|
||||
//it->filament_id = filament_id?filament_id->get_at(it->id):"unknown";
|
||||
@@ -1729,7 +1729,7 @@ extern "C" {
|
||||
argv_ptrs[i] = argv_narrow[i].data();
|
||||
|
||||
//BBS: register default exception handler
|
||||
#if BBL_RELEASE_TO_PUBLIC
|
||||
#if 1
|
||||
SET_DEFULTER_HANDLER();
|
||||
#else
|
||||
AddVectoredExceptionHandler(1, CBaseException::UnhandledExceptionFilter);
|
||||
|
||||
@@ -164,9 +164,8 @@ namespace ImGui
|
||||
const wchar_t HeightRangeIcon = 0x0813;
|
||||
const wchar_t FoldButtonIcon = 0x0814;
|
||||
const wchar_t UnfoldButtonIcon = 0x0815;
|
||||
const wchar_t GcodePauseIcon = 0x0816;
|
||||
const wchar_t SphereButtonIcon = 0x0817;
|
||||
const wchar_t FragmentFilterIcon = 0x0818;
|
||||
const wchar_t SphereButtonIcon = 0x0816;
|
||||
const wchar_t FragmentFilterIcon = 0x0817;
|
||||
|
||||
// void MyFunction(const char* name, const MyMatrix44& v);
|
||||
}
|
||||
|
||||
@@ -4117,7 +4117,7 @@ bool ImGui::BBLInputScalar(const char *label, ImGuiDataType data_type, void *p_d
|
||||
|
||||
if (format == NULL) format = DataTypeGetInfo(data_type)->PrintFmt;
|
||||
|
||||
char buf[16];
|
||||
char buf[8];
|
||||
DataTypeFormatString(buf, IM_ARRAYSIZE(buf), data_type, p_data, format);
|
||||
|
||||
bool value_changed = false;
|
||||
@@ -6235,7 +6235,11 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl
|
||||
if (g.Style.FrameBorderSize > 0.0f)
|
||||
RenderFrameBorder(bb.Min, bb.Max, rounding);
|
||||
else
|
||||
#ifdef __APPLE__
|
||||
window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), rounding,NULL,2.0f); // Color button are often in need of some sort of border
|
||||
#else
|
||||
window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), rounding); // Color button are often in need of some sort of border
|
||||
#endif
|
||||
}
|
||||
|
||||
// Drag and Drop Source
|
||||
|
||||
@@ -256,9 +256,15 @@ void AppConfig::set_defaults()
|
||||
set("backup_interval", "10");
|
||||
}
|
||||
|
||||
#if BBL_RELEASE_TO_PUBLIC
|
||||
if (get("iot_environment").empty()) {
|
||||
set("iot_environment", "3");
|
||||
}
|
||||
#else
|
||||
if (get("iot_environment").empty()) {
|
||||
set("iot_environment", "1");
|
||||
}
|
||||
#endif
|
||||
|
||||
// Remove legacy window positions/sizes
|
||||
erase("app", "main_frame_maximized");
|
||||
@@ -1003,12 +1009,7 @@ std::string AppConfig::get_region()
|
||||
std::string AppConfig::get_country_code()
|
||||
{
|
||||
std::string region = get_region();
|
||||
/* fix PRE environment when release to public */
|
||||
#if 0
|
||||
this->set("iot_environment", "2");
|
||||
return "ENV_CN_PRE";
|
||||
#else
|
||||
//if (is_engineering_region()) { return region; }
|
||||
if (is_engineering_region()) { return region; }
|
||||
if (region == "CHN" || region == "China")
|
||||
return "CN";
|
||||
else if (region == "USA")
|
||||
@@ -1022,7 +1023,7 @@ std::string AppConfig::get_country_code()
|
||||
else
|
||||
return "Others";
|
||||
return "";
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
bool AppConfig::is_engineering_region(){
|
||||
|
||||
+17
-58
@@ -762,40 +762,7 @@ bool compSecondMoment(const ExPolygons& expolys, double& smExpolysX, double& smE
|
||||
return true;
|
||||
}
|
||||
|
||||
// BBS: thermal length is calculated according to the material of a volume
|
||||
double getThermalLength(const ModelVolume* modelVolumePtr) {
|
||||
double thermalLength = 200.;
|
||||
auto aa = modelVolumePtr->extruder_id();
|
||||
if (Model::extruderParamsMap.find(aa) != Model::extruderParamsMap.end()) {
|
||||
if (Model::extruderParamsMap.at(aa).materialName == "ABS" ||
|
||||
Model::extruderParamsMap.at(aa).materialName == "PA-CF" ||
|
||||
Model::extruderParamsMap.at(aa).materialName == "PET-CF") {
|
||||
thermalLength = 100;
|
||||
}
|
||||
if (Model::extruderParamsMap.at(aa).materialName == "PC") {
|
||||
thermalLength = 40;
|
||||
}
|
||||
if (Model::extruderParamsMap.at(aa).materialName == "TPU") {
|
||||
thermalLength = 1000;
|
||||
}
|
||||
|
||||
}
|
||||
return thermalLength;
|
||||
}
|
||||
|
||||
// BBS: thermal length calculation for a group of volumes
|
||||
double getThermalLength(const std::vector<ModelVolume*> modelVolumePtrs)
|
||||
{
|
||||
double thermalLength = 1250.;
|
||||
|
||||
for (const auto& modelVolumePtr : modelVolumePtrs) {
|
||||
if (modelVolumePtr != nullptr) {
|
||||
// the thermal length of a group is decided by the volume with shortest thermal length
|
||||
thermalLength = std::min(thermalLength, getThermalLength(modelVolumePtr));
|
||||
}
|
||||
}
|
||||
return thermalLength;
|
||||
}
|
||||
|
||||
//BBS: config brimwidth by volumes
|
||||
double configBrimWidthByVolumes(double deltaT, double adhension, double maxSpeed, const ModelVolume* modelVolumePtr, const ExPolygons& expolys)
|
||||
@@ -825,7 +792,7 @@ double configBrimWidthByVolumes(double deltaT, double adhension, double maxSpeed
|
||||
const double& bboxX = bbox2.size()(0);
|
||||
const double& bboxY = bbox2.size()(1);
|
||||
double thermalLength = sqrt(bboxX * bboxX + bboxY * bboxY) * SCALING_FACTOR;
|
||||
double thermalLengthRef = getThermalLength(modelVolumePtr);
|
||||
double thermalLengthRef = Model::getThermalLength(modelVolumePtr);
|
||||
|
||||
double height_to_area = std::max(height / Ixx * (bbox2.size()(1) * SCALING_FACTOR), height / Iyy * (bbox2.size()(0) * SCALING_FACTOR));
|
||||
double brim_width = adhension * std::min(std::min(std::max(height_to_area * maxSpeed / 24, thermalLength * 8. / thermalLengthRef * std::min(height, 30.) / 30.), 18.), 1.5 * thermalLength);
|
||||
@@ -846,8 +813,12 @@ double configBrimWidthByVolumeGroups(double adhension, double maxSpeed, const st
|
||||
BoundingBoxf3 mergedBbx;
|
||||
for (const auto& modelVolumePtr : modelVolumePtrs) {
|
||||
if (modelVolumePtr->is_model_part()) {
|
||||
auto rawBoundingbox = modelVolumePtr->mesh().transformed_bounding_box(modelVolumePtr->get_matrix());
|
||||
auto bbox = modelVolumePtr->get_object()->instances.front()->transform_bounding_box(rawBoundingbox);
|
||||
Slic3r::Transform3d t;
|
||||
if (modelVolumePtr->get_object()->instances.size() > 0)
|
||||
t = modelVolumePtr->get_object()->instances.front()->get_matrix() * modelVolumePtr->get_matrix();
|
||||
else
|
||||
t = modelVolumePtr->get_matrix();
|
||||
auto bbox = modelVolumePtr->mesh().transformed_bounding_box(t);
|
||||
mergedBbx.merge(bbox);
|
||||
}
|
||||
}
|
||||
@@ -870,7 +841,7 @@ double configBrimWidthByVolumeGroups(double adhension, double maxSpeed, const st
|
||||
const double& bboxX = bbox2.size()(0);
|
||||
const double& bboxY = bbox2.size()(1);
|
||||
double thermalLength = sqrt(bboxX * bboxX + bboxY * bboxY) * SCALING_FACTOR;
|
||||
double thermalLengthRef = getThermalLength(modelVolumePtrs);
|
||||
double thermalLengthRef = Model::getThermalLength(modelVolumePtrs);
|
||||
|
||||
double height_to_area = std::max(height / Ixx * (bbox2.size()(1) * SCALING_FACTOR), height / Iyy * (bbox2.size()(0) * SCALING_FACTOR));
|
||||
double brim_width = adhension * std::min(std::min(std::max(height_to_area * maxSpeed / 24, thermalLength * 8. / thermalLengthRef * std::min(height, 30.) / 30.), 18.), 1.5 * thermalLength);
|
||||
@@ -884,26 +855,13 @@ double configBrimWidthByVolumeGroups(double adhension, double maxSpeed, const st
|
||||
}
|
||||
|
||||
//BBS: create all brims
|
||||
static ExPolygons outer_inner_brim_area(const Print& print, const ConstPrintObjectPtrs& top_level_objects_with_brim,
|
||||
static ExPolygons outer_inner_brim_area(const Print& print,
|
||||
const float no_brim_offset, std::map<ObjectID, ExPolygons>& brimAreaMap,
|
||||
std::map<ObjectID, ExPolygons>& supportBrimAreaMap,
|
||||
std::vector<std::pair<ObjectID, unsigned int>>& objPrintVec,
|
||||
std::vector<unsigned int>& printExtruders)
|
||||
{
|
||||
std::unordered_set<size_t> top_level_objects_idx;
|
||||
top_level_objects_idx.reserve(top_level_objects_with_brim.size());
|
||||
for (const PrintObject* object : top_level_objects_with_brim)
|
||||
top_level_objects_idx.insert(object->id().id);
|
||||
|
||||
unsigned int support_material_extruder = printExtruders.front() + 1;
|
||||
auto allExtruders = print.extruders();
|
||||
if (print.has_support_material()) {
|
||||
assert(top_level_objects_with_brim.front()->config().support_filament >= 0);
|
||||
if (top_level_objects_with_brim.front()->config().support_filament > 0)
|
||||
support_material_extruder = top_level_objects_with_brim.front()->config().support_filament;
|
||||
allExtruders.push_back(support_material_extruder - 1);
|
||||
sort_remove_duplicates(allExtruders);
|
||||
}
|
||||
|
||||
ExPolygons brim_area;
|
||||
ExPolygons no_brim_area;
|
||||
@@ -927,7 +885,6 @@ static ExPolygons outer_inner_brim_area(const Print& print, const ConstPrintObje
|
||||
float brim_offset = scale_(object->config().brim_object_gap.value);
|
||||
double flowWidth = print.brim_flow().scaled_spacing() * SCALING_FACTOR;
|
||||
float brim_width = scale_(floor(object->config().brim_width.value / flowWidth / 2) * flowWidth * 2);
|
||||
const bool top_outer_brim = top_level_objects_idx.find(object->id().id) != top_level_objects_idx.end();
|
||||
const float scaled_flow_width = print.brim_flow().scaled_spacing();
|
||||
const float scaled_additional_brim_width = scale_(floor(5 / flowWidth / 2) * flowWidth * 2);
|
||||
const float scaled_half_min_adh_length = scale_(1.1);
|
||||
@@ -1017,8 +974,13 @@ static ExPolygons outer_inner_brim_area(const Print& print, const ConstPrintObje
|
||||
if (brimAreaMap.find(object->id()) != brimAreaMap.end())
|
||||
expolygons_append(brim_area, brimAreaMap[object->id()]);
|
||||
}
|
||||
if ((print.config().print_sequence == PrintSequence::ByObject) && top_level_objects_with_brim.front()->config().support_filament == 0)
|
||||
support_material_extruder = objectWithExtruder.second;
|
||||
support_material_extruder = object->config().support_filament;
|
||||
if (support_material_extruder == 0 && object->has_support_material()) {
|
||||
if (print.config().print_sequence == PrintSequence::ByObject)
|
||||
support_material_extruder = objectWithExtruder.second;
|
||||
else
|
||||
support_material_extruder = printExtruders.front() + 1;
|
||||
}
|
||||
if (support_material_extruder == extruderNo && brimToWrite.at(object->id()).sup) {
|
||||
if (!object->support_layers().empty()) {
|
||||
for (const Polygon& support_contour : object->support_layers().front()->support_fills.polygons_covered_by_spacing()) {
|
||||
@@ -1658,10 +1620,7 @@ void make_brim(const Print& print, PrintTryCancel try_cancel, Polygons& islands_
|
||||
std::map<ObjectID, ExPolygons> supportBrimAreaMap;
|
||||
Flow flow = print.brim_flow();
|
||||
const auto scaled_resolution = scaled<double>(print.config().resolution.value);
|
||||
std::vector<ExPolygons> bottom_layers_expolygons = get_print_bottom_layers_expolygons(print);
|
||||
ConstPrintObjectPtrs top_level_objects_with_brim = get_top_level_objects_with_brim(print, bottom_layers_expolygons);
|
||||
Polygons islands = top_level_outer_brim_islands(top_level_objects_with_brim, scaled_resolution);
|
||||
ExPolygons islands_area_ex = outer_inner_brim_area(print, top_level_objects_with_brim,
|
||||
ExPolygons islands_area_ex = outer_inner_brim_area(print,
|
||||
float(flow.scaled_spacing()), brimAreaMap, supportBrimAreaMap, objPrintVec, printExtruders);
|
||||
|
||||
// BBS: Find boundingbox of the first layer
|
||||
|
||||
@@ -122,8 +122,6 @@ set(lisbslic3r_sources
|
||||
GCode/SpiralVase.hpp
|
||||
GCode/SeamPlacer.cpp
|
||||
GCode/SeamPlacer.hpp
|
||||
GCode/SpeedGenerator.cpp
|
||||
GCode/SpeedGenerator.hpp
|
||||
GCode/ToolOrdering.cpp
|
||||
GCode/ToolOrdering.hpp
|
||||
GCode/WipeTower.cpp
|
||||
@@ -317,6 +315,12 @@ set(lisbslic3r_sources
|
||||
SLA/ReprojectPointsOnMesh.hpp
|
||||
)
|
||||
|
||||
if (APPLE)
|
||||
list(APPEND lisbslic3r_sources
|
||||
MacUtils.mm
|
||||
)
|
||||
endif ()
|
||||
|
||||
add_library(libslic3r STATIC ${lisbslic3r_sources}
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/libslic3r_version.h"
|
||||
${OpenVDBUtils_SOURCES})
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
#include <cassert>
|
||||
#include "Geometry.hpp"
|
||||
|
||||
|
||||
//BBS: Refer to ArcWelderLib for the arc fitting functions
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
//BBS: threshold used to judge collineation
|
||||
|
||||
@@ -127,6 +127,7 @@ std::vector<SurfaceFill> group_fills(const Layer &layer)
|
||||
std::vector<std::vector<const SurfaceFillParams*>> region_to_surface_params(layer.regions().size(), std::vector<const SurfaceFillParams*>());
|
||||
SurfaceFillParams params;
|
||||
bool has_internal_voids = false;
|
||||
const PrintObjectConfig& object_config = layer.object()->config();
|
||||
for (size_t region_id = 0; region_id < layer.regions().size(); ++ region_id) {
|
||||
const LayerRegion &layerm = *layer.regions()[region_id];
|
||||
region_to_surface_params[region_id].assign(layerm.fill_surfaces.size(), nullptr);
|
||||
@@ -163,7 +164,7 @@ std::vector<SurfaceFill> group_fills(const Layer &layer)
|
||||
params.bridge = is_bridge || Fill::use_bridge_flow(params.pattern);
|
||||
params.flow = params.bridge ?
|
||||
//BBS: always enable thick bridge for internal bridge
|
||||
layerm.bridging_flow(extrusion_role, (surface.is_bridge() && !surface.is_external()) || g_config_thick_bridges) :
|
||||
layerm.bridging_flow(extrusion_role, (surface.is_bridge() && !surface.is_external()) || object_config.thick_bridges) :
|
||||
layerm.flow(extrusion_role, (surface.thickness == -1) ? layer.height : surface.thickness);
|
||||
|
||||
// Calculate flow spacing for infill pattern generation.
|
||||
|
||||
@@ -80,9 +80,8 @@ void FillConcentricWGapFill::fill_surface_extrusion(const Surface* surface, cons
|
||||
|
||||
ThickPolylines polylines;
|
||||
for (ExPolygon& ex : gaps_ex_sorted) {
|
||||
//BBS: medial axis algorithm can't handle duplicated points in expolygon.
|
||||
//Use DP simplify to avoid duplicated points and accelerate medial-axis calculation as well.
|
||||
ex.douglas_peucker(SCALED_RESOLUTION);
|
||||
//BBS: Use DP simplify to avoid duplicated points and accelerate medial-axis calculation as well.
|
||||
ex.douglas_peucker(SCALED_RESOLUTION * 0.1);
|
||||
ex.medial_axis(max, min, &polylines);
|
||||
}
|
||||
|
||||
@@ -114,9 +113,8 @@ void FillConcentricWGapFill::fill_surface_extrusion(const Surface* surface, cons
|
||||
|
||||
ThickPolylines polylines;
|
||||
for (ExPolygon& ex : external_gaps_collapsed) {
|
||||
//BBS: medial axis algorithm can't handle duplicated points in expolygon.
|
||||
//Use DP simplify to avoid duplicated points and accelerate medial-axis calculation as well.
|
||||
ex.douglas_peucker(SCALED_RESOLUTION);
|
||||
//BBS: Use DP simplify to avoid duplicated points and accelerate medial-axis calculation as well.
|
||||
ex.douglas_peucker(SCALED_RESOLUTION * 0.1);
|
||||
ex.medial_axis(max, min, &polylines);
|
||||
}
|
||||
|
||||
|
||||
@@ -3156,7 +3156,7 @@ void FillMonotonicLineWGapFill::fill_surface_extrusion(const Surface* surface, c
|
||||
ThickPolylines polylines;
|
||||
for (ExPolygon& ex : gaps_ex_sorted) {
|
||||
//BBS: Use DP simplify to avoid duplicated points and accelerate medial-axis calculation as well.
|
||||
ex.douglas_peucker(SCALED_RESOLUTION);
|
||||
ex.douglas_peucker(SCALED_RESOLUTION * 0.1);
|
||||
ex.medial_axis(max, min, &polylines);
|
||||
}
|
||||
|
||||
|
||||
@@ -232,6 +232,7 @@ static constexpr const char* LOCK_ATTR = "locked";
|
||||
static constexpr const char* GCODE_FILE_ATTR = "gcode_file";
|
||||
static constexpr const char* THUMBNAIL_FILE_ATTR = "thumbnail_file";
|
||||
static constexpr const char* PATTERN_FILE_ATTR = "pattern_file";
|
||||
static constexpr const char* PATTERN_BBOX_FILE_ATTR = "pattern_bbox_file";
|
||||
static constexpr const char* OBJECT_ID_ATTR = "object_id";
|
||||
static constexpr const char* INSTANCEID_ATTR = "instance_id";
|
||||
static constexpr const char* PLATERID_ATTR = "plater_id";
|
||||
@@ -451,7 +452,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
info.id = it->first;
|
||||
info.used_m = used_filament_m;
|
||||
info.used_g = used_filament_g;
|
||||
slice_flaments_info.push_back(info);
|
||||
slice_filaments_info.push_back(info);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1464,9 +1465,10 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
plate_data_list[it->first-1]->gcode_prediction = it->second->gcode_prediction;
|
||||
plate_data_list[it->first-1]->gcode_weight = it->second->gcode_weight;
|
||||
plate_data_list[it->first-1]->toolpath_outside = it->second->toolpath_outside;
|
||||
plate_data_list[it->first-1]->slice_flaments_info = it->second->slice_flaments_info;
|
||||
plate_data_list[it->first-1]->slice_filaments_info = it->second->slice_filaments_info;
|
||||
plate_data_list[it->first-1]->thumbnail_file = (m_load_restore || it->second->thumbnail_file.empty()) ? it->second->thumbnail_file : m_backup_path + "/" + it->second->thumbnail_file;
|
||||
plate_data_list[it->first-1]->pattern_file = (m_load_restore || it->second->pattern_file.empty()) ? it->second->pattern_file : m_backup_path + "/" + it->second->pattern_file;
|
||||
plate_data_list[it->first-1]->pattern_bbox_file = (m_load_restore || it->second->pattern_bbox_file.empty()) ? it->second->pattern_bbox_file : m_backup_path + "/" + it->second->pattern_bbox_file;
|
||||
it++;
|
||||
}
|
||||
|
||||
@@ -3039,6 +3041,10 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
{
|
||||
m_curr_plater->pattern_file = value;
|
||||
}
|
||||
else if (key == PATTERN_BBOX_FILE_ATTR)
|
||||
{
|
||||
m_curr_plater->pattern_bbox_file = value;
|
||||
}
|
||||
else if (key == INSTANCEID_ATTR)
|
||||
{
|
||||
m_curr_instance.instance_id = atoi(value.c_str());
|
||||
@@ -3110,7 +3116,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
filament_info.color = color;
|
||||
filament_info.used_m = atof(used_m.c_str());
|
||||
filament_info.used_g = atof(used_g.c_str());
|
||||
m_curr_plater->slice_flaments_info.push_back(filament_info);
|
||||
m_curr_plater->slice_filaments_info.push_back(filament_info);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -5327,10 +5333,14 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << THUMBNAIL_FILE_ATTR << "\" " << VALUE_ATTR << "=\"" << std::boolalpha << thumbnail_file_in_3mf << "\"/>\n";
|
||||
}
|
||||
|
||||
if (plate_data->pattern_thumbnail.is_valid()) {
|
||||
if (!plate_data->pattern_file.empty()) {
|
||||
std::string pattern_file_in_3mf = (boost::format(PATTERN_FILE_FORMAT) % (plate_data->plate_index + 1)).str();
|
||||
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << PATTERN_FILE_ATTR << "\" " << VALUE_ATTR << "=\"" << std::boolalpha << pattern_file_in_3mf << "\"/>\n";
|
||||
}
|
||||
if (!plate_data->pattern_bbox_file.empty()) {
|
||||
std::string pattern_bbox_file_in_3mf = (boost::format(PATTERN_CONFIG_FILE_FORMAT) % (plate_data->plate_index + 1)).str();
|
||||
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << PATTERN_BBOX_FILE_ATTR << "\" " << VALUE_ATTR << "=\"" << std::boolalpha << pattern_bbox_file_in_3mf << "\"/>\n";
|
||||
}
|
||||
|
||||
if (instance_size > 0)
|
||||
{
|
||||
@@ -5430,7 +5440,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << SLICE_WEIGHT_ATTR << "\" " << VALUE_ATTR << "=\"" << plate_data->get_gcode_weight_str() << "\"/>\n";
|
||||
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << OUTSIDE_ATTR << "\" " << VALUE_ATTR << "=\"" << std::boolalpha<< plate_data->toolpath_outside << "\"/>\n";
|
||||
|
||||
for (auto it = plate_data->slice_flaments_info.begin(); it != plate_data->slice_flaments_info.end(); it++)
|
||||
for (auto it = plate_data->slice_filaments_info.begin(); it != plate_data->slice_filaments_info.end(); it++)
|
||||
{
|
||||
stream << " <" << FILAMENT_TAG << " " << FILAMENT_ID_TAG << "=\"" << std::to_string(it->id + 1) << "\" "
|
||||
<< FILAMENT_TYPE_TAG << "=\"" << it->type << "\" "
|
||||
@@ -5903,7 +5913,8 @@ private:
|
||||
break;
|
||||
case AddObject: {
|
||||
{
|
||||
_BBS_3MF_Exporter e;
|
||||
CNumericLocalesSetter locales_setter;
|
||||
_BBS_3MF_Exporter e;
|
||||
e.save_object_mesh(t.path, *t.object, (int) t.id);
|
||||
// response to delete cloned object
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ public:
|
||||
std::string _3mf_thumbnail;
|
||||
std::string _3mf_printer_thumbnail_middle;
|
||||
std::string _3mf_printer_thumbnail_small;
|
||||
|
||||
|
||||
PackingTemporaryData() {}
|
||||
};
|
||||
|
||||
@@ -63,9 +63,10 @@ struct PlateData
|
||||
ThumbnailData plate_thumbnail;
|
||||
ThumbnailData pattern_thumbnail;
|
||||
std::string pattern_file;
|
||||
std::string pattern_bbox_file;
|
||||
std::string gcode_prediction;
|
||||
std::string gcode_weight;
|
||||
std::vector<FilamentInfo> slice_flaments_info;
|
||||
std::vector<FilamentInfo> slice_filaments_info;
|
||||
bool is_sliced_valid = false;
|
||||
bool toolpath_outside {false};
|
||||
|
||||
@@ -114,7 +115,7 @@ enum class LoadStrategy
|
||||
{
|
||||
Default = 0,
|
||||
AddDefaultInstances = 1,
|
||||
CheckVersion = 2,
|
||||
CheckVersion = 2,
|
||||
LoadModel = 4,
|
||||
LoadConfig = 8,
|
||||
LoadAuxiliary = 16,
|
||||
@@ -223,7 +224,7 @@ extern bool store_bbs_3mf(StoreParams& store_params);
|
||||
|
||||
extern void release_PlateData_list(PlateDataPtrs& plate_data_list);
|
||||
|
||||
// backup & restore project
|
||||
// backup & restore project
|
||||
|
||||
extern void save_object_mesh(ModelObject& object);
|
||||
|
||||
|
||||
+32
-1
@@ -2542,6 +2542,24 @@ GCode::LayerResult GCode::process_layer(
|
||||
// Shall the support interface be printed with the active extruder, preferably with non-soluble, to avoid tool changes?
|
||||
bool interface_dontcare = object.config().support_interface_filament.value == 0;
|
||||
|
||||
// BBS: apply wiping overridden extruders
|
||||
WipingExtrusions& wiping_extrusions = const_cast<LayerTools&>(layer_tools).wiping_extrusions();
|
||||
if (support_dontcare) {
|
||||
int extruder_override = wiping_extrusions.get_support_extruder_overrides(&object);
|
||||
if (extruder_override >= 0) {
|
||||
support_extruder = extruder_override;
|
||||
support_dontcare = false;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -2609,7 +2627,16 @@ GCode::LayerResult GCode::process_layer(
|
||||
// Shall the support interface be printed with the active extruder, preferably with non-soluble, to avoid tool changes?
|
||||
bool interface_dontcare = object.config().support_interface_filament.value == 0;
|
||||
|
||||
// BBS: apply wiping overridden extruders
|
||||
WipingExtrusions& wiping_extrusions = const_cast<LayerTools&>(layer_tools).wiping_extrusions();
|
||||
if (support_dontcare) {
|
||||
int extruder_override = wiping_extrusions.get_support_extruder_overrides(&object);
|
||||
if (extruder_override >= 0) {
|
||||
support_extruder = extruder_override;
|
||||
support_dontcare = false;
|
||||
}
|
||||
}
|
||||
|
||||
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?
|
||||
@@ -2897,8 +2924,12 @@ GCode::LayerResult GCode::process_layer(
|
||||
|
||||
// BBS
|
||||
WipingExtrusions& wiping_extrusions = const_cast<LayerTools&>(layer_tools).wiping_extrusions();
|
||||
bool support_overridden = wiping_extrusions.is_support_overridden(layer.object());
|
||||
bool support_intf_overridden = wiping_extrusions.is_support_interface_overridden(layer.object());
|
||||
|
||||
ExtrusionRole support_extrusion_role = instance_to_print.object_by_extruder.support_extrusion_role;
|
||||
if (print_wipe_extrusions == 0)
|
||||
bool is_overridden = support_extrusion_role == erSupportMaterialInterface ? support_intf_overridden : support_overridden;
|
||||
if (is_overridden == (print_wipe_extrusions != 0))
|
||||
support_eec.entities = filter_by_extrusion_role(instance_to_print.object_by_extruder.support->entities, instance_to_print.object_by_extruder.support_extrusion_role);
|
||||
|
||||
for (auto& ptr : support_eec.entities)
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
#include "SpeedGenerator.hpp"
|
||||
#include "libslic3r/ExtrusionEntity.hpp"
|
||||
#include "libslic3r/Utils.hpp"
|
||||
|
||||
#define BOOST_SPIRIT_THREADSAFE
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
#include <boost/property_tree/json_parser.hpp>
|
||||
#include <boost/date_time.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
SpeedGenerator::SpeedGenerator() {
|
||||
// default is 100 speed
|
||||
for (int i = 0; i < 6; i++) {
|
||||
speed_table[i] = 100;
|
||||
}
|
||||
std::string config_file = resources_dir() + "/PerimeterSpeedConfig.json";
|
||||
std::string encoded_path = encode_path(config_file.c_str());
|
||||
boost::property_tree::read_json<boost::property_tree::ptree>(encoded_path, root);
|
||||
if (root.count("speed_table")) {
|
||||
int i = 0;
|
||||
auto array6 = root.get_child("speed_table");
|
||||
for (auto pos = array6.begin(); pos != array6.end() && i < 6; pos++, i++)
|
||||
speed_table[i] = pos->second.get_value<int>();
|
||||
}
|
||||
}
|
||||
|
||||
double SpeedGenerator::calculate_speed(const ExtrusionPath& path, double max_speed, double min_speed) {
|
||||
// limit the speed in case of F0 generated in gcode when user set 0 speed in UI
|
||||
// which cause printer stopped. 1mm/s is slow enough and can make printer not really stopped.
|
||||
max_speed = max_speed < 1 ? 1 : max_speed;
|
||||
min_speed = min_speed < 1 ? 1 : min_speed;
|
||||
// switch min and max speed if user set the max speed to be slower than min_speed
|
||||
if (max_speed < min_speed) {
|
||||
double temp = max_speed;
|
||||
max_speed = min_speed;
|
||||
min_speed = temp;
|
||||
}
|
||||
speed_table[0] = max_speed;
|
||||
|
||||
int overhang_degree = path.get_overhang_degree();
|
||||
assert(overhang_degree >= 0 && overhang_degree <= 6);
|
||||
double speed = (double)speed_table[overhang_degree];
|
||||
speed = std::max(speed, min_speed);
|
||||
speed = std::min(speed, max_speed);
|
||||
return speed;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
#ifndef libslic3r_SpeedGenerator_hpp_
|
||||
#define libslic3r_SpeedGenerator_hpp_
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
class ExtrusionPath;
|
||||
|
||||
class SpeedGenerator {
|
||||
public:
|
||||
SpeedGenerator();
|
||||
double calculate_speed(const ExtrusionPath& path, double max_speed, double min_speed);
|
||||
|
||||
private:
|
||||
boost::property_tree::ptree root;
|
||||
int speed_table[6];
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // libslic3r_SpeedGenerator_hpp_
|
||||
@@ -304,6 +304,7 @@ void ToolOrdering::collect_extruders(const PrintObject &object, const std::vecto
|
||||
layer_tools.extruders.push_back(extruder_interface);
|
||||
if (has_support || has_interface) {
|
||||
layer_tools.has_support = true;
|
||||
layer_tools.wiping_extrusions().is_support_overriddable_and_mark(role, object);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -321,6 +322,7 @@ void ToolOrdering::collect_extruders(const PrintObject &object, const std::vecto
|
||||
layer_tools.extruders.push_back(extruder_interface);
|
||||
if (has_support || has_interface) {
|
||||
layer_tools.has_support = true;
|
||||
layer_tools.wiping_extrusions().is_support_overriddable_and_mark(role, object);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -797,6 +799,19 @@ void WipingExtrusions::set_extruder_override(const ExtrusionEntity* entity, size
|
||||
copies_vector[copy_id] = extruder;
|
||||
}
|
||||
|
||||
// BBS
|
||||
void WipingExtrusions::set_support_extruder_override(const PrintObject* object, size_t copy_id, int extruder, size_t num_of_copies)
|
||||
{
|
||||
something_overridden = true;
|
||||
support_map.emplace(object, extruder);
|
||||
}
|
||||
|
||||
void WipingExtrusions::set_support_interface_extruder_override(const PrintObject* object, size_t copy_id, int extruder, size_t num_of_copies)
|
||||
{
|
||||
something_overridden = true;
|
||||
support_intf_map.emplace(object, extruder);
|
||||
}
|
||||
|
||||
// Finds first non-soluble extruder on the layer
|
||||
int WipingExtrusions::first_nonsoluble_extruder_on_layer(const PrintConfig& print_config) const
|
||||
{
|
||||
@@ -834,6 +849,25 @@ bool WipingExtrusions::is_overriddable(const ExtrusionEntityCollection& eec, con
|
||||
return true;
|
||||
}
|
||||
|
||||
// BBS
|
||||
bool WipingExtrusions::is_support_overriddable(const ExtrusionRole role, const PrintObject& object) const
|
||||
{
|
||||
if (!object.config().flush_into_support)
|
||||
return false;
|
||||
|
||||
if (role == erMixed) {
|
||||
return object.config().support_filament == 0 || object.config().support_interface_filament == 0;
|
||||
}
|
||||
else if (role == erSupportMaterial || role == erSupportTransition) {
|
||||
return object.config().support_filament == 0;
|
||||
}
|
||||
else if (role == erSupportMaterialInterface) {
|
||||
return object.config().support_interface_filament == 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Following function iterates through all extrusions on the layer, remembers those that could be used for wiping after toolchange
|
||||
// and returns volume that is left to be wiped on the wipe tower.
|
||||
float WipingExtrusions::mark_wiping_extrusions(const Print& print, unsigned int old_extruder, unsigned int new_extruder, float volume_to_wipe)
|
||||
@@ -844,6 +878,10 @@ float WipingExtrusions::mark_wiping_extrusions(const Print& print, unsigned int
|
||||
if (! this->something_overridable || volume_to_wipe <= 0. || print.config().filament_soluble.get_at(old_extruder) || print.config().filament_soluble.get_at(new_extruder))
|
||||
return std::max(0.f, volume_to_wipe); // Soluble filament cannot be wiped in a random infill, neither the filament after it
|
||||
|
||||
// BBS
|
||||
if (print.config().filament_is_support.get_at(old_extruder))
|
||||
return std::max(0.f, volume_to_wipe); // Support filament cannot be used to print support, infill, wipe_tower, etc.
|
||||
|
||||
// we will sort objects so that dedicated for wiping are at the beginning:
|
||||
ConstPrintObjectPtrs object_list = print.objects().vector();
|
||||
std::sort(object_list.begin(), object_list.end(), [](const PrintObject* a, const PrintObject* b) { return a->config().flush_into_objects; });
|
||||
@@ -876,7 +914,7 @@ float WipingExtrusions::mark_wiping_extrusions(const Print& print, unsigned int
|
||||
for (const LayerRegion *layerm : this_layer->regions()) {
|
||||
const auto ®ion = layerm->region();
|
||||
|
||||
if (!object->config().flush_into_infill && !object->config().flush_into_objects)
|
||||
if (!object->config().flush_into_infill && !object->config().flush_into_objects && !object->config().flush_into_support)
|
||||
continue;
|
||||
bool wipe_into_infill_only = !object->config().flush_into_objects && object->config().flush_into_infill;
|
||||
bool is_infill_first = print.config().wall_infill_order == WallInfillOrder::InfillInnerOuter ||
|
||||
@@ -918,6 +956,46 @@ float WipingExtrusions::mark_wiping_extrusions(const Print& print, unsigned int
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// BBS
|
||||
if (object->config().flush_into_support) {
|
||||
auto& object_config = object->config();
|
||||
const SupportLayer* this_support_layer = object->get_support_layer_at_printz(lt.print_z, EPSILON);
|
||||
const TreeSupportLayer* this_tree_support_layer = object->get_tree_support_layer_at_printz(lt.print_z, EPSILON);
|
||||
|
||||
do {
|
||||
if (this_support_layer == nullptr && this_tree_support_layer == nullptr)
|
||||
break;
|
||||
|
||||
bool support_overriddable = object_config.support_filament == 0;
|
||||
bool support_intf_overriddable = object_config.support_interface_filament == 0;
|
||||
if (!support_overriddable && !support_intf_overriddable)
|
||||
break;
|
||||
|
||||
auto& entities = this_support_layer != nullptr ? this_support_layer->support_fills.entities : this_tree_support_layer->support_fills.entities;
|
||||
if (support_overriddable && !is_support_overridden(object)) {
|
||||
set_support_extruder_override(object, copy, new_extruder, num_of_copies);
|
||||
for (const ExtrusionEntity* ee : entities) {
|
||||
if (ee->role() == erSupportMaterial || ee->role() == erSupportTransition)
|
||||
volume_to_wipe -= ee->total_volume();
|
||||
|
||||
if (volume_to_wipe <= 0.f)
|
||||
return 0.f;
|
||||
}
|
||||
}
|
||||
|
||||
if (support_intf_overriddable && !is_support_interface_overridden(object)) {
|
||||
set_support_interface_extruder_override(object, copy, new_extruder, num_of_copies);
|
||||
for (const ExtrusionEntity* ee : entities) {
|
||||
if (ee->role() == erSupportMaterialInterface)
|
||||
volume_to_wipe -= ee->total_volume();
|
||||
|
||||
if (volume_to_wipe <= 0.f)
|
||||
return 0.f;
|
||||
}
|
||||
}
|
||||
} while (0);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Some purge remains to be done on the Wipe Tower.
|
||||
@@ -1010,4 +1088,24 @@ const WipingExtrusions::ExtruderPerCopy* WipingExtrusions::get_extruder_override
|
||||
return overrides;
|
||||
}
|
||||
|
||||
// BBS
|
||||
int WipingExtrusions::get_support_extruder_overrides(const PrintObject* object)
|
||||
{
|
||||
auto iter = support_map.find(object);
|
||||
if (iter != support_map.end())
|
||||
return iter->second;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int WipingExtrusions::get_support_interface_extruder_overrides(const PrintObject* object)
|
||||
{
|
||||
auto iter = support_intf_map.find(object);
|
||||
if (iter != support_intf_map.end())
|
||||
return iter->second;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
@@ -32,6 +32,8 @@ public:
|
||||
|
||||
// This is called from GCode::process_layer - see implementation for further comments:
|
||||
const ExtruderPerCopy* get_extruder_overrides(const ExtrusionEntity* entity, int correct_extruder_id, size_t num_of_copies);
|
||||
int get_support_extruder_overrides(const PrintObject* object);
|
||||
int get_support_interface_extruder_overrides(const PrintObject* object);
|
||||
|
||||
// This function goes through all infill entities, decides which ones will be used for wiping and
|
||||
// marks them by the extruder id. Returns volume that remains to be wiped on the wipe tower:
|
||||
@@ -46,6 +48,22 @@ public:
|
||||
return out;
|
||||
}
|
||||
|
||||
// BBS
|
||||
bool is_support_overriddable(const ExtrusionRole role, const PrintObject& object) const;
|
||||
bool is_support_overriddable_and_mark(const ExtrusionRole role, const PrintObject& object) {
|
||||
bool out = this->is_support_overriddable(role, object);
|
||||
this->something_overridable |= out;
|
||||
return out;
|
||||
}
|
||||
|
||||
bool is_support_overridden(const PrintObject* object) const {
|
||||
return support_map.find(object) != support_map.end();
|
||||
}
|
||||
|
||||
bool is_support_interface_overridden(const PrintObject* object) const {
|
||||
return support_intf_map.find(object) != support_intf_map.end();
|
||||
}
|
||||
|
||||
void set_layer_tools_ptr(const LayerTools* lt) { m_layer_tools = lt; }
|
||||
|
||||
private:
|
||||
@@ -54,6 +72,9 @@ private:
|
||||
|
||||
// This function is called from mark_wiping_extrusions and sets extruder that it should be printed with (-1 .. as usual)
|
||||
void set_extruder_override(const ExtrusionEntity* entity, size_t copy_id, int extruder, size_t num_of_copies);
|
||||
// BBS
|
||||
void set_support_extruder_override(const PrintObject* object, size_t copy_id, int extruder, size_t num_of_copies);
|
||||
void set_support_interface_extruder_override(const PrintObject* object, size_t copy_id, int extruder, size_t num_of_copies);
|
||||
|
||||
// Returns true in case that entity is not printed with its usual extruder for a given copy:
|
||||
bool is_entity_overridden(const ExtrusionEntity* entity, size_t copy_id) const {
|
||||
@@ -62,6 +83,9 @@ private:
|
||||
}
|
||||
|
||||
std::map<const ExtrusionEntity*, ExtruderPerCopy> entity_map; // to keep track of who prints what
|
||||
// BBS
|
||||
std::map<const PrintObject*, int> support_map;
|
||||
std::map<const PrintObject*, int> support_intf_map;
|
||||
bool something_overridable = false;
|
||||
bool something_overridden = false;
|
||||
const LayerTools* m_layer_tools = nullptr; // so we know which LayerTools object this belongs to
|
||||
|
||||
@@ -251,6 +251,12 @@ public:
|
||||
};
|
||||
std::vector<std::pair<ExPolygon *, int>> area_groups;
|
||||
|
||||
enum OverhangType {
|
||||
Detected=0,
|
||||
Enforced
|
||||
};
|
||||
std::map<const ExPolygon *, OverhangType> overhang_types;
|
||||
|
||||
virtual bool has_extrusions() const { return !support_fills.empty(); }
|
||||
|
||||
void simplify_support_extrusion_path() { this->simplify_support_entity_collection(&support_fills);}
|
||||
|
||||
@@ -70,6 +70,7 @@ void LayerRegion::make_perimeters(const SurfaceCollection &slices, SurfaceCollec
|
||||
|
||||
const PrintConfig &print_config = this->layer()->object()->print()->config();
|
||||
const PrintRegionConfig ®ion_config = this->region().config();
|
||||
const PrintObjectConfig& object_config = this->layer()->object()->config();
|
||||
// This needs to be in sync with PrintObject::_slice() slicing_mode_normal_below_layer!
|
||||
bool spiral_mode = print_config.spiral_mode &&
|
||||
//FIXME account for raft layers.
|
||||
@@ -100,7 +101,7 @@ void LayerRegion::make_perimeters(const SurfaceCollection &slices, SurfaceCollec
|
||||
|
||||
g.layer_id = (int)this->layer()->id();
|
||||
g.ext_perimeter_flow = this->flow(frExternalPerimeter);
|
||||
g.overhang_flow = this->bridging_flow(frPerimeter, g_config_thick_bridges);
|
||||
g.overhang_flow = this->bridging_flow(frPerimeter, object_config.thick_bridges);
|
||||
g.solid_infill_flow = this->flow(frSolidInfill);
|
||||
|
||||
g.process();
|
||||
@@ -118,6 +119,9 @@ void LayerRegion::process_external_surfaces(const Layer *lower_layer, const Poly
|
||||
const bool has_infill = this->region().config().sparse_infill_density.value > 0.;
|
||||
const float margin = float(scale_(EXTERNAL_INFILL_MARGIN));
|
||||
|
||||
// BBS
|
||||
const PrintObjectConfig& object_config = this->layer()->object()->config();
|
||||
|
||||
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
||||
export_region_fill_surfaces_to_svg_debug("3_process_external_surfaces-initial");
|
||||
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
|
||||
@@ -285,7 +289,7 @@ void LayerRegion::process_external_surfaces(const Layer *lower_layer, const Poly
|
||||
// would get merged into a single one while they need different directions
|
||||
// also, supply the original expolygon instead of the grown one, because in case
|
||||
// of very thin (but still working) anchors, the grown expolygon would go beyond them
|
||||
BridgeDetector bd(initial, lower_layer->lslices, this->bridging_flow(frInfill, g_config_thick_bridges).scaled_width());
|
||||
BridgeDetector bd(initial, lower_layer->lslices, this->bridging_flow(frInfill, object_config.thick_bridges).scaled_width());
|
||||
#ifdef SLIC3R_DEBUG
|
||||
printf("Processing bridge at layer %zu:\n", this->layer()->id());
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
#ifndef __MAC_UTILS_H
|
||||
#define __MAC_UTILS_H
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
bool is_macos_support_boost_add_file_log();
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,15 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "MacUtils.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
bool is_macos_support_boost_add_file_log()
|
||||
{
|
||||
if (@available(macOS 12.0, *)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}; // namespace Slic3r
|
||||
+38
-2
@@ -2754,6 +2754,41 @@ double Model::findMaxSpeed(const ModelObject* object) {
|
||||
if (objMaxSpeed <= 0) objMaxSpeed = 250.;
|
||||
return objMaxSpeed;
|
||||
}
|
||||
|
||||
// BBS: thermal length is calculated according to the material of a volume
|
||||
double Model::getThermalLength(const ModelVolume* modelVolumePtr) {
|
||||
double thermalLength = 200.;
|
||||
auto aa = modelVolumePtr->extruder_id();
|
||||
if (Model::extruderParamsMap.find(aa) != Model::extruderParamsMap.end()) {
|
||||
if (Model::extruderParamsMap.at(aa).materialName == "ABS" ||
|
||||
Model::extruderParamsMap.at(aa).materialName == "PA-CF" ||
|
||||
Model::extruderParamsMap.at(aa).materialName == "PET-CF") {
|
||||
thermalLength = 100;
|
||||
}
|
||||
if (Model::extruderParamsMap.at(aa).materialName == "PC") {
|
||||
thermalLength = 40;
|
||||
}
|
||||
if (Model::extruderParamsMap.at(aa).materialName == "TPU") {
|
||||
thermalLength = 1000;
|
||||
}
|
||||
|
||||
}
|
||||
return thermalLength;
|
||||
}
|
||||
|
||||
// BBS: thermal length calculation for a group of volumes
|
||||
double Model::getThermalLength(const std::vector<ModelVolume*> modelVolumePtrs)
|
||||
{
|
||||
double thermalLength = 1250.;
|
||||
|
||||
for (const auto& modelVolumePtr : modelVolumePtrs) {
|
||||
if (modelVolumePtr != nullptr) {
|
||||
// the thermal length of a group is decided by the volume with shortest thermal length
|
||||
thermalLength = std::min(thermalLength, getThermalLength(modelVolumePtr));
|
||||
}
|
||||
}
|
||||
return thermalLength;
|
||||
}
|
||||
// max printing speed, difference in bed temperature and envirument temperature and bed adhension coefficients are considered
|
||||
double ModelInstance::get_auto_brim_width(double deltaT, double adhension) const
|
||||
{
|
||||
@@ -2763,9 +2798,10 @@ double ModelInstance::get_auto_brim_width(double deltaT, double adhension) const
|
||||
auto bbox_size = transform_bounding_box(raw_bbox).size();
|
||||
double height_to_area = std::max(bbox_size(2) / (bbox_size(0) * bbox_size(0) * bbox_size(1)),
|
||||
bbox_size(2) / (bbox_size(1) * bbox_size(1) * bbox_size(0)));
|
||||
double thermalLength = std::max(bbox_size(0), bbox_size(1));
|
||||
double thermalLength = sqrt(bbox_size(0)* bbox_size(0) + bbox_size(1)* bbox_size(1));
|
||||
double thermalLengthRef = Model::getThermalLength(object->volumes);
|
||||
|
||||
double brim_width = adhension * std::min(std::min(std::max(height_to_area * 200 * maxSpeed/200, (deltaT-30)/75 * thermalLength * 0.15), 20.), 1.5 * thermalLength);
|
||||
double brim_width = adhension * std::min(std::min(std::max(height_to_area * 200 * maxSpeed/200, thermalLength * 8. / thermalLengthRef * std::min(bbox_size(2), 30.) / 30.), 20.), 1.5 * thermalLength);
|
||||
// small brims are omitted
|
||||
if (brim_width < 5 && brim_width < 1.5 * thermalLength)
|
||||
brim_width = 0;
|
||||
|
||||
@@ -1274,6 +1274,9 @@ public:
|
||||
ImportStepProgressFn stepFn = nullptr, StepIsUtf8Fn stepIsUtf8Fn = nullptr, BBLProject* project = nullptr);
|
||||
// BBS
|
||||
static double findMaxSpeed(const ModelObject* object);
|
||||
static double getThermalLength(const ModelVolume* modelVolumePtr);
|
||||
static double getThermalLength(const std::vector<ModelVolume*> modelVolumePtrs);
|
||||
|
||||
// BBS: backup
|
||||
static Model read_from_archive(
|
||||
const std::string& input_file,
|
||||
|
||||
@@ -553,58 +553,33 @@ void PerimeterGenerator::process()
|
||||
offset_top_surface = 0;
|
||||
//don't takes into account too thin areas
|
||||
double min_width_top_surface = std::max(double(ext_perimeter_spacing / 2 + 10), 1.0 * (double(perimeter_width)));
|
||||
//make thin upper surfaces disapear with -+offset_top_surface
|
||||
ExPolygons grown_upper_slices;
|
||||
//do offset2 per island, to avoid big blob merging
|
||||
//remove polygon too thin (but don't mess with holes)
|
||||
for (const ExPolygon& expoly_to_grow : *this->upper_slices) {
|
||||
//only offset the contour, as it can merge holes
|
||||
Polygons contour = offset2({ ExPolygon(expoly_to_grow.contour) }, -offset_top_surface, offset_top_surface + min_width_top_surface);
|
||||
if (!contour.empty()) {
|
||||
if (expoly_to_grow.holes.empty()) {
|
||||
for (Polygon& p : contour)
|
||||
grown_upper_slices.push_back(ExPolygon{ p });
|
||||
}
|
||||
else {
|
||||
Polygons holes = expoly_to_grow.holes;
|
||||
for (Polygon& h : holes)
|
||||
h.reverse();
|
||||
holes = offset(holes, -min_width_top_surface);
|
||||
for (ExPolygon p : diff_ex(contour, holes))
|
||||
grown_upper_slices.push_back(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
grown_upper_slices = union_ex(grown_upper_slices);
|
||||
ExPolygons grown_upper_slices = offset_ex(*this->upper_slices, min_width_top_surface);
|
||||
//set the clip to a virtual "second perimeter"
|
||||
fill_clip = offset_ex(last, -double(ext_perimeter_spacing));
|
||||
auto fill_clip_old = fill_clip;
|
||||
// get the real top surface
|
||||
const ExPolygons top_grown_polygons = diff_ex(last, grown_upper_slices, ApplySafetyOffset::Yes);
|
||||
ExPolygons top_polygons = diff_ex(last, grown_upper_slices, ApplySafetyOffset::Yes);
|
||||
|
||||
//get the not-top surface, from the "real top" but enlarged by external_infill_margin (and the min_width_top_surface we removed a bit before)
|
||||
//also remove the ext_perimeter_spacing/2 width because we are faking the external periemter, and we will remove ext_perimeter_spacing2
|
||||
const ExPolygons inner_polygons = diff_ex(last,
|
||||
offset_ex(top_grown_polygons, offset_top_surface + min_width_top_surface - double(ext_perimeter_spacing / 2)),
|
||||
ApplySafetyOffset::Yes);
|
||||
ExPolygons inner_polygons = diff_ex(last,
|
||||
offset_ex(top_polygons, offset_top_surface + min_width_top_surface - double(ext_perimeter_spacing / 2)),
|
||||
ApplySafetyOffset::Yes);
|
||||
// get the enlarged top surface, by using inner_polygons instead of upper_slices, and clip it for it to be exactly the polygons to fill.
|
||||
const ExPolygons top_polygons = diff_ex(fill_clip, inner_polygons, ApplySafetyOffset::Yes);
|
||||
top_polygons = diff_ex(fill_clip, inner_polygons, ApplySafetyOffset::Yes);
|
||||
// increase by half peri the inner space to fill the frontier between last and stored.
|
||||
top_fills = union_ex(top_fills, top_polygons);
|
||||
//set the clip to the external wall but go back inside by infill_extrusion_width/2 to be sure the extrusion won't go outside even with a 100% overlap.
|
||||
double infill_spacing_unscaled = this->config->sparse_infill_line_width.value;
|
||||
//if (infill_spacing_unscaled == 0) infill_spacing_unscaled = Flow::auto_extrusion_width(frInfill, nozzle_diameter);
|
||||
fill_clip = offset_ex(last, double(ext_perimeter_spacing / 2) - scale_(infill_spacing_unscaled / 2));
|
||||
last = intersection_ex(inner_polygons, last);
|
||||
//{
|
||||
// std::stringstream stri;
|
||||
// stri << this->layer->id() << "_1_"<< i <<"_only_one_peri"<< ".svg";
|
||||
// SVG svg(stri.str());
|
||||
// svg.draw(to_polylines(oldLast), "orange");
|
||||
// svg.draw(to_polylines(fill_clip), "purple");
|
||||
// svg.draw(to_polylines(top_fills), "green");
|
||||
// svg.draw(to_polylines(inner_polygons), "yellow");
|
||||
// svg.draw(to_polylines(top_polygons), "cyan");
|
||||
// svg.draw(to_polylines(oldLast), "orange");
|
||||
// svg.draw(to_polylines(last), "red");
|
||||
// svg.draw(to_polylines(fill_clip_old), "green");
|
||||
// svg.Close();
|
||||
//}
|
||||
}
|
||||
@@ -700,9 +675,8 @@ void PerimeterGenerator::process()
|
||||
offset2_ex(gaps, - float(max / 2.), float(max / 2. + ClipperSafetyOffset)));
|
||||
ThickPolylines polylines;
|
||||
for (ExPolygon& ex : gaps_ex) {
|
||||
//BBS: medial axis algorithm can't handle duplicated points in expolygon.
|
||||
//Use DP simplify to avoid duplicated points and accelerate medial-axis calculation as well.
|
||||
ex.douglas_peucker(SCALED_RESOLUTION);
|
||||
//BBS: Use DP simplify to avoid duplicated points and accelerate medial-axis calculation as well.
|
||||
ex.douglas_peucker(surface_simplify_resolution);
|
||||
ex.medial_axis(max, min, &polylines);
|
||||
}
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ public:
|
||||
overhang_flow(flow), solid_infill_flow(flow),
|
||||
config(config), object_config(object_config), print_config(print_config),
|
||||
m_spiral_vase(spiral_mode),
|
||||
m_scaled_resolution(scaled<double>(print_config->resolution.value)),
|
||||
m_scaled_resolution(scaled<double>(print_config->resolution.value > EPSILON ? print_config->resolution.value : EPSILON)),
|
||||
loops(loops), gap_fill(gap_fill), fill_surfaces(fill_surfaces),
|
||||
m_ext_mm3_per_mm(-1), m_mm3_per_mm(-1), m_mm3_per_mm_overhang(-1), m_ext_mm3_per_mm_smaller_width(-1)
|
||||
{}
|
||||
|
||||
@@ -311,6 +311,54 @@ bool Polyline::is_straight() const
|
||||
return true;
|
||||
}
|
||||
|
||||
void Polyline::append(const Polyline &src)
|
||||
{
|
||||
if (!src.is_valid()) return;
|
||||
|
||||
if (this->points.empty()) {
|
||||
this->points = src.points;
|
||||
this->fitting_result = src.fitting_result;
|
||||
} else {
|
||||
//BBS: append the first point to create connection first, update the fitting date as well
|
||||
this->append(src.points[0]);
|
||||
//BBS: append a polyline which has fitting data to a polyline without fitting data.
|
||||
//Then create a fake fitting data first, so that we can keep the fitting data in last polyline
|
||||
if (this->fitting_result.empty() &&
|
||||
!src.fitting_result.empty()) {
|
||||
this->fitting_result.emplace_back(PathFittingData{ 0, this->points.size() - 1, EMovePathType::Linear_move, ArcSegment() });
|
||||
}
|
||||
//BBS: then append the remain points
|
||||
MultiPoint::append(src.points.begin() + 1, src.points.end());
|
||||
//BBS: finally append the fitting data
|
||||
append_fitting_result_after_append_polyline(src);
|
||||
}
|
||||
}
|
||||
|
||||
void Polyline::append(Polyline &&src)
|
||||
{
|
||||
if (!src.is_valid()) return;
|
||||
|
||||
if (this->points.empty()) {
|
||||
this->points = std::move(src.points);
|
||||
this->fitting_result = std::move(src.fitting_result);
|
||||
} else {
|
||||
//BBS: append the first point to create connection first, update the fitting date as well
|
||||
this->append(src.points[0]);
|
||||
//BBS: append a polyline which has fitting data to a polyline without fitting data.
|
||||
//Then create a fake fitting data first, so that we can keep the fitting data in last polyline
|
||||
if (this->fitting_result.empty() &&
|
||||
!src.fitting_result.empty()) {
|
||||
this->fitting_result.emplace_back(PathFittingData{ 0, this->points.size() - 1, EMovePathType::Linear_move, ArcSegment() });
|
||||
}
|
||||
//BBS: then append the remain points
|
||||
MultiPoint::append(src.points.begin() + 1, src.points.end());
|
||||
//BBS: finally append the fitting data
|
||||
append_fitting_result_after_append_polyline(src);
|
||||
src.points.clear();
|
||||
src.fitting_result.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void Polyline::append_fitting_result_after_append_points() {
|
||||
if (!fitting_result.empty()) {
|
||||
if (fitting_result.back().is_linear_move()) {
|
||||
@@ -326,14 +374,6 @@ void Polyline::append_fitting_result_after_append_points() {
|
||||
|
||||
void Polyline::append_fitting_result_after_append_polyline(const Polyline& src)
|
||||
{
|
||||
//BBS: append a polyline which has fitting data to a polyline without fitting data.
|
||||
//Then create a fake fitting data first, so that we can keep the fitting data in last polyline
|
||||
if (this->fitting_result.empty() &&
|
||||
!src.fitting_result.empty()) {
|
||||
if (!this->points.empty())
|
||||
this->fitting_result.emplace_back(PathFittingData{ 0, this->size() - 1, EMovePathType::Linear_move, ArcSegment() });
|
||||
}
|
||||
|
||||
if (!this->fitting_result.empty()) {
|
||||
//BBS: offset and save the fitting_result from src polyline
|
||||
if (!src.fitting_result.empty()) {
|
||||
@@ -346,7 +386,7 @@ void Polyline::append_fitting_result_after_append_polyline(const Polyline& src)
|
||||
}
|
||||
} else {
|
||||
//BBS: the append polyline has no fitting data, then append as linear move directly
|
||||
size_t new_start = fitting_result.back().end_point_index;
|
||||
size_t new_start = this->fitting_result.back().end_point_index;
|
||||
size_t new_end = this->size() - 1;
|
||||
if (new_start != new_end)
|
||||
this->fitting_result.emplace_back(PathFittingData{ new_start, new_end, EMovePathType::Linear_move, ArcSegment() });
|
||||
|
||||
@@ -99,41 +99,8 @@ public:
|
||||
MultiPoint::append(std::move(src));
|
||||
append_fitting_result_after_append_points();
|
||||
}
|
||||
void append(const Polyline &src)
|
||||
{
|
||||
if (!src.is_valid()) return;
|
||||
|
||||
if (this->points.empty()) {
|
||||
this->points = src.points;
|
||||
this->fitting_result = src.fitting_result;
|
||||
} else {
|
||||
//BBS: append the first point to create connection first, update the fitting date as well
|
||||
this->append(src.points[0]);
|
||||
//BBS: then append the remain points
|
||||
MultiPoint::append(src.points.begin() + 1, src.points.end());
|
||||
//BBS: finally append the fitting data
|
||||
append_fitting_result_after_append_polyline(src);
|
||||
}
|
||||
}
|
||||
|
||||
void append(Polyline &&src)
|
||||
{
|
||||
if (!src.is_valid()) return;
|
||||
|
||||
if (this->points.empty()) {
|
||||
this->points = std::move(src.points);
|
||||
this->fitting_result = std::move(src.fitting_result);
|
||||
} else {
|
||||
//BBS: append the first point to create connection first, update the fitting date as well
|
||||
this->append(src.points[0]);
|
||||
//BBS: then append the remain points
|
||||
MultiPoint::append(src.points.begin() + 1, src.points.end());
|
||||
//BBS: finally append the fitting data
|
||||
append_fitting_result_after_append_polyline(src);
|
||||
src.points.clear();
|
||||
src.fitting_result.clear();
|
||||
}
|
||||
}
|
||||
void append(const Polyline& src);
|
||||
void append(Polyline&& src);
|
||||
|
||||
const Point& last_point() const override { return this->points.back(); }
|
||||
const Point& leftmost_point() const;
|
||||
|
||||
@@ -666,7 +666,7 @@ static std::vector<std::string> s_Preset_print_options {
|
||||
//"independent_support_layer_height",
|
||||
"support_angle", "support_interface_top_layers", "support_interface_bottom_layers",
|
||||
"support_interface_pattern", "support_interface_spacing", "support_interface_loop_pattern",
|
||||
"support_top_z_distance", "support_on_build_plate_only", "bridge_no_support","max_bridge_length", "print_sequence",
|
||||
"support_top_z_distance", "support_on_build_plate_only", "bridge_no_support", "thick_bridges", "max_bridge_length", "print_sequence",
|
||||
"filename_format", "wall_filament",
|
||||
"sparse_infill_filament", "solid_infill_filament", "support_filament", "support_interface_filament",
|
||||
"ooze_prevention", "standby_temperature_delta", "interface_shells", "line_width", "initial_layer_line_width",
|
||||
@@ -675,7 +675,7 @@ static std::vector<std::string> s_Preset_print_options {
|
||||
"elefant_foot_compensation", "xy_contour_compensation", "xy_hole_compensation", "resolution", "enable_prime_tower",
|
||||
"prime_tower_width", "prime_tower_brim_width", "prime_volume",
|
||||
"wipe_tower_no_sparse_layers", "compatible_printers", "compatible_printers_condition", "inherits",
|
||||
"flush_into_infill", "flush_into_objects",
|
||||
"flush_into_infill", "flush_into_objects", "flush_into_support",
|
||||
// BBS
|
||||
"tree_support_branch_angle", "tree_support_with_infill", "tree_support_wall_count", "tree_support_branch_distance",
|
||||
"tree_support_branch_diameter",
|
||||
|
||||
@@ -181,6 +181,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|
||||
|| opt_key == "flush_volumes_matrix"
|
||||
|| opt_key == "prime_volume"
|
||||
|| opt_key == "flush_into_infill"
|
||||
|| opt_key == "flush_into_support"
|
||||
|| opt_key == "initial_layer_infill_speed"
|
||||
|| opt_key == "travel_speed"
|
||||
|| opt_key == "travel_speed_z"
|
||||
|
||||
@@ -165,7 +165,6 @@ class ConstSupportLayerPtrsAdaptor : public ConstVectorOfPtrsAdaptor<SupportLaye
|
||||
|
||||
// BBS
|
||||
typedef std::vector<TreeSupportLayer*> TreeSupportLayerPtrs;
|
||||
typedef std::vector<const TreeSupportLayer*> ConstTreeSupportLayerPtrs;
|
||||
class ConstTreeSupportLayerPtrsAdaptor : public ConstVectorOfPtrsAdaptor<TreeSupportLayer> {
|
||||
friend PrintObject;
|
||||
ConstTreeSupportLayerPtrsAdaptor(const TreeSupportLayerPtrs* data) : ConstVectorOfPtrsAdaptor<TreeSupportLayer>(data) {}
|
||||
@@ -300,7 +299,8 @@ public:
|
||||
const Layer* current_layer,
|
||||
float extrusion_width,
|
||||
PolysType* overhang_regions,
|
||||
float max_bridge_length = scale_(10));
|
||||
float max_bridge_length = scale_(10),
|
||||
bool break_bridge=false);
|
||||
|
||||
// Bounding box is used to align the object infill patterns, and to calculate attractor for the rear seam.
|
||||
// The bounding box may not be quite snug.
|
||||
@@ -340,6 +340,10 @@ public:
|
||||
// Get a layer approximately at print_z.
|
||||
const Layer* get_layer_at_printz(coordf_t print_z, coordf_t epsilon) const;
|
||||
Layer* get_layer_at_printz(coordf_t print_z, coordf_t epsilon);
|
||||
// BBS
|
||||
const Layer* get_layer_at_bottomz(coordf_t bottom_z, coordf_t epsilon) const;
|
||||
Layer* get_layer_at_bottomz(coordf_t bottom_z, coordf_t epsilon);
|
||||
|
||||
// Get the first layer approximately bellow print_z.
|
||||
const Layer* get_first_layer_bellow_printz(coordf_t print_z, coordf_t epsilon) const;
|
||||
|
||||
@@ -354,6 +358,7 @@ public:
|
||||
void clear_tree_support_layers();
|
||||
size_t tree_support_layer_count() const { return m_tree_support_layers.size(); }
|
||||
std::shared_ptr<TreeSupportData> alloc_tree_support_preview_cache();
|
||||
void clear_tree_support_preview_cache() { m_tree_support_preview_cache.reset(); }
|
||||
|
||||
size_t support_layer_count() const { return m_support_layers.size(); }
|
||||
void clear_support_layers();
|
||||
|
||||
@@ -686,7 +686,15 @@ void PrintConfigDef::init_fff_params()
|
||||
def->tooltip = L("Don't support the whole bridge area which make support very large. "
|
||||
"Bridge usually can be printing directly without support if not very long");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionBool(true));
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("thick_bridges", coBool);
|
||||
def->label = L("Thick bridges");
|
||||
def->category = L("Layers and Perimeters");
|
||||
def->tooltip = L("If enabled, bridges are more reliable, can bridge longer distances, but may look worse. "
|
||||
"If disabled, bridges look better but are reliable just for shorter bridged distances.");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("max_bridge_length", coFloat);
|
||||
def->label = L("Max bridge length");
|
||||
@@ -722,10 +730,7 @@ void PrintConfigDef::init_fff_params()
|
||||
def->enum_keys_map = &ConfigOptionEnum<InfillPattern>::get_enum_values();
|
||||
def->enum_values.push_back("concentric");
|
||||
def->enum_values.push_back("zig-zag");
|
||||
#if !BBL_RELEASE_TO_PUBLIC
|
||||
def->enum_values.push_back("monotonic");
|
||||
#endif
|
||||
//BBS: use monotonicline pattern to replace monotonic for top and bottom surface
|
||||
def->enum_values.push_back("monotonicline");
|
||||
//def->enum_values.push_back("alignedrectilinear");
|
||||
//def->enum_values.push_back("hilbertcurve");
|
||||
@@ -733,9 +738,7 @@ void PrintConfigDef::init_fff_params()
|
||||
//def->enum_values.push_back("octagramspiral");
|
||||
def->enum_labels.push_back(L("Concentric"));
|
||||
def->enum_labels.push_back(L("Zig zag"));
|
||||
#if !BBL_RELEASE_TO_PUBLIC
|
||||
def->enum_labels.push_back(L("Monotonic"));
|
||||
#endif
|
||||
def->enum_labels.push_back(L("Monotonic line"));
|
||||
//def->enum_labels.push_back(L("Aligned Rectilinear"));
|
||||
//def->enum_labels.push_back(L("Hilbert Curve"));
|
||||
@@ -1627,8 +1630,10 @@ void PrintConfigDef::init_fff_params()
|
||||
|
||||
def = this->add("reduce_infill_retraction", coBool);
|
||||
def->label = L("Reduce infill retraction");
|
||||
def->tooltip = L("Don't retract when the travel is in infill area absolutely. That means the oozing can't been seen");
|
||||
def->mode = comDevelop;
|
||||
def->tooltip = L("Don't retract when the travel is in infill area absolutely. That means the oozing can't been seen. "
|
||||
"This can reduce times of retraction for complex model and save printing time, but make slicing and "
|
||||
"G-code generating slower");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionBool(true));
|
||||
|
||||
def = this->add("ooze_prevention", coBool);
|
||||
@@ -2545,6 +2550,13 @@ void PrintConfigDef::init_fff_params()
|
||||
"If the walls are printed with transparent filament, the mixed color infill will be seen outside");
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("flush_into_support", coBool);
|
||||
def->category = L("Flush options");
|
||||
def->label = L("Flush into objects' support");
|
||||
def->tooltip = L("Purging after filament change will be done inside objects' support. "
|
||||
"This may lower the amount of waste and decrease the print time");
|
||||
def->set_default_value(new ConfigOptionBool(true));
|
||||
|
||||
def = this->add("flush_into_objects", coBool);
|
||||
def->category = L("Flush options");
|
||||
def->label = L("Flush into this object");
|
||||
@@ -3345,12 +3357,6 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va
|
||||
//But now these key-value must be absolute value.
|
||||
//Reset to default value by erasing these key to avoid parsing error.
|
||||
opt_key = "";
|
||||
} else if (opt_key == "top_surface_pattern" || opt_key == "bottom_surface_pattern") {
|
||||
#if BBL_RELEASE_TO_PUBLIC
|
||||
//BBS: replace monotonic pattern to be monotonicline for top and bottom surface
|
||||
if (value == "monotonic")
|
||||
value = "monotonicline";
|
||||
#endif
|
||||
} else if (opt_key == "filament_type" && value == "PA-CF") {
|
||||
value == "PA";
|
||||
} else if (opt_key == "inherits_cummulative") {
|
||||
@@ -3372,7 +3378,7 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va
|
||||
, "max_volumetric_extrusion_rate_slope_positive", "max_volumetric_extrusion_rate_slope_negative"
|
||||
#endif /* HAS_PRESSURE_EQUALIZER */
|
||||
// BBS
|
||||
, "thick_bridges","support_sharp_tails","remove_small_overhangs", "support_with_sheath",
|
||||
, "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",
|
||||
|
||||
@@ -596,6 +596,7 @@ PRINT_CONFIG_CLASS_DEFINE(
|
||||
((ConfigOptionEnum<SupportMaterialStyle>, support_style))
|
||||
// BBS
|
||||
((ConfigOptionBool, independent_support_layer_height))
|
||||
((ConfigOptionBool, thick_bridges))
|
||||
// Overhang angle threshold.
|
||||
((ConfigOptionInt, support_threshold_angle))
|
||||
((ConfigOptionFloat, support_object_xy_distance))
|
||||
@@ -604,6 +605,7 @@ PRINT_CONFIG_CLASS_DEFINE(
|
||||
((ConfigOptionBool, flush_into_objects))
|
||||
// BBS
|
||||
((ConfigOptionBool, flush_into_infill))
|
||||
((ConfigOptionBool, flush_into_support))
|
||||
// BBS
|
||||
((ConfigOptionFloat, tree_support_branch_distance))
|
||||
((ConfigOptionFloat, tree_support_branch_diameter))
|
||||
|
||||
@@ -566,7 +566,7 @@ void PrintObject::clear_tree_support_layers()
|
||||
|
||||
std::shared_ptr<TreeSupportData> PrintObject::alloc_tree_support_preview_cache()
|
||||
{
|
||||
if (m_tree_support_preview_cache == nullptr) {
|
||||
if (!m_tree_support_preview_cache) {
|
||||
const coordf_t layer_height = m_config.layer_height.value;
|
||||
const coordf_t xy_distance = m_config.support_object_xy_distance.value;
|
||||
const double angle = m_config.tree_support_branch_angle.value * M_PI / 180.;
|
||||
@@ -787,7 +787,8 @@ bool PrintObject::invalidate_state_by_config_options(
|
||||
invalidated |= m_print->invalidate_step(psGCodeExport);
|
||||
} else if (
|
||||
opt_key == "flush_into_infill"
|
||||
|| opt_key == "flush_into_objects") {
|
||||
|| opt_key == "flush_into_objects"
|
||||
|| opt_key == "flush_into_support") {
|
||||
invalidated |= m_print->invalidate_step(psWipeTower);
|
||||
invalidated |= m_print->invalidate_step(psGCodeExport);
|
||||
} else {
|
||||
@@ -827,7 +828,7 @@ bool PrintObject::invalidate_step(PrintObjectStep step)
|
||||
}
|
||||
|
||||
// Wipe tower depends on the ordering of extruders, which in turn depends on everything.
|
||||
// It also decides about what the flush_into_infill / wipe_into_object features will do,
|
||||
// It also decides about what the flush_into_infill / wipe_into_object / flush_into_support features will do,
|
||||
// and that too depends on many of the settings.
|
||||
invalidated |= m_print->invalidate_step(psWipeTower);
|
||||
// Invalidate G-code export in any case.
|
||||
@@ -2297,7 +2298,8 @@ void PrintObject::remove_bridges_from_contacts(
|
||||
const Layer* current_layer,
|
||||
float extrusion_width,
|
||||
PolysType* overhang_regions,
|
||||
float max_bridge_length)
|
||||
float max_bridge_length,
|
||||
bool break_bridge)
|
||||
{
|
||||
// Extrusion width accounts for the roundings of the extrudates.
|
||||
// It is the maximum widh of the extrudate.
|
||||
@@ -2305,6 +2307,7 @@ void PrintObject::remove_bridges_from_contacts(
|
||||
Lines overhang_perimeters = to_lines(*overhang_regions);
|
||||
auto layer_regions = current_layer->regions();
|
||||
Polygons lower_layer_polygons = to_polygons(lower_layer->lslices);
|
||||
const PrintObjectConfig& object_config = current_layer->object()->config();
|
||||
|
||||
Polygons all_bridges;
|
||||
for (LayerRegion* layerm : layer_regions)
|
||||
@@ -2321,7 +2324,7 @@ void PrintObject::remove_bridges_from_contacts(
|
||||
// since we're dealing with bridges, we can't assume width is larger than spacing,
|
||||
// so we take the largest value and also apply safety offset to be ensure no gaps
|
||||
// are left in between
|
||||
Flow bridge_flow = layerm->bridging_flow(frPerimeter, g_config_thick_bridges);
|
||||
Flow bridge_flow = layerm->bridging_flow(frPerimeter, object_config.thick_bridges);
|
||||
float w = float(std::max(bridge_flow.scaled_width(), bridge_flow.scaled_spacing()));
|
||||
for (Polyline& polyline : overhang_perimeters)
|
||||
if (polyline.is_straight()) {
|
||||
@@ -2338,12 +2341,16 @@ void PrintObject::remove_bridges_from_contacts(
|
||||
if (supported[0] && supported[1]) {
|
||||
Polylines lines;
|
||||
if (polyline.length() > max_bridge_length + 10) {
|
||||
// equally divide the polyline
|
||||
float len = polyline.length() / ceil(polyline.length() / max_bridge_length);
|
||||
lines = polyline.equally_spaced_lines(len);
|
||||
for (auto& line : lines) {
|
||||
line.clip_start(fw);
|
||||
line.clip_end(fw);
|
||||
if (break_bridge) {
|
||||
// equally divide the polyline
|
||||
float len = polyline.length() / ceil(polyline.length() / max_bridge_length);
|
||||
lines = polyline.equally_spaced_lines(len);
|
||||
for (auto& line : lines) {
|
||||
if (line.is_valid())
|
||||
line.clip_start(fw);
|
||||
if (line.is_valid())
|
||||
line.clip_end(fw);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -2357,8 +2364,52 @@ void PrintObject::remove_bridges_from_contacts(
|
||||
// remove the entire bridges and only support the unsupported edges
|
||||
//FIXME the brided regions are already collected as layerm->bridged. Use it?
|
||||
for (const Surface& surface : layerm->fill_surfaces.surfaces)
|
||||
if (surface.surface_type == stBottomBridge && surface.bridge_angle != -1)
|
||||
polygons_append(bridges, surface.expolygon);
|
||||
if (surface.surface_type == stBottomBridge && surface.bridge_angle != -1) {
|
||||
auto bbox = get_extents(surface.expolygon);
|
||||
auto bbox_size = bbox.size();
|
||||
if (bbox_size[0] < max_bridge_length || bbox_size[1] < max_bridge_length)
|
||||
polygons_append(bridges, surface.expolygon);
|
||||
else {
|
||||
if (break_bridge) {
|
||||
Polygons holes;
|
||||
int x0 = bbox.min.x();
|
||||
int x1 = bbox.max.x();
|
||||
int y0 = bbox.min.y();
|
||||
int y1 = bbox.max.y();
|
||||
const int grid_lw = int(w/2); // grid line width
|
||||
|
||||
#if 1
|
||||
if (fabs(surface.bridge_angle-0)<fabs(surface.bridge_angle-M_PI_2)) {
|
||||
int step = bbox_size(0) / ceil(bbox_size(0) / max_bridge_length);
|
||||
for (int x = x0 + step; x < x1; x += step) {
|
||||
Polygon poly;
|
||||
poly.points = {Point(x - grid_lw, y0), Point(x + grid_lw, y0), Point(x + grid_lw, y1), Point(x - grid_lw, y1)};
|
||||
holes.emplace_back(poly);
|
||||
}
|
||||
} else {
|
||||
int step = bbox_size(1) / ceil(bbox_size(1) / max_bridge_length);
|
||||
for (int y = y0 + step; y < y1; y += step) {
|
||||
Polygon poly;
|
||||
poly.points = {Point(x0, y - grid_lw), Point(x0, y + grid_lw), Point(x1, y + grid_lw), Point(x1, y - grid_lw)};
|
||||
holes.emplace_back(poly);
|
||||
}
|
||||
}
|
||||
#else
|
||||
int stepx = bbox_size(0) / ceil(bbox_size(0) / max_bridge_length);
|
||||
int stepy = bbox_size(1) / ceil(bbox_size(1) / max_bridge_length);
|
||||
for (int x = x0 + stepx; x < x1; x += stepx)
|
||||
for (int y = y0 + stepy; y < y1; y += stepy) {
|
||||
Polygon poly;
|
||||
poly.points = {Point(x-grid_lw, y - grid_lw), Point(x+grid_lw, y - grid_lw), Point(x+grid_lw, y + grid_lw), Point(x-grid_lw, y + grid_lw)};
|
||||
holes.emplace_back(poly);
|
||||
}
|
||||
|
||||
#endif
|
||||
auto expoly = diff_ex(surface.expolygon, holes);
|
||||
polygons_append(bridges, expoly);
|
||||
}
|
||||
}
|
||||
}
|
||||
//FIXME add the gap filled areas. Extrude the gaps with a bridge flow?
|
||||
// Remove the unsupported ends of the bridges from the bridged areas.
|
||||
//FIXME add supports at regular intervals to support long bridges!
|
||||
@@ -2380,13 +2431,13 @@ template void PrintObject::remove_bridges_from_contacts<ExPolygons>(
|
||||
const Layer* current_layer,
|
||||
float extrusion_width,
|
||||
ExPolygons* overhang_regions,
|
||||
float max_bridge_length);
|
||||
float max_bridge_length, bool break_bridge);
|
||||
template void PrintObject::remove_bridges_from_contacts<Polygons>(
|
||||
const Layer* lower_layer,
|
||||
const Layer* current_layer,
|
||||
float extrusion_width,
|
||||
Polygons* overhang_regions,
|
||||
float max_bridge_length);
|
||||
float max_bridge_length, bool break_bridge);
|
||||
|
||||
|
||||
bool PrintObject::is_support_necessary()
|
||||
@@ -2721,4 +2772,20 @@ const Layer *PrintObject::get_first_layer_bellow_printz(coordf_t print_z, coordf
|
||||
return (it == m_layers.begin()) ? nullptr : *(--it);
|
||||
}
|
||||
|
||||
// BBS
|
||||
const Layer* PrintObject::get_layer_at_bottomz(coordf_t bottom_z, coordf_t epsilon) const {
|
||||
coordf_t limit_upper = bottom_z + epsilon;
|
||||
coordf_t limit_lower = bottom_z - epsilon;
|
||||
|
||||
for (const Layer* layer : m_layers) {
|
||||
if (layer->bottom_z() > limit_lower)
|
||||
return layer->bottom_z() < limit_upper ? layer : nullptr;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Layer* PrintObject::get_layer_at_bottomz(coordf_t bottom_z, coordf_t epsilon) { return const_cast<Layer*>(std::as_const(*this).get_layer_at_bottomz(bottom_z, epsilon)); }
|
||||
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
@@ -446,6 +446,9 @@ static std::vector<std::vector<ExPolygons>> slices_to_regions(
|
||||
std::string fix_slicing_errors(PrintObject* object, LayerPtrs &layers, const std::function<void()> &throw_if_canceled)
|
||||
{
|
||||
std::string error_msg;//BBS
|
||||
|
||||
if (layers.size() == 0) return error_msg;
|
||||
|
||||
// Collect layers with slicing errors.
|
||||
// These layers will be fixed in parallel.
|
||||
std::vector<size_t> buggy_layers;
|
||||
@@ -740,24 +743,39 @@ static inline void apply_mm_segmentation(PrintObject &print_object, ThrowOnCance
|
||||
bool doesVolumeIntersect(VolumeSlices& vs1, VolumeSlices& vs2)
|
||||
{
|
||||
if (vs1.volume_id == vs2.volume_id) return true;
|
||||
if (vs1.slices.size() != vs1.slices.size()) return false;
|
||||
if (vs1.slices.size() != vs2.slices.size()) return false;
|
||||
|
||||
double offsetValue = 0.4 / SCALING_FACTOR;
|
||||
for (int i = 0; i != vs1.slices.size(); ++i) {
|
||||
auto eps1 = offset_ex(vs1.slices[i], offsetValue);
|
||||
auto eps2 = offset_ex(vs2.slices[i], offsetValue);
|
||||
|
||||
if (!intersection_ex(eps1, eps2).empty()) return true;
|
||||
if (vs1.slices[i].empty()) continue;
|
||||
if (!vs2.slices[i].empty() && !intersection_ex(vs1.slices[i], vs2.slices[i]).empty()) return true;
|
||||
if (i + 1 != vs2.slices.size() && !vs2.slices[i + 1].empty()) {
|
||||
if (!intersection_ex(vs1.slices[i], vs2.slices[i + 1]).empty()) return true;
|
||||
}
|
||||
if (i - 1 >= 0 && !vs2.slices[i - 1].empty()) {
|
||||
if (!intersection_ex(vs1.slices[i], vs2.slices[i - 1]).empty()) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//BBS: grouping the volumes of an object according to their connection relationship
|
||||
bool groupingVolumes(std::vector<VolumeSlices>& objSliceByVolume, std::vector<groupedVolumeSlices>& groups)
|
||||
bool groupingVolumes(std::vector<VolumeSlices> objSliceByVolume, std::vector<groupedVolumeSlices>& groups, double resolution)
|
||||
{
|
||||
int existGroups = 0;
|
||||
std::vector<int> groupIndex(objSliceByVolume.size(), -1);
|
||||
|
||||
double offsetValue = 0.4 / SCALING_FACTOR;
|
||||
|
||||
for (int i = 0; i != objSliceByVolume.size(); ++i) {
|
||||
for (int j = 0; j != objSliceByVolume[i].slices.size(); ++j) {
|
||||
objSliceByVolume[i].slices[j] = offset_ex(objSliceByVolume[i].slices[j], offsetValue);
|
||||
for (ExPolygon& poly_ex : objSliceByVolume[i].slices[j])
|
||||
poly_ex.douglas_peucker(resolution);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i != objSliceByVolume.size(); ++i) {
|
||||
if (groupIndex[i] < 0) {
|
||||
groupIndex[i] = i;
|
||||
@@ -765,7 +783,7 @@ bool groupingVolumes(std::vector<VolumeSlices>& objSliceByVolume, std::vector<gr
|
||||
}
|
||||
for (int j = i + 1; j != objSliceByVolume.size(); ++j) {
|
||||
if (doesVolumeIntersect(objSliceByVolume[i], objSliceByVolume[j])) {
|
||||
if (groupIndex[j] < 0) groupIndex[j] = i;
|
||||
if (groupIndex[j] < 0) groupIndex[j] = groupIndex[i];
|
||||
if (groupIndex[j] != groupIndex[i]) {
|
||||
int retain = std::min(groupIndex[i], groupIndex[j]);
|
||||
int cover = std::max(groupIndex[i], groupIndex[j]);
|
||||
@@ -791,9 +809,6 @@ bool groupingVolumes(std::vector<VolumeSlices>& objSliceByVolume, std::vector<gr
|
||||
if (!exist) groupVector.push_back(gi);
|
||||
}
|
||||
|
||||
if (groupVector.size() != existGroups);
|
||||
|
||||
|
||||
// group volumes and their slices according to the grouping Vector
|
||||
groups.clear();
|
||||
|
||||
@@ -808,9 +823,7 @@ bool groupingVolumes(std::vector<VolumeSlices>& objSliceByVolume, std::vector<gr
|
||||
}
|
||||
|
||||
// the slices of a group should be unioned
|
||||
double offsetValue = 0.4 / SCALING_FACTOR;
|
||||
gvs.slices = offset_ex(union_ex(offset_ex(gvs.slices, offsetValue)), -offsetValue);
|
||||
double resolution = 0.0125 / SCALING_FACTOR;
|
||||
gvs.slices = offset_ex(union_ex(gvs.slices), -offsetValue);
|
||||
for (ExPolygon& poly_ex : gvs.slices)
|
||||
poly_ex.douglas_peucker(resolution);
|
||||
|
||||
@@ -830,6 +843,24 @@ std::vector<VolumeSlices> findPartVolumes(const std::vector<VolumeSlices>& objSl
|
||||
return outPut;
|
||||
}
|
||||
|
||||
void applyNegtiveVolumes(ModelVolumePtrs model_volumes, const std::vector<VolumeSlices>& objSliceByVolume, std::vector<groupedVolumeSlices>& groups, double resolution) {
|
||||
ExPolygons negTotal;
|
||||
for (const auto& vs : objSliceByVolume) {
|
||||
for (const auto& mv : model_volumes) {
|
||||
if (vs.volume_id == mv->id() && mv->is_negative_volume()) {
|
||||
if (vs.slices.size() > 0) {
|
||||
append(negTotal, vs.slices.front());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& g : groups) {
|
||||
g.slices = diff_ex(g.slices, negTotal);
|
||||
for (ExPolygon& poly_ex : g.slices)
|
||||
poly_ex.douglas_peucker(resolution);
|
||||
}
|
||||
}
|
||||
// 1) Decides Z positions of the layers,
|
||||
// 2) Initializes layers and their regions
|
||||
// 3) Slices the object meshes
|
||||
@@ -873,9 +904,10 @@ void PrintObject::slice_volumes()
|
||||
}
|
||||
|
||||
//BBS: "model_part" volumes are grouded according to their connections
|
||||
const auto scaled_resolution = scaled<double>(print->config().resolution.value);
|
||||
std::vector<VolumeSlices> objSliceByVolumeParts = findPartVolumes(objSliceByVolume, this->model_object()->volumes);
|
||||
groupingVolumes(objSliceByVolumeParts, firstLayerObjSliceByGroups);
|
||||
|
||||
groupingVolumes(objSliceByVolumeParts, firstLayerObjSliceByGroups, scaled_resolution);
|
||||
applyNegtiveVolumes(this->model_object()->volumes, objSliceByVolume, firstLayerObjSliceByGroups, scaled_resolution);
|
||||
|
||||
std::vector<std::vector<ExPolygons>> region_slices = slices_to_regions(this->model_object()->volumes, *m_shared_regions, slice_zs,
|
||||
std::move(objSliceByVolume),
|
||||
|
||||
@@ -29,12 +29,13 @@ enum MachineBedType {
|
||||
|
||||
struct FilamentInfo
|
||||
{
|
||||
int id; // filament id = extruder id, start with 0.
|
||||
int id; // filament id = extruder id, start with 0.
|
||||
std::string type;
|
||||
std::string color;
|
||||
float used_m;
|
||||
float used_g;
|
||||
int tray_id;
|
||||
int tray_id; // start with 0
|
||||
float distance;
|
||||
};
|
||||
|
||||
class BBLSliceInfo {
|
||||
|
||||
@@ -19,6 +19,7 @@ public:
|
||||
float height;
|
||||
bool flipY;
|
||||
|
||||
SVG() = default;
|
||||
SVG(const char* afilename) :
|
||||
arrows(false), fill("grey"), stroke("black"), filename(afilename), flipY(false)
|
||||
{ open(filename); }
|
||||
|
||||
@@ -118,10 +118,11 @@ inline bool equal_layering(const SlicingParameters &sp1, const SlicingParameters
|
||||
sp1.first_print_layer_height == sp2.first_print_layer_height &&
|
||||
sp1.first_object_layer_height == sp2.first_object_layer_height &&
|
||||
sp1.first_object_layer_bridging == sp2.first_object_layer_bridging &&
|
||||
// BBS: following are not required for equal layer height.
|
||||
// Since the z-gap diff may be multiple of layer height.
|
||||
#if 0
|
||||
sp1.soluble_interface == sp2.soluble_interface &&
|
||||
sp1.gap_raft_object == sp2.gap_raft_object &&
|
||||
// BBS
|
||||
#if 0
|
||||
sp1.gap_object_support == sp2.gap_object_support &&
|
||||
sp1.gap_support_object == sp2.gap_support_object &&
|
||||
#endif
|
||||
|
||||
@@ -379,7 +379,7 @@ PrintObjectSupportMaterial::PrintObjectSupportMaterial(const PrintObject *object
|
||||
m_support_params.gap_xy = m_object_config->support_object_xy_distance.value;
|
||||
bridge_flow /= object->num_printing_regions();
|
||||
|
||||
m_support_params.support_material_bottom_interface_flow = m_slicing_params.soluble_interface || ! g_config_thick_bridges ?
|
||||
m_support_params.support_material_bottom_interface_flow = m_slicing_params.soluble_interface || ! m_object_config->thick_bridges ?
|
||||
m_support_params.support_material_interface_flow.with_flow_ratio(bridge_flow) :
|
||||
Flow::bridging_flow(bridge_flow * m_support_params.support_material_interface_flow.nozzle_diameter(), m_support_params.support_material_interface_flow.nozzle_diameter());
|
||||
|
||||
@@ -1339,7 +1339,7 @@ namespace SupportMaterialInternal {
|
||||
}
|
||||
}
|
||||
|
||||
static void remove_bridges_from_contactsxx(
|
||||
static void remove_bridges_from_contacts(
|
||||
const PrintConfig &print_config,
|
||||
const Layer &lower_layer,
|
||||
const Polygons &lower_layer_polygons,
|
||||
@@ -1374,7 +1374,9 @@ namespace SupportMaterialInternal {
|
||||
// since we're dealing with bridges, we can't assume width is larger than spacing,
|
||||
// so we take the largest value and also apply safety offset to be ensure no gaps
|
||||
// are left in between
|
||||
Flow perimeter_bridge_flow = layerm.bridging_flow(frPerimeter, g_config_thick_bridges);
|
||||
// BBS
|
||||
const PrintObjectConfig& object_config = layerm.layer()->object()->config();
|
||||
Flow perimeter_bridge_flow = layerm.bridging_flow(frPerimeter, object_config.thick_bridges);
|
||||
//FIXME one may want to use a maximum of bridging flow width and normal flow width, as the perimeters are calculated using the normal flow
|
||||
// and then turned to bridging flow, thus their centerlines are derived from non-bridging flow and expanding them by a bridging flow
|
||||
// may not expand them to the edge of their respective islands.
|
||||
@@ -1509,7 +1511,7 @@ static inline Polygons detect_overhangs(
|
||||
M_PI * double(object_config.support_threshold_angle.value + 1) / 180. : // +1 makes the threshold inclusive
|
||||
0.;
|
||||
const coordf_t max_bridge_length = scale_(object_config.max_bridge_length.value);
|
||||
const bool bridge_no_support = max_bridge_length > 0;// config.bridge_no_support.value;
|
||||
const bool bridge_no_support = object_config.bridge_no_support.value;
|
||||
|
||||
if (layer_id == 0)
|
||||
{
|
||||
@@ -1667,7 +1669,8 @@ static inline Polygons detect_overhangs(
|
||||
|
||||
if (bridge_no_support) {
|
||||
//FIXME Expensive, potentially not precise enough. Misses gap fill extrusions, which bridge.
|
||||
PrintObject::remove_bridges_from_contacts(&lower_layer, &layer, fw, &diff_polygons, max_bridge_length);
|
||||
SupportMaterialInternal::remove_bridges_from_contacts(
|
||||
print_config, lower_layer, lower_layer_polygons, *layerm, fw, diff_polygons);
|
||||
}
|
||||
|
||||
if (diff_polygons.empty() || offset(diff_polygons, -0.1 * fw).empty())
|
||||
@@ -1861,7 +1864,7 @@ static inline std::pair<PrintObjectSupportMaterial::MyLayer*, PrintObjectSupport
|
||||
|
||||
// Contact layer will be printed with a normal flow, but
|
||||
// it will support layers printed with a bridging flow.
|
||||
if (g_config_thick_bridges && SupportMaterialInternal::has_bridging_extrusions(layer)) {
|
||||
if (object_config.thick_bridges && SupportMaterialInternal::has_bridging_extrusions(layer)) {
|
||||
coordf_t bridging_height = 0.;
|
||||
for (const LayerRegion* region : layer.regions())
|
||||
bridging_height += region->region().bridging_height_avg(print_config);
|
||||
@@ -2429,7 +2432,7 @@ static inline PrintObjectSupportMaterial::MyLayer* detect_bottom_contacts(
|
||||
layer.print_z + layer_new.height + slicing_params.gap_object_support;
|
||||
layer_new.bottom_z = layer.print_z;
|
||||
layer_new.idx_object_layer_below = layer_id;
|
||||
layer_new.bridging = !slicing_params.soluble_interface && g_config_thick_bridges;
|
||||
layer_new.bridging = !slicing_params.soluble_interface && object.config().thick_bridges;
|
||||
//FIXME how much to inflate the bottom surface, as it is being extruded with a bridging flow? The following line uses a normal flow.
|
||||
layer_new.polygons = expand(touching, float(support_params.support_material_flow.scaled_width()), SUPPORT_SURFACES_OFFSET_PARAMETERS);
|
||||
|
||||
@@ -3234,7 +3237,7 @@ void PrintObjectSupportMaterial::trim_support_layers_by_object(
|
||||
polygons_append(polygons_trimming, offset({ expoly }, trimming_offset, SUPPORT_SURFACES_OFFSET_PARAMETERS));
|
||||
}
|
||||
}
|
||||
if (! m_slicing_params.soluble_interface && g_config_thick_bridges) {
|
||||
if (! m_slicing_params.soluble_interface && m_object_config->thick_bridges) {
|
||||
// Collect all bottom surfaces, which will be extruded with a bridging flow.
|
||||
for (; i < object.layers().size(); ++ i) {
|
||||
const Layer &object_layer = *object.layers()[i];
|
||||
@@ -4515,6 +4518,7 @@ void PrintObjectSupportMaterial::generate_toolpaths(
|
||||
angles[support_layer_id % angles.size()] :
|
||||
// Use interface angle for the interface layers.
|
||||
m_support_params.interface_angle + interface_angle_delta;
|
||||
|
||||
double density = interface_as_base ? m_support_params.support_density : m_support_params.interface_density;
|
||||
filler_interface->spacing = interface_as_base ? m_support_params.support_material_flow.spacing() : m_support_params.support_material_interface_flow.spacing();
|
||||
filler_interface->link_max_length = coord_t(scale_(filler_interface->spacing * link_max_length_factor / density));
|
||||
|
||||
+172
-89
@@ -9,15 +9,11 @@
|
||||
#include "SVG.hpp"
|
||||
#include "ShortestPath.hpp"
|
||||
#include "I18N.hpp"
|
||||
#include <libnest2d/backends/libslic3r/geometries.hpp>
|
||||
|
||||
#define _L(s) Slic3r::I18N::translate(s)
|
||||
|
||||
#define SQUARE_SUPPORT 0
|
||||
#if SQUARE_SUPPORT
|
||||
#define CIRCLE_RESOLUTION 4 // 100 //The number of vertices in each circle.
|
||||
#else
|
||||
#define CIRCLE_RESOLUTION 100 //The number of vertices in each circle.
|
||||
#endif
|
||||
|
||||
#define MAX_BRANCH_RADIUS 10.0
|
||||
#define HEIGHT_TO_SWITCH_INFILL_DIRECTION 30 // change infill direction every 20mm
|
||||
#define DO_NOT_MOVER_UNDER_MM 5 // do not move contact points under 5mm
|
||||
@@ -31,7 +27,7 @@
|
||||
#define TAU (2.0 * M_PI)
|
||||
#define NO_INDEX (std::numeric_limits<unsigned int>::max())
|
||||
|
||||
//#define SUPPORT_TREE_DEBUG_TO_SVG
|
||||
#define SUPPORT_TREE_DEBUG_TO_SVG
|
||||
|
||||
namespace Slic3r
|
||||
{
|
||||
@@ -225,14 +221,18 @@ static void draw_contours_and_nodes_to_svg
|
||||
bbox.max.x() = std::max(bbox.max.x(), (coord_t)scale_(10));
|
||||
bbox.max.y() = std::max(bbox.max.y(), (coord_t)scale_(10));
|
||||
|
||||
SVG svg(get_svg_filename(std::to_string(layer_nr), name_prefix), bbox);
|
||||
SVG svg;
|
||||
if(layer_nr>=0)
|
||||
svg.open(get_svg_filename(std::to_string(layer_nr), name_prefix), bbox);
|
||||
else
|
||||
svg.open(name_prefix, bbox);
|
||||
if (!svg.is_opened()) return;
|
||||
|
||||
// draw grid
|
||||
svg.draw_grid(bbox, "gray", coord_t(scale_(0.05)));
|
||||
|
||||
// draw overhang areas
|
||||
svg.draw(union_ex(overhangs), colors[0]);
|
||||
svg.draw_outline(union_ex(overhangs), colors[0]);
|
||||
svg.draw_outline(union_ex(overhangs_after_offset), colors[1]);
|
||||
svg.draw_outline(outlines_below, colors[2]);
|
||||
|
||||
@@ -661,6 +661,8 @@ void TreeSupport::detect_object_overhangs()
|
||||
|
||||
// Create Tree Support Layers
|
||||
m_object->clear_tree_support_layers();
|
||||
m_object->clear_tree_support_preview_cache();
|
||||
|
||||
create_tree_support_layers();
|
||||
m_ts_data = m_object->alloc_tree_support_preview_cache();
|
||||
|
||||
@@ -932,7 +934,7 @@ void TreeSupport::detect_object_overhangs()
|
||||
|
||||
|
||||
if (bridge_no_support && overhang_areas.size()>0) {
|
||||
m_object->remove_bridges_from_contacts(lower_layer, layer, extrusion_width_scaled, &overhang_areas, max_bridge_length);
|
||||
m_object->remove_bridges_from_contacts(lower_layer, layer, extrusion_width_scaled, &overhang_areas, max_bridge_length, true);
|
||||
}
|
||||
|
||||
TreeSupportLayer* ts_layer = m_object->get_tree_support_layer(layer_nr + m_raft_layers);
|
||||
@@ -1081,9 +1083,6 @@ void TreeSupport::detect_object_overhangs()
|
||||
}
|
||||
}
|
||||
|
||||
total_overhang_area = 0;
|
||||
max_overhang_area = 0;
|
||||
total_overhang_layer_cnt = 0;
|
||||
for (int layer_nr = 0; layer_nr < m_object->layer_count(); layer_nr++) {
|
||||
if (m_object->print()->canceled())
|
||||
break;
|
||||
@@ -1095,6 +1094,10 @@ void TreeSupport::detect_object_overhangs()
|
||||
ts_layer->overhang_areas = diff_ex(ts_layer->overhang_areas, offset_ex(blocker, scale_(radius_sample_resolution)));
|
||||
}
|
||||
|
||||
for (auto &area : ts_layer->overhang_areas) {
|
||||
ts_layer->overhang_types.emplace(&area, TreeSupportLayer::Detected);
|
||||
}
|
||||
|
||||
if (layer_nr < enforcers.size()) {
|
||||
Polygons& enforcer = enforcers[layer_nr];
|
||||
// coconut: enforcer can't do offset2_ex, otherwise faces with angle near 90 degrees can't have enforcers, which
|
||||
@@ -1102,15 +1105,9 @@ void TreeSupport::detect_object_overhangs()
|
||||
//enforcer = std::move(offset2_ex(enforcer, -0.1 * extrusion_width_scaled, 0.1 * extrusion_width_scaled));
|
||||
for (const Polygon& poly : enforcer) {
|
||||
ts_layer->overhang_areas.emplace_back(poly);
|
||||
ts_layer->overhang_types.emplace(&ts_layer->overhang_areas.back(), TreeSupportLayer::Enforced);
|
||||
}
|
||||
}
|
||||
|
||||
if (!ts_layer->overhang_areas.empty()) {
|
||||
float a = area(ts_layer->overhang_areas);
|
||||
total_overhang_area += a;
|
||||
max_overhang_area = std::max(max_overhang_area, a);
|
||||
total_overhang_layer_cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SUPPORT_TREE_DEBUG_TO_SVG
|
||||
@@ -1825,17 +1822,25 @@ void TreeSupport::draw_circles(const std::vector<std::vector<Node*>>& contact_no
|
||||
{
|
||||
const PrintObjectConfig &config = m_object->config();
|
||||
bool has_brim = m_object->print()->has_brim();
|
||||
bool has_infill = config.tree_support_with_infill.value;
|
||||
int bottom_gap_layers = round(m_slicing_params.gap_object_support / m_slicing_params.layer_height);
|
||||
const coordf_t branch_radius = config.tree_support_branch_diameter.value / 2;
|
||||
const coordf_t branch_radius_scaled = scale_(branch_radius);
|
||||
Polygon branch_circle; //Pre-generate a circle with correct diameter so that we don't have to recompute those (co)sines every time.
|
||||
|
||||
// Use square support if there are too many nodes per layer because circle support needs much longer time to compute
|
||||
// Hower circle support can be printed faster, so we prefer circle for fewer nodes case.
|
||||
const bool SQUARE_SUPPORT = avg_node_per_layer > 200;
|
||||
const int CIRCLE_RESOLUTION = SQUARE_SUPPORT ? 4 : 100; // The number of vertices in each circle.
|
||||
|
||||
|
||||
for (unsigned int i = 0; i < CIRCLE_RESOLUTION; i++)
|
||||
{
|
||||
#if SQUARE_SUPPORT
|
||||
double angle = (double)i / CIRCLE_RESOLUTION * TAU + TAU/8.0;
|
||||
#else
|
||||
double angle = (double)i / CIRCLE_RESOLUTION * TAU;
|
||||
#endif
|
||||
double angle;
|
||||
if (SQUARE_SUPPORT)
|
||||
angle = (double) i / CIRCLE_RESOLUTION * TAU + PI / 4.0 + nodes_angle;
|
||||
else
|
||||
angle = (double) i / CIRCLE_RESOLUTION * TAU;
|
||||
branch_circle.append(Point(cos(angle) * branch_radius_scaled, sin(angle) * branch_radius_scaled));
|
||||
}
|
||||
|
||||
@@ -1850,7 +1855,6 @@ void TreeSupport::draw_circles(const std::vector<std::vector<Node*>>& contact_no
|
||||
}
|
||||
|
||||
// generate areas
|
||||
const coordf_t circle_side_length = 2 * branch_radius * sin(M_PI / CIRCLE_RESOLUTION); //Side length of a regular polygon.
|
||||
const coordf_t layer_height = config.layer_height.value;
|
||||
const size_t top_interface_layers = config.support_interface_top_layers.value;
|
||||
const size_t bottom_interface_layers = config.support_interface_bottom_layers.value;
|
||||
@@ -2024,16 +2028,12 @@ void TreeSupport::draw_circles(const std::vector<std::vector<Node*>>& contact_no
|
||||
base_areas = std::move(diff_ex(base_areas, roof_areas));
|
||||
base_areas = std::move(diff_ex(base_areas, roof_1st_layer));
|
||||
|
||||
#if SQUARE_SUPPORT
|
||||
if (m_object->print()->config().enable_arc_fitting.value == false) {
|
||||
// simplify support contours if arc fitting is disabled
|
||||
if (SQUARE_SUPPORT) {
|
||||
// simplify support contours
|
||||
ExPolygons base_areas_simplified;
|
||||
for (auto& area : base_areas) {
|
||||
area.simplify(scale_(line_width / 2), &base_areas_simplified, SimplifyMethodDP);
|
||||
}
|
||||
for (auto &area : base_areas) { area.simplify(scale_(line_width / 2), &base_areas_simplified, SimplifyMethodDP); }
|
||||
base_areas = std::move(base_areas_simplified);
|
||||
}
|
||||
#endif
|
||||
//Subtract support floors. We can only compute floor_areas here instead of with roof_areas,
|
||||
// or we'll get much wider floor than necessary.
|
||||
if (bottom_interface_layers + bottom_gap_layers > 0)
|
||||
@@ -2073,15 +2073,13 @@ void TreeSupport::draw_circles(const std::vector<std::vector<Node*>>& contact_no
|
||||
}),
|
||||
expoly->holes.end());
|
||||
}
|
||||
#ifdef SUPPORT_TREE_DEBUG_TO_SVG
|
||||
draw_contours_and_nodes_to_svg(layer_nr, base_areas, roof_areas, roof_1st_layer, {}, {}, "circles", { "base","roof","roof1st" });
|
||||
#endif
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
#if 1
|
||||
// move the holes to contour so they can be well supported
|
||||
|
||||
if (!has_infill) {
|
||||
// check if poly's contour intersects with expoly's contour
|
||||
auto intersects_contour = [](Polygon poly, ExPolygon expoly, Point &pt_on_poly, Point &pt_on_expoly, Point &pt_far_on_poly, float dist_thresh = 0.01) {
|
||||
float min_dist = std::numeric_limits<float>::max();
|
||||
@@ -2099,18 +2097,15 @@ void TreeSupport::draw_circles(const std::vector<std::vector<Node*>>& contact_no
|
||||
max_dist = dist2;
|
||||
pt_far_on_poly = from;
|
||||
}
|
||||
if (dist2 < dist_thresh) {
|
||||
return true;
|
||||
}
|
||||
if (dist2 < dist_thresh) { return true; }
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
std::map<const Polygon *, int> holeDepth;
|
||||
std::map<const Polygon *, Point> holeDiretions;
|
||||
std::map<const Polygon *, Point> holeFarPoints;
|
||||
for (int layer_nr = m_object->layer_count()-1; layer_nr >0; layer_nr--) {
|
||||
// polygon pointer: depth, direction, farPoint
|
||||
std::map<const Polygon *, std::tuple<int, Point, Point>> holePropagationInfos;
|
||||
for (int layer_nr = m_object->layer_count() - 1; layer_nr > 0; layer_nr--) {
|
||||
if (print->canceled()) break;
|
||||
m_object->print()->set_status(66, (boost::format(_L("Support: fix holes at layer %d")) % layer_nr).str());
|
||||
|
||||
@@ -2127,47 +2122,88 @@ void TreeSupport::draw_circles(const std::vector<std::vector<Node*>>& contact_no
|
||||
for (layer_nr_lower; layer_nr_lower >= 0; layer_nr_lower--) {
|
||||
if (!m_object->get_tree_support_layer(layer_nr_lower + m_raft_layers)->area_groups.empty()) break;
|
||||
}
|
||||
auto & area_groups_lower = m_object->get_tree_support_layer(layer_nr_lower + m_raft_layers)->area_groups;
|
||||
auto &area_groups_lower = m_object->get_tree_support_layer(layer_nr_lower + m_raft_layers)->area_groups;
|
||||
|
||||
for (const auto& area_group:ts_layer->area_groups){
|
||||
if (area_group.second == 1 || area_group.second == 2) continue;
|
||||
const auto base_area = area_group.first;
|
||||
for (const auto &hole : base_area->holes) {
|
||||
for (const auto &area_group : ts_layer->area_groups) {
|
||||
if (area_group.second != TreeSupportLayer::BaseType) continue;
|
||||
const auto area = area_group.first;
|
||||
for (const auto &hole : area->holes) {
|
||||
// auto hole_bbox = get_extents(hole).polygon();
|
||||
for (auto & area_group_lower: area_groups_lower) {
|
||||
if (area_group.second == 1 || area_group.second == 2) continue;
|
||||
for (auto &area_group_lower : area_groups_lower) {
|
||||
if (area_group.second != TreeSupportLayer::BaseType) continue;
|
||||
auto &base_area_lower = *area_group_lower.first;
|
||||
Point pt_on_poly, pt_on_expoly, pt_far_on_poly;
|
||||
// if a hole doesn't intersect with lower layer's contours, add a hole to lower layer and move it slightly to the contour
|
||||
if (base_area_lower.contour.contains(hole.points.front()) && !intersects_contour(hole, base_area_lower, pt_on_poly, pt_on_expoly, pt_far_on_poly)) {
|
||||
Polygon hole_lower = hole;
|
||||
Point direction = normal(pt_on_expoly - pt_on_poly, line_width_scaled/2);
|
||||
Point direction = normal(pt_on_expoly - pt_on_poly, line_width_scaled / 2);
|
||||
hole_lower.translate(direction);
|
||||
// note to expand a hole, we need to do negative offset
|
||||
auto hole_expanded = offset(hole_lower, -line_width_scaled / 4, ClipperLib::JoinType::jtSquare);
|
||||
if (!hole_expanded.empty()) {
|
||||
base_area_lower.holes.push_back(std::move(hole_expanded[0]));
|
||||
holeDepth.insert({&base_area_lower.holes.back(), 15});
|
||||
holeDiretions.insert({&base_area_lower.holes.back(), direction});
|
||||
holeFarPoints.insert({&base_area_lower.holes.back(), pt_far_on_poly});
|
||||
holePropagationInfos.insert({&base_area_lower.holes.back(), {25, direction, pt_far_on_poly}});
|
||||
}
|
||||
break;
|
||||
} else if (holeDepth.find(&hole) != holeDepth.end() && holeDepth[&hole] > 0 && base_area_lower.contour.contains(holeFarPoints[&hole])) {
|
||||
} else if (holePropagationInfos.find(&hole) != holePropagationInfos.end() && std::get<0>(holePropagationInfos[&hole]) > 0 &&
|
||||
base_area_lower.contour.contains(std::get<2>(holePropagationInfos[&hole]))) {
|
||||
Polygon hole_lower = hole;
|
||||
hole_lower.translate(holeDiretions[&hole]);
|
||||
Point farPoint = holeFarPoints[&hole] + holeDiretions[&hole];
|
||||
{
|
||||
base_area_lower.holes.push_back(std::move(hole_lower));
|
||||
holeDepth.insert({&base_area_lower.holes.back(), holeDepth[&hole]-1});
|
||||
holeDiretions.insert({&base_area_lower.holes.back(), holeDiretions[&hole]});
|
||||
holeFarPoints.insert({&base_area_lower.holes.back(), farPoint});
|
||||
auto && direction = std::get<1>(holePropagationInfos[&hole]);
|
||||
hole_lower.translate(direction);
|
||||
// note to shrink a hole, we need to do positive offset
|
||||
auto hole_expanded = offset(hole_lower, line_width_scaled / 2, ClipperLib::JoinType::jtSquare);
|
||||
Point farPoint = std::get<2>(holePropagationInfos[&hole]) + direction * 2;
|
||||
if (!hole_expanded.empty()) {
|
||||
base_area_lower.holes.push_back(std::move(hole_expanded[0]));
|
||||
holePropagationInfos.insert({&base_area_lower.holes.back(), {std::get<0>(holePropagationInfos[&hole]) - 1, direction, farPoint}});
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
{
|
||||
// if roof1 interface is inside a hole, need to expand the interface
|
||||
for (auto &roof1 : ts_layer->roof_1st_layer) {
|
||||
//if (hole.contains(roof1.contour.points.front()) && hole.contains(roof1.contour.bounding_box().center()))
|
||||
bool is_inside_hole = std::all_of(roof1.contour.points.begin(), roof1.contour.points.end(), [&hole](Point &pt) { return hole.contains(pt); });
|
||||
if (is_inside_hole) {
|
||||
Polygon hole_reoriented = hole;
|
||||
if (roof1.contour.is_counter_clockwise())
|
||||
hole_reoriented.make_counter_clockwise();
|
||||
else if (roof1.contour.is_clockwise())
|
||||
hole_reoriented.make_clockwise();
|
||||
auto tmp = union_({roof1.contour}, {hole_reoriented});
|
||||
if (!tmp.empty()) roof1.contour = tmp[0];
|
||||
|
||||
// make sure 1) roof1 and object 2) roof1 and roof, won't intersect
|
||||
// Note: We can't replace roof1 directly, as we have recorded its address.
|
||||
// So instead we need to replace its members one by one.
|
||||
auto tmp1 = diff_ex(roof1, m_ts_data->get_collision((layer_nr == 0 && has_brim) ? config.brim_object_gap : m_ts_data->m_xy_distance, layer_nr));
|
||||
tmp1 = diff_ex(tmp1, ts_layer->roof_areas);
|
||||
if (!tmp1.empty()) {
|
||||
roof1.contour = std::move(tmp1[0].contour);
|
||||
roof1.holes = std::move(tmp1[0].holes);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SUPPORT_TREE_DEBUG_TO_SVG
|
||||
for (int layer_nr = m_object->layer_count() - 1; layer_nr > 0; layer_nr--) {
|
||||
TreeSupportLayer* ts_layer = m_object->get_tree_support_layer(layer_nr + m_raft_layers);
|
||||
ExPolygons& base_areas = ts_layer->base_areas;
|
||||
ExPolygons& roof_areas = ts_layer->roof_areas;
|
||||
ExPolygons& roof_1st_layer = ts_layer->roof_1st_layer;
|
||||
ExPolygons& floor_areas = ts_layer->floor_areas;
|
||||
if (base_areas.empty() && roof_areas.empty() && roof_1st_layer.empty()) continue;
|
||||
char fname[10]; sprintf(fname, "%d_%.2f", layer_nr, ts_layer->print_z);
|
||||
draw_contours_and_nodes_to_svg(-1, base_areas, roof_areas, roof_1st_layer, {}, {}, get_svg_filename(fname, "circles"), {"base", "roof", "roof1st"});
|
||||
}
|
||||
#endif
|
||||
|
||||
TreeSupportLayerPtrs& ts_layers = m_object->tree_support_layers();
|
||||
@@ -2257,6 +2293,7 @@ void TreeSupport::drop_nodes(std::vector<std::vector<Node*>>& contact_nodes)
|
||||
next_node->distance_to_top++;
|
||||
next_node->support_roof_layers_below--;
|
||||
next_node->print_z -= m_object->get_layer(layer_nr)->height;
|
||||
next_node->to_buildplate = !is_inside_ex(m_ts_data->m_layer_outlines[layer_nr], next_node->position);
|
||||
contact_nodes[layer_nr - 1].emplace_back(next_node);
|
||||
}
|
||||
}
|
||||
@@ -2290,10 +2327,6 @@ void TreeSupport::drop_nodes(std::vector<std::vector<Node*>>& contact_nodes)
|
||||
for (Node* p_node : layer_contact_nodes)
|
||||
{
|
||||
const Node& node = *p_node;
|
||||
if (node.type == ePolygon) {
|
||||
// polygon node do not merge or move
|
||||
continue;
|
||||
}
|
||||
|
||||
if (support_on_buildplate_only && !node.to_buildplate) //Can't rest on model and unable to reach the build plate. Then we must drop the node and leave parts unsupported.
|
||||
{
|
||||
@@ -2305,6 +2338,10 @@ void TreeSupport::drop_nodes(std::vector<std::vector<Node*>>& contact_nodes)
|
||||
nodes_per_part[0][node.position] = p_node;
|
||||
continue;
|
||||
}
|
||||
if (node.type == ePolygon) {
|
||||
// polygon node do not merge or move
|
||||
continue;
|
||||
}
|
||||
/* Find which part this node is located in and group the nodes in
|
||||
* the same part together. Since nodes have a radius and the
|
||||
* avoidance areas are offset by that radius, the set of parts may
|
||||
@@ -2720,7 +2757,7 @@ void TreeSupport::generate_contact_points(std::vector<std::vector<TreeSupport::N
|
||||
coordf_t z_distance_top = m_slicing_params.gap_support_object;
|
||||
// BBS: add extra distance if thick bridge is enabled
|
||||
// Note: normal support uses print_z, but tree support uses integer layers, so we need to subtract layer_height
|
||||
if (!m_slicing_params.soluble_interface && g_config_thick_bridges) {
|
||||
if (!m_slicing_params.soluble_interface && m_object_config->thick_bridges) {
|
||||
z_distance_top += m_object->layers()[0]->regions()[0]->region().bridging_height_avg(m_object->print()->config()) - layer_height;
|
||||
}
|
||||
const size_t z_distance_top_layers = round_up_divide(scale_(z_distance_top), scale_(layer_height)) + 1; //Support must always be 1 layer below overhang.
|
||||
@@ -2729,17 +2766,20 @@ void TreeSupport::generate_contact_points(std::vector<std::vector<TreeSupport::N
|
||||
coordf_t thresh_angle = config.support_threshold_angle.value < EPSILON ? 30.f : config.support_threshold_angle.value;
|
||||
coordf_t half_overhang_distance = scale_(tan(thresh_angle * M_PI / 180.0) * layer_height / 2);
|
||||
|
||||
m_highest_overhang_layer = 0;
|
||||
// fix bug of generating support for very thin objects
|
||||
if (m_object->layers().size() <= z_distance_top_layers + 1)
|
||||
return;
|
||||
|
||||
m_highest_overhang_layer = 0;
|
||||
int nonempty_layers = 0;
|
||||
std::vector<Slic3r::Vec3f> all_nodes;
|
||||
for (size_t layer_nr = 1; layer_nr < m_object->layers().size() - z_distance_top_layers; layer_nr++)
|
||||
{
|
||||
if (m_object->print()->canceled())
|
||||
break;
|
||||
|
||||
const ExPolygons &overhang = m_object->get_tree_support_layer(layer_nr + m_raft_layers + z_distance_top_layers)->overhang_areas;
|
||||
auto ts_layer = m_object->get_tree_support_layer(layer_nr + m_raft_layers + z_distance_top_layers);
|
||||
const ExPolygons &overhang = ts_layer->overhang_areas;
|
||||
auto & curr_nodes = contact_nodes[layer_nr];
|
||||
if (overhang.empty())
|
||||
continue;
|
||||
|
||||
@@ -2757,7 +2797,7 @@ void TreeSupport::generate_contact_points(std::vector<std::vector<TreeSupport::N
|
||||
Node *contact_node = new Node(candidate, 0, (layer_nr + z_distance_top_layers) % 2, support_roof_layers, true, Node::NO_PARENT, print_z, height);
|
||||
contact_node->type = ePolygon;
|
||||
contact_node->overhang = &overhang_part;
|
||||
contact_nodes[layer_nr].emplace_back(contact_node);
|
||||
curr_nodes.emplace_back(contact_node);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -2783,7 +2823,7 @@ void TreeSupport::generate_contact_points(std::vector<std::vector<TreeSupport::N
|
||||
constexpr size_t distance_to_top = 0;
|
||||
constexpr bool to_buildplate = true;
|
||||
Node* contact_node = new Node(candidate, distance_to_top, (layer_nr + z_distance_top_layers) % 2, support_roof_layers, to_buildplate, Node::NO_PARENT,print_z,height);
|
||||
contact_nodes[layer_nr].emplace_back(contact_node);
|
||||
curr_nodes.emplace_back(contact_node);
|
||||
added = true;
|
||||
}
|
||||
}
|
||||
@@ -2793,38 +2833,81 @@ void TreeSupport::generate_contact_points(std::vector<std::vector<TreeSupport::N
|
||||
if (!added) //If we didn't add any points due to bad luck, we want to add one anyway such that loose parts are also supported.
|
||||
{
|
||||
auto bbox = overhang_part.contour.bounding_box();
|
||||
Points candidates = { bbox.min, bounding_box_middle(bbox), bbox.max };
|
||||
Points candidates;
|
||||
if (ts_layer->overhang_types[&overhang_part] == TreeSupportLayer::Detected)
|
||||
candidates = {bbox.min, bounding_box_middle(bbox), bbox.max};
|
||||
else
|
||||
candidates = {bounding_box_middle(bbox)};
|
||||
|
||||
for (Point candidate : candidates) {
|
||||
if (!overhang_part.contains(candidate))
|
||||
move_inside_expoly(overhang_part, candidate);
|
||||
constexpr size_t distance_to_top = 0;
|
||||
constexpr bool to_buildplate = true;
|
||||
Node * contact_node = new Node(candidate, distance_to_top, layer_nr % 2, support_roof_layers, to_buildplate, Node::NO_PARENT, print_z, height);
|
||||
contact_nodes[layer_nr].emplace_back(contact_node);
|
||||
curr_nodes.emplace_back(contact_node);
|
||||
}
|
||||
}
|
||||
|
||||
// add points at corners
|
||||
auto& points = overhang_part.contour.points;
|
||||
for (int i=0;i<points.size();i++)
|
||||
{
|
||||
auto pt = points[i];
|
||||
auto v1 = (pt - points[(i - 1 + points.size()) % points.size()]).normalized();
|
||||
auto v2 = (pt - points[(i + 1) % points.size()]).normalized();
|
||||
if (v1.dot(v2) > -0.7) {
|
||||
Node* contact_node = new Node(pt, 0, layer_nr % 2, support_roof_layers, true, Node::NO_PARENT, print_z, height);
|
||||
contact_nodes[layer_nr].emplace_back(contact_node);
|
||||
if (ts_layer->overhang_types[&overhang_part] == TreeSupportLayer::Detected) {
|
||||
// add points at corners
|
||||
auto &points = overhang_part.contour.points;
|
||||
for (int i = 0; i < points.size(); i++) {
|
||||
auto pt = points[i];
|
||||
auto v1 = (pt - points[(i - 1 + points.size()) % points.size()]).normalized();
|
||||
auto v2 = (pt - points[(i + 1) % points.size()]).normalized();
|
||||
if (v1.dot(v2) > -0.7) {
|
||||
Node *contact_node = new Node(pt, 0, layer_nr % 2, support_roof_layers, true, Node::NO_PARENT, print_z, height);
|
||||
curr_nodes.emplace_back(contact_node);
|
||||
}
|
||||
}
|
||||
} else if(ts_layer->overhang_types[&overhang_part] == TreeSupportLayer::Enforced){
|
||||
// remove close points in Enforcers
|
||||
auto above_nodes = contact_nodes[layer_nr - 1];
|
||||
if (!curr_nodes.empty() && !above_nodes.empty()) {
|
||||
for (auto it = curr_nodes.begin(); it != curr_nodes.end();) {
|
||||
bool is_duplicate = false;
|
||||
Slic3r::Vec3f curr_pt((*it)->position(0), (*it)->position(1), scale_((*it)->print_z));
|
||||
for (auto &pt : all_nodes) {
|
||||
auto dif = curr_pt - pt;
|
||||
if (dif.norm() < scale_(2)) {
|
||||
delete (*it);
|
||||
it = curr_nodes.erase(it);
|
||||
is_duplicate = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!is_duplicate) it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (!curr_nodes.empty()) nonempty_layers++;
|
||||
for (auto node : curr_nodes) { all_nodes.emplace_back(node->position(0), node->position(1), scale_(node->print_z)); }
|
||||
#ifdef SUPPORT_TREE_DEBUG_TO_SVG
|
||||
draw_contours_and_nodes_to_svg(layer_nr, overhang, m_ts_data->m_layer_outlines_below[layer_nr], {},
|
||||
contact_nodes[layer_nr], {}, "init_contact_points", { "overhang","outlines","" });
|
||||
#endif
|
||||
}
|
||||
int nNodes = all_nodes.size();
|
||||
avg_node_per_layer = nodes_angle = 0;
|
||||
if (nNodes > 0) {
|
||||
avg_node_per_layer = nNodes / nonempty_layers;
|
||||
// get orientation of nodes by line fitting
|
||||
// line: y=kx+b, where
|
||||
// k=tan(nodes_angle)=(n\sum{xy}-\sum{x}\sum{y})/(n\sum{x^2}-\sum{x}^2)
|
||||
float mx = 0, my = 0, mxy = 0, mx2 = 0;
|
||||
for (auto &pt : all_nodes) {
|
||||
float x = unscale_(pt(0));
|
||||
float y = unscale_(pt(1));
|
||||
mx += x;
|
||||
my += y;
|
||||
mxy += x * y;
|
||||
mx2 += x * x;
|
||||
}
|
||||
nodes_angle = atan2(nNodes * mxy - mx * my, nNodes * mx2 - SQ(mx));
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << "avg_node_per_layer=" << avg_node_per_layer << ", nodes_angle=" << nodes_angle;
|
||||
}
|
||||
}
|
||||
|
||||
void TreeSupport::insert_dropped_node(std::vector<Node*>& nodes_layer, Node* p_node)
|
||||
|
||||
@@ -340,9 +340,8 @@ public:
|
||||
bool with_sheath;
|
||||
};
|
||||
|
||||
float total_overhang_area;
|
||||
float max_overhang_area;
|
||||
size_t total_overhang_layer_cnt;
|
||||
int avg_node_per_layer = 0;
|
||||
float nodes_angle = 0;
|
||||
bool has_sharp_tail;
|
||||
private:
|
||||
/*!
|
||||
|
||||
@@ -497,15 +497,10 @@ BoundingBoxf3 TriangleMesh::transformed_bounding_box(const Transform3d& trafod,
|
||||
|
||||
TriangleMesh TriangleMesh::convex_hull_3d() const
|
||||
{
|
||||
// BBS: don't compute convex hull for objects like a single sheet
|
||||
if (this->m_stats.volume>0.001) {
|
||||
TriangleMesh mesh(its_convex_hull(this->its));
|
||||
// Quite often qhull produces non-manifold mesh.
|
||||
// assert(mesh.stats().manifold());
|
||||
return mesh;
|
||||
}
|
||||
else
|
||||
return TriangleMesh();
|
||||
TriangleMesh mesh(its_convex_hull(this->its));
|
||||
// Quite often qhull produces non-manifold mesh.
|
||||
// assert(mesh.stats().manifold());
|
||||
return mesh;
|
||||
}
|
||||
|
||||
std::vector<ExPolygons> TriangleMesh::slice(const std::vector<double> &z) const
|
||||
|
||||
@@ -84,6 +84,124 @@ static ExtrusionPaths thick_polyline_to_extrusion_paths(const ThickPolyline& thi
|
||||
return paths;
|
||||
}
|
||||
|
||||
//BBS: new function to filter width to avoid too fragmented segments
|
||||
static ExtrusionPaths thick_polyline_to_extrusion_paths_2(const ThickPolyline& thick_polyline, ExtrusionRole role, const Flow& flow, const float tolerance)
|
||||
{
|
||||
ExtrusionPaths paths;
|
||||
ExtrusionPath path(role);
|
||||
ThickLines lines = thick_polyline.thicklines();
|
||||
|
||||
size_t start_index = 0;
|
||||
double max_width, min_width;
|
||||
|
||||
for (int i = 0; i < (int)lines.size(); ++i) {
|
||||
const ThickLine& line = lines[i];
|
||||
|
||||
if (i == 0) {
|
||||
max_width = line.a_width;
|
||||
min_width = line.a_width;
|
||||
}
|
||||
|
||||
const coordf_t line_len = line.length();
|
||||
if (line_len < SCALED_EPSILON) continue;
|
||||
|
||||
double thickness_delta = std::max(fabs(max_width - line.b_width), fabs(min_width - line.b_width));
|
||||
//BBS: has large difference in width
|
||||
if (thickness_delta > tolerance) {
|
||||
//BBS: 1 generate path from start_index to i(not included)
|
||||
if (start_index != i){
|
||||
path = ExtrusionPath(role);
|
||||
double length = lines[start_index].length();
|
||||
double sum = lines[start_index].length() * lines[start_index].a_width;
|
||||
path.polyline.append(lines[start_index].a);
|
||||
for (int idx = start_index + 1; idx < i; idx++) {
|
||||
length += lines[idx].length();
|
||||
sum += lines[idx].length() * lines[idx].a_width;
|
||||
path.polyline.append(lines[idx].a);
|
||||
}
|
||||
path.polyline.append(lines[i].a);
|
||||
if (length > SCALED_EPSILON) {
|
||||
double w = sum / length;
|
||||
Flow new_flow = flow.with_width(unscale<float>(w) + flow.height() * float(1. - 0.25 * PI));
|
||||
path.mm3_per_mm = new_flow.mm3_per_mm();
|
||||
path.width = new_flow.width();
|
||||
path.height = new_flow.height();
|
||||
paths.emplace_back(std::move(path));
|
||||
}
|
||||
}
|
||||
|
||||
start_index = i;
|
||||
max_width = line.a_width;
|
||||
min_width = line.a_width;
|
||||
|
||||
//BBS: 2 handle the i-th segment
|
||||
thickness_delta = fabs(line.a_width - line.b_width);
|
||||
if (thickness_delta > tolerance){
|
||||
const unsigned int segments = (unsigned int)ceil(thickness_delta / tolerance);
|
||||
const coordf_t seg_len = line_len / segments;
|
||||
Points pp;
|
||||
std::vector<coordf_t> width;
|
||||
{
|
||||
pp.push_back(line.a);
|
||||
width.push_back(line.a_width);
|
||||
for (size_t j = 1; j < segments; ++j) {
|
||||
pp.push_back((line.a.cast<double>() + (line.b - line.a).cast<double>().normalized() * (j * seg_len)).cast<coord_t>());
|
||||
|
||||
coordf_t w = line.a_width + (j * seg_len) * (line.b_width - line.a_width) / line_len;
|
||||
width.push_back(w);
|
||||
width.push_back(w);
|
||||
}
|
||||
pp.push_back(line.b);
|
||||
width.push_back(line.b_width);
|
||||
|
||||
assert(pp.size() == segments + 1u);
|
||||
assert(width.size() == segments * 2);
|
||||
}
|
||||
|
||||
// delete this line and insert new ones
|
||||
lines.erase(lines.begin() + i);
|
||||
for (size_t j = 0; j < segments; ++j) {
|
||||
ThickLine new_line(pp[j], pp[j + 1]);
|
||||
new_line.a_width = width[2 * j];
|
||||
new_line.b_width = width[2 * j + 1];
|
||||
lines.insert(lines.begin() + i + j, new_line);
|
||||
}
|
||||
--i;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
//BBS: just update the max and min width and continue
|
||||
else {
|
||||
max_width = std::max(max_width, std::max(line.a_width, line.b_width));
|
||||
min_width = std::min(min_width, std::min(line.a_width, line.b_width));
|
||||
}
|
||||
}
|
||||
//BBS: handle the remaining segment
|
||||
size_t final_size = lines.size();
|
||||
if (start_index < final_size) {
|
||||
path = ExtrusionPath(role);
|
||||
double length = lines[start_index].length();
|
||||
double sum = lines[start_index].length() * lines[start_index].a_width;
|
||||
path.polyline.append(lines[start_index].a);
|
||||
for (int idx = start_index + 1; idx < final_size; idx++) {
|
||||
length += lines[idx].length();
|
||||
sum += lines[idx].length() * lines[idx].a_width;
|
||||
path.polyline.append(lines[idx].a);
|
||||
}
|
||||
path.polyline.append(lines[final_size - 1].b);
|
||||
if (length > SCALED_EPSILON) {
|
||||
double w = sum / length;
|
||||
Flow new_flow = flow.with_width(unscale<float>(w) + flow.height() * float(1. - 0.25 * PI));
|
||||
path.mm3_per_mm = new_flow.mm3_per_mm();
|
||||
path.width = new_flow.width();
|
||||
path.height = new_flow.height();
|
||||
paths.emplace_back(std::move(path));
|
||||
}
|
||||
}
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
void variable_width(const ThickPolylines& polylines, ExtrusionRole role, const Flow& flow, std::vector<ExtrusionEntity*>& out)
|
||||
{
|
||||
// This value determines granularity of adaptive width, as G-code does not allow
|
||||
@@ -91,7 +209,7 @@ void variable_width(const ThickPolylines& polylines, ExtrusionRole role, const F
|
||||
// of segments, and any pruning shall be performed before we apply this tolerance.
|
||||
const float tolerance = float(scale_(0.05));
|
||||
for (const ThickPolyline& p : polylines) {
|
||||
ExtrusionPaths paths = thick_polyline_to_extrusion_paths(p, role, flow, tolerance);
|
||||
ExtrusionPaths paths = thick_polyline_to_extrusion_paths_2(p, role, flow, tolerance);
|
||||
// Append paths to collection.
|
||||
if (!paths.empty()) {
|
||||
if (paths.front().first_point() == paths.back().last_point())
|
||||
|
||||
@@ -84,7 +84,6 @@ static constexpr bool RELATIVE_E_AXIS = 1;
|
||||
#endif /* UNUSED */
|
||||
|
||||
//BBS: some global const config which user can not change, but developer can
|
||||
static constexpr bool g_config_thick_bridges = true;
|
||||
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;
|
||||
|
||||
@@ -11,6 +11,10 @@
|
||||
#include "Time.hpp"
|
||||
#include "libslic3r.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include "MacUtils.hpp"
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#include <psapi.h>
|
||||
@@ -292,12 +296,21 @@ namespace keywords = boost::log::keywords;
|
||||
namespace attrs = boost::log::attributes;
|
||||
void set_log_path_and_level(const std::string& file, unsigned int level)
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
//currently on old macos, the boost::log::add_file_log will crash
|
||||
//TODO: need to be fixed
|
||||
if (!is_macos_support_boost_add_file_log()) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
//BBS log file at C:\\Users\\[yourname]\\AppData\\Roaming\\BambuStudio\\log\\[log_filename].log
|
||||
auto log_folder = boost::filesystem::path(g_data_dir) / "log";
|
||||
if (!boost::filesystem::exists(log_folder)) {
|
||||
boost::filesystem::create_directory(log_folder);
|
||||
}
|
||||
auto full_path = (log_folder / file).make_preferred();
|
||||
|
||||
g_log_sink = boost::log::add_file_log(
|
||||
keywords::file_name = full_path.string() + ".%N",
|
||||
keywords::rotation_size = 100 * 1024 * 1024,
|
||||
@@ -309,6 +322,7 @@ void set_log_path_and_level(const std::string& file, unsigned int level)
|
||||
<< ":" << expr::smessage
|
||||
)
|
||||
);
|
||||
|
||||
logging::add_common_attributes();
|
||||
|
||||
set_logging_level(level);
|
||||
|
||||
@@ -221,8 +221,8 @@ set(SLIC3R_GUI_SOURCES
|
||||
GUI/Monitor.hpp
|
||||
GUI/WebViewDialog.cpp
|
||||
GUI/WebViewDialog.hpp
|
||||
GUI/WebDailytipDialog.hpp
|
||||
GUI/WebDailytipDialog.cpp
|
||||
GUI/WebDownPluginDlg.hpp
|
||||
GUI/WebDownPluginDlg.cpp
|
||||
GUI/WebGuideDialog.hpp
|
||||
GUI/WebGuideDialog.cpp
|
||||
GUI/WebUserLoginDialog.cpp
|
||||
@@ -268,12 +268,16 @@ set(SLIC3R_GUI_SOURCES
|
||||
GUI/ConfigWizard_private.hpp
|
||||
GUI/MsgDialog.cpp
|
||||
GUI/MsgDialog.hpp
|
||||
GUI/DownloadProgressDialog.hpp
|
||||
GUI/DownloadProgressDialog.cpp
|
||||
GUI/UpdateDialogs.cpp
|
||||
GUI/UpdateDialogs.hpp
|
||||
GUI/Jobs/Job.hpp
|
||||
GUI/Jobs/Job.cpp
|
||||
GUI/Jobs/PlaterJob.hpp
|
||||
GUI/Jobs/PlaterJob.cpp
|
||||
GUI/Jobs/UpgradeNetworkJob.hpp
|
||||
GUI/Jobs/UpgradeNetworkJob.cpp
|
||||
GUI/Jobs/ArrangeJob.hpp
|
||||
GUI/Jobs/ArrangeJob.cpp
|
||||
GUI/Jobs/OrientJob.hpp
|
||||
|
||||
@@ -4,9 +4,14 @@
|
||||
#include "I18N.hpp"
|
||||
|
||||
namespace Slic3r { namespace GUI {
|
||||
static bool show_flag;
|
||||
|
||||
AMSMaterialsSetting::AMSMaterialsSetting(wxWindow *parent, wxWindowID id): wxPopupTransientWindow(parent, id)
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
#define COMBOBOX_FILAMENT (m_comboBox_filament_mac)
|
||||
#else
|
||||
#define COMBOBOX_FILAMENT (m_comboBox_filament)
|
||||
#endif
|
||||
AMSMaterialsSetting::AMSMaterialsSetting(wxWindow *parent, wxWindowID id) : wxPopupTransientWindow(parent, wxPU_CONTAINS_CONTROLS) {
|
||||
create();
|
||||
}
|
||||
|
||||
@@ -28,9 +33,13 @@ void AMSMaterialsSetting::create()
|
||||
|
||||
m_sizer_filament->Add(0, 0, 0, wxEXPAND, 0);
|
||||
|
||||
#ifdef __APPLE__
|
||||
m_comboBox_filament_mac = new wxComboBox(m_panel_body, wxID_ANY, wxEmptyString, wxDefaultPosition, AMS_MATERIALS_SETTING_COMBOX_WIDTH, 0, nullptr, wxCB_READONLY);
|
||||
#else
|
||||
m_comboBox_filament = new ::ComboBox(m_panel_body, wxID_ANY, wxEmptyString, wxDefaultPosition, AMS_MATERIALS_SETTING_COMBOX_WIDTH, 0, nullptr, wxCB_READONLY);
|
||||
m_sizer_filament->Add(m_comboBox_filament, 0, wxALIGN_CENTER, 0);
|
||||
#endif
|
||||
|
||||
m_sizer_filament->Add(COMBOBOX_FILAMENT, 1, wxALIGN_CENTER, 0);
|
||||
wxBoxSizer *m_sizer_colour = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
m_title_colour = new wxStaticText(m_panel_body, wxID_ANY, _L("Colour"), wxDefaultPosition, wxSize(AMS_MATERIALS_SETTING_LABEL_WIDTH, -1), 0);
|
||||
@@ -77,18 +86,18 @@ void AMSMaterialsSetting::create()
|
||||
|
||||
wxBoxSizer *sizer_other = new wxBoxSizer(wxVERTICAL);
|
||||
wxBoxSizer *sizer_tempinput = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
|
||||
m_input_nozzle_max = new ::TextInput(m_panel_body, wxEmptyString, wxEmptyString, wxEmptyString, wxDefaultPosition, AMS_MATERIALS_SETTING_INPUT_SIZE,
|
||||
wxTE_CENTRE | wxTE_PROCESS_ENTER);
|
||||
m_input_nozzle_max = new ::TextInput(m_panel_body, wxEmptyString, wxEmptyString, wxEmptyString, wxDefaultPosition, AMS_MATERIALS_SETTING_INPUT_SIZE, wxTE_CENTRE | wxTE_PROCESS_ENTER);
|
||||
m_input_nozzle_min = new ::TextInput(m_panel_body, wxEmptyString, wxEmptyString, wxEmptyString, wxDefaultPosition, AMS_MATERIALS_SETTING_INPUT_SIZE, wxTE_CENTRE | wxTE_PROCESS_ENTER);
|
||||
m_input_nozzle_max->Enable(false);
|
||||
m_input_nozzle_min->Enable(false);
|
||||
|
||||
m_input_nozzle_max->GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
|
||||
m_input_nozzle_max->GetTextCtrl()->SetSize(wxSize(-1, FromDIP(20)));
|
||||
auto bitmap_max_degree = new wxStaticBitmap(m_panel_body, -1, create_scaled_bitmap("degree", nullptr, 16), wxDefaultPosition, wxDefaultSize);
|
||||
|
||||
m_input_nozzle_min = new ::TextInput(m_panel_body, wxEmptyString, wxEmptyString, wxEmptyString, wxDefaultPosition, AMS_MATERIALS_SETTING_INPUT_SIZE,
|
||||
wxTE_CENTRE | wxTE_PROCESS_ENTER);
|
||||
m_input_nozzle_min->GetTextCtrl()->SetSize(wxSize(-1, FromDIP(20)));
|
||||
m_input_nozzle_min->GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
|
||||
m_input_nozzle_min->GetTextCtrl()->SetSize(wxSize(-1, FromDIP(20)));
|
||||
|
||||
auto bitmap_max_degree = new wxStaticBitmap(m_panel_body, -1, create_scaled_bitmap("degree", nullptr, 16), wxDefaultPosition, wxDefaultSize);
|
||||
auto bitmap_min_degree = new wxStaticBitmap(m_panel_body, -1, create_scaled_bitmap("degree", nullptr, 16), wxDefaultPosition, wxDefaultSize);
|
||||
|
||||
sizer_tempinput->Add(m_input_nozzle_max, 1, wxALIGN_CENTER, 0);
|
||||
@@ -125,7 +134,7 @@ void AMSMaterialsSetting::create()
|
||||
warning_text->SetMinSize(wxSize(AMS_MATERIALS_SETTING_BODY_WIDTH, -1));
|
||||
warning_text->Hide();
|
||||
|
||||
m_input_nozzle_min->GetTextCtrl()->Bind(wxEVT_SET_FOCUS, [this](wxFocusEvent &e) {
|
||||
m_input_nozzle_min->GetTextCtrl()->Bind(wxEVT_SET_FOCUS, [this](wxFocusEvent &e) {
|
||||
warning_text->Hide();
|
||||
Layout();
|
||||
Fit();
|
||||
@@ -135,22 +144,22 @@ void AMSMaterialsSetting::create()
|
||||
input_min_finish();
|
||||
e.Skip();
|
||||
});
|
||||
m_input_nozzle_min->GetTextCtrl()->Bind(wxEVT_KILL_FOCUS, [this](wxFocusEvent &e) {
|
||||
m_input_nozzle_min->GetTextCtrl()->Bind(wxEVT_KILL_FOCUS, [this](wxFocusEvent &e) {
|
||||
input_min_finish();
|
||||
e.Skip();
|
||||
});
|
||||
|
||||
m_input_nozzle_max->GetTextCtrl()->Bind(wxEVT_SET_FOCUS, [this](wxFocusEvent& e) {
|
||||
m_input_nozzle_max->GetTextCtrl()->Bind(wxEVT_SET_FOCUS, [this](wxFocusEvent &e) {
|
||||
warning_text->Hide();
|
||||
Layout();
|
||||
Fit();
|
||||
e.Skip();
|
||||
});
|
||||
m_input_nozzle_max->GetTextCtrl()->Bind(wxEVT_TEXT_ENTER, [this](wxCommandEvent& e) {
|
||||
m_input_nozzle_max->GetTextCtrl()->Bind(wxEVT_TEXT_ENTER, [this](wxCommandEvent &e) {
|
||||
input_max_finish();
|
||||
e.Skip();
|
||||
});
|
||||
m_input_nozzle_max->GetTextCtrl()->Bind(wxEVT_KILL_FOCUS, [this](wxFocusEvent& e) {
|
||||
m_input_nozzle_max->GetTextCtrl()->Bind(wxEVT_KILL_FOCUS, [this](wxFocusEvent &e) {
|
||||
input_max_finish();
|
||||
e.Skip();
|
||||
});
|
||||
@@ -170,13 +179,6 @@ void AMSMaterialsSetting::create()
|
||||
m_button_confirm->Bind(wxEVT_LEFT_DOWN, &AMSMaterialsSetting::on_select_ok, this);
|
||||
m_sizer_button->Add(m_button_confirm, 0, wxALIGN_CENTER, 0);
|
||||
|
||||
|
||||
|
||||
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));
|
||||
StateColor btn_bd_white(std::pair<wxColour, int>(*wxWHITE, StateColor::Disabled), std::pair<wxColour, int>(wxColour(38, 46, 48), StateColor::Enabled));
|
||||
|
||||
m_sizer_body->Add(m_sizer_filament, 0, wxEXPAND, 0);
|
||||
m_sizer_body->Add(0, 0, 0, wxEXPAND | wxTOP, FromDIP(16));
|
||||
m_sizer_body->Add(m_sizer_colour, 0, wxEXPAND, 0);
|
||||
@@ -200,7 +202,7 @@ void AMSMaterialsSetting::create()
|
||||
this->Centre(wxBOTH);
|
||||
|
||||
Bind(wxEVT_PAINT, &AMSMaterialsSetting::paintEvent, this);
|
||||
m_comboBox_filament->Connect(wxEVT_COMMAND_COMBOBOX_SELECTED, wxCommandEventHandler(AMSMaterialsSetting::on_select_filament), NULL, this);
|
||||
COMBOBOX_FILAMENT->Connect(wxEVT_COMMAND_COMBOBOX_SELECTED, wxCommandEventHandler(AMSMaterialsSetting::on_select_filament), NULL, this);
|
||||
}
|
||||
|
||||
void AMSMaterialsSetting::paintEvent(wxPaintEvent &evt)
|
||||
@@ -214,13 +216,13 @@ void AMSMaterialsSetting::paintEvent(wxPaintEvent &evt)
|
||||
|
||||
AMSMaterialsSetting::~AMSMaterialsSetting()
|
||||
{
|
||||
m_comboBox_filament->Disconnect(wxEVT_COMMAND_COMBOBOX_SELECTED, wxCommandEventHandler(AMSMaterialsSetting::on_select_filament), NULL, this);
|
||||
COMBOBOX_FILAMENT->Disconnect(wxEVT_COMMAND_COMBOBOX_SELECTED, wxCommandEventHandler(AMSMaterialsSetting::on_select_filament), NULL, this);
|
||||
}
|
||||
|
||||
|
||||
void AMSMaterialsSetting::input_min_finish()
|
||||
{
|
||||
if (m_input_nozzle_min->GetTextCtrl()->GetValue().empty())return;
|
||||
if (m_input_nozzle_min->GetTextCtrl()->GetValue().empty()) return;
|
||||
|
||||
auto val = std::atoi(m_input_nozzle_min->GetTextCtrl()->GetValue().c_str());
|
||||
|
||||
@@ -235,7 +237,7 @@ void AMSMaterialsSetting::input_min_finish()
|
||||
|
||||
void AMSMaterialsSetting::input_max_finish()
|
||||
{
|
||||
if (m_input_nozzle_max->GetTextCtrl()->GetValue().empty())return;
|
||||
if (m_input_nozzle_max->GetTextCtrl()->GetValue().empty()) return;
|
||||
|
||||
auto val = std::atoi(m_input_nozzle_max->GetTextCtrl()->GetValue().c_str());
|
||||
|
||||
@@ -279,8 +281,8 @@ void AMSMaterialsSetting::enable_confirm_button(bool en)
|
||||
|
||||
void AMSMaterialsSetting::on_select_ok(wxMouseEvent &event)
|
||||
{
|
||||
wxString nozzle_temp_min = m_input_nozzle_min->GetTextCtrl()->GetValue();
|
||||
auto filament = m_comboBox_filament->GetValue();
|
||||
wxString nozzle_temp_min = m_input_nozzle_min->GetTextCtrl()->GetValue();
|
||||
auto filament = COMBOBOX_FILAMENT->GetValue();
|
||||
|
||||
wxString nozzle_temp_max = m_input_nozzle_max->GetTextCtrl()->GetValue();
|
||||
|
||||
@@ -295,7 +297,7 @@ void AMSMaterialsSetting::on_select_ok(wxMouseEvent &event)
|
||||
PresetBundle *preset_bundle = wxGetApp().preset_bundle;
|
||||
if (preset_bundle) {
|
||||
for (auto it = preset_bundle->filaments.begin(); it != preset_bundle->filaments.end(); it++) {
|
||||
if (it->alias.compare(m_comboBox_filament->GetValue().ToStdString()) == 0) {
|
||||
if (it->alias.compare(COMBOBOX_FILAMENT->GetValue().ToStdString()) == 0) {
|
||||
ams_filament_id = it->filament_id;
|
||||
}
|
||||
}
|
||||
@@ -313,19 +315,12 @@ void AMSMaterialsSetting::on_select_ok(wxMouseEvent &event)
|
||||
|
||||
void AMSMaterialsSetting::set_color(wxColour color)
|
||||
{
|
||||
m_clrData = new wxColourData();
|
||||
m_clrData->SetColour(color);
|
||||
}
|
||||
|
||||
static bool show_flag;
|
||||
void AMSMaterialsSetting::on_clr_picker(wxCommandEvent & event) {
|
||||
|
||||
void AMSMaterialsSetting::on_clr_picker(wxCommandEvent & event)
|
||||
{
|
||||
auto clr_dialog = new wxColourDialog(this, m_clrData);
|
||||
|
||||
clr_dialog->Bind(wxEVT_ACTIVATE, [this](wxActivateEvent &e) {
|
||||
int a ;
|
||||
});
|
||||
|
||||
show_flag = true;
|
||||
if (clr_dialog->ShowModal() == wxID_OK) {
|
||||
m_clrData = &(clr_dialog->GetColourData());
|
||||
@@ -338,12 +333,14 @@ void AMSMaterialsSetting::Dismiss()
|
||||
if (show_flag)
|
||||
{
|
||||
show_flag = false;
|
||||
}
|
||||
else
|
||||
} else
|
||||
{
|
||||
wxPopupTransientWindow::Dismiss();
|
||||
#ifdef __APPLE__
|
||||
|
||||
#else
|
||||
wxPopupTransientWindow::Dismiss();
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool AMSMaterialsSetting::Show(bool show)
|
||||
@@ -360,12 +357,14 @@ void AMSMaterialsSetting::Popup(bool show, bool third, wxString filament, wxColo
|
||||
{
|
||||
if (!m_is_third) {
|
||||
m_panel_SN->Show();
|
||||
m_comboBox_filament->SetValue(filament);
|
||||
COMBOBOX_FILAMENT->SetValue(filament);
|
||||
m_sn_number->SetLabelText(sn);
|
||||
m_input_nozzle_min->GetTextCtrl()->SetValue(tep);
|
||||
m_clrData->SetColour(colour);
|
||||
m_comboBox_filament->Disable();
|
||||
COMBOBOX_FILAMENT->Disable();
|
||||
|
||||
m_input_nozzle_min->Disable();
|
||||
|
||||
wxPopupTransientWindow::Popup();
|
||||
Layout();
|
||||
return;
|
||||
@@ -438,13 +437,13 @@ void AMSMaterialsSetting::Popup(bool show, bool third, wxString filament, wxColo
|
||||
}
|
||||
}
|
||||
}
|
||||
m_comboBox_filament->Set(filament_items);
|
||||
COMBOBOX_FILAMENT->Set(filament_items);
|
||||
if (selection_idx >= 0 && selection_idx < filament_items.size()) {
|
||||
m_comboBox_filament->SetSelection(selection_idx);
|
||||
COMBOBOX_FILAMENT->SetSelection(selection_idx);
|
||||
post_select_event();
|
||||
}
|
||||
else {
|
||||
m_comboBox_filament->SetSelection(selection_idx);
|
||||
COMBOBOX_FILAMENT->SetSelection(selection_idx);
|
||||
post_select_event();
|
||||
}
|
||||
}
|
||||
@@ -453,8 +452,8 @@ void AMSMaterialsSetting::Popup(bool show, bool third, wxString filament, wxColo
|
||||
|
||||
void AMSMaterialsSetting::post_select_event() {
|
||||
wxCommandEvent event(wxEVT_COMBOBOX);
|
||||
event.SetEventObject(m_comboBox_filament);
|
||||
wxPostEvent(m_comboBox_filament, event);
|
||||
event.SetEventObject(COMBOBOX_FILAMENT);
|
||||
wxPostEvent(COMBOBOX_FILAMENT, event);
|
||||
}
|
||||
|
||||
void AMSMaterialsSetting::on_select_filament(wxCommandEvent &evt)
|
||||
@@ -464,7 +463,7 @@ void AMSMaterialsSetting::on_select_filament(wxCommandEvent &evt)
|
||||
if (preset_bundle) {
|
||||
for (auto it = preset_bundle->filaments.begin(); it != preset_bundle->filaments.end(); it++) {
|
||||
auto a = it->alias;
|
||||
if (it->alias.compare(m_comboBox_filament->GetValue().ToStdString()) == 0) {
|
||||
if (it->alias.compare(COMBOBOX_FILAMENT->GetValue().ToStdString()) == 0) {
|
||||
// ) if nozzle_temperature_range is found
|
||||
ConfigOption* opt_min = it->config.option("nozzle_temperature_range_low");
|
||||
if (opt_min) {
|
||||
@@ -498,10 +497,24 @@ void AMSMaterialsSetting::on_select_filament(wxCommandEvent &evt)
|
||||
}
|
||||
}
|
||||
if (m_input_nozzle_min->GetTextCtrl()->GetValue().IsEmpty()) {
|
||||
m_input_nozzle_min->GetTextCtrl()->SetValue("220");
|
||||
m_input_nozzle_min->GetTextCtrl()->SetValue("220");
|
||||
}
|
||||
if (m_input_nozzle_max->GetTextCtrl()->GetValue().IsEmpty()) {
|
||||
m_input_nozzle_max->GetTextCtrl()->SetValue("220");
|
||||
m_input_nozzle_max->GetTextCtrl()->SetValue("220");
|
||||
}
|
||||
}
|
||||
|
||||
bool AMSMaterialsSetting::ProcessLeftDown(wxMouseEvent &evt)
|
||||
{
|
||||
wxPoint mouse_pos = ClientToScreen(evt.GetPosition());
|
||||
wxPoint top_left = this->ClientToScreen(wxPoint(0, 0));
|
||||
wxPoint range = wxPoint(this->GetRect().width, this->GetRect().height);
|
||||
wxPoint bottom_right = top_left + range;
|
||||
if (mouse_pos.x > top_left.x && mouse_pos.y > top_left.y && mouse_pos.x < bottom_right.x && mouse_pos.y < bottom_right.y) {
|
||||
return true;
|
||||
} else {
|
||||
wxPopupTransientWindow::Dismiss();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,13 +39,13 @@ public:
|
||||
void input_max_finish();
|
||||
void update();
|
||||
void enable_confirm_button(bool en);
|
||||
void on_select_cancel(wxMouseEvent &event);
|
||||
void Dismiss() override;
|
||||
bool Show(bool show) override;
|
||||
void Popup(bool show, bool third = true, wxString filament = wxEmptyString, wxColour colour = *wxWHITE, wxString sn = wxEmptyString, wxString tep = wxEmptyString);
|
||||
|
||||
void post_select_event();
|
||||
void on_select_ok(wxMouseEvent &event);
|
||||
|
||||
void set_color(wxColour color);
|
||||
|
||||
void on_clr_picker(wxCommandEvent &event);
|
||||
@@ -67,6 +67,8 @@ protected:
|
||||
//void on_dpi_changed(const wxRect &suggested_rect) override;
|
||||
void on_select_filament(wxCommandEvent& evt);
|
||||
|
||||
bool ProcessLeftDown(wxMouseEvent &evt);
|
||||
|
||||
protected:
|
||||
StateColor m_btn_bg_green;
|
||||
wxPanel * m_panel_SN;
|
||||
@@ -82,6 +84,9 @@ protected:
|
||||
TextInput * m_input_nozzle_min;
|
||||
TextInput* m_input_nozzle_max;
|
||||
Button * m_button_confirm;
|
||||
#ifdef __APPLE__
|
||||
wxComboBox *m_comboBox_filament_mac;
|
||||
#endif
|
||||
wxColourData * m_clrData;
|
||||
|
||||
};
|
||||
|
||||
@@ -80,7 +80,7 @@ CopyrightsDialog::CopyrightsDialog()
|
||||
|
||||
SetSizer(sizer);
|
||||
sizer->SetSizeHints(this);
|
||||
|
||||
CenterOnParent();
|
||||
}
|
||||
|
||||
void CopyrightsDialog::fill_entries()
|
||||
@@ -88,6 +88,7 @@ void CopyrightsDialog::fill_entries()
|
||||
m_entries = {
|
||||
{ "Admesh", "", "https://admesh.readthedocs.io/" },
|
||||
{ "Anti-Grain Geometry", "", "http://antigrain.com" },
|
||||
{ "ArcWelderLib", "", "https://plugins.octoprint.org/plugins/arc_welder" },
|
||||
{ "Boost", "", "http://www.boost.org" },
|
||||
{ "Cereal", "", "http://uscilab.github.io/cereal" },
|
||||
{ "CGAL", "", "https://www.cgal.org" },
|
||||
@@ -115,6 +116,7 @@ void CopyrightsDialog::fill_entries()
|
||||
{ "Real-Time DXT1/DXT5 C compression library", "", "https://github.com/Cyan4973/RygsDXTc" },
|
||||
{ "SemVer", "", "https://semver.org" },
|
||||
{ "Shinyprofiler", "", "https://code.google.com/p/shinyprofiler" },
|
||||
{ "SuperSlicer", "", "https://github.com/supermerill/SuperSlicer" },
|
||||
{ "TBB", "", "https://www.intel.cn/content/www/cn/zh/developer/tools/oneapi/onetbb.html" },
|
||||
{ "wxWidgets", "", "https://www.wxwidgets.org" },
|
||||
{ "zlib", "", "http://zlib.net" },
|
||||
@@ -219,7 +221,7 @@ AboutDialog::AboutDialog()
|
||||
std::string icon_path = (boost::format("%1%/images/BambuStudioTitle.ico") % resources_dir()).str();
|
||||
SetIcon(wxIcon(encode_path(icon_path.c_str()), wxBITMAP_TYPE_ICO));
|
||||
|
||||
wxPanel *m_panel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(FromDIP(430), FromDIP(237)), wxTAB_TRAVERSAL);
|
||||
wxPanel *m_panel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(FromDIP(560), FromDIP(237)), wxTAB_TRAVERSAL);
|
||||
|
||||
wxBoxSizer *panel_versizer = new wxBoxSizer(wxVERTICAL);
|
||||
wxBoxSizer *vesizer = new wxBoxSizer(wxVERTICAL);
|
||||
@@ -233,7 +235,7 @@ AboutDialog::AboutDialog()
|
||||
main_sizer->Add(ver_sizer, 0, wxEXPAND | wxALL, 0);
|
||||
|
||||
// logo
|
||||
m_logo_bitmap = ScalableBitmap(this, "BambuStudio_about", 240);
|
||||
m_logo_bitmap = ScalableBitmap(this, "BambuStudio_about", 250);
|
||||
m_logo = new wxStaticBitmap(this, wxID_ANY, m_logo_bitmap.bmp(), wxDefaultPosition,wxDefaultSize, 0);
|
||||
m_logo->SetSizer(vesizer);
|
||||
|
||||
@@ -250,20 +252,70 @@ AboutDialog::AboutDialog()
|
||||
#else
|
||||
version_font.SetPointSize(11);
|
||||
#endif
|
||||
version_font.SetPointSize(12);
|
||||
version_font.SetPointSize(FromDIP(16));
|
||||
version->SetFont(version_font);
|
||||
version->SetForegroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT));
|
||||
version->SetForegroundColour(wxColour(255, 255, 255));
|
||||
version->SetBackgroundColour(wxColour(0, 174, 66));
|
||||
vesizer->Add(version, 0, wxALL | wxALIGN_CENTER_HORIZONTAL, FromDIP(5));
|
||||
vesizer->Add(0, 0, 1, wxEXPAND, FromDIP(5));
|
||||
}
|
||||
|
||||
wxBoxSizer *text_sizer_horiz = new wxBoxSizer(wxHORIZONTAL);
|
||||
wxBoxSizer *text_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
text_sizer_horiz->Add( 0, 0, 0, wxLEFT, FromDIP(23));
|
||||
|
||||
std::vector<wxString> text_list;
|
||||
text_list.push_back(_L("Bambu Studio is based on PrusaSlicer by PrusaResearch and SuperSlicer by Merill(supermerill)."));
|
||||
text_list.push_back(_L("PrusaSlicer is originally based on Slic3r by Alessandro Ranellucci."));
|
||||
text_list.push_back(_L("Slic3r was created by Alessandro Ranellucci with the help of many other contributors."));
|
||||
text_list.push_back(_L("Bambu Studio also referenced some ideas from Cura by Ultimaker."));
|
||||
text_list.push_back(_L("There many parts of the software that come from community contributions, so we're unable to list them one-by-one, and instead, they'll be attributed in the corresponding code comments."));
|
||||
|
||||
text_sizer->Add( 0, 0, 0, wxTOP, FromDIP(33));
|
||||
bool is_zh = wxGetApp().app_config->get("language") == "zh_CN";
|
||||
for (int i = 0; i < text_list.size(); i++)
|
||||
{
|
||||
auto staticText = new wxStaticText( this, wxID_ANY, wxEmptyString,wxDefaultPosition,wxSize(FromDIP(520), -1), wxALIGN_LEFT );
|
||||
staticText->SetForegroundColour(wxColour(107, 107, 107));
|
||||
staticText->SetMinSize(wxSize(FromDIP(520), -1));
|
||||
staticText->SetFont(Label::Body_12);
|
||||
if (is_zh) {
|
||||
wxString find_txt = "";
|
||||
wxString count_txt = "";
|
||||
for (auto o = 0; o < text_list[i].length(); o++) {
|
||||
auto size = staticText->GetTextExtent(count_txt);
|
||||
if (size.x < FromDIP(506)) {
|
||||
find_txt += text_list[i][o];
|
||||
count_txt += text_list[i][o];
|
||||
} else {
|
||||
find_txt += std::string("\n") + text_list[i][o];
|
||||
count_txt = text_list[i][o];
|
||||
}
|
||||
}
|
||||
staticText->SetLabel(find_txt);
|
||||
} else {
|
||||
staticText->SetLabel(text_list[i]);
|
||||
staticText->Wrap(FromDIP(520));
|
||||
}
|
||||
|
||||
text_sizer->Add( staticText, 0, wxUP | wxDOWN, FromDIP(3));
|
||||
}
|
||||
|
||||
text_sizer_horiz->Add(text_sizer, 1, wxALL,0);
|
||||
ver_sizer->Add(text_sizer_horiz, 0, wxALL,0);
|
||||
ver_sizer->Add( 0, 0, 0, wxTOP, FromDIP(43));
|
||||
|
||||
wxBoxSizer *copyright_ver_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
wxBoxSizer *copyright_hor_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
copyright_hor_sizer->Add(copyright_ver_sizer, 0, wxALL,5);
|
||||
copyright_hor_sizer->Add( 0, 0, 0, wxLEFT, FromDIP(120));
|
||||
|
||||
wxStaticText *html_text = new wxStaticText(this, wxID_ANY, "Copyright(C) 2021-2022 Bambu Lab", wxDefaultPosition, wxDefaultSize);
|
||||
ver_sizer->Add(0, 0, 0, wxTOP, FromDIP(38));
|
||||
html_text->SetForegroundColour(wxColour(107, 107, 107));
|
||||
ver_sizer->Add(html_text, 0, wxALL | wxALIGN_CENTER_HORIZONTAL, 0);
|
||||
|
||||
copyright_ver_sizer->Add(html_text, 0, wxALL , 0);
|
||||
|
||||
// text
|
||||
m_html = new wxHtmlWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHW_SCROLLBAR_NEVER /*NEVER*/);
|
||||
{
|
||||
wxFont font = get_default_font(this);
|
||||
@@ -276,12 +328,12 @@ AboutDialog::AboutDialog()
|
||||
(boost::format(
|
||||
"<html>"
|
||||
"<body>"
|
||||
"<p style=\"text-align:center\"><a href=\"www.bambulab.com\">www.bambulab.com</ a></p>"
|
||||
"<p style=\"text-align:left\"><a href=\"www.bambulab.com\">www.bambulab.com</ a></p>"
|
||||
"</body>"
|
||||
"</html>")
|
||||
).str());
|
||||
m_html->SetPage(text);
|
||||
ver_sizer->Add(m_html, 0, wxEXPAND, 0);
|
||||
copyright_ver_sizer->Add(m_html, 0, wxEXPAND, 0);
|
||||
m_html->Bind(wxEVT_HTML_LINK_CLICKED, &AboutDialog::onLinkClicked, this);
|
||||
}
|
||||
//Add "Portions copyright" button
|
||||
@@ -298,14 +350,21 @@ AboutDialog::AboutDialog()
|
||||
button_portions->SetCornerRadius(FromDIP(12));
|
||||
button_portions->SetMinSize(wxSize(FromDIP(120), FromDIP(24)));
|
||||
|
||||
ver_sizer->Add( 0, 0, 0, wxTOP, FromDIP(22));
|
||||
ver_sizer->Add(button_portions, 0, wxALIGN_CENTER_HORIZONTAL|wxALL,0);
|
||||
ver_sizer->Add( 0, 0, 0, wxTOP, FromDIP(38));
|
||||
wxBoxSizer *copyright_button_ver = new wxBoxSizer(wxVERTICAL);
|
||||
copyright_button_ver->Add( 0, 0, 0, wxTOP, FromDIP(10));
|
||||
copyright_button_ver->Add(button_portions, 0, wxALL,0);
|
||||
|
||||
copyright_hor_sizer->Add(copyright_button_ver, 0, wxALL,0);
|
||||
copyright_hor_sizer->Add( 0, 0, 0, wxRIGHT, FromDIP(13));
|
||||
|
||||
ver_sizer->Add(copyright_hor_sizer, 0, wxALIGN_CENTER_HORIZONTAL|wxALL,0);
|
||||
ver_sizer->Add( 0, 0, 0, wxTOP, FromDIP(30));
|
||||
button_portions->Bind(wxEVT_BUTTON, &AboutDialog::onCopyrightBtn, this);
|
||||
|
||||
m_panel->Layout();
|
||||
SetSizer(main_sizer);
|
||||
main_sizer->SetSizeHints(this);
|
||||
Layout();
|
||||
Fit();
|
||||
CenterOnParent();
|
||||
}
|
||||
|
||||
void AboutDialog::on_dpi_changed(const wxRect &suggested_rect)
|
||||
|
||||
@@ -48,11 +48,12 @@ wxDEFINE_EVENT(EVT_SET_FINISH_MAPPING, wxCommandEvent);
|
||||
|
||||
void MaterialItem::msw_rescale() {}
|
||||
|
||||
void MaterialItem::set_ams_info(wxColour col, wxString txt)
|
||||
void MaterialItem::set_ams_info(wxColour col, wxString txt)
|
||||
{
|
||||
m_ams_coloul = col;
|
||||
m_ams_name = txt;
|
||||
Refresh();
|
||||
auto need_refresh = false;
|
||||
if (m_ams_coloul != col) { m_ams_coloul = col; need_refresh = true;}
|
||||
if (m_ams_name != txt) {m_ams_name = txt;need_refresh = true;}
|
||||
if (need_refresh) { Refresh();}
|
||||
}
|
||||
|
||||
void MaterialItem::on_selected()
|
||||
@@ -74,17 +75,22 @@ void MaterialItem::on_warning()
|
||||
|
||||
void MaterialItem::on_normal()
|
||||
{
|
||||
m_selected = false;
|
||||
m_warning = false;
|
||||
Refresh();
|
||||
if (m_selected || m_warning) {
|
||||
m_selected = false;
|
||||
m_warning = false;
|
||||
Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void MaterialItem::paintEvent(wxPaintEvent &evt)
|
||||
{
|
||||
wxPaintDC dc(this);
|
||||
render(dc);
|
||||
|
||||
//PrepareDC(buffdc);
|
||||
//PrepareDC(dc);
|
||||
|
||||
}
|
||||
|
||||
void MaterialItem::render(wxDC &dc)
|
||||
@@ -107,29 +113,33 @@ void MaterialItem::render(wxDC &dc)
|
||||
doRender(dc);
|
||||
#endif
|
||||
|
||||
//materials name
|
||||
dc.SetFont(::Label::Body_13);
|
||||
// materials name
|
||||
dc.SetFont(::Label::Body_13);
|
||||
|
||||
auto material_name_colour = m_material_coloul.GetLuminance() < 0.5 ? *wxWHITE : wxColour(0x26,0x2E,0x30);
|
||||
dc.SetTextForeground(material_name_colour);
|
||||
auto material_name_colour = m_material_coloul.GetLuminance() < 0.5 ? *wxWHITE : wxColour(0x26, 0x2E, 0x30);
|
||||
dc.SetTextForeground(material_name_colour);
|
||||
|
||||
auto material_txt_size = dc.GetTextExtent(m_material_name);
|
||||
dc.DrawText(m_material_name, wxPoint((MATERIAL_ITEM_SIZE.x - material_txt_size.x) / 2, FromDIP(3)));
|
||||
if (dc.GetTextExtent(m_material_name).x > GetSize().x - 10) {
|
||||
dc.SetFont(::Label::Body_10);
|
||||
|
||||
//mapping num
|
||||
dc.SetFont(::Label::Body_10);
|
||||
dc.SetTextForeground(m_ams_coloul.GetLuminance() < 0.5 ? *wxWHITE : wxColour(0x26,0x2E,0x30));
|
||||
}
|
||||
|
||||
auto material_txt_size = dc.GetTextExtent(m_material_name);
|
||||
dc.DrawText(m_material_name, wxPoint((MATERIAL_ITEM_SIZE.x - material_txt_size.x) / 2, (FromDIP(22) - material_txt_size.y) / 2));
|
||||
|
||||
wxString mapping_txt = wxEmptyString;
|
||||
if (m_ams_name.empty()) {
|
||||
mapping_txt = "-";
|
||||
}else{
|
||||
mapping_txt = m_ams_name;
|
||||
}
|
||||
|
||||
auto mapping_txt_size = dc.GetTextExtent(mapping_txt);
|
||||
dc.DrawText(mapping_txt, wxPoint((MATERIAL_ITEM_SIZE.x - mapping_txt_size.x) / 2, FromDIP(2) + material_txt_size.y ));
|
||||
// mapping num
|
||||
dc.SetFont(::Label::Body_10);
|
||||
dc.SetTextForeground(m_ams_coloul.GetLuminance() < 0.5 ? *wxWHITE : wxColour(0x26, 0x2E, 0x30));
|
||||
|
||||
wxString mapping_txt = wxEmptyString;
|
||||
if (m_ams_name.empty()) {
|
||||
mapping_txt = "-";
|
||||
} else {
|
||||
mapping_txt = m_ams_name;
|
||||
}
|
||||
|
||||
auto mapping_txt_size = dc.GetTextExtent(mapping_txt);
|
||||
dc.DrawText(mapping_txt, wxPoint((MATERIAL_ITEM_SIZE.x - mapping_txt_size.x) / 2, FromDIP(20) + (FromDIP(14) - mapping_txt_size.y) / 2));
|
||||
}
|
||||
|
||||
void MaterialItem::doRender(wxDC &dc)
|
||||
@@ -137,36 +147,33 @@ void MaterialItem::doRender(wxDC &dc)
|
||||
//top
|
||||
dc.SetPen(*wxTRANSPARENT_PEN);
|
||||
dc.SetBrush(wxBrush(m_material_coloul));
|
||||
dc.DrawRoundedRectangle(FromDIP(3), FromDIP(3), MATERIAL_ITEM_SIZE.x - FromDIP(6), MATERIAL_ITEM_SIZE.y / 2, 5);
|
||||
dc.DrawRoundedRectangle(FromDIP(1), FromDIP(1), MATERIAL_ITEM_REAL_SIZE.x, FromDIP(18), 5);
|
||||
|
||||
//bottom
|
||||
dc.SetPen(*wxTRANSPARENT_PEN);
|
||||
dc.SetBrush(wxBrush(wxColour(m_ams_coloul)));
|
||||
dc.DrawRoundedRectangle(FromDIP(3), MATERIAL_ITEM_SIZE.y / 2 - FromDIP(2), MATERIAL_ITEM_SIZE.x - FromDIP(6), MATERIAL_ITEM_SIZE.y / 2, 5);
|
||||
dc.DrawRoundedRectangle(FromDIP(1), FromDIP(18), MATERIAL_ITEM_REAL_SIZE.x, FromDIP(16), 5);
|
||||
|
||||
//middle
|
||||
////middle
|
||||
dc.SetPen(*wxTRANSPARENT_PEN);
|
||||
dc.SetBrush(wxBrush(m_material_coloul));
|
||||
dc.DrawRectangle(FromDIP(3), FromDIP(10), MATERIAL_ITEM_SIZE.x - FromDIP(6), FromDIP(8));
|
||||
dc.DrawRectangle(FromDIP(1), FromDIP(11), MATERIAL_ITEM_REAL_SIZE.x, FromDIP(8));
|
||||
|
||||
//border
|
||||
if (m_material_coloul == *wxWHITE) {
|
||||
dc.SetPen(*wxTRANSPARENT_PEN);
|
||||
dc.SetBrush(wxBrush(m_ams_coloul));
|
||||
dc.DrawRectangle(FromDIP(1), FromDIP(18), MATERIAL_ITEM_REAL_SIZE.x, FromDIP(8));
|
||||
|
||||
////border
|
||||
if (m_material_coloul == *wxWHITE || m_ams_coloul == *wxWHITE) {
|
||||
dc.SetPen(wxColour(0xAC, 0xAC, 0xAC));
|
||||
dc.SetBrush(*wxTRANSPARENT_BRUSH);
|
||||
dc.DrawRoundedRectangle(3, 3, MATERIAL_ITEM_SIZE.x -6, MATERIAL_ITEM_SIZE.y - 6, 5);
|
||||
dc.DrawRoundedRectangle(0, 0, MATERIAL_ITEM_SIZE.x, MATERIAL_ITEM_SIZE.y, 5);
|
||||
}
|
||||
|
||||
|
||||
if (m_selected) {
|
||||
dc.SetPen(wxColour(0x00, 0xAE, 0x42));
|
||||
dc.SetBrush(*wxTRANSPARENT_BRUSH);
|
||||
dc.DrawRoundedRectangle(1, 1, MATERIAL_ITEM_SIZE.x - 2, MATERIAL_ITEM_SIZE.y - 2, 5);
|
||||
}
|
||||
|
||||
if (m_warning) {
|
||||
dc.SetPen(wxColour(0xFF, 0x6F, 0x00));
|
||||
dc.SetBrush(*wxTRANSPARENT_BRUSH);
|
||||
dc.DrawRoundedRectangle(1, 1, MATERIAL_ITEM_SIZE.x - 2, MATERIAL_ITEM_SIZE.y - 2, 5);
|
||||
dc.DrawRoundedRectangle(0, 0, MATERIAL_ITEM_SIZE.x, MATERIAL_ITEM_SIZE.y, 5);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,10 +193,6 @@ void MaterialItem::doRender(wxDC &dc)
|
||||
Layout();
|
||||
}
|
||||
|
||||
void AmsMapingPopup::Popup(wxWindow *focus /*= NULL*/)
|
||||
{
|
||||
wxPopupTransientWindow::Popup();
|
||||
}
|
||||
|
||||
void AmsMapingPopup::update_materials_list(std::vector<std::string> list)
|
||||
{
|
||||
@@ -210,6 +213,11 @@ bool AmsMapingPopup::is_match_material(int id, std::string material)
|
||||
|
||||
void AmsMapingPopup::update_ams_data(std::map<std::string, Ams*> amsList)
|
||||
{
|
||||
if (m_amsmapping_sizer_list.size() > 0) {
|
||||
for (wxBoxSizer *bz : m_amsmapping_sizer_list) { bz->Clear(true); }
|
||||
m_amsmapping_sizer_list.clear();
|
||||
}
|
||||
|
||||
std::map<std::string, Ams *>::iterator ams_iter;
|
||||
|
||||
BOOST_LOG_TRIVIAL(trace) << "ams_mapping total count " << amsList.size();
|
||||
@@ -229,8 +237,6 @@ void AmsMapingPopup::update_ams_data(std::map<std::string, Ams*> amsList)
|
||||
|
||||
td.id = ams_indx * AMS_TOTAL_COUNT + atoi(tray_data->id.c_str());
|
||||
|
||||
BOOST_LOG_TRIVIAL(trace) << "ams_mapping ams data ==type==" << tray_data->type << "==colour=="<<tray_data->color << "==trayid=="<<tray_data->id.c_str() << "==ftrayid=="<<td.id;
|
||||
|
||||
if (!tray_data->is_exists) {
|
||||
td.type = EMPTY;
|
||||
} else {
|
||||
@@ -254,9 +260,7 @@ void AmsMapingPopup::update_ams_data(std::map<std::string, Ams*> amsList)
|
||||
|
||||
void AmsMapingPopup::add_ams_mapping(std::vector<TrayData> tray_data)
|
||||
{
|
||||
wxBoxSizer *sizer_mapping_list = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
|
||||
auto sizer_mapping_list = new wxBoxSizer(wxHORIZONTAL);
|
||||
for (auto i = 0; i < tray_data.size(); i++) {
|
||||
wxBoxSizer *sizer_mapping_item = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
@@ -299,7 +303,7 @@ void AmsMapingPopup::add_ams_mapping(std::vector<TrayData> tray_data)
|
||||
if (!is_match_material(tray_data[i].id, tray_data[i].name)) return;
|
||||
wxCommandEvent event(EVT_SET_FINISH_MAPPING);
|
||||
event.SetInt(tray_data[i].id);
|
||||
wxString param = wxString::Format("%d|%d|%d|%02d", tray_data[i].colour.Red(), tray_data[i].colour.Green(), tray_data[i].colour.Blue(), tray_data[i].id + 1);
|
||||
wxString param = wxString::Format("%d|%d|%d|%02d|%d", tray_data[i].colour.Red(), tray_data[i].colour.Green(), tray_data[i].colour.Blue(), tray_data[i].id + 1, m_current_filament_id);
|
||||
event.SetString(param);
|
||||
event.SetEventObject(this->GetParent());
|
||||
wxPostEvent(this->GetParent(), event);
|
||||
@@ -317,7 +321,7 @@ void AmsMapingPopup::add_ams_mapping(std::vector<TrayData> tray_data)
|
||||
m_filament_name->Bind(wxEVT_BUTTON, [this, tray_data, i](wxCommandEvent &e) {
|
||||
wxCommandEvent event(EVT_SET_FINISH_MAPPING);
|
||||
event.SetInt(tray_data[i].id);
|
||||
wxString param = wxString::Format("%d|%d|%d|%02d", 0x6B, 0x6B, 0x6B, tray_data[i].id + 1);
|
||||
wxString param = wxString::Format("%d|%d|%d|%02d|%d", 0x6B, 0x6B, 0x6B, tray_data[i].id + 1, m_current_filament_id);
|
||||
event.SetString(param);
|
||||
event.SetEventObject(this->GetParent());
|
||||
wxPostEvent(this->GetParent(), event);
|
||||
@@ -334,7 +338,7 @@ void AmsMapingPopup::add_ams_mapping(std::vector<TrayData> tray_data)
|
||||
m_filament_name->Bind(wxEVT_BUTTON, [this, tray_data, i](wxCommandEvent &e) {
|
||||
wxCommandEvent event(EVT_SET_FINISH_MAPPING);
|
||||
event.SetInt(tray_data[i].id);
|
||||
wxString param = wxString::Format("%d|%d|%d|%02d", 0x6B, 0x6B, 0x6B, tray_data[i].id + 1);
|
||||
wxString param = wxString::Format("%d|%d|%d|%02d|%d", 0x6B, 0x6B, 0x6B, tray_data[i].id + 1, m_current_filament_id);
|
||||
event.SetString(param);
|
||||
event.SetEventObject(this->GetParent());
|
||||
wxPostEvent(this->GetParent(), event);
|
||||
@@ -342,17 +346,17 @@ void AmsMapingPopup::add_ams_mapping(std::vector<TrayData> tray_data)
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
sizer_mapping_item->Add(number, 0, wxALIGN_CENTER_HORIZONTAL, 0);
|
||||
sizer_mapping_item->Add(m_filament_name, 0, wxALIGN_CENTER_HORIZONTAL, 0);
|
||||
sizer_mapping_list->Add(sizer_mapping_item, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, FromDIP(5));
|
||||
m_amsmapping_sizer_list.push_back(sizer_mapping_list);
|
||||
}
|
||||
m_sizer_main->Add(sizer_mapping_list, 0, wxALIGN_CENTER_HORIZONTAL, 0);
|
||||
}
|
||||
|
||||
void AmsMapingPopup::OnDismiss()
|
||||
{
|
||||
delete this;
|
||||
|
||||
}
|
||||
|
||||
bool AmsMapingPopup::ProcessLeftDown(wxMouseEvent &event)
|
||||
|
||||
@@ -39,7 +39,8 @@
|
||||
|
||||
namespace Slic3r { namespace GUI {
|
||||
|
||||
#define MATERIAL_ITEM_SIZE wxSize(FromDIP(42), FromDIP(31))
|
||||
#define MATERIAL_ITEM_SIZE wxSize(FromDIP(64), FromDIP(34))
|
||||
#define MATERIAL_ITEM_REAL_SIZE wxSize(FromDIP(62), FromDIP(32))
|
||||
#define AMS_TOTAL_COUNT 4
|
||||
|
||||
enum TrayType {
|
||||
@@ -92,14 +93,18 @@ public:
|
||||
~AmsMapingPopup() {};
|
||||
|
||||
std::vector<std::string> m_materials_list;
|
||||
std::vector<wxBoxSizer*> m_amsmapping_sizer_list;
|
||||
|
||||
int m_current_filament_id;
|
||||
std::string m_tag_material;
|
||||
wxBoxSizer *m_sizer_main;
|
||||
wxBoxSizer *m_sizer_main{nullptr};
|
||||
|
||||
virtual void Popup(wxWindow *focus = NULL) wxOVERRIDE;
|
||||
void update_materials_list(std::vector<std::string> list);
|
||||
void set_tag_texture(std::string texture);
|
||||
void update_ams_data(std::map<std::string, Ams *> amsList);
|
||||
void add_ams_mapping(std::vector<TrayData> tray_data);
|
||||
void set_current_filament_id(int id){m_current_filament_id = id;};
|
||||
int get_current_filament_id(){return m_current_filament_id;};
|
||||
bool is_match_material(int id, std::string material);
|
||||
virtual void OnDismiss() wxOVERRIDE;
|
||||
virtual bool ProcessLeftDown(wxMouseEvent &event) wxOVERRIDE;
|
||||
|
||||
@@ -501,7 +501,7 @@ AuFolderPanel::AuFolderPanel(wxWindow *parent, AuxiliaryFolderType type, wxWindo
|
||||
m_button_add = new Button(m_scrolledWindow, _L("Add"), "auxiliary_add_file", 12, 12);
|
||||
m_button_add->SetBackgroundColor(btn_bg_white);
|
||||
m_button_add->SetBorderColor(btn_bd_white);
|
||||
m_button_add->SetMinSize(wxSize(FromDIP(80), FromDIP(24)));
|
||||
m_button_add->SetMinSize(wxSize(-1, FromDIP(24)));
|
||||
m_button_add->SetCornerRadius(12);
|
||||
m_button_add->SetFont(Label::Body_14);
|
||||
// m_button_add->Bind(wxEVT_LEFT_UP, &AuxiliaryPanel::on_add, this);
|
||||
@@ -563,7 +563,7 @@ void AuFolderPanel::update(std::vector<fs::path> paths)
|
||||
|
||||
void AuFolderPanel::msw_rescale()
|
||||
{
|
||||
m_button_add->SetMinSize(wxSize(FromDIP(80), FromDIP(24)));
|
||||
m_button_add->SetMinSize(wxSize(-1, FromDIP(24)));
|
||||
for (auto i = 0; i < m_aufiles_list.GetCount(); i++) {
|
||||
AuFiles *aufile = m_aufiles_list[i];
|
||||
aufile->file->msw_rescale();
|
||||
@@ -707,21 +707,14 @@ void AuxiliaryPanel::init_tabpanel()
|
||||
m_tabpanel->SetBackgroundColour(*wxWHITE);
|
||||
m_tabpanel->Bind(wxEVT_BOOKCTRL_PAGE_CHANGED, [this](wxBookCtrlEvent &e) { ; });
|
||||
|
||||
#if !BBL_RELEASE_TO_PUBLIC
|
||||
m_designer_panel = new DesignerPanel(m_tabpanel, AuxiliaryFolderType::DESIGNER);
|
||||
#endif
|
||||
|
||||
m_pictures_panel = new AuFolderPanel(m_tabpanel, AuxiliaryFolderType::MODEL_PICTURE);
|
||||
m_bill_of_materials_panel = new AuFolderPanel(m_tabpanel, AuxiliaryFolderType::BILL_OF_MATERIALS);
|
||||
m_assembly_panel = new AuFolderPanel(m_tabpanel, AuxiliaryFolderType::ASSEMBLY_GUIDE);
|
||||
m_others_panel = new AuFolderPanel(m_tabpanel, AuxiliaryFolderType::OTHERS);
|
||||
|
||||
#if !BBL_RELEASE_TO_PUBLIC
|
||||
m_tabpanel->AddPage(m_designer_panel, _L("Basic Info"), "", true);
|
||||
m_tabpanel->AddPage(m_pictures_panel, _L("Pictures"), "", false);
|
||||
#else
|
||||
m_tabpanel->AddPage(m_pictures_panel, _L("Pictures"), "", true);
|
||||
#endif
|
||||
m_tabpanel->AddPage(m_bill_of_materials_panel, _L("Bill of Materials"), "", false);
|
||||
m_tabpanel->AddPage(m_assembly_panel, _L("Assembly Guide"), "", false);
|
||||
m_tabpanel->AddPage(m_others_panel, _L("Others"), "", false);
|
||||
@@ -743,9 +736,7 @@ void AuxiliaryPanel::msw_rescale() {
|
||||
m_bill_of_materials_panel->msw_rescale();
|
||||
m_assembly_panel->msw_rescale();
|
||||
m_others_panel->msw_rescale();
|
||||
#if !BBL_RELEASE_TO_PUBLIC
|
||||
m_designer_panel->msw_rescale();
|
||||
#endif
|
||||
}
|
||||
|
||||
void AuxiliaryPanel::on_size(wxSizeEvent &event)
|
||||
@@ -897,9 +888,7 @@ void AuxiliaryPanel::Reload(wxString aux_path)
|
||||
fs::create_directory(folder_path.ToStdWstring());
|
||||
}
|
||||
update_all_panel();
|
||||
#if !BBL_RELEASE_TO_PUBLIC
|
||||
m_designer_panel->update_info();
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -947,9 +936,7 @@ void AuxiliaryPanel::Reload(wxString aux_path)
|
||||
|
||||
update_all_panel();
|
||||
update_all_cover();
|
||||
#if !BBL_RELEASE_TO_PUBLIC
|
||||
m_designer_panel->update_info();
|
||||
#endif
|
||||
}
|
||||
|
||||
void AuxiliaryPanel::update_all_panel()
|
||||
|
||||
@@ -77,28 +77,13 @@ void BBLStatusBarBind::set_progress(int val)
|
||||
if(val < 0)
|
||||
return;
|
||||
|
||||
bool need_layout = false;
|
||||
//add the logic for arrange/orient jobs, which don't call stop_busy
|
||||
if(val == m_prog->GetRange()) {
|
||||
m_prog->SetValue(0);
|
||||
set_percent_text("0%");
|
||||
//m_sizer->Hide(m_prog);
|
||||
need_layout = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!m_sizer->IsShown(m_prog)) {
|
||||
m_sizer->Show(m_prog);
|
||||
m_sizer->Show(m_cancelbutton);
|
||||
need_layout = true;
|
||||
}
|
||||
m_prog->SetValue(val);
|
||||
set_percent_text(wxString::Format("%d%%", val));
|
||||
}
|
||||
|
||||
if (need_layout) {
|
||||
m_sizer->Layout();
|
||||
if (!m_sizer->IsShown(m_prog)) {
|
||||
m_sizer->Show(m_prog);
|
||||
m_sizer->Show(m_cancelbutton);
|
||||
}
|
||||
m_prog->SetValue(val);
|
||||
set_percent_text(wxString::Format("%d%%", val));
|
||||
m_sizer->Layout();
|
||||
}
|
||||
|
||||
int BBLStatusBarBind::get_range() const
|
||||
|
||||
@@ -26,19 +26,19 @@ BBLStatusBarSend::BBLStatusBarSend(wxWindow *parent, int id)
|
||||
wxBoxSizer *m_sizer_body = new wxBoxSizer(wxVERTICAL);
|
||||
wxBoxSizer *m_sizer_bottom = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
m_status_text = new wxStaticText(m_self, wxID_ANY, L(""), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_status_text = new wxStaticText(m_self, wxID_ANY, L(""), wxDefaultPosition, wxSize(m_self->FromDIP(280), -1), 0);
|
||||
m_status_text->SetForegroundColour(wxColour(107, 107, 107));
|
||||
m_status_text->SetFont(::Label::Body_13);
|
||||
m_status_text->Wrap(-1);
|
||||
m_sizer_body->Add(m_status_text, 0, 0, 0);
|
||||
m_status_text->Wrap(m_self->FromDIP(280));
|
||||
|
||||
|
||||
m_prog = new wxGauge(m_self, wxID_ANY, 100, wxDefaultPosition, wxSize(-1, m_self->FromDIP(6)), wxGA_HORIZONTAL);
|
||||
m_prog->SetValue(0);
|
||||
|
||||
block_left = new wxWindow(m_prog, wxID_ANY, wxPoint(0, 0), wxSize(2, m_prog->GetSize().GetHeight() * 2));
|
||||
block_left->SetBackgroundColour(wxColour(255, 255, 255));
|
||||
block_right = new wxWindow(m_prog, wxID_ANY, wxPoint(m_prog->GetSize().GetWidth() - 2, 0), wxSize(2, m_prog->GetSize().GetHeight() * 2));
|
||||
block_right->SetBackgroundColour(wxColour(255, 255, 255));
|
||||
/* block_left = new wxWindow(m_prog, wxID_ANY, wxPoint(0, 0), wxSize(2, m_prog->GetSize().GetHeight() * 2));
|
||||
block_left->SetBackgroundColour(wxColour(255, 255, 255));
|
||||
block_right = new wxWindow(m_prog, wxID_ANY, wxPoint(m_prog->GetSize().GetWidth() - 2, 0), wxSize(2, m_prog->GetSize().GetHeight() * 2));
|
||||
block_right->SetBackgroundColour(wxColour(255, 255, 255));*/
|
||||
|
||||
m_sizer_bottom->Add(m_prog, 1, wxALIGN_CENTER, 0);
|
||||
|
||||
@@ -47,9 +47,10 @@ BBLStatusBarSend::BBLStatusBarSend(wxWindow *parent, int id)
|
||||
m_cancelbutton->SetTextColor(wxColour(107, 107, 107));
|
||||
m_cancelbutton->SetBackgroundColor(wxColour(255, 255, 255));
|
||||
m_cancelbutton->SetCornerRadius(12);
|
||||
m_cancelbutton->Bind(wxEVT_BUTTON, [this](const wxCommandEvent &) {
|
||||
m_cancelbutton->Bind(wxEVT_BUTTON,
|
||||
[this](wxCommandEvent &evt) {
|
||||
m_was_cancelled = true;
|
||||
if (m_cancel_cb_fina)
|
||||
if (m_cancel_cb_fina)
|
||||
m_cancel_cb_fina();
|
||||
});
|
||||
|
||||
@@ -60,7 +61,9 @@ BBLStatusBarSend::BBLStatusBarSend(wxWindow *parent, int id)
|
||||
m_sizer_bottom->Add(m_stext_percent, 0, wxALIGN_CENTER | wxLEFT | wxRIGHT, 10);
|
||||
|
||||
m_sizer_bottom->Add(m_cancelbutton, 0, wxALIGN_CENTER, 0);
|
||||
m_sizer_body->Add(0, 0, 0, wxTOP, 5);
|
||||
|
||||
m_sizer_body->Add(m_status_text, 0, 0, 0);
|
||||
m_sizer_body->Add(0, 0, 0, wxTOP, 1);
|
||||
m_sizer_body->Add(m_sizer_bottom, 1, wxEXPAND, 0);
|
||||
|
||||
m_sizer->Add(m_sizer_body, 1, wxALIGN_CENTER, 0);
|
||||
@@ -73,8 +76,8 @@ BBLStatusBarSend::BBLStatusBarSend(wxWindow *parent, int id)
|
||||
|
||||
void BBLStatusBarSend::set_prog_block()
|
||||
{
|
||||
block_left->SetPosition(wxPoint(0, 0));
|
||||
block_right->SetPosition(wxPoint(m_prog->GetSize().GetWidth() - 2, 0));
|
||||
//block_left->SetPosition(wxPoint(0, 0));
|
||||
//block_right->SetPosition(wxPoint(m_prog->GetSize().GetWidth() - 2, 0));
|
||||
}
|
||||
|
||||
int BBLStatusBarSend::get_progress() const
|
||||
@@ -84,33 +87,19 @@ int BBLStatusBarSend::get_progress() const
|
||||
|
||||
void BBLStatusBarSend::set_progress(int val)
|
||||
{
|
||||
set_prog_block();
|
||||
//set_prog_block();
|
||||
|
||||
if(val < 0)
|
||||
return;
|
||||
|
||||
bool need_layout = false;
|
||||
//add the logic for arrange/orient jobs, which don't call stop_busy
|
||||
if(val == m_prog->GetRange()) {
|
||||
m_prog->SetValue(0);
|
||||
set_percent_text("0%");
|
||||
m_sizer->Hide(m_prog);
|
||||
need_layout = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!m_sizer->IsShown(m_prog)) {
|
||||
m_sizer->Show(m_prog);
|
||||
m_sizer->Show(m_cancelbutton);
|
||||
need_layout = true;
|
||||
}
|
||||
m_prog->SetValue(val);
|
||||
set_percent_text(wxString::Format("%d%%", val));
|
||||
}
|
||||
|
||||
if (need_layout) {
|
||||
m_sizer->Layout();
|
||||
if (!m_sizer->IsShown(m_prog)) {
|
||||
m_sizer->Show(m_prog);
|
||||
m_sizer->Show(m_cancelbutton);
|
||||
}
|
||||
m_prog->SetValue(val);
|
||||
set_percent_text(wxString::Format("%d%%", val));
|
||||
m_sizer->Layout();
|
||||
}
|
||||
|
||||
int BBLStatusBarSend::get_range() const
|
||||
@@ -185,6 +174,9 @@ void BBLStatusBarSend::set_status_text(const wxString& txt)
|
||||
//auto txtss = "The printing project is being uploaded... 25%%";
|
||||
//m_status_text->SetLabelText(txtss);
|
||||
m_status_text->SetLabelText(txt);
|
||||
m_status_text->SetSize(wxSize(m_self->FromDIP(280), -1));
|
||||
m_status_text->SetMaxSize(wxSize(m_self->FromDIP(280), -1));
|
||||
m_status_text->Wrap(m_self->FromDIP(280));
|
||||
}
|
||||
|
||||
void BBLStatusBarSend::set_percent_text(const wxString &txt)
|
||||
@@ -203,7 +195,7 @@ void BBLStatusBarSend::set_status_text(const char *txt)
|
||||
}
|
||||
|
||||
void BBLStatusBarSend::msw_rescale() {
|
||||
set_prog_block();
|
||||
//set_prog_block();
|
||||
m_cancelbutton->SetMinSize(wxSize(m_self->FromDIP(56), m_self->FromDIP(24)));
|
||||
}
|
||||
|
||||
@@ -230,6 +222,7 @@ void BBLStatusBarSend::reset()
|
||||
set_status_text("");
|
||||
m_was_cancelled = false;
|
||||
set_progress(0);
|
||||
set_percent_text(wxString::Format("%d%%", 0));
|
||||
}
|
||||
|
||||
|
||||
@@ -250,4 +243,9 @@ void BBLStatusBarSend::hide_cancel_button()
|
||||
m_sizer->Layout();
|
||||
}
|
||||
|
||||
void BBLStatusBarSend::change_button_label(wxString name)
|
||||
{
|
||||
m_cancelbutton->SetLabel(name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -73,6 +73,7 @@ public:
|
||||
// Temporary methods to satisfy Perl side
|
||||
void show_cancel_button();
|
||||
void hide_cancel_button();
|
||||
void change_button_label(wxString name);
|
||||
|
||||
private:
|
||||
bool m_busy = false;
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "PartPlate.hpp"
|
||||
|
||||
#define TOPBAR_ICON_SIZE 18
|
||||
#define TOPBAR_TITLE_WIDTH 300
|
||||
|
||||
using namespace Slic3r;
|
||||
|
||||
@@ -243,7 +244,7 @@ void BBLTopbar::Init(wxFrame* parent)
|
||||
this->AddSpacer(FromDIP(10));
|
||||
this->AddStretchSpacer(1);
|
||||
|
||||
m_title_item = this->AddLabel(ID_TITLE, "", FromDIP(300));
|
||||
m_title_item = this->AddLabel(ID_TITLE, "", FromDIP(TOPBAR_TITLE_WIDTH));
|
||||
m_title_item->SetAlignment(wxCENTER);
|
||||
|
||||
this->AddSpacer(FromDIP(10));
|
||||
@@ -402,6 +403,9 @@ wxMenu* BBLTopbar::GetTopMenu()
|
||||
|
||||
void BBLTopbar::SetTitle(wxString title)
|
||||
{
|
||||
wxGCDC dc(this);
|
||||
title = wxControl::Ellipsize(title, dc, wxELLIPSIZE_END, FromDIP(TOPBAR_TITLE_WIDTH));
|
||||
|
||||
m_title_item->SetLabel(title);
|
||||
m_title_item->SetAlignment(wxALIGN_CENTRE_HORIZONTAL);
|
||||
this->Refresh();
|
||||
|
||||
@@ -436,17 +436,23 @@ void UnBindMachineDilaog::on_unbind_printer(wxCommandEvent &event)
|
||||
if (result == 0) {
|
||||
DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
|
||||
if (!dev) return;
|
||||
dev->update_user_machine_list_info();
|
||||
// clean local machine access code info
|
||||
MachineObject* obj = dev->get_local_machine(m_machine_info->dev_id);
|
||||
if (obj) {
|
||||
obj->set_access_code("");
|
||||
}
|
||||
dev->erase_user_machine(m_machine_info->dev_id);
|
||||
|
||||
m_status_text->SetLabelText(_L("Log out successful."));
|
||||
m_button_cancel->SetLabel(_L("Close"));
|
||||
m_button_unbind->Hide();
|
||||
EndModal(wxID_OK);
|
||||
}
|
||||
else {
|
||||
m_status_text->SetLabelText(_L("Failed to log out."));
|
||||
EndModal(wxID_CANCEL);
|
||||
return;
|
||||
}
|
||||
EndModal(wxID_OK);
|
||||
}
|
||||
|
||||
void UnBindMachineDilaog::on_dpi_changed(const wxRect &suggested_rect)
|
||||
|
||||
@@ -97,13 +97,23 @@ CalibrationDialog::CalibrationDialog(Plater *plater)
|
||||
|
||||
auto staticline = new ::StaticLine(cali_right_panel);
|
||||
staticline->SetLineColour(wxColour(0x00, 0xAE, 0x42));
|
||||
|
||||
m_calibration_flow = new StepIndicator(cali_right_panel, wxID_ANY);
|
||||
auto calibration_panel = new wxPanel(cali_right_panel);
|
||||
calibration_panel->SetBackgroundColour(wxColour(0xF8, 0xF8, 0xF8));
|
||||
auto calibration_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
calibration_panel->SetMinSize(wxSize(FromDIP(170), FromDIP(160)));
|
||||
calibration_panel->SetSize(wxSize(FromDIP(170), FromDIP(160)));
|
||||
|
||||
m_calibration_flow = new StepIndicator(calibration_panel, wxID_ANY);
|
||||
StateColor bg_color(std::pair<wxColour, int>(wxColour(248, 248, 248), StateColor::Normal));
|
||||
m_calibration_flow->SetBackgroundColor(bg_color);
|
||||
m_calibration_flow->SetFont(Label::Body_12);
|
||||
|
||||
m_calibration_flow->SetMinSize(wxSize(FromDIP(170), FromDIP(160)));
|
||||
m_calibration_flow->SetSize(wxSize(FromDIP(170), FromDIP(160)));
|
||||
|
||||
calibration_panel->SetSizer(calibration_sizer);
|
||||
calibration_panel->Layout();
|
||||
calibration_sizer->Add(m_calibration_flow, 0, wxALIGN_CENTER_HORIZONTAL | wxEXPAND, 0);
|
||||
|
||||
StateColor btn_bg_green(std::pair<wxColour, int>(AMS_CONTROL_DISABLE_COLOUR, StateColor::Disabled), 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));
|
||||
@@ -119,10 +129,10 @@ CalibrationDialog::CalibrationDialog(Plater *plater)
|
||||
cali_right_sizer_v->Add(cali_text_right_top, 0, wxALIGN_CENTER, 0);
|
||||
cali_right_sizer_v->Add(0, 0, 0, wxTOP, FromDIP(7));
|
||||
cali_right_sizer_v->Add(staticline, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(10));
|
||||
cali_right_sizer_v->Add(0, 0, 0, wxTOP, FromDIP(9));
|
||||
cali_right_sizer_v->Add(m_calibration_flow, 0, wxALIGN_CENTER | wxLEFT | wxRIGHT, FromDIP(6));
|
||||
cali_right_sizer_v->Add(0, 0, 0, wxTOP, FromDIP(10));
|
||||
cali_right_sizer_v->Add(m_calibration_btn, 0, wxALIGN_CENTER, 0);
|
||||
cali_right_sizer_v->Add(0, 0, 0, wxTOP, FromDIP(3));
|
||||
cali_right_sizer_v->Add(calibration_panel, 0, wxALIGN_CENTER_HORIZONTAL | wxLEFT | wxRIGHT, FromDIP(6));
|
||||
cali_right_sizer_v->Add(0, 0, 1, wxEXPAND, 5);
|
||||
cali_right_sizer_v->Add(m_calibration_btn, 0, wxALIGN_CENTER_HORIZONTAL, 0);
|
||||
|
||||
cali_right_sizer_h->Add(cali_right_sizer_v, 0, wxALIGN_CENTER, 0);
|
||||
cali_right_panel->SetSizer(cali_right_sizer_h);
|
||||
@@ -137,7 +147,6 @@ CalibrationDialog::CalibrationDialog(Plater *plater)
|
||||
SetSizer(m_sizer_main);
|
||||
Layout();
|
||||
Fit();
|
||||
Centre(wxBOTH);
|
||||
|
||||
Bind(wxEVT_CLOSE_WINDOW, [this](wxCloseEvent &evt) { Hide(); });
|
||||
|
||||
@@ -151,29 +160,41 @@ void CalibrationDialog::on_dpi_changed(const wxRect &suggested_rect) {}
|
||||
void CalibrationDialog::update_cali(MachineObject *obj)
|
||||
{
|
||||
if (!obj) return;
|
||||
|
||||
// in printing
|
||||
if (obj->is_in_printing()) {
|
||||
m_calibration_flow->DeleteAllItems();
|
||||
m_calibration_btn->Disable();
|
||||
return;
|
||||
} else {
|
||||
m_calibration_btn->Enable();
|
||||
if (!obj->is_in_calibration()) {
|
||||
m_calibration_flow->DeleteAllItems();
|
||||
m_calibration_btn->SetLabel(_L("Start Calibration"));
|
||||
if (obj->is_in_calibration() || obj->is_calibration_done()) {
|
||||
if (obj->is_calibration_done()) {
|
||||
m_calibration_btn->Enable();
|
||||
m_calibration_btn->SetLabel(_L("Completed"));
|
||||
} else {
|
||||
// RUNNING && IDLE
|
||||
m_calibration_btn->Disable();
|
||||
m_calibration_btn->SetLabel(_L("Calibrating"));
|
||||
|
||||
if (is_stage_list_info_changed(obj)) {
|
||||
// change items if stage_list_info changed
|
||||
m_calibration_flow->DeleteAllItems();
|
||||
for (int i = 0; i < obj->stage_list_info.size(); i++) { m_calibration_flow->AppendItem(get_stage_string(obj->stage_list_info[i])); }
|
||||
}
|
||||
int index = obj->get_curr_stage_idx();
|
||||
m_calibration_flow->SelectItem(index);
|
||||
}
|
||||
auto size = wxSize(-1, obj->stage_list_info.size() * FromDIP(44));
|
||||
if (m_calibration_flow->GetSize().y != size.y) {
|
||||
m_calibration_flow->SetSize(size);
|
||||
m_calibration_flow->SetMinSize(size);
|
||||
m_calibration_flow->SetMaxSize(size);
|
||||
Layout();
|
||||
}
|
||||
if (is_stage_list_info_changed(obj)) {
|
||||
// change items if stage_list_info changed
|
||||
m_calibration_flow->DeleteAllItems();
|
||||
for (int i = 0; i < obj->stage_list_info.size(); i++) {
|
||||
m_calibration_flow->AppendItem(get_stage_string(obj->stage_list_info[i]));
|
||||
}
|
||||
}
|
||||
int index = obj->get_curr_stage_idx();
|
||||
m_calibration_flow->SelectItem(index);
|
||||
} else {
|
||||
// IDLE
|
||||
if (obj->is_in_printing()) {
|
||||
m_calibration_btn->Disable();
|
||||
}
|
||||
else {
|
||||
m_calibration_btn->Enable();
|
||||
}
|
||||
m_calibration_flow->DeleteAllItems();
|
||||
m_calibration_btn->SetLabel(_L("Start Calibration"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,11 +214,23 @@ bool CalibrationDialog::is_stage_list_info_changed(MachineObject *obj)
|
||||
void CalibrationDialog::on_start_calibration(wxMouseEvent &event)
|
||||
{
|
||||
if (m_obj) {
|
||||
BOOST_LOG_TRIVIAL(trace) << "on_start_calibration";
|
||||
m_obj->command_start_calibration();
|
||||
if (m_obj->is_calibration_done()) {
|
||||
m_obj->calibration_done = false;
|
||||
EndModal(wxID_CANCEL);
|
||||
Close();
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(info) << "on_start_calibration";
|
||||
m_obj->command_start_calibration();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CalibrationDialog::update_machine_obj(MachineObject *obj) { m_obj = obj; }
|
||||
|
||||
bool CalibrationDialog::Show(bool show)
|
||||
{
|
||||
if (show) { CentreOnParent(); }
|
||||
return DPIDialog::Show(show);
|
||||
}
|
||||
|
||||
}} // namespace Slic3r::GUI
|
||||
|
||||
@@ -50,6 +50,7 @@ public:
|
||||
bool is_stage_list_info_changed(MachineObject *obj);
|
||||
void on_start_calibration(wxMouseEvent &event);
|
||||
void update_machine_obj(MachineObject *obj);
|
||||
bool Show(bool show) override;
|
||||
};
|
||||
|
||||
}} // namespace Slic3r::GUI
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
#include "I18N.hpp"
|
||||
#include "Widgets/Label.hpp"
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include "BitmapCache.hpp"
|
||||
#include <wx/progdlg.h>
|
||||
#include <wx/clipbrd.h>
|
||||
#include <wx/dcgraph.h>
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
@@ -128,5 +132,94 @@ void CameraPopup::OnMouse(wxMouseEvent &event)
|
||||
}
|
||||
|
||||
|
||||
CameraItem::CameraItem(wxWindow *parent,std::string off_normal, std::string on_normal, std::string off_hover, std::string on_hover)
|
||||
: wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize)
|
||||
{
|
||||
#ifdef __WINDOWS__
|
||||
SetDoubleBuffered(true);
|
||||
#endif //__WINDOWS__
|
||||
|
||||
m_bitmap_on_normal = create_scaled_bitmap(on_normal, nullptr, 20);
|
||||
m_bitmap_off_normal = create_scaled_bitmap(off_normal, nullptr, 20);
|
||||
m_bitmap_on_hover = create_scaled_bitmap(on_hover, nullptr, 20);
|
||||
m_bitmap_off_hover = create_scaled_bitmap(off_hover, nullptr, 20);
|
||||
|
||||
SetSize(wxSize(FromDIP(20), FromDIP(20)));
|
||||
SetMinSize(wxSize(FromDIP(20), FromDIP(20)));
|
||||
SetMaxSize(wxSize(FromDIP(20), FromDIP(20)));
|
||||
Bind(wxEVT_PAINT, &CameraItem::paintEvent, this);
|
||||
Bind(wxEVT_ENTER_WINDOW, &CameraItem::on_enter_win, this);
|
||||
Bind(wxEVT_LEAVE_WINDOW, &CameraItem::on_level_win, this);
|
||||
}
|
||||
|
||||
CameraItem::~CameraItem() {}
|
||||
|
||||
void CameraItem::msw_rescale() {}
|
||||
|
||||
void CameraItem::set_switch(bool is_on)
|
||||
{
|
||||
m_on = is_on;
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void CameraItem::on_enter_win(wxMouseEvent &evt)
|
||||
{
|
||||
m_hover = true;
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void CameraItem::on_level_win(wxMouseEvent &evt)
|
||||
{
|
||||
m_hover = false;
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void CameraItem::paintEvent(wxPaintEvent &evt)
|
||||
{
|
||||
wxPaintDC dc(this);
|
||||
render(dc);
|
||||
|
||||
// PrepareDC(buffdc);
|
||||
// PrepareDC(dc);
|
||||
}
|
||||
|
||||
void CameraItem::render(wxDC &dc)
|
||||
{
|
||||
#ifdef __WXMSW__
|
||||
wxSize size = GetSize();
|
||||
wxMemoryDC memdc;
|
||||
wxBitmap bmp(size.x, size.y);
|
||||
memdc.SelectObject(bmp);
|
||||
memdc.Blit({0, 0}, size, &dc, {0, 0});
|
||||
|
||||
{
|
||||
wxGCDC dc2(memdc);
|
||||
doRender(dc2);
|
||||
}
|
||||
|
||||
memdc.SelectObject(wxNullBitmap);
|
||||
dc.DrawBitmap(bmp, 0, 0);
|
||||
#else
|
||||
doRender(dc);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CameraItem::doRender(wxDC &dc)
|
||||
{
|
||||
if (m_on) {
|
||||
if (m_hover) {
|
||||
dc.DrawBitmap(m_bitmap_on_hover, wxPoint((GetSize().x - m_bitmap_on_hover.GetSize().x) / 2, (GetSize().y - m_bitmap_on_hover.GetSize().y) / 2));
|
||||
} else {
|
||||
dc.DrawBitmap(m_bitmap_on_normal, wxPoint((GetSize().x - m_bitmap_on_normal.GetSize().x) / 2, (GetSize().y - m_bitmap_on_normal.GetSize().y) / 2));
|
||||
}
|
||||
|
||||
} else {
|
||||
if (m_hover) {
|
||||
dc.DrawBitmap(m_bitmap_off_hover, wxPoint((GetSize().x - m_bitmap_off_hover.GetSize().x) / 2, (GetSize().y - m_bitmap_off_hover.GetSize().y) / 2));
|
||||
} else {
|
||||
dc.DrawBitmap(m_bitmap_off_normal, wxPoint((GetSize().x - m_bitmap_off_normal.GetSize().x) / 2, (GetSize().y - m_bitmap_off_normal.GetSize().y) / 2));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,11 @@
|
||||
#include "DeviceManager.hpp"
|
||||
#include "GUI.hpp"
|
||||
#include <wx/panel.h>
|
||||
#include <wx/bitmap.h>
|
||||
#include <wx/image.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/gbsizer.h>
|
||||
#include <wx/webrequest.h>
|
||||
#include "Widgets/SwitchButton.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
@@ -44,6 +49,31 @@ private:
|
||||
wxDECLARE_EVENT_TABLE();
|
||||
};
|
||||
|
||||
|
||||
class CameraItem : public wxPanel
|
||||
{
|
||||
public:
|
||||
CameraItem(wxWindow *parent, std::string off_normal, std::string on_normal, std::string off_hover, std::string on_hover);
|
||||
~CameraItem();
|
||||
|
||||
MachineObject *m_obj{nullptr};
|
||||
bool m_on{false};
|
||||
bool m_hover{false};
|
||||
wxBitmap m_bitmap_on_normal;
|
||||
wxBitmap m_bitmap_on_hover;
|
||||
wxBitmap m_bitmap_off_normal;
|
||||
wxBitmap m_bitmap_off_hover;
|
||||
|
||||
void msw_rescale();
|
||||
void set_switch(bool is_on);
|
||||
bool get_switch_status() { return m_on; };
|
||||
void on_enter_win(wxMouseEvent &evt);
|
||||
void on_level_win(wxMouseEvent &evt);
|
||||
void paintEvent(wxPaintEvent &evt);
|
||||
void render(wxDC &dc);
|
||||
void doRender(wxDC &dc);
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -519,7 +519,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
|
||||
for (auto el : { "support_style", "support_base_pattern",
|
||||
"support_base_pattern_spacing", "support_angle",
|
||||
"support_interface_pattern", "support_interface_top_layers", "support_interface_bottom_layers",
|
||||
"bridge_no_support","max_bridge_length" "support_top_z_distance",
|
||||
"bridge_no_support", "thick_bridges", "max_bridge_length", "support_top_z_distance",
|
||||
//BBS: add more support params to dependent of enable_support
|
||||
"support_type","support_on_build_plate_only",
|
||||
"support_object_xy_distance", "independent_support_layer_height"})
|
||||
@@ -537,6 +537,10 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
|
||||
toggle_line("tree_support_branch_angle", support_is_tree);
|
||||
toggle_line("tree_support_wall_count", support_is_tree);
|
||||
toggle_line("tree_support_with_infill", support_is_tree);
|
||||
toggle_line("max_bridge_length", support_is_tree);
|
||||
|
||||
// tree support use max_bridge_length instead of bridge_no_support
|
||||
toggle_line("bridge_no_support", !support_is_tree);
|
||||
|
||||
for (auto el : { "support_interface_spacing", "support_interface_filament",
|
||||
"support_interface_loop_pattern", "support_bottom_interface_spacing" })
|
||||
|
||||
@@ -96,7 +96,7 @@ ConnectPrinterDialog::ConnectPrinterDialog(wxWindow *parent, wxWindowID id, cons
|
||||
this->SetSizer(main_sizer);
|
||||
this->Layout();
|
||||
this->Fit();
|
||||
this->Centre(wxBOTH);
|
||||
CentreOnParent();
|
||||
|
||||
m_textCtrl_code->Bind(wxEVT_TEXT, &ConnectPrinterDialog::on_input_enter, this);
|
||||
m_button_confirm->Bind(wxEVT_BUTTON, &ConnectPrinterDialog::on_button_confirm, this);
|
||||
|
||||
@@ -8,8 +8,9 @@
|
||||
#include "libslic3r/PlaceholderParser.hpp"
|
||||
#include "libslic3r/Print.hpp"
|
||||
#include "libslic3r/PrintConfig.hpp"
|
||||
#include "MsgDialog.hpp"
|
||||
#include "Plater.hpp"
|
||||
|
||||
#include "GUI_App.hpp"
|
||||
#include "nlohmann/json.hpp"
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
@@ -24,7 +25,6 @@ using namespace nlohmann;
|
||||
|
||||
namespace pt = boost::property_tree;
|
||||
|
||||
|
||||
const int PRINTING_STAGE_COUNT = 20;
|
||||
std::string PRINTING_STAGE_STR[PRINTING_STAGE_COUNT] = {
|
||||
"printing",
|
||||
@@ -455,6 +455,16 @@ void MachineObject::_parse_ams_status(int ams_status)
|
||||
BOOST_LOG_TRIVIAL(trace) << "ams_debug: main = " << ams_status_main_int << ", sub = " << ams_status_sub;
|
||||
}
|
||||
|
||||
bool MachineObject::is_U0_firmware()
|
||||
{
|
||||
auto ota_ver_it = module_vers.find("ota");
|
||||
if (ota_ver_it != module_vers.end()) {
|
||||
if (ota_ver_it->second.sw_ver.compare("00.01.04.00") < 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MachineObject::is_support_ams_mapping()
|
||||
{
|
||||
AppConfig* config = Slic3r::GUI::wxGetApp().app_config;
|
||||
@@ -590,7 +600,6 @@ int MachineObject::ams_filament_mapping(std::vector<FilamentInfo> filaments, std
|
||||
|
||||
// tray_index : tray_color
|
||||
std::map<int, FilamentInfo> tray_filaments;
|
||||
|
||||
for (auto ams = amsList.begin(); ams != amsList.end(); ams++) {
|
||||
for (auto tray = ams->second->trayList.begin(); tray != ams->second->trayList.end(); tray++) {
|
||||
int ams_id = atoi(ams->first.c_str());
|
||||
@@ -634,45 +643,48 @@ int MachineObject::ams_filament_mapping(std::vector<FilamentInfo> filaments, std
|
||||
|
||||
// is_support_ams_mapping
|
||||
if (!is_support_ams_mapping()) {
|
||||
BOOST_LOG_TRIVIAL(info) << "ams_mapping: do not support, use order mapping";
|
||||
for (int i = 0; i < filaments.size(); i++) {
|
||||
FilamentInfo info;
|
||||
if (i < tray_info_list.size()) {
|
||||
info.id = filaments[i].id;
|
||||
info.tray_id = filaments[i].id;
|
||||
info.color = tray_info_list[i].color;
|
||||
info.type = tray_info_list[i].type;
|
||||
} else {
|
||||
info.id = filaments[i].id;
|
||||
info.tray_id = -1;
|
||||
}
|
||||
info.id = filaments[i].id;
|
||||
info.tray_id = -1;
|
||||
result.push_back(info);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// calc distance map
|
||||
struct DisValue {
|
||||
int tray_id;
|
||||
float distance;
|
||||
bool is_same_color = true;
|
||||
bool is_type_match = true;
|
||||
};
|
||||
char buffer[256];
|
||||
std::vector<std::vector<DisValue>> distance_map;
|
||||
|
||||
// print title
|
||||
::sprintf(buffer, "F(id)");
|
||||
std::string line = std::string(buffer);
|
||||
for (auto tray = tray_filaments.begin(); tray != tray_filaments.end(); tray++) {
|
||||
::sprintf(buffer, " AMS%02d", tray->second.id+1);
|
||||
line += std::string(buffer);
|
||||
}
|
||||
BOOST_LOG_TRIVIAL(info) << "ams_mapping_distance:" << line;
|
||||
|
||||
for (int i = 0; i < filaments.size(); i++) {
|
||||
std::vector<DisValue> rol;
|
||||
::sprintf(buffer, "F(%02d)", filaments[i].id+1);
|
||||
line = std::string(buffer);
|
||||
for (auto tray = tray_filaments.begin(); tray != tray_filaments.end(); tray++) {
|
||||
DisValue val;
|
||||
val.tray_id = tray->first;
|
||||
val.tray_id = tray->second.id;
|
||||
wxColour c = wxColour(filaments[i].color);
|
||||
val.distance = calc_color_distance(c, AmsTray::decode_color(tray->second.color));
|
||||
//val.is_same_color = val.distance < MAPPING_COLOR_THRESHOLD;
|
||||
if (filaments[i].type != tray->second.type) {
|
||||
val.distance = 999999;
|
||||
val.is_type_match = false;
|
||||
} else {
|
||||
val.is_type_match = true;
|
||||
}
|
||||
::sprintf(buffer, " %6.0f", val.distance);
|
||||
line += std::string(buffer);
|
||||
rol.push_back(val);
|
||||
}
|
||||
BOOST_LOG_TRIVIAL(info) << "ams_mapping_distance:" << line;
|
||||
distance_map.push_back(rol);
|
||||
}
|
||||
|
||||
@@ -683,6 +695,7 @@ int MachineObject::ams_filament_mapping(std::vector<FilamentInfo> filaments, std
|
||||
info.tray_id = -1;
|
||||
result.push_back(info);
|
||||
}
|
||||
|
||||
std::set<int> picked_src;
|
||||
std::set<int> picked_tar;
|
||||
for (int k = 0; k < distance_map.size(); k++) {
|
||||
@@ -693,8 +706,9 @@ int MachineObject::ams_filament_mapping(std::vector<FilamentInfo> filaments, std
|
||||
if (picked_src.find(i) != picked_src.end())
|
||||
continue;
|
||||
for (int j = 0; j < distance_map[i].size(); j++) {
|
||||
if (picked_tar.find(j) == picked_tar.end()
|
||||
&& distance_map[i][j].is_same_color
|
||||
if (picked_tar.find(j) != picked_tar.end())
|
||||
continue;
|
||||
if (distance_map[i][j].is_same_color
|
||||
&& distance_map[i][j].is_type_match) {
|
||||
if (min_val > distance_map[i][j].distance) {
|
||||
min_val = distance_map[i][j].distance;
|
||||
@@ -707,25 +721,31 @@ int MachineObject::ams_filament_mapping(std::vector<FilamentInfo> filaments, std
|
||||
if (picked_src_idx >= 0 && picked_tar_idx >= 0) {
|
||||
auto tray = tray_filaments.find(distance_map[k][picked_tar_idx].tray_id);
|
||||
if (tray != tray_filaments.end()) {
|
||||
result[picked_src_idx].tray_id = tray->first;
|
||||
result[picked_src_idx].color = tray->second.color;
|
||||
result[picked_src_idx].type = tray->second.type;
|
||||
BOOST_LOG_TRIVIAL(trace) << "tray_id = " << tray->first << ", distance = " << distance_map[k][picked_tar_idx].distance;
|
||||
result[picked_src_idx].tray_id = tray->first;
|
||||
result[picked_src_idx].color = tray->second.color;
|
||||
result[picked_src_idx].type = tray->second.type;
|
||||
result[picked_src_idx].distance = tray->second.distance;
|
||||
}
|
||||
else {
|
||||
FilamentInfo info;
|
||||
info.tray_id = -1;
|
||||
}
|
||||
picked_tar.insert(picked_tar_idx);
|
||||
::sprintf(buffer, "ams_mapping, picked F(%02d) AMS(%02d), distance=%6.0f", picked_src_idx+1, picked_tar_idx+1,
|
||||
distance_map[picked_src_idx][picked_tar_idx].distance);
|
||||
BOOST_LOG_TRIVIAL(info) << std::string(buffer);
|
||||
picked_src.insert(picked_src_idx);
|
||||
picked_tar.insert(picked_tar_idx);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<FilamentInfo> cache_map_result = result;
|
||||
|
||||
//check ams mapping result
|
||||
if (is_valid_mapping_result(result)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
reset_mapping_result(result);
|
||||
try {
|
||||
// try to use ordering ams mapping
|
||||
bool order_mapping_result = true;
|
||||
@@ -749,15 +769,23 @@ int MachineObject::ams_filament_mapping(std::vector<FilamentInfo> filaments, std
|
||||
}
|
||||
|
||||
//check order mapping result
|
||||
if (!is_valid_mapping_result(result)) {
|
||||
reset_mapping_result(result);
|
||||
return -1;
|
||||
if (is_valid_mapping_result(result)) {
|
||||
return 0;
|
||||
}
|
||||
} catch(...) {
|
||||
reset_mapping_result(result);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// try to match some color
|
||||
reset_mapping_result(result);
|
||||
result = cache_map_result;
|
||||
for (auto it = result.begin(); it != result.end(); it++) {
|
||||
if (it->distance >= 6000) {
|
||||
it->tray_id = -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -778,6 +806,7 @@ void MachineObject::reset_mapping_result(std::vector<FilamentInfo>& result)
|
||||
{
|
||||
for (int i = 0; i < result.size(); i++) {
|
||||
result[i].tray_id = -1;
|
||||
result[i].distance = 99999;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -904,7 +933,7 @@ std::map<int, MachineObject::ModuleVersionInfo> MachineObject::get_ams_version()
|
||||
|
||||
bool MachineObject::is_system_printing()
|
||||
{
|
||||
if (is_in_calibration())
|
||||
if (is_in_calibration() && is_in_printing_status(print_status))
|
||||
return true;
|
||||
//FIXME
|
||||
//if (print_type == "system" && is_in_printing_status(print_status))
|
||||
@@ -936,10 +965,40 @@ bool MachineObject::is_in_calibration()
|
||||
if (boost::contains(m_gcode_file, "auto_cali_for_user.gcode")
|
||||
&& stage_curr != 0) {
|
||||
return true;
|
||||
} else {
|
||||
// reset
|
||||
if (stage_curr != 0) {
|
||||
calibration_done = false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MachineObject::is_calibration_done()
|
||||
{
|
||||
return calibration_done;
|
||||
}
|
||||
|
||||
bool MachineObject::is_calibration_running()
|
||||
{
|
||||
if (is_in_calibration() && is_in_printing_status(print_status))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void MachineObject::parse_state_changed_event()
|
||||
{
|
||||
// parse calibration done
|
||||
if (last_mc_print_stage != mc_print_stage) {
|
||||
if (mc_print_stage == 1 && boost::contains(m_gcode_file, "auto_cali_for_user.gcode")) {
|
||||
calibration_done = true;
|
||||
} else {
|
||||
calibration_done = false;
|
||||
}
|
||||
}
|
||||
last_mc_print_stage = mc_print_stage;
|
||||
}
|
||||
|
||||
PrintingSpeedLevel MachineObject::_parse_printing_speed_lvl(int lvl)
|
||||
{
|
||||
if (lvl < (int)SPEED_LEVEL_COUNT)
|
||||
@@ -950,7 +1009,10 @@ PrintingSpeedLevel MachineObject::_parse_printing_speed_lvl(int lvl)
|
||||
|
||||
bool MachineObject::is_sdcard_printing()
|
||||
{
|
||||
if (can_abort() && obj_subtask_id.compare("0") == 0 && profile_id_ == "0" && project_id_ == "0")
|
||||
if (can_abort()
|
||||
&& (obj_subtask_id.compare("0") == 0 || obj_subtask_id.empty())
|
||||
&& (profile_id_ == "0" || profile_id_.empty())
|
||||
&& (project_id_ == "0" || project_id_.empty()))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
@@ -961,6 +1023,16 @@ bool MachineObject::has_sdcard()
|
||||
return camera_has_sdcard;
|
||||
}
|
||||
|
||||
bool MachineObject::has_timelapse()
|
||||
{
|
||||
return camera_timelapse;
|
||||
}
|
||||
|
||||
bool MachineObject::has_recording()
|
||||
{
|
||||
return camera_recording;
|
||||
}
|
||||
|
||||
int MachineObject::command_get_version()
|
||||
{
|
||||
json j;
|
||||
@@ -974,10 +1046,10 @@ int MachineObject::command_request_push_all()
|
||||
auto curr_time = std::chrono::system_clock::now();
|
||||
auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(curr_time - last_request_push);
|
||||
if (diff.count() < REQUEST_PUSH_MIN_TIME) {
|
||||
BOOST_LOG_TRIVIAL(trace) << "command_request_push_all: send request too fast";
|
||||
BOOST_LOG_TRIVIAL(trace) << "static: command_request_push_all: send request too fast, dev_id=" << dev_id;
|
||||
return -1;
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(trace) << "command_request_push_all";
|
||||
BOOST_LOG_TRIVIAL(trace) << "static: command_request_push_all, dev_id=" << dev_id;
|
||||
last_request_push = std::chrono::system_clock::now();
|
||||
}
|
||||
json j;
|
||||
@@ -1365,6 +1437,11 @@ bool MachineObject::is_in_printing()
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MachineObject::is_in_prepare()
|
||||
{
|
||||
return print_status == "PREPARE";
|
||||
}
|
||||
|
||||
bool MachineObject::is_printing_finished()
|
||||
{
|
||||
if (print_status.compare("FINISH") == 0
|
||||
@@ -1388,8 +1465,10 @@ void MachineObject::reset()
|
||||
camera_recording = false;
|
||||
camera_timelapse = false;
|
||||
printing_speed_mag = 100;
|
||||
gcode_file_prepare_percent = 0;
|
||||
iot_print_status = "";
|
||||
print_status = "";
|
||||
last_mc_print_stage = -1;
|
||||
|
||||
subtask_ = nullptr;
|
||||
|
||||
@@ -1444,6 +1523,11 @@ bool MachineObject::is_connected()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MachineObject::is_connecting()
|
||||
{
|
||||
return is_connected() && m_push_count == 0;
|
||||
}
|
||||
|
||||
void MachineObject::set_online_state(bool on_off)
|
||||
{
|
||||
m_is_online = on_off;
|
||||
@@ -1508,9 +1592,10 @@ int MachineObject::parse_json(std::string payload)
|
||||
if (j_pre.contains("print")) {
|
||||
if (j_pre["print"].contains("command")) {
|
||||
if (j_pre["print"]["command"].get<std::string>() == "push_status") {
|
||||
m_push_count++;
|
||||
if (j_pre["print"].contains("msg")) {
|
||||
if (j_pre["print"]["msg"].get<int>() == 0) { //all message
|
||||
BOOST_LOG_TRIVIAL(trace) << "static: get push_all msg, dev_id=" << dev_id;
|
||||
m_push_count++;
|
||||
print_json.diff2all_base_reset(j_pre);
|
||||
} else if (j_pre["print"]["msg"].get<int>() == 1) { //diff message
|
||||
if (print_json.diff2all(j_pre, j) == 0) {
|
||||
@@ -1544,11 +1629,14 @@ int MachineObject::parse_json(std::string payload)
|
||||
json jj = j["print"];
|
||||
if (jj.contains("command")) {
|
||||
if (jj["command"].get<std::string>() == "push_status") {
|
||||
m_push_count++;
|
||||
last_push_time = std::chrono::system_clock::now();
|
||||
#pragma region printing
|
||||
// U0 firmware
|
||||
if (jj.contains("print_type")) {
|
||||
print_type = jj["print_type"].get<std::string>();
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -1603,8 +1691,15 @@ int MachineObject::parse_json(std::string payload)
|
||||
|
||||
if (jj.contains("gcode_file"))
|
||||
this->m_gcode_file = jj["gcode_file"].get<std::string>();
|
||||
|
||||
if (jj.contains("project_id")
|
||||
if (jj.contains("gcode_file_prepare_percent")) {
|
||||
std::string percent_str = jj["gcode_file_prepare_percent"].get<std::string>();
|
||||
if (!percent_str.empty()) {
|
||||
try{
|
||||
this->gcode_file_prepare_percent = atoi(percent_str.c_str());
|
||||
} catch(...) {}
|
||||
}
|
||||
}
|
||||
if (jj.contains("project_id")
|
||||
&& jj.contains("profile_id")
|
||||
&& jj.contains("subtask_id")
|
||||
){
|
||||
@@ -1633,11 +1728,11 @@ int MachineObject::parse_json(std::string payload)
|
||||
curr_task->task_progress = mc_print_percent;
|
||||
curr_task->printing_status = print_status;
|
||||
curr_task->task_id = jj["subtask_id"].get<std::string>();
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
|
||||
#pragma region status
|
||||
/* temperature */
|
||||
if (jj.contains("bed_temper")) {
|
||||
@@ -1755,14 +1850,14 @@ int MachineObject::parse_json(std::string payload)
|
||||
camera_has_sdcard = jj["sdcard"].get<bool>();
|
||||
} else {
|
||||
//do not check sdcard if no sdcard field
|
||||
camera_has_sdcard = true;
|
||||
camera_has_sdcard = false;
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
;
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
|
||||
#pragma region upgrade
|
||||
try {
|
||||
if (jj.contains("upgrade_state")) {
|
||||
@@ -1788,9 +1883,15 @@ int MachineObject::parse_json(std::string payload)
|
||||
upgrade_force_upgrade = jj["upgrade_state"]["force_upgrade"].get<bool>();
|
||||
if (jj["upgrade_state"].contains("err_code"))
|
||||
upgrade_err_code = jj["upgrade_state"]["err_code"].get<int>();
|
||||
if (jj["upgrade_state"].contains("dis_state"))
|
||||
if (jj["upgrade_state"].contains("dis_state")) {
|
||||
if (upgrade_display_state != jj["upgrade_state"]["dis_state"].get<int>()
|
||||
&& jj["upgrade_state"]["dis_state"].get<int>() == 3) {
|
||||
GUI::wxGetApp().CallAfter([this] {
|
||||
this->command_get_version();
|
||||
});
|
||||
}
|
||||
upgrade_display_state = jj["upgrade_state"]["dis_state"].get<int>();
|
||||
else {
|
||||
} else {
|
||||
//BBS compatibility with old version
|
||||
if (upgrade_status == "DOWNLOADING"
|
||||
|| upgrade_status == "FLASHING"
|
||||
@@ -1847,7 +1948,7 @@ int MachineObject::parse_json(std::string payload)
|
||||
catch (...) {
|
||||
;
|
||||
}
|
||||
#pragma endregion
|
||||
#pragma endregion
|
||||
|
||||
#pragma region hms
|
||||
// parse hms msg
|
||||
@@ -1977,9 +2078,17 @@ int MachineObject::parse_json(std::string payload)
|
||||
curr_tray = tray_iter->second;
|
||||
}
|
||||
if (!curr_tray) continue;
|
||||
|
||||
if (curr_tray->hold_count > 0) {
|
||||
curr_tray->hold_count--;
|
||||
continue;
|
||||
}
|
||||
|
||||
curr_tray->id = (*tray_it)["id"].get<std::string>();
|
||||
if (tray_it->contains("tag_uid"))
|
||||
curr_tray->tag_uid = (*tray_it)["tag_uid"].get<std::string>();
|
||||
else
|
||||
curr_tray->tag_uid = "0";
|
||||
if (tray_it->contains("tray_info_idx") && tray_it->contains("tray_type")) {
|
||||
curr_tray->setting_id = (*tray_it)["tray_info_idx"].get<std::string>();
|
||||
std::string type = (*tray_it)["tray_type"].get<std::string>();
|
||||
@@ -1990,32 +2099,59 @@ int MachineObject::parse_json(std::string payload)
|
||||
} else {
|
||||
curr_tray->type = type;
|
||||
}
|
||||
} else {
|
||||
curr_tray->setting_id = "";
|
||||
curr_tray->type = "";
|
||||
}
|
||||
if (tray_it->contains("tray_sub_brands"))
|
||||
curr_tray->sub_brands = (*tray_it)["tray_sub_brands"].get<std::string>();
|
||||
else
|
||||
curr_tray->sub_brands = "";
|
||||
if (tray_it->contains("tray_weight"))
|
||||
curr_tray->weight = (*tray_it)["tray_weight"].get<std::string>();
|
||||
else
|
||||
curr_tray->weight = "";
|
||||
if (tray_it->contains("tray_diameter"))
|
||||
curr_tray->diameter = (*tray_it)["tray_diameter"].get<std::string>();
|
||||
else
|
||||
curr_tray->diameter = "";
|
||||
if (tray_it->contains("tray_temp"))
|
||||
curr_tray->temp = (*tray_it)["tray_temp"].get<std::string>();
|
||||
else
|
||||
curr_tray->temp = "";
|
||||
if (tray_it->contains("tray_time"))
|
||||
curr_tray->time = (*tray_it)["tray_time"].get<std::string>();
|
||||
else
|
||||
curr_tray->time = "";
|
||||
if (tray_it->contains("bed_temp_type"))
|
||||
curr_tray->bed_temp_type = (*tray_it)["bed_temp_type"].get<std::string>();
|
||||
else
|
||||
curr_tray->bed_temp_type = "";
|
||||
if (tray_it->contains("bed_temp"))
|
||||
curr_tray->bed_temp = (*tray_it)["bed_temp"].get<std::string>();
|
||||
else
|
||||
curr_tray->bed_temp = "";
|
||||
if (tray_it->contains("nozzle_temp_max"))
|
||||
curr_tray->nozzle_temp_max = (*tray_it)["nozzle_temp_max"].get<std::string>();
|
||||
else
|
||||
curr_tray->nozzle_temp_max = "";
|
||||
if (tray_it->contains("nozzle_temp_min"))
|
||||
curr_tray->nozzle_temp_min = (*tray_it)["nozzle_temp_min"].get<std::string>();
|
||||
else
|
||||
curr_tray->nozzle_temp_min = "";
|
||||
if (tray_it->contains("xcam_info"))
|
||||
curr_tray->xcam_info = (*tray_it)["xcam_info"].get<std::string>();
|
||||
else
|
||||
curr_tray->xcam_info = "";
|
||||
if (tray_it->contains("tray_uuid"))
|
||||
curr_tray->uuid = (*tray_it)["tray_uuid"].get<std::string>();
|
||||
else
|
||||
curr_tray->uuid = "0";
|
||||
if (tray_it->contains("tray_color")) {
|
||||
auto color = (*tray_it)["tray_color"].get<std::string>();
|
||||
curr_tray->update_color_from_str(color);
|
||||
} else {
|
||||
curr_tray->color = "";
|
||||
}
|
||||
try {
|
||||
if (!ams_id.empty() && !curr_tray->id.empty()) {
|
||||
@@ -2051,12 +2187,20 @@ int MachineObject::parse_json(std::string payload)
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
|
||||
|
||||
} else if (jj["command"].get<std::string>() == "gcode_line") {
|
||||
//ack of gcode_line
|
||||
BOOST_LOG_TRIVIAL(debug) << "parse_json, ack of gcode_line = " << j.dump(4);
|
||||
} else if (jj["command"].get<std::string>() == "project_file") {
|
||||
//ack of project file
|
||||
BOOST_LOG_TRIVIAL(debug) << "parse_json, ack of project_file = " << j.dump(4);
|
||||
std::string result;
|
||||
if (jj.contains("result")) {
|
||||
result = jj["result"].get<std::string>();
|
||||
if (result == "FAIL") {
|
||||
wxString text = _L("Failed to start printing job");
|
||||
GUI::wxGetApp().show_dialog(text);
|
||||
}
|
||||
}
|
||||
} else if (jj["command"].get<std::string>() == "ams_filament_setting") {
|
||||
if (jj["ams_id"].is_number()) {
|
||||
int ams_id = jj["ams_id"].get<int>();
|
||||
@@ -2071,6 +2215,8 @@ int MachineObject::parse_json(std::string payload)
|
||||
tray_it->second->type = jj["tray_type"].get<std::string>();
|
||||
tray_it->second->color = jj["tray_color"].get<std::string>();
|
||||
tray_it->second->setting_id = jj["tray_info_idx"].get<std::string>();
|
||||
// delay update
|
||||
tray_it->second->set_hold_count();
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(warning) << "ams_filament_setting, can not find in trayList, tray_id=" << tray_id;
|
||||
}
|
||||
@@ -2133,6 +2279,8 @@ int MachineObject::parse_json(std::string payload)
|
||||
}
|
||||
}
|
||||
catch (...) {}
|
||||
|
||||
parse_state_changed_event();
|
||||
}
|
||||
catch (...) {
|
||||
BOOST_LOG_TRIVIAL(trace) << "parse_json failed! dev_id=" << this->dev_id <<", payload = " << payload;
|
||||
@@ -2339,6 +2487,10 @@ DeviceManager::~DeviceManager()
|
||||
userMachineList.clear();
|
||||
}
|
||||
|
||||
void DeviceManager::set_agent(NetworkAgent* agent)
|
||||
{
|
||||
m_agent = agent;
|
||||
}
|
||||
|
||||
void DeviceManager::on_machine_alive(std::string json_str)
|
||||
{
|
||||
@@ -2376,7 +2528,12 @@ void DeviceManager::on_machine_alive(std::string json_str)
|
||||
obj->wifi_signal = printer_signal;
|
||||
obj->dev_connection_type = connect_type;
|
||||
obj->bind_state = bind_state;
|
||||
BOOST_LOG_TRIVIAL(info) << "SsdpDiscovery:: Update Machine Info, printer_sn = " << dev_id << ", signal = " << printer_signal;
|
||||
|
||||
// U0 firmware
|
||||
if (obj->dev_connection_type.empty() && obj->bind_state.empty())
|
||||
obj->bind_state = "free";
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug) << "SsdpDiscovery:: Update Machine Info, printer_sn = " << dev_id << ", signal = " << printer_signal;
|
||||
obj->last_alive = Slic3r::Utils::get_current_time_utc();
|
||||
obj->m_is_online = true;
|
||||
}
|
||||
@@ -2396,7 +2553,7 @@ void DeviceManager::on_machine_alive(std::string json_str)
|
||||
localMachineList.insert(std::make_pair(dev_id, obj));
|
||||
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << "SsdpDiscovery::New Machine, ip = " << dev_ip << ", printer_name= " << dev_name << ", printer_type = " << printer_type_str << ", signal = " << printer_signal;
|
||||
BOOST_LOG_TRIVIAL(debug) << "SsdpDiscovery::New Machine, ip = " << dev_ip << ", printer_name= " << dev_name << ", printer_type = " << printer_type_str << ", signal = " << printer_signal;
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
@@ -2480,6 +2637,11 @@ MachineObject* DeviceManager::get_local_machine(std::string dev_id)
|
||||
return it->second;
|
||||
}
|
||||
|
||||
void DeviceManager::erase_user_machine(std::string dev_id)
|
||||
{
|
||||
userMachineList.erase(dev_id);
|
||||
}
|
||||
|
||||
MachineObject* DeviceManager::get_user_machine(std::string dev_id)
|
||||
{
|
||||
if (!Slic3r::GUI::wxGetApp().is_user_login())
|
||||
@@ -2522,7 +2684,7 @@ void DeviceManager::clean_user_info()
|
||||
|
||||
bool DeviceManager::set_selected_machine(std::string dev_id)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(trace) << "set_selected_machine=" << dev_id;
|
||||
BOOST_LOG_TRIVIAL(info) << "set_selected_machine=" << dev_id;
|
||||
auto my_machine_list = get_my_machine_list();
|
||||
auto it = my_machine_list.find(dev_id);
|
||||
if (it != my_machine_list.end()) {
|
||||
@@ -2534,7 +2696,7 @@ bool DeviceManager::set_selected_machine(std::string dev_id)
|
||||
if (m_agent) {
|
||||
if (it->second->connection_type() != "lan" || it->second->connection_type().empty()) {
|
||||
if (m_agent->get_user_selected_machine() != dev_id) {
|
||||
BOOST_LOG_TRIVIAL(trace) << "set_selected_machine: same dev_id = " << dev_id;
|
||||
BOOST_LOG_TRIVIAL(info) << "static: set_selected_machine: same dev_id = " << dev_id;
|
||||
m_agent->set_user_selected_machine(dev_id);
|
||||
it->second->reset();
|
||||
} else {
|
||||
@@ -2680,7 +2842,7 @@ void DeviceManager::update_user_machine_list_info()
|
||||
{
|
||||
if (!m_agent) return;
|
||||
|
||||
BOOST_LOG_TRIVIAL(trace) << "update_user_machine_list_info";
|
||||
BOOST_LOG_TRIVIAL(debug) << "update_user_machine_list_info";
|
||||
unsigned int http_code;
|
||||
std::string body;
|
||||
int result = m_agent->get_user_print_info(&http_code, &body);
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
|
||||
#define USE_LOCAL_SOCKET_BIND 0
|
||||
|
||||
#define DISCONNECT_TIMEOUT 10000.f // milliseconds
|
||||
#define DISCONNECT_TIMEOUT 30000.f // milliseconds
|
||||
#define PUSHINFO_TIMEOUT 15000.f // milliseconds
|
||||
#define REQUEST_PUSH_MIN_TIME 3000.f // milliseconds
|
||||
#define REQUEST_PUSH_MIN_TIME 15000.f // milliseconds
|
||||
|
||||
#define FILAMENT_MAX_TEMP 300
|
||||
#define FILAMENT_DEF_TEMP 220
|
||||
@@ -153,11 +153,13 @@ public:
|
||||
wxColour wx_color;
|
||||
bool is_bbl;
|
||||
bool is_exists = false;
|
||||
int hold_count = 0;
|
||||
|
||||
AmsRoadPosition road_position;
|
||||
AmsStep step_state;
|
||||
AmsRfidState rfid_state;
|
||||
|
||||
void set_hold_count() { hold_count = 3; }
|
||||
void update_color_from_str(std::string color);
|
||||
wxColour get_color();
|
||||
|
||||
@@ -244,7 +246,13 @@ public:
|
||||
#define UpgradeFlashFailed -3
|
||||
#define UpgradePrinting -4
|
||||
|
||||
|
||||
// calc distance map
|
||||
struct DisValue {
|
||||
int tray_id;
|
||||
float distance;
|
||||
bool is_same_color = true;
|
||||
bool is_type_match = true;
|
||||
};
|
||||
|
||||
class MachineObject
|
||||
{
|
||||
@@ -347,6 +355,7 @@ public:
|
||||
// parse amsStatusMain and ams_status_sub
|
||||
void _parse_ams_status(int ams_status);
|
||||
bool has_ams() { return ams_exist_bits != 0; }
|
||||
bool is_U0_firmware();
|
||||
bool is_support_ams_mapping();
|
||||
bool is_only_support_cloud_print();
|
||||
static bool is_support_ams_mapping_version(std::string module, std::string version);
|
||||
@@ -415,16 +424,22 @@ public:
|
||||
int mc_print_line_number;
|
||||
int mc_print_percent; /* left print progess in percent */
|
||||
int mc_left_time; /* left time in seconds */
|
||||
int last_mc_print_stage;
|
||||
bool is_system_printing();
|
||||
|
||||
std::vector<int> stage_list_info;
|
||||
int stage_curr = 0;
|
||||
int m_push_count = 0;
|
||||
bool calibration_done { false };
|
||||
|
||||
wxString get_curr_stage();
|
||||
// return curr stage index of stage list
|
||||
int get_curr_stage_idx();
|
||||
bool is_in_calibration();
|
||||
bool is_calibration_running();
|
||||
bool is_calibration_done();
|
||||
|
||||
void parse_state_changed_event();
|
||||
|
||||
/* printing status */
|
||||
std::string print_status; /* enum string: FINISH, RUNNING, PAUSE, INIT, FAILED */
|
||||
@@ -455,11 +470,14 @@ public:
|
||||
BBLSliceInfo* slice_info {nullptr};
|
||||
int plate_index { -1 };
|
||||
std::string m_gcode_file;
|
||||
int gcode_file_prepare_percent = 0;
|
||||
BBLSubTask* subtask_;
|
||||
std::string obj_subtask_id; // subtask_id == 0 for sdcard
|
||||
std::string subtask_name;
|
||||
bool is_sdcard_printing();
|
||||
bool has_sdcard();
|
||||
bool has_timelapse();
|
||||
bool has_recording();
|
||||
|
||||
|
||||
MachineObject(NetworkAgent* agent, std::string name, std::string id, std::string ip);
|
||||
@@ -517,6 +535,7 @@ public:
|
||||
bool can_pause();
|
||||
bool can_abort();
|
||||
bool is_in_printing();
|
||||
bool is_in_prepare();
|
||||
bool is_printing_finished();
|
||||
void reset_update_time();
|
||||
void reset();
|
||||
@@ -525,6 +544,7 @@ public:
|
||||
void set_print_state(std::string status);
|
||||
|
||||
bool is_connected();
|
||||
bool is_connecting();
|
||||
void set_online_state(bool on_off);
|
||||
bool is_online() { return m_is_online; }
|
||||
bool is_info_ready();
|
||||
@@ -554,6 +574,7 @@ private:
|
||||
public:
|
||||
DeviceManager(NetworkAgent* agent = nullptr);
|
||||
~DeviceManager();
|
||||
void set_agent(NetworkAgent* agent);
|
||||
|
||||
std::mutex listMutex;
|
||||
std::string selected_machine; /* dev_id */
|
||||
@@ -566,6 +587,7 @@ public:
|
||||
MachineObject* get_local_machine(std::string dev_id);
|
||||
MachineObject* get_user_machine(std::string dev_id);
|
||||
MachineObject* get_my_machine(std::string dev_id);
|
||||
void erase_user_machine(std::string dev_id);
|
||||
void clean_user_info();
|
||||
|
||||
bool set_selected_machine(std::string dev_id);
|
||||
@@ -588,8 +610,6 @@ public:
|
||||
// get alive machine
|
||||
std::map<std::string, MachineObject*> get_local_machine_list();
|
||||
void load_last_machine();
|
||||
|
||||
void check_alive();
|
||||
};
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
#include "DownloadProgressDialog.hpp"
|
||||
|
||||
#include <wx/settings.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/statbmp.h>
|
||||
#include <wx/scrolwin.h>
|
||||
#include <wx/clipbrd.h>
|
||||
#include <wx/checkbox.h>
|
||||
#include <wx/html/htmlwin.h>
|
||||
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
|
||||
#include "libslic3r/libslic3r.h"
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include "GUI.hpp"
|
||||
#include "I18N.hpp"
|
||||
//#include "ConfigWizard.hpp"
|
||||
#include "wxExtensions.hpp"
|
||||
#include "slic3r/GUI/MainFrame.hpp"
|
||||
#include "GUI_App.hpp"
|
||||
|
||||
#define DESIGN_INPUT_SIZE wxSize(FromDIP(100), -1)
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
|
||||
|
||||
DownloadProgressDialog::DownloadProgressDialog(wxString title)
|
||||
: DPIDialog(static_cast<wxWindow *>(wxGetApp().mainframe), wxID_ANY, title, wxDefaultPosition, wxDefaultSize, wxCAPTION | wxCLOSE_BOX)
|
||||
{
|
||||
std::string icon_path = (boost::format("%1%/images/BambuStudioTitle.ico") % resources_dir()).str();
|
||||
SetIcon(wxIcon(encode_path(icon_path.c_str()), wxBITMAP_TYPE_ICO));
|
||||
|
||||
SetBackgroundColour(*wxWHITE);
|
||||
wxBoxSizer *m_sizer_main = new wxBoxSizer(wxVERTICAL);
|
||||
auto m_line_top = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(-1, 1));
|
||||
m_line_top->SetBackgroundColour(wxColour(166, 169, 170));
|
||||
m_sizer_main->Add(m_line_top, 0, wxEXPAND, 0);
|
||||
m_status_bar = std::make_shared<BBLStatusBarSend>(this);
|
||||
m_panel_download = m_status_bar->get_panel();
|
||||
m_panel_download->SetSize(wxSize(FromDIP(340), -1));
|
||||
m_panel_download->SetMinSize(wxSize(FromDIP(340), -1));
|
||||
m_panel_download->SetMaxSize(wxSize(FromDIP(340), -1));
|
||||
m_sizer_main->Add(m_panel_download, 0, wxALIGN_CENTER_VERTICAL|wxALL, FromDIP(20));
|
||||
m_sizer_main->Add(0, 0, 1, wxBOTTOM, 10);
|
||||
|
||||
SetSizer(m_sizer_main);
|
||||
Layout();
|
||||
Fit();
|
||||
CentreOnParent();
|
||||
}
|
||||
|
||||
bool DownloadProgressDialog::Show(bool show)
|
||||
{
|
||||
if (show) {
|
||||
m_upgrade_job = std::make_shared<UpgradeNetworkJob>(m_status_bar);
|
||||
m_upgrade_job->set_event_handle(this);
|
||||
m_status_bar->set_progress(0);
|
||||
Bind(EVT_UPGRADE_NETWORK_SUCCESS, [this](wxCommandEvent& evt) {
|
||||
m_status_bar->change_button_label(_L("Finish"));
|
||||
wxGetApp().restart_networking();
|
||||
m_status_bar->set_cancel_callback_fina(
|
||||
[this]() {
|
||||
this->Close();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
Bind(EVT_UPGRADE_NETWORK_FAILED, [this](wxCommandEvent& evt) {
|
||||
m_status_bar->change_button_label(_L("Close"));
|
||||
m_status_bar->set_progress(0);
|
||||
m_status_bar->set_cancel_callback_fina(
|
||||
[this]() {
|
||||
this->Close();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
m_status_bar->set_cancel_callback_fina([this]() {
|
||||
if (m_upgrade_job) {
|
||||
m_upgrade_job->cancel();
|
||||
//EndModal(wxID_CLOSE);
|
||||
}
|
||||
|
||||
});
|
||||
m_upgrade_job->start();
|
||||
}
|
||||
return DPIDialog::Show(show);
|
||||
}
|
||||
|
||||
DownloadProgressDialog::~DownloadProgressDialog() {}
|
||||
|
||||
void DownloadProgressDialog::on_dpi_changed(const wxRect &suggested_rect) {}
|
||||
|
||||
void DownloadProgressDialog::update_release_note(std::string release_note, std::string version) {}
|
||||
|
||||
}} // namespace Slic3r::GUI
|
||||
@@ -0,0 +1,55 @@
|
||||
#ifndef slic3r_DownloadProgressDialog_hpp_
|
||||
#define slic3r_DownloadProgressDialog_hpp_
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "GUI_Utils.hpp"
|
||||
#include <wx/dialog.h>
|
||||
#include <wx/font.h>
|
||||
#include <wx/bitmap.h>
|
||||
#include <wx/msgdlg.h>
|
||||
#include <wx/richmsgdlg.h>
|
||||
#include <wx/textctrl.h>
|
||||
#include <wx/statline.h>
|
||||
#include "Widgets/Button.hpp"
|
||||
#include "BBLStatusBar.hpp"
|
||||
#include "BBLStatusBarSend.hpp"
|
||||
#include "Jobs/UpgradeNetworkJob.hpp"
|
||||
|
||||
class wxBoxSizer;
|
||||
class wxCheckBox;
|
||||
class wxStaticBitmap;
|
||||
|
||||
#define MSG_DIALOG_BUTTON_SIZE wxSize(FromDIP(58), FromDIP(24))
|
||||
#define MSG_DIALOG_MIDDLE_BUTTON_SIZE wxSize(FromDIP(76), FromDIP(24))
|
||||
#define MSG_DIALOG_LONG_BUTTON_SIZE wxSize(FromDIP(90), FromDIP(24))
|
||||
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
class DownloadProgressDialog : public DPIDialog
|
||||
{
|
||||
protected:
|
||||
bool Show(bool show) override;
|
||||
|
||||
public:
|
||||
DownloadProgressDialog(wxString title);
|
||||
~DownloadProgressDialog();
|
||||
|
||||
void on_dpi_changed(const wxRect &suggested_rect) override;
|
||||
void update_release_note(std::string release_note, std::string version);
|
||||
|
||||
std::shared_ptr<BBLStatusBarSend> m_status_bar;
|
||||
std::shared_ptr<UpgradeNetworkJob> m_upgrade_job;
|
||||
wxPanel * m_panel_download;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -4988,7 +4988,8 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
|
||||
::sprintf(buf, imperial_units ? "%.2f in" : "%.2f m", ps.total_used_filament / /*1000*/koef);
|
||||
imgui.text(buf);
|
||||
ImGui::SameLine();
|
||||
::sprintf(buf, " %.2f g", ps.total_weight);
|
||||
double unit_conver = imperial_units ? GizmoObjectManipulation::oz_to_g : 1;
|
||||
::sprintf(buf, imperial_units ?" %.2f oz":" %.2f g", ps.total_weight / unit_conver);
|
||||
imgui.text(buf);
|
||||
|
||||
auto role_time = [time_mode](ExtrusionRole role) {
|
||||
|
||||
@@ -1349,7 +1349,12 @@ void GLCanvas3D::render(bool only_init)
|
||||
right_margin = SLIDER_RIGHT_MARGIN;
|
||||
bottom_margin = SLIDER_BOTTOM_MARGIN;
|
||||
}
|
||||
wxGetApp().plater()->get_notification_manager()->render_notifications(*this, get_overlay_window_width(), bottom_margin, right_margin);
|
||||
#if ENABLE_RETINA_GL
|
||||
float sc = m_retina_helper->get_scale_factor();
|
||||
wxGetApp().plater()->get_notification_manager()->render_notifications(*this, get_overlay_window_width(), bottom_margin * sc, right_margin);
|
||||
#else
|
||||
wxGetApp().plater()->get_notification_manager()->render_notifications(*this, get_overlay_window_width(), bottom_margin, right_margin);
|
||||
#endif
|
||||
}
|
||||
|
||||
wxGetApp().imgui()->render();
|
||||
@@ -3038,6 +3043,14 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
// Grab keyboard focus for input in gizmo dialogs.
|
||||
m_canvas->SetFocus();
|
||||
|
||||
if (evt.LeftDown()) {
|
||||
// Clear hover state in main toolbar
|
||||
wxMouseEvent evt2 = evt;
|
||||
evt2.SetEventType(wxEVT_MOTION);
|
||||
evt2.SetLeftDown(false);
|
||||
m_main_toolbar.on_mouse(evt2, *this);
|
||||
}
|
||||
|
||||
if (evt.LeftUp() || evt.MiddleUp() || evt.RightUp())
|
||||
mouse_up_cleanup();
|
||||
|
||||
@@ -6397,34 +6410,25 @@ void GLCanvas3D::_render_paint_toolbar() const
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
std::string item_text = (boost::format("%1% %2%") % (11) % filament_types[0]).str();
|
||||
const ImVec2 label_size = ImGui::CalcTextSize(item_text.c_str(), NULL, true);
|
||||
int button_size = label_size.x + item_spacing;
|
||||
#else
|
||||
int button_size = GLToolbar::Default_Icons_Size * wxGetApp().toolbar_icon_scale() + item_spacing;
|
||||
#endif
|
||||
float button_size = GLToolbar::Default_Icons_Size * f_scale * wxGetApp().toolbar_icon_scale() + item_spacing;
|
||||
|
||||
imgui.set_next_window_pos(0.5f * (canvas_w + (button_size + item_spacing) * extruder_num), button_size + item_spacing * 2, ImGuiCond_Always, 1.0f, 1.0f);
|
||||
imgui.begin(_L("Paint Toolbar"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar);
|
||||
bool disabled = !wxGetApp().plater()->can_fillcolor();
|
||||
unsigned char rgb[3];
|
||||
|
||||
float max_text = 0;
|
||||
for (int i = 0; i < extruder_num; i++) {
|
||||
if (i > 0) {
|
||||
if (filament_types.size() <= i) continue;
|
||||
std::string item_text = (boost::format("%1% %2%") % (i + 1) % filament_types[i]).str();
|
||||
const ImVec2 label_size = ImGui::CalcTextSize(item_text.c_str(), NULL, true);
|
||||
#ifdef __WINDOWS__
|
||||
if (i > 8)
|
||||
ImGui::SameLine(0.5 * item_spacing + (button_size - label_size.x) / 2 + (button_size + item_spacing) * i);
|
||||
else
|
||||
ImGui::SameLine((button_size - label_size.x) / 2 + (button_size + item_spacing) * i);
|
||||
#else
|
||||
ImGui::SameLine();
|
||||
#endif
|
||||
}
|
||||
//ImGui::SameLine();
|
||||
std::string item_text = (boost::format("%1%%2%") % (i + 1) % filament_types[i]).str();
|
||||
ImVec2 label_size = ImGui::CalcTextSize(item_text.c_str(), NULL, true);
|
||||
if (label_size.x > button_size)
|
||||
label_size.x = button_size * 0.6;
|
||||
max_text = std::max(max_text,label_size.x);
|
||||
}
|
||||
for (int i = 0; i < extruder_num; i++) {
|
||||
if (filament_types.size() <= i) continue;
|
||||
|
||||
ImGui::SameLine(item_spacing / 2 + (button_size - max_text) / 2 + (button_size + item_spacing) * i);
|
||||
ImGui::PushID(i);
|
||||
Slic3r::GUI::BitmapCache::parse_color(colors[i], rgb);
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImColor(rgb[0], rgb[1], rgb[2]).Value);
|
||||
@@ -6450,21 +6454,78 @@ void GLCanvas3D::_render_paint_toolbar() const
|
||||
ImGui::PopItemFlag();
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
for (int i = 0; i < extruder_num; i++){
|
||||
if (filament_types.size() <= i) continue;
|
||||
//TODO use filament type from filament management, current use PLA by default
|
||||
std::string item_text = (boost::format("%1% %2%") % (i + 1) % filament_types[i]).str();
|
||||
std::string item_text = (boost::format("%1%%2%") % (i + 1) % filament_types[i]).str();
|
||||
const ImVec2 label_size = ImGui::CalcTextSize(item_text.c_str(), NULL, true);
|
||||
|
||||
ImGui::SameLine(item_spacing + (button_size - label_size.x) / 2 + (button_size + item_spacing) * i);
|
||||
int len = strlen(filament_types[i].c_str());
|
||||
|
||||
ImGui::SameLine(item_spacing / 2 + (button_size - max_text) / 2 + (button_size + item_spacing) * i);
|
||||
|
||||
int count = 0;
|
||||
if (label_size.x > button_size)
|
||||
{
|
||||
for (int j = 0; j < filament_types[i].size(); j++)
|
||||
{
|
||||
if(std::isalpha(filament_types[i][j]))
|
||||
count++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i > 8)
|
||||
{
|
||||
if (label_size.x > button_size)
|
||||
{
|
||||
if(count * ImGui::GetFontSize() > button_size){
|
||||
if ((len - (count + 1)) <= 3)
|
||||
item_text = "\t" + std::to_string(i + 1) + "\n" + filament_types[i].substr(0, count) + "\n" + "\t" + filament_types[i].substr(count, len);
|
||||
else
|
||||
item_text = "\t" + std::to_string(i + 1) + "\n" + filament_types[i].substr(0, count + 1) + "\n"+ filament_types[i].substr(count + 1, len);
|
||||
} else {
|
||||
if (count <= 4)
|
||||
item_text = "\t" + std::to_string(i + 1) + "\n" + " " + filament_types[i].substr(0, count + 1) + "\n" + filament_types[i].substr(count + 1, len);
|
||||
else
|
||||
item_text = "\t" + std::to_string(i + 1) + "\n" + filament_types[i].substr(0, count + 1) + "\n" + filament_types[i].substr(count + 1, len);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
item_text = (boost::format("\t%1%\n %2%") % (i + 1) % filament_types[i]).str();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (label_size.x > button_size)
|
||||
{
|
||||
if(count * ImGui::GetFontSize() > button_size){
|
||||
if ((len - (count + 1)) <= 3)
|
||||
item_text = "\t " + std::to_string(i + 1) + "\n" + filament_types[i].substr(0, count) + "\n" + "\t" + filament_types[i].substr(count, len);
|
||||
else
|
||||
item_text = "\t " + std::to_string(i + 1) + "\n" + filament_types[i].substr(0, count + 1) + "\n"+ filament_types[i].substr(count + 1, len);
|
||||
} else {
|
||||
if (count <= 4)
|
||||
item_text = "\t " + std::to_string(i + 1) + "\n" + " " + filament_types[i].substr(0, count + 1) + "\n" + filament_types[i].substr(count + 1, len);
|
||||
else
|
||||
item_text = "\t " + std::to_string(i + 1) + "\n" + filament_types[i].substr(0, count + 1) + "\n" + filament_types[i].substr(count + 1, len);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
item_text = (boost::format("\t %1%\n\t%2%") % (i + 1) % filament_types[i]).str();
|
||||
}
|
||||
}
|
||||
Slic3r::GUI::BitmapCache::parse_color(colors[i], rgb);
|
||||
float gray = 0.299 * rgb[0] + 0.587 * rgb[1] + 0.114 * rgb[2];
|
||||
if (gray < 80)
|
||||
ImGui::TextColored(ImVec4(1.0f, 1.0f, 1.0f, 1.0f), item_text.c_str());
|
||||
else
|
||||
ImGui::TextColored(ImVec4(0.0f, 0.0f, 0.0f, 1.0f), item_text.c_str());
|
||||
|
||||
if (gray < 80){
|
||||
ImGui::TextColored(ImVec4(1.0f, 1.0f, 1.0f, 1.0f), item_text.c_str());
|
||||
} else{
|
||||
ImGui::TextColored(ImVec4(0.0f, 0.0f, 0.0f, 1.0f), item_text.c_str());
|
||||
}
|
||||
}
|
||||
ImGui::AlignTextToFramePadding();
|
||||
imgui.end();
|
||||
@@ -7468,8 +7529,8 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state)
|
||||
case EWarning::SlaSupportsOutside: text = ("SLA supports outside the print area were detected."); error = ErrorType::PLATER_ERROR; break;
|
||||
case EWarning::SomethingNotShown: text = _u8L("Only the object being edit is visible."); break;
|
||||
case EWarning::ObjectClashed:
|
||||
text = _u8L("An object is layed over the boundary of plate.\n"
|
||||
"Please solve the problem by moving it totally inside or outside plate.");
|
||||
text = _u8L("An object is laid over the boundary of plate or exceeds the height limit.\n"
|
||||
"Please solve the problem by moving it totally on or off the plate, and confirming that the height is within the build volume.");
|
||||
error = ErrorType::PLATER_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -299,10 +299,12 @@ bool GLTexture::load_from_svg_files_as_sprites_array(const std::vector<std::stri
|
||||
::memcpy((void*)pressed_data.data(), (const void*)sprite_data.data(), sprite_bytes);
|
||||
for (int i = 0; i < sprite_n_pixels; ++i) {
|
||||
int offset = i * 4;
|
||||
if (pressed_data.data()[offset] == 0) {
|
||||
::memset((void*)&pressed_data.data()[offset], 172, 3);
|
||||
pressed_data.data()[offset + 3] = (unsigned char)150;
|
||||
}
|
||||
if (pressed_data.data()[offset + 0] == 0 &&
|
||||
pressed_data.data()[offset + 1] == 0 &&
|
||||
pressed_data.data()[offset + 2] == 0) {
|
||||
::memset((void*)&pressed_data.data()[offset], 238, 3);
|
||||
pressed_data.data()[offset + 3] = (unsigned char) 225;
|
||||
}
|
||||
}
|
||||
|
||||
::memcpy((void*)disable_data.data(), (const void*)sprite_data.data(), sprite_bytes);
|
||||
@@ -315,25 +317,36 @@ bool GLTexture::load_from_svg_files_as_sprites_array(const std::vector<std::stri
|
||||
::memcpy((void*)hover_data.data(), (const void*)sprite_data.data(), sprite_bytes);
|
||||
for (int i = 0; i < sprite_n_pixels; ++i) {
|
||||
int offset = i * 4;
|
||||
if (hover_data.data()[offset] == 0) {
|
||||
::memset((void*)&hover_data.data()[offset], 172, 3);
|
||||
hover_data.data()[offset + 3] = (unsigned char)75;
|
||||
if (hover_data.data()[offset + 0] == 0 &&
|
||||
hover_data.data()[offset + 1] == 0 &&
|
||||
hover_data.data()[offset + 2] == 0)
|
||||
{
|
||||
::memset((void *) &hover_data.data()[offset], 238, 3);
|
||||
hover_data.data()[offset + 3] = (unsigned char) 75;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
::memcpy((void*)sprite_white_only_data.data(), (const void*)sprite_data.data(), sprite_bytes);
|
||||
for (int i = 0; i < sprite_n_pixels; ++i) {
|
||||
int offset = i * 4;
|
||||
if (sprite_white_only_data.data()[offset + 0] != 0 ||
|
||||
sprite_white_only_data.data()[offset + 1] != 0 ||
|
||||
sprite_white_only_data.data()[offset + 2] != 0){
|
||||
sprite_white_only_data.data()[offset + 0] = (unsigned char) 43;
|
||||
sprite_white_only_data.data()[offset + 1] = (unsigned char) 52;
|
||||
sprite_white_only_data.data()[offset + 2] = (unsigned char) 54;
|
||||
}
|
||||
}
|
||||
|
||||
::memcpy((void*)sprite_gray_only_data.data(), (const void*)sprite_data.data(), sprite_bytes);
|
||||
for (int i = 0; i < sprite_n_pixels; ++i) {
|
||||
int offset = i * 4;
|
||||
if (sprite_gray_only_data.data()[offset + 0] == 0) {
|
||||
if (sprite_gray_only_data.data()[offset + 0] != 0 ||
|
||||
sprite_gray_only_data.data()[offset + 1] != 0 ||
|
||||
sprite_gray_only_data.data()[offset + 2] != 0 ) {
|
||||
::memset((void*)&sprite_gray_only_data.data()[offset], 200, 3);
|
||||
}
|
||||
else {
|
||||
sprite_gray_only_data.data()[offset + 0] = (unsigned char)(sprite_data.data()[offset + 0] * 0.3 + 178);
|
||||
sprite_gray_only_data.data()[offset + 1] = (unsigned char)(sprite_data.data()[offset + 1] * 0.3 + 178);
|
||||
sprite_gray_only_data.data()[offset + 2] = (unsigned char)(sprite_data.data()[offset + 2] * 0.3 + 178);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -394,9 +407,9 @@ bool GLTexture::load_from_svg_files_as_sprites_array(const std::vector<std::stri
|
||||
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data()));
|
||||
else
|
||||
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data()));
|
||||
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
|
||||
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
|
||||
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0));
|
||||
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
|
||||
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
|
||||
|
||||
glsafe(::glBindTexture(GL_TEXTURE_2D, 0));
|
||||
|
||||
|
||||
@@ -538,4 +538,52 @@ void desktop_open_datadir_folder()
|
||||
#endif
|
||||
}
|
||||
|
||||
void desktop_open_any_folder( const std::string path )
|
||||
{
|
||||
// Execute command to open a file explorer, platform dependent.
|
||||
// FIXME: The const_casts aren't needed in wxWidgets 3.1, remove them when we upgrade.
|
||||
|
||||
#ifdef _WIN32
|
||||
const wxString widepath = from_u8(path);
|
||||
const wchar_t *argv[] = {L"explorer", widepath.GetData(), nullptr};
|
||||
::wxExecute(const_cast<wchar_t **>(argv), wxEXEC_ASYNC, nullptr);
|
||||
#elif __APPLE__
|
||||
const char *argv[] = {"open", path.data(), nullptr};
|
||||
::wxExecute(const_cast<char **>(argv), wxEXEC_ASYNC, nullptr);
|
||||
#else
|
||||
const char *argv[] = {"xdg-open", path.data(), nullptr};
|
||||
|
||||
// Check if we're running in an AppImage container, if so, we need to remove AppImage's env vars,
|
||||
// because they may mess up the environment expected by the file manager.
|
||||
// Mostly this is about LD_LIBRARY_PATH, but we remove a few more too for good measure.
|
||||
if (wxGetEnv("APPIMAGE", nullptr)) {
|
||||
// We're running from AppImage
|
||||
wxEnvVariableHashMap env_vars;
|
||||
wxGetEnvMap(&env_vars);
|
||||
|
||||
env_vars.erase("APPIMAGE");
|
||||
env_vars.erase("APPDIR");
|
||||
env_vars.erase("LD_LIBRARY_PATH");
|
||||
env_vars.erase("LD_PRELOAD");
|
||||
env_vars.erase("UNION_PRELOAD");
|
||||
|
||||
wxExecuteEnv exec_env;
|
||||
exec_env.env = std::move(env_vars);
|
||||
|
||||
wxString owd;
|
||||
if (wxGetEnv("OWD", &owd)) {
|
||||
// This is the original work directory from which the AppImage image was run,
|
||||
// set it as CWD for the child process:
|
||||
exec_env.cwd = std::move(owd);
|
||||
}
|
||||
|
||||
::wxExecute(const_cast<char **>(argv), wxEXEC_ASYNC, nullptr, &exec_env);
|
||||
} else {
|
||||
// Looks like we're NOT running from AppImage, we'll make no changes to the environment.
|
||||
::wxExecute(const_cast<char **>(argv), wxEXEC_ASYNC, nullptr, nullptr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
} }
|
||||
|
||||
@@ -82,7 +82,8 @@ extern void about();
|
||||
extern void login();
|
||||
// Ask the destop to open the datadir using the default file explorer.
|
||||
extern void desktop_open_datadir_folder();
|
||||
|
||||
// Ask the destop to open one folder
|
||||
extern void desktop_open_any_folder(const std::string path);
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
||||
|
||||
+606
-153
File diff suppressed because it is too large
Load Diff
@@ -11,6 +11,7 @@
|
||||
#include "slic3r/GUI/DeviceManager.hpp"
|
||||
#include "slic3r/Utils/NetworkAgent.hpp"
|
||||
#include "slic3r/GUI/WebViewDialog.hpp"
|
||||
#include "slic3r/GUI/Jobs/UpgradeNetworkJob.hpp"
|
||||
|
||||
#include <wx/app.h>
|
||||
#include <wx/colour.h>
|
||||
@@ -22,7 +23,8 @@
|
||||
#include <mutex>
|
||||
#include <stack>
|
||||
|
||||
#define BBL_HAS_FIRST_PAGE 1
|
||||
#define BBL_HAS_FIRST_PAGE 1
|
||||
#define STUDIO_INACTIVE_TIMEOUT 15*60*1000
|
||||
|
||||
class wxMenuItem;
|
||||
class wxMenuBar;
|
||||
@@ -104,6 +106,7 @@ enum CameraMenuIDs {
|
||||
wxID_CAMERA_COUNT,
|
||||
};
|
||||
|
||||
|
||||
class Tab;
|
||||
class ConfigWizard;
|
||||
|
||||
@@ -186,6 +189,7 @@ public:
|
||||
class GUI_App : public wxApp
|
||||
{
|
||||
public:
|
||||
|
||||
//BBS: remove GCodeViewer as seperate APP logic
|
||||
enum class EAppMode : unsigned char
|
||||
{
|
||||
@@ -241,9 +245,13 @@ private:
|
||||
|
||||
//BBS
|
||||
bool m_is_closing {false};
|
||||
Slic3r::DeviceManager* m_device_manager;
|
||||
Slic3r::DeviceManager* m_device_manager { nullptr };
|
||||
NetworkAgent* m_agent { nullptr };
|
||||
std::vector<std::string> need_delete_presets; // store setting ids of preset
|
||||
bool m_networking_compatible { false };
|
||||
bool m_networking_need_update { false };
|
||||
bool m_networking_cancel_update { false };
|
||||
std::shared_ptr<UpgradeNetworkJob> m_upgrade_network_job;
|
||||
|
||||
VersionInfo version_info;
|
||||
|
||||
@@ -335,7 +343,7 @@ public:
|
||||
void load_gcode(wxWindow* parent, wxString& input_file) const;
|
||||
|
||||
void ShowUserGuide();
|
||||
void ShowDailyTip();
|
||||
void ShowDownNetPluginDlg();
|
||||
void ShowUserLogin();
|
||||
void ShowOnlyFilament();
|
||||
//BBS
|
||||
@@ -358,11 +366,18 @@ public:
|
||||
void on_http_error(wxCommandEvent &evt);
|
||||
void on_user_login(wxCommandEvent &evt);
|
||||
|
||||
// BBS
|
||||
bool is_studio_active();
|
||||
void reset_to_active();
|
||||
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 enter_force_upgrade();
|
||||
void no_new_version();
|
||||
void show_dialog(wxString msg);
|
||||
void reload_settings();
|
||||
void remove_user_presets();
|
||||
void sync_preset(Preset* preset);
|
||||
@@ -484,12 +499,23 @@ public:
|
||||
void associate_files(std::wstring extend);
|
||||
void disassociate_files(std::wstring extend);
|
||||
#endif // __WXMSW__
|
||||
std::string get_plugin_url(std::string country_code);
|
||||
int download_plugin(InstallProgressFn pro_fn = nullptr, WasCancelledFn cancel_fn = nullptr);
|
||||
int install_plugin(InstallProgressFn pro_fn = nullptr, WasCancelledFn cancel_fn = nullptr);
|
||||
std::string get_http_url(std::string country_code);
|
||||
bool is_compatibility_version();
|
||||
bool check_networking_version();
|
||||
void cancel_networking_install();
|
||||
void restart_networking();
|
||||
|
||||
private:
|
||||
int updating_bambu_networking();
|
||||
bool on_init_inner();
|
||||
bool on_init_network();
|
||||
void init_networking_callbacks();
|
||||
void init_app_config();
|
||||
//BBS set extra header for http request
|
||||
std::map<std::string, std::string> get_extra_header();
|
||||
void init_http_extra_header();
|
||||
bool check_older_app_config(Semver current_version, bool backup);
|
||||
void copy_older_config();
|
||||
|
||||
@@ -464,7 +464,8 @@ wxMenu* MenuFactory::append_submenu_add_generic(wxMenu* menu, ModelVolumeType ty
|
||||
auto item = L("Timelapse Wipe Tower");
|
||||
type = ModelVolumeType::TIMELAPSE_WIPE_TOWER;
|
||||
append_menu_item(sub_menu, wxID_ANY, _(item), "",
|
||||
[type, item](wxCommandEvent&) { obj_list()->load_generic_subobject(item, type); }, "", menu);
|
||||
[type, item](wxCommandEvent &) { obj_list()->load_generic_subobject(item, type); }, "", menu,
|
||||
[]() { return plater()->can_add_timelapse_wt(); }, m_parent);
|
||||
}
|
||||
|
||||
return sub_menu;
|
||||
|
||||
@@ -264,6 +264,8 @@ ObjectList::ObjectList(wxWindow* parent) :
|
||||
// which seems to be working as of now.
|
||||
this->CallAfter([this](){ ensure_current_item_visible(); });
|
||||
#else
|
||||
update_name_column_width();
|
||||
|
||||
ensure_current_item_visible();
|
||||
#endif
|
||||
e.Skip();
|
||||
@@ -768,17 +770,21 @@ void ObjectList::update_filament_colors()
|
||||
|
||||
void ObjectList::update_name_column_width() const
|
||||
{
|
||||
auto em = em_unit(const_cast<ObjectList*>(this));
|
||||
int extra_width = 0;
|
||||
wxSize client_size = this->GetClientSize();
|
||||
bool p_vbar = this->GetParent()->HasScrollbar(wxVERTICAL);
|
||||
bool p_hbar = this->GetParent()->HasScrollbar(wxHORIZONTAL);
|
||||
|
||||
auto em = em_unit(const_cast<ObjectList*>(this));
|
||||
// BBS: walkaround for wxDataViewCtrl::HasScrollbar() does not return correct status
|
||||
int others_width = 0;
|
||||
for (int cn = colName; cn < colCount; cn++) {
|
||||
if (cn != colName) {
|
||||
if (GetColumn(cn)->IsHidden())
|
||||
extra_width += m_columns_width[cn];
|
||||
if (!GetColumn(cn)->IsHidden())
|
||||
others_width += m_columns_width[cn];
|
||||
}
|
||||
}
|
||||
|
||||
GetColumn(colName)->SetWidth((m_columns_width[colName] + extra_width) * em);
|
||||
GetColumn(colName)->SetWidth(client_size.x - (others_width)*em);
|
||||
}
|
||||
|
||||
void ObjectList::set_filament_column_hidden(const bool hide) const
|
||||
@@ -1145,6 +1151,8 @@ void ObjectList::list_manipulation(const wxPoint& mouse_pos, bool evt_context_me
|
||||
GLGizmosManager& gizmos_mgr = wxGetApp().plater()->get_view3D_canvas3D()->get_gizmos_manager();
|
||||
if (gizmos_mgr.get_current_type() != GLGizmosManager::EType::FdmSupports)
|
||||
gizmos_mgr.open_gizmo(GLGizmosManager::EType::FdmSupports);
|
||||
else
|
||||
gizmos_mgr.reset_all_states();
|
||||
}
|
||||
}
|
||||
else if (col_num == colColorPaint) {
|
||||
@@ -1153,6 +1161,8 @@ void ObjectList::list_manipulation(const wxPoint& mouse_pos, bool evt_context_me
|
||||
GLGizmosManager& gizmos_mgr = wxGetApp().plater()->get_view3D_canvas3D()->get_gizmos_manager();
|
||||
if (gizmos_mgr.get_current_type() != GLGizmosManager::EType::MmuSegmentation)
|
||||
gizmos_mgr.open_gizmo(GLGizmosManager::EType::MmuSegmentation);
|
||||
else
|
||||
gizmos_mgr.reset_all_states();
|
||||
}
|
||||
}
|
||||
else if (col_num == colEditing) {
|
||||
@@ -2028,13 +2038,16 @@ void ObjectList::load_mesh_object(const TriangleMesh &mesh, const wxString &name
|
||||
new_object->translate(-bb.center());
|
||||
|
||||
if (is_timelapse_wt) {
|
||||
new_object->instances[0]->set_offset( Vec3d(80.0, 230.0, -new_object->origin_translation.z()) );
|
||||
new_object->is_timelapse_wipe_tower = true;
|
||||
auto curr_plate = wxGetApp().plater()->get_partplate_list().get_curr_plate();
|
||||
int highest_extruder = 0;
|
||||
double max_height = curr_plate->estimate_timelapse_wipe_tower_height(&highest_extruder);
|
||||
new_object->scale(1, 1, max_height / new_object->bounding_box().size()[2]);
|
||||
|
||||
// move to garbage bin of curr plate
|
||||
auto offset = curr_plate->get_origin() + Vec3d(80.0, 230.0, -new_object->origin_translation.z());
|
||||
new_object->instances[0]->set_offset(offset);
|
||||
|
||||
new_object->config.set_key_value("sparse_infill_density", new ConfigOptionPercent(0));
|
||||
new_object->config.set_key_value("top_shell_layers", new ConfigOptionInt(0));
|
||||
new_object->config.set("extruder", highest_extruder);
|
||||
@@ -2237,14 +2250,15 @@ bool ObjectList::del_subobject_from_object(const int obj_idx, const int idx, con
|
||||
|
||||
// update extruder color in ObjectList
|
||||
wxDataViewItem obj_item = m_objects_model->GetItemById(obj_idx);
|
||||
// BBS
|
||||
#if 0
|
||||
if (obj_item) {
|
||||
// BBS
|
||||
if (last_volume->config.has("extruder")) {
|
||||
int extruder_id = last_volume->config.opt_int("extruder");
|
||||
object->config.set("extruder", extruder_id);
|
||||
}
|
||||
wxString extruder = object->config.has("extruder") ? wxString::Format("%d", object->config.extruder()) : _devL("1");
|
||||
m_objects_model->SetExtruder(extruder, obj_item);
|
||||
}
|
||||
#endif
|
||||
// add settings to the object, if it has them
|
||||
add_settings_item(obj_item, &object->config.get());
|
||||
}
|
||||
|
||||
@@ -246,7 +246,7 @@ void GLGizmoBase::GizmoImguiEnd()
|
||||
m_imgui->end();
|
||||
}
|
||||
|
||||
void GLGizmoBase::GizmoImguiSetNextWIndowPos(float x, float y, int flag, float pivot_x, float pivot_y)
|
||||
void GLGizmoBase::GizmoImguiSetNextWIndowPos(float &x, float y, int flag, float pivot_x, float pivot_y)
|
||||
{
|
||||
if (abs(last_input_window_width) > 0.01f) {
|
||||
if (x + last_input_window_width > m_parent.get_canvas_size().get_width()) {
|
||||
|
||||
@@ -206,7 +206,7 @@ protected:
|
||||
|
||||
bool GizmoImguiBegin(const std::string& name, int flags);
|
||||
void GizmoImguiEnd();
|
||||
void GizmoImguiSetNextWIndowPos(float x, float y, int flag, float pivot_x = 0.0f, float pivot_y = 0.0f);
|
||||
void GizmoImguiSetNextWIndowPos(float &x, float y, int flag, float pivot_x = 0.0f, float pivot_y = 0.0f);
|
||||
// Returns the picking color for the given id, based on the BASE_ID constant
|
||||
// No check is made for clashing with other picking color (i.e. GLVolumes)
|
||||
std::array<float, 4> picking_color_component(unsigned int id) const;
|
||||
|
||||
@@ -88,7 +88,7 @@ bool GLGizmoFdmSupports::on_init()
|
||||
m_desc["remove"] = _L("Erase painting");
|
||||
m_desc["remove_all"] = _L("Erase all painting");
|
||||
m_desc["highlight_by_angle"] = _L("Highlight overhang areas") + ": ";
|
||||
m_desc["fragment_filter"] = _L("Fragment filter");
|
||||
m_desc["fragment_filter"] = _L("Gap fill");
|
||||
m_desc["perform_filter"] = _L("Perform");
|
||||
m_desc["fragment_area"] = _L("Fragment area");
|
||||
m_desc["brush_size"] = _L("Set pen size");
|
||||
@@ -246,7 +246,7 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l
|
||||
ImGui::AlignTextToFramePadding();
|
||||
m_imgui->text(m_desc.at("tool_type"));
|
||||
std::array<wchar_t, 4> tool_icons = { ImGui::CircleButtonIcon, ImGui::SphereButtonIcon, ImGui::FillButtonIcon, ImGui::FragmentFilterIcon };
|
||||
std::array<wxString, 4> tool_tips = { _L("Circle"), _L("Sphere"), _L("Fill"), _L("Fragment Filter") };
|
||||
std::array<wxString, 4> tool_tips = { _L("Circle"), _L("Sphere"), _L("Fill"), _L("Gap Fill") };
|
||||
for (int i = 0; i < tool_icons.size(); i++) {
|
||||
std::string str_label = std::string("##");
|
||||
std::wstring btn_name = tool_icons[i] + boost::nowide::widen(str_label);
|
||||
|
||||
@@ -337,12 +337,12 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott
|
||||
GizmoImguiBegin(get_name(), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar);
|
||||
|
||||
// First calculate width of all the texts that are could possibly be shown. We will decide set the dialog width based on that:
|
||||
const float clipping_slider_left = m_imgui->calc_text_size(m_desc.at("clipping_of_view")).x + m_imgui->scaled(1.5f);
|
||||
const float clipping_slider_left = m_imgui->calc_text_size(m_desc.at("clipping_of_view")).x + m_imgui->scaled(1.f);
|
||||
const float cursor_slider_left = m_imgui->calc_text_size(m_desc.at("cursor_size")).x + m_imgui->scaled(1.f);
|
||||
const float smart_fill_slider_left = m_imgui->calc_text_size(m_desc.at("smart_fill_angle")).x + m_imgui->scaled(1.5f);
|
||||
const float edge_detect_slider_left = m_imgui->calc_text_size(m_desc.at("edge_detection")).x + m_imgui->scaled(1.f);
|
||||
const float fragment_area_slider_left = m_imgui->calc_text_size(m_desc.at("fragment_area")).x + m_imgui->scaled(1.f);
|
||||
const float height_range_slider_left = m_imgui->calc_text_size(m_desc.at("height_range")).x + m_imgui->scaled(1.f);
|
||||
const float fragment_area_slider_left = m_imgui->calc_text_size(m_desc.at("fragment_area")).x + m_imgui->scaled(1.5f);
|
||||
const float height_range_slider_left = m_imgui->calc_text_size(m_desc.at("height_range")).x + m_imgui->scaled(1.5f);
|
||||
|
||||
const float remove_btn_width = m_imgui->calc_text_size(m_desc.at("remove_all")).x + m_imgui->scaled(1.f);
|
||||
const float filter_btn_width = m_imgui->calc_text_size(m_desc.at("perform_filter")).x + m_imgui->scaled(1.f);
|
||||
@@ -359,6 +359,8 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott
|
||||
total_text_max += caption_max + m_imgui->scaled(1.f);
|
||||
caption_max += m_imgui->scaled(1.f);
|
||||
|
||||
const float circle_max_width = std::max(clipping_slider_left,cursor_slider_left);
|
||||
const float height_max_width = std::max(clipping_slider_left,height_range_slider_left);
|
||||
const float sliders_left_width = std::max(smart_fill_slider_left,
|
||||
std::max(cursor_slider_left, std::max(edge_detect_slider_left, std::max(fragment_area_slider_left, std::max(height_range_slider_left,
|
||||
clipping_slider_left)))));
|
||||
@@ -404,7 +406,15 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott
|
||||
// draw filament background
|
||||
ImGuiColorEditFlags flags = ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_NoTooltip;
|
||||
if (m_selected_extruder_idx != extruder_idx) flags |= ImGuiColorEditFlags_NoBorder;
|
||||
bool color_picked = ImGui::ColorButton(color_label.c_str(), color_vec, flags, button_size);
|
||||
#ifdef __APPLE__
|
||||
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.4f, 0.4f, 0.4f, 1.0f));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0f);
|
||||
bool color_picked = ImGui::ColorButton(color_label.c_str(), color_vec, flags, button_size);
|
||||
ImGui::PopStyleVar(1);
|
||||
ImGui::PopStyleColor(1);
|
||||
#else
|
||||
bool color_picked = ImGui::ColorButton(color_label.c_str(), color_vec, flags, button_size);
|
||||
#endif
|
||||
color_button_high = ImGui::GetCursorPos().y - color_button - 2.0;
|
||||
if (color_picked) { m_selected_extruder_idx = extruder_idx; }
|
||||
|
||||
@@ -425,7 +435,7 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott
|
||||
m_imgui->text(m_desc.at("tool_type"));
|
||||
|
||||
std::array<wchar_t, 6> tool_icons = { ImGui::CircleButtonIcon,ImGui::SphereButtonIcon, ImGui::TriangleButtonIcon, ImGui::HeightRangeIcon, ImGui::FillButtonIcon, ImGui::FragmentFilterIcon };
|
||||
std::array<wxString, 6> tool_tips = { _L("Circle"), _L("Sphere"), _L("Triangle"), _L("Height Range"), _L("Fill"), _L("Fragment Filter") };
|
||||
std::array<wxString, 6> tool_tips = { _L("Circle"), _L("Sphere"), _L("Triangle"), _L("Height Range"), _L("Fill"), _L("Gap Fill") };
|
||||
for (int i = 0; i < tool_icons.size(); i++) {
|
||||
std::string str_label = std::string("##");
|
||||
std::wstring btn_name = tool_icons[i] + boost::nowide::widen(str_label);
|
||||
@@ -460,33 +470,54 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott
|
||||
if (m_current_tool != old_tool)
|
||||
this->tool_changed(old_tool, m_current_tool);
|
||||
|
||||
if (m_current_tool == ImGui::CircleButtonIcon) {
|
||||
m_cursor_type = TriangleSelector::CursorType::CIRCLE;
|
||||
if (m_current_tool == ImGui::CircleButtonIcon || m_current_tool == ImGui::SphereButtonIcon) {
|
||||
if (m_current_tool == ImGui::CircleButtonIcon)
|
||||
m_cursor_type = TriangleSelector::CursorType::CIRCLE;
|
||||
else
|
||||
m_cursor_type = TriangleSelector::CursorType::SPHERE;
|
||||
m_tool_type = ToolType::BRUSH;
|
||||
|
||||
ImGui::AlignTextToFramePadding();
|
||||
m_imgui->text(m_desc.at("cursor_size"));
|
||||
ImGui::SameLine(sliders_left_width);
|
||||
ImGui::PushItemWidth(window_width - sliders_left_width - slider_width_times * slider_icon_width);
|
||||
ImGui::SameLine(circle_max_width);
|
||||
ImGui::PushItemWidth(window_width - circle_max_width - slider_width_times * slider_icon_width);
|
||||
m_imgui->bbl_slider_float_style("##cursor_radius", &m_cursor_radius, CursorRadiusMin, CursorRadiusMax, "%.2f", 1.0f, true);
|
||||
ImGui::SameLine(window_width - slider_icon_width);
|
||||
ImGui::PushItemWidth(1.5 * slider_icon_width);
|
||||
ImGui::BBLDragFloat("##cursor_radius_input", &m_cursor_radius, 0.05f, 0.0f, 0.0f, "%.2f");
|
||||
} else if (m_current_tool == ImGui::SphereButtonIcon){
|
||||
m_cursor_type = TriangleSelector::CursorType::SPHERE;
|
||||
m_tool_type = ToolType::BRUSH;
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::AlignTextToFramePadding();
|
||||
m_imgui->text(m_desc.at("cursor_size"));
|
||||
ImGui::SameLine(sliders_left_width);
|
||||
ImGui::PushItemWidth(window_width - sliders_left_width - slider_width_times * slider_icon_width);
|
||||
m_imgui->bbl_slider_float_style("##cursor_radius", &m_cursor_radius, CursorRadiusMin, CursorRadiusMax, "%.2f", 1.0f, true);
|
||||
m_imgui->text(m_desc.at("clipping_of_view"));
|
||||
|
||||
auto clp_dist = float(m_c->object_clipper()->get_position());
|
||||
ImGui::SameLine(circle_max_width);
|
||||
ImGui::PushItemWidth(window_width - circle_max_width - slider_width_times * slider_icon_width);
|
||||
bool slider_clp_dist = m_imgui->bbl_slider_float_style("##clp_dist", &clp_dist, 0.f, 1.f, "%.2f", 1.0f, true);
|
||||
ImGui::SameLine(window_width - slider_icon_width);
|
||||
ImGui::PushItemWidth(1.5 * slider_icon_width);
|
||||
ImGui::BBLDragFloat("##cursor_radius_input", &m_cursor_radius, 0.05f, 0.0f, 0.0f, "%.2f");
|
||||
bool b_clp_dist_input = ImGui::BBLDragFloat("##clp_dist_input", &clp_dist, 0.05f, 0.0f, 0.0f, "%.2f");
|
||||
|
||||
if (slider_clp_dist || b_clp_dist_input) { m_c->object_clipper()->set_position(clp_dist, true); }
|
||||
|
||||
} else if (m_current_tool == ImGui::TriangleButtonIcon) {
|
||||
m_cursor_type = TriangleSelector::CursorType::POINTER;
|
||||
m_tool_type = ToolType::BRUSH;
|
||||
|
||||
ImGui::AlignTextToFramePadding();
|
||||
m_imgui->text(m_desc.at("clipping_of_view"));
|
||||
|
||||
auto clp_dist = float(m_c->object_clipper()->get_position());
|
||||
ImGui::SameLine(clipping_slider_left);
|
||||
ImGui::PushItemWidth(window_width - clipping_slider_left - slider_width_times * slider_icon_width);
|
||||
bool slider_clp_dist = m_imgui->bbl_slider_float_style("##clp_dist", &clp_dist, 0.f, 1.f, "%.2f", 1.0f, true);
|
||||
ImGui::SameLine(window_width - slider_icon_width);
|
||||
ImGui::PushItemWidth(1.5 * slider_icon_width);
|
||||
bool b_clp_dist_input = ImGui::BBLDragFloat("##clp_dist_input", &clp_dist, 0.05f, 0.0f, 0.0f, "%.2f");
|
||||
|
||||
if (slider_clp_dist || b_clp_dist_input) { m_c->object_clipper()->set_position(clp_dist, true); }
|
||||
|
||||
} else if (m_current_tool == ImGui::FillButtonIcon) {
|
||||
m_cursor_type = TriangleSelector::CursorType::POINTER;
|
||||
m_imgui->bbl_checkbox(m_desc["edge_detection"], m_detect_geometry_edge);
|
||||
@@ -511,34 +542,6 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott
|
||||
// set to negative value to disable edge detection
|
||||
m_smart_fill_angle = -1.f;
|
||||
}
|
||||
} else if (m_current_tool == ImGui::HeightRangeIcon) {
|
||||
m_tool_type = ToolType::BRUSH;
|
||||
m_cursor_type = TriangleSelector::CursorType::HEIGHT_RANGE;
|
||||
ImGui::AlignTextToFramePadding();
|
||||
m_imgui->text(m_desc["height_range"] + ":");
|
||||
ImGui::SameLine(sliders_left_width);
|
||||
ImGui::PushItemWidth(window_width - sliders_left_width - slider_width_times * slider_icon_width);
|
||||
std::string format_str = std::string("%.2f") + I18N::translate_utf8("mm", "Heigh range," "Facet in [cursor z, cursor z + height] will be selected.");
|
||||
m_imgui->bbl_slider_float_style("##cursor_height", &m_cursor_height, CursorHeightMin, CursorHeightMax, format_str.data(), 1.0f, true);
|
||||
ImGui::SameLine(window_width - slider_icon_width);
|
||||
ImGui::PushItemWidth(1.5 * slider_icon_width);
|
||||
ImGui::BBLDragFloat("##cursor_height_input", &m_cursor_height, 0.05f, 0.0f, 0.0f, "%.2f");
|
||||
}
|
||||
else if (m_current_tool == ImGui::FragmentFilterIcon) {
|
||||
m_tool_type = ToolType::FRAGMENT_FILTER;
|
||||
m_cursor_type = TriangleSelector::CursorType::POINTER;
|
||||
ImGui::AlignTextToFramePadding();
|
||||
m_imgui->text(m_desc["fragment_area"] + ":");
|
||||
ImGui::SameLine(sliders_left_width);
|
||||
ImGui::PushItemWidth(window_width - sliders_left_width - slider_width_times * slider_icon_width);
|
||||
std::string format_str = std::string("%.2f") + I18N::translate_utf8("", "Triangle patch area threshold,""triangle patch will be merged to neighbor if its area is less than threshold");
|
||||
m_imgui->bbl_slider_float_style("##fragment_area", &TriangleSelectorPatch::fragment_area, TriangleSelectorPatch::FragmentAreaMin, TriangleSelectorPatch::FragmentAreaMax, format_str.data(), 1.0f, true);
|
||||
ImGui::SameLine(window_width - slider_icon_width);
|
||||
ImGui::PushItemWidth(1.5 * slider_icon_width);
|
||||
ImGui::BBLDragFloat("##fragment_area_input", &TriangleSelectorPatch::fragment_area, 0.05f, 0.0f, 0.0f, "%.2f");
|
||||
}
|
||||
|
||||
if (m_current_tool != ImGui::FragmentFilterIcon) {
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::AlignTextToFramePadding();
|
||||
@@ -552,8 +555,49 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott
|
||||
ImGui::PushItemWidth(1.5 * slider_icon_width);
|
||||
bool b_clp_dist_input = ImGui::BBLDragFloat("##clp_dist_input", &clp_dist, 0.05f, 0.0f, 0.0f, "%.2f");
|
||||
|
||||
if (slider_clp_dist || b_clp_dist_input) { m_c->object_clipper()->set_position(clp_dist, true);}
|
||||
|
||||
} else if (m_current_tool == ImGui::HeightRangeIcon) {
|
||||
m_tool_type = ToolType::BRUSH;
|
||||
m_cursor_type = TriangleSelector::CursorType::HEIGHT_RANGE;
|
||||
ImGui::AlignTextToFramePadding();
|
||||
m_imgui->text(m_desc["height_range"] + ":");
|
||||
ImGui::SameLine(height_max_width);
|
||||
ImGui::PushItemWidth(window_width - height_max_width - slider_width_times * slider_icon_width);
|
||||
std::string format_str = std::string("%.2f") + I18N::translate_utf8("mm", "Heigh range," "Facet in [cursor z, cursor z + height] will be selected.");
|
||||
m_imgui->bbl_slider_float_style("##cursor_height", &m_cursor_height, CursorHeightMin, CursorHeightMax, format_str.data(), 1.0f, true);
|
||||
ImGui::SameLine(window_width - slider_icon_width);
|
||||
ImGui::PushItemWidth(1.5 * slider_icon_width);
|
||||
ImGui::BBLDragFloat("##cursor_height_input", &m_cursor_height, 0.05f, 0.0f, 0.0f, "%.2f");
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::AlignTextToFramePadding();
|
||||
m_imgui->text(m_desc.at("clipping_of_view"));
|
||||
|
||||
auto clp_dist = float(m_c->object_clipper()->get_position());
|
||||
ImGui::SameLine(height_max_width);
|
||||
ImGui::PushItemWidth(window_width - height_max_width - slider_width_times * slider_icon_width);
|
||||
bool slider_clp_dist = m_imgui->bbl_slider_float_style("##clp_dist", &clp_dist, 0.f, 1.f, "%.2f", 1.0f, true);
|
||||
ImGui::SameLine(window_width - slider_icon_width);
|
||||
ImGui::PushItemWidth(1.5 * slider_icon_width);
|
||||
bool b_clp_dist_input = ImGui::BBLDragFloat("##clp_dist_input", &clp_dist, 0.05f, 0.0f, 0.0f, "%.2f");
|
||||
|
||||
if (slider_clp_dist || b_clp_dist_input) { m_c->object_clipper()->set_position(clp_dist, true); }
|
||||
}
|
||||
else if (m_current_tool == ImGui::FragmentFilterIcon) {
|
||||
m_tool_type = ToolType::FRAGMENT_FILTER;
|
||||
m_cursor_type = TriangleSelector::CursorType::POINTER;
|
||||
ImGui::AlignTextToFramePadding();
|
||||
m_imgui->text(m_desc["fragment_area"] + ":");
|
||||
ImGui::SameLine(fragment_area_slider_left);
|
||||
ImGui::PushItemWidth(window_width - fragment_area_slider_left - slider_width_times * slider_icon_width);
|
||||
std::string format_str = std::string("%.2f") + I18N::translate_utf8("", "Triangle patch area threshold,""triangle patch will be merged to neighbor if its area is less than threshold");
|
||||
m_imgui->bbl_slider_float_style("##fragment_area", &TriangleSelectorPatch::fragment_area, TriangleSelectorPatch::FragmentAreaMin, TriangleSelectorPatch::FragmentAreaMax, format_str.data(), 1.0f, true);
|
||||
ImGui::SameLine(window_width - slider_icon_width);
|
||||
ImGui::PushItemWidth(1.5 * slider_icon_width);
|
||||
ImGui::BBLDragFloat("##fragment_area_input", &TriangleSelectorPatch::fragment_area, 0.05f, 0.0f, 0.0f, "%.2f");
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(6.0f, 10.0f));
|
||||
|
||||
@@ -85,7 +85,7 @@ size_t GLGizmosManager::get_gizmo_idx_from_mouse(const Vec2d& mouse_pos) const
|
||||
//if ((border <= (float)mouse_pos(0) && ((float)mouse_pos(0) <= border + icons_size))) {
|
||||
if (((top_y + border) <= (float)mouse_pos(1)) && ((float)mouse_pos(1) <= (top_y + border + icons_size))) {
|
||||
// which icon is it on?
|
||||
size_t from_left = (size_t)((float)mouse_pos(0) - top_x) / stride_x;
|
||||
int from_left = (float) mouse_pos(0) - top_x < 0 ? -1 : (int) ((float) mouse_pos(0) - top_x) / stride_x;
|
||||
if (from_left < 0)
|
||||
return Undefined;
|
||||
// is it really on the icon or already past the border?
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
#define MAX_NUM 9999.99
|
||||
#define MAX_SIZE "9999.99"
|
||||
|
||||
namespace Slic3r
|
||||
{
|
||||
namespace GUI
|
||||
@@ -25,6 +28,8 @@ namespace GUI
|
||||
|
||||
const double GizmoObjectManipulation::in_to_mm = 25.4;
|
||||
const double GizmoObjectManipulation::mm_to_in = 0.0393700787;
|
||||
const double GizmoObjectManipulation::oz_to_g = 28.34952;
|
||||
const double GizmoObjectManipulation::g_to_oz = 0.035274;
|
||||
|
||||
// Helper function to be used by drop to bed button. Returns lowest point of this
|
||||
// volume in world coordinate system.
|
||||
@@ -576,9 +581,10 @@ void GizmoObjectManipulation::do_render_move_window(ImGuiWrapper *imgui_wrapper,
|
||||
else
|
||||
original_position = this->m_new_position;
|
||||
Vec3d display_position = m_buffered_position;
|
||||
|
||||
// Rotation
|
||||
Vec3d rotation = this->m_buffered_rotation;
|
||||
float unit_size = max_unit_size(2, display_position, display_position, "move") + space_size;;
|
||||
float unit_size = imgui_wrapper->calc_text_size(MAX_SIZE).x + space_size;
|
||||
int index = 1;
|
||||
int index_unit = 1;
|
||||
|
||||
@@ -611,6 +617,12 @@ void GizmoObjectManipulation::do_render_move_window(ImGuiWrapper *imgui_wrapper,
|
||||
ImGui::BBLInputDouble(label_values[0][2], &display_position[2], 0.0f, 0.0f, "%.2f");
|
||||
ImGui::SameLine(caption_max + (++index_unit) * unit_size + (++index) * space_size);
|
||||
imgui_wrapper->text(this->m_new_unit_string);
|
||||
|
||||
for (int i = 0;i<display_position.size();i++)
|
||||
{
|
||||
if (display_position[i] > MAX_NUM)display_position[i] = MAX_NUM;
|
||||
}
|
||||
|
||||
m_buffered_position = display_position;
|
||||
update(current_active_id, "position", original_position, m_buffered_position);
|
||||
// the init position values are not zero, won't add reset button
|
||||
@@ -671,7 +683,7 @@ void GizmoObjectManipulation::do_render_rotate_window(ImGuiWrapper *imgui_wrappe
|
||||
};
|
||||
|
||||
float space_size = imgui_wrapper->get_style_scaling() * 8;
|
||||
float position_size = imgui_wrapper->calc_text_size(_L("Position")).x + space_size;
|
||||
float position_size = imgui_wrapper->calc_text_size(_L("Rotation")).x + space_size;
|
||||
float World_size = imgui_wrapper->calc_text_size(_L("World coordinates")).x + space_size;
|
||||
float caption_max = std::max(position_size, World_size) + 2 * space_size;
|
||||
float end_text_size = imgui_wrapper->calc_text_size(this->m_new_unit_string).x;
|
||||
@@ -685,7 +697,8 @@ void GizmoObjectManipulation::do_render_rotate_window(ImGuiWrapper *imgui_wrappe
|
||||
Vec3d display_position = m_buffered_position;
|
||||
// Rotation
|
||||
Vec3d rotation = this->m_buffered_rotation;
|
||||
float unit_size = max_unit_size(2, rotation, rotation, "rotate") + space_size * 2;
|
||||
|
||||
float unit_size = imgui_wrapper->calc_text_size(MAX_SIZE).x + space_size;
|
||||
int index = 1;
|
||||
int index_unit = 1;
|
||||
|
||||
@@ -792,7 +805,9 @@ void GizmoObjectManipulation::do_render_scale_input_window(ImGuiWrapper* imgui_w
|
||||
};
|
||||
|
||||
float space_size = imgui_wrapper->get_style_scaling() * 8;
|
||||
float caption_max = imgui_wrapper->calc_text_size(_L("Position:")).x + space_size;
|
||||
float scale_size = imgui_wrapper->calc_text_size(_L("Scale")).x + space_size;
|
||||
float size_len = imgui_wrapper->calc_text_size(_L("Size")).x + space_size;
|
||||
float caption_max = std::max(scale_size, size_len) + 2 * space_size;
|
||||
float end_text_size = imgui_wrapper->calc_text_size(this->m_new_unit_string).x;
|
||||
ImGui::AlignTextToFramePadding();
|
||||
unsigned int current_active_id = ImGui::GetActiveID();
|
||||
@@ -802,12 +817,12 @@ void GizmoObjectManipulation::do_render_scale_input_window(ImGuiWrapper* imgui_w
|
||||
|
||||
Vec3d display_position = m_buffered_position;
|
||||
|
||||
float unit_size = max_unit_size(2, scale, display_size, "scale") + space_size;
|
||||
float unit_size = imgui_wrapper->calc_text_size(MAX_SIZE).x + space_size;
|
||||
bool imperial_units = this->m_imperial_units;
|
||||
|
||||
int index = 2;
|
||||
int index_unit = 1;
|
||||
|
||||
|
||||
ImGui::PushItemWidth(caption_max);
|
||||
ImGui::Dummy(ImVec2(caption_max, -1));
|
||||
//imgui_wrapper->text(_L(" "));
|
||||
@@ -839,8 +854,6 @@ void GizmoObjectManipulation::do_render_scale_input_window(ImGuiWrapper* imgui_w
|
||||
ImGui::BBLInputDouble(label_scale_values[0][2], &scale[2], 0.0f, 0.0f, "%.2f");
|
||||
ImGui::SameLine(caption_max + (++index_unit) *unit_size + (++index) * space_size);
|
||||
imgui_wrapper->text(_L("%"));
|
||||
m_buffered_scale = scale;
|
||||
|
||||
|
||||
if (m_show_clear_scale) {
|
||||
ImGui::SameLine(caption_max + 3 * unit_size + 4 * space_size + end_text_size);
|
||||
@@ -851,7 +864,6 @@ void GizmoObjectManipulation::do_render_scale_input_window(ImGuiWrapper* imgui_w
|
||||
ImGui::InvisibleButton("", ImVec2(ImGui::GetFontSize(), ImGui::GetFontSize()));
|
||||
}
|
||||
|
||||
|
||||
//Size
|
||||
Vec3d original_size;
|
||||
if (this->m_imperial_units)
|
||||
@@ -875,6 +887,12 @@ void GizmoObjectManipulation::do_render_scale_input_window(ImGuiWrapper* imgui_w
|
||||
ImGui::BBLInputDouble(label_scale_values[1][2], &display_size[2], 0.0f, 0.0f, "%.2f");
|
||||
ImGui::SameLine(caption_max + (++index_unit) *unit_size + (++index) * space_size);
|
||||
imgui_wrapper->text(this->m_new_unit_string);
|
||||
|
||||
for (int i = 0;i<display_size.size();i++)
|
||||
{
|
||||
if (display_size[i] > MAX_NUM || scale[i]> MAX_NUM)display_size[i] = MAX_NUM;
|
||||
}
|
||||
m_buffered_scale = scale;
|
||||
m_buffered_size = display_size;
|
||||
int size_sel = update(current_active_id, "size", original_size, m_buffered_size);
|
||||
ImGui::PopStyleVar(1);
|
||||
|
||||
@@ -19,6 +19,8 @@ class GizmoObjectManipulation
|
||||
public:
|
||||
static const double in_to_mm;
|
||||
static const double mm_to_in;
|
||||
static const double g_to_oz;
|
||||
static const double oz_to_g;
|
||||
|
||||
struct Cache
|
||||
{
|
||||
|
||||
+41
-102
@@ -451,6 +451,8 @@ bool IMSlider::init_texture()
|
||||
result &= IMTexture::load_from_svg_file(Slic3r::resources_dir() + "/images/one_layer_off.svg", 28, 28, m_one_layer_off_id);
|
||||
result &= IMTexture::load_from_svg_file(Slic3r::resources_dir() + "/images/one_layer_off_hover.svg", 28, 28, m_one_layer_off_hover_id);
|
||||
result &= IMTexture::load_from_svg_file(Slic3r::resources_dir() + "/images/one_layer_arrow.svg", 28, 28, m_one_layer_arrow_id);
|
||||
result &= IMTexture::load_from_svg_file(Slic3r::resources_dir() + "/images/im_gcode_pause.svg", 14, 14, m_pause_icon_id);
|
||||
result &= IMTexture::load_from_svg_file(Slic3r::resources_dir() + "/images/im_slider_delete.svg", 14, 14, m_delete_icon_id);
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -859,11 +861,13 @@ void IMSlider::draw_ticks(const ImRect& slideable_region) {
|
||||
if (m_ticks.empty())
|
||||
return;
|
||||
|
||||
ImGuiContext &context = *GImGui;
|
||||
|
||||
ImVec2 tick_box = ImVec2(46.0f, 16.0f) * m_scale;
|
||||
ImVec2 tick_offset = ImVec2(19.0f, 11.0f) * m_scale;
|
||||
float tick_width = 1.0f * m_scale;
|
||||
ImVec2 icon_offset = ImVec2(13.0f, 7.0f) * m_scale;
|
||||
ImVec2 icon_size = ImVec2(16.0f, 16.0f) * m_scale;
|
||||
ImVec2 icon_size = ImVec2(14.0f, 14.0f) * m_scale;
|
||||
|
||||
const ImU32 tick_clr = IM_COL32(144, 144, 144, 255);
|
||||
const ImU32 tick_hover_box_clr = IM_COL32(219, 253, 231, 255);
|
||||
@@ -876,12 +880,10 @@ void IMSlider::draw_ticks(const ImRect& slideable_region) {
|
||||
return get_pos_from_value(v_min, v_max, tick, slideable_region);
|
||||
};
|
||||
|
||||
|
||||
float tick_pos;
|
||||
std::set<TickCode>::const_iterator tick_it = m_ticks.ticks.begin();
|
||||
while (tick_it != m_ticks.ticks.end())
|
||||
{
|
||||
tick_pos = get_tick_pos(tick_it->tick);
|
||||
float tick_pos = get_tick_pos(tick_it->tick);
|
||||
|
||||
//draw tick hover box when hovered
|
||||
ImRect tick_hover_box = ImRect(slideable_region.GetCenter().x - tick_box.x / 2, tick_pos - tick_box.y / 2, slideable_region.GetCenter().x + tick_box.x / 2,
|
||||
@@ -890,8 +892,10 @@ void IMSlider::draw_ticks(const ImRect& slideable_region) {
|
||||
if (ImGui::IsMouseHoveringRect(tick_hover_box.Min, tick_hover_box.Max))
|
||||
{
|
||||
ImGui::RenderFrame(tick_hover_box.Min, tick_hover_box.Max, tick_hover_box_clr, false);
|
||||
m_tick_value = tick_it->tick;
|
||||
m_tick_rect = ImVec4(tick_hover_box.Min.x, tick_hover_box.Min.y, tick_hover_box.Max.x, tick_hover_box.Max.y);
|
||||
if (context.IO.MouseClicked[0]) {
|
||||
m_tick_value = tick_it->tick;
|
||||
m_tick_rect = ImVec4(tick_hover_box.Min.x, tick_hover_box.Min.y, tick_hover_box.Max.x, tick_hover_box.Max.y);
|
||||
}
|
||||
}
|
||||
++tick_it;
|
||||
}
|
||||
@@ -899,7 +903,7 @@ void IMSlider::draw_ticks(const ImRect& slideable_region) {
|
||||
tick_it = m_ticks.ticks.begin();
|
||||
while (tick_it != m_ticks.ticks.end())
|
||||
{
|
||||
tick_pos = get_tick_pos(tick_it->tick);
|
||||
float tick_pos = get_tick_pos(tick_it->tick);
|
||||
|
||||
//draw ticks
|
||||
ImRect tick_left = ImRect(slideable_region.GetCenter().x - tick_offset.x, tick_pos - tick_width, slideable_region.GetCenter().x - tick_offset.y, tick_pos);
|
||||
@@ -908,17 +912,36 @@ void IMSlider::draw_ticks(const ImRect& slideable_region) {
|
||||
ImGui::RenderFrame(tick_right.Min, tick_right.Max, tick_clr, false);
|
||||
|
||||
//draw pause icon
|
||||
ImGui::PushID(tick_it->tick);
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
|
||||
if (tick_it->type == PausePrint) {
|
||||
std::wstring pause_icon_name = ImGui::GcodePauseIcon + boost::nowide::widen(std::string(""));
|
||||
button_with_pos(into_u8(pause_icon_name).c_str(), icon_size, ImVec2(slideable_region.GetCenter().x + icon_offset.x, tick_pos - icon_offset.y));
|
||||
ImTextureID pause_icon_id = m_pause_icon_id;
|
||||
ImVec2 icon_pos = ImVec2(slideable_region.GetCenter().x + icon_offset.x, tick_pos - icon_offset.y);
|
||||
button_with_pos(pause_icon_id, icon_size, icon_pos);
|
||||
if (ImGui::IsMouseHoveringRect(icon_pos, icon_pos + icon_size)) {
|
||||
if(context.IO.MouseClicked[0])
|
||||
int a = 0;
|
||||
}
|
||||
}
|
||||
ImGui::PopStyleColor(1);
|
||||
ImGui::PopID();
|
||||
|
||||
++tick_it;
|
||||
}
|
||||
|
||||
tick_it = GetSelection() == ssHigher ? m_ticks.ticks.find(TickCode{this->GetHigherValue()}) :
|
||||
GetSelection() == ssLower ? m_ticks.ticks.find(TickCode{this->GetLowerValue()}) :
|
||||
m_ticks.ticks.end();
|
||||
if (tick_it != m_ticks.ticks.end()) {
|
||||
// draw delete icon
|
||||
ImTextureID delete_icon_id = m_delete_icon_id;
|
||||
ImVec2 icon_pos = ImVec2(slideable_region.GetCenter().x + icon_offset.x, get_tick_pos(tick_it->tick) - icon_offset.y);
|
||||
button_with_pos(m_delete_icon_id, icon_size, icon_pos);
|
||||
if (ImGui::IsMouseHoveringRect(icon_pos, icon_pos + icon_size)) {
|
||||
if (context.IO.MouseClicked[0]) {
|
||||
// delete tick
|
||||
Type type = tick_it->type;
|
||||
m_ticks.ticks.erase(tick_it);
|
||||
post_ticks_changed_event(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool IMSlider::vertical_slider(const char* str_id, int* higher_value, int* lower_value, std::string& higher_label, std::string& lower_label,int v_min, int v_max, const ImVec2& pos,const ImVec2& size, SelectedSlider& selection, bool one_layer_flag, float scale)
|
||||
@@ -989,8 +1012,7 @@ bool IMSlider::vertical_slider(const char* str_id, int* higher_value, int* lower
|
||||
|
||||
ImRect one_handle = ImRect(higher_handle.Min - ImVec2(one_handle_offset, 0), higher_handle.Max - ImVec2(one_handle_offset, 0));
|
||||
|
||||
static bool become_del_handle = false;
|
||||
static bool pressed_in_del = false;
|
||||
//static bool become_del_handle = false;
|
||||
bool value_changed = false;
|
||||
if (!one_layer_flag)
|
||||
{
|
||||
@@ -999,14 +1021,10 @@ bool IMSlider::vertical_slider(const char* str_id, int* higher_value, int* lower
|
||||
if (ImGui::ItemHoverable(higher_handle, id) && context.IO.MouseClicked[0]) {
|
||||
selection = ssHigher;
|
||||
h_selected = true;
|
||||
m_tick_value = -1;
|
||||
m_tick_rect = ImVec4();
|
||||
}
|
||||
if (ImGui::ItemHoverable(lower_handle, id) && context.IO.MouseClicked[0]) {
|
||||
selection = ssLower;
|
||||
h_selected = false;
|
||||
m_tick_value = -1;
|
||||
m_tick_rect = ImVec4();
|
||||
}
|
||||
|
||||
// update handle position and value
|
||||
@@ -1015,31 +1033,11 @@ bool IMSlider::vertical_slider(const char* str_id, int* higher_value, int* lower
|
||||
value_changed = slider_behavior(id, higher_slideable_region, v_min, v_max,
|
||||
higher_value, &higher_handle, ImGuiSliderFlags_Vertical,
|
||||
m_tick_value, m_tick_rect);
|
||||
|
||||
auto it = m_ticks.ticks.find(TickCode{ *higher_value });
|
||||
if (it != m_ticks.ticks.end() && check_ticks_changed_event(it->type))
|
||||
{
|
||||
become_del_handle = true;
|
||||
}
|
||||
else {
|
||||
become_del_handle = false;
|
||||
pressed_in_del = false;
|
||||
}
|
||||
}
|
||||
if (!h_selected) {
|
||||
value_changed = slider_behavior(id, lower_slideable_region, v_min, v_max,
|
||||
lower_value, &lower_handle, ImGuiSliderFlags_Vertical,
|
||||
m_tick_value, m_tick_rect);
|
||||
|
||||
auto it = m_ticks.ticks.find(TickCode{ *lower_value });
|
||||
if (it != m_ticks.ticks.end() && check_ticks_changed_event(it->type))
|
||||
{
|
||||
become_del_handle = true;
|
||||
}
|
||||
else {
|
||||
become_del_handle = false;
|
||||
pressed_in_del = false;
|
||||
}
|
||||
}
|
||||
|
||||
ImVec2 higher_handle_center = higher_handle.GetCenter();
|
||||
@@ -1095,37 +1093,6 @@ bool IMSlider::vertical_slider(const char* str_id, int* higher_value, int* lower
|
||||
window->DrawList->AddLine(lower_handle_center + ImVec2(0.0f, -line_offset), lower_handle_center + ImVec2(0.0f, line_offset), white_bg, line_width);
|
||||
}
|
||||
|
||||
if (become_del_handle) {
|
||||
|
||||
if (context.IO.MouseDown[0] &&
|
||||
(ImGui::ItemHoverable(h_selected ? higher_handle : lower_handle, id)))
|
||||
{
|
||||
pressed_in_del = true;
|
||||
}
|
||||
if (pressed_in_del && context.IO.MouseReleased[0] && ImGui::ItemHoverable(h_selected ? higher_handle : lower_handle, id)) {
|
||||
pressed_in_del = false;
|
||||
//delete tick
|
||||
auto it = m_ticks.ticks.find(TickCode{ h_selected ? *higher_value : *lower_value });
|
||||
if (it != m_ticks.ticks.end() && check_ticks_changed_event(it->type))
|
||||
{
|
||||
Type type = it->type;
|
||||
m_ticks.ticks.erase(it);
|
||||
post_ticks_changed_event(type);
|
||||
m_tick_value = -1;
|
||||
m_tick_rect = ImVec4();
|
||||
}
|
||||
}
|
||||
|
||||
if (h_selected) {
|
||||
window->DrawList->AddCircleFilled(higher_handle_center, handle_radius - handle_border, delete_btn_clr);
|
||||
window->DrawList->AddLine(higher_handle_center + ImVec2(-line_offset, 0.0f), higher_handle_center + ImVec2(line_offset, 0.0f), white_bg, line_width);
|
||||
}
|
||||
if (!h_selected) {
|
||||
window->DrawList->AddCircleFilled(lower_handle_center, handle_radius - handle_border, delete_btn_clr);
|
||||
window->DrawList->AddLine(lower_handle_center + ImVec2(-line_offset, 0.0f), lower_handle_center + ImVec2(line_offset, 0.0f), white_bg, line_width);
|
||||
}
|
||||
}
|
||||
|
||||
// draw higher label
|
||||
auto text_utf8 = into_u8(higher_label);
|
||||
text_content_size = ImGui::CalcTextSize(text_utf8.c_str());
|
||||
@@ -1157,15 +1124,7 @@ bool IMSlider::vertical_slider(const char* str_id, int* higher_value, int* lower
|
||||
value_changed = slider_behavior(id, one_slideable_region, v_min, v_max,
|
||||
higher_value, &one_handle, ImGuiSliderFlags_Vertical,
|
||||
m_tick_value, m_tick_rect);
|
||||
auto it = m_ticks.ticks.find(TickCode{ *higher_value });
|
||||
if (it != m_ticks.ticks.end() && check_ticks_changed_event(it->type))
|
||||
{
|
||||
become_del_handle = true;
|
||||
}
|
||||
else {
|
||||
become_del_handle = false;
|
||||
pressed_in_del;
|
||||
}
|
||||
|
||||
ImVec2 handle_center = one_handle.GetCenter();
|
||||
|
||||
// judge whether to open menu
|
||||
@@ -1190,28 +1149,6 @@ bool IMSlider::vertical_slider(const char* str_id, int* higher_value, int* lower
|
||||
window->DrawList->AddCircleFilled(handle_center, handle_radius - handle_border, handle_clr);
|
||||
window->DrawList->AddLine(handle_center + ImVec2(-line_offset, 0.0f), handle_center + ImVec2(line_offset, 0.0f), white_bg, line_width);
|
||||
window->DrawList->AddLine(handle_center + ImVec2(0.0f, -line_offset), handle_center + ImVec2(0.0f, line_offset), white_bg, line_width);
|
||||
if (become_del_handle) {
|
||||
if (context.IO.MouseDown[0] &&
|
||||
(ImGui::ItemHoverable(one_handle, id)))
|
||||
{
|
||||
pressed_in_del = true;
|
||||
}
|
||||
if (pressed_in_del && context.IO.MouseReleased[0] && ImGui::ItemHoverable(one_handle, id)) {
|
||||
pressed_in_del = false;
|
||||
//delete tick
|
||||
auto it = m_ticks.ticks.find(TickCode{ *higher_value });
|
||||
if (it != m_ticks.ticks.end() && check_ticks_changed_event(it->type))
|
||||
{
|
||||
Type type = it->type;
|
||||
m_ticks.ticks.erase(it);
|
||||
post_ticks_changed_event(type);
|
||||
m_tick_value = -1;
|
||||
m_tick_rect = ImVec4();
|
||||
}
|
||||
}
|
||||
window->DrawList->AddCircleFilled(handle_center, handle_radius - handle_border, delete_btn_clr);
|
||||
window->DrawList->AddLine(handle_center + ImVec2(-line_offset, 0.0f), handle_center + ImVec2(line_offset, 0.0f), white_bg, line_width);
|
||||
}
|
||||
|
||||
// draw label
|
||||
auto text_utf8 = into_u8(higher_label);
|
||||
@@ -1222,6 +1159,7 @@ bool IMSlider::vertical_slider(const char* str_id, int* higher_value, int* lower
|
||||
ImGui::RenderFrame(text_rect.Min, text_rect.Max, white_bg, false, rounding);
|
||||
ImGui::RenderText(text_start + text_padding, higher_label.c_str());
|
||||
}
|
||||
|
||||
return value_changed;
|
||||
}
|
||||
|
||||
@@ -1294,6 +1232,7 @@ bool IMSlider::render(int canvas_width, int canvas_height)
|
||||
|
||||
ImGui::PopStyleVar(3);
|
||||
ImGui::PopStyleColor(2);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -343,6 +343,8 @@ private:
|
||||
void *m_one_layer_arrow_id;
|
||||
void *m_one_layer_off_id;
|
||||
void *m_one_layer_off_hover_id;
|
||||
void *m_pause_icon_id;
|
||||
void *m_delete_icon_id;
|
||||
|
||||
DrawMode m_draw_mode = dmRegular;
|
||||
Mode m_mode = SingleExtruder;
|
||||
|
||||
@@ -64,8 +64,7 @@ static const std::map<const wchar_t, std::string> font_icons = {
|
||||
{ImGui::FragmentFilterIcon , "fragment_filter" },
|
||||
{ImGui::FoldButtonIcon , "im_fold" },
|
||||
{ImGui::UnfoldButtonIcon , "im_unfold" },
|
||||
{ImGui::GcodePauseIcon , "im_gcode_pause" },
|
||||
{ImGui::SphereButtonIcon , "toolbar_modifier_sphere" },
|
||||
{ImGui::SphereButtonIcon , "toolbar_modifier_sphere" },
|
||||
|
||||
};
|
||||
static const std::map<const wchar_t, std::string> font_icons_large = {
|
||||
@@ -257,30 +256,37 @@ bool slider_behavior(ImGuiID id, const ImRect& region, const ImS32 v_min, const
|
||||
return value_changed;
|
||||
}
|
||||
|
||||
bool button_with_pos(const char* label, const ImVec2& size, const ImVec2& pos, ImGuiButtonFlags flags/* = 0*/) {
|
||||
bool button_with_pos(ImTextureID user_texture_id, const ImVec2 &size, const ImVec2 &pos, const ImVec2 &uv0, const ImVec2 &uv1, int frame_padding, const ImVec4 &bg_col, const ImVec4 &tint_col, const ImVec2 &margin)
|
||||
{
|
||||
|
||||
ImGuiWindow* window = ImGui::GetCurrentWindow();
|
||||
if (window->SkipItems)
|
||||
return false;
|
||||
ImGuiContext &g = *GImGui;
|
||||
ImGuiWindow * window = g.CurrentWindow;
|
||||
if (window->SkipItems) return false;
|
||||
|
||||
ImGuiContext& g = *GImGui;
|
||||
const ImGuiStyle& style = g.Style;
|
||||
const ImGuiID id = window->GetID(label);
|
||||
const ImVec2 label_size = ImGui::CalcTextSize(label, NULL, true);
|
||||
// Default to using texture ID as ID. User can still push string/integer prefixes.
|
||||
ImGui::PushID((void *) (intptr_t) user_texture_id);
|
||||
const ImGuiID id = window->GetID("#image");
|
||||
ImGui::PopID();
|
||||
|
||||
const ImRect bb(pos, pos + size);
|
||||
const ImVec2 padding = (frame_padding >= 0) ? ImVec2((float) frame_padding, (float) frame_padding) : g.Style.FramePadding;
|
||||
|
||||
const ImRect bb(pos, pos + size + padding * 2 + margin * 2);
|
||||
|
||||
bool hovered, held;
|
||||
bool pressed = ImGui::ButtonBehavior(bb, id, &hovered, &held, flags);
|
||||
bool pressed = ImGui::ButtonBehavior(bb, id, &hovered, &held);
|
||||
|
||||
// Render
|
||||
const ImU32 col = ImGui::GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
|
||||
ImGui::RenderNavHighlight(bb, id);
|
||||
ImGui::RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding);
|
||||
|
||||
if (g.LogEnabled)
|
||||
ImGui::LogSetNextTextDecoration("[", "]");
|
||||
ImGui::RenderTextClipped(bb.Min + style.FramePadding, bb.Max - style.FramePadding, label, NULL, &label_size, style.ButtonTextAlign, &bb);
|
||||
const float border_size = g.Style.FrameBorderSize;
|
||||
if (border_size > 0.0f) {
|
||||
window->DrawList->AddRect(bb.Min + ImVec2(1, 1), bb.Max + ImVec2(1, 1), col, g.Style.FrameRounding, 0, border_size);
|
||||
window->DrawList->AddRect(bb.Min, bb.Max, col, g.Style.FrameRounding, 0, border_size);
|
||||
}
|
||||
|
||||
if (bg_col.w > 0.0f) window->DrawList->AddRectFilled(bb.Min + padding, bb.Max - padding, ImGui::GetColorU32(bg_col));
|
||||
window->DrawList->AddImage(user_texture_id, bb.Min + padding + margin, bb.Max - padding - margin, uv0, uv1, ImGui::GetColorU32(tint_col));
|
||||
|
||||
return pressed;
|
||||
}
|
||||
|
||||
@@ -28,7 +28,15 @@ namespace GUI {
|
||||
bool get_data_from_svg(const std::string &filename, unsigned int max_size_px, ThumbnailData &thumbnail_data);
|
||||
|
||||
bool slider_behavior(ImGuiID id, const ImRect& region, const ImS32 v_min, const ImS32 v_max, ImS32* out_value, ImRect* out_handle, ImGuiSliderFlags flags = 0, const int fixed_value = -1, const ImVec4& fixed_rect = ImVec4());
|
||||
bool button_with_pos(const char* label, const ImVec2& size, const ImVec2& pos, ImGuiButtonFlags flags = 0);
|
||||
bool button_with_pos(ImTextureID user_texture_id,
|
||||
const ImVec2 &size,
|
||||
const ImVec2 &pos,
|
||||
const ImVec2 &uv0 = ImVec2(0, 0),
|
||||
const ImVec2 &uv1 = ImVec2(1, 1),
|
||||
int frame_padding = -1,
|
||||
const ImVec4 &bg_col = ImVec4(0, 0, 0, 0),
|
||||
const ImVec4 &tint_col = ImVec4(1, 1, 1, 1),
|
||||
const ImVec2 &margin = ImVec2(0, 0));
|
||||
bool menu_item_with_icon(const char* label, const char* shortcut, ImU32 icon_color, bool selected, bool enabled = true);
|
||||
|
||||
|
||||
|
||||
@@ -99,9 +99,11 @@ void BindJob::process()
|
||||
} else if (stage == BBL::BindJobStage::LoginStageFinished) {
|
||||
curr_percent = 100;
|
||||
msg = _L("Logging in");
|
||||
} else {
|
||||
msg = _L("Logging in");
|
||||
}
|
||||
if (code != 0) {
|
||||
msg = login_failed_str + wxString::Format("(code=%d,info=%s)", code, info);
|
||||
msg = _L("Login failed") + wxString::Format("(code=%d,info=%s)", code, info);
|
||||
}
|
||||
update_status(curr_percent, msg);
|
||||
}
|
||||
|
||||
@@ -51,6 +51,49 @@ void PrintJob::on_success(std::function<void()> success)
|
||||
m_success_fun = success;
|
||||
}
|
||||
|
||||
wxString PrintJob::get_http_error_msg(unsigned int status, std::string body)
|
||||
{
|
||||
int code = 0;
|
||||
std::string error;
|
||||
std::string message;
|
||||
wxString result;
|
||||
if (status >= 400 && status < 500)
|
||||
try {
|
||||
json j = json::parse(body);
|
||||
if (j.contains("code")) {
|
||||
if (!j["code"].is_null())
|
||||
code = j["code"].get<int>();
|
||||
}
|
||||
if (j.contains("error")) {
|
||||
if (!j["error"].is_null())
|
||||
error = j["error"].get<std::string>();
|
||||
}
|
||||
if (j.contains("message")) {
|
||||
if (!j["message"].is_null())
|
||||
message = j["message"].get<std::string>();
|
||||
}
|
||||
switch (status) {
|
||||
;
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
;
|
||||
}
|
||||
else if (status == 503) {
|
||||
return _L("Service Unavailable");
|
||||
}
|
||||
else {
|
||||
wxString unkown_text = _L("Unkown Error.");
|
||||
unkown_text += wxString::Format("status=%u, body=%s", status, body);
|
||||
return unkown_text;
|
||||
}
|
||||
|
||||
BOOST_LOG_TRIVIAL(error) << "http_error: status=" << status << ", code=" << code << ", error=" << error;
|
||||
|
||||
result = wxString::Format("code=%u, error=%s", code, from_u8(error));
|
||||
return result;
|
||||
}
|
||||
|
||||
void PrintJob::process()
|
||||
{
|
||||
/* display info */
|
||||
@@ -114,8 +157,10 @@ void PrintJob::process()
|
||||
params.dev_ip = m_dev_ip;
|
||||
params.username = "bblp";
|
||||
params.password = m_access_code;
|
||||
wxString error_text;
|
||||
wxString msg_text;
|
||||
|
||||
auto update_fn = [this, &msg, &curr_percent](int stage, int code, std::string info) {
|
||||
auto update_fn = [this, &msg, &curr_percent, &error_text](int stage, int code, std::string info) {
|
||||
if (stage == BBL::SendingPrintJobStage::PrintingStageCreate) {
|
||||
if (this->connection_type == "lan") {
|
||||
msg = _L("Sending print job over LAN");
|
||||
@@ -157,7 +202,7 @@ void PrintJob::process()
|
||||
}
|
||||
else if (stage == BBL::SendingPrintJobStage::PrintingStageFinished) {
|
||||
curr_percent = 100;
|
||||
msg = wxString::Format(_L("Successfully sent.Will automatically jump to the device page in %s s"), info);
|
||||
msg = wxString::Format(_L("Successfully sent. Will automatically jump to the device page in %s s"), info);
|
||||
} else {
|
||||
if (this->connection_type == "lan") {
|
||||
msg = _L("Sending print job over LAN");
|
||||
@@ -165,6 +210,10 @@ void PrintJob::process()
|
||||
msg = _L("Sending print job through cloud service");
|
||||
}
|
||||
}
|
||||
if (code != 0) {
|
||||
error_text = this->get_http_error_msg(code, info);
|
||||
msg += wxString::Format("[%s]", error_text);
|
||||
}
|
||||
this->update_status(curr_percent, msg);
|
||||
};
|
||||
|
||||
@@ -193,19 +242,6 @@ void PrintJob::process()
|
||||
BOOST_LOG_TRIVIAL(info) << "print_job: send with cloud";
|
||||
this->update_status(curr_percent, _L("Sending print job through cloud service"));
|
||||
result = m_agent->start_print(params, update_fn, cancel_fn);
|
||||
if (result < 0) {
|
||||
if (!params.password.empty() && !params.dev_ip.empty()) {
|
||||
//try to send with local only
|
||||
if (this->has_sdcard) {
|
||||
this->update_status(curr_percent, _L("Sending print job over LAN"));
|
||||
result = m_agent->start_local_print(params, update_fn, cancel_fn);
|
||||
} else {
|
||||
this->update_status(curr_percent, _L("Failed to connect to the cloud server connection. Please insert an SD card and resend the print job, which will transfer the print file via LAN. "));
|
||||
BOOST_LOG_TRIVIAL(error) << "print_job: failed, need sdcard";
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (this->has_sdcard) {
|
||||
@@ -224,26 +260,29 @@ void PrintJob::process()
|
||||
|
||||
if (result < 0) {
|
||||
if (result == BAMBU_NETWORK_ERR_FTP_LOGIN_DENIED) {
|
||||
update_status(curr_percent, upload_failed_str);
|
||||
msg_text = upload_failed_str;
|
||||
} if (result == BAMBU_NETWORK_ERR_FILE_NOT_EXIST) {
|
||||
update_status(curr_percent, file_is_not_exists_str);
|
||||
msg_text = file_is_not_exists_str;
|
||||
} else if (result == BAMBU_NETWORK_ERR_FILE_OVER_SIZE) {
|
||||
update_status(curr_percent, file_over_size_str);
|
||||
msg_text = file_over_size_str;
|
||||
} else if (result == BAMBU_NETWORK_ERR_CHECK_MD5_FAILED) {
|
||||
update_status(curr_percent, failed_in_cloud_service_str);
|
||||
msg_text = failed_in_cloud_service_str;
|
||||
} else if (result == BAMBU_NETWORK_ERR_INVALID_PARAMS) {
|
||||
update_status(curr_percent, upload_failed_str);
|
||||
msg_text = upload_failed_str;
|
||||
} else if (result == BAMBU_NETWORK_ERR_CANCELED) {
|
||||
update_status(curr_percent, print_canceled_str);
|
||||
msg_text = print_canceled_str;
|
||||
} else if (result == BAMBU_NETWORK_ERR_TIMEOUT) {
|
||||
update_status(curr_percent, timeout_to_upload_str);
|
||||
msg_text = timeout_to_upload_str;
|
||||
} else if (result == BAMBU_NETWORK_ERR_INVALID_RESULT) {
|
||||
update_status(curr_percent, upload_failed_str);
|
||||
msg_text = upload_failed_str;
|
||||
} else if (result == BAMBU_NETWORK_ERR_FTP_UPLOAD_FAILED) {
|
||||
update_status(curr_percent, upload_failed_str);
|
||||
msg_text = upload_failed_str;
|
||||
} else {
|
||||
update_status(curr_percent, failed_in_cloud_service_str);
|
||||
}
|
||||
if (!error_text.IsEmpty())
|
||||
msg_text += wxString::Format("[%s]", error_text);
|
||||
update_status(curr_percent, msg_text);
|
||||
BOOST_LOG_TRIVIAL(error) << "print_job: failed, result = " << result;
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(error) << "print_job: send ok.";
|
||||
|
||||
@@ -70,6 +70,7 @@ public:
|
||||
void set_print_job_finished_event(int event_id) { m_print_job_completed_id = event_id; }
|
||||
|
||||
void on_success(std::function<void()> success);
|
||||
wxString get_http_error_msg(unsigned int status, std::string body);
|
||||
void process() override;
|
||||
void finalize() override;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
#include "UpgradeNetworkJob.hpp"
|
||||
|
||||
#include "slic3r/GUI/GUI.hpp"
|
||||
#include "slic3r/GUI/GUI_App.hpp"
|
||||
#include "slic3r/Utils/Http.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
wxDEFINE_EVENT(EVT_UPGRADE_UPDATE_MESSAGE, wxCommandEvent);
|
||||
wxDEFINE_EVENT(EVT_UPGRADE_NETWORK_SUCCESS, wxCommandEvent);
|
||||
wxDEFINE_EVENT(EVT_UPGRADE_NETWORK_FAILED, wxCommandEvent);
|
||||
|
||||
|
||||
UpgradeNetworkJob::UpgradeNetworkJob(std::shared_ptr<ProgressIndicator> pri)
|
||||
: Job{std::move(pri)}
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
void UpgradeNetworkJob::on_exception(const std::exception_ptr &eptr)
|
||||
{
|
||||
try {
|
||||
if (eptr)
|
||||
std::rethrow_exception(eptr);
|
||||
} catch (std::exception &e) {
|
||||
UpgradeNetworkJob::on_exception(eptr);
|
||||
}
|
||||
}
|
||||
|
||||
void UpgradeNetworkJob::on_success(std::function<void()> success)
|
||||
{
|
||||
m_success_fun = success;
|
||||
}
|
||||
|
||||
void UpgradeNetworkJob::update_status(int st, const wxString &msg)
|
||||
{
|
||||
GUI::Job::update_status(st, msg);
|
||||
wxCommandEvent event(EVT_UPGRADE_UPDATE_MESSAGE);
|
||||
event.SetString(msg);
|
||||
event.SetEventObject(m_event_handle);
|
||||
wxPostEvent(m_event_handle, event);
|
||||
}
|
||||
|
||||
void UpgradeNetworkJob::process()
|
||||
{
|
||||
// downloading
|
||||
int result = 0;
|
||||
|
||||
AppConfig* app_config = wxGetApp().app_config;
|
||||
if (!app_config)
|
||||
return;
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << "[download_plugin]: enter";
|
||||
|
||||
// get temp path
|
||||
fs::path target_file_path = (fs::temp_directory_path() / "network_plugin.zip");
|
||||
fs::path tmp_path = target_file_path;
|
||||
auto path_str = tmp_path.string() + wxString::Format(".%d%s", get_current_pid(), ".tmp").ToStdString();
|
||||
tmp_path = fs::path(path_str);
|
||||
|
||||
auto cancel_fn = [this]() {
|
||||
return was_canceled();
|
||||
};
|
||||
int curr_percent = 0;
|
||||
result = wxGetApp().download_plugin(
|
||||
[this, &curr_percent](int state, int percent, bool &cancel) {
|
||||
if (state == InstallStatusNormal) {
|
||||
update_status(percent, _L("Downloading"));
|
||||
} else if (state == InstallStatusDownloadFailed) {
|
||||
update_status(percent, _L("Download failed"));
|
||||
} else {
|
||||
update_status(percent, _L("Downloading"));
|
||||
}
|
||||
curr_percent = percent;
|
||||
}, cancel_fn);
|
||||
|
||||
if (was_canceled()) {
|
||||
update_status(0, _L("Cancelled"));
|
||||
wxCommandEvent event(wxEVT_CLOSE_WINDOW);
|
||||
event.SetEventObject(m_event_handle);
|
||||
wxPostEvent(m_event_handle, event);
|
||||
return;
|
||||
}
|
||||
|
||||
if (result < 0) {
|
||||
update_status(curr_percent, _L("Download failed"));
|
||||
wxCommandEvent event(EVT_UPGRADE_NETWORK_FAILED);
|
||||
event.SetEventObject(m_event_handle);
|
||||
wxPostEvent(m_event_handle, event);
|
||||
return;
|
||||
}
|
||||
|
||||
result = wxGetApp().install_plugin([this](int state, int percent, bool&cancel) {
|
||||
if (state == InstallStatusInstallCompleted) {
|
||||
update_status(percent, _L("Finish"));
|
||||
} else {
|
||||
update_status(percent, _L("Installing"));
|
||||
}
|
||||
}, cancel_fn);
|
||||
|
||||
if (was_canceled()) {
|
||||
update_status(0, _L("Cancelled"));
|
||||
wxCommandEvent event(wxEVT_CLOSE_WINDOW);
|
||||
event.SetEventObject(m_event_handle);
|
||||
wxPostEvent(m_event_handle, event);
|
||||
return;
|
||||
}
|
||||
|
||||
if (result != 0) {
|
||||
update_status(curr_percent, _L("Install failed"));
|
||||
wxCommandEvent event(EVT_UPGRADE_NETWORK_FAILED);
|
||||
event.SetEventObject(m_event_handle);
|
||||
wxPostEvent(m_event_handle, event);
|
||||
return;
|
||||
}
|
||||
|
||||
wxCommandEvent event(EVT_UPGRADE_NETWORK_SUCCESS);
|
||||
event.SetEventObject(m_event_handle);
|
||||
wxPostEvent(m_event_handle, event);
|
||||
return;
|
||||
}
|
||||
|
||||
void UpgradeNetworkJob::finalize()
|
||||
{
|
||||
if (was_canceled()) return;
|
||||
|
||||
Job::finalize();
|
||||
}
|
||||
|
||||
void UpgradeNetworkJob::set_event_handle(wxWindow *hanle)
|
||||
{
|
||||
m_event_handle = hanle;
|
||||
}
|
||||
|
||||
}} // namespace Slic3r::GUI
|
||||
@@ -0,0 +1,56 @@
|
||||
#ifndef __UpgradeNetworkJob_HPP__
|
||||
#define __UpgradeNetworkJob_HPP__
|
||||
|
||||
#include <functional>
|
||||
#include "Job.hpp"
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
enum PluginInstallStatus {
|
||||
InstallStatusNormal = 0,
|
||||
InstallStatusDownloadFailed = 1,
|
||||
InstallStatusDownloadCompleted = 2,
|
||||
InstallStatusUnzipFailed = 3,
|
||||
InstallStatusInstallCompleted = 4,
|
||||
};
|
||||
|
||||
typedef std::function<void(int status, int percent, bool& cancel)> InstallProgressFn;
|
||||
|
||||
class UpgradeNetworkJob : public Job
|
||||
{
|
||||
wxWindow * m_event_handle{nullptr};
|
||||
std::function<void()> m_success_fun{nullptr};
|
||||
bool m_job_finished{ false };
|
||||
int m_print_job_completed_id = 0;
|
||||
|
||||
InstallProgressFn pro_fn { nullptr };
|
||||
|
||||
protected:
|
||||
void on_exception(const std::exception_ptr &) override;
|
||||
public:
|
||||
UpgradeNetworkJob(std::shared_ptr<ProgressIndicator> pri);
|
||||
|
||||
int status_range() const override
|
||||
{
|
||||
return 100;
|
||||
}
|
||||
|
||||
bool is_finished() { return m_job_finished; }
|
||||
|
||||
void on_success(std::function<void()> success);
|
||||
void update_status(int st, const wxString &msg);
|
||||
void process() override;
|
||||
void finalize() override;
|
||||
void set_event_handle(wxWindow* hanle);
|
||||
};
|
||||
|
||||
wxDECLARE_EVENT(EVT_UPGRADE_UPDATE_MESSAGE, wxCommandEvent);
|
||||
wxDECLARE_EVENT(EVT_UPGRADE_NETWORK_SUCCESS, wxCommandEvent);
|
||||
wxDECLARE_EVENT(EVT_UPGRADE_NETWORK_FAILED, wxCommandEvent);
|
||||
|
||||
}} // namespace Slic3r::GUI
|
||||
|
||||
#endif // ARRANGEJOB_HPP
|
||||
@@ -157,7 +157,7 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, BORDERLESS_FRAME_
|
||||
#ifdef __WXOSX__
|
||||
set_miniaturizable(GetHandle());
|
||||
#endif
|
||||
|
||||
|
||||
//reset developer_mode to false and user_mode to comAdvanced
|
||||
wxGetApp().app_config->set_bool("developer_mode", false);
|
||||
if (wxGetApp().app_config->get("user_mode") == "develop") {
|
||||
@@ -178,17 +178,17 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, BORDERLESS_FRAME_
|
||||
// Fonts were created by the DPIFrame constructor for the monitor, on which the window opened.
|
||||
wxGetApp().update_fonts(this);
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
m_topbar = new BBLTopbar(this);
|
||||
#else
|
||||
#ifdef __WINDOWS__
|
||||
m_topbar = new BBLTopbar(this);
|
||||
#else
|
||||
auto panel_topbar = new wxPanel(this, wxID_ANY);
|
||||
panel_topbar->SetBackgroundColour(wxColour(38, 46, 48));
|
||||
auto sizer_tobar = new wxBoxSizer(wxVERTICAL);
|
||||
m_topbar = new BBLTopbar(panel_topbar, this);
|
||||
m_topbar = new BBLTopbar(this);
|
||||
sizer_tobar->Add(m_topbar, 0, wxEXPAND);
|
||||
panel_topbar->SetSizer(sizer_tobar);
|
||||
panel_topbar->Layout();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -326,11 +326,11 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, BORDERLESS_FRAME_
|
||||
// initialize layout
|
||||
m_main_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
wxSizer* sizer = new wxBoxSizer(wxVERTICAL);
|
||||
#ifdef __WINDOWS__
|
||||
#ifdef __WINDOWS__
|
||||
sizer->Add(m_topbar, 0, wxEXPAND);
|
||||
#else
|
||||
#else
|
||||
sizer->Add(panel_topbar, 0, wxEXPAND);
|
||||
#endif // __WINDOWS__
|
||||
#endif // __WINDOWS__
|
||||
|
||||
|
||||
sizer->Add(m_main_sizer, 1, wxEXPAND);
|
||||
@@ -357,14 +357,10 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, BORDERLESS_FRAME_
|
||||
Fit();
|
||||
|
||||
const wxSize min_size = wxGetApp().get_min_size(); //wxSize(76*wxGetApp().em_unit(), 49*wxGetApp().em_unit());
|
||||
#ifdef __APPLE__
|
||||
// Using SetMinSize() on Mac messes up the window position in some cases
|
||||
// cf. https://groups.google.com/forum/#!topic/wx-users/yUKPBBfXWO0
|
||||
SetSize(min_size/*wxSize(760, 490)*/);
|
||||
#else
|
||||
|
||||
SetMinSize(min_size/*wxSize(760, 490)*/);
|
||||
SetSize(wxSize(FromDIP(1200), FromDIP(800)));
|
||||
#endif
|
||||
|
||||
Layout();
|
||||
|
||||
update_title();
|
||||
@@ -747,6 +743,29 @@ void MainFrame::init_tabpanel()
|
||||
m_tabpanel->Hide();
|
||||
m_settings_dialog.set_tabpanel(m_tabpanel);
|
||||
|
||||
m_tabpanel->Bind(wxEVT_NOTEBOOK_PAGE_CHANGING, [this](wxBookCtrlEvent& e) {
|
||||
int old_sel = e.GetOldSelection();
|
||||
int new_sel = e.GetSelection();
|
||||
if (new_sel == tpMonitor) {
|
||||
if (!wxGetApp().getAgent()) {
|
||||
e.Veto();
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("skipped tab switch from %1% to %2%, lack of network plugins")%old_sel %new_sel;
|
||||
if (m_plater) {
|
||||
wxCommandEvent *evt = new wxCommandEvent(EVT_INSTALL_PLUGIN_HINT);
|
||||
wxQueueEvent(m_plater, evt);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (new_sel == tp3DEditor) {
|
||||
if (m_plater && (m_plater->only_gcode_mode() || (m_plater->using_exported_file()))) {
|
||||
e.Veto();
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("skipped tab switch from %1% to %2% in preview mode")%old_sel %new_sel;
|
||||
wxCommandEvent *evt = new wxCommandEvent(EVT_PREVIEW_ONLY_MODE_HINT);
|
||||
wxQueueEvent(m_plater, evt);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
#ifdef __WXMSW__
|
||||
m_tabpanel->Bind(wxEVT_BOOKCTRL_PAGE_CHANGED, [this](wxBookCtrlEvent& e) {
|
||||
#else
|
||||
@@ -758,12 +777,11 @@ void MainFrame::init_tabpanel()
|
||||
//wxString page_text = m_tabpanel->GetPageText(sel);
|
||||
m_last_selected_tab = m_tabpanel->GetSelection();
|
||||
if (panel == m_plater) {
|
||||
if (m_with_3dEditor && (sel == tp3DEditor)) {
|
||||
if (sel == tp3DEditor) {
|
||||
wxPostEvent(m_plater, SimpleEvent(EVT_GLVIEWTOOLBAR_3D));
|
||||
m_param_panel->OnActivate();
|
||||
}
|
||||
else if ((m_with_3dEditor&&(sel == tpPreview))
|
||||
|| (!m_with_3dEditor&&(sel == tp3DEditor))){
|
||||
else if (sel == tpPreview) {
|
||||
wxPostEvent(m_plater, SimpleEvent(EVT_GLVIEWTOOLBAR_PREVIEW));
|
||||
m_param_panel->OnActivate();
|
||||
}
|
||||
@@ -774,7 +792,7 @@ void MainFrame::init_tabpanel()
|
||||
//monitor
|
||||
}
|
||||
|
||||
if (m_with_3dEditor && (sel == tp3DEditor)) {
|
||||
if (sel == tp3DEditor) {
|
||||
m_topbar->EnableUndoRedoItems();
|
||||
}
|
||||
else {
|
||||
@@ -1672,10 +1690,13 @@ void MainFrame::init_menubar_as_editor()
|
||||
append_menu_item(export_menu, wxID_ANY, _L("Export all objects as STL") + dots, _L("Export all objects as STL"),
|
||||
[this](wxCommandEvent&) { if (m_plater) m_plater->export_stl(); }, "menu_export_stl", nullptr,
|
||||
[this](){return can_export_model(); }, this);
|
||||
// BBS export Gcode
|
||||
wxMenuItem* item_export_gcode = append_menu_item(export_menu, wxID_ANY, _L("Export Sliced File") + dots/* + "\tCtrl+G"*/, _L("Export current Sliced file"),
|
||||
// BBS export .gcode.3mf
|
||||
append_menu_item(export_menu, wxID_ANY, _L("Export Sliced File") + dots/* + "\tCtrl+G"*/, _L("Export current Sliced file"),
|
||||
[this](wxCommandEvent&) { if (m_plater) wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_EXPORT_SLICED_FILE)); }, "menu_export_sliced_file", nullptr,
|
||||
[this](){return can_export_gcode(); }, this);
|
||||
append_menu_item(export_menu, wxID_ANY, _L("Export G-code") + dots/* + "\tCtrl+G"*/, _L("Export current plate as G-code"),
|
||||
[this](wxCommandEvent&) { if (m_plater) m_plater->export_gcode(false); }, "menu_export_gcode", nullptr,
|
||||
[this]() {return can_export_gcode(); }, this);
|
||||
|
||||
append_submenu(fileMenu, export_menu, wxID_ANY, _L("Export"), "");
|
||||
|
||||
@@ -1788,20 +1809,20 @@ void MainFrame::init_menubar_as_editor()
|
||||
append_menu_item(editMenu, wxID_ANY, _L("Deselect all") + "\tEsc",
|
||||
_L("Deselects all objects"), [this](wxCommandEvent&) { m_plater->deselect_all(); },
|
||||
"", nullptr, [this](){return can_deselect(); }, this);
|
||||
editMenu->AppendSeparator();
|
||||
append_menu_check_item(editMenu, wxID_ANY, _L("Show Model Mesh(TODO)"),
|
||||
_L("Display triangles of models"), [this](wxCommandEvent& evt) {
|
||||
wxGetApp().app_config->set_bool("show_model_mesh", evt.GetInt() == 1);
|
||||
}, nullptr, [this]() {return can_select(); }, [this]() { return wxGetApp().app_config->get("show_model_mesh").compare("true") == 0; }, this);
|
||||
append_menu_check_item(editMenu, wxID_ANY, _L("Show Model Shadow(TODO)"), _L("Display shadow of objects"),
|
||||
[this](wxCommandEvent& evt) {
|
||||
wxGetApp().app_config->set_bool("show_model_shadow", evt.GetInt() == 1);
|
||||
}, nullptr, [this]() {return can_select(); }, [this]() { return wxGetApp().app_config->get("show_model_shadow").compare("true") == 0; }, this);
|
||||
editMenu->AppendSeparator();
|
||||
append_menu_check_item(editMenu, wxID_ANY, _L("Show Printable Box(TODO)"), _L("Display printable box"),
|
||||
[this](wxCommandEvent& evt) {
|
||||
wxGetApp().app_config->set_bool("show_printable_box", evt.GetInt() == 1);
|
||||
}, nullptr, [this]() {return can_select(); }, [this]() { return wxGetApp().app_config->get("show_printable_box").compare("true") == 0; }, this);
|
||||
//editMenu->AppendSeparator();
|
||||
//append_menu_check_item(editMenu, wxID_ANY, _L("Show Model Mesh(TODO)"),
|
||||
// _L("Display triangles of models"), [this](wxCommandEvent& evt) {
|
||||
// wxGetApp().app_config->set_bool("show_model_mesh", evt.GetInt() == 1);
|
||||
// }, nullptr, [this]() {return can_select(); }, [this]() { return wxGetApp().app_config->get("show_model_mesh").compare("true") == 0; }, this);
|
||||
//append_menu_check_item(editMenu, wxID_ANY, _L("Show Model Shadow(TODO)"), _L("Display shadow of objects"),
|
||||
// [this](wxCommandEvent& evt) {
|
||||
// wxGetApp().app_config->set_bool("show_model_shadow", evt.GetInt() == 1);
|
||||
// }, nullptr, [this]() {return can_select(); }, [this]() { return wxGetApp().app_config->get("show_model_shadow").compare("true") == 0; }, this);
|
||||
//editMenu->AppendSeparator();
|
||||
//append_menu_check_item(editMenu, wxID_ANY, _L("Show Printable Box(TODO)"), _L("Display printable box"),
|
||||
// [this](wxCommandEvent& evt) {
|
||||
// wxGetApp().app_config->set_bool("show_printable_box", evt.GetInt() == 1);
|
||||
// }, nullptr, [this]() {return can_select(); }, [this]() { return wxGetApp().app_config->get("show_printable_box").compare("true") == 0; }, this);
|
||||
}
|
||||
|
||||
// BBS
|
||||
@@ -2234,7 +2255,7 @@ void MainFrame::select_tab(wxPanel* panel)
|
||||
//BBS
|
||||
void MainFrame::jump_to_monitor(std::string dev_id)
|
||||
{
|
||||
m_tabpanel->SetSelection(m_with_3dEditor? tpMonitor:(tpMonitor-1));
|
||||
m_tabpanel->SetSelection(tpMonitor);
|
||||
((MonitorPanel*)m_monitor)->select_machine(dev_id);
|
||||
}
|
||||
|
||||
@@ -2273,42 +2294,10 @@ void MainFrame::select_tab(size_t tab/* = size_t(-1)*/)
|
||||
select(false);
|
||||
}
|
||||
|
||||
void MainFrame::enable_tab(size_t tab, bool enabled)
|
||||
{
|
||||
if (tab != tp3DEditor)
|
||||
//currently only support 3dEditor
|
||||
return;
|
||||
|
||||
if ((enabled && m_with_3dEditor) || (!enabled && !m_with_3dEditor))
|
||||
//already done
|
||||
return;
|
||||
|
||||
Freeze();
|
||||
if (enabled) {
|
||||
int sel = m_tabpanel->GetSelection();
|
||||
m_tabpanel->InsertPage(tab, m_plater, _L("Prepare"), std::string("tab_3d_active"), std::string("tab_3d_active"));
|
||||
if (sel >= tab)
|
||||
m_tabpanel->SetSelection(sel + 1);
|
||||
}
|
||||
else {
|
||||
int sel = m_tabpanel->GetSelection();
|
||||
m_tabpanel->RemovePage(tab);
|
||||
if (sel >= tab)
|
||||
m_tabpanel->SetSelection(sel - 1);
|
||||
}
|
||||
m_with_3dEditor = enabled;
|
||||
m_plater->Show();
|
||||
m_tabpanel->Show();
|
||||
Thaw();
|
||||
}
|
||||
|
||||
void MainFrame::request_select_tab(TabPosition pos)
|
||||
{
|
||||
int position = pos;
|
||||
if ((!m_with_3dEditor)&&(pos >= tpPreview))
|
||||
position = (int)pos -1;
|
||||
wxCommandEvent* evt = new wxCommandEvent(EVT_SELECT_TAB);
|
||||
evt->SetInt(position);
|
||||
evt->SetInt(pos);
|
||||
wxQueueEvent(this, evt);
|
||||
}
|
||||
|
||||
@@ -2487,6 +2476,12 @@ void MainFrame::load_url(wxString url)
|
||||
wxQueueEvent(this, evt);
|
||||
}
|
||||
|
||||
void MainFrame::refresh_plugin_tips()
|
||||
{
|
||||
if (m_webview != nullptr)
|
||||
m_webview->ShowNetpluginTip();
|
||||
}
|
||||
|
||||
void MainFrame::RunScript(wxString js)
|
||||
{
|
||||
if (m_webview != nullptr)
|
||||
@@ -2538,7 +2533,7 @@ void MainFrame::on_select_default_preset(SimpleEvent& evt)
|
||||
{
|
||||
MessageDialog dialog(this,
|
||||
_L("Do you want to synchronize your personal data from Bambu Cloud? \n"
|
||||
"Contains the following information:\n"
|
||||
"It contains the following information:\n"
|
||||
"1. The Process presets\n"
|
||||
"2. The Filament presets\n"
|
||||
"3. The Printer presets\n"),
|
||||
|
||||
@@ -83,7 +83,6 @@ protected:
|
||||
class MainFrame : public DPIFrame
|
||||
{
|
||||
bool m_loaded {false};
|
||||
bool m_with_3dEditor { true };
|
||||
|
||||
wxString m_qs_last_input_file = wxEmptyString;
|
||||
wxString m_qs_last_output_file = wxEmptyString;
|
||||
@@ -278,7 +277,6 @@ public:
|
||||
// Select tab in m_tabpanel
|
||||
// When tab == -1, will be selected last selected tab
|
||||
//BBS: GUI refactor
|
||||
void enable_tab(size_t tab, bool enabled = true);
|
||||
void select_tab(wxPanel* panel);
|
||||
void select_tab(size_t tab = size_t(-1));
|
||||
void request_select_tab(TabPosition pos);
|
||||
@@ -301,6 +299,7 @@ public:
|
||||
|
||||
//BBS
|
||||
void load_url(wxString url);
|
||||
void refresh_plugin_tips();
|
||||
void RunScript(wxString js);
|
||||
|
||||
// BBS. Replace title bar and menu bar with top bar.
|
||||
|
||||
@@ -108,19 +108,23 @@ bool MarkdownTip::ShowTip(wxPoint pos, std::string const &tip, std::string const
|
||||
return false;
|
||||
if (pos.x) {
|
||||
_hide = true;
|
||||
BOOST_LOG_TRIVIAL(info) << "MarkdownTip::ShowTip: hide soon on empty tip.";
|
||||
this->Hide();
|
||||
}
|
||||
else if (!_hide) {
|
||||
_hide = true;
|
||||
BOOST_LOG_TRIVIAL(info) << "MarkdownTip::ShowTip: start hide timer (300)...";
|
||||
_timer->StartOnce(300);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (_lastTip != tip) {
|
||||
bool tipChanged = _lastTip != tip;
|
||||
if (tipChanged) {
|
||||
auto content = LoadTip(tip, tooltip);
|
||||
if (content.empty()) {
|
||||
_hide = true;
|
||||
this->Hide();
|
||||
BOOST_LOG_TRIVIAL(info) << "MarkdownTip::ShowTip: hide soon on empty content.";
|
||||
return false;
|
||||
}
|
||||
auto script = "window.showMarkdown('" + url_encode(content) + "', true);";
|
||||
@@ -140,8 +144,11 @@ bool MarkdownTip::ShowTip(wxPoint pos, std::string const &tip, std::string const
|
||||
if (pos.y + this->GetSize().y > size.y)
|
||||
pos.y = size.y - this->GetSize().y;
|
||||
this->SetPosition(pos);
|
||||
_hide = false;
|
||||
_timer->StartOnce(500);
|
||||
if (tipChanged || _hide) {
|
||||
_hide = false;
|
||||
BOOST_LOG_TRIVIAL(info) << "MarkdownTip::ShowTip: start show timer (500)...";
|
||||
_timer->StartOnce(500);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -264,11 +271,14 @@ void MarkdownTip::OnTimer(wxTimerEvent& event)
|
||||
if (_hide) {
|
||||
wxPoint pos = ScreenToClient(wxGetMousePosition());
|
||||
if (GetClientRect().Contains(pos)) {
|
||||
BOOST_LOG_TRIVIAL(info) << "MarkdownTip::OnTimer: restart hide timer...";
|
||||
_timer->StartOnce();
|
||||
return;
|
||||
}
|
||||
BOOST_LOG_TRIVIAL(info) << "MarkdownTip::OnTimer: hide.";
|
||||
this->Hide();
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(info) << "MarkdownTip::OnTimer: show.";
|
||||
this->Show();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,7 +163,7 @@ void MediaFilePanel::SetMachineObject(MachineObject* obj)
|
||||
auto fs = m_image_grid->GetFileSystem();
|
||||
if (fs) {
|
||||
m_image_grid->SetFileSystem(nullptr);
|
||||
fs->Unbind(EVT_MODE_CHANGED, &MediaFilePanel::fileChanged, this);
|
||||
fs->Unbind(EVT_MODE_CHANGED, &MediaFilePanel::modeChanged, this);
|
||||
fs->Stop(true);
|
||||
}
|
||||
if (m_machine.empty()) {
|
||||
@@ -171,7 +171,7 @@ void MediaFilePanel::SetMachineObject(MachineObject* obj)
|
||||
} else {
|
||||
boost::shared_ptr<PrinterFileSystem> fs(new PrinterFileSystem);
|
||||
m_image_grid->SetFileSystem(fs);
|
||||
fs->Bind(EVT_MODE_CHANGED, &MediaFilePanel::fileChanged, this);
|
||||
fs->Bind(EVT_MODE_CHANGED, &MediaFilePanel::modeChanged, this);
|
||||
fs->Bind(EVT_STATUS_CHANGED, [this, wfs = boost::weak_ptr(fs)](auto &e) {
|
||||
boost::shared_ptr fs(wfs.lock());
|
||||
if (m_image_grid->GetFileSystem() != fs) // canceled
|
||||
@@ -183,6 +183,7 @@ void MediaFilePanel::SetMachineObject(MachineObject* obj)
|
||||
case PrinterFileSystem::Connecting: icon = m_bmp_loading.bmp(); msg = _L("Connecting..."); break;
|
||||
case PrinterFileSystem::Failed: icon = m_bmp_failed.bmp(); msg = _L("Connect failed [%d]!"); break;
|
||||
case PrinterFileSystem::ListSyncing: icon = m_bmp_loading.bmp(); msg = _L("Loading file list..."); break;
|
||||
case PrinterFileSystem::ListReady: icon = m_bmp_empty.bmp(); msg = _L("No files"); break;
|
||||
}
|
||||
if (fs->GetCount() == 0)
|
||||
m_image_grid->SetStatus(icon, msg);
|
||||
@@ -192,7 +193,7 @@ void MediaFilePanel::SetMachineObject(MachineObject* obj)
|
||||
if (IsShown()) fs->Start();
|
||||
}
|
||||
wxCommandEvent e(EVT_MODE_CHANGED);
|
||||
fileChanged(e);
|
||||
modeChanged(e);
|
||||
}
|
||||
|
||||
void MediaFilePanel::Rescale()
|
||||
@@ -218,12 +219,10 @@ void MediaFilePanel::Rescale()
|
||||
m_image_grid->Rescale();
|
||||
}
|
||||
|
||||
void MediaFilePanel::fileChanged(wxCommandEvent& e1)
|
||||
void MediaFilePanel::modeChanged(wxCommandEvent& e1)
|
||||
{
|
||||
e1.Skip();
|
||||
auto fs = m_image_grid->GetFileSystem();
|
||||
if (fs)
|
||||
m_image_grid->SetStatus(m_bmp_empty.bmp(), fs->GetCount() ? L"" : _L("No files"));
|
||||
auto mode = fs ? fs->GetGroupMode() : 0;
|
||||
if (m_last_mode == mode)
|
||||
return;
|
||||
@@ -247,7 +246,7 @@ void MediaFilePanel::fetchUrl(boost::weak_ptr<PrinterFileSystem> wfs)
|
||||
BOOST_LOG_TRIVIAL(info) << "MediaFilePanel::fetchUrl: camera_url: " << url;
|
||||
CallAfter([this, url, wfs] {
|
||||
boost::shared_ptr fs(wfs.lock());
|
||||
if (fs != m_image_grid->GetFileSystem()) return;
|
||||
if (!fs || fs != m_image_grid->GetFileSystem()) return;
|
||||
fs->SetUrl(url);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -38,7 +38,7 @@ public:
|
||||
void Rescale();
|
||||
|
||||
private:
|
||||
void fileChanged(wxCommandEvent & e);
|
||||
void modeChanged(wxCommandEvent & e);
|
||||
|
||||
void fetchUrl(boost::weak_ptr<PrinterFileSystem> fs);
|
||||
|
||||
|
||||
@@ -111,7 +111,7 @@ void MediaPlayCtrl::Stop()
|
||||
m_media_ctrl->InvalidateBestSize();
|
||||
m_button_play->SetIcon("media_play");
|
||||
boost::unique_lock lock(m_mutex);
|
||||
m_tasks.push_back("");
|
||||
m_tasks.push_back("<stop>");
|
||||
m_cond.notify_all();
|
||||
}
|
||||
m_last_state = MEDIASTATE_IDLE;
|
||||
@@ -132,6 +132,11 @@ void MediaPlayCtrl::SetStatus(wxString const& msg2)
|
||||
{
|
||||
auto msg = wxString::Format(msg2, m_failed_code);
|
||||
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::SetStatus: " << msg.ToUTF8().data();
|
||||
#ifdef __WXMSW__
|
||||
OutputDebugStringA("MediaPlayCtrl::SetStatus: ");
|
||||
OutputDebugStringA(msg.ToUTF8().data());
|
||||
OutputDebugStringA("\n");
|
||||
#endif // __WXMSW__
|
||||
m_label_status->SetLabel(msg);
|
||||
//m_label_status->SetForegroundColour(!msg.EndsWith("!") ? 0x42AE00 : 0x3B65E9);
|
||||
Layout();
|
||||
@@ -147,11 +152,17 @@ void MediaPlayCtrl::media_proc()
|
||||
wxString url = m_tasks.front();
|
||||
lock.unlock();
|
||||
if (url.IsEmpty()) {
|
||||
break;
|
||||
}
|
||||
else if (url == "<stop>") {
|
||||
m_media_ctrl->Stop();
|
||||
}
|
||||
else if (url == "<exit>") {
|
||||
break;
|
||||
}
|
||||
else if (url == "<play>") {
|
||||
m_media_ctrl->Play();
|
||||
}
|
||||
else {
|
||||
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: start load";
|
||||
m_media_ctrl->Load(wxURI(url));
|
||||
@@ -193,10 +204,11 @@ void MediaPlayCtrl::onStateChanged(wxMediaEvent& event)
|
||||
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::onStateChanged: size: " << size.x << "x" << size.y;
|
||||
m_failed_code = m_media_ctrl->GetLastError();
|
||||
if (size.GetWidth() > 1000) {
|
||||
m_media_ctrl->Play();
|
||||
SetStatus(_L("Playing..."));
|
||||
m_failed_retry = 0;
|
||||
m_last_state = m_media_ctrl->GetState();
|
||||
boost::unique_lock lock(m_mutex);
|
||||
m_tasks.push_back("<play>");
|
||||
m_cond.notify_all();
|
||||
}
|
||||
else if (event.GetId()) {
|
||||
Stop();
|
||||
|
||||
+22
-15
@@ -335,7 +335,7 @@ void MonitorPanel::on_size(wxSizeEvent &event)
|
||||
|
||||
// update wifi signal image
|
||||
int wifi_signal_val = 0;
|
||||
if (!obj->is_connected()) {
|
||||
if (!obj->is_connected() || obj->is_connecting()) {
|
||||
m_side_tools->set_current_printer_signal(WifiSignal::NONE);
|
||||
} else {
|
||||
if (!obj->wifi_signal.empty() && boost::ends_with(obj->wifi_signal, "dBm")) {
|
||||
@@ -381,6 +381,7 @@ void MonitorPanel::update_all()
|
||||
}
|
||||
|
||||
if (obj) {
|
||||
wxGetApp().reset_to_active();
|
||||
if (obj->connection_type() != last_conn_type) {
|
||||
last_conn_type = obj->connection_type();
|
||||
}
|
||||
@@ -404,7 +405,10 @@ void MonitorPanel::update_all()
|
||||
return;
|
||||
}
|
||||
|
||||
if (!obj->is_connected()) {
|
||||
if (obj->is_connecting()) {
|
||||
show_status(MONITOR_CONNECTING);
|
||||
return;
|
||||
} else if (!obj->is_connected()) {
|
||||
int server_status = 0;
|
||||
// only disconnected server in cloud mode
|
||||
if (obj->connection_type() != "lan") {
|
||||
@@ -413,7 +417,6 @@ void MonitorPanel::update_all()
|
||||
}
|
||||
}
|
||||
show_status((int) MONITOR_DISCONNECTED + server_status);
|
||||
m_status_info_panel->show_unload_ctrl();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -457,15 +460,9 @@ bool MonitorPanel::Show(bool show)
|
||||
obj->reset_update_time();
|
||||
}
|
||||
}
|
||||
|
||||
if (m_agent)
|
||||
m_agent->start_subscribe("monitor");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
m_refresh_timer->Stop();
|
||||
m_status_info_panel->m_media_play_ctrl->SetMachineObject(nullptr);
|
||||
if (m_agent)
|
||||
m_agent->stop_subscribe("monitor");
|
||||
}
|
||||
return wxPanel::Show(show);
|
||||
}
|
||||
@@ -503,8 +500,15 @@ void MonitorPanel::show_status(int status)
|
||||
else
|
||||
m_connection_info->SetLabel(_L("Failed to connect to the printer"));
|
||||
m_connection_info->Show();
|
||||
}else if ((status & (int) MonitorStatus::MONITOR_NORMAL) != 0) {
|
||||
m_connection_info->SetBackgroundColor(wxColour(255, 111, 0));
|
||||
m_connection_info->SetBorderColor(wxColour(255, 111, 0));
|
||||
} else if ((status & (int) MonitorStatus::MONITOR_NORMAL) != 0) {
|
||||
m_connection_info->Hide();
|
||||
} else if ((status & (int) MonitorStatus::MONITOR_CONNECTING) != 0) {
|
||||
m_connection_info->SetLabel(_L("Connecting..."));
|
||||
m_connection_info->SetBackgroundColor(wxColour(0, 174, 66));
|
||||
m_connection_info->SetBorderColor(wxColour(0, 174, 66));
|
||||
m_connection_info->Show();
|
||||
}
|
||||
|
||||
Freeze();
|
||||
@@ -515,11 +519,14 @@ void MonitorPanel::show_status(int status)
|
||||
m_status_info_panel->show_status(status);
|
||||
m_tabpanel->Refresh();
|
||||
m_tabpanel->Layout();
|
||||
} else if (((status & (int)MonitorStatus::MONITOR_NORMAL) != 0) ||
|
||||
((status & (int)MonitorStatus::MONITOR_DISCONNECTED) != 0) ||
|
||||
((status & (int) MonitorStatus::MONITOR_DISCONNECTED_SERVER) != 0)
|
||||
} else if (((status & (int)MonitorStatus::MONITOR_NORMAL) != 0)
|
||||
|| ((status & (int)MonitorStatus::MONITOR_DISCONNECTED) != 0)
|
||||
|| ((status & (int) MonitorStatus::MONITOR_DISCONNECTED_SERVER) != 0)
|
||||
|| ((status & (int)MonitorStatus::MONITOR_CONNECTING) != 0)
|
||||
) {
|
||||
if (((status & (int) MonitorStatus::MONITOR_DISCONNECTED) != 0) || ((status & (int) MonitorStatus::MONITOR_DISCONNECTED_SERVER) != 0)) {
|
||||
if (((status & (int) MonitorStatus::MONITOR_DISCONNECTED) != 0)
|
||||
|| ((status & (int) MonitorStatus::MONITOR_DISCONNECTED_SERVER) != 0)
|
||||
|| ((status & (int)MonitorStatus::MONITOR_CONNECTING) != 0)) {
|
||||
m_side_tools->set_current_printer_signal(WifiSignal::NONE);
|
||||
set_default();
|
||||
}
|
||||
|
||||
@@ -390,5 +390,4 @@ void DownloadDialog::SetExtendedMessage(const wxString &extendedMessage)
|
||||
Fit();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}} // namespace Slic3r::GUI
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
#include <wx/textctrl.h>
|
||||
#include <wx/statline.h>
|
||||
#include "Widgets/Button.hpp"
|
||||
#include "BBLStatusBar.hpp"
|
||||
#include "BBLStatusBarSend.hpp"
|
||||
|
||||
class wxBoxSizer;
|
||||
class wxCheckBox;
|
||||
@@ -364,7 +366,6 @@ private:
|
||||
wxString msg;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user