mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-10 17:21:10 +00:00
refactor: rename iXex → IMEX throughout; use IDEX/IQEX as user-facing label
- All config keys: ixex_* → imex_* (is_imex, imex_gantry_count, etc.) - All C++ identifiers: IXexModesCtrl → IMEXModesCtrl, m_ixex_* → m_imex_*, etc. - 3MF serialization key: ixex_parallel_mode → imex_parallel_mode - UI strings: iXex → IDEX/IQEX - SVG icons: plate_ixex_mode*.svg → plate_imex_mode*.svg - Remove unused ixex_mode.svg Breaking change for existing printer configs — acceptable pre-merge. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
2934b18d2a
commit
461c69c83e
@@ -0,0 +1,10 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="43" height="43" viewBox="0 0 43 43">
|
||||||
|
<rect x="1.5" y="1.5" width="40" height="40" rx="3.5" style="fill:#e9e9e9"/>
|
||||||
|
<path d="M38,2a3,3,0,0,1,3,3V38a3,3,0,0,1-3,3H5a3,3,0,0,1-3-3V5A3,3,0,0,1,5,2H38m0-1H5A4,4,0,0,0,1,5V38a4,4,0,0,0,4,4H38a4,4,0,0,0,4-4V5a4,4,0,0,0-4-4Z" style="fill:#545454;stroke-width:1.0015748;stroke-dasharray:none"/>
|
||||||
|
<path d="M 16.798963,13.679793 14.08412,14.062706 12.860469,16.516209 11.657363,14.052567 8.9458146,13.646979 10.917098,11.741451 10.46492,9.0372811 12.886345,10.323242 15.318433,9.0575608 14.843673,11.757857 Z" style="fill:none;stroke:#545454;stroke-width:0.8;stroke-dasharray:none" transform="translate(2,0.6593574)"/>
|
||||||
|
<path d="M 16.798963,13.679793 14.08412,14.062706 12.860469,16.516209 11.657363,14.052567 8.9458146,13.646979 10.917098,11.741451 10.46492,9.0372811 12.886345,10.323242 15.318433,9.0575608 14.843673,11.757857 Z" style="fill:none;stroke:#545454;stroke-width:0.8;stroke-dasharray:none" transform="translate(15.543848,0.6593574)"/>
|
||||||
|
<path d="M 16.798963,13.679793 14.08412,14.062706 12.860469,16.516209 11.657363,14.052567 8.9458146,13.646979 10.917098,11.741451 10.46492,9.0372811 12.886345,10.323242 15.318433,9.0575608 14.843673,11.757857 Z" style="fill:none;stroke:#545454;stroke-width:0.8;stroke-dasharray:none" transform="translate(1.9999996,17.214798)"/>
|
||||||
|
<path d="M 16.798963,13.679793 14.08412,14.062706 12.860469,16.516209 11.657363,14.052567 8.9458146,13.646979 10.917098,11.741451 10.46492,9.0372811 12.886345,10.323242 15.318433,9.0575608 14.843673,11.757857 Z" style="fill:none;stroke:#545454;stroke-width:0.8;stroke-dasharray:none" transform="translate(15.517972,17.291251)"/>
|
||||||
|
<path d="M 21.527502,7.146574 V 35.745655" style="fill:#545454;stroke:#545454;stroke-width:0.8;stroke-linecap:round;stroke-dasharray:none"/>
|
||||||
|
<path d="M 8.3002566,21.575891 H 34.251585" style="fill:#545454;stroke:#545454;stroke-width:0.8;stroke-linecap:round;stroke-dasharray:none"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.9 KiB |
@@ -0,0 +1,10 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="43" height="43" viewBox="0 0 43 43">
|
||||||
|
<rect x="1.5" y="1.5" width="40" height="40" rx="3.5" style="fill:#54545a"/>
|
||||||
|
<path d="M38,2a3,3,0,0,1,3,3V38a3,3,0,0,1-3,3H5a3,3,0,0,1-3-3V5A3,3,0,0,1,5,2H38m0-1H5A4,4,0,0,0,1,5V38a4,4,0,0,0,4,4H38a4,4,0,0,0,4-4V5a4,4,0,0,0-4-4Z" style="fill:#b3b3b3;stroke-width:1.0015748;stroke-dasharray:none"/>
|
||||||
|
<path d="M 16.798963,13.679793 14.08412,14.062706 12.860469,16.516209 11.657363,14.052567 8.9458146,13.646979 10.917098,11.741451 10.46492,9.0372811 12.886345,10.323242 15.318433,9.0575608 14.843673,11.757857 Z" style="fill:none;stroke:#c4c4c4;stroke-width:0.8;stroke-dasharray:none" transform="translate(2,0.6593574)"/>
|
||||||
|
<path d="M 16.798963,13.679793 14.08412,14.062706 12.860469,16.516209 11.657363,14.052567 8.9458146,13.646979 10.917098,11.741451 10.46492,9.0372811 12.886345,10.323242 15.318433,9.0575608 14.843673,11.757857 Z" style="fill:none;stroke:#c4c4c4;stroke-width:0.8;stroke-dasharray:none" transform="translate(15.543848,0.6593574)"/>
|
||||||
|
<path d="M 16.798963,13.679793 14.08412,14.062706 12.860469,16.516209 11.657363,14.052567 8.9458146,13.646979 10.917098,11.741451 10.46492,9.0372811 12.886345,10.323242 15.318433,9.0575608 14.843673,11.757857 Z" style="fill:none;stroke:#c4c4c4;stroke-width:0.8;stroke-dasharray:none" transform="translate(1.9999996,17.214798)"/>
|
||||||
|
<path d="M 16.798963,13.679793 14.08412,14.062706 12.860469,16.516209 11.657363,14.052567 8.9458146,13.646979 10.917098,11.741451 10.46492,9.0372811 12.886345,10.323242 15.318433,9.0575608 14.843673,11.757857 Z" style="fill:none;stroke:#c4c4c4;stroke-width:0.8;stroke-dasharray:none" transform="translate(15.517972,17.291251)"/>
|
||||||
|
<path d="M 21.527502,7.146574 V 35.745655" style="fill:#c4c4c4;stroke:#c4c4c4;stroke-width:0.8;stroke-linecap:round;stroke-dasharray:none"/>
|
||||||
|
<path d="M 8.3002566,21.575891 H 34.251585" style="fill:#c4c4c4;stroke:#c4c4c4;stroke-width:0.8;stroke-linecap:round;stroke-dasharray:none"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.9 KiB |
@@ -0,0 +1,10 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="43" height="43" viewBox="0 0 43 43">
|
||||||
|
<rect x="1.5" y="1.5" width="40" height="40" rx="3.5" style="fill:#e9e9e9"/>
|
||||||
|
<path d="M38,2a3,3,0,0,1,3,3V38a3,3,0,0,1-3,3H5a3,3,0,0,1-3-3V5A3,3,0,0,1,5,2H38m0-1H5A4,4,0,0,0,1,5V38a4,4,0,0,0,4,4H38a4,4,0,0,0,4-4V5a4,4,0,0,0-4-4Z" style="fill:#009688;stroke-width:1.0015748;stroke-dasharray:none"/>
|
||||||
|
<path d="M 16.798963,13.679793 14.08412,14.062706 12.860469,16.516209 11.657363,14.052567 8.9458146,13.646979 10.917098,11.741451 10.46492,9.0372811 12.886345,10.323242 15.318433,9.0575608 14.843673,11.757857 Z" style="fill:none;stroke:#009688;stroke-width:0.8;stroke-dasharray:none" transform="translate(2,0.6593574)"/>
|
||||||
|
<path d="M 16.798963,13.679793 14.08412,14.062706 12.860469,16.516209 11.657363,14.052567 8.9458146,13.646979 10.917098,11.741451 10.46492,9.0372811 12.886345,10.323242 15.318433,9.0575608 14.843673,11.757857 Z" style="fill:none;stroke:#009688;stroke-width:0.8;stroke-dasharray:none" transform="translate(15.543848,0.6593574)"/>
|
||||||
|
<path d="M 16.798963,13.679793 14.08412,14.062706 12.860469,16.516209 11.657363,14.052567 8.9458146,13.646979 10.917098,11.741451 10.46492,9.0372811 12.886345,10.323242 15.318433,9.0575608 14.843673,11.757857 Z" style="fill:none;stroke:#009688;stroke-width:0.8;stroke-dasharray:none" transform="translate(1.9999996,17.214798)"/>
|
||||||
|
<path d="M 16.798963,13.679793 14.08412,14.062706 12.860469,16.516209 11.657363,14.052567 8.9458146,13.646979 10.917098,11.741451 10.46492,9.0372811 12.886345,10.323242 15.318433,9.0575608 14.843673,11.757857 Z" style="fill:none;stroke:#009688;stroke-width:0.8;stroke-dasharray:none" transform="translate(15.517972,17.291251)"/>
|
||||||
|
<path d="M 21.527502,7.146574 V 35.745655" style="fill:#009688;stroke:#009688;stroke-width:0.8;stroke-linecap:round;stroke-dasharray:none"/>
|
||||||
|
<path d="M 8.3002566,21.575891 H 34.251585" style="fill:#009688;stroke:#009688;stroke-width:0.8;stroke-linecap:round;stroke-dasharray:none"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.9 KiB |
@@ -0,0 +1,10 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="43" height="43" viewBox="0 0 43 43">
|
||||||
|
<rect x="1.5" y="1.5" width="40" height="40" rx="3.5" style="fill:#54545a"/>
|
||||||
|
<path d="M38,2a3,3,0,0,1,3,3V38a3,3,0,0,1-3,3H5a3,3,0,0,1-3-3V5A3,3,0,0,1,5,2H38m0-1H5A4,4,0,0,0,1,5V38a4,4,0,0,0,4,4H38a4,4,0,0,0,4-4V5a4,4,0,0,0-4-4Z" style="fill:#009688;stroke-width:1.0015748;stroke-dasharray:none"/>
|
||||||
|
<path d="M 16.798963,13.679793 14.08412,14.062706 12.860469,16.516209 11.657363,14.052567 8.9458146,13.646979 10.917098,11.741451 10.46492,9.0372811 12.886345,10.323242 15.318433,9.0575608 14.843673,11.757857 Z" style="fill:none;stroke:#009688;stroke-width:0.8;stroke-dasharray:none" transform="translate(2,0.6593574)"/>
|
||||||
|
<path d="M 16.798963,13.679793 14.08412,14.062706 12.860469,16.516209 11.657363,14.052567 8.9458146,13.646979 10.917098,11.741451 10.46492,9.0372811 12.886345,10.323242 15.318433,9.0575608 14.843673,11.757857 Z" style="fill:none;stroke:#009688;stroke-width:0.8;stroke-dasharray:none" transform="translate(15.543848,0.6593574)"/>
|
||||||
|
<path d="M 16.798963,13.679793 14.08412,14.062706 12.860469,16.516209 11.657363,14.052567 8.9458146,13.646979 10.917098,11.741451 10.46492,9.0372811 12.886345,10.323242 15.318433,9.0575608 14.843673,11.757857 Z" style="fill:none;stroke:#009688;stroke-width:0.8;stroke-dasharray:none" transform="translate(1.9999996,17.214798)"/>
|
||||||
|
<path d="M 16.798963,13.679793 14.08412,14.062706 12.860469,16.516209 11.657363,14.052567 8.9458146,13.646979 10.917098,11.741451 10.46492,9.0372811 12.886345,10.323242 15.318433,9.0575608 14.843673,11.757857 Z" style="fill:none;stroke:#009688;stroke-width:0.8;stroke-dasharray:none" transform="translate(15.517972,17.291251)"/>
|
||||||
|
<path d="M 21.527502,7.146574 V 35.745655" style="fill:#009688;stroke:#009688;stroke-width:0.8;stroke-linecap:round;stroke-dasharray:none"/>
|
||||||
|
<path d="M 8.3002566,21.575891 H 34.251585" style="fill:#009688;stroke:#009688;stroke-width:0.8;stroke-linecap:round;stroke-dasharray:none"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.9 KiB |
@@ -333,7 +333,7 @@ static constexpr const char* FIRST_LAYER_PRINT_SEQUENCE_ATTR = "first_layer_prin
|
|||||||
static constexpr const char* OTHER_LAYERS_PRINT_SEQUENCE_ATTR = "other_layers_print_sequence";
|
static constexpr const char* OTHER_LAYERS_PRINT_SEQUENCE_ATTR = "other_layers_print_sequence";
|
||||||
static constexpr const char* OTHER_LAYERS_PRINT_SEQUENCE_NUMS_ATTR = "other_layers_print_sequence_nums";
|
static constexpr const char* OTHER_LAYERS_PRINT_SEQUENCE_NUMS_ATTR = "other_layers_print_sequence_nums";
|
||||||
static constexpr const char* SPIRAL_VASE_MODE = "spiral_mode";
|
static constexpr const char* SPIRAL_VASE_MODE = "spiral_mode";
|
||||||
static constexpr const char* IXEX_PARALLEL_MODE_ATTR = "ixex_parallel_mode";
|
static constexpr const char* IMEX_PARALLEL_MODE_ATTR = "imex_parallel_mode";
|
||||||
static constexpr const char* FILAMENT_MAP_MODE_ATTR = "filament_map_mode";
|
static constexpr const char* FILAMENT_MAP_MODE_ATTR = "filament_map_mode";
|
||||||
static constexpr const char* FILAMENT_MAP_ATTR = "filament_maps";
|
static constexpr const char* FILAMENT_MAP_ATTR = "filament_maps";
|
||||||
static constexpr const char* LIMIT_FILAMENT_MAP_ATTR = "limit_filament_maps";
|
static constexpr const char* LIMIT_FILAMENT_MAP_ATTR = "limit_filament_maps";
|
||||||
@@ -4293,8 +4293,8 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||||||
std::istringstream(value) >> std::boolalpha >> spiral_mode;
|
std::istringstream(value) >> std::boolalpha >> spiral_mode;
|
||||||
m_curr_plater->config.set_key_value("spiral_mode", new ConfigOptionBool(spiral_mode));
|
m_curr_plater->config.set_key_value("spiral_mode", new ConfigOptionBool(spiral_mode));
|
||||||
}
|
}
|
||||||
else if (key == IXEX_PARALLEL_MODE_ATTR) {
|
else if (key == IMEX_PARALLEL_MODE_ATTR) {
|
||||||
m_curr_plater->config.set_key_value("ixex_parallel_mode", new ConfigOptionString(value));
|
m_curr_plater->config.set_key_value("imex_parallel_mode", new ConfigOptionString(value));
|
||||||
}
|
}
|
||||||
else if (key == FILAMENT_MAP_MODE_ATTR)
|
else if (key == FILAMENT_MAP_MODE_ATTR)
|
||||||
{
|
{
|
||||||
@@ -7778,9 +7778,9 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||||||
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << SPIRAL_VASE_MODE << "\" " << VALUE_ATTR << "=\"" << spiral_mode_opt->getBool() << "\"/>\n";
|
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << SPIRAL_VASE_MODE << "\" " << VALUE_ATTR << "=\"" << spiral_mode_opt->getBool() << "\"/>\n";
|
||||||
|
|
||||||
{
|
{
|
||||||
auto* ixex_mode_opt = plate_data->config.option<ConfigOptionString>("ixex_parallel_mode");
|
auto* imex_mode_opt = plate_data->config.option<ConfigOptionString>("imex_parallel_mode");
|
||||||
if (ixex_mode_opt && !ixex_mode_opt->value.empty() && ixex_mode_opt->value != "primary")
|
if (imex_mode_opt && !imex_mode_opt->value.empty() && imex_mode_opt->value != "primary")
|
||||||
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << IXEX_PARALLEL_MODE_ATTR << "\" " << VALUE_ATTR << "=\"" << ixex_mode_opt->value << "\"/>\n";
|
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << IMEX_PARALLEL_MODE_ATTR << "\" " << VALUE_ATTR << "=\"" << imex_mode_opt->value << "\"/>\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
//filament map related
|
//filament map related
|
||||||
|
|||||||
+10
-10
@@ -3054,18 +3054,18 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
|||||||
file.write(m_writer.set_chamber_temperature(max_chamber_temp, true)); // set chamber_temperature
|
file.write(m_writer.set_chamber_temperature(max_chamber_temp, true)); // set chamber_temperature
|
||||||
}
|
}
|
||||||
|
|
||||||
// iXex: inject mode G-code before machine_start_gcode so the carriage mode
|
// IDEX/IQEX: inject mode G-code before machine_start_gcode so the carriage mode
|
||||||
// macro is active before any motion, homing, or probing in start G-code.
|
// macro is active before any motion, homing, or probing in start G-code.
|
||||||
if (print.config().is_ixex.value && !print.objects().empty()) {
|
if (print.config().is_imex.value && !print.objects().empty()) {
|
||||||
const std::string& ixex_mode = print.objects().front()->config().ixex_parallel_mode.value;
|
const std::string& imex_mode = print.objects().front()->config().imex_parallel_mode.value;
|
||||||
if (!ixex_mode.empty() && ixex_mode != "primary") {
|
if (!imex_mode.empty() && imex_mode != "primary") {
|
||||||
const auto& mode_names = print.config().ixex_mode_names.values;
|
const auto& mode_names = print.config().imex_mode_names.values;
|
||||||
const auto& mode_gcodes = print.config().ixex_mode_gcodes.values;
|
const auto& mode_gcodes = print.config().imex_mode_gcodes.values;
|
||||||
for (size_t i = 0; i < mode_names.size() && i < mode_gcodes.size(); ++i) {
|
for (size_t i = 0; i < mode_names.size() && i < mode_gcodes.size(); ++i) {
|
||||||
if (mode_names[i] == ixex_mode && !mode_gcodes[i].empty()) {
|
if (mode_names[i] == imex_mode && !mode_gcodes[i].empty()) {
|
||||||
std::string ixex_gcode = this->placeholder_parser_process(
|
std::string imex_gcode = this->placeholder_parser_process(
|
||||||
"ixex_mode_gcode", mode_gcodes[i], initial_extruder_id);
|
"imex_mode_gcode", mode_gcodes[i], initial_extruder_id);
|
||||||
file.writeln(ixex_gcode);
|
file.writeln(imex_gcode);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -961,8 +961,8 @@ static std::vector<std::string> s_Preset_print_options {
|
|||||||
"enable_wrapping_detection",
|
"enable_wrapping_detection",
|
||||||
"seam_slope_type", "seam_slope_conditional", "scarf_angle_threshold", "scarf_joint_speed", "scarf_joint_flow_ratio", "seam_slope_start_height", "seam_slope_entire_loop", "seam_slope_min_length", "seam_slope_steps", "seam_slope_inner_walls", "scarf_overhang_threshold",
|
"seam_slope_type", "seam_slope_conditional", "scarf_angle_threshold", "scarf_joint_speed", "scarf_joint_flow_ratio", "seam_slope_start_height", "seam_slope_entire_loop", "seam_slope_min_length", "seam_slope_steps", "seam_slope_inner_walls", "scarf_overhang_threshold",
|
||||||
"interlocking_beam", "interlocking_orientation", "interlocking_beam_layer_count", "interlocking_depth", "interlocking_boundary_avoidance", "interlocking_beam_width","calib_flowrate_topinfill_special_order",
|
"interlocking_beam", "interlocking_orientation", "interlocking_beam_layer_count", "interlocking_depth", "interlocking_boundary_avoidance", "interlocking_beam_width","calib_flowrate_topinfill_special_order",
|
||||||
// iXex parallel print mode (per-print selection)
|
// IDEX/IQEX parallel print mode (per-print selection)
|
||||||
"ixex_parallel_mode",
|
"imex_parallel_mode",
|
||||||
};
|
};
|
||||||
|
|
||||||
static std::vector<std::string> s_Preset_filament_options {/*"filament_colour", */ "default_filament_colour", "required_nozzle_HRC", "filament_diameter", "pellet_flow_coefficient", "volumetric_speed_coefficients", "filament_type",
|
static std::vector<std::string> s_Preset_filament_options {/*"filament_colour", */ "default_filament_colour", "required_nozzle_HRC", "filament_diameter", "pellet_flow_coefficient", "volumetric_speed_coefficients", "filament_type",
|
||||||
@@ -1040,10 +1040,10 @@ static std::vector<std::string> s_Preset_printer_options {
|
|||||||
"z_offset",
|
"z_offset",
|
||||||
"disable_m73", "preferred_orientation", "emit_machine_limits_to_gcode", "pellet_modded_printer", "support_multi_bed_types", "default_bed_type", "bed_mesh_min","bed_mesh_max","bed_mesh_probe_distance", "adaptive_bed_mesh_margin", "enable_long_retraction_when_cut","long_retractions_when_cut","retraction_distances_when_cut",
|
"disable_m73", "preferred_orientation", "emit_machine_limits_to_gcode", "pellet_modded_printer", "support_multi_bed_types", "default_bed_type", "bed_mesh_min","bed_mesh_max","bed_mesh_probe_distance", "adaptive_bed_mesh_margin", "enable_long_retraction_when_cut","long_retractions_when_cut","retraction_distances_when_cut",
|
||||||
"bed_temperature_formula", "nozzle_flush_dataset",
|
"bed_temperature_formula", "nozzle_flush_dataset",
|
||||||
// iXex (independent X extruder) — printer capability and user-defined modes
|
// IDEX/IQEX (independent X extruder) — printer capability and user-defined modes
|
||||||
"is_ixex", "ixex_gantry_count", "ixex_tools_per_gantry", "ixex_tool_layout",
|
"is_imex", "imex_gantry_count", "imex_tools_per_gantry", "imex_tool_layout",
|
||||||
"ixex_nozzle_clearance_x", "ixex_nozzle_clearance_y", "ixex_carriage_margin", "ixex_viz_theme",
|
"imex_nozzle_clearance_x", "imex_nozzle_clearance_y", "imex_carriage_margin", "imex_viz_theme",
|
||||||
"ixex_mode_names", "ixex_mode_active_tools", "ixex_mode_gcodes"
|
"imex_mode_names", "imex_mode_active_tools", "imex_mode_gcodes"
|
||||||
};
|
};
|
||||||
|
|
||||||
static std::vector<std::string> s_Preset_sla_print_options {
|
static std::vector<std::string> s_Preset_sla_print_options {
|
||||||
|
|||||||
@@ -5487,14 +5487,14 @@ void PrintConfigDef::init_fff_params()
|
|||||||
def->mode = comAdvanced;
|
def->mode = comAdvanced;
|
||||||
def->set_default_value(new ConfigOptionBool(true));
|
def->set_default_value(new ConfigOptionBool(true));
|
||||||
|
|
||||||
// iXex (independent X extruder) — parallel printing support for IDEX/IQEX printers
|
// IDEX/IQEX (independent X extruder) — parallel printing support for IDEX/IQEX printers
|
||||||
def = this->add("is_ixex", coBool);
|
def = this->add("is_imex", coBool);
|
||||||
def->label = L("iXex Printer");
|
def->label = L("IDEX/IQEX Printer");
|
||||||
def->tooltip = L("Enable iXex (independent X extruder) support for IDEX/IQEX printers with multiple independent carriages.");
|
def->tooltip = L("Enable IDEX/IQEX (independent X extruder) support for IDEX/IQEX printers with multiple independent carriages.");
|
||||||
def->mode = comAdvanced;
|
def->mode = comAdvanced;
|
||||||
def->set_default_value(new ConfigOptionBool(false));
|
def->set_default_value(new ConfigOptionBool(false));
|
||||||
|
|
||||||
def = this->add("ixex_gantry_count", coInt);
|
def = this->add("imex_gantry_count", coInt);
|
||||||
def->label = L("Gantry Count");
|
def->label = L("Gantry Count");
|
||||||
def->tooltip = L("Number of independent Y-axis gantries. 1 for IDEX/single-rail IQEX. 2 for dual-gantry systems (divides bed into rows).");
|
def->tooltip = L("Number of independent Y-axis gantries. 1 for IDEX/single-rail IQEX. 2 for dual-gantry systems (divides bed into rows).");
|
||||||
def->min = 1;
|
def->min = 1;
|
||||||
@@ -5502,7 +5502,7 @@ void PrintConfigDef::init_fff_params()
|
|||||||
def->mode = comAdvanced;
|
def->mode = comAdvanced;
|
||||||
def->set_default_value(new ConfigOptionInt(1));
|
def->set_default_value(new ConfigOptionInt(1));
|
||||||
|
|
||||||
def = this->add("ixex_tools_per_gantry", coInt);
|
def = this->add("imex_tools_per_gantry", coInt);
|
||||||
def->label = L("Tools per Gantry");
|
def->label = L("Tools per Gantry");
|
||||||
def->tooltip = L("Number of independent toolheads per gantry along X. 2 for IDEX-style.");
|
def->tooltip = L("Number of independent toolheads per gantry along X. 2 for IDEX-style.");
|
||||||
def->min = 1;
|
def->min = 1;
|
||||||
@@ -5510,7 +5510,7 @@ void PrintConfigDef::init_fff_params()
|
|||||||
def->mode = comAdvanced;
|
def->mode = comAdvanced;
|
||||||
def->set_default_value(new ConfigOptionInt(2));
|
def->set_default_value(new ConfigOptionInt(2));
|
||||||
|
|
||||||
def = this->add("ixex_tool_layout", coString);
|
def = this->add("imex_tool_layout", coString);
|
||||||
def->label = L("Tool 0 Corner");
|
def->label = L("Tool 0 Corner");
|
||||||
def->tooltip = L("Physical corner of the bed where tool T0 (index 0) is located. "
|
def->tooltip = L("Physical corner of the bed where tool T0 (index 0) is located. "
|
||||||
"Determines how tool indices map to bed zones. "
|
"Determines how tool indices map to bed zones. "
|
||||||
@@ -5518,7 +5518,7 @@ void PrintConfigDef::init_fff_params()
|
|||||||
def->mode = comAdvanced;
|
def->mode = comAdvanced;
|
||||||
def->set_default_value(new ConfigOptionString("front-left"));
|
def->set_default_value(new ConfigOptionString("front-left"));
|
||||||
|
|
||||||
def = this->add("ixex_nozzle_clearance_x", coFloat);
|
def = this->add("imex_nozzle_clearance_x", coFloat);
|
||||||
def->label = L("Nozzle Clearance X");
|
def->label = L("Nozzle Clearance X");
|
||||||
def->tooltip = L("Distance (mm) from the nozzle to the collision-side carriage edge in X. Used to calculate the width of the collision exclusion strip at each X boundary.");
|
def->tooltip = L("Distance (mm) from the nozzle to the collision-side carriage edge in X. Used to calculate the width of the collision exclusion strip at each X boundary.");
|
||||||
def->sidetext = L("mm");
|
def->sidetext = L("mm");
|
||||||
@@ -5526,7 +5526,7 @@ void PrintConfigDef::init_fff_params()
|
|||||||
def->mode = comAdvanced;
|
def->mode = comAdvanced;
|
||||||
def->set_default_value(new ConfigOptionFloat(30.0));
|
def->set_default_value(new ConfigOptionFloat(30.0));
|
||||||
|
|
||||||
def = this->add("ixex_nozzle_clearance_y", coFloat);
|
def = this->add("imex_nozzle_clearance_y", coFloat);
|
||||||
def->label = L("Nozzle Clearance Y");
|
def->label = L("Nozzle Clearance Y");
|
||||||
def->tooltip = L("Distance (mm) from the nozzle to the collision-side carriage edge in Y. Used to calculate the width of the collision exclusion strip at each Y boundary.");
|
def->tooltip = L("Distance (mm) from the nozzle to the collision-side carriage edge in Y. Used to calculate the width of the collision exclusion strip at each Y boundary.");
|
||||||
def->sidetext = L("mm");
|
def->sidetext = L("mm");
|
||||||
@@ -5534,7 +5534,7 @@ void PrintConfigDef::init_fff_params()
|
|||||||
def->mode = comAdvanced;
|
def->mode = comAdvanced;
|
||||||
def->set_default_value(new ConfigOptionFloat(30.0));
|
def->set_default_value(new ConfigOptionFloat(30.0));
|
||||||
|
|
||||||
def = this->add("ixex_carriage_margin", coFloat);
|
def = this->add("imex_carriage_margin", coFloat);
|
||||||
def->label = L("Safety Margin");
|
def->label = L("Safety Margin");
|
||||||
def->tooltip = L("Non-blocking advisory clearance strip (mm) drawn inside the primary zone at each carriage boundary. Parts placed within this strip will still slice; it is a visual reminder to leave extra clearance near the zone edge.");
|
def->tooltip = L("Non-blocking advisory clearance strip (mm) drawn inside the primary zone at each carriage boundary. Parts placed within this strip will still slice; it is a visual reminder to leave extra clearance near the zone edge.");
|
||||||
def->sidetext = L("mm");
|
def->sidetext = L("mm");
|
||||||
@@ -5543,32 +5543,32 @@ void PrintConfigDef::init_fff_params()
|
|||||||
def->mode = comAdvanced;
|
def->mode = comAdvanced;
|
||||||
def->set_default_value(new ConfigOptionFloat(0.0));
|
def->set_default_value(new ConfigOptionFloat(0.0));
|
||||||
|
|
||||||
def = this->add("ixex_viz_theme", coString);
|
def = this->add("imex_viz_theme", coString);
|
||||||
def->label = L("Visualization Theme");
|
def->label = L("Visualization Theme");
|
||||||
def->tooltip = L("Color theme for iXex bed zone visualization. Choose a colorblind-friendly theme if needed.");
|
def->tooltip = L("Color theme for IDEX/IQEX bed zone visualization. Choose a colorblind-friendly theme if needed.");
|
||||||
def->mode = comAdvanced;
|
def->mode = comAdvanced;
|
||||||
def->set_default_value(new ConfigOptionString("standard"));
|
def->set_default_value(new ConfigOptionString("standard"));
|
||||||
|
|
||||||
def = this->add("ixex_parallel_mode", coString);
|
def = this->add("imex_parallel_mode", coString);
|
||||||
def->label = L("iXex Print Mode");
|
def->label = L("IDEX/IQEX Print Mode");
|
||||||
def->tooltip = L("Name of the active iXex parallel print mode, or \"primary\" for single-carriage printing. Requires iXex Printer enabled in the Printer preset (Printer \u2192 iXex tab).");
|
def->tooltip = L("Name of the active IDEX/IQEX parallel print mode, or \"primary\" for single-carriage printing. Requires IDEX/IQEX Printer enabled in the Printer preset (Printer \u2192 IDEX/IQEX tab).");
|
||||||
def->mode = comAdvanced;
|
def->mode = comAdvanced;
|
||||||
def->set_default_value(new ConfigOptionString("primary"));
|
def->set_default_value(new ConfigOptionString("primary"));
|
||||||
|
|
||||||
def = this->add("ixex_mode_names", coStrings);
|
def = this->add("imex_mode_names", coStrings);
|
||||||
def->label = L("iXex Mode Names");
|
def->label = L("IDEX/IQEX Mode Names");
|
||||||
def->tooltip = L("Display names for each user-defined iXex parallel print mode.");
|
def->tooltip = L("Display names for each user-defined IDEX/IQEX parallel print mode.");
|
||||||
def->mode = comAdvanced;
|
def->mode = comAdvanced;
|
||||||
def->set_default_value(new ConfigOptionStrings());
|
def->set_default_value(new ConfigOptionStrings());
|
||||||
|
|
||||||
def = this->add("ixex_mode_active_tools", coStrings);
|
def = this->add("imex_mode_active_tools", coStrings);
|
||||||
def->label = L("iXex Mode Active Tools");
|
def->label = L("IDEX/IQEX Mode Active Tools");
|
||||||
def->tooltip = L("Tool role assignments for each mode. Format: \"idx:P,idx:C,idx:M\" where P=Primary, C=Copy, M=Mirror (e.g. \"0:P,1:C,2:M,3:M\"). Managed by the iXex Modes editor in the Printer preset.");
|
def->tooltip = L("Tool role assignments for each mode. Format: \"idx:P,idx:C,idx:M\" where P=Primary, C=Copy, M=Mirror (e.g. \"0:P,1:C,2:M,3:M\"). Managed by the IDEX/IQEX Modes editor in the Printer preset.");
|
||||||
def->mode = comAdvanced;
|
def->mode = comAdvanced;
|
||||||
def->set_default_value(new ConfigOptionStrings());
|
def->set_default_value(new ConfigOptionStrings());
|
||||||
|
|
||||||
def = this->add("ixex_mode_gcodes", coStrings);
|
def = this->add("imex_mode_gcodes", coStrings);
|
||||||
def->label = L("iXex Mode G-codes");
|
def->label = L("IDEX/IQEX Mode G-codes");
|
||||||
def->tooltip = L("G-code or macro call to inject at print start for each mode.");
|
def->tooltip = L("G-code or macro call to inject at print start for each mode.");
|
||||||
def->mode = comAdvanced;
|
def->mode = comAdvanced;
|
||||||
def->set_default_value(new ConfigOptionStrings());
|
def->set_default_value(new ConfigOptionStrings());
|
||||||
|
|||||||
@@ -1035,8 +1035,8 @@ PRINT_CONFIG_CLASS_DEFINE(
|
|||||||
// Orca: internal use only
|
// Orca: internal use only
|
||||||
((ConfigOptionBool, calib_flowrate_topinfill_special_order)) // ORCA: special flag for flow rate calibration
|
((ConfigOptionBool, calib_flowrate_topinfill_special_order)) // ORCA: special flag for flow rate calibration
|
||||||
|
|
||||||
// iXex parallel print mode (per-print selection, stores mode name or "primary")
|
// IDEX/IQEX parallel print mode (per-print selection, stores mode name or "primary")
|
||||||
((ConfigOptionString, ixex_parallel_mode))
|
((ConfigOptionString, imex_parallel_mode))
|
||||||
)
|
)
|
||||||
|
|
||||||
// This object is mapped to Perl as Slic3r::Config::PrintRegion.
|
// This object is mapped to Perl as Slic3r::Config::PrintRegion.
|
||||||
@@ -1334,15 +1334,15 @@ PRINT_CONFIG_CLASS_DEFINE(
|
|||||||
((ConfigOptionStrings, filament_start_gcode))
|
((ConfigOptionStrings, filament_start_gcode))
|
||||||
((ConfigOptionBool, single_extruder_multi_material))
|
((ConfigOptionBool, single_extruder_multi_material))
|
||||||
((ConfigOptionBool, manual_filament_change))
|
((ConfigOptionBool, manual_filament_change))
|
||||||
// iXex (independent X extruder) — parallel printing support for IDEX/IQEX printers
|
// IDEX/IQEX (independent X extruder) — parallel printing support for IDEX/IQEX printers
|
||||||
((ConfigOptionBool, is_ixex))
|
((ConfigOptionBool, is_imex))
|
||||||
((ConfigOptionInt, ixex_gantry_count))
|
((ConfigOptionInt, imex_gantry_count))
|
||||||
((ConfigOptionInt, ixex_tools_per_gantry))
|
((ConfigOptionInt, imex_tools_per_gantry))
|
||||||
((ConfigOptionFloat, ixex_nozzle_clearance_x))
|
((ConfigOptionFloat, imex_nozzle_clearance_x))
|
||||||
((ConfigOptionFloat, ixex_nozzle_clearance_y))
|
((ConfigOptionFloat, imex_nozzle_clearance_y))
|
||||||
((ConfigOptionStrings, ixex_mode_names))
|
((ConfigOptionStrings, imex_mode_names))
|
||||||
((ConfigOptionStrings, ixex_mode_active_tools))
|
((ConfigOptionStrings, imex_mode_active_tools))
|
||||||
((ConfigOptionStrings, ixex_mode_gcodes))
|
((ConfigOptionStrings, imex_mode_gcodes))
|
||||||
((ConfigOptionBool, single_extruder_multi_material_priming))
|
((ConfigOptionBool, single_extruder_multi_material_priming))
|
||||||
((ConfigOptionBool, wipe_tower_no_sparse_layers))
|
((ConfigOptionBool, wipe_tower_no_sparse_layers))
|
||||||
((ConfigOptionString, change_filament_gcode))
|
((ConfigOptionString, change_filament_gcode))
|
||||||
|
|||||||
@@ -913,8 +913,8 @@ void GCodeViewer::SequentialView::render(const bool has_render_path, float legen
|
|||||||
// marker.set_world_offset(current_offset);
|
// marker.set_world_offset(current_offset);
|
||||||
marker.render(canvas_width, canvas_height, view_type);
|
marker.render(canvas_width, canvas_height, view_type);
|
||||||
marker.render_position_window(viewer, canvas_width, canvas_height, view_type);
|
marker.render_position_window(viewer, canvas_width, canvas_height, view_type);
|
||||||
// iXex secondary carriage markers
|
// IDEX/IQEX secondary carriage markers
|
||||||
for (auto& sec : m_ixex_secondary_markers)
|
for (auto& sec : m_imex_secondary_markers)
|
||||||
sec.render(canvas_width, canvas_height, view_type);
|
sec.render(canvas_width, canvas_height, view_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1511,7 +1511,7 @@ void GCodeViewer::render(int canvas_width, int canvas_height, int right_margin)
|
|||||||
m_sequential_view.marker.set_world_position(libvgcode::convert(curr_vertex.position));
|
m_sequential_view.marker.set_world_position(libvgcode::convert(curr_vertex.position));
|
||||||
m_sequential_view.marker.set_z_offset(m_z_offset + 0.5f);
|
m_sequential_view.marker.set_z_offset(m_z_offset + 0.5f);
|
||||||
|
|
||||||
// iXex: compute all carriage positions; update secondary nozzle markers;
|
// IDEX/IQEX: compute all carriage positions; update secondary nozzle markers;
|
||||||
// carriage_box_draws is populated for toolhead footprint rendering after sequential_view.render().
|
// carriage_box_draws is populated for toolhead footprint rendering after sequential_view.render().
|
||||||
// Okabe-Ito colorblind-safe palette — excludes orange (#E69F00) and sky blue (#56B4E9)
|
// Okabe-Ito colorblind-safe palette — excludes orange (#E69F00) and sky blue (#56B4E9)
|
||||||
// which are used by the bed zone fills, ensuring the markers contrast against the background.
|
// which are used by the bed zone fills, ensuring the markers contrast against the background.
|
||||||
@@ -1523,41 +1523,41 @@ void GCodeViewer::render(int canvas_width, int canvas_height, int right_margin)
|
|||||||
}};
|
}};
|
||||||
struct CarriageDraw { Vec3f pos; ColorRGBA color; float box_offset_x = 0.0f; float box_offset_y = 0.0f; };
|
struct CarriageDraw { Vec3f pos; ColorRGBA color; float box_offset_x = 0.0f; float box_offset_y = 0.0f; };
|
||||||
std::vector<CarriageDraw> carriage_box_draws;
|
std::vector<CarriageDraw> carriage_box_draws;
|
||||||
float ixex_box_wx = 0.0f, ixex_box_wy = 0.0f;
|
float imex_box_wx = 0.0f, imex_box_wy = 0.0f;
|
||||||
{
|
{
|
||||||
PresetBundle* preset_bundle = wxGetApp().preset_bundle;
|
PresetBundle* preset_bundle = wxGetApp().preset_bundle;
|
||||||
bool ixex_active = false;
|
bool imex_active = false;
|
||||||
if (preset_bundle && m_sequential_view.m_show_marker) {
|
if (preset_bundle && m_sequential_view.m_show_marker) {
|
||||||
const DynamicPrintConfig& printer_cfg = preset_bundle->printers.get_edited_preset().config;
|
const DynamicPrintConfig& printer_cfg = preset_bundle->printers.get_edited_preset().config;
|
||||||
auto* is_ixex_opt = printer_cfg.opt<ConfigOptionBool>("is_ixex");
|
auto* is_imex_opt = printer_cfg.opt<ConfigOptionBool>("is_imex");
|
||||||
if (is_ixex_opt && is_ixex_opt->value) {
|
if (is_imex_opt && is_imex_opt->value) {
|
||||||
const DynamicPrintConfig& process_cfg = preset_bundle->prints.get_edited_preset().config;
|
const DynamicPrintConfig& process_cfg = preset_bundle->prints.get_edited_preset().config;
|
||||||
auto* mode_opt = process_cfg.opt<ConfigOptionString>("ixex_parallel_mode");
|
auto* mode_opt = process_cfg.opt<ConfigOptionString>("imex_parallel_mode");
|
||||||
std::string mode = mode_opt ? mode_opt->value : "primary";
|
std::string mode = mode_opt ? mode_opt->value : "primary";
|
||||||
// Per-plate mode overrides the process preset.
|
// Per-plate mode overrides the process preset.
|
||||||
if (auto* plate = wxGetApp().plater()->get_partplate_list().get_curr_plate()) {
|
if (auto* plate = wxGetApp().plater()->get_partplate_list().get_curr_plate()) {
|
||||||
std::string plate_mode = plate->get_ixex_mode();
|
std::string plate_mode = plate->get_imex_mode();
|
||||||
if (plate_mode != "primary")
|
if (plate_mode != "primary")
|
||||||
mode = plate_mode;
|
mode = plate_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode != m_ixex_last_mode) {
|
if (mode != m_imex_last_mode) {
|
||||||
m_sequential_view.m_ixex_secondary_markers.clear();
|
m_sequential_view.m_imex_secondary_markers.clear();
|
||||||
m_ixex_last_mode = mode;
|
m_imex_last_mode = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mode.empty() && mode != "primary") {
|
if (!mode.empty() && mode != "primary") {
|
||||||
auto* mode_names_opt = printer_cfg.opt<ConfigOptionStrings>("ixex_mode_names");
|
auto* mode_names_opt = printer_cfg.opt<ConfigOptionStrings>("imex_mode_names");
|
||||||
auto* active_tools_opt = printer_cfg.opt<ConfigOptionStrings>("ixex_mode_active_tools");
|
auto* active_tools_opt = printer_cfg.opt<ConfigOptionStrings>("imex_mode_active_tools");
|
||||||
|
|
||||||
auto* tpg_opt = printer_cfg.opt<ConfigOptionInt>("ixex_tools_per_gantry");
|
auto* tpg_opt = printer_cfg.opt<ConfigOptionInt>("imex_tools_per_gantry");
|
||||||
auto* wx_opt = printer_cfg.opt<ConfigOptionFloat>("ixex_nozzle_clearance_x");
|
auto* wx_opt = printer_cfg.opt<ConfigOptionFloat>("imex_nozzle_clearance_x");
|
||||||
auto* wy_opt = printer_cfg.opt<ConfigOptionFloat>("ixex_nozzle_clearance_y");
|
auto* wy_opt = printer_cfg.opt<ConfigOptionFloat>("imex_nozzle_clearance_y");
|
||||||
int tools_per_gantry = tpg_opt ? std::max(1, tpg_opt->value) : 1;
|
int tools_per_gantry = tpg_opt ? std::max(1, tpg_opt->value) : 1;
|
||||||
ixex_box_wx = wx_opt ? (float)wx_opt->value : 30.0f;
|
imex_box_wx = wx_opt ? (float)wx_opt->value : 30.0f;
|
||||||
ixex_box_wy = wy_opt ? (float)wy_opt->value : 30.0f;
|
imex_box_wy = wy_opt ? (float)wy_opt->value : 30.0f;
|
||||||
|
|
||||||
// Parse "idx:P/C/M" format — matches PartPlate::calc_ixex_zones() exactly.
|
// Parse "idx:P/C/M" format — matches PartPlate::calc_imex_zones() exactly.
|
||||||
// Primary = state 1 (P), Copy = 2 (C), Mirror = 3 (M).
|
// Primary = state 1 (P), Copy = 2 (C), Mirror = 3 (M).
|
||||||
// Inactive tools (state 0) are not included in the stored string.
|
// Inactive tools (state 0) are not included in the stored string.
|
||||||
int pri_tool = -1;
|
int pri_tool = -1;
|
||||||
@@ -1594,21 +1594,21 @@ void GCodeViewer::render(int canvas_width, int canvas_height, int right_margin)
|
|||||||
int sec_count = (int)sec_tool_ids.size();
|
int sec_count = (int)sec_tool_ids.size();
|
||||||
|
|
||||||
if (sec_count > 0) {
|
if (sec_count > 0) {
|
||||||
ixex_active = true;
|
imex_active = true;
|
||||||
|
|
||||||
// Lazy init secondary nozzle markers
|
// Lazy init secondary nozzle markers
|
||||||
if ((int)m_sequential_view.m_ixex_secondary_markers.size() != sec_count) {
|
if ((int)m_sequential_view.m_imex_secondary_markers.size() != sec_count) {
|
||||||
m_sequential_view.m_ixex_secondary_markers.resize(sec_count);
|
m_sequential_view.m_imex_secondary_markers.resize(sec_count);
|
||||||
for (int i = 0; i < sec_count; ++i) {
|
for (int i = 0; i < sec_count; ++i) {
|
||||||
m_sequential_view.m_ixex_secondary_markers[i].init(m_marker_filename);
|
m_sequential_view.m_imex_secondary_markers[i].init(m_marker_filename);
|
||||||
m_sequential_view.m_ixex_secondary_markers[i].set_color(
|
m_sequential_view.m_imex_secondary_markers[i].set_color(
|
||||||
s_carriage_colors[(i + 1) % s_carriage_colors.size()]);
|
s_carriage_colors[(i + 1) % s_carriage_colors.size()]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bed X and Y bounds — read from the current plate's shape, which is
|
// Bed X and Y bounds — read from the current plate's shape, which is
|
||||||
// in world/GL coordinates (same space as curr_vertex.position), and is
|
// in world/GL coordinates (same space as curr_vertex.position), and is
|
||||||
// the exact same source used by PartPlate::calc_ixex_zones().
|
// the exact same source used by PartPlate::calc_imex_zones().
|
||||||
float bed_x_min, bed_x_max, bed_y_min, bed_y_max;
|
float bed_x_min, bed_x_max, bed_y_min, bed_y_max;
|
||||||
{
|
{
|
||||||
PartPlate* curr_plate = wxGetApp().plater()->get_partplate_list().get_curr_plate();
|
PartPlate* curr_plate = wxGetApp().plater()->get_partplate_list().get_curr_plate();
|
||||||
@@ -1633,12 +1633,12 @@ void GCodeViewer::render(int canvas_width, int canvas_height, int right_margin)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* gc_opt = printer_cfg.opt<ConfigOptionInt>("ixex_gantry_count");
|
auto* gc_opt = printer_cfg.opt<ConfigOptionInt>("imex_gantry_count");
|
||||||
int gantry_count = gc_opt ? std::max(1, gc_opt->value) : 1;
|
int gantry_count = gc_opt ? std::max(1, gc_opt->value) : 1;
|
||||||
|
|
||||||
// Apply the same flip logic as PartPlate::calc_ixex_zones() so physical
|
// Apply the same flip logic as PartPlate::calc_imex_zones() so physical
|
||||||
// grid positions match the bed zone visualization.
|
// grid positions match the bed zone visualization.
|
||||||
auto* layout_opt = printer_cfg.opt<ConfigOptionString>("ixex_tool_layout");
|
auto* layout_opt = printer_cfg.opt<ConfigOptionString>("imex_tool_layout");
|
||||||
const std::string layout_str = layout_opt ? layout_opt->value : "front-left";
|
const std::string layout_str = layout_opt ? layout_opt->value : "front-left";
|
||||||
const bool flip_x = (layout_str == "front-right" || layout_str == "rear-right");
|
const bool flip_x = (layout_str == "front-right" || layout_str == "rear-right");
|
||||||
const bool flip_y = (layout_str == "rear-left" || layout_str == "rear-right");
|
const bool flip_y = (layout_str == "rear-left" || layout_str == "rear-right");
|
||||||
@@ -1673,15 +1673,15 @@ void GCodeViewer::render(int canvas_width, int canvas_height, int right_margin)
|
|||||||
|
|
||||||
// Primary carriage box: nozzle sits at the collision-side edge.
|
// Primary carriage box: nozzle sits at the collision-side edge.
|
||||||
// Default to centered; override once we know which side the secondaries are on.
|
// Default to centered; override once we know which side the secondaries are on.
|
||||||
float pri_box_offset_x = (pri_phys_col == 0) ? 0.0f : -ixex_box_wx; // nozzle at inner edge (facing center of bed)
|
float pri_box_offset_x = (pri_phys_col == 0) ? 0.0f : -imex_box_wx; // nozzle at inner edge (facing center of bed)
|
||||||
float pri_box_offset_y = -ixex_box_wy; // nozzle at high-Y edge by default (gantry always behind nozzle); override if secondary is behind
|
float pri_box_offset_y = -imex_box_wy; // nozzle at high-Y edge by default (gantry always behind nozzle); override if secondary is behind
|
||||||
for (int i = 0; i < sec_count; ++i) {
|
for (int i = 0; i < sec_count; ++i) {
|
||||||
int sc = phys_col_of(sec_tool_ids[i]);
|
int sc = phys_col_of(sec_tool_ids[i]);
|
||||||
int sr = phys_row_of(sec_tool_ids[i]);
|
int sr = phys_row_of(sec_tool_ids[i]);
|
||||||
if (sc > pri_phys_col) { pri_box_offset_x = 0.0f; }
|
if (sc > pri_phys_col) { pri_box_offset_x = 0.0f; }
|
||||||
else if (sc < pri_phys_col) { pri_box_offset_x = -ixex_box_wx; }
|
else if (sc < pri_phys_col) { pri_box_offset_x = -imex_box_wx; }
|
||||||
if (sr > pri_phys_row) { pri_box_offset_y = 0.0f; }
|
if (sr > pri_phys_row) { pri_box_offset_y = 0.0f; }
|
||||||
else if (sr < pri_phys_row) { pri_box_offset_y = -ixex_box_wy; }
|
else if (sr < pri_phys_row) { pri_box_offset_y = -imex_box_wy; }
|
||||||
}
|
}
|
||||||
carriage_box_draws.push_back({ prim_pos, s_carriage_colors[0], pri_box_offset_x, pri_box_offset_y });
|
carriage_box_draws.push_back({ prim_pos, s_carriage_colors[0], pri_box_offset_x, pri_box_offset_y });
|
||||||
|
|
||||||
@@ -1719,8 +1719,8 @@ void GCodeViewer::render(int canvas_width, int canvas_height, int right_margin)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Vec3f sec_pos{ sec_x, sec_y, prim_pos.z() };
|
Vec3f sec_pos{ sec_x, sec_y, prim_pos.z() };
|
||||||
m_sequential_view.m_ixex_secondary_markers[i].set_world_position(sec_pos);
|
m_sequential_view.m_imex_secondary_markers[i].set_world_position(sec_pos);
|
||||||
m_sequential_view.m_ixex_secondary_markers[i].set_z_offset(m_z_offset + 0.5f);
|
m_sequential_view.m_imex_secondary_markers[i].set_z_offset(m_z_offset + 0.5f);
|
||||||
// X: copy tools move in sync with primary so they share the same
|
// X: copy tools move in sync with primary so they share the same
|
||||||
// X-facing orientation. Mirror tools approach from the opposite side
|
// X-facing orientation. Mirror tools approach from the opposite side
|
||||||
// so the nozzle sits at the collision-side edge.
|
// so the nozzle sits at the collision-side edge.
|
||||||
@@ -1728,16 +1728,16 @@ void GCodeViewer::render(int canvas_width, int canvas_height, int right_margin)
|
|||||||
if (sec_state == 2) {
|
if (sec_state == 2) {
|
||||||
sec_box_offset_x = pri_box_offset_x;
|
sec_box_offset_x = pri_box_offset_x;
|
||||||
} else {
|
} else {
|
||||||
if (sec_phys_col > pri_phys_col) sec_box_offset_x = -ixex_box_wx;
|
if (sec_phys_col > pri_phys_col) sec_box_offset_x = -imex_box_wx;
|
||||||
else if (sec_phys_col < pri_phys_col) sec_box_offset_x = 0.0f;
|
else if (sec_phys_col < pri_phys_col) sec_box_offset_x = 0.0f;
|
||||||
else sec_box_offset_x = pri_box_offset_x;
|
else sec_box_offset_x = pri_box_offset_x;
|
||||||
}
|
}
|
||||||
// Y: always row-based — gantry is always behind nozzle regardless of
|
// Y: always row-based — gantry is always behind nozzle regardless of
|
||||||
// copy/mirror (a back-row copy still has its gantry at the back).
|
// copy/mirror (a back-row copy still has its gantry at the back).
|
||||||
float sec_box_offset_y;
|
float sec_box_offset_y;
|
||||||
if (sec_phys_row > pri_phys_row) sec_box_offset_y = -ixex_box_wy;
|
if (sec_phys_row > pri_phys_row) sec_box_offset_y = -imex_box_wy;
|
||||||
else if (sec_phys_row < pri_phys_row) sec_box_offset_y = 0.0f;
|
else if (sec_phys_row < pri_phys_row) sec_box_offset_y = 0.0f;
|
||||||
else sec_box_offset_y = -ixex_box_wy;
|
else sec_box_offset_y = -imex_box_wy;
|
||||||
carriage_box_draws.push_back({
|
carriage_box_draws.push_back({
|
||||||
sec_pos, s_carriage_colors[(i + 1) % s_carriage_colors.size()],
|
sec_pos, s_carriage_colors[(i + 1) % s_carriage_colors.size()],
|
||||||
sec_box_offset_x, sec_box_offset_y });
|
sec_box_offset_x, sec_box_offset_y });
|
||||||
@@ -1746,28 +1746,28 @@ void GCodeViewer::render(int canvas_width, int canvas_height, int right_margin)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!ixex_active)
|
if (!imex_active)
|
||||||
m_sequential_view.m_ixex_secondary_markers.clear();
|
m_sequential_view.m_imex_secondary_markers.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// BBS fixed buttom margin. m_moves_slider.pos_y
|
// BBS fixed buttom margin. m_moves_slider.pos_y
|
||||||
m_sequential_view.render(!m_no_render_path, legend_height, &m_viewer, m_viewer.get_current_vertex().gcode_id, canvas_width, canvas_height - bottom_margin * m_scale, right_margin * m_scale, m_viewer.get_view_type());
|
m_sequential_view.render(!m_no_render_path, legend_height, &m_viewer, m_viewer.get_current_vertex().gcode_id, canvas_width, canvas_height - bottom_margin * m_scale, right_margin * m_scale, m_viewer.get_view_type());
|
||||||
|
|
||||||
// iXex: render toolhead footprint boxes for each active carriage.
|
// IDEX/IQEX: render toolhead footprint boxes for each active carriage.
|
||||||
// Each box is ixex_nozzle_clearance_x × ixex_nozzle_clearance_y, sitting above the nozzle tip.
|
// Each box is imex_nozzle_clearance_x × imex_nozzle_clearance_y, sitting above the nozzle tip.
|
||||||
if (!carriage_box_draws.empty() && ixex_box_wx > 0.0f && ixex_box_wy > 0.0f) {
|
if (!carriage_box_draws.empty() && imex_box_wx > 0.0f && imex_box_wy > 0.0f) {
|
||||||
// Rebuild box mesh every frame — dimensions can change via config edit without a
|
// Rebuild box mesh every frame — dimensions can change via config edit without a
|
||||||
// G-code reload, so dimension-based caching isn't safe.
|
// G-code reload, so dimension-based caching isn't safe.
|
||||||
// Mesh origin: nozzle at x=0, centered in Y, Z starts at nozzle tip level.
|
// Mesh origin: nozzle at x=0, centered in Y, Z starts at nozzle tip level.
|
||||||
// Per-carriage box_offset_x shifts the mesh left or right so the nozzle lands
|
// Per-carriage box_offset_x shifts the mesh left or right so the nozzle lands
|
||||||
// at the correct (collision-side) edge.
|
// at the correct (collision-side) edge.
|
||||||
{
|
{
|
||||||
const float box_h = std::max(ixex_box_wx, ixex_box_wy);
|
const float box_h = std::max(imex_box_wx, imex_box_wy);
|
||||||
indexed_triangle_set its = its_make_cube((double)ixex_box_wx, (double)ixex_box_wy, (double)box_h);
|
indexed_triangle_set its = its_make_cube((double)imex_box_wx, (double)imex_box_wy, (double)box_h);
|
||||||
// No vertex pre-shifting — box_offset_x/y in the per-carriage transform
|
// No vertex pre-shifting — box_offset_x/y in the per-carriage transform
|
||||||
// positions the nozzle at the correct collision-side edge.
|
// positions the nozzle at the correct collision-side edge.
|
||||||
m_ixex_toolhead_box.reset();
|
m_imex_toolhead_box.reset();
|
||||||
m_ixex_toolhead_box.init_from(its);
|
m_imex_toolhead_box.init_from(its);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
|
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
|
||||||
@@ -1787,8 +1787,8 @@ void GCodeViewer::render(int canvas_width, int canvas_height, int right_margin)
|
|||||||
view_matrix.matrix().block(0, 0, 3, 3) *
|
view_matrix.matrix().block(0, 0, 3, 3) *
|
||||||
model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose();
|
model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose();
|
||||||
shader->set_uniform("view_normal_matrix", view_normal_matrix);
|
shader->set_uniform("view_normal_matrix", view_normal_matrix);
|
||||||
m_ixex_toolhead_box.set_color(draw.color);
|
m_imex_toolhead_box.set_color(draw.color);
|
||||||
m_ixex_toolhead_box.render();
|
m_imex_toolhead_box.render();
|
||||||
}
|
}
|
||||||
shader->stop_using();
|
shader->stop_using();
|
||||||
glsafe(::glDisable(GL_BLEND));
|
glsafe(::glDisable(GL_BLEND));
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
Marker marker;
|
Marker marker;
|
||||||
std::vector<Marker> m_ixex_secondary_markers; // one per active secondary carriage in iXex mode
|
std::vector<Marker> m_imex_secondary_markers; // one per active secondary carriage in IDEX/IQEX mode
|
||||||
GCodeWindow gcode_window;
|
GCodeWindow gcode_window;
|
||||||
float m_scale = 1.0;
|
float m_scale = 1.0;
|
||||||
bool m_show_marker = false;
|
bool m_show_marker = false;
|
||||||
@@ -205,8 +205,8 @@ private:
|
|||||||
ConfigOptionMode m_user_mode;
|
ConfigOptionMode m_user_mode;
|
||||||
bool m_fold = {false};
|
bool m_fold = {false};
|
||||||
std::string m_marker_filename; // cached for lazy secondary marker init
|
std::string m_marker_filename; // cached for lazy secondary marker init
|
||||||
std::string m_ixex_last_mode; // detect mode changes for secondary marker rebuild
|
std::string m_imex_last_mode; // detect mode changes for secondary marker rebuild
|
||||||
GLModel m_ixex_toolhead_box; // shared box mesh for all carriage footprint overlays
|
GLModel m_imex_toolhead_box; // shared box mesh for all carriage footprint overlays
|
||||||
|
|
||||||
size_t m_extruders_count;
|
size_t m_extruders_count;
|
||||||
std::vector<float> m_filament_diameters;
|
std::vector<float> m_filament_diameters;
|
||||||
|
|||||||
@@ -540,13 +540,13 @@ void ArrangeJob::process(Ctl &ctl)
|
|||||||
|
|
||||||
Points bedpts = get_shrink_bedpts(m_plater->config(),params);
|
Points bedpts = get_shrink_bedpts(m_plater->config(),params);
|
||||||
|
|
||||||
// When an iXex parallel mode is active, constrain auto-arrange to the primary zone only
|
// When an IDEX/IQEX parallel mode is active, constrain auto-arrange to the primary zone only
|
||||||
// and treat carriage collision strips as hard excluded regions.
|
// and treat carriage collision strips as hard excluded regions.
|
||||||
// NOTE: m_ixex_primary_zone_box and ixex_collision_zones() are in global (world) coordinates
|
// NOTE: m_imex_primary_zone_box and imex_collision_zones() are in global (world) coordinates
|
||||||
// because they are derived from m_shape which includes the plate origin offset. The arranger
|
// because they are derived from m_shape which includes the plate origin offset. The arranger
|
||||||
// always works in plate-local space (origin = 0,0), so we subtract the plate origin here.
|
// always works in plate-local space (origin = 0,0), so we subtract the plate origin here.
|
||||||
if (PartPlate* curr_plate = partplate_list.get_curr_plate()) {
|
if (PartPlate* curr_plate = partplate_list.get_curr_plate()) {
|
||||||
if (auto pz = curr_plate->ixex_primary_zone()) {
|
if (auto pz = curr_plate->imex_primary_zone()) {
|
||||||
Vec3d plate_origin = curr_plate->get_origin();
|
Vec3d plate_origin = curr_plate->get_origin();
|
||||||
double ox = plate_origin.x(), oy = plate_origin.y();
|
double ox = plate_origin.x(), oy = plate_origin.y();
|
||||||
BoundingBoxf pz_local(Vec2d(pz->min.x() - ox, pz->min.y() - oy),
|
BoundingBoxf pz_local(Vec2d(pz->min.x() - ox, pz->min.y() - oy),
|
||||||
@@ -558,7 +558,7 @@ void ArrangeJob::process(Ctl &ctl)
|
|||||||
{ scaled_pz.max.x(), scaled_pz.max.y() },
|
{ scaled_pz.max.x(), scaled_pz.max.y() },
|
||||||
{ scaled_pz.min.x(), scaled_pz.max.y() },
|
{ scaled_pz.min.x(), scaled_pz.max.y() },
|
||||||
};
|
};
|
||||||
for (const BoundingBoxf3& cz : curr_plate->ixex_collision_zones()) {
|
for (const BoundingBoxf3& cz : curr_plate->imex_collision_zones()) {
|
||||||
Polygon poly({
|
Polygon poly({
|
||||||
{ scaled(cz.min.x() - ox), scaled(cz.min.y() - oy) },
|
{ scaled(cz.min.x() - ox), scaled(cz.min.y() - oy) },
|
||||||
{ scaled(cz.max.x() - ox), scaled(cz.min.y() - oy) },
|
{ scaled(cz.max.x() - ox), scaled(cz.min.y() - oy) },
|
||||||
@@ -572,7 +572,7 @@ void ArrangeJob::process(Ctl &ctl)
|
|||||||
ap.is_virt_object = true;
|
ap.is_virt_object = true;
|
||||||
ap.bed_idx = current_plate_index;
|
ap.bed_idx = current_plate_index;
|
||||||
ap.height = 1;
|
ap.height = 1;
|
||||||
ap.name = "IXexCollisionZone";
|
ap.name = "IMEXCollisionZone";
|
||||||
m_unselected.emplace_back(std::move(ap));
|
m_unselected.emplace_back(std::move(ap));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+109
-109
@@ -365,32 +365,32 @@ std::vector<Vec2d> PartPlate::get_plate_wrapping_detection_area() const
|
|||||||
return std::vector<Vec2d>();
|
return std::vector<Vec2d>();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string PartPlate::get_ixex_mode() const
|
std::string PartPlate::get_imex_mode() const
|
||||||
{
|
{
|
||||||
if (m_config.has("ixex_parallel_mode")) {
|
if (m_config.has("imex_parallel_mode")) {
|
||||||
auto* opt = m_config.option<ConfigOptionString>("ixex_parallel_mode");
|
auto* opt = m_config.option<ConfigOptionString>("imex_parallel_mode");
|
||||||
if (opt && !opt->value.empty())
|
if (opt && !opt->value.empty())
|
||||||
return opt->value;
|
return opt->value;
|
||||||
}
|
}
|
||||||
return "primary";
|
return "primary";
|
||||||
}
|
}
|
||||||
|
|
||||||
void PartPlate::set_ixex_mode(const std::string& mode)
|
void PartPlate::set_imex_mode(const std::string& mode)
|
||||||
{
|
{
|
||||||
if (mode.empty() || mode == "primary") {
|
if (mode.empty() || mode == "primary") {
|
||||||
m_config.erase("ixex_parallel_mode");
|
m_config.erase("imex_parallel_mode");
|
||||||
} else {
|
} else {
|
||||||
m_config.set_key_value("ixex_parallel_mode", new ConfigOptionString(mode));
|
m_config.set_key_value("imex_parallel_mode", new ConfigOptionString(mode));
|
||||||
}
|
}
|
||||||
update_slice_result_valid_state(false);
|
update_slice_result_valid_state(false);
|
||||||
m_ixex_zones_mode_cache = "\x01"; // force zone rebuild
|
m_imex_zones_mode_cache = "\x01"; // force zone rebuild
|
||||||
}
|
}
|
||||||
|
|
||||||
void PartPlate::reset_ixex_mode()
|
void PartPlate::reset_imex_mode()
|
||||||
{
|
{
|
||||||
m_config.erase("ixex_parallel_mode");
|
m_config.erase("imex_parallel_mode");
|
||||||
update_slice_result_valid_state(false);
|
update_slice_result_valid_state(false);
|
||||||
m_ixex_zones_mode_cache = "\x01";
|
m_imex_zones_mode_cache = "\x01";
|
||||||
}
|
}
|
||||||
|
|
||||||
void PartPlate::set_spiral_vase_mode(bool spiral_mode, bool as_global)
|
void PartPlate::set_spiral_vase_mode(bool spiral_mode, bool as_global)
|
||||||
@@ -484,30 +484,30 @@ void PartPlate::calc_exclude_triangles(const ExPolygon &poly)
|
|||||||
// Forward declaration (defined later in this file)
|
// Forward declaration (defined later in this file)
|
||||||
static bool init_model_from_lines(GLModel &model, const Lines &lines, float z);
|
static bool init_model_from_lines(GLModel &model, const Lines &lines, float z);
|
||||||
|
|
||||||
void PartPlate::calc_ixex_zones()
|
void PartPlate::calc_imex_zones()
|
||||||
{
|
{
|
||||||
m_ixex_copy_zones.clear();
|
m_imex_copy_zones.clear();
|
||||||
m_ixex_mirror_zones.clear();
|
m_imex_mirror_zones.clear();
|
||||||
// Clear blocking vectors at the top so early returns don't leave stale data.
|
// Clear blocking vectors at the top so early returns don't leave stale data.
|
||||||
m_ixex_secondary_zone_boxes.clear();
|
m_imex_secondary_zone_boxes.clear();
|
||||||
m_ixex_collision_zones.clear();
|
m_imex_collision_zones.clear();
|
||||||
m_ixex_collision_overlay.clear();
|
m_imex_collision_overlay.clear();
|
||||||
m_ixex_margin_overlay.clear();
|
m_imex_margin_overlay.clear();
|
||||||
m_ixex_primary_zone_box = std::nullopt;
|
m_imex_primary_zone_box = std::nullopt;
|
||||||
|
|
||||||
if (!wxGetApp().preset_bundle)
|
if (!wxGetApp().preset_bundle)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const DynamicPrintConfig& printer_cfg = wxGetApp().preset_bundle->printers.get_edited_preset().config;
|
const DynamicPrintConfig& printer_cfg = wxGetApp().preset_bundle->printers.get_edited_preset().config;
|
||||||
auto* is_ixex_opt = printer_cfg.option<ConfigOptionBool>("is_ixex");
|
auto* is_imex_opt = printer_cfg.option<ConfigOptionBool>("is_imex");
|
||||||
if (!is_ixex_opt || !is_ixex_opt->value)
|
if (!is_imex_opt || !is_imex_opt->value)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Per-plate mode takes priority over the process preset.
|
// Per-plate mode takes priority over the process preset.
|
||||||
std::string active_mode = get_ixex_mode();
|
std::string active_mode = get_imex_mode();
|
||||||
if (active_mode == "primary") {
|
if (active_mode == "primary") {
|
||||||
const DynamicPrintConfig& process_cfg = wxGetApp().preset_bundle->prints.get_edited_preset().config;
|
const DynamicPrintConfig& process_cfg = wxGetApp().preset_bundle->prints.get_edited_preset().config;
|
||||||
auto* mode_opt = process_cfg.option<ConfigOptionString>("ixex_parallel_mode");
|
auto* mode_opt = process_cfg.option<ConfigOptionString>("imex_parallel_mode");
|
||||||
if (mode_opt && !mode_opt->value.empty())
|
if (mode_opt && !mode_opt->value.empty())
|
||||||
active_mode = mode_opt->value;
|
active_mode = mode_opt->value;
|
||||||
}
|
}
|
||||||
@@ -515,9 +515,9 @@ void PartPlate::calc_ixex_zones()
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// Grid dimensions and tool layout from printer config
|
// Grid dimensions and tool layout from printer config
|
||||||
auto* gantry_opt = printer_cfg.option<ConfigOptionInt>("ixex_gantry_count");
|
auto* gantry_opt = printer_cfg.option<ConfigOptionInt>("imex_gantry_count");
|
||||||
auto* tpg_opt = printer_cfg.option<ConfigOptionInt>("ixex_tools_per_gantry");
|
auto* tpg_opt = printer_cfg.option<ConfigOptionInt>("imex_tools_per_gantry");
|
||||||
auto* layout_opt = printer_cfg.option<ConfigOptionString>("ixex_tool_layout");
|
auto* layout_opt = printer_cfg.option<ConfigOptionString>("imex_tool_layout");
|
||||||
|
|
||||||
int n_cols = tpg_opt ? std::max(1, tpg_opt->value) : 2;
|
int n_cols = tpg_opt ? std::max(1, tpg_opt->value) : 2;
|
||||||
int n_rows = gantry_opt ? std::max(1, gantry_opt->value) : 1;
|
int n_rows = gantry_opt ? std::max(1, gantry_opt->value) : 1;
|
||||||
@@ -541,8 +541,8 @@ void PartPlate::calc_ixex_zones()
|
|||||||
return; // nothing to dim with a single zone
|
return; // nothing to dim with a single zone
|
||||||
|
|
||||||
// Look up secondary tool indices (active in mode, but NOT the primary tool)
|
// Look up secondary tool indices (active in mode, but NOT the primary tool)
|
||||||
auto* names_opt = printer_cfg.option<ConfigOptionStrings>("ixex_mode_names");
|
auto* names_opt = printer_cfg.option<ConfigOptionStrings>("imex_mode_names");
|
||||||
auto* tools_opt = printer_cfg.option<ConfigOptionStrings>("ixex_mode_active_tools");
|
auto* tools_opt = printer_cfg.option<ConfigOptionStrings>("imex_mode_active_tools");
|
||||||
std::string active_tools_str;
|
std::string active_tools_str;
|
||||||
if (names_opt && tools_opt) {
|
if (names_opt && tools_opt) {
|
||||||
for (size_t i = 0; i < names_opt->values.size(); ++i) {
|
for (size_t i = 0; i < names_opt->values.size(); ++i) {
|
||||||
@@ -668,18 +668,18 @@ void PartPlate::calc_ixex_zones()
|
|||||||
for (const auto& b : make_boxes(cells))
|
for (const auto& b : make_boxes(cells))
|
||||||
push_zone_fill(vec, b.x0, b.x1, b.y0, b.y1);
|
push_zone_fill(vec, b.x0, b.x1, b.y0, b.y1);
|
||||||
};
|
};
|
||||||
push_expanded_fills(m_ixex_copy_zones, copy_cells);
|
push_expanded_fills(m_imex_copy_zones, copy_cells);
|
||||||
push_expanded_fills(m_ixex_mirror_zones, mirror_cells);
|
push_expanded_fills(m_imex_mirror_zones, mirror_cells);
|
||||||
|
|
||||||
|
|
||||||
// --- Secondary zone blocking ---
|
// --- Secondary zone blocking ---
|
||||||
// Collect the expanded bounding boxes for all secondary (copy+mirror) zones.
|
// Collect the expanded bounding boxes for all secondary (copy+mirror) zones.
|
||||||
// check_outside() uses these to prevent objects being placed outside the primary zone.
|
// check_outside() uses these to prevent objects being placed outside the primary zone.
|
||||||
for (const auto& b : make_boxes(copy_cells))
|
for (const auto& b : make_boxes(copy_cells))
|
||||||
m_ixex_secondary_zone_boxes.push_back(
|
m_imex_secondary_zone_boxes.push_back(
|
||||||
BoundingBoxf3(Vec3d(b.x0, b.y0, -1.0), Vec3d(b.x1, b.y1, 1e4)));
|
BoundingBoxf3(Vec3d(b.x0, b.y0, -1.0), Vec3d(b.x1, b.y1, 1e4)));
|
||||||
for (const auto& b : make_boxes(mirror_cells))
|
for (const auto& b : make_boxes(mirror_cells))
|
||||||
m_ixex_secondary_zone_boxes.push_back(
|
m_imex_secondary_zone_boxes.push_back(
|
||||||
BoundingBoxf3(Vec3d(b.x0, b.y0, -1.0), Vec3d(b.x1, b.y1, 1e4)));
|
BoundingBoxf3(Vec3d(b.x0, b.y0, -1.0), Vec3d(b.x1, b.y1, 1e4)));
|
||||||
|
|
||||||
// --- Carriage collision danger strips ---
|
// --- Carriage collision danger strips ---
|
||||||
@@ -696,9 +696,9 @@ void PartPlate::calc_ixex_zones()
|
|||||||
// !has_row_sep → full bed height; has_row_sep → primary row only
|
// !has_row_sep → full bed height; has_row_sep → primary row only
|
||||||
// !has_col_sep → full bed width; has_col_sep → primary column only
|
// !has_col_sep → full bed width; has_col_sep → primary column only
|
||||||
|
|
||||||
auto* cw_opt = printer_cfg.option<ConfigOptionFloat>("ixex_nozzle_clearance_x");
|
auto* cw_opt = printer_cfg.option<ConfigOptionFloat>("imex_nozzle_clearance_x");
|
||||||
auto* ch_opt = printer_cfg.option<ConfigOptionFloat>("ixex_nozzle_clearance_y");
|
auto* ch_opt = printer_cfg.option<ConfigOptionFloat>("imex_nozzle_clearance_y");
|
||||||
auto* mgn_opt = printer_cfg.option<ConfigOptionFloat>("ixex_carriage_margin");
|
auto* mgn_opt = printer_cfg.option<ConfigOptionFloat>("imex_carriage_margin");
|
||||||
double carriage_w = cw_opt ? cw_opt->value : 0.0;
|
double carriage_w = cw_opt ? cw_opt->value : 0.0;
|
||||||
double carriage_h = ch_opt ? ch_opt->value : 0.0;
|
double carriage_h = ch_opt ? ch_opt->value : 0.0;
|
||||||
double margin = mgn_opt ? mgn_opt->value : 0.0;
|
double margin = mgn_opt ? mgn_opt->value : 0.0;
|
||||||
@@ -714,7 +714,7 @@ void PartPlate::calc_ixex_zones()
|
|||||||
if (!clipped.empty()) {
|
if (!clipped.empty()) {
|
||||||
GLModel m;
|
GLModel m;
|
||||||
if (init_model_from_poly(m, clipped.front(), GROUND_Z))
|
if (init_model_from_poly(m, clipped.front(), GROUND_Z))
|
||||||
m_ixex_margin_overlay.push_back(std::move(m));
|
m_imex_margin_overlay.push_back(std::move(m));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -723,14 +723,14 @@ void PartPlate::calc_ixex_zones()
|
|||||||
double pz_x1 = has_col_sep ? x_min + (pri_col + 1) * zone_w : x_max;
|
double pz_x1 = has_col_sep ? x_min + (pri_col + 1) * zone_w : x_max;
|
||||||
double pz_y0 = has_row_sep ? y_min + pri_row * zone_h : y_min;
|
double pz_y0 = has_row_sep ? y_min + pri_row * zone_h : y_min;
|
||||||
double pz_y1 = has_row_sep ? y_min + (pri_row + 1) * zone_h : y_max;
|
double pz_y1 = has_row_sep ? y_min + (pri_row + 1) * zone_h : y_max;
|
||||||
m_ixex_primary_zone_box = BoundingBoxf(Vec2d(pz_x0, pz_y0), Vec2d(pz_x1, pz_y1));
|
m_imex_primary_zone_box = BoundingBoxf(Vec2d(pz_x0, pz_y0), Vec2d(pz_x1, pz_y1));
|
||||||
|
|
||||||
// Helper: build a BoundingBoxf3 strip, clip to bed, add to members
|
// Helper: build a BoundingBoxf3 strip, clip to bed, add to members
|
||||||
auto add_strip = [&](double sx0, double sx1, double sy0, double sy1) {
|
auto add_strip = [&](double sx0, double sx1, double sy0, double sy1) {
|
||||||
BoundingBoxf3 box;
|
BoundingBoxf3 box;
|
||||||
box.min = Vec3d(sx0, sy0, -1.0);
|
box.min = Vec3d(sx0, sy0, -1.0);
|
||||||
box.max = Vec3d(sx1, sy1, 1e4);
|
box.max = Vec3d(sx1, sy1, 1e4);
|
||||||
m_ixex_collision_zones.push_back(box);
|
m_imex_collision_zones.push_back(box);
|
||||||
|
|
||||||
ExPolygon cell;
|
ExPolygon cell;
|
||||||
cell.contour.append({ scale_(sx0), scale_(sy0) });
|
cell.contour.append({ scale_(sx0), scale_(sy0) });
|
||||||
@@ -741,7 +741,7 @@ void PartPlate::calc_ixex_zones()
|
|||||||
if (!clipped.empty()) {
|
if (!clipped.empty()) {
|
||||||
GLModel m;
|
GLModel m;
|
||||||
if (init_model_from_poly(m, clipped.front(), GROUND_Z))
|
if (init_model_from_poly(m, clipped.front(), GROUND_Z))
|
||||||
m_ixex_collision_overlay.push_back(std::move(m));
|
m_imex_collision_overlay.push_back(std::move(m));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -799,29 +799,29 @@ void PartPlate::calc_ixex_zones()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build a cache key from the current iXex config options, or "" if iXex is off.
|
// Build a cache key from the current IDEX/IQEX config options, or "" if IDEX/IQEX is off.
|
||||||
// Reads per-plate mode from m_config first, falling back to the process preset.
|
// Reads per-plate mode from m_config first, falling back to the process preset.
|
||||||
std::string PartPlate::build_ixex_cache_key() const
|
std::string PartPlate::build_imex_cache_key() const
|
||||||
{
|
{
|
||||||
if (!wxGetApp().preset_bundle)
|
if (!wxGetApp().preset_bundle)
|
||||||
return "";
|
return "";
|
||||||
const DynamicPrintConfig& printer_cfg = wxGetApp().preset_bundle->printers.get_edited_preset().config;
|
const DynamicPrintConfig& printer_cfg = wxGetApp().preset_bundle->printers.get_edited_preset().config;
|
||||||
auto* is_ixex_opt = printer_cfg.option<ConfigOptionBool>("is_ixex");
|
auto* is_imex_opt = printer_cfg.option<ConfigOptionBool>("is_imex");
|
||||||
if (!is_ixex_opt || !is_ixex_opt->value)
|
if (!is_imex_opt || !is_imex_opt->value)
|
||||||
return "";
|
return "";
|
||||||
// Per-plate mode takes priority over process preset.
|
// Per-plate mode takes priority over process preset.
|
||||||
std::string active_mode = get_ixex_mode();
|
std::string active_mode = get_imex_mode();
|
||||||
if (active_mode == "primary") {
|
if (active_mode == "primary") {
|
||||||
const DynamicPrintConfig& process_cfg = wxGetApp().preset_bundle->prints.get_edited_preset().config;
|
const DynamicPrintConfig& process_cfg = wxGetApp().preset_bundle->prints.get_edited_preset().config;
|
||||||
auto* mode_opt = process_cfg.option<ConfigOptionString>("ixex_parallel_mode");
|
auto* mode_opt = process_cfg.option<ConfigOptionString>("imex_parallel_mode");
|
||||||
if (mode_opt && !mode_opt->value.empty())
|
if (mode_opt && !mode_opt->value.empty())
|
||||||
active_mode = mode_opt->value;
|
active_mode = mode_opt->value;
|
||||||
}
|
}
|
||||||
auto* n_col_opt = printer_cfg.option<ConfigOptionInt>("ixex_tools_per_gantry");
|
auto* n_col_opt = printer_cfg.option<ConfigOptionInt>("imex_tools_per_gantry");
|
||||||
auto* n_row_opt = printer_cfg.option<ConfigOptionInt>("ixex_gantry_count");
|
auto* n_row_opt = printer_cfg.option<ConfigOptionInt>("imex_gantry_count");
|
||||||
auto* cw_opt = printer_cfg.option<ConfigOptionFloat>("ixex_nozzle_clearance_x");
|
auto* cw_opt = printer_cfg.option<ConfigOptionFloat>("imex_nozzle_clearance_x");
|
||||||
auto* ch_opt = printer_cfg.option<ConfigOptionFloat>("ixex_nozzle_clearance_y");
|
auto* ch_opt = printer_cfg.option<ConfigOptionFloat>("imex_nozzle_clearance_y");
|
||||||
auto* mgn_opt = printer_cfg.option<ConfigOptionFloat>("ixex_carriage_margin");
|
auto* mgn_opt = printer_cfg.option<ConfigOptionFloat>("imex_carriage_margin");
|
||||||
return active_mode
|
return active_mode
|
||||||
+ "|" + std::to_string(n_col_opt ? n_col_opt->value : 2)
|
+ "|" + std::to_string(n_col_opt ? n_col_opt->value : 2)
|
||||||
+ "x" + std::to_string(n_row_opt ? n_row_opt->value : 1)
|
+ "x" + std::to_string(n_row_opt ? n_row_opt->value : 1)
|
||||||
@@ -832,19 +832,19 @@ std::string PartPlate::build_ixex_cache_key() const
|
|||||||
|
|
||||||
// Ensure zone geometry (secondary boxes, collision strips, visual meshes) is up to date.
|
// Ensure zone geometry (secondary boxes, collision strips, visual meshes) is up to date.
|
||||||
// Called before any collision check AND before rendering so both paths share the same data.
|
// Called before any collision check AND before rendering so both paths share the same data.
|
||||||
void PartPlate::ensure_ixex_zones()
|
void PartPlate::ensure_imex_zones()
|
||||||
{
|
{
|
||||||
std::string cache_key = build_ixex_cache_key();
|
std::string cache_key = build_imex_cache_key();
|
||||||
if (cache_key != m_ixex_zones_mode_cache) {
|
if (cache_key != m_imex_zones_mode_cache) {
|
||||||
m_ixex_zones_mode_cache = cache_key;
|
m_imex_zones_mode_cache = cache_key;
|
||||||
calc_ixex_zones();
|
calc_imex_zones();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PartPlate::has_ixex_placement_violations()
|
bool PartPlate::has_imex_placement_violations()
|
||||||
{
|
{
|
||||||
ensure_ixex_zones();
|
ensure_imex_zones();
|
||||||
if (m_ixex_secondary_zone_boxes.empty() && m_ixex_collision_zones.empty())
|
if (m_imex_secondary_zone_boxes.empty() && m_imex_collision_zones.empty())
|
||||||
return false;
|
return false;
|
||||||
for (const auto& pr : obj_to_instance_set) {
|
for (const auto& pr : obj_to_instance_set) {
|
||||||
int obj_id = pr.first;
|
int obj_id = pr.first;
|
||||||
@@ -855,11 +855,11 @@ bool PartPlate::has_ixex_placement_violations()
|
|||||||
Polygon hull = instance->convex_hull_2d();
|
Polygon hull = instance->convex_hull_2d();
|
||||||
if (hull.points.empty())
|
if (hull.points.empty())
|
||||||
continue;
|
continue;
|
||||||
for (const auto& box : m_ixex_secondary_zone_boxes) {
|
for (const auto& box : m_imex_secondary_zone_boxes) {
|
||||||
if (!intersection({box.polygon(true)}, {hull}).empty())
|
if (!intersection({box.polygon(true)}, {hull}).empty())
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
for (const auto& strip : m_ixex_collision_zones) {
|
for (const auto& strip : m_imex_collision_zones) {
|
||||||
if (!intersection({strip.polygon(true)}, {hull}).empty())
|
if (!intersection({strip.polygon(true)}, {hull}).empty())
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -867,15 +867,15 @@ bool PartPlate::has_ixex_placement_violations()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PartPlate::render_ixex_zones(bool force_default_color)
|
void PartPlate::render_imex_zones(bool force_default_color)
|
||||||
{
|
{
|
||||||
if (force_default_color)
|
if (force_default_color)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ensure_ixex_zones();
|
ensure_imex_zones();
|
||||||
|
|
||||||
// Read visualization theme from printer config.
|
// Read visualization theme from printer config.
|
||||||
struct IXexTheme {
|
struct IMEXTheme {
|
||||||
ColorRGBA copy; // secondary copy zone fill
|
ColorRGBA copy; // secondary copy zone fill
|
||||||
ColorRGBA mirror; // secondary mirror zone fill
|
ColorRGBA mirror; // secondary mirror zone fill
|
||||||
ColorRGBA danger; // blocking collision strip
|
ColorRGBA danger; // blocking collision strip
|
||||||
@@ -883,7 +883,7 @@ void PartPlate::render_ixex_zones(bool force_default_color)
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Standard (Okabe-Ito orange + sky blue)
|
// Standard (Okabe-Ito orange + sky blue)
|
||||||
static const IXexTheme k_standard = {
|
static const IMEXTheme k_standard = {
|
||||||
{ 0.337f, 0.706f, 0.914f, 0.45f }, // copy — sky blue #56B4E9
|
{ 0.337f, 0.706f, 0.914f, 0.45f }, // copy — sky blue #56B4E9
|
||||||
{ 0.902f, 0.624f, 0.000f, 0.45f }, // mirror — orange #E69F00
|
{ 0.902f, 0.624f, 0.000f, 0.45f }, // mirror — orange #E69F00
|
||||||
{ 0.850f, 0.100f, 0.100f, 0.55f }, // danger — red
|
{ 0.850f, 0.100f, 0.100f, 0.55f }, // danger — red
|
||||||
@@ -891,7 +891,7 @@ void PartPlate::render_ixex_zones(bool force_default_color)
|
|||||||
};
|
};
|
||||||
// Deuteranopia / Protanopia: avoids red-green confusion.
|
// Deuteranopia / Protanopia: avoids red-green confusion.
|
||||||
// Danger strip uses strong blue-violet (red invisible to protanopes).
|
// Danger strip uses strong blue-violet (red invisible to protanopes).
|
||||||
static const IXexTheme k_deuteranopia = {
|
static const IMEXTheme k_deuteranopia = {
|
||||||
{ 0.000f, 0.447f, 0.698f, 0.50f }, // copy — blue #0072B2
|
{ 0.000f, 0.447f, 0.698f, 0.50f }, // copy — blue #0072B2
|
||||||
{ 0.941f, 0.894f, 0.259f, 0.50f }, // mirror — yellow #F0E442
|
{ 0.941f, 0.894f, 0.259f, 0.50f }, // mirror — yellow #F0E442
|
||||||
{ 0.200f, 0.100f, 0.800f, 0.65f }, // danger — blue-violet (red not visible)
|
{ 0.200f, 0.100f, 0.800f, 0.65f }, // danger — blue-violet (red not visible)
|
||||||
@@ -899,24 +899,24 @@ void PartPlate::render_ixex_zones(bool force_default_color)
|
|||||||
};
|
};
|
||||||
// Tritanopia: avoids blue-yellow confusion.
|
// Tritanopia: avoids blue-yellow confusion.
|
||||||
// Copy uses vermilion, mirror uses reddish-purple, margin uses teal.
|
// Copy uses vermilion, mirror uses reddish-purple, margin uses teal.
|
||||||
static const IXexTheme k_tritanopia = {
|
static const IMEXTheme k_tritanopia = {
|
||||||
{ 0.835f, 0.369f, 0.000f, 0.50f }, // copy — vermilion #D55E00
|
{ 0.835f, 0.369f, 0.000f, 0.50f }, // copy — vermilion #D55E00
|
||||||
{ 0.800f, 0.475f, 0.655f, 0.50f }, // mirror — reddish purple #CC79A7
|
{ 0.800f, 0.475f, 0.655f, 0.50f }, // mirror — reddish purple #CC79A7
|
||||||
{ 0.850f, 0.100f, 0.100f, 0.55f }, // danger — red (visible to tritanopes)
|
{ 0.850f, 0.100f, 0.100f, 0.55f }, // danger — red (visible to tritanopes)
|
||||||
{ 0.000f, 0.700f, 0.600f, 0.45f }, // margin — teal
|
{ 0.000f, 0.700f, 0.600f, 0.45f }, // margin — teal
|
||||||
};
|
};
|
||||||
// High contrast: saturated, higher alpha for low-vision users.
|
// High contrast: saturated, higher alpha for low-vision users.
|
||||||
static const IXexTheme k_high_contrast = {
|
static const IMEXTheme k_high_contrast = {
|
||||||
{ 0.000f, 0.600f, 1.000f, 0.65f }, // copy — vivid blue
|
{ 0.000f, 0.600f, 1.000f, 0.65f }, // copy — vivid blue
|
||||||
{ 1.000f, 0.600f, 0.000f, 0.65f }, // mirror — vivid orange
|
{ 1.000f, 0.600f, 0.000f, 0.65f }, // mirror — vivid orange
|
||||||
{ 1.000f, 0.000f, 0.000f, 0.75f }, // danger — full red
|
{ 1.000f, 0.000f, 0.000f, 0.75f }, // danger — full red
|
||||||
{ 0.000f, 1.000f, 0.200f, 0.60f }, // margin — bright green
|
{ 0.000f, 1.000f, 0.200f, 0.60f }, // margin — bright green
|
||||||
};
|
};
|
||||||
|
|
||||||
const IXexTheme* theme = &k_standard;
|
const IMEXTheme* theme = &k_standard;
|
||||||
if (wxGetApp().preset_bundle) {
|
if (wxGetApp().preset_bundle) {
|
||||||
const DynamicPrintConfig& pcfg = wxGetApp().preset_bundle->printers.get_edited_preset().config;
|
const DynamicPrintConfig& pcfg = wxGetApp().preset_bundle->printers.get_edited_preset().config;
|
||||||
if (auto* t = pcfg.option<ConfigOptionString>("ixex_viz_theme")) {
|
if (auto* t = pcfg.option<ConfigOptionString>("imex_viz_theme")) {
|
||||||
if (t->value == "deuteranopia") theme = &k_deuteranopia;
|
if (t->value == "deuteranopia") theme = &k_deuteranopia;
|
||||||
else if (t->value == "tritanopia") theme = &k_tritanopia;
|
else if (t->value == "tritanopia") theme = &k_tritanopia;
|
||||||
else if (t->value == "high_contrast") theme = &k_high_contrast;
|
else if (t->value == "high_contrast") theme = &k_high_contrast;
|
||||||
@@ -926,27 +926,27 @@ void PartPlate::render_ixex_zones(bool force_default_color)
|
|||||||
// Both fills and border lines use the flat shader already active from render().
|
// Both fills and border lines use the flat shader already active from render().
|
||||||
glsafe(::glDepthMask(GL_FALSE));
|
glsafe(::glDepthMask(GL_FALSE));
|
||||||
|
|
||||||
if (!m_ixex_copy_zones.empty())
|
if (!m_imex_copy_zones.empty())
|
||||||
for (GLModel& z : m_ixex_copy_zones)
|
for (GLModel& z : m_imex_copy_zones)
|
||||||
if (z.is_initialized()) { z.set_color(theme->copy); z.render(); }
|
if (z.is_initialized()) { z.set_color(theme->copy); z.render(); }
|
||||||
|
|
||||||
if (!m_ixex_mirror_zones.empty())
|
if (!m_imex_mirror_zones.empty())
|
||||||
for (GLModel& z : m_ixex_mirror_zones)
|
for (GLModel& z : m_imex_mirror_zones)
|
||||||
if (z.is_initialized()) { z.set_color(theme->mirror); z.render(); }
|
if (z.is_initialized()) { z.set_color(theme->mirror); z.render(); }
|
||||||
|
|
||||||
glsafe(::glDepthMask(GL_TRUE));
|
glsafe(::glDepthMask(GL_TRUE));
|
||||||
|
|
||||||
|
|
||||||
if (!m_ixex_collision_overlay.empty()) {
|
if (!m_imex_collision_overlay.empty()) {
|
||||||
glsafe(::glDepthMask(GL_FALSE));
|
glsafe(::glDepthMask(GL_FALSE));
|
||||||
for (GLModel& s : m_ixex_collision_overlay)
|
for (GLModel& s : m_imex_collision_overlay)
|
||||||
if (s.is_initialized()) { s.set_color(theme->danger); s.render(); }
|
if (s.is_initialized()) { s.set_color(theme->danger); s.render(); }
|
||||||
glsafe(::glDepthMask(GL_TRUE));
|
glsafe(::glDepthMask(GL_TRUE));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_ixex_margin_overlay.empty()) {
|
if (!m_imex_margin_overlay.empty()) {
|
||||||
glsafe(::glDepthMask(GL_FALSE));
|
glsafe(::glDepthMask(GL_FALSE));
|
||||||
for (GLModel& b : m_ixex_margin_overlay)
|
for (GLModel& b : m_imex_margin_overlay)
|
||||||
if (b.is_initialized()) { b.set_color(theme->margin); b.render(); }
|
if (b.is_initialized()) { b.set_color(theme->margin); b.render(); }
|
||||||
glsafe(::glDepthMask(GL_TRUE));
|
glsafe(::glDepthMask(GL_TRUE));
|
||||||
}
|
}
|
||||||
@@ -1683,17 +1683,17 @@ void PartPlate::render_icons(bool bottom, bool only_name, int hover_id)
|
|||||||
} else
|
} else
|
||||||
render_icon_texture(m_move_front_icon.model, m_partplate_list->m_move_front_texture);
|
render_icon_texture(m_move_front_icon.model, m_partplate_list->m_move_front_texture);
|
||||||
|
|
||||||
// iXex mode icon — only when is_ixex is active
|
// IDEX/IQEX mode icon — only when is_imex is active
|
||||||
{
|
{
|
||||||
PresetBundle* pb = wxGetApp().preset_bundle;
|
PresetBundle* pb = wxGetApp().preset_bundle;
|
||||||
auto* is_ixex_opt = pb ? pb->printers.get_edited_preset().config.option<ConfigOptionBool>("is_ixex") : nullptr;
|
auto* is_imex_opt = pb ? pb->printers.get_edited_preset().config.option<ConfigOptionBool>("is_imex") : nullptr;
|
||||||
if (is_ixex_opt && is_ixex_opt->value) {
|
if (is_imex_opt && is_imex_opt->value) {
|
||||||
if (hover_id == (int)PLATE_IXEX_MODE_ID) {
|
if (hover_id == (int)PLATE_IMEX_MODE_ID) {
|
||||||
render_icon_texture(m_ixex_mode_icon.model, m_partplate_list->m_ixex_mode_hovered_texture);
|
render_icon_texture(m_imex_mode_icon.model, m_partplate_list->m_imex_mode_hovered_texture);
|
||||||
std::string cur = get_ixex_mode();
|
std::string cur = get_imex_mode();
|
||||||
show_tooltip(_u8L("iXex mode: ") + cur + _u8L(" (left-click to cycle, right-click for menu)"));
|
show_tooltip(_u8L("IDEX/IQEX mode: ") + cur + _u8L(" (left-click to cycle, right-click for menu)"));
|
||||||
} else {
|
} else {
|
||||||
render_icon_texture(m_ixex_mode_icon.model, m_partplate_list->m_ixex_mode_texture);
|
render_icon_texture(m_imex_mode_icon.model, m_partplate_list->m_imex_mode_texture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2007,11 +2007,11 @@ void PartPlate::register_raycasters_for_picking(GLCanvas3D &canvas)
|
|||||||
if (dual_bbl)
|
if (dual_bbl)
|
||||||
register_model_for_picking(canvas, m_plate_filament_map_icon, picking_id_component(PLATE_FILAMENT_MAP_ID));
|
register_model_for_picking(canvas, m_plate_filament_map_icon, picking_id_component(PLATE_FILAMENT_MAP_ID));
|
||||||
|
|
||||||
// Register iXex mode icon only when iXex is active on the current printer preset.
|
// Register IDEX/IQEX mode icon only when IDEX/IQEX is active on the current printer preset.
|
||||||
if (preset) {
|
if (preset) {
|
||||||
auto* is_ixex_opt = preset->printers.get_edited_preset().config.option<ConfigOptionBool>("is_ixex");
|
auto* is_imex_opt = preset->printers.get_edited_preset().config.option<ConfigOptionBool>("is_imex");
|
||||||
if (is_ixex_opt && is_ixex_opt->value)
|
if (is_imex_opt && is_imex_opt->value)
|
||||||
register_model_for_picking(canvas, m_ixex_mode_icon, picking_id_component(PLATE_IXEX_MODE_ID));
|
register_model_for_picking(canvas, m_imex_mode_icon, picking_id_component(PLATE_IMEX_MODE_ID));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3024,8 +3024,8 @@ bool PartPlate::contain_instance_totally(int obj_id, int instance_id) const
|
|||||||
//check whether instance is outside the plate or not
|
//check whether instance is outside the plate or not
|
||||||
bool PartPlate::check_outside(int obj_id, int instance_id, BoundingBoxf3* bounding_box)
|
bool PartPlate::check_outside(int obj_id, int instance_id, BoundingBoxf3* bounding_box)
|
||||||
{
|
{
|
||||||
// Ensure iXex zone geometry is current before any placement check.
|
// Ensure IDEX/IQEX zone geometry is current before any placement check.
|
||||||
ensure_ixex_zones();
|
ensure_imex_zones();
|
||||||
|
|
||||||
bool outside = true;
|
bool outside = true;
|
||||||
|
|
||||||
@@ -3070,14 +3070,14 @@ bool PartPlate::check_outside(int obj_id, int instance_id, BoundingBoxf3* boundi
|
|||||||
outside = false;
|
outside = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// iXex placement check (prepare-mode bounding-box test).
|
// IDEX/IQEX placement check (prepare-mode bounding-box test).
|
||||||
// Block objects that overlap secondary (copy/mirror) zones or the carriage
|
// Block objects that overlap secondary (copy/mirror) zones or the carriage
|
||||||
// danger strip at the primary zone boundary. Reuses the existing
|
// danger strip at the primary zone boundary. Reuses the existing
|
||||||
// outside=true → instance_outside_set → update_states() → blocks slicing path.
|
// outside=true → instance_outside_set → update_states() → blocks slicing path.
|
||||||
if (!outside && (!m_ixex_secondary_zone_boxes.empty() || !m_ixex_collision_zones.empty())) {
|
if (!outside && (!m_imex_secondary_zone_boxes.empty() || !m_imex_collision_zones.empty())) {
|
||||||
Polygon obj_hull = instance->convex_hull_2d(); // scaled Clipper coords
|
Polygon obj_hull = instance->convex_hull_2d(); // scaled Clipper coords
|
||||||
// 1. Object must not touch any secondary zone.
|
// 1. Object must not touch any secondary zone.
|
||||||
for (const auto& box : m_ixex_secondary_zone_boxes) {
|
for (const auto& box : m_imex_secondary_zone_boxes) {
|
||||||
Polygon p = box.polygon(true);
|
Polygon p = box.polygon(true);
|
||||||
if (!intersection({ p }, { obj_hull }).empty()) {
|
if (!intersection({ p }, { obj_hull }).empty()) {
|
||||||
outside = true;
|
outside = true;
|
||||||
@@ -3086,7 +3086,7 @@ bool PartPlate::check_outside(int obj_id, int instance_id, BoundingBoxf3* boundi
|
|||||||
}
|
}
|
||||||
// 2. Object must not enter the carriage danger strip inside the primary zone.
|
// 2. Object must not enter the carriage danger strip inside the primary zone.
|
||||||
if (!outside) {
|
if (!outside) {
|
||||||
for (const auto& strip : m_ixex_collision_zones) {
|
for (const auto& strip : m_imex_collision_zones) {
|
||||||
Polygon strip_poly = strip.polygon(true);
|
Polygon strip_poly = strip.polygon(true);
|
||||||
if (!intersection({ strip_poly }, { obj_hull }).empty()) {
|
if (!intersection({ strip_poly }, { obj_hull }).empty()) {
|
||||||
outside = true;
|
outside = true;
|
||||||
@@ -3684,8 +3684,8 @@ bool PartPlate::set_shape(const Pointfs& shape, const Pointfs& exclude_areas, co
|
|||||||
|
|
||||||
const BoundingBox& pp_bbox = poly.contour.bounding_box();
|
const BoundingBox& pp_bbox = poly.contour.bounding_box();
|
||||||
calc_gridlines(poly, pp_bbox);
|
calc_gridlines(poly, pp_bbox);
|
||||||
m_ixex_zones_mode_cache = "\x01"; // force rebuild on next render
|
m_imex_zones_mode_cache = "\x01"; // force rebuild on next render
|
||||||
calc_ixex_zones();
|
calc_imex_zones();
|
||||||
|
|
||||||
calc_vertex_for_icons(0, m_del_icon);
|
calc_vertex_for_icons(0, m_del_icon);
|
||||||
calc_vertex_for_icons(1, m_orient_icon);
|
calc_vertex_for_icons(1, m_orient_icon);
|
||||||
@@ -3699,9 +3699,9 @@ bool PartPlate::set_shape(const Pointfs& shape, const Pointfs& exclude_areas, co
|
|||||||
calc_vertex_for_icons(dual_bbl ? 5 : 6, m_plate_filament_map_icon);
|
calc_vertex_for_icons(dual_bbl ? 5 : 6, m_plate_filament_map_icon);
|
||||||
calc_vertex_for_icons(dual_bbl ? 6 : 5, m_move_front_icon);
|
calc_vertex_for_icons(dual_bbl ? 6 : 5, m_move_front_icon);
|
||||||
{
|
{
|
||||||
auto* is_ixex_opt = preset->printers.get_edited_preset().config.option<ConfigOptionBool>("is_ixex");
|
auto* is_imex_opt = preset->printers.get_edited_preset().config.option<ConfigOptionBool>("is_imex");
|
||||||
if (is_ixex_opt && is_ixex_opt->value)
|
if (is_imex_opt && is_imex_opt->value)
|
||||||
calc_vertex_for_icons(dual_bbl ? 7 : 6, m_ixex_mode_icon);
|
calc_vertex_for_icons(dual_bbl ? 7 : 6, m_imex_mode_icon);
|
||||||
}
|
}
|
||||||
|
|
||||||
calc_vertex_for_number(0, false, m_plate_idx_icon);
|
calc_vertex_for_number(0, false, m_plate_idx_icon);
|
||||||
@@ -3795,7 +3795,7 @@ void PartPlate::render(const Transform3d& view_matrix, const Transform3d& projec
|
|||||||
render_background(force_background_color);
|
render_background(force_background_color);
|
||||||
|
|
||||||
render_exclude_area(force_background_color);
|
render_exclude_area(force_background_color);
|
||||||
render_ixex_zones(force_background_color);
|
render_imex_zones(force_background_color);
|
||||||
if(m_selected && wxGetApp().plater()->get_enable_wrapping_detection()){
|
if(m_selected && wxGetApp().plater()->get_enable_wrapping_detection()){
|
||||||
if(!m_wrapping_detection_triangles.is_initialized()){
|
if(!m_wrapping_detection_triangles.is_initialized()){
|
||||||
auto points = get_plate_wrapping_detection_area();
|
auto points = get_plate_wrapping_detection_area();
|
||||||
@@ -4572,17 +4572,17 @@ void PartPlateList::generate_icon_textures()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// iXex mode icon textures (fall back gracefully if SVG not present yet)
|
// IDEX/IQEX mode icon textures (fall back gracefully if SVG not present yet)
|
||||||
{
|
{
|
||||||
file_name = path + (m_is_dark ? "plate_ixex_mode_dark.svg" : "plate_ixex_mode.svg");
|
file_name = path + (m_is_dark ? "plate_imex_mode_dark.svg" : "plate_imex_mode.svg");
|
||||||
if (!m_ixex_mode_texture.load_from_svg_file(file_name, true, false, false, icon_size)) {
|
if (!m_imex_mode_texture.load_from_svg_file(file_name, true, false, false, icon_size)) {
|
||||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(":load file %1% failed (iXex mode icon)") % file_name;
|
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(":load file %1% failed (IDEX/IQEX mode icon)") % file_name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
file_name = path + (m_is_dark ? "plate_ixex_mode_hover_dark.svg" : "plate_ixex_mode_hover.svg");
|
file_name = path + (m_is_dark ? "plate_imex_mode_hover_dark.svg" : "plate_imex_mode_hover.svg");
|
||||||
if (!m_ixex_mode_hovered_texture.load_from_svg_file(file_name, true, false, false, icon_size)) {
|
if (!m_imex_mode_hovered_texture.load_from_svg_file(file_name, true, false, false, icon_size)) {
|
||||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(":load file %1% failed (iXex mode hover icon)") % file_name;
|
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(":load file %1% failed (IDEX/IQEX mode hover icon)") % file_name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4629,8 +4629,8 @@ void PartPlateList::release_icon_textures()
|
|||||||
m_plate_set_filament_map_hovered_texture.reset();
|
m_plate_set_filament_map_hovered_texture.reset();
|
||||||
m_plate_name_edit_texture.reset();
|
m_plate_name_edit_texture.reset();
|
||||||
m_plate_name_edit_hovered_texture.reset();
|
m_plate_name_edit_hovered_texture.reset();
|
||||||
m_ixex_mode_texture.reset();
|
m_imex_mode_texture.reset();
|
||||||
m_ixex_mode_hovered_texture.reset();
|
m_imex_mode_hovered_texture.reset();
|
||||||
for (int i = 0;i < MAX_PLATE_COUNT; i++) {
|
for (int i = 0;i < MAX_PLATE_COUNT; i++) {
|
||||||
m_idx_textures[i].reset();
|
m_idx_textures[i].reset();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -136,14 +136,14 @@ private:
|
|||||||
GLModel m_logo_triangles;
|
GLModel m_logo_triangles;
|
||||||
GLModel m_gridlines;
|
GLModel m_gridlines;
|
||||||
GLModel m_gridlines_bolder;
|
GLModel m_gridlines_bolder;
|
||||||
std::vector<GLModel> m_ixex_copy_zones; // blue tint (Wong #56B4E9)
|
std::vector<GLModel> m_imex_copy_zones; // blue tint (Wong #56B4E9)
|
||||||
std::vector<GLModel> m_ixex_mirror_zones; // orange tint (Wong #E69F00)
|
std::vector<GLModel> m_imex_mirror_zones; // orange tint (Wong #E69F00)
|
||||||
std::vector<BoundingBoxf3> m_ixex_secondary_zone_boxes; // secondary (copy/mirror) zone rects — objects blocked here
|
std::vector<BoundingBoxf3> m_imex_secondary_zone_boxes; // secondary (copy/mirror) zone rects — objects blocked here
|
||||||
std::vector<BoundingBoxf3> m_ixex_collision_zones; // carriage danger strips inside primary zone (mm)
|
std::vector<BoundingBoxf3> m_imex_collision_zones; // carriage danger strips inside primary zone (mm)
|
||||||
std::vector<GLModel> m_ixex_collision_overlay; // red-orange rendered fill for danger strips
|
std::vector<GLModel> m_imex_collision_overlay; // red-orange rendered fill for danger strips
|
||||||
std::vector<GLModel> m_ixex_margin_overlay; // amber advisory bands just inside collision strips
|
std::vector<GLModel> m_imex_margin_overlay; // amber advisory bands just inside collision strips
|
||||||
std::optional<BoundingBoxf> m_ixex_primary_zone_box; // primary zone extents in mm; empty when iXex is off/primary-only
|
std::optional<BoundingBoxf> m_imex_primary_zone_box; // primary zone extents in mm; empty when IDEX/IQEX is off/primary-only
|
||||||
std::string m_ixex_zones_mode_cache{ "\x01" }; // cached mode+topology key; sentinel = unbuilt
|
std::string m_imex_zones_mode_cache{ "\x01" }; // cached mode+topology key; sentinel = unbuilt
|
||||||
GLModel m_height_limit_common;
|
GLModel m_height_limit_common;
|
||||||
GLModel m_height_limit_bottom;
|
GLModel m_height_limit_bottom;
|
||||||
GLModel m_height_limit_top;
|
GLModel m_height_limit_top;
|
||||||
@@ -155,7 +155,7 @@ private:
|
|||||||
PickingModel m_plate_filament_map_icon;
|
PickingModel m_plate_filament_map_icon;
|
||||||
PickingModel m_plate_name_edit_icon;
|
PickingModel m_plate_name_edit_icon;
|
||||||
PickingModel m_move_front_icon;
|
PickingModel m_move_front_icon;
|
||||||
PickingModel m_ixex_mode_icon;
|
PickingModel m_imex_mode_icon;
|
||||||
GLModel m_plate_idx_icon;
|
GLModel m_plate_idx_icon;
|
||||||
GLTexture m_texture;
|
GLTexture m_texture;
|
||||||
|
|
||||||
@@ -187,10 +187,10 @@ private:
|
|||||||
void calc_triangles_from_polygon(const ExPolygon &poly, GLModel& render_model);
|
void calc_triangles_from_polygon(const ExPolygon &poly, GLModel& render_model);
|
||||||
void calc_gridlines(const ExPolygon& poly, const BoundingBox& pp_bbox);
|
void calc_gridlines(const ExPolygon& poly, const BoundingBox& pp_bbox);
|
||||||
void calc_height_limit();
|
void calc_height_limit();
|
||||||
void calc_ixex_zones();
|
void calc_imex_zones();
|
||||||
void ensure_ixex_zones();
|
void ensure_imex_zones();
|
||||||
std::string build_ixex_cache_key() const;
|
std::string build_imex_cache_key() const;
|
||||||
void render_ixex_zones(bool force_default_color);
|
void render_imex_zones(bool force_default_color);
|
||||||
void calc_vertex_for_number(int index, bool one_number, GLModel &buffer);
|
void calc_vertex_for_number(int index, bool one_number, GLModel &buffer);
|
||||||
void calc_vertex_for_plate_name_edit_icon(GLTexture *texture, int index, PickingModel &model);
|
void calc_vertex_for_plate_name_edit_icon(GLTexture *texture, int index, PickingModel &model);
|
||||||
void calc_vertex_for_icons(int index, PickingModel &model);
|
void calc_vertex_for_icons(int index, PickingModel &model);
|
||||||
@@ -222,7 +222,7 @@ private:
|
|||||||
public:
|
public:
|
||||||
static constexpr unsigned int PLATE_NAME_HOVER_ID = 6;
|
static constexpr unsigned int PLATE_NAME_HOVER_ID = 6;
|
||||||
static constexpr unsigned int PLATE_FILAMENT_MAP_ID = 8;
|
static constexpr unsigned int PLATE_FILAMENT_MAP_ID = 8;
|
||||||
static constexpr unsigned int PLATE_IXEX_MODE_ID = 9;
|
static constexpr unsigned int PLATE_IMEX_MODE_ID = 9;
|
||||||
static constexpr unsigned int GRABBER_COUNT = 10;
|
static constexpr unsigned int GRABBER_COUNT = 10;
|
||||||
|
|
||||||
static ColorRGBA SELECT_COLOR;
|
static ColorRGBA SELECT_COLOR;
|
||||||
@@ -283,9 +283,9 @@ public:
|
|||||||
bool get_spiral_vase_mode() const;
|
bool get_spiral_vase_mode() const;
|
||||||
void set_spiral_vase_mode(bool spiral_mode, bool as_global);
|
void set_spiral_vase_mode(bool spiral_mode, bool as_global);
|
||||||
|
|
||||||
std::string get_ixex_mode() const;
|
std::string get_imex_mode() const;
|
||||||
void set_ixex_mode(const std::string& mode);
|
void set_imex_mode(const std::string& mode);
|
||||||
void reset_ixex_mode();
|
void reset_imex_mode();
|
||||||
|
|
||||||
std::vector<Vec2d> get_plate_wrapping_detection_area() const;
|
std::vector<Vec2d> get_plate_wrapping_detection_area() const;
|
||||||
|
|
||||||
@@ -451,14 +451,14 @@ public:
|
|||||||
{
|
{
|
||||||
return m_ready_for_slice && !m_apply_invalid;
|
return m_ready_for_slice && !m_apply_invalid;
|
||||||
}
|
}
|
||||||
// Returns true if any instance on this plate overlaps an iXex secondary or collision zone.
|
// Returns true if any instance on this plate overlaps an IDEX/IQEX secondary or collision zone.
|
||||||
bool has_ixex_placement_violations();
|
bool has_imex_placement_violations();
|
||||||
// Returns the primary-zone bounding box in mm when an iXex parallel mode is active.
|
// Returns the primary-zone bounding box in mm when an IDEX/IQEX parallel mode is active.
|
||||||
// Empty (nullopt) when iXex is off or the mode is "primary" (full-bed).
|
// Empty (nullopt) when IDEX/IQEX is off or the mode is "primary" (full-bed).
|
||||||
std::optional<BoundingBoxf> ixex_primary_zone() { ensure_ixex_zones(); return m_ixex_primary_zone_box; }
|
std::optional<BoundingBoxf> imex_primary_zone() { ensure_imex_zones(); return m_imex_primary_zone_box; }
|
||||||
// Returns carriage collision strips (mm) for the current iXex mode.
|
// Returns carriage collision strips (mm) for the current IDEX/IQEX mode.
|
||||||
// Always call ixex_primary_zone() first to ensure the cache is warm.
|
// Always call imex_primary_zone() first to ensure the cache is warm.
|
||||||
const std::vector<BoundingBoxf3>& ixex_collision_zones() const { return m_ixex_collision_zones; }
|
const std::vector<BoundingBoxf3>& imex_collision_zones() const { return m_imex_collision_zones; }
|
||||||
void update_slice_ready_status(bool ready_slice)
|
void update_slice_ready_status(bool ready_slice)
|
||||||
{
|
{
|
||||||
m_ready_for_slice = ready_slice;
|
m_ready_for_slice = ready_slice;
|
||||||
@@ -634,8 +634,8 @@ class PartPlateList : public ObjectBase
|
|||||||
GLTexture m_plate_set_filament_map_hovered_texture;
|
GLTexture m_plate_set_filament_map_hovered_texture;
|
||||||
GLTexture m_plate_name_edit_texture;
|
GLTexture m_plate_name_edit_texture;
|
||||||
GLTexture m_plate_name_edit_hovered_texture;
|
GLTexture m_plate_name_edit_hovered_texture;
|
||||||
GLTexture m_ixex_mode_texture;
|
GLTexture m_imex_mode_texture;
|
||||||
GLTexture m_ixex_mode_hovered_texture;
|
GLTexture m_imex_mode_hovered_texture;
|
||||||
GLTexture m_idx_textures[MAX_PLATE_COUNT];
|
GLTexture m_idx_textures[MAX_PLATE_COUNT];
|
||||||
// set render option
|
// set render option
|
||||||
bool render_bedtype_logo = true;
|
bool render_bedtype_logo = true;
|
||||||
|
|||||||
+12
-12
@@ -7722,13 +7722,13 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool
|
|||||||
q->post_process_string_object_exception(err);
|
q->post_process_string_object_exception(err);
|
||||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": validate err=%1%, warning=%2%")%err.string%warning.string;
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": validate err=%1%, warning=%2%")%err.string%warning.string;
|
||||||
|
|
||||||
// iXex placement check: if objects overlap secondary zones, treat it as a
|
// IDEX/IQEX placement check: if objects overlap secondary zones, treat it as a
|
||||||
// validation error so the standard pathway handles button state, notifications,
|
// validation error so the standard pathway handles button state, notifications,
|
||||||
// and auto-slice blocking consistently.
|
// and auto-slice blocking consistently.
|
||||||
if (err.string.empty()) {
|
if (err.string.empty()) {
|
||||||
PartPlate* ixex_plate = partplate_list.get_curr_plate();
|
PartPlate* imex_plate = partplate_list.get_curr_plate();
|
||||||
if (ixex_plate && ixex_plate->has_ixex_placement_violations())
|
if (imex_plate && imex_plate->has_imex_placement_violations())
|
||||||
err.string = _u8L("Cannot slice: objects are in secondary zones reserved for iXex parallel printing.");
|
err.string = _u8L("Cannot slice: objects are in secondary zones reserved for IDEX/IQEX parallel printing.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (err.string.empty()) {
|
if (err.string.empty()) {
|
||||||
@@ -17640,7 +17640,7 @@ int Plater::select_plate_by_hover_id(int hover_id, bool right_click, bool isModi
|
|||||||
update();
|
update();
|
||||||
p->partplate_list.select_plate(0);
|
p->partplate_list.select_plate(0);
|
||||||
}
|
}
|
||||||
else if (action == (int)PartPlate::PLATE_IXEX_MODE_ID)
|
else if (action == (int)PartPlate::PLATE_IMEX_MODE_ID)
|
||||||
{
|
{
|
||||||
ret = select_plate(plate_index);
|
ret = select_plate(plate_index);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
@@ -17649,7 +17649,7 @@ int Plater::select_plate_by_hover_id(int hover_id, bool right_click, bool isModi
|
|||||||
std::vector<std::string> modes;
|
std::vector<std::string> modes;
|
||||||
modes.push_back("primary");
|
modes.push_back("primary");
|
||||||
const DynamicPrintConfig& printer_cfg = wxGetApp().preset_bundle->printers.get_edited_preset().config;
|
const DynamicPrintConfig& printer_cfg = wxGetApp().preset_bundle->printers.get_edited_preset().config;
|
||||||
auto* names_opt = printer_cfg.option<ConfigOptionStrings>("ixex_mode_names");
|
auto* names_opt = printer_cfg.option<ConfigOptionStrings>("imex_mode_names");
|
||||||
if (names_opt) {
|
if (names_opt) {
|
||||||
for (const auto& n : names_opt->values)
|
for (const auto& n : names_opt->values)
|
||||||
if (!n.empty()) modes.push_back(n);
|
if (!n.empty()) modes.push_back(n);
|
||||||
@@ -17658,7 +17658,7 @@ int Plater::select_plate_by_hover_id(int hover_id, bool right_click, bool isModi
|
|||||||
if (right_click) {
|
if (right_click) {
|
||||||
// Show a popup menu with all modes.
|
// Show a popup menu with all modes.
|
||||||
wxMenu menu;
|
wxMenu menu;
|
||||||
std::string current = curr_plate->get_ixex_mode();
|
std::string current = curr_plate->get_imex_mode();
|
||||||
for (size_t i = 0; i < modes.size(); ++i) {
|
for (size_t i = 0; i < modes.size(); ++i) {
|
||||||
wxMenuItem* item = menu.AppendRadioItem(wxID_HIGHEST + (int)i, from_u8(modes[i]));
|
wxMenuItem* item = menu.AppendRadioItem(wxID_HIGHEST + (int)i, from_u8(modes[i]));
|
||||||
if (modes[i] == current)
|
if (modes[i] == current)
|
||||||
@@ -17667,8 +17667,8 @@ int Plater::select_plate_by_hover_id(int hover_id, bool right_click, bool isModi
|
|||||||
menu.Bind(wxEVT_MENU, [this, curr_plate, &modes](wxCommandEvent& e) {
|
menu.Bind(wxEVT_MENU, [this, curr_plate, &modes](wxCommandEvent& e) {
|
||||||
int idx = e.GetId() - wxID_HIGHEST;
|
int idx = e.GetId() - wxID_HIGHEST;
|
||||||
if (idx >= 0 && idx < (int)modes.size()) {
|
if (idx >= 0 && idx < (int)modes.size()) {
|
||||||
take_snapshot("set ixex mode");
|
take_snapshot("set imex mode");
|
||||||
curr_plate->set_ixex_mode(modes[idx]);
|
curr_plate->set_imex_mode(modes[idx]);
|
||||||
update_project_dirty_from_presets();
|
update_project_dirty_from_presets();
|
||||||
set_plater_dirty(true);
|
set_plater_dirty(true);
|
||||||
update();
|
update();
|
||||||
@@ -17678,13 +17678,13 @@ int Plater::select_plate_by_hover_id(int hover_id, bool right_click, bool isModi
|
|||||||
ret = 1; // signal to caller: popup was shown, suppress plate context menu
|
ret = 1; // signal to caller: popup was shown, suppress plate context menu
|
||||||
} else {
|
} else {
|
||||||
// Left-click: cycle to next mode.
|
// Left-click: cycle to next mode.
|
||||||
std::string current = curr_plate->get_ixex_mode();
|
std::string current = curr_plate->get_imex_mode();
|
||||||
auto it = std::find(modes.begin(), modes.end(), current);
|
auto it = std::find(modes.begin(), modes.end(), current);
|
||||||
size_t next_idx = (it == modes.end()) ? 0 : ((it - modes.begin() + 1) % modes.size());
|
size_t next_idx = (it == modes.end()) ? 0 : ((it - modes.begin() + 1) % modes.size());
|
||||||
std::string next_mode = modes[next_idx];
|
std::string next_mode = modes[next_idx];
|
||||||
if (next_mode != current) {
|
if (next_mode != current) {
|
||||||
take_snapshot("set ixex mode");
|
take_snapshot("set imex mode");
|
||||||
curr_plate->set_ixex_mode(next_mode);
|
curr_plate->set_imex_mode(next_mode);
|
||||||
update_project_dirty_from_presets();
|
update_project_dirty_from_presets();
|
||||||
set_plater_dirty(true);
|
set_plater_dirty(true);
|
||||||
update();
|
update();
|
||||||
|
|||||||
+72
-72
@@ -4338,7 +4338,7 @@ void TabPrinter::build()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// IXexModesCtrl — visual parallel-mode editor for the iXex printer tab
|
// IMEXModesCtrl — visual parallel-mode editor for the IDEX/IQEX printer tab
|
||||||
//
|
//
|
||||||
// Tool button states:
|
// Tool button states:
|
||||||
// 0 = Inactive (grey) — not participating in this mode
|
// 0 = Inactive (grey) — not participating in this mode
|
||||||
@@ -4348,7 +4348,7 @@ void TabPrinter::build()
|
|||||||
//
|
//
|
||||||
// Active-tools string format: "idx:P,idx:C,idx:M" (backwards-compat: plain "idx" = Primary)
|
// Active-tools string format: "idx:P,idx:C,idx:M" (backwards-compat: plain "idx" = Primary)
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
class IXexModesCtrl : public wxPanel {
|
class IMEXModesCtrl : public wxPanel {
|
||||||
public:
|
public:
|
||||||
std::function<void()> on_change;
|
std::function<void()> on_change;
|
||||||
|
|
||||||
@@ -4360,7 +4360,7 @@ public:
|
|||||||
return 0; // "front-left" default
|
return 0; // "front-left" default
|
||||||
}
|
}
|
||||||
|
|
||||||
IXexModesCtrl(wxWindow* parent, int n_cols, int n_rows, int layout = 0)
|
IMEXModesCtrl(wxWindow* parent, int n_cols, int n_rows, int layout = 0)
|
||||||
: wxPanel(parent, wxID_ANY), m_n_cols(std::max(1, n_cols)), m_n_rows(std::max(1, n_rows)), m_layout(layout)
|
: wxPanel(parent, wxID_ANY), m_n_cols(std::max(1, n_cols)), m_n_rows(std::max(1, n_rows)), m_layout(layout)
|
||||||
{
|
{
|
||||||
m_outer = new wxBoxSizer(wxVERTICAL);
|
m_outer = new wxBoxSizer(wxVERTICAL);
|
||||||
@@ -4437,9 +4437,9 @@ public:
|
|||||||
|
|
||||||
void load_from_config(const DynamicPrintConfig& cfg) {
|
void load_from_config(const DynamicPrintConfig& cfg) {
|
||||||
clear_rows();
|
clear_rows();
|
||||||
auto* names = cfg.option<ConfigOptionStrings>("ixex_mode_names");
|
auto* names = cfg.option<ConfigOptionStrings>("imex_mode_names");
|
||||||
auto* tools = cfg.option<ConfigOptionStrings>("ixex_mode_active_tools");
|
auto* tools = cfg.option<ConfigOptionStrings>("imex_mode_active_tools");
|
||||||
auto* gcodes = cfg.option<ConfigOptionStrings>("ixex_mode_gcodes");
|
auto* gcodes = cfg.option<ConfigOptionStrings>("imex_mode_gcodes");
|
||||||
size_t n = names ? names->values.size() : 0;
|
size_t n = names ? names->values.size() : 0;
|
||||||
for (size_t i = 0; i < n; ++i)
|
for (size_t i = 0; i < n; ++i)
|
||||||
add_row(names->values[i],
|
add_row(names->values[i],
|
||||||
@@ -4931,14 +4931,14 @@ void TabPrinter::build_fff()
|
|||||||
option.opt.height = gcode_field_height;//150;
|
option.opt.height = gcode_field_height;//150;
|
||||||
optgroup->append_single_option_line(option, "printer_machine_gcode#template-custom-g-code");
|
optgroup->append_single_option_line(option, "printer_machine_gcode#template-custom-g-code");
|
||||||
|
|
||||||
page = add_options_page(L("iXex"), "custom-gcode_multi_material"); // ORCA: icon only visible on placeholders
|
page = add_options_page(L("IDEX/IQEX"), "custom-gcode_multi_material"); // ORCA: icon only visible on placeholders
|
||||||
optgroup = page->new_optgroup(L("Carriage Configuration"), L"param_advanced");
|
optgroup = page->new_optgroup(L("Carriage Configuration"), L"param_advanced");
|
||||||
optgroup->append_single_option_line("is_ixex");
|
optgroup->append_single_option_line("is_imex");
|
||||||
optgroup->append_single_option_line("ixex_gantry_count");
|
optgroup->append_single_option_line("imex_gantry_count");
|
||||||
optgroup->append_single_option_line("ixex_tools_per_gantry");
|
optgroup->append_single_option_line("imex_tools_per_gantry");
|
||||||
{
|
{
|
||||||
// Tool 0 corner selector
|
// Tool 0 corner selector
|
||||||
auto opt = optgroup->get_option("ixex_tool_layout");
|
auto opt = optgroup->get_option("imex_tool_layout");
|
||||||
auto line = Line{ opt.opt.label, opt.opt.tooltip };
|
auto line = Line{ opt.opt.label, opt.opt.tooltip };
|
||||||
line.append_option(opt);
|
line.append_option(opt);
|
||||||
line.widget = [this](wxWindow* parent) -> wxSizer* {
|
line.widget = [this](wxWindow* parent) -> wxSizer* {
|
||||||
@@ -4947,37 +4947,37 @@ void TabPrinter::build_fff()
|
|||||||
_L("Rear-left"), _L("Rear-right")
|
_L("Rear-left"), _L("Rear-right")
|
||||||
};
|
};
|
||||||
static const char* values[] = { "front-left", "front-right", "rear-left", "rear-right" };
|
static const char* values[] = { "front-left", "front-right", "rear-left", "rear-right" };
|
||||||
m_ixex_layout_combo = new ComboBox(parent, wxID_ANY, wxEmptyString,
|
m_imex_layout_combo = new ComboBox(parent, wxID_ANY, wxEmptyString,
|
||||||
wxDefaultPosition,
|
wxDefaultPosition,
|
||||||
wxSize(12 * wxGetApp().em_unit(), -1),
|
wxSize(12 * wxGetApp().em_unit(), -1),
|
||||||
4, choices, wxCB_READONLY);
|
4, choices, wxCB_READONLY);
|
||||||
m_ixex_layout_combo->GetDropDown().SetUseContentWidth(true);
|
m_imex_layout_combo->GetDropDown().SetUseContentWidth(true);
|
||||||
// Set current selection
|
// Set current selection
|
||||||
std::string cur = "front-left";
|
std::string cur = "front-left";
|
||||||
if (auto* o = m_config->option<ConfigOptionString>("ixex_tool_layout")) cur = o->value;
|
if (auto* o = m_config->option<ConfigOptionString>("imex_tool_layout")) cur = o->value;
|
||||||
for (int i = 0; i < 4; ++i)
|
for (int i = 0; i < 4; ++i)
|
||||||
if (cur == values[i]) { m_ixex_layout_combo->SetSelection(i); break; }
|
if (cur == values[i]) { m_imex_layout_combo->SetSelection(i); break; }
|
||||||
m_ixex_layout_combo->Bind(wxEVT_COMBOBOX, [this](wxCommandEvent&) {
|
m_imex_layout_combo->Bind(wxEVT_COMBOBOX, [this](wxCommandEvent&) {
|
||||||
static const char* layout_vals[] = { "front-left", "front-right", "rear-left", "rear-right" };
|
static const char* layout_vals[] = { "front-left", "front-right", "rear-left", "rear-right" };
|
||||||
int sel = m_ixex_layout_combo->GetSelection();
|
int sel = m_imex_layout_combo->GetSelection();
|
||||||
std::string val = (sel >= 0 && sel < 4) ? layout_vals[sel] : "front-left";
|
std::string val = (sel >= 0 && sel < 4) ? layout_vals[sel] : "front-left";
|
||||||
m_config->set_key_value("ixex_tool_layout", new ConfigOptionString(val));
|
m_config->set_key_value("imex_tool_layout", new ConfigOptionString(val));
|
||||||
on_value_change("ixex_tool_layout", val);
|
on_value_change("imex_tool_layout", val);
|
||||||
if (m_ixex_modes_ctrl)
|
if (m_imex_modes_ctrl)
|
||||||
m_ixex_modes_ctrl->set_grid_size(
|
m_imex_modes_ctrl->set_grid_size(
|
||||||
m_config->opt_int("ixex_tools_per_gantry"),
|
m_config->opt_int("imex_tools_per_gantry"),
|
||||||
m_config->opt_int("ixex_gantry_count"),
|
m_config->opt_int("imex_gantry_count"),
|
||||||
IXexModesCtrl::parse_layout(val));
|
IMEXModesCtrl::parse_layout(val));
|
||||||
});
|
});
|
||||||
auto* s = new wxBoxSizer(wxHORIZONTAL);
|
auto* s = new wxBoxSizer(wxHORIZONTAL);
|
||||||
s->Add(m_ixex_layout_combo, 0, wxALIGN_CENTER_VERTICAL);
|
s->Add(m_imex_layout_combo, 0, wxALIGN_CENTER_VERTICAL);
|
||||||
return s;
|
return s;
|
||||||
};
|
};
|
||||||
optgroup->append_line(line);
|
optgroup->append_line(line);
|
||||||
}
|
}
|
||||||
optgroup->append_single_option_line("ixex_nozzle_clearance_x");
|
optgroup->append_single_option_line("imex_nozzle_clearance_x");
|
||||||
optgroup->append_single_option_line("ixex_nozzle_clearance_y");
|
optgroup->append_single_option_line("imex_nozzle_clearance_y");
|
||||||
optgroup->append_single_option_line("ixex_carriage_margin");
|
optgroup->append_single_option_line("imex_carriage_margin");
|
||||||
|
|
||||||
{
|
{
|
||||||
static const wxString theme_choices[] = {
|
static const wxString theme_choices[] = {
|
||||||
@@ -4986,27 +4986,27 @@ void TabPrinter::build_fff()
|
|||||||
_L("Tritanopia (blue-yellow)"),
|
_L("Tritanopia (blue-yellow)"),
|
||||||
_L("High Contrast") };
|
_L("High Contrast") };
|
||||||
static const char* theme_vals[] = { "standard", "deuteranopia", "tritanopia", "high_contrast" };
|
static const char* theme_vals[] = { "standard", "deuteranopia", "tritanopia", "high_contrast" };
|
||||||
auto opt = optgroup->get_option("ixex_viz_theme");
|
auto opt = optgroup->get_option("imex_viz_theme");
|
||||||
auto line = Line{ opt.opt.label, opt.opt.tooltip };
|
auto line = Line{ opt.opt.label, opt.opt.tooltip };
|
||||||
line.append_option(opt);
|
line.append_option(opt);
|
||||||
line.widget = [this](wxWindow* parent) -> wxSizer* {
|
line.widget = [this](wxWindow* parent) -> wxSizer* {
|
||||||
m_ixex_theme_combo = new ComboBox(parent, wxID_ANY, wxEmptyString,
|
m_imex_theme_combo = new ComboBox(parent, wxID_ANY, wxEmptyString,
|
||||||
wxDefaultPosition,
|
wxDefaultPosition,
|
||||||
wxSize(22 * wxGetApp().em_unit(), -1),
|
wxSize(22 * wxGetApp().em_unit(), -1),
|
||||||
4, theme_choices, wxCB_READONLY);
|
4, theme_choices, wxCB_READONLY);
|
||||||
m_ixex_theme_combo->GetDropDown().SetUseContentWidth(true);
|
m_imex_theme_combo->GetDropDown().SetUseContentWidth(true);
|
||||||
std::string cur = "standard";
|
std::string cur = "standard";
|
||||||
if (auto* o = m_config->option<ConfigOptionString>("ixex_viz_theme")) cur = o->value;
|
if (auto* o = m_config->option<ConfigOptionString>("imex_viz_theme")) cur = o->value;
|
||||||
for (int i = 0; i < 4; ++i)
|
for (int i = 0; i < 4; ++i)
|
||||||
if (cur == theme_vals[i]) { m_ixex_theme_combo->SetSelection(i); break; }
|
if (cur == theme_vals[i]) { m_imex_theme_combo->SetSelection(i); break; }
|
||||||
m_ixex_theme_combo->Bind(wxEVT_COMBOBOX, [this](wxCommandEvent&) {
|
m_imex_theme_combo->Bind(wxEVT_COMBOBOX, [this](wxCommandEvent&) {
|
||||||
int sel = m_ixex_theme_combo->GetSelection();
|
int sel = m_imex_theme_combo->GetSelection();
|
||||||
std::string val = (sel >= 0 && sel < 4) ? theme_vals[sel] : "standard";
|
std::string val = (sel >= 0 && sel < 4) ? theme_vals[sel] : "standard";
|
||||||
m_config->set_key_value("ixex_viz_theme", new ConfigOptionString(val));
|
m_config->set_key_value("imex_viz_theme", new ConfigOptionString(val));
|
||||||
on_value_change("ixex_viz_theme", val);
|
on_value_change("imex_viz_theme", val);
|
||||||
});
|
});
|
||||||
auto* s = new wxBoxSizer(wxHORIZONTAL);
|
auto* s = new wxBoxSizer(wxHORIZONTAL);
|
||||||
s->Add(m_ixex_theme_combo, 0, wxALIGN_CENTER_VERTICAL);
|
s->Add(m_imex_theme_combo, 0, wxALIGN_CENTER_VERTICAL);
|
||||||
return s;
|
return s;
|
||||||
};
|
};
|
||||||
optgroup->append_line(line);
|
optgroup->append_line(line);
|
||||||
@@ -5018,23 +5018,23 @@ void TabPrinter::build_fff()
|
|||||||
auto line = Line{ L("Modes"), L("") };
|
auto line = Line{ L("Modes"), L("") };
|
||||||
line.full_width = 1;
|
line.full_width = 1;
|
||||||
line.widget = [this](wxWindow* parent) -> wxSizer* {
|
line.widget = [this](wxWindow* parent) -> wxSizer* {
|
||||||
int n_cols = m_config->opt_int("ixex_tools_per_gantry");
|
int n_cols = m_config->opt_int("imex_tools_per_gantry");
|
||||||
int n_rows = m_config->opt_int("ixex_gantry_count");
|
int n_rows = m_config->opt_int("imex_gantry_count");
|
||||||
std::string layout_str = "front-left";
|
std::string layout_str = "front-left";
|
||||||
if (auto* o = m_config->option<ConfigOptionString>("ixex_tool_layout")) layout_str = o->value;
|
if (auto* o = m_config->option<ConfigOptionString>("imex_tool_layout")) layout_str = o->value;
|
||||||
int layout = IXexModesCtrl::parse_layout(layout_str);
|
int layout = IMEXModesCtrl::parse_layout(layout_str);
|
||||||
m_ixex_modes_ctrl = new IXexModesCtrl(parent, n_cols, n_rows, layout);
|
m_imex_modes_ctrl = new IMEXModesCtrl(parent, n_cols, n_rows, layout);
|
||||||
m_ixex_modes_ctrl->load_from_config(*m_config);
|
m_imex_modes_ctrl->load_from_config(*m_config);
|
||||||
m_ixex_modes_ctrl->on_change = [this]() {
|
m_imex_modes_ctrl->on_change = [this]() {
|
||||||
auto [names, tools, gcodes] = m_ixex_modes_ctrl->get_mode_data();
|
auto [names, tools, gcodes] = m_imex_modes_ctrl->get_mode_data();
|
||||||
m_config->set_key_value("ixex_mode_names", new ConfigOptionStrings(names));
|
m_config->set_key_value("imex_mode_names", new ConfigOptionStrings(names));
|
||||||
m_config->set_key_value("ixex_mode_active_tools", new ConfigOptionStrings(tools));
|
m_config->set_key_value("imex_mode_active_tools", new ConfigOptionStrings(tools));
|
||||||
m_config->set_key_value("ixex_mode_gcodes", new ConfigOptionStrings(gcodes));
|
m_config->set_key_value("imex_mode_gcodes", new ConfigOptionStrings(gcodes));
|
||||||
update_dirty();
|
update_dirty();
|
||||||
on_value_change("ixex_mode_names", std::string(""));
|
on_value_change("imex_mode_names", std::string(""));
|
||||||
};
|
};
|
||||||
auto* sizer = new wxBoxSizer(wxHORIZONTAL);
|
auto* sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||||
sizer->Add(m_ixex_modes_ctrl, 1, wxEXPAND);
|
sizer->Add(m_imex_modes_ctrl, 1, wxEXPAND);
|
||||||
return sizer;
|
return sizer;
|
||||||
};
|
};
|
||||||
modes_og->append_line(line);
|
modes_og->append_line(line);
|
||||||
@@ -5622,28 +5622,28 @@ void TabPrinter::reload_config()
|
|||||||
|
|
||||||
if (m_config) {
|
if (m_config) {
|
||||||
// Sync layout combo
|
// Sync layout combo
|
||||||
if (m_ixex_layout_combo) {
|
if (m_imex_layout_combo) {
|
||||||
static const char* layout_vals[] = { "front-left", "front-right", "rear-left", "rear-right" };
|
static const char* layout_vals[] = { "front-left", "front-right", "rear-left", "rear-right" };
|
||||||
std::string cur = "front-left";
|
std::string cur = "front-left";
|
||||||
if (auto* o = m_config->option<ConfigOptionString>("ixex_tool_layout")) cur = o->value;
|
if (auto* o = m_config->option<ConfigOptionString>("imex_tool_layout")) cur = o->value;
|
||||||
for (int i = 0; i < 4; ++i)
|
for (int i = 0; i < 4; ++i)
|
||||||
if (cur == layout_vals[i]) { m_ixex_layout_combo->SetSelection(i); break; }
|
if (cur == layout_vals[i]) { m_imex_layout_combo->SetSelection(i); break; }
|
||||||
}
|
}
|
||||||
// Sync theme combo
|
// Sync theme combo
|
||||||
if (m_ixex_theme_combo) {
|
if (m_imex_theme_combo) {
|
||||||
static const char* theme_vals[] = { "standard", "deuteranopia", "tritanopia", "high_contrast" };
|
static const char* theme_vals[] = { "standard", "deuteranopia", "tritanopia", "high_contrast" };
|
||||||
std::string cur = "standard";
|
std::string cur = "standard";
|
||||||
if (auto* o = m_config->option<ConfigOptionString>("ixex_viz_theme")) cur = o->value;
|
if (auto* o = m_config->option<ConfigOptionString>("imex_viz_theme")) cur = o->value;
|
||||||
for (int i = 0; i < 4; ++i)
|
for (int i = 0; i < 4; ++i)
|
||||||
if (cur == theme_vals[i]) { m_ixex_theme_combo->SetSelection(i); break; }
|
if (cur == theme_vals[i]) { m_imex_theme_combo->SetSelection(i); break; }
|
||||||
}
|
}
|
||||||
if (m_ixex_modes_ctrl) {
|
if (m_imex_modes_ctrl) {
|
||||||
int n_cols = m_config->opt_int("ixex_tools_per_gantry");
|
int n_cols = m_config->opt_int("imex_tools_per_gantry");
|
||||||
int n_rows = m_config->opt_int("ixex_gantry_count");
|
int n_rows = m_config->opt_int("imex_gantry_count");
|
||||||
std::string layout_str = "front-left";
|
std::string layout_str = "front-left";
|
||||||
if (auto* o = m_config->option<ConfigOptionString>("ixex_tool_layout")) layout_str = o->value;
|
if (auto* o = m_config->option<ConfigOptionString>("imex_tool_layout")) layout_str = o->value;
|
||||||
m_ixex_modes_ctrl->set_grid_size(n_cols, n_rows, IXexModesCtrl::parse_layout(layout_str));
|
m_imex_modes_ctrl->set_grid_size(n_cols, n_rows, IMEXModesCtrl::parse_layout(layout_str));
|
||||||
m_ixex_modes_ctrl->load_from_config(*m_config);
|
m_imex_modes_ctrl->load_from_config(*m_config);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5662,9 +5662,9 @@ void TabPrinter::clear_pages()
|
|||||||
{
|
{
|
||||||
Tab::clear_pages();
|
Tab::clear_pages();
|
||||||
m_reset_to_filament_color = nullptr;
|
m_reset_to_filament_color = nullptr;
|
||||||
m_ixex_modes_ctrl = nullptr;
|
m_imex_modes_ctrl = nullptr;
|
||||||
m_ixex_layout_combo = nullptr;
|
m_imex_layout_combo = nullptr;
|
||||||
m_ixex_theme_combo = nullptr;
|
m_imex_theme_combo = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabPrinter::toggle_options()
|
void TabPrinter::toggle_options()
|
||||||
@@ -5874,13 +5874,13 @@ void TabPrinter::update_fff()
|
|||||||
m_use_silent_mode = m_config->opt_bool("silent_mode");
|
m_use_silent_mode = m_config->opt_bool("silent_mode");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sync iXex tool grid whenever carriage configuration changes.
|
// Sync IDEX/IQEX tool grid whenever carriage configuration changes.
|
||||||
// set_grid_size() is a no-op when dimensions and layout are unchanged.
|
// set_grid_size() is a no-op when dimensions and layout are unchanged.
|
||||||
if (m_ixex_modes_ctrl) {
|
if (m_imex_modes_ctrl) {
|
||||||
int n_cols = m_config->opt_int("ixex_tools_per_gantry");
|
int n_cols = m_config->opt_int("imex_tools_per_gantry");
|
||||||
int n_rows = m_config->opt_int("ixex_gantry_count");
|
int n_rows = m_config->opt_int("imex_gantry_count");
|
||||||
std::string layout_str = m_config->opt_string("ixex_tool_layout");
|
std::string layout_str = m_config->opt_string("imex_tool_layout");
|
||||||
m_ixex_modes_ctrl->set_grid_size(n_cols, n_rows, IXexModesCtrl::parse_layout(layout_str));
|
m_imex_modes_ctrl->set_grid_size(n_cols, n_rows, IMEXModesCtrl::parse_layout(layout_str));
|
||||||
}
|
}
|
||||||
|
|
||||||
toggle_options();
|
toggle_options();
|
||||||
|
|||||||
@@ -589,7 +589,7 @@ public:
|
|||||||
void set_custom_gcode(const t_config_option_key& opt_key, const std::string& value) override;
|
void set_custom_gcode(const t_config_option_key& opt_key, const std::string& value) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class IXexModesCtrl;
|
class IMEXModesCtrl;
|
||||||
|
|
||||||
class TabPrinter : public Tab
|
class TabPrinter : public Tab
|
||||||
{
|
{
|
||||||
@@ -605,9 +605,9 @@ private:
|
|||||||
std::vector<PageShp> m_pages_sla;
|
std::vector<PageShp> m_pages_sla;
|
||||||
|
|
||||||
wxBoxSizer* m_presets_sizer {nullptr};
|
wxBoxSizer* m_presets_sizer {nullptr};
|
||||||
IXexModesCtrl* m_ixex_modes_ctrl {nullptr};
|
IMEXModesCtrl* m_imex_modes_ctrl {nullptr};
|
||||||
ComboBox* m_ixex_layout_combo {nullptr};
|
ComboBox* m_imex_layout_combo {nullptr};
|
||||||
ComboBox* m_ixex_theme_combo {nullptr};
|
ComboBox* m_imex_theme_combo {nullptr};
|
||||||
public:
|
public:
|
||||||
ScalableButton* m_reset_to_filament_color = nullptr;
|
ScalableButton* m_reset_to_filament_color = nullptr;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user