mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-06-10 22:12:49 +00:00
Compare commits
25 Commits
feature/au
...
feature/pr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 |
6
.github/workflows/build_all.yml
vendored
6
.github/workflows/build_all.yml
vendored
@@ -211,6 +211,12 @@ 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
|
||||
run: |
|
||||
python3 -m venv /tmp/codegen_venv
|
||||
/tmp/codegen_venv/bin/pip install grpcio-tools pyyaml -q
|
||||
/tmp/codegen_venv/bin/python 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
|
||||
|
||||
20
.github/workflows/build_orca.yml
vendored
20
.github/workflows/build_orca.yml
vendored
@@ -50,6 +50,26 @@ jobs:
|
||||
useLocalCache: true # <--= Use the local cache (default is 'false').
|
||||
useCloudCache: true
|
||||
|
||||
- name: Install codegen tools and generate config sources
|
||||
run: |
|
||||
pip install grpcio-tools
|
||||
python tools/run_codegen.py
|
||||
if: runner.os == 'Windows'
|
||||
shell: pwsh
|
||||
|
||||
- name: Install codegen tools and generate config sources
|
||||
run: |
|
||||
if [ "$(uname)" = "Linux" ]; then
|
||||
pip3 install grpcio-tools pyyaml
|
||||
python3 tools/run_codegen.py
|
||||
else
|
||||
python3 -m venv /tmp/codegen_venv
|
||||
/tmp/codegen_venv/bin/pip install grpcio-tools pyyaml -q
|
||||
/tmp/codegen_venv/bin/python tools/run_codegen.py
|
||||
fi
|
||||
if: runner.os != 'Windows'
|
||||
shell: bash
|
||||
|
||||
- name: Get the version and date on Ubuntu and macOS
|
||||
if: runner.os != 'Windows'
|
||||
run: |
|
||||
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -45,4 +45,7 @@ test.js
|
||||
.clangd
|
||||
internal_docs/
|
||||
*.flatpak
|
||||
/flatpak-repo/
|
||||
/flatpak-repo/
|
||||
config.desc
|
||||
tools/__pycache__/
|
||||
src/slic3r/GUI/generated/
|
||||
@@ -721,7 +721,6 @@ foreach(po_file ${BBL_L10N_PO_FILES})
|
||||
add_custom_command(
|
||||
TARGET gettext_merge_po_with_pot PRE_BUILD
|
||||
COMMAND msgmerge -N -o ${po_file} ${po_file} "${BBL_L18N_DIR}/OrcaSlicer.pot"
|
||||
DEPENDS ${po_file}
|
||||
)
|
||||
endforeach()
|
||||
add_custom_target(gettext_po_to_mo
|
||||
@@ -737,7 +736,6 @@ foreach(po_file ${BBL_L10N_PO_FILES})
|
||||
TARGET gettext_po_to_mo PRE_BUILD
|
||||
COMMAND msgfmt ARGS --check-format -o ${mo_file} ${po_file}
|
||||
#COMMAND msgfmt ARGS --check-compatibility -o ${mo_file} ${po_file}
|
||||
DEPENDS ${po_file}
|
||||
)
|
||||
endforeach()
|
||||
|
||||
@@ -872,6 +870,11 @@ 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).
|
||||
# Requires: pip install grpcio-tools OR standalone protoc in PATH.
|
||||
include(cmake/modules/ConfigCodegen.cmake)
|
||||
|
||||
# libslic3r, OrcaSlicer GUI and the OrcaSlicer executable.
|
||||
add_subdirectory(deps_src)
|
||||
add_subdirectory(src)
|
||||
|
||||
@@ -545,6 +545,10 @@ 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..."
|
||||
pip install grpcio-tools -q
|
||||
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 \
|
||||
|
||||
@@ -180,6 +180,12 @@ function pack_deps() {
|
||||
}
|
||||
|
||||
function build_slicer() {
|
||||
echo "Generating config sources from proto..."
|
||||
python3 -m venv /tmp/codegen_venv
|
||||
/tmp/codegen_venv/bin/pip install grpcio-tools pyyaml -q
|
||||
/tmp/codegen_venv/bin/python tools/run_codegen.py || { echo "ERROR: config codegen failed"; exit 1; }
|
||||
CODEGEN_PYTHON="/tmp/codegen_venv/bin/python3"
|
||||
|
||||
# iterate over two architectures: x86_64 and arm64
|
||||
for _ARCH in x86_64 arm64; do
|
||||
# if ARCH is universal or equal to _ARCH
|
||||
@@ -204,6 +210,7 @@ function build_slicer() {
|
||||
-DCMAKE_OSX_ARCHITECTURES="${_ARCH}" \
|
||||
-DCMAKE_OSX_DEPLOYMENT_TARGET="${OSX_DEPLOYMENT_TARGET}" \
|
||||
-DCMAKE_IGNORE_PREFIX_PATH="${CMAKE_IGNORE_PREFIX_PATH}" \
|
||||
-DPython3_EXECUTABLE="${CODEGEN_PYTHON}" \
|
||||
${CMAKE_POLICY_COMPAT}
|
||||
fi
|
||||
cmake --build . --config "$BUILD_CONFIG" --target "$SLICER_BUILD_TARGET"
|
||||
|
||||
@@ -126,6 +126,15 @@ if "%1"=="deps" goto :done
|
||||
:slicer
|
||||
echo "building Orca Slicer..."
|
||||
cd %WP%
|
||||
|
||||
echo "generating config sources from proto..."
|
||||
pip install grpcio-tools -q
|
||||
python tools/run_codegen.py
|
||||
if errorlevel 1 (
|
||||
echo "ERROR: config codegen failed"
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
mkdir %build_dir%
|
||||
cd %build_dir%
|
||||
|
||||
|
||||
@@ -57,6 +57,15 @@ if "%1"=="deps" exit /b 0
|
||||
:slicer
|
||||
echo "building Orca Slicer..."
|
||||
cd %WP%
|
||||
|
||||
echo "generating config sources from proto..."
|
||||
pip install grpcio-tools -q
|
||||
python tools/run_codegen.py
|
||||
if errorlevel 1 (
|
||||
echo "ERROR: config codegen failed"
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
mkdir %build_dir%
|
||||
cd %build_dir%
|
||||
|
||||
|
||||
99
cmake/modules/ConfigCodegen.cmake
Normal file
99
cmake/modules/ConfigCodegen.cmake
Normal file
@@ -0,0 +1,99 @@
|
||||
# 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' (requires grpcio-tools or protoc) to regenerate.
|
||||
#
|
||||
# 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)
|
||||
|
||||
# If generated files are missing (fresh clone), run codegen immediately at configure time.
|
||||
# This allows cmake configure + build to work without a separate pre-build step.
|
||||
set(_generated_marker "${CMAKE_SOURCE_DIR}/src/slic3r/GUI/generated/PrintConfigDef_generated.cpp")
|
||||
if(Python3_EXECUTABLE AND NOT EXISTS "${_generated_marker}")
|
||||
message(STATUS "Config codegen: generated files missing — running codegen now...")
|
||||
execute_process(
|
||||
COMMAND ${Python3_EXECUTABLE} "${CMAKE_SOURCE_DIR}/tools/run_codegen.py" --no-validate
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
RESULT_VARIABLE _codegen_result
|
||||
)
|
||||
if(NOT _codegen_result EQUAL 0)
|
||||
message(FATAL_ERROR "Config codegen failed. Install grpcio-tools: pip install grpcio-tools")
|
||||
endif()
|
||||
message(STATUS "Config codegen: generated files created successfully")
|
||||
elseif(NOT Python3_EXECUTABLE AND NOT EXISTS "${_generated_marker}")
|
||||
message(FATAL_ERROR "Config codegen: generated files missing and Python3 not found.\n"
|
||||
"Install Python and grpcio-tools: pip install grpcio-tools\n"
|
||||
"Then run: python tools/run_codegen.py")
|
||||
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"
|
||||
)
|
||||
|
||||
# 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(Python3_EXECUTABLE)
|
||||
# Single command: run_codegen.py handles protoc/grpcio-tools detection internally.
|
||||
# Proto files → generated .cpp files. Runs automatically when any .proto changes.
|
||||
add_custom_command(
|
||||
OUTPUT ${CONFIG_GENERATED_SOURCES}
|
||||
COMMAND ${Python3_EXECUTABLE} ${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 ${Python3_EXECUTABLE} ${VALIDATE_TOOL}
|
||||
DEPENDS ${CONFIG_GENERATED_SOURCES}
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
COMMENT "Validating generated config code against PrintConfig.cpp"
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
# Export for use by subdirectories (libslic3r, etc.)
|
||||
set(CONFIG_GENERATED_SOURCES "${CONFIG_GENERATED_SOURCES}" CACHE INTERNAL "Generated config cpp files")
|
||||
|
||||
message(STATUS "Config codegen: enabled — proto changes auto-regenerate on next build")
|
||||
else()
|
||||
message(STATUS "Config codegen: Python3 not found — run: pip install grpcio-tools && python tools/run_codegen.py")
|
||||
endif()
|
||||
490
docs/PrintConfig_Codegen_Design.md
Normal file
490
docs/PrintConfig_Codegen_Design.md
Normal file
@@ -0,0 +1,490 @@
|
||||
# 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/generated/print.proto` | ~477 print/process settings |
|
||||
| `src/PrintConfigs/generated/filament.proto` | ~103 filament settings |
|
||||
| `src/PrintConfigs/generated/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 protoc --descriptor_set_out=config.desc src/PrintConfigs/generated/*.proto
|
||||
COMMAND python3 tools/config_codegen.py config.desc ${GENERATED_DIR}
|
||||
DEPENDS src/PrintConfigs/generated/*.proto tools/config_codegen.py
|
||||
)
|
||||
```
|
||||
|
||||
Generated files are checked into the repo (not gitignored) so builds work without `protoc`. CI validates that committed generated files match what the generator produces.
|
||||
|
||||
### 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 and the updated generated files together
|
||||
|
||||
### 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)
|
||||
└── generated/
|
||||
├── print.proto # ~477 print/process settings
|
||||
├── filament.proto # ~103 filament settings
|
||||
└── printer.proto # ~42 printer/machine settings
|
||||
|
||||
tools/
|
||||
├── parse_printconfig.py # Bootstrap: PrintConfig.cpp → .proto
|
||||
├── config_codegen.py # Proto descriptor → C++ codegen
|
||||
├── validate_codegen.py # Generated vs original validation
|
||||
├── run_codegen.py # Full pipeline script
|
||||
├── annotate_protos.py # Inject (invalidates)/(list_membership) from C++
|
||||
├── move_proto_fields.py # Utility: move fields between proto files
|
||||
└── config_metadata_pb2.py # Generated Python bindings for extensions
|
||||
|
||||
codegen/
|
||||
└── generated/
|
||||
├── 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
|
||||
|
||||
cmake/modules/
|
||||
└── ConfigCodegen.cmake # CMake integration (build-time regeneration)
|
||||
|
||||
docs/
|
||||
└── PrintConfig_Codegen_Design.md # This design document
|
||||
```
|
||||
@@ -375,6 +375,9 @@ modules:
|
||||
- type: dir
|
||||
path: ../../localization
|
||||
dest: localization
|
||||
- type: dir
|
||||
path: ../../tools
|
||||
dest: tools
|
||||
|
||||
- type: file
|
||||
path: ../../CMakeLists.txt
|
||||
|
||||
@@ -237,10 +237,6 @@ else ()
|
||||
COMMAND ln -sf OrcaSlicer orca-slicer
|
||||
WORKING_DIRECTORY "$<TARGET_FILE_DIR:OrcaSlicer>"
|
||||
VERBATIM)
|
||||
else ()
|
||||
add_custom_command(TARGET OrcaSlicer POST_BUILD
|
||||
WORKING_DIRECTORY "$<TARGET_FILE_DIR:OrcaSlicer>"
|
||||
VERBATIM)
|
||||
endif ()
|
||||
if (XCODE)
|
||||
# Because of Debug/Release/etc. configurations (similar to MSVC) the slic3r binary is located in an extra level
|
||||
|
||||
144
src/PrintConfigs/config_metadata.proto
Normal file
144
src/PrintConfigs/config_metadata.proto
Normal file
@@ -0,0 +1,144 @@
|
||||
// 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// --- 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")
|
||||
string 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
|
||||
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;
|
||||
|
||||
// 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;
|
||||
}
|
||||
1933
src/PrintConfigs/filament.proto
Normal file
1933
src/PrintConfigs/filament.proto
Normal file
File diff suppressed because it is too large
Load Diff
669
src/PrintConfigs/layout.yaml
Normal file
669
src/PrintConfigs/layout.yaml
Normal file
@@ -0,0 +1,669 @@
|
||||
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
|
||||
- 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
|
||||
- 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
|
||||
- bottom_shell_layers
|
||||
- bottom_shell_thickness
|
||||
- bottom_surface_density
|
||||
- bottom_surface_pattern
|
||||
- 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
|
||||
- infill_wall_overlap
|
||||
- name: "Advanced"
|
||||
fields:
|
||||
- align_infill_direction_to_model
|
||||
- extra_solid_infills
|
||||
- bridge_angle
|
||||
- internal_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
|
||||
- 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
|
||||
- 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
|
||||
- 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: ""
|
||||
7045
src/PrintConfigs/print.proto
Normal file
7045
src/PrintConfigs/print.proto
Normal file
File diff suppressed because it is too large
Load Diff
776
src/PrintConfigs/printer.proto
Normal file
776
src/PrintConfigs/printer.proto
Normal file
@@ -0,0 +1,776 @@
|
||||
// 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";
|
||||
|
||||
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
|
||||
];
|
||||
|
||||
}
|
||||
@@ -489,6 +489,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 ()
|
||||
|
||||
@@ -967,346 +967,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",
|
||||
"bottom_surface_pattern",
|
||||
"infill_direction",
|
||||
"solid_infill_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",
|
||||
"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",
|
||||
"wall_filament",
|
||||
"support_bottom_z_distance",
|
||||
"sparse_infill_filament",
|
||||
"solid_infill_filament",
|
||||
"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",
|
||||
"process_change_extrusion_role_gcode",
|
||||
"min_length_factor",
|
||||
"wall_maximum_resolution",
|
||||
"wall_maximum_deviation",
|
||||
"small_perimeter_speed",
|
||||
"small_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",
|
||||
"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",
|
||||
"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_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", "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_retraction_length", "filament_z_hop", "filament_z_hop_types", "filament_retract_lift_above", "filament_retract_lift_below", "filament_retract_lift_enforce", "filament_retraction_speed", "filament_deretraction_speed", "filament_retract_restart_extra", "filament_retraction_minimum_travel",
|
||||
"filament_retract_when_changing_layer", "filament_wipe", "filament_retract_before_wipe",
|
||||
// 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",
|
||||
"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_cooling_before_tower",
|
||||
"long_retractions_when_ec", "retraction_distances_when_ec"
|
||||
};
|
||||
|
||||
static std::vector<std::string> s_Preset_machine_limits_options {
|
||||
"machine_max_acceleration_extruding", "machine_max_acceleration_retracting", "machine_max_acceleration_travel",
|
||||
@@ -1321,31 +983,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", "nozzle_volume","upward_compatible_machine", "z_hop_types", "travel_slope", "retract_lift_enforce","support_chamber_temp_control","support_air_filtration","printer_structure",
|
||||
"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", "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"
|
||||
};
|
||||
|
||||
static std::vector<std::string> s_Preset_sla_print_options {
|
||||
"layer_height",
|
||||
|
||||
@@ -96,313 +96,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",
|
||||
"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",
|
||||
"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",
|
||||
"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",
|
||||
"thumbnails",
|
||||
"thumbnails_format",
|
||||
"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"
|
||||
};
|
||||
#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 == "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 == "extruder_ams_count"
|
||||
|| opt_key == "filament_map_mode"
|
||||
|| opt_key == "filament_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.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -735,7 +445,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
|
||||
{
|
||||
@@ -769,7 +479,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) {
|
||||
@@ -785,13 +495,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
|
||||
@@ -801,8 +511,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)];
|
||||
@@ -870,7 +580,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
@@ -460,6 +460,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
|
||||
|
||||
@@ -86,6 +86,10 @@ int mode_to_selection(ConfigOptionMode mode)
|
||||
// Forward declaration for early use; definitions live later in this translation unit.
|
||||
static void validate_custom_gcode_cb(Tab* tab, const wxString& title, const t_config_option_key& opt_key, const boost::any& value);
|
||||
|
||||
// TabLayout_generated.cpp must be included AFTER the forward declaration of
|
||||
// validate_custom_gcode_cb so the inline layout functions can call it.
|
||||
#include "generated/TabLayout_generated.cpp"
|
||||
|
||||
static const std::vector<std::string> plate_keys = { "curr_bed_type", "skirt_start_angle", "first_layer_print_sequence", "first_layer_sequence_choice", "other_layers_print_sequence", "other_layers_sequence_choice", "print_sequence", "spiral_mode"};
|
||||
|
||||
void Tab::Highlighter::set_timer_owner(wxEvtHandler* owner, int timerid/* = wxID_ANY*/)
|
||||
@@ -233,7 +237,7 @@ void Tab::create_preset_tab()
|
||||
if (m_type == Preset::TYPE_PRINTER && !m_presets_choice->is_selected_physical_printer())
|
||||
m_preset_bundle->physical_printers.unselect_printer();
|
||||
|
||||
// select preset — prefer stored internal name to avoid alias collisions
|
||||
// select preset — prefer stored internal name to avoid alias collisions
|
||||
wxString stored_name = m_presets_choice->GetItemAlias(selection);
|
||||
std::string preset_name;
|
||||
if (!stored_name.empty()) {
|
||||
@@ -2313,485 +2317,7 @@ void TabPrint::build()
|
||||
if (m_presets == nullptr)
|
||||
m_presets = &m_preset_bundle->prints;
|
||||
load_initial_data();
|
||||
|
||||
auto page = add_options_page(L("Quality"), "custom-gcode_quality"); // ORCA: icon only visible on placeholders
|
||||
auto optgroup = page->new_optgroup(L("Layer height"), L"param_layer_height");
|
||||
optgroup->append_single_option_line("layer_height","quality_settings_layer_height");
|
||||
optgroup->append_single_option_line("initial_layer_print_height","quality_settings_layer_height");
|
||||
|
||||
optgroup = page->new_optgroup(L("Line width"), L"param_line_width");
|
||||
optgroup->append_single_option_line("line_width","quality_settings_line_width");
|
||||
optgroup->append_single_option_line("initial_layer_line_width","quality_settings_line_width#first-layer");
|
||||
optgroup->append_single_option_line("outer_wall_line_width","quality_settings_line_width#outer-wall");
|
||||
optgroup->append_single_option_line("inner_wall_line_width","quality_settings_line_width#inner-wall");
|
||||
optgroup->append_single_option_line("top_surface_line_width","quality_settings_line_width#top-surface");
|
||||
optgroup->append_single_option_line("sparse_infill_line_width","quality_settings_line_width#sparse-infill");
|
||||
optgroup->append_single_option_line("internal_solid_infill_line_width","quality_settings_line_width#internal-solid-infill");
|
||||
optgroup->append_single_option_line("support_line_width","quality_settings_line_width#support");
|
||||
optgroup->append_single_option_line("bridge_line_width","quality_settings_line_width#bridge");
|
||||
|
||||
optgroup = page->new_optgroup(L("Seam"), L"param_seam");
|
||||
optgroup->append_single_option_line("seam_position", "quality_settings_seam#seam-position");
|
||||
optgroup->append_single_option_line("staggered_inner_seams", "quality_settings_seam#staggered-inner-seams");
|
||||
optgroup->append_single_option_line("seam_gap","quality_settings_seam#seam-gap");
|
||||
optgroup->append_single_option_line("seam_slope_type", "quality_settings_seam#scarf-joint-seam");
|
||||
optgroup->append_single_option_line("seam_slope_conditional", "quality_settings_seam#scarf-joint-seam");
|
||||
optgroup->append_single_option_line("scarf_angle_threshold", "quality_settings_seam#scarf-joint-seam");
|
||||
optgroup->append_single_option_line("scarf_overhang_threshold", "quality_settings_seam#scarf-joint-seam");
|
||||
optgroup->append_single_option_line("scarf_joint_speed", "quality_settings_seam#scarf-joint-seam");
|
||||
optgroup->append_single_option_line("seam_slope_start_height", "quality_settings_seam#scarf-joint-seam");
|
||||
optgroup->append_single_option_line("seam_slope_entire_loop", "quality_settings_seam#scarf-joint-seam");
|
||||
optgroup->append_single_option_line("seam_slope_min_length", "quality_settings_seam#scarf-joint-seam");
|
||||
optgroup->append_single_option_line("seam_slope_steps", "quality_settings_seam#scarf-joint-seam");
|
||||
optgroup->append_single_option_line("scarf_joint_flow_ratio", "quality_settings_seam#scarf-joint-seam");
|
||||
optgroup->append_single_option_line("seam_slope_inner_walls", "quality_settings_seam#scarf-joint-seam");
|
||||
optgroup->append_single_option_line("role_based_wipe_speed","quality_settings_seam#role-based-wipe-speed");
|
||||
optgroup->append_single_option_line("wipe_speed", "quality_settings_seam#wipe-speed");
|
||||
optgroup->append_single_option_line("wipe_on_loops","quality_settings_seam#wipe-on-loop-inward-movement");
|
||||
optgroup->append_single_option_line("wipe_before_external_loop","quality_settings_seam#wipe-before-external");
|
||||
|
||||
|
||||
optgroup = page->new_optgroup(L("Precision"), L"param_precision");
|
||||
optgroup->append_single_option_line("slice_closing_radius", "quality_settings_precision#slice-gap-closing-radius");
|
||||
optgroup->append_single_option_line("resolution", "quality_settings_precision#resolution");
|
||||
optgroup->append_single_option_line("enable_arc_fitting", "quality_settings_precision#arc-fitting");
|
||||
optgroup->append_single_option_line("xy_hole_compensation", "quality_settings_precision#x-y-compensation");
|
||||
optgroup->append_single_option_line("xy_contour_compensation", "quality_settings_precision#x-y-compensation");
|
||||
optgroup->append_single_option_line("elefant_foot_compensation", "quality_settings_precision#elephant-foot-compensation");
|
||||
optgroup->append_single_option_line("elefant_foot_layers_density", "quality_settings_precision#elephant-foot-compensation-density");
|
||||
optgroup->append_single_option_line("elefant_foot_compensation_layers", "quality_settings_precision#elephant-foot-compensation");
|
||||
optgroup->append_single_option_line("precise_outer_wall", "quality_settings_precision#precise-wall");
|
||||
optgroup->append_single_option_line("precise_z_height", "quality_settings_precision#precise-z-height");
|
||||
optgroup->append_single_option_line("hole_to_polyhole", "quality_settings_precision#polyholes");
|
||||
optgroup->append_single_option_line("hole_to_polyhole_threshold", "quality_settings_precision#polyholes");
|
||||
optgroup->append_single_option_line("hole_to_polyhole_twisted", "quality_settings_precision#polyholes");
|
||||
|
||||
optgroup = page->new_optgroup(L("Ironing"), L"param_ironing");
|
||||
optgroup->append_single_option_line("ironing_type", "quality_settings_ironing#type");
|
||||
optgroup->append_single_option_line("ironing_pattern", "quality_settings_ironing#pattern");
|
||||
optgroup->append_single_option_line("ironing_flow", "quality_settings_ironing#flow");
|
||||
optgroup->append_single_option_line("ironing_spacing", "quality_settings_ironing#line-spacing");
|
||||
optgroup->append_single_option_line("ironing_inset", "quality_settings_ironing#inset");
|
||||
optgroup->append_single_option_line("ironing_angle", "quality_settings_ironing#angle-offset");
|
||||
optgroup->append_single_option_line("ironing_angle_fixed", "quality_settings_ironing#fixed-angle");
|
||||
|
||||
optgroup = page->new_optgroup("Z Contouring", L"param_advanced");
|
||||
optgroup->append_single_option_line("zaa_enabled", "quality_settings_z_contouring");
|
||||
optgroup->append_single_option_line("zaa_minimize_perimeter_height", "quality_settings_z_contouring#minimize-wall-height-angle");
|
||||
optgroup->append_single_option_line("zaa_min_z", "quality_settings_z_contouring#minimum-z-height");
|
||||
optgroup->append_single_option_line("zaa_dont_alternate_fill_direction", "quality_settings_z_contouring#dont-alternate-fill-direction");
|
||||
// Orca: it's not used yet, so hide it in UI for now
|
||||
// optgroup->append_single_option_line("ironing_expansion");
|
||||
|
||||
optgroup = page->new_optgroup(L("Wall generator"), L"param_wall_generator");
|
||||
optgroup->append_single_option_line("wall_generator", "quality_settings_wall_generator");
|
||||
optgroup->append_single_option_line("wall_transition_angle", "quality_settings_wall_generator#wall-transitioning-threshhold-angle");
|
||||
optgroup->append_single_option_line("wall_transition_filter_deviation", "quality_settings_wall_generator#wall-transitioning-filter-margin");
|
||||
optgroup->append_single_option_line("wall_transition_length", "quality_settings_wall_generator#wall-transitioning-length");
|
||||
optgroup->append_single_option_line("wall_distribution_count", "quality_settings_wall_generator#wall-distribution-count");
|
||||
optgroup->append_single_option_line("initial_layer_min_bead_width", "quality_settings_wall_generator#first-layer-minimum-wall-width");
|
||||
optgroup->append_single_option_line("min_bead_width", "quality_settings_wall_generator#minimum-wall-width");
|
||||
optgroup->append_single_option_line("min_feature_size", "quality_settings_wall_generator#minimum-feature-size");
|
||||
optgroup->append_single_option_line("min_length_factor", "quality_settings_wall_generator#minimum-wall-length");
|
||||
optgroup->append_single_option_line("wall_maximum_resolution", "quality_settings_wall_generator#maximum-wall-resolution");
|
||||
optgroup->append_single_option_line("wall_maximum_deviation", "quality_settings_wall_generator#maximum-wall-deviation");
|
||||
|
||||
optgroup = page->new_optgroup(L("Walls and surfaces"), L"param_wall_surface");
|
||||
optgroup->append_single_option_line("wall_sequence", "quality_settings_wall_and_surfaces#walls-printing-order");
|
||||
optgroup->append_single_option_line("is_infill_first", "quality_settings_wall_and_surfaces#print-infill-first");
|
||||
optgroup->append_single_option_line("wall_direction", "quality_settings_wall_and_surfaces#wall-loop-direction");
|
||||
optgroup->append_single_option_line("print_flow_ratio", "quality_settings_wall_and_surfaces#surface-flow-ratio");
|
||||
optgroup->append_single_option_line("top_solid_infill_flow_ratio", "quality_settings_wall_and_surfaces#surface-flow-ratio");
|
||||
optgroup->append_single_option_line("bottom_solid_infill_flow_ratio", "quality_settings_wall_and_surfaces#surface-flow-ratio");
|
||||
optgroup->append_single_option_line("set_other_flow_ratios", "quality_settings_wall_and_surfaces#surface-flow-ratio");
|
||||
optgroup->append_single_option_line("first_layer_flow_ratio", "quality_settings_wall_and_surfaces#surface-flow-ratio");
|
||||
optgroup->append_single_option_line("outer_wall_flow_ratio", "quality_settings_wall_and_surfaces#surface-flow-ratio");
|
||||
optgroup->append_single_option_line("inner_wall_flow_ratio", "quality_settings_wall_and_surfaces#surface-flow-ratio");
|
||||
optgroup->append_single_option_line("overhang_flow_ratio", "quality_settings_wall_and_surfaces#surface-flow-ratio");
|
||||
optgroup->append_single_option_line("sparse_infill_flow_ratio", "quality_settings_wall_and_surfaces#surface-flow-ratio");
|
||||
optgroup->append_single_option_line("internal_solid_infill_flow_ratio", "quality_settings_wall_and_surfaces#surface-flow-ratio");
|
||||
optgroup->append_single_option_line("gap_fill_flow_ratio", "quality_settings_wall_and_surfaces#surface-flow-ratio");
|
||||
optgroup->append_single_option_line("support_flow_ratio", "quality_settings_wall_and_surfaces#surface-flow-ratio");
|
||||
optgroup->append_single_option_line("support_interface_flow_ratio", "quality_settings_wall_and_surfaces#surface-flow-ratio");
|
||||
optgroup->append_single_option_line("only_one_wall_first_layer", "quality_settings_wall_and_surfaces#only-one-wall");
|
||||
optgroup->append_single_option_line("only_one_wall_top", "quality_settings_wall_and_surfaces#only-one-wall");
|
||||
optgroup->append_single_option_line("min_width_top_surface", "quality_settings_wall_and_surfaces#threshold");
|
||||
optgroup->append_single_option_line("reduce_crossing_wall", "quality_settings_wall_and_surfaces#avoid-crossing-walls");
|
||||
optgroup->append_single_option_line("max_travel_detour_distance", "quality_settings_wall_and_surfaces#max-detour-length");
|
||||
|
||||
optgroup->append_single_option_line("small_area_infill_flow_compensation", "quality_settings_wall_and_surfaces#small-area-flow-compensation");
|
||||
Option option = optgroup->get_option("small_area_infill_flow_compensation_model");
|
||||
option.opt.full_width = true;
|
||||
option.opt.is_code = true;
|
||||
option.opt.height = 15;
|
||||
optgroup->append_single_option_line(option, "quality_settings_wall_and_surfaces#small-area-flow-compensation");
|
||||
|
||||
optgroup = page->new_optgroup(L("Bridging"), L"param_bridge");
|
||||
optgroup->append_single_option_line("bridge_flow", "quality_settings_bridging#flow-ratio");
|
||||
optgroup->append_single_option_line("internal_bridge_flow", "quality_settings_bridging#flow-ratio");
|
||||
optgroup->append_single_option_line("bridge_density", "quality_settings_bridging#bridge-density");
|
||||
optgroup->append_single_option_line("internal_bridge_density", "quality_settings_bridging#bridge-density");
|
||||
optgroup->append_single_option_line("thick_bridges", "quality_settings_bridging#thick-bridges");
|
||||
optgroup->append_single_option_line("thick_internal_bridges", "quality_settings_bridging#thick-bridges");
|
||||
optgroup->append_single_option_line("enable_extra_bridge_layer", "quality_settings_bridging#extra-bridge-layers");
|
||||
optgroup->append_single_option_line("dont_filter_internal_bridges", "quality_settings_bridging#filter-out-small-internal-bridges");
|
||||
optgroup->append_single_option_line("counterbore_hole_bridging", "quality_settings_bridging#bridge-counterbore-hole");
|
||||
|
||||
optgroup = page->new_optgroup(L("Overhangs"), L"param_overhang");
|
||||
optgroup->append_single_option_line("detect_overhang_wall", "quality_settings_overhangs#detect-overhang-wall");
|
||||
optgroup->append_single_option_line("make_overhang_printable", "quality_settings_overhangs#make-overhang-printable");
|
||||
optgroup->append_single_option_line("make_overhang_printable_angle", "quality_settings_overhangs#maximum-angle");
|
||||
optgroup->append_single_option_line("make_overhang_printable_hole_size", "quality_settings_overhangs#hole-area");
|
||||
optgroup->append_single_option_line("extra_perimeters_on_overhangs", "quality_settings_overhangs#extra-perimeters-on-overhangs");
|
||||
optgroup->append_single_option_line("overhang_reverse", "quality_settings_overhangs#reverse-on-even");
|
||||
optgroup->append_single_option_line("overhang_reverse_internal_only", "quality_settings_overhangs#reverse-internal-only");
|
||||
optgroup->append_single_option_line("overhang_reverse_threshold", "quality_settings_overhangs#reverse-threshold");
|
||||
|
||||
page = add_options_page(L("Strength"), "custom-gcode_strength"); // ORCA: icon only visible on placeholders
|
||||
optgroup = page->new_optgroup(L("Walls"), L"param_wall");
|
||||
optgroup->append_single_option_line("wall_loops", "strength_settings_walls#wall-loops");
|
||||
optgroup->append_single_option_line("alternate_extra_wall", "strength_settings_walls#alternate-extra-wall");
|
||||
optgroup->append_single_option_line("detect_thin_wall", "strength_settings_walls#detect-thin-wall");
|
||||
|
||||
optgroup = page->new_optgroup(L("Top/bottom shells"), L"param_shell");
|
||||
|
||||
optgroup->append_single_option_line("top_shell_layers", "strength_settings_top_bottom_shells#shell-layers");
|
||||
optgroup->append_single_option_line("top_shell_thickness", "strength_settings_top_bottom_shells#shell-thickness");
|
||||
optgroup->append_single_option_line("top_surface_density", "strength_settings_top_bottom_shells#surface-density");
|
||||
optgroup->append_single_option_line("top_surface_pattern", "strength_settings_top_bottom_shells#surface-pattern");
|
||||
optgroup->append_single_option_line("bottom_shell_layers", "strength_settings_top_bottom_shells#shell-layers");
|
||||
optgroup->append_single_option_line("bottom_shell_thickness", "strength_settings_top_bottom_shells#shell-thickness");
|
||||
optgroup->append_single_option_line("bottom_surface_density", "strength_settings_top_bottom_shells#surface-density");
|
||||
optgroup->append_single_option_line("bottom_surface_pattern", "strength_settings_top_bottom_shells#surface-pattern");
|
||||
optgroup->append_single_option_line("top_bottom_infill_wall_overlap", "strength_settings_top_bottom_shells#infillwall-overlap");
|
||||
|
||||
optgroup = page->new_optgroup(L("Infill"), L"param_infill");
|
||||
optgroup->append_single_option_line("sparse_infill_density", "strength_settings_infill#sparse-infill-density");
|
||||
optgroup->append_single_option_line("fill_multiline", "strength_settings_infill#fill-multiline");
|
||||
optgroup->append_single_option_line("sparse_infill_pattern", "strength_settings_infill#sparse-infill-pattern");
|
||||
optgroup->append_single_option_line("gyroid_optimized", "strength_settings_patterns#gyroid-optimized");
|
||||
optgroup->append_single_option_line("infill_direction", "strength_settings_infill#direction");
|
||||
optgroup->append_single_option_line("sparse_infill_rotate_template", "strength_settings_infill_rotation_template_metalanguage");
|
||||
optgroup->append_single_option_line("skin_infill_density", "strength_settings_patterns#locked-zag");
|
||||
optgroup->append_single_option_line("skeleton_infill_density", "strength_settings_patterns#locked-zag");
|
||||
optgroup->append_single_option_line("infill_lock_depth", "strength_settings_patterns#locked-zag");
|
||||
optgroup->append_single_option_line("skin_infill_depth", "strength_settings_patterns#locked-zag");
|
||||
optgroup->append_single_option_line("skin_infill_line_width", "strength_settings_patterns#locked-zag");
|
||||
optgroup->append_single_option_line("skeleton_infill_line_width", "strength_settings_patterns#locked-zag");
|
||||
optgroup->append_single_option_line("symmetric_infill_y_axis", "strength_settings_infill#symmetric-infill-y-axis");
|
||||
optgroup->append_single_option_line("infill_shift_step", "strength_settings_patterns#cross-hatch");
|
||||
optgroup->append_single_option_line("lateral_lattice_angle_1", "strength_settings_patterns#lateral-lattice");
|
||||
optgroup->append_single_option_line("lateral_lattice_angle_2", "strength_settings_patterns#lateral-lattice");
|
||||
optgroup->append_single_option_line("infill_overhang_angle", "strength_settings_patterns#lateral-honeycomb");
|
||||
optgroup->append_single_option_line("lightning_overhang_angle", "strength_settings_patterns#lightning");
|
||||
optgroup->append_single_option_line("lightning_prune_angle", "strength_settings_patterns#lightning");
|
||||
optgroup->append_single_option_line("lightning_straightening_angle", "strength_settings_patterns#lightning");
|
||||
optgroup->append_single_option_line("infill_anchor_max", "strength_settings_infill#anchor");
|
||||
optgroup->append_single_option_line("infill_anchor", "strength_settings_infill#anchor");
|
||||
optgroup->append_single_option_line("internal_solid_infill_pattern", "strength_settings_infill#internal-solid-infill");
|
||||
optgroup->append_single_option_line("solid_infill_direction", "strength_settings_infill#direction");
|
||||
optgroup->append_single_option_line("solid_infill_rotate_template", "strength_settings_infill_rotation_template_metalanguage");
|
||||
optgroup->append_single_option_line("gap_fill_target", "strength_settings_infill#apply-gap-fill");
|
||||
optgroup->append_single_option_line("filter_out_gap_fill", "strength_settings_infill#filter-out-tiny-gaps");
|
||||
optgroup->append_single_option_line("infill_wall_overlap", "strength_settings_infill#infill-wall-overlap");
|
||||
|
||||
optgroup = page->new_optgroup(L("Advanced"), L"param_advanced");
|
||||
optgroup->append_single_option_line("align_infill_direction_to_model", "strength_settings_advanced#align-infill-direction-to-model");
|
||||
optgroup->append_single_option_line("extra_solid_infills", "strength_settings_infill#extra-solid-infill");
|
||||
optgroup->append_single_option_line("bridge_angle", "strength_settings_advanced#bridge-infill-direction");
|
||||
optgroup->append_single_option_line("internal_bridge_angle", "strength_settings_advanced#bridge-infill-direction"); // ORCA: Internal bridge angle override
|
||||
optgroup->append_single_option_line("relative_bridge_angle", "strength_settings_advanced#relative-bridge-angle");
|
||||
optgroup->append_single_option_line("minimum_sparse_infill_area", "strength_settings_advanced#minimum-sparse-infill-threshold");
|
||||
optgroup->append_single_option_line("infill_combination", "strength_settings_advanced#infill-combination");
|
||||
optgroup->append_single_option_line("infill_combination_max_layer_height", "strength_settings_advanced#max-layer-height");
|
||||
optgroup->append_single_option_line("detect_narrow_internal_solid_infill", "strength_settings_advanced#detect-narrow-internal-solid-infill");
|
||||
optgroup->append_single_option_line("ensure_vertical_shell_thickness", "strength_settings_advanced#ensure-vertical-shell-thickness");
|
||||
|
||||
page = add_options_page(L("Speed"), "custom-gcode_speed"); // ORCA: icon only visible on placeholders
|
||||
optgroup = page->new_optgroup(L("First layer speed"), L"param_speed_first", 15);
|
||||
optgroup->append_single_option_line("initial_layer_speed", "speed_settings_initial_layer_speed#initial-layer");
|
||||
optgroup->append_single_option_line("initial_layer_infill_speed", "speed_settings_initial_layer_speed#initial-layer-infill");
|
||||
optgroup->append_single_option_line("initial_layer_travel_speed", "speed_settings_initial_layer_speed#initial-layer-travel-speed");
|
||||
optgroup->append_single_option_line("slow_down_layers", "speed_settings_initial_layer_speed#number-of-slow-layers");
|
||||
optgroup = page->new_optgroup(L("Other layers speed"), L"param_speed", 15);
|
||||
optgroup->append_single_option_line("outer_wall_speed", "speed_settings_other_layers_speed#outer-wall");
|
||||
optgroup->append_single_option_line("inner_wall_speed", "speed_settings_other_layers_speed#inner-wall");
|
||||
optgroup->append_single_option_line("small_perimeter_speed", "speed_settings_other_layers_speed#small-perimeters");
|
||||
optgroup->append_single_option_line("small_perimeter_threshold", "speed_settings_other_layers_speed#small-perimeters-threshold");
|
||||
optgroup->append_single_option_line("sparse_infill_speed", "speed_settings_other_layers_speed#sparse-infill");
|
||||
optgroup->append_single_option_line("internal_solid_infill_speed", "speed_settings_other_layers_speed#internal-solid-infill");
|
||||
optgroup->append_single_option_line("top_surface_speed", "speed_settings_other_layers_speed#top-surface");
|
||||
optgroup->append_single_option_line("gap_infill_speed", "speed_settings_other_layers_speed#gap-infill");
|
||||
optgroup->append_single_option_line("ironing_speed", "speed_settings_other_layers_speed#ironing-speed");
|
||||
optgroup->append_single_option_line("support_speed", "speed_settings_other_layers_speed#support");
|
||||
optgroup->append_single_option_line("support_interface_speed", "speed_settings_other_layers_speed#support-interface");
|
||||
optgroup = page->new_optgroup(L("Overhang speed"), L"param_overhang_speed", 15);
|
||||
optgroup->append_single_option_line("enable_overhang_speed", "speed_settings_overhang_speed#slow-down-for-overhang");
|
||||
|
||||
optgroup->append_single_option_line("slowdown_for_curled_perimeters", "speed_settings_overhang_speed#slow-down-for-curled-perimeters");
|
||||
Line line = { L("Overhang speed"), L("This is the speed for various overhang degrees. Overhang degrees are expressed as a percentage of line width. 0 speed means no slowing down for the overhang degree range and wall speed is used") };
|
||||
line.label_path = "speed_settings_overhang_speed#speed";
|
||||
line.append_option(optgroup->get_option("overhang_1_4_speed"));
|
||||
line.append_option(optgroup->get_option("overhang_2_4_speed"));
|
||||
line.append_option(optgroup->get_option("overhang_3_4_speed"));
|
||||
line.append_option(optgroup->get_option("overhang_4_4_speed"));
|
||||
optgroup->append_line(line);
|
||||
optgroup->append_separator();
|
||||
line = { L("Bridge"), L("Set speed for external and internal bridges") };
|
||||
line.append_option(optgroup->get_option("bridge_speed"));
|
||||
line.append_option(optgroup->get_option("internal_bridge_speed"));
|
||||
optgroup->append_line(line);
|
||||
|
||||
optgroup = page->new_optgroup(L("Travel speed"), L"param_travel_speed", 15);
|
||||
optgroup->append_single_option_line("travel_speed", "speed_settings_travel");
|
||||
|
||||
optgroup = page->new_optgroup(L("Acceleration"), L"param_acceleration", 15);
|
||||
optgroup->append_single_option_line("default_acceleration", "speed_settings_acceleration#normal-printing");
|
||||
optgroup->append_single_option_line("outer_wall_acceleration", "speed_settings_acceleration#outer-wall");
|
||||
optgroup->append_single_option_line("inner_wall_acceleration", "speed_settings_acceleration#inner-wall");
|
||||
optgroup->append_single_option_line("bridge_acceleration", "speed_settings_acceleration#bridge");
|
||||
optgroup->append_single_option_line("sparse_infill_acceleration", "speed_settings_acceleration#sparse-infill");
|
||||
optgroup->append_single_option_line("internal_solid_infill_acceleration", "speed_settings_acceleration#internal-solid-infill");
|
||||
optgroup->append_single_option_line("initial_layer_acceleration", "speed_settings_acceleration#initial-layer");
|
||||
optgroup->append_single_option_line("initial_layer_travel_acceleration", "speed_settings_acceleration#initial-layer-travel");
|
||||
optgroup->append_single_option_line("top_surface_acceleration", "speed_settings_acceleration#top-surface");
|
||||
optgroup->append_single_option_line("travel_acceleration", "speed_settings_acceleration#travel");
|
||||
optgroup->append_single_option_line("accel_to_decel_enable", "speed_settings_acceleration");
|
||||
optgroup->append_single_option_line("accel_to_decel_factor", "speed_settings_acceleration");
|
||||
|
||||
optgroup = page->new_optgroup(L("Jerk(XY)"), L"param_jerk", 15);
|
||||
optgroup->append_single_option_line("default_junction_deviation", "speed_settings_jerk_xy#junction-deviation");
|
||||
optgroup->append_single_option_line("default_jerk", "speed_settings_jerk_xy#default");
|
||||
optgroup->append_single_option_line("outer_wall_jerk", "speed_settings_jerk_xy#outer-wall");
|
||||
optgroup->append_single_option_line("inner_wall_jerk", "speed_settings_jerk_xy#inner-wall");
|
||||
optgroup->append_single_option_line("infill_jerk", "speed_settings_jerk_xy#infill");
|
||||
optgroup->append_single_option_line("top_surface_jerk", "speed_settings_jerk_xy#top-surface");
|
||||
optgroup->append_single_option_line("initial_layer_jerk", "speed_settings_jerk_xy#initial-layer");
|
||||
optgroup->append_single_option_line("initial_layer_travel_jerk", "speed_settings_jerk_xy#initial-layer-travel");
|
||||
optgroup->append_single_option_line("travel_jerk", "speed_settings_jerk_xy#travel");
|
||||
|
||||
optgroup = page->new_optgroup(L("Advanced"), L"param_advanced", 15);
|
||||
optgroup->append_single_option_line("max_volumetric_extrusion_rate_slope", "speed_settings_advanced");
|
||||
optgroup->append_single_option_line("max_volumetric_extrusion_rate_slope_segment_length", "speed_settings_advanced");
|
||||
optgroup->append_single_option_line("extrusion_rate_smoothing_external_perimeter_only", "speed_settings_advanced");
|
||||
|
||||
page = add_options_page(L("Support"), "custom-gcode_support"); // ORCA: icon only visible on placeholders
|
||||
optgroup = page->new_optgroup(L("Support"), L"param_support");
|
||||
optgroup->append_single_option_line("enable_support", "support_settings_support");
|
||||
optgroup->append_single_option_line("support_type", "support_settings_support#type");
|
||||
optgroup->append_single_option_line("support_style", "support_settings_support#style");
|
||||
optgroup->append_single_option_line("support_threshold_angle", "support_settings_support#threshold-angle");
|
||||
optgroup->append_single_option_line("support_threshold_overlap", "support_settings_support#threshold-overlap");
|
||||
optgroup->append_single_option_line("raft_first_layer_density", "support_settings_support#initial-layer-density");
|
||||
optgroup->append_single_option_line("raft_first_layer_expansion", "support_settings_support#initial-layer-expansion");
|
||||
optgroup->append_single_option_line("support_on_build_plate_only", "support_settings_support#on-build-plate-only");
|
||||
optgroup->append_single_option_line("support_critical_regions_only", "support_settings_support#support-critical-regions-only");
|
||||
optgroup->append_single_option_line("support_remove_small_overhang", "support_settings_support#ignore-small-overhangs");
|
||||
//optgroup->append_single_option_line("enforce_support_layers", "support_settings_support");
|
||||
|
||||
optgroup = page->new_optgroup(L("Raft"), L"param_raft");
|
||||
optgroup->append_single_option_line("raft_layers", "support_settings_raft");
|
||||
optgroup->append_single_option_line("raft_contact_distance", "support_settings_raft");
|
||||
|
||||
optgroup = page->new_optgroup(L("Support filament"), L"param_support_filament");
|
||||
optgroup->append_single_option_line("support_filament", "support_settings_filament#base");
|
||||
optgroup->append_single_option_line("support_interface_filament", "support_settings_filament#interface");
|
||||
optgroup->append_single_option_line("support_interface_not_for_body", "support_settings_filament#avoid-interface-filament-for-base");
|
||||
|
||||
optgroup = page->new_optgroup(L("Support ironing"), L"param_ironing");
|
||||
optgroup->append_single_option_line("support_ironing", "support_settings_ironing");
|
||||
optgroup->append_single_option_line("support_ironing_pattern", "support_settings_ironing#pattern");
|
||||
optgroup->append_single_option_line("support_ironing_flow", "support_settings_ironing#flow");
|
||||
optgroup->append_single_option_line("support_ironing_spacing", "support_settings_ironing#line-spacing");
|
||||
|
||||
//optgroup = page->new_optgroup(L("Options for support material and raft"));
|
||||
|
||||
// Support
|
||||
optgroup = page->new_optgroup(L("Advanced"), L"param_advanced");
|
||||
optgroup->append_single_option_line("support_top_z_distance", "support_settings_advanced#z-distance");
|
||||
optgroup->append_single_option_line("support_bottom_z_distance", "support_settings_advanced#z-distance");
|
||||
optgroup->append_single_option_line("tree_support_wall_count", "support_settings_advanced#support-wall-loops");
|
||||
optgroup->append_single_option_line("support_base_pattern", "support_settings_advanced#base-pattern");
|
||||
optgroup->append_single_option_line("support_base_pattern_spacing", "support_settings_advanced#base-pattern-spacing");
|
||||
optgroup->append_single_option_line("support_angle", "support_settings_advanced#pattern-angle");
|
||||
optgroup->append_single_option_line("support_interface_top_layers", "support_settings_advanced#interface-layers");
|
||||
optgroup->append_single_option_line("support_interface_bottom_layers", "support_settings_advanced#interface-layers");
|
||||
optgroup->append_single_option_line("support_interface_pattern", "support_settings_advanced#interface-pattern");
|
||||
optgroup->append_single_option_line("support_interface_spacing", "support_settings_advanced#interface-spacing");
|
||||
optgroup->append_single_option_line("support_bottom_interface_spacing", "support_settings_advanced#interface-spacing");
|
||||
optgroup->append_single_option_line("support_expansion", "support_settings_advanced#normal-support-expansion");
|
||||
//optgroup->append_single_option_line("support_interface_loop_pattern", "support_settings_advanced");
|
||||
|
||||
optgroup->append_single_option_line("support_object_xy_distance", "support_settings_advanced#supportobject-xy-distance");
|
||||
optgroup->append_single_option_line("support_object_first_layer_gap", "support_settings_advanced#supportobject-first-layer-gap");
|
||||
optgroup->append_single_option_line("bridge_no_support", "support_settings_advanced#dont-support-bridges");
|
||||
optgroup->append_single_option_line("max_bridge_length", "support_settings_advanced");
|
||||
optgroup->append_single_option_line("independent_support_layer_height", "support_settings_advanced#independent-support-layer-height");
|
||||
|
||||
optgroup = page->new_optgroup(L("Tree supports"), L"param_support_tree");
|
||||
optgroup->append_single_option_line("tree_support_tip_diameter", "support_settings_tree#tip-diameter");
|
||||
optgroup->append_single_option_line("tree_support_branch_distance", "support_settings_tree#branch-distance");
|
||||
optgroup->append_single_option_line("tree_support_branch_distance_organic", "support_settings_tree#branch-distance");
|
||||
optgroup->append_single_option_line("tree_support_top_rate", "support_settings_tree#branch-density");
|
||||
optgroup->append_single_option_line("tree_support_branch_diameter", "support_settings_tree#branch-diameter");
|
||||
optgroup->append_single_option_line("tree_support_branch_diameter_organic", "support_settings_tree#branch-diameter");
|
||||
optgroup->append_single_option_line("tree_support_branch_diameter_angle", "support_settings_tree#branch-diameter-angle");
|
||||
optgroup->append_single_option_line("tree_support_branch_angle", "support_settings_tree#branch-angle");
|
||||
optgroup->append_single_option_line("tree_support_branch_angle_organic", "support_settings_tree#branch-angle");
|
||||
optgroup->append_single_option_line("tree_support_angle_slow", "support_settings_tree#preferred-branch-angle");
|
||||
optgroup->append_single_option_line("tree_support_auto_brim", "support_settings_tree");
|
||||
optgroup->append_single_option_line("tree_support_brim_width", "support_settings_tree");
|
||||
|
||||
page = add_options_page(L("Multimaterial"), "custom-gcode_multi_material"); // ORCA: icon only visible on placeholders
|
||||
optgroup = page->new_optgroup(L("Prime tower"), L"param_tower");
|
||||
optgroup->append_single_option_line("enable_prime_tower", "multimaterial_settings_prime_tower");
|
||||
optgroup->append_single_option_line("prime_tower_skip_points", "multimaterial_settings_prime_tower");
|
||||
optgroup->append_single_option_line("enable_tower_interface_features", "multimaterial_settings_prime_tower");
|
||||
optgroup->append_single_option_line("enable_tower_interface_cooldown_during_tower", "multimaterial_settings_prime_tower");
|
||||
optgroup->append_single_option_line("prime_tower_enable_framework", "multimaterial_settings_prime_tower");
|
||||
optgroup->append_single_option_line("prime_tower_width", "multimaterial_settings_prime_tower#width");
|
||||
optgroup->append_single_option_line("prime_volume", "multimaterial_settings_prime_tower");
|
||||
optgroup->append_single_option_line("prime_tower_brim_width", "multimaterial_settings_prime_tower#brim-width");
|
||||
optgroup->append_single_option_line("prime_tower_infill_gap", "multimaterial_settings_prime_tower");
|
||||
optgroup->append_single_option_line("wipe_tower_rotation_angle", "multimaterial_settings_prime_tower#wipe-tower-rotation-angle");
|
||||
optgroup->append_single_option_line("wipe_tower_bridging", "multimaterial_settings_prime_tower#maximal-bridging-distance");
|
||||
optgroup->append_single_option_line("wipe_tower_extra_spacing", "multimaterial_settings_prime_tower#wipe-tower-purge-lines-spacing");
|
||||
optgroup->append_single_option_line("wipe_tower_extra_flow", "multimaterial_settings_prime_tower#extra-flow-for-purge");
|
||||
optgroup->append_single_option_line("wipe_tower_max_purge_speed", "multimaterial_settings_prime_tower#maximum-wipe-tower-print-speed");
|
||||
optgroup->append_single_option_line("wipe_tower_wall_type", "multimaterial_settings_prime_tower#wall-type");
|
||||
optgroup->append_single_option_line("wipe_tower_cone_angle", "multimaterial_settings_prime_tower#stabilization-cone-apex-angle");
|
||||
optgroup->append_single_option_line("wipe_tower_extra_rib_length", "multimaterial_settings_prime_tower#extra-rib-length");
|
||||
optgroup->append_single_option_line("wipe_tower_rib_width", "multimaterial_settings_prime_tower#rib-width");
|
||||
optgroup->append_single_option_line("wipe_tower_fillet_wall", "multimaterial_settings_prime_tower#fillet-wall");
|
||||
optgroup->append_single_option_line("wipe_tower_no_sparse_layers", "multimaterial_settings_prime_tower#no-sparse-layers");
|
||||
optgroup->append_single_option_line("single_extruder_multi_material_priming", "multimaterial_settings_prime_tower");
|
||||
|
||||
optgroup = page->new_optgroup(L("Filament for Features"), L"param_filament_for_features");
|
||||
optgroup->append_single_option_line("wall_filament", "multimaterial_settings_filament_for_features#walls");
|
||||
optgroup->append_single_option_line("sparse_infill_filament", "multimaterial_settings_filament_for_features#infill");
|
||||
optgroup->append_single_option_line("solid_infill_filament", "multimaterial_settings_filament_for_features#solid-infill");
|
||||
optgroup->append_single_option_line("wipe_tower_filament", "multimaterial_settings_filament_for_features#wipe-tower");
|
||||
|
||||
optgroup = page->new_optgroup(L("Ooze prevention"), L"param_ooze_prevention");
|
||||
optgroup->append_single_option_line("ooze_prevention", "multimaterial_settings_ooze_prevention");
|
||||
optgroup->append_single_option_line("standby_temperature_delta", "multimaterial_settings_ooze_prevention#temperature-variation");
|
||||
optgroup->append_single_option_line("preheat_time", "multimaterial_settings_ooze_prevention#preheat-time");
|
||||
optgroup->append_single_option_line("preheat_steps", "multimaterial_settings_ooze_prevention#preheat-steps");
|
||||
|
||||
optgroup = page->new_optgroup(L("Flush options"), L"param_flush");
|
||||
optgroup->append_single_option_line("flush_into_infill", "multimaterial_settings_flush_options#flush-into-objects-infill");
|
||||
optgroup->append_single_option_line("flush_into_objects", "multimaterial_settings_flush_options");
|
||||
optgroup->append_single_option_line("flush_into_support", "multimaterial_settings_flush_options#flush-into-objects-support");
|
||||
optgroup = page->new_optgroup(L("Advanced"), L"advanced");
|
||||
optgroup->append_single_option_line("interlocking_beam", "multimaterial_settings_advanced#interlocking-beam");
|
||||
optgroup->append_single_option_line("interface_shells", "multimaterial_settings_advanced#interface-shells");
|
||||
optgroup->append_single_option_line("mmu_segmented_region_max_width", "multimaterial_settings_advanced#maximum-width-of-segmented-region");
|
||||
optgroup->append_single_option_line("mmu_segmented_region_interlocking_depth", "multimaterial_settings_advanced#interlocking-depth-of-segmented-region");
|
||||
optgroup->append_single_option_line("interlocking_beam_width", "multimaterial_settings_advanced#interlocking-beam-width");
|
||||
optgroup->append_single_option_line("interlocking_orientation", "multimaterial_settings_advanced#interlocking-direction");
|
||||
optgroup->append_single_option_line("interlocking_beam_layer_count", "multimaterial_settings_advanced#interlocking-beam-layers");
|
||||
optgroup->append_single_option_line("interlocking_depth", "multimaterial_settings_advanced#interlocking-depth");
|
||||
optgroup->append_single_option_line("interlocking_boundary_avoidance", "multimaterial_settings_advanced#interlocking-boundary-avoidance");
|
||||
|
||||
page = add_options_page(L("Others"), "custom-gcode_other"); // ORCA: icon only visible on placeholders
|
||||
optgroup = page->new_optgroup(L("Skirt"), L"param_skirt");
|
||||
optgroup->append_single_option_line("skirt_loops", "others_settings_skirt#loops");
|
||||
optgroup->append_single_option_line("skirt_type", "others_settings_skirt#type");
|
||||
optgroup->append_single_option_line("min_skirt_length", "others_settings_skirt#minimum-extrusion-length");
|
||||
optgroup->append_single_option_line("skirt_distance", "others_settings_skirt#distance");
|
||||
optgroup->append_single_option_line("skirt_start_angle", "others_settings_skirt#start-point");
|
||||
optgroup->append_single_option_line("skirt_speed", "others_settings_skirt#speed");
|
||||
optgroup->append_single_option_line("skirt_height", "others_settings_skirt#height");
|
||||
optgroup->append_single_option_line("draft_shield", "others_settings_skirt#shield");
|
||||
optgroup->append_single_option_line("single_loop_draft_shield", "others_settings_skirt#single-loop-after-first-layer");
|
||||
|
||||
optgroup = page->new_optgroup(L("Brim"), L"param_adhension");
|
||||
optgroup->append_single_option_line("brim_type", "others_settings_brim#type");
|
||||
optgroup->append_single_option_line("brim_width", "others_settings_brim#width");
|
||||
optgroup->append_single_option_line("brim_object_gap", "others_settings_brim#brim-object-gap");
|
||||
optgroup->append_single_option_line("brim_flow_ratio", "others_settings_brim#brim-flow-ratio");
|
||||
optgroup->append_single_option_line("brim_use_efc_outline", "others_settings_brim#brim-use-efc-outline");
|
||||
optgroup->append_single_option_line("combine_brims", "others_settings_brim#combine-brims");
|
||||
optgroup->append_single_option_line("brim_ears_max_angle", "others_settings_brim#ear-max-angle");
|
||||
optgroup->append_single_option_line("brim_ears_detection_length", "others_settings_brim#ear-detection-radius");
|
||||
|
||||
optgroup = page->new_optgroup(L("Special mode"), L"param_special");
|
||||
optgroup->append_single_option_line("slicing_mode", "others_settings_special_mode#slicing-mode");
|
||||
optgroup->append_single_option_line("print_sequence", "others_settings_special_mode#print-sequence");
|
||||
optgroup->append_single_option_line("print_order", "others_settings_special_mode#intra-layer-order");
|
||||
optgroup->append_single_option_line("spiral_mode", "others_settings_special_mode#spiral-vase");
|
||||
optgroup->append_single_option_line("spiral_mode_smooth", "others_settings_special_mode#smooth-spiral");
|
||||
optgroup->append_single_option_line("spiral_mode_max_xy_smoothing", "others_settings_special_mode#max-xy-smoothing");
|
||||
optgroup->append_single_option_line("spiral_starting_flow_ratio", "others_settings_special_mode#spiral-starting-flow-ratio");
|
||||
optgroup->append_single_option_line("spiral_finishing_flow_ratio", "others_settings_special_mode#spiral-finishing-flow-ratio");
|
||||
|
||||
optgroup->append_single_option_line("timelapse_type", "others_settings_special_mode#timelapse");
|
||||
optgroup->append_single_option_line("enable_wrapping_detection");
|
||||
|
||||
optgroup = page->new_optgroup(L("Fuzzy Skin"), L"fuzzy_skin");
|
||||
optgroup->append_single_option_line("fuzzy_skin", "others_settings_fuzzy_skin");
|
||||
optgroup->append_single_option_line("fuzzy_skin_mode", "others_settings_fuzzy_skin#fuzzy-skin-mode");
|
||||
optgroup->append_single_option_line("fuzzy_skin_noise_type", "others_settings_fuzzy_skin#noise-type");
|
||||
optgroup->append_single_option_line("fuzzy_skin_point_distance", "others_settings_fuzzy_skin#point-distance");
|
||||
optgroup->append_single_option_line("fuzzy_skin_thickness", "others_settings_fuzzy_skin#skin-thickness");
|
||||
optgroup->append_single_option_line("fuzzy_skin_scale", "others_settings_fuzzy_skin#skin-feature-size");
|
||||
optgroup->append_single_option_line("fuzzy_skin_octaves", "others_settings_fuzzy_skin#skin-noise-octaves");
|
||||
optgroup->append_single_option_line("fuzzy_skin_persistence", "others_settings_fuzzy_skin#skin-noise-persistence");
|
||||
optgroup->append_single_option_line("fuzzy_skin_ripples_per_layer", "others_settings_fuzzy_skin#ripples-per-layer");
|
||||
optgroup->append_single_option_line("fuzzy_skin_ripple_offset", "others_settings_fuzzy_skin#ripple-offset");
|
||||
optgroup->append_single_option_line("fuzzy_skin_layers_between_ripple_offset", "others_settings_fuzzy_skin#layers-between-ripple-offset");
|
||||
optgroup->append_single_option_line("fuzzy_skin_first_layer", "others_settings_fuzzy_skin#apply-fuzzy-skin-to-first-layer");
|
||||
|
||||
optgroup = page->new_optgroup(L("G-code output"), L"param_gcode");
|
||||
optgroup->append_single_option_line("reduce_infill_retraction", "others_settings_g_code_output#reduce-infill-retraction");
|
||||
optgroup->append_single_option_line("gcode_add_line_number", "others_settings_g_code_output#add-line-number");
|
||||
optgroup->append_single_option_line("gcode_comments", "others_settings_g_code_output#verbose-g-code");
|
||||
optgroup->append_single_option_line("gcode_label_objects", "others_settings_g_code_output#label-objects");
|
||||
optgroup->append_single_option_line("exclude_object", "others_settings_g_code_output#exclude-objects");
|
||||
option = optgroup->get_option("filename_format");
|
||||
// option.opt.full_width = true;
|
||||
option.opt.is_code = true;
|
||||
option.opt.multiline = true;
|
||||
// option.opt.height = 5;
|
||||
optgroup->append_single_option_line(option, "others_settings_g_code_output#filename-format");
|
||||
|
||||
optgroup = page->new_optgroup(L("Change extrusion role G-code"), L"param_gcode", 0);
|
||||
optgroup->m_on_change = [this, &optgroup_title = optgroup->title](const t_config_option_key& opt_key, const boost::any& value) {
|
||||
validate_custom_gcode_cb(this, optgroup_title, opt_key, value);
|
||||
};
|
||||
optgroup->edit_custom_gcode = [this](const t_config_option_key& opt_key) { edit_custom_gcode(opt_key); };
|
||||
option = optgroup->get_option("process_change_extrusion_role_gcode");
|
||||
option.opt.full_width = true;
|
||||
option.opt.is_code = true;
|
||||
option.opt.height = 15;
|
||||
optgroup->append_single_option_line(option);
|
||||
|
||||
optgroup = page->new_optgroup(L("Post-processing Scripts"), L"param_gcode", 0);
|
||||
option = optgroup->get_option("post_process");
|
||||
option.opt.full_width = true;
|
||||
option.opt.is_code = true;
|
||||
option.opt.height = 15;
|
||||
optgroup->append_single_option_line(option, "others_settings_post_processing_scripts");
|
||||
|
||||
optgroup = page->new_optgroup(L("Notes"), "note", 0);
|
||||
option = optgroup->get_option("notes");
|
||||
option.opt.full_width = true;
|
||||
option.opt.height = 25;//250;
|
||||
optgroup->append_single_option_line(option, "others_settings_notes");
|
||||
|
||||
// Orca: hide the dependencies tab for process for now. The UI is not ready yet.
|
||||
// page = add_options_page(L("Dependencies"), "param_profile_dependencies"); // icons ready
|
||||
// optgroup = page->new_optgroup(L("Profile dependencies"), "param_profile_dependencies"); // icons ready
|
||||
|
||||
// create_line_with_widget(optgroup.get(), "compatible_printers", "", [this](wxWindow* parent) {
|
||||
// return compatible_widget_create(parent, m_compatible_printers);
|
||||
// });
|
||||
|
||||
// option = optgroup->get_option("compatible_printers_condition");
|
||||
// option.opt.full_width = true;
|
||||
// optgroup->append_single_option_line(option);
|
||||
|
||||
// build_preset_description_line(optgroup.get());
|
||||
TabPrint_build_layout(*this);
|
||||
}
|
||||
|
||||
// Reload current config (aka presets->edited_preset->config) into the UI fields.
|
||||
@@ -3888,334 +3414,8 @@ void TabFilament::build()
|
||||
{
|
||||
m_presets = &m_preset_bundle->filaments;
|
||||
load_initial_data();
|
||||
|
||||
auto page = add_options_page(L("Filament"), "custom-gcode_filament"); // ORCA: icon only visible on placeholders
|
||||
//BBS
|
||||
auto optgroup = page->new_optgroup(L("Basic information"), L"param_information");
|
||||
optgroup->append_single_option_line("filament_type", "material_basic_information#type"); // ORCA use same width with other elements
|
||||
optgroup->append_single_option_line("filament_vendor", "material_basic_information#vendor");
|
||||
optgroup->append_single_option_line("filament_soluble", "material_basic_information#soluble-material");
|
||||
// BBS
|
||||
optgroup->append_single_option_line("filament_is_support", "material_basic_information#support-material");
|
||||
optgroup->append_single_option_line("filament_change_length", "material_basic_information#filament-ramming-length");
|
||||
|
||||
//optgroup->append_single_option_line("filament_colour");
|
||||
optgroup->append_single_option_line("required_nozzle_HRC", "material_basic_information#required-nozzle-hrc");
|
||||
optgroup->append_single_option_line("default_filament_colour", "material_basic_information#default-color");
|
||||
optgroup->append_single_option_line("filament_diameter", "material_basic_information#diameter");
|
||||
optgroup->append_single_option_line("filament_adhesiveness_category", "material_basic_information#adhesiveness-category");
|
||||
|
||||
optgroup->append_single_option_line("filament_density", "material_basic_information#density");
|
||||
optgroup->append_single_option_line("filament_shrink", "material_basic_information#shrinkage-xy");
|
||||
optgroup->append_single_option_line("filament_shrinkage_compensation_z", "material_basic_information#shrinkage-z");
|
||||
optgroup->append_single_option_line("filament_cost", "material_basic_information#price");
|
||||
//BBS
|
||||
optgroup->append_single_option_line("temperature_vitrification", "material_basic_information#softening-temperature");
|
||||
optgroup->append_single_option_line("idle_temperature", "material_basic_information#idle-temperature");
|
||||
Line line = { L("Recommended nozzle temperature"), L("Recommended nozzle temperature range of this filament. 0 means no set") };
|
||||
line.append_option(optgroup->get_option("nozzle_temperature_range_low"));
|
||||
line.append_option(optgroup->get_option("nozzle_temperature_range_high"));
|
||||
optgroup->append_line(line);
|
||||
|
||||
optgroup->m_on_change = [this, optgroup](t_config_option_key opt_key, boost::any value) {
|
||||
DynamicPrintConfig &filament_config = m_preset_bundle->filaments.get_edited_preset().config;
|
||||
|
||||
update_dirty();
|
||||
if (!m_postpone_update_ui && (opt_key == "nozzle_temperature_range_low" || opt_key == "nozzle_temperature_range_high")) {
|
||||
m_config_manipulation.check_nozzle_recommended_temperature_range(&filament_config);
|
||||
}
|
||||
on_value_change(opt_key, value);
|
||||
};
|
||||
|
||||
// Orca: New section to focus on flow rate and PA to declutter general section
|
||||
optgroup = page->new_optgroup(L("Flow ratio and Pressure Advance"), L"param_flow_ratio_and_pressure_advance");
|
||||
optgroup->append_single_option_line("pellet_flow_coefficient", "printer_basic_information_advanced#pellet-modded-printer");
|
||||
optgroup->append_single_option_line("filament_flow_ratio", "material_flow_ratio_and_pressure_advance#flow-ratio", 0);
|
||||
|
||||
optgroup->append_single_option_line("enable_pressure_advance", "material_flow_ratio_and_pressure_advance#pressure-advance");
|
||||
optgroup->append_single_option_line("pressure_advance", "material_flow_ratio_and_pressure_advance#pressure-advance");
|
||||
|
||||
// Orca: adaptive pressure advance and calibration model
|
||||
optgroup->append_single_option_line("adaptive_pressure_advance", "material_flow_ratio_and_pressure_advance#enable-adaptive-pressure-advance-beta");
|
||||
optgroup->append_single_option_line("adaptive_pressure_advance_overhangs", "material_flow_ratio_and_pressure_advance#enable-adaptive-pressure-advance-for-overhangs-beta");
|
||||
optgroup->append_single_option_line("adaptive_pressure_advance_bridges", "material_flow_ratio_and_pressure_advance#pressure-advance-for-bridges");
|
||||
|
||||
Option option = optgroup->get_option("adaptive_pressure_advance_model");
|
||||
option.opt.full_width = true;
|
||||
option.opt.is_code = true;
|
||||
option.opt.height = 15;
|
||||
optgroup->append_single_option_line(option);
|
||||
//
|
||||
|
||||
optgroup = page->new_optgroup(L("Print chamber temperature"), L"param_chamber_temp");
|
||||
optgroup->append_single_option_line("activate_chamber_temp_control", "material_temperatures#print-chamber-temperature");
|
||||
optgroup->append_single_option_line("chamber_temperature", "material_temperatures#print-chamber-temperature");
|
||||
|
||||
optgroup = page->new_optgroup(L("Print temperature"), L"param_extruder_temp");
|
||||
line = { L("Nozzle"), L("Nozzle temperature when printing") };
|
||||
line.label_path = "material_temperatures#nozzle";
|
||||
line.append_option(optgroup->get_option("nozzle_temperature_initial_layer", 0));
|
||||
line.append_option(optgroup->get_option("nozzle_temperature", 0));
|
||||
optgroup->append_line(line);
|
||||
|
||||
optgroup = page->new_optgroup(L("Bed temperature"), L"param_bed_temp");
|
||||
line = { L("Cool Plate (SuperTack)"),
|
||||
L("Bed temperature when the Cool Plate SuperTack is installed. A value of 0 means the filament does not support printing on the Cool Plate SuperTack.") };
|
||||
line.label_path = "material_temperatures#bed";
|
||||
line.append_option(optgroup->get_option("supertack_plate_temp_initial_layer"));
|
||||
line.append_option(optgroup->get_option("supertack_plate_temp"));
|
||||
optgroup->append_line(line);
|
||||
|
||||
line = { L("Cool Plate"),
|
||||
L("Bed temperature when the Cool Plate is installed. A value of 0 means the filament does not support printing on the Cool Plate.") };
|
||||
line.label_path = "material_temperatures#bed";
|
||||
line.append_option(optgroup->get_option("cool_plate_temp_initial_layer"));
|
||||
line.append_option(optgroup->get_option("cool_plate_temp"));
|
||||
optgroup->append_line(line);
|
||||
|
||||
line = { L("Textured Cool Plate"),
|
||||
L("Bed temperature when the Textured Cool Plate is installed. A value of 0 means the filament does not support printing on the Textured Cool Plate.") };
|
||||
line.label_path = "material_temperatures#bed";
|
||||
line.append_option(optgroup->get_option("textured_cool_plate_temp_initial_layer"));
|
||||
line.append_option(optgroup->get_option("textured_cool_plate_temp"));
|
||||
optgroup->append_line(line);
|
||||
|
||||
line = { L("Engineering Plate"),
|
||||
L("Bed temperature when the Engineering Plate is installed. A value of 0 means the filament does not support printing on the Engineering Plate.") };
|
||||
line.label_path = "material_temperatures#bed";
|
||||
line.append_option(optgroup->get_option("eng_plate_temp_initial_layer"));
|
||||
line.append_option(optgroup->get_option("eng_plate_temp"));
|
||||
optgroup->append_line(line);
|
||||
|
||||
line = { L("Smooth PEI Plate / High Temp Plate"),
|
||||
L("Bed temperature when the Smooth PEI Plate/High Temperature Plate is installed. A value of 0 means the filament does not support printing on the Smooth PEI Plate/High Temp Plate.") };
|
||||
line.label_path = "material_temperatures#bed";
|
||||
line.append_option(optgroup->get_option("hot_plate_temp_initial_layer"));
|
||||
line.append_option(optgroup->get_option("hot_plate_temp"));
|
||||
optgroup->append_line(line);
|
||||
|
||||
line = { L("Textured PEI Plate"),
|
||||
L("Bed temperature when the Textured PEI Plate is installed. A value of 0 means the filament does not support printing on the Textured PEI Plate.") };
|
||||
line.label_path = "material_temperatures#bed";
|
||||
line.append_option(optgroup->get_option("textured_plate_temp_initial_layer"));
|
||||
line.append_option(optgroup->get_option("textured_plate_temp"));
|
||||
optgroup->append_line(line);
|
||||
|
||||
optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value)
|
||||
{
|
||||
DynamicPrintConfig& filament_config = m_preset_bundle->filaments.get_edited_preset().config;
|
||||
|
||||
update_dirty();
|
||||
/*if (opt_key == "cool_plate_temp" || opt_key == "cool_plate_temp_initial_layer") {
|
||||
m_config_manipulation.check_bed_temperature_difference(BedType::btPC, &filament_config);
|
||||
}
|
||||
else if (opt_key == "eng_plate_temp" || opt_key == "eng_plate_temp_initial_layer") {
|
||||
m_config_manipulation.check_bed_temperature_difference(BedType::btEP, &filament_config);
|
||||
}
|
||||
else if (opt_key == "hot_plate_temp" || opt_key == "hot_plate_temp_initial_layer") {
|
||||
m_config_manipulation.check_bed_temperature_difference(BedType::btPEI, &filament_config);
|
||||
}
|
||||
else if (opt_key == "textured_plate_temp" || opt_key == "textured_plate_temp_initial_layer") {
|
||||
m_config_manipulation.check_bed_temperature_difference(BedType::btPTE, &filament_config);
|
||||
}
|
||||
else */if (opt_key == "nozzle_temperature") {
|
||||
m_config_manipulation.check_nozzle_temperature_range(&filament_config);
|
||||
}
|
||||
else if (opt_key == "nozzle_temperature_initial_layer") {
|
||||
m_config_manipulation.check_nozzle_temperature_initial_layer_range(&filament_config);
|
||||
}
|
||||
else if (opt_key == "chamber_temperature") {
|
||||
m_config_manipulation.check_chamber_temperature(&filament_config);
|
||||
}
|
||||
|
||||
on_value_change(opt_key, value);
|
||||
};
|
||||
|
||||
//BBS
|
||||
optgroup = page->new_optgroup(L("Volumetric speed limitation"), L"param_volumetric_speed");
|
||||
optgroup->append_single_option_line("filament_adaptive_volumetric_speed", "material_volumetric_speed_limitation#adaptive-volumetric-speed", 0);
|
||||
optgroup->append_single_option_line("filament_max_volumetric_speed", "material_volumetric_speed_limitation#max-volumetric-speed", 0);
|
||||
|
||||
//line = { "", "" };
|
||||
//line.full_width = 1;
|
||||
//line.widget = [this](wxWindow* parent) {
|
||||
// return description_line_widget(parent, &m_volumetric_speed_description_line);
|
||||
//};
|
||||
//optgroup->append_line(line);
|
||||
|
||||
page = add_options_page(L("Cooling"), "custom-gcode_cooling_fan"); // ORCA: icon only visible on placeholders
|
||||
|
||||
//line = { "", "" };
|
||||
//line.full_width = 1;
|
||||
//line.widget = [this](wxWindow* parent) {
|
||||
// return description_line_widget(parent, &m_cooling_description_line);
|
||||
//};
|
||||
//optgroup->append_line(line);
|
||||
optgroup = page->new_optgroup(L("Cooling for specific layer"), L"param_cooling_specific_layer");
|
||||
optgroup->append_single_option_line("close_fan_the_first_x_layers", "material_cooling#no-cooling-for-the-first");
|
||||
optgroup->append_single_option_line("full_fan_speed_layer", "material_cooling#full-fan-speed-at-layer");
|
||||
|
||||
optgroup = page->new_optgroup(L("Part cooling fan"), L"param_cooling_part_fan");
|
||||
line = { L("Min fan speed threshold"), L("Part cooling fan speed will start to run at min speed when the estimated layer time is no longer than the layer time in setting. When layer time is shorter than threshold, fan speed is interpolated between the minimum and maximum fan speed according to layer printing time") };
|
||||
line.label_path = "material_cooling#material-part-cooling-fan";
|
||||
line.append_option(optgroup->get_option("fan_min_speed"));
|
||||
line.append_option(optgroup->get_option("fan_cooling_layer_time"));
|
||||
optgroup->append_line(line);
|
||||
line = { L("Max fan speed threshold"), L("Part cooling fan speed will be max when the estimated layer time is shorter than the setting value") };
|
||||
line.label_path = "material_cooling#material-part-cooling-fan";
|
||||
line.append_option(optgroup->get_option("fan_max_speed"));
|
||||
line.append_option(optgroup->get_option("slow_down_layer_time"));
|
||||
optgroup->append_line(line);
|
||||
optgroup->append_single_option_line("reduce_fan_stop_start_freq", "material_cooling#keep-fan-always-on");
|
||||
optgroup->append_single_option_line("slow_down_for_layer_cooling", "material_cooling#slow-printing-down-for-better-layer-cooling");
|
||||
optgroup->append_single_option_line("dont_slow_down_outer_wall", "material_cooling#dont-slow-down-outer-walls");
|
||||
optgroup->append_single_option_line("slow_down_min_speed", "material_cooling#min-print-speed");
|
||||
|
||||
optgroup->append_single_option_line("enable_overhang_bridge_fan", "material_cooling#force-cooling-for-overhangs-and-bridges");
|
||||
optgroup->append_single_option_line("overhang_fan_threshold", "material_cooling#overhang-cooling-activation-threshold");
|
||||
optgroup->append_single_option_line("overhang_fan_speed", "material_cooling#overhangs-and-external-bridges-fan-speed");
|
||||
optgroup->append_single_option_line("internal_bridge_fan_speed", "material_cooling#internal-bridges-fan-speed"); // ORCA: Add support for separate internal bridge fan speed control
|
||||
optgroup->append_single_option_line("support_material_interface_fan_speed", "material_cooling#support-interface-fan-speed");
|
||||
optgroup->append_single_option_line("ironing_fan_speed", "material_cooling#ironing-fan-speed"); // ORCA: Add support for ironing fan speed control
|
||||
|
||||
optgroup = page->new_optgroup(L("Auxiliary part cooling fan"), L"param_cooling_aux_fan");
|
||||
optgroup->append_single_option_line("additional_cooling_fan_speed", "material_cooling#auxiliary-part-cooling-fan");
|
||||
|
||||
optgroup = page->new_optgroup(L("Exhaust fan"),L"param_cooling_exhaust");
|
||||
|
||||
optgroup->append_single_option_line("activate_air_filtration", "material_cooling#activate-air-filtration");
|
||||
|
||||
line = {L("During print"), ""};
|
||||
line.append_option(optgroup->get_option("activate_air_filtration_during_print"));
|
||||
line.append_option(optgroup->get_option("during_print_exhaust_fan_speed"));
|
||||
line.label_path = "material_cooling#during-print";
|
||||
optgroup->append_line(line);
|
||||
|
||||
|
||||
line = {L("Complete print"), ""};
|
||||
line.append_option(optgroup->get_option("activate_air_filtration_on_completion"));
|
||||
line.append_option(optgroup->get_option("complete_print_exhaust_fan_speed"));
|
||||
line.label_path = "material_cooling#complete-print";
|
||||
optgroup->append_line(line);
|
||||
//BBS
|
||||
add_filament_overrides_page();
|
||||
const int gcode_field_height = 15; // 150
|
||||
const int notes_field_height = 25; // 250
|
||||
|
||||
auto edit_custom_gcode_fn = [this](const t_config_option_key& opt_key) { edit_custom_gcode(opt_key); };
|
||||
|
||||
page = add_options_page(L("Advanced"), "custom-gcode_advanced"); // ORCA: icon only visible on placeholders
|
||||
optgroup = page->new_optgroup(L("Filament start G-code"), L"param_gcode", 0);
|
||||
optgroup->m_on_change = [this, &optgroup_title = optgroup->title](const t_config_option_key& opt_key, const boost::any& value) {
|
||||
validate_custom_gcode_cb(this, optgroup_title, opt_key, value);
|
||||
};
|
||||
optgroup->edit_custom_gcode = edit_custom_gcode_fn;
|
||||
option = optgroup->get_option("filament_start_gcode");
|
||||
option.opt.full_width = true;
|
||||
option.opt.is_code = true;
|
||||
option.opt.height = gcode_field_height;// 150;
|
||||
optgroup->append_single_option_line(option);
|
||||
|
||||
optgroup = page->new_optgroup(L("Change extrusion role G-code"), L"param_gcode", 0);
|
||||
optgroup->m_on_change = [this, &optgroup_title = optgroup->title](const t_config_option_key& opt_key, const boost::any& value) {
|
||||
validate_custom_gcode_cb(this, optgroup_title, opt_key, value);
|
||||
};
|
||||
optgroup->edit_custom_gcode = edit_custom_gcode_fn;
|
||||
option = optgroup->get_option("filament_change_extrusion_role_gcode");
|
||||
option.opt.full_width = true;
|
||||
option.opt.is_code = true;
|
||||
option.opt.height = gcode_field_height;// 150;
|
||||
optgroup->append_single_option_line(option);
|
||||
|
||||
optgroup = page->new_optgroup(L("Filament end G-code"), L"param_gcode", 0);
|
||||
optgroup->m_on_change = [this, &optgroup_title = optgroup->title](const t_config_option_key& opt_key, const boost::any& value) {
|
||||
validate_custom_gcode_cb(this, optgroup_title, opt_key, value);
|
||||
};
|
||||
optgroup->edit_custom_gcode = edit_custom_gcode_fn;
|
||||
option = optgroup->get_option("filament_end_gcode");
|
||||
option.opt.full_width = true;
|
||||
option.opt.is_code = true;
|
||||
option.opt.height = gcode_field_height;// 150;
|
||||
optgroup->append_single_option_line(option);
|
||||
|
||||
page = add_options_page(L("Multimaterial"), "custom-gcode_multi_material"); // ORCA: icon only visible on placeholders
|
||||
optgroup = page->new_optgroup(L("Wipe tower parameters"), "param_tower");
|
||||
optgroup->append_single_option_line("filament_minimal_purge_on_wipe_tower", "material_multimaterial#multimaterial-wipe-tower-parameters");
|
||||
optgroup->append_single_option_line("filament_tower_interface_pre_extrusion_dist", "material_multimaterial#multimaterial-wipe-tower-parameters");
|
||||
optgroup->append_single_option_line("filament_tower_interface_pre_extrusion_length", "material_multimaterial#multimaterial-wipe-tower-parameters");
|
||||
optgroup->append_single_option_line("filament_tower_ironing_area", "material_multimaterial#multimaterial-wipe-tower-parameters");
|
||||
optgroup->append_single_option_line("filament_tower_interface_purge_volume", "material_multimaterial#multimaterial-wipe-tower-parameters");
|
||||
optgroup->append_single_option_line("filament_tower_interface_print_temp", "material_multimaterial#multimaterial-wipe-tower-parameters");
|
||||
|
||||
optgroup = page->new_optgroup(L("Multi Filament"));
|
||||
// optgroup->append_single_option_line("filament_flush_temp", "", 0);
|
||||
// optgroup->append_single_option_line("filament_flush_volumetric_speed", "", 0);
|
||||
optgroup->append_single_option_line("long_retractions_when_ec", "material_multimaterial#multi-filament" , 0);
|
||||
optgroup->append_single_option_line("retraction_distances_when_ec", "material_multimaterial#multi-filament" , 0);
|
||||
|
||||
optgroup = page->new_optgroup(L("Tool change parameters with single extruder MM printers"), "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) {
|
||||
|
||||
// ORCA modernize button style
|
||||
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& e) {
|
||||
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;
|
||||
});
|
||||
|
||||
optgroup = page->new_optgroup(L("Tool change parameters with multi extruder MM printers"), "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");
|
||||
|
||||
page = add_options_page(L("Dependencies"), "advanced");
|
||||
optgroup = page->new_optgroup(L("Compatible printers"), "param_dependencies_printers");
|
||||
create_line_with_widget(optgroup.get(), "compatible_printers", "", [this](wxWindow* parent) {
|
||||
return compatible_widget_create(parent, m_compatible_printers);
|
||||
});
|
||||
|
||||
option = optgroup->get_option("compatible_printers_condition");
|
||||
option.opt.full_width = true;
|
||||
optgroup->append_single_option_line(option, "material_dependencies#compatible-printers");
|
||||
|
||||
optgroup = page->new_optgroup(L("Compatible process profiles"), "param_dependencies_presets");
|
||||
create_line_with_widget(optgroup.get(), "compatible_prints", "", [this](wxWindow* parent) {
|
||||
return compatible_widget_create(parent, m_compatible_prints);
|
||||
});
|
||||
|
||||
option = optgroup->get_option("compatible_prints_condition");
|
||||
option.opt.full_width = true;
|
||||
optgroup->append_single_option_line(option, "material_dependencies#compatible-process-profiles");
|
||||
|
||||
page = add_options_page(L("Notes"), "custom-gcode_note"); // ORCA: icon only visible on placeholders
|
||||
optgroup = page->new_optgroup(L("Notes"),"note", 0);
|
||||
optgroup->label_width = 0;
|
||||
option = optgroup->get_option("filament_notes");
|
||||
option.opt.full_width = true;
|
||||
option.opt.height = notes_field_height;// 250;
|
||||
optgroup->append_single_option_line(option);
|
||||
|
||||
//build_preset_description_line(optgroup.get());
|
||||
TabFilament_build_main_layout(*this); // generated: Filament / Cooling / Multimaterial pages
|
||||
build_extra_layout(); // TabLayoutExtra.cpp: toolchange+ramming / overrides / deps / notes
|
||||
}
|
||||
|
||||
// Reload current config (aka presets->edited_preset->config) into the UI fields.
|
||||
@@ -4551,154 +3751,11 @@ void TabPrinter::build_fff()
|
||||
optgroup->append_single_option_line("support_chamber_temp_control", "printer_basic_information_accessory#support-controlling-chamber-temperature");
|
||||
optgroup->append_single_option_line("support_air_filtration", "printer_basic_information_accessory#support-air-filtration");
|
||||
|
||||
auto edit_custom_gcode_fn = [this](const t_config_option_key& opt_key) { edit_custom_gcode(opt_key); };
|
||||
// Basic info page: yaml-generated structure, hook methods in TabLayoutExtra.cpp
|
||||
TabPrinter_build_basic_info_layout(*this);
|
||||
// Machine G-code + Notes pages: yaml-generated
|
||||
TabPrinter_build_gcode_layout(*this);
|
||||
|
||||
const int gcode_field_height = 15; // 150
|
||||
const int notes_field_height = 25; // 250
|
||||
page = add_options_page(L("Machine G-code"), "custom-gcode_gcode"); // ORCA: icon only visible on placeholders
|
||||
optgroup = page->new_optgroup(L("File header G-code"), L"param_gcode", 0);
|
||||
optgroup->m_on_change = [this, &optgroup_title = optgroup->title](const t_config_option_key& opt_key, const boost::any& value) {
|
||||
validate_custom_gcode_cb(this, optgroup_title, opt_key, value);
|
||||
};
|
||||
optgroup->edit_custom_gcode = edit_custom_gcode_fn;
|
||||
option = optgroup->get_option("file_start_gcode");
|
||||
option.opt.full_width = true;
|
||||
option.opt.is_code = true;
|
||||
option.opt.height = 8;
|
||||
optgroup->append_single_option_line(option);
|
||||
|
||||
optgroup = page->new_optgroup(L("Machine start G-code"), L"param_gcode", 0);
|
||||
optgroup->m_on_change = [this, &optgroup_title = optgroup->title](const t_config_option_key& opt_key, const boost::any& value) {
|
||||
validate_custom_gcode_cb(this, optgroup_title, opt_key, value);
|
||||
};
|
||||
optgroup->edit_custom_gcode = edit_custom_gcode_fn;
|
||||
option = optgroup->get_option("machine_start_gcode");
|
||||
option.opt.full_width = true;
|
||||
option.opt.is_code = true;
|
||||
option.opt.height = gcode_field_height;//150;
|
||||
optgroup->append_single_option_line(option, "printer_machine_gcode#machine-start-g-code");
|
||||
|
||||
optgroup = page->new_optgroup(L("Machine end G-code"), L"param_gcode", 0);
|
||||
optgroup->m_on_change = [this, &optgroup_title = optgroup->title](const t_config_option_key& opt_key, const boost::any& value) {
|
||||
validate_custom_gcode_cb(this, optgroup_title, opt_key, value);
|
||||
};
|
||||
optgroup->edit_custom_gcode = edit_custom_gcode_fn;
|
||||
option = optgroup->get_option("machine_end_gcode");
|
||||
option.opt.full_width = true;
|
||||
option.opt.is_code = true;
|
||||
option.opt.height = gcode_field_height;//150;
|
||||
optgroup->append_single_option_line(option, "printer_machine_gcode#machine-end-g-code");
|
||||
|
||||
optgroup = page->new_optgroup(L("Printing by object G-code"), L"param_gcode", 0);
|
||||
optgroup->m_on_change = [this, optgroup](const t_config_option_key &opt_key, const boost::any &value) {
|
||||
validate_custom_gcode_cb(this, optgroup, opt_key, value);
|
||||
};
|
||||
optgroup->edit_custom_gcode = edit_custom_gcode_fn;
|
||||
option = optgroup->get_option("printing_by_object_gcode");
|
||||
option.opt.full_width = true;
|
||||
option.opt.is_code = true;
|
||||
option.opt.height = gcode_field_height; // 150;
|
||||
optgroup->append_single_option_line(option, "printer_machine_gcode#printing-by-object-g-code");
|
||||
|
||||
|
||||
optgroup = page->new_optgroup(L("Before layer change G-code"),"param_gcode", 0);
|
||||
optgroup->m_on_change = [this, &optgroup_title = optgroup->title](const t_config_option_key& opt_key, const boost::any& value) {
|
||||
validate_custom_gcode_cb(this, optgroup_title, opt_key, value);
|
||||
};
|
||||
optgroup->edit_custom_gcode = edit_custom_gcode_fn;
|
||||
option = optgroup->get_option("before_layer_change_gcode");
|
||||
option.opt.full_width = true;
|
||||
option.opt.is_code = true;
|
||||
option.opt.height = gcode_field_height;//150;
|
||||
optgroup->append_single_option_line(option, "printer_machine_gcode#before-layer-change-g-code");
|
||||
|
||||
optgroup = page->new_optgroup(L("Layer change G-code"), L"param_gcode", 0);
|
||||
optgroup->m_on_change = [this, &optgroup_title = optgroup->title](const t_config_option_key& opt_key, const boost::any& value) {
|
||||
validate_custom_gcode_cb(this, optgroup_title, opt_key, value);
|
||||
};
|
||||
optgroup->edit_custom_gcode = edit_custom_gcode_fn;
|
||||
option = optgroup->get_option("layer_change_gcode");
|
||||
option.opt.full_width = true;
|
||||
option.opt.is_code = true;
|
||||
option.opt.height = gcode_field_height;//150;
|
||||
optgroup->append_single_option_line(option, "printer_machine_gcode#layer-change-g-code");
|
||||
|
||||
optgroup = page->new_optgroup(L("Timelapse G-code"), L"param_gcode", 0);
|
||||
optgroup->m_on_change = [this, &optgroup_title = optgroup->title](const t_config_option_key& opt_key, const boost::any& value) {
|
||||
validate_custom_gcode_cb(this, optgroup_title, opt_key, value);
|
||||
};
|
||||
optgroup->edit_custom_gcode = edit_custom_gcode_fn;
|
||||
option = optgroup->get_option("time_lapse_gcode");
|
||||
option.opt.full_width = true;
|
||||
option.opt.is_code = true;
|
||||
option.opt.height = gcode_field_height;//150;
|
||||
optgroup->append_single_option_line(option, "printer_machine_gcode#timelapse-g-code");
|
||||
|
||||
optgroup = page->new_optgroup(L("Clumping Detection G-code"), L"param_gcode", 0);
|
||||
optgroup->m_on_change = [this, optgroup](const t_config_option_key &opt_key, const boost::any &value) {
|
||||
validate_custom_gcode_cb(this, optgroup, opt_key, value);
|
||||
};
|
||||
optgroup->edit_custom_gcode = edit_custom_gcode_fn;
|
||||
option = optgroup->get_option("wrapping_detection_gcode");
|
||||
option.opt.full_width = true;
|
||||
option.opt.is_code = true;
|
||||
option.opt.height = gcode_field_height; // 150;
|
||||
optgroup->append_single_option_line(option, "printer_machine_gcode#clumping-detection-g-code");
|
||||
|
||||
optgroup = page->new_optgroup(L("Change filament G-code"), L"param_gcode", 0);
|
||||
optgroup->m_on_change = [this, &optgroup_title = optgroup->title](const t_config_option_key& opt_key, const boost::any& value) {
|
||||
validate_custom_gcode_cb(this, optgroup_title, opt_key, value);
|
||||
};
|
||||
optgroup->edit_custom_gcode = edit_custom_gcode_fn;
|
||||
option = optgroup->get_option("change_filament_gcode");
|
||||
option.opt.full_width = true;
|
||||
option.opt.is_code = true;
|
||||
option.opt.height = gcode_field_height;//150;
|
||||
optgroup->append_single_option_line(option, "printer_machine_gcode#change-filament-g-code");
|
||||
|
||||
optgroup = page->new_optgroup(L("Change extrusion role G-code"), L"param_gcode", 0);
|
||||
optgroup->m_on_change = [this, &optgroup_title = optgroup->title](const t_config_option_key &opt_key, const boost::any &value) {
|
||||
validate_custom_gcode_cb(this, optgroup_title, opt_key, value);
|
||||
};
|
||||
optgroup->edit_custom_gcode = edit_custom_gcode_fn;
|
||||
option = optgroup->get_option("change_extrusion_role_gcode");
|
||||
option.opt.full_width = true;
|
||||
option.opt.is_code = true;
|
||||
option.opt.height = gcode_field_height;//150;
|
||||
optgroup->append_single_option_line(option, "printer_machine_gcode#change-extrusion-role-g-code");
|
||||
|
||||
optgroup = page->new_optgroup(L("Pause G-code"), L"param_gcode", 0);
|
||||
optgroup->m_on_change = [this, &optgroup_title = optgroup->title](const t_config_option_key& opt_key, const boost::any& value) {
|
||||
validate_custom_gcode_cb(this, optgroup_title, opt_key, value);
|
||||
};
|
||||
optgroup->edit_custom_gcode = edit_custom_gcode_fn;
|
||||
option = optgroup->get_option("machine_pause_gcode");
|
||||
option.opt.is_code = true;
|
||||
option.opt.height = gcode_field_height;//150;
|
||||
optgroup->append_single_option_line(option, "printer_machine_gcode#pause-g-code");
|
||||
|
||||
optgroup = page->new_optgroup(L("Template Custom G-code"), L"param_gcode", 0);
|
||||
optgroup->m_on_change = [this, &optgroup_title = optgroup->title](const t_config_option_key& opt_key, const boost::any& value) {
|
||||
validate_custom_gcode_cb(this, optgroup_title, opt_key, value);
|
||||
};
|
||||
optgroup->edit_custom_gcode = edit_custom_gcode_fn;
|
||||
option = optgroup->get_option("template_custom_gcode");
|
||||
option.opt.is_code = true;
|
||||
option.opt.height = gcode_field_height;//150;
|
||||
optgroup->append_single_option_line(option, "printer_machine_gcode#template-custom-g-code");
|
||||
|
||||
page = add_options_page(L("Notes"), "custom-gcode_note"); // ORCA: icon only visible on placeholders
|
||||
optgroup = page->new_optgroup(L("Notes"), "note", 0);
|
||||
option = optgroup->get_option("printer_notes");
|
||||
option.opt.full_width = true;
|
||||
option.opt.height = notes_field_height;//250;
|
||||
optgroup->append_single_option_line(option);
|
||||
#if 0
|
||||
//page = add_options_page(L("Dependencies"), "advanced");
|
||||
// optgroup = page->new_optgroup(L("Profile dependencies"));
|
||||
|
||||
// build_preset_description_line(optgroup.get());
|
||||
#endif
|
||||
build_unregular_pages(true);
|
||||
}
|
||||
|
||||
|
||||
@@ -573,6 +573,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;
|
||||
@@ -644,6 +645,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
|
||||
872
tools/config_codegen.py
Normal file
872
tools/config_codegen.py
Normal file
@@ -0,0 +1,872 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
OrcaSlicer Config Code Generator
|
||||
|
||||
Reads compiled protobuf descriptor set and generates C++ source files
|
||||
that replace hand-written config registration, preset lists, and invalidation chains.
|
||||
|
||||
Usage:
|
||||
# Step 1: Compile .proto files to a descriptor set
|
||||
protoc --proto_path=src/PrintConfigs --descriptor_set_out=config.desc \
|
||||
--include_imports src/PrintConfigs/*.proto
|
||||
|
||||
# Step 2: Generate Python bindings (one-time, or when config_metadata.proto changes)
|
||||
protoc --proto_path=src/PrintConfigs --python_out=tools/ config_metadata.proto
|
||||
|
||||
# Step 3: Run codegen
|
||||
python tools/config_codegen.py config.desc codegen/generated/
|
||||
|
||||
Outputs:
|
||||
- PrintConfigDef_generated.cpp (init_fff_params body)
|
||||
- Preset_options_generated.cpp (s_Preset_*_options arrays)
|
||||
- Invalidation_generated.cpp (opt_key -> steps map)
|
||||
- OptionKeys_generated.cpp (extruder/filament key lists)
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import re
|
||||
import argparse
|
||||
from pathlib import Path
|
||||
|
||||
# Add tools/ to path so we can import generated config_metadata_pb2
|
||||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
try:
|
||||
from google.protobuf import descriptor_pb2
|
||||
# Import the generated bindings - this registers extensions globally
|
||||
import config_metadata_pb2 as meta_pb2
|
||||
except ImportError as e:
|
||||
print(f"ERROR: {e}")
|
||||
print("Ensure google-protobuf is installed: pip install protobuf")
|
||||
print("And that config_metadata_pb2.py exists in tools/")
|
||||
print("Generate it with: protoc --proto_path=src/PrintConfigs --python_out=tools/ config_metadata.proto")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
# Proto FieldDescriptorProto.Type enum values
|
||||
TYPE_DOUBLE = 1
|
||||
TYPE_FLOAT = 2
|
||||
TYPE_INT64 = 3
|
||||
TYPE_UINT64 = 4
|
||||
TYPE_INT32 = 5
|
||||
TYPE_FIXED64 = 6
|
||||
TYPE_FIXED32 = 7
|
||||
TYPE_BOOL = 8
|
||||
TYPE_STRING = 9
|
||||
TYPE_MESSAGE = 11
|
||||
TYPE_UINT32 = 13
|
||||
TYPE_ENUM = 14
|
||||
TYPE_SINT32 = 17
|
||||
TYPE_SINT64 = 18
|
||||
|
||||
# Proto label
|
||||
LABEL_OPTIONAL = 1
|
||||
LABEL_REQUIRED = 2
|
||||
LABEL_REPEATED = 3
|
||||
|
||||
|
||||
def mode_to_cpp(mode_val):
|
||||
"""Convert mode enum value to C++ constant."""
|
||||
return {
|
||||
meta_pb2.MODE_SIMPLE: "comSimple",
|
||||
meta_pb2.MODE_ADVANCED: "comAdvanced",
|
||||
meta_pb2.MODE_DEVELOP: "comDevelop",
|
||||
}.get(mode_val, "comAdvanced")
|
||||
|
||||
|
||||
_PRINT_STEPS = None # set after meta_pb2 import resolves enum values
|
||||
_OBJECT_STEPS = None
|
||||
|
||||
|
||||
def _init_step_sets():
|
||||
global _PRINT_STEPS, _OBJECT_STEPS
|
||||
if _PRINT_STEPS is None:
|
||||
_PRINT_STEPS = {meta_pb2.STEP_GCODE_EXPORT, meta_pb2.STEP_SKIRT_BRIM, meta_pb2.STEP_WIPE_TOWER}
|
||||
_OBJECT_STEPS = {meta_pb2.STEP_SLICE, meta_pb2.STEP_PERIMETERS, meta_pb2.STEP_INFILL, meta_pb2.STEP_SUPPORT}
|
||||
|
||||
|
||||
def step_to_cpp(step_val):
|
||||
"""Convert invalidation step to C++ constant."""
|
||||
return {
|
||||
meta_pb2.STEP_GCODE_EXPORT: "psGCodeExport",
|
||||
meta_pb2.STEP_SKIRT_BRIM: "psSkirtBrim",
|
||||
meta_pb2.STEP_WIPE_TOWER: "psWipeTower",
|
||||
meta_pb2.STEP_SLICE: "posSlice",
|
||||
meta_pb2.STEP_PERIMETERS: "posPerimeters",
|
||||
meta_pb2.STEP_INFILL: "posInfill",
|
||||
meta_pb2.STEP_SUPPORT: "posSupportMaterial",
|
||||
meta_pb2.STEP_NONE: "",
|
||||
}.get(step_val, "")
|
||||
|
||||
|
||||
def proto_type_to_co_type(field_desc, is_nullable=False):
|
||||
"""
|
||||
Map a protobuf field descriptor to OrcaSlicer's coXXX type constant
|
||||
and ConfigOptionXXX class name.
|
||||
|
||||
Returns: (co_type_str, config_option_class, is_vector)
|
||||
"""
|
||||
ftype = field_desc.type
|
||||
is_repeated = (field_desc.label == LABEL_REPEATED)
|
||||
type_name = field_desc.type_name # For message types
|
||||
|
||||
# Handle message types (FloatOrPercent, Point2D)
|
||||
if ftype == TYPE_MESSAGE:
|
||||
if "FloatOrPercent" in type_name:
|
||||
if is_repeated:
|
||||
return ("coFloatsOrPercents", "ConfigOptionFloatsOrPercents", True)
|
||||
return ("coFloatOrPercent", "ConfigOptionFloatOrPercent", False)
|
||||
elif "Point2D" in type_name:
|
||||
if is_repeated:
|
||||
return ("coPoints", "ConfigOptionPoints", True)
|
||||
return ("coPoint", "ConfigOptionPoint", False)
|
||||
|
||||
# Handle enum types
|
||||
if ftype == TYPE_ENUM:
|
||||
if is_repeated:
|
||||
return ("coEnums", "ConfigOptionEnumsGeneric", True)
|
||||
return ("coEnum", "ConfigOptionEnum", False)
|
||||
|
||||
# Scalar/vector types
|
||||
if ftype in (TYPE_FLOAT, TYPE_DOUBLE):
|
||||
if is_repeated:
|
||||
if is_nullable:
|
||||
return ("coFloats", "ConfigOptionFloatsNullable", True)
|
||||
return ("coFloats", "ConfigOptionFloats", True)
|
||||
return ("coFloat", "ConfigOptionFloat", False)
|
||||
|
||||
if ftype in (TYPE_INT32, TYPE_INT64, TYPE_SINT32, TYPE_SINT64,
|
||||
TYPE_UINT32, TYPE_UINT64, TYPE_FIXED32, TYPE_FIXED64):
|
||||
if is_repeated:
|
||||
if is_nullable:
|
||||
return ("coInts", "ConfigOptionIntsNullable", True)
|
||||
return ("coInts", "ConfigOptionInts", True)
|
||||
return ("coInt", "ConfigOptionInt", False)
|
||||
|
||||
if ftype == TYPE_BOOL:
|
||||
if is_repeated:
|
||||
if is_nullable:
|
||||
return ("coBools", "ConfigOptionBoolsNullable", True)
|
||||
return ("coBools", "ConfigOptionBools", True)
|
||||
return ("coBool", "ConfigOptionBool", False)
|
||||
|
||||
if ftype == TYPE_STRING:
|
||||
if is_repeated:
|
||||
return ("coStrings", "ConfigOptionStrings", True)
|
||||
return ("coString", "ConfigOptionString", False)
|
||||
|
||||
return ("coNone", "ConfigOption", False)
|
||||
|
||||
|
||||
def parse_field_options(field_desc_proto):
|
||||
"""
|
||||
Re-parse FieldOptions from a FieldDescriptorProto with extensions registered.
|
||||
This is needed because the FileDescriptorSet parser doesn't know about our
|
||||
custom extensions, so they end up as unknown fields. Re-parsing with the
|
||||
extensions registered (via config_metadata_pb2 import) resolves them.
|
||||
"""
|
||||
from google.protobuf import descriptor_pb2
|
||||
opts = field_desc_proto.options
|
||||
if not opts.ByteSize():
|
||||
return descriptor_pb2.FieldOptions()
|
||||
|
||||
# Re-parse the serialized options with extensions registered
|
||||
reparsed = descriptor_pb2.FieldOptions()
|
||||
reparsed.ParseFromString(opts.SerializeToString())
|
||||
return reparsed
|
||||
|
||||
|
||||
class FieldInfo:
|
||||
"""Parsed information about a single config field from proto descriptor."""
|
||||
|
||||
def __init__(self, field_desc):
|
||||
self.name = field_desc.name
|
||||
self.field_desc = field_desc
|
||||
|
||||
# Re-parse options with extensions registered
|
||||
opts = parse_field_options(field_desc)
|
||||
|
||||
# Read extensions using the proper protobuf API
|
||||
self.label = opts.Extensions[meta_pb2.label] or None
|
||||
self.full_label = opts.Extensions[meta_pb2.full_label] or None
|
||||
self.tooltip = opts.Extensions[meta_pb2.tooltip] or None
|
||||
self.category = opts.Extensions[meta_pb2.category] or None
|
||||
self.sidetext = opts.Extensions[meta_pb2.sidetext] or None
|
||||
self.min_value = opts.Extensions[meta_pb2.min_value] if opts.HasExtension(meta_pb2.min_value) else None
|
||||
self.max_value = opts.Extensions[meta_pb2.max_value] if opts.HasExtension(meta_pb2.max_value) else None
|
||||
self.max_literal = opts.Extensions[meta_pb2.max_literal] if opts.HasExtension(meta_pb2.max_literal) else None
|
||||
self.mode = opts.Extensions[meta_pb2.mode] # 0 = MODE_SIMPLE (default)
|
||||
self.has_mode = opts.HasExtension(meta_pb2.mode)
|
||||
self.ratio_over = opts.Extensions[meta_pb2.ratio_over] or None
|
||||
self.multiline = opts.Extensions[meta_pb2.multiline]
|
||||
self.full_width = opts.Extensions[meta_pb2.full_width]
|
||||
self.height = opts.Extensions[meta_pb2.height] or None
|
||||
self.is_nullable = opts.Extensions[meta_pb2.is_nullable]
|
||||
self.gui_type = opts.Extensions[meta_pb2.gui_type] or None
|
||||
self.gui_flags = opts.Extensions[meta_pb2.gui_flags] or None
|
||||
self.enum_keys_map = opts.Extensions[meta_pb2.enum_keys_map_ref] or None
|
||||
self.no_cli = opts.Extensions[meta_pb2.no_cli]
|
||||
self.readonly = opts.Extensions[meta_pb2.readonly]
|
||||
self.preset = opts.Extensions[meta_pb2.preset] # 0 = PRESET_PRINT
|
||||
self.invalidates = list(opts.Extensions[meta_pb2.invalidates])
|
||||
self.list_membership = list(opts.Extensions[meta_pb2.list_membership])
|
||||
self.legacy_name = opts.Extensions[meta_pb2.legacy_name] or None
|
||||
|
||||
# Default value and enum metadata
|
||||
self.has_default = opts.Extensions[meta_pb2.has_default]
|
||||
self.default_value = opts.Extensions[meta_pb2.default_value] if self.has_default else None
|
||||
self.enum_value_entries = list(opts.Extensions[meta_pb2.enum_value_entries])
|
||||
self.enum_label_entries = list(opts.Extensions[meta_pb2.enum_label_entries])
|
||||
self.co_type_hint = opts.Extensions[meta_pb2.co_type_hint] or None
|
||||
|
||||
# Resolve C++ type info - co_type_hint overrides auto-detection
|
||||
co_type, option_class, is_vec = proto_type_to_co_type(
|
||||
field_desc, self.is_nullable)
|
||||
if self.co_type_hint:
|
||||
co_type = self.co_type_hint
|
||||
# Fix up option_class for hint-overridden types
|
||||
hint_class_map = {
|
||||
"coPercent": "ConfigOptionPercent",
|
||||
"coPercents": "ConfigOptionPercents",
|
||||
"coEnum": "ConfigOptionEnum",
|
||||
"coEnums": "ConfigOptionEnumsGeneric",
|
||||
}
|
||||
if self.co_type_hint in hint_class_map:
|
||||
option_class = hint_class_map[self.co_type_hint]
|
||||
self.co_type = co_type
|
||||
self.option_class = option_class
|
||||
self.is_vector = is_vec
|
||||
|
||||
|
||||
class CodeGenerator:
|
||||
"""Generates C++ source files from parsed proto descriptors."""
|
||||
|
||||
def __init__(self, descriptor_set):
|
||||
self.descriptor_set = descriptor_set
|
||||
self.fields = [] # All FieldInfo objects
|
||||
self.virtual_keys_by_preset = { # virtual_preset_keys per preset type
|
||||
meta_pb2.PRESET_PRINT: [],
|
||||
meta_pb2.PRESET_FILAMENT: [],
|
||||
meta_pb2.PRESET_PRINTER: [],
|
||||
}
|
||||
self._parse_all_fields()
|
||||
|
||||
@staticmethod
|
||||
def _preset_type_from_filename(name: str) -> int:
|
||||
"""Infer preset type from proto filename (printer/filament/print)."""
|
||||
n = name.lower()
|
||||
if "printer" in n:
|
||||
return meta_pb2.PRESET_PRINTER
|
||||
if "filament" in n:
|
||||
return meta_pb2.PRESET_FILAMENT
|
||||
return meta_pb2.PRESET_PRINT
|
||||
|
||||
def _parse_all_fields(self):
|
||||
"""Parse all message fields from all proto files in the descriptor set."""
|
||||
for file_desc in self.descriptor_set.file:
|
||||
# Skip google/protobuf imports
|
||||
if file_desc.name.startswith("google/"):
|
||||
continue
|
||||
# Skip config_metadata.proto (it's just extensions, no settings)
|
||||
if "config_metadata" in file_desc.name:
|
||||
continue
|
||||
|
||||
preset_type = self._preset_type_from_filename(file_desc.name)
|
||||
|
||||
for msg_desc in file_desc.message_type:
|
||||
# Skip wrapper messages (FloatOrPercent, Point2D)
|
||||
if msg_desc.name in ("FloatOrPercent", "Point2D"):
|
||||
continue
|
||||
|
||||
# Collect message-level virtual_preset_keys
|
||||
vkeys = list(msg_desc.options.Extensions[meta_pb2.virtual_preset_keys])
|
||||
self.virtual_keys_by_preset[preset_type].extend(vkeys)
|
||||
|
||||
for field_desc in msg_desc.field:
|
||||
self.fields.append(FieldInfo(field_desc))
|
||||
|
||||
def generate_init_fff_params(self) -> str:
|
||||
"""
|
||||
Generate the body of PrintConfigDef::init_fff_params().
|
||||
Output: C++ code that's a drop-in replacement for the hand-written registrations.
|
||||
"""
|
||||
lines = []
|
||||
lines.append("// ===== AUTO-GENERATED by tools/config_codegen.py =====")
|
||||
lines.append("// DO NOT EDIT MANUALLY. Edit .proto files and re-run codegen.")
|
||||
lines.append("")
|
||||
|
||||
for field in self.fields:
|
||||
lines.append(f' def = this->add("{field.name}", {field.co_type});')
|
||||
|
||||
if field.label:
|
||||
lines.append(f' def->label = L("{self._escape_cpp(field.label)}");')
|
||||
|
||||
if field.full_label:
|
||||
lines.append(f' def->full_label = L("{self._escape_cpp(field.full_label)}");')
|
||||
|
||||
if field.category:
|
||||
lines.append(f' def->category = L("{self._escape_cpp(field.category)}");')
|
||||
|
||||
if field.tooltip:
|
||||
tooltip_escaped = self._escape_cpp(field.tooltip)
|
||||
# Split long tooltips across lines
|
||||
if len(tooltip_escaped) > 80:
|
||||
lines.append(f' def->tooltip = L("{tooltip_escaped}");')
|
||||
else:
|
||||
lines.append(f' def->tooltip = L("{tooltip_escaped}");')
|
||||
|
||||
if field.sidetext:
|
||||
lines.append(f' def->sidetext = L("{self._escape_cpp(field.sidetext)}");')
|
||||
|
||||
if field.min_value is not None:
|
||||
lines.append(f' def->min = {self._format_number(field.min_value)};')
|
||||
|
||||
if field.max_value is not None:
|
||||
lines.append(f' def->max = {self._format_number(field.max_value)};')
|
||||
|
||||
if field.max_literal is not None:
|
||||
lines.append(f' def->max_literal = {self._format_number(field.max_literal)};')
|
||||
|
||||
if field.ratio_over:
|
||||
lines.append(f' def->ratio_over = "{field.ratio_over}";')
|
||||
|
||||
if field.has_mode:
|
||||
lines.append(f' def->mode = {mode_to_cpp(field.mode)};')
|
||||
|
||||
if field.is_nullable:
|
||||
lines.append(f' def->nullable = true;')
|
||||
|
||||
if field.readonly:
|
||||
lines.append(f' def->readonly = true;')
|
||||
|
||||
if field.multiline:
|
||||
lines.append(f' def->multiline = true;')
|
||||
|
||||
if field.full_width:
|
||||
lines.append(f' def->full_width = true;')
|
||||
|
||||
if field.height:
|
||||
lines.append(f' def->height = {field.height};')
|
||||
|
||||
if field.gui_type:
|
||||
lines.append(f' def->gui_type = ConfigOptionDef::GUIType::{field.gui_type};')
|
||||
|
||||
if field.gui_flags:
|
||||
lines.append(f' def->gui_flags = "{field.gui_flags}";')
|
||||
|
||||
if field.no_cli:
|
||||
lines.append(f' def->cli = ConfigOptionDef::nocli;')
|
||||
|
||||
if field.enum_keys_map:
|
||||
lines.append(f' def->enum_keys_map = &{field.enum_keys_map};')
|
||||
|
||||
# Enum values/labels
|
||||
for ev in field.enum_value_entries:
|
||||
lines.append(f' def->enum_values.push_back("{self._escape_cpp(ev)}");')
|
||||
for el in field.enum_label_entries:
|
||||
lines.append(f' def->enum_labels.push_back(L("{self._escape_cpp(el)}"));')
|
||||
|
||||
# Default value - reconstruct full C++ from co_type + default_value
|
||||
if field.has_default:
|
||||
cpp_expr = self._reconstruct_default_cpp(
|
||||
field.default_value or "", field.co_type, field.enum_keys_map,
|
||||
field.is_nullable)
|
||||
lines.append(f' def->set_default_value({cpp_expr});')
|
||||
|
||||
lines.append("")
|
||||
|
||||
return "\n".join(lines)
|
||||
|
||||
def generate_preset_options(self) -> str:
|
||||
"""Generate s_Preset_print_options, s_Preset_filament_options, etc."""
|
||||
lines = []
|
||||
lines.append("// ===== AUTO-GENERATED by tools/config_codegen.py =====")
|
||||
lines.append("")
|
||||
|
||||
for var_name, preset_type in [
|
||||
("s_Preset_print_options", meta_pb2.PRESET_PRINT),
|
||||
("s_Preset_filament_options", meta_pb2.PRESET_FILAMENT),
|
||||
("s_Preset_printer_options", meta_pb2.PRESET_PRINTER),
|
||||
]:
|
||||
# Field-derived keys + message-level virtual keys, deduplicated and sorted
|
||||
field_names = [f.name for f in self.fields if f.preset == preset_type]
|
||||
virtual_names = self.virtual_keys_by_preset[preset_type]
|
||||
all_names = sorted(set(field_names) | set(virtual_names))
|
||||
|
||||
lines.append(f"static const std::vector<std::string> {var_name} = {{")
|
||||
for name in all_names:
|
||||
lines.append(f' "{name}",')
|
||||
lines.append("};")
|
||||
lines.append("")
|
||||
|
||||
return "\n".join(lines)
|
||||
|
||||
def generate_invalidation_map(self) -> str:
|
||||
"""Generate opt_key -> invalidation steps mapping, split by PrintStep vs PrintObjectStep."""
|
||||
_init_step_sets()
|
||||
lines = []
|
||||
lines.append("// ===== AUTO-GENERATED by tools/config_codegen.py =====")
|
||||
lines.append("")
|
||||
|
||||
lines.append("static const std::unordered_map<std::string, std::vector<PrintStep>> "
|
||||
"s_print_steps_map = {")
|
||||
for field in sorted(self.fields, key=lambda x: x.name):
|
||||
if field.invalidates:
|
||||
steps = [step_to_cpp(s) for s in field.invalidates
|
||||
if s in _PRINT_STEPS and step_to_cpp(s)]
|
||||
if steps:
|
||||
lines.append(f' {{"{field.name}", {{{", ".join(steps)}}}}},')
|
||||
lines.append("};")
|
||||
lines.append("")
|
||||
|
||||
lines.append("static const std::unordered_map<std::string, std::vector<PrintObjectStep>> "
|
||||
"s_object_steps_map = {")
|
||||
for field in sorted(self.fields, key=lambda x: x.name):
|
||||
if field.invalidates:
|
||||
steps = [step_to_cpp(s) for s in field.invalidates
|
||||
if s in _OBJECT_STEPS and step_to_cpp(s)]
|
||||
if steps:
|
||||
lines.append(f' {{"{field.name}", {{{", ".join(steps)}}}}},')
|
||||
lines.append("};")
|
||||
|
||||
return "\n".join(lines)
|
||||
|
||||
def generate_option_key_lists(self) -> str:
|
||||
"""Generate extruder_option_keys, filament_option_keys, etc."""
|
||||
lines = []
|
||||
lines.append("// ===== AUTO-GENERATED by tools/config_codegen.py =====")
|
||||
lines.append("")
|
||||
|
||||
extruder_keys = [f for f in self.fields
|
||||
if meta_pb2.LIST_EXTRUDER_OPTION_KEYS in f.list_membership]
|
||||
filament_keys = [f for f in self.fields
|
||||
if meta_pb2.LIST_FILAMENT_OPTION_KEYS in f.list_membership]
|
||||
|
||||
for var_name, keys in [
|
||||
("s_extruder_option_keys", extruder_keys),
|
||||
("s_filament_option_keys", filament_keys),
|
||||
]:
|
||||
lines.append(f"static const std::vector<std::string> {var_name} = {{")
|
||||
for f in sorted(keys, key=lambda x: x.name):
|
||||
lines.append(f' "{f.name}",')
|
||||
lines.append("};")
|
||||
lines.append("")
|
||||
|
||||
return "\n".join(lines)
|
||||
|
||||
@staticmethod
|
||||
def _reconstruct_default_cpp(default_value, co_type, enum_keys_map=None, is_nullable=False):
|
||||
"""Reconstruct full C++ default expression from co_type + extracted value args.
|
||||
|
||||
Maps (co_type, args) -> 'new ConfigOptionXxx(args)' or 'new ConfigOptionXxx{args}'.
|
||||
"""
|
||||
import re as _re
|
||||
|
||||
# Type -> C++ class mappings
|
||||
SCALAR_CLASS = {
|
||||
"coFloat": "ConfigOptionFloat",
|
||||
"coBool": "ConfigOptionBool",
|
||||
"coInt": "ConfigOptionInt",
|
||||
"coString": "ConfigOptionString",
|
||||
"coPercent": "ConfigOptionPercent",
|
||||
"coFloatOrPercent": "ConfigOptionFloatOrPercent",
|
||||
"coPoint": "ConfigOptionPoint",
|
||||
"coPoint3": "ConfigOptionPoint3",
|
||||
}
|
||||
LIST_CLASS = {
|
||||
"coFloats": "ConfigOptionFloats",
|
||||
"coInts": "ConfigOptionInts",
|
||||
"coBools": "ConfigOptionBools",
|
||||
"coStrings": "ConfigOptionStrings",
|
||||
"coPercents": "ConfigOptionPercents",
|
||||
"coFloatsOrPercents": "ConfigOptionFloatsOrPercents",
|
||||
"coPoints": "ConfigOptionPoints",
|
||||
}
|
||||
|
||||
# Unescape escaped quotes, then re-escape actual newlines so they remain valid
|
||||
# in C++ string literals (proto \n is parsed as actual newline by protobuf).
|
||||
args = default_value.replace('\\"', '"').replace('\n', '\\n')
|
||||
|
||||
# Empty args -> default constructor for any type
|
||||
if not args:
|
||||
if co_type == "coEnum":
|
||||
enum_type = "int"
|
||||
if enum_keys_map:
|
||||
m = _re.match(r'ConfigOptionEnum<(\w+)>::', enum_keys_map)
|
||||
if m:
|
||||
enum_type = m.group(1)
|
||||
else:
|
||||
m2 = _re.match(r's_keys_map_(\w+)$', enum_keys_map)
|
||||
if m2:
|
||||
enum_type = m2.group(1)
|
||||
return f"new ConfigOptionEnum<{enum_type}>()"
|
||||
if co_type == "coEnums":
|
||||
cls = "ConfigOptionEnumsGenericNullable" if is_nullable else "ConfigOptionEnumsGeneric"
|
||||
return f"new {cls}{{}}"
|
||||
NULLABLE_LIST_CLASS = {
|
||||
"coFloats": "ConfigOptionFloatsNullable",
|
||||
"coInts": "ConfigOptionIntsNullable",
|
||||
"coBools": "ConfigOptionBoolsNullable",
|
||||
"coPercents": "ConfigOptionPercentsNullable",
|
||||
}
|
||||
all_classes = {**SCALAR_CLASS, **LIST_CLASS}
|
||||
if is_nullable and co_type in NULLABLE_LIST_CLASS:
|
||||
cls = NULLABLE_LIST_CLASS[co_type]
|
||||
else:
|
||||
cls = all_classes.get(co_type, "ConfigOption")
|
||||
return f"new {cls}()"
|
||||
|
||||
if co_type in SCALAR_CLASS:
|
||||
return f"new {SCALAR_CLASS[co_type]}({args})"
|
||||
|
||||
if co_type in LIST_CLASS:
|
||||
NULLABLE_LIST_CLASS = {
|
||||
"coFloats": "ConfigOptionFloatsNullable",
|
||||
"coInts": "ConfigOptionIntsNullable",
|
||||
"coBools": "ConfigOptionBoolsNullable",
|
||||
"coPercents": "ConfigOptionPercentsNullable",
|
||||
}
|
||||
cls = NULLABLE_LIST_CLASS[co_type] if (is_nullable and co_type in NULLABLE_LIST_CLASS) else LIST_CLASS[co_type]
|
||||
return f"new {cls}{{{args}}}"
|
||||
|
||||
if co_type == "coEnum":
|
||||
# Extract enum type from two possible enum_keys_map formats:
|
||||
# "ConfigOptionEnum<BedType>::get_enum_values()" -> "BedType"
|
||||
# "s_keys_map_BedType" -> "BedType"
|
||||
enum_type = "int"
|
||||
if enum_keys_map:
|
||||
m = _re.match(r'ConfigOptionEnum<(\w+)>::', enum_keys_map)
|
||||
if m:
|
||||
enum_type = m.group(1)
|
||||
else:
|
||||
m2 = _re.match(r's_keys_map_(\w+)$', enum_keys_map)
|
||||
if m2:
|
||||
enum_type = m2.group(1)
|
||||
return f"new ConfigOptionEnum<{enum_type}>({args})"
|
||||
|
||||
if co_type == "coEnums":
|
||||
cls = "ConfigOptionEnumsGenericNullable" if is_nullable else "ConfigOptionEnumsGeneric"
|
||||
return f"new {cls}{{ {args} }}"
|
||||
|
||||
# Fallback: try generic
|
||||
return f"new ConfigOption({args})"
|
||||
|
||||
@staticmethod
|
||||
def _escape_cpp(s):
|
||||
"""Escape a string for C++ string literal.
|
||||
|
||||
Proto strings already contain C++ escape sequences (\\n, \\", etc.)
|
||||
as literal backslash + char. We pass those through and only escape
|
||||
unescaped quotes and actual newlines.
|
||||
"""
|
||||
if not s:
|
||||
return ""
|
||||
# Replace actual newline characters (rare) with \n escape
|
||||
s = s.replace('\n', '\\n')
|
||||
# Don't double-escape backslashes that are already part of escape sequences.
|
||||
# The proto strings store them as literal \n, \", \t etc.
|
||||
return s
|
||||
|
||||
@staticmethod
|
||||
def _format_number(val):
|
||||
"""Format a number for C++ (int vs float)."""
|
||||
if val is None:
|
||||
return "0"
|
||||
if isinstance(val, float) and val == int(val):
|
||||
return str(int(val))
|
||||
return str(val)
|
||||
|
||||
|
||||
def _group_name_to_hook(name):
|
||||
"""Convert group name to a C++ hook method suffix: 'Cooling Fan' -> 'cooling_fan'."""
|
||||
return re.sub(r'[^a-z0-9]+', '_', name.lower()).strip('_')
|
||||
|
||||
|
||||
def _extract_field_paths(tab_layout_cpp):
|
||||
"""
|
||||
Read existing TabLayout_generated.cpp to build a field -> doc-path lookup.
|
||||
Used as a bootstrap so the yaml doesn't need to repeat every path.
|
||||
Returns dict: field_key -> path_string
|
||||
"""
|
||||
mapping = {}
|
||||
if not Path(tab_layout_cpp).exists():
|
||||
return mapping
|
||||
with open(tab_layout_cpp, 'r', encoding='utf-8', errors='replace') as f:
|
||||
content = f.read()
|
||||
for key, path in re.findall(
|
||||
r'append_single_option_line\("([^"]+)",\s*"([^"]+)"\)', content):
|
||||
mapping[key] = path
|
||||
return mapping
|
||||
|
||||
|
||||
def generate_tab_layout(layout_yaml_path, output_path, existing_cpp_path=None):
|
||||
"""
|
||||
Generate TabLayout_generated.cpp from layout.yaml.
|
||||
|
||||
YAML group fields can be:
|
||||
- key string → append_single_option_line(key, <lookup>)
|
||||
- {key: "path"} dict → append_single_option_line(key, "path")
|
||||
- [k1, k2, ...] list → multi-option Line
|
||||
- _separator_ string → optgroup->append_separator()
|
||||
|
||||
Group attributes:
|
||||
hook: true → tab.layout_hook_<name>(optgroup.get()) (no field generation)
|
||||
gcode: true → validate_custom_gcode_cb + edit_custom_gcode lambdas + gcode fields
|
||||
icon: "..." → second arg to new_optgroup()
|
||||
"""
|
||||
try:
|
||||
import yaml
|
||||
except ImportError:
|
||||
print(" ERROR: PyYAML not installed. Run: pip install pyyaml")
|
||||
return False
|
||||
|
||||
with open(layout_yaml_path, 'r', encoding='utf-8') as f:
|
||||
layout = yaml.safe_load(f)
|
||||
|
||||
# Bootstrap: extract existing field→path mappings so yaml doesn't need them all
|
||||
path_map = _extract_field_paths(existing_cpp_path) if existing_cpp_path else {}
|
||||
|
||||
lines = [
|
||||
"// ===== AUTO-GENERATED by tools/config_codegen.py from layout.yaml =====",
|
||||
"// DO NOT EDIT MANUALLY. Edit layout.yaml and re-run: python tools/run_codegen.py",
|
||||
"//",
|
||||
"// Included inside namespace Slic3r::GUI in Tab.cpp after validate_custom_gcode_cb",
|
||||
"// forward declaration. No namespace wrapper needed here.",
|
||||
"",
|
||||
"namespace { constexpr int gcode_field_height = 15; }",
|
||||
"namespace { constexpr int notes_field_height = 25; }",
|
||||
"",
|
||||
]
|
||||
|
||||
for tab in layout.get('tabs', []):
|
||||
tab_name = tab['name'] # e.g. TabPrint, TabFilament, TabPrinter
|
||||
pages = tab.get('pages', [])
|
||||
if not pages:
|
||||
continue
|
||||
|
||||
# One inline function per page (or per tab if single page makes sense)
|
||||
# Convention: TabPrint_build_layout, TabFilament_build_main_layout,
|
||||
# TabPrinter_build_basic_info_layout, TabPrinter_build_gcode_layout, etc.
|
||||
for page in pages:
|
||||
page_name = page['name']
|
||||
page_icon = page.get('icon', '')
|
||||
# Derive function name: TabPrint/"Quality" → TabPrint_build_quality_layout
|
||||
fn_suffix = _group_name_to_hook(page_name)
|
||||
fn_name = f"{tab_name}_build_{fn_suffix}_layout"
|
||||
|
||||
lines.append(f"inline void {fn_name}({tab_name}& tab)")
|
||||
lines.append("{")
|
||||
lines.append(f" PageShp page = tab.add_options_page(L(\"{page_name}\"), \"{page_icon}\");")
|
||||
|
||||
for group in page.get('groups', []):
|
||||
gname = group['name']
|
||||
gicon = group.get('icon', '')
|
||||
is_hook = group.get('hook', False)
|
||||
is_gcode = group.get('gcode', False)
|
||||
fields = group.get('fields', [])
|
||||
indent_n = group.get('indent', 15)
|
||||
|
||||
icon_arg = f', L"{gicon}"' if gicon else ''
|
||||
indent_arg = f', {indent_n}' if (is_gcode and indent_n != 15) else ''
|
||||
if is_gcode:
|
||||
icon_arg = f', L"{gicon}"' if gicon else ', L"param_gcode"'
|
||||
indent_arg = ', 0'
|
||||
|
||||
lines.append(" {")
|
||||
lines.append(f" auto optgroup = page->new_optgroup(L(\"{gname}\"){icon_arg}{indent_arg});")
|
||||
|
||||
if is_hook:
|
||||
hook_method = f"layout_hook_{_group_name_to_hook(gname)}"
|
||||
lines.append(f" tab.{hook_method}(optgroup.get());")
|
||||
|
||||
elif is_gcode:
|
||||
# Standard g-code group: validate callback + edit button + gcode fields
|
||||
lines.append(" optgroup->m_on_change = [&tab, &optgroup_title = optgroup->title](const t_config_option_key& opt_key, const boost::any& value) {")
|
||||
lines.append(" validate_custom_gcode_cb(&tab, optgroup_title, opt_key, value);")
|
||||
lines.append(" };")
|
||||
lines.append(" optgroup->edit_custom_gcode = [&tab](const t_config_option_key& opt_key) { tab.edit_custom_gcode(opt_key); };")
|
||||
for field in fields:
|
||||
key, path = _resolve_field(field, path_map)
|
||||
if key:
|
||||
path_arg = f', "{path}"' if path else ''
|
||||
lines.append(" {")
|
||||
lines.append(f" Option option = optgroup->get_option(\"{key}\");")
|
||||
lines.append(" option.opt.full_width = true;")
|
||||
lines.append(" option.opt.is_code = true;")
|
||||
lines.append(" option.opt.height = gcode_field_height;")
|
||||
lines.append(f" optgroup->append_single_option_line(option{path_arg});")
|
||||
lines.append(" }")
|
||||
|
||||
else:
|
||||
# Regular group: generate append_single_option_line / multi-option line
|
||||
for field in fields:
|
||||
if isinstance(field, list):
|
||||
# Multi-option line: [key1, key2, ...]
|
||||
lines.append(" {")
|
||||
first = field[0]
|
||||
lines.append(f" Line line_{{optgroup->get_option(\"{first}\").opt.label, optgroup->get_option(\"{first}\").opt.tooltip}};")
|
||||
for k in field:
|
||||
lines.append(f" line_.append_option(optgroup->get_option(\"{k}\"));")
|
||||
lines.append(" optgroup->append_line(line_);")
|
||||
lines.append(" }")
|
||||
elif isinstance(field, str):
|
||||
if field == '_separator_':
|
||||
lines.append(" optgroup->append_separator();")
|
||||
else:
|
||||
path = path_map.get(field, '')
|
||||
path_arg = f', "{path}"' if path else ''
|
||||
lines.append(f" optgroup->append_single_option_line(\"{field}\"{path_arg});")
|
||||
elif isinstance(field, dict):
|
||||
# {key: path} explicit path
|
||||
for key, path in field.items():
|
||||
path_arg = f', "{path}"' if path else ''
|
||||
lines.append(f" optgroup->append_single_option_line(\"{key}\"{path_arg});")
|
||||
|
||||
lines.append(" }")
|
||||
|
||||
lines.append("}")
|
||||
lines.append("")
|
||||
|
||||
# Add backward-compatible wrapper functions that aggregate per-page functions
|
||||
# so Tab.cpp can call e.g. TabPrint_build_layout(*this) as before.
|
||||
wrappers = _build_wrappers(layout)
|
||||
lines.extend(wrappers)
|
||||
|
||||
content = "\n".join(lines) + "\n"
|
||||
output_dir = Path(output_path).parent
|
||||
output_dir.mkdir(parents=True, exist_ok=True)
|
||||
with open(output_path, 'w', encoding='utf-8') as f:
|
||||
f.write(content)
|
||||
print(f"Generated: {output_path}")
|
||||
return True
|
||||
|
||||
|
||||
def _build_wrappers(layout):
|
||||
"""Generate aggregate wrapper functions for backward compatibility with Tab.cpp."""
|
||||
lines = ["// ── Aggregate wrappers (backward-compatible with Tab.cpp call sites) ──", ""]
|
||||
|
||||
# Known wrappers: map from legacy function name → (tab_type, [page_names_to_include])
|
||||
# The tab_name and page_names determine which per-page functions get called.
|
||||
wrapper_specs = {
|
||||
"TabPrint": ("TabPrint_build_layout", None), # all pages
|
||||
"TabFilament": ("TabFilament_build_main_layout", ["Filament", "Cooling", "Multimaterial"]),
|
||||
}
|
||||
|
||||
for tab in layout.get('tabs', []):
|
||||
tab_name = tab['name']
|
||||
pages = tab.get('pages', [])
|
||||
|
||||
if tab_name == "TabPrinter":
|
||||
# Per-page wrappers for printer tab
|
||||
basic_info = [p for p in pages if p['name'] == "Basic information"]
|
||||
gcode_pages = [p for p in pages if p['name'] in ("Machine G-code", "Notes")]
|
||||
|
||||
if basic_info:
|
||||
fn = f"TabPrinter_build_basic_info_layout"
|
||||
lines.append(f"inline void {fn}(TabPrinter& tab)")
|
||||
lines.append("{")
|
||||
for p in basic_info:
|
||||
pf = f"TabPrinter_build_{_group_name_to_hook(p['name'])}_layout"
|
||||
lines.append(f" {pf}(tab);")
|
||||
lines.append("}")
|
||||
lines.append("")
|
||||
|
||||
if gcode_pages:
|
||||
fn = "TabPrinter_build_gcode_layout"
|
||||
lines.append(f"inline void {fn}(TabPrinter& tab)")
|
||||
lines.append("{")
|
||||
for p in gcode_pages:
|
||||
pf = f"TabPrinter_build_{_group_name_to_hook(p['name'])}_layout"
|
||||
lines.append(f" {pf}(tab);")
|
||||
lines.append("}")
|
||||
lines.append("")
|
||||
|
||||
elif tab_name in wrapper_specs:
|
||||
legacy_fn, page_filter = wrapper_specs[tab_name]
|
||||
filtered = [p for p in pages if page_filter is None or p['name'] in page_filter]
|
||||
if not filtered:
|
||||
continue
|
||||
lines.append(f"inline void {legacy_fn}({tab_name}& tab)")
|
||||
lines.append("{")
|
||||
for p in filtered:
|
||||
pf = f"{tab_name}_build_{_group_name_to_hook(p['name'])}_layout"
|
||||
lines.append(f" {pf}(tab);")
|
||||
lines.append("}")
|
||||
lines.append("")
|
||||
|
||||
return lines
|
||||
|
||||
|
||||
def _resolve_field(field, path_map):
|
||||
"""Return (key, path) from a field entry in various yaml formats."""
|
||||
if isinstance(field, str):
|
||||
return field, path_map.get(field, '')
|
||||
elif isinstance(field, dict):
|
||||
for k, v in field.items():
|
||||
return k, (v or path_map.get(k, ''))
|
||||
return None, ''
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Generate C++ config code from protobuf descriptors")
|
||||
parser.add_argument("descriptor_set",
|
||||
help="Path to compiled .desc file (protoc --descriptor_set_out)")
|
||||
parser.add_argument("output_dir",
|
||||
help="Directory to write generated C++ files")
|
||||
args = parser.parse_args()
|
||||
|
||||
# Read descriptor set
|
||||
desc_path = Path(args.descriptor_set)
|
||||
if not desc_path.exists():
|
||||
print(f"ERROR: Descriptor file not found: {desc_path}")
|
||||
sys.exit(1)
|
||||
|
||||
with open(desc_path, 'rb') as f:
|
||||
raw = f.read()
|
||||
|
||||
file_descriptor_set = descriptor_pb2.FileDescriptorSet()
|
||||
file_descriptor_set.ParseFromString(raw)
|
||||
|
||||
print(f"Loaded {len(file_descriptor_set.file)} proto files")
|
||||
for fd in file_descriptor_set.file:
|
||||
if not fd.name.startswith("google/"):
|
||||
print(f" - {fd.name}: {len(fd.message_type)} messages")
|
||||
|
||||
# Generate code
|
||||
gen = CodeGenerator(file_descriptor_set)
|
||||
|
||||
output_dir = Path(args.output_dir)
|
||||
output_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
outputs = {
|
||||
"PrintConfigDef_generated.cpp": gen.generate_init_fff_params(),
|
||||
"Preset_options_generated.cpp": gen.generate_preset_options(),
|
||||
"Invalidation_generated.cpp": gen.generate_invalidation_map(),
|
||||
"OptionKeys_generated.cpp": gen.generate_option_key_lists(),
|
||||
}
|
||||
|
||||
for filename, content in outputs.items():
|
||||
out_path = output_dir / filename
|
||||
with open(out_path, 'w', encoding='utf-8') as f:
|
||||
f.write(content)
|
||||
print(f"Generated: {out_path}")
|
||||
|
||||
print(f"\nDone. {len(gen.fields)} settings processed.")
|
||||
|
||||
# Generate tab layout from layout.yaml
|
||||
layout_yaml = desc_path.parent.parent / "src" / "PrintConfigs" / "layout.yaml"
|
||||
if not layout_yaml.exists():
|
||||
# Try repo root relative path
|
||||
layout_yaml = Path(__file__).resolve().parent.parent / "src" / "PrintConfigs" / "layout.yaml"
|
||||
if layout_yaml.exists():
|
||||
tab_layout_out = output_dir / "TabLayout_generated.cpp"
|
||||
existing = tab_layout_out if tab_layout_out.exists() else None
|
||||
generate_tab_layout(str(layout_yaml), str(tab_layout_out), str(existing) if existing else None)
|
||||
else:
|
||||
print(f" NOTE: layout.yaml not found at {layout_yaml}, skipping tab layout generation")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
47
tools/config_metadata_pb2.py
Normal file
47
tools/config_metadata_pb2.py
Normal file
@@ -0,0 +1,47 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
# NO CHECKED-IN PROTOBUF GENCODE
|
||||
# source: config_metadata.proto
|
||||
# Protobuf Python Version: 6.32.1
|
||||
"""Generated protocol buffer code."""
|
||||
from google.protobuf import descriptor as _descriptor
|
||||
from google.protobuf import descriptor_pool as _descriptor_pool
|
||||
from google.protobuf import runtime_version as _runtime_version
|
||||
from google.protobuf import symbol_database as _symbol_database
|
||||
from google.protobuf.internal import builder as _builder
|
||||
_runtime_version.ValidateProtobufRuntimeVersion(
|
||||
_runtime_version.Domain.PUBLIC,
|
||||
6,
|
||||
32,
|
||||
1,
|
||||
'',
|
||||
'config_metadata.proto'
|
||||
)
|
||||
# @@protoc_insertion_point(imports)
|
||||
|
||||
_sym_db = _symbol_database.Default()
|
||||
|
||||
|
||||
from google.protobuf import descriptor_pb2 as google_dot_protobuf_dot_descriptor__pb2
|
||||
|
||||
|
||||
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15\x63onfig_metadata.proto\x12\x04orca\x1a google/protobuf/descriptor.proto\"0\n\x0e\x46loatOrPercent\x12\r\n\x05value\x18\x01 \x01(\x01\x12\x0f\n\x07percent\x18\x02 \x01(\x08\"\x1f\n\x07Point2D\x12\t\n\x01x\x18\x01 \x01(\x01\x12\t\n\x01y\x18\x02 \x01(\x01*B\n\nConfigMode\x12\x0f\n\x0bMODE_SIMPLE\x10\x00\x12\x11\n\rMODE_ADVANCED\x10\x01\x12\x10\n\x0cMODE_DEVELOP\x10\x02*G\n\nPresetType\x12\x10\n\x0cPRESET_PRINT\x10\x00\x12\x13\n\x0fPRESET_FILAMENT\x10\x01\x12\x12\n\x0ePRESET_PRINTER\x10\x02*\xaa\x01\n\x10InvalidationStep\x12\x15\n\x11STEP_GCODE_EXPORT\x10\x00\x12\x13\n\x0fSTEP_SKIRT_BRIM\x10\x01\x12\x13\n\x0fSTEP_WIPE_TOWER\x10\x02\x12\x0e\n\nSTEP_SLICE\x10\x03\x12\x13\n\x0fSTEP_PERIMETERS\x10\x04\x12\x0f\n\x0bSTEP_INFILL\x10\x05\x12\x10\n\x0cSTEP_SUPPORT\x10\x06\x12\r\n\tSTEP_NONE\x10\x07*\x81\x01\n\x14OptionListMembership\x12\r\n\tLIST_NONE\x10\x00\x12\x1d\n\x19LIST_EXTRUDER_OPTION_KEYS\x10\x01\x12\x1d\n\x19LIST_FILAMENT_OPTION_KEYS\x10\x02\x12\x1c\n\x18LIST_VARIANT_OPTION_KEYS\x10\x03:.\n\x05label\x12\x1d.google.protobuf.FieldOptions\x18\xd1\x86\x03 \x01(\t:3\n\nfull_label\x12\x1d.google.protobuf.FieldOptions\x18\xd2\x86\x03 \x01(\t:0\n\x07tooltip\x12\x1d.google.protobuf.FieldOptions\x18\xd3\x86\x03 \x01(\t:1\n\x08\x63\x61tegory\x12\x1d.google.protobuf.FieldOptions\x18\xd4\x86\x03 \x01(\t:1\n\x08sidetext\x12\x1d.google.protobuf.FieldOptions\x18\xd5\x86\x03 \x01(\t:2\n\tmin_value\x12\x1d.google.protobuf.FieldOptions\x18\xd6\x86\x03 \x01(\x01:2\n\tmax_value\x12\x1d.google.protobuf.FieldOptions\x18\xd7\x86\x03 \x01(\x01:4\n\x0bmax_literal\x12\x1d.google.protobuf.FieldOptions\x18\xd8\x86\x03 \x01(\x01:?\n\x04mode\x12\x1d.google.protobuf.FieldOptions\x18\xd9\x86\x03 \x01(\x0e\x32\x10.orca.ConfigMode:3\n\nratio_over\x12\x1d.google.protobuf.FieldOptions\x18\xda\x86\x03 \x01(\t:2\n\tmultiline\x12\x1d.google.protobuf.FieldOptions\x18\xdd\x86\x03 \x01(\x08:3\n\nfull_width\x12\x1d.google.protobuf.FieldOptions\x18\xde\x86\x03 \x01(\x08:/\n\x06height\x12\x1d.google.protobuf.FieldOptions\x18\xdf\x86\x03 \x01(\x05:A\n\x06preset\x12\x1d.google.protobuf.FieldOptions\x18\xdb\x86\x03 \x01(\x0e\x32\x10.orca.PresetType:L\n\x0binvalidates\x12\x1d.google.protobuf.FieldOptions\x18\xdc\x86\x03 \x03(\x0e\x32\x16.orca.InvalidationStep:T\n\x0flist_membership\x12\x1d.google.protobuf.FieldOptions\x18\xe2\x86\x03 \x03(\x0e\x32\x1a.orca.OptionListMembership:4\n\x0blegacy_name\x12\x1d.google.protobuf.FieldOptions\x18\xe0\x86\x03 \x01(\t:4\n\x0bis_nullable\x12\x1d.google.protobuf.FieldOptions\x18\xe1\x86\x03 \x01(\x08:1\n\x08gui_type\x12\x1d.google.protobuf.FieldOptions\x18\xe3\x86\x03 \x01(\t:2\n\tgui_flags\x12\x1d.google.protobuf.FieldOptions\x18\xe4\x86\x03 \x01(\t::\n\x11\x65num_keys_map_ref\x12\x1d.google.protobuf.FieldOptions\x18\xe5\x86\x03 \x01(\t:/\n\x06no_cli\x12\x1d.google.protobuf.FieldOptions\x18\xe6\x86\x03 \x01(\x08:1\n\x08readonly\x12\x1d.google.protobuf.FieldOptions\x18\xe7\x86\x03 \x01(\x08:5\n\x0c\x63o_type_hint\x12\x1d.google.protobuf.FieldOptions\x18\xe8\x86\x03 \x01(\t:6\n\rdefault_value\x12\x1d.google.protobuf.FieldOptions\x18\xe9\x86\x03 \x01(\t:4\n\x0bhas_default\x12\x1d.google.protobuf.FieldOptions\x18\xec\x86\x03 \x01(\x08:;\n\x12\x65num_value_entries\x12\x1d.google.protobuf.FieldOptions\x18\xea\x86\x03 \x03(\t:;\n\x12\x65num_label_entries\x12\x1d.google.protobuf.FieldOptions\x18\xeb\x86\x03 \x03(\t:1\n\x08tab_type\x12\x1d.google.protobuf.FieldOptions\x18\xed\x86\x03 \x01(\t:1\n\x08tab_page\x12\x1d.google.protobuf.FieldOptions\x18\xee\x86\x03 \x01(\t:5\n\x0ctab_optgroup\x12\x1d.google.protobuf.FieldOptions\x18\xef\x86\x03 \x01(\t:>\n\x13virtual_preset_keys\x12\x1f.google.protobuf.MessageOptions\x18\xe1\xd4\x03 \x03(\tb\x06proto3')
|
||||
|
||||
_globals = globals()
|
||||
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
||||
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'config_metadata_pb2', _globals)
|
||||
if not _descriptor._USE_C_DESCRIPTORS:
|
||||
DESCRIPTOR._loaded_options = None
|
||||
_globals['_CONFIGMODE']._serialized_start=148
|
||||
_globals['_CONFIGMODE']._serialized_end=214
|
||||
_globals['_PRESETTYPE']._serialized_start=216
|
||||
_globals['_PRESETTYPE']._serialized_end=287
|
||||
_globals['_INVALIDATIONSTEP']._serialized_start=290
|
||||
_globals['_INVALIDATIONSTEP']._serialized_end=460
|
||||
_globals['_OPTIONLISTMEMBERSHIP']._serialized_start=463
|
||||
_globals['_OPTIONLISTMEMBERSHIP']._serialized_end=592
|
||||
_globals['_FLOATORPERCENT']._serialized_start=65
|
||||
_globals['_FLOATORPERCENT']._serialized_end=113
|
||||
_globals['_POINT2D']._serialized_start=115
|
||||
_globals['_POINT2D']._serialized_end=146
|
||||
# @@protoc_insertion_point(module_scope)
|
||||
120
tools/run_codegen.py
Normal file
120
tools/run_codegen.py
Normal file
@@ -0,0 +1,120 @@
|
||||
#!/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
|
||||
|
||||
Usage:
|
||||
python tools/run_codegen.py # full pipeline
|
||||
python tools/run_codegen.py --validate-only # just validate
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
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 _ensure_pyyaml():
|
||||
"""Install pyyaml if not present — needed for tab layout generation."""
|
||||
try:
|
||||
import yaml # noqa: F401
|
||||
return True
|
||||
except ImportError:
|
||||
print(" Installing pyyaml (required for tab layout generation)...")
|
||||
result = subprocess.run(
|
||||
[sys.executable, "-m", "pip", "install", "pyyaml", "-q"],
|
||||
capture_output=True)
|
||||
if result.returncode != 0:
|
||||
print(" ERROR: failed to install pyyaml")
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
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 _protoc_cmd():
|
||||
"""Return the protoc command list. Prefers standalone protoc, falls back to grpc_tools."""
|
||||
if shutil.which("protoc"):
|
||||
return ["protoc"]
|
||||
try:
|
||||
import grpc_tools.protoc # noqa: F401
|
||||
return [sys.executable, "-m", "grpc_tools.protoc"]
|
||||
except ImportError:
|
||||
pass
|
||||
print(" ERROR: protoc not found. Install protoc or run: pip install grpcio-tools")
|
||||
return None
|
||||
|
||||
|
||||
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 = _protoc_cmd()
|
||||
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 ===")
|
||||
_ensure_pyyaml() # tab layout generation requires pyyaml
|
||||
return run([sys.executable, str(ROOT / "tools" / "config_codegen.py"),
|
||||
str(DESC_FILE), str(CODEGEN_OUT)])
|
||||
|
||||
|
||||
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()
|
||||
|
||||
if args.validate_only:
|
||||
sys.exit(0 if 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