mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-05-21 20:18:17 +08:00
Merge branch 'master' into tm_pad_improve
This commit is contained in:
commit
a25072f0a3
@ -2,6 +2,8 @@ project(Slic3r)
|
|||||||
cmake_minimum_required(VERSION 3.2)
|
cmake_minimum_required(VERSION 3.2)
|
||||||
|
|
||||||
include("version.inc")
|
include("version.inc")
|
||||||
|
include(GNUInstallDirs)
|
||||||
|
|
||||||
set(SLIC3R_RESOURCES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/resources")
|
set(SLIC3R_RESOURCES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/resources")
|
||||||
file(TO_NATIVE_PATH "${SLIC3R_RESOURCES_DIR}" SLIC3R_RESOURCES_DIR_WIN)
|
file(TO_NATIVE_PATH "${SLIC3R_RESOURCES_DIR}" SLIC3R_RESOURCES_DIR_WIN)
|
||||||
|
|
||||||
@ -22,6 +24,7 @@ endif()
|
|||||||
|
|
||||||
option(SLIC3R_STATIC "Compile Slic3r with static libraries (Boost, TBB, glew)" ${SLIC3R_STATIC_INITIAL})
|
option(SLIC3R_STATIC "Compile Slic3r with static libraries (Boost, TBB, glew)" ${SLIC3R_STATIC_INITIAL})
|
||||||
option(SLIC3R_GUI "Compile Slic3r with GUI components (OpenGL, wxWidgets)" 1)
|
option(SLIC3R_GUI "Compile Slic3r with GUI components (OpenGL, wxWidgets)" 1)
|
||||||
|
option(SLIC3R_FHS "Assume Slic3r is to be installed in a FHS directory structure" 0)
|
||||||
option(SLIC3R_PROFILE "Compile Slic3r with an invasive Shiny profiler" 0)
|
option(SLIC3R_PROFILE "Compile Slic3r with an invasive Shiny profiler" 0)
|
||||||
option(SLIC3R_MSVC_COMPILE_PARALLEL "Compile on Visual Studio in parallel" 1)
|
option(SLIC3R_MSVC_COMPILE_PARALLEL "Compile on Visual Studio in parallel" 1)
|
||||||
option(SLIC3R_MSVC_PDB "Generate PDB files on MSVC in Release mode" 1)
|
option(SLIC3R_MSVC_PDB "Generate PDB files on MSVC in Release mode" 1)
|
||||||
@ -61,6 +64,8 @@ foreach (DIR ${PREFIX_PATH_CHECK})
|
|||||||
endif ()
|
endif ()
|
||||||
endforeach ()
|
endforeach ()
|
||||||
|
|
||||||
|
message(STATUS "SLIC3R_FHS: ${SLIC3R_FHS}")
|
||||||
|
|
||||||
# Add our own cmake module path.
|
# Add our own cmake module path.
|
||||||
list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/modules/)
|
list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/modules/)
|
||||||
|
|
||||||
@ -146,12 +151,14 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STRE
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Where all the bundled libraries reside?
|
# Where all the bundled libraries reside?
|
||||||
set(LIBDIR ${CMAKE_CURRENT_SOURCE_DIR}/src/)
|
set(LIBDIR ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||||
|
set(LIBDIR_BIN ${CMAKE_CURRENT_BINARY_DIR}/src)
|
||||||
# For the bundled boost libraries (boost::nowide)
|
# For the bundled boost libraries (boost::nowide)
|
||||||
include_directories(${LIBDIR})
|
include_directories(${LIBDIR})
|
||||||
|
# For generated header files
|
||||||
|
include_directories(${LIBDIR_BIN}/platform)
|
||||||
# For libslic3r.h
|
# For libslic3r.h
|
||||||
include_directories(${LIBDIR}/clipper ${LIBDIR}/polypartition)
|
include_directories(${LIBDIR}/clipper ${LIBDIR}/polypartition)
|
||||||
#set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
# BOOST_ALL_NO_LIB: Avoid the automatic linking of Boost libraries on Windows. Rather rely on explicit linking.
|
# BOOST_ALL_NO_LIB: Avoid the automatic linking of Boost libraries on Windows. Rather rely on explicit linking.
|
||||||
@ -215,7 +222,6 @@ endif()
|
|||||||
# The Intel TBB library will use the std::exception_ptr feature of C++11.
|
# The Intel TBB library will use the std::exception_ptr feature of C++11.
|
||||||
add_definitions(-DTBB_USE_CAPTURED_EXCEPTION=0)
|
add_definitions(-DTBB_USE_CAPTURED_EXCEPTION=0)
|
||||||
|
|
||||||
#set(CURL_DEBUG 1)
|
|
||||||
find_package(CURL REQUIRED)
|
find_package(CURL REQUIRED)
|
||||||
include_directories(${CURL_INCLUDE_DIRS})
|
include_directories(${CURL_INCLUDE_DIRS})
|
||||||
|
|
||||||
@ -280,7 +286,6 @@ include_directories(${GLEW_INCLUDE_DIRS})
|
|||||||
# l10n
|
# l10n
|
||||||
set(L10N_DIR "${SLIC3R_RESOURCES_DIR}/localization")
|
set(L10N_DIR "${SLIC3R_RESOURCES_DIR}/localization")
|
||||||
add_custom_target(pot
|
add_custom_target(pot
|
||||||
# FIXME: file list stale
|
|
||||||
COMMAND xgettext --keyword=L --from-code=UTF-8 --debug
|
COMMAND xgettext --keyword=L --from-code=UTF-8 --debug
|
||||||
-f "${L10N_DIR}/list.txt"
|
-f "${L10N_DIR}/list.txt"
|
||||||
-o "${L10N_DIR}/Slic3rPE.pot"
|
-o "${L10N_DIR}/Slic3rPE.pot"
|
||||||
@ -307,5 +312,12 @@ if(SLIC3R_BUILD_TESTS)
|
|||||||
add_subdirectory(tests)
|
add_subdirectory(tests)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
file(GLOB MyVar var/*.png)
|
|
||||||
install(FILES ${MyVar} DESTINATION share/slic3r-prusa3d)
|
# Resources install target, configure fhs.hpp on UNIX
|
||||||
|
if (WIN32)
|
||||||
|
install(DIRECTORY "${SLIC3R_RESOURCES_DIR}/" DESTINATION "${CMAKE_INSTALL_PREFIX}/resources")
|
||||||
|
else ()
|
||||||
|
set(SLIC3R_FHS_RESOURCES "${CMAKE_INSTALL_FULL_DATAROOTDIR}/slic3r-prusa3d")
|
||||||
|
install(DIRECTORY "${SLIC3R_RESOURCES_DIR}/" DESTINATION "${SLIC3R_FHS_RESOURCES}")
|
||||||
|
endif ()
|
||||||
|
configure_file(${LIBDIR}/platform/unix/fhs.hpp.in ${LIBDIR_BIN}/platform/unix/fhs.hpp)
|
||||||
|
1
deps/CMakeLists.txt
vendored
1
deps/CMakeLists.txt
vendored
@ -6,6 +6,7 @@
|
|||||||
# All the dependencies are installed in a `destdir` directory in the root of the build directory,
|
# All the dependencies are installed in a `destdir` directory in the root of the build directory,
|
||||||
# in a traditional Unix-style prefix structure. The destdir can be used directly by CMake
|
# in a traditional Unix-style prefix structure. The destdir can be used directly by CMake
|
||||||
# when building Slic3r - to do this, set the CMAKE_PREFIX_PATH to ${destdir}/usr/local.
|
# when building Slic3r - to do this, set the CMAKE_PREFIX_PATH to ${destdir}/usr/local.
|
||||||
|
# Warning: On UNIX/Linux, you also need to set -DSLIC3R_STATIC=1 when building Slic3r.
|
||||||
#
|
#
|
||||||
# For better clarity of console output, it's recommended to _not_ use a parallelized build
|
# For better clarity of console output, it's recommended to _not_ use a parallelized build
|
||||||
# for the top-level command, ie. use `make -j 1` or `ninja -j 1` to force single-threaded top-level
|
# for the top-level command, ie. use `make -j 1` or `ninja -j 1` to force single-threaded top-level
|
||||||
|
31
deps/deps-windows.cmake
vendored
31
deps/deps-windows.cmake
vendored
@ -121,7 +121,8 @@ ExternalProject_Add(dep_zlib
|
|||||||
URL_HASH SHA256=4ff941449631ace0d4d203e3483be9dbc9da454084111f97ea0a2114e19bf066
|
URL_HASH SHA256=4ff941449631ace0d4d203e3483be9dbc9da454084111f97ea0a2114e19bf066
|
||||||
CMAKE_GENERATOR "${DEP_MSVC_GEN}"
|
CMAKE_GENERATOR "${DEP_MSVC_GEN}"
|
||||||
CMAKE_ARGS
|
CMAKE_ARGS
|
||||||
"-DINSTALL_BIN_DIR=${CMAKE_CURRENT_BINARY_DIR}\\fallout" # I found no better way of preventing zlib creating & installing DLLs :-/
|
-DSKIP_INSTALL_FILES=ON # Prevent installation of man pages et al.
|
||||||
|
"-DINSTALL_BIN_DIR=${CMAKE_CURRENT_BINARY_DIR}\\fallout" # I found no better way of preventing zlib from creating & installing DLLs :-/
|
||||||
-DCMAKE_POSITION_INDEPENDENT_CODE=ON
|
-DCMAKE_POSITION_INDEPENDENT_CODE=ON
|
||||||
"-DCMAKE_INSTALL_PREFIX:PATH=${DESTDIR}\\usr\\local"
|
"-DCMAKE_INSTALL_PREFIX:PATH=${DESTDIR}\\usr\\local"
|
||||||
BUILD_COMMAND msbuild /P:Configuration=Release INSTALL.vcxproj
|
BUILD_COMMAND msbuild /P:Configuration=Release INSTALL.vcxproj
|
||||||
@ -136,6 +137,19 @@ if (${DEP_DEBUG})
|
|||||||
WORKING_DIRECTORY "${BINARY_DIR}"
|
WORKING_DIRECTORY "${BINARY_DIR}"
|
||||||
)
|
)
|
||||||
endif ()
|
endif ()
|
||||||
|
# The following steps are unfortunately needed to remove the _static suffix on libraries
|
||||||
|
ExternalProject_Add_Step(dep_zlib fix_static
|
||||||
|
DEPENDEES install
|
||||||
|
COMMAND "${CMAKE_COMMAND}" -E rename zlibstatic.lib zlib.lib
|
||||||
|
WORKING_DIRECTORY "${DESTDIR}\\usr\\local\\lib\\"
|
||||||
|
)
|
||||||
|
if (${DEP_DEBUG})
|
||||||
|
ExternalProject_Add_Step(dep_zlib fix_static_debug
|
||||||
|
DEPENDEES install
|
||||||
|
COMMAND "${CMAKE_COMMAND}" -E rename zlibstaticd.lib zlibd.lib
|
||||||
|
WORKING_DIRECTORY "${DESTDIR}\\usr\\local\\lib\\"
|
||||||
|
)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
|
||||||
ExternalProject_Add(dep_libpng
|
ExternalProject_Add(dep_libpng
|
||||||
@ -147,6 +161,7 @@ ExternalProject_Add(dep_libpng
|
|||||||
CMAKE_ARGS
|
CMAKE_ARGS
|
||||||
-DPNG_SHARED=OFF
|
-DPNG_SHARED=OFF
|
||||||
-DPNG_TESTS=OFF
|
-DPNG_TESTS=OFF
|
||||||
|
-DSKIP_INSTALL_FILES=ON # Prevent installation of man pages et al.
|
||||||
-DCMAKE_POSITION_INDEPENDENT_CODE=ON
|
-DCMAKE_POSITION_INDEPENDENT_CODE=ON
|
||||||
"-DCMAKE_INSTALL_PREFIX:PATH=${DESTDIR}\\usr\\local"
|
"-DCMAKE_INSTALL_PREFIX:PATH=${DESTDIR}\\usr\\local"
|
||||||
BUILD_COMMAND msbuild /P:Configuration=Release INSTALL.vcxproj
|
BUILD_COMMAND msbuild /P:Configuration=Release INSTALL.vcxproj
|
||||||
@ -161,6 +176,20 @@ if (${DEP_DEBUG})
|
|||||||
WORKING_DIRECTORY "${BINARY_DIR}"
|
WORKING_DIRECTORY "${BINARY_DIR}"
|
||||||
)
|
)
|
||||||
endif ()
|
endif ()
|
||||||
|
# The following steps are unfortunately needed to remove the _static suffix on libraries
|
||||||
|
# (And also overwrite the dynamic .lib)
|
||||||
|
ExternalProject_Add_Step(dep_libpng fix_static
|
||||||
|
DEPENDEES install
|
||||||
|
COMMAND "${CMAKE_COMMAND}" -E rename libpng16_static.lib libpng16.lib
|
||||||
|
WORKING_DIRECTORY "${DESTDIR}\\usr\\local\\lib\\"
|
||||||
|
)
|
||||||
|
if (${DEP_DEBUG})
|
||||||
|
ExternalProject_Add_Step(dep_libpng fix_static_debug
|
||||||
|
DEPENDEES install
|
||||||
|
COMMAND "${CMAKE_COMMAND}" -E rename libpng16_staticd.lib libpng16d.lib
|
||||||
|
WORKING_DIRECTORY "${DESTDIR}\\usr\\local\\lib\\"
|
||||||
|
)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
|
||||||
if (${DEPS_BITS} EQUAL 32)
|
if (${DEPS_BITS} EQUAL 32)
|
||||||
|
66
doc/How to build - Linux et al.md
Normal file
66
doc/How to build - Linux et al.md
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
|
||||||
|
# Building Slic3r PE on UNIX/Linux
|
||||||
|
|
||||||
|
Slic3r PE uses the CMake build system and requires several dependencies.
|
||||||
|
The dependencies can be listed in `deps/deps-linux.cmake`, although they don't necessarily need to be as recent
|
||||||
|
as the versions listed - generally versions available on conservative Linux distros such as Debian stable or CentOS should suffice.
|
||||||
|
|
||||||
|
Perl is not required any more.
|
||||||
|
|
||||||
|
In a typical situaction, one would open a command line, go to the Slic3r sources, create a directory called `build` or similar,
|
||||||
|
`cd` into it and call:
|
||||||
|
|
||||||
|
cmake ..
|
||||||
|
make -jN
|
||||||
|
|
||||||
|
where `N` is the number of CPU cores available.
|
||||||
|
|
||||||
|
Additional CMake flags may be applicable as explained below.
|
||||||
|
|
||||||
|
### Dependenciy resolution
|
||||||
|
|
||||||
|
By default Slic3r looks for dependencies the default way CMake looks for them, ie. in default system locations.
|
||||||
|
On Linux this will typically make Slic3r depend on dynamically loaded libraries from the system, however, Slic3r can be told
|
||||||
|
to specifically look for static libraries with the `SLIC3R_STATIC` flag passed to cmake:
|
||||||
|
|
||||||
|
cmake .. -DSLIC3R_STATIC=1
|
||||||
|
|
||||||
|
Additionally, Slic3r can be built in a static manner mostly independent of the system libraries with a dependencies bundle
|
||||||
|
created using CMake script in the `deps` directory (these are not interconnected with the rest of the CMake scripts).
|
||||||
|
|
||||||
|
Note: We say _mostly independent_ because it's still expected the system will provide some transitive dependencies, such as GTK for wxWidgets.
|
||||||
|
|
||||||
|
To do this, go to the `deps` directory, create a `build` subdirectory (or the like) and use:
|
||||||
|
|
||||||
|
cmake .. -DDESTDIR=<target destdir>
|
||||||
|
|
||||||
|
where the target destdir is a directory of your choosing where the dependencies will be installed.
|
||||||
|
You can also omit the `DESTDIR` option to use the default, in that case the `destdir` will be created inside the `build` directory where `cmake` is run.
|
||||||
|
|
||||||
|
To pass the destdir path to the top-level Slic3r CMake script, use the `CMAKE_PREFIX_PATH` option along with turning on `SLIC3R_STATIC`:
|
||||||
|
|
||||||
|
cmake .. -DSLIC3R_STATIC=1 -DCMAKE_PREFIX_PATH=<path to destdir>/usr/local
|
||||||
|
|
||||||
|
Note that `/usr/local` needs to be appended to the destdir path and also the prefix path should be absolute.
|
||||||
|
|
||||||
|
**Warning**: Once the dependency bundle is installed in a destdir, the destdir cannot be moved elsewhere.
|
||||||
|
This is because wxWidgets hardcode the installation path.
|
||||||
|
|
||||||
|
### Build variant
|
||||||
|
|
||||||
|
By default Scli3r builds the release variant.
|
||||||
|
To create a debug build, use the following CMake flag:
|
||||||
|
|
||||||
|
-DCMAKE_BUILD_TYPE=Debug
|
||||||
|
|
||||||
|
### Installation
|
||||||
|
|
||||||
|
In runtime, Slic3r needs a way to access its resource files. By default, it looks for a `resources` directory relative to its binary.
|
||||||
|
|
||||||
|
If you instead wnat Slic3r installed in a structure according to the Filesystem Hierarchy Standard, use the `SLIC3R_FHS` flag
|
||||||
|
|
||||||
|
cmake .. -DSLIC3R_FHS=1
|
||||||
|
|
||||||
|
This will make Slic3r look for a fixed-location `share/slic3r-prusa3d` directory instead (note that the location becomes hardcoded).
|
||||||
|
|
||||||
|
You can then use the `make install` target to install Slic3r.
|
62
doc/How to build - Mac OS.md
Normal file
62
doc/How to build - Mac OS.md
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
|
||||||
|
# Building Slic3r PE on Mac OS
|
||||||
|
|
||||||
|
To build Slic3r PE on Mac OS, you will need to install XCode and an appropriate SDK.
|
||||||
|
You will also need [CMake](https://cmake.org/) installed (available on Brew) and possibly git.
|
||||||
|
|
||||||
|
Currently Slic3r PE is built against the Mac OS X SDK version 10.9.
|
||||||
|
Building against older SDKs is unsupported. Building against newer SDKs might work,
|
||||||
|
but there may be subtle issues, such as dark mode not working very well on Mojave or other GUI problems.
|
||||||
|
|
||||||
|
You can obtain the SDK 10.9 for example [in this repository](https://github.com/phracker/MacOSX-SDKs).
|
||||||
|
If you don't already have the 10.9 version as part of your Mac OS installation, please download it
|
||||||
|
and place it into a reachable location.
|
||||||
|
|
||||||
|
The default location for Mac OS SDKs is:
|
||||||
|
|
||||||
|
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/
|
||||||
|
|
||||||
|
Wherever the 10.9 SDK is, please note down its location, it will be required to build Slic3r.
|
||||||
|
|
||||||
|
On my system, for example, the path to the SDK is
|
||||||
|
|
||||||
|
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk
|
||||||
|
|
||||||
|
### Dependencies
|
||||||
|
|
||||||
|
Slic3r comes with a set of CMake scripts to build its dependencies, it lives in the `deps` directory.
|
||||||
|
Open a terminal window and navigate to Slic3r sources directory and then to `deps`.
|
||||||
|
Use the following commands to build the dependencies:
|
||||||
|
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake .. -DDEPS_OSX_SYSROOT=<path to the 10.9 SDK>
|
||||||
|
|
||||||
|
This will create a dependencies bundle inside the `build/destdir` directory.
|
||||||
|
You can also customize the bundle output path using the `-DDESTDIR=<some path>` option passed to `cmake`.
|
||||||
|
|
||||||
|
### Building Slic3r
|
||||||
|
|
||||||
|
If dependencies built without an error, you can proceed to build Slic3r itself.
|
||||||
|
Go back to top level Slic3r sources directory and use these commands:
|
||||||
|
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake .. -DCMAKE_PREFIX_PATH="$PWD/../deps/build/destdir/usr/local" -DCMAKE_OSX_SYSROOT=<path to the 10.9 SDK>
|
||||||
|
|
||||||
|
The `CMAKE_PREFIX_PATH` is the path to the dependencies bundle but with `/usr/local` appended - if you set a custom path
|
||||||
|
using the `DESTDIR` option, you will need to change this accordingly. **Warning:** the `CMAKE_PREFIX_PATH` needs to be an absolute path.
|
||||||
|
|
||||||
|
The CMake command above prepares Slic3r for building from the command line.
|
||||||
|
To start the build, use
|
||||||
|
|
||||||
|
make -jN
|
||||||
|
|
||||||
|
where `N` is the number of CPU cores, so, for example `make -j4` for a 4-core machine.
|
||||||
|
|
||||||
|
Alternatively, if you would like to use XCode GUI, modify the `cmake` command to include the `-GXcode` option:
|
||||||
|
|
||||||
|
cmake .. -GXcode -DCMAKE_PREFIX_PATH="$PWD/../deps/build/destdir/usr/local" -DCMAKE_OSX_SYSROOT=<path to the 10.9 SDK>
|
||||||
|
|
||||||
|
and then open the `Slic3r.xcodeproj` file.
|
||||||
|
This should open up XCode where you can perform build using the GUI or perform other tasks.
|
@ -1,99 +1,98 @@
|
|||||||
|
|
||||||
### NOTE: This document is currently outdated wrt. the new post-Perl Slic3rPE. A new build process and the description thereof is a work in progress and is comming soon. Please stay tuned.
|
|
||||||
|
|
||||||
--
|
|
||||||
|
|
||||||
|
|
||||||
# Building Slic3r PE on Microsoft Windows
|
# Building Slic3r PE on Microsoft Windows
|
||||||
|
|
||||||
The currently supported way of building Slic3r PE on Windows is with CMake and MS Visual Studio 2013
|
The currently supported way of building Slic3r PE on Windows is with CMake and MS Visual Studio 2013.
|
||||||
using our Perl binary distribution (compiled from official Perl sources).
|
|
||||||
You can use the free [Visual Studio 2013 Community Edition](https://www.visualstudio.com/vs/older-downloads/).
|
You can use the free [Visual Studio 2013 Community Edition](https://www.visualstudio.com/vs/older-downloads/).
|
||||||
CMake installer can be downloaded from [the official website](https://cmake.org/download/).
|
CMake installer can be downloaded from [the official website](https://cmake.org/download/).
|
||||||
|
|
||||||
Other setups (such as mingw + Strawberry Perl) _may_ work, but we cannot guarantee this will work
|
Building with newer versions of MSVS (2015, 2017) may work too as reported by some of our users.
|
||||||
and cannot provide guidance.
|
|
||||||
|
|
||||||
|
_Note:_ Thanks to **@supermerill** for testing and inspiration on this guide.
|
||||||
|
|
||||||
### Geting the dependencies
|
### Dependencies
|
||||||
|
|
||||||
First, download and upnack our Perl + wxWidgets binary distribution:
|
On Windows Slic3r is built against statically built libraries.
|
||||||
|
We provide a prebuilt package of all the needed dependencies.
|
||||||
|
The package comes in a several variants:
|
||||||
|
|
||||||
- 32 bit, release mode: [wperl32-5.24.0-2018-03-02.7z](https://bintray.com/vojtechkral/Slic3r-PE/download_file?file_path=wperl32-5.24.0-2018-03-02.7z)
|
- [64 bit, Release mode only](https://bintray.com/vojtechkral/Slic3r-PE/download_file?file_path=destdir-64.7z) (41 MB, 578 MB unpacked)
|
||||||
- 64 bit, release mode: [wperl64-5.24.0-2018-03-02.7z](https://bintray.com/vojtechkral/Slic3r-PE/download_file?file_path=wperl64-5.24.0-2018-03-02.7z)
|
- [64 bit, Release and Debug mode](https://bintray.com/vojtechkral/Slic3r-PE/download_file?file_path=destdir-64-dev.7z) (88 MB, 1.3 GB unpacked)
|
||||||
- 64 bit, release mode + debug symbols: [wperl64d-5.24.0-2018-03-02.7z](https://bintray.com/vojtechkral/Slic3r-PE/download_file?file_path=wperl64d-5.24.0-2018-03-02.7z)
|
- [32 bit, Release mode only](https://bintray.com/vojtechkral/Slic3r-PE/download_file?file_path=destdir-32.7z) (38 MB, 520 MB unpacked)
|
||||||
|
- [32 bit, Release and Debug mode](https://bintray.com/vojtechkral/Slic3r-PE/download_file?file_path=destdir-32-dev.7z) (74 MB, 1.1 GB unpacked)
|
||||||
|
|
||||||
It is recommended to unpack this package into `C:\`.
|
When unsure, use the _Release mode only_ variant, the _Release and Debug_ variant is only needed for debugging & developement.
|
||||||
|
|
||||||
Apart from wxWidgets and Perl, you will also need additional dependencies:
|
If you're unsure where to unpack the package, unpack it into `C:\local\` (but it can really be anywhere).
|
||||||
|
|
||||||
- Boost
|
Alternatively you can also compile the dependencies yourself, see below.
|
||||||
- Intel TBB
|
|
||||||
- libcurl
|
|
||||||
|
|
||||||
We have prepared a binary package of the listed libraries:
|
### Building Slic3r PE with Visual Studio
|
||||||
|
|
||||||
- 32 bit: [slic3r-destdir-32.7z](https://bintray.com/vojtechkral/Slic3r-PE/download_file?file_path=2%2Fslic3r-destdir-32.7z)
|
First obtain the Slic3 PE sources via either git or by extracting the source archive.
|
||||||
- 64 bit: [slic3r-destdir-64.7z](https://bintray.com/vojtechkral/Slic3r-PE/download_file?file_path=2%2Fslic3r-destdir-64.7z)
|
|
||||||
|
|
||||||
It is recommended you unpack this package into `C:\local\` as the environment
|
Then you will need to note down the so-called 'prefix path' to the dependencies, this is the location of the dependencies packages + `\usr\local` appended.
|
||||||
setup script expects it there.
|
For example on 64 bits this would be `C:\local\destdir-64\usr\local`. The prefix path will need to be passed to CMake.
|
||||||
|
|
||||||
Alternatively you can also compile the additional dependencies yourself.
|
When ready, open the relevant Visual Studio command line and `cd` into the directory with Slic3r sources.
|
||||||
There is a [powershell script](./deps-build/windows/slic3r-makedeps.ps1) which automates this process.
|
Use these commands to prepare Visual Studio solution file:
|
||||||
|
|
||||||
### Building Slic3r PE
|
|
||||||
|
|
||||||
Once the dependencies are set up in their respective locations,
|
|
||||||
go to the `wperl*` directory extracted earlier and launch the `cmdline.lnk` file
|
|
||||||
which opens a command line prompt with appropriate environment variables set up.
|
|
||||||
|
|
||||||
In this command line, `cd` into the directory with Slic3r sources
|
|
||||||
and use these commands to build the Slic3r from the command line:
|
|
||||||
|
|
||||||
perl Build.PL
|
|
||||||
perl Build.PL --gui
|
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
cmake .. -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=Release
|
cmake .. -G "Visual Studio 12 Win64" -DCMAKE_PREFIX_PATH="<insert prefix path here>"
|
||||||
nmake
|
|
||||||
cd ..
|
|
||||||
perl slic3r.pl
|
|
||||||
|
|
||||||
The above commands use `nmake` Makefiles.
|
Note that if you're building a 32-bit variant, you will need to change the `"Visual Studio 12 Win64"` to just `"Visual Studio 12"`.
|
||||||
You may also build Slic3r PE with other build tools:
|
|
||||||
|
|
||||||
|
Conversely, if you're using Visual Studio version other than 2013, the version number will need to be changed accordingly.
|
||||||
|
|
||||||
### Building with Visual Studio
|
If `cmake` has finished without errors, go to the build directory and open the `Slic3r.sln` solution file in Visual Studio.
|
||||||
|
Before building, make sure you're building the right project (use one of those starting with `slic3r_app_...`) and that you're building
|
||||||
|
with the right configuration, ie. _Release_ vs. _Debug_. When unsure, choose _Release_.
|
||||||
|
Note that you won't be able to build a _Debug_ variant against a _Release_-only dependencies package.
|
||||||
|
|
||||||
To build and debug Slic3r PE with Visual Studio (64 bits), replace the `cmake` command with:
|
#### Installing using the `INSTALL` project
|
||||||
|
|
||||||
cmake .. -G "Visual Studio 12 Win64" -DCMAKE_CONFIGURATION_TYPES=RelWithDebInfo
|
Slic3r PE can be run from the Visual Studio or from Visual Studio's build directory (`src\Release` or `src\Debug`),
|
||||||
|
but for longer-term usage you migth want to install somewhere using the `INSTALL` project.
|
||||||
|
By default, this installs into `C:\Program Files\Slic3r`.
|
||||||
|
To customize the install path, use the `-DCMAKE_INSTALL_PREFIX=<path of your choice>` when invoking `cmake`.
|
||||||
|
|
||||||
For the 32-bit variant, use:
|
### Building from the command line
|
||||||
|
|
||||||
cmake .. -G "Visual Studio 12" -DCMAKE_CONFIGURATION_TYPES=RelWithDebInfo
|
There are several options for building from the command line:
|
||||||
|
|
||||||
After `cmake` has finished, go to the build directory and open the `Slic3r.sln` solution file.
|
- [msbuild](https://docs.microsoft.com/en-us/visualstudio/msbuild/msbuild-reference?view=vs-2017&viewFallbackFrom=vs-2013)
|
||||||
This should open Visual Studio and load the Slic3r solution containing all the projects.
|
- [Ninja](https://ninja-build.org/)
|
||||||
Make sure you use Visual Studio 2013 to open the solution.
|
- [nmake](https://docs.microsoft.com/en-us/cpp/build/nmake-reference?view=vs-2017)
|
||||||
|
|
||||||
You can then use the usual Visual Studio controls to build Slic3r (Hit `F5` to build and run with debugger).
|
To build with msbuild, use the same CMake command as in previous paragraph and then build using
|
||||||
If you want to run or debug Slic3r from within Visual Studio, make sure the `XS` project is activated.
|
|
||||||
It should be set as the Startup project by CMake by default, but you might want to check anyway.
|
|
||||||
There are multiple projects in the Slic3r solution, but only the `XS` project is configured with the right
|
|
||||||
commands to run and debug Slic3r.
|
|
||||||
|
|
||||||
The above cmake commands generate Visual Studio project files with the `RelWithDebInfo` configuration only.
|
msbuild /P:Configuration=Release ALL_BUILD.vcxproj
|
||||||
If you also want to use the `Release` configuration, you can generate Visual Studio projects with:
|
|
||||||
|
|
||||||
-DCMAKE_CONFIGURATION_TYPES=Release;RelWithDebInfo
|
To build with Ninja or nmake, replace the `-G` option in the CMake call with `-G Ninja` or `-G "NMake Makefiles"` , respectively.
|
||||||
|
Then use either `ninja` or `nmake` to start the build.
|
||||||
|
|
||||||
(The `Debug` configuration is not supported as of now.)
|
To install, use `msbuild /P:Configuration=Release INSTALL.vcxproj` , `ninja install` , or `nmake install` .
|
||||||
|
|
||||||
### Building with ninja
|
### Building the dependencies package yourself
|
||||||
|
|
||||||
To use [Ninja](https://ninja-build.org/), replace the `cmake` and `nmake` commands with:
|
The dependencies package is built using CMake scripts inside the `deps` subdirectory of Slic3r PE sources.
|
||||||
|
(This is intentionally not interconnected with the CMake scripts in the rest of the sources.)
|
||||||
|
|
||||||
cmake .. -G Ninja -DCMAKE_BUILD_TYPE=Release
|
Open the preferred Visual Studio command line (64 or 32 bit variant) and `cd` into the directory with Slic3r sources.
|
||||||
ninja
|
Then `cd` into the `deps` directory and use these commands to build:
|
||||||
|
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake .. -G "Visual Studio 12 Win64" -DDESTDIR="C:\local\destdir-custom"
|
||||||
|
msbuild ALL_BUILD.vcxproj
|
||||||
|
|
||||||
|
You can also use the Visual Studio GUI or other generators as mentioned above.
|
||||||
|
|
||||||
|
The `DESTDIR` option is the location where the bundle will be installed.
|
||||||
|
This may be customized. If you leave it empty, the `DESTDIR` will be places inside the same `build` directory.
|
||||||
|
|
||||||
|
Note that the build variant that you may choose using Visual Studio (ie. _Release_ or _Debug_ etc.) when building the dependency package is **not relevant**.
|
||||||
|
The dependency build will by default build _both_ the _Release_ and _Debug_ variants regardless of what you choose in Visual Studio.
|
||||||
|
You can disable building of the debug variant by passing the `-DDEP_DEBUG=OFF` option to CMake, this will only produce a _Release_ build.
|
||||||
|
|
||||||
|
Refer to the CMake scripts inside the `deps` directory to see which dependencies are built in what versions and how this is done.
|
||||||
|
@ -33,6 +33,7 @@ if(PNG_FOUND AND NOT RASTERIZER_FORCE_BUILTIN_LIBPNG)
|
|||||||
else()
|
else()
|
||||||
set(ZLIB_LIBRARY "")
|
set(ZLIB_LIBRARY "")
|
||||||
message(WARNING "Using builtin libpng. This can cause crashes on some platforms.")
|
message(WARNING "Using builtin libpng. This can cause crashes on some platforms.")
|
||||||
|
set(SKIP_INSTALL_ALL 1) # Prevent png+zlib from creating install targets
|
||||||
add_subdirectory(png/zlib)
|
add_subdirectory(png/zlib)
|
||||||
set(ZLIB_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/png/zlib ${CMAKE_CURRENT_BINARY_DIR}/png/zlib)
|
set(ZLIB_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/png/zlib ${CMAKE_CURRENT_BINARY_DIR}/png/zlib)
|
||||||
include_directories(${ZLIB_INCLUDE_DIR})
|
include_directories(${ZLIB_INCLUDE_DIR})
|
||||||
@ -188,3 +189,15 @@ else ()
|
|||||||
VERBATIM
|
VERBATIM
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Slic3r binary install target
|
||||||
|
if (WIN32)
|
||||||
|
install(TARGETS slic3r RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}")
|
||||||
|
if (MSVC)
|
||||||
|
install(TARGETS slic3r_app_gui RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}")
|
||||||
|
install(TARGETS slic3r_app_console RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}")
|
||||||
|
install(TARGETS slic3r_app_noconsole RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}")
|
||||||
|
endif ()
|
||||||
|
else ()
|
||||||
|
install(TARGETS slic3r RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
|
||||||
|
endif ()
|
||||||
|
@ -218,7 +218,7 @@ public:
|
|||||||
|
|
||||||
const T& get_at(size_t i) const { return const_cast<ConfigOptionVector<T>*>(this)->get_at(i); }
|
const T& get_at(size_t i) const { return const_cast<ConfigOptionVector<T>*>(this)->get_at(i); }
|
||||||
|
|
||||||
// Resize this vector by duplicating the last value.
|
// Resize this vector by duplicating the /*last*/first value.
|
||||||
// If the current vector is empty, the default value is used instead.
|
// If the current vector is empty, the default value is used instead.
|
||||||
void resize(size_t n, const ConfigOption *opt_default = nullptr) override
|
void resize(size_t n, const ConfigOption *opt_default = nullptr) override
|
||||||
{
|
{
|
||||||
@ -238,7 +238,7 @@ public:
|
|||||||
this->values.resize(n, static_cast<const ConfigOptionVector<T>*>(opt_default)->values.front());
|
this->values.resize(n, static_cast<const ConfigOptionVector<T>*>(opt_default)->values.front());
|
||||||
} else {
|
} else {
|
||||||
// Resize by duplicating the last value.
|
// Resize by duplicating the last value.
|
||||||
this->values.resize(n, this->values.back());
|
this->values.resize(n, this->values./*back*/front());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -204,7 +204,9 @@ std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::T
|
|||||||
if (! start_filament_gcode.empty()) {
|
if (! start_filament_gcode.empty()) {
|
||||||
// Process the start_filament_gcode for the active filament only.
|
// Process the start_filament_gcode for the active filament only.
|
||||||
gcodegen.placeholder_parser().set("current_extruder", new_extruder_id);
|
gcodegen.placeholder_parser().set("current_extruder", new_extruder_id);
|
||||||
gcode += gcodegen.placeholder_parser_process("start_filament_gcode", start_filament_gcode, new_extruder_id);
|
DynamicConfig config;
|
||||||
|
config.set_key_value("filament_extruder_id", new ConfigOptionInt(new_extruder_id));
|
||||||
|
gcode += gcodegen.placeholder_parser_process("start_filament_gcode", start_filament_gcode, new_extruder_id, &config);
|
||||||
check_add_eol(gcode);
|
check_add_eol(gcode);
|
||||||
}
|
}
|
||||||
// A phony move to the end position at the wipe tower.
|
// A phony move to the end position at the wipe tower.
|
||||||
@ -787,11 +789,17 @@ void GCode::_do_export(Print &print, FILE *file)
|
|||||||
// Wipe tower will control the extruder switching, it will call the start_filament_gcode.
|
// Wipe tower will control the extruder switching, it will call the start_filament_gcode.
|
||||||
} else {
|
} else {
|
||||||
// Only initialize the initial extruder.
|
// Only initialize the initial extruder.
|
||||||
_writeln(file, this->placeholder_parser_process("start_filament_gcode", print.config().start_filament_gcode.values[initial_extruder_id], initial_extruder_id));
|
DynamicConfig config;
|
||||||
|
config.set_key_value("filament_extruder_id", new ConfigOptionInt(int(initial_extruder_id)));
|
||||||
|
_writeln(file, this->placeholder_parser_process("start_filament_gcode", print.config().start_filament_gcode.values[initial_extruder_id], initial_extruder_id, &config));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (const std::string &start_gcode : print.config().start_filament_gcode.values)
|
DynamicConfig config;
|
||||||
_writeln(file, this->placeholder_parser_process("start_filament_gcode", start_gcode, (unsigned int)(&start_gcode - &print.config().start_filament_gcode.values.front())));
|
for (const std::string &start_gcode : print.config().start_filament_gcode.values) {
|
||||||
|
int extruder_id = (unsigned int)(&start_gcode - &print.config().start_filament_gcode.values.front());
|
||||||
|
config.set_key_value("filament_extruder_id", new ConfigOptionInt(extruder_id));
|
||||||
|
_writeln(file, this->placeholder_parser_process("start_filament_gcode", start_gcode, extruder_id, &config));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this->_print_first_layer_extruder_temperatures(file, print, start_gcode, initial_extruder_id, true);
|
this->_print_first_layer_extruder_temperatures(file, print, start_gcode, initial_extruder_id, true);
|
||||||
print.throw_if_canceled();
|
print.throw_if_canceled();
|
||||||
@ -809,7 +817,7 @@ void GCode::_do_export(Print &print, FILE *file)
|
|||||||
for (const ExPolygon &expoly : layer->slices.expolygons)
|
for (const ExPolygon &expoly : layer->slices.expolygons)
|
||||||
for (const Point © : object->copies()) {
|
for (const Point © : object->copies()) {
|
||||||
islands.emplace_back(expoly.contour);
|
islands.emplace_back(expoly.contour);
|
||||||
islands.back().translate(- copy);
|
islands.back().translate(copy);
|
||||||
}
|
}
|
||||||
//FIXME Mege the islands in parallel.
|
//FIXME Mege the islands in parallel.
|
||||||
m_avoid_crossing_perimeters.init_external_mp(union_ex(islands));
|
m_avoid_crossing_perimeters.init_external_mp(union_ex(islands));
|
||||||
@ -990,10 +998,15 @@ void GCode::_do_export(Print &print, FILE *file)
|
|||||||
config.set_key_value("layer_z", new ConfigOptionFloat(m_writer.get_position()(2) - m_config.z_offset.value));
|
config.set_key_value("layer_z", new ConfigOptionFloat(m_writer.get_position()(2) - m_config.z_offset.value));
|
||||||
if (print.config().single_extruder_multi_material) {
|
if (print.config().single_extruder_multi_material) {
|
||||||
// Process the end_filament_gcode for the active filament only.
|
// Process the end_filament_gcode for the active filament only.
|
||||||
_writeln(file, this->placeholder_parser_process("end_filament_gcode", print.config().end_filament_gcode.get_at(m_writer.extruder()->id()), m_writer.extruder()->id(), &config));
|
int extruder_id = m_writer.extruder()->id();
|
||||||
|
config.set_key_value("filament_extruder_id", new ConfigOptionInt(extruder_id));
|
||||||
|
_writeln(file, this->placeholder_parser_process("end_filament_gcode", print.config().end_filament_gcode.get_at(extruder_id), extruder_id, &config));
|
||||||
} else {
|
} else {
|
||||||
for (const std::string &end_gcode : print.config().end_filament_gcode.values)
|
for (const std::string &end_gcode : print.config().end_filament_gcode.values) {
|
||||||
_writeln(file, this->placeholder_parser_process("end_filament_gcode", end_gcode, (unsigned int)(&end_gcode - &print.config().end_filament_gcode.values.front()), &config));
|
int extruder_id = (unsigned int)(&end_gcode - &print.config().end_filament_gcode.values.front());
|
||||||
|
config.set_key_value("filament_extruder_id", new ConfigOptionInt(extruder_id));
|
||||||
|
_writeln(file, this->placeholder_parser_process("end_filament_gcode", end_gcode, extruder_id, &config));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_writeln(file, this->placeholder_parser_process("end_gcode", print.config().end_gcode, m_writer.extruder()->id(), &config));
|
_writeln(file, this->placeholder_parser_process("end_gcode", print.config().end_gcode, m_writer.extruder()->id(), &config));
|
||||||
}
|
}
|
||||||
|
@ -1194,7 +1194,7 @@ Vec3d extract_euler_angles(const Eigen::Matrix<double, 3, 3, Eigen::DontAlign>&
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
angles(1) = 0.0;
|
angles(0) = 0.0;
|
||||||
angles(1) = ::atan2(-rotation_matrix(2, 0), sy);
|
angles(1) = ::atan2(-rotation_matrix(2, 0), sy);
|
||||||
angles(2) = (angles(1) >-0.0) ? ::atan2(rotation_matrix(1, 2), rotation_matrix(1, 1)) : ::atan2(-rotation_matrix(1, 2), rotation_matrix(1, 1));
|
angles(2) = (angles(1) >-0.0) ? ::atan2(rotation_matrix(1, 2), rotation_matrix(1, 1)) : ::atan2(-rotation_matrix(1, 2), rotation_matrix(1, 1));
|
||||||
}
|
}
|
||||||
|
2
src/platform/unix/fhs.hpp.in
Normal file
2
src/platform/unix/fhs.hpp.in
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
#cmakedefine SLIC3R_FHS @SLIC3R_FHS@
|
||||||
|
#define SLIC3R_FHS_RESOURCES "@SLIC3R_FHS_RESOURCES@"
|
@ -22,6 +22,8 @@
|
|||||||
#include <boost/nowide/cenv.hpp>
|
#include <boost/nowide/cenv.hpp>
|
||||||
#include <boost/nowide/iostream.hpp>
|
#include <boost/nowide/iostream.hpp>
|
||||||
|
|
||||||
|
#include "unix/fhs.hpp" // Generated by CMake from ../platform/unix/fhs.hpp.in
|
||||||
|
|
||||||
#include "libslic3r/libslic3r.h"
|
#include "libslic3r/libslic3r.h"
|
||||||
#include "libslic3r/Config.hpp"
|
#include "libslic3r/Config.hpp"
|
||||||
#include "libslic3r/Geometry.hpp"
|
#include "libslic3r/Geometry.hpp"
|
||||||
@ -77,6 +79,10 @@ int main(int argc, char **argv)
|
|||||||
// The resources are packed to 'resources'
|
// The resources are packed to 'resources'
|
||||||
// Path from Slic3r binary to resources:
|
// Path from Slic3r binary to resources:
|
||||||
boost::filesystem::path path_resources = path_to_binary.parent_path() / "resources";
|
boost::filesystem::path path_resources = path_to_binary.parent_path() / "resources";
|
||||||
|
#elif defined SLIC3R_FHS
|
||||||
|
// The application is packaged according to the Linux Filesystem Hierarchy Standard
|
||||||
|
// Resources are set to the 'Architecture-independent (shared) data', typically /usr/share or /usr/local/share
|
||||||
|
boost::filesystem::path path_resources = SLIC3R_FHS_RESOURCES;
|
||||||
#else
|
#else
|
||||||
// The application is packed in the .tar.bz archive (or in AppImage) as 'bin/slic3r',
|
// The application is packed in the .tar.bz archive (or in AppImage) as 'bin/slic3r',
|
||||||
// The resources are packed to 'resources'
|
// The resources are packed to 'resources'
|
||||||
|
@ -66,12 +66,8 @@ void Field::PostInitialize()
|
|||||||
BUILD();
|
BUILD();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Field::on_kill_focus(wxEvent& event)
|
void Field::on_kill_focus()
|
||||||
{
|
{
|
||||||
// Without this, there will be nasty focus bugs on Windows.
|
|
||||||
// Also, docs for wxEvent::Skip() say "In general, it is recommended to skip all
|
|
||||||
// non-command events to allow the default handling to take place."
|
|
||||||
event.Skip();
|
|
||||||
// call the registered function if it is available
|
// call the registered function if it is available
|
||||||
if (m_on_kill_focus!=nullptr)
|
if (m_on_kill_focus!=nullptr)
|
||||||
m_on_kill_focus(m_opt_id);
|
m_on_kill_focus(m_opt_id);
|
||||||
@ -250,11 +246,23 @@ void TextCtrl::BUILD() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const long style = m_opt.multiline ? wxTE_MULTILINE : 0;
|
const long style = m_opt.multiline ? wxTE_MULTILINE : wxTE_PROCESS_ENTER/*0*/;
|
||||||
auto temp = new wxTextCtrl(m_parent, wxID_ANY, text_value, wxDefaultPosition, size, style);
|
auto temp = new wxTextCtrl(m_parent, wxID_ANY, text_value, wxDefaultPosition, size, style);
|
||||||
|
|
||||||
temp->SetToolTip(get_tooltip_text(text_value));
|
temp->SetToolTip(get_tooltip_text(text_value));
|
||||||
|
|
||||||
|
if (style == wxTE_PROCESS_ENTER) {
|
||||||
|
temp->Bind(wxEVT_TEXT_ENTER, ([this, temp](wxEvent& e)
|
||||||
|
{
|
||||||
|
#if !defined(__WXGTK__)
|
||||||
|
e.Skip();
|
||||||
|
temp->GetToolTip()->Enable(true);
|
||||||
|
#endif // __WXGTK__
|
||||||
|
propagate_value();
|
||||||
|
bEnterPressed = true;
|
||||||
|
}), temp->GetId());
|
||||||
|
}
|
||||||
|
|
||||||
temp->Bind(wxEVT_SET_FOCUS, ([this](wxEvent& e) { on_set_focus(e); }), temp->GetId());
|
temp->Bind(wxEVT_SET_FOCUS, ([this](wxEvent& e) { on_set_focus(e); }), temp->GetId());
|
||||||
|
|
||||||
temp->Bind(wxEVT_LEFT_DOWN, ([temp](wxEvent& event)
|
temp->Bind(wxEVT_LEFT_DOWN, ([temp](wxEvent& event)
|
||||||
@ -272,14 +280,15 @@ void TextCtrl::BUILD() {
|
|||||||
|
|
||||||
temp->Bind(wxEVT_KILL_FOCUS, ([this, temp](wxEvent& e)
|
temp->Bind(wxEVT_KILL_FOCUS, ([this, temp](wxEvent& e)
|
||||||
{
|
{
|
||||||
#if !defined(__WXGTK__)
|
|
||||||
e.Skip();
|
e.Skip();
|
||||||
|
#if !defined(__WXGTK__)
|
||||||
temp->GetToolTip()->Enable(true);
|
temp->GetToolTip()->Enable(true);
|
||||||
#endif // __WXGTK__
|
#endif // __WXGTK__
|
||||||
if (is_defined_input_value<wxTextCtrl>(window, m_opt.type))
|
if (bEnterPressed) {
|
||||||
on_change_field();
|
bEnterPressed = false;
|
||||||
else
|
return;
|
||||||
on_kill_focus(e);
|
}
|
||||||
|
propagate_value();
|
||||||
}), temp->GetId());
|
}), temp->GetId());
|
||||||
/*
|
/*
|
||||||
temp->Bind(wxEVT_TEXT, ([this](wxCommandEvent& evt)
|
temp->Bind(wxEVT_TEXT, ([this](wxCommandEvent& evt)
|
||||||
@ -311,6 +320,14 @@ void TextCtrl::BUILD() {
|
|||||||
window = dynamic_cast<wxWindow*>(temp);
|
window = dynamic_cast<wxWindow*>(temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TextCtrl::propagate_value()
|
||||||
|
{
|
||||||
|
if (is_defined_input_value<wxTextCtrl>(window, m_opt.type))
|
||||||
|
on_change_field();
|
||||||
|
else
|
||||||
|
on_kill_focus();
|
||||||
|
}
|
||||||
|
|
||||||
boost::any& TextCtrl::get_value()
|
boost::any& TextCtrl::get_value()
|
||||||
{
|
{
|
||||||
wxString ret_str = static_cast<wxTextCtrl*>(window)->GetValue();
|
wxString ret_str = static_cast<wxTextCtrl*>(window)->GetValue();
|
||||||
@ -398,7 +415,7 @@ void SpinCtrl::BUILD() {
|
|||||||
const int max_val = m_opt.max < 2147483647 ? m_opt.max : 2147483647;
|
const int max_val = m_opt.max < 2147483647 ? m_opt.max : 2147483647;
|
||||||
|
|
||||||
auto temp = new wxSpinCtrl(m_parent, wxID_ANY, text_value, wxDefaultPosition, size,
|
auto temp = new wxSpinCtrl(m_parent, wxID_ANY, text_value, wxDefaultPosition, size,
|
||||||
0, min_val, max_val, default_value);
|
0|wxTE_PROCESS_ENTER, min_val, max_val, default_value);
|
||||||
|
|
||||||
#ifndef __WXOSX__
|
#ifndef __WXOSX__
|
||||||
// #ys_FIXME_KILL_FOCUS
|
// #ys_FIXME_KILL_FOCUS
|
||||||
@ -407,15 +424,23 @@ void SpinCtrl::BUILD() {
|
|||||||
// and on TEXT event under OSX
|
// and on TEXT event under OSX
|
||||||
temp->Bind(wxEVT_KILL_FOCUS, ([this](wxEvent& e)
|
temp->Bind(wxEVT_KILL_FOCUS, ([this](wxEvent& e)
|
||||||
{
|
{
|
||||||
if (tmp_value < 0)
|
e.Skip();
|
||||||
on_kill_focus(e);
|
if (bEnterPressed) {
|
||||||
else {
|
bEnterPressed = false;
|
||||||
e.Skip();
|
return;
|
||||||
on_change_field();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
propagate_value();
|
||||||
}), temp->GetId());
|
}), temp->GetId());
|
||||||
|
|
||||||
temp->Bind(wxEVT_SPINCTRL, ([this](wxCommandEvent e) { on_change_field(); }), temp->GetId());
|
temp->Bind(wxEVT_SPINCTRL, ([this](wxCommandEvent e) { on_change_field(); }), temp->GetId());
|
||||||
|
|
||||||
|
temp->Bind(wxEVT_TEXT_ENTER, ([this](wxCommandEvent e)
|
||||||
|
{
|
||||||
|
e.Skip();
|
||||||
|
propagate_value();
|
||||||
|
bEnterPressed = true;
|
||||||
|
}), temp->GetId());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
temp->Bind(wxEVT_TEXT, ([this](wxCommandEvent e)
|
temp->Bind(wxEVT_TEXT, ([this](wxCommandEvent e)
|
||||||
@ -430,12 +455,7 @@ void SpinCtrl::BUILD() {
|
|||||||
tmp_value = std::stoi(value);
|
tmp_value = std::stoi(value);
|
||||||
else tmp_value = -9999;
|
else tmp_value = -9999;
|
||||||
#ifdef __WXOSX__
|
#ifdef __WXOSX__
|
||||||
if (tmp_value < 0) {
|
propagate_value();
|
||||||
if (m_on_kill_focus != nullptr)
|
|
||||||
m_on_kill_focus(m_opt_id);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
on_change_field();
|
|
||||||
#endif
|
#endif
|
||||||
}), temp->GetId());
|
}), temp->GetId());
|
||||||
|
|
||||||
@ -445,6 +465,14 @@ void SpinCtrl::BUILD() {
|
|||||||
window = dynamic_cast<wxWindow*>(temp);
|
window = dynamic_cast<wxWindow*>(temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SpinCtrl::propagate_value()
|
||||||
|
{
|
||||||
|
if (tmp_value < 0)
|
||||||
|
on_kill_focus();
|
||||||
|
else
|
||||||
|
on_change_field();
|
||||||
|
}
|
||||||
|
|
||||||
void Choice::BUILD() {
|
void Choice::BUILD() {
|
||||||
auto size = wxSize(wxDefaultSize);
|
auto size = wxSize(wxDefaultSize);
|
||||||
if (m_opt.height >= 0) size.SetHeight(m_opt.height);
|
if (m_opt.height >= 0) size.SetHeight(m_opt.height);
|
||||||
@ -474,6 +502,7 @@ void Choice::BUILD() {
|
|||||||
if (temp->GetWindowStyle() != wxCB_READONLY) {
|
if (temp->GetWindowStyle() != wxCB_READONLY) {
|
||||||
temp->Bind(wxEVT_KILL_FOCUS, ([this](wxEvent& e) {
|
temp->Bind(wxEVT_KILL_FOCUS, ([this](wxEvent& e) {
|
||||||
e.Skip();
|
e.Skip();
|
||||||
|
if (m_opt.type == coStrings) return;
|
||||||
double old_val = !m_value.empty() ? boost::any_cast<double>(m_value) : -99999;
|
double old_val = !m_value.empty() ? boost::any_cast<double>(m_value) : -99999;
|
||||||
if (is_defined_input_value<wxComboBox>(window, m_opt.type)) {
|
if (is_defined_input_value<wxComboBox>(window, m_opt.type)) {
|
||||||
if (fabs(old_val - boost::any_cast<double>(get_value())) <= 0.0001)
|
if (fabs(old_val - boost::any_cast<double>(get_value())) <= 0.0001)
|
||||||
@ -482,7 +511,7 @@ void Choice::BUILD() {
|
|||||||
on_change_field();
|
on_change_field();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
on_kill_focus(e);
|
on_kill_focus();
|
||||||
}), temp->GetId());
|
}), temp->GetId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -692,7 +721,7 @@ boost::any& Choice::get_value()
|
|||||||
}
|
}
|
||||||
else if (m_opt.gui_type == "f_enum_open") {
|
else if (m_opt.gui_type == "f_enum_open") {
|
||||||
const int ret_enum = static_cast<wxComboBox*>(window)->GetSelection();
|
const int ret_enum = static_cast<wxComboBox*>(window)->GetSelection();
|
||||||
if (ret_enum < 0 || m_opt.enum_values.empty())
|
if (ret_enum < 0 || m_opt.enum_values.empty() || m_opt.type == coStrings)
|
||||||
get_value_by_opt_type(ret_str);
|
get_value_by_opt_type(ret_str);
|
||||||
else
|
else
|
||||||
m_value = atof(m_opt.enum_values[ret_enum].c_str());
|
m_value = atof(m_opt.enum_values[ret_enum].c_str());
|
||||||
@ -754,8 +783,8 @@ void PointCtrl::BUILD()
|
|||||||
val = default_pt(1);
|
val = default_pt(1);
|
||||||
wxString Y = val - int(val) == 0 ? wxString::Format(_T("%i"), int(val)) : wxNumberFormatter::ToString(val, 2, wxNumberFormatter::Style_None);
|
wxString Y = val - int(val) == 0 ? wxString::Format(_T("%i"), int(val)) : wxNumberFormatter::ToString(val, 2, wxNumberFormatter::Style_None);
|
||||||
|
|
||||||
x_textctrl = new wxTextCtrl(m_parent, wxID_ANY, X, wxDefaultPosition, field_size);
|
x_textctrl = new wxTextCtrl(m_parent, wxID_ANY, X, wxDefaultPosition, field_size, wxEVT_TEXT_ENTER);
|
||||||
y_textctrl = new wxTextCtrl(m_parent, wxID_ANY, Y, wxDefaultPosition, field_size);
|
y_textctrl = new wxTextCtrl(m_parent, wxID_ANY, Y, wxDefaultPosition, field_size, wxEVT_TEXT_ENTER);
|
||||||
|
|
||||||
temp->Add(new wxStaticText(m_parent, wxID_ANY, "x : "), 0, wxALIGN_CENTER_VERTICAL, 0);
|
temp->Add(new wxStaticText(m_parent, wxID_ANY, "x : "), 0, wxALIGN_CENTER_VERTICAL, 0);
|
||||||
temp->Add(x_textctrl);
|
temp->Add(x_textctrl);
|
||||||
@ -765,8 +794,11 @@ void PointCtrl::BUILD()
|
|||||||
// x_textctrl->Bind(wxEVT_TEXT, ([this](wxCommandEvent e) { on_change_field(); }), x_textctrl->GetId());
|
// x_textctrl->Bind(wxEVT_TEXT, ([this](wxCommandEvent e) { on_change_field(); }), x_textctrl->GetId());
|
||||||
// y_textctrl->Bind(wxEVT_TEXT, ([this](wxCommandEvent e) { on_change_field(); }), y_textctrl->GetId());
|
// y_textctrl->Bind(wxEVT_TEXT, ([this](wxCommandEvent e) { on_change_field(); }), y_textctrl->GetId());
|
||||||
|
|
||||||
x_textctrl->Bind(wxEVT_KILL_FOCUS, ([this](wxEvent& e) { OnKillFocus(e, x_textctrl); }), x_textctrl->GetId());
|
x_textctrl->Bind(wxEVT_TEXT_ENTER, ([this](wxCommandEvent e) { propagate_value(x_textctrl); }), x_textctrl->GetId());
|
||||||
y_textctrl->Bind(wxEVT_KILL_FOCUS, ([this](wxEvent& e) { OnKillFocus(e, x_textctrl); }), y_textctrl->GetId());
|
y_textctrl->Bind(wxEVT_TEXT_ENTER, ([this](wxCommandEvent e) { propagate_value(y_textctrl); }), y_textctrl->GetId());
|
||||||
|
|
||||||
|
x_textctrl->Bind(wxEVT_KILL_FOCUS, ([this](wxEvent& e) { e.Skip(); propagate_value(x_textctrl); }), x_textctrl->GetId());
|
||||||
|
y_textctrl->Bind(wxEVT_KILL_FOCUS, ([this](wxEvent& e) { e.Skip(); propagate_value(y_textctrl); }), y_textctrl->GetId());
|
||||||
|
|
||||||
// // recast as a wxWindow to fit the calling convention
|
// // recast as a wxWindow to fit the calling convention
|
||||||
sizer = dynamic_cast<wxSizer*>(temp);
|
sizer = dynamic_cast<wxSizer*>(temp);
|
||||||
@ -775,14 +807,12 @@ void PointCtrl::BUILD()
|
|||||||
y_textctrl->SetToolTip(get_tooltip_text(X+", "+Y));
|
y_textctrl->SetToolTip(get_tooltip_text(X+", "+Y));
|
||||||
}
|
}
|
||||||
|
|
||||||
void PointCtrl::OnKillFocus(wxEvent& e, wxTextCtrl* win)
|
void PointCtrl::propagate_value(wxTextCtrl* win)
|
||||||
{
|
{
|
||||||
e.Skip();
|
if (!win->GetValue().empty())
|
||||||
if (!win->GetValue().empty()) {
|
|
||||||
on_change_field();
|
on_change_field();
|
||||||
}
|
|
||||||
else
|
else
|
||||||
on_kill_focus(e);
|
on_kill_focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PointCtrl::set_value(const Vec2d& value, bool change_event)
|
void PointCtrl::set_value(const Vec2d& value, bool change_event)
|
||||||
|
@ -74,7 +74,7 @@ protected:
|
|||||||
/// Call the attached on_kill_focus method.
|
/// Call the attached on_kill_focus method.
|
||||||
//! It's important to use wxEvent instead of wxFocusEvent,
|
//! It's important to use wxEvent instead of wxFocusEvent,
|
||||||
//! in another case we can't unfocused control at all
|
//! in another case we can't unfocused control at all
|
||||||
void on_kill_focus(wxEvent& event);
|
void on_kill_focus();
|
||||||
/// Call the attached on_change method.
|
/// Call the attached on_change method.
|
||||||
void on_set_focus(wxEvent& event);
|
void on_set_focus(wxEvent& event);
|
||||||
/// Call the attached on_change method.
|
/// Call the attached on_change method.
|
||||||
@ -226,6 +226,8 @@ protected:
|
|||||||
|
|
||||||
// current value
|
// current value
|
||||||
boost::any m_value;
|
boost::any m_value;
|
||||||
|
|
||||||
|
bool bEnterPressed = false;
|
||||||
|
|
||||||
friend class OptionsGroup;
|
friend class OptionsGroup;
|
||||||
};
|
};
|
||||||
@ -252,6 +254,8 @@ public:
|
|||||||
~TextCtrl() {}
|
~TextCtrl() {}
|
||||||
|
|
||||||
void BUILD();
|
void BUILD();
|
||||||
|
// Propagate value from field to the OptionGroupe and Config after kill_focus/ENTER
|
||||||
|
void propagate_value();
|
||||||
wxWindow* window {nullptr};
|
wxWindow* window {nullptr};
|
||||||
|
|
||||||
virtual void set_value(const std::string& value, bool change_event = false) {
|
virtual void set_value(const std::string& value, bool change_event = false) {
|
||||||
@ -310,6 +314,8 @@ public:
|
|||||||
|
|
||||||
wxWindow* window{ nullptr };
|
wxWindow* window{ nullptr };
|
||||||
void BUILD() override;
|
void BUILD() override;
|
||||||
|
/// Propagate value from field to the OptionGroupe and Config after kill_focus/ENTER
|
||||||
|
void propagate_value() ;
|
||||||
|
|
||||||
void set_value(const std::string& value, bool change_event = false) {
|
void set_value(const std::string& value, bool change_event = false) {
|
||||||
m_disable_change_event = !change_event;
|
m_disable_change_event = !change_event;
|
||||||
@ -393,8 +399,8 @@ public:
|
|||||||
wxTextCtrl* y_textctrl{ nullptr };
|
wxTextCtrl* y_textctrl{ nullptr };
|
||||||
|
|
||||||
void BUILD() override;
|
void BUILD() override;
|
||||||
|
// Propagate value from field to the OptionGroupe and Config after kill_focus/ENTER
|
||||||
void OnKillFocus(wxEvent& e, wxTextCtrl* win);
|
void propagate_value(wxTextCtrl* win);
|
||||||
void set_value(const Vec2d& value, bool change_event = false);
|
void set_value(const Vec2d& value, bool change_event = false);
|
||||||
void set_value(const boost::any& value, bool change_event = false);
|
void set_value(const boost::any& value, bool change_event = false);
|
||||||
boost::any& get_value() override;
|
boost::any& get_value() override;
|
||||||
|
@ -2513,7 +2513,9 @@ void GLCanvas3D::Selection::_render_sidebar_rotation_hints(const std::string& si
|
|||||||
|
|
||||||
void GLCanvas3D::Selection::_render_sidebar_scale_hints(const std::string& sidebar_field) const
|
void GLCanvas3D::Selection::_render_sidebar_scale_hints(const std::string& sidebar_field) const
|
||||||
{
|
{
|
||||||
if (boost::ends_with(sidebar_field, "x") || requires_uniform_scale())
|
bool uniform_scale = requires_uniform_scale() || wxGetApp().obj_manipul()->get_uniform_scaling();
|
||||||
|
|
||||||
|
if (boost::ends_with(sidebar_field, "x") || uniform_scale)
|
||||||
{
|
{
|
||||||
::glPushMatrix();
|
::glPushMatrix();
|
||||||
::glRotated(-90.0, 0.0, 0.0, 1.0);
|
::glRotated(-90.0, 0.0, 0.0, 1.0);
|
||||||
@ -2521,14 +2523,14 @@ void GLCanvas3D::Selection::_render_sidebar_scale_hints(const std::string& sideb
|
|||||||
::glPopMatrix();
|
::glPopMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (boost::ends_with(sidebar_field, "y") || requires_uniform_scale())
|
if (boost::ends_with(sidebar_field, "y") || uniform_scale)
|
||||||
{
|
{
|
||||||
::glPushMatrix();
|
::glPushMatrix();
|
||||||
_render_sidebar_scale_hint(Y);
|
_render_sidebar_scale_hint(Y);
|
||||||
::glPopMatrix();
|
::glPopMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (boost::ends_with(sidebar_field, "z") || requires_uniform_scale())
|
if (boost::ends_with(sidebar_field, "z") || uniform_scale)
|
||||||
{
|
{
|
||||||
::glPushMatrix();
|
::glPushMatrix();
|
||||||
::glRotated(90.0, 1.0, 0.0, 0.0);
|
::glRotated(90.0, 1.0, 0.0, 0.0);
|
||||||
@ -2559,7 +2561,7 @@ void GLCanvas3D::Selection::_render_sidebar_rotation_hint(Axis axis) const
|
|||||||
|
|
||||||
void GLCanvas3D::Selection::_render_sidebar_scale_hint(Axis axis) const
|
void GLCanvas3D::Selection::_render_sidebar_scale_hint(Axis axis) const
|
||||||
{
|
{
|
||||||
m_arrow.set_color((requires_uniform_scale() ? UNIFORM_SCALE_COLOR : AXES_COLOR[axis]), 3);
|
m_arrow.set_color(((requires_uniform_scale() || wxGetApp().obj_manipul()->get_uniform_scaling()) ? UNIFORM_SCALE_COLOR : AXES_COLOR[axis]), 3);
|
||||||
|
|
||||||
::glTranslated(0.0, 5.0, 0.0);
|
::glTranslated(0.0, 5.0, 0.0);
|
||||||
m_arrow.render();
|
m_arrow.render();
|
||||||
@ -3979,6 +3981,12 @@ BoundingBoxf3 GLCanvas3D::scene_bounding_box() const
|
|||||||
{
|
{
|
||||||
BoundingBoxf3 bb = volumes_bounding_box();
|
BoundingBoxf3 bb = volumes_bounding_box();
|
||||||
bb.merge(m_bed.get_bounding_box());
|
bb.merge(m_bed.get_bounding_box());
|
||||||
|
if (m_config != nullptr)
|
||||||
|
{
|
||||||
|
double h = m_config->opt_float("max_print_height");
|
||||||
|
bb.min(2) = std::min(bb.min(2), -h);
|
||||||
|
bb.max(2) = std::max(bb.max(2), h);
|
||||||
|
}
|
||||||
return bb;
|
return bb;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4939,8 +4947,9 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
|||||||
|
|
||||||
if (evt.Entering())
|
if (evt.Entering())
|
||||||
{
|
{
|
||||||
#if defined(__WXMSW__) || defined(__linux__)
|
//#if defined(__WXMSW__) || defined(__linux__)
|
||||||
// On Windows and Linux needs focus in order to catch key events
|
// // On Windows and Linux needs focus in order to catch key events
|
||||||
|
// Set focus in order to remove it from sidebar fields
|
||||||
if (m_canvas != nullptr) {
|
if (m_canvas != nullptr) {
|
||||||
// Only set focus, if the top level window of this canvas is active.
|
// Only set focus, if the top level window of this canvas is active.
|
||||||
auto p = dynamic_cast<wxWindow*>(evt.GetEventObject());
|
auto p = dynamic_cast<wxWindow*>(evt.GetEventObject());
|
||||||
@ -4952,7 +4961,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_mouse.set_start_position_2D_as_invalid();
|
m_mouse.set_start_position_2D_as_invalid();
|
||||||
#endif
|
//#endif
|
||||||
}
|
}
|
||||||
else if (evt.Leaving())
|
else if (evt.Leaving())
|
||||||
{
|
{
|
||||||
|
@ -1523,7 +1523,7 @@ void GLGizmoFlatten::update_planes()
|
|||||||
const Transform3d& inst_matrix = m_model_object->instances.front()->get_matrix();
|
const Transform3d& inst_matrix = m_model_object->instances.front()->get_matrix();
|
||||||
|
|
||||||
// Following constants are used for discarding too small polygons.
|
// Following constants are used for discarding too small polygons.
|
||||||
const float minimal_area = 20.f; // in square mm (world coordinates)
|
const float minimal_area = 5.f; // in square mm (world coordinates)
|
||||||
const float minimal_side = 1.f; // mm
|
const float minimal_side = 1.f; // mm
|
||||||
|
|
||||||
// Now we'll go through all the facets and append Points of facets sharing the same normal.
|
// Now we'll go through all the facets and append Points of facets sharing the same normal.
|
||||||
|
@ -148,19 +148,21 @@ void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt
|
|||||||
config.set_key_value(opt_key, new ConfigOptionString(boost::any_cast<std::string>(value)));
|
config.set_key_value(opt_key, new ConfigOptionString(boost::any_cast<std::string>(value)));
|
||||||
break;
|
break;
|
||||||
case coStrings:{
|
case coStrings:{
|
||||||
if (opt_key == "compatible_prints" || opt_key == "compatible_printers" || opt_key == "post_process") {
|
if (opt_key == "compatible_prints" || opt_key == "compatible_printers") {
|
||||||
config.option<ConfigOptionStrings>(opt_key)->values =
|
config.option<ConfigOptionStrings>(opt_key)->values =
|
||||||
boost::any_cast<std::vector<std::string>>(value);
|
boost::any_cast<std::vector<std::string>>(value);
|
||||||
}
|
}
|
||||||
else if (config.def()->get(opt_key)->gui_flags.compare("serialized") == 0) {
|
else if (config.def()->get(opt_key)->gui_flags.compare("serialized") == 0) {
|
||||||
std::string str = boost::any_cast<std::string>(value);
|
std::string str = boost::any_cast<std::string>(value);
|
||||||
if (str.back() == ';') str.pop_back();
|
std::vector<std::string> values {};
|
||||||
// Split a string to multiple strings by a semi - colon.This is the old way of storing multi - string values.
|
if (!str.empty()) {
|
||||||
// Currently used for the post_process config value only.
|
if (str.back() == ';') str.pop_back();
|
||||||
std::vector<std::string> values;
|
// Split a string to multiple strings by a semi - colon.This is the old way of storing multi - string values.
|
||||||
boost::split(values, str, boost::is_any_of(";"));
|
// Currently used for the post_process config value only.
|
||||||
if (values.size() == 1 && values[0] == "")
|
boost::split(values, str, boost::is_any_of(";"));
|
||||||
values.resize(0);//break;
|
if (values.size() == 1 && values[0] == "")
|
||||||
|
values.resize(0);
|
||||||
|
}
|
||||||
config.option<ConfigOptionStrings>(opt_key)->values = values;
|
config.option<ConfigOptionStrings>(opt_key)->values = values;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
#include <boost/algorithm/string.hpp>
|
#include <boost/algorithm/string.hpp>
|
||||||
#include <boost/filesystem.hpp>
|
|
||||||
|
|
||||||
#include <wx/stdpaths.h>
|
#include <wx/stdpaths.h>
|
||||||
#include <wx/imagpng.h>
|
#include <wx/imagpng.h>
|
||||||
@ -15,6 +14,7 @@
|
|||||||
#include <wx/filedlg.h>
|
#include <wx/filedlg.h>
|
||||||
#include <wx/dir.h>
|
#include <wx/dir.h>
|
||||||
#include <wx/wupdlock.h>
|
#include <wx/wupdlock.h>
|
||||||
|
#include <wx/filefn.h>
|
||||||
|
|
||||||
#include "libslic3r/Utils.hpp"
|
#include "libslic3r/Utils.hpp"
|
||||||
#include "libslic3r/Model.hpp"
|
#include "libslic3r/Model.hpp"
|
||||||
@ -83,6 +83,11 @@ GUI_App::GUI_App()
|
|||||||
|
|
||||||
bool GUI_App::OnInit()
|
bool GUI_App::OnInit()
|
||||||
{
|
{
|
||||||
|
// Verify resources path
|
||||||
|
const wxString resources_dir = from_u8(Slic3r::resources_dir());
|
||||||
|
wxCHECK_MSG(wxDirExists(resources_dir), false,
|
||||||
|
wxString::Format("Resources path does not exist or is not a directory: %s", resources_dir));
|
||||||
|
|
||||||
#if ENABLE_IMGUI
|
#if ENABLE_IMGUI
|
||||||
wxCHECK_MSG(m_imgui->init(), false, "Failed to initialize ImGui");
|
wxCHECK_MSG(m_imgui->init(), false, "Failed to initialize ImGui");
|
||||||
#endif // ENABLE_IMGUI
|
#endif // ENABLE_IMGUI
|
||||||
|
@ -635,7 +635,7 @@ void ObjectList::get_settings_choice(const wxString& category_name)
|
|||||||
// Add settings item for object
|
// Add settings item for object
|
||||||
const auto item = GetSelection();
|
const auto item = GetSelection();
|
||||||
if (item) {
|
if (item) {
|
||||||
const auto settings_item = m_objects_model->GetSettingsItem(item);
|
const auto settings_item = m_objects_model->IsSettingsItem(item) ? item : m_objects_model->GetSettingsItem(item);
|
||||||
select_item(settings_item ? settings_item :
|
select_item(settings_item ? settings_item :
|
||||||
m_objects_model->AddSettingsChild(item));
|
m_objects_model->AddSettingsChild(item));
|
||||||
}
|
}
|
||||||
@ -849,7 +849,7 @@ void ObjectList::load_part( ModelObject* model_object,
|
|||||||
new_volume->set_type(static_cast<ModelVolume::Type>(type));
|
new_volume->set_type(static_cast<ModelVolume::Type>(type));
|
||||||
new_volume->name = boost::filesystem::path(input_file).filename().string();
|
new_volume->name = boost::filesystem::path(input_file).filename().string();
|
||||||
|
|
||||||
part_names.Add(new_volume->name);
|
part_names.Add(from_u8(new_volume->name));
|
||||||
|
|
||||||
// set a default extruder value, since user can't add it manually
|
// set a default extruder value, since user can't add it manually
|
||||||
new_volume->config.set_key_value("extruder", new ConfigOptionInt(0));
|
new_volume->config.set_key_value("extruder", new ConfigOptionInt(0));
|
||||||
@ -903,7 +903,7 @@ void ObjectList::load_generic_subobject(const std::string& type_name, const int
|
|||||||
m_parts_changed = true;
|
m_parts_changed = true;
|
||||||
parts_changed(obj_idx);
|
parts_changed(obj_idx);
|
||||||
|
|
||||||
select_item(m_objects_model->AddVolumeChild(GetSelection(), name, type));
|
select_item(m_objects_model->AddVolumeChild(GetSelection(), from_u8(name), type));
|
||||||
#ifndef __WXOSX__ //#ifdef __WXMSW__ // #ys_FIXME
|
#ifndef __WXOSX__ //#ifdef __WXMSW__ // #ys_FIXME
|
||||||
selection_changed();
|
selection_changed();
|
||||||
#endif //no __WXOSX__ //__WXMSW__
|
#endif //no __WXOSX__ //__WXMSW__
|
||||||
@ -1031,7 +1031,7 @@ void ObjectList::split()
|
|||||||
parent = item;
|
parent = item;
|
||||||
|
|
||||||
for (auto id = 0; id < model_object->volumes.size(); id++) {
|
for (auto id = 0; id < model_object->volumes.size(); id++) {
|
||||||
const auto vol_item = m_objects_model->AddVolumeChild(parent, model_object->volumes[id]->name,
|
const auto vol_item = m_objects_model->AddVolumeChild(parent, from_u8(model_object->volumes[id]->name),
|
||||||
model_object->volumes[id]->is_modifier() ?
|
model_object->volumes[id]->is_modifier() ?
|
||||||
ModelVolume::PARAMETER_MODIFIER : ModelVolume::MODEL_PART,
|
ModelVolume::PARAMETER_MODIFIER : ModelVolume::MODEL_PART,
|
||||||
model_object->volumes[id]->config.has("extruder") ?
|
model_object->volumes[id]->config.has("extruder") ?
|
||||||
@ -1188,7 +1188,7 @@ void ObjectList::part_selection_changed()
|
|||||||
void ObjectList::add_object_to_list(size_t obj_idx)
|
void ObjectList::add_object_to_list(size_t obj_idx)
|
||||||
{
|
{
|
||||||
auto model_object = (*m_objects)[obj_idx];
|
auto model_object = (*m_objects)[obj_idx];
|
||||||
wxString item_name = model_object->name;
|
wxString item_name = from_u8(model_object->name);
|
||||||
const auto item = m_objects_model->Add(item_name,
|
const auto item = m_objects_model->Add(item_name,
|
||||||
!model_object->config.has("extruder") ? 0 :
|
!model_object->config.has("extruder") ? 0 :
|
||||||
model_object->config.option<ConfigOptionInt>("extruder")->value);
|
model_object->config.option<ConfigOptionInt>("extruder")->value);
|
||||||
@ -1207,8 +1207,8 @@ void ObjectList::add_object_to_list(size_t obj_idx)
|
|||||||
if (model_object->volumes.size() > 1) {
|
if (model_object->volumes.size() > 1) {
|
||||||
for (auto id = 0; id < model_object->volumes.size(); id++) {
|
for (auto id = 0; id < model_object->volumes.size(); id++) {
|
||||||
auto vol_item = m_objects_model->AddVolumeChild(item,
|
auto vol_item = m_objects_model->AddVolumeChild(item,
|
||||||
model_object->volumes[id]->name,
|
from_u8(model_object->volumes[id]->name),
|
||||||
model_object->volumes[id]->type()/*ModelVolume::MODEL_PART*/,
|
model_object->volumes[id]->type(),
|
||||||
!model_object->volumes[id]->config.has("extruder") ? 0 :
|
!model_object->volumes[id]->config.has("extruder") ? 0 :
|
||||||
model_object->volumes[id]->config.option<ConfigOptionInt>("extruder")->value,
|
model_object->volumes[id]->config.option<ConfigOptionInt>("extruder")->value,
|
||||||
false);
|
false);
|
||||||
|
@ -17,15 +17,9 @@ namespace GUI
|
|||||||
|
|
||||||
ObjectManipulation::ObjectManipulation(wxWindow* parent) :
|
ObjectManipulation::ObjectManipulation(wxWindow* parent) :
|
||||||
OG_Settings(parent, true)
|
OG_Settings(parent, true)
|
||||||
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
|
||||||
, m_cache_position(Vec3d(DBL_MAX, DBL_MAX, DBL_MAX))
|
|
||||||
, m_cache_rotation(Vec3d(DBL_MAX, DBL_MAX, DBL_MAX))
|
|
||||||
, m_cache_scale(Vec3d(DBL_MAX, DBL_MAX, DBL_MAX))
|
|
||||||
, m_cache_size(Vec3d(DBL_MAX, DBL_MAX, DBL_MAX))
|
|
||||||
#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
|
||||||
{
|
{
|
||||||
m_og->set_name(_(L("Object Manipulation")));
|
m_og->set_name(_(L("Object Manipulation")));
|
||||||
m_og->label_width = 100;
|
m_og->label_width = 125;
|
||||||
m_og->set_grid_vgap(5);
|
m_og->set_grid_vgap(5);
|
||||||
|
|
||||||
m_og->m_on_change = [this](const std::string& opt_key, const boost::any& value) {
|
m_og->m_on_change = [this](const std::string& opt_key, const boost::any& value) {
|
||||||
@ -80,25 +74,41 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
|
|||||||
int axis = opt_key.back() == 'x' ? 0 :
|
int axis = opt_key.back() == 'x' ? 0 :
|
||||||
opt_key.back() == 'y' ? 1 : 2;
|
opt_key.back() == 'y' ? 1 : 2;
|
||||||
|
|
||||||
|
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||||
|
value = m_cache.position(axis);
|
||||||
|
#else
|
||||||
value = m_cache_position(axis);
|
value = m_cache_position(axis);
|
||||||
|
#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||||
}
|
}
|
||||||
else if (param == "rotation") {
|
else if (param == "rotation") {
|
||||||
int axis = opt_key.back() == 'x' ? 0 :
|
int axis = opt_key.back() == 'x' ? 0 :
|
||||||
opt_key.back() == 'y' ? 1 : 2;
|
opt_key.back() == 'y' ? 1 : 2;
|
||||||
|
|
||||||
|
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||||
|
value = m_cache.rotation(axis);
|
||||||
|
#else
|
||||||
value = m_cache_rotation(axis);
|
value = m_cache_rotation(axis);
|
||||||
|
#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||||
}
|
}
|
||||||
else if (param == "scale") {
|
else if (param == "scale") {
|
||||||
int axis = opt_key.back() == 'x' ? 0 :
|
int axis = opt_key.back() == 'x' ? 0 :
|
||||||
opt_key.back() == 'y' ? 1 : 2;
|
opt_key.back() == 'y' ? 1 : 2;
|
||||||
|
|
||||||
|
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||||
|
value = m_cache.scale(axis);
|
||||||
|
#else
|
||||||
value = m_cache_scale(axis);
|
value = m_cache_scale(axis);
|
||||||
|
#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||||
}
|
}
|
||||||
else if (param == "size") {
|
else if (param == "size") {
|
||||||
int axis = opt_key.back() == 'x' ? 0 :
|
int axis = opt_key.back() == 'x' ? 0 :
|
||||||
opt_key.back() == 'y' ? 1 : 2;
|
opt_key.back() == 'y' ? 1 : 2;
|
||||||
|
|
||||||
|
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||||
|
value = m_cache.size(axis);
|
||||||
|
#else
|
||||||
value = m_cache_size(axis);
|
value = m_cache_size(axis);
|
||||||
|
#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||||
}
|
}
|
||||||
|
|
||||||
m_og->set_value(opt_key, double_to_string(value));
|
m_og->set_value(opt_key, double_to_string(value));
|
||||||
@ -140,7 +150,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
|
|||||||
m_og->append_line(line);
|
m_og->append_line(line);
|
||||||
|
|
||||||
|
|
||||||
auto add_og_to_object_settings = [](const std::string& option_name, const std::string& sidetext)
|
auto add_og_to_object_settings = [this](const std::string& option_name, const std::string& sidetext)
|
||||||
{
|
{
|
||||||
Line line = { _(option_name), "" };
|
Line line = { _(option_name), "" };
|
||||||
ConfigOptionDef def;
|
ConfigOptionDef def;
|
||||||
@ -154,6 +164,26 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
|
|||||||
def.max = 360;
|
def.max = 360;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add "uniform scaling" button in front of "Scale" option
|
||||||
|
else if (option_name == "Scale") {
|
||||||
|
line.near_label_widget = [this](wxWindow* parent) {
|
||||||
|
auto btn = new PrusaLockButton(parent, wxID_ANY);
|
||||||
|
btn->Bind(wxEVT_BUTTON, [btn, this](wxCommandEvent &event){
|
||||||
|
event.Skip();
|
||||||
|
wxTheApp->CallAfter([btn, this]() { set_uniform_scaling(btn->IsLocked()); });
|
||||||
|
});
|
||||||
|
return btn;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add empty bmp (Its size have to be equal to PrusaLockButton) in front of "Size" option to label alignment
|
||||||
|
else if (option_name == "Size") {
|
||||||
|
line.near_label_widget = [this](wxWindow* parent) {
|
||||||
|
return new wxStaticBitmap(parent, wxID_ANY, wxNullBitmap, wxDefaultPosition,
|
||||||
|
wxBitmap(from_u8(var("one_layer_lock_on.png")), wxBITMAP_TYPE_PNG).GetSize());
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const std::string lower_name = boost::algorithm::to_lower_copy(option_name);
|
const std::string lower_name = boost::algorithm::to_lower_copy(option_name);
|
||||||
|
|
||||||
std::vector<std::string> axes{ "x", "y", "z" };
|
std::vector<std::string> axes{ "x", "y", "z" };
|
||||||
@ -229,16 +259,38 @@ void ObjectManipulation::update_settings_value(const GLCanvas3D::Selection& sele
|
|||||||
m_new_rotation = volume->get_instance_rotation();
|
m_new_rotation = volume->get_instance_rotation();
|
||||||
m_new_scale = volume->get_instance_scaling_factor();
|
m_new_scale = volume->get_instance_scaling_factor();
|
||||||
int obj_idx = volume->object_idx();
|
int obj_idx = volume->object_idx();
|
||||||
|
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||||
|
int instance_idx = volume->instance_idx();
|
||||||
|
if ((0 <= obj_idx) && (obj_idx < (int)wxGetApp().model_objects()->size()))
|
||||||
|
{
|
||||||
|
bool changed_box = false;
|
||||||
|
if (!m_cache.instance.matches_object(obj_idx))
|
||||||
|
{
|
||||||
|
m_cache.instance.set(obj_idx, instance_idx, (*wxGetApp().model_objects())[obj_idx]->raw_mesh().bounding_box().size());
|
||||||
|
changed_box = true;
|
||||||
|
}
|
||||||
|
if (changed_box || !m_cache.instance.matches_instance(instance_idx) || !m_cache.scale.isApprox(100.0 * m_new_scale))
|
||||||
|
m_new_size = volume->get_instance_transformation().get_matrix(true, true) * m_cache.instance.box_size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
// this should never happen
|
||||||
|
m_new_size = Vec3d::Zero();
|
||||||
|
#else
|
||||||
if ((0 <= obj_idx) && (obj_idx < (int)wxGetApp().model_objects()->size()))
|
if ((0 <= obj_idx) && (obj_idx < (int)wxGetApp().model_objects()->size()))
|
||||||
m_new_size = volume->get_instance_transformation().get_matrix(true, true) * (*wxGetApp().model_objects())[obj_idx]->raw_mesh().bounding_box().size();
|
m_new_size = volume->get_instance_transformation().get_matrix(true, true) * (*wxGetApp().model_objects())[obj_idx]->raw_mesh().bounding_box().size();
|
||||||
else
|
else
|
||||||
// this should never happen
|
// this should never happen
|
||||||
m_new_size = Vec3d::Zero();
|
m_new_size = Vec3d::Zero();
|
||||||
|
#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||||
|
|
||||||
m_new_enabled = true;
|
m_new_enabled = true;
|
||||||
}
|
}
|
||||||
else if (selection.is_single_full_object())
|
else if (selection.is_single_full_object())
|
||||||
{
|
{
|
||||||
|
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||||
|
m_cache.instance.reset();
|
||||||
|
#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||||
|
|
||||||
const BoundingBoxf3& box = selection.get_bounding_box();
|
const BoundingBoxf3& box = selection.get_bounding_box();
|
||||||
m_new_position = box.center();
|
m_new_position = box.center();
|
||||||
m_new_rotation = Vec3d::Zero();
|
m_new_rotation = Vec3d::Zero();
|
||||||
@ -250,6 +302,10 @@ void ObjectManipulation::update_settings_value(const GLCanvas3D::Selection& sele
|
|||||||
}
|
}
|
||||||
else if (selection.is_single_modifier() || selection.is_single_volume())
|
else if (selection.is_single_modifier() || selection.is_single_volume())
|
||||||
{
|
{
|
||||||
|
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||||
|
m_cache.instance.reset();
|
||||||
|
#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||||
|
|
||||||
// the selection contains a single volume
|
// the selection contains a single volume
|
||||||
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
|
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
|
||||||
m_new_position = volume->get_volume_offset();
|
m_new_position = volume->get_volume_offset();
|
||||||
@ -280,59 +336,71 @@ void ObjectManipulation::update_settings_value(const GLCanvas3D::Selection& sele
|
|||||||
void ObjectManipulation::update_if_dirty()
|
void ObjectManipulation::update_if_dirty()
|
||||||
{
|
{
|
||||||
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||||
if (_(m_new_move_label_string) != m_move_Label->GetLabel())
|
if (m_cache.move_label_string != _(m_new_move_label_string))
|
||||||
m_move_Label->SetLabel(_(m_new_move_label_string));
|
{
|
||||||
|
m_cache.move_label_string = _(m_new_move_label_string);
|
||||||
|
m_move_Label->SetLabel(m_cache.move_label_string);
|
||||||
|
}
|
||||||
|
|
||||||
if (_(m_new_rotate_label_string) != m_rotate_Label->GetLabel())
|
if (m_cache.rotate_label_string != _(m_new_rotate_label_string))
|
||||||
m_rotate_Label->SetLabel(_(m_new_rotate_label_string));
|
{
|
||||||
|
m_cache.rotate_label_string = _(m_new_rotate_label_string);
|
||||||
|
m_rotate_Label->SetLabel(m_cache.rotate_label_string);
|
||||||
|
}
|
||||||
|
|
||||||
if (_(m_new_scale_label_string) != m_scale_Label->GetLabel())
|
if (m_cache.scale_label_string != _(m_new_scale_label_string))
|
||||||
m_scale_Label->SetLabel(_(m_new_scale_label_string));
|
{
|
||||||
|
m_cache.scale_label_string = _(m_new_scale_label_string);
|
||||||
|
m_scale_Label->SetLabel(m_cache.scale_label_string);
|
||||||
|
}
|
||||||
|
|
||||||
if (m_cache_position(0) != m_new_position(0))
|
if (m_cache.position(0) != m_new_position(0))
|
||||||
m_og->set_value("position_x", double_to_string(m_new_position(0), 2));
|
m_og->set_value("position_x", double_to_string(m_new_position(0), 2));
|
||||||
|
|
||||||
if (m_cache_position(1) != m_new_position(1))
|
if (m_cache.position(1) != m_new_position(1))
|
||||||
m_og->set_value("position_y", double_to_string(m_new_position(1), 2));
|
m_og->set_value("position_y", double_to_string(m_new_position(1), 2));
|
||||||
|
|
||||||
if (m_cache_position(2) != m_new_position(2))
|
if (m_cache.position(2) != m_new_position(2))
|
||||||
m_og->set_value("position_z", double_to_string(m_new_position(2), 2));
|
m_og->set_value("position_z", double_to_string(m_new_position(2), 2));
|
||||||
|
|
||||||
m_cache_position = m_new_position;
|
m_cache.position = m_new_position;
|
||||||
|
|
||||||
auto scale = m_new_scale * 100.0;
|
auto scale = m_new_scale * 100.0;
|
||||||
if (m_cache_scale(0) != scale(0))
|
if (m_cache.scale(0) != scale(0))
|
||||||
m_og->set_value("scale_x", double_to_string(scale(0), 2));
|
m_og->set_value("scale_x", double_to_string(scale(0), 2));
|
||||||
|
|
||||||
if (m_cache_scale(1) != scale(1))
|
if (m_cache.scale(1) != scale(1))
|
||||||
m_og->set_value("scale_y", double_to_string(scale(1), 2));
|
m_og->set_value("scale_y", double_to_string(scale(1), 2));
|
||||||
|
|
||||||
if (m_cache_scale(2) != scale(2))
|
if (m_cache.scale(2) != scale(2))
|
||||||
m_og->set_value("scale_z", double_to_string(scale(2), 2));
|
m_og->set_value("scale_z", double_to_string(scale(2), 2));
|
||||||
|
|
||||||
m_cache_scale = scale;
|
m_cache.scale = scale;
|
||||||
|
|
||||||
if (m_cache_size(0) != m_new_size(0))
|
if (m_cache.size(0) != m_new_size(0))
|
||||||
m_og->set_value("size_x", double_to_string(m_new_size(0), 2));
|
m_og->set_value("size_x", double_to_string(m_new_size(0), 2));
|
||||||
|
|
||||||
if (m_cache_size(1) != m_new_size(1))
|
if (m_cache.size(1) != m_new_size(1))
|
||||||
m_og->set_value("size_y", double_to_string(m_new_size(1), 2));
|
m_og->set_value("size_y", double_to_string(m_new_size(1), 2));
|
||||||
|
|
||||||
if (m_cache_size(2) != m_new_size(2))
|
if (m_cache.size(2) != m_new_size(2))
|
||||||
m_og->set_value("size_z", double_to_string(m_new_size(2), 2));
|
m_og->set_value("size_z", double_to_string(m_new_size(2), 2));
|
||||||
|
|
||||||
m_cache_size = m_new_size;
|
m_cache.size = m_new_size;
|
||||||
|
|
||||||
if (m_cache_rotation(0) != m_new_rotation(0))
|
if (m_cache.rotation(0) != m_new_rotation(0))
|
||||||
m_og->set_value("rotation_x", double_to_string(round_nearest(Geometry::rad2deg(m_new_rotation(0)), 0), 2));
|
m_og->set_value("rotation_x", double_to_string(round_nearest(Geometry::rad2deg(m_new_rotation(0)), 0), 2));
|
||||||
|
|
||||||
if (m_cache_rotation(1) != m_new_rotation(1))
|
if (m_cache.rotation(1) != m_new_rotation(1))
|
||||||
m_og->set_value("rotation_y", double_to_string(round_nearest(Geometry::rad2deg(m_new_rotation(1)), 0), 2));
|
m_og->set_value("rotation_y", double_to_string(round_nearest(Geometry::rad2deg(m_new_rotation(1)), 0), 2));
|
||||||
|
|
||||||
if (m_cache_rotation(2) != m_new_rotation(2))
|
if (m_cache.rotation(2) != m_new_rotation(2))
|
||||||
m_og->set_value("rotation_z", double_to_string(round_nearest(Geometry::rad2deg(m_new_rotation(2)), 0), 2));
|
m_og->set_value("rotation_z", double_to_string(round_nearest(Geometry::rad2deg(m_new_rotation(2)), 0), 2));
|
||||||
|
|
||||||
m_cache_rotation = m_new_rotation;
|
m_cache.rotation = m_new_rotation;
|
||||||
|
|
||||||
|
// if (wxGetApp().plater()->canvas3D()->get_selection().requires_uniform_scale())
|
||||||
|
// m_uniform_scale = true;
|
||||||
|
|
||||||
if (m_new_enabled)
|
if (m_new_enabled)
|
||||||
m_og->enable();
|
m_og->enable();
|
||||||
@ -378,11 +446,14 @@ void ObjectManipulation::update_if_dirty()
|
|||||||
|
|
||||||
void ObjectManipulation::reset_settings_value()
|
void ObjectManipulation::reset_settings_value()
|
||||||
{
|
{
|
||||||
m_new_position = Vec3d::Zero();
|
m_new_position = Vec3d::Zero();
|
||||||
m_new_rotation = Vec3d::Zero();
|
m_new_rotation = Vec3d::Zero();
|
||||||
m_new_scale = Vec3d::Ones();
|
m_new_scale = Vec3d::Ones();
|
||||||
m_new_size = Vec3d::Zero();
|
m_new_size = Vec3d::Zero();
|
||||||
m_new_enabled = false;
|
m_new_enabled = false;
|
||||||
|
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||||
|
m_cache.instance.reset();
|
||||||
|
#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||||
#if !ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
#if !ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||||
m_dirty = true;
|
m_dirty = true;
|
||||||
#endif // !ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
#endif // !ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||||
@ -393,10 +464,18 @@ void ObjectManipulation::change_position_value(const Vec3d& position)
|
|||||||
auto canvas = wxGetApp().plater()->canvas3D();
|
auto canvas = wxGetApp().plater()->canvas3D();
|
||||||
GLCanvas3D::Selection& selection = canvas->get_selection();
|
GLCanvas3D::Selection& selection = canvas->get_selection();
|
||||||
selection.start_dragging();
|
selection.start_dragging();
|
||||||
|
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||||
|
selection.translate(position - m_cache.position, selection.requires_local_axes());
|
||||||
|
#else
|
||||||
selection.translate(position - m_cache_position, selection.requires_local_axes());
|
selection.translate(position - m_cache_position, selection.requires_local_axes());
|
||||||
|
#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||||
canvas->do_move();
|
canvas->do_move();
|
||||||
|
|
||||||
|
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||||
|
m_cache.position = position;
|
||||||
|
#else
|
||||||
m_cache_position = position;
|
m_cache_position = position;
|
||||||
|
#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjectManipulation::change_rotation_value(const Vec3d& rotation)
|
void ObjectManipulation::change_rotation_value(const Vec3d& rotation)
|
||||||
@ -415,7 +494,7 @@ void ObjectManipulation::change_rotation_value(const Vec3d& rotation)
|
|||||||
canvas->do_rotate();
|
canvas->do_rotate();
|
||||||
|
|
||||||
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||||
m_cache_rotation = rotation;
|
m_cache.rotation = rotation;
|
||||||
#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -423,9 +502,13 @@ void ObjectManipulation::change_scale_value(const Vec3d& scale)
|
|||||||
{
|
{
|
||||||
Vec3d scaling_factor = scale;
|
Vec3d scaling_factor = scale;
|
||||||
const GLCanvas3D::Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
|
const GLCanvas3D::Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
|
||||||
if (selection.requires_uniform_scale())
|
if (m_uniform_scale || selection.requires_uniform_scale())
|
||||||
{
|
{
|
||||||
|
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||||
|
Vec3d abs_scale_diff = (scale - m_cache.scale).cwiseAbs();
|
||||||
|
#else
|
||||||
Vec3d abs_scale_diff = (scale - m_cache_scale).cwiseAbs();
|
Vec3d abs_scale_diff = (scale - m_cache_scale).cwiseAbs();
|
||||||
|
#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||||
double max_diff = abs_scale_diff(X);
|
double max_diff = abs_scale_diff(X);
|
||||||
Axis max_diff_axis = X;
|
Axis max_diff_axis = X;
|
||||||
if (max_diff < abs_scale_diff(Y))
|
if (max_diff < abs_scale_diff(Y))
|
||||||
@ -449,7 +532,10 @@ void ObjectManipulation::change_scale_value(const Vec3d& scale)
|
|||||||
canvas->do_scale();
|
canvas->do_scale();
|
||||||
|
|
||||||
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||||
m_cache_scale = scale;
|
if (!m_cache.scale.isApprox(scale))
|
||||||
|
m_cache.instance.instance_idx = -1;
|
||||||
|
|
||||||
|
m_cache.scale = scale;
|
||||||
#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -457,7 +543,11 @@ void ObjectManipulation::change_size_value(const Vec3d& size)
|
|||||||
{
|
{
|
||||||
const GLCanvas3D::Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
|
const GLCanvas3D::Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
|
||||||
|
|
||||||
|
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||||
|
Vec3d ref_size = m_cache.size;
|
||||||
|
#else
|
||||||
Vec3d ref_size = m_cache_size;
|
Vec3d ref_size = m_cache_size;
|
||||||
|
#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||||
if (selection.is_single_full_instance())
|
if (selection.is_single_full_instance())
|
||||||
{
|
{
|
||||||
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
|
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
|
||||||
@ -470,7 +560,7 @@ void ObjectManipulation::change_size_value(const Vec3d& size)
|
|||||||
|
|
||||||
if (selection.requires_uniform_scale())
|
if (selection.requires_uniform_scale())
|
||||||
{
|
{
|
||||||
Vec3d abs_scale_diff = (scale - m_cache_scale).cwiseAbs();
|
Vec3d abs_scale_diff = (scale - m_cache.scale).cwiseAbs();
|
||||||
double max_diff = abs_scale_diff(X);
|
double max_diff = abs_scale_diff(X);
|
||||||
Axis max_diff_axis = X;
|
Axis max_diff_axis = X;
|
||||||
if (max_diff < abs_scale_diff(Y))
|
if (max_diff < abs_scale_diff(Y))
|
||||||
@ -493,7 +583,7 @@ void ObjectManipulation::change_size_value(const Vec3d& size)
|
|||||||
canvas->get_selection().scale(scaling_factor, false);
|
canvas->get_selection().scale(scaling_factor, false);
|
||||||
canvas->do_scale();
|
canvas->do_scale();
|
||||||
|
|
||||||
m_cache_size = size;
|
m_cache.size = size;
|
||||||
#else
|
#else
|
||||||
change_scale_value(100.0 * Vec3d(size(0) / ref_size(0), size(1) / ref_size(1), size(2) / ref_size(2)));
|
change_scale_value(100.0 * Vec3d(size(0) / ref_size(0), size(1) / ref_size(1), size(2) / ref_size(2)));
|
||||||
#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
#endif // ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||||
|
@ -15,10 +15,41 @@ namespace GUI {
|
|||||||
class ObjectManipulation : public OG_Settings
|
class ObjectManipulation : public OG_Settings
|
||||||
{
|
{
|
||||||
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
#if ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION
|
||||||
Vec3d m_cache_position;
|
struct Cache
|
||||||
Vec3d m_cache_rotation;
|
{
|
||||||
Vec3d m_cache_scale;
|
Vec3d position;
|
||||||
Vec3d m_cache_size;
|
Vec3d rotation;
|
||||||
|
Vec3d scale;
|
||||||
|
Vec3d size;
|
||||||
|
|
||||||
|
std::string move_label_string;
|
||||||
|
std::string rotate_label_string;
|
||||||
|
std::string scale_label_string;
|
||||||
|
|
||||||
|
struct Instance
|
||||||
|
{
|
||||||
|
int object_idx;
|
||||||
|
int instance_idx;
|
||||||
|
Vec3d box_size;
|
||||||
|
|
||||||
|
Instance() { reset(); }
|
||||||
|
void reset() { this->object_idx = -1; this->instance_idx = -1; this->box_size = Vec3d::Zero(); }
|
||||||
|
void set(int object_idx, int instance_idx, const Vec3d& box_size) { this->object_idx = object_idx; this->instance_idx = instance_idx; this->box_size = box_size; }
|
||||||
|
bool matches(int object_idx, int instance_idx) const { return (this->object_idx == object_idx) && (this->instance_idx == instance_idx); }
|
||||||
|
bool matches_object(int object_idx) const { return (this->object_idx == object_idx); }
|
||||||
|
bool matches_instance(int instance_idx) const { return (this->instance_idx == instance_idx); }
|
||||||
|
};
|
||||||
|
|
||||||
|
Instance instance;
|
||||||
|
|
||||||
|
Cache() : position(Vec3d(DBL_MAX, DBL_MAX, DBL_MAX)) , rotation(Vec3d(DBL_MAX, DBL_MAX, DBL_MAX))
|
||||||
|
, scale(Vec3d(DBL_MAX, DBL_MAX, DBL_MAX)) , size(Vec3d(DBL_MAX, DBL_MAX, DBL_MAX))
|
||||||
|
, move_label_string("") , rotate_label_string("") , scale_label_string("")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Cache m_cache;
|
||||||
#else
|
#else
|
||||||
Vec3d m_cache_position{ 0., 0., 0. };
|
Vec3d m_cache_position{ 0., 0., 0. };
|
||||||
Vec3d m_cache_rotation{ 0., 0., 0. };
|
Vec3d m_cache_rotation{ 0., 0., 0. };
|
||||||
@ -43,6 +74,7 @@ class ObjectManipulation : public OG_Settings
|
|||||||
Vec3d m_new_scale;
|
Vec3d m_new_scale;
|
||||||
Vec3d m_new_size;
|
Vec3d m_new_size;
|
||||||
bool m_new_enabled;
|
bool m_new_enabled;
|
||||||
|
bool m_uniform_scale {false};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ObjectManipulation(wxWindow* parent);
|
ObjectManipulation(wxWindow* parent);
|
||||||
@ -57,6 +89,9 @@ public:
|
|||||||
// Called from the App to update the UI if dirty.
|
// Called from the App to update the UI if dirty.
|
||||||
void update_if_dirty();
|
void update_if_dirty();
|
||||||
|
|
||||||
|
void set_uniform_scaling(const bool uniform_scale) { m_uniform_scale = uniform_scale;}
|
||||||
|
bool get_uniform_scaling() const { return m_uniform_scale; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void reset_settings_value();
|
void reset_settings_value();
|
||||||
|
|
||||||
|
@ -1053,7 +1053,7 @@ std::vector<std::string> PresetCollection::dirty_options(const Preset *edited, c
|
|||||||
std::vector<std::string> changed;
|
std::vector<std::string> changed;
|
||||||
if (edited != nullptr && reference != nullptr) {
|
if (edited != nullptr && reference != nullptr) {
|
||||||
changed = deep_compare ?
|
changed = deep_compare ?
|
||||||
deep_diff(reference->config, edited->config) :
|
deep_diff(edited->config, reference->config) :
|
||||||
reference->config.diff(edited->config);
|
reference->config.diff(edited->config);
|
||||||
// The "compatible_printers" option key is handled differently from the others:
|
// The "compatible_printers" option key is handled differently from the others:
|
||||||
// It is not mandatory. If the key is missing, it means it is compatible with any printer.
|
// It is not mandatory. If the key is missing, it means it is compatible with any printer.
|
||||||
@ -1161,6 +1161,21 @@ std::string PresetCollection::name() const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> PresetCollection::system_preset_names() const
|
||||||
|
{
|
||||||
|
size_t num = 0;
|
||||||
|
for (const Preset &preset : m_presets)
|
||||||
|
if (preset.is_system)
|
||||||
|
++ num;
|
||||||
|
std::vector<std::string> out;
|
||||||
|
out.reserve(num);
|
||||||
|
for (const Preset &preset : m_presets)
|
||||||
|
if (preset.is_system)
|
||||||
|
out.emplace_back(preset.name);
|
||||||
|
std::sort(out.begin(), out.end());
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
// Generate a file path from a profile name. Add the ".ini" suffix if it is missing.
|
// Generate a file path from a profile name. Add the ".ini" suffix if it is missing.
|
||||||
std::string PresetCollection::path_from_name(const std::string &new_name) const
|
std::string PresetCollection::path_from_name(const std::string &new_name) const
|
||||||
{
|
{
|
||||||
|
@ -365,6 +365,9 @@ public:
|
|||||||
std::vector<std::string> current_different_from_parent_options(const bool deep_compare = false) const
|
std::vector<std::string> current_different_from_parent_options(const bool deep_compare = false) const
|
||||||
{ return dirty_options(&this->get_edited_preset(), this->get_selected_preset_parent(), deep_compare); }
|
{ return dirty_options(&this->get_edited_preset(), this->get_selected_preset_parent(), deep_compare); }
|
||||||
|
|
||||||
|
// Return a sorted list of system preset names.
|
||||||
|
std::vector<std::string> system_preset_names() const;
|
||||||
|
|
||||||
// Update the choice UI from the list of presets.
|
// Update the choice UI from the list of presets.
|
||||||
// If show_incompatible, all presets are shown, otherwise only the compatible presets are shown.
|
// If show_incompatible, all presets are shown, otherwise only the compatible presets are shown.
|
||||||
// If an incompatible preset is selected, it is shown as well.
|
// If an incompatible preset is selected, it is shown as well.
|
||||||
|
@ -876,7 +876,8 @@ void PresetBundle::load_config_file_config_bundle(const std::string &path, const
|
|||||||
// The presets starting with '*' are considered non-terminal and they are
|
// The presets starting with '*' are considered non-terminal and they are
|
||||||
// removed through the flattening process by this function.
|
// removed through the flattening process by this function.
|
||||||
// This function will never fail, but it will produce error messages through boost::log.
|
// This function will never fail, but it will produce error messages through boost::log.
|
||||||
static void flatten_configbundle_hierarchy(boost::property_tree::ptree &tree, const std::string &group_name)
|
// system_profiles will not be flattened, and they will be kept inside the "inherits" field
|
||||||
|
static void flatten_configbundle_hierarchy(boost::property_tree::ptree &tree, const std::string &group_name, const std::vector<std::string> &system_profiles)
|
||||||
{
|
{
|
||||||
namespace pt = boost::property_tree;
|
namespace pt = boost::property_tree;
|
||||||
|
|
||||||
@ -911,23 +912,38 @@ static void flatten_configbundle_hierarchy(boost::property_tree::ptree &tree, co
|
|||||||
for (const Prst &prst : presets) {
|
for (const Prst &prst : presets) {
|
||||||
// Parse the list of comma separated values, possibly enclosed in quotes.
|
// Parse the list of comma separated values, possibly enclosed in quotes.
|
||||||
std::vector<std::string> inherits_names;
|
std::vector<std::string> inherits_names;
|
||||||
|
std::vector<std::string> inherits_system;
|
||||||
if (Slic3r::unescape_strings_cstyle(prst.node->get<std::string>("inherits", ""), inherits_names)) {
|
if (Slic3r::unescape_strings_cstyle(prst.node->get<std::string>("inherits", ""), inherits_names)) {
|
||||||
// Resolve the inheritance by name.
|
// Resolve the inheritance by name.
|
||||||
std::vector<Prst*> &inherits_nodes = const_cast<Prst&>(prst).inherits;
|
std::vector<Prst*> &inherits_nodes = const_cast<Prst&>(prst).inherits;
|
||||||
for (const std::string &node_name : inherits_names) {
|
for (const std::string &node_name : inherits_names) {
|
||||||
auto it = presets.find(Prst(node_name, nullptr));
|
auto it_system = std::lower_bound(system_profiles.begin(), system_profiles.end(), node_name);
|
||||||
if (it == presets.end())
|
if (it_system != system_profiles.end() && *it_system == node_name) {
|
||||||
BOOST_LOG_TRIVIAL(error) << "flatten_configbundle_hierarchy: The preset " << prst.name << " inherits an unknown preset \"" << node_name << "\"";
|
// Loading a user config budnle, this preset is derived from a system profile.
|
||||||
else {
|
inherits_system.emplace_back(node_name);
|
||||||
inherits_nodes.emplace_back(const_cast<Prst*>(&(*it)));
|
} else {
|
||||||
inherits_nodes.back()->parent_of.emplace_back(const_cast<Prst*>(&prst));
|
auto it = presets.find(Prst(node_name, nullptr));
|
||||||
|
if (it == presets.end())
|
||||||
|
BOOST_LOG_TRIVIAL(error) << "flatten_configbundle_hierarchy: The preset " << prst.name << " inherits an unknown preset \"" << node_name << "\"";
|
||||||
|
else {
|
||||||
|
inherits_nodes.emplace_back(const_cast<Prst*>(&(*it)));
|
||||||
|
inherits_nodes.back()->parent_of.emplace_back(const_cast<Prst*>(&prst));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
BOOST_LOG_TRIVIAL(error) << "flatten_configbundle_hierarchy: The preset " << prst.name << " has an invalid \"inherits\" field";
|
BOOST_LOG_TRIVIAL(error) << "flatten_configbundle_hierarchy: The preset " << prst.name << " has an invalid \"inherits\" field";
|
||||||
}
|
}
|
||||||
// Remove the "inherits" key, it has no meaning outside the config bundle.
|
// Remove the "inherits" key, it has no meaning outside of the config bundle.
|
||||||
const_cast<pt::ptree*>(prst.node)->erase("inherits");
|
const_cast<pt::ptree*>(prst.node)->erase("inherits");
|
||||||
|
if (! inherits_system.empty()) {
|
||||||
|
// Loaded a user config bundle, where a profile inherits a system profile.
|
||||||
|
// User profile should be derived from a single system profile only.
|
||||||
|
assert(inherits_system.size() == 1);
|
||||||
|
if (inherits_system.size() > 1)
|
||||||
|
BOOST_LOG_TRIVIAL(error) << "flatten_configbundle_hierarchy: The preset " << prst.name << " inherits from more than single system preset";
|
||||||
|
prst.node->put("inherits", Slic3r::escape_string_cstyle(inherits_system.front()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2) Create a linear ordering for the directed acyclic graph of preset inheritance.
|
// 2) Create a linear ordering for the directed acyclic graph of preset inheritance.
|
||||||
@ -983,13 +999,14 @@ static void flatten_configbundle_hierarchy(boost::property_tree::ptree &tree, co
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void flatten_configbundle_hierarchy(boost::property_tree::ptree &tree)
|
// preset_bundle is set when loading user config bundles, which must not overwrite the system profiles.
|
||||||
|
static void flatten_configbundle_hierarchy(boost::property_tree::ptree &tree, const PresetBundle *preset_bundle)
|
||||||
{
|
{
|
||||||
flatten_configbundle_hierarchy(tree, "print");
|
flatten_configbundle_hierarchy(tree, "print", preset_bundle ? preset_bundle->prints.system_preset_names() : std::vector<std::string>());
|
||||||
flatten_configbundle_hierarchy(tree, "filament");
|
flatten_configbundle_hierarchy(tree, "filament", preset_bundle ? preset_bundle->filaments.system_preset_names() : std::vector<std::string>());
|
||||||
flatten_configbundle_hierarchy(tree, "sla_print");
|
flatten_configbundle_hierarchy(tree, "sla_print", preset_bundle ? preset_bundle->sla_prints.system_preset_names() : std::vector<std::string>());
|
||||||
flatten_configbundle_hierarchy(tree, "sla_material");
|
flatten_configbundle_hierarchy(tree, "sla_material", preset_bundle ? preset_bundle->sla_materials.system_preset_names() : std::vector<std::string>());
|
||||||
flatten_configbundle_hierarchy(tree, "printer");
|
flatten_configbundle_hierarchy(tree, "printer", preset_bundle ? preset_bundle->printers.system_preset_names() : std::vector<std::string>());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load a config bundle file, into presets and store the loaded presets into separate files
|
// Load a config bundle file, into presets and store the loaded presets into separate files
|
||||||
@ -1019,7 +1036,8 @@ size_t PresetBundle::load_configbundle(const std::string &path, unsigned int fla
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 1.5) Flatten the config bundle by applying the inheritance rules. Internal profiles (with names starting with '*') are removed.
|
// 1.5) Flatten the config bundle by applying the inheritance rules. Internal profiles (with names starting with '*') are removed.
|
||||||
flatten_configbundle_hierarchy(tree);
|
// If loading a user config bundle, do not flatten with the system profiles, but keep the "inherits" flag intact.
|
||||||
|
flatten_configbundle_hierarchy(tree, ((flags & LOAD_CFGBNDLE_SYSTEM) == 0) ? this : nullptr);
|
||||||
|
|
||||||
// 2) Parse the property_tree, extract the active preset names and the profiles, save them into local config files.
|
// 2) Parse the property_tree, extract the active preset names and the profiles, save them into local config files.
|
||||||
// Parse the obsolete preset names, to be deleted when upgrading from the old configuration structure.
|
// Parse the obsolete preset names, to be deleted when upgrading from the old configuration structure.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user