diff --git a/conandata.yml b/conandata.yml index f5da580fcb..909c921748 100644 --- a/conandata.yml +++ b/conandata.yml @@ -2,7 +2,7 @@ version: "5.9.0-alpha.0" requirements: - "scripta/0.1.0@ultimaker/testing" requirements_arcus: - - "arcus/5.3.1" + - "arcus/5.4.1" requirements_plugins: - "curaengine_grpc_definitions/0.2.1" requirements_cura_resources: diff --git a/src/LayerPlan.cpp b/src/LayerPlan.cpp index b28cc5034c..8f6c12317c 100644 --- a/src/LayerPlan.cpp +++ b/src/LayerPlan.cpp @@ -2350,7 +2350,11 @@ void LayerPlan::writeGCode(GCodeExport& gcode) } } } - gcode.writePrepareFansForExtrusion(extruder_plan.getFanSpeed()); + // Fan speed may already be set by a plugin. Prevents two fan speed commands without move in between. + if (! extruder_plan.paths_.empty() && extruder_plan.paths_.front().fan_speed == -1) + { + gcode.writePrepareFansForExtrusion(extruder_plan.getFanSpeed()); + } std::vector& paths = extruder_plan.paths_; extruder_plan.inserts_.sort(); @@ -2425,6 +2429,13 @@ void LayerPlan::writeGCode(GCodeExport& gcode) assert(! path.points.empty()); + // If travel paths have a non default fan speed for some reason set it as fan speed as such modification could be made by a plugin. + if (! path.isTravelPath() || path.fan_speed >= 0) + { + const double path_fan_speed = path.getFanSpeed(); + gcode.writeFanCommand(path_fan_speed != GCodePathConfig::FAN_SPEED_DEFAULT ? path_fan_speed : extruder_plan.getFanSpeed()); + } + if (path.perform_prime) { gcode.writePrimeTrain(extruder.settings_.get("speed_travel")); @@ -2599,10 +2610,6 @@ void LayerPlan::writeGCode(GCodeExport& gcode) bool spiralize = path.spiralize; if (! spiralize) // normal (extrusion) move (with coasting) { - // if path provides a valid (in range 0-100) fan speed, use it - const double path_fan_speed = path.getFanSpeed(); - gcode.writeFanCommand(path_fan_speed != GCodePathConfig::FAN_SPEED_DEFAULT ? path_fan_speed : extruder_plan.getFanSpeed()); - bool coasting = extruder.settings_.get("coasting_enable"); if (coasting) { @@ -2895,6 +2902,7 @@ bool LayerPlan::writePathWithCoasting( void LayerPlan::applyModifyPlugin() { + bool handled_initial_travel = false; for (auto& extruder_plan : extruder_plans_) { scripta::log( @@ -2917,6 +2925,40 @@ void LayerPlan::applyModifyPlugin() extruder_plan.paths_ = slots::instance().modify(extruder_plan.paths_, extruder_plan.extruder_nr_, layer_nr_); + // Check if the plugin changed first_travel_destination and update it accordingly if it has + if (! handled_initial_travel) + { + for (auto& path : extruder_plan.paths_) + { + if (path.isTravelPath() && path.points.size() > 0) + { + if (path.points.front() != first_travel_destination_) + { + first_travel_destination_ = path.points.front().toPoint2LL(); + } + handled_initial_travel = true; + break; + } + } + } + + size_t removed_count = std::erase_if( + extruder_plan.paths_, + [](GCodePath& path) + { + return path.points.empty(); + }); + if (removed_count > 0) + { + spdlog::warn("Removed {} empty paths after plugin slot GCODE_PATHS_MODIFY was executed", removed_count); + } + // Ensure that the output is at least valid enough to not cause crashes. + if (extruder_plan.paths_.size() == 0) + { + GCodePath* reinstated_path = getLatestPathWithConfig(configs_storage_.travel_config_per_extruder[getExtruder()], SpaceFillType::None); + addTravel_simple(first_travel_destination_.value_or(getLastPlannedPositionOrStartingPosition()), reinstated_path); + } + scripta::log( "extruder_plan_1", extruder_plan.paths_, diff --git a/src/plugins/converters.cpp b/src/plugins/converters.cpp index f9dfcfed90..c5a33d5edd 100644 --- a/src/plugins/converters.cpp +++ b/src/plugins/converters.cpp @@ -51,12 +51,28 @@ broadcast_settings_request::value_type broadcast_settings_request::operator()(co } auto* object_settings = message.mutable_object_settings(); - for (const auto& object : slice_message.object_lists()) + for (const auto& mesh_group : slice_message.object_lists()) { - auto* settings = object_settings->Add()->mutable_settings(); - for (const auto& setting : object.settings()) + std::unordered_map mesh_group_settings; + for (const auto& setting : mesh_group.settings()) { - settings->emplace(setting.name(), setting.value()); + mesh_group_settings[setting.name()] = setting.value(); + } + for (const auto& object : mesh_group.objects()) + { + std::unordered_map per_object_settings = mesh_group_settings; + for (const auto& setting : object.settings()) + { + per_object_settings[setting.name()] = setting.value(); + } + + per_object_settings["mesh_name"] = object.name(); + + auto* settings = object_settings->Add()->mutable_settings(); + for (const auto& key_value_pair : per_object_settings) + { + settings->emplace(key_value_pair.first, key_value_pair.second); + } } } diff --git a/tests/arcus/MockSocket.cpp b/tests/arcus/MockSocket.cpp index df41690a41..a6860202c4 100644 --- a/tests/arcus/MockSocket.cpp +++ b/tests/arcus/MockSocket.cpp @@ -21,9 +21,10 @@ void MockSocket::reset() { /* Do nothing. */ } -void MockSocket::sendMessage(Arcus::MessagePtr message) +bool MockSocket::sendMessage(Arcus::MessagePtr message) { sent_messages.push_back(message); + return true; } Arcus::MessagePtr MockSocket::takeNextMessage() @@ -45,4 +46,4 @@ Arcus::MessagePtr MockSocket::popMessageFromSendQueue() return result; } -} // namespace cura \ No newline at end of file +} // namespace cura diff --git a/tests/arcus/MockSocket.h b/tests/arcus/MockSocket.h index 272720f216..9bed7467e0 100644 --- a/tests/arcus/MockSocket.h +++ b/tests/arcus/MockSocket.h @@ -4,9 +4,10 @@ #ifndef MOCKSOCKET_H #define MOCKSOCKET_H -#include //Inheriting from this to be able to swap this socket in the tested class. #include //History of sent and received messages. +#include //Inheriting from this to be able to swap this socket in the tested class. + namespace cura { @@ -27,7 +28,7 @@ class MockSocket : public Arcus::Socket void reset() override; // Catch these functions so that we can see whether they are called. - void sendMessage(Arcus::MessagePtr message) override; + bool sendMessage(Arcus::MessagePtr message) override; Arcus::MessagePtr takeNextMessage() override; // Helpers to store send and received messages. @@ -39,4 +40,4 @@ class MockSocket : public Arcus::Socket // NOLINTEND(misc-non-private-member-variables-in-classes) } // namespace cura -#endif // MOCKSOCKET_H \ No newline at end of file +#endif // MOCKSOCKET_H