Files
OrcaSlicer/src/slic3r/plugin/PluginHooks.cpp
T
HanifKoh 4895bc03b4 Remove Unused Project Includes and Forward-Declare Where a Type Is Only Referenced (#16099)
* Remove Unused Project Includes and Forward-Declare Where a Type Is Only Referenced

Generated with include-what-you-use and applied conservatively. Only OrcaSlicer's own headers, the ones under src/ and tests/, are removed or forward-declared; standard-library and third-party includes are left alone. An include is removed only when both the Release and the Debug configuration leave it unused, never from inside a conditional block, and never from a file with platform-specific blocks, which only gain includes. Files whose only use of a header sits behind a feature or debug macro (libvgcode's OpenGL ES and marker code, the ARACHNE/TESTS_EXPORT_SVGS debug output) keep their includes.

clonable_ptr.hpp gains #pragma once; it had no include guard and was only safe while Config.hpp was its sole includer.

* Remove Unused Project Includes From Files With Platform-Specific Code

A Linux include-what-you-use run cannot see the code inside _WIN32, __APPLE__ or __linux__ blocks, so its verdict is only taken where nothing the removed header declares, directly or through what it includes, is named inside those blocks. Removals also have to hold in both the Release and Debug configuration and never touch a line inside a conditional block.

* Restore the libslic3r Precompiled Header and Direct Includes Lost in the Platform Pass

The platform-file pass treated pchheader.hpp as an ordinary header and
emptied it, and left GUI_Preview.hpp and 14 other files relying on
headers they no longer reached directly.

* Restore MainFrame.hpp in ParamsDialog.cpp for the Windows-Only Reparent Call

* Include Headers That Files Reached Through Ones the Cleanup Removed

* Drop Includes Duplicated by the Cleanup or by Main's Own Additions

* Leave PreciseSeam.cpp as Main Has It After the Precise Seam Rework
2026-10-05 16:47:17 +08:00

152 lines
7.7 KiB
C++

#include "PluginHooks.hpp"
#include "PluginManager.hpp"
#include "PythonInterpreter.hpp"
#include "PythonPluginInterface.hpp"
#include "pluginTypes/slicingPipeline/SlicingPipelinePluginCapability.hpp"
#include "libslic3r/Config.hpp"
#include "libslic3r/Exception.hpp"
#include "libslic3r/LifecycleEvents.hpp"
#include "libslic3r/Print.hpp"
#include "libslic3r_version.h"
#include <boost/log/trivial.hpp>
#include <exception>
#include <cstddef>
#include <memory>
#include "slic3r/plugin/PluginDescriptor.hpp"
#include <string>
#include <stdexcept>
#include "libslic3r/PrintBase.hpp"
#include "libslic3r/PrintConfig.hpp"
namespace Slic3r::plugin_hooks {
namespace {
// Manifest resolver: turns the bare capability name a preset stores into the full
// "name;uuid;capability" reference the dispatchers consume (see
// ConfigBase::collect_plugin_manifest / update_plugin_manifest).
void install_capability_resolver()
{
ConfigBase::set_resolve_capability_fn([](const std::string& cap_name, const std::string& cap_type) {
PluginManager& plugin_mgr = PluginManager::instance();
const PluginCapabilityType type = plugin_capability_type_from_string(cap_type);
// only_enabled = false: this resolves the reference a preset STORES, which must stay
// resolvable whether or not the user currently has the capability enabled. Filtering on
// the enable flag here would quietly drop the reference out of the preset's manifest.
auto plugin_cap = plugin_mgr.get_plugin_capability(cap_name, type, /*only_enabled=*/false);
if (!plugin_cap)
return std::string();
PluginDescriptor descriptor;
if (!plugin_mgr.try_get_plugin_descriptor_for_capability(cap_name, type, descriptor))
return std::string();
// Cloud plugins are resolved at runtime via the UUID in the middle field, so the first
// field keeps the friendly display name. Local plugins are looked up by plugin_key (the
// first field, with an empty UUID), so emit the plugin_key to keep them resolvable.
const std::string identity = descriptor.is_cloud_plugin() ? descriptor.name : descriptor.plugin_key;
return identity + ';' + descriptor.cloud_uuid() + ';' + cap_name;
});
}
// Global libslic3r-side seam (Slic3r::fire_lifecycle_event, in libslic3r/LifecycleEvents.hpp):
// broadcasts to every loaded, enabled capability regardless of type, unlike the SlicingPipeline
// hook below which only targets picker-selected SlicingPipeline capabilities.
void install_lifecycle_event_hook()
{
set_lifecycle_hook_fn([](LifecycleEvent event, const LifecycleEventContext& ctx) {
PluginManager::instance().dispatch_lifecycle_event(event, ctx);
});
}
// Print::process() fires this hook at each pipeline seam on the slicing worker
// thread; here we run the picker-selected SlicingPipeline capabilities. Per
// capability we acquire the GIL, honor cancellation, and convert a plugin
// failure into a (non-critical) SlicingError so it surfaces as a slicing-error
// notification rather than the fatal-crash dialog.
void install_slicing_pipeline_hook()
{
Print::set_slicing_pipeline_hook_fn(
[](Print& print, const PrintObject* object, SlicingPipelineStepPlugin step) {
const auto* caps = print.config().option<ConfigOptionStrings>("slicing_pipeline_plugin");
// `plugins` is a dynamic-only manifest key (not a static PrintConfig member), so it
// must be read from the full/dynamic config -- reading it off print.config() (the
// static PrintConfig) always yields nullptr and skips every capability. Mirrors the
// post-process path (PostProcessor.cpp, via BackgroundSlicingProcess::full_print_config()).
const auto* plugs = print.full_print_config().option<ConfigOptionStrings>("plugins");
if (caps == nullptr || caps->values.empty())
return;
execute_capabilities_from_refs<SlicingPipelinePluginCapability>(
*caps, plugs, PluginCapabilityType::SlicingPipeline,
[&](std::shared_ptr<SlicingPipelinePluginCapability> cap, const PluginCapabilityRef& ref) {
const std::string plugin_key = ref.uuid.empty() ? ref.name : ref.uuid;
ExecutionResult r;
try {
// GIL is acquired per capability (not once for the whole dispatch) so it
// is released between capabilities.
PythonGILState gil;
if (!gil)
throw std::runtime_error("Python interpreter is shutting down");
// throw_if_canceled() is protected on PrintBase; canceled() is the public
// equivalent check (same cancel flag), so honor cancellation via it.
if (print.canceled())
throw CanceledException();
SlicingPipelineContext ctx;
ctx.orca_version = SoftFever_VERSION;
ctx.step = step;
ctx.print = &print;
ctx.object = object;
r = cap->execute(ctx);
} catch (const CanceledException&) {
throw; // cancellation must reach process(), never become a slicing error
} catch (const std::exception& ex) {
// A Python raise reaches here as pybind11::error_already_set; surface it as a
// (non-critical) slicing error instead of a crash.
throw SlicingError(std::string("Slicing pipeline plugin '") +
ref.capability_name + "' error: " + ex.what());
}
if (r.status == PluginResult::FatalError)
throw SlicingError(std::string("Slicing pipeline plugin '") +
ref.capability_name + "' error: " + r.message);
// log a non-empty success/skipped message instead of dropping it. This is
// log-only by design: every pipeline hook fires AFTER set_done() (see Print.cpp),
// so the Print-level m_step_active is -1 here. Calling active_step_add_warning()
// would then index m_state[-1] (out-of-bounds; the guarding assert is compiled
// out in Release), so it must NOT be called from a pipeline hook.
if (!r.message.empty()) {
static const char* const kStepNames[] = {
"posSlice", "posPerimeters", "posEstimateCurledExtrusions", "posPrepareInfill", "posInfill",
"posIroning", "posContouring", "posSupportMaterial", "posDetectOverhangsForLift",
"posSimplifyPath", "psWipeTower", "psSkirtBrim", "psGCodePostProcess"
}; // order must match SlicingPipelineStepPlugin
const char* step_name = static_cast<size_t>(step) < sizeof(kStepNames) / sizeof(kStepNames[0])
? kStepNames[static_cast<int>(step)] : "Unknown";
BOOST_LOG_TRIVIAL(info) << "Slicing pipeline plugin '" << ref.capability_name
<< "' [" << step_name << "]: " << r.message;
}
});
});
}
} // namespace
void install()
{
install_capability_resolver();
install_slicing_pipeline_hook();
install_lifecycle_event_hook();
}
void uninstall()
{
ConfigBase::set_resolve_capability_fn(nullptr);
Print::set_slicing_pipeline_hook_fn(nullptr);
set_lifecycle_hook_fn(nullptr);
}
} // namespace Slic3r::plugin_hooks