mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-08-04 08:42:10 +00:00
Compare commits
41 Commits
feature/wi
...
feature/pr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2f67e46047 | ||
|
|
fae4b1241b | ||
|
|
5a5c25b8d1 | ||
|
|
571819bfb2 | ||
|
|
d47b57af8a | ||
|
|
5f15ead5ee | ||
|
|
9679cc5b81 | ||
|
|
08bfb37bb6 | ||
|
|
be9322fd6e | ||
|
|
9e7c41d130 | ||
|
|
4583516e4a | ||
|
|
bb919a7171 | ||
|
|
1c576873fc | ||
|
|
b1d1fb7dfc | ||
|
|
8be6b40e7f | ||
|
|
cd6223ffaf | ||
|
|
0458925f85 | ||
|
|
7c34e089e4 | ||
|
|
d314e9c09a | ||
|
|
7fa650e410 | ||
|
|
1c1cee7784 | ||
|
|
1d7da51991 | ||
|
|
3be63d4369 | ||
|
|
99a0dd8556 | ||
|
|
fcd3a66af4 | ||
|
|
972da86fbc | ||
|
|
8cb357ec06 | ||
|
|
a29fac5de8 | ||
|
|
14097382d8 | ||
|
|
3db76d7f89 | ||
|
|
c47fc4529e | ||
|
|
b823994feb | ||
|
|
403766b1b6 | ||
|
|
6e84139d60 | ||
|
|
a78ef9ce1c | ||
|
|
064e10c069 | ||
|
|
87ceeaa0aa | ||
|
|
35d4bae778 | ||
|
|
2eb1b8ddd6 | ||
|
|
5475e0aebe | ||
|
|
04b7ae9219 |
4
.github/workflows/build_all.yml
vendored
4
.github/workflows/build_all.yml
vendored
@@ -282,6 +282,10 @@ jobs:
|
||||
sed -i "/name: OrcaSlicer/{n;s|buildsystem: simple|buildsystem: simple\n build-options:\n env:\n git_commit_hash: \"$git_commit_hash\"|}" \
|
||||
scripts/flatpak/com.orcaslicer.OrcaSlicer.yml
|
||||
shell: bash
|
||||
- name: Generate config sources
|
||||
# Generated on the host: the flatpak build itself runs offline.
|
||||
run: python3 tools/run_codegen.py
|
||||
shell: bash
|
||||
- uses: flatpak/flatpak-github-actions/flatpak-builder@master
|
||||
with:
|
||||
bundle: OrcaSlicer-Linux-flatpak_${{ env.ver }}_${{ matrix.variant.arch }}.flatpak
|
||||
|
||||
13
.github/workflows/build_orca.yml
vendored
13
.github/workflows/build_orca.yml
vendored
@@ -57,6 +57,19 @@ jobs:
|
||||
useLocalCache: true # <--= Use the local cache (default is 'false').
|
||||
useCloudCache: true
|
||||
|
||||
# run_codegen.py resolves its own toolchain (a pinned protoc plus protobuf/pyyaml in a
|
||||
# cached virtualenv), so nothing has to be pip-installed around it. That is what makes it
|
||||
# work on windows-11-arm, where `pip install grpcio-tools` has no wheel and fails building
|
||||
# the grpcio C extension from source.
|
||||
- name: Generate config sources
|
||||
if: runner.os == 'Windows'
|
||||
run: python tools/run_codegen.py
|
||||
shell: pwsh
|
||||
|
||||
- name: Generate config sources
|
||||
if: runner.os != 'Windows'
|
||||
run: python3 tools/run_codegen.py
|
||||
shell: bash
|
||||
- name: Install CMake 3.31.x (Windows ARM64)
|
||||
# windows-11-arm ships CMake 4.x, which removed pre-3.5 policy
|
||||
# compatibility AND has incomplete ASM_ARMASM linker modules
|
||||
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -46,6 +46,11 @@ test.js
|
||||
internal_docs/
|
||||
*.flatpak
|
||||
/flatpak-repo/
|
||||
# Config codegen: descriptor set, generated C++ and the downloaded protoc /
|
||||
# bootstrap virtualenv. All of it is produced by tools/run_codegen.py.
|
||||
config.desc
|
||||
src/slic3r/GUI/generated/
|
||||
.codegen-tools/
|
||||
# Python bytecode
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
@@ -1082,6 +1082,12 @@ function(orcaslicer_copy_dlls target config postfix output_dlls)
|
||||
endfunction()
|
||||
|
||||
|
||||
# Config codegen — generates src/slic3r/GUI/generated/*.cpp from src/PrintConfigs/*.proto.
|
||||
# Must run before compiling libslic3r (PrintConfig.cpp #includes the generated files).
|
||||
# The toolchain (protoc, protobuf, pyyaml) is resolved by tools/run_codegen.py itself;
|
||||
# set PROTOC=<path> to use an installed protoc instead of the pinned download.
|
||||
include(cmake/modules/ConfigCodegen.cmake)
|
||||
|
||||
# libslic3r, OrcaSlicer GUI and the OrcaSlicer executable.
|
||||
add_subdirectory(deps_src)
|
||||
add_subdirectory(src)
|
||||
|
||||
@@ -556,6 +556,11 @@ if [[ -n "${BUILD_ORCA}" ]] || [[ -n "${BUILD_TESTS}" ]] ; then
|
||||
BUILD_ARGS+=(-DORCA_UPDATER_SIG_KEY="${ORCA_UPDATER_SIG_KEY}")
|
||||
fi
|
||||
|
||||
echo "Generating config sources from proto..."
|
||||
# Resolves protoc and its Python packages itself; nothing is installed into the
|
||||
# system interpreter (distro Pythons refuse that under PEP 668 anyway).
|
||||
python3 tools/run_codegen.py || { echo "ERROR: config codegen failed"; exit 1; }
|
||||
|
||||
print_and_run cmake -S . -B $BUILD_DIR "${CMAKE_C_CXX_COMPILER_CLANG[@]}" "${CMAKE_LLD_LINKER_ARGS[@]}" "${CMAKE_CCACHE_ARGS[@]}" -G "Ninja Multi-Config" \
|
||||
-DSLIC3R_PCH=${SLIC3R_PRECOMPILED_HEADERS} \
|
||||
-DORCA_TOOLS=ON \
|
||||
|
||||
@@ -240,6 +240,11 @@ function verify_python_runtime() {
|
||||
}
|
||||
|
||||
function build_slicer() {
|
||||
echo "Generating config sources from proto..."
|
||||
# Resolves protoc and its Python packages itself (into .codegen-tools/), so nothing
|
||||
# is installed into the system interpreter.
|
||||
python3 tools/run_codegen.py || { echo "ERROR: config codegen failed"; exit 1; }
|
||||
|
||||
# iterate over two architectures: x86_64 and arm64
|
||||
for _ARCH in x86_64 arm64; do
|
||||
# if ARCH is universal or equal to _ARCH
|
||||
|
||||
@@ -145,6 +145,16 @@ if "%1"=="deps" goto :done
|
||||
:slicer
|
||||
echo "building Orca Slicer..."
|
||||
cd %WP%
|
||||
|
||||
echo "generating config sources from proto..."
|
||||
REM run_codegen.py resolves protoc and its python packages itself (grpcio-tools has
|
||||
REM no wheel on ARM64 and fails to build there).
|
||||
python tools/run_codegen.py
|
||||
if errorlevel 1 (
|
||||
echo "ERROR: config codegen failed"
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
mkdir %build_dir%
|
||||
cd %build_dir%
|
||||
|
||||
|
||||
@@ -66,6 +66,16 @@ if "%1"=="deps" exit /b 0
|
||||
:slicer
|
||||
echo "building Orca Slicer..."
|
||||
cd %WP%
|
||||
|
||||
echo "generating config sources from proto..."
|
||||
REM run_codegen.py resolves protoc and its python packages itself (grpcio-tools has
|
||||
REM no wheel on ARM64 and fails to build there).
|
||||
python tools/run_codegen.py
|
||||
if errorlevel 1 (
|
||||
echo "ERROR: config codegen failed"
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
mkdir %build_dir%
|
||||
cd %build_dir%
|
||||
|
||||
|
||||
144
cmake/modules/ConfigCodegen.cmake
Normal file
144
cmake/modules/ConfigCodegen.cmake
Normal file
@@ -0,0 +1,144 @@
|
||||
# OrcaSlicer Config Codegen CMake Module
|
||||
#
|
||||
# Generates C++ source files from protobuf schema definitions.
|
||||
# Generated files live in src/slic3r/GUI/generated/ and are gitignored.
|
||||
# Run 'python tools/run_codegen.py' to regenerate; it resolves protoc and the Python
|
||||
# packages it needs itself (see tools/codegen_toolchain.py).
|
||||
#
|
||||
# Targets:
|
||||
# codegen_config - Custom target to regenerate C++ from .proto files
|
||||
# validate_config - Custom target to validate generated vs original
|
||||
#
|
||||
# Usage in parent CMakeLists.txt:
|
||||
# include(cmake/modules/ConfigCodegen.cmake)
|
||||
|
||||
find_program(PROTOC_EXECUTABLE protoc)
|
||||
find_package(Python3 COMPONENTS Interpreter QUIET)
|
||||
|
||||
set(_generated_marker "${CMAKE_SOURCE_DIR}/src/slic3r/GUI/generated/PrintConfigDef_generated.cpp")
|
||||
|
||||
# Decide which interpreter can actually run the codegen.
|
||||
#
|
||||
# The main CMakeLists forces Python3_EXECUTABLE to the *bundled embed* interpreter (used for
|
||||
# the in-app Python plugin runtime). That interpreter has neither protoc nor the protobuf /
|
||||
# pyyaml packages, and for cross-compiled targets it may not even be the host architecture — so
|
||||
# it cannot run tools/run_codegen.py. Prefer a host interpreter, which tools/run_codegen.py can
|
||||
# bootstrap the toolchain into.
|
||||
#
|
||||
# ORCA_CODEGEN_PYTHON lets a build explicitly point at the interpreter to use.
|
||||
if(NOT ORCA_CODEGEN_PYTHON)
|
||||
find_program(_orca_host_python NAMES python3 python)
|
||||
if(_orca_host_python)
|
||||
set(ORCA_CODEGEN_PYTHON "${_orca_host_python}")
|
||||
else()
|
||||
set(ORCA_CODEGEN_PYTHON "${Python3_EXECUTABLE}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# --check answers "can this interpreter regenerate right now?" (protobuf + pyyaml importable
|
||||
# and a protoc already resolvable). It never downloads or installs, so wiring up the build-time
|
||||
# regeneration below never turns a build into a network operation.
|
||||
set(_codegen_usable FALSE)
|
||||
if(ORCA_CODEGEN_PYTHON)
|
||||
execute_process(
|
||||
COMMAND ${ORCA_CODEGEN_PYTHON} "${CMAKE_SOURCE_DIR}/tools/codegen_toolchain.py" --check
|
||||
RESULT_VARIABLE _codegen_probe
|
||||
OUTPUT_QUIET ERROR_QUIET
|
||||
)
|
||||
if(_codegen_probe EQUAL 0)
|
||||
set(_codegen_usable TRUE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# If generated files are missing (fresh clone), run the codegen now at configure time so a plain
|
||||
# cmake configure + build works without a separate pre-build step. Unlike the build-time
|
||||
# regeneration above this is allowed to fetch the toolchain — there is nothing to build without it.
|
||||
if(NOT EXISTS "${_generated_marker}")
|
||||
set(_codegen_result 1)
|
||||
if(ORCA_CODEGEN_PYTHON)
|
||||
message(STATUS "Config codegen: generated files missing — running codegen now...")
|
||||
execute_process(
|
||||
COMMAND ${ORCA_CODEGEN_PYTHON} "${CMAKE_SOURCE_DIR}/tools/run_codegen.py" --no-validate
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
RESULT_VARIABLE _codegen_result
|
||||
)
|
||||
endif()
|
||||
if(NOT _codegen_result EQUAL 0)
|
||||
message(FATAL_ERROR
|
||||
"Config codegen: generated files are missing and could not be generated.\n"
|
||||
"Run it manually with a host Python:\n"
|
||||
" python tools/run_codegen.py\n"
|
||||
"or pass -DORCA_CODEGEN_PYTHON=<python>. Offline builds can point at an installed\n"
|
||||
"protoc with PROTOC=<path>.")
|
||||
endif()
|
||||
message(STATUS "Config codegen: generated files created successfully")
|
||||
endif()
|
||||
|
||||
set(CONFIG_PROTO_DIR "${CMAKE_SOURCE_DIR}/src/PrintConfigs")
|
||||
set(CONFIG_CODEGEN_DIR "${CMAKE_SOURCE_DIR}/src/slic3r/GUI/generated")
|
||||
set(CONFIG_LAYOUT_YAML "${CMAKE_SOURCE_DIR}/src/PrintConfigs/layout.yaml")
|
||||
set(CONFIG_DESC_FILE "${CMAKE_BINARY_DIR}/config.desc")
|
||||
|
||||
set(CODEGEN_TOOL "${CMAKE_SOURCE_DIR}/tools/config_codegen.py")
|
||||
set(VALIDATE_TOOL "${CMAKE_SOURCE_DIR}/tools/validate_codegen.py")
|
||||
set(RUN_CODEGEN_TOOL "${CMAKE_SOURCE_DIR}/tools/run_codegen.py")
|
||||
|
||||
# Generated output files (TabLayout_generated.cpp is also generated from layout.yaml)
|
||||
set(CONFIG_GENERATED_SOURCES
|
||||
"${CONFIG_CODEGEN_DIR}/PrintConfigDef_generated.cpp"
|
||||
"${CONFIG_CODEGEN_DIR}/Preset_options_generated.cpp"
|
||||
"${CONFIG_CODEGEN_DIR}/Invalidation_generated.cpp"
|
||||
"${CONFIG_CODEGEN_DIR}/OptionKeys_generated.cpp"
|
||||
"${CONFIG_CODEGEN_DIR}/TabLayout_generated.cpp"
|
||||
)
|
||||
set(CONFIG_GENERATED_SOURCES "${CONFIG_GENERATED_SOURCES}" CACHE INTERNAL "Generated config cpp files")
|
||||
|
||||
# Collect all .proto source files (flat in src/PrintConfigs/, excluding config_metadata.proto)
|
||||
file(GLOB CONFIG_PROTO_FILES
|
||||
"${CONFIG_PROTO_DIR}/filament.proto"
|
||||
"${CONFIG_PROTO_DIR}/print.proto"
|
||||
"${CONFIG_PROTO_DIR}/printer.proto"
|
||||
)
|
||||
set(CONFIG_PROTO_FILES
|
||||
"${CONFIG_PROTO_DIR}/config_metadata.proto"
|
||||
${CONFIG_PROTO_FILES}
|
||||
)
|
||||
|
||||
if(_codegen_usable)
|
||||
# Single command: run_codegen.py resolves protoc itself.
|
||||
# Proto files → generated .cpp files. Runs automatically when any .proto changes.
|
||||
add_custom_command(
|
||||
OUTPUT ${CONFIG_GENERATED_SOURCES}
|
||||
COMMAND ${ORCA_CODEGEN_PYTHON} ${RUN_CODEGEN_TOOL} --no-validate
|
||||
DEPENDS ${CONFIG_PROTO_FILES} ${CONFIG_LAYOUT_YAML} ${CODEGEN_TOOL}
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
COMMENT "Re-generating config C++ from changed .proto files"
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
# codegen_config is part of ALL — runs before every build, checks if protos changed.
|
||||
add_custom_target(codegen_config ALL
|
||||
DEPENDS ${CONFIG_GENERATED_SOURCES}
|
||||
COMMENT "Config codegen up to date"
|
||||
)
|
||||
|
||||
# Validation target: cmake --build . --target validate_config
|
||||
add_custom_target(validate_config
|
||||
COMMAND ${ORCA_CODEGEN_PYTHON} ${VALIDATE_TOOL}
|
||||
DEPENDS ${CONFIG_GENERATED_SOURCES}
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
COMMENT "Validating generated config code against PrintConfig.cpp"
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
message(STATUS "Config codegen: enabled — proto changes auto-regenerate on next build")
|
||||
else()
|
||||
# No usable codegen toolchain in this interpreter (e.g. the bundled embed Python in CI).
|
||||
# The generated files already exist (checked/produced above); use them as-is and provide a
|
||||
# no-op codegen_config target so dependents that reference it still resolve.
|
||||
add_custom_target(codegen_config ALL
|
||||
COMMENT "Config codegen: using pre-generated files (no codegen toolchain in this interpreter)")
|
||||
add_custom_target(validate_config
|
||||
COMMENT "Config codegen: validation skipped (no codegen toolchain in this interpreter)")
|
||||
message(STATUS "Config codegen: no codegen toolchain in '${ORCA_CODEGEN_PYTHON}' — using pre-generated files")
|
||||
endif()
|
||||
495
docs/PrintConfig_Codegen_Design.md
Normal file
495
docs/PrintConfig_Codegen_Design.md
Normal file
@@ -0,0 +1,495 @@
|
||||
# PrintConfig Codegen — Design Document
|
||||
|
||||
## 1. Problem Statement
|
||||
|
||||
Every config setting in OrcaSlicer (e.g. `travel_speed`, `wipe_distance`) is independently maintained as string literals across ~12 locations in the codebase with zero compile-time validation linking them.
|
||||
|
||||
A single setting like `wipe_distance` appears in:
|
||||
|
||||
| # | Location | What's duplicated |
|
||||
|---|----------|-------------------|
|
||||
| 1 | `PrintConfig.cpp` `init_fff_params()` | Key, type, label, tooltip, default, constraints |
|
||||
| 2 | `PrintConfig.hpp` struct members | Type + member name (must match key string) |
|
||||
| 3 | `Preset.cpp` option lists | Key string in serialization lists |
|
||||
| 4 | `PrintConfig.cpp` extruder/filament lists | Key string in 4 sub-lists |
|
||||
| 5 | `PrintConfig.cpp` variant option sets | Key string in variant sets |
|
||||
| 6 | `Print.cpp` invalidation chains | `opt_key == "..."` checks |
|
||||
| 7 | `Tab.cpp` GUI layout | `append_single_option_line("key")` |
|
||||
| 8 | GUI files (`Field.cpp`, `OptionsGroup.cpp`) | `opt_key == "..."` special-case handling |
|
||||
| 9 | `PrintConfig.cpp` `handle_legacy()` | Old-to-new key name mapping |
|
||||
| 10 | `PrintConfig.cpp` `new_def` G-code placeholders | Re-declared type, label, tooltip |
|
||||
| 11 | `resources/profiles/*.json` | Key strings as JSON keys |
|
||||
|
||||
### Consequences
|
||||
|
||||
- Adding a new setting requires editing ~12 files manually
|
||||
- A typo in any one location causes a silent bug (no compile-time validation)
|
||||
- Print providers cannot add/customize settings without forking the C++ codebase
|
||||
- No cross-language tooling (Python scripts, web editors) can consume the schema
|
||||
- No build-time validation of profile JSONs against the canonical option list
|
||||
|
||||
---
|
||||
|
||||
## 2. Goals
|
||||
|
||||
- **Single source of truth** for all setting definitions
|
||||
- **Compile-time safety** against key mismatches across the codebase
|
||||
- **Adding a new setting = editing 1 file** (instead of ~12)
|
||||
- **Enable print providers** to customize settings (defaults, constraints, visibility) without C++ changes
|
||||
- **Cross-language API generation** (Python, TypeScript, JSON Schema)
|
||||
- **Build-time validation** of profile JSONs
|
||||
- **Hidden mode** — setting exists in config/serialization but is not shown in UI
|
||||
- **Disabled mode** — setting shown in UI but greyed out / non-editable
|
||||
- **Automated UI layout** — new settings with GUI annotations appear in UI without manual `Tab.cpp` edits
|
||||
|
||||
### Non-goals
|
||||
|
||||
- Runtime performance changes (slicing engine untouched)
|
||||
- Changing the `.3mf` wire format (cereal/JSON serialization preserved)
|
||||
|
||||
---
|
||||
|
||||
## 3. Current Architecture
|
||||
|
||||
### 3.1 Type System
|
||||
|
||||
`Config.hpp` defines ~15 `ConfigOptionType` variants:
|
||||
|
||||
```cpp
|
||||
coFloat, coInt, coBool, coString, coPercent, coFloatOrPercent,
|
||||
coPoint, coPoint3, coEnum,
|
||||
coFloats, coInts, coBools, coStrings, coPercents, coFloatsOrPercents,
|
||||
coPoints, coEnums
|
||||
```
|
||||
|
||||
Each has a corresponding C++ class (`ConfigOptionFloat`, `ConfigOptionBools`, etc.) with virtual `serialize()`/`deserialize()` methods:
|
||||
|
||||
```cpp
|
||||
class ConfigOption {
|
||||
virtual ConfigOptionType type() const = 0;
|
||||
virtual std::string serialize() const = 0;
|
||||
virtual bool deserialize(const std::string &str, bool append = false) = 0;
|
||||
virtual ConfigOption* clone() const = 0;
|
||||
// ...
|
||||
};
|
||||
|
||||
class ConfigOptionFloat : public ConfigOptionSingle<double> {
|
||||
ConfigOptionType type() const override { return coFloat; }
|
||||
std::string serialize() const override { /* double -> string */ }
|
||||
bool deserialize(const std::string &str, bool append) override { /* string -> double */ }
|
||||
};
|
||||
```
|
||||
|
||||
### 3.2 Definition Layer
|
||||
|
||||
`ConfigOptionDef` holds all metadata for one setting:
|
||||
|
||||
```
|
||||
opt_key, type, nullable, default_value,
|
||||
label, full_label, category, tooltip, sidetext,
|
||||
mode (Simple/Advanced/Develop),
|
||||
min, max, max_literal, ratio_over,
|
||||
gui_type, multiline, full_width, height,
|
||||
enum_values, enum_labels, enum_keys_map,
|
||||
aliases, shortcut
|
||||
```
|
||||
|
||||
All ~500 settings are registered in `PrintConfigDef::init_fff_params()` (~6000 lines) into the global `print_config_def` singleton. Each registration block:
|
||||
|
||||
```cpp
|
||||
def = this->add("bridge_flow", coFloat); // register key + type
|
||||
def->label = L("Bridge flow ratio"); // UI label
|
||||
def->category = L("Quality"); // tab category
|
||||
def->tooltip = L("..."); // tooltip
|
||||
def->min = 0; // constraint
|
||||
def->max = 2.0; // constraint
|
||||
def->mode = comAdvanced; // visibility mode
|
||||
def->set_default_value(new ConfigOptionFloat(1)); // default
|
||||
```
|
||||
|
||||
### 3.3 Storage Layer
|
||||
|
||||
Two parallel systems:
|
||||
|
||||
**StaticPrintConfig** — compiled-in struct fields via `PRINT_CONFIG_CLASS_DEFINE` macro. Name-to-byte-offset cache. Used in the slicing engine for direct member access (performance-critical).
|
||||
|
||||
**DynamicPrintConfig** — `std::map<string, ConfigOptionUniquePtr>`. Used in GUI and for diff/apply operations.
|
||||
|
||||
Class hierarchy:
|
||||
|
||||
```
|
||||
FullPrintConfig
|
||||
├── PrintObjectConfig (~120 fields)
|
||||
├── PrintRegionConfig (~80 fields)
|
||||
└── PrintConfig
|
||||
├── MachineEnvelopeConfig (~25 fields)
|
||||
└── GCodeConfig (~80 fields)
|
||||
```
|
||||
|
||||
### 3.4 Serialization
|
||||
|
||||
- **JSON presets**: `ConfigBase::save_to_json()` / `load_from_json()` — iterates option keys, calls `opt->serialize()` to string, writes JSON key-value pairs
|
||||
- **Binary .3mf**: cereal archives via `load_option_from_archive()` / `save_option_to_archive()`
|
||||
- Both formats use the same string keys as identifiers
|
||||
|
||||
### 3.5 Invalidation
|
||||
|
||||
`Print::invalidate_state_by_config_options()` contains large `opt_key == "..."` chains that classify each changed option key into pipeline steps to invalidate:
|
||||
|
||||
```
|
||||
posSlice, posPerimeters, posInfill, posSupportMaterial,
|
||||
psGCodeExport, psSkirtBrim, psWipeTower
|
||||
```
|
||||
|
||||
### 3.6 GUI Binding
|
||||
|
||||
- `Tab.cpp` builds UI via `append_single_option_line("key_name")` — looks up `ConfigOptionDef` from `print_config_def`, auto-creates the appropriate widget
|
||||
- `ConfigManipulation.cpp` contains `toggle_print_fff_options()` — imperative logic that reads config values and toggles field visibility
|
||||
|
||||
|
||||
## 4. Proposed Solution
|
||||
|
||||
### 4.1 Architecture
|
||||
|
||||
Protobuf as schema + codegen, NOT a runtime replacement.
|
||||
|
||||
```
|
||||
┌─────────────────────┐ ┌──────────────────────────────┐
|
||||
│ src/PrintConfigs/ │ codegen │ PrintConfigDef_generated.cpp │ done
|
||||
│ *.proto │ ──────────────> │ Preset_options_generated.cpp │ done
|
||||
│ layout.yaml │ │ Invalidation_generated.cpp │ done
|
||||
│ │ │ OptionKeys_generated.cpp │ done
|
||||
└─────────────────────┘ │ PrintConfig_generated.hpp │ future
|
||||
│ TabLayout_generated.cpp │ future
|
||||
└──────────────────────────────┘
|
||||
```
|
||||
|
||||
### 4.2 Proto Schema Design
|
||||
|
||||
#### 4.2.1 Custom Field Options
|
||||
|
||||
`src/PrintConfigs/config_metadata.proto` defines custom extensions covering all `ConfigOptionDef` metadata:
|
||||
|
||||
```protobuf
|
||||
syntax = "proto3";
|
||||
import "google/protobuf/descriptor.proto";
|
||||
package orca;
|
||||
|
||||
enum ConfigMode {
|
||||
MODE_SIMPLE = 0;
|
||||
MODE_ADVANCED = 1;
|
||||
MODE_DEVELOP = 2;
|
||||
}
|
||||
|
||||
enum PresetType {
|
||||
PRESET_PRINT = 0;
|
||||
PRESET_FILAMENT = 1;
|
||||
PRESET_PRINTER = 2;
|
||||
}
|
||||
|
||||
enum InvalidationStep {
|
||||
STEP_GCODE_EXPORT = 0;
|
||||
STEP_SKIRT_BRIM = 1;
|
||||
STEP_WIPE_TOWER = 2;
|
||||
STEP_SLICE = 3;
|
||||
STEP_PERIMETERS = 4;
|
||||
STEP_INFILL = 5;
|
||||
STEP_SUPPORT = 6;
|
||||
STEP_NONE = 7;
|
||||
}
|
||||
|
||||
enum OptionListMembership {
|
||||
LIST_NONE = 0;
|
||||
LIST_EXTRUDER_OPTION_KEYS = 1;
|
||||
LIST_FILAMENT_OPTION_KEYS = 2;
|
||||
LIST_VARIANT_OPTION_KEYS = 3;
|
||||
}
|
||||
|
||||
extend google.protobuf.FieldOptions {
|
||||
// Display metadata
|
||||
string label = 50001;
|
||||
string full_label = 50002;
|
||||
string tooltip = 50003;
|
||||
string category = 50004;
|
||||
string sidetext = 50005;
|
||||
|
||||
// Numeric constraints
|
||||
double min_value = 50006;
|
||||
double max_value = 50007;
|
||||
double max_literal = 50008;
|
||||
|
||||
// UI behavior
|
||||
ConfigMode mode = 50009;
|
||||
string ratio_over = 50010;
|
||||
bool multiline = 50013;
|
||||
bool full_width = 50014;
|
||||
int32 height = 50015;
|
||||
|
||||
// Classification
|
||||
PresetType preset = 50011;
|
||||
repeated InvalidationStep invalidates = 50012;
|
||||
repeated OptionListMembership list_membership = 50018;
|
||||
|
||||
// Migration
|
||||
string legacy_name = 50016;
|
||||
|
||||
// Nullable support (for ConfigOptionFloatsNullable, etc.)
|
||||
bool is_nullable = 50017;
|
||||
|
||||
// GUI type override (e.g. "i_enum_open", "color", "f_enum_open")
|
||||
string gui_type = 50019;
|
||||
string gui_flags = 50020;
|
||||
|
||||
// Enum metadata
|
||||
string enum_keys_map_ref = 50021;
|
||||
bool no_cli = 50022;
|
||||
bool readonly = 50023;
|
||||
|
||||
// C++ codegen hints
|
||||
string co_type_hint = 50024;
|
||||
|
||||
// Default value — constructor args only (e.g. "1.0", "5000.0, 5000.0")
|
||||
// Codegen reconstructs full C++ from co_type + this value
|
||||
string default_value = 50025;
|
||||
bool has_default = 50028; // proto3 can't distinguish empty string from unset
|
||||
|
||||
// Enum values and labels
|
||||
repeated string enum_value_entries = 50026;
|
||||
repeated string enum_label_entries = 50027;
|
||||
}
|
||||
|
||||
extend google.protobuf.MessageOptions {
|
||||
// Virtual preset keys: keys that belong to this preset type in Preset.cpp
|
||||
// option lists but have no ConfigOptionDef entry (printer identity fields,
|
||||
// host/connectivity settings, filament retraction overrides, compatibility
|
||||
// flags, cross-preset keys). The codegen emits these directly into the
|
||||
// s_Preset_*_options array alongside the field-derived keys.
|
||||
// To add a virtual key: add one option line here and re-run codegen.
|
||||
repeated string virtual_preset_keys = 60001;
|
||||
}
|
||||
```
|
||||
|
||||
#### 4.2.2 Setting Files
|
||||
|
||||
Settings are split into three `.proto` files by preset type. Each setting becomes a proto field with annotations:
|
||||
|
||||
| File | Contents |
|
||||
|------|----------|
|
||||
| `src/PrintConfigs/print.proto` | ~477 print/process settings |
|
||||
| `src/PrintConfigs/filament.proto` | ~103 filament settings |
|
||||
| `src/PrintConfigs/printer.proto` | ~42 printer settings |
|
||||
|
||||
Each file also carries message-level `virtual_preset_keys` declarations (see §5.2.3).
|
||||
|
||||
Example field:
|
||||
|
||||
```protobuf
|
||||
float travel_speed = 42 [
|
||||
(label) = "Travel",
|
||||
(tooltip) = "Speed of travel which is faster and without extrusion.",
|
||||
(sidetext) = "mm/s",
|
||||
(min_value) = 1,
|
||||
(mode) = MODE_ADVANCED,
|
||||
(preset) = PRESET_PRINT,
|
||||
(has_default) = true,
|
||||
(default_value) = "200",
|
||||
(invalidates) = STEP_GCODE_EXPORT
|
||||
];
|
||||
```
|
||||
|
||||
#### 4.2.3 Virtual Preset Keys
|
||||
|
||||
The `s_Preset_*_options` vectors in `Preset.cpp` need to include keys beyond those with `ConfigOptionDef` entries — for example, printer identity fields (`printer_technology`, `printable_area`), connectivity settings (`host_type`, `print_host`), filament retraction overrides (`filament_retraction_length`, `filament_z_hop`, …), and cross-preset keys that belong to multiple preset types.
|
||||
|
||||
These are declared directly in the `.proto` message body using the `virtual_preset_keys` message option:
|
||||
|
||||
```protobuf
|
||||
message PrinterSettings {
|
||||
|
||||
// Virtual keys (not in PrintConfigDef)
|
||||
option (virtual_preset_keys) = "printer_technology";
|
||||
option (virtual_preset_keys) = "printable_area";
|
||||
option (virtual_preset_keys) = "host_type";
|
||||
option (virtual_preset_keys) = "print_host";
|
||||
// ... etc
|
||||
|
||||
// Cross-preset keys (defined in print.proto, also saved in printer presets)
|
||||
option (virtual_preset_keys) = "single_extruder_multi_material";
|
||||
option (virtual_preset_keys) = "wipe_tower_type";
|
||||
// ... etc
|
||||
|
||||
float extruder_clearance_height_to_rod = 1 [ ... ];
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
The codegen reads these and merges them (deduplicated, sorted) with the field-derived keys into the generated `s_Preset_printer_options` vector. No hand-written extender struct in `Preset.cpp` is needed.
|
||||
|
||||
#### 4.2.4 Type Mapping
|
||||
|
||||
| C++ Type | Proto Representation | Notes |
|
||||
|---|---|---|
|
||||
| `ConfigOptionFloat` | `float field = N` | |
|
||||
| `ConfigOptionInt` | `int32 field = N` | |
|
||||
| `ConfigOptionBool` | `bool field = N` | |
|
||||
| `ConfigOptionString` | `string field = N` | |
|
||||
| `ConfigOptionFloats` | `repeated float field = N` | Per-extruder vectors |
|
||||
| `ConfigOptionInts` | `repeated int32 field = N` | |
|
||||
| `ConfigOptionBools` | `repeated bool field = N` | |
|
||||
| `ConfigOptionStrings` | `repeated string field = N` | |
|
||||
| `ConfigOptionPercent` | `float field = N` | `(co_type_hint) = "coPercent"` |
|
||||
| `ConfigOptionPercents` | `repeated float field = N` | `(co_type_hint) = "coPercents"` |
|
||||
| `ConfigOptionFloatOrPercent` | `FloatOrPercent field = N` | Custom wrapper message |
|
||||
| `ConfigOptionEnum<T>` | `int32 field = N` | `(co_type_hint) = "coEnum"` + `(enum_keys_map_ref)` |
|
||||
| `ConfigOptionPoint` | `Point2D field = N` | Custom wrapper message |
|
||||
| `ConfigOptionFloatsNullable` | `repeated float field = N` | `(is_nullable) = true` |
|
||||
|
||||
#### 4.2.5 UI Layout File
|
||||
|
||||
`src/PrintConfigs/layout.yaml` declares the UI tab/page/group structure used by `Tab.cpp`. It lists field names in display order under their respective groups. The codegen will eventually use this to generate `TabLayout_generated.cpp` (future phase).
|
||||
|
||||
### 4.3 Code Generator Outputs
|
||||
|
||||
| Output | Replaces | Status |
|
||||
|---|---|---|
|
||||
| `PrintConfigDef_generated.cpp` | `init_fff_params()` body (~6000 lines) | Done |
|
||||
| `Preset_options_generated.cpp` | `s_Preset_*_options` string vectors | Done |
|
||||
| `Invalidation_generated.cpp` | `opt_key ==` chains in `Print.cpp` | Done |
|
||||
| `OptionKeys_generated.cpp` | Extruder/filament key lists | Done |
|
||||
| `PrintConfig_generated.hpp` | `PRINT_CONFIG_CLASS_DEFINE` macro blocks | Future |
|
||||
| `TabLayout_generated.cpp` | `append_single_option_line()` calls in `Tab.cpp` | Future |
|
||||
|
||||
### 4.4 CMake Integration
|
||||
|
||||
```cmake
|
||||
add_custom_command(
|
||||
OUTPUT ${GENERATED_SOURCES}
|
||||
COMMAND ${ORCA_CODEGEN_PYTHON} tools/run_codegen.py --no-validate
|
||||
DEPENDS src/PrintConfigs/*.proto src/PrintConfigs/layout.yaml tools/config_codegen.py
|
||||
)
|
||||
```
|
||||
|
||||
Generated files are **not** checked into the repo — `src/slic3r/GUI/generated/` and `config.desc` are gitignored, and every build produces them. Each build script and CI job runs `tools/run_codegen.py` before configuring; a fresh clone that goes straight to `cmake` gets them generated at configure time.
|
||||
|
||||
`tools/run_codegen.py` resolves its own toolchain (`tools/codegen_toolchain.py`), so no caller has to install anything:
|
||||
|
||||
- **protoc** — `$PROTOC`, then `PATH`, then a cached copy, then a pinned checksum-verified release downloaded into `.codegen-tools/` (also gitignored)
|
||||
- **protobuf + pyyaml** — the calling interpreter if it has them, otherwise a virtualenv under `.codegen-tools/` that the script re-execs into
|
||||
|
||||
Set `PROTOC=<path>` to build offline or against a distro protoc.
|
||||
|
||||
### 4.5 Provider Customization
|
||||
|
||||
Providers ship an overlay file alongside their existing JSON profiles:
|
||||
|
||||
```yaml
|
||||
# resources/profiles/Creality/settings_overlay.yaml
|
||||
overrides:
|
||||
travel_speed:
|
||||
max_value: 600
|
||||
default: 300
|
||||
travel_speed_z:
|
||||
mode: hidden # not relevant for this printer
|
||||
firmware_retraction:
|
||||
mode: disabled # shown but locked — firmware handles this
|
||||
custom_options:
|
||||
- key: creality_vibration_compensation
|
||||
type: bool
|
||||
label: "Vibration Compensation"
|
||||
default: true
|
||||
category: "Quality"
|
||||
mode: advanced
|
||||
gui_page: "Quality"
|
||||
gui_group: "Other"
|
||||
```
|
||||
|
||||
Custom options get field numbers > 1000 to avoid conflicts.
|
||||
|
||||
---
|
||||
|
||||
## 5. What Changes vs. What Stays
|
||||
|
||||
### Changes (generated from proto)
|
||||
|
||||
| Artifact | Current | After | Status |
|
||||
|---|---|---|---|
|
||||
| `init_fff_params()` body (~6000 lines) | Hand-written C++ | `#include` of generated file | Done |
|
||||
| `s_Preset_*_options` lists | Hand-written string vectors | Generated from `(preset)` + `virtual_preset_keys` | Done |
|
||||
| `invalidate_state_by_config_options()` | Hand-written `opt_key ==` chains | Generated map lookup | Done |
|
||||
| Extruder/filament key lists | Hand-written string vectors | Generated from `(list_membership)` | Done |
|
||||
| `PRINT_CONFIG_CLASS_DEFINE` blocks in `.hpp` | Hand-written macros | Generated from `.proto` | Future |
|
||||
| `Tab.cpp` `append_single_option_line()` layout | Hand-written per-setting calls | Generated from `layout.yaml` + `(tab_*)` annotations | Future |
|
||||
|
||||
### Stays manual (NOT generated)
|
||||
|
||||
| Component | Reason |
|
||||
|---|---|
|
||||
| Conditional visibility (`toggle_print_fff_options`) | Complex runtime logic depending on config values; cannot be declaratively expressed |
|
||||
| Custom GUI rendering (`Field.cpp`, `OptionsGroup.cpp`) | Case-specific widget behavior (color pickers, special enums) |
|
||||
| `handle_legacy()` | Migration logic; partially automatable via `(legacy_name)` but complex transforms stay manual |
|
||||
| Enum C++ maps (top of `PrintConfig.cpp`) | Could eventually generate from proto enums |
|
||||
|
||||
---
|
||||
|
||||
## 6. Developer Workflow
|
||||
|
||||
### Adding a new setting
|
||||
|
||||
1. Add a field to the appropriate `.proto` file (`print.proto`, `filament.proto`, or `printer.proto`) with all relevant annotations
|
||||
2. Run `python tools/run_codegen.py`
|
||||
3. Commit the `.proto` change — the generated files are gitignored build output, never committed
|
||||
|
||||
### Adding a virtual preset key
|
||||
|
||||
Virtual keys are preset option keys that have no `ConfigOptionDef` (printer identity fields, connectivity settings, etc.) or that exist in one preset type's proto but also need to appear in another preset's options list.
|
||||
|
||||
1. Add `option (virtual_preset_keys) = "key_name";` in the appropriate `.proto` message body
|
||||
2. Run `python tools/run_codegen.py`
|
||||
|
||||
### Running the codegen pipeline manually
|
||||
|
||||
```bash
|
||||
# Full pipeline: compile protos → generate C++ → validate
|
||||
python tools/run_codegen.py
|
||||
|
||||
# Validate only (check generated files are up to date)
|
||||
python tools/run_codegen.py --validate-only
|
||||
|
||||
# Inject invalidation/list-membership annotations from Print.cpp / PrintConfig.cpp
|
||||
python tools/annotate_protos.py [--dry-run]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. File Layout
|
||||
|
||||
```
|
||||
src/PrintConfigs/
|
||||
├── config_metadata.proto # Custom field/message option extensions
|
||||
├── layout.yaml # UI tab/page/group structure (Tab.cpp layout)
|
||||
├── print.proto # ~477 print/process settings
|
||||
├── filament.proto # ~103 filament settings
|
||||
└── printer.proto # ~42 printer/machine settings
|
||||
|
||||
tools/
|
||||
├── run_codegen.py # Full pipeline script — the entry point everything calls
|
||||
├── codegen_toolchain.py # Resolves protoc / protobuf / pyyaml
|
||||
├── config_codegen.py # Proto descriptor → C++ codegen
|
||||
├── config_metadata.py # Reads the orca.* option extensions from the descriptor set
|
||||
└── validate_codegen.py # Generated vs original validation
|
||||
|
||||
src/slic3r/GUI/generated/ # gitignored — regenerated by every build
|
||||
├── PrintConfigDef_generated.cpp # init_fff_params() body — #included by PrintConfig.cpp
|
||||
├── Preset_options_generated.cpp # s_Preset_*_options — #included by Preset.cpp
|
||||
├── Invalidation_generated.cpp # s_print_steps_map + s_object_steps_map — #included by Print.cpp
|
||||
├── OptionKeys_generated.cpp # s_extruder_option_keys, s_filament_option_keys
|
||||
└── TabLayout_generated.cpp # Tab page/group layout from layout.yaml
|
||||
|
||||
.codegen-tools/ # gitignored — downloaded protoc + bootstrap virtualenv
|
||||
|
||||
cmake/modules/
|
||||
└── ConfigCodegen.cmake # CMake integration (build-time regeneration)
|
||||
|
||||
docs/
|
||||
└── PrintConfig_Codegen_Design.md # This design document
|
||||
```
|
||||
@@ -393,6 +393,9 @@ modules:
|
||||
- type: dir
|
||||
path: ../../localization
|
||||
dest: localization
|
||||
- type: dir
|
||||
path: ../../tools
|
||||
dest: tools
|
||||
|
||||
- type: file
|
||||
path: ../../CMakeLists.txt
|
||||
|
||||
174
src/PrintConfigs/config_metadata.proto
Normal file
174
src/PrintConfigs/config_metadata.proto
Normal file
@@ -0,0 +1,174 @@
|
||||
// OrcaSlicer Print Config - Custom Field Options
|
||||
// This file defines the metadata annotations used on all config setting fields.
|
||||
// These annotations are read by the codegen tool to produce:
|
||||
// - PrintConfigDef_generated.cpp (init_fff_params replacement)
|
||||
// - PrintConfig_generated.hpp (struct definitions)
|
||||
// - Preset_options_generated.cpp (preset option lists)
|
||||
// - Invalidation_generated.cpp (invalidation map)
|
||||
// - OptionKeys_generated.cpp (extruder/filament/variant key lists)
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
import "google/protobuf/descriptor.proto";
|
||||
|
||||
package orca;
|
||||
|
||||
// --- Enums for annotations ---
|
||||
|
||||
enum ConfigMode {
|
||||
MODE_SIMPLE = 0;
|
||||
MODE_ADVANCED = 1;
|
||||
MODE_DEVELOP = 2;
|
||||
MODE_EXPERT = 3;
|
||||
}
|
||||
|
||||
enum PresetType {
|
||||
PRESET_PRINT = 0;
|
||||
PRESET_FILAMENT = 1;
|
||||
PRESET_PRINTER = 2;
|
||||
}
|
||||
|
||||
enum InvalidationStep {
|
||||
STEP_GCODE_EXPORT = 0;
|
||||
STEP_SKIRT_BRIM = 1;
|
||||
STEP_WIPE_TOWER = 2;
|
||||
STEP_SLICE = 3;
|
||||
STEP_PERIMETERS = 4;
|
||||
STEP_INFILL = 5;
|
||||
STEP_SUPPORT = 6;
|
||||
STEP_NONE = 7;
|
||||
}
|
||||
|
||||
enum OptionListMembership {
|
||||
LIST_NONE = 0;
|
||||
LIST_EXTRUDER_OPTION_KEYS = 1;
|
||||
LIST_FILAMENT_OPTION_KEYS = 2;
|
||||
LIST_VARIANT_OPTION_KEYS = 3;
|
||||
}
|
||||
|
||||
// C++ co_type override values, used when the proto wire type (float/int32) is
|
||||
// ambiguous about the real ConfigOption class. Each value name is the coXXX
|
||||
// identifier the codegen emits, and must have a matching entry in
|
||||
// hint_class_map (config_codegen.py). Making this an enum lets protoc reject a
|
||||
// typo'd hint (e.g. coFloar) at compile time instead of silently mis-typing a
|
||||
// setting. To add a new override: add a value here AND its hint_class_map entry.
|
||||
enum CoTypeHint {
|
||||
CO_TYPE_HINT_UNSET = 0;
|
||||
coPercent = 1;
|
||||
coPercents = 2;
|
||||
coEnum = 3;
|
||||
coEnums = 4;
|
||||
}
|
||||
|
||||
// Mirrors ConfigOptionDef::GUIType in src/libslic3r/Config.hpp. The codegen
|
||||
// emits ConfigOptionDef::GUIType::<name>, so each value name must match a C++
|
||||
// enumerator there. As an enum, a typo'd gui_type fails at protoc time.
|
||||
enum GuiType {
|
||||
GUI_TYPE_UNSET = 0;
|
||||
i_enum_open = 1;
|
||||
f_enum_open = 2;
|
||||
color = 3;
|
||||
select_open = 4;
|
||||
slider = 5;
|
||||
legend = 6;
|
||||
one_string = 7;
|
||||
plugin_picker = 8;
|
||||
}
|
||||
|
||||
// --- Custom field options ---
|
||||
|
||||
extend google.protobuf.FieldOptions {
|
||||
// Display metadata
|
||||
string label = 50001;
|
||||
string full_label = 50002;
|
||||
string tooltip = 50003;
|
||||
string category = 50004;
|
||||
string sidetext = 50005;
|
||||
|
||||
// Numeric constraints
|
||||
double min_value = 50006;
|
||||
double max_value = 50007;
|
||||
double max_literal = 50008;
|
||||
|
||||
// UI behavior
|
||||
ConfigMode mode = 50009;
|
||||
string ratio_over = 50010;
|
||||
bool multiline = 50013;
|
||||
bool full_width = 50014;
|
||||
int32 height = 50015;
|
||||
|
||||
// Classification
|
||||
PresetType preset = 50011;
|
||||
repeated InvalidationStep invalidates = 50012;
|
||||
repeated OptionListMembership list_membership = 50018;
|
||||
|
||||
// Migration
|
||||
string legacy_name = 50016;
|
||||
|
||||
// Nullable support (for ConfigOptionFloatsNullable, etc.)
|
||||
bool is_nullable = 50017;
|
||||
|
||||
// GUI type override (e.g. i_enum_open, color, f_enum_open)
|
||||
GuiType gui_type = 50019;
|
||||
string gui_flags = 50020;
|
||||
|
||||
// Enum metadata (key map reference for C++ enum binding)
|
||||
string enum_keys_map_ref = 50021;
|
||||
|
||||
// Whether this option should not appear in CLI
|
||||
bool no_cli = 50022;
|
||||
|
||||
// ConfigOptionDef::readonly
|
||||
bool readonly = 50023;
|
||||
|
||||
// Override the auto-detected co_type (e.g. coPercent, coEnum)
|
||||
// Used when proto type (float, int32) is ambiguous
|
||||
CoTypeHint co_type_hint = 50024;
|
||||
|
||||
// Default value — constructor args only (e.g. "1.0", "5000.0, 5000.0")
|
||||
// Codegen reconstructs full C++ from co_type + this value
|
||||
string default_value = 50025;
|
||||
|
||||
// Whether a default value is present (needed because proto3 can't
|
||||
// distinguish "set to empty string" from "not set")
|
||||
bool has_default = 50028;
|
||||
|
||||
// Enum values (string keys for coEnum options)
|
||||
repeated string enum_value_entries = 50026;
|
||||
|
||||
// Enum labels (display names for enum values)
|
||||
repeated string enum_label_entries = 50027;
|
||||
|
||||
// UI layout: where this option appears in Tab.cpp
|
||||
// tab_type = "Print" | "Filament" | "Printer"
|
||||
// tab_page = page title as shown in the UI (e.g. "Quality")
|
||||
// tab_optgroup = optgroup title within that page (e.g. "Layer height")
|
||||
string tab_type = 50029;
|
||||
string tab_page = 50030;
|
||||
string tab_optgroup = 50031;
|
||||
}
|
||||
|
||||
// --- Message-level options ---
|
||||
|
||||
extend google.protobuf.MessageOptions {
|
||||
// Virtual keys: preset option keys that belong to this preset type but have
|
||||
// no ConfigOptionDef entry (printer metadata, host settings, compatibility
|
||||
// flags, filament retraction overrides, cross-preset keys, etc.).
|
||||
// The codegen emits these directly into s_Preset_*_options alongside the
|
||||
// field-derived keys, so no hand-written extender is needed in Preset.cpp.
|
||||
repeated string virtual_preset_keys = 60001;
|
||||
}
|
||||
|
||||
// --- Wrapper messages for complex types ---
|
||||
|
||||
// Represents ConfigOptionFloatOrPercent
|
||||
message FloatOrPercent {
|
||||
double value = 1;
|
||||
bool percent = 2;
|
||||
}
|
||||
|
||||
// Represents ConfigOptionPoint (Vec2d)
|
||||
message Point2D {
|
||||
double x = 1;
|
||||
double y = 2;
|
||||
}
|
||||
2268
src/PrintConfigs/filament.proto
Normal file
2268
src/PrintConfigs/filament.proto
Normal file
File diff suppressed because it is too large
Load Diff
687
src/PrintConfigs/layout.yaml
Normal file
687
src/PrintConfigs/layout.yaml
Normal file
@@ -0,0 +1,687 @@
|
||||
tabs:
|
||||
- name: TabPrint
|
||||
pages:
|
||||
- name: "Quality"
|
||||
icon: "custom-gcode_quality"
|
||||
groups:
|
||||
- name: "Layer height"
|
||||
fields:
|
||||
- layer_height
|
||||
- initial_layer_print_height
|
||||
- name: "Line width"
|
||||
fields:
|
||||
- line_width
|
||||
- initial_layer_line_width
|
||||
- outer_wall_line_width
|
||||
- inner_wall_line_width
|
||||
- top_surface_line_width
|
||||
- sparse_infill_line_width
|
||||
- internal_solid_infill_line_width
|
||||
- bridge_line_width: quality_settings_line_width#bridge
|
||||
- support_line_width
|
||||
- name: "Seam"
|
||||
fields:
|
||||
- seam_position
|
||||
- staggered_inner_seams
|
||||
- seam_gap
|
||||
- seam_slope_type
|
||||
- seam_slope_conditional
|
||||
- scarf_angle_threshold
|
||||
- scarf_overhang_threshold
|
||||
- scarf_joint_speed
|
||||
- seam_slope_start_height
|
||||
- seam_slope_entire_loop
|
||||
- seam_slope_min_length
|
||||
- seam_slope_steps
|
||||
- scarf_joint_flow_ratio
|
||||
- seam_slope_inner_walls
|
||||
- role_based_wipe_speed
|
||||
- wipe_speed
|
||||
- wipe_on_loops
|
||||
- wipe_before_external_loop
|
||||
- name: "Precision"
|
||||
fields:
|
||||
- slice_closing_radius
|
||||
- resolution
|
||||
- enable_arc_fitting
|
||||
- xy_hole_compensation
|
||||
- xy_contour_compensation
|
||||
- elefant_foot_compensation
|
||||
- elefant_foot_layers_density
|
||||
- elefant_foot_compensation_layers
|
||||
- precise_outer_wall
|
||||
- precise_z_height
|
||||
- hole_to_polyhole
|
||||
- hole_to_polyhole_threshold
|
||||
- hole_to_polyhole_twisted
|
||||
- hole_to_polyhole_max_edges
|
||||
- name: "Ironing"
|
||||
fields:
|
||||
- ironing_type
|
||||
- ironing_pattern
|
||||
- ironing_flow
|
||||
- ironing_spacing
|
||||
- ironing_inset
|
||||
- ironing_angle
|
||||
- ironing_angle_fixed
|
||||
- name: "Wall generator"
|
||||
fields:
|
||||
- wall_generator
|
||||
- wall_transition_angle
|
||||
- wall_transition_filter_deviation
|
||||
- wall_transition_length
|
||||
- wall_distribution_count
|
||||
- initial_layer_min_bead_width
|
||||
- min_bead_width
|
||||
- min_feature_size
|
||||
- min_length_factor
|
||||
- wall_maximum_resolution
|
||||
- wall_maximum_deviation
|
||||
- name: "Walls and surfaces"
|
||||
fields:
|
||||
- wall_sequence
|
||||
- is_infill_first
|
||||
- wall_direction
|
||||
- print_flow_ratio
|
||||
- top_solid_infill_flow_ratio
|
||||
- bottom_solid_infill_flow_ratio
|
||||
- set_other_flow_ratios
|
||||
- first_layer_flow_ratio
|
||||
- outer_wall_flow_ratio
|
||||
- inner_wall_flow_ratio
|
||||
- overhang_flow_ratio
|
||||
- sparse_infill_flow_ratio
|
||||
- internal_solid_infill_flow_ratio
|
||||
- gap_fill_flow_ratio
|
||||
- support_flow_ratio
|
||||
- support_interface_flow_ratio
|
||||
- only_one_wall_first_layer
|
||||
- only_one_wall_top
|
||||
- min_width_top_surface
|
||||
- reduce_crossing_wall
|
||||
- max_travel_detour_distance
|
||||
- small_area_infill_flow_compensation
|
||||
- small_area_infill_flow_compensation_model
|
||||
- name: "Bridging"
|
||||
fields:
|
||||
- bridge_flow
|
||||
- internal_bridge_flow
|
||||
- bridge_density
|
||||
- internal_bridge_density
|
||||
- thick_bridges
|
||||
- thick_internal_bridges
|
||||
- enable_extra_bridge_layer
|
||||
- dont_filter_internal_bridges
|
||||
- counterbore_hole_bridging
|
||||
- name: "Overhangs"
|
||||
fields:
|
||||
- detect_overhang_wall
|
||||
- make_overhang_printable
|
||||
- make_overhang_printable_angle
|
||||
- make_overhang_printable_hole_size
|
||||
- extra_perimeters_on_overhangs
|
||||
- overhang_reverse
|
||||
- overhang_reverse_internal_only
|
||||
- overhang_reverse_threshold
|
||||
- name: "Strength"
|
||||
icon: "custom-gcode_strength"
|
||||
groups:
|
||||
- name: "Walls"
|
||||
fields:
|
||||
- wall_loops
|
||||
- alternate_extra_wall
|
||||
- detect_thin_wall
|
||||
- name: "Top/bottom shells"
|
||||
fields:
|
||||
- top_shell_layers
|
||||
- top_shell_thickness
|
||||
- top_surface_density
|
||||
- top_surface_pattern
|
||||
- top_layer_direction
|
||||
- top_surface_expansion: strength_settings_top_bottom_shells#surface-expansion
|
||||
- top_surface_expansion_margin: strength_settings_top_bottom_shells#surface-expansion-margin
|
||||
- top_surface_expansion_direction: strength_settings_top_bottom_shells#surface-expansion-direction
|
||||
- bottom_shell_layers
|
||||
- bottom_shell_thickness
|
||||
- bottom_surface_density
|
||||
- bottom_surface_pattern
|
||||
- bottom_layer_direction
|
||||
- center_of_surface_pattern: strength_settings_top_bottom_shells#center-surface-pattern-on
|
||||
- anisotropic_surfaces: strength_settings_top_bottom_shells#anisotropic-surfaces
|
||||
- top_bottom_infill_wall_overlap
|
||||
- name: "Infill"
|
||||
fields:
|
||||
- sparse_infill_density
|
||||
- fill_multiline
|
||||
- sparse_infill_pattern
|
||||
- infill_direction
|
||||
- sparse_infill_rotate_template
|
||||
- skin_infill_density
|
||||
- skeleton_infill_density
|
||||
- infill_lock_depth
|
||||
- skin_infill_depth
|
||||
- skin_infill_line_width
|
||||
- skeleton_infill_line_width
|
||||
- symmetric_infill_y_axis
|
||||
- infill_shift_step
|
||||
- lateral_lattice_angle_1
|
||||
- lateral_lattice_angle_2
|
||||
- infill_overhang_angle
|
||||
- infill_anchor_max
|
||||
- infill_anchor
|
||||
- internal_solid_infill_pattern
|
||||
- solid_infill_direction
|
||||
- solid_infill_rotate_template
|
||||
- gap_fill_target
|
||||
- filter_out_gap_fill
|
||||
- separated_infills: strength_settings_infill#separated-infills
|
||||
- infill_wall_overlap
|
||||
- lightning_overhang_angle: strength_settings_patterns#lightning
|
||||
- lightning_prune_angle: strength_settings_patterns#lightning
|
||||
- lightning_straightening_angle: strength_settings_patterns#lightning
|
||||
- name: "Advanced"
|
||||
fields:
|
||||
- align_infill_direction_to_model
|
||||
- extra_solid_infills
|
||||
- bridge_angle
|
||||
- internal_bridge_angle
|
||||
- relative_bridge_angle: strength_settings_advanced#relative-bridge-angle
|
||||
- minimum_sparse_infill_area
|
||||
- infill_combination
|
||||
- infill_combination_max_layer_height
|
||||
- detect_narrow_internal_solid_infill
|
||||
- ensure_vertical_shell_thickness
|
||||
- name: "Speed"
|
||||
icon: "custom-gcode_speed"
|
||||
groups:
|
||||
- name: "First layer speed"
|
||||
fields:
|
||||
- initial_layer_speed
|
||||
- initial_layer_infill_speed
|
||||
- initial_layer_travel_speed
|
||||
- slow_down_layers
|
||||
- name: "Other layers speed"
|
||||
fields:
|
||||
- outer_wall_speed
|
||||
- inner_wall_speed
|
||||
- small_perimeter_speed
|
||||
- small_perimeter_threshold
|
||||
- sparse_infill_speed
|
||||
- internal_solid_infill_speed
|
||||
- top_surface_speed
|
||||
- gap_infill_speed
|
||||
- ironing_speed
|
||||
- support_speed
|
||||
- support_interface_speed
|
||||
- small_support_perimeter_speed
|
||||
- small_support_perimeter_threshold
|
||||
- name: "Overhang speed"
|
||||
fields:
|
||||
- enable_overhang_speed
|
||||
- slowdown_for_curled_perimeters
|
||||
- [overhang_1_4_speed, overhang_2_4_speed, overhang_3_4_speed, overhang_4_4_speed]
|
||||
- [bridge_speed, internal_bridge_speed]
|
||||
- name: "Travel speed"
|
||||
fields:
|
||||
- travel_speed
|
||||
- name: "Acceleration"
|
||||
fields:
|
||||
- default_acceleration
|
||||
- outer_wall_acceleration
|
||||
- inner_wall_acceleration
|
||||
- bridge_acceleration
|
||||
- sparse_infill_acceleration
|
||||
- internal_solid_infill_acceleration
|
||||
- initial_layer_acceleration
|
||||
- initial_layer_travel_acceleration
|
||||
- top_surface_acceleration
|
||||
- travel_acceleration
|
||||
- accel_to_decel_enable
|
||||
- accel_to_decel_factor
|
||||
- name: "Jerk(XY)"
|
||||
fields:
|
||||
- default_junction_deviation
|
||||
- default_jerk
|
||||
- outer_wall_jerk
|
||||
- inner_wall_jerk
|
||||
- infill_jerk
|
||||
- top_surface_jerk
|
||||
- initial_layer_jerk
|
||||
- initial_layer_travel_jerk
|
||||
- travel_jerk
|
||||
- name: "Advanced"
|
||||
fields:
|
||||
- max_volumetric_extrusion_rate_slope
|
||||
- max_volumetric_extrusion_rate_slope_segment_length
|
||||
- extrusion_rate_smoothing_external_perimeter_only
|
||||
- name: "Support"
|
||||
icon: "custom-gcode_support"
|
||||
groups:
|
||||
- name: "Support"
|
||||
fields:
|
||||
- enable_support
|
||||
- support_type
|
||||
- support_style
|
||||
- support_threshold_angle
|
||||
- support_threshold_overlap
|
||||
- raft_first_layer_density
|
||||
- raft_first_layer_expansion
|
||||
- support_on_build_plate_only
|
||||
- support_critical_regions_only
|
||||
- support_remove_small_overhang
|
||||
- name: "Raft"
|
||||
fields:
|
||||
- raft_layers
|
||||
- raft_contact_distance
|
||||
- name: "Support filament"
|
||||
fields:
|
||||
- support_filament
|
||||
- support_interface_filament
|
||||
- support_interface_not_for_body
|
||||
- name: "Support ironing"
|
||||
fields:
|
||||
- support_ironing
|
||||
- support_ironing_pattern
|
||||
- support_ironing_flow
|
||||
- support_ironing_spacing
|
||||
- name: "Advanced"
|
||||
fields:
|
||||
- support_top_z_distance
|
||||
- support_bottom_z_distance
|
||||
- tree_support_wall_count
|
||||
- support_base_pattern
|
||||
- support_base_pattern_spacing
|
||||
- support_angle
|
||||
- support_interface_top_layers
|
||||
- support_interface_bottom_layers
|
||||
- support_interface_pattern
|
||||
- support_interface_spacing
|
||||
- support_bottom_interface_spacing
|
||||
- support_expansion
|
||||
- support_object_xy_distance
|
||||
- support_object_first_layer_gap
|
||||
- bridge_no_support
|
||||
- max_bridge_length
|
||||
- independent_support_layer_height
|
||||
- name: "Tree supports"
|
||||
fields:
|
||||
- tree_support_tip_diameter
|
||||
- tree_support_branch_distance
|
||||
- tree_support_branch_distance_organic
|
||||
- tree_support_top_rate
|
||||
- tree_support_branch_diameter
|
||||
- tree_support_branch_diameter_organic
|
||||
- tree_support_branch_diameter_angle
|
||||
- tree_support_branch_angle
|
||||
- tree_support_branch_angle_organic
|
||||
- tree_support_angle_slow
|
||||
- tree_support_auto_brim
|
||||
- tree_support_brim_width
|
||||
- name: "Multimaterial"
|
||||
icon: "custom-gcode_multi_material"
|
||||
groups:
|
||||
- name: "Prime tower"
|
||||
fields:
|
||||
- enable_prime_tower
|
||||
- prime_tower_skip_points
|
||||
- enable_tower_interface_features
|
||||
- enable_tower_interface_cooldown_during_tower
|
||||
- prime_tower_enable_framework
|
||||
- prime_tower_width
|
||||
- prime_volume
|
||||
- prime_tower_brim_width
|
||||
- prime_tower_infill_gap
|
||||
- wipe_tower_rotation_angle
|
||||
- wipe_tower_bridging
|
||||
- wipe_tower_extra_spacing
|
||||
- wipe_tower_extra_flow
|
||||
- wipe_tower_max_purge_speed
|
||||
- wipe_tower_wall_type
|
||||
- wipe_tower_cone_angle
|
||||
- wipe_tower_extra_rib_length
|
||||
- wipe_tower_rib_width
|
||||
- wipe_tower_fillet_wall
|
||||
- wipe_tower_no_sparse_layers
|
||||
- single_extruder_multi_material_priming
|
||||
- name: "Filament for Features"
|
||||
fields:
|
||||
- wall_filament
|
||||
- sparse_infill_filament
|
||||
- solid_infill_filament
|
||||
- wipe_tower_filament
|
||||
- name: "Ooze prevention"
|
||||
fields:
|
||||
- ooze_prevention
|
||||
- standby_temperature_delta
|
||||
- preheat_time
|
||||
- preheat_steps
|
||||
- name: "Flush options"
|
||||
fields:
|
||||
- flush_into_infill
|
||||
- flush_into_objects
|
||||
- flush_into_support
|
||||
- name: "Advanced"
|
||||
fields:
|
||||
- interlocking_beam
|
||||
- toolchange_ordering: multimaterial_settings_advanced#toolchange-ordering
|
||||
- interface_shells
|
||||
- mmu_segmented_region_max_width
|
||||
- mmu_segmented_region_interlocking_depth
|
||||
- interlocking_beam_width
|
||||
- interlocking_orientation
|
||||
- interlocking_beam_layer_count
|
||||
- interlocking_depth
|
||||
- interlocking_boundary_avoidance
|
||||
- name: "Others"
|
||||
icon: "custom-gcode_other"
|
||||
groups:
|
||||
- name: "Skirt"
|
||||
fields:
|
||||
- skirt_loops
|
||||
- skirt_type
|
||||
- min_skirt_length
|
||||
- skirt_distance
|
||||
- skirt_start_angle
|
||||
- skirt_speed
|
||||
- skirt_height
|
||||
- draft_shield
|
||||
- single_loop_draft_shield
|
||||
- name: "Brim"
|
||||
fields:
|
||||
- brim_type
|
||||
- brim_width
|
||||
- brim_object_gap
|
||||
- brim_flow_ratio
|
||||
- brim_use_efc_outline
|
||||
- combine_brims
|
||||
- brim_ears_max_angle
|
||||
- brim_ears_detection_length
|
||||
- name: "Special mode"
|
||||
fields:
|
||||
- slicing_mode
|
||||
- print_sequence
|
||||
- print_order
|
||||
- spiral_mode
|
||||
- spiral_mode_smooth
|
||||
- spiral_mode_max_xy_smoothing
|
||||
- spiral_starting_flow_ratio
|
||||
- spiral_finishing_flow_ratio
|
||||
- timelapse_type
|
||||
- enable_wrapping_detection
|
||||
- name: "Fuzzy Skin"
|
||||
fields:
|
||||
- fuzzy_skin
|
||||
- fuzzy_skin_mode
|
||||
- fuzzy_skin_noise_type
|
||||
- fuzzy_skin_point_distance
|
||||
- fuzzy_skin_thickness
|
||||
- fuzzy_skin_scale
|
||||
- fuzzy_skin_octaves
|
||||
- fuzzy_skin_persistence
|
||||
- fuzzy_skin_first_layer
|
||||
- name: "G-code output"
|
||||
fields:
|
||||
- reduce_infill_retraction
|
||||
- gcode_add_line_number
|
||||
- gcode_comments
|
||||
- gcode_label_objects
|
||||
- exclude_object
|
||||
- filename_format
|
||||
- name: "Change extrusion role G-code" # HOOK
|
||||
fields:
|
||||
- process_change_extrusion_role_gcode
|
||||
- name: "Post-processing Scripts"
|
||||
fields:
|
||||
- post_process
|
||||
- name: "Notes"
|
||||
fields:
|
||||
- notes
|
||||
- name: TabFilament
|
||||
pages:
|
||||
- name: "Filament"
|
||||
icon: "custom-gcode_filament"
|
||||
groups:
|
||||
- name: "Basic information" # HOOK
|
||||
fields:
|
||||
- filament_type
|
||||
- filament_vendor
|
||||
- filament_soluble
|
||||
- filament_is_support
|
||||
- filament_change_length
|
||||
- required_nozzle_HRC
|
||||
- default_filament_colour
|
||||
- filament_diameter
|
||||
- filament_adhesiveness_category
|
||||
- filament_density
|
||||
- filament_shrink
|
||||
- filament_shrinkage_compensation_z
|
||||
- filament_cost
|
||||
- temperature_vitrification
|
||||
- idle_temperature
|
||||
- [nozzle_temperature_range_low, nozzle_temperature_range_high]
|
||||
- name: "Flow ratio and Pressure Advance"
|
||||
fields:
|
||||
- pellet_flow_coefficient
|
||||
- filament_flow_ratio
|
||||
- enable_pressure_advance
|
||||
- pressure_advance
|
||||
- adaptive_pressure_advance
|
||||
- adaptive_pressure_advance_overhangs
|
||||
- adaptive_pressure_advance_bridges
|
||||
- adaptive_pressure_advance_model
|
||||
- name: "Print chamber temperature"
|
||||
fields:
|
||||
- activate_chamber_temp_control
|
||||
- chamber_temperature
|
||||
- name: "Print temperature"
|
||||
fields:
|
||||
- [nozzle_temperature_initial_layer, nozzle_temperature]
|
||||
- name: "Bed temperature"
|
||||
fields:
|
||||
- [supertack_plate_temp_initial_layer, supertack_plate_temp]
|
||||
- [cool_plate_temp_initial_layer, cool_plate_temp]
|
||||
- [textured_cool_plate_temp_initial_layer, textured_cool_plate_temp]
|
||||
- [eng_plate_temp_initial_layer, eng_plate_temp]
|
||||
- [hot_plate_temp_initial_layer, hot_plate_temp]
|
||||
- [textured_plate_temp_initial_layer, textured_plate_temp]
|
||||
- name: "Volumetric speed limitation"
|
||||
fields:
|
||||
- filament_adaptive_volumetric_speed
|
||||
- filament_max_volumetric_speed
|
||||
- name: "Cooling"
|
||||
icon: "custom-gcode_cooling_fan"
|
||||
groups:
|
||||
- name: "Cooling for specific layer"
|
||||
fields:
|
||||
- close_fan_the_first_x_layers
|
||||
- full_fan_speed_layer
|
||||
- initial_layer_fan_speed: material_cooling#first-layer-fan-speed
|
||||
- name: "Part cooling fan"
|
||||
fields:
|
||||
- [fan_min_speed, fan_cooling_layer_time]
|
||||
- [fan_max_speed, slow_down_layer_time]
|
||||
- reduce_fan_stop_start_freq
|
||||
- slow_down_for_layer_cooling
|
||||
- dont_slow_down_outer_wall
|
||||
- slow_down_min_speed
|
||||
- enable_overhang_bridge_fan
|
||||
- overhang_fan_threshold
|
||||
- overhang_fan_speed
|
||||
- internal_bridge_fan_speed
|
||||
- support_material_interface_fan_speed
|
||||
- ironing_fan_speed
|
||||
- name: "Auxiliary part cooling fan"
|
||||
fields:
|
||||
- additional_cooling_fan_speed
|
||||
- name: "Exhaust fan"
|
||||
fields:
|
||||
- activate_air_filtration
|
||||
- [activate_air_filtration_during_print, during_print_exhaust_fan_speed]
|
||||
- [activate_air_filtration_on_completion, complete_print_exhaust_fan_speed]
|
||||
- name: "Advanced"
|
||||
icon: "custom-gcode_advanced"
|
||||
groups:
|
||||
- name: "Filament start G-code" # HOOK
|
||||
fields:
|
||||
- filament_start_gcode
|
||||
- name: "Change extrusion role G-code" # HOOK
|
||||
fields:
|
||||
- filament_change_extrusion_role_gcode
|
||||
- name: "Filament end G-code" # HOOK
|
||||
fields:
|
||||
- filament_end_gcode
|
||||
- name: "Multimaterial"
|
||||
icon: "custom-gcode_multi_material"
|
||||
groups:
|
||||
- name: "Wipe tower parameters"
|
||||
fields:
|
||||
- filament_minimal_purge_on_wipe_tower
|
||||
- filament_tower_interface_pre_extrusion_dist
|
||||
- filament_tower_interface_pre_extrusion_length
|
||||
- filament_tower_ironing_area
|
||||
- filament_tower_interface_purge_volume
|
||||
- filament_tower_interface_print_temp
|
||||
- name: "Multi Filament"
|
||||
fields:
|
||||
- long_retractions_when_ec
|
||||
- retraction_distances_when_ec
|
||||
- name: "Tool change parameters with single extruder MM printers"
|
||||
fields:
|
||||
- filament_loading_speed_start
|
||||
- filament_loading_speed
|
||||
- filament_unloading_speed_start
|
||||
- filament_unloading_speed
|
||||
- filament_toolchange_delay
|
||||
- filament_cooling_moves
|
||||
- filament_cooling_initial_speed
|
||||
- filament_cooling_final_speed
|
||||
- filament_stamping_loading_speed
|
||||
- filament_stamping_distance
|
||||
- filament_ramming_parameters # HOOK
|
||||
- name: "Tool change parameters with multi extruder MM printers"
|
||||
fields:
|
||||
- filament_multitool_ramming
|
||||
- filament_multitool_ramming_volume
|
||||
- filament_multitool_ramming_flow
|
||||
- name: "Dependencies"
|
||||
icon: "advanced"
|
||||
groups:
|
||||
- name: "Compatible printers"
|
||||
fields:
|
||||
- compatible_printers # HOOK
|
||||
- compatible_printers_condition
|
||||
- name: "Compatible process profiles"
|
||||
fields:
|
||||
- compatible_prints # HOOK
|
||||
- compatible_prints_condition
|
||||
- name: "Notes"
|
||||
icon: "custom-gcode_note"
|
||||
groups:
|
||||
- name: "Notes"
|
||||
fields:
|
||||
- filament_notes
|
||||
- name: TabPrinter
|
||||
pages:
|
||||
- name: "Basic information"
|
||||
icon: "custom-gcode_object-info"
|
||||
groups:
|
||||
- name: "Printable space"
|
||||
icon: "param_printable_space"
|
||||
hook: true
|
||||
- name: "Advanced"
|
||||
icon: "param_advanced"
|
||||
hook: true
|
||||
- name: "Cooling Fan"
|
||||
icon: "param_cooling_fan"
|
||||
hook: true
|
||||
- name: "Extruder Clearance"
|
||||
icon: "param_extruder_clearance"
|
||||
fields:
|
||||
- extruder_clearance_radius: printer_basic_information_extruder_clearance#radius
|
||||
- extruder_clearance_height_to_rod: printer_basic_information_extruder_clearance#height-to-rod
|
||||
- extruder_clearance_height_to_lid: printer_basic_information_extruder_clearance#height-to-lid
|
||||
- name: "Adaptive bed mesh"
|
||||
icon: "param_adaptive_mesh"
|
||||
fields:
|
||||
- bed_mesh_min: printer_basic_information_adaptive_bed_mesh#bed-mesh
|
||||
- bed_mesh_max: printer_basic_information_adaptive_bed_mesh#bed-mesh
|
||||
- bed_mesh_probe_distance: printer_basic_information_adaptive_bed_mesh#probe-point-distance
|
||||
- adaptive_bed_mesh_margin: printer_basic_information_adaptive_bed_mesh#mesh-margin
|
||||
- name: "Accessory"
|
||||
icon: "param_accessory"
|
||||
fields:
|
||||
- nozzle_type: printer_basic_information_accessory#nozzle-type
|
||||
- nozzle_hrc: printer_basic_information_accessory#nozzle-hrc
|
||||
- auxiliary_fan: printer_basic_information_accessory#auxiliary-part-cooling-fan
|
||||
- support_chamber_temp_control: printer_basic_information_accessory#support-controlling-chamber-temperature
|
||||
- support_air_filtration: printer_basic_information_accessory#support-air-filtration
|
||||
- name: "Machine G-code"
|
||||
icon: "custom-gcode_gcode"
|
||||
groups:
|
||||
- name: "File header G-code"
|
||||
icon: "param_gcode"
|
||||
gcode: true
|
||||
fields:
|
||||
- file_start_gcode: ""
|
||||
- name: "Machine start G-code"
|
||||
icon: "param_gcode"
|
||||
gcode: true
|
||||
fields:
|
||||
- machine_start_gcode: printer_machine_gcode#machine-start-g-code
|
||||
- name: "Machine end G-code"
|
||||
icon: "param_gcode"
|
||||
gcode: true
|
||||
fields:
|
||||
- machine_end_gcode: printer_machine_gcode#machine-end-g-code
|
||||
- name: "Printing by object G-code"
|
||||
icon: "param_gcode"
|
||||
gcode: true
|
||||
fields:
|
||||
- printing_by_object_gcode: printer_machine_gcode#between-object-g-code
|
||||
- name: "Before layer change G-code"
|
||||
icon: "param_gcode"
|
||||
gcode: true
|
||||
fields:
|
||||
- before_layer_change_gcode: printer_machine_gcode#before-layer-change-g-code
|
||||
- name: "Layer change G-code"
|
||||
icon: "param_gcode"
|
||||
gcode: true
|
||||
fields:
|
||||
- layer_change_gcode: printer_machine_gcode#after-layer-change-g-code
|
||||
- name: "Timelapse G-code"
|
||||
icon: "param_gcode"
|
||||
gcode: true
|
||||
fields:
|
||||
- time_lapse_gcode: printer_machine_gcode#time-lapse-g-code
|
||||
- name: "Clumping Detection G-code"
|
||||
icon: "param_gcode"
|
||||
gcode: true
|
||||
fields:
|
||||
- wrapping_detection_gcode: printer_machine_gcode#clumping-detection-g-code
|
||||
- name: "Change filament G-code"
|
||||
icon: "param_gcode"
|
||||
gcode: true
|
||||
fields:
|
||||
- change_filament_gcode: printer_machine_gcode#change-filament-g-code
|
||||
- name: "Change extrusion role G-code"
|
||||
icon: "param_gcode"
|
||||
gcode: true
|
||||
fields:
|
||||
- change_extrusion_role_gcode: printer_machine_gcode#change-extrusion-role-g-code
|
||||
- name: "Pause G-code"
|
||||
icon: "param_gcode"
|
||||
gcode: true
|
||||
fields:
|
||||
- machine_pause_gcode: printer_machine_gcode#pause-g-code
|
||||
- name: "Template Custom G-code"
|
||||
icon: "param_gcode"
|
||||
gcode: true
|
||||
fields:
|
||||
- template_custom_gcode: printer_machine_gcode#template-custom-g-code
|
||||
- name: "Notes"
|
||||
icon: "custom-gcode_note"
|
||||
groups:
|
||||
- name: "Notes"
|
||||
icon: "note"
|
||||
fields:
|
||||
- printer_notes: ""
|
||||
7502
src/PrintConfigs/print.proto
Normal file
7502
src/PrintConfigs/print.proto
Normal file
File diff suppressed because it is too large
Load Diff
967
src/PrintConfigs/printer.proto
Normal file
967
src/PrintConfigs/printer.proto
Normal file
@@ -0,0 +1,967 @@
|
||||
// OrcaSlicer - PrinterSettings
|
||||
// Edit this file and re-run: python tools/run_codegen.py
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
import "config_metadata.proto";
|
||||
|
||||
package orca;
|
||||
|
||||
message PrinterSettings {
|
||||
|
||||
// ── Virtual keys: not in PrintConfigDef, but required in printer presets ──
|
||||
// Printer identity / bed shape (handled by Preset/PrinterConfig directly)
|
||||
option (virtual_preset_keys) = "bed_custom_model";
|
||||
option (virtual_preset_keys) = "bed_custom_texture";
|
||||
option (virtual_preset_keys) = "bed_exclude_area";
|
||||
option (virtual_preset_keys) = "bbl_use_printhost";
|
||||
option (virtual_preset_keys) = "default_print_profile";
|
||||
option (virtual_preset_keys) = "extruder_printable_area";
|
||||
option (virtual_preset_keys) = "extruder_variant_list";
|
||||
option (virtual_preset_keys) = "grab_length";
|
||||
option (virtual_preset_keys) = "head_wrap_detect_zone";
|
||||
option (virtual_preset_keys) = "inherits";
|
||||
option (virtual_preset_keys) = "physical_extruder_map";
|
||||
option (virtual_preset_keys) = "printable_area";
|
||||
option (virtual_preset_keys) = "printable_height";
|
||||
option (virtual_preset_keys) = "extruder_printable_height";
|
||||
option (virtual_preset_keys) = "printer_agent";
|
||||
option (virtual_preset_keys) = "printer_extruder_id";
|
||||
option (virtual_preset_keys) = "printer_extruder_variant";
|
||||
option (virtual_preset_keys) = "printer_model";
|
||||
option (virtual_preset_keys) = "printer_technology";
|
||||
option (virtual_preset_keys) = "printer_variant";
|
||||
option (virtual_preset_keys) = "silent_mode";
|
||||
option (virtual_preset_keys) = "support_object_skip_flush";
|
||||
// Print-host / connectivity
|
||||
option (virtual_preset_keys) = "host_type";
|
||||
option (virtual_preset_keys) = "print_host";
|
||||
option (virtual_preset_keys) = "print_host_webui";
|
||||
option (virtual_preset_keys) = "printhost_apikey";
|
||||
option (virtual_preset_keys) = "printhost_authorization_type";
|
||||
option (virtual_preset_keys) = "printhost_cafile";
|
||||
option (virtual_preset_keys) = "printhost_port";
|
||||
option (virtual_preset_keys) = "printhost_password";
|
||||
option (virtual_preset_keys) = "printhost_ssl_ignore_revoke";
|
||||
option (virtual_preset_keys) = "printhost_user";
|
||||
// Cross-preset: defined in print.proto but also saved in printer presets
|
||||
option (virtual_preset_keys) = "bed_temperature_formula";
|
||||
option (virtual_preset_keys) = "cooling_tube_length";
|
||||
option (virtual_preset_keys) = "cooling_tube_retraction";
|
||||
option (virtual_preset_keys) = "default_bed_type";
|
||||
option (virtual_preset_keys) = "default_nozzle_volume_type";
|
||||
option (virtual_preset_keys) = "emit_machine_limits_to_gcode";
|
||||
option (virtual_preset_keys) = "enable_filament_ramming";
|
||||
option (virtual_preset_keys) = "enable_long_retraction_when_cut";
|
||||
option (virtual_preset_keys) = "extra_loading_move";
|
||||
option (virtual_preset_keys) = "extruder_type";
|
||||
option (virtual_preset_keys) = "high_current_on_filament_swap";
|
||||
option (virtual_preset_keys) = "long_retractions_when_cut";
|
||||
option (virtual_preset_keys) = "machine_load_filament_time";
|
||||
option (virtual_preset_keys) = "machine_tool_change_time";
|
||||
option (virtual_preset_keys) = "machine_unload_filament_time";
|
||||
option (virtual_preset_keys) = "manual_filament_change";
|
||||
option (virtual_preset_keys) = "master_extruder_id";
|
||||
option (virtual_preset_keys) = "nozzle_flush_dataset";
|
||||
option (virtual_preset_keys) = "nozzle_height";
|
||||
option (virtual_preset_keys) = "nozzle_volume";
|
||||
option (virtual_preset_keys) = "parking_pos_retraction";
|
||||
option (virtual_preset_keys) = "preferred_orientation";
|
||||
option (virtual_preset_keys) = "purge_in_prime_tower";
|
||||
option (virtual_preset_keys) = "retract_lift_enforce";
|
||||
option (virtual_preset_keys) = "retraction_distances_when_cut";
|
||||
option (virtual_preset_keys) = "single_extruder_multi_material";
|
||||
option (virtual_preset_keys) = "thumbnails_format";
|
||||
option (virtual_preset_keys) = "tool_change_on_wipe_tower";
|
||||
option (virtual_preset_keys) = "travel_slope";
|
||||
option (virtual_preset_keys) = "upward_compatible_machine";
|
||||
option (virtual_preset_keys) = "wipe_tower_type";
|
||||
option (virtual_preset_keys) = "wrapping_detection_layers";
|
||||
option (virtual_preset_keys) = "wrapping_exclude_area";
|
||||
option (virtual_preset_keys) = "z_hop_types";
|
||||
// Printer keys with hand-written defs in init_common_params (not proto fields);
|
||||
// declared here so they land in s_Preset_printer_options and vendor machine
|
||||
// profiles that set them are not stripped on load.
|
||||
option (virtual_preset_keys) = "use_3mf";
|
||||
option (virtual_preset_keys) = "support_parallel_printheads";
|
||||
option (virtual_preset_keys) = "parallel_printheads_count";
|
||||
option (virtual_preset_keys) = "parallel_printheads_bed_exclude_areas";
|
||||
|
||||
float extruder_clearance_height_to_rod = 1 [
|
||||
(label) = "Height to rod",
|
||||
(tooltip) = "Distance of the nozzle tip to the lower rod. Used for collision avoidance in by-object printing.",
|
||||
(category) = "Printer/Basic information",
|
||||
(sidetext) = "mm",
|
||||
(tab_type) = "Printer",
|
||||
(tab_page) = "Basic information",
|
||||
(tab_optgroup) = "Extruder Clearance",
|
||||
(min_value) = 0,
|
||||
(mode) = MODE_ADVANCED,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "40",
|
||||
(invalidates) = STEP_GCODE_EXPORT
|
||||
];
|
||||
|
||||
float extruder_clearance_height_to_lid = 2 [
|
||||
(label) = "Height to lid",
|
||||
(tooltip) = "Distance of the nozzle tip to the lid. Used for collision avoidance in by-object printing.",
|
||||
(category) = "Printer/Basic information",
|
||||
(sidetext) = "mm",
|
||||
(tab_type) = "Printer",
|
||||
(tab_page) = "Basic information",
|
||||
(tab_optgroup) = "Extruder Clearance",
|
||||
(min_value) = 0,
|
||||
(mode) = MODE_ADVANCED,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "120",
|
||||
(invalidates) = STEP_GCODE_EXPORT
|
||||
];
|
||||
|
||||
float extruder_clearance_radius = 3 [
|
||||
(label) = "Radius",
|
||||
(tooltip) = "Clearance radius around extruder. Used for collision avoidance in by-object printing.",
|
||||
(category) = "Printer/Basic information",
|
||||
(sidetext) = "mm",
|
||||
(tab_type) = "Printer",
|
||||
(tab_page) = "Basic information",
|
||||
(tab_optgroup) = "Extruder Clearance",
|
||||
(min_value) = 0,
|
||||
(mode) = MODE_ADVANCED,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "40",
|
||||
(invalidates) = STEP_GCODE_EXPORT
|
||||
];
|
||||
|
||||
Point2D bed_mesh_min = 4 [
|
||||
(label) = "Bed mesh min",
|
||||
(tooltip) = "This option sets the min point for the allowed bed mesh area. Due to the probe's XY offset, most printers are unable to probe the entire bed. To ensure the probe point does not go outside the bed area, the minimum and maximum points of the bed mesh should be set appropriately. OrcaSlicer ensures that adaptive_bed_mesh_min/adaptive_bed_mesh_max values do not exceed these min/max points. This information can usually be obtained from your printer manufacturer. The default setting is (-99999, -99999), which means there are no limits, thus allowing probing across the entire bed.",
|
||||
(category) = "Printer/Basic information",
|
||||
(sidetext) = "mm",
|
||||
(tab_type) = "Printer",
|
||||
(tab_page) = "Basic information",
|
||||
(tab_optgroup) = "Adaptive bed mesh",
|
||||
(mode) = MODE_ADVANCED,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "Vec2d(-99999, -99999)"
|
||||
];
|
||||
|
||||
Point2D bed_mesh_max = 5 [
|
||||
(label) = "Bed mesh max",
|
||||
(tooltip) = "This option sets the max point for the allowed bed mesh area. Due to the probe's XY offset, most printers are unable to probe the entire bed. To ensure the probe point does not go outside the bed area, the minimum and maximum points of the bed mesh should be set appropriately. OrcaSlicer ensures that adaptive_bed_mesh_min/adaptive_bed_mesh_max values do not exceed these min/max points. This information can usually be obtained from your printer manufacturer. The default setting is (99999, 99999), which means there are no limits, thus allowing probing across the entire bed.",
|
||||
(category) = "Printer/Basic information",
|
||||
(sidetext) = "mm",
|
||||
(tab_type) = "Printer",
|
||||
(tab_page) = "Basic information",
|
||||
(tab_optgroup) = "Adaptive bed mesh",
|
||||
(mode) = MODE_ADVANCED,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "Vec2d(99999, 99999)"
|
||||
];
|
||||
|
||||
Point2D bed_mesh_probe_distance = 6 [
|
||||
(label) = "Probe point distance",
|
||||
(tooltip) = "This option sets the preferred distance between probe points (grid size) for the X and Y directions, with the default being 50mm for both X and Y.",
|
||||
(category) = "Printer/Basic information",
|
||||
(sidetext) = "mm",
|
||||
(tab_type) = "Printer",
|
||||
(tab_page) = "Basic information",
|
||||
(tab_optgroup) = "Adaptive bed mesh",
|
||||
(min_value) = 0,
|
||||
(mode) = MODE_ADVANCED,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "Vec2d(50, 50)"
|
||||
];
|
||||
|
||||
float adaptive_bed_mesh_margin = 7 [
|
||||
(label) = "Mesh margin",
|
||||
(tooltip) = "This option determines the additional distance by which the adaptive bed mesh area should be expanded in the XY directions.",
|
||||
(category) = "Printer/Basic information",
|
||||
(sidetext) = "mm",
|
||||
(tab_type) = "Printer",
|
||||
(tab_page) = "Basic information",
|
||||
(tab_optgroup) = "Adaptive bed mesh",
|
||||
(mode) = MODE_ADVANCED,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "0"
|
||||
];
|
||||
|
||||
bool scan_first_layer = 8 [
|
||||
(label) = "Scan first layer",
|
||||
(tooltip) = "Enable this to enable the camera on printer to check the quality of first layer.",
|
||||
(category) = "Printer/Basic information",
|
||||
(tab_type) = "Printer",
|
||||
(tab_page) = "Basic information",
|
||||
(tab_optgroup) = "Advanced",
|
||||
(mode) = MODE_ADVANCED,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "false"
|
||||
];
|
||||
|
||||
int32 enable_power_loss_recovery = 9 [
|
||||
(label) = "Power Loss Recovery",
|
||||
(tooltip) = "Choose how to control power loss recovery. When set to Printer configuration, the slicer will not emit power loss recovery G-code and will leave the printer's configuration unchanged. Applicable to Bambu Lab or Marlin 2 firmware based printers.",
|
||||
(category) = "Printer/Basic information",
|
||||
(enum_keys_map_ref) = "ConfigOptionEnum<PowerLossRecoveryMode>::get_enum_values()",
|
||||
(co_type_hint) = coEnum,
|
||||
(tab_type) = "Printer",
|
||||
(tab_page) = "Basic information",
|
||||
(tab_optgroup) = "Advanced",
|
||||
(mode) = MODE_ADVANCED,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "PowerLossRecoveryMode::PrinterConfiguration",
|
||||
(enum_value_entries) = "printer_configuration",
|
||||
(enum_value_entries) = "enable",
|
||||
(enum_value_entries) = "disable",
|
||||
(enum_label_entries) = "Printer configuration",
|
||||
(enum_label_entries) = "Enable",
|
||||
(enum_label_entries) = "Disable"
|
||||
];
|
||||
|
||||
repeated int32 nozzle_type = 10 [
|
||||
(label) = "Nozzle type",
|
||||
(tooltip) = "The metallic material of nozzle. This determines the abrasive resistance of nozzle, and what kind of filament can be printed.",
|
||||
(category) = "Printer/Basic information",
|
||||
(enum_keys_map_ref) = "ConfigOptionEnum<NozzleType>::get_enum_values()",
|
||||
(co_type_hint) = coEnums,
|
||||
(tab_type) = "Printer",
|
||||
(tab_page) = "Basic information",
|
||||
(tab_optgroup) = "Accessory",
|
||||
(mode) = MODE_ADVANCED,
|
||||
(is_nullable) = true,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "ntUndefine",
|
||||
(enum_value_entries) = "undefine",
|
||||
(enum_value_entries) = "hardened_steel",
|
||||
(enum_value_entries) = "stainless_steel",
|
||||
(enum_value_entries) = "tungsten_carbide",
|
||||
(enum_value_entries) = "brass",
|
||||
(enum_label_entries) = "Undefine",
|
||||
(enum_label_entries) = "Hardened steel",
|
||||
(enum_label_entries) = "Stainless steel",
|
||||
(enum_label_entries) = "Tungsten carbide",
|
||||
(enum_label_entries) = "Brass",
|
||||
(list_membership) = LIST_EXTRUDER_OPTION_KEYS
|
||||
];
|
||||
|
||||
int32 nozzle_hrc = 11 [
|
||||
(label) = "Nozzle HRC",
|
||||
(tooltip) = "The nozzle's hardness. Zero means no checking for nozzle's hardness during slicing.",
|
||||
(category) = "Printer/Basic information",
|
||||
(sidetext) = "HRC",
|
||||
(tab_type) = "Printer",
|
||||
(tab_page) = "Basic information",
|
||||
(tab_optgroup) = "Accessory",
|
||||
(min_value) = 0,
|
||||
(max_value) = 500,
|
||||
(mode) = MODE_DEVELOP,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "0",
|
||||
(invalidates) = STEP_GCODE_EXPORT
|
||||
];
|
||||
|
||||
int32 printer_structure = 12 [
|
||||
(label) = "Printer structure",
|
||||
(tooltip) = "The physical arrangement and components of a printing device.",
|
||||
(category) = "Printer/Basic information",
|
||||
(enum_keys_map_ref) = "ConfigOptionEnum<PrinterStructure>::get_enum_values()",
|
||||
(co_type_hint) = coEnum,
|
||||
(tab_type) = "Printer",
|
||||
(tab_page) = "Basic information",
|
||||
(tab_optgroup) = "Advanced",
|
||||
(mode) = MODE_DEVELOP,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "psUndefine",
|
||||
(enum_value_entries) = "undefine",
|
||||
(enum_value_entries) = "corexy",
|
||||
(enum_value_entries) = "i3",
|
||||
(enum_value_entries) = "hbot",
|
||||
(enum_value_entries) = "delta",
|
||||
(enum_label_entries) = "Undefine",
|
||||
(enum_label_entries) = "CoreXY",
|
||||
(enum_label_entries) = "I3",
|
||||
(enum_label_entries) = "Hbot",
|
||||
(enum_label_entries) = "Delta"
|
||||
];
|
||||
|
||||
Point2D best_object_pos = 13 [
|
||||
(label) = "Best object position",
|
||||
(tooltip) = "Best auto arranging position in range [0,1] w.r.t. bed shape.",
|
||||
(category) = "Printer/Basic information",
|
||||
(tab_type) = "Printer",
|
||||
(tab_page) = "Basic information",
|
||||
(tab_optgroup) = "Printable space",
|
||||
(mode) = MODE_ADVANCED,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "Vec2d(0.5, 0.5)"
|
||||
];
|
||||
|
||||
bool auxiliary_fan = 14 [
|
||||
(label) = "Auxiliary part cooling fan",
|
||||
(tooltip) = "Enable this option if machine has auxiliary part cooling fan. G-code command: M106 P2 S(0-255).",
|
||||
(category) = "Printer/Basic information",
|
||||
(tab_type) = "Printer",
|
||||
(tab_page) = "Basic information",
|
||||
(tab_optgroup) = "Accessory",
|
||||
(mode) = MODE_ADVANCED,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "false"
|
||||
];
|
||||
|
||||
float fan_speedup_time = 15 [
|
||||
(tooltip) = "Start the fan this number of seconds earlier than its target start time (you can use fractional seconds). It assumes infinite acceleration for this time estimation, and will only take into account G1 and G0 moves (arc fitting is unsupported).\\nIt won't move fan commands from custom G-code (they act as a sort of 'barrier').\\nIt won't move fan commands into the start G-code if the 'only custom start G-code' is activated.\\nUse 0 to deactivate.",
|
||||
(category) = "Printer/Basic information",
|
||||
(sidetext) = "s",
|
||||
(tab_type) = "Printer",
|
||||
(tab_page) = "Basic information",
|
||||
(tab_optgroup) = "Cooling Fan",
|
||||
(mode) = MODE_ADVANCED,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "0",
|
||||
(invalidates) = STEP_GCODE_EXPORT
|
||||
];
|
||||
|
||||
bool fan_speedup_overhangs = 16 [
|
||||
(label) = "Only overhangs",
|
||||
(tooltip) = "Will only take into account the delay for the cooling of overhangs.",
|
||||
(category) = "Printer/Basic information",
|
||||
(tab_type) = "Printer",
|
||||
(tab_page) = "Basic information",
|
||||
(tab_optgroup) = "Cooling Fan",
|
||||
(mode) = MODE_ADVANCED,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "true",
|
||||
(invalidates) = STEP_GCODE_EXPORT
|
||||
];
|
||||
|
||||
float fan_kickstart = 17 [
|
||||
(label) = "Fan kick-start time",
|
||||
(tooltip) = "Emit a max fan speed command for this amount of seconds before reducing to target speed to kick-start the cooling fan.\\nThis is useful for fans where a low PWM/power may be insufficient to get the fan started spinning from a stop, or to get the fan up to speed faster.\\nSet to 0 to deactivate.",
|
||||
(category) = "Printer/Basic information",
|
||||
(sidetext) = "s",
|
||||
(tab_type) = "Printer",
|
||||
(tab_page) = "Basic information",
|
||||
(tab_optgroup) = "Cooling Fan",
|
||||
(min_value) = 0,
|
||||
(mode) = MODE_ADVANCED,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "0",
|
||||
(invalidates) = STEP_GCODE_EXPORT
|
||||
];
|
||||
|
||||
int32 part_cooling_fan_min_pwm = 18 [
|
||||
(label) = "Minimum non-zero part cooling fan speed",
|
||||
(tooltip) = "Some part-cooling fans cannot start spinning when commanded below a certain PWM duty cycle. When set above 0, any non-zero part-cooling fan command will be raised to at least this percentage so the fan reliably starts. A fan command of 0 (fan off) is always honoured exactly. This clamp is applied after every other fan calculation (first-layer ramp, layer-time interpolation, overhang/bridge/support-interface/ironing overrides), so scaling still operates within the range [this value, 100%].\\nIf your firmware already disables the fan below a threshold (for example Klipper's [fan] off_below: 0.10 shuts the fan off whenever the commanded duty cycle is below 10%), this option and the firmware threshold should ideally be set to the same value. Matching them (e.g. off_below: 0.10 in Klipper and 10% here) guarantees the slicer never emits a non-zero value that the firmware would silently drop, and the fan never receives a value below the one you know it can actually spool at.\\nSet to 0 to deactivate.",
|
||||
(category) = "Printer/Basic information",
|
||||
(sidetext) = "%",
|
||||
(tab_type) = "Printer",
|
||||
(tab_page) = "Basic information",
|
||||
(tab_optgroup) = "Cooling Fan",
|
||||
(min_value) = 0,
|
||||
(max_value) = 100,
|
||||
(mode) = MODE_ADVANCED,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "0",
|
||||
(invalidates) = STEP_GCODE_EXPORT
|
||||
];
|
||||
|
||||
float time_cost = 19 [
|
||||
(label) = "Time cost",
|
||||
(tooltip) = "The printer cost per hour.",
|
||||
(category) = "Printer/Basic information",
|
||||
(sidetext) = "money/h",
|
||||
(tab_type) = "Printer",
|
||||
(tab_page) = "Basic information",
|
||||
(tab_optgroup) = "Advanced",
|
||||
(min_value) = 0,
|
||||
(mode) = MODE_ADVANCED,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "0"
|
||||
];
|
||||
|
||||
bool support_chamber_temp_control = 20 [
|
||||
(label) = "Support control chamber temperature",
|
||||
(tooltip) = "This option is enabled if machine support controlling chamber temperature\\nG-code command: M141 S(0-255)",
|
||||
(category) = "Printer/Basic information",
|
||||
(tab_type) = "Printer",
|
||||
(tab_page) = "Basic information",
|
||||
(tab_optgroup) = "Accessory",
|
||||
(mode) = MODE_ADVANCED,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "true"
|
||||
];
|
||||
|
||||
bool support_air_filtration = 21 [
|
||||
(label) = "Support air filtration",
|
||||
(tooltip) = "Enable this if printer support air filtration\\nG-code command: M106 P3 S(0-255)",
|
||||
(category) = "Printer/Basic information",
|
||||
(tab_type) = "Printer",
|
||||
(tab_page) = "Basic information",
|
||||
(tab_optgroup) = "Accessory",
|
||||
(mode) = MODE_DEVELOP,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "true"
|
||||
];
|
||||
|
||||
int32 gcode_flavor = 22 [
|
||||
(label) = "G-code flavor",
|
||||
(tooltip) = "What kind of G-code the printer is compatible with.",
|
||||
(category) = "Printer/Basic information",
|
||||
(enum_keys_map_ref) = "ConfigOptionEnum<GCodeFlavor>::get_enum_values()",
|
||||
(co_type_hint) = coEnum,
|
||||
(tab_type) = "Printer",
|
||||
(tab_page) = "Basic information",
|
||||
(tab_optgroup) = "Advanced",
|
||||
(mode) = MODE_ADVANCED,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "gcfMarlinLegacy",
|
||||
(enum_value_entries) = "marlin",
|
||||
(enum_value_entries) = "klipper",
|
||||
(enum_value_entries) = "reprapfirmware",
|
||||
(enum_value_entries) = "repetier",
|
||||
(enum_value_entries) = "marlin2",
|
||||
(enum_value_entries) = "reprap",
|
||||
(enum_value_entries) = "teacup",
|
||||
(enum_value_entries) = "makerware",
|
||||
(enum_value_entries) = "sailfish",
|
||||
(enum_value_entries) = "mach3",
|
||||
(enum_value_entries) = "machinekit",
|
||||
(enum_value_entries) = "smoothie",
|
||||
(enum_value_entries) = "no-extrusion",
|
||||
(enum_label_entries) = "Marlin(legacy)",
|
||||
(enum_label_entries) = "Klipper",
|
||||
(enum_label_entries) = "RepRapFirmware",
|
||||
(enum_label_entries) = "Repetier",
|
||||
(enum_label_entries) = "Marlin 2",
|
||||
(enum_label_entries) = "RepRap/Sprinter",
|
||||
(enum_label_entries) = "Teacup",
|
||||
(enum_label_entries) = "MakerWare (MakerBot)",
|
||||
(enum_label_entries) = "Sailfish (MakerBot)",
|
||||
(enum_label_entries) = "Mach3/LinuxCNC",
|
||||
(enum_label_entries) = "Machinekit",
|
||||
(enum_label_entries) = "Smoothie",
|
||||
(enum_label_entries) = "No extrusion",
|
||||
(invalidates) = STEP_SKIRT_BRIM,
|
||||
(invalidates) = STEP_WIPE_TOWER
|
||||
];
|
||||
|
||||
bool pellet_modded_printer = 23 [
|
||||
(label) = "Pellet Modded Printer",
|
||||
(tooltip) = "Enable this option if your printer uses pellets instead of filaments.",
|
||||
(category) = "Printer/Basic information",
|
||||
(tab_type) = "Printer",
|
||||
(tab_page) = "Basic information",
|
||||
(tab_optgroup) = "Advanced",
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "false"
|
||||
];
|
||||
|
||||
bool support_multi_bed_types = 24 [
|
||||
(label) = "Support multi bed types",
|
||||
(tooltip) = "Enable this option if you want to use multiple bed types.",
|
||||
(category) = "Printer/Basic information",
|
||||
(tab_type) = "Printer",
|
||||
(tab_page) = "Basic information",
|
||||
(tab_optgroup) = "Printable space",
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "false",
|
||||
(invalidates) = STEP_SKIRT_BRIM,
|
||||
(invalidates) = STEP_WIPE_TOWER
|
||||
];
|
||||
|
||||
bool use_firmware_retraction = 25 [
|
||||
(label) = "Use firmware retraction",
|
||||
(tooltip) = "This experimental setting uses G10 and G11 commands to have the firmware handle the retraction. This is only supported in recent Marlin.",
|
||||
(category) = "Printer/Basic information",
|
||||
(tab_type) = "Printer",
|
||||
(tab_page) = "Basic information",
|
||||
(tab_optgroup) = "Advanced",
|
||||
(mode) = MODE_ADVANCED,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "false",
|
||||
(invalidates) = STEP_GCODE_EXPORT
|
||||
];
|
||||
|
||||
bool disable_m73 = 26 [
|
||||
(label) = "Disable set remaining print time",
|
||||
(tooltip) = "Disable generating of the M73: Set remaining print time in the final G-code.",
|
||||
(category) = "Printer/Basic information",
|
||||
(tab_type) = "Printer",
|
||||
(tab_page) = "Basic information",
|
||||
(tab_optgroup) = "Advanced",
|
||||
(mode) = MODE_ADVANCED,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "false",
|
||||
(invalidates) = STEP_GCODE_EXPORT
|
||||
];
|
||||
|
||||
float z_offset = 27 [
|
||||
(label) = "Z offset",
|
||||
(tooltip) = "This value will be added (or subtracted) from all the Z coordinates in the output G-code. It is used to compensate for bad Z endstop position: for example, if your endstop zero actually leaves the nozzle 0.3mm far from the print bed, set this to -0.3 (or fix your endstop).",
|
||||
(category) = "Printer/Basic information",
|
||||
(sidetext) = "mm",
|
||||
(tab_type) = "Printer",
|
||||
(tab_page) = "Basic information",
|
||||
(tab_optgroup) = "Printable space",
|
||||
(mode) = MODE_ADVANCED,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "0",
|
||||
(invalidates) = STEP_SKIRT_BRIM,
|
||||
(invalidates) = STEP_WIPE_TOWER
|
||||
];
|
||||
|
||||
string thumbnails = 28 [
|
||||
(label) = "G-code thumbnails",
|
||||
(tooltip) = "Picture sizes to be stored into a .gcode and .sl1 / .sl1s files, in the following format: \\\"XxY, XxY, ...\\\"",
|
||||
(category) = "Printer/Basic information",
|
||||
(gui_type) = one_string,
|
||||
(tab_type) = "Printer",
|
||||
(tab_page) = "Basic information",
|
||||
(tab_optgroup) = "Advanced",
|
||||
(mode) = MODE_ADVANCED,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "\"48x48/PNG,300x300/PNG\"",
|
||||
(invalidates) = STEP_GCODE_EXPORT
|
||||
];
|
||||
|
||||
bool use_relative_e_distances = 29 [
|
||||
(label) = "Use relative E distances",
|
||||
(tooltip) = "Relative extrusion is recommended when using \\\"label_objects\\\" option. Some extruders work better with this option unchecked (absolute extrusion mode). Wipe tower is only compatible with relative mode. It is recommended on most printers. Default is checked.",
|
||||
(category) = "Printer/Basic information",
|
||||
(tab_type) = "Printer",
|
||||
(tab_page) = "Basic information",
|
||||
(tab_optgroup) = "Advanced",
|
||||
(mode) = MODE_ADVANCED,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "true",
|
||||
(invalidates) = STEP_GCODE_EXPORT
|
||||
];
|
||||
|
||||
string before_layer_change_gcode = 30 [
|
||||
(label) = "Before layer change G-code",
|
||||
(tooltip) = "This G-code is inserted at every layer change before the Z lift.",
|
||||
(category) = "Printer/Machine G-code",
|
||||
(tab_type) = "Printer",
|
||||
(tab_page) = "Machine G-code",
|
||||
(tab_optgroup) = "Before layer change G-code",
|
||||
(height) = 5,
|
||||
(mode) = MODE_ADVANCED,
|
||||
(multiline) = true,
|
||||
(full_width) = true,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "",
|
||||
(invalidates) = STEP_GCODE_EXPORT
|
||||
];
|
||||
|
||||
string machine_end_gcode = 31 [
|
||||
(label) = "End G-code",
|
||||
(tooltip) = "End G-code when finishing the entire print.",
|
||||
(category) = "Printer/Machine G-code",
|
||||
(tab_type) = "Printer",
|
||||
(tab_page) = "Machine G-code",
|
||||
(tab_optgroup) = "Machine end G-code",
|
||||
(height) = 12,
|
||||
(mode) = MODE_ADVANCED,
|
||||
(multiline) = true,
|
||||
(full_width) = true,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "\"M104 S0 ; turn off temperature\nG28 X0 ; home X axis\nM84 ; disable motors\n\"",
|
||||
(invalidates) = STEP_GCODE_EXPORT
|
||||
];
|
||||
|
||||
string printing_by_object_gcode = 32 [
|
||||
(label) = "Between Object G-code",
|
||||
(tooltip) = "Insert G-code between objects. This parameter will only come into effect when you print your models object by object.",
|
||||
(category) = "Printer/Machine G-code",
|
||||
(tab_type) = "Printer",
|
||||
(tab_page) = "Machine G-code",
|
||||
(tab_optgroup) = "Printing by object G-code",
|
||||
(height) = 12,
|
||||
(mode) = MODE_ADVANCED,
|
||||
(multiline) = true,
|
||||
(full_width) = true,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "",
|
||||
(invalidates) = STEP_GCODE_EXPORT
|
||||
];
|
||||
|
||||
string layer_change_gcode = 33 [
|
||||
(label) = "Layer change G-code",
|
||||
(tooltip) = "This G-code is inserted at every layer change after the Z lift.",
|
||||
(category) = "Printer/Machine G-code",
|
||||
(tab_type) = "Printer",
|
||||
(tab_page) = "Machine G-code",
|
||||
(tab_optgroup) = "Layer change G-code",
|
||||
(height) = 5,
|
||||
(mode) = MODE_ADVANCED,
|
||||
(multiline) = true,
|
||||
(full_width) = true,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "",
|
||||
(invalidates) = STEP_GCODE_EXPORT
|
||||
];
|
||||
|
||||
string time_lapse_gcode = 34 [
|
||||
(label) = "Timelapse G-code",
|
||||
(category) = "Printer/Machine G-code",
|
||||
(tab_type) = "Printer",
|
||||
(tab_page) = "Machine G-code",
|
||||
(tab_optgroup) = "Timelapse G-code",
|
||||
(height) = 5,
|
||||
(mode) = MODE_ADVANCED,
|
||||
(multiline) = true,
|
||||
(full_width) = true,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "",
|
||||
(invalidates) = STEP_GCODE_EXPORT
|
||||
];
|
||||
|
||||
string wrapping_detection_gcode = 35 [
|
||||
(label) = "Clumping detection G-code",
|
||||
(category) = "Printer/Machine G-code",
|
||||
(tab_type) = "Printer",
|
||||
(tab_page) = "Machine G-code",
|
||||
(tab_optgroup) = "Clumping Detection G-code",
|
||||
(height) = 5,
|
||||
(mode) = MODE_ADVANCED,
|
||||
(multiline) = true,
|
||||
(full_width) = true,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "\"\"",
|
||||
(invalidates) = STEP_GCODE_EXPORT
|
||||
];
|
||||
|
||||
string machine_pause_gcode = 36 [
|
||||
(label) = "Pause G-code",
|
||||
(tooltip) = "This G-code will be used as a code for the pause print. Users can insert pause G-code in the G-code viewer.",
|
||||
(category) = "Printer/Machine G-code",
|
||||
(tab_type) = "Printer",
|
||||
(tab_page) = "Machine G-code",
|
||||
(tab_optgroup) = "Pause G-code",
|
||||
(height) = 12,
|
||||
(mode) = MODE_ADVANCED,
|
||||
(multiline) = true,
|
||||
(full_width) = true,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = ""
|
||||
];
|
||||
|
||||
string template_custom_gcode = 37 [
|
||||
(label) = "Custom G-code",
|
||||
(tooltip) = "This G-code will be used as a custom code.",
|
||||
(category) = "Printer/Machine G-code",
|
||||
(tab_type) = "Printer",
|
||||
(tab_page) = "Machine G-code",
|
||||
(tab_optgroup) = "Template Custom G-code",
|
||||
(height) = 12,
|
||||
(mode) = MODE_ADVANCED,
|
||||
(multiline) = true,
|
||||
(full_width) = true,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = ""
|
||||
];
|
||||
|
||||
string file_start_gcode = 38 [
|
||||
(label) = "File header G-code",
|
||||
(tooltip) = "G-code written at the very top of the output file, before any other content. Useful for adding metadata that printer firmware reads from the first lines of the file (e.g. estimated print time, filament usage). Supports placeholders like {print_time_sec} and {used_filament_length}.",
|
||||
(category) = "Printer/Machine G-code",
|
||||
(tab_type) = "Printer",
|
||||
(tab_page) = "Machine G-code",
|
||||
(tab_optgroup) = "File header G-code",
|
||||
(height) = 8,
|
||||
(mode) = MODE_ADVANCED,
|
||||
(multiline) = true,
|
||||
(full_width) = true,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "\"\""
|
||||
];
|
||||
|
||||
string machine_start_gcode = 39 [
|
||||
(label) = "Start G-code",
|
||||
(tooltip) = "Start G-code when starting the entire print.",
|
||||
(category) = "Printer/Machine G-code",
|
||||
(tab_type) = "Printer",
|
||||
(tab_page) = "Machine G-code",
|
||||
(tab_optgroup) = "Machine start G-code",
|
||||
(height) = 12,
|
||||
(mode) = MODE_ADVANCED,
|
||||
(multiline) = true,
|
||||
(full_width) = true,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "\"G28 ; home all axes\nG1 Z5 F5000 ; lift nozzle\n\"",
|
||||
(invalidates) = STEP_GCODE_EXPORT
|
||||
];
|
||||
|
||||
string change_filament_gcode = 40 [
|
||||
(label) = "Change filament G-code",
|
||||
(tooltip) = "This G-code is inserted when filament is changed, including T commands to trigger tool change.",
|
||||
(category) = "Printer/Machine G-code",
|
||||
(tab_type) = "Printer",
|
||||
(tab_page) = "Machine G-code",
|
||||
(tab_optgroup) = "Change filament G-code",
|
||||
(height) = 5,
|
||||
(mode) = MODE_ADVANCED,
|
||||
(multiline) = true,
|
||||
(full_width) = true,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "",
|
||||
(invalidates) = STEP_GCODE_EXPORT
|
||||
];
|
||||
|
||||
string change_extrusion_role_gcode = 41 [
|
||||
(label) = "Change extrusion role G-code",
|
||||
(tooltip) = "This G-code is inserted when the extrusion role is changed.",
|
||||
(category) = "Printer/Machine G-code",
|
||||
(tab_type) = "Printer",
|
||||
(tab_page) = "Machine G-code",
|
||||
(tab_optgroup) = "Change extrusion role G-code",
|
||||
(height) = 5,
|
||||
(mode) = MODE_ADVANCED,
|
||||
(multiline) = true,
|
||||
(full_width) = true,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = ""
|
||||
];
|
||||
|
||||
string printer_notes = 42 [
|
||||
(label) = "Printer notes",
|
||||
(tooltip) = "You can put your notes regarding the printer here.",
|
||||
(category) = "Printer/Notes",
|
||||
(tab_type) = "Printer",
|
||||
(tab_page) = "Notes",
|
||||
(tab_optgroup) = "Notes",
|
||||
(height) = 13,
|
||||
(mode) = MODE_ADVANCED,
|
||||
(multiline) = true,
|
||||
(full_width) = true,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "",
|
||||
(invalidates) = STEP_GCODE_EXPORT
|
||||
];
|
||||
|
||||
|
||||
|
||||
bool cooling_filter_enabled = 43 [
|
||||
(label) = "Use cooling filter",
|
||||
(tooltip) = "Enable this if printer support cooling filter",
|
||||
(mode) = MODE_ADVANCED,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "false"
|
||||
];
|
||||
|
||||
|
||||
repeated float deretract_speed_extruder_change = 44 [
|
||||
(label) = "Deretraction speed (extruder change)",
|
||||
(tooltip) = "Speed for reloading filament into the nozzle when switching extruder.",
|
||||
(sidetext) = "mm/s",
|
||||
(is_nullable) = true,
|
||||
(mode) = MODE_DEVELOP,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "0."
|
||||
];
|
||||
|
||||
|
||||
bool enable_pre_heating = 45 [
|
||||
(label) = "enable_pre_heating",
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "false"
|
||||
];
|
||||
|
||||
|
||||
repeated int32 extruder_max_nozzle_count = 46 [
|
||||
(label) = "extruder_max_nozzle_count",
|
||||
(is_nullable) = true,
|
||||
(mode) = MODE_DEVELOP,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "1"
|
||||
];
|
||||
|
||||
|
||||
repeated int32 extruder_nozzle_count = 47 [
|
||||
(label) = "extruder nozzle count",
|
||||
(tooltip) = "extruder nozzle count",
|
||||
(mode) = MODE_DEVELOP,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "1"
|
||||
];
|
||||
|
||||
|
||||
repeated string extruder_nozzle_stats = 48 [
|
||||
(label) = "Extruder nozzle stats",
|
||||
(tooltip) = "Physical nozzle counts per extruder, keyed by nozzle volume type.",
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = ""
|
||||
];
|
||||
|
||||
|
||||
repeated int32 extruder_nozzle_volume_type = 49 [
|
||||
(label) = "Extruder nozzle volume type",
|
||||
(tooltip) = "Nozzle volume type per physical nozzle of an extruder.",
|
||||
(co_type_hint) = coEnums,
|
||||
(enum_keys_map_ref) = "ConfigOptionEnum<NozzleVolumeType>::get_enum_values()",
|
||||
(mode) = MODE_DEVELOP,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "NozzleVolumeType::nvtStandard",
|
||||
(enum_value_entries) = "Standard",
|
||||
(enum_value_entries) = "High Flow",
|
||||
(enum_value_entries) = "TPU High Flow",
|
||||
(enum_label_entries) = "Standard",
|
||||
(enum_label_entries) = "High Flow",
|
||||
(enum_label_entries) = "TPU High Flow"
|
||||
];
|
||||
|
||||
|
||||
int32 fan_direction = 50 [
|
||||
(label) = "Fan direction",
|
||||
(tooltip) = "Cooling fan direction of the printer",
|
||||
(co_type_hint) = coEnum,
|
||||
(enum_keys_map_ref) = "ConfigOptionEnum<FanDirection>::get_enum_values()",
|
||||
(mode) = MODE_DEVELOP,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "fdUndefine",
|
||||
(enum_value_entries) = "undefine",
|
||||
(enum_value_entries) = "left",
|
||||
(enum_value_entries) = "right",
|
||||
(enum_value_entries) = "both",
|
||||
(enum_label_entries) = "Undefined",
|
||||
(enum_label_entries) = "Left",
|
||||
(enum_label_entries) = "Right",
|
||||
(enum_label_entries) = "Both"
|
||||
];
|
||||
|
||||
|
||||
bool farthest_point_timelapse = 51 [
|
||||
(label) = "Farthest point timelapse",
|
||||
(tooltip) = "When enabled, the timelapse snapshot is taken at the farthest point from camera instead of traveling to the wipe tower or excess chute. Only effective in traditional timelapse mode on non-I3 printers.",
|
||||
(mode) = MODE_SIMPLE,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "false"
|
||||
];
|
||||
|
||||
|
||||
bool group_algo_with_time = 52 [
|
||||
(label) = "group_algo_with_time",
|
||||
(mode) = MODE_DEVELOP,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "false"
|
||||
];
|
||||
|
||||
|
||||
bool handle_hotend_as_extruder = 53 [
|
||||
(label) = "handle_hotend_as_extruder",
|
||||
(mode) = MODE_DEVELOP,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "false"
|
||||
];
|
||||
|
||||
|
||||
repeated float hotend_cooling_rate = 54 [
|
||||
(label) = "hotend_cooling_rate",
|
||||
(is_nullable) = true,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "2"
|
||||
];
|
||||
|
||||
|
||||
repeated float hotend_heating_rate = 55 [
|
||||
(label) = "hotend_heating_rate",
|
||||
(is_nullable) = true,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "2"
|
||||
];
|
||||
|
||||
|
||||
float machine_hotend_change_time = 56 [
|
||||
(label) = "Hotend change time",
|
||||
(tooltip) = "Time to change hotend.",
|
||||
(sidetext) = "s",
|
||||
(min_value) = 0,
|
||||
(mode) = MODE_ADVANCED,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "0.0"
|
||||
];
|
||||
|
||||
|
||||
float machine_prepare_compensation_time = 57 [
|
||||
(label) = "machine_prepare_compensation_time",
|
||||
(mode) = MODE_DEVELOP,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "260"
|
||||
];
|
||||
|
||||
|
||||
bool support_cooling_filter = 58 [
|
||||
(label) = "support_cooling_filter",
|
||||
(mode) = MODE_ADVANCED,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "false"
|
||||
];
|
||||
|
||||
|
||||
bool support_fast_purge_mode = 59 [
|
||||
(label) = "Support fast purge mode",
|
||||
(tooltip) = "Whether this printer supports fast purge mode with optimized temperature and multiplier.",
|
||||
(mode) = MODE_DEVELOP,
|
||||
(preset) = PRESET_PRINTER,
|
||||
(has_default) = true,
|
||||
(default_value) = "false"
|
||||
];
|
||||
|
||||
}
|
||||
@@ -493,6 +493,21 @@ add_library(libslic3r STATIC ${lisbslic3r_sources}
|
||||
${OpenVDBUtils_SOURCES})
|
||||
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${lisbslic3r_sources})
|
||||
|
||||
# Ensure codegen runs before compiling libslic3r (PrintConfig.cpp, Preset.cpp, Print.cpp
|
||||
# all #include generated files — MSVC tracks the #include deps automatically after first build,
|
||||
# but this dependency ensures the generated files exist and are up-to-date before compilation).
|
||||
if(TARGET codegen_config)
|
||||
add_dependencies(libslic3r codegen_config)
|
||||
# Tell cmake that the three source files that #include generated code depend on them,
|
||||
# so an incremental build recompiles them when protos change.
|
||||
set_source_files_properties(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/PrintConfig.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/Preset.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/Print.cpp"
|
||||
PROPERTIES OBJECT_DEPENDS "${CONFIG_GENERATED_SOURCES}"
|
||||
)
|
||||
endif()
|
||||
|
||||
if (SLIC3R_STATIC)
|
||||
set(CGAL_Boost_USE_STATIC_LIBS ON CACHE BOOL "" FORCE)
|
||||
endif ()
|
||||
|
||||
@@ -1002,388 +1002,8 @@ bool Preset::has_cali_lines(PresetBundle* preset_bundle)
|
||||
return false;
|
||||
}
|
||||
|
||||
static std::vector<std::string> s_Preset_print_options{
|
||||
"layer_height",
|
||||
"initial_layer_print_height",
|
||||
"wall_loops",
|
||||
"alternate_extra_wall",
|
||||
"slice_closing_radius",
|
||||
"spiral_mode",
|
||||
"spiral_mode_smooth",
|
||||
"spiral_mode_max_xy_smoothing",
|
||||
"spiral_starting_flow_ratio",
|
||||
"spiral_finishing_flow_ratio",
|
||||
"slicing_mode",
|
||||
"top_shell_layers",
|
||||
"top_shell_thickness",
|
||||
"top_surface_density",
|
||||
"bottom_surface_density",
|
||||
"bottom_shell_layers",
|
||||
"bottom_shell_thickness",
|
||||
"extra_perimeters_on_overhangs",
|
||||
"ensure_vertical_shell_thickness",
|
||||
"reduce_crossing_wall",
|
||||
"detect_thin_wall",
|
||||
"detect_overhang_wall",
|
||||
"overhang_reverse",
|
||||
"overhang_reverse_threshold",
|
||||
"overhang_reverse_internal_only",
|
||||
"wall_direction",
|
||||
"seam_position",
|
||||
"staggered_inner_seams",
|
||||
"wall_sequence",
|
||||
"is_infill_first",
|
||||
"sparse_infill_density",
|
||||
"fill_multiline",
|
||||
"gyroid_optimized",
|
||||
"sparse_infill_pattern",
|
||||
"lateral_lattice_angle_1",
|
||||
"lateral_lattice_angle_2",
|
||||
"infill_overhang_angle",
|
||||
"lightning_overhang_angle",
|
||||
"lightning_prune_angle",
|
||||
"lightning_straightening_angle",
|
||||
"top_surface_pattern",
|
||||
"top_surface_expansion",
|
||||
"top_surface_expansion_margin",
|
||||
"top_surface_expansion_direction",
|
||||
"bottom_surface_pattern",
|
||||
"top_surface_fill_order",
|
||||
"bottom_surface_fill_order",
|
||||
"infill_direction",
|
||||
"solid_infill_direction",
|
||||
"top_layer_direction",
|
||||
"bottom_layer_direction",
|
||||
"counterbore_hole_bridging",
|
||||
"infill_shift_step",
|
||||
"sparse_infill_rotate_template",
|
||||
"solid_infill_rotate_template",
|
||||
"symmetric_infill_y_axis",
|
||||
"skeleton_infill_density",
|
||||
"infill_lock_depth",
|
||||
"skin_infill_depth",
|
||||
"skin_infill_density",
|
||||
"align_infill_direction_to_model",
|
||||
"extra_solid_infills",
|
||||
"center_of_surface_pattern",
|
||||
"separated_infills",
|
||||
"minimum_sparse_infill_area",
|
||||
"reduce_infill_retraction",
|
||||
"internal_solid_infill_pattern",
|
||||
"gap_fill_target",
|
||||
"ironing_type",
|
||||
"ironing_pattern",
|
||||
"ironing_flow",
|
||||
"ironing_speed",
|
||||
"ironing_spacing",
|
||||
"ironing_angle",
|
||||
"ironing_angle_fixed",
|
||||
"ironing_inset",
|
||||
"support_ironing",
|
||||
"support_ironing_pattern",
|
||||
"support_ironing_flow",
|
||||
"support_ironing_spacing",
|
||||
"max_travel_detour_distance",
|
||||
"fuzzy_skin", "fuzzy_skin_thickness", "fuzzy_skin_point_distance", "fuzzy_skin_first_layer", "fuzzy_skin_noise_type", "fuzzy_skin_mode", "fuzzy_skin_scale", "fuzzy_skin_octaves", "fuzzy_skin_persistence", "fuzzy_skin_ripples_per_layer", "fuzzy_skin_ripple_offset", "fuzzy_skin_layers_between_ripple_offset",
|
||||
"max_volumetric_extrusion_rate_slope", "max_volumetric_extrusion_rate_slope_segment_length","extrusion_rate_smoothing_external_perimeter_only",
|
||||
"inner_wall_speed", "outer_wall_speed", "sparse_infill_speed", "internal_solid_infill_speed",
|
||||
"top_surface_speed", "support_speed", "support_object_xy_distance", "support_object_first_layer_gap", "support_interface_speed",
|
||||
"bridge_speed", "internal_bridge_speed", "gap_infill_speed", "travel_speed", "travel_speed_z", "initial_layer_speed",
|
||||
"outer_wall_acceleration", "initial_layer_acceleration", "top_surface_acceleration", "default_acceleration", "skirt_type", "skirt_loops", "skirt_speed","min_skirt_length", "skirt_distance", "skirt_start_angle", "skirt_height","single_loop_draft_shield", "draft_shield",
|
||||
"brim_width", "brim_object_gap", "brim_flow_ratio", "brim_use_efc_outline", "combine_brims", "brim_type", "brim_ears_max_angle", "brim_ears_detection_length", "enable_support", "support_type", "support_threshold_angle", "support_threshold_overlap","enforce_support_layers",
|
||||
"raft_layers", "raft_first_layer_density", "raft_first_layer_expansion", "raft_contact_distance", "raft_expansion",
|
||||
"support_base_pattern", "support_base_pattern_spacing", "support_expansion", "support_style",
|
||||
// BBS
|
||||
"print_extruder_id",
|
||||
"print_extruder_variant",
|
||||
"independent_support_layer_height",
|
||||
"support_angle",
|
||||
"support_interface_top_layers",
|
||||
"support_interface_bottom_layers",
|
||||
"support_interface_pattern",
|
||||
"support_interface_spacing",
|
||||
"support_interface_loop_pattern",
|
||||
"support_top_z_distance",
|
||||
"support_on_build_plate_only",
|
||||
"support_critical_regions_only",
|
||||
"bridge_no_support",
|
||||
"thick_bridges",
|
||||
"thick_internal_bridges",
|
||||
"dont_filter_internal_bridges",
|
||||
"enable_extra_bridge_layer",
|
||||
"max_bridge_length",
|
||||
"print_sequence",
|
||||
"print_order",
|
||||
"support_remove_small_overhang",
|
||||
"filename_format",
|
||||
"outer_wall_filament_id",
|
||||
"inner_wall_filament_id",
|
||||
"support_bottom_z_distance",
|
||||
"sparse_infill_filament_id",
|
||||
"internal_solid_filament_id",
|
||||
"top_surface_filament_id",
|
||||
"bottom_surface_filament_id",
|
||||
"support_filament",
|
||||
"support_interface_filament",
|
||||
"support_interface_not_for_body",
|
||||
"ooze_prevention",
|
||||
"standby_temperature_delta",
|
||||
"preheat_time",
|
||||
"preheat_steps",
|
||||
"interface_shells",
|
||||
"line_width",
|
||||
"initial_layer_line_width",
|
||||
"inner_wall_line_width",
|
||||
"outer_wall_line_width",
|
||||
"sparse_infill_line_width",
|
||||
"internal_solid_infill_line_width",
|
||||
"skin_infill_line_width",
|
||||
"skeleton_infill_line_width",
|
||||
"top_surface_line_width",
|
||||
"support_line_width",
|
||||
"infill_wall_overlap",
|
||||
"top_bottom_infill_wall_overlap",
|
||||
"bridge_flow",
|
||||
"bridge_line_width",
|
||||
"internal_bridge_flow",
|
||||
"elefant_foot_compensation",
|
||||
"elefant_foot_compensation_layers",
|
||||
"elefant_foot_layers_density",
|
||||
"xy_contour_compensation",
|
||||
"xy_hole_compensation",
|
||||
"resolution",
|
||||
"enable_prime_tower",
|
||||
"prime_tower_enable_framework",
|
||||
"prime_tower_width",
|
||||
"prime_tower_brim_width",
|
||||
"prime_tower_skip_points",
|
||||
"prime_volume",
|
||||
"prime_tower_infill_gap",
|
||||
"prime_tower_flat_ironing",
|
||||
"enable_tower_interface_features",
|
||||
"enable_tower_interface_cooldown_during_tower",
|
||||
"wipe_tower_no_sparse_layers",
|
||||
"compatible_printers",
|
||||
"compatible_printers_condition",
|
||||
"inherits",
|
||||
"flush_into_infill",
|
||||
"flush_into_objects",
|
||||
"flush_into_support",
|
||||
"tree_support_branch_angle",
|
||||
"tree_support_angle_slow",
|
||||
"tree_support_wall_count",
|
||||
"tree_support_top_rate",
|
||||
"tree_support_branch_distance",
|
||||
"tree_support_tip_diameter",
|
||||
"tree_support_branch_diameter",
|
||||
"tree_support_branch_diameter_angle",
|
||||
"detect_narrow_internal_solid_infill",
|
||||
"gcode_add_line_number",
|
||||
"enable_arc_fitting",
|
||||
"precise_z_height",
|
||||
"infill_combination",
|
||||
"infill_combination_max_layer_height", /*"adaptive_layer_height",*/
|
||||
"support_bottom_interface_spacing",
|
||||
"enable_overhang_speed",
|
||||
"slowdown_for_curled_perimeters",
|
||||
"overhang_1_4_speed",
|
||||
"overhang_2_4_speed",
|
||||
"overhang_3_4_speed",
|
||||
"overhang_4_4_speed",
|
||||
"initial_layer_infill_speed",
|
||||
"only_one_wall_top",
|
||||
"timelapse_type",
|
||||
"wall_generator",
|
||||
"wall_transition_length",
|
||||
"wall_transition_filter_deviation",
|
||||
"wall_transition_angle",
|
||||
"wall_distribution_count",
|
||||
"min_feature_size",
|
||||
"min_bead_width",
|
||||
"post_process",
|
||||
"slicing_pipeline_plugin",
|
||||
"plugins",
|
||||
"print_plugin_config_overrides",
|
||||
"process_change_extrusion_role_gcode",
|
||||
"min_length_factor",
|
||||
"wall_maximum_resolution",
|
||||
"wall_maximum_deviation",
|
||||
"small_perimeter_speed",
|
||||
"small_perimeter_threshold",
|
||||
"small_support_perimeter_speed",
|
||||
"small_support_perimeter_threshold",
|
||||
"bridge_angle",
|
||||
"internal_bridge_angle",
|
||||
"relative_bridge_angle",
|
||||
"filter_out_gap_fill",
|
||||
"travel_acceleration",
|
||||
"inner_wall_acceleration",
|
||||
"min_width_top_surface",
|
||||
"default_jerk",
|
||||
"outer_wall_jerk",
|
||||
"inner_wall_jerk",
|
||||
"infill_jerk",
|
||||
"top_surface_jerk",
|
||||
"initial_layer_jerk",
|
||||
"travel_jerk",
|
||||
"default_junction_deviation",
|
||||
"top_solid_infill_flow_ratio",
|
||||
"bottom_solid_infill_flow_ratio",
|
||||
"only_one_wall_first_layer",
|
||||
"print_flow_ratio",
|
||||
"seam_gap",
|
||||
"set_other_flow_ratios",
|
||||
"first_layer_flow_ratio",
|
||||
"outer_wall_flow_ratio",
|
||||
"inner_wall_flow_ratio",
|
||||
"overhang_flow_ratio",
|
||||
"sparse_infill_flow_ratio",
|
||||
"internal_solid_infill_flow_ratio",
|
||||
"gap_fill_flow_ratio",
|
||||
"support_flow_ratio",
|
||||
"support_interface_flow_ratio",
|
||||
"role_based_wipe_speed",
|
||||
"wipe_speed",
|
||||
"accel_to_decel_enable",
|
||||
"accel_to_decel_factor",
|
||||
"wipe_on_loops",
|
||||
"wipe_before_external_loop",
|
||||
"bridge_density",
|
||||
"internal_bridge_density",
|
||||
"precise_outer_wall",
|
||||
"bridge_acceleration",
|
||||
"sparse_infill_acceleration",
|
||||
"internal_solid_infill_acceleration",
|
||||
"tree_support_auto_brim",
|
||||
"tree_support_brim_width",
|
||||
"gcode_comments",
|
||||
"gcode_label_objects",
|
||||
"initial_layer_travel_speed",
|
||||
"initial_layer_travel_acceleration",
|
||||
"initial_layer_travel_jerk",
|
||||
"exclude_object",
|
||||
"slow_down_layers",
|
||||
"infill_anchor",
|
||||
"infill_anchor_max",
|
||||
"initial_layer_min_bead_width",
|
||||
"make_overhang_printable",
|
||||
"make_overhang_printable_angle",
|
||||
"make_overhang_printable_hole_size",
|
||||
"notes",
|
||||
"wipe_tower_cone_angle",
|
||||
"wipe_tower_extra_spacing",
|
||||
"wipe_tower_max_purge_speed",
|
||||
"wipe_tower_wall_type",
|
||||
"wipe_tower_extra_rib_length",
|
||||
"wipe_tower_rib_width",
|
||||
"wipe_tower_fillet_wall",
|
||||
"wipe_tower_filament",
|
||||
"wiping_volumes_extruders",
|
||||
"wipe_tower_bridging",
|
||||
"wipe_tower_extra_flow",
|
||||
"single_extruder_multi_material_priming",
|
||||
"toolchange_ordering",
|
||||
"wipe_tower_rotation_angle",
|
||||
"tree_support_branch_distance_organic",
|
||||
"tree_support_branch_diameter_organic",
|
||||
"tree_support_branch_angle_organic",
|
||||
"hole_to_polyhole",
|
||||
"hole_to_polyhole_threshold",
|
||||
"hole_to_polyhole_twisted",
|
||||
"hole_to_polyhole_max_edges",
|
||||
"mmu_segmented_region_max_width",
|
||||
"mmu_segmented_region_interlocking_depth",
|
||||
"small_area_infill_flow_compensation",
|
||||
"small_area_infill_flow_compensation_model",
|
||||
"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",
|
||||
"interlocking_beam",
|
||||
"interlocking_orientation",
|
||||
"interlocking_beam_layer_count",
|
||||
"interlocking_depth",
|
||||
"interlocking_boundary_avoidance",
|
||||
"interlocking_beam_width",
|
||||
"calib_flowrate_topinfill_special_order",
|
||||
// Z Anti-Aliasing (ZAA)
|
||||
"zaa_enabled",
|
||||
"zaa_minimize_perimeter_height",
|
||||
"zaa_dont_alternate_fill_direction",
|
||||
"zaa_min_z",
|
||||
"ironing_expansion",
|
||||
};
|
||||
#include "../slic3r/GUI/generated/Preset_options_generated.cpp"
|
||||
|
||||
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",
|
||||
"filament_soluble", "filament_is_support", "filament_printable", "filament_extruder_compatibility",
|
||||
"filament_max_volumetric_speed", "filament_adaptive_volumetric_speed",
|
||||
"filament_flow_ratio", "filament_density", "filament_adhesiveness_category", "filament_cost", "filament_minimal_purge_on_wipe_tower",
|
||||
"filament_tower_interface_pre_extrusion_dist", "filament_tower_interface_pre_extrusion_length", "filament_tower_ironing_area", "filament_tower_interface_purge_volume",
|
||||
"filament_tower_interface_print_temp",
|
||||
"nozzle_temperature", "nozzle_temperature_initial_layer",
|
||||
// BBS
|
||||
"cool_plate_temp", "textured_cool_plate_temp", "eng_plate_temp", "hot_plate_temp", "textured_plate_temp", "cool_plate_temp_initial_layer", "textured_cool_plate_temp_initial_layer", "eng_plate_temp_initial_layer", "hot_plate_temp_initial_layer", "textured_plate_temp_initial_layer", "supertack_plate_temp_initial_layer", "supertack_plate_temp",
|
||||
// "bed_type",
|
||||
//BBS:temperature_vitrification
|
||||
"temperature_vitrification", "reduce_fan_stop_start_freq","dont_slow_down_outer_wall", "slow_down_for_layer_cooling", "fan_min_speed",
|
||||
"fan_max_speed", "enable_overhang_bridge_fan", "overhang_fan_speed", "overhang_fan_threshold", "close_fan_the_first_x_layers", "close_additional_fan_first_x_layers", "first_x_layer_fan_speed", "full_fan_speed_layer", "initial_layer_fan_speed", "additional_fan_full_speed_layer", "fan_cooling_layer_time", "slow_down_layer_time", "slow_down_min_speed",
|
||||
"filament_start_gcode", "filament_end_gcode", "filament_change_extrusion_role_gcode",
|
||||
//exhaust fan control
|
||||
"activate_air_filtration","activate_air_filtration_during_print","activate_air_filtration_on_completion","during_print_exhaust_fan_speed","complete_print_exhaust_fan_speed",
|
||||
// Retract overrides
|
||||
"filament_deretraction_speed",
|
||||
"filament_retract_after_wipe", // Orca
|
||||
"filament_retract_before_wipe",
|
||||
"filament_retract_lift_above",
|
||||
"filament_retract_lift_below",
|
||||
"filament_retract_lift_enforce",
|
||||
"filament_retract_restart_extra",
|
||||
"filament_retract_when_changing_layer",
|
||||
"filament_retraction_length",
|
||||
"filament_retraction_minimum_travel",
|
||||
"filament_retraction_speed",
|
||||
"filament_wipe",
|
||||
"filament_z_hop",
|
||||
"filament_z_hop_types",
|
||||
// Profile compatibility
|
||||
"filament_vendor", "compatible_prints", "compatible_prints_condition", "compatible_printers", "compatible_printers_condition", "inherits",
|
||||
//BBS
|
||||
"filament_wipe_distance", "additional_cooling_fan_speed",
|
||||
"nozzle_temperature_range_low", "nozzle_temperature_range_high",
|
||||
"filament_extruder_variant",
|
||||
//SoftFever
|
||||
"enable_pressure_advance", "pressure_advance","adaptive_pressure_advance","adaptive_pressure_advance_model","adaptive_pressure_advance_overhangs", "adaptive_pressure_advance_bridges","chamber_temperature", "filament_shrink","filament_shrinkage_compensation_z", "support_material_interface_fan_speed","internal_bridge_fan_speed", "filament_notes" /*,"filament_seam_gap"*/,
|
||||
"ironing_fan_speed",
|
||||
// Filament ironing overrides
|
||||
"filament_ironing_flow", "filament_ironing_spacing", "filament_ironing_inset", "filament_ironing_speed",
|
||||
"filament_loading_speed", "filament_loading_speed_start",
|
||||
"filament_unloading_speed", "filament_unloading_speed_start", "filament_toolchange_delay", "filament_cooling_moves", "filament_stamping_loading_speed", "filament_stamping_distance",
|
||||
"filament_cooling_initial_speed", "filament_cooling_final_speed", "filament_ramming_parameters",
|
||||
"filament_multitool_ramming", "filament_multitool_ramming_volume", "filament_multitool_ramming_flow", "activate_chamber_temp_control", "chamber_minimal_temperature",
|
||||
"filament_long_retractions_when_cut","filament_retraction_distances_when_cut", "idle_temperature",
|
||||
//BBS filament change length while the extruder color
|
||||
"filament_change_length","filament_flush_volumetric_speed","filament_flush_temp","filament_flush_temp_fast", "filament_cooling_before_tower",
|
||||
// Multi-nozzle pre-cooling / ramming / nozzle-change (nc) filament overrides
|
||||
"filament_ramming_volumetric_speed", "filament_ramming_volumetric_speed_nc",
|
||||
"filament_ramming_travel_time", "filament_ramming_travel_time_nc",
|
||||
"filament_pre_cooling_temperature", "filament_pre_cooling_temperature_nc",
|
||||
"filament_preheat_temperature_delta", "filament_retract_length_nc",
|
||||
"filament_change_length_nc", "filament_prime_volume", "filament_prime_volume_nc",
|
||||
"long_retractions_when_ec", "retraction_distances_when_ec",
|
||||
"filament_plugin_config_overrides",
|
||||
//ams chamber
|
||||
"filament_dev_ams_drying_ams_limitations", "filament_dev_ams_drying_temperature", "filament_dev_ams_drying_time", "filament_dev_ams_drying_heat_distortion_temperature",
|
||||
"filament_dev_chamber_drying_bed_temperature", "filament_dev_chamber_drying_time",
|
||||
"filament_dev_drying_softening_temperature", "filament_dev_drying_cooling_temperature"
|
||||
};
|
||||
|
||||
static std::vector<std::string> s_Preset_machine_limits_options {
|
||||
"machine_max_acceleration_extruding", "machine_max_acceleration_retracting", "machine_max_acceleration_travel",
|
||||
@@ -1400,38 +1020,6 @@ static std::vector<std::string> s_Preset_machine_limits_options {
|
||||
"input_shaping_emit", "input_shaping_type", "input_shaping_freq_x", "input_shaping_freq_y", "input_shaping_damp_x", "input_shaping_damp_y",
|
||||
};
|
||||
|
||||
static std::vector<std::string> s_Preset_printer_options {
|
||||
"printer_technology",
|
||||
"printable_area", "extruder_printable_area", "support_parallel_printheads", "parallel_printheads_count", "parallel_printheads_bed_exclude_areas", "bed_exclude_area","bed_custom_texture", "bed_custom_model", "gcode_flavor",
|
||||
"fan_kickstart", "part_cooling_fan_min_pwm", "fan_speedup_time", "fan_speedup_overhangs",
|
||||
"single_extruder_multi_material", "manual_filament_change", "file_start_gcode", "machine_start_gcode", "machine_end_gcode", "before_layer_change_gcode", "printing_by_object_gcode", "layer_change_gcode", "time_lapse_gcode", "wrapping_detection_gcode", "change_filament_gcode", "change_extrusion_role_gcode",
|
||||
"printer_model", "printer_variant", "printer_extruder_id", "printer_extruder_variant", "extruder_variant_list", "default_nozzle_volume_type",
|
||||
"printable_height", "extruder_printable_height", "extruder_clearance_radius", "extruder_clearance_height_to_lid", "extruder_clearance_height_to_rod",
|
||||
"nozzle_height", "master_extruder_id",
|
||||
"default_print_profile", "inherits",
|
||||
"silent_mode",
|
||||
"scan_first_layer", "enable_power_loss_recovery", "wrapping_detection_layers", "wrapping_exclude_area", "machine_load_filament_time", "machine_unload_filament_time", "machine_tool_change_time", "time_cost", "machine_pause_gcode", "template_custom_gcode",
|
||||
"nozzle_type", "nozzle_hrc","auxiliary_fan", "fan_direction", "nozzle_volume","upward_compatible_machine", "z_hop_types", "travel_slope", "retract_lift_enforce","support_chamber_temp_control","support_air_filtration","support_cooling_filter","cooling_filter_enabled","printer_structure","farthest_point_timelapse",
|
||||
"best_object_pos", "head_wrap_detect_zone",
|
||||
"host_type", "print_host", "printhost_apikey", "flashforge_serial_number", "bbl_use_printhost", "printer_agent",
|
||||
"print_host_webui",
|
||||
"printhost_cafile","printhost_port","printhost_authorization_type",
|
||||
"printhost_user", "printhost_password", "printhost_ssl_ignore_revoke", "thumbnails", "thumbnails_format",
|
||||
"use_relative_e_distances", "extruder_type", "use_firmware_retraction", "printer_notes",
|
||||
"grab_length", "support_object_skip_flush", "physical_extruder_map",
|
||||
"cooling_tube_retraction",
|
||||
"cooling_tube_length", "high_current_on_filament_swap", "parking_pos_retraction", "extra_loading_move", "wipe_tower_type", "purge_in_prime_tower", "enable_filament_ramming", "tool_change_on_wipe_tower",
|
||||
"z_offset",
|
||||
"disable_m73", "preferred_orientation", "emit_machine_limits_to_gcode", "pellet_modded_printer", "support_multi_bed_types", "use_3mf", "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",
|
||||
// Multi-nozzle count + pre-heat model printer options
|
||||
"extruder_max_nozzle_count", "group_algo_with_time", "enable_pre_heating", "hotend_heating_rate", "hotend_cooling_rate",
|
||||
"machine_hotend_change_time", "machine_prepare_compensation_time",
|
||||
// Fast-purge printer flag + device/firmware-facing per-variant extruder-change
|
||||
// deretraction speed (unconsumed by the slicer; carried by H2D/A2L/X2D/P2S machine profiles).
|
||||
"support_fast_purge_mode", "deretract_speed_extruder_change",
|
||||
"printer_plugin_config_overrides"
|
||||
};
|
||||
|
||||
static std::vector<std::string> s_Preset_sla_print_options {
|
||||
"layer_height",
|
||||
|
||||
@@ -101,329 +101,23 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|
||||
if (opt_keys.empty())
|
||||
return false;
|
||||
|
||||
// Cache the plenty of parameters, which influence the G-code generator only,
|
||||
// or they are only notes not influencing the generated G-code.
|
||||
static std::unordered_set<std::string> steps_gcode = {
|
||||
//BBS
|
||||
"additional_cooling_fan_speed",
|
||||
"reduce_crossing_wall",
|
||||
"max_travel_detour_distance",
|
||||
"printable_area",
|
||||
//BBS: add bed_exclude_area
|
||||
"bed_exclude_area",
|
||||
"thumbnail_size",
|
||||
"before_layer_change_gcode",
|
||||
"enable_pressure_advance",
|
||||
"pressure_advance",
|
||||
"enable_overhang_bridge_fan",
|
||||
"overhang_fan_speed",
|
||||
"overhang_fan_threshold",
|
||||
"slow_down_for_layer_cooling",
|
||||
"default_acceleration",
|
||||
"deretraction_speed",
|
||||
"close_fan_the_first_x_layers",
|
||||
"machine_end_gcode",
|
||||
"printing_by_object_gcode",
|
||||
"filament_end_gcode",
|
||||
"post_process",
|
||||
// "plugins" is the derived manifest backing the plugin-picker options; on its own it only
|
||||
// affects G-code export. The specific option (e.g. slicing_pipeline_plugin) drives any re-slice.
|
||||
"plugins",
|
||||
"extruder_clearance_height_to_rod",
|
||||
"extruder_clearance_height_to_lid",
|
||||
"extruder_clearance_radius",
|
||||
"nozzle_height",
|
||||
"extruder_colour",
|
||||
"extruder_offset",
|
||||
"filament_flow_ratio",
|
||||
"reduce_fan_stop_start_freq",
|
||||
"dont_slow_down_outer_wall",
|
||||
"fan_cooling_layer_time",
|
||||
"full_fan_speed_layer",
|
||||
"initial_layer_fan_speed",
|
||||
"fan_kickstart",
|
||||
"part_cooling_fan_min_pwm",
|
||||
"fan_speedup_overhangs",
|
||||
"fan_speedup_time",
|
||||
"filament_colour",
|
||||
"default_filament_colour",
|
||||
"filament_diameter",
|
||||
"volumetric_speed_coefficients",
|
||||
"filament_density",
|
||||
"filament_cost",
|
||||
"filament_notes",
|
||||
"outer_wall_acceleration",
|
||||
"inner_wall_acceleration",
|
||||
"initial_layer_acceleration",
|
||||
"top_surface_acceleration",
|
||||
"bridge_acceleration",
|
||||
"travel_acceleration",
|
||||
"sparse_infill_acceleration",
|
||||
"internal_solid_infill_acceleration",
|
||||
// BBS
|
||||
"supertack_plate_temp_initial_layer",
|
||||
"cool_plate_temp_initial_layer",
|
||||
"textured_cool_plate_temp_initial_layer",
|
||||
"eng_plate_temp_initial_layer",
|
||||
"hot_plate_temp_initial_layer",
|
||||
"textured_plate_temp_initial_layer",
|
||||
"gcode_add_line_number",
|
||||
"layer_change_gcode",
|
||||
"time_lapse_gcode",
|
||||
"wrapping_detection_gcode",
|
||||
"fan_min_speed",
|
||||
"fan_max_speed",
|
||||
"printable_height",
|
||||
"slow_down_min_speed",
|
||||
"max_volumetric_extrusion_rate_slope",
|
||||
"max_volumetric_extrusion_rate_slope_segment_length",
|
||||
"extrusion_rate_smoothing_external_perimeter_only",
|
||||
"reduce_infill_retraction",
|
||||
"filename_format",
|
||||
"retraction_minimum_travel",
|
||||
"retract_before_wipe",
|
||||
// Orca:
|
||||
"retract_after_wipe",
|
||||
"retract_when_changing_layer",
|
||||
"retraction_length",
|
||||
"retract_length_toolchange",
|
||||
"z_hop",
|
||||
"travel_slope",
|
||||
"retract_lift_above",
|
||||
"retract_lift_below",
|
||||
"retract_lift_enforce",
|
||||
"retract_restart_extra",
|
||||
"retract_restart_extra_toolchange",
|
||||
"retraction_speed",
|
||||
"use_firmware_retraction",
|
||||
"slow_down_layer_time",
|
||||
"standby_temperature_delta",
|
||||
"preheat_time",
|
||||
"preheat_steps",
|
||||
"machine_start_gcode",
|
||||
"filament_start_gcode",
|
||||
"change_filament_gcode",
|
||||
"wipe",
|
||||
// BBS
|
||||
"wipe_distance",
|
||||
"curr_bed_type",
|
||||
"nozzle_volume",
|
||||
"nozzle_hrc",
|
||||
"required_nozzle_HRC",
|
||||
"upward_compatible_machine",
|
||||
"is_infill_first",
|
||||
// Orca
|
||||
"chamber_temperature",
|
||||
"chamber_minimal_temperature",
|
||||
"thumbnails",
|
||||
"thumbnails_format",
|
||||
"center_of_surface_pattern",
|
||||
"separated_infills",
|
||||
"seam_gap",
|
||||
"role_based_wipe_speed",
|
||||
"wipe_speed",
|
||||
"use_relative_e_distances",
|
||||
"accel_to_decel_enable",
|
||||
"accel_to_decel_factor",
|
||||
"wipe_on_loops",
|
||||
"gcode_comments",
|
||||
"gcode_label_objects",
|
||||
"exclude_object",
|
||||
"support_material_interface_fan_speed",
|
||||
"internal_bridge_fan_speed", // ORCA: Add support for separate internal bridge fan speed control
|
||||
"ironing_fan_speed",
|
||||
"single_extruder_multi_material_priming",
|
||||
"activate_air_filtration",
|
||||
"activate_air_filtration_during_print",
|
||||
"activate_air_filtration_on_completion",
|
||||
"during_print_exhaust_fan_speed",
|
||||
"complete_print_exhaust_fan_speed",
|
||||
"activate_chamber_temp_control",
|
||||
"manual_filament_change",
|
||||
"disable_m73",
|
||||
"use_firmware_retraction",
|
||||
"enable_long_retraction_when_cut",
|
||||
"long_retractions_when_cut",
|
||||
"retraction_distances_when_cut",
|
||||
"filament_long_retractions_when_cut",
|
||||
"filament_retraction_distances_when_cut",
|
||||
"grab_length",
|
||||
"bed_temperature_formula",
|
||||
"filament_notes",
|
||||
"process_notes",
|
||||
"printer_notes",
|
||||
"use_3mf"
|
||||
};
|
||||
#include "../slic3r/GUI/generated/Invalidation_generated.cpp"
|
||||
|
||||
static std::unordered_set<std::string> steps_ignore;
|
||||
|
||||
std::vector<PrintStep> steps;
|
||||
std::vector<PrintStep> steps;
|
||||
std::vector<PrintObjectStep> osteps;
|
||||
bool invalidated = false;
|
||||
|
||||
for (const t_config_option_key &opt_key : opt_keys) {
|
||||
if (steps_gcode.find(opt_key) != steps_gcode.end()) {
|
||||
// These options only affect G-code export or they are just notes without influence on the generated G-code,
|
||||
// so there is nothing to invalidate.
|
||||
steps.emplace_back(psGCodeExport);
|
||||
} else if (steps_ignore.find(opt_key) != steps_ignore.end()) {
|
||||
// These steps have no influence on the G-code whatsoever. Just ignore them.
|
||||
} else if (
|
||||
opt_key == "skirt_type"
|
||||
|| opt_key == "skirt_loops"
|
||||
|| opt_key == "skirt_speed"
|
||||
|| opt_key == "skirt_height"
|
||||
|| opt_key == "min_skirt_length"
|
||||
|| opt_key == "single_loop_draft_shield"
|
||||
|| opt_key == "draft_shield"
|
||||
|| opt_key == "skirt_distance"
|
||||
|| opt_key == "skirt_start_angle"
|
||||
|| opt_key == "ooze_prevention"
|
||||
|| opt_key == "wipe_tower_x"
|
||||
|| opt_key == "wipe_tower_y"
|
||||
|| opt_key == "wipe_tower_rotation_angle") {
|
||||
steps.emplace_back(psSkirtBrim);
|
||||
} else if (
|
||||
opt_key == "slicing_pipeline_plugin"
|
||||
|| opt_key == "print_plugin_config_overrides"
|
||||
|| opt_key == "initial_layer_print_height"
|
||||
|| opt_key == "nozzle_diameter"
|
||||
|| opt_key == "filament_shrink"
|
||||
|| opt_key == "filament_shrinkage_compensation_z"
|
||||
|| opt_key == "resolution"
|
||||
|| opt_key == "precise_z_height"
|
||||
// Spiral Vase forces different kind of slicing than the normal model:
|
||||
// In Spiral Vase mode, holes are closed and only the largest area contour is kept at each layer.
|
||||
// Therefore toggling the Spiral Vase on / off requires complete reslicing.
|
||||
|| opt_key == "spiral_mode") {
|
||||
osteps.emplace_back(posSlice);
|
||||
} else if (
|
||||
opt_key == "print_sequence"
|
||||
|| opt_key == "filament_type"
|
||||
|| opt_key == "chamber_temperature"
|
||||
|| opt_key == "nozzle_temperature_initial_layer"
|
||||
|| opt_key == "filament_minimal_purge_on_wipe_tower"
|
||||
|| opt_key == "filament_max_volumetric_speed"
|
||||
|| opt_key == "filament_adaptive_volumetric_speed"
|
||||
|| opt_key == "filament_loading_speed"
|
||||
|| opt_key == "filament_loading_speed_start"
|
||||
|| opt_key == "filament_unloading_speed"
|
||||
|| opt_key == "filament_unloading_speed_start"
|
||||
|| opt_key == "filament_toolchange_delay"
|
||||
|| opt_key == "filament_cooling_moves"
|
||||
|| opt_key == "filament_stamping_loading_speed"
|
||||
|| opt_key == "filament_stamping_distance"
|
||||
|| opt_key == "filament_cooling_initial_speed"
|
||||
|| opt_key == "filament_cooling_final_speed"
|
||||
|| opt_key == "filament_ramming_parameters"
|
||||
|| opt_key == "filament_multitool_ramming"
|
||||
|| opt_key == "filament_multitool_ramming_volume"
|
||||
|| opt_key == "filament_multitool_ramming_flow"
|
||||
|| opt_key == "filament_max_volumetric_speed"
|
||||
|| opt_key == "gcode_flavor"
|
||||
|| opt_key == "single_extruder_multi_material"
|
||||
|| opt_key == "nozzle_temperature"
|
||||
// BBS
|
||||
|| opt_key == "supertack_plate_temp"
|
||||
|| opt_key == "cool_plate_temp"
|
||||
|| opt_key == "textured_cool_plate_temp"
|
||||
|| opt_key == "eng_plate_temp"
|
||||
|| opt_key == "hot_plate_temp"
|
||||
|| opt_key == "textured_plate_temp"
|
||||
|| opt_key == "enable_prime_tower"
|
||||
|| opt_key == "enable_wrapping_detection"
|
||||
|| opt_key == "prime_tower_enable_framework"
|
||||
|| opt_key == "prime_tower_width"
|
||||
|| opt_key == "prime_tower_brim_width"
|
||||
|| opt_key == "wipe_tower_type"
|
||||
|| opt_key == "prime_tower_skip_points"
|
||||
|| opt_key == "prime_tower_flat_ironing"
|
||||
|| opt_key == "enable_tower_interface_features"
|
||||
|| opt_key == "first_layer_print_sequence"
|
||||
|| opt_key == "other_layers_print_sequence"
|
||||
|| opt_key == "other_layers_print_sequence_nums"
|
||||
|| opt_key == "toolchange_ordering"
|
||||
|| opt_key == "extruder_ams_count"
|
||||
|| opt_key == "extruder_nozzle_stats"
|
||||
|| opt_key == "filament_map_mode"
|
||||
|| opt_key == "filament_map"
|
||||
|| opt_key == "filament_nozzle_map"
|
||||
|| opt_key == "filament_volume_map"
|
||||
|| opt_key == "filament_adhesiveness_category"
|
||||
|| opt_key == "filament_tower_interface_pre_extrusion_dist"
|
||||
|| opt_key == "filament_tower_interface_pre_extrusion_length"
|
||||
|| opt_key == "filament_tower_ironing_area"
|
||||
|| opt_key == "filament_tower_interface_purge_volume"
|
||||
|| opt_key == "filament_tower_interface_print_temp"
|
||||
|| opt_key == "wipe_tower_bridging"
|
||||
|| opt_key == "wipe_tower_extra_flow"
|
||||
|| opt_key == "wipe_tower_no_sparse_layers"
|
||||
|| opt_key == "flush_volumes_matrix"
|
||||
|| opt_key == "prime_volume"
|
||||
|| opt_key == "flush_into_infill"
|
||||
|| opt_key == "flush_into_support"
|
||||
|| opt_key == "initial_layer_infill_speed"
|
||||
|| opt_key == "travel_speed"
|
||||
|| opt_key == "travel_speed_z"
|
||||
|| opt_key == "initial_layer_speed"
|
||||
|| opt_key == "initial_layer_travel_speed"
|
||||
|| opt_key == "initial_layer_travel_acceleration"
|
||||
|| opt_key == "initial_layer_travel_jerk"
|
||||
|| opt_key == "slow_down_layers"
|
||||
|| opt_key == "idle_temperature"
|
||||
|| opt_key == "wipe_tower_cone_angle"
|
||||
|| opt_key == "wipe_tower_extra_spacing"
|
||||
|| opt_key == "wipe_tower_max_purge_speed"
|
||||
|| opt_key == "wipe_tower_wall_type"
|
||||
|| opt_key == "wipe_tower_extra_rib_length"
|
||||
|| opt_key == "wipe_tower_rib_width"
|
||||
|| opt_key == "wipe_tower_fillet_wall"
|
||||
|| opt_key == "wipe_tower_filament"
|
||||
|| opt_key == "wiping_volumes_extruders"
|
||||
|| opt_key == "enable_filament_ramming"
|
||||
|| opt_key == "tool_change_on_wipe_tower"
|
||||
|| opt_key == "purge_in_prime_tower"
|
||||
|| opt_key == "z_offset"
|
||||
|| opt_key == "support_multi_bed_types"
|
||||
) {
|
||||
steps.emplace_back(psWipeTower);
|
||||
steps.emplace_back(psSkirtBrim);
|
||||
} else if (opt_key == "filament_soluble"
|
||||
|| opt_key == "filament_is_support"
|
||||
|| opt_key == "filament_printable"
|
||||
|| opt_key == "filament_change_length"
|
||||
|| opt_key == "independent_support_layer_height") {
|
||||
steps.emplace_back(psWipeTower);
|
||||
// Soluble support interface / non-soluble base interface produces non-soluble interface layers below soluble interface layers.
|
||||
// Thus switching between soluble / non-soluble interface layer material may require recalculation of supports.
|
||||
//FIXME Killing supports on any change of "filament_soluble" is rough. We should check for each object whether that is necessary.
|
||||
osteps.emplace_back(posSupportMaterial);
|
||||
osteps.emplace_back(posSimplifySupportPath);
|
||||
} else if (
|
||||
opt_key == "initial_layer_line_width"
|
||||
|| opt_key == "min_layer_height"
|
||||
|| opt_key == "max_layer_height"
|
||||
//|| opt_key == "resolution"
|
||||
//BBS: when enable arc fitting, we must re-generate perimeter
|
||||
|| opt_key == "enable_arc_fitting"
|
||||
|| opt_key == "print_order"
|
||||
|| opt_key == "wall_sequence") {
|
||||
osteps.emplace_back(posPerimeters);
|
||||
osteps.emplace_back(posEstimateCurledExtrusions);
|
||||
osteps.emplace_back(posInfill);
|
||||
osteps.emplace_back(posSupportMaterial);
|
||||
osteps.emplace_back(posSimplifyPath);
|
||||
osteps.emplace_back(posSimplifyInfill);
|
||||
osteps.emplace_back(posSimplifySupportPath);
|
||||
steps.emplace_back(psSkirtBrim);
|
||||
}
|
||||
else if (opt_key == "z_hop_types") {
|
||||
osteps.emplace_back(posDetectOverhangsForLift);
|
||||
auto it_ps = s_print_steps_map.find(opt_key);
|
||||
auto it_os = s_object_steps_map.find(opt_key);
|
||||
if (it_ps != s_print_steps_map.end() || it_os != s_object_steps_map.end()) {
|
||||
if (it_ps != s_print_steps_map.end())
|
||||
steps.insert(steps.end(), it_ps->second.begin(), it_ps->second.end());
|
||||
if (it_os != s_object_steps_map.end())
|
||||
osteps.insert(osteps.end(), it_os->second.begin(), it_os->second.end());
|
||||
} else {
|
||||
// for legacy, if we can't handle this option let's invalidate all steps
|
||||
//FIXME invalidate all steps of all objects as well?
|
||||
// Unknown option — conservatively invalidate all steps
|
||||
invalidated |= this->invalidate_all_steps();
|
||||
// Continue with the other opt_keys to possibly invalidate any object specific steps.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -756,7 +450,7 @@ StringObjectException Print::sequential_print_clearance_valid(const Print &print
|
||||
#if 0 //do not sort anymore, use the order in object list
|
||||
auto bed_points = get_bed_shape(print_config);
|
||||
float bed_width = bed_points[1].x() - bed_points[0].x();
|
||||
// 如果扩大以后的多边形的距离小于这个值,就需要严格保证从左到右的打印顺序,否则会撞工具头右侧
|
||||
// е¦‚жћњж‰©е¤§д»ҐеђЋзљ„е¤љиѕ№еЅўзљ„и·ќз¦»е°ЏдєЋиї™дёЄеЂјпјЊе°±йњЂи¦ЃдёҐж јдїќиЇЃд»Ће·¦е€°еЏізљ„ж‰“еЌ°йЎєеєЏпјЊеђ¦е€™дјљж’ће·Ґе…·е¤ґеЏідѕ§
|
||||
float unsafe_dist = scale_(print_config.extruder_clearance_max_radius.value - print_config.extruder_clearance_radius.value);
|
||||
struct VecHash
|
||||
{
|
||||
@@ -790,7 +484,7 @@ StringObjectException Print::sequential_print_clearance_valid(const Print &print
|
||||
auto inter_max = std::min(ly2, ry2);
|
||||
auto inter_y = inter_max - inter_min;
|
||||
|
||||
// 如果y方向的重合超过轮廓的膨胀量,说明两个物体在一行,应该先打左边的物体,即先比较二者的x坐标。
|
||||
// 如果yж–№еђ‘зљ„й‡Ќеђ€и¶…иї‡иЅ®е»“зљ„и†ЁиѓЂй‡ЏпјЊиЇґжЋдё¤дёЄз‰©дЅ“在一行,应该先打左边的物体,即先比较二者的xеќђж ‡гЂ‚
|
||||
// If the overlap in the y direction exceeds the expansion of the contour, it means that the two objects are in a row and the object on the left should be hit first, that is, the x coordinates of the two should be compared first.
|
||||
if (inter_y > scale_(0.5 * print.config().extruder_clearance_radius.value)) {
|
||||
if (std::max(rx1 - lx2, lx1 - rx2) < unsafe_dist) {
|
||||
@@ -806,13 +500,13 @@ StringObjectException Print::sequential_print_clearance_valid(const Print &print
|
||||
}
|
||||
}
|
||||
if (l.height > hc1 && r.height < hc1) {
|
||||
// 当前物体超过了顶盖高度,必须后打
|
||||
// 当前物体超过了顶盖й«еє¦пјЊеї…须后打
|
||||
left_right_pair.insert({j, i});
|
||||
BOOST_LOG_TRIVIAL(debug) << "height>hc1, print_instance " << r.print_instance->model_instance->get_object()->name << "(" << r.arrange_score << ")"
|
||||
<< " -> " << l.print_instance->model_instance->get_object()->name << "(" << l.arrange_score << ")";
|
||||
}
|
||||
else if (l.height > hc2 && l.height > r.height && l.arrange_score<r.arrange_score) {
|
||||
// 如果当前物体的高度超过滑杆,且比r高,就给它加一点代价,尽量让高的物体后打(只有物体高度超过滑杆时才有必要按高度来)
|
||||
// 如果当前物体的й«еє¦и¶…иї‡ж»‘жќ†пјЊдё”жЇ”rй«пјЊе°±з»™е®ѓеЉ дёЂз‚№д»Јд»·пјЊе°Ѕй‡Џи®©й«зљ„物体后打(只有物体й«еє¦и¶…иї‡ж»‘жќ†ж—¶ж‰Ќжњ‰еї…и¦ЃжЊ‰й«еє¦жќҐпј‰
|
||||
if (l.arrange_score < r.arrange_score)
|
||||
l.arrange_score = r.arrange_score + 10;
|
||||
BOOST_LOG_TRIVIAL(debug) << "height>hc2, print_instance " << inst.print_instance->model_instance->get_object()->name
|
||||
@@ -822,8 +516,8 @@ StringObjectException Print::sequential_print_clearance_valid(const Print &print
|
||||
}
|
||||
}
|
||||
}
|
||||
// 多做几次代价传播,因为前一次有些值没有更新。
|
||||
// TODO 更好的办法是建立一颗树,一步到位。不过我暂时没精力搞,先就这样吧
|
||||
// е¤љеЃље‡ ж¬Ўд»Јд»·дј ж’пјЊе› дёєе‰ЌдёЂж¬Ўжњ‰дє›еЂјжІЎжњ‰ж›ґж–°гЂ‚
|
||||
// TODO 更好的办法жЇе»єз«‹дёЂйў—ж ‘пјЊдёЂжҐе€°дЅЌгЂ‚дёЌиї‡ж€‘жљ‚ж—¶жІЎзІѕеЉ›жђћпјЊе…€е°±иї™ж ·еђ§
|
||||
for (int k=0;k<5;k++)
|
||||
for (auto p : left_right_pair) {
|
||||
auto &l = print_instance_with_bounding_box[p(0)];
|
||||
@@ -891,7 +585,7 @@ StringObjectException Print::sequential_print_clearance_valid(const Print &print
|
||||
for (int k = 0; k < print_instance_count; k++)
|
||||
{
|
||||
auto inst = print_instance_with_bounding_box[k].print_instance;
|
||||
// 只需要考虑喷嘴到滑杆的偏移量,这个比整个工具头的碰撞半径要小得多
|
||||
// еЏЄйњЂи¦ЃиЂѓи™‘е–·еґе€°ж»‘杆的偏移量,这个比整个工具头的碰撞半径要小得多
|
||||
// Only the offset from the nozzle to the slide bar needs to be considered, which is much smaller than the collision radius of the entire tool head.
|
||||
auto bbox = print_instance_with_bounding_box[k].bounding_box.inflated(-scale_(0.5 * print.config().extruder_clearance_radius.value + object_skirt_offset));
|
||||
auto iy1 = bbox.min.y();
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -490,6 +490,7 @@ set(SLIC3R_GUI_SOURCES
|
||||
GUI/TabButton.hpp
|
||||
GUI/Tab.cpp
|
||||
GUI/Tab.hpp
|
||||
GUI/TabLayoutExtra.cpp
|
||||
GUI/TaskManager.cpp
|
||||
GUI/TaskManager.hpp
|
||||
GUI/TextLines.cpp
|
||||
@@ -830,6 +831,16 @@ else ()
|
||||
endif ()
|
||||
target_include_directories(libslic3r_gui PRIVATE Utils ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
# Tab.cpp #includes GUI/generated/TabLayout_generated.cpp, so it must not be compiled
|
||||
# while the codegen is rewriting it (same contract as libslic3r's generated includes).
|
||||
if(TARGET codegen_config)
|
||||
add_dependencies(libslic3r_gui codegen_config)
|
||||
set_source_files_properties(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/GUI/Tab.cpp"
|
||||
PROPERTIES OBJECT_DEPENDS "${CONFIG_GENERATED_SOURCES}"
|
||||
)
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
target_include_directories(libslic3r_gui SYSTEM PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../deps/WebView2/include)
|
||||
target_link_libraries(libslic3r_gui Advapi32)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -590,6 +590,7 @@ private:
|
||||
|
||||
void add_filament_overrides_page();
|
||||
void update_filament_overrides_page(const DynamicPrintConfig* printers_config);
|
||||
void build_extra_layout(); // TabLayoutExtra.cpp: toolchange/ramming/dependencies/notes
|
||||
void update_volumetric_flow_preset_hints();
|
||||
|
||||
std::map<std::string, ::CheckBox*> m_overrides_options;
|
||||
@@ -663,6 +664,11 @@ public:
|
||||
void extruders_count_changed(size_t extruders_count);
|
||||
PageShp build_kinematics_page();
|
||||
void build_unregular_pages(bool from_initial_build = false);
|
||||
void build_fff_extra_layout(); // TabLayoutExtra.cpp: Basic info page with bed-shape widget
|
||||
// Hook methods called from TabPrinter_build_basic_info_layout (TabLayout_generated.cpp)
|
||||
void layout_hook_printable_space(ConfigOptionsGroup* optgroup); // bed shape widget
|
||||
void layout_hook_advanced(ConfigOptionsGroup* optgroup); // thumbnail m_on_change
|
||||
void layout_hook_cooling_fan(ConfigOptionsGroup* optgroup); // multi-option line
|
||||
void on_preset_loaded() override;
|
||||
void init_options_list() override;
|
||||
void msw_rescale() override;
|
||||
|
||||
217
src/slic3r/GUI/TabLayoutExtra.cpp
Normal file
217
src/slic3r/GUI/TabLayoutExtra.cpp
Normal file
@@ -0,0 +1,217 @@
|
||||
// TabLayoutExtra.cpp
|
||||
//
|
||||
// TabFilament::build_extra_layout() - member function implementation.
|
||||
//
|
||||
// Supplements TabLayout_generated.cpp with UI sections that require custom
|
||||
// widget factories (create_line_with_widget) and therefore cannot be
|
||||
// auto-generated from the proto schema.
|
||||
//
|
||||
// Called from TabFilament::build() after TabFilament_build_main_layout():
|
||||
// 1. Toolchange + ramming parameters sections (single + multi extruder)
|
||||
// 2. Setting Overrides page (checkbox-driven nullable retraction overrides)
|
||||
// 3. Dependencies page (compatible_printers and compatible_prints widgets)
|
||||
// 4. Notes page
|
||||
|
||||
#include "Tab.hpp"
|
||||
#include "GUI_App.hpp" // dots, wxGetApp()
|
||||
#include "libslic3r/FlushVolCalc.hpp" // g_max_flush_volume (needed by WipeTowerDialog)
|
||||
#include "WipeTowerDialog.hpp" // RammingDialog
|
||||
#include "MsgDialog.hpp" // InfoDialog
|
||||
#include "libslic3r/GCode/Thumbnails.hpp"
|
||||
#include "format.hpp"
|
||||
|
||||
namespace Slic3r { namespace GUI {
|
||||
|
||||
void TabFilament::build_extra_layout()
|
||||
{
|
||||
constexpr int notes_field_height = 25;
|
||||
|
||||
// -- Continue the Multimaterial page ----------------------------------
|
||||
// TabFilament_build_main_layout() ended after the Multi Filament optgroup.
|
||||
// We continue on the same page by accessing m_pages.back().
|
||||
{
|
||||
PageShp page = m_pages.back();
|
||||
|
||||
// Tool change parameters - single extruder MM printers
|
||||
// (includes filament_ramming_parameters which needs a custom button widget)
|
||||
{
|
||||
auto optgroup = page->new_optgroup(L("Tool change parameters with single extruder MM printers"), L"param_toolchange");
|
||||
optgroup->append_single_option_line("filament_loading_speed_start", "material_multimaterial#loading-speed-at-the-start");
|
||||
optgroup->append_single_option_line("filament_loading_speed", "material_multimaterial#loading-speed");
|
||||
optgroup->append_single_option_line("filament_unloading_speed_start", "material_multimaterial#unloading-speed-at-the-start");
|
||||
optgroup->append_single_option_line("filament_unloading_speed", "material_multimaterial#unloading-speed");
|
||||
optgroup->append_single_option_line("filament_toolchange_delay", "material_multimaterial#delay-after-unloading");
|
||||
optgroup->append_single_option_line("filament_cooling_moves", "material_multimaterial#number-of-cooling-moves");
|
||||
optgroup->append_single_option_line("filament_cooling_initial_speed", "material_multimaterial#speed-of-the-first-cooling-move");
|
||||
optgroup->append_single_option_line("filament_cooling_final_speed", "material_multimaterial#speed-of-the-last-cooling-move");
|
||||
optgroup->append_single_option_line("filament_stamping_loading_speed", "material_multimaterial#stamping-loading-speed");
|
||||
optgroup->append_single_option_line("filament_stamping_distance", "material_multimaterial#stamping-distance");
|
||||
create_line_with_widget(optgroup.get(), "filament_ramming_parameters",
|
||||
"material_multimaterial#ramming-parameters",
|
||||
[this](wxWindow* parent) {
|
||||
Button* btn = new Button(parent, _(L("Set")) + " " + dots);
|
||||
btn->SetStyle(ButtonStyle::Regular, ButtonType::Parameter);
|
||||
auto sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
sizer->Add(btn);
|
||||
btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) {
|
||||
RammingDialog dlg(this,
|
||||
(m_config->option<ConfigOptionStrings>("filament_ramming_parameters"))->get_at(0));
|
||||
if (dlg.ShowModal() == wxID_OK) {
|
||||
load_key_value("filament_ramming_parameters", dlg.get_parameters());
|
||||
update_changed_ui();
|
||||
}
|
||||
});
|
||||
return sizer;
|
||||
});
|
||||
}
|
||||
|
||||
// Tool change parameters - multi extruder MM printers
|
||||
{
|
||||
auto optgroup = page->new_optgroup(L("Tool change parameters with multi extruder MM printers"), L"param_toolchange_multi_extruder");
|
||||
optgroup->append_single_option_line("filament_multitool_ramming", "material_multimaterial#tool-change-parameters-with-multi-extruder");
|
||||
optgroup->append_single_option_line("filament_multitool_ramming_volume", "material_multimaterial#multi-tool-ramming-volume");
|
||||
optgroup->append_single_option_line("filament_multitool_ramming_flow", "material_multimaterial#multi-tool-ramming-flow");
|
||||
}
|
||||
}
|
||||
|
||||
// -- Setting Overrides page --------------------------------------------
|
||||
// Checkbox-driven nullable retraction overrides - complex runtime logic,
|
||||
// cannot be expressed in the proto schema.
|
||||
add_filament_overrides_page();
|
||||
|
||||
// -- Dependencies page -------------------------------------------------
|
||||
// compatible_printers and compatible_prints require create_line_with_widget
|
||||
// and must come BEFORE the text condition inputs in each optgroup.
|
||||
{
|
||||
auto page = add_options_page(L("Dependencies"), "advanced");
|
||||
{
|
||||
auto optgroup = page->new_optgroup(L("Compatible printers"), L"param_dependencies_printers");
|
||||
create_line_with_widget(optgroup.get(), "compatible_printers", "", [this](wxWindow* parent) {
|
||||
return compatible_widget_create(parent, m_compatible_printers);
|
||||
});
|
||||
Option option = optgroup->get_option("compatible_printers_condition");
|
||||
option.opt.full_width = true;
|
||||
optgroup->append_single_option_line(option, "material_dependencies#compatible-printers");
|
||||
}
|
||||
{
|
||||
auto optgroup = page->new_optgroup(L("Compatible process profiles"), L"param_dependencies_presets");
|
||||
create_line_with_widget(optgroup.get(), "compatible_prints", "", [this](wxWindow* parent) {
|
||||
return compatible_widget_create(parent, m_compatible_prints);
|
||||
});
|
||||
Option option = optgroup->get_option("compatible_prints_condition");
|
||||
option.opt.full_width = true;
|
||||
optgroup->append_single_option_line(option, "material_dependencies#compatible-process-profiles");
|
||||
}
|
||||
}
|
||||
|
||||
// -- Notes page --------------------------------------------------------
|
||||
{
|
||||
auto page = add_options_page(L("Notes"), "custom-gcode_note");
|
||||
auto optgroup = page->new_optgroup(L("Notes"), L"note", 0);
|
||||
Option option = optgroup->get_option("filament_notes");
|
||||
option.opt.full_width = true;
|
||||
option.opt.height = notes_field_height;
|
||||
optgroup->append_single_option_line(option);
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// TabPrinter::build_fff_extra_layout()
|
||||
//
|
||||
// Builds the "Basic information" page for the Printer/FFF tab.
|
||||
// Kept here (not generated) because it contains:
|
||||
// - create_line_with_widget for printable_area (bed shape editor)
|
||||
// - m_on_change for the thumbnails field (thumbnail format sync logic)
|
||||
// - append_line for Cooling Fan multi-option line (fan_speedup_time + fan_speedup_overhangs)
|
||||
//
|
||||
// Called from TabPrinter::build_fff() before TabPrinter_build_gcode_layout().
|
||||
// -----------------------------------------------------------------------------
|
||||
// ── TabPrinter hook methods called by TabPrinter_build_basic_information_layout ──
|
||||
// These implement the optgroups that cannot be auto-generated from yaml because they
|
||||
// require custom widget factories, special m_on_change callbacks, or multi-option lines.
|
||||
|
||||
void TabPrinter::layout_hook_printable_space(ConfigOptionsGroup* optgroup)
|
||||
{
|
||||
// Bed shape widget must be FIRST in the group
|
||||
create_line_with_widget(optgroup, "printable_area", "custom-svg-and-png-bed-textures_124612", [this](wxWindow* parent) {
|
||||
return create_bed_shape_widget(parent);
|
||||
});
|
||||
Option option = optgroup->get_option("bed_exclude_area");
|
||||
option.opt.full_width = true;
|
||||
optgroup->append_single_option_line(option, "printer_basic_information_printable_space#excluded-bed-area");
|
||||
optgroup->append_single_option_line("printable_height", "printer_basic_information_printable_space#printable-height");
|
||||
optgroup->append_single_option_line("support_multi_bed_types", "printer_basic_information_printable_space#support-multi-bed-types");
|
||||
optgroup->append_single_option_line("best_object_pos", "printer_basic_information_printable_space#best-object-position");
|
||||
optgroup->append_single_option_line("z_offset", "printer_basic_information_printable_space#z-offset");
|
||||
optgroup->append_single_option_line("preferred_orientation", "printer_basic_information_printable_space#preferred-orientation");
|
||||
}
|
||||
|
||||
void TabPrinter::layout_hook_advanced(ConfigOptionsGroup* optgroup)
|
||||
{
|
||||
optgroup->append_single_option_line("printer_structure", "printer_basic_information_advanced#printer-structure");
|
||||
optgroup->append_single_option_line("gcode_flavor", "printer_basic_information_advanced#g-code-flavor");
|
||||
optgroup->append_single_option_line("pellet_modded_printer", "printer_basic_information_advanced#pellet-modded-printer");
|
||||
optgroup->append_single_option_line("bbl_use_printhost", "printer_basic_information_advanced#use-3rd-party-print-host");
|
||||
optgroup->append_single_option_line("scan_first_layer", "printer_basic_information_advanced#scan-first-layer");
|
||||
optgroup->append_single_option_line("enable_power_loss_recovery", "printer_basic_information_advanced#power-loss-recovery");
|
||||
optgroup->append_single_option_line("disable_m73", "printer_basic_information_advanced#disable-set-remaining-print-time");
|
||||
{
|
||||
Option option = optgroup->get_option("thumbnails");
|
||||
option.opt.full_width = true;
|
||||
optgroup->append_single_option_line(option, "printer_basic_information_advanced#g-code-thumbnails");
|
||||
}
|
||||
// Thumbnail format sync — cannot be expressed in proto schema
|
||||
optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value) {
|
||||
wxTheApp->CallAfter([this, opt_key, value]() {
|
||||
if (opt_key == "thumbnails" && m_config->has("thumbnails_format")) {
|
||||
const std::string val = boost::any_cast<std::string>(value);
|
||||
if (!value.empty()) {
|
||||
auto [thumbnails_list, errors] = GCodeThumbnails::make_and_check_thumbnail_list(val);
|
||||
if (errors != enum_bitmask<ThumbnailError>()) {
|
||||
std::string error_str = format(_u8L("Invalid value provided for parameter %1%: %2%"), "thumbnails", val);
|
||||
error_str += GCodeThumbnails::get_error_string(errors);
|
||||
InfoDialog(parent(), _L("G-code flavor is switched"), from_u8(error_str)).ShowModal();
|
||||
}
|
||||
if (!thumbnails_list.empty()) {
|
||||
GCodeThumbnailsFormat old_format = GCodeThumbnailsFormat(m_config->option("thumbnails_format")->getInt());
|
||||
GCodeThumbnailsFormat new_format = thumbnails_list.begin()->first;
|
||||
if (old_format != new_format) {
|
||||
DynamicPrintConfig new_conf = *m_config;
|
||||
auto* opt = m_config->option("thumbnails_format")->clone();
|
||||
opt->setInt(int(new_format));
|
||||
new_conf.set_key_value("thumbnails_format", opt);
|
||||
load_config(new_conf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
update_dirty();
|
||||
on_value_change(opt_key, value);
|
||||
});
|
||||
};
|
||||
optgroup->append_single_option_line("use_relative_e_distances", "printer_basic_information_advanced#use-relative-e-distances");
|
||||
optgroup->append_single_option_line("use_firmware_retraction", "printer_basic_information_advanced#use-firmware-retraction");
|
||||
optgroup->append_single_option_line("time_cost", "printer_basic_information_advanced#time-cost");
|
||||
}
|
||||
|
||||
void TabPrinter::layout_hook_cooling_fan(ConfigOptionsGroup* optgroup)
|
||||
{
|
||||
Line line = Line{ L("Fan speed-up time"), optgroup->get_option("fan_speedup_time").opt.tooltip };
|
||||
line.label_path = "printer_basic_information_cooling_fan#fan-speed-up-time";
|
||||
line.append_option(optgroup->get_option("fan_speedup_time"));
|
||||
line.append_option(optgroup->get_option("fan_speedup_overhangs"));
|
||||
optgroup->append_line(line);
|
||||
optgroup->append_single_option_line("fan_kickstart", "printer_basic_information_cooling_fan#fan-kick-start-time");
|
||||
optgroup->append_single_option_line("part_cooling_fan_min_pwm", "printer_basic_information_cooling_fan#minimum-non-zero-part-cooling-fan-speed");
|
||||
}
|
||||
|
||||
// build_fff_extra_layout is kept for backward compatibility.
|
||||
// It now delegates to the yaml-generated TabPrinter_build_basic_info_layout
|
||||
// which calls the hook methods above.
|
||||
void TabPrinter::build_fff_extra_layout()
|
||||
{
|
||||
// Superseded: Tab.cpp now calls TabPrinter_build_basic_info_layout(*this) directly.
|
||||
// Hook methods below are called by that generated function.
|
||||
}
|
||||
|
||||
} } // namespace Slic3r::GUI
|
||||
260
tools/codegen_toolchain.py
Normal file
260
tools/codegen_toolchain.py
Normal file
@@ -0,0 +1,260 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Toolchain resolution for the config codegen.
|
||||
|
||||
The codegen needs exactly three things: a protoc binary, the protobuf Python
|
||||
runtime and pyyaml. Every entry point used to install `grpcio-tools` to get
|
||||
protoc, which drags in the grpcio C extension: it has no Windows/ARM64 wheel and
|
||||
falls back to building from source there, which is what broke the ARM64 build
|
||||
("Failed building wheel for grpcio" -> "protoc not found"). Nothing in the
|
||||
codegen uses gRPC.
|
||||
|
||||
Resolution order, so callers only ever run `python tools/run_codegen.py`:
|
||||
|
||||
protoc $PROTOC -> PATH -> cached download -> grpc_tools (if installed) ->
|
||||
pinned, checksum-verified protoc release downloaded into
|
||||
.codegen-tools/ (gitignored)
|
||||
runtime the current interpreter, else a cached virtualenv under
|
||||
.codegen-tools/venv that the entry point re-execs into
|
||||
|
||||
Set PROTOC=/path/to/protoc (or put protoc on PATH) to build offline.
|
||||
"""
|
||||
|
||||
import hashlib
|
||||
import importlib.util
|
||||
import os
|
||||
import platform
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import urllib.request
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parent.parent
|
||||
CACHE_DIR = ROOT / ".codegen-tools"
|
||||
|
||||
# Pinned so every machine generates with the same compiler, and checksummed
|
||||
# because we execute what we download. To bump: change the version and refresh
|
||||
# every hash from https://github.com/protocolbuffers/protobuf/releases/tag/v<ver>
|
||||
PROTOC_VERSION = "28.3"
|
||||
PROTOC_ARCHIVE_SHA256 = {
|
||||
"win64": "ce64f49bdeddef49ce4bd313a8f59bcf92fcf67b5831efbf66170386d2e66948",
|
||||
"linux-x86_64": "0ad949f04a6a174da83cdcbdb36dee0a4925272a5b6d83f79a6bf9852076d53f",
|
||||
"linux-aarch_64": "1de522032a8b194002fe35cab86d747848238b5e4de4f99648372079f5b46f9a",
|
||||
"osx-universal_binary": "52df502b263da20f3311b23b5c6553d10cc25c6ebb85df381d80a2806b6a698b",
|
||||
}
|
||||
|
||||
# pip name -> import name
|
||||
PYTHON_PACKAGES = {"protobuf": "google.protobuf", "pyyaml": "yaml"}
|
||||
|
||||
# Guards against an endless re-exec loop if the virtualenv still can't import.
|
||||
_BOOTSTRAP_ENV = "ORCA_CODEGEN_BOOTSTRAPPED"
|
||||
|
||||
_PROTOC_EXE = "protoc.exe" if os.name == "nt" else "protoc"
|
||||
|
||||
|
||||
def _protoc_dir():
|
||||
return CACHE_DIR / f"protoc-{PROTOC_VERSION}"
|
||||
|
||||
|
||||
def _archive_key():
|
||||
"""Release asset for this host, or None if protobuf ships no build for it."""
|
||||
if sys.platform == "win32":
|
||||
# There is no win/arm64 release; the x64 build runs under Windows'
|
||||
# emulation, which is how the ARM64 CI job gets a protoc.
|
||||
return "win64"
|
||||
if sys.platform == "darwin":
|
||||
return "osx-universal_binary"
|
||||
if sys.platform.startswith("linux"):
|
||||
machine = platform.machine().lower()
|
||||
if machine in ("x86_64", "amd64"):
|
||||
return "linux-x86_64"
|
||||
if machine in ("aarch64", "arm64"):
|
||||
return "linux-aarch_64"
|
||||
return None
|
||||
|
||||
|
||||
def _download_protoc():
|
||||
"""Fetch and unpack the pinned protoc. Returns the binary path, or None."""
|
||||
key = _archive_key()
|
||||
if key is None:
|
||||
print(f" ERROR: no pinned protoc release for {sys.platform}/{platform.machine()}.")
|
||||
print(" Install protoc from your package manager and re-run, or set PROTOC=<path>.")
|
||||
return None
|
||||
|
||||
url = (f"https://github.com/protocolbuffers/protobuf/releases/download/"
|
||||
f"v{PROTOC_VERSION}/protoc-{PROTOC_VERSION}-{key}.zip")
|
||||
print(f" Downloading protoc {PROTOC_VERSION} ({key})...")
|
||||
CACHE_DIR.mkdir(parents=True, exist_ok=True)
|
||||
with tempfile.TemporaryDirectory(dir=CACHE_DIR) as tmp:
|
||||
archive = Path(tmp) / "protoc.zip"
|
||||
try:
|
||||
with urllib.request.urlopen(url, timeout=120) as response:
|
||||
archive.write_bytes(response.read())
|
||||
except OSError as exc:
|
||||
print(f" ERROR: download failed: {exc}")
|
||||
print(" Install protoc manually and re-run, or set PROTOC=<path>.")
|
||||
return None
|
||||
|
||||
actual = hashlib.sha256(archive.read_bytes()).hexdigest()
|
||||
expected = PROTOC_ARCHIVE_SHA256[key]
|
||||
if actual != expected:
|
||||
print(f" ERROR: protoc archive checksum mismatch for {key} {PROTOC_VERSION}:")
|
||||
print(f" expected {expected}")
|
||||
print(f" actual {actual}")
|
||||
return None
|
||||
|
||||
# Unpack the whole archive, not just bin/: protoc resolves the well-known
|
||||
# imports (google/protobuf/descriptor.proto) from ../include next to it.
|
||||
staging = Path(tmp) / "unpacked"
|
||||
with zipfile.ZipFile(archive) as zf:
|
||||
zf.extractall(staging)
|
||||
|
||||
target = _protoc_dir()
|
||||
if target.exists():
|
||||
shutil.rmtree(target)
|
||||
# Move into place only once complete, so an interrupted run never leaves
|
||||
# a half-extracted toolchain that later runs would happily use.
|
||||
shutil.move(str(staging), str(target))
|
||||
|
||||
binary = target / "bin" / _PROTOC_EXE
|
||||
if not binary.exists():
|
||||
print(f" ERROR: protoc archive did not contain bin/{_PROTOC_EXE}")
|
||||
return None
|
||||
binary.chmod(binary.stat().st_mode | 0o755)
|
||||
return binary
|
||||
|
||||
|
||||
def find_protoc(allow_download=True):
|
||||
"""Return the protoc command as a list, or None if it can't be resolved."""
|
||||
override = os.environ.get("PROTOC")
|
||||
if override:
|
||||
return [override]
|
||||
|
||||
on_path = shutil.which("protoc")
|
||||
if on_path:
|
||||
return [on_path]
|
||||
|
||||
cached = _protoc_dir() / "bin" / _PROTOC_EXE
|
||||
if cached.exists():
|
||||
return [str(cached)]
|
||||
|
||||
# Honour a pre-existing grpcio-tools install rather than downloading.
|
||||
if importlib.util.find_spec("grpc_tools") is not None:
|
||||
return [sys.executable, "-m", "grpc_tools.protoc"]
|
||||
|
||||
if allow_download:
|
||||
binary = _download_protoc()
|
||||
if binary is not None:
|
||||
return [str(binary)]
|
||||
return None
|
||||
|
||||
|
||||
def missing_packages():
|
||||
"""pip names of the required Python packages this interpreter can't import."""
|
||||
missing = []
|
||||
for pip_name, module in PYTHON_PACKAGES.items():
|
||||
try:
|
||||
found = importlib.util.find_spec(module) is not None
|
||||
except (ImportError, ValueError):
|
||||
found = False
|
||||
if not found:
|
||||
missing.append(pip_name)
|
||||
return missing
|
||||
|
||||
|
||||
def _venv_python():
|
||||
venv_dir = CACHE_DIR / "venv"
|
||||
if os.name == "nt":
|
||||
return venv_dir / "Scripts" / "python.exe"
|
||||
return venv_dir / "bin" / "python"
|
||||
|
||||
|
||||
def bootstrap_python():
|
||||
"""The cached virtualenv interpreter, if it exists and has the packages."""
|
||||
python = _venv_python()
|
||||
if not python.exists():
|
||||
return None
|
||||
probe = subprocess.run([str(python), "-c", "import google.protobuf, yaml"],
|
||||
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||
return python if probe.returncode == 0 else None
|
||||
|
||||
|
||||
def _ensure_venv(missing):
|
||||
"""Create/reuse .codegen-tools/venv with the required packages installed."""
|
||||
python = _venv_python()
|
||||
|
||||
if not python.exists():
|
||||
print(f" Creating codegen virtualenv in {python.parent.parent}...")
|
||||
if subprocess.run([sys.executable, "-m", "venv", str(python.parent.parent)]).returncode != 0 \
|
||||
or not python.exists():
|
||||
return None
|
||||
|
||||
print(f" Installing {', '.join(missing)} into the codegen virtualenv...")
|
||||
result = subprocess.run([str(python), "-m", "pip", "install", "--quiet",
|
||||
"--disable-pip-version-check", *missing])
|
||||
return python if result.returncode == 0 else None
|
||||
|
||||
|
||||
def ensure_python_runtime():
|
||||
"""
|
||||
Guarantee protobuf + pyyaml are importable.
|
||||
|
||||
If they aren't, re-run the calling script in a cached virtualenv that has
|
||||
them and exit with its status. Keeping the packages out of the caller's
|
||||
interpreter is what lets the build scripts work on distros that refuse
|
||||
`pip install` into a system Python (PEP 668).
|
||||
"""
|
||||
missing = missing_packages()
|
||||
if not missing:
|
||||
return
|
||||
|
||||
if os.environ.get(_BOOTSTRAP_ENV):
|
||||
# We are already inside the bootstrapped environment: installing again
|
||||
# would just fail the same way.
|
||||
print(f" ERROR: {', '.join(missing)} still missing after bootstrap.")
|
||||
sys.exit(1)
|
||||
|
||||
# Reuse a complete virtualenv as-is: builds call this every time, and pip
|
||||
# would otherwise hit the network on each one.
|
||||
python = bootstrap_python() or _ensure_venv(missing)
|
||||
if python is None:
|
||||
print(f" ERROR: could not provide {', '.join(missing)}.")
|
||||
print(f" Install them for this interpreter: {sys.executable} -m pip install "
|
||||
f"{' '.join(missing)}")
|
||||
sys.exit(1)
|
||||
|
||||
env = dict(os.environ, **{_BOOTSTRAP_ENV: "1"})
|
||||
sys.exit(subprocess.run([str(python), *sys.argv], env=env).returncode)
|
||||
|
||||
|
||||
def toolchain_ready():
|
||||
"""
|
||||
True if the codegen can run without downloading or installing anything --
|
||||
either from this interpreter or by re-execing into an existing bootstrap
|
||||
virtualenv. This is what decides whether a build regenerates on proto edits.
|
||||
"""
|
||||
if missing_packages() and bootstrap_python() is None:
|
||||
return False
|
||||
return find_protoc(allow_download=False) is not None
|
||||
|
||||
|
||||
def main():
|
||||
# --check is what ConfigCodegen.cmake probes with: it answers whether this
|
||||
# interpreter can regenerate during a build, and must not download, install
|
||||
# or create anything while doing so.
|
||||
if "--check" in sys.argv[1:]:
|
||||
return 0 if toolchain_ready() else 1
|
||||
|
||||
missing = missing_packages()
|
||||
print(f"python: {sys.executable}")
|
||||
print(f"packages: {'all present' if not missing else 'missing ' + ', '.join(missing)}")
|
||||
protoc = find_protoc()
|
||||
print(f"protoc: {' '.join(protoc) if protoc else 'NOT FOUND'}")
|
||||
return 0 if protoc else 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
1049
tools/config_codegen.py
Normal file
1049
tools/config_codegen.py
Normal file
File diff suppressed because it is too large
Load Diff
67
tools/config_metadata.py
Normal file
67
tools/config_metadata.py
Normal file
@@ -0,0 +1,67 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Access to the orca.* option extensions declared in config_metadata.proto.
|
||||
|
||||
The extensions are read straight out of the compiled descriptor set: protoc runs
|
||||
with --include_imports, so config_metadata.proto travels inside the .desc file
|
||||
that the codegen already consumes. Registering it in the default descriptor pool
|
||||
before the descriptor set is parsed is what makes the custom options resolve
|
||||
instead of landing in unknown fields.
|
||||
|
||||
Doing it this way keeps generated code out of git. The alternative -- a checked-in
|
||||
config_metadata_pb2.py -- also pinned the protobuf runtime to whichever protoc
|
||||
produced it, because gencode embeds a hard ValidateProtobufRuntimeVersion() check.
|
||||
"""
|
||||
|
||||
from google.protobuf import descriptor_pb2, descriptor_pool
|
||||
|
||||
METADATA_PROTO = "config_metadata.proto"
|
||||
|
||||
|
||||
class Metadata:
|
||||
"""
|
||||
Stand-in for the generated config_metadata_pb2 module.
|
||||
|
||||
Exposes each orca extension as an attribute holding its FieldDescriptor
|
||||
(usable as `options.Extensions[meta.label]`) and each enum value as an int
|
||||
constant (`meta.MODE_SIMPLE`, `meta.STEP_SLICE`, ...), matching how the
|
||||
generated module was used.
|
||||
"""
|
||||
|
||||
def __init__(self, file_descriptor):
|
||||
for name, extension in file_descriptor.extensions_by_name.items():
|
||||
setattr(self, name, extension)
|
||||
for enum in file_descriptor.enum_types_by_name.values():
|
||||
for value in enum.values:
|
||||
setattr(self, value.name, value.number)
|
||||
|
||||
|
||||
def load_descriptor_set(path):
|
||||
"""
|
||||
Read a protoc descriptor set and return (FileDescriptorSet, Metadata).
|
||||
|
||||
The file is parsed twice on purpose: the first pass only locates the embedded
|
||||
config_metadata.proto so its extensions can be registered, the second one
|
||||
parses with those extensions known.
|
||||
"""
|
||||
with open(path, 'rb') as f:
|
||||
raw = f.read()
|
||||
|
||||
probe = descriptor_pb2.FileDescriptorSet()
|
||||
probe.ParseFromString(raw)
|
||||
metadata_file = next((f for f in probe.file if f.name == METADATA_PROTO), None)
|
||||
if metadata_file is None:
|
||||
raise RuntimeError(
|
||||
f"{path} does not contain {METADATA_PROTO} -- protoc must be run with "
|
||||
"--include_imports")
|
||||
|
||||
pool = descriptor_pool.Default()
|
||||
try:
|
||||
file_descriptor = pool.FindFileByName(METADATA_PROTO)
|
||||
except KeyError:
|
||||
pool.Add(metadata_file)
|
||||
file_descriptor = pool.FindFileByName(METADATA_PROTO)
|
||||
|
||||
descriptor_set = descriptor_pb2.FileDescriptorSet()
|
||||
descriptor_set.ParseFromString(raw)
|
||||
return descriptor_set, Metadata(file_descriptor)
|
||||
106
tools/run_codegen.py
Normal file
106
tools/run_codegen.py
Normal file
@@ -0,0 +1,106 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Convenience script: runs the codegen pipeline.
|
||||
|
||||
1. Compile .proto -> binary descriptor set (protoc)
|
||||
2. Generate C++ from descriptors (config_codegen.py)
|
||||
3. Validate output against original
|
||||
|
||||
The toolchain (protoc, protobuf, pyyaml) is resolved by codegen_toolchain.py, so
|
||||
this script is the single entry point every build script and CI job calls -- no
|
||||
`pip install` lines needed around it.
|
||||
|
||||
Usage:
|
||||
python tools/run_codegen.py # full pipeline
|
||||
python tools/run_codegen.py --validate-only # just validate
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
||||
import codegen_toolchain # noqa: E402
|
||||
|
||||
ROOT = Path(__file__).resolve().parent.parent
|
||||
PROTO_DIR = ROOT / "src" / "PrintConfigs"
|
||||
CODEGEN_OUT = ROOT / "src" / "slic3r" / "GUI" / "generated"
|
||||
DESC_FILE = ROOT / "config.desc"
|
||||
LAYOUT_YAML = PROTO_DIR / "layout.yaml"
|
||||
|
||||
|
||||
def run(cmd, **kwargs):
|
||||
print(f" $ {' '.join(str(c) for c in cmd)}")
|
||||
result = subprocess.run(cmd, **kwargs)
|
||||
if result.returncode != 0:
|
||||
print(f" FAILED (exit code {result.returncode})")
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def step_compile():
|
||||
print("\n=== Step 1: Compile .proto -> descriptor set ===")
|
||||
proto_files = [f for f in PROTO_DIR.glob("*.proto") if not f.name.endswith("_gen.proto") and f.name != "config_metadata.proto"]
|
||||
if not proto_files:
|
||||
print(" ERROR: No .proto files found")
|
||||
return False
|
||||
|
||||
protoc = codegen_toolchain.find_protoc()
|
||||
if protoc is None:
|
||||
return False
|
||||
|
||||
return run(protoc + [
|
||||
f"--proto_path={PROTO_DIR}",
|
||||
f"--descriptor_set_out={DESC_FILE}",
|
||||
"--include_imports",
|
||||
] + [str(f) for f in proto_files])
|
||||
|
||||
|
||||
def step_generate():
|
||||
print("\n=== Step 2: Generate C++ from descriptors + layout.yaml ===")
|
||||
return run([sys.executable, str(ROOT / "tools" / "config_codegen.py"),
|
||||
str(DESC_FILE), str(CODEGEN_OUT)])
|
||||
|
||||
|
||||
def step_lint():
|
||||
print("\n=== Lint: proto sanity checks ===")
|
||||
return run([sys.executable, str(ROOT / "tools" / "config_codegen.py"),
|
||||
str(DESC_FILE), str(CODEGEN_OUT), "--lint-only"])
|
||||
|
||||
|
||||
def step_validate():
|
||||
print("\n=== Step 3: Validate ===")
|
||||
return run([sys.executable, str(ROOT / "tools" / "validate_codegen.py")])
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Run OrcaSlicer config codegen pipeline")
|
||||
parser.add_argument("--validate-only", action="store_true",
|
||||
help="Only run validation")
|
||||
parser.add_argument("--no-validate", action="store_true",
|
||||
help="Skip validation step (used by cmake build)")
|
||||
args = parser.parse_args()
|
||||
|
||||
# Re-execs into a virtualenv with protobuf/pyyaml if this interpreter lacks them.
|
||||
codegen_toolchain.ensure_python_runtime()
|
||||
|
||||
if args.validate_only:
|
||||
# Compile + lint the protos, then check the generated files against PrintConfig.cpp.
|
||||
sys.exit(0 if (step_compile() and step_lint() and step_validate()) else 1)
|
||||
|
||||
for name, fn in [("Compile", step_compile), ("Generate", step_generate)]:
|
||||
if not fn():
|
||||
print(f"\n*** Pipeline FAILED at: {name} ***")
|
||||
sys.exit(1)
|
||||
|
||||
if not args.no_validate:
|
||||
if not step_validate():
|
||||
print("\n*** Validate FAILED (run with --no-validate to skip) ***")
|
||||
sys.exit(1)
|
||||
|
||||
print("\n=== Pipeline completed successfully ===")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
214
tools/validate_codegen.py
Normal file
214
tools/validate_codegen.py
Normal file
@@ -0,0 +1,214 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Validates generated PrintConfigDef code against the original PrintConfig.cpp.
|
||||
|
||||
Compares setting keys, types, defaults, enum values/labels, and metadata
|
||||
to ensure the codegen output is a faithful reproduction.
|
||||
"""
|
||||
|
||||
import re
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from collections import OrderedDict
|
||||
|
||||
|
||||
def parse_original_settings(cpp_path):
|
||||
"""Parse the original init_fff_params() into a dict of key -> properties."""
|
||||
with open(cpp_path, 'r', encoding='utf-8') as f:
|
||||
text = f.read()
|
||||
|
||||
m = re.search(r'void PrintConfigDef::init_fff_params\(\)(.*?)^\}', text, re.DOTALL | re.MULTILINE)
|
||||
if not m:
|
||||
print("ERROR: Could not find init_fff_params()")
|
||||
sys.exit(1)
|
||||
body = m.group(1)
|
||||
|
||||
settings = OrderedDict()
|
||||
current_key = None
|
||||
|
||||
for line in body.split('\n'):
|
||||
stripped = line.strip()
|
||||
|
||||
# Detect this->add("key", coType)
|
||||
add_match = re.search(r'this->add(?:_nullable)?\s*\(\s*"([^"]+)"\s*,\s*(co\w+)\s*\)', stripped)
|
||||
if add_match:
|
||||
current_key = add_match.group(1)
|
||||
co_type = add_match.group(2)
|
||||
# Last definition wins (handles duplicates)
|
||||
settings[current_key] = {
|
||||
'co_type': co_type,
|
||||
'has_default': False,
|
||||
'enum_values': 0,
|
||||
'enum_labels': 0,
|
||||
'has_enum_map': False,
|
||||
}
|
||||
continue
|
||||
|
||||
if current_key and current_key in settings:
|
||||
s = settings[current_key]
|
||||
if 'set_default_value' in stripped:
|
||||
s['has_default'] = True
|
||||
if re.search(r'enum_values\.(?:push_back|emplace_back)', stripped):
|
||||
s['enum_values'] += 1
|
||||
if re.search(r'enum_labels\.(?:push_back|emplace_back)', stripped):
|
||||
s['enum_labels'] += 1
|
||||
if 'enum_keys_map' in stripped and '=' in stripped:
|
||||
s['has_enum_map'] = True
|
||||
|
||||
return settings
|
||||
|
||||
|
||||
def parse_generated_settings(gen_path):
|
||||
"""Parse the generated PrintConfigDef code into a dict of key -> properties."""
|
||||
with open(gen_path, 'r', encoding='utf-8') as f:
|
||||
text = f.read()
|
||||
|
||||
settings = OrderedDict()
|
||||
current_key = None
|
||||
|
||||
for line in text.split('\n'):
|
||||
stripped = line.strip()
|
||||
|
||||
add_match = re.search(r'this->add(?:_nullable)?\s*\(\s*"([^"]+)"\s*,\s*(co\w+)\s*\)', stripped)
|
||||
if add_match:
|
||||
current_key = add_match.group(1)
|
||||
co_type = add_match.group(2)
|
||||
settings[current_key] = {
|
||||
'co_type': co_type,
|
||||
'has_default': False,
|
||||
'enum_values': 0,
|
||||
'enum_labels': 0,
|
||||
'has_enum_map': False,
|
||||
}
|
||||
continue
|
||||
|
||||
if current_key and current_key in settings:
|
||||
s = settings[current_key]
|
||||
if 'set_default_value' in stripped:
|
||||
s['has_default'] = True
|
||||
if 'enum_values.push_back' in stripped:
|
||||
s['enum_values'] += 1
|
||||
if 'enum_labels.push_back' in stripped:
|
||||
s['enum_labels'] += 1
|
||||
if 'enum_keys_map' in stripped and '=' in stripped:
|
||||
s['has_enum_map'] = True
|
||||
|
||||
return settings
|
||||
|
||||
|
||||
def main():
|
||||
root = Path(__file__).resolve().parent.parent
|
||||
orig_path = root / "src/libslic3r/PrintConfig.cpp"
|
||||
gen_path = root / "src/slic3r/GUI/generated/PrintConfigDef_generated.cpp"
|
||||
|
||||
if not orig_path.exists() or not gen_path.exists():
|
||||
print("ERROR: Required files not found")
|
||||
sys.exit(1)
|
||||
|
||||
print("Parsing original...")
|
||||
orig = parse_original_settings(orig_path)
|
||||
print(f" {len(orig)} settings")
|
||||
|
||||
print("Parsing generated...")
|
||||
gen = parse_generated_settings(gen_path)
|
||||
print(f" {len(gen)} settings")
|
||||
|
||||
# Known exceptions: settings that exist in original but are commented out
|
||||
# or have runtime-generated enums
|
||||
known_exceptions = {
|
||||
'adaptive_layer_height', # Commented out in original
|
||||
'spaghetti_detector', # Commented out in original
|
||||
}
|
||||
# Settings with runtime-generated enum values (loop over MaterialType::all())
|
||||
runtime_enum_keys = {
|
||||
'filament_type', # enum_values from runtime loop
|
||||
}
|
||||
|
||||
# Compare
|
||||
errors = []
|
||||
warnings = []
|
||||
|
||||
# Missing keys
|
||||
orig_keys = set(orig.keys())
|
||||
gen_keys = set(gen.keys())
|
||||
|
||||
missing = orig_keys - gen_keys
|
||||
extra = gen_keys - orig_keys
|
||||
|
||||
if missing:
|
||||
real_missing = missing - known_exceptions
|
||||
if real_missing:
|
||||
errors.append(f"MISSING from generated ({len(real_missing)}): {sorted(real_missing)}")
|
||||
noted = missing & known_exceptions
|
||||
if noted:
|
||||
warnings.append(f"Known exceptions (commented out in original): {sorted(noted)}")
|
||||
if extra:
|
||||
warnings.append(f"EXTRA in generated ({len(extra)}): {sorted(extra)}")
|
||||
|
||||
# Compare shared keys
|
||||
shared = orig_keys & gen_keys
|
||||
type_mismatches = []
|
||||
default_mismatches = []
|
||||
enum_val_mismatches = []
|
||||
enum_lbl_mismatches = []
|
||||
enum_map_mismatches = []
|
||||
|
||||
for key in sorted(shared):
|
||||
o = orig[key]
|
||||
g = gen[key]
|
||||
|
||||
if o['co_type'] != g['co_type']:
|
||||
type_mismatches.append(f" {key}: orig={o['co_type']} gen={g['co_type']}")
|
||||
|
||||
if o['has_default'] != g['has_default'] and key not in known_exceptions:
|
||||
default_mismatches.append(f" {key}: orig={o['has_default']} gen={g['has_default']}")
|
||||
|
||||
if o['enum_values'] != g['enum_values'] and key not in runtime_enum_keys:
|
||||
enum_val_mismatches.append(f" {key}: orig={o['enum_values']} gen={g['enum_values']}")
|
||||
|
||||
if o['enum_labels'] != g['enum_labels']:
|
||||
enum_lbl_mismatches.append(f" {key}: orig={o['enum_labels']} gen={g['enum_labels']}")
|
||||
|
||||
if o['has_enum_map'] != g['has_enum_map']:
|
||||
enum_map_mismatches.append(f" {key}: orig={o['has_enum_map']} gen={g['has_enum_map']}")
|
||||
|
||||
# Report
|
||||
print("\n=== VALIDATION RESULTS ===\n")
|
||||
|
||||
if type_mismatches:
|
||||
errors.append(f"TYPE MISMATCHES ({len(type_mismatches)}):\n" + "\n".join(type_mismatches))
|
||||
|
||||
if default_mismatches:
|
||||
errors.append(f"DEFAULT MISMATCHES ({len(default_mismatches)}):\n" + "\n".join(default_mismatches))
|
||||
|
||||
if enum_val_mismatches:
|
||||
warnings.append(f"ENUM VALUE COUNT MISMATCHES ({len(enum_val_mismatches)}):\n" + "\n".join(enum_val_mismatches))
|
||||
|
||||
if enum_lbl_mismatches:
|
||||
warnings.append(f"ENUM LABEL COUNT MISMATCHES ({len(enum_lbl_mismatches)}):\n" + "\n".join(enum_lbl_mismatches))
|
||||
|
||||
if enum_map_mismatches:
|
||||
warnings.append(f"ENUM MAP MISMATCHES ({len(enum_map_mismatches)}):\n" + "\n".join(enum_map_mismatches))
|
||||
|
||||
if warnings:
|
||||
print("WARNINGS:")
|
||||
for w in warnings:
|
||||
print(f" {w}")
|
||||
print()
|
||||
|
||||
if errors:
|
||||
print("ERRORS:")
|
||||
for e in errors:
|
||||
print(f" {e}")
|
||||
print(f"\nValidation FAILED with {len(errors)} error(s)")
|
||||
sys.exit(1)
|
||||
else:
|
||||
print(f"All {len(shared)} shared settings validated successfully")
|
||||
if extra:
|
||||
print(f" ({len(extra)} extra settings from axis expansion)")
|
||||
print("\nValidation PASSED")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user