mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-29 19:53:44 -06:00 
			
		
		
		
	Merge remote-tracking branch 'origin/master' into ys_imperial_unit
This commit is contained in:
		
						commit
						bf09d8f93a
					
				
					 103 changed files with 19303 additions and 1133 deletions
				
			
		|  | @ -160,6 +160,9 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Linux") | |||
|     # Boost on Raspberry-Pi does not link to pthreads. | ||||
|     set(THREADS_PREFER_PTHREAD_FLAG ON) | ||||
|     find_package(Threads REQUIRED) | ||||
| 
 | ||||
|     find_package(DBus REQUIRED) | ||||
|     include_directories(${DBUS_INCLUDE_DIRS}) | ||||
| endif() | ||||
| 
 | ||||
| if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUXX) | ||||
|  | @ -369,9 +372,9 @@ include_directories(BEFORE SYSTEM ${EIGEN3_INCLUDE_DIR}) | |||
| 
 | ||||
| # Find expat or use bundled version | ||||
| # Always use the system libexpat on Linux. | ||||
| if (NOT SLIC3R_STATIC OR CMAKE_SYSTEM_NAME STREQUAL "Linux") | ||||
|     find_package(EXPAT) | ||||
| endif () | ||||
| 
 | ||||
| find_package(EXPAT) | ||||
| 
 | ||||
| if (NOT EXPAT_FOUND) | ||||
|     add_library(expat STATIC | ||||
|         ${LIBDIR}/expat/xmlparse.c | ||||
|  | @ -382,7 +385,8 @@ if (NOT EXPAT_FOUND) | |||
|     set(EXPAT_INCLUDE_DIRS ${LIBDIR}/expat/) | ||||
|     set(EXPAT_LIBRARIES expat) | ||||
| endif () | ||||
| include_directories(${EXPAT_INCLUDE_DIRS}) | ||||
| 
 | ||||
| find_package(PNG) | ||||
| 
 | ||||
| find_package(OpenGL REQUIRED) | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										59
									
								
								cmake/modules/FindDBus.cmake
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								cmake/modules/FindDBus.cmake
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,59 @@ | |||
| # - Try to find DBus | ||||
| # Once done, this will define | ||||
| # | ||||
| #  DBUS_FOUND - system has DBus | ||||
| #  DBUS_INCLUDE_DIRS - the DBus include directories | ||||
| #  DBUS_LIBRARIES - link these to use DBus | ||||
| # | ||||
| # Copyright (C) 2012 Raphael Kubo da Costa <rakuco@webkit.org> | ||||
| # | ||||
| # Redistribution and use in source and binary forms, with or without | ||||
| # modification, are permitted provided that the following conditions | ||||
| # are met: | ||||
| # 1.  Redistributions of source code must retain the above copyright | ||||
| #     notice, this list of conditions and the following disclaimer. | ||||
| # 2.  Redistributions in binary form must reproduce the above copyright | ||||
| #     notice, this list of conditions and the following disclaimer in the | ||||
| #     documentation and/or other materials provided with the distribution. | ||||
| # | ||||
| # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND ITS CONTRIBUTORS ``AS | ||||
| # IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | ||||
| # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | ||||
| # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR ITS | ||||
| # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||||
| # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||||
| # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | ||||
| # OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | ||||
| # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | ||||
| # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | ||||
| # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
| 
 | ||||
| FIND_PACKAGE(PkgConfig) | ||||
| PKG_CHECK_MODULES(PC_DBUS QUIET dbus-1) | ||||
| 
 | ||||
| FIND_LIBRARY(DBUS_LIBRARIES | ||||
|     NAMES dbus-1 | ||||
|     HINTS ${PC_DBUS_LIBDIR} | ||||
|           ${PC_DBUS_LIBRARY_DIRS} | ||||
| ) | ||||
| 
 | ||||
| FIND_PATH(DBUS_INCLUDE_DIR | ||||
|     NAMES dbus/dbus.h | ||||
|     HINTS ${PC_DBUS_INCLUDEDIR} | ||||
|           ${PC_DBUS_INCLUDE_DIRS} | ||||
| ) | ||||
| 
 | ||||
| GET_FILENAME_COMPONENT(_DBUS_LIBRARY_DIR ${DBUS_LIBRARIES} PATH) | ||||
| FIND_PATH(DBUS_ARCH_INCLUDE_DIR | ||||
|     NAMES dbus/dbus-arch-deps.h | ||||
|     HINTS ${PC_DBUS_INCLUDEDIR} | ||||
|           ${PC_DBUS_INCLUDE_DIRS} | ||||
|           ${_DBUS_LIBRARY_DIR} | ||||
|           ${DBUS_INCLUDE_DIR} | ||||
|     PATH_SUFFIXES include | ||||
| ) | ||||
| 
 | ||||
| SET(DBUS_INCLUDE_DIRS ${DBUS_INCLUDE_DIR} ${DBUS_ARCH_INCLUDE_DIR}) | ||||
| 
 | ||||
| INCLUDE(FindPackageHandleStandardArgs) | ||||
| FIND_PACKAGE_HANDLE_STANDARD_ARGS(DBUS REQUIRED_VARS DBUS_INCLUDE_DIRS DBUS_LIBRARIES) | ||||
							
								
								
									
										35
									
								
								deps/CMakeLists.txt
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										35
									
								
								deps/CMakeLists.txt
									
										
									
									
										vendored
									
									
								
							|  | @ -34,8 +34,10 @@ endif () | |||
| set(DESTDIR "${CMAKE_CURRENT_BINARY_DIR}/destdir" CACHE PATH "Destination directory") | ||||
| 
 | ||||
| option(DEP_DEBUG "Build debug variants (only applicable on Windows)" ON) | ||||
| option(DEP_WX_STABLE "Build against wxWidgets stable 3.0 as opposed to default 3.1 (Linux only)" OFF) | ||||
| option(DEP_WX_GTK3 "Build wxWidgets against GTK3" OFF) | ||||
| 
 | ||||
| if(CMAKE_SYSTEM_NAME STREQUAL "Linux") | ||||
|     option(DEP_WX_GTK3 "Build wxWidgets against GTK3" OFF) | ||||
| endif() | ||||
| 
 | ||||
| # On developer machines, it can be enabled to speed up compilation and suppress warnings coming from IGL.  | ||||
| # FIXME: | ||||
|  | @ -127,12 +129,28 @@ else() | |||
|     include("deps-linux.cmake") | ||||
| endif() | ||||
| 
 | ||||
| set(ZLIB_PKG "") | ||||
| if (NOT ZLIB_FOUND)  | ||||
|     include(ZLIB/ZLIB.cmake) | ||||
|     set(ZLIB_PKG dep_ZLIB) | ||||
| endif () | ||||
| set(PNG_PKG "") | ||||
| if (NOT PNG_FOUND)  | ||||
|     include(PNG/PNG.cmake) | ||||
|     set(PNG_PKG dep_PNG) | ||||
| endif () | ||||
| set(EXPAT_PKG "") | ||||
| if (NOT EXPAT_FOUND)  | ||||
|     include(EXPAT/EXPAT.cmake) | ||||
|     set(EXPAT_PKG dep_EXPAT) | ||||
| endif () | ||||
| 
 | ||||
| include(GLEW/GLEW.cmake) | ||||
| include(OpenCSG/OpenCSG.cmake) | ||||
| 
 | ||||
| include(GMP/GMP.cmake) | ||||
| include(MPFR/MPFR.cmake) | ||||
| include(CGAL/CGAL.cmake) | ||||
| include(wxWidgets/wxWidgets.cmake) | ||||
| 
 | ||||
| if (MSVC) | ||||
| 
 | ||||
|  | @ -141,15 +159,17 @@ if (MSVC) | |||
|         dep_boost | ||||
|         dep_tbb | ||||
|         dep_libcurl | ||||
|         dep_wxwidgets | ||||
|         dep_wxWidgets | ||||
|         dep_gtest | ||||
|         dep_cereal | ||||
|         dep_nlopt | ||||
|         # dep_qhull # Experimental | ||||
|         dep_ZLIB    # on Windows we still need zlib | ||||
|         dep_openvdb | ||||
|         dep_OpenCSG | ||||
|         dep_CGAL | ||||
|         ${PNG_PKG} | ||||
|         ${ZLIB_PKG} | ||||
|         ${EXPAT_PKG} | ||||
|     ) | ||||
| 
 | ||||
| else() | ||||
|  | @ -159,7 +179,7 @@ else() | |||
|         dep_boost | ||||
|         dep_tbb | ||||
|         dep_libcurl | ||||
|         dep_wxwidgets | ||||
|         dep_wxWidgets | ||||
|         dep_gtest | ||||
|         dep_cereal | ||||
|         dep_nlopt | ||||
|  | @ -167,6 +187,9 @@ else() | |||
|         dep_openvdb | ||||
|         dep_OpenCSG | ||||
|         dep_CGAL | ||||
|         ${PNG_PKG} | ||||
|         ${ZLIB_PKG} | ||||
|         ${EXPAT_PKG} | ||||
|         # dep_libigl # Not working, static build has different Eigen | ||||
|     ) | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										9
									
								
								deps/EXPAT/EXPAT.cmake
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								deps/EXPAT/EXPAT.cmake
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,9 @@ | |||
| prusaslicer_add_cmake_project(EXPAT | ||||
|   # GIT_REPOSITORY https://github.com/nigels-com/glew.git | ||||
|   # GIT_TAG 3a8eff7 # 2.1.0 | ||||
|   SOURCE_DIR          ${CMAKE_CURRENT_LIST_DIR}/expat | ||||
| ) | ||||
| 
 | ||||
| if (MSVC) | ||||
|     add_debug_dep(dep_EXPAT) | ||||
| endif () | ||||
							
								
								
									
										71
									
								
								deps/EXPAT/expat/CMakeLists.txt
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								deps/EXPAT/expat/CMakeLists.txt
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,71 @@ | |||
| cmake_minimum_required(VERSION 3.0) | ||||
| 
 | ||||
| project(EXPAT) | ||||
| 
 | ||||
| if (BUILD_SHARED_LIBS AND MSVC) | ||||
|   set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) | ||||
| endif() | ||||
| 
 | ||||
| add_library(expat | ||||
|     xmlparse.c | ||||
|     xmlrole.c | ||||
|     xmltok.c | ||||
| ) | ||||
| 
 | ||||
| target_include_directories(expat PRIVATE ${PROJECT_SOURCE_DIR}) | ||||
| 
 | ||||
| include(GNUInstallDirs) | ||||
| 
 | ||||
| install(  | ||||
|     FILES | ||||
|         ${PROJECT_SOURCE_DIR}/expat.h | ||||
|         ${PROJECT_SOURCE_DIR}/expat_config.h | ||||
|         ${PROJECT_SOURCE_DIR}/expat_external.h | ||||
|     DESTINATION | ||||
|         ${CMAKE_INSTALL_INCLUDEDIR} | ||||
| ) | ||||
| 
 | ||||
| add_library(EXPAT INTERFACE) | ||||
| target_link_libraries(EXPAT INTERFACE expat) | ||||
| 
 | ||||
| include(CMakePackageConfigHelpers) | ||||
| 
 | ||||
| write_basic_package_version_file( | ||||
|     "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"      | ||||
|     VERSION 1.95 | ||||
|     COMPATIBILITY AnyNewerVersion | ||||
| ) | ||||
| 
 | ||||
| install(TARGETS expat EXPAT | ||||
|   EXPORT ${PROJECT_NAME}Targets | ||||
|   RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}  | ||||
|   ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} | ||||
|   LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} | ||||
|   INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} | ||||
| ) | ||||
| 
 | ||||
| export(EXPORT ${PROJECT_NAME}Targets  | ||||
|        FILE "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Targets.cmake"  | ||||
|        NAMESPACE ${PROJECT_NAME}:: ) | ||||
| 
 | ||||
| set(ConfigPackageLocation ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}) | ||||
| 
 | ||||
| install(EXPORT ${PROJECT_NAME}Targets | ||||
|   FILE | ||||
|     "${PROJECT_NAME}Targets.cmake" | ||||
|   NAMESPACE | ||||
|     ${PROJECT_NAME}:: | ||||
|   DESTINATION | ||||
|     ${ConfigPackageLocation} | ||||
| ) | ||||
| 
 | ||||
| configure_file(config.cmake.in ${PROJECT_NAME}Config.cmake @ONLY) | ||||
| 
 | ||||
| install( | ||||
|     FILES | ||||
|       "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" | ||||
|       "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" | ||||
|     DESTINATION | ||||
|       ${ConfigPackageLocation} | ||||
| ) | ||||
| 
 | ||||
							
								
								
									
										21
									
								
								deps/EXPAT/expat/COPYING
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								deps/EXPAT/expat/COPYING
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,21 @@ | |||
| Copyright (c) 1998-2000 Thai Open Source Software Center Ltd and Clark Cooper | ||||
| Copyright (c) 2001-2016 Expat maintainers | ||||
| 
 | ||||
| Permission is hereby granted, free of charge, to any person obtaining | ||||
| a copy of this software and associated documentation files (the | ||||
| "Software"), to deal in the Software without restriction, including | ||||
| without limitation the rights to use, copy, modify, merge, publish, | ||||
| distribute, sublicense, and/or sell copies of the Software, and to | ||||
| permit persons to whom the Software is furnished to do so, subject to | ||||
| the following conditions: | ||||
| 
 | ||||
| The above copyright notice and this permission notice shall be included | ||||
| in all copies or substantial portions of the Software. | ||||
| 
 | ||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||||
| EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||||
| IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | ||||
| CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
| SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
							
								
								
									
										146
									
								
								deps/EXPAT/expat/README
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										146
									
								
								deps/EXPAT/expat/README
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,146 @@ | |||
| Expat, Release 2.2.0, stripped and modified for inclusion into Slic3r. | ||||
| Only the library sources needed for static linking were left. | ||||
| 
 | ||||
| The original README follows: | ||||
| --------------------------------------------------------------------- | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|                         Expat, Release 2.2.0 | ||||
| 
 | ||||
| This is Expat, a C library for parsing XML, written by James Clark. | ||||
| Expat is a stream-oriented XML parser.  This means that you register | ||||
| handlers with the parser before starting the parse.  These handlers | ||||
| are called when the parser discovers the associated structures in the | ||||
| document being parsed.  A start tag is an example of the kind of | ||||
| structures for which you may register handlers. | ||||
| 
 | ||||
| Windows users should use the expat_win32bin package, which includes | ||||
| both precompiled libraries and executables, and source code for | ||||
| developers. | ||||
| 
 | ||||
| Expat is free software.  You may copy, distribute, and modify it under | ||||
| the terms of the License contained in the file COPYING distributed | ||||
| with this package.  This license is the same as the MIT/X Consortium | ||||
| license. | ||||
| 
 | ||||
| Versions of Expat that have an odd minor version (the middle number in | ||||
| the release above), are development releases and should be considered | ||||
| as beta software.  Releases with even minor version numbers are | ||||
| intended to be production grade software. | ||||
| 
 | ||||
| If you are building Expat from a check-out from the CVS repository, | ||||
| you need to run a script that generates the configure script using the | ||||
| GNU autoconf and libtool tools.  To do this, you need to have | ||||
| autoconf 2.58 or newer. Run the script like this: | ||||
| 
 | ||||
|         ./buildconf.sh | ||||
| 
 | ||||
| Once this has been done, follow the same instructions as for building | ||||
| from a source distribution. | ||||
| 
 | ||||
| To build Expat from a source distribution, you first run the | ||||
| configuration shell script in the top level distribution directory: | ||||
| 
 | ||||
|         ./configure | ||||
| 
 | ||||
| There are many options which you may provide to configure (which you | ||||
| can discover by running configure with the --help option).  But the | ||||
| one of most interest is the one that sets the installation directory. | ||||
| By default, the configure script will set things up to install | ||||
| libexpat into /usr/local/lib, expat.h into /usr/local/include, and | ||||
| xmlwf into /usr/local/bin.  If, for example, you'd prefer to install | ||||
| into /home/me/mystuff/lib, /home/me/mystuff/include, and | ||||
| /home/me/mystuff/bin, you can tell configure about that with: | ||||
| 
 | ||||
|         ./configure --prefix=/home/me/mystuff | ||||
|          | ||||
| Another interesting option is to enable 64-bit integer support for | ||||
| line and column numbers and the over-all byte index: | ||||
| 
 | ||||
|         ./configure CPPFLAGS=-DXML_LARGE_SIZE | ||||
|          | ||||
| However, such a modification would be a breaking change to the ABI | ||||
| and is therefore not recommended for general use - e.g. as part of | ||||
| a Linux distribution - but rather for builds with special requirements. | ||||
| 
 | ||||
| After running the configure script, the "make" command will build | ||||
| things and "make install" will install things into their proper | ||||
| location.  Have a look at the "Makefile" to learn about additional | ||||
| "make" options.  Note that you need to have write permission into | ||||
| the directories into which things will be installed. | ||||
| 
 | ||||
| If you are interested in building Expat to provide document | ||||
| information in UTF-16 encoding rather than the default UTF-8, follow | ||||
| these instructions (after having run "make distclean"): | ||||
| 
 | ||||
|         1. For UTF-16 output as unsigned short (and version/error | ||||
|            strings as char), run: | ||||
| 
 | ||||
|                ./configure CPPFLAGS=-DXML_UNICODE | ||||
| 
 | ||||
|            For UTF-16 output as wchar_t (incl. version/error strings), | ||||
|            run: | ||||
| 
 | ||||
|                ./configure CFLAGS="-g -O2 -fshort-wchar" \ | ||||
|                            CPPFLAGS=-DXML_UNICODE_WCHAR_T | ||||
| 
 | ||||
|         2. Edit the MakeFile, changing: | ||||
| 
 | ||||
|                LIBRARY = libexpat.la | ||||
| 
 | ||||
|            to: | ||||
| 
 | ||||
|                LIBRARY = libexpatw.la | ||||
| 
 | ||||
|            (Note the additional "w" in the library name.) | ||||
| 
 | ||||
|         3. Run "make buildlib" (which builds the library only). | ||||
|            Or, to save step 2, run "make buildlib LIBRARY=libexpatw.la". | ||||
| 
 | ||||
|         4. Run "make installlib" (which installs the library only). | ||||
|            Or, if step 2 was omitted, run "make installlib LIBRARY=libexpatw.la". | ||||
|             | ||||
| Using DESTDIR or INSTALL_ROOT is enabled, with INSTALL_ROOT being the default | ||||
| value for DESTDIR, and the rest of the make file using only DESTDIR. | ||||
| It works as follows: | ||||
|    $ make install DESTDIR=/path/to/image | ||||
| overrides the in-makefile set DESTDIR, while both | ||||
|    $ INSTALL_ROOT=/path/to/image make install | ||||
|    $ make install INSTALL_ROOT=/path/to/image | ||||
| use DESTDIR=$(INSTALL_ROOT), even if DESTDIR eventually is defined in the | ||||
| environment, because variable-setting priority is | ||||
| 1) commandline | ||||
| 2) in-makefile | ||||
| 3) environment   | ||||
| 
 | ||||
| Note: This only applies to the Expat library itself, building UTF-16 versions | ||||
| of xmlwf and the tests is currently not supported.          | ||||
| 
 | ||||
| Note for Solaris users:  The "ar" command is usually located in | ||||
| "/usr/ccs/bin", which is not in the default PATH.  You will need to | ||||
| add this to your path for the "make" command, and probably also switch | ||||
| to GNU make (the "make" found in /usr/ccs/bin does not seem to work | ||||
| properly -- apparently it does not understand .PHONY directives).  If | ||||
| you're using ksh or bash, use this command to build: | ||||
| 
 | ||||
|         PATH=/usr/ccs/bin:$PATH make | ||||
| 
 | ||||
| When using Expat with a project using autoconf for configuration, you | ||||
| can use the probing macro in conftools/expat.m4 to determine how to | ||||
| include Expat.  See the comments at the top of that file for more | ||||
| information. | ||||
| 
 | ||||
| A reference manual is available in the file doc/reference.html in this | ||||
| distribution. | ||||
| 
 | ||||
| The homepage for this project is http://www.libexpat.org/.  There | ||||
| are links there to connect you to the bug reports page.  If you need | ||||
| to report a bug when you don't have access to a browser, you may also | ||||
| send a bug report by email to expat-bugs@mail.libexpat.org. | ||||
| 
 | ||||
| Discussion related to the direction of future expat development takes | ||||
| place on expat-discuss@mail.libexpat.org.  Archives of this list and | ||||
| other Expat-related lists may be found at: | ||||
| 
 | ||||
|         http://mail.libexpat.org/mailman/listinfo/ | ||||
							
								
								
									
										92
									
								
								deps/EXPAT/expat/ascii.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								deps/EXPAT/expat/ascii.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,92 @@ | |||
| /* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
 | ||||
|    See the file COPYING for copying permission. | ||||
| */ | ||||
| 
 | ||||
| #define ASCII_A 0x41 | ||||
| #define ASCII_B 0x42 | ||||
| #define ASCII_C 0x43 | ||||
| #define ASCII_D 0x44 | ||||
| #define ASCII_E 0x45 | ||||
| #define ASCII_F 0x46 | ||||
| #define ASCII_G 0x47 | ||||
| #define ASCII_H 0x48 | ||||
| #define ASCII_I 0x49 | ||||
| #define ASCII_J 0x4A | ||||
| #define ASCII_K 0x4B | ||||
| #define ASCII_L 0x4C | ||||
| #define ASCII_M 0x4D | ||||
| #define ASCII_N 0x4E | ||||
| #define ASCII_O 0x4F | ||||
| #define ASCII_P 0x50 | ||||
| #define ASCII_Q 0x51 | ||||
| #define ASCII_R 0x52 | ||||
| #define ASCII_S 0x53 | ||||
| #define ASCII_T 0x54 | ||||
| #define ASCII_U 0x55 | ||||
| #define ASCII_V 0x56 | ||||
| #define ASCII_W 0x57 | ||||
| #define ASCII_X 0x58 | ||||
| #define ASCII_Y 0x59 | ||||
| #define ASCII_Z 0x5A | ||||
| 
 | ||||
| #define ASCII_a 0x61 | ||||
| #define ASCII_b 0x62 | ||||
| #define ASCII_c 0x63 | ||||
| #define ASCII_d 0x64 | ||||
| #define ASCII_e 0x65 | ||||
| #define ASCII_f 0x66 | ||||
| #define ASCII_g 0x67 | ||||
| #define ASCII_h 0x68 | ||||
| #define ASCII_i 0x69 | ||||
| #define ASCII_j 0x6A | ||||
| #define ASCII_k 0x6B | ||||
| #define ASCII_l 0x6C | ||||
| #define ASCII_m 0x6D | ||||
| #define ASCII_n 0x6E | ||||
| #define ASCII_o 0x6F | ||||
| #define ASCII_p 0x70 | ||||
| #define ASCII_q 0x71 | ||||
| #define ASCII_r 0x72 | ||||
| #define ASCII_s 0x73 | ||||
| #define ASCII_t 0x74 | ||||
| #define ASCII_u 0x75 | ||||
| #define ASCII_v 0x76 | ||||
| #define ASCII_w 0x77 | ||||
| #define ASCII_x 0x78 | ||||
| #define ASCII_y 0x79 | ||||
| #define ASCII_z 0x7A | ||||
| 
 | ||||
| #define ASCII_0 0x30 | ||||
| #define ASCII_1 0x31 | ||||
| #define ASCII_2 0x32 | ||||
| #define ASCII_3 0x33 | ||||
| #define ASCII_4 0x34 | ||||
| #define ASCII_5 0x35 | ||||
| #define ASCII_6 0x36 | ||||
| #define ASCII_7 0x37 | ||||
| #define ASCII_8 0x38 | ||||
| #define ASCII_9 0x39 | ||||
| 
 | ||||
| #define ASCII_TAB 0x09 | ||||
| #define ASCII_SPACE 0x20 | ||||
| #define ASCII_EXCL 0x21 | ||||
| #define ASCII_QUOT 0x22 | ||||
| #define ASCII_AMP 0x26 | ||||
| #define ASCII_APOS 0x27 | ||||
| #define ASCII_MINUS 0x2D | ||||
| #define ASCII_PERIOD 0x2E | ||||
| #define ASCII_COLON 0x3A | ||||
| #define ASCII_SEMI 0x3B | ||||
| #define ASCII_LT 0x3C | ||||
| #define ASCII_EQUALS 0x3D | ||||
| #define ASCII_GT 0x3E | ||||
| #define ASCII_LSQB 0x5B | ||||
| #define ASCII_RSQB 0x5D | ||||
| #define ASCII_UNDERSCORE 0x5F | ||||
| #define ASCII_LPAREN 0x28 | ||||
| #define ASCII_RPAREN 0x29 | ||||
| #define ASCII_FF 0x0C | ||||
| #define ASCII_SLASH 0x2F | ||||
| #define ASCII_HASH 0x23 | ||||
| #define ASCII_PIPE 0x7C | ||||
| #define ASCII_COMMA 0x2C | ||||
							
								
								
									
										36
									
								
								deps/EXPAT/expat/asciitab.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								deps/EXPAT/expat/asciitab.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,36 @@ | |||
| /* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
 | ||||
|    See the file COPYING for copying permission. | ||||
| */ | ||||
| 
 | ||||
| /* 0x00 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, | ||||
| /* 0x04 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, | ||||
| /* 0x08 */ BT_NONXML, BT_S, BT_LF, BT_NONXML, | ||||
| /* 0x0C */ BT_NONXML, BT_CR, BT_NONXML, BT_NONXML, | ||||
| /* 0x10 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, | ||||
| /* 0x14 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, | ||||
| /* 0x18 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, | ||||
| /* 0x1C */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, | ||||
| /* 0x20 */ BT_S, BT_EXCL, BT_QUOT, BT_NUM, | ||||
| /* 0x24 */ BT_OTHER, BT_PERCNT, BT_AMP, BT_APOS, | ||||
| /* 0x28 */ BT_LPAR, BT_RPAR, BT_AST, BT_PLUS, | ||||
| /* 0x2C */ BT_COMMA, BT_MINUS, BT_NAME, BT_SOL, | ||||
| /* 0x30 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT, | ||||
| /* 0x34 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT, | ||||
| /* 0x38 */ BT_DIGIT, BT_DIGIT, BT_COLON, BT_SEMI, | ||||
| /* 0x3C */ BT_LT, BT_EQUALS, BT_GT, BT_QUEST, | ||||
| /* 0x40 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX, | ||||
| /* 0x44 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT, | ||||
| /* 0x48 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, | ||||
| /* 0x4C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, | ||||
| /* 0x50 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, | ||||
| /* 0x54 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, | ||||
| /* 0x58 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_LSQB, | ||||
| /* 0x5C */ BT_OTHER, BT_RSQB, BT_OTHER, BT_NMSTRT, | ||||
| /* 0x60 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX, | ||||
| /* 0x64 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT, | ||||
| /* 0x68 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, | ||||
| /* 0x6C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, | ||||
| /* 0x70 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, | ||||
| /* 0x74 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, | ||||
| /* 0x78 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER, | ||||
| /* 0x7C */ BT_VERBAR, BT_OTHER, BT_OTHER, BT_OTHER, | ||||
							
								
								
									
										4
									
								
								deps/EXPAT/expat/config.cmake.in
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								deps/EXPAT/expat/config.cmake.in
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,4 @@ | |||
| include(${CMAKE_CURRENT_LIST_DIR}/EXPATTargets.cmake) | ||||
| set(EXPAT_LIBRARIES EXPAT::expat) | ||||
| set(EXPAT_INCLUDE_DIRS ${_IMPORT_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}) | ||||
| 
 | ||||
							
								
								
									
										1048
									
								
								deps/EXPAT/expat/expat.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1048
									
								
								deps/EXPAT/expat/expat.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										33
									
								
								deps/EXPAT/expat/expat_config.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								deps/EXPAT/expat/expat_config.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,33 @@ | |||
| /*================================================================
 | ||||
| ** Copyright 2000, Clark Cooper | ||||
| ** All rights reserved. | ||||
| ** | ||||
| ** This is free software. You are permitted to copy, distribute, or modify | ||||
| ** it under the terms of the MIT/X license (contained in the COPYING file | ||||
| ** with this distribution.) | ||||
| */ | ||||
| 
 | ||||
| #ifndef EXPATCONFIG_H | ||||
| #define EXPATCONFIG_H | ||||
| 
 | ||||
| #include <memory.h> | ||||
| #include <string.h> | ||||
| 
 | ||||
| #define XML_NS 1 | ||||
| #define XML_DTD 1 | ||||
| #define XML_CONTEXT_BYTES 1024 | ||||
| 
 | ||||
| /* we will assume all Windows platforms are little endian */ | ||||
| #define BYTEORDER 1234 | ||||
| 
 | ||||
| /* Windows has memmove() available. */ | ||||
| #define HAVE_MEMMOVE | ||||
| 
 | ||||
| #ifdef WIN32 | ||||
| 	#define WIN32_LEAN_AND_MEAN | ||||
| 	#include <windows.h> | ||||
| 	#undef WIN32_LEAN_AND_MEAN | ||||
| #else | ||||
| #endif | ||||
| 
 | ||||
| #endif /* ifndef EXPATCONFIG_H */ | ||||
							
								
								
									
										129
									
								
								deps/EXPAT/expat/expat_external.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								deps/EXPAT/expat/expat_external.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,129 @@ | |||
| /* Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
 | ||||
|    See the file COPYING for copying permission. | ||||
| */ | ||||
| 
 | ||||
| #ifndef Expat_External_INCLUDED | ||||
| #define Expat_External_INCLUDED 1 | ||||
| 
 | ||||
| /* External API definitions */ | ||||
| 
 | ||||
| #if defined(_MSC_EXTENSIONS) && !defined(__BEOS__) && !defined(__CYGWIN__) | ||||
| #define XML_USE_MSC_EXTENSIONS 1 | ||||
| #endif | ||||
| 
 | ||||
| /* Expat tries very hard to make the API boundary very specifically
 | ||||
|    defined.  There are two macros defined to control this boundary; | ||||
|    each of these can be defined before including this header to | ||||
|    achieve some different behavior, but doing so it not recommended or | ||||
|    tested frequently. | ||||
| 
 | ||||
|    XMLCALL    - The calling convention to use for all calls across the | ||||
|                 "library boundary."  This will default to cdecl, and | ||||
|                 try really hard to tell the compiler that's what we | ||||
|                 want. | ||||
| 
 | ||||
|    XMLIMPORT  - Whatever magic is needed to note that a function is | ||||
|                 to be imported from a dynamically loaded library | ||||
|                 (.dll, .so, or .sl, depending on your platform). | ||||
| 
 | ||||
|    The XMLCALL macro was added in Expat 1.95.7.  The only one which is | ||||
|    expected to be directly useful in client code is XMLCALL. | ||||
| 
 | ||||
|    Note that on at least some Unix versions, the Expat library must be | ||||
|    compiled with the cdecl calling convention as the default since | ||||
|    system headers may assume the cdecl convention. | ||||
| */ | ||||
| #ifndef XMLCALL | ||||
| #if defined(_MSC_VER) | ||||
| #define XMLCALL __cdecl | ||||
| #elif defined(__GNUC__) && defined(__i386) && !defined(__INTEL_COMPILER) | ||||
| #define XMLCALL __attribute__((cdecl)) | ||||
| #else | ||||
| /* For any platform which uses this definition and supports more than
 | ||||
|    one calling convention, we need to extend this definition to | ||||
|    declare the convention used on that platform, if it's possible to | ||||
|    do so. | ||||
| 
 | ||||
|    If this is the case for your platform, please file a bug report | ||||
|    with information on how to identify your platform via the C | ||||
|    pre-processor and how to specify the same calling convention as the | ||||
|    platform's malloc() implementation. | ||||
| */ | ||||
| #define XMLCALL | ||||
| #endif | ||||
| #endif  /* not defined XMLCALL */ | ||||
| 
 | ||||
| 
 | ||||
| #if !defined(XML_STATIC) && !defined(XMLIMPORT) | ||||
| #ifndef XML_BUILDING_EXPAT | ||||
| /* using Expat from an application */ | ||||
| 
 | ||||
| #ifdef XML_USE_MSC_EXTENSIONS | ||||
| // #define XMLIMPORT __declspec(dllimport)
 | ||||
| #endif | ||||
| 
 | ||||
| #endif | ||||
| #endif  /* not defined XML_STATIC */ | ||||
| 
 | ||||
| #if !defined(XMLIMPORT) && defined(__GNUC__) && (__GNUC__ >= 4) | ||||
| #define XMLIMPORT __attribute__ ((visibility ("default"))) | ||||
| #endif | ||||
| 
 | ||||
| /* If we didn't define it above, define it away: */ | ||||
| #ifndef XMLIMPORT | ||||
| #define XMLIMPORT | ||||
| #endif | ||||
| 
 | ||||
| #if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)) | ||||
| #define XML_ATTR_MALLOC __attribute__((__malloc__)) | ||||
| #else | ||||
| #define XML_ATTR_MALLOC | ||||
| #endif | ||||
| 
 | ||||
| #if defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) | ||||
| #define XML_ATTR_ALLOC_SIZE(x)  __attribute__((__alloc_size__(x))) | ||||
| #else | ||||
| #define XML_ATTR_ALLOC_SIZE(x) | ||||
| #endif | ||||
| 
 | ||||
| #define XMLPARSEAPI(type) XMLIMPORT type XMLCALL | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| #ifdef XML_UNICODE_WCHAR_T | ||||
| #define XML_UNICODE | ||||
| #endif | ||||
| 
 | ||||
| #ifdef XML_UNICODE     /* Information is UTF-16 encoded. */ | ||||
| #ifdef XML_UNICODE_WCHAR_T | ||||
| typedef wchar_t XML_Char; | ||||
| typedef wchar_t XML_LChar; | ||||
| #else | ||||
| typedef unsigned short XML_Char; | ||||
| typedef char XML_LChar; | ||||
| #endif /* XML_UNICODE_WCHAR_T */ | ||||
| #else                  /* Information is UTF-8 encoded. */ | ||||
| typedef char XML_Char; | ||||
| typedef char XML_LChar; | ||||
| #endif /* XML_UNICODE */ | ||||
| 
 | ||||
| #ifdef XML_LARGE_SIZE  /* Use large integers for file/stream positions. */ | ||||
| #if defined(XML_USE_MSC_EXTENSIONS) && _MSC_VER < 1400 | ||||
| typedef __int64 XML_Index;  | ||||
| typedef unsigned __int64 XML_Size; | ||||
| #else | ||||
| typedef long long XML_Index; | ||||
| typedef unsigned long long XML_Size; | ||||
| #endif | ||||
| #else | ||||
| typedef long XML_Index; | ||||
| typedef unsigned long XML_Size; | ||||
| #endif /* XML_LARGE_SIZE */ | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #endif /* not Expat_External_INCLUDED */ | ||||
							
								
								
									
										37
									
								
								deps/EXPAT/expat/iasciitab.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								deps/EXPAT/expat/iasciitab.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,37 @@ | |||
| /* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
 | ||||
|    See the file COPYING for copying permission. | ||||
| */ | ||||
| 
 | ||||
| /* Like asciitab.h, except that 0xD has code BT_S rather than BT_CR */ | ||||
| /* 0x00 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, | ||||
| /* 0x04 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, | ||||
| /* 0x08 */ BT_NONXML, BT_S, BT_LF, BT_NONXML, | ||||
| /* 0x0C */ BT_NONXML, BT_S, BT_NONXML, BT_NONXML, | ||||
| /* 0x10 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, | ||||
| /* 0x14 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, | ||||
| /* 0x18 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, | ||||
| /* 0x1C */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, | ||||
| /* 0x20 */ BT_S, BT_EXCL, BT_QUOT, BT_NUM, | ||||
| /* 0x24 */ BT_OTHER, BT_PERCNT, BT_AMP, BT_APOS, | ||||
| /* 0x28 */ BT_LPAR, BT_RPAR, BT_AST, BT_PLUS, | ||||
| /* 0x2C */ BT_COMMA, BT_MINUS, BT_NAME, BT_SOL, | ||||
| /* 0x30 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT, | ||||
| /* 0x34 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT, | ||||
| /* 0x38 */ BT_DIGIT, BT_DIGIT, BT_COLON, BT_SEMI, | ||||
| /* 0x3C */ BT_LT, BT_EQUALS, BT_GT, BT_QUEST, | ||||
| /* 0x40 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX, | ||||
| /* 0x44 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT, | ||||
| /* 0x48 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, | ||||
| /* 0x4C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, | ||||
| /* 0x50 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, | ||||
| /* 0x54 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, | ||||
| /* 0x58 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_LSQB, | ||||
| /* 0x5C */ BT_OTHER, BT_RSQB, BT_OTHER, BT_NMSTRT, | ||||
| /* 0x60 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX, | ||||
| /* 0x64 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT, | ||||
| /* 0x68 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, | ||||
| /* 0x6C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, | ||||
| /* 0x70 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, | ||||
| /* 0x74 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, | ||||
| /* 0x78 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER, | ||||
| /* 0x7C */ BT_VERBAR, BT_OTHER, BT_OTHER, BT_OTHER, | ||||
							
								
								
									
										95
									
								
								deps/EXPAT/expat/internal.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								deps/EXPAT/expat/internal.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,95 @@ | |||
| /* internal.h
 | ||||
| 
 | ||||
|    Internal definitions used by Expat.  This is not needed to compile | ||||
|    client code. | ||||
| 
 | ||||
|    The following calling convention macros are defined for frequently | ||||
|    called functions: | ||||
| 
 | ||||
|    FASTCALL    - Used for those internal functions that have a simple | ||||
|                  body and a low number of arguments and local variables. | ||||
| 
 | ||||
|    PTRCALL     - Used for functions called though function pointers. | ||||
| 
 | ||||
|    PTRFASTCALL - Like PTRCALL, but for low number of arguments. | ||||
| 
 | ||||
|    inline      - Used for selected internal functions for which inlining | ||||
|                  may improve performance on some platforms. | ||||
| 
 | ||||
|    Note: Use of these macros is based on judgement, not hard rules, | ||||
|          and therefore subject to change. | ||||
| */ | ||||
| 
 | ||||
| #if defined(__GNUC__) && defined(__i386__) && !defined(__MINGW32__) | ||||
| /* We'll use this version by default only where we know it helps.
 | ||||
| 
 | ||||
|    regparm() generates warnings on Solaris boxes.   See SF bug #692878. | ||||
| 
 | ||||
|    Instability reported with egcs on a RedHat Linux 7.3. | ||||
|    Let's comment out: | ||||
|    #define FASTCALL __attribute__((stdcall, regparm(3))) | ||||
|    and let's try this: | ||||
| */ | ||||
| #define FASTCALL __attribute__((regparm(3))) | ||||
| #define PTRFASTCALL __attribute__((regparm(3))) | ||||
| #endif | ||||
| 
 | ||||
| /* Using __fastcall seems to have an unexpected negative effect under
 | ||||
|    MS VC++, especially for function pointers, so we won't use it for | ||||
|    now on that platform. It may be reconsidered for a future release | ||||
|    if it can be made more effective. | ||||
|    Likely reason: __fastcall on Windows is like stdcall, therefore | ||||
|    the compiler cannot perform stack optimizations for call clusters. | ||||
| */ | ||||
| 
 | ||||
| /* Make sure all of these are defined if they aren't already. */ | ||||
| 
 | ||||
| #ifndef FASTCALL | ||||
| #define FASTCALL | ||||
| #endif | ||||
| 
 | ||||
| #ifndef PTRCALL | ||||
| #define PTRCALL | ||||
| #endif | ||||
| 
 | ||||
| #ifndef PTRFASTCALL | ||||
| #define PTRFASTCALL | ||||
| #endif | ||||
| 
 | ||||
| #ifndef XML_MIN_SIZE | ||||
| #if !defined(__cplusplus) && !defined(inline) | ||||
| #ifdef __GNUC__ | ||||
| #define inline __inline | ||||
| #endif /* __GNUC__ */ | ||||
| #endif | ||||
| #endif /* XML_MIN_SIZE */ | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| #define inline inline | ||||
| #else | ||||
| #ifndef inline | ||||
| #define inline | ||||
| #endif | ||||
| #endif | ||||
| 
 | ||||
| #ifndef UNUSED_P | ||||
| # ifdef __GNUC__ | ||||
| #  define UNUSED_P(p) UNUSED_ ## p __attribute__((__unused__)) | ||||
| # else | ||||
| #  define UNUSED_P(p) UNUSED_ ## p | ||||
| # endif | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| void | ||||
| align_limit_to_full_utf8_characters(const char * from, const char ** fromLimRef); | ||||
| 
 | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
							
								
								
									
										36
									
								
								deps/EXPAT/expat/latin1tab.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								deps/EXPAT/expat/latin1tab.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,36 @@ | |||
| /* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
 | ||||
|    See the file COPYING for copying permission. | ||||
| */ | ||||
| 
 | ||||
| /* 0x80 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, | ||||
| /* 0x84 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, | ||||
| /* 0x88 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, | ||||
| /* 0x8C */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, | ||||
| /* 0x90 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, | ||||
| /* 0x94 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, | ||||
| /* 0x98 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, | ||||
| /* 0x9C */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, | ||||
| /* 0xA0 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, | ||||
| /* 0xA4 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, | ||||
| /* 0xA8 */ BT_OTHER, BT_OTHER, BT_NMSTRT, BT_OTHER, | ||||
| /* 0xAC */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, | ||||
| /* 0xB0 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, | ||||
| /* 0xB4 */ BT_OTHER, BT_NMSTRT, BT_OTHER, BT_NAME, | ||||
| /* 0xB8 */ BT_OTHER, BT_OTHER, BT_NMSTRT, BT_OTHER, | ||||
| /* 0xBC */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER, | ||||
| /* 0xC0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, | ||||
| /* 0xC4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, | ||||
| /* 0xC8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, | ||||
| /* 0xCC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, | ||||
| /* 0xD0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, | ||||
| /* 0xD4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER, | ||||
| /* 0xD8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, | ||||
| /* 0xDC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, | ||||
| /* 0xE0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, | ||||
| /* 0xE4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, | ||||
| /* 0xE8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, | ||||
| /* 0xEC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, | ||||
| /* 0xF0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, | ||||
| /* 0xF4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER, | ||||
| /* 0xF8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, | ||||
| /* 0xFC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, | ||||
							
								
								
									
										150
									
								
								deps/EXPAT/expat/nametab.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										150
									
								
								deps/EXPAT/expat/nametab.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,150 @@ | |||
| static const unsigned namingBitmap[] = { | ||||
| 0x00000000, 0x00000000, 0x00000000, 0x00000000, | ||||
| 0x00000000, 0x00000000, 0x00000000, 0x00000000, | ||||
| 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, | ||||
| 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, | ||||
| 0x00000000, 0x04000000, 0x87FFFFFE, 0x07FFFFFE, | ||||
| 0x00000000, 0x00000000, 0xFF7FFFFF, 0xFF7FFFFF, | ||||
| 0xFFFFFFFF, 0x7FF3FFFF, 0xFFFFFDFE, 0x7FFFFFFF, | ||||
| 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE00F, 0xFC31FFFF, | ||||
| 0x00FFFFFF, 0x00000000, 0xFFFF0000, 0xFFFFFFFF, | ||||
| 0xFFFFFFFF, 0xF80001FF, 0x00000003, 0x00000000, | ||||
| 0x00000000, 0x00000000, 0x00000000, 0x00000000, | ||||
| 0xFFFFD740, 0xFFFFFFFB, 0x547F7FFF, 0x000FFFFD, | ||||
| 0xFFFFDFFE, 0xFFFFFFFF, 0xDFFEFFFF, 0xFFFFFFFF, | ||||
| 0xFFFF0003, 0xFFFFFFFF, 0xFFFF199F, 0x033FCFFF, | ||||
| 0x00000000, 0xFFFE0000, 0x027FFFFF, 0xFFFFFFFE, | ||||
| 0x0000007F, 0x00000000, 0xFFFF0000, 0x000707FF, | ||||
| 0x00000000, 0x07FFFFFE, 0x000007FE, 0xFFFE0000, | ||||
| 0xFFFFFFFF, 0x7CFFFFFF, 0x002F7FFF, 0x00000060, | ||||
| 0xFFFFFFE0, 0x23FFFFFF, 0xFF000000, 0x00000003, | ||||
| 0xFFF99FE0, 0x03C5FDFF, 0xB0000000, 0x00030003, | ||||
| 0xFFF987E0, 0x036DFDFF, 0x5E000000, 0x001C0000, | ||||
| 0xFFFBAFE0, 0x23EDFDFF, 0x00000000, 0x00000001, | ||||
| 0xFFF99FE0, 0x23CDFDFF, 0xB0000000, 0x00000003, | ||||
| 0xD63DC7E0, 0x03BFC718, 0x00000000, 0x00000000, | ||||
| 0xFFFDDFE0, 0x03EFFDFF, 0x00000000, 0x00000003, | ||||
| 0xFFFDDFE0, 0x03EFFDFF, 0x40000000, 0x00000003, | ||||
| 0xFFFDDFE0, 0x03FFFDFF, 0x00000000, 0x00000003, | ||||
| 0x00000000, 0x00000000, 0x00000000, 0x00000000, | ||||
| 0xFFFFFFFE, 0x000D7FFF, 0x0000003F, 0x00000000, | ||||
| 0xFEF02596, 0x200D6CAE, 0x0000001F, 0x00000000, | ||||
| 0x00000000, 0x00000000, 0xFFFFFEFF, 0x000003FF, | ||||
| 0x00000000, 0x00000000, 0x00000000, 0x00000000, | ||||
| 0x00000000, 0x00000000, 0x00000000, 0x00000000, | ||||
| 0x00000000, 0xFFFFFFFF, 0xFFFF003F, 0x007FFFFF, | ||||
| 0x0007DAED, 0x50000000, 0x82315001, 0x002C62AB, | ||||
| 0x40000000, 0xF580C900, 0x00000007, 0x02010800, | ||||
| 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, | ||||
| 0x0FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x03FFFFFF, | ||||
| 0x3F3FFFFF, 0xFFFFFFFF, 0xAAFF3F3F, 0x3FFFFFFF, | ||||
| 0xFFFFFFFF, 0x5FDFFFFF, 0x0FCF1FDC, 0x1FDC1FFF, | ||||
| 0x00000000, 0x00004C40, 0x00000000, 0x00000000, | ||||
| 0x00000007, 0x00000000, 0x00000000, 0x00000000, | ||||
| 0x00000080, 0x000003FE, 0xFFFFFFFE, 0xFFFFFFFF, | ||||
| 0x001FFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x07FFFFFF, | ||||
| 0xFFFFFFE0, 0x00001FFF, 0x00000000, 0x00000000, | ||||
| 0x00000000, 0x00000000, 0x00000000, 0x00000000, | ||||
| 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, | ||||
| 0xFFFFFFFF, 0x0000003F, 0x00000000, 0x00000000, | ||||
| 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, | ||||
| 0xFFFFFFFF, 0x0000000F, 0x00000000, 0x00000000, | ||||
| 0x00000000, 0x07FF6000, 0x87FFFFFE, 0x07FFFFFE, | ||||
| 0x00000000, 0x00800000, 0xFF7FFFFF, 0xFF7FFFFF, | ||||
| 0x00FFFFFF, 0x00000000, 0xFFFF0000, 0xFFFFFFFF, | ||||
| 0xFFFFFFFF, 0xF80001FF, 0x00030003, 0x00000000, | ||||
| 0xFFFFFFFF, 0xFFFFFFFF, 0x0000003F, 0x00000003, | ||||
| 0xFFFFD7C0, 0xFFFFFFFB, 0x547F7FFF, 0x000FFFFD, | ||||
| 0xFFFFDFFE, 0xFFFFFFFF, 0xDFFEFFFF, 0xFFFFFFFF, | ||||
| 0xFFFF007B, 0xFFFFFFFF, 0xFFFF199F, 0x033FCFFF, | ||||
| 0x00000000, 0xFFFE0000, 0x027FFFFF, 0xFFFFFFFE, | ||||
| 0xFFFE007F, 0xBBFFFFFB, 0xFFFF0016, 0x000707FF, | ||||
| 0x00000000, 0x07FFFFFE, 0x0007FFFF, 0xFFFF03FF, | ||||
| 0xFFFFFFFF, 0x7CFFFFFF, 0xFFEF7FFF, 0x03FF3DFF, | ||||
| 0xFFFFFFEE, 0xF3FFFFFF, 0xFF1E3FFF, 0x0000FFCF, | ||||
| 0xFFF99FEE, 0xD3C5FDFF, 0xB080399F, 0x0003FFCF, | ||||
| 0xFFF987E4, 0xD36DFDFF, 0x5E003987, 0x001FFFC0, | ||||
| 0xFFFBAFEE, 0xF3EDFDFF, 0x00003BBF, 0x0000FFC1, | ||||
| 0xFFF99FEE, 0xF3CDFDFF, 0xB0C0398F, 0x0000FFC3, | ||||
| 0xD63DC7EC, 0xC3BFC718, 0x00803DC7, 0x0000FF80, | ||||
| 0xFFFDDFEE, 0xC3EFFDFF, 0x00603DDF, 0x0000FFC3, | ||||
| 0xFFFDDFEC, 0xC3EFFDFF, 0x40603DDF, 0x0000FFC3, | ||||
| 0xFFFDDFEC, 0xC3FFFDFF, 0x00803DCF, 0x0000FFC3, | ||||
| 0x00000000, 0x00000000, 0x00000000, 0x00000000, | ||||
| 0xFFFFFFFE, 0x07FF7FFF, 0x03FF7FFF, 0x00000000, | ||||
| 0xFEF02596, 0x3BFF6CAE, 0x03FF3F5F, 0x00000000, | ||||
| 0x03000000, 0xC2A003FF, 0xFFFFFEFF, 0xFFFE03FF, | ||||
| 0xFEBF0FDF, 0x02FE3FFF, 0x00000000, 0x00000000, | ||||
| 0x00000000, 0x00000000, 0x00000000, 0x00000000, | ||||
| 0x00000000, 0x00000000, 0x1FFF0000, 0x00000002, | ||||
| 0x000000A0, 0x003EFFFE, 0xFFFFFFFE, 0xFFFFFFFF, | ||||
| 0x661FFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x77FFFFFF, | ||||
| }; | ||||
| static const unsigned char nmstrtPages[] = { | ||||
| 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, | ||||
| 0x00, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, | ||||
| 0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13, | ||||
| 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||
| 0x15, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, | ||||
| 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, | ||||
| 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, | ||||
| 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, | ||||
| 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, | ||||
| 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, | ||||
| 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, | ||||
| 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, | ||||
| 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, | ||||
| 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, | ||||
| 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x17, | ||||
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||
| 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, | ||||
| 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, | ||||
| 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, | ||||
| 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, | ||||
| 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, | ||||
| 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18, | ||||
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||
| }; | ||||
| static const unsigned char namePages[] = { | ||||
| 0x19, 0x03, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x00, | ||||
| 0x00, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, | ||||
| 0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13, | ||||
| 0x26, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||
| 0x27, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, | ||||
| 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, | ||||
| 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, | ||||
| 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, | ||||
| 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, | ||||
| 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, | ||||
| 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, | ||||
| 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, | ||||
| 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, | ||||
| 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, | ||||
| 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x17, | ||||
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||
| 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, | ||||
| 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, | ||||
| 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, | ||||
| 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, | ||||
| 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, | ||||
| 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18, | ||||
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||||
| }; | ||||
							
								
								
									
										37
									
								
								deps/EXPAT/expat/utf8tab.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								deps/EXPAT/expat/utf8tab.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,37 @@ | |||
| /* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
 | ||||
|    See the file COPYING for copying permission. | ||||
| */ | ||||
| 
 | ||||
| 
 | ||||
| /* 0x80 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, | ||||
| /* 0x84 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, | ||||
| /* 0x88 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, | ||||
| /* 0x8C */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, | ||||
| /* 0x90 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, | ||||
| /* 0x94 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, | ||||
| /* 0x98 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, | ||||
| /* 0x9C */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, | ||||
| /* 0xA0 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, | ||||
| /* 0xA4 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, | ||||
| /* 0xA8 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, | ||||
| /* 0xAC */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, | ||||
| /* 0xB0 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, | ||||
| /* 0xB4 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, | ||||
| /* 0xB8 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, | ||||
| /* 0xBC */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL, | ||||
| /* 0xC0 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, | ||||
| /* 0xC4 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, | ||||
| /* 0xC8 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, | ||||
| /* 0xCC */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, | ||||
| /* 0xD0 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, | ||||
| /* 0xD4 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, | ||||
| /* 0xD8 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, | ||||
| /* 0xDC */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2, | ||||
| /* 0xE0 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3, | ||||
| /* 0xE4 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3, | ||||
| /* 0xE8 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3, | ||||
| /* 0xEC */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3, | ||||
| /* 0xF0 */ BT_LEAD4, BT_LEAD4, BT_LEAD4, BT_LEAD4, | ||||
| /* 0xF4 */ BT_LEAD4, BT_NONXML, BT_NONXML, BT_NONXML, | ||||
| /* 0xF8 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML, | ||||
| /* 0xFC */ BT_NONXML, BT_NONXML, BT_MALFORM, BT_MALFORM, | ||||
							
								
								
									
										6458
									
								
								deps/EXPAT/expat/xmlparse.c
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										6458
									
								
								deps/EXPAT/expat/xmlparse.c
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										1322
									
								
								deps/EXPAT/expat/xmlrole.c
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1322
									
								
								deps/EXPAT/expat/xmlrole.c
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										114
									
								
								deps/EXPAT/expat/xmlrole.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								deps/EXPAT/expat/xmlrole.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,114 @@ | |||
| /* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
 | ||||
|    See the file COPYING for copying permission. | ||||
| */ | ||||
| 
 | ||||
| #ifndef XmlRole_INCLUDED | ||||
| #define XmlRole_INCLUDED 1 | ||||
| 
 | ||||
| #ifdef __VMS | ||||
| /*      0        1         2         3      0        1         2         3
 | ||||
|         1234567890123456789012345678901     1234567890123456789012345678901 */ | ||||
| #define XmlPrologStateInitExternalEntity    XmlPrologStateInitExternalEnt | ||||
| #endif | ||||
| 
 | ||||
| #include "xmltok.h" | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| enum { | ||||
|   XML_ROLE_ERROR = -1, | ||||
|   XML_ROLE_NONE = 0, | ||||
|   XML_ROLE_XML_DECL, | ||||
|   XML_ROLE_INSTANCE_START, | ||||
|   XML_ROLE_DOCTYPE_NONE, | ||||
|   XML_ROLE_DOCTYPE_NAME, | ||||
|   XML_ROLE_DOCTYPE_SYSTEM_ID, | ||||
|   XML_ROLE_DOCTYPE_PUBLIC_ID, | ||||
|   XML_ROLE_DOCTYPE_INTERNAL_SUBSET, | ||||
|   XML_ROLE_DOCTYPE_CLOSE, | ||||
|   XML_ROLE_GENERAL_ENTITY_NAME, | ||||
|   XML_ROLE_PARAM_ENTITY_NAME, | ||||
|   XML_ROLE_ENTITY_NONE, | ||||
|   XML_ROLE_ENTITY_VALUE, | ||||
|   XML_ROLE_ENTITY_SYSTEM_ID, | ||||
|   XML_ROLE_ENTITY_PUBLIC_ID, | ||||
|   XML_ROLE_ENTITY_COMPLETE, | ||||
|   XML_ROLE_ENTITY_NOTATION_NAME, | ||||
|   XML_ROLE_NOTATION_NONE, | ||||
|   XML_ROLE_NOTATION_NAME, | ||||
|   XML_ROLE_NOTATION_SYSTEM_ID, | ||||
|   XML_ROLE_NOTATION_NO_SYSTEM_ID, | ||||
|   XML_ROLE_NOTATION_PUBLIC_ID, | ||||
|   XML_ROLE_ATTRIBUTE_NAME, | ||||
|   XML_ROLE_ATTRIBUTE_TYPE_CDATA, | ||||
|   XML_ROLE_ATTRIBUTE_TYPE_ID, | ||||
|   XML_ROLE_ATTRIBUTE_TYPE_IDREF, | ||||
|   XML_ROLE_ATTRIBUTE_TYPE_IDREFS, | ||||
|   XML_ROLE_ATTRIBUTE_TYPE_ENTITY, | ||||
|   XML_ROLE_ATTRIBUTE_TYPE_ENTITIES, | ||||
|   XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN, | ||||
|   XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS, | ||||
|   XML_ROLE_ATTRIBUTE_ENUM_VALUE, | ||||
|   XML_ROLE_ATTRIBUTE_NOTATION_VALUE, | ||||
|   XML_ROLE_ATTLIST_NONE, | ||||
|   XML_ROLE_ATTLIST_ELEMENT_NAME, | ||||
|   XML_ROLE_IMPLIED_ATTRIBUTE_VALUE, | ||||
|   XML_ROLE_REQUIRED_ATTRIBUTE_VALUE, | ||||
|   XML_ROLE_DEFAULT_ATTRIBUTE_VALUE, | ||||
|   XML_ROLE_FIXED_ATTRIBUTE_VALUE, | ||||
|   XML_ROLE_ELEMENT_NONE, | ||||
|   XML_ROLE_ELEMENT_NAME, | ||||
|   XML_ROLE_CONTENT_ANY, | ||||
|   XML_ROLE_CONTENT_EMPTY, | ||||
|   XML_ROLE_CONTENT_PCDATA, | ||||
|   XML_ROLE_GROUP_OPEN, | ||||
|   XML_ROLE_GROUP_CLOSE, | ||||
|   XML_ROLE_GROUP_CLOSE_REP, | ||||
|   XML_ROLE_GROUP_CLOSE_OPT, | ||||
|   XML_ROLE_GROUP_CLOSE_PLUS, | ||||
|   XML_ROLE_GROUP_CHOICE, | ||||
|   XML_ROLE_GROUP_SEQUENCE, | ||||
|   XML_ROLE_CONTENT_ELEMENT, | ||||
|   XML_ROLE_CONTENT_ELEMENT_REP, | ||||
|   XML_ROLE_CONTENT_ELEMENT_OPT, | ||||
|   XML_ROLE_CONTENT_ELEMENT_PLUS, | ||||
|   XML_ROLE_PI, | ||||
|   XML_ROLE_COMMENT, | ||||
| #ifdef XML_DTD | ||||
|   XML_ROLE_TEXT_DECL, | ||||
|   XML_ROLE_IGNORE_SECT, | ||||
|   XML_ROLE_INNER_PARAM_ENTITY_REF, | ||||
| #endif /* XML_DTD */ | ||||
|   XML_ROLE_PARAM_ENTITY_REF | ||||
| }; | ||||
| 
 | ||||
| typedef struct prolog_state { | ||||
|   int (PTRCALL *handler) (struct prolog_state *state, | ||||
|                           int tok, | ||||
|                           const char *ptr, | ||||
|                           const char *end, | ||||
|                           const ENCODING *enc); | ||||
|   unsigned level; | ||||
|   int role_none; | ||||
| #ifdef XML_DTD | ||||
|   unsigned includeLevel; | ||||
|   int documentEntity; | ||||
|   int inEntityValue; | ||||
| #endif /* XML_DTD */ | ||||
| } PROLOG_STATE; | ||||
| 
 | ||||
| void XmlPrologStateInit(PROLOG_STATE *); | ||||
| #ifdef XML_DTD | ||||
| void XmlPrologStateInitExternalEntity(PROLOG_STATE *); | ||||
| #endif /* XML_DTD */ | ||||
| 
 | ||||
| #define XmlTokenRole(state, tok, ptr, end, enc) \ | ||||
|  (((state)->handler)(state, tok, ptr, end, enc)) | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #endif /* not XmlRole_INCLUDED */ | ||||
							
								
								
									
										1737
									
								
								deps/EXPAT/expat/xmltok.c
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1737
									
								
								deps/EXPAT/expat/xmltok.c
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										322
									
								
								deps/EXPAT/expat/xmltok.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										322
									
								
								deps/EXPAT/expat/xmltok.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,322 @@ | |||
| /* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
 | ||||
|    See the file COPYING for copying permission. | ||||
| */ | ||||
| 
 | ||||
| #ifndef XmlTok_INCLUDED | ||||
| #define XmlTok_INCLUDED 1 | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| /* The following token may be returned by XmlContentTok */ | ||||
| #define XML_TOK_TRAILING_RSQB -5 /* ] or ]] at the end of the scan; might be | ||||
|                                     start of illegal ]]> sequence */ | ||||
| /* The following tokens may be returned by both XmlPrologTok and
 | ||||
|    XmlContentTok. | ||||
| */ | ||||
| #define XML_TOK_NONE -4          /* The string to be scanned is empty */ | ||||
| #define XML_TOK_TRAILING_CR -3   /* A CR at the end of the scan; | ||||
|                                     might be part of CRLF sequence */ | ||||
| #define XML_TOK_PARTIAL_CHAR -2  /* only part of a multibyte sequence */ | ||||
| #define XML_TOK_PARTIAL -1       /* only part of a token */ | ||||
| #define XML_TOK_INVALID 0 | ||||
| 
 | ||||
| /* The following tokens are returned by XmlContentTok; some are also
 | ||||
|    returned by XmlAttributeValueTok, XmlEntityTok, XmlCdataSectionTok. | ||||
| */ | ||||
| #define XML_TOK_START_TAG_WITH_ATTS 1 | ||||
| #define XML_TOK_START_TAG_NO_ATTS 2 | ||||
| #define XML_TOK_EMPTY_ELEMENT_WITH_ATTS 3 /* empty element tag <e/> */ | ||||
| #define XML_TOK_EMPTY_ELEMENT_NO_ATTS 4 | ||||
| #define XML_TOK_END_TAG 5 | ||||
| #define XML_TOK_DATA_CHARS 6 | ||||
| #define XML_TOK_DATA_NEWLINE 7 | ||||
| #define XML_TOK_CDATA_SECT_OPEN 8 | ||||
| #define XML_TOK_ENTITY_REF 9 | ||||
| #define XML_TOK_CHAR_REF 10               /* numeric character reference */ | ||||
| 
 | ||||
| /* The following tokens may be returned by both XmlPrologTok and
 | ||||
|    XmlContentTok. | ||||
| */ | ||||
| #define XML_TOK_PI 11                     /* processing instruction */ | ||||
| #define XML_TOK_XML_DECL 12               /* XML decl or text decl */ | ||||
| #define XML_TOK_COMMENT 13 | ||||
| #define XML_TOK_BOM 14                    /* Byte order mark */ | ||||
| 
 | ||||
| /* The following tokens are returned only by XmlPrologTok */ | ||||
| #define XML_TOK_PROLOG_S 15 | ||||
| #define XML_TOK_DECL_OPEN 16              /* <!foo */ | ||||
| #define XML_TOK_DECL_CLOSE 17             /* > */ | ||||
| #define XML_TOK_NAME 18 | ||||
| #define XML_TOK_NMTOKEN 19 | ||||
| #define XML_TOK_POUND_NAME 20             /* #name */ | ||||
| #define XML_TOK_OR 21                     /* | */ | ||||
| #define XML_TOK_PERCENT 22 | ||||
| #define XML_TOK_OPEN_PAREN 23 | ||||
| #define XML_TOK_CLOSE_PAREN 24 | ||||
| #define XML_TOK_OPEN_BRACKET 25 | ||||
| #define XML_TOK_CLOSE_BRACKET 26 | ||||
| #define XML_TOK_LITERAL 27 | ||||
| #define XML_TOK_PARAM_ENTITY_REF 28 | ||||
| #define XML_TOK_INSTANCE_START 29 | ||||
| 
 | ||||
| /* The following occur only in element type declarations */ | ||||
| #define XML_TOK_NAME_QUESTION 30          /* name? */ | ||||
| #define XML_TOK_NAME_ASTERISK 31          /* name* */ | ||||
| #define XML_TOK_NAME_PLUS 32              /* name+ */ | ||||
| #define XML_TOK_COND_SECT_OPEN 33         /* <![ */ | ||||
| #define XML_TOK_COND_SECT_CLOSE 34        /* ]]> */ | ||||
| #define XML_TOK_CLOSE_PAREN_QUESTION 35   /* )? */ | ||||
| #define XML_TOK_CLOSE_PAREN_ASTERISK 36   /* )* */ | ||||
| #define XML_TOK_CLOSE_PAREN_PLUS 37       /* )+ */ | ||||
| #define XML_TOK_COMMA 38 | ||||
| 
 | ||||
| /* The following token is returned only by XmlAttributeValueTok */ | ||||
| #define XML_TOK_ATTRIBUTE_VALUE_S 39 | ||||
| 
 | ||||
| /* The following token is returned only by XmlCdataSectionTok */ | ||||
| #define XML_TOK_CDATA_SECT_CLOSE 40 | ||||
| 
 | ||||
| /* With namespace processing this is returned by XmlPrologTok for a
 | ||||
|    name with a colon. | ||||
| */ | ||||
| #define XML_TOK_PREFIXED_NAME 41 | ||||
| 
 | ||||
| #ifdef XML_DTD | ||||
| #define XML_TOK_IGNORE_SECT 42 | ||||
| #endif /* XML_DTD */ | ||||
| 
 | ||||
| #ifdef XML_DTD | ||||
| #define XML_N_STATES 4 | ||||
| #else /* not XML_DTD */ | ||||
| #define XML_N_STATES 3 | ||||
| #endif /* not XML_DTD */ | ||||
| 
 | ||||
| #define XML_PROLOG_STATE 0 | ||||
| #define XML_CONTENT_STATE 1 | ||||
| #define XML_CDATA_SECTION_STATE 2 | ||||
| #ifdef XML_DTD | ||||
| #define XML_IGNORE_SECTION_STATE 3 | ||||
| #endif /* XML_DTD */ | ||||
| 
 | ||||
| #define XML_N_LITERAL_TYPES 2 | ||||
| #define XML_ATTRIBUTE_VALUE_LITERAL 0 | ||||
| #define XML_ENTITY_VALUE_LITERAL 1 | ||||
| 
 | ||||
| /* The size of the buffer passed to XmlUtf8Encode must be at least this. */ | ||||
| #define XML_UTF8_ENCODE_MAX 4 | ||||
| /* The size of the buffer passed to XmlUtf16Encode must be at least this. */ | ||||
| #define XML_UTF16_ENCODE_MAX 2 | ||||
| 
 | ||||
| typedef struct position { | ||||
|   /* first line and first column are 0 not 1 */ | ||||
|   XML_Size lineNumber; | ||||
|   XML_Size columnNumber; | ||||
| } POSITION; | ||||
| 
 | ||||
| typedef struct { | ||||
|   const char *name; | ||||
|   const char *valuePtr; | ||||
|   const char *valueEnd; | ||||
|   char normalized; | ||||
| } ATTRIBUTE; | ||||
| 
 | ||||
| struct encoding; | ||||
| typedef struct encoding ENCODING; | ||||
| 
 | ||||
| typedef int (PTRCALL *SCANNER)(const ENCODING *, | ||||
|                                const char *, | ||||
|                                const char *, | ||||
|                                const char **); | ||||
| 
 | ||||
| enum XML_Convert_Result { | ||||
|   XML_CONVERT_COMPLETED = 0, | ||||
|   XML_CONVERT_INPUT_INCOMPLETE = 1, | ||||
|   XML_CONVERT_OUTPUT_EXHAUSTED = 2  /* and therefore potentially input remaining as well */ | ||||
| }; | ||||
| 
 | ||||
| struct encoding { | ||||
|   SCANNER scanners[XML_N_STATES]; | ||||
|   SCANNER literalScanners[XML_N_LITERAL_TYPES]; | ||||
|   int (PTRCALL *sameName)(const ENCODING *, | ||||
|                           const char *, | ||||
|                           const char *); | ||||
|   int (PTRCALL *nameMatchesAscii)(const ENCODING *, | ||||
|                                   const char *, | ||||
|                                   const char *, | ||||
|                                   const char *); | ||||
|   int (PTRFASTCALL *nameLength)(const ENCODING *, const char *); | ||||
|   const char *(PTRFASTCALL *skipS)(const ENCODING *, const char *); | ||||
|   int (PTRCALL *getAtts)(const ENCODING *enc, | ||||
|                          const char *ptr, | ||||
|                          int attsMax, | ||||
|                          ATTRIBUTE *atts); | ||||
|   int (PTRFASTCALL *charRefNumber)(const ENCODING *enc, const char *ptr); | ||||
|   int (PTRCALL *predefinedEntityName)(const ENCODING *, | ||||
|                                       const char *, | ||||
|                                       const char *); | ||||
|   void (PTRCALL *updatePosition)(const ENCODING *, | ||||
|                                  const char *ptr, | ||||
|                                  const char *end, | ||||
|                                  POSITION *); | ||||
|   int (PTRCALL *isPublicId)(const ENCODING *enc, | ||||
|                             const char *ptr, | ||||
|                             const char *end, | ||||
|                             const char **badPtr); | ||||
|   enum XML_Convert_Result (PTRCALL *utf8Convert)(const ENCODING *enc, | ||||
|                               const char **fromP, | ||||
|                               const char *fromLim, | ||||
|                               char **toP, | ||||
|                               const char *toLim); | ||||
|   enum XML_Convert_Result (PTRCALL *utf16Convert)(const ENCODING *enc, | ||||
|                                const char **fromP, | ||||
|                                const char *fromLim, | ||||
|                                unsigned short **toP, | ||||
|                                const unsigned short *toLim); | ||||
|   int minBytesPerChar; | ||||
|   char isUtf8; | ||||
|   char isUtf16; | ||||
| }; | ||||
| 
 | ||||
| /* Scan the string starting at ptr until the end of the next complete
 | ||||
|    token, but do not scan past eptr.  Return an integer giving the | ||||
|    type of token. | ||||
| 
 | ||||
|    Return XML_TOK_NONE when ptr == eptr; nextTokPtr will not be set. | ||||
| 
 | ||||
|    Return XML_TOK_PARTIAL when the string does not contain a complete | ||||
|    token; nextTokPtr will not be set. | ||||
| 
 | ||||
|    Return XML_TOK_INVALID when the string does not start a valid | ||||
|    token; nextTokPtr will be set to point to the character which made | ||||
|    the token invalid. | ||||
| 
 | ||||
|    Otherwise the string starts with a valid token; nextTokPtr will be | ||||
|    set to point to the character following the end of that token. | ||||
| 
 | ||||
|    Each data character counts as a single token, but adjacent data | ||||
|    characters may be returned together.  Similarly for characters in | ||||
|    the prolog outside literals, comments and processing instructions. | ||||
| */ | ||||
| 
 | ||||
| 
 | ||||
| #define XmlTok(enc, state, ptr, end, nextTokPtr) \ | ||||
|   (((enc)->scanners[state])(enc, ptr, end, nextTokPtr)) | ||||
| 
 | ||||
| #define XmlPrologTok(enc, ptr, end, nextTokPtr) \ | ||||
|    XmlTok(enc, XML_PROLOG_STATE, ptr, end, nextTokPtr) | ||||
| 
 | ||||
| #define XmlContentTok(enc, ptr, end, nextTokPtr) \ | ||||
|    XmlTok(enc, XML_CONTENT_STATE, ptr, end, nextTokPtr) | ||||
| 
 | ||||
| #define XmlCdataSectionTok(enc, ptr, end, nextTokPtr) \ | ||||
|    XmlTok(enc, XML_CDATA_SECTION_STATE, ptr, end, nextTokPtr) | ||||
| 
 | ||||
| #ifdef XML_DTD | ||||
| 
 | ||||
| #define XmlIgnoreSectionTok(enc, ptr, end, nextTokPtr) \ | ||||
|    XmlTok(enc, XML_IGNORE_SECTION_STATE, ptr, end, nextTokPtr) | ||||
| 
 | ||||
| #endif /* XML_DTD */ | ||||
| 
 | ||||
| /* This is used for performing a 2nd-level tokenization on the content
 | ||||
|    of a literal that has already been returned by XmlTok. | ||||
| */ | ||||
| #define XmlLiteralTok(enc, literalType, ptr, end, nextTokPtr) \ | ||||
|   (((enc)->literalScanners[literalType])(enc, ptr, end, nextTokPtr)) | ||||
| 
 | ||||
| #define XmlAttributeValueTok(enc, ptr, end, nextTokPtr) \ | ||||
|    XmlLiteralTok(enc, XML_ATTRIBUTE_VALUE_LITERAL, ptr, end, nextTokPtr) | ||||
| 
 | ||||
| #define XmlEntityValueTok(enc, ptr, end, nextTokPtr) \ | ||||
|    XmlLiteralTok(enc, XML_ENTITY_VALUE_LITERAL, ptr, end, nextTokPtr) | ||||
| 
 | ||||
| #define XmlSameName(enc, ptr1, ptr2) (((enc)->sameName)(enc, ptr1, ptr2)) | ||||
| 
 | ||||
| #define XmlNameMatchesAscii(enc, ptr1, end1, ptr2) \ | ||||
|   (((enc)->nameMatchesAscii)(enc, ptr1, end1, ptr2)) | ||||
| 
 | ||||
| #define XmlNameLength(enc, ptr) \ | ||||
|   (((enc)->nameLength)(enc, ptr)) | ||||
| 
 | ||||
| #define XmlSkipS(enc, ptr) \ | ||||
|   (((enc)->skipS)(enc, ptr)) | ||||
| 
 | ||||
| #define XmlGetAttributes(enc, ptr, attsMax, atts) \ | ||||
|   (((enc)->getAtts)(enc, ptr, attsMax, atts)) | ||||
| 
 | ||||
| #define XmlCharRefNumber(enc, ptr) \ | ||||
|   (((enc)->charRefNumber)(enc, ptr)) | ||||
| 
 | ||||
| #define XmlPredefinedEntityName(enc, ptr, end) \ | ||||
|   (((enc)->predefinedEntityName)(enc, ptr, end)) | ||||
| 
 | ||||
| #define XmlUpdatePosition(enc, ptr, end, pos) \ | ||||
|   (((enc)->updatePosition)(enc, ptr, end, pos)) | ||||
| 
 | ||||
| #define XmlIsPublicId(enc, ptr, end, badPtr) \ | ||||
|   (((enc)->isPublicId)(enc, ptr, end, badPtr)) | ||||
| 
 | ||||
| #define XmlUtf8Convert(enc, fromP, fromLim, toP, toLim) \ | ||||
|   (((enc)->utf8Convert)(enc, fromP, fromLim, toP, toLim)) | ||||
| 
 | ||||
| #define XmlUtf16Convert(enc, fromP, fromLim, toP, toLim) \ | ||||
|   (((enc)->utf16Convert)(enc, fromP, fromLim, toP, toLim)) | ||||
| 
 | ||||
| typedef struct { | ||||
|   ENCODING initEnc; | ||||
|   const ENCODING **encPtr; | ||||
| } INIT_ENCODING; | ||||
| 
 | ||||
| int XmlParseXmlDecl(int isGeneralTextEntity, | ||||
|                     const ENCODING *enc, | ||||
|                     const char *ptr, | ||||
|                     const char *end, | ||||
|                     const char **badPtr, | ||||
|                     const char **versionPtr, | ||||
|                     const char **versionEndPtr, | ||||
|                     const char **encodingNamePtr, | ||||
|                     const ENCODING **namedEncodingPtr, | ||||
|                     int *standalonePtr); | ||||
| 
 | ||||
| int XmlInitEncoding(INIT_ENCODING *, const ENCODING **, const char *name); | ||||
| const ENCODING *XmlGetUtf8InternalEncoding(void); | ||||
| const ENCODING *XmlGetUtf16InternalEncoding(void); | ||||
| int FASTCALL XmlUtf8Encode(int charNumber, char *buf); | ||||
| int FASTCALL XmlUtf16Encode(int charNumber, unsigned short *buf); | ||||
| int XmlSizeOfUnknownEncoding(void); | ||||
| 
 | ||||
| 
 | ||||
| typedef int (XMLCALL *CONVERTER) (void *userData, const char *p); | ||||
| 
 | ||||
| ENCODING * | ||||
| XmlInitUnknownEncoding(void *mem, | ||||
|                        int *table, | ||||
|                        CONVERTER convert, | ||||
|                        void *userData); | ||||
| 
 | ||||
| int XmlParseXmlDeclNS(int isGeneralTextEntity, | ||||
|                       const ENCODING *enc, | ||||
|                       const char *ptr, | ||||
|                       const char *end, | ||||
|                       const char **badPtr, | ||||
|                       const char **versionPtr, | ||||
|                       const char **versionEndPtr, | ||||
|                       const char **encodingNamePtr, | ||||
|                       const ENCODING **namedEncodingPtr, | ||||
|                       int *standalonePtr); | ||||
| 
 | ||||
| int XmlInitEncodingNS(INIT_ENCODING *, const ENCODING **, const char *name); | ||||
| const ENCODING *XmlGetUtf8InternalEncodingNS(void); | ||||
| const ENCODING *XmlGetUtf16InternalEncodingNS(void); | ||||
| ENCODING * | ||||
| XmlInitUnknownEncodingNS(void *mem, | ||||
|                          int *table, | ||||
|                          CONVERTER convert, | ||||
|                          void *userData); | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #endif /* not XmlTok_INCLUDED */ | ||||
							
								
								
									
										46
									
								
								deps/EXPAT/expat/xmltok_impl.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								deps/EXPAT/expat/xmltok_impl.h
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,46 @@ | |||
| /*
 | ||||
| Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd | ||||
| See the file COPYING for copying permission. | ||||
| */ | ||||
| 
 | ||||
| enum { | ||||
|   BT_NONXML, | ||||
|   BT_MALFORM, | ||||
|   BT_LT, | ||||
|   BT_AMP, | ||||
|   BT_RSQB, | ||||
|   BT_LEAD2, | ||||
|   BT_LEAD3, | ||||
|   BT_LEAD4, | ||||
|   BT_TRAIL, | ||||
|   BT_CR, | ||||
|   BT_LF, | ||||
|   BT_GT, | ||||
|   BT_QUOT, | ||||
|   BT_APOS, | ||||
|   BT_EQUALS, | ||||
|   BT_QUEST, | ||||
|   BT_EXCL, | ||||
|   BT_SOL, | ||||
|   BT_SEMI, | ||||
|   BT_NUM, | ||||
|   BT_LSQB, | ||||
|   BT_S, | ||||
|   BT_NMSTRT, | ||||
|   BT_COLON, | ||||
|   BT_HEX, | ||||
|   BT_DIGIT, | ||||
|   BT_NAME, | ||||
|   BT_MINUS, | ||||
|   BT_OTHER, /* known not to be a name or name start character */ | ||||
|   BT_NONASCII, /* might be a name or name start character */ | ||||
|   BT_PERCNT, | ||||
|   BT_LPAR, | ||||
|   BT_RPAR, | ||||
|   BT_AST, | ||||
|   BT_PLUS, | ||||
|   BT_COMMA, | ||||
|   BT_VERBAR | ||||
| }; | ||||
| 
 | ||||
| #include <stddef.h> | ||||
							
								
								
									
										1779
									
								
								deps/EXPAT/expat/xmltok_impl.inc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1779
									
								
								deps/EXPAT/expat/xmltok_impl.inc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										115
									
								
								deps/EXPAT/expat/xmltok_ns.inc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								deps/EXPAT/expat/xmltok_ns.inc
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,115 @@ | |||
| /* Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd | ||||
|    See the file COPYING for copying permission. | ||||
| */ | ||||
| 
 | ||||
| /* This file is included! */ | ||||
| #ifdef XML_TOK_NS_C
 | ||||
| 
 | ||||
| const ENCODING * | ||||
| NS(XmlGetUtf8InternalEncoding)(void) | ||||
| { | ||||
|   return &ns(internal_utf8_encoding).enc; | ||||
| } | ||||
| 
 | ||||
| const ENCODING * | ||||
| NS(XmlGetUtf16InternalEncoding)(void) | ||||
| { | ||||
| #if BYTEORDER == 1234
 | ||||
|   return &ns(internal_little2_encoding).enc; | ||||
| #elif BYTEORDER == 4321
 | ||||
|   return &ns(internal_big2_encoding).enc; | ||||
| #else
 | ||||
|   const short n = 1; | ||||
|   return (*(const char *)&n | ||||
|           ? &ns(internal_little2_encoding).enc | ||||
|           : &ns(internal_big2_encoding).enc); | ||||
| #endif
 | ||||
| } | ||||
| 
 | ||||
| static const ENCODING * const NS(encodings)[] = { | ||||
|   &ns(latin1_encoding).enc, | ||||
|   &ns(ascii_encoding).enc, | ||||
|   &ns(utf8_encoding).enc, | ||||
|   &ns(big2_encoding).enc, | ||||
|   &ns(big2_encoding).enc, | ||||
|   &ns(little2_encoding).enc, | ||||
|   &ns(utf8_encoding).enc /* NO_ENC */ | ||||
| }; | ||||
| 
 | ||||
| static int PTRCALL | ||||
| NS(initScanProlog)(const ENCODING *enc, const char *ptr, const char *end, | ||||
|                    const char **nextTokPtr) | ||||
| { | ||||
|   return initScan(NS(encodings), (const INIT_ENCODING *)enc, | ||||
|                   XML_PROLOG_STATE, ptr, end, nextTokPtr); | ||||
| } | ||||
| 
 | ||||
| static int PTRCALL | ||||
| NS(initScanContent)(const ENCODING *enc, const char *ptr, const char *end, | ||||
|                     const char **nextTokPtr) | ||||
| { | ||||
|   return initScan(NS(encodings), (const INIT_ENCODING *)enc, | ||||
|                   XML_CONTENT_STATE, ptr, end, nextTokPtr); | ||||
| } | ||||
| 
 | ||||
| int | ||||
| NS(XmlInitEncoding)(INIT_ENCODING *p, const ENCODING **encPtr, | ||||
|                     const char *name) | ||||
| { | ||||
|   int i = getEncodingIndex(name); | ||||
|   if (i == UNKNOWN_ENC) | ||||
|     return 0; | ||||
|   SET_INIT_ENC_INDEX(p, i); | ||||
|   p->initEnc.scanners[XML_PROLOG_STATE] = NS(initScanProlog); | ||||
|   p->initEnc.scanners[XML_CONTENT_STATE] = NS(initScanContent); | ||||
|   p->initEnc.updatePosition = initUpdatePosition; | ||||
|   p->encPtr = encPtr; | ||||
|   *encPtr = &(p->initEnc); | ||||
|   return 1; | ||||
| } | ||||
| 
 | ||||
| static const ENCODING * | ||||
| NS(findEncoding)(const ENCODING *enc, const char *ptr, const char *end) | ||||
| { | ||||
| #define ENCODING_MAX 128
 | ||||
|   char buf[ENCODING_MAX]; | ||||
|   char *p = buf; | ||||
|   int i; | ||||
|   XmlUtf8Convert(enc, &ptr, end, &p, p + ENCODING_MAX - 1); | ||||
|   if (ptr != end) | ||||
|     return 0; | ||||
|   *p = 0; | ||||
|   if (streqci(buf, KW_UTF_16) && enc->minBytesPerChar == 2) | ||||
|     return enc; | ||||
|   i = getEncodingIndex(buf); | ||||
|   if (i == UNKNOWN_ENC) | ||||
|     return 0; | ||||
|   return NS(encodings)[i]; | ||||
| } | ||||
| 
 | ||||
| int | ||||
| NS(XmlParseXmlDecl)(int isGeneralTextEntity, | ||||
|                     const ENCODING *enc, | ||||
|                     const char *ptr, | ||||
|                     const char *end, | ||||
|                     const char **badPtr, | ||||
|                     const char **versionPtr, | ||||
|                     const char **versionEndPtr, | ||||
|                     const char **encodingName, | ||||
|                     const ENCODING **encoding, | ||||
|                     int *standalone) | ||||
| { | ||||
|   return doParseXmlDecl(NS(findEncoding), | ||||
|                         isGeneralTextEntity, | ||||
|                         enc, | ||||
|                         ptr, | ||||
|                         end, | ||||
|                         badPtr, | ||||
|                         versionPtr, | ||||
|                         versionEndPtr, | ||||
|                         encodingName, | ||||
|                         encoding, | ||||
|                         standalone); | ||||
| } | ||||
| 
 | ||||
| #endif /* XML_TOK_NS_C */
 | ||||
							
								
								
									
										1
									
								
								deps/GLEW/GLEW.cmake
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								deps/GLEW/GLEW.cmake
									
										
									
									
										vendored
									
									
								
							|  | @ -1,4 +1,5 @@ | |||
| # We have to check for OpenGL to compile GLEW | ||||
| set(OpenGL_GL_PREFERENCE "LEGACY") # to prevent a nasty warning by cmake | ||||
| find_package(OpenGL QUIET REQUIRED) | ||||
| 
 | ||||
| prusaslicer_add_cmake_project( | ||||
|  |  | |||
							
								
								
									
										4
									
								
								deps/OpenCSG/OpenCSG.cmake
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								deps/OpenCSG/OpenCSG.cmake
									
										
									
									
										vendored
									
									
								
							|  | @ -6,8 +6,8 @@ prusaslicer_add_cmake_project(OpenCSG | |||
|     DEPENDS dep_GLEW | ||||
| ) | ||||
| 
 | ||||
| if (TARGET dep_ZLIB) | ||||
|     add_dependencies(dep_OpenCSG dep_ZLIB) | ||||
| if (TARGET ${ZLIB_PKG}) | ||||
|     add_dependencies(dep_OpenCSG ${ZLIB_PKG}) | ||||
| endif() | ||||
| 
 | ||||
| if (MSVC) | ||||
|  |  | |||
							
								
								
									
										13
									
								
								deps/PNG/PNG.cmake
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								deps/PNG/PNG.cmake
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,13 @@ | |||
| prusaslicer_add_cmake_project(PNG  | ||||
|     GIT_REPOSITORY https://github.com/glennrp/libpng.git  | ||||
|     GIT_TAG v1.6.35 | ||||
|     DEPENDS ${ZLIB_PKG} | ||||
|     CMAKE_ARGS | ||||
|         -DPNG_SHARED=OFF | ||||
|         -DPNG_STATIC=ON | ||||
|         -DPNG_TESTS=OFF | ||||
| ) | ||||
| 
 | ||||
| if (MSVC) | ||||
|     add_debug_dep(dep_PNG) | ||||
| endif () | ||||
							
								
								
									
										48
									
								
								deps/deps-linux.cmake
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										48
									
								
								deps/deps-linux.cmake
									
										
									
									
										vendored
									
									
								
							|  | @ -3,6 +3,13 @@ set(DEP_CMAKE_OPTS "-DCMAKE_POSITION_INDEPENDENT_CODE=ON") | |||
| 
 | ||||
| include("deps-unix-common.cmake") | ||||
| 
 | ||||
| find_package(PNG QUIET) | ||||
| if (NOT PNG_FOUND) | ||||
|     message(WARNING "No PNG dev package found in system, building static library. You should install the system package.") | ||||
| endif () | ||||
| 
 | ||||
| #TODO UDEV | ||||
| 
 | ||||
| ExternalProject_Add(dep_boost | ||||
|     EXCLUDE_FROM_ALL 1 | ||||
|     URL "https://dl.bintray.com/boostorg/release/1.70.0/source/boost_1_70_0.tar.gz" | ||||
|  | @ -93,45 +100,4 @@ ExternalProject_Add(dep_libcurl | |||
|     INSTALL_COMMAND make install "DESTDIR=${DESTDIR}" | ||||
| ) | ||||
| 
 | ||||
| if (DEP_WX_STABLE) | ||||
|     set(DEP_WX_TAG "v3.0.4") | ||||
| else () | ||||
|     set(DEP_WX_TAG "v3.1.1-patched") | ||||
| endif() | ||||
| 
 | ||||
| if (DEP_WX_GTK3) | ||||
|     set(WX_GTK_VERSION "3") | ||||
| else () | ||||
|     set(WX_GTK_VERSION "2") | ||||
| endif() | ||||
| 
 | ||||
| ExternalProject_Add(dep_wxwidgets | ||||
|     EXCLUDE_FROM_ALL 1 | ||||
|     GIT_REPOSITORY "https://github.com/prusa3d/wxWidgets" | ||||
|     GIT_TAG "${DEP_WX_TAG}" | ||||
|     BUILD_IN_SOURCE 1 | ||||
|     # PATCH_COMMAND "${CMAKE_COMMAND}" -E copy "${CMAKE_CURRENT_SOURCE_DIR}/wxwidgets-pngprefix.h" src/png/pngprefix.h | ||||
|     CONFIGURE_COMMAND ./configure | ||||
|         "--prefix=${DESTDIR}/usr/local" | ||||
|         --disable-shared | ||||
|         --with-gtk=${WX_GTK_VERSION} | ||||
|         --with-opengl | ||||
|         --enable-unicode | ||||
|         --enable-graphics_ctx | ||||
|         --with-regex=builtin | ||||
|         --with-libpng=builtin | ||||
|         --with-libxpm=builtin | ||||
|         --with-libjpeg=builtin | ||||
|         --with-libtiff=builtin | ||||
|         --with-zlib | ||||
|         --with-expat=builtin | ||||
|         --disable-precomp-headers | ||||
|         --enable-debug_info | ||||
|         --enable-debug_gdb | ||||
|         --disable-debug | ||||
|         --disable-debug_flag | ||||
|     BUILD_COMMAND make "-j${NPROC}" && make -C locale allmo | ||||
|     INSTALL_COMMAND make install | ||||
| ) | ||||
| 
 | ||||
| add_dependencies(dep_openvdb dep_boost) | ||||
|  |  | |||
							
								
								
									
										26
									
								
								deps/deps-macos.cmake
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										26
									
								
								deps/deps-macos.cmake
									
										
									
									
										vendored
									
									
								
							|  | @ -86,30 +86,4 @@ ExternalProject_Add(dep_libcurl | |||
|     INSTALL_COMMAND make install "DESTDIR=${DESTDIR}" | ||||
| ) | ||||
| 
 | ||||
| ExternalProject_Add(dep_wxwidgets | ||||
|     EXCLUDE_FROM_ALL 1 | ||||
|     GIT_REPOSITORY "https://github.com/prusa3d/wxWidgets" | ||||
|     GIT_TAG v3.1.3-patched | ||||
|     BUILD_IN_SOURCE 1 | ||||
| #    PATCH_COMMAND "${CMAKE_COMMAND}" -E copy "${CMAKE_CURRENT_SOURCE_DIR}/wxwidgets-pngprefix.h" src/png/pngprefix.h | ||||
|     CONFIGURE_COMMAND env "CXXFLAGS=${DEP_WERRORS_SDK}" "CFLAGS=${DEP_WERRORS_SDK}" ./configure | ||||
|         "--prefix=${DESTDIR}/usr/local" | ||||
|         --disable-shared | ||||
|         --with-osx_cocoa | ||||
|         --with-macosx-sdk=${CMAKE_OSX_SYSROOT} | ||||
|         "--with-macosx-version-min=${DEP_OSX_TARGET}" | ||||
|         --with-opengl | ||||
|         --with-regex=builtin | ||||
|         --with-libpng=builtin | ||||
|         --with-libxpm=builtin | ||||
|         --with-libjpeg=builtin | ||||
|         --with-libtiff=builtin | ||||
|         --with-zlib | ||||
|         --with-expat=builtin | ||||
|         --disable-debug | ||||
|         --disable-debug_flag | ||||
|     BUILD_COMMAND make "-j${NPROC}" && PATH=/usr/local/opt/gettext/bin/:$ENV{PATH} make -C locale allmo | ||||
|     INSTALL_COMMAND make install | ||||
| ) | ||||
| 
 | ||||
| add_dependencies(dep_openvdb dep_boost) | ||||
							
								
								
									
										16
									
								
								deps/deps-mingw.cmake
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										16
									
								
								deps/deps-mingw.cmake
									
										
									
									
										vendored
									
									
								
							|  | @ -57,20 +57,4 @@ ExternalProject_Add(dep_libcurl | |||
|         -DCURL_DISABLE_GOPHER=ON | ||||
|         -DCMAKE_INSTALL_PREFIX=${DESTDIR}/usr/local | ||||
|         ${DEP_CMAKE_OPTS} | ||||
| ) | ||||
| 
 | ||||
| ExternalProject_Add(dep_wxwidgets | ||||
|     EXCLUDE_FROM_ALL 1 | ||||
|     GIT_REPOSITORY "https://github.com/prusa3d/wxWidgets" | ||||
|     GIT_TAG v3.1.1-patched | ||||
| #    URL "https://github.com/wxWidgets/wxWidgets/releases/download/v3.1.1/wxWidgets-3.1.1.tar.bz2" | ||||
| #    URL_HASH SHA256=c925dfe17e8f8b09eb7ea9bfdcfcc13696a3e14e92750effd839f5e10726159e | ||||
| #    PATCH_COMMAND "${CMAKE_COMMAND}" -E copy "${CMAKE_CURRENT_SOURCE_DIR}\\wxwidgets-pngprefix.h" src\\png\\pngprefix.h | ||||
|     CMAKE_ARGS | ||||
|         -DBUILD_SHARED_LIBS=OFF | ||||
|         -DwxUSE_LIBPNG=builtin | ||||
|         -DwxUSE_ZLIB=builtin | ||||
|         -DwxUSE_OPENGL=ON | ||||
|         -DCMAKE_INSTALL_PREFIX=${DESTDIR}/usr/local | ||||
|         ${DEP_CMAKE_OPTS} | ||||
| ) | ||||
							
								
								
									
										8
									
								
								deps/deps-unix-common.cmake
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								deps/deps-unix-common.cmake
									
										
									
									
										vendored
									
									
								
							|  | @ -9,9 +9,15 @@ endif () | |||
| 
 | ||||
| find_package(ZLIB QUIET) | ||||
| if (NOT ZLIB_FOUND) | ||||
|     include(ZLIB/ZLIB.cmake) | ||||
|     message(WARNING "No ZLIB dev package found in system, building static library. You should install the system package.") | ||||
| endif () | ||||
| 
 | ||||
| # TODO Evaluate expat modifications in the bundled version and test with system versions in various distros and OSX SDKs | ||||
| # find_package(EXPAT QUIET) | ||||
| # if (NOT EXPAT_FOUND) | ||||
| #     message(WARNING "No EXPAT dev package found in system, building static library. Consider installing the system package.") | ||||
| # endif () | ||||
| 
 | ||||
| ExternalProject_Add(dep_tbb | ||||
|     EXCLUDE_FROM_ALL 1 | ||||
|     URL "https://github.com/wjakob/tbb/archive/a0dc9bf76d0120f917b641ed095360448cabc85b.tar.gz" | ||||
|  |  | |||
							
								
								
									
										61
									
								
								deps/deps-windows.cmake
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										61
									
								
								deps/deps-windows.cmake
									
										
									
									
										vendored
									
									
								
							|  | @ -149,38 +149,6 @@ ExternalProject_Add(dep_nlopt | |||
| 
 | ||||
| add_debug_dep(dep_nlopt) | ||||
| 
 | ||||
| include(ZLIB/ZLIB.cmake) | ||||
| # ExternalProject_Add(dep_zlib | ||||
| #     EXCLUDE_FROM_ALL 1 | ||||
| #     URL "https://zlib.net/zlib-1.2.11.tar.xz" | ||||
| #     URL_HASH SHA256=4ff941449631ace0d4d203e3483be9dbc9da454084111f97ea0a2114e19bf066 | ||||
| #     CMAKE_GENERATOR "${DEP_MSVC_GEN}" | ||||
| #     CMAKE_GENERATOR_PLATFORM "${DEP_PLATFORM}" | ||||
| #     CMAKE_ARGS | ||||
| #         -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_INSTALL_PREFIX:PATH=${DESTDIR}\\usr\\local" | ||||
| #     BUILD_COMMAND msbuild /m /P:Configuration=Release INSTALL.vcxproj | ||||
| #     INSTALL_COMMAND "" | ||||
| # ) | ||||
| 
 | ||||
| add_debug_dep(dep_ZLIB) | ||||
| 
 | ||||
| # 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 () | ||||
| 
 | ||||
| if (${DEPS_BITS} EQUAL 32) | ||||
|     set(DEP_LIBCURL_TARGET "x86") | ||||
| else () | ||||
|  | @ -243,36 +211,13 @@ endif () | |||
| 
 | ||||
| find_package(Git REQUIRED) | ||||
| 
 | ||||
| ExternalProject_Add(dep_wxwidgets | ||||
|     EXCLUDE_FROM_ALL 1 | ||||
|     GIT_REPOSITORY "https://github.com/prusa3d/wxWidgets" | ||||
|     GIT_TAG v3.1.1-patched | ||||
| #    URL "https://github.com/wxWidgets/wxWidgets/releases/download/v3.1.1/wxWidgets-3.1.1.tar.bz2" | ||||
| #    URL_HASH SHA256=c925dfe17e8f8b09eb7ea9bfdcfcc13696a3e14e92750effd839f5e10726159e | ||||
|     BUILD_IN_SOURCE 1 | ||||
| #    PATCH_COMMAND "${CMAKE_COMMAND}" -E copy "${CMAKE_CURRENT_SOURCE_DIR}\\wxwidgets-pngprefix.h" src\\png\\pngprefix.h | ||||
|     CONFIGURE_COMMAND "" | ||||
|     BUILD_COMMAND cd build\\msw && nmake /f makefile.vc BUILD=release SHARED=0 UNICODE=1 USE_GUI=1 "${DEP_WXWIDGETS_TARGET}" | ||||
|     INSTALL_COMMAND "${CMAKE_COMMAND}" -E copy_directory include "${DESTDIR}\\usr\\local\\include" | ||||
|         && "${CMAKE_COMMAND}" -E copy_directory "lib\\${DEP_WXWIDGETS_LIBDIR}" "${DESTDIR}\\usr\\local\\lib\\${DEP_WXWIDGETS_LIBDIR}" | ||||
| ) | ||||
| if (${DEP_DEBUG}) | ||||
|     ExternalProject_Get_Property(dep_wxwidgets SOURCE_DIR) | ||||
|     ExternalProject_Add_Step(dep_wxwidgets build_debug | ||||
|         DEPENDEES build | ||||
|         DEPENDERS install | ||||
|         COMMAND cd build\\msw && nmake /f makefile.vc BUILD=debug SHARED=0 UNICODE=1 USE_GUI=1 "${DEP_WXWIDGETS_TARGET}" | ||||
|         WORKING_DIRECTORY "${SOURCE_DIR}" | ||||
|     ) | ||||
| endif () | ||||
| 
 | ||||
| ExternalProject_Add(dep_blosc | ||||
|     EXCLUDE_FROM_ALL 1 | ||||
|     #URL https://github.com/Blosc/c-blosc/archive/v1.17.0.zip | ||||
|     #URL_HASH SHA256=7463a1df566704f212263312717ab2c36b45d45cba6cd0dccebf91b2cc4b4da9 | ||||
|     GIT_REPOSITORY https://github.com/Blosc/c-blosc.git | ||||
|     GIT_TAG e63775855294b50820ef44d1b157f4de1cc38d3e #v1.17.0 | ||||
|     DEPENDS dep_ZLIB | ||||
|     DEPENDS ${ZLIB_PKG} | ||||
|     CMAKE_GENERATOR "${DEP_MSVC_GEN}" | ||||
|     CMAKE_GENERATOR_PLATFORM "${DEP_PLATFORM}" | ||||
|     CMAKE_ARGS | ||||
|  | @ -299,7 +244,7 @@ ExternalProject_Add(dep_openexr | |||
|     EXCLUDE_FROM_ALL 1 | ||||
|     GIT_REPOSITORY https://github.com/openexr/openexr.git | ||||
|     GIT_TAG eae0e337c9f5117e78114fd05f7a415819df413a #v2.4.0  | ||||
|     DEPENDS dep_ZLIB | ||||
|     DEPENDS ${ZLIB_PKG} | ||||
|     CMAKE_GENERATOR "${DEP_MSVC_GEN}" | ||||
|     CMAKE_GENERATOR_PLATFORM "${DEP_PLATFORM}" | ||||
|     CMAKE_ARGS | ||||
|  | @ -352,4 +297,4 @@ if (${DEP_DEBUG}) | |||
|         COMMAND msbuild /m /P:Configuration=Debug INSTALL.vcxproj | ||||
|         WORKING_DIRECTORY "${BINARY_DIR}" | ||||
|     ) | ||||
| endif () | ||||
| endif () | ||||
							
								
								
									
										36
									
								
								deps/wxWidgets/wxWidgets.cmake
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								deps/wxWidgets/wxWidgets.cmake
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,36 @@ | |||
| set(_wx_git_tag v3.1.3-patched) | ||||
| 
 | ||||
| # set(_patch_command "") | ||||
| set(_wx_toolkit "") | ||||
| if(CMAKE_SYSTEM_NAME STREQUAL "Linux") | ||||
|     set(_gtk_ver 2) | ||||
|     if (DEP_WX_GTK3) | ||||
|         set(_gtk_ver 3) | ||||
|     endif () | ||||
|     set(_wx_toolkit "-DwxBUILD_TOOLKIT=gtk${_gtk_ver}") | ||||
| endif() | ||||
| 
 | ||||
| prusaslicer_add_cmake_project(wxWidgets | ||||
|     GIT_REPOSITORY "https://github.com/prusa3d/wxWidgets" | ||||
|     GIT_TAG ${_wx_git_tag} | ||||
|     # PATCH_COMMAND "${_patch_command}" | ||||
|     DEPENDS ${PNG_PKG} ${ZLIB_PKG} ${EXPAT_PKG} | ||||
|     CMAKE_ARGS | ||||
|         -DwxBUILD_PRECOMP=ON | ||||
|         ${_wx_toolkit} | ||||
|         "-DCMAKE_DEBUG_POSTFIX:STRING=" | ||||
|         -DwxUSE_DETECT_SM=OFF | ||||
|         -DwxUSE_UNICODE=ON | ||||
|         -DwxUSE_OPENGL=ON | ||||
|         -DwxUSE_LIBPNG=sys | ||||
|         -DwxUSE_ZLIB=sys | ||||
|         -DwxUSE_REGEX=builtin | ||||
|         -DwxUSE_LIBXPM=builtin | ||||
|         -DwxUSE_LIBJPEG=builtin | ||||
|         -DwxUSE_LIBTIFF=builtin | ||||
|         -DwxUSE_EXPAT=sys | ||||
| ) | ||||
| 
 | ||||
| if (MSVC) | ||||
|     add_debug_dep(dep_wxWidgets) | ||||
| endif () | ||||
							
								
								
									
										12
									
								
								resources/icons/attention.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								resources/icons/attention.svg
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,12 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <!-- Generator: Adobe Illustrator 24.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  --> | ||||
| <svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" | ||||
| 	 viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve"> | ||||
| <g id="attention"> | ||||
| 	<path fill="#ED0000" d="M8,1.85l5.29,3.53V7v3.62L8,14.15l-5.29-3.53V7V5.38L8,1.85 M8,1L2,5v2v4l6,4l6-4V7V5L8,1L8,1z"/>	 | ||||
| 	 | ||||
|     <path fill="none" stroke="#ED0000" stroke-linecap="round" stroke-width="3" d="M8 4 L8 8" /> | ||||
| 		 | ||||
| 	<circle fill="#ED0000" cx="8" cy="12" r="1.5"/>	 | ||||
| </g> | ||||
| </svg> | ||||
| After Width: | Height: | Size: 641 B | 
							
								
								
									
										16
									
								
								resources/icons/collapse.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								resources/icons/collapse.svg
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,16 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0)  --> | ||||
| <svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" | ||||
| 	 viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve"> | ||||
| <g id="cross"> | ||||
| 	<g><line fill="none" stroke="#ED6B21" stroke-width="1" stroke-linecap="round" stroke-miterlimit="10" x1="12" y1="1" x2="15" y2="4"/></g> | ||||
| 	<g><line fill="none" stroke="#ED6B21" stroke-width="1" stroke-linecap="round" stroke-miterlimit="10" x1="12" y1="7" x2="15" y2="4"/></g> | ||||
| 	<g><line fill="none" stroke="#ED6B21" stroke-width="1" stroke-linecap="round" stroke-miterlimit="10" x1="8"  y1="1" x2="11" y2="4"/></g> | ||||
| 	<g><line fill="none" stroke="#ED6B21" stroke-width="1" stroke-linecap="round" stroke-miterlimit="10" x1="8"  y1="7" x2="11" y2="4"/></g> | ||||
| 	 | ||||
| 	<g><line fill="none" stroke="#ED6B21" stroke-width="1" stroke-linecap="round" stroke-miterlimit="10" x1="4" y1="9"  x2="1" y2="12"/></g> | ||||
| 	<g><line fill="none" stroke="#ED6B21" stroke-width="1" stroke-linecap="round" stroke-miterlimit="10" x1="4" y1="15" x2="1" y2="12"/></g> | ||||
| 	<g><line fill="none" stroke="#ED6B21" stroke-width="1" stroke-linecap="round" stroke-miterlimit="10" x1="8" y1="9"  x2="5" y2="12"/></g> | ||||
| 	<g><line fill="none" stroke="#ED6B21" stroke-width="1" stroke-linecap="round" stroke-miterlimit="10" x1="8" y1="15" x2="5" y2="12"/></g> | ||||
| </g> | ||||
| </svg> | ||||
| After Width: | Height: | Size: 1.4 KiB | 
							
								
								
									
										4
									
								
								resources/icons/search.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								resources/icons/search.svg
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,4 @@ | |||
| <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24px" height="24px"> | ||||
| <path fill="#808080" d="M 13.261719 14.867188 L 15.742188 17.347656 C 15.363281 18.070313 15.324219 18.789063 15.722656 19.1875 L 20.25 23.714844 C 20.820313 24.285156 22.0625 23.972656 23.015625 23.015625 C 23.972656 22.058594 24.285156 20.820313 23.714844 20.25 L 19.191406 15.722656 C 18.789063 15.324219 18.070313 15.363281 17.347656 15.738281 L 14.867188 13.261719 Z M 8.5 0 C 3.804688 0 0 3.804688 0 8.5 C 0 13.195313 3.804688 17 8.5 17 C 13.195313 17 17 13.195313 17 8.5 C 17 3.804688 13.195313 0 8.5 0 Z M 8.5 15 C 4.910156 15 2 12.089844 2 8.5 C 2 4.910156 4.910156 2 8.5 2 C 12.089844 2 15 4.910156 15 8.5 C 15 12.089844 12.089844 15 8.5 15 Z"/> | ||||
| <path fill="#ED6B21" d="M 13.261719 14.867188 L 19.191406 15.722656 C 18.789063 15.324219 18.070313 15.363281 17.347656 15.738281 M 8.5 0 C 3.804688 0 0 3.804688 0 8.5 C 0 13.195313 3.804688 17 8.5 17 C 13.195313 17 17 13.195313 17 8.5 C 17 3.804688 13.195313 0 8.5 0 Z M 8.5 15 C 4.910156 15 2 12.089844 2 8.5 C 2 4.910156 4.910156 2 8.5 2 C 12.089844 2 15 4.910156 15 8.5 C 15 12.089844 12.089844 15 8.5 15 Z"/> | ||||
| </svg> | ||||
| After Width: | Height: | Size: 1.1 KiB | 
							
								
								
									
										4
									
								
								resources/icons/search_.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								resources/icons/search_.svg
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,4 @@ | |||
| <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24px" height="24px"> | ||||
| <path fill="#FFFFFF" d="M 13.261719 14.867188 L 15.742188 17.347656 C 15.363281 18.070313 15.324219 18.789063 15.722656 19.1875 L 20.25 23.714844 C 20.820313 24.285156 22.0625 23.972656 23.015625 23.015625 C 23.972656 22.058594 24.285156 20.820313 23.714844 20.25 L 19.191406 15.722656 C 18.789063 15.324219 18.070313 15.363281 17.347656 15.738281 L 14.867188 13.261719 Z M 8.5 0 C 3.804688 0 0 3.804688 0 8.5 C 0 13.195313 3.804688 17 8.5 17 C 13.195313 17 17 13.195313 17 8.5 C 17 3.804688 13.195313 0 8.5 0 Z M 8.5 15 C 4.910156 15 2 12.089844 2 8.5 C 2 4.910156 4.910156 2 8.5 2 C 12.089844 2 15 4.910156 15 8.5 C 15 12.089844 12.089844 15 8.5 15 Z"/> | ||||
| <path fill="#ED6B21" d="M 13.261719 14.867188 L 19.191406 15.722656 C 18.789063 15.324219 18.070313 15.363281 17.347656 15.738281 M 8.5 0 C 3.804688 0 0 3.804688 0 8.5 C 0 13.195313 3.804688 17 8.5 17 C 13.195313 17 17 13.195313 17 8.5 C 17 3.804688 13.195313 0 8.5 0 Z M 8.5 15 C 4.910156 15 2 12.089844 2 8.5 C 2 4.910156 4.910156 2 8.5 2 C 12.089844 2 15 4.910156 15 8.5 C 15 12.089844 12.089844 15 8.5 15 Z"/> | ||||
| </svg> | ||||
| After Width: | Height: | Size: 1.1 KiB | 
							
								
								
									
										4
									
								
								resources/icons/search_gray.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								resources/icons/search_gray.svg
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,4 @@ | |||
| <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24px" height="24px"> | ||||
| <path fill="#808080" d="M 13.261719 14.867188 L 15.742188 17.347656 C 15.363281 18.070313 15.324219 18.789063 15.722656 19.1875 L 20.25 23.714844 C 20.820313 24.285156 22.0625 23.972656 23.015625 23.015625 C 23.972656 22.058594 24.285156 20.820313 23.714844 20.25 L 19.191406 15.722656 C 18.789063 15.324219 18.070313 15.363281 17.347656 15.738281 L 14.867188 13.261719 Z M 8.5 0 C 3.804688 0 0 3.804688 0 8.5 C 0 13.195313 3.804688 17 8.5 17 C 13.195313 17 17 13.195313 17 8.5 C 17 3.804688 13.195313 0 8.5 0 Z M 8.5 15 C 4.910156 15 2 12.089844 2 8.5 C 2 4.910156 4.910156 2 8.5 2 C 12.089844 2 15 4.910156 15 8.5 C 15 12.089844 12.089844 15 8.5 15 Z"/> | ||||
| <path fill="#808080" d="M 13.261719 14.867188 L 19.191406 15.722656 C 18.789063 15.324219 18.070313 15.363281 17.347656 15.738281 M 8.5 0 C 3.804688 0 0 3.804688 0 8.5 C 0 13.195313 3.804688 17 8.5 17 C 13.195313 17 17 13.195313 17 8.5 C 17 3.804688 13.195313 0 8.5 0 Z M 8.5 15 C 4.910156 15 2 12.089844 2 8.5 C 2 4.910156 4.910156 2 8.5 2 C 12.089844 2 15 4.910156 15 8.5 C 15 12.089844 12.089844 15 8.5 15 Z"/> | ||||
| </svg> | ||||
| After Width: | Height: | Size: 1.1 KiB | 
|  | @ -59,6 +59,29 @@ if (SLIC3R_GUI) | |||
| 
 | ||||
|     include(${wxWidgets_USE_FILE}) | ||||
| 
 | ||||
|     string(REGEX MATCH "wxpng" WX_PNG_BUILTIN ${wxWidgets_LIBRARIES}) | ||||
|     if (PNG_FOUND AND NOT WX_PNG_BUILTIN) | ||||
|         list(FILTER wxWidgets_LIBRARIES EXCLUDE REGEX png) | ||||
|         list(APPEND wxWidgets_LIBRARIES ${PNG_LIBRARIES}) | ||||
|     endif () | ||||
| 
 | ||||
|     string(REGEX MATCH "wxexpat" WX_EXPAT_BUILTIN ${wxWidgets_LIBRARIES}) | ||||
|     if (EXPAT_FOUND AND NOT WX_EXPAT_BUILTIN) | ||||
|         list(FILTER wxWidgets_LIBRARIES EXCLUDE REGEX expat) | ||||
|         list(APPEND wxWidgets_LIBRARIES ${EXPAT_LIBRARIES}) | ||||
|     endif () | ||||
| 
 | ||||
|     # This is an issue in the new wxWidgets cmake build, doesn't deal with librt | ||||
|     find_library(LIBRT rt) | ||||
|     if(LIBRT) | ||||
|         list(APPEND wxWidgets_LIBRARIES ${LIBRT}) | ||||
|     endif() | ||||
| 
 | ||||
|     # This fixes a OpenGL linking issue on OSX. wxWidgets cmake build includes | ||||
|     # wrong libs for opengl in the link line and it does not link to it by himself. | ||||
|     # libslic3r_gui will link to opengl anyway, so lets override wx | ||||
|     list(FILTER wxWidgets_LIBRARIES EXCLUDE REGEX OpenGL) | ||||
| 
 | ||||
| #    list(REMOVE_ITEM wxWidgets_LIBRARIES oleacc) | ||||
|     message(STATUS "wx libs: ${wxWidgets_LIBRARIES}") | ||||
| 
 | ||||
|  | @ -178,13 +201,13 @@ if (WIN32) | |||
| elseif (XCODE) | ||||
|     # Because of Debug/Release/etc. configurations (similar to MSVC) the slic3r binary is located in an extra level | ||||
|     add_custom_command(TARGET PrusaSlicer POST_BUILD | ||||
|         COMMAND ln -sf "${SLIC3R_RESOURCES_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/resources" | ||||
|         COMMAND ln -sfn "${SLIC3R_RESOURCES_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/resources" | ||||
|         COMMENT "Symlinking the resources directory into the build tree" | ||||
|         VERBATIM | ||||
|     ) | ||||
| else () | ||||
|     add_custom_command(TARGET PrusaSlicer POST_BUILD | ||||
|         COMMAND ln -sf "${SLIC3R_RESOURCES_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/../resources" | ||||
|         COMMAND ln -sfn "${SLIC3R_RESOURCES_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/../resources" | ||||
|         COMMENT "Symlinking the resources directory into the build tree" | ||||
|         VERBATIM | ||||
|     ) | ||||
|  |  | |||
|  | @ -51,13 +51,14 @@ | |||
|     #include "slic3r/GUI/GUI.hpp" | ||||
|     #include "slic3r/GUI/GUI_App.hpp" | ||||
|     #include "slic3r/GUI/3DScene.hpp" | ||||
|     #include "slic3r/GUI/InstanceCheck.hpp"  | ||||
|     #include "slic3r/GUI/AppConfig.hpp"  | ||||
| #endif /* SLIC3R_GUI */ | ||||
| 
 | ||||
| using namespace Slic3r; | ||||
| 
 | ||||
| int CLI::run(int argc, char **argv) | ||||
| { | ||||
| 
 | ||||
| #ifdef __WXGTK__ | ||||
|     // On Linux, wxGTK has no support for Wayland, and the app crashes on
 | ||||
|     // startup if gtk3 is used. This env var has to be set explicitly to
 | ||||
|  | @ -524,6 +525,16 @@ int CLI::run(int argc, char **argv) | |||
| #ifdef SLIC3R_GUI | ||||
| // #ifdef USE_WX
 | ||||
|         GUI::GUI_App *gui = new GUI::GUI_App(); | ||||
| 
 | ||||
| 		bool gui_single_instance_setting = gui->app_config->get("single_instance") == "1"; | ||||
| 		if (Slic3r::instance_check(argc, argv, gui_single_instance_setting)) { | ||||
| 			//TODO: do we have delete gui and other stuff?
 | ||||
| 			return -1; | ||||
| 		} | ||||
| 		 | ||||
| 		//gui->app_config = app_config;
 | ||||
| 		//app_config = nullptr;
 | ||||
| 		 | ||||
| //		gui->autosave = m_config.opt_string("autosave");
 | ||||
|         GUI::GUI_App::SetInstance(gui); | ||||
|         gui->CallAfter([gui, this, &load_configs] { | ||||
|  |  | |||
|  | @ -7,6 +7,8 @@ | |||
| #include <shellapi.h> | ||||
| #include <wchar.h> | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| #ifdef SLIC3R_GUI | ||||
| extern "C" | ||||
| { | ||||
|  | @ -216,7 +218,6 @@ int APIENTRY wWinMain(HINSTANCE /* hInstance */, HINSTANCE /* hPrevInstance */, | |||
| int wmain(int argc, wchar_t **argv) | ||||
| { | ||||
| #endif | ||||
| 
 | ||||
|     std::vector<wchar_t*> argv_extended; | ||||
|     argv_extended.emplace_back(argv[0]); | ||||
| 
 | ||||
|  |  | |||
|  | @ -97,9 +97,17 @@ | |||
| //#define IMGUI_DEBUG_PARANOID
 | ||||
| 
 | ||||
| //---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files.
 | ||||
| /*
 | ||||
| 
 | ||||
| namespace ImGui | ||||
| { | ||||
|     void MyFunction(const char* name, const MyMatrix44& v); | ||||
|     // Special ASCII character is used here as markup symbols for tokens to be highlighted as a for hovered item
 | ||||
|     const char ColorMarkerHovered   = 0x1; // STX
 | ||||
| 
 | ||||
|     // Special ASCII characters STX and ETX are used here as markup symbols for tokens to be highlighted.
 | ||||
|     const char ColorMarkerStart = 0x2; // STX
 | ||||
|     const char ColorMarkerEnd   = 0x3; // ETX
 | ||||
| 
 | ||||
| //    void MyFunction(const char* name, const MyMatrix44& v);
 | ||||
| 
 | ||||
| } | ||||
| */ | ||||
| 
 | ||||
|  |  | |||
|  | @ -33,6 +33,7 @@ Index of this file: | |||
| #define IMGUI_DEFINE_MATH_OPERATORS | ||||
| #endif | ||||
| #include "imgui_internal.h" | ||||
| #include "imconfig.h" | ||||
| 
 | ||||
| #include <stdio.h>      // vsnprintf, sscanf, printf
 | ||||
| #if !defined(alloca) | ||||
|  | @ -2991,6 +2992,15 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col | |||
|     ImDrawIdx* idx_write = draw_list->_IdxWritePtr; | ||||
|     unsigned int vtx_current_idx = draw_list->_VtxCurrentIdx; | ||||
| 
 | ||||
|     ImU32 defaultCol = col; | ||||
|     ImU32 highlighCol = ImGui::GetColorU32(ImGuiCol_ButtonHovered); | ||||
| 
 | ||||
|     // if text is started with ColorMarkerHovered symbol, we should use another color for a highlighting
 | ||||
|     if (*s == ImGui::ColorMarkerHovered) { | ||||
|         highlighCol = ImGui::GetColorU32(ImGuiCol_FrameBg); | ||||
|         s += 1; | ||||
|     } | ||||
| 
 | ||||
|     while (s < text_end) | ||||
|     { | ||||
|         if (word_wrap_enabled) | ||||
|  | @ -3019,6 +3029,17 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col | |||
|             } | ||||
|         } | ||||
| 
 | ||||
|         if (*s == ImGui::ColorMarkerStart) { | ||||
|             col = highlighCol; | ||||
|             s += 1; | ||||
|         } | ||||
|         else if (*s == ImGui::ColorMarkerEnd) { | ||||
|             col = defaultCol; | ||||
|             s += 1; | ||||
|             if (s == text_end) | ||||
|                 break; | ||||
|         } | ||||
| 
 | ||||
|         // Decode and advance source
 | ||||
|         unsigned int c = (unsigned int)*s; | ||||
|         if (c < 0x80) | ||||
|  |  | |||
|  | @ -272,7 +272,8 @@ endif () | |||
| encoding_check(libslic3r) | ||||
| 
 | ||||
| target_compile_definitions(libslic3r PUBLIC -DUSE_TBB -DTBB_USE_CAPTURED_EXCEPTION=0) | ||||
| target_include_directories(libslic3r PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${LIBNEST2D_INCLUDES} PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) | ||||
| target_include_directories(libslic3r PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) | ||||
| target_include_directories(libslic3r PUBLIC ${EXPAT_INCLUDE_DIRS}) | ||||
| target_link_libraries(libslic3r | ||||
|     libnest2d | ||||
|     admesh | ||||
|  |  | |||
|  | @ -312,6 +312,7 @@ std::string ExtrusionEntity::role_to_string(ExtrusionRole role) | |||
|         case erOverhangPerimeter            : return L("Overhang perimeter"); | ||||
|         case erInternalInfill               : return L("Internal infill"); | ||||
|         case erSolidInfill                  : return L("Solid infill"); | ||||
|         case erIroning                      : return L("Ironing"); | ||||
|         case erTopSolidInfill               : return L("Top solid infill"); | ||||
|         case erBridgeInfill                 : return L("Bridge infill"); | ||||
|         case erGapFill                      : return L("Gap fill"); | ||||
|  |  | |||
|  | @ -22,6 +22,7 @@ enum ExtrusionRole : uint8_t { | |||
|     erInternalInfill, | ||||
|     erSolidInfill, | ||||
|     erTopSolidInfill, | ||||
|     erIroning, | ||||
|     erBridgeInfill, | ||||
|     erGapFill, | ||||
|     erSkirt, | ||||
|  | @ -54,14 +55,16 @@ inline bool is_infill(ExtrusionRole role) | |||
|     return role == erBridgeInfill | ||||
|         || role == erInternalInfill | ||||
|         || role == erSolidInfill | ||||
|         || role == erTopSolidInfill; | ||||
|         || role == erTopSolidInfill | ||||
|         || role == erIroning; | ||||
| } | ||||
| 
 | ||||
| inline bool is_solid_infill(ExtrusionRole role) | ||||
| { | ||||
|     return role == erBridgeInfill | ||||
|         || role == erSolidInfill | ||||
|         || role == erTopSolidInfill; | ||||
|         || role == erTopSolidInfill | ||||
|         || role == erIroning; | ||||
| } | ||||
| 
 | ||||
| inline bool is_bridge(ExtrusionRole role) { | ||||
|  |  | |||
|  | @ -10,6 +10,7 @@ | |||
| #include "../Surface.hpp" | ||||
| 
 | ||||
| #include "FillBase.hpp" | ||||
| #include "FillRectilinear2.hpp" | ||||
| 
 | ||||
| namespace Slic3r { | ||||
| 
 | ||||
|  | @ -372,7 +373,11 @@ void Layer::make_fills() | |||
| 			// Spacing is modified by the filler to indicate adjustments. Reset it for each expolygon.
 | ||||
| 			f->spacing = surface_fill.params.spacing; | ||||
| 			surface_fill.surface.expolygon = std::move(expoly); | ||||
| 			Polylines polylines = f->fill_surface(&surface_fill.surface, params); | ||||
| 			Polylines polylines; | ||||
| 			try { | ||||
| 				polylines = f->fill_surface(&surface_fill.surface, params); | ||||
| 			} catch (InfillFailedException &) { | ||||
| 			} | ||||
| 	        if (! polylines.empty()) { | ||||
| 		        // calculate actual flow from spacing (which might have been adjusted by the infill
 | ||||
| 		        // pattern generator)
 | ||||
|  | @ -388,8 +393,8 @@ void Layer::make_fills() | |||
| 		        	flow_width      = new_flow.width; | ||||
| 		        } | ||||
| 		        // Save into layer.
 | ||||
| 		        auto *eec = new ExtrusionEntityCollection(); | ||||
| 		        m_regions[surface_fill.region_id]->fills.entities.push_back(eec); | ||||
| 				ExtrusionEntityCollection* eec = nullptr; | ||||
| 		        m_regions[surface_fill.region_id]->fills.entities.push_back(eec = new ExtrusionEntityCollection()); | ||||
| 		        // Only concentric fills are not sorted.
 | ||||
| 		        eec->no_sort = f->no_sort(); | ||||
| 		        extrusion_entities_append_paths( | ||||
|  | @ -418,4 +423,170 @@ void Layer::make_fills() | |||
| #endif | ||||
| } | ||||
| 
 | ||||
| // Create ironing extrusions over top surfaces.
 | ||||
| void Layer::make_ironing() | ||||
| { | ||||
| 	// LayerRegion::slices contains surfaces marked with SurfaceType.
 | ||||
| 	// Here we want to collect top surfaces extruded with the same extruder.
 | ||||
| 	// A surface will be ironed with the same extruder to not contaminate the print with another material leaking from the nozzle.
 | ||||
| 
 | ||||
| 	// First classify regions based on the extruder used.
 | ||||
| 	struct IroningParams { | ||||
| 		int 		extruder 	= -1; | ||||
| 		bool 		just_infill = false; | ||||
| 		// Spacing of the ironing lines, also to calculate the extrusion flow from.
 | ||||
| 		double 		line_spacing; | ||||
| 		// Height of the extrusion, to calculate the extrusion flow from.
 | ||||
| 		double 		height; | ||||
| 		double 		speed; | ||||
| 		double 		angle; | ||||
| 
 | ||||
| 		bool operator<(const IroningParams &rhs) const { | ||||
| 			if (this->extruder < rhs.extruder) | ||||
| 				return true; | ||||
| 			if (this->extruder > rhs.extruder) | ||||
| 				return false; | ||||
| 			if (int(this->just_infill) < int(rhs.just_infill)) | ||||
| 				return true; | ||||
| 			if (int(this->just_infill) > int(rhs.just_infill)) | ||||
| 				return false; | ||||
| 			if (this->line_spacing < rhs.line_spacing) | ||||
| 				return true; | ||||
| 			if (this->line_spacing > rhs.line_spacing) | ||||
| 				return false; | ||||
| 			if (this->height < rhs.height) | ||||
| 				return true; | ||||
| 			if (this->height > rhs.height) | ||||
| 				return false; | ||||
| 			if (this->speed < rhs.speed) | ||||
| 				return true; | ||||
| 			if (this->speed > rhs.speed) | ||||
| 				return false; | ||||
| 			if (this->angle < rhs.angle) | ||||
| 				return true; | ||||
| 			if (this->angle > rhs.angle) | ||||
| 				return false; | ||||
| 			return false; | ||||
| 		} | ||||
| 
 | ||||
| 		bool operator==(const IroningParams &rhs) const { | ||||
| 			return this->extruder == rhs.extruder && this->just_infill == rhs.just_infill && | ||||
| 				   this->line_spacing == rhs.line_spacing && this->height == rhs.height && this->speed == rhs.speed && | ||||
| 				   this->angle == rhs.angle; | ||||
| 		} | ||||
| 
 | ||||
| 		LayerRegion *layerm		= nullptr; | ||||
| 
 | ||||
| 		// IdeaMaker: ironing
 | ||||
| 		// ironing flowrate (5% percent)
 | ||||
| 		// ironing speed (10 mm/sec)
 | ||||
| 
 | ||||
| 		// Kisslicer: 
 | ||||
| 		// iron off, Sweep, Group
 | ||||
| 		// ironing speed: 15 mm/sec
 | ||||
| 
 | ||||
| 		// Cura:
 | ||||
| 		// Pattern (zig-zag / concentric)
 | ||||
| 		// line spacing (0.1mm)
 | ||||
| 		// flow: from normal layer height. 10%
 | ||||
| 		// speed: 20 mm/sec
 | ||||
| 	}; | ||||
| 
 | ||||
| 	std::vector<IroningParams> by_extruder; | ||||
| 	bool   extruder_dont_care   = this->object()->config().wipe_into_objects; | ||||
|     double default_layer_height = this->object()->config().layer_height; | ||||
| 
 | ||||
| 	for (LayerRegion *layerm : m_regions) | ||||
| 		if (! layerm->slices.empty()) { | ||||
| 			IroningParams ironing_params; | ||||
| 			const PrintRegionConfig &config = layerm->region()->config(); | ||||
| 			if (config.ironing &&  | ||||
| 				(config.ironing_type == IroningType::AllSolid || | ||||
| 				 	(config.top_solid_layers > 0 &&  | ||||
| 						(config.ironing_type == IroningType::TopSurfaces || | ||||
| 					 	(config.ironing_type == IroningType::TopmostOnly && layerm->layer()->upper_layer == nullptr))))) { | ||||
| 				if (config.perimeter_extruder == config.solid_infill_extruder || config.perimeters == 0) { | ||||
| 					// Iron the whole face.
 | ||||
| 					ironing_params.extruder = config.solid_infill_extruder; | ||||
| 				} else { | ||||
| 					// Iron just the infill.
 | ||||
| 					ironing_params.extruder = config.solid_infill_extruder; | ||||
| 				} | ||||
| 			} | ||||
| 			if (ironing_params.extruder != -1) { | ||||
| 				ironing_params.just_infill 	= false; | ||||
| 				ironing_params.line_spacing = config.ironing_spacing; | ||||
| 				ironing_params.height 		= default_layer_height * 0.01 * config.ironing_flowrate; | ||||
| 				ironing_params.speed 		= config.ironing_speed; | ||||
| 				ironing_params.angle 		= config.fill_angle * M_PI / 180.; | ||||
| 				ironing_params.layerm 		= layerm; | ||||
| 				by_extruder.emplace_back(ironing_params); | ||||
| 			} | ||||
| 		} | ||||
| 	std::sort(by_extruder.begin(), by_extruder.end()); | ||||
| 
 | ||||
|     FillRectilinear2 	fill; | ||||
|     FillParams 			fill_params; | ||||
| 	fill.set_bounding_box(this->object()->bounding_box()); | ||||
| 	fill.layer_id 			 = this->id(); | ||||
|     fill.z 					 = this->print_z; | ||||
|     fill.overlap 			 = 0; | ||||
|     fill_params.density 	 = 1.; | ||||
| //    fill_params.dont_connect = true;
 | ||||
|     fill_params.dont_connect = false; | ||||
|     fill_params.monotonous   = true; | ||||
| 
 | ||||
| 	for (size_t i = 0; i < by_extruder.size(); ++ i) { | ||||
| 		// Find span of regions equivalent to the ironing operation.
 | ||||
| 		IroningParams &ironing_params = by_extruder[i]; | ||||
| 		size_t j = i; | ||||
| 		for (++ j; j < by_extruder.size() && ironing_params == by_extruder[j]; ++ j) ; | ||||
| 
 | ||||
| 		// Create the ironing extrusions for regions <i, j)
 | ||||
| 		ExPolygons ironing_areas; | ||||
| 		double nozzle_dmr = this->object()->print()->config().nozzle_diameter.values[ironing_params.extruder - 1]; | ||||
| 		if (ironing_params.just_infill) { | ||||
| 			// Just infill.
 | ||||
| 		} else { | ||||
| 			// Infill and perimeter.
 | ||||
| 			// Merge top surfaces with the same ironing parameters.
 | ||||
| 			Polygons polys; | ||||
| 			for (size_t k = i; k < j; ++ k) | ||||
| 				for (const Surface &surface : by_extruder[k].layerm->slices.surfaces) | ||||
| 					if (surface.surface_type == stTop) | ||||
| 						polygons_append(polys, surface.expolygon); | ||||
| 			// Trim the top surfaces with half the nozzle diameter.
 | ||||
| 			ironing_areas = intersection_ex(polys, offset(this->lslices, - float(scale_(0.5 * nozzle_dmr)))); | ||||
| 		} | ||||
| 
 | ||||
|         // Create the filler object.
 | ||||
|         fill.spacing = ironing_params.line_spacing; | ||||
|         fill.angle = float(ironing_params.angle + 0.25 * M_PI); | ||||
|         fill.link_max_length = (coord_t)scale_(3. * fill.spacing); | ||||
| 		double height = ironing_params.height * fill.spacing / nozzle_dmr; | ||||
|         Flow flow = Flow::new_from_spacing(float(nozzle_dmr), 0., float(height), false); | ||||
|         double flow_mm3_per_mm = flow.mm3_per_mm(); | ||||
|         Surface surface_fill(stTop, ExPolygon()); | ||||
|         for (ExPolygon &expoly : ironing_areas) { | ||||
| 			surface_fill.expolygon = std::move(expoly); | ||||
| 			Polylines polylines; | ||||
| 			try { | ||||
| 				polylines = fill.fill_surface(&surface_fill, fill_params); | ||||
| 			} catch (InfillFailedException &) { | ||||
| 			} | ||||
| 	        if (! polylines.empty()) { | ||||
| 		        // Save into layer.
 | ||||
| 				ExtrusionEntityCollection *eec = nullptr; | ||||
| 		        ironing_params.layerm->fills.entities.push_back(eec = new ExtrusionEntityCollection()); | ||||
| 		        // Don't sort the ironing infill lines as they are monotonously ordered.
 | ||||
| 				eec->no_sort = true; | ||||
| 		        extrusion_entities_append_paths( | ||||
| 		            eec->entities, std::move(polylines), | ||||
| 		            erIroning, | ||||
| 		            flow_mm3_per_mm, float(flow.width), float(height)); | ||||
| 		    } | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| } // namespace Slic3r
 | ||||
|  |  | |||
|  | @ -27,7 +27,7 @@ Fill* Fill::new_from_type(const InfillPattern type) | |||
|     case ip3DHoneycomb:         return new Fill3DHoneycomb(); | ||||
|     case ipGyroid:              return new FillGyroid(); | ||||
|     case ipRectilinear:         return new FillRectilinear2(); | ||||
| //  case ipRectilinear:         return new FillRectilinear();
 | ||||
|     case ipMonotonous:          return new FillMonotonous(); | ||||
|     case ipLine:                return new FillLine(); | ||||
|     case ipGrid:                return new FillGrid2(); | ||||
|     case ipTriangles:           return new FillTriangles(); | ||||
|  |  | |||
|  | @ -5,6 +5,7 @@ | |||
| #include <memory.h> | ||||
| #include <float.h> | ||||
| #include <stdint.h> | ||||
| #include <stdexcept> | ||||
| 
 | ||||
| #include <type_traits> | ||||
| 
 | ||||
|  | @ -18,29 +19,31 @@ namespace Slic3r { | |||
| class ExPolygon; | ||||
| class Surface; | ||||
| 
 | ||||
| class InfillFailedException : public std::runtime_error { | ||||
| public: | ||||
|     InfillFailedException() : std::runtime_error("Infill failed") {} | ||||
| }; | ||||
| 
 | ||||
| struct FillParams | ||||
| { | ||||
|     FillParams() {  | ||||
|         memset(this, 0, sizeof(FillParams)); | ||||
|         // Adjustment does not work.
 | ||||
|         dont_adjust = true; | ||||
|     } | ||||
| 
 | ||||
|     bool        full_infill() const { return density > 0.9999f; } | ||||
| 
 | ||||
|     // Fill density, fraction in <0, 1>
 | ||||
|     float       density; | ||||
|     float       density 		{ 0.f }; | ||||
| 
 | ||||
|     // Don't connect the fill lines around the inner perimeter.
 | ||||
|     bool        dont_connect; | ||||
|     bool        dont_connect 	{ false }; | ||||
| 
 | ||||
|     // Don't adjust spacing to fill the space evenly.
 | ||||
|     bool        dont_adjust; | ||||
|     bool        dont_adjust 	{ true }; | ||||
| 
 | ||||
|     // Monotonous infill - strictly left to right for better surface quality of top infills.
 | ||||
|     bool 		monotonous		{ false }; | ||||
| 
 | ||||
|     // For Honeycomb.
 | ||||
|     // we were requested to complete each loop;
 | ||||
|     // in this case we don't try to make more continuous paths
 | ||||
|     bool        complete; | ||||
|     bool        complete 		{ false }; | ||||
| }; | ||||
| static_assert(IsTriviallyCopyable<FillParams>::value, "FillParams class is not POD (and it should be - see constructor)."); | ||||
| 
 | ||||
|  |  | |||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -13,18 +13,27 @@ class FillRectilinear2 : public Fill | |||
| { | ||||
| public: | ||||
|     virtual Fill* clone() const { return new FillRectilinear2(*this); }; | ||||
|     virtual ~FillRectilinear2() {} | ||||
|     virtual ~FillRectilinear2() = default; | ||||
|     virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms); | ||||
| 
 | ||||
| protected: | ||||
| 	bool fill_surface_by_lines(const Surface *surface, const FillParams ¶ms, float angleBase, float pattern_shift, Polylines &polylines_out); | ||||
| }; | ||||
| 
 | ||||
| class FillMonotonous : public FillRectilinear2 | ||||
| { | ||||
| public: | ||||
|     virtual Fill* clone() const { return new FillMonotonous(*this); }; | ||||
|     virtual ~FillMonotonous() = default; | ||||
|     virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms); | ||||
| 	virtual bool no_sort() const { return true; } | ||||
| }; | ||||
| 
 | ||||
| class FillGrid2 : public FillRectilinear2 | ||||
| { | ||||
| public: | ||||
|     virtual Fill* clone() const { return new FillGrid2(*this); }; | ||||
|     virtual ~FillGrid2() {} | ||||
|     virtual ~FillGrid2() = default; | ||||
|     virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms); | ||||
| 
 | ||||
| protected: | ||||
|  | @ -36,7 +45,7 @@ class FillTriangles : public FillRectilinear2 | |||
| { | ||||
| public: | ||||
|     virtual Fill* clone() const { return new FillTriangles(*this); }; | ||||
|     virtual ~FillTriangles() {} | ||||
|     virtual ~FillTriangles() = default; | ||||
|     virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms); | ||||
| 
 | ||||
| protected: | ||||
|  | @ -48,7 +57,7 @@ class FillStars : public FillRectilinear2 | |||
| { | ||||
| public: | ||||
|     virtual Fill* clone() const { return new FillStars(*this); }; | ||||
|     virtual ~FillStars() {} | ||||
|     virtual ~FillStars() = default; | ||||
|     virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms); | ||||
| 
 | ||||
| protected: | ||||
|  | @ -60,7 +69,7 @@ class FillCubic : public FillRectilinear2 | |||
| { | ||||
| public: | ||||
|     virtual Fill* clone() const { return new FillCubic(*this); }; | ||||
|     virtual ~FillCubic() {} | ||||
|     virtual ~FillCubic() = default; | ||||
|     virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms); | ||||
| 
 | ||||
| protected: | ||||
|  |  | |||
|  | @ -2246,12 +2246,14 @@ void GCode::process_layer( | |||
|                     const auto& by_region_specific = is_anything_overridden ? island.by_region_per_copy(by_region_per_copy_cache, static_cast<unsigned int>(instance_to_print.instance_id), extruder_id, print_wipe_extrusions != 0) : island.by_region; | ||||
|                 	//FIXME the following code prints regions in the order they are defined, the path is not optimized in any way.
 | ||||
|                     if (print.config().infill_first) { | ||||
|                         gcode += this->extrude_infill(print, by_region_specific); | ||||
|                         gcode += this->extrude_infill(print, by_region_specific, false); | ||||
|                         gcode += this->extrude_perimeters(print, by_region_specific, lower_layer_edge_grids[instance_to_print.layer_id]); | ||||
|                     } else { | ||||
|                         gcode += this->extrude_perimeters(print, by_region_specific, lower_layer_edge_grids[instance_to_print.layer_id]); | ||||
|                         gcode += this->extrude_infill(print,by_region_specific); | ||||
|                         gcode += this->extrude_infill(print,by_region_specific, false); | ||||
|                     } | ||||
|                     // ironing
 | ||||
|                     gcode += this->extrude_infill(print,by_region_specific, true); | ||||
|                 } | ||||
|                 if (this->config().gcode_label_objects) | ||||
| 					gcode += std::string("; stop printing object ") + instance_to_print.print_object.model_object()->name + " id:" + std::to_string(instance_to_print.layer_id) + " copy " + std::to_string(instance_to_print.instance_id) + "\n"; | ||||
|  | @ -2873,22 +2875,30 @@ std::string GCode::extrude_perimeters(const Print &print, const std::vector<Obje | |||
| } | ||||
| 
 | ||||
| // Chain the paths hierarchically by a greedy algorithm to minimize a travel distance.
 | ||||
| std::string GCode::extrude_infill(const Print &print, const std::vector<ObjectByExtruder::Island::Region> &by_region) | ||||
| std::string GCode::extrude_infill(const Print &print, const std::vector<ObjectByExtruder::Island::Region> &by_region, bool ironing) | ||||
| { | ||||
|     std::string gcode; | ||||
|     std::string 		 gcode; | ||||
|     ExtrusionEntitiesPtr extrusions; | ||||
|     const char*          extrusion_name = ironing ? "ironing" : "infill"; | ||||
|     for (const ObjectByExtruder::Island::Region ®ion : by_region) | ||||
|         if (! region.infills.empty()) { | ||||
|             m_config.apply(print.regions()[®ion - &by_region.front()]->config()); | ||||
| 		    ExtrusionEntitiesPtr extrusions { region.infills }; | ||||
| 		    chain_and_reorder_extrusion_entities(extrusions, &m_last_pos); | ||||
|             for (const ExtrusionEntity *fill : extrusions) { | ||||
|                 auto *eec = dynamic_cast<const ExtrusionEntityCollection*>(fill); | ||||
|                 if (eec) { | ||||
| 				    for (ExtrusionEntity *ee : eec->chained_path_from(m_last_pos).entities) | ||||
|                         gcode += this->extrude_entity(*ee, "infill"); | ||||
|                 } else | ||||
|                     gcode += this->extrude_entity(*fill, "infill"); | ||||
|             } | ||||
|         	extrusions.clear(); | ||||
|         	extrusions.reserve(region.infills.size()); | ||||
|         	for (ExtrusionEntity *ee : region.infills) | ||||
|         		if ((ee->role() == erIroning) == ironing) | ||||
|         			extrusions.emplace_back(ee); | ||||
|         	if (! extrusions.empty()) { | ||||
| 	            m_config.apply(print.regions()[®ion - &by_region.front()]->config()); | ||||
| 			    chain_and_reorder_extrusion_entities(extrusions, &m_last_pos); | ||||
| 	            for (const ExtrusionEntity *fill : extrusions) { | ||||
| 	                auto *eec = dynamic_cast<const ExtrusionEntityCollection*>(fill); | ||||
| 	                if (eec) { | ||||
| 					    for (ExtrusionEntity *ee : eec->chained_path_from(m_last_pos).entities) | ||||
| 	                        gcode += this->extrude_entity(*ee, extrusion_name); | ||||
| 	                } else | ||||
| 	                    gcode += this->extrude_entity(*fill, extrusion_name); | ||||
| 	            } | ||||
| 	        } | ||||
|         } | ||||
|     return gcode; | ||||
| } | ||||
|  | @ -3027,6 +3037,8 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description, | |||
|             speed = m_config.get_abs_value("solid_infill_speed"); | ||||
|         } else if (path.role() == erTopSolidInfill) { | ||||
|             speed = m_config.get_abs_value("top_solid_infill_speed"); | ||||
|         } else if (path.role() == erIroning) { | ||||
|             speed = m_config.get_abs_value("ironing_speed"); | ||||
|         } else if (path.role() == erGapFill) { | ||||
|             speed = m_config.get_abs_value("gap_fill_speed"); | ||||
|         } else { | ||||
|  | @ -3427,10 +3439,13 @@ void GCode::ObjectByExtruder::Island::Region::append(const Type type, const Extr | |||
| 
 | ||||
|     // First we append the entities, there are eec->entities.size() of them:
 | ||||
|     size_t old_size = perimeters_or_infills->size(); | ||||
|     size_t new_size = old_size + eec->entities.size(); | ||||
|     size_t new_size = old_size + (eec->can_reverse() ? eec->entities.size() : 1); | ||||
|     perimeters_or_infills->reserve(new_size); | ||||
|     for (auto* ee : eec->entities) | ||||
|         perimeters_or_infills->emplace_back(ee); | ||||
|     if (eec->can_reverse()) { | ||||
| 	    for (auto* ee : eec->entities) | ||||
| 	        perimeters_or_infills->emplace_back(ee); | ||||
| 	} else | ||||
| 		perimeters_or_infills->emplace_back(const_cast<ExtrusionEntityCollection*>(eec)); | ||||
| 
 | ||||
|     if (copies_extruder != nullptr) { | ||||
|     	// Don't reallocate overrides if not needed.
 | ||||
|  |  | |||
|  | @ -295,7 +295,7 @@ private: | |||
| 		const size_t                     				 single_object_instance_idx); | ||||
| 
 | ||||
|     std::string     extrude_perimeters(const Print &print, const std::vector<ObjectByExtruder::Island::Region> &by_region, std::unique_ptr<EdgeGrid::Grid> &lower_layer_edge_grid); | ||||
|     std::string     extrude_infill(const Print &print, const std::vector<ObjectByExtruder::Island::Region> &by_region); | ||||
|     std::string     extrude_infill(const Print &print, const std::vector<ObjectByExtruder::Island::Region> &by_region, bool ironing); | ||||
|     std::string     extrude_support(const ExtrusionEntityCollection &support_fills); | ||||
| 
 | ||||
|     std::string     travel_to(const Point &point, ExtrusionRole role, std::string comment); | ||||
|  |  | |||
|  | @ -117,6 +117,7 @@ const Color GCodePreviewData::Extrusion::Default_Extrusion_Role_Colors[erCount] | |||
|     Color(1.0f, 1.0f, 0.0f, 1.0f),   // erInternalInfill
 | ||||
|     Color(1.0f, 0.0f, 1.0f, 1.0f),   // erSolidInfill
 | ||||
|     Color(0.0f, 1.0f, 1.0f, 1.0f),   // erTopSolidInfill
 | ||||
|     Color(0.0f, 1.0f, 1.0f, 1.0f),   // erIroning    
 | ||||
|     Color(0.5f, 0.5f, 0.5f, 1.0f),   // erBridgeInfill
 | ||||
|     Color(1.0f, 1.0f, 1.0f, 1.0f),   // erGapFill
 | ||||
|     Color(0.5f, 0.0f, 0.0f, 1.0f),   // erSkirt
 | ||||
|  |  | |||
|  | @ -36,11 +36,6 @@ public: | |||
|     // collection of surfaces for infill generation
 | ||||
|     SurfaceCollection           fill_surfaces; | ||||
| 
 | ||||
|     // Collection of perimeter surfaces. This is a cached result of diff(slices, fill_surfaces).
 | ||||
|     // While not necessary, the memory consumption is meager and it speeds up calculation.
 | ||||
|     // The perimeter_surfaces keep the IDs of the slices (top/bottom/)
 | ||||
|     SurfaceCollection           perimeter_surfaces; | ||||
| 
 | ||||
|     // collection of expolygons representing the bridged areas (thus not
 | ||||
|     // needing support material)
 | ||||
|     Polygons                    bridged; | ||||
|  | @ -140,6 +135,7 @@ public: | |||
|     } | ||||
|     void                    make_perimeters(); | ||||
|     void                    make_fills(); | ||||
|     void 					make_ironing(); | ||||
| 
 | ||||
|     void                    export_region_slices_to_svg(const char *path) const; | ||||
|     void                    export_region_fill_surfaces_to_svg(const char *path) const; | ||||
|  |  | |||
|  | @ -1586,6 +1586,8 @@ void Print::process() | |||
|     this->set_status(70, L("Infilling layers")); | ||||
|     for (PrintObject *obj : m_objects) | ||||
|         obj->infill(); | ||||
|     for (PrintObject *obj : m_objects) | ||||
|         obj->ironing(); | ||||
|     for (PrintObject *obj : m_objects) | ||||
|         obj->generate_support_material(); | ||||
|     if (this->set_started(psWipeTower)) { | ||||
|  |  | |||
|  | @ -41,7 +41,7 @@ enum PrintStep { | |||
| 
 | ||||
| enum PrintObjectStep { | ||||
|     posSlice, posPerimeters, posPrepareInfill, | ||||
|     posInfill, posSupportMaterial, posCount, | ||||
|     posInfill, posIroning, posSupportMaterial, posCount, | ||||
| }; | ||||
| 
 | ||||
| // A PrintRegion object represents a group of volumes to print
 | ||||
|  | @ -223,6 +223,7 @@ private: | |||
|     void make_perimeters(); | ||||
|     void prepare_infill(); | ||||
|     void infill(); | ||||
|     void ironing(); | ||||
|     void generate_support_material(); | ||||
| 
 | ||||
|     void _slice(const std::vector<coordf_t> &layer_height_profile); | ||||
|  |  | |||
|  | @ -39,6 +39,11 @@ void PrintConfigDef::init_common_params() | |||
| { | ||||
|     ConfigOptionDef* def; | ||||
| 
 | ||||
| 	def = this->add("single_instance", coBool); | ||||
| 	def->label = L("Single Instance"); | ||||
| 	def->mode = comAdvanced; | ||||
| 	def->set_default_value(new ConfigOptionBool(false)); | ||||
| 
 | ||||
|     def = this->add("printer_technology", coEnum); | ||||
|     def->label = L("Printer technology"); | ||||
|     def->tooltip = L("Printer technology"); | ||||
|  | @ -144,6 +149,7 @@ void PrintConfigDef::init_fff_params() | |||
|     def->label = L("Other layers"); | ||||
|     def->tooltip = L("Bed temperature for layers after the first one. " | ||||
|                    "Set this to zero to disable bed temperature control commands in the output."); | ||||
|     def->sidetext = L("°C"); | ||||
|     def->full_label = L("Bed temperature"); | ||||
|     def->min = 0; | ||||
|     def->max = 300; | ||||
|  | @ -418,18 +424,20 @@ void PrintConfigDef::init_fff_params() | |||
|     def->cli = "top-fill-pattern|external-fill-pattern|solid-fill-pattern"; | ||||
|     def->enum_keys_map = &ConfigOptionEnum<InfillPattern>::get_enum_values(); | ||||
|     def->enum_values.push_back("rectilinear"); | ||||
|     def->enum_values.push_back("monotonous"); | ||||
|     def->enum_values.push_back("concentric"); | ||||
|     def->enum_values.push_back("hilbertcurve"); | ||||
|     def->enum_values.push_back("archimedeanchords"); | ||||
|     def->enum_values.push_back("octagramspiral"); | ||||
|     def->enum_labels.push_back(L("Rectilinear")); | ||||
|     def->enum_labels.push_back(L("Monotonous")); | ||||
|     def->enum_labels.push_back(L("Concentric")); | ||||
|     def->enum_labels.push_back(L("Hilbert Curve")); | ||||
|     def->enum_labels.push_back(L("Archimedean Chords")); | ||||
|     def->enum_labels.push_back(L("Octagram Spiral")); | ||||
|     // solid_fill_pattern is an obsolete equivalent to top_fill_pattern/bottom_fill_pattern.
 | ||||
|     def->aliases = { "solid_fill_pattern", "external_fill_pattern" }; | ||||
|     def->set_default_value(new ConfigOptionEnum<InfillPattern>(ipRectilinear)); | ||||
|     def->set_default_value(new ConfigOptionEnum<InfillPattern>(ipMonotonous)); | ||||
| 
 | ||||
|     def = this->add("bottom_fill_pattern", coEnum); | ||||
|     def->label = L("Bottom fill pattern"); | ||||
|  | @ -866,8 +874,10 @@ void PrintConfigDef::init_fff_params() | |||
| 
 | ||||
|     def = this->add("first_layer_bed_temperature", coInts); | ||||
|     def->label = L("First layer"); | ||||
|     def->full_label = L("First layer bed temperature"); | ||||
|     def->tooltip = L("Heated build plate temperature for the first layer. Set this to zero to disable " | ||||
|                    "bed temperature control commands in the output."); | ||||
|     def->sidetext = L("°C"); | ||||
|     def->max = 0; | ||||
|     def->max = 300; | ||||
|     def->set_default_value(new ConfigOptionInts { 0 }); | ||||
|  | @ -908,8 +918,10 @@ void PrintConfigDef::init_fff_params() | |||
| 
 | ||||
|     def = this->add("first_layer_temperature", coInts); | ||||
|     def->label = L("First layer"); | ||||
|     def->full_label = L("First layer extruder temperature"); | ||||
|     def->tooltip = L("Extruder temperature for first layer. If you want to control temperature manually " | ||||
|                    "during print, set this to zero to disable temperature control commands in the output file."); | ||||
|     def->sidetext = L("°C"); | ||||
|     def->min = 0; | ||||
|     def->max = max_temp; | ||||
|     def->set_default_value(new ConfigOptionInts { 200 }); | ||||
|  | @ -1076,6 +1088,53 @@ void PrintConfigDef::init_fff_params() | |||
|     def->mode = comExpert; | ||||
|     def->set_default_value(new ConfigOptionBool(false)); | ||||
| 
 | ||||
|     def = this->add("ironing", coBool); | ||||
|     def->label = L("Enable ironing"); | ||||
|     def->tooltip = L("Enable ironing of the top layers with the hot print head for smooth surface"); | ||||
|     def->category = L("Ironing"); | ||||
|     def->mode = comAdvanced; | ||||
|     def->set_default_value(new ConfigOptionBool(false)); | ||||
| 
 | ||||
|     def = this->add("ironing_type", coEnum); | ||||
|     def->label = L("Ironingy Type"); | ||||
|     def->tooltip = L("Ironingy Type"); | ||||
|     def->enum_keys_map = &ConfigOptionEnum<IroningType>::get_enum_values(); | ||||
|     def->enum_values.push_back("top"); | ||||
|     def->enum_values.push_back("topmost"); | ||||
|     def->enum_values.push_back("solid"); | ||||
|     def->enum_labels.push_back("All top surfaces"); | ||||
|     def->enum_labels.push_back("Topmost surface only"); | ||||
|     def->enum_labels.push_back("All solid surfaces"); | ||||
|     def->mode = comAdvanced; | ||||
|     def->set_default_value(new ConfigOptionEnum<IroningType>(IroningType::TopSurfaces)); | ||||
| 
 | ||||
|     def = this->add("ironing_flowrate", coPercent); | ||||
|     def->label = L("Flow rate"); | ||||
|     def->category = L("Ironing"); | ||||
|     def->tooltip = L("Percent of a flow rate relative to object's normal layer height."); | ||||
|     def->sidetext = L("%"); | ||||
|     def->ratio_over = "layer_height"; | ||||
|     def->min = 0; | ||||
|     def->mode = comExpert; | ||||
|     def->set_default_value(new ConfigOptionPercent(15)); | ||||
| 
 | ||||
|     def = this->add("ironing_spacing", coFloat); | ||||
|     def->label = L("Spacing between ironing passes"); | ||||
|     def->tooltip = L("Distance between ironing lins"); | ||||
|     def->sidetext = L("mm"); | ||||
|     def->min = 0; | ||||
|     def->mode = comExpert; | ||||
|     def->set_default_value(new ConfigOptionFloat(0.1)); | ||||
| 
 | ||||
|     def = this->add("ironing_speed", coFloat); | ||||
|     def->label = L("Ironing speed"); | ||||
|     def->category = L("Speed"); | ||||
|     def->tooltip = L("Ironing speed"); | ||||
|     def->sidetext = L("mm/s"); | ||||
|     def->min = 0; | ||||
|     def->mode = comAdvanced; | ||||
|     def->set_default_value(new ConfigOptionFloat(15)); | ||||
| 
 | ||||
|     def = this->add("layer_gcode", coString); | ||||
|     def->label = L("After layer change G-code"); | ||||
|     def->tooltip = L("This custom code is inserted at every layer change, right after the Z move " | ||||
|  | @ -2071,7 +2130,8 @@ void PrintConfigDef::init_fff_params() | |||
|     def->label = L("Other layers"); | ||||
|     def->tooltip = L("Extruder temperature for layers after the first one. Set this to zero to disable " | ||||
|                    "temperature control commands in the output."); | ||||
|     def->full_label = L("Temperature"); | ||||
|     def->sidetext = L("°C"); | ||||
|     def->full_label = L("Extruder temperature"); | ||||
|     def->min = 0; | ||||
|     def->max = max_temp; | ||||
|     def->set_default_value(new ConfigOptionInts { 200 }); | ||||
|  |  | |||
|  | @ -34,10 +34,17 @@ enum PrintHostType { | |||
| }; | ||||
| 
 | ||||
| enum InfillPattern { | ||||
|     ipRectilinear, ipGrid, ipTriangles, ipStars, ipCubic, ipLine, ipConcentric, ipHoneycomb, ip3DHoneycomb, | ||||
|     ipRectilinear, ipMonotonous, ipGrid, ipTriangles, ipStars, ipCubic, ipLine, ipConcentric, ipHoneycomb, ip3DHoneycomb, | ||||
|     ipGyroid, ipHilbertCurve, ipArchimedeanChords, ipOctagramSpiral, ipCount, | ||||
| }; | ||||
| 
 | ||||
| enum class IroningType { | ||||
| 	TopSurfaces, | ||||
| 	TopmostOnly, | ||||
| 	AllSolid, | ||||
| 	Count, | ||||
| }; | ||||
| 
 | ||||
| enum SupportMaterialPattern { | ||||
|     smpRectilinear, smpRectilinearGrid, smpHoneycomb, | ||||
| }; | ||||
|  | @ -106,6 +113,7 @@ template<> inline const t_config_enum_values& ConfigOptionEnum<InfillPattern>::g | |||
|     static t_config_enum_values keys_map; | ||||
|     if (keys_map.empty()) { | ||||
|         keys_map["rectilinear"]         = ipRectilinear; | ||||
|         keys_map["monotonous"]          = ipMonotonous; | ||||
|         keys_map["grid"]                = ipGrid; | ||||
|         keys_map["triangles"]           = ipTriangles; | ||||
|         keys_map["stars"]               = ipStars; | ||||
|  | @ -122,6 +130,16 @@ template<> inline const t_config_enum_values& ConfigOptionEnum<InfillPattern>::g | |||
|     return keys_map; | ||||
| } | ||||
| 
 | ||||
| template<> inline const t_config_enum_values& ConfigOptionEnum<IroningType>::get_enum_values() { | ||||
|     static t_config_enum_values keys_map; | ||||
|     if (keys_map.empty()) { | ||||
|         keys_map["top"]                 = int(IroningType::TopSurfaces); | ||||
|         keys_map["topmost"]             = int(IroningType::TopmostOnly); | ||||
|         keys_map["solid"]               = int(IroningType::AllSolid); | ||||
|     } | ||||
|     return keys_map; | ||||
| } | ||||
| 
 | ||||
| template<> inline const t_config_enum_values& ConfigOptionEnum<SupportMaterialPattern>::get_enum_values() { | ||||
|     static t_config_enum_values keys_map; | ||||
|     if (keys_map.empty()) { | ||||
|  | @ -488,6 +506,12 @@ public: | |||
|     ConfigOptionInt                 infill_every_layers; | ||||
|     ConfigOptionFloatOrPercent      infill_overlap; | ||||
|     ConfigOptionFloat               infill_speed; | ||||
|     // Ironing options
 | ||||
|     ConfigOptionBool 				ironing; | ||||
|     ConfigOptionEnum<IroningType> 	ironing_type; | ||||
|     ConfigOptionPercent 			ironing_flowrate; | ||||
|     ConfigOptionFloat 				ironing_spacing; | ||||
|     ConfigOptionFloat 				ironing_speed; | ||||
|     // Detect bridging perimeters
 | ||||
|     ConfigOptionBool                overhangs; | ||||
|     ConfigOptionInt                 perimeter_extruder; | ||||
|  | @ -533,6 +557,11 @@ protected: | |||
|         OPT_PTR(infill_every_layers); | ||||
|         OPT_PTR(infill_overlap); | ||||
|         OPT_PTR(infill_speed); | ||||
|         OPT_PTR(ironing); | ||||
|         OPT_PTR(ironing_type); | ||||
|         OPT_PTR(ironing_flowrate); | ||||
|         OPT_PTR(ironing_spacing); | ||||
|         OPT_PTR(ironing_speed); | ||||
|         OPT_PTR(overhangs); | ||||
|         OPT_PTR(perimeter_extruder); | ||||
|         OPT_PTR(perimeter_extrusion_width); | ||||
|  |  | |||
|  | @ -387,6 +387,25 @@ void PrintObject::infill() | |||
|     } | ||||
| } | ||||
| 
 | ||||
| void PrintObject::ironing() | ||||
| { | ||||
|     if (this->set_started(posIroning)) { | ||||
|         BOOST_LOG_TRIVIAL(debug) << "Ironing in parallel - start"; | ||||
|         tbb::parallel_for( | ||||
|             tbb::blocked_range<size_t>(1, m_layers.size()), | ||||
|             [this](const tbb::blocked_range<size_t>& range) { | ||||
|                 for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) { | ||||
|                     m_print->throw_if_canceled(); | ||||
|                     m_layers[layer_idx]->make_ironing(); | ||||
|                 } | ||||
|             } | ||||
|         ); | ||||
|         m_print->throw_if_canceled(); | ||||
|         BOOST_LOG_TRIVIAL(debug) << "Ironing in parallel - end"; | ||||
|         this->set_done(posIroning); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void PrintObject::generate_support_material() | ||||
| { | ||||
|     if (this->set_started(posSupportMaterial)) { | ||||
|  | @ -2610,6 +2629,7 @@ void PrintObject::combine_infill() | |||
|              // Because fill areas for rectilinear and honeycomb are grown 
 | ||||
|              // later to overlap perimeters, we need to counteract that too.
 | ||||
|                 ((region->config().fill_pattern == ipRectilinear   || | ||||
|                   region->config().fill_pattern == ipMonotonous    || | ||||
|                   region->config().fill_pattern == ipGrid          || | ||||
|                   region->config().fill_pattern == ipLine          || | ||||
|                   region->config().fill_pattern == ipHoneycomb) ? 1.5f : 0.5f) *  | ||||
|  | @ -2686,7 +2706,7 @@ void PrintObject::project_and_append_custom_supports( | |||
| 
 | ||||
|         // Iterate over all triangles.
 | ||||
|         tbb::parallel_for( | ||||
|             tbb::blocked_range<size_t>(0, custom_facets.size() - 1), | ||||
|             tbb::blocked_range<size_t>(0, custom_facets.size()), | ||||
|             [&](const tbb::blocked_range<size_t>& range) { | ||||
|             for (size_t idx = range.begin(); idx < range.end(); ++ idx) { | ||||
| 
 | ||||
|  | @ -2799,10 +2819,9 @@ void PrintObject::project_and_append_custom_supports( | |||
|         // Now append the collected polygons to respective layers.
 | ||||
|         for (auto& trg : projections_of_triangles) { | ||||
|             int layer_id = trg.first_layer_id; | ||||
|             if (layer_id == 0) | ||||
|                 continue; | ||||
| 
 | ||||
|             for (const LightPolygon& poly : trg.polygons) { | ||||
|                 expolys[layer_id-1].emplace_back(std::move(poly.pts)); | ||||
|                 expolys[layer_id].emplace_back(std::move(poly.pts)); | ||||
|                 ++layer_id; | ||||
|             } | ||||
|         } | ||||
|  |  | |||
|  | @ -38,11 +38,12 @@ std::vector<std::pair<size_t, bool>> chain_segments_closest_point(std::vector<En | |||
|     	// Ignore the starting point as the starting point is considered to be occupied, no end point coud connect to it.
 | ||||
| 		size_t next_idx = find_closest_point(kdtree, this_point.pos, | ||||
| 			[this_idx, &end_points, &could_reverse_func](size_t idx) { | ||||
| 				return (idx ^ this_idx) > 1 && end_points[idx].chain_id == 0 && ((idx ^ 1) == 0 || could_reverse_func(idx >> 1)); | ||||
| 				return (idx ^ this_idx) > 1 && end_points[idx].chain_id == 0 && ((idx & 1) == 0 || could_reverse_func(idx >> 1)); | ||||
| 		}); | ||||
| 		assert(next_idx < end_points.size()); | ||||
| 		EndPointType &end_point = end_points[next_idx]; | ||||
| 		end_point.chain_id = 1; | ||||
| 		assert((next_idx & 1) == 0 || could_reverse_func(next_idx >> 1)); | ||||
| 		out.emplace_back(next_idx / 2, (next_idx & 1) != 0); | ||||
| 		this_idx = next_idx ^ 1; | ||||
| 	} | ||||
|  | @ -165,7 +166,9 @@ std::vector<std::pair<size_t, bool>> chain_segments_greedy_constrained_reversals | |||
| 		EndPoint *first_point = nullptr; | ||||
| 		size_t    first_point_idx = std::numeric_limits<size_t>::max(); | ||||
| 		if (start_near != nullptr) { | ||||
|             size_t idx = find_closest_point(kdtree, start_near->template cast<double>()); | ||||
|             size_t idx = find_closest_point(kdtree, start_near->template cast<double>(), | ||||
| 				// Don't start with a reverse segment, if flipping of the segment is not allowed.
 | ||||
| 				[&could_reverse_func](size_t idx) { return (idx & 1) == 0 || could_reverse_func(idx >> 1); }); | ||||
| 			assert(idx < end_points.size()); | ||||
| 			first_point = &end_points[idx]; | ||||
| 			first_point->distance_out = 0.; | ||||
|  |  | |||
|  | @ -1101,10 +1101,10 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_ | |||
|                             if (! enforcers.empty()) { | ||||
|                                 // Apply the "support enforcers".
 | ||||
|                                 //FIXME add the "enforcers" to the sparse support regions only.
 | ||||
|                                 const ExPolygons &enforcer = enforcers[layer_id - 1]; | ||||
|                                 const ExPolygons &enforcer = enforcers[layer_id]; | ||||
|                                 if (! enforcer.empty()) { | ||||
|                                     // Enforce supports (as if with 90 degrees of slope) for the regions covered by the enforcer meshes.
 | ||||
|                                     Polygons new_contacts = diff(intersection(layerm_polygons, to_polygons(enforcer)), | ||||
|                                     Polygons new_contacts = diff(intersection(layerm_polygons, to_polygons(std::move(enforcer))), | ||||
|                                             offset(lower_layer_polygons, 0.05f * fw, SUPPORT_SURFACES_OFFSET_PARAMETERS)); | ||||
|                                     if (! new_contacts.empty()) { | ||||
|                                         if (diff_polygons.empty()) | ||||
|  | @ -1115,19 +1115,26 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_ | |||
|                                 } | ||||
|                             } | ||||
|                         } | ||||
|                         // Apply the "support blockers".
 | ||||
|                         if (! diff_polygons.empty() && ! blockers.empty() && ! blockers[layer_id].empty()) { | ||||
|                             // Enforce supports (as if with 90 degrees of slope) for the regions covered by the enforcer meshes.
 | ||||
|                             diff_polygons = diff(diff_polygons, to_polygons(blockers[layer_id])); | ||||
|                         } | ||||
| 
 | ||||
|                         if (diff_polygons.empty()) | ||||
|                             continue; | ||||
| 
 | ||||
|                         // Apply the "support blockers".
 | ||||
|                         if (! blockers.empty() && ! blockers[layer_id].empty()) { | ||||
|                             // Expand the blocker a bit. Custom blockers produce strips
 | ||||
|                             // spanning just the projection between the two slices.
 | ||||
|                             // Subtracting them as they are may leave unwanted narrow
 | ||||
|                             // residues of diff_polygons that would then be supported.
 | ||||
|                             diff_polygons = diff(diff_polygons, | ||||
|                                 offset(union_(to_polygons(std::move(blockers[layer_id]))), | ||||
|                                        1000.*SCALED_EPSILON)); | ||||
|                         } | ||||
| 
 | ||||
|                         #ifdef SLIC3R_DEBUG | ||||
|                         { | ||||
|                             ::Slic3r::SVG svg(debug_out_path("support-top-contacts-raw-run%d-layer%d-region%d.svg",  | ||||
|                                 iRun, layer_id,  | ||||
|                                 std::find_if(layer.regions.begin(), layer.regions.end(), [layerm](const LayerRegion* other){return other == layerm;}) - layer.regions.begin()),  | ||||
|                                 std::find_if(layer.regions.begin(), layer.regions.end(), [layerm](const LayerRegion* other){return other == layerm;}) - layer.regions.begin()), | ||||
|                             get_extents(diff_polygons)); | ||||
|                             Slic3r::ExPolygons expolys = union_ex(diff_polygons, false); | ||||
|                             svg.draw(expolys); | ||||
|  | @ -2321,10 +2328,15 @@ static inline void fill_expolygons_generate_paths( | |||
|     fill_params.dont_adjust = true; | ||||
|     for (const ExPolygon &expoly : expolygons) { | ||||
|         Surface surface(stInternal, expoly); | ||||
|         Polylines polylines; | ||||
|     	try { | ||||
|             polylines = filler->fill_surface(&surface, fill_params); | ||||
| 		} catch (InfillFailedException &) { | ||||
| 		} | ||||
|         extrusion_entities_append_paths( | ||||
|             dst, | ||||
|             filler->fill_surface(&surface, fill_params), | ||||
|             role,  | ||||
|             std::move(polylines), | ||||
|             role, | ||||
|             flow.mm3_per_mm(), flow.width, flow.height); | ||||
|     } | ||||
| } | ||||
|  | @ -2343,9 +2355,14 @@ static inline void fill_expolygons_generate_paths( | |||
|     fill_params.dont_adjust = true; | ||||
|     for (ExPolygon &expoly : expolygons) { | ||||
|         Surface surface(stInternal, std::move(expoly)); | ||||
|         Polylines polylines; | ||||
|     	try { | ||||
|             polylines = filler->fill_surface(&surface, fill_params); | ||||
| 		} catch (InfillFailedException &) { | ||||
| 		} | ||||
|         extrusion_entities_append_paths( | ||||
|             dst, | ||||
|             filler->fill_surface(&surface, fill_params), | ||||
|             std::move(polylines), | ||||
|             role, | ||||
|             flow.mm3_per_mm(), flow.width, flow.height); | ||||
|     } | ||||
|  |  | |||
|  | @ -26,6 +26,7 @@ | |||
| // Saves around 32% RAM after slicing step, 6.7% after G-code export (tested on PrusaSlicer 2.2.0 final).
 | ||||
| typedef int32_t coord_t; | ||||
| #else | ||||
| //FIXME At least FillRectilinear2 requires coord_t to be 32bit.
 | ||||
| typedef int64_t coord_t; | ||||
| #endif | ||||
| 
 | ||||
|  |  | |||
|  | @ -161,6 +161,10 @@ set(SLIC3R_GUI_SOURCES | |||
|     GUI/DoubleSlider.hpp | ||||
|     GUI/ObjectDataViewModel.cpp | ||||
|     GUI/ObjectDataViewModel.hpp | ||||
|     GUI/InstanceCheck.cpp | ||||
|     GUI/InstanceCheck.hpp | ||||
|     GUI/Search.cpp | ||||
|     GUI/Search.hpp | ||||
|     Utils/Http.cpp | ||||
|     Utils/Http.hpp | ||||
|     Utils/FixModelByWin10.cpp | ||||
|  | @ -195,6 +199,8 @@ if (APPLE) | |||
|             GUI/RemovableDriveManagerMM.mm | ||||
|             GUI/RemovableDriveManagerMM.h | ||||
|             GUI/Mouse3DHandlerMac.mm | ||||
|             GUI/InstanceCheckMac.mm | ||||
|             GUI/InstanceCheckMac.h | ||||
|         ) | ||||
|     FIND_LIBRARY(DISKARBITRATION_LIBRARY DiskArbitration) | ||||
| 
 | ||||
|  | @ -206,6 +212,10 @@ encoding_check(libslic3r_gui) | |||
| 
 | ||||
| target_link_libraries(libslic3r_gui libslic3r avrdude cereal imgui GLEW::GLEW OpenGL::GL OpenGL::GLU hidapi libcurl ${wxWidgets_LIBRARIES}) | ||||
| 
 | ||||
| if (CMAKE_SYSTEM_NAME STREQUAL "Linux") | ||||
|     target_link_libraries(libslic3r_gui ${DBUS_LIBRARIES})  | ||||
| endif() | ||||
| 
 | ||||
| if(APPLE) | ||||
|     target_link_libraries(libslic3r_gui ${DISKARBITRATION_LIBRARY}) | ||||
| endif() | ||||
|  |  | |||
|  | @ -115,7 +115,9 @@ void CopyrightsDialog::fill_entries() | |||
|         { "Icons for STL and GCODE files." | ||||
|                             , "Akira Yasuda"                                , "http://3dp0.com/icons-for-stl-and-gcode/" }, | ||||
|         { "AppImage packaging for Linux using AppImageKit" | ||||
|                             , "2004-2019 Simon Peter and contributors"      , "https://appimage.org/" } | ||||
|                             , "2004-2019 Simon Peter and contributors"      , "https://appimage.org/" }, | ||||
|         { "lib_fts" | ||||
|                             , "Forrest Smith"                               , "https://www.forrestthewoods.com/" } | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -69,6 +69,9 @@ void AppConfig::set_defaults() | |||
|         set("use_retina_opengl", "1"); | ||||
| #endif | ||||
| 
 | ||||
| 	if (get("single_instance").empty()) | ||||
| 		set("single_instance", "0"); | ||||
| 
 | ||||
|     if (get("remember_output_path").empty()) | ||||
|         set("remember_output_path", "1"); | ||||
| 
 | ||||
|  |  | |||
|  | @ -298,6 +298,10 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config) | |||
|     toggle_field("support_material_extruder", have_support_material || have_skirt); | ||||
|     toggle_field("support_material_speed", have_support_material || have_brim || have_skirt); | ||||
| 
 | ||||
|     bool has_ironing = config->opt_bool("ironing"); | ||||
|     for (auto el : { "ironing_type", "ironing_flowrate", "ironing_spacing", "ironing_speed" }) | ||||
|     	toggle_field(el, has_ironing); | ||||
| 
 | ||||
|     bool have_sequential_printing = config->opt_bool("complete_objects"); | ||||
|     for (auto el : { "extruder_clearance_radius", "extruder_clearance_height" }) | ||||
|         toggle_field(el, have_sequential_printing); | ||||
|  |  | |||
|  | @ -57,6 +57,8 @@ void Field::PostInitialize() | |||
|     m_Undo_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent) { on_back_to_initial_value(); })); | ||||
| 	m_Undo_to_sys_btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent) { on_back_to_sys_value(); })); | ||||
| 
 | ||||
| 	m_blinking_bmp		= new BlinkingBitmap(m_parent); | ||||
| 
 | ||||
| 	switch (m_opt.type) | ||||
| 	{ | ||||
| 	case coPercents: | ||||
|  | @ -943,7 +945,7 @@ void Choice::set_value(const boost::any& value, bool change_event) | |||
| 	} | ||||
| 	case coEnum: { | ||||
| 		int val = boost::any_cast<int>(value); | ||||
| 		if (m_opt_id == "top_fill_pattern" || m_opt_id == "bottom_fill_pattern") | ||||
| 		if (m_opt_id == "top_fill_pattern" || m_opt_id == "bottom_fill_pattern" || m_opt_id == "fill_pattern") | ||||
| 		{ | ||||
| 			if (!m_opt.enum_values.empty()) { | ||||
| 				std::string key; | ||||
|  | @ -1013,7 +1015,7 @@ boost::any& Choice::get_value() | |||
| 	if (m_opt.type == coEnum) | ||||
| 	{ | ||||
| 		int ret_enum = field->GetSelection();  | ||||
| 		if (m_opt_id == "top_fill_pattern" || m_opt_id == "bottom_fill_pattern") | ||||
| 		if (m_opt_id == "top_fill_pattern" || m_opt_id == "bottom_fill_pattern" || m_opt_id == "fill_pattern") | ||||
| 		{ | ||||
| 			if (!m_opt.enum_values.empty()) { | ||||
| 				std::string key = m_opt.enum_values[ret_enum]; | ||||
|  | @ -1025,8 +1027,8 @@ boost::any& Choice::get_value() | |||
| 			else | ||||
| 				m_value = static_cast<InfillPattern>(0); | ||||
| 		} | ||||
| 		if (m_opt_id.compare("fill_pattern") == 0) | ||||
| 			m_value = static_cast<InfillPattern>(ret_enum); | ||||
| 		else if (m_opt_id.compare("ironing_type") == 0) | ||||
| 			m_value = static_cast<IroningType>(ret_enum); | ||||
| 		else if (m_opt_id.compare("gcode_flavor") == 0) | ||||
| 			m_value = static_cast<GCodeFlavor>(ret_enum); | ||||
| 		else if (m_opt_id.compare("support_material_pattern") == 0) | ||||
|  |  | |||
|  | @ -230,6 +230,8 @@ public: | |||
| 	static int def_width_wider()	; | ||||
| 	static int def_width_thinner()	; | ||||
| 
 | ||||
| 	BlinkingBitmap*			blinking_bitmap() const { return m_blinking_bmp;} | ||||
| 
 | ||||
| protected: | ||||
| 	RevertButton*			m_Undo_btn = nullptr; | ||||
| 	// Bitmap and Tooltip text for m_Undo_btn. The wxButton will be updated only if the new wxBitmap pointer differs from the currently rendered one.
 | ||||
|  | @ -240,6 +242,8 @@ protected: | |||
|     const ScalableBitmap*   m_undo_to_sys_bitmap = nullptr; | ||||
| 	const wxString*		    m_undo_to_sys_tooltip = nullptr; | ||||
| 
 | ||||
| 	BlinkingBitmap*			m_blinking_bmp{ nullptr }; | ||||
| 
 | ||||
| 	wxStaticText*		m_Label = nullptr; | ||||
| 	// Color for Label. The wxColour will be updated only if the new wxColour pointer differs from the currently rendered one.
 | ||||
| 	const wxColour*		m_label_color = nullptr; | ||||
|  | @ -461,6 +465,7 @@ public: | |||
| 		x_textctrl->Disable(); | ||||
| 		y_textctrl->Disable(); } | ||||
| 	wxSizer*		getSizer() override { return sizer; } | ||||
| 	wxWindow*		getWindow() override { return dynamic_cast<wxWindow*>(x_textctrl); } | ||||
| }; | ||||
| 
 | ||||
| class StaticText : public Field { | ||||
|  |  | |||
|  | @ -1531,6 +1531,7 @@ wxDEFINE_EVENT(EVT_GLCANVAS_MOVE_DOUBLE_SLIDER, wxKeyEvent); | |||
| wxDEFINE_EVENT(EVT_GLCANVAS_EDIT_COLOR_CHANGE, wxKeyEvent); | ||||
| wxDEFINE_EVENT(EVT_GLCANVAS_UNDO, SimpleEvent); | ||||
| wxDEFINE_EVENT(EVT_GLCANVAS_REDO, SimpleEvent); | ||||
| wxDEFINE_EVENT(EVT_GLCANVAS_COLLAPSE_SIDEBAR, SimpleEvent); | ||||
| wxDEFINE_EVENT(EVT_GLCANVAS_RESET_LAYER_HEIGHT_PROFILE, SimpleEvent); | ||||
| wxDEFINE_EVENT(EVT_GLCANVAS_ADAPTIVE_LAYER_HEIGHT_PROFILE, Event<float>); | ||||
| wxDEFINE_EVENT(EVT_GLCANVAS_SMOOTH_LAYER_HEIGHT_PROFILE, HeightProfileSmoothEvent); | ||||
|  | @ -1556,6 +1557,7 @@ GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas, Bed3D& bed, Camera& camera, GLToolbar | |||
| #endif // !ENABLE_NON_STATIC_CANVAS_MANAGER
 | ||||
|     , m_main_toolbar(GLToolbar::Normal, "Top") | ||||
|     , m_undoredo_toolbar(GLToolbar::Normal, "Top") | ||||
|     , m_collapse_toolbar(GLToolbar::Normal, "Top") | ||||
|     , m_gizmos(*this) | ||||
|     , m_use_clipping_planes(false) | ||||
|     , m_sidebar_field("") | ||||
|  | @ -1961,6 +1963,11 @@ void GLCanvas3D::enable_undoredo_toolbar(bool enable) | |||
|     m_undoredo_toolbar.set_enabled(enable); | ||||
| } | ||||
| 
 | ||||
| void GLCanvas3D::enable_collapse_toolbar(bool enable) | ||||
| { | ||||
|     m_collapse_toolbar.set_enabled(enable); | ||||
| } | ||||
| 
 | ||||
| void GLCanvas3D::enable_dynamic_background(bool enable) | ||||
| { | ||||
|     m_dynamic_background_enabled = enable; | ||||
|  | @ -2186,6 +2193,9 @@ void GLCanvas3D::render() | |||
| 	        tooltip = m_undoredo_toolbar.get_tooltip(); | ||||
| 
 | ||||
| 	    if (tooltip.empty()) | ||||
| 	        tooltip = m_collapse_toolbar.get_tooltip(); | ||||
| 
 | ||||
| 	    if (tooltip.empty()) | ||||
| #if ENABLE_NON_STATIC_CANVAS_MANAGER | ||||
|             tooltip = wxGetApp().plater()->get_view_toolbar().get_tooltip(); | ||||
| #else | ||||
|  | @ -2224,6 +2234,9 @@ void GLCanvas3D::render() | |||
|     if (tooltip.empty()) | ||||
|         tooltip = m_undoredo_toolbar.get_tooltip(); | ||||
| 
 | ||||
|     if (tooltip.empty()) | ||||
|         tooltip = m_collapse_toolbar.get_tooltip(); | ||||
| 
 | ||||
|     if (tooltip.empty()) | ||||
|         tooltip = m_view_toolbar.get_tooltip(); | ||||
| 
 | ||||
|  | @ -2950,6 +2963,7 @@ void GLCanvas3D::on_idle(wxIdleEvent& evt) | |||
| 
 | ||||
|     m_dirty |= m_main_toolbar.update_items_state(); | ||||
|     m_dirty |= m_undoredo_toolbar.update_items_state(); | ||||
|     m_dirty |= m_collapse_toolbar.update_items_state(); | ||||
| #if ENABLE_NON_STATIC_CANVAS_MANAGER | ||||
|     m_dirty |= wxGetApp().plater()->get_view_toolbar().update_items_state(); | ||||
|     bool mouse3d_controller_applied = wxGetApp().plater()->get_mouse3d_controller().apply(wxGetApp().plater()->get_camera()); | ||||
|  | @ -2989,7 +3003,7 @@ void GLCanvas3D::on_char(wxKeyEvent& evt) | |||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     if ((keyCode == WXK_ESCAPE) && _deactivate_undo_redo_toolbar_items()) | ||||
|     if ((keyCode == WXK_ESCAPE) && (_deactivate_undo_redo_toolbar_items() || _deactivate_search_toolbar_item())) | ||||
|         return; | ||||
| 
 | ||||
|     if (m_gizmos.on_char(evt)) | ||||
|  | @ -3037,6 +3051,16 @@ void GLCanvas3D::on_char(wxKeyEvent& evt) | |||
|         break; | ||||
| 
 | ||||
| 
 | ||||
| #ifdef __APPLE__ | ||||
|         case 'f': | ||||
|         case 'F': | ||||
| #else /* __APPLE__ */ | ||||
|         case WXK_CONTROL_F: | ||||
| #endif /* __APPLE__ */ | ||||
|             _activate_search_toolbar_item(); | ||||
|             break; | ||||
| 
 | ||||
| 
 | ||||
| #ifdef __APPLE__ | ||||
|         case 'y': | ||||
|         case 'Y': | ||||
|  | @ -3436,6 +3460,15 @@ void GLCanvas3D::on_mouse_wheel(wxMouseEvent& evt) | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // If the Search window or Undo/Redo list is opened, 
 | ||||
|     // update them according to the event
 | ||||
|     if (m_main_toolbar.is_item_pressed("search")    ||  | ||||
|         m_undoredo_toolbar.is_item_pressed("undo")  ||  | ||||
|         m_undoredo_toolbar.is_item_pressed("redo")) { | ||||
|         m_mouse_wheel = int((double)evt.GetWheelRotation() / (double)evt.GetWheelDelta()); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     // Inform gizmos about the event so they have the opportunity to react.
 | ||||
|     if (m_gizmos.on_mouse_wheel(evt)) | ||||
|         return; | ||||
|  | @ -3571,6 +3604,14 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) | |||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     if (m_collapse_toolbar.on_mouse(evt, *this)) | ||||
|     { | ||||
|         if (evt.LeftUp() || evt.MiddleUp() || evt.RightUp()) | ||||
|             mouse_up_cleanup(); | ||||
|         m_mouse.set_start_position_3D_as_invalid(); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
| #if ENABLE_NON_STATIC_CANVAS_MANAGER | ||||
|     if (wxGetApp().plater()->get_view_toolbar().on_mouse(evt, *this)) | ||||
| #else | ||||
|  | @ -3636,6 +3677,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) | |||
|     else if (evt.Leaving()) | ||||
|     { | ||||
|         _deactivate_undo_redo_toolbar_items(); | ||||
|         _deactivate_search_toolbar_item(); | ||||
| 
 | ||||
|         // to remove hover on objects when the mouse goes out of this canvas
 | ||||
|         m_mouse.position = Vec2d(-1.0, -1.0); | ||||
|  | @ -3643,7 +3685,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) | |||
|     } | ||||
|     else if (evt.LeftDown() || evt.RightDown() || evt.MiddleDown()) | ||||
|     { | ||||
|         if (_deactivate_undo_redo_toolbar_items()) | ||||
|         if (_deactivate_undo_redo_toolbar_items() || _deactivate_search_toolbar_item()) | ||||
|             return; | ||||
| 
 | ||||
|         // If user pressed left or right button we first check whether this happened
 | ||||
|  | @ -4434,7 +4476,7 @@ bool GLCanvas3D::_render_undo_redo_stack(const bool is_undo, float pos_x) const | |||
| 	em *= m_retina_helper->get_scale_factor(); | ||||
| #endif | ||||
| 
 | ||||
|     if (imgui->undo_redo_list(ImVec2(18 * em, 26 * em), is_undo, &string_getter, hovered, selected)) | ||||
|     if (imgui->undo_redo_list(ImVec2(18 * em, 26 * em), is_undo, &string_getter, hovered, selected, m_mouse_wheel)) | ||||
|         m_imgui_undo_redo_hovered_pos = hovered; | ||||
|     else | ||||
|         m_imgui_undo_redo_hovered_pos = -1; | ||||
|  | @ -4452,6 +4494,64 @@ bool GLCanvas3D::_render_undo_redo_stack(const bool is_undo, float pos_x) const | |||
|     return action_taken; | ||||
| } | ||||
| 
 | ||||
| // Getter for the const char*[] for the search list 
 | ||||
| static bool search_string_getter(int idx, const char** label, const char** tooltip) | ||||
| { | ||||
|     return wxGetApp().plater()->search_string_getter(idx, label, tooltip); | ||||
| } | ||||
| 
 | ||||
| bool GLCanvas3D::_render_search_list(float pos_x) const | ||||
| { | ||||
|     bool action_taken = false; | ||||
|     ImGuiWrapper* imgui = wxGetApp().imgui(); | ||||
| 
 | ||||
| #if ENABLE_NON_STATIC_CANVAS_MANAGER | ||||
|     const float x = pos_x * (float)wxGetApp().plater()->get_camera().get_zoom() + 0.5f * (float)get_canvas_size().get_width(); | ||||
| #else | ||||
|     const float x = pos_x * (float)get_camera().get_zoom() + 0.5f * (float)get_canvas_size().get_width(); | ||||
| #endif | ||||
|     imgui->set_next_window_pos(x, m_main_toolbar.get_height(), ImGuiCond_Always, 0.5f, 0.0f); | ||||
|     std::string title = L("Search"); | ||||
|     imgui->begin(_(title), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse); | ||||
| 
 | ||||
|     int selected = -1; | ||||
|     bool edited = false; | ||||
|     bool check_changed = false; | ||||
|     float em = static_cast<float>(wxGetApp().em_unit()); | ||||
| #if ENABLE_RETINA_GL | ||||
| 	em *= m_retina_helper->get_scale_factor(); | ||||
| #endif | ||||
| 
 | ||||
|     Sidebar& sidebar = wxGetApp().sidebar(); | ||||
| 
 | ||||
|     std::string& search_line = sidebar.get_search_line(); | ||||
|     char *s = new char[255]; | ||||
|     strcpy(s, search_line.empty() ? _u8L("Type here to search").c_str() : search_line.c_str()); | ||||
| 
 | ||||
|     imgui->search_list(ImVec2(45 * em, 30 * em), &search_string_getter, s,  | ||||
|                        sidebar.get_searcher().view_params, | ||||
|                        selected, edited, m_mouse_wheel); | ||||
| 
 | ||||
|     search_line = s; | ||||
|     delete [] s; | ||||
|     if (search_line == _u8L("Type here to search")) | ||||
|         search_line.clear(); | ||||
| 
 | ||||
|     if (edited) | ||||
|         sidebar.search(); | ||||
| 
 | ||||
|     if (selected != size_t(-1)) { | ||||
|         // selected == 9999 means that Esc kye was pressed
 | ||||
|         if (selected != 9999) | ||||
|             sidebar.jump_to_option(selected); | ||||
|         action_taken = true; | ||||
|     } | ||||
| 
 | ||||
|     imgui->end(); | ||||
| 
 | ||||
|     return action_taken; | ||||
| } | ||||
| 
 | ||||
| #define ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT 0 | ||||
| #if ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT | ||||
| static void debug_output_thumbnail(const ThumbnailData& thumbnail_data) | ||||
|  | @ -4821,6 +4921,9 @@ bool GLCanvas3D::_init_toolbars() | |||
|     if (!_init_view_toolbar()) | ||||
|         return false; | ||||
| 
 | ||||
|     if (!_init_collapse_toolbar()) | ||||
|         return false; | ||||
| 
 | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
|  | @ -4978,6 +5081,26 @@ bool GLCanvas3D::_init_main_toolbar() | |||
|     if (!m_main_toolbar.add_item(item)) | ||||
|         return false; | ||||
| 
 | ||||
|     if (!m_main_toolbar.add_separator()) | ||||
|         return false; | ||||
| 
 | ||||
|     item.name = "search"; | ||||
|     item.icon_filename = "search_.svg"; | ||||
|     item.tooltip = _utf8(L("Search")) + " [" + GUI::shortkey_ctrl_prefix() + "F]"; | ||||
|     item.sprite_id = 11; | ||||
|     item.left.render_callback = [this](float left, float right, float, float) { | ||||
|         if (m_canvas != nullptr) | ||||
|         { | ||||
|             if (_render_search_list(0.5f * (left + right))) | ||||
|                 _deactivate_search_toolbar_item(); | ||||
|         } | ||||
|     }; | ||||
|     item.left.action_callback   = GLToolbarItem::Default_Action_Callback; | ||||
|     item.visibility_callback    = GLToolbarItem::Default_Visibility_Callback; | ||||
|     item.enabling_callback      = GLToolbarItem::Default_Enabling_Callback; | ||||
|     if (!m_main_toolbar.add_item(item)) | ||||
|         return false; | ||||
| 
 | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
|  | @ -5087,6 +5210,9 @@ bool GLCanvas3D::_init_undoredo_toolbar() | |||
|     if (!m_undoredo_toolbar.add_item(item)) | ||||
|         return false; | ||||
| 
 | ||||
|     if (!m_undoredo_toolbar.add_separator()) | ||||
|         return false; | ||||
| 
 | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
|  | @ -5095,6 +5221,106 @@ bool GLCanvas3D::_init_view_toolbar() | |||
|     return wxGetApp().plater()->init_view_toolbar(); | ||||
| } | ||||
| 
 | ||||
| bool GLCanvas3D::_init_collapse_toolbar() | ||||
| { | ||||
|     if (!m_collapse_toolbar.is_enabled()) | ||||
|         return true; | ||||
| 
 | ||||
|     BackgroundTexture::Metadata background_data; | ||||
|     background_data.filename = "toolbar_background.png"; | ||||
|     background_data.left = 16; | ||||
|     background_data.top = 16; | ||||
|     background_data.right = 16; | ||||
|     background_data.bottom = 16; | ||||
| 
 | ||||
|     if (!m_collapse_toolbar.init(background_data)) | ||||
|     { | ||||
|         // unable to init the toolbar texture, disable it
 | ||||
|         m_collapse_toolbar.set_enabled(false); | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     m_collapse_toolbar.set_layout_type(GLToolbar::Layout::Vertical); | ||||
|     m_collapse_toolbar.set_horizontal_orientation(GLToolbar::Layout::HO_Right); | ||||
|     m_collapse_toolbar.set_vertical_orientation(GLToolbar::Layout::VO_Top); | ||||
|     m_collapse_toolbar.set_border(5.0f); | ||||
|     m_collapse_toolbar.set_separator_size(5); | ||||
|     m_collapse_toolbar.set_gap_size(2); | ||||
| 
 | ||||
|     GLToolbarItem::Data item; | ||||
| 
 | ||||
|     item.name = "collapse_sidebar"; | ||||
|     item.icon_filename = "collapse.svg"; | ||||
|     item.tooltip =  wxGetApp().plater()->is_sidebar_collapsed() ? _utf8(L("Expand right panel")) : _utf8(L("Collapse right panel")); | ||||
|     item.sprite_id = 0; | ||||
|     item.left.action_callback = [this, item]() { | ||||
|         std::string new_tooltip = wxGetApp().plater()->is_sidebar_collapsed() ? | ||||
|             _utf8(L("Collapse right panel")) : _utf8(L("Expand right panel")); | ||||
| 
 | ||||
|         int id = m_collapse_toolbar.get_item_id("collapse_sidebar"); | ||||
|         m_collapse_toolbar.set_tooltip(id, new_tooltip); | ||||
|         set_tooltip(""); | ||||
| 
 | ||||
|         wxGetApp().plater()->collapse_sidebar(!wxGetApp().plater()->is_sidebar_collapsed()); | ||||
|     }; | ||||
| 
 | ||||
|     if (!m_collapse_toolbar.add_item(item)) | ||||
|         return false; | ||||
| 
 | ||||
|     if (!m_collapse_toolbar.add_separator()) | ||||
|         return false; | ||||
| 
 | ||||
|     item.name = "print"; | ||||
|     item.icon_filename = "cog.svg"; | ||||
|     item.tooltip = _utf8(L("Switch to Print Settings")) + " [" + GUI::shortkey_ctrl_prefix() + "2]"; | ||||
|     item.sprite_id = 1; | ||||
|     item.left.action_callback = [this]() { wxGetApp().mainframe->select_tab(/*0*/1); }; | ||||
| 
 | ||||
|     if (!m_collapse_toolbar.add_item(item)) | ||||
|         return false; | ||||
| 
 | ||||
|     item.name = "filament"; | ||||
|     item.icon_filename = "spool.svg"; | ||||
|     item.tooltip = _utf8(L("Switch to Filament Settings")) + " [" + GUI::shortkey_ctrl_prefix() + "3]"; | ||||
|     item.sprite_id = 2; | ||||
|     item.left.action_callback = [this]() { wxGetApp().mainframe->select_tab(/*1*/2); }; | ||||
|     item.visibility_callback  = [this]() { return wxGetApp().plater()->printer_technology() == ptFFF; }; | ||||
| 
 | ||||
|     if (!m_collapse_toolbar.add_item(item)) | ||||
|         return false; | ||||
| 
 | ||||
|     item.name = "printer"; | ||||
|     item.icon_filename = "printer.svg"; | ||||
|     item.tooltip = _utf8(L("Switch to Printer Settings")) + " [" + GUI::shortkey_ctrl_prefix() + "4]"; | ||||
|     item.sprite_id = 3; | ||||
|     item.left.action_callback = [this]() { wxGetApp().mainframe->select_tab(/*2*/3); }; | ||||
| 
 | ||||
|     if (!m_collapse_toolbar.add_item(item)) | ||||
|         return false; | ||||
| 
 | ||||
|     item.name = "resin"; | ||||
|     item.icon_filename = "resin.svg"; | ||||
|     item.tooltip = _utf8(L("Switch to SLA Material Settings")) + " [" + GUI::shortkey_ctrl_prefix() + "3]"; | ||||
|     item.sprite_id = 4; | ||||
|     item.left.action_callback = [this]() { wxGetApp().mainframe->select_tab(/*1*/2); }; | ||||
|     item.visibility_callback  = [this]() { return m_process->current_printer_technology() == ptSLA; }; | ||||
| 
 | ||||
|     if (!m_collapse_toolbar.add_item(item)) | ||||
|         return false; | ||||
| 
 | ||||
|     item.name = "sla_printer"; | ||||
|     item.icon_filename = "sla_printer.svg"; | ||||
|     item.tooltip = _utf8(L("Switch to Printer Settings")) + " [" + GUI::shortkey_ctrl_prefix() + "4]"; | ||||
|     item.sprite_id = 5; | ||||
|     item.left.action_callback = [this]() { wxGetApp().mainframe->select_tab(/*2*/3); }; | ||||
| 
 | ||||
|     if (!m_collapse_toolbar.add_item(item)) | ||||
|         return false; | ||||
| 
 | ||||
|     return true; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| bool GLCanvas3D::_set_current() | ||||
| { | ||||
|     return m_context != nullptr && m_canvas->SetCurrent(*m_context); | ||||
|  | @ -5477,14 +5703,17 @@ void GLCanvas3D::_render_overlays() const | |||
|     const float scale = m_retina_helper->get_scale_factor() * wxGetApp().toolbar_icon_scale(true); | ||||
|     m_main_toolbar.set_scale(scale); | ||||
|     m_undoredo_toolbar.set_scale(scale); | ||||
|     m_collapse_toolbar.set_scale(scale); | ||||
| #else | ||||
|     const float size = int(GLToolbar::Default_Icons_Size * wxGetApp().toolbar_icon_scale(true)); | ||||
|     m_main_toolbar.set_icons_size(size); | ||||
|     m_undoredo_toolbar.set_icons_size(size); | ||||
|     m_collapse_toolbar.set_icons_size(size); | ||||
| #endif // ENABLE_RETINA_GL
 | ||||
| 
 | ||||
|     _render_main_toolbar(); | ||||
|     _render_undoredo_toolbar(); | ||||
|     _render_collapse_toolbar(); | ||||
|     _render_view_toolbar(); | ||||
| 
 | ||||
|     if ((m_layers_editing.last_object_id >= 0) && (m_layers_editing.object_max_z() > 0.0f)) | ||||
|  | @ -5615,6 +5844,27 @@ void GLCanvas3D::_render_undoredo_toolbar() const | |||
|     m_undoredo_toolbar.render(*this); | ||||
| } | ||||
| 
 | ||||
| void GLCanvas3D::_render_collapse_toolbar() const | ||||
| { | ||||
|     if (!m_collapse_toolbar.is_enabled()) | ||||
|         return; | ||||
| 
 | ||||
|     Size cnv_size = get_canvas_size(); | ||||
| #if ENABLE_NON_STATIC_CANVAS_MANAGER | ||||
|     float inv_zoom = (float)wxGetApp().plater()->get_camera().get_inv_zoom(); | ||||
| #else | ||||
|     float inv_zoom = (float)m_camera.get_inv_zoom(); | ||||
| #endif // ENABLE_NON_STATIC_CANVAS_MANAGER
 | ||||
| 
 | ||||
|     float band = m_layers_editing.is_enabled() ? (wxGetApp().imgui()->get_style_scaling() * LayersEditing::THICKNESS_BAR_WIDTH) : 0.0; | ||||
| 
 | ||||
|     float top  = 0.5f * (float)cnv_size.get_height() * inv_zoom; | ||||
|     float left = (0.5f * (float)cnv_size.get_width() - (float)m_collapse_toolbar.get_width() - band) * inv_zoom; | ||||
| 
 | ||||
|     m_collapse_toolbar.set_position(top, left); | ||||
|     m_collapse_toolbar.render(*this); | ||||
| } | ||||
| 
 | ||||
| void GLCanvas3D::_render_view_toolbar() const | ||||
| { | ||||
| #if ENABLE_NON_STATIC_CANVAS_MANAGER | ||||
|  | @ -7142,6 +7392,39 @@ bool GLCanvas3D::_deactivate_undo_redo_toolbar_items() | |||
|     return false; | ||||
| } | ||||
| 
 | ||||
| bool GLCanvas3D::_deactivate_search_toolbar_item() | ||||
| { | ||||
|     if (m_main_toolbar.is_item_pressed("search")) | ||||
|     { | ||||
|         m_main_toolbar.force_left_action(m_main_toolbar.get_item_id("search"), *this); | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| bool GLCanvas3D::_activate_search_toolbar_item() | ||||
| { | ||||
|     if (!m_main_toolbar.is_item_pressed("search")) | ||||
|     { | ||||
|         m_main_toolbar.force_left_action(m_main_toolbar.get_item_id("search"), *this); | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| bool GLCanvas3D::_deactivate_collapse_toolbar_items() | ||||
| { | ||||
|     if (m_collapse_toolbar.is_item_pressed("print")) | ||||
|     { | ||||
|         m_collapse_toolbar.force_left_action(m_collapse_toolbar.get_item_id("print"), *this); | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| const Print* GLCanvas3D::fff_print() const | ||||
| { | ||||
|     return (m_process == nullptr) ? nullptr : m_process->fff_print(); | ||||
|  |  | |||
|  | @ -110,6 +110,7 @@ wxDECLARE_EVENT(EVT_GLCANVAS_MOVE_DOUBLE_SLIDER, wxKeyEvent); | |||
| wxDECLARE_EVENT(EVT_GLCANVAS_EDIT_COLOR_CHANGE, wxKeyEvent); | ||||
| wxDECLARE_EVENT(EVT_GLCANVAS_UNDO, SimpleEvent); | ||||
| wxDECLARE_EVENT(EVT_GLCANVAS_REDO, SimpleEvent); | ||||
| wxDECLARE_EVENT(EVT_GLCANVAS_COLLAPSE_SIDEBAR, SimpleEvent); | ||||
| wxDECLARE_EVENT(EVT_GLCANVAS_RESET_LAYER_HEIGHT_PROFILE, SimpleEvent); | ||||
| wxDECLARE_EVENT(EVT_GLCANVAS_ADAPTIVE_LAYER_HEIGHT_PROFILE, Event<float>); | ||||
| wxDECLARE_EVENT(EVT_GLCANVAS_SMOOTH_LAYER_HEIGHT_PROFILE, HeightProfileSmoothEvent); | ||||
|  | @ -159,8 +160,8 @@ private: | |||
|             Num_States | ||||
|         }; | ||||
| 
 | ||||
|     private: | ||||
|         static const float THICKNESS_BAR_WIDTH; | ||||
|     private: | ||||
| 
 | ||||
|         bool                        m_enabled; | ||||
|         Shader                      m_shader; | ||||
|  | @ -455,6 +456,7 @@ private: | |||
|     mutable GLGizmosManager m_gizmos; | ||||
|     mutable GLToolbar m_main_toolbar; | ||||
|     mutable GLToolbar m_undoredo_toolbar; | ||||
|     mutable GLToolbar m_collapse_toolbar; | ||||
|     ClippingPlane m_clipping_planes[2]; | ||||
|     mutable ClippingPlane m_camera_clipping_plane; | ||||
|     bool m_use_clipping_planes; | ||||
|  | @ -504,6 +506,7 @@ private: | |||
| #endif // ENABLE_RENDER_STATISTICS
 | ||||
| 
 | ||||
|     mutable int m_imgui_undo_redo_hovered_pos{ -1 }; | ||||
|     mutable int m_mouse_wheel {0}; | ||||
|     int m_selected_extruder; | ||||
| 
 | ||||
|     Labels m_labels; | ||||
|  | @ -601,6 +604,7 @@ public: | |||
|     void enable_selection(bool enable); | ||||
|     void enable_main_toolbar(bool enable); | ||||
|     void enable_undoredo_toolbar(bool enable); | ||||
|     void enable_collapse_toolbar(bool enable); | ||||
|     void enable_dynamic_background(bool enable); | ||||
|     void enable_labels(bool enable) { m_labels.enable(enable); } | ||||
| #if ENABLE_SLOPE_RENDERING | ||||
|  | @ -741,6 +745,7 @@ private: | |||
|     bool _init_main_toolbar(); | ||||
|     bool _init_undoredo_toolbar(); | ||||
|     bool _init_view_toolbar(); | ||||
|     bool _init_collapse_toolbar(); | ||||
| 
 | ||||
|     bool _set_current(); | ||||
|     void _resize(unsigned int w, unsigned int h); | ||||
|  | @ -769,6 +774,7 @@ private: | |||
|     void _render_gizmos_overlay() const; | ||||
|     void _render_main_toolbar() const; | ||||
|     void _render_undoredo_toolbar() const; | ||||
|     void _render_collapse_toolbar() const; | ||||
|     void _render_view_toolbar() const; | ||||
| #if ENABLE_SHOW_CAMERA_TARGET | ||||
|     void _render_camera_target() const; | ||||
|  | @ -776,6 +782,7 @@ private: | |||
|     void _render_sla_slices() const; | ||||
|     void _render_selection_sidebar_hints() const; | ||||
|     bool _render_undo_redo_stack(const bool is_undo, float pos_x) const; | ||||
|     bool _render_search_list(float pos_x) const; | ||||
|     void _render_thumbnail_internal(ThumbnailData& thumbnail_data, bool printable_only, bool parts_only, bool show_bed, bool transparent_background) const; | ||||
|     // render thumbnail using an off-screen framebuffer
 | ||||
|     void _render_thumbnail_framebuffer(ThumbnailData& thumbnail_data, unsigned int w, unsigned int h, bool printable_only, bool parts_only, bool show_bed, bool transparent_background) const; | ||||
|  | @ -835,6 +842,9 @@ private: | |||
|     void _update_selection_from_hover(); | ||||
| 
 | ||||
|     bool _deactivate_undo_redo_toolbar_items(); | ||||
|     bool _deactivate_search_toolbar_item(); | ||||
|     bool _activate_search_toolbar_item(); | ||||
|     bool _deactivate_collapse_toolbar_items(); | ||||
| 
 | ||||
|     static std::vector<float> _parse_colors(const std::vector<std::string>& colors); | ||||
| 
 | ||||
|  |  | |||
|  | @ -406,6 +406,12 @@ void GLToolbar::set_additional_tooltip(int item_id, const std::string& text) | |||
|         m_items[item_id]->set_additional_tooltip(text); | ||||
| } | ||||
| 
 | ||||
| void GLToolbar::set_tooltip(int item_id, const std::string& text) | ||||
| { | ||||
|     if (0 <= item_id && item_id < (int)m_items.size()) | ||||
|         m_items[item_id]->set_tooltip(text); | ||||
| } | ||||
| 
 | ||||
| bool GLToolbar::update_items_state() | ||||
| { | ||||
|     bool ret = false; | ||||
|  |  | |||
|  | @ -118,6 +118,7 @@ public: | |||
|     const std::string& get_tooltip() const { return m_data.tooltip; } | ||||
|     const std::string& get_additional_tooltip() const { return m_data.additional_tooltip; } | ||||
|     void set_additional_tooltip(const std::string& text) { m_data.additional_tooltip = text; } | ||||
|     void set_tooltip(const std::string& text)            { m_data.tooltip = text; } | ||||
| 
 | ||||
|     void do_left_action() { m_last_action_type = Left; m_data.left.action_callback(); } | ||||
|     void do_right_action() { m_last_action_type = Right; m_data.right.action_callback(); } | ||||
|  | @ -317,6 +318,7 @@ public: | |||
| 
 | ||||
|     void get_additional_tooltip(int item_id, std::string& text); | ||||
|     void set_additional_tooltip(int item_id, const std::string& text); | ||||
|     void set_tooltip(int item_id, const std::string& text); | ||||
| 
 | ||||
|     // returns true if any item changed its state
 | ||||
|     bool update_items_state(); | ||||
|  |  | |||
|  | @ -188,6 +188,8 @@ void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt | |||
| 				opt_key == "bottom_fill_pattern" || | ||||
| 				opt_key == "fill_pattern") | ||||
| 				config.set_key_value(opt_key, new ConfigOptionEnum<InfillPattern>(boost::any_cast<InfillPattern>(value)));  | ||||
| 			else if (opt_key.compare("ironing_type") == 0) | ||||
| 				config.set_key_value(opt_key, new ConfigOptionEnum<IroningType>(boost::any_cast<IroningType>(value)));  | ||||
| 			else if (opt_key.compare("gcode_flavor") == 0) | ||||
| 				config.set_key_value(opt_key, new ConfigOptionEnum<GCodeFlavor>(boost::any_cast<GCodeFlavor>(value)));  | ||||
| 			else if (opt_key.compare("support_material_pattern") == 0) | ||||
|  |  | |||
|  | @ -50,6 +50,7 @@ | |||
| #include "UpdateDialogs.hpp" | ||||
| #include "Mouse3DController.hpp" | ||||
| #include "RemovableDriveManager.hpp" | ||||
| #include "InstanceCheck.hpp" | ||||
| 
 | ||||
| #ifdef __WXMSW__ | ||||
| #include <dbt.h> | ||||
|  | @ -209,6 +210,17 @@ static void register_win32_device_notification_event() | |||
| 		} | ||||
|         return false; | ||||
|     }); | ||||
| 
 | ||||
| 	wxWindow::MSWRegisterMessageHandler(WM_COPYDATA, [](wxWindow* win, WXUINT /* nMsg */, WXWPARAM wParam, WXLPARAM lParam) { | ||||
| 
 | ||||
| 		COPYDATASTRUCT* copy_data_structure = { 0 }; | ||||
| 		copy_data_structure = (COPYDATASTRUCT*)lParam; | ||||
| 		if (copy_data_structure->dwData == 1) { | ||||
| 			LPCWSTR arguments = (LPCWSTR)copy_data_structure->lpData; | ||||
| 			Slic3r::GUI::wxGetApp().other_instance_message_handler()->handle_message(boost::nowide::narrow(arguments)); | ||||
| 		} | ||||
| 		return true; | ||||
| 		}); | ||||
| } | ||||
| #endif // WIN32
 | ||||
| 
 | ||||
|  | @ -253,7 +265,11 @@ GUI_App::GUI_App() | |||
|     , m_imgui(new ImGuiWrapper()) | ||||
|     , m_wizard(nullptr) | ||||
| 	, m_removable_drive_manager(std::make_unique<RemovableDriveManager>()) | ||||
| {} | ||||
| 	, m_other_instance_message_handler(std::make_unique<OtherInstanceMessageHandler>()) | ||||
| { | ||||
| 	//app config initializes early becasuse it is used in instance checking in PrusaSlicer.cpp
 | ||||
| 	this->init_app_config(); | ||||
| } | ||||
| 
 | ||||
| GUI_App::~GUI_App() | ||||
| { | ||||
|  | @ -284,6 +300,30 @@ bool GUI_App::init_opengl() | |||
| } | ||||
| #endif // ENABLE_NON_STATIC_CANVAS_MANAGER
 | ||||
| 
 | ||||
| void GUI_App::init_app_config() | ||||
| { | ||||
| 	// Profiles for the alpha are stored into the PrusaSlicer-alpha directory to not mix with the current release.
 | ||||
| 	SetAppName(SLIC3R_APP_KEY); | ||||
| 	//SetAppName(SLIC3R_APP_KEY "-beta");
 | ||||
| 	SetAppDisplayName(SLIC3R_APP_NAME); | ||||
| 
 | ||||
| 	// Set the Slic3r data directory at the Slic3r XS module.
 | ||||
| 	// Unix: ~/ .Slic3r
 | ||||
| 	// Windows : "C:\Users\username\AppData\Roaming\Slic3r" or "C:\Documents and Settings\username\Application Data\Slic3r"
 | ||||
| 	// Mac : "~/Library/Application Support/Slic3r"
 | ||||
| 
 | ||||
| 	if (data_dir().empty()) | ||||
| 		set_data_dir(wxStandardPaths::Get().GetUserDataDir().ToUTF8().data()); | ||||
| 
 | ||||
| 	if (!app_config) | ||||
| 		app_config = new AppConfig(); | ||||
| 
 | ||||
| 	// load settings
 | ||||
| 	app_conf_exists = app_config->exists(); | ||||
| 	if (app_conf_exists) { | ||||
| 		app_config->load(); | ||||
| 	} | ||||
| } | ||||
| bool GUI_App::OnInit() | ||||
| { | ||||
|     try { | ||||
|  | @ -301,46 +341,24 @@ bool GUI_App::on_init_inner() | |||
|     wxCHECK_MSG(wxDirExists(resources_dir), false, | ||||
|         wxString::Format("Resources path does not exist or is not a directory: %s", resources_dir)); | ||||
| 
 | ||||
|     // Profiles for the alpha are stored into the PrusaSlicer-alpha directory to not mix with the current release.
 | ||||
|     SetAppName(SLIC3R_APP_KEY); | ||||
| //    SetAppName(SLIC3R_APP_KEY "-beta");
 | ||||
|     SetAppDisplayName(SLIC3R_APP_NAME); | ||||
| 
 | ||||
| // Enable this to get the default Win32 COMCTRL32 behavior of static boxes.
 | ||||
|      // Enable this to get the default Win32 COMCTRL32 behavior of static boxes.
 | ||||
| //    wxSystemOptions::SetOption("msw.staticbox.optimized-paint", 0);
 | ||||
| // Enable this to disable Windows Vista themes for all wxNotebooks. The themes seem to lead to terrible
 | ||||
| // performance when working on high resolution multi-display setups.
 | ||||
|     // Enable this to disable Windows Vista themes for all wxNotebooks. The themes seem to lead to terrible
 | ||||
|     // performance when working on high resolution multi-display setups.
 | ||||
| //    wxSystemOptions::SetOption("msw.notebook.themed-background", 0);
 | ||||
| 
 | ||||
| //     Slic3r::debugf "wxWidgets version %s, Wx version %s\n", wxVERSION_STRING, wxVERSION;
 | ||||
| 
 | ||||
|     // Set the Slic3r data directory at the Slic3r XS module.
 | ||||
|     // Unix: ~/ .Slic3r
 | ||||
|     // Windows : "C:\Users\username\AppData\Roaming\Slic3r" or "C:\Documents and Settings\username\Application Data\Slic3r"
 | ||||
|     // Mac : "~/Library/Application Support/Slic3r"
 | ||||
|     if (data_dir().empty()) | ||||
|         set_data_dir(wxStandardPaths::Get().GetUserDataDir().ToUTF8().data()); | ||||
| 
 | ||||
|     app_config = new AppConfig(); | ||||
| 
 | ||||
|     // load settings
 | ||||
|     app_conf_exists = app_config->exists(); | ||||
|     if (app_conf_exists) { | ||||
|         app_config->load(); | ||||
|     } | ||||
|      | ||||
|     | ||||
|     std::string msg = Http::tls_global_init(); | ||||
|     wxRichMessageDialog | ||||
|         dlg(nullptr, | ||||
|             wxString::Format(_(L("%s\nDo you want to continue?")), _(msg)), | ||||
|             "PrusaSlicer", wxICON_QUESTION | wxYES_NO); | ||||
|      | ||||
|     bool ssl_accept = app_config->get("tls_cert_store_accepted") == "yes"; | ||||
|     std::string ssl_cert_store = app_config->get("tls_accepted_cert_store_location"); | ||||
|     ssl_accept = ssl_accept && ssl_cert_store == Http::tls_system_cert_store(); | ||||
|     bool ssl_accept = app_config->get("tls_cert_store_accepted") == "yes" && ssl_cert_store == Http::tls_system_cert_store(); | ||||
|      | ||||
|     dlg.ShowCheckBox(_(L("Remember my choice"))); | ||||
|     if (!msg.empty() && !ssl_accept) { | ||||
|         wxRichMessageDialog | ||||
|             dlg(nullptr, | ||||
|                 wxString::Format(_(L("%s\nDo you want to continue?")), msg), | ||||
|                 "PrusaSlicer", wxICON_QUESTION | wxYES_NO); | ||||
|         dlg.ShowCheckBox(_(L("Remember my choice"))); | ||||
|         if (dlg.ShowModal() != wxID_YES) return false; | ||||
| 
 | ||||
|         app_config->set("tls_cert_store_accepted", | ||||
|  | @ -395,6 +413,8 @@ bool GUI_App::on_init_inner() | |||
|     if (wxImage::FindHandler(wxBITMAP_TYPE_PNG) == nullptr) | ||||
|         wxImage::AddHandler(new wxPNGHandler()); | ||||
|     mainframe = new MainFrame(); | ||||
|     mainframe->switch_to(true); // hide settings tabs after first Layout
 | ||||
| 
 | ||||
|     sidebar().obj_list()->init_objects(); // propagate model objects to object list
 | ||||
| //     update_mode(); // !!! do that later
 | ||||
|     SetTopWindow(mainframe); | ||||
|  | @ -407,6 +427,8 @@ bool GUI_App::on_init_inner() | |||
|         if (! plater_) | ||||
|             return; | ||||
| 
 | ||||
| 		//m_other_instance_message_handler->report();
 | ||||
| 
 | ||||
|         if (app_config->dirty() && app_config->get("autosave") == "1") | ||||
|             app_config->save(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -35,6 +35,7 @@ class PrintHostJobQueue; | |||
| 
 | ||||
| namespace GUI{ | ||||
| class RemovableDriveManager; | ||||
| class OtherInstanceMessageHandler; | ||||
| enum FileType | ||||
| { | ||||
|     FT_STL, | ||||
|  | @ -108,7 +109,7 @@ class GUI_App : public wxApp | |||
|     std::unique_ptr<ImGuiWrapper> m_imgui; | ||||
|     std::unique_ptr<PrintHostJobQueue> m_printhost_job_queue; | ||||
|     ConfigWizard* m_wizard;    // Managed by wxWindow tree
 | ||||
| 
 | ||||
| 	std::unique_ptr <OtherInstanceMessageHandler> m_other_instance_message_handler; | ||||
| public: | ||||
|     bool            OnInit() override; | ||||
|     bool            initialized() const { return m_initialized; } | ||||
|  | @ -196,6 +197,7 @@ public: | |||
|     std::vector<Tab *>      tabs_list; | ||||
| 
 | ||||
| 	RemovableDriveManager* removable_drive_manager() { return m_removable_drive_manager.get(); } | ||||
| 	OtherInstanceMessageHandler* other_instance_message_handler() { return m_other_instance_message_handler.get(); } | ||||
| 
 | ||||
|     ImGuiWrapper* imgui() { return m_imgui.get(); } | ||||
| 
 | ||||
|  | @ -211,6 +213,7 @@ public: | |||
| 
 | ||||
| private: | ||||
|     bool            on_init_inner(); | ||||
| 	void            init_app_config(); | ||||
|     void            window_pos_save(wxTopLevelWindow* window, const std::string &name); | ||||
|     void            window_pos_restore(wxTopLevelWindow* window, const std::string &name, bool default_maximized = false); | ||||
|     void            window_pos_sanitize(wxTopLevelWindow* window); | ||||
|  |  | |||
|  | @ -97,6 +97,7 @@ bool View3D::init(wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view_ | |||
|     m_canvas->enable_selection(true); | ||||
|     m_canvas->enable_main_toolbar(true); | ||||
|     m_canvas->enable_undoredo_toolbar(true); | ||||
|     m_canvas->enable_collapse_toolbar(true); | ||||
|     m_canvas->enable_labels(true); | ||||
| #if ENABLE_SLOPE_RENDERING | ||||
|     m_canvas->enable_slope(true); | ||||
|  | @ -270,6 +271,7 @@ bool Preview::init(wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view | |||
|     m_canvas->set_process(m_process); | ||||
|     m_canvas->enable_legend_texture(true); | ||||
|     m_canvas->enable_dynamic_background(true); | ||||
|     m_canvas->enable_collapse_toolbar(true); | ||||
| 
 | ||||
|     m_double_slider_sizer = new wxBoxSizer(wxHORIZONTAL); | ||||
|     create_double_slider(); | ||||
|  |  | |||
|  | @ -15,12 +15,17 @@ | |||
| 
 | ||||
| #include <GL/glew.h> | ||||
| 
 | ||||
| #ifndef IMGUI_DEFINE_MATH_OPERATORS | ||||
| #define IMGUI_DEFINE_MATH_OPERATORS | ||||
| #endif | ||||
| #include <imgui/imgui_internal.h> | ||||
| 
 | ||||
| #include "libslic3r/libslic3r.h" | ||||
| #include "libslic3r/Utils.hpp" | ||||
| #include "3DScene.hpp" | ||||
| #include "GUI.hpp" | ||||
| #include "I18N.hpp" | ||||
| #include "Search.hpp" | ||||
| 
 | ||||
| namespace Slic3r { | ||||
| namespace GUI { | ||||
|  | @ -374,7 +379,40 @@ bool ImGuiWrapper::combo(const wxString& label, const std::vector<std::string>& | |||
|     return res; | ||||
| } | ||||
| 
 | ||||
| bool ImGuiWrapper::undo_redo_list(const ImVec2& size, const bool is_undo, bool (*items_getter)(const bool , int , const char**), int& hovered, int& selected) | ||||
| // Scroll up for one item 
 | ||||
| static void scroll_up() | ||||
| { | ||||
|     ImGuiContext& g = *GImGui; | ||||
|     ImGuiWindow* window = g.CurrentWindow; | ||||
| 
 | ||||
|     float item_size_y = window->DC.PrevLineSize.y + g.Style.ItemSpacing.y; | ||||
|     float win_top = window->Scroll.y; | ||||
| 
 | ||||
|     ImGui::SetScrollY(win_top - item_size_y); | ||||
| } | ||||
| 
 | ||||
| // Scroll down for one item 
 | ||||
| static void scroll_down() | ||||
| { | ||||
|     ImGuiContext& g = *GImGui; | ||||
|     ImGuiWindow* window = g.CurrentWindow; | ||||
| 
 | ||||
|     float item_size_y = window->DC.PrevLineSize.y + g.Style.ItemSpacing.y; | ||||
|     float win_top = window->Scroll.y; | ||||
| 
 | ||||
|     ImGui::SetScrollY(win_top + item_size_y); | ||||
| } | ||||
| 
 | ||||
| static void process_mouse_wheel(int& mouse_wheel) | ||||
| { | ||||
|     if (mouse_wheel > 0) | ||||
|         scroll_up(); | ||||
|     else if (mouse_wheel < 0) | ||||
|         scroll_down(); | ||||
|     mouse_wheel = 0; | ||||
| } | ||||
| 
 | ||||
| bool ImGuiWrapper::undo_redo_list(const ImVec2& size, const bool is_undo, bool (*items_getter)(const bool , int , const char**), int& hovered, int& selected, int& mouse_wheel) | ||||
| { | ||||
|     bool is_hovered = false; | ||||
|     ImGui::ListBoxHeader("", size); | ||||
|  | @ -396,10 +434,312 @@ bool ImGuiWrapper::undo_redo_list(const ImVec2& size, const bool is_undo, bool ( | |||
|         i++; | ||||
|     } | ||||
| 
 | ||||
|     if (is_hovered) | ||||
|         process_mouse_wheel(mouse_wheel); | ||||
| 
 | ||||
|     ImGui::ListBoxFooter(); | ||||
|     return is_hovered; | ||||
| } | ||||
| 
 | ||||
| // It's a copy of IMGui::Selactable function.
 | ||||
| // But a little beat modified to change a label text.
 | ||||
| // If item is hovered we should use another color for highlighted letters.
 | ||||
| // To do that we push a ColorMarkerHovered symbol at the very beginning of the label
 | ||||
| // This symbol will be used to a color selection for the highlighted letters.
 | ||||
| // see imgui_draw.cpp, void ImFont::RenderText()
 | ||||
| static bool selectable(const char* label, bool selected, ImGuiSelectableFlags flags = 0, const ImVec2& size_arg = ImVec2(0, 0)) | ||||
| { | ||||
|     ImGuiWindow* window = ImGui::GetCurrentWindow(); | ||||
|     if (window->SkipItems) | ||||
|         return false; | ||||
| 
 | ||||
|     ImGuiContext& g = *GImGui; | ||||
|     const ImGuiStyle& style = g.Style; | ||||
| 
 | ||||
|     if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.CurrentColumns) // FIXME-OPT: Avoid if vertically clipped.
 | ||||
|         ImGui::PushColumnsBackground(); | ||||
| 
 | ||||
|     ImGuiID id = window->GetID(label); | ||||
|     ImVec2 label_size = ImGui::CalcTextSize(label, NULL, true); | ||||
|     ImVec2 size(size_arg.x != 0.0f ? size_arg.x : label_size.x, size_arg.y != 0.0f ? size_arg.y : label_size.y); | ||||
|     ImVec2 pos = window->DC.CursorPos; | ||||
|     pos.y += window->DC.CurrLineTextBaseOffset; | ||||
|     ImRect bb_inner(pos, pos + size); | ||||
|     ImGui::ItemSize(size, 0.0f); | ||||
| 
 | ||||
|     // Fill horizontal space.
 | ||||
|     ImVec2 window_padding = window->WindowPadding; | ||||
|     float max_x = (flags & ImGuiSelectableFlags_SpanAllColumns) ? ImGui::GetWindowContentRegionMax().x : ImGui::GetContentRegionMax().x; | ||||
|     float w_draw = ImMax(label_size.x, window->Pos.x + max_x - window_padding.x - pos.x); | ||||
|     ImVec2 size_draw((size_arg.x != 0 && !(flags & ImGuiSelectableFlags_DrawFillAvailWidth)) ? size_arg.x : w_draw, size_arg.y != 0.0f ? size_arg.y : size.y); | ||||
|     ImRect bb(pos, pos + size_draw); | ||||
|     if (size_arg.x == 0.0f || (flags & ImGuiSelectableFlags_DrawFillAvailWidth)) | ||||
|         bb.Max.x += window_padding.x; | ||||
| 
 | ||||
|     // Selectables are tightly packed together so we extend the box to cover spacing between selectable.
 | ||||
|     const float spacing_x = style.ItemSpacing.x; | ||||
|     const float spacing_y = style.ItemSpacing.y; | ||||
|     const float spacing_L = IM_FLOOR(spacing_x * 0.50f); | ||||
|     const float spacing_U = IM_FLOOR(spacing_y * 0.50f); | ||||
|     bb.Min.x -= spacing_L; | ||||
|     bb.Min.y -= spacing_U; | ||||
|     bb.Max.x += (spacing_x - spacing_L); | ||||
|     bb.Max.y += (spacing_y - spacing_U); | ||||
| 
 | ||||
|     bool item_add; | ||||
|     if (flags & ImGuiSelectableFlags_Disabled) | ||||
|     { | ||||
|         ImGuiItemFlags backup_item_flags = window->DC.ItemFlags; | ||||
|         window->DC.ItemFlags |= ImGuiItemFlags_Disabled | ImGuiItemFlags_NoNavDefaultFocus; | ||||
|         item_add = ImGui::ItemAdd(bb, id); | ||||
|         window->DC.ItemFlags = backup_item_flags; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         item_add = ImGui::ItemAdd(bb, id); | ||||
|     } | ||||
|     if (!item_add) | ||||
|     { | ||||
|         if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.CurrentColumns) | ||||
|             ImGui::PopColumnsBackground(); | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     // We use NoHoldingActiveID on menus so user can click and _hold_ on a menu then drag to browse child entries
 | ||||
|     ImGuiButtonFlags button_flags = 0; | ||||
|     if (flags & ImGuiSelectableFlags_NoHoldingActiveID) { button_flags |= ImGuiButtonFlags_NoHoldingActiveId; } | ||||
|     if (flags & ImGuiSelectableFlags_PressedOnClick) { button_flags |= ImGuiButtonFlags_PressedOnClick; } | ||||
|     if (flags & ImGuiSelectableFlags_PressedOnRelease) { button_flags |= ImGuiButtonFlags_PressedOnRelease; } | ||||
|     if (flags & ImGuiSelectableFlags_Disabled) { button_flags |= ImGuiButtonFlags_Disabled; } | ||||
|     if (flags & ImGuiSelectableFlags_AllowDoubleClick) { button_flags |= ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnDoubleClick; } | ||||
|     if (flags & ImGuiSelectableFlags_AllowItemOverlap) { button_flags |= ImGuiButtonFlags_AllowItemOverlap; } | ||||
| 
 | ||||
|     if (flags & ImGuiSelectableFlags_Disabled) | ||||
|         selected = false; | ||||
| 
 | ||||
|     const bool was_selected = selected; | ||||
|     bool hovered, held; | ||||
|     bool pressed = ImGui::ButtonBehavior(bb, id, &hovered, &held, button_flags); | ||||
| 
 | ||||
|     // Update NavId when clicking or when Hovering (this doesn't happen on most widgets), so navigation can be resumed with gamepad/keyboard
 | ||||
|     if (pressed || (hovered && (flags & ImGuiSelectableFlags_SetNavIdOnHover))) | ||||
|     { | ||||
|         if (!g.NavDisableMouseHover && g.NavWindow == window && g.NavLayer == window->DC.NavLayerCurrent) | ||||
|         { | ||||
|             g.NavDisableHighlight = true; | ||||
|             ImGui::SetNavID(id, window->DC.NavLayerCurrent, window->DC.NavFocusScopeIdCurrent); | ||||
|         } | ||||
|     } | ||||
|     if (pressed) | ||||
|         ImGui::MarkItemEdited(id); | ||||
| 
 | ||||
|     if (flags & ImGuiSelectableFlags_AllowItemOverlap) | ||||
|         ImGui::SetItemAllowOverlap(); | ||||
| 
 | ||||
|     // In this branch, Selectable() cannot toggle the selection so this will never trigger.
 | ||||
|     if (selected != was_selected) //-V547
 | ||||
|         window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_ToggledSelection; | ||||
| 
 | ||||
|     // Render
 | ||||
|     if (held && (flags & ImGuiSelectableFlags_DrawHoveredWhenHeld)) | ||||
|         hovered = true; | ||||
|     if (hovered || selected) | ||||
|     { | ||||
|         const ImU32 col = ImGui::GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header); | ||||
|         ImGui::RenderFrame(bb.Min, bb.Max, col, false, 0.0f); | ||||
|         ImGui::RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_TypeThin | ImGuiNavHighlightFlags_NoRounding); | ||||
|     } | ||||
| 
 | ||||
|     if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.CurrentColumns) | ||||
|     { | ||||
|         ImGui::PopColumnsBackground(); | ||||
|         bb.Max.x -= (ImGui::GetContentRegionMax().x - max_x); | ||||
|     } | ||||
| 
 | ||||
|     // mark a label with a ImGui::ColorMarkerHovered, if item is hovered
 | ||||
|     char* marked_label = new char[255]; | ||||
|     if (hovered) | ||||
|         sprintf(marked_label, "%c%s", ImGui::ColorMarkerHovered, label); | ||||
|     else | ||||
|         strcpy(marked_label, label); | ||||
| 
 | ||||
|     if (flags & ImGuiSelectableFlags_Disabled) ImGui::PushStyleColor(ImGuiCol_Text, style.Colors[ImGuiCol_TextDisabled]); | ||||
|     ImGui::RenderTextClipped(bb_inner.Min, bb_inner.Max, marked_label, NULL, &label_size, style.SelectableTextAlign, &bb); | ||||
|     if (flags & ImGuiSelectableFlags_Disabled) ImGui::PopStyleColor(); | ||||
| 
 | ||||
|     delete[] marked_label; | ||||
| 
 | ||||
|     // Automatically close popups
 | ||||
|     if (pressed && (window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiSelectableFlags_DontClosePopups) && !(window->DC.ItemFlags & ImGuiItemFlags_SelectableDontClosePopup)) ImGui::CloseCurrentPopup(); | ||||
| 
 | ||||
|     IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags); | ||||
|     return pressed; | ||||
| } | ||||
| 
 | ||||
| // Scroll so that the hovered item is at the top of the window
 | ||||
| static void scroll_y(int hover_id) | ||||
| { | ||||
|     if (hover_id < 0) | ||||
|         return; | ||||
|     ImGuiContext& g = *GImGui; | ||||
|     ImGuiWindow* window = g.CurrentWindow; | ||||
| 
 | ||||
|     float item_size_y = window->DC.PrevLineSize.y + g.Style.ItemSpacing.y; | ||||
|     float item_delta = 0.5 * item_size_y; | ||||
| 
 | ||||
|     float item_top = item_size_y * hover_id; | ||||
|     float item_bottom = item_top + item_size_y; | ||||
| 
 | ||||
|     float win_top = window->Scroll.y; | ||||
|     float win_bottom = window->Scroll.y + window->Size.y; | ||||
| 
 | ||||
|     if (item_bottom + item_delta >= win_bottom) | ||||
|         ImGui::SetScrollY(win_top + item_size_y); | ||||
|     else if (item_top - item_delta <= win_top) | ||||
|         ImGui::SetScrollY(win_top - item_size_y); | ||||
| } | ||||
| 
 | ||||
| // Use this function instead of ImGui::IsKeyPressed.
 | ||||
| // ImGui::IsKeyPressed is related for *GImGui.IO.KeysDownDuration[user_key_index]
 | ||||
| // And after first key pressing IsKeyPressed() return "true" always even if key wasn't pressed
 | ||||
| static void process_key_down(ImGuiKey imgui_key, std::function<void()> f) | ||||
| { | ||||
|     if (ImGui::IsKeyDown(ImGui::GetKeyIndex(imgui_key))) | ||||
|     { | ||||
|         f(); | ||||
|         // set KeysDown to false to avoid redundant key down processing
 | ||||
|         ImGuiContext& g = *GImGui; | ||||
|         g.IO.KeysDown[ImGui::GetKeyIndex(imgui_key)] = false; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void ImGuiWrapper::search_list(const ImVec2& size_, bool (*items_getter)(int, const char** label, const char** tooltip), char* search_str, | ||||
|                                Search::OptionViewParameters& view_params, int& selected, bool& edited, int& mouse_wheel) | ||||
| { | ||||
|     // ImGui::ListBoxHeader("", size);
 | ||||
|     {    | ||||
|         // rewrote part of function to add a TextInput instead of label Text
 | ||||
|         ImGuiContext& g = *GImGui; | ||||
|         ImGuiWindow* window = ImGui::GetCurrentWindow(); | ||||
|         if (window->SkipItems) | ||||
|             return ; | ||||
| 
 | ||||
|         const ImGuiStyle& style = g.Style; | ||||
| 
 | ||||
|         // Size default to hold ~7 items. Fractional number of items helps seeing that we can scroll down/up without looking at scrollbar.
 | ||||
|         ImVec2 size = ImGui::CalcItemSize(size_, ImGui::CalcItemWidth(), ImGui::GetTextLineHeightWithSpacing() * 7.4f + style.ItemSpacing.y); | ||||
|         ImRect frame_bb(window->DC.CursorPos, ImVec2(window->DC.CursorPos.x + size.x, window->DC.CursorPos.y + size.y)); | ||||
| 
 | ||||
|         ImRect bb(frame_bb.Min, frame_bb.Max); | ||||
|         window->DC.LastItemRect = bb; // Forward storage for ListBoxFooter.. dodgy.
 | ||||
|         g.NextItemData.ClearFlags(); | ||||
| 
 | ||||
|         if (!ImGui::IsRectVisible(bb.Min, bb.Max)) | ||||
|         { | ||||
|             ImGui::ItemSize(bb.GetSize(), style.FramePadding.y); | ||||
|             ImGui::ItemAdd(bb, 0, &frame_bb); | ||||
|             return ; | ||||
|         } | ||||
| 
 | ||||
|         ImGui::BeginGroup(); | ||||
| 
 | ||||
|         const ImGuiID id = ImGui::GetID(search_str); | ||||
|         ImVec2 search_size = ImVec2(size.x, ImGui::GetTextLineHeightWithSpacing() + style.ItemSpacing.y); | ||||
| 
 | ||||
|         if (!ImGui::IsAnyItemFocused() && !ImGui::IsAnyItemActive() && !ImGui::IsMouseClicked(0)) | ||||
|             ImGui::SetKeyboardFocusHere(0); | ||||
| 
 | ||||
|         // The press on Esc key invokes editing of InputText (removes last changes)
 | ||||
|         // So we should save previous value...
 | ||||
|         std::string str = search_str; | ||||
|         ImGui::InputTextEx("", NULL, search_str, 20, search_size, ImGuiInputTextFlags_AutoSelectAll, NULL, NULL); | ||||
|         edited = ImGui::IsItemEdited(); | ||||
|         if (edited) | ||||
|             view_params.hovered_id = -1; | ||||
| 
 | ||||
|         process_key_down(ImGuiKey_Escape, [&selected, search_str, str]() { | ||||
|             // use 9999 to mark selection as a Esc key
 | ||||
|             selected = 9999; | ||||
|             // ... and when Esc key was pressed, than revert search_str value
 | ||||
|             strcpy(search_str, str.c_str()); | ||||
|         }); | ||||
| 
 | ||||
|         ImGui::BeginChildFrame(id, frame_bb.GetSize()); | ||||
|     } | ||||
| 
 | ||||
|     int i = 0; | ||||
|     const char* item_text; | ||||
|     const char* tooltip; | ||||
|     int mouse_hovered = -1; | ||||
|     int& hovered_id = view_params.hovered_id; | ||||
| 
 | ||||
|     while (items_getter(i, &item_text, &tooltip)) | ||||
|     { | ||||
|         selectable(item_text, i == hovered_id); | ||||
| 
 | ||||
|         if (ImGui::IsItemHovered()) { | ||||
|             ImGui::SetTooltip("%s", /*item_text*/tooltip); | ||||
|             view_params.hovered_id = -1; | ||||
|             mouse_hovered = i; | ||||
|         } | ||||
| 
 | ||||
|         if (ImGui::IsItemClicked()) | ||||
|             selected = i; | ||||
|         i++; | ||||
|     } | ||||
| 
 | ||||
|     scroll_y(mouse_hovered); | ||||
| 
 | ||||
|     // Process mouse wheel
 | ||||
|     if (mouse_hovered > 0) | ||||
|         process_mouse_wheel(mouse_wheel); | ||||
| 
 | ||||
|     // process Up/DownArrows and Enter
 | ||||
|     process_key_down(ImGuiKey_UpArrow, [&hovered_id, mouse_hovered]() { | ||||
|         if (mouse_hovered > 0) | ||||
|             scroll_up(); | ||||
|         else { | ||||
|             if (hovered_id > 0 && hovered_id != size_t(-1)) | ||||
|                 --hovered_id; | ||||
|             scroll_y(hovered_id); | ||||
|         } | ||||
|     }); | ||||
| 
 | ||||
|     process_key_down(ImGuiKey_DownArrow, [&hovered_id, mouse_hovered, i]() { | ||||
|         if (mouse_hovered > 0) | ||||
|             scroll_down(); | ||||
|         else { | ||||
|             if (hovered_id == size_t(-1)) | ||||
|                 hovered_id = 0; | ||||
|             else if (hovered_id < size_t(i - 1)) | ||||
|                 ++hovered_id; | ||||
|             scroll_y(hovered_id); | ||||
|         } | ||||
|     }); | ||||
| 
 | ||||
|     process_key_down(ImGuiKey_Enter, [&selected, hovered_id]() { | ||||
|         selected = hovered_id; | ||||
|     }); | ||||
| 
 | ||||
|     ImGui::ListBoxFooter(); | ||||
| 
 | ||||
|     auto check_box = [&edited, this](const wxString& label, bool& check) { | ||||
|         ImGui::SameLine(); | ||||
|         bool ch = check; | ||||
|         checkbox(label, ch); | ||||
|         if (ImGui::IsItemClicked()) { | ||||
|             check = !check; | ||||
|             edited = true; | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     // add checkboxes for show/hide Categories and Groups
 | ||||
|     text(_L("Use for search")+":"); | ||||
|     check_box(_L("Type"),       view_params.type); | ||||
|     check_box(_L("Category"),   view_params.category); | ||||
|     check_box(_L("Group"),      view_params.group); | ||||
| } | ||||
| 
 | ||||
| void ImGuiWrapper::disabled_begin(bool disabled) | ||||
| { | ||||
|     wxCHECK_RET(!m_disabled, "ImGUI: Unbalanced disabled_begin() call"); | ||||
|  |  | |||
|  | @ -8,6 +8,10 @@ | |||
| 
 | ||||
| #include "libslic3r/Point.hpp" | ||||
| 
 | ||||
| namespace Slic3r {namespace Search { | ||||
| struct OptionViewParameters; | ||||
| }} | ||||
| 
 | ||||
| class wxString; | ||||
| class wxMouseEvent; | ||||
| class wxKeyEvent; | ||||
|  | @ -73,7 +77,9 @@ public: | |||
|     bool slider_float(const std::string& label, float* v, float v_min, float v_max, const char* format = "%.3f", float power = 1.0f); | ||||
|     bool slider_float(const wxString& label, float* v, float v_min, float v_max, const char* format = "%.3f", float power = 1.0f); | ||||
|     bool combo(const wxString& label, const std::vector<std::string>& options, int& selection);   // Use -1 to not mark any option as selected
 | ||||
|     bool undo_redo_list(const ImVec2& size, const bool is_undo, bool (*items_getter)(const bool, int, const char**), int& hovered, int& selected); | ||||
|     bool undo_redo_list(const ImVec2& size, const bool is_undo, bool (*items_getter)(const bool, int, const char**), int& hovered, int& selected, int& mouse_wheel); | ||||
|     void search_list(const ImVec2& size, bool (*items_getter)(int, const char** label, const char** tooltip), char* search_str, | ||||
|                      Search::OptionViewParameters& view_params, int& selected, bool& edited, int& mouse_wheel); | ||||
| 
 | ||||
|     void disabled_begin(bool disabled); | ||||
|     void disabled_end(); | ||||
|  |  | |||
							
								
								
									
										495
									
								
								src/slic3r/GUI/InstanceCheck.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										495
									
								
								src/slic3r/GUI/InstanceCheck.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,495 @@ | |||
| #include "GUI_App.hpp" | ||||
| #include "InstanceCheck.hpp" | ||||
| 
 | ||||
| #include "boost/nowide/convert.hpp" | ||||
| #include <boost/log/trivial.hpp> | ||||
| #include <iostream> | ||||
| 
 | ||||
| #include <fcntl.h> | ||||
| #include <errno.h> | ||||
| 
 | ||||
| #if __linux__ | ||||
| #include <dbus/dbus.h> /* Pull in all of D-Bus headers. */ | ||||
| #endif //__linux__
 | ||||
| 
 | ||||
| namespace Slic3r { | ||||
| namespace instance_check_internal | ||||
| { | ||||
| 	struct CommandLineAnalysis | ||||
| 	{ | ||||
| 		bool           should_send; | ||||
| 		std::string    cl_string; | ||||
| 	}; | ||||
| 	static CommandLineAnalysis process_command_line(int argc, char** argv) //d:\3dmodels\Klapka\Klapka.3mf
 | ||||
| 	{ | ||||
| 		CommandLineAnalysis ret { false }; | ||||
| 		if (argc < 2) | ||||
| 			return ret; | ||||
| 		ret.cl_string = argv[0]; | ||||
| 		for (size_t i = 1; i < argc; i++) { | ||||
| 			std::string token = argv[i]; | ||||
| 			if (token == "--single-instance") { | ||||
| 				ret.should_send = true; | ||||
| 			} else { | ||||
| 				ret.cl_string += " "; | ||||
| 				ret.cl_string += token; | ||||
| 			} | ||||
| 		} | ||||
| 		BOOST_LOG_TRIVIAL(debug) << "single instance: "<< ret.should_send << ". other params: " << ret.cl_string; | ||||
| 		return ret; | ||||
| 	} | ||||
| } //namespace instance_check_internal
 | ||||
| 
 | ||||
| #if _WIN32 | ||||
| 
 | ||||
| namespace instance_check_internal | ||||
| { | ||||
| 	static HWND l_prusa_slicer_hwnd; | ||||
| 	static BOOL CALLBACK EnumWindowsProc(_In_ HWND   hwnd, _In_ LPARAM lParam) | ||||
| 	{ | ||||
| 		//checks for other instances of prusaslicer, if found brings it to front and return false to stop enumeration and quit this instance
 | ||||
| 		//search is done by classname(wxWindowNR is wxwidgets thing, so probably not unique) and name in window upper panel
 | ||||
| 		//other option would be do a mutex and check for its existence
 | ||||
| 		TCHAR wndText[1000]; | ||||
| 		TCHAR className[1000]; | ||||
| 		GetClassName(hwnd, className, 1000); | ||||
| 		GetWindowText(hwnd, wndText, 1000); | ||||
| 		std::wstring classNameString(className); | ||||
| 		std::wstring wndTextString(wndText); | ||||
| 		if (wndTextString.find(L"PrusaSlicer") != std::wstring::npos && classNameString == L"wxWindowNR") { | ||||
| 			l_prusa_slicer_hwnd = hwnd; | ||||
| 			ShowWindow(hwnd, SW_SHOWMAXIMIZED); | ||||
| 			SetForegroundWindow(hwnd); | ||||
| 			return false; | ||||
| 		} | ||||
| 		return true; | ||||
| 	} | ||||
| 	static void send_message(const HWND hwnd) | ||||
| 	{ | ||||
| 		LPWSTR command_line_args = GetCommandLine(); | ||||
| 		//Create a COPYDATASTRUCT to send the information
 | ||||
| 		//cbData represents the size of the information we want to send.
 | ||||
| 		//lpData represents the information we want to send.
 | ||||
| 		//dwData is an ID defined by us(this is a type of ID different than WM_COPYDATA).
 | ||||
| 		COPYDATASTRUCT data_to_send = { 0 }; | ||||
| 		data_to_send.dwData = 1; | ||||
| 		data_to_send.cbData = sizeof(TCHAR) * (wcslen(command_line_args) + 1); | ||||
| 		data_to_send.lpData = command_line_args; | ||||
| 
 | ||||
| 		SendMessage(hwnd, WM_COPYDATA, 0, (LPARAM)&data_to_send); | ||||
| 	} | ||||
| } //namespace instance_check_internal
 | ||||
| 
 | ||||
| bool instance_check(int argc, char** argv, bool app_config_single_instance) | ||||
| { | ||||
| 	instance_check_internal::CommandLineAnalysis cla = instance_check_internal::process_command_line(argc, argv); | ||||
| 	if (cla.should_send || app_config_single_instance) { | ||||
| 		// Call EnumWidnows with own callback. cons: Based on text in the name of the window and class name which is generic.
 | ||||
| 		if (!EnumWindows(instance_check_internal::EnumWindowsProc, 0)) { | ||||
| 			BOOST_LOG_TRIVIAL(info) << "instance check: Another instance found. This instance will terminate."; | ||||
| 			instance_check_internal::send_message(instance_check_internal::l_prusa_slicer_hwnd); | ||||
| 			return true; | ||||
| 		} | ||||
| 	} | ||||
| 	BOOST_LOG_TRIVIAL(info) << "instance check: Another instance not found or single-instance not set."; | ||||
| 	return false; | ||||
| } | ||||
| 
 | ||||
| #elif defined(__APPLE__) | ||||
| 
 | ||||
| namespace instance_check_internal | ||||
| { | ||||
| 	static int get_lock()  | ||||
| 	{ | ||||
| 		struct flock fl; | ||||
| 		int fdlock; | ||||
| 		fl.l_type = F_WRLCK; | ||||
| 		fl.l_whence = SEEK_SET; | ||||
| 		fl.l_start = 0; | ||||
| 		fl.l_len = 1; | ||||
| 
 | ||||
| 		if ((fdlock = open("/tmp/prusaslicer.lock", O_WRONLY | O_CREAT, 0666)) == -1) | ||||
| 			return 0; | ||||
| 
 | ||||
| 		if (fcntl(fdlock, F_SETLK, &fl) == -1) | ||||
| 			return 0; | ||||
| 
 | ||||
| 		return 1; | ||||
| 	} | ||||
| } //namespace instance_check_internal
 | ||||
| 
 | ||||
| bool instance_check(int argc, char** argv, bool app_config_single_instance) | ||||
| { | ||||
| 	instance_check_internal::CommandLineAnalysis cla = instance_check_internal::process_command_line(argc, argv); | ||||
| 	if (!instance_check_internal::get_lock() && (cla.should_send || app_config_single_instance)) { | ||||
| 		BOOST_LOG_TRIVIAL(info) << "instance check: Another instance found. This instance will terminate."; | ||||
| 		send_message_mac(cla.cl_string); | ||||
| 		return true; | ||||
| 	} | ||||
| 	BOOST_LOG_TRIVIAL(info) << "instance check: Another instance not found or single-instance not set."; | ||||
| 	return false; | ||||
| } | ||||
| 
 | ||||
| #elif defined(__linux__) | ||||
| 
 | ||||
| namespace instance_check_internal | ||||
| { | ||||
| 	static int get_lock()  | ||||
| 	{ | ||||
| 		struct flock fl; | ||||
| 		int fdlock; | ||||
| 		fl.l_type = F_WRLCK; | ||||
| 		fl.l_whence = SEEK_SET; | ||||
| 		fl.l_start = 0; | ||||
| 		fl.l_len = 1; | ||||
| 
 | ||||
| 		if ((fdlock = open("/tmp/prusaslicer.lock", O_WRONLY | O_CREAT, 0666)) == -1) | ||||
| 			return 0; | ||||
| 
 | ||||
| 		if (fcntl(fdlock, F_SETLK, &fl) == -1) | ||||
| 			return 0; | ||||
| 
 | ||||
| 		return 1; | ||||
| 	} | ||||
| 
 | ||||
| 	static void send_message(std::string message_text) | ||||
| 	{ | ||||
| 		DBusMessage* 	msg; | ||||
| 	    DBusMessageIter args; | ||||
| 	    DBusConnection* conn; | ||||
| 	    DBusError 		err; | ||||
| 	    dbus_uint32_t 	serial 			= 0; | ||||
| 	    const char*		sigval 			= message_text.c_str(); | ||||
| 		std::string		interface_name  = "com.prusa3d.prusaslicer.InstanceCheck"; | ||||
| 		std::string   	method_name 	= "AnotherInstace"; | ||||
|     	std::string		object_name 	= "/com/prusa3d/prusaslicer/InstanceCheck";				 | ||||
| 
 | ||||
| 
 | ||||
| 	    // initialise the error value
 | ||||
| 	    dbus_error_init(&err); | ||||
| 
 | ||||
| 	    // connect to bus, and check for errors (use SESSION bus everywhere!)
 | ||||
| 	    conn = dbus_bus_get(DBUS_BUS_SESSION, &err); | ||||
| 	    if (dbus_error_is_set(&err)) {  | ||||
| 	    	BOOST_LOG_TRIVIAL(error) << "DBus Connection Error. Message to another instance wont be send."; | ||||
| 	    	BOOST_LOG_TRIVIAL(error) << "DBus Connection Error: "<< err.message; | ||||
| 	        dbus_error_free(&err);  | ||||
| 	        return; | ||||
| 	    } | ||||
| 	    if (NULL == conn) {  | ||||
| 	    	BOOST_LOG_TRIVIAL(error) << "DBus Connection is NULL. Message to another instance wont be send."; | ||||
| 	        return; | ||||
| 	    }	     | ||||
| 
 | ||||
| 		//some sources do request interface ownership before constructing msg but i think its wrong.
 | ||||
| 
 | ||||
| 	    //create new method call message
 | ||||
| 		msg = dbus_message_new_method_call(interface_name.c_str(), object_name.c_str(), interface_name.c_str(), method_name.c_str()); | ||||
| 	    if (NULL == msg) {  | ||||
| 	    	BOOST_LOG_TRIVIAL(error) << "DBus Message is NULL. Message to another instance wont be send."; | ||||
| 	    	dbus_connection_unref(conn); | ||||
| 	        return; | ||||
| 	    } | ||||
| 	    //the AnotherInstace method is not sending reply.
 | ||||
| 	    dbus_message_set_no_reply(msg, TRUE); | ||||
| 
 | ||||
| 	    //append arguments to message
 | ||||
| 		if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &sigval, DBUS_TYPE_INVALID)) { | ||||
| 			BOOST_LOG_TRIVIAL(error) << "Ran out of memory while constructing args for DBus message. Message to another instance wont be send."; | ||||
| 		    dbus_message_unref(msg); | ||||
| 		    dbus_connection_unref(conn); | ||||
| 		    return; | ||||
| 		} | ||||
| 
 | ||||
| 	    // send the message and flush the connection
 | ||||
| 	    if (!dbus_connection_send(conn, msg, &serial)) { | ||||
| 	        BOOST_LOG_TRIVIAL(error) << "Ran out of memory while sending DBus message."; | ||||
| 	        dbus_message_unref(msg); | ||||
| 	        dbus_connection_unref(conn); | ||||
| 	        return; | ||||
| 	    } | ||||
| 	    dbus_connection_flush(conn); | ||||
| 	    | ||||
| 		BOOST_LOG_TRIVIAL(trace) << "DBus message sent."; | ||||
| 	    | ||||
| 	    // free the message and close the connection
 | ||||
| 	    dbus_message_unref(msg); | ||||
| 	    dbus_connection_unref(conn); | ||||
| 	} | ||||
| } //namespace instance_check_internal
 | ||||
| 
 | ||||
| bool instance_check(int argc, char** argv, bool app_config_single_instance) | ||||
| { | ||||
| 	instance_check_internal::CommandLineAnalysis cla = instance_check_internal::process_command_line(argc, argv); | ||||
| 	if (!instance_check_internal::get_lock() && (cla.should_send || app_config_single_instance)) { | ||||
| 		BOOST_LOG_TRIVIAL(info) << "instance check: Another instance found. This instance will terminate."; | ||||
| 		instance_check_internal::send_message(cla.cl_string); | ||||
| 		return true; | ||||
| 	} | ||||
| 	BOOST_LOG_TRIVIAL(info) << "instance check: Another instance not found or single-instance not set."; | ||||
| 	return false; | ||||
| } | ||||
| #endif //_WIN32/__APPLE__/__linux__
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| namespace GUI { | ||||
| 
 | ||||
| wxDEFINE_EVENT(EVT_LOAD_MODEL_OTHER_INSTANCE, LoadFromOtherInstanceEvent); | ||||
| wxDEFINE_EVENT(EVT_INSTANCE_GO_TO_FRONT, InstanceGoToFrontEvent); | ||||
| 
 | ||||
| void OtherInstanceMessageHandler::init(wxEvtHandler* callback_evt_handler) | ||||
| { | ||||
| 	assert(!m_initialized); | ||||
| 	assert(m_callback_evt_handler == nullptr); | ||||
| 	if (m_initialized)  | ||||
| 		return; | ||||
| 
 | ||||
| 	m_initialized = true; | ||||
| 	m_callback_evt_handler = callback_evt_handler; | ||||
| 
 | ||||
| #if _WIN32  | ||||
| 	//create_listener_window();
 | ||||
| #endif  //_WIN32
 | ||||
| 
 | ||||
| #if defined(__APPLE__) | ||||
| 	this->register_for_messages(); | ||||
| #endif //__APPLE__
 | ||||
| 
 | ||||
| #ifdef BACKGROUND_MESSAGE_LISTENER | ||||
| 	m_thread = boost::thread((boost::bind(&OtherInstanceMessageHandler::listen, this))); | ||||
| #endif //BACKGROUND_MESSAGE_LISTENER
 | ||||
| } | ||||
| void OtherInstanceMessageHandler::shutdown() | ||||
| { | ||||
| 	BOOST_LOG_TRIVIAL(debug) << "message handler shutdown()."; | ||||
| 	assert(m_initialized); | ||||
| 	if (m_initialized) { | ||||
| #if __APPLE__ | ||||
| 		//delete macos implementation
 | ||||
| 		this->unregister_for_messages(); | ||||
| #endif //__APPLE__
 | ||||
| #ifdef BACKGROUND_MESSAGE_LISTENER | ||||
| 		if (m_thread.joinable()) { | ||||
| 			// Stop the worker thread, if running.
 | ||||
| 			{ | ||||
| 				// Notify the worker thread to cancel wait on detection polling.
 | ||||
| 				std::lock_guard<std::mutex> lck(m_thread_stop_mutex); | ||||
| 				m_stop = true; | ||||
| 			} | ||||
| 			m_thread_stop_condition.notify_all(); | ||||
| 			// Wait for the worker thread to stop.
 | ||||
| 			m_thread.join(); | ||||
| 			m_stop = false; | ||||
| 		} | ||||
| #endif //BACKGROUND_MESSAGE_LISTENER
 | ||||
| 	m_initialized = false; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| namespace MessageHandlerInternal | ||||
| { | ||||
|    // returns ::path to possible model or empty ::path if input string is not existing path
 | ||||
| 	static boost::filesystem::path get_path(const std::string possible_path) | ||||
| 	{ | ||||
| 		BOOST_LOG_TRIVIAL(debug) << "message part: " << possible_path; | ||||
| 
 | ||||
| 		if (possible_path.empty() || possible_path.size() < 3) { | ||||
| 			BOOST_LOG_TRIVIAL(debug) << "empty"; | ||||
| 			return boost::filesystem::path(); | ||||
| 		} | ||||
| 		if (boost::filesystem::exists(possible_path)) { | ||||
| 			BOOST_LOG_TRIVIAL(debug) << "is path"; | ||||
| 			return boost::filesystem::path(possible_path); | ||||
| 		} else if (possible_path[0] == '\"') { | ||||
| 			if(boost::filesystem::exists(possible_path.substr(1, possible_path.size() - 2))) { | ||||
| 				BOOST_LOG_TRIVIAL(debug) << "is path in quotes"; | ||||
| 				return boost::filesystem::path(possible_path.substr(1, possible_path.size() - 2)); | ||||
| 			} | ||||
| 		} | ||||
| 		BOOST_LOG_TRIVIAL(debug) << "is NOT path"; | ||||
| 		return boost::filesystem::path(); | ||||
| 	} | ||||
| } //namespace MessageHandlerInternal
 | ||||
| 
 | ||||
| void OtherInstanceMessageHandler::handle_message(const std::string message) { | ||||
| 	std::vector<boost::filesystem::path> paths; | ||||
| 	auto                                 next_space = message.find(' '); | ||||
| 	size_t                               last_space = 0; | ||||
| 	int                                  counter    = 0; | ||||
| 
 | ||||
| 	BOOST_LOG_TRIVIAL(info) << "message from other instance: " << message; | ||||
| 
 | ||||
| 	while (next_space != std::string::npos) | ||||
| 	{	 | ||||
| 		if (counter != 0) { | ||||
| 			const std::string possible_path = message.substr(last_space, next_space - last_space); | ||||
| 			boost::filesystem::path p = MessageHandlerInternal::get_path(possible_path); | ||||
| 			if(!p.string().empty()) | ||||
| 				paths.emplace_back(p); | ||||
| 		} | ||||
| 		last_space = next_space; | ||||
| 		next_space = message.find(' ', last_space + 1); | ||||
| 		counter++; | ||||
| 	} | ||||
| 	if (counter != 0 ) { | ||||
| 		boost::filesystem::path p = MessageHandlerInternal::get_path(message.substr(last_space + 1)); | ||||
| 		if (!p.string().empty()) | ||||
| 			paths.emplace_back(p); | ||||
| 	} | ||||
| 	if (!paths.empty()) { | ||||
| 		//wxEvtHandler* evt_handler = wxGetApp().plater(); //assert here?
 | ||||
| 		//if (evt_handler) {
 | ||||
| 			wxPostEvent(m_callback_evt_handler, LoadFromOtherInstanceEvent(GUI::EVT_LOAD_MODEL_OTHER_INSTANCE, std::vector<boost::filesystem::path>(std::move(paths)))); | ||||
| 		//}
 | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| #ifdef BACKGROUND_MESSAGE_LISTENER | ||||
| 
 | ||||
| namespace MessageHandlerDBusInternal | ||||
| { | ||||
| 	//reply to introspect makes our DBus object visible for other programs like D-Feet
 | ||||
| 	static void respond_to_introspect(DBusConnection *connection, DBusMessage *request)  | ||||
| 	{ | ||||
|     	DBusMessage *reply; | ||||
| 	    const char  *introspection_data = | ||||
| 	        " <!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\" " | ||||
| 	        "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">" | ||||
| 	        " <!-- dbus-sharp 0.8.1 -->" | ||||
| 	        " <node>" | ||||
| 	        "   <interface name=\"org.freedesktop.DBus.Introspectable\">" | ||||
| 	        "     <method name=\"Introspect\">" | ||||
| 	        "       <arg name=\"data\" direction=\"out\" type=\"s\" />" | ||||
| 	        "     </method>" | ||||
| 	        "   </interface>" | ||||
| 	        "   <interface name=\"com.prusa3d.prusaslicer.InstanceCheck\">" | ||||
| 	        "     <method name=\"AnotherInstace\">" | ||||
| 	        "       <arg name=\"data\" direction=\"in\" type=\"s\" />" | ||||
| 	        "     </method>" | ||||
| 	        "   </interface>" | ||||
| 	        " </node>"; | ||||
| 	      | ||||
| 	    reply = dbus_message_new_method_return(request); | ||||
| 	    dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection_data, DBUS_TYPE_INVALID); | ||||
| 	    dbus_connection_send(connection, reply, NULL); | ||||
| 	    dbus_message_unref(reply); | ||||
| 	} | ||||
| 	//method AnotherInstance receives message from another PrusaSlicer instance 
 | ||||
| 	static void handle_method_another_instance(DBusConnection *connection, DBusMessage *request) | ||||
| 	{ | ||||
| 	    DBusError     err; | ||||
| 	    char*         text= ""; | ||||
| 		wxEvtHandler* evt_handler; | ||||
| 
 | ||||
| 	    dbus_error_init(&err); | ||||
| 	    dbus_message_get_args(request, &err, DBUS_TYPE_STRING, &text, DBUS_TYPE_INVALID); | ||||
| 	    if (dbus_error_is_set(&err)) { | ||||
| 	    	BOOST_LOG_TRIVIAL(trace) << "Dbus method AnotherInstance received with wrong arguments."; | ||||
| 	    	dbus_error_free(&err); | ||||
| 	        return; | ||||
| 	    } | ||||
| 	    wxGetApp().other_instance_message_handler()->handle_message(text); | ||||
| 
 | ||||
| 		evt_handler = wxGetApp().plater(); | ||||
| 		if (evt_handler) { | ||||
| 			wxPostEvent(evt_handler, InstanceGoToFrontEvent(EVT_INSTANCE_GO_TO_FRONT)); | ||||
| 		} | ||||
| 	} | ||||
| 	//every dbus message received comes here
 | ||||
| 	static DBusHandlerResult handle_dbus_object_message(DBusConnection *connection, DBusMessage *message, void *user_data) | ||||
| 	{ | ||||
| 		const char* interface_name = dbus_message_get_interface(message); | ||||
| 	    const char* member_name    = dbus_message_get_member(message); | ||||
| 
 | ||||
| 	    BOOST_LOG_TRIVIAL(trace) << "DBus message received: interface: " << interface_name << ", member: " << member_name; | ||||
| 
 | ||||
| 	    if (0 == strcmp("org.freedesktop.DBus.Introspectable", interface_name) && 0 == strcmp("Introspect", member_name)) {		 | ||||
| 	        respond_to_introspect(connection, message); | ||||
| 	        return DBUS_HANDLER_RESULT_HANDLED; | ||||
| 	    } else if (0 == strcmp("com.prusa3d.prusaslicer.InstanceCheck", interface_name) && 0 == strcmp("AnotherInstace", member_name)) { | ||||
| 	        handle_method_another_instance(connection, message); | ||||
| 	        return DBUS_HANDLER_RESULT_HANDLED; | ||||
| 	    }  | ||||
| 	    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; | ||||
| 	} | ||||
| } //namespace MessageHandlerDBusInternal
 | ||||
| 
 | ||||
| void OtherInstanceMessageHandler::listen() | ||||
| { | ||||
|     DBusConnection* 	 conn; | ||||
|     DBusError 			 err; | ||||
|     int 				 name_req_val; | ||||
|     DBusObjectPathVTable vtable; | ||||
| 	std::string			 interface_name = "com.prusa3d.prusaslicer.InstanceCheck"; | ||||
|     std::string			 object_name 	= "/com/prusa3d/prusaslicer/InstanceCheck"; | ||||
| 
 | ||||
|     dbus_error_init(&err); | ||||
| 
 | ||||
|     // connect to the bus and check for errors (use SESSION bus everywhere!)
 | ||||
|     conn = dbus_bus_get(DBUS_BUS_SESSION, &err); | ||||
|     if (dbus_error_is_set(&err)) {  | ||||
| 	    BOOST_LOG_TRIVIAL(error) << "DBus Connection Error: "<< err.message; | ||||
| 	    BOOST_LOG_TRIVIAL(error) << "Dbus Messages listening terminating."; | ||||
|         dbus_error_free(&err);  | ||||
|         return; | ||||
|     } | ||||
|     if (NULL == conn) {  | ||||
| 		BOOST_LOG_TRIVIAL(error) << "DBus Connection is NULL. Dbus Messages listening terminating."; | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
| 	// request our name on the bus and check for errors
 | ||||
| 	name_req_val = dbus_bus_request_name(conn, interface_name.c_str(), DBUS_NAME_FLAG_REPLACE_EXISTING , &err); | ||||
| 	if (dbus_error_is_set(&err)) { | ||||
| 	    BOOST_LOG_TRIVIAL(error) << "DBus Request name Error: "<< err.message;  | ||||
| 	    BOOST_LOG_TRIVIAL(error) << "Dbus Messages listening terminating."; | ||||
| 	    dbus_error_free(&err);  | ||||
| 	    dbus_connection_unref(conn); | ||||
| 	    return; | ||||
| 	} | ||||
| 	if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != name_req_val) { | ||||
| 		BOOST_LOG_TRIVIAL(error) << "Not primary owner of DBus name - probably another PrusaSlicer instance is running."; | ||||
| 	    BOOST_LOG_TRIVIAL(error) << "Dbus Messages listening terminating."; | ||||
| 	    dbus_connection_unref(conn); | ||||
| 	    return; | ||||
| 	} | ||||
| 
 | ||||
| 	// Set callbacks. Unregister function should not be nessary.
 | ||||
| 	vtable.message_function = MessageHandlerDBusInternal::handle_dbus_object_message; | ||||
|     vtable.unregister_function = NULL; | ||||
| 
 | ||||
|     // register new object - this is our access to DBus
 | ||||
|     dbus_connection_try_register_object_path(conn, object_name.c_str(), &vtable, NULL, &err); | ||||
|    	if ( dbus_error_is_set(&err) ) { | ||||
|    		BOOST_LOG_TRIVIAL(error) << "DBus Register object Error: "<< err.message;  | ||||
| 	    BOOST_LOG_TRIVIAL(error) << "Dbus Messages listening terminating."; | ||||
| 	    dbus_connection_unref(conn); | ||||
| 		dbus_error_free(&err); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	BOOST_LOG_TRIVIAL(trace) << "Dbus object registered. Starting listening for messages."; | ||||
| 
 | ||||
| 	for (;;) { | ||||
| 		// Wait for 1 second 
 | ||||
| 		// Cancellable.
 | ||||
| 		{ | ||||
| 			std::unique_lock<std::mutex> lck(m_thread_stop_mutex); | ||||
| 			m_thread_stop_condition.wait_for(lck, std::chrono::seconds(1), [this] { return m_stop; }); | ||||
| 		} | ||||
| 		if (m_stop) | ||||
| 			// Stop the worker thread.
 | ||||
| 
 | ||||
| 			break; | ||||
| 		//dispatch should do all the work with incoming messages
 | ||||
| 		//second parameter is blocking time that funciton waits for new messages
 | ||||
| 		//that is handled here with our own event loop above
 | ||||
| 		dbus_connection_read_write_dispatch(conn, 0); | ||||
|      } | ||||
|       | ||||
|    	 dbus_connection_unref(conn); | ||||
| } | ||||
| #endif //BACKGROUND_MESSAGE_LISTENER
 | ||||
| } // namespace GUI
 | ||||
| } // namespace Slic3r
 | ||||
							
								
								
									
										91
									
								
								src/slic3r/GUI/InstanceCheck.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								src/slic3r/GUI/InstanceCheck.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,91 @@ | |||
| #ifndef slic3r_InstanceCheck_hpp_ | ||||
| #define slic3r_InstanceCheck_hpp_ | ||||
| 
 | ||||
| #include "Event.hpp" | ||||
| 
 | ||||
| #if _WIN32 | ||||
| #include <windows.h> | ||||
| #endif //_WIN32
 | ||||
| 
 | ||||
| #include <string> | ||||
| 
 | ||||
| #include <boost/filesystem.hpp> | ||||
| 
 | ||||
| #include <boost/thread.hpp> | ||||
| #include <tbb/mutex.h> | ||||
| #include <condition_variable> | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| namespace Slic3r { | ||||
| // checks for other running instances and sends them argv,
 | ||||
| // if there is --single-instance argument or AppConfig is set to single_instance=1
 | ||||
| // returns true if this instance should terminate
 | ||||
| bool    instance_check(int argc, char** argv, bool app_config_single_instance); | ||||
| 
 | ||||
| #if __APPLE__ | ||||
| // apple implementation of inner functions of instance_check
 | ||||
| // in InstanceCheckMac.mm
 | ||||
| void    send_message_mac(const std::string msg); | ||||
| #endif //__APPLE__
 | ||||
| 
 | ||||
| namespace GUI { | ||||
| 
 | ||||
| #if __linux__ | ||||
|     #define BACKGROUND_MESSAGE_LISTENER | ||||
| #endif // __linux__
 | ||||
| 
 | ||||
| using LoadFromOtherInstanceEvent = Event<std::vector<boost::filesystem::path>>; | ||||
| wxDECLARE_EVENT(EVT_LOAD_MODEL_OTHER_INSTANCE, LoadFromOtherInstanceEvent); | ||||
| 
 | ||||
| using InstanceGoToFrontEvent = SimpleEvent; | ||||
| wxDECLARE_EVENT(EVT_INSTANCE_GO_TO_FRONT, InstanceGoToFrontEvent); | ||||
| 
 | ||||
| class OtherInstanceMessageHandler | ||||
| { | ||||
| public: | ||||
| 	OtherInstanceMessageHandler() = default; | ||||
| 	OtherInstanceMessageHandler(OtherInstanceMessageHandler const&) = delete; | ||||
| 	void operator=(OtherInstanceMessageHandler const&) = delete; | ||||
| 	~OtherInstanceMessageHandler() { assert(!m_initialized); } | ||||
| 
 | ||||
| 	// inits listening, on each platform different. On linux starts background thread
 | ||||
| 	void    init(wxEvtHandler* callback_evt_handler); | ||||
| 	// stops listening, on linux stops the background thread
 | ||||
| 	void    shutdown(); | ||||
| 
 | ||||
| 	//finds paths to models in message(= command line arguments, first should be prusaSlicer executable)
 | ||||
| 	//and sends them to plater via LoadFromOtherInstanceEvent
 | ||||
| 	//security of messages: from message all existing paths are proccesed to load model 
 | ||||
| 	//						win32 - anybody who has hwnd can send message.
 | ||||
| 	//						mac - anybody who posts notification with name:@"OtherPrusaSlicerTerminating"
 | ||||
| 	//						linux - instrospectable on dbus
 | ||||
| 	void    handle_message(const std::string message); | ||||
| private: | ||||
| 	bool                    m_initialized { false }; | ||||
| 	wxEvtHandler*           m_callback_evt_handler { nullptr }; | ||||
| 
 | ||||
| #ifdef BACKGROUND_MESSAGE_LISTENER | ||||
| 	//worker thread to listen incoming dbus communication
 | ||||
| 	boost::thread 			m_thread; | ||||
| 	std::condition_variable m_thread_stop_condition; | ||||
| 	mutable std::mutex 		m_thread_stop_mutex; | ||||
| 	bool 					m_stop{ false }; | ||||
| 	bool					m_start{ true }; | ||||
| 	 | ||||
| 	// background thread method
 | ||||
| 	void    listen(); | ||||
| #endif //BACKGROUND_MESSAGE_LISTENER
 | ||||
| 
 | ||||
| #if __APPLE__ | ||||
| 	//implemented at InstanceCheckMac.mm
 | ||||
| 	void    register_for_messages(); | ||||
| 	void    unregister_for_messages(); | ||||
| 	// Opaque pointer to RemovableDriveManagerMM
 | ||||
| 	void* m_impl_osx; | ||||
| #endif //__APPLE__
 | ||||
| 
 | ||||
| }; | ||||
| } // namespace GUI
 | ||||
| } // namespace Slic3r
 | ||||
| #endif // slic3r_InstanceCheck_hpp_
 | ||||
							
								
								
									
										8
									
								
								src/slic3r/GUI/InstanceCheckMac.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/slic3r/GUI/InstanceCheckMac.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,8 @@ | |||
| #import <Cocoa/Cocoa.h> | ||||
| 
 | ||||
| @interface OtherInstanceMessageHandlerMac : NSObject | ||||
| 
 | ||||
| -(instancetype) init; | ||||
| -(void) add_observer; | ||||
| -(void) message_update:(NSNotification *)note; | ||||
| @end | ||||
							
								
								
									
										68
									
								
								src/slic3r/GUI/InstanceCheckMac.mm
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								src/slic3r/GUI/InstanceCheckMac.mm
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,68 @@ | |||
| #import "InstanceCheck.hpp" | ||||
| #import "InstanceCheckMac.h" | ||||
| #import "GUI_App.hpp" | ||||
| 
 | ||||
| @implementation OtherInstanceMessageHandlerMac | ||||
| 
 | ||||
| -(instancetype) init | ||||
| { | ||||
| 	self = [super init]; | ||||
| 	return self; | ||||
| } | ||||
| -(void)add_observer | ||||
| { | ||||
| 	NSLog(@"adding observer"); | ||||
| 	[[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(message_update:) name:@"OtherPrusaSlicerInstanceMessage" object:nil suspensionBehavior:NSNotificationSuspensionBehaviorDeliverImmediately]; | ||||
| } | ||||
| 
 | ||||
| -(void)message_update:(NSNotification *)msg | ||||
| { | ||||
| 	//NSLog(@"recieved msg %@", msg);	 | ||||
| 	//demiaturize all windows | ||||
| 	for(NSWindow* win in [NSApp windows]) | ||||
| 	{ | ||||
| 		if([win isMiniaturized]) | ||||
| 		{ | ||||
| 			[win deminiaturize:self]; | ||||
| 		} | ||||
| 	} | ||||
| 	//bring window to front  | ||||
| 	[[NSApplication sharedApplication] activateIgnoringOtherApps : YES]; | ||||
| 	//pass message   | ||||
| 	Slic3r::GUI::wxGetApp().other_instance_message_handler()->handle_message(std::string([msg.userInfo[@"data"] UTF8String])); | ||||
| } | ||||
| 
 | ||||
| @end | ||||
| 
 | ||||
| namespace Slic3r { | ||||
| 
 | ||||
| void send_message_mac(const std::string msg) | ||||
| { | ||||
| 	NSString *nsmsg = [NSString stringWithCString:msg.c_str() encoding:[NSString defaultCStringEncoding]]; | ||||
| 	//NSLog(@"sending msg %@", nsmsg); | ||||
| 	[[NSDistributedNotificationCenter defaultCenter] postNotificationName:@"OtherPrusaSlicerInstanceMessage" object:nil userInfo:[NSDictionary dictionaryWithObject:nsmsg forKey:@"data"] deliverImmediately:YES]; | ||||
| } | ||||
| 
 | ||||
| namespace GUI { | ||||
| void OtherInstanceMessageHandler::register_for_messages() | ||||
| { | ||||
| 	m_impl_osx = [[OtherInstanceMessageHandlerMac alloc] init]; | ||||
| 	if(m_impl_osx) { | ||||
| 		[m_impl_osx add_observer]; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void OtherInstanceMessageHandler::unregister_for_messages() | ||||
| { | ||||
| 	//NSLog(@"unreegistering other instance messages"); | ||||
| 	if (m_impl_osx) { | ||||
|         [m_impl_osx release]; | ||||
|         m_impl_osx = nullptr; | ||||
|     } else { | ||||
| 		NSLog(@"unreegister not required"); | ||||
| 	} | ||||
| } | ||||
| }//namespace GUI | ||||
| }//namespace Slicer | ||||
| 
 | ||||
| 
 | ||||
|  | @ -134,6 +134,7 @@ void KBShortcutsDialog::fill_shortcuts() | |||
|         { ctrl + "C", L("Copy to clipboard") }, | ||||
|         { ctrl + "V", L("Paste from clipboard") }, | ||||
|         { "F5", L("Reload plater from disk") }, | ||||
|         { ctrl + "F", L("Search") }, | ||||
|         // Window
 | ||||
|         { ctrl + "1", L("Select Plater Tab") }, | ||||
|         { ctrl + "2", L("Select Print Settings Tab") }, | ||||
|  |  | |||
|  | @ -26,6 +26,7 @@ | |||
| #include "GUI_ObjectList.hpp" | ||||
| #include "Mouse3DController.hpp" | ||||
| #include "RemovableDriveManager.hpp" | ||||
| #include "InstanceCheck.hpp" | ||||
| #include "I18N.hpp" | ||||
| 
 | ||||
| #include <fstream> | ||||
|  | @ -89,6 +90,8 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_S | |||
| 
 | ||||
|     // initialize layout
 | ||||
|     auto sizer = new wxBoxSizer(wxVERTICAL); | ||||
|     if (m_plater) | ||||
|         sizer->Add(m_plater, 1, wxEXPAND); | ||||
|     if (m_tabpanel) | ||||
|         sizer->Add(m_tabpanel, 1, wxEXPAND); | ||||
|     sizer->SetSizeHints(this); | ||||
|  | @ -234,7 +237,8 @@ void MainFrame::shutdown() | |||
| 
 | ||||
|     // Stop the background thread of the removable drive manager, so that no new updates will be sent to the Plater.
 | ||||
|     wxGetApp().removable_drive_manager()->shutdown(); | ||||
| 
 | ||||
| 	//stop listening for messages from other instances
 | ||||
| 	wxGetApp().other_instance_message_handler()->shutdown(); | ||||
|     // Save the slic3r.ini.Usually the ini file is saved from "on idle" callback,
 | ||||
|     // but in rare cases it may not have been called yet.
 | ||||
|     wxGetApp().app_config->save(); | ||||
|  | @ -304,11 +308,16 @@ void MainFrame::init_tabpanel() | |||
|             // before the MainFrame is fully set up.
 | ||||
|             static_cast<Tab*>(panel)->OnActivate(); | ||||
|         } | ||||
|         else | ||||
|             select_tab(0); | ||||
|     }); | ||||
| 
 | ||||
|     m_plater = new Slic3r::GUI::Plater(m_tabpanel, this); | ||||
| //!    m_plater = new Slic3r::GUI::Plater(m_tabpanel, this);
 | ||||
|     m_plater = new Plater(this, this); | ||||
| 
 | ||||
|     wxGetApp().plater_ = m_plater; | ||||
|     m_tabpanel->AddPage(m_plater, _(L("Plater"))); | ||||
| //    m_tabpanel->AddPage(m_plater, _(L("Plater")));
 | ||||
|     m_tabpanel->AddPage(new wxPanel(m_tabpanel), _L("Plater")); // empty panel just for Plater tab
 | ||||
| 
 | ||||
|     wxGetApp().obj_list()->create_popup_menus(); | ||||
| 
 | ||||
|  | @ -334,6 +343,13 @@ void MainFrame::init_tabpanel() | |||
|     } | ||||
| } | ||||
| 
 | ||||
| void MainFrame::switch_to(bool plater) | ||||
| { | ||||
|     this->m_plater->Show(plater); | ||||
|     this->m_tabpanel->Show(!plater); | ||||
|     this->Layout(); | ||||
| } | ||||
| 
 | ||||
| void MainFrame::create_preset_tabs() | ||||
| { | ||||
|     wxGetApp().update_label_colours_from_appconfig(); | ||||
|  | @ -741,31 +757,37 @@ void MainFrame::init_menubar() | |||
|         append_menu_item(editMenu, wxID_ANY, _(L("Re&load from disk")) + sep + "F5", | ||||
|             _(L("Reload the plater from disk")), [this](wxCommandEvent&) { m_plater->reload_all_from_disk(); }, | ||||
|             "", nullptr, [this]() {return !m_plater->model().objects.empty(); }, this); | ||||
| 
 | ||||
|         editMenu->AppendSeparator(); | ||||
|         append_menu_item(editMenu, wxID_ANY, _(L("Searc&h")) + "\tCtrl+F", | ||||
|             _(L("Find option")), [this](wxCommandEvent&) { m_plater->search(/*m_tabpanel->GetCurrentPage() == */m_plater->IsShown()); }, | ||||
|             "search", nullptr, [this]() {return true; }, this); | ||||
|     } | ||||
| 
 | ||||
|     // Window menu
 | ||||
|     auto windowMenu = new wxMenu(); | ||||
|     { | ||||
|         size_t tab_offset = 0; | ||||
| //!        size_t tab_offset = 0;
 | ||||
|         if (m_plater) { | ||||
|             append_menu_item(windowMenu, wxID_HIGHEST + 1, _(L("&Plater Tab")) + "\tCtrl+1", _(L("Show the plater")), | ||||
|                 [this](wxCommandEvent&) { select_tab(0); }, "plater", nullptr, | ||||
|                 [this/*, tab_offset*/](wxCommandEvent&) { select_tab(/*(size_t)(-1)*/0); }, "plater", nullptr, | ||||
|                 [this]() {return true; }, this); | ||||
|             tab_offset += 1; | ||||
|         } | ||||
|         if (tab_offset > 0) { | ||||
| //!            tab_offset += 1;
 | ||||
| //!        }
 | ||||
| //!        if (tab_offset > 0) {
 | ||||
|             windowMenu->AppendSeparator(); | ||||
|         } | ||||
|         append_menu_item(windowMenu, wxID_HIGHEST + 2, _(L("P&rint Settings Tab")) + "\tCtrl+2", _(L("Show the print settings")), | ||||
|             [this, tab_offset](wxCommandEvent&) { select_tab(tab_offset + 0); }, "cog", nullptr, | ||||
|             [this/*, tab_offset*/](wxCommandEvent&) { select_tab(/*tab_offset + 0*/1); }, "cog", nullptr, | ||||
|             [this]() {return true; }, this); | ||||
|         wxMenuItem* item_material_tab = append_menu_item(windowMenu, wxID_HIGHEST + 3, _(L("&Filament Settings Tab")) + "\tCtrl+3", _(L("Show the filament settings")), | ||||
|             [this, tab_offset](wxCommandEvent&) { select_tab(tab_offset + 1); }, "spool", nullptr, | ||||
|             [this/*, tab_offset*/](wxCommandEvent&) { select_tab(/*tab_offset + 1*/2); }, "spool", nullptr, | ||||
|             [this]() {return true; }, this); | ||||
|         m_changeable_menu_items.push_back(item_material_tab); | ||||
|         append_menu_item(windowMenu, wxID_HIGHEST + 4, _(L("Print&er Settings Tab")) + "\tCtrl+4", _(L("Show the printer settings")), | ||||
|             [this, tab_offset](wxCommandEvent&) { select_tab(tab_offset + 2); }, "printer", nullptr, | ||||
|         wxMenuItem* item_printer_tab = append_menu_item(windowMenu, wxID_HIGHEST + 4, _(L("Print&er Settings Tab")) + "\tCtrl+4", _(L("Show the printer settings")), | ||||
|             [this/*, tab_offset*/](wxCommandEvent&) { select_tab(/*tab_offset + 2*/3); }, "printer", nullptr, | ||||
|             [this]() {return true; }, this); | ||||
|         m_changeable_menu_items.push_back(item_printer_tab); | ||||
|         if (m_plater) { | ||||
|             windowMenu->AppendSeparator(); | ||||
|             append_menu_item(windowMenu, wxID_HIGHEST + 5, _(L("3&D")) + "\tCtrl+5", _(L("Show the 3D editing view")), | ||||
|  | @ -832,6 +854,9 @@ void MainFrame::init_menubar() | |||
|             [this](wxCommandEvent&) { m_plater->show_view3D_labels(!m_plater->are_view3D_labels_shown()); }, this, | ||||
|             [this]() { return m_plater->is_view3D_shown(); }, [this]() { return m_plater->are_view3D_labels_shown(); }, this); | ||||
| #endif // ENABLE_SLOPE_RENDERING
 | ||||
|         append_menu_check_item(viewMenu, wxID_ANY, _(L("&Collapse sidebar")), _(L("Collapse sidebar")), | ||||
|             [this](wxCommandEvent&) { m_plater->collapse_sidebar(!m_plater->is_sidebar_collapsed()); }, this, | ||||
|             [this]() { return true; }, [this]() { return m_plater->is_sidebar_collapsed(); }, this); | ||||
|     } | ||||
| 
 | ||||
|     // Help menu
 | ||||
|  | @ -906,7 +931,9 @@ void MainFrame::update_menubar() | |||
|     m_changeable_menu_items[miSend]         ->SetItemLabel((is_fff ? _(L("S&end G-code"))           : _(L("S&end to print"))) + dots    + "\tCtrl+Shift+G"); | ||||
| 
 | ||||
|     m_changeable_menu_items[miMaterialTab]  ->SetItemLabel((is_fff ? _(L("&Filament Settings Tab")) : _(L("Mate&rial Settings Tab")))   + "\tCtrl+3"); | ||||
|     m_changeable_menu_items[miMaterialTab]  ->SetBitmap(create_scaled_bitmap(is_fff ? "spool": "resin")); | ||||
|     m_changeable_menu_items[miMaterialTab]  ->SetBitmap(create_scaled_bitmap(is_fff ? "spool"   : "resin")); | ||||
| 
 | ||||
|     m_changeable_menu_items[miPrinterTab]   ->SetBitmap(create_scaled_bitmap(is_fff ? "printer" : "sla_printer")); | ||||
| } | ||||
| 
 | ||||
| // To perform the "Quck Slice", "Quick Slice and Save As", "Repeat last Quick Slice" and "Slice to SVG".
 | ||||
|  | @ -1222,9 +1249,17 @@ void MainFrame::load_config(const DynamicPrintConfig& config) | |||
| #endif | ||||
| } | ||||
| 
 | ||||
| void MainFrame::select_tab(size_t tab) const | ||||
| void MainFrame::select_tab(size_t tab) | ||||
| { | ||||
|     m_tabpanel->SetSelection(tab); | ||||
|     if (tab == /*(size_t)(-1)*/0) { | ||||
|         if (m_plater && !m_plater->IsShown()) | ||||
|             this->switch_to(true); | ||||
|     } | ||||
|     else { | ||||
|         if (m_plater && m_plater->IsShown()) | ||||
|             switch_to(false); | ||||
|         m_tabpanel->SetSelection(tab); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // Set a camera direction, zoom to all objects.
 | ||||
|  |  | |||
|  | @ -86,6 +86,7 @@ class MainFrame : public DPIFrame | |||
|         miExport = 0,   // Export G-code        Export
 | ||||
|         miSend,         // Send G-code          Send to print
 | ||||
|         miMaterialTab,  // Filament Settings    Material Settings
 | ||||
|         miPrinterTab,   // Different bitmap for Printer Settings
 | ||||
|     }; | ||||
| 
 | ||||
|     // vector of a MenuBar items changeable in respect to printer technology 
 | ||||
|  | @ -108,6 +109,7 @@ public: | |||
|     void        update_title(); | ||||
| 
 | ||||
|     void        init_tabpanel(); | ||||
|     void        switch_to(bool plater); | ||||
|     void        create_preset_tabs(); | ||||
|     void        add_created_tab(Tab* panel); | ||||
|     void        init_menubar(); | ||||
|  | @ -128,7 +130,7 @@ public: | |||
|     void        export_configbundle(); | ||||
|     void        load_configbundle(wxString file = wxEmptyString); | ||||
|     void        load_config(const DynamicPrintConfig& config); | ||||
|     void        select_tab(size_t tab) const; | ||||
|     void        select_tab(size_t tab); | ||||
|     void        select_view(const std::string& direction); | ||||
|     // Propagate changed configuration from the Tab to the Plater and save changes to the AppConfig
 | ||||
|     void        on_config_changed(DynamicPrintConfig* cfg) const ; | ||||
|  |  | |||
|  | @ -108,6 +108,7 @@ void OptionsGroup::add_undo_buttuns_to_sizer(wxSizer* sizer, const t_field& fiel | |||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
|     sizer->Add(field->m_blinking_bmp, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, 2); | ||||
| 	sizer->Add(field->m_Undo_to_sys_btn, 0, wxALIGN_CENTER_VERTICAL); | ||||
| 	sizer->Add(field->m_Undo_btn, 0, wxALIGN_CENTER_VERTICAL); | ||||
| } | ||||
|  | @ -378,6 +379,9 @@ Option ConfigOptionsGroup::get_option(const std::string& opt_key, int opt_index | |||
| 	std::pair<std::string, int> pair(opt_key, opt_index); | ||||
| 	m_opt_map.emplace(opt_id, pair); | ||||
| 
 | ||||
| 	if (m_show_modified_btns) // fill group and category values just fro options from Settings Tab 
 | ||||
| 	    wxGetApp().sidebar().get_searcher().add_key(opt_id, title, config_category); | ||||
| 
 | ||||
| 	return Option(*m_config->def()->get(opt_key), opt_id); | ||||
| } | ||||
| 
 | ||||
|  | @ -680,6 +684,9 @@ boost::any ConfigOptionsGroup::get_config_value(const DynamicPrintConfig& config | |||
| 			opt_key == "fill_pattern" ) { | ||||
| 			ret = static_cast<int>(config.option<ConfigOptionEnum<InfillPattern>>(opt_key)->value); | ||||
| 		} | ||||
| 		else if (opt_key.compare("ironing_type") == 0 ) { | ||||
| 			ret = static_cast<int>(config.option<ConfigOptionEnum<IroningType>>(opt_key)->value); | ||||
| 		} | ||||
| 		else if (opt_key.compare("gcode_flavor") == 0 ) { | ||||
| 			ret = static_cast<int>(config.option<ConfigOptionEnum<GCodeFlavor>>(opt_key)->value); | ||||
| 		} | ||||
|  |  | |||
|  | @ -12,6 +12,7 @@ | |||
| 
 | ||||
| #include "Field.hpp" | ||||
| #include "GUI_App.hpp" | ||||
| #include "I18N.hpp" | ||||
| 
 | ||||
| // Translate the ifdef 
 | ||||
| #ifdef __WXOSX__ | ||||
|  | @ -59,7 +60,7 @@ public: | |||
| 		m_extra_widgets.push_back(widget); | ||||
|     } | ||||
| 	Line(wxString label, wxString tooltip) : | ||||
| 		label(label), label_tooltip(tooltip) {} | ||||
| 		label(_(label)), label_tooltip(_(tooltip)) {} | ||||
| 
 | ||||
|     const std::vector<widget_t>&	get_extra_widgets() const {return m_extra_widgets;} | ||||
|     const std::vector<Option>&		get_options() const { return m_options; } | ||||
|  | @ -78,7 +79,7 @@ class OptionsGroup { | |||
| 	wxStaticBox*	stb; | ||||
| public: | ||||
|     const bool		staticbox {true}; | ||||
|     const wxString	title {wxString("")}; | ||||
|     const wxString	title; | ||||
|     size_t			label_width = 20 ;// {200};
 | ||||
|     wxSizer*		sizer {nullptr}; | ||||
|     column_t		extra_column {nullptr}; | ||||
|  | @ -175,7 +176,7 @@ public: | |||
|                     m_show_modified_btns(is_tab_opt), | ||||
| 					staticbox(title!=""), extra_column(extra_clmn) { | ||||
|         if (staticbox) { | ||||
|             stb = new wxStaticBox(_parent, wxID_ANY, title); | ||||
|             stb = new wxStaticBox(_parent, wxID_ANY, _(title)); | ||||
|             if (!wxOSX) stb->SetBackgroundStyle(wxBG_STYLE_PAINT); | ||||
|             stb->SetFont(wxGetApp().bold_font()); | ||||
|         } else | ||||
|  | @ -194,6 +195,7 @@ public: | |||
| #else | ||||
|         sizer->Add(m_grid_sizer, 0, wxEXPAND | wxALL, wxOSX||!staticbox ? 0: 5); | ||||
| #endif /* __WXGTK__ */ | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     wxGridSizer*        get_grid_sizer() { return m_grid_sizer; } | ||||
|  | @ -247,6 +249,8 @@ public: | |||
|     bool					m_full_labels {0}; | ||||
| 	t_opt_map				m_opt_map; | ||||
| 
 | ||||
|     std::string             config_category; | ||||
| 
 | ||||
|     void        set_config(DynamicPrintConfig* config) { m_config = config; } | ||||
| 	Option		get_option(const std::string& opt_key, int opt_index = -1); | ||||
| 	Line		create_single_option_line(const std::string& title, int idx = -1) /*const*/{ | ||||
|  |  | |||
|  | @ -74,6 +74,8 @@ | |||
| #include "../Utils/FixModelByWin10.hpp" | ||||
| #include "../Utils/UndoRedo.hpp" | ||||
| #include "RemovableDriveManager.hpp" | ||||
| #include "InstanceCheck.hpp" | ||||
| 
 | ||||
| #if ENABLE_NON_STATIC_CANVAS_MANAGER | ||||
| #ifdef __APPLE__ | ||||
| #include "Gizmos/GLGizmosManager.hpp" | ||||
|  | @ -355,6 +357,9 @@ PresetBitmapComboBox(parent, wxSize(15 * wxGetApp().em_unit(), -1)), | |||
| 
 | ||||
|         wxGetApp().tab_panel()->ChangeSelection(page_id); | ||||
| 
 | ||||
|         // Switch to Settings NotePad
 | ||||
|         wxGetApp().mainframe->switch_to(false); | ||||
| 
 | ||||
|         /* In a case of a multi-material printing, for editing another Filament Preset
 | ||||
|          * it's needed to select this preset for the "Filament settings" Tab | ||||
|          */ | ||||
|  | @ -714,6 +719,9 @@ struct Sidebar::priv | |||
|     ScalableButton *btn_remove_device; | ||||
| 	ScalableButton* btn_export_gcode_removable; //exports to removable drives (appears only if removable drive is connected)
 | ||||
| 
 | ||||
|     bool                is_collapsed {false}; | ||||
|     Search::OptionsSearcher     searcher; | ||||
| 
 | ||||
|     priv(Plater *plater) : plater(plater) {} | ||||
|     ~priv(); | ||||
| 
 | ||||
|  | @ -762,6 +770,8 @@ Sidebar::Sidebar(Plater *parent) | |||
|     p->scrolled = new wxScrolledWindow(this); | ||||
|     p->scrolled->SetScrollbars(0, 100, 1, 2); | ||||
| 
 | ||||
|     SetFont(wxGetApp().normal_font()); | ||||
|     SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); | ||||
| 
 | ||||
|     // Sizer in the scrolled area
 | ||||
|     auto *scrolled_sizer = new wxBoxSizer(wxVERTICAL); | ||||
|  | @ -1080,6 +1090,21 @@ void Sidebar::msw_rescale() | |||
|     p->scrolled->Layout(); | ||||
| } | ||||
| 
 | ||||
| void Sidebar::search() | ||||
| { | ||||
|     p->searcher.search(); | ||||
| } | ||||
| 
 | ||||
| void Sidebar::jump_to_option(size_t selected) | ||||
| { | ||||
|     const Search::Option& opt = p->searcher.get_option(selected); | ||||
|     wxGetApp().get_tab(opt.type)->activate_option(opt.opt_key, opt.category); | ||||
| 
 | ||||
|     // Switch to the Settings NotePad, if plater is shown
 | ||||
|     if (p->plater->IsShown()) | ||||
|         wxGetApp().mainframe->switch_to(false); | ||||
| } | ||||
| 
 | ||||
| ObjectManipulation* Sidebar::obj_manipul() | ||||
| { | ||||
|     return p->object_manipulation; | ||||
|  | @ -1346,6 +1371,23 @@ bool Sidebar::is_multifilament() | |||
|     return p->combos_filament.size() > 1; | ||||
| } | ||||
| 
 | ||||
| static std::vector<Search::InputInfo> get_search_inputs(ConfigOptionMode mode) | ||||
| { | ||||
|     std::vector<Search::InputInfo> ret {}; | ||||
| 
 | ||||
|     auto& tabs_list = wxGetApp().tabs_list; | ||||
|     auto print_tech = wxGetApp().preset_bundle->printers.get_selected_preset().printer_technology(); | ||||
|     for (auto tab : tabs_list) | ||||
|         if (tab->supports_printer_technology(print_tech)) | ||||
|             ret.emplace_back(Search::InputInfo {tab->get_config(), tab->type(), mode}); | ||||
| 
 | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| void Sidebar::update_searcher() | ||||
| { | ||||
|     p->searcher.init(get_search_inputs(m_mode)); | ||||
| } | ||||
| 
 | ||||
| void Sidebar::update_mode() | ||||
| { | ||||
|  | @ -1353,6 +1395,7 @@ void Sidebar::update_mode() | |||
| 
 | ||||
|     update_reslice_btn_tooltip(); | ||||
|     update_mode_sizer(); | ||||
|     update_searcher(); | ||||
| 
 | ||||
|     wxWindowUpdateLocker noUpdates(this); | ||||
| 
 | ||||
|  | @ -1365,6 +1408,20 @@ void Sidebar::update_mode() | |||
|     Layout(); | ||||
| } | ||||
| 
 | ||||
| bool Sidebar::is_collapsed() { return p->is_collapsed; } | ||||
| 
 | ||||
| void Sidebar::collapse(bool collapse) | ||||
| { | ||||
|     p->is_collapsed = collapse; | ||||
| 
 | ||||
|     this->Show(!collapse); | ||||
|     p->plater->Layout(); | ||||
| 
 | ||||
|     // save collapsing state to the AppConfig
 | ||||
|     wxGetApp().app_config->set("collapsed_sidebar", collapse ? "1" : "0"); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void Sidebar::update_ui_from_settings() | ||||
| { | ||||
|     p->object_manipulation->update_ui_from_settings(); | ||||
|  | @ -1377,6 +1434,16 @@ std::vector<PresetComboBox*>& Sidebar::combos_filament() | |||
|     return p->combos_filament; | ||||
| } | ||||
| 
 | ||||
| Search::OptionsSearcher& Sidebar::get_searcher() | ||||
| { | ||||
|     return p->searcher; | ||||
| } | ||||
| 
 | ||||
| std::string& Sidebar::get_search_line() | ||||
| { | ||||
|     return p->searcher.search_string(); | ||||
| } | ||||
| 
 | ||||
| // Plater::DropTarget
 | ||||
| 
 | ||||
| class PlaterDropTarget : public wxFileDropTarget | ||||
|  | @ -1568,6 +1635,9 @@ struct Plater::priv | |||
|     bool are_view3D_labels_shown() const { return (current_panel == view3D) && view3D->get_canvas3d()->are_labels_shown(); } | ||||
|     void show_view3D_labels(bool show) { if (current_panel == view3D) view3D->get_canvas3d()->show_labels(show); } | ||||
| 
 | ||||
|     bool is_sidebar_collapsed() const   { return sidebar->is_collapsed(); } | ||||
|     void collapse_sidebar(bool show)    { sidebar->collapse(show); } | ||||
| 
 | ||||
| #if ENABLE_SLOPE_RENDERING | ||||
|     bool is_view3D_slope_shown() const { return (current_panel == view3D) && view3D->get_canvas3d()->is_slope_shown(); } | ||||
|     void show_view3D_slope(bool show) { if (current_panel == view3D) view3D->get_canvas3d()->show_slope(show); } | ||||
|  | @ -1874,6 +1944,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) | |||
|     view3D_canvas->Bind(EVT_GLCANVAS_RESETGIZMOS, [this](SimpleEvent&) { reset_all_gizmos(); }); | ||||
|     view3D_canvas->Bind(EVT_GLCANVAS_UNDO, [this](SimpleEvent&) { this->undo(); }); | ||||
|     view3D_canvas->Bind(EVT_GLCANVAS_REDO, [this](SimpleEvent&) { this->redo(); }); | ||||
|     view3D_canvas->Bind(EVT_GLCANVAS_COLLAPSE_SIDEBAR, [this](SimpleEvent&) { this->q->collapse_sidebar(!this->q->is_sidebar_collapsed());  }); | ||||
|     view3D_canvas->Bind(EVT_GLCANVAS_RESET_LAYER_HEIGHT_PROFILE, [this](SimpleEvent&) { this->view3D->get_canvas3d()->reset_layer_height_profile(); }); | ||||
|     view3D_canvas->Bind(EVT_GLCANVAS_ADAPTIVE_LAYER_HEIGHT_PROFILE, [this](Event<float>& evt) { this->view3D->get_canvas3d()->adaptive_layer_height_profile(evt.data); }); | ||||
|     view3D_canvas->Bind(EVT_GLCANVAS_SMOOTH_LAYER_HEIGHT_PROFILE, [this](HeightProfileSmoothEvent& evt) { this->view3D->get_canvas3d()->smooth_layer_height_profile(evt.data); }); | ||||
|  | @ -1962,6 +2033,31 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) | |||
| 
 | ||||
|     // Initialize the Undo / Redo stack with a first snapshot.
 | ||||
|     this->take_snapshot(_L("New Project")); | ||||
| 
 | ||||
|     this->q->Bind(EVT_LOAD_MODEL_OTHER_INSTANCE, [this](LoadFromOtherInstanceEvent &evt) {  | ||||
| 		BOOST_LOG_TRIVIAL(debug) << "received load from other instance event "; | ||||
|         this->load_files(evt.data, true, true); | ||||
|     }); | ||||
|     this->q->Bind(EVT_INSTANCE_GO_TO_FRONT, [this](InstanceGoToFrontEvent &) {  | ||||
|         BOOST_LOG_TRIVIAL(debug) << "prusaslicer window going forward"; | ||||
| 		//this code maximize app window on Fedora
 | ||||
| 		wxGetApp().mainframe->Iconize(false); | ||||
|         if (wxGetApp().mainframe->IsMaximized()) | ||||
|             wxGetApp().mainframe->Maximize(true); | ||||
|         else | ||||
|             wxGetApp().mainframe->Maximize(false); | ||||
| 		//this code (without code above) maximize window on Ubuntu
 | ||||
| 		wxGetApp().mainframe->Restore();   | ||||
| 		wxGetApp().GetTopWindow()->SetFocus();  // focus on my window
 | ||||
| 		wxGetApp().GetTopWindow()->Raise();  // bring window to front
 | ||||
| 		wxGetApp().GetTopWindow()->Show(true); // show the window
 | ||||
| 
 | ||||
|     }); | ||||
| 	wxGetApp().other_instance_message_handler()->init(this->q); | ||||
| 
 | ||||
| 
 | ||||
|     // collapse sidebar according to saved value
 | ||||
|     sidebar->collapse(wxGetApp().app_config->get("collapsed_sidebar") == "1"); | ||||
| } | ||||
| 
 | ||||
| Plater::priv::~priv() | ||||
|  | @ -3239,13 +3335,14 @@ void Plater::priv::on_select_preset(wxCommandEvent &evt) | |||
| 
 | ||||
|     // update plater with new config
 | ||||
|     q->on_config_change(wxGetApp().preset_bundle->full_config()); | ||||
|     if (preset_type == Preset::TYPE_PRINTER) { | ||||
|     /* Settings list can be changed after printer preset changing, so
 | ||||
|      * update all settings items for all item had it. | ||||
|      * Furthermore, Layers editing is implemented only for FFF printers | ||||
|      * and for SLA presets they should be deleted | ||||
|      */ | ||||
|     if (preset_type == Preset::TYPE_PRINTER) | ||||
|         wxGetApp().obj_list()->update_object_list_by_printer_technology(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void Plater::priv::on_slicing_update(SlicingStatusEvent &evt) | ||||
|  | @ -4341,6 +4438,9 @@ bool Plater::is_view3D_shown() const { return p->is_view3D_shown(); } | |||
| bool Plater::are_view3D_labels_shown() const { return p->are_view3D_labels_shown(); } | ||||
| void Plater::show_view3D_labels(bool show) { p->show_view3D_labels(show); } | ||||
| 
 | ||||
| bool Plater::is_sidebar_collapsed() const { return p->is_sidebar_collapsed(); } | ||||
| void Plater::collapse_sidebar(bool show) { p->collapse_sidebar(show); } | ||||
| 
 | ||||
| #if ENABLE_SLOPE_RENDERING | ||||
| bool Plater::is_view3D_slope_shown() const { return p->is_view3D_slope_shown(); } | ||||
| void Plater::show_view3D_slope(bool show) { p->show_view3D_slope(show); } | ||||
|  | @ -4913,6 +5013,18 @@ void Plater::undo_redo_topmost_string_getter(const bool is_undo, std::string& ou | |||
|     out_text = ""; | ||||
| } | ||||
| 
 | ||||
| bool Plater::search_string_getter(int idx, const char** label, const char** tooltip) | ||||
| { | ||||
|     const Search::OptionsSearcher& search_list = p->sidebar->get_searcher(); | ||||
|      | ||||
|     if (0 <= idx && (size_t)idx < search_list.size()) { | ||||
|         search_list[idx].get_marked_label_and_tooltip(label, tooltip); | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| void Plater::on_extruders_change(size_t num_extruders) | ||||
| { | ||||
|     auto& choices = sidebar().combos_filament(); | ||||
|  | @ -4972,8 +5084,11 @@ void Plater::on_config_change(const DynamicPrintConfig &config) | |||
|         } | ||||
|          | ||||
|         p->config->set_key_value(opt_key, config.option(opt_key)->clone()); | ||||
|         if (opt_key == "printer_technology") | ||||
|         if (opt_key == "printer_technology") { | ||||
|             this->set_printer_technology(config.opt_enum<PrinterTechnology>(opt_key)); | ||||
|             // print technology is changed, so we should to update a search list
 | ||||
|             p->sidebar->update_searcher(); | ||||
|         } | ||||
|         else if ((opt_key == "bed_shape") || (opt_key == "bed_custom_texture") || (opt_key == "bed_custom_model")) { | ||||
|             bed_shape_changed = true; | ||||
|             update_scheduled = true; | ||||
|  | @ -5283,6 +5398,27 @@ void Plater::paste_from_clipboard() | |||
|     p->view3D->get_canvas3d()->get_selection().paste_from_clipboard(); | ||||
| } | ||||
| 
 | ||||
| void Plater::search(bool plater_is_active) | ||||
| { | ||||
|     if (plater_is_active) { | ||||
|         wxKeyEvent evt; | ||||
| #ifdef __APPLE__ | ||||
|         evt.m_keyCode = 'f'; | ||||
| #else /* __APPLE__ */ | ||||
|         evt.m_keyCode = WXK_CONTROL_F; | ||||
| #endif /* __APPLE__ */ | ||||
|         evt.SetControlDown(true); | ||||
|         canvas3D()->on_char(evt); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         wxPoint pos = this->ClientToScreen(wxPoint(0, 0)); | ||||
|         pos.x += em_unit(this) * 40; | ||||
|         pos.y += em_unit(this) * 4; | ||||
|         p->sidebar->get_searcher().search_dialog->Popup(pos); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void Plater::msw_rescale() | ||||
| { | ||||
|     p->preview->msw_rescale(); | ||||
|  |  | |||
|  | @ -14,6 +14,7 @@ | |||
| #include "libslic3r/BoundingBox.hpp" | ||||
| #include "Jobs/Job.hpp" | ||||
| #include "wxExtensions.hpp" | ||||
| #include "Search.hpp" | ||||
| 
 | ||||
| class wxButton; | ||||
| class ScalableButton; | ||||
|  | @ -106,6 +107,8 @@ public: | |||
|     void update_mode_sizer() const; | ||||
|     void update_reslice_btn_tooltip() const; | ||||
|     void msw_rescale(); | ||||
|     void search(); | ||||
|     void jump_to_option(size_t selected); | ||||
| 
 | ||||
|     ObjectManipulation*     obj_manipul(); | ||||
|     ObjectList*             obj_list(); | ||||
|  | @ -129,9 +132,15 @@ public: | |||
| 	bool                    show_export_removable(bool show) const; | ||||
|     bool                    is_multifilament(); | ||||
|     void                    update_mode(); | ||||
|     bool                    is_collapsed(); | ||||
|     void                    collapse(bool collapse); | ||||
|     void                    update_searcher(); | ||||
|     void                    update_ui_from_settings(); | ||||
| 
 | ||||
|     std::vector<PresetComboBox*>& combos_filament(); | ||||
|     std::vector<PresetComboBox*>&   combos_filament(); | ||||
|     Search::OptionsSearcher&        get_searcher(); | ||||
|     std::string&                    get_search_line(); | ||||
| 
 | ||||
| private: | ||||
|     struct priv; | ||||
|     std::unique_ptr<priv> p; | ||||
|  | @ -179,6 +188,9 @@ public: | |||
|     bool are_view3D_labels_shown() const; | ||||
|     void show_view3D_labels(bool show); | ||||
| 
 | ||||
|     bool is_sidebar_collapsed() const; | ||||
|     void collapse_sidebar(bool show); | ||||
| 
 | ||||
| #if ENABLE_SLOPE_RENDERING | ||||
|     bool is_view3D_slope_shown() const; | ||||
|     void show_view3D_slope(bool show); | ||||
|  | @ -234,6 +246,7 @@ public: | |||
|     void redo_to(int selection); | ||||
|     bool undo_redo_string_getter(const bool is_undo, int idx, const char** out_text); | ||||
|     void undo_redo_topmost_string_getter(const bool is_undo, std::string& out_text); | ||||
|     bool search_string_getter(int idx, const char** label, const char** tooltip); | ||||
|     // For the memory statistics. 
 | ||||
|     const Slic3r::UndoRedo::Stack& undo_redo_stack_main() const; | ||||
|     // Enter / leave the Gizmos specific Undo / Redo stack. To be used by the SLA support point editing gizmo.
 | ||||
|  | @ -279,6 +292,7 @@ public: | |||
| 
 | ||||
|     void copy_selection_to_clipboard(); | ||||
|     void paste_from_clipboard(); | ||||
|     void search(bool plater_is_active); | ||||
| 
 | ||||
|     bool can_delete() const; | ||||
|     bool can_delete_all() const; | ||||
|  |  | |||
|  | @ -100,6 +100,13 @@ void PreferencesDialog::build() | |||
| 	option = Option (def,"show_incompatible_presets"); | ||||
| 	m_optgroup_general->append_single_option_line(option); | ||||
| 
 | ||||
| 	def.label = L("Single Instance"); | ||||
| 	def.type = coBool; | ||||
| 	def.tooltip = L("If this is enabled, when staring PrusaSlicer and another instance is running, that instance will be reactivated instead."); | ||||
| 	def.set_default_value(new ConfigOptionBool{ app_config->has("single_instance") ? app_config->get("single_instance") == "1" : false }); | ||||
| 	option = Option(def, "single_instance"); | ||||
| 	m_optgroup_general->append_single_option_line(option); | ||||
| 
 | ||||
| #if __APPLE__ | ||||
| 	def.label = L("Use Retina resolution for the 3D scene"); | ||||
| 	def.type = coBool; | ||||
|  | @ -186,6 +193,8 @@ void PreferencesDialog::accept() | |||
| 		app_config->set(it->first, it->second); | ||||
| 	} | ||||
| 
 | ||||
| 	app_config->save(); | ||||
| 
 | ||||
| 	EndModal(wxID_OK); | ||||
| 
 | ||||
| 	// Nothify the UI to update itself from the ini file.
 | ||||
|  |  | |||
|  | @ -405,8 +405,9 @@ const std::vector<std::string>& Preset::print_options() | |||
|         "extra_perimeters", "ensure_vertical_shell_thickness", "avoid_crossing_perimeters", "thin_walls", "overhangs", | ||||
|         "seam_position", "external_perimeters_first", "fill_density", "fill_pattern", "top_fill_pattern", "bottom_fill_pattern", | ||||
|         "infill_every_layers", "infill_only_where_needed", "solid_infill_every_layers", "fill_angle", "bridge_angle", | ||||
|         "solid_infill_below_area", "only_retract_when_crossing_perimeters", "infill_first", "max_print_speed", | ||||
|         "max_volumetric_speed", | ||||
|         "solid_infill_below_area", "only_retract_when_crossing_perimeters", "infill_first",  | ||||
|     	"ironing", "ironing_type", "ironing_flowrate", "ironing_speed", "ironing_spacing", | ||||
|         "max_print_speed", "max_volumetric_speed", | ||||
| #ifdef HAS_PRESSURE_EQUALIZER | ||||
|         "max_volumetric_extrusion_rate_slope_positive", "max_volumetric_extrusion_rate_slope_negative", | ||||
| #endif /* HAS_PRESSURE_EQUALIZER */ | ||||
|  |  | |||
							
								
								
									
										608
									
								
								src/slic3r/GUI/Search.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										608
									
								
								src/slic3r/GUI/Search.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,608 @@ | |||
| #include "Search.hpp" | ||||
| 
 | ||||
| #include <cstddef> | ||||
| #include <string> | ||||
| #include <boost/optional.hpp> | ||||
| 
 | ||||
| #include "libslic3r/PrintConfig.hpp" | ||||
| #include "GUI_App.hpp" | ||||
| #include "Tab.hpp" | ||||
| #include "PresetBundle.hpp" | ||||
| 
 | ||||
| #define FTS_FUZZY_MATCH_IMPLEMENTATION | ||||
| #include "fts_fuzzy_match.h" | ||||
| 
 | ||||
| #include "imgui/imconfig.h" | ||||
| 
 | ||||
| using boost::optional; | ||||
| 
 | ||||
| namespace Slic3r { | ||||
| 
 | ||||
| using GUI::from_u8; | ||||
| using GUI::into_u8; | ||||
| 
 | ||||
| namespace Search { | ||||
| 
 | ||||
| static std::map<Preset::Type, std::string> NameByType = { | ||||
|     { Preset::TYPE_PRINT,           L("Print")     }, | ||||
|     { Preset::TYPE_FILAMENT,        L("Filament")  }, | ||||
|     { Preset::TYPE_SLA_MATERIAL,    L("Material")  }, | ||||
|     { Preset::TYPE_SLA_PRINT,       L("Print")     }, | ||||
|     { Preset::TYPE_PRINTER,         L("Printer")   } | ||||
| }; | ||||
| 
 | ||||
| FMFlag Option::fuzzy_match_simple(char const * search_pattern) const | ||||
| { | ||||
|     return  fts::fuzzy_match_simple(search_pattern, label_local.utf8_str())     ? fmLabelLocal      : | ||||
|             fts::fuzzy_match_simple(search_pattern, group_local.utf8_str())     ? fmGroupLocal      : | ||||
|             fts::fuzzy_match_simple(search_pattern, category_local.utf8_str())  ? fmCategoryLocal   : | ||||
|             fts::fuzzy_match_simple(search_pattern, opt_key.c_str())            ? fmOptKey          : | ||||
|             fts::fuzzy_match_simple(search_pattern, label.utf8_str())           ? fmLabel           : | ||||
|             fts::fuzzy_match_simple(search_pattern, group.utf8_str())           ? fmGroup           : | ||||
|             fts::fuzzy_match_simple(search_pattern, category.utf8_str())        ? fmCategory        : fmUndef   ; | ||||
| } | ||||
| 
 | ||||
| FMFlag Option::fuzzy_match_simple(const wxString& search) const | ||||
| { | ||||
|     char const* search_pattern = search.utf8_str(); | ||||
|     return fuzzy_match_simple(search_pattern); | ||||
| } | ||||
| 
 | ||||
| FMFlag Option::fuzzy_match_simple(const std::string& search) const | ||||
| { | ||||
|     char const* search_pattern = search.c_str(); | ||||
|     return fuzzy_match_simple(search_pattern); | ||||
| } | ||||
| 
 | ||||
| FMFlag Option::fuzzy_match(char const* search_pattern, int& outScore) const | ||||
| { | ||||
|     FMFlag flag = fmUndef; | ||||
|     int score; | ||||
| 
 | ||||
|     if (fts::fuzzy_match(search_pattern, label_local.utf8_str(),    score) && outScore < score) { | ||||
|         outScore = score; flag = fmLabelLocal   ; } | ||||
|     if (fts::fuzzy_match(search_pattern, group_local.utf8_str(),    score) && outScore < score) { | ||||
|         outScore = score; flag = fmGroupLocal   ; } | ||||
|     if (fts::fuzzy_match(search_pattern, category_local.utf8_str(), score) && outScore < score) { | ||||
|         outScore = score; flag = fmCategoryLocal; } | ||||
|     if (fts::fuzzy_match(search_pattern, opt_key.c_str(),           score) && outScore < score) { | ||||
|         outScore = score; flag = fmOptKey       ; } | ||||
|     if (fts::fuzzy_match(search_pattern, label.utf8_str(),          score) && outScore < score) { | ||||
|         outScore = score; flag = fmLabel        ; } | ||||
|     if (fts::fuzzy_match(search_pattern, group.utf8_str(),          score) && outScore < score) { | ||||
|         outScore = score; flag = fmGroup        ; } | ||||
|     if (fts::fuzzy_match(search_pattern, category.utf8_str(),       score) && outScore < score) { | ||||
|         outScore = score; flag = fmCategory     ; } | ||||
| 
 | ||||
|     return flag; | ||||
| } | ||||
| 
 | ||||
| FMFlag Option::fuzzy_match(const wxString& search, int& outScore) const | ||||
| { | ||||
|     char const* search_pattern = search.utf8_str(); | ||||
|     return fuzzy_match(search_pattern, outScore);  | ||||
| } | ||||
| 
 | ||||
| FMFlag Option::fuzzy_match(const std::string& search, int& outScore) const | ||||
| { | ||||
|     char const* search_pattern = search.c_str(); | ||||
|     return fuzzy_match(search_pattern, outScore); | ||||
| } | ||||
| 
 | ||||
| void FoundOption::get_label(const char** out_text) const | ||||
| { | ||||
|     *out_text = label.utf8_str(); | ||||
| } | ||||
| 
 | ||||
| void FoundOption::get_marked_label_and_tooltip(const char** label_, const char** tooltip_) const | ||||
| { | ||||
|     *label_   = marked_label.utf8_str(); | ||||
|     *tooltip_ = tooltip.utf8_str(); | ||||
| } | ||||
| 
 | ||||
| template<class T> | ||||
| //void change_opt_key(std::string& opt_key, DynamicPrintConfig* config)
 | ||||
| void change_opt_key(std::string& opt_key, DynamicPrintConfig* config, int& cnt) | ||||
| { | ||||
|     T* opt_cur = static_cast<T*>(config->option(opt_key)); | ||||
|     cnt = opt_cur->values.size(); | ||||
|     return; | ||||
| 
 | ||||
|     if (opt_cur->values.size() > 0) | ||||
|         opt_key += "#" + std::to_string(0); | ||||
| } | ||||
| 
 | ||||
| void OptionsSearcher::append_options(DynamicPrintConfig* config, Preset::Type type, ConfigOptionMode mode) | ||||
| { | ||||
|     auto emplace = [this, type](const std::string opt_key, const wxString& label) | ||||
|     { | ||||
|         const GroupAndCategory& gc = groups_and_categories[opt_key]; | ||||
|         if (gc.group.IsEmpty() || gc.category.IsEmpty()) | ||||
|             return; | ||||
| 
 | ||||
|         wxString suffix; | ||||
|         if (gc.category == "Machine limits") | ||||
|             suffix = opt_key.back()=='1' ? L("Stealth") : L("Normal"); | ||||
| 
 | ||||
|         if (!label.IsEmpty()) | ||||
|             options.emplace_back(Option{ opt_key, type, | ||||
|                                         label+ " " + suffix, _(label)+ " " + _(suffix), | ||||
|                                         gc.group, _(gc.group), | ||||
|                                         gc.category, _(gc.category) }); | ||||
|     }; | ||||
| 
 | ||||
|     for (std::string opt_key : config->keys()) | ||||
|     { | ||||
|         const ConfigOptionDef& opt = config->def()->options.at(opt_key); | ||||
|         if (opt.mode > mode) | ||||
|             continue; | ||||
| 
 | ||||
|         int cnt = 0; | ||||
| 
 | ||||
|         if ( (type == Preset::TYPE_SLA_MATERIAL || type == Preset::TYPE_PRINTER) && opt_key != "bed_shape") | ||||
|             switch (config->option(opt_key)->type()) | ||||
|             { | ||||
|             case coInts:	change_opt_key<ConfigOptionInts		>(opt_key, config, cnt);	break; | ||||
|             case coBools:	change_opt_key<ConfigOptionBools	>(opt_key, config, cnt);	break; | ||||
|             case coFloats:	change_opt_key<ConfigOptionFloats	>(opt_key, config, cnt);	break; | ||||
|             case coStrings:	change_opt_key<ConfigOptionStrings	>(opt_key, config, cnt);	break; | ||||
|             case coPercents:change_opt_key<ConfigOptionPercents	>(opt_key, config, cnt);	break; | ||||
|             case coPoints:	change_opt_key<ConfigOptionPoints	>(opt_key, config, cnt);	break; | ||||
|             default:		break; | ||||
|             } | ||||
| 
 | ||||
|         wxString label = opt.full_label.empty() ? opt.label : opt.full_label; | ||||
| 
 | ||||
|         if (cnt == 0) | ||||
|             emplace(opt_key, label); | ||||
|         else | ||||
|             for (int i = 0; i < cnt; ++i) | ||||
|                 emplace(opt_key + "#" + std::to_string(i), label); | ||||
| 
 | ||||
|         /*const GroupAndCategory& gc = groups_and_categories[opt_key];
 | ||||
|         if (gc.group.IsEmpty() || gc.category.IsEmpty()) | ||||
|             continue; | ||||
| 
 | ||||
|         if (!label.IsEmpty()) | ||||
|             options.emplace_back(Option{opt_key, type, | ||||
|                                         label, _(label), | ||||
|                                         gc.group, _(gc.group), | ||||
|                                         gc.category, _(gc.category) });*/ | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // Wrap a string with ColorMarkerStart and ColorMarkerEnd symbols
 | ||||
| static wxString wrap_string(const wxString& str) | ||||
| { | ||||
|     return wxString::Format("%c%s%c", ImGui::ColorMarkerStart, str, ImGui::ColorMarkerEnd); | ||||
| } | ||||
| 
 | ||||
| // Mark a string using ColorMarkerStart and ColorMarkerEnd symbols
 | ||||
| static void mark_string(wxString& str, const wxString& search_str) | ||||
| { | ||||
|     // Try to find whole search string
 | ||||
|     if (str.Replace(search_str, wrap_string(search_str), false) != 0) | ||||
|         return; | ||||
| 
 | ||||
|     // Try to find whole capitalized search string
 | ||||
|     wxString search_str_capitalized = search_str.Capitalize(); | ||||
|     if (str.Replace(search_str_capitalized, wrap_string(search_str_capitalized), false) != 0) | ||||
|         return; | ||||
| 
 | ||||
|     // if search string is just a one letter now, there is no reason to continue 
 | ||||
|     if (search_str.Len()==1) | ||||
|         return; | ||||
| 
 | ||||
|     // Split a search string for two strings (string without last letter and last letter)
 | ||||
|     // and repeat a function with new search strings
 | ||||
|     mark_string(str, search_str.SubString(0, search_str.Len() - 2)); | ||||
|     mark_string(str, search_str.Last()); | ||||
| } | ||||
| 
 | ||||
| // clear marked string from a redundant use of ColorMarkers
 | ||||
| static void clear_marked_string(wxString& str) | ||||
| { | ||||
|     // Check if the string has a several ColorMarkerStart in a row and replace them to only one, if any
 | ||||
|     wxString delete_string = wxString::Format("%c%c", ImGui::ColorMarkerStart, ImGui::ColorMarkerStart); | ||||
|     str.Replace(delete_string, ImGui::ColorMarkerStart, true); | ||||
|     // If there were several ColorMarkerStart in a row, it means there should be a several ColorMarkerStop in a row,
 | ||||
|     // replace them to only one
 | ||||
|     delete_string = wxString::Format("%c%c", ImGui::ColorMarkerEnd, ImGui::ColorMarkerEnd); | ||||
|     str.Replace(delete_string, ImGui::ColorMarkerEnd, true); | ||||
| 
 | ||||
|     // And we should to remove redundant ColorMarkers, if they are in "End, Start" sequence in a row
 | ||||
|     delete_string = wxString::Format("%c%c", ImGui::ColorMarkerEnd, ImGui::ColorMarkerStart); | ||||
|     str.Replace(delete_string, wxEmptyString, true); | ||||
| } | ||||
| 
 | ||||
| bool OptionsSearcher::search() | ||||
| { | ||||
|     return search(search_line, true); | ||||
| } | ||||
| 
 | ||||
| bool OptionsSearcher::search(const std::string& search, bool force/* = false*/) | ||||
| { | ||||
|     if (search_line == search && !force) | ||||
|         return false; | ||||
| 
 | ||||
|     found.clear(); | ||||
| 
 | ||||
|     bool full_list = search.empty(); | ||||
|     wxString sep = " : "; | ||||
| 
 | ||||
|     auto get_label = [this, sep](const Option& opt) | ||||
|     { | ||||
|         wxString label; | ||||
|         if (view_params.type) | ||||
|             label += _(NameByType[opt.type]) + sep; | ||||
|         if (view_params.category) | ||||
|             label += opt.category_local + sep; | ||||
|         if (view_params.group) | ||||
|             label += opt.group_local + sep; | ||||
|         label += opt.label_local; | ||||
|         return label; | ||||
|     }; | ||||
| 
 | ||||
|     auto get_tooltip = [this, sep](const Option& opt) | ||||
|     { | ||||
|         return  _(NameByType[opt.type]) + sep + | ||||
|                 opt.category_local + sep + | ||||
|                 opt.group_local + sep + opt.label_local; | ||||
|     }; | ||||
| 
 | ||||
|     for (size_t i=0; i < options.size(); i++) | ||||
|     { | ||||
|         const Option &opt = options[i]; | ||||
|         if (full_list) { | ||||
|             wxString label = get_label(opt); | ||||
|             found.emplace_back(FoundOption{ label, label, get_tooltip(opt), i, 0 }); | ||||
|             continue; | ||||
|         } | ||||
| 
 | ||||
|         int score = 0; | ||||
| 
 | ||||
|         FMFlag fuzzy_match_flag = opt.fuzzy_match(search, score); | ||||
|         if (fuzzy_match_flag != fmUndef) | ||||
|         { | ||||
|             wxString label = get_label(opt); | ||||
| 
 | ||||
|             if (     fuzzy_match_flag == fmLabel   ) label += "(" + opt.label    + ")"; | ||||
|             else if (fuzzy_match_flag == fmGroup   ) label += "(" + opt.group    + ")"; | ||||
|             else if (fuzzy_match_flag == fmCategory) label += "(" + opt.category + ")"; | ||||
|             else if (fuzzy_match_flag == fmOptKey  ) label += "(" + opt.opt_key  + ")"; | ||||
| 
 | ||||
|             wxString marked_label = label; | ||||
|             mark_string(marked_label, from_u8(search)); | ||||
|             clear_marked_string(marked_label); | ||||
| 
 | ||||
|             found.emplace_back(FoundOption{ label, marked_label, get_tooltip(opt), i, score }); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if (!full_list) | ||||
|         sort_found(); | ||||
| 
 | ||||
|     if (search_line != search) | ||||
|         search_line = search; | ||||
| 
 | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| OptionsSearcher::OptionsSearcher() | ||||
| { | ||||
|     search_dialog = new SearchDialog(this); | ||||
| } | ||||
| 
 | ||||
| OptionsSearcher::~OptionsSearcher() | ||||
| { | ||||
|     if (search_dialog) | ||||
|         search_dialog->Destroy(); | ||||
| } | ||||
| 
 | ||||
| void OptionsSearcher::init(std::vector<InputInfo> input_values) | ||||
| { | ||||
|     options.clear(); | ||||
|     for (auto i : input_values) | ||||
|         append_options(i.config, i.type, i.mode); | ||||
|     sort_options(); | ||||
| 
 | ||||
|     search(search_line, true); | ||||
| } | ||||
| 
 | ||||
| void OptionsSearcher::apply(DynamicPrintConfig* config, Preset::Type type, ConfigOptionMode mode) | ||||
| { | ||||
|     if (options.empty()) | ||||
|         return; | ||||
| 
 | ||||
|     options.erase(std::remove_if(options.begin(), options.end(), [type](Option opt) { | ||||
|             return opt.type == type; | ||||
|         }), options.end()); | ||||
| 
 | ||||
|     append_options(config, type, mode); | ||||
| 
 | ||||
|     sort_options(); | ||||
| 
 | ||||
|     search(search_line, true); | ||||
| } | ||||
| 
 | ||||
| const Option& OptionsSearcher::get_option(size_t pos_in_filter) const | ||||
| { | ||||
|     assert(pos_in_filter != size_t(-1) && found[pos_in_filter].option_idx != size_t(-1)); | ||||
|     return options[found[pos_in_filter].option_idx]; | ||||
| } | ||||
| 
 | ||||
| void OptionsSearcher::add_key(const std::string& opt_key, const wxString& group, const wxString& category) | ||||
| { | ||||
|     groups_and_categories[opt_key] = GroupAndCategory{group, category}; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| //------------------------------------------
 | ||||
| //          SearchComboPopup
 | ||||
| //------------------------------------------
 | ||||
| 
 | ||||
| 
 | ||||
| void SearchComboPopup::Init() | ||||
| { | ||||
|     this->Bind(wxEVT_MOTION,    &SearchComboPopup::OnMouseMove,     this); | ||||
|     this->Bind(wxEVT_LEFT_UP,   &SearchComboPopup::OnMouseClick,    this); | ||||
|     this->Bind(wxEVT_KEY_DOWN,  &SearchComboPopup::OnKeyDown,       this); | ||||
| } | ||||
| 
 | ||||
| bool SearchComboPopup::Create(wxWindow* parent) | ||||
| { | ||||
|     return wxListBox::Create(parent, 1, wxPoint(0, 0), wxDefaultSize); | ||||
| } | ||||
| 
 | ||||
| void SearchComboPopup::SetStringValue(const wxString& s) | ||||
| { | ||||
|     int n = wxListBox::FindString(s); | ||||
|     if (n >= 0 && n < wxListBox::GetCount()) | ||||
|         wxListBox::Select(n); | ||||
| 
 | ||||
|     // save a combo control's string
 | ||||
|     m_input_string = s; | ||||
| } | ||||
| 
 | ||||
| void SearchComboPopup::ProcessSelection(int selection)  | ||||
| { | ||||
|     wxCommandEvent event(wxEVT_LISTBOX, GetId()); | ||||
|     event.SetInt(selection); | ||||
|     event.SetEventObject(this); | ||||
|     ProcessEvent(event); | ||||
| 
 | ||||
|     Dismiss(); | ||||
| } | ||||
| 
 | ||||
| void SearchComboPopup::OnMouseMove(wxMouseEvent& event) | ||||
| { | ||||
|     wxPoint pt = wxGetMousePosition() - this->GetScreenPosition(); | ||||
|     int selection = this->HitTest(pt); | ||||
|     wxListBox::Select(selection); | ||||
| } | ||||
| 
 | ||||
| void SearchComboPopup::OnMouseClick(wxMouseEvent&) | ||||
| { | ||||
|     int selection = wxListBox::GetSelection(); | ||||
|     SetSelection(wxNOT_FOUND); | ||||
|     ProcessSelection(selection); | ||||
| } | ||||
| 
 | ||||
| void SearchComboPopup::OnKeyDown(wxKeyEvent& event) | ||||
| { | ||||
|     int key = event.GetKeyCode(); | ||||
| 
 | ||||
|     // change selected item in the list
 | ||||
|     if (key == WXK_UP || key == WXK_DOWN) | ||||
|     { | ||||
|         int selection = wxListBox::GetSelection(); | ||||
| 
 | ||||
|         if (key == WXK_UP && selection > 0) | ||||
|             selection--; | ||||
|         if (key == WXK_DOWN && selection < int(wxListBox::GetCount() - 1)) | ||||
|             selection++; | ||||
| 
 | ||||
|         wxListBox::Select(selection); | ||||
|     } | ||||
|     // send wxEVT_LISTBOX event if "Enter" was pushed
 | ||||
|     else if (key == WXK_NUMPAD_ENTER || key == WXK_RETURN) | ||||
|         ProcessSelection(wxListBox::GetSelection()); | ||||
|     else | ||||
|         event.Skip(); // !Needed to have EVT_CHAR generated as well
 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| //------------------------------------------
 | ||||
| //          SearchDialog
 | ||||
| //------------------------------------------
 | ||||
| 
 | ||||
| SearchDialog::SearchDialog(OptionsSearcher* searcher) | ||||
|     : GUI::DPIDialog(NULL, wxID_ANY, _L("Search"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER), | ||||
|     searcher(searcher) | ||||
| { | ||||
|     SetFont(GUI::wxGetApp().normal_font()); | ||||
|     wxColour bgr_clr = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); | ||||
|     SetBackgroundColour(bgr_clr); | ||||
| 
 | ||||
|     default_string = _L("Type here to search"); | ||||
|     int border = 10; | ||||
| 
 | ||||
|     search_line = new wxTextCtrl(this, wxID_ANY, "", wxDefaultPosition, wxDefaultSize); | ||||
| 
 | ||||
|     // wxWANTS_CHARS style is neede for process Enter key press
 | ||||
|     search_list = new wxListBox(this, wxID_ANY, wxDefaultPosition, wxSize(em_unit() * 40, em_unit() * 30), 0, NULL, wxWANTS_CHARS); | ||||
| 
 | ||||
|     wxBoxSizer* check_sizer = new wxBoxSizer(wxHORIZONTAL); | ||||
| 
 | ||||
|     check_type      = new wxCheckBox(this, wxID_ANY, _L("Type")); | ||||
|     check_category  = new wxCheckBox(this, wxID_ANY, _L("Category")); | ||||
|     check_group     = new wxCheckBox(this, wxID_ANY, _L("Group")); | ||||
| 
 | ||||
|     wxStdDialogButtonSizer* cancel_btn = this->CreateStdDialogButtonSizer(wxCANCEL); | ||||
| 
 | ||||
|     check_sizer->Add(check_type,     0, wxALIGN_CENTER_VERTICAL | wxRIGHT, border); | ||||
|     check_sizer->Add(check_category, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, border); | ||||
|     check_sizer->Add(check_group,    0, wxALIGN_CENTER_VERTICAL | wxRIGHT, border); | ||||
|     check_sizer->AddStretchSpacer(border); | ||||
|     check_sizer->Add(cancel_btn,     0, wxALIGN_CENTER_VERTICAL); | ||||
| 
 | ||||
|     wxBoxSizer* topSizer = new wxBoxSizer(wxVERTICAL); | ||||
| 
 | ||||
|     topSizer->Add(search_line, 0, wxEXPAND | wxLEFT | wxTOP | wxRIGHT, border); | ||||
|     topSizer->Add(search_list, 1, wxEXPAND | wxLEFT | wxTOP | wxRIGHT, border); | ||||
|     topSizer->Add(check_sizer, 0, wxEXPAND | wxALL, border); | ||||
| 
 | ||||
|     search_line->Bind(wxEVT_TEXT,    &SearchDialog::OnInputText, this); | ||||
|     search_line->Bind(wxEVT_LEFT_UP, &SearchDialog::OnLeftUpInTextCtrl, this); | ||||
|     // process wxEVT_KEY_DOWN to navigate inside search_list, if ArrowUp/Down was pressed
 | ||||
|     search_line->Bind(wxEVT_KEY_DOWN,&SearchDialog::OnKeyDown, this); | ||||
| 
 | ||||
|     search_list->Bind(wxEVT_MOTION,  &SearchDialog::OnMouseMove, this); | ||||
|     search_list->Bind(wxEVT_LEFT_UP, &SearchDialog::OnMouseClick, this); | ||||
|     search_list->Bind(wxEVT_KEY_DOWN,&SearchDialog::OnKeyDown, this); | ||||
| 
 | ||||
|     check_type    ->Bind(wxEVT_CHECKBOX, &SearchDialog::OnCheck, this); | ||||
|     check_category->Bind(wxEVT_CHECKBOX, &SearchDialog::OnCheck, this); | ||||
|     check_group   ->Bind(wxEVT_CHECKBOX, &SearchDialog::OnCheck, this); | ||||
| 
 | ||||
|     this->Bind(wxEVT_LISTBOX, &SearchDialog::OnSelect, this); | ||||
| 
 | ||||
|     SetSizer(topSizer); | ||||
|     topSizer->SetSizeHints(this); | ||||
| } | ||||
| 
 | ||||
| void SearchDialog::Popup(wxPoint position /*= wxDefaultPosition*/) | ||||
| { | ||||
|     const std::string& line = searcher->search_string(); | ||||
|     search_line->SetValue(line.empty() ? default_string : from_u8(line)); | ||||
|     search_line->SetFocus(); | ||||
|     search_line->SelectAll(); | ||||
| 
 | ||||
|     update_list(); | ||||
| 
 | ||||
|     const OptionViewParameters& params = searcher->view_params; | ||||
|     check_type->SetValue(params.type); | ||||
|     check_category->SetValue(params.category); | ||||
|     check_group->SetValue(params.group); | ||||
| 
 | ||||
|     this->SetPosition(position); | ||||
|     this->ShowModal(); | ||||
| } | ||||
| 
 | ||||
| void SearchDialog::ProcessSelection(int selection) | ||||
| { | ||||
|     if (selection < 0) | ||||
|         return; | ||||
| 
 | ||||
|     GUI::wxGetApp().sidebar().jump_to_option(selection); | ||||
|     this->EndModal(wxID_CLOSE); | ||||
| } | ||||
| 
 | ||||
| void SearchDialog::OnInputText(wxCommandEvent&) | ||||
| { | ||||
|     search_line->SetInsertionPointEnd(); | ||||
| 
 | ||||
|     wxString input_string = search_line->GetValue(); | ||||
|     if (input_string == default_string) | ||||
|         input_string.Clear(); | ||||
| 
 | ||||
|     searcher->search(into_u8(input_string)); | ||||
| 
 | ||||
|     update_list(); | ||||
| } | ||||
| 
 | ||||
| void SearchDialog::OnLeftUpInTextCtrl(wxEvent& event) | ||||
| { | ||||
|     if (search_line->GetValue() == default_string) | ||||
|         search_line->SetValue(""); | ||||
| 
 | ||||
|     event.Skip(); | ||||
| } | ||||
| 
 | ||||
| void SearchDialog::OnMouseMove(wxMouseEvent& event) | ||||
| { | ||||
|     wxPoint pt = wxGetMousePosition() - search_list->GetScreenPosition(); | ||||
|     int selection = search_list->HitTest(pt); | ||||
|     search_list->Select(selection); | ||||
| } | ||||
| 
 | ||||
| void SearchDialog::OnMouseClick(wxMouseEvent&) | ||||
| { | ||||
|     int selection = search_list->GetSelection(); | ||||
|     search_list->SetSelection(wxNOT_FOUND); | ||||
| 
 | ||||
|     wxCommandEvent event(wxEVT_LISTBOX, search_list->GetId()); | ||||
|     event.SetInt(selection); | ||||
|     event.SetEventObject(search_list); | ||||
|     ProcessEvent(event); | ||||
| } | ||||
| 
 | ||||
| void SearchDialog::OnSelect(wxCommandEvent& event) | ||||
| { | ||||
|     int selection = event.GetSelection(); | ||||
|     ProcessSelection(selection); | ||||
| } | ||||
| 
 | ||||
| void SearchDialog::update_list() | ||||
| { | ||||
|     search_list->Clear(); | ||||
| 
 | ||||
|     const std::vector<FoundOption>& filters = searcher->found_options(); | ||||
|     for (const FoundOption& item : filters) | ||||
|         search_list->Append(item.label); | ||||
| } | ||||
| 
 | ||||
| void SearchDialog::OnKeyDown(wxKeyEvent& event) | ||||
| { | ||||
|     int key = event.GetKeyCode(); | ||||
| 
 | ||||
|     // change selected item in the list
 | ||||
|     if (key == WXK_UP || key == WXK_DOWN) | ||||
|     { | ||||
|         int selection = search_list->GetSelection(); | ||||
| 
 | ||||
|         if (key == WXK_UP && selection > 0) | ||||
|             selection--; | ||||
|         if (key == WXK_DOWN && selection < int(search_list->GetCount() - 1)) | ||||
|             selection++; | ||||
| 
 | ||||
|         search_list->Select(selection); | ||||
|         // This function could be called from search_line,
 | ||||
|         // So, for the next correct navigation, set focus on the search_list
 | ||||
|         search_list->SetFocus(); | ||||
|     } | ||||
|     // process "Enter" pressed
 | ||||
|     else if (key == WXK_NUMPAD_ENTER || key == WXK_RETURN) | ||||
|         ProcessSelection(search_list->GetSelection()); | ||||
|     else | ||||
|         event.Skip(); // !Needed to have EVT_CHAR generated as well
 | ||||
| } | ||||
| 
 | ||||
| void SearchDialog::OnCheck(wxCommandEvent& event) | ||||
| { | ||||
|     OptionViewParameters& params = searcher->view_params; | ||||
|     params.type     = check_type->GetValue(); | ||||
|     params.category = check_category->GetValue(); | ||||
|     params.group    = check_group->GetValue(); | ||||
| 
 | ||||
|     searcher->search(); | ||||
|     update_list(); | ||||
| } | ||||
| 
 | ||||
| void SearchDialog::on_dpi_changed(const wxRect& suggested_rect) | ||||
| { | ||||
|     const int& em = em_unit(); | ||||
| 
 | ||||
|     msw_buttons_rescale(this, em, { wxID_CANCEL }); | ||||
| 
 | ||||
|     const wxSize& size = wxSize(40 * em, 30 * em); | ||||
|     SetMinSize(size); | ||||
| 
 | ||||
|     Fit(); | ||||
|     Refresh(); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| }    // namespace Slic3r::GUI
 | ||||
							
								
								
									
										220
									
								
								src/slic3r/GUI/Search.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										220
									
								
								src/slic3r/GUI/Search.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,220 @@ | |||
| #ifndef slic3r_SearchComboBox_hpp_ | ||||
| #define slic3r_SearchComboBox_hpp_ | ||||
| 
 | ||||
| #include <vector> | ||||
| #include <map> | ||||
| 
 | ||||
| #include <wx/panel.h> | ||||
| #include <wx/sizer.h> | ||||
| #include <wx/listctrl.h> | ||||
| 
 | ||||
| #include <wx/combo.h> | ||||
| 
 | ||||
| #include <wx/checkbox.h> | ||||
| #include <wx/dialog.h> | ||||
| 
 | ||||
| #include "GUI_Utils.hpp" | ||||
| #include "Preset.hpp" | ||||
| #include "wxExtensions.hpp" | ||||
| 
 | ||||
| 
 | ||||
| namespace Slic3r { | ||||
| 
 | ||||
| namespace Search{ | ||||
| 
 | ||||
| class SearchDialog; | ||||
| 
 | ||||
| struct InputInfo | ||||
| { | ||||
|     DynamicPrintConfig* config  {nullptr}; | ||||
|     Preset::Type        type    {Preset::TYPE_INVALID}; | ||||
|     ConfigOptionMode    mode    {comSimple}; | ||||
| }; | ||||
| 
 | ||||
| struct GroupAndCategory { | ||||
|     wxString        group; | ||||
|     wxString        category; | ||||
| }; | ||||
| 
 | ||||
| // fuzzy_match flag
 | ||||
| enum FMFlag | ||||
| { | ||||
|     fmUndef = 0, // didn't find 
 | ||||
|     fmOptKey, | ||||
|     fmLabel, | ||||
|     fmLabelLocal, | ||||
|     fmGroup, | ||||
|     fmGroupLocal, | ||||
|     fmCategory, | ||||
|     fmCategoryLocal | ||||
| }; | ||||
| 
 | ||||
| struct Option { | ||||
|     bool operator<(const Option& other) const { return other.label > this->label; } | ||||
|     bool operator>(const Option& other) const { return other.label < this->label; } | ||||
| 
 | ||||
|     std::string     opt_key; | ||||
|     Preset::Type    type {Preset::TYPE_INVALID}; | ||||
|     wxString        label; | ||||
|     wxString        label_local; | ||||
|     wxString        group; | ||||
|     wxString        group_local; | ||||
|     wxString        category; | ||||
|     wxString        category_local; | ||||
| 
 | ||||
|     FMFlag fuzzy_match_simple(char const *search_pattern) const; | ||||
|     FMFlag fuzzy_match_simple(const wxString& search) const; | ||||
|     FMFlag fuzzy_match_simple(const std::string &search) const; | ||||
|     FMFlag fuzzy_match(char const *search_pattern, int &outScore) const; | ||||
|     FMFlag fuzzy_match(const wxString &search, int &outScore) const ; | ||||
|     FMFlag fuzzy_match(const std::string &search, int &outScore) const ; | ||||
| }; | ||||
| 
 | ||||
| struct FoundOption { | ||||
|     wxString        label; | ||||
|     wxString        marked_label; | ||||
|     wxString        tooltip; | ||||
|     size_t          option_idx {0}; | ||||
|     int             outScore {0}; | ||||
| 
 | ||||
|     void get_label(const char** out_text) const; | ||||
|     void get_marked_label_and_tooltip(const char** label, const char** tooltip) const; | ||||
| }; | ||||
| 
 | ||||
| struct OptionViewParameters | ||||
| { | ||||
|     bool type       {false}; | ||||
|     bool category   {false}; | ||||
|     bool group      {true }; | ||||
| 
 | ||||
|     int  hovered_id {-1}; | ||||
| }; | ||||
| 
 | ||||
| class OptionsSearcher | ||||
| { | ||||
|     std::string                             search_line; | ||||
|     std::map<std::string, GroupAndCategory> groups_and_categories; | ||||
| 
 | ||||
|     std::vector<Option>                     options {}; | ||||
|     std::vector<FoundOption>                found {}; | ||||
| 
 | ||||
|     void append_options(DynamicPrintConfig* config, Preset::Type type, ConfigOptionMode mode); | ||||
| 
 | ||||
|     void sort_options() { | ||||
|         std::sort(options.begin(), options.end(), [](const Option& o1, const Option& o2) { | ||||
|             return o1.label < o2.label; }); | ||||
|     } | ||||
|     void sort_found() { | ||||
|         std::sort(found.begin(), found.end(), [](const FoundOption& f1, const FoundOption& f2) { | ||||
|             return f1.outScore > f2.outScore; }); | ||||
|     }; | ||||
| 
 | ||||
|     size_t options_size() const { return options.size(); } | ||||
|     size_t found_size()   const { return found.size(); } | ||||
| 
 | ||||
| public: | ||||
|     OptionViewParameters                    view_params; | ||||
| 
 | ||||
|     SearchDialog*                           search_dialog { nullptr }; | ||||
| 
 | ||||
|     OptionsSearcher(); | ||||
|     ~OptionsSearcher(); | ||||
| 
 | ||||
|     void init(std::vector<InputInfo> input_values); | ||||
|     void apply(DynamicPrintConfig *config, | ||||
|                Preset::Type        type, | ||||
|                ConfigOptionMode    mode); | ||||
|     bool search(); | ||||
|     bool search(const std::string& search, bool force = false); | ||||
| 
 | ||||
|     void add_key(const std::string& opt_key, const wxString& group, const wxString& category); | ||||
| 
 | ||||
|     size_t size() const         { return found_size(); } | ||||
| 
 | ||||
|     const FoundOption& operator[](const size_t pos) const noexcept { return found[pos]; } | ||||
|     const Option& get_option(size_t pos_in_filter) const; | ||||
| 
 | ||||
|     const std::vector<FoundOption>& found_options() { return found; } | ||||
|     const GroupAndCategory&         get_group_and_category (const std::string& opt_key) { return groups_and_categories[opt_key]; } | ||||
|     std::string& search_string() { return search_line; } | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| class SearchComboPopup : public wxListBox, public wxComboPopup | ||||
| { | ||||
| public: | ||||
|     // Initialize member variables
 | ||||
|     void Init(); | ||||
| 
 | ||||
|     // Create popup control
 | ||||
|     virtual bool Create(wxWindow* parent); | ||||
|     // Return pointer to the created control
 | ||||
|     virtual wxWindow* GetControl() { return this; } | ||||
| 
 | ||||
|     // Translate string into a list selection
 | ||||
|     virtual void SetStringValue(const wxString& s); | ||||
|     // Get list selection as a string
 | ||||
|     virtual wxString GetStringValue() const { | ||||
|         // we shouldn't change a combo control's string
 | ||||
|         return m_input_string; | ||||
|     } | ||||
| 
 | ||||
|     void ProcessSelection(int selection); | ||||
| 
 | ||||
|     // Do mouse hot-tracking (which is typical in list popups)
 | ||||
|     void OnMouseMove(wxMouseEvent& event); | ||||
|     // On mouse left up, set the value and close the popup
 | ||||
|     void OnMouseClick(wxMouseEvent& WXUNUSED(event)); | ||||
|     // process Up/Down arrows and Enter press
 | ||||
|     void OnKeyDown(wxKeyEvent& event); | ||||
| 
 | ||||
| protected: | ||||
|     wxString m_input_string; | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| //------------------------------------------
 | ||||
| //          SearchDialog
 | ||||
| //------------------------------------------
 | ||||
| 
 | ||||
| class SearchDialog : public GUI::DPIDialog | ||||
| { | ||||
|     wxString search_str; | ||||
|     wxString default_string; | ||||
| 
 | ||||
|     wxTextCtrl*     search_line    { nullptr }; | ||||
|     wxListBox*      search_list    { nullptr }; | ||||
|     wxCheckBox*     check_type     { nullptr }; | ||||
|     wxCheckBox*     check_category { nullptr }; | ||||
|     wxCheckBox*     check_group    { nullptr }; | ||||
| 
 | ||||
|     OptionsSearcher* searcher; | ||||
| 
 | ||||
|     void update_list(); | ||||
| 
 | ||||
|     void OnInputText(wxCommandEvent& event); | ||||
|     void OnLeftUpInTextCtrl(wxEvent& event); | ||||
|      | ||||
|     void OnMouseMove(wxMouseEvent& event);  | ||||
|     void OnMouseClick(wxMouseEvent& event); | ||||
|     void OnSelect(wxCommandEvent& event); | ||||
|     void OnKeyDown(wxKeyEvent& event); | ||||
| 
 | ||||
|     void OnCheck(wxCommandEvent& event); | ||||
| 
 | ||||
| public: | ||||
|     SearchDialog(OptionsSearcher* searcher); | ||||
|     ~SearchDialog() {} | ||||
| 
 | ||||
|     void Popup(wxPoint position = wxDefaultPosition); | ||||
|     void ProcessSelection(int selection); | ||||
| 
 | ||||
| protected: | ||||
|     void on_dpi_changed(const wxRect& suggested_rect) override; | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| } // Search namespace
 | ||||
| } | ||||
| 
 | ||||
| #endif //slic3r_SearchComboBox_hpp_
 | ||||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -33,6 +33,7 @@ | |||
| #include "Event.hpp" | ||||
| #include "wxExtensions.hpp" | ||||
| #include "ConfigManipulation.hpp" | ||||
| #include "Search.hpp" | ||||
| 
 | ||||
| namespace Slic3r { | ||||
| namespace GUI { | ||||
|  | @ -49,7 +50,7 @@ class Page : public wxScrolledWindow | |||
| 	wxBoxSizer*		m_vsizer; | ||||
|     bool            m_show = true; | ||||
| public: | ||||
|     Page(wxWindow* parent, const wxString title, const int iconID, const std::vector<ScalableBitmap>& mode_bmp_cache) : | ||||
|     Page(wxWindow* parent, const wxString& title, const int iconID, const std::vector<ScalableBitmap>& mode_bmp_cache) : | ||||
| 			m_parent(parent), | ||||
| 			m_title(title), | ||||
| 			m_iconID(iconID), | ||||
|  | @ -121,6 +122,7 @@ protected: | |||
| 	std::string			m_name; | ||||
| 	const wxString		m_title; | ||||
| 	PresetBitmapComboBox*	m_presets_choice; | ||||
| 	ScalableButton*		m_search_btn; | ||||
| 	ScalableButton*		m_btn_save_preset; | ||||
| 	ScalableButton*		m_btn_delete_preset; | ||||
| 	ScalableButton*		m_btn_hide_incompatible_presets; | ||||
|  | @ -221,6 +223,21 @@ protected: | |||
|     bool                m_completed { false }; | ||||
|     ConfigOptionMode    m_mode = comExpert; // to correct first Tab update_visibility() set mode to Expert
 | ||||
| 
 | ||||
| 	struct Highlighter | ||||
| 	{ | ||||
| 		void set_timer_owner(wxEvtHandler* owner, int timerid = wxID_ANY); | ||||
| 		void init(BlinkingBitmap* bmp); | ||||
| 		void blink(); | ||||
| 
 | ||||
| 	private: | ||||
| 		void invalidate(); | ||||
| 
 | ||||
| 		BlinkingBitmap*	bbmp {nullptr}; | ||||
| 		int				blink_counter {0}; | ||||
| 	    wxTimer         timer; | ||||
| 	}  | ||||
|     m_highlighter; | ||||
| 
 | ||||
| public: | ||||
| 	PresetBundle*		m_preset_bundle; | ||||
| 	bool				m_show_btn_incompatible_presets = false; | ||||
|  | @ -233,6 +250,10 @@ public: | |||
|     // Used for options which don't have corresponded field
 | ||||
| 	std::map<std::string, wxStaticText*>	m_colored_Labels; | ||||
| 
 | ||||
| 	// map of option name -> BlinkingBitmap (blinking ikon, associated with option) 
 | ||||
|     // Used for options which don't have corresponded field
 | ||||
| 	std::map<std::string, BlinkingBitmap*>	m_blinking_ikons; | ||||
| 
 | ||||
|     // Counter for the updating (because of an update() function can have a recursive behavior):
 | ||||
|     // 1. increase value from the very beginning of an update() function
 | ||||
|     // 2. decrease value at the end of an update() function
 | ||||
|  | @ -299,6 +320,7 @@ public: | |||
|     void            update_visibility(); | ||||
|     virtual void    msw_rescale(); | ||||
| 	Field*			get_field(const t_config_option_key& opt_key, int opt_index = -1) const; | ||||
|     Field*          get_field(const t_config_option_key &opt_key, Page** selected_page, int opt_index = -1); | ||||
| 	bool			set_value(const t_config_option_key& opt_key, const boost::any& value); | ||||
| 	wxSizer*		description_line_widget(wxWindow* parent, ogStaticText** StaticText); | ||||
| 	bool			current_preset_is_dirty(); | ||||
|  | @ -310,6 +332,8 @@ public: | |||
| 	void			on_value_change(const std::string& opt_key, const boost::any& value); | ||||
| 
 | ||||
|     void            update_wiping_button_visibility(); | ||||
| 	void			activate_option(const std::string& opt_key, const wxString& category); | ||||
|     void			apply_searcher(); | ||||
| 
 | ||||
| protected: | ||||
| 	void			create_line_with_widget(ConfigOptionsGroup* optgroup, const std::string& opt_key, widget_t widget); | ||||
|  |  | |||
							
								
								
									
										223
									
								
								src/slic3r/GUI/fts_fuzzy_match.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										223
									
								
								src/slic3r/GUI/fts_fuzzy_match.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,223 @@ | |||
|   // LICENSE
 | ||||
| //
 | ||||
| //   This software is dual-licensed to the public domain and under the following
 | ||||
| //   license: you are granted a perpetual, irrevocable license to copy, modify,
 | ||||
| //   publish, and distribute this file as you see fit.
 | ||||
| //
 | ||||
| // VERSION 
 | ||||
| //   0.2.0  (2017-02-18)  Scored matches perform exhaustive search for best score
 | ||||
| //   0.1.0  (2016-03-28)  Initial release
 | ||||
| //
 | ||||
| // AUTHOR
 | ||||
| //   Forrest Smith
 | ||||
| //
 | ||||
| // NOTES
 | ||||
| //   Compiling
 | ||||
| //     You MUST add '#define FTS_FUZZY_MATCH_IMPLEMENTATION' before including this header in ONE source file to create implementation.
 | ||||
| //
 | ||||
| //   fuzzy_match_simple(...)
 | ||||
| //     Returns true if each character in pattern is found sequentially within str
 | ||||
| //
 | ||||
| //   fuzzy_match(...)
 | ||||
| //     Returns true if pattern is found AND calculates a score.
 | ||||
| //     Performs exhaustive search via recursion to find all possible matches and match with highest score.
 | ||||
| //     Scores values have no intrinsic meaning. Possible score range is not normalized and varies with pattern.
 | ||||
| //     Recursion is limited internally (default=10) to prevent degenerate cases (pattern="aaaaaa" str="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
 | ||||
| //     Uses uint8_t for match indices. Therefore patterns are limited to 256 characters.
 | ||||
| //     Score system should be tuned for YOUR use case. Words, sentences, file names, or method names all prefer different tuning.
 | ||||
| 
 | ||||
| 
 | ||||
| #ifndef FTS_FUZZY_MATCH_H | ||||
| #define FTS_FUZZY_MATCH_H | ||||
| 
 | ||||
| 
 | ||||
| #include <cstdint> // uint8_t | ||||
| #include <ctype.h> // ::tolower, ::toupper | ||||
| #include <cstring> // memcpy | ||||
| 
 | ||||
| #include <cstdio> | ||||
| 
 | ||||
| // Public interface
 | ||||
| namespace fts { | ||||
|     static bool fuzzy_match_simple(char const * pattern, char const * str); | ||||
|     static bool fuzzy_match(char const * pattern, char const * str, int & outScore); | ||||
|     static bool fuzzy_match(char const * pattern, char const * str, int & outScore, uint8_t * matches, int maxMatches); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| #ifdef FTS_FUZZY_MATCH_IMPLEMENTATION | ||||
| namespace fts { | ||||
| 
 | ||||
|     // Forward declarations for "private" implementation
 | ||||
|     namespace fuzzy_internal { | ||||
|         static bool fuzzy_match_recursive(const char * pattern, const char * str, int & outScore, const char * strBegin,           | ||||
|             uint8_t const * srcMatches,  uint8_t * newMatches,  int maxMatches, int nextMatch,  | ||||
|             int & recursionCount, int recursionLimit); | ||||
|     } | ||||
| 
 | ||||
|     // Public interface
 | ||||
|     static bool fuzzy_match_simple(char const * pattern, char const * str) { | ||||
|         while (*pattern != '\0' && *str != '\0')  { | ||||
|             if (tolower(*pattern) == tolower(*str)) | ||||
|                 ++pattern; | ||||
|             ++str; | ||||
|         } | ||||
| 
 | ||||
|         return *pattern == '\0' ? true : false; | ||||
|     } | ||||
| 
 | ||||
|     static bool fuzzy_match(char const * pattern, char const * str, int & outScore) { | ||||
|          | ||||
|         uint8_t matches[256]; | ||||
|         return fuzzy_match(pattern, str, outScore, matches, sizeof(matches)); | ||||
|     } | ||||
| 
 | ||||
|     static bool fuzzy_match(char const * pattern, char const * str, int & outScore, uint8_t * matches, int maxMatches) { | ||||
|         int recursionCount = 0; | ||||
|         int recursionLimit = 10; | ||||
| 
 | ||||
|         return fuzzy_internal::fuzzy_match_recursive(pattern, str, outScore, str, nullptr, matches, maxMatches, 0, recursionCount, recursionLimit); | ||||
|     } | ||||
| 
 | ||||
|     // Private implementation
 | ||||
|     static bool fuzzy_internal::fuzzy_match_recursive(const char * pattern, const char * str, int & outScore,  | ||||
|         const char * strBegin, uint8_t const * srcMatches, uint8_t * matches, int maxMatches,  | ||||
|         int nextMatch, int & recursionCount, int recursionLimit) | ||||
|     { | ||||
|         // Count recursions
 | ||||
|         ++recursionCount; | ||||
|         if (recursionCount >= recursionLimit) | ||||
|             return false; | ||||
| 
 | ||||
|         // Detect end of strings
 | ||||
|         if (*pattern == '\0' || *str == '\0') | ||||
|             return false; | ||||
| 
 | ||||
|         // Recursion params
 | ||||
|         bool recursiveMatch = false; | ||||
|         uint8_t bestRecursiveMatches[256]; | ||||
|         int bestRecursiveScore = 0; | ||||
| 
 | ||||
|         // Loop through pattern and str looking for a match
 | ||||
|         bool first_match = true; | ||||
|         while (*pattern != '\0' && *str != '\0') { | ||||
|              | ||||
|             // Found match
 | ||||
|             if (tolower(*pattern) == tolower(*str)) { | ||||
| 
 | ||||
|                 // Supplied matches buffer was too short
 | ||||
|                 if (nextMatch >= maxMatches) | ||||
|                     return false; | ||||
|                  | ||||
|                 // "Copy-on-Write" srcMatches into matches
 | ||||
|                 if (first_match && srcMatches) { | ||||
|                     memcpy(matches, srcMatches, nextMatch); | ||||
|                     first_match = false; | ||||
|                 } | ||||
| 
 | ||||
|                 // Recursive call that "skips" this match
 | ||||
|                 uint8_t recursiveMatches[256]; | ||||
|                 int recursiveScore; | ||||
|                 if (fuzzy_match_recursive(pattern, str + 1, recursiveScore, strBegin, matches, recursiveMatches, sizeof(recursiveMatches), nextMatch, recursionCount, recursionLimit)) { | ||||
|                      | ||||
|                     // Pick best recursive score
 | ||||
|                     if (!recursiveMatch || recursiveScore > bestRecursiveScore) { | ||||
|                         memcpy(bestRecursiveMatches, recursiveMatches, 256); | ||||
|                         bestRecursiveScore = recursiveScore; | ||||
|                     } | ||||
|                     recursiveMatch = true; | ||||
|                 } | ||||
| 
 | ||||
|                 // Advance
 | ||||
|                 matches[nextMatch++] = (uint8_t)(str - strBegin); | ||||
|                 ++pattern; | ||||
|             } | ||||
|             ++str; | ||||
|         } | ||||
| 
 | ||||
|         // Determine if full pattern was matched
 | ||||
|         bool matched = *pattern == '\0' ? true : false; | ||||
| 
 | ||||
|         // Calculate score
 | ||||
|         if (matched) { | ||||
|             const int sequential_bonus = 15;            // bonus for adjacent matches
 | ||||
|             const int separator_bonus = 30;             // bonus if match occurs after a separator
 | ||||
|             const int camel_bonus = 30;                 // bonus if match is uppercase and prev is lower
 | ||||
|             const int first_letter_bonus = 15;          // bonus if the first letter is matched
 | ||||
| 
 | ||||
|             const int leading_letter_penalty = -5;      // penalty applied for every letter in str before the first match
 | ||||
|             const int max_leading_letter_penalty = -15; // maximum penalty for leading letters
 | ||||
|             const int unmatched_letter_penalty = -1;    // penalty for every letter that doesn't matter
 | ||||
| 
 | ||||
|             // Iterate str to end
 | ||||
|             while (*str != '\0') | ||||
|                 ++str; | ||||
| 
 | ||||
|             // Initialize score
 | ||||
|             outScore = 100; | ||||
| 
 | ||||
|             // Apply leading letter penalty
 | ||||
|             int penalty = leading_letter_penalty * matches[0]; | ||||
|             if (penalty < max_leading_letter_penalty) | ||||
|                 penalty = max_leading_letter_penalty; | ||||
|             outScore += penalty; | ||||
| 
 | ||||
|             // Apply unmatched penalty
 | ||||
|             int unmatched = (int)(str - strBegin) - nextMatch; | ||||
|             outScore += unmatched_letter_penalty * unmatched; | ||||
| 
 | ||||
|             // Apply ordering bonuses
 | ||||
|             for (int i = 0; i < nextMatch; ++i) { | ||||
|                 uint8_t currIdx = matches[i]; | ||||
| 
 | ||||
|                 if (i > 0) { | ||||
|                     uint8_t prevIdx = matches[i - 1]; | ||||
| 
 | ||||
|                     // Sequential
 | ||||
|                     if (currIdx == (prevIdx + 1)) | ||||
|                         outScore += sequential_bonus; | ||||
|                 } | ||||
| 
 | ||||
|                 // Check for bonuses based on neighbor character value
 | ||||
|                 if (currIdx > 0) { | ||||
|                     // Camel case
 | ||||
|                     // ::islower() expects an unsigned char in range of 0 to 255.
 | ||||
|                     unsigned char uneighbor = ((unsigned char *)strBegin)[currIdx - 1]; | ||||
|                     unsigned char ucurr = ((unsigned char*)strBegin)[currIdx]; | ||||
|                     if (::islower(uneighbor) && ::isupper(ucurr)) | ||||
|                         outScore += camel_bonus; | ||||
| 
 | ||||
|                     // Separator
 | ||||
|                     char neighbor = strBegin[currIdx - 1]; | ||||
|                     bool neighborSeparator = neighbor == '_' || neighbor == ' '; | ||||
|                     if (neighborSeparator) | ||||
|                         outScore += separator_bonus; | ||||
|                 } | ||||
|                 else { | ||||
|                     // First letter
 | ||||
|                     outScore += first_letter_bonus; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // Return best result
 | ||||
|         if (recursiveMatch && (!matched || bestRecursiveScore > outScore)) { | ||||
|             // Recursive score is better than "this"
 | ||||
|             memcpy(matches, bestRecursiveMatches, maxMatches); | ||||
|             outScore = bestRecursiveScore; | ||||
|             return true; | ||||
|         } | ||||
|         else if (matched) { | ||||
|             // "this" score is better than recursive
 | ||||
|             return true; | ||||
|         } | ||||
|         else { | ||||
|             // no match
 | ||||
|             return false; | ||||
|         } | ||||
|     } | ||||
| } // namespace fts
 | ||||
| 
 | ||||
| #endif // FTS_FUZZY_MATCH_IMPLEMENTATION
 | ||||
| 
 | ||||
| #endif // FTS_FUZZY_MATCH_H
 | ||||
|  | @ -943,5 +943,40 @@ void ScalableButton::msw_rescale() | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| // ----------------------------------------------------------------------------
 | ||||
| // BlinkingBitmap
 | ||||
| // ----------------------------------------------------------------------------
 | ||||
| 
 | ||||
| BlinkingBitmap::BlinkingBitmap(wxWindow* parent, const std::string& icon_name) : | ||||
|     wxStaticBitmap(parent, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize(int(1.6 * Slic3r::GUI::wxGetApp().em_unit()), -1)) | ||||
| { | ||||
|     bmp = ScalableBitmap(parent, icon_name); | ||||
| } | ||||
| 
 | ||||
| void BlinkingBitmap::msw_rescale() | ||||
| { | ||||
|     bmp.msw_rescale(); | ||||
|     this->SetSize(bmp.GetBmpSize()); | ||||
|     this->SetMinSize(bmp.GetBmpSize()); | ||||
| } | ||||
| 
 | ||||
| void BlinkingBitmap::invalidate() | ||||
| { | ||||
|     this->SetBitmap(wxNullBitmap); | ||||
| } | ||||
| 
 | ||||
| void BlinkingBitmap::activate() | ||||
| { | ||||
|     this->SetBitmap(bmp.bmp()); | ||||
|     show = true; | ||||
| } | ||||
| 
 | ||||
| void BlinkingBitmap::blink() | ||||
| { | ||||
|     show = !show; | ||||
|     this->SetBitmap(show ? bmp.bmp() : wxNullBitmap); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
Some files were not shown because too many files have changed in this diff Show more
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 YuSanka
						YuSanka