Merge remote-tracking branch 'origin/master' into ys_msw_dpi
309
README.md
|
@ -20,9 +20,8 @@ All user facing code is written in C++, and some legacy code as well as unit
|
|||
tests are written in Perl. Perl is not required for either development or use
|
||||
of Slic3r.
|
||||
|
||||
The C++ API is public and its use in other projects is encouraged.
|
||||
The goal is to make Slic3r fully modular so that any part of its logic
|
||||
can be used separately.
|
||||
The slicing core is the `libslic3r` library, which can be built and used in a standalone way.
|
||||
The command line interface is a thin wrapper over `libslic3r`.
|
||||
|
||||
### What are Slic3r's main features?
|
||||
|
||||
|
@ -67,309 +66,13 @@ Sure! You can do the following to find things that are available to help with:
|
|||
|
||||
### What's Slic3r license?
|
||||
|
||||
Slic3r is licensed under the _GNU Affero General Public License, version 3_.
|
||||
The author is Alessandro Ranellucci.
|
||||
Slic3r PE is licensed under the _GNU Affero General Public License, version 3_.
|
||||
The Prusa Edition is originally based on Slic3r by Alessandro Ranellucci.
|
||||
|
||||
The [Silk icon set](http://www.famfamfam.com/lab/icons/silk/) used in Slic3r is
|
||||
licensed under the _Creative Commons Attribution 3.0 License_.
|
||||
The author of the Silk icon set is Mark James.
|
||||
|
||||
### How can I invoke slic3r.pl using the command line?
|
||||
### How can I use Slic3r PE from the command line?
|
||||
|
||||
Usage: slic3r.pl [ OPTIONS ] [ file.stl ] [ file2.stl ] ...
|
||||
|
||||
--help Output this usage screen and exit
|
||||
--version Output the version of Slic3r and exit
|
||||
--save <file> Save configuration to the specified file
|
||||
--load <file> Load configuration from the specified file. It can be used
|
||||
more than once to load options from multiple files.
|
||||
-o, --output <file> File to output gcode to (by default, the file will be saved
|
||||
into the same directory as the input file using the
|
||||
--output-filename-format to generate the filename.) If a
|
||||
directory is specified for this option, the output will
|
||||
be saved under that directory, and the filename will be
|
||||
generated by --output-filename-format.
|
||||
|
||||
Non-slicing actions (no G-code will be generated):
|
||||
--repair Repair given STL files and save them as <name>_fixed.obj
|
||||
--cut <z> Cut given input files at given Z (relative) and export
|
||||
them as <name>_upper.stl and <name>_lower.stl
|
||||
--split Split the shells contained in given STL file into several STL files
|
||||
--info Output information about the supplied file(s) and exit
|
||||
|
||||
-j, --threads <num> Number of threads to use (1+, default: 2)
|
||||
|
||||
GUI options:
|
||||
--gui Forces the GUI launch instead of command line slicing (if you
|
||||
supply a model file, it will be loaded into the plater)
|
||||
--no-plater Disable the plater tab
|
||||
--no-gui Forces the command line slicing instead of gui.
|
||||
This takes precedence over --gui if both are present.
|
||||
--autosave <file> Automatically export current configuration to the specified file
|
||||
|
||||
Output options:
|
||||
--output-filename-format
|
||||
Output file name format; all config options enclosed in brackets
|
||||
will be replaced by their values, as well as [input_filename_base]
|
||||
and [input_filename] (default: [input_filename_base].gcode)
|
||||
--post-process Generated G-code will be processed with the supplied script;
|
||||
call this more than once to process through multiple scripts.
|
||||
--export-png Export zipped PNG files containing slices instead of G-code.
|
||||
-m, --merge If multiple files are supplied, they will be composed into a single
|
||||
print rather than processed individually.
|
||||
|
||||
Printer options:
|
||||
--nozzle-diameter Diameter of nozzle in mm (default: 0.5)
|
||||
--print-center Coordinates in mm of the point to center the print around
|
||||
(default: 100,100)
|
||||
--z-offset Additional height in mm to add to vertical coordinates
|
||||
(+/-, default: 0)
|
||||
--gcode-flavor The type of G-code to generate (reprap/teacup/repetier/makerware/sailfish/mach3/machinekit/smoothie/no-extrusion,
|
||||
default: reprap)
|
||||
--use-relative-e-distances Enable this to get relative E values (default: no)
|
||||
--use-firmware-retraction Enable firmware-controlled retraction using G10/G11 (default: no)
|
||||
--use-volumetric-e Express E in cubic millimeters and prepend M200 (default: no)
|
||||
--gcode-comments Make G-code verbose by adding comments (default: no)
|
||||
|
||||
Filament options:
|
||||
--filament-diameter Diameter in mm of your raw filament (default: 3)
|
||||
--extrusion-multiplier
|
||||
Change this to alter the amount of plastic extruded. There should be
|
||||
very little need to change this value, which is only useful to
|
||||
compensate for filament packing (default: 1)
|
||||
--temperature Extrusion temperature in degree Celsius, set 0 to disable (default: 200)
|
||||
--first-layer-temperature Extrusion temperature for the first layer, in degree Celsius,
|
||||
set 0 to disable (default: same as --temperature)
|
||||
--bed-temperature Heated bed temperature in degree Celsius, set 0 to disable (default: 0)
|
||||
--first-layer-bed-temperature Heated bed temperature for the first layer, in degree Celsius,
|
||||
set 0 to disable (default: same as --bed-temperature)
|
||||
|
||||
Speed options:
|
||||
--travel-speed Speed of non-print moves in mm/s (default: 130)
|
||||
--perimeter-speed Speed of print moves for perimeters in mm/s (default: 30)
|
||||
--small-perimeter-speed
|
||||
Speed of print moves for small perimeters in mm/s or % over perimeter speed
|
||||
(default: 30)
|
||||
--external-perimeter-speed
|
||||
Speed of print moves for the external perimeter in mm/s or % over perimeter speed
|
||||
(default: 70%)
|
||||
--infill-speed Speed of print moves in mm/s (default: 60)
|
||||
--solid-infill-speed Speed of print moves for solid surfaces in mm/s or % over infill speed
|
||||
(default: 60)
|
||||
--top-solid-infill-speed Speed of print moves for top surfaces in mm/s or % over solid infill speed
|
||||
(default: 50)
|
||||
--support-material-speed
|
||||
Speed of support material print moves in mm/s (default: 60)
|
||||
--support-material-interface-speed
|
||||
Speed of support material interface print moves in mm/s or % over support material
|
||||
speed (default: 100%)
|
||||
--bridge-speed Speed of bridge print moves in mm/s (default: 60)
|
||||
--gap-fill-speed Speed of gap fill print moves in mm/s (default: 20)
|
||||
--first-layer-speed Speed of print moves for bottom layer, expressed either as an absolute
|
||||
value or as a percentage over normal speeds (default: 30%)
|
||||
|
||||
Acceleration options:
|
||||
--perimeter-acceleration
|
||||
Overrides firmware's default acceleration for perimeters. (mm/s^2, set zero
|
||||
to disable; default: 0)
|
||||
--infill-acceleration
|
||||
Overrides firmware's default acceleration for infill. (mm/s^2, set zero
|
||||
to disable; default: 0)
|
||||
--bridge-acceleration
|
||||
Overrides firmware's default acceleration for bridges. (mm/s^2, set zero
|
||||
to disable; default: 0)
|
||||
--first-layer-acceleration
|
||||
Overrides firmware's default acceleration for first layer. (mm/s^2, set zero
|
||||
to disable; default: 0)
|
||||
--default-acceleration
|
||||
Acceleration will be reset to this value after the specific settings above
|
||||
have been applied. (mm/s^2, set zero to disable; default: 0)
|
||||
|
||||
Accuracy options:
|
||||
--layer-height Layer height in mm (default: 0.3)
|
||||
--first-layer-height Layer height for first layer (mm or %, default: 0.35)
|
||||
--infill-every-layers
|
||||
Infill every N layers (default: 1)
|
||||
--solid-infill-every-layers
|
||||
Force a solid layer every N layers (default: 0)
|
||||
|
||||
Print options:
|
||||
--perimeters Number of perimeters/horizontal skins (range: 0+, default: 3)
|
||||
--top-solid-layers Number of solid layers to do for top surfaces (range: 0+, default: 3)
|
||||
--bottom-solid-layers Number of solid layers to do for bottom surfaces (range: 0+, default: 3)
|
||||
--solid-layers Shortcut for setting the two options above at once
|
||||
--fill-density Infill density (range: 0%-100%, default: 40%)
|
||||
--fill-angle Infill angle in degrees (range: 0-90, default: 45)
|
||||
--fill-pattern Pattern to use to fill non-solid layers (default: honeycomb)
|
||||
--solid-fill-pattern Pattern to use to fill solid layers (default: rectilinear)
|
||||
--start-gcode Load initial G-code from the supplied file. This will overwrite
|
||||
the default command (home all axes [G28]).
|
||||
--end-gcode Load final G-code from the supplied file. This will overwrite
|
||||
the default commands (turn off temperature [M104 S0],
|
||||
home X axis [G28 X], disable motors [M84]).
|
||||
--before-layer-gcode Load before-layer-change G-code from the supplied file (default: nothing).
|
||||
--layer-gcode Load after-layer-change G-code from the supplied file (default: nothing).
|
||||
--toolchange-gcode Load tool-change G-code from the supplied file (default: nothing).
|
||||
--seam-position Position of loop starting points (random/nearest/aligned, default: aligned).
|
||||
--external-perimeters-first Reverse perimeter order. (default: no)
|
||||
--spiral-vase Experimental option to raise Z gradually when printing single-walled vases
|
||||
(default: no)
|
||||
--only-retract-when-crossing-perimeters
|
||||
Disable retraction when travelling between infill paths inside the same island.
|
||||
(default: no)
|
||||
--solid-infill-below-area
|
||||
Force solid infill when a region has a smaller area than this threshold
|
||||
(mm^2, default: 70)
|
||||
--infill-only-where-needed
|
||||
Only infill under ceilings (default: no)
|
||||
--infill-first Make infill before perimeters (default: no)
|
||||
|
||||
Quality options (slower slicing):
|
||||
--extra-perimeters Add more perimeters when needed (default: yes)
|
||||
--avoid-crossing-perimeters Optimize travel moves so that no perimeters are crossed (default: no)
|
||||
--thin-walls Detect single-width walls (default: yes)
|
||||
--overhangs Experimental option to use bridge flow, speed and fan for overhangs
|
||||
(default: yes)
|
||||
|
||||
Support material options:
|
||||
--support-material Generate support material for overhangs
|
||||
--support-material-threshold
|
||||
Overhang threshold angle (range: 0-90, set 0 for automatic detection,
|
||||
default: 0)
|
||||
--support-material-pattern
|
||||
Pattern to use for support material (default: honeycomb)
|
||||
--support-material-spacing
|
||||
Spacing between pattern lines (mm, default: 2.5)
|
||||
--support-material-angle
|
||||
Support material angle in degrees (range: 0-90, default: 0)
|
||||
--support-material-contact-distance
|
||||
Vertical distance between object and support material
|
||||
(0+, default: 0.2)
|
||||
--support-material-interface-layers
|
||||
Number of perpendicular layers between support material and object (0+, default: 3)
|
||||
--support-material-interface-spacing
|
||||
Spacing between interface pattern lines (mm, set 0 to get a solid layer, default: 0)
|
||||
--raft-layers Number of layers to raise the printed objects by (range: 0+, default: 0)
|
||||
--support-material-enforce-layers
|
||||
Enforce support material on the specified number of layers from bottom,
|
||||
regardless of --support-material and threshold (0+, default: 0)
|
||||
--dont-support-bridges
|
||||
Experimental option for preventing support material from being generated under bridged areas (default: yes)
|
||||
|
||||
Retraction options:
|
||||
--retract-length Length of retraction in mm when pausing extrusion (default: 1)
|
||||
--retract-speed Speed for retraction in mm/s (default: 30)
|
||||
--retract-restart-extra
|
||||
Additional amount of filament in mm to push after
|
||||
compensating retraction (default: 0)
|
||||
--retract-before-travel
|
||||
Only retract before travel moves of this length in mm (default: 2)
|
||||
--retract-lift Lift Z by the given distance in mm when retracting (default: 0)
|
||||
--retract-lift-above Only lift Z when above the specified height (default: 0)
|
||||
--retract-lift-below Only lift Z when below the specified height (default: 0)
|
||||
--retract-layer-change
|
||||
Enforce a retraction before each Z move (default: no)
|
||||
--wipe Wipe the nozzle while doing a retraction (default: no)
|
||||
|
||||
Retraction options for multi-extruder setups:
|
||||
--retract-length-toolchange
|
||||
Length of retraction in mm when disabling tool (default: 10)
|
||||
--retract-restart-extra-toolchange
|
||||
Additional amount of filament in mm to push after
|
||||
switching tool (default: 0)
|
||||
|
||||
Cooling options:
|
||||
--cooling Enable fan and cooling control
|
||||
--min-fan-speed Minimum fan speed (default: 35%)
|
||||
--max-fan-speed Maximum fan speed (default: 100%)
|
||||
--bridge-fan-speed Fan speed to use when bridging (default: 100%)
|
||||
--fan-below-layer-time Enable fan if layer print time is below this approximate number
|
||||
of seconds (default: 60)
|
||||
--slowdown-below-layer-time Slow down if layer print time is below this approximate number
|
||||
of seconds (default: 30)
|
||||
--min-print-speed Minimum print speed (mm/s, default: 10)
|
||||
--disable-fan-first-layers Disable fan for the first N layers (default: 1)
|
||||
--fan-always-on Keep fan always on at min fan speed, even for layers that don't need
|
||||
cooling
|
||||
|
||||
Skirt options:
|
||||
--skirts Number of skirts to draw (0+, default: 1)
|
||||
--skirt-distance Distance in mm between innermost skirt and object
|
||||
(default: 6)
|
||||
--skirt-height Height of skirts to draw (expressed in layers, 0+, default: 1)
|
||||
--min-skirt-length Generate no less than the number of loops required to consume this length
|
||||
of filament on the first layer, for each extruder (mm, 0+, default: 0)
|
||||
--brim-width Width of the brim that will get added to each object to help adhesion
|
||||
(mm, default: 0)
|
||||
|
||||
Transform options:
|
||||
--scale Factor for scaling input object (default: 1)
|
||||
--rotate Rotation angle in degrees (0-360, default: 0)
|
||||
--duplicate Number of items with auto-arrange (1+, default: 1)
|
||||
--duplicate-grid Number of items with grid arrangement (default: 1,1)
|
||||
--duplicate-distance Distance in mm between copies (default: 6)
|
||||
--dont-arrange Don't arrange the objects on the build plate. The model coordinates
|
||||
define the absolute positions on the build plate.
|
||||
The option --print-center will be ignored.
|
||||
--xy-size-compensation
|
||||
Grow/shrink objects by the configured absolute distance (mm, default: 0)
|
||||
|
||||
Sequential printing options:
|
||||
--complete-objects When printing multiple objects and/or copies, complete each one before
|
||||
starting the next one; watch out for extruder collisions (default: no)
|
||||
--extruder-clearance-radius Radius in mm above which extruder won't collide with anything
|
||||
(default: 20)
|
||||
--extruder-clearance-height Maximum vertical extruder depth; i.e. vertical distance from
|
||||
extruder tip and carriage bottom (default: 20)
|
||||
|
||||
Miscellaneous options:
|
||||
--notes Notes to be added as comments to the output file
|
||||
--resolution Minimum detail resolution (mm, set zero for full resolution, default: 0)
|
||||
|
||||
Flow options (advanced):
|
||||
--extrusion-width Set extrusion width manually; it accepts either an absolute value in mm
|
||||
(like 0.65) or a percentage over layer height (like 200%)
|
||||
--first-layer-extrusion-width
|
||||
Set a different extrusion width for first layer
|
||||
--perimeter-extrusion-width
|
||||
Set a different extrusion width for perimeters
|
||||
--external-perimeter-extrusion-width
|
||||
Set a different extrusion width for external perimeters
|
||||
--infill-extrusion-width
|
||||
Set a different extrusion width for infill
|
||||
--solid-infill-extrusion-width
|
||||
Set a different extrusion width for solid infill
|
||||
--top-infill-extrusion-width
|
||||
Set a different extrusion width for top infill
|
||||
--support-material-extrusion-width
|
||||
Set a different extrusion width for support material
|
||||
--infill-overlap Overlap between infill and perimeters (default: 15%)
|
||||
--bridge-flow-ratio Multiplier for extrusion when bridging (> 0, default: 1)
|
||||
|
||||
Multiple extruder options:
|
||||
--extruder-offset Offset of each extruder, if firmware doesn't handle the displacement
|
||||
(can be specified multiple times, default: 0x0)
|
||||
--perimeter-extruder
|
||||
Extruder to use for perimeters and brim (1+, default: 1)
|
||||
--infill-extruder Extruder to use for infill (1+, default: 1)
|
||||
--solid-infill-extruder Extruder to use for solid infill (1+, default: 1)
|
||||
--support-material-extruder
|
||||
Extruder to use for support material, raft and skirt (1+, default: 1)
|
||||
--support-material-interface-extruder
|
||||
Extruder to use for support material interface (1+, default: 1)
|
||||
--ooze-prevention Drop temperature and park extruders outside a full skirt for automatic wiping
|
||||
(default: no)
|
||||
--ooze-prevention Drop temperature and park extruders outside a full skirt for automatic wiping
|
||||
(default: no)
|
||||
--standby-temperature-delta
|
||||
Temperature difference to be applied when an extruder is not active and
|
||||
--ooze-prevention is enabled (default: -5)
|
||||
|
||||
|
||||
If you want to change a preset file, just do
|
||||
|
||||
slic3r.pl --load config.ini --layer-height 0.25 --save config.ini
|
||||
|
||||
If you want to slice a file overriding an option contained in your preset file:
|
||||
|
||||
slic3r.pl --load config.ini --layer-height 0.25 file.stl
|
||||
Please refer to the [Command Line Interface](https://github.com/prusa3d/Slic3r/wiki/Command-Line-Interface) wiki page.
|
||||
|
|
15
resources/icons/cross.svg
Normal file
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.3, 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 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
|
||||
<g id="cross">
|
||||
<g>
|
||||
|
||||
<line fill="none" stroke="#ED6B21" stroke-width="2" stroke-linecap="round" stroke-miterlimit="10" x1="14" y1="2" x2="2" y2="14"/>
|
||||
</g>
|
||||
<g>
|
||||
|
||||
<line fill="none" stroke="#ED6B21" stroke-width="2" stroke-linecap="round" stroke-miterlimit="10" x1="2" y1="2" x2="14" y2="14"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 659 B |
10
resources/icons/flag_green.svg
Normal file
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.3, 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 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
|
||||
<g id="flag_x5F_green">
|
||||
|
||||
<line fill="none" stroke="#808080" stroke-width="2" stroke-linecap="round" stroke-miterlimit="10" x1="14" y1="2" x2="14" y2="14"/>
|
||||
<path fill="#8CC63F" d="M13,2C8.2,2,5.8,4.4,1,4.4v7.2c4.8,0,7.2-2.4,12-2.4V2z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 591 B |
10
resources/icons/flag_red.svg
Normal file
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.3, 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 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
|
||||
<g id="flag_x5F_red">
|
||||
|
||||
<line fill="none" stroke="#808080" stroke-width="2" stroke-linecap="round" stroke-miterlimit="10" x1="14" y1="2" x2="14" y2="14"/>
|
||||
<path fill="#ED1C24" d="M13,2C8.2,2,5.8,4.4,1,4.4v7.2c4.8,0,7.2-2.4,12-2.4V2z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 589 B |
27
resources/icons/layers_white.svg
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.3, 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 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
|
||||
<g id="layers">
|
||||
<g>
|
||||
<g>
|
||||
<rect x="1" y="13" fill="#FFFFFF" width="14" height="2"/>
|
||||
</g>
|
||||
<g>
|
||||
<rect x="1" y="10.6" fill="#FFFFFF" width="14" height="1.74"/>
|
||||
</g>
|
||||
<g>
|
||||
<rect x="1" y="8.19" fill="#FFFFFF" width="14" height="1.47"/>
|
||||
</g>
|
||||
<g>
|
||||
<rect x="1" y="5.79" fill="#ED6B21" width="14" height="1.2"/>
|
||||
</g>
|
||||
<g>
|
||||
<rect x="1" y="3.39" fill="#ED6B21" width="14" height="0.93"/>
|
||||
</g>
|
||||
<g>
|
||||
<rect x="1" y="0.99" fill="#FFFFFF" width="14" height="0.67"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 845 B |
10
resources/icons/lock_closed.svg
Normal file
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.3, 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 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
|
||||
<g id="lock_x5F_closed">
|
||||
<path fill="none" stroke="#808080" stroke-width="2" stroke-miterlimit="10" d="M4,8V4c0,0,0-2,2-2c1,0,3,0,4,0c2,0,2,2,2,2v4"/>
|
||||
<path fill="#808080" d="M13,8H3C2.45,8,2,8.45,2,9v5c0,0.55,0.45,1,1,1h10c0.55,0,1-0.45,1-1V9C14,8.45,13.55,8,13,8z M10,12H8.91
|
||||
c-0.21,0.58-0.76,1-1.41,1C6.67,13,6,12.33,6,11.5S6.67,10,7.5,10c0.65,0,1.2,0.42,1.41,1H10V12z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 729 B |
10
resources/icons/lock_closed_white.svg
Normal file
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.3, 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 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
|
||||
<g id="lock_x5F_closed">
|
||||
<path fill="none" stroke="#FFFFFF" stroke-width="2" stroke-miterlimit="10" d="M4,8V4c0,0,0-2,2-2c1,0,3,0,4,0c2,0,2,2,2,2v4"/>
|
||||
<path fill="#FFFFFF" d="M13,8H3C2.45,8,2,8.45,2,9v5c0,0.55,0.45,1,1,1h10c0.55,0,1-0.45,1-1V9C14,8.45,13.55,8,13,8z M10,12H8.91
|
||||
c-0.21,0.58-0.76,1-1.41,1C6.67,13,6,12.33,6,11.5S6.67,10,7.5,10c0.65,0,1.2,0.42,1.41,1H10V12z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 729 B |
11
resources/icons/lock_open.svg
Normal file
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.3, 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 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
|
||||
<g id="lock_x5F_open">
|
||||
<path fill="none" stroke="#ED6B21" stroke-width="2" stroke-linecap="round" stroke-miterlimit="10" d="M4,8V4c0,0,0-2,2-2
|
||||
c1,0,3,0,4,0c2,0,2,2,2,2v1"/>
|
||||
<path fill="#ED6B21" d="M13,8H3C2.45,8,2,8.45,2,9v5c0,0.55,0.45,1,1,1h10c0.55,0,1-0.45,1-1V9C14,8.45,13.55,8,13,8z M10,12H8.91
|
||||
c-0.21,0.58-0.76,1-1.41,1C6.67,13,6,12.33,6,11.5S6.67,10,7.5,10c0.65,0,1.2,0.42,1.41,1H10V12z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 753 B |
10
resources/icons/question.svg
Normal file
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.3, 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 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
|
||||
<g id="question">
|
||||
<path fill="none" stroke="#ED6B21" stroke-width="2" stroke-linecap="round" stroke-miterlimit="10" d="M4,5c0,0,0,0,0-1s1-2,2-2
|
||||
s3,0,4,0c2,0,2,2,2,3v1c0,1-1,2-2,2S9,8,9,8s1,0,0,0s-2,1-2,2s0,1,0,1"/>
|
||||
<circle fill="#ED6B21" cx="7" cy="14" r="1"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 615 B |
10
resources/icons/resin.svg
Normal file
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.3, 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 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
|
||||
<g id="resin">
|
||||
<rect x="4" y="7" fill="#ED6B21" width="8" height="8"/>
|
||||
<path fill="none" stroke="#808080" stroke-linecap="round" stroke-miterlimit="10" d="M4.5,15h6.99c0.28,0,0.5-0.23,0.5-0.5V6
|
||||
c0-1-2-1-2-2s0-1,0-1h1V1.5C11,1.23,10.77,1,10.5,1H5.5C5.23,1,5,1.23,5,1.5V3h1v1c0,1-2,1-2,2v8.5C4,14.77,4.23,15,4.5,15z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 671 B |
24
resources/icons/save.svg
Normal file
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.3, 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 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
|
||||
<g id="save">
|
||||
<g>
|
||||
<path fill="#808080" d="M12,2c1.44,0,2,0.56,2,2v10L2,14L2,2H12 M12,1H2C1.45,1,1,1.45,1,2V14c0,0.55,0.45,1,1,1h12
|
||||
c0.55,0,1-0.45,1-1l0-10C15,2,14,1,12,1L12,1z"/>
|
||||
</g>
|
||||
<g>
|
||||
<line fill="none" stroke="#808080" stroke-linecap="round" stroke-miterlimit="10" x1="3" y1="8" x2="10" y2="8"/>
|
||||
</g>
|
||||
<g>
|
||||
<line fill="none" stroke="#808080" stroke-linecap="round" stroke-miterlimit="10" x1="3" y1="10" x2="10" y2="10"/>
|
||||
</g>
|
||||
<g>
|
||||
<line fill="none" stroke="#808080" stroke-linecap="round" stroke-miterlimit="10" x1="3" y1="12" x2="7" y2="12"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#ED6B21" d="M11,1H5C4.45,1,4,1.45,4,2V5c0,0.55,0.45,1,1,1H11c0.55,0,1-0.45,1-1V2C12,1.45,11.55,1,11,1z M6,4.5
|
||||
C6,4.78,5.78,5,5.5,5S5,4.78,5,4.5v-2C5,2.22,5.22,2,5.5,2S6,2.22,6,2.5V4.5z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
12
resources/icons/undo.svg
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.3, 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 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
|
||||
<g id="undo">
|
||||
<path fill="none" stroke="#ED6B21" stroke-width="2" stroke-linecap="round" stroke-miterlimit="10" d="M3,11
|
||||
c0.91,1.78,2.76,3,4.89,3c3.04,0,5.5-2.46,5.5-5.5c0-3.04-2.46-5.5-5.5-5.5c-0.17,0-0.34,0.01-0.5,0.03"/>
|
||||
|
||||
<polygon fill="#ED6B21" stroke="#ED6B21" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="
|
||||
7.39,1 7.39,5 4.39,3 "/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 746 B |
|
@ -8,11 +8,17 @@ src/slic3r/GUI/ConfigWizard.cpp
|
|||
src/slic3r/GUI/Field.cpp
|
||||
src/slic3r/GUI/FirmwareDialog.cpp
|
||||
src/slic3r/GUI/GLCanvas3D.cpp
|
||||
src/slic3r/GUI/GLGizmo.cpp
|
||||
src/slic3r/GUI/Gizmos/GLGizmoCut.cpp
|
||||
src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp
|
||||
src/slic3r/GUI/Gizmos/GLGizmoMove.cpp
|
||||
src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp
|
||||
src/slic3r/GUI/Gizmos/GLGizmoScale.cpp
|
||||
src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp
|
||||
src/slic3r/GUI/GUI.cpp
|
||||
src/slic3r/GUI/GUI_App.cpp
|
||||
src/slic3r/GUI/GUI_ObjectList.cpp
|
||||
src/slic3r/GUI/GUI_ObjectManipulation.cpp
|
||||
src/slic3r/GUI/GUI_ObjectSettings.cpp
|
||||
src/slic3r/GUI/GUI_Preview.cpp
|
||||
src/slic3r/GUI/KBShortcutsDialog.cpp
|
||||
src/slic3r/GUI/MainFrame.cpp
|
||||
|
@ -23,15 +29,22 @@ src/slic3r/GUI/Preset.cpp
|
|||
src/slic3r/GUI/PresetBundle.cpp
|
||||
src/slic3r/GUI/PresetHints.cpp
|
||||
src/slic3r/GUI/PrintHostDialogs.cpp
|
||||
src/slic3r/GUI/ProgressStatusBar.cpp
|
||||
src/slic3r/GUI/RammingChart.cpp
|
||||
src/slic3r/GUI/SysInfoDialog.cpp
|
||||
src/slic3r/GUI/Tab.cpp
|
||||
src/slic3r/GUI/Tab.hpp
|
||||
src/slic3r/GUI/UpdateDialogs.cpp
|
||||
src/slic3r/GUI/WipeTowerDialog.cpp
|
||||
src/slic3r/GUI/wxExtensions.cpp
|
||||
src/slic3r/Utils/Duet.cpp
|
||||
src/slic3r/Utils/OctoPrint.cpp
|
||||
src/slic3r/Utils/PresetUpdater.cpp
|
||||
src/slic3r/Utils/FixModelByWin10.cpp
|
||||
src/libslic3r/Zipper.cpp
|
||||
src/libslic3r/SLA/SLASupportTree.cpp
|
||||
src/libslic3r/Print.cpp
|
||||
src/libslic3r/SLAPrint.cpp
|
||||
src/libslic3r/PrintBase.cpp
|
||||
src/libslic3r/PrintConfig.cpp
|
||||
src/libslic3r/GCode/PreviewData.cpp
|
||||
|
|
|
@ -1455,4 +1455,28 @@ Transformation Transformation::operator * (const Transformation& other) const
|
|||
return Transformation(get_matrix() * other.get_matrix());
|
||||
}
|
||||
|
||||
Eigen::Quaterniond rotation_xyz_diff(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to)
|
||||
{
|
||||
return
|
||||
// From the current coordinate system to world.
|
||||
Eigen::AngleAxisd(rot_xyz_to(2), Vec3d::UnitZ()) * Eigen::AngleAxisd(rot_xyz_to(1), Vec3d::UnitY()) * Eigen::AngleAxisd(rot_xyz_to(0), Vec3d::UnitX()) *
|
||||
// From world to the initial coordinate system.
|
||||
Eigen::AngleAxisd(-rot_xyz_from(0), Vec3d::UnitX()) * Eigen::AngleAxisd(-rot_xyz_from(1), Vec3d::UnitY()) * Eigen::AngleAxisd(-rot_xyz_from(2), Vec3d::UnitZ());
|
||||
}
|
||||
|
||||
// This should only be called if it is known, that the two rotations only differ in rotation around the Z axis.
|
||||
double rotation_diff_z(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to)
|
||||
{
|
||||
Eigen::AngleAxisd angle_axis(rotation_xyz_diff(rot_xyz_from, rot_xyz_to));
|
||||
Vec3d axis = angle_axis.axis();
|
||||
double angle = angle_axis.angle();
|
||||
#ifndef NDEBUG
|
||||
if (std::abs(angle) > 1e-8) {
|
||||
assert(std::abs(axis.x()) < 1e-8);
|
||||
assert(std::abs(axis.y()) < 1e-8);
|
||||
}
|
||||
#endif /* NDEBUG */
|
||||
return (axis.z() < 0) ? -angle : angle;
|
||||
}
|
||||
|
||||
} }
|
||||
|
|
|
@ -262,6 +262,13 @@ public:
|
|||
Transformation operator * (const Transformation& other) const;
|
||||
};
|
||||
|
||||
// Rotation when going from the first coordinate system with rotation rot_xyz_from applied
|
||||
// to a coordinate system with rot_xyz_to applied.
|
||||
extern Eigen::Quaterniond rotation_xyz_diff(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to);
|
||||
// Rotation by Z to align rot_xyz_from to rot_xyz_to.
|
||||
// This should only be called if it is known, that the two rotations only differ in rotation around the Z axis.
|
||||
extern double rotation_diff_z(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to);
|
||||
|
||||
} }
|
||||
|
||||
#endif
|
||||
|
|
|
@ -2260,11 +2260,33 @@ void PrintConfigDef::init_sla_params()
|
|||
def->mode = comExpert;
|
||||
def->default_value = new ConfigOptionFloat(50.);
|
||||
|
||||
def = this->add("printer_correction", coFloats);
|
||||
def = this->add("relative_correction", coFloats);
|
||||
def->label = L("Printer scaling correction");
|
||||
def->full_label = L("Printer scaling correction");
|
||||
def->tooltip = L("Printer scaling correction");
|
||||
def->min = 0;
|
||||
def->mode = comExpert;
|
||||
def->default_value = new ConfigOptionFloats( { 1., 1., 1. } );
|
||||
|
||||
def = this->add("absolute_correction", coFloat);
|
||||
def->label = L("Printer absolute correction");
|
||||
def->full_label = L("Printer absolute correction");
|
||||
def->tooltip = L("Will inflate or deflate the sliced 2D polygons according "
|
||||
"to the sign of the correction.");
|
||||
def->mode = comExpert;
|
||||
def->default_value = new ConfigOptionFloat(0.0);
|
||||
|
||||
def = this->add("gamma_correction", coFloat);
|
||||
def->label = L("Printer gamma correction");
|
||||
def->full_label = L("Printer gamma correction");
|
||||
def->tooltip = L("This will apply a gamma correction to the rasterized 2D "
|
||||
"polygons. A gamma value of zero means thresholding with "
|
||||
"the threshold in the middle. This behaviour eliminates "
|
||||
"antialiasing without losing holes in polygons.");
|
||||
def->min = 0;
|
||||
def->mode = comExpert;
|
||||
def->default_value = new ConfigOptionFloat(1.0);
|
||||
|
||||
|
||||
// SLA Material settings.
|
||||
def = this->add("initial_layer_height", coFloat);
|
||||
|
@ -2296,16 +2318,11 @@ void PrintConfigDef::init_sla_params()
|
|||
def->min = 0;
|
||||
def->default_value = new ConfigOptionFloat(15);
|
||||
|
||||
def = this->add("material_correction_printing", coFloats);
|
||||
def->full_label = L("Correction for expansion when printing");
|
||||
def->tooltip = L("Correction for expansion when printing");
|
||||
def->min = 0;
|
||||
def->default_value = new ConfigOptionFloats( { 1. , 1., 1. } );
|
||||
|
||||
def = this->add("material_correction_curing", coFloats);
|
||||
def->full_label = L("Correction for expansion after curing");
|
||||
def->tooltip = L("Correction for expansion after curing");
|
||||
def = this->add("material_correction", coFloats);
|
||||
def->full_label = L("Correction for expansion");
|
||||
def->tooltip = L("Correction for expansion");
|
||||
def->min = 0;
|
||||
def->mode = comExpert;
|
||||
def->default_value = new ConfigOptionFloats( { 1. , 1., 1. } );
|
||||
|
||||
def = this->add("material_notes", coString);
|
||||
|
@ -2490,7 +2507,7 @@ void PrintConfigDef::init_sla_params()
|
|||
def->tooltip = L("No support points will be placed closer than this threshold.");
|
||||
def->sidetext = L("mm");
|
||||
def->min = 0;
|
||||
def->default_value = new ConfigOptionFloat(0.f);
|
||||
def->default_value = new ConfigOptionFloat(1.f);
|
||||
|
||||
def = this->add("pad_enable", coBool);
|
||||
def->label = L("Use pad");
|
||||
|
|
|
@ -1056,16 +1056,14 @@ public:
|
|||
ConfigOptionFloat initial_layer_height;
|
||||
ConfigOptionFloat exposure_time;
|
||||
ConfigOptionFloat initial_exposure_time;
|
||||
ConfigOptionFloats material_correction_printing;
|
||||
ConfigOptionFloats material_correction_curing;
|
||||
ConfigOptionFloats material_correction;
|
||||
protected:
|
||||
void initialize(StaticCacheBase &cache, const char *base_ptr)
|
||||
{
|
||||
OPT_PTR(initial_layer_height);
|
||||
OPT_PTR(exposure_time);
|
||||
OPT_PTR(initial_exposure_time);
|
||||
OPT_PTR(material_correction_printing);
|
||||
OPT_PTR(material_correction_curing);
|
||||
OPT_PTR(material_correction);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1081,7 +1079,9 @@ public:
|
|||
ConfigOptionInt display_pixels_x;
|
||||
ConfigOptionInt display_pixels_y;
|
||||
ConfigOptionEnum<SLADisplayOrientation> display_orientation;
|
||||
ConfigOptionFloats printer_correction;
|
||||
ConfigOptionFloats relative_correction;
|
||||
ConfigOptionFloat absolute_correction;
|
||||
ConfigOptionFloat gamma_correction;
|
||||
ConfigOptionFloat fast_tilt_time;
|
||||
ConfigOptionFloat slow_tilt_time;
|
||||
ConfigOptionFloat area_fill;
|
||||
|
@ -1096,7 +1096,9 @@ protected:
|
|||
OPT_PTR(display_pixels_x);
|
||||
OPT_PTR(display_pixels_y);
|
||||
OPT_PTR(display_orientation);
|
||||
OPT_PTR(printer_correction);
|
||||
OPT_PTR(relative_correction);
|
||||
OPT_PTR(absolute_correction);
|
||||
OPT_PTR(gamma_correction);
|
||||
OPT_PTR(fast_tilt_time);
|
||||
OPT_PTR(slow_tilt_time);
|
||||
OPT_PTR(area_fill);
|
||||
|
|
|
@ -138,6 +138,7 @@ template<> class FilePrinter<FilePrinterFormat::SLA_PNGZIP>
|
|||
double m_exp_time_s = .0, m_exp_time_first_s = .0;
|
||||
double m_layer_height = .0;
|
||||
Raster::Origin m_o = Raster::Origin::TOP_LEFT;
|
||||
double m_gamma;
|
||||
|
||||
double m_used_material = 0.0;
|
||||
int m_cnt_fade_layers = 0;
|
||||
|
@ -194,7 +195,8 @@ public:
|
|||
unsigned width_px, unsigned height_px,
|
||||
double layer_height,
|
||||
double exp_time, double exp_time_first,
|
||||
RasterOrientation ro = RO_PORTRAIT):
|
||||
RasterOrientation ro = RO_PORTRAIT,
|
||||
double gamma = 1.0):
|
||||
m_res(width_px, height_px),
|
||||
m_pxdim(width_mm/width_px, height_mm/height_px),
|
||||
m_exp_time_s(exp_time),
|
||||
|
@ -203,7 +205,8 @@ public:
|
|||
|
||||
// Here is the trick with the orientation.
|
||||
m_o(ro == RO_LANDSCAPE? Raster::Origin::BOTTOM_LEFT :
|
||||
Raster::Origin::TOP_LEFT )
|
||||
Raster::Origin::TOP_LEFT ),
|
||||
m_gamma(gamma)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -228,12 +231,12 @@ public:
|
|||
|
||||
inline void begin_layer(unsigned lyr) {
|
||||
if(m_layers_rst.size() <= lyr) m_layers_rst.resize(lyr+1);
|
||||
m_layers_rst[lyr].raster.reset(m_res, m_pxdim, m_o);
|
||||
m_layers_rst[lyr].raster.reset(m_res, m_pxdim, m_o, m_gamma);
|
||||
}
|
||||
|
||||
inline void begin_layer() {
|
||||
m_layers_rst.emplace_back();
|
||||
m_layers_rst.front().raster.reset(m_res, m_pxdim, m_o);
|
||||
m_layers_rst.front().raster.reset(m_res, m_pxdim, m_o, m_gamma);
|
||||
}
|
||||
|
||||
inline void finish_layer(unsigned lyr_id) {
|
||||
|
|
|
@ -19,6 +19,12 @@
|
|||
|
||||
namespace Slic3r {
|
||||
|
||||
const Polygon& contour(const ExPolygon& p) { return p.contour; }
|
||||
const ClipperLib::Path& contour(const ClipperLib::Polygon& p) { return p.Contour; }
|
||||
|
||||
const Polygons& holes(const ExPolygon& p) { return p.holes; }
|
||||
const ClipperLib::Paths& holes(const ClipperLib::Polygon& p) { return p.Holes; }
|
||||
|
||||
class Raster::Impl {
|
||||
public:
|
||||
using TPixelRenderer = agg::pixfmt_gray8; // agg::pixfmt_rgb24;
|
||||
|
@ -37,14 +43,17 @@ public:
|
|||
|
||||
private:
|
||||
Raster::Resolution m_resolution;
|
||||
Raster::PixelDim m_pxdim;
|
||||
// Raster::PixelDim m_pxdim;
|
||||
Raster::PixelDim m_pxdim_scaled; // used for scaled coordinate polygons
|
||||
TBuffer m_buf;
|
||||
TRawBuffer m_rbuf;
|
||||
TPixelRenderer m_pixfmt;
|
||||
TRawRenderer m_raw_renderer;
|
||||
TRendererAA m_renderer;
|
||||
|
||||
std::function<double(double)> m_gammafn;
|
||||
Origin m_o;
|
||||
|
||||
|
||||
inline void flipy(agg::path_storage& path) const {
|
||||
path.flip_y(0, m_resolution.height_px);
|
||||
}
|
||||
|
@ -52,8 +61,10 @@ private:
|
|||
public:
|
||||
|
||||
inline Impl(const Raster::Resolution& res, const Raster::PixelDim &pd,
|
||||
Origin o):
|
||||
m_resolution(res), m_pxdim(pd),
|
||||
Origin o, double gamma = 1.0):
|
||||
m_resolution(res),
|
||||
// m_pxdim(pd),
|
||||
m_pxdim_scaled(SCALING_FACTOR / pd.w_mm, SCALING_FACTOR / pd.h_mm),
|
||||
m_buf(res.pixels()),
|
||||
m_rbuf(reinterpret_cast<TPixelRenderer::value_type*>(m_buf.data()),
|
||||
res.width_px, res.height_px,
|
||||
|
@ -64,43 +75,26 @@ public:
|
|||
m_o(o)
|
||||
{
|
||||
m_renderer.color(ColorWhite);
|
||||
|
||||
// If we would like to play around with gamma
|
||||
// ras.gamma(agg::gamma_power(1.0));
|
||||
|
||||
|
||||
if(gamma > 0) m_gammafn = agg::gamma_power(gamma);
|
||||
else m_gammafn = agg::gamma_threshold(0.5);
|
||||
|
||||
clear();
|
||||
}
|
||||
|
||||
void draw(const ExPolygon &poly) {
|
||||
template<class P> void draw(const P &poly) {
|
||||
agg::rasterizer_scanline_aa<> ras;
|
||||
agg::scanline_p8 scanlines;
|
||||
|
||||
ras.gamma(m_gammafn);
|
||||
|
||||
auto&& path = to_path(poly.contour);
|
||||
auto&& path = to_path(contour(poly));
|
||||
|
||||
if(m_o == Origin::TOP_LEFT) flipy(path);
|
||||
|
||||
ras.add_path(path);
|
||||
|
||||
for(auto h : poly.holes) {
|
||||
auto&& holepath = to_path(h);
|
||||
if(m_o == Origin::TOP_LEFT) flipy(holepath);
|
||||
ras.add_path(holepath);
|
||||
}
|
||||
|
||||
agg::render_scanlines(ras, scanlines, m_renderer);
|
||||
}
|
||||
|
||||
void draw(const ClipperLib::Polygon &poly) {
|
||||
agg::rasterizer_scanline_aa<> ras;
|
||||
agg::scanline_p8 scanlines;
|
||||
|
||||
auto&& path = to_path(poly.Contour);
|
||||
|
||||
if(m_o == Origin::TOP_LEFT) flipy(path);
|
||||
|
||||
ras.add_path(path);
|
||||
|
||||
for(auto h : poly.Holes) {
|
||||
for(auto& h : holes(poly)) {
|
||||
auto&& holepath = to_path(h);
|
||||
if(m_o == Origin::TOP_LEFT) flipy(holepath);
|
||||
ras.add_path(holepath);
|
||||
|
@ -120,40 +114,34 @@ public:
|
|||
inline Origin origin() const /*noexcept*/ { return m_o; }
|
||||
|
||||
private:
|
||||
double getPx(const Point& p) {
|
||||
return p(0) * SCALING_FACTOR/m_pxdim.w_mm;
|
||||
inline double getPx(const Point& p) {
|
||||
return p(0) * m_pxdim_scaled.w_mm;
|
||||
}
|
||||
|
||||
double getPy(const Point& p) {
|
||||
return p(1) * SCALING_FACTOR/m_pxdim.h_mm;
|
||||
inline double getPy(const Point& p) {
|
||||
return p(1) * m_pxdim_scaled.h_mm;
|
||||
}
|
||||
|
||||
agg::path_storage to_path(const Polygon& poly)
|
||||
{
|
||||
agg::path_storage path;
|
||||
|
||||
auto it = poly.points.begin();
|
||||
path.move_to(getPx(*it), getPy(*it));
|
||||
while(++it != poly.points.end()) path.line_to(getPx(*it), getPy(*it));
|
||||
path.line_to(getPx(poly.points.front()), getPy(poly.points.front()));
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
double getPx(const ClipperLib::IntPoint& p) {
|
||||
return p.X * SCALING_FACTOR/m_pxdim.w_mm;
|
||||
}
|
||||
|
||||
double getPy(const ClipperLib::IntPoint& p) {
|
||||
return p.Y * SCALING_FACTOR/m_pxdim.h_mm;
|
||||
}
|
||||
|
||||
agg::path_storage to_path(const ClipperLib::Path& poly)
|
||||
inline agg::path_storage to_path(const Polygon& poly)
|
||||
{
|
||||
return to_path(poly.points);
|
||||
}
|
||||
|
||||
inline double getPx(const ClipperLib::IntPoint& p) {
|
||||
return p.X * m_pxdim_scaled.w_mm;
|
||||
}
|
||||
|
||||
inline double getPy(const ClipperLib::IntPoint& p) {
|
||||
return p.Y * m_pxdim_scaled.h_mm;
|
||||
}
|
||||
|
||||
template<class PointVec> agg::path_storage to_path(const PointVec& poly)
|
||||
{
|
||||
agg::path_storage path;
|
||||
|
||||
auto it = poly.begin();
|
||||
path.move_to(getPx(*it), getPy(*it));
|
||||
|
||||
while(++it != poly.end())
|
||||
path.line_to(getPx(*it), getPy(*it));
|
||||
|
||||
|
@ -166,8 +154,8 @@ private:
|
|||
const Raster::Impl::TPixel Raster::Impl::ColorWhite = Raster::Impl::TPixel(255);
|
||||
const Raster::Impl::TPixel Raster::Impl::ColorBlack = Raster::Impl::TPixel(0);
|
||||
|
||||
Raster::Raster(const Resolution &r, const PixelDim &pd, Origin o):
|
||||
m_impl(new Impl(r, pd, o)) {}
|
||||
Raster::Raster(const Resolution &r, const PixelDim &pd, Origin o, double g):
|
||||
m_impl(new Impl(r, pd, o, g)) {}
|
||||
|
||||
Raster::Raster() {}
|
||||
|
||||
|
@ -176,19 +164,20 @@ Raster::~Raster() {}
|
|||
Raster::Raster(Raster &&m):
|
||||
m_impl(std::move(m.m_impl)) {}
|
||||
|
||||
void Raster::reset(const Raster::Resolution &r, const Raster::PixelDim &pd)
|
||||
void Raster::reset(const Raster::Resolution &r, const Raster::PixelDim &pd,
|
||||
double g)
|
||||
{
|
||||
// Free up the unnecessary memory and make sure it stays clear after
|
||||
// an exception
|
||||
auto o = m_impl? m_impl->origin() : Origin::TOP_LEFT;
|
||||
reset(r, pd, o);
|
||||
reset(r, pd, o, g);
|
||||
}
|
||||
|
||||
void Raster::reset(const Raster::Resolution &r, const Raster::PixelDim &pd,
|
||||
Raster::Origin o)
|
||||
Raster::Origin o, double gamma)
|
||||
{
|
||||
m_impl.reset();
|
||||
m_impl.reset(new Impl(r, pd, o));
|
||||
m_impl.reset(new Impl(r, pd, o, gamma));
|
||||
}
|
||||
|
||||
void Raster::reset()
|
||||
|
|
|
@ -99,8 +99,9 @@ public:
|
|||
};
|
||||
|
||||
/// Constructor taking the resolution and the pixel dimension.
|
||||
explicit Raster(const Resolution& r, const PixelDim& pd,
|
||||
Origin o = Origin::BOTTOM_LEFT );
|
||||
Raster(const Resolution& r, const PixelDim& pd,
|
||||
Origin o = Origin::BOTTOM_LEFT, double gamma = 1.0);
|
||||
|
||||
Raster();
|
||||
Raster(const Raster& cpy) = delete;
|
||||
Raster& operator=(const Raster& cpy) = delete;
|
||||
|
@ -108,8 +109,8 @@ public:
|
|||
~Raster();
|
||||
|
||||
/// Reallocated everything for the given resolution and pixel dimension.
|
||||
void reset(const Resolution& r, const PixelDim& pd);
|
||||
void reset(const Resolution& r, const PixelDim& pd, Origin o);
|
||||
void reset(const Resolution& r, const PixelDim& pd, double gamma = 1.0);
|
||||
void reset(const Resolution& r, const PixelDim& pd, Origin o, double gamma);
|
||||
|
||||
/**
|
||||
* Release the allocated resources. Drawing in this state ends in
|
||||
|
|
|
@ -19,7 +19,7 @@ public:
|
|||
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 support_force() const { return 7.7f / 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)
|
||||
};
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "SLA/SLABasePool.hpp"
|
||||
#include "SLA/SLAAutoSupports.hpp"
|
||||
#include "ClipperUtils.hpp"
|
||||
#include "Geometry.hpp"
|
||||
#include "MTUtils.hpp"
|
||||
|
||||
#include <unordered_set>
|
||||
|
@ -85,17 +86,32 @@ void SLAPrint::clear()
|
|||
}
|
||||
|
||||
// Transformation without rotation around Z and without a shift by X and Y.
|
||||
static Transform3d sla_trafo(const ModelObject &model_object)
|
||||
static Transform3d sla_trafo(const SLAPrint& p, const ModelObject &model_object)
|
||||
{
|
||||
|
||||
Vec3d corr = p.relative_correction();
|
||||
|
||||
ModelInstance &model_instance = *model_object.instances.front();
|
||||
Vec3d offset = model_instance.get_offset();
|
||||
Vec3d rotation = model_instance.get_rotation();
|
||||
offset(0) = 0.;
|
||||
offset(1) = 0.;
|
||||
rotation(2) = 0.;
|
||||
Transform3d trafo = Geometry::assemble_transform(offset, rotation, model_instance.get_scaling_factor(), model_instance.get_mirror());
|
||||
if (model_instance.is_left_handed())
|
||||
trafo = Eigen::Scaling(Vec3d(-1., 1., 1.)) * trafo;
|
||||
|
||||
offset(Z) *= corr(Z);
|
||||
|
||||
auto trafo = Transform3d::Identity();
|
||||
trafo.translate(offset);
|
||||
trafo.scale(corr);
|
||||
trafo.rotate(Eigen::AngleAxisd(rotation(2), Vec3d::UnitZ()));
|
||||
trafo.rotate(Eigen::AngleAxisd(rotation(1), Vec3d::UnitY()));
|
||||
trafo.rotate(Eigen::AngleAxisd(rotation(0), Vec3d::UnitX()));
|
||||
trafo.scale(model_instance.get_scaling_factor());
|
||||
trafo.scale(model_instance.get_mirror());
|
||||
|
||||
if (model_instance.is_left_handed())
|
||||
trafo = Eigen::Scaling(Vec3d(-1., 1., 1.)) * trafo;
|
||||
|
||||
return trafo;
|
||||
}
|
||||
|
||||
|
@ -103,13 +119,18 @@ static Transform3d sla_trafo(const ModelObject &model_object)
|
|||
static std::vector<SLAPrintObject::Instance> sla_instances(const ModelObject &model_object)
|
||||
{
|
||||
std::vector<SLAPrintObject::Instance> instances;
|
||||
for (ModelInstance *model_instance : model_object.instances)
|
||||
if (model_instance->is_printable()) {
|
||||
instances.emplace_back(
|
||||
model_instance->id(),
|
||||
Point::new_scale(model_instance->get_offset(X), model_instance->get_offset(Y)),
|
||||
float(model_instance->get_rotation(Z)));
|
||||
}
|
||||
assert(! model_object.instances.empty());
|
||||
if (! model_object.instances.empty()) {
|
||||
Vec3d rotation0 = model_object.instances.front()->get_rotation();
|
||||
rotation0(2) = 0.;
|
||||
for (ModelInstance *model_instance : model_object.instances)
|
||||
if (model_instance->is_printable()) {
|
||||
instances.emplace_back(
|
||||
model_instance->id(),
|
||||
Point::new_scale(model_instance->get_offset(X), model_instance->get_offset(Y)),
|
||||
float(Geometry::rotation_diff_z(rotation0, model_instance->get_rotation())));
|
||||
}
|
||||
}
|
||||
return instances;
|
||||
}
|
||||
|
||||
|
@ -121,12 +142,12 @@ 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.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);
|
||||
t_config_option_keys print_diff = m_print_config.diff(config);
|
||||
t_config_option_keys printer_diff = m_printer_config.diff(config);
|
||||
t_config_option_keys material_diff = m_material_config.diff(config);
|
||||
t_config_option_keys object_diff = m_default_object_config.diff(config);
|
||||
|
@ -143,23 +164,24 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, const DynamicPrintConf
|
|||
tbb::mutex::scoped_lock lock(this->state_mutex());
|
||||
|
||||
// The following call may stop the background processing.
|
||||
bool invalidate_all_model_objects = false;
|
||||
if (! print_diff.empty())
|
||||
update_apply_status(this->invalidate_state_by_config_options(print_diff));
|
||||
update_apply_status(this->invalidate_state_by_config_options(print_diff, invalidate_all_model_objects));
|
||||
if (! printer_diff.empty())
|
||||
update_apply_status(this->invalidate_state_by_config_options(printer_diff));
|
||||
update_apply_status(this->invalidate_state_by_config_options(printer_diff, invalidate_all_model_objects));
|
||||
if (! material_diff.empty())
|
||||
update_apply_status(this->invalidate_state_by_config_options(material_diff));
|
||||
update_apply_status(this->invalidate_state_by_config_options(material_diff, invalidate_all_model_objects));
|
||||
|
||||
// Apply variables to placeholder parser. The placeholder parser is currently used
|
||||
// only to generate the output file name.
|
||||
if (! placeholder_parser_diff.empty()) {
|
||||
if (! placeholder_parser_diff.empty()) {
|
||||
// update_apply_status(this->invalidate_step(slapsRasterize));
|
||||
PlaceholderParser &pp = this->placeholder_parser();
|
||||
pp.apply_config(config);
|
||||
PlaceholderParser &pp = this->placeholder_parser();
|
||||
pp.apply_config(config);
|
||||
// Set the profile aliases for the PrintBase::output_filename()
|
||||
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());
|
||||
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.
|
||||
|
@ -187,7 +209,7 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, const DynamicPrintConf
|
|||
std::set<ModelObjectStatus> model_object_status;
|
||||
|
||||
// 1) Synchronize model objects.
|
||||
if (model.id() != m_model.id()) {
|
||||
if (model.id() != m_model.id() || invalidate_all_model_objects) {
|
||||
// Kill everything, initialize from scratch.
|
||||
// Stop background processing.
|
||||
this->call_cancel_callback();
|
||||
|
@ -306,106 +328,91 @@ 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);
|
||||
// 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)) ||
|
||||
model_object.instances.front()->is_left_handed() != model_object_new.instances.front()->is_left_handed()));
|
||||
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(*this, model_object).isApprox(sla_trafo(*this, model_object_new)) ||
|
||||
model_object.instances.front()->is_left_handed() != model_object_new.instances.front()->is_left_handed()));
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
// The SLAPrintObject is already there.
|
||||
if (new_instances.empty()) {
|
||||
const_cast<PrintObjectStatus&>(*it_print_object_status).status = PrintObjectStatus::Deleted;
|
||||
} else {
|
||||
if (new_instances != it_print_object_status->print_object->instances()) {
|
||||
// Instances changed.
|
||||
it_print_object_status->print_object->set_instances(new_instances);
|
||||
if (new_instances.empty()) {
|
||||
const_cast<PrintObjectStatus&>(*it_print_object_status).status = PrintObjectStatus::Deleted;
|
||||
} else {
|
||||
if (new_instances != it_print_object_status->print_object->instances()) {
|
||||
// Instances changed.
|
||||
it_print_object_status->print_object->set_instances(new_instances);
|
||||
update_apply_status(this->invalidate_step(slapsMergeSlicesAndEval));
|
||||
}
|
||||
print_objects_new.emplace_back(it_print_object_status->print_object);
|
||||
const_cast<PrintObjectStatus&>(*it_print_object_status).status = PrintObjectStatus::Reused;
|
||||
}
|
||||
} else if (! new_instances.empty()) {
|
||||
}
|
||||
print_objects_new.emplace_back(it_print_object_status->print_object);
|
||||
const_cast<PrintObjectStatus&>(*it_print_object_status).status = PrintObjectStatus::Reused;
|
||||
}
|
||||
} else if (! new_instances.empty()) {
|
||||
auto print_object = new SLAPrintObject(this, &model_object);
|
||||
|
||||
// FIXME: this invalidates the transformed mesh in SLAPrintObject
|
||||
// which is expensive to calculate (especially the raw_mesh() call)
|
||||
print_object->set_trafo(sla_trafo(model_object), model_object.instances.front()->is_left_handed());
|
||||
print_object->set_trafo(sla_trafo(*this, model_object), model_object.instances.front()->is_left_handed());
|
||||
|
||||
print_object->set_instances(std::move(new_instances));
|
||||
print_object->config_apply(config, true);
|
||||
|
@ -440,56 +447,56 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, const DynamicPrintConf
|
|||
// After calling the apply() function, set_task() may be called to limit the task to be processed by process().
|
||||
void SLAPrint::set_task(const TaskParams ¶ms)
|
||||
{
|
||||
// Grab the lock for the Print / PrintObject milestones.
|
||||
tbb::mutex::scoped_lock lock(this->state_mutex());
|
||||
// Grab the lock for the Print / PrintObject milestones.
|
||||
tbb::mutex::scoped_lock lock(this->state_mutex());
|
||||
|
||||
int n_object_steps = int(params.to_object_step) + 1;
|
||||
if (n_object_steps == 0)
|
||||
n_object_steps = (int)slaposCount;
|
||||
int n_object_steps = int(params.to_object_step) + 1;
|
||||
if (n_object_steps == 0)
|
||||
n_object_steps = (int)slaposCount;
|
||||
|
||||
if (params.single_model_object.valid()) {
|
||||
if (params.single_model_object.valid()) {
|
||||
// Find the print object to be processed with priority.
|
||||
SLAPrintObject *print_object = nullptr;
|
||||
size_t idx_print_object = 0;
|
||||
for (; idx_print_object < m_objects.size(); ++ idx_print_object)
|
||||
if (m_objects[idx_print_object]->model_object()->id() == params.single_model_object) {
|
||||
print_object = m_objects[idx_print_object];
|
||||
break;
|
||||
}
|
||||
assert(print_object != nullptr);
|
||||
SLAPrintObject *print_object = nullptr;
|
||||
size_t idx_print_object = 0;
|
||||
for (; idx_print_object < m_objects.size(); ++ idx_print_object)
|
||||
if (m_objects[idx_print_object]->model_object()->id() == params.single_model_object) {
|
||||
print_object = m_objects[idx_print_object];
|
||||
break;
|
||||
}
|
||||
assert(print_object != nullptr);
|
||||
// Find out whether the priority print object is being currently processed.
|
||||
bool running = false;
|
||||
for (int istep = 0; istep < n_object_steps; ++ istep) {
|
||||
if (! print_object->m_stepmask[istep])
|
||||
for (int istep = 0; istep < n_object_steps; ++ istep) {
|
||||
if (! print_object->m_stepmask[istep])
|
||||
// Step was skipped, cancel.
|
||||
break;
|
||||
if (print_object->is_step_started_unguarded(SLAPrintObjectStep(istep))) {
|
||||
break;
|
||||
if (print_object->is_step_started_unguarded(SLAPrintObjectStep(istep))) {
|
||||
// No step was skipped, and a wanted step is being processed. Don't cancel.
|
||||
running = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (! running)
|
||||
this->call_cancel_callback();
|
||||
running = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (! running)
|
||||
this->call_cancel_callback();
|
||||
|
||||
// Now the background process is either stopped, or it is inside one of the print object steps to be calculated anyway.
|
||||
if (params.single_model_instance_only) {
|
||||
// Suppress all the steps of other instances.
|
||||
for (SLAPrintObject *po : m_objects)
|
||||
for (int istep = 0; istep < (int)slaposCount; ++ istep)
|
||||
po->m_stepmask[istep] = false;
|
||||
} else if (! running) {
|
||||
// Swap the print objects, so that the selected print_object is first in the row.
|
||||
// At this point the background processing must be stopped, so it is safe to shuffle print objects.
|
||||
if (idx_print_object != 0)
|
||||
std::swap(m_objects.front(), m_objects[idx_print_object]);
|
||||
}
|
||||
// Now the background process is either stopped, or it is inside one of the print object steps to be calculated anyway.
|
||||
if (params.single_model_instance_only) {
|
||||
// Suppress all the steps of other instances.
|
||||
for (SLAPrintObject *po : m_objects)
|
||||
for (int istep = 0; istep < (int)slaposCount; ++ istep)
|
||||
po->m_stepmask[istep] = false;
|
||||
} else if (! running) {
|
||||
// Swap the print objects, so that the selected print_object is first in the row.
|
||||
// At this point the background processing must be stopped, so it is safe to shuffle print objects.
|
||||
if (idx_print_object != 0)
|
||||
std::swap(m_objects.front(), m_objects[idx_print_object]);
|
||||
}
|
||||
// and set the steps for the current object.
|
||||
for (int istep = 0; istep < n_object_steps; ++ istep)
|
||||
print_object->m_stepmask[istep] = true;
|
||||
for (int istep = n_object_steps; istep < (int)slaposCount; ++ istep)
|
||||
print_object->m_stepmask[istep] = false;
|
||||
} else {
|
||||
for (int istep = 0; istep < n_object_steps; ++ istep)
|
||||
print_object->m_stepmask[istep] = true;
|
||||
for (int istep = n_object_steps; istep < (int)slaposCount; ++ istep)
|
||||
print_object->m_stepmask[istep] = false;
|
||||
} else {
|
||||
// Slicing all objects.
|
||||
bool running = false;
|
||||
for (SLAPrintObject *print_object : m_objects)
|
||||
|
@ -518,9 +525,9 @@ void SLAPrint::set_task(const TaskParams ¶ms)
|
|||
|
||||
if (params.to_object_step != -1 || params.to_print_step != -1) {
|
||||
// Limit the print steps.
|
||||
size_t istep = (params.to_object_step != -1) ? 0 : size_t(params.to_print_step) + 1;
|
||||
for (; istep < m_stepmask.size(); ++ istep)
|
||||
m_stepmask[istep] = false;
|
||||
size_t istep = (params.to_object_step != -1) ? 0 : size_t(params.to_print_step) + 1;
|
||||
for (; istep < m_stepmask.size(); ++ istep)
|
||||
m_stepmask[istep] = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -530,7 +537,7 @@ void SLAPrint::finalize()
|
|||
{
|
||||
for (SLAPrintObject *po : m_objects)
|
||||
for (int istep = 0; istep < (int)slaposCount; ++ istep)
|
||||
po->m_stepmask[istep] = true;
|
||||
po->m_stepmask[istep] = true;
|
||||
for (int istep = 0; istep < (int)slapsCount; ++ istep)
|
||||
m_stepmask[istep] = true;
|
||||
}
|
||||
|
@ -539,7 +546,7 @@ void SLAPrint::finalize()
|
|||
// (timestamps, object placeholders derived from the model, current placeholder prameters and print statistics.
|
||||
// Use the final print statistics if available, or just keep the print statistics placeholders if not available yet (before the output is finalized).
|
||||
std::string SLAPrint::output_filename() const
|
||||
{
|
||||
{
|
||||
DynamicConfig config = this->finished() ? this->print_statistics().config() : this->print_statistics().placeholders();
|
||||
return this->PrintBase::output_filename(m_print_config.output_filename_format.value, "sl1", &config);
|
||||
}
|
||||
|
@ -708,10 +715,17 @@ void SLAPrint::process()
|
|||
[this](){ throw_if_canceled(); });
|
||||
|
||||
auto mit = slindex_it;
|
||||
double doffs = m_printer_config.absolute_correction.getFloat();
|
||||
coord_t clpr_offs = coord_t(doffs / SCALING_FACTOR);
|
||||
for(size_t id = 0;
|
||||
id < po.m_model_slices.size() && mit != po.m_slice_index.end();
|
||||
id++)
|
||||
{
|
||||
// We apply the printer correction offset here.
|
||||
if(clpr_offs != 0)
|
||||
po.m_model_slices[id] =
|
||||
offset_ex(po.m_model_slices[id], clpr_offs);
|
||||
|
||||
mit->set_model_slice_idx(po, id); ++mit;
|
||||
}
|
||||
};
|
||||
|
@ -771,7 +785,7 @@ void SLAPrint::process()
|
|||
po.m_supportdata->emesh,
|
||||
po.get_model_slices(),
|
||||
heights,
|
||||
config,
|
||||
config,
|
||||
[this]() { throw_if_canceled(); },
|
||||
statuscb);
|
||||
|
||||
|
@ -913,10 +927,17 @@ void SLAPrint::process()
|
|||
heights, float(po.config().slice_closing_radius.value));
|
||||
}
|
||||
|
||||
double doffs = m_printer_config.absolute_correction.getFloat();
|
||||
coord_t clpr_offs = coord_t(doffs / SCALING_FACTOR);
|
||||
for(size_t i = 0;
|
||||
i < sd->support_slices.size() && i < po.m_slice_index.size();
|
||||
++i)
|
||||
{
|
||||
// We apply the printer correction offset here.
|
||||
if(clpr_offs != 0)
|
||||
sd->support_slices[i] =
|
||||
offset_ex(sd->support_slices[i], clpr_offs);
|
||||
|
||||
po.m_slice_index[i].set_support_slice_idx(po, i);
|
||||
}
|
||||
|
||||
|
@ -1024,6 +1045,8 @@ void SLAPrint::process()
|
|||
const double width = m_printer_config.display_width.getFloat() / SCALING_FACTOR;
|
||||
const double height = m_printer_config.display_height.getFloat() / SCALING_FACTOR;
|
||||
const double display_area = width*height;
|
||||
|
||||
const coord_t clpr_back_offs = - coord_t(m_printer_config.absolute_correction.getFloat() / SCALING_FACTOR);
|
||||
|
||||
// get polygons for all instances in the object
|
||||
auto get_all_polygons =
|
||||
|
@ -1107,7 +1130,7 @@ void SLAPrint::process()
|
|||
auto printlayerfn = [this,
|
||||
// functions and read only vars
|
||||
get_all_polygons, polyunion, polydiff, areafn,
|
||||
area_fill, display_area, exp_time, init_exp_time, fast_tilt, slow_tilt, delta_fade_time,
|
||||
area_fill, display_area, exp_time, init_exp_time, fast_tilt, slow_tilt, delta_fade_time, clpr_back_offs,
|
||||
|
||||
// write vars
|
||||
&mutex, &models_volume, &supports_volume, &estim_time, &slow_layers,
|
||||
|
@ -1143,14 +1166,18 @@ void SLAPrint::process()
|
|||
for(const SliceRecord& record : layer.slices()) {
|
||||
const SLAPrintObject *po = record.print_obj();
|
||||
|
||||
const ExPolygons &modelslices = record.get_slice(soModel);
|
||||
const ExPolygons &rawmodelslices = record.get_slice(soModel);
|
||||
const ExPolygons &modelslices = clpr_back_offs != 0 ? offset_ex(rawmodelslices, clpr_back_offs) : rawmodelslices;
|
||||
|
||||
bool is_lefth = record.print_obj()->is_left_handed();
|
||||
if (!modelslices.empty()) {
|
||||
ClipperPolygons v = get_all_polygons(modelslices, po->instances(), is_lefth);
|
||||
for(ClipperPolygon& p_tmp : v) model_polygons.emplace_back(std::move(p_tmp));
|
||||
}
|
||||
|
||||
const ExPolygons &supportslices = record.get_slice(soSupport);
|
||||
const ExPolygons &rawsupportslices = record.get_slice(soSupport);
|
||||
const ExPolygons &supportslices = clpr_back_offs != 0 ? offset_ex(rawsupportslices, clpr_back_offs) : rawsupportslices;
|
||||
|
||||
if (!supportslices.empty()) {
|
||||
ClipperPolygons v = get_all_polygons(supportslices, po->instances(), is_lefth);
|
||||
for(ClipperPolygon& p_tmp : v) supports_polygons.emplace_back(std::move(p_tmp));
|
||||
|
@ -1259,12 +1286,16 @@ void SLAPrint::process()
|
|||
double lh = ocfg.layer_height.getFloat();
|
||||
double exp_t = matcfg.exposure_time.getFloat();
|
||||
double iexp_t = matcfg.initial_exposure_time.getFloat();
|
||||
|
||||
double gamma = m_printer_config.gamma_correction.getFloat();
|
||||
|
||||
if(flpXY) { std::swap(w, h); std::swap(pw, ph); }
|
||||
|
||||
m_printer.reset(new SLAPrinter(w, h, pw, ph, lh, exp_t, iexp_t,
|
||||
flpXY? SLAPrinter::RO_PORTRAIT :
|
||||
SLAPrinter::RO_LANDSCAPE));
|
||||
m_printer.reset(
|
||||
new SLAPrinter(w, h, pw, ph, lh, exp_t, iexp_t,
|
||||
flpXY? SLAPrinter::RO_PORTRAIT :
|
||||
SLAPrinter::RO_LANDSCAPE,
|
||||
gamma));
|
||||
}
|
||||
|
||||
// Allocate space for all the layers
|
||||
|
@ -1418,24 +1449,29 @@ void SLAPrint::process()
|
|||
m_report_status(*this, 100, L("Slicing done"));
|
||||
}
|
||||
|
||||
bool SLAPrint::invalidate_state_by_config_options(const std::vector<t_config_option_key> &opt_keys)
|
||||
bool SLAPrint::invalidate_state_by_config_options(const std::vector<t_config_option_key> &opt_keys, bool &invalidate_all_model_objects)
|
||||
{
|
||||
if (opt_keys.empty())
|
||||
return false;
|
||||
|
||||
static std::unordered_set<std::string> steps_full = {
|
||||
"initial_layer_height",
|
||||
"material_correction",
|
||||
"relative_correction",
|
||||
"absolute_correction",
|
||||
"gamma_correction"
|
||||
};
|
||||
|
||||
// Cache the plenty of parameters, which influence the final rasterization only,
|
||||
// or they are only notes not influencing the rasterization step.
|
||||
static std::unordered_set<std::string> steps_rasterize = {
|
||||
"exposure_time",
|
||||
"initial_exposure_time",
|
||||
"material_correction_printing",
|
||||
"material_correction_curing",
|
||||
"display_width",
|
||||
"display_height",
|
||||
"display_pixels_x",
|
||||
"display_pixels_y",
|
||||
"display_orientation",
|
||||
"printer_correction"
|
||||
"display_orientation"
|
||||
};
|
||||
|
||||
static std::unordered_set<std::string> steps_ignore = {
|
||||
|
@ -1443,8 +1479,8 @@ bool SLAPrint::invalidate_state_by_config_options(const std::vector<t_config_opt
|
|||
"max_print_height",
|
||||
"printer_technology",
|
||||
"output_filename_format",
|
||||
"fast_tilt_time",
|
||||
"slow_tilt_time",
|
||||
"fast_tilt_time",
|
||||
"slow_tilt_time",
|
||||
"area_fill"
|
||||
};
|
||||
|
||||
|
@ -1459,9 +1495,10 @@ bool SLAPrint::invalidate_state_by_config_options(const std::vector<t_config_opt
|
|||
steps.emplace_back(slapsMergeSlicesAndEval);
|
||||
} else if (steps_ignore.find(opt_key) != steps_ignore.end()) {
|
||||
// These steps have no influence on the output. Just ignore them.
|
||||
} else if (opt_key == "initial_layer_height") {
|
||||
} else if (steps_full.find(opt_key) != steps_full.end()) {
|
||||
steps.emplace_back(slapsMergeSlicesAndEval);
|
||||
osteps.emplace_back(slaposObjectSlice);
|
||||
invalidate_all_model_objects = true;
|
||||
} else {
|
||||
// All values should be covered.
|
||||
assert(false);
|
||||
|
@ -1511,20 +1548,20 @@ bool SLAPrintObject::invalidate_state_by_config_options(const std::vector<t_conf
|
|||
std::vector<SLAPrintObjectStep> steps;
|
||||
bool invalidated = false;
|
||||
for (const t_config_option_key &opt_key : opt_keys) {
|
||||
if ( opt_key == "layer_height"
|
||||
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);
|
||||
steps.emplace_back(slaposObjectSlice);
|
||||
} else if (
|
||||
|
||||
opt_key == "support_points_density_relative"
|
||||
|| opt_key == "support_points_minimal_distance") {
|
||||
steps.emplace_back(slaposSupportPoints);
|
||||
} else if (
|
||||
} else if (
|
||||
opt_key == "support_head_front_diameter"
|
||||
|| opt_key == "support_head_penetration"
|
||||
|| opt_key == "support_head_width"
|
||||
|
@ -1613,6 +1650,25 @@ double SLAPrintObject::get_current_elevation() const
|
|||
return get_elevation();
|
||||
}
|
||||
|
||||
Vec3d SLAPrint::relative_correction() const
|
||||
{
|
||||
Vec3d corr(1., 1., 1.);
|
||||
|
||||
if(printer_config().relative_correction.values.size() == 2) {
|
||||
corr(X) = printer_config().relative_correction.values[0];
|
||||
corr(Y) = printer_config().relative_correction.values[0];
|
||||
corr(Z) = printer_config().relative_correction.values[1];
|
||||
}
|
||||
|
||||
if(material_config().material_correction.values.size() == 2) {
|
||||
corr(X) *= material_config().material_correction.values[0];
|
||||
corr(Y) *= material_config().material_correction.values[0];
|
||||
corr(Z) *= material_config().material_correction.values[1];
|
||||
}
|
||||
|
||||
return corr;
|
||||
}
|
||||
|
||||
namespace { // dummy empty static containers for return values in some methods
|
||||
const std::vector<ExPolygons> EMPTY_SLICES;
|
||||
const TriangleMesh EMPTY_MESH;
|
||||
|
|
|
@ -397,7 +397,10 @@ public:
|
|||
const SLAMaterialConfig& material_config() const { return m_material_config; }
|
||||
const SLAPrintObjectConfig& default_object_config() const { return m_default_object_config; }
|
||||
|
||||
std::string output_filename() const override;
|
||||
// Extracted value from the configuration objects
|
||||
Vec3d relative_correction() const;
|
||||
|
||||
std::string output_filename() const override;
|
||||
|
||||
const SLAPrintStatistics& print_statistics() const { return m_print_statistics; }
|
||||
|
||||
|
@ -452,7 +455,7 @@ private:
|
|||
bool invalidate_step(SLAPrintStep st);
|
||||
|
||||
// Invalidate steps based on a set of parameters changed.
|
||||
bool invalidate_state_by_config_options(const std::vector<t_config_option_key> &opt_keys);
|
||||
bool invalidate_state_by_config_options(const std::vector<t_config_option_key> &opt_keys, bool &invalidate_all_model_objects);
|
||||
|
||||
SLAPrintConfig m_print_config;
|
||||
SLAPrinterConfig m_printer_config;
|
||||
|
|
|
@ -18,10 +18,10 @@ wxPanel(parent, wxID_ANY, wxDefaultPosition, wxSize(25 * wxGetApp().em_unit(), -
|
|||
#ifdef __APPLE__
|
||||
m_user_drawn_background = false;
|
||||
#endif /*__APPLE__*/
|
||||
Bind(wxEVT_PAINT, ([this](wxPaintEvent e) { repaint(); }));
|
||||
Bind(wxEVT_LEFT_DOWN, ([this](wxMouseEvent event) { mouse_event(event); }));
|
||||
Bind(wxEVT_MOTION, ([this](wxMouseEvent event) { mouse_event(event); }));
|
||||
Bind(wxEVT_SIZE, ([this](wxSizeEvent e) { Refresh(); }));
|
||||
Bind(wxEVT_PAINT, ([this](wxPaintEvent &/* e */) { repaint(); }));
|
||||
Bind(wxEVT_LEFT_DOWN, ([this](wxMouseEvent &event) { mouse_event(event); }));
|
||||
Bind(wxEVT_MOTION, ([this](wxMouseEvent &event) { mouse_event(event); }));
|
||||
Bind(wxEVT_SIZE, ([this](wxSizeEvent & /* e */) { Refresh(); }));
|
||||
}
|
||||
void Bed_2D::repaint()
|
||||
{
|
||||
|
|
|
@ -227,6 +227,12 @@ const float GLVolume::HOVER_COLOR[4] = { 0.4f, 0.9f, 0.1f, 1.0f };
|
|||
const float GLVolume::OUTSIDE_COLOR[4] = { 0.0f, 0.38f, 0.8f, 1.0f };
|
||||
const float GLVolume::SELECTED_OUTSIDE_COLOR[4] = { 0.19f, 0.58f, 1.0f, 1.0f };
|
||||
const float GLVolume::DISABLED_COLOR[4] = { 0.25f, 0.25f, 0.25f, 1.0f };
|
||||
const float GLVolume::MODEL_COLOR[4][4] = {
|
||||
{ 1.0f, 1.0f, 0.0f, 1.f },
|
||||
{ 1.0f, 0.5f, 0.5f, 1.f },
|
||||
{ 0.5f, 1.0f, 0.5f, 1.f },
|
||||
{ 0.5f, 0.5f, 1.0f, 1.f }
|
||||
};
|
||||
const float GLVolume::SLA_SUPPORT_COLOR[4] = { 0.75f, 0.75f, 0.75f, 1.0f };
|
||||
const float GLVolume::SLA_PAD_COLOR[4] = { 0.0f, 0.2f, 0.0f, 1.0f };
|
||||
|
||||
|
@ -568,19 +574,12 @@ int GLVolumeCollection::load_object_volume(
|
|||
const std::string &color_by,
|
||||
bool use_VBOs)
|
||||
{
|
||||
static float colors[4][4] = {
|
||||
{ 1.0f, 1.0f, 0.0f, 1.f },
|
||||
{ 1.0f, 0.5f, 0.5f, 1.f },
|
||||
{ 0.5f, 1.0f, 0.5f, 1.f },
|
||||
{ 0.5f, 0.5f, 1.0f, 1.f }
|
||||
};
|
||||
|
||||
const ModelVolume *model_volume = model_object->volumes[volume_idx];
|
||||
const int extruder_id = model_volume->extruder_id();
|
||||
const ModelInstance *instance = model_object->instances[instance_idx];
|
||||
const TriangleMesh& mesh = model_volume->mesh;
|
||||
float color[4];
|
||||
memcpy(color, colors[((color_by == "volume") ? volume_idx : obj_idx) % 4], sizeof(float) * 3);
|
||||
memcpy(color, GLVolume::MODEL_COLOR[((color_by == "volume") ? volume_idx : obj_idx) % 4], sizeof(float) * 3);
|
||||
/* if (model_volume->is_support_blocker()) {
|
||||
color[0] = 1.0f;
|
||||
color[1] = 0.2f;
|
||||
|
@ -595,10 +594,7 @@ int GLVolumeCollection::load_object_volume(
|
|||
this->volumes.emplace_back(new GLVolume(color));
|
||||
GLVolume &v = *this->volumes.back();
|
||||
v.set_color_from_model_volume(model_volume);
|
||||
if (use_VBOs)
|
||||
v.indexed_vertex_array.load_mesh_full_shading(mesh);
|
||||
else
|
||||
v.indexed_vertex_array.load_mesh_flat_shading(mesh);
|
||||
v.indexed_vertex_array.load_mesh(mesh, use_VBOs);
|
||||
|
||||
// finalize_geometry() clears the vertex arrays, therefore the bounding box has to be computed before finalize_geometry().
|
||||
v.bounding_box = v.indexed_vertex_array.bounding_box();
|
||||
|
@ -640,14 +636,10 @@ void GLVolumeCollection::load_object_auxiliary(
|
|||
// Convex hull is required for out of print bed detection.
|
||||
TriangleMesh convex_hull = mesh.convex_hull_3d();
|
||||
for (const std::pair<size_t, size_t> &instance_idx : instances) {
|
||||
const ModelInstance &model_instance = *print_object->model_object()->instances[instance_idx.first];
|
||||
const SLAPrintObject::Instance &print_instance = print_object->instances()[instance_idx.second];
|
||||
const ModelInstance &model_instance = *print_object->model_object()->instances[instance_idx.first];
|
||||
this->volumes.emplace_back(new GLVolume((milestone == slaposBasePool) ? GLVolume::SLA_PAD_COLOR : GLVolume::SLA_SUPPORT_COLOR));
|
||||
GLVolume &v = *this->volumes.back();
|
||||
if (use_VBOs)
|
||||
v.indexed_vertex_array.load_mesh_full_shading(mesh);
|
||||
else
|
||||
v.indexed_vertex_array.load_mesh_flat_shading(mesh);
|
||||
v.indexed_vertex_array.load_mesh(mesh, use_VBOs);
|
||||
// finalize_geometry() clears the vertex arrays, therefore the bounding box has to be computed before finalize_geometry().
|
||||
v.bounding_box = v.indexed_vertex_array.bounding_box();
|
||||
v.indexed_vertex_array.finalize_geometry(use_VBOs);
|
||||
|
@ -718,14 +710,8 @@ int GLVolumeCollection::load_wipe_tower_preview(
|
|||
|
||||
this->volumes.emplace_back(new GLVolume(color));
|
||||
GLVolume &v = *this->volumes.back();
|
||||
|
||||
if (use_VBOs)
|
||||
v.indexed_vertex_array.load_mesh_full_shading(mesh);
|
||||
else
|
||||
v.indexed_vertex_array.load_mesh_flat_shading(mesh);
|
||||
|
||||
v.indexed_vertex_array.load_mesh(mesh, use_VBOs);
|
||||
v.set_volume_offset(Vec3d(pos_x, pos_y, 0.0));
|
||||
|
||||
// finalize_geometry() clears the vertex arrays, therefore the bounding box has to be computed before finalize_geometry().
|
||||
v.bounding_box = v.indexed_vertex_array.bounding_box();
|
||||
v.indexed_vertex_array.finalize_geometry(use_VBOs);
|
||||
|
@ -1856,12 +1842,7 @@ bool GLArrow::on_init(bool useVBOs)
|
|||
triangles.emplace_back(7, 13, 6);
|
||||
|
||||
m_useVBOs = useVBOs;
|
||||
|
||||
if (m_useVBOs)
|
||||
m_volume.indexed_vertex_array.load_mesh_full_shading(TriangleMesh(vertices, triangles));
|
||||
else
|
||||
m_volume.indexed_vertex_array.load_mesh_flat_shading(TriangleMesh(vertices, triangles));
|
||||
|
||||
m_volume.indexed_vertex_array.load_mesh(TriangleMesh(vertices, triangles), useVBOs);
|
||||
m_volume.finalize_geometry(m_useVBOs);
|
||||
return true;
|
||||
}
|
||||
|
@ -1976,12 +1957,7 @@ bool GLCurvedArrow::on_init(bool useVBOs)
|
|||
triangles.emplace_back(vertices_per_level, 2 * vertices_per_level + 1, vertices_per_level + 1);
|
||||
|
||||
m_useVBOs = useVBOs;
|
||||
|
||||
if (m_useVBOs)
|
||||
m_volume.indexed_vertex_array.load_mesh_full_shading(TriangleMesh(vertices, triangles));
|
||||
else
|
||||
m_volume.indexed_vertex_array.load_mesh_flat_shading(TriangleMesh(vertices, triangles));
|
||||
|
||||
m_volume.indexed_vertex_array.load_mesh(TriangleMesh(vertices, triangles), useVBOs);
|
||||
m_volume.bounding_box = m_volume.indexed_vertex_array.bounding_box();
|
||||
m_volume.finalize_geometry(m_useVBOs);
|
||||
return true;
|
||||
|
@ -2016,10 +1992,7 @@ bool GLBed::on_init_from_file(const std::string& filename, bool useVBOs)
|
|||
TriangleMesh mesh = model.mesh();
|
||||
mesh.repair();
|
||||
|
||||
if (m_useVBOs)
|
||||
m_volume.indexed_vertex_array.load_mesh_full_shading(mesh);
|
||||
else
|
||||
m_volume.indexed_vertex_array.load_mesh_flat_shading(mesh);
|
||||
m_volume.indexed_vertex_array.load_mesh(mesh, useVBOs);
|
||||
|
||||
float color[4] = { 0.235f, 0.235f, 0.235f, 1.0f };
|
||||
set_color(color, 4);
|
||||
|
|
|
@ -116,6 +116,7 @@ public:
|
|||
|
||||
void load_mesh_flat_shading(const TriangleMesh &mesh);
|
||||
void load_mesh_full_shading(const TriangleMesh &mesh);
|
||||
void load_mesh(const TriangleMesh &mesh, bool use_VBOs) { use_VBOs ? this->load_mesh_full_shading(mesh) : this->load_mesh_flat_shading(mesh); }
|
||||
|
||||
inline bool has_VBOs() const { return vertices_and_normals_interleaved_VBO_id != 0; }
|
||||
|
||||
|
@ -228,6 +229,7 @@ public:
|
|||
static const float OUTSIDE_COLOR[4];
|
||||
static const float SELECTED_OUTSIDE_COLOR[4];
|
||||
static const float DISABLED_COLOR[4];
|
||||
static const float MODEL_COLOR[4][4];
|
||||
static const float SLA_SUPPORT_COLOR[4];
|
||||
static const float SLA_PAD_COLOR[4];
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ AboutDialog::AboutDialog()
|
|||
main_sizer->Add(hsizer, 0, wxEXPAND | wxALL, 20);
|
||||
|
||||
// logo
|
||||
auto *logo = new wxStaticBitmap(this, wxID_ANY, create_scaled_bitmap("Slic3r_192px.png", 192));
|
||||
auto *logo = new wxStaticBitmap(this, wxID_ANY, create_scaled_bitmap(this, "Slic3r_192px.png", 192));
|
||||
hsizer->Add(logo, 1, wxALIGN_CENTER_VERTICAL);
|
||||
|
||||
wxBoxSizer* vsizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
|
|
@ -27,16 +27,25 @@ void BitmapCache::clear()
|
|||
m_map.clear();
|
||||
}
|
||||
|
||||
static wxBitmap wxImage_to_wxBitmap_with_alpha(wxImage &&image)
|
||||
static wxBitmap wxImage_to_wxBitmap_with_alpha(wxImage &&image, float scale = 1.0f)
|
||||
{
|
||||
#ifdef BROKEN_ALPHA
|
||||
wxMemoryOutputStream stream;
|
||||
image.SaveFile(stream, wxBITMAP_TYPE_PNG);
|
||||
wxStreamBuffer *buf = stream.GetOutputStreamBuffer();
|
||||
return wxBitmap::NewFromPNGData(buf->GetBufferStart(), buf->GetBufferSize());
|
||||
#else
|
||||
#ifdef __APPLE__
|
||||
// This is a c-tor native to Mac OS. We need to let the Mac OS wxBitmap implementation
|
||||
// know that the image may already be scaled appropriately for Retina,
|
||||
// and thereby that it's not supposed to upscale it.
|
||||
// Contrary to intuition, the `scale` argument isn't "please scale this to such and such"
|
||||
// but rather "the wxImage is sized for backing scale such and such".
|
||||
return wxBitmap(std::move(image), -1, scale);
|
||||
#else
|
||||
return wxBitmap(std::move(image));
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
wxBitmap* BitmapCache::insert(const std::string &bitmap_key, size_t width, size_t height)
|
||||
|
@ -165,7 +174,7 @@ wxBitmap* BitmapCache::insert(const std::string &bitmap_key, const wxBitmap *beg
|
|||
#endif
|
||||
}
|
||||
|
||||
wxBitmap* BitmapCache::insert_raw_rgba(const std::string &bitmap_key, unsigned int width, unsigned int height, const unsigned char *raw_data)
|
||||
wxBitmap* BitmapCache::insert_raw_rgba(const std::string &bitmap_key, unsigned width, unsigned height, const unsigned char *raw_data, float scale /* = 1.0f */)
|
||||
{
|
||||
wxImage image(width, height);
|
||||
image.InitAlpha();
|
||||
|
@ -178,7 +187,7 @@ wxBitmap* BitmapCache::insert_raw_rgba(const std::string &bitmap_key, unsigned i
|
|||
*rgb ++ = *raw_data ++;
|
||||
*alpha ++ = *raw_data ++;
|
||||
}
|
||||
return this->insert(bitmap_key, wxImage_to_wxBitmap_with_alpha(std::move(image)));
|
||||
return this->insert(bitmap_key, wxImage_to_wxBitmap_with_alpha(std::move(image), scale));
|
||||
}
|
||||
|
||||
wxBitmap* BitmapCache::load_png(const std::string &bitmap_name, unsigned int width, unsigned int height)
|
||||
|
@ -186,6 +195,7 @@ wxBitmap* BitmapCache::load_png(const std::string &bitmap_name, unsigned int wid
|
|||
std::string bitmap_key = bitmap_name + ( height !=0 ?
|
||||
"-h" + std::to_string(height) :
|
||||
"-w" + std::to_string(width));
|
||||
|
||||
auto it = m_map.find(bitmap_key);
|
||||
if (it != m_map.end())
|
||||
return it->second;
|
||||
|
@ -206,11 +216,15 @@ wxBitmap* BitmapCache::load_png(const std::string &bitmap_name, unsigned int wid
|
|||
return this->insert(bitmap_key, wxImage_to_wxBitmap_with_alpha(std::move(image)));
|
||||
}
|
||||
|
||||
wxBitmap* BitmapCache::load_svg(const std::string &bitmap_name, unsigned int target_width, unsigned int target_height)
|
||||
wxBitmap* BitmapCache::load_svg(const std::string &bitmap_name, unsigned target_width, unsigned target_height, float scale /* = 1.0f */)
|
||||
{
|
||||
std::string bitmap_key = bitmap_name + (target_height != 0 ?
|
||||
"-h" + std::to_string(target_height) :
|
||||
"-w" + std::to_string(target_width));
|
||||
std::string bitmap_key = bitmap_name + ( target_height !=0 ?
|
||||
"-h" + std::to_string(target_height) :
|
||||
"-w" + std::to_string(target_width))
|
||||
+ (scale != 1.0f ? "-s" + std::to_string(scale) : "");
|
||||
|
||||
target_height != 0 ? target_height *= scale : target_width *= scale;
|
||||
|
||||
auto it = m_map.find(bitmap_key);
|
||||
if (it != m_map.end())
|
||||
return it->second;
|
||||
|
@ -219,12 +233,12 @@ wxBitmap* BitmapCache::load_svg(const std::string &bitmap_name, unsigned int tar
|
|||
if (image == nullptr)
|
||||
return nullptr;
|
||||
|
||||
float scale = target_height != 0 ?
|
||||
float svg_scale = target_height != 0 ?
|
||||
(float)target_height / image->height : target_width != 0 ?
|
||||
(float)target_width / image->width : 1;
|
||||
|
||||
int width = (int)(scale * image->width + 0.5f);
|
||||
int height = (int)(scale * image->height + 0.5f);
|
||||
int width = (int)(svg_scale * image->width + 0.5f);
|
||||
int height = (int)(svg_scale * image->height + 0.5f);
|
||||
int n_pixels = width * height;
|
||||
if (n_pixels <= 0) {
|
||||
::nsvgDelete(image);
|
||||
|
@ -238,11 +252,11 @@ wxBitmap* BitmapCache::load_svg(const std::string &bitmap_name, unsigned int tar
|
|||
}
|
||||
|
||||
std::vector<unsigned char> data(n_pixels * 4, 0);
|
||||
::nsvgRasterize(rast, image, 0, 0, scale, data.data(), width, height, width * 4);
|
||||
::nsvgRasterize(rast, image, 0, 0, svg_scale, data.data(), width, height, width * 4);
|
||||
::nsvgDeleteRasterizer(rast);
|
||||
::nsvgDelete(image);
|
||||
|
||||
return this->insert_raw_rgba(bitmap_key, width, height, data.data());
|
||||
return this->insert_raw_rgba(bitmap_key, width, height, data.data(), scale);
|
||||
}
|
||||
|
||||
wxBitmap BitmapCache::mksolid(size_t width, size_t height, unsigned char r, unsigned char g, unsigned char b, unsigned char transparency)
|
||||
|
|
|
@ -29,12 +29,12 @@ public:
|
|||
wxBitmap* insert(const std::string &name, const wxBitmap &bmp, const wxBitmap &bmp2, const wxBitmap &bmp3);
|
||||
wxBitmap* insert(const std::string &name, const std::vector<wxBitmap> &bmps) { return this->insert(name, &bmps.front(), &bmps.front() + bmps.size()); }
|
||||
wxBitmap* insert(const std::string &name, const wxBitmap *begin, const wxBitmap *end);
|
||||
wxBitmap* insert_raw_rgba(const std::string &bitmap_key, unsigned int width, unsigned int height, const unsigned char *raw_data);
|
||||
wxBitmap* insert_raw_rgba(const std::string &bitmap_key, unsigned width, unsigned height, const unsigned char *raw_data, float scale = 1.0f);
|
||||
|
||||
// Load png from resources/icons. bitmap_key is given without the .png suffix. Bitmap will be rescaled to provided height/width if nonzero.
|
||||
wxBitmap* load_png(const std::string &bitmap_key, unsigned int width = 0, unsigned int height = 0);
|
||||
// Load svg from resources/icons. bitmap_key is given without the .svg suffix. SVG will be rasterized to provided height/width.
|
||||
wxBitmap* load_svg(const std::string &bitmap_key, unsigned int width = 0, unsigned int height = 0);
|
||||
wxBitmap* load_svg(const std::string &bitmap_key, unsigned int width = 0, unsigned int height = 0, float scale = 1.0f);
|
||||
|
||||
static wxBitmap mksolid(size_t width, size_t height, unsigned char r, unsigned char g, unsigned char b, unsigned char transparency);
|
||||
static wxBitmap mksolid(size_t width, size_t height, const unsigned char rgb[3]) { return mksolid(width, height, rgb[0], rgb[1], rgb[2], wxALPHA_OPAQUE); }
|
||||
|
|
|
@ -1893,6 +1893,9 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
|||
size_t idx = 0;
|
||||
const SLAPrint *sla_print = this->sla_print();
|
||||
std::vector<double> shift_zs(m_model->objects.size(), 0);
|
||||
double relative_correction_z = sla_print->relative_correction().z();
|
||||
if (relative_correction_z <= EPSILON)
|
||||
relative_correction_z = 1.;
|
||||
for (const SLAPrintObject *print_object : sla_print->objects()) {
|
||||
SLASupportState &state = sla_support_state[idx ++];
|
||||
const ModelObject *model_object = print_object->model_object();
|
||||
|
@ -1906,7 +1909,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
|||
assert(it != sla_print->model().objects.end());
|
||||
object_idx = it - sla_print->model().objects.begin();
|
||||
// Cache the Z offset to be applied to all volumes with this object_idx.
|
||||
shift_zs[object_idx] = print_object->get_current_elevation();
|
||||
shift_zs[object_idx] = print_object->get_current_elevation() / relative_correction_z;
|
||||
// Collect indices of this print_object's instances, for which the SLA support meshes are to be added to the scene.
|
||||
// pairs of <instance_idx, print_instance_idx>
|
||||
std::vector<std::pair<size_t, size_t>> instances[std::tuple_size<SLASteps>::value];
|
||||
|
@ -2310,6 +2313,9 @@ void GLCanvas3D::on_key(wxKeyEvent& evt)
|
|||
|
||||
void GLCanvas3D::on_mouse_wheel(wxMouseEvent& evt)
|
||||
{
|
||||
if (!m_initialized)
|
||||
return;
|
||||
|
||||
// Ignore the wheel events if the middle button is pressed.
|
||||
if (evt.MiddleIsDown())
|
||||
return;
|
||||
|
@ -2563,8 +2569,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
|||
m_selection.remove(m_hover_volume_id);
|
||||
else
|
||||
{
|
||||
bool add_as_single = !already_selected && !ctrl_down;
|
||||
m_selection.add(m_hover_volume_id, add_as_single);
|
||||
m_selection.add(m_hover_volume_id, !ctrl_down);
|
||||
m_mouse.drag.move_requires_threshold = !already_selected;
|
||||
if (already_selected)
|
||||
m_mouse.set_move_start_threshold_position_2D_as_invalid();
|
||||
|
@ -3293,8 +3298,9 @@ bool GLCanvas3D::_init_toolbar()
|
|||
|
||||
bool GLCanvas3D::_set_current()
|
||||
{
|
||||
if ((m_canvas != nullptr) && (m_context != nullptr))
|
||||
if (_is_shown_on_screen() && (m_context != nullptr)) {
|
||||
return m_canvas->SetCurrent(*m_context);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -5038,97 +5044,44 @@ void GLCanvas3D::_load_shells_sla()
|
|||
// nothing to render, return
|
||||
return;
|
||||
|
||||
auto add_volume = [this](const SLAPrintObject &object, const SLAPrintObject::Instance& instance,
|
||||
const TriangleMesh &mesh, const float color[4], bool outside_printer_detection_enabled) {
|
||||
m_volumes.volumes.emplace_back(new GLVolume(color));
|
||||
GLVolume& v = *m_volumes.volumes.back();
|
||||
v.indexed_vertex_array.load_mesh(mesh, m_use_VBOs);
|
||||
v.shader_outside_printer_detection_enabled = outside_printer_detection_enabled;
|
||||
v.composite_id.volume_id = -1;
|
||||
v.set_instance_offset(unscale(instance.shift(0), instance.shift(1), 0));
|
||||
v.set_instance_rotation(Vec3d(0.0, 0.0, (double)instance.rotation));
|
||||
v.set_instance_mirror(X, object.is_left_handed() ? -1. : 1.);
|
||||
};
|
||||
|
||||
// adds objects' volumes
|
||||
int obj_idx = 0;
|
||||
for (const SLAPrintObject* obj : print->objects())
|
||||
{
|
||||
if (!obj->is_step_done(slaposSliceSupports))
|
||||
continue;
|
||||
|
||||
unsigned int initial_volumes_count = (unsigned int)m_volumes.volumes.size();
|
||||
|
||||
// selects only instances which were sliced
|
||||
const ModelObject* model_obj = obj->model_object();
|
||||
const std::vector<SLAPrintObject::Instance>& sla_instances = obj->instances();
|
||||
std::vector<int> instances_model_idxs(sla_instances.size());
|
||||
for (int i = 0; i < (int)sla_instances.size(); ++i)
|
||||
{
|
||||
instances_model_idxs[i] = (int)sla_instances[i].instance_id.id;
|
||||
}
|
||||
|
||||
std::vector<int> sliced_instance_idxs;
|
||||
for (int i = 0; i < (int)model_obj->instances.size(); ++i)
|
||||
{
|
||||
if (std::find(instances_model_idxs.begin(), instances_model_idxs.end(), (int)model_obj->instances[i]->id().id) != instances_model_idxs.end())
|
||||
sliced_instance_idxs.push_back(i);
|
||||
}
|
||||
|
||||
m_volumes.load_object(model_obj, obj_idx, sliced_instance_idxs, "object", m_use_VBOs && m_initialized);
|
||||
|
||||
for (const SLAPrintObject::Instance& instance : sla_instances)
|
||||
{
|
||||
Vec3d offset = unscale(instance.shift(0), instance.shift(1), 0);
|
||||
Vec3d rotation(0.0, 0.0, (double)instance.rotation);
|
||||
|
||||
unsigned int partial_volumes_count = (unsigned int)m_volumes.volumes.size();
|
||||
|
||||
// add supports
|
||||
if (obj->is_step_done(slaposSupportTree) && obj->has_mesh(slaposSupportTree))
|
||||
{
|
||||
const TriangleMesh& mesh = obj->support_mesh();
|
||||
m_volumes.volumes.emplace_back(new GLVolume(GLVolume::SLA_SUPPORT_COLOR));
|
||||
GLVolume& v = *m_volumes.volumes.back();
|
||||
|
||||
if (m_use_VBOs)
|
||||
v.indexed_vertex_array.load_mesh_full_shading(mesh);
|
||||
else
|
||||
v.indexed_vertex_array.load_mesh_flat_shading(mesh);
|
||||
|
||||
v.shader_outside_printer_detection_enabled = true;
|
||||
v.composite_id.volume_id = -1;
|
||||
v.set_instance_offset(offset);
|
||||
v.set_instance_rotation(rotation);
|
||||
v.set_instance_mirror(X, obj->is_left_handed() ? -1. : 1.);
|
||||
if (obj->is_step_done(slaposSliceSupports)) {
|
||||
unsigned int initial_volumes_count = (unsigned int)m_volumes.volumes.size();
|
||||
for (const SLAPrintObject::Instance& instance : obj->instances()) {
|
||||
add_volume(*obj, instance, obj->transformed_mesh(), GLVolume::MODEL_COLOR[0], true);
|
||||
// Set the extruder_id and volume_id to achieve the same color as in the 3D scene when
|
||||
// through the update_volumes_colors_by_extruder() call.
|
||||
m_volumes.volumes.back()->extruder_id = obj->model_object()->volumes.front()->extruder_id();
|
||||
m_volumes.volumes.back()->composite_id.volume_id = 0;
|
||||
if (obj->is_step_done(slaposSupportTree) && obj->has_mesh(slaposSupportTree))
|
||||
add_volume(*obj, instance, obj->support_mesh(), GLVolume::SLA_SUPPORT_COLOR, true);
|
||||
if (obj->is_step_done(slaposBasePool) && obj->has_mesh(slaposBasePool))
|
||||
add_volume(*obj, instance, obj->pad_mesh(), GLVolume::SLA_PAD_COLOR, true);
|
||||
}
|
||||
|
||||
// add pad
|
||||
if (obj->is_step_done(slaposBasePool) && obj->has_mesh(slaposBasePool))
|
||||
{
|
||||
const TriangleMesh& mesh = obj->pad_mesh();
|
||||
m_volumes.volumes.emplace_back(new GLVolume(GLVolume::SLA_PAD_COLOR));
|
||||
GLVolume& v = *m_volumes.volumes.back();
|
||||
|
||||
if (m_use_VBOs)
|
||||
v.indexed_vertex_array.load_mesh_full_shading(mesh);
|
||||
else
|
||||
v.indexed_vertex_array.load_mesh_flat_shading(mesh);
|
||||
|
||||
v.shader_outside_printer_detection_enabled = false;
|
||||
v.composite_id.volume_id = -1;
|
||||
v.set_instance_offset(offset);
|
||||
v.set_instance_rotation(rotation);
|
||||
v.set_instance_mirror(X, obj->is_left_handed() ? -1. : 1.);
|
||||
}
|
||||
|
||||
// finalize volumes and sends geometry to gpu
|
||||
for (unsigned int i = partial_volumes_count; i < m_volumes.volumes.size(); ++i)
|
||||
{
|
||||
double shift_z = obj->get_current_elevation();
|
||||
for (unsigned int i = initial_volumes_count; i < m_volumes.volumes.size(); ++ i) {
|
||||
GLVolume& v = *m_volumes.volumes[i];
|
||||
// finalize volumes and sends geometry to gpu
|
||||
v.bounding_box = v.indexed_vertex_array.bounding_box();
|
||||
v.indexed_vertex_array.finalize_geometry(m_use_VBOs);
|
||||
// apply shift z
|
||||
v.set_sla_shift_z(shift_z);
|
||||
}
|
||||
|
||||
++obj_idx;
|
||||
}
|
||||
|
||||
// apply shift z
|
||||
double shift_z = obj->get_current_elevation();
|
||||
for (unsigned int i = initial_volumes_count; i < m_volumes.volumes.size(); ++i)
|
||||
{
|
||||
m_volumes.volumes[i]->set_sla_shift_z(shift_z);
|
||||
}
|
||||
}
|
||||
|
||||
update_volumes_colors_by_extruder();
|
||||
#else
|
||||
this->reload_scene(true, true);
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#include <wx/wupdlock.h>
|
||||
#include <wx/filefn.h>
|
||||
#include <wx/sysopt.h>
|
||||
#include <wx/msgdlg.h>
|
||||
#include <wx/log.h>
|
||||
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include "libslic3r/Model.hpp"
|
||||
|
@ -94,6 +96,34 @@ static void register_dpi_event()
|
|||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void generic_exception_handle()
|
||||
{
|
||||
// Note: Some wxWidgets APIs use wxLogError() to report errors, eg. wxImage
|
||||
// - see https://docs.wxwidgets.org/3.1/classwx_image.html#aa249e657259fe6518d68a5208b9043d0
|
||||
//
|
||||
// wxLogError typically goes around exception handling and display an error dialog some time
|
||||
// after an error is logged even if exception handling and OnExceptionInMainLoop() take place.
|
||||
// This is why we use wxLogError() here as well instead of a custom dialog, because it accumulates
|
||||
// errors if multiple have been collected and displays just one error message for all of them.
|
||||
// Otherwise we would get multiple error messages for one missing png, for example.
|
||||
//
|
||||
// If a custom error message window (or some other solution) were to be used, it would be necessary
|
||||
// to turn off wxLogError() usage in wx APIs, most notably in wxImage
|
||||
// - see https://docs.wxwidgets.org/trunk/classwx_image.html#aa32e5d3507cc0f8c3330135bc0befc6a
|
||||
|
||||
try {
|
||||
throw;
|
||||
} catch (const std::exception &ex) {
|
||||
wxLogError("Internal error: %s", ex.what());
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("Uncaught exception: %1%") % ex.what();
|
||||
throw;
|
||||
} catch (...) {
|
||||
wxLogError("Unknown internal error");
|
||||
BOOST_LOG_TRIVIAL(error) << "Uncaught exception: Unknown error";
|
||||
}
|
||||
}
|
||||
|
||||
IMPLEMENT_APP(GUI_App)
|
||||
|
||||
GUI_App::GUI_App()
|
||||
|
@ -103,6 +133,16 @@ GUI_App::GUI_App()
|
|||
{}
|
||||
|
||||
bool GUI_App::OnInit()
|
||||
{
|
||||
try {
|
||||
return on_init_inner();
|
||||
} catch (...) {
|
||||
generic_exception_handle();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool GUI_App::on_init_inner()
|
||||
{
|
||||
// Verify resources path
|
||||
const wxString resources_dir = from_u8(Slic3r::resources_dir());
|
||||
|
@ -132,13 +172,7 @@ bool GUI_App::OnInit()
|
|||
|
||||
// just checking for existence of Slic3r::data_dir is not enough : it may be an empty directory
|
||||
// supplied as argument to --datadir; in that case we should still run the wizard
|
||||
try {
|
||||
preset_bundle->setup_directories();
|
||||
} catch (const std::exception &ex) {
|
||||
show_error(nullptr, ex.what());
|
||||
// Exit the application.
|
||||
return false;
|
||||
}
|
||||
preset_bundle->setup_directories();
|
||||
|
||||
app_conf_exists = app_config->exists();
|
||||
// load settings
|
||||
|
@ -161,11 +195,11 @@ bool GUI_App::OnInit()
|
|||
|
||||
// Suppress the '- default -' presets.
|
||||
preset_bundle->set_default_suppressed(app_config->get("no_defaults") == "1");
|
||||
try {
|
||||
preset_bundle->load_presets(*app_config);
|
||||
} catch (const std::exception &ex) {
|
||||
show_error(nullptr, ex.what());
|
||||
}
|
||||
try {
|
||||
preset_bundle->load_presets(*app_config);
|
||||
} catch (const std::exception &ex) {
|
||||
show_error(nullptr, from_u8(ex.what()));
|
||||
}
|
||||
|
||||
register_dpi_event();
|
||||
|
||||
|
@ -184,8 +218,8 @@ bool GUI_App::OnInit()
|
|||
|
||||
Bind(wxEVT_IDLE, [this](wxIdleEvent& event)
|
||||
{
|
||||
if (! plater_)
|
||||
return;
|
||||
if (! plater_)
|
||||
return;
|
||||
|
||||
if (app_config->dirty() && app_config->get("autosave") == "1")
|
||||
app_config->save();
|
||||
|
@ -207,7 +241,7 @@ bool GUI_App::OnInit()
|
|||
mainframe->Close();
|
||||
}
|
||||
} catch (const std::exception &ex) {
|
||||
show_error(nullptr, ex.what());
|
||||
show_error(nullptr, from_u8(ex.what()));
|
||||
}
|
||||
|
||||
CallAfter([this] {
|
||||
|
@ -752,18 +786,7 @@ void GUI_App::load_current_presets()
|
|||
|
||||
bool GUI_App::OnExceptionInMainLoop()
|
||||
{
|
||||
try {
|
||||
throw;
|
||||
} catch (const std::exception &ex) {
|
||||
const std::string error = (boost::format("Uncaught exception: %1%") % ex.what()).str();
|
||||
BOOST_LOG_TRIVIAL(error) << error;
|
||||
show_error(nullptr, from_u8(error));
|
||||
} catch (...) {
|
||||
const char *error = "Uncaught exception: Unknown error";
|
||||
BOOST_LOG_TRIVIAL(error) << error;
|
||||
show_error(nullptr, from_u8(error));
|
||||
}
|
||||
|
||||
generic_exception_handle();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -169,6 +169,7 @@ public:
|
|||
PrintHostJobQueue& printhost_job_queue() { return *m_printhost_job_queue.get(); }
|
||||
|
||||
private:
|
||||
bool on_init_inner();
|
||||
void window_pos_save(wxTopLevelWindow* window, const std::string &name);
|
||||
void window_pos_restore(wxTopLevelWindow* window, const std::string &name);
|
||||
void window_pos_sanitize(wxTopLevelWindow* window);
|
||||
|
|
|
@ -62,18 +62,18 @@ ObjectList::ObjectList(wxWindow* parent) :
|
|||
// Fill CATEGORY_ICON
|
||||
{
|
||||
// ptFFF
|
||||
CATEGORY_ICON[L("Layers and Perimeters")] = create_scaled_bitmap("layers");
|
||||
CATEGORY_ICON[L("Infill")] = create_scaled_bitmap("infill");
|
||||
CATEGORY_ICON[L("Support material")] = create_scaled_bitmap("support");
|
||||
CATEGORY_ICON[L("Speed")] = create_scaled_bitmap("time");
|
||||
CATEGORY_ICON[L("Extruders")] = create_scaled_bitmap("funnel");
|
||||
CATEGORY_ICON[L("Extrusion Width")] = create_scaled_bitmap("funnel");
|
||||
// CATEGORY_ICON[L("Skirt and brim")] = create_scaled_bitmap("skirt+brim");
|
||||
// CATEGORY_ICON[L("Speed > Acceleration")] = create_scaled_bitmap("time");
|
||||
CATEGORY_ICON[L("Advanced")] = create_scaled_bitmap("wrench");
|
||||
CATEGORY_ICON[L("Layers and Perimeters")] = create_scaled_bitmap(this, "layers");
|
||||
CATEGORY_ICON[L("Infill")] = create_scaled_bitmap(this, "infill");
|
||||
CATEGORY_ICON[L("Support material")] = create_scaled_bitmap(this, "support");
|
||||
CATEGORY_ICON[L("Speed")] = create_scaled_bitmap(this, "time");
|
||||
CATEGORY_ICON[L("Extruders")] = create_scaled_bitmap(this, "funnel");
|
||||
CATEGORY_ICON[L("Extrusion Width")] = create_scaled_bitmap(this, "funnel");
|
||||
// CATEGORY_ICON[L("Skirt and brim")] = create_scaled_bitmap(this, "skirt+brim");
|
||||
// CATEGORY_ICON[L("Speed > Acceleration")] = create_scaled_bitmap(this, "time");
|
||||
CATEGORY_ICON[L("Advanced")] = create_scaled_bitmap(this, "wrench");
|
||||
// ptSLA
|
||||
CATEGORY_ICON[L("Supports")] = create_scaled_bitmap("sla_supports");
|
||||
CATEGORY_ICON[L("Pad")] = create_scaled_bitmap("brick.png");
|
||||
CATEGORY_ICON[L("Supports")] = create_scaled_bitmap(this, "sla_supports");
|
||||
CATEGORY_ICON[L("Pad")] = create_scaled_bitmap(this, "brick.png");
|
||||
}
|
||||
|
||||
// create control
|
||||
|
@ -88,7 +88,7 @@ ObjectList::ObjectList(wxWindow* parent) :
|
|||
// before the kill focus event handler on the object manipulator when changing selection in the list, invalidating the object
|
||||
// manipulator cache with the following call to selection_changed()
|
||||
wxGetApp().obj_manipul()->emulate_kill_focus();
|
||||
|
||||
#else
|
||||
// To avoid selection update from SetSelection() and UnselectAll() under osx
|
||||
if (m_prevent_list_events)
|
||||
return;
|
||||
|
@ -141,6 +141,8 @@ ObjectList::ObjectList(wxWindow* parent) :
|
|||
#ifdef __WXOSX__
|
||||
Bind(wxEVT_KEY_DOWN, &ObjectList::OnChar, this);
|
||||
#endif //__WXOSX__
|
||||
|
||||
Bind(wxEVT_SIZE, ([this](wxSizeEvent &e) { this->EnsureVisible(this->GetCurrentItem()); e.Skip(); }));
|
||||
}
|
||||
|
||||
ObjectList::~ObjectList()
|
||||
|
@ -390,10 +392,10 @@ void ObjectList::update_name_in_model(const wxDataViewItem& item) const
|
|||
|
||||
void ObjectList::init_icons()
|
||||
{
|
||||
m_bmp_modifiermesh = create_scaled_bitmap("lambda.png");
|
||||
m_bmp_solidmesh = create_scaled_bitmap("object.png");
|
||||
m_bmp_support_enforcer = create_scaled_bitmap("support_enforcer_.png");
|
||||
m_bmp_support_blocker = create_scaled_bitmap("support_blocker_.png");
|
||||
m_bmp_modifiermesh = create_scaled_bitmap(this, "lambda.png");
|
||||
m_bmp_solidmesh = create_scaled_bitmap(this, "object.png");
|
||||
m_bmp_support_enforcer = create_scaled_bitmap(this, "support_enforcer_.png");
|
||||
m_bmp_support_blocker = create_scaled_bitmap(this, "support_blocker_.png");
|
||||
|
||||
|
||||
m_bmp_vector.reserve(4); // bitmaps for different types of parts
|
||||
|
@ -404,13 +406,13 @@ void ObjectList::init_icons()
|
|||
m_objects_model->SetVolumeBitmaps(m_bmp_vector);
|
||||
|
||||
// init icon for manifold warning
|
||||
m_bmp_manifold_warning = create_scaled_bitmap("exclamation_mark_.png");
|
||||
m_bmp_manifold_warning = create_scaled_bitmap(this, "exclamation_mark_.png");
|
||||
|
||||
// init bitmap for "Split to sub-objects" context menu
|
||||
m_bmp_split = create_scaled_bitmap("split_parts");
|
||||
m_bmp_split = create_scaled_bitmap(this, "split_parts");
|
||||
|
||||
// init bitmap for "Add Settings" context menu
|
||||
m_bmp_cog = create_scaled_bitmap("cog");
|
||||
m_bmp_cog = create_scaled_bitmap(this, "cog");
|
||||
}
|
||||
|
||||
|
||||
|
@ -1977,7 +1979,7 @@ void ObjectList::update_selections()
|
|||
if (selection.is_single_full_object() &&
|
||||
m_objects_model->GetIdByItem(m_objects_model->GetParent(item)) == selection.get_object_idx())
|
||||
return;
|
||||
if (selection.is_single_volume() || selection.is_modifier()) {
|
||||
if (selection.is_single_volume() || selection.is_any_modifier()) {
|
||||
const auto gl_vol = selection.get_volume(*selection.get_volume_idxs().begin());
|
||||
if (m_objects_model->GetVolumeIdByItem(m_objects_model->GetParent(item)) == gl_vol->volume_idx())
|
||||
return;
|
||||
|
@ -2012,7 +2014,7 @@ void ObjectList::update_selections()
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (selection.is_single_volume() || selection.is_modifier() || selection.is_multiple_volume())
|
||||
else if (selection.is_any_volume() || selection.is_any_modifier())
|
||||
{
|
||||
for (auto idx : selection.get_volume_idxs()) {
|
||||
const auto gl_vol = selection.get_volume(idx);
|
||||
|
@ -2071,23 +2073,8 @@ void ObjectList::update_selections()
|
|||
|
||||
select_items(sels);
|
||||
|
||||
/* Because of ScrollLines() and GetItemRect() functions are implemented
|
||||
* only for GENERIC DataViewCtrl in current version of wxWidgets,
|
||||
* use this part of code only for MSW
|
||||
*/
|
||||
#if defined(wxUSE_GENERICDATAVIEWCTRL)
|
||||
// Scroll selected Item in the middle of an object list
|
||||
if (GetSelection()) {
|
||||
const wxRect& sel_rc = GetItemRect(GetSelection());
|
||||
const wxRect& main_rc = GetClientRect();
|
||||
if (sel_rc.GetBottom() <= main_rc.GetTop()+sel_rc.height ||
|
||||
sel_rc.GetTop() >= main_rc.GetBottom() )
|
||||
{
|
||||
const wxRect& top_rc = GetItemRect(GetTopItem());
|
||||
ScrollLines(int((sel_rc.y - top_rc.y) / top_rc.GetHeight()) - 0.5*GetCountPerPage());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
this->EnsureVisible(this->GetCurrentItem());
|
||||
}
|
||||
|
||||
void ObjectList::update_selections_on_canvas()
|
||||
|
@ -2133,6 +2120,7 @@ void ObjectList::update_selections_on_canvas()
|
|||
add_to_selection(item, selection, instance_idx, true);
|
||||
|
||||
wxGetApp().plater()->canvas3D()->update_gizmos_on_off_state();
|
||||
wxGetApp().plater()->canvas3D()->render();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -92,7 +92,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
|
|||
else if (option_name == "Size") {
|
||||
line.near_label_widget = [this](wxWindow* parent) {
|
||||
return new wxStaticBitmap(parent, wxID_ANY, wxNullBitmap, wxDefaultPosition,
|
||||
create_scaled_bitmap("one_layer_lock_on.png").GetSize());
|
||||
create_scaled_bitmap(m_parent, "one_layer_lock_on.png").GetSize());
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -77,7 +77,7 @@ void ObjectSettings::update_settings_list()
|
|||
{
|
||||
auto opt_key = (line.get_options())[0].opt_id; //we assume that we have one option per line
|
||||
|
||||
auto btn = new wxBitmapButton(parent, wxID_ANY, create_scaled_bitmap("colorchange_delete_on.png"),
|
||||
auto btn = new wxBitmapButton(parent, wxID_ANY, create_scaled_bitmap(m_parent, "cross"/*"colorchange_delete_on.png"*/),
|
||||
wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
|
||||
#ifdef __WXMSW__
|
||||
btn->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
|
||||
|
|
|
@ -96,11 +96,16 @@ void GLGizmoSlaSupports::on_render(const Selection& selection) const
|
|||
|
||||
void GLGizmoSlaSupports::render_selection_rectangle() const
|
||||
{
|
||||
if (!m_selection_rectangle_active)
|
||||
if (m_selection_rectangle_status == srOff)
|
||||
return;
|
||||
|
||||
glsafe(::glLineWidth(1.5f));
|
||||
float render_color[3] = {1.f, 0.f, 0.f};
|
||||
float render_color[3] = {0.f, 1.f, 0.f};
|
||||
if (m_selection_rectangle_status == srDeselect) {
|
||||
render_color[0] = 1.f;
|
||||
render_color[1] = 0.3f;
|
||||
render_color[2] = 0.3f;
|
||||
}
|
||||
glsafe(::glColor3fv(render_color));
|
||||
|
||||
glsafe(::glPushAttrib(GL_TRANSFORM_BIT)); // remember current MatrixMode
|
||||
|
@ -316,31 +321,35 @@ std::pair<Vec3f, Vec3f> GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse
|
|||
// The gizmo has an opportunity to react - if it does, it should return true so that the Canvas3D is
|
||||
// aware that the event was reacted to and stops trying to make different sense of it. If the gizmo
|
||||
// concludes that the event was not intended for it, it should return false.
|
||||
bool GLGizmoSlaSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down)
|
||||
bool GLGizmoSlaSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down)
|
||||
{
|
||||
if (m_editing_mode) {
|
||||
|
||||
// left down - show the selection rectangle:
|
||||
if (action == SLAGizmoEventType::LeftDown && shift_down) {
|
||||
// left down with shift - show the selection rectangle:
|
||||
if (action == SLAGizmoEventType::LeftDown && (shift_down || alt_down || control_down)) {
|
||||
if (m_hover_id == -1) {
|
||||
m_selection_rectangle_active = true;
|
||||
m_selection_rectangle_start_corner = mouse_position;
|
||||
m_selection_rectangle_end_corner = mouse_position;
|
||||
m_canvas_width = m_parent.get_canvas_size().get_width();
|
||||
m_canvas_height = m_parent.get_canvas_size().get_height();
|
||||
if (shift_down || alt_down) {
|
||||
m_selection_rectangle_status = shift_down ? srSelect : srDeselect;
|
||||
m_selection_rectangle_start_corner = mouse_position;
|
||||
m_selection_rectangle_end_corner = mouse_position;
|
||||
m_canvas_width = m_parent.get_canvas_size().get_width();
|
||||
m_canvas_height = m_parent.get_canvas_size().get_height();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (m_editing_mode_cache[m_hover_id].selected)
|
||||
unselect_point(m_hover_id);
|
||||
else
|
||||
select_point(m_hover_id);
|
||||
else {
|
||||
if (!alt_down)
|
||||
select_point(m_hover_id);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// left down without selection rectangle - place point on the mesh:
|
||||
if (action == SLAGizmoEventType::LeftDown && !m_selection_rectangle_active && !shift_down) {
|
||||
if (action == SLAGizmoEventType::LeftDown && m_selection_rectangle_status == srOff && !shift_down) {
|
||||
// If any point is in hover state, this should initiate its move - return control back to GLCanvas:
|
||||
if (m_hover_id != -1)
|
||||
return false;
|
||||
|
@ -365,7 +374,7 @@ bool GLGizmoSlaSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
|||
}
|
||||
|
||||
// left up with selection rectangle - select points inside the rectangle:
|
||||
if ((action == SLAGizmoEventType::LeftUp || action == SLAGizmoEventType::ShiftUp) && m_selection_rectangle_active) {
|
||||
if ((action == SLAGizmoEventType::LeftUp || action == SLAGizmoEventType::ShiftUp || action == SLAGizmoEventType::AltUp) && m_selection_rectangle_status != srOff) {
|
||||
const Transform3d& instance_matrix = m_model_object->instances[m_active_instance]->get_transformation().get_matrix();
|
||||
const Camera& camera = m_parent.get_camera();
|
||||
const std::array<int, 4>& viewport = camera.get_viewport();
|
||||
|
@ -405,11 +414,15 @@ bool GLGizmoSlaSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
|||
if (hits.size() > 1 || hits.front().t > 0.001f)
|
||||
is_obscured = true;
|
||||
|
||||
if (!is_obscured)
|
||||
select_point(i);
|
||||
if (!is_obscured) {
|
||||
if (m_selection_rectangle_status == srDeselect)
|
||||
unselect_point(i);
|
||||
else
|
||||
select_point(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
m_selection_rectangle_active = false;
|
||||
m_selection_rectangle_status = srOff;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -427,8 +440,9 @@ bool GLGizmoSlaSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
|||
return true; // point has been placed and the button not released yet
|
||||
// this prevents GLCanvas from starting scene rotation
|
||||
|
||||
if (m_selection_rectangle_active) {
|
||||
if (m_selection_rectangle_status != srOff) {
|
||||
m_selection_rectangle_end_corner = mouse_position;
|
||||
m_selection_rectangle_status = shift_down ? srSelect : srDeselect;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ public:
|
|||
#endif // ENABLE_SVG_ICONS
|
||||
virtual ~GLGizmoSlaSupports();
|
||||
void set_sla_support_data(ModelObject* model_object, const Selection& selection);
|
||||
bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down);
|
||||
bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down);
|
||||
void delete_selected_points(bool force = false);
|
||||
std::pair<float, float> get_sla_clipping_plane() const;
|
||||
|
||||
|
@ -75,7 +75,12 @@ private:
|
|||
mutable std::vector<CacheEntry> m_editing_mode_cache; // a support point and whether it is currently selected
|
||||
float m_clipping_plane_distance = 0.f;
|
||||
|
||||
bool m_selection_rectangle_active = false;
|
||||
enum SelectionRectangleStatus {
|
||||
srOff = 0,
|
||||
srSelect = 1,
|
||||
srDeselect = 2
|
||||
}m_selection_rectangle_status = srOff;
|
||||
|
||||
Vec2d m_selection_rectangle_start_corner;
|
||||
Vec2d m_selection_rectangle_end_corner;
|
||||
bool m_wait_for_up_event = false;
|
||||
|
|
|
@ -10,6 +10,7 @@ enum class SLAGizmoEventType {
|
|||
Delete,
|
||||
SelectAll,
|
||||
ShiftUp,
|
||||
AltUp,
|
||||
ApplyChanges,
|
||||
DiscardChanges,
|
||||
AutomaticGeneration,
|
||||
|
|
|
@ -455,14 +455,14 @@ void GLGizmosManager::set_sla_support_data(ModelObject* model_object, const Sele
|
|||
}
|
||||
|
||||
// Returns true if the gizmo used the event to do something, false otherwise.
|
||||
bool GLGizmosManager::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down)
|
||||
bool GLGizmosManager::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down)
|
||||
{
|
||||
if (!m_enabled)
|
||||
return false;
|
||||
|
||||
GizmosMap::const_iterator it = m_gizmos.find(SlaSupports);
|
||||
if (it != m_gizmos.end())
|
||||
return reinterpret_cast<GLGizmoSlaSupports*>(it->second)->gizmo_event(action, mouse_position, shift_down);
|
||||
return reinterpret_cast<GLGizmoSlaSupports*>(it->second)->gizmo_event(action, mouse_position, shift_down, alt_down, control_down);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -546,7 +546,7 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt, GLCanvas3D& canvas)
|
|||
|
||||
if (evt.LeftDown())
|
||||
{
|
||||
if ((m_current == SlaSupports) && gizmo_event(SLAGizmoEventType::LeftDown, mouse_pos, evt.ShiftDown()))
|
||||
if ((m_current == SlaSupports) && gizmo_event(SLAGizmoEventType::LeftDown, mouse_pos, evt.ShiftDown(), evt.AltDown(), evt.ControlDown()))
|
||||
// the gizmo got the event and took some action, there is no need to do anything more
|
||||
processed = true;
|
||||
else if (!selection.is_empty() && grabber_contains_mouse())
|
||||
|
@ -573,7 +573,7 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt, GLCanvas3D& canvas)
|
|||
else if (evt.Dragging() && (canvas.get_move_volume_id() != -1) && (m_current == SlaSupports))
|
||||
// don't allow dragging objects with the Sla gizmo on
|
||||
processed = true;
|
||||
else if (evt.Dragging() && (m_current == SlaSupports) && gizmo_event(SLAGizmoEventType::Dragging, mouse_pos, evt.ShiftDown()))
|
||||
else if (evt.Dragging() && (m_current == SlaSupports) && gizmo_event(SLAGizmoEventType::Dragging, mouse_pos, evt.ShiftDown(), evt.AltDown(), evt.ControlDown()))
|
||||
{
|
||||
// the gizmo got the event and took some action, no need to do anything more here
|
||||
canvas.set_as_dirty();
|
||||
|
@ -660,7 +660,7 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt, GLCanvas3D& canvas)
|
|||
{
|
||||
// in case SLA gizmo is selected, we just pass the LeftUp event and stop processing - neither
|
||||
// object moving or selecting is suppressed in that case
|
||||
gizmo_event(SLAGizmoEventType::LeftUp, mouse_pos, evt.ShiftDown());
|
||||
gizmo_event(SLAGizmoEventType::LeftUp, mouse_pos, evt.ShiftDown(), evt.AltDown(), evt.ControlDown());
|
||||
processed = true;
|
||||
}
|
||||
else if (evt.LeftUp() && (m_current == Flatten) && ((canvas.get_hover_volume_id() != -1) || grabber_contains_mouse()))
|
||||
|
@ -801,6 +801,10 @@ bool GLGizmosManager::on_key(wxKeyEvent& evt, GLCanvas3D& canvas)
|
|||
if ((m_current == SlaSupports) && (keyCode == WXK_SHIFT) && gizmo_event(SLAGizmoEventType::ShiftUp))
|
||||
// shift has been just released - SLA gizmo might want to close rectangular selection.
|
||||
processed = true;
|
||||
|
||||
if ((m_current == SlaSupports) && (keyCode == WXK_ALT) && gizmo_event(SLAGizmoEventType::AltUp))
|
||||
// alt has been just released - SLA gizmo might want to close rectangular selection.
|
||||
processed = true;
|
||||
}
|
||||
|
||||
if (processed)
|
||||
|
|
|
@ -145,7 +145,8 @@ public:
|
|||
void set_flattening_data(const ModelObject* model_object);
|
||||
|
||||
void set_sla_support_data(ModelObject* model_object, const Selection& selection);
|
||||
bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position = Vec2d::Zero(), bool shift_down = false);
|
||||
bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position = Vec2d::Zero(), bool shift_down = false, bool alt_down = false, bool control_down = false);
|
||||
|
||||
|
||||
void render_current_gizmo(const Selection& selection) const;
|
||||
void render_current_gizmo_for_picking_pass(const Selection& selection) const;
|
||||
|
|
|
@ -17,7 +17,7 @@ KBShortcutsDialog::KBShortcutsDialog()
|
|||
auto main_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
// logo
|
||||
const wxBitmap logo_bmp = create_scaled_bitmap("Slic3r_32px.png", 32);
|
||||
const wxBitmap logo_bmp = create_scaled_bitmap(this, "Slic3r_32px.png", 32);
|
||||
|
||||
// fonts
|
||||
wxFont head_font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT).Bold();
|
||||
|
@ -119,7 +119,7 @@ void KBShortcutsDialog::fill_shortcuts()
|
|||
main_shortcuts.push_back(Shortcut("+" ,L("Add Instance to selected object ")));
|
||||
main_shortcuts.push_back(Shortcut("-" ,L("Remove Instance from selected object")));
|
||||
main_shortcuts.push_back(Shortcut("?" ,L("Show keyboard shortcuts list")));
|
||||
main_shortcuts.push_back(Shortcut("Shift+LeftMouse", L("Select multiple object/Move multiple object")));
|
||||
main_shortcuts.push_back(Shortcut(ctrl+"LeftMouse" ,L("Select multiple object/Move multiple object")));
|
||||
|
||||
m_full_shortcuts.push_back(std::make_pair( _(L("Main Shortcuts")), std::make_pair(main_shortcuts, 0) ));
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ DPIFrame(NULL, wxID_ANY, SLIC3R_BUILD, wxDefaultPosition, wxDefaultSize, wxDEFAU
|
|||
/* Load default preset bitmaps before a tabpanel initialization,
|
||||
* but after filling of an em_unit value
|
||||
*/
|
||||
wxGetApp().preset_bundle->load_default_preset_bitmaps();
|
||||
wxGetApp().preset_bundle->load_default_preset_bitmaps(this);
|
||||
|
||||
// initialize tabpanel and menubar
|
||||
init_tabpanel();
|
||||
|
@ -327,9 +327,9 @@ void MainFrame::init_menubar()
|
|||
wxMenuItem* item_open = append_menu_item(fileMenu, wxID_ANY, _(L("&Open Project")) + dots + "\tCtrl+O", _(L("Open a project file")),
|
||||
[this](wxCommandEvent&) { if (m_plater) m_plater->load_project(); }, "brick_add.png");
|
||||
wxMenuItem* item_save = append_menu_item(fileMenu, wxID_ANY, _(L("&Save Project")) + "\tCtrl+S", _(L("Save current project file")),
|
||||
[this](wxCommandEvent&) { if (m_plater) m_plater->export_3mf(into_path(m_plater->get_project_filename())); }, "disk.png");
|
||||
[this](wxCommandEvent&) { if (m_plater) m_plater->export_3mf(into_path(m_plater->get_project_filename())); }, "save");
|
||||
wxMenuItem* item_save_as = append_menu_item(fileMenu, wxID_ANY, _(L("Save Project &as")) + dots + "\tCtrl+Alt+S", _(L("Save current project file as")),
|
||||
[this](wxCommandEvent&) { if (m_plater) m_plater->export_3mf(); }, "disk.png");
|
||||
[this](wxCommandEvent&) { if (m_plater) m_plater->export_3mf(); }, "save");
|
||||
|
||||
fileMenu->AppendSeparator();
|
||||
|
||||
|
|
|
@ -23,15 +23,11 @@ namespace Slic3r {
|
|||
namespace GUI {
|
||||
|
||||
|
||||
MsgDialog::MsgDialog(wxWindow *parent, const wxString &title, const wxString &headline, wxWindowID button_id) :
|
||||
MsgDialog(parent, title, headline, create_scaled_bitmap("Slic3r_192px.png", 192), button_id)
|
||||
{}
|
||||
|
||||
MsgDialog::MsgDialog(wxWindow *parent, const wxString &title, const wxString &headline, wxBitmap bitmap, wxWindowID button_id) :
|
||||
wxDialog(parent, wxID_ANY, title, wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER),
|
||||
boldfont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT)),
|
||||
content_sizer(new wxBoxSizer(wxVERTICAL)),
|
||||
btn_sizer(new wxBoxSizer(wxHORIZONTAL))
|
||||
MsgDialog::MsgDialog(wxWindow *parent, const wxString &title, const wxString &headline, wxWindowID button_id, wxBitmap bitmap)
|
||||
: wxDialog(parent, wxID_ANY, title, wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
|
||||
, boldfont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT))
|
||||
, content_sizer(new wxBoxSizer(wxVERTICAL))
|
||||
, btn_sizer(new wxBoxSizer(wxHORIZONTAL))
|
||||
{
|
||||
boldfont.SetWeight(wxFONTWEIGHT_BOLD);
|
||||
|
||||
|
@ -54,7 +50,11 @@ wxDialog(parent, wxID_ANY, title, wxDefaultPosition, wxDefaultSize, wxDEFAULT_DI
|
|||
|
||||
rightsizer->Add(btn_sizer, 0, wxALIGN_RIGHT);
|
||||
|
||||
auto *logo = new wxStaticBitmap(this, wxID_ANY, std::move(bitmap));
|
||||
if (! bitmap.IsOk()) {
|
||||
bitmap = create_scaled_bitmap(this, "Slic3r_192px.png", 192);
|
||||
}
|
||||
|
||||
logo = new wxStaticBitmap(this, wxID_ANY, wxNullBitmap);
|
||||
|
||||
topsizer->Add(logo, 0, wxALL, BORDER);
|
||||
topsizer->Add(rightsizer, 1, wxALL | wxEXPAND, BORDER);
|
||||
|
@ -69,7 +69,6 @@ MsgDialog::~MsgDialog() {}
|
|||
|
||||
ErrorDialog::ErrorDialog(wxWindow *parent, const wxString &msg)
|
||||
: MsgDialog(parent, _(L("Slic3r error")), _(L("Slic3r has encountered an error")),
|
||||
create_scaled_bitmap("Slic3r_192px_grayscale.png"),
|
||||
wxID_NONE)
|
||||
, msg(msg)
|
||||
{
|
||||
|
@ -97,6 +96,8 @@ ErrorDialog::ErrorDialog(wxWindow *parent, const wxString &msg)
|
|||
btn_ok->SetFocus();
|
||||
btn_sizer->Add(btn_ok, 0, wxRIGHT, HORIZ_SPACING);
|
||||
|
||||
logo->SetBitmap(create_scaled_bitmap(this, "Slic3r_192px_grayscale.png", 192));
|
||||
|
||||
SetMaxSize(wxSize(-1, CONTENT_MAX_HEIGHT*wxGetApp().em_unit()));
|
||||
Fit();
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
class wxBoxSizer;
|
||||
class wxCheckBox;
|
||||
class wxStaticBitmap;
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
|
@ -40,12 +41,12 @@ protected:
|
|||
};
|
||||
|
||||
// button_id is an id of a button that can be added by default, use wxID_NONE to disable
|
||||
MsgDialog(wxWindow *parent, const wxString &title, const wxString &headline, wxWindowID button_id = wxID_OK);
|
||||
MsgDialog(wxWindow *parent, const wxString &title, const wxString &headline, wxBitmap bitmap, wxWindowID button_id = wxID_OK);
|
||||
MsgDialog(wxWindow *parent, const wxString &title, const wxString &headline, wxWindowID button_id = wxID_OK, wxBitmap bitmap = wxNullBitmap);
|
||||
|
||||
wxFont boldfont;
|
||||
wxBoxSizer *content_sizer;
|
||||
wxBoxSizer *btn_sizer;
|
||||
wxStaticBitmap *logo;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -286,7 +286,7 @@ wxBitmapComboBox(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(15 *
|
|||
#ifdef __WINDOWS__
|
||||
edit_btn->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
|
||||
#endif
|
||||
edit_btn->SetBitmap(create_scaled_bitmap("cog"));
|
||||
edit_btn->SetBitmap(create_scaled_bitmap(this, "cog"));
|
||||
edit_btn->SetToolTip(_(L("Click to edit preset")));
|
||||
|
||||
edit_btn->Bind(wxEVT_BUTTON, ([preset_type, this](wxCommandEvent)
|
||||
|
@ -747,6 +747,7 @@ Sidebar::Sidebar(Plater *parent)
|
|||
p->plater->export_gcode();
|
||||
else
|
||||
p->plater->reslice();
|
||||
p->plater->select_view_3D("Preview");
|
||||
});
|
||||
p->btn_send_gcode->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { p->plater->send_gcode(); });
|
||||
}
|
||||
|
@ -2314,20 +2315,14 @@ unsigned int Plater::priv::update_background_process(bool force_validation)
|
|||
this->sidebar->show_sliced_info_sizer(false);
|
||||
// Reset preview canvases. If the print has been invalidated, the preview canvases will be cleared.
|
||||
// Otherwise they will be just refreshed.
|
||||
switch (this->printer_technology) {
|
||||
case ptFFF:
|
||||
if (this->preview != nullptr)
|
||||
// If the preview is not visible, the following line just invalidates the preview,
|
||||
// but the G-code paths are calculated first once the preview is made visible.
|
||||
this->preview->reload_print();
|
||||
// We also need to reload 3D scene because of the wipe tower preview box
|
||||
if (this->config->opt_bool("wipe_tower"))
|
||||
return_state |= UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE;
|
||||
break;
|
||||
case ptSLA:
|
||||
return_state |= UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE;
|
||||
break;
|
||||
}
|
||||
if (this->preview != nullptr)
|
||||
// If the preview is not visible, the following line just invalidates the preview,
|
||||
// but the G-code paths or SLA preview are calculated first once the preview is made visible.
|
||||
this->preview->reload_print();
|
||||
// In FDM mode, we need to reload the 3D scene because of the wipe tower preview box.
|
||||
// In SLA mode, we need to reload the 3D scene every time to show the support structures.
|
||||
if (this->printer_technology == ptSLA || (this->printer_technology == ptFFF && this->config->opt_bool("wipe_tower")))
|
||||
return_state |= UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE;
|
||||
}
|
||||
|
||||
if ((invalidated != Print::APPLY_STATUS_UNCHANGED || force_validation) && ! this->background_process.empty()) {
|
||||
|
|
|
@ -486,7 +486,7 @@ const std::vector<std::string>& Preset::sla_material_options()
|
|||
s_opts = {
|
||||
"initial_layer_height",
|
||||
"exposure_time", "initial_exposure_time",
|
||||
"material_correction_printing", "material_correction_curing",
|
||||
"material_correction",
|
||||
"material_notes",
|
||||
"default_sla_material_profile",
|
||||
"compatible_prints", "compatible_prints_condition",
|
||||
|
@ -506,7 +506,9 @@ const std::vector<std::string>& Preset::sla_printer_options()
|
|||
"display_width", "display_height", "display_pixels_x", "display_pixels_y",
|
||||
"display_orientation",
|
||||
"fast_tilt_time", "slow_tilt_time", "area_fill",
|
||||
"printer_correction",
|
||||
"relative_correction",
|
||||
"absolute_correction",
|
||||
"gamma_correction",
|
||||
"print_host", "printhost_apikey", "printhost_cafile",
|
||||
"printer_notes",
|
||||
"inherits"
|
||||
|
@ -797,16 +799,14 @@ bool PresetCollection::delete_current_preset()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool PresetCollection::load_bitmap_default(const std::string &file_name)
|
||||
void PresetCollection::load_bitmap_default(wxWindow *window, const std::string &file_name)
|
||||
{
|
||||
// return m_bitmap_main_frame->LoadFile(wxString::FromUTF8(Slic3r::var(file_name).c_str()), wxBITMAP_TYPE_PNG);
|
||||
return load_scaled_bitmap(&m_bitmap_main_frame, file_name);
|
||||
*m_bitmap_main_frame = create_scaled_bitmap(window, file_name);
|
||||
}
|
||||
|
||||
bool PresetCollection::load_bitmap_add(const std::string &file_name)
|
||||
void PresetCollection::load_bitmap_add(wxWindow *window, const std::string &file_name)
|
||||
{
|
||||
// return m_bitmap_add->LoadFile(wxString::FromUTF8(Slic3r::var(file_name).c_str()), wxBITMAP_TYPE_PNG);
|
||||
return load_scaled_bitmap(&m_bitmap_add, file_name);
|
||||
*m_bitmap_add = create_scaled_bitmap(window, file_name);
|
||||
}
|
||||
|
||||
const Preset* PresetCollection::get_selected_preset_parent() const
|
||||
|
|
|
@ -15,6 +15,7 @@ class wxBitmapComboBox;
|
|||
class wxChoice;
|
||||
class wxItemContainer;
|
||||
class wxString;
|
||||
class wxWindow;
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
|
@ -276,10 +277,10 @@ public:
|
|||
bool delete_current_preset();
|
||||
|
||||
// Load default bitmap to be placed at the wxBitmapComboBox of a MainFrame.
|
||||
bool load_bitmap_default(const std::string &file_name);
|
||||
void load_bitmap_default(wxWindow *window, const std::string &file_name);
|
||||
|
||||
// Load "add new printer" bitmap to be placed at the wxBitmapComboBox of a MainFrame.
|
||||
bool load_bitmap_add(const std::string &file_name);
|
||||
void load_bitmap_add(wxWindow *window, const std::string &file_name);
|
||||
|
||||
// Compatible & incompatible marks, to be placed at the wxBitmapComboBox items.
|
||||
void set_bitmap_compatible (const wxBitmap *bmp) { m_bitmap_compatible = bmp; }
|
||||
|
|
|
@ -396,55 +396,36 @@ void PresetBundle::export_selections(AppConfig &config)
|
|||
config.set("presets", "printer", printers.get_selected_preset_name());
|
||||
}
|
||||
|
||||
bool PresetBundle::load_compatible_bitmaps()
|
||||
void PresetBundle::load_compatible_bitmaps(wxWindow *window)
|
||||
{
|
||||
const std::string path_bitmap_compatible = "flag-green-icon.png";
|
||||
const std::string path_bitmap_incompatible = "flag-red-icon.png";
|
||||
const std::string path_bitmap_lock = "sys_lock.png";//"lock.png";
|
||||
const std::string path_bitmap_lock_open = "sys_unlock.png";//"lock_open.png";
|
||||
// bool loaded_compatible = m_bitmapCompatible ->LoadFile(
|
||||
// wxString::FromUTF8(Slic3r::var(path_bitmap_compatible).c_str()), wxBITMAP_TYPE_PNG);
|
||||
// bool loaded_incompatible = m_bitmapIncompatible->LoadFile(
|
||||
// wxString::FromUTF8(Slic3r::var(path_bitmap_incompatible).c_str()), wxBITMAP_TYPE_PNG);
|
||||
// bool loaded_lock = m_bitmapLock->LoadFile(
|
||||
// wxString::FromUTF8(Slic3r::var(path_bitmap_lock).c_str()), wxBITMAP_TYPE_PNG);
|
||||
// bool loaded_lock_open = m_bitmapLockOpen->LoadFile(
|
||||
// wxString::FromUTF8(Slic3r::var(path_bitmap_lock_open).c_str()), wxBITMAP_TYPE_PNG);
|
||||
*m_bitmapCompatible = create_scaled_bitmap(window, "flag_green");
|
||||
*m_bitmapIncompatible = create_scaled_bitmap(window, "flag_red");
|
||||
*m_bitmapLock = create_scaled_bitmap(window, "lock_closed");
|
||||
*m_bitmapLockOpen = create_scaled_bitmap(window, "sys_unlock.png");
|
||||
|
||||
bool loaded_compatible = load_scaled_bitmap(&m_bitmapCompatible, path_bitmap_compatible);
|
||||
bool loaded_incompatible = load_scaled_bitmap(&m_bitmapIncompatible,path_bitmap_incompatible);
|
||||
bool loaded_lock = load_scaled_bitmap(&m_bitmapLock, path_bitmap_lock);
|
||||
bool loaded_lock_open = load_scaled_bitmap(&m_bitmapLockOpen, path_bitmap_lock_open);
|
||||
prints .set_bitmap_compatible(m_bitmapCompatible);
|
||||
filaments .set_bitmap_compatible(m_bitmapCompatible);
|
||||
sla_prints .set_bitmap_compatible(m_bitmapCompatible);
|
||||
sla_materials.set_bitmap_compatible(m_bitmapCompatible);
|
||||
printers .set_bitmap_compatible(m_bitmapCompatible);
|
||||
|
||||
if (loaded_compatible) {
|
||||
prints .set_bitmap_compatible(m_bitmapCompatible);
|
||||
filaments .set_bitmap_compatible(m_bitmapCompatible);
|
||||
sla_prints .set_bitmap_compatible(m_bitmapCompatible);
|
||||
sla_materials.set_bitmap_compatible(m_bitmapCompatible);
|
||||
// printers .set_bitmap_compatible(m_bitmapCompatible);
|
||||
}
|
||||
if (loaded_incompatible) {
|
||||
prints .set_bitmap_incompatible(m_bitmapIncompatible);
|
||||
filaments .set_bitmap_incompatible(m_bitmapIncompatible);
|
||||
sla_prints .set_bitmap_incompatible(m_bitmapIncompatible);
|
||||
sla_materials.set_bitmap_incompatible(m_bitmapIncompatible);
|
||||
// printers .set_bitmap_incompatible(m_bitmapIncompatible);
|
||||
}
|
||||
if (loaded_lock) {
|
||||
prints .set_bitmap_lock(m_bitmapLock);
|
||||
filaments .set_bitmap_lock(m_bitmapLock);
|
||||
sla_prints .set_bitmap_lock(m_bitmapLock);
|
||||
sla_materials.set_bitmap_lock(m_bitmapLock);
|
||||
printers .set_bitmap_lock(m_bitmapLock);
|
||||
}
|
||||
if (loaded_lock_open) {
|
||||
prints .set_bitmap_lock_open(m_bitmapLock);
|
||||
filaments .set_bitmap_lock_open(m_bitmapLock);
|
||||
sla_prints .set_bitmap_lock_open(m_bitmapLock);
|
||||
sla_materials.set_bitmap_lock_open(m_bitmapLock);
|
||||
printers .set_bitmap_lock_open(m_bitmapLock);
|
||||
}
|
||||
return loaded_compatible && loaded_incompatible && loaded_lock && loaded_lock_open;
|
||||
prints .set_bitmap_incompatible(m_bitmapIncompatible);
|
||||
filaments .set_bitmap_incompatible(m_bitmapIncompatible);
|
||||
sla_prints .set_bitmap_incompatible(m_bitmapIncompatible);
|
||||
sla_materials.set_bitmap_incompatible(m_bitmapIncompatible);
|
||||
printers .set_bitmap_incompatible(m_bitmapIncompatible);
|
||||
|
||||
prints .set_bitmap_lock(m_bitmapLock);
|
||||
filaments .set_bitmap_lock(m_bitmapLock);
|
||||
sla_prints .set_bitmap_lock(m_bitmapLock);
|
||||
sla_materials.set_bitmap_lock(m_bitmapLock);
|
||||
printers .set_bitmap_lock(m_bitmapLock);
|
||||
|
||||
prints .set_bitmap_lock_open(m_bitmapLock);
|
||||
filaments .set_bitmap_lock_open(m_bitmapLock);
|
||||
sla_prints .set_bitmap_lock_open(m_bitmapLock);
|
||||
sla_materials.set_bitmap_lock_open(m_bitmapLock);
|
||||
printers .set_bitmap_lock_open(m_bitmapLock);
|
||||
}
|
||||
|
||||
DynamicPrintConfig PresetBundle::full_config() const
|
||||
|
@ -1446,7 +1427,7 @@ bool PresetBundle::parse_color(const std::string &scolor, unsigned char *rgb_out
|
|||
return true;
|
||||
}
|
||||
|
||||
void PresetBundle::load_default_preset_bitmaps()
|
||||
void PresetBundle::load_default_preset_bitmaps(wxWindow *window)
|
||||
{
|
||||
// Clear bitmap cache, before load new scaled default preset bitmaps
|
||||
m_bitmapCache->clear();
|
||||
|
@ -1456,13 +1437,13 @@ void PresetBundle::load_default_preset_bitmaps()
|
|||
this->sla_materials.clear_bitmap_cache();
|
||||
this->printers.clear_bitmap_cache();
|
||||
|
||||
this->prints.load_bitmap_default("cog");
|
||||
this->sla_prints.load_bitmap_default("cog");
|
||||
this->filaments.load_bitmap_default("spool.png");
|
||||
this->sla_materials.load_bitmap_default("package_green.png");
|
||||
this->printers.load_bitmap_default("printer");
|
||||
this->printers.load_bitmap_add("add.png");
|
||||
this->load_compatible_bitmaps();
|
||||
this->prints.load_bitmap_default(window, "cog");
|
||||
this->sla_prints.load_bitmap_default(window, "cog");
|
||||
this->filaments.load_bitmap_default(window, "spool.png");
|
||||
this->sla_materials.load_bitmap_default(window, "resin");
|
||||
this->printers.load_bitmap_default(window, "printer");
|
||||
this->printers.load_bitmap_add(window, "add.png");
|
||||
this->load_compatible_bitmaps(window);
|
||||
}
|
||||
|
||||
void PresetBundle::update_platter_filament_ui(unsigned int idx_extruder, GUI::PresetComboBox *ui)
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
#include <set>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
|
||||
class wxWindow;
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
namespace GUI {
|
||||
|
@ -127,7 +129,7 @@ public:
|
|||
|
||||
static bool parse_color(const std::string &scolor, unsigned char *rgb_out);
|
||||
|
||||
void load_default_preset_bitmaps();
|
||||
void load_default_preset_bitmaps(wxWindow *window);
|
||||
|
||||
private:
|
||||
std::string load_system_presets();
|
||||
|
@ -148,7 +150,7 @@ private:
|
|||
// If it is not an external config, then the config will be stored into the user profile directory.
|
||||
void load_config_file_config(const std::string &name_or_path, bool is_external, DynamicPrintConfig &&config);
|
||||
void load_config_file_config_bundle(const std::string &path, const boost::property_tree::ptree &tree);
|
||||
bool load_compatible_bitmaps();
|
||||
void load_compatible_bitmaps(wxWindow *window);
|
||||
|
||||
DynamicPrintConfig full_fff_config() const;
|
||||
DynamicPrintConfig full_sla_config() const;
|
||||
|
|
|
@ -109,19 +109,20 @@ void Selection::add(unsigned int volume_idx, bool as_single_selection)
|
|||
if (is_wipe_tower() && volume->is_wipe_tower)
|
||||
return;
|
||||
|
||||
bool keep_instance_mode = (m_mode == Instance) && !as_single_selection && (is_single_full_instance() || is_multiple_full_instance());
|
||||
bool keep_instance_mode = (m_mode == Instance) && !as_single_selection;
|
||||
bool already_contained = contains_volume(volume_idx);
|
||||
|
||||
// resets the current list if needed
|
||||
bool needs_reset = as_single_selection;
|
||||
bool needs_reset = as_single_selection && !already_contained;
|
||||
needs_reset |= volume->is_wipe_tower;
|
||||
needs_reset |= is_wipe_tower() && !volume->is_wipe_tower;
|
||||
needs_reset |= !keep_instance_mode && !is_modifier() && volume->is_modifier;
|
||||
needs_reset |= is_modifier() && !volume->is_modifier;
|
||||
needs_reset |= as_single_selection && !is_any_modifier() && volume->is_modifier;
|
||||
needs_reset |= is_any_modifier() && !volume->is_modifier;
|
||||
|
||||
if (needs_reset)
|
||||
clear();
|
||||
|
||||
if (!contains_volume(volume_idx))
|
||||
if (!already_contained || needs_reset)
|
||||
{
|
||||
if (!keep_instance_mode)
|
||||
m_mode = volume->is_modifier ? Volume : Instance;
|
||||
|
@ -482,30 +483,6 @@ void Selection::translate(const Vec3d& displacement, bool local)
|
|||
m_bounding_box_dirty = true;
|
||||
}
|
||||
|
||||
static Eigen::Quaterniond rotation_xyz_diff(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to)
|
||||
{
|
||||
return
|
||||
// From the current coordinate system to world.
|
||||
Eigen::AngleAxisd(rot_xyz_to(2), Vec3d::UnitZ()) * Eigen::AngleAxisd(rot_xyz_to(1), Vec3d::UnitY()) * Eigen::AngleAxisd(rot_xyz_to(0), Vec3d::UnitX()) *
|
||||
// From world to the initial coordinate system.
|
||||
Eigen::AngleAxisd(-rot_xyz_from(0), Vec3d::UnitX()) * Eigen::AngleAxisd(-rot_xyz_from(1), Vec3d::UnitY()) * Eigen::AngleAxisd(-rot_xyz_from(2), Vec3d::UnitZ());
|
||||
}
|
||||
|
||||
// This should only be called if it is known, that the two rotations only differ in rotation around the Z axis.
|
||||
static double rotation_diff_z(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to)
|
||||
{
|
||||
Eigen::AngleAxisd angle_axis(rotation_xyz_diff(rot_xyz_from, rot_xyz_to));
|
||||
Vec3d axis = angle_axis.axis();
|
||||
double angle = angle_axis.angle();
|
||||
#ifndef NDEBUG
|
||||
if (std::abs(angle) > 1e-8) {
|
||||
assert(std::abs(axis.x()) < 1e-8);
|
||||
assert(std::abs(axis.y()) < 1e-8);
|
||||
}
|
||||
#endif /* NDEBUG */
|
||||
return (axis.z() < 0) ? -angle : angle;
|
||||
}
|
||||
|
||||
// Rotate an object around one of the axes. Only one rotation component is expected to be changing.
|
||||
void Selection::rotate(const Vec3d& rotation, TransformationType transformation_type)
|
||||
{
|
||||
|
@ -548,7 +525,7 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_
|
|||
assert(is_approx(rotation.z(), 0.0));
|
||||
const GLVolume &first_volume = *(*m_volumes)[first_volume_idx];
|
||||
const Vec3d &rotation = first_volume.get_instance_rotation();
|
||||
double z_diff = rotation_diff_z(m_cache.volumes_data[first_volume_idx].get_instance_rotation(), m_cache.volumes_data[i].get_instance_rotation());
|
||||
double z_diff = Geometry::rotation_diff_z(m_cache.volumes_data[first_volume_idx].get_instance_rotation(), m_cache.volumes_data[i].get_instance_rotation());
|
||||
volume.set_instance_rotation(Vec3d(rotation(0), rotation(1), rotation(2) + z_diff));
|
||||
}
|
||||
else {
|
||||
|
@ -1538,7 +1515,7 @@ void Selection::render_sidebar_size_hint(Axis axis, double length) const
|
|||
#ifndef NDEBUG
|
||||
static bool is_rotation_xy_synchronized(const Vec3d &rot_xyz_from, const Vec3d &rot_xyz_to)
|
||||
{
|
||||
Eigen::AngleAxisd angle_axis(rotation_xyz_diff(rot_xyz_from, rot_xyz_to));
|
||||
Eigen::AngleAxisd angle_axis(Geometry::rotation_xyz_diff(rot_xyz_from, rot_xyz_to));
|
||||
Vec3d axis = angle_axis.axis();
|
||||
double angle = angle_axis.angle();
|
||||
if (std::abs(angle) < 1e-8)
|
||||
|
@ -1618,7 +1595,7 @@ void Selection::synchronize_unselected_instances(SyncRotationType sync_rotation_
|
|||
break;
|
||||
case SYNC_ROTATION_GENERAL:
|
||||
// generic rotation -> update instance z with the delta of the rotation.
|
||||
double z_diff = rotation_diff_z(m_cache.volumes_data[i].get_instance_rotation(), m_cache.volumes_data[j].get_instance_rotation());
|
||||
double z_diff = Geometry::rotation_diff_z(m_cache.volumes_data[i].get_instance_rotation(), m_cache.volumes_data[j].get_instance_rotation());
|
||||
v->set_instance_rotation(Vec3d(rotation(0), rotation(1), rotation(2) + z_diff));
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -213,7 +213,7 @@ public:
|
|||
|
||||
bool is_empty() const { return m_type == Empty; }
|
||||
bool is_wipe_tower() const { return m_type == WipeTower; }
|
||||
bool is_modifier() const { return (m_type == SingleModifier) || (m_type == MultipleModifier); }
|
||||
bool is_any_modifier() const { return is_single_modifier() || is_multiple_modifier(); }
|
||||
bool is_single_modifier() const { return m_type == SingleModifier; }
|
||||
bool is_multiple_modifier() const { return m_type == MultipleModifier; }
|
||||
bool is_single_full_instance() const;
|
||||
|
@ -222,6 +222,7 @@ public:
|
|||
bool is_multiple_full_object() const { return m_type == MultipleFullObject; }
|
||||
bool is_single_volume() const { return m_type == SingleVolume; }
|
||||
bool is_multiple_volume() const { return m_type == MultipleVolume; }
|
||||
bool is_any_volume() const { return is_single_volume() || is_multiple_volume(); }
|
||||
bool is_mixed() const { return m_type == Mixed; }
|
||||
bool is_from_single_instance() const { return get_instance_idx() != -1; }
|
||||
bool is_from_single_object() const;
|
||||
|
|
|
@ -52,7 +52,7 @@ SysInfoDialog::SysInfoDialog()
|
|||
main_sizer->Add(hsizer, 1, wxEXPAND | wxALL, 10);
|
||||
|
||||
// logo
|
||||
auto *logo = new wxStaticBitmap(this, wxID_ANY, create_scaled_bitmap("Slic3r_192px.png", 192));
|
||||
auto *logo = new wxStaticBitmap(this, wxID_ANY, create_scaled_bitmap(this, "Slic3r_192px.png", 192));
|
||||
hsizer->Add(logo, 0, wxALIGN_CENTER_VERTICAL);
|
||||
|
||||
wxBoxSizer* vsizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
|
|
@ -116,16 +116,16 @@ void Tab::create_preset_tab()
|
|||
|
||||
//buttons
|
||||
wxBitmap bmpMenu;
|
||||
bmpMenu = create_scaled_bitmap("disk.png");
|
||||
bmpMenu = create_scaled_bitmap(this, "save");
|
||||
m_btn_save_preset = new wxBitmapButton(panel, wxID_ANY, bmpMenu, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
|
||||
if (wxMSW) m_btn_save_preset->SetBackgroundColour(color);
|
||||
bmpMenu = create_scaled_bitmap("delete.png");
|
||||
bmpMenu = create_scaled_bitmap(this, "cross"/*"delete.png"*/);
|
||||
m_btn_delete_preset = new wxBitmapButton(panel, wxID_ANY, bmpMenu, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
|
||||
if (wxMSW) m_btn_delete_preset->SetBackgroundColour(color);
|
||||
|
||||
m_show_incompatible_presets = false;
|
||||
m_bmp_show_incompatible_presets = create_scaled_bitmap("flag-red-icon.png");
|
||||
m_bmp_hide_incompatible_presets = create_scaled_bitmap("flag-green-icon.png");
|
||||
m_bmp_show_incompatible_presets = create_scaled_bitmap(this, "flag_red");
|
||||
m_bmp_hide_incompatible_presets = create_scaled_bitmap(this, "flag_green");
|
||||
m_btn_hide_incompatible_presets = new wxBitmapButton(panel, wxID_ANY, m_bmp_hide_incompatible_presets, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
|
||||
if (wxMSW) m_btn_hide_incompatible_presets->SetBackgroundColour(color);
|
||||
|
||||
|
@ -148,13 +148,13 @@ void Tab::create_preset_tab()
|
|||
// Determine the theme color of OS (dark or light)
|
||||
auto luma = wxGetApp().get_colour_approx_luma(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
|
||||
// Bitmaps to be shown on the "Revert to system" aka "Lock to system" button next to each input field.
|
||||
m_bmp_value_lock = create_scaled_bitmap("sys_lock.png");
|
||||
m_bmp_value_unlock = create_scaled_bitmap(luma >= 128 ? "sys_unlock.png" : "sys_unlock_grey.png");
|
||||
m_bmp_value_lock = create_scaled_bitmap(this, luma >= 128 ? "lock_closed" : "lock_closed_white");
|
||||
m_bmp_value_unlock = create_scaled_bitmap(this, "lock_open");
|
||||
m_bmp_non_system = &m_bmp_white_bullet;
|
||||
// Bitmaps to be shown on the "Undo user changes" button next to each input field.
|
||||
m_bmp_value_revert = create_scaled_bitmap(luma >= 128 ? "action_undo.png" : "action_undo_grey.png");
|
||||
m_bmp_white_bullet = create_scaled_bitmap("bullet_white.png");
|
||||
m_bmp_question = create_scaled_bitmap("question_mark_01.png");
|
||||
m_bmp_value_revert = create_scaled_bitmap(this, "undo");
|
||||
m_bmp_white_bullet = create_scaled_bitmap(this, "bullet_white.png");
|
||||
m_bmp_question = create_scaled_bitmap(this, "question");
|
||||
|
||||
fill_icon_descriptions();
|
||||
set_tooltips_text();
|
||||
|
@ -283,7 +283,7 @@ Slic3r::GUI::PageShp Tab::add_options_page(const wxString& title, const std::str
|
|||
// Add a new icon to the icon list.
|
||||
// wxIcon img_icon(from_u8(Slic3r::var(icon)), wxBITMAP_TYPE_PNG);
|
||||
// m_icons->Add(img_icon);
|
||||
m_icons->Add(create_scaled_bitmap(icon));
|
||||
m_icons->Add(create_scaled_bitmap(this, icon));
|
||||
icon_idx = ++m_icon_count;
|
||||
m_icon_index[icon] = icon_idx;
|
||||
}
|
||||
|
@ -1642,7 +1642,7 @@ void TabPrinter::build_printhost(ConfigOptionsGroup *optgroup)
|
|||
auto btn = m_printhost_browse_btn = new wxButton(parent, wxID_ANY, _(L(" Browse ")) + dots,
|
||||
wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT);
|
||||
btn->SetFont(Slic3r::GUI::wxGetApp().normal_font());
|
||||
btn->SetBitmap(create_scaled_bitmap("zoom.png"));
|
||||
btn->SetBitmap(create_scaled_bitmap(this, "zoom.png"));
|
||||
auto sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
sizer->Add(btn);
|
||||
|
||||
|
@ -1661,7 +1661,7 @@ void TabPrinter::build_printhost(ConfigOptionsGroup *optgroup)
|
|||
auto btn = m_print_host_test_btn = new wxButton(parent, wxID_ANY, _(L("Test")),
|
||||
wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT);
|
||||
btn->SetFont(Slic3r::GUI::wxGetApp().normal_font());
|
||||
btn->SetBitmap(create_scaled_bitmap("wrench.png"));
|
||||
btn->SetBitmap(create_scaled_bitmap(this, "wrench.png"));
|
||||
auto sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
sizer->Add(btn);
|
||||
|
||||
|
@ -1698,7 +1698,7 @@ void TabPrinter::build_printhost(ConfigOptionsGroup *optgroup)
|
|||
auto printhost_cafile_browse = [this, optgroup] (wxWindow* parent) {
|
||||
auto btn = new wxButton(parent, wxID_ANY, _(L(" Browse "))+dots, wxDefaultPosition, wxDefaultSize, wxBU_LEFT);
|
||||
btn->SetFont(Slic3r::GUI::wxGetApp().normal_font());
|
||||
btn->SetBitmap(create_scaled_bitmap("zoom.png"));
|
||||
btn->SetBitmap(create_scaled_bitmap(this, "zoom.png"));
|
||||
auto sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
sizer->Add(btn);
|
||||
|
||||
|
@ -1776,7 +1776,7 @@ void TabPrinter::build_fff()
|
|||
line.widget = [this](wxWindow* parent) {
|
||||
auto btn = new wxButton(parent, wxID_ANY, _(L(" Set "))+dots, wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT);
|
||||
btn->SetFont(wxGetApp().small_font());
|
||||
btn->SetBitmap(create_scaled_bitmap("printer"));
|
||||
btn->SetBitmap(create_scaled_bitmap(this, "printer"));
|
||||
|
||||
auto sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
sizer->Add(btn);
|
||||
|
@ -1977,7 +1977,7 @@ void TabPrinter::build_sla()
|
|||
line.widget = [this](wxWindow* parent) {
|
||||
auto btn = new wxButton(parent, wxID_ANY, _(L(" Set ")) + dots, wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT);
|
||||
btn->SetFont(wxGetApp().small_font());
|
||||
btn->SetBitmap(create_scaled_bitmap("printer"));
|
||||
btn->SetBitmap(create_scaled_bitmap(this, "printer"));
|
||||
|
||||
auto sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
sizer->Add(btn);
|
||||
|
@ -2016,16 +2016,19 @@ void TabPrinter::build_sla()
|
|||
optgroup->append_single_option_line("area_fill");
|
||||
|
||||
optgroup = page->new_optgroup(_(L("Corrections")));
|
||||
line = Line{ m_config->def()->get("printer_correction")->full_label, "" };
|
||||
std::vector<std::string> axes{ "X", "Y", "Z" };
|
||||
line = Line{ m_config->def()->get("relative_correction")->full_label, "" };
|
||||
// std::vector<std::string> axes{ "X", "Y", "Z" };
|
||||
std::vector<std::string> axes{ "XY", "Z" };
|
||||
int id = 0;
|
||||
for (auto& axis : axes) {
|
||||
auto opt = optgroup->get_option("printer_correction", id);
|
||||
auto opt = optgroup->get_option("relative_correction", id);
|
||||
opt.opt.label = axis;
|
||||
line.append_option(opt);
|
||||
++id;
|
||||
}
|
||||
optgroup->append_line(line);
|
||||
optgroup->append_single_option_line("absolute_correction");
|
||||
optgroup->append_single_option_line("gamma_correction");
|
||||
|
||||
optgroup = page->new_optgroup(_(L("Print Host upload")));
|
||||
build_printhost(optgroup.get());
|
||||
|
@ -2919,7 +2922,7 @@ wxSizer* Tab::compatible_widget_create(wxWindow* parent, PresetDependencies &dep
|
|||
deps.btn = new wxButton(parent, wxID_ANY, _(L(" Set "))+dots, wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT);
|
||||
deps.btn->SetFont(Slic3r::GUI::wxGetApp().normal_font());
|
||||
|
||||
deps.btn->SetBitmap(create_scaled_bitmap("printer"));
|
||||
deps.btn->SetBitmap(create_scaled_bitmap(this, "printer"));
|
||||
|
||||
auto sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
sizer->Add((deps.checkbox), 0, wxALIGN_CENTER_VERTICAL);
|
||||
|
@ -3110,7 +3113,7 @@ ConfigOptionsGroupShp Page::new_optgroup(const wxString& title, int noncommon_la
|
|||
bmp_name = mode == comExpert ? "mode_expert_.png" :
|
||||
mode == comAdvanced ? "mode_middle_.png" : "mode_simple_.png";
|
||||
}
|
||||
auto bmp = new wxStaticBitmap(parent, wxID_ANY, bmp_name.empty() ? wxNullBitmap : create_scaled_bitmap(bmp_name));
|
||||
auto bmp = new wxStaticBitmap(parent, wxID_ANY, bmp_name.empty() ? wxNullBitmap : create_scaled_bitmap(parent, bmp_name));
|
||||
bmp->SetBackgroundStyle(wxBG_STYLE_PAINT);
|
||||
return bmp;
|
||||
};
|
||||
|
@ -3218,7 +3221,7 @@ void TabSLAMaterial::build()
|
|||
m_presets = &m_preset_bundle->sla_materials;
|
||||
load_initial_data();
|
||||
|
||||
auto page = add_options_page(_(L("Material")), "package_green.png");
|
||||
auto page = add_options_page(_(L("Material")), "resin");
|
||||
|
||||
auto optgroup = page->new_optgroup(_(L("Layers")));
|
||||
// optgroup->append_single_option_line("layer_height");
|
||||
|
@ -3230,7 +3233,7 @@ void TabSLAMaterial::build()
|
|||
|
||||
optgroup = page->new_optgroup(_(L("Corrections")));
|
||||
optgroup->label_width = 19 * m_em_unit;//190;
|
||||
std::vector<std::string> corrections = { "material_correction_printing", "material_correction_curing" };
|
||||
std::vector<std::string> corrections = {"material_correction"};
|
||||
std::vector<std::string> axes{ "X", "Y", "Z" };
|
||||
for (auto& opt_key : corrections) {
|
||||
auto line = Line{ m_config->def()->get(opt_key)->full_label, "" };
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "GUI_App.hpp"
|
||||
#include "I18N.hpp"
|
||||
#include "ConfigWizard.hpp"
|
||||
#include "wxExtensions.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
@ -108,8 +109,10 @@ MsgUpdateConfig::~MsgUpdateConfig() {}
|
|||
// MsgDataIncompatible
|
||||
|
||||
MsgDataIncompatible::MsgDataIncompatible(const std::unordered_map<std::string, wxString> &incompats) :
|
||||
MsgDialog(nullptr, _(L("Slic3r incompatibility")), _(L("Slic3r configuration is incompatible")), wxBitmap(from_u8(Slic3r::var("Slic3r_192px_grayscale.png")), wxBITMAP_TYPE_PNG), wxID_NONE)
|
||||
MsgDialog(nullptr, _(L("Slic3r incompatibility")), _(L("Slic3r configuration is incompatible")), wxID_NONE)
|
||||
{
|
||||
logo->SetBitmap(create_scaled_bitmap(this, "Slic3r_192px_grayscale.png", 192));
|
||||
|
||||
auto *text = new wxStaticText(this, wxID_ANY, _(L(
|
||||
"This version of Slic3r PE is not compatible with currently installed configuration bundles.\n"
|
||||
"This probably happened as a result of running an older Slic3r PE after using a newer one.\n\n"
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#include "wxExtensions.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include "libslic3r/Model.hpp"
|
||||
|
||||
|
@ -44,7 +46,7 @@ wxMenuItem* append_menu_item(wxMenu* menu, int id, const wxString& string, const
|
|||
wxMenuItem* append_menu_item(wxMenu* menu, int id, const wxString& string, const wxString& description,
|
||||
std::function<void(wxCommandEvent& event)> cb, const std::string& icon, wxEvtHandler* event_handler)
|
||||
{
|
||||
const wxBitmap& bmp = !icon.empty() ? create_scaled_bitmap(icon) : wxNullBitmap;
|
||||
const wxBitmap& bmp = !icon.empty() ? create_scaled_bitmap(nullptr, icon) : wxNullBitmap; // FIXME: pass window ptr
|
||||
return append_menu_item(menu, id, string, description, cb, bmp, event_handler);
|
||||
}
|
||||
|
||||
|
@ -55,7 +57,7 @@ wxMenuItem* append_submenu(wxMenu* menu, wxMenu* sub_menu, int id, const wxStrin
|
|||
|
||||
wxMenuItem* item = new wxMenuItem(menu, id, string, description);
|
||||
if (!icon.empty())
|
||||
item->SetBitmap(create_scaled_bitmap(icon));
|
||||
item->SetBitmap(create_scaled_bitmap(nullptr, icon)); // FIXME: pass window ptr
|
||||
|
||||
item->SetSubMenu(sub_menu);
|
||||
menu->Append(item);
|
||||
|
@ -420,27 +422,36 @@ void PrusaCollapsiblePaneMSW::Collapse(bool collapse)
|
|||
|
||||
|
||||
// If an icon has horizontal orientation (width > height) call this function with is_horizontal = true
|
||||
bool load_scaled_bitmap(wxBitmap** bmp, const std::string& bmp_name_in, const int px_cnt/* = 16*/, const bool is_horizontal /*= false*/)
|
||||
wxBitmap create_scaled_bitmap(wxWindow *win, const std::string& bmp_name_in, const int px_cnt/* = 16*/, const bool is_horizontal /* = false*/)
|
||||
{
|
||||
static Slic3r::GUI::BitmapCache cache;
|
||||
|
||||
#ifdef __APPLE__
|
||||
const float scale_factor = win != nullptr ? win->GetContentScaleFactor() : 1.0f;
|
||||
#else
|
||||
(void)(win);
|
||||
const float scale_factor = 1.0f;
|
||||
#endif
|
||||
|
||||
unsigned int height, width = height = 0;
|
||||
unsigned int& scale_base = is_horizontal ? width : height;
|
||||
|
||||
scale_base = (unsigned int)(Slic3r::GUI::wxGetApp().em_unit() * px_cnt * 0.1f + 0.5f);
|
||||
|
||||
std::string bmp_name = bmp_name_in;
|
||||
boost::replace_last(bmp_name, ".png", "");
|
||||
*bmp = cache.load_svg(bmp_name, width, height);
|
||||
if (*bmp == nullptr)
|
||||
*bmp = cache.load_png(bmp_name, width, height);
|
||||
return *bmp != nullptr;
|
||||
}
|
||||
boost::replace_last(bmp_name, ".png", "");
|
||||
|
||||
// Try loading an SVG first, then PNG if SVG is not found:
|
||||
wxBitmap *bmp = cache.load_svg(bmp_name, width, height, scale_factor);
|
||||
if (bmp == nullptr) {
|
||||
bmp = cache.load_png(bmp_name, width, height);
|
||||
}
|
||||
|
||||
if (bmp == nullptr) {
|
||||
// Neither SVG nor PNG has been found, raise error
|
||||
throw std::runtime_error("Could not load bitmap: " + bmp_name);
|
||||
}
|
||||
|
||||
// If an icon has horizontal orientation (width > height) call this function with is_horizontal = true
|
||||
wxBitmap create_scaled_bitmap(const std::string& bmp_name_in, const int px_cnt/* = 16*/, const bool is_horizontal /* = false*/)
|
||||
{
|
||||
wxBitmap *bmp {nullptr};
|
||||
load_scaled_bitmap(&bmp, bmp_name_in, px_cnt, is_horizontal);
|
||||
return *bmp;
|
||||
}
|
||||
|
||||
|
@ -450,10 +461,10 @@ wxBitmap create_scaled_bitmap(const std::string& bmp_name_in, const int px_cnt/*
|
|||
// ----------------------------------------------------------------------------
|
||||
|
||||
void PrusaObjectDataViewModelNode::set_object_action_icon() {
|
||||
m_action_icon = create_scaled_bitmap("add_object.png");
|
||||
m_action_icon = create_scaled_bitmap(nullptr, "add_object.png"); // FIXME: pass window ptr
|
||||
}
|
||||
void PrusaObjectDataViewModelNode::set_part_action_icon() {
|
||||
m_action_icon = create_scaled_bitmap(m_type == itVolume ? "cog" : "brick_go.png");
|
||||
m_action_icon = create_scaled_bitmap(nullptr, m_type == itVolume ? "cog.png" : "brick_go.png"); // FIXME: pass window ptr
|
||||
}
|
||||
|
||||
Slic3r::GUI::BitmapCache *m_bitmap_cache = nullptr;
|
||||
|
@ -1495,20 +1506,20 @@ PrusaDoubleSlider::PrusaDoubleSlider(wxWindow *parent,
|
|||
if (!is_osx)
|
||||
SetDoubleBuffered(true);// SetDoubleBuffered exists on Win and Linux/GTK, but is missing on OSX
|
||||
|
||||
m_bmp_thumb_higher = wxBitmap(style == wxSL_HORIZONTAL ? create_scaled_bitmap("right_half_circle.png") : create_scaled_bitmap("up_half_circle.png", 16, true));
|
||||
m_bmp_thumb_lower = wxBitmap(style == wxSL_HORIZONTAL ? create_scaled_bitmap("left_half_circle.png" ) : create_scaled_bitmap("down_half_circle.png",16, true));
|
||||
m_bmp_thumb_higher = wxBitmap(style == wxSL_HORIZONTAL ? create_scaled_bitmap(this, "right_half_circle.png") : create_scaled_bitmap(this, "up_half_circle.png", 16, true));
|
||||
m_bmp_thumb_lower = wxBitmap(style == wxSL_HORIZONTAL ? create_scaled_bitmap(this, "left_half_circle.png" ) : create_scaled_bitmap(this, "down_half_circle.png", 16, true));
|
||||
m_thumb_size = m_bmp_thumb_lower.GetSize();
|
||||
|
||||
m_bmp_add_tick_on = create_scaled_bitmap("colorchange_add_on.png");
|
||||
m_bmp_add_tick_off = create_scaled_bitmap("colorchange_add_off.png");
|
||||
m_bmp_del_tick_on = create_scaled_bitmap("colorchange_delete_on.png");
|
||||
m_bmp_del_tick_off = create_scaled_bitmap("colorchange_delete_off.png");
|
||||
m_bmp_add_tick_on = create_scaled_bitmap(this, "colorchange_add_on.png");
|
||||
m_bmp_add_tick_off = create_scaled_bitmap(this, "colorchange_add_off.png");
|
||||
m_bmp_del_tick_on = create_scaled_bitmap(this, "colorchange_delete_on.png");
|
||||
m_bmp_del_tick_off = create_scaled_bitmap(this, "colorchange_delete_off.png");
|
||||
m_tick_icon_dim = m_bmp_add_tick_on.GetSize().x;
|
||||
|
||||
m_bmp_one_layer_lock_on = create_scaled_bitmap("one_layer_lock_on.png");
|
||||
m_bmp_one_layer_lock_off = create_scaled_bitmap("one_layer_lock_off.png");
|
||||
m_bmp_one_layer_unlock_on = create_scaled_bitmap("one_layer_unlock_on.png");
|
||||
m_bmp_one_layer_unlock_off = create_scaled_bitmap("one_layer_unlock_off.png");
|
||||
m_bmp_one_layer_lock_on = create_scaled_bitmap(this, "one_layer_lock_on.png");
|
||||
m_bmp_one_layer_lock_off = create_scaled_bitmap(this, "one_layer_lock_off.png");
|
||||
m_bmp_one_layer_unlock_on = create_scaled_bitmap(this, "one_layer_unlock_on.png");
|
||||
m_bmp_one_layer_unlock_off = create_scaled_bitmap(this, "one_layer_unlock_off.png");
|
||||
m_lock_icon_dim = m_bmp_one_layer_lock_on.GetSize().x;
|
||||
|
||||
m_selection = ssUndef;
|
||||
|
@ -2332,10 +2343,10 @@ PrusaLockButton::PrusaLockButton( wxWindow *parent,
|
|||
const wxSize& size /*= wxDefaultSize*/):
|
||||
wxButton(parent, id, wxEmptyString, pos, size, wxBU_EXACTFIT | wxNO_BORDER)
|
||||
{
|
||||
m_bmp_lock_on = create_scaled_bitmap("one_layer_lock_on.png");
|
||||
m_bmp_lock_off = create_scaled_bitmap("one_layer_lock_off.png");
|
||||
m_bmp_unlock_on = create_scaled_bitmap("one_layer_unlock_on.png");
|
||||
m_bmp_unlock_off = create_scaled_bitmap("one_layer_unlock_off.png");
|
||||
m_bmp_lock_on = create_scaled_bitmap(this, "one_layer_lock_on.png");
|
||||
m_bmp_lock_off = create_scaled_bitmap(this, "one_layer_lock_off.png");
|
||||
m_bmp_unlock_on = create_scaled_bitmap(this, "one_layer_unlock_on.png");
|
||||
m_bmp_unlock_off = create_scaled_bitmap(this, "one_layer_unlock_off.png");
|
||||
|
||||
|
||||
#ifdef __WXMSW__
|
||||
|
@ -2393,7 +2404,7 @@ PrusaModeButton::PrusaModeButton( wxWindow *parent,
|
|||
#ifdef __WXMSW__
|
||||
SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
|
||||
#endif // __WXMSW__
|
||||
m_bmp_off = create_scaled_bitmap("mode_off_sq.png");
|
||||
m_bmp_off = create_scaled_bitmap(this, "mode_off_sq.png");
|
||||
|
||||
m_tt_focused = wxString::Format(_(L("Switch to the %s mode")), mode);
|
||||
m_tt_selected = wxString::Format(_(L("Current mode is %s")), mode);
|
||||
|
@ -2447,9 +2458,9 @@ PrusaModeSizer::PrusaModeSizer(wxWindow *parent, int hgap/* = 10*/) :
|
|||
SetFlexibleDirection(wxHORIZONTAL);
|
||||
|
||||
std::vector<std::pair<wxString, wxBitmap>> buttons = {
|
||||
{_(L("Simple")), create_scaled_bitmap("mode_simple_sq.png")},
|
||||
{_(L("Advanced")), create_scaled_bitmap("mode_middle_sq.png")},
|
||||
{_(L("Expert")), create_scaled_bitmap("mode_expert_sq.png")}
|
||||
{_(L("Simple")), create_scaled_bitmap(parent, "mode_simple_sq.png")},
|
||||
{_(L("Advanced")), create_scaled_bitmap(parent, "mode_middle_sq.png")},
|
||||
{_(L("Expert")), create_scaled_bitmap(parent, "mode_expert_sq.png")}
|
||||
};
|
||||
|
||||
mode_btns.reserve(3);
|
||||
|
|
|
@ -31,8 +31,7 @@ wxMenuItem* append_submenu(wxMenu* menu, wxMenu* sub_menu, int id, const wxStrin
|
|||
wxMenuItem* append_menu_radio_item(wxMenu* menu, int id, const wxString& string, const wxString& description,
|
||||
std::function<void(wxCommandEvent& event)> cb, wxEvtHandler* event_handler);
|
||||
|
||||
bool load_scaled_bitmap(wxBitmap** bmp, const std::string& bmp_name, const int px_cnt=16, const bool is_horizontal = false);
|
||||
wxBitmap create_scaled_bitmap(const std::string& bmp_name, const int px_cnt=16, const bool is_horizontal = false);
|
||||
wxBitmap create_scaled_bitmap(wxWindow *win, const std::string& bmp_name, const int px_cnt=16, const bool is_horizontal = false);
|
||||
|
||||
class wxCheckListBoxComboPopup : public wxCheckListBox, public wxComboPopup
|
||||
{
|
||||
|
|