Skip to content

Commit

Permalink
Port EditGCodeDialog from PrusaSlicer (#3417)
Browse files Browse the repository at this point in the history
This is a port of the EditGCodeDialog from PrusaSlicer 2.7.x. There were
a few changes made to make it a bit more functional. Also, it isn't
quite fully complete, but it should be in a very usable state.

General Changes:
- Implement UndoValueUIManager and EditValueUI in Field
- Implement EditGCodeDialog and add buttons to the tabs
- Other minor changes to accommodate the new classes

Differences from PrusaSlicer's Implementation:
- backported to wxWidgets 3.1.5 (reverse commit 8770c4b after updating
to 3.2.x)
- icons have been updated to use Orca colors
- improve the report that tells you if certain placeholders have not
been defined properly for the dialog. It now shows all issues at once
rather than having to fix then recompile to see the next issue.
- allow the use of the cmake option `ORCA_CHECK_GCODE_PLACEHOLDERS` to
toggle the above report since our workflow rarely uses debug mode.
- if a custom gcode value is not set when checking gcode placeholders, a
testing value is set. Custom gcode is not parsed if it is empty, and the
only way to check if the placeholders are all defined is by running the
placeholder operation on the custom gcode.
- some calls to `print.config()` in Gcode.cpp were changed to `m_config`
to support the above testing values feature (only m_config is modified
with the placeholders and `print.config()` would return an empty string)
- a macro has been added to quickly add a definition to
SlicingStatesConfigDefs with less boiler plate (it could technically be
used for any ConfigOptionDef, but that would hurt interoperability with
PS. I tried to not use the macro for too many PS defined definitions.)
- the presets are now also categorized by the page they are on in their
tab
<table>
<tr>
 <td>Prusa
 <td>Orca
<tr>
 <td>
<img
src="https://github.com/SoftFever/OrcaSlicer/assets/24759591/27cb4f48-d225-4563-9aeb-b2b461f8bff5"
/>
 <td>
<img
src="https://github.com/SoftFever/OrcaSlicer/assets/24759591/4fcd8cde-2427-4d1a-a0ed-1738b570b919"
/>
</table>

TODO:
- [x] Make sure all linux fixes have been applied
- [x] Finish adding "universal" gcode options
- [x] add search function to dataview (maybe?)
- [x] determine if any options are being left out of the preset
categories by getting options from Tab rather than Presets. If so,
consider adding outside of the groupings
  • Loading branch information
SoftFever authored Jan 24, 2024
2 parents c4a66f3 + 11fd73a commit 5ff00fb
Show file tree
Hide file tree
Showing 33 changed files with 2,155 additions and 122 deletions.
2 changes: 2 additions & 0 deletions resources/images/custom-gcode_gcode.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions resources/images/custom-gcode_measure.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions resources/images/custom-gcode_object-info.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions resources/images/custom-gcode_single.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions resources/images/custom-gcode_slicing-state.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions resources/images/custom-gcode_slicing-state_global.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions resources/images/custom-gcode_stats.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 14 additions & 0 deletions resources/images/custom-gcode_temperature.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions resources/images/custom-gcode_vector-index.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions resources/images/custom-gcode_vector.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/OrcaSlicer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5329,6 +5329,7 @@ bool CLI::setup(int argc, char **argv)
set_var_dir((path_resources / "images").string());
set_local_dir((path_resources / "i18n").string());
set_sys_shapes_dir((path_resources / "shapes").string());
set_custom_gcodes_dir((path_resources / "custom_gcodes").string());

// Parse all command line options into a DynamicConfig.
// If any option is unsupported, print usage and abort immediately.
Expand Down
4 changes: 4 additions & 0 deletions src/libslic3r/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ include(PrecompiledHeader)
string(TIMESTAMP COMPILE_TIME %Y%m%d-%H%M%S)
set(SLIC3R_BUILD_TIME ${COMPILE_TIME})

if(NOT DEFINED ORCA_CHECK_GCODE_PLACEHOLDERS)
set(ORCA_CHECK_GCODE_PLACEHOLDERS "0")
endif()

configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libslic3r_version.h.in ${CMAKE_CURRENT_BINARY_DIR}/libslic3r_version.h @ONLY)

if (MINGW)
Expand Down
3 changes: 3 additions & 0 deletions src/libslic3r/Config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1786,6 +1786,8 @@ class ConfigOptionDef
// Create a default option to be inserted into a DynamicConfig.
ConfigOption* create_default_option() const;

bool is_scalar() const { return (int(this->type) & int(coVectorType)) == 0; }

template<class Archive> ConfigOption* load_option_from_archive(Archive &archive) const {
if (this->nullable) {
switch (this->type) {
Expand Down Expand Up @@ -1973,6 +1975,7 @@ class ConfigDef
out.push_back(kvp.first);
return out;
}
bool empty() { return options.empty(); }

// Iterate through all of the CLI options and write them to a stream.
std::ostream& print_cli_help(
Expand Down
86 changes: 82 additions & 4 deletions src/libslic3r/GCode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1585,6 +1585,21 @@ void GCode::do_export(Print* print, const char* path, GCodeProcessorResult* resu

check_placeholder_parser_failed();

#if ORCA_CHECK_GCODE_PLACEHOLDERS
if (!m_placeholder_error_messages.empty()){
std::ostringstream message;
message << "Some EditGcodeDialog defs were not specified properly. Do so in PrintConfig under SlicingStatesConfigDef:" << std::endl;
for (const auto& error : m_placeholder_error_messages) {
message << std::endl << error.first << ": " << std::endl;
for (const auto& str : error.second)
message << str << ", ";
message.seekp(-2, std::ios_base::end);
message << std::endl;
}
throw Slic3r::PlaceholderParserError(message.str());
}
#endif

BOOST_LOG_TRIVIAL(debug) << "Start processing gcode, " << log_memory_info();
// Post-process the G-code to update time stamps.

Expand Down Expand Up @@ -2936,6 +2951,42 @@ void GCode::process_layers(

std::string GCode::placeholder_parser_process(const std::string &name, const std::string &templ, unsigned int current_extruder_id, const DynamicConfig *config_override)
{
// Orca: Added CMake config option since debug is rarely used in current workflow.
// Also changed from throwing error immediately to storing messages till slicing is completed
// to raise all errors at the same time.
#if !defined(NDEBUG) || ORCA_CHECK_GCODE_PLACEHOLDERS // CHECK_CUSTOM_GCODE_PLACEHOLDERS
if (config_override) {
const auto& custom_gcode_placeholders = custom_gcode_specific_placeholders();

// 1-st check: custom G-code "name" have to be present in s_CustomGcodeSpecificOptions;
//if (custom_gcode_placeholders.count(name) > 0) {
// const auto& placeholders = custom_gcode_placeholders.at(name);
if (auto it = custom_gcode_placeholders.find(name); it != custom_gcode_placeholders.end()) {
const auto& placeholders = it->second;

for (const std::string& key : config_override->keys()) {
// 2-nd check: "key" have to be present in s_CustomGcodeSpecificOptions for "name" custom G-code ;
if (std::find(placeholders.begin(), placeholders.end(), key) == placeholders.end()) {
auto& vector = m_placeholder_error_messages[name + " - option not specified for custom gcode type (s_CustomGcodeSpecificOptions)"];
if (std::find(vector.begin(), vector.end(), key) == vector.end())
vector.emplace_back(key);
}
// 3-rd check: "key" have to be present in CustomGcodeSpecificConfigDef for "key" placeholder;
if (!custom_gcode_specific_config_def.has(key)) {
auto& vector = m_placeholder_error_messages[name + " - option has no definition (CustomGcodeSpecificConfigDef)"];
if (std::find(vector.begin(), vector.end(), key) == vector.end())
vector.emplace_back(key);
}
}
}
else {
auto& vector = m_placeholder_error_messages[name + " - gcode type not found in s_CustomGcodeSpecificOptions"];
if (vector.empty())
vector.emplace_back("");
}
}
#endif

PlaceholderParserIntegration &ppi = m_placeholder_parser_integration;
try {
ppi.update_from_gcodewriter(m_writer);
Expand Down Expand Up @@ -3528,7 +3579,7 @@ LayerResult GCode::process_layer(
m_last_height = height;

// Set new layer - this will change Z and force a retraction if retract_when_changing_layer is enabled.
if (! print.config().before_layer_change_gcode.value.empty()) {
if (! m_config.before_layer_change_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));
Expand All @@ -3551,7 +3602,7 @@ LayerResult GCode::process_layer(

auto insert_timelapse_gcode = [this, print_z, &print]() -> std::string {
std::string gcode_res;
if (!print.config().time_lapse_gcode.value.empty()) {
if (!m_config.time_lapse_gcode.value.empty()) {
DynamicConfig config;
config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index));
config.set_key_value("layer_z", new ConfigOptionFloat(print_z));
Expand Down Expand Up @@ -3579,7 +3630,7 @@ LayerResult GCode::process_layer(
}
}
} else {
if (!print.config().time_lapse_gcode.value.empty()) {
if (!m_config.time_lapse_gcode.value.empty()) {
DynamicConfig config;
config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index));
config.set_key_value("layer_z", new ConfigOptionFloat(print_z));
Expand All @@ -3589,7 +3640,7 @@ LayerResult GCode::process_layer(
"\n";
}
}
if (! print.config().layer_change_gcode.value.empty()) {
if (! m_config.layer_change_gcode.value.empty()) {
DynamicConfig config;
config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index));
config.set_key_value("layer_z", new ConfigOptionFloat(print_z));
Expand Down Expand Up @@ -4287,6 +4338,33 @@ void GCode::apply_print_config(const PrintConfig &print_config)
m_writer.apply_print_config(print_config);
m_config.apply(print_config);
m_scaled_resolution = scaled<double>(print_config.resolution.value);

#if ORCA_CHECK_GCODE_PLACEHOLDERS
// If the gcode value is empty, set a value so that the check code within the parser is run
for (auto opt : std::initializer_list<ConfigOptionString*>{
&m_config.machine_start_gcode,
&m_config.machine_end_gcode,
&m_config.before_layer_change_gcode,
&m_config.layer_change_gcode,
&m_config.time_lapse_gcode,
&m_config.change_filament_gcode,
&m_config.change_extrusion_role_gcode,
&m_config.printing_by_object_gcode,
&m_config.machine_pause_gcode,
&m_config.template_custom_gcode,
}) {
if (opt->empty())
opt->set(new ConfigOptionString(";VALUE FOR TESTING"));
}
for (auto opt : std::initializer_list<ConfigOptionStrings*>{
&m_config.filament_start_gcode,
&m_config.filament_end_gcode
}) {
if (opt->empty())
for (int i = 0; i < opt->size(); ++i)
opt->set_at(new ConfigOptionString(";VALUE FOR TESTING"), i, 0);
}
#endif
}

void GCode::append_full_config(const Print &print, std::string &str)
Expand Down
5 changes: 5 additions & 0 deletions src/libslic3r/GCode.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ struct LayerResult {
};

class GCode {

public:
GCode() :
m_origin(Vec2d::Zero()),
Expand Down Expand Up @@ -522,6 +523,10 @@ class GCode {
double m_last_mm3_per_mm;
#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING

#if ORCA_CHECK_GCODE_PLACEHOLDERS
std::map<std::string, std::vector<std::string>> m_placeholder_error_messages;
#endif

Point m_last_pos;
bool m_last_pos_defined;

Expand Down
1 change: 1 addition & 0 deletions src/libslic3r/Print.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2041,6 +2041,7 @@ std::string Print::export_gcode(const std::string& path_template, GCodeProcessor
const Vec3d origin = this->get_plate_origin();
gcode.set_gcode_offset(origin(0), origin(1));
gcode.do_export(this, path.c_str(), result, thumbnail_cb);

//BBS
result->conflict_result = m_conflict_result;
return path.c_str();
Expand Down
Loading

0 comments on commit 5ff00fb

Please sign in to comment.