Merge branch 'master' into SoftFever

This commit is contained in:
SoftFever 2022-08-11 20:06:32 +08:00
commit 159ff850e4
256 changed files with 14986 additions and 4365 deletions

View file

@ -189,7 +189,25 @@ int CLI::run(int argc, char **argv)
params.argv = argv;
params.load_configs = load_configs;
params.extra_config = std::move(m_extra_config);
params.input_files = std::move(m_input_files);
std::vector<std::string> gcode_files;
std::vector<std::string> non_gcode_files;
for (const auto& filename : m_input_files) {
if (is_gcode_file(filename))
gcode_files.emplace_back(filename);
else {
non_gcode_files.emplace_back(filename);
}
}
if (non_gcode_files.empty() && !gcode_files.empty()) {
params.input_gcode = true;
params.input_files = std::move(gcode_files);
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", gcode only, gcode_files size = "<<params.input_files.size();
}
else {
params.input_files = std::move(m_input_files);
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", normal mode, input_files size = "<<params.input_files.size();
}
//BBS: remove GCodeViewer as seperate APP logic
//params.start_as_gcodeviewer = start_as_gcodeviewer;

View file

@ -165,7 +165,7 @@ namespace ImGui
const wchar_t FoldButtonIcon = 0x0814;
const wchar_t UnfoldButtonIcon = 0x0815;
const wchar_t SphereButtonIcon = 0x0816;
const wchar_t FragmentFilterIcon = 0x0817;
const wchar_t GapFillIcon = 0x0817;
// void MyFunction(const char* name, const MyMatrix44& v);
}

View file

@ -203,6 +203,20 @@ public:
inline Unit area() const BP2D_NOEXCEPT {
return Unit(width())*height();
}
_Box intersection(_Box other) {
_Box inter;
inter.p1.x() = std::max(p1.x(), other.p1.x());
inter.p1.y() = std::max(p1.y(), other.p1.y());
inter.p2.x() = std::min(p2.x(), other.p2.x());
inter.p2.y() = std::min(p2.y(), other.p2.y());
inter.defined = true;
if (inter.p2.y() < inter.p1.y() || inter.p2.x() < inter.p1.x()) {
inter.p2 = inter.p1;
inter.defined = false;
}
return inter;
}
static inline _Box infinite(const P &center = {TCoord<P>(0), TCoord<P>(0)});
};

View file

@ -1083,9 +1083,13 @@ private:
auto d = cb - ci;
// BBS TODO we assume the exclude region contains bottom left corner. If not, change the code below
if (!config_.m_excluded_regions.empty()) {
d.x() = d.x() < 0 ? 0 : d.x();
d.y() = d.y() < 0 ? 0 : d.y();
if (!config_.m_excluded_regions.empty()) { // do not move to left to much to avoid clash with excluded regions
if (d.x() < 0) {
d.x() = 0;// std::max(long(d.x()), long(bbin.maxCorner().x() - bb.maxCorner().x()));
}
if (d.y() < 0) {
d.y() = 0;// std::max(long(d.y()), long(bbin.maxCorner().y() - bb.maxCorner().y()));
}
}
for(Item& item : items_)
if (!item.is_virt_object)

View file

@ -44,6 +44,41 @@ static const std::string MODELS_STR = "models";
const std::string AppConfig::SECTION_FILAMENTS = "filaments";
const std::string AppConfig::SECTION_MATERIALS = "sla_materials";
std::string AppConfig::get_langauge_code()
{
std::string get_lang = get("language");
if (get_lang.empty()) return "";
if (get_lang == "zh_CN")
{
get_lang = "zh-cn";
}
else
{
if (get_lang.length() >= 2) { get_lang = get_lang.substr(0, 2); }
}
return get_lang;
}
std::string AppConfig::get_hms_host()
{
std::string sel = get("iot_environment");
std::string host = "";
#if !BBL_RELEASE_TO_PUBLIC
if (sel == ENV_DEV_HOST)
host = "e-dev.bambu-lab.com";
else if (sel == ENV_QAT_HOST)
host = "e-qa.bambu-lab.com";
else if (sel == ENV_PRE_HOST)
host = "e-pre.bambu-lab.com";
else if (sel == ENV_PRODUCT_HOST)
host = "e.bambulab.com";
return host;
#else
return "e.bambulab.com";
#endif
}
void AppConfig::reset()
{

View file

@ -39,6 +39,9 @@ public:
this->reset();
}
std::string get_langauge_code();
std::string get_hms_host();
// Clear and reset to defaults.
void reset();
// Override missing or keys with their defaults.

View file

@ -136,6 +136,25 @@ static double fixed_overfit(const std::tuple<double, Box>& result, const Box &bi
return score;
}
// useful for arranging big circle objects
static double fixed_overfit_topright_sliding(const std::tuple<double, Box>& result, const Box& binbb)
{
double score = std::get<0>(result);
Box pilebb = std::get<1>(result);
auto shift = binbb.maxCorner() - pilebb.maxCorner();
shift.x() = std::max(0, shift.x()); // do not allow left shift
shift.y() = std::max(0, shift.y()); // do not allow bottom shift
pilebb.minCorner() += shift;
pilebb.maxCorner() += shift;
Box fullbb = sl::boundingBox(pilebb, binbb);
auto diff = double(fullbb.area()) - binbb.area();
if (diff > 0) score += diff;
return score;
}
// A class encapsulating the libnest2d Nester class and extending it with other
// management and spatial index structures for acceleration.
template<class TBin>
@ -503,8 +522,9 @@ public:
break;
}
}
cfg.object_function = [this, bb, starting_point](const Item& item) {
return fixed_overfit(objfunc(item, starting_point), bb);
return fixed_overfit_topright_sliding(objfunc(item, starting_point), bb);
};
};

View file

@ -65,8 +65,7 @@ struct ArrangePolygon {
int itemid{ 0 }; // item id in the vector, used for accessing all possible params like extrude_id
int is_applied{ 0 }; // transform has been applied
double height{ 0 }; // item height
double auto_brim_width{ 0 }; // auto brim width
double user_brim_width{ 0 }; // user defined brim width
double brim_width{ 0 }; // brim width
std::string name;
// If empty, any rotation is allowed (currently unsupported)

View file

@ -641,7 +641,7 @@ double getadhesionCoeff(const PrintObject* printObject)
for (auto iter = extrudersFirstLayer.begin(); iter != extrudersFirstLayer.end(); iter++)
if (modelVolume->extruder_id() == *iter) {
if (Model::extruderParamsMap.find(modelVolume->extruder_id()) != Model::extruderParamsMap.end())
if (Model::extruderParamsMap.at(modelVolume->extruder_id()).materialName == "PET") {
if (Model::extruderParamsMap.at(modelVolume->extruder_id()).materialName == "PETG") {
adhesionCoeff = 2;
}
else if (Model::extruderParamsMap.at(modelVolume->extruder_id()).materialName == "TPU") {
@ -806,7 +806,7 @@ double configBrimWidthByVolumes(double deltaT, double adhension, double maxSpeed
}
//BBS: config brimwidth by group of volumes
double configBrimWidthByVolumeGroups(double adhension, double maxSpeed, const std::vector<ModelVolume*> modelVolumePtrs, const ExPolygons& expolys)
double configBrimWidthByVolumeGroups(double adhension, double maxSpeed, const std::vector<ModelVolume*> modelVolumePtrs, const ExPolygons& expolys, double &groupHeight)
{
// height of a group of volumes
double height = 0;
@ -824,7 +824,7 @@ double configBrimWidthByVolumeGroups(double adhension, double maxSpeed, const st
}
auto bbox_size = mergedBbx.size();
height = bbox_size(2);
groupHeight = height;
// second moment of the expolygons of the first layer of the volume group
double Ixx = -1.e30, Iyy = -1.e30;
if (!expolys.empty()) {
@ -843,8 +843,8 @@ double configBrimWidthByVolumeGroups(double adhension, double maxSpeed, const st
double thermalLength = sqrt(bboxX * bboxX + bboxY * bboxY) * SCALING_FACTOR;
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);
double height_to_area = std::max(height / Ixx * (bbox2.size()(1) * SCALING_FACTOR), height / Iyy * (bbox2.size()(0) * SCALING_FACTOR)) * height / 1920;
double brim_width = adhension * std::min(std::min(std::max(height_to_area * maxSpeed, thermalLength * 8. / thermalLengthRef * std::min(height, 30.) / 30.), 18.), 1.5 * thermalLength);
// small brims are omitted
if (brim_width < 5 && brim_width < 1.5 * thermalLength)
brim_width = 0;
@ -915,17 +915,17 @@ static ExPolygons outer_inner_brim_area(const Print& print,
if (currentModelVolumePtr != nullptr) groupVolumePtrs.push_back(currentModelVolumePtr);
}
if (groupVolumePtrs.empty()) continue;
double groupHeight = 0.;
// config brim width in auto-brim mode
if (has_brim_auto) {
double brimWidthRaw = configBrimWidthByVolumeGroups(adhension, maxSpeed, groupVolumePtrs, volumeGroup.slices);
double brimWidthRaw = configBrimWidthByVolumeGroups(adhension, maxSpeed, groupVolumePtrs, volumeGroup.slices, groupHeight);
brim_width = scale_(floor(brimWidthRaw / flowWidth / 2) * flowWidth * 2);
}
for (const ExPolygon& ex_poly : volumeGroup.slices) {
// BBS: additional brim width will be added if part's adhension area is too small and brim is not generated
float brim_width_mod;
if (brim_width < scale_(5.) && has_brim_auto) {
if (brim_width < scale_(5.) && has_brim_auto && groupHeight > 10.) {
brim_width_mod = ex_poly.area() / ex_poly.contour.length() < scaled_half_min_adh_length
&& brim_width < scaled_flow_width ? brim_width + scaled_additional_brim_width : brim_width;
}

View file

@ -3099,6 +3099,8 @@ void FillMonotonicLineWGapFill::fill_surface_extrusion(const Surface* surface, c
FillParams params2 = params;
params2.monotonic = true;
params2.anchor_length_max = 0.0f;
//BBS: always don't adjust the spacing of top surface infill
params2.dont_adjust = true;
//BBS: always use no overlap expolygons to avoid overflow in top surface
for (const ExPolygon &rectilinear_area : this->no_overlap_expolygons) {
@ -3188,14 +3190,14 @@ void FillMonotonicLineWGapFill::fill_surface_by_lines(const Surface* surface, co
std::pair<float, Point> rotate_vector = this->_infill_direction(surface);
assert(params.full_infill());
coord_t line_spacing = coord_t(scale_(this->spacing));
coord_t line_spacing = params.flow.scaled_spacing();
// On the polygons of poly_with_offset, the infill lines will be connected.
ExPolygonWithOffset poly_with_offset(
surface->expolygon,
- rotate_vector.first,
float(scale_(0 - (0.5 - INFILL_OVERLAP_OVER_SPACING) * this->spacing)),
float(scale_(0 - 0.5f * this->spacing)));
float(scale_(0 - (0.5 - INFILL_OVERLAP_OVER_SPACING) * params.flow.spacing())),
float(scale_(0 - 0.5f * params.flow.spacing())));
if (poly_with_offset.n_contours_inner == 0) {
// Not a single infill line fits.
//FIXME maybe one shall trigger the gap fill here?
@ -3205,9 +3207,18 @@ void FillMonotonicLineWGapFill::fill_surface_by_lines(const Surface* surface, co
BoundingBox bounding_box = poly_with_offset.bounding_box_src();
// define flow spacing according to requested density
assert(!params.dont_adjust);
line_spacing = this->_adjust_solid_spacing(bounding_box.size()(0), line_spacing);
this->spacing = unscale<double>(line_spacing);
if (params.full_infill() && !params.dont_adjust) {
line_spacing = this->_adjust_solid_spacing(bounding_box.size()(0), line_spacing);
this->spacing = unscale<double>(line_spacing);
} else {
// extend bounding box so that our pattern will be aligned with other layers
// Transform the reference point to the rotated coordinate system.
Point refpt = rotate_vector.second.rotated(-rotate_vector.first);
bounding_box.merge(align_to_grid(
bounding_box.min,
Point(line_spacing, line_spacing),
refpt));
}
// Intersect a set of euqally spaced vertical lines wiht expolygon.
size_t n_vlines = (bounding_box.max(0) - bounding_box.min(0) + line_spacing - 1) / line_spacing;

View file

@ -271,6 +271,105 @@ namespace Slic3r {
//! return same string
#define L(s) (s)
#define _(s) Slic3r::I18N::translate(s)
void XMLCALL PrusaFileParser::start_element_handler(void *userData, const char *name, const char **attributes)
{
PrusaFileParser *prusa_parser = (PrusaFileParser *) userData;
if (prusa_parser != nullptr) { prusa_parser->_start_element_handler(name, attributes); }
}
void XMLCALL PrusaFileParser::characters_handler(void *userData, const XML_Char *s, int len)
{
PrusaFileParser *prusa_parser = (PrusaFileParser *) userData;
if (prusa_parser != nullptr) { prusa_parser->_characters_handler(s, len); }
}
bool PrusaFileParser::check_3mf_from_prusa(const std::string filename)
{
mz_zip_archive archive;
mz_zip_zero_struct(&archive);
if (!open_zip_reader(&archive, filename)) {
// throw Slic3r::RuntimeError("Loading 3mf file failed.");
return false;
}
const std::string sub_relationship_file = "3D/_rels/3dmodel.model.rels";
int sub_index = mz_zip_reader_locate_file(&archive, sub_relationship_file.c_str(), nullptr, 0);
if (sub_index == -1) {
const std::string model_file = "3D/3dmodel.model";
int model_file_index = mz_zip_reader_locate_file(&archive, model_file.c_str(), nullptr, 0);
if (model_file_index != -1) {
int depth = 0;
m_parser = XML_ParserCreate(nullptr);
XML_SetUserData(m_parser, (void *) this);
XML_SetElementHandler(m_parser, start_element_handler, nullptr);
XML_SetCharacterDataHandler(m_parser, characters_handler);
mz_zip_archive_file_stat stat;
if (!mz_zip_reader_file_stat(&archive, model_file_index, &stat)) goto EXIT;
void *parser_buffer = XML_GetBuffer(m_parser, (int) stat.m_uncomp_size);
if (parser_buffer == nullptr) goto EXIT;
mz_bool res = mz_zip_reader_extract_file_to_mem(&archive, stat.m_filename, parser_buffer, (size_t) stat.m_uncomp_size, 0);
if (res == 0) goto EXIT;
XML_ParseBuffer(m_parser, (int) stat.m_uncomp_size, 1);
}
}
EXIT:
close_zip_reader(&archive);
return m_from_prusa;
}
void PrusaFileParser::_characters_handler(const XML_Char *s, int len)
{
if (m_is_application_key) {
std::string str(s, len);
if (!str.empty() && str.find("PrusaSlicer") != std::string::npos) m_from_prusa = true;
}
}
void PrusaFileParser::_start_element_handler(const char *name, const char **attributes)
{
if (::strcmp(name, "metadata") == 0) {
unsigned int num_attributes = (unsigned int) XML_GetSpecifiedAttributeCount(m_parser);
std::string str_name = get_attribute_value_string(attributes, num_attributes, "name");
if (!str_name.empty() && str_name.find("Application") != std::string::npos) { m_is_application_key = true; }
}
}
const char *PrusaFileParser::get_attribute_value_charptr(const char **attributes, unsigned int attributes_size, const char *attribute_key)
{
if ((attributes == nullptr) || (attributes_size == 0) || (attributes_size % 2 != 0) || (attribute_key == nullptr)) return nullptr;
for (unsigned int a = 0; a < attributes_size; a += 2) {
if (::strcmp(attributes[a], attribute_key) == 0) return attributes[a + 1];
}
return nullptr;
}
std::string PrusaFileParser::get_attribute_value_string(const char **attributes, unsigned int attributes_size, const char *attribute_key)
{
const char *text = get_attribute_value_charptr(attributes, attributes_size, attribute_key);
return (text != nullptr) ? text : "";
}
ModelVolumeType type_from_string(const std::string &s)
{
// Legacy support
if (s == "1") return ModelVolumeType::PARAMETER_MODIFIER;
// New type (supporting the support enforcers & blockers)
if (s == "ModelPart") return ModelVolumeType::MODEL_PART;
if (s == "NegativeVolume") return ModelVolumeType::NEGATIVE_VOLUME;
if (s == "ParameterModifier") return ModelVolumeType::PARAMETER_MODIFIER;
if (s == "SupportEnforcer") return ModelVolumeType::SUPPORT_ENFORCER;
if (s == "SupportBlocker") return ModelVolumeType::SUPPORT_BLOCKER;
// Default value if invalud type string received.
return ModelVolumeType::MODEL_PART;
}
// Base class with error messages management
class _3MF_Base
@ -668,6 +767,7 @@ namespace Slic3r {
std::string name(stat.m_filename);
std::replace(name.begin(), name.end(), '\\', '/');
/*
if (boost::algorithm::iequals(name, LAYER_HEIGHTS_PROFILE_FILE)) {
// extract slic3r layer heights profile file
_extract_layer_heights_profile_config_from_archive(archive, stat);
@ -692,7 +792,9 @@ namespace Slic3r {
// extract slic3r layer config ranges file
_extract_custom_gcode_per_print_z_from_archive(archive, stat);
}
else if (boost::algorithm::iequals(name, MODEL_CONFIG_FILE)) {
*/
// only read the model config for Prusa 3mf
if (boost::algorithm::iequals(name, MODEL_CONFIG_FILE)) {
// extract slic3r model config file
if (!_extract_model_config_from_archive(archive, stat, model)) {
close_zip_reader(&archive);
@ -1913,6 +2015,27 @@ namespace Slic3r {
std::string key = get_attribute_value_string(attributes, num_attributes, KEY_ATTR);
std::string value = get_attribute_value_string(attributes, num_attributes, VALUE_ATTR);
// filter the prusa model config keys
std::vector<std::string> valid_keys = {
"name",
"volume_type",
"matrix",
"source_file",
"source_object_id",
"source_volume_id",
"source_offset_x",
"source_offset_y",
"source_offset_z",
"extruder",
"modifier"
};
auto itor = std::find(valid_keys.begin(), valid_keys.end(), key);
if (itor == valid_keys.end()) {
// do nothing if not valid keys
return true;
}
if (type == OBJECT_TYPE)
object->second.metadata.emplace_back(key, value);
else if (type == VOLUME_TYPE) {
@ -2044,7 +2167,7 @@ namespace Slic3r {
else if ((metadata.key == MODIFIER_KEY) && (metadata.value == "1"))
volume->set_type(ModelVolumeType::PARAMETER_MODIFIER);
else if (metadata.key == VOLUME_TYPE_KEY)
volume->set_type(ModelVolume::type_from_string(metadata.value));
volume->set_type(type_from_string(metadata.value));
else if (metadata.key == SOURCE_FILE_KEY)
volume->source.input_file = metadata.value;
else if (metadata.key == SOURCE_OBJECT_ID_KEY)

View file

@ -1,7 +1,30 @@
#ifndef slic3r_Format_3mf_hpp_
#define slic3r_Format_3mf_hpp_
#include "../expat.h"
namespace Slic3r {
// PrusaFileParser is used to check 3mf file is from Prusa
class PrusaFileParser
{
public:
PrusaFileParser() {}
~PrusaFileParser() {}
bool check_3mf_from_prusa(const std::string filename);
void _start_element_handler(const char *name, const char **attributes);
void _characters_handler(const XML_Char *s, int len);
private:
const char *get_attribute_value_charptr(const char **attributes, unsigned int attributes_size, const char *attribute_key);
std::string get_attribute_value_string(const char **attributes, unsigned int attributes_size, const char *attribute_key);
static void XMLCALL start_element_handler(void *userData, const char *name, const char **attributes);
static void XMLCALL characters_handler(void *userData, const XML_Char *s, int len);
private:
bool m_from_prusa = false;
bool m_is_application_key = false;
XML_Parser m_parser;
};
/* The format for saving the SLA points was changing in the past. This enum holds the latest version that is being currently used.
* Examples of the Slic3r_PE_sla_support_points.txt for historically used versions:

View file

@ -3755,7 +3755,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
bool _add_project_config_file_to_archive(mz_zip_archive& archive, const DynamicPrintConfig &config, Model& model);
//BBS: add project embedded preset files
bool _add_project_embedded_presets_to_archive(mz_zip_archive& archive, Model& model, std::vector<Preset*> project_presets);
bool _add_model_config_file_to_archive(mz_zip_archive& archive, const Model& model, PlateDataPtrs& plate_data_list, const IdToObjectDataMap &objects_data, int export_plate_idx = -1);
bool _add_model_config_file_to_archive(mz_zip_archive& archive, const Model& model, PlateDataPtrs& plate_data_list, const IdToObjectDataMap &objects_data, int export_plate_idx = -1, bool save_gcode = true);
bool _add_slice_info_config_file_to_archive(mz_zip_archive& archive, const Model& model, PlateDataPtrs& plate_data_list);
bool _add_gcode_file_to_archive(mz_zip_archive& archive, const Model& model, PlateDataPtrs& plate_data_list, Export3mfProgressFn proFn = nullptr);
bool _add_custom_gcode_per_print_z_file_to_archive(mz_zip_archive& archive, Model& model, const DynamicPrintConfig* config);
@ -4093,7 +4093,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
// This file contains all the attributes of all ModelObjects and their ModelVolumes (names, parameter overrides).
// As there is just a single Indexed Triangle Set data stored per ModelObject, offsets of volumes into their respective Indexed Triangle Set data
// is stored here as well.
if (!_add_model_config_file_to_archive(archive, model, plate_data_list, objects_data, export_plate_idx)) {
if (!_add_model_config_file_to_archive(archive, model, plate_data_list, objects_data, export_plate_idx, m_save_gcode)) {
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ":" << __LINE__ << boost::format(", _add_model_config_file_to_archive failed\n");
return false;
}
@ -4414,13 +4414,13 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
region_code = project->project_country_code;
}
stream << " <" << METADATA_TAG << " name=\"" << BBL_MODEL_NAME_TAG << "\">" << name << "</" << METADATA_TAG << ">\n";
stream << " <" << METADATA_TAG << " name=\"" << BBL_DESIGNER_TAG << "\">" << user_name << "</" << METADATA_TAG << ">\n";
stream << " <" << METADATA_TAG << " name=\"" << BBL_DESIGNER_USER_ID_TAG << "\">" << user_id << "</" << METADATA_TAG << ">\n";
stream << " <" << METADATA_TAG << " name=\"" << BBL_DESIGNER_COVER_FILE_TAG << "\">" << design_cover << "</" << METADATA_TAG << ">\n";
stream << " <" << METADATA_TAG << " name=\"" << BBL_DESCRIPTION_TAG << "\">" << description << "</" << METADATA_TAG << ">\n";
stream << " <" << METADATA_TAG << " name=\"" << BBL_COPYRIGHT_TAG << "\">" << copyright << "</" << METADATA_TAG << ">\n";
stream << " <" << METADATA_TAG << " name=\"" << BBL_LICENSE_TAG << "\">" << license << "</" << METADATA_TAG << ">\n";
stream << " <" << METADATA_TAG << " name=\"" << BBL_MODEL_NAME_TAG << "\">" << xml_escape(name) << "</" << METADATA_TAG << ">\n";
stream << " <" << METADATA_TAG << " name=\"" << BBL_DESIGNER_TAG << "\">" << xml_escape(user_name) << "</" << METADATA_TAG << ">\n";
stream << " <" << METADATA_TAG << " name=\"" << BBL_DESIGNER_USER_ID_TAG << "\">" << user_id << "</" << METADATA_TAG << ">\n";
stream << " <" << METADATA_TAG << " name=\"" << BBL_DESIGNER_COVER_FILE_TAG << "\">" << xml_escape(design_cover) << "</" << METADATA_TAG << ">\n";
stream << " <" << METADATA_TAG << " name=\"" << BBL_DESCRIPTION_TAG << "\">" << xml_escape(description) << "</" << METADATA_TAG << ">\n";
stream << " <" << METADATA_TAG << " name=\"" << BBL_COPYRIGHT_TAG << "\">" << xml_escape(copyright) << "</" << METADATA_TAG << ">\n";
stream << " <" << METADATA_TAG << " name=\"" << BBL_LICENSE_TAG << "\">" << xml_escape(license) << "</" << METADATA_TAG << ">\n";
/* save model info */
if (!model_id.empty()) {
@ -5199,7 +5199,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
return true;
}
bool _BBS_3MF_Exporter::_add_model_config_file_to_archive(mz_zip_archive& archive, const Model& model, PlateDataPtrs& plate_data_list, const IdToObjectDataMap &objects_data, int export_plate_idx)
bool _BBS_3MF_Exporter::_add_model_config_file_to_archive(mz_zip_archive& archive, const Model& model, PlateDataPtrs& plate_data_list, const IdToObjectDataMap &objects_data, int export_plate_idx, bool save_gcode)
{
std::stringstream stream;
// Store mesh transformation in full precision, as the volumes are stored transformed and they need to be transformed back
@ -5324,7 +5324,8 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
//plate index
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << PLATERID_ATTR << "\" " << VALUE_ATTR << "=\"" << plate_data->plate_index + 1 << "\"/>\n";
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << LOCK_ATTR << "\" " << VALUE_ATTR << "=\"" << std::boolalpha<< plate_data->locked<< "\"/>\n";
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << GCODE_FILE_ATTR << "\" " << VALUE_ATTR << "=\"" << std::boolalpha << plate_data->gcode_file << "\"/>\n";
if (save_gcode)
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << GCODE_FILE_ATTR << "\" " << VALUE_ATTR << "=\"" << std::boolalpha << xml_escape(plate_data->gcode_file) << "\"/>\n";
if (!plate_data->gcode_file.empty()) {
gcode_paths.push_back(plate_data->gcode_file);
}
@ -5363,8 +5364,10 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
stream << " </" << PLATE_TAG << ">\n";
}
}
// write model rels
_add_relationships_file_to_archive(archive, BBS_MODEL_CONFIG_RELS_FILE, gcode_paths, {"http://schemas.bambulab.com/package/2021/gcode"}, Slic3r::PackingTemporaryData(), export_plate_idx);
if (save_gcode)
_add_relationships_file_to_archive(archive, BBS_MODEL_CONFIG_RELS_FILE, gcode_paths, {"http://schemas.bambulab.com/package/2021/gcode"}, Slic3r::PackingTemporaryData(), export_plate_idx);
//BBS: store assemble related info
stream << " <" << ASSEMBLE_TAG << ">\n";

View file

@ -344,7 +344,9 @@ bool GCode::gcode_label_objects = false;
float purge_length = purge_volume / filament_area;
int old_filament_e_feedrate = gcode_writer.extruder() != nullptr ? (int)(60.0 * full_config.filament_max_volumetric_speed.get_at(previous_extruder_id) / filament_area) : 200;
old_filament_e_feedrate = old_filament_e_feedrate == 0 ? 100 : old_filament_e_feedrate;
int new_filament_e_feedrate = (int)(60.0 * full_config.filament_max_volumetric_speed.get_at(new_extruder_id) / filament_area);
new_filament_e_feedrate = new_filament_e_feedrate == 0 ? 100 : new_filament_e_feedrate;
config.set_key_value("max_layer_z", new ConfigOptionFloat(gcodegen.m_max_layer_z));
config.set_key_value("relative_e_axis", new ConfigOptionBool(RELATIVE_E_AXIS));
@ -3923,6 +3925,7 @@ std::string GCode::set_extruder(unsigned int extruder_id, double print_z)
old_filament_temp = m_config.nozzle_temperature.get_at(previous_extruder_id);
wipe_volume = flush_matrix[previous_extruder_id * number_of_extruders + extruder_id];
old_filament_e_feedrate = (int)(60.0 * m_config.filament_max_volumetric_speed.get_at(previous_extruder_id) / filament_area);
old_filament_e_feedrate = old_filament_e_feedrate == 0 ? 100 : old_filament_e_feedrate;
}
else {
old_retract_length = 0.f;
@ -3933,6 +3936,7 @@ std::string GCode::set_extruder(unsigned int extruder_id, double print_z)
}
float wipe_length = wipe_volume / filament_area;
int new_filament_e_feedrate = (int)(60.0 * m_config.filament_max_volumetric_speed.get_at(extruder_id) / filament_area);
new_filament_e_feedrate = new_filament_e_feedrate == 0 ? 100 : new_filament_e_feedrate;
DynamicConfig dyn_config;
dyn_config.set_key_value("previous_extruder", new ConfigOptionInt((int)(m_writer.extruder() != nullptr ? m_writer.extruder()->id() : -1)));

View file

@ -33,6 +33,7 @@
// BBS: for segment
#include "MeshBoolean.hpp"
#include "Format/3mf.hpp"
namespace Slic3r {
// BBS initialization of static variables
@ -202,7 +203,7 @@ Model Model::read_from_file(const std::string& input_file, DynamicPrintConfig* c
//BBS: add part plate related logic
// BBS: backup & restore
// Loading model from a file (3MF or AMF), not from a simple geometry file (STL or OBJ).
Model Model::read_from_archive(const std::string& input_file, DynamicPrintConfig* config, ConfigSubstitutionContext* config_substitutions, LoadStrategy options, PlateDataPtrs* plate_data, std::vector<Preset*>* project_presets, bool *is_bbl_3mf, Semver* file_version, Import3mfProgressFn proFn, BBLProject *project)
Model Model::read_from_archive(const std::string& input_file, DynamicPrintConfig* config, ConfigSubstitutionContext* config_substitutions, En3mfType& out_file_type, LoadStrategy options, PlateDataPtrs* plate_data, std::vector<Preset*>* project_presets, Semver* file_version, Import3mfProgressFn proFn, BBLProject *project)
{
assert(config != nullptr);
assert(config_substitutions != nullptr);
@ -210,15 +211,28 @@ Model Model::read_from_archive(const std::string& input_file, DynamicPrintConfig
Model model;
bool result = false;
if (boost::algorithm::iends_with(input_file, ".3mf"))
//BBS: add part plate related logic
// BBS: backup & restore
result = load_bbs_3mf(input_file.c_str(), config, config_substitutions, &model, plate_data, project_presets, is_bbl_3mf, file_version, proFn, options, project);
bool is_bbl_3mf;
if (boost::algorithm::iends_with(input_file, ".3mf")) {
PrusaFileParser prusa_file_parser;
if (prusa_file_parser.check_3mf_from_prusa(input_file)) {
// for Prusa 3mf
result = load_3mf(input_file.c_str(), *config, *config_substitutions, &model, true);
out_file_type = En3mfType::From_Prusa;
} else {
// BBS: add part plate related logic
// BBS: backup & restore
result = load_bbs_3mf(input_file.c_str(), config, config_substitutions, &model, plate_data, project_presets, &is_bbl_3mf, file_version, proFn, options, project);
}
}
else if (boost::algorithm::iends_with(input_file, ".zip.amf"))
result = load_amf(input_file.c_str(), config, config_substitutions, &model, is_bbl_3mf);
result = load_amf(input_file.c_str(), config, config_substitutions, &model, &is_bbl_3mf);
else
throw Slic3r::RuntimeError("Unknown file format. Input file must have .3mf or .zip.amf extension.");
if (out_file_type != En3mfType::From_Prusa) {
out_file_type = is_bbl_3mf ? En3mfType::From_BBS : En3mfType::From_Other;
}
if (!result)
throw Slic3r::RuntimeError("Loading of a model file failed.");
@ -2837,7 +2851,7 @@ double getadhesionCoeff(const ModelVolumePtrs objectVolumes)
double adhesionCoeff = 1;
for (const ModelVolume* modelVolume : objectVolumes) {
if (Model::extruderParamsMap.find(modelVolume->extruder_id()) != Model::extruderParamsMap.end())
if (Model::extruderParamsMap.at(modelVolume->extruder_id()).materialName == "PET") {
if (Model::extruderParamsMap.at(modelVolume->extruder_id()).materialName == "PETG") {
adhesionCoeff = 2;
}
else if (Model::extruderParamsMap.at(modelVolume->extruder_id()).materialName == "TPU") {
@ -2871,6 +2885,14 @@ double getTemperatureFromExtruder(const ModelVolumePtrs objectVolumes) {
#endif
}
double ModelInstance::get_auto_brim_width() const
{
double adhcoeff = getadhesionCoeff(object->volumes);
double DeltaT = getTemperatureFromExtruder(object->volumes);
// get auto brim width (Note even if the global brim_type=btOuterBrim, we can still go into this branch)
return get_auto_brim_width(DeltaT, adhcoeff);
}
void ModelInstance::get_arrange_polygon(void* ap) const
{
// static const double SIMPLIFY_TOLERANCE_MM = 0.1;
@ -2910,18 +2932,6 @@ void ModelInstance::get_arrange_polygon(void* ap) const
ret.extrude_ids = volume->get_extruders();
if (ret.extrude_ids.empty()) //the default extruder
ret.extrude_ids.push_back(1);
// get user specified brim width per object
// Note: if global brim_type=btNoBrim or brAutoBrim, user can't set individual brim_width
if (object->config.has("brim_width"))
ret.user_brim_width = object->config.opt_float("brim_width");
else {
// BBS: get DeltaT, adhcoeff before calculating brim width
double adhcoeff = getadhesionCoeff(object->volumes);
double DeltaT = getTemperatureFromExtruder(object->volumes);
// get auto brim width (Note even if the global brim_type=btOuterBrim, we can still go into this branch)
ret.auto_brim_width = get_auto_brim_width(DeltaT, adhcoeff);
}
}
indexed_triangle_set FacetsAnnotation::get_facets(const ModelVolume& mv, EnforcerBlockerType type) const

View file

@ -297,6 +297,12 @@ public:
const Model* get_model() const { return m_model; }
// BBS: production extension
int get_backup_id() const;
template<typename T> const T* get_config_value(const DynamicPrintConfig& global_config, const std::string& config_option) {
if (config.has(config_option))
return static_cast<const T*>(config.option(config_option));
else
return global_config.option<T>(config_option);
}
ModelVolume* add_volume(const TriangleMesh &mesh);
ModelVolume* add_volume(TriangleMesh &&mesh, ModelVolumeType type = ModelVolumeType::MODEL_PART);
@ -577,6 +583,12 @@ enum class ConversionType : int {
CONV_FROM_METER,
};
enum class En3mfType : int {
From_BBS,
From_Prusa,
From_Other
};
class FacetsAnnotation final : public ObjectWithTimestamp {
public:
// Assign the content if the timestamp differs, don't assign an ObjectID.
@ -1077,6 +1089,7 @@ public:
//BBS
double get_auto_brim_width(double deltaT, double adhension) const;
double get_auto_brim_width() const;
// BBS
Polygon convex_hull_2d();
void invalidate_convex_hull_2d();
@ -1280,8 +1293,8 @@ public:
// BBS: backup
static Model read_from_archive(
const std::string& input_file,
DynamicPrintConfig* config, ConfigSubstitutionContext* config_substitutions,
LoadStrategy options = LoadStrategy::AddDefaultInstances, PlateDataPtrs* plate_data = nullptr, std::vector<Preset*>* project_presets = nullptr, bool* is_bbl_3mf = nullptr, Semver* file_version = nullptr, Import3mfProgressFn proFn = nullptr, BBLProject* project = nullptr);
DynamicPrintConfig* config, ConfigSubstitutionContext* config_substitutions, En3mfType& out_file_type,
LoadStrategy options = LoadStrategy::AddDefaultInstances, PlateDataPtrs* plate_data = nullptr, std::vector<Preset*>* project_presets = nullptr, Semver* file_version = nullptr, Import3mfProgressFn proFn = nullptr, BBLProject* project = nullptr);
// Add a new ModelObject to this Model, generate a new ID for this ModelObject.
ModelObject* add_object();

View file

@ -144,8 +144,22 @@ ArrangePolygon get_instance_arrange_poly(ModelInstance* instance, const Slic3r::
for (int i = 0; i < BedType::btCount; i++)
ap.vitrify_temp += tmp * pow(100, BedType::btCount - i - 1);
}
ap.height = instance->get_object()->bounding_box().size().z();
ap.name = instance->get_object()->name;
// get brim width
auto obj = instance->get_object();
ap.brim_width = instance->get_auto_brim_width();
auto brim_type_ptr = obj->get_config_value<ConfigOptionEnum<BrimType>>(config, "brim_type");
if (brim_type_ptr) {
auto brim_type = brim_type_ptr->getInt();
if (brim_type == btOuterOnly)
ap.brim_width = obj->get_config_value<ConfigOptionFloat>(config, "brim_width")->getFloat();
else if (brim_type == btNoBrim)
ap.brim_width = 0;
}
ap.height = obj->bounding_box().size().z();
ap.name = obj->name;
return ap;
}

View file

@ -637,9 +637,9 @@ void Preset::set_visible_from_appconfig(const AppConfig &app_config)
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(": name %1%, is_visible set to %2%")%name % is_visible;
}
std::string Preset::get_filament_type()
std::string Preset::get_filament_type(std::string &display_filament_type)
{
return config.get_filament_type();
return config.get_filament_type(display_filament_type);
}
static std::vector<std::string> s_Preset_print_options {

View file

@ -295,7 +295,7 @@ public:
bool operator<(const Preset &other) const { return this->name < other.name; }
// special for upport G and Support W
std::string get_filament_type();
std::string get_filament_type(std::string &display_filament_type);
static const std::vector<std::string>& print_options();
static const std::vector<std::string>& filament_options();

View file

@ -729,7 +729,7 @@ void PresetBundle::remove_users_preset(AppConfig& config)
}
printers.select_preset_by_name(default_printer_name, true);
} else {
printers.select_preset_by_name(printer_selected_preset_name, true);
printers.select_preset_by_name(printer_selected_preset_name, false);
}
std::string selected_print_name = prints.get_selected_preset().name;
@ -750,7 +750,7 @@ void PresetBundle::remove_users_preset(AppConfig& config)
std::string default_print_profile_name = printers.get_selected_preset().config.opt_string("default_print_profile");
prints.select_preset_by_name(default_print_profile_name, true);
} else {
prints.select_preset_by_name(selected_print_name, true);
prints.select_preset_by_name(selected_print_name, false);
}
std::string selected_filament_name = filaments.get_selected_preset().name;
@ -771,7 +771,7 @@ void PresetBundle::remove_users_preset(AppConfig& config)
if (prefered_filament_profiles.size() > 0)
filaments.select_preset_by_name(prefered_filament_profiles[0], true);
} else {
filaments.select_preset_by_name(selected_filament_name, true);
filaments.select_preset_by_name(selected_filament_name, false);
}
/* set selected preset */

View file

@ -692,14 +692,15 @@ static StringObjectException layered_print_cleareance_valid(const Print &print,
//BBS
static std::map<std::string, bool> filament_is_high_temp {
{"PLA", false},
{"PET", true},
{"PLA-CF", false},
{"PETG", true},
{"ABS", true},
{"TPU", false},
{"PA", true},
{"PA-CF", true},
{"PET-CF", true},
{"PC", true},
{"ASA", true},
{"PVA", false}
{"ASA", true}
};
//BBS: this function is used to check whether multi filament can be printed

View file

@ -264,8 +264,11 @@ void PrintConfigDef::init_common_params()
//BBS: add "bed_exclude_area"
def = this->add("bed_exclude_area", coPoints);
def->label = L("Bed exclude area");
def->mode = comDevelop;
def->set_default_value(new ConfigOptionPoints{});
def->tooltip = L("Unprintable area in XY plane. For example, X1 Series printers use the front left corner to cut filament during filament change. "
"The area is expressed as polygon by points in following format: \"XxY, XxY, ...\"");
def->mode = comAdvanced;
def->gui_type = ConfigOptionDef::GUIType::one_string;
def->set_default_value(new ConfigOptionPoints{ Vec2d(0, 0) });
def = this->add("elefant_foot_compensation", coFloat);
def->label = L("Elephant foot compensation");
@ -290,7 +293,6 @@ void PrintConfigDef::init_common_params()
def->sidetext = L("mm");
def->min = 0;
def->max = 1000;
def->readonly = true;
def->mode = comSimple;
def->set_default_value(new ConfigOptionFloat(100.0));
@ -720,7 +722,7 @@ void PrintConfigDef::init_fff_params()
def->multiline = true;
def->full_width = true;
def->height = 120;
def->mode = comDevelop;
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionStrings { " " });
auto def_top_fill_pattern = def = this->add("top_surface_pattern", coEnum);
@ -951,13 +953,15 @@ void PrintConfigDef::init_fff_params()
def->gui_type = ConfigOptionDef::GUIType::f_enum_open;
def->gui_flags = "show_value";
def->enum_values.push_back("PLA");
def->enum_values.push_back("PET");
def->enum_values.push_back("ABS");
def->enum_values.push_back("TPU");
def->enum_values.push_back("PA");
def->enum_values.push_back("PET-CF");
def->enum_values.push_back("PC");
def->enum_values.push_back("ASA");
def->enum_values.push_back("PETG");
def->enum_values.push_back("TPU");
def->enum_values.push_back("PC");
def->enum_values.push_back("PA");
def->enum_values.push_back("PA-CF");
def->enum_values.push_back("PLA-CF");
def->enum_values.push_back("PET-CF");
def->enum_values.push_back("PVA");
def->mode = comSimple;
def->set_default_value(new ConfigOptionStrings { "PLA" });
@ -1970,7 +1974,7 @@ void PrintConfigDef::init_fff_params()
def->set_default_value(new ConfigOptionFloat(100));
def = this->add("spiral_mode", coBool);
def->label = L("Spiral mode");
def->label = L("Spiral vase");
def->tooltip = L("Spiralize smooths out the z moves of the outer contour. "
"And turns a solid model into a single walled print with solid bottom layers. "
"The final generated model has no seam");
@ -1978,7 +1982,7 @@ void PrintConfigDef::init_fff_params()
def->set_default_value(new ConfigOptionBool(false));
def = this->add("timelapse_no_toolhead", coBool);
def->label = L("Timelapse without toolhead");
def->label = L("Timelapse");
def->tooltip = L("Record timelapse video of printing without showing toolhead. In this mode "
"the toolhead docks near the excess chute at each layer change, and then "
"a snapshot is taken with the chamber camera. When printing finishes a timelapse "
@ -2012,7 +2016,7 @@ void PrintConfigDef::init_fff_params()
def->multiline = true;
def->full_width = true;
def->height = 12;
def->mode = comDevelop;
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionStrings { " " });
def = this->add("single_extruder_multi_material", coBool);
@ -3583,7 +3587,7 @@ std::string DynamicPrintConfig::validate()
}
}
std::string DynamicPrintConfig::get_filament_type(int id)
std::string DynamicPrintConfig::get_filament_type(std::string &displayed_filament_type, int id)
{
auto* filament_id = dynamic_cast<const ConfigOptionStrings*>(this->option("filament_id"));
auto* filament_type = dynamic_cast<const ConfigOptionStrings*>(this->option("filament_type"));
@ -3594,9 +3598,11 @@ std::string DynamicPrintConfig::get_filament_type(int id)
if (!filament_is_support) {
if (filament_type) {
displayed_filament_type = filament_type->get_at(id);
return filament_type->get_at(id);
}
else {
displayed_filament_type = "";
return "";
}
}
@ -3605,25 +3611,33 @@ std::string DynamicPrintConfig::get_filament_type(int id)
if (is_support) {
if (filament_id) {
if (filament_id->get_at(id) == "GFS00") {
return "Support W";
displayed_filament_type = "Support W";
return "PLA-S";
}
else if (filament_id->get_at(id) == "GFS01") {
return "Support G";
displayed_filament_type = "Support G";
return "PA-S";
}
else {
return filament_type->get_at(id) + "-Support";
displayed_filament_type = filament_type->get_at(id);
return filament_type->get_at(id);
}
}
else {
if (filament_type->get_at(id) == "PLA")
return "Support W";
else if (filament_type->get_at(id) == "PA")
return "Support G";
else
return filament_type->get_at(id) + "-Support";
if (filament_type->get_at(id) == "PLA") {
displayed_filament_type = "Support W";
return "PLA-S";
} else if (filament_type->get_at(id) == "PA") {
displayed_filament_type = "Support G";
return "PA-S";
} else {
displayed_filament_type = filament_type->get_at(id);
return filament_type->get_at(id);
}
}
}
else {
displayed_filament_type = filament_type->get_at(id);
return filament_type->get_at(id);
}
}

View file

@ -325,7 +325,7 @@ public:
{ PrintConfigDef::handle_legacy(opt_key, value); }
//BBS special case Support G/ Support W
std::string get_filament_type(int id = 0);
std::string get_filament_type(std::string &displayed_filament_type, int id = 0);
};
void handle_legacy_sla(DynamicPrintConfig &config);

View file

@ -745,7 +745,6 @@ bool doesVolumeIntersect(VolumeSlices& vs1, VolumeSlices& vs2)
if (vs1.volume_id == vs2.volume_id) return true;
if (vs1.slices.size() != vs2.slices.size()) return false;
double offsetValue = 0.4 / SCALING_FACTOR;
for (int i = 0; i != vs1.slices.size(); ++i) {
if (vs1.slices[i].empty()) continue;
@ -766,7 +765,7 @@ bool groupingVolumes(std::vector<VolumeSlices> objSliceByVolume, std::vector<gro
int existGroups = 0;
std::vector<int> groupIndex(objSliceByVolume.size(), -1);
double offsetValue = 0.4 / SCALING_FACTOR;
double offsetValue = 0.15 / SCALING_FACTOR;
for (int i = 0; i != objSliceByVolume.size(); ++i) {
for (int j = 0; j != objSliceByVolume[i].slices.size(); ++j) {

View file

@ -27,6 +27,12 @@ enum MachineBedType {
BED_TYPE_COUNT,
};
enum MappingResult {
MAPPING_RESULT_DEFAULT = 0,
MAPPING_RESULT_TYPE_MISMATCH = 1,
MAPPING_RESULT_EXCEED = 2
};
struct FilamentInfo
{
int id; // filament id = extruder id, start with 0.
@ -36,6 +42,7 @@ struct FilamentInfo
float used_g;
int tray_id; // start with 0
float distance;
int mapping_result = 0;
};
class BBLSliceInfo {

View file

@ -3286,7 +3286,9 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::generate_raf
const BrimType brim_type = object.config().brim_type;
const bool brim_outer = brim_type == btOuterOnly || brim_type == btOuterAndInner;
const bool brim_inner = brim_type == btInnerOnly || brim_type == btOuterAndInner;
const auto brim_object_gap = scaled<float>(object.config().brim_object_gap.value + object.config().brim_width.value);
// BBS: the pattern of raft and brim are the same, thus the brim can be serpated by support raft.
const auto brim_object_gap = scaled<float>(object.config().brim_object_gap.value);
//const auto brim_object_gap = scaled<float>(object.config().brim_object_gap.value + object.config().brim_width.value);
for (const ExPolygon &ex : object.layers().front()->lslices) {
if (brim_outer && brim_inner)
polygons_append(brim, offset(ex, brim_object_gap));
@ -3389,7 +3391,12 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::generate_raf
if (columns_base != nullptr) {
// Expand the bases of the support columns in the 1st layer.
Polygons &raft = columns_base->polygons;
Polygons trimming = offset(m_object->layers().front()->lslices, (float)scale_(m_support_params.gap_xy), SUPPORT_SURFACES_OFFSET_PARAMETERS);
Polygons trimming;
// BBS: if first layer of support is intersected with object island, it must have the same function as brim unless in nobrim mode.
if (object.has_brim())
trimming = offset(m_object->layers().front()->lslices, (float)scale_(object.config().brim_object_gap.value), SUPPORT_SURFACES_OFFSET_PARAMETERS);
else
trimming = offset(m_object->layers().front()->lslices, (float)scale_(m_support_params.gap_xy), SUPPORT_SURFACES_OFFSET_PARAMETERS);
if (inflate_factor_1st_layer > SCALED_EPSILON) {
// Inflate in multiple steps to avoid leaking of the support 1st layer through object walls.
auto nsteps = std::max(5, int(ceil(inflate_factor_1st_layer / m_support_params.first_layer_flow.scaled_width())));

View file

@ -28,7 +28,7 @@ public:
POINTER,
// BBS
HEIGHT_RANGE,
FRAGMENT_FILTER,
GAP_FILL,
};
struct ClippingPlane

View file

@ -68,6 +68,8 @@ set(SLIC3R_GUI_SOURCES
GUI/Widgets/SideTools.hpp
GUI/Widgets/WebView.cpp
GUI/Widgets/WebView.hpp
GUI/Widgets/wxStaticText2.cpp
GUI/Widgets/wxStaticText2.hpp
GUI/AboutDialog.cpp
GUI/AboutDialog.hpp
GUI/AuxiliaryDialog.cpp
@ -125,8 +127,6 @@ set(SLIC3R_GUI_SOURCES
GUI/Gizmos/GLGizmoFaceDetector.hpp
GUI/Gizmos/GLGizmoSeam.cpp
GUI/Gizmos/GLGizmoSeam.hpp
GUI/Gizmos/GLGizmoModifier.cpp
GUI/Gizmos/GLGizmoModifier.hpp
GUI/GLSelectionRectangle.cpp
GUI/GLSelectionRectangle.hpp
GUI/Gizmos/GizmoObjectManipulation.cpp
@ -213,6 +213,8 @@ set(SLIC3R_GUI_SOURCES
GUI/MonitorPage.hpp
GUI/StatusPanel.cpp
GUI/StatusPanel.hpp
GUI/UpdateErrorMessage.cpp
GUI/UpdateErrorMessage.hpp
GUI/SliceInfoPanel.cpp
GUI/SliceInfoPanel.hpp
GUI/CameraPopup.cpp
@ -344,6 +346,8 @@ set(SLIC3R_GUI_SOURCES
GUI/ReleaseNote.cpp
GUI/Calibration.hpp
GUI/Calibration.cpp
GUI/PrintOptionsDialog.hpp
GUI/PrintOptionsDialog.cpp
Utils/json_diff.hpp
Utils/json_diff.cpp
GUI/KBShortcutsDialog.hpp

View file

@ -11,7 +11,9 @@ static bool show_flag;
#else
#define COMBOBOX_FILAMENT (m_comboBox_filament)
#endif
AMSMaterialsSetting::AMSMaterialsSetting(wxWindow *parent, wxWindowID id) : wxPopupTransientWindow(parent, wxPU_CONTAINS_CONTROLS) {
AMSMaterialsSetting::AMSMaterialsSetting(wxWindow *parent, wxWindowID id)
: DPIDialog(parent, id, _L("AMSMaterialsSetting"), wxDefaultPosition, wxDefaultSize, wxBORDER_NONE)
{
create();
}
@ -19,13 +21,15 @@ void AMSMaterialsSetting::create()
{
SetBackgroundColour(*wxWHITE);
wxBoxSizer *m_sizer_main = new wxBoxSizer(wxVERTICAL);
wxBoxSizer *m_sizer_body = new wxBoxSizer(wxVERTICAL);
SetSize(wxSize(AMS_MATERIALS_SETTING_BODY_WIDTH, -1));
SetMinSize(wxSize(AMS_MATERIALS_SETTING_BODY_WIDTH, -1));
SetMaxSize(wxSize(AMS_MATERIALS_SETTING_BODY_WIDTH, -1));
m_panel_body = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(AMS_MATERIALS_SETTING_BODY_WIDTH, -1), wxTAB_TRAVERSAL);
m_panel_body->SetBackgroundColour(*wxWHITE);
wxBoxSizer *m_sizer_filament = new wxBoxSizer(wxHORIZONTAL);
m_title_filament = new wxStaticText(m_panel_body, wxID_ANY, _L("Filament"), wxDefaultPosition, wxSize(AMS_MATERIALS_SETTING_LABEL_WIDTH, -1), 0);
m_title_filament = new wxStaticText(this, wxID_ANY, _L("Filament"), wxDefaultPosition, wxSize(AMS_MATERIALS_SETTING_LABEL_WIDTH, -1), 0);
m_title_filament->SetFont(::Label::Body_13);
m_title_filament->SetForegroundColour(AMS_MATERIALS_SETTING_GREY800);
m_title_filament->Wrap(-1);
@ -34,15 +38,15 @@ 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);
m_comboBox_filament_mac = new wxComboBox(this, 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_comboBox_filament = new ::ComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, AMS_MATERIALS_SETTING_COMBOX_WIDTH, 0, nullptr, wxCB_READONLY);
#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);
m_title_colour = new wxStaticText(this, wxID_ANY, _L("Colour"), wxDefaultPosition, wxSize(AMS_MATERIALS_SETTING_LABEL_WIDTH, -1), 0);
m_title_colour->SetFont(::Label::Body_13);
m_title_colour->SetForegroundColour(AMS_MATERIALS_SETTING_GREY800);
m_title_colour->Wrap(-1);
@ -53,30 +57,18 @@ void AMSMaterialsSetting::create()
m_clrData = new wxColourData();
m_clrData->SetChooseFull(true);
m_clrData->SetChooseAlpha(false);
m_clr_picker = new wxButton(m_panel_body, wxID_ANY, "", wxDefaultPosition, wxSize(FromDIP(20), FromDIP(20)), wxBU_EXACTFIT | wxBORDER_NONE);
m_clr_picker = new Button(this, "", "");
m_clr_picker->SetCanFocus(false);
m_clr_picker->SetSize(FromDIP(50), FromDIP(25));
m_clr_picker->SetMinSize(wxSize(FromDIP(50), FromDIP(25)));
m_clr_picker->SetCornerRadius(FromDIP(6));
m_clr_picker->SetBorderColor(wxColour(172, 172, 172));
m_clr_picker->Bind(wxEVT_BUTTON, &AMSMaterialsSetting::on_clr_picker, this);
m_sizer_colour->Add(m_clr_picker, 0, 0, 0);
m_panel_SN = new wxPanel(m_panel_body, wxID_ANY);
wxBoxSizer *m_sizer_SN = new wxBoxSizer(wxHORIZONTAL);
auto m_title_SN = new wxStaticText(m_panel_SN, wxID_ANY, _L("SN"), wxDefaultPosition, wxSize(AMS_MATERIALS_SETTING_LABEL_WIDTH, -1), 0);
m_title_SN->SetFont(::Label::Body_13);
m_title_SN->SetForegroundColour(AMS_MATERIALS_SETTING_GREY800);
m_title_SN->Wrap(-1);
m_sizer_SN->Add(m_title_SN, 0, wxALIGN_CENTER, 0);
m_sizer_SN->Add(0, 0, 0, wxEXPAND, 0);
m_sn_number = new wxStaticText(m_panel_SN, wxID_ANY, wxEmptyString, wxDefaultPosition, AMS_MATERIALS_SETTING_COMBOX_WIDTH);
m_sizer_SN->Add(m_sn_number, 0, wxALIGN_CENTER, 0);
m_panel_SN->SetSizer(m_sizer_SN);
m_panel_SN->Layout();
m_panel_SN->Fit();
wxBoxSizer *m_sizer_temperature = new wxBoxSizer(wxHORIZONTAL);
m_title_temperature = new wxStaticText(m_panel_body, wxID_ANY, _L("Nozzle\nTemperature"), wxDefaultPosition, wxSize(AMS_MATERIALS_SETTING_LABEL_WIDTH, -1), 0);
m_title_temperature = new wxStaticText(this, wxID_ANY, _L("Nozzle\nTemperature"), wxDefaultPosition, wxSize(AMS_MATERIALS_SETTING_LABEL_WIDTH, -1), 0);
m_title_temperature->SetFont(::Label::Body_13);
m_title_temperature->SetForegroundColour(AMS_MATERIALS_SETTING_GREY800);
m_title_temperature->Wrap(-1);
@ -87,8 +79,8 @@ 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_min = 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(this, wxEmptyString, wxEmptyString, wxEmptyString, wxDefaultPosition, AMS_MATERIALS_SETTING_INPUT_SIZE, wxTE_CENTRE | wxTE_PROCESS_ENTER);
m_input_nozzle_min = new ::TextInput(this, 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);
@ -97,8 +89,8 @@ void AMSMaterialsSetting::create()
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);
auto bitmap_max_degree = new wxStaticBitmap(this, -1, create_scaled_bitmap("degree", nullptr, 16), wxDefaultPosition, wxDefaultSize);
auto bitmap_min_degree = new wxStaticBitmap(this, -1, create_scaled_bitmap("degree", nullptr, 16), wxDefaultPosition, wxDefaultSize);
sizer_tempinput->Add(m_input_nozzle_max, 1, wxALIGN_CENTER, 0);
sizer_tempinput->Add(bitmap_min_degree, 0, wxALIGN_CENTER, 0);
@ -107,10 +99,10 @@ void AMSMaterialsSetting::create()
sizer_tempinput->Add(bitmap_max_degree, 0, wxALIGN_CENTER, 0);
wxBoxSizer *sizer_temp_txt = new wxBoxSizer(wxHORIZONTAL);
auto m_title_max = new wxStaticText(m_panel_body, wxID_ANY, _L("max"), wxDefaultPosition, AMS_MATERIALS_SETTING_INPUT_SIZE);
auto m_title_max = new wxStaticText(this, wxID_ANY, _L("max"), wxDefaultPosition, AMS_MATERIALS_SETTING_INPUT_SIZE);
m_title_max->SetForegroundColour(AMS_MATERIALS_SETTING_GREY800);
m_title_max->SetFont(::Label::Body_13);
auto m_title_min = new wxStaticText(m_panel_body, wxID_ANY, _L("min"), wxDefaultPosition, AMS_MATERIALS_SETTING_INPUT_SIZE);
auto m_title_min = new wxStaticText(this, wxID_ANY, _L("min"), wxDefaultPosition, AMS_MATERIALS_SETTING_INPUT_SIZE);
m_title_min->SetForegroundColour(AMS_MATERIALS_SETTING_GREY800);
m_title_min->SetFont(::Label::Body_13);
sizer_temp_txt->Add(m_title_max, 1, wxALIGN_CENTER, 0);
@ -126,7 +118,7 @@ void AMSMaterialsSetting::create()
wxString warning_string = wxString::FromUTF8(
(boost::format(_u8L("The input value should be greater than %1% and less than %2%")) % FILAMENT_MIN_TEMP % FILAMENT_MAX_TEMP).str());
warning_text = new wxStaticText(m_panel_body, wxID_ANY, warning_string, wxDefaultPosition, wxDefaultSize, 0);
warning_text = new wxStaticText(this, wxID_ANY, warning_string, wxDefaultPosition, wxDefaultSize, 0);
warning_text->SetFont(::Label::Body_13);
warning_text->SetForegroundColour(wxColour(255, 111, 0));
@ -164,42 +156,71 @@ void AMSMaterialsSetting::create()
e.Skip();
});
m_panel_SN = new wxPanel(this, wxID_ANY);
wxBoxSizer *m_sizer_SN = new wxBoxSizer(wxVERTICAL);
m_sizer_SN->AddSpacer(FromDIP(16));
wxBoxSizer *m_sizer_SN_inside = new wxBoxSizer(wxHORIZONTAL);
auto m_title_SN = new wxStaticText(m_panel_SN, wxID_ANY, _L("SN"), wxDefaultPosition, wxSize(AMS_MATERIALS_SETTING_LABEL_WIDTH, -1), 0);
m_title_SN->SetFont(::Label::Body_13);
m_title_SN->SetForegroundColour(AMS_MATERIALS_SETTING_GREY800);
m_title_SN->Wrap(-1);
m_sizer_SN_inside->Add(m_title_SN, 0, wxALIGN_CENTER, 0);
m_sizer_SN_inside->Add(0, 0, 0, wxEXPAND, 0);
m_sn_number = new wxStaticText(m_panel_SN, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize);
m_sizer_SN_inside->Add(m_sn_number, 0, wxALIGN_CENTER, 0);
m_sizer_SN->Add(m_sizer_SN_inside);
m_panel_SN->SetSizer(m_sizer_SN);
m_panel_SN->Layout();
m_panel_SN->Fit();
wxBoxSizer *m_sizer_button = new wxBoxSizer(wxHORIZONTAL);
m_sizer_button->Add(0, 0, 1, wxEXPAND, 0);
m_button_confirm = new Button(m_panel_body, _L("Confirm"));
m_button_confirm = new Button(this, _L("Confirm"));
m_btn_bg_green = StateColor(std::pair<wxColour, int>(wxColour(27, 136, 68), StateColor::Pressed), std::pair<wxColour, int>(wxColour(61, 203, 115), StateColor::Hovered),
std::pair<wxColour, int>(wxColour(0, 174, 66), StateColor::Normal));
m_button_confirm->SetBackgroundColor(m_btn_bg_green);
m_button_confirm->SetBorderColor(wxColour(0, 174, 66));
m_button_confirm->SetTextColor(AMS_MATERIALS_SETTING_GREY200);
m_button_confirm->SetMinSize(AMS_MATERIALS_SETTING_BUTTON_SIZE);
m_button_confirm->SetCornerRadius(12);
m_button_confirm->Bind(wxEVT_LEFT_DOWN, &AMSMaterialsSetting::on_select_ok, this);
m_sizer_button->Add(m_button_confirm, 0, wxALIGN_CENTER, 0);
m_button_confirm->SetCornerRadius(FromDIP(12));
m_button_confirm->Bind(wxEVT_BUTTON, &AMSMaterialsSetting::on_select_ok, this);
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);
m_sizer_body->Add(0, 0, 0, wxEXPAND | wxTOP, FromDIP(16));
m_sizer_body->Add(m_panel_SN, 0, wxEXPAND, 0);
m_sizer_body->Add(0, 0, 0, wxEXPAND | wxTOP, FromDIP(10));
m_sizer_body->Add(m_sizer_temperature, 0, wxEXPAND, 0);
m_sizer_body->Add(0, 0, 0, wxEXPAND | wxTOP, FromDIP(5));
m_sizer_body->Add(warning_text, 0, wxEXPAND, 0);
m_sizer_body->Add(0, 0, 0, wxEXPAND | wxTOP, FromDIP(24));
m_sizer_body->Add(m_sizer_button, 0, wxEXPAND, 0);
m_button_close = new Button(this, _L("Close"));
m_btn_bg_gray = StateColor(std::pair<wxColour, int>(wxColour(206, 206, 206), StateColor::Pressed), std::pair<wxColour, int>(*wxWHITE, StateColor::Focused),
std::pair<wxColour, int>(wxColour(238, 238, 238), StateColor::Hovered),
std::pair<wxColour, int>(*wxWHITE, StateColor::Normal));
m_button_close->SetBackgroundColor(m_btn_bg_gray);
m_button_close->SetBorderColor(AMS_MATERIALS_SETTING_GREY900);
m_button_close->SetTextColor(AMS_MATERIALS_SETTING_GREY900);
m_button_close->SetMinSize(AMS_MATERIALS_SETTING_BUTTON_SIZE);
m_button_close->SetCornerRadius(FromDIP(12));
m_button_close->Bind(wxEVT_BUTTON, &AMSMaterialsSetting::on_select_close, this);
m_panel_body->SetSizer(m_sizer_body);
m_panel_body->Layout();
m_sizer_main->Add(m_panel_body, 0, wxALL | wxEXPAND, 24);
m_sizer_button->Add(m_button_confirm, 0, wxALIGN_CENTER | wxRIGHT, FromDIP(20));
m_sizer_button->Add(m_button_close, 0, wxALIGN_CENTER, 0);
this->SetSizer(m_sizer_main);
this->Layout();
m_sizer_main->Fit(this);
m_sizer_main->Add(0, 0, 0, wxTOP, FromDIP(16));
m_sizer_main->Add(m_sizer_filament, 0, wxLEFT | wxRIGHT, FromDIP(20));
m_sizer_main->Add(0, 0, 0, wxTOP, FromDIP(16));
m_sizer_main->Add(m_sizer_colour, 0, wxLEFT | wxRIGHT, FromDIP(20));
m_sizer_main->Add(0, 0, 0, wxTOP, FromDIP(16));
m_sizer_main->Add(m_sizer_temperature, 0, wxLEFT | wxRIGHT, FromDIP(20));
m_sizer_main->Add(0, 0, 0, wxTOP, FromDIP(5));
m_sizer_main->Add(warning_text, 0, wxLEFT | wxRIGHT, FromDIP(20));
m_sizer_main->Add(m_panel_SN, 0, wxLEFT, FromDIP(20));
m_sizer_main->Add(0, 0, 0, wxTOP, FromDIP(24));
m_sizer_main->Add(m_sizer_button, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(20));
m_sizer_main->Add(0, 0, 0, wxTOP, FromDIP(16));
this->Centre(wxBOTH);
SetSizer(m_sizer_main);
Layout();
Fit();
Bind(wxEVT_PAINT, &AMSMaterialsSetting::paintEvent, this);
COMBOBOX_FILAMENT->Connect(wxEVT_COMMAND_COMBOBOX_SELECTED, wxCommandEventHandler(AMSMaterialsSetting::on_select_filament), NULL, this);
@ -219,7 +240,6 @@ AMSMaterialsSetting::~AMSMaterialsSetting()
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;
@ -264,23 +284,29 @@ void AMSMaterialsSetting::update()
void AMSMaterialsSetting::enable_confirm_button(bool en)
{
if (!en) {
if (m_button_confirm->IsEnabled()) {
m_button_confirm->Disable();
m_button_confirm->SetBackgroundColor(wxColour(0x90, 0x90, 0x90));
m_button_confirm->SetBorderColor(wxColour(0x90, 0x90, 0x90));
}
} else {
if (!m_button_confirm->IsEnabled()) {
m_button_confirm->Enable();
m_button_confirm->SetBackgroundColor(m_btn_bg_green);
m_button_confirm->SetBorderColor(m_btn_bg_green);
}
}
if (m_is_third) m_button_confirm->Show(en);
//if (!en) {
// if (m_button_confirm->IsEnabled()) {
// m_button_confirm->Disable();
// m_button_confirm->SetBackgroundColor(wxColour(0x90, 0x90, 0x90));
// m_button_confirm->SetBorderColor(wxColour(0x90, 0x90, 0x90));
// }
//} else {
// if (!m_button_confirm->IsEnabled()) {
// m_button_confirm->Enable();
// m_button_confirm->SetBackgroundColor(m_btn_bg_green);
// m_button_confirm->SetBorderColor(m_btn_bg_green);
// }
//}
}
void AMSMaterialsSetting::on_select_ok(wxMouseEvent &event)
void AMSMaterialsSetting::on_select_ok(wxCommandEvent &event)
{
if (!m_is_third) {
Close();
return;
}
wxString nozzle_temp_min = m_input_nozzle_min->GetTextCtrl()->GetValue();
auto filament = COMBOBOX_FILAMENT->GetValue();
@ -310,7 +336,12 @@ void AMSMaterialsSetting::on_select_ok(wxMouseEvent &event)
obj->command_ams_filament_settings(ams_id, tray_id, ams_filament_id, std::string(col_buf), m_filament_type, nozzle_temp_min_int, nozzle_temp_max_int);
}
}
wxPopupTransientWindow::Dismiss();
Close();
}
void AMSMaterialsSetting::on_select_close(wxCommandEvent &event)
{
Close();
}
void AMSMaterialsSetting::set_color(wxColour color)
@ -320,26 +351,13 @@ void AMSMaterialsSetting::set_color(wxColour color)
void AMSMaterialsSetting::on_clr_picker(wxCommandEvent & event)
{
if(!m_is_third)
return;
auto clr_dialog = new wxColourDialog(this, m_clrData);
show_flag = true;
if (clr_dialog->ShowModal() == wxID_OK) {
m_clrData = &(clr_dialog->GetColourData());
m_clr_picker->SetBackgroundColour(m_clrData->GetColour());
}
}
void AMSMaterialsSetting::Dismiss()
{
if (show_flag)
{
show_flag = false;
} else
{
#ifdef __APPLE__
#else
wxPopupTransientWindow::Dismiss();
#endif
m_clr_picker->SetBackgroundColor(m_clrData->GetColour());
}
}
@ -350,36 +368,45 @@ bool AMSMaterialsSetting::Show(bool show)
m_input_nozzle_max->GetTextCtrl()->SetSize(wxSize(-1, FromDIP(20)));
m_input_nozzle_min->GetTextCtrl()->SetSize(wxSize(-1, FromDIP(20)));
}
return wxPopupTransientWindow::Show(show);
return DPIDialog::Show(show);
}
void AMSMaterialsSetting::Popup(bool show, bool third, wxString filament, wxColour colour, wxString sn, wxString tep)
void AMSMaterialsSetting::Popup(wxString filament, wxString sn, wxString temp_min, wxString temp_max)
{
m_clr_picker->SetBackgroundColor(m_clrData->GetColour());
if (!m_is_third) {
m_button_confirm->Hide();
m_sn_number->SetLabel(sn);
m_panel_SN->Show();
#ifdef __APPLE__
wxArrayString filament_only;
filament_only.push_back(filament);
COMBOBOX_FILAMENT->Set(filament_only);
#else
COMBOBOX_FILAMENT->Set(wxArrayString());
#endif
COMBOBOX_FILAMENT->SetValue(filament);
m_sn_number->SetLabelText(sn);
m_input_nozzle_min->GetTextCtrl()->SetValue(tep);
m_clrData->SetColour(colour);
COMBOBOX_FILAMENT->Disable();
m_input_nozzle_min->Disable();
m_input_nozzle_min->GetTextCtrl()->SetValue(temp_min);
m_input_nozzle_max->GetTextCtrl()->SetValue(temp_max);
wxPopupTransientWindow::Popup();
Layout();
Fit();
ShowModal();
return;
}
m_button_confirm->Show();
m_panel_SN->Hide();
Layout();
Fit();
m_clr_picker->SetBackgroundColour(m_clrData->GetColour());
int selection_idx = -1, idx = 0;
wxArrayString filament_items;
std::set<std::string> filament_id_set;
if (show) {
PresetBundle* preset_bundle = wxGetApp().preset_bundle;
if (preset_bundle) {
BOOST_LOG_TRIVIAL(trace) << "system_preset_bundle filament number=" << preset_bundle->filaments.size();
@ -436,18 +463,12 @@ void AMSMaterialsSetting::Popup(bool show, bool third, wxString filament, wxColo
}
}
}
}
COMBOBOX_FILAMENT->Set(filament_items);
if (selection_idx >= 0 && selection_idx < filament_items.size()) {
COMBOBOX_FILAMENT->SetSelection(selection_idx);
post_select_event();
}
else {
COMBOBOX_FILAMENT->SetSelection(selection_idx);
post_select_event();
}
COMBOBOX_FILAMENT->SetSelection(selection_idx);
post_select_event();
}
wxPopupTransientWindow::Popup();
update();
ShowModal();
}
void AMSMaterialsSetting::post_select_event() {
@ -488,7 +509,8 @@ void AMSMaterialsSetting::on_select_filament(wxCommandEvent &evt)
if (opt_type_strs) {
found_filament_type = true;
//m_filament_type = opt_type_strs->get_at(0);
m_filament_type = it->config.get_filament_type();
std::string display_filament_type;
m_filament_type = it->config.get_filament_type(display_filament_type);
}
}
if (!found_filament_type)
@ -504,18 +526,6 @@ void AMSMaterialsSetting::on_select_filament(wxCommandEvent &evt)
}
}
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;
}
}
void AMSMaterialsSetting::on_dpi_changed(const wxRect &suggested_rect) { this->Refresh(); }
}} // namespace Slic3r::GUI

View file

@ -15,11 +15,12 @@
#include "Widgets/TextInput.hpp"
#define AMS_MATERIALS_SETTING_DEF_COLOUR wxColour(255, 255, 255)
#define AMS_MATERIALS_SETTING_GREY900 wxColour(38, 46, 48)
#define AMS_MATERIALS_SETTING_GREY800 wxColour(50, 58, 61)
#define AMS_MATERIALS_SETTING_GREY700 wxColour(107, 107, 107)
#define AMS_MATERIALS_SETTING_GREY300 wxColour(174,174,174)
#define AMS_MATERIALS_SETTING_GREY200 wxColour(248, 248, 248)
#define AMS_MATERIALS_SETTING_BODY_WIDTH FromDIP(340)
#define AMS_MATERIALS_SETTING_BODY_WIDTH FromDIP(380)
#define AMS_MATERIALS_SETTING_LABEL_WIDTH FromDIP(80)
#define AMS_MATERIALS_SETTING_COMBOX_WIDTH wxSize(FromDIP(250), FromDIP(30))
#define AMS_MATERIALS_SETTING_BUTTON_SIZE wxSize(FromDIP(90), FromDIP(24))
@ -27,7 +28,7 @@
namespace Slic3r { namespace GUI {
class AMSMaterialsSetting : public wxPopupTransientWindow
class AMSMaterialsSetting : public DPIDialog
{
public:
AMSMaterialsSetting(wxWindow *parent, wxWindowID id);
@ -39,17 +40,13 @@ public:
void input_max_finish();
void update();
void enable_confirm_button(bool en);
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 Popup(wxString filament = wxEmptyString, wxString sn = wxEmptyString, wxString temp_min = wxEmptyString, wxString temp_max = wxEmptyString);
void post_select_event();
void on_select_ok(wxMouseEvent &event);
void set_color(wxColour color);
void on_clr_picker(wxCommandEvent &event);
MachineObject *obj{nullptr};
int ams_id { 0 }; /* 0 ~ 3 */
int tray_id { 0 }; /* 0 ~ 3 */
@ -64,31 +61,35 @@ public:
std::string m_filament_type;
protected:
//void on_dpi_changed(const wxRect &suggested_rect) override;
void on_dpi_changed(const wxRect &suggested_rect) override;
void on_select_filament(wxCommandEvent& evt);
bool ProcessLeftDown(wxMouseEvent &evt);
void on_select_ok(wxCommandEvent &event);
void on_select_close(wxCommandEvent &event);
void on_clr_picker(wxCommandEvent &event);
protected:
StateColor m_btn_bg_green;
StateColor m_btn_bg_gray;
wxPanel * m_panel_SN;
wxStaticText * m_sn_number;
wxStaticText * warning_text;
wxPanel * m_panel_body;
//wxPanel * m_panel_body;
wxStaticText * m_title_filament;
ComboBox * m_comboBox_filament;
wxStaticText * m_title_colour;
wxButton * m_clr_picker;
wxStaticText * m_title_temperature;
wxStaticText * m_label_other;
TextInput * m_input_nozzle_min;
TextInput* m_input_nozzle_max;
Button * m_button_confirm;
#ifdef __APPLE__
wxComboBox *m_comboBox_filament_mac;
#endif
Button * m_button_close;
Button * m_clr_picker;
wxColourData * m_clrData;
#ifdef __APPLE__
wxComboBox *m_comboBox_filament_mac;
#else
ComboBox *m_comboBox_filament;
#endif
};
}} // namespace Slic3r::GUI

View file

@ -17,8 +17,8 @@ AboutDialogLogo::AboutDialogLogo(wxWindow* parent)
: wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize)
{
this->SetBackgroundColour(*wxWHITE);
this->logo = wxBitmap(from_u8(Slic3r::var("BambuStudio_192px.png")), wxBITMAP_TYPE_PNG);
this->SetMinSize(this->logo.GetSize());
this->logo = ScalableBitmap(this, Slic3r::var("BambuStudio_192px.png"), wxBITMAP_TYPE_PNG);
this->SetMinSize(this->logo.GetBmpSize());
this->Bind(wxEVT_PAINT, &AboutDialogLogo::onRepaint, this);
}
@ -29,9 +29,9 @@ void AboutDialogLogo::onRepaint(wxEvent &event)
dc.SetBackgroundMode(wxTRANSPARENT);
wxSize size = this->GetSize();
int logo_w = this->logo.GetWidth();
int logo_h = this->logo.GetHeight();
dc.DrawBitmap(this->logo, (size.GetWidth() - logo_w)/2, (size.GetHeight() - logo_h)/2, true);
int logo_w = this->logo.GetBmpWidth();
int logo_h = this->logo.GetBmpHeight();
dc.DrawBitmap(this->logo.bmp(), (size.GetWidth() - logo_w)/2, (size.GetHeight() - logo_h)/2, true);
event.Skip();
}

View file

@ -17,7 +17,7 @@ public:
AboutDialogLogo(wxWindow* parent);
private:
wxBitmap logo;
ScalableBitmap logo;
void onRepaint(wxEvent &event);
};

View file

@ -179,9 +179,9 @@ void MaterialItem::doRender(wxDC &dc)
AmsMapingPopup::AmsMapingPopup(wxWindow *parent)
:wxPopupTransientWindow(parent, wxBORDER_NONE)
{
SetSize(wxSize(FromDIP(220), -1));
SetMinSize(wxSize(FromDIP(220), -1));
SetMaxSize(wxSize(FromDIP(220), -1));
SetSize(wxSize(FromDIP(300), -1));
SetMinSize(wxSize(FromDIP(300), -1));
SetMaxSize(wxSize(FromDIP(300), -1));
Bind(wxEVT_PAINT, &AmsMapingPopup::paintEvent, this);
@ -193,11 +193,62 @@ void MaterialItem::doRender(wxDC &dc)
m_sizer_main = new wxBoxSizer(wxVERTICAL);
//m_sizer_main->Add(0, 0, 1, wxEXPAND, 0);
auto title_panel = new wxPanel(this, wxID_ANY);
title_panel->SetBackgroundColour(wxColour(0xF8, 0xF8, 0xF8));
title_panel->SetSize(wxSize(-1, FromDIP(30)));
title_panel->SetMinSize(wxSize(-1, FromDIP(30)));
wxBoxSizer *title_sizer_h= new wxBoxSizer(wxHORIZONTAL);
wxBoxSizer *title_sizer_v = new wxBoxSizer(wxVERTICAL);
auto title_text = new wxStaticText(title_panel, wxID_ANY, _L("AMS Slots"));
title_text->SetForegroundColour(wxColour(0x32, 0x3A, 0x3D));
title_text->SetFont(::Label::Head_13);
title_sizer_v->Add(title_text, 0, wxALIGN_CENTER, 5);
title_sizer_h->Add(title_sizer_v, 1, wxALIGN_CENTER, 5);
title_panel->SetSizer(title_sizer_h);
title_panel->Layout();
title_panel->Fit();
m_sizer_list = new wxBoxSizer(wxVERTICAL);
m_warning_text = new wxStaticText(this, wxID_ANY, wxEmptyString);
m_warning_text->SetForegroundColour(wxColour(0xFF, 0x6F, 0x00));
m_warning_text->SetFont(::Label::Body_12);
auto cant_not_match_tip = _L("Note: Only the AMS slots loaded with the same material type can be selected.");
m_warning_text->SetLabel(format_text(cant_not_match_tip));
m_warning_text->SetMinSize(wxSize(FromDIP(280), FromDIP(-1)));
m_warning_text->Wrap(FromDIP(280));
m_sizer_main->Add(title_panel, 0, wxEXPAND | wxALL, FromDIP(2));
m_sizer_main->Add(m_sizer_list, 0, wxEXPAND | wxALL, FromDIP(0));
m_sizer_main->Add(m_warning_text, 0, wxEXPAND | wxALL, FromDIP(10));
SetSizer(m_sizer_main);
Layout();
}
wxString AmsMapingPopup::format_text(wxString &m_msg)
{
if (wxGetApp().app_config->get("language") != "zh_CN") { return m_msg; }
wxString out_txt = m_msg;
wxString count_txt = "";
int new_line_pos = 0;
for (int i = 0; i < m_msg.length(); i++) {
auto text_size = m_warning_text->GetTextExtent(count_txt);
if (text_size.x < (FromDIP(280))) {
count_txt += m_msg[i];
} else {
out_txt.insert(i - 1, '\n');
count_txt = "";
}
}
return out_txt;
}
void AmsMapingPopup::update_materials_list(std::vector<std::string> list)
{
@ -224,7 +275,7 @@ void AmsMapingPopup::on_left_down(wxMouseEvent &evt)
auto left = item->GetSize();
if (pos.x > p_rect.x && pos.y > p_rect.y && pos.x < (p_rect.x + item->GetSize().x) && pos.y < (p_rect.y + item->GetSize().y)) {
if (item->m_tray_data.type == TrayType::NORMAL && !is_match_material(item->m_tray_data.name)) return;
if (item->m_tray_data.type == TrayType::NORMAL && !is_match_material(item->m_tray_data.filament_type)) return;
item->send_event(m_current_filament_id);
Dismiss();
}
@ -233,6 +284,7 @@ void AmsMapingPopup::on_left_down(wxMouseEvent &evt)
void AmsMapingPopup::update_ams_data(std::map<std::string, Ams*> amsList)
{
m_has_unmatch_filament = false;
m_mapping_item_list.clear();
if (m_amsmapping_sizer_list.size() > 0) {
for (wxBoxSizer *bz : m_amsmapping_sizer_list) { bz->Clear(true); }
@ -266,7 +318,8 @@ void AmsMapingPopup::update_ams_data(std::map<std::string, Ams*> amsList)
} else {
td.type = NORMAL;
td.colour = AmsTray::decode_color(tray_data->color);
td.name = tray_data->type;
td.name = tray_data->get_display_filament_type();
td.filament_type = tray_data->get_filament_type();
}
}
@ -275,6 +328,8 @@ void AmsMapingPopup::update_ams_data(std::map<std::string, Ams*> amsList)
add_ams_mapping(tray_datas);
}
m_warning_text->Show(m_has_unmatch_filament);
Layout();
Fit();
}
@ -294,57 +349,43 @@ void AmsMapingPopup::add_ams_mapping(std::vector<TrayData> tray_data)
// set button
MappingItem *m_filament_name = new MappingItem(this);
m_filament_name->SetSize(wxSize(FromDIP(38), FromDIP(20)));
m_filament_name->SetMinSize(wxSize(FromDIP(38), FromDIP(20)));
m_filament_name->SetMaxSize(wxSize(FromDIP(38), FromDIP(20)));
m_filament_name->SetSize(wxSize(FromDIP(62), FromDIP(22)));
m_filament_name->SetMinSize(wxSize(FromDIP(62), FromDIP(22)));
m_filament_name->SetMaxSize(wxSize(FromDIP(62), FromDIP(22)));
//m_filament_name->SetCornerRadius(5);
m_filament_name->SetFont(::Label::Body_12);
m_mapping_item_list.push_back(m_filament_name);
if (tray_data[i].type == NORMAL) {
m_filament_name->set_data(tray_data[i].colour, tray_data[i].name, tray_data[i]);
if (is_match_material(tray_data[i].filament_type)) {
m_filament_name->set_data(tray_data[i].colour, tray_data[i].name, tray_data[i]);
} else {
m_filament_name->set_data(wxColour(0xEE,0xEE,0xEE), tray_data[i].name, tray_data[i], true);
m_has_unmatch_filament = true;
}
m_filament_name->Bind(wxEVT_LEFT_DOWN, [this, tray_data, i, m_filament_name](wxMouseEvent &e) {
if (!is_match_material(tray_data[i].name)) return;
if (!is_match_material(tray_data[i].filament_type)) return;
m_filament_name->send_event(m_current_filament_id);
Dismiss();
/* wxCommandEvent event(EVT_SET_FINISH_MAPPING);
event.SetInt(tray_data[i].id);
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);
Dismiss();*/
});
}
// temp
if (tray_data[i].type == EMPTY) {
m_filament_name->set_data(wxColour(0x6B, 0x6B, 0x6B), "-", tray_data[i]);
m_filament_name->set_data(wxColour(0xCE, 0xCE, 0xCE), "-", tray_data[i]);
m_filament_name->Bind(wxEVT_LEFT_DOWN, [this, tray_data, i, m_filament_name](wxMouseEvent &e) {
m_filament_name->send_event(m_current_filament_id);
/* wxCommandEvent event(EVT_SET_FINISH_MAPPING);
event.SetInt(tray_data[i].id);
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);*/
Dismiss();
});
}
// third party
if (tray_data[i].type == THIRD) {
m_filament_name->set_data(wxColour(0x6B, 0x6B, 0x6B), "?", tray_data[i]);
m_filament_name->set_data(wxColour(0xCE, 0xCE, 0xCE), "?", tray_data[i]);
m_filament_name->Bind(wxEVT_LEFT_DOWN, [this, tray_data, i, m_filament_name](wxMouseEvent &e) {
m_filament_name->send_event(m_current_filament_id);
//wxCommandEvent event(EVT_SET_FINISH_MAPPING);
//event.SetInt(tray_data[i].id);
//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);
Dismiss();
});
}
@ -355,7 +396,7 @@ void AmsMapingPopup::add_ams_mapping(std::vector<TrayData> tray_data)
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);
m_sizer_list->Add(sizer_mapping_list, 0, wxALIGN_CENTER_HORIZONTAL, 0);
}
void AmsMapingPopup::OnDismiss()
@ -399,14 +440,6 @@ void MappingItem::send_event(int fliament_id)
event.SetString(param);
event.SetEventObject(this->GetParent()->GetParent());
wxPostEvent(this->GetParent()->GetParent(), event);
/* wxCommandEvent event(EVT_SET_FINISH_MAPPING);
event.SetInt(tray_data[i].id);
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);*/
}
void MappingItem::msw_rescale()
@ -443,22 +476,25 @@ void MappingItem::render(wxDC &dc)
#endif
// materials name
dc.SetFont(::Label::Body_13);
dc.SetFont(::Label::Body_12);
auto txt_colour = m_coloul.GetLuminance() < 0.5 ? *wxWHITE : wxColour(0x26, 0x2E, 0x30);
txt_colour = m_unmatch ? wxColour(0xCE, 0xCE, 0xCE) : txt_colour;
dc.SetTextForeground(txt_colour);
if (dc.GetTextExtent(m_name).x > GetSize().x - 10) {
/*if (dc.GetTextExtent(m_name).x > GetSize().x - 10) {
dc.SetFont(::Label::Body_10);
m_name = m_name.substr(0, 3) + "." + m_name.substr(m_name.length() - 1);
}
}*/
auto txt_size = dc.GetTextExtent(m_name);
dc.DrawText(m_name, wxPoint((GetSize().x - txt_size.x) / 2, (GetSize().y - txt_size.y) / 2));
}
void MappingItem::set_data(wxColour colour, wxString name, TrayData data)
void MappingItem::set_data(wxColour colour, wxString name, TrayData data, bool unmatch)
{
m_unmatch = unmatch;
m_tray_data = data;
if (m_coloul != colour || m_name != name) {
m_coloul = colour;

View file

@ -54,6 +54,7 @@ struct TrayData
TrayType type;
int id;
std::string name;
std::string filament_type;
wxColour colour;
};
@ -96,11 +97,12 @@ public:
wxColour m_coloul;
wxString m_name;
TrayData m_tray_data;
bool m_unmatch{false};
void msw_rescale();
void paintEvent(wxPaintEvent &evt);
void render(wxDC &dc);
void set_data(wxColour colour, wxString name, TrayData data);
void set_data(wxColour colour, wxString name, TrayData data, bool unmatch = false);
void doRender(wxDC &dc);
};
@ -108,15 +110,19 @@ class AmsMapingPopup : public wxPopupTransientWindow
{
public:
AmsMapingPopup(wxWindow *parent);
~AmsMapingPopup() {};
wxString format_text(wxString &m_msg);
~AmsMapingPopup(){};
wxStaticText * m_warning_text{nullptr};
std::vector<std::string> m_materials_list;
std::vector<wxBoxSizer*> m_amsmapping_sizer_list;
std::vector<MappingItem*> m_mapping_item_list;
bool m_has_unmatch_filament {false};
int m_current_filament_id;
std::string m_tag_material;
wxBoxSizer *m_sizer_main{nullptr};
wxBoxSizer *m_sizer_list{nullptr};
void update_materials_list(std::vector<std::string> list);
void set_tag_texture(std::string texture);

View file

@ -94,9 +94,9 @@ AuFile::AuFile(wxWindow *parent, fs::path file_path, wxString file_name, Auxilia
cover_text_right = _L("Rename");
cover_text_cover = _L("Cover");
m_file_cover = create_scaled_bitmap("auxiliary_cover", this, 50);
m_file_edit_mask = create_scaled_bitmap("auxiliary_edit_mask", this, 43);
m_file_delete = create_scaled_bitmap("auxiliary_delete", this, 28);
m_file_cover = ScalableBitmap(this, "auxiliary_cover", 50);
m_file_edit_mask = ScalableBitmap(this, "auxiliary_edit_mask", 43);
m_file_delete = ScalableBitmap(this, "auxiliary_delete", 28);
auto m_text_panel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(FromDIP(300), FromDIP(40)), wxTAB_TRAVERSAL);
m_text_panel->SetBackgroundColour(AUFILE_GREY300);
@ -183,7 +183,7 @@ void AuFile::PaintForeground(wxDC &dc)
wxSize size = wxSize(FromDIP(300), FromDIP(300));
if (m_hover) {
dc.DrawBitmap(m_file_edit_mask, 0, size.y - m_file_edit_mask.GetSize().y);
dc.DrawBitmap(m_file_edit_mask.bmp(), 0, size.y - m_file_edit_mask.GetBmpSize().y);
dc.SetFont(Label::Body_14);
dc.SetTextForeground(*wxWHITE);
if (m_type == MODEL_PICTURE) {
@ -191,14 +191,14 @@ void AuFile::PaintForeground(wxDC &dc)
auto sizet = dc.GetTextExtent(cover_text_left);
auto pos = wxPoint(0, 0);
pos.x = (size.x / 2 - sizet.x) / 2;
pos.y = (size.y - (m_file_edit_mask.GetSize().y + sizet.y) / 2);
pos.y = (size.y - (m_file_edit_mask.GetBmpSize().y + sizet.y) / 2);
dc.DrawText(cover_text_left, pos);
// right text
sizet = dc.GetTextExtent(cover_text_right);
pos = wxPoint(0, 0);
pos.x = size.x / 2 + (size.x / 2 - sizet.x) / 2;
pos.y = (size.y - (m_file_edit_mask.GetSize().y + sizet.y) / 2);
pos.y = (size.y - (m_file_edit_mask.GetBmpSize().y + sizet.y) / 2);
dc.DrawText(cover_text_right, pos);
// Split
@ -206,21 +206,21 @@ void AuFile::PaintForeground(wxDC &dc)
dc.SetBrush(AUFILE_GREY700);
pos = wxPoint(0, 0);
pos.x = size.x / 2 - 1;
pos.y = size.y - FromDIP(30) - (m_file_edit_mask.GetSize().y - FromDIP(30)) / 2;
pos.y = size.y - FromDIP(30) - (m_file_edit_mask.GetBmpSize().y - FromDIP(30)) / 2;
dc.DrawRectangle(pos.x, pos.y, 2, FromDIP(30));
} else {
// right text
auto sizet = dc.GetTextExtent(cover_text_right);
auto pos = wxPoint(0, 0);
pos.x = (size.x - sizet.x) / 2;
pos.y = (size.y - (m_file_edit_mask.GetSize().y + sizet.y) / 2);
pos.y = (size.y - (m_file_edit_mask.GetBmpSize().y + sizet.y) / 2);
dc.DrawText(cover_text_right, pos);
}
}
if (m_cover) {
dc.SetTextForeground(*wxWHITE);
dc.DrawBitmap(m_file_cover, size.x - m_file_cover.GetSize().x, 0);
dc.DrawBitmap(m_file_cover.bmp(), size.x - m_file_cover.GetBmpSize().x, 0);
dc.SetFont(Label::Body_12);
auto sizet = dc.GetTextExtent(cover_text_cover);
auto pos = wxPoint(0, 0);
@ -229,7 +229,7 @@ void AuFile::PaintForeground(wxDC &dc)
dc.DrawText(cover_text_cover, pos);
}
if (m_hover) { dc.DrawBitmap(m_file_delete, size.x - m_file_delete.GetSize().x - FromDIP(15), FromDIP(15)); }
if (m_hover) { dc.DrawBitmap(m_file_delete.bmp(), size.x - m_file_delete.GetBmpSize().x - FromDIP(15), FromDIP(15)); }
}
void AuFile::on_mouse_enter(wxMouseEvent &evt)
@ -337,7 +337,7 @@ void AuFile::on_mouse_left_up(wxMouseEvent &evt)
auto pos = evt.GetPosition();
// set cover
auto mask_size = m_file_edit_mask.GetSize();
auto mask_size = m_file_edit_mask.GetBmpSize();
auto cover_left = 0;
auto cover_top = size.y - mask_size.y;
auto cover_right = mask_size.x / 2;
@ -353,10 +353,10 @@ void AuFile::on_mouse_left_up(wxMouseEvent &evt)
if (pos.x > rename_left && pos.x < rename_right && pos.y > rename_top && pos.y < rename_bottom) { on_set_rename(); }
// close
auto close_left = size.x - m_file_delete.GetSize().x - FromDIP(15);
auto close_left = size.x - m_file_delete.GetBmpSize().x - FromDIP(15);
auto close_top = FromDIP(15);
auto close_right = size.x - FromDIP(15);
auto close_bottom = m_file_delete.GetSize().y + FromDIP(15);
auto close_bottom = m_file_delete.GetBmpSize().y + FromDIP(15);
if (pos.x > close_left && pos.x < close_right && pos.y > close_top && pos.y < close_bottom) { on_set_delete(); }
}
@ -449,9 +449,9 @@ AuFile::~AuFile() {}
void AuFile::msw_rescale()
{
m_file_cover = create_scaled_bitmap("auxiliary_cover", this, 50);
m_file_edit_mask = create_scaled_bitmap("auxiliary_edit_mask", this, 43);
m_file_delete = create_scaled_bitmap("auxiliary_delete", this, 28);
m_file_cover = ScalableBitmap(this, "auxiliary_cover", 50);
m_file_edit_mask = ScalableBitmap(this, "auxiliary_edit_mask", 43);
m_file_delete = ScalableBitmap(this, "auxiliary_delete", 28);
if (m_type == MODEL_PICTURE) {
if (m_file_path.empty()) { return;}

View file

@ -81,9 +81,9 @@ public:
wxString cover_text_right;
wxString cover_text_cover;
wxBitmap m_file_bitmap;
wxBitmap m_file_cover;
wxBitmap m_file_edit_mask;
wxBitmap m_file_delete;
ScalableBitmap m_file_cover;
ScalableBitmap m_file_edit_mask;
ScalableBitmap m_file_delete;
wxBitmap m_bitmap_excel;
wxBitmap m_bitmap_pdf;

View file

@ -493,6 +493,9 @@ void BBLTopbar::OnFullScreen(wxAuiToolBarEvent& event)
m_frame->Restore();
}
else {
wxDisplay display(wxDisplay::GetFromWindow(this));
auto size = display.GetClientArea().GetSize();
m_frame->SetMaxSize(size + wxSize{16, 16});
m_normalRect = m_frame->GetRect();
m_frame->Maximize();
}
@ -505,17 +508,25 @@ void BBLTopbar::OnCloseFrame(wxAuiToolBarEvent& event)
void BBLTopbar::OnMouseLeftDClock(wxMouseEvent& mouse)
{
wxPoint mouse_pos = ::wxGetMousePosition();
// check whether mouse is not on any tool item
if (this->FindToolByCurrentPosition() != NULL &&
this->FindToolByCurrentPosition() != m_title_item) {
mouse.Skip();
return;
}
#ifdef __W1XMSW__
::PostMessage((HWND) m_frame->GetHandle(), WM_NCLBUTTONDBLCLK, HTCAPTION, MAKELPARAM(mouse_pos.x, mouse_pos.y));
return;
#endif // __WXMSW__
if (m_frame->IsMaximized()) {
m_frame->Restore();
}
else {
wxDisplay display(wxDisplay::GetFromWindow(this));
auto size = display.GetClientArea().GetSize();
m_frame->SetMaxSize(size + wxSize{16, 16});
m_normalRect = m_frame->GetRect();
m_frame->Maximize();
}
@ -561,16 +572,23 @@ void BBLTopbar::OnMouseLeftDown(wxMouseEvent& event)
wxPoint frame_pos = m_frame->GetScreenPosition();
m_delta = mouse_pos - frame_pos;
if (FindToolByCurrentPosition() == NULL)
if (FindToolByCurrentPosition() == NULL
|| this->FindToolByCurrentPosition() == m_title_item)
{
CaptureMouse();
#ifdef __WXMSW__
ReleaseMouse();
::PostMessage((HWND) m_frame->GetHandle(), WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(mouse_pos.x, mouse_pos.y));
return;
#endif // __WXMSW__
}
event.Skip();
}
void BBLTopbar::OnMouseLeftUp(wxMouseEvent& event)
{
wxPoint mouse_pos = ::wxGetMousePosition();
if (HasCapture())
{
ReleaseMouse();
@ -581,7 +599,8 @@ void BBLTopbar::OnMouseLeftUp(wxMouseEvent& event)
void BBLTopbar::OnMouseMotion(wxMouseEvent& event)
{
wxPoint mouse_pos = event.GetPosition();
wxPoint mouse_pos = ::wxGetMousePosition();
if (!HasCapture()) {
//m_frame->OnMouseMotion(event);
@ -591,7 +610,6 @@ void BBLTopbar::OnMouseMotion(wxMouseEvent& event)
if (event.Dragging() && event.LeftIsDown())
{
wxPoint mouse_pos = ::wxGetMousePosition();
// leave max state and adjust position
if (m_frame->IsMaximized()) {
wxRect rect = m_frame->GetRect();

View file

@ -148,8 +148,6 @@ CalibrationDialog::CalibrationDialog(Plater *plater)
Layout();
Fit();
Bind(wxEVT_CLOSE_WINDOW, [this](wxCloseEvent &evt) { Hide(); });
m_calibration_btn->Bind(wxEVT_LEFT_DOWN, &CalibrationDialog::on_start_calibration, this);
}

View file

@ -139,10 +139,10 @@ CameraItem::CameraItem(wxWindow *parent,std::string off_normal, std::string on_n
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);
m_bitmap_on_normal = ScalableBitmap(this, on_normal, 20);
m_bitmap_off_normal = ScalableBitmap(this, off_normal, 20);
m_bitmap_on_hover = ScalableBitmap(this, on_hover, 20);
m_bitmap_off_hover = ScalableBitmap(this, off_hover, 20);
SetSize(wxSize(FromDIP(20), FromDIP(20)));
SetMinSize(wxSize(FromDIP(20), FromDIP(20)));
@ -208,16 +208,16 @@ 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));
dc.DrawBitmap(m_bitmap_on_hover.bmp(), wxPoint((GetSize().x - m_bitmap_on_hover.GetBmpSize().x) / 2, (GetSize().y - m_bitmap_on_hover.GetBmpSize().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));
dc.DrawBitmap(m_bitmap_on_normal.bmp(), wxPoint((GetSize().x - m_bitmap_on_normal.GetBmpSize().x) / 2, (GetSize().y - m_bitmap_on_normal.GetBmpSize().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));
dc.DrawBitmap(m_bitmap_off_hover.bmp(), wxPoint((GetSize().x - m_bitmap_off_hover.GetBmpSize().x) / 2, (GetSize().y - m_bitmap_off_hover.GetBmpSize().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));
dc.DrawBitmap(m_bitmap_off_normal.bmp(), wxPoint((GetSize().x - m_bitmap_off_normal.GetBmpSize().x) / 2, (GetSize().y - m_bitmap_off_normal.GetBmpSize().y) / 2));
}
}
}

View file

@ -59,10 +59,10 @@ public:
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;
ScalableBitmap m_bitmap_on_normal;
ScalableBitmap m_bitmap_on_hover;
ScalableBitmap m_bitmap_off_normal;
ScalableBitmap m_bitmap_off_hover;
void msw_rescale();
void set_switch(bool is_on);

View file

@ -291,17 +291,6 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con
is_msg_dlg_already_exist = false;
}
//BBS
if (config->opt_bool("timelapse_no_toolhead") && !is_timelapse_wipe_tower_already_prompted) {
wxString msg_text = _(L("When recording timelapse without toolhead, it is recommended to add a \"Timelapse Wipe Tower\" \n"
"by right-click the empty position of build plate and choose \"Add Primitive\"->\"Timelapse Wipe Tower\".\n"));
MessageDialog dialog(m_msg_dlg_parent, msg_text, "", wxICON_WARNING | wxOK);
is_msg_dlg_already_exist = true;
dialog.ShowModal();
is_msg_dlg_already_exist = false;
is_timelapse_wipe_tower_already_prompted = true;
}
// BBS
int filament_cnt = wxGetApp().preset_bundle->filament_presets.size();
#if 0

View file

@ -21,7 +21,6 @@ namespace GUI {
class ConfigManipulation
{
bool is_msg_dlg_already_exist{ false };
bool is_timelapse_wipe_tower_already_prompted{false}; // BBS
bool m_is_initialized_support_material_overhangs_queried{ false };
bool m_support_material_overhangs_queried{ false };

View file

@ -33,6 +33,7 @@ ConnectPrinterDialog::ConnectPrinterDialog(wxWindow *parent, wxWindowID id, cons
sizer_connect = new wxBoxSizer(wxHORIZONTAL);
m_textCtrl_code = new TextInput(this, wxEmptyString);
m_textCtrl_code->GetTextCtrl()->SetMaxLength(10);
m_textCtrl_code->SetFont(Label::Body_14);
m_textCtrl_code->SetCornerRadius(FromDIP(5));
m_textCtrl_code->SetSize(wxSize(FromDIP(330), FromDIP(40)));
@ -132,6 +133,12 @@ void ConnectPrinterDialog::on_input_enter(wxCommandEvent& evt)
void ConnectPrinterDialog::on_button_confirm(wxCommandEvent &event)
{
wxString code = m_textCtrl_code->GetTextCtrl()->GetValue();
for (char c : code) {
if (!('0' <= c && c <= '9' || 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z')) {
show_error(this, _L("Invalid input."));
return;
}
}
if (m_obj) {
m_obj->set_access_code(code.ToStdString());
}

View file

@ -148,6 +148,47 @@ bool AmsTray::is_tray_info_ready()
return true;
}
bool AmsTray::is_unset_third_filament()
{
if (this->is_bbl)
return false;
if (color.empty() || type.empty())
return true;
return false;
}
std::string AmsTray::get_display_filament_type()
{
if (type == "PLA-S")
return "Support W";
else if (type == "PA-S")
return "Support G";
else
return type;
return type;
}
std::string AmsTray::get_filament_type()
{
if (type == "Support W") {
return "PLA-S";
} else if (type == "Support G") {
return "PA-S";
} else if (type == "Support") {
if (setting_id == "GFS00") {
type = "PLA-S";
} else if (setting_id == "GFS01") {
type = "PA-S";
} else {
return "PLA-S";
}
} else {
return type;
}
return type;
}
bool HMSItem::parse_hms_info(unsigned attr, unsigned code)
{
bool result = true;
@ -336,6 +377,7 @@ MachineObject::MachineObject(NetworkAgent* agent, std::string name, std::string
/* printing */
mc_print_stage = 0;
mc_print_error_code = 0;
print_error = 0;
mc_print_line_number = 0;
mc_print_percent = 0;
mc_print_sub_stage = 0;
@ -350,6 +392,13 @@ MachineObject::~MachineObject()
subtask_ = nullptr;
}
if (get_slice_info_thread) {
if (get_slice_info_thread->joinable()) {
get_slice_info_thread->join();
get_slice_info_thread = nullptr;
}
}
if (slice_info) {
delete slice_info;
slice_info = nullptr;
@ -614,7 +663,7 @@ int MachineObject::ams_filament_mapping(std::vector<FilamentInfo> filaments, std
if (tray->second->is_tray_info_ready()) {
FilamentInfo info;
info.color = tray->second->color;
info.type = tray->second->type;
info.type = tray->second->get_filament_type();
info.id = tray_index;
tray_filaments.emplace(std::make_pair(tray_index, info));
}
@ -631,7 +680,7 @@ int MachineObject::ams_filament_mapping(std::vector<FilamentInfo> filaments, std
info.id = atoi(tray_it->first.c_str()) + atoi(it->first.c_str()) * 4;
info.tray_id = atoi(tray_it->first.c_str()) + atoi(it->first.c_str()) * 4;
info.color = tray_it->second->color;
info.type = tray_it->second->type;
info.type = tray_it->second->get_filament_type();
}
else {
info.id = -1;
@ -647,7 +696,29 @@ int MachineObject::ams_filament_mapping(std::vector<FilamentInfo> filaments, std
for (int i = 0; i < filaments.size(); i++) {
FilamentInfo info;
info.id = filaments[i].id;
info.tray_id = filaments[i].id;
int ams_id = filaments[i].id / 4;
auto ams_it = amsList.find(std::to_string(ams_id));
if (ams_it == amsList.end()) {
info.tray_id = -1;
info.mapping_result = (int)MappingResult::MAPPING_RESULT_EXCEED;
} else {
info.tray_id = filaments[i].id;
int tray_id = filaments[i].id % 4;
auto tray_it = ams_it->second->trayList.find(std::to_string(tray_id));
if (tray_it != ams_it->second->trayList.end()) {
if (!tray_it->second->is_exists || tray_it->second->is_unset_third_filament()) {
;
} else {
if (filaments[i].type == tray_it->second->get_filament_type()) {
info.color = tray_it->second->color;
info.type = tray_it->second->get_filament_type();
} else {
info.tray_id = -1;
info.mapping_result = (int)MappingResult::MAPPING_RESULT_TYPE_MISMATCH;
}
}
}
}
result.push_back(info);
}
return 1;
@ -807,11 +878,12 @@ bool MachineObject::is_valid_mapping_result(std::vector<FilamentInfo>& result)
for (int i = 0; i < result.size(); i++) {
// invalid mapping result
if (result[i].tray_id < 0)
return false;
is_valid = false;
else {
int ams_id = result[i].tray_id / 4;
if (amsList.find(std::to_string(ams_id)) == amsList.end()) {
return false;
result[i].tray_id = -1;
is_valid = false;
}
}
}
@ -820,12 +892,32 @@ bool MachineObject::is_valid_mapping_result(std::vector<FilamentInfo>& result)
return true;
}
bool MachineObject::is_mapping_exceed_filament(std::vector<FilamentInfo> & result, int &exceed_index)
{
bool is_exceed = false;
for (int i = 0; i < result.size(); i++) {
int ams_id = result[i].tray_id / 4;
if (amsList.find(std::to_string(ams_id)) == amsList.end()) {
exceed_index = result[i].tray_id;
result[i].tray_id = -1;
is_exceed = true;
break;
}
if (result[i].mapping_result == MappingResult::MAPPING_RESULT_EXCEED) {
exceed_index = result[i].id;
is_exceed = true;
break;
}
}
return is_exceed;
}
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;
result[i].mapping_result = 0;
}
}
@ -1387,6 +1479,31 @@ int MachineObject::command_ipcam_timelapse(bool on_off)
return this->publish_json(j.dump());
}
int MachineObject::command_xcam_control(std::string module_name, bool on_off, bool print_halt)
{
json j;
j["xcam"]["command"] = "xcam_control_set";
j["xcam"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++);
j["xcam"]["module_name"] = module_name;
j["xcam"]["control"] = on_off;
j["xcam"]["print_halt"] = print_halt;
return this->publish_json(j.dump());
}
int MachineObject::command_xcam_control_first_layer_inspector(bool on_off, bool print_halt)
{
xcam_first_layer_inspector = on_off;
xcam_first_layer_hold_count = HOLD_COUNT_MAX;
return command_xcam_control("first_layer_inspector", on_off, print_halt);
}
int MachineObject::command_xcam_control_spaghetti_detector(bool on_off, bool print_halt)
{
xcam_spaghetti_detector = on_off;
xcam_spaghetti_print_halt = print_halt;
xcam_spaghetti_hold_count = HOLD_COUNT_MAX;
return command_xcam_control("spaghetti_detector", on_off, print_halt);
}
void MachineObject::set_bind_status(std::string status)
{
@ -1680,8 +1797,6 @@ int MachineObject::parse_json(std::string payload)
mc_print_stage = jj["mc_print_stage"].get<int>();
}
if (jj.contains("mc_print_error_code")) {
if (jj["mc_print_error_code"].is_string())
mc_print_error_code = atoi(jj["mc_print_error_code"].get<std::string>().c_str());
if (jj["mc_print_error_code"].is_number())
mc_print_error_code = jj["mc_print_error_code"].get<int>();
@ -1690,6 +1805,11 @@ int MachineObject::parse_json(std::string payload)
if (jj["mc_print_line_number"].is_string() && !jj["mc_print_line_number"].is_null())
mc_print_line_number = atoi(jj["mc_print_line_number"].get<std::string>().c_str());
}
if (jj.contains("print_error")) {
if (jj["print_error"].is_number())
print_error = jj["print_error"].get<int>();
}
#pragma endregion
#pragma region print_task
@ -1750,6 +1870,8 @@ int MachineObject::parse_json(std::string payload)
}
}
#pragma endregion
#pragma region status
@ -1967,6 +2089,32 @@ int MachineObject::parse_json(std::string payload)
catch (...) {
;
}
try {
if (jj.contains("xcam")) {
if (xcam_first_layer_hold_count > 0)
xcam_first_layer_hold_count--;
else {
if (jj["xcam"].contains("first_layer_inspector")) {
xcam_first_layer_inspector = jj["xcam"]["first_layer_inspector"].get<bool>();
}
}
if (xcam_spaghetti_hold_count > 0) {
xcam_spaghetti_hold_count--;
} else {
if (jj["xcam"].contains("spaghetti_detector")) {
xcam_spaghetti_detector = jj["xcam"]["spaghetti_detector"].get<bool>();
}
if (jj["xcam"].contains("print_halt")) {
xcam_spaghetti_print_halt = jj["xcam"]["print_halt"].get<bool>();
}
}
}
}
catch (...) {
;
}
#pragma endregion
#pragma region hms
@ -2112,9 +2260,10 @@ int MachineObject::parse_json(std::string payload)
curr_tray->setting_id = (*tray_it)["tray_info_idx"].get<std::string>();
std::string type = (*tray_it)["tray_type"].get<std::string>();
if (curr_tray->setting_id == "GFS00") {
curr_tray->type = "Support W";
} else if (curr_tray->setting_id == "GFS01") {
curr_tray->type = "Support G";
curr_tray->type = "PLA-S";
}
else if (curr_tray->setting_id == "GFS01") {
curr_tray->type = "PA-S";
} else {
curr_tray->type = type;
}
@ -2243,6 +2392,18 @@ int MachineObject::parse_json(std::string payload)
BOOST_LOG_TRIVIAL(warning) << "ams_filament_setting, can not find in amsList, ams_id=" << ams_id;
}
}
} else if (jj["command"].get<std::string>() == "xcam_control_set") {
if (jj.contains("module_name") && jj.contains("control")) {
if (jj["module_name"].get<std::string>() == "first_layer_inspector") {
xcam_first_layer_inspector = jj["control"].get<bool>();
xcam_first_layer_hold_count = HOLD_COUNT_MAX;
} else if (jj["module_name"].get<std::string>() == "spaghetti_detector") {
xcam_spaghetti_detector = jj["control"].get<bool>();
xcam_spaghetti_hold_count = HOLD_COUNT_MAX;
if (jj.contains("print_halt"))
xcam_spaghetti_print_halt = jj["print_halt"].get<bool>();
}
}
}
}
}
@ -2352,7 +2513,7 @@ void MachineObject::update_slice_info(std::string project_id, std::string profil
BOOST_LOG_TRIVIAL(trace) << "slice_info: start";
slice_info = new BBLSliceInfo();
auto get_slice_info_thread = boost::thread([this, project_id, profile_id, subtask_id, plate_idx] {
get_slice_info_thread = new boost::thread([this, project_id, profile_id, subtask_id, plate_idx] {
int plate_index = -1;
if (!m_agent) return;
@ -2360,6 +2521,8 @@ void MachineObject::update_slice_info(std::string project_id, std::string profil
if (plate_idx >= 0) {
plate_index = plate_idx;
} else {
if (subtask_id.compare("0") == 0)
return;
m_agent->get_task_plate_index(subtask_id, &plate_index);
}
@ -2686,6 +2849,7 @@ void DeviceManager::clean_user_info()
BOOST_LOG_TRIVIAL(trace) << "DeviceManager::clean_user_info";
// reset selected_machine
selected_machine = "";
local_selected_machine = "";
// clean access code
for (auto it = userMachineList.begin(); it != userMachineList.end(); it++) {

View file

@ -21,6 +21,8 @@
#define FILAMENT_DEF_TEMP 220
#define FILAMENT_MIN_TEMP 120
#define HOLD_COUNT_MAX 3
inline int correct_filament_temperature(int filament_temp)
{
int temp = std::min(filament_temp, FILAMENT_MAX_TEMP);
@ -159,11 +161,14 @@ public:
AmsStep step_state;
AmsRfidState rfid_state;
void set_hold_count() { hold_count = 3; }
void set_hold_count() { hold_count = HOLD_COUNT_MAX; }
void update_color_from_str(std::string color);
wxColour get_color();
bool is_tray_info_ready();
bool is_unset_third_filament();
std::string get_display_filament_type();
std::string get_filament_type();
};
@ -362,6 +367,8 @@ public:
int ams_filament_mapping(std::vector<FilamentInfo> filaments, std::vector<FilamentInfo> &result, std::vector<int> exclude_id = std::vector<int>());
bool is_valid_mapping_result(std::vector<FilamentInfo>& result);
// exceed index start with 0
bool is_mapping_exceed_filament(std::vector<FilamentInfo>& result, int &exceed_index);
void reset_mapping_result(std::vector<FilamentInfo>& result);
@ -426,6 +433,7 @@ public:
int mc_left_time; /* left time in seconds */
int last_mc_print_stage;
bool is_system_printing();
int print_error;
std::vector<int> stage_list_info;
int stage_curr = 0;
@ -452,6 +460,11 @@ public:
bool camera_recording { false };
bool camera_timelapse { false };
bool camera_has_sdcard { false };
bool xcam_first_layer_inspector { false };
int xcam_first_layer_hold_count = 0;
bool xcam_spaghetti_detector { false };
bool xcam_spaghetti_print_halt{ false };
int xcam_spaghetti_hold_count = 0;
/* HMS */
std::vector<HMSItem> hms_list;
@ -468,6 +481,8 @@ public:
std::string task_id_;
std::string subtask_id_;
BBLSliceInfo* slice_info {nullptr};
boost::thread* get_slice_info_thread { nullptr };
int plate_index { -1 };
std::string m_gcode_file;
int gcode_file_prepare_percent = 0;
@ -525,6 +540,9 @@ public:
// camera control
int command_ipcam_record(bool on_off);
int command_ipcam_timelapse(bool on_off);
int command_xcam_control(std::string module_name, bool on_off, bool print_halt);
int command_xcam_control_first_layer_inspector(bool on_off, bool print_halt);
int command_xcam_control_spaghetti_detector(bool on_off, bool print_halt);
/* common apis */
inline bool is_local() { return !dev_ip.empty(); }

View file

@ -317,25 +317,14 @@ wxWindow* BitmapChoiceRenderer::CreateEditorCtrl(wxWindow* parent, wxRect labelR
c_editor->SetSelection(atoi(data.GetText().c_str()) - 1);
#ifndef _WIN32
c_editor->Bind(wxEVT_COMBOBOX, [this, c_editor](wxCommandEvent& evt) {
#ifdef __linux__
c_editor->Bind(wxEVT_COMBOBOX, [this](wxCommandEvent& evt) {
// to avoid event propagation to other sidebar items
evt.StopPropagation();
// FinishEditing grabs new selection and triggers config update. We better call
// it explicitly, automatic update on KILL_FOCUS didn't work on Linux.
c_editor->SetClientData(this);
this->FinishEditing();
});
c_editor->Bind(wxEVT_COMBOBOX_DROPDOWN, [this, c_editor](wxCommandEvent& evt) {
c_editor->SetClientData(this);
this->FinishEditing();
});
c_editor->Bind(wxEVT_KILL_FOCUS, [this, c_editor](wxFocusEvent& evt) {
if (!c_editor->GetDropDown().IsShown() && c_editor->GetClientData() == nullptr) { // TODO: Fix called twice
c_editor->SetClientData(this);
this->FinishEditing();
}
}, c_editor->GetId());
#else
// to avoid event propagation to other sidebar items
c_editor->Bind(wxEVT_COMBOBOX, [](wxCommandEvent& evt) { evt.StopPropagation(); });

View file

@ -195,22 +195,21 @@ void Field::toggle(bool en) { en && !m_opt.readonly ? enable() : disable(); }
wxString Field::get_tooltip_text(const wxString &default_string)
{
wxString tooltip_text("");
//wxString tooltip = _(m_opt.tooltip);
// edit_tooltip(tooltip);
#ifdef NDEBUG
wxString tooltip = _(m_opt.tooltip);
edit_tooltip(tooltip);
// std::string opt_id = m_opt_id;
// auto hash_pos = opt_id.find("#");
// if (hash_pos != std::string::npos) {
// opt_id.replace(hash_pos, 1,"[");
// opt_id += "]";
// }
//if (tooltip.length() > 0)
// tooltip_text = tooltip + "\n" + _(L("default value")) + "\t: " +
// (boost::iends_with(opt_id, "_gcode") ? "\n" : "") + default_string +
// (boost::iends_with(opt_id, "_gcode") ? "" : "\n") +
// _(L("parameter name")) + "\t: " + opt_id;
std::string opt_id = m_opt_id;
auto hash_pos = opt_id.find("#");
if (hash_pos != std::string::npos) {
opt_id.replace(hash_pos, 1,"[");
opt_id += "]";
}
if (tooltip.length() > 0)
tooltip_text = tooltip + "\n" +
_(L("parameter name")) + "\t: " + opt_id;
#endif
return tooltip_text;
}
@ -374,9 +373,17 @@ void Field::get_value_by_opt_type(wxString& str, const bool check_value/* = true
if (x_str.ToDouble(&x) && thumbnail.HasMoreTokens()) {
wxString y_str = thumbnail.GetNextToken();
if (y_str.ToDouble(&y) && !thumbnail.HasMoreTokens()) {
if (0 < x && x < 1000 && 0 < y && y < 1000) {
out_values.push_back(Vec2d(x, y));
continue;
if (m_opt_id == "bed_exclude_area") {
if (0 <= x && x <= 256 && 0 <= y && y <= 256) {
out_values.push_back(Vec2d(x, y));
continue;
}
}
else {
if (0 < x && x < 1000 && 0 < y && y < 1000) {
out_values.push_back(Vec2d(x, y));
continue;
}
}
out_of_range_val = true;
break;

View file

@ -1070,7 +1070,6 @@ void GCodeViewer::reset()
}
m_paths_bounding_box = BoundingBoxf3();
m_max_bounding_box = BoundingBoxf3();
m_shell_bounding_box = BoundingBoxf3();
m_max_print_height = 0.0f;
m_tools.m_tool_colors = std::vector<Color>();
m_tools.m_tool_visibles = std::vector<bool>();
@ -4423,7 +4422,7 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
};
const bool visible = m_buffers[buffer_id(type)].visible;
if (type == EMoveType::Travel) {
//TODO display travel time, salt.wei
//TODO display travel time
append_option_item_with_type(type, Travel_Colors[0], _u8L("Travel"), visible);
}
else if (type == EMoveType::Seam)

View file

@ -27,6 +27,7 @@
#include "slic3r/Utils/UndoRedo.hpp"
#include "slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp"
#include "slic3r/GUI/BitmapCache.hpp"
#include "slic3r/Utils/MacDarkMode.hpp"
#include "GUI_App.hpp"
#include "GUI_ObjectList.hpp"
@ -739,6 +740,15 @@ void GLCanvas3D::set_as_dirty()
m_dirty = true;
}
const float GLCanvas3D::get_scale() const
{
#if ENABLE_RETINA_GL
return m_retina_helper->get_scale_factor();
#else
return 1.0f;
#endif
}
unsigned int GLCanvas3D::get_volumes_count() const
{
return (unsigned int)m_volumes.volumes.size();
@ -2133,8 +2143,15 @@ void GLCanvas3D::bind_event_handlers()
m_canvas->Bind(wxEVT_RIGHT_DCLICK, &GLCanvas3D::on_mouse, this);
m_canvas->Bind(wxEVT_PAINT, &GLCanvas3D::on_paint, this);
m_canvas->Bind(wxEVT_SET_FOCUS, &GLCanvas3D::on_set_focus, this);
m_canvas->Bind(wxEVT_KILL_FOCUS, &GLCanvas3D::on_kill_focus, this);
m_event_handlers_bound = true;
m_canvas->Bind(wxEVT_GESTURE_PAN, &GLCanvas3D::on_gesture, this);
m_canvas->Bind(wxEVT_GESTURE_ZOOM, &GLCanvas3D::on_gesture, this);
m_canvas->Bind(wxEVT_GESTURE_ROTATE, &GLCanvas3D::on_gesture, this);
m_canvas->EnableTouchEvents(wxTOUCH_ZOOM_GESTURE | wxTOUCH_ROTATE_GESTURE);
#if __WXOSX__
initGestures(m_canvas->GetHandle(), m_canvas); // for UIPanGestureRecognizer allowedScrollTypesMask
#endif
}
}
@ -2163,9 +2180,11 @@ void GLCanvas3D::unbind_event_handlers()
m_canvas->Unbind(wxEVT_RIGHT_DCLICK, &GLCanvas3D::on_mouse, this);
m_canvas->Unbind(wxEVT_PAINT, &GLCanvas3D::on_paint, this);
m_canvas->Unbind(wxEVT_SET_FOCUS, &GLCanvas3D::on_set_focus, this);
m_canvas->Unbind(wxEVT_KILL_FOCUS, &GLCanvas3D::on_kill_focus, this);
m_event_handlers_bound = false;
m_canvas->Unbind(wxEVT_GESTURE_PAN, &GLCanvas3D::on_gesture, this);
m_canvas->Unbind(wxEVT_GESTURE_ZOOM, &GLCanvas3D::on_gesture, this);
m_canvas->Unbind(wxEVT_GESTURE_ROTATE, &GLCanvas3D::on_gesture, this);
}
}
@ -2935,6 +2954,40 @@ std::string format_mouse_event_debug_message(const wxMouseEvent &evt)
}
#endif /* SLIC3R_DEBUG_MOUSE_EVENTS */
void GLCanvas3D::on_gesture(wxGestureEvent &evt)
{
if (!m_initialized || !_set_current())
return;
auto & camera = wxGetApp().plater()->get_camera();
if (evt.GetEventType() == wxEVT_GESTURE_PAN) {
auto p = evt.GetPosition();
auto d = static_cast<wxPanGestureEvent&>(evt).GetDelta();
float z = 0;
const Vec3d &p2 = _mouse_to_3d({p.x, p.y}, &z);
const Vec3d &p1 = _mouse_to_3d({p.x - d.x, p.y - d.y}, &z);
camera.set_target(camera.get_target() + p2 - p1);
} else if (evt.GetEventType() == wxEVT_GESTURE_ZOOM) {
static float zoom_start = 1;
if (evt.IsGestureStart())
zoom_start = camera.get_zoom();
camera.set_zoom(zoom_start * static_cast<wxZoomGestureEvent&>(evt).GetZoomFactor());
} else if (evt.GetEventType() == wxEVT_GESTURE_ROTATE) {
PartPlate* plate = wxGetApp().plater()->get_partplate_list().get_curr_plate();
bool rotate_limit = current_printer_technology() != ptSLA;
static double last_rotate = 0;
if (evt.IsGestureStart())
last_rotate = 0;
auto rotate = static_cast<wxRotateGestureEvent&>(evt).GetRotationAngle() - last_rotate;
last_rotate += rotate;
if (plate)
camera.rotate_on_sphere_with_target(-rotate, 0, rotate_limit, plate->get_bounding_box().center());
else
camera.rotate_on_sphere(-rotate, 0, rotate_limit);
}
m_dirty = true;
}
void GLCanvas3D::on_mouse(wxMouseEvent& evt)
{
if (!m_initialized || !_set_current())
@ -3136,7 +3189,9 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
return;
}
if (evt.LeftDown() && (evt.ShiftDown() || evt.AltDown()) && m_picking_enabled) {
// BBS: define Alt key to enable volume selection mode
m_selection.set_volume_selection_mode(evt.AltDown() ? Selection::Volume : Selection::Instance);
if (evt.LeftDown() && evt.ShiftDown() && m_picking_enabled) {
if (m_gizmos.get_current_type() != GLGizmosManager::SlaSupports
&& m_gizmos.get_current_type() != GLGizmosManager::FdmSupports
&& m_gizmos.get_current_type() != GLGizmosManager::Seam
@ -3484,19 +3539,14 @@ void GLCanvas3D::on_set_focus(wxFocusEvent& evt)
{
m_tooltip_enabled = false;
if (m_canvas_type == ECanvasType::CanvasPreview) {
// update thumbnails and update plate toolbar
wxGetApp().plater()->update_platplate_thumbnails();
_update_imgui_select_plate_toolbar();
}
_refresh_if_shown_on_screen();
m_tooltip_enabled = true;
}
void GLCanvas3D::on_kill_focus(wxFocusEvent& evt)
{
if (m_canvas_type == ECanvasType::CanvasView3D) {
wxGetApp().plater()->update_platplate_thumbnails();
}
}
Size GLCanvas3D::get_canvas_size() const
{
int w = 0;
@ -4363,7 +4413,7 @@ bool GLCanvas3D::_render_orient_menu(float left, float right, float bottom, floa
//now change to left_up as {0,0}, and top is 0, bottom is canvas_h
#if BBS_TOOLBAR_ON_TOP
const float x = left * float(wxGetApp().plater()->get_camera().get_zoom()) + 0.5f * canvas_w;
ImGuiWrapper::push_toolbar_style();
ImGuiWrapper::push_toolbar_style(get_scale());
imgui->set_next_window_pos(x, m_main_toolbar.get_height(), ImGuiCond_Always, 0.5f, 0.0f);
#else
const float x = canvas_w - m_main_toolbar.get_width();
@ -4459,7 +4509,7 @@ bool GLCanvas3D::_render_arrange_menu(float left, float right, float bottom, flo
#endif
//BBS
ImGuiWrapper::push_toolbar_style();
ImGuiWrapper::push_toolbar_style(get_scale());
imgui->begin(_L("Arrange options"), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar);
@ -5026,7 +5076,7 @@ bool GLCanvas3D::_init_main_toolbar()
item.name = "add";
item.icon_filename = "toolbar_open.svg";
item.tooltip = _utf8(L("Add"));
item.tooltip = _utf8(L("Add")) + " [" + GUI::shortkey_ctrl_prefix() + "I]";
item.sprite_id = 0;
item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_ADD)); };
item.enabling_callback = []()->bool {return wxGetApp().plater()->can_add_model(); };
@ -5064,7 +5114,7 @@ bool GLCanvas3D::_init_main_toolbar()
item.name = "arrange";
item.icon_filename = "toolbar_arrange.svg";
item.tooltip = _utf8(L("Auto arrange"));
item.tooltip = _utf8(L("Arrange all objects")) + " [A]\n" + _utf8(L("Arrange objects on selected plates")) + " [Shift+A]";
item.sprite_id++;
item.left.action_callback = []() {};
item.enabling_callback = []()->bool { return wxGetApp().plater()->can_arrange(); };
@ -6404,7 +6454,9 @@ void GLCanvas3D::_render_paint_toolbar() const
for (auto filament_name : preset_bundle->filament_presets) {
for (auto iter = preset_bundle->filaments.lbegin(); iter != preset_bundle->filaments.end(); iter++) {
if (filament_name.compare(iter->name) == 0) {
filament_types.push_back(iter->config.get_filament_type());
std::string display_filament_type;
iter->config.get_filament_type(display_filament_type);
filament_types.push_back(display_filament_type);
}
}
}
@ -6541,7 +6593,7 @@ void GLCanvas3D::_render_explosion_control() const
ImGuiWrapper* imgui = wxGetApp().imgui();
ImGuiWrapper::push_toolbar_style();
ImGuiWrapper::push_toolbar_style(get_scale());
auto canvas_w = float(get_canvas_size().get_width());
auto canvas_h = float(get_canvas_size().get_height());
@ -6611,7 +6663,7 @@ void GLCanvas3D::_render_assemble_info() const
ImGui::PushFont(font);
ImGui::PopFont();
imgui->set_next_window_pos(canvas_w - window_width, 0.0f, ImGuiCond_Always, 0, 0);
ImGuiWrapper::push_toolbar_style();
ImGuiWrapper::push_toolbar_style(get_scale());
imgui->begin(_L("Assembly Info"), ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse);
font->Scale = origScale;
ImGui::PushFont(font);

View file

@ -361,7 +361,7 @@ public:
// float distance_seq_print = 6.; // Used when sequential print is ON
// float distance_sla = 6.;
float accuracy = 0.65f; // Unused currently
bool enable_rotation = true;
bool enable_rotation = false;
bool allow_multi_materials_on_same_plate = true;
bool avoid_extrusion_cali_region = true;
//BBS: add more arrangeSettings
@ -600,6 +600,7 @@ public:
const GLVolumeCollection& get_volumes() const { return m_volumes; }
void reset_volumes();
ModelInstanceEPrintVolumeState check_volumes_outside_state() const;
const float get_scale() const;
//BBS
GCodeViewer& get_gcode_viewer() { return m_gcode_viewer; }
@ -765,9 +766,9 @@ public:
void on_timer(wxTimerEvent& evt);
void on_render_timer(wxTimerEvent& evt);
void on_mouse(wxMouseEvent& evt);
void on_gesture(wxGestureEvent& evt);
void on_paint(wxPaintEvent& evt);
void on_set_focus(wxFocusEvent& evt);
void on_kill_focus(wxFocusEvent& evt);
Size get_canvas_size() const;
Vec2d get_local_mouse_position() const;
@ -909,6 +910,10 @@ public:
bool is_object_sinking(int object_idx) const;
// Convert the screen space coordinate to an object space coordinate.
// If the Z screen space coordinate is not provided, a depth buffer value is substituted.
Vec3d _mouse_to_3d(const Point& mouse_pos, float* z = nullptr);
private:
bool _is_shown_on_screen() const;
@ -981,10 +986,6 @@ private:
void _update_volumes_hover_state();
// Convert the screen space coordinate to an object space coordinate.
// If the Z screen space coordinate is not provided, a depth buffer value is substituted.
Vec3d _mouse_to_3d(const Point& mouse_pos, float* z = nullptr);
// Convert the screen space coordinate to world coordinate on the bed.
Vec3d _mouse_to_bed_3d(const Point& mouse_pos);

View file

@ -197,7 +197,7 @@ void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt
}
break;
case coPoints:{
if (opt_key == "printable_area") {
if (opt_key == "printable_area" || opt_key == "bed_exclude_area") {
config.option<ConfigOptionPoints>(opt_key)->values = boost::any_cast<std::vector<Vec2d>>(value);
break;
}

View file

@ -187,9 +187,9 @@ public:
scale_bitmap(m_main_bitmap, m_scale);
// init constant texts and scale fonts
m_constant_text.init(get_default_font(this));
m_constant_text.init(Label::Body_16);
scale_font(m_constant_text.title_font, 2.0f);
scale_font(m_constant_text.version_font, 1.5f);
scale_font(m_constant_text.version_font, 1.2f);
// this font will be used for the action string
m_action_font = m_constant_text.credits_font;
@ -930,23 +930,32 @@ void GUI_App::post_init()
bool switch_to_3d = false;
if (!this->init_params->input_files.empty()) {
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", init with input files, size %1%, input_gcode %2%")
%this->init_params->input_files.size() %this->init_params->input_gcode;
switch_to_3d = true;
mainframe->select_tab(size_t(MainFrame::tp3DEditor));
plater_->select_view_3D("3D");
const std::vector<size_t> res = this->plater()->load_files(this->init_params->input_files);
if (!res.empty()) {
if (this->init_params->input_files.size() == 1) {
// Update application titlebar when opening a project file
const std::string& filename = this->init_params->input_files.front();
//BBS: remove amf logic as project
if (boost::algorithm::iends_with(filename, ".3mf"))
this->plater()->set_project_filename(from_u8(filename));
if (this->init_params->input_gcode) {
mainframe->select_tab(size_t(MainFrame::tp3DEditor));
plater_->select_view_3D("3D");
this->plater()->load_gcode(from_u8(this->init_params->input_files.front()));
}
else {
mainframe->select_tab(size_t(MainFrame::tp3DEditor));
plater_->select_view_3D("3D");
const std::vector<size_t> res = this->plater()->load_files(this->init_params->input_files);
if (!res.empty()) {
if (this->init_params->input_files.size() == 1) {
// Update application titlebar when opening a project file
const std::string& filename = this->init_params->input_files.front();
//BBS: remove amf logic as project
if (boost::algorithm::iends_with(filename, ".3mf"))
this->plater()->set_project_filename(from_u8(filename));
}
}
}
}
#if BBL_HAS_FIRST_PAGE
if (!switch_to_3d) {
BOOST_LOG_TRIVIAL(info) << "begin load_gl_resources";
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", begin load_gl_resources";
mainframe->Freeze();
plater_->canvas3D()->enable_render(false);
mainframe->select_tab(size_t(MainFrame::tp3DEditor));
@ -954,26 +963,26 @@ void GUI_App::post_init()
//BBS init the opengl resource here
Size canvas_size = plater_->canvas3D()->get_canvas_size();
wxGetApp().imgui()->set_display_size(static_cast<float>(canvas_size.get_width()), static_cast<float>(canvas_size.get_height()));
BOOST_LOG_TRIVIAL(info) << "start to init opengl";
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", start to init opengl";
wxGetApp().init_opengl();
BOOST_LOG_TRIVIAL(info) << "finished init opengl";
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", finished init opengl";
plater_->canvas3D()->init();
BOOST_LOG_TRIVIAL(info) << "finished init canvas3D";
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", finished init canvas3D";
wxGetApp().imgui()->new_frame();
BOOST_LOG_TRIVIAL(info) << "finished init imgui frame";
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", finished init imgui frame";
plater_->canvas3D()->enable_render(true);
BOOST_LOG_TRIVIAL(info) << "start to render a first frame for test";
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", start to render a first frame for test";
plater_->canvas3D()->render(false);
BOOST_LOG_TRIVIAL(info) << "finished rendering a first frame for test";
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", finished rendering a first frame for test";
if (is_editor())
mainframe->select_tab(size_t(0));
mainframe->Thaw();
plater_->trigger_restore_project(1);
BOOST_LOG_TRIVIAL(info) << "end load_gl_resources";
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", end load_gl_resources";
}
#endif
@ -1046,7 +1055,8 @@ void GUI_App::post_init()
bool cw_showed = this->config_wizard_startup();
std::string http_url = get_http_url(app_config->get_country_code());
this->preset_updater->sync(http_url, preset_bundle);
std::string language = GUI::into_u8(current_language_code());
this->preset_updater->sync(http_url, language, preset_bundle);
//BBS: check new version
this->check_new_version();
@ -1056,16 +1066,19 @@ void GUI_App::post_init()
if(!m_networking_need_update && m_agent) {
m_agent->set_on_ssdp_msg_fn(
[this](std::string json_str) {
if (m_is_closing) {
return;
}
GUI::wxGetApp().CallAfter([this, json_str] {
if (m_is_closing) {
return;
}
if (m_device_manager) {
m_device_manager->on_machine_alive(json_str);
}
});
}
);
m_agent->set_on_http_error_fn([this](unsigned int status, std::string body) {
this->handle_http_error(status, body);
});
m_agent->start_discovery(true, false);
}
@ -1105,6 +1118,26 @@ GUI_App::GUI_App()
reset_to_active();
}
void GUI_App::shutdown()
{
BOOST_LOG_TRIVIAL(info) << "shutdown";
if (m_is_recreating_gui) return;
m_is_closing = true;
stop_sync_user_preset();
if (m_device_manager) {
delete m_device_manager;
m_device_manager = nullptr;
}
if (m_agent) {
m_agent->start_discovery(false, false);
delete m_agent;
m_agent = nullptr;
}
}
std::string GUI_App::get_http_url(std::string country_code)
{
@ -1196,7 +1229,7 @@ int GUI_App::download_plugin(InstallProgressFn pro_fn, WasCancelledFn cancel_fn)
for (auto sub_iter = iter.value().begin(); sub_iter != iter.value().end(); sub_iter++) {
if (boost::iequals(sub_iter.key(), "type")) {
type = sub_iter.value();
BOOST_LOG_TRIVIAL(info) << "[BBL Updater]: get version of settings's type, " << sub_iter.value();
BOOST_LOG_TRIVIAL(info) << "[download_plugin]: get version of settings's type, " << sub_iter.value();
}
else if (boost::iequals(sub_iter.key(), "version")) {
version = *(Semver::parse(sub_iter.value()));
@ -1208,22 +1241,22 @@ int GUI_App::download_plugin(InstallProgressFn pro_fn, WasCancelledFn cancel_fn)
url = sub_iter.value();
}
}
BOOST_LOG_TRIVIAL(info) << "[download_plugin]: get type " << type << ", version " << version.to_string() << ", url " << url;
BOOST_LOG_TRIVIAL(info) << "[download_plugin 1]: get type " << type << ", version " << version.to_string() << ", url " << url;
download_url = url;
}
}
}
else {
BOOST_LOG_TRIVIAL(info) << "[download_plugin]: get version of plugin failed, body=" << body;
BOOST_LOG_TRIVIAL(info) << "[download_plugin 1]: get version of plugin failed, body=" << body;
}
}
catch (...) {
BOOST_LOG_TRIVIAL(error) << "[download_plugin]: catch unknown exception";
BOOST_LOG_TRIVIAL(error) << "[download_plugin 1]: catch unknown exception";
;
}
}).on_error(
[&result](std::string body, std::string error, unsigned int status) {
BOOST_LOG_TRIVIAL(error) << "" << body;
BOOST_LOG_TRIVIAL(error) << "[download_plugin 1] on_error: " << error<<", body = " << body;
result = -1;
}).perform_sync();
@ -1235,7 +1268,7 @@ int GUI_App::download_plugin(InstallProgressFn pro_fn, WasCancelledFn cancel_fn)
if (download_url.empty()) {
BOOST_LOG_TRIVIAL(info) << "[download_plugin]: no availaible plugin found for this app version: " << SLIC3R_VERSION;
BOOST_LOG_TRIVIAL(info) << "[download_plugin 1]: no availaible plugin found for this app version: " << SLIC3R_VERSION;
if (pro_fn) pro_fn(InstallStatusDownloadFailed, 0, cancel);
return -1;
}
@ -1244,10 +1277,10 @@ int GUI_App::download_plugin(InstallProgressFn pro_fn, WasCancelledFn cancel_fn)
}
if (m_networking_cancel_update || cancel) {
BOOST_LOG_TRIVIAL(info) << boost::format("download_plugin: %1%, cancelled by user") % __LINE__;
BOOST_LOG_TRIVIAL(info) << boost::format("[download_plugin 1]: %1%, cancelled by user") % __LINE__;
return -1;
}
BOOST_LOG_TRIVIAL(info) << "download_plugin, get_url = " << download_url;
BOOST_LOG_TRIVIAL(info) << "[download_plugin] get_url = " << download_url;
// download
Slic3r::Http http = Slic3r::Http::get(download_url);
@ -1261,6 +1294,7 @@ int GUI_App::download_plugin(InstallProgressFn pro_fn, WasCancelledFn cancel_fn)
if (pro_fn && ((percent - reported_percent) >= 10)) {
pro_fn(InstallStatusNormal, percent, was_cancel);
reported_percent = percent;
BOOST_LOG_TRIVIAL(info) << "[download_plugin 2] progress: " << reported_percent;
}
cancel = m_networking_cancel_update || was_cancel;
if (cancel_fn)
@ -1271,7 +1305,7 @@ int GUI_App::download_plugin(InstallProgressFn pro_fn, WasCancelledFn cancel_fn)
result = -1;
})
.on_complete([&pro_fn, tmp_path, target_file_path](std::string body, unsigned status) {
BOOST_LOG_TRIVIAL(info) << "download_plugin, completed";
BOOST_LOG_TRIVIAL(info) << "[download_plugin 2] completed";
bool cancel = false;
int percent = 0;
fs::fstream file(tmp_path, std::ios::out | std::ios::binary | std::ios::trunc);
@ -1283,6 +1317,7 @@ int GUI_App::download_plugin(InstallProgressFn pro_fn, WasCancelledFn cancel_fn)
.on_error([&pro_fn, &result](std::string body, std::string error, unsigned int status) {
bool cancel = false;
if (pro_fn) pro_fn(InstallStatusDownloadFailed, 0, cancel);
BOOST_LOG_TRIVIAL(error) << "[download_plugin 2] on_error: " << error<<", body = " << body;
result = -1;
});
http.perform_sync();
@ -1293,14 +1328,22 @@ int GUI_App::install_plugin(InstallProgressFn pro_fn, WasCancelledFn cancel_fn)
{
bool cancel = false;
std::string target_file_path = (fs::temp_directory_path() / "network_plugin.zip").string();
BOOST_LOG_TRIVIAL(info) << "[install_plugin] enter";
// get plugin folder
auto plugin_folder = boost::filesystem::path(wxStandardPaths::Get().GetUserDataDir().ToUTF8().data()) / "plugins";
auto backup_folder = plugin_folder/"backup";
if (!boost::filesystem::exists(plugin_folder)) {
BOOST_LOG_TRIVIAL(info) << "[install_plugin] will create directory "<<plugin_folder.string();
boost::filesystem::create_directory(plugin_folder);
}
if (!boost::filesystem::exists(backup_folder)) {
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", will create directory %1%")%backup_folder.string();
boost::filesystem::create_directory(backup_folder);
}
if (m_networking_cancel_update) {
BOOST_LOG_TRIVIAL(info) << boost::format("install_plugin: %1%, cancelled by user")%__LINE__;
BOOST_LOG_TRIVIAL(info) << boost::format("[install_plugin]: %1%, cancelled by user")%__LINE__;
return -1;
}
if (pro_fn) {
@ -1310,17 +1353,17 @@ int GUI_App::install_plugin(InstallProgressFn pro_fn, WasCancelledFn cancel_fn)
mz_zip_archive archive;
mz_zip_zero_struct(&archive);
if (!open_zip_reader(&archive, target_file_path)) {
BOOST_LOG_TRIVIAL(error) << boost::format("install_plugin: %1%, open zip file failed")%__LINE__;
BOOST_LOG_TRIVIAL(error) << boost::format("[install_plugin]: %1%, open zip file failed")%__LINE__;
if (pro_fn) pro_fn(InstallStatusDownloadFailed, 0, cancel);
return InstallStatusUnzipFailed;
}
mz_uint num_entries = mz_zip_reader_get_num_files(&archive);
mz_zip_archive_file_stat stat;
BOOST_LOG_TRIVIAL(error) << boost::format("install_plugin: %1%, got %2% files")%__LINE__ %num_entries;
BOOST_LOG_TRIVIAL(error) << boost::format("[install_plugin]: %1%, got %2% files")%__LINE__ %num_entries;
for (mz_uint i = 0; i < num_entries; i++) {
if (m_networking_cancel_update || cancel) {
BOOST_LOG_TRIVIAL(info) << boost::format("install_plugin: %1%, cancelled by user")%__LINE__;
BOOST_LOG_TRIVIAL(info) << boost::format("[install_plugin]: %1%, cancelled by user")%__LINE__;
return -1;
}
if (mz_zip_reader_file_stat(&archive, i, &stat)) {
@ -1356,6 +1399,21 @@ int GUI_App::install_plugin(InstallProgressFn pro_fn, WasCancelledFn cancel_fn)
if (pro_fn) {
pro_fn(InstallStatusNormal, 50 + i/num_entries, cancel);
}
try {
auto backup_path = boost::filesystem::path(backup_folder.string() + "/" + dest_file);
if (fs::exists(backup_path))
fs::remove(backup_path);
std::string error_message;
CopyFileResult cfr = copy_file(dest_path.string(), backup_path.string(), error_message, false);
if (cfr != CopyFileResult::SUCCESS) {
BOOST_LOG_TRIVIAL(error) << "Copying to backup failed(" << cfr << "): " << error_message;
}
}
catch (const std::exception& e)
{
BOOST_LOG_TRIVIAL(error) << "Copying to backup failed: " << e.what();
//continue
}
}
}
catch (const std::exception& e)
@ -1371,7 +1429,7 @@ int GUI_App::install_plugin(InstallProgressFn pro_fn, WasCancelledFn cancel_fn)
}
}
else {
BOOST_LOG_TRIVIAL(error) << boost::format("install_plugin: %1%, mz_zip_reader_file_stat for file %2% failed")%__LINE__%i;
BOOST_LOG_TRIVIAL(error) << boost::format("[install_plugin]: %1%, mz_zip_reader_file_stat for file %2% failed")%__LINE__%i;
}
}
@ -1380,27 +1438,31 @@ int GUI_App::install_plugin(InstallProgressFn pro_fn, WasCancelledFn cancel_fn)
if (pro_fn)
pro_fn(InstallStatusInstallCompleted, 100, cancel);
app_config->set_str("app", "installed_networking", "1");
BOOST_LOG_TRIVIAL(info) << "[install_plugin] success";
return 0;
}
void GUI_App::restart_networking()
{
BOOST_LOG_TRIVIAL(info) << __FUNCTION__<< boost::format(" enter, mainframe %1%")%mainframe;
on_init_network();
on_init_network(true);
if(m_agent) {
init_networking_callbacks();
m_agent->set_on_ssdp_msg_fn(
[this](std::string json_str) {
if (m_is_closing) {
return;
}
GUI::wxGetApp().CallAfter([this, json_str] {
if (m_is_closing) {
return;
}
if (m_device_manager) {
m_device_manager->on_machine_alive(json_str);
}
});
}
);
m_agent->set_on_http_error_fn([this](unsigned int status, std::string body) {
this->handle_http_error(status, body);
});
m_agent->start_discovery(true, false);
if (mainframe)
mainframe->refresh_plugin_tips();
@ -1412,7 +1474,7 @@ void GUI_App::restart_networking()
int GUI_App::updating_bambu_networking()
{
DownloadProgressDialog dlg(_L("Downloading Bambu Network plug-in"));
DownloadProgressDialog dlg(_L("Downloading Bambu Network Plug-in"));
dlg.ShowModal();
return 0;
}
@ -1457,20 +1519,20 @@ void GUI_App::init_networking_callbacks()
});
m_agent->set_on_server_connected_fn([this]() {
if (m_is_closing) {
return;
}
GUI::wxGetApp().CallAfter([this] {
if (m_is_closing) {
return;
}
BOOST_LOG_TRIVIAL(trace) << "static: server connected";
m_agent->set_user_selected_machine(m_agent->get_user_selected_machine());
});
});
m_agent->set_on_printer_connected_fn([this](std::string dev_id) {
if (m_is_closing) {
return;
}
GUI::wxGetApp().CallAfter([this, dev_id] {
if (m_is_closing) {
return;
}
/* request_pushing */
MachineObject* obj = m_device_manager->get_my_machine(dev_id);
if (obj) {
@ -1489,6 +1551,9 @@ void GUI_App::init_networking_callbacks()
m_agent->set_on_local_connect_fn(
[this](int state, std::string dev_id, std::string msg) {
if (m_is_closing) {
return;
}
CallAfter([this, state, dev_id, msg] {
if (m_is_closing) {
return;
@ -1502,31 +1567,31 @@ void GUI_App::init_networking_callbacks()
obj->command_get_version();
} else if (state == ConnectStatus::ConnectStatusFailed || ConnectStatus::ConnectStatusLost) {
obj->set_access_code("");
wxString text = wxString::Format(_L("Connect %s[SN:%s] failed!"), from_u8(obj->dev_name), obj->dev_id);
MessageDialog msg_dlg(nullptr, text, "", wxAPPLY | wxOK);
if (msg_dlg.ShowModal() == wxOK) {
return;
wxString text;
if (msg == "5") {
text = wxString::Format(_L("Incorrect password"));
wxGetApp().show_dialog(text);
} else {
text = wxString::Format(_L("Connect %s failed! [SN:%s, code=%s]"), from_u8(obj->dev_name), obj->dev_id, msg);
wxGetApp().show_dialog(text);
}
} else {
BOOST_LOG_TRIVIAL(info) << "set_on_local_connect_fn: state = " << state;
}
}
}
});
});
}
);
m_agent->set_on_http_error_fn([this](unsigned int status, std::string body) {
this->handle_http_error(status, body);
});
auto message_arrive_fn = [this](std::string dev_id, std::string msg) {
if (m_is_closing) {
return;
}
CallAfter([this, dev_id, msg] {
if (m_is_closing) {
return;
}
MachineObject* obj = this->m_device_manager->get_user_machine(dev_id);
if (obj) {
obj->is_ams_need_update = false;
obj->parse_json(msg);
if (this->m_device_manager->get_selected_machine() == obj && obj->is_ams_need_update) {
@ -1539,11 +1604,10 @@ void GUI_App::init_networking_callbacks()
m_agent->set_on_message_fn(message_arrive_fn);
auto lan_message_arrive_fn = [this](std::string dev_id, std::string msg) {
if (m_is_closing) {
return;
}
CallAfter([this, dev_id, msg] {
if (m_is_closing) {
return;
}
MachineObject* obj = m_device_manager->get_my_machine(dev_id);
if (!obj) {
obj = m_device_manager->get_local_machine(dev_id);
@ -1943,13 +2007,13 @@ bool GUI_App::on_init_inner()
});
Bind(EVT_SHOW_DIALOG, [this](const wxCommandEvent& evt) {
/*wxString msg = evt.GetString();
wxString msg = evt.GetString();
InfoDialog dlg(this->mainframe, _L("Info"), msg);
dlg.ShowModal();*/
dlg.ShowModal();
wxString text = evt.GetString();
/*wxString text = evt.GetString();
Slic3r::GUI::MessageDialog msg_dlg(this->mainframe, text, "", wxAPPLY | wxOK);
msg_dlg.ShowModal();
msg_dlg.ShowModal();*/
});
}
else {
@ -2032,7 +2096,9 @@ bool GUI_App::on_init_inner()
}
// BBS:
#ifdef __WINDOWS__
mainframe->topbar()->SaveNormalRect();
#endif
mainframe->Show(true);
BOOST_LOG_TRIVIAL(info) << "main frame firstly shown";
@ -2093,16 +2159,17 @@ bool GUI_App::on_init_inner()
// BBS
//this->obj_manipul()->update_if_dirty();
static bool update_gui_after_init = true;
//use m_post_initialized instead
//static bool update_gui_after_init = true;
// An ugly solution to GH #5537 in which GUI_App::init_opengl (normally called from events wxEVT_PAINT
// and wxEVT_SET_FOCUS before GUI_App::post_init is called) wasn't called before GUI_App::post_init and OpenGL wasn't initialized.
#ifdef __linux__
if (update_gui_after_init && m_opengl_initialized) {
if (!m_post_initialized && m_opengl_initialized) {
#else
if (update_gui_after_init) {
if (!m_post_initialized) {
#endif
update_gui_after_init = false;
m_post_initialized = true;
#ifdef WIN32
this->mainframe->register_win32_callbacks();
#endif
@ -2120,10 +2187,11 @@ bool GUI_App::on_init_inner()
return true;
}
bool GUI_App::on_init_network()
bool GUI_App::on_init_network(bool try_backup)
{
int load_agent_dll = Slic3r::NetworkAgent::initialize_network_module();
bool create_network_agent = false;
__retry:
if (!load_agent_dll) {
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": on_init_network, load dll ok";
if (check_networking_version()) {
@ -2138,6 +2206,13 @@ bool GUI_App::on_init_network()
else
create_network_agent = true;
} else {
if (try_backup) {
int result = Slic3r::NetworkAgent::unload_network_module();
BOOST_LOG_TRIVIAL(info) << "on_init_network, version mismatch, unload_network_module, result = " << result;
load_agent_dll = Slic3r::NetworkAgent::initialize_network_module(true);
try_backup = false;
goto __retry;
}
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": on_init_network, version dismatch, need upload network module";
if (app_config->get("installed_networking") == "1") {
m_networking_need_update = true;
@ -2240,11 +2315,11 @@ const wxColour GUI_App::get_label_default_clr_modified()
void GUI_App::init_label_colours()
{
m_color_label_modified = wxColour("#F1754E");
m_color_label_sys = wxColour("#2B3436");
m_color_label_sys = wxColour("#323A3D");
bool is_dark_mode = dark_mode();
#ifdef _WIN32
m_color_label_default = is_dark_mode ? wxColour(250, 250, 250): wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
m_color_label_default = is_dark_mode ? wxColour(250, 250, 250) : m_color_label_sys; // wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
m_color_highlight_label_default = is_dark_mode ? wxColour(230, 230, 230): wxSystemSettings::GetColour(/*wxSYS_COLOUR_HIGHLIGHTTEXT*/wxSYS_COLOUR_WINDOWTEXT);
m_color_highlight_default = is_dark_mode ? wxColour(78, 78, 78) : wxSystemSettings::GetColour(wxSYS_COLOUR_3DLIGHT);
m_color_hovered_btn_label = is_dark_mode ? wxColour(253, 111, 40) : wxColour(252, 77, 1);
@ -2523,7 +2598,7 @@ void GUI_App::recreate_GUI(const wxString& msg_name)
dlg.Update(80, _L("Loading current presets") + dots);
load_current_presets();
mainframe->Show(true);
mainframe->refresh_plugin_tips();
//mainframe->refresh_plugin_tips();
dlg.Update(90, _L("Loading a mode view") + dots);
@ -2574,7 +2649,7 @@ void GUI_App::ShowUserGuide() {
void GUI_App::ShowDownNetPluginDlg() {
try {
DownloadProgressDialog dlg(_L("Downloading Bambu Network plug-in"));
DownloadProgressDialog dlg(_L("Downloading Bambu Network Plug-in"));
dlg.ShowModal();
} catch (std::exception &e) {
;
@ -2699,21 +2774,7 @@ void GUI_App::persist_window_geometry(wxTopLevelWindow *window, bool default_max
const std::string name = into_u8(window->GetName());
window->Bind(wxEVT_CLOSE_WINDOW, [=](wxCloseEvent &event) {
m_is_closing = true;
window_pos_save(window, "mainframe");
//
stop_sync_user_preset();
if (m_device_manager) {
delete m_device_manager;
m_device_manager = nullptr;
}
if (m_agent) {
m_agent->start_discovery(false, false);
delete m_agent;
m_agent = nullptr;
}
event.Skip();
});
@ -2823,6 +2884,12 @@ void GUI_App::request_user_login(int online_login)
void GUI_App::request_user_logout()
{
if (m_agent) {
bool transfer_preset_changes = false;
wxString header = _L("Some presets are modified.") + "\n" +
_L("You can keep the modifield presets to the new project, discard or save changes as new presets.");
using ab = UnsavedChangesDialog::ActionButtons;
wxGetApp().check_and_keep_current_preset_changes(_L("User logged out"), header, ab::KEEP | ab::SAVE, &transfer_preset_changes);
m_agent->user_logout();
m_agent->set_user_selected_machine("");
/* delete old user settings */
@ -2936,6 +3003,26 @@ std::string GUI_App::handle_web_request(std::string cmd)
else if (command_str.compare("begin_network_plugin_download") == 0) {
CallAfter([this] { wxGetApp().ShowDownNetPluginDlg(); });
}
else if (command_str.compare("get_web_shortcut") == 0) {
if (root.get_child_optional("key_event") != boost::none) {
pt::ptree key_event_node = root.get_child("key_event");
auto keyCode = key_event_node.get<int>("key");
auto ctrlKey = key_event_node.get<bool>("ctrl");
auto shiftKey = key_event_node.get<bool>("shift");
auto cmdKey = key_event_node.get<bool>("cmd");
wxKeyEvent e(wxEVT_CHAR_HOOK);
#ifdef __APPLE__
e.SetControlDown(cmdKey);
#else
e.SetControlDown(ctrlKey);
#endif
e.SetShiftDown(shiftKey);
e.m_keyCode = keyCode;
e.SetEventObject(mainframe);
wxPostEvent(mainframe, e);
}
}
}
}
catch (...) {
@ -2992,6 +3079,11 @@ void GUI_App::request_project_download(std::string project_id)
void GUI_App::request_open_project(std::string project_id)
{
if (plater()->is_background_process_slicing()) {
Slic3r::GUI::show_info(nullptr, _L("new or open project file is not allowed during the slicing process!"), _L("Open Project"));
return;
}
if (project_id == "<new>")
plater()->new_project();
else if (project_id.empty())
@ -3624,6 +3716,7 @@ bool GUI_App::load_language(wxString language, bool initial)
{"fr", wxString::FromUTF8("\x46\x72\x61\x6E\xC3\xA7\x61\x69\x73")},
{"it", wxString::FromUTF8("\x49\x74\x61\x6C\x69\x61\x6E\x6F")},
{"ru", wxString::FromUTF8("\xD1\x80\xD1\x83\xD1\x81\xD1\x81\xD0\xBA\xD0\xB8\xD0\xB9")},
{"hu", wxString::FromUTF8("Magyar")}
};
for (auto l : language_descptions) {
const wxLanguageInfo *langinfo = wxLocale::FindLanguageInfo(l.first);
@ -3720,13 +3813,22 @@ bool GUI_App::load_language(wxString language, bool initial)
else if (initial) {
// bbs supported languages
//TODO: use a global one with Preference
wxLanguage supported_languages[] {wxLANGUAGE_ENGLISH, wxLANGUAGE_CHINESE_SIMPLIFIED, wxLANGUAGE_GERMAN, wxLANGUAGE_FRENCH, wxLANGUAGE_SPANISH, wxLANGUAGE_SWEDISH, wxLANGUAGE_DUTCH };
wxLanguage supported_languages[] {
wxLANGUAGE_ENGLISH,
wxLANGUAGE_CHINESE_SIMPLIFIED,
wxLANGUAGE_GERMAN,
wxLANGUAGE_FRENCH,
wxLANGUAGE_SPANISH,
wxLANGUAGE_SWEDISH,
wxLANGUAGE_DUTCH,
wxLANGUAGE_HUNGARIAN };
std::string cur_language = app_config->get("language");
if (cur_language != "") {
//cleanup the language wrongly set before
const wxLanguageInfo *langinfo = nullptr;
bool embedded_language = false;
for (auto index = 0; index < 7; index++) {
int language_num = sizeof(supported_languages) / sizeof(supported_languages[0]);
for (auto index = 0; index < language_num; index++) {
langinfo = wxLocale::GetLanguageInfo(supported_languages[index]);
std::string temp_lan = langinfo->CanonicalName.ToUTF8().data();
if (cur_language == temp_lan) {
@ -4283,6 +4385,7 @@ void GUI_App::MacOpenFiles(const wxArrayString &fileNames)
std::vector<std::string> files;
std::vector<wxString> gcode_files;
std::vector<wxString> non_gcode_files;
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", open files, size " << fileNames.size();
for (const auto& filename : fileNames) {
if (is_gcode_file(into_u8(filename)))
gcode_files.emplace_back(filename);
@ -4303,21 +4406,27 @@ void GUI_App::MacOpenFiles(const wxArrayString &fileNames)
} else*/
{
if (! files.empty()) {
wxArrayString input_files;
for (size_t i = 0; i < non_gcode_files.size(); ++i) {
input_files.push_back(non_gcode_files[i]);
if (m_post_initialized) {
wxArrayString input_files;
for (size_t i = 0; i < non_gcode_files.size(); ++i) {
input_files.push_back(non_gcode_files[i]);
}
this->plater()->load_files(input_files);
}
this->plater()->load_files(input_files);
if (gcode_files.size() > 0) {
show_info(this->plater(), _L("G-code files can not be loaded with models together!"), _L("G-code loading"));
else {
for (size_t i = 0; i < files.size(); ++i) {
this->init_params->input_files.emplace_back(files[i]);
}
}
}
else {
wxArrayString input_files;
for (size_t i = 0; i < gcode_files.size(); ++i) {
input_files.push_back(gcode_files[i]);
if (m_post_initialized) {
this->plater()->load_gcode(gcode_files.front());
}
else {
this->init_params->input_gcode = true;
this->init_params->input_files = { into_u8(gcode_files.front()) };
}
this->plater()->load_files(input_files);
}
/*for (const wxString &filename : gcode_files)
start_new_gcodeviewer(&filename);*/
@ -4352,12 +4461,16 @@ const Plater* GUI_App::plater() const
ParamsPanel* GUI_App::params_panel()
{
return mainframe->m_param_panel;
if (mainframe)
return mainframe->m_param_panel;
return nullptr;
}
ParamsDialog* GUI_App::params_dialog()
{
return mainframe->m_param_dialog;
if (mainframe)
return mainframe->m_param_dialog;
return nullptr;
}
Model& GUI_App::model()
@ -4367,22 +4480,28 @@ Model& GUI_App::model()
void GUI_App::load_url(wxString url)
{
return mainframe->load_url(url);
if (mainframe)
return mainframe->load_url(url);
}
void GUI_App::run_script(wxString js)
{
return mainframe->RunScript(js);
if (mainframe)
return mainframe->RunScript(js);
}
Notebook* GUI_App::tab_panel() const
{
return mainframe->m_tabpanel;
if (mainframe)
return mainframe->m_tabpanel;
return nullptr;
}
NotificationManager * GUI_App::notification_manager()
{
return plater_->get_notification_manager();
if (plater_)
return plater_->get_notification_manager();
return nullptr;
}
// extruders count from selected printer preset
@ -4807,8 +4926,15 @@ void GUI_App::disassociate_files(std::wstring extend)
bool is_new = false;
is_new |= del_win_registry(HKEY_CURRENT_USER, reg_extension.c_str(), prog_id.c_str());
is_new |= del_win_registry(HKEY_CURRENT_USER, reg_prog_id.c_str(), prog_desc.c_str());
is_new |= del_win_registry(HKEY_CURRENT_USER, reg_prog_id_command.c_str(), prog_command.c_str());
bool is_associate_3mf = app_config->get("associate_3mf") == "true";
bool is_associate_stl = app_config->get("associate_stl") == "true";
bool is_associate_step = app_config->get("associate_step") == "true";
if (!is_associate_3mf && !is_associate_stl && !is_associate_step)
{
is_new |= del_win_registry(HKEY_CURRENT_USER, reg_prog_id.c_str(), prog_desc.c_str());
is_new |= del_win_registry(HKEY_CURRENT_USER, reg_prog_id_command.c_str(), prog_command.c_str());
}
if (is_new)
::SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, nullptr, nullptr);

View file

@ -100,6 +100,11 @@ enum ConfigMenuIDs {
ConfigMenuCnt,
};
enum BambuStudioMenuIDs {
BambuStudioMenuAbout,
BambuStudioMenuPreferences,
};
enum CameraMenuIDs {
wxID_CAMERA_PERSPECTIVE,
wxID_CAMERA_ORTHOGONAL,
@ -189,7 +194,7 @@ public:
class GUI_App : public wxApp
{
public:
//BBS: remove GCodeViewer as seperate APP logic
enum class EAppMode : unsigned char
{
@ -199,6 +204,7 @@ public:
private:
bool m_initialized { false };
bool m_post_initialized { false };
bool m_app_conf_exists{ false };
EAppMode m_app_mode{ EAppMode::Editor };
bool m_is_recreating_gui{ false };
@ -280,6 +286,7 @@ public:
// Process command line parameters cached in this->init_params,
// load configs, STLs etc.
void post_init();
void shutdown();
// If formatted for github, plaintext with OpenGL extensions enclosed into <details>.
// Otherwise HTML formatted for the system info dialog.
static std::string get_gl_info(bool for_github);
@ -511,7 +518,7 @@ public:
private:
int updating_bambu_networking();
bool on_init_inner();
bool on_init_network();
bool on_init_network(bool try_backup = false);
void init_networking_callbacks();
void init_app_config();
//BBS set extra header for http request

View file

@ -53,7 +53,16 @@ int GUI_Run(GUI_InitParams &params)
GUI::GUI_App::SetInstance(gui);
gui->init_params = &params;
return wxEntry(params.argc, params.argv);
if (params.argc > 1) {
// STUDIO-273 wxWidgets report error when opening some files with specific names
// wxWidgets does not handle parameters, so intercept parameters here, only keep the app name
int argc = 1;
std::vector<char *> argv;
argv.push_back(params.argv[0]);
return wxEntry(argc, argv.data());
} else {
return wxEntry(params.argc, params.argv);
}
} catch (const Slic3r::Exception &ex) {
BOOST_LOG_TRIVIAL(error) << ex.what() << std::endl;
wxMessageBox(boost::nowide::widen(ex.what()), _L("Bambu Studio GUI initialization failed"), wxICON_STOP);

View file

@ -22,6 +22,7 @@ struct GUI_InitParams
//BBS: remove start_as_gcodeviewer logic
//bool start_as_gcodeviewer;
bool input_gcode { false };
};
int GUI_Run(GUI_InitParams &params);

View file

@ -71,9 +71,6 @@ static void take_snapshot(const std::string& snapshot_name)
plater->take_snapshot(snapshot_name);
}
#define ID_OBJECT_ORG_MENU_ITEM_MODULE 11000
#define ID_OBJECT_ORG_MENU_ITEM_PLATE 11001
ObjectList::ObjectList(wxWindow* parent) :
wxDataViewCtrl(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxDV_MULTIPLE)
{
@ -85,17 +82,6 @@ ObjectList::ObjectList(wxWindow* parent) :
//BBS: add part plate related event
//Bind(EVT_PARTPLATE_LIST_PLATE_SELECT, &ObjectList::on_select_plate, this);
// BBS
wxMenuItem* org_by_plate = new wxMenuItem(&m_object_org_menu, ID_OBJECT_ORG_MENU_ITEM_PLATE, "Organize By Plate");
m_object_org_menu.Append(org_by_plate);
wxMenuItem* org_by_module = new wxMenuItem(&m_object_org_menu, ID_OBJECT_ORG_MENU_ITEM_MODULE, "Organize By Module");
m_object_org_menu.Append(org_by_module);
//Bind(wxEVT_DATAVIEW_COLUMN_HEADER_CLICK, &ObjectList::OnColumnHeadClicked, this);
Bind(wxEVT_MENU, [this](wxCommandEvent& evt) { this->OnOrganizeObjects(ortByPlate); }, ID_OBJECT_ORG_MENU_ITEM_PLATE);
Bind(wxEVT_MENU, [this](wxCommandEvent& evt) { this->OnOrganizeObjects(ortByModule); }, ID_OBJECT_ORG_MENU_ITEM_MODULE);
// describe control behavior
Bind(wxEVT_DATAVIEW_SELECTION_CHANGED, [this](wxDataViewEvent& event) {
// detect the current mouse position here, to pass it to list_manipulation() method
@ -266,7 +252,8 @@ ObjectList::ObjectList(wxWindow* parent) :
#else
update_name_column_width();
ensure_current_item_visible();
// BBS
this->CallAfter([this]() { ensure_current_item_visible(); });
#endif
e.Skip();
}));
@ -278,10 +265,13 @@ ObjectList::~ObjectList()
void ObjectList::set_min_height()
{
// BBS
#if 0
if (m_items_count == size_t(-1))
m_items_count = 7;
int list_min_height = lround(2.25 * (m_items_count + 1) * wxGetApp().em_unit()); // +1 is for height of control header
this->SetMinSize(wxSize(1, list_min_height));
#endif
}
void ObjectList::update_min_height()
@ -289,10 +279,14 @@ void ObjectList::update_min_height()
wxDataViewItemArray all_items;
m_objects_model->GetAllChildren(wxDataViewItem(nullptr), all_items);
size_t items_cnt = all_items.Count();
#if 0
if (items_cnt < 7)
items_cnt = 7;
else if (items_cnt >= 15)
items_cnt = 15;
#else
items_cnt = 8;
#endif
if (m_items_count == items_cnt)
return;
@ -304,14 +298,14 @@ void ObjectList::update_min_height()
void ObjectList::create_objects_ctrl()
{
// BBS
#if 0
/* Temporary workaround for the correct behavior of the Scrolled sidebar panel:
* 1. set a height of the list to some big value
* 2. change it to the normal(meaningful) min value after first whole Mainframe updating/layouting
*/
SetMinSize(wxSize(-1, 3000));
m_sizer = new wxBoxSizer(wxVERTICAL);
m_sizer->Add(this, 1, wxGROW);
#endif
m_objects_model = new ObjectDataViewModel;
AssociateModel(m_objects_model);
@ -356,7 +350,7 @@ void ObjectList::create_objects_ctrl()
bmp_choice_renderer->set_default_extruder_idx([this]() {
return m_objects_model->GetDefaultExtruderIdx(GetSelection());
});
AppendColumn(new wxDataViewColumn(_L(""), bmp_choice_renderer,
AppendColumn(new wxDataViewColumn(_L("Fila."), bmp_choice_renderer,
colFilament, m_columns_width[colFilament] * em, wxALIGN_CENTER_HORIZONTAL, 0));
// BBS
@ -642,6 +636,9 @@ void ObjectList::update_plate_values_for_items()
if (plate_idx == old_plate_idx)
continue;
// hotfix for wxDataViewCtrl selection not updated after wxDataViewModel::ItemDeleted()
Unselect(item);
bool is_old_parent_expanded = IsExpanded(old_parent);
bool is_expanded = IsExpanded(item);
m_objects_model->OnPlateChange(plate_idx, item);
@ -661,20 +658,6 @@ void ObjectList::update_name_for_items()
wxGetApp().plater()->update();
}
// BBS
void ObjectList::OnColumnHeadClicked(wxDataViewEvent& event)
{
int col = event.GetColumn();
if (col == 0) {
this->PopupMenu(&m_object_org_menu, 0, FromDIP(20));
}
}
void ObjectList::OnOrganizeObjects(OBJECT_ORGANIZE_TYPE type)
{
printf("%d\n", type);
}
void ObjectList::object_config_options_changed(const ObjectVolumeID& ov_id)
{
if (ov_id.object == nullptr)
@ -1977,6 +1960,30 @@ void ObjectList::load_generic_subobject(const std::string& type_name, const Mode
// update printable state on canvas
wxGetApp().plater()->canvas3D()->update_instance_printable_state_for_object((size_t)obj_idx);
// apply the instance transform to all volumes and reset instance transform except the offset
{
const Geometry::Transformation &instance_transformation = model_object.instances[0]->get_transformation();
Vec3d original_instance_center = instance_transformation.get_offset();
const Transform3d &transformation_matrix = instance_transformation.get_matrix();
for (ModelVolume *volume : model_object.volumes) {
const Transform3d &volume_matrix = volume->get_matrix();
Transform3d new_matrix = transformation_matrix * volume_matrix;
volume->set_transformation(new_matrix);
}
model_object.instances[0]->set_transformation(Geometry::Transformation());
model_object.ensure_on_bed();
// keep new instance center the same as the original center
model_object.translate(-original_instance_center);
model_object.origin_translation += original_instance_center;
model_object.translate_instances(model_object.origin_translation);
model_object.origin_translation = Vec3d::Zero();
// update the cache data in selection to keep the data of ModelVolume and GLVolume are consistent
wxGetApp().plater()->update();
}
selection_changed();
//BBS: notify partplate the modify
@ -4734,9 +4741,7 @@ void ObjectList::OnEditingStarted(wxDataViewEvent &event)
auto item = event.GetItem();
if (!renderer->GetEditorCtrl()) {
renderer->StartEditing(item, GetItemRect(item, column));
if (col == colFilament) // TODO: not handle KILL_FOCUS from ComboBox
renderer->GetEditorCtrl()->PopEventHandler();
else if (col == colName) // TODO: for colName editing, disable shortcuts
if (col == colName) // TODO: for colName editing, disable shortcuts
SetAcceleratorTable(wxNullAcceleratorTable);
}
#endif //__WXMSW__

View file

@ -163,8 +163,6 @@ private:
} m_dragged_data;
wxBoxSizer *m_sizer {nullptr};
ObjectDataViewModel *m_objects_model{ nullptr };
ModelConfig *m_config {nullptr};
std::vector<ModelObject*> *m_objects{ nullptr };
@ -308,7 +306,6 @@ public:
bool can_merge_to_single_object() const;
wxPoint get_mouse_position_in_control() const { return wxGetMousePosition() - this->GetScreenPosition(); }
wxBoxSizer* get_sizer() {return m_sizer;}
int get_selected_obj_idx() const;
ModelConfig& get_item_config(const wxDataViewItem& item) const;
@ -453,11 +450,6 @@ private:
void OnEditingStarted(wxDataViewEvent &event);
void OnEditingDone(wxDataViewEvent &event);
// BBS
void OnColumnHeadClicked(wxDataViewEvent& event);
void OnOrganizeObjects(OBJECT_ORGANIZE_TYPE type);
wxMenu m_object_org_menu;
std::vector<int> m_columns_width;
};

View file

@ -236,6 +236,25 @@ void GridCellFilamentsEditor::BeginEdit(int row, int col, wxGrid* grid)
}
}
bool GridCellFilamentsEditor::EndEdit(int WXUNUSED(row),
int WXUNUSED(col),
const wxGrid* WXUNUSED(grid),
const wxString& WXUNUSED(oldval),
wxString *newval)
{
const wxString value = Combo()->GetValue();
if ( value == m_value )
return false;
m_value = value;
if ( newval )
*newval = value;
return true;
}
wxGridActivationResult GridCellFilamentsEditor::TryActivate(int row, int col, wxGrid* grid, const wxGridActivationSource& actSource)
{
ObjectGridTable *table = dynamic_cast<ObjectGridTable *>(grid->GetTable());
@ -2365,7 +2384,7 @@ ObjectTablePanel::ObjectTablePanel( wxWindow* parent, wxWindowID id, const wxPoi
SetSize(wxSize(-1, FromDIP(450)));
SetMinSize(wxSize(-1, FromDIP(450)));
SetMaxSize(wxSize(-1, FromDIP(450)));
//m_search_line = new wxTextCtrl(this, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER);
init_bitmap();
@ -2401,7 +2420,7 @@ ObjectTablePanel::ObjectTablePanel( wxWindow* parent, wxWindowID id, const wxPoi
m_page_top_sizer->Add(m_page_text, 0, wxEXPAND, 5);*/
//TODO, adjust later
/*
@ -2445,7 +2464,7 @@ ObjectTablePanel::ObjectTablePanel( wxWindow* parent, wxWindowID id, const wxPoi
int ObjectTablePanel::init_bitmap()
{
m_undo_bitmap = create_scaled_bitmap("undo", nullptr, 24);
m_undo_bitmap = create_scaled_bitmap("lock_normal", nullptr, 24);
m_color_bitmaps = get_extruder_color_icons();
return 0;

View file

@ -40,7 +40,7 @@ public:
const wxRect& rect,
int row, int col,
bool isSelected) wxOVERRIDE;
virtual wxSize GetBestSize(wxGrid& WXUNUSED(grid),
wxGridCellAttr& attr,
wxDC& dc,
@ -71,6 +71,8 @@ public:
virtual wxGridCellEditor *Clone() const wxOVERRIDE;
virtual void BeginEdit(int row, int col, wxGrid* grid) wxOVERRIDE;
virtual bool EndEdit(int row, int col, const wxGrid* grid,
const wxString& oldval, wxString *newval) wxOVERRIDE;
virtual wxGridActivationResult TryActivate(int row, int col, wxGrid* grid, const wxGridActivationSource& actSource) wxOVERRIDE;
virtual void DoActivate(int row, int col, wxGrid* grid) wxOVERRIDE;
@ -151,7 +153,7 @@ public:
//ObjectGrid for the param setting table
class ObjectGrid : public wxGrid
{
public:
public:
ObjectGrid(wxWindow *parent,
wxWindowID id,
const wxPoint& pos = wxDefaultPosition,
@ -377,7 +379,7 @@ public:
virtual int GetNumberRows() wxOVERRIDE;
virtual int GetNumberCols() wxOVERRIDE;
virtual bool IsEmptyCell( int row, int col ) wxOVERRIDE;
//virtual wxString GetColLabelValue( int col ) wxOVERRIDE;
@ -537,7 +539,7 @@ private:
wxFloatingPointValidator<float> m_float_validator;
wxBitmap m_undo_bitmap;
std::vector<wxBitmap*> m_color_bitmaps;
std::vector<wxBitmap*> m_color_bitmaps;
ScalableBitmap m_bmp_reset;
ScalableBitmap m_bmp_reset_disable;
private:

View file

@ -66,8 +66,8 @@ ObjectTableSettings::ObjectTableSettings(wxWindow* parent, ObjectGridTable* tabl
m_settings_list_sizer = new wxBoxSizer(wxVERTICAL);
m_og->sizer->Add(m_settings_list_sizer, 1, wxEXPAND | wxLEFT, 5);
m_bmp_reset = ScalableBitmap(parent, "undo");
m_bmp_reset_focus = ScalableBitmap(parent, "undo");
m_bmp_reset = ScalableBitmap(parent, "lock_normal");
m_bmp_reset_focus = ScalableBitmap(parent, "lock_normal");
//TODO, adjust later
m_bmp_reset_disable = ScalableBitmap(parent, "dot");
}

View file

@ -766,6 +766,7 @@ bool AssembleView::init(wxWindow* parent, Bed3D& bed, Model* model, DynamicPrint
// BBS: set volume_selection_mode to Volume
m_canvas->get_selection().set_volume_selection_mode(Selection::Volume);
m_canvas->get_selection().lock_volume_selection_mode();
wxBoxSizer* main_sizer = new wxBoxSizer(wxVERTICAL);
main_sizer->Add(m_canvas_widget, 1, wxALL | wxEXPAND, 0);

View file

@ -158,6 +158,10 @@ void GLGizmoAdvancedCut::reset_cut_plane()
m_rotation.setZero();
//m_current_base_rotation.setZero();
m_rotate_cmds.clear();
m_buffered_movement = 0.0;
m_buffered_height = m_height;
m_buffered_rotation.setZero();
}
void GLGizmoAdvancedCut::reset_all()
@ -174,7 +178,7 @@ bool GLGizmoAdvancedCut::on_init()
if (!GLGizmoRotate3D::on_init())
return false;
m_shortcut_key = WXK_NONE;
m_shortcut_key = WXK_CONTROL_C;
return true;
}
@ -414,7 +418,7 @@ void GLGizmoAdvancedCut::on_render_input_window(float x, float y, float bottom_l
GizmoImguiSetNextWIndowPos(x, y, ImGuiCond_Always, 0.0f, 0.0f);
ImGuiWrapper::push_toolbar_style();
ImGuiWrapper::push_toolbar_style(m_parent.get_scale());
GizmoImguiBegin(on_get_name(), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar);

View file

@ -76,7 +76,7 @@ std::string GLGizmoFdmSupports::on_get_name() const
bool GLGizmoFdmSupports::on_init()
{
// BBS
m_shortcut_key = WXK_NONE;
m_shortcut_key = WXK_CONTROL_L;
m_desc["clipping_of_view"] = _L("Section view") + ": ";
m_desc["cursor_size"] = _L("Pen size") + ": ";
@ -88,9 +88,9 @@ 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("Gap fill");
m_desc["perform_filter"] = _L("Perform");
m_desc["fragment_area"] = _L("Fragment area");
m_desc["gap_fill"] = _L("Gap fill");
m_desc["perform"] = _L("Perform");
m_desc["gap_area"] = _L("Gap area");
m_desc["brush_size"] = _L("Set pen size");
m_desc["brush_size_caption"] = _L("Ctrl + Mouse wheel") + ": ";
m_desc["tool_type"] = _L("Tool type");
@ -175,6 +175,10 @@ void GLGizmoFdmSupports::on_set_state()
if (get_state() == On) {
m_support_threshold_angle = -1;
}
else if (get_state() == Off) {
ModelObject* mo = m_c->selection_info()->model_object();
if (mo) Slic3r::save_object_mesh(*mo);
}
}
static std::string into_u8(const wxString& str)
@ -206,16 +210,16 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l
GizmoImguiSetNextWIndowPos(x, y, ImGuiCond_Always, 0.0f, 0.0f);
//BBS
ImGuiWrapper::push_toolbar_style();
ImGuiWrapper::push_toolbar_style(m_parent.get_scale());
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 cursor_slider_left = m_imgui->calc_text_size(m_desc.at("cursor_size")).x + m_imgui->scaled(1.5f);
const float fragment_filter_slider_left = m_imgui->calc_text_size(m_desc.at("fragment_filter")).x + m_imgui->scaled(1.5f);
const float gap_fill_slider_left = m_imgui->calc_text_size(m_desc.at("gap_fill")).x + m_imgui->scaled(1.5f);
const float highlight_slider_left = m_imgui->calc_text_size(m_desc.at("highlight_by_angle")).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.5f);
const float filter_btn_width = m_imgui->calc_text_size(m_desc.at("perform_filter")).x + m_imgui->scaled(1.5f);
const float filter_btn_width = m_imgui->calc_text_size(m_desc.at("perform")).x + m_imgui->scaled(1.5f);
const float buttons_width = remove_btn_width + filter_btn_width + m_imgui->scaled(1.5f);
const float empty_button_width = m_imgui->calc_button_size("").x;
@ -232,7 +236,7 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l
total_text_max += caption_max + m_imgui->scaled(1.f);
caption_max += m_imgui->scaled(1.f);
const float sliders_left_width = std::max(std::max(cursor_slider_left, clipping_slider_left), std::max(highlight_slider_left, fragment_filter_slider_left));
const float sliders_left_width = std::max(std::max(cursor_slider_left, clipping_slider_left), std::max(highlight_slider_left, gap_fill_slider_left));
const float slider_icon_width = m_imgui->get_slider_icon_size().x;
float window_width = minimal_slider_width + sliders_left_width + slider_icon_width;
const float max_tooltip_width = ImGui::GetFontSize() * 20.0f;
@ -245,7 +249,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<wchar_t, 4> tool_icons = { ImGui::CircleButtonIcon, ImGui::SphereButtonIcon, ImGui::FillButtonIcon, ImGui::GapFillIcon };
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("##");
@ -322,19 +326,19 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l
ImGui::SameLine(window_width - drag_pos_times * slider_icon_width);
ImGui::PushItemWidth(1.5 * slider_icon_width);
ImGui::BBLDragFloat("##smart_fill_angle_input", &m_smart_fill_angle, 0.05f, 0.0f, 0.0f, "%.2f");
} else if (m_current_tool == ImGui::FragmentFilterIcon) {
m_tool_type = ToolType::FRAGMENT_FILTER;
} else if (m_current_tool == ImGui::GapFillIcon) {
m_tool_type = ToolType::GAP_FILL;
m_cursor_type = TriangleSelector::CursorType::POINTER;
ImGui::AlignTextToFramePadding();
m_imgui->text(m_desc["fragment_area"] + ":");
m_imgui->text(m_desc["gap_area"] + ":");
ImGui::SameLine(sliders_left_width);
ImGui::PushItemWidth(window_width - sliders_left_width - 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);
m_imgui->bbl_slider_float_style("##gap_area", &TriangleSelectorPatch::gap_area, TriangleSelectorPatch::GapAreaMin, TriangleSelectorPatch::GapAreaMax, format_str.data(), 1.0f, true);
ImGui::SameLine(window_width - drag_pos_times * 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::BBLDragFloat("##gap_area_input", &TriangleSelectorPatch::gap_area, 0.05f, 0.0f, 0.0f, "%.2f");
}
float position_before_text_y = ImGui::GetCursorPos().y;
@ -374,7 +378,7 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l
ImGui::PushItemWidth(1.5 * slider_icon_width);
ImGui::BBLDragFloat("##angle_threshold_deg_input", &m_highlight_by_angle_threshold_deg, 0.05f, 0.0f, 0.0f, "%.2f");
if (m_current_tool != ImGui::FragmentFilterIcon) {
if (m_current_tool != ImGui::GapFillIcon) {
ImGui::Separator();
ImGui::AlignTextToFramePadding();
m_imgui->text(m_desc.at("clipping_of_view"));
@ -395,12 +399,15 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(6.0f, 10.0f));
float get_cur_y = ImGui::GetContentRegionMax().y + ImGui::GetFrameHeight() + y;
show_tooltip_information(caption_max, x, get_cur_y);
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(6.0f, 5.0f));
float f_scale =m_parent.get_gizmos_manager().get_layout_scale();
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(6.0f, 4.0f * f_scale));
ImGui::SameLine();
// Perform button is for gap fill
if (m_current_tool == ImGui::FragmentFilterIcon) {
if (m_imgui->button(m_desc.at("perform_filter"))) {
if (m_current_tool == ImGui::GapFillIcon) {
if (m_imgui->button(m_desc.at("perform"))) {
Plater::TakeSnapshot snapshot(wxGetApp().plater(), "Reset selection", UndoRedo::SnapshotType::GizmoAction);
for (int i = 0; i < m_triangle_selectors.size(); i++) {
@ -439,13 +446,13 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l
void GLGizmoFdmSupports::tool_changed(wchar_t old_tool, wchar_t new_tool)
{
if ((old_tool == ImGui::FragmentFilterIcon && new_tool == ImGui::FragmentFilterIcon) ||
(old_tool != ImGui::FragmentFilterIcon && new_tool != ImGui::FragmentFilterIcon))
if ((old_tool == ImGui::GapFillIcon && new_tool == ImGui::GapFillIcon) ||
(old_tool != ImGui::GapFillIcon && new_tool != ImGui::GapFillIcon))
return;
for (auto& selector_ptr : m_triangle_selectors) {
TriangleSelectorPatch* tsp = dynamic_cast<TriangleSelectorPatch*>(selector_ptr.get());
tsp->set_filter_state(new_tool == ImGui::FragmentFilterIcon);
tsp->set_filter_state(new_tool == ImGui::GapFillIcon);
}
}
@ -549,8 +556,6 @@ void GLGizmoFdmSupports::update_model_object()
const ModelObjectPtrs& mos = wxGetApp().model().objects;
wxGetApp().obj_list()->update_info_items(std::find(mos.begin(), mos.end(), mo) - mos.begin());
// BBS: backup
Slic3r::save_object_mesh(*mo);
m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
}

View file

@ -25,7 +25,7 @@ GLGizmoFlatten::GLGizmoFlatten(GLCanvas3D& parent, const std::string& icon_filen
bool GLGizmoFlatten::on_init()
{
// BBS
m_shortcut_key = WXK_NONE;
m_shortcut_key = WXK_CONTROL_F;
return true;
}

View file

@ -94,7 +94,7 @@ void GLGizmoMmuSegmentation::init_extruders_data()
bool GLGizmoMmuSegmentation::on_init()
{
// BBS
m_shortcut_key = WXK_NONE;
m_shortcut_key = WXK_CONTROL_N;
m_desc["clipping_of_view"] = _L("Section view") + ": ";
m_desc["cursor_size"] = _L("Pen size") + ": ";
@ -108,10 +108,10 @@ bool GLGizmoMmuSegmentation::on_init()
m_desc["shortcut_key_caption"] = _L("Key 1~9") + ": ";
m_desc["shortcut_key"] = _L("Choose filament");
m_desc["edge_detection"] = _L("Edge detection");
m_desc["fragment_area"] = _L("Fragment area");
m_desc["perform_filter"] = _L("Perform");
m_desc["gap_area"] = _L("Gap area");
m_desc["perform"] = _L("Perform");
m_desc["remove_all"] = _L("Clear all");
m_desc["remove_all"] = _L("Erase all painting");
m_desc["circle"] = _L("Circle");
m_desc["sphere"] = _L("Sphere");
m_desc["pointer"] = _L("Triangles");
@ -332,7 +332,7 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott
wchar_t old_tool = m_current_tool;
// BBS
ImGuiWrapper::push_toolbar_style();
ImGuiWrapper::push_toolbar_style(m_parent.get_scale());
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(8.0f, 16.0f));
GizmoImguiBegin(get_name(), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar);
@ -341,11 +341,11 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott
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.5f);
const float gap_area_slider_left = m_imgui->calc_text_size(m_desc.at("gap_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);
const float filter_btn_width = m_imgui->calc_text_size(m_desc.at("perform")).x + m_imgui->scaled(1.f);
const float buttons_width = remove_btn_width + filter_btn_width + m_imgui->scaled(1.f);
const float minimal_slider_width = m_imgui->scaled(4.f);
const float color_button_width = m_imgui->calc_text_size("").x + m_imgui->scaled(1.75f);
@ -362,7 +362,7 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott
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,
std::max(cursor_slider_left, std::max(edge_detect_slider_left, std::max(gap_area_slider_left, std::max(height_range_slider_left,
clipping_slider_left)))));
const float slider_icon_width = m_imgui->get_slider_icon_size().x;
float window_width = minimal_slider_width + sliders_left_width + slider_icon_width;
@ -434,7 +434,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<wchar_t, 6> tool_icons = { ImGui::CircleButtonIcon,ImGui::SphereButtonIcon, ImGui::TriangleButtonIcon, ImGui::HeightRangeIcon, ImGui::FillButtonIcon, ImGui::GapFillIcon };
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("##");
@ -585,31 +585,33 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott
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;
else if (m_current_tool == ImGui::GapFillIcon) {
m_tool_type = ToolType::GAP_FILL;
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);
m_imgui->text(m_desc["gap_area"] + ":");
ImGui::SameLine(gap_area_slider_left);
ImGui::PushItemWidth(window_width - gap_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);
m_imgui->bbl_slider_float_style("##gap_area", &TriangleSelectorPatch::gap_area, TriangleSelectorPatch::GapAreaMin, TriangleSelectorPatch::GapAreaMax, 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::BBLDragFloat("##gap_area_input", &TriangleSelectorPatch::gap_area, 0.05f, 0.0f, 0.0f, "%.2f");
}
ImGui::Separator();
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(6.0f, 10.0f));
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(6.0f, 5.0f));
float get_cur_y = ImGui::GetContentRegionMax().y + ImGui::GetFrameHeight() + y;
show_tooltip_information(caption_max, x, get_cur_y);
float f_scale =m_parent.get_gizmos_manager().get_layout_scale();
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(6.0f, 4.0f * f_scale));
ImGui::SameLine();
if (m_current_tool == ImGui::FragmentFilterIcon) {
if (m_imgui->button(m_desc.at("perform_filter"))) {
Plater::TakeSnapshot snapshot(wxGetApp().plater(), "Filter fragment", UndoRedo::SnapshotType::GizmoAction);
if (m_current_tool == ImGui::GapFillIcon) {
if (m_imgui->button(m_desc.at("perform"))) {
Plater::TakeSnapshot snapshot(wxGetApp().plater(), "Gap fill", UndoRedo::SnapshotType::GizmoAction);
for (int i = 0; i < m_triangle_selectors.size(); i++) {
TriangleSelectorPatch* ts_mm = dynamic_cast<TriangleSelectorPatch*>(m_triangle_selectors[i].get());
@ -661,11 +663,7 @@ void GLGizmoMmuSegmentation::update_model_object()
if (updated) {
const ModelObjectPtrs &mos = wxGetApp().model().objects;
wxGetApp().obj_list()->update_info_items(std::find(mos.begin(), mos.end(), mo) - mos.begin());
// BBS: backup
Slic3r::save_object_mesh(*mo);
m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
// BBS
m_parent.post_event(SimpleEvent(EVT_GLCANVAS_FORCE_UPDATE));
}
}
@ -730,13 +728,13 @@ void GLGizmoMmuSegmentation::update_from_model_object(bool first_update)
void GLGizmoMmuSegmentation::tool_changed(wchar_t old_tool, wchar_t new_tool)
{
if ((old_tool == ImGui::FragmentFilterIcon && new_tool == ImGui::FragmentFilterIcon) ||
(old_tool != ImGui::FragmentFilterIcon && new_tool != ImGui::FragmentFilterIcon))
if ((old_tool == ImGui::GapFillIcon && new_tool == ImGui::GapFillIcon) ||
(old_tool != ImGui::GapFillIcon && new_tool != ImGui::GapFillIcon))
return;
for (auto& selector_ptr : m_triangle_selectors) {
TriangleSelectorPatch* tsp = dynamic_cast<TriangleSelectorPatch*>(selector_ptr.get());
tsp->set_filter_state(new_tool == ImGui::FragmentFilterIcon);
tsp->set_filter_state(new_tool == ImGui::GapFillIcon);
}
}
@ -754,6 +752,16 @@ std::array<float, 4> GLGizmoMmuSegmentation::get_cursor_hover_color() const
return m_extruders_colors[0];
}
void GLGizmoMmuSegmentation::on_set_state()
{
GLGizmoPainterBase::on_set_state();
if (get_state() == Off) {
ModelObject* mo = m_c->selection_info()->model_object();
if (mo) Slic3r::save_object_mesh(*mo);
}
}
wxString GLGizmoMmuSegmentation::handle_snapshot_action_name(bool shift_down, GLGizmoPainterBase::Button button_down) const
{
wxString action_name;

View file

@ -87,6 +87,7 @@ public:
protected:
// BBS
std::array<float, 4> get_cursor_hover_color() const override;
void on_set_state() override;
EnforcerBlockerType get_left_button_state_type() const override { return EnforcerBlockerType(m_selected_extruder_idx + 1); }
EnforcerBlockerType get_right_button_state_type() const override { return EnforcerBlockerType::NONE; }

View file

@ -1,138 +0,0 @@
// Include GLGizmoBase.hpp before I18N.hpp as it includes some libigl code, which overrides our localization "L" macro.
#include "GLGizmoModifier.hpp"
#include "slic3r/GUI/GUI_App.hpp"
#include "slic3r/GUI/GUI_ObjectList.hpp"
#include "slic3r/GUI/ImGuiWrapper.hpp"
#include "slic3r/GUI/GLCanvas3D.hpp"
#include "slic3r/GUI/Gizmos/GLGizmosCommon.hpp"
#include "libslic3r/Geometry/ConvexHull.hpp"
#include "libslic3r/Model.hpp"
#include <numeric>
#include <GL/glew.h>
namespace Slic3r {
namespace GUI {
const int SHAPE_IMAGE_SIZE = 34;
const std::vector<std::pair<std::string, std::string>> GLGizmoModifier::MODIFIER_SHAPES = {
{L("Cube"), "toolbar_modifier_cube.svg" },
{L("Cylinder"), "toolbar_modifier_cylinder.svg" },
{L("Sphere"), "toolbar_modifier_sphere.svg" },
{L("Cone"), "toolbar_modifier_cone.svg" },
{L("Timelapse Wipe Tower"), "toolbar_modifier_cube.svg"},
};
GLGizmoModifier::GLGizmoModifier(GLCanvas3D &parent, const std::string &icon_filename, unsigned int sprite_id)
: GLGizmoBase(parent, icon_filename, sprite_id)
{
}
bool GLGizmoModifier::on_init()
{
bool result = true;
texture_ids.clear();
for (auto item: MODIFIER_SHAPES) {
result = result && init_shape_texture(item.second);
}
// BBS
m_shortcut_key = WXK_NONE;
return result;
}
bool GLGizmoModifier::init_shape_texture(std::string image_name)
{
// init shapes image
bool compress = false;
GLint last_texture;
unsigned m_image_texture{0};
std::string path = resources_dir() + "/images/";
std::string file_name = path + image_name;
ThumbnailData data;
if (!get_data_from_svg(file_name, SHAPE_IMAGE_SIZE, data)) return false;
unsigned char *pixels = (unsigned char *) (&data.pixels[0]);
glsafe(::glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture));
glsafe(::glGenTextures(1, &m_image_texture));
glsafe(::glBindTexture(GL_TEXTURE_2D, m_image_texture));
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
glsafe(::glPixelStorei(GL_UNPACK_ROW_LENGTH, 0));
if (compress && GLEW_EXT_texture_compression_s3tc)
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, data.width, data.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels));
else
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, data.width, data.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels));
// Store our identifier
ImTextureID texture_id = (ImTextureID) (intptr_t) m_image_texture;
texture_ids.push_back(texture_id);
// Restore state
glsafe(::glBindTexture(GL_TEXTURE_2D, last_texture));
return true;
}
void GLGizmoModifier::on_set_state()
{
}
void GLGizmoModifier::on_render_input_window(float x, float y, float bottom_limit)
{
// BBS: GUI refactor: move gizmo to the right
m_imgui->set_next_window_pos(x, y, ImGuiCond_Always, 0.f, 0.0f);
// BBS
ImGuiWrapper::push_toolbar_style();
std::string name = "Add Modifier##Modifier";
m_imgui->begin(_L(name), ImGuiWrapper::TOOLBAR_WINDOW_FLAGS);
for (int i = 0; i < MODIFIER_SHAPES.size(); i++) {
if (ImGui::ImageButton(texture_ids[i], ImVec2(34.0f, 34.0f))) {
wxGetApp().obj_list()->load_generic_subobject(MODIFIER_SHAPES[i].first, ModelVolumeType::PARAMETER_MODIFIER);
}
ImGui::SameLine();
}
m_imgui->end();
ImGuiWrapper::pop_toolbar_style();
}
CommonGizmosDataID GLGizmoModifier::on_get_requirements() const
{
return CommonGizmosDataID::SelectionInfo;
}
std::string GLGizmoModifier::on_get_name() const
{
return _u8L("Add Modifier");
}
bool GLGizmoModifier::on_is_activable() const
{
return m_parent.get_selection().is_single_full_instance();
}
void GLGizmoModifier::on_start_dragging()
{
;
}
void GLGizmoModifier::on_render()
{
;
}
void GLGizmoModifier::on_render_for_picking()
{
;
}
} // namespace GUI
} // namespace Slic3r

View file

@ -1,42 +0,0 @@
#ifndef slic3r_GLGizmoModifier_hpp_
#define slic3r_GLGizmoModifier_hpp_
#include "GLGizmoBase.hpp"
#include "slic3r/GUI/3DScene.hpp"
namespace Slic3r {
enum class ModelVolumeType : int;
namespace GUI {
class GLGizmoModifier : public GLGizmoBase
{
// This gizmo does not use grabbers. The m_hover_id relates to polygon managed by the class itself.
private:
std::vector<void*> texture_ids;
public:
static const std::vector<std::pair<std::string, std::string>> MODIFIER_SHAPES;
GLGizmoModifier(GLCanvas3D &parent, const std::string &icon_filename, unsigned int sprite_id);
protected:
virtual bool on_init() override;
virtual std::string on_get_name() const override;
virtual bool on_is_activable() const override;
virtual void on_start_dragging() override;
virtual void on_render() override;
virtual void on_render_for_picking() override;
virtual void on_set_state() override;
virtual void on_render_input_window(float x, float y, float bottom_limit);
virtual CommonGizmosDataID on_get_requirements() const override;
bool init_shape_texture(std::string image_name);
};
} // namespace GUI
} // namespace Slic3r
#endif // slic3r_GLGizmoFlatten_hpp_

View file

@ -56,7 +56,7 @@ bool GLGizmoMove3D::on_init()
m_grabbers.push_back(Grabber());
}
m_shortcut_key = WXK_NONE;
m_shortcut_key = WXK_CONTROL_M;
return true;
}

View file

@ -1036,10 +1036,10 @@ void TriangleSelectorGUI::update_render_data()
// BBS
bool TrianglePatch::is_fragment() const
{
return this->area < TriangleSelectorPatch::fragment_area;
return this->area < TriangleSelectorPatch::gap_area;
}
float TriangleSelectorPatch::fragment_area = TriangleSelectorPatch::FragmentAreaMin;
float TriangleSelectorPatch::gap_area = TriangleSelectorPatch::GapAreaMin;
void TriangleSelectorPatch::render(ImGuiWrapper* imgui)
{
@ -1198,7 +1198,7 @@ void TriangleSelectorPatch::update_triangles_per_patch()
visited[current_facet] = true;
}
patch.area = calc_fragment_area(patch, FragmentAreaMax);
patch.area = calc_fragment_area(patch, GapAreaMax);
patch.type = start_facet_state;
m_triangle_patches.emplace_back(std::move(patch));
}

View file

@ -78,7 +78,7 @@ public:
void request_update_render_data(bool paint_changed = false)
{
m_update_render_data = true;
m_paint_changed = paint_changed;
m_paint_changed |= paint_changed;
};
// BBS
@ -116,7 +116,7 @@ struct TrianglePatch {
std::vector<int> facet_indices;
EnforcerBlockerType type = EnforcerBlockerType::NONE;
std::set<EnforcerBlockerType> neighbor_types;
// if area is larger than FragmentAreaMax, stop accumulate left triangle areas to improve performance
// if area is larger than GapAreaMax, stop accumulate left triangle areas to improve performance
float area = 0.f;
bool is_fragment() const;
@ -140,11 +140,11 @@ public:
void set_ebt_colors(const std::vector<std::array<float, 4>> ebt_colors) { m_ebt_colors = ebt_colors; }
void set_filter_state(bool is_filter_state);
constexpr static float FragmentAreaMin = 0.f;
constexpr static float FragmentAreaMax = 5.f;
constexpr static float GapAreaMin = 0.f;
constexpr static float GapAreaMax = 5.f;
// BBS: fix me
static float fragment_area;
static float gap_area;
protected:
// Release the geometry data, release OpenGL VBOs.
@ -265,7 +265,7 @@ protected:
BUCKET_FILL,
SMART_FILL,
// BBS
FRAGMENT_FILTER,
GAP_FILL,
};
struct ProjectedMousePosition

View file

@ -466,7 +466,7 @@ bool GLGizmoRotate3D::on_init()
m_gizmos[i].set_highlight_color(AXES_COLOR[i]);
}
m_shortcut_key = WXK_NONE;
m_shortcut_key = WXK_CONTROL_R;
return true;
}

View file

@ -74,7 +74,7 @@ bool GLGizmoScale3D::on_init()
// BBS
m_grabbers[4].enabled = false;
m_shortcut_key = WXK_NONE;
m_shortcut_key = WXK_CONTROL_S;
return true;
}

View file

@ -28,7 +28,7 @@ bool GLGizmoSeam::on_init()
{
m_shortcut_key = WXK_CONTROL_P;
m_desc["clipping_of_view"] = _L("Clipping of view") + ": ";
m_desc["clipping_of_view"] = _L("Section view") + ": ";
m_desc["reset_direction"] = _L("Reset direction");
m_desc["cursor_size"] = _L("Brush size") + ": ";
m_desc["cursor_type"] = _L("Brush shape") + ": ";
@ -38,13 +38,18 @@ bool GLGizmoSeam::on_init()
m_desc["block"] = _L("Block seam");
m_desc["remove_caption"] = _L("Shift + Left mouse button") + ": ";
m_desc["remove"] = _L("Remove selection");
m_desc["remove_all"] = _L("Remove all selection");
m_desc["remove_all"] = _L("Erase all painting");
m_desc["circle"] = _L("Circle");
m_desc["sphere"] = _L("Sphere");
return true;
}
GLGizmoSeam::GLGizmoSeam(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
: GLGizmoPainterBase(parent, icon_filename, sprite_id), m_current_tool(ImGui::CircleButtonIcon)
{
}
std::string GLGizmoSeam::on_get_name() const
@ -114,6 +119,48 @@ void GLGizmoSeam::render_triangles(const Selection& selection) const
}
}
void GLGizmoSeam::show_tooltip_information(float caption_max, float x, float y)
{
ImTextureID normal_id = m_parent.get_gizmos_manager().get_icon_texture_id(GLGizmosManager::MENU_ICON_NAME::IC_TOOLBAR_TOOLTIP);
ImTextureID hover_id = m_parent.get_gizmos_manager().get_icon_texture_id(GLGizmosManager::MENU_ICON_NAME::IC_TOOLBAR_TOOLTIP_HOVER);
float font_size = ImGui::GetFontSize();
ImVec2 button_size = ImVec2(font_size * 1.8, font_size * 1.3);
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0f);
ImGui::ImageButton3(normal_id, hover_id, button_size);
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip2(ImVec2(x, y));
auto draw_text_with_caption = [this, &caption_max](const wxString &caption, const wxString &text) {
m_imgui->text_colored(ImGuiWrapper::COL_ACTIVE, caption);
ImGui::SameLine(caption_max);
m_imgui->text_colored(ImGuiWrapper::COL_WINDOW_BG, text);
};
for (const auto &t : std::array<std::string, 3>{"enforce", "block", "remove"}) draw_text_with_caption(m_desc.at(t + "_caption"), m_desc.at(t));
ImGui::EndTooltip();
}
ImGui::PopStyleVar(1);
}
void GLGizmoSeam::tool_changed(wchar_t old_tool, wchar_t new_tool)
{
if ((old_tool == ImGui::GapFillIcon && new_tool == ImGui::GapFillIcon) ||
(old_tool != ImGui::GapFillIcon && new_tool != ImGui::GapFillIcon))
return;
for (auto& selector_ptr : m_triangle_selectors) {
TriangleSelectorPatch* tsp = dynamic_cast<TriangleSelectorPatch*>(selector_ptr.get());
tsp->set_filter_state(new_tool == ImGui::GapFillIcon);
}
}
static std::string into_u8(const wxString& str)
{
auto buffer_utf8 = str.utf8_str();
return std::string(buffer_utf8.data());
}
void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit)
{
if (! m_c->selection_info()->model_object())
@ -123,16 +170,17 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit)
y = std::min(y, bottom_limit - approx_height);
//BBS: GUI refactor: move gizmo to the right
#if BBS_TOOLBAR_ON_TOP
m_imgui->set_next_window_pos(x, y, ImGuiCond_Always, 0.0f, 0.0f);
GizmoImguiSetNextWIndowPos(x, y, ImGuiCond_Always, 0.0f, 0.0f);
#else
m_imgui->set_next_window_pos(x, y, ImGuiCond_Always, 1.0f, 0.0f);
GizmoImguiSetNextWIndowPos(x, y, ImGuiCond_Always, 1.0f, 0.0f);
#endif
//m_imgui->set_next_window_pos(x, y, ImGuiCond_Always);
wchar_t old_tool = m_current_tool;
//BBS
ImGuiWrapper::push_toolbar_style();
ImGuiWrapper::push_toolbar_style(m_parent.get_scale());
m_imgui->begin(get_name(), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse);
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 = std::max(m_imgui->calc_text_size(m_desc.at("clipping_of_view")).x,
@ -146,6 +194,7 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit)
const float button_width = m_imgui->calc_text_size(m_desc.at("remove_all")).x + m_imgui->scaled(1.f);
const float minimal_slider_width = m_imgui->scaled(4.f);
const float empty_button_width = m_imgui->calc_button_size("").x;
float caption_max = 0.f;
float total_text_max = 0.f;
@ -155,7 +204,7 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit)
}
total_text_max += caption_max + m_imgui->scaled(1.f);
caption_max += m_imgui->scaled(1.f);
float slider_width_times = 1.5;
const float sliders_left_width = std::max(cursor_size_slider_left, clipping_slider_left);
#if ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT
const float slider_icon_width = m_imgui->get_slider_icon_size().x;
@ -167,82 +216,89 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit)
window_width = std::max(window_width, button_width);
window_width = std::max(window_width, cursor_type_radio_left + cursor_type_radio_sphere + cursor_type_radio_circle);
auto draw_text_with_caption = [this, &caption_max](const wxString& caption, const wxString& text) {
//BBS set text colored to BLUE_LIGHT
m_imgui->text_colored(ImGuiWrapper::COL_BLUE_LIGHT, caption);
ImGui::SameLine(caption_max);
m_imgui->text(text);
};
for (const auto &t : std::array<std::string, 3>{"enforce", "block", "remove"})
draw_text_with_caption(m_desc.at(t + "_caption"), m_desc.at(t));
ImGui::Separator();
const float max_tooltip_width = ImGui::GetFontSize() * 20.0f;
ImGui::AlignTextToFramePadding();
m_imgui->text(m_desc.at("cursor_type"));
std::array<wchar_t, 2> tool_icons = { ImGui::CircleButtonIcon, ImGui::SphereButtonIcon};
std::array<wxString, 2> tool_tips = { _L("Circle"), _L("Sphere")};
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);
if (i != 0) ImGui::SameLine((empty_button_width + m_imgui->scaled(1.75f)) * i + m_imgui->scaled(1.3f));
if (m_current_tool == tool_icons[i]) {
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.81f, 0.81f, 0.81f, 1.0f)); // r, g, b, a
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.81f, 0.81f, 0.81f, 1.0f));
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.81f, 0.81f, 0.81f, 1.0f));
}
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0);
bool btn_clicked = ImGui::Button(into_u8(btn_name).c_str());
ImGui::PopStyleVar(1);
if (m_current_tool == tool_icons[i])ImGui::PopStyleColor(3);
if (btn_clicked && m_current_tool != tool_icons[i]) {
m_current_tool = tool_icons[i];
for (auto& triangle_selector : m_triangle_selectors) {
triangle_selector->seed_fill_unselect_all_triangles();
triangle_selector->request_update_render_data();
}
}
if (ImGui::IsItemHovered()) {
m_imgui->tooltip(tool_tips[i], max_tooltip_width);
}
}
if (m_current_tool != old_tool)
this->tool_changed(old_tool, m_current_tool);
ImGui::Dummy(ImVec2(0.0f, ImGui::GetFontSize() * 0.1));
if (m_current_tool == ImGui::CircleButtonIcon) {
m_cursor_type = TriangleSelector::CursorType::CIRCLE;
m_tool_type = ToolType::BRUSH;
} else if (m_current_tool == ImGui::SphereButtonIcon) {
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);
#if ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT
ImGui::PushItemWidth(window_width - sliders_left_width - slider_icon_width);
m_imgui->slider_float("##cursor_radius", &m_cursor_radius, CursorRadiusMin, CursorRadiusMax, "%.2f", 1.0f, true, _L("Alt + Mouse wheel"));
#else
ImGui::PushItemWidth(window_width - sliders_left_width);
m_imgui->slider_float("##cursor_radius", &m_cursor_radius, CursorRadiusMin, CursorRadiusMax, "%.2f");
if (ImGui::IsItemHovered())
m_imgui->tooltip(_L("Alt + Mouse wheel"), max_tooltip_width);
#endif // ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT
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);
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");
ImGui::AlignTextToFramePadding();
m_imgui->text(m_desc.at("cursor_type"));
float cursor_type_offset = cursor_type_radio_left + (window_width - cursor_type_radio_left - cursor_type_radio_sphere - cursor_type_radio_circle + m_imgui->scaled(0.5f)) / 2.f;
ImGui::SameLine(cursor_type_offset);
ImGui::PushItemWidth(cursor_type_radio_sphere);
if (m_imgui->radio_button(m_desc["sphere"], m_cursor_type == TriangleSelector::CursorType::SPHERE))
m_cursor_type = TriangleSelector::CursorType::SPHERE;
if (ImGui::IsItemHovered())
m_imgui->tooltip(_L("Paints all facets inside, regardless of their orientation."), max_tooltip_width);
ImGui::SameLine(cursor_type_offset + cursor_type_radio_sphere);
ImGui::PushItemWidth(cursor_type_radio_circle);
if (m_imgui->radio_button(m_desc["circle"], m_cursor_type == TriangleSelector::CursorType::CIRCLE))
m_cursor_type = TriangleSelector::CursorType::CIRCLE;
if (ImGui::IsItemHovered())
m_imgui->tooltip(_L("Ignores facets facing away from the camera."), max_tooltip_width);
ImGui::Separator();
if (m_c->object_clipper()->get_position() == 0.f) {
ImGui::AlignTextToFramePadding();
m_imgui->text(m_desc.at("clipping_of_view"));
}
else {
if (m_imgui->button(m_desc.at("reset_direction"))) {
wxGetApp().CallAfter([this](){
m_c->object_clipper()->set_position(-1., false);
});
}
}
m_imgui->text(m_desc.at("clipping_of_view"));
auto clp_dist = float(m_c->object_clipper()->get_position());
ImGui::SameLine(sliders_left_width);
#if ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT
ImGui::PushItemWidth(window_width - sliders_left_width - slider_icon_width);
if (m_imgui->slider_float("##clp_dist", &clp_dist, 0.f, 1.f, "%.2f", 1.0f, true, _L("Ctrl + Mouse wheel")))
m_c->object_clipper()->set_position(clp_dist, true);
#else
ImGui::PushItemWidth(window_width - sliders_left_width);
if (m_imgui->slider_float("##clp_dist", &clp_dist, 0.f, 1.f, "%.2f"))
m_c->object_clipper()->set_position(clp_dist, true);
if (ImGui::IsItemHovered())
m_imgui->tooltip(_L("Ctrl + Mouse wheel"), max_tooltip_width);
#endif // ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT
ImGui::PushItemWidth(window_width - sliders_left_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); }
ImGui::Separator();
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(6.0f, 10.0f));
float get_cur_y = ImGui::GetContentRegionMax().y + ImGui::GetFrameHeight() + y;
show_tooltip_information(caption_max, x, get_cur_y);
float f_scale =m_parent.get_gizmos_manager().get_layout_scale();
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(6.0f, 4.0f * f_scale));
ImGui::SameLine();
if (m_imgui->button(m_desc.at("remove_all"))) {
Plater::TakeSnapshot snapshot(wxGetApp().plater(), "Reset selection", UndoRedo::SnapshotType::GizmoAction);
ModelObject *mo = m_c->selection_info()->model_object();
@ -251,19 +307,29 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit)
if (mv->is_model_part()) {
++idx;
m_triangle_selectors[idx]->reset();
m_triangle_selectors[idx]->request_update_render_data();
m_triangle_selectors[idx]->request_update_render_data(true);
}
update_model_object();
m_parent.set_as_dirty();
}
m_imgui->end();
ImGui::PopStyleVar(2);
GizmoImguiEnd();
//BBS
ImGuiWrapper::pop_toolbar_style();
}
// BBS
void GLGizmoSeam::on_set_state()
{
GLGizmoPainterBase::on_set_state();
if (get_state() == Off) {
ModelObject* mo = m_c->selection_info()->model_object();
if (mo) Slic3r::save_object_mesh(*mo);
}
}
//BBS: remove const
void GLGizmoSeam::update_model_object()
@ -281,9 +347,6 @@ void GLGizmoSeam::update_model_object()
if (updated) {
const ModelObjectPtrs& mos = wxGetApp().model().objects;
wxGetApp().obj_list()->update_info_items(std::find(mos.begin(), mos.end(), mo) - mos.begin());
// BBS: backup
Slic3r::save_object_mesh(*mo);
m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
}
}

View file

@ -8,17 +8,24 @@ namespace Slic3r::GUI {
class GLGizmoSeam : public GLGizmoPainterBase
{
public:
GLGizmoSeam(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
: GLGizmoPainterBase(parent, icon_filename, sprite_id) {}
GLGizmoSeam(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
void render_painter_gizmo() const override;
protected:
// BBS
void on_set_state() override;
wchar_t m_current_tool = 0;
void on_render_input_window(float x, float y, float bottom_limit) override;
std::string on_get_name() const override;
PainterGizmoType get_painter_type() const override;
void render_triangles(const Selection& selection) const override;
void render_triangles(const Selection &selection) const override;
void show_tooltip_information(float caption_max, float x, float y);
void tool_changed(wchar_t old_tool, wchar_t new_tool);
wxString handle_snapshot_action_name(bool shift_down, Button button_down) const override;

View file

@ -22,7 +22,6 @@
#include "slic3r/GUI/Gizmos/GLGizmoSeam.hpp"
#include "slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp"
#include "slic3r/GUI/Gizmos/GLGizmoSimplify.hpp"
#include "slic3r/GUI/Gizmos/GLGizmoModifier.hpp"
#include "libslic3r/format.hpp"
#include "libslic3r/Model.hpp"
@ -146,10 +145,9 @@ bool GLGizmosManager::init()
m_gizmos.emplace_back(new GLGizmoFlatten(m_parent, "toolbar_flatten.svg", EType::Flatten));
m_gizmos.emplace_back(new GLGizmoAdvancedCut(m_parent, "toolbar_cut.svg", EType::Cut));
m_gizmos.emplace_back(new GLGizmoFdmSupports(m_parent, "toolbar_support.svg", EType::FdmSupports));
m_gizmos.emplace_back(new GLGizmoSeam(m_parent, "toolbar_seam.svg", EType::Seam));
m_gizmos.emplace_back(new GLGizmoMmuSegmentation(m_parent, "mmu_segmentation.svg", EType::MmuSegmentation));
m_gizmos.emplace_back(new GLGizmoSimplify(m_parent, "reduce_triangles.svg", EType::Simplify));
//m_gizmos.emplace_back(new GLGizmoModifier(m_parent, "toolbar_modifier.svg", EType::Modifier));
//m_gizmos.emplace_back(new GLGizmoSeam(m_parent, "toolbar_seam.svg", EType::Seam));
//m_gizmos.emplace_back(new GLGizmoSlaSupports(m_parent, "sla_supports.svg", sprite_id++));
//m_gizmos.emplace_back(new GLGizmoFaceDetector(m_parent, "face recognition.svg", sprite_id++));
//m_gizmos.emplace_back(new GLGizmoHollow(m_parent, "hollow.svg", sprite_id++));
@ -199,6 +197,11 @@ bool GLGizmosManager::init_icon_textures()
return true;
}
float GLGizmosManager::get_layout_scale()
{
return m_layout.scale;
}
bool GLGizmosManager::init_arrow(const BackgroundTexture::Metadata& arrow_texture)
{
if (m_arrow_texture.texture.get_id() != 0)
@ -515,12 +518,8 @@ void GLGizmosManager::set_painter_gizmo_data()
return;
dynamic_cast<GLGizmoFdmSupports*>(m_gizmos[FdmSupports].get())->set_painter_gizmo_data(m_parent.get_selection());
dynamic_cast<GLGizmoSeam*>(m_gizmos[Seam].get())->set_painter_gizmo_data(m_parent.get_selection());
dynamic_cast<GLGizmoMmuSegmentation*>(m_gizmos[MmuSegmentation].get())->set_painter_gizmo_data(m_parent.get_selection());
if (Seam < m_gizmos.size()) {
GLGizmoSeam* gizmo_seam = dynamic_cast<GLGizmoSeam*>(m_gizmos[Seam].get());
if (gizmo_seam != nullptr)
gizmo_seam->set_painter_gizmo_data(m_parent.get_selection());
}
}
// Returns true if the gizmo used the event to do something, false otherwise.

View file

@ -71,10 +71,9 @@ public:
Flatten,
Cut,
FdmSupports,
Seam,
MmuSegmentation,
Simplify,
Modifier,
Seam,
SlaSupports,
// BBS
//FaceRecognition,
@ -159,6 +158,8 @@ public:
bool init_icon_textures();
float get_layout_scale();
bool init_arrow(const BackgroundTexture::Metadata& arrow_texture);
template<class Archive>

View file

@ -98,7 +98,7 @@ void GizmoObjectManipulation::update_settings_value(const Selection& selection)
if (m_world_coordinates) {
m_new_rotate_label_string = L("Rotate");
m_new_rotation = Vec3d::Zero();
m_new_rotation = volume->get_instance_rotation() * (180. / M_PI);
m_new_size = selection.get_scaled_instance_bounding_box().size();
m_new_scale = m_new_size.cwiseProduct(selection.get_unscaled_instance_bounding_box().size().cwiseInverse()) * 100.;
}
@ -550,7 +550,7 @@ void GizmoObjectManipulation::do_render_move_window(ImGuiWrapper *imgui_wrapper,
#endif
// BBS
ImGuiWrapper::push_toolbar_style();
ImGuiWrapper::push_toolbar_style(m_glcanvas.get_scale());
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0, 6.0));
std::string name = this->m_new_title_string + "##" + window_name;
@ -664,7 +664,7 @@ void GizmoObjectManipulation::do_render_rotate_window(ImGuiWrapper *imgui_wrappe
#endif
// BBS
ImGuiWrapper::push_toolbar_style();
ImGuiWrapper::push_toolbar_style(m_glcanvas.get_scale());
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0, 6.0));
std::string name = this->m_new_title_string + "##" + window_name;
@ -783,7 +783,7 @@ void GizmoObjectManipulation::do_render_scale_input_window(ImGuiWrapper* imgui_w
#endif
//BBS
ImGuiWrapper::push_toolbar_style();
ImGuiWrapper::push_toolbar_style(m_glcanvas.get_scale());
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0, 6.0));
std::string name = this->m_new_title_string + "##" + window_name;

View file

@ -1238,7 +1238,7 @@ bool IMSlider::render(int canvas_width, int canvas_height)
void IMSlider::render_menu()
{
ImGuiWrapper::push_menu_style();
ImGuiWrapper::push_menu_style(m_scale);
std::vector<std::string> colors = wxGetApp().plater()->get_extruder_colors_from_plater_config();
int extruder_num = colors.size();
@ -1246,24 +1246,25 @@ void IMSlider::render_menu()
ImGui::OpenPopup("slider_menu_popup");
}
ImGui::PushStyleVar(ImGuiStyleVar_::ImGuiStyleVar_ChildRounding, 4.0f * m_scale);
if (ImGui::BeginPopup("slider_menu_popup")) {
bool selected = false;
ImGui::MenuItem(_u8L("Add Pause").c_str(), "", &selected);
if (selected) { add_code_as_tick(PausePrint); }
if(menu_item_with_icon(_u8L("Add Pause").c_str(), "")) { add_code_as_tick(PausePrint); }
//BBS render this menu item only when extruder_num > 1
if (extruder_num > 1) {
if (ImGui::BeginMenu(_u8L("Change Filament").c_str())) {
if (begin_menu(_u8L("Change Filament").c_str())) {
for (int i = 0; i < extruder_num; i++) {
std::array<float, 4> rgba = decode_color_to_float_array(colors[i]);
ImU32 icon_clr = IM_COL32(rgba[0] * 255.0f, rgba[1] * 255.0f, rgba[2] * 255.0f, rgba[3] * 255.0f);
if (menu_item_with_icon((_u8L("Filament ") + std::to_string(i + 1)).c_str(), "", icon_clr, false, true)) add_code_as_tick(ToolChange, i + 1);
if (menu_item_with_icon((_u8L("Filament ") + std::to_string(i + 1)).c_str(), "", ImVec2(14, 14) * m_scale, icon_clr)) add_code_as_tick(ToolChange, i + 1);
}
ImGui::EndMenu();
end_menu();
}
}
ImGui::EndPopup();
}
ImGui::PopStyleVar(1);
ImGuiWrapper::pop_menu_style();
}

View file

@ -58,10 +58,10 @@ static const std::map<const wchar_t, std::string> font_icons = {
{ImGui::SliderFloatEditBtnIcon, "edit_button" },
#endif // ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT
{ImGui::CircleButtonIcon , "circle_paint" },
{ImGui::TriangleButtonIcon , "Triangle_paint" },
{ImGui::TriangleButtonIcon , "triangle_paint" },
{ImGui::FillButtonIcon , "fill_paint" },
{ImGui::HeightRangeIcon , "height_range" },
{ImGui::FragmentFilterIcon , "fragment_filter" },
{ImGui::GapFillIcon , "gap_fill" },
{ImGui::FoldButtonIcon , "im_fold" },
{ImGui::UnfoldButtonIcon , "im_unfold" },
{ImGui::SphereButtonIcon , "toolbar_modifier_sphere" },
@ -196,7 +196,7 @@ bool slider_behavior(ImGuiID id, const ImRect& region, const ImS32 v_min, const
mouse_wheel_responsive_region = ImRect(region.Min - ImVec2(0, handle_sz.y), region.Max + ImVec2(0, handle_sz.y));
if (ImGui::ItemHoverable(mouse_wheel_responsive_region, id)) {
#ifdef __APPLE__
if (io.KeyShift)
if (io.KeyShift)
v_new = ImClamp(*out_value - 5 * (ImS32) (context.IO.MouseWheel), v_min, v_max);
else if (io.KeyCtrl)
v_new = ImClamp(*out_value + 5 * (ImS32) (context.IO.MouseWheel), v_min, v_max);
@ -236,7 +236,7 @@ bool slider_behavior(ImGuiID id, const ImRect& region, const ImS32 v_min, const
{
v_new = fixed_value;
}
// apply result, output value
if (*out_value != v_new)
{
@ -291,56 +291,6 @@ bool button_with_pos(ImTextureID user_texture_id, const ImVec2 &size, const ImVe
return pressed;
}
bool menu_item_with_icon(const char* label, const char* shortcut, ImU32 icon_color, bool selected, bool enabled/* = true*/) {
ImGuiWindow* window = ImGui::GetCurrentWindow();
if (window->SkipItems)
return false;
ImGuiContext& g = *GImGui;
ImGuiStyle& style = g.Style;
ImVec2 pos = window->DC.CursorPos;
ImVec2 label_size = ImGui::CalcTextSize(label, NULL, true);
// We've been using the equivalent of ImGuiSelectableFlags_SetNavIdOnHover on all Selectable() since early Nav system days (commit 43ee5d73),
// but I am unsure whether this should be kept at all. For now moved it to be an opt-in feature used by menus only.
ImGuiSelectableFlags flags = ImGuiSelectableFlags_SelectOnRelease | ImGuiSelectableFlags_SetNavIdOnHover | (enabled ? 0 : ImGuiSelectableFlags_Disabled);
bool pressed;
if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
{
// Mimic the exact layout spacing of BeginMenu() to allow MenuItem() inside a menu bar, which is a little misleading but may be useful
// Note that in this situation: we don't render the shortcut, we render a highlight instead of the selected tick mark.
float w = label_size.x;
window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * 0.5f);
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x * 2.0f, style.ItemSpacing.y));
pressed = ImGui::Selectable(label, selected, flags, ImVec2(w, 0.0f));
ImGui::PopStyleVar();
window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar().
}
else
{
// Menu item inside a vertical menu
// (In a typical menu window where all items are BeginMenu() or MenuItem() calls, extra_w will always be 0.0f.
// Only when they are other items sticking out we're going to add spacing, yet only register minimum width into the layout system.
float shortcut_w = shortcut ? ImGui::CalcTextSize(shortcut, NULL).x : 0.0f;
float min_w = window->DC.MenuColumns.DeclColumns(label_size.x, shortcut_w, IM_FLOOR(g.FontSize * 1.20f)); // Feedback for next frame
float extra_w = std::max(0.0f, ImGui::GetContentRegionAvail().x - min_w);
pressed = ImGui::Selectable(label, false, flags | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, 0.0f));
ImVec2 pos_min = pos + ImVec2(window->DC.MenuColumns.Pos[2] + extra_w + g.FontSize * 0.40f, g.FontSize * 0.134f * 0.5f);
ImGui::RenderFrame(pos_min, pos_min + ImVec2(14, 14), icon_color);
if (shortcut_w > 0.0f)
{
ImGui::PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]);
ImGui::RenderText(pos + ImVec2(window->DC.MenuColumns.Pos[1] + extra_w, 0.0f), shortcut, NULL, false);
ImGui::PopStyleColor();
}
if (selected)
ImGui::RenderCheckMark(window->DrawList, pos + ImVec2(window->DC.MenuColumns.Pos[2] + extra_w + g.FontSize * 0.40f, g.FontSize * 0.134f * 0.5f), ImGui::GetColorU32(enabled ? ImGuiCol_Text : ImGuiCol_TextDisabled), g.FontSize * 0.866f);
}
IMGUI_TEST_ENGINE_ITEM_INFO(window->DC.LastItemId, label, window->DC.LastItemStatusFlags | ImGuiItemStatusFlags_Checkable | (selected ? ImGuiItemStatusFlags_Checked : 0));
return pressed;
}
ImGuiWrapper::ImGuiWrapper()
{
ImGui::CreateContext();
@ -606,7 +556,7 @@ bool ImGuiWrapper::bbl_slider_float_style(const std::string &label, float *v, fl
bool ImGuiWrapper::bbl_slider_float(const std::string& label, float* v, float v_min, float v_max, const char* format, float power, bool clamp, const wxString& tooltip)
{
const float max_tooltip_width = ImGui::GetFontSize() * 20.0f;
// let the label string start with "##" to hide the automatic label from ImGui::SliderFloat()
@ -969,7 +919,7 @@ bool ImGuiWrapper::combo(const wxString& label, const std::vector<std::string>&
return res;
}
// Scroll up for one item
// Scroll up for one item
static void scroll_up()
{
ImGuiContext& g = *GImGui;
@ -981,7 +931,7 @@ static void scroll_up()
ImGui::SetScrollY(win_top - item_size_y);
}
// Scroll down for one item
// Scroll down for one item
static void scroll_down()
{
ImGuiContext& g = *GImGui;
@ -1170,14 +1120,17 @@ static bool selectable(const char* label, bool selected, ImGuiSelectableFlags fl
// mark a label with a ColorMarkerHovered, if item is hovered
char marked_label[512]; //255 symbols is not enough for translated string (e.t. to Russian)
if (hovered)
if (hovered || selected) {
sprintf(marked_label, "%c%s", ImGui::ColorMarkerHovered, label);
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
}
else
strcpy(marked_label, label);
if (flags & ImGuiSelectableFlags_Disabled) ImGui::PushStyleColor(ImGuiCol_Text, style.Colors[ImGuiCol_TextDisabled]);
ImGui::RenderTextClipped(text_min, text_max, marked_label, NULL, &label_size, style.SelectableTextAlign, &bb);
if (flags & ImGuiSelectableFlags_Disabled) ImGui::PopStyleColor();
if (hovered || selected) ImGui::PopStyleColor();
// Automatically close popups
if (pressed && (window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiSelectableFlags_DontClosePopups) && !(g.CurrentItemFlags & ImGuiItemFlags_SelectableDontClosePopup))
@ -1187,6 +1140,228 @@ static bool selectable(const char* label, bool selected, ImGuiSelectableFlags fl
return pressed;
}
bool begin_menu(const char *label, bool enabled)
{
ImGuiWindow *window = ImGui::GetCurrentWindow();
if (window->SkipItems) return false;
ImGuiContext & g = *GImGui;
const ImGuiStyle &style = g.Style;
const ImGuiID id = window->GetID(label);
bool menu_is_open = ImGui::IsPopupOpen(id, ImGuiPopupFlags_None);
// Sub-menus are ChildWindow so that mouse can be hovering across them (otherwise top-most popup menu would steal focus and not allow hovering on parent menu)
ImGuiWindowFlags flags = ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar |
ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoNavFocus;
if (window->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) flags |= ImGuiWindowFlags_ChildWindow;
// If a menu with same the ID was already submitted, we will append to it, matching the behavior of Begin().
// We are relying on a O(N) search - so O(N log N) over the frame - which seems like the most efficient for the expected small amount of BeginMenu() calls per frame.
// If somehow this is ever becoming a problem we can switch to use e.g. ImGuiStorage mapping key to last frame used.
if (g.MenusIdSubmittedThisFrame.contains(id)) {
if (menu_is_open)
menu_is_open = ImGui::BeginPopupEx(id, flags); // menu_is_open can be 'false' when the popup is completely clipped (e.g. zero size display)
else
g.NextWindowData.ClearFlags(); // we behave like Begin() and need to consume those values
return menu_is_open;
}
// Tag menu as used. Next time BeginMenu() with same ID is called it will append to existing menu
g.MenusIdSubmittedThisFrame.push_back(id);
ImVec2 label_size = ImGui::CalcTextSize(label, NULL, true);
bool pressed;
bool menuset_is_open = !(window->Flags & ImGuiWindowFlags_Popup) &&
(g.OpenPopupStack.Size > g.BeginPopupStack.Size && g.OpenPopupStack[g.BeginPopupStack.Size].OpenParentId == window->IDStack.back());
ImGuiWindow *backed_nav_window = g.NavWindow;
if (menuset_is_open) g.NavWindow = window; // Odd hack to allow hovering across menus of a same menu-set (otherwise we wouldn't be able to hover parent)
// The reference position stored in popup_pos will be used by Begin() to find a suitable position for the child menu,
// However the final position is going to be different! It is chosen by FindBestWindowPosForPopup().
// e.g. Menus tend to overlap each other horizontally to amplify relative Z-ordering.
ImVec2 popup_pos, pos = window->DC.CursorPos;
if (window->DC.LayoutType == ImGuiLayoutType_Horizontal) {
// Menu inside an horizontal menu bar
// Selectable extend their highlight by half ItemSpacing in each direction.
// For ChildMenu, the popup position will be overwritten by the call to FindBestWindowPosForPopup() in Begin()
popup_pos = ImVec2(pos.x - 1.0f - IM_FLOOR(style.ItemSpacing.x * 0.5f), pos.y - style.FramePadding.y + window->MenuBarHeight());
window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * 0.5f);
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x * 2.0f, style.ItemSpacing.y));
float w = label_size.x;
pressed = selectable(label, menu_is_open,
ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_SelectOnClick | ImGuiSelectableFlags_DontClosePopups |
(!enabled ? ImGuiSelectableFlags_Disabled : 0),
ImVec2(w, 0.0f));
ImGui::PopStyleVar();
window->DC.CursorPos.x += IM_FLOOR(
style.ItemSpacing.x *
(-1.0f +
0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar().
} else {
// Menu inside a menu
// (In a typical menu window where all items are BeginMenu() or MenuItem() calls, extra_w will always be 0.0f.
// Only when they are other items sticking out we're going to add spacing, yet only register minimum width into the layout system.
popup_pos = ImVec2(pos.x, pos.y - style.WindowPadding.y);
float min_w = window->DC.MenuColumns.DeclColumns(label_size.x, 0.0f, IM_FLOOR(g.FontSize * 1.20f)); // Feedback to next frame
float extra_w = ImMax(0.0f, ImGui::GetContentRegionAvail().x - min_w);
pressed = selectable(label, menu_is_open,
ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_SelectOnClick | ImGuiSelectableFlags_DontClosePopups |
ImGuiSelectableFlags_SpanAvailWidth | (!enabled ? ImGuiSelectableFlags_Disabled : 0),
ImVec2(min_w, 0.0f));
ImU32 text_col = ImGui::GetColorU32(enabled ? ImGuiCol_Text : ImGuiCol_TextDisabled);
ImGui::RenderArrow(window->DrawList, pos + ImVec2(window->DC.MenuColumns.Pos[2] + extra_w + g.FontSize * 0.30f, 0.0f), text_col, ImGuiDir_Right);
}
const bool hovered = enabled && ImGui::ItemHoverable(window->DC.LastItemRect, id);
if (menuset_is_open) g.NavWindow = backed_nav_window;
bool want_open = false;
bool want_close = false;
if (window->DC.LayoutType == ImGuiLayoutType_Vertical) // (window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu))
{
// Close menu when not hovering it anymore unless we are moving roughly in the direction of the menu
// Implement http://bjk5.com/post/44698559168/breaking-down-amazons-mega-dropdown to avoid using timers, so menus feels more reactive.
bool moving_toward_other_child_menu = false;
ImGuiWindow *child_menu_window = (g.BeginPopupStack.Size < g.OpenPopupStack.Size && g.OpenPopupStack[g.BeginPopupStack.Size].SourceWindow == window) ?
g.OpenPopupStack[g.BeginPopupStack.Size].Window :
NULL;
if (g.HoveredWindow == window && child_menu_window != NULL && !(window->Flags & ImGuiWindowFlags_MenuBar)) {
// FIXME-DPI: Values should be derived from a master "scale" factor.
ImRect next_window_rect = child_menu_window->Rect();
ImVec2 ta = g.IO.MousePos - g.IO.MouseDelta;
ImVec2 tb = (window->Pos.x < child_menu_window->Pos.x) ? next_window_rect.GetTL() : next_window_rect.GetTR();
ImVec2 tc = (window->Pos.x < child_menu_window->Pos.x) ? next_window_rect.GetBL() : next_window_rect.GetBR();
float extra = ImClamp(ImFabs(ta.x - tb.x) * 0.30f, 5.0f, 30.0f); // add a bit of extra slack.
ta.x += (window->Pos.x < child_menu_window->Pos.x) ? -0.5f : +0.5f; // to avoid numerical issues
tb.y = ta.y +
ImMax((tb.y - extra) - ta.y, -100.0f); // triangle is maximum 200 high to limit the slope and the bias toward large sub-menus // FIXME: Multiply by fb_scale?
tc.y = ta.y + ImMin((tc.y + extra) - ta.y, +100.0f);
moving_toward_other_child_menu = ImTriangleContainsPoint(ta, tb, tc, g.IO.MousePos);
// GetForegroundDrawList()->AddTriangleFilled(ta, tb, tc, moving_within_opened_triangle ? IM_COL32(0,128,0,128) : IM_COL32(128,0,0,128)); // [DEBUG]
}
if (menu_is_open && !hovered && g.HoveredWindow == window && g.HoveredIdPreviousFrame != 0 && g.HoveredIdPreviousFrame != id && !moving_toward_other_child_menu)
want_close = true;
if (!menu_is_open && hovered && pressed) // Click to open
want_open = true;
else if (!menu_is_open && hovered && !moving_toward_other_child_menu) // Hover to open
want_open = true;
if (g.NavActivateId == id) {
want_close = menu_is_open;
want_open = !menu_is_open;
}
if (g.NavId == id && g.NavMoveRequest && g.NavMoveDir == ImGuiDir_Right) // Nav-Right to open
{
want_open = true;
ImGui::NavMoveRequestCancel();
}
} else {
// Menu bar
if (menu_is_open && pressed && menuset_is_open) // Click an open menu again to close it
{
want_close = true;
want_open = menu_is_open = false;
} else if (pressed || (hovered && menuset_is_open && !menu_is_open)) // First click to open, then hover to open others
{
want_open = true;
} else if (g.NavId == id && g.NavMoveRequest && g.NavMoveDir == ImGuiDir_Down) // Nav-Down to open
{
want_open = true;
ImGui::NavMoveRequestCancel();
}
}
if (!enabled) // explicitly close if an open menu becomes disabled, facilitate users code a lot in pattern such as 'if (BeginMenu("options", has_object)) { ..use object.. }'
want_close = true;
if (want_close && ImGui::IsPopupOpen(id, ImGuiPopupFlags_None)) ImGui::ClosePopupToLevel(g.BeginPopupStack.Size, true);
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags | ImGuiItemStatusFlags_Openable | (menu_is_open ? ImGuiItemStatusFlags_Opened : 0));
if (!menu_is_open && want_open && g.OpenPopupStack.Size > g.BeginPopupStack.Size) {
// Don't recycle same menu level in the same frame, first close the other menu and yield for a frame.
ImGui::OpenPopup(label);
return false;
}
menu_is_open |= want_open;
if (want_open) ImGui::OpenPopup(label);
if (menu_is_open) {
ImGui::SetNextWindowPos(popup_pos,
ImGuiCond_Always); // Note: this is super misleading! The value will serve as reference for FindBestWindowPosForPopup(), not actual pos.
menu_is_open = ImGui::BeginPopupEx(id, flags); // menu_is_open can be 'false' when the popup is completely clipped (e.g. zero size display)
} else {
g.NextWindowData.ClearFlags(); // We behave like Begin() and need to consume those values
}
return menu_is_open;
}
void end_menu()
{
ImGui::EndMenu();
}
bool menu_item_with_icon(const char *label, const char *shortcut, ImVec2 icon_size /* = ImVec2(0, 0)*/, ImU32 icon_color /* = 0*/, bool selected /* = false*/, bool enabled /* = true*/)
{
ImGuiWindow *window = ImGui::GetCurrentWindow();
if (window->SkipItems) return false;
ImGuiContext &g = *GImGui;
ImGuiStyle & style = g.Style;
ImVec2 pos = window->DC.CursorPos;
ImVec2 label_size = ImGui::CalcTextSize(label, NULL, true);
// We've been using the equivalent of ImGuiSelectableFlags_SetNavIdOnHover on all Selectable() since early Nav system days (commit 43ee5d73),
// but I am unsure whether this should be kept at all. For now moved it to be an opt-in feature used by menus only.
ImGuiSelectableFlags flags = ImGuiSelectableFlags_SelectOnRelease | ImGuiSelectableFlags_SetNavIdOnHover | (enabled ? 0 : ImGuiSelectableFlags_Disabled);
bool pressed;
if (window->DC.LayoutType == ImGuiLayoutType_Horizontal) {
// Mimic the exact layout spacing of BeginMenu() to allow MenuItem() inside a menu bar, which is a little misleading but may be useful
// Note that in this situation: we don't render the shortcut, we render a highlight instead of the selected tick mark.
float w = label_size.x;
window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * 0.5f);
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x * 2.0f, style.ItemSpacing.y));
pressed = ImGui::Selectable(label, selected, flags, ImVec2(w, 0.0f));
ImGui::PopStyleVar();
window->DC.CursorPos.x += IM_FLOOR(
style.ItemSpacing.x *
(-1.0f +
0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar().
} else {
// Menu item inside a vertical menu
// (In a typical menu window where all items are BeginMenu() or MenuItem() calls, extra_w will always be 0.0f.
// Only when they are other items sticking out we're going to add spacing, yet only register minimum width into the layout system.
float shortcut_w = shortcut ? ImGui::CalcTextSize(shortcut, NULL).x : 0.0f;
float min_w = window->DC.MenuColumns.DeclColumns(label_size.x, shortcut_w, IM_FLOOR(g.FontSize * 1.20f)); // Feedback for next frame
float extra_w = std::max(0.0f, ImGui::GetContentRegionAvail().x - min_w);
pressed = selectable(label, false, flags | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, 0.0f));
if (icon_size.x != 0 && icon_size.y != 0) {
float selectable_pos_y = pos.y + -0.5f * style.ItemSpacing.y;
float icon_pos_y = selectable_pos_y + (label_size.y + style.ItemSpacing.y - icon_size.y) / 2;
float icon_pos_x = pos.x + window->DC.MenuColumns.Pos[2] + extra_w + g.FontSize * 0.40f;
ImVec2 icon_pos = ImVec2(icon_pos_x, icon_pos_y);
ImGui::RenderFrame(icon_pos, icon_pos + icon_size, icon_color);
}
if (shortcut_w > 0.0f) {
ImGui::PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]);
ImGui::RenderText(pos + ImVec2(window->DC.MenuColumns.Pos[1] + extra_w, 0.0f), shortcut, NULL, false);
ImGui::PopStyleColor();
}
if (selected) {
//ImGui::RenderCheckMark(window->DrawList, pos + ImVec2(window->DC.MenuColumns.Pos[2] + extra_w + g.FontSize * 0.40f, g.FontSize * 0.134f * 0.5f),
// ImGui::GetColorU32(enabled ? ImGuiCol_Text : ImGuiCol_TextDisabled), g.FontSize * 0.866f);
}
}
IMGUI_TEST_ENGINE_ITEM_INFO(window->DC.LastItemId, label, window->DC.LastItemStatusFlags | ImGuiItemStatusFlags_Checkable | (selected ? ImGuiItemStatusFlags_Checked : 0));
return pressed;
}
// Scroll so that the hovered item is at the top of the window
static void scroll_y(int hover_id)
{
@ -1229,7 +1404,7 @@ void ImGuiWrapper::search_list(const ImVec2& size_, bool (*items_getter)(int, co
{
int& hovered_id = view_params.hovered_id;
// ImGui::ListBoxHeader("", size);
{
{
// rewrote part of function to add a TextInput instead of label Text
ImGuiContext& g = *GImGui;
ImGuiWindow* window = ImGui::GetCurrentWindow();
@ -1445,13 +1620,13 @@ std::vector<unsigned char> ImGuiWrapper::load_svg(const std::string& bitmap_name
//BBS
void ImGuiWrapper::push_toolbar_style()
void ImGuiWrapper::push_toolbar_style(const float scale)
{
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(20.0f, 10.0f));
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 3.0f);
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f * scale);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(20.0f, 10.0f) * scale);
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 3.0f * scale);
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(10.0f, 10.0f));
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(10.0f, 10.0f) * scale);
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(50/255.0f, 58/255.0f, 61/255.0f, 1.00f)); // 1
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImGuiWrapper::COL_WINDOW_BG); // 2
ImGui::PushStyleColor(ImGuiCol_TitleBg, ImGuiWrapper::COL_TITLE_BG); // 3
@ -1476,11 +1651,11 @@ void ImGuiWrapper::pop_toolbar_style()
ImGui::PopStyleVar(5);
}
void ImGuiWrapper::push_menu_style()
void ImGuiWrapper::push_menu_style(const float scale)
{
ImGuiWrapper::push_toolbar_style();
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(10.0f, 10.0f));
ImGui::PushStyleVar(ImGuiStyleVar_PopupRounding, 4.0f);
ImGuiWrapper::push_toolbar_style(scale);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(10.0f, 10.0f) * scale);
ImGui::PushStyleVar(ImGuiStyleVar_PopupRounding, 4.0f * scale);
ImGui::PushStyleVar(ImGuiStyleVar_PopupBorderSize, 0.0f);
ImGui::PushStyleColor(ImGuiCol_PopupBg, ImGuiWrapper::COL_WINDOW_BG);
ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0.00f, 0.68f, 0.26f, 1.0f));

View file

@ -37,7 +37,9 @@ bool button_with_pos(ImTextureID user_texture_id,
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);
bool begin_menu(const char *label, bool enabled = true);
void end_menu();
bool menu_item_with_icon(const char *label, const char *shortcut, ImVec2 icon_size = ImVec2(0, 0), ImU32 icon_color = 0, bool selected = false, bool enabled = true);
class ImGuiWrapper
@ -181,9 +183,9 @@ public:
static const ImVec4 COL_SEPARATOR;
//BBS
static void push_toolbar_style();
static void push_toolbar_style(const float scale);
static void pop_toolbar_style();
static void push_menu_style();
static void push_menu_style(const float scale);
static void pop_menu_style();
//BBS

View file

@ -403,7 +403,7 @@ void ArrangeJob::prepare()
int state = m_plater->get_prepare_state();
if (state == Job::JobPrepareState::PREPARE_STATE_DEFAULT) {
only_on_partplate = false;
prepare_selected();
prepare_all();
}
else if (state == Job::JobPrepareState::PREPARE_STATE_MENU) {
only_on_partplate = true; // only arrange items on current plate
@ -412,7 +412,7 @@ void ArrangeJob::prepare()
//add the virtual object into unselect list if has
m_plater->get_partplate_list().preprocess_exclude_areas(m_unselected, MAX_NUM_PLATES);
#if SAVE_ARRANGE_POLY
if (1)
{ // subtract excluded region and get a polygon bed
@ -508,16 +508,8 @@ void ArrangeJob::process()
double skirt_distance = print.has_skirt() ? print.config().skirt_distance.value : 0;
bool is_auto_brim = print.has_auto_brim();
double brim_max = 0;
if (is_auto_brim) {
brim_max = 0;
std::for_each(m_selected.begin(), m_selected.end(), [&](ArrangePolygon ap) { brim_max = std::max(brim_max, ap.auto_brim_width); });
}
else {
brim_max = print.has_brim() ? print.default_object_config().brim_width : 0;
std::for_each(m_selected.begin(), m_selected.end(), [&](ArrangePolygon ap) { brim_max = std::max(brim_max, ap.user_brim_width); });
}
std::for_each(m_selected.begin(), m_selected.end(), [&](ArrangePolygon ap) { brim_max = std::max(brim_max, ap.brim_width); });
// Note: skirt_distance is now defined between outermost brim and skirt, not the object and skirt.
// So we can't do max but do adding instead.
@ -558,10 +550,8 @@ void ArrangeJob::process()
params.stopcondition = [this]() { return was_canceled(); };
auto count = unsigned(m_selected.size());// + m_unprintable.size());
params.progressind = [this, count](unsigned num_finished, std::string str="") {
// if (num_finished >= 0 && num_finished <= count)
// update_status(int(float(num_finished) / count * 100), _L("Arranging") + " "+str);
params.progressind = [this](unsigned num_finished, std::string str="") {
update_status(num_finished, _L("Arranging") + " " + str);
};
if(!params.is_seq_print)
@ -610,7 +600,7 @@ void ArrangeJob::process()
}
// finalize just here.
update_status(100,
update_status(status_range(),
was_canceled() ? _(L("Arranging canceled.")) :
we_have_unpackable_items ? _(L("Arranging is done but there are unpacked items. Reduce spacing and try again.")) : _(L("Arranging done.")));
}

View file

@ -59,7 +59,8 @@ public:
int status_range() const override
{
return int(m_selected.size() + m_unprintable.size());
// ensure finalize() is called after all operations in process() is finished.
return int(m_selected.size() + m_unprintable.size() + 1);
}
void finalize() override;

View file

@ -101,10 +101,10 @@ void PrintJob::process()
int curr_percent = 10;
if (this->connection_type == "lan") {
msg = sending_over_lan_str;
msg = _L("Sending print job over LAN");
}
else {
msg = sending_over_cloud_str;
msg = _L("Sending print job through cloud service");
}
int result = -1;

View file

@ -46,12 +46,12 @@ void UpgradeNetworkJob::process()
{
// downloading
int result = 0;
AppConfig* app_config = wxGetApp().app_config;
if (!app_config)
return;
BOOST_LOG_TRIVIAL(info) << "[download_plugin]: enter";
BOOST_LOG_TRIVIAL(info) << "[UpgradeNetworkJob process]: enter";
// get temp path
fs::path target_file_path = (fs::temp_directory_path() / "network_plugin.zip");
@ -74,7 +74,7 @@ void UpgradeNetworkJob::process()
}
curr_percent = percent;
}, cancel_fn);
if (was_canceled()) {
update_status(0, _L("Cancelled"));
wxCommandEvent event(wxEVT_CLOSE_WINDOW);
@ -84,7 +84,7 @@ void UpgradeNetworkJob::process()
}
if (result < 0) {
update_status(curr_percent, _L("Download failed"));
update_status(0, _L("Download failed"));
wxCommandEvent event(EVT_UPGRADE_NETWORK_FAILED);
event.SetEventObject(m_event_handle);
wxPostEvent(m_event_handle, event);
@ -108,7 +108,7 @@ void UpgradeNetworkJob::process()
}
if (result != 0) {
update_status(curr_percent, _L("Install failed"));
update_status(0, _L("Install failed"));
wxCommandEvent event(EVT_UPGRADE_NETWORK_FAILED);
event.SetEventObject(m_event_handle);
wxPostEvent(m_event_handle, event);
@ -118,6 +118,7 @@ void UpgradeNetworkJob::process()
wxCommandEvent event(EVT_UPGRADE_NETWORK_SUCCESS);
event.SetEventObject(m_event_handle);
wxPostEvent(m_event_handle, event);
BOOST_LOG_TRIVIAL(info) << "[UpgradeNetworkJob process]: exit";
return;
}

View file

@ -178,28 +178,14 @@ void KBShortcutsDialog::fill_shortcuts()
// File>Import
{ ctrl + "I", L("Import geometry data from STL/STEP/3MF/OBJ/AMF files.") },
// Edit
{ ctrl + "A", L("Select all objects") },
{ ctrl + "D", L("Delete all") },
{ ctrl + "Z", L("Undo") },
{ ctrl + "Y", L("Redo") },
{ ctrl + "X", L("Cut") },
{ ctrl + "C", L("Copy to clipboard") },
{ ctrl + "V", L("Paste from clipboard") },
{ ctrl + "M", L("Clone selected")},
// Window
{ ctrl + "0", L("Camera view - Default") },
{ ctrl + "1", L("Camera view - Top") },
{ ctrl + "2", L("Camera view - Bottom") },
{ ctrl + "3", L("Camera view - Front") },
{ ctrl + "4", L("Camera view - Behind") },
{ ctrl + "5", L("Camera Angle - Left side") },
{ ctrl + "6", L("Camera Angle - Right side") },
// Configuration
{ ctrl + "P", L("Preferences") },
{ "Esc", L("Deselect all") },
{ "Del", L("Delete selected") },
// View
{ "1-9", L("keyboard 1-9: set filament for object/part") },
#ifdef __APPLE__
{"fn+⌫", L("Delete selected")},
#else
{"Del", L("Delete selected")},
#endif
// Help
{ "?", L("Show keyboard shortcuts list") }
};
@ -209,16 +195,20 @@ void KBShortcutsDialog::fill_shortcuts()
{ "A", L("Arrange all objects") },
{ "Shift+A", L("Arrange objects on selected plates") },
{ "R", L("Auto orientates selected objects or all objects.If there are selected objects, it just orientates the selected ones.Otherwise, it will orientates all objects in the project.") },
//{ "R", L("Auto orientates selected objects or all objects.If there are selected objects, it just orientates the selected ones.Otherwise, it will orientates all objects in the project.") },
{"Shift+R", L("Auto orientates selected objects or all objects.If there are selected objects, it just orientates the selected ones.Otherwise, it will orientates all objects in the current disk.")},
#ifdef __APPLE__
{"Shift+Tab", L("Collapse/Expand the sidebar")},
#ifdef __APPLE__
{L("⌘+Any arrow"), L("Movement in camera space")},
{L("⌥+Left mouse button"), L("Select a part")},
{L("⌘+Left mouse button"), L("Select multiple objects")},
#else
{L("Ctrl+Left mouse button"), L("Select multiple objects")},
#endif
{L("Ctrl+Any arrow"), L("Movement in camera space")},
{L("Alt+Left mouse button"), L("Select a part")},
{L("Ctrl+Left mouse button"), L("Select multiple objects")},
#endif
{L("Shift+Left mouse button"), L("Select objects by rectangle")},
{L("Arrow Up"), L("Move selection 10 mm in positive Y direction")},
{L("Arrow Down"), L("Move selection 10 mm in negative Y direction")},
@ -226,12 +216,27 @@ void KBShortcutsDialog::fill_shortcuts()
{L("Arrow Right"), L("Move selection 10 mm in positive X direction")},
{L("Shift+Any arrow"), L("Movement step set to 1 mm")},
#ifdef __APPLE__
{L("⌘+Any arrow"), L("Movement in camera space")},
#else
{L("Ctrl+Any arrow"), L("Movement in camera space")},
#endif
{"Shift+Tab", L("Collapse/Expand the sidebar")},
{"Esc", L("Deselect all")},
{"1-9", L("keyboard 1-9: set filament for object/part")},
{ctrl + "0", L("Camera view - Default")},
{ctrl + "1", L("Camera view - Top")},
{ctrl + "2", L("Camera view - Bottom")},
{ctrl + "3", L("Camera view - Front")},
{ctrl + "4", L("Camera view - Behind")},
{ctrl + "5", L("Camera Angle - Left side")},
{ctrl + "6", L("Camera Angle - Right side")},
{ctrl + "A", L("Select all objects")},
{ctrl + "D", L("Delete all")},
{ctrl + "Z", L("Undo")},
{ctrl + "Y", L("Redo")},
{ctrl + "M", L("Clone selected")},
{ "M", L("Gizmo move") },
{ "S", L("Gizmo scale") },
{ "R", L("Gizmo rotate") },
{ "C", L("Gizmo cut") },
{ "F", L("Gizmo Place face on bed") },
{ "L", L("Gizmo SLA support points") },
{ "P", L("Gizmo FDM paint-on seam") },
};
m_full_shortcuts.push_back({ { _L("Plater"), "" }, plater_shortcuts });
@ -305,34 +310,25 @@ wxPanel* KBShortcutsDialog::create_page(wxWindow* parent, const ShortcutsItem& s
main_sizer->AddSpacer(FromDIP(10));
}
static const int max_items_per_column = 20;
int columns_count = 1 + static_cast<int>(shortcuts.second.size()) / max_items_per_column;
wxScrolledWindow* scrollable_panel = new wxScrolledWindow(main_page);
int items_count = (int) shortcuts.second.size();
wxScrolledWindow *scrollable_panel = new wxScrolledWindow(main_page);
wxGetApp().UpdateDarkUI(scrollable_panel);
scrollable_panel->SetScrollbars(20, 20, 50, 50);
scrollable_panel->SetInitialSize(wxSize(FromDIP(850), FromDIP(450)));
wxBoxSizer* scrollable_panel_sizer = new wxBoxSizer(wxVERTICAL);
wxFlexGridSizer* grid_sizer = new wxFlexGridSizer(3 * columns_count, 5, 15);
wxBoxSizer * scrollable_panel_sizer = new wxBoxSizer(wxVERTICAL);
wxFlexGridSizer *grid_sizer = new wxFlexGridSizer(items_count, 2, FromDIP(10), FromDIP(20));
int items_count = (int)shortcuts.second.size();
for (int i = 0; i < max_items_per_column; ++i) {
for (int j = 0; j < columns_count; ++j) {
int id = j * max_items_per_column + i;
if (id < items_count) {
const auto& [shortcut, description] = shortcuts.second[id];
auto key = new wxStaticText(scrollable_panel, wxID_ANY, _(shortcut));
key->SetFont(bold_font);
grid_sizer->Add(key, 0, wxALIGN_CENTRE_VERTICAL);
for (int i = 0; i < items_count; ++i) {
const auto &[shortcut, description] = shortcuts.second[i];
auto key = new wxStaticText(scrollable_panel, wxID_ANY, _(shortcut));
key->SetFont(bold_font);
grid_sizer->Add(key, 0, wxALIGN_CENTRE_VERTICAL);
grid_sizer->Add(new wxStaticText(scrollable_panel, wxID_ANY, " "), 0, wxALIGN_CENTRE_VERTICAL);
auto desc = new wxStaticText(scrollable_panel, wxID_ANY, _(description));
desc->SetFont(font);
grid_sizer->Add(desc, 0, wxALIGN_CENTRE_VERTICAL);
}
}
auto desc = new wxStaticText(scrollable_panel, wxID_ANY, _(description));
desc->SetFont(font);
desc->Wrap(FromDIP(600));
grid_sizer->Add(desc, 0, wxALIGN_CENTRE_VERTICAL);
}
scrollable_panel_sizer->Add(grid_sizer, 1, wxEXPAND | wxALL, FromDIP(20));

View file

@ -142,7 +142,7 @@ static wxIcon main_frame_icon(GUI_App::EAppMode app_mode)
#ifdef __WINDOWS__
#define BORDERLESS_FRAME_STYLE (wxRESIZE_BORDER | wxMINIMIZE_BOX | wxMAXIMIZE_BOX | wxCLOSE_BOX)
#else
#define BORDERLESS_FRAME_STYLE (wxRESIZE_BORDER)
#define BORDERLESS_FRAME_STYLE (wxMINIMIZE_BOX | wxMAXIMIZE_BOX | wxCLOSE_BOX)
#endif
wxDEFINE_EVENT(EVT_SYNC_CLOUD_PRESET, SimpleEvent);
@ -184,8 +184,6 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, BORDERLESS_FRAME_
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(this);
sizer_tobar->Add(m_topbar, 0, wxEXPAND);
panel_topbar->SetSizer(sizer_tobar);
panel_topbar->Layout();
#endif
@ -206,7 +204,7 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, BORDERLESS_FRAME_
default:
case GUI_App::EAppMode::Editor:
m_taskbar_icon = std::make_unique<BambuStudioTaskBarIcon>(wxTBI_DOCK);
m_taskbar_icon->SetIcon(wxIcon(Slic3r::var("BambuStudio-mac_128px.png"), wxBITMAP_TYPE_PNG), "BambuStudio");
m_taskbar_icon->SetIcon(wxIcon(Slic3r::var("BambuStudio-mac_256px.ico"), wxBITMAP_TYPE_ICO), "BambuStudio");
break;
case GUI_App::EAppMode::GCodeViewer:
break;
@ -238,61 +236,63 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, BORDERLESS_FRAME_
#endif // _WIN32
// BBS
wxAcceleratorEntry entries[13];
int index = 0;
entries[index++].Set(wxACCEL_CTRL, (int)'N', wxID_HIGHEST + wxID_NEW);
entries[index++].Set(wxACCEL_CTRL, (int)'O', wxID_HIGHEST + wxID_OPEN);
entries[index++].Set(wxACCEL_CTRL, (int)'S', wxID_HIGHEST + wxID_SAVE);
entries[index++].Set(wxACCEL_CTRL | wxACCEL_SHIFT, (int)'S', wxID_HIGHEST + wxID_SAVEAS);
entries[index++].Set(wxACCEL_CTRL, (int)'X', wxID_HIGHEST + wxID_CUT);
//entries[index++].Set(wxACCEL_CTRL, (int)'I', wxID_HIGHEST + wxID_ADD);
entries[index++].Set(wxACCEL_CTRL, (int)'A', wxID_HIGHEST + wxID_SELECTALL);
entries[index++].Set(wxACCEL_NORMAL, (int)27 /* escape */, wxID_HIGHEST + wxID_CANCEL);
entries[index++].Set(wxACCEL_CTRL, (int)'Z', wxID_HIGHEST + wxID_UNDO);
entries[index++].Set(wxACCEL_CTRL, (int)'Y', wxID_HIGHEST + wxID_REDO);
entries[index++].Set(wxACCEL_CTRL, (int)'C', wxID_HIGHEST + wxID_COPY);
entries[index++].Set(wxACCEL_CTRL, (int)'V', wxID_HIGHEST + wxID_PASTE);
entries[index++].Set(wxACCEL_CTRL, (int)'P', wxID_HIGHEST + wxID_PREFERENCES);
entries[index++].Set(wxACCEL_CTRL, (int)'I', wxID_HIGHEST + wxID_FILE6);
wxAcceleratorTable accel(sizeof(entries) / sizeof(entries[0]), entries);
SetAcceleratorTable(accel);
//wxAcceleratorEntry entries[13];
//int index = 0;
//entries[index++].Set(wxACCEL_CTRL, (int)'N', wxID_HIGHEST + wxID_NEW);
//entries[index++].Set(wxACCEL_CTRL, (int)'O', wxID_HIGHEST + wxID_OPEN);
//entries[index++].Set(wxACCEL_CTRL, (int)'S', wxID_HIGHEST + wxID_SAVE);
//entries[index++].Set(wxACCEL_CTRL | wxACCEL_SHIFT, (int)'S', wxID_HIGHEST + wxID_SAVEAS);
//entries[index++].Set(wxACCEL_CTRL, (int)'X', wxID_HIGHEST + wxID_CUT);
////entries[index++].Set(wxACCEL_CTRL, (int)'I', wxID_HIGHEST + wxID_ADD);
//entries[index++].Set(wxACCEL_CTRL, (int)'A', wxID_HIGHEST + wxID_SELECTALL);
//entries[index++].Set(wxACCEL_NORMAL, (int)27 /* escape */, wxID_HIGHEST + wxID_CANCEL);
//entries[index++].Set(wxACCEL_CTRL, (int)'Z', wxID_HIGHEST + wxID_UNDO);
//entries[index++].Set(wxACCEL_CTRL, (int)'Y', wxID_HIGHEST + wxID_REDO);
//entries[index++].Set(wxACCEL_CTRL, (int)'C', wxID_HIGHEST + wxID_COPY);
//entries[index++].Set(wxACCEL_CTRL, (int)'V', wxID_HIGHEST + wxID_PASTE);
//entries[index++].Set(wxACCEL_CTRL, (int)'P', wxID_HIGHEST + wxID_PREFERENCES);
//entries[index++].Set(wxACCEL_CTRL, (int)'I', wxID_HIGHEST + wxID_FILE6);
//wxAcceleratorTable accel(sizeof(entries) / sizeof(entries[0]), entries);
//SetAcceleratorTable(accel);
Bind(wxEVT_MENU, [this](wxCommandEvent&) { m_plater->new_project(); }, wxID_HIGHEST + wxID_NEW);
Bind(wxEVT_MENU, [this](wxCommandEvent&) { m_plater->load_project(); }, wxID_HIGHEST + wxID_OPEN);
// BBS: close save project
Bind(wxEVT_MENU, [this](wxCommandEvent&) { if (m_plater) m_plater->save_project(); }, wxID_HIGHEST + wxID_SAVE);
Bind(wxEVT_MENU, [this](wxCommandEvent&) { if (m_plater) m_plater->save_project(true); }, wxID_HIGHEST + wxID_SAVEAS);
//Bind(wxEVT_MENU, [this](wxCommandEvent&) { if (m_plater) m_plater->add_model(); }, wxID_HIGHEST + wxID_ADD);
//Bind(wxEVT_MENU, [this](wxCommandEvent&) { m_plater->remove_selected(); }, wxID_HIGHEST + wxID_DELETE);
Bind(wxEVT_MENU, [this](wxCommandEvent&) {
if (!can_add_models())
return;
if (m_plater) {
m_plater->add_model();
}
}, wxID_HIGHEST + wxID_FILE6);
Bind(wxEVT_MENU, [this](wxCommandEvent&) { m_plater->select_all(); }, wxID_HIGHEST + wxID_SELECTALL);
Bind(wxEVT_MENU, [this](wxCommandEvent&) { m_plater->deselect_all(); }, wxID_HIGHEST + wxID_CANCEL);
Bind(wxEVT_MENU, [this](wxCommandEvent&) {
if (m_plater->is_view3D_shown())
m_plater->undo();
}, wxID_HIGHEST + wxID_UNDO);
Bind(wxEVT_MENU, [this](wxCommandEvent&) {
if (m_plater->is_view3D_shown())
m_plater->redo();
}, wxID_HIGHEST + wxID_REDO);
Bind(wxEVT_MENU, [this](wxCommandEvent&) { m_plater->copy_selection_to_clipboard(); }, wxID_HIGHEST + wxID_COPY);
Bind(wxEVT_MENU, [this](wxCommandEvent&) { m_plater->paste_from_clipboard(); }, wxID_HIGHEST + wxID_PASTE);
Bind(wxEVT_MENU, [this](wxCommandEvent&) { m_plater->cut_selection_to_clipboard(); }, wxID_HIGHEST + wxID_CUT);
//Bind(wxEVT_MENU, [this](wxCommandEvent&) { m_plater->new_project(); }, wxID_HIGHEST + wxID_NEW);
//Bind(wxEVT_MENU, [this](wxCommandEvent&) { m_plater->load_project(); }, wxID_HIGHEST + wxID_OPEN);
//// BBS: close save project
//Bind(wxEVT_MENU, [this](wxCommandEvent&) { if (m_plater) m_plater->save_project(); }, wxID_HIGHEST + wxID_SAVE);
//Bind(wxEVT_MENU, [this](wxCommandEvent&) { if (m_plater) m_plater->save_project(true); }, wxID_HIGHEST + wxID_SAVEAS);
////Bind(wxEVT_MENU, [this](wxCommandEvent&) { if (m_plater) m_plater->add_model(); }, wxID_HIGHEST + wxID_ADD);
////Bind(wxEVT_MENU, [this](wxCommandEvent&) { m_plater->remove_selected(); }, wxID_HIGHEST + wxID_DELETE);
//Bind(wxEVT_MENU, [this](wxCommandEvent&) {
// if (!can_add_models())
// return;
// if (m_plater) {
// m_plater->add_model();
// }
// }, wxID_HIGHEST + wxID_FILE6);
//Bind(wxEVT_MENU, [this](wxCommandEvent&) { m_plater->select_all(); }, wxID_HIGHEST + wxID_SELECTALL);
//Bind(wxEVT_MENU, [this](wxCommandEvent&) { m_plater->deselect_all(); }, wxID_HIGHEST + wxID_CANCEL);
//Bind(wxEVT_MENU, [this](wxCommandEvent&) {
// if (m_plater->is_view3D_shown())
// m_plater->undo();
// }, wxID_HIGHEST + wxID_UNDO);
//Bind(wxEVT_MENU, [this](wxCommandEvent&) {
// if (m_plater->is_view3D_shown())
// m_plater->redo();
// }, wxID_HIGHEST + wxID_REDO);
//Bind(wxEVT_MENU, [this](wxCommandEvent&) { m_plater->copy_selection_to_clipboard(); }, wxID_HIGHEST + wxID_COPY);
//Bind(wxEVT_MENU, [this](wxCommandEvent&) { m_plater->paste_from_clipboard(); }, wxID_HIGHEST + wxID_PASTE);
//Bind(wxEVT_MENU, [this](wxCommandEvent&) { m_plater->cut_selection_to_clipboard(); }, wxID_HIGHEST + wxID_CUT);
Bind(wxEVT_SIZE, [this](wxSizeEvent&) {
BOOST_LOG_TRIVIAL(trace) << "mainframe: size changed, is maximized = " << this->IsMaximized();
#ifdef __WINDOWS__
if (this->IsMaximized()) {
m_topbar->SetWindowSize();
} else {
m_topbar->SetMaximizedSize();
}
Refresh();
Layout();
#endif
Refresh();
Layout();
});
//BBS
@ -302,18 +302,18 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, BORDERLESS_FRAME_
});
Bind(EVT_SYNC_CLOUD_PRESET, &MainFrame::on_select_default_preset, this);
Bind(wxEVT_MENU,
[this](wxCommandEvent&)
{
PreferencesDialog dlg(this);
dlg.ShowModal();
#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER
if (dlg.seq_top_layer_only_changed() || dlg.seq_seq_top_gcode_indices_changed())
#else
if (dlg.seq_top_layer_only_changed())
#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER
plater()->refresh_print();
}, wxID_HIGHEST + wxID_PREFERENCES);
// Bind(wxEVT_MENU,
// [this](wxCommandEvent&)
// {
// PreferencesDialog dlg(this);
// dlg.ShowModal();
//#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER
// if (dlg.seq_top_layer_only_changed() || dlg.seq_seq_top_gcode_indices_changed())
//#else
// if (dlg.seq_top_layer_only_changed())
//#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER
// plater()->refresh_print();
// }, wxID_HIGHEST + wxID_PREFERENCES);
// set default tooltip timer in msec
@ -352,6 +352,12 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, BORDERLESS_FRAME_
e.Skip();
});
setMaxSize();
this->Bind(wxEVT_MAXIMIZE, [this](auto &e) {
wxDisplay display(wxDisplay::GetFromWindow(this));
auto pos = display.GetClientArea().GetPosition();
Move(pos - wxPoint{8, 8});
e.Skip();
});
#endif // WIN32
// BBS
Fit();
@ -468,6 +474,35 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, BORDERLESS_FRAME_
Slic3r::run_backup_ui_tasks();
});
; }
this->Bind(wxEVT_CHAR_HOOK, [this](wxKeyEvent &evt) {
#ifdef __APPLE__
if (evt.CmdDown() && evt.GetKeyCode() == 'H') { this->Iconize(); return;}
if (evt.CmdDown() && evt.GetKeyCode() == 'Q') { wxPostEvent(this, wxCloseEvent(wxEVT_CLOSE_WINDOW)); return;}
#endif
if (evt.CmdDown() && evt.GetKeyCode() == 'N') { m_plater->new_project(); return;}
if (evt.CmdDown() && evt.GetKeyCode() == 'O') { m_plater->load_project(); return;}
if (evt.CmdDown() && evt.ShiftDown() && evt.GetKeyCode() == 'S') { if (m_plater) m_plater->save_project(true); return;}
else if (evt.CmdDown() && evt.GetKeyCode() == 'S') { if (m_plater) m_plater->save_project(); return;}
if (evt.CmdDown() && evt.GetKeyCode() == 'P') {
PreferencesDialog dlg(this);
dlg.ShowModal();
#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER
if (dlg.seq_top_layer_only_changed() || dlg.seq_seq_top_gcode_indices_changed())
#else
if (dlg.seq_top_layer_only_changed())
#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER
plater()->refresh_print();
return;
}
if (evt.CmdDown() && evt.GetKeyCode() == 'I') {
if (!can_add_models()) return;
if (m_plater) { m_plater->add_model(); }
return;
}
evt.Skip();
});
}
#ifdef __WIN32__
@ -700,13 +735,21 @@ void MainFrame::shutdown()
// to avoid any manipulations with them from App->wxEVT_IDLE after of the mainframe closing
wxGetApp().tabs_list.clear();
wxGetApp().model_tabs_list.clear();
wxGetApp().shutdown();
// BBS: why clear ?
//wxGetApp().plater_ = nullptr;
}
void MainFrame::update_title()
{
return;
return;
}
void MainFrame::update_title_colour_after_set_title()
{
#ifdef __WXOSX__
set_title_colour_after_set_title();
#endif
}
void MainFrame::show_option(bool show)
@ -792,13 +835,14 @@ void MainFrame::init_tabpanel()
//monitor
}
#ifdef __WINDOWS__
if (sel == tp3DEditor) {
m_topbar->EnableUndoRedoItems();
}
else {
m_topbar->DisableUndoRedoItems();
}
#endif
/*switch (sel) {
case TabPosition::tpHome:
@ -1452,8 +1496,10 @@ void MainFrame::on_dpi_changed(const wxRect& suggested_rect)
dynamic_cast<Notebook*>(m_tabpanel)->Rescale();
#endif
#ifdef __WINDOWS__
// BBS
m_topbar->Rescale();
#endif
m_tabpanel->Rescale();
@ -1573,9 +1619,11 @@ static wxMenu* generate_help_menu()
return true;
});
// About
#ifdef __WINDOWS__
wxString about_title = wxString::Format(_L("&About %s"), SLIC3R_APP_FULL_NAME);
append_menu_item(helpMenu, wxID_ANY, about_title, about_title,
[](wxCommandEvent&) { Slic3r::GUI::about(); });
#endif
return helpMenu;
}
@ -1605,6 +1653,7 @@ void MainFrame::init_menubar_as_editor()
{
#ifdef __APPLE__
wxMenuBar::SetAutoWindowMenu(false);
m_menubar = new wxMenuBar();
#endif
// File menu
@ -1867,10 +1916,18 @@ void MainFrame::init_menubar_as_editor()
//auto config_wizard_name = _(ConfigWizard::name(true) + "(Debug)");
//const auto config_wizard_tooltip = from_u8((boost::format(_utf8(L("Run %s"))) % config_wizard_name).str());
//auto config_item = new wxMenuItem(m_topbar->GetTopMenu(), ConfigMenuWizard + config_id_base, config_wizard_name, config_wizard_tooltip);
auto preference_item = new wxMenuItem(m_topbar->GetTopMenu(), ConfigMenuPreferences + config_id_base, _L("Preferences") + "\tCtrl+P", "");
//auto printer_item = new wxMenuItem(m_topbar->GetTopMenu(), ConfigMenuPrinter + config_id_base, _L("Printer"), "");
//auto language_item = new wxMenuItem(m_topbar->GetTopMenu(), ConfigMenuLanguage + config_id_base, _L("Switch Language"), "");
m_topbar->GetTopMenu()->Bind(wxEVT_MENU, [this, config_id_base](wxEvent& event) {
#ifdef __APPLE__
wxWindowID bambu_studio_id_base = wxWindow::NewControlId(int(2));
wxMenu* parent_menu = m_menubar->OSXGetAppleMenu();
auto preference_item = new wxMenuItem(parent_menu, BambuStudioMenuPreferences + bambu_studio_id_base, _L("Preferences") + "\tCtrl+P", "");
#else
wxMenu* parent_menu = m_topbar->GetTopMenu();
auto preference_item = new wxMenuItem(parent_menu, ConfigMenuPreferences + config_id_base, _L("Preferences") + "\tCtrl+P", "");
#endif
//auto printer_item = new wxMenuItem(parent_menu, ConfigMenuPrinter + config_id_base, _L("Printer"), "");
//auto language_item = new wxMenuItem(parent_menu, ConfigMenuLanguage + config_id_base, _L("Switch Language"), "");
parent_menu->Bind(wxEVT_MENU, [this, config_id_base](wxEvent& event) {
switch (event.GetId() - config_id_base) {
//case ConfigMenuLanguage:
//{
@ -1935,10 +1992,50 @@ void MainFrame::init_menubar_as_editor()
}
});
#ifdef __APPLE__
wxString about_title = wxString::Format(_L("&About %s"), SLIC3R_APP_FULL_NAME);
auto about_item = new wxMenuItem(parent_menu, BambuStudioMenuAbout + bambu_studio_id_base, about_title, "");
parent_menu->Bind(wxEVT_MENU, [this, bambu_studio_id_base](wxEvent& event) {
switch (event.GetId() - bambu_studio_id_base) {
case BambuStudioMenuAbout:
Slic3r::GUI::about();
break;
case BambuStudioMenuPreferences:
wxGetApp().CallAfter([this] {
PreferencesDialog dlg(this);
dlg.ShowModal();
#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER
if (dlg.seq_top_layer_only_changed() || dlg.seq_seq_top_gcode_indices_changed())
#else
if (dlg.seq_top_layer_only_changed())
#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER
plater()->refresh_print();
#if ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN
#ifdef _WIN32
/*
if (wxGetApp().app_config()->get("associate_3mf") == "true")
wxGetApp().associate_3mf_files();
if (wxGetApp().app_config()->get("associate_stl") == "true")
wxGetApp().associate_stl_files();
/*if (wxGetApp().app_config()->get("associate_step") == "true")
wxGetApp().associate_step_files();*/
#endif // _WIN32
#endif
});
break;
default:
break;
}
});
parent_menu->Insert(0, about_item);
parent_menu->Insert(1, preference_item);
#endif
// Help menu
auto helpMenu = generate_help_menu();
#ifdef __WINDOWS__
m_topbar->SetFileMenu(fileMenu);
if (editMenu)
m_topbar->AddDropDownSubMenu(editMenu, _L("Edit"));
@ -1950,6 +2047,16 @@ void MainFrame::init_menubar_as_editor()
//m_topbar->AddDropDownMenuItem(language_item);
//m_topbar->AddDropDownMenuItem(config_item);
m_topbar->AddDropDownSubMenu(helpMenu, _L("Help"));
#else
m_menubar->Append(fileMenu, _L("&File"));
if (editMenu)
m_menubar->Append(editMenu, _L("&Edit"));
if (viewMenu)
m_menubar->Append(viewMenu, _L("&View"));
if (helpMenu)
m_menubar->Append(helpMenu, _L("&Help"));
SetMenuBar(m_menubar);
#endif
#ifdef _MSW_DARK_MODE
if (wxGetApp().tabs_as_menu())
@ -1959,12 +2066,12 @@ void MainFrame::init_menubar_as_editor()
#ifdef __APPLE__
// This fixes a bug on Mac OS where the quit command doesn't emit window close events
// wx bug: https://trac.wxwidgets.org/ticket/18328
/* wxMenu* apple_menu = m_menubar->OSXGetAppleMenu();
wxMenu* apple_menu = m_menubar->OSXGetAppleMenu();
if (apple_menu != nullptr) {
apple_menu->Bind(wxEVT_MENU, [this](wxCommandEvent &) {
Close();
}, wxID_EXIT);
}*/
}
#endif // __APPLE__
}

View file

@ -226,7 +226,8 @@ public:
void update_title();
void show_option(bool show);
void update_title_colour_after_set_title();
void show_option(bool show);
void init_tabpanel();
void create_preset_tabs();
//BBS: GUI refactor

View file

@ -293,6 +293,9 @@ MarkdownTip* MarkdownTip::markdownTip(bool create)
bool MarkdownTip::ShowTip(std::string const& tip, std::string const & tooltip, wxPoint pos)
{
#ifdef NDEBUG
return false;
#endif
return markdownTip()->ShowTip(pos, tip, tooltip);
}

View file

@ -230,11 +230,13 @@ void wxMediaCtrl2::DoSetSize(int x, int y, int width, int height, int sizeFlags)
size = wxSize{16, 9};
int maxHeight = (width * size.GetHeight() + size.GetHeight() - 1) / size.GetWidth();
if (maxHeight != GetMaxHeight()) {
BOOST_LOG_TRIVIAL(info) << "wxMediaCtrl2::DoSetSize: width: " << width << ", height: " << height << ", maxHeight: " << maxHeight;
// BOOST_LOG_TRIVIAL(info) << "wxMediaCtrl2::DoSetSize: width: " << width << ", height: " << height << ", maxHeight: " << maxHeight;
SetMaxSize({-1, maxHeight});
Slic3r::GUI::wxGetApp().CallAfter([this] {
GetParent()->Layout();
GetParent()->Refresh();
if (auto p = GetParent()) {
p->Layout();
p->Refresh();
}
});
}
}

View file

@ -148,6 +148,12 @@ MonitorPanel::~MonitorPanel()
m_refresh_timer->SetOwner(this);
m_refresh_timer->Start(REFRESH_INTERVAL);
wxPostEvent(this, wxTimerEvent());
Slic3r::DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
if (!dev) return;
MachineObject *obj_ = dev->get_selected_machine();
if (obj_)
GUI::wxGetApp().sidebar().load_ams_list(obj_->amsList);
}
void MonitorPanel::init_tabpanel()

View file

@ -227,7 +227,7 @@ static void add_msg_content(wxWindow* parent, wxBoxSizer* content_sizer, wxStrin
wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
wxFont monospace = wxGetApp().code_font();
#ifdef _WIN32
#if 1
wxColour text_clr = wxGetApp().get_label_clr_default();
#else
wxColour text_clr = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
@ -318,7 +318,7 @@ WarningDialog::WarningDialog(wxWindow *parent,
finalize();
}
#ifdef _WIN32
#if 1
// MessageDialog
MessageDialog::MessageDialog(wxWindow* parent,

View file

@ -122,7 +122,7 @@ public:
virtual ~WarningDialog() = default;
};
#ifdef _WIN32
#if 1
// Generic static line, used intead of wxStaticLine
class StaticLine: public wxTextCtrl
{

View file

@ -148,7 +148,7 @@ NotificationManager::PopNotification::PopNotification(const NotificationData &n,
m_TextColor = ImVec4(.2f, .2f, .2f, 1.0f);
m_HyperTextColor = ImVec4(0.03, 0.6, 0.18, 1);
m_WindowRadius = 4;
m_WindowRadius = 4.0f * wxGetApp().plater()->get_current_canvas3D()->get_scale();
}

View file

@ -848,7 +848,8 @@ void OG_CustomCtrl::CtrlLine::render(wxDC& dc, wxCoord h_pos, wxCoord v_pos)
// is_url_string = false;
//else if(opt == option_set.front())
// is_url_string = !suppress_hyperlinks && !og_line.label_path.empty();
h_pos = draw_text(dc, wxPoint(h_pos, v_pos), label, field ? (field->blink() ? &blink_color : field->label_color()) : nullptr, ctrl->opt_group->sublabel_width * ctrl->m_em_unit);
static wxColor c("#6B6B6B");
h_pos = draw_text(dc, wxPoint(h_pos, v_pos), label, field ? (field->blink() ? &blink_color : &c) : nullptr, ctrl->opt_group->sublabel_width * ctrl->m_em_unit);
h_pos += 8;
}

View file

@ -196,7 +196,7 @@ void ObjectDataViewModelNode::set_printable_icon(PrintIndicator printable)
void ObjectDataViewModelNode::set_action_icon(bool enable)
{
m_action_enable = enable;
auto undo = enable ? "undo" : "dot";
auto undo = enable ? "lock_normal" : "dot";
m_action_icon_name = m_type & itPlate ? "dot" :
m_type & itObject ? undo :
m_type & (itVolume | itLayer) ? undo : /*m_type & itInstance*/ "set_separate_obj";

View file

@ -462,8 +462,8 @@ bool OptionsGroup::activate(std::function<void()> throw_if_canceled/* = [](){}*/
else {
// BBS: new layout
::StaticLine* stl = new ::StaticLine(m_parent, false, _(title));
stl->SetFont(wxGetApp().normal_font());
stl->SetForegroundColour("#6B6B6B");
stl->SetFont(Label::Head_14);
stl->SetForegroundColour("#262E30");
sizer = new wxBoxSizer(wxVERTICAL);
if (title.IsEmpty()) {
stl->Hide();
@ -1022,6 +1022,8 @@ boost::any ConfigOptionsGroup::get_config_value(const DynamicPrintConfig& config
case coPoints:
if (opt_key == "printable_area")
ret = config.option<ConfigOptionPoints>(opt_key)->values;
else if (opt_key == "bed_exclude_area")
ret = get_thumbnails_string(config.option<ConfigOptionPoints>(opt_key)->values);
else
ret = config.option<ConfigOptionPoints>(opt_key)->get_at(idx);
break;
@ -1130,6 +1132,8 @@ boost::any ConfigOptionsGroup::get_config_value2(const DynamicPrintConfig& confi
case coPoints:
if (opt_key == "printable_area")
ret = config.option<ConfigOptionPoints>(opt_key)->values;
else if (opt_key == "bed_exclude_area")
ret = get_thumbnails_string(config.option<ConfigOptionPoints>(opt_key)->values);
else
ret = config.option<ConfigOptionPoints>(opt_key)->get_at(idx);
break;

View file

@ -21,11 +21,10 @@ ParamsDialog::ParamsDialog(wxWindow * parent)
m_panel = new ParamsPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBK_LEFT | wxTAB_TRAVERSAL);
auto* topsizer = new wxBoxSizer(wxVERTICAL);
topsizer->Add(m_panel, 1, wxALL | wxEXPAND, 5, NULL);
topsizer->Add(-1, 5);
topsizer->Add(m_panel, 1, wxALL | wxEXPAND, 0, NULL);
SetSizerAndFit(topsizer);
SetSize({100 * em_unit(), 60 * em_unit()});
SetSize({70 * em_unit(), 60 * em_unit()});
Layout();
Center();
@ -70,7 +69,7 @@ void ParamsDialog::Popup()
void ParamsDialog::on_dpi_changed(const wxRect &suggested_rect)
{
Fit();
SetSize({100 * em_unit(), 60 * em_unit()});
SetSize({70 * em_unit(), 60 * em_unit()});
m_panel->msw_rescale();
Refresh();
}

View file

@ -402,6 +402,7 @@ void ParamsPanel::create_layout()
//m_top_sizer->Add( m_right_sizer, 1, wxEXPAND, 5 );
// BBS: new layout
m_left_sizer->AddSpacer(6 * em_unit(this) / 10);
#if __WXOSX__
m_left_sizer->Add(m_tmp_panel, 1, wxEXPAND | wxALL, 0);
m_tmp_panel->GetSizer()->Add( m_page_view, 1, wxEXPAND );

View file

@ -62,7 +62,7 @@ namespace GUI {
class Bed3D;
std::array<float, 4> PartPlate::SELECT_COLOR = { 0.4196f, 0.4235f, 0.4235f, 1.0f };
std::array<float, 4> PartPlate::SELECT_COLOR = { 0.2666f, 0.2784f, 0.2784f, 1.0f }; //{ 0.4196f, 0.4235f, 0.4235f, 1.0f };
std::array<float, 4> PartPlate::UNSELECT_COLOR = { 0.82f, 0.82f, 0.82f, 1.0f };
std::array<float, 4> PartPlate::DEFAULT_COLOR = { 0.5f, 0.5f, 0.5f, 1.0f };
std::array<float, 4> PartPlate::LINE_TOP_COLOR = { 0.89f, 0.89f, 0.89f, 1.0f };
@ -199,11 +199,11 @@ void PartPlate::calc_gridlines(const ExPolygon& poly, const BoundingBox& pp_bbox
line.append(Point(x, pp_bbox.min(1)));
line.append(Point(x, pp_bbox.max(1)));
count ++;
if ( (count % 5) == 0 )
axes_lines_bolder.push_back(line);
else
axes_lines.push_back(line);
count ++;
}
count = 0;
for (coord_t y = pp_bbox.min(1); y <= pp_bbox.max(1); y += scale_(10.0)) {
@ -212,11 +212,11 @@ void PartPlate::calc_gridlines(const ExPolygon& poly, const BoundingBox& pp_bbox
line.append(Point(pp_bbox.max(0), y));
axes_lines.push_back(line);
count ++;
if ( (count % 5) == 0 )
axes_lines_bolder.push_back(line);
else
axes_lines.push_back(line);
count ++;
}
// clip with a slightly grown expolygon because our lines lay on the contours and may get erroneously clipped
@ -385,7 +385,8 @@ void PartPlate::render_logo(bool bottom) const
// starts generating the main texture, compression will run asynchronously
GLint max_tex_size = OpenGLManager::get_gl_info().get_max_tex_size();
if (!m_partplate_list->m_logo_texture.load_from_svg_file(m_partplate_list->m_logo_texture_filename, true, true, true, max_tex_size/8)) {
GLint logo_tex_size = (max_tex_size < 2048)?max_tex_size: 2048;
if (!m_partplate_list->m_logo_texture.load_from_svg_file(m_partplate_list->m_logo_texture_filename, true, true, true, logo_tex_size)) {
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(": load logo texture from %1% failed!")%m_partplate_list->m_logo_texture_filename;
return;
}
@ -1838,8 +1839,8 @@ bool PartPlate::set_shape(const Pointfs& shape, const Pointfs& exclude_areas, Ve
ExPolygon logo_poly;
generate_logo_polygon(logo_poly);
if (!m_logo_triangles.set_from_triangles(triangulate_expolygon_2f(logo_poly, NORMALS_UP), GROUND_Z+0.28f))
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ":Unable to create plate triangles\n";
if (!m_logo_triangles.set_from_triangles(triangulate_expolygon_2f(logo_poly, NORMALS_UP), GROUND_Z+0.02f))
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ":Unable to create logo triangles\n";
ExPolygon poly;
/*for (const Vec2d& p : m_shape) {
@ -1882,9 +1883,9 @@ const BoundingBox PartPlate::get_bounding_box_crd()
return plate_shape.bounding_box();
}
bool PartPlate::contains(const Point& point) const
bool PartPlate::contains(const Vec3d& point) const
{
return m_polygon.contains(point);
return m_bounding_box.contains(point);
}
bool PartPlate::contains(const GLVolume& v) const
@ -1916,11 +1917,6 @@ bool PartPlate::intersects(const BoundingBoxf3& bb) const
return print_volume.intersects(bb);
}
Point PartPlate::point_projection(const Point& point) const
{
return m_polygon.point_projection(point);
}
void PartPlate::render(bool bottom, bool only_body, bool force_background_color, HeightLimitMode mode, int hover_id)
{
glsafe(::glEnable(GL_DEPTH_TEST));

Some files were not shown because too many files have changed in this diff Show more