Compare commits

...
Author SHA1 Message Date
Lam Wei Lun 0ee529e283 Fixes missing Plugins category for installed plugins 2026-09-24 15:25:11 +08:00
Lam Wei Lun 7ae76e44b1 Merge branch 'main' into feat/speed-dial-fixes 2026-09-24 10:42:19 +08:00
Lam Wei Lun 54c32a54b4 Change some search actions and results text. Force repaint for when resizing and show happens 2026-09-24 10:41:55 +08:00
Valerii Bokhan 037b859447 Fix: Correct camera panning for the perspective view (#15212) 2026-09-23 20:38:26 -03:00
Ian BassiandRodrigo Faselli 02746cd0f5 Disable SSAO for grid (#15865)
Co-authored-by: Rodrigo Faselli <162915171+RF47@users.noreply.github.com>
2026-09-23 20:38:04 -03:00
Kris Austin 66b300987b feat: faster startup by lazy-loading main window panels on idle or first use (#15811) 2026-09-23 19:11:10 -03:00
Kris Austin 9bae19fcb3 fix: the 3D scene is drawn in the wrong view for the first half second of startup (#15830) 2026-09-23 18:21:16 -03:00
Lam Wei Lun fcd8131998 WebGuide's Filament Dialog Fix to ensure filaments inheritance chain is checked properly (#15855)
* fix: resolve filament vendor/type across split base presets

WebGuide's filament list dropped presets whose vendor and type came from different ancestors, and looped forever on inherits cycles. Walk the full inherits chain with a path-scoped guard, fill only missing values, and skip presets that still lack vendor or type. Add tests for split-base resolution and validate the real profile tree.

* Merge branch 'main' into feat/filament_dialog_fix

* Fixes unit test

* Merge branch 'main' into feat/filament_dialog_fix

* Merge branch 'main' into feat/filament_dialog_fix

* revert tests/fff_print/test_gcodewriter.cpp changes
2026-09-23 20:23:52 +08:00
a8f1061a02 Add Sovol Zero nozzle profiles and filament profiles (#15756)
* Add Sovol Zero nozzle profiles and filament updates

Preserve inherited tuning with Zero-only overrides so shared
Sovol defaults and other printers remain unchanged. Retain migration
aliases while using canonical names in compatibility references.

Co-authored-by: Codex <noreply@openai.com>

* Fix Sovol Zero bed model reference and ignored settings

Point the Zero model at the shipped bed mesh. Remove unsupported filament
and process keys that the loader silently discards, preserving effective
tuning and the existing preset names and IDs. Bump the Sovol bundle version.

Co-authored-by: Codex <noreply@openai.com>

* Fix Sovol Zero filament identity and vector formatting

Add hardened-steel nozzle variants with disjoint filament compatibility, retain generic product IDs and preserve renamed preset aliases. Convert 43 scalar vector fields to arrays without changing tuning values and bump the Sovol bundle version.

Co-authored-by: Codex <codex@openai.com>

* Keep only shipped names in the Sovol Zero profile renames

The Zero machines, processes, machine model and SPEEDBENCHY filament carried renamed_from entries for names that only ever existed inside this branch (Sovol ZERO ..., " - Brass", " - Hardened Steel"). Drop those, and keep only the redirects that matter to existing users: the historical Sovol Zero material names and the three deleted hardened-steel presets. The Sovol Zero machine model also sheds the setting_id, instantiation and from keys the model loader ignores.

---------

Co-authored-by: Codex <noreply@openai.com>
Co-authored-by: SoftFever <103989404+SoftFever@users.noreply.github.com>
Co-authored-by: Codex <codex@openai.com>
Co-authored-by: SoftFever <softfeverever@gmail.com>
2026-09-23 20:05:01 +08:00
SoftFever b46916a8be Revert "Sync Bambu Lab profiles with BambuStudio"
This reverts commit cc883e458d.
2026-09-23 18:19:23 +08:00
SoftFever bf024ed34e Revert "Restore the Bambu Lab bed-model offset so stock BambuStudio meshes line up"
This reverts commit 7758332406.
2026-09-23 18:19:03 +08:00
Sylvain 0211277976 Add Wanhao Duplicator 9 profiles (D9/300, D9/400, D9/500) (#15773) 2026-09-23 17:24:17 +08:00
SoftFever 7758332406 Restore the Bambu Lab bed-model offset so stock BambuStudio meshes line up 2026-09-23 14:58:41 +08:00
SoftFever cc883e458d Sync Bambu Lab profiles with BambuStudio
Polymaker, Overture and eSUN presets move from brand subfolders to
BBL/filament/, matching BambuStudio's layout; their names and ids are
unchanged. Default filament lists keep pointing at presets that exist,
0.2 mm nozzles keep a default PLA, and user presets based on removed or
renamed presets still load. Generic SBS is no longer in the Bambu bundle;
new selections on those printers fall back to OrcaFilamentLibrary's
Generic SBS @System. The profile tool now recognises BambuStudio's new
filament id/name maps and support_recommended_params.json as data files.
2026-09-23 14:58:41 +08:00
145 changed files with 5825 additions and 1094 deletions
+220
View File
@@ -0,0 +1,220 @@
# Deferred Page Construction: High Level Design
## Why it exists
The main window is a notebook of tabs. When the first frame appears, one tab is on
screen and the others are not; some of them are opened later in the session, some
never, and some only exist for certain printers. Building a tab before the first frame
adds its cost to every startup, whether or not the tab is used.
This subsystem builds a tab's panel the first time the tab is shown. It also builds the
remaining tabs while the user is idle after startup, in units of tens of milliseconds,
so a click that lands in the middle of one waits for that unit and no longer. Startup
pays only for what the first frame shows, and the other tabs are usually built before
anyone opens them.
## The parts
`src/slic3r/GUI/Lazy.hpp`, `LazyPage.hpp`, `StagedBuild.hpp` and `IdleScheduler.hpp/.cpp`
(with its wx-free `PrebuildQueue.hpp`) are independent. A holder can hold anything a
factory makes, a page is a holder with a placeholder widget, a staged object can live
outside a holder, and the scheduler knows none of them; it runs tasks, which `MainFrame`
makes from the holders.
### Lazy<T>: the holder
Holds an object that a factory makes on first use, under a name for the log and a place
in the idle queue, both given by the owner. The header has no wx dependency; the busy
cursor for an on-demand build lives in `Lazy.cpp` and is skipped when there is no app,
so the holder is unit-tested.
- `get()` is null until the object is completely built; `built()` says the same.
- `ensure()` builds whatever is left now, under a busy cursor, and returns the object, or
null in the two cases below. A click on an unbuilt tab or a first open of a dialog goes
through this, and it logs the units and time it took.
- `build_step()` runs one unit of construction and returns true while more remain. The
first unit is the factory call, and each later unit is one `StagedBuild` step if the
type has them.
- `when_built(fn)` runs `fn(object)` now if it exists, otherwise once it is built.
- `pending()` says whether the idle prebuild has work here: not built, and the factory
has not returned null. A null factory result is logged and the holder stays unbuilt.
- A unit that pumps the event loop cannot re-enter the holder; a nested `build_step()`
does nothing and a nested `ensure()` returns null.
- After a unit throws, the holder and the scheduler still run the next one.
The holder does not own the object; its wx parent does, as for any window. A type with
one instance in the app derives from `LazyInstance<T>`, which points at that instance's
holder (the holder registers itself, and a recreated `MainFrame`'s holder replaces the
old frame's) and gives the type the static entry points the rest of the app uses,
`T::if_built()`, `T::ensure()` and `T::when_built(fn)`. They return null, or do
nothing, while no holder exists, so a caller needs no `mainframe` check.
`built()` is an atomic flag, since a job worker reads it through the statics
(`MainFrame::get_calibration_curr_tab()`); it is set after the object is complete.
`LazyBase` is the holder's type-free interface (`name()`, `built()`, `pending()`,
`build_step()`, `prebuild_order()`) and is what the scheduler side sees.
### LazyPage<Panel>: the placeholder
A `wxPanel` placed in the parent in place of the real panel, and a `Lazy<Panel>` whose
factory makes the panel inside it (by default `new Panel(parent)`). The notebook needs a
page object for the tab to exist and for `show_device()` to insert and remove tabs by
pointer, and the placeholder is that object. `MainFrame` creates every page once, named
after its `TAB_ID_*`, and keeps it for the frame's life; `show_device()` only moves
pages in and out of the book.
- `Show()` is forwarded to the panel, so a panel's own `Show()` override stays its
activation hook (refresh timers, machine sync) and `SelectPageByName()` works
unchanged. A show builds the panel unless the frame itself is still hidden, because
the book selects its first page as it is inserted; `MainFrame::Show()` shows the
current page again when the frame becomes visible, which builds it.
- `in_book()` says whether the parent notebook currently lists the page, and
`pending()` is that and not built, so a tab `show_device()` has taken out of the book
is not prebuilt.
- A panel built while its page is hidden stays hidden, and a completed panel gets the
dark-mode pass the frame ran before it existed.
The Compare presets dialog is a holder without a page. `MainFrame` keeps a
`Lazy<DiffPresetDialog>` whose factory constructs the dialog and binds its events, the
dialog derives from `LazyInstance`, and its callers use
`DiffPresetDialog::ensure()->show()` and `DiffPresetDialog::if_built()` like a tab's
callers do. Saving a preset refreshes the dialog only while it is shown, since `show()`
reloads the presets.
### StagedBuild: construction in units
A mixin for a panel whose constructor is too big to be one unit. The constructor builds
the skeleton (sizers, and the parts other code may touch) and queues the rest with
`add_build_step()`. `build_step()` runs one step, and `add_build_steps_of(child)`
forwards a child's steps so a nested panel is spread the same way; the parent is built
only once the child is, including steps the child queues later. Steps run in order, on
the main thread. A `Lazy<T>` recognises a staged type at compile time and runs its steps
one per unit.
Nothing may touch what a step builds before the last step has run. In practice:
- nothing paints the panel before it is complete, since a panel built at idle is hidden
with its page and one built on demand finishes inside `ensure()` before the event loop
runs again;
- members created in steps are initialised to null in the header, so a partially built
panel can be destroyed;
- timers and event handlers that use step content check `built()` first
(`MonitorPanel::update_all()`, `CalibrationPanel::update_all()`), and a child's steps
are queued before anything in the constructor can fire such a handler;
- a destructor that disconnects from step content checks `built()` first;
- a constructor or step does not take focus while the panel is off screen
(`IsShownOnScreen()` before `SetFocus()`), since it may run while the user is typing
elsewhere;
- where a step's widgets must keep their place in a sizer that later steps also fill, the
constructor adds an empty slot sizer in that position and the step fills the slot
(`StatusBasePanel`).
### IdleScheduler: when to build
A task is any `LazyBase`: a name for the log, `pending()`, `build_step()` and
`prebuild_order()`. `PrebuildQueue` holds the tasks by order (equal order in the order
added) and runs a slice, the units of the first pending task until it completes, the
budget is spent on the clock it is given, or the interrupt predicate says input arrived.
It has no wx dependency and is unit-tested with a fake clock. A task whose work is gone
is passed over and stays in the queue, so a tab that `show_device()` removes and later
re-inserts is pending again.
`IdleScheduler` drives the queue with the real clock, the app's input timestamp and the
Windows queue check, and logs each unit and slice. Each slice is a timer message: a
period of 250 ms while waiting for the user to go quiet, and a one-shot of zero after a
slice that left work, so the event loop dispatches whatever it has queued (paint,
timers, input) before the next slice runs. Chaining slices with `CallAfter` would not do
this: wx drains pending events fully before the next native message, on every platform.
On GTK the one-shot is 5 ms, because a due GLib timeout runs ahead of the redraw and
idle sources that paint and deliver posted events.
A slice runs only once the user has been idle for the quiet time, and the timer stops
itself once no task is pending. The tick period, quiet time and slice length are
constants in `IdleScheduler.cpp`. A unit cannot be interrupted once started, so the
largest unit bounds click latency on Windows; on the other platforms a click also waits
for the rest of the slice. A unit that pumps the event loop lets the timer fire inside
its own slice, and that tick does nothing.
The tasks are made by their owners. `MainFrame::prebuild_pages_when_idle()` registers
every `LazyPage` the frame created, in or out of the book (`pending()` is false for a
page out of the book), the Compare presets holder, and the Prepare sidebar's settings
page from `ParamsPanel::settings_page_prebuild()`, whose first unit selects the default
tab if none is selected yet and whose later units build one option group each.
`show_device()` only restarts the timer. `MainFrame` owns the scheduler because it owns
everything the tasks build, and clearing the queue with the frame is what keeps a task
from outliving its object.
Idle time comes from `GUI_App::FilterEvent`, which timestamps mouse and keyboard events
(`wxEVT_CATEGORY_USER_INPUT` minus command events, which all claim that category), and
`GUI_App::input_idle_ms()` reports it. On Windows a slice additionally refuses to start
when the message queue holds keyboard, button, touch or pen input. Mouse moves are
excluded because Windows synthesises one whenever a window appears under the cursor,
which every unit does. Other platforms use the timestamp alone.
Once every registered page is built the timer is stopped and the subsystem costs
nothing.
## Rules
**What builds before the first frame.** The Prepare tab's plater, because `post_init()`
needs its GL canvas on screen to initialise OpenGL in every startup state, and the start
page the user configured. Home is built by the first `MainFrame::Show()`, Prepare's
settings page by selecting the tab. `post_init()` passes through the Prepare tab for GL
init under `Freeze()` with `MainFrame::select_prepare_for_gl_init()`, which changes the
selection without the page-changed event, so nothing else is built for that pass.
**Reaching a lazy object.** A caller uses the type's own statics. `T::if_built()` may
return null and is for telling the object something it can live without (a rescale, a
colour change, a status update). `T::ensure()` builds the object and is for navigating
to it or for a caller that is about to show it. A caller that tells the object something
it would not fetch for itself on construction uses `T::when_built()`, which keeps the
message until the object exists. A panel that pulls its state when constructed (the Home
page requests the recent list on load, the Device tab reads the device manager on show)
is reached with `if_built()`; one that cannot pull gets `when_built()`.
**Unit size.** A unit cannot be interrupted, so it should stay within the slice length on
a fast machine. A constructor above that is staged. A single widget above it is the
floor unless the widget itself is split.
**Order.** Cheapest and most likely to be opened first, given where `MainFrame` creates
each holder. The settings page is 0 (the Prepare tab's own content), Home 10, Device 20
(a Bambu user's usual second stop), Calibration 30, Multi-device 40, the web Device
view 50, Project 60 (a second WebView2 instance) and the Compare presets dialog 100;
steps of ten so a new tab takes a value between its neighbours without renumbering
them. `MainFrame::prebuild_pages_when_idle()` registers the tasks once, from
`post_init()`.
**Never prebuilt.** A holder with a negative order, for a tab that few sessions open
and that costs more to build unasked than it saves (the Design tab), and plugin-provided
tabs, which are Python-side and not lazy pages.
## Adopting it
A lazy tab needs:
1. The panel derived from `LazyInstance<Panel>`, since a tab's panel has one instance.
2. A `LazyPage<Panel>*` member in `MainFrame`, created once in `init_tabpanel()` with
its `TAB_ID_*` as the name, its place by the order rule (and a factory if
`new Panel(parent)` is not enough), added to `m_lazy_pages`, and used wherever the
tab is added to or looked up in the notebook.
3. Every use of the panel outside `MainFrame` going through one of the panel's statics,
chosen by the rule above. When converting an existing member, `grep` for it; the
compiler finds the rest.
4. A constructor that copes with the frame already existing and the user being busy
elsewhere, since `wxGetApp().mainframe` is set, the frame may be shown, and the user
may be typing when a lazy panel is built: no `SetFocus()` while off screen, and
whatever the constructor did through a `MainFrame` accessor before (a mode update, a
deferred URL) done in the constructor itself.
To stage a heavy constructor, inherit `StagedBuild`, keep the skeleton in the constructor,
move the rest into `add_build_step()` lambdas in the original order, and follow the
staged-panel rules above. Measure the units. A step that is still one big widget has to
be split inside that widget or accepted as the floor.
Verification is by log. `MainFrame::prebuild_pages_when_idle` lists the queue it
registered, `IdleScheduler::tick` reports each completed task by name at info level and
each slice and unit at debug level, and `Lazy::ensure` reports an object a user built
on demand with the units and time it took. A run from the configured start
page shows every registered page complete, in order, with no unit longer than intended.
A click on a tab mid-prebuild shows the finished panel with an `ensure` line for what was
left, and the slices resume for the remaining tasks once the user is idle again.
+121 -17
View File
@@ -1,7 +1,7 @@
{ {
"name": "Sovol", "name": "Sovol",
"url": "", "url": "",
"version": "02.04.00.04", "version": "02.04.00.07",
"force_update": "0", "force_update": "0",
"description": "Sovol configurations", "description": "Sovol configurations",
"machine_model_list": [ "machine_model_list": [
@@ -167,10 +167,6 @@
"name": "0.20mm Standard @Sovol SV08 MAX 0.4 nozzle", "name": "0.20mm Standard @Sovol SV08 MAX 0.4 nozzle",
"sub_path": "process/0.20mm Standard @Sovol SV08 MAX 0.4 nozzle.json" "sub_path": "process/0.20mm Standard @Sovol SV08 MAX 0.4 nozzle.json"
}, },
{
"name": "0.20mm Standard @Sovol Zero 0.4 nozzle",
"sub_path": "process/0.20mm Standard @Sovol Zero 0.4 nozzle.json"
},
{ {
"name": "0.28mm Fast @Sovol SV06 ACE", "name": "0.28mm Fast @Sovol SV06 ACE",
"sub_path": "process/0.28mm Fast @Sovol SV06 ACE 0.4 nozzle.json" "sub_path": "process/0.28mm Fast @Sovol SV06 ACE 0.4 nozzle.json"
@@ -198,6 +194,74 @@
{ {
"name": "0.40mm Standard @Sovol SV08 MAX 0.8 nozzle", "name": "0.40mm Standard @Sovol SV08 MAX 0.8 nozzle",
"sub_path": "process/0.40mm Standard @Sovol SV08 MAX 0.8 nozzle.json" "sub_path": "process/0.40mm Standard @Sovol SV08 MAX 0.8 nozzle.json"
},
{
"name": "fdm_process_zero",
"sub_path": "process/fdm_process_zero.json"
},
{
"name": "0.06mm Quality @Sovol Zero 0.2 nozzle",
"sub_path": "process/0.06mm Quality @Sovol Zero 0.2 nozzle.json"
},
{
"name": "0.10mm Standard @Sovol Zero 0.2 nozzle",
"sub_path": "process/0.10mm Standard @Sovol Zero 0.2 nozzle.json"
},
{
"name": "0.12mm Quality @Sovol Zero 0.4 nozzle",
"sub_path": "process/0.12mm Quality @Sovol Zero 0.4 nozzle.json"
},
{
"name": "0.14mm Fast @Sovol Zero 0.2 nozzle",
"sub_path": "process/0.14mm Fast @Sovol Zero 0.2 nozzle.json"
},
{
"name": "0.15mm Quality @Sovol Zero 0.6 nozzle",
"sub_path": "process/0.15mm Quality @Sovol Zero 0.6 nozzle.json"
},
{
"name": "0.20mm Quality @Sovol Zero 0.8 nozzle",
"sub_path": "process/0.20mm Quality @Sovol Zero 0.8 nozzle.json"
},
{
"name": "0.20mm Standard @Sovol Zero 0.4 nozzle",
"sub_path": "process/0.20mm Standard @Sovol Zero 0.4 nozzle.json"
},
{
"name": "0.25mm Quality @Sovol Zero 1.0 nozzle",
"sub_path": "process/0.25mm Quality @Sovol Zero 1.0 nozzle.json"
},
{
"name": "0.25mm SPEEDBENCHY @Sovol Zero 0.4 nozzle",
"sub_path": "process/0.25mm SPEEDBENCHY @Sovol Zero 0.4 nozzle.json"
},
{
"name": "0.28mm Fast @Sovol Zero 0.4 nozzle",
"sub_path": "process/0.28mm Fast @Sovol Zero 0.4 nozzle.json"
},
{
"name": "0.30mm Standard @Sovol Zero 0.6 nozzle",
"sub_path": "process/0.30mm Standard @Sovol Zero 0.6 nozzle.json"
},
{
"name": "0.40mm Standard @Sovol Zero 0.8 nozzle",
"sub_path": "process/0.40mm Standard @Sovol Zero 0.8 nozzle.json"
},
{
"name": "0.42mm Fast @Sovol Zero 0.6 nozzle",
"sub_path": "process/0.42mm Fast @Sovol Zero 0.6 nozzle.json"
},
{
"name": "0.50mm Standard @Sovol Zero 1.0 nozzle",
"sub_path": "process/0.50mm Standard @Sovol Zero 1.0 nozzle.json"
},
{
"name": "0.56mm Fast @Sovol Zero 0.8 nozzle",
"sub_path": "process/0.56mm Fast @Sovol Zero 0.8 nozzle.json"
},
{
"name": "0.70mm Fast @Sovol Zero 1.0 nozzle",
"sub_path": "process/0.70mm Fast @Sovol Zero 1.0 nozzle.json"
} }
], ],
"filament_list": [ "filament_list": [
@@ -249,6 +313,10 @@
"name": "Generic PETG @Sovol Zero", "name": "Generic PETG @Sovol Zero",
"sub_path": "filament/Generic PETG @Sovol Zero.json" "sub_path": "filament/Generic PETG @Sovol Zero.json"
}, },
{
"name": "Generic PETG @Sovol Zero Hardened Steel nozzle",
"sub_path": "filament/Generic PETG @Sovol Zero Hardened Steel nozzle.json"
},
{ {
"name": "Generic PLA @Sovol SV06 ACE", "name": "Generic PLA @Sovol SV06 ACE",
"sub_path": "filament/Generic PLA @Sovol SV06 ACE.json" "sub_path": "filament/Generic PLA @Sovol SV06 ACE.json"
@@ -277,6 +345,14 @@
"name": "Generic PLA @Sovol Zero", "name": "Generic PLA @Sovol Zero",
"sub_path": "filament/Generic PLA @Sovol Zero.json" "sub_path": "filament/Generic PLA @Sovol Zero.json"
}, },
{
"name": "Generic PLA @Sovol Zero Hardened Steel nozzle",
"sub_path": "filament/Generic PLA @Sovol Zero Hardened Steel nozzle.json"
},
{
"name": "Generic PLA SPEEDBENCHY @Sovol Zero",
"sub_path": "filament/Generic PLA SPEEDBENCHY @Sovol Zero.json"
},
{ {
"name": "Generic PLA Silk @Sovol SV08 MAX", "name": "Generic PLA Silk @Sovol SV08 MAX",
"sub_path": "filament/Generic PLA Silk @Sovol SV08 MAX.json" "sub_path": "filament/Generic PLA Silk @Sovol SV08 MAX.json"
@@ -285,6 +361,10 @@
"name": "Generic PLA Silk @Sovol Zero", "name": "Generic PLA Silk @Sovol Zero",
"sub_path": "filament/Generic PLA Silk @Sovol Zero.json" "sub_path": "filament/Generic PLA Silk @Sovol Zero.json"
}, },
{
"name": "Generic PLA Silk @Sovol Zero Hardened Steel nozzle",
"sub_path": "filament/Generic PLA Silk @Sovol Zero Hardened Steel nozzle.json"
},
{ {
"name": "Generic TPU @Sovol SV06 ACE", "name": "Generic TPU @Sovol SV06 ACE",
"sub_path": "filament/Generic TPU @Sovol SV06 ACE.json" "sub_path": "filament/Generic TPU @Sovol SV06 ACE.json"
@@ -312,18 +392,6 @@
{ {
"name": "SUNLU PETG @Sovol SV08 MAX", "name": "SUNLU PETG @Sovol SV08 MAX",
"sub_path": "filament/SUNLU PETG @Sovol SV08 MAX.json" "sub_path": "filament/SUNLU PETG @Sovol SV08 MAX.json"
},
{
"name": "Sovol Zero PETG HS Nozzle",
"sub_path": "filament/Sovol Zero PETG HS Nozzle.json"
},
{
"name": "Sovol Zero PLA Basic HS Nozzle",
"sub_path": "filament/Sovol Zero PLA Basic HS Nozzle.json"
},
{
"name": "Sovol Zero PLA Silk HS Nozzle",
"sub_path": "filament/Sovol Zero PLA Silk HS Nozzle.json"
} }
], ],
"machine_list": [ "machine_list": [
@@ -415,9 +483,45 @@
"name": "Sovol SV08 MAX 0.8 nozzle", "name": "Sovol SV08 MAX 0.8 nozzle",
"sub_path": "machine/Sovol SV08 MAX 0.8 nozzle.json" "sub_path": "machine/Sovol SV08 MAX 0.8 nozzle.json"
}, },
{
"name": "Sovol Zero 0.2 nozzle",
"sub_path": "machine/Sovol Zero 0.2 nozzle.json"
},
{ {
"name": "Sovol Zero 0.4 nozzle", "name": "Sovol Zero 0.4 nozzle",
"sub_path": "machine/Sovol Zero 0.4 nozzle.json" "sub_path": "machine/Sovol Zero 0.4 nozzle.json"
},
{
"name": "Sovol Zero 0.6 nozzle",
"sub_path": "machine/Sovol Zero 0.6 nozzle.json"
},
{
"name": "Sovol Zero 0.8 nozzle",
"sub_path": "machine/Sovol Zero 0.8 nozzle.json"
},
{
"name": "Sovol Zero 1.0 nozzle",
"sub_path": "machine/Sovol Zero 1.0 nozzle.json"
},
{
"name": "Sovol Zero 0.2 Hardened Steel nozzle",
"sub_path": "machine/Sovol Zero 0.2 Hardened Steel nozzle.json"
},
{
"name": "Sovol Zero 0.4 Hardened Steel nozzle",
"sub_path": "machine/Sovol Zero 0.4 Hardened Steel nozzle.json"
},
{
"name": "Sovol Zero 0.6 Hardened Steel nozzle",
"sub_path": "machine/Sovol Zero 0.6 Hardened Steel nozzle.json"
},
{
"name": "Sovol Zero 0.8 Hardened Steel nozzle",
"sub_path": "machine/Sovol Zero 0.8 Hardened Steel nozzle.json"
},
{
"name": "Sovol Zero 1.0 Hardened Steel nozzle",
"sub_path": "machine/Sovol Zero 1.0 Hardened Steel nozzle.json"
} }
] ]
} }
@@ -1,10 +1,11 @@
{ {
"type": "filament", "type": "filament",
"name": "Generic ABS @Sovol Zero", "name": "Generic ABS @Sovol Zero",
"inherits": "Generic ABS @System",
"renamed_from": "Sovol Zero ABS", "renamed_from": "Sovol Zero ABS",
"inherits": "fdm_filament_abs",
"from": "system", "from": "system",
"setting_id": "g6sSyyIFYJUzlXsp", "setting_id": "g6sSyyIFYJUzlXsp",
"filament_id": "OFY9muEs",
"instantiation": "true", "instantiation": "true",
"filament_flow_ratio": [ "filament_flow_ratio": [
"0.98" "0.98"
@@ -73,6 +74,39 @@
"0" "0"
], ],
"compatible_printers": [ "compatible_printers": [
"Sovol Zero 0.4 nozzle" "Sovol Zero 0.2 nozzle",
"Sovol Zero 0.4 nozzle",
"Sovol Zero 0.6 nozzle",
"Sovol Zero 0.8 nozzle",
"Sovol Zero 1.0 nozzle",
"Sovol Zero 0.2 Hardened Steel nozzle",
"Sovol Zero 0.4 Hardened Steel nozzle",
"Sovol Zero 0.6 Hardened Steel nozzle",
"Sovol Zero 0.8 Hardened Steel nozzle",
"Sovol Zero 1.0 Hardened Steel nozzle"
],
"cool_plate_temp": [
"80"
],
"eng_plate_temp": [
"80"
],
"textured_plate_temp": [
"80"
],
"cool_plate_temp_initial_layer": [
"80"
],
"eng_plate_temp_initial_layer": [
"80"
],
"textured_plate_temp_initial_layer": [
"80"
],
"filament_end_gcode": [
"; filament end gcode \n"
],
"filament_density": [
"1.10"
] ]
} }
@@ -1,11 +1,12 @@
{ {
"type": "filament", "type": "filament",
"filament_id": "OFLakOUI",
"setting_id": "yRKCiPMN6fxibcyg",
"name": "Generic PC @Sovol Zero", "name": "Generic PC @Sovol Zero",
"inherits": "Generic PC @System",
"renamed_from": "Sovol Zero PC", "renamed_from": "Sovol Zero PC",
"from": "system", "from": "system",
"setting_id": "yRKCiPMN6fxibcyg",
"instantiation": "true", "instantiation": "true",
"inherits": "fdm_filament_pc",
"filament_flow_ratio": [ "filament_flow_ratio": [
"0.98" "0.98"
], ],
@@ -13,7 +14,16 @@
"21" "21"
], ],
"compatible_printers": [ "compatible_printers": [
"Sovol Zero 0.4 nozzle" "Sovol Zero 0.2 nozzle",
"Sovol Zero 0.4 nozzle",
"Sovol Zero 0.6 nozzle",
"Sovol Zero 0.8 nozzle",
"Sovol Zero 1.0 nozzle",
"Sovol Zero 0.2 Hardened Steel nozzle",
"Sovol Zero 0.4 Hardened Steel nozzle",
"Sovol Zero 0.6 Hardened Steel nozzle",
"Sovol Zero 0.8 Hardened Steel nozzle",
"Sovol Zero 1.0 Hardened Steel nozzle"
], ],
"nozzle_temperature_initial_layer": [ "nozzle_temperature_initial_layer": [
"290" "290"
@@ -51,7 +61,9 @@
"slow_down_min_speed": [ "slow_down_min_speed": [
"10" "10"
], ],
"dont_slow_down_outer_wall": "0", "dont_slow_down_outer_wall": [
"0"
],
"overhang_fan_speed": [ "overhang_fan_speed": [
"20" "20"
], ],
@@ -61,8 +73,19 @@
"temperature_vitrification": [ "temperature_vitrification": [
"60" "60"
], ],
"additional_cooling_fan_speed": "0", "additional_cooling_fan_speed": [
"activate_air_filtration": "1", "0"
"during_print_exhaust_fan_speed": "50", ],
"complete_print_exhaust_fan_speed": "50" "activate_air_filtration": [
"1"
],
"during_print_exhaust_fan_speed": [
"50"
],
"complete_print_exhaust_fan_speed": [
"50"
],
"filament_end_gcode": [
"; filament end gcode \n"
]
} }
@@ -0,0 +1,116 @@
{
"type": "filament",
"filament_id": "OFYPdQJh",
"setting_id": "d9QbCESNz3ZLU6eu",
"name": "Generic PETG @Sovol Zero Hardened Steel nozzle",
"renamed_from": "Sovol Zero PETG HS Nozzle",
"from": "system",
"instantiation": "true",
"inherits": "fdm_filament_pet",
"filament_flow_ratio": [
"0.98"
],
"enable_pressure_advance": [
"1"
],
"pressure_advance": [
"0.048"
],
"filament_max_volumetric_speed": [
"15"
],
"nozzle_temperature_initial_layer": [
"265"
],
"nozzle_temperature": [
"250"
],
"nozzle_temperature_range_low": [
"230"
],
"nozzle_temperature_range_high": [
"280"
],
"hot_plate_temp": [
"85"
],
"hot_plate_temp_initial_layer": [
"85"
],
"fan_min_speed": [
"10"
],
"fan_max_speed": [
"40"
],
"fan_cooling_layer_time": [
"50"
],
"full_fan_speed_layer": [
"3"
],
"slow_down_layer_time": [
"10"
],
"slow_down_min_speed": [
"10"
],
"overhang_fan_speed": [
"70"
],
"overhang_fan_threshold": [
"10%"
],
"temperature_vitrification": [
"60"
],
"close_fan_the_first_x_layers": [
"1"
],
"filament_retraction_length": [
"0.5"
],
"filament_z_hop": [
"0.4"
],
"activate_air_filtration": [
"1"
],
"during_print_exhaust_fan_speed": [
"50"
],
"complete_print_exhaust_fan_speed": [
"50"
],
"compatible_printers": [
"Sovol Zero 0.2 Hardened Steel nozzle",
"Sovol Zero 0.4 Hardened Steel nozzle",
"Sovol Zero 0.6 Hardened Steel nozzle",
"Sovol Zero 0.8 Hardened Steel nozzle",
"Sovol Zero 1.0 Hardened Steel nozzle"
],
"cool_plate_temp": [
"85"
],
"eng_plate_temp": [
"85"
],
"textured_plate_temp": [
"85"
],
"cool_plate_temp_initial_layer": [
"85"
],
"eng_plate_temp_initial_layer": [
"85"
],
"textured_plate_temp_initial_layer": [
"85"
],
"filament_end_gcode": [
"; filament end gcode \n"
],
"filament_start_gcode": [
"; filament start gcode\n"
]
}
@@ -1,16 +1,21 @@
{ {
"type": "filament", "type": "filament",
"filament_id": "OFYPdQJh",
"setting_id": "i4OW2eAtXOKdtVNj",
"name": "Generic PETG @Sovol Zero", "name": "Generic PETG @Sovol Zero",
"inherits": "Generic PETG @System",
"renamed_from": "Sovol Zero PETG", "renamed_from": "Sovol Zero PETG",
"from": "system", "from": "system",
"setting_id": "i4OW2eAtXOKdtVNj",
"instantiation": "true", "instantiation": "true",
"inherits": "fdm_filament_pet",
"filament_flow_ratio": [ "filament_flow_ratio": [
"1.0348" "1.0348"
], ],
"enable_pressure_advance": "1", "enable_pressure_advance": [
"pressure_advance": "0.046", "1"
],
"pressure_advance": [
"0.046"
],
"filament_max_volumetric_speed": [ "filament_max_volumetric_speed": [
"15" "15"
], ],
@@ -68,10 +73,44 @@
"filament_z_hop": [ "filament_z_hop": [
"0.4" "0.4"
], ],
"activate_air_filtration": "1", "activate_air_filtration": [
"during_print_exhaust_fan_speed": "50", "1"
"complete_print_exhaust_fan_speed": "50", ],
"during_print_exhaust_fan_speed": [
"50"
],
"complete_print_exhaust_fan_speed": [
"50"
],
"compatible_printers": [ "compatible_printers": [
"Sovol Zero 0.4 nozzle" "Sovol Zero 0.2 nozzle",
"Sovol Zero 0.4 nozzle",
"Sovol Zero 0.6 nozzle",
"Sovol Zero 0.8 nozzle",
"Sovol Zero 1.0 nozzle"
],
"cool_plate_temp": [
"85"
],
"eng_plate_temp": [
"85"
],
"textured_plate_temp": [
"85"
],
"cool_plate_temp_initial_layer": [
"85"
],
"eng_plate_temp_initial_layer": [
"85"
],
"textured_plate_temp_initial_layer": [
"85"
],
"filament_end_gcode": [
"; filament end gcode \n"
],
"filament_start_gcode": [
"; filament start gcode\n"
] ]
} }
@@ -0,0 +1,110 @@
{
"type": "filament",
"filament_id": "OFDSrzZ8",
"setting_id": "nZgETe4CTpicEjQX",
"name": "Generic PLA @Sovol Zero Hardened Steel nozzle",
"renamed_from": "Sovol Zero PLA Basic HS Nozzle",
"from": "system",
"instantiation": "true",
"inherits": "fdm_filament_pla",
"filament_flow_ratio": [
"1.0348"
],
"filament_max_volumetric_speed": [
"21"
],
"enable_pressure_advance": [
"1"
],
"pressure_advance": [
"0.03"
],
"compatible_printers": [
"Sovol Zero 0.2 Hardened Steel nozzle",
"Sovol Zero 0.4 Hardened Steel nozzle",
"Sovol Zero 0.6 Hardened Steel nozzle",
"Sovol Zero 0.8 Hardened Steel nozzle",
"Sovol Zero 1.0 Hardened Steel nozzle"
],
"nozzle_temperature_initial_layer": [
"245"
],
"nozzle_temperature": [
"230"
],
"nozzle_temperature_range_low": [
"190"
],
"nozzle_temperature_range_high": [
"250"
],
"hot_plate_temp": [
"65"
],
"hot_plate_temp_initial_layer": [
"65"
],
"fan_min_speed": [
"70"
],
"fan_max_speed": [
"100"
],
"fan_cooling_layer_time": [
"80"
],
"full_fan_speed_layer": [
"3"
],
"slow_down_layer_time": [
"5"
],
"slow_down_min_speed": [
"10"
],
"dont_slow_down_outer_wall": [
"0"
],
"overhang_fan_speed": [
"100"
],
"overhang_fan_threshold": [
"50%"
],
"temperature_vitrification": [
"60"
],
"additional_cooling_fan_speed": [
"75%"
],
"activate_air_filtration": [
"1"
],
"during_print_exhaust_fan_speed": [
"80%"
],
"complete_print_exhaust_fan_speed": [
"80%"
],
"cool_plate_temp": [
"60"
],
"eng_plate_temp": [
"60"
],
"textured_plate_temp": [
"60"
],
"cool_plate_temp_initial_layer": [
"55"
],
"eng_plate_temp_initial_layer": [
"55"
],
"filament_end_gcode": [
"; filament end gcode \n"
],
"filament_start_gcode": [
"; filament start gcode\n"
]
}
@@ -1,21 +1,24 @@
{ {
"type": "filament", "type": "filament",
"filament_id": "OFDSrzZ8",
"setting_id": "NNDerIjh7qtuh1I3",
"name": "Generic PLA @Sovol Zero", "name": "Generic PLA @Sovol Zero",
"inherits": "Generic PLA @System",
"renamed_from": "Sovol Zero PLA Basic", "renamed_from": "Sovol Zero PLA Basic",
"from": "system", "from": "system",
"setting_id": "NNDerIjh7qtuh1I3",
"instantiation": "true", "instantiation": "true",
"inherits": "fdm_filament_pla",
"filament_flow_ratio": [ "filament_flow_ratio": [
"0.98" "0.98"
], ],
"filament_max_volumetric_speed": [ "filament_max_volumetric_speed": [
"21" "25"
], ],
"enable_pressure_advance": "1",
"pressure_advance": "0.032",
"compatible_printers": [ "compatible_printers": [
"Sovol Zero 0.4 nozzle" "Sovol Zero 0.2 nozzle",
"Sovol Zero 0.4 nozzle",
"Sovol Zero 0.6 nozzle",
"Sovol Zero 0.8 nozzle",
"Sovol Zero 1.0 nozzle"
], ],
"nozzle_temperature_initial_layer": [ "nozzle_temperature_initial_layer": [
"230" "230"
@@ -24,28 +27,28 @@
"210" "210"
], ],
"nozzle_temperature_range_low": [ "nozzle_temperature_range_low": [
"190" "180"
], ],
"nozzle_temperature_range_high": [ "nozzle_temperature_range_high": [
"250" "240"
], ],
"hot_plate_temp": [ "hot_plate_temp": [
"65" "60"
], ],
"hot_plate_temp_initial_layer": [ "hot_plate_temp_initial_layer": [
"65" "60"
], ],
"fan_min_speed": [ "fan_min_speed": [
"70" "100"
], ],
"fan_max_speed": [ "fan_max_speed": [
"100" "100"
], ],
"fan_cooling_layer_time": [ "fan_cooling_layer_time": [
"80" "60"
], ],
"full_fan_speed_layer": [ "full_fan_speed_layer": [
"3" "2"
], ],
"slow_down_layer_time": [ "slow_down_layer_time": [
"5" "5"
@@ -53,18 +56,43 @@
"slow_down_min_speed": [ "slow_down_min_speed": [
"10" "10"
], ],
"dont_slow_down_outer_wall": "0",
"overhang_fan_speed": [ "overhang_fan_speed": [
"100" "100"
], ],
"overhang_fan_threshold": [ "overhang_fan_threshold": [
"50%" "10%"
], ],
"temperature_vitrification": [ "temperature_vitrification": [
"50"
],
"filament_z_hop": [
"0.4"
],
"filament_retraction_length": [
"0.4"
],
"filament_diameter": [
"1.75"
],
"cool_plate_temp": [
"60" "60"
], ],
"additional_cooling_fan_speed": "75%", "eng_plate_temp": [
"activate_air_filtration": "1", "60"
"during_print_exhaust_fan_speed": "80%", ],
"complete_print_exhaust_fan_speed": "80%" "textured_plate_temp": [
"60"
],
"cool_plate_temp_initial_layer": [
"55"
],
"eng_plate_temp_initial_layer": [
"55"
],
"filament_end_gcode": [
"; filament end gcode \n"
],
"filament_start_gcode": [
"; filament start gcode\n"
]
} }
@@ -0,0 +1,118 @@
{
"type": "filament",
"filament_id": "OFIUkWYN",
"setting_id": "MC2InZ7iKDjIGike",
"name": "Generic PLA SPEEDBENCHY @Sovol Zero",
"from": "system",
"instantiation": "true",
"inherits": "fdm_filament_pla",
"filament_flow_ratio": [
"1"
],
"filament_max_volumetric_speed": [
"50"
],
"compatible_printers": [
"Sovol Zero 0.4 nozzle",
"Sovol Zero 0.4 Hardened Steel nozzle"
],
"nozzle_temperature_initial_layer": [
"245"
],
"nozzle_temperature": [
"225"
],
"nozzle_temperature_range_low": [
"190"
],
"nozzle_temperature_range_high": [
"250"
],
"hot_plate_temp": [
"65"
],
"hot_plate_temp_initial_layer": [
"65"
],
"enable_pressure_advance": [
"1"
],
"pressure_advance": [
"0.032"
],
"fan_min_speed": [
"100"
],
"fan_max_speed": [
"100"
],
"fan_cooling_layer_time": [
"30"
],
"full_fan_speed_layer": [
"3"
],
"slow_down_layer_time": [
"1.7"
],
"slow_down_min_speed": [
"40"
],
"overhang_fan_speed": [
"100"
],
"overhang_fan_threshold": [
"75%"
],
"additional_cooling_fan_speed": [
"100"
],
"filament_z_hop": [
"0"
],
"filament_retraction_length": [
"0.35"
],
"filament_retraction_speed": [
"90"
],
"filament_deretraction_speed": [
"90"
],
"filament_retract_before_wipe": [
"0%"
],
"filament_wipe_distance": [
"2"
],
"filament_retract_when_changing_layer": [
"0"
],
"filament_diameter": [
"1.75"
],
"cool_plate_temp": [
"60"
],
"eng_plate_temp": [
"60"
],
"textured_plate_temp": [
"60"
],
"cool_plate_temp_initial_layer": [
"55"
],
"eng_plate_temp_initial_layer": [
"55"
],
"filament_end_gcode": [
"; filament end gcode \n"
],
"filament_start_gcode": [
"; filament start gcode\n"
],
"temperature_vitrification": [
"100"
]
}
@@ -0,0 +1,110 @@
{
"type": "filament",
"filament_id": "OFesA6rF",
"setting_id": "LA8X1RsMdV2xNT1o",
"name": "Generic PLA Silk @Sovol Zero Hardened Steel nozzle",
"renamed_from": "Sovol Zero PLA Silk HS Nozzle",
"from": "system",
"instantiation": "true",
"inherits": "fdm_filament_pla",
"filament_flow_ratio": [
"0.98"
],
"filament_max_volumetric_speed": [
"15"
],
"enable_pressure_advance": [
"1"
],
"pressure_advance": [
"0.027"
],
"compatible_printers": [
"Sovol Zero 0.2 Hardened Steel nozzle",
"Sovol Zero 0.4 Hardened Steel nozzle",
"Sovol Zero 0.6 Hardened Steel nozzle",
"Sovol Zero 0.8 Hardened Steel nozzle",
"Sovol Zero 1.0 Hardened Steel nozzle"
],
"nozzle_temperature_initial_layer": [
"245"
],
"nozzle_temperature": [
"230"
],
"nozzle_temperature_range_low": [
"190"
],
"nozzle_temperature_range_high": [
"250"
],
"hot_plate_temp": [
"65"
],
"hot_plate_temp_initial_layer": [
"65"
],
"fan_min_speed": [
"70"
],
"fan_max_speed": [
"100"
],
"fan_cooling_layer_time": [
"80"
],
"full_fan_speed_layer": [
"3"
],
"slow_down_layer_time": [
"5"
],
"slow_down_min_speed": [
"10"
],
"dont_slow_down_outer_wall": [
"0"
],
"overhang_fan_speed": [
"100"
],
"overhang_fan_threshold": [
"50%"
],
"temperature_vitrification": [
"60"
],
"additional_cooling_fan_speed": [
"75%"
],
"activate_air_filtration": [
"1"
],
"during_print_exhaust_fan_speed": [
"80%"
],
"complete_print_exhaust_fan_speed": [
"80%"
],
"cool_plate_temp": [
"60"
],
"eng_plate_temp": [
"60"
],
"textured_plate_temp": [
"60"
],
"cool_plate_temp_initial_layer": [
"55"
],
"eng_plate_temp_initial_layer": [
"55"
],
"filament_end_gcode": [
"; filament end gcode \n"
],
"filament_start_gcode": [
"; filament start gcode\n"
]
}
@@ -1,27 +1,30 @@
{ {
"type": "filament", "type": "filament",
"filament_id": "OFesA6rF",
"setting_id": "Se2yKerHRStYtWf5",
"name": "Generic PLA Silk @Sovol Zero", "name": "Generic PLA Silk @Sovol Zero",
"inherits": "Generic PLA Silk @System",
"renamed_from": "Sovol Zero PLA Silk", "renamed_from": "Sovol Zero PLA Silk",
"from": "system", "from": "system",
"setting_id": "Se2yKerHRStYtWf5",
"instantiation": "true", "instantiation": "true",
"filament_multitool_ramming_flow": [ "inherits": "fdm_filament_pla",
"20"
],
"filament_retraction_length": [
"nil"
],
"filament_flow_ratio": [ "filament_flow_ratio": [
"0.98" "0.98"
], ],
"filament_max_volumetric_speed": [ "filament_max_volumetric_speed": [
"15" "15"
], ],
"enable_pressure_advance": "1", "enable_pressure_advance": [
"pressure_advance": "0.029", "1"
],
"pressure_advance": [
"0.029"
],
"compatible_printers": [ "compatible_printers": [
"Sovol Zero 0.4 nozzle" "Sovol Zero 0.2 nozzle",
"Sovol Zero 0.4 nozzle",
"Sovol Zero 0.6 nozzle",
"Sovol Zero 0.8 nozzle",
"Sovol Zero 1.0 nozzle"
], ],
"nozzle_temperature_initial_layer": [ "nozzle_temperature_initial_layer": [
"245" "245"
@@ -59,7 +62,9 @@
"slow_down_min_speed": [ "slow_down_min_speed": [
"10" "10"
], ],
"dont_slow_down_outer_wall": "0", "dont_slow_down_outer_wall": [
"0"
],
"overhang_fan_speed": [ "overhang_fan_speed": [
"100" "100"
], ],
@@ -69,8 +74,43 @@
"temperature_vitrification": [ "temperature_vitrification": [
"60" "60"
], ],
"additional_cooling_fan_speed": "75%", "additional_cooling_fan_speed": [
"activate_air_filtration": "1", "75%"
"during_print_exhaust_fan_speed": "80%", ],
"complete_print_exhaust_fan_speed": "80%" "activate_air_filtration": [
"1"
],
"during_print_exhaust_fan_speed": [
"80%"
],
"complete_print_exhaust_fan_speed": [
"80%"
],
"filament_multitool_ramming_flow": [
"20"
],
"filament_retraction_length": [
"nil"
],
"cool_plate_temp": [
"60"
],
"eng_plate_temp": [
"60"
],
"textured_plate_temp": [
"60"
],
"cool_plate_temp_initial_layer": [
"55"
],
"eng_plate_temp_initial_layer": [
"55"
],
"filament_end_gcode": [
"; filament end gcode \n"
],
"filament_start_gcode": [
"; filament start gcode\n"
]
} }
@@ -1,11 +1,12 @@
{ {
"type": "filament", "type": "filament",
"filament_id": "OFgbpcy9",
"setting_id": "MlY6WQ41FE8zDPSV",
"name": "Generic TPU @Sovol Zero", "name": "Generic TPU @Sovol Zero",
"inherits": "Generic TPU @System",
"renamed_from": "Sovol Zero TPU", "renamed_from": "Sovol Zero TPU",
"from": "system", "from": "system",
"setting_id": "MlY6WQ41FE8zDPSV",
"instantiation": "true", "instantiation": "true",
"inherits": "fdm_filament_tpu",
"filament_flow_ratio": [ "filament_flow_ratio": [
"0.98" "0.98"
], ],
@@ -60,11 +61,55 @@
"filament_z_hop": [ "filament_z_hop": [
"0.4" "0.4"
], ],
"additional_cooling_fan_speed": "50", "additional_cooling_fan_speed": [
"activate_air_filtration": "1", "50"
"during_print_exhaust_fan_speed": "100", ],
"complete_print_exhaust_fan_speed": "50", "activate_air_filtration": [
"1"
],
"during_print_exhaust_fan_speed": [
"100"
],
"complete_print_exhaust_fan_speed": [
"50"
],
"compatible_printers": [ "compatible_printers": [
"Sovol Zero 0.4 nozzle" "Sovol Zero 0.2 nozzle",
"Sovol Zero 0.4 nozzle",
"Sovol Zero 0.6 nozzle",
"Sovol Zero 0.8 nozzle",
"Sovol Zero 1.0 nozzle",
"Sovol Zero 0.2 Hardened Steel nozzle",
"Sovol Zero 0.4 Hardened Steel nozzle",
"Sovol Zero 0.6 Hardened Steel nozzle",
"Sovol Zero 0.8 Hardened Steel nozzle",
"Sovol Zero 1.0 Hardened Steel nozzle"
],
"cool_plate_temp": [
"60"
],
"eng_plate_temp": [
"60"
],
"textured_plate_temp": [
"60"
],
"cool_plate_temp_initial_layer": [
"55"
],
"eng_plate_temp_initial_layer": [
"55"
],
"textured_plate_temp_initial_layer": [
"55"
],
"filament_end_gcode": [
"; filament end gcode \n"
],
"filament_retraction_length": [
"nil"
],
"filament_start_gcode": [
"; filament start gcode\n"
] ]
} }
@@ -1,77 +0,0 @@
{
"type": "filament",
"name": "Sovol Zero PETG HS Nozzle",
"inherits": "Generic PETG @System",
"from": "system",
"setting_id": "AfxHmpdOkMDJa2fk",
"filament_id": "OFymnal9",
"instantiation": "true",
"filament_flow_ratio": [
"0.98"
],
"enable_pressure_advance": "1",
"pressure_advance": "0.048",
"filament_max_volumetric_speed": [
"15"
],
"nozzle_temperature_initial_layer": [
"265"
],
"nozzle_temperature": [
"250"
],
"nozzle_temperature_range_low": [
"230"
],
"nozzle_temperature_range_high": [
"280"
],
"hot_plate_temp": [
"85"
],
"hot_plate_temp_initial_layer": [
"85"
],
"fan_min_speed": [
"10"
],
"fan_max_speed": [
"40"
],
"fan_cooling_layer_time": [
"50"
],
"full_fan_speed_layer": [
"3"
],
"slow_down_layer_time": [
"10"
],
"slow_down_min_speed": [
"10"
],
"overhang_fan_speed": [
"70"
],
"overhang_fan_threshold": [
"10%"
],
"temperature_vitrification": [
"60"
],
"close_fan_the_first_x_layers": [
"1"
],
"filament_retraction_length": [
"0.5"
],
"filament_z_hop": [
"0.4"
],
"activate_air_filtration": "1",
"during_print_exhaust_fan_speed": "50",
"complete_print_exhaust_fan_speed": "50",
"compatible_printers": [
"Sovol Zero 0.4 nozzle"
]
}
@@ -1,70 +0,0 @@
{
"type": "filament",
"name": "Sovol Zero PLA Basic HS Nozzle",
"inherits": "Generic PLA @System",
"from": "system",
"setting_id": "i9wDnSEIrOBPbOZl",
"filament_id": "OFzB4uOs",
"instantiation": "true",
"filament_flow_ratio": [
"1.0348"
],
"filament_max_volumetric_speed": [
"21"
],
"enable_pressure_advance": "1",
"pressure_advance": "0.03",
"compatible_printers": [
"Sovol Zero 0.4 nozzle"
],
"nozzle_temperature_initial_layer": [
"245"
],
"nozzle_temperature": [
"230"
],
"nozzle_temperature_range_low": [
"190"
],
"nozzle_temperature_range_high": [
"250"
],
"hot_plate_temp": [
"65"
],
"hot_plate_temp_initial_layer": [
"65"
],
"fan_min_speed": [
"70"
],
"fan_max_speed": [
"100"
],
"fan_cooling_layer_time": [
"80"
],
"full_fan_speed_layer": [
"3"
],
"slow_down_layer_time": [
"5"
],
"slow_down_min_speed": [
"10"
],
"dont_slow_down_outer_wall": "0",
"overhang_fan_speed": [
"100"
],
"overhang_fan_threshold": [
"50%"
],
"temperature_vitrification": [
"60"
],
"additional_cooling_fan_speed": "75%",
"activate_air_filtration": "1",
"during_print_exhaust_fan_speed": "80%",
"complete_print_exhaust_fan_speed": "80%"
}
@@ -1,70 +0,0 @@
{
"type": "filament",
"name": "Sovol Zero PLA Silk HS Nozzle",
"inherits": "Generic PLA @System",
"from": "system",
"setting_id": "XxEJBNFLRltR2Xwn",
"filament_id": "OFAO9A7J",
"instantiation": "true",
"filament_flow_ratio": [
"0.98"
],
"filament_max_volumetric_speed": [
"15"
],
"enable_pressure_advance": "1",
"pressure_advance": "0.027",
"compatible_printers": [
"Sovol Zero 0.4 nozzle"
],
"nozzle_temperature_initial_layer": [
"245"
],
"nozzle_temperature": [
"230"
],
"nozzle_temperature_range_low": [
"190"
],
"nozzle_temperature_range_high": [
"250"
],
"hot_plate_temp": [
"65"
],
"hot_plate_temp_initial_layer": [
"65"
],
"fan_min_speed": [
"70"
],
"fan_max_speed": [
"100"
],
"fan_cooling_layer_time": [
"80"
],
"full_fan_speed_layer": [
"3"
],
"slow_down_layer_time": [
"5"
],
"slow_down_min_speed": [
"10"
],
"dont_slow_down_outer_wall": "0",
"overhang_fan_speed": [
"100"
],
"overhang_fan_threshold": [
"50%"
],
"temperature_vitrification": [
"60"
],
"additional_cooling_fan_speed": "75%",
"activate_air_filtration": "1",
"during_print_exhaust_fan_speed": "80%",
"complete_print_exhaust_fan_speed": "80%"
}
@@ -0,0 +1,19 @@
{
"type": "machine",
"name": "Sovol Zero 0.2 Hardened Steel nozzle",
"inherits": "Sovol Zero 0.2 nozzle",
"from": "system",
"setting_id": "OkvEInEyzUUJzw9K",
"instantiation": "true",
"printer_model": "Sovol Zero",
"printer_variant": "0.2HS",
"nozzle_diameter": [
"0.2"
],
"default_filament_profile": [
"Generic PLA @Sovol Zero Hardened Steel nozzle"
],
"nozzle_type": [
"hardened_steel"
]
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,19 @@
{
"type": "machine",
"name": "Sovol Zero 0.4 Hardened Steel nozzle",
"inherits": "Sovol Zero 0.4 nozzle",
"from": "system",
"setting_id": "RqwHKS8MYRdoeJPi",
"instantiation": "true",
"printer_model": "Sovol Zero",
"printer_variant": "0.4HS",
"nozzle_diameter": [
"0.4"
],
"default_filament_profile": [
"Generic PLA @Sovol Zero Hardened Steel nozzle"
],
"nozzle_type": [
"hardened_steel"
]
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,19 @@
{
"type": "machine",
"name": "Sovol Zero 0.6 Hardened Steel nozzle",
"inherits": "Sovol Zero 0.6 nozzle",
"from": "system",
"setting_id": "s3N3FJkWrzOylFm8",
"instantiation": "true",
"printer_model": "Sovol Zero",
"printer_variant": "0.6HS",
"nozzle_diameter": [
"0.6"
],
"default_filament_profile": [
"Generic PLA @Sovol Zero Hardened Steel nozzle"
],
"nozzle_type": [
"hardened_steel"
]
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,19 @@
{
"type": "machine",
"name": "Sovol Zero 0.8 Hardened Steel nozzle",
"inherits": "Sovol Zero 0.8 nozzle",
"from": "system",
"setting_id": "houacf8sQ3bLozqD",
"instantiation": "true",
"printer_model": "Sovol Zero",
"printer_variant": "0.8HS",
"nozzle_diameter": [
"0.8"
],
"default_filament_profile": [
"Generic PLA @Sovol Zero Hardened Steel nozzle"
],
"nozzle_type": [
"hardened_steel"
]
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,19 @@
{
"type": "machine",
"name": "Sovol Zero 1.0 Hardened Steel nozzle",
"inherits": "Sovol Zero 1.0 nozzle",
"from": "system",
"setting_id": "sqlEiL0in8LSjmmn",
"instantiation": "true",
"printer_model": "Sovol Zero",
"printer_variant": "1.0HS",
"nozzle_diameter": [
"1.0"
],
"default_filament_profile": [
"Generic PLA @Sovol Zero Hardened Steel nozzle"
],
"nozzle_type": [
"hardened_steel"
]
}
File diff suppressed because one or more lines are too long
@@ -2,11 +2,11 @@
"type": "machine_model", "type": "machine_model",
"name": "Sovol Zero", "name": "Sovol Zero",
"model_id": "Sovol-Zero", "model_id": "Sovol-Zero",
"nozzle_diameter": "0.4", "nozzle_diameter": "0.2;0.4;0.6;0.8;1.0;0.2HS;0.4HS;0.6HS;0.8HS;1.0HS",
"machine_tech": "FFF", "machine_tech": "FFF",
"family": "Sovol", "family": "Sovol",
"bed_model": "sovol_zero_buildplate_model.stl", "bed_model": "sovol_zero_buildplate_model.stl",
"bed_texture": "sovol_zero_buildplate_texture.svg", "bed_texture": "sovol_zero_buildplate_texture.svg",
"hotend_model": "", "hotend_model": "",
"default_materials": "Generic PLA @Sovol Zero;Sovol Zero PLA Basic HS Nozzle;Generic PLA Silk @Sovol Zero;Sovol Zero PLA Silk HS Nozzle;Generic ABS @Sovol Zero;Generic PETG @Sovol Zero;Sovol Zero PETG HS Nozzle;Generic TPU @Sovol Zero;Generic PC @Sovol Zero" "default_materials": "Generic PLA @Sovol Zero;Generic PLA SPEEDBENCHY @Sovol Zero;Generic PLA @Sovol Zero Hardened Steel nozzle;Generic PLA Silk @Sovol Zero;Generic PLA Silk @Sovol Zero Hardened Steel nozzle;Generic ABS @Sovol Zero;Generic PETG @Sovol Zero;Generic PETG @Sovol Zero Hardened Steel nozzle;Generic TPU @Sovol Zero;Generic PC @Sovol Zero"
} }
@@ -0,0 +1,36 @@
{
"type": "process",
"name": "0.06mm Quality @Sovol Zero 0.2 nozzle",
"inherits": "fdm_process_zero",
"from": "system",
"setting_id": "fWP7jaL7sJmmZ6QN",
"instantiation": "true",
"layer_height": "0.06",
"bottom_shell_layers": "8",
"bottom_shell_thickness": "0.8",
"bridge_speed": "30",
"outer_wall_acceleration": "10000",
"top_surface_acceleration": "5000",
"outer_wall_line_width": "0.21",
"line_width": "0.21",
"sparse_infill_density": "15%",
"inner_wall_acceleration": "12000",
"initial_layer_print_height": "0.06",
"initial_layer_line_width": "0.3",
"infill_wall_overlap": "18",
"inner_wall_line_width": "0.22",
"wall_loops": "3",
"internal_solid_infill_line_width": "0.21",
"sparse_infill_line_width": "0.21",
"support_top_z_distance": "0.10",
"support_line_width": "0.21",
"tree_support_tip_diameter": "0.21",
"support_speed": "100",
"top_surface_line_width": "0.21",
"top_shell_layers": "8",
"top_shell_thickness": "1",
"compatible_printers": [
"Sovol Zero 0.2 nozzle",
"Sovol Zero 0.2 Hardened Steel nozzle"
]
}
@@ -0,0 +1,36 @@
{
"type": "process",
"name": "0.10mm Standard @Sovol Zero 0.2 nozzle",
"inherits": "fdm_process_zero",
"from": "system",
"setting_id": "Gql3487jsaTXyuYZ",
"instantiation": "true",
"layer_height": "0.10",
"bottom_shell_layers": "4",
"bottom_shell_thickness": "0.8",
"bridge_speed": "50",
"outer_wall_acceleration": "10000",
"top_surface_acceleration": "5000",
"outer_wall_line_width": "0.22",
"line_width": "0.22",
"sparse_infill_density": "15%",
"inner_wall_acceleration": "12000",
"initial_layer_print_height": "0.12",
"initial_layer_line_width": "0.3",
"infill_wall_overlap": "20",
"inner_wall_line_width": "0.22",
"wall_loops": "2",
"internal_solid_infill_line_width": "0.22",
"sparse_infill_line_width": "0.22",
"support_top_z_distance": "0.20",
"support_line_width": "0.22",
"tree_support_tip_diameter": "0.22",
"support_speed": "100",
"top_surface_line_width": "0.22",
"top_shell_layers": "4",
"top_shell_thickness": "1",
"compatible_printers": [
"Sovol Zero 0.2 nozzle",
"Sovol Zero 0.2 Hardened Steel nozzle"
]
}
@@ -0,0 +1,35 @@
{
"type": "process",
"setting_id": "CaEopiv2Wg6pQJjH",
"name": "0.12mm Quality @Sovol Zero 0.4 nozzle",
"from": "system",
"inherits": "fdm_process_zero",
"instantiation": "true",
"layer_height": "0.12",
"bottom_shell_layers": "8",
"bottom_shell_thickness": "0.8",
"bridge_speed": "30",
"outer_wall_acceleration": "10000",
"top_surface_acceleration": "5000",
"outer_wall_line_width": "0.42",
"line_width": "0.42",
"sparse_infill_density": "15%",
"inner_wall_acceleration": "12000",
"initial_layer_print_height": "0.12",
"initial_layer_line_width": "0.6",
"sparse_infill_line_width": "0.42",
"infill_wall_overlap": "18",
"inner_wall_line_width": "0.44",
"wall_loops": "3",
"support_top_z_distance": "0.10",
"support_line_width": "0.42",
"tree_support_tip_diameter": "0.42",
"support_speed": "100",
"top_surface_line_width": "0.42",
"internal_solid_infill_line_width": "0.42",
"top_shell_layers": "8",
"compatible_printers": [
"Sovol Zero 0.4 nozzle",
"Sovol Zero 0.4 Hardened Steel nozzle"
]
}
@@ -0,0 +1,36 @@
{
"type": "process",
"name": "0.14mm Fast @Sovol Zero 0.2 nozzle",
"inherits": "fdm_process_zero",
"from": "system",
"setting_id": "I9yoyCcGGTRrDoKu",
"instantiation": "true",
"layer_height": "0.14",
"bottom_shell_layers": "3",
"bottom_shell_thickness": "0",
"bridge_speed": "60",
"outer_wall_acceleration": "22000",
"top_surface_acceleration": "22000",
"outer_wall_line_width": "0.24",
"line_width": "0.24",
"sparse_infill_density": "10%",
"inner_wall_acceleration": "28000",
"initial_layer_print_height": "0.14",
"initial_layer_line_width": "0.3",
"infill_wall_overlap": "20",
"inner_wall_line_width": "0.24",
"wall_loops": "2",
"internal_solid_infill_line_width": "0.24",
"sparse_infill_line_width": "0.24",
"support_top_z_distance": "0.30",
"support_line_width": "0.24",
"tree_support_tip_diameter": "0.24",
"support_speed": "120",
"top_surface_line_width": "0.24",
"top_shell_layers": "4",
"top_shell_thickness": "1",
"compatible_printers": [
"Sovol Zero 0.2 nozzle",
"Sovol Zero 0.2 Hardened Steel nozzle"
]
}
@@ -0,0 +1,34 @@
{
"type": "process",
"setting_id": "IfDpa3vM99D4ytny",
"name": "0.15mm Quality @Sovol Zero 0.6 nozzle",
"from": "system",
"inherits": "fdm_process_zero",
"instantiation": "true",
"layer_height": "0.15",
"bottom_shell_layers": "5",
"bottom_shell_thickness": "0.8",
"bridge_speed": "30",
"outer_wall_acceleration": "10000",
"top_surface_acceleration": "5000",
"outer_wall_line_width": "0.63",
"line_width": "0.63",
"sparse_infill_density": "15%",
"inner_wall_acceleration": "12000",
"initial_layer_line_width": "0.9",
"sparse_infill_line_width": "0.63",
"infill_wall_overlap": "18",
"inner_wall_line_width": "0.66",
"wall_loops": "3",
"support_top_z_distance": "0.15",
"support_line_width": "0.63",
"tree_support_tip_diameter": "0.63",
"support_speed": "100",
"top_surface_line_width": "0.63",
"top_shell_layers": "5",
"internal_solid_infill_line_width": "0.63",
"compatible_printers": [
"Sovol Zero 0.6 nozzle",
"Sovol Zero 0.6 Hardened Steel nozzle"
]
}
@@ -0,0 +1,42 @@
{
"type": "process",
"name": "0.20mm Quality @Sovol Zero 0.8 nozzle",
"inherits": "fdm_process_zero",
"from": "system",
"setting_id": "MSxikpQZNYdoBynZ",
"instantiation": "true",
"layer_height": "0.20",
"bottom_shell_layers": "4",
"bottom_shell_thickness": "0.8",
"bridge_speed": "30",
"outer_wall_acceleration": "10000",
"top_surface_acceleration": "5000",
"outer_wall_line_width": "0.84",
"line_width": "0.84",
"sparse_infill_density": "15%",
"inner_wall_acceleration": "12000",
"initial_layer_print_height": "0.36",
"initial_layer_line_width": "1.2",
"sparse_infill_line_width": "0.84",
"infill_wall_overlap": "18",
"inner_wall_line_width": "0.88",
"wall_loops": "3",
"support_top_z_distance": "0.20",
"support_line_width": "0.84",
"tree_support_tip_diameter": "0.84",
"support_speed": "100",
"top_surface_line_width": "0.84",
"top_shell_layers": "4",
"outer_wall_speed": "350",
"inner_wall_speed": "400",
"small_perimeter_speed": "50%",
"internal_solid_infill_speed": "200",
"internal_solid_infill_line_width": "0.84",
"top_surface_speed": "200",
"gap_infill_speed": "200",
"sparse_infill_speed": "500",
"compatible_printers": [
"Sovol Zero 0.8 nozzle",
"Sovol Zero 0.8 Hardened Steel nozzle"
]
}
@@ -1,141 +1,36 @@
{ {
"type": "process", "type": "process",
"name": "0.20mm Standard @Sovol Zero 0.4 nozzle",
"inherits": "fdm_process_common",
"from": "system",
"setting_id": "ShJTVnJ492No1j2j", "setting_id": "ShJTVnJ492No1j2j",
"name": "0.20mm Standard @Sovol Zero 0.4 nozzle",
"from": "system",
"inherits": "fdm_process_zero",
"instantiation": "true", "instantiation": "true",
"reduce_crossing_wall": "1",
"max_travel_detour_distance": "100%",
"layer_height": "0.20", "layer_height": "0.20",
"bottom_surface_pattern": "monotonic", "bottom_shell_layers": "4",
"bottom_shell_layers": "3", "bottom_shell_thickness": "0.8",
"bottom_shell_thickness": "0",
"bridge_flow": "1.2",
"internal_bridge_flow": "1.2",
"bridge_speed": "50", "bridge_speed": "50",
"internal_bridge_speed": "200",
"brim_type": "auto_brim",
"brim_width": "5",
"brim_object_gap": "0",
"compatible_printers_condition": "",
"print_sequence": "by layer",
"default_acceleration": "40000",
"outer_wall_acceleration": "10000", "outer_wall_acceleration": "10000",
"top_surface_acceleration": "5000", "top_surface_acceleration": "5000",
"bridge_no_support": "0", "outer_wall_line_width": "0.44",
"draft_shield": "disabled", "line_width": "0.44",
"elefant_foot_compensation": "0.1", "sparse_infill_density": "15%",
"enable_arc_fitting": "0",
"exclude_object": "1",
"outer_wall_line_width": "0.4",
"wall_infill_order": "inner wall/outer wall/infill",
"line_width": "0.4",
"infill_direction": "45",
"sparse_infill_density": "10%",
"sparse_infill_pattern": "grid",
"internal_solid_infill_acceleration": "50%",
"initial_layer_acceleration": "1000",
"initial_solid_infill_acceleration": "3000",
"travel_acceleration": "40000",
"inner_wall_acceleration": "12000", "inner_wall_acceleration": "12000",
"outer_wall_jerk": "5", "initial_layer_print_height": "0.24",
"inner_wall_jerk": "5", "initial_layer_line_width": "0.6",
"infill_jerk": "5", "sparse_infill_line_width": "0.44",
"top_surface_jerk": "5", "infill_wall_overlap": "20",
"initial_layer_jerk": "5", "ironing_speed": "100",
"travel_jerk": "5", "inner_wall_line_width": "0.44",
"initial_layer_line_width": "0.42",
"initial_layer_print_height": "0.25",
"infill_combination": "0",
"sparse_infill_line_width": "0.45",
"infill_wall_overlap": "15%",
"interface_shells": "0",
"ironing_flow": "15%",
"ironing_spacing": "0.25",
"ironing_speed": "15",
"ironing_type": "no ironing",
"reduce_infill_retraction": "1",
"filename_format": "{printer_model}_{input_filename_base}_{filament_type[0]}_{layer_height}_{print_time}.gcode",
"detect_overhang_wall": "1",
"overhang_1_4_speed": "0",
"overhang_2_4_speed": "50",
"overhang_3_4_speed": "30",
"overhang_4_4_speed": "20",
"inner_wall_line_width": "0.4",
"wall_loops": "2", "wall_loops": "2",
"print_settings_id": "", "support_top_z_distance": "0.20",
"raft_layers": "0", "support_line_width": "0.44",
"seam_position": "aligned", "tree_support_tip_diameter": "0.44",
"skirt_distance": "0.8", "support_speed": "60",
"skirt_height": "1", "top_surface_line_width": "0.44",
"skirt_loops": "1",
"minimum_sparse_infill_area": "15",
"internal_solid_infill_line_width": "0.45",
"spiral_mode": "0",
"standby_temperature_delta": "-5",
"enable_support": "0",
"resolution": "0.012",
"support_type": "tree(auto)",
"support_style": "default",
"support_on_build_plate_only": "0",
"support_top_z_distance": "0.235",
"support_bottom_z_distance": "0.235",
"support_filament": "0",
"support_line_width": "0.45",
"support_interface_loop_pattern": "0",
"support_interface_filament": "0",
"support_interface_top_layers": "5",
"support_interface_bottom_layers": "-1",
"support_interface_spacing": "0.2",
"support_bottom_interface_spacing": "0.2",
"support_interface_speed": "100%",
"support_interface_pattern": "grid",
"support_base_pattern": "rectilinear",
"support_base_pattern_spacing": "3.5",
"support_speed": "100",
"support_threshold_angle": "20",
"support_object_xy_distance": "0.35",
"tree_support_branch_angle": "40",
"tree_support_wall_count": "0",
"detect_thin_wall": "1",
"top_surface_pattern": "monotonic",
"top_surface_line_width": "0.38",
"top_shell_layers": "4", "top_shell_layers": "4",
"top_shell_thickness": "1", "internal_solid_infill_line_width": "0.44",
"initial_layer_speed": "55",
"initial_layer_infill_speed": "105",
"initial_layer_travel_speed": "60%",
"outer_wall_speed": "350",
"inner_wall_speed": "400",
"small_perimeter_speed": "50%",
"internal_solid_infill_speed": "200",
"top_surface_speed": "200",
"gap_infill_speed": "200",
"sparse_infill_speed": "500",
"accel_to_decel_enable": "1",
"accel_to_decel_factor": "25%",
"travel_speed": "1000",
"enable_prime_tower": "1",
"wipe_tower_no_sparse_layers": "0",
"prime_tower_width": "60",
"xy_hole_compensation": "0",
"xy_contour_compensation": "0",
"bridge_acceleration": "50%",
"seam_gap": "10%",
"precise_outer_wall": "1",
"wall_generator": "classic",
"gcode_label_objects": "1",
"slow_down_layers": "3",
"top_solid_infill_flow_ratio": "0.9",
"only_one_wall_top": "1",
"wall_loop_direction": "clockwise",
"top_bottom_infill_wall_overlap": "25%",
"filter_out_gap_fill": "0",
"detect_narrow_internal_solid_infill": "1",
"thick_bridges": "1",
"bridge_angle": "0",
"compatible_printers": [ "compatible_printers": [
"Sovol Zero 0.4 nozzle" "Sovol Zero 0.4 nozzle",
"Sovol Zero 0.4 Hardened Steel nozzle"
] ]
} }
@@ -0,0 +1,79 @@
{
"type": "process",
"name": "0.25mm Quality @Sovol Zero 1.0 nozzle",
"inherits": "fdm_process_zero",
"from": "system",
"setting_id": "JUmnFOoEMJrbWCN9",
"instantiation": "true",
"layer_height": "0.25",
"bottom_shell_layers": "4",
"bottom_shell_thickness": "0.8",
"bridge_speed": "30",
"internal_bridge_speed": "200",
"default_acceleration": "40000",
"outer_wall_acceleration": "10000",
"top_surface_acceleration": "5000",
"outer_wall_line_width": "1.05",
"line_width": "1.05",
"sparse_infill_density": "15%",
"inner_wall_acceleration": "12000",
"initial_layer_print_height": "0.45",
"initial_layer_line_width": "1.5",
"infill_combination": "0",
"sparse_infill_line_width": "1.05",
"infill_wall_overlap": "18",
"interface_shells": "0",
"ironing_flow": "15%",
"ironing_spacing": "0.25",
"ironing_speed": "15",
"ironing_type": "no ironing",
"filename_format": "{input_filename_base}_{nozzle_diameter[0]}n_{filament_type[0]}_{layer_height}_{print_time}.gcode",
"detect_overhang_wall": "1",
"overhang_1_4_speed": "0",
"overhang_2_4_speed": "50",
"overhang_3_4_speed": "30",
"overhang_4_4_speed": "20",
"inner_wall_line_width": "1.1",
"wall_loops": "3",
"print_settings_id": "",
"raft_layers": "0",
"seam_position": "aligned",
"skirt_distance": "0.8",
"skirt_height": "1",
"skirt_loops": "1",
"minimum_sparse_infill_area": "15",
"internal_solid_infill_line_width": "1.05",
"spiral_mode": "0",
"standby_temperature_delta": "-5",
"enable_support": "0",
"resolution": "0.012",
"support_type": "tree(auto)",
"support_style": "snug",
"support_on_build_plate_only": "0",
"support_top_z_distance": "0.25",
"support_bottom_z_distance": "0.235",
"support_filament": "0",
"support_line_width": "1.05",
"tree_support_tip_diameter": "1.05",
"support_interface_loop_pattern": "0",
"support_interface_filament": "0",
"support_interface_top_layers": "5",
"support_interface_bottom_layers": "-1",
"support_interface_spacing": "0.2",
"support_bottom_interface_spacing": "0.2",
"support_interface_speed": "100%",
"support_interface_pattern": "grid",
"support_base_pattern": "rectilinear",
"support_base_pattern_spacing": "3.5",
"support_speed": "100",
"support_threshold_angle": "50",
"support_object_xy_distance": "0.35",
"tree_support_branch_angle": "40",
"top_surface_line_width": "1.05",
"top_shell_layers": "4",
"top_shell_thickness": "1",
"compatible_printers": [
"Sovol Zero 1.0 nozzle",
"Sovol Zero 1.0 Hardened Steel nozzle"
]
}
@@ -0,0 +1,85 @@
{
"type": "process",
"setting_id": "oFrWcSxmad1b6sD4",
"name": "0.25mm SPEEDBENCHY @Sovol Zero 0.4 nozzle",
"from": "system",
"inherits": "fdm_process_zero",
"instantiation": "true",
"layer_height": "0.25",
"initial_layer_print_height": "0.25",
"line_width": "0.5",
"initial_layer_line_width": "0.5",
"outer_wall_line_width": "0.5",
"inner_wall_line_width": "0.5",
"top_surface_line_width": "0.55",
"internal_solid_infill_line_width": "0.55",
"sparse_infill_line_width": "0.55",
"support_line_width": "0.5",
"tree_support_tip_diameter": "0.5",
"wall_loops": "2",
"top_shell_layers": "3",
"bottom_shell_layers": "3",
"bottom_shell_thickness": "0",
"sparse_infill_density": "10%",
"sparse_infill_pattern": "grid",
"bottom_solid_infill_flow_ratio": "1.2",
"top_solid_infill_flow_ratio": "1.4",
"bridge_flow": "1",
"internal_bridge_flow": "1",
"bridge_speed": "250",
"internal_bridge_speed": "250",
"bridge_acceleration": "100%",
"thick_bridges": "0",
"thick_internal_bridges": "0",
"brim_type": "outer_only",
"brim_width": "1",
"brim_object_gap": "0",
"filter_out_gap_fill": "13",
"gap_fill_target": "nowhere",
"min_width_top_surface": "200%",
"minimum_sparse_infill_area": "0",
"infill_direction": "0",
"solid_infill_direction": "0",
"infill_wall_overlap": "15%",
"reduce_crossing_wall": "0",
"skirt_loops": "0",
"only_one_wall_top": "1",
"slow_down_layers": "1",
"wall_direction": "cw",
"initial_layer_speed": "300",
"initial_layer_infill_speed": "300",
"initial_layer_travel_speed": "100%",
"outer_wall_speed": "350",
"inner_wall_speed": "400",
"small_perimeter_speed": "100%",
"internal_solid_infill_speed": "400",
"top_surface_speed": "300",
"gap_infill_speed": "350",
"sparse_infill_speed": "500",
"support_speed": "100",
"travel_speed": "1200",
"default_acceleration": "40000",
"initial_layer_acceleration": "20000",
"outer_wall_acceleration": "40000",
"inner_wall_acceleration": "40000",
"top_surface_acceleration": "20000",
"internal_solid_infill_acceleration": "100%",
"travel_acceleration": "40000",
"accel_to_decel_factor": "50%",
"outer_wall_jerk": "20",
"inner_wall_jerk": "20",
"infill_jerk": "20",
"top_surface_jerk": "20",
"initial_layer_jerk": "20",
"travel_jerk": "20",
"overhang_1_4_speed": "160",
"overhang_2_4_speed": "100",
"overhang_3_4_speed": "60",
"overhang_4_4_speed": "40",
"support_top_z_distance": "0.235",
"support_bottom_z_distance": "0.235",
"compatible_printers": [
"Sovol Zero 0.4 nozzle",
"Sovol Zero 0.4 Hardened Steel nozzle"
]
}
@@ -0,0 +1,39 @@
{
"type": "process",
"name": "0.28mm Fast @Sovol Zero 0.4 nozzle",
"inherits": "fdm_process_zero",
"from": "system",
"setting_id": "1VoML2LGDk4TJgLI",
"instantiation": "true",
"layer_height": "0.28",
"bottom_shell_layers": "3",
"bottom_shell_thickness": "0",
"bridge_speed": "60",
"outer_wall_acceleration": "22000",
"top_surface_acceleration": "22000",
"outer_wall_line_width": "0.48",
"line_width": "0.48",
"sparse_infill_density": "10%",
"inner_wall_acceleration": "28000",
"initial_layer_print_height": "0.28",
"initial_layer_line_width": "0.6",
"sparse_infill_line_width": "0.48",
"inner_wall_line_width": "0.48",
"internal_solid_infill_line_width": "0.48",
"support_top_z_distance": "0.30",
"support_line_width": "0.48",
"tree_support_tip_diameter": "0.48",
"support_speed": "120",
"top_surface_line_width": "0.48",
"outer_wall_speed": "350",
"inner_wall_speed": "400",
"small_perimeter_speed": "50%",
"internal_solid_infill_speed": "200",
"top_surface_speed": "200",
"gap_infill_speed": "200",
"sparse_infill_speed": "500",
"compatible_printers": [
"Sovol Zero 0.4 nozzle",
"Sovol Zero 0.4 Hardened Steel nozzle"
]
}
@@ -0,0 +1,35 @@
{
"type": "process",
"setting_id": "lTAs2USEP8D749K7",
"name": "0.30mm Standard @Sovol Zero 0.6 nozzle",
"from": "system",
"inherits": "fdm_process_zero",
"instantiation": "true",
"layer_height": "0.30",
"bottom_shell_layers": "4",
"bottom_shell_thickness": "0.8",
"bridge_speed": "50",
"outer_wall_acceleration": "10000",
"top_surface_acceleration": "5000",
"outer_wall_line_width": "0.66",
"line_width": "0.66",
"sparse_infill_density": "15%",
"inner_wall_acceleration": "12000",
"initial_layer_print_height": "0.36",
"initial_layer_line_width": "0.9",
"sparse_infill_line_width": "0.66",
"infill_wall_overlap": "20",
"inner_wall_line_width": "0.66",
"wall_loops": "2",
"support_top_z_distance": "0.30",
"support_line_width": "0.66",
"tree_support_tip_diameter": "0.66",
"support_speed": "100",
"top_surface_line_width": "0.66",
"top_shell_layers": "4",
"internal_solid_infill_line_width": "0.66",
"compatible_printers": [
"Sovol Zero 0.6 nozzle",
"Sovol Zero 0.6 Hardened Steel nozzle"
]
}
@@ -0,0 +1,42 @@
{
"type": "process",
"name": "0.40mm Standard @Sovol Zero 0.8 nozzle",
"inherits": "fdm_process_zero",
"from": "system",
"setting_id": "8x4CsuqroC9HOdAN",
"instantiation": "true",
"layer_height": "0.40",
"bottom_shell_layers": "4",
"bottom_shell_thickness": "0.8",
"bridge_speed": "50",
"outer_wall_acceleration": "10000",
"top_surface_acceleration": "5000",
"outer_wall_line_width": "0.88",
"line_width": "0.88",
"sparse_infill_density": "15%",
"inner_wall_acceleration": "12000",
"initial_layer_print_height": "0.48",
"initial_layer_line_width": "1.2",
"sparse_infill_line_width": "0.88",
"infill_wall_overlap": "20",
"inner_wall_line_width": "0.88",
"wall_loops": "2",
"support_top_z_distance": "0.40",
"support_line_width": "0.88",
"tree_support_tip_diameter": "0.88",
"support_speed": "100",
"top_surface_line_width": "0.88",
"top_shell_layers": "4",
"outer_wall_speed": "350",
"inner_wall_speed": "400",
"small_perimeter_speed": "50%",
"internal_solid_infill_speed": "200",
"top_surface_speed": "200",
"gap_infill_speed": "200",
"sparse_infill_speed": "500",
"internal_solid_infill_line_width": "0.88",
"compatible_printers": [
"Sovol Zero 0.8 nozzle",
"Sovol Zero 0.8 Hardened Steel nozzle"
]
}
@@ -0,0 +1,39 @@
{
"type": "process",
"name": "0.42mm Fast @Sovol Zero 0.6 nozzle",
"inherits": "fdm_process_zero",
"from": "system",
"setting_id": "illqJAnGiA2pY0hw",
"instantiation": "true",
"layer_height": "0.42",
"bottom_shell_layers": "3",
"bottom_shell_thickness": "0",
"bridge_speed": "60",
"outer_wall_acceleration": "22000",
"top_surface_acceleration": "22000",
"outer_wall_line_width": "0.72",
"line_width": "0.72",
"sparse_infill_density": "10%",
"inner_wall_acceleration": "28000",
"initial_layer_print_height": "0.42",
"initial_layer_line_width": "0.9",
"sparse_infill_line_width": "0.72",
"inner_wall_line_width": "0.72",
"internal_solid_infill_line_width": "0.72",
"support_top_z_distance": "0.45",
"support_line_width": "0.72",
"tree_support_tip_diameter": "0.72",
"support_speed": "120",
"top_surface_line_width": "0.72",
"outer_wall_speed": "350",
"inner_wall_speed": "400",
"small_perimeter_speed": "50%",
"internal_solid_infill_speed": "200",
"top_surface_speed": "200",
"gap_infill_speed": "200",
"sparse_infill_speed": "500",
"compatible_printers": [
"Sovol Zero 0.6 nozzle",
"Sovol Zero 0.6 Hardened Steel nozzle"
]
}
@@ -0,0 +1,87 @@
{
"type": "process",
"name": "0.50mm Standard @Sovol Zero 1.0 nozzle",
"inherits": "fdm_process_zero",
"from": "system",
"setting_id": "E5K55O4RkMyYCAlt",
"instantiation": "true",
"layer_height": "0.50",
"bottom_shell_layers": "4",
"bottom_shell_thickness": "0.8",
"bridge_speed": "45",
"internal_bridge_speed": "200",
"default_acceleration": "22000",
"outer_wall_acceleration": "16000",
"top_surface_acceleration": "16000",
"outer_wall_line_width": "1.1",
"line_width": "1.1",
"sparse_infill_density": "15%",
"inner_wall_acceleration": "22000",
"initial_layer_print_height": "0.60",
"initial_layer_line_width": "1.5",
"infill_combination": "0",
"sparse_infill_line_width": "1.1",
"infill_wall_overlap": "20",
"interface_shells": "0",
"ironing_flow": "15%",
"ironing_spacing": "0.25",
"ironing_speed": "15",
"ironing_type": "no ironing",
"filename_format": "{input_filename_base}_{nozzle_diameter[0]}n_{filament_type[0]}_{layer_height}_{print_time}.gcode",
"detect_overhang_wall": "1",
"overhang_1_4_speed": "0",
"overhang_2_4_speed": "50",
"overhang_3_4_speed": "30",
"overhang_4_4_speed": "20",
"inner_wall_line_width": "1.1",
"wall_loops": "2",
"print_settings_id": "",
"raft_layers": "0",
"seam_position": "aligned",
"skirt_distance": "0.8",
"skirt_height": "1",
"skirt_loops": "1",
"minimum_sparse_infill_area": "15",
"internal_solid_infill_line_width": "1.1",
"spiral_mode": "0",
"standby_temperature_delta": "-5",
"enable_support": "0",
"resolution": "0.012",
"support_type": "tree(auto)",
"support_style": "snug",
"support_on_build_plate_only": "0",
"support_top_z_distance": "0.50",
"support_bottom_z_distance": "0.235",
"support_filament": "0",
"support_line_width": "1.1",
"tree_support_tip_diameter": "1.1",
"support_interface_loop_pattern": "0",
"support_interface_filament": "0",
"support_interface_top_layers": "5",
"support_interface_bottom_layers": "-1",
"support_interface_spacing": "0.2",
"support_bottom_interface_spacing": "0.2",
"support_interface_speed": "100%",
"support_interface_pattern": "grid",
"support_base_pattern": "rectilinear",
"support_base_pattern_spacing": "3.5",
"support_speed": "60",
"support_threshold_angle": "50",
"support_object_xy_distance": "0.35",
"tree_support_branch_angle": "40",
"top_surface_line_width": "1.1",
"top_shell_layers": "4",
"top_shell_thickness": "1",
"outer_wall_speed": "30",
"inner_wall_speed": "45",
"small_perimeter_speed": "45",
"internal_solid_infill_speed": "45",
"top_surface_speed": "35",
"gap_infill_speed": "35",
"sparse_infill_speed": "70",
"travel_acceleration": "38000",
"compatible_printers": [
"Sovol Zero 1.0 nozzle",
"Sovol Zero 1.0 Hardened Steel nozzle"
]
}
@@ -0,0 +1,40 @@
{
"type": "process",
"name": "0.56mm Fast @Sovol Zero 0.8 nozzle",
"inherits": "fdm_process_zero",
"from": "system",
"setting_id": "g9PPRM4FLMwjMUfy",
"instantiation": "true",
"layer_height": "0.56",
"bottom_shell_layers": "3",
"bottom_shell_thickness": "0",
"bridge_speed": "60",
"default_acceleration": "28000",
"outer_wall_acceleration": "22000",
"top_surface_acceleration": "22000",
"outer_wall_line_width": "0.96",
"line_width": "0.96",
"sparse_infill_density": "10%",
"inner_wall_acceleration": "28000",
"initial_layer_print_height": "0.56",
"initial_layer_line_width": "1.2",
"sparse_infill_line_width": "0.96",
"inner_wall_line_width": "0.96",
"internal_solid_infill_line_width": "0.96",
"support_top_z_distance": "0.60",
"support_line_width": "0.96",
"tree_support_tip_diameter": "0.96",
"top_surface_line_width": "0.96",
"top_shell_layers": "4",
"outer_wall_speed": "35",
"inner_wall_speed": "55",
"small_perimeter_speed": "60",
"internal_solid_infill_speed": "55",
"top_surface_speed": "40",
"gap_infill_speed": "40",
"sparse_infill_speed": "80",
"compatible_printers": [
"Sovol Zero 0.8 nozzle",
"Sovol Zero 0.8 Hardened Steel nozzle"
]
}
@@ -0,0 +1,33 @@
{
"type": "process",
"name": "0.70mm Fast @Sovol Zero 1.0 nozzle",
"inherits": "fdm_process_zero",
"from": "system",
"setting_id": "fW5KJBVndgQE868q",
"instantiation": "true",
"layer_height": "0.70",
"bottom_shell_layers": "3",
"bottom_shell_thickness": "0",
"bridge_speed": "60",
"outer_wall_acceleration": "22000",
"top_surface_acceleration": "22000",
"outer_wall_line_width": "1.2",
"line_width": "1.2",
"sparse_infill_density": "10%",
"inner_wall_acceleration": "28000",
"initial_layer_print_height": "0.70",
"initial_layer_line_width": "1.5",
"sparse_infill_line_width": "1.2",
"inner_wall_line_width": "1.2",
"internal_solid_infill_line_width": "1.2",
"support_top_z_distance": "0.75",
"support_line_width": "1.2",
"tree_support_tip_diameter": "1.2",
"support_speed": "120",
"top_surface_line_width": "1.2",
"top_shell_layers": "3",
"compatible_printers": [
"Sovol Zero 1.0 nozzle",
"Sovol Zero 1.0 Hardened Steel nozzle"
]
}
@@ -0,0 +1,73 @@
{
"type": "process",
"name": "fdm_process_zero",
"inherits": "fdm_process_common",
"from": "system",
"instantiation": "false",
"reduce_crossing_wall": "1",
"max_travel_detour_distance": "10",
"bottom_surface_pattern": "monotonic",
"bridge_flow": "1.2",
"internal_bridge_flow": "1.2",
"brim_type": "auto_brim",
"brim_width": "5",
"brim_object_gap": "0",
"print_sequence": "by layer",
"bridge_no_support": "0",
"draft_shield": "disabled",
"elefant_foot_compensation": "0.1",
"enable_arc_fitting": "0",
"exclude_object": "1",
"wall_infill_order": "inner wall/outer wall/infill",
"infill_direction": "45",
"sparse_infill_pattern": "grid",
"internal_solid_infill_acceleration": "50%",
"initial_layer_acceleration": "1000",
"travel_acceleration": "40000",
"outer_wall_jerk": "5",
"inner_wall_jerk": "5",
"infill_jerk": "5",
"top_surface_jerk": "5",
"initial_layer_jerk": "5",
"travel_jerk": "5",
"tree_support_wall_count": "0",
"reduce_infill_retraction": "1",
"detect_thin_wall": "1",
"top_surface_pattern": "monotonic",
"initial_layer_speed": "55",
"initial_layer_infill_speed": "105",
"initial_layer_travel_speed": "60%",
"outer_wall_speed": "350",
"inner_wall_speed": "400",
"small_perimeter_speed": "50%",
"internal_solid_infill_speed": "200",
"top_surface_speed": "200",
"gap_infill_speed": "200",
"sparse_infill_speed": "500",
"accel_to_decel_enable": "1",
"accel_to_decel_factor": "25%",
"travel_speed": "1000",
"enable_prime_tower": "0",
"wipe_tower_no_sparse_layers": "0",
"prime_tower_width": "60",
"xy_hole_compensation": "0",
"xy_contour_compensation": "0",
"bridge_acceleration": "50%",
"seam_gap": "10%",
"precise_outer_wall": "1",
"wall_generator": "classic",
"gcode_label_objects": "1",
"slow_down_layers": "3",
"top_solid_infill_flow_ratio": "0.9",
"only_one_wall_top": "1",
"top_bottom_infill_wall_overlap": "25%",
"filter_out_gap_fill": "0",
"detect_narrow_internal_solid_infill": "1",
"thick_bridges": "1",
"bridge_angle": "0",
"initial_layer_line_width": "150%",
"default_acceleration": "40000",
"compatible_printers": [],
"internal_bridge_speed": "150",
"filename_format": "{input_filename_base}_{nozzle_diameter[0]}n_{filament_type[0]}_{layer_height}_{print_time}.gcode"
}
+137 -1
View File
@@ -1,12 +1,60 @@
{ {
"name": "Wanhao", "name": "Wanhao",
"version": "02.04.00.02", "version": "02.04.00.03",
"force_update": "0", "force_update": "0",
"description": "Wanhao configurations", "description": "Wanhao configurations",
"machine_model_list": [ "machine_model_list": [
{ {
"name": "Wanhao D12-300", "name": "Wanhao D12-300",
"sub_path": "machine/Wanhao D12-300.json" "sub_path": "machine/Wanhao D12-300.json"
},
{
"name": "Wanhao D9-300 MK1",
"sub_path": "machine/Wanhao D9-300 MK1.json"
},
{
"name": "Wanhao D9-300 MK1 BLTouch kit",
"sub_path": "machine/Wanhao D9-300 MK1 BLTouch kit.json"
},
{
"name": "Wanhao D9-300 MK2",
"sub_path": "machine/Wanhao D9-300 MK2.json"
},
{
"name": "Wanhao D9-300 MK3",
"sub_path": "machine/Wanhao D9-300 MK3.json"
},
{
"name": "Wanhao D9-400 MK1",
"sub_path": "machine/Wanhao D9-400 MK1.json"
},
{
"name": "Wanhao D9-400 MK1 BLTouch kit",
"sub_path": "machine/Wanhao D9-400 MK1 BLTouch kit.json"
},
{
"name": "Wanhao D9-400 MK2",
"sub_path": "machine/Wanhao D9-400 MK2.json"
},
{
"name": "Wanhao D9-400 MK3",
"sub_path": "machine/Wanhao D9-400 MK3.json"
},
{
"name": "Wanhao D9-500 MK1",
"sub_path": "machine/Wanhao D9-500 MK1.json"
},
{
"name": "Wanhao D9-500 MK1 BLTouch kit",
"sub_path": "machine/Wanhao D9-500 MK1 BLTouch kit.json"
},
{
"name": "Wanhao D9-500 MK2",
"sub_path": "machine/Wanhao D9-500 MK2.json"
},
{
"name": "Wanhao D9-500 MK3",
"sub_path": "machine/Wanhao D9-500 MK3.json"
} }
], ],
"process_list": [ "process_list": [
@@ -33,6 +81,38 @@
{ {
"name": "0.24mm Draft @Wanhao D12-300", "name": "0.24mm Draft @Wanhao D12-300",
"sub_path": "process/0.24mm Draft @Wanhao D12-300.json" "sub_path": "process/0.24mm Draft @Wanhao D12-300.json"
},
{
"name": "fdm_process_wanhao_d9_common",
"sub_path": "process/fdm_process_wanhao_d9_common.json"
},
{
"name": "0.12mm Fine @Wanhao D9",
"sub_path": "process/0.12mm Fine @Wanhao D9.json"
},
{
"name": "0.20mm Standard @Wanhao D9",
"sub_path": "process/0.20mm Standard @Wanhao D9.json"
},
{
"name": "0.28mm Draft @Wanhao D9",
"sub_path": "process/0.28mm Draft @Wanhao D9.json"
},
{
"name": "fdm_process_wanhao_d9_mk1_common",
"sub_path": "process/fdm_process_wanhao_d9_mk1_common.json"
},
{
"name": "0.12mm Fine @Wanhao D9 MK1",
"sub_path": "process/0.12mm Fine @Wanhao D9 MK1.json"
},
{
"name": "0.20mm Standard @Wanhao D9 MK1",
"sub_path": "process/0.20mm Standard @Wanhao D9 MK1.json"
},
{
"name": "0.28mm Draft @Wanhao D9 MK1",
"sub_path": "process/0.28mm Draft @Wanhao D9 MK1.json"
} }
], ],
"filament_list": [], "filament_list": [],
@@ -48,6 +128,62 @@
{ {
"name": "Wanhao D12-300 0.4 nozzle", "name": "Wanhao D12-300 0.4 nozzle",
"sub_path": "machine/Wanhao D12-300 0.4 nozzle.json" "sub_path": "machine/Wanhao D12-300 0.4 nozzle.json"
},
{
"name": "fdm_wanhao_d9_common",
"sub_path": "machine/fdm_wanhao_d9_common.json"
},
{
"name": "Wanhao D9-300 MK1 BLTouch kit 0.4 nozzle",
"sub_path": "machine/Wanhao D9-300 MK1 BLTouch kit 0.4 nozzle.json"
},
{
"name": "Wanhao D9-300 MK2 0.4 nozzle",
"sub_path": "machine/Wanhao D9-300 MK2 0.4 nozzle.json"
},
{
"name": "Wanhao D9-300 MK3 0.4 nozzle",
"sub_path": "machine/Wanhao D9-300 MK3 0.4 nozzle.json"
},
{
"name": "Wanhao D9-400 MK1 BLTouch kit 0.4 nozzle",
"sub_path": "machine/Wanhao D9-400 MK1 BLTouch kit 0.4 nozzle.json"
},
{
"name": "Wanhao D9-400 MK2 0.4 nozzle",
"sub_path": "machine/Wanhao D9-400 MK2 0.4 nozzle.json"
},
{
"name": "Wanhao D9-400 MK3 0.4 nozzle",
"sub_path": "machine/Wanhao D9-400 MK3 0.4 nozzle.json"
},
{
"name": "Wanhao D9-500 MK1 BLTouch kit 0.4 nozzle",
"sub_path": "machine/Wanhao D9-500 MK1 BLTouch kit 0.4 nozzle.json"
},
{
"name": "Wanhao D9-500 MK2 0.4 nozzle",
"sub_path": "machine/Wanhao D9-500 MK2 0.4 nozzle.json"
},
{
"name": "Wanhao D9-500 MK3 0.4 nozzle",
"sub_path": "machine/Wanhao D9-500 MK3 0.4 nozzle.json"
},
{
"name": "fdm_wanhao_d9_mk1_common",
"sub_path": "machine/fdm_wanhao_d9_mk1_common.json"
},
{
"name": "Wanhao D9-300 MK1 0.4 nozzle",
"sub_path": "machine/Wanhao D9-300 MK1 0.4 nozzle.json"
},
{
"name": "Wanhao D9-400 MK1 0.4 nozzle",
"sub_path": "machine/Wanhao D9-400 MK1 0.4 nozzle.json"
},
{
"name": "Wanhao D9-500 MK1 0.4 nozzle",
"sub_path": "machine/Wanhao D9-500 MK1 0.4 nozzle.json"
} }
] ]
} }
@@ -0,0 +1,20 @@
{
"type": "machine",
"name": "Wanhao D9-300 MK1 0.4 nozzle",
"inherits": "fdm_wanhao_d9_mk1_common",
"from": "system",
"setting_id": "MXNRpMDaVXj2xUx0",
"instantiation": "true",
"printer_model": "Wanhao D9-300 MK1",
"nozzle_diameter": [
"0.4"
],
"printable_area": [
"0x0",
"300x0",
"300x300",
"0x300"
],
"printable_height": "400",
"default_print_profile": "0.20mm Standard @Wanhao D9 MK1"
}
@@ -0,0 +1,20 @@
{
"type": "machine",
"name": "Wanhao D9-300 MK1 BLTouch kit 0.4 nozzle",
"inherits": "fdm_wanhao_d9_common",
"from": "system",
"setting_id": "rq6cPs92KgrUyZrn",
"instantiation": "true",
"printer_model": "Wanhao D9-300 MK1 BLTouch kit",
"nozzle_diameter": [
"0.4"
],
"printable_area": [
"0x0",
"300x0",
"300x300",
"0x300"
],
"printable_height": "400",
"default_print_profile": "0.20mm Standard @Wanhao D9"
}
@@ -0,0 +1,9 @@
{
"type": "machine_model",
"name": "Wanhao D9-300 MK1 BLTouch kit",
"model_id": "Wanhao-D9-300-MK1u2",
"nozzle_diameter": "0.4",
"machine_tech": "FFF",
"family": "Wanhao",
"default_materials": "Generic PLA @System;Generic PETG @System;Generic ABS @System"
}
@@ -0,0 +1,9 @@
{
"type": "machine_model",
"name": "Wanhao D9-300 MK1",
"model_id": "Wanhao-D9-300-MK1",
"nozzle_diameter": "0.4",
"machine_tech": "FFF",
"family": "Wanhao",
"default_materials": "Generic PLA @System;Generic PETG @System;Generic ABS @System"
}
@@ -0,0 +1,20 @@
{
"type": "machine",
"name": "Wanhao D9-300 MK2 0.4 nozzle",
"inherits": "fdm_wanhao_d9_common",
"from": "system",
"setting_id": "w3Cin9es1Jfx0dmR",
"instantiation": "true",
"printer_model": "Wanhao D9-300 MK2",
"nozzle_diameter": [
"0.4"
],
"printable_area": [
"0x0",
"300x0",
"300x300",
"0x300"
],
"printable_height": "400",
"default_print_profile": "0.20mm Standard @Wanhao D9"
}
@@ -0,0 +1,9 @@
{
"type": "machine_model",
"name": "Wanhao D9-300 MK2",
"model_id": "Wanhao-D9-300-MK2",
"nozzle_diameter": "0.4",
"machine_tech": "FFF",
"family": "Wanhao",
"default_materials": "Generic PLA @System;Generic PETG @System;Generic ABS @System"
}
@@ -0,0 +1,20 @@
{
"type": "machine",
"name": "Wanhao D9-300 MK3 0.4 nozzle",
"inherits": "fdm_wanhao_d9_common",
"from": "system",
"setting_id": "acFQWZqlt4QSgBPv",
"instantiation": "true",
"printer_model": "Wanhao D9-300 MK3",
"nozzle_diameter": [
"0.4"
],
"printable_area": [
"0x0",
"300x0",
"300x300",
"0x300"
],
"printable_height": "400",
"default_print_profile": "0.20mm Standard @Wanhao D9"
}
@@ -0,0 +1,9 @@
{
"type": "machine_model",
"name": "Wanhao D9-300 MK3",
"model_id": "Wanhao-D9-300-MK3",
"nozzle_diameter": "0.4",
"machine_tech": "FFF",
"family": "Wanhao",
"default_materials": "Generic PLA @System;Generic PETG @System;Generic ABS @System"
}
@@ -0,0 +1,20 @@
{
"type": "machine",
"name": "Wanhao D9-400 MK1 0.4 nozzle",
"inherits": "fdm_wanhao_d9_mk1_common",
"from": "system",
"setting_id": "DGSNE3AbmlBBG5PY",
"instantiation": "true",
"printer_model": "Wanhao D9-400 MK1",
"nozzle_diameter": [
"0.4"
],
"printable_area": [
"0x0",
"400x0",
"400x400",
"0x400"
],
"printable_height": "400",
"default_print_profile": "0.20mm Standard @Wanhao D9 MK1"
}
@@ -0,0 +1,20 @@
{
"type": "machine",
"name": "Wanhao D9-400 MK1 BLTouch kit 0.4 nozzle",
"inherits": "fdm_wanhao_d9_common",
"from": "system",
"setting_id": "WcKY7v24ewtzPfnU",
"instantiation": "true",
"printer_model": "Wanhao D9-400 MK1 BLTouch kit",
"nozzle_diameter": [
"0.4"
],
"printable_area": [
"0x0",
"400x0",
"400x400",
"0x400"
],
"printable_height": "400",
"default_print_profile": "0.20mm Standard @Wanhao D9"
}
@@ -0,0 +1,9 @@
{
"type": "machine_model",
"name": "Wanhao D9-400 MK1 BLTouch kit",
"model_id": "Wanhao-D9-400-MK1u2",
"nozzle_diameter": "0.4",
"machine_tech": "FFF",
"family": "Wanhao",
"default_materials": "Generic PLA @System;Generic PETG @System;Generic ABS @System"
}
@@ -0,0 +1,9 @@
{
"type": "machine_model",
"name": "Wanhao D9-400 MK1",
"model_id": "Wanhao-D9-400-MK1",
"nozzle_diameter": "0.4",
"machine_tech": "FFF",
"family": "Wanhao",
"default_materials": "Generic PLA @System;Generic PETG @System;Generic ABS @System"
}
@@ -0,0 +1,20 @@
{
"type": "machine",
"name": "Wanhao D9-400 MK2 0.4 nozzle",
"inherits": "fdm_wanhao_d9_common",
"from": "system",
"setting_id": "jn1FEJFeN7S2gEbD",
"instantiation": "true",
"printer_model": "Wanhao D9-400 MK2",
"nozzle_diameter": [
"0.4"
],
"printable_area": [
"0x0",
"400x0",
"400x400",
"0x400"
],
"printable_height": "400",
"default_print_profile": "0.20mm Standard @Wanhao D9"
}
@@ -0,0 +1,9 @@
{
"type": "machine_model",
"name": "Wanhao D9-400 MK2",
"model_id": "Wanhao-D9-400-MK2",
"nozzle_diameter": "0.4",
"machine_tech": "FFF",
"family": "Wanhao",
"default_materials": "Generic PLA @System;Generic PETG @System;Generic ABS @System"
}
@@ -0,0 +1,20 @@
{
"type": "machine",
"name": "Wanhao D9-400 MK3 0.4 nozzle",
"inherits": "fdm_wanhao_d9_common",
"from": "system",
"setting_id": "2kFyH1E3tqMWtDmG",
"instantiation": "true",
"printer_model": "Wanhao D9-400 MK3",
"nozzle_diameter": [
"0.4"
],
"printable_area": [
"0x0",
"400x0",
"400x400",
"0x400"
],
"printable_height": "400",
"default_print_profile": "0.20mm Standard @Wanhao D9"
}
@@ -0,0 +1,9 @@
{
"type": "machine_model",
"name": "Wanhao D9-400 MK3",
"model_id": "Wanhao-D9-400-MK3",
"nozzle_diameter": "0.4",
"machine_tech": "FFF",
"family": "Wanhao",
"default_materials": "Generic PLA @System;Generic PETG @System;Generic ABS @System"
}
@@ -0,0 +1,20 @@
{
"type": "machine",
"name": "Wanhao D9-500 MK1 0.4 nozzle",
"inherits": "fdm_wanhao_d9_mk1_common",
"from": "system",
"setting_id": "nj0TfnDKHb4wFX1R",
"instantiation": "true",
"printer_model": "Wanhao D9-500 MK1",
"nozzle_diameter": [
"0.4"
],
"printable_area": [
"0x0",
"500x0",
"500x500",
"0x500"
],
"printable_height": "500",
"default_print_profile": "0.20mm Standard @Wanhao D9 MK1"
}
@@ -0,0 +1,20 @@
{
"type": "machine",
"name": "Wanhao D9-500 MK1 BLTouch kit 0.4 nozzle",
"inherits": "fdm_wanhao_d9_common",
"from": "system",
"setting_id": "Hmrnlh6pJzdO2dIJ",
"instantiation": "true",
"printer_model": "Wanhao D9-500 MK1 BLTouch kit",
"nozzle_diameter": [
"0.4"
],
"printable_area": [
"0x0",
"500x0",
"500x500",
"0x500"
],
"printable_height": "500",
"default_print_profile": "0.20mm Standard @Wanhao D9"
}
@@ -0,0 +1,9 @@
{
"type": "machine_model",
"name": "Wanhao D9-500 MK1 BLTouch kit",
"model_id": "Wanhao-D9-500-MK1u2",
"nozzle_diameter": "0.4",
"machine_tech": "FFF",
"family": "Wanhao",
"default_materials": "Generic PLA @System;Generic PETG @System;Generic ABS @System"
}
@@ -0,0 +1,9 @@
{
"type": "machine_model",
"name": "Wanhao D9-500 MK1",
"model_id": "Wanhao-D9-500-MK1",
"nozzle_diameter": "0.4",
"machine_tech": "FFF",
"family": "Wanhao",
"default_materials": "Generic PLA @System;Generic PETG @System;Generic ABS @System"
}
@@ -0,0 +1,20 @@
{
"type": "machine",
"name": "Wanhao D9-500 MK2 0.4 nozzle",
"inherits": "fdm_wanhao_d9_common",
"from": "system",
"setting_id": "g2GSmhWJLFDwqzFI",
"instantiation": "true",
"printer_model": "Wanhao D9-500 MK2",
"nozzle_diameter": [
"0.4"
],
"printable_area": [
"0x0",
"500x0",
"500x500",
"0x500"
],
"printable_height": "500",
"default_print_profile": "0.20mm Standard @Wanhao D9"
}
@@ -0,0 +1,9 @@
{
"type": "machine_model",
"name": "Wanhao D9-500 MK2",
"model_id": "Wanhao-D9-500-MK2",
"nozzle_diameter": "0.4",
"machine_tech": "FFF",
"family": "Wanhao",
"default_materials": "Generic PLA @System;Generic PETG @System;Generic ABS @System"
}
@@ -0,0 +1,20 @@
{
"type": "machine",
"name": "Wanhao D9-500 MK3 0.4 nozzle",
"inherits": "fdm_wanhao_d9_common",
"from": "system",
"setting_id": "F7l90Rgr8Ni0sQva",
"instantiation": "true",
"printer_model": "Wanhao D9-500 MK3",
"nozzle_diameter": [
"0.4"
],
"printable_area": [
"0x0",
"500x0",
"500x500",
"0x500"
],
"printable_height": "500",
"default_print_profile": "0.20mm Standard @Wanhao D9"
}
@@ -0,0 +1,9 @@
{
"type": "machine_model",
"name": "Wanhao D9-500 MK3",
"model_id": "Wanhao-D9-500-MK3",
"nozzle_diameter": "0.4",
"machine_tech": "FFF",
"family": "Wanhao",
"default_materials": "Generic PLA @System;Generic PETG @System;Generic ABS @System"
}
@@ -0,0 +1,108 @@
{
"type": "machine",
"name": "fdm_wanhao_d9_common",
"inherits": "fdm_wanhao_common",
"from": "system",
"instantiation": "false",
"gcode_flavor": "marlin2",
"use_relative_e_distances": "1",
"emit_machine_limits_to_gcode": "0",
"nozzle_diameter": [
"0.4"
],
"printer_variant": "0.4",
"max_layer_height": [
"0.32"
],
"min_layer_height": [
"0.08"
],
"machine_max_speed_x": [
"300",
"300"
],
"machine_max_speed_y": [
"300",
"300"
],
"machine_max_speed_z": [
"5",
"5"
],
"machine_max_speed_e": [
"25",
"25"
],
"machine_max_acceleration_x": [
"3000",
"3000"
],
"machine_max_acceleration_y": [
"3000",
"3000"
],
"machine_max_acceleration_z": [
"100",
"100"
],
"machine_max_acceleration_e": [
"3000",
"3000"
],
"machine_max_acceleration_extruding": [
"1000",
"1000"
],
"machine_max_acceleration_travel": [
"1000",
"1000"
],
"machine_max_acceleration_retracting": [
"800",
"800"
],
"machine_max_jerk_x": [
"10",
"10"
],
"machine_max_jerk_y": [
"10",
"10"
],
"machine_max_jerk_z": [
"0.4",
"0.4"
],
"machine_max_jerk_e": [
"1",
"1"
],
"retraction_length": [
"2.0"
],
"retraction_speed": [
"25"
],
"deretraction_speed": [
"25"
],
"retraction_minimum_travel": [
"1"
],
"z_hop": [
"0"
],
"wipe": [
"0"
],
"retract_when_changing_layer": [
"1"
],
"machine_start_gcode": "; Wanhao Duplicator 9 start G-code, for the Marlin 2.1 firmwares at github.com/Le-Syl21/WANHAO-Duplicator-9\nG21 ; millimetres\nG90 ; absolute coordinates\nM83 ; relative extrusion\nM140 S[bed_temperature_initial_layer_single] ; heat the bed\nM104 S150 ; warm the nozzle without letting it ooze\nG91 ; a print stopped by hand can leave the nozzle down on the bed\nG1 Z10 F300 ; so raise it before homing: a BLTouch needs 10 mm to deploy\nG90\nM280 P0 S160 ; BLTouch: clear an alarm and stow the pin\nG28 ; home all axes (this turns bed levelling off)\nM420 S1 ; turn the bed mesh saved from the screen back on\nG1 Z10 F300\nM104 S[nozzle_temperature_initial_layer] ; start the nozzle now, the bed is still heating\nM190 S[bed_temperature_initial_layer_single] ; wait for the bed\nM109 S[nozzle_temperature_initial_layer] ; and confirm the nozzle\nG92 E0\nG1 X15 Y20 Z0.3 F3000 ; start of the priming line\nG1 Y140 E9.0 F1200 ; draw a line of filament\nG1 X15.5 F3000\nG1 Y20 E9.0 F1200 ; and back, next to it\nG92 E0\nG1 X22 F6000 ; wipe sideways to snap the string\nG1 Z2 F300 ; lift, so the line does not stick to the nozzle",
"machine_end_gcode": "; Wanhao Duplicator 9 end G-code\nM104 S0 ; nozzle heater off\nM140 S0 ; bed heater off\nM107 ; fan off\nG91 ; relative moves\nG1 E-2 F1500 ; release the pressure in the nozzle\nG1 Z10 F300 ; lift the nozzle\nG90 ; absolute moves\nG1 X5 Y{print_bed_max[1] - 10} F3000 ; bring the bed to the front\nM84 X Y E ; motors off, Z keeps its position",
"layer_change_gcode": "G92 E0",
"machine_pause_gcode": "M600",
"default_filament_profile": [
"Generic PLA @System"
]
}
@@ -0,0 +1,28 @@
{
"type": "machine",
"name": "fdm_wanhao_d9_mk1_common",
"inherits": "fdm_wanhao_d9_common",
"from": "system",
"instantiation": "false",
"machine_start_gcode": "; Wanhao Duplicator 9 start G-code, for the Marlin 2.1 firmwares at github.com/Le-Syl21/WANHAO-Duplicator-9\nG21 ; millimetres\nG90 ; absolute coordinates\nM83 ; relative extrusion\nM140 S[bed_temperature_initial_layer_single] ; heat the bed\nM104 S150 ; warm the nozzle without letting it ooze\nG91 ; a print stopped by hand can leave the nozzle down on the bed\nG1 Z10 F300 ; clear the bed before homing\nG90\nG28 ; home all axes (this turns bed levelling off)\nM420 S1 ; turn the bed mesh saved from the screen back on\nG1 Z10 F300\nM104 S[nozzle_temperature_initial_layer] ; start the nozzle now, the bed is still heating\nM190 S[bed_temperature_initial_layer_single] ; wait for the bed\nM109 S[nozzle_temperature_initial_layer] ; and confirm the nozzle\nG92 E0\nG1 X15 Y20 Z0.3 F3000 ; start of the priming line\nG1 Y140 E9.0 F1200 ; draw a line of filament\nG1 X15.5 F3000\nG1 Y20 E9.0 F1200 ; and back, next to it\nG92 E0\nG1 X22 F6000 ; wipe sideways to snap the string\nG1 Z2 F300 ; lift, so the line does not stick to the nozzle",
"machine_max_acceleration_x": [
"500",
"500"
],
"machine_max_acceleration_y": [
"500",
"500"
],
"machine_max_acceleration_e": [
"500",
"500"
],
"machine_max_acceleration_extruding": [
"500",
"500"
],
"machine_max_acceleration_travel": [
"500",
"500"
]
}
@@ -0,0 +1,17 @@
{
"type": "process",
"name": "0.12mm Fine @Wanhao D9 MK1",
"inherits": "fdm_process_wanhao_d9_mk1_common",
"from": "system",
"setting_id": "EClNN5UDWbLACTuz",
"instantiation": "true",
"layer_height": "0.12",
"initial_layer_print_height": "0.14",
"top_shell_layers": "4",
"bottom_shell_layers": "4",
"compatible_printers": [
"Wanhao D9-300 MK1 0.4 nozzle",
"Wanhao D9-400 MK1 0.4 nozzle",
"Wanhao D9-500 MK1 0.4 nozzle"
]
}
@@ -0,0 +1,23 @@
{
"type": "process",
"name": "0.12mm Fine @Wanhao D9",
"inherits": "fdm_process_wanhao_d9_common",
"from": "system",
"setting_id": "0hvsKsPO55TlduZR",
"instantiation": "true",
"layer_height": "0.12",
"initial_layer_print_height": "0.14",
"top_shell_layers": "4",
"bottom_shell_layers": "4",
"compatible_printers": [
"Wanhao D9-300 MK1 BLTouch kit 0.4 nozzle",
"Wanhao D9-400 MK1 BLTouch kit 0.4 nozzle",
"Wanhao D9-500 MK1 BLTouch kit 0.4 nozzle",
"Wanhao D9-300 MK2 0.4 nozzle",
"Wanhao D9-400 MK2 0.4 nozzle",
"Wanhao D9-500 MK2 0.4 nozzle",
"Wanhao D9-300 MK3 0.4 nozzle",
"Wanhao D9-400 MK3 0.4 nozzle",
"Wanhao D9-500 MK3 0.4 nozzle"
]
}
@@ -0,0 +1,17 @@
{
"type": "process",
"name": "0.20mm Standard @Wanhao D9 MK1",
"inherits": "fdm_process_wanhao_d9_mk1_common",
"from": "system",
"setting_id": "CXNOj3tPeTUXx81B",
"instantiation": "true",
"layer_height": "0.20",
"initial_layer_print_height": "0.24",
"top_shell_layers": "3",
"bottom_shell_layers": "3",
"compatible_printers": [
"Wanhao D9-300 MK1 0.4 nozzle",
"Wanhao D9-400 MK1 0.4 nozzle",
"Wanhao D9-500 MK1 0.4 nozzle"
]
}
@@ -0,0 +1,23 @@
{
"type": "process",
"name": "0.20mm Standard @Wanhao D9",
"inherits": "fdm_process_wanhao_d9_common",
"from": "system",
"setting_id": "UVXxknNxJswqaURQ",
"instantiation": "true",
"layer_height": "0.20",
"initial_layer_print_height": "0.24",
"top_shell_layers": "3",
"bottom_shell_layers": "3",
"compatible_printers": [
"Wanhao D9-300 MK1 BLTouch kit 0.4 nozzle",
"Wanhao D9-400 MK1 BLTouch kit 0.4 nozzle",
"Wanhao D9-500 MK1 BLTouch kit 0.4 nozzle",
"Wanhao D9-300 MK2 0.4 nozzle",
"Wanhao D9-400 MK2 0.4 nozzle",
"Wanhao D9-500 MK2 0.4 nozzle",
"Wanhao D9-300 MK3 0.4 nozzle",
"Wanhao D9-400 MK3 0.4 nozzle",
"Wanhao D9-500 MK3 0.4 nozzle"
]
}
@@ -0,0 +1,17 @@
{
"type": "process",
"name": "0.28mm Draft @Wanhao D9 MK1",
"inherits": "fdm_process_wanhao_d9_mk1_common",
"from": "system",
"setting_id": "omfIWwVnQVVxPrtb",
"instantiation": "true",
"layer_height": "0.28",
"initial_layer_print_height": "0.34",
"top_shell_layers": "3",
"bottom_shell_layers": "3",
"compatible_printers": [
"Wanhao D9-300 MK1 0.4 nozzle",
"Wanhao D9-400 MK1 0.4 nozzle",
"Wanhao D9-500 MK1 0.4 nozzle"
]
}
@@ -0,0 +1,23 @@
{
"type": "process",
"name": "0.28mm Draft @Wanhao D9",
"inherits": "fdm_process_wanhao_d9_common",
"from": "system",
"setting_id": "FEJqq1ylXWqaBPR6",
"instantiation": "true",
"layer_height": "0.28",
"initial_layer_print_height": "0.34",
"top_shell_layers": "3",
"bottom_shell_layers": "3",
"compatible_printers": [
"Wanhao D9-300 MK1 BLTouch kit 0.4 nozzle",
"Wanhao D9-400 MK1 BLTouch kit 0.4 nozzle",
"Wanhao D9-500 MK1 BLTouch kit 0.4 nozzle",
"Wanhao D9-300 MK2 0.4 nozzle",
"Wanhao D9-400 MK2 0.4 nozzle",
"Wanhao D9-500 MK2 0.4 nozzle",
"Wanhao D9-300 MK3 0.4 nozzle",
"Wanhao D9-400 MK3 0.4 nozzle",
"Wanhao D9-500 MK3 0.4 nozzle"
]
}
@@ -0,0 +1,38 @@
{
"type": "process",
"name": "fdm_process_wanhao_d9_common",
"inherits": "fdm_process_wanhao_common",
"from": "system",
"instantiation": "false",
"line_width": "0.4",
"initial_layer_line_width": "0.6",
"wall_loops": "2",
"infill_wall_overlap": "15%",
"sparse_infill_density": "15%",
"sparse_infill_pattern": "gyroid",
"outer_wall_speed": "25",
"inner_wall_speed": "40",
"sparse_infill_speed": "50",
"internal_solid_infill_speed": "50",
"top_surface_speed": "40",
"gap_infill_speed": "40",
"bridge_speed": "50",
"support_speed": "35",
"initial_layer_speed": "25",
"initial_layer_infill_speed": "25",
"travel_speed": "100",
"default_acceleration": "1000",
"outer_wall_acceleration": "1000",
"inner_wall_acceleration": "1000",
"top_surface_acceleration": "1000",
"sparse_infill_acceleration": "1000",
"initial_layer_acceleration": "1000",
"bridge_acceleration": "1000",
"travel_acceleration": "1000",
"default_jerk": "0",
"skirt_loops": "2",
"skirt_distance": "4",
"brim_type": "no_brim",
"enable_support": "0",
"enable_arc_fitting": "0"
}
@@ -0,0 +1,15 @@
{
"type": "process",
"name": "fdm_process_wanhao_d9_mk1_common",
"inherits": "fdm_process_wanhao_d9_common",
"from": "system",
"instantiation": "false",
"default_acceleration": "500",
"outer_wall_acceleration": "500",
"inner_wall_acceleration": "500",
"top_surface_acceleration": "500",
"sparse_infill_acceleration": "500",
"initial_layer_acceleration": "500",
"bridge_acceleration": "500",
"travel_acceleration": "500"
}
+57 -23
View File
@@ -30,7 +30,7 @@ var USER_MODE = "simple";
var MODE_RANK = { simple: 0, advanced: 1, expert: 2, develop: 3 }; var MODE_RANK = { simple: 0, advanced: 1, expert: 2, develop: 3 };
// Search ranking weights: every contiguous match must outrank every fuzzy one regardless of field, // Search ranking weights: every contiguous match must outrank every fuzzy one regardless of field,
// and title must outrank group, which outranks source. // and title must outrank group/category, which outranks source.
var SCORE_CONTIGUOUS = 100000; var SCORE_CONTIGUOUS = 100000;
var SCORE_TITLE = 2000; var SCORE_TITLE = 2000;
var SCORE_GROUP = 1000; var SCORE_GROUP = 1000;
@@ -118,6 +118,18 @@ function sourceNorm(a) {
a._sn = NormText(a.source || "", false); a._sn = NormText(a.source || "", false);
return a._sn; return a._sn;
} }
function pluginCategoryNorm(a) {
if (a._pcn === undefined)
a._pcn = a.kind === "plugin" ? NormText(T("sd_plugins", "Plugins"), false) : "";
return a._pcn;
}
// Plugin type is searchable metadata, so typing "plugin" can find runnable plugin actions even
// when neither their capability nor plugin name contains that word. Keep both category forms.
function pluginTypeNorm(a) {
if (a._pn === undefined)
a._pn = a.kind === "plugin" ? NormText("plugin plugins", false) : "";
return a._pn;
}
// Search-only alias for the descriptive name when the title differs (e.g. "Reverse on even" vs // Search-only alias for the descriptive name when the title differs (e.g. "Reverse on even" vs
// "Overhang reversal"). Never rendered, so no highlight ranges. // "Overhang reversal"). Never rendered, so no highlight ranges.
function fullNorm(a) { function fullNorm(a) {
@@ -152,7 +164,7 @@ function fieldMatchScore(norm, needle, wwRe) {
// Split a query into normalized (folded+lowercased) whitespace-separated tokens. Empty for a blank // Split a query into normalized (folded+lowercased) whitespace-separated tokens. Empty for a blank
// query. These drive the multi-token path: every token must match some field, but different tokens // query. These drive the multi-token path: every token must match some field, but different tokens
// may match different fields (the title, the group, or the source breadcrumb). // may match different fields (the title, group, source breadcrumb, or plugin kind).
function queryTokens(query) { function queryTokens(query) {
var norm = NormText(String(query || "").trim(), false); var norm = NormText(String(query || "").trim(), false);
return norm ? norm.split(/\s+/).filter(Boolean) : []; return norm ? norm.split(/\s+/).filter(Boolean) : [];
@@ -170,14 +182,19 @@ function tokenMatch(a, token, wwRe) {
var g = fieldMatchScore(groupNorm(a), token, wwRe); var g = fieldMatchScore(groupNorm(a), token, wwRe);
var s = fieldMatchScore(sourceNorm(a), token, wwRe); var s = fieldMatchScore(sourceNorm(a), token, wwRe);
var f = fieldMatchScore(fullNorm(a), token, wwRe); var f = fieldMatchScore(fullNorm(a), token, wwRe);
if (!t && !g && !s && !f) return null; var p = fieldMatchScore(pluginCategoryNorm(a), token, wwRe);
var typeMatch = fieldMatchScore(pluginTypeNorm(a), token, wwRe);
if (!t && !g && !s && !f && !p && !typeMatch) return null;
var score = Math.max( var score = Math.max(
t ? (t.contiguous ? SCORE_CONTIGUOUS : 0) + SCORE_TITLE + t.score : -Infinity, t ? (t.contiguous ? SCORE_CONTIGUOUS : 0) + SCORE_TITLE + t.score : -Infinity,
g ? (g.contiguous ? SCORE_CONTIGUOUS : 0) + SCORE_GROUP + g.score : -Infinity, g ? (g.contiguous ? SCORE_CONTIGUOUS : 0) + SCORE_GROUP + g.score : -Infinity,
s ? (s.contiguous ? SCORE_CONTIGUOUS : 0) + s.score : -Infinity, s ? (s.contiguous ? SCORE_CONTIGUOUS : 0) + s.score : -Infinity,
f ? (f.contiguous ? SCORE_CONTIGUOUS : 0) + f.score : -Infinity f ? (f.contiguous ? SCORE_CONTIGUOUS : 0) + f.score : -Infinity,
p ? (p.contiguous ? SCORE_CONTIGUOUS : 0) + SCORE_GROUP + p.score : -Infinity,
typeMatch ? (typeMatch.contiguous ? SCORE_CONTIGUOUS : 0) + SCORE_GROUP + typeMatch.score : -Infinity
); );
return { score: score, title: t ? t.ranges : null, group: g ? g.ranges : null, source: s ? s.ranges : null }; return { score: score, title: t ? t.ranges : null, group: g ? g.ranges : null, source: s ? s.ranges : null,
plugin: p ? p.ranges : null };
} }
// Merge per-field token ranges into sorted, coalesced ranges for highlighting. Overlapping or adjacent // Merge per-field token ranges into sorted, coalesced ranges for highlighting. Overlapping or adjacent
@@ -201,8 +218,8 @@ function mergeRanges(ranges) {
} }
// Combine per-field scores into one value, or null when nothing matched. // Combine per-field scores into one value, or null when nothing matched.
// Ranking: contiguous > fuzzy, then title > group > source/full alias, then start/gaps. // Ranking: contiguous > fuzzy, then title > group/category > source/full alias, then start/gaps.
function scoreFields(t, g, s, f) { function scoreFields(t, g, s, f, p, typeMatch) {
var best = null; var best = null;
function consider(m, weight) { function consider(m, weight) {
if (!m) return; if (!m) return;
@@ -213,6 +230,8 @@ function scoreFields(t, g, s, f) {
consider(g, SCORE_GROUP); consider(g, SCORE_GROUP);
consider(s, 0); consider(s, 0);
consider(f, 0); consider(f, 0);
consider(p, SCORE_GROUP);
consider(typeMatch, SCORE_GROUP);
return best; return best;
} }
@@ -226,7 +245,8 @@ function scoreFields(t, g, s, f) {
// - tokens: every whitespace-separated word must match SOME field, but different words may match // - tokens: every whitespace-separated word must match SOME field, but different words may match
// different fields. This is what lets "speed acceleration inner" find "Inner wall" whose path is // different fields. This is what lets "speed acceleration inner" find "Inner wall" whose path is
// "Process : Speed : Acceleration" (title + source breadcrumb together). // "Process : Speed : Acceleration" (title + source breadcrumb together).
// full_label is searchable too but never highlighted, since it is not rendered. // full_label and canonical plugin kind are searchable aliases. The visible category is also searchable
// so its own match can be highlighted in plugin rows.
// A phrase match always outranks a distributed token match. // A phrase match always outranks a distributed token match.
function searchActions(actions, query) { function searchActions(actions, query) {
var q = (query || "").trim(); var q = (query || "").trim();
@@ -251,26 +271,31 @@ function searchActions(actions, query) {
var g = fieldMatchScore(groupNorm(a), searchNeedle, wwRe); var g = fieldMatchScore(groupNorm(a), searchNeedle, wwRe);
var s = fieldMatchScore(sourceNorm(a), searchNeedle, wwRe); var s = fieldMatchScore(sourceNorm(a), searchNeedle, wwRe);
var f = fieldMatchScore(fullNorm(a), searchNeedle, wwRe); var f = fieldMatchScore(fullNorm(a), searchNeedle, wwRe);
var phrase = scoreFields(t, g, s, f); var p = fieldMatchScore(pluginCategoryNorm(a), searchNeedle, wwRe);
var typeMatch = fieldMatchScore(pluginTypeNorm(a), searchNeedle, wwRe);
var phrase = scoreFields(t, g, s, f, p, typeMatch);
var score, ranges; var score, ranges;
if (phrase !== null) { if (phrase !== null) {
score = phrase + SCORE_PHRASE; score = phrase + SCORE_PHRASE;
ranges = { title: t ? t.ranges : null, group: g ? g.ranges : null, source: s ? s.ranges : null }; ranges = { title: t ? t.ranges : null, group: g ? g.ranges : null, source: s ? s.ranges : null,
plugin: p ? p.ranges : null };
} else { } else {
// Require every token; a token that matches nothing drops the action immediately. Ranges // Require every token; a token that matches nothing drops the action immediately. Ranges
// from all matching tokens are merged per field so each matched word highlights. // from all matching tokens are merged per field so each matched word highlights.
var sum = 0, titleR = null, groupR = null, sourceR = null, all = true; var sum = 0, titleR = null, groupR = null, sourceR = null, pluginR = null, all = true;
for (var k = 0; k < searchTokens.length; k++) { for (var tokenIndex = 0; tokenIndex < searchTokens.length; tokenIndex++) {
var m = tokenMatch(a, searchTokens[k], searchTokenRes[k]); var m = tokenMatch(a, searchTokens[tokenIndex], searchTokenRes[tokenIndex]);
if (!m) { all = false; break; } if (!m) { all = false; break; }
sum += m.score; sum += m.score;
if (m.title) (titleR || (titleR = [])).push(m.title); if (m.title) (titleR || (titleR = [])).push(m.title);
if (m.group) (groupR || (groupR = [])).push(m.group); if (m.group) (groupR || (groupR = [])).push(m.group);
if (m.source) (sourceR || (sourceR = [])).push(m.source); if (m.source) (sourceR || (sourceR = [])).push(m.source);
if (m.plugin) (pluginR || (pluginR = [])).push(m.plugin);
} }
if (!all) continue; if (!all) continue;
score = sum; score = sum;
ranges = { title: mergeRanges(titleR), group: mergeRanges(groupR), source: mergeRanges(sourceR) }; ranges = { title: mergeRanges(titleR), group: mergeRanges(groupR), source: mergeRanges(sourceR),
plugin: mergeRanges(pluginR) };
} }
// Ranges are per-field against the ACTUAL text drawn: title for the row-name, and group (or // Ranges are per-field against the ACTUAL text drawn: title for the row-name, and group (or
// source when group is empty) for the eyebrow - so highlight offsets stay aligned to the label. // source when group is empty) for the eyebrow - so highlight offsets stay aligned to the label.
@@ -278,6 +303,7 @@ function searchActions(actions, query) {
title: ranges.title, title: ranges.title,
group: ranges.group, group: ranges.group,
source: ranges.source, source: ranges.source,
plugin: ranges.plugin,
useEyebrowGroup: !!(a.group) useEyebrowGroup: !!(a.group)
}; };
scored.push({ a: a, s: score }); scored.push({ a: a, s: score });
@@ -390,7 +416,7 @@ function favDigitFromEvent(e) {
function resultCountText(total, shown, query) { function resultCountText(total, shown, query) {
return (query || "").trim() ? return (query || "").trim() ?
T("sd_result_count", "Showing %s of %s actions", shown, total) : T("sd_result_count", "Showing %s actions", shown) :
T("sd_result_count_all", "%s actions", total); T("sd_result_count_all", "%s actions", total);
} }
@@ -461,6 +487,12 @@ function actionCategory(a) {
return cat || T("sd_other", "Other"); return cat || T("sd_other", "Other");
} }
function actionEyebrow(a, typedQuery, isRecent) {
if (a && a.kind === "plugin" && (String(typedQuery || "").trim() || isRecent))
return T("sd_plugins", "Plugins");
return (a && (a.group || a.source)) || "";
}
// Stable-bucket actions by category, then order the groups alphabetically. Within a group the incoming // Stable-bucket actions by category, then order the groups alphabetically. Within a group the incoming
// (frecency) order is kept. Pure so the node-vm test can exercise grouping. // (frecency) order is kept. Pure so the node-vm test can exercise grouping.
function groupActions(list) { function groupActions(list) {
@@ -711,7 +743,7 @@ window.HandleStudio = function (payload) {
builtKey = ""; builtKey = "";
if (qEl) { if (qEl) {
qEl.value = ""; qEl.value = "";
qEl.placeholder = T("sd_search_n", "Search %s actions", ACTIONS.length); qEl.placeholder = T("sd_search", "Search actions");
syncClearButton(); syncClearButton();
} }
render({ resize: true, resetScroll: true }); render({ resize: true, resetScroll: true });
@@ -931,12 +963,14 @@ function beginRow(item, i, mono, ariaLabel) {
function renderActionRow(a, i) { function renderActionRow(a, i) {
var on = FAVS.indexOf(a.id) !== -1; var on = FAVS.indexOf(a.id) !== -1;
var shell = beginRow(a, i, false, actionLabel(a, ACTIONS)); var shell = beginRow(a, i, false, actionLabel(a, ACTIONS));
var mi = matchIndex[a.id]; var typedQuery = String(query || "").trim();
// The eyebrow shows group when present, else source. Highlight with the ranges of whichever of the var isRecent = !typedQuery && i < RECENTS.length && RECENTS[i].id === a.id;
// two the eyebrow actually renders (so a "Recent Projects"/"Object" header match lights up like a var mi = typedQuery ? matchIndex[a.id] : null;
// setting path does - the offsets are computed against the same string we are marking). // Plugin search/recent rows show their category; other rows show their group or source breadcrumb.
var eyebrow = a.group || a.source; // Use match ranges from the visible field so category and breadcrumb highlights stay aligned.
var eyebrowMatch = mi ? (mi.useEyebrowGroup ? mi.group : mi.source) : null; var showPluginCategory = a.kind === "plugin" && (typedQuery || isRecent);
var eyebrow = actionEyebrow(a, query, isRecent);
var eyebrowMatch = mi ? (showPluginCategory ? mi.plugin : (mi.useEyebrowGroup ? mi.group : mi.source)) : null;
shell.left.insertBefore(markedText("row-eyebrow", eyebrow, eyebrowMatch), shell.line); shell.left.insertBefore(markedText("row-eyebrow", eyebrow, eyebrowMatch), shell.line);
shell.line.appendChild(markedText("row-name", a.title, mi ? mi.title : null)); shell.line.appendChild(markedText("row-name", a.title, mi ? mi.title : null));
var badge = modeBadge(a, USER_MODE); var badge = modeBadge(a, USER_MODE);
@@ -1376,7 +1410,7 @@ function exitPhase() {
// It survives a second-phase exit (which never goes through exitPhase from the commands view), // It survives a second-phase exit (which never goes through exitPhase from the commands view),
// so without a reset the cached empty-query key would skip the rebuild and leave stale content. // so without a reset the cached empty-query key would skip the rebuild and leave stale content.
builtKey = ""; builtKey = "";
qEl.placeholder = T("sd_search_n", "Search %s actions", ACTIONS.length); qEl.placeholder = T("sd_search", "Search actions");
render({ resize: true, resetScroll: true }); render({ resize: true, resetScroll: true });
qEl.focus(); qEl.focus();
} }
@@ -82,6 +82,20 @@ assert.equal(ctx.searchActions(pool, "layer").length >= 2, true,
assert.equal(ctx.searchActions(pool, "surface")[0].id, "c2", assert.equal(ctx.searchActions(pool, "surface")[0].id, "c2",
"a later-but-precise match still ranks by relevance, not by pool type"); "a later-but-precise match still ranks by relevance, not by pool type");
const pluginPool = [
{ id: "plugin-action", title: "Optimize G-code", source: "Gcode Optimizer", group: "", kind: "plugin" },
{ id: "command-action", title: "Open Preferences", source: "OrcaSlicer", group: "Commands", kind: "command" }
];
assert.deepEqual(ctx.searchActions(pluginPool, "plugin").map(function (a) { return a.id; }), ["plugin-action"],
"the plugin kind makes runnable plugin actions searchable by plugin");
assert.deepEqual(ctx.searchActions(pluginPool, "plugins").map(function (a) { return a.id; }), ["plugin-action"],
"the plural Plugins category also finds plugin actions");
ctx.searchActions(pluginPool, "plugins");
assert.deepEqual(ctx.matchIndex["plugin-action"].plugin, [[0, 7]],
"a category match highlights the visible Plugins label");
assert.deepEqual(ctx.searchActions(pluginPool, "plugin optimize").map(function (a) { return a.id; }), ["plugin-action"],
"plugin kind can match one token while the action title matches another");
// A perfect match (the needle as one contiguous run) outranks a fuzzy match of the same field - and a // A perfect match (the needle as one contiguous run) outranks a fuzzy match of the same field - and a
// contiguous GROUP/header hit ("Recent Projects") beats a scattered fuzzy TITLE hit ("Retraction Length"), // contiguous GROUP/header hit ("Recent Projects") beats a scattered fuzzy TITLE hit ("Retraction Length"),
// which is what the old flat title-bonus ranking got backwards. // which is what the old flat title-bonus ranking got backwards.
@@ -188,6 +202,12 @@ assert.equal(ctx.actionCategory({ id: "s", group: "", source: "Filament : Coolin
"a Filament setting groups under Filament"); "a Filament setting groups under Filament");
assert.equal(ctx.actionCategory({ id: "plugin_script_action:Foo:bar.py", group: "", source: "Gcode Optimizer", kind: "plugin" }), "Plugins", assert.equal(ctx.actionCategory({ id: "plugin_script_action:Foo:bar.py", group: "", source: "Gcode Optimizer", kind: "plugin" }), "Plugins",
"every plugin shares one Plugins header"); "every plugin shares one Plugins header");
assert.equal(ctx.actionEyebrow({ group: "", source: "Gcode Optimizer", kind: "plugin" }, "plugin"), "Plugins",
"typed results show only the Plugins category");
assert.equal(ctx.actionEyebrow({ group: "", source: "Gcode Optimizer", kind: "plugin" }, "", true), "Plugins",
"recent plugin actions show only the Plugins category");
assert.equal(ctx.actionEyebrow({ group: "", source: "Gcode Optimizer", kind: "plugin" }, ""), "Gcode Optimizer",
"the unfiltered plugin section keeps the source name on non-recent rows");
assert.equal(ctx.actionCategory({ id: "x", group: "", source: "", kind: "command" }), "Other", assert.equal(ctx.actionCategory({ id: "x", group: "", source: "", kind: "command" }), "Other",
"a category-less action falls back to Other"); "a category-less action falls back to Other");
@@ -436,4 +456,9 @@ assert.equal(ctx.stateFromPayload({}).tooltipExpanded, true, "expansion defaults
assert.equal(ctx.stateFromPayload({ tooltip_expanded: false }).tooltipExpanded, false, "a collapsed payload is honored"); assert.equal(ctx.stateFromPayload({ tooltip_expanded: false }).tooltipExpanded, false, "a collapsed payload is honored");
assert.equal(ctx.stateFromPayload({ tooltip_expanded: true }).tooltipExpanded, true, "an expanded payload is honored"); assert.equal(ctx.stateFromPayload({ tooltip_expanded: true }).tooltipExpanded, true, "an expanded payload is honored");
// resultCountText: a search counts the shown matches only ("Showing N actions"); the total is used
// solely for the empty-query count.
assert.equal(ctx.resultCountText(100, 3, "lay"), "Showing 3 actions", "a search reports the shown match count only");
assert.equal(ctx.resultCountText(100, 100, ""), "100 actions", "an empty query reports the total");
console.log("ok"); console.log("ok");
+45
View File
@@ -405,6 +405,20 @@ class TestTripleResolution(unittest.TestCase):
self.assertEqual(afi.resolve_triple("MyPLA @P1", fmap, {}), self.assertEqual(afi.resolve_triple("MyPLA @P1", fmap, {}),
("MyVendor", "PLA", "MyPLA")) ("MyVendor", "PLA", "MyPLA"))
def test_split_vendor_and_type_bases_resolve(self):
# A partial base is normal, not an error: vendor and type may live on
# different ancestors, with an intermediate supplying neither (the
# Snapmaker shape). The pair is complete at the instantiated preset.
recs = [
self.rec("APLA @P1", inherits="mid"),
self.rec("mid", inherits="typebase"),
self.rec("typebase", filament_type=["PLA"], inherits="vendorbase"),
self.rec("vendorbase", filament_vendor=["AV"]),
]
fmap = {r["name"]: r for r in recs}
self.assertEqual(afi.resolve_triple("APLA @P1", fmap, {}),
("AV", "PLA", "APLA"))
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# checks on synthetic trees # checks on synthetic trees
@@ -417,6 +431,24 @@ class TestChecks(OfCleanTreeCase):
self.assertNotIn("[ERROR]", out) self.assertNotIn("[ERROR]", out)
self.assertNotIn("[WARNING]", out) self.assertNotIn("[WARNING]", out)
def test_instantiated_preset_over_partial_bases_is_silent(self):
# Vendor and type split across two non-instantiated bases, an
# intermediate base with neither: base profiles are allowed to be
# partial. Only the instantiated preset must resolve both.
self.t.write_preset("VendorA", preset("XPLA vendorbase", instantiation=False,
filament_vendor="XV"))
self.t.write_preset("VendorA", preset("XPLA typebase", instantiation=False,
filament_type="PLA",
inherits="XPLA vendorbase"))
self.t.write_preset("VendorA", preset("XPLA mid", instantiation=False,
inherits="XPLA typebase"))
self.t.write_preset("VendorA", preset(
"XPLA @P1", inherits="XPLA mid",
filament_id=afi.generate_filament_id("XV", "PLA", "XPLA"),
compatible_printers=["P1"]))
errors, out = self.t.check()
self.assertEqual(errors, 0, out)
def test_check1_unknown_non_of_id(self): def test_check1_unknown_non_of_id(self):
self.t.write_preset("VendorA", preset("BPLA @base", filament_id="BOGUS_9", self.t.write_preset("VendorA", preset("BPLA @base", filament_id="BOGUS_9",
instantiation=False, instantiation=False,
@@ -1523,6 +1555,19 @@ class TestRealTree(unittest.TestCase):
self.assertEqual(analysis["missing_effective"], []) self.assertEqual(analysis["missing_effective"], [])
self.assertEqual(analysis["read_errors"], []) self.assertEqual(analysis["read_errors"], [])
def test_every_instantiated_filament_resolves_vendor_and_type(self):
# The property the web guide resolves at load: a partial base is fine as
# long as the instantiated preset ends up with both fields. Guards the
# split-base bundles (Snapmaker, Anker, SeeMeCNC).
analysis = afi.analyze_tree(REAL_PROFILES)
unresolved = [
(vendor, rec["name"], rec["triple"][0], rec["triple"][1])
for vendor, filaments in analysis["vendors"].items()
for rec in filaments.values()
if rec["instantiation"] and not (rec["triple"][0] and rec["triple"][1])
]
self.assertEqual(unresolved, [])
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# review-fix regressions # review-fix regressions
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
+8
View File
@@ -286,6 +286,8 @@ set(SLIC3R_GUI_SOURCES
GUI/FilamentMapDialog.hpp GUI/FilamentMapDialog.hpp
GUI/IconManager.cpp GUI/IconManager.cpp
GUI/IconManager.hpp GUI/IconManager.hpp
GUI/IdleScheduler.cpp
GUI/IdleScheduler.hpp
GUI/ImageGrid.cpp GUI/ImageGrid.cpp
GUI/ImageGrid.h GUI/ImageGrid.h
GUI/ImGuiWrapper.cpp GUI/ImGuiWrapper.cpp
@@ -347,6 +349,10 @@ set(SLIC3R_GUI_SOURCES
GUI/KBShortcutsDialog.hpp GUI/KBShortcutsDialog.hpp
GUI/KeyChord.cpp GUI/KeyChord.cpp
GUI/KeyChord.hpp GUI/KeyChord.hpp
GUI/Lazy.cpp
GUI/Lazy.hpp
GUI/LazyPage.cpp
GUI/LazyPage.hpp
GUI/LibVGCode/LibVGCodeWrapper.hpp GUI/LibVGCode/LibVGCodeWrapper.hpp
GUI/LibVGCode/LibVGCodeWrapper.cpp GUI/LibVGCode/LibVGCodeWrapper.cpp
GUI/LinuxDisplayBackend.cpp GUI/LinuxDisplayBackend.cpp
@@ -433,6 +439,7 @@ set(SLIC3R_GUI_SOURCES
GUI/Plater.hpp GUI/Plater.hpp
GUI/PlateSettingsDialog.cpp GUI/PlateSettingsDialog.cpp
GUI/PlateSettingsDialog.hpp GUI/PlateSettingsDialog.hpp
GUI/PrebuildQueue.hpp
GUI/Preferences.cpp GUI/Preferences.cpp
GUI/Preferences.hpp GUI/Preferences.hpp
GUI/PresetBundleDialog.cpp GUI/PresetBundleDialog.cpp
@@ -512,6 +519,7 @@ set(SLIC3R_GUI_SOURCES
GUI/SliceInfoPanel.hpp GUI/SliceInfoPanel.hpp
GUI/SlicingProgressNotification.cpp GUI/SlicingProgressNotification.cpp
GUI/SlicingProgressNotification.hpp GUI/SlicingProgressNotification.hpp
GUI/StagedBuild.hpp
GUI/StatusPanel.cpp GUI/StatusPanel.cpp
GUI/StatusPanel.hpp GUI/StatusPanel.hpp
GUI/StepMeshDialog.cpp GUI/StepMeshDialog.cpp
+21 -11
View File
@@ -863,17 +863,27 @@ void AuxiliaryPanel::init_tabpanel()
m_tabpanel->SetBackgroundColour(wxColour("#FEFFFF")); m_tabpanel->SetBackgroundColour(wxColour("#FEFFFF"));
m_tabpanel->Bind(wxEVT_BOOKCTRL_PAGE_CHANGED, [](wxBookCtrlEvent &e) { /* Event handling */ }); m_tabpanel->Bind(wxEVT_BOOKCTRL_PAGE_CHANGED, [](wxBookCtrlEvent &e) { /* Event handling */ });
m_designer_panel = new DesignerPanel(m_tabpanel, AuxiliaryFolderType::DESIGNER); add_build_step([this] {
m_pictures_panel = new AuFolderPanel(m_tabpanel, AuxiliaryFolderType::MODEL_PICTURE); m_designer_panel = new DesignerPanel(m_tabpanel, AuxiliaryFolderType::DESIGNER);
m_bill_of_materials_panel = new AuFolderPanel(m_tabpanel, AuxiliaryFolderType::BILL_OF_MATERIALS); m_tabpanel->AddPage(m_designer_panel, _L("Basic Info"), true);
m_assembly_panel = new AuFolderPanel(m_tabpanel, AuxiliaryFolderType::ASSEMBLY_GUIDE); });
m_others_panel = new AuFolderPanel(m_tabpanel, AuxiliaryFolderType::OTHERS); add_build_step([this] {
m_pictures_panel = new AuFolderPanel(m_tabpanel, AuxiliaryFolderType::MODEL_PICTURE);
m_tabpanel->AddPage(m_designer_panel, _L("Basic Info"), true); m_tabpanel->AddPage(m_pictures_panel, _L("Pictures"), false);
m_tabpanel->AddPage(m_pictures_panel, _L("Pictures"), false); });
m_tabpanel->AddPage(m_bill_of_materials_panel, _L("Bill of Materials"), false); add_build_step([this] {
m_tabpanel->AddPage(m_assembly_panel, _L("Assembly Guide"), false); m_bill_of_materials_panel = new AuFolderPanel(m_tabpanel, AuxiliaryFolderType::BILL_OF_MATERIALS);
m_tabpanel->AddPage(m_others_panel, _L("Others"), false); m_tabpanel->AddPage(m_bill_of_materials_panel, _L("Bill of Materials"), false);
});
add_build_step([this] {
m_assembly_panel = new AuFolderPanel(m_tabpanel, AuxiliaryFolderType::ASSEMBLY_GUIDE);
m_tabpanel->AddPage(m_assembly_panel, _L("Assembly Guide"), false);
});
add_build_step([this] {
m_others_panel = new AuFolderPanel(m_tabpanel, AuxiliaryFolderType::OTHERS);
m_tabpanel->AddPage(m_others_panel, _L("Others"), false);
Layout();
});
} }
wxWindow *AuxiliaryPanel::create_side_tools() wxWindow *AuxiliaryPanel::create_side_tools()
+2 -1
View File
@@ -46,6 +46,7 @@
#include "slic3r/GUI/UpgradePanel.hpp" #include "slic3r/GUI/UpgradePanel.hpp"
#include "slic3r/GUI/AmsWidgets.hpp" #include "slic3r/GUI/AmsWidgets.hpp"
#include "Widgets/SideTools.hpp" #include "Widgets/SideTools.hpp"
#include "StagedBuild.hpp"
#define AUFILE_GREY700 wxColour(107, 107, 107) #define AUFILE_GREY700 wxColour(107, 107, 107)
#define AUFILE_GREY500 wxColour(158, 158, 158) #define AUFILE_GREY500 wxColour(158, 158, 158)
@@ -194,7 +195,7 @@ public:
}; };
class AuxiliaryPanel : public wxPanel class AuxiliaryPanel : public wxPanel, public StagedBuild
{ {
private: private:
Tabbook *m_tabpanel = {nullptr}; Tabbook *m_tabpanel = {nullptr};
+2 -1
View File
@@ -12,6 +12,7 @@
#include "libslic3r/CAD/CadDocument.hpp" #include "libslic3r/CAD/CadDocument.hpp"
#include "slic3r/GUI/CAD/DesignInteraction.hpp" // CadLevel: what one Esc press means #include "slic3r/GUI/CAD/DesignInteraction.hpp" // CadLevel: what one Esc press means
#include "slic3r/GUI/Lazy.hpp"
class ComboBox; // Orca dropdown (Widgets/ComboBox.hpp) — replaces wxChoice everywhere here class ComboBox; // Orca dropdown (Widgets/ComboBox.hpp) — replaces wxChoice everywhere here
class StaticBox; // Orca rounded card frame (Widgets/StaticBox.hpp) class StaticBox; // Orca rounded card frame (Widgets/StaticBox.hpp)
@@ -46,7 +47,7 @@ class DesignCanvas;
// Design (CAD) tab: a sketch-first, Onshape-style form-driven CAD panel. // Design (CAD) tab: a sketch-first, Onshape-style form-driven CAD panel.
// Sketch and Extrude are independent tools: the user creates a Sketch first, // Sketch and Extrude are independent tools: the user creates a Sketch first,
// then selects it and Extrudes to produce a solid. // then selects it and Extrudes to produce a solid.
class DesignPanel : public wxPanel class DesignPanel : public wxPanel, public LazyInstance<DesignPanel>
{ {
public: public:
explicit DesignPanel(wxWindow* parent); explicit DesignPanel(wxWindow* parent);
+1 -2
View File
@@ -1989,11 +1989,10 @@ json action_set_feature_expr(DesignPanel* panel, const json& params)
// Dispatch one parsed request ON THE MAIN THREAD. Returns a JSON-RPC reply string. // Dispatch one parsed request ON THE MAIN THREAD. Returns a JSON-RPC reply string.
std::string handle_on_main(const std::string& method, const json& params, const json& id) std::string handle_on_main(const std::string& method, const json& params, const json& id)
{ {
MainFrame* mf = wxGetApp().mainframe;
// The panel is built on first use, and in a headless session nobody clicks the tab that // The panel is built on first use, and in a headless session nobody clicks the tab that
// would build it -- so build it here rather than refusing. Safe: this runs on the main // would build it -- so build it here rather than refusing. Safe: this runs on the main
// thread (see the CallAfter that dispatches us). // thread (see the CallAfter that dispatches us).
DesignPanel* panel = mf ? mf->ensure_design_panel() : nullptr; DesignPanel* panel = DesignPanel::ensure();
if (!panel) if (!panel)
return rpc_error(id, -32001, "Design panel not ready"); return rpc_error(id, -32001, "Design panel not ready");
+6 -3
View File
@@ -491,14 +491,15 @@ void CalibrationPanel::init_tabpanel() {
selected); selected);
} }
for (int i = 0; i < (int)CALI_MODE_COUNT; i++)
add_build_steps_of(*m_cali_panels[i]);
// ORCA use standard paddings and keep arrow icon for consistent look between sidebars // ORCA use standard paddings and keep arrow icon for consistent look between sidebars
//for (int i = 0; i < (int)CALI_MODE_COUNT; i++) //for (int i = 0; i < (int)CALI_MODE_COUNT; i++)
// m_tabpanel->SetPageImage(i, ""); // m_tabpanel->SetPageImage(i, "");
//auto padding_size = m_tabpanel->GetBtnsListCtrl()->GetPaddingSize(0); //auto padding_size = m_tabpanel->GetBtnsListCtrl()->GetPaddingSize(0);
//m_tabpanel->GetBtnsListCtrl()->SetPaddingSize({ FromDIP(15), padding_size.y }); //m_tabpanel->GetBtnsListCtrl()->SetPaddingSize({ FromDIP(15), padding_size.y });
m_initialized = true;
} }
void CalibrationPanel::init_timer() void CalibrationPanel::init_timer()
@@ -534,6 +535,8 @@ void CalibrationPanel::update_print_error_info(int code, std::string msg, std::s
} }
void CalibrationPanel::update_all() { void CalibrationPanel::update_all() {
// Every wizard's pages exist once the last build step has run.
if (!built()) return;
NetworkAgent* m_agent = wxGetApp().getAgent(); NetworkAgent* m_agent = wxGetApp().getAgent();
Slic3r::DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager(); Slic3r::DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
@@ -597,7 +600,7 @@ void CalibrationPanel::update_all() {
void CalibrationPanel::show_status(int status) void CalibrationPanel::show_status(int status)
{ {
if (!m_initialized) return; if (!built()) return;
if (last_status == status)return; if (last_status == status)return;
last_status = status; last_status = status;
+2 -2
View File
@@ -3,6 +3,7 @@
#include "CalibrationWizard.hpp" #include "CalibrationWizard.hpp"
#include "Tabbook.hpp" #include "Tabbook.hpp"
#include "Lazy.hpp"
//#include "Widgets/SideTools.hpp" //#include "Widgets/SideTools.hpp"
namespace Slic3r { namespace GUI { namespace Slic3r { namespace GUI {
@@ -88,7 +89,7 @@ private:
}; };
class CalibrationPanel : public wxPanel class CalibrationPanel : public wxPanel, public StagedBuild, public LazyInstance<CalibrationPanel>
{ {
public: public:
CalibrationPanel(wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxTAB_TRAVERSAL); CalibrationPanel(wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxTAB_TRAVERSAL);
@@ -109,7 +110,6 @@ protected:
int last_status; int last_status;
bool m_initialized { false };
std::string last_conn_type = "undedefined"; std::string last_conn_type = "undedefined";
MachineObject* obj{ nullptr }; MachineObject* obj{ nullptr };
MachineObject* last_obj { nullptr }; MachineObject* last_obj { nullptr };
+56 -65
View File
@@ -130,6 +130,15 @@ CalibrationWizard::~CalibrationWizard()
; ;
} }
void CalibrationWizard::add_page_step(CalibrationWizardPageStep*& step, std::function<CalibrationWizardPage*()> make)
{
add_build_step([this, &step, make = std::move(make)] {
step = new CalibrationWizardPageStep(make());
m_all_pages_sizer->Add(step->page, 1, wxEXPAND | wxALL, FromDIP(25));
step->page->Hide();
});
}
void CalibrationWizard::on_cali_job_finished(wxCommandEvent& event) void CalibrationWizard::on_cali_job_finished(wxCommandEvent& event)
{ {
this->on_cali_job_finished(event.GetString()); this->on_cali_job_finished(event.GetString());
@@ -520,33 +529,28 @@ void PressureAdvanceWizard::on_cali_job_finished(wxString evt_data)
void PressureAdvanceWizard::create_pages() void PressureAdvanceWizard::create_pages()
{ {
start_step = new CalibrationWizardPageStep(new CalibrationPAStartPage(m_scrolledWindow)); add_page_step(start_step, [this] { return new CalibrationPAStartPage(m_scrolledWindow); });
preset_step = new CalibrationWizardPageStep(new CalibrationPresetPage(m_scrolledWindow, m_mode, false)); add_page_step(preset_step, [this] { return new CalibrationPresetPage(m_scrolledWindow, m_mode, false); });
cali_step = new CalibrationWizardPageStep(new CalibrationCaliPage(m_scrolledWindow, m_mode)); add_page_step(cali_step, [this] { return new CalibrationCaliPage(m_scrolledWindow, m_mode); });
save_step = new CalibrationWizardPageStep(new CalibrationPASavePage(m_scrolledWindow)); add_page_step(save_step, [this] { return new CalibrationPASavePage(m_scrolledWindow); });
m_all_pages_sizer->Add(start_step->page, 1, wxEXPAND | wxALL, FromDIP(25)); add_build_step([this] {
m_all_pages_sizer->Add(preset_step->page, 1, wxEXPAND | wxALL, FromDIP(25)); m_page_steps.push_back(start_step);
m_all_pages_sizer->Add(cali_step->page, 1, wxEXPAND | wxALL, FromDIP(25)); m_page_steps.push_back(preset_step);
m_all_pages_sizer->Add(save_step->page, 1, wxEXPAND | wxALL, FromDIP(25)); m_page_steps.push_back(cali_step);
m_page_steps.push_back(save_step);
for (int i = 0; i < m_page_steps.size() -1; i++) {
m_page_steps[i]->chain(m_page_steps[i+1]);
}
m_page_steps.push_back(start_step); for (int i = 0; i < m_page_steps.size(); i++) {
m_page_steps.push_back(preset_step); m_page_steps[i]->page->Bind(EVT_CALI_ACTION, &PressureAdvanceWizard::on_cali_action, this);
m_page_steps.push_back(cali_step); }
m_page_steps.push_back(save_step);
for (int i = 0; i < m_page_steps.size() -1; i++) { if (!m_page_steps.empty())
m_page_steps[i]->chain(m_page_steps[i+1]); show_step(m_page_steps.front());
} });
for (int i = 0; i < m_page_steps.size(); i++) {
m_page_steps[i]->page->Hide();
m_page_steps[i]->page->Bind(EVT_CALI_ACTION, &PressureAdvanceWizard::on_cali_action, this);
}
if (!m_page_steps.empty())
show_step(m_page_steps.front());
} }
void PressureAdvanceWizard::on_cali_action(wxCommandEvent& evt) void PressureAdvanceWizard::on_cali_action(wxCommandEvent& evt)
@@ -1053,59 +1057,46 @@ FlowRateWizard::FlowRateWizard(wxWindow* parent, wxWindowID id, const wxPoint& p
void FlowRateWizard::create_pages() void FlowRateWizard::create_pages()
{ {
start_step = new CalibrationWizardPageStep(new CalibrationFlowRateStartPage(m_scrolledWindow)); add_page_step(start_step, [this] { return new CalibrationFlowRateStartPage(m_scrolledWindow); });
preset_step = new CalibrationWizardPageStep(new CalibrationPresetPage(m_scrolledWindow, m_mode, false)); add_page_step(preset_step, [this] { return new CalibrationPresetPage(m_scrolledWindow, m_mode, false); });
// manual // manual
cali_coarse_step = new CalibrationWizardPageStep(new CalibrationCaliPage(m_scrolledWindow, m_mode, CaliPageType::CALI_PAGE_CALI)); add_page_step(cali_coarse_step, [this] { return new CalibrationCaliPage(m_scrolledWindow, m_mode, CaliPageType::CALI_PAGE_CALI); });
coarse_save_step = new CalibrationWizardPageStep(new CalibrationFlowCoarseSavePage(m_scrolledWindow)); add_page_step(coarse_save_step, [this] { return new CalibrationFlowCoarseSavePage(m_scrolledWindow); });
cali_fine_step = new CalibrationWizardPageStep(new CalibrationCaliPage(m_scrolledWindow, m_mode, CaliPageType::CALI_PAGE_FINE_CALI)); add_page_step(cali_fine_step, [this] { return new CalibrationCaliPage(m_scrolledWindow, m_mode, CaliPageType::CALI_PAGE_FINE_CALI); });
fine_save_step = new CalibrationWizardPageStep(new CalibrationFlowFineSavePage(m_scrolledWindow)); add_page_step(fine_save_step, [this] { return new CalibrationFlowFineSavePage(m_scrolledWindow); });
// auto // auto
cali_step = new CalibrationWizardPageStep(new CalibrationCaliPage(m_scrolledWindow, m_mode)); add_page_step(cali_step, [this] { return new CalibrationCaliPage(m_scrolledWindow, m_mode); });
save_step = new CalibrationWizardPageStep(new CalibrationFlowX1SavePage(m_scrolledWindow)); add_page_step(save_step, [this] { return new CalibrationFlowX1SavePage(m_scrolledWindow); });
m_all_pages_sizer->Add(start_step->page, 1, wxEXPAND | wxALL, FromDIP(25)); add_build_step([this] {
m_all_pages_sizer->Add(preset_step->page, 1, wxEXPAND | wxALL, FromDIP(25)); m_page_steps.push_back(start_step);
m_all_pages_sizer->Add(cali_coarse_step->page, 1, wxEXPAND | wxALL, FromDIP(25)); m_page_steps.push_back(preset_step);
m_all_pages_sizer->Add(coarse_save_step->page, 1, wxEXPAND | wxALL, FromDIP(25)); m_page_steps.push_back(cali_coarse_step);
m_all_pages_sizer->Add(cali_fine_step->page, 1, wxEXPAND | wxALL, FromDIP(25)); m_page_steps.push_back(coarse_save_step);
m_all_pages_sizer->Add(fine_save_step->page, 1, wxEXPAND | wxALL, FromDIP(25)); m_page_steps.push_back(cali_fine_step);
m_page_steps.push_back(fine_save_step);
m_all_pages_sizer->Add(cali_step->page, 1, wxEXPAND | wxALL, FromDIP(25)); //m_page_steps.push_back(cali_step);
m_all_pages_sizer->Add(save_step->page, 1, wxEXPAND | wxALL, FromDIP(25)); //m_page_steps.push_back(save_step);
m_page_steps.push_back(start_step); for (int i = 0; i < m_page_steps.size() - 1; i++) {
m_page_steps.push_back(preset_step); m_page_steps[i]->chain(m_page_steps[i + 1]);
m_page_steps.push_back(cali_coarse_step); }
m_page_steps.push_back(coarse_save_step);
m_page_steps.push_back(cali_fine_step);
m_page_steps.push_back(fine_save_step);
//m_page_steps.push_back(cali_step); for (int i = 0; i < m_page_steps.size(); i++) {
//m_page_steps.push_back(save_step); m_page_steps[i]->page->Bind(EVT_CALI_ACTION, &FlowRateWizard::on_cali_action, this);
}
for (int i = 0; i < m_page_steps.size() - 1; i++) { cali_step->page->Bind(EVT_CALI_ACTION, &FlowRateWizard::on_cali_action, this);
m_page_steps[i]->chain(m_page_steps[i + 1]); save_step->page->Bind(EVT_CALI_ACTION, &FlowRateWizard::on_cali_action, this);
}
// hide all pages if (!m_page_steps.empty())
cali_step->page->Hide(); show_step(m_page_steps.front());
save_step->page->Hide();
for (int i = 0; i < m_page_steps.size(); i++) {
m_page_steps[i]->page->Hide();
m_page_steps[i]->page->Bind(EVT_CALI_ACTION, &FlowRateWizard::on_cali_action, this);
}
set_cali_method(CalibrationMethod::CALI_METHOD_MANUAL);
cali_step->page->Bind(EVT_CALI_ACTION, &FlowRateWizard::on_cali_action, this); });
save_step->page->Bind(EVT_CALI_ACTION, &FlowRateWizard::on_cali_action, this);
if (!m_page_steps.empty())
show_step(m_page_steps.front());
set_cali_method(CalibrationMethod::CALI_METHOD_MANUAL);
} }
void FlowRateWizard::on_cali_action(wxCommandEvent& evt) void FlowRateWizard::on_cali_action(wxCommandEvent& evt)
+5 -1
View File
@@ -9,6 +9,7 @@
#include "CalibrationWizardPresetPage.hpp" #include "CalibrationWizardPresetPage.hpp"
#include "CalibrationWizardCaliPage.hpp" #include "CalibrationWizardCaliPage.hpp"
#include "CalibrationWizardSavePage.hpp" #include "CalibrationWizardSavePage.hpp"
#include "StagedBuild.hpp"
namespace Slic3r { namespace GUI { namespace Slic3r { namespace GUI {
@@ -36,7 +37,7 @@ struct ConfigIndexValue
int index{0}; int index{0};
}; };
class CalibrationWizard : public wxPanel { class CalibrationWizard : public wxPanel, public StagedBuild {
public: public:
CalibrationWizard(wxWindow* parent, CalibMode mode, CalibrationWizard(wxWindow* parent, CalibMode mode,
wxWindowID id = wxID_ANY, wxWindowID id = wxID_ANY,
@@ -79,6 +80,9 @@ public:
protected: protected:
void on_cali_go_home(); void on_cali_go_home();
// Queues a page as a build step, created hidden and added to the pages sizer.
void add_page_step(CalibrationWizardPageStep*& step, std::function<CalibrationWizardPage*()> make);
protected: protected:
/* wx widgets*/ /* wx widgets*/
wxScrolledWindow* m_scrolledWindow; wxScrolledWindow* m_scrolledWindow;
+3 -1
View File
@@ -192,8 +192,10 @@ void CalibrationCaliPage::update(MachineObject* obj)
set_cali_img(); set_cali_img();
} }
// A calibration can run before the Device tab is ever opened, and only its status
// panel shows a print error.
if (obj->print_error > 0) { if (obj->print_error > 0) {
StatusPanel* status_panel = Slic3r::GUI::wxGetApp().mainframe->m_monitor->get_status_panel(); StatusPanel* status_panel = MonitorPanel::ensure()->get_status_panel();
status_panel->obj = obj; status_panel->obj = obj;
status_panel->update_error_message(); status_panel->update_error_message();
} }
+6 -3
View File
@@ -538,7 +538,8 @@ void DeviceErrorDialog::on_button_click(ActionButton btn_id)
break; break;
} }
case DeviceErrorDialog::CHECK_ASSISTANT: { case DeviceErrorDialog::CHECK_ASSISTANT: {
wxGetApp().mainframe->m_monitor->jump_to_HMS(); // go to assistant page if (MonitorPanel* monitor = MonitorPanel::if_built())
monitor->jump_to_HMS(); // go to assistant page
break; break;
} }
case DeviceErrorDialog::FILAMENT_EXTRUDED: { case DeviceErrorDialog::FILAMENT_EXTRUDED: {
@@ -568,7 +569,8 @@ void DeviceErrorDialog::on_button_click(ActionButton btn_id)
} }
case DeviceErrorDialog::JUMP_TO_LIVEVIEW: { case DeviceErrorDialog::JUMP_TO_LIVEVIEW: {
Slic3r::GUI::wxGetApp().mainframe->jump_to_monitor(); Slic3r::GUI::wxGetApp().mainframe->jump_to_monitor();
Slic3r::GUI::wxGetApp().mainframe->m_monitor->jump_to_LiveView(); if (MonitorPanel* monitor = MonitorPanel::if_built())
monitor->jump_to_LiveView();
break; break;
} }
case DeviceErrorDialog::NO_REMINDER_NEXT_TIME: { case DeviceErrorDialog::NO_REMINDER_NEXT_TIME: {
@@ -618,7 +620,8 @@ void DeviceErrorDialog::on_button_click(ActionButton btn_id)
} }
case DeviceErrorDialog::OK_JUMP_RACK: { case DeviceErrorDialog::OK_JUMP_RACK: {
Slic3r::GUI::wxGetApp().mainframe->jump_to_monitor(); Slic3r::GUI::wxGetApp().mainframe->jump_to_monitor();
Slic3r::GUI::wxGetApp().mainframe->m_monitor->jump_to_Rack(); if (MonitorPanel* monitor = MonitorPanel::if_built())
monitor->jump_to_Rack();
break; break;
} }
case DeviceErrorDialog::ABORT: { case DeviceErrorDialog::ABORT: {
@@ -934,7 +934,8 @@ void wgtDeviceNozzleRackNozzleItem::OnBtnNozzleStatus(wxMouseEvent& evt)
dlg.AddButton(wxID_OK,_L("Jump to the upgrade page"), true); dlg.AddButton(wxID_OK,_L("Jump to the upgrade page"), true);
if (dlg.ShowModal() == wxID_OK) { if (dlg.ShowModal() == wxID_OK) {
wxGetApp().mainframe->m_monitor->jump_to_Upgrade(); if (MonitorPanel* monitor = MonitorPanel::if_built())
monitor->jump_to_Upgrade();
}; };
} }
} }
@@ -344,7 +344,8 @@ void wgtDeviceNozzleRackHotendUpdate::OnStatusIconClick(wxMouseEvent& event)
if (dlg.ShowModal() == wxID_OK) if (dlg.ShowModal() == wxID_OK)
{ {
wxGetApp().mainframe->m_monitor->jump_to_Upgrade(); if (MonitorPanel* monitor = MonitorPanel::if_built())
monitor->jump_to_Upgrade();
wxCommandEvent evt(wxEVT_NOZZLE_JUMP_UPGRADE, GetId()); wxCommandEvent evt(wxEVT_NOZZLE_JUMP_UPGRADE, GetId());
evt.SetEventObject(this); evt.SetEventObject(this);
+210 -51
View File
@@ -20,6 +20,7 @@
#include "libslic3r/AppConfig.hpp" #include "libslic3r/AppConfig.hpp"
#include "3DScene.hpp" #include "3DScene.hpp"
#include "BackgroundSlicingProcess.hpp" #include "BackgroundSlicingProcess.hpp"
#include "CameraUtils.hpp"
#include "GLShader.hpp" #include "GLShader.hpp"
#include "GUI.hpp" #include "GUI.hpp"
#include "Tab.hpp" #include "Tab.hpp"
@@ -117,6 +118,36 @@ void GLCanvas3D::load_render_colors()
namespace Slic3r { namespace Slic3r {
namespace GUI { namespace GUI {
static void pan_camera(Camera& camera, const Vec2d& screen_delta, const Vec3d& anchor)
{
// Orca: Derive world-units-per-pixel from the projection which produced the visible frame.
// Perspective additionally scales with the eye-space depth of the point being dragged.
const auto& viewport = camera.get_viewport();
const auto& projection = camera.get_projection_matrix().matrix();
const double depth_scale = camera.get_type() == Camera::EType::Perspective ?
(anchor - camera.get_position()).dot(camera.get_dir_forward()) : 1.0;
const double projection_x = projection(0, 0) * viewport[2];
const double projection_y = projection(1, 1) * viewport[3];
// Orca: X/Y projection coefficients already include zoom. Using them directly avoids a
// project/unproject round-trip through window depth, whose precision depends on the scene frustum.
if (viewport[2] > 0 && viewport[3] > 0 && anchor.allFinite() && depth_scale > EPSILON &&
std::abs(projection_x) > EPSILON && std::abs(projection_y) > EPSILON) {
const Vec3d displacement = 2.0 * depth_scale *
(screen_delta.y() / projection_y * camera.get_dir_up() -
screen_delta.x() / projection_x * camera.get_dir_right());
if (displacement.allFinite()) {
camera.translate(displacement);
return;
}
}
// Orca: Preserve the former target-plane behavior if the projection or anchor is invalid.
// Screen Y grows downward, and the camera moves opposite to the drag.
camera.translate(camera.get_inv_zoom() *
(screen_delta.y() * camera.get_dir_up() - screen_delta.x() * camera.get_dir_right()));
}
#ifdef __WXGTK3__ #ifdef __WXGTK3__
// wxGTK3 seems to simulate OSX behavior in regard to HiDPI scaling support. // wxGTK3 seems to simulate OSX behavior in regard to HiDPI scaling support.
RetinaHelper::RetinaHelper(wxWindow* window) : m_window(window), m_self(nullptr) {} RetinaHelper::RetinaHelper(wxWindow* window) : m_window(window), m_self(nullptr) {}
@@ -2206,15 +2237,14 @@ void GLCanvas3D::_render_scene(const Camera& camera, const Size& cnv_size)
_render_background(); _render_background();
//BBS add partplater rendering logic //BBS add partplater rendering logic
bool only_current = false, only_body = false, no_partplate = false; bool only_current = false, only_body = false;
const bool show_bed = is_bed_visible();
bool show_grid = true; bool show_grid = true;
GLGizmosManager::EType gizmo_type = m_gizmos.get_current_type(); GLGizmosManager::EType gizmo_type = m_gizmos.get_current_type();
if (!m_main_toolbar.is_enabled()) { if (!m_main_toolbar.is_enabled()) {
//only_body = true; //only_body = true;
only_current = true; only_current = true;
} }
else if ((gizmo_type == GLGizmosManager::FdmSupports) || (gizmo_type == GLGizmosManager::Seam) || (gizmo_type == GLGizmosManager::MmSegmentation) || (gizmo_type == GLGizmosManager::FuzzySkin))
no_partplate = true;
else if (gizmo_type == GLGizmosManager::BrimEars && !camera.is_looking_downward()) else if (gizmo_type == GLGizmosManager::BrimEars && !camera.is_looking_downward())
show_grid = false; show_grid = false;
if (m_axes_at_bed_center) if (m_axes_at_bed_center)
@@ -2228,11 +2258,11 @@ void GLCanvas3D::_render_scene(const Camera& camera, const Size& cnv_size)
if (m_canvas_type == ECanvasType::CanvasView3D) { if (m_canvas_type == ECanvasType::CanvasView3D) {
// m_show_bed gates the plate list too: hiding the bed but leaving its grid and outline // m_show_bed gates the plate list too: hiding the bed but leaving its grid and outline
// floating would read as a rendering fault rather than a deliberate view option. // floating would read as a rendering fault rather than a deliberate view option.
if (!no_partplate && m_show_bed) if (show_bed)
_render_bed(camera.get_view_matrix(), camera.get_projection_matrix(), !camera.is_looking_downward(), m_show_world_axes); _render_bed(camera.get_view_matrix(), camera.get_projection_matrix(), !camera.is_looking_downward(), m_show_world_axes);
if (!no_partplate && m_show_bed) //BBS: add outline logic if (show_bed) //BBS: add outline logic
_render_platelist(camera.get_view_matrix(), camera.get_projection_matrix(), !camera.is_looking_downward(), only_current, only_body, hover_id, true, show_grid); _render_platelist(camera.get_view_matrix(), camera.get_projection_matrix(), !camera.is_looking_downward(), only_current, only_body, hover_id, true, show_grid);
if (m_axes_at_bed_center && m_show_bed && !no_partplate) if (m_axes_at_bed_center && show_bed)
// Design tab: replace the plate's corner-origin grid with the origin-centred CAD grid. // Design tab: replace the plate's corner-origin grid with the origin-centred CAD grid.
_render_cad_grid(camera.get_view_matrix(), camera.get_projection_matrix()); _render_cad_grid(camera.get_view_matrix(), camera.get_projection_matrix());
@@ -3281,6 +3311,9 @@ void GLCanvas3D::unbind_event_handlers()
m_canvas->Unbind(wxEVT_GESTURE_PAN, &GLCanvas3D::on_gesture, this); m_canvas->Unbind(wxEVT_GESTURE_PAN, &GLCanvas3D::on_gesture, this);
m_canvas->Unbind(wxEVT_GESTURE_ZOOM, &GLCanvas3D::on_gesture, this); m_canvas->Unbind(wxEVT_GESTURE_ZOOM, &GLCanvas3D::on_gesture, this);
m_canvas->Unbind(wxEVT_GESTURE_ROTATE, &GLCanvas3D::on_gesture, this); m_canvas->Unbind(wxEVT_GESTURE_ROTATE, &GLCanvas3D::on_gesture, this);
#if __WXOSX__
initGestures(m_canvas->GetHandle(), nullptr);
#endif
} }
} }
@@ -4029,27 +4062,38 @@ void GLCanvas3D::on_gesture(wxGestureEvent &evt)
auto & camera = wxGetApp().plater()->get_camera(); auto & camera = wxGetApp().plater()->get_camera();
if (evt.GetEventType() == wxEVT_GESTURE_PAN) { if (evt.GetEventType() == wxEVT_GESTURE_PAN) {
auto p = evt.GetPosition(); // Orca: Gesture coordinates must use framebuffer pixels, and one stable world-space
// anchor must be retained for the complete gesture to prevent perspective drift.
const auto p = evt.GetPosition();
auto d = static_cast<wxPanGestureEvent&>(evt).GetDelta(); auto d = static_cast<wxPanGestureEvent&>(evt).GetDelta();
float z = 0; Vec2d screen_position(p.x, p.y);
const Vec3d &p2 = _mouse_to_3d({p.x, p.y}, &z); Vec2d screen_delta(d.x, d.y);
const Vec3d &p1 = _mouse_to_3d({p.x - d.x, p.y - d.y}, &z); apply_retina_scale(screen_position);
camera.set_target(camera.get_target() + p1 - p2); apply_retina_scale(screen_delta);
if (evt.IsGestureStart() || !m_gesture_pan_anchor.has_value())
m_gesture_pan_anchor = get_camera_pan_anchor(camera, ECameraNavigationType::Gesture,
screen_position - screen_delta);
pan_camera(camera, screen_delta, *m_gesture_pan_anchor);
if (evt.IsGestureEnd())
m_gesture_pan_anchor.reset();
} else if (evt.GetEventType() == wxEVT_GESTURE_ZOOM) { } else if (evt.GetEventType() == wxEVT_GESTURE_ZOOM) {
static float zoom_start = 1; static float zoom_start = 1;
if (evt.IsGestureStart()) if (evt.IsGestureStart())
zoom_start = camera.get_zoom(); zoom_start = camera.get_zoom();
camera.set_zoom(zoom_start * static_cast<wxZoomGestureEvent&>(evt).GetZoomFactor()); camera.set_zoom(zoom_start * static_cast<wxZoomGestureEvent&>(evt).GetZoomFactor());
} else if (evt.GetEventType() == wxEVT_GESTURE_ROTATE) { } else if (evt.GetEventType() == wxEVT_GESTURE_ROTATE) {
PartPlate* plate = wxGetApp().plater()->get_partplate_list().get_curr_plate(); // Orca: Rotation starts a different navigation operation, so a previous pan anchor
// must not be reused; rotation and pan fallbacks share the same navigation pivot.
m_gesture_pan_anchor.reset();
bool rotate_limit = current_printer_technology() != ptSLA; bool rotate_limit = current_printer_technology() != ptSLA;
static double last_rotate = 0; static double last_rotate = 0;
if (evt.IsGestureStart()) if (evt.IsGestureStart())
last_rotate = 0; last_rotate = 0;
auto rotate = static_cast<wxRotateGestureEvent&>(evt).GetRotationAngle() - last_rotate; auto rotate = static_cast<wxRotateGestureEvent&>(evt).GetRotationAngle() - last_rotate;
last_rotate += rotate; last_rotate += rotate;
if (plate) const std::optional<Vec3d> rotate_target = get_camera_orbit_target(ECameraNavigationType::Gesture);
camera.rotate_on_sphere_with_target(-rotate, 0, rotate_limit, plate->get_bounding_box().center()); if (rotate_target.has_value())
camera.rotate_on_sphere_with_target(-rotate, 0, rotate_limit, *rotate_target);
else else
camera.rotate_on_sphere(-rotate, 0, rotate_limit); camera.rotate_on_sphere(-rotate, 0, rotate_limit);
camera.auto_type(Camera::EType::Perspective); camera.auto_type(Camera::EType::Perspective);
@@ -4339,6 +4383,10 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
post_event(SimpleEvent(EVT_GLCANVAS_SWITCH_TO_GLOBAL)); post_event(SimpleEvent(EVT_GLCANVAS_SWITCH_TO_GLOBAL));
} }
else if (evt.LeftDown() || evt.RightDown() || evt.MiddleDown()) { else if (evt.LeftDown() || evt.RightDown() || evt.MiddleDown()) {
// Orca: Retain the click position even if the first motion event crosses a surface edge.
m_mouse.set_start_position_2D_as_invalid();
m_mouse.drag.start_position_2D = pos;
//BBS: add orient deactivate logic //BBS: add orient deactivate logic
if (!m_gizmos.on_mouse(evt)) { if (!m_gizmos.on_mouse(evt)) {
if (_deactivate_arrange_menu() || _deactivate_orient_menu()) if (_deactivate_arrange_menu() || _deactivate_orient_menu())
@@ -4532,6 +4580,9 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
} }
// do not process the dragging if the left mouse was set down in another canvas // do not process the dragging if the left mouse was set down in another canvas
else if (is_camera_rotate(evt, button_mappings)) { else if (is_camera_rotate(evt, button_mappings)) {
// Orca: Rotation and panning use different drag coordinates and cached anchors.
// Clear the pan state before processing rotation or switching buttons mid-drag.
m_mouse.set_start_position_2D_as_invalid();
if (!has_mouse_capture()) // ORCA keep tracking mouse position while drag active and cursor not in window bounds if (!has_mouse_capture()) // ORCA keep tracking mouse position while drag active and cursor not in window bounds
m_canvas->CaptureMouse(); m_canvas->CaptureMouse();
@@ -4549,12 +4600,12 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
if (this->m_canvas_type == ECanvasType::CanvasAssembleView || m_gizmos.get_current_type() == GLGizmosManager::FdmSupports || if (this->m_canvas_type == ECanvasType::CanvasAssembleView || m_gizmos.get_current_type() == GLGizmosManager::FdmSupports ||
m_gizmos.get_current_type() == GLGizmosManager::Seam || m_gizmos.get_current_type() == GLGizmosManager::MmSegmentation || m_gizmos.get_current_type() == GLGizmosManager::Seam || m_gizmos.get_current_type() == GLGizmosManager::MmSegmentation ||
m_gizmos.get_current_type() == GLGizmosManager::FuzzySkin) { m_gizmos.get_current_type() == GLGizmosManager::FuzzySkin) {
Vec3d rotate_target = Vec3d::Zero(); // Orca: Reuse the centralized pivot policy for scene-oriented tools.
if (!m_selection.is_empty()) const std::optional<Vec3d> rotate_target = get_camera_orbit_target(ECameraNavigationType::Mouse);
rotate_target = m_selection.get_bounding_box().center(); if (rotate_target.has_value())
camera.rotate_on_sphere_with_target(rot.x(), rot.y(), false, *rotate_target);
else else
rotate_target = volumes_bounding_box().center(); camera.rotate_on_sphere(rot.x(), rot.y(), false);
camera.rotate_on_sphere_with_target(rot.x(), rot.y(), false, rotate_target);
} }
else { else {
if (wxGetApp().app_config->get_bool("use_free_camera")) if (wxGetApp().app_config->get_bool("use_free_camera"))
@@ -4578,28 +4629,11 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
} }
camera.rotate_on_sphere_with_target(rot.x(), rot.y(), rotate_limit, m_rotation_center); camera.rotate_on_sphere_with_target(rot.x(), rot.y(), rotate_limit, m_rotation_center);
} else { } else {
Vec3d rotate_target = Vec3d::Zero(); // Orca: Keep regular mouse orbit and perspective-pan fallback centered
if (m_canvas_type == ECanvasType::CanvasPreview) { // on the same selection, active-plate, or scene reference.
PartPlate *plate = wxGetApp().plater()->get_partplate_list().get_curr_plate(); const std::optional<Vec3d> rotate_target = get_camera_orbit_target(ECameraNavigationType::Mouse);
if (plate) if (rotate_target.has_value())
rotate_target = plate->get_bounding_box().center(); camera.rotate_on_sphere_with_target(rot.x(), rot.y(), rotate_limit, *rotate_target);
}
else {
if (!m_selection.is_empty())
rotate_target = m_selection.get_bounding_box().center();
else {
// Rotate around the center of objects on current plate
auto bbox = volumes_bounding_box(true);
if (!bbox.defined) {
// Rotate around current plate center if current plate is empty
bbox = wxGetApp().plater()->get_partplate_list().get_curr_plate()->get_bounding_box();
}
rotate_target = bbox.center();
}
}
if (!rotate_target.isZero())
camera.rotate_on_sphere_with_target(rot.x(), rot.y(), rotate_limit, rotate_target);
else else
camera.rotate_on_sphere(rot.x(), rot.y(), rotate_limit); camera.rotate_on_sphere(rot.x(), rot.y(), rotate_limit);
} }
@@ -4615,16 +4649,14 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
m_mouse.drag.start_position_3D = Vec3d((double)pos(0), (double)pos(1), 0.0); m_mouse.drag.start_position_3D = Vec3d((double)pos(0), (double)pos(1), 0.0);
} }
else if (is_camera_pan(evt, button_mappings)) { else if (is_camera_pan(evt, button_mappings)) {
// Orca: Pan uses screen coordinates and must not inherit the rotation start point.
m_mouse.set_start_position_3D_as_invalid();
if (!has_mouse_capture()) // ORCA keep tracking mouse position while drag active and cursor not in window bounds if (!has_mouse_capture()) // ORCA keep tracking mouse position while drag active and cursor not in window bounds
m_canvas->CaptureMouse(); m_canvas->CaptureMouse();
// if dragging with right button or if button functions swapped and dragging with left button over blank area then pan // if dragging with right button or if button functions swapped and dragging with left button over blank area then pan
if (m_mouse.is_start_position_2D_defined()) { if (m_mouse.is_start_position_2D_defined()) {
// get point in model space at Z = 0
float z = 0.0f;
const Vec3d& cur_pos = _mouse_to_3d(pos, &z);
Vec3d orig = _mouse_to_3d(m_mouse.drag.start_position_2D, &z);
Camera& camera = wxGetApp().plater()->get_camera(); Camera& camera = wxGetApp().plater()->get_camera();
if (this->m_canvas_type != ECanvasType::CanvasAssembleView) { if (this->m_canvas_type != ECanvasType::CanvasAssembleView) {
// Orca: Use a constrained camera when navigating the 3D scene with a regular mouse, if the free camera is not selected // Orca: Use a constrained camera when navigating the 3D scene with a regular mouse, if the free camera is not selected
@@ -4636,7 +4668,14 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
camera.recover_from_free_camera(); camera.recover_from_free_camera();
} }
camera.set_target(camera.get_target() + orig - cur_pos); // Orca: Cache the surface under the initial click and apply every incremental
// cursor delta at that depth, so perspective zoom and camera angle stay exact.
const Vec2d screen_delta =
pos.cast<double>() - m_mouse.drag.start_position_2D.cast<double>();
if (!m_mouse.drag.camera_pan_anchor.has_value())
m_mouse.drag.camera_pan_anchor = get_camera_pan_anchor(camera, ECameraNavigationType::Mouse,
m_mouse.drag.start_position_2D.cast<double>());
pan_camera(camera, screen_delta, *m_mouse.drag.camera_pan_anchor);
m_dirty = true; m_dirty = true;
m_mouse.ignore_right_up = true; // will be reset on button up event even if not right button is pressed m_mouse.ignore_right_up = true; // will be reset on button up event even if not right button is pressed
} }
@@ -7329,11 +7368,8 @@ void GLCanvas3D::_picking_pass()
m_hover_volume_idxs.clear(); m_hover_volume_idxs.clear();
m_hover_plate_idxs.clear(); m_hover_plate_idxs.clear();
// Orca: ignore clipping plane if not applying // Orca: Picking and camera navigation must interpret the active gizmo clipping plane identically.
GLGizmoBase *current_gizmo = m_gizmos.get_current(); const ClippingPlane clipping_plane = get_raycaster_clipping_plane();
const ClippingPlane clipping_plane = ((!current_gizmo || current_gizmo->apply_clipping_plane()) ? m_gizmos.get_clipping_plane() :
ClippingPlane::ClipsNothing())
.inverted_normal();
const SceneRaycaster::HitResult hit = m_scene_raycaster.hit(m_mouse.position, wxGetApp().plater()->get_camera(), &clipping_plane); const SceneRaycaster::HitResult hit = m_scene_raycaster.hit(m_mouse.position, wxGetApp().plater()->get_camera(), &clipping_plane);
if (hit.is_valid()) { if (hit.is_valid()) {
switch (hit.type) switch (hit.type)
@@ -10627,6 +10663,129 @@ Vec3d GLCanvas3D::_mouse_to_bed_3d(const Point& mouse_pos)
return mouse_ray(mouse_pos).intersect_plane(0.0); return mouse_ray(mouse_pos).intersect_plane(0.0);
} }
ClippingPlane GLCanvas3D::get_raycaster_clipping_plane() const
{
// Orca: Ignore the gizmo clipping plane when the active tool does not apply it, and
// invert the result into the convention expected by SceneRaycaster.
GLGizmoBase* current_gizmo = m_gizmos.get_current();
return ((!current_gizmo || current_gizmo->apply_clipping_plane()) ? m_gizmos.get_clipping_plane() :
ClippingPlane::ClipsNothing())
.inverted_normal();
}
std::optional<Vec3d> GLCanvas3D::get_camera_orbit_target(ECameraNavigationType navigation_type) const
{
// Orca: Centralize the pre-existing pivot rules so orbiting and pan fallback cannot
// choose different reference depths for the same canvas and active tool.
PartPlate* current_plate = wxGetApp().plater()->get_partplate_list().get_curr_plate();
if (navigation_type == ECameraNavigationType::Gesture)
return current_plate == nullptr ? std::nullopt :
std::make_optional(current_plate->get_bounding_box().center());
const GLGizmosManager::EType gizmo_type = m_gizmos.get_current_type();
const bool use_scene_target = m_canvas_type == ECanvasType::CanvasAssembleView ||
gizmo_type == GLGizmosManager::FdmSupports || gizmo_type == GLGizmosManager::Seam ||
gizmo_type == GLGizmosManager::MmSegmentation || gizmo_type == GLGizmosManager::FuzzySkin;
if (use_scene_target) {
if (!m_selection.is_empty())
return m_selection.get_bounding_box().center();
// Orca: Preserve the world-origin fallback used by orbit in an empty scene.
return volumes_bounding_box().center();
}
// Orca: Free-camera rotation uses Camera::m_target rather than a plate or selection pivot.
if (wxGetApp().app_config->get_bool("use_free_camera"))
return std::nullopt;
Vec3d target = Vec3d::Zero();
if (m_canvas_type == ECanvasType::CanvasPreview) {
if (current_plate != nullptr)
target = current_plate->get_bounding_box().center();
} else if (!m_selection.is_empty()) {
target = m_selection.get_bounding_box().center();
} else {
// Orca: Match regular mouse orbit: objects on the active plate, then the plate itself.
BoundingBoxf3 bbox = volumes_bounding_box(true);
if (!bbox.defined && current_plate != nullptr)
bbox = current_plate->get_bounding_box();
if (bbox.defined)
target = bbox.center();
}
// Orca: Preserve the existing zero sentinel used by regular mouse orbit.
return target.isZero() ? std::nullopt : std::make_optional(target);
}
bool GLCanvas3D::is_bed_visible() const
{
if (m_canvas_type == ECanvasType::CanvasPreview)
return m_render_preview;
if (m_canvas_type != ECanvasType::CanvasView3D || !m_show_bed)
return false;
if (!m_main_toolbar.is_enabled())
return true;
const auto type = m_gizmos.get_current_type();
return type != GLGizmosManager::FdmSupports && type != GLGizmosManager::Seam &&
type != GLGizmosManager::MmSegmentation && type != GLGizmosManager::FuzzySkin;
}
Vec3d GLCanvas3D::get_camera_pan_anchor(Camera& camera, ECameraNavigationType navigation_type,
const Vec2d& screen_position) const
{
// Orthographic panning has the same scale at every depth, so no raycast is needed.
if (camera.get_type() != Camera::EType::Perspective)
return camera.get_target();
// Orca: Reject non-finite anchors and points behind the camera before their depth is
// allowed to scale a perspective pan.
const Vec3d camera_position = camera.get_position();
const Vec3d camera_forward = camera.get_dir_forward();
const auto is_valid_anchor = [&camera_position, &camera_forward](const Vec3d& anchor) {
return anchor.allFinite() && (anchor - camera_position).dot(camera_forward) > EPSILON;
};
// Orca: Prefer the nearest visible bed or volume surface and exclude gizmos and
// selected-volume picking priority from navigation depth selection.
const ClippingPlane clipping_plane = get_raycaster_clipping_plane();
const bool bed_visible = is_bed_visible();
const SceneRaycaster::HitResult hit = m_scene_raycaster.hit(screen_position, camera, &clipping_plane,
bed_visible ? SceneRaycaster::EHitMode::SceneOnly : SceneRaycaster::EHitMode::VolumesOnly);
if (hit.is_valid()) {
const Vec3d hit_position = hit.position.cast<double>();
if (is_valid_anchor(hit_position))
return hit_position;
}
// Orca: When the cursor is just outside the visible plate, use the point under it on the active
// plate plane. Using the plate center here would give it a different perspective depth.
PartPlate* current_plate = wxGetApp().plater()->get_partplate_list().get_curr_plate();
// Orca: An almost edge-on perspective makes intersection depth extremely sensitive to
// the cursor's vertical position. Use the stable orbit depth around horizontal views.
static constexpr double min_plate_plane_forward_z = 0.05;
if (bed_visible && std::abs(camera_forward.z()) >= min_plate_plane_forward_z &&
current_plate != nullptr && current_plate->get_bounding_box().defined) {
Vec3d ray_origin;
Vec3d ray_direction;
CameraUtils::ray_from_screen_pos(camera, screen_position, ray_origin, ray_direction);
const double z_direction = ray_direction.z();
if (ray_origin.allFinite() && ray_direction.allFinite() && std::abs(z_direction) > EPSILON) {
const double plate_z = current_plate->get_bounding_box().center().z();
const double distance = (plate_z - ray_origin.z()) / z_direction;
const Vec3d plate_position = ray_origin + distance * ray_direction;
const double eye_depth = (plate_position - camera_position).dot(camera_forward);
if (distance >= 0.0 && is_valid_anchor(plate_position) &&
eye_depth >= camera.get_near_z() && eye_depth <= camera.get_far_z())
return plate_position;
}
}
// Orca: Near-horizontal rays and points outside the scene depth use the orbit reference point.
const std::optional<Vec3d> orbit_target = get_camera_orbit_target(navigation_type);
return orbit_target.has_value() && is_valid_anchor(*orbit_target) ? *orbit_target : camera.get_target();
}
// While it looks like we can call // While it looks like we can call
// this->reload_scene(true, true) // this->reload_scene(true, true)
// the two functions are quite different: // the two functions are quite different:
+24 -1
View File
@@ -338,6 +338,8 @@ class GLCanvas3D
int move_volume_idx{ -1 }; int move_volume_idx{ -1 };
bool move_requires_threshold{ false }; bool move_requires_threshold{ false };
Point move_start_threshold_position_2D{ Invalid_2D_Point }; Point move_start_threshold_position_2D{ Invalid_2D_Point };
// Orca: Keep the world-space point selected at the start of a mouse pan.
std::optional<Vec3d> camera_pan_anchor;
}; };
bool dragging{ false }; bool dragging{ false };
@@ -346,7 +348,12 @@ class GLCanvas3D
Drag drag; Drag drag;
bool ignore_right_up; bool ignore_right_up;
void set_start_position_2D_as_invalid() { drag.start_position_2D = Drag::Invalid_2D_Point; } // Orca: The screen-space start and world-space anchor describe the same pan session.
// Invalidating one must invalidate the other so a new drag cannot reuse stale depth.
void set_start_position_2D_as_invalid() {
drag.start_position_2D = Drag::Invalid_2D_Point;
drag.camera_pan_anchor.reset();
}
void set_start_position_3D_as_invalid() { drag.start_position_3D = Drag::Invalid_3D_Point; } void set_start_position_3D_as_invalid() { drag.start_position_3D = Drag::Invalid_3D_Point; }
void set_move_start_threshold_position_2D_as_invalid() { drag.move_start_threshold_position_2D = Drag::Invalid_2D_Point; } void set_move_start_threshold_position_2D_as_invalid() { drag.move_start_threshold_position_2D = Drag::Invalid_2D_Point; }
@@ -549,6 +556,8 @@ private:
bool m_fps_overlay_tick{ false }; bool m_fps_overlay_tick{ false };
LayersEditing m_layers_editing; LayersEditing m_layers_editing;
Mouse m_mouse; Mouse m_mouse;
// Orca: Gesture pans have their own lifecycle and stable world-space anchor.
std::optional<Vec3d> m_gesture_pan_anchor;
GLGizmosManager m_gizmos; GLGizmosManager m_gizmos;
//BBS: GUI refactor: GLToolbar //BBS: GUI refactor: GLToolbar
mutable GLToolbar m_main_toolbar; mutable GLToolbar m_main_toolbar;
@@ -1406,6 +1415,20 @@ private:
// Convert the screen space coordinate to world coordinate on the bed. // Convert the screen space coordinate to world coordinate on the bed.
Vec3d _mouse_to_bed_3d(const Point& mouse_pos); Vec3d _mouse_to_bed_3d(const Point& mouse_pos);
// Orca: Navigation type selects the legacy pivot policy used when no visible surface is hit.
enum class ECameraNavigationType : unsigned char
{
Mouse,
Gesture
};
// Orca: These helpers keep clipping, orbit pivots, and perspective-pan depth selection consistent.
ClippingPlane get_raycaster_clipping_plane() const;
bool is_bed_visible() const;
std::optional<Vec3d> get_camera_orbit_target(ECameraNavigationType navigation_type) const;
Vec3d get_camera_pan_anchor(Camera& camera, ECameraNavigationType navigation_type,
const Vec2d& screen_position) const;
void _start_timer() { m_timer.Start(100, wxTIMER_CONTINUOUS); } void _start_timer() { m_timer.Start(100, wxTIMER_CONTINUOUS); }
void _stop_timer() { m_timer.Stop(); } void _stop_timer() { m_timer.Stop(); }
+60 -32
View File
@@ -863,8 +863,11 @@ void GUI_App::post_init()
mainframe->Freeze(); mainframe->Freeze();
#endif #endif
plater_->canvas3D()->enable_render(false); plater_->canvas3D()->enable_render(false);
mainframe->select_tab(TAB_ID_PREPARE); mainframe->select_prepare_for_gl_init();
plater_->select_view_3D("3D"); plater_->select_view_3D("3D");
// The first render happens before the queued new_project() sets the same view.
plater_->get_camera().select_view("topfront");
plater_->get_camera().requires_zoom_to_bed = true;
//BBS init the opengl resource here //BBS init the opengl resource here
if (!plater_->canvas3D()->get_wxglcanvas()->IsShownOnScreen() || if (!plater_->canvas3D()->get_wxglcanvas()->IsShownOnScreen() ||
!plater_->canvas3D()->make_current_for_postinit()) { !plater_->canvas3D()->make_current_for_postinit()) {
@@ -900,10 +903,10 @@ void GUI_App::post_init()
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", finished rendering a first frame for test"; BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", finished rendering a first frame for test";
} }
} }
if (is_editor()) if (starts_on_prepare())
mainframe->select_tab(TAB_ID_HOME);
if (app_config->get("default_page") == "1")
mainframe->select_tab(TAB_ID_PREPARE); mainframe->select_tab(TAB_ID_PREPARE);
else if (is_editor())
mainframe->select_tab(TAB_ID_HOME);
#ifndef __linux__ #ifndef __linux__
mainframe->Thaw(); mainframe->Thaw();
#endif #endif
@@ -912,6 +915,7 @@ void GUI_App::post_init()
plater_->trigger_restore_project(1); plater_->trigger_restore_project(1);
//#endif //#endif
mainframe->prebuild_pages_when_idle();
//BBS: remove GCodeViewer as seperate APP logic //BBS: remove GCodeViewer as seperate APP logic
/*if (this->init_params->start_as_gcodeviewer) { /*if (this->init_params->start_as_gcodeviewer) {
@@ -1926,9 +1930,9 @@ bool GUI_App::hot_reload_network_plugin()
m_device_manager->add_user_subscribe(); m_device_manager->add_user_subscribe();
} }
if (mainframe && mainframe->m_monitor) { if (MonitorPanel* monitor = MonitorPanel::if_built()) {
mainframe->m_monitor->update_network_version_footer(); monitor->update_network_version_footer();
mainframe->m_monitor->set_default(); monitor->set_default();
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": reset monitor panel"; BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": reset monitor panel";
} }
@@ -3419,14 +3423,16 @@ bool GUI_App::on_init_inner()
} }
BOOST_LOG_TRIVIAL(info) << "create the main window"; BOOST_LOG_TRIVIAL(info) << "create the main window";
mainframe = new MainFrame(); mainframe = new MainFrame();
// hide settings tabs after first Layout
if (is_editor()) { if (is_editor()) {
mainframe->select_tab(TAB_ID_HOME); if (starts_on_prepare()) {
mainframe->select_tab(TAB_ID_PREPARE);
} else {
mainframe->select_tab(TAB_ID_HOME);
}
} }
sidebar().obj_list()->init(); sidebar().obj_list()->init();
//sidebar().aux_list()->init_auxiliary(); //sidebar().aux_list()->init_auxiliary();
mainframe->m_project->init_auxiliary();
// update_mode(); // !!! do that later // update_mode(); // !!! do that later
SetTopWindow(mainframe); SetTopWindow(mainframe);
@@ -4137,13 +4143,13 @@ void GUI_App::select_machine(const std::string& agent_id)
// Use MonitorPanel::select_machine() to trigger full selection flow // Use MonitorPanel::select_machine() to trigger full selection flow
// This reuses existing logic for machine switching (UI updates, callbacks, etc.) // This reuses existing logic for machine switching (UI updates, callbacks, etc.)
if (mainframe && mainframe->m_monitor) { if (MonitorPanel* monitor = MonitorPanel::if_built()) {
mainframe->m_monitor->select_machine(dev_id); monitor->select_machine(dev_id);
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": triggered select_machine for dev_id=" << dev_id; BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": triggered select_machine for dev_id=" << dev_id;
} else { } else if (m_device_manager->set_selected_machine(dev_id)) {
// Fallback if MonitorPanel not available // The Device tab's own state is set when the tab is built.
m_device_manager->set_selected_machine(dev_id); MonitorPanel::on_machine_selected(m_device_manager->get_selected_machine());
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": fallback set_selected_machine dev_id=" << dev_id; BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": set_selected_machine dev_id=" << dev_id;
} }
} }
@@ -4667,6 +4673,7 @@ void GUI_App::recreate_GUI(const wxString &msg_name)
//BBS: trigger restore project logic here, and skip confirm //BBS: trigger restore project logic here, and skip confirm
plater_->trigger_restore_project(1); plater_->trigger_restore_project(1);
mainframe->prebuild_pages_when_idle();
// #ys_FIXME_delete_after_testing Do we still need this ? // #ys_FIXME_delete_after_testing Do we still need this ?
// CallAfter([]() { // CallAfter([]() {
@@ -5008,7 +5015,8 @@ void GUI_App::get_login_info(const std::string& provider/* = ORCA_CLOUD_PROVIDER
wxString strJS = wxString::Format("window.postMessage(%s)", from_u8(logout_cmd)); wxString strJS = wxString::Format("window.postMessage(%s)", from_u8(logout_cmd));
GUI::wxGetApp().run_script(strJS); GUI::wxGetApp().run_script(strJS);
} }
mainframe->m_webview->SetLoginPanelVisibility(true); if (WebViewPanel* home = WebViewPanel::if_built())
home->SetLoginPanelVisibility(true);
} }
} }
@@ -5140,9 +5148,9 @@ std::string GUI_App::handle_web_request(std::string cmd)
"homepage_bambu_login_or_register", "homepage_bambu_login_or_register",
}; };
if (app_config->get_stealth_mode() && stealth_blocked_info_commands.count(command_str)) { if (app_config->get_stealth_mode() && stealth_blocked_info_commands.count(command_str)) {
CallAfter([this] { CallAfter([] {
if (mainframe && mainframe->m_webview) if (WebViewPanel* home = WebViewPanel::if_built())
mainframe->m_webview->SendCloudProvidersInfo(); home->SendCloudProvidersInfo();
}); });
return ""; return "";
} }
@@ -5156,8 +5164,8 @@ std::string GUI_App::handle_web_request(std::string cmd)
if (dlg.ShowModal() == wxID_OK) { if (dlg.ShowModal() == wxID_OK) {
app_config->set_bool("stealth_mode", false); app_config->set_bool("stealth_mode", false);
app_config->save(); app_config->save();
if (mainframe && mainframe->m_webview) if (WebViewPanel* home = WebViewPanel::if_built())
mainframe->m_webview->SendCloudProvidersInfo(); home->SendCloudProvidersInfo();
// Continue with login // Continue with login
if (command_str == "homepage_login_or_register") if (command_str == "homepage_login_or_register")
this->request_login(true); this->request_login(true);
@@ -5238,8 +5246,8 @@ std::string GUI_App::handle_web_request(std::string cmd)
} }
else if (command_str.compare("get_recent_projects") == 0) { else if (command_str.compare("get_recent_projects") == 0) {
if (mainframe) { if (mainframe) {
if (mainframe->m_webview) { if (WebViewPanel* home = WebViewPanel::if_built()) {
mainframe->m_webview->SendRecentList(INT_MAX); home->SendRecentList(INT_MAX);
} }
} }
} }
@@ -7772,8 +7780,8 @@ void GUI_App::on_stealth_mode_enter()
BOOST_LOG_TRIVIAL(info) << "logout: on_stealth_mode_enter"; BOOST_LOG_TRIVIAL(info) << "logout: on_stealth_mode_enter";
request_user_logout(ORCA_CLOUD_PROVIDER); request_user_logout(ORCA_CLOUD_PROVIDER);
request_user_logout(BBL_CLOUD_PROVIDER); request_user_logout(BBL_CLOUD_PROVIDER);
if (mainframe && mainframe->m_webview) { if (WebViewPanel* home = WebViewPanel::if_built()) {
mainframe->m_webview->SendCloudProvidersInfo(); home->SendCloudProvidersInfo();
} }
} }
@@ -8183,6 +8191,24 @@ ConfigOptionMode GUI_App::get_saved_mode()
return saved_mode_from_string(app_config->get("user_mode")); return saved_mode_from_string(app_config->get("user_mode"));
} }
bool GUI_App::starts_on_prepare() const
{
return app_config->get("default_page") == "1";
}
int GUI_App::input_idle_ms() const
{
return int(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - m_last_input).count());
}
// Every wxCommandEvent claims the user-input category, so only real mouse and key events count.
int GUI_App::FilterEvent(wxEvent& event)
{
if (!event.IsCommandEvent() && (event.GetEventCategory() & wxEVT_CATEGORY_USER_INPUT))
m_last_input = std::chrono::steady_clock::now();
return Event_Skip;
}
ConfigOptionMode GUI_App::get_mode() ConfigOptionMode GUI_App::get_mode()
{ {
return app_config->get_bool("developer_mode") ? comDevelop : get_saved_mode(); return app_config->get_bool("developer_mode") ? comDevelop : get_saved_mode();
@@ -8234,9 +8260,10 @@ void GUI_App::update_mode()
mainframe->m_param_panel->update_mode(); mainframe->m_param_panel->update_mode();
if (mainframe->m_param_dialog) if (mainframe->m_param_dialog)
mainframe->m_param_dialog->panel()->update_mode(); mainframe->m_param_dialog->panel()->update_mode();
if (mainframe->m_printer_view) if (PrinterWebView* view = PrinterWebView::if_built())
mainframe->m_printer_view->update_mode(); view->update_mode();
mainframe->m_webview->update_mode(); if (WebViewPanel* home = WebViewPanel::if_built())
home->update_mode();
#ifdef _MSW_DARK_MODE #ifdef _MSW_DARK_MODE
if (!wxGetApp().tabs_as_menu()) if (!wxGetApp().tabs_as_menu())
@@ -8254,9 +8281,10 @@ void GUI_App::update_mode()
} }
void GUI_App::update_internal_development() { void GUI_App::update_internal_development() {
mainframe->m_webview->update_mode(); if (WebViewPanel* home = WebViewPanel::if_built())
if (mainframe->m_printer_view) home->update_mode();
mainframe->m_printer_view->update_mode(); if (PrinterWebView* view = PrinterWebView::if_built())
view->update_mode();
} }
void GUI_App::show_ip_address_enter_dialog(wxString title) void GUI_App::show_ip_address_enter_dialog(wxString title)
+7
View File
@@ -1,6 +1,7 @@
#ifndef slic3r_GUI_App_hpp_ #ifndef slic3r_GUI_App_hpp_
#define slic3r_GUI_App_hpp_ #define slic3r_GUI_App_hpp_
#include <chrono>
#include <functional> #include <functional>
#include <memory> #include <memory>
#include <string> #include <string>
@@ -248,6 +249,7 @@ private:
bool m_app_conf_exists{ false }; bool m_app_conf_exists{ false };
EAppMode m_app_mode{ EAppMode::Editor }; EAppMode m_app_mode{ EAppMode::Editor };
bool m_is_recreating_gui{ false }; bool m_is_recreating_gui{ false };
std::chrono::steady_clock::time_point m_last_input{ std::chrono::steady_clock::now() };
#ifdef __linux__ #ifdef __linux__
bool m_opengl_initialized{ false }; bool m_opengl_initialized{ false };
#endif #endif
@@ -387,6 +389,11 @@ public:
bool is_editor() const { return m_app_mode == EAppMode::Editor; } bool is_editor() const { return m_app_mode == EAppMode::Editor; }
bool is_gcode_viewer() const { return m_app_mode == EAppMode::GCodeViewer; } bool is_gcode_viewer() const { return m_app_mode == EAppMode::GCodeViewer; }
bool is_recreating_gui() const { return m_is_recreating_gui; } bool is_recreating_gui() const { return m_is_recreating_gui; }
// Milliseconds since the last mouse or keyboard event the app processed.
int input_idle_ms() const;
int FilterEvent(wxEvent& event) override;
// The Preferences "Default page" choice, stored as its index: 0 Home, 1 Prepare.
bool starts_on_prepare() const;
std::string logo_name() const { return is_editor() ? "OrcaSlicer" : "OrcaSlicer-gcodeviewer"; } std::string logo_name() const { return is_editor() ? "OrcaSlicer" : "OrcaSlicer-gcodeviewer"; }
bool is_closing() const { return m_is_closing.load(std::memory_order_acquire); } bool is_closing() const { return m_is_closing.load(std::memory_order_acquire); }
+2 -1
View File
@@ -122,7 +122,8 @@ HMSNotifyItem::HMSNotifyItem(const std::string& dev_id, wxWindow *parent, DevHMS
m_hms_content->Bind(wxEVT_LEFT_UP, [this](wxMouseEvent& e) { m_hms_content->Bind(wxEVT_LEFT_UP, [this](wxMouseEvent& e) {
wxCommandEvent evt(EVT_ALREADY_READ_HMS); wxCommandEvent evt(EVT_ALREADY_READ_HMS);
evt.SetString(long_error_code); evt.SetString(long_error_code);
wxPostEvent(wxGetApp().mainframe->m_monitor, evt); if (MonitorPanel* monitor = MonitorPanel::if_built())
wxPostEvent(monitor, evt);
if (!m_url.empty()) wxLaunchDefaultBrowser(m_url); if (!m_url.empty()) wxLaunchDefaultBrowser(m_url);
}); });
+100
View File
@@ -0,0 +1,100 @@
#include "IdleScheduler.hpp"
#include <chrono>
#include <boost/log/trivial.hpp>
#include "libslic3r/Utils.hpp"
#ifdef _WIN32
#include <windows.h>
#endif
namespace Slic3r { namespace GUI {
namespace {
// The timer's period while waiting for the user to go quiet.
constexpr int tick_ms = 250;
// Input-free time before a slice may start, about a double-click interval, so a user
// mid-gesture is left alone.
constexpr int quiet_ms = 500;
// Budget of one slice. The next slice is a timer message, so paint, timers and input
// queued meanwhile are handled first; a click waits at most a slice plus the unit that
// overran it.
constexpr int slice_ms = 40;
// On GTK a due timer runs ahead of repaints and posted events, so the next slice waits a few ms.
#ifdef __WXGTK__
constexpr int next_slice_ms = 5;
#else
constexpr int next_slice_ms = 0;
#endif
// True when unhandled keyboard, button, touch or pen input is queued; only Windows can ask.
bool input_pending()
{
#ifdef _WIN32
// Windows synthesizes a mouse move whenever a window appears under the cursor, so those
// do not count.
return (GetQueueStatus(QS_INPUT & ~QS_MOUSEMOVE) >> 16) != 0;
#else
return false;
#endif
}
} // namespace
IdleScheduler::IdleScheduler(std::function<int()> input_idle_ms) : m_input_idle_ms(std::move(input_idle_ms))
{
m_timer.Bind(wxEVT_TIMER, [this](wxTimerEvent&) { tick(); });
}
void IdleScheduler::start()
{
if (!m_timer.IsRunning())
m_timer.Start(tick_ms);
}
void IdleScheduler::stop()
{
m_timer.Stop();
}
void IdleScheduler::tick()
{
// A unit that pumps the event loop lets the timer fire inside its own slice.
if (m_in_slice)
return;
if (!m_queue.pending()) {
stop();
return;
}
if (m_input_idle_ms() < quiet_ms || input_pending()) {
start();
return;
}
const auto now_ms = [] {
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
};
const char* const fn = __FUNCTION__;
m_in_slice = true;
PrebuildQueue::Slice slice;
{
ScopeGuard in_slice([this] { m_in_slice = false; });
slice = m_queue.run_slice(slice_ms, now_ms, input_pending, [fn](const std::string& name, long long ms) {
BOOST_LOG_TRIVIAL(debug) << fn << ": " << name << ": unit took " << ms << " ms";
});
}
if (slice.completed)
BOOST_LOG_TRIVIAL(info) << fn << ": task complete: " << slice.name << ", " << slice.units << " unit(s) in " << slice.ms << " ms this slice";
else
BOOST_LOG_TRIVIAL(debug) << fn << ": " << slice.name << ": " << slice.units << " unit(s) in " << slice.ms << " ms, yielding";
if (!slice.remaining)
stop();
else if (input_pending())
m_timer.Start(tick_ms);
else
m_timer.StartOnce(next_slice_ms);
}
}} // namespace Slic3r::GUI

Some files were not shown because too many files have changed in this diff Show More