Merge remote-tracking branch 'remotes/prusa/master'
@ -34,6 +34,8 @@ option(SLIC3R_PERL_XS "Compile XS Perl module and enable Perl unit and
|
||||
option(SLIC3R_ASAN "Enable ASan on Clang and GCC" 0)
|
||||
option(SLIC3R_SYNTAXONLY "Only perform source code correctness checking, no binary output (UNIX only)" 0)
|
||||
|
||||
set(SLIC3R_GTK "2" CACHE STRING "GTK version to use with wxWidgets on Linux")
|
||||
|
||||
# Proposal for C++ unit tests and sandboxes
|
||||
option(SLIC3R_BUILD_SANDBOXES "Build development sandboxes" OFF)
|
||||
option(SLIC3R_BUILD_TESTS "Build unit tests" OFF)
|
||||
|
@ -7,7 +7,7 @@ as the versions listed - generally versions available on conservative Linux dist
|
||||
|
||||
Perl is not required any more.
|
||||
|
||||
In a typical situaction, one would open a command line, go to the Slic3r sources, create a directory called `build` or similar,
|
||||
In a typical situation, one would open a command line, go to the Slic3r sources, create a directory called `build` or similar,
|
||||
`cd` into it and call:
|
||||
|
||||
cmake ..
|
||||
@ -19,7 +19,7 @@ Additional CMake flags may be applicable as explained below.
|
||||
|
||||
### Dependency resolution
|
||||
|
||||
By default Slic3r looks for dependencies the default way CMake looks for them, ie. in default system locations.
|
||||
By default Slic3r looks for dependencies the default way CMake looks for them, i.e. in default system locations.
|
||||
On Linux this will typically make Slic3r depend on dynamically loaded libraries from the system, however, Slic3r can be told
|
||||
to specifically look for static libraries with the `SLIC3R_STATIC` flag passed to cmake:
|
||||
|
||||
@ -58,16 +58,25 @@ Note that Slic3r PE is tested with wxWidgets 3.0 somewhat sporadically and so th
|
||||
|
||||
### Build variant
|
||||
|
||||
By default Scli3r builds the release variant.
|
||||
By default Slic3r builds the release variant.
|
||||
To create a debug build, use the following CMake flag:
|
||||
|
||||
-DCMAKE_BUILD_TYPE=Debug
|
||||
|
||||
### Enabling address sanitizer
|
||||
|
||||
If you're using GCC/Clang compiler, it is possible to build Slic3r with the built-in address sanitizer enabled to help detect memory-corruption issues.
|
||||
To enable it, simply use the following CMake flag:
|
||||
|
||||
-DSLIC3R_ASAN=1
|
||||
|
||||
This requires GCC>4.8 or Clang>3.1.
|
||||
|
||||
### Installation
|
||||
|
||||
In runtime, Slic3r needs a way to access its resource files. By default, it looks for a `resources` directory relative to its binary.
|
||||
At runtime, Slic3r needs a way to access its resource files. By default, it looks for a `resources` directory relative to its binary.
|
||||
|
||||
If you instead wnat Slic3r installed in a structure according to the Filesystem Hierarchy Standard, use the `SLIC3R_FHS` flag
|
||||
If you instead want Slic3r installed in a structure according to the File System Hierarchy Standard, use the `SLIC3R_FHS` flag
|
||||
|
||||
cmake .. -DSLIC3R_FHS=1
|
||||
|
||||
|
@ -18,12 +18,12 @@ This will create a dependencies bundle inside the `build/destdir` directory.
|
||||
You can also customize the bundle output path using the `-DDESTDIR=<some path>` option passed to `cmake`.
|
||||
|
||||
**Warning**: Once the dependency bundle is installed in a destdir, the destdir cannot be moved elsewhere.
|
||||
(This is because wxWidgets hardcode the installation path.)
|
||||
(This is because wxWidgets hardcodes the installation path.)
|
||||
|
||||
|
||||
### Building Slic3r
|
||||
|
||||
If dependencies built without an error, you can proceed to build Slic3r itself.
|
||||
If dependencies are built without errors, you can proceed to build Slic3r itself.
|
||||
Go back to top level Slic3r sources directory and use these commands:
|
||||
|
||||
mkdir build
|
||||
|
@ -7,7 +7,7 @@ CMake installer can be downloaded from [the official website](https://cmake.org/
|
||||
|
||||
Building with newer versions of MSVS (2015, 2017) may work too as reported by some of our users.
|
||||
|
||||
_Note:_ Thanks to [**@supermerill**](https://github.com/supermerill) for testing and inspiration on this guide.
|
||||
_Note:_ Thanks to [**@supermerill**](https://github.com/supermerill) for testing and inspiration for this guide.
|
||||
|
||||
### Dependencies
|
||||
|
||||
@ -20,7 +20,7 @@ The package comes in a several variants:
|
||||
- [32 bit, Release mode only](https://bintray.com/vojtechkral/Slic3r-PE/download_file?file_path=destdir-32.7z) (38 MB, 520 MB unpacked)
|
||||
- [32 bit, Release and Debug mode](https://bintray.com/vojtechkral/Slic3r-PE/download_file?file_path=destdir-32-dev.7z) (74 MB, 1.1 GB unpacked)
|
||||
|
||||
When unsure, use the _Release mode only_ variant, the _Release and Debug_ variant is only needed for debugging & developement.
|
||||
When unsure, use the _Release mode only_ variant, the _Release and Debug_ variant is only needed for debugging & development.
|
||||
|
||||
If you're unsure where to unpack the package, unpack it into `C:\local\` (but it can really be anywhere).
|
||||
|
||||
@ -46,13 +46,13 @@ Conversely, if you're using Visual Studio version other than 2013, the version n
|
||||
|
||||
If `cmake` has finished without errors, go to the build directory and open the `Slic3r.sln` solution file in Visual Studio.
|
||||
Before building, make sure you're building the right project (use one of those starting with `slic3r_app_...`) and that you're building
|
||||
with the right configuration, ie. _Release_ vs. _Debug_. When unsure, choose _Release_.
|
||||
with the right configuration, i.e. _Release_ vs. _Debug_. When unsure, choose _Release_.
|
||||
Note that you won't be able to build a _Debug_ variant against a _Release_-only dependencies package.
|
||||
|
||||
#### Installing using the `INSTALL` project
|
||||
|
||||
Slic3r PE can be run from the Visual Studio or from Visual Studio's build directory (`src\Release` or `src\Debug`),
|
||||
but for longer-term usage you migth want to install somewhere using the `INSTALL` project.
|
||||
but for longer-term usage you might want to install somewhere using the `INSTALL` project.
|
||||
By default, this installs into `C:\Program Files\Slic3r`.
|
||||
To customize the install path, use the `-DCMAKE_INSTALL_PREFIX=<path of your choice>` when invoking `cmake`.
|
||||
|
||||
@ -91,7 +91,11 @@ You can also use the Visual Studio GUI or other generators as mentioned above.
|
||||
The `DESTDIR` option is the location where the bundle will be installed.
|
||||
This may be customized. If you leave it empty, the `DESTDIR` will be places inside the same `build` directory.
|
||||
|
||||
Note that the build variant that you may choose using Visual Studio (ie. _Release_ or _Debug_ etc.) when building the dependency package is **not relevant**.
|
||||
Warning: If the `build` directory is nested too deep inside other folders, various file paths during the build
|
||||
become too long and the build might fail due to file writing errors. For this reason, it is recommended to
|
||||
place the `build` directory relatively close to the drive root.
|
||||
|
||||
Note that the build variant that you may choose using Visual Studio (i.e. _Release_ or _Debug_ etc.) when building the dependency package is **not relevant**.
|
||||
The dependency build will by default build _both_ the _Release_ and _Debug_ variants regardless of what you choose in Visual Studio.
|
||||
You can disable building of the debug variant by passing the `-DDEP_DEBUG=OFF` option to CMake, this will only produce a _Release_ build.
|
||||
|
||||
|
@ -2,20 +2,20 @@
|
||||
|
||||
The purpose of this guide is to describe how to contribute to the Slic3rPE translations. We use GNUgettext for extracting string resources from the project and PoEdit for editing translations.
|
||||
|
||||
Those are possible to download here:
|
||||
Those can be downloaded here:
|
||||
- https://sourceforge.net/directory/os:windows/?q=gnu+gettext GNUgettext package contains a set of tools to extract strings from the source code and to create the translation Catalog.
|
||||
- https://poedit.net PoEdit provides good interface for the translators.
|
||||
|
||||
After GNUgettext is installed it is recommended to add the path to gettext/bin to PATH variable.
|
||||
After GNUgettext is installed, it is recommended to add the path to gettext/bin to PATH variable.
|
||||
|
||||
Full manual for GNUgettext you can see here: http://www.gnu.org/software/gettext/manual/gettext.html
|
||||
Full manual for GNUgettext can be seen here: http://www.gnu.org/software/gettext/manual/gettext.html
|
||||
|
||||
|
||||
### Scenario 1. How do I add a translation or fix the existing translation
|
||||
### Scenario 1. How do I add a translation or fix an existing translation
|
||||
1. Get PO-file from corresponding folder here:
|
||||
https://github.com/prusa3d/Slic3r/tree/master/resources/localization
|
||||
2. Open this file in PoEdit as "Edit a translation"
|
||||
3. Apply your corrections to translation
|
||||
3. Apply your corrections to the translation
|
||||
4. Push changed Slic3rPE.po and Slic3rPE.mo (will create automatically after saving of Slic3r.po in PoEdit) back to to the enter folder.
|
||||
|
||||
### Scenario 2. How do I add a new language support
|
||||
@ -23,10 +23,10 @@ https://github.com/prusa3d/Slic3r/tree/master/resources/localization
|
||||
https://github.com/prusa3d/Slic3r/tree/master/resources/localization
|
||||
2. Open it in PoEdit for "Create new translation"
|
||||
3. Select Translation Language (for example French).
|
||||
4. As a result you will have fr.po - the file contaning translation to French.
|
||||
Notice. When the transtation is complete you need to:
|
||||
4. As a result you will have fr.po - the file containing translation to French.
|
||||
Notice. When the translation is complete you need to:
|
||||
- Rename the file to Slic3rPE.po
|
||||
- Click "Save file" button. Slic3rPE.mo will be created immediatly
|
||||
- Click "Save file" button. Slic3rPE.mo will be created immediately
|
||||
- Both Slic3rPE.po and Slic3rPE.mo have to be saved here:
|
||||
https://github.com/prusa3d/Slic3r/tree/master/resources/localization/fr
|
||||
( name of folder "fr" means "French" - the translation language).
|
||||
@ -37,11 +37,11 @@ Each string resource in Slic3rPE available for translation needs to be explicitl
|
||||
auto msg = L("This message to be localized")
|
||||
```
|
||||
To get translated text use one of needed macro/function (`_(s)`, `_CHB(s)` or `L_str(s)` ).
|
||||
If you add new file resourse, add it to list of files contaned macro `L()`
|
||||
If you add new file resource, add it to the list of files containing macro `L()`
|
||||
|
||||
### Scenario 4. How do I use GNUgettext to localize my own application taking Slic3rPE as an example
|
||||
|
||||
1. For conviniance create list of files with this macro `L(s)`. We have
|
||||
1. For convenience create a list of files with this macro `L(s)`. We have
|
||||
https://github.com/prusa3d/Slic3r/tree/master/resources/localization/list.txt.
|
||||
|
||||
2. Create template file(*.POT) with GNUgettext command:
|
||||
@ -50,11 +50,11 @@ https://github.com/prusa3d/Slic3r/tree/master/resources/localization/list.txt.
|
||||
```
|
||||
|
||||
Use flag `--from-code=UTF-8` to specify that the source strings are in UTF-8 encoding
|
||||
Use flag `--debug` to correctly extract formated strings(used %d, %s etc.)
|
||||
Use flag `--debug` to correctly extract formatted strings(used %d, %s etc.)
|
||||
|
||||
3. Create PO- and MO-files for your project as described above.
|
||||
|
||||
4. To merge old PO-file with strings from creaded new POT-file use command:
|
||||
4. To merge old PO-file with strings from created new POT-file use command:
|
||||
```
|
||||
msgmerge -N -o new.po old.po new.pot
|
||||
```
|
||||
@ -71,6 +71,6 @@ https://github.com/prusa3d/Slic3r/tree/master/resources/localization/list.txt.
|
||||
```
|
||||
Notice, in this Catalog it will be totally same strings for initial text and translated.
|
||||
|
||||
When you have Catalog to translation open POT or PO file in PoEdit and start to translation.
|
||||
It's very important to keep attention to every gaps and punctuation. Especially with
|
||||
formated strings. (used %d, %s etc.)
|
||||
When you have Catalog to translation open POT or PO file in PoEdit and start to translation,
|
||||
it's very important to keep attention to every gaps and punctuation. Especially with
|
||||
formatted strings. (using %d, %s, etc.)
|
@ -12,7 +12,7 @@ There are three new features:
|
||||
- _System preset_: These are the presets that come with Slic3r PE installation. They come from a vendor configuration bundle (not individual files like before). They are **read-only** – a user cannot modify them, but may instead create a derived User preset based on a System preset
|
||||
- _User preset_: These are regular presets stored in files just like before. Additionally, they may be derived (inherited) from one of the System presets
|
||||
|
||||
A derived User preset keeps track of wich settings are inherited from the parent System preset and which are modified by the user. When a system preset is updated (either via installation of a new Slic3r or automatically from the internet), in a User preset the settings that are modified by the user will stay that way, while the ones that are inherited reflect the updated System preset.
|
||||
A derived User preset keeps track of which settings are inherited from the parent System preset and which are modified by the user. When a system preset is updated (either via installation of a new Slic3r or automatically from the internet), in a User preset the settings that are modified by the user will stay that way, while the ones that are inherited reflect the updated System preset.
|
||||
|
||||
This system ensures that we don't overwrite user's settings when there is an update to the built in presets.
|
||||
|
||||
@ -25,9 +25,9 @@ A settings modified in a User preset has an open lock icon:
|
||||
|
||||

|
||||
|
||||
Clickign the open lock icon restored the system setting.
|
||||
Clicking the open lock icon restores the system setting.
|
||||
|
||||
Additionaly, any setting that is modified but not yet saved onto disk is represented by orange label and a back-arrow:
|
||||
Additionally, any setting that is modified but not yet saved onto disk is represented by orange label and a back-arrow:
|
||||
|
||||

|
||||
|
17
resources/icons/add.svg
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
|
||||
<path fill="#FFFFFF" d="M87.29,22.62H34.71c-1.39,0-3.14,0.69-4.16,1.63L9.81,43.46c-1.05,0.98-1.82,2.73-1.82,4.16v54.31
|
||||
c0,1.9,1.55,3.45,3.45,3.45h55.17c1.4,0,3.15-0.7,4.16-1.67l12.41-11.83c0.69-0.66,0.72-1.75,0.06-2.44s-1.75-0.71-2.44-0.06
|
||||
L70.05,99.63v-53.2c0.26-0.19,0.51-0.39,0.72-0.61L87.3,28.29v33.12c0,0.35-0.02,0.64-0.04,0.85c-0.51,0.55-0.62,1.39-0.22,2.06
|
||||
c0.49,0.82,1.55,1.08,2.37,0.59l0.25-0.15c0.67-0.4,1.09-1.1,1.09-3.35V26.07C90.74,24.17,89.2,22.62,87.29,22.62z M11.44,47.62
|
||||
L11.44,47.62h55.17v54.31H11.44V47.62z M68.26,43.46c-0.33,0.35-1.18,0.71-1.65,0.71H14.12L32.9,26.78
|
||||
c0.37-0.35,1.31-0.71,1.82-0.71h49.94L68.26,43.46z"/>
|
||||
<path id="_x2B__1_" fill="#ED6B21" d="M110.57,82.1c0,0.95-0.78,1.72-1.72,1.72h-4.31c-0.95,0-1.72,0.78-1.72,1.72v4.31
|
||||
c0,0.95-0.78,1.72-1.72,1.72h-4.31c-0.95,0-1.72-0.78-1.72-1.72v-4.31c0-0.95-0.78-1.72-1.72-1.72h-4.31
|
||||
c-0.95,0-1.72-0.78-1.72-1.72v-4.31c0-0.95,0.78-1.72,1.72-1.72h4.31c0.95,0,1.72-0.78,1.72-1.72v-4.31c0-0.95,0.78-1.72,1.72-1.72
|
||||
h4.31c0.95,0,1.72,0.78,1.72,1.72v4.31c0,0.95,0.78,1.72,1.72,1.72h4.31c0.95,0,1.72,0.78,1.72,1.72V82.1z M120.05,79.95
|
||||
c0-11.65-9.47-21.12-21.12-21.12S77.81,68.3,77.81,79.95s9.47,21.12,21.12,21.12S120.05,91.59,120.05,79.95z M116.6,79.95
|
||||
c0,9.74-7.93,17.67-17.67,17.67s-17.67-7.93-17.67-17.67s7.93-17.67,17.67-17.67S116.6,70.2,116.6,79.95z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.6 KiB |
24
resources/icons/arrange.svg
Normal file
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
|
||||
<g id="ARRANGE">
|
||||
<path fill="#FFFFFF" d="M113.85,14.27v99.36h-99.7V14.27H113.85 M115.85,8.27H12.15c-2.2,0-4,1.8-4,4v103.36c0,2.2,1.8,4,4,4h103.7
|
||||
c2.2,0,4-1.8,4-4V12.27C119.85,10.07,118.05,8.27,115.85,8.27L115.85,8.27z"/>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M48.04,99.24c0,2.2-1.8,4-4,4H28.11c-2.2,0-4-1.8-4-4v-47c0-2.2,1.8-4,4-4h15.94c2.2,0,4,1.8,4,4
|
||||
L48.04,99.24L48.04,99.24z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M28.11,40.38c-2.2,0-4-1.8-4-4v-7.72c0-2.2,1.8-4,4-4h15.94c2.2,0,4,1.8,4,4v7.72c0,2.2-1.8,4-4,4H28.11z"
|
||||
/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M68,103.24c-2.2,0-4-1.8-4-4V83.67c0-2.2,1.8-4,4-4h31.89c2.2,0,4,1.8,4,4v15.57c0,2.2-1.8,4-4,4H68z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M103.89,59.95c0,2.2-1.8,4-4,4H68c-2.2,0-4-1.8-4-4V28.66c0-2.2,1.8-4,4-4h31.89c2.2,0,4,1.8,4,4V59.95z"
|
||||
/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 144 KiB |
Before Width: | Height: | Size: 364 KiB |
Before Width: | Height: | Size: 398 KiB |
Before Width: | Height: | Size: 794 KiB |
Before Width: | Height: | Size: 63 KiB |
Before Width: | Height: | Size: 159 KiB |
Before Width: | Height: | Size: 143 KiB |
Before Width: | Height: | Size: 361 KiB |
Before Width: | Height: | Size: 396 KiB |
Before Width: | Height: | Size: 790 KiB |
Before Width: | Height: | Size: 63 KiB |
Before Width: | Height: | Size: 159 KiB |
Before Width: | Height: | Size: 105 KiB |
Before Width: | Height: | Size: 277 KiB |
Before Width: | Height: | Size: 324 KiB |
Before Width: | Height: | Size: 674 KiB |
Before Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 20 KiB |
28
resources/icons/cut.svg
Normal file
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
|
||||
<g id="cut">
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M118.12,65.5h-10c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h10c0.83,0,1.5,0.67,1.5,1.5
|
||||
S118.95,65.5,118.12,65.5z M98.12,65.5h-10c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h10c0.83,0,1.5,0.67,1.5,1.5
|
||||
S98.95,65.5,98.12,65.5z M78.12,65.5h-10c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h10c0.83,0,1.5,0.67,1.5,1.5
|
||||
S78.95,65.5,78.12,65.5z M58.12,65.5h-10c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h10c0.83,0,1.5,0.67,1.5,1.5
|
||||
S58.95,65.5,58.12,65.5z M38.12,65.5h-10c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h10c0.83,0,1.5,0.67,1.5,1.5
|
||||
S38.95,65.5,38.12,65.5z M18.12,65.5h-10c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h10c0.83,0,1.5,0.67,1.5,1.5
|
||||
S18.95,65.5,18.12,65.5z"/>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M108.79,51.6H19.21c-1.93,0-3.5-1.57-3.5-3.5V10.12c0-1.93,1.57-3.5,3.5-3.5h89.57
|
||||
c1.93,0,3.5,1.57,3.5,3.5V48.1C112.29,50.03,110.71,51.6,108.79,51.6z M19.21,9.62c-0.27,0-0.5,0.23-0.5,0.5V48.1
|
||||
c0,0.27,0.23,0.5,0.5,0.5h89.57c0.27,0,0.5-0.23,0.5-0.5V10.12c0-0.27-0.23-0.5-0.5-0.5H19.21z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M108.79,121.38H19.21c-1.93,0-3.5-1.57-3.5-3.5V79.4c0-1.93,1.57-3.5,3.5-3.5h89.57
|
||||
c1.93,0,3.5,1.57,3.5,3.5v38.49C112.29,119.81,110.71,121.38,108.79,121.38z M19.21,78.9c-0.27,0-0.5,0.23-0.5,0.5v38.49
|
||||
c0,0.27,0.23,0.5,0.5,0.5h89.57c0.27,0,0.5-0.23,0.5-0.5V79.4c0-0.27-0.23-0.5-0.5-0.5H19.21z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.7 KiB |
31
resources/icons/delete_all.svg
Normal file
@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
|
||||
<g id="DELETE_ALL_1_">
|
||||
<path fill="#FFFFFF" d="M103.52,43.87l-13.31,69.97H37.79L24.48,43.87H103.52 M108.77,37.87H19.23c-1.1,0-1.83,0.88-1.63,1.96
|
||||
l14.84,78.04c0.21,1.08,1.27,1.96,2.37,1.96h58.36c1.1,0,2.17-0.88,2.37-1.96l14.84-78.04C110.6,38.75,109.87,37.87,108.77,37.87
|
||||
L108.77,37.87z"/>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M89.38,22.97c-1.1,0-2-0.9-2-2v-10.9c0-1.1-0.9-2-2-2H42.62c-1.1,0-2,0.9-2,2v10.9c0,1.1-0.9,2-2,2H19.23
|
||||
c-1.1,0-2,0.9-2,2v3.45c0,1.1,0.9,2,2,2h89.54c1.1,0,2-0.9,2-2v-3.45c0-1.1-0.9-2-2-2H89.38z M79.59,20.97c0,1.1-0.9,2-2,2H50.41
|
||||
c-1.1,0-2-0.9-2-2v-3.45c0-1.1,0.9-2,2-2h27.18c1.1,0,2,0.9,2,2V20.97z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M93.17,73.5H34.83c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h58.34c0.83,0,1.5,0.67,1.5,1.5
|
||||
S94,73.5,93.17,73.5z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M90.14,89.45H37.96c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h52.18c0.83,0,1.5,0.67,1.5,1.5
|
||||
S90.97,89.45,90.14,89.45z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M87.1,105.4H40.9c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h46.2c0.83,0,1.5,0.67,1.5,1.5
|
||||
S87.93,105.4,87.1,105.4z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M96.2,57.56H31.8c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h64.4c0.83,0,1.5,0.67,1.5,1.5
|
||||
S97.03,57.56,96.2,57.56z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.6 KiB |
20
resources/icons/editor.svg
Normal file
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
|
||||
<g id="editor">
|
||||
<g>
|
||||
<path fill="none" stroke="#ED6B21" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
|
||||
M118.68,8.83L92.1,37.03c-0.75,0.8-2.27,1.46-3.37,1.46H9.44"/>
|
||||
</g>
|
||||
<g>
|
||||
|
||||
<line fill="none" stroke="#ED6B21" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="90.72" y1="118.69" x2="90.72" y2="38.81"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="none" stroke="#ED6B21" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
|
||||
M119.88,91.51v-81.4c0-1.1-0.9-2-2-2H42.92c-1.1,0-2.66,0.61-3.47,1.36L9.59,37.13c-0.81,0.75-1.47,2.26-1.47,3.36v77.39
|
||||
c0,1.1,0.9,2,2,2h78.61c1.1,0,2.65-0.63,3.44-1.39l27.67-26.82"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
BIN
resources/icons/empty_icon.png
Normal file
After Width: | Height: | Size: 893 B |
BIN
resources/icons/gizmos.png
Normal file
After Width: | Height: | Size: 19 KiB |
50
resources/icons/instance_add.svg
Normal file
@ -0,0 +1,50 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
|
||||
<g id="ADD_INSTANCE">
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M88.01,57.95c0-1.1-0.9-2-2-2H74c-1.1,0-2-0.9-2-2V41.94c0-1.1-0.9-2-2-2H58c-1.1,0-2,0.9-2,2v12.01
|
||||
c0,1.1-0.9,2-2,2H41.99c-1.1,0-2,0.9-2,2v12.01c0,1.1,0.9,2,2,2H54c1.1,0,2,0.9,2,2v12.01c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2
|
||||
V73.95c0-1.1,0.9-2,2-2h12.01c1.1,0,2-0.9,2-2V57.95z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M67.06,119.73c-2.1,0-3.87-1.64-3.99-3.77c-0.13-2.21,1.56-4.1,3.76-4.23c1.85-0.11,3.71-0.32,5.53-0.64
|
||||
c2.17-0.38,4.25,1.07,4.63,3.25s-1.07,4.25-3.25,4.63c-2.12,0.37-4.29,0.63-6.45,0.75C67.22,119.73,67.14,119.73,67.06,119.73z
|
||||
M55.05,119.05c-0.23,0-0.46-0.02-0.69-0.06c-2.13-0.37-4.26-0.87-6.32-1.49c-2.12-0.63-3.32-2.86-2.69-4.98s2.86-3.32,4.98-2.69
|
||||
c1.77,0.53,3.59,0.96,5.41,1.27c2.18,0.38,3.63,2.45,3.25,4.63C58.65,117.68,56.96,119.05,55.05,119.05z M84.58,115.58
|
||||
c-1.55,0-3.02-0.9-3.67-2.41c-0.88-2.03,0.06-4.38,2.08-5.26c1.69-0.73,3.36-1.57,4.96-2.5c1.91-1.11,4.36-0.46,5.47,1.46
|
||||
c1.11,1.91,0.46,4.36-1.46,5.47c-1.87,1.08-3.82,2.07-5.8,2.92C85.65,115.47,85.11,115.58,84.58,115.58z M38.12,112.91
|
||||
c-0.68,0-1.37-0.17-2-0.54c-1.87-1.08-3.69-2.28-5.43-3.57c-1.77-1.32-2.14-3.82-0.82-5.6c1.32-1.77,3.82-2.14,5.6-0.82
|
||||
c1.49,1.11,3.05,2.13,4.65,3.06c1.91,1.1,2.57,3.55,1.47,5.46C40.84,112.2,39.5,112.91,38.12,112.91z M99.61,105.67
|
||||
c-1.06,0-2.12-0.42-2.91-1.25c-1.52-1.61-1.45-4.14,0.16-5.66c1.35-1.27,2.63-2.64,3.82-4.05c1.42-1.69,3.94-1.91,5.64-0.49
|
||||
c1.69,1.42,1.91,3.94,0.49,5.64c-1.39,1.65-2.88,3.24-4.45,4.72C101.58,105.3,100.59,105.67,99.61,105.67z M24.32,101.35
|
||||
c-1.14,0-2.27-0.48-3.06-1.42c-1.39-1.65-2.7-3.4-3.89-5.2c-1.22-1.84-0.71-4.32,1.13-5.54c1.84-1.22,4.32-0.71,5.54,1.13
|
||||
c1.02,1.54,2.14,3.04,3.33,4.46c1.42,1.69,1.21,4.21-0.48,5.64C26.14,101.04,25.23,101.35,24.32,101.35z M110.36,91.23
|
||||
c-0.6,0-1.22-0.14-1.79-0.43c-1.97-0.99-2.77-3.4-1.78-5.37c0.83-1.65,1.57-3.37,2.2-5.11c0.75-2.08,3.05-3.15,5.13-2.39
|
||||
c2.08,0.75,3.15,3.05,2.39,5.13c-0.74,2.03-1.61,4.04-2.58,5.97C113.24,90.42,111.83,91.23,110.36,91.23z M15.28,85.78
|
||||
c-1.63,0-3.16-1-3.76-2.63c-0.74-2.03-1.37-4.12-1.87-6.22c-0.51-2.15,0.82-4.31,2.97-4.82s4.31,0.82,4.82,2.97
|
||||
c0.43,1.8,0.97,3.59,1.6,5.32c0.76,2.08-0.31,4.37-2.38,5.13C16.2,85.7,15.73,85.78,15.28,85.78z M115.53,73.97
|
||||
c-0.15,0-0.31-0.01-0.46-0.03c-2.19-0.25-3.77-2.24-3.52-4.43c0.21-1.83,0.32-3.7,0.32-5.56v-0.21c0-2.21,1.79-4,4-4s4,1.79,4,4
|
||||
v0.15c0,2.22-0.12,4.4-0.37,6.53C119.26,72.47,117.53,73.97,115.53,73.97z M12.13,68.05c-2.21,0-4-1.79-4-4h4l-4-0.05
|
||||
c0-2.18,0.12-4.33,0.36-6.42c0.25-2.19,2.24-3.76,4.43-3.52c2.2,0.25,3.77,2.23,3.52,4.43c-0.21,1.8-0.31,3.64-0.31,5.46v0.1
|
||||
C16.13,66.26,14.34,68.05,12.13,68.05z M114.43,55.8c-1.81,0-3.45-1.23-3.89-3.07c-0.43-1.8-0.98-3.59-1.61-5.32
|
||||
c-0.76-2.07,0.3-4.37,2.37-5.14c2.07-0.76,4.37,0.3,5.14,2.37c0.74,2.02,1.38,4.11,1.88,6.22c0.52,2.15-0.81,4.31-2.95,4.82
|
||||
C115.06,55.76,114.74,55.8,114.43,55.8z M15.21,50.31c-0.45,0-0.91-0.08-1.36-0.24c-2.08-0.75-3.15-3.04-2.4-5.12
|
||||
c0.73-2.03,1.6-4.04,2.56-5.97C15,37,17.4,36.2,19.38,37.19c1.98,0.99,2.77,3.39,1.79,5.37c-0.83,1.65-1.57,3.37-2.19,5.11
|
||||
C18.38,49.3,16.85,50.31,15.21,50.31z M107.24,39.3c-1.29,0-2.57-0.63-3.34-1.79c-1.02-1.54-2.15-3.04-3.34-4.45
|
||||
c-1.43-1.69-1.22-4.21,0.47-5.64s4.21-1.22,5.64,0.47c1.39,1.65,2.71,3.39,3.9,5.19c1.22,1.84,0.72,4.32-1.12,5.54
|
||||
C108.77,39.08,108,39.3,107.24,39.3z M24.19,34.7c-0.91,0-1.82-0.31-2.56-0.93c-1.69-1.42-1.92-3.94-0.5-5.63
|
||||
c1.38-1.66,2.88-3.25,4.44-4.73c1.6-1.52,4.13-1.45,5.65,0.15s1.45,4.13-0.15,5.65c-1.34,1.27-2.62,2.64-3.81,4.06
|
||||
C26.47,34.21,25.33,34.7,24.19,34.7z M94.83,26.24c-0.83,0-1.66-0.26-2.38-0.79c-1.49-1.1-3.05-2.13-4.66-3.05
|
||||
c-1.92-1.1-2.58-3.54-1.48-5.46c1.1-1.91,3.54-2.58,5.46-1.48c1.87,1.07,3.7,2.27,5.44,3.56c1.78,1.31,2.15,3.82,0.83,5.6
|
||||
C97.27,25.68,96.06,26.24,94.83,26.24z M37.95,23.09c-1.38,0-2.72-0.71-3.46-1.99c-1.11-1.91-0.46-4.36,1.44-5.47
|
||||
c1.86-1.08,3.81-2.07,5.79-2.93c2.03-0.88,4.38,0.05,5.26,2.07c0.88,2.03-0.05,4.38-2.07,5.26c-1.69,0.74-3.36,1.58-4.96,2.51
|
||||
C39.33,22.92,38.64,23.09,37.95,23.09z M78.72,18.21c-0.38,0-0.76-0.05-1.13-0.17c-1.77-0.52-3.59-0.95-5.42-1.26
|
||||
c-2.18-0.37-3.64-2.44-3.26-4.62s2.45-3.64,4.62-3.26c2.13,0.37,4.26,0.86,6.33,1.47c2.12,0.63,3.33,2.85,2.7,4.97
|
||||
C82.04,17.08,80.45,18.21,78.72,18.21z M54.84,16.89c-1.9,0-3.59-1.36-3.93-3.3c-0.39-2.17,1.06-4.25,3.24-4.64
|
||||
c2.12-0.38,4.29-0.63,6.45-0.76c2.19-0.14,4.1,1.55,4.23,3.75c0.13,2.21-1.55,4.1-3.75,4.23c-1.85,0.11-3.71,0.33-5.52,0.66
|
||||
C55.31,16.87,55.07,16.89,54.84,16.89z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 4.8 KiB |
49
resources/icons/instance_remove.svg
Normal file
@ -0,0 +1,49 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
|
||||
<g id="REMOVE_INSTANCE">
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M88.01,57.95c0-1.1-0.9-2-2-2H41.99c-1.1,0-2,0.9-2,2v12.01c0,1.1,0.9,2,2,2h44.02c1.1,0,2-0.9,2-2V57.95z
|
||||
"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M67.06,119.73c-2.1,0-3.87-1.64-3.99-3.77c-0.13-2.21,1.56-4.1,3.76-4.23c1.85-0.11,3.71-0.32,5.53-0.64
|
||||
c2.17-0.38,4.25,1.07,4.63,3.25s-1.07,4.25-3.25,4.63c-2.12,0.37-4.29,0.63-6.45,0.75C67.22,119.73,67.14,119.73,67.06,119.73z
|
||||
M55.05,119.05c-0.23,0-0.46-0.02-0.69-0.06c-2.13-0.37-4.26-0.87-6.32-1.49c-2.12-0.63-3.32-2.86-2.69-4.98s2.86-3.32,4.98-2.69
|
||||
c1.77,0.53,3.59,0.96,5.41,1.27c2.18,0.38,3.63,2.45,3.25,4.63C58.65,117.68,56.96,119.05,55.05,119.05z M84.58,115.58
|
||||
c-1.55,0-3.02-0.9-3.67-2.41c-0.88-2.03,0.06-4.38,2.08-5.26c1.69-0.73,3.36-1.57,4.96-2.5c1.91-1.11,4.36-0.46,5.47,1.46
|
||||
c1.11,1.91,0.46,4.36-1.46,5.47c-1.87,1.08-3.82,2.07-5.8,2.92C85.65,115.47,85.11,115.58,84.58,115.58z M38.12,112.91
|
||||
c-0.68,0-1.37-0.17-2-0.54c-1.87-1.08-3.69-2.28-5.43-3.57c-1.77-1.32-2.14-3.82-0.82-5.6c1.32-1.77,3.82-2.14,5.6-0.82
|
||||
c1.49,1.11,3.05,2.13,4.65,3.06c1.91,1.1,2.57,3.55,1.47,5.46C40.84,112.2,39.5,112.91,38.12,112.91z M99.61,105.67
|
||||
c-1.06,0-2.12-0.42-2.91-1.25c-1.52-1.61-1.45-4.14,0.16-5.66c1.35-1.27,2.63-2.64,3.82-4.05c1.42-1.69,3.94-1.91,5.64-0.49
|
||||
c1.69,1.42,1.91,3.94,0.49,5.64c-1.39,1.65-2.88,3.24-4.45,4.72C101.58,105.3,100.59,105.67,99.61,105.67z M24.32,101.35
|
||||
c-1.14,0-2.27-0.48-3.06-1.42c-1.39-1.65-2.7-3.4-3.89-5.2c-1.22-1.84-0.71-4.32,1.13-5.54c1.84-1.22,4.32-0.71,5.54,1.13
|
||||
c1.02,1.54,2.14,3.04,3.33,4.46c1.42,1.69,1.21,4.21-0.48,5.64C26.14,101.04,25.23,101.35,24.32,101.35z M110.36,91.23
|
||||
c-0.6,0-1.22-0.14-1.79-0.43c-1.97-0.99-2.77-3.4-1.78-5.37c0.83-1.65,1.57-3.37,2.2-5.11c0.75-2.08,3.05-3.15,5.13-2.39
|
||||
c2.08,0.75,3.15,3.05,2.39,5.13c-0.74,2.03-1.61,4.04-2.58,5.97C113.24,90.42,111.83,91.23,110.36,91.23z M15.28,85.78
|
||||
c-1.63,0-3.16-1-3.76-2.63c-0.74-2.03-1.37-4.12-1.87-6.22c-0.51-2.15,0.82-4.31,2.97-4.82s4.31,0.82,4.82,2.97
|
||||
c0.43,1.8,0.97,3.59,1.6,5.32c0.76,2.08-0.31,4.37-2.38,5.13C16.2,85.7,15.73,85.78,15.28,85.78z M115.53,73.97
|
||||
c-0.15,0-0.31-0.01-0.46-0.03c-2.19-0.25-3.77-2.24-3.52-4.43c0.21-1.83,0.32-3.7,0.32-5.56v-0.21c0-2.21,1.79-4,4-4s4,1.79,4,4
|
||||
v0.15c0,2.22-0.12,4.4-0.37,6.53C119.26,72.47,117.53,73.97,115.53,73.97z M12.13,68.05c-2.21,0-4-1.79-4-4h4l-4-0.05
|
||||
c0-2.18,0.12-4.33,0.36-6.42c0.25-2.19,2.24-3.76,4.43-3.52c2.2,0.25,3.77,2.23,3.52,4.43c-0.21,1.8-0.31,3.64-0.31,5.46v0.1
|
||||
C16.13,66.26,14.34,68.05,12.13,68.05z M114.43,55.8c-1.81,0-3.45-1.23-3.89-3.07c-0.43-1.8-0.98-3.59-1.61-5.32
|
||||
c-0.76-2.07,0.3-4.37,2.37-5.14c2.07-0.76,4.37,0.3,5.14,2.37c0.74,2.02,1.38,4.11,1.88,6.22c0.52,2.15-0.81,4.31-2.95,4.82
|
||||
C115.06,55.76,114.74,55.8,114.43,55.8z M15.21,50.31c-0.45,0-0.91-0.08-1.36-0.24c-2.08-0.75-3.15-3.04-2.4-5.12
|
||||
c0.73-2.03,1.6-4.04,2.56-5.97C15,37,17.4,36.2,19.38,37.19c1.98,0.99,2.77,3.39,1.79,5.37c-0.83,1.65-1.57,3.37-2.19,5.11
|
||||
C18.38,49.3,16.85,50.31,15.21,50.31z M107.24,39.3c-1.29,0-2.57-0.63-3.34-1.79c-1.02-1.54-2.15-3.04-3.34-4.45
|
||||
c-1.43-1.69-1.22-4.21,0.47-5.64s4.21-1.22,5.64,0.47c1.39,1.65,2.71,3.39,3.9,5.19c1.22,1.84,0.72,4.32-1.12,5.54
|
||||
C108.77,39.08,108,39.3,107.24,39.3z M24.19,34.7c-0.91,0-1.82-0.31-2.56-0.93c-1.69-1.42-1.92-3.94-0.5-5.63
|
||||
c1.38-1.66,2.88-3.25,4.44-4.73c1.6-1.52,4.13-1.45,5.65,0.15s1.45,4.13-0.15,5.65c-1.34,1.27-2.62,2.64-3.81,4.06
|
||||
C26.47,34.21,25.33,34.7,24.19,34.7z M94.83,26.24c-0.83,0-1.66-0.26-2.38-0.79c-1.49-1.1-3.05-2.13-4.66-3.05
|
||||
c-1.92-1.1-2.58-3.54-1.48-5.46c1.1-1.91,3.54-2.58,5.46-1.48c1.87,1.07,3.7,2.27,5.44,3.56c1.78,1.31,2.15,3.82,0.83,5.6
|
||||
C97.27,25.68,96.06,26.24,94.83,26.24z M37.95,23.09c-1.38,0-2.72-0.71-3.46-1.99c-1.11-1.91-0.46-4.36,1.44-5.47
|
||||
c1.86-1.08,3.81-2.07,5.79-2.93c2.03-0.88,4.38,0.05,5.26,2.07c0.88,2.03-0.05,4.38-2.07,5.26c-1.69,0.74-3.36,1.58-4.96,2.51
|
||||
C39.33,22.92,38.64,23.09,37.95,23.09z M78.72,18.21c-0.38,0-0.76-0.05-1.13-0.17c-1.77-0.52-3.59-0.95-5.42-1.26
|
||||
c-2.18-0.37-3.64-2.44-3.26-4.62s2.45-3.64,4.62-3.26c2.13,0.37,4.26,0.86,6.33,1.47c2.12,0.63,3.33,2.85,2.7,4.97
|
||||
C82.04,17.08,80.45,18.21,78.72,18.21z M54.84,16.89c-1.9,0-3.59-1.36-3.93-3.3c-0.39-2.17,1.06-4.25,3.24-4.64
|
||||
c2.12-0.38,4.29-0.63,6.45-0.76c2.19-0.14,4.1,1.55,4.23,3.75c0.13,2.21-1.55,4.1-3.75,4.23c-1.85,0.11-3.71,0.33-5.52,0.66
|
||||
C55.31,16.87,55.07,16.89,54.84,16.89z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 4.6 KiB |
25
resources/icons/layers.svg
Normal file
@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
|
||||
<g>
|
||||
<g>
|
||||
<rect x="7.98" y="105" fill="#FFFFFF" width="112.04" height="15"/>
|
||||
</g>
|
||||
<g>
|
||||
<rect x="7.98" y="85.67" fill="#FFFFFF" width="112.04" height="13"/>
|
||||
</g>
|
||||
<g>
|
||||
<rect x="7.98" y="66.33" fill="#FFFFFF" width="112.04" height="11"/>
|
||||
</g>
|
||||
<g>
|
||||
<rect x="7.98" y="47" fill="#ED6B21" width="112.04" height="9"/>
|
||||
</g>
|
||||
<g>
|
||||
<rect x="7.98" y="27.67" fill="#ED6B21" width="112.04" height="7"/>
|
||||
</g>
|
||||
<g>
|
||||
<rect x="7.98" y="8.33" fill="#ED6B21" width="112.04" height="5"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 841 B |
42
resources/icons/move.svg
Normal file
@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
|
||||
<g id="move">
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M83.47,86.79H44.53c-1.83,0-3.32-1.49-3.32-3.32V44.53c0-1.83,1.49-3.32,3.32-3.32h38.94
|
||||
c1.83,0,3.32,1.49,3.32,3.32v38.94C86.79,85.3,85.3,86.79,83.47,86.79z M44.53,44.21c-0.17,0-0.32,0.15-0.32,0.32v38.94
|
||||
c0,0.17,0.15,0.32,0.32,0.32h38.94c0.17,0,0.32-0.15,0.32-0.32V44.53c0-0.17-0.15-0.32-0.32-0.32H44.53z"/>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M76.81,28.66H51.19c-1.06,0-1.9-0.46-2.31-1.25c-0.4-0.8-0.28-1.74,0.35-2.6L61.72,7.7
|
||||
c0.57-0.78,1.4-1.22,2.28-1.22c0,0,0,0,0,0c0.89,0,1.72,0.45,2.28,1.22l12.48,17.1c0.63,0.86,0.75,1.81,0.35,2.6
|
||||
C78.71,28.2,77.87,28.66,76.81,28.66z M52.33,25.66l23.34,0L64,9.67L52.33,25.66z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M26.44,79.35c-0.54,0-1.1-0.2-1.63-0.58L7.7,66.28c-0.78-0.57-1.22-1.4-1.22-2.28s0.45-1.72,1.22-2.29
|
||||
l17.1-12.48c0.86-0.62,1.81-0.75,2.6-0.35s1.25,1.25,1.25,2.31v25.61c0,1.06-0.46,1.9-1.25,2.31
|
||||
C27.1,79.27,26.77,79.35,26.44,79.35z M9.67,64l15.99,11.67l0-23.34L9.67,64z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M64,121.52c-0.89,0-1.72-0.45-2.28-1.22l-12.48-17.1c-0.63-0.86-0.75-1.81-0.35-2.6s1.25-1.25,2.31-1.25
|
||||
h25.61c1.06,0,1.9,0.46,2.31,1.25c0.4,0.8,0.28,1.74-0.35,2.6l-12.48,17.1C65.72,121.07,64.89,121.52,64,121.52L64,121.52z
|
||||
M52.33,102.34L64,118.33l11.67-15.99L52.33,102.34z M76.87,102.34L76.87,102.34L76.87,102.34z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M101.56,79.35c-0.34,0-0.67-0.08-0.97-0.23c-0.8-0.41-1.25-1.25-1.25-2.31V51.19
|
||||
c0-1.06,0.46-1.9,1.25-2.31c0.8-0.41,1.75-0.28,2.6,0.35l17.1,12.48c0.78,0.57,1.22,1.4,1.22,2.29s-0.45,1.72-1.22,2.28
|
||||
l-17.1,12.48C102.67,79.15,102.1,79.35,101.56,79.35z M102.34,52.33l0,23.34L118.33,64L102.34,52.33z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.1 KiB |
32
resources/icons/place.svg
Normal file
@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
|
||||
<g id="place">
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M101.56,93.65c-0.28,0-0.57-0.04-0.85-0.1L37.65,77.82c-0.9-0.22-1.67-0.79-2.15-1.59s-0.62-1.74-0.4-2.65
|
||||
l15.72-63.06c0.47-1.87,2.37-3.02,4.24-2.55l63.06,15.72c1.87,0.47,3.02,2.37,2.55,4.24l-15.72,63.06h0
|
||||
c-0.23,0.91-0.79,1.67-1.59,2.15C102.8,93.47,102.18,93.65,101.56,93.65z M54.21,10.87c-0.22,0-0.43,0.15-0.49,0.38L38.01,74.31
|
||||
c-0.04,0.17,0.02,0.31,0.06,0.38c0.04,0.07,0.13,0.19,0.31,0.23l63.06,15.72c0.17,0.04,0.31-0.02,0.38-0.06
|
||||
c0.07-0.04,0.19-0.13,0.23-0.3c0,0,0,0,0,0l15.72-63.06c0.07-0.26-0.1-0.54-0.37-0.61L54.33,10.88
|
||||
C54.29,10.87,54.25,10.87,54.21,10.87z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M118.02,120.54H9.98c-1.93,0-3.5-1.57-3.5-3.5v-4c0-1.93,1.57-3.5,3.5-3.5h108.04c1.93,0,3.5,1.57,3.5,3.5
|
||||
v4C121.52,118.97,119.95,120.54,118.02,120.54z M9.98,112.54c-0.27,0-0.5,0.23-0.5,0.5v4c0,0.27,0.23,0.5,0.5,0.5h108.04
|
||||
c0.27,0,0.5-0.23,0.5-0.5v-4c0-0.27-0.23-0.5-0.5-0.5H9.98z"/>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M15.99,103.92c-0.08,0-0.15,0-0.23-0.01c-0.92-0.09-1.69-0.72-2.11-1.73L7.42,87.2
|
||||
c-0.41-0.98-0.33-1.97,0.22-2.71c0.55-0.74,1.48-1.11,2.53-1L25.29,85c1.06,0.11,1.89,0.65,2.28,1.48
|
||||
c0.39,0.84,0.27,1.82-0.32,2.71l-9.08,13.43C17.61,103.46,16.82,103.92,15.99,103.92z M10.4,86.52l5.72,13.77l8.36-12.35
|
||||
L10.4,86.52z M24.81,87.43L24.81,87.43z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M17.54,85.9c-0.83,0-1.5-0.67-1.5-1.5c0-8.88,8.1-24.47,17.34-25.5c0.82-0.09,1.56,0.5,1.66,1.33
|
||||
c0.09,0.82-0.5,1.56-1.33,1.66c-6.94,0.77-14.67,14.08-14.67,22.52C19.04,85.22,18.37,85.9,17.54,85.9z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.9 KiB |
48
resources/icons/preview.svg
Normal file
@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
|
||||
<g id="preview">
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M90.72,121.38H8.12c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h81.99l28.72-28.15
|
||||
c0.59-0.58,1.54-0.57,2.12,0.02c0.58,0.59,0.57,1.54-0.02,2.12l-29.16,28.57C91.49,121.23,91.11,121.38,90.72,121.38z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M90.72,111.38H8.12c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h81.99l28.72-28.14
|
||||
c0.59-0.58,1.54-0.57,2.12,0.02c0.58,0.59,0.57,1.54-0.02,2.12l-29.16,28.57C91.49,111.23,91.11,111.38,90.72,111.38z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M90.72,101.38H8.12c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h81.99l28.72-28.14
|
||||
c0.59-0.58,1.54-0.57,2.12,0.02s0.57,1.54-0.02,2.12l-29.16,28.57C91.49,101.23,91.11,101.38,90.72,101.38z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M90.72,91.38H8.12c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h81.99l28.72-28.15
|
||||
c0.59-0.58,1.54-0.57,2.12,0.02s0.57,1.54-0.02,2.12L91.77,90.95C91.49,91.23,91.11,91.38,90.72,91.38z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M90.72,81.38H8.12c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h81.99l28.72-28.15
|
||||
c0.59-0.58,1.54-0.57,2.12,0.02c0.58,0.59,0.57,1.54-0.02,2.12L91.77,80.95C91.49,81.23,91.11,81.38,90.72,81.38z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M90.72,71.38H8.12c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h81.99l28.72-28.15
|
||||
c0.59-0.58,1.54-0.57,2.12,0.02c0.58,0.59,0.57,1.54-0.02,2.12L91.77,70.95C91.49,71.23,91.11,71.38,90.72,71.38z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M90.72,61.38H8.12c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h81.99l28.72-28.15
|
||||
c0.59-0.58,1.54-0.57,2.12,0.02c0.58,0.59,0.57,1.54-0.02,2.12L91.77,60.95C91.49,61.23,91.11,61.38,90.72,61.38z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M90.72,51.38H8.12c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h81.99l28.72-28.15
|
||||
c0.59-0.58,1.54-0.57,2.12,0.02s0.57,1.54-0.02,2.12L91.77,50.95C91.49,51.23,91.11,51.38,90.72,51.38z"/>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M88.72,41.38H9.18c-1.68,0-2.22-0.95-2.37-1.36s-0.37-1.48,0.89-2.59L38.43,10.5
|
||||
c1.1-0.96,3.03-1.69,4.49-1.69h75.85c1.65,0,2.22,0.94,2.38,1.34s0.42,1.47-0.75,2.63c0,0,0,0,0,0L93.2,39.55
|
||||
C92.14,40.59,90.21,41.38,88.72,41.38z M11.17,38.38h77.55c0.71,0,1.87-0.47,2.37-0.97l26.01-25.6H42.92
|
||||
c-0.74,0-1.96,0.46-2.51,0.95L11.17,38.38z M118.89,11.82C118.89,11.82,118.89,11.82,118.89,11.82
|
||||
C118.89,11.82,118.89,11.82,118.89,11.82z M119.34,11.71L119.34,11.71L119.34,11.71z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.7 KiB |
44
resources/icons/remove.svg
Normal file
@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
|
||||
<path fill="#FFFFFF" d="M38.11,44.25H25.75c-0.95,0-1.72,0.77-1.72,1.72s0.77,1.72,1.72,1.72H38.1c0.95,0,1.72-0.77,1.72-1.72
|
||||
C39.83,45.02,39.06,44.25,38.11,44.25z M45.89,45.97c0,0.95,0.77,1.72,1.72,1.72h12.35c0.95,0,1.72-0.77,1.72-1.72
|
||||
s-0.77-1.72-1.72-1.72H47.61C46.66,44.25,45.89,45.02,45.89,45.97z M68.11,43.6c-0.33,0.28-0.52,0.65-0.59,1.04
|
||||
c-0.59,0.27-1,0.87-1,1.56v5.6c0,0.95,0.77,1.72,1.72,1.72c0.95,0,1.72-0.77,1.72-1.72v-5.34c0.12-0.06,0.24-0.13,0.35-0.22
|
||||
c0.13-0.11,0.25-0.23,0.36-0.34l8.27-8.77c0.65-0.69,0.62-1.78-0.07-2.43s-1.78-0.62-2.43,0.07l-8.27,8.78
|
||||
C68.16,43.56,68.14,43.58,68.11,43.6z M68.25,76.84c-0.95,0-1.72,0.77-1.72,1.72V89.1c0,0.95,0.77,1.72,1.72,1.72
|
||||
c0.95,0,1.72-0.77,1.72-1.72V78.56C69.97,77.61,69.2,76.84,68.25,76.84z M69.97,59.91c0-0.95-0.77-1.72-1.72-1.72
|
||||
c-0.95,0-1.72,0.77-1.72,1.72v10.54c0,0.95,0.77,1.72,1.72,1.72c0.95,0,1.72-0.77,1.72-1.72V59.91z M88.92,56.35
|
||||
c-0.95,0-1.72,0.77-1.72,1.72v3.4c0,0.34-0.02,0.63-0.04,0.85c-0.51,0.55-0.62,1.38-0.22,2.06c0.32,0.54,0.89,0.84,1.48,0.84
|
||||
c0.3,0,0.6-0.08,0.88-0.24l0.25-0.15c0.67-0.4,1.09-1.1,1.09-3.35v-3.4C90.64,57.12,89.87,56.35,88.92,56.35z M41.81,26.17h11.3
|
||||
c0.95,0,1.72-0.77,1.72-1.72s-0.77-1.72-1.72-1.72h-11.3c-0.95,0-1.72,0.77-1.72,1.72S40.86,26.17,41.81,26.17z M87.2,22.73h-5.39
|
||||
c-0.95,0-1.72,0.77-1.72,1.72s0.77,1.72,1.72,1.72h2.75l-1.58,1.68c-0.65,0.69-0.62,1.78,0.07,2.43c0.33,0.31,0.76,0.47,1.18,0.47
|
||||
c0.46,0,0.91-0.18,1.25-0.54l1.72-1.82v0.99c0,0.95,0.77,1.72,1.72,1.72c0.95,0,1.72-0.77,1.72-1.72v-3.21
|
||||
C90.64,24.27,89.09,22.73,87.2,22.73z M61.81,26.17h11.3c0.95,0,1.72-0.77,1.72-1.72s-0.77-1.72-1.72-1.72h-11.3
|
||||
c-0.95,0-1.72,0.77-1.72,1.72S60.86,26.17,61.81,26.17z M9.71,67.54c0.95,0,1.72-0.77,1.72-1.72v-11.3c0-0.95-0.77-1.72-1.72-1.72
|
||||
s-1.72,0.77-1.72,1.72v11.3C7.99,66.77,8.76,67.54,9.71,67.54z M24.65,33.86c0.42,0,0.84-0.15,1.17-0.46l7.04-6.52
|
||||
c0.14-0.13,0.46-0.34,0.9-0.51c0.89-0.34,1.34-1.33,1-2.22s-1.33-1.34-2.22-1c-0.8,0.3-1.52,0.73-2.03,1.2l-7.04,6.52
|
||||
c-0.7,0.65-0.74,1.74-0.09,2.43C23.73,33.68,24.19,33.86,24.65,33.86z M70.35,99.28l-0.37,0.36v-2.43c0-0.95-0.77-1.72-1.72-1.72
|
||||
c-0.95,0-1.72,0.77-1.72,1.72v4.72H61.3c-0.95,0-1.72,0.77-1.72,1.72s0.77,1.72,1.72,1.72h5.23c1.4,0,3.15-0.7,4.16-1.66l2.03-1.94
|
||||
c0.69-0.66,0.71-1.75,0.06-2.43C72.13,98.65,71.03,98.63,70.35,99.28z M52.6,101.93H41.3c-0.95,0-1.72,0.77-1.72,1.72
|
||||
s0.77,1.72,1.72,1.72h11.3c0.95,0,1.72-0.77,1.72-1.72S53.55,101.93,52.6,101.93z M88.92,36.35c-0.95,0-1.72,0.77-1.72,1.72v11.3
|
||||
c0,0.95,0.77,1.72,1.72,1.72c0.95,0,1.72-0.77,1.72-1.72v-11.3C90.64,37.12,89.87,36.35,88.92,36.35z M32.61,101.93H21.3
|
||||
c-0.95,0-1.72,0.77-1.72,1.72s0.77,1.72,1.72,1.72h11.3c0.95,0,1.72-0.77,1.72-1.72S33.56,101.93,32.61,101.93z M9.71,87.54
|
||||
c0.95,0,1.72-0.77,1.72-1.72v-11.3c0-0.95-0.77-1.72-1.72-1.72s-1.72,0.77-1.72,1.72v11.3C7.99,86.77,8.76,87.54,9.71,87.54z
|
||||
M12.61,101.93h-1.18v-7.42c0-0.95-0.77-1.72-1.72-1.72s-1.72,0.77-1.72,1.72v7.42c0,1.9,1.54,3.44,3.44,3.44h1.18
|
||||
c0.95,0,1.72-0.77,1.72-1.72S13.56,101.93,12.61,101.93z M19.53,36.88c-0.65-0.7-1.74-0.74-2.43-0.09l-7.3,6.76
|
||||
c-0.55,0.51-0.93,1.15-1.16,1.6C8.22,46,8.56,47.03,9.41,47.46c0.25,0.12,0.51,0.18,0.77,0.18h0.01c0.14,0.04,0.29,0.07,0.45,0.07
|
||||
h5.6c0.95,0,1.72-0.77,1.72-1.72s-0.77-1.72-1.72-1.72h-2.13l5.33-4.94C20.14,38.66,20.18,37.57,19.53,36.88z M80.7,89.4l-4.05,3.86
|
||||
c-0.69,0.66-0.71,1.75-0.06,2.43c0.34,0.35,0.79,0.53,1.25,0.53c0.43,0,0.86-0.16,1.19-0.48l4.05-3.86
|
||||
c0.69-0.66,0.71-1.75,0.06-2.43C82.48,88.77,81.39,88.75,80.7,89.4z"/>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M98.82,101.06c-11.63,0-21.09-9.46-21.09-21.09s9.46-21.09,21.09-21.09s21.09,9.46,21.09,21.09
|
||||
S110.45,101.06,98.82,101.06z M98.82,62.32c-9.73,0-17.65,7.92-17.65,17.65s7.92,17.65,17.65,17.65s17.65-7.92,17.65-17.65
|
||||
S108.55,62.32,98.82,62.32z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M110.44,81.84c0,1.1-0.9,2-2,2H89.2c-1.1,0-2-0.9-2-2v-3.75c0-1.1,0.9-2,2-2h19.25c1.1,0,2,0.9,2,2
|
||||
L110.44,81.84L110.44,81.84z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 4.2 KiB |
25
resources/icons/rotate.svg
Normal file
@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
|
||||
<g id="rotate">
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M66.98,120.65c-0.9,0-1.79-0.34-2.47-1.02L25.27,80.4c-0.66-0.66-1.02-1.54-1.02-2.47s0.36-1.82,1.02-2.47
|
||||
L64.5,36.22c1.37-1.36,3.58-1.36,4.95,0l39.23,39.23c1.36,1.36,1.36,3.58,0,4.95l-39.23,39.23
|
||||
C68.77,120.31,67.88,120.65,66.98,120.65z M66.98,38.19c-0.13,0-0.26,0.05-0.35,0.14L27.39,77.57c-0.13,0.12-0.14,0.28-0.14,0.35
|
||||
s0.02,0.23,0.14,0.35l39.23,39.23c0.19,0.19,0.52,0.19,0.71,0l39.23-39.23c0.19-0.19,0.19-0.52,0-0.71L67.33,38.34
|
||||
C67.24,38.24,67.11,38.19,66.98,38.19z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M11.27,78.49c-0.65,0-1.25-0.43-1.44-1.08c-1.45-5.02-2.19-10.21-2.19-15.41
|
||||
c0-30.59,24.89-55.48,55.48-55.48c15.38,0,29.68,6.15,40.27,17.33c0.57,0.6,0.54,1.55-0.06,2.12c-0.6,0.57-1.55,0.54-2.12-0.06
|
||||
C91.2,15.34,77.67,9.52,63.12,9.52c-28.94,0-52.48,23.54-52.48,52.48c0,4.92,0.7,9.82,2.07,14.58c0.23,0.8-0.23,1.63-1.03,1.86
|
||||
C11.55,78.47,11.41,78.49,11.27,78.49z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M117.27,42.19c-0.22,0-0.44-0.02-0.67-0.07l-23.34-4.67c-1.07-0.21-1.84-0.84-2.11-1.73
|
||||
c-0.27-0.88,0.02-1.83,0.8-2.61l18.98-18.98c0.77-0.77,1.73-1.07,2.61-0.8c0.88,0.27,1.51,1.04,1.73,2.11v0l4.67,23.34
|
||||
c0.2,1.01-0.06,1.97-0.71,2.62C118.72,41.92,118.03,42.19,117.27,42.19z M94.64,34.66l22.29,4.47l-4.45-22.3L94.64,34.66z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.6 KiB |
38
resources/icons/scale.svg
Normal file
@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
|
||||
<g id="scale">
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M118.05,121.55H57.99c-1.93,0-3.5-1.57-3.5-3.5V57.99c0-1.93,1.57-3.5,3.5-3.5h60.06
|
||||
c1.93,0,3.5,1.57,3.5,3.5v60.06C121.55,119.98,119.98,121.55,118.05,121.55z M57.99,57.49c-0.27,0-0.5,0.23-0.5,0.5v60.06
|
||||
c0,0.27,0.23,0.5,0.5,0.5h60.06c0.27,0,0.5-0.23,0.5-0.5V57.99c0-0.27-0.23-0.5-0.5-0.5H57.99z"/>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M43.54,121.55h-10.5c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h10.5c0.83,0,1.5,0.67,1.5,1.5
|
||||
S44.37,121.55,43.54,121.55z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M18.35,121.55h-8.4c-1.93,0-3.5-1.57-3.5-3.5v-10.5c0-0.83,0.67-1.5,1.5-1.5s1.5,0.67,1.5,1.5v10.5
|
||||
c0,0.27,0.23,0.5,0.5,0.5h8.4c0.83,0,1.5,0.67,1.5,1.5S19.18,121.55,18.35,121.55z M7.95,94.36c-0.83,0-1.5-0.67-1.5-1.5V70.82
|
||||
c0-0.83,0.67-1.5,1.5-1.5s1.5,0.67,1.5,1.5v22.04C9.45,93.69,8.78,94.36,7.95,94.36z M7.95,57.63c-0.83,0-1.5-0.67-1.5-1.5V34.1
|
||||
c0-0.83,0.67-1.5,1.5-1.5s1.5,0.67,1.5,1.5v22.04C9.45,56.96,8.78,57.63,7.95,57.63z M7.95,20.91c-0.83,0-1.5-0.67-1.5-1.5V9.95
|
||||
c0-1.93,1.57-3.5,3.5-3.5h9.44c0.83,0,1.5,0.67,1.5,1.5s-0.67,1.5-1.5,1.5H9.95c-0.27,0-0.5,0.23-0.5,0.5v9.46
|
||||
C9.45,20.24,8.78,20.91,7.95,20.91z M120.05,19.83c-0.83,0-1.5-0.67-1.5-1.5V9.95c0-0.27-0.23-0.5-0.5-0.5h-10.52
|
||||
c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h10.52c1.93,0,3.5,1.57,3.5,3.5v8.38C121.55,19.16,120.88,19.83,120.05,19.83z
|
||||
M92.84,9.45H70.81c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h22.04c0.83,0,1.5,0.67,1.5,1.5S93.67,9.45,92.84,9.45z
|
||||
M56.12,9.45H34.08c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5h22.04c0.83,0,1.5,0.67,1.5,1.5S56.94,9.45,56.12,9.45z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M120.05,45.04c-0.83,0-1.5-0.67-1.5-1.5v-10.5c0-0.83,0.67-1.5,1.5-1.5s1.5,0.67,1.5,1.5v10.5
|
||||
C121.55,44.37,120.88,45.04,120.05,45.04z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M49.38,44.41c0.78-0.78,0.78-2.05,0-2.83l-9.27-9.27c-0.78-0.78-0.78-2.05,0-2.83l4.95-4.95
|
||||
c0.78-0.78,0.51-1.41-0.59-1.41H25.13c-1.1,0-2,0.9-2,2v19.34c0,1.1,0.64,1.36,1.41,0.59l4.95-4.95c0.78-0.78,2.05-0.78,2.83,0
|
||||
l9.27,9.27c0.78,0.78,2.05,0.78,2.83,0L49.38,44.41z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.4 KiB |
42
resources/icons/sla_supports.svg
Normal file
@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
|
||||
<g id="SLA_supports">
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M117.02,121.54H11.12c-1.93,0-3.5-1.57-3.5-3.5v-3.99c0-1.93,1.57-3.5,3.5-3.5h105.9
|
||||
c1.93,0,3.5,1.57,3.5,3.5v3.99C120.52,119.97,118.95,121.54,117.02,121.54z M11.12,113.55c-0.27,0-0.5,0.23-0.5,0.5v3.99
|
||||
c0,0.27,0.23,0.5,0.5,0.5h105.9c0.27,0,0.5-0.23,0.5-0.5v-3.99c0-0.27-0.23-0.5-0.5-0.5H11.12z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M32.08,108.06c-0.83,0-1.5-0.67-1.5-1.5v-18.8c0-0.83,0.67-1.5,1.5-1.5s1.5,0.67,1.5,1.5v18.8
|
||||
C33.58,107.39,32.9,108.06,32.08,108.06z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M48.02,108.06c-0.83,0-1.5-0.67-1.5-1.5v-8.14c0-0.83,0.67-1.5,1.5-1.5s1.5,0.67,1.5,1.5v8.14
|
||||
C49.52,107.39,48.85,108.06,48.02,108.06z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M88.04,108.06c-0.83,0-1.5-0.67-1.5-1.5V93.09c0-0.83,0.67-1.5,1.5-1.5s1.5,0.67,1.5,1.5v13.47
|
||||
C89.54,107.39,88.87,108.06,88.04,108.06z"/>
|
||||
</g>
|
||||
<path fill="#FFFFFF" d="M70.36,95.12l-6.29,4.2l-14.45-9.63l-2.5,2.6l15.96,10.64c0.3,0.2,0.64,0.3,0.99,0.3s0.69-0.1,0.99-0.3
|
||||
l7.9-5.27L70.36,95.12z"/>
|
||||
<polygon fill="#FFFFFF" points="88.97,86.99 86.35,84.46 77.91,90.09 80.5,92.63 "/>
|
||||
<path fill="#FFFFFF" d="M103.99,35.1L65.05,9.14c-0.6-0.4-1.37-0.4-1.97,0L24.14,35.1c-0.49,0.33-0.79,0.88-0.79,1.48v38.91
|
||||
c0,0.59,0.3,1.15,0.79,1.48l15.47,10.32l2.5-2.6L26.9,74.54V37.53l37.16-24.78l37.16,24.78v37.01l-7.32,4.88l2.61,2.53l7.46-4.98
|
||||
c0.49-0.33,0.79-0.88,0.79-1.48V36.58C104.78,35.99,104.49,35.43,103.99,35.1z"/>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M96.16,108.06c-0.83,0-1.5-0.67-1.5-1.5V87.93L79,73.22c-0.6-0.57-0.63-1.52-0.07-2.12
|
||||
c0.57-0.6,1.52-0.63,2.12-0.07l16.13,15.15c0.3,0.28,0.47,0.68,0.47,1.09v19.27C97.66,107.39,96.99,108.06,96.16,108.06z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M40.08,108.06c-0.83,0-1.5-0.67-1.5-1.5V93.29c0-0.39,0.15-0.76,0.41-1.04l16.13-16.91
|
||||
c0.57-0.6,1.52-0.62,2.12-0.05c0.6,0.57,0.62,1.52,0.05,2.12L41.58,93.89v12.67C41.58,107.39,40.91,108.06,40.08,108.06z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M80.13,108.06c-0.83,0-1.5-0.67-1.5-1.5v-7.65L62.94,83.19c-0.59-0.59-0.58-1.54,0-2.12
|
||||
c0.59-0.58,1.54-0.59,2.12,0l16.13,16.15c0.28,0.28,0.44,0.66,0.44,1.06v8.27C81.63,107.39,80.96,108.06,80.13,108.06z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.5 KiB |
19
resources/icons/split_objects.svg
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
|
||||
<g id="OBJECTS">
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M34.63,91.95h-17.3c-4.96,0-9-4.04-9-9V17.28c0-4.96,4.04-9,9-9H83c4.96,0,9,4.04,9,9v17.3
|
||||
c0,1.66-1.34,3-3,3s-3-1.34-3-3v-17.3c0-1.65-1.35-3-3-3H17.32c-1.65,0-3,1.35-3,3v65.67c0,1.65,1.35,3,3,3h17.3
|
||||
c1.66,0,3,1.34,3,3S36.28,91.95,34.63,91.95z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M114.89,42.35H47.57c-2.85,0-5.18,2.33-5.18,5.18v67.32c0,2.85,2.33,5.18,5.18,5.18h67.32
|
||||
c2.85,0,5.18-2.33,5.18-5.18V47.52C120.07,44.68,117.74,42.35,114.89,42.35z M101.82,94.28c0,12.63-6.35,18.27-20.89,18.27
|
||||
s-20.42-5.64-20.42-18.27v-25.9c0-12.95,5.64-18.27,20.42-18.27c14.77,0,20.89,5.32,20.89,18.27V94.28z"/>
|
||||
<path fill="#ED6B21" d="M80.93,59.8c-7.94,0-9.45,3.58-9.45,9.14v24.78c0,5.8,1.51,9.13,9.45,9.13s9.93-3.33,9.93-9.13V68.94
|
||||
C90.86,63.38,89.43,59.8,80.93,59.8z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
18
resources/icons/split_parts.svg
Normal file
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
|
||||
<g id="PARTS">
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M34.63,91.95h-17.3c-4.96,0-9-4.04-9-9V17.28c0-4.96,4.04-9,9-9H83c4.96,0,9,4.04,9,9v17.3
|
||||
c0,1.66-1.34,3-3,3s-3-1.34-3-3v-17.3c0-1.65-1.35-3-3-3H17.32c-1.65,0-3,1.35-3,3v65.67c0,1.65,1.35,3,3,3h17.3
|
||||
c1.66,0,3,1.34,3,3S36.28,91.95,34.63,91.95z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M114.91,42.32H47.57c-2.85,0-5.18,2.33-5.18,5.18v67.34c0,2.85,2.33,5.18,5.18,5.18h67.34
|
||||
c2.85,0,5.18-2.33,5.18-5.18V47.5C120.09,44.65,117.76,42.32,114.91,42.32z M99.95,74.39c0,12.84-7.27,18.81-22.04,18.81h-4.28
|
||||
v19.05H62.25V50.09h15.66c15.02,0,22.04,5.41,22.04,18.57C99.95,68.66,99.95,74.39,99.95,74.39z"/>
|
||||
<path fill="#ED6B21" d="M78.07,60.26h-4.52v22.2h4.36c8.08,0,10.74-2.74,10.74-8.64v-4.6C88.65,63.33,86.71,60.26,78.07,60.26z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
@ -1,14 +1,22 @@
|
||||
min_slic3r_version = 1.42.0-alpha6
|
||||
0.8.0-alpha7
|
||||
0.8.0-alpha6
|
||||
0.8.0-beta Updated SLA profiles
|
||||
0.8.0-alpha9 Updated SLA and FFF profiles
|
||||
0.8.0-alpha8 Updated SLA profiles
|
||||
0.8.0-alpha7 Updated SLA profiles
|
||||
0.8.0-alpha6 Updated SLA profiles
|
||||
min_slic3r_version = 1.42.0-alpha
|
||||
0.8.0-alpha
|
||||
0.8.0-alpha Updated SLA profiles
|
||||
0.4.0-alpha4 Updated SLA profiles
|
||||
0.4.0-alpha3 Update of SLA profiles
|
||||
0.4.0-alpha2 First SLA profiles
|
||||
min_slic3r_version = 1.41.3-alpha
|
||||
0.4.4 Changelog: https://github.com/prusa3d/Slic3r-settings/blob/master/live/PrusaResearch/changelog.txt
|
||||
0.4.3 Changelog: https://github.com/prusa3d/Slic3r-settings/blob/master/live/PrusaResearch/changelog.txt
|
||||
0.4.2 Changelog: https://github.com/prusa3d/Slic3r-settings/blob/master/live/PrusaResearch/changelog.txt
|
||||
0.4.1 New MK2.5S and MK3S FW versions
|
||||
0.4.0 Changelog: https://github.com/prusa3d/Slic3r-settings/blob/master/live/PrusaResearch/changelog.txt
|
||||
min_slic3r_version = 1.41.1
|
||||
0.3.5 New MK2.5 and MK3 FW versions
|
||||
0.3.4 Changelog: https://github.com/prusa3d/Slic3r-settings/blob/master/live/PrusaResearch/changelog.txt
|
||||
0.3.3 Prusament PETG released
|
||||
0.3.2 New MK2.5 and MK3 FW versions
|
||||
@ -41,6 +49,7 @@ min_slic3r_version = 1.41.0-alpha
|
||||
0.2.0-alpha1 added initial profiles for the i3 MK3 Multi Material Upgrade 2.0
|
||||
0.2.0-alpha moved machine limits from the start G-code to the new print profile parameters
|
||||
min_slic3r_version = 1.40.0
|
||||
0.1.13 New MK2.5 and MK3 FW versions
|
||||
0.1.12 New MK2.5 and MK3 FW versions
|
||||
0.1.11 fw version changed to 3.3.1
|
||||
0.1.10 MK3 jerk and acceleration update
|
||||
|
@ -8,7 +8,7 @@ full_name = Prusa {technology} Technology Printers
|
||||
|
||||
# Configuration version of this file. Config file will only be installed, if the config_version differs.
|
||||
# This means, the server may force the Slic3r configuration to be downgraded.
|
||||
config_version = 0.8.0-alpha7
|
||||
config_version = 0.8.0-beta
|
||||
# Where to get the updates from?
|
||||
config_update_url = https://raw.githubusercontent.com/prusa3d/Slic3r-settings/master/live/PrusaResearch/
|
||||
|
||||
@ -198,6 +198,14 @@ travel_speed = 180
|
||||
wipe_tower_x = 170
|
||||
wipe_tower_y = 125
|
||||
|
||||
[print:*MK306*]
|
||||
fill_pattern = gyroid
|
||||
fill_density = 15%
|
||||
single_extruder_multi_material_priming = 0
|
||||
travel_speed = 180
|
||||
wipe_tower_x = 170
|
||||
wipe_tower_y = 125
|
||||
|
||||
# Print parameters common to a 0.25mm diameter nozzle.
|
||||
[print:*0.25nozzle*]
|
||||
external_perimeter_extrusion_width = 0.25
|
||||
@ -213,6 +221,38 @@ support_material_interface_spacing = 0.15
|
||||
support_material_spacing = 1
|
||||
support_material_xy_spacing = 150%
|
||||
|
||||
[print:*0.25nozzleMK3*]
|
||||
external_perimeter_extrusion_width = 0.25
|
||||
extrusion_width = 0.25
|
||||
first_layer_extrusion_width = 0.35
|
||||
infill_extrusion_width = 0.25
|
||||
perimeter_extrusion_width = 0.25
|
||||
solid_infill_extrusion_width = 0.25
|
||||
top_infill_extrusion_width = 0.25
|
||||
support_material_extrusion_width = 0.2
|
||||
support_material_interface_layers = 0
|
||||
support_material_interface_spacing = 0.15
|
||||
support_material_spacing = 1
|
||||
support_material_xy_spacing = 150%
|
||||
perimeter_speed = 30
|
||||
external_perimeter_speed = 20
|
||||
small_perimeter_speed = 20
|
||||
infill_speed = 45
|
||||
solid_infill_speed = 45
|
||||
top_solid_infill_speed = 30
|
||||
support_material_speed = 40
|
||||
bridge_speed = 20
|
||||
gap_fill_speed = 30
|
||||
perimeter_acceleration = 500
|
||||
infill_acceleration = 1000
|
||||
bridge_acceleration = 500
|
||||
first_layer_acceleration = 500
|
||||
default_acceleration = 1000
|
||||
max_print_speed = 80
|
||||
perimeters = 3
|
||||
fill_pattern = grid
|
||||
fill_density = 20%
|
||||
|
||||
# Print parameters common to a 0.6mm diameter nozzle.
|
||||
[print:*0.6nozzle*]
|
||||
external_perimeter_extrusion_width = 0.61
|
||||
@ -224,6 +264,18 @@ solid_infill_extrusion_width = 0.65
|
||||
top_infill_extrusion_width = 0.6
|
||||
support_material_extrusion_width = 0.55
|
||||
|
||||
[print:*0.6nozzleMK3*]
|
||||
external_perimeter_extrusion_width = 0.65
|
||||
extrusion_width = 0.65
|
||||
first_layer_extrusion_width = 0.65
|
||||
infill_extrusion_width = 0.7
|
||||
perimeter_extrusion_width = 0.65
|
||||
solid_infill_extrusion_width = 0.7
|
||||
top_infill_extrusion_width = 0.6
|
||||
support_material_extrusion_width = 0.55
|
||||
bridge_flow_ratio = 0.95
|
||||
bridge_speed = 25
|
||||
|
||||
[print:*soluble_support*]
|
||||
overhangs = 1
|
||||
skirts = 0
|
||||
@ -298,6 +350,9 @@ support_material_speed = 20
|
||||
[print:0.05mm ULTRADETAIL 0.25 nozzle MK3]
|
||||
inherits = *0.05mm*; *0.25nozzle*; *MK3*
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.25 and num_extruders==1
|
||||
fill_pattern = grid
|
||||
fill_density = 20%
|
||||
first_layer_extrusion_width = 0.35
|
||||
|
||||
# XXXXXXXXXXXXXXXXXXXX
|
||||
# XXX--- 0.07mm ---XXX
|
||||
@ -336,6 +391,17 @@ fill_pattern = gyroid
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.4 and ! single_extruder_multi_material
|
||||
top_infill_extrusion_width = 0.4
|
||||
|
||||
[print:0.07mm ULTRADETAIL 0.25 nozzle MK3]
|
||||
inherits = *0.07mm*; *0.25nozzle*; *MK3*
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.25 and num_extruders==1
|
||||
infill_speed = 30
|
||||
solid_infill_speed = 30
|
||||
support_material_speed = 30
|
||||
top_solid_infill_speed = 20
|
||||
fill_pattern = grid
|
||||
fill_density = 20%
|
||||
first_layer_extrusion_width = 0.35
|
||||
|
||||
# XXXXXXXXXXXXXXXXXXXX
|
||||
# XXX--- 0.10mm ---XXX
|
||||
# XXXXXXXXXXXXXXXXXXXX
|
||||
@ -392,29 +458,10 @@ top_solid_infill_speed = 30
|
||||
|
||||
# MK3 #
|
||||
[print:0.10mm DETAIL 0.25 nozzle MK3]
|
||||
inherits = *0.10mm*; *0.25nozzle*; *MK3*
|
||||
bridge_speed = 30
|
||||
inherits = *0.10mm*; *0.25nozzleMK3*; *MK3*
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.25
|
||||
external_perimeter_speed = 35
|
||||
infill_acceleration = 1250
|
||||
infill_speed = 200
|
||||
max_print_speed = 200
|
||||
perimeter_speed = 45
|
||||
solid_infill_speed = 200
|
||||
top_solid_infill_speed = 50
|
||||
|
||||
# MK3 #
|
||||
[print:0.10mm DETAIL 0.6 nozzle MK3]
|
||||
inherits = *0.10mm*; *0.6nozzle*; *MK3*
|
||||
bridge_speed = 30
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.6
|
||||
external_perimeter_speed = 35
|
||||
infill_acceleration = 1250
|
||||
infill_speed = 200
|
||||
max_print_speed = 200
|
||||
perimeter_speed = 45
|
||||
solid_infill_speed = 200
|
||||
top_solid_infill_speed = 50
|
||||
fill_pattern = grid
|
||||
fill_density = 20%
|
||||
|
||||
# XXXXXXXXXXXXXXXXXXXX
|
||||
# XXX--- 0.15mm ---XXX
|
||||
@ -541,17 +588,27 @@ support_material_with_sheath = 0
|
||||
support_material_xy_spacing = 80%
|
||||
|
||||
# MK3 #
|
||||
[print:0.15mm OPTIMAL 0.25 nozzle MK3]
|
||||
inherits = *0.15mm*; *0.25nozzle*; *MK3*
|
||||
bridge_speed = 30
|
||||
[print:0.15mm QUALITY 0.25 nozzle MK3]
|
||||
inherits = *0.15mm*; *0.25nozzleMK3*; *MK3*
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.25
|
||||
fill_pattern = grid
|
||||
fill_density = 20%
|
||||
|
||||
# MK3 #
|
||||
[print:0.15mm DETAIL 0.6 nozzle MK3]
|
||||
inherits = *0.15mm*; *0.6nozzleMK3*; *MK306*
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.6
|
||||
external_perimeter_speed = 35
|
||||
infill_acceleration = 1250
|
||||
infill_speed = 200
|
||||
max_print_speed = 200
|
||||
infill_speed = 70
|
||||
max_print_speed = 100
|
||||
perimeter_speed = 45
|
||||
solid_infill_speed = 200
|
||||
top_solid_infill_speed = 50
|
||||
solid_infill_speed = 70
|
||||
top_solid_infill_speed = 45
|
||||
|
||||
# XXXXXXXXXXXXXXXXXXXX
|
||||
# XXX--- 0.20mm ---XXX
|
||||
# XXXXXXXXXXXXXXXXXXXX
|
||||
|
||||
[print:*0.20mm*]
|
||||
inherits = *common*
|
||||
@ -567,23 +624,6 @@ solid_infill_speed = 50
|
||||
top_infill_extrusion_width = 0.4
|
||||
top_solid_layers = 5
|
||||
|
||||
# MK3 #
|
||||
[print:0.15mm OPTIMAL 0.6 nozzle MK3]
|
||||
inherits = *0.15mm*; *0.6nozzle*; *MK3*
|
||||
bridge_speed = 30
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.6
|
||||
external_perimeter_speed = 35
|
||||
infill_acceleration = 1250
|
||||
infill_speed = 200
|
||||
max_print_speed = 200
|
||||
perimeter_speed = 45
|
||||
solid_infill_speed = 200
|
||||
top_solid_infill_speed = 50
|
||||
|
||||
# XXXXXXXXXXXXXXXXXXXX
|
||||
# XXX--- 0.20mm ---XXX
|
||||
# XXXXXXXXXXXXXXXXXXXX
|
||||
|
||||
# MK2 #
|
||||
[print:0.20mm 100mms Linear Advance]
|
||||
inherits = *0.20mm*
|
||||
@ -674,17 +714,68 @@ support_material_with_sheath = 0
|
||||
support_material_xy_spacing = 80%
|
||||
|
||||
# MK3 #
|
||||
[print:0.20mm FAST 0.6 nozzle MK3]
|
||||
inherits = *0.20mm*; *0.6nozzle*; *MK3*
|
||||
bridge_speed = 30
|
||||
[print:0.20mm DETAIL 0.6 nozzle MK3]
|
||||
inherits = *0.20mm*; *0.6nozzleMK3*; *MK306*
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.6
|
||||
external_perimeter_speed = 35
|
||||
infill_acceleration = 1250
|
||||
infill_speed = 200
|
||||
max_print_speed = 200
|
||||
infill_speed = 70
|
||||
max_print_speed = 100
|
||||
perimeter_speed = 45
|
||||
solid_infill_speed = 200
|
||||
top_solid_infill_speed = 50
|
||||
solid_infill_speed = 70
|
||||
top_solid_infill_speed = 45
|
||||
|
||||
# XXXXXXXXXXXXXXXXXXXX
|
||||
# XXX--- 0.30mm ---XXX
|
||||
# XXXXXXXXXXXXXXXXXXXX
|
||||
|
||||
[print:*0.30mm*]
|
||||
inherits = *common*
|
||||
bottom_solid_layers = 4
|
||||
bridge_flow_ratio = 0.95
|
||||
external_perimeter_speed = 40
|
||||
infill_acceleration = 2000
|
||||
infill_speed = 60
|
||||
layer_height = 0.3
|
||||
perimeter_acceleration = 800
|
||||
perimeter_speed = 50
|
||||
solid_infill_speed = 50
|
||||
top_infill_extrusion_width = 0.4
|
||||
top_solid_layers = 4
|
||||
|
||||
[print:0.30mm QUALITY 0.6 nozzle MK3]
|
||||
inherits = *0.30mm*; *0.6nozzleMK3*; *MK306*
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.6
|
||||
external_perimeter_speed = 35
|
||||
infill_acceleration = 1250
|
||||
infill_speed = 70
|
||||
max_print_speed = 100
|
||||
perimeter_speed = 45
|
||||
solid_infill_speed = 70
|
||||
top_solid_infill_speed = 45
|
||||
|
||||
[print:0.30mm DRAFT MK3]
|
||||
inherits = *0.30mm*; *MK3*
|
||||
bottom_solid_layers = 3
|
||||
bridge_speed = 30
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.4
|
||||
external_perimeter_speed = 35
|
||||
infill_acceleration = 1250
|
||||
infill_speed = 85
|
||||
max_print_speed = 200
|
||||
perimeter_speed = 50
|
||||
small_perimeter_speed = 30
|
||||
solid_infill_speed = 80
|
||||
top_solid_infill_speed = 40
|
||||
support_material_speed = 45
|
||||
external_perimeter_extrusion_width = 0.6
|
||||
extrusion_width = 0.5
|
||||
first_layer_extrusion_width = 0.42
|
||||
infill_extrusion_width = 0.5
|
||||
perimeter_extrusion_width = 0.5
|
||||
solid_infill_extrusion_width = 0.5
|
||||
top_infill_extrusion_width = 0.45
|
||||
support_material_extrusion_width = 0.35
|
||||
|
||||
# XXXXXXXXXXXXXXXXXXXX
|
||||
# XXX--- 0.35mm ---XXX
|
||||
@ -742,6 +833,57 @@ support_material_interface_layers = 2
|
||||
support_material_with_sheath = 0
|
||||
support_material_xy_spacing = 150%
|
||||
|
||||
# MK3 #
|
||||
[print:0.35mm SPEED 0.6 nozzle MK3]
|
||||
inherits = *0.35mm*; *0.6nozzleMK3*; *MK306*
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.6
|
||||
external_perimeter_speed = 35
|
||||
infill_acceleration = 1250
|
||||
infill_speed = 70
|
||||
max_print_speed = 100
|
||||
perimeter_speed = 45
|
||||
solid_infill_speed = 70
|
||||
top_solid_infill_speed = 45
|
||||
external_perimeter_extrusion_width = 0.68
|
||||
perimeter_extrusion_width = 0.68
|
||||
|
||||
# XXXXXXXXXXXXXXXXXXXX
|
||||
# XXX--- 0.40mm ---XXX
|
||||
# XXXXXXXXXXXXXXXXXXXX
|
||||
|
||||
[print:*0.40mm*]
|
||||
inherits = *common*
|
||||
bottom_solid_layers = 3
|
||||
external_perimeter_extrusion_width = 0.6
|
||||
external_perimeter_speed = 40
|
||||
first_layer_extrusion_width = 0.65
|
||||
infill_acceleration = 2000
|
||||
infill_speed = 60
|
||||
layer_height = 0.4
|
||||
perimeter_acceleration = 800
|
||||
perimeter_extrusion_width = 0.65
|
||||
perimeter_speed = 50
|
||||
solid_infill_extrusion_width = 0.65
|
||||
solid_infill_speed = 60
|
||||
top_solid_infill_speed = 40
|
||||
top_solid_layers = 4
|
||||
|
||||
# MK3 #
|
||||
[print:0.40mm DRAFT 0.6 nozzle MK3]
|
||||
inherits = *0.40mm*; *0.6nozzleMK3*; *MK306*
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.6
|
||||
external_perimeter_speed = 35
|
||||
infill_acceleration = 1250
|
||||
infill_speed = 70
|
||||
max_print_speed = 100
|
||||
perimeter_speed = 45
|
||||
solid_infill_speed = 70
|
||||
top_solid_infill_speed = 45
|
||||
external_perimeter_extrusion_width = 0.7
|
||||
perimeter_extrusion_width = 0.7
|
||||
infill_extrusion_width = 0.72
|
||||
solid_infill_extrusion_width = 0.72
|
||||
|
||||
# XXXXXXXXXXXXXXXXXXXXXX
|
||||
# XXX----- MK2.5 ----XXX
|
||||
# XXXXXXXXXXXXXXXXXXXXXX
|
||||
@ -837,7 +979,7 @@ filament_settings_id = ""
|
||||
filament_soluble = 0
|
||||
min_print_speed = 15
|
||||
slowdown_below_layer_time = 20
|
||||
start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}30{endif}; Filament gcode"
|
||||
start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}30{endif} ; Filament gcode"
|
||||
|
||||
[filament:*PLA*]
|
||||
inherits = *common*
|
||||
@ -854,6 +996,7 @@ first_layer_temperature = 215
|
||||
max_fan_speed = 100
|
||||
min_fan_speed = 100
|
||||
temperature = 210
|
||||
start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{elsif nozzle_diameter[0]==0.6}15{else}30{endif} ; Filament gcode"
|
||||
|
||||
[filament:*PET*]
|
||||
inherits = *common*
|
||||
@ -869,9 +1012,14 @@ first_layer_bed_temperature = 85
|
||||
first_layer_temperature = 230
|
||||
max_fan_speed = 50
|
||||
min_fan_speed = 30
|
||||
start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}45{endif}; Filament gcode"
|
||||
start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{elsif nozzle_diameter[0]==0.6}22{else}45{endif} ; Filament gcode"
|
||||
temperature = 240
|
||||
|
||||
[filament:*PET06*]
|
||||
inherits = *PET*
|
||||
compatible_printers_condition = nozzle_diameter[0]==0.6 and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material)
|
||||
filament_max_volumetric_speed = 15
|
||||
|
||||
[filament:*ABS*]
|
||||
inherits = *common*
|
||||
bed_temperature = 110
|
||||
@ -889,6 +1037,7 @@ first_layer_temperature = 255
|
||||
max_fan_speed = 30
|
||||
min_fan_speed = 20
|
||||
temperature = 255
|
||||
start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{elsif nozzle_diameter[0]==0.6}15{else}30{endif} ; Filament gcode"
|
||||
|
||||
[filament:*FLEX*]
|
||||
inherits = *common*
|
||||
@ -916,10 +1065,11 @@ inherits = *PLA*
|
||||
# For now, all but selected filaments are disabled for the MMU 2.0
|
||||
compatible_printers_condition = nozzle_diameter[0]>0.35 and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material)
|
||||
extrusion_multiplier = 1.2
|
||||
filament_cost = 80.65
|
||||
filament_density = 4
|
||||
filament_cost = 56.64
|
||||
filament_density = 3.9
|
||||
filament_colour = #804040
|
||||
filament_max_volumetric_speed = 10
|
||||
filament_max_volumetric_speed = 9
|
||||
filament_notes = "List of materials tested with standard print settings:\n\nColorFabb bronzeFill\nColorFabb brassFill\nColorFabb steelFill\nColorFabb copperFill"
|
||||
|
||||
[filament:ColorFabb HT]
|
||||
inherits = *PET*
|
||||
@ -943,19 +1093,31 @@ inherits = *PLA*
|
||||
filament_cost = 55.5
|
||||
filament_density = 1.24
|
||||
|
||||
[filament:ColorFabb Woodfil]
|
||||
[filament:ColorFabb woodFill]
|
||||
inherits = *PLA*
|
||||
# For now, all but selected filaments are disabled for the MMU 2.0
|
||||
compatible_printers_condition = nozzle_diameter[0]>0.35 and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material)
|
||||
extrusion_multiplier = 1.2
|
||||
filament_cost = 62.9
|
||||
filament_density = 1.15
|
||||
filament_colour = #804040
|
||||
filament_colour = #dfc287
|
||||
filament_max_volumetric_speed = 10
|
||||
first_layer_temperature = 200
|
||||
start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}10{endif}; Filament gcode"
|
||||
temperature = 200
|
||||
|
||||
[filament:ColorFabb corkFill]
|
||||
inherits = *PLA*
|
||||
compatible_printers_condition = nozzle_diameter[0]>0.35 and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material)
|
||||
extrusion_multiplier = 1.2
|
||||
filament_cost = 45.45
|
||||
filament_density = 1.18
|
||||
filament_colour = #634d33
|
||||
filament_max_volumetric_speed = 6
|
||||
first_layer_temperature = 220
|
||||
start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}10{endif}; Filament gcode"
|
||||
temperature = 220
|
||||
|
||||
[filament:ColorFabb XT]
|
||||
inherits = *PET*
|
||||
filament_type = PET
|
||||
@ -1011,7 +1173,7 @@ temperature = 260
|
||||
inherits = *PET*
|
||||
filament_cost = 56.9
|
||||
filament_density = 1.26
|
||||
filament_notes = "List of manufacturers tested with standart PET print settings:\n\nE3D Edge\nFillamentum CPE GH100\nPlasty Mladec PETG"
|
||||
filament_notes = "List of manufacturers tested with standard PET print settings:\n\nE3D Edge\nFillamentum CPE GH100\nPlasty Mladec PETG"
|
||||
|
||||
[filament:E3D PC-ABS]
|
||||
inherits = *ABS*
|
||||
@ -1046,7 +1208,7 @@ max_fan_speed = 50
|
||||
min_fan_speed = 50
|
||||
temperature = 275
|
||||
|
||||
[filament:Fillamentum Timberfil]
|
||||
[filament:Fillamentum Timberfill]
|
||||
inherits = *PLA*
|
||||
# For now, all but selected filaments are disabled for the MMU 2.0
|
||||
compatible_printers_condition = nozzle_diameter[0]>0.35 and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material)
|
||||
@ -1063,19 +1225,19 @@ temperature = 190
|
||||
inherits = *ABS*
|
||||
filament_cost = 27.82
|
||||
filament_density = 1.04
|
||||
filament_notes = "List of materials tested with standart ABS print settings:\n\nEsun ABS\nFil-A-Gehr ABS\nHatchboxABS\nPlasty Mladec ABS"
|
||||
filament_notes = "List of materials tested with standard ABS print settings:\n\nEsun ABS\nFil-A-Gehr ABS\nHatchboxABS\nPlasty Mladec ABS"
|
||||
|
||||
[filament:Generic PET]
|
||||
inherits = *PET*
|
||||
filament_cost = 27.82
|
||||
filament_density = 1.27
|
||||
filament_notes = "List of manufacturers tested with standart PET print settings:\n\nE3D Edge\nFillamentum CPE GH100\nPlasty Mladec PETG"
|
||||
filament_notes = "List of manufacturers tested with standard PET print settings:\n\nE3D Edge\nFillamentum CPE GH100\nPlasty Mladec PETG"
|
||||
|
||||
[filament:Generic PLA]
|
||||
inherits = *PLA*
|
||||
filament_cost = 25.4
|
||||
filament_density = 1.24
|
||||
filament_notes = "List of materials tested with standart PLA print settings:\n\nDas Filament\nEsun PLA\nEUMAKERS PLA\nFiberlogy HD-PLA\nFillamentum PLA\nFloreon3D\nHatchbox PLA\nPlasty Mladec PLA\nPrimavalue PLA\nProto pasta Matte Fiber\nVerbatim PLA\nVerbatim BVOH"
|
||||
filament_notes = "List of materials tested with standard PLA print settings:\n\nDas Filament\nEsun PLA\nEUMAKERS PLA\nFiberlogy HD-PLA\nFillamentum PLA\nFloreon3D\nHatchbox PLA\nPlasty Mladec PLA\nPrimavalue PLA\nProto pasta Matte Fiber\nVerbatim PLA\nVerbatim BVOH"
|
||||
|
||||
[filament:Polymaker PC-Max]
|
||||
inherits = *ABS*
|
||||
@ -1094,11 +1256,11 @@ filament_density = 1.23
|
||||
cooling = 0
|
||||
fan_always_on = 0
|
||||
filament_colour = #FFFFD7
|
||||
filament_max_volumetric_speed = 10
|
||||
filament_notes = "List of materials tested with standart PVA print settings:\n\nPrimaSelect PVA+\nICE FILAMENTS PVA 'NAUGHTY NATURAL'\nVerbatim BVOH"
|
||||
filament_max_volumetric_speed = 4
|
||||
filament_notes = "List of materials tested with standard PVA print settings:\n\nPrimaSelect PVA+\nICE FILAMENTS PVA 'NAUGHTY NATURAL'"
|
||||
filament_ramming_parameters = "120 100 8.3871 8.6129 8.93548 9.22581 9.48387 9.70968 9.87097 10.0323 10.2258 10.4194 10.6452 10.8065| 0.05 8.34193 0.45 8.73548 0.95 9.34836 1.45 9.78385 1.95 10.0871 2.45 10.5161 2.95 10.8903 3.45 7.6 3.95 7.6 4.45 7.6 4.95 7.6"
|
||||
filament_soluble = 1
|
||||
filament_type = PVA
|
||||
filament_type = PLA
|
||||
first_layer_temperature = 195
|
||||
start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}10{endif}; Filament gcode"
|
||||
temperature = 195
|
||||
@ -1107,7 +1269,7 @@ temperature = 195
|
||||
inherits = *ABS*
|
||||
filament_cost = 27.82
|
||||
filament_density = 1.08
|
||||
filament_notes = "List of materials tested with standart ABS print settings:\n\nEsun ABS\nFil-A-Gehr ABS\nHatchboxABS\nPlasty Mladec ABS"
|
||||
filament_notes = "List of materials tested with standard ABS print settings:\n\nEsun ABS\nFil-A-Gehr ABS\nHatchboxABS\nPlasty Mladec ABS"
|
||||
|
||||
[filament:*ABS MMU2*]
|
||||
inherits = Prusa ABS
|
||||
@ -1150,7 +1312,8 @@ temperature = 220
|
||||
inherits = *PET*
|
||||
filament_cost = 27.82
|
||||
filament_density = 1.27
|
||||
filament_notes = "List of manufacturers tested with standart PET print settings:\n\nE3D Edge\nFillamentum CPE GH100\nPlasty Mladec PETG"
|
||||
filament_notes = "List of manufacturers tested with standard PET print settings:\n\nE3D Edge\nFillamentum CPE GH100\nPlasty Mladec PETG"
|
||||
compatible_printers_condition = nozzle_diameter[0]!=0.6 and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material)
|
||||
|
||||
[filament:Prusament PETG]
|
||||
inherits = *PET*
|
||||
@ -1158,6 +1321,20 @@ first_layer_temperature = 240
|
||||
temperature = 250
|
||||
filament_cost = 24.99
|
||||
filament_density = 1.27
|
||||
compatible_printers_condition = nozzle_diameter[0]!=0.6 and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material)
|
||||
|
||||
[filament:Prusa PET 0.6 nozzle]
|
||||
inherits = *PET06*
|
||||
filament_cost = 27.82
|
||||
filament_density = 1.27
|
||||
filament_notes = "List of manufacturers tested with standard PET print settings:\n\nE3D Edge\nFillamentum CPE GH100\nPlasty Mladec PETG"
|
||||
|
||||
[filament:Prusament PETG 0.6 nozzle]
|
||||
inherits = *PET06*
|
||||
first_layer_temperature = 240
|
||||
temperature = 250
|
||||
filament_cost = 24.99
|
||||
filament_density = 1.27
|
||||
|
||||
[filament:*PET MMU2*]
|
||||
inherits = Prusa PET
|
||||
@ -1189,7 +1366,7 @@ inherits = *PET MMU2*
|
||||
inherits = *PLA*
|
||||
filament_cost = 25.4
|
||||
filament_density = 1.24
|
||||
filament_notes = "List of materials tested with standart PLA print settings:\n\nDas Filament\nEsun PLA\nEUMAKERS PLA\nFiberlogy HD-PLA\nFillamentum PLA\nFloreon3D\nHatchbox PLA\nPlasty Mladec PLA\nPrimavalue PLA\nProto pasta Matte Fiber\nVerbatim PLA\nVerbatim BVOH"
|
||||
filament_notes = "List of materials tested with standard PLA print settings:\n\nDas Filament\nEsun PLA\nEUMAKERS PLA\nFiberlogy HD-PLA\nFillamentum PLA\nFloreon3D\nHatchbox PLA\nPlasty Mladec PLA\nPrimavalue PLA\nProto pasta Matte Fiber\nVerbatim PLA\nVerbatim BVOH"
|
||||
|
||||
[filament:Prusament PLA]
|
||||
inherits = *PLA*
|
||||
@ -1275,7 +1452,7 @@ fan_always_on = 0
|
||||
fan_below_layer_time = 100
|
||||
filament_colour = #FFFFD7
|
||||
filament_max_volumetric_speed = 4
|
||||
filament_notes = "List of materials tested with standart PLA print settings:\n\nDas Filament\nEsun PLA\nEUMAKERS PLA\nFiberlogy HD-PLA\nFillamentum PLA\nFloreon3D\nHatchbox PLA\nPlasty Mladec PLA\nPrimavalue PLA\nProto pasta Matte Fiber\nVerbatim PLA\nVerbatim BVOH"
|
||||
filament_notes = "List of materials tested with standard PVA print settings:\n\nVerbatim BVOH"
|
||||
filament_soluble = 1
|
||||
filament_type = PLA
|
||||
first_layer_bed_temperature = 60
|
||||
@ -1289,7 +1466,6 @@ temperature = 210
|
||||
inherits = Verbatim BVOH
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material
|
||||
temperature = 195
|
||||
filament_notes = BVOH
|
||||
fan_always_on = 1
|
||||
first_layer_temperature = 200
|
||||
filament_cooling_final_speed = 1
|
||||
@ -1326,7 +1502,7 @@ filament_loading_speed = 14
|
||||
filament_loading_speed_start = 19
|
||||
filament_max_volumetric_speed = 4
|
||||
filament_minimal_purge_on_wipe_tower = 5
|
||||
filament_notes = PVA
|
||||
filament_notes = "List of materials tested with standard PVA print settings:\n\nPrimaSelect PVA+"
|
||||
filament_ramming_parameters = "120 110 3.83871 3.90323 3.96774 4.03226 4.09677 4.19355 4.3871 4.83871 5.67742 6.93548 8.54839 10.3226 11.9677 13.2581 14.129 14.5806| 0.05 3.8258 0.45 3.89676 0.95 4.05807 1.45 4.23548 1.95 5.18386 2.45 7.80651 2.95 11.5356 3.45 13.9872 3.95 14.7613 4.45 7.6 4.95 7.6"
|
||||
filament_soluble = 1
|
||||
filament_toolchange_delay = 0
|
||||
@ -1356,7 +1532,7 @@ fan_always_on = 1
|
||||
fan_below_layer_time = 100
|
||||
filament_colour = #DEE0E6
|
||||
filament_max_volumetric_speed = 5
|
||||
filament_notes = "List of materials tested with standart PLA print settings:\n\nEsun PLA\nFiberlogy HD-PLA\nFillamentum PLA\nFloreon3D\nHatchbox PLA\nPlasty Mladec PLA\nPrimavalue PLA\nProto pasta Matte Fiber\nEUMAKERS PLA"
|
||||
filament_notes = "List of materials tested with standard PLA print settings:\n\nEsun PLA\nFiberlogy HD-PLA\nFillamentum PLA\nFloreon3D\nHatchbox PLA\nPlasty Mladec PLA\nPrimavalue PLA\nProto pasta Matte Fiber\nEUMAKERS PLA"
|
||||
filament_type = PLA
|
||||
first_layer_bed_temperature = 100
|
||||
first_layer_temperature = 220
|
||||
@ -1368,14 +1544,15 @@ temperature = 220
|
||||
[sla_print:*common*]
|
||||
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_SL1.*/
|
||||
layer_height = 0.05
|
||||
output_filename_format = [input_filename_base].dwz
|
||||
output_filename_format = [input_filename_base].sl1
|
||||
pad_edge_radius = 0.5
|
||||
pad_enable = 1
|
||||
pad_max_merge_distance = 50
|
||||
pad_wall_height = 3
|
||||
pad_wall_height = 0
|
||||
pad_wall_thickness = 1
|
||||
pad_wall_slope = 90
|
||||
support_base_diameter = 3
|
||||
support_base_height = 0.5
|
||||
support_base_height = 1
|
||||
support_critical_angle = 45
|
||||
support_density_at_45 = 250
|
||||
support_density_at_horizontal = 500
|
||||
@ -1386,6 +1563,7 @@ support_max_bridge_length = 10
|
||||
support_minimal_z = 0
|
||||
support_object_elevation = 5
|
||||
support_pillar_diameter = 1
|
||||
support_pillar_connection_mode = zigzag
|
||||
support_pillar_widening_factor = 0
|
||||
supports_enable = 1
|
||||
|
||||
@ -1451,6 +1629,11 @@ inherits = *common 0.025*
|
||||
exposure_time = 5
|
||||
initial_exposure_time = 35
|
||||
|
||||
[sla_material:SL1 Orange solid 0.025]
|
||||
inherits = *common 0.025*
|
||||
exposure_time = 5
|
||||
initial_exposure_time = 35
|
||||
|
||||
########### Materials 0.05
|
||||
|
||||
[sla_material:3DM-HTR140 (high temperature) 0.05]
|
||||
@ -1468,11 +1651,31 @@ inherits = *common 0.05*
|
||||
exposure_time = 8
|
||||
initial_exposure_time = 45
|
||||
|
||||
[sla_material:Bluecast Keramaster Dental 0.05]
|
||||
inherits = *common 0.05*
|
||||
exposure_time = 7
|
||||
initial_exposure_time = 45
|
||||
|
||||
[sla_material:Bluecast LCD-DLP Original 0.05]
|
||||
inherits = *common 0.05*
|
||||
exposure_time = 10
|
||||
initial_exposure_time = 60
|
||||
|
||||
[sla_material:Bluecast Phrozen Wax 0.05]
|
||||
inherits = *common 0.05*
|
||||
exposure_time = 10
|
||||
initial_exposure_time = 55
|
||||
|
||||
[sla_material:Bluecast S+ 0.05]
|
||||
inherits = *common 0.05*
|
||||
exposure_time = 9
|
||||
initial_exposure_time = 45
|
||||
|
||||
[sla_material:Bluecast X2 0.05]
|
||||
inherits = *common 0.05*
|
||||
exposure_time = 10
|
||||
initial_exposure_time = 60
|
||||
|
||||
[sla_material:Jamg He PJHC-00 Yellow 0.05]
|
||||
inherits = *common 0.05*
|
||||
exposure_time = 7
|
||||
@ -1485,7 +1688,7 @@ initial_exposure_time = 45
|
||||
|
||||
[sla_material:Jamg He PJHC-30 Orange 0.05]
|
||||
inherits = *common 0.05*
|
||||
exposure_time = 7
|
||||
exposure_time = 7.5
|
||||
initial_exposure_time = 45
|
||||
|
||||
[sla_material:Jamg He PJHC-60 Gray 0.05]
|
||||
@ -1523,8 +1726,6 @@ inherits = *common 0.05*
|
||||
exposure_time = 7
|
||||
initial_exposure_time = 40
|
||||
|
||||
# v2
|
||||
|
||||
[sla_material:3DM-ABS 0.05]
|
||||
inherits = *common 0.05*
|
||||
exposure_time = 9
|
||||
@ -1570,11 +1771,101 @@ inherits = *common 0.05*
|
||||
exposure_time = 6.5
|
||||
initial_exposure_time = 40
|
||||
|
||||
[sla_material:Harz Labs Model Resin Cherry 0.05]
|
||||
inherits = *common 0.05*
|
||||
exposure_time = 8
|
||||
initial_exposure_time = 45
|
||||
|
||||
[sla_material:Jamg He CRX-70C High Tenacity Black 0.05]
|
||||
inherits = *common 0.05*
|
||||
exposure_time = 7
|
||||
initial_exposure_time = 40
|
||||
|
||||
[sla_material:Jamg He MC-2000 Casting Green 0.05]
|
||||
inherits = *common 0.05*
|
||||
exposure_time = 13
|
||||
initial_exposure_time = 40
|
||||
|
||||
[sla_material:Jamg He PJHC-00 Solid Yellow 0.05]
|
||||
inherits = *common 0.05*
|
||||
exposure_time = 7
|
||||
initial_exposure_time = 40
|
||||
|
||||
[sla_material:Jamg He PJHC-20 White 0.05]
|
||||
inherits = *common 0.05*
|
||||
exposure_time = 7
|
||||
initial_exposure_time = 45
|
||||
|
||||
[sla_material:Jamg He PJHC-80 Transparent Green 0.05]
|
||||
inherits = *common 0.05*
|
||||
exposure_time = 8
|
||||
initial_exposure_time = 45
|
||||
|
||||
[sla_material:Jamg He PJHC-80 Transparent Red 0.05]
|
||||
inherits = *common 0.05*
|
||||
exposure_time = 7
|
||||
initial_exposure_time = 45
|
||||
|
||||
[sla_material:Jamg He PJHC-81 Solid Maroon 0.05]
|
||||
inherits = *common 0.05*
|
||||
exposure_time = 9
|
||||
initial_exposure_time = 45
|
||||
|
||||
[sla_material:Jamg He PJHC-90 Solid Pink 0.05]
|
||||
inherits = *common 0.05*
|
||||
exposure_time = 7
|
||||
initial_exposure_time = 40
|
||||
|
||||
[sla_material:Jamg He RJHC-00 Yellow Flexible 0.05]
|
||||
inherits = *common 0.05*
|
||||
exposure_time = 9
|
||||
initial_exposure_time = 40
|
||||
|
||||
[sla_material:Jamg He RJHC-10 Clear Flexible 0.05]
|
||||
inherits = *common 0.05*
|
||||
exposure_time = 9
|
||||
initial_exposure_time = 40
|
||||
|
||||
[sla_material:Jamg He RJHC-20 White Flexible 0.05]
|
||||
inherits = *common 0.05*
|
||||
exposure_time = 9
|
||||
initial_exposure_time = 40
|
||||
|
||||
[sla_material:Jamg He RJHC-50 Blue Flexible 0.05]
|
||||
inherits = *common 0.05*
|
||||
exposure_time = 9
|
||||
initial_exposure_time = 40
|
||||
|
||||
[sla_material:Jamg He RJHC-70 Black Flexible 0.05]
|
||||
inherits = *common 0.05*
|
||||
exposure_time = 9
|
||||
initial_exposure_time = 40
|
||||
|
||||
[sla_material:Jamg He RJHC-81 Red Flexible 0.05]
|
||||
inherits = *common 0.05*
|
||||
exposure_time = 9
|
||||
initial_exposure_time = 40
|
||||
|
||||
[sla_material:SL1 Orange solid 0.05]
|
||||
inherits = *common 0.05*
|
||||
exposure_time = 7.5
|
||||
initial_exposure_time = 45
|
||||
|
||||
[sla_material:SL1 Red transparent 0.05]
|
||||
inherits = *common 0.05*
|
||||
exposure_time = 7.5
|
||||
initial_exposure_time = 45
|
||||
|
||||
########### Materials 0.035
|
||||
|
||||
[sla_material:Jamg He PJHC-30 Orange 0.035]
|
||||
inherits = *common 0.035*
|
||||
exposure_time = 9
|
||||
exposure_time = 6
|
||||
initial_exposure_time = 35
|
||||
|
||||
[sla_material:SL1 Orange solid 0.035]
|
||||
inherits = *common 0.035*
|
||||
exposure_time = 6
|
||||
initial_exposure_time = 35
|
||||
|
||||
########### Materials 0.1
|
||||
@ -1584,6 +1875,11 @@ inherits = *common 0.1*
|
||||
exposure_time = 10
|
||||
initial_exposure_time = 45
|
||||
|
||||
[sla_material:SL1 Orange solid 0.1]
|
||||
inherits = *common 0.1*
|
||||
exposure_time = 10
|
||||
initial_exposure_time = 45
|
||||
|
||||
[printer:*common*]
|
||||
printer_technology = FFF
|
||||
bed_shape = 0x0,250x0,250x210,0x210
|
||||
@ -1750,19 +2046,19 @@ min_layer_height = 0.1
|
||||
inherits = Original Prusa i3 MK2S
|
||||
printer_model = MK2.5
|
||||
remaining_times = 1
|
||||
start_gcode = M115 U3.5.1 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0
|
||||
start_gcode = M115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0
|
||||
|
||||
[printer:Original Prusa i3 MK2.5 0.25 nozzle]
|
||||
inherits = Original Prusa i3 MK2S 0.25 nozzle
|
||||
printer_model = MK2.5
|
||||
remaining_times = 1
|
||||
start_gcode = M115 U3.5.1 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0
|
||||
start_gcode = M115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0
|
||||
|
||||
[printer:Original Prusa i3 MK2.5 0.6 nozzle]
|
||||
inherits = Original Prusa i3 MK2S 0.6 nozzle
|
||||
printer_model = MK2.5
|
||||
remaining_times = 1
|
||||
start_gcode = M115 U3.5.1 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0
|
||||
start_gcode = M115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0
|
||||
|
||||
[printer:Original Prusa i3 MK2.5 MMU2 Single]
|
||||
inherits = Original Prusa i3 MK2.5; *mm2*
|
||||
@ -1791,7 +2087,7 @@ machine_min_travel_rate = 0
|
||||
default_print_profile = 0.15mm OPTIMAL MK2.5
|
||||
default_filament_profile = Prusament PLA
|
||||
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK2.5\n
|
||||
start_gcode = M107\nM115 U3.5.1 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n
|
||||
start_gcode = M107\nM115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n
|
||||
end_gcode = G1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG1 X0 Y200; home X axis\nM84 ; disable motors
|
||||
|
||||
[printer:Original Prusa i3 MK2.5 MMU2]
|
||||
@ -1825,20 +2121,23 @@ single_extruder_multi_material = 1
|
||||
# to be defined explicitely.
|
||||
nozzle_diameter = 0.4,0.4,0.4,0.4,0.4
|
||||
extruder_colour = #FF8000;#DB5182;#00FFFF;#FF4F4F;#9FFF9F
|
||||
start_gcode = M107\nM115 U3.5.1 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG21 ; set units to millimeters\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E32.0 F1073.0\nG1 X5.0 E32.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n
|
||||
start_gcode = M107\nM115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG21 ; set units to millimeters\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E32.0 F1073.0\nG1 X5.0 E32.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n
|
||||
end_gcode = {if has_wipe_tower}\nG1 E-15.0000 F3000\n{else}\nG1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n{endif}\n\n; Unload filament\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n; Lift print head a bit\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+30, max_print_height)}{endif} ; Move print head up\nG1 X0 Y200; home X axis\nM84 ; disable motors\n
|
||||
|
||||
[printer:Original Prusa i3 MK2.5S]
|
||||
inherits = Original Prusa i3 MK2.5
|
||||
printer_model = MK2.5S
|
||||
start_gcode = M115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0
|
||||
|
||||
[printer:Original Prusa i3 MK2.5S 0.25 nozzle]
|
||||
inherits = Original Prusa i3 MK2.5 0.25 nozzle
|
||||
printer_model = MK2.5S
|
||||
start_gcode = M115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0
|
||||
|
||||
[printer:Original Prusa i3 MK2.5S 0.6 nozzle]
|
||||
inherits = Original Prusa i3 MK2.5 0.6 nozzle
|
||||
printer_model = MK2.5S
|
||||
start_gcode = M115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0
|
||||
|
||||
[printer:Original Prusa i3 MK2.5S MMU2S Single]
|
||||
inherits = Original Prusa i3 MK2.5; *mm2s*
|
||||
@ -1867,7 +2166,7 @@ machine_min_travel_rate = 0
|
||||
default_print_profile = 0.15mm OPTIMAL MK2.5
|
||||
default_filament_profile = Prusament PLA
|
||||
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK2.5\n
|
||||
start_gcode = M107\nM115 U3.5.1 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n
|
||||
start_gcode = M107\nM115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n
|
||||
end_gcode = G1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG1 X0 Y200; home X axis\nM84 ; disable motors
|
||||
|
||||
[printer:Original Prusa i3 MK2.5S MMU2S]
|
||||
@ -1901,7 +2200,7 @@ single_extruder_multi_material = 1
|
||||
# to be defined explicitely.
|
||||
nozzle_diameter = 0.4,0.4,0.4,0.4,0.4
|
||||
extruder_colour = #FF8000;#DB5182;#00FFFF;#FF4F4F;#9FFF9F
|
||||
start_gcode = M107\nM115 U3.5.1 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG21 ; set units to millimeters\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E29.0 F1073.0\nG1 X5.0 E29.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n
|
||||
start_gcode = M107\nM115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG21 ; set units to millimeters\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E29.0 F1073.0\nG1 X5.0 E29.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n
|
||||
end_gcode = {if has_wipe_tower}\nG1 E-15.0000 F3000\n{else}\nG1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n{endif}\n\n; Unload filament\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n; Lift print head a bit\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+30, max_print_height)}{endif} ; Move print head up\nG1 X0 Y200; home X axis\nM84 ; disable motors\n
|
||||
|
||||
|
||||
@ -1933,7 +2232,7 @@ remaining_times = 1
|
||||
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK3\n
|
||||
retract_lift_below = 209
|
||||
max_print_height = 210
|
||||
start_gcode = M115 U3.5.1 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif}
|
||||
start_gcode = M115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif}
|
||||
printer_model = MK3
|
||||
default_print_profile = 0.15mm QUALITY MK3
|
||||
|
||||
@ -1943,27 +2242,31 @@ nozzle_diameter = 0.25
|
||||
max_layer_height = 0.15
|
||||
min_layer_height = 0.05
|
||||
printer_variant = 0.25
|
||||
start_gcode = M115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E8.0 F700.0 ; intro line\nG1 X100.0 E12.5 F700.0 ; intro line\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif}
|
||||
default_print_profile = 0.10mm DETAIL 0.25 nozzle MK3
|
||||
|
||||
[printer:Original Prusa i3 MK3 0.6 nozzle]
|
||||
inherits = Original Prusa i3 MK3
|
||||
nozzle_diameter = 0.6
|
||||
max_layer_height = 0.35
|
||||
min_layer_height = 0.1
|
||||
max_layer_height = 0.40
|
||||
min_layer_height = 0.15
|
||||
printer_variant = 0.6
|
||||
default_print_profile = 0.15mm OPTIMAL 0.6 nozzle MK3
|
||||
default_print_profile = 0.30mm QUALITY 0.6 nozzle MK3
|
||||
|
||||
[printer:Original Prusa i3 MK3S]
|
||||
inherits = Original Prusa i3 MK3
|
||||
printer_model = MK3S
|
||||
start_gcode = M115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif}
|
||||
|
||||
[printer:Original Prusa i3 MK3S 0.25 nozzle]
|
||||
inherits = Original Prusa i3 MK3 0.25 nozzle
|
||||
printer_model = MK3S
|
||||
start_gcode = M115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E8.0 F700.0 ; intro line\nG1 X100.0 E12.5 F700.0 ; intro line\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif}
|
||||
|
||||
[printer:Original Prusa i3 MK3S 0.6 nozzle]
|
||||
inherits = Original Prusa i3 MK3 0.6 nozzle
|
||||
printer_model = MK3S
|
||||
start_gcode = M115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif}
|
||||
|
||||
[printer:*mm2*]
|
||||
inherits = Original Prusa i3 MK3
|
||||
@ -1993,7 +2296,7 @@ default_filament_profile = Prusament PLA MMU2
|
||||
inherits = *mm2*
|
||||
single_extruder_multi_material = 0
|
||||
default_filament_profile = Prusament PLA
|
||||
start_gcode = M107\nM115 U3.5.1 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n
|
||||
start_gcode = M107\nM115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n
|
||||
end_gcode = G1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG1 X0 Y200; home X axis\nM84 ; disable motors
|
||||
|
||||
[printer:Original Prusa i3 MK3 MMU2]
|
||||
@ -2004,14 +2307,14 @@ inherits = *mm2*
|
||||
machine_max_acceleration_e = 8000,8000
|
||||
nozzle_diameter = 0.4,0.4,0.4,0.4,0.4
|
||||
extruder_colour = #FF8000;#DB5182;#00FFFF;#FF4F4F;#9FFF9F
|
||||
start_gcode = M107\nM115 U3.5.1 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG21 ; set units to millimeters\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E32.0 F1073.0\nG1 X5.0 E32.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n
|
||||
start_gcode = M107\nM115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG21 ; set units to millimeters\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E32.0 F1073.0\nG1 X5.0 E32.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n
|
||||
end_gcode = {if has_wipe_tower}\nG1 E-15.0000 F3000\n{else}\nG1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n{endif}\n\n; Unload filament\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n; Lift print head a bit\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+30, max_print_height)}{endif} ; Move print head up\nG1 X0 Y200; home X axis\nM84 ; disable motors\n
|
||||
|
||||
[printer:Original Prusa i3 MK3S MMU2S Single]
|
||||
inherits = *mm2s*
|
||||
single_extruder_multi_material = 0
|
||||
default_filament_profile = Prusament PLA
|
||||
start_gcode = M107\nM115 U3.5.1 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n
|
||||
start_gcode = M107\nM115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n
|
||||
end_gcode = G1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG1 X0 Y200; home X axis\nM84 ; disable motors
|
||||
|
||||
[printer:Original Prusa i3 MK3S MMU2S]
|
||||
@ -2019,14 +2322,14 @@ inherits = *mm2s*
|
||||
machine_max_acceleration_e = 8000,8000
|
||||
nozzle_diameter = 0.4,0.4,0.4,0.4,0.4
|
||||
extruder_colour = #FF8000;#DB5182;#00FFFF;#FF4F4F;#9FFF9F
|
||||
start_gcode = M107\nM115 U3.5.1 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG21 ; set units to millimeters\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E29.0 F1073.0\nG1 X5.0 E29.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n
|
||||
start_gcode = M107\nM115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG21 ; set units to millimeters\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E29.0 F1073.0\nG1 X5.0 E29.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n
|
||||
end_gcode = {if has_wipe_tower}\nG1 E-15.0000 F3000\n{else}\nG1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n{endif}\n\n; Unload filament\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n; Lift print head a bit\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+30, max_print_height)}{endif} ; Move print head up\nG1 X0 Y200; home X axis\nM84 ; disable motors\n
|
||||
|
||||
[printer:Original Prusa SL1]
|
||||
printer_technology = SLA
|
||||
printer_model = SL1
|
||||
printer_variant = default
|
||||
default_sla_material_profile = Jamg He Transparent Green 0.05
|
||||
default_sla_material_profile = Jamg He PJHC-30 Orange 0.05
|
||||
default_sla_print_profile = 0.05 Normal
|
||||
bed_shape = 0.98x1.02,119.98x1.02,119.98x68.02,0.98x68.02
|
||||
display_height = 68.04
|
||||
|
@ -13,6 +13,7 @@ add_subdirectory(qhull)
|
||||
add_subdirectory(Shiny)
|
||||
add_subdirectory(semver)
|
||||
add_subdirectory(imgui)
|
||||
#add_subdirectory(test)
|
||||
|
||||
# Adding libnest2d project for bin packing...
|
||||
set(LIBNEST2D_UNITTESTS ON CACHE BOOL "Force generating unittests for libnest2d")
|
||||
@ -60,6 +61,7 @@ if (SLIC3R_GUI)
|
||||
endif()
|
||||
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
set (wxWidgets_CONFIG_OPTIONS "--toolkit=gtk${SLIC3R_GTK}")
|
||||
if (SLIC3R_WX_STABLE)
|
||||
find_package(wxWidgets 3.0 REQUIRED COMPONENTS base core adv html gl)
|
||||
else ()
|
||||
@ -88,9 +90,9 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/platform/msw/slic3r.rc.in ${CMAKE_CUR
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/platform/msw/slic3r.manifest.in ${CMAKE_CURRENT_BINARY_DIR}/slic3r.manifest @ONLY)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/platform/osx/Info.plist.in ${CMAKE_CURRENT_BINARY_DIR}/Info.plist @ONLY)
|
||||
if (MSVC)
|
||||
add_library(slic3r SHARED slic3r.cpp)
|
||||
add_library(slic3r SHARED slic3r.cpp slic3r.hpp)
|
||||
else ()
|
||||
add_executable(slic3r slic3r.cpp)
|
||||
add_executable(slic3r slic3r.cpp slic3r.hpp)
|
||||
endif ()
|
||||
if (NOT MSVC)
|
||||
if(SLIC3R_GUI)
|
||||
@ -153,19 +155,19 @@ endif ()
|
||||
# Also the shim may load the Mesa software OpenGL renderer if the default renderer does not support OpenGL 2.0 and higher.
|
||||
if (MSVC)
|
||||
add_executable(slic3r_app_gui WIN32 slic3r_app_msvc.cpp ${CMAKE_CURRENT_BINARY_DIR}/slic3r.rc)
|
||||
target_compile_definitions(slic3r_app_gui PRIVATE -DSLIC3R_WRAPPER_NOCONSOLE -DSLIC3R_WRAPPER_GUI)
|
||||
target_compile_definitions(slic3r_app_gui PRIVATE -DSLIC3R_WRAPPER_NOCONSOLE)
|
||||
add_dependencies(slic3r_app_gui slic3r)
|
||||
set_target_properties(slic3r_app_gui PROPERTIES OUTPUT_NAME "slic3r")
|
||||
|
||||
add_executable(slic3r_app_console slic3r_app_msvc.cpp ${CMAKE_CURRENT_BINARY_DIR}/slic3r.rc)
|
||||
target_compile_definitions(slic3r_app_console PRIVATE -DSLIC3R_WRAPPER_CONSOLE -DSLIC3R_WRAPPER_NOGUI)
|
||||
target_compile_definitions(slic3r_app_console PRIVATE -DSLIC3R_WRAPPER_CONSOLE)
|
||||
add_dependencies(slic3r_app_console slic3r)
|
||||
set_target_properties(slic3r_app_console PROPERTIES OUTPUT_NAME "slic3r-console")
|
||||
|
||||
add_executable(slic3r_app_noconsole WIN32 slic3r_app_msvc.cpp ${CMAKE_CURRENT_BINARY_DIR}/slic3r.rc)
|
||||
target_compile_definitions(slic3r_app_noconsole PRIVATE -DSLIC3R_WRAPPER_NOCONSOLE -DSLIC3R_WRAPPER_NOGUI)
|
||||
add_dependencies(slic3r_app_noconsole slic3r)
|
||||
set_target_properties(slic3r_app_noconsole PROPERTIES OUTPUT_NAME "slic3r-noconsole")
|
||||
# add_executable(slic3r_test slic3r.cpp ${CMAKE_CURRENT_BINARY_DIR}/slic3r.rc)
|
||||
# target_compile_definitions(slic3r_test PRIVATE -DSLIC3R_WRAPPER_CONSOLE)
|
||||
# add_dependencies(slic3r_test slic3r)
|
||||
# set_target_properties(slic3r_test PROPERTIES OUTPUT_NAME "slic3r-test")
|
||||
endif ()
|
||||
|
||||
# Link the resources dir to where Slic3r GUI expects it
|
||||
@ -213,7 +215,7 @@ if (WIN32)
|
||||
if (MSVC)
|
||||
install(TARGETS slic3r_app_gui RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}")
|
||||
install(TARGETS slic3r_app_console RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}")
|
||||
install(TARGETS slic3r_app_noconsole RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}")
|
||||
# install(TARGETS slic3r_test RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}")
|
||||
endif ()
|
||||
else ()
|
||||
install(TARGETS slic3r RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
|
||||
|
@ -293,8 +293,8 @@ static int stl_load_edge_nearby(stl_file *stl, stl_hash_edge *edge, stl_vertex *
|
||||
{
|
||||
// Index of a grid cell spaced by tolerance.
|
||||
typedef Eigen::Matrix<int32_t, 3, 1, Eigen::DontAlign> Vec3i;
|
||||
Vec3i vertex1 = (*a / tolerance).cast<int32_t>();
|
||||
Vec3i vertex2 = (*b / tolerance).cast<int32_t>();
|
||||
Vec3i vertex1 = ((*a - stl->stats.min) / tolerance).cast<int32_t>();
|
||||
Vec3i vertex2 = ((*b - stl->stats.min) / tolerance).cast<int32_t>();
|
||||
static_assert(sizeof(Vec3i) == 12, "size of Vec3i incorrect");
|
||||
|
||||
if (vertex1 == vertex2)
|
||||
|
@ -143,7 +143,7 @@ stl_generate_shared_vertices(stl_file *stl) {
|
||||
}
|
||||
|
||||
void
|
||||
stl_write_off(stl_file *stl, char *file) {
|
||||
stl_write_off(stl_file *stl, const char *file) {
|
||||
int i;
|
||||
FILE *fp;
|
||||
char *error_msg;
|
||||
@ -179,7 +179,7 @@ stl_write_off(stl_file *stl, char *file) {
|
||||
}
|
||||
|
||||
void
|
||||
stl_write_vrml(stl_file *stl, char *file) {
|
||||
stl_write_vrml(stl_file *stl, const char *file) {
|
||||
int i;
|
||||
FILE *fp;
|
||||
char *error_msg;
|
||||
@ -236,7 +236,7 @@ stl_write_vrml(stl_file *stl, char *file) {
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
void stl_write_obj (stl_file *stl, char *file) {
|
||||
void stl_write_obj (stl_file *stl, const char *file) {
|
||||
int i;
|
||||
FILE* fp;
|
||||
|
||||
|
@ -177,10 +177,10 @@ extern void stl_transform(stl_file *stl, const Eigen::Transform<double, 3, Eigen
|
||||
extern void stl_open_merge(stl_file *stl, char *file);
|
||||
extern void stl_invalidate_shared_vertices(stl_file *stl);
|
||||
extern void stl_generate_shared_vertices(stl_file *stl);
|
||||
extern void stl_write_obj(stl_file *stl, char *file);
|
||||
extern void stl_write_off(stl_file *stl, char *file);
|
||||
extern void stl_write_dxf(stl_file *stl, char *file, char *label);
|
||||
extern void stl_write_vrml(stl_file *stl, char *file);
|
||||
extern void stl_write_obj(stl_file *stl, const char *file);
|
||||
extern void stl_write_off(stl_file *stl, const char *file);
|
||||
extern void stl_write_dxf(stl_file *stl, const char *file, char *label);
|
||||
extern void stl_write_vrml(stl_file *stl, const char *file);
|
||||
inline void stl_calculate_normal(stl_normal &normal, stl_facet *facet) {
|
||||
normal = (facet->vertex[1] - facet->vertex[0]).cross(facet->vertex[2] - facet->vertex[0]);
|
||||
}
|
||||
|
@ -365,7 +365,7 @@ stl_write_quad_object(stl_file *stl, char *file) {
|
||||
}
|
||||
|
||||
void
|
||||
stl_write_dxf(stl_file *stl, char *file, char *label) {
|
||||
stl_write_dxf(stl_file *stl, const char *file, char *label) {
|
||||
int i;
|
||||
FILE *fp;
|
||||
char *error_msg;
|
||||
|
@ -14,6 +14,8 @@ public:
|
||||
localmethod_ = m;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline void seed(unsigned long val) { nlopt::srand(val); }
|
||||
};
|
||||
|
||||
template<>
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <assert.h>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <exception> // std::runtime_error
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/algorithm/string/classification.hpp>
|
||||
@ -14,6 +15,7 @@
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/nowide/cenv.hpp>
|
||||
#include <boost/nowide/iostream.hpp>
|
||||
#include <boost/nowide/fstream.hpp>
|
||||
#include <boost/property_tree/ini_parser.hpp>
|
||||
#include <boost/format.hpp>
|
||||
@ -190,6 +192,123 @@ bool unescape_strings_cstyle(const std::string &str, std::vector<std::string> &o
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> ConfigOptionDef::cli_args(const std::string &key) const
|
||||
{
|
||||
std::vector<std::string> args;
|
||||
if (this->cli != ConfigOptionDef::nocli) {
|
||||
std::string cli = this->cli.substr(0, this->cli.find("="));
|
||||
boost::trim_right_if(cli, boost::is_any_of("!"));
|
||||
if (cli.empty()) {
|
||||
// Add the key
|
||||
std::string opt = key;
|
||||
boost::replace_all(opt, "_", "-");
|
||||
args.emplace_back(std::move(opt));
|
||||
} else
|
||||
boost::split(args, cli, boost::is_any_of("|"));
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
std::string ConfigOptionDef::nocli = "~~~noCLI";
|
||||
|
||||
std::ostream& ConfigDef::print_cli_help(std::ostream& out, bool show_defaults, std::function<bool(const ConfigOptionDef &)> filter) const
|
||||
{
|
||||
// prepare a function for wrapping text
|
||||
auto wrap = [](std::string text, size_t line_length) -> std::string {
|
||||
std::istringstream words(text);
|
||||
std::ostringstream wrapped;
|
||||
std::string word;
|
||||
|
||||
if (words >> word) {
|
||||
wrapped << word;
|
||||
size_t space_left = line_length - word.length();
|
||||
while (words >> word) {
|
||||
if (space_left < word.length() + 1) {
|
||||
wrapped << '\n' << word;
|
||||
space_left = line_length - word.length();
|
||||
} else {
|
||||
wrapped << ' ' << word;
|
||||
space_left -= word.length() + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return wrapped.str();
|
||||
};
|
||||
|
||||
// get the unique categories
|
||||
std::set<std::string> categories;
|
||||
for (const auto& opt : this->options) {
|
||||
const ConfigOptionDef& def = opt.second;
|
||||
if (filter(def))
|
||||
categories.insert(def.category);
|
||||
}
|
||||
|
||||
for (auto category : categories) {
|
||||
if (category != "") {
|
||||
out << category << ":" << std::endl;
|
||||
} else if (categories.size() > 1) {
|
||||
out << "Misc options:" << std::endl;
|
||||
}
|
||||
|
||||
for (const auto& opt : this->options) {
|
||||
const ConfigOptionDef& def = opt.second;
|
||||
if (def.category != category || def.cli == ConfigOptionDef::nocli || !filter(def))
|
||||
continue;
|
||||
|
||||
// get all possible variations: --foo, --foobar, -f...
|
||||
std::vector<std::string> cli_args = def.cli_args(opt.first);
|
||||
if (cli_args.empty())
|
||||
continue;
|
||||
|
||||
for (auto& arg : cli_args) {
|
||||
arg.insert(0, (arg.size() == 1) ? "-" : "--");
|
||||
if (def.type == coFloat || def.type == coInt || def.type == coFloatOrPercent
|
||||
|| def.type == coFloats || def.type == coInts) {
|
||||
arg += " N";
|
||||
} else if (def.type == coPoint) {
|
||||
arg += " X,Y";
|
||||
} else if (def.type == coPoint3) {
|
||||
arg += " X,Y,Z";
|
||||
} else if (def.type == coString || def.type == coStrings) {
|
||||
arg += " ABCD";
|
||||
}
|
||||
}
|
||||
|
||||
// left: command line options
|
||||
const std::string cli = boost::algorithm::join(cli_args, ", ");
|
||||
out << " " << std::left << std::setw(20) << cli;
|
||||
|
||||
// right: option description
|
||||
std::string descr = def.tooltip;
|
||||
if (show_defaults && def.default_value != nullptr && def.type != coBool
|
||||
&& (def.type != coString || !def.default_value->serialize().empty())) {
|
||||
descr += " (";
|
||||
if (!def.sidetext.empty()) {
|
||||
descr += def.sidetext + ", ";
|
||||
} else if (!def.enum_values.empty()) {
|
||||
descr += boost::algorithm::join(def.enum_values, ", ") + "; ";
|
||||
}
|
||||
descr += "default: " + def.default_value->serialize() + ")";
|
||||
}
|
||||
|
||||
// wrap lines of description
|
||||
descr = wrap(descr, 80);
|
||||
std::vector<std::string> lines;
|
||||
boost::split(lines, descr, boost::is_any_of("\n"));
|
||||
|
||||
// if command line options are too long, print description in new line
|
||||
for (size_t i = 0; i < lines.size(); ++i) {
|
||||
if (i == 0 && cli.size() > 19)
|
||||
out << std::endl;
|
||||
if (i > 0 || cli.size() > 19)
|
||||
out << std::string(21, ' ');
|
||||
out << lines[i] << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
void ConfigBase::apply_only(const ConfigBase &other, const t_config_option_keys &keys, bool ignore_nonexistent)
|
||||
{
|
||||
// loop through options and apply them
|
||||
@ -522,50 +641,53 @@ ConfigOption* DynamicConfig::optptr(const t_config_option_key &opt_key, bool cre
|
||||
// Let the parent decide what to do if the opt_key is not defined by this->def().
|
||||
return nullptr;
|
||||
ConfigOption *opt = nullptr;
|
||||
switch (optdef->type) {
|
||||
case coFloat: opt = new ConfigOptionFloat(); break;
|
||||
case coFloats: opt = new ConfigOptionFloats(); break;
|
||||
case coInt: opt = new ConfigOptionInt(); break;
|
||||
case coInts: opt = new ConfigOptionInts(); break;
|
||||
case coString: opt = new ConfigOptionString(); break;
|
||||
case coStrings: opt = new ConfigOptionStrings(); break;
|
||||
case coPercent: opt = new ConfigOptionPercent(); break;
|
||||
case coPercents: opt = new ConfigOptionPercents(); break;
|
||||
case coFloatOrPercent: opt = new ConfigOptionFloatOrPercent(); break;
|
||||
case coPoint: opt = new ConfigOptionPoint(); break;
|
||||
case coPoints: opt = new ConfigOptionPoints(); break;
|
||||
case coBool: opt = new ConfigOptionBool(); break;
|
||||
case coBools: opt = new ConfigOptionBools(); break;
|
||||
case coEnum: opt = new ConfigOptionEnumGeneric(optdef->enum_keys_map); break;
|
||||
default: throw std::runtime_error(std::string("Unknown option type for option ") + opt_key);
|
||||
if (optdef->default_value != nullptr) {
|
||||
opt = (optdef->default_value->type() == coEnum) ?
|
||||
// Special case: For a DynamicConfig, convert a templated enum to a generic enum.
|
||||
new ConfigOptionEnumGeneric(optdef->enum_keys_map, optdef->default_value->getInt()) :
|
||||
optdef->default_value->clone();
|
||||
} else {
|
||||
switch (optdef->type) {
|
||||
case coFloat: opt = new ConfigOptionFloat(); break;
|
||||
case coFloats: opt = new ConfigOptionFloats(); break;
|
||||
case coInt: opt = new ConfigOptionInt(); break;
|
||||
case coInts: opt = new ConfigOptionInts(); break;
|
||||
case coString: opt = new ConfigOptionString(); break;
|
||||
case coStrings: opt = new ConfigOptionStrings(); break;
|
||||
case coPercent: opt = new ConfigOptionPercent(); break;
|
||||
case coPercents: opt = new ConfigOptionPercents(); break;
|
||||
case coFloatOrPercent: opt = new ConfigOptionFloatOrPercent(); break;
|
||||
case coPoint: opt = new ConfigOptionPoint(); break;
|
||||
case coPoints: opt = new ConfigOptionPoints(); break;
|
||||
case coPoint3: opt = new ConfigOptionPoint3(); break;
|
||||
// case coPoint3s: opt = new ConfigOptionPoint3s(); break;
|
||||
case coBool: opt = new ConfigOptionBool(); break;
|
||||
case coBools: opt = new ConfigOptionBools(); break;
|
||||
case coEnum: opt = new ConfigOptionEnumGeneric(optdef->enum_keys_map); break;
|
||||
default: throw std::runtime_error(std::string("Unknown option type for option ") + opt_key);
|
||||
}
|
||||
}
|
||||
this->options[opt_key] = opt;
|
||||
return opt;
|
||||
}
|
||||
|
||||
void DynamicConfig::read_cli(const std::vector<std::string> &tokens, t_config_option_keys* extra)
|
||||
void DynamicConfig::read_cli(const std::vector<std::string> &tokens, t_config_option_keys* extra, t_config_option_keys* keys)
|
||||
{
|
||||
std::vector<char*> args;
|
||||
// push a bogus executable name (argv[0])
|
||||
args.emplace_back(const_cast<char*>(""));
|
||||
for (size_t i = 0; i < tokens.size(); ++ i)
|
||||
args.emplace_back(const_cast<char *>(tokens[i].c_str()));
|
||||
this->read_cli(int(args.size()), &args[0], extra);
|
||||
this->read_cli(int(args.size()), &args[0], extra, keys);
|
||||
}
|
||||
|
||||
bool DynamicConfig::read_cli(int argc, char** argv, t_config_option_keys* extra)
|
||||
bool DynamicConfig::read_cli(int argc, char** argv, t_config_option_keys* extra, t_config_option_keys* keys)
|
||||
{
|
||||
// cache the CLI option => opt_key mapping
|
||||
std::map<std::string,std::string> opts;
|
||||
for (const auto &oit : this->def()->options) {
|
||||
std::string cli = oit.second.cli;
|
||||
cli = cli.substr(0, cli.find("="));
|
||||
boost::trim_right_if(cli, boost::is_any_of("!"));
|
||||
std::vector<std::string> tokens;
|
||||
boost::split(tokens, cli, boost::is_any_of("|"));
|
||||
for (const std::string &t : tokens)
|
||||
for (const auto &oit : this->def()->options)
|
||||
for (auto t : oit.second.cli_args(oit.first))
|
||||
opts[t] = oit.first;
|
||||
}
|
||||
|
||||
bool parse_options = true;
|
||||
for (int i = 1; i < argc; ++ i) {
|
||||
@ -606,11 +728,8 @@ bool DynamicConfig::read_cli(int argc, char** argv, t_config_option_keys* extra)
|
||||
// Look for the cli -> option mapping.
|
||||
const auto it = opts.find(token);
|
||||
if (it == opts.end()) {
|
||||
printf("Warning: unknown option --%s\n", token.c_str());
|
||||
// instead of continuing, return false to caller
|
||||
// to stop execution and print usage
|
||||
return false;
|
||||
//continue;
|
||||
boost::nowide::cerr << "Unknown option --" << token.c_str() << std::endl;
|
||||
return false;
|
||||
}
|
||||
const t_config_option_key opt_key = it->second;
|
||||
const ConfigOptionDef &optdef = this->def()->options.at(opt_key);
|
||||
@ -618,13 +737,17 @@ bool DynamicConfig::read_cli(int argc, char** argv, t_config_option_keys* extra)
|
||||
// look for it in the next token.
|
||||
if (optdef.type != coBool && optdef.type != coBools && value.empty()) {
|
||||
if (i == (argc-1)) {
|
||||
printf("No value supplied for --%s\n", token.c_str());
|
||||
continue;
|
||||
boost::nowide::cerr << "No value supplied for --" << token.c_str() << std::endl;
|
||||
return false;
|
||||
}
|
||||
value = argv[++ i];
|
||||
}
|
||||
// Store the option value.
|
||||
const bool existing = this->has(opt_key);
|
||||
if (keys != nullptr && !existing) {
|
||||
// Save the order of detected keys.
|
||||
keys->push_back(opt_key);
|
||||
}
|
||||
ConfigOption *opt_base = this->option(opt_key, true);
|
||||
ConfigOptionVectorBase *opt_vector = opt_base->is_vector() ? static_cast<ConfigOptionVectorBase*>(opt_base) : nullptr;
|
||||
if (opt_vector) {
|
||||
@ -648,7 +771,10 @@ bool DynamicConfig::read_cli(int argc, char** argv, t_config_option_keys* extra)
|
||||
static_cast<ConfigOptionString*>(opt_base)->value = value;
|
||||
} else {
|
||||
// Any scalar value of a type different from Bool and String.
|
||||
this->set_deserialize(opt_key, value, false);
|
||||
if (! this->set_deserialize(opt_key, value, false)) {
|
||||
boost::nowide::cerr << "Invalid value supplied for --" << token.c_str() << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <climits>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
@ -27,6 +28,24 @@ extern std::string escape_strings_cstyle(const std::vector<std::string> &strs);
|
||||
extern bool unescape_string_cstyle(const std::string &str, std::string &out);
|
||||
extern bool unescape_strings_cstyle(const std::string &str, std::vector<std::string> &out);
|
||||
|
||||
/// Specialization of std::exception to indicate that an unknown config option has been encountered.
|
||||
class UnknownOptionException : public std::runtime_error {
|
||||
public:
|
||||
UnknownOptionException() :
|
||||
std::runtime_error("Unknown option exception") {}
|
||||
UnknownOptionException(const std::string &opt_key) :
|
||||
std::runtime_error(std::string("Unknown option exception: ") + opt_key) {}
|
||||
};
|
||||
|
||||
/// Indicate that the ConfigBase derived class does not provide config definition (the method def() returns null).
|
||||
class NoDefinitionException : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
NoDefinitionException() :
|
||||
std::runtime_error("No definition exception") {}
|
||||
NoDefinitionException(const std::string &opt_key) :
|
||||
std::runtime_error(std::string("No definition exception: ") + opt_key) {}
|
||||
};
|
||||
|
||||
// Type of a configuration value.
|
||||
enum ConfigOptionType {
|
||||
@ -54,12 +73,14 @@ enum ConfigOptionType {
|
||||
coPoint = 6,
|
||||
// vector of 2d points (Point2f). Currently used for the definition of the print bed and for the extruder offsets.
|
||||
coPoints = coPoint + coVectorType,
|
||||
coPoint3 = 7,
|
||||
// coPoint3s = coPoint3 + coVectorType,
|
||||
// single boolean value
|
||||
coBool = 7,
|
||||
coBool = 8,
|
||||
// vector of boolean values
|
||||
coBools = coBool + coVectorType,
|
||||
// a generic enum
|
||||
coEnum = 8,
|
||||
coEnum = 9,
|
||||
};
|
||||
|
||||
enum ConfigOptionMode {
|
||||
@ -68,6 +89,30 @@ enum ConfigOptionMode {
|
||||
comExpert
|
||||
};
|
||||
|
||||
enum PrinterTechnology : uint8_t
|
||||
{
|
||||
// Fused Filament Fabrication
|
||||
ptFFF = 1 << 0,
|
||||
// Stereolitography
|
||||
ptSLA = 1 << 1,
|
||||
// Selective Laser-Sintering
|
||||
ptSLS = 1 << 2,
|
||||
// Unknown, useful for command line processing
|
||||
ptUnknown = 1 << 7
|
||||
};
|
||||
inline PrinterTechnology operator|(PrinterTechnology a, PrinterTechnology b) {
|
||||
return static_cast<PrinterTechnology>(static_cast<uint8_t>(a) | static_cast<uint8_t>(b));
|
||||
}
|
||||
inline PrinterTechnology operator&(PrinterTechnology a, PrinterTechnology b) {
|
||||
return static_cast<PrinterTechnology>(static_cast<uint8_t>(a)& static_cast<uint8_t>(b));
|
||||
}
|
||||
inline PrinterTechnology operator|=(PrinterTechnology& a, PrinterTechnology b) {
|
||||
a = a | b; return a;
|
||||
}
|
||||
inline PrinterTechnology operator&=(PrinterTechnology& a, PrinterTechnology b) {
|
||||
a = a & b; return a;
|
||||
}
|
||||
|
||||
// A generic value of a configuration option.
|
||||
class ConfigOption {
|
||||
public:
|
||||
@ -718,6 +763,39 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class ConfigOptionPoint3 : public ConfigOptionSingle<Vec3d>
|
||||
{
|
||||
public:
|
||||
ConfigOptionPoint3() : ConfigOptionSingle<Vec3d>(Vec3d(0,0,0)) {}
|
||||
explicit ConfigOptionPoint3(const Vec3d &value) : ConfigOptionSingle<Vec3d>(value) {}
|
||||
|
||||
static ConfigOptionType static_type() { return coPoint3; }
|
||||
ConfigOptionType type() const override { return static_type(); }
|
||||
ConfigOption* clone() const override { return new ConfigOptionPoint3(*this); }
|
||||
ConfigOptionPoint3& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
|
||||
bool operator==(const ConfigOptionPoint3 &rhs) const { return this->value == rhs.value; }
|
||||
|
||||
std::string serialize() const override
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << this->value(0);
|
||||
ss << ",";
|
||||
ss << this->value(1);
|
||||
ss << ",";
|
||||
ss << this->value(2);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
bool deserialize(const std::string &str, bool append = false) override
|
||||
{
|
||||
UNUSED(append);
|
||||
char dummy;
|
||||
return sscanf(str.data(), " %lf , %lf , %lf %c", &this->value(0), &this->value(1), &this->value(2), &dummy) == 2 ||
|
||||
sscanf(str.data(), " %lf x %lf x %lf %c", &this->value(0), &this->value(1), &this->value(2), &dummy) == 2;
|
||||
}
|
||||
};
|
||||
|
||||
class ConfigOptionBool : public ConfigOptionSingle<bool>
|
||||
{
|
||||
public:
|
||||
@ -893,6 +971,7 @@ class ConfigOptionEnumGeneric : public ConfigOptionInt
|
||||
{
|
||||
public:
|
||||
ConfigOptionEnumGeneric(const t_config_enum_values* keys_map = nullptr) : keys_map(keys_map) {}
|
||||
explicit ConfigOptionEnumGeneric(const t_config_enum_values* keys_map, int value) : ConfigOptionInt(value), keys_map(keys_map) {}
|
||||
|
||||
const t_config_enum_values* keys_map;
|
||||
|
||||
@ -960,6 +1039,8 @@ public:
|
||||
// The full label is shown, when adding an override parameter for an object or a modified object.
|
||||
std::string label;
|
||||
std::string full_label;
|
||||
// With which printer technology is this configuration valid?
|
||||
PrinterTechnology printer_technology = ptUnknown;
|
||||
// Category of a configuration field, from the GUI perspective.
|
||||
// One of: "Layers and Perimeters", "Infill", "Support material", "Speed", "Extruders", "Advanced", "Extrusion Width"
|
||||
std::string category;
|
||||
@ -1010,6 +1091,13 @@ public:
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Returns the alternative CLI arguments for the given option.
|
||||
// If there are no cli arguments defined, use the key and replace underscores with dashes.
|
||||
std::vector<std::string> cli_args(const std::string &key) const;
|
||||
|
||||
// Assign this key to cli to disable CLI for this option.
|
||||
static std::string nocli;
|
||||
};
|
||||
|
||||
// Map from a config option name to its definition.
|
||||
@ -1044,6 +1132,11 @@ public:
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Iterate through all of the CLI options and write them to a stream.
|
||||
std::ostream& print_cli_help(
|
||||
std::ostream& out, bool show_defaults,
|
||||
std::function<bool(const ConfigOptionDef &)> filter = [](const ConfigOptionDef &){ return true; }) const;
|
||||
|
||||
protected:
|
||||
ConfigOptionDef* add(const t_config_option_key &opt_key, ConfigOptionType type) {
|
||||
ConfigOptionDef* opt = &this->options[opt_key];
|
||||
@ -1089,12 +1182,24 @@ public:
|
||||
TYPE* option(const t_config_option_key &opt_key, bool create = false)
|
||||
{
|
||||
ConfigOption *opt = this->optptr(opt_key, create);
|
||||
// assert(opt == nullptr || opt->type() == TYPE::static_type());
|
||||
return (opt == nullptr || opt->type() != TYPE::static_type()) ? nullptr : static_cast<TYPE*>(opt);
|
||||
}
|
||||
template<typename TYPE>
|
||||
const TYPE* option(const t_config_option_key &opt_key) const
|
||||
{ return const_cast<ConfigBase*>(this)->option<TYPE>(opt_key, false); }
|
||||
template<typename TYPE>
|
||||
TYPE* option_throw(const t_config_option_key &opt_key, bool create = false)
|
||||
{
|
||||
ConfigOption *opt = this->optptr(opt_key, create);
|
||||
if (opt == nullptr)
|
||||
throw UnknownOptionException(opt_key);
|
||||
if (opt->type() != TYPE::static_type())
|
||||
throw std::runtime_error("Conversion to a wrong type");
|
||||
return static_cast<TYPE*>(opt);
|
||||
}
|
||||
template<typename TYPE>
|
||||
const TYPE* option_throw(const t_config_option_key &opt_key) const
|
||||
{ return const_cast<ConfigBase*>(this)->option_throw<TYPE>(opt_key, false); }
|
||||
// Apply all keys of other ConfigBase defined by this->def() to this ConfigBase.
|
||||
// An UnknownOptionException is thrown in case some option keys of other are not defined by this->def(),
|
||||
// or this ConfigBase is of a StaticConfig type and it does not support some of the keys, and ignore_nonexistent is not set.
|
||||
@ -1276,8 +1381,8 @@ public:
|
||||
bool opt_bool(const t_config_option_key &opt_key, unsigned int idx) const { return this->option<ConfigOptionBools>(opt_key)->get_at(idx) != 0; }
|
||||
|
||||
// Command line processing
|
||||
void read_cli(const std::vector<std::string> &tokens, t_config_option_keys* extra);
|
||||
bool read_cli(int argc, char** argv, t_config_option_keys* extra);
|
||||
void read_cli(const std::vector<std::string> &tokens, t_config_option_keys* extra, t_config_option_keys* keys = nullptr);
|
||||
bool read_cli(int argc, char** argv, t_config_option_keys* extra, t_config_option_keys* keys = nullptr);
|
||||
|
||||
typedef std::map<t_config_option_key,ConfigOption*> t_options_map;
|
||||
t_options_map::const_iterator cbegin() const { return options.cbegin(); }
|
||||
@ -1303,25 +1408,6 @@ protected:
|
||||
void set_defaults();
|
||||
};
|
||||
|
||||
/// Specialization of std::exception to indicate that an unknown config option has been encountered.
|
||||
class UnknownOptionException : public std::runtime_error {
|
||||
public:
|
||||
UnknownOptionException() :
|
||||
std::runtime_error("Unknown option exception") {}
|
||||
UnknownOptionException(const std::string &opt_key) :
|
||||
std::runtime_error(std::string("Unknown option exception: ") + opt_key) {}
|
||||
};
|
||||
|
||||
/// Indicate that the ConfigBase derived class does not provide config definition (the method def() returns null).
|
||||
class NoDefinitionException : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
NoDefinitionException() :
|
||||
std::runtime_error("No definition exception") {}
|
||||
NoDefinitionException(const std::string &opt_key) :
|
||||
std::runtime_error(std::string("No definition exception: ") + opt_key) {}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -15,7 +15,7 @@ void FillPlanePath::_fill_surface_single(
|
||||
{
|
||||
expolygon.rotate(- direction.first);
|
||||
|
||||
coord_t distance_between_lines = scale_(this->spacing) / params.density;
|
||||
coord_t distance_between_lines = coord_t(scale_(this->spacing) / params.density);
|
||||
|
||||
// align infill across layers using the object's bounding box
|
||||
// Rotated bounding box of the whole object.
|
||||
@ -89,7 +89,8 @@ Pointfs FillArchimedeanChords::_generate(coord_t min_x, coord_t min_y, coord_t m
|
||||
out.push_back(Vec2d(0, 0));
|
||||
out.push_back(Vec2d(1, 0));
|
||||
while (r < rmax) {
|
||||
theta += 1. / r;
|
||||
// Discretization angle to achieve a discretization error lower than RESOLUTION.
|
||||
theta += 2. * acos(1. - RESOLUTION / r);
|
||||
r = a + b * theta;
|
||||
out.push_back(Vec2d(r * cos(theta), r * sin(theta)));
|
||||
}
|
||||
|
@ -42,14 +42,20 @@ public:
|
||||
bool bridge;
|
||||
|
||||
Flow(float _w, float _h, float _nd, bool _bridge = false) :
|
||||
width(_w), height(_h), nozzle_diameter(_nd), bridge(_bridge) {};
|
||||
width(_w), height(_h), nozzle_diameter(_nd), bridge(_bridge) {}
|
||||
|
||||
float spacing() const;
|
||||
float spacing(const Flow &other) const;
|
||||
double mm3_per_mm() const;
|
||||
coord_t scaled_width() const { return coord_t(scale_(this->width)); };
|
||||
coord_t scaled_spacing() const { return coord_t(scale_(this->spacing())); };
|
||||
coord_t scaled_spacing(const Flow &other) const { return coord_t(scale_(this->spacing(other))); };
|
||||
coord_t scaled_width() const { return coord_t(scale_(this->width)); }
|
||||
coord_t scaled_spacing() const { return coord_t(scale_(this->spacing())); }
|
||||
coord_t scaled_spacing(const Flow &other) const { return coord_t(scale_(this->spacing(other))); }
|
||||
|
||||
// Elephant foot compensation spacing to be used to detect narrow parts, where the elephant foot compensation cannot be applied.
|
||||
// To be used on frExternalPerimeter only.
|
||||
// Enable some perimeter squish (see INSET_OVERLAP_TOLERANCE).
|
||||
// Here an overlap of 0.2x external perimeter spacing is allowed for by the elephant foot compensation.
|
||||
coord_t scaled_elephant_foot_spacing() const { return coord_t(0.5f * float(this->scaled_width() + 0.6f * this->scaled_spacing())); }
|
||||
|
||||
static Flow new_from_config_width(FlowRole role, const ConfigOptionFloatOrPercent &width, float nozzle_diameter, float height, float bridge_flow_ratio);
|
||||
// Create a flow from the spacing of extrusion lines.
|
||||
|
@ -587,8 +587,10 @@ namespace Slic3r {
|
||||
object.second->layer_height_profile = obj_layer_heights_profile->second;
|
||||
|
||||
IdToSlaSupportPointsMap::iterator obj_sla_support_points = m_sla_support_points.find(object.first);
|
||||
if (obj_sla_support_points != m_sla_support_points.end() && !obj_sla_support_points->second.empty())
|
||||
if (obj_sla_support_points != m_sla_support_points.end() && !obj_sla_support_points->second.empty()) {
|
||||
object.second->sla_support_points = obj_sla_support_points->second;
|
||||
object.second->sla_points_status = sla::PointsStatus::UserModified;
|
||||
}
|
||||
|
||||
IdToMetadataMap::iterator obj_metadata = m_objects_metadata.find(object.first);
|
||||
if (obj_metadata != m_objects_metadata.end())
|
||||
|
@ -175,6 +175,11 @@ struct AMFParserContext
|
||||
bool mirrory_set;
|
||||
float mirrorz;
|
||||
bool mirrorz_set;
|
||||
|
||||
bool anything_set() const { return deltax_set || deltay_set || deltaz_set ||
|
||||
rx_set || ry_set || rz_set ||
|
||||
scalex_set || scaley_set || scalez_set ||
|
||||
mirrorx_set || mirrory_set || mirrorz_set; }
|
||||
};
|
||||
|
||||
struct Object {
|
||||
@ -600,6 +605,7 @@ void AMFParserContext::endElement(const char * /* name */)
|
||||
break;
|
||||
p = end + 1;
|
||||
}
|
||||
m_object->sla_points_status = sla::PointsStatus::UserModified;
|
||||
}
|
||||
else if (m_path.size() == 5 && m_path[3] == NODE_TYPE_VOLUME && m_volume) {
|
||||
if (strcmp(opt_key, "modifier") == 0) {
|
||||
@ -643,11 +649,7 @@ void AMFParserContext::endDocument()
|
||||
continue;
|
||||
}
|
||||
for (const Instance &instance : object.second.instances)
|
||||
#if ENABLE_VOLUMES_CENTERING_FIXES
|
||||
{
|
||||
#else
|
||||
if (instance.deltax_set && instance.deltay_set) {
|
||||
#endif // ENABLE_VOLUMES_CENTERING_FIXES
|
||||
if (instance.anything_set()) {
|
||||
ModelInstance *mi = m_model.objects[object.second.idx]->add_instance();
|
||||
mi->set_offset(Vec3d(instance.deltax_set ? (double)instance.deltax : 0.0, instance.deltay_set ? (double)instance.deltay : 0.0, instance.deltaz_set ? (double)instance.deltaz : 0.0));
|
||||
mi->set_rotation(Vec3d(instance.rx_set ? (double)instance.rx : 0.0, instance.ry_set ? (double)instance.ry : 0.0, instance.rz_set ? (double)instance.rz : 0.0));
|
||||
|
@ -115,4 +115,23 @@ bool load_obj(const char *path, Model *model, const char *object_name_in)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool store_obj(const char *path, TriangleMesh *mesh)
|
||||
{
|
||||
//FIXME returning false even if write failed.
|
||||
mesh->WriteOBJFile(path);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool store_obj(const char *path, ModelObject *model_object)
|
||||
{
|
||||
TriangleMesh mesh = model_object->mesh();
|
||||
return store_obj(path, &mesh);
|
||||
}
|
||||
|
||||
bool store_obj(const char *path, Model *model)
|
||||
{
|
||||
TriangleMesh mesh = model->mesh();
|
||||
return store_obj(path, &mesh);
|
||||
}
|
||||
|
||||
}; // namespace Slic3r
|
||||
|
@ -9,6 +9,10 @@ class Model;
|
||||
// Load an OBJ file into a provided model.
|
||||
extern bool load_obj(const char *path, Model *model, const char *object_name = nullptr);
|
||||
|
||||
extern bool store_obj(const char *path, TriangleMesh *mesh);
|
||||
extern bool store_obj(const char *path, ModelObject *model);
|
||||
extern bool store_obj(const char *path, Model *model);
|
||||
|
||||
}; // namespace Slic3r
|
||||
|
||||
#endif /* slic3r_Format_OBJ_hpp_ */
|
||||
|
@ -55,4 +55,10 @@ bool store_stl(const char *path, ModelObject *model_object, bool binary)
|
||||
return store_stl(path, &mesh, binary);
|
||||
}
|
||||
|
||||
bool store_stl(const char *path, Model *model, bool binary)
|
||||
{
|
||||
TriangleMesh mesh = model->mesh();
|
||||
return store_stl(path, &mesh, binary);
|
||||
}
|
||||
|
||||
}; // namespace Slic3r
|
||||
|
@ -11,6 +11,7 @@ extern bool load_stl(const char *path, Model *model, const char *object_name = n
|
||||
|
||||
extern bool store_stl(const char *path, TriangleMesh *mesh, bool binary);
|
||||
extern bool store_stl(const char *path, ModelObject *model_object, bool binary);
|
||||
extern bool store_stl(const char *path, Model *model, bool binary);
|
||||
|
||||
}; // namespace Slic3r
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
#include "libslic3r.h"
|
||||
#include "GCode.hpp"
|
||||
#include "ExtrusionEntity.hpp"
|
||||
#include "EdgeGrid.hpp"
|
||||
@ -486,7 +487,7 @@ void GCode::do_export(Print *print, const char *path, GCodePreviewData *preview_
|
||||
// starts analyzer calculations
|
||||
if (m_enable_analyzer) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "Preparing G-code preview data";
|
||||
m_analyzer.calc_gcode_preview_data(*preview_data);
|
||||
m_analyzer.calc_gcode_preview_data(*preview_data, [print]() { print->throw_if_canceled(); });
|
||||
m_analyzer.reset();
|
||||
}
|
||||
|
||||
@ -574,6 +575,16 @@ void GCode::_do_export(Print &print, FILE *file)
|
||||
// resets analyzer
|
||||
m_analyzer.reset();
|
||||
|
||||
// send extruder offset data to analyzer
|
||||
GCodeAnalyzer::ExtruderOffsetsMap extruder_offsets;
|
||||
for (unsigned int extruder_id : print.extruders())
|
||||
{
|
||||
Vec2d offset = print.config().extruder_offset.get_at(extruder_id);
|
||||
if (!offset.isApprox(Vec2d::Zero()))
|
||||
extruder_offsets[extruder_id] = offset;
|
||||
}
|
||||
m_analyzer.set_extruder_offsets(extruder_offsets);
|
||||
|
||||
// resets analyzer's tracking data
|
||||
m_last_mm3_per_mm = GCodeAnalyzer::Default_mm3_per_mm;
|
||||
m_last_width = GCodeAnalyzer::Default_Width;
|
||||
@ -860,7 +871,7 @@ void GCode::_do_export(Print &print, FILE *file)
|
||||
for (unsigned int extruder_id : print.extruders()) {
|
||||
const Vec2d &extruder_offset = print.config().extruder_offset.get_at(extruder_id);
|
||||
Polygon s(outer_skirt);
|
||||
s.translate(Point::new_scale(- extruder_offset(0), - extruder_offset(1)));
|
||||
s.translate(Point::new_scale(-extruder_offset(0), -extruder_offset(1)));
|
||||
skirts.emplace_back(std::move(s));
|
||||
}
|
||||
m_ooze_prevention.enable = true;
|
||||
|
@ -101,6 +101,11 @@ GCodeAnalyzer::GCodeAnalyzer()
|
||||
reset();
|
||||
}
|
||||
|
||||
void GCodeAnalyzer::set_extruder_offsets(const GCodeAnalyzer::ExtruderOffsetsMap& extruder_offsets)
|
||||
{
|
||||
m_extruder_offsets = extruder_offsets;
|
||||
}
|
||||
|
||||
void GCodeAnalyzer::reset()
|
||||
{
|
||||
_set_units(Millimeters);
|
||||
@ -118,6 +123,7 @@ void GCodeAnalyzer::reset()
|
||||
_reset_axes_position();
|
||||
|
||||
m_moves_map.clear();
|
||||
m_extruder_offsets.clear();
|
||||
}
|
||||
|
||||
const std::string& GCodeAnalyzer::process_gcode(const std::string& gcode)
|
||||
@ -131,22 +137,22 @@ const std::string& GCodeAnalyzer::process_gcode(const std::string& gcode)
|
||||
return m_process_output;
|
||||
}
|
||||
|
||||
void GCodeAnalyzer::calc_gcode_preview_data(GCodePreviewData& preview_data)
|
||||
void GCodeAnalyzer::calc_gcode_preview_data(GCodePreviewData& preview_data, std::function<void()> cancel_callback)
|
||||
{
|
||||
// resets preview data
|
||||
preview_data.reset();
|
||||
|
||||
// calculates extrusion layers
|
||||
_calc_gcode_preview_extrusion_layers(preview_data);
|
||||
_calc_gcode_preview_extrusion_layers(preview_data, cancel_callback);
|
||||
|
||||
// calculates travel
|
||||
_calc_gcode_preview_travel(preview_data);
|
||||
_calc_gcode_preview_travel(preview_data, cancel_callback);
|
||||
|
||||
// calculates retractions
|
||||
_calc_gcode_preview_retractions(preview_data);
|
||||
_calc_gcode_preview_retractions(preview_data, cancel_callback);
|
||||
|
||||
// calculates unretractions
|
||||
_calc_gcode_preview_unretractions(preview_data);
|
||||
_calc_gcode_preview_unretractions(preview_data, cancel_callback);
|
||||
}
|
||||
|
||||
bool GCodeAnalyzer::is_valid_extrusion_role(ExtrusionRole role)
|
||||
@ -654,7 +660,15 @@ void GCodeAnalyzer::_store_move(GCodeAnalyzer::GCodeMove::EType type)
|
||||
it = m_moves_map.insert(TypeToMovesMap::value_type(type, GCodeMovesList())).first;
|
||||
|
||||
// store move
|
||||
it->second.emplace_back(type, _get_extrusion_role(), _get_extruder_id(), _get_mm3_per_mm(), _get_width(), _get_height(), _get_feedrate(), _get_start_position(), _get_end_position(), _get_delta_extrusion(), _get_cp_color_id());
|
||||
Vec3d extruder_offset = Vec3d::Zero();
|
||||
unsigned int extruder_id = _get_extruder_id();
|
||||
ExtruderOffsetsMap::iterator extr_it = m_extruder_offsets.find(extruder_id);
|
||||
if (extr_it != m_extruder_offsets.end())
|
||||
extruder_offset = Vec3d(extr_it->second(0), extr_it->second(1), 0.0);
|
||||
|
||||
Vec3d start_position = _get_start_position() + extruder_offset;
|
||||
Vec3d end_position = _get_end_position() + extruder_offset;
|
||||
it->second.emplace_back(type, _get_extrusion_role(), extruder_id, _get_mm3_per_mm(), _get_width(), _get_height(), _get_feedrate(), start_position, end_position, _get_delta_extrusion(), _get_cp_color_id());
|
||||
}
|
||||
|
||||
bool GCodeAnalyzer::_is_valid_extrusion_role(int value) const
|
||||
@ -662,7 +676,7 @@ bool GCodeAnalyzer::_is_valid_extrusion_role(int value) const
|
||||
return ((int)erNone <= value) && (value <= (int)erMixed);
|
||||
}
|
||||
|
||||
void GCodeAnalyzer::_calc_gcode_preview_extrusion_layers(GCodePreviewData& preview_data)
|
||||
void GCodeAnalyzer::_calc_gcode_preview_extrusion_layers(GCodePreviewData& preview_data, std::function<void()> cancel_callback)
|
||||
{
|
||||
struct Helper
|
||||
{
|
||||
@ -711,9 +725,18 @@ void GCodeAnalyzer::_calc_gcode_preview_extrusion_layers(GCodePreviewData& previ
|
||||
GCodePreviewData::Range feedrate_range;
|
||||
GCodePreviewData::Range volumetric_rate_range;
|
||||
|
||||
// to avoid to call the callback too often
|
||||
unsigned int cancel_callback_threshold = (unsigned int)std::max((int)extrude_moves->second.size() / 25, 1);
|
||||
unsigned int cancel_callback_curr = 0;
|
||||
|
||||
// constructs the polylines while traversing the moves
|
||||
for (const GCodeMove& move : extrude_moves->second)
|
||||
{
|
||||
// to avoid to call the callback too often
|
||||
cancel_callback_curr = (cancel_callback_curr + 1) % cancel_callback_threshold;
|
||||
if (cancel_callback_curr == 0)
|
||||
cancel_callback();
|
||||
|
||||
if ((data != move.data) || (z != move.start_position.z()) || (position != move.start_position) || (volumetric_rate != move.data.feedrate * (float)move.data.mm3_per_mm))
|
||||
{
|
||||
// store current polyline
|
||||
@ -755,7 +778,7 @@ void GCodeAnalyzer::_calc_gcode_preview_extrusion_layers(GCodePreviewData& previ
|
||||
preview_data.ranges.volumetric_rate.update_from(volumetric_rate_range);
|
||||
}
|
||||
|
||||
void GCodeAnalyzer::_calc_gcode_preview_travel(GCodePreviewData& preview_data)
|
||||
void GCodeAnalyzer::_calc_gcode_preview_travel(GCodePreviewData& preview_data, std::function<void()> cancel_callback)
|
||||
{
|
||||
struct Helper
|
||||
{
|
||||
@ -783,9 +806,17 @@ void GCodeAnalyzer::_calc_gcode_preview_travel(GCodePreviewData& preview_data)
|
||||
GCodePreviewData::Range width_range;
|
||||
GCodePreviewData::Range feedrate_range;
|
||||
|
||||
// to avoid to call the callback too often
|
||||
unsigned int cancel_callback_threshold = (unsigned int)std::max((int)travel_moves->second.size() / 25, 1);
|
||||
unsigned int cancel_callback_curr = 0;
|
||||
|
||||
// constructs the polylines while traversing the moves
|
||||
for (const GCodeMove& move : travel_moves->second)
|
||||
{
|
||||
cancel_callback_curr = (cancel_callback_curr + 1) % cancel_callback_threshold;
|
||||
if (cancel_callback_curr == 0)
|
||||
cancel_callback();
|
||||
|
||||
GCodePreviewData::Travel::EType move_type = (move.delta_extruder < 0.0f) ? GCodePreviewData::Travel::Retract : ((move.delta_extruder > 0.0f) ? GCodePreviewData::Travel::Extrude : GCodePreviewData::Travel::Move);
|
||||
GCodePreviewData::Travel::Polyline::EDirection move_direction = ((move.start_position.x() != move.end_position.x()) || (move.start_position.y() != move.end_position.y())) ? GCodePreviewData::Travel::Polyline::Generic : GCodePreviewData::Travel::Polyline::Vertical;
|
||||
|
||||
@ -826,28 +857,44 @@ void GCodeAnalyzer::_calc_gcode_preview_travel(GCodePreviewData& preview_data)
|
||||
preview_data.ranges.feedrate.update_from(feedrate_range);
|
||||
}
|
||||
|
||||
void GCodeAnalyzer::_calc_gcode_preview_retractions(GCodePreviewData& preview_data)
|
||||
void GCodeAnalyzer::_calc_gcode_preview_retractions(GCodePreviewData& preview_data, std::function<void()> cancel_callback)
|
||||
{
|
||||
TypeToMovesMap::iterator retraction_moves = m_moves_map.find(GCodeMove::Retract);
|
||||
if (retraction_moves == m_moves_map.end())
|
||||
return;
|
||||
|
||||
// to avoid to call the callback too often
|
||||
unsigned int cancel_callback_threshold = (unsigned int)std::max((int)retraction_moves->second.size() / 25, 1);
|
||||
unsigned int cancel_callback_curr = 0;
|
||||
|
||||
for (const GCodeMove& move : retraction_moves->second)
|
||||
{
|
||||
cancel_callback_curr = (cancel_callback_curr + 1) % cancel_callback_threshold;
|
||||
if (cancel_callback_curr == 0)
|
||||
cancel_callback();
|
||||
|
||||
// store position
|
||||
Vec3crd position(scale_(move.start_position.x()), scale_(move.start_position.y()), scale_(move.start_position.z()));
|
||||
preview_data.retraction.positions.emplace_back(position, move.data.width, move.data.height);
|
||||
}
|
||||
}
|
||||
|
||||
void GCodeAnalyzer::_calc_gcode_preview_unretractions(GCodePreviewData& preview_data)
|
||||
void GCodeAnalyzer::_calc_gcode_preview_unretractions(GCodePreviewData& preview_data, std::function<void()> cancel_callback)
|
||||
{
|
||||
TypeToMovesMap::iterator unretraction_moves = m_moves_map.find(GCodeMove::Unretract);
|
||||
if (unretraction_moves == m_moves_map.end())
|
||||
return;
|
||||
|
||||
// to avoid to call the callback too often
|
||||
unsigned int cancel_callback_threshold = (unsigned int)std::max((int)unretraction_moves->second.size() / 25, 1);
|
||||
unsigned int cancel_callback_curr = 0;
|
||||
|
||||
for (const GCodeMove& move : unretraction_moves->second)
|
||||
{
|
||||
cancel_callback_curr = (cancel_callback_curr + 1) % cancel_callback_threshold;
|
||||
if (cancel_callback_curr == 0)
|
||||
cancel_callback();
|
||||
|
||||
// store position
|
||||
Vec3crd position(scale_(move.start_position.x()), scale_(move.start_position.y()), scale_(move.start_position.z()));
|
||||
preview_data.unretraction.positions.emplace_back(position, move.data.width, move.data.height);
|
||||
|
@ -87,6 +87,7 @@ public:
|
||||
|
||||
typedef std::vector<GCodeMove> GCodeMovesList;
|
||||
typedef std::map<GCodeMove::EType, GCodeMovesList> TypeToMovesMap;
|
||||
typedef std::map<unsigned int, Vec2d> ExtruderOffsetsMap;
|
||||
|
||||
private:
|
||||
struct State
|
||||
@ -105,6 +106,7 @@ private:
|
||||
State m_state;
|
||||
GCodeReader m_parser;
|
||||
TypeToMovesMap m_moves_map;
|
||||
ExtruderOffsetsMap m_extruder_offsets;
|
||||
|
||||
// The output of process_layer()
|
||||
std::string m_process_output;
|
||||
@ -112,6 +114,8 @@ private:
|
||||
public:
|
||||
GCodeAnalyzer();
|
||||
|
||||
void set_extruder_offsets(const ExtruderOffsetsMap& extruder_offsets);
|
||||
|
||||
// Reinitialize the analyzer
|
||||
void reset();
|
||||
|
||||
@ -119,7 +123,8 @@ public:
|
||||
const std::string& process_gcode(const std::string& gcode);
|
||||
|
||||
// Calculates all data needed for gcode visualization
|
||||
void calc_gcode_preview_data(GCodePreviewData& preview_data);
|
||||
// throws CanceledException through print->throw_if_canceled() (sent by the caller as callback).
|
||||
void calc_gcode_preview_data(GCodePreviewData& preview_data, std::function<void()> cancel_callback = std::function<void()>());
|
||||
|
||||
// Return an estimate of the memory consumed by the time estimator.
|
||||
size_t memory_used() const;
|
||||
@ -234,10 +239,11 @@ private:
|
||||
// Checks if the given int is a valid extrusion role (contained into enum ExtrusionRole)
|
||||
bool _is_valid_extrusion_role(int value) const;
|
||||
|
||||
void _calc_gcode_preview_extrusion_layers(GCodePreviewData& preview_data);
|
||||
void _calc_gcode_preview_travel(GCodePreviewData& preview_data);
|
||||
void _calc_gcode_preview_retractions(GCodePreviewData& preview_data);
|
||||
void _calc_gcode_preview_unretractions(GCodePreviewData& preview_data);
|
||||
// All the following methods throw CanceledException through print->throw_if_canceled() (sent by the caller as callback).
|
||||
void _calc_gcode_preview_extrusion_layers(GCodePreviewData& preview_data, std::function<void()> cancel_callback);
|
||||
void _calc_gcode_preview_travel(GCodePreviewData& preview_data, std::function<void()> cancel_callback);
|
||||
void _calc_gcode_preview_retractions(GCodePreviewData& preview_data, std::function<void()> cancel_callback);
|
||||
void _calc_gcode_preview_unretractions(GCodePreviewData& preview_data, std::function<void()> cancel_callback);
|
||||
};
|
||||
|
||||
class BufferData {
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#ifdef WIN32
|
||||
@ -88,7 +89,7 @@ static DWORD execute_process_winapi(const std::wstring &command_line)
|
||||
// Run the script. If it is a perl script, run it through the bundled perl interpreter.
|
||||
// If it is a batch file, run it through the cmd.exe.
|
||||
// Otherwise run it directly.
|
||||
static int run_script_win32(const std::string &script, const std::string &gcode)
|
||||
static int run_script(const std::string &script, const std::string &gcode, std::string &/*std_err*/)
|
||||
{
|
||||
// Unpack the argument list provided by the user.
|
||||
int nArgs;
|
||||
@ -132,9 +133,46 @@ static int run_script_win32(const std::string &script, const std::string &gcode)
|
||||
}
|
||||
|
||||
#else
|
||||
#include <sys/stat.h> //for getting filesystem UID/GID
|
||||
#include <unistd.h> //for getting current UID/GID
|
||||
#include <boost/process.hpp>
|
||||
// POSIX
|
||||
|
||||
#include <cstdlib> // getenv()
|
||||
#include <sstream>
|
||||
#include <boost/process.hpp>
|
||||
|
||||
namespace process = boost::process;
|
||||
|
||||
static int run_script(const std::string &script, const std::string &gcode, std::string &std_err)
|
||||
{
|
||||
// Try to obtain user's default shell
|
||||
const char *shell = ::getenv("SHELL");
|
||||
if (shell == nullptr) { shell = "sh"; }
|
||||
|
||||
// Quote and escape the gcode path argument
|
||||
std::string command { script };
|
||||
command.append(" '");
|
||||
for (char c : gcode) {
|
||||
if (c == '\'') { command.append("'\\''"); }
|
||||
else { command.push_back(c); }
|
||||
}
|
||||
command.push_back('\'');
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug) << boost::format("Executing script, shell: %1%, command: %2%") % shell % command;
|
||||
|
||||
process::ipstream istd_err;
|
||||
process::child child(shell, "-c", command, process::std_err > istd_err);
|
||||
|
||||
std_err.clear();
|
||||
std::string line;
|
||||
|
||||
while (child.running() && std::getline(istd_err, line)) {
|
||||
std_err.append(line);
|
||||
std_err.push_back('\n');
|
||||
}
|
||||
|
||||
child.wait();
|
||||
return child.exit_code();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
namespace Slic3r {
|
||||
@ -158,27 +196,15 @@ void run_post_process_scripts(const std::string &path, const PrintConfig &config
|
||||
if (script.empty())
|
||||
continue;
|
||||
BOOST_LOG_TRIVIAL(info) << "Executing script " << script << " on file " << path;
|
||||
#ifdef WIN32
|
||||
int result = run_script_win32(script, gcode_file.string());
|
||||
#else
|
||||
//FIXME testing existence of a script is risky, as the script line may contain the script and some additional command line parameters.
|
||||
// We would have to process the script line into parameters before testing for the existence of the command, the command may be looked up
|
||||
// in the PATH etc.
|
||||
if (! boost::filesystem::exists(boost::filesystem::path(script)))
|
||||
throw std::runtime_error(std::string("The configured post-processing script does not exist: ") + script);
|
||||
struct stat info;
|
||||
if (stat(script.c_str(), &info))
|
||||
throw std::runtime_error(std::string("Cannot read information for post-processing script: ") + script);
|
||||
boost::filesystem::perms script_perms = boost::filesystem::status(script).permissions();
|
||||
//if UID matches, check UID perm. else if GID matches, check GID perm. Otherwise check other perm.
|
||||
if (!(script_perms & ((info.st_uid == geteuid()) ? boost::filesystem::perms::owner_exe
|
||||
: ((info.st_gid == getegid()) ? boost::filesystem::perms::group_exe
|
||||
: boost::filesystem::perms::others_exe))))
|
||||
throw std::runtime_error(std::string("The configured post-processing script is not executable: check permissions. ") + script);
|
||||
int result = boost::process::system(script, gcode_file);
|
||||
if (result < 0)
|
||||
BOOST_LOG_TRIVIAL(error) << "Script " << script << " on file " << path << " failed. Negative error code returned.";
|
||||
#endif
|
||||
|
||||
std::string std_err;
|
||||
const int result = run_script(script, gcode_file.string(), std_err);
|
||||
if (result != 0) {
|
||||
const std::string msg = std_err.empty() ? (boost::format("Post-processing script %1% on file %2% failed.\nError code: %3%") % script % path % result).str()
|
||||
: (boost::format("Post-processing script %1% on file %2% failed.\nError code: %3%\nOutput:\n%4%") % script % path % result % std_err).str();
|
||||
BOOST_LOG_TRIVIAL(error) << msg;
|
||||
throw std::runtime_error(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -741,12 +741,11 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::toolchange_Brim(bool sideOnly, flo
|
||||
// The tool is supposed to be active and primed at the time when the wipe tower brim is extruded.
|
||||
// Extrude 4 rounds of a brim around the future wipe tower.
|
||||
box_coordinates box(wipeTower_box);
|
||||
box.expand(m_brim_width);
|
||||
for (size_t i = 0; i < 4; ++ i) {
|
||||
box.expand(m_perimeter_width - m_layer_height*(1.f-M_PI_4)); // the brim shall have 'normal' spacing with no extra void space
|
||||
writer.travel (box.ld, 7000)
|
||||
.extrude(box.lu, 2100).extrude(box.ru)
|
||||
.extrude(box.rd ).extrude(box.ld);
|
||||
box.expand(m_brim_width);
|
||||
}
|
||||
|
||||
writer.travel(wipeTower_box.ld, 7000); // Move to the front left corner.
|
||||
|
@ -65,6 +65,7 @@ void Layer::make_slices()
|
||||
this->slices.expolygons.push_back(std::move(slices[i]));
|
||||
}
|
||||
|
||||
// Merge typed slices into untyped slices. This method is used to revert the effects of detect_surfaces_type() called for posPrepareInfill.
|
||||
void Layer::merge_slices()
|
||||
{
|
||||
if (m_regions.size() == 1) {
|
||||
@ -78,6 +79,24 @@ void Layer::merge_slices()
|
||||
}
|
||||
}
|
||||
|
||||
ExPolygons Layer::merged(float offset_scaled) const
|
||||
{
|
||||
assert(offset_scaled >= 0.f);
|
||||
// If no offset is set, apply EPSILON offset before union, and revert it afterwards.
|
||||
float offset_scaled2 = 0;
|
||||
if (offset_scaled == 0.f) {
|
||||
offset_scaled = float( EPSILON);
|
||||
offset_scaled2 = float(- EPSILON);
|
||||
}
|
||||
Polygons polygons;
|
||||
for (LayerRegion *layerm : m_regions)
|
||||
append(polygons, offset(to_expolygons(layerm->slices.surfaces), offset_scaled));
|
||||
ExPolygons out = union_ex(polygons);
|
||||
if (offset_scaled2 != 0.f)
|
||||
out = offset_ex(out, offset_scaled2);
|
||||
return out;
|
||||
}
|
||||
|
||||
// Here the perimeters are created cummulatively for all layer regions sharing the same parameters influencing the perimeters.
|
||||
// The perimeter paths and the thin fills (ExtrusionEntityCollection) are assigned to the first compatible layer region.
|
||||
// The resulting fill surface is split back among the originating regions.
|
||||
@ -86,13 +105,14 @@ void Layer::make_perimeters()
|
||||
BOOST_LOG_TRIVIAL(trace) << "Generating perimeters for layer " << this->id();
|
||||
|
||||
// keep track of regions whose perimeters we have already generated
|
||||
std::set<size_t> done;
|
||||
std::vector<unsigned char> done(m_regions.size(), false);
|
||||
|
||||
for (LayerRegionPtrs::iterator layerm = m_regions.begin(); layerm != m_regions.end(); ++ layerm) {
|
||||
size_t region_id = layerm - m_regions.begin();
|
||||
if (done.find(region_id) != done.end()) continue;
|
||||
if (done[region_id])
|
||||
continue;
|
||||
BOOST_LOG_TRIVIAL(trace) << "Generating perimeters for layer " << this->id() << ", region " << region_id;
|
||||
done.insert(region_id);
|
||||
done[region_id] = true;
|
||||
const PrintRegionConfig &config = (*layerm)->region()->config();
|
||||
|
||||
// find compatible regions
|
||||
@ -116,7 +136,7 @@ void Layer::make_perimeters()
|
||||
&& config.external_perimeters_first == other_config.external_perimeters_first
|
||||
&& config.perimeter_loop == other_config.perimeter_loop) {
|
||||
layerms.push_back(other_layerm);
|
||||
done.insert(it - m_regions.begin());
|
||||
done[it - m_regions.begin()] = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -128,15 +148,13 @@ void Layer::make_perimeters()
|
||||
SurfaceCollection new_slices;
|
||||
{
|
||||
// group slices (surfaces) according to number of extra perimeters
|
||||
std::map<unsigned short,Surfaces> slices; // extra_perimeters => [ surface, surface... ]
|
||||
for (LayerRegionPtrs::iterator l = layerms.begin(); l != layerms.end(); ++l) {
|
||||
for (Surfaces::iterator s = (*l)->slices.surfaces.begin(); s != (*l)->slices.surfaces.end(); ++s) {
|
||||
slices[s->extra_perimeters].push_back(*s);
|
||||
}
|
||||
}
|
||||
std::map<unsigned short, Surfaces> slices; // extra_perimeters => [ surface, surface... ]
|
||||
for (LayerRegion *layerm : layerms)
|
||||
for (Surface &surface : layerm->slices.surfaces)
|
||||
slices[surface.extra_perimeters].emplace_back(surface);
|
||||
// merge the surfaces assigned to each group
|
||||
for (std::map<unsigned short,Surfaces>::const_iterator it = slices.begin(); it != slices.end(); ++it)
|
||||
new_slices.append(union_ex(it->second, true), it->second.front());
|
||||
for (std::pair<const unsigned short,Surfaces> &surfaces_with_extra_perimeters : slices)
|
||||
new_slices.append(union_ex(surfaces_with_extra_perimeters.second, true), surfaces_with_extra_perimeters.second.front());
|
||||
}
|
||||
|
||||
// make perimeters
|
||||
|
@ -65,7 +65,12 @@ public:
|
||||
void prepare_fill_surfaces();
|
||||
void make_perimeters(SurfaceCollection &slices, SurfaceCollection* fill_surfaces);
|
||||
void process_external_surfaces(const Layer* lower_layer);
|
||||
double infill_area_threshold() const;
|
||||
double infill_area_threshold() const;
|
||||
// Trim surfaces by trimming polygons. Used by the elephant foot compensation at the 1st layer.
|
||||
void trim_surfaces(const Polygons &trimming_polygons);
|
||||
// Single elephant foot compensation step, used by the elephant foor compensation at the 1st layer.
|
||||
// Trim surfaces by trimming polygons (shrunk by an elephant foot compensation step), but don't shrink narrow parts so much that no perimeter would fit.
|
||||
void elephant_foot_compensation_step(const float elephant_foot_compensation_perimeter_step, const Polygons &trimming_polygons);
|
||||
|
||||
void export_region_slices_to_svg(const char *path) const;
|
||||
void export_region_fill_surfaces_to_svg(const char *path) const;
|
||||
@ -119,7 +124,10 @@ public:
|
||||
// Test whether whether there are any slices assigned to this layer.
|
||||
bool empty() const;
|
||||
void make_slices();
|
||||
// Merge typed slices into untyped slices. This method is used to revert the effects of detect_surfaces_type() called for posPrepareInfill.
|
||||
void merge_slices();
|
||||
// Slices merged into islands, to be used by the elephant foot compensation to trim the individual surfaces with the shrunk merged slices.
|
||||
ExPolygons merged(float offset) const;
|
||||
template <class T> bool any_internal_region_slice_contains(const T &item) const {
|
||||
for (const LayerRegion *layerm : m_regions) if (layerm->slices.any_internal_contains(item)) return true;
|
||||
return false;
|
||||
|
@ -79,7 +79,7 @@ void LayerRegion::make_perimeters(SurfaceCollection &slices, SurfaceCollection*
|
||||
if (this->layer()->upper_layer != NULL)
|
||||
g.upper_slices = &this->layer()->upper_layer->slices;
|
||||
|
||||
g.layer_id = this->layer()->id();
|
||||
g.layer_id = (int)this->layer()->id();
|
||||
g.ext_perimeter_flow = this->flow(frExternalPerimeter);
|
||||
g.overhang_flow = this->region()->flow(frPerimeter, -1, true, false, -1, *this->layer()->object());
|
||||
g.solid_infill_flow = this->flow(frSolidInfill);
|
||||
@ -413,6 +413,28 @@ double LayerRegion::infill_area_threshold() const
|
||||
return ss*ss;
|
||||
}
|
||||
|
||||
void LayerRegion::trim_surfaces(const Polygons &trimming_polygons)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
for (const Surface &surface : this->slices.surfaces)
|
||||
assert(surface.surface_type == stInternal);
|
||||
#endif /* NDEBUG */
|
||||
this->slices.set(intersection_ex(to_polygons(std::move(this->slices.surfaces)), trimming_polygons, false), stPosInternal | stDensSparse);
|
||||
}
|
||||
|
||||
void LayerRegion::elephant_foot_compensation_step(const float elephant_foot_compensation_perimeter_step, const Polygons &trimming_polygons)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
for (const Surface &surface : this->slices.surfaces)
|
||||
assert(surface.surface_type == stInternal);
|
||||
#endif /* NDEBUG */
|
||||
ExPolygons slices_expolygons = to_expolygons(std::move(this->slices.surfaces));
|
||||
Polygons slices_polygons = to_polygons(slices_expolygons);
|
||||
Polygons tmp = intersection(slices_polygons, trimming_polygons, false);
|
||||
append(tmp, diff(slices_polygons, offset(offset_ex(slices_expolygons, -elephant_foot_compensation_perimeter_step), elephant_foot_compensation_perimeter_step)));
|
||||
this->slices.set(std::move(union_ex(tmp)), stPosInternal | stDensSparse);
|
||||
}
|
||||
|
||||
void LayerRegion::export_region_slices_to_svg(const char *path) const
|
||||
{
|
||||
BoundingBox bbox;
|
||||
|
@ -56,6 +56,113 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template<class Vector,
|
||||
class Value = typename Vector::value_type>
|
||||
class IndexBasedIterator {
|
||||
static const size_t NONE = size_t(-1);
|
||||
|
||||
std::reference_wrapper<Vector> m_index_ref;
|
||||
size_t m_idx = NONE;
|
||||
public:
|
||||
|
||||
using value_type = Value;
|
||||
using pointer = Value *;
|
||||
using reference = Value &;
|
||||
using difference_type = long;
|
||||
using iterator_category = std::random_access_iterator_tag;
|
||||
|
||||
inline explicit
|
||||
IndexBasedIterator(Vector& index, size_t idx):
|
||||
m_index_ref(index), m_idx(idx) {}
|
||||
|
||||
// Post increment
|
||||
inline IndexBasedIterator operator++(int) {
|
||||
IndexBasedIterator cpy(*this); ++m_idx; return cpy;
|
||||
}
|
||||
|
||||
inline IndexBasedIterator operator--(int) {
|
||||
IndexBasedIterator cpy(*this); --m_idx; return cpy;
|
||||
}
|
||||
|
||||
inline IndexBasedIterator& operator++() {
|
||||
++m_idx; return *this;
|
||||
}
|
||||
|
||||
inline IndexBasedIterator& operator--() {
|
||||
--m_idx; return *this;
|
||||
}
|
||||
|
||||
inline IndexBasedIterator& operator+=(difference_type l) {
|
||||
m_idx += size_t(l); return *this;
|
||||
}
|
||||
|
||||
inline IndexBasedIterator operator+(difference_type l) {
|
||||
auto cpy = *this; cpy += l; return cpy;
|
||||
}
|
||||
|
||||
inline IndexBasedIterator& operator-=(difference_type l) {
|
||||
m_idx -= size_t(l); return *this;
|
||||
}
|
||||
|
||||
inline IndexBasedIterator operator-(difference_type l) {
|
||||
auto cpy = *this; cpy -= l; return cpy;
|
||||
}
|
||||
|
||||
operator difference_type() { return difference_type(m_idx); }
|
||||
|
||||
inline bool is_end() const { return m_idx >= m_index_ref.get().size();}
|
||||
|
||||
inline Value & operator*() const {
|
||||
assert(m_idx < m_index_ref.get().size());
|
||||
return m_index_ref.get().operator[](m_idx);
|
||||
}
|
||||
|
||||
inline Value * operator->() const {
|
||||
assert(m_idx < m_index_ref.get().size());
|
||||
return &m_index_ref.get().operator[](m_idx);
|
||||
}
|
||||
|
||||
inline bool operator ==(const IndexBasedIterator& other) {
|
||||
size_t e = m_index_ref.get().size();
|
||||
return m_idx == other.m_idx || (m_idx >= e && other.m_idx >= e);
|
||||
}
|
||||
|
||||
inline bool operator !=(const IndexBasedIterator& other) {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
inline bool operator <=(const IndexBasedIterator& other) {
|
||||
return (m_idx < other.m_idx) || (*this == other);
|
||||
}
|
||||
|
||||
inline bool operator <(const IndexBasedIterator& other) {
|
||||
return m_idx < other.m_idx && (*this != other);
|
||||
}
|
||||
|
||||
inline bool operator >=(const IndexBasedIterator& other) {
|
||||
return m_idx > other.m_idx || *this == other;
|
||||
}
|
||||
|
||||
inline bool operator >(const IndexBasedIterator& other) {
|
||||
return m_idx > other.m_idx && *this != other;
|
||||
}
|
||||
};
|
||||
|
||||
template<class It> class Range {
|
||||
It from, to;
|
||||
public:
|
||||
It begin() const { return from; }
|
||||
It end() const { return to; }
|
||||
using Type = It;
|
||||
|
||||
Range() = default;
|
||||
Range(It &&b, It &&e):
|
||||
from(std::forward<It>(b)), to(std::forward<It>(e)) {}
|
||||
|
||||
inline size_t size() const { return end() - begin(); }
|
||||
inline bool empty() const { return size() == 0; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // MTUTILS_HPP
|
||||
|
@ -577,6 +577,11 @@ end:
|
||||
return input_file;
|
||||
}
|
||||
|
||||
std::string Model::propose_export_file_name_and_path(const std::string &new_extension) const
|
||||
{
|
||||
return boost::filesystem::path(this->propose_export_file_name_and_path()).replace_extension(new_extension).string();
|
||||
}
|
||||
|
||||
ModelObject::~ModelObject()
|
||||
{
|
||||
this->clear_volumes();
|
||||
@ -992,12 +997,16 @@ Polygon ModelObject::convex_hull_2d(const Transform3d &trafo_instance)
|
||||
return hull;
|
||||
}
|
||||
|
||||
#if ENABLE_VOLUMES_CENTERING_FIXES
|
||||
void ModelObject::center_around_origin(bool include_modifiers)
|
||||
#else
|
||||
void ModelObject::center_around_origin()
|
||||
#endif // ENABLE_VOLUMES_CENTERING_FIXES
|
||||
{
|
||||
// calculate the displacements needed to
|
||||
// center this object around the origin
|
||||
#if ENABLE_VOLUMES_CENTERING_FIXES
|
||||
BoundingBoxf3 bb = full_raw_mesh_bounding_box();
|
||||
BoundingBoxf3 bb = include_modifiers ? full_raw_mesh_bounding_box() : raw_mesh_bounding_box();
|
||||
#else
|
||||
BoundingBoxf3 bb;
|
||||
for (ModelVolume *v : this->volumes)
|
||||
@ -1456,6 +1465,15 @@ int ModelVolume::extruder_id() const
|
||||
return extruder_id;
|
||||
}
|
||||
|
||||
bool ModelVolume::is_splittable() const
|
||||
{
|
||||
// the call mesh.has_multiple_patches() is expensive, so cache the value to calculate it only once
|
||||
if (m_is_splittable == -1)
|
||||
m_is_splittable = (int)mesh.has_multiple_patches();
|
||||
|
||||
return m_is_splittable == 1;
|
||||
}
|
||||
|
||||
void ModelVolume::center_geometry()
|
||||
{
|
||||
#if ENABLE_VOLUMES_CENTERING_FIXES
|
||||
@ -1568,6 +1586,22 @@ void ModelVolume::scale(const Vec3d& scaling_factors)
|
||||
set_scaling_factor(get_scaling_factor().cwiseProduct(scaling_factors));
|
||||
}
|
||||
|
||||
void ModelObject::scale_to_fit(const Vec3d &size)
|
||||
{
|
||||
/*
|
||||
BoundingBoxf3 instance_bounding_box(size_t instance_idx, bool dont_translate = false) const;
|
||||
Vec3d orig_size = this->bounding_box().size();
|
||||
float factor = fminf(
|
||||
size.x / orig_size.x,
|
||||
fminf(
|
||||
size.y / orig_size.y,
|
||||
size.z / orig_size.z
|
||||
)
|
||||
);
|
||||
this->scale(factor);
|
||||
*/
|
||||
}
|
||||
|
||||
void ModelVolume::rotate(double angle, Axis axis)
|
||||
{
|
||||
switch (axis)
|
||||
|
@ -236,7 +236,11 @@ public:
|
||||
// This method is used by the auto arrange function.
|
||||
Polygon convex_hull_2d(const Transform3d &trafo_instance);
|
||||
|
||||
#if ENABLE_VOLUMES_CENTERING_FIXES
|
||||
void center_around_origin(bool include_modifiers = true);
|
||||
#else
|
||||
void center_around_origin();
|
||||
#endif // ENABLE_VOLUMES_CENTERING_FIXES
|
||||
void ensure_on_bed();
|
||||
void translate_instances(const Vec3d& vector);
|
||||
void translate_instance(size_t instance_idx, const Vec3d& vector);
|
||||
@ -245,6 +249,10 @@ public:
|
||||
void scale(const Vec3d &versor);
|
||||
void scale(const double s) { this->scale(Vec3d(s, s, s)); }
|
||||
void scale(double x, double y, double z) { this->scale(Vec3d(x, y, z)); }
|
||||
/// Scale the current ModelObject to fit by altering the scaling factor of ModelInstances.
|
||||
/// It operates on the total size by duplicating the object according to all the instances.
|
||||
/// \param size Sizef3 the size vector
|
||||
void scale_to_fit(const Vec3d &size);
|
||||
void rotate(double angle, Axis axis);
|
||||
void rotate(double angle, const Vec3d& axis);
|
||||
void mirror(Axis axis);
|
||||
@ -336,8 +344,7 @@ public:
|
||||
// Extruder ID is only valid for FFF. Returns -1 for SLA or if the extruder ID is not applicable (support volumes).
|
||||
int extruder_id() const;
|
||||
|
||||
void set_splittable(const int val) { m_is_splittable = val; }
|
||||
int is_splittable() const { return m_is_splittable; }
|
||||
bool is_splittable() const;
|
||||
|
||||
// Split this volume, append the result to the object owning this volume.
|
||||
// Return the number of volumes created from this one.
|
||||
@ -417,7 +424,7 @@ private:
|
||||
// -1 -> is unknown value (before first cheking)
|
||||
// 0 -> is not splittable
|
||||
// 1 -> is splittable
|
||||
int m_is_splittable {-1};
|
||||
mutable int m_is_splittable{ -1 };
|
||||
|
||||
ModelVolume(ModelObject *object, const TriangleMesh &mesh) : mesh(mesh), m_type(ModelVolumeType::MODEL_PART), object(object)
|
||||
{
|
||||
@ -619,6 +626,8 @@ public:
|
||||
|
||||
// Propose an output file name & path based on the first printable object's name and source input file's path.
|
||||
std::string propose_export_file_name_and_path() const;
|
||||
// Propose an output path, replace extension. The new_extension shall contain the initial dot.
|
||||
std::string propose_export_file_name_and_path(const std::string &new_extension) const;
|
||||
|
||||
private:
|
||||
MODELBASE_DERIVED_PRIVATE_COPY_MOVE(Model)
|
||||
|
@ -556,29 +556,7 @@ ShapeData2D projectModelFromTop(const Slic3r::Model &model) {
|
||||
// TODO export the exact 2D projection. Cannot do it as libnest2d
|
||||
// does not support concave shapes (yet).
|
||||
ClipperLib::Path clpath;
|
||||
//WIP Vojtech's optimization of the calculation of the convex hull is not working correctly yet.
|
||||
#if 1
|
||||
{
|
||||
TriangleMesh rmesh = objptr->raw_mesh();
|
||||
|
||||
ModelInstance * finst = objptr->instances.front();
|
||||
|
||||
// Object instances should carry the same scaling and
|
||||
// x, y rotation that is why we use the first instance.
|
||||
// The next line will apply only the full mirroring and scaling
|
||||
rmesh.transform(finst->get_matrix(true, true, false, false));
|
||||
rmesh.rotate_x(float(finst->get_rotation()(X)));
|
||||
rmesh.rotate_y(float(finst->get_rotation()(Y)));
|
||||
|
||||
// TODO export the exact 2D projection. Cannot do it as libnest2d
|
||||
// does not support concave shapes (yet).
|
||||
auto p = rmesh.convex_hull();
|
||||
|
||||
p.make_clockwise();
|
||||
p.append(p.first_point());
|
||||
clpath = Slic3rMultiPoint_to_ClipperPath(p);
|
||||
}
|
||||
#else
|
||||
// Object instances should carry the same scaling and
|
||||
// x, y rotation that is why we use the first instance.
|
||||
{
|
||||
@ -593,7 +571,6 @@ ShapeData2D projectModelFromTop(const Slic3r::Model &model) {
|
||||
p.append(p.first_point());
|
||||
clpath = Slic3rMultiPoint_to_ClipperPath(p);
|
||||
}
|
||||
#endif
|
||||
|
||||
for(ModelInstance* objinst : objptr->instances) {
|
||||
if(objinst) {
|
||||
|
@ -240,7 +240,7 @@ public:
|
||||
const ValueType &value = it->second;
|
||||
const Vec2crd *pt2 = m_point_accessor(value);
|
||||
if (pt2 != nullptr) {
|
||||
const double d2 = (pt - *pt2).squaredNorm();
|
||||
const double d2 = (pt - *pt2).cast<double>().squaredNorm();
|
||||
if (d2 < dist_min) {
|
||||
dist_min = d2;
|
||||
value_min = &value;
|
||||
|
@ -532,6 +532,9 @@ exit_for_rearrange_regions:
|
||||
invalidated = true;
|
||||
}
|
||||
|
||||
for (PrintObject *object : m_objects)
|
||||
object->update_slicing_parameters();
|
||||
|
||||
return invalidated;
|
||||
}
|
||||
|
||||
@ -667,6 +670,9 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co
|
||||
|
||||
// Make a copy of the config, normalize it.
|
||||
DynamicPrintConfig config(config_in);
|
||||
config.option("print_settings_id", true);
|
||||
config.option("filament_settings_id", true);
|
||||
config.option("printer_settings_id", true);
|
||||
config.normalize();
|
||||
// Collect changes to print config.
|
||||
t_config_option_keys print_diff = m_config.diff(config);
|
||||
@ -694,9 +700,9 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co
|
||||
PlaceholderParser &pp = this->placeholder_parser();
|
||||
pp.apply_only(config, placeholder_parser_diff);
|
||||
// Set the profile aliases for the PrintBase::output_filename()
|
||||
pp.set("print_preset", config_in.option("print_settings_id" )->clone());
|
||||
pp.set("filament_preset", config_in.option("filament_settings_id")->clone());
|
||||
pp.set("printer_preset", config_in.option("printer_settings_id" )->clone());
|
||||
pp.set("print_preset", config.option("print_settings_id")->clone());
|
||||
pp.set("filament_preset", config.option("filament_settings_id")->clone());
|
||||
pp.set("printer_preset", config.option("printer_settings_id")->clone());
|
||||
}
|
||||
|
||||
// It is also safe to change m_config now after this->invalidate_state_by_config_options() call.
|
||||
@ -1107,6 +1113,12 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co
|
||||
}
|
||||
}
|
||||
|
||||
// Update SlicingParameters for each object where the SlicingParameters is not valid.
|
||||
// If it is not valid, then it is ensured that PrintObject.m_slicing_params is not in use
|
||||
// (posSlicing and posSupportMaterial was invalidated).
|
||||
for (PrintObject *object : m_objects)
|
||||
object->update_slicing_parameters();
|
||||
|
||||
#ifdef _DEBUG
|
||||
check_model_ids_equal(m_model, model);
|
||||
#endif /* _DEBUG */
|
||||
@ -1245,21 +1257,21 @@ std::string Print::validate() const
|
||||
break;
|
||||
}
|
||||
}
|
||||
SlicingParameters slicing_params0 = m_objects.front()->slicing_parameters();
|
||||
const SlicingParameters &slicing_params0 = m_objects.front()->slicing_parameters();
|
||||
size_t tallest_object_idx = 0;
|
||||
if (has_custom_layering)
|
||||
PrintObject::update_layer_height_profile(*m_objects.front()->model_object(), slicing_params0, layer_height_profiles.front());
|
||||
for (size_t i = 1; i < m_objects.size(); ++ i) {
|
||||
const PrintObject *object = m_objects[i];
|
||||
const SlicingParameters slicing_params = object->slicing_parameters();
|
||||
const PrintObject *object = m_objects[i];
|
||||
const SlicingParameters &slicing_params = object->slicing_parameters();
|
||||
if (std::abs(slicing_params.first_print_layer_height - slicing_params0.first_print_layer_height) > EPSILON ||
|
||||
std::abs(slicing_params.layer_height - slicing_params0.layer_height ) > EPSILON)
|
||||
return L("The Wipe Tower is only supported for multiple objects if they have equal layer heigths");
|
||||
if (slicing_params.raft_layers() != slicing_params0.raft_layers())
|
||||
return L("The Wipe Tower is only supported for multiple objects if they are printed over an equal number of raft layers");
|
||||
if (object->config().support_material_contact_distance_type != m_objects.front()->config().support_material_contact_distance_type
|
||||
|| object->config().support_material_contact_distance_top != m_objects.front()->config().support_material_contact_distance_top
|
||||
|| object->config().support_material_contact_distance_bottom != m_objects.front()->config().support_material_contact_distance_bottom)
|
||||
|| object->config().support_material_contact_distance_top != m_objects.front()->config().support_material_contact_distance_top
|
||||
|| object->config().support_material_contact_distance_bottom != m_objects.front()->config().support_material_contact_distance_bottom)
|
||||
return L("The Wipe Tower is only supported for multiple objects if they are printed with the same support_material_contact_distance");
|
||||
if (! equal_layering(slicing_params, slicing_params0))
|
||||
return L("The Wipe Tower is only supported for multiple objects if they are sliced equally.");
|
||||
@ -1574,7 +1586,7 @@ void Print::process()
|
||||
// The export_gcode may die for various reasons (fails to process output_filename_format,
|
||||
// write error into the G-code, cannot execute post-processing scripts).
|
||||
// It is up to the caller to show an error message.
|
||||
void Print::export_gcode(const std::string &path_template, GCodePreviewData *preview_data)
|
||||
std::string Print::export_gcode(const std::string &path_template, GCodePreviewData *preview_data)
|
||||
{
|
||||
// output everything to a G-code file
|
||||
// The following call may die if the output_filename_format template substitution fails.
|
||||
@ -1590,6 +1602,7 @@ void Print::export_gcode(const std::string &path_template, GCodePreviewData *pre
|
||||
// The following line may die for multiple reasons.
|
||||
GCode gcode;
|
||||
gcode.do_export(this, path.c_str(), preview_data);
|
||||
return path.c_str();
|
||||
}
|
||||
|
||||
void Print::_make_skirt(const PrintObjectPtrs &objects, ExtrusionEntityCollection &out)
|
||||
@ -1763,6 +1776,8 @@ void Print::_make_brim(const PrintObjectPtrs &objects, ExtrusionEntityCollection
|
||||
}
|
||||
|
||||
loops = union_pt_chained(loops, false);
|
||||
// The function above produces ordering well suited for concentric infill (from outside to inside).
|
||||
// For Brim, the ordering should be reversed (from inside to outside).
|
||||
std::reverse(loops.begin(), loops.end());
|
||||
extrusion_entities_append_loops(out.entities, std::move(loops), erSkirt, float(flow.mm3_per_mm()), float(flow.width), float(this->skirt_first_layer_height()));
|
||||
}
|
||||
|
@ -93,7 +93,7 @@ public:
|
||||
const LayerPtrs& layers() const { return m_layers; }
|
||||
const SupportLayerPtrs& support_layers() const { return m_support_layers; }
|
||||
const Transform3d& trafo() const { return m_trafo; }
|
||||
const Points& copies() const { return m_copies; }
|
||||
const Points& copies() const { return m_copies; }
|
||||
|
||||
// since the object is aligned to origin, bounding box coincides with size
|
||||
BoundingBox bounding_box() const { return BoundingBox(Point(0,0), to_2d(this->size)); }
|
||||
@ -131,7 +131,7 @@ public:
|
||||
// by the interactive layer height editor and by the printing process itself.
|
||||
// The slicing parameters are dependent on various configuration values
|
||||
// (layer height, first layer height, raft settings, print nozzle diameter etc).
|
||||
SlicingParameters slicing_parameters() const;
|
||||
const SlicingParameters& slicing_parameters() const { return m_slicing_params; }
|
||||
static SlicingParameters slicing_parameters(const DynamicPrintConfig &full_config, const ModelObject &model_object);
|
||||
|
||||
// returns 0-based indices of extruders used to print the object (without brim, support and other helper extrusions)
|
||||
@ -165,6 +165,8 @@ protected:
|
||||
bool invalidate_all_steps();
|
||||
// Invalidate steps based on a set of parameters changed.
|
||||
bool invalidate_state_by_config_options(const std::vector<t_config_option_key> &opt_keys);
|
||||
// If ! m_slicing_params.valid, recalculate.
|
||||
void update_slicing_parameters();
|
||||
|
||||
static PrintObjectConfig object_config_from_model_object(const PrintObjectConfig &default_object_config, const ModelObject &object, size_t num_extruders);
|
||||
static PrintRegionConfig region_config_from_model_volume(const PrintRegionConfig &default_region_config, const ModelVolume &volume, size_t num_extruders);
|
||||
@ -203,6 +205,7 @@ private:
|
||||
// for external callers)
|
||||
Point m_copies_shift;
|
||||
|
||||
SlicingParameters m_slicing_params;
|
||||
LayerPtrs m_layers;
|
||||
SupportLayerPtrs m_support_layers;
|
||||
|
||||
@ -214,6 +217,7 @@ private:
|
||||
|
||||
std::vector<ExPolygons> _slice_region(size_t region_id, const std::vector<float> &z, bool modifier);
|
||||
std::vector<ExPolygons> _slice_volumes(const std::vector<float> &z, const std::vector<const ModelVolume*> &volumes) const;
|
||||
std::vector<ExPolygons> _slice_volume(const std::vector<float> &z, const ModelVolume &volume) const;
|
||||
};
|
||||
|
||||
struct WipeTowerData
|
||||
@ -307,7 +311,9 @@ public:
|
||||
bool apply_config(DynamicPrintConfig config);
|
||||
|
||||
void process() override;
|
||||
void export_gcode(const std::string &path_template, GCodePreviewData *preview_data);
|
||||
// Exports G-code into a file name based on the path_template, returns the file path of the generated G-code file.
|
||||
// If preview_data is not null, the preview_data is filled in for the G-code visualization (not used by the command line Slic3r).
|
||||
std::string export_gcode(const std::string &path_template, GCodePreviewData *preview_data);
|
||||
|
||||
// methods for handling state
|
||||
bool is_step_done(PrintStep step) const { return Inherited::is_step_done(step); }
|
||||
|
@ -272,6 +272,7 @@ public:
|
||||
NO_RELOAD_SCENE = 0,
|
||||
RELOAD_SCENE = 1 << 1,
|
||||
RELOAD_SLA_SUPPORT_POINTS = 1 << 2,
|
||||
RELOAD_SLA_PREVIEW = 1 << 3,
|
||||
};
|
||||
// Bitmap of FlagBits
|
||||
unsigned int flags;
|
||||
|
@ -24,17 +24,6 @@
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
enum PrinterTechnology
|
||||
{
|
||||
// Fused Filament Fabrication
|
||||
ptFFF,
|
||||
// Stereolitography
|
||||
ptSLA,
|
||||
// laser-sintered powder
|
||||
ptSLS,
|
||||
};
|
||||
|
||||
|
||||
enum WipeAlgo {
|
||||
waLinear,
|
||||
waQuadra,
|
||||
@ -47,7 +36,7 @@ enum GCodeFlavor {
|
||||
};
|
||||
|
||||
enum PrintHostType {
|
||||
htOctoPrint, htDuet, htSL1,
|
||||
htOctoPrint, htDuet
|
||||
};
|
||||
|
||||
enum InfillPattern {
|
||||
@ -97,6 +86,7 @@ template<> inline const t_config_enum_values& ConfigOptionEnum<PrinterTechnology
|
||||
if (keys_map.empty()) {
|
||||
keys_map["FFF"] = ptFFF;
|
||||
keys_map["SLA"] = ptSLA;
|
||||
keys_map["SLS"] = ptSLS;
|
||||
}
|
||||
return keys_map;
|
||||
}
|
||||
@ -959,12 +949,6 @@ public:
|
||||
ConfigOptionFloats wiping_volumes_matrix;
|
||||
ConfigOptionFloats wiping_volumes_extruders;
|
||||
ConfigOptionFloat z_offset;
|
||||
ConfigOptionFloat bed_size_x;
|
||||
ConfigOptionFloat bed_size_y;
|
||||
ConfigOptionInt pixel_width;
|
||||
ConfigOptionInt pixel_height;
|
||||
ConfigOptionFloat exp_time;
|
||||
ConfigOptionFloat exp_time_first;
|
||||
|
||||
protected:
|
||||
PrintConfig(int) : MachineEnvelopeConfig(1), GCodeConfig(1) {}
|
||||
@ -1041,12 +1025,6 @@ protected:
|
||||
OPT_PTR(wiping_volumes_matrix);
|
||||
OPT_PTR(wiping_volumes_extruders);
|
||||
OPT_PTR(z_offset);
|
||||
OPT_PTR(bed_size_x);
|
||||
OPT_PTR(bed_size_y);
|
||||
OPT_PTR(pixel_width);
|
||||
OPT_PTR(pixel_height);
|
||||
OPT_PTR(exp_time);
|
||||
OPT_PTR(exp_time_first);
|
||||
}
|
||||
};
|
||||
|
||||
@ -1163,6 +1141,9 @@ public:
|
||||
// The max length of a bridge in mm
|
||||
ConfigOptionFloat support_max_bridge_length /*= 15.0*/;
|
||||
|
||||
// The max distance of two pillars to get cross linked.
|
||||
ConfigOptionFloat support_max_pillar_link_distance;
|
||||
|
||||
// The elevation in Z direction upwards. This is the space between the pad
|
||||
// and the model object's bounding box bottom. Units in mm.
|
||||
ConfigOptionFloat support_object_elevation /*= 5.0*/;
|
||||
@ -1210,6 +1191,7 @@ protected:
|
||||
OPT_PTR(support_base_height);
|
||||
OPT_PTR(support_critical_angle);
|
||||
OPT_PTR(support_max_bridge_length);
|
||||
OPT_PTR(support_max_pillar_link_distance);
|
||||
OPT_PTR(support_points_density_relative);
|
||||
OPT_PTR(support_points_minimal_distance);
|
||||
OPT_PTR(support_object_elevation);
|
||||
@ -1302,72 +1284,32 @@ protected:
|
||||
#undef STATIC_PRINT_CONFIG_CACHE_DERIVED
|
||||
#undef OPT_PTR
|
||||
|
||||
class CLIConfigDef : public ConfigDef
|
||||
class CLIActionsConfigDef : public ConfigDef
|
||||
{
|
||||
public:
|
||||
CLIConfigDef();
|
||||
CLIActionsConfigDef();
|
||||
};
|
||||
|
||||
extern const CLIConfigDef cli_config_def;
|
||||
|
||||
#define OPT_PTR(KEY) if (opt_key == #KEY) return &this->KEY
|
||||
|
||||
class CLIConfig : public virtual ConfigBase, public StaticConfig
|
||||
class CLITransformConfigDef : public ConfigDef
|
||||
{
|
||||
public:
|
||||
ConfigOptionFloat cut;
|
||||
ConfigOptionString datadir;
|
||||
ConfigOptionBool dont_arrange;
|
||||
ConfigOptionBool export_3mf;
|
||||
ConfigOptionBool gui;
|
||||
ConfigOptionBool info;
|
||||
ConfigOptionBool help;
|
||||
ConfigOptionStrings load;
|
||||
ConfigOptionBool no_gui;
|
||||
ConfigOptionString output;
|
||||
ConfigOptionPoint print_center;
|
||||
ConfigOptionFloat rotate;
|
||||
ConfigOptionFloat rotate_x;
|
||||
ConfigOptionFloat rotate_y;
|
||||
ConfigOptionString save;
|
||||
ConfigOptionFloat scale;
|
||||
// ConfigOptionPoint3 scale_to_fit;
|
||||
ConfigOptionBool slice;
|
||||
|
||||
CLIConfig() : ConfigBase(), StaticConfig()
|
||||
{
|
||||
this->set_defaults();
|
||||
};
|
||||
|
||||
// Overrides ConfigBase::def(). Static configuration definition. Any value stored into this ConfigBase shall have its definition here.
|
||||
const ConfigDef* def() const override { return &cli_config_def; }
|
||||
t_config_option_keys keys() const override { return cli_config_def.keys(); }
|
||||
|
||||
ConfigOption* optptr(const t_config_option_key &opt_key, bool create = false) override
|
||||
{
|
||||
OPT_PTR(cut);
|
||||
OPT_PTR(datadir);
|
||||
OPT_PTR(dont_arrange);
|
||||
OPT_PTR(export_3mf);
|
||||
OPT_PTR(gui);
|
||||
OPT_PTR(help);
|
||||
OPT_PTR(info);
|
||||
OPT_PTR(load);
|
||||
OPT_PTR(no_gui);
|
||||
OPT_PTR(output);
|
||||
OPT_PTR(print_center);
|
||||
OPT_PTR(rotate);
|
||||
OPT_PTR(rotate_x);
|
||||
OPT_PTR(rotate_y);
|
||||
OPT_PTR(save);
|
||||
OPT_PTR(scale);
|
||||
// OPT_PTR(scale_to_fit);
|
||||
OPT_PTR(slice);
|
||||
return NULL;
|
||||
}
|
||||
CLITransformConfigDef();
|
||||
};
|
||||
|
||||
#undef OPT_PTR
|
||||
class CLIMiscConfigDef : public ConfigDef
|
||||
{
|
||||
public:
|
||||
CLIMiscConfigDef();
|
||||
};
|
||||
|
||||
// This class defines the command line options representing actions.
|
||||
extern const CLIActionsConfigDef cli_actions_config_def;
|
||||
|
||||
// This class defines the command line options representing transforms.
|
||||
extern const CLITransformConfigDef cli_transform_config_def;
|
||||
|
||||
// This class defines all command line options that are not actions or transforms.
|
||||
extern const CLIMiscConfigDef cli_misc_config_def;
|
||||
|
||||
class DynamicPrintAndCLIConfig : public DynamicPrintConfig
|
||||
{
|
||||
@ -1390,19 +1332,16 @@ private:
|
||||
public:
|
||||
PrintAndCLIConfigDef() {
|
||||
this->options.insert(print_config_def.options.begin(), print_config_def.options.end());
|
||||
this->options.insert(cli_config_def.options.begin(), cli_config_def.options.end());
|
||||
this->options.insert(cli_actions_config_def.options.begin(), cli_actions_config_def.options.end());
|
||||
this->options.insert(cli_transform_config_def.options.begin(), cli_transform_config_def.options.end());
|
||||
this->options.insert(cli_misc_config_def.options.begin(), cli_misc_config_def.options.end());
|
||||
}
|
||||
// Do not release the default values, they are handled by print_config_def & cli_config_def.
|
||||
// Do not release the default values, they are handled by print_config_def & cli_actions_config_def / cli_transform_config_def / cli_misc_config_def.
|
||||
~PrintAndCLIConfigDef() { this->options.clear(); }
|
||||
};
|
||||
static PrintAndCLIConfigDef s_def;
|
||||
};
|
||||
|
||||
/// Iterate through all of the print options and write them to a stream.
|
||||
std::ostream& print_print_options(std::ostream& out);
|
||||
/// Iterate through all of the CLI options and write them to a stream.
|
||||
std::ostream& print_cli_options(std::ostream& out);
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif
|
||||
|
@ -104,7 +104,7 @@ void PrintObject::slice()
|
||||
return;
|
||||
m_print->set_status(10, "Processing triangulated mesh");
|
||||
std::vector<coordf_t> layer_height_profile;
|
||||
this->update_layer_height_profile(*this->model_object(), this->slicing_parameters(), layer_height_profile);
|
||||
this->update_layer_height_profile(*this->model_object(), m_slicing_params, layer_height_profile);
|
||||
m_print->throw_if_canceled();
|
||||
this->_slice(layer_height_profile);
|
||||
m_print->throw_if_canceled();
|
||||
@ -608,8 +608,11 @@ bool PrintObject::invalidate_step(PrintObjectStep step)
|
||||
} else if (step == posSlice) {
|
||||
invalidated |= this->invalidate_steps({ posPerimeters, posPrepareInfill, posInfill, posSupportMaterial });
|
||||
invalidated |= m_print->invalidate_steps({ psSkirt, psBrim });
|
||||
} else if (step == posSupportMaterial)
|
||||
this->m_slicing_params.valid = false;
|
||||
} else if (step == posSupportMaterial) {
|
||||
invalidated |= m_print->invalidate_steps({ psSkirt, psBrim });
|
||||
this->m_slicing_params.valid = false;
|
||||
}
|
||||
|
||||
// Wipe tower depends on the ordering of extruders, which in turn depends on everything.
|
||||
// It also decides about what the wipe_into_infill / wipe_into_object features will do,
|
||||
@ -1065,7 +1068,7 @@ void PrintObject::process_external_surfaces()
|
||||
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) {
|
||||
m_print->throw_if_canceled();
|
||||
// BOOST_LOG_TRIVIAL(trace) << "Processing external surface, layer" << m_layers[layer_idx]->print_z;
|
||||
m_layers[layer_idx]->get_region(region_id)->process_external_surfaces((layer_idx == 0) ? NULL : m_layers[layer_idx - 1]);
|
||||
m_layers[layer_idx]->get_region((int)region_id)->process_external_surfaces((layer_idx == 0) ? NULL : m_layers[layer_idx - 1]);
|
||||
}
|
||||
}
|
||||
);
|
||||
@ -1684,11 +1687,11 @@ PrintRegionConfig PrintObject::region_config_from_model_volume(const PrintRegion
|
||||
return config;
|
||||
}
|
||||
|
||||
SlicingParameters PrintObject::slicing_parameters() const
|
||||
void PrintObject::update_slicing_parameters()
|
||||
{
|
||||
return SlicingParameters::create_from_config(
|
||||
this->print()->config(), m_config,
|
||||
unscale<double>(this->size(2)), this->object_extruders());
|
||||
if (! m_slicing_params.valid)
|
||||
m_slicing_params = SlicingParameters::create_from_config(
|
||||
this->print()->config(), m_config, unscale<double>(this->size(2)), this->object_extruders());
|
||||
}
|
||||
|
||||
SlicingParameters PrintObject::slicing_parameters(const DynamicPrintConfig &full_config, const ModelObject &model_object)
|
||||
@ -1775,23 +1778,21 @@ void PrintObject::_slice(const std::vector<coordf_t> &layer_height_profile)
|
||||
tbb_init = new tbb::task_scheduler_init(1);
|
||||
#endif
|
||||
|
||||
SlicingParameters slicing_params = this->slicing_parameters();
|
||||
|
||||
// 1) Initialize layers and their slice heights.
|
||||
std::vector<float> slice_zs;
|
||||
{
|
||||
this->clear_layers();
|
||||
// Object layers (pairs of bottom/top Z coordinate), without the raft.
|
||||
std::vector<coordf_t> object_layers = generate_object_layers(slicing_params, layer_height_profile);
|
||||
std::vector<coordf_t> object_layers = generate_object_layers(m_slicing_params, layer_height_profile);
|
||||
// Reserve object layers for the raft. Last layer of the raft is the contact layer.
|
||||
int id = int(slicing_params.raft_layers());
|
||||
int id = int(m_slicing_params.raft_layers());
|
||||
slice_zs.reserve(object_layers.size());
|
||||
Layer *prev = nullptr;
|
||||
for (size_t i_layer = 0; i_layer < object_layers.size(); i_layer += 2) {
|
||||
coordf_t lo = object_layers[i_layer];
|
||||
coordf_t hi = object_layers[i_layer + 1];
|
||||
coordf_t slice_z = 0.5 * (lo + hi);
|
||||
Layer *layer = this->add_layer(id ++, hi - lo, hi + slicing_params.object_print_z_min, slice_z);
|
||||
Layer *layer = this->add_layer(id ++, hi - lo, hi + m_slicing_params.object_print_z_min, slice_z);
|
||||
slice_zs.push_back(float(slice_z));
|
||||
if (prev != nullptr) {
|
||||
prev->upper_layer = layer;
|
||||
@ -1803,46 +1804,151 @@ void PrintObject::_slice(const std::vector<coordf_t> &layer_height_profile)
|
||||
prev = layer;
|
||||
}
|
||||
}
|
||||
|
||||
// Count model parts and modifier meshes, check whether the model parts are of the same region.
|
||||
int single_volume_region = -2; // not set yet
|
||||
size_t num_volumes = 0;
|
||||
size_t num_modifiers = 0;
|
||||
std::vector<int> map_volume_to_region(this->model_object()->volumes.size());
|
||||
for (int region_id = 0; region_id < (int)this->region_volumes.size(); ++ region_id) {
|
||||
for (int volume_id : this->region_volumes[region_id]) {
|
||||
const ModelVolume *model_volume = this->model_object()->volumes[volume_id];
|
||||
if (model_volume->is_model_part()) {
|
||||
map_volume_to_region[volume_id] = region_id;
|
||||
if (single_volume_region == -2)
|
||||
// first model volume met
|
||||
single_volume_region = region_id;
|
||||
else if (single_volume_region != region_id)
|
||||
// multiple volumes met and they are not equal
|
||||
single_volume_region = -1;
|
||||
++ num_volumes;
|
||||
} else if (model_volume->is_modifier())
|
||||
++ num_modifiers;
|
||||
}
|
||||
}
|
||||
assert(num_volumes > 0);
|
||||
|
||||
// Slice all non-modifier volumes.
|
||||
for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - region " << region_id;
|
||||
std::vector<ExPolygons> expolygons_by_layer = this->_slice_region(region_id, slice_zs, false);
|
||||
m_print->throw_if_canceled();
|
||||
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - append slices " << region_id << " start";
|
||||
for (size_t layer_id = 0; layer_id < expolygons_by_layer.size(); ++ layer_id)
|
||||
m_layers[layer_id]->regions()[region_id]->slices.append(std::move(expolygons_by_layer[layer_id]), stPosInternal | stDensSparse);
|
||||
m_print->throw_if_canceled();
|
||||
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - append slices " << region_id << " end";
|
||||
bool clipped = false;
|
||||
bool upscaled = false;
|
||||
if (! m_config.clip_multipart_objects.value || single_volume_region >= 0) {
|
||||
// Cheap path: Slice regions without mutual clipping.
|
||||
// The cheap path is possible if no clipping is allowed or if slicing volumes of just a single region.
|
||||
for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - region " << region_id;
|
||||
// slicing in parallel
|
||||
std::vector<ExPolygons> expolygons_by_layer = this->_slice_region(region_id, slice_zs, false);
|
||||
m_print->throw_if_canceled();
|
||||
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - append slices " << region_id << " start";
|
||||
for (size_t layer_id = 0; layer_id < expolygons_by_layer.size(); ++ layer_id)
|
||||
m_layers[layer_id]->regions()[region_id]->slices.append(std::move(expolygons_by_layer[layer_id]), stPosInternal | stDensSparse);
|
||||
m_print->throw_if_canceled();
|
||||
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - append slices " << region_id << " end";
|
||||
}
|
||||
} else {
|
||||
// Expensive path: Slice one volume after the other in the order they are presented at the user interface,
|
||||
// clip the last volumes with the first.
|
||||
// First slice the volumes.
|
||||
struct SlicedVolume {
|
||||
SlicedVolume(int volume_id, int region_id, std::vector<ExPolygons> &&expolygons_by_layer) :
|
||||
volume_id(volume_id), region_id(region_id), expolygons_by_layer(std::move(expolygons_by_layer)) {}
|
||||
int volume_id;
|
||||
int region_id;
|
||||
std::vector<ExPolygons> expolygons_by_layer;
|
||||
};
|
||||
std::vector<SlicedVolume> sliced_volumes;
|
||||
sliced_volumes.reserve(num_volumes);
|
||||
for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id)
|
||||
for (int volume_id : this->region_volumes[region_id]) {
|
||||
const ModelVolume *model_volume = this->model_object()->volumes[volume_id];
|
||||
if (model_volume->is_model_part()) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - volume " << volume_id;
|
||||
// slicing in parallel
|
||||
sliced_volumes.emplace_back(volume_id, map_volume_to_region[volume_id], this->_slice_volume(slice_zs, *model_volume));
|
||||
}
|
||||
}
|
||||
// Second clip the volumes in the order they are presented at the user interface.
|
||||
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - parallel clipping - start";
|
||||
tbb::parallel_for(
|
||||
tbb::blocked_range<size_t>(0, slice_zs.size()),
|
||||
[this, &sliced_volumes, num_modifiers](const tbb::blocked_range<size_t>& range) {
|
||||
float delta = float(scale_(m_config.xy_size_compensation.value));
|
||||
// Only upscale together with clipping if there are no modifiers, as the modifiers shall be applied before upscaling
|
||||
// (upscaling may grow the object outside of the modifier mesh).
|
||||
bool upscale = delta > 0 && num_modifiers == 0;
|
||||
for (size_t layer_id = range.begin(); layer_id < range.end(); ++ layer_id) {
|
||||
m_print->throw_if_canceled();
|
||||
// Trim volumes in a single layer, one by the other, possibly apply upscaling.
|
||||
{
|
||||
Polygons processed;
|
||||
for (SlicedVolume &sliced_volume : sliced_volumes) {
|
||||
ExPolygons slices = std::move(sliced_volume.expolygons_by_layer[layer_id]);
|
||||
if (upscale)
|
||||
slices = offset_ex(std::move(slices), delta);
|
||||
if (! processed.empty())
|
||||
// Trim by the slices of already processed regions.
|
||||
slices = diff_ex(to_polygons(std::move(slices)), processed);
|
||||
if (size_t(&sliced_volume - &sliced_volumes.front()) + 1 < sliced_volumes.size())
|
||||
// Collect the already processed regions to trim the to be processed regions.
|
||||
polygons_append(processed, slices);
|
||||
sliced_volume.expolygons_by_layer[layer_id] = std::move(slices);
|
||||
}
|
||||
}
|
||||
// Collect and union volumes of a single region.
|
||||
for (int region_id = 0; region_id < (int)this->region_volumes.size(); ++ region_id) {
|
||||
ExPolygons expolygons;
|
||||
size_t num_volumes = 0;
|
||||
for (SlicedVolume &sliced_volume : sliced_volumes)
|
||||
if (sliced_volume.region_id == region_id && ! sliced_volume.expolygons_by_layer[layer_id].empty()) {
|
||||
++ num_volumes;
|
||||
append(expolygons, std::move(sliced_volume.expolygons_by_layer[layer_id]));
|
||||
}
|
||||
if (num_volumes > 1)
|
||||
// Merge the islands using a positive / negative offset.
|
||||
expolygons = offset_ex(offset_ex(expolygons, float(scale_(EPSILON))), -float(scale_(EPSILON)));
|
||||
m_layers[layer_id]->regions()[region_id]->slices.append(std::move(expolygons), stPosInternal | stDensSparse);
|
||||
}
|
||||
}
|
||||
});
|
||||
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - parallel clipping - end";
|
||||
clipped = true;
|
||||
upscaled = m_config.xy_size_compensation.value > 0 && num_modifiers == 0;
|
||||
}
|
||||
|
||||
// Slice all modifier volumes.
|
||||
if (this->region_volumes.size() > 1) {
|
||||
for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "Slicing modifier volumes - region " << region_id;
|
||||
// slicing in parallel
|
||||
std::vector<ExPolygons> expolygons_by_layer = this->_slice_region(region_id, slice_zs, true);
|
||||
m_print->throw_if_canceled();
|
||||
if (expolygons_by_layer.empty())
|
||||
continue;
|
||||
// loop through the other regions and 'steal' the slices belonging to this one
|
||||
BOOST_LOG_TRIVIAL(debug) << "Slicing modifier volumes - stealing " << region_id << " start";
|
||||
for (size_t other_region_id = 0; other_region_id < this->region_volumes.size(); ++ other_region_id) {
|
||||
if (region_id == other_region_id)
|
||||
continue;
|
||||
for (size_t layer_id = 0; layer_id < expolygons_by_layer.size(); ++ layer_id) {
|
||||
Layer *layer = m_layers[layer_id];
|
||||
LayerRegion *layerm = layer->m_regions[region_id];
|
||||
LayerRegion *other_layerm = layer->m_regions[other_region_id];
|
||||
if (layerm == nullptr || other_layerm == nullptr)
|
||||
continue;
|
||||
Polygons other_slices = to_polygons(other_layerm->slices);
|
||||
ExPolygons my_parts = intersection_ex(other_slices, to_polygons(expolygons_by_layer[layer_id]));
|
||||
if (my_parts.empty())
|
||||
continue;
|
||||
// Remove such parts from original region.
|
||||
other_layerm->slices.set(diff_ex(other_slices, to_polygons(my_parts)), stPosInternal | stDensSparse);
|
||||
// Append new parts to our region.
|
||||
layerm->slices.append(std::move(my_parts), stPosInternal | stDensSparse);
|
||||
}
|
||||
}
|
||||
tbb::parallel_for(
|
||||
tbb::blocked_range<size_t>(0, m_layers.size()),
|
||||
[this, &expolygons_by_layer, region_id](const tbb::blocked_range<size_t>& range) {
|
||||
for (size_t layer_id = range.begin(); layer_id < range.end(); ++ layer_id) {
|
||||
for (size_t other_region_id = 0; other_region_id < this->region_volumes.size(); ++ other_region_id) {
|
||||
if (region_id == other_region_id)
|
||||
continue;
|
||||
Layer *layer = m_layers[layer_id];
|
||||
LayerRegion *layerm = layer->m_regions[region_id];
|
||||
LayerRegion *other_layerm = layer->m_regions[other_region_id];
|
||||
if (layerm == nullptr || other_layerm == nullptr)
|
||||
continue;
|
||||
Polygons other_slices = to_polygons(other_layerm->slices);
|
||||
ExPolygons my_parts = intersection_ex(other_slices, to_polygons(expolygons_by_layer[layer_id]));
|
||||
if (my_parts.empty())
|
||||
continue;
|
||||
// Remove such parts from original region.
|
||||
other_layerm->slices.set(diff_ex(other_slices, to_polygons(my_parts)), stPosInternal | stDensSparse);
|
||||
// Append new parts to our region.
|
||||
layerm->slices.append(std::move(my_parts), stPosInternal | stDensSparse);
|
||||
}
|
||||
}
|
||||
});
|
||||
m_print->throw_if_canceled();
|
||||
BOOST_LOG_TRIVIAL(debug) << "Slicing modifier volumes - stealing " << region_id << " end";
|
||||
}
|
||||
@ -1865,43 +1971,97 @@ end:
|
||||
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - make_slices in parallel - begin";
|
||||
tbb::parallel_for(
|
||||
tbb::blocked_range<size_t>(0, m_layers.size()),
|
||||
[this](const tbb::blocked_range<size_t>& range) {
|
||||
[this, upscaled, clipped](const tbb::blocked_range<size_t>& range) {
|
||||
for (size_t layer_id = range.begin(); layer_id < range.end(); ++ layer_id) {
|
||||
m_print->throw_if_canceled();
|
||||
Layer *layer = m_layers[layer_id];
|
||||
// Apply size compensation and perform clipping of multi-part objects.
|
||||
float delta = float(scale_(m_config.xy_size_compensation.value));
|
||||
float hole_delta = float(scale_(this->config().hole_size_compensation.value));
|
||||
float elephant_foot_compensation = 0.f;
|
||||
if (layer_id == 0)
|
||||
delta += float(scale_(m_config.elefant_foot_compensation.value));
|
||||
bool scale = delta != 0.f;
|
||||
bool clip = m_config.clip_multipart_objects.value || delta > 0.f;
|
||||
elephant_foot_compensation = float(scale_(m_config.elefant_foot_compensation.value));
|
||||
if (layer->m_regions.size() == 1) {
|
||||
if (scale) {
|
||||
// Optimized version for a single region layer.
|
||||
if (layer_id == 0) {
|
||||
if (delta > elephant_foot_compensation) {
|
||||
delta -= elephant_foot_compensation;
|
||||
elephant_foot_compensation = 0.f;
|
||||
} else if (delta > 0)
|
||||
elephant_foot_compensation -= delta;
|
||||
}
|
||||
if (delta != 0.f || elephant_foot_compensation > 0.f) {
|
||||
// Single region, growing or shrinking.
|
||||
LayerRegion *layerm = layer->m_regions.front();
|
||||
layerm->slices.set(offset_ex(to_expolygons(std::move(layerm->slices.surfaces)), delta), stPosInternal | stDensSparse);
|
||||
// Apply the XY compensation.
|
||||
ExPolygons expolygons = (delta == 0.f) ?
|
||||
to_expolygons(std::move(layerm->slices.surfaces)) :
|
||||
offset_ex(to_expolygons(std::move(layerm->slices.surfaces)), delta);
|
||||
// Apply the elephant foot compensation.
|
||||
if (elephant_foot_compensation > 0) {
|
||||
float elephant_foot_spacing = float(layerm->flow(frExternalPerimeter).scaled_elephant_foot_spacing());
|
||||
float external_perimeter_nozzle = float(scale_(this->print()->config().nozzle_diameter.get_at(layerm->region()->config().perimeter_extruder.value - 1)));
|
||||
// Apply the elephant foot compensation by steps of 1/10 nozzle diameter.
|
||||
float steps = std::ceil(elephant_foot_compensation / (0.1f * external_perimeter_nozzle));
|
||||
size_t nsteps = size_t(steps);
|
||||
float step = elephant_foot_compensation / steps;
|
||||
for (size_t i = 0; i < nsteps; ++ i) {
|
||||
Polygons tmp = offset(expolygons, - step);
|
||||
append(tmp, diff(to_polygons(expolygons), offset(offset_ex(expolygons, -elephant_foot_spacing - step), elephant_foot_spacing + step)));
|
||||
expolygons = union_ex(tmp);
|
||||
}
|
||||
}
|
||||
layerm->slices.set(std::move(expolygons), stPosInternal | stDensSparse);
|
||||
}
|
||||
_offset_holes(hole_delta, layer->regions().front());
|
||||
_smooth_curves(layer->regions().front());
|
||||
} else if (scale || clip || hole_delta != 0.f) {
|
||||
// Multiple regions, growing, shrinking or just clipping one region by the other.
|
||||
// When clipping the regions, priority is given to the first regions.
|
||||
Polygons processed;
|
||||
for (size_t region_id = 0; region_id < layer->m_regions.size(); ++ region_id) {
|
||||
LayerRegion *layerm = layer->m_regions[region_id];
|
||||
ExPolygons slices = to_expolygons(std::move(layerm->slices.surfaces));
|
||||
if (scale)
|
||||
slices = offset_ex(slices, delta);
|
||||
if (region_id > 0 && clip)
|
||||
// Trim by the slices of already processed regions.
|
||||
slices = diff_ex(to_polygons(std::move(slices)), processed);
|
||||
if (clip && region_id + 1 < layer->m_regions.size())
|
||||
// Collect the already processed regions to trim the to be processed regions.
|
||||
polygons_append(processed, slices);
|
||||
layerm->slices.set(std::move(slices), stPosInternal | stDensSparse);
|
||||
_offset_holes(hole_delta, layerm);
|
||||
_smooth_curves(layerm);
|
||||
} else {
|
||||
bool upscale = ! upscaled && delta > 0.f;
|
||||
bool clip = ! clipped && m_config.clip_multipart_objects.value;
|
||||
if (upscale || clip || hole_delta != 0.f) {
|
||||
// Multiple regions, growing or just clipping one region by the other.
|
||||
// When clipping the regions, priority is given to the first regions.
|
||||
Polygons processed;
|
||||
for (size_t region_id = 0; region_id < layer->m_regions.size(); ++ region_id) {
|
||||
LayerRegion *layerm = layer->m_regions[region_id];
|
||||
ExPolygons slices = to_expolygons(std::move(layerm->slices.surfaces));
|
||||
if (upscale)
|
||||
slices = offset_ex(std::move(slices), delta);
|
||||
if (region_id > 0 && clip)
|
||||
// Trim by the slices of already processed regions.
|
||||
slices = diff_ex(to_polygons(std::move(slices)), processed);
|
||||
if (clip && (region_id + 1 < layer->m_regions.size()))
|
||||
// Collect the already processed regions to trim the to be processed regions.
|
||||
polygons_append(processed, slices);
|
||||
layerm->slices.set(std::move(slices), stPosInternal | stDensSparse);
|
||||
}
|
||||
}
|
||||
if (delta < 0.f) {
|
||||
// Apply the negative XY compensation.
|
||||
Polygons trimming = offset(layer->merged(float(EPSILON)), delta - float(EPSILON));
|
||||
for (size_t region_id = 0; region_id < layer->m_regions.size(); ++ region_id)
|
||||
layer->m_regions[region_id]->trim_surfaces(trimming);
|
||||
}
|
||||
if (elephant_foot_compensation > 0.f) {
|
||||
// Apply the elephant foot compensation.
|
||||
std::vector<float> elephant_foot_spacing;
|
||||
elephant_foot_spacing.reserve(layer->m_regions.size());
|
||||
float external_perimeter_nozzle = 0.f;
|
||||
for (size_t region_id = 0; region_id < layer->m_regions.size(); ++ region_id) {
|
||||
LayerRegion *layerm = layer->m_regions[region_id];
|
||||
elephant_foot_spacing.emplace_back(float(layerm->flow(frExternalPerimeter).scaled_elephant_foot_spacing()));
|
||||
external_perimeter_nozzle += float(scale_(this->print()->config().nozzle_diameter.get_at(layerm->region()->config().perimeter_extruder.value - 1)));
|
||||
}
|
||||
external_perimeter_nozzle /= (float)layer->m_regions.size();
|
||||
// Apply the elephant foot compensation by steps of 1/10 nozzle diameter.
|
||||
float steps = std::ceil(elephant_foot_compensation / (0.1f * external_perimeter_nozzle));
|
||||
size_t nsteps = size_t(steps);
|
||||
float step = elephant_foot_compensation / steps;
|
||||
for (size_t i = 0; i < nsteps; ++ i) {
|
||||
Polygons trimming_polygons = offset(layer->merged(float(EPSILON)), - step - float(EPSILON));
|
||||
for (size_t region_id = 0; region_id < layer->m_regions.size(); ++ region_id)
|
||||
layer->m_regions[region_id]->elephant_foot_compensation_step(elephant_foot_spacing[region_id] + step, trimming_polygons);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Merge all regions' slices to get islands, chain them by a shortest path.
|
||||
@ -2109,6 +2269,28 @@ std::vector<ExPolygons> PrintObject::_slice_volumes(const std::vector<float> &z,
|
||||
return layers;
|
||||
}
|
||||
|
||||
std::vector<ExPolygons> PrintObject::_slice_volume(const std::vector<float> &z, const ModelVolume &volume) const
|
||||
{
|
||||
std::vector<ExPolygons> layers;
|
||||
// Compose mesh.
|
||||
//FIXME better to perform slicing over each volume separately and then to use a Boolean operation to merge them.
|
||||
TriangleMesh mesh(volume.mesh);
|
||||
mesh.transform(volume.get_matrix());
|
||||
if (mesh.stl.stats.number_of_facets > 0) {
|
||||
mesh.transform(m_trafo);
|
||||
// apply XY shift
|
||||
mesh.translate(- unscale<float>(m_copies_shift(0)), - unscale<float>(m_copies_shift(1)), 0);
|
||||
// perform actual slicing
|
||||
TriangleMeshSlicer mslicer(float(m_config.slice_closing_radius.value), float(m_config.model_precision.value));
|
||||
const Print *print = this->print();
|
||||
auto callback = TriangleMeshSlicer::throw_on_cancel_callback_type([print](){print->throw_if_canceled();});
|
||||
mslicer.init(&mesh, callback);
|
||||
mslicer.slice(z, &layers, callback);
|
||||
m_print->throw_if_canceled();
|
||||
}
|
||||
return layers;
|
||||
}
|
||||
|
||||
std::string PrintObject::_fix_slicing_errors()
|
||||
{
|
||||
// Collect layers with slicing errors.
|
||||
@ -2708,7 +2890,7 @@ void PrintObject::combine_infill()
|
||||
|
||||
void PrintObject::_generate_support_material()
|
||||
{
|
||||
PrintObjectSupportMaterial support_material(this, PrintObject::slicing_parameters());
|
||||
PrintObjectSupportMaterial support_material(this, m_slicing_params);
|
||||
support_material.generate(*this);
|
||||
}
|
||||
|
||||
|
@ -496,7 +496,7 @@ void SLAAutoSupports::uniformly_cover(const ExPolygons& islands, Structure& stru
|
||||
poisson_samples.erase(poisson_samples.begin() + poisson_samples_target, poisson_samples.end());
|
||||
}
|
||||
for (const Vec2f &pt : poisson_samples) {
|
||||
m_output.emplace_back(float(pt(0)), float(pt(1)), structure.height, 0.2f, is_new_island);
|
||||
m_output.emplace_back(float(pt(0)), float(pt(1)), structure.height, m_config.head_diameter/2.f, is_new_island);
|
||||
structure.supports_force_this_layer += m_config.support_force();
|
||||
grid3d.insert(pt, &structure);
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ public:
|
||||
struct Config {
|
||||
float density_relative;
|
||||
float minimal_distance;
|
||||
float head_diameter;
|
||||
///////////////
|
||||
inline float support_force() const { return 10.f / density_relative; } // a force one point can support (arbitrary force unit)
|
||||
inline float tear_pressure() const { return 1.f; } // pressure that the display exerts (the force unit per mm2)
|
||||
|
@ -601,14 +601,16 @@ void create_base_pool(const ExPolygons &ground_layer, TriangleMesh& out,
|
||||
const double thickness = cfg.min_wall_thickness_mm;
|
||||
const double wingheight = cfg.min_wall_height_mm;
|
||||
const double fullheight = wingheight + thickness;
|
||||
const double slope = cfg.wall_slope;
|
||||
const double slope = cfg.wall_slope;
|
||||
const double wingdist = wingheight / std::tan(slope);
|
||||
const double bottom_offs = (thickness + wingheight) / std::tan(slope);
|
||||
|
||||
// scaled values
|
||||
const coord_t s_thickness = mm(thickness);
|
||||
const coord_t s_eradius = mm(cfg.edge_radius_mm);
|
||||
const coord_t s_safety_dist = 2*s_eradius + coord_t(0.8*s_thickness);
|
||||
const coord_t s_wingdist = mm(wingdist);
|
||||
const coord_t s_bottom_offs = mm(bottom_offs);
|
||||
|
||||
auto& thrcl = cfg.throw_on_cancel;
|
||||
|
||||
@ -620,7 +622,7 @@ void create_base_pool(const ExPolygons &ground_layer, TriangleMesh& out,
|
||||
// Get rid of any holes in the concave hull output.
|
||||
concaveh.holes.clear();
|
||||
|
||||
// Here lies the trick that does the smooting only with clipper offset
|
||||
// Here lies the trick that does the smoothing only with clipper offset
|
||||
// calls. The offset is configured to round edges. Inner edges will
|
||||
// be rounded because we offset twice: ones to get the outer (top) plate
|
||||
// and again to get the inner (bottom) plate
|
||||
@ -628,10 +630,9 @@ void create_base_pool(const ExPolygons &ground_layer, TriangleMesh& out,
|
||||
outer_base.holes.clear();
|
||||
offset(outer_base, s_safety_dist + s_wingdist + s_thickness);
|
||||
|
||||
|
||||
ExPolygon bottom_poly = outer_base;
|
||||
bottom_poly.holes.clear();
|
||||
if(s_wingdist > 0) offset(bottom_poly, -s_wingdist);
|
||||
offset(bottom_poly, -s_bottom_offs);
|
||||
|
||||
// Punching a hole in the top plate for the cavity
|
||||
ExPolygon top_poly;
|
||||
@ -692,7 +693,7 @@ void create_base_pool(const ExPolygons &ground_layer, TriangleMesh& out,
|
||||
// Now that we have the rounded edge connecting the top plate with
|
||||
// the outer side walls, we can generate and merge the sidewall geometry
|
||||
pool.merge(walls(ob.contour, bottom_poly.contour, wh, -fullheight,
|
||||
wingdist, thrcl));
|
||||
bottom_offs, thrcl));
|
||||
|
||||
if(wingheight > 0) {
|
||||
// Generate the smoothed edge geometry
|
||||
|
@ -2,6 +2,7 @@
|
||||
#define SLACOMMON_HPP
|
||||
|
||||
#include <Eigen/Geometry>
|
||||
#include <memory>
|
||||
|
||||
// #define SLIC3R_SLA_NEEDS_WINDTREE
|
||||
|
||||
@ -44,7 +45,6 @@ struct SupportPoint {
|
||||
bool operator!=(const SupportPoint& sp) const { return !(sp == (*this)); }
|
||||
};
|
||||
|
||||
|
||||
/// An index-triangle structure for libIGL functions. Also serves as an
|
||||
/// alternative (raw) input format for the SLASupportTree
|
||||
/*struct EigenMesh3D {
|
||||
@ -78,24 +78,38 @@ public:
|
||||
|
||||
// Result of a raycast
|
||||
class hit_result {
|
||||
double m_t = std::numeric_limits<double>::infinity();
|
||||
double m_t = std::nan("");
|
||||
int m_face_id = -1;
|
||||
const EigenMesh3D& m_mesh;
|
||||
const EigenMesh3D *m_mesh = nullptr;
|
||||
Vec3d m_dir;
|
||||
inline hit_result(const EigenMesh3D& em): m_mesh(em) {}
|
||||
Vec3d m_source;
|
||||
friend class EigenMesh3D;
|
||||
|
||||
// A valid object of this class can only be obtained from
|
||||
// EigenMesh3D::query_ray_hit method.
|
||||
explicit inline hit_result(const EigenMesh3D& em): m_mesh(&em) {}
|
||||
public:
|
||||
|
||||
// This can create a placeholder object which is invalid (not created
|
||||
// by a query_ray_hit call) but the distance can be preset to
|
||||
// a specific value for distinguishing the placeholder.
|
||||
inline hit_result(double val = std::nan("")): m_t(val) {}
|
||||
|
||||
inline double distance() const { return m_t; }
|
||||
inline const Vec3d& direction() const { return m_dir; }
|
||||
inline Vec3d position() const { return m_source + m_dir * m_t; }
|
||||
inline int face() const { return m_face_id; }
|
||||
inline bool is_valid() const { return m_mesh != nullptr; }
|
||||
|
||||
// Hit_result can decay into a double as the hit distance.
|
||||
inline operator double() const { return distance(); }
|
||||
|
||||
inline Vec3d normal() const {
|
||||
if(m_face_id < 0) return {};
|
||||
auto trindex = m_mesh.m_F.row(m_face_id);
|
||||
const Vec3d& p1 = m_mesh.V().row(trindex(0));
|
||||
const Vec3d& p2 = m_mesh.V().row(trindex(1));
|
||||
const Vec3d& p3 = m_mesh.V().row(trindex(2));
|
||||
if(m_face_id < 0 || !is_valid()) return {};
|
||||
auto trindex = m_mesh->m_F.row(m_face_id);
|
||||
const Vec3d& p1 = m_mesh->V().row(trindex(0));
|
||||
const Vec3d& p2 = m_mesh->V().row(trindex(1));
|
||||
const Vec3d& p3 = m_mesh->V().row(trindex(2));
|
||||
Eigen::Vector3d U = p2 - p1;
|
||||
Eigen::Vector3d V = p3 - p1;
|
||||
return U.cross(V).normalized();
|
||||
@ -133,6 +147,8 @@ public:
|
||||
|
||||
bool inside(const Vec3d& p) const;
|
||||
#endif /* SLIC3R_SLA_NEEDS_WINDTREE */
|
||||
|
||||
double squared_distance(const Vec3d& p, int& i, Vec3d& c) const;
|
||||
};
|
||||
|
||||
|
||||
@ -142,4 +158,4 @@ public:
|
||||
} // namespace Slic3r
|
||||
|
||||
|
||||
#endif // SLASUPPORTTREE_HPP
|
||||
#endif // SLASUPPORTTREE_HPP
|
||||
|
@ -43,6 +43,8 @@ public:
|
||||
// For testing
|
||||
size_t size() const;
|
||||
bool empty() const { return size() == 0; }
|
||||
|
||||
void foreach(std::function<void(const SpatElement& el)> fn);
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -50,11 +50,6 @@ struct SupportConfig {
|
||||
// Width in mm from the back sphere center to the front sphere center.
|
||||
double head_width_mm = 1.0;
|
||||
|
||||
// Radius in mm of the support pillars. The actual radius of the pillars
|
||||
// beginning with a head will not be higher than head_back_radius but the
|
||||
// headless pillars will have half of this value.
|
||||
double headless_pillar_radius_mm = 0.4;
|
||||
|
||||
// How to connect pillars
|
||||
PillarConnectionMode pillar_connection_mode = PillarConnectionMode::dynamic;
|
||||
|
||||
@ -74,18 +69,34 @@ struct SupportConfig {
|
||||
double base_height_mm = 1.0;
|
||||
|
||||
// The default angle for connecting support sticks and junctions.
|
||||
double tilt = M_PI/4;
|
||||
double bridge_slope = M_PI/4;
|
||||
|
||||
// The max length of a bridge in mm
|
||||
double max_bridge_length_mm = 15.0;
|
||||
double max_bridge_length_mm = 10.0;
|
||||
|
||||
// The max distance of a pillar to pillar link.
|
||||
double max_pillar_link_distance_mm = 10.0;
|
||||
|
||||
// The elevation in Z direction upwards. This is the space between the pad
|
||||
// and the model object's bounding box bottom.
|
||||
double object_elevation_mm = 10;
|
||||
|
||||
// The max Z angle for a normal at which it will get completely ignored.
|
||||
double normal_cutoff_angle = 150.0 * M_PI / 180.0;
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
// Compile time configuration values (candidates for runtime)
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// The max Z angle for a normal at which it will get completely ignored.
|
||||
static const double normal_cutoff_angle;
|
||||
|
||||
// The shortest distance of any support structure from the model surface
|
||||
static const double safety_distance_mm;
|
||||
|
||||
static const double max_solo_pillar_height_mm;
|
||||
static const double max_dual_pillar_height_mm;
|
||||
static const double optimizer_rel_score_diff;
|
||||
static const unsigned optimizer_max_iterations;
|
||||
static const unsigned pillar_cascade_neighbors;
|
||||
static const unsigned max_bridges_on_pillar;
|
||||
};
|
||||
|
||||
struct PoolConfig;
|
||||
@ -116,21 +127,14 @@ using PointSet = Eigen::MatrixXd;
|
||||
//EigenMesh3D to_eigenmesh(const ModelObject& model);
|
||||
|
||||
// Simple conversion of 'vector of points' to an Eigen matrix
|
||||
PointSet to_point_set(const std::vector<sla::SupportPoint>&);
|
||||
//PointSet to_point_set(const std::vector<sla::SupportPoint>&);
|
||||
|
||||
|
||||
/* ************************************************************************** */
|
||||
|
||||
/// Just a wrapper to the runtime error to be recognizable in try blocks
|
||||
class SLASupportsStoppedException: public std::runtime_error {
|
||||
public:
|
||||
using std::runtime_error::runtime_error;
|
||||
SLASupportsStoppedException();
|
||||
};
|
||||
|
||||
/// The class containing mesh data for the generated supports.
|
||||
class SLASupportTree {
|
||||
class Impl;
|
||||
class Impl; // persistent support data
|
||||
std::unique_ptr<Impl> m_impl;
|
||||
|
||||
Impl& get() { return *m_impl; }
|
||||
@ -140,16 +144,25 @@ class SLASupportTree {
|
||||
const SupportConfig&,
|
||||
const Controller&);
|
||||
|
||||
/// Generate the 3D supports for a model intended for SLA print.
|
||||
bool generate(const PointSet& pts,
|
||||
// The generation algorithm is quite long and will be captured in a separate
|
||||
// class with private data, helper methods, etc... This data is only needed
|
||||
// during the calculation whereas the Impl class contains the persistent
|
||||
// data, mostly the meshes.
|
||||
class Algorithm;
|
||||
|
||||
// Generate the 3D supports for a model intended for SLA print. This
|
||||
// will instantiate the Algorithm class and call its appropriate methods
|
||||
// with status indication.
|
||||
bool generate(const std::vector<SupportPoint>& pts,
|
||||
const EigenMesh3D& mesh,
|
||||
const SupportConfig& cfg = {},
|
||||
const Controller& ctl = {});
|
||||
|
||||
public:
|
||||
|
||||
SLASupportTree();
|
||||
|
||||
SLASupportTree(const PointSet& pts,
|
||||
SLASupportTree(const std::vector<SupportPoint>& pts,
|
||||
const EigenMesh3D& em,
|
||||
const SupportConfig& cfg = {},
|
||||
const Controller& ctl = {});
|
||||
@ -168,6 +181,8 @@ public:
|
||||
/// Get the sliced 2d layers of the support geometry.
|
||||
SlicedSupports slice(float layerh, float init_layerh = -1.0) const;
|
||||
|
||||
SlicedSupports slice(const std::vector<float>&, float closing_radius) const;
|
||||
|
||||
/// Adding the "pad" (base pool) under the supports
|
||||
const TriangleMesh& add_pad(const SliceLayer& baseplate,
|
||||
const PoolConfig& pcfg) const;
|
||||
|
@ -17,6 +17,8 @@
|
||||
#include <igl/remove_duplicate_vertices.h>
|
||||
#include <igl/signed_distance.h>
|
||||
|
||||
#include <tbb/parallel_for.h>
|
||||
|
||||
#include "SLASpatIndex.hpp"
|
||||
#include "ClipperUtils.hpp"
|
||||
|
||||
@ -89,6 +91,11 @@ size_t SpatIndex::size() const
|
||||
return m_impl->m_store.size();
|
||||
}
|
||||
|
||||
void SpatIndex::foreach(std::function<void (const SpatElement &)> fn)
|
||||
{
|
||||
for(auto& el : m_impl->m_store) fn(el);
|
||||
}
|
||||
|
||||
/* ****************************************************************************
|
||||
* EigenMesh3D implementation
|
||||
* ****************************************************************************/
|
||||
@ -167,6 +174,7 @@ EigenMesh3D::query_ray_hit(const Vec3d &s, const Vec3d &dir) const
|
||||
hit_result ret(*this);
|
||||
ret.m_t = double(hit.t);
|
||||
ret.m_dir = dir;
|
||||
ret.m_source = s;
|
||||
if(!std::isinf(hit.t) && !std::isnan(hit.t)) ret.m_face_id = hit.id;
|
||||
|
||||
return ret;
|
||||
@ -186,6 +194,15 @@ bool EigenMesh3D::inside(const Vec3d &p) const {
|
||||
}
|
||||
#endif /* SLIC3R_SLA_NEEDS_WINDTREE */
|
||||
|
||||
double EigenMesh3D::squared_distance(const Vec3d &p, int& i, Vec3d& c) const {
|
||||
double sqdst = 0;
|
||||
Eigen::Matrix<double, 1, 3> pp = p;
|
||||
Eigen::Matrix<double, 1, 3> cc;
|
||||
sqdst = m_aabb->squared_distance(m_V, m_F, pp, i, cc);
|
||||
c = cc;
|
||||
return sqdst;
|
||||
}
|
||||
|
||||
/* ****************************************************************************
|
||||
* Misc functions
|
||||
* ****************************************************************************/
|
||||
@ -208,22 +225,31 @@ template<class Vec> double distance(const Vec& pp1, const Vec& pp2) {
|
||||
PointSet normals(const PointSet& points,
|
||||
const EigenMesh3D& mesh,
|
||||
double eps,
|
||||
std::function<void()> throw_on_cancel)
|
||||
std::function<void()> thr, // throw on cancel
|
||||
const std::vector<unsigned>& pt_indices = {})
|
||||
{
|
||||
if(points.rows() == 0 || mesh.V().rows() == 0 || mesh.F().rows() == 0)
|
||||
return {};
|
||||
|
||||
Eigen::VectorXd dists;
|
||||
Eigen::VectorXi I;
|
||||
PointSet C;
|
||||
std::vector<unsigned> range = pt_indices;
|
||||
if(range.empty()) {
|
||||
range.resize(size_t(points.rows()), 0);
|
||||
std::iota(range.begin(), range.end(), 0);
|
||||
}
|
||||
|
||||
igl::point_mesh_squared_distance( points, mesh.V(), mesh.F(), dists, I, C);
|
||||
PointSet ret(range.size(), 3);
|
||||
|
||||
PointSet ret(I.rows(), 3);
|
||||
for(int i = 0; i < I.rows(); i++) {
|
||||
throw_on_cancel();
|
||||
auto idx = I(i);
|
||||
auto trindex = mesh.F().row(idx);
|
||||
tbb::parallel_for(size_t(0), range.size(),
|
||||
[&ret, &range, &mesh, &points, thr, eps](size_t ridx)
|
||||
{
|
||||
thr();
|
||||
auto eidx = Eigen::Index(range[ridx]);
|
||||
int faceid = 0;
|
||||
Vec3d p;
|
||||
|
||||
mesh.squared_distance(points.row(eidx), faceid, p);
|
||||
|
||||
auto trindex = mesh.F().row(faceid);
|
||||
|
||||
const Vec3d& p1 = mesh.V().row(trindex(0));
|
||||
const Vec3d& p2 = mesh.V().row(trindex(1));
|
||||
@ -237,8 +263,6 @@ PointSet normals(const PointSet& points,
|
||||
// of its triangle. The procedure is the same, get the neighbor
|
||||
// triangles and calculate an average normal.
|
||||
|
||||
const Vec3d& p = C.row(i);
|
||||
|
||||
// mark the vertex indices of the edge. ia and ib marks and edge ic
|
||||
// will mark a single vertex.
|
||||
int ia = -1, ib = -1, ic = -1;
|
||||
@ -266,7 +290,7 @@ PointSet normals(const PointSet& points,
|
||||
std::vector<Vec3i> neigh;
|
||||
if(ic >= 0) { // The point is right on a vertex of the triangle
|
||||
for(int n = 0; n < mesh.F().rows(); ++n) {
|
||||
throw_on_cancel();
|
||||
thr();
|
||||
Vec3i ni = mesh.F().row(n);
|
||||
if((ni(X) == ic || ni(Y) == ic || ni(Z) == ic))
|
||||
neigh.emplace_back(ni);
|
||||
@ -275,7 +299,7 @@ PointSet normals(const PointSet& points,
|
||||
else if(ia >= 0 && ib >= 0) { // the point is on and edge
|
||||
// now get all the neigboring triangles
|
||||
for(int n = 0; n < mesh.F().rows(); ++n) {
|
||||
throw_on_cancel();
|
||||
thr();
|
||||
Vec3i ni = mesh.F().row(n);
|
||||
if((ni(X) == ia || ni(Y) == ia || ni(Z) == ia) &&
|
||||
(ni(X) == ib || ni(Y) == ib || ni(Z) == ib))
|
||||
@ -316,52 +340,32 @@ PointSet normals(const PointSet& points,
|
||||
Vec3d sumnorm(0, 0, 0);
|
||||
sumnorm = std::accumulate(neighnorms.begin(), lend, sumnorm);
|
||||
sumnorm.normalize();
|
||||
ret.row(i) = sumnorm;
|
||||
ret.row(long(ridx)) = sumnorm;
|
||||
}
|
||||
else { // point lies safely within its triangle
|
||||
Eigen::Vector3d U = p2 - p1;
|
||||
Eigen::Vector3d V = p3 - p1;
|
||||
ret.row(i) = U.cross(V).normalized();
|
||||
ret.row(long(ridx)) = U.cross(V).normalized();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
namespace bgi = boost::geometry::index;
|
||||
using Index3D = bgi::rtree< SpatElement, bgi::rstar<16, 4> /* ? */ >;
|
||||
|
||||
// Clustering a set of points by the given criteria
|
||||
ClusteredPoints cluster(
|
||||
const sla::PointSet& points,
|
||||
std::function<bool(const SpatElement&, const SpatElement&)> pred,
|
||||
unsigned max_points = 0)
|
||||
ClusteredPoints cluster(Index3D& sindex, unsigned max_points,
|
||||
std::function<std::vector<SpatElement>(const Index3D&, const SpatElement&)> qfn)
|
||||
{
|
||||
|
||||
namespace bgi = boost::geometry::index;
|
||||
using Index3D = bgi::rtree< SpatElement, bgi::rstar<16, 4> /* ? */ >;
|
||||
|
||||
// A spatial index for querying the nearest points
|
||||
Index3D sindex;
|
||||
|
||||
// Build the index
|
||||
for(unsigned idx = 0; idx < points.rows(); idx++)
|
||||
sindex.insert( std::make_pair(points.row(idx), idx));
|
||||
|
||||
using Elems = std::vector<SpatElement>;
|
||||
|
||||
// Recursive function for visiting all the points in a given distance to
|
||||
// each other
|
||||
std::function<void(Elems&, Elems&)> group =
|
||||
[&sindex, &group, pred, max_points](Elems& pts, Elems& cluster)
|
||||
[&sindex, &group, max_points, qfn](Elems& pts, Elems& cluster)
|
||||
{
|
||||
for(auto& p : pts) {
|
||||
std::vector<SpatElement> tmp;
|
||||
|
||||
sindex.query(
|
||||
bgi::satisfies([p, pred](const SpatElement& se) {
|
||||
return pred(p, se);
|
||||
}),
|
||||
std::back_inserter(tmp)
|
||||
);
|
||||
|
||||
std::vector<SpatElement> tmp = qfn(sindex, p);
|
||||
auto cmp = [](const SpatElement& e1, const SpatElement& e2){
|
||||
return e1.second < e2.second;
|
||||
};
|
||||
@ -405,5 +409,84 @@ ClusteredPoints cluster(
|
||||
return result;
|
||||
}
|
||||
|
||||
namespace {
|
||||
std::vector<SpatElement> distance_queryfn(const Index3D& sindex,
|
||||
const SpatElement& p,
|
||||
double dist,
|
||||
unsigned max_points)
|
||||
{
|
||||
std::vector<SpatElement> tmp; tmp.reserve(max_points);
|
||||
sindex.query(
|
||||
bgi::nearest(p.first, max_points),
|
||||
std::back_inserter(tmp)
|
||||
);
|
||||
|
||||
for(auto it = tmp.begin(); it < tmp.end(); ++it)
|
||||
if(distance(p.first, it->first) > dist) it = tmp.erase(it);
|
||||
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
|
||||
// Clustering a set of points by the given criteria
|
||||
ClusteredPoints cluster(
|
||||
const std::vector<unsigned>& indices,
|
||||
std::function<Vec3d(unsigned)> pointfn,
|
||||
double dist,
|
||||
unsigned max_points)
|
||||
{
|
||||
// A spatial index for querying the nearest points
|
||||
Index3D sindex;
|
||||
|
||||
// Build the index
|
||||
for(auto idx : indices) sindex.insert( std::make_pair(pointfn(idx), idx));
|
||||
|
||||
return cluster(sindex, max_points,
|
||||
[dist, max_points](const Index3D& sidx, const SpatElement& p)
|
||||
{
|
||||
return distance_queryfn(sidx, p, dist, max_points);
|
||||
});
|
||||
}
|
||||
|
||||
// Clustering a set of points by the given criteria
|
||||
ClusteredPoints cluster(
|
||||
const std::vector<unsigned>& indices,
|
||||
std::function<Vec3d(unsigned)> pointfn,
|
||||
std::function<bool(const SpatElement&, const SpatElement&)> predicate,
|
||||
unsigned max_points)
|
||||
{
|
||||
// A spatial index for querying the nearest points
|
||||
Index3D sindex;
|
||||
|
||||
// Build the index
|
||||
for(auto idx : indices) sindex.insert( std::make_pair(pointfn(idx), idx));
|
||||
|
||||
return cluster(sindex, max_points,
|
||||
[max_points, predicate](const Index3D& sidx, const SpatElement& p)
|
||||
{
|
||||
std::vector<SpatElement> tmp; tmp.reserve(max_points);
|
||||
sidx.query(bgi::satisfies([p, predicate](const SpatElement& e){
|
||||
return predicate(p, e);
|
||||
}), std::back_inserter(tmp));
|
||||
return tmp;
|
||||
});
|
||||
}
|
||||
|
||||
ClusteredPoints cluster(const PointSet& pts, double dist, unsigned max_points)
|
||||
{
|
||||
// A spatial index for querying the nearest points
|
||||
Index3D sindex;
|
||||
|
||||
// Build the index
|
||||
for(Eigen::Index i = 0; i < pts.rows(); i++)
|
||||
sindex.insert(std::make_pair(Vec3d(pts.row(i)), unsigned(i)));
|
||||
|
||||
return cluster(sindex, max_points,
|
||||
[dist, max_points](const Index3D& sidx, const SpatElement& p)
|
||||
{
|
||||
return distance_queryfn(sidx, p, dist, max_points);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,6 @@ public:
|
||||
std::vector<sla::SupportPoint> support_points; // all the support points (manual/auto)
|
||||
SupportTreePtr support_tree_ptr; // the supports
|
||||
SlicedSupports support_slices; // sliced supports
|
||||
std::vector<LevelID> level_ids;
|
||||
|
||||
inline SupportData(const TriangleMesh& trmesh): emesh(trmesh) {}
|
||||
};
|
||||
@ -118,6 +117,9 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, const DynamicPrintConf
|
||||
|
||||
// Make a copy of the config, normalize it.
|
||||
DynamicPrintConfig config(config_in);
|
||||
config.option("sla_print_settings_id", true);
|
||||
config.option("sla_material_settings_id", true);
|
||||
config.option("printer_settings_id", true);
|
||||
config.normalize();
|
||||
// Collect changes to print config.
|
||||
t_config_option_keys print_diff = m_print_config.diff(config);
|
||||
@ -151,9 +153,9 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, const DynamicPrintConf
|
||||
PlaceholderParser &pp = this->placeholder_parser();
|
||||
pp.apply_config(config);
|
||||
// Set the profile aliases for the PrintBase::output_filename()
|
||||
pp.set("print_preset", config_in.option("sla_print_settings_id")->clone());
|
||||
pp.set("material_preset", config_in.option("sla_material_settings_id")->clone());
|
||||
pp.set("printer_preset", config_in.option("printer_settings_id")->clone());
|
||||
pp.set("print_preset", config.option("sla_print_settings_id")->clone());
|
||||
pp.set("material_preset", config.option("sla_material_settings_id")->clone());
|
||||
pp.set("printer_preset", config.option("printer_settings_id")->clone());
|
||||
}
|
||||
|
||||
// It is also safe to change m_config now after this->invalidate_state_by_config_options() call.
|
||||
@ -300,81 +302,82 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, const DynamicPrintConf
|
||||
auto it_status = model_object_status.find(ModelObjectStatus(model_object.id()));
|
||||
assert(it_status != model_object_status.end());
|
||||
assert(it_status->status != ModelObjectStatus::Deleted);
|
||||
if (it_status->status == ModelObjectStatus::New)
|
||||
// PrintObject instances will be added in the next loop.
|
||||
continue;
|
||||
// Update the ModelObject instance, possibly invalidate the linked PrintObjects.
|
||||
assert(it_status->status == ModelObjectStatus::Old || it_status->status == ModelObjectStatus::Moved);
|
||||
const ModelObject &model_object_new = *model.objects[idx_model_object];
|
||||
auto it_print_object_status = print_object_status.lower_bound(PrintObjectStatus(model_object.id()));
|
||||
if (it_print_object_status != print_object_status.end() && it_print_object_status->id != model_object.id())
|
||||
it_print_object_status = print_object_status.end();
|
||||
// Check whether a model part volume was added or removed, their transformations or order changed.
|
||||
bool model_parts_differ = model_volume_list_changed(model_object, model_object_new, ModelVolumeType::MODEL_PART);
|
||||
bool sla_trafo_differs = model_object.instances.empty() != model_object_new.instances.empty() ||
|
||||
(! model_object.instances.empty() && ! sla_trafo(model_object).isApprox(sla_trafo(model_object_new)));
|
||||
if (model_parts_differ || sla_trafo_differs) {
|
||||
// The very first step (the slicing step) is invalidated. One may freely remove all associated PrintObjects.
|
||||
if (it_print_object_status != print_object_status.end()) {
|
||||
update_apply_status(it_print_object_status->print_object->invalidate_all_steps());
|
||||
const_cast<PrintObjectStatus&>(*it_print_object_status).status = PrintObjectStatus::Deleted;
|
||||
}
|
||||
// Copy content of the ModelObject including its ID, do not change the parent.
|
||||
model_object.assign_copy(model_object_new);
|
||||
} else {
|
||||
// Synchronize Object's config.
|
||||
bool object_config_changed = model_object.config != model_object_new.config;
|
||||
if (object_config_changed)
|
||||
model_object.config = model_object_new.config;
|
||||
if (! object_diff.empty() || object_config_changed) {
|
||||
SLAPrintObjectConfig new_config = m_default_object_config;
|
||||
normalize_and_apply_config(new_config, model_object.config);
|
||||
if (it_print_object_status != print_object_status.end()) {
|
||||
t_config_option_keys diff = it_print_object_status->print_object->config().diff(new_config);
|
||||
if (! diff.empty()) {
|
||||
update_apply_status(it_print_object_status->print_object->invalidate_state_by_config_options(diff));
|
||||
it_print_object_status->print_object->config_apply_only(new_config, diff, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*if (model_object.sla_support_points != model_object_new.sla_support_points) {
|
||||
model_object.sla_support_points = model_object_new.sla_support_points;
|
||||
if (it_print_object_status != print_object_status.end())
|
||||
update_apply_status(it_print_object_status->print_object->invalidate_step(slaposSupportPoints));
|
||||
}
|
||||
if (model_object.sla_points_status != model_object_new.sla_points_status) {
|
||||
// Change of this status should invalidate support points. The points themselves are not enough, there are none
|
||||
// in case that nothing was generated OR that points were autogenerated already and not copied to the front-end.
|
||||
// These cases can only be differentiated by checking the status change. However, changing from 'Generating' should NOT
|
||||
// invalidate - that would keep stopping the background processing without a reason.
|
||||
if (model_object.sla_points_status != sla::PointsStatus::Generating)
|
||||
if (it_print_object_status != print_object_status.end())
|
||||
update_apply_status(it_print_object_status->print_object->invalidate_step(slaposSupportPoints));
|
||||
model_object.sla_points_status = model_object_new.sla_points_status;
|
||||
}*/
|
||||
// PrintObject for this ModelObject, if it exists.
|
||||
auto it_print_object_status = print_object_status.end();
|
||||
if (it_status->status != ModelObjectStatus::New) {
|
||||
// Update the ModelObject instance, possibly invalidate the linked PrintObjects.
|
||||
assert(it_status->status == ModelObjectStatus::Old || it_status->status == ModelObjectStatus::Moved);
|
||||
const ModelObject &model_object_new = *model.objects[idx_model_object];
|
||||
it_print_object_status = print_object_status.lower_bound(PrintObjectStatus(model_object.id()));
|
||||
if (it_print_object_status != print_object_status.end() && it_print_object_status->id != model_object.id())
|
||||
it_print_object_status = print_object_status.end();
|
||||
// Check whether a model part volume was added or removed, their transformations or order changed.
|
||||
bool model_parts_differ = model_volume_list_changed(model_object, model_object_new, ModelVolumeType::MODEL_PART);
|
||||
bool sla_trafo_differs = model_object.instances.empty() != model_object_new.instances.empty() ||
|
||||
(! model_object.instances.empty() && ! sla_trafo(model_object).isApprox(sla_trafo(model_object_new)));
|
||||
if (model_parts_differ || sla_trafo_differs) {
|
||||
// The very first step (the slicing step) is invalidated. One may freely remove all associated PrintObjects.
|
||||
if (it_print_object_status != print_object_status.end()) {
|
||||
update_apply_status(it_print_object_status->print_object->invalidate_all_steps());
|
||||
const_cast<PrintObjectStatus&>(*it_print_object_status).status = PrintObjectStatus::Deleted;
|
||||
}
|
||||
// Copy content of the ModelObject including its ID, do not change the parent.
|
||||
model_object.assign_copy(model_object_new);
|
||||
} else {
|
||||
// Synchronize Object's config.
|
||||
bool object_config_changed = model_object.config != model_object_new.config;
|
||||
if (object_config_changed)
|
||||
model_object.config = model_object_new.config;
|
||||
if (! object_diff.empty() || object_config_changed) {
|
||||
SLAPrintObjectConfig new_config = m_default_object_config;
|
||||
normalize_and_apply_config(new_config, model_object.config);
|
||||
if (it_print_object_status != print_object_status.end()) {
|
||||
t_config_option_keys diff = it_print_object_status->print_object->config().diff(new_config);
|
||||
if (! diff.empty()) {
|
||||
update_apply_status(it_print_object_status->print_object->invalidate_state_by_config_options(diff));
|
||||
it_print_object_status->print_object->config_apply_only(new_config, diff, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*if (model_object.sla_support_points != model_object_new.sla_support_points) {
|
||||
model_object.sla_support_points = model_object_new.sla_support_points;
|
||||
if (it_print_object_status != print_object_status.end())
|
||||
update_apply_status(it_print_object_status->print_object->invalidate_step(slaposSupportPoints));
|
||||
}
|
||||
if (model_object.sla_points_status != model_object_new.sla_points_status) {
|
||||
// Change of this status should invalidate support points. The points themselves are not enough, there are none
|
||||
// in case that nothing was generated OR that points were autogenerated already and not copied to the front-end.
|
||||
// These cases can only be differentiated by checking the status change. However, changing from 'Generating' should NOT
|
||||
// invalidate - that would keep stopping the background processing without a reason.
|
||||
if (model_object.sla_points_status != sla::PointsStatus::Generating)
|
||||
if (it_print_object_status != print_object_status.end())
|
||||
update_apply_status(it_print_object_status->print_object->invalidate_step(slaposSupportPoints));
|
||||
model_object.sla_points_status = model_object_new.sla_points_status;
|
||||
}*/
|
||||
|
||||
bool old_user_modified = model_object.sla_points_status == sla::PointsStatus::UserModified;
|
||||
bool new_user_modified = model_object_new.sla_points_status == sla::PointsStatus::UserModified;
|
||||
if ((old_user_modified && ! new_user_modified) || // switching to automatic supports from manual supports
|
||||
(! old_user_modified && new_user_modified) || // switching to manual supports from automatic supports
|
||||
(new_user_modified && model_object.sla_support_points != model_object_new.sla_support_points)) {
|
||||
if (it_print_object_status != print_object_status.end())
|
||||
update_apply_status(it_print_object_status->print_object->invalidate_step(slaposSupportPoints));
|
||||
bool old_user_modified = model_object.sla_points_status == sla::PointsStatus::UserModified;
|
||||
bool new_user_modified = model_object_new.sla_points_status == sla::PointsStatus::UserModified;
|
||||
if ((old_user_modified && ! new_user_modified) || // switching to automatic supports from manual supports
|
||||
(! old_user_modified && new_user_modified) || // switching to manual supports from automatic supports
|
||||
(new_user_modified && model_object.sla_support_points != model_object_new.sla_support_points)) {
|
||||
if (it_print_object_status != print_object_status.end())
|
||||
update_apply_status(it_print_object_status->print_object->invalidate_step(slaposSupportPoints));
|
||||
|
||||
model_object.sla_points_status = model_object_new.sla_points_status;
|
||||
model_object.sla_support_points = model_object_new.sla_support_points;
|
||||
}
|
||||
model_object.sla_points_status = model_object_new.sla_points_status;
|
||||
model_object.sla_support_points = model_object_new.sla_support_points;
|
||||
}
|
||||
|
||||
// Copy the ModelObject name, input_file and instances. The instances will compared against PrintObject instances in the next step.
|
||||
model_object.name = model_object_new.name;
|
||||
model_object.input_file = model_object_new.input_file;
|
||||
model_object.clear_instances();
|
||||
model_object.instances.reserve(model_object_new.instances.size());
|
||||
for (const ModelInstance *model_instance : model_object_new.instances) {
|
||||
model_object.instances.emplace_back(new ModelInstance(*model_instance));
|
||||
model_object.instances.back()->set_model_object(&model_object);
|
||||
}
|
||||
}
|
||||
// Copy the ModelObject name, input_file and instances. The instances will compared against PrintObject instances in the next step.
|
||||
model_object.name = model_object_new.name;
|
||||
model_object.input_file = model_object_new.input_file;
|
||||
model_object.clear_instances();
|
||||
model_object.instances.reserve(model_object_new.instances.size());
|
||||
for (const ModelInstance *model_instance : model_object_new.instances) {
|
||||
model_object.instances.emplace_back(new ModelInstance(*model_instance));
|
||||
model_object.instances.back()->set_model_object(&model_object);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<SLAPrintObject::Instance> new_instances = sla_instances(model_object);
|
||||
if (it_print_object_status != print_object_status.end() && it_print_object_status->status != PrintObjectStatus::Deleted) {
|
||||
@ -544,9 +547,9 @@ sla::SupportConfig make_support_cfg(const SLAPrintObjectConfig& c) {
|
||||
scfg.head_penetration_mm = c.support_head_penetration.getFloat();
|
||||
scfg.head_width_mm = c.support_head_width.getFloat();
|
||||
scfg.object_elevation_mm = c.support_object_elevation.getFloat();
|
||||
scfg.tilt = c.support_critical_angle.getFloat() * PI / 180.0 ;
|
||||
scfg.bridge_slope = c.support_critical_angle.getFloat() * PI / 180.0 ;
|
||||
scfg.max_bridge_length_mm = c.support_max_bridge_length.getFloat();
|
||||
scfg.headless_pillar_radius_mm = 0.375*c.support_pillar_diameter.getFloat();
|
||||
scfg.max_pillar_link_distance_mm = c.support_max_pillar_link_distance.getFloat();
|
||||
switch(c.support_pillar_connection_mode.getInt()) {
|
||||
case slapcmZigZag:
|
||||
scfg.pillar_connection_mode = sla::PillarConnectionMode::zigzag; break;
|
||||
@ -563,32 +566,45 @@ sla::SupportConfig make_support_cfg(const SLAPrintObjectConfig& c) {
|
||||
return scfg;
|
||||
}
|
||||
|
||||
sla::PoolConfig make_pool_config(const SLAPrintObjectConfig& c) {
|
||||
sla::PoolConfig pcfg;
|
||||
|
||||
pcfg.min_wall_thickness_mm = c.pad_wall_thickness.getFloat();
|
||||
pcfg.wall_slope = c.pad_wall_slope.getFloat();
|
||||
pcfg.edge_radius_mm = c.pad_edge_radius.getFloat();
|
||||
pcfg.max_merge_distance_mm = c.pad_max_merge_distance.getFloat();
|
||||
pcfg.min_wall_height_mm = c.pad_wall_height.getFloat();
|
||||
|
||||
return pcfg;
|
||||
}
|
||||
|
||||
void swapXY(ExPolygon& expoly) {
|
||||
for(auto& p : expoly.contour.points) std::swap(p(X), p(Y));
|
||||
for(auto& h : expoly.holes) for(auto& p : h.points) std::swap(p(X), p(Y));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
std::vector<float> SLAPrint::calculate_heights(const BoundingBoxf3& bb3d,
|
||||
float elevation,
|
||||
float initial_layer_height,
|
||||
float layer_height) const
|
||||
std::string SLAPrint::validate() const
|
||||
{
|
||||
std::vector<float> heights;
|
||||
float minZ = float(bb3d.min(Z)) - float(elevation);
|
||||
float maxZ = float(bb3d.max(Z));
|
||||
auto flh = float(layer_height);
|
||||
auto gnd = float(bb3d.min(Z));
|
||||
for(SLAPrintObject * po : m_objects) {
|
||||
sla::SupportConfig cfg = make_support_cfg(po->config());
|
||||
|
||||
for(float h = minZ + initial_layer_height; h < maxZ; h += flh)
|
||||
if(h >= gnd) heights.emplace_back(h);
|
||||
double pinhead_width =
|
||||
2 * cfg.head_front_radius_mm +
|
||||
cfg.head_width_mm +
|
||||
2 * cfg.head_back_radius_mm -
|
||||
cfg.head_penetration_mm;
|
||||
|
||||
return heights;
|
||||
if(pinhead_width > cfg.object_elevation_mm)
|
||||
return L("Elevetion is too low for object.");
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
template<class...Args>
|
||||
void report_status(SLAPrint& p, int st, const std::string& msg, Args&&...args) {
|
||||
void report_status(SLAPrint& p, int st, const std::string& msg, Args&&...args)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(info) << st << "% " << msg;
|
||||
p.set_status(st, msg, std::forward<Args>(args)...);
|
||||
}
|
||||
@ -599,12 +615,19 @@ void SLAPrint::process()
|
||||
using namespace sla;
|
||||
using ExPolygon = Slic3r::ExPolygon;
|
||||
|
||||
if(m_objects.empty()) return;
|
||||
|
||||
// Assumption: at this point the print objects should be populated only with
|
||||
// the model objects we have to process and the instances are also filtered
|
||||
|
||||
// shortcut to initial layer height
|
||||
double ilhd = m_material_config.initial_layer_height.getFloat();
|
||||
auto ilh = float(ilhd);
|
||||
double lhd = m_objects.front()->m_config.layer_height.getFloat();
|
||||
float lh = float(lhd);
|
||||
|
||||
auto ilhs = LevelID(ilhd / SCALING_FACTOR);
|
||||
auto lhs = LevelID(lhd / SCALING_FACTOR);
|
||||
const size_t objcount = m_objects.size();
|
||||
|
||||
const unsigned min_objstatus = 0; // where the per object operations start
|
||||
@ -625,25 +648,59 @@ void SLAPrint::process()
|
||||
|
||||
// Slicing the model object. This method is oversimplified and needs to
|
||||
// be compared with the fff slicing algorithm for verification
|
||||
auto slice_model = [this, ilh](SLAPrintObject& po) {
|
||||
double lh = po.m_config.layer_height.getFloat();
|
||||
|
||||
auto slice_model = [this, ilhs, lhs, ilh, lh](SLAPrintObject& po) {
|
||||
TriangleMesh mesh = po.transformed_mesh();
|
||||
|
||||
// We need to prepare the slice index...
|
||||
|
||||
auto&& bb3d = mesh.bounding_box();
|
||||
double minZ = bb3d.min(Z) - po.get_elevation();
|
||||
double maxZ = bb3d.max(Z);
|
||||
|
||||
auto minZs = LevelID(minZ / SCALING_FACTOR);
|
||||
auto maxZs = LevelID(maxZ / SCALING_FACTOR);
|
||||
|
||||
po.m_slice_index.clear();
|
||||
po.m_slice_index.reserve(size_t(maxZs - (minZs + ilhs) / lhs) + 1);
|
||||
po.m_slice_index.emplace_back(minZs + ilhs, float(minZ) + ilh / 2.f, ilh);
|
||||
|
||||
for(LevelID h = minZs + ilhs + lhs; h <= maxZs; h += lhs) {
|
||||
po.m_slice_index.emplace_back(h, float(h*SCALING_FACTOR) - lh / 2.f, lh);
|
||||
}
|
||||
|
||||
auto slindex_it = po.search_slice_index(float(bb3d.min(Z)));
|
||||
|
||||
if(slindex_it == po.m_slice_index.end())
|
||||
throw std::runtime_error(L("Slicing had to be stopped "
|
||||
"due to an internal error."));
|
||||
|
||||
po.m_model_height_levels.clear();
|
||||
po.m_model_height_levels.reserve(po.m_slice_index.size());
|
||||
for(auto it = slindex_it; it != po.m_slice_index.end(); ++it)
|
||||
{
|
||||
po.m_model_height_levels.emplace_back(it->slice_level());
|
||||
}
|
||||
|
||||
TriangleMeshSlicer slicer(float(po.config().slice_closing_radius.value),0);
|
||||
slicer.init(&mesh, [](){});
|
||||
|
||||
// The 1D grid heights
|
||||
std::vector<float> heights = calculate_heights(mesh.bounding_box(),
|
||||
float(po.get_elevation()),
|
||||
ilh, float(lh));
|
||||
po.m_model_slices.clear();
|
||||
slicer.slice(po.m_model_height_levels,
|
||||
&po.m_model_slices,
|
||||
[this](){ throw_if_canceled(); });
|
||||
|
||||
auto& layers = po.m_model_slices; layers.clear();
|
||||
slicer.slice(heights, &layers, [this](){ throw_if_canceled(); });
|
||||
auto mit = slindex_it;
|
||||
for(size_t id = 0;
|
||||
id < po.m_model_slices.size() && mit != po.m_slice_index.end();
|
||||
id++)
|
||||
{
|
||||
mit->set_model_slice_idx(id); ++mit;
|
||||
}
|
||||
};
|
||||
|
||||
// In this step we check the slices, identify island and cover them with
|
||||
// support points. Then we sprinkle the rest of the mesh.
|
||||
auto support_points = [this, ilh](SLAPrintObject& po) {
|
||||
auto support_points = [this](SLAPrintObject& po) {
|
||||
const ModelObject& mo = *po.m_model_object;
|
||||
po.m_supportdata.reset(
|
||||
new SLAPrintObject::SupportData(po.transformed_mesh()) );
|
||||
@ -660,12 +717,7 @@ void SLAPrint::process()
|
||||
if (mo.sla_points_status != sla::PointsStatus::UserModified) {
|
||||
|
||||
// calculate heights of slices (slices are calculated already)
|
||||
double lh = po.m_config.layer_height.getFloat();
|
||||
|
||||
std::vector<float> heights =
|
||||
calculate_heights(po.transformed_mesh().bounding_box(),
|
||||
float(po.get_elevation()),
|
||||
ilh, float(lh));
|
||||
const std::vector<float>& heights = po.m_model_height_levels;
|
||||
|
||||
this->throw_if_canceled();
|
||||
SLAAutoSupports::Config config;
|
||||
@ -674,6 +726,7 @@ void SLAPrint::process()
|
||||
// the density config value is in percents:
|
||||
config.density_relative = float(cfg.support_points_density_relative / 100.f);
|
||||
config.minimal_distance = float(cfg.support_points_minimal_distance);
|
||||
config.head_diameter = float(cfg.support_head_front_diameter);
|
||||
|
||||
// Construction of this object does the calculation.
|
||||
this->throw_if_canceled();
|
||||
@ -711,54 +764,52 @@ void SLAPrint::process()
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
sla::SupportConfig scfg = make_support_cfg(po.m_config);
|
||||
sla::Controller ctl;
|
||||
sla::SupportConfig scfg = make_support_cfg(po.m_config);
|
||||
sla::Controller ctl;
|
||||
|
||||
// some magic to scale the status values coming from the support
|
||||
// tree creation into the whole print process
|
||||
auto stfirst = OBJ_STEP_LEVELS.begin();
|
||||
auto stthis = stfirst + slaposSupportTree;
|
||||
// we need to add up the status portions until this operation
|
||||
int init = std::accumulate(stfirst, stthis, 0);
|
||||
init = int(init * ostepd); // scale the init portion
|
||||
// some magic to scale the status values coming from the support
|
||||
// tree creation into the whole print process
|
||||
auto stfirst = OBJ_STEP_LEVELS.begin();
|
||||
auto stthis = stfirst + slaposSupportTree;
|
||||
// we need to add up the status portions until this operation
|
||||
int init = std::accumulate(stfirst, stthis, 0);
|
||||
init = int(init * ostepd); // scale the init portion
|
||||
|
||||
// scaling for the sub operations
|
||||
double d = *stthis / (objcount * 100.0);
|
||||
// scaling for the sub operations
|
||||
double d = *stthis / (objcount * 100.0);
|
||||
|
||||
ctl.statuscb = [this, init, d](unsigned st, const std::string& msg)
|
||||
{
|
||||
//FIXME this status line scaling does not seem to be correct.
|
||||
// How does it account for an increasing object index?
|
||||
report_status(*this, int(init + st*d), msg);
|
||||
};
|
||||
ctl.statuscb = [this, init, d](unsigned st, const std::string& msg)
|
||||
{
|
||||
//FIXME this status line scaling does not seem to be correct.
|
||||
// How does it account for an increasing object index?
|
||||
report_status(*this, int(init + st*d), msg);
|
||||
};
|
||||
|
||||
ctl.stopcondition = [this](){ return canceled(); };
|
||||
ctl.cancelfn = [this]() { throw_if_canceled(); };
|
||||
ctl.stopcondition = [this](){ return canceled(); };
|
||||
ctl.cancelfn = [this]() { throw_if_canceled(); };
|
||||
|
||||
po.m_supportdata->support_tree_ptr.reset(
|
||||
new SLASupportTree(sla::to_point_set(po.m_supportdata->support_points),
|
||||
po.m_supportdata->emesh, scfg, ctl));
|
||||
po.m_supportdata->support_tree_ptr.reset(
|
||||
new SLASupportTree(po.m_supportdata->support_points,
|
||||
po.m_supportdata->emesh, scfg, ctl));
|
||||
|
||||
// Create the unified mesh
|
||||
auto rc = SlicingStatus::RELOAD_SCENE;
|
||||
throw_if_canceled();
|
||||
|
||||
// This is to prevent "Done." being displayed during merged_mesh()
|
||||
report_status(*this, -1, L("Visualizing supports"));
|
||||
po.m_supportdata->support_tree_ptr->merged_mesh();
|
||||
// Create the unified mesh
|
||||
auto rc = SlicingStatus::RELOAD_SCENE;
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug) << "Processed support point count "
|
||||
<< po.m_supportdata->support_points.size();
|
||||
// This is to prevent "Done." being displayed during merged_mesh()
|
||||
report_status(*this, -1, L("Visualizing supports"));
|
||||
po.m_supportdata->support_tree_ptr->merged_mesh();
|
||||
|
||||
// Check the mesh for later troubleshooting.
|
||||
if(po.support_mesh().empty())
|
||||
BOOST_LOG_TRIVIAL(warning) << "Support mesh is empty";
|
||||
BOOST_LOG_TRIVIAL(debug) << "Processed support point count "
|
||||
<< po.m_supportdata->support_points.size();
|
||||
|
||||
// Check the mesh for later troubleshooting.
|
||||
if(po.support_mesh().empty())
|
||||
BOOST_LOG_TRIVIAL(warning) << "Support mesh is empty";
|
||||
|
||||
report_status(*this, -1, L("Visualizing supports"), rc);
|
||||
|
||||
report_status(*this, -1, L("Visualizing supports"), rc);
|
||||
} catch(sla::SLASupportsStoppedException&) {
|
||||
// no need to rethrow
|
||||
// throw_if_canceled();
|
||||
}
|
||||
};
|
||||
|
||||
// This step generates the sla base pad
|
||||
@ -812,85 +863,36 @@ void SLAPrint::process()
|
||||
// Slicing the support geometries similarly to the model slicing procedure.
|
||||
// If the pad had been added previously (see step "base_pool" than it will
|
||||
// be part of the slices)
|
||||
auto slice_supports = [ilh](SLAPrintObject& po) {
|
||||
auto slice_supports = [](SLAPrintObject& po) {
|
||||
auto& sd = po.m_supportdata;
|
||||
|
||||
if(sd) sd->support_slices.clear();
|
||||
|
||||
if(sd && sd->support_tree_ptr) {
|
||||
auto lh = float(po.m_config.layer_height.getFloat());
|
||||
sd->support_slices = sd->support_tree_ptr->slice(lh, ilh);
|
||||
|
||||
std::vector<float> heights; heights.reserve(po.m_slice_index.size());
|
||||
|
||||
for(auto& rec : po.m_slice_index) {
|
||||
heights.emplace_back(rec.slice_level());
|
||||
}
|
||||
|
||||
sd->support_slices = sd->support_tree_ptr->slice(
|
||||
heights, float(po.config().slice_closing_radius.value));
|
||||
}
|
||||
|
||||
for(size_t i = 0;
|
||||
i < sd->support_slices.size() && i < po.m_slice_index.size();
|
||||
++i)
|
||||
{
|
||||
po.m_slice_index[i].set_support_slice_idx(i);
|
||||
}
|
||||
};
|
||||
|
||||
// We have the layer polygon collection but we need to unite them into
|
||||
// an index where the key is the height level in discrete levels (clipper)
|
||||
auto index_slices = [ilhd](SLAPrintObject& po) {
|
||||
po.m_slice_index.clear();
|
||||
auto sih = LevelID(scale_(ilhd));
|
||||
|
||||
// Establish the slice grid boundaries
|
||||
auto bb = po.transformed_mesh().bounding_box();
|
||||
double modelgnd = bb.min(Z);
|
||||
double elevation = po.get_elevation();
|
||||
double lh = po.m_config.layer_height.getFloat();
|
||||
double minZ = modelgnd - elevation;
|
||||
|
||||
// scaled values:
|
||||
auto sminZ = LevelID(scale_(minZ));
|
||||
auto smaxZ = LevelID(scale_(bb.max(Z)));
|
||||
auto smodelgnd = LevelID(scale_(modelgnd));
|
||||
auto slh = LevelID(scale_(lh));
|
||||
|
||||
// It is important that the next levels match the levels in
|
||||
// model_slice method. Only difference is that here it works with
|
||||
// scaled coordinates
|
||||
po.m_level_ids.clear();
|
||||
for(LevelID h = sminZ + sih; h < smaxZ; h += slh)
|
||||
if(h >= smodelgnd) po.m_level_ids.emplace_back(h);
|
||||
|
||||
std::vector<ExPolygons>& oslices = po.m_model_slices;
|
||||
|
||||
// If everything went well this code should not run at all, but
|
||||
// let's be robust...
|
||||
// assert(levelids.size() == oslices.size());
|
||||
if(po.m_level_ids.size() < oslices.size()) { // extend the levels until...
|
||||
|
||||
BOOST_LOG_TRIVIAL(warning)
|
||||
<< "Height level mismatch at rasterization!\n";
|
||||
|
||||
LevelID lastlvl = po.m_level_ids.back();
|
||||
while(po.m_level_ids.size() < oslices.size()) {
|
||||
lastlvl += slh;
|
||||
po.m_level_ids.emplace_back(lastlvl);
|
||||
}
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < oslices.size(); ++i) {
|
||||
LevelID h = po.m_level_ids[i];
|
||||
|
||||
float fh = float(double(h) * SCALING_FACTOR);
|
||||
|
||||
// now for the public slice index:
|
||||
SLAPrintObject::SliceRecord& sr = po.m_slice_index[fh];
|
||||
// There should be only one slice layer for each print object
|
||||
assert(sr.model_slices_idx == SLAPrintObject::SliceRecord::NONE);
|
||||
sr.model_slices_idx = i;
|
||||
}
|
||||
|
||||
if(po.m_supportdata) { // deal with the support slices if present
|
||||
std::vector<ExPolygons>& sslices = po.m_supportdata->support_slices;
|
||||
po.m_supportdata->level_ids.clear();
|
||||
po.m_supportdata->level_ids.reserve(sslices.size());
|
||||
|
||||
for(int i = 0; i < int(sslices.size()); ++i) {
|
||||
LevelID h = sminZ + sih + i * slh;
|
||||
po.m_supportdata->level_ids.emplace_back(h);
|
||||
|
||||
float fh = float(double(h) * SCALING_FACTOR);
|
||||
|
||||
SLAPrintObject::SliceRecord& sr = po.m_slice_index[fh];
|
||||
assert(sr.support_slices_idx == SLAPrintObject::SliceRecord::NONE);
|
||||
sr.support_slices_idx = SLAPrintObject::SliceRecord::Idx(i);
|
||||
}
|
||||
}
|
||||
auto index_slices = [this/*, ilhd*/](SLAPrintObject& /*po*/) {
|
||||
// Using RELOAD_SLA_PREVIEW to tell the Plater to pass the update status to the 3D preview to load the SLA slices.
|
||||
report_status(*this, -2, "", SlicingStatus::RELOAD_SLA_PREVIEW);
|
||||
};
|
||||
|
||||
// Rasterizing the model objects, and their supports
|
||||
@ -901,30 +903,18 @@ void SLAPrint::process()
|
||||
m_printer_input.clear();
|
||||
|
||||
for(SLAPrintObject * o : m_objects) {
|
||||
auto& po = *o;
|
||||
std::vector<ExPolygons>& oslices = po.m_model_slices;
|
||||
LevelID gndlvl = o->get_slice_index().front().key();
|
||||
for(auto& slicerecord : o->get_slice_index()) {
|
||||
auto& lyrs = m_printer_input[slicerecord.key() - gndlvl];
|
||||
|
||||
// We need to adjust the min Z level of the slices to be zero
|
||||
LevelID smfirst =
|
||||
po.m_supportdata && !po.m_supportdata->level_ids.empty() ?
|
||||
po.m_supportdata->level_ids.front() : 0;
|
||||
LevelID mfirst = po.m_level_ids.empty()? 0 : po.m_level_ids.front();
|
||||
LevelID gndlvl = -(std::min(smfirst, mfirst));
|
||||
const ExPolygons& objslices = o->get_slices_from_record(slicerecord, soModel);
|
||||
const ExPolygons& supslices = o->get_slices_from_record(slicerecord, soSupport);
|
||||
|
||||
// now merge this object's support and object slices with the rest
|
||||
// of the print object slices
|
||||
if(!objslices.empty())
|
||||
lyrs.emplace_back(objslices, o->instances());
|
||||
|
||||
for(size_t i = 0; i < oslices.size(); ++i) {
|
||||
auto& lyrs = m_printer_input[gndlvl + po.m_level_ids[i]];
|
||||
lyrs.emplace_back(oslices[i], po.m_instances);
|
||||
}
|
||||
|
||||
if(!po.m_supportdata) continue;
|
||||
std::vector<ExPolygons>& sslices = po.m_supportdata->support_slices;
|
||||
for(size_t i = 0; i < sslices.size(); ++i) {
|
||||
LayerRefs& lyrs =
|
||||
m_printer_input[gndlvl + po.m_supportdata->level_ids[i]];
|
||||
lyrs.emplace_back(sslices[i], po.m_instances);
|
||||
if(!supslices.empty())
|
||||
lyrs.emplace_back(supslices, o->instances());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1227,13 +1217,13 @@ void SLAPrint::fill_statistics()
|
||||
|
||||
// find highest object
|
||||
// Which is a better bet? To compare by max_z or by number of layers in the index?
|
||||
double max_z = 0.;
|
||||
float max_z = 0.;
|
||||
size_t max_layers_cnt = 0;
|
||||
size_t highest_obj_idx = 0;
|
||||
for (SLAPrintObject *&po : m_objects) {
|
||||
const SLAPrintObject::SliceIndex& slice_index = po->get_slice_index();
|
||||
if (! slice_index.empty()) {
|
||||
double z = (-- slice_index.end())->first;
|
||||
float z = (-- slice_index.end())->slice_level();
|
||||
size_t cnt = slice_index.size();
|
||||
//if (z > max_z) {
|
||||
if (cnt > max_layers_cnt) {
|
||||
@ -1253,7 +1243,7 @@ void SLAPrint::fill_statistics()
|
||||
int sliced_layer_cnt = 0;
|
||||
for (const auto& layer : highest_obj_slice_index)
|
||||
{
|
||||
const double l_height = (layer.first == highest_obj_slice_index.begin()->first) ? init_layer_height : layer_height;
|
||||
const double l_height = (layer.key() == highest_obj_slice_index.begin()->key()) ? init_layer_height : layer_height;
|
||||
|
||||
// Calculation of the consumed material
|
||||
|
||||
@ -1262,21 +1252,22 @@ void SLAPrint::fill_statistics()
|
||||
|
||||
for (SLAPrintObject * po : m_objects)
|
||||
{
|
||||
const SLAPrintObject::SliceRecord *record = nullptr;
|
||||
const SLAPrintObject::_SliceRecord *record = nullptr;
|
||||
{
|
||||
const SLAPrintObject::SliceIndex& index = po->get_slice_index();
|
||||
auto key = layer.first;
|
||||
const SLAPrintObject::SliceIndex::const_iterator it_key = index.lower_bound(key - float(EPSILON));
|
||||
if (it_key == index.end() || it_key->first > key + EPSILON)
|
||||
auto it = po->search_slice_index(layer.slice_level() - float(EPSILON));
|
||||
if (it == index.end() || it->slice_level() > layer.slice_level() + float(EPSILON))
|
||||
continue;
|
||||
record = &it_key->second;
|
||||
record = &(*it);
|
||||
}
|
||||
|
||||
if (record->model_slices_idx != SLAPrintObject::SliceRecord::NONE)
|
||||
append(model_polygons, get_all_polygons(po->get_model_slices()[record->model_slices_idx], po->instances()));
|
||||
|
||||
if (record->support_slices_idx != SLAPrintObject::SliceRecord::NONE)
|
||||
append(supports_polygons, get_all_polygons(po->get_support_slices()[record->support_slices_idx], po->instances()));
|
||||
const ExPolygons &modelslices = po->get_slices_from_record(*record, soModel);
|
||||
if (!modelslices.empty())
|
||||
append(model_polygons, get_all_polygons(modelslices, po->instances()));
|
||||
|
||||
const ExPolygons &supportslices = po->get_slices_from_record(*record, soSupport);
|
||||
if (!supportslices.empty())
|
||||
append(supports_polygons, get_all_polygons(supportslices, po->instances()));
|
||||
}
|
||||
|
||||
model_polygons = union_(model_polygons);
|
||||
@ -1372,11 +1363,15 @@ bool SLAPrintObject::invalidate_state_by_config_options(const std::vector<t_conf
|
||||
for (const t_config_option_key &opt_key : opt_keys) {
|
||||
if ( opt_key == "layer_height"
|
||||
|| opt_key == "faded_layers"
|
||||
|| opt_key == "pad_enable"
|
||||
|| opt_key == "pad_wall_thickness"
|
||||
|| opt_key == "supports_enable"
|
||||
|| opt_key == "support_object_elevation"
|
||||
|| opt_key == "slice_closing_radius") {
|
||||
steps.emplace_back(slaposObjectSlice);
|
||||
} else if (
|
||||
opt_key == "supports_enable"
|
||||
|| opt_key == "support_points_density_relative"
|
||||
|
||||
opt_key == "support_points_density_relative"
|
||||
|| opt_key == "support_points_minimal_distance") {
|
||||
steps.emplace_back(slaposSupportPoints);
|
||||
} else if (
|
||||
@ -1390,12 +1385,11 @@ bool SLAPrintObject::invalidate_state_by_config_options(const std::vector<t_conf
|
||||
|| opt_key == "support_base_height"
|
||||
|| opt_key == "support_critical_angle"
|
||||
|| opt_key == "support_max_bridge_length"
|
||||
|| opt_key == "support_object_elevation") {
|
||||
|| opt_key == "support_max_pillar_link_distance"
|
||||
) {
|
||||
steps.emplace_back(slaposSupportTree);
|
||||
} else if (
|
||||
opt_key == "pad_enable"
|
||||
|| opt_key == "pad_wall_thickness"
|
||||
|| opt_key == "pad_wall_height"
|
||||
opt_key == "pad_wall_height"
|
||||
|| opt_key == "pad_max_merge_distance"
|
||||
|| opt_key == "pad_wall_slope"
|
||||
|| opt_key == "pad_edge_radius") {
|
||||
@ -1451,11 +1445,7 @@ double SLAPrintObject::get_elevation() const {
|
||||
// its walls but currently it is half of its thickness. Whatever it
|
||||
// will be in the future, we provide the config to the get_pad_elevation
|
||||
// method and we will have the correct value
|
||||
sla::PoolConfig pcfg;
|
||||
pcfg.min_wall_height_mm = m_config.pad_wall_height.getFloat();
|
||||
pcfg.min_wall_thickness_mm = m_config.pad_wall_thickness.getFloat();
|
||||
pcfg.edge_radius_mm = m_config.pad_edge_radius.getFloat();
|
||||
pcfg.max_merge_distance_mm = m_config.pad_max_merge_distance.getFloat();
|
||||
sla::PoolConfig pcfg = make_pool_config(m_config);
|
||||
ret += sla::get_pad_elevation(pcfg);
|
||||
}
|
||||
|
||||
@ -1479,6 +1469,7 @@ double SLAPrintObject::get_current_elevation() const
|
||||
namespace { // dummy empty static containers for return values in some methods
|
||||
const std::vector<ExPolygons> EMPTY_SLICES;
|
||||
const TriangleMesh EMPTY_MESH;
|
||||
const ExPolygons EMPTY_SLICE;
|
||||
}
|
||||
|
||||
const std::vector<sla::SupportPoint>& SLAPrintObject::get_support_points() const
|
||||
@ -1486,6 +1477,72 @@ const std::vector<sla::SupportPoint>& SLAPrintObject::get_support_points() const
|
||||
return m_supportdata->support_points;
|
||||
}
|
||||
|
||||
SLAPrintObject::SliceIndex::iterator
|
||||
SLAPrintObject::search_slice_index(float slice_level)
|
||||
{
|
||||
_SliceRecord query(0, slice_level, 0);
|
||||
auto it = std::lower_bound(m_slice_index.begin(), m_slice_index.end(),
|
||||
query,
|
||||
[](const _SliceRecord& r1, const _SliceRecord& r2)
|
||||
{
|
||||
return r1.slice_level() < r2.slice_level();
|
||||
});
|
||||
|
||||
return it;
|
||||
}
|
||||
|
||||
SLAPrintObject::SliceIndex::const_iterator
|
||||
SLAPrintObject::search_slice_index(float slice_level) const
|
||||
{
|
||||
_SliceRecord query(0, slice_level, 0);
|
||||
auto it = std::lower_bound(m_slice_index.cbegin(), m_slice_index.cend(),
|
||||
query,
|
||||
[](const _SliceRecord& r1, const _SliceRecord& r2)
|
||||
{
|
||||
return r1.slice_level() < r2.slice_level();
|
||||
});
|
||||
|
||||
return it;
|
||||
}
|
||||
|
||||
SLAPrintObject::SliceIndex::iterator
|
||||
SLAPrintObject::search_slice_index(SLAPrintObject::_SliceRecord::Key key,
|
||||
bool exact)
|
||||
{
|
||||
_SliceRecord query(key, 0.f, 0.f);
|
||||
auto it = std::lower_bound(m_slice_index.begin(), m_slice_index.end(),
|
||||
query,
|
||||
[](const _SliceRecord& r1, const _SliceRecord& r2)
|
||||
{
|
||||
return r1.key() < r2.key();
|
||||
});
|
||||
|
||||
// Return valid iterator only if the keys really match
|
||||
if(exact && it != m_slice_index.end() && it->key() != key)
|
||||
it = m_slice_index.end();
|
||||
|
||||
return it;
|
||||
}
|
||||
|
||||
SLAPrintObject::SliceIndex::const_iterator
|
||||
SLAPrintObject::search_slice_index(SLAPrintObject::_SliceRecord::Key key,
|
||||
bool exact) const
|
||||
{
|
||||
_SliceRecord query(key, 0.f, 0.f);
|
||||
auto it = std::lower_bound(m_slice_index.cbegin(), m_slice_index.cend(),
|
||||
query,
|
||||
[](const _SliceRecord& r1, const _SliceRecord& r2)
|
||||
{
|
||||
return r1.key() < r2.key();
|
||||
});
|
||||
|
||||
// Return valid iterator only if the keys really match
|
||||
if(exact && it != m_slice_index.end() && it->key() != key)
|
||||
it = m_slice_index.end();
|
||||
|
||||
return it;
|
||||
}
|
||||
|
||||
const std::vector<ExPolygons> &SLAPrintObject::get_support_slices() const
|
||||
{
|
||||
// assert(is_step_done(slaposSliceSupports));
|
||||
@ -1493,7 +1550,30 @@ const std::vector<ExPolygons> &SLAPrintObject::get_support_slices() const
|
||||
return m_supportdata->support_slices;
|
||||
}
|
||||
|
||||
const SLAPrintObject::SliceIndex &SLAPrintObject::get_slice_index() const
|
||||
const ExPolygons &SLAPrintObject::get_slices_from_record(
|
||||
const _SliceRecord &rec,
|
||||
SliceOrigin o) const
|
||||
{
|
||||
size_t idx = o == soModel ? rec.get_model_slice_idx() :
|
||||
rec.get_support_slice_idx();
|
||||
|
||||
const std::vector<ExPolygons>& v = o == soModel? get_model_slices() :
|
||||
get_support_slices();
|
||||
|
||||
if(idx >= v.size()) return EMPTY_SLICE;
|
||||
|
||||
return idx >= v.size() ? EMPTY_SLICE : v[idx];
|
||||
}
|
||||
|
||||
const ExPolygons &SLAPrintObject::get_slices_from_record(
|
||||
SLAPrintObject::SliceRecordConstIterator it, SliceOrigin o) const
|
||||
{
|
||||
if(it.is_end()) return EMPTY_SLICE;
|
||||
return get_slices_from_record(*it, o);
|
||||
}
|
||||
|
||||
const std::vector<SLAPrintObject::_SliceRecord>&
|
||||
SLAPrintObject::get_slice_index() const
|
||||
{
|
||||
// assert(is_step_done(slaposIndexSlices));
|
||||
return m_slice_index;
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "PrintExport.hpp"
|
||||
#include "Point.hpp"
|
||||
#include "MTUtils.hpp"
|
||||
#include <iterator>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
@ -35,12 +36,19 @@ using _SLAPrintObjectBase =
|
||||
// the printer (rasterizer) in the SLAPrint class.
|
||||
using LevelID = long long;
|
||||
|
||||
enum SliceOrigin { soSupport, soModel };
|
||||
|
||||
class SLAPrintObject : public _SLAPrintObjectBase
|
||||
{
|
||||
private: // Prevents erroneous use by other classes.
|
||||
using Inherited = _SLAPrintObjectBase;
|
||||
|
||||
public:
|
||||
|
||||
// I refuse to grantee copying (Tamas)
|
||||
SLAPrintObject(const SLAPrintObject&) = delete;
|
||||
SLAPrintObject& operator=(const SLAPrintObject&) = delete;
|
||||
|
||||
const SLAPrintObjectConfig& config() const { return m_config; }
|
||||
const Transform3d& trafo() const { return m_trafo; }
|
||||
|
||||
@ -82,40 +90,146 @@ public:
|
||||
// pad is not, then without the pad, otherwise the full value is returned.
|
||||
double get_current_elevation() const;
|
||||
|
||||
// These two methods should be callable on the client side (e.g. UI thread)
|
||||
// when the appropriate steps slaposObjectSlice and slaposSliceSupports
|
||||
// are ready. All the print objects are processed before slapsRasterize so
|
||||
// it is safe to call them during and/or after slapsRasterize.
|
||||
const std::vector<ExPolygons>& get_model_slices() const;
|
||||
const std::vector<ExPolygons>& get_support_slices() const;
|
||||
|
||||
// This method returns the support points of this SLAPrintObject.
|
||||
const std::vector<sla::SupportPoint>& get_support_points() const;
|
||||
|
||||
// The public Slice record structure. It corresponds to one printable layer.
|
||||
// To get the sliced polygons, use SLAPrintObject::get_slices_from_record
|
||||
class SliceRecord {
|
||||
public:
|
||||
using Key = LevelID;
|
||||
|
||||
private:
|
||||
Key m_print_z = 0; // Top of the layer
|
||||
float m_slice_z = 0.f; // Exact level of the slice
|
||||
float m_height = 0.f; // Height of the sliced layer
|
||||
|
||||
protected:
|
||||
SliceRecord(Key key, float slicez, float height):
|
||||
m_print_z(key), m_slice_z(slicez), m_height(height) {}
|
||||
|
||||
public:
|
||||
|
||||
// The key will be the integer height level of the top of the layer.
|
||||
inline Key key() const { return m_print_z; }
|
||||
|
||||
// Returns the exact floating point Z coordinate of the slice
|
||||
inline float slice_level() const { return m_slice_z; }
|
||||
|
||||
// Returns the current layer height
|
||||
inline float layer_height() const { return m_height; }
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
// An index record referencing the slices
|
||||
// (get_model_slices(), get_support_slices()) where the keys are the height
|
||||
// levels of the model in scaled-clipper coordinates. The levels correspond
|
||||
// to the z coordinate of the object coordinate system.
|
||||
struct SliceRecord {
|
||||
using Key = float;
|
||||
class _SliceRecord: public SliceRecord {
|
||||
public:
|
||||
static const size_t NONE = size_t(-1); // this will be the max limit of size_t
|
||||
private:
|
||||
size_t m_model_slices_idx = NONE;
|
||||
size_t m_support_slices_idx = NONE;
|
||||
|
||||
using Idx = size_t;
|
||||
static const Idx NONE = Idx(-1); // this will be the max limit of size_t
|
||||
public:
|
||||
_SliceRecord(Key key, float slicez, float height):
|
||||
SliceRecord(key, slicez, height) {}
|
||||
|
||||
Idx model_slices_idx = NONE;
|
||||
Idx support_slices_idx = NONE;
|
||||
// Methods for setting the indices into the slice vectors.
|
||||
void set_model_slice_idx(size_t id) { m_model_slices_idx = id; }
|
||||
void set_support_slice_idx(size_t id) { m_support_slices_idx = id; }
|
||||
|
||||
inline size_t get_model_slice_idx() const { return m_model_slices_idx; }
|
||||
inline size_t get_support_slice_idx() const { return m_support_slices_idx; }
|
||||
};
|
||||
|
||||
using SliceIndex = std::map<SliceRecord::Key, SliceRecord>;
|
||||
// Slice index will be a plain vector sorted by the integer height levels
|
||||
using SliceIndex = std::vector<_SliceRecord>;
|
||||
|
||||
// Retrieve the slice index which is readable only after slaposIndexSlices
|
||||
// is done.
|
||||
const SliceIndex& get_slice_index() const;
|
||||
|
||||
// I refuse to grantee copying (Tamas)
|
||||
SLAPrintObject(const SLAPrintObject&) = delete;
|
||||
SLAPrintObject& operator=(const SLAPrintObject&) = delete;
|
||||
// Search slice index for the closest slice to the given level
|
||||
SliceIndex::iterator search_slice_index(float slice_level);
|
||||
SliceIndex::const_iterator search_slice_index(float slice_level) const;
|
||||
|
||||
// Search the slice index for a particular level in integer coordinates.
|
||||
// If no such layer is present, it will return m_slice_index.end()
|
||||
// This behavior can be suppressed by the second parameter. If it is true
|
||||
// the method will return the closest (non-equal) record
|
||||
SliceIndex::iterator search_slice_index(_SliceRecord::Key key, bool exact = false);
|
||||
SliceIndex::const_iterator search_slice_index(_SliceRecord::Key key, bool = false) const;
|
||||
|
||||
const std::vector<ExPolygons>& get_model_slices() const;
|
||||
const std::vector<ExPolygons>& get_support_slices() const;
|
||||
|
||||
public:
|
||||
|
||||
// Should work as a polymorphic bidirectional iterator to the slice records
|
||||
using SliceRecordConstIterator =
|
||||
IndexBasedIterator<const SliceIndex, const _SliceRecord>;
|
||||
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// These two methods should be callable on the client side (e.g. UI thread)
|
||||
// when the appropriate steps slaposObjectSlice and slaposSliceSupports
|
||||
// are ready. All the print objects are processed before slapsRasterize so
|
||||
// it is safe to call them during and/or after slapsRasterize.
|
||||
//
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Get the slice records from a range of slice levels (inclusive). Floating
|
||||
// point keys are the levels where the model was sliced with the mesh
|
||||
// slicer. Integral keys are the keys of the slice records, which
|
||||
// correspond to the top of each layer.. The end() method of the returned
|
||||
// range points *after* the last valid element. This is for being
|
||||
// consistent with std and makeing range based for loops work. use
|
||||
// std::prev(range.end()) or --range.end() to get the last element.
|
||||
template<class Key> Range<SliceRecordConstIterator>
|
||||
get_slice_records(Key from, Key to = std::numeric_limits<Key>::max()) const
|
||||
{
|
||||
SliceIndex::const_iterator it_from, it_to;
|
||||
if(std::is_integral<Key>::value) {
|
||||
it_from = search_slice_index(SliceRecord::Key(from));
|
||||
it_to = search_slice_index(SliceRecord::Key(to));
|
||||
} else if(std::is_floating_point<Key>::value) {
|
||||
it_from = search_slice_index(float(from));
|
||||
it_to = search_slice_index(float(to));
|
||||
} else return {
|
||||
SliceRecordConstIterator(m_slice_index, _SliceRecord::NONE ),
|
||||
SliceRecordConstIterator(m_slice_index, _SliceRecord::NONE ),
|
||||
};
|
||||
|
||||
auto start = m_slice_index.begin();
|
||||
|
||||
size_t bidx = it_from == m_slice_index.end() ? _SliceRecord::NONE :
|
||||
size_t(it_from - start);
|
||||
|
||||
size_t eidx = it_to == m_slice_index.end() ? _SliceRecord::NONE :
|
||||
size_t(it_to - start) + 1;
|
||||
|
||||
return {
|
||||
SliceRecordConstIterator(m_slice_index, bidx),
|
||||
SliceRecordConstIterator(m_slice_index, eidx),
|
||||
};
|
||||
}
|
||||
|
||||
// Get all the slice records as a range.
|
||||
inline Range<SliceRecordConstIterator> get_slice_records() const {
|
||||
return {
|
||||
SliceRecordConstIterator(m_slice_index, 0),
|
||||
SliceRecordConstIterator(m_slice_index, m_slice_index.size())
|
||||
};
|
||||
}
|
||||
|
||||
const ExPolygons& get_slices_from_record(SliceRecordConstIterator it,
|
||||
SliceOrigin o) const;
|
||||
|
||||
const ExPolygons& get_slices_from_record(const _SliceRecord& rec,
|
||||
SliceOrigin o) const;
|
||||
protected:
|
||||
// to be called from SLAPrint only.
|
||||
friend class SLAPrint;
|
||||
@ -145,8 +259,10 @@ protected:
|
||||
private:
|
||||
// Object specific configuration, pulled from the configuration layer.
|
||||
SLAPrintObjectConfig m_config;
|
||||
|
||||
// Translation in Z + Rotation by Y and Z + Scaling / Mirroring.
|
||||
Transform3d m_trafo = Transform3d::Identity();
|
||||
|
||||
std::vector<Instance> m_instances;
|
||||
|
||||
// Individual 2d slice polygons from lower z to higher z levels
|
||||
@ -154,11 +270,9 @@ private:
|
||||
|
||||
// Exact (float) height levels mapped to the slices. Each record contains
|
||||
// the index to the model and the support slice vectors.
|
||||
SliceIndex m_slice_index;
|
||||
std::vector<_SliceRecord> m_slice_index;
|
||||
|
||||
// The height levels corrected and scaled up in integer values. This will
|
||||
// be used at rasterization.
|
||||
std::vector<LevelID> m_level_ids;
|
||||
std::vector<float> m_model_height_levels;
|
||||
|
||||
// Caching the transformed (m_trafo) raw mesh of the object
|
||||
mutable CachedObject<TriangleMesh> m_transformed_rmesh;
|
||||
@ -236,10 +350,17 @@ public:
|
||||
}
|
||||
const PrintObjects& objects() const { return m_objects; }
|
||||
|
||||
const SLAPrintConfig& print_config() const { return m_print_config; }
|
||||
const SLAPrinterConfig& printer_config() const { return m_printer_config; }
|
||||
const SLAMaterialConfig& material_config() const { return m_material_config; }
|
||||
|
||||
|
||||
std::string output_filename() const override;
|
||||
|
||||
const SLAPrintStatistics& print_statistics() const { return m_print_statistics; }
|
||||
|
||||
std::string validate() const override;
|
||||
|
||||
private:
|
||||
using SLAPrinter = FilePrinter<FilePrinterFormat::SLA_PNGZIP>;
|
||||
using SLAPrinterPtr = std::unique_ptr<SLAPrinter>;
|
||||
@ -270,8 +391,6 @@ private:
|
||||
lref(std::cref(lyr)), copies(std::cref(cp)) {}
|
||||
};
|
||||
|
||||
std::vector<float> calculate_heights(const BoundingBoxf3& bb, float elevation, float initial_layer_height, float layer_height) const;
|
||||
|
||||
// One level may contain multiple slices from multiple objects and their
|
||||
// supports
|
||||
using LayerRefs = std::vector<LayerRef>;
|
||||
|
@ -150,6 +150,7 @@ SlicingParameters SlicingParameters::create_from_config(
|
||||
params.object_print_z_max += print_z;
|
||||
}
|
||||
|
||||
params.valid = true;
|
||||
return params;
|
||||
}
|
||||
|
||||
|
@ -42,6 +42,8 @@ struct SlicingParameters
|
||||
// Height of the object to be printed. This value does not contain the raft height.
|
||||
coordf_t object_print_z_height() const { return object_print_z_max - object_print_z_min; }
|
||||
|
||||
bool valid;
|
||||
|
||||
// Number of raft layers.
|
||||
size_t base_raft_layers;
|
||||
// Number of interface layers including the contact layer.
|
||||
@ -101,6 +103,8 @@ static_assert(IsTriviallyCopyable<SlicingParameters>::value, "SlicingParameters
|
||||
// The two slicing parameters lead to the same layering as long as the variable layer thickness is not in action.
|
||||
inline bool equal_layering(const SlicingParameters &sp1, const SlicingParameters &sp2)
|
||||
{
|
||||
assert(sp1.valid);
|
||||
assert(sp2.valid);
|
||||
return sp1.base_raft_layers == sp2.base_raft_layers &&
|
||||
sp1.interface_raft_layers == sp2.interface_raft_layers &&
|
||||
sp1.base_raft_layer_height == sp2.base_raft_layer_height &&
|
||||
|
@ -2864,7 +2864,7 @@ void modulate_extrusion_by_overlapping_layers(
|
||||
if (end_and_dist2.first == nullptr) {
|
||||
// New fragment connecting to pt_current was not found.
|
||||
// Verify that the last point found is close to the original end point of the unfragmented path.
|
||||
//const double d2 = (pt_end - pt_current).squaredNorm();
|
||||
//const double d2 = (pt_end - pt_current).cast<double>.squaredNorm();
|
||||
//assert(d2 < coordf_t(search_radius * search_radius));
|
||||
// End of the path.
|
||||
break;
|
||||
|
@ -20,9 +20,8 @@
|
||||
|
||||
// Disable synchronization of unselected instances
|
||||
#define DISABLE_INSTANCES_SYNCH (0 && ENABLE_1_42_0_ALPHA1)
|
||||
// Scene's GUI made using imgui library
|
||||
#define ENABLE_IMGUI (1 && ENABLE_1_42_0_ALPHA1)
|
||||
#define DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI (1 && ENABLE_IMGUI)
|
||||
// Disable imgui dialog for move, rotate and scale gizmos
|
||||
#define DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI (1 && ENABLE_1_42_0_ALPHA1)
|
||||
// Use wxDataViewRender instead of wxDataViewCustomRenderer
|
||||
#define ENABLE_NONCUSTOM_DATA_VIEW_RENDERING (0 && ENABLE_1_42_0_ALPHA1)
|
||||
|
||||
@ -34,23 +33,12 @@
|
||||
|
||||
// Changed algorithm to extract euler angles from rotation matrix
|
||||
#define ENABLE_NEW_EULER_ANGLES (1 && ENABLE_1_42_0_ALPHA4)
|
||||
// Added minimum threshold for click and drag movements
|
||||
#define ENABLE_MOVE_MIN_THRESHOLD (1 && ENABLE_1_42_0_ALPHA4)
|
||||
// Modified initial default placement of generic subparts
|
||||
#define ENABLE_GENERIC_SUBPARTS_PLACEMENT (1 && ENABLE_1_42_0_ALPHA4)
|
||||
// Bunch of fixes related to volumes centering
|
||||
#define ENABLE_VOLUMES_CENTERING_FIXES (1 && ENABLE_1_42_0_ALPHA4)
|
||||
|
||||
|
||||
//====================
|
||||
// 1.42.0.alpha5 techs
|
||||
//====================
|
||||
#define ENABLE_1_42_0_ALPHA5 1
|
||||
|
||||
// Toolbar items hidden/shown in dependence of the user mode
|
||||
#define ENABLE_MODE_AWARE_TOOLBAR_ITEMS (1 && ENABLE_1_42_0_ALPHA5)
|
||||
|
||||
|
||||
//====================
|
||||
// 1.42.0.alpha7 techs
|
||||
//====================
|
||||
@ -59,4 +47,14 @@
|
||||
// Printbed textures generated from svg files
|
||||
#define ENABLE_TEXTURES_FROM_SVG (1 && ENABLE_1_42_0_ALPHA7)
|
||||
|
||||
|
||||
//====================
|
||||
// 1.42.0.alpha8 techs
|
||||
//====================
|
||||
#define ENABLE_1_42_0_ALPHA8 1
|
||||
|
||||
// Toolbars and Gizmos use icons imported from svg files
|
||||
#define ENABLE_SVG_ICONS (1 && ENABLE_1_42_0_ALPHA8 && ENABLE_TEXTURES_FROM_SVG)
|
||||
|
||||
|
||||
#endif // _technologies_h_
|
||||
|
@ -247,7 +247,7 @@ bool TriangleMesh::needed_repair() const
|
||||
|| this->stl.stats.backwards_edges > 0;
|
||||
}
|
||||
|
||||
void TriangleMesh::WriteOBJFile(char* output_file)
|
||||
void TriangleMesh::WriteOBJFile(const char* output_file)
|
||||
{
|
||||
stl_generate_shared_vertices(&stl);
|
||||
stl_write_obj(&stl, output_file);
|
||||
@ -619,10 +619,11 @@ void TriangleMesh::require_shared_vertices()
|
||||
const int *vertices = stl.v_indices[facet_idx].vertex;
|
||||
for (int nbr_idx = 0; nbr_idx < 3; ++nbr_idx) {
|
||||
int nbr_face = this->stl.neighbors_start[facet_idx].neighbor[nbr_idx];
|
||||
//if (nbr_face != -1) {
|
||||
// assert(stl.v_indices[nbr_face].vertex[(nbr.which_vertex_not[nbr_idx] + 1) % 3] == vertices[(nbr_idx + 1) % 3]);
|
||||
// assert(stl.v_indices[nbr_face].vertex[(nbr.which_vertex_not[nbr_idx] + 2) % 3] == vertices[nbr_idx]);
|
||||
//}
|
||||
if (nbr_face != -1) {
|
||||
assert(
|
||||
(stl.v_indices[nbr_face].vertex[(nbr.which_vertex_not[nbr_idx] + 1) % 3] == vertices[(nbr_idx + 1) % 3] && stl.v_indices[nbr_face].vertex[(nbr.which_vertex_not[nbr_idx] + 2) % 3] == vertices[nbr_idx]) ||
|
||||
(stl.v_indices[nbr_face].vertex[(nbr.which_vertex_not[nbr_idx] + 2) % 3] == vertices[(nbr_idx + 1) % 3] && stl.v_indices[nbr_face].vertex[(nbr.which_vertex_not[nbr_idx] + 1) % 3] == vertices[nbr_idx]));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* _DEBUG */
|
||||
@ -1498,9 +1499,16 @@ void TriangleMeshSlicer::make_loops(std::vector<IntersectionLine> &lines, Polygo
|
||||
// Try to close gaps.
|
||||
// Do it in two rounds, first try to connect in the same direction only,
|
||||
// then try to connect the open polylines in reversed order as well.
|
||||
#if 0
|
||||
for (double max_gap : { EPSILON, 0.001, 0.1, 1., 2. }) {
|
||||
chain_open_polylines_close_gaps(open_polylines, *loops, max_gap, false);
|
||||
chain_open_polylines_close_gaps(open_polylines, *loops, max_gap, true);
|
||||
}
|
||||
#else
|
||||
const double max_gap = 2.; //mm
|
||||
chain_open_polylines_close_gaps(open_polylines, *loops, max_gap, false);
|
||||
chain_open_polylines_close_gaps(open_polylines, *loops, max_gap, true);
|
||||
#endif
|
||||
|
||||
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
||||
{
|
||||
|
@ -36,7 +36,7 @@ public:
|
||||
float volume();
|
||||
void check_topology();
|
||||
bool is_manifold() const { return this->stl.stats.connected_facets_3_edge == (int)this->stl.stats.number_of_facets; }
|
||||
void WriteOBJFile(char* output_file);
|
||||
void WriteOBJFile(const char* output_file);
|
||||
void scale(float factor);
|
||||
void scale(const Vec3d &versor);
|
||||
void translate(float x, float y, float z);
|
||||
|
753
src/slic3r.cpp
@ -31,22 +31,456 @@
|
||||
#include "libslic3r/Print.hpp"
|
||||
#include "libslic3r/SLAPrint.hpp"
|
||||
#include "libslic3r/TriangleMesh.hpp"
|
||||
#include "libslic3r/Format/AMF.hpp"
|
||||
#include "libslic3r/Format/3mf.hpp"
|
||||
#include "libslic3r/Format/STL.hpp"
|
||||
#include "libslic3r/Format/OBJ.hpp"
|
||||
#include "libslic3r/Utils.hpp"
|
||||
|
||||
#include "slic3r.hpp"
|
||||
#include "slic3r/GUI/GUI.hpp"
|
||||
#include "slic3r/GUI/GUI_App.hpp"
|
||||
|
||||
using namespace Slic3r;
|
||||
|
||||
/// utility function for displaying CLI usage
|
||||
void printUsage();
|
||||
PrinterTechnology get_printer_technology(const DynamicConfig &config)
|
||||
{
|
||||
const ConfigOptionEnum<PrinterTechnology> *opt = config.option<ConfigOptionEnum<PrinterTechnology>>("printer_technology");
|
||||
return (opt == nullptr) ? ptUnknown : opt->value;
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
int slic3r_main_(int argc, char **argv)
|
||||
int CLI::run(int argc, char **argv)
|
||||
{
|
||||
if (! this->setup(argc, argv))
|
||||
return 1;
|
||||
|
||||
m_extra_config.apply(m_config, true);
|
||||
m_extra_config.normalize();
|
||||
|
||||
bool start_gui = m_actions.empty() &&
|
||||
// cutting transformations are setting an "export" action.
|
||||
std::find(m_transforms.begin(), m_transforms.end(), "cut") == m_transforms.end() &&
|
||||
std::find(m_transforms.begin(), m_transforms.end(), "cut_x") == m_transforms.end() &&
|
||||
std::find(m_transforms.begin(), m_transforms.end(), "cut_y") == m_transforms.end();
|
||||
PrinterTechnology printer_technology = get_printer_technology(m_extra_config);
|
||||
const std::vector<std::string> &load_configs = m_config.option<ConfigOptionStrings>("load", true)->values;
|
||||
|
||||
// load config files supplied via --load
|
||||
for (auto const &file : load_configs) {
|
||||
if (! boost::filesystem::exists(file)) {
|
||||
if (m_config.opt_bool("ignore_nonexistent_config")) {
|
||||
continue;
|
||||
} else {
|
||||
boost::nowide::cerr << "No such file: " << file << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
DynamicPrintConfig config;
|
||||
try {
|
||||
config.load(file);
|
||||
} catch (std::exception &ex) {
|
||||
boost::nowide::cerr << "Error while reading config file: " << ex.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
config.normalize();
|
||||
PrinterTechnology other_printer_technology = get_printer_technology(config);
|
||||
if (printer_technology == ptUnknown) {
|
||||
printer_technology = other_printer_technology;
|
||||
} else if (printer_technology != other_printer_technology) {
|
||||
boost::nowide::cerr << "Mixing configurations for FFF and SLA technologies" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
m_print_config.apply(config);
|
||||
}
|
||||
|
||||
// Read input file(s) if any.
|
||||
for (const std::string &file : m_input_files) {
|
||||
if (! boost::filesystem::exists(file)) {
|
||||
boost::nowide::cerr << "No such file: " << file << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
Model model;
|
||||
try {
|
||||
// When loading an AMF or 3MF, config is imported as well, including the printer technology.
|
||||
model = Model::read_from_file(file, &m_print_config, true);
|
||||
PrinterTechnology other_printer_technology = get_printer_technology(m_print_config);
|
||||
if (printer_technology == ptUnknown) {
|
||||
printer_technology = other_printer_technology;
|
||||
} else if (printer_technology != other_printer_technology) {
|
||||
boost::nowide::cerr << "Mixing configurations for FFF and SLA technologies" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
} catch (std::exception &e) {
|
||||
boost::nowide::cerr << file << ": " << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
if (model.objects.empty()) {
|
||||
boost::nowide::cerr << "Error: file is empty: " << file << std::endl;
|
||||
continue;
|
||||
}
|
||||
m_models.push_back(model);
|
||||
}
|
||||
|
||||
// Apply command line options to a more specific DynamicPrintConfig which provides normalize()
|
||||
// (command line options override --load files)
|
||||
m_print_config.apply(m_extra_config, true);
|
||||
// Normalizing after importing the 3MFs / AMFs
|
||||
m_print_config.normalize();
|
||||
|
||||
if (printer_technology == ptUnknown)
|
||||
printer_technology = std::find(m_actions.begin(), m_actions.end(), "export_sla") == m_actions.end() ? ptFFF : ptSLA;
|
||||
|
||||
// Initialize full print configs for both the FFF and SLA technologies.
|
||||
FullPrintConfig fff_print_config;
|
||||
// SLAFullPrintConfig sla_print_config;
|
||||
fff_print_config.apply(m_print_config, true);
|
||||
// sla_print_config.apply(m_print_config, true);
|
||||
|
||||
// Loop through transform options.
|
||||
for (auto const &opt_key : m_transforms) {
|
||||
if (opt_key == "merge") {
|
||||
Model m;
|
||||
for (auto &model : m_models)
|
||||
for (ModelObject *o : model.objects)
|
||||
m.add_object(*o);
|
||||
// Rearrange instances unless --dont-arrange is supplied
|
||||
if (! m_config.opt_bool("dont_arrange")) {
|
||||
m.add_default_instances();
|
||||
const BoundingBoxf &bb = fff_print_config.bed_shape.values;
|
||||
m.arrange_objects(
|
||||
fff_print_config.min_object_distance(),
|
||||
// If we are going to use the merged model for printing, honor
|
||||
// the configured print bed for arranging, otherwise do it freely.
|
||||
this->has_print_action() ? &bb : nullptr
|
||||
);
|
||||
}
|
||||
m_models.clear();
|
||||
m_models.emplace_back(std::move(m));
|
||||
} else if (opt_key == "duplicate") {
|
||||
const BoundingBoxf &bb = fff_print_config.bed_shape.values;
|
||||
for (auto &model : m_models) {
|
||||
const bool all_objects_have_instances = std::none_of(
|
||||
model.objects.begin(), model.objects.end(),
|
||||
[](ModelObject* o){ return o->instances.empty(); }
|
||||
);
|
||||
if (all_objects_have_instances) {
|
||||
// if all input objects have defined position(s) apply duplication to the whole model
|
||||
model.duplicate(m_config.opt_int("duplicate"), fff_print_config.min_object_distance(), &bb);
|
||||
} else {
|
||||
model.add_default_instances();
|
||||
model.duplicate_objects(m_config.opt_int("duplicate"), fff_print_config.min_object_distance(), &bb);
|
||||
}
|
||||
}
|
||||
} else if (opt_key == "duplicate_grid") {
|
||||
std::vector<int> &ints = m_config.option<ConfigOptionInts>("duplicate_grid")->values;
|
||||
const int x = ints.size() > 0 ? ints.at(0) : 1;
|
||||
const int y = ints.size() > 1 ? ints.at(1) : 1;
|
||||
const double distance = fff_print_config.duplicate_distance.value;
|
||||
for (auto &model : m_models)
|
||||
model.duplicate_objects_grid(x, y, (distance > 0) ? distance : 6); // TODO: this is not the right place for setting a default
|
||||
} else if (opt_key == "center") {
|
||||
for (auto &model : m_models) {
|
||||
model.add_default_instances();
|
||||
// this affects instances:
|
||||
model.center_instances_around_point(m_config.option<ConfigOptionPoint>("center")->value);
|
||||
// this affects volumes:
|
||||
//FIXME Vojtech: Who knows why the complete model should be aligned with Z as a single rigid body?
|
||||
//model.align_to_ground();
|
||||
BoundingBoxf3 bbox;
|
||||
for (ModelObject *model_object : model.objects)
|
||||
// We are interested into the Z span only, therefore it is sufficient to measure the bounding box of the 1st instance only.
|
||||
bbox.merge(model_object->instance_bounding_box(0, false));
|
||||
for (ModelObject *model_object : model.objects)
|
||||
for (ModelInstance *model_instance : model_object->instances)
|
||||
model_instance->set_offset(Z, model_instance->get_offset(Z) - bbox.min.z());
|
||||
}
|
||||
} else if (opt_key == "align_xy") {
|
||||
const Vec2d &p = m_config.option<ConfigOptionPoint>("align_xy")->value;
|
||||
for (auto &model : m_models) {
|
||||
BoundingBoxf3 bb = model.bounding_box();
|
||||
// this affects volumes:
|
||||
model.translate(-(bb.min.x() - p.x()), -(bb.min.y() - p.y()), -bb.min.z());
|
||||
}
|
||||
} else if (opt_key == "dont_arrange") {
|
||||
// do nothing - this option alters other transform options
|
||||
} else if (opt_key == "rotate") {
|
||||
for (auto &model : m_models)
|
||||
for (auto &o : model.objects)
|
||||
// this affects volumes:
|
||||
o->rotate(Geometry::deg2rad(m_config.opt_float(opt_key)), Z);
|
||||
} else if (opt_key == "rotate_x") {
|
||||
for (auto &model : m_models)
|
||||
for (auto &o : model.objects)
|
||||
// this affects volumes:
|
||||
o->rotate(Geometry::deg2rad(m_config.opt_float(opt_key)), X);
|
||||
} else if (opt_key == "rotate_y") {
|
||||
for (auto &model : m_models)
|
||||
for (auto &o : model.objects)
|
||||
// this affects volumes:
|
||||
o->rotate(Geometry::deg2rad(m_config.opt_float(opt_key)), Y);
|
||||
} else if (opt_key == "scale") {
|
||||
for (auto &model : m_models)
|
||||
for (auto &o : model.objects)
|
||||
// this affects volumes:
|
||||
o->scale(m_config.get_abs_value(opt_key, 1));
|
||||
} else if (opt_key == "scale_to_fit") {
|
||||
const Vec3d &opt = m_config.opt<ConfigOptionPoint3>(opt_key)->value;
|
||||
if (opt.x() <= 0 || opt.y() <= 0 || opt.z() <= 0) {
|
||||
boost::nowide::cerr << "--scale-to-fit requires a positive volume" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
for (auto &model : m_models)
|
||||
for (auto &o : model.objects)
|
||||
// this affects volumes:
|
||||
o->scale_to_fit(opt);
|
||||
} else if (opt_key == "cut" || opt_key == "cut_x" || opt_key == "cut_y") {
|
||||
std::vector<Model> new_models;
|
||||
for (auto &model : m_models) {
|
||||
model.repair();
|
||||
model.translate(0, 0, -model.bounding_box().min.z()); // align to z = 0
|
||||
size_t num_objects = model.objects.size();
|
||||
for (size_t i = 0; i < num_objects; ++ i) {
|
||||
|
||||
#if 0
|
||||
if (opt_key == "cut_x") {
|
||||
o->cut(X, m_config.opt_float("cut_x"), &out);
|
||||
} else if (opt_key == "cut_y") {
|
||||
o->cut(Y, m_config.opt_float("cut_y"), &out);
|
||||
} else if (opt_key == "cut") {
|
||||
o->cut(Z, m_config.opt_float("cut"), &out);
|
||||
}
|
||||
#else
|
||||
int main(int argc, char **argv)
|
||||
model.objects.front()->cut(0, m_config.opt_float("cut"), true, true, true);
|
||||
#endif
|
||||
model.delete_object(size_t(0));
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: copy less stuff around using pointers
|
||||
m_models = new_models;
|
||||
|
||||
if (m_actions.empty())
|
||||
m_actions.push_back("export_stl");
|
||||
}
|
||||
#if 0
|
||||
else if (opt_key == "cut_grid") {
|
||||
std::vector<Model> new_models;
|
||||
for (auto &model : m_models) {
|
||||
TriangleMesh mesh = model.mesh();
|
||||
mesh.repair();
|
||||
|
||||
TriangleMeshPtrs meshes = mesh.cut_by_grid(m_config.option<ConfigOptionPoint>("cut_grid")->value);
|
||||
size_t i = 0;
|
||||
for (TriangleMesh* m : meshes) {
|
||||
Model out;
|
||||
auto o = out.add_object();
|
||||
o->add_volume(*m);
|
||||
o->input_file += "_" + std::to_string(i++);
|
||||
delete m;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: copy less stuff around using pointers
|
||||
m_models = new_models;
|
||||
|
||||
if (m_actions.empty())
|
||||
m_actions.push_back("export_stl");
|
||||
}
|
||||
#endif
|
||||
else if (opt_key == "split") {
|
||||
for (Model &model : m_models) {
|
||||
size_t num_objects = model.objects.size();
|
||||
for (size_t i = 0; i < num_objects; ++ i) {
|
||||
model.objects.front()->split(nullptr);
|
||||
model.delete_object(size_t(0));
|
||||
}
|
||||
}
|
||||
} else if (opt_key == "repair") {
|
||||
for (auto &model : m_models)
|
||||
model.repair();
|
||||
} else {
|
||||
boost::nowide::cerr << "error: option not implemented yet: " << opt_key << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// loop through action options
|
||||
for (auto const &opt_key : m_actions) {
|
||||
if (opt_key == "help") {
|
||||
this->print_help();
|
||||
} else if (opt_key == "help_fff") {
|
||||
this->print_help(true, ptFFF);
|
||||
} else if (opt_key == "help_sla") {
|
||||
this->print_help(true, ptSLA);
|
||||
} else if (opt_key == "save") {
|
||||
//FIXME check for mixing the FFF / SLA parameters.
|
||||
// or better save fff_print_config vs. sla_print_config
|
||||
m_print_config.save(m_config.opt_string("save"));
|
||||
} else if (opt_key == "info") {
|
||||
// --info works on unrepaired model
|
||||
for (Model &model : m_models) {
|
||||
model.add_default_instances();
|
||||
model.print_info();
|
||||
}
|
||||
} else if (opt_key == "export_stl") {
|
||||
for (auto &model : m_models)
|
||||
model.add_default_instances();
|
||||
if (! this->export_models(IO::STL))
|
||||
return 1;
|
||||
} else if (opt_key == "export_obj") {
|
||||
for (auto &model : m_models)
|
||||
model.add_default_instances();
|
||||
if (! this->export_models(IO::OBJ))
|
||||
return 1;
|
||||
} else if (opt_key == "export_amf") {
|
||||
if (! this->export_models(IO::AMF))
|
||||
return 1;
|
||||
} else if (opt_key == "export_3mf") {
|
||||
if (! this->export_models(IO::TMF))
|
||||
return 1;
|
||||
} else if (opt_key == "export_gcode" || opt_key == "export_sla" || opt_key == "slice") {
|
||||
if (opt_key == "export_gcode" && printer_technology == ptSLA) {
|
||||
boost::nowide::cerr << "error: cannot export G-code for an FFF configuration" << std::endl;
|
||||
return 1;
|
||||
} else if (opt_key == "export_sla" && printer_technology == ptFFF) {
|
||||
boost::nowide::cerr << "error: cannot export SLA slices for a SLA configuration" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
// Make a copy of the model if the current action is not the last action, as the model may be
|
||||
// modified by the centering and such.
|
||||
Model model_copy;
|
||||
bool make_copy = &opt_key != &m_actions.back();
|
||||
for (Model &model_in : m_models) {
|
||||
if (make_copy)
|
||||
model_copy = model_in;
|
||||
Model &model = make_copy ? model_copy : model_in;
|
||||
// If all objects have defined instances, their relative positions will be
|
||||
// honored when printing (they will be only centered, unless --dont-arrange
|
||||
// is supplied); if any object has no instances, it will get a default one
|
||||
// and all instances will be rearranged (unless --dont-arrange is supplied).
|
||||
std::string outfile = m_config.opt_string("output");
|
||||
Print fff_print;
|
||||
SLAPrint sla_print;
|
||||
PrintBase *print = (printer_technology == ptFFF) ? static_cast<PrintBase*>(&fff_print) : static_cast<PrintBase*>(&sla_print);
|
||||
if (! m_config.opt_bool("dont_arrange")) {
|
||||
//FIXME make the min_object_distance configurable.
|
||||
model.arrange_objects(fff_print.config().min_object_distance());
|
||||
model.center_instances_around_point(m_config.option<ConfigOptionPoint>("center")->value);
|
||||
}
|
||||
if (printer_technology == ptFFF) {
|
||||
for (auto* mo : model.objects)
|
||||
fff_print.auto_assign_extruders(mo);
|
||||
}
|
||||
print->apply(model, m_print_config);
|
||||
std::string err = print->validate();
|
||||
if (! err.empty()) {
|
||||
boost::nowide::cerr << err << std::endl;
|
||||
return 1;
|
||||
}
|
||||
if (print->empty())
|
||||
boost::nowide::cout << "Nothing to print for " << outfile << " . Either the print is empty or no object is fully inside the print volume." << std::endl;
|
||||
else
|
||||
try {
|
||||
std::string outfile_final;
|
||||
print->process();
|
||||
if (printer_technology == ptFFF) {
|
||||
// The outfile is processed by a PlaceholderParser.
|
||||
outfile = fff_print.export_gcode(outfile, nullptr);
|
||||
outfile_final = fff_print.print_statistics().finalize_output_path(outfile);
|
||||
} else {
|
||||
outfile = sla_print.output_filepath(outfile);
|
||||
//FIXME Tamas, please port it to miniz
|
||||
// sla_print.export_raster<SLAZipFmt>(outfile);
|
||||
outfile_final = sla_print.print_statistics().finalize_output_path(outfile);
|
||||
}
|
||||
if (outfile != outfile_final && Slic3r::rename_file(outfile, outfile_final) != 0) {
|
||||
boost::nowide::cerr << "Renaming file " << outfile << " to " << outfile_final << " failed" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
boost::nowide::cout << "Slicing result exported to " << outfile << std::endl;
|
||||
} catch (const std::exception &ex) {
|
||||
boost::nowide::cerr << ex.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
/*
|
||||
print.center = ! m_config.has("center")
|
||||
&& ! m_config.has("align_xy")
|
||||
&& ! m_config.opt_bool("dont_arrange");
|
||||
print.set_model(model);
|
||||
|
||||
// start chronometer
|
||||
typedef std::chrono::high_resolution_clock clock_;
|
||||
typedef std::chrono::duration<double, std::ratio<1> > second_;
|
||||
std::chrono::time_point<clock_> t0{ clock_::now() };
|
||||
|
||||
const std::string outfile = this->output_filepath(model, IO::Gcode);
|
||||
try {
|
||||
print.export_gcode(outfile);
|
||||
} catch (std::runtime_error &e) {
|
||||
boost::nowide::cerr << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
boost::nowide::cout << "G-code exported to " << outfile << std::endl;
|
||||
|
||||
// output some statistics
|
||||
double duration { std::chrono::duration_cast<second_>(clock_::now() - t0).count() };
|
||||
boost::nowide::cout << std::fixed << std::setprecision(0)
|
||||
<< "Done. Process took " << (duration/60) << " minutes and "
|
||||
<< std::setprecision(3)
|
||||
<< std::fmod(duration, 60.0) << " seconds." << std::endl
|
||||
<< std::setprecision(2)
|
||||
<< "Filament required: " << print.total_used_filament() << "mm"
|
||||
<< " (" << print.total_extruded_volume()/1000 << "cm3)" << std::endl;
|
||||
*/
|
||||
}
|
||||
} else {
|
||||
boost::nowide::cerr << "error: option not supported yet: " << opt_key << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (start_gui) {
|
||||
#if 1
|
||||
// #ifdef USE_WX
|
||||
GUI::GUI_App *gui = new GUI::GUI_App();
|
||||
// gui->autosave = m_config.opt_string("autosave");
|
||||
GUI::GUI_App::SetInstance(gui);
|
||||
gui->CallAfter([gui, this, &load_configs] {
|
||||
if (!gui->initialized()) {
|
||||
return;
|
||||
}
|
||||
#if 0
|
||||
// Load the cummulative config over the currently active profiles.
|
||||
//FIXME if multiple configs are loaded, only the last one will have an effect.
|
||||
// We need to decide what to do about loading of separate presets (just print preset, just filament preset etc).
|
||||
// As of now only the full configs are supported here.
|
||||
if (!m_print_config.empty())
|
||||
gui->mainframe->load_config(m_print_config);
|
||||
#endif
|
||||
if (! load_configs.empty())
|
||||
// Load the last config to give it a name at the UI. The name of the preset may be later
|
||||
// changed by loading an AMF or 3MF.
|
||||
//FIXME this is not strictly correct, as one may pass a print/filament/printer profile here instead of a full config.
|
||||
gui->mainframe->load_config_file(load_configs.back());
|
||||
// If loading a 3MF file, the config is loaded from the last one.
|
||||
if (! m_input_files.empty())
|
||||
gui->plater()->load_files(m_input_files, true, true);
|
||||
if (! m_extra_config.empty())
|
||||
gui->mainframe->load_config(m_extra_config);
|
||||
});
|
||||
return wxEntry(argc, argv);
|
||||
#else
|
||||
// No GUI support. Just print out a help.
|
||||
this->print_help(false);
|
||||
// If started without a parameter, consider it to be OK, otherwise report an error code (no action etc).
|
||||
return (argc == 0) ? 0 : 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool CLI::setup(int argc, char **argv)
|
||||
{
|
||||
{
|
||||
const char *loglevel = boost::nowide::getenv("SLIC3R_LOGLEVEL");
|
||||
@ -58,15 +492,6 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
// parse all command line options into a DynamicConfig
|
||||
DynamicPrintAndCLIConfig all_config;
|
||||
t_config_option_keys input_files;
|
||||
// if any option is unsupported, print usage and abort immediately
|
||||
if (! all_config.read_cli(argc, argv, &input_files)) {
|
||||
printUsage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
boost::filesystem::path path_to_binary = boost::filesystem::system_complete(argv[0]);
|
||||
|
||||
// Path from the Slic3r binary to its resources.
|
||||
@ -94,207 +519,114 @@ int main(int argc, char **argv)
|
||||
set_var_dir((path_resources / "icons").string());
|
||||
set_local_dir((path_resources / "localization").string());
|
||||
|
||||
// apply command line options to a more handy CLIConfig
|
||||
CLIConfig cli_config;
|
||||
#ifdef __APPLE__
|
||||
// Enable the GUI mode by default, to support drag & drop.
|
||||
cli_config.gui.value = true;
|
||||
#endif /* __APPLE__ */
|
||||
// Parse all command line options into a DynamicConfig.
|
||||
// If any option is unsupported, print usage and abort immediately.
|
||||
t_config_option_keys opt_order;
|
||||
if (! m_config.read_cli(argc, argv, &m_input_files, &opt_order)) {
|
||||
// Separate error message reported by the CLI parser from the help.
|
||||
boost::nowide::cerr << std::endl;
|
||||
this->print_help();
|
||||
return false;
|
||||
}
|
||||
// Parse actions and transform options.
|
||||
for (auto const &opt_key : opt_order) {
|
||||
if (cli_actions_config_def.has(opt_key))
|
||||
m_actions.emplace_back(opt_key);
|
||||
else if (cli_transform_config_def.has(opt_key))
|
||||
m_transforms.emplace_back(opt_key);
|
||||
}
|
||||
|
||||
cli_config.apply(all_config, true);
|
||||
set_data_dir(cli_config.datadir.value);
|
||||
|
||||
// Load the extra config values.
|
||||
DynamicPrintConfig extra_config;
|
||||
extra_config.apply(all_config, true);
|
||||
|
||||
// load config files supplied via --load
|
||||
DynamicPrintConfig print_config;
|
||||
for (const std::string &file : cli_config.load.values) {
|
||||
if (! boost::filesystem::exists(file)) {
|
||||
boost::nowide::cout << "No such file: " << file << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
DynamicPrintConfig c;
|
||||
try {
|
||||
c.load(file);
|
||||
} catch (std::exception &e) {
|
||||
boost::nowide::cout << "Error while reading config file: " << e.what() << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
c.normalize();
|
||||
print_config.apply(c);
|
||||
{
|
||||
const ConfigOptionInt *opt_loglevel = m_config.opt<ConfigOptionInt>("loglevel");
|
||||
if (opt_loglevel != 0)
|
||||
set_logging_level(opt_loglevel->value);
|
||||
}
|
||||
|
||||
if ((input_files.empty() || cli_config.gui.value) && ! cli_config.no_gui.value && ! cli_config.help.value && cli_config.save.value.empty()) {
|
||||
#if 1
|
||||
GUI::GUI_App *gui = new GUI::GUI_App();
|
||||
GUI::GUI_App::SetInstance(gui);
|
||||
gui->CallAfter([gui, &input_files, &cli_config, &extra_config, &print_config] {
|
||||
if (! gui->initialized()) {
|
||||
return;
|
||||
}
|
||||
#if 0
|
||||
// Load the cummulative config over the currently active profiles.
|
||||
//FIXME if multiple configs are loaded, only the last one will have an effect.
|
||||
// We need to decide what to do about loading of separate presets (just print preset, just filament preset etc).
|
||||
// As of now only the full configs are supported here.
|
||||
if (! print_config.empty())
|
||||
gui->mainframe->load_config(print_config);
|
||||
#endif
|
||||
if (! cli_config.load.values.empty())
|
||||
// Load the last config to give it a name at the UI. The name of the preset may be later
|
||||
// changed by loading an AMF or 3MF.
|
||||
//FIXME this is not strictly correct, as one may pass a print/filament/printer profile here instead of a full config.
|
||||
gui->mainframe->load_config_file(cli_config.load.values.back());
|
||||
// If loading a 3MF file, the config is loaded from the last one.
|
||||
gui->plater()->load_files(input_files, true, true);
|
||||
if (! extra_config.empty())
|
||||
gui->mainframe->load_config(extra_config);
|
||||
});
|
||||
return wxEntry(argc, argv);
|
||||
#else
|
||||
std::cout << "GUI support has not been built." << "\n";
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
// Initialize with defaults.
|
||||
for (const t_optiondef_map *options : { &cli_actions_config_def.options, &cli_transform_config_def.options, &cli_misc_config_def.options })
|
||||
for (const std::pair<t_config_option_key, ConfigOptionDef> &optdef : *options)
|
||||
m_config.optptr(optdef.first, true);
|
||||
|
||||
// apply command line options to a more specific DynamicPrintConfig which provides normalize()
|
||||
// (command line options override --load files)
|
||||
print_config.apply(extra_config, true);
|
||||
|
||||
// write config if requested
|
||||
if (! cli_config.save.value.empty()) {
|
||||
print_config.normalize();
|
||||
print_config.save(cli_config.save.value);
|
||||
}
|
||||
set_data_dir(m_config.opt_string("datadir"));
|
||||
|
||||
if (cli_config.help) {
|
||||
printUsage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// read input file(s) if any
|
||||
std::vector<Model> models;
|
||||
for (const t_config_option_key &file : input_files) {
|
||||
if (! boost::filesystem::exists(file)) {
|
||||
boost::nowide::cerr << "No such file: " << file << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
Model model;
|
||||
try {
|
||||
model = Model::read_from_file(file, &print_config, true);
|
||||
} catch (std::exception &e) {
|
||||
boost::nowide::cerr << file << ": " << e.what() << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
if (model.objects.empty()) {
|
||||
boost::nowide::cerr << "Error: file is empty: " << file << std::endl;
|
||||
continue;
|
||||
}
|
||||
model.add_default_instances();
|
||||
// apply command line transform options
|
||||
for (ModelObject* o : model.objects) {
|
||||
/*
|
||||
if (cli_config.scale_to_fit.is_positive_volume())
|
||||
o->scale_to_fit(cli_config.scale_to_fit.value);
|
||||
*/
|
||||
// TODO: honor option order?
|
||||
o->scale(cli_config.scale.value);
|
||||
o->rotate(Geometry::deg2rad(cli_config.rotate_x.value), X);
|
||||
o->rotate(Geometry::deg2rad(cli_config.rotate_y.value), Y);
|
||||
o->rotate(Geometry::deg2rad(cli_config.rotate.value), Z);
|
||||
}
|
||||
// TODO: handle --merge
|
||||
models.push_back(model);
|
||||
}
|
||||
|
||||
for (Model &model : models) {
|
||||
if (cli_config.info) {
|
||||
// --info works on unrepaired model
|
||||
model.print_info();
|
||||
} else if (cli_config.export_3mf) {
|
||||
std::string outfile = cli_config.output.value;
|
||||
if (outfile.empty()) outfile = model.objects.front()->input_file;
|
||||
// Check if the file is already a 3mf.
|
||||
if(outfile.substr(outfile.find_last_of('.'), outfile.length()) == ".3mf")
|
||||
outfile = outfile.substr(0, outfile.find_last_of('.')) + "_2" + ".3mf";
|
||||
else
|
||||
// Remove the previous extension and add .3mf extention.
|
||||
outfile = outfile.substr(0, outfile.find_last_of('.')) + ".3mf";
|
||||
store_3mf(outfile.c_str(), &model, nullptr);
|
||||
boost::nowide::cout << "File file exported to " << outfile << std::endl;
|
||||
} else if (cli_config.cut > 0) {
|
||||
model.repair();
|
||||
model.translate(0, 0, - model.bounding_box().min(2));
|
||||
if (! model.objects.empty()) {
|
||||
// XXX
|
||||
// Model out;
|
||||
// model.objects.front()->cut(cli_config.cut, &out);
|
||||
// ModelObject &upper = *out.objects[0];
|
||||
// ModelObject &lower = *out.objects[1];
|
||||
// // Use the input name and trim off the extension.
|
||||
// std::string outfile = cli_config.output.value;
|
||||
// if (outfile.empty())
|
||||
// outfile = model.objects.front()->input_file;
|
||||
// outfile = outfile.substr(0, outfile.find_last_of('.'));
|
||||
// std::cerr << outfile << "\n";
|
||||
// if (upper.facets_count() > 0)
|
||||
// upper.mesh().write_binary((outfile + "_upper.stl").c_str());
|
||||
// if (lower.facets_count() > 0)
|
||||
// lower.mesh().write_binary((outfile + "_lower.stl").c_str());
|
||||
}
|
||||
} else if (cli_config.slice) {
|
||||
PrinterTechnology printer_technology = print_config.option<ConfigOptionEnum<PrinterTechnology>>("printer_technology", true)->value;
|
||||
std::string outfile = cli_config.output.value;
|
||||
Print fff_print;
|
||||
SLAPrint sla_print;
|
||||
PrintBase *print = (printer_technology == ptFFF) ? static_cast<PrintBase*>(&fff_print) : static_cast<PrintBase*>(&sla_print);
|
||||
if (! cli_config.dont_arrange) {
|
||||
//FIXME make the min_object_distance configurable.
|
||||
model.arrange_objects(fff_print.config().min_object_distance());
|
||||
model.center_instances_around_point(cli_config.print_center);
|
||||
}
|
||||
if (printer_technology == ptFFF) {
|
||||
for (auto* mo : model.objects)
|
||||
fff_print.auto_assign_extruders(mo);
|
||||
}
|
||||
print_config.normalize();
|
||||
print->apply(model, print_config);
|
||||
std::string err = print->validate();
|
||||
if (err.empty()) {
|
||||
if (printer_technology == ptFFF) {
|
||||
// The outfile is processed by a PlaceholderParser.
|
||||
fff_print.export_gcode(outfile, nullptr);
|
||||
} else {
|
||||
assert(printer_technology == ptSLA);
|
||||
//FIXME add the output here
|
||||
}
|
||||
} else
|
||||
std::cerr << err << "\n";
|
||||
} else {
|
||||
boost::nowide::cerr << "error: command not supported" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
void printUsage()
|
||||
void CLI::print_help(bool include_print_options, PrinterTechnology printer_technology) const
|
||||
{
|
||||
std::cout << "Slic3r " << SLIC3R_VERSION << " is a STL-to-GCODE translator for RepRap 3D printers" << "\n"
|
||||
<< "written by Alessandro Ranellucci <aar@cpan.org> - http://slic3r.org/ - https://github.com/slic3r/Slic3r" << "\n"
|
||||
// << "Git Version " << BUILD_COMMIT << "\n\n"
|
||||
<< "Usage: ./slic3r [ OPTIONS ] [ file.stl ] [ file2.stl ] ..." << "\n";
|
||||
// CLI Options
|
||||
std::cout << "** CLI OPTIONS **\n";
|
||||
print_cli_options(boost::nowide::cout);
|
||||
std::cout << "****\n";
|
||||
// Print options
|
||||
std::cout << "** PRINT OPTIONS **\n";
|
||||
print_print_options(boost::nowide::cout);
|
||||
std::cout << "****\n";
|
||||
boost::nowide::cout
|
||||
<< "Slic3r Prusa Edition " << SLIC3R_BUILD << std::endl
|
||||
<< "https://github.com/prusa3d/Slic3r" << std::endl << std::endl
|
||||
<< "Usage: slic3r [ ACTIONS ] [ TRANSFORM ] [ OPTIONS ] [ file.stl ... ]" << std::endl
|
||||
<< std::endl
|
||||
<< "Actions:" << std::endl;
|
||||
cli_actions_config_def.print_cli_help(boost::nowide::cout, false);
|
||||
|
||||
boost::nowide::cout
|
||||
<< std::endl
|
||||
<< "Transform options:" << std::endl;
|
||||
cli_transform_config_def.print_cli_help(boost::nowide::cout, false);
|
||||
|
||||
boost::nowide::cout
|
||||
<< std::endl
|
||||
<< "Other options:" << std::endl;
|
||||
cli_misc_config_def.print_cli_help(boost::nowide::cout, false);
|
||||
|
||||
if (include_print_options) {
|
||||
boost::nowide::cout << std::endl;
|
||||
print_config_def.print_cli_help(boost::nowide::cout, true, [printer_technology](const ConfigOptionDef &def)
|
||||
{ return (printer_technology & def.printer_technology) != 0; });
|
||||
} else {
|
||||
boost::nowide::cout
|
||||
<< std::endl
|
||||
<< "Run --help-fff / --help-sla to see the full listing of print options." << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
bool CLI::export_models(IO::ExportFormat format)
|
||||
{
|
||||
for (Model &model : m_models) {
|
||||
const std::string path = this->output_filepath(model, format);
|
||||
bool success = false;
|
||||
switch (format) {
|
||||
case IO::AMF: success = Slic3r::store_amf(path.c_str(), &model, nullptr); break;
|
||||
case IO::OBJ: success = Slic3r::store_obj(path.c_str(), &model); break;
|
||||
case IO::STL: success = Slic3r::store_stl(path.c_str(), &model, true); break;
|
||||
case IO::TMF: success = Slic3r::store_3mf(path.c_str(), &model, nullptr); break;
|
||||
default: assert(false); break;
|
||||
}
|
||||
if (success)
|
||||
std::cout << "File exported to " << path << std::endl;
|
||||
else {
|
||||
std::cerr << "File export to " << path << " failed" << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string CLI::output_filepath(const Model &model, IO::ExportFormat format) const
|
||||
{
|
||||
std::string ext;
|
||||
switch (format) {
|
||||
case IO::AMF: ext = ".amf"; break;
|
||||
case IO::OBJ: ext = ".obj"; break;
|
||||
case IO::STL: ext = ".stl"; break;
|
||||
case IO::TMF: ext = ".3mf"; break;
|
||||
default: assert(false); break;
|
||||
};
|
||||
auto proposed_path = boost::filesystem::path(model.propose_export_file_name_and_path(ext));
|
||||
// use --output when available
|
||||
std::string cmdline_param = m_config.opt_string("output");
|
||||
if (! cmdline_param.empty()) {
|
||||
// if we were supplied a directory, use it and append our automatically generated filename
|
||||
boost::filesystem::path cmdline_path(cmdline_param);
|
||||
if (boost::filesystem::is_directory(cmdline_path))
|
||||
proposed_path = cmdline_path / proposed_path.filename();
|
||||
else
|
||||
proposed_path = cmdline_path;
|
||||
}
|
||||
return proposed_path.string();
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
@ -309,7 +641,12 @@ extern "C" {
|
||||
for (size_t i = 0; i < argc; ++ i)
|
||||
argv_ptrs[i] = const_cast<char*>(argv_narrow[i].data());
|
||||
// Call the UTF8 main.
|
||||
return slic3r_main_(argc, argv_ptrs.data());
|
||||
return CLI().run(argc, argv_ptrs.data());
|
||||
}
|
||||
}
|
||||
#else /* _MSC_VER */
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
return CLI().run(argc, argv);
|
||||
}
|
||||
#endif /* _MSC_VER */
|
||||
|
48
src/slic3r.hpp
Normal file
@ -0,0 +1,48 @@
|
||||
#ifndef SLIC3R_HPP
|
||||
#define SLIC3R_HPP
|
||||
|
||||
#include "libslic3r/Config.hpp"
|
||||
#include "libslic3r/Model.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
namespace IO {
|
||||
enum ExportFormat : int {
|
||||
AMF,
|
||||
OBJ,
|
||||
STL,
|
||||
// SVG,
|
||||
TMF,
|
||||
Gcode
|
||||
};
|
||||
}
|
||||
|
||||
class CLI {
|
||||
public:
|
||||
int run(int argc, char **argv);
|
||||
|
||||
private:
|
||||
DynamicPrintAndCLIConfig m_config;
|
||||
DynamicPrintConfig m_print_config;
|
||||
DynamicPrintConfig m_extra_config;
|
||||
std::vector<std::string> m_input_files;
|
||||
std::vector<std::string> m_actions;
|
||||
std::vector<std::string> m_transforms;
|
||||
std::vector<Model> m_models;
|
||||
|
||||
bool setup(int argc, char **argv);
|
||||
|
||||
/// Prints usage of the CLI.
|
||||
void print_help(bool include_print_options = false, PrinterTechnology printer_technology = ptFFF | ptSLA | ptSLS) const;
|
||||
|
||||
/// Exports loaded models to a file of the specified format, according to the options affecting output filename.
|
||||
bool export_models(IO::ExportFormat format);
|
||||
|
||||
bool has_print_action() const { return m_config.opt_bool("export_gcode") || m_config.opt_bool("export_sla"); }
|
||||
|
||||
std::string output_filepath(const Model &model, IO::ExportFormat format) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -28,8 +28,22 @@ set(SLIC3R_GUI_SOURCES
|
||||
GUI/GLCanvas3D.cpp
|
||||
GUI/GLCanvas3DManager.hpp
|
||||
GUI/GLCanvas3DManager.cpp
|
||||
GUI/GLGizmo.hpp
|
||||
GUI/GLGizmo.cpp
|
||||
GUI/Selection.hpp
|
||||
GUI/Selection.cpp
|
||||
GUI/Gizmos/GLGizmoBase.cpp
|
||||
GUI/Gizmos/GLGizmoBase.hpp
|
||||
GUI/Gizmos/GLGizmoMove.cpp
|
||||
GUI/Gizmos/GLGizmoMove.hpp
|
||||
GUI/Gizmos/GLGizmoRotate.cpp
|
||||
GUI/Gizmos/GLGizmoRotate.hpp
|
||||
GUI/Gizmos/GLGizmoScale.cpp
|
||||
GUI/Gizmos/GLGizmoScale.hpp
|
||||
GUI/Gizmos/GLGizmoSlaSupports.cpp
|
||||
GUI/Gizmos/GLGizmoSlaSupports.hpp
|
||||
GUI/Gizmos/GLGizmoFlatten.cpp
|
||||
GUI/Gizmos/GLGizmoFlatten.hpp
|
||||
GUI/Gizmos/GLGizmoCut.cpp
|
||||
GUI/Gizmos/GLGizmoCut.hpp
|
||||
GUI/GLTexture.hpp
|
||||
GUI/GLTexture.cpp
|
||||
GUI/GLToolbar.hpp
|
||||
@ -76,6 +90,8 @@ set(SLIC3R_GUI_SOURCES
|
||||
GUI/2DBed.hpp
|
||||
GUI/3DBed.cpp
|
||||
GUI/3DBed.hpp
|
||||
GUI/Camera.cpp
|
||||
GUI/Camera.hpp
|
||||
GUI/wxExtensions.cpp
|
||||
GUI/wxExtensions.hpp
|
||||
GUI/WipeTowerDialog.cpp
|
||||
|