mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-10-23 16:51:21 -06:00
Merge remote-tracking branch 'origin/master' into lh_avoid_crossing_perimeters
This commit is contained in:
commit
f25e5c0ec6
23 changed files with 13175 additions and 97 deletions
|
|
@ -663,62 +663,79 @@ private:
|
|||
remlist.insert(remlist.end(), remaining.from, remaining.to);
|
||||
}
|
||||
|
||||
double global_score = std::numeric_limits<double>::max();
|
||||
|
||||
auto initial_tr = item.translation();
|
||||
auto initial_rot = item.rotation();
|
||||
Vertex final_tr = {0, 0};
|
||||
Radians final_rot = initial_rot;
|
||||
Shapes nfps;
|
||||
|
||||
auto& bin = bin_;
|
||||
double norm = norm_;
|
||||
auto pbb = sl::boundingBox(merged_pile_);
|
||||
auto binbb = sl::boundingBox(bin);
|
||||
|
||||
// This is the kernel part of the object function that is
|
||||
// customizable by the library client
|
||||
std::function<double(const Item&)> _objfunc;
|
||||
if(config_.object_function) _objfunc = config_.object_function;
|
||||
else {
|
||||
|
||||
// Inside check has to be strict if no alignment was enabled
|
||||
std::function<double(const Box&)> ins_check;
|
||||
if(config_.alignment == Config::Alignment::DONT_ALIGN)
|
||||
ins_check = [&binbb, norm](const Box& fullbb) {
|
||||
double ret = 0;
|
||||
if(!sl::isInside(fullbb, binbb))
|
||||
ret += norm;
|
||||
return ret;
|
||||
};
|
||||
else
|
||||
ins_check = [&bin](const Box& fullbb) {
|
||||
double miss = overfit(fullbb, bin);
|
||||
miss = miss > 0? miss : 0;
|
||||
return std::pow(miss, 2);
|
||||
};
|
||||
|
||||
_objfunc = [norm, binbb, pbb, ins_check](const Item& item)
|
||||
{
|
||||
auto ibb = item.boundingBox();
|
||||
auto fullbb = sl::boundingBox(pbb, ibb);
|
||||
|
||||
double score = pl::distance(ibb.center(),
|
||||
binbb.center());
|
||||
score /= norm;
|
||||
|
||||
score += ins_check(fullbb);
|
||||
|
||||
return score;
|
||||
};
|
||||
}
|
||||
|
||||
if(items_.empty()) {
|
||||
setInitialPosition(item);
|
||||
auto best_tr = item.translation();
|
||||
auto best_rot = item.rotation();
|
||||
best_overfit = overfit(item.transformedShape(), bin_);
|
||||
can_pack = best_overfit <= 0;
|
||||
} else {
|
||||
|
||||
double global_score = std::numeric_limits<double>::max();
|
||||
|
||||
auto initial_tr = item.translation();
|
||||
auto initial_rot = item.rotation();
|
||||
Vertex final_tr = {0, 0};
|
||||
Radians final_rot = initial_rot;
|
||||
Shapes nfps;
|
||||
|
||||
auto& bin = bin_;
|
||||
double norm = norm_;
|
||||
auto pbb = sl::boundingBox(merged_pile_);
|
||||
auto binbb = sl::boundingBox(bin);
|
||||
|
||||
// This is the kernel part of the object function that is
|
||||
// customizable by the library client
|
||||
std::function<double(const Item&)> _objfunc;
|
||||
if(config_.object_function) _objfunc = config_.object_function;
|
||||
else {
|
||||
|
||||
// Inside check has to be strict if no alignment was enabled
|
||||
std::function<double(const Box&)> ins_check;
|
||||
if(config_.alignment == Config::Alignment::DONT_ALIGN)
|
||||
ins_check = [&binbb, norm](const Box& fullbb) {
|
||||
double ret = 0;
|
||||
if(!sl::isInside(fullbb, binbb))
|
||||
ret += norm;
|
||||
return ret;
|
||||
};
|
||||
else
|
||||
ins_check = [&bin](const Box& fullbb) {
|
||||
double miss = overfit(fullbb, bin);
|
||||
miss = miss > 0? miss : 0;
|
||||
return std::pow(miss, 2);
|
||||
};
|
||||
|
||||
_objfunc = [norm, binbb, pbb, ins_check](const Item& item)
|
||||
{
|
||||
auto ibb = item.boundingBox();
|
||||
auto fullbb = sl::boundingBox(pbb, ibb);
|
||||
|
||||
double score = pl::distance(ibb.center(),
|
||||
binbb.center());
|
||||
score /= norm;
|
||||
|
||||
score += ins_check(fullbb);
|
||||
|
||||
return score;
|
||||
};
|
||||
for(auto rot : config_.rotations) {
|
||||
item.translation(initial_tr);
|
||||
item.rotation(initial_rot + rot);
|
||||
setInitialPosition(item);
|
||||
double of = 0.;
|
||||
if ((of = overfit(item.transformedShape(), bin_)) < best_overfit) {
|
||||
best_overfit = of;
|
||||
best_tr = item.translation();
|
||||
best_rot = item.rotation();
|
||||
}
|
||||
}
|
||||
|
||||
can_pack = best_overfit <= 0;
|
||||
item.rotation(best_rot);
|
||||
item.translation(best_tr);
|
||||
} else {
|
||||
|
||||
Pile merged_pile = merged_pile_;
|
||||
|
||||
for(auto rot : config_.rotations) {
|
||||
|
|
@ -948,10 +965,9 @@ private:
|
|||
if(items_.empty() ||
|
||||
config_.alignment == Config::Alignment::DONT_ALIGN) return;
|
||||
|
||||
nfp::Shapes<RawShape> m;
|
||||
m.reserve(items_.size());
|
||||
for(Item& item : items_) m.emplace_back(item.transformedShape());
|
||||
auto&& bb = sl::boundingBox(m);
|
||||
Box bb = items_.front().get().boundingBox();
|
||||
for(Item& item : items_)
|
||||
bb = sl::boundingBox(item.boundingBox(), bb);
|
||||
|
||||
Vertex ci, cb;
|
||||
|
||||
|
|
@ -988,7 +1004,7 @@ private:
|
|||
for(Item& item : items_) item.translate(d);
|
||||
}
|
||||
|
||||
void setInitialPosition(Item& item) {
|
||||
void setInitialPosition(Item& item) {
|
||||
Box bb = item.boundingBox();
|
||||
|
||||
Vertex ci, cb;
|
||||
|
|
|
|||
|
|
@ -273,6 +273,7 @@ namespace Slic3r {
|
|||
// Otherwise, leave control to the user completely.
|
||||
std::string toolchange_gcode_str;
|
||||
const std::string& toolchange_gcode = gcodegen.config().toolchange_gcode.value;
|
||||
// m_max_layer_z = std::max(m_max_layer_z, tcr.print_z);
|
||||
if (! toolchange_gcode.empty()) {
|
||||
DynamicConfig config;
|
||||
int previous_extruder_id = gcodegen.writer().extruder() ? (int)gcodegen.writer().extruder()->id() : -1;
|
||||
|
|
@ -280,6 +281,7 @@ namespace Slic3r {
|
|||
config.set_key_value("next_extruder", new ConfigOptionInt((int)new_extruder_id));
|
||||
config.set_key_value("layer_num", new ConfigOptionInt(gcodegen.m_layer_index));
|
||||
config.set_key_value("layer_z", new ConfigOptionFloat(tcr.print_z));
|
||||
// config.set_key_value("max_layer_z", new ConfigOptionFloat(m_max_layer_z));
|
||||
toolchange_gcode_str = gcodegen.placeholder_parser_process("toolchange_gcode", toolchange_gcode, new_extruder_id, &config);
|
||||
check_add_eol(toolchange_gcode_str);
|
||||
}
|
||||
|
|
@ -924,11 +926,12 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu
|
|||
DoExport::init_gcode_processor(print.config(), m_processor, m_silent_time_estimator_enabled);
|
||||
|
||||
// resets analyzer's tracking data
|
||||
m_last_height = 0.0f;
|
||||
m_last_layer_z = 0.0f;
|
||||
m_last_height = 0.f;
|
||||
m_last_layer_z = 0.f;
|
||||
m_max_layer_z = 0.f;
|
||||
#if ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
m_last_mm3_per_mm = 0.0;
|
||||
m_last_width = 0.0f;
|
||||
m_last_mm3_per_mm = 0.;
|
||||
m_last_width = 0.f;
|
||||
#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
|
||||
// How many times will be change_layer() called?
|
||||
|
|
@ -1282,6 +1285,7 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu
|
|||
DynamicConfig config;
|
||||
config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index));
|
||||
config.set_key_value("layer_z", new ConfigOptionFloat(m_writer.get_position()(2) - m_config.z_offset.value));
|
||||
config.set_key_value("max_layer_z", new ConfigOptionFloat(m_max_layer_z));
|
||||
if (print.config().single_extruder_multi_material) {
|
||||
// Process the end_filament_gcode for the active filament only.
|
||||
int extruder_id = m_writer.extruder()->id();
|
||||
|
|
@ -1783,13 +1787,15 @@ void GCode::process_layer(
|
|||
gcode += buf;
|
||||
// update caches
|
||||
m_last_layer_z = static_cast<float>(print_z);
|
||||
m_max_layer_z = std::max(m_max_layer_z, m_last_layer_z);
|
||||
m_last_height = height;
|
||||
|
||||
// Set new layer - this will change Z and force a retraction if retract_layer_change is enabled.
|
||||
if (! print.config().before_layer_gcode.value.empty()) {
|
||||
DynamicConfig config;
|
||||
config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index + 1));
|
||||
config.set_key_value("layer_z", new ConfigOptionFloat(print_z));
|
||||
config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index + 1));
|
||||
config.set_key_value("layer_z", new ConfigOptionFloat(print_z));
|
||||
config.set_key_value("max_layer_z", new ConfigOptionFloat(m_max_layer_z));
|
||||
gcode += this->placeholder_parser_process("before_layer_gcode",
|
||||
print.config().before_layer_gcode.value, m_writer.extruder()->id(), &config)
|
||||
+ "\n";
|
||||
|
|
@ -1803,6 +1809,7 @@ void GCode::process_layer(
|
|||
gcode += this->placeholder_parser_process("layer_gcode",
|
||||
print.config().layer_gcode.value, m_writer.extruder()->id(), &config)
|
||||
+ "\n";
|
||||
config.set_key_value("max_layer_z", new ConfigOptionFloat(m_max_layer_z));
|
||||
}
|
||||
|
||||
if (! first_layer && ! m_second_layer_things_done) {
|
||||
|
|
@ -2811,6 +2818,7 @@ std::string GCode::set_extruder(unsigned int extruder_id, double print_z)
|
|||
config.set_key_value("next_extruder", new ConfigOptionInt((int)extruder_id));
|
||||
config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index));
|
||||
config.set_key_value("layer_z", new ConfigOptionFloat(print_z));
|
||||
config.set_key_value("max_layer_z", new ConfigOptionFloat(m_max_layer_z));
|
||||
toolchange_gcode_parsed = placeholder_parser_process("toolchange_gcode", toolchange_gcode, extruder_id, &config);
|
||||
gcode += toolchange_gcode_parsed;
|
||||
check_add_eol(gcode);
|
||||
|
|
|
|||
|
|
@ -323,6 +323,7 @@ private:
|
|||
// Support for G-Code Processor
|
||||
float m_last_height{ 0.0f };
|
||||
float m_last_layer_z{ 0.0f };
|
||||
float m_max_layer_z{ 0.0f };
|
||||
#if ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
double m_last_mm3_per_mm;
|
||||
float m_last_width{ 0.0f };
|
||||
|
|
|
|||
|
|
@ -266,8 +266,9 @@ inline bool liang_barsky_line_clipping(
|
|||
// Clipped successfully.
|
||||
x1 = x0 + interval.second * v;
|
||||
x0 += interval.first * v;
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Based on Liang-Barsky function by Daniel White @ http://www.skytopia.com/project/articles/compsci/clipping.html
|
||||
|
|
|
|||
|
|
@ -159,8 +159,8 @@ void PrintConfigDef::init_common_params()
|
|||
def->enum_keys_map = &ConfigOptionEnum<AuthorizationType>::get_enum_values();
|
||||
def->enum_values.push_back("key");
|
||||
def->enum_values.push_back("user");
|
||||
def->enum_labels.push_back("KeyPassword");
|
||||
def->enum_labels.push_back("UserPassword");
|
||||
def->enum_labels.push_back("API key");
|
||||
def->enum_labels.push_back("HTTP digest");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionEnum<AuthorizationType>(atKeyPassword));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,4 +83,12 @@
|
|||
#define ENABLE_CUSTOMIZABLE_FILES_ASSOCIATION_ON_WIN (1 && ENABLE_2_3_0_BETA1)
|
||||
|
||||
|
||||
//===================
|
||||
// 2.3.0.beta2 techs
|
||||
//===================
|
||||
#define ENABLE_2_3_0_BETA2 1
|
||||
|
||||
#define ENABLE_ARROW_KEYS_WITH_SLIDERS (1 && ENABLE_2_3_0_BETA2)
|
||||
|
||||
|
||||
#endif // _prusaslicer_technologies_h_
|
||||
|
|
|
|||
|
|
@ -552,6 +552,7 @@ std::string encode_path(const char *src)
|
|||
}
|
||||
|
||||
// Encode an 8-bit string from a local code page to UTF-8.
|
||||
// Multibyte to utf8
|
||||
std::string decode_path(const char *src)
|
||||
{
|
||||
#ifdef WIN32
|
||||
|
|
|
|||
|
|
@ -149,30 +149,37 @@ void BackgroundSlicingProcess::process_fff()
|
|||
// Perform the final post-processing of the export path by applying the print statistics over the file name.
|
||||
std::string export_path = m_fff_print->print_statistics().finalize_output_path(m_export_path);
|
||||
std::string error_message;
|
||||
int copy_ret_val = copy_file(m_temp_output_path, export_path, error_message, m_export_path_on_removable_media);
|
||||
int copy_ret_val = CopyFileResult::SUCCESS;
|
||||
try
|
||||
{
|
||||
copy_ret_val = copy_file(m_temp_output_path, export_path, error_message, m_export_path_on_removable_media);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
throw Slic3r::ExportError(_utf8(L("Unknown error occured during exporting G-code.")));
|
||||
}
|
||||
switch (copy_ret_val) {
|
||||
case SUCCESS: break; // no error
|
||||
case FAIL_COPY_FILE:
|
||||
case CopyFileResult::SUCCESS: break; // no error
|
||||
case CopyFileResult::FAIL_COPY_FILE:
|
||||
throw Slic3r::ExportError((boost::format(_utf8(L("Copying of the temporary G-code to the output G-code failed. Maybe the SD card is write locked?\nError message: %1%"))) % error_message).str());
|
||||
break;
|
||||
case FAIL_FILES_DIFFERENT:
|
||||
case CopyFileResult::FAIL_FILES_DIFFERENT:
|
||||
throw Slic3r::ExportError((boost::format(_utf8(L("Copying of the temporary G-code to the output G-code failed. There might be problem with target device, please try exporting again or using different device. The corrupted output G-code is at %1%.tmp."))) % export_path).str());
|
||||
break;
|
||||
case FAIL_RENAMING:
|
||||
case CopyFileResult::FAIL_RENAMING:
|
||||
throw Slic3r::ExportError((boost::format(_utf8(L("Renaming of the G-code after copying to the selected destination folder has failed. Current path is %1%.tmp. Please try exporting again."))) % export_path).str());
|
||||
break;
|
||||
case FAIL_CHECK_ORIGIN_NOT_OPENED:
|
||||
case CopyFileResult::FAIL_CHECK_ORIGIN_NOT_OPENED:
|
||||
throw Slic3r::ExportError((boost::format(_utf8(L("Copying of the temporary G-code has finished but the original code at %1% couldn't be opened during copy check. The output G-code is at %2%.tmp."))) % m_temp_output_path % export_path).str());
|
||||
break;
|
||||
case FAIL_CHECK_TARGET_NOT_OPENED:
|
||||
case CopyFileResult::FAIL_CHECK_TARGET_NOT_OPENED:
|
||||
throw Slic3r::ExportError((boost::format(_utf8(L("Copying of the temporary G-code has finished but the exported code couldn't be opened during copy check. The output G-code is at %1%.tmp."))) % export_path).str());
|
||||
break;
|
||||
default:
|
||||
throw Slic3r::RuntimeError(_utf8(L("Unknown error occured during exporting G-code.")));
|
||||
throw Slic3r::ExportError(_utf8(L("Unknown error occured during exporting G-code.")));
|
||||
BOOST_LOG_TRIVIAL(error) << "Unexpected fail code(" << (int)copy_ret_val << ") durring copy_file() to " << export_path << ".";
|
||||
break;
|
||||
}
|
||||
|
||||
m_print->set_status(95, _utf8(L("Running post-processing scripts")));
|
||||
run_post_process_scripts(export_path, m_fff_print->config());
|
||||
m_print->set_status(100, (boost::format(_utf8(L("G-code file exported to %1%"))) % export_path).str());
|
||||
|
|
|
|||
|
|
@ -1519,6 +1519,10 @@ void Control::move_current_thumb(const bool condition)
|
|||
if (accelerator > 0)
|
||||
delta *= accelerator;
|
||||
|
||||
#if ENABLE_ARROW_KEYS_WITH_SLIDERS
|
||||
if (m_selection == ssUndef) m_selection = ssHigher;
|
||||
#endif // ENABLE_ARROW_KEYS_WITH_SLIDERS
|
||||
|
||||
if (m_selection == ssLower) {
|
||||
m_lower_value -= delta;
|
||||
correct_lower_value();
|
||||
|
|
@ -1579,13 +1583,26 @@ void Control::OnKeyDown(wxKeyEvent &event)
|
|||
if (key == WXK_LEFT || key == WXK_RIGHT)
|
||||
move_current_thumb(key == WXK_LEFT);
|
||||
else if (key == WXK_UP || key == WXK_DOWN) {
|
||||
#if ENABLE_ARROW_KEYS_WITH_SLIDERS
|
||||
if (key == WXK_DOWN)
|
||||
m_selection = ssHigher;
|
||||
else if (key == WXK_UP && is_lower_thumb_editable())
|
||||
m_selection = ssLower;
|
||||
#else
|
||||
if (key == WXK_UP)
|
||||
m_selection = ssHigher;
|
||||
else if (key == WXK_DOWN && is_lower_thumb_editable())
|
||||
m_selection = ssLower;
|
||||
#endif // ENABLE_ARROW_KEYS_WITH_SLIDERS
|
||||
Refresh();
|
||||
}
|
||||
}
|
||||
#if ENABLE_ARROW_KEYS_WITH_SLIDERS
|
||||
else {
|
||||
if (key == WXK_LEFT || key == WXK_RIGHT)
|
||||
move_current_thumb(key == WXK_LEFT);
|
||||
}
|
||||
#endif // ENABLE_ARROW_KEYS_WITH_SLIDERS
|
||||
}
|
||||
else {
|
||||
if (m_is_focused) {
|
||||
|
|
@ -1599,6 +1616,12 @@ void Control::OnKeyDown(wxKeyEvent &event)
|
|||
else if (key == WXK_UP || key == WXK_DOWN)
|
||||
move_current_thumb(key == WXK_UP);
|
||||
}
|
||||
#if ENABLE_ARROW_KEYS_WITH_SLIDERS
|
||||
else {
|
||||
if (key == WXK_UP || key == WXK_DOWN)
|
||||
move_current_thumb(key == WXK_UP);
|
||||
}
|
||||
#endif // ENABLE_ARROW_KEYS_WITH_SLIDERS
|
||||
}
|
||||
|
||||
event.Skip(); // !Needed to have EVT_CHAR generated as well
|
||||
|
|
|
|||
|
|
@ -128,8 +128,8 @@ void Field::PostInitialize()
|
|||
}
|
||||
|
||||
// Values of width to alignments of fields
|
||||
int Field::def_width() { return wxOSX ? 8 : 7; }
|
||||
int Field::def_width_wider() { return 14; }
|
||||
int Field::def_width() { return 8; }
|
||||
int Field::def_width_wider() { return 16; }
|
||||
int Field::def_width_thinner() { return 4; }
|
||||
|
||||
void Field::on_kill_focus()
|
||||
|
|
@ -1085,7 +1085,7 @@ void Choice::set_values(const wxArrayString &values)
|
|||
|
||||
// # it looks that Clear() also clears the text field in recent wxWidgets versions,
|
||||
// # but we want to preserve it
|
||||
auto ww = dynamic_cast<wxBitmapComboBox*>(window);
|
||||
auto ww = dynamic_cast<choice_ctrl*>(window);
|
||||
auto value = ww->GetValue();
|
||||
ww->Clear();
|
||||
ww->Append("");
|
||||
|
|
|
|||
|
|
@ -1078,7 +1078,11 @@ wxDEFINE_EVENT(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED, SimpleEvent);
|
|||
wxDEFINE_EVENT(EVT_GLCANVAS_UPDATE_BED_SHAPE, SimpleEvent);
|
||||
wxDEFINE_EVENT(EVT_GLCANVAS_TAB, SimpleEvent);
|
||||
wxDEFINE_EVENT(EVT_GLCANVAS_RESETGIZMOS, SimpleEvent);
|
||||
#if ENABLE_ARROW_KEYS_WITH_SLIDERS
|
||||
wxDEFINE_EVENT(EVT_GLCANVAS_MOVE_SLIDERS, wxKeyEvent);
|
||||
#else
|
||||
wxDEFINE_EVENT(EVT_GLCANVAS_MOVE_LAYERS_SLIDER, wxKeyEvent);
|
||||
#endif // ENABLE_ARROW_KEYS_WITH_SLIDERS
|
||||
wxDEFINE_EVENT(EVT_GLCANVAS_EDIT_COLOR_CHANGE, wxKeyEvent);
|
||||
wxDEFINE_EVENT(EVT_GLCANVAS_JUMP_TO, wxKeyEvent);
|
||||
wxDEFINE_EVENT(EVT_GLCANVAS_UNDO, SimpleEvent);
|
||||
|
|
@ -1098,12 +1102,18 @@ static GLCanvas3D::ArrangeSettings load_arrange_settings()
|
|||
std::string dist_str =
|
||||
wxGetApp().app_config->get("arrange", "min_object_distance");
|
||||
|
||||
std::string dist_seq_print_str =
|
||||
wxGetApp().app_config->get("arrange", "min_object_distance_seq_print");
|
||||
|
||||
std::string en_rot_str =
|
||||
wxGetApp().app_config->get("arrange", "enable_rotation");
|
||||
|
||||
if (!dist_str.empty())
|
||||
settings.distance = std::stof(dist_str);
|
||||
|
||||
if (!dist_seq_print_str.empty())
|
||||
settings.distance_seq_print = std::stof(dist_seq_print_str);
|
||||
|
||||
if (!en_rot_str.empty())
|
||||
settings.enable_rotation = (en_rot_str == "1" || en_rot_str == "yes");
|
||||
|
||||
|
|
@ -2409,10 +2419,15 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
|
|||
post_event(SimpleEvent(EVT_GLCANVAS_ARRANGE));
|
||||
};
|
||||
|
||||
auto action_question_mark = [this]() {
|
||||
post_event(SimpleEvent(EVT_GLCANVAS_QUESTION_MARK));
|
||||
};
|
||||
|
||||
//#ifdef __APPLE__
|
||||
// ctrlMask |= wxMOD_RAW_CONTROL;
|
||||
//#endif /* __APPLE__ */
|
||||
if ((evt.GetModifiers() & ctrlMask) != 0) {
|
||||
// CTRL is pressed
|
||||
switch (keyCode) {
|
||||
#ifdef __APPLE__
|
||||
case 'a':
|
||||
|
|
@ -2500,7 +2515,8 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
|
|||
default: evt.Skip();
|
||||
}
|
||||
}
|
||||
else if ((evt.GetModifiers() & shiftMask) != 0) {
|
||||
else if ((evt.GetModifiers() & shiftMask) != 0) {
|
||||
// SHIFT is pressed
|
||||
switch (keyCode) {
|
||||
case '+': { action_plus(evt); break; }
|
||||
case 'A':
|
||||
|
|
@ -2511,6 +2527,7 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
|
|||
post_event(wxKeyEvent(EVT_GLCANVAS_JUMP_TO, evt));
|
||||
break;
|
||||
}
|
||||
case '?': { action_question_mark(); break; }
|
||||
default:
|
||||
evt.Skip();
|
||||
}
|
||||
|
|
@ -2539,7 +2556,7 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
|
|||
else
|
||||
post_event(Event<int>(EVT_GLCANVAS_INCREASE_INSTANCES, -1));
|
||||
break; }
|
||||
case '?': { post_event(SimpleEvent(EVT_GLCANVAS_QUESTION_MARK)); break; }
|
||||
case '?': { action_question_mark(); break; }
|
||||
case 'A':
|
||||
case 'a': { action_a(); break; }
|
||||
case 'B':
|
||||
|
|
@ -2818,7 +2835,11 @@ void GLCanvas3D::on_key(wxKeyEvent& evt)
|
|||
keyCode == WXK_UP ||
|
||||
keyCode == WXK_DOWN) {
|
||||
if (dynamic_cast<Preview*>(m_canvas->GetParent()) != nullptr)
|
||||
#if ENABLE_ARROW_KEYS_WITH_SLIDERS
|
||||
post_event(wxKeyEvent(EVT_GLCANVAS_MOVE_SLIDERS, evt));
|
||||
#else
|
||||
post_event(wxKeyEvent(EVT_GLCANVAS_MOVE_LAYERS_SLIDER, evt));
|
||||
#endif // ENABLE_ARROW_KEYS_WITH_SLIDERS
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3892,9 +3913,18 @@ bool GLCanvas3D::_render_arrange_menu(float pos_x)
|
|||
auto &appcfg = wxGetApp().app_config;
|
||||
|
||||
bool settings_changed = false;
|
||||
bool is_seq_print = m_config->opt_bool("complete_objects");
|
||||
|
||||
imgui->text(_L("Use CTRL+left mouse key to enter text edit mode:"));
|
||||
|
||||
float &dist_val = is_seq_print ? settings.distance_seq_print : settings.distance;
|
||||
float dist_min = is_seq_print ? float(min_object_distance(*m_config)) : 0.f;
|
||||
dist_val = std::max(dist_min, dist_val);
|
||||
|
||||
if (imgui->slider_float(_L("Clearance size"), &dist_val, dist_min, 100.0f, "%5.2f")) {
|
||||
is_seq_print ? m_arrange_settings.distance_seq_print = dist_val :
|
||||
m_arrange_settings.distance = dist_val;
|
||||
|
||||
if (imgui->slider_float(_L("Gap size"), &settings.distance, 0.f, 100.f)) {
|
||||
m_arrange_settings.distance = settings.distance;
|
||||
settings_changed = true;
|
||||
}
|
||||
|
||||
|
|
@ -3912,6 +3942,7 @@ bool GLCanvas3D::_render_arrange_menu(float pos_x)
|
|||
|
||||
if (settings_changed) {
|
||||
appcfg->set("arrange", "min_object_distance", std::to_string(m_arrange_settings.distance));
|
||||
appcfg->set("arrange", "min_object_distance_seq_print", std::to_string(m_arrange_settings.distance_seq_print));
|
||||
appcfg->set("arrange", "enable_rotation", m_arrange_settings.enable_rotation? "1" : "0");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -103,7 +103,11 @@ wxDECLARE_EVENT(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED, SimpleEvent);
|
|||
wxDECLARE_EVENT(EVT_GLCANVAS_UPDATE_BED_SHAPE, SimpleEvent);
|
||||
wxDECLARE_EVENT(EVT_GLCANVAS_TAB, SimpleEvent);
|
||||
wxDECLARE_EVENT(EVT_GLCANVAS_RESETGIZMOS, SimpleEvent);
|
||||
#if ENABLE_ARROW_KEYS_WITH_SLIDERS
|
||||
wxDECLARE_EVENT(EVT_GLCANVAS_MOVE_SLIDERS, wxKeyEvent);
|
||||
#else
|
||||
wxDECLARE_EVENT(EVT_GLCANVAS_MOVE_LAYERS_SLIDER, wxKeyEvent);
|
||||
#endif // ENABLE_ARROW_KEYS_WITH_SLIDERS
|
||||
wxDECLARE_EVENT(EVT_GLCANVAS_EDIT_COLOR_CHANGE, wxKeyEvent);
|
||||
wxDECLARE_EVENT(EVT_GLCANVAS_JUMP_TO, wxKeyEvent);
|
||||
wxDECLARE_EVENT(EVT_GLCANVAS_UNDO, SimpleEvent);
|
||||
|
|
@ -383,9 +387,10 @@ public:
|
|||
|
||||
struct ArrangeSettings
|
||||
{
|
||||
float distance = 6.;
|
||||
float accuracy = 0.65f;
|
||||
bool enable_rotation = false;
|
||||
float distance = 6.;
|
||||
float distance_seq_print = 6.; // Used when sequential print is ON
|
||||
float accuracy = 0.65f; // Unused currently
|
||||
bool enable_rotation = false;
|
||||
};
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -1278,6 +1278,11 @@ bool GUI_App::select_language()
|
|||
wxArrayString translations = wxTranslations::Get()->GetAvailableTranslations(SLIC3R_APP_KEY);
|
||||
std::vector<const wxLanguageInfo*> language_infos;
|
||||
language_infos.emplace_back(wxLocale::GetLanguageInfo(wxLANGUAGE_ENGLISH));
|
||||
#ifdef __linux__
|
||||
// wxWidgets consider the default English locale to be en_GB, which is often missing on Linux.
|
||||
// Thus we offer en_US on Linux as well.
|
||||
language_infos.emplace_back(wxLocale::GetLanguageInfo(wxLANGUAGE_ENGLISH_US));
|
||||
#endif // __linux__
|
||||
for (size_t i = 0; i < translations.GetCount(); ++ i) {
|
||||
const wxLanguageInfo *langinfo = wxLocale::FindLanguageInfo(translations[i]);
|
||||
if (langinfo != nullptr)
|
||||
|
|
@ -1306,6 +1311,13 @@ bool GUI_App::select_language()
|
|||
if (language_infos[i]->CanonicalName.BeforeFirst('_') == "en")
|
||||
// This will be the default selection if the active language does not match any dictionary.
|
||||
init_selection_default = i;
|
||||
#ifdef __linux__
|
||||
// wxWidgets consider the default English locale to be en_GB, which is often missing on Linux.
|
||||
// Thus we make the distintion between "en_US" and "en_GB" clear.
|
||||
if (language_infos[i]->CanonicalName == "en_GB" && language_infos[i]->Description == "English")
|
||||
names.Add("English (U.K.)");
|
||||
else
|
||||
#endif // __linux__
|
||||
names.Add(language_infos[i]->Description);
|
||||
}
|
||||
if (init_selection == -1)
|
||||
|
|
|
|||
|
|
@ -460,6 +460,13 @@ void Preview::unbind_event_handlers()
|
|||
m_moves_slider->Unbind(wxEVT_SCROLL_CHANGED, &Preview::on_moves_slider_scroll_changed, this);
|
||||
}
|
||||
|
||||
#if ENABLE_ARROW_KEYS_WITH_SLIDERS
|
||||
void Preview::move_moves_slider(wxKeyEvent& evt)
|
||||
{
|
||||
if (m_moves_slider != nullptr) m_moves_slider->OnKeyDown(evt);
|
||||
}
|
||||
#endif // ENABLE_ARROW_KEYS_WITH_SLIDERS
|
||||
|
||||
void Preview::hide_layers_slider()
|
||||
{
|
||||
m_layers_slider_sizer->Hide((size_t)0);
|
||||
|
|
@ -765,12 +772,26 @@ void Preview::update_layers_slider_from_canvas(wxKeyEvent& event)
|
|||
|
||||
const auto key = event.GetKeyCode();
|
||||
|
||||
#if ENABLE_ARROW_KEYS_WITH_SLIDERS
|
||||
if (key == 'S' || key == 'W') {
|
||||
const int new_pos = key == 'W' ? m_layers_slider->GetHigherValue() + 1 : m_layers_slider->GetHigherValue() - 1;
|
||||
#else
|
||||
if (key == 'U' || key == 'D') {
|
||||
const int new_pos = key == 'U' ? m_layers_slider->GetHigherValue() + 1 : m_layers_slider->GetHigherValue() - 1;
|
||||
#endif // ENABLE_ARROW_KEYS_WITH_SLIDERS
|
||||
m_layers_slider->SetHigherValue(new_pos);
|
||||
if (event.ShiftDown() || m_layers_slider->is_one_layer()) m_layers_slider->SetLowerValue(m_layers_slider->GetHigherValue());
|
||||
}
|
||||
#if ENABLE_ARROW_KEYS_WITH_SLIDERS
|
||||
else if (key == 'A' || key == 'D') {
|
||||
const int new_pos = key == 'D' ? m_moves_slider->GetHigherValue() + 1 : m_moves_slider->GetHigherValue() - 1;
|
||||
m_moves_slider->SetHigherValue(new_pos);
|
||||
if (event.ShiftDown() || m_moves_slider->is_one_layer()) m_moves_slider->SetLowerValue(m_moves_slider->GetHigherValue());
|
||||
}
|
||||
else if (key == 'X')
|
||||
#else
|
||||
else if (key == 'S')
|
||||
#endif // ENABLE_ARROW_KEYS_WITH_SLIDERS
|
||||
m_layers_slider->ChangeOneLayerLock();
|
||||
else if (key == WXK_SHIFT)
|
||||
m_layers_slider->UseDefaultColors(false);
|
||||
|
|
|
|||
|
|
@ -157,6 +157,9 @@ public:
|
|||
void update_bottom_toolbar();
|
||||
void update_moves_slider();
|
||||
void enable_moves_slider(bool enable);
|
||||
#if ENABLE_ARROW_KEYS_WITH_SLIDERS
|
||||
void move_moves_slider(wxKeyEvent& evt);
|
||||
#endif // ENABLE_ARROW_KEYS_WITH_SLIDERS
|
||||
void hide_layers_slider();
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -147,10 +147,13 @@ void ArrangeJob::process()
|
|||
|
||||
GLCanvas3D::ArrangeSettings settings =
|
||||
m_plater->canvas3D()->get_arrange_settings();
|
||||
|
||||
|
||||
arrangement::ArrangeParams params;
|
||||
params.min_obj_distance = scaled(settings.distance);
|
||||
params.allow_rotations = settings.enable_rotation;
|
||||
params.min_obj_distance = m_plater->config()->opt_bool("complete_objects") ?
|
||||
scaled(settings.distance_seq_print) :
|
||||
scaled(settings.distance);
|
||||
|
||||
|
||||
auto count = unsigned(m_selected.size() + m_unprintable.size());
|
||||
Points bedpts = get_bed_shape(*m_plater->config());
|
||||
|
|
|
|||
|
|
@ -87,8 +87,10 @@ void FillBedJob::process()
|
|||
m_plater->canvas3D()->get_arrange_settings();
|
||||
|
||||
arrangement::ArrangeParams params;
|
||||
params.min_obj_distance = scaled(settings.distance);
|
||||
params.allow_rotations = settings.enable_rotation;
|
||||
params.min_obj_distance = m_plater->config()->opt_bool("complete_objects") ?
|
||||
scaled(settings.distance_seq_print) :
|
||||
scaled(settings.distance);
|
||||
|
||||
bool do_stop = false;
|
||||
params.stopcondition = [this, &do_stop]() {
|
||||
|
|
@ -114,6 +116,9 @@ void FillBedJob::process()
|
|||
|
||||
void FillBedJob::finalize()
|
||||
{
|
||||
// Ignore the arrange result if aborted.
|
||||
if (was_canceled()) return;
|
||||
|
||||
if (m_object_idx == -1) return;
|
||||
|
||||
ModelObject *model_object = m_plater->model().objects[m_object_idx];
|
||||
|
|
|
|||
|
|
@ -203,22 +203,48 @@ void KBShortcutsDialog::fill_shortcuts()
|
|||
}
|
||||
|
||||
Shortcuts preview_shortcuts = {
|
||||
{ L("Arrow Up"), L("Upper Layer") },
|
||||
{ L("Arrow Down"), L("Lower Layer") },
|
||||
#if ENABLE_ARROW_KEYS_WITH_SLIDERS
|
||||
{ L("Arrow Up"), L("Move vertical slider current thumb Up") },
|
||||
{ L("Arrow Down"), L("Move vertical slider current thumb Down") },
|
||||
{ L("Arrow Left"), L("Move horizontal slider current thumb Left") },
|
||||
{ L("Arrow Right"), L("Move horizontal slider current thumb Right") },
|
||||
{ "W", L("Move vertical slider current thumb Up") },
|
||||
{ "S", L("Move vertical slider current thumb Down") },
|
||||
{ "A", L("Move horizontal slider current thumb Left") },
|
||||
{ "D", L("Move horizontal slider current thumb Right") },
|
||||
{ "X", L("Toggle vertical slider one layer mode ON/OFF") },
|
||||
{ "L", L("Show/Hide Legend and Estimated printing time") },
|
||||
#else
|
||||
{ L("Arrow Up"), L("Upper layer") },
|
||||
{ L("Arrow Down"), L("Lower layer") },
|
||||
{ "U", L("Upper Layer") },
|
||||
{ "D", L("Lower Layer") },
|
||||
{ "L", L("Show/Hide Legend & Estimated printing time") },
|
||||
#endif // ENABLE_ARROW_KEYS_WITH_SLIDERS
|
||||
};
|
||||
|
||||
m_full_shortcuts.push_back(std::make_pair(_L("Preview"), preview_shortcuts));
|
||||
|
||||
Shortcuts layers_slider_shortcuts = {
|
||||
#if ENABLE_ARROW_KEYS_WITH_SLIDERS
|
||||
{ L("Arrow Up"), L("Vertical slider - Move current thumb Up") },
|
||||
{ L("Arrow Down"), L("Vertical slider - Move current thumb Down") },
|
||||
{ L("Arrow Left"), L("Vertical slider - Set upper thumb to current thumb") },
|
||||
{ L("Arrow Right"), L("Vertical slider - Set lower thumb to current thumb") },
|
||||
{ "+", L("Vertical slider - Add color change marker for current layer") },
|
||||
{ "-", L("Vertical slider - Delete color change marker for current layer") },
|
||||
{ L("Arrow Up"), L("Horizontal slider - Set left thumb to current thumb") },
|
||||
{ L("Arrow Down"), L("Horizontal slider - Set right thumb to current thumb") },
|
||||
{ L("Arrow Left"), L("Horizontal slider - Move current thumb Left") },
|
||||
{ L("Arrow Right"), L("Horizontal slider - Move current thumb Right") },
|
||||
#else
|
||||
{ L("Arrow Up"), L("Move current slider thumb Up") },
|
||||
{ L("Arrow Down"), L("Move current slider thumb Down") },
|
||||
{ L("Arrow Left"), L("Set upper thumb to current slider thumb") },
|
||||
{ L("Arrow Right"), L("Set lower thumb to current slider thumb") },
|
||||
{ "+", L("Add color change marker for current layer") },
|
||||
{ "-", L("Delete color change marker for current layer") },
|
||||
#endif // ENABLE_ARROW_KEYS_WITH_SLIDERS
|
||||
{ "Shift+", L("Press to speed up 5 times while moving thumb\nwith arrow keys or mouse wheel") },
|
||||
{ ctrl, L("Press to speed up 5 times while moving thumb\nwith arrow keys or mouse wheel") },
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2055,7 +2055,14 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
|
|||
preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_TAB, [this](SimpleEvent&) { select_next_view_3D(); });
|
||||
preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_COLLAPSE_SIDEBAR, [this](SimpleEvent&) { this->q->collapse_sidebar(!this->q->is_sidebar_collapsed()); });
|
||||
preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_JUMP_TO, [this](wxKeyEvent& evt) { preview->jump_layers_slider(evt); });
|
||||
#if ENABLE_ARROW_KEYS_WITH_SLIDERS
|
||||
preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_MOVE_SLIDERS, [this](wxKeyEvent& evt) {
|
||||
preview->move_layers_slider(evt);
|
||||
preview->move_moves_slider(evt);
|
||||
});
|
||||
#else
|
||||
preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_MOVE_LAYERS_SLIDER, [this](wxKeyEvent& evt) { preview->move_layers_slider(evt); });
|
||||
#endif // ENABLE_ARROW_KEYS_WITH_SLIDERS
|
||||
preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_EDIT_COLOR_CHANGE, [this](wxKeyEvent& evt) { preview->edit_layers_slider(evt); });
|
||||
|
||||
if (wxGetApp().is_editor()) {
|
||||
|
|
@ -3633,7 +3640,8 @@ void Plater::priv::on_process_completed(SlicingProcessCompletedEvent &evt)
|
|||
|
||||
// Reset the "export G-code path" name, so that the automatic background processing will be enabled again.
|
||||
this->background_process.reset_export();
|
||||
|
||||
// This bool stops showing export finished notification even when process_completed_with_error is false
|
||||
bool has_error = false;
|
||||
if (evt.error()) {
|
||||
std::string message = evt.format_error_message();
|
||||
if (evt.critical_error()) {
|
||||
|
|
@ -3653,7 +3661,7 @@ void Plater::priv::on_process_completed(SlicingProcessCompletedEvent &evt)
|
|||
sidebar->set_btn_label(btn, invalid_str);
|
||||
process_completed_with_error = true;
|
||||
}
|
||||
|
||||
has_error = true;
|
||||
}
|
||||
if (evt.cancelled())
|
||||
this->statusbar()->set_status_text(_L("Cancelled"));
|
||||
|
|
@ -3688,11 +3696,11 @@ void Plater::priv::on_process_completed(SlicingProcessCompletedEvent &evt)
|
|||
show_action_buttons(false);
|
||||
}
|
||||
// If writing to removable drive was scheduled, show notification with eject button
|
||||
if (exporting_status == ExportingStatus::EXPORTING_TO_REMOVABLE && !this->process_completed_with_error) {
|
||||
if (exporting_status == ExportingStatus::EXPORTING_TO_REMOVABLE && !has_error) {
|
||||
show_action_buttons(false);
|
||||
notification_manager->push_exporting_finished_notification(*q->get_current_canvas3D(), last_output_path, last_output_dir_path, true);
|
||||
wxGetApp().removable_drive_manager()->set_exporting_finished(true);
|
||||
}else if (exporting_status == ExportingStatus::EXPORTING_TO_LOCAL && !this->process_completed_with_error)
|
||||
}else if (exporting_status == ExportingStatus::EXPORTING_TO_LOCAL && !has_error)
|
||||
notification_manager->push_exporting_finished_notification(*q->get_current_canvas3D(), last_output_path, last_output_dir_path, false);
|
||||
}
|
||||
exporting_status = ExportingStatus::NOT_EXPORTING;
|
||||
|
|
|
|||
|
|
@ -24,6 +24,12 @@
|
|||
|
||||
using boost::optional;
|
||||
|
||||
#ifdef __Linux__
|
||||
#define wxLinux true
|
||||
#else
|
||||
#define wxLinux false
|
||||
#endif
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
namespace GUI {
|
||||
|
|
@ -586,7 +592,7 @@ void UnsavedChangesDialog::build(Preset::Type type, PresetCollection* dependent_
|
|||
m_tree->AssociateModel(m_tree_model);
|
||||
m_tree_model->SetAssociatedControl(m_tree);
|
||||
|
||||
m_tree->AppendToggleColumn(L"\u2714", UnsavedChangesModel::colToggle, wxDATAVIEW_CELL_ACTIVATABLE, 6 * em);//2610,11,12 //2714
|
||||
m_tree->AppendToggleColumn(L"\u2714", UnsavedChangesModel::colToggle, wxDATAVIEW_CELL_ACTIVATABLE, (wxLinux ? 8 : 6) * em);
|
||||
|
||||
auto append_bmp_text_column = [this](const wxString& label, unsigned model_column, int width, bool set_expander = false)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue