From 0558b53493a77bae44831cf87bb0f59359828ef5 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Wed, 19 Sep 2018 11:02:24 +0200 Subject: [PATCH 001/186] WIP: Moved sources int src/, separated most of the source code from Perl. The XS was left only for the unit / integration tests, and it links libslic3r only. No wxWidgets are allowed to be used from Perl starting from now. --- CMakeLists.txt | 198 +- resources/localization/CMakeLists.txt | 8 + src/CMakeLists.txt | 65 + src/Shiny/CMakeLists.txt | 25 + {xs/src => src}/Shiny/Shiny.h | 0 {xs/src => src}/Shiny/ShinyConfig.h | 0 {xs/src => src}/Shiny/ShinyData.h | 0 {xs/src => src}/Shiny/ShinyMacros.h | 0 {xs/src => src}/Shiny/ShinyManager.c | 0 {xs/src => src}/Shiny/ShinyManager.h | 0 {xs/src => src}/Shiny/ShinyNode.c | 0 {xs/src => src}/Shiny/ShinyNode.h | 0 {xs/src => src}/Shiny/ShinyNodePool.c | 0 {xs/src => src}/Shiny/ShinyNodePool.h | 0 {xs/src => src}/Shiny/ShinyNodeState.c | 0 {xs/src => src}/Shiny/ShinyNodeState.h | 0 {xs/src => src}/Shiny/ShinyOutput.c | 0 {xs/src => src}/Shiny/ShinyOutput.h | 0 {xs/src => src}/Shiny/ShinyPrereqs.h | 0 {xs/src => src}/Shiny/ShinyTools.c | 0 {xs/src => src}/Shiny/ShinyTools.h | 0 {xs/src => src}/Shiny/ShinyVersion.h | 0 {xs/src => src}/Shiny/ShinyZone.c | 0 {xs/src => src}/Shiny/ShinyZone.h | 0 src/admesh/CMakeLists.txt | 12 + {xs/src => src}/admesh/connect.cpp | 0 {xs/src => src}/admesh/normals.cpp | 0 {xs/src => src}/admesh/shared.cpp | 0 {xs/src => src}/admesh/stl.h | 0 {xs/src => src}/admesh/stl_io.cpp | 0 {xs/src => src}/admesh/stlinit.cpp | 0 {xs/src => src}/admesh/util.cpp | 0 {xs/src => src}/agg/AUTHORS | 0 {xs/src => src}/agg/VERSION | 0 {xs/src => src}/agg/agg_array.h | 0 {xs/src => src}/agg/agg_basics.h | 0 {xs/src => src}/agg/agg_bezier_arc.h | 0 {xs/src => src}/agg/agg_clip_liang_barsky.h | 0 {xs/src => src}/agg/agg_color_gray.h | 0 {xs/src => src}/agg/agg_color_rgba.h | 0 {xs/src => src}/agg/agg_config.h | 0 {xs/src => src}/agg/agg_conv_transform.h | 0 {xs/src => src}/agg/agg_gamma_functions.h | 0 {xs/src => src}/agg/agg_gamma_lut.h | 0 {xs/src => src}/agg/agg_math.h | 0 {xs/src => src}/agg/agg_path_storage.h | 0 {xs/src => src}/agg/agg_pixfmt_base.h | 0 {xs/src => src}/agg/agg_pixfmt_gray.h | 0 {xs/src => src}/agg/agg_pixfmt_rgb.h | 0 {xs/src => src}/agg/agg_rasterizer_cells_aa.h | 0 .../agg/agg_rasterizer_scanline_aa.h | 0 .../agg/agg_rasterizer_scanline_aa_nogamma.h | 0 {xs/src => src}/agg/agg_rasterizer_sl_clip.h | 0 {xs/src => src}/agg/agg_renderer_base.h | 0 {xs/src => src}/agg/agg_renderer_scanline.h | 0 {xs/src => src}/agg/agg_rendering_buffer.h | 0 {xs/src => src}/agg/agg_scanline_p.h | 0 {xs/src => src}/agg/agg_trans_affine.h | 0 {xs/src => src}/agg/copying | 0 {xs/src => src}/avrdude/AUTHORS | 0 {xs/src => src}/avrdude/BUILD-FROM-SVN | 0 {xs/src => src}/avrdude/CMakeLists.txt | 0 {xs/src => src}/avrdude/COPYING | 0 {xs/src => src}/avrdude/ChangeLog | 0 {xs/src => src}/avrdude/ChangeLog-2001 | 0 {xs/src => src}/avrdude/ChangeLog-2002 | 0 {xs/src => src}/avrdude/ChangeLog-2003 | 0 {xs/src => src}/avrdude/ChangeLog-2004-2006 | 0 {xs/src => src}/avrdude/ChangeLog-2007 | 0 {xs/src => src}/avrdude/ChangeLog-2008 | 0 {xs/src => src}/avrdude/ChangeLog-2009 | 0 {xs/src => src}/avrdude/ChangeLog-2010 | 0 {xs/src => src}/avrdude/ChangeLog-2011 | 0 {xs/src => src}/avrdude/ChangeLog-2012 | 0 {xs/src => src}/avrdude/ChangeLog-2013 | 0 {xs/src => src}/avrdude/ChangeLog-2014 | 0 {xs/src => src}/avrdude/ChangeLog-2015 | 0 {xs/src => src}/avrdude/Makefile.am | 0 {xs/src => src}/avrdude/Makefile.standalone | 0 {xs/src => src}/avrdude/NEWS | 0 {xs/src => src}/avrdude/README | 0 {xs/src => src}/avrdude/ac_cfg.h | 0 {xs/src => src}/avrdude/ac_cfg.h.in | 0 {xs/src => src}/avrdude/arduino.c | 0 {xs/src => src}/avrdude/arduino.h | 0 {xs/src => src}/avrdude/atmel-docs/AVR109.pdf | Bin {xs/src => src}/avrdude/atmel-docs/AVR910.pdf | Bin .../avrdude/atmel-docs/AVRISPmkII-AVR069.pdf | Bin .../atmel-docs/EDBG/common/browserDetect.js | 0 .../atmel-docs/EDBG/common/css/960.css | 0 .../atmel-docs/EDBG/common/css/docbook.css | 0 .../atmel-docs/EDBG/common/css/fluid_grid.css | 0 .../atmel-docs/EDBG/common/css/index.css | 0 .../EDBG/common/css/positioning.css | 0 .../atmel-docs/EDBG/common/css/print.css | 0 .../atmel-docs/EDBG/common/css/reset.css | 0 .../atmel-docs/EDBG/common/css/text.css | 0 .../EDBG/common/fonts/DroidSansMono.eot | Bin .../EDBG/common/fonts/DroidSansMono.ttf | Bin .../EDBG/common/images/Book_Closed.png | Bin .../EDBG/common/images/Book_Open.png | Bin .../EDBG/common/images/Document_Text.png | Bin .../atmel-docs/EDBG/common/images/Library.png | Bin .../EDBG/common/images/external_link.gif | Bin .../atmel-docs/EDBG/common/images/loading.gif | Bin .../atmel-docs/EDBG/common/images/logo.png | Bin .../atmel-docs/EDBG/common/images/minus.png | Bin .../EDBG/common/images/next-arrow.png | Bin .../atmel-docs/EDBG/common/images/plus.png | Bin .../EDBG/common/images/previous-arrow.png | Bin .../EDBG/common/images/search-icon.png | Bin .../atmel-docs/EDBG/common/images/sidebar.png | Bin .../EDBG/common/images/starsSmall.png | Bin .../EDBG/common/images/toc-icon.png | Bin .../common/images/ui-icons_217bc0_256x240.png | Bin .../EDBG/common/jquery/jquery-1.7.2.min.js | 0 .../EDBG/common/jquery/jquery.cookie.js | 0 .../EDBG/common/jquery/jquery.ui.all.js | 0 .../common/jquery/layout/jquery.layout.js | 0 .../images/ui-anim_basic_16x16.gif | Bin .../images/ui-bg_flat_0_aaaaaa_40x100.png | Bin .../images/ui-bg_flat_55_fbec88_40x100.png | Bin .../images/ui-bg_glass_75_d0e5f5_1x400.png | Bin .../images/ui-bg_glass_85_dfeffc_1x400.png | Bin .../images/ui-bg_glass_95_fef1ec_1x400.png | Bin .../ui-bg_gloss-wave_55_5c9ccc_500x100.png | Bin .../ui-bg_inset-hard_100_f5f8f9_1x100.png | Bin .../ui-bg_inset-hard_100_fcfdfd_1x100.png | Bin .../images/ui-icons_217bc0_256x240.png | Bin .../images/ui-icons_2e83ff_256x240.png | Bin .../images/ui-icons_469bdd_256x240.png | Bin .../images/ui-icons_6da8d5_256x240.png | Bin .../images/ui-icons_cd0a0a_256x240.png | Bin .../images/ui-icons_d8e7f3_256x240.png | Bin .../images/ui-icons_f9bd01_256x240.png | Bin .../theme-redmond/jquery-ui-1.8.2.custom.css | 0 .../common/jquery/treeview/images/file.gif | Bin .../jquery/treeview/images/folder-closed.gif | Bin .../common/jquery/treeview/images/folder.gif | Bin .../treeview/images/treeview-black-line.gif | Bin .../jquery/treeview/images/treeview-black.gif | Bin .../treeview/images/treeview-default-line.gif | Bin .../treeview/images/treeview-default.gif | Bin .../images/treeview-famfamfam-line.gif | Bin .../treeview/images/treeview-famfamfam.gif | Bin .../treeview/images/treeview-gray-line.gif | Bin .../jquery/treeview/images/treeview-gray.gif | Bin .../treeview/images/treeview-red-line.gif | Bin .../jquery/treeview/images/treeview-red.gif | Bin .../jquery/treeview/jquery.treeview.css | 0 .../jquery/treeview/jquery.treeview.min.js | 0 .../avrdude/atmel-docs/EDBG/common/main.js | 0 .../atmel-docs/EDBG/common/splitterInit.js | 0 .../atmel-docs/EDBG/protocoldocs/ch01s01.html | 0 .../atmel-docs/EDBG/protocoldocs/ch01s02.html | 0 .../atmel-docs/EDBG/protocoldocs/ch02s01.html | 0 .../atmel-docs/EDBG/protocoldocs/ch02s02.html | 0 .../EDBG/protocoldocs/ch02s02s01.html | 0 .../EDBG/protocoldocs/ch02s02s02.html | 0 .../EDBG/protocoldocs/ch02s02s02s01.html | 0 .../EDBG/protocoldocs/ch02s02s02s02.html | 0 .../EDBG/protocoldocs/ch02s02s03.html | 0 .../EDBG/protocoldocs/ch02s02s03s01.html | 0 .../EDBG/protocoldocs/ch02s02s03s02.html | 0 .../EDBG/protocoldocs/ch02s02s03s03.html | 0 .../EDBG/protocoldocs/ch02s02s03s04.html | 0 .../EDBG/protocoldocs/ch02s03s01.html | 0 .../EDBG/protocoldocs/ch02s03s02.html | 0 .../EDBG/protocoldocs/ch02s03s03.html | 0 .../EDBG/protocoldocs/ch02s03s04.html | 0 .../EDBG/protocoldocs/ch02s03s05.html | 0 .../EDBG/protocoldocs/ch02s03s06.html | 0 .../EDBG/protocoldocs/ch02s03s07.html | 0 .../EDBG/protocoldocs/ch02s03s08.html | 0 .../EDBG/protocoldocs/ch02s03s09.html | 0 .../atmel-docs/EDBG/protocoldocs/ch02s04.html | 0 .../EDBG/protocoldocs/ch02s04s01.html | 0 .../EDBG/protocoldocs/ch02s04s02.html | 0 .../EDBG/protocoldocs/ch02s04s03.html | 0 .../atmel-docs/EDBG/protocoldocs/ch03s01.html | 0 .../EDBG/protocoldocs/ch03s01s01.html | 0 .../EDBG/protocoldocs/ch03s01s02.html | 0 .../EDBG/protocoldocs/ch03s01s03.html | 0 .../EDBG/protocoldocs/ch03s01s03s01.html | 0 .../atmel-docs/EDBG/protocoldocs/ch03s02.html | 0 .../EDBG/protocoldocs/ch03s02s01.html | 0 .../EDBG/protocoldocs/ch03s02s02.html | 0 .../EDBG/protocoldocs/ch03s02s03.html | 0 .../EDBG/protocoldocs/ch03s02s04.html | 0 .../atmel-docs/EDBG/protocoldocs/ch04s01.html | 0 .../atmel-docs/EDBG/protocoldocs/ch04s02.html | 0 .../atmel-docs/EDBG/protocoldocs/ch04s03.html | 0 .../atmel-docs/EDBG/protocoldocs/ch04s04.html | 0 .../EDBG/protocoldocs/ch04s04s01.html | 0 .../EDBG/protocoldocs/ch04s04s03.html | 0 .../EDBG/protocoldocs/ch04s04s04.html | 0 .../EDBG/protocoldocs/ch04s04s05.html | 0 .../atmel-docs/EDBG/protocoldocs/ch04s05.html | 0 .../EDBG/protocoldocs/ch04s05s01.html | 0 .../EDBG/protocoldocs/ch04s05s03.html | 0 .../EDBG/protocoldocs/ch04s05s04.html | 0 .../EDBG/protocoldocs/ch04s05s06.html | 0 .../EDBG/protocoldocs/ch04s05s06s02.html | 0 .../EDBG/protocoldocs/ch04s05s06s03.html | 0 .../EDBG/protocoldocs/ch04s05s06s04.html | 0 .../EDBG/protocoldocs/ch04s05s06s05.html | 0 .../EDBG/protocoldocs/ch04s05s07.html | 0 .../EDBG/protocoldocs/ch04s05s07s01.html | 0 .../EDBG/protocoldocs/ch04s05s07s02.html | 0 .../EDBG/protocoldocs/ch04s05s07s03.html | 0 .../EDBG/protocoldocs/ch04s05s07s04.html | 0 .../EDBG/protocoldocs/ch04s05s08.html | 0 .../EDBG/protocoldocs/ch04s05s08s01.html | 0 .../EDBG/protocoldocs/ch04s05s08s02.html | 0 .../EDBG/protocoldocs/ch04s05s08s03.html | 0 .../EDBG/protocoldocs/ch04s05s09.html | 0 .../EDBG/protocoldocs/ch04s05s10.html | 0 .../atmel-docs/EDBG/protocoldocs/ch05s01.html | 0 .../EDBG/protocoldocs/ch05s01s01.html | 0 .../EDBG/protocoldocs/ch05s01s02.html | 0 .../EDBG/protocoldocs/ch05s01s03.html | 0 .../EDBG/protocoldocs/ch05s01s04.html | 0 .../EDBG/protocoldocs/ch05s01s05.html | 0 .../EDBG/protocoldocs/ch05s01s06.html | 0 .../EDBG/protocoldocs/ch05s01s07.html | 0 .../EDBG/protocoldocs/ch05s01s08.html | 0 .../EDBG/protocoldocs/ch05s01s09.html | 0 .../EDBG/protocoldocs/ch05s01s10.html | 0 .../EDBG/protocoldocs/ch05s01s11.html | 0 .../EDBG/protocoldocs/ch05s01s12.html | 0 .../EDBG/protocoldocs/ch05s01s13.html | 0 .../EDBG/protocoldocs/ch05s01s14.html | 0 .../EDBG/protocoldocs/ch05s01s15.html | 0 .../atmel-docs/EDBG/protocoldocs/ch05s02.html | 0 .../EDBG/protocoldocs/ch05s02s01.html | 0 .../EDBG/protocoldocs/ch05s02s02.html | 0 .../EDBG/protocoldocs/ch05s02s03.html | 0 .../EDBG/protocoldocs/ch05s02s04.html | 0 .../EDBG/protocoldocs/ch05s02s05.html | 0 .../EDBG/protocoldocs/ch05s02s06.html | 0 .../atmel-docs/EDBG/protocoldocs/ch05s03.html | 0 .../EDBG/protocoldocs/ch05s03s01.html | 0 .../EDBG/protocoldocs/ch05s03s02.html | 0 .../EDBG/protocoldocs/ch05s03s03.html | 0 .../atmel-docs/EDBG/protocoldocs/ch05s04.html | 0 .../atmel-docs/EDBG/protocoldocs/ch06s01.html | 0 .../EDBG/protocoldocs/ch06s01s01.html | 0 .../EDBG/protocoldocs/ch06s01s02.html | 0 .../EDBG/protocoldocs/ch06s01s03.html | 0 .../EDBG/protocoldocs/ch06s01s04.html | 0 .../EDBG/protocoldocs/ch06s01s05.html | 0 .../EDBG/protocoldocs/ch06s01s06.html | 0 .../EDBG/protocoldocs/ch06s01s07.html | 0 .../EDBG/protocoldocs/ch06s01s08.html | 0 .../EDBG/protocoldocs/ch06s01s09.html | 0 .../EDBG/protocoldocs/ch06s01s10.html | 0 .../EDBG/protocoldocs/ch06s01s11.html | 0 .../EDBG/protocoldocs/ch06s01s12.html | 0 .../EDBG/protocoldocs/ch06s01s13.html | 0 .../EDBG/protocoldocs/ch06s01s14.html | 0 .../EDBG/protocoldocs/ch06s01s15.html | 0 .../EDBG/protocoldocs/ch06s01s16.html | 0 .../EDBG/protocoldocs/ch06s01s17.html | 0 .../EDBG/protocoldocs/ch06s01s18.html | 0 .../EDBG/protocoldocs/ch06s01s19.html | 0 .../EDBG/protocoldocs/ch06s01s20.html | 0 .../EDBG/protocoldocs/ch06s01s21.html | 0 .../EDBG/protocoldocs/ch06s01s22.html | 0 .../EDBG/protocoldocs/ch06s01s23.html | 0 .../EDBG/protocoldocs/ch06s01s24.html | 0 .../EDBG/protocoldocs/ch06s01s25.html | 0 .../EDBG/protocoldocs/ch06s01s26.html | 0 .../EDBG/protocoldocs/ch06s01s27.html | 0 .../EDBG/protocoldocs/ch06s01s28.html | 0 .../EDBG/protocoldocs/ch06s01s29.html | 0 .../atmel-docs/EDBG/protocoldocs/ch06s02.html | 0 .../EDBG/protocoldocs/ch06s02s01.html | 0 .../EDBG/protocoldocs/ch06s02s02.html | 0 .../EDBG/protocoldocs/ch06s02s03.html | 0 .../EDBG/protocoldocs/ch06s02s04.html | 0 .../EDBG/protocoldocs/ch06s02s05.html | 0 .../atmel-docs/EDBG/protocoldocs/ch06s03.html | 0 .../EDBG/protocoldocs/ch06s03s01.html | 0 .../EDBG/protocoldocs/ch06s03s02.html | 0 .../EDBG/protocoldocs/ch06s04s01.html | 0 .../EDBG/protocoldocs/ch06s04s02.html | 0 .../EDBG/protocoldocs/ch06s04s03.html | 0 .../atmel-docs/EDBG/protocoldocs/ch06s05.html | 0 .../EDBG/protocoldocs/ch06s05s01.html | 0 .../EDBG/protocoldocs/ch06s05s02.html | 0 .../EDBG/protocoldocs/ch06s05s03.html | 0 .../EDBG/protocoldocs/ch06s05s04.html | 0 .../EDBG/protocoldocs/ch06s05s05.html | 0 .../atmel-docs/EDBG/protocoldocs/ch06s06.html | 0 .../atmel-docs/EDBG/protocoldocs/ch07s01.html | 0 .../EDBG/protocoldocs/ch07s01s01.html | 0 .../EDBG/protocoldocs/ch07s01s02.html | 0 .../EDBG/protocoldocs/ch07s01s03.html | 0 .../EDBG/protocoldocs/ch07s01s04.html | 0 .../EDBG/protocoldocs/ch07s01s05.html | 0 .../EDBG/protocoldocs/ch07s01s06.html | 0 .../EDBG/protocoldocs/ch07s01s07.html | 0 .../EDBG/protocoldocs/ch07s01s08.html | 0 .../EDBG/protocoldocs/ch07s01s09.html | 0 .../EDBG/protocoldocs/ch07s01s10.html | 0 .../EDBG/protocoldocs/ch07s01s11.html | 0 .../EDBG/protocoldocs/ch07s01s12.html | 0 .../EDBG/protocoldocs/ch07s01s13.html | 0 .../EDBG/protocoldocs/ch07s01s14.html | 0 .../EDBG/protocoldocs/ch07s01s15.html | 0 .../EDBG/protocoldocs/ch07s01s16.html | 0 .../EDBG/protocoldocs/ch07s01s17.html | 0 .../atmel-docs/EDBG/protocoldocs/ch07s02.html | 0 .../atmel-docs/EDBG/protocoldocs/ch07s03.html | 0 .../atmel-docs/EDBG/protocoldocs/ch08s01.html | 0 .../EDBG/protocoldocs/ch08s01s01.html | 0 .../EDBG/protocoldocs/ch08s01s02.html | 0 .../EDBG/protocoldocs/ch08s01s03.html | 0 .../EDBG/protocoldocs/ch08s01s04.html | 0 .../EDBG/protocoldocs/ch08s01s05.html | 0 .../EDBG/protocoldocs/ch08s01s06.html | 0 .../atmel-docs/EDBG/protocoldocs/ch08s02.html | 0 .../atmel-docs/EDBG/protocoldocs/ch08s03.html | 0 .../EDBG/protocoldocs/document.revisions.html | 0 .../atmel-docs/EDBG/protocoldocs/index.html | 0 .../atmel-docs/EDBG/protocoldocs/pr01.html | 0 .../protocoldocs.Introduction.html | 0 .../protocoldocs.avr32protocol.html | 0 .../protocoldocs.avr8protocol.html | 0 .../protocoldocs.avrispprotocol.html | 0 .../protocoldocs.avrprotocol.Overview.html | 0 .../protocoldocs/protocoldocs.cmsis_dap.html | 0 .../protocoldocs.edbg_ctrl_protocol.html | 0 .../protocoldocs.tpiprotocol.html | 0 .../protocoldocs/search/htmlFileInfoList.js | 0 .../EDBG/protocoldocs/search/index-1.js | 0 .../EDBG/protocoldocs/search/index-2.js | 0 .../EDBG/protocoldocs/search/index-3.js | 0 .../EDBG/protocoldocs/search/l10n.js | 0 .../EDBG/protocoldocs/search/nwSearchFnt.js | 0 .../search/stemmers/en_stemmer.js | 0 .../protocoldocs/section_avr32_memtypes.html | 0 .../section_avr32_setget_params.html | 0 .../protocoldocs/section_avr8_memtypes.html | 0 .../section_avr8_query_contexts.html | 0 .../section_avr8_setget_params.html | 0 .../section_edbg_ctrl_setget_params.html | 0 .../section_edbg_query_contexts.html | 0 .../section_housekeeping_start_session.html | 0 .../EDBG/protocoldocs/section_i5v_3yz_rl.html | 0 .../EDBG/protocoldocs/section_jdx_m11_sl.html | 0 .../EDBG/protocoldocs/section_qhb_x1c_sl.html | 0 .../protocoldocs/section_serial_trace.html | 0 .../EDBG/protocoldocs/section_t1f_hb1_sl.html | 0 .../avrdude/atmel-docs/JTAGICE-AVR060.pdf | Bin .../avrdude/atmel-docs/JTAGICEmkII-AVR067.pdf | Bin .../avrdude/atmel-docs/STK500-AVR061.pdf | Bin .../avrdude/atmel-docs/STK500v2-AVR068.pdf | Bin {xs/src => src}/avrdude/avr.c | 0 {xs/src => src}/avrdude/avr910.c | 0 {xs/src => src}/avrdude/avr910.h | 0 {xs/src => src}/avrdude/avrdude-slic3r.cpp | 0 {xs/src => src}/avrdude/avrdude-slic3r.hpp | 0 {xs/src => src}/avrdude/avrdude.1 | 0 {xs/src => src}/avrdude/avrdude.conf | 0 {xs/src => src}/avrdude/avrdude.conf.in | 0 {xs/src => src}/avrdude/avrdude.conf.tmp | 0 {xs/src => src}/avrdude/avrdude.h | 0 {xs/src => src}/avrdude/avrdude.spec.in | 0 {xs/src => src}/avrdude/avrftdi.c | 0 {xs/src => src}/avrdude/avrftdi.h | 0 {xs/src => src}/avrdude/avrftdi_private.h | 0 {xs/src => src}/avrdude/avrftdi_tpi.c | 0 {xs/src => src}/avrdude/avrftdi_tpi.h | 0 {xs/src => src}/avrdude/avrpart.c | 0 {xs/src => src}/avrdude/bitbang.c | 0 {xs/src => src}/avrdude/bitbang.h | 0 {xs/src => src}/avrdude/bootstrap | 0 {xs/src => src}/avrdude/buspirate.c | 0 {xs/src => src}/avrdude/buspirate.h | 0 {xs/src => src}/avrdude/butterfly.c | 0 {xs/src => src}/avrdude/butterfly.h | 0 {xs/src => src}/avrdude/config.c | 0 {xs/src => src}/avrdude/config.h | 0 {xs/src => src}/avrdude/config_gram.c | 0 {xs/src => src}/avrdude/config_gram.h | 0 {xs/src => src}/avrdude/config_gram.y | 0 {xs/src => src}/avrdude/configure.ac | 0 {xs/src => src}/avrdude/confwin.c | 0 {xs/src => src}/avrdude/crc16.c | 0 {xs/src => src}/avrdude/crc16.h | 0 {xs/src => src}/avrdude/dfu.c | 0 {xs/src => src}/avrdude/dfu.h | 0 {xs/src => src}/avrdude/doc/.cvsignore | 0 {xs/src => src}/avrdude/doc/Makefile.am | 0 {xs/src => src}/avrdude/doc/TODO | 0 {xs/src => src}/avrdude/doc/avrdude.texi | 0 .../avrdude/doc/parts_comments.txt | 0 {xs/src => src}/avrdude/fileio.c | 0 {xs/src => src}/avrdude/flip1.c | 0 {xs/src => src}/avrdude/flip1.h | 0 {xs/src => src}/avrdude/flip2.c | 0 {xs/src => src}/avrdude/flip2.h | 0 {xs/src => src}/avrdude/freebsd_ppi.h | 0 {xs/src => src}/avrdude/ft245r.c | 0 {xs/src => src}/avrdude/ft245r.h | 0 {xs/src => src}/avrdude/jtag3.c | 0 {xs/src => src}/avrdude/jtag3.h | 0 {xs/src => src}/avrdude/jtag3_private.h | 0 {xs/src => src}/avrdude/jtagmkI.c | 0 {xs/src => src}/avrdude/jtagmkI.h | 0 {xs/src => src}/avrdude/jtagmkII.c | 0 {xs/src => src}/avrdude/jtagmkII.h | 0 {xs/src => src}/avrdude/jtagmkII_private.h | 0 {xs/src => src}/avrdude/jtagmkI_private.h | 0 {xs/src => src}/avrdude/lexer.c | 0 {xs/src => src}/avrdude/lexer.l | 0 {xs/src => src}/avrdude/libavrdude.h | 0 {xs/src => src}/avrdude/linux_ppdev.h | 0 {xs/src => src}/avrdude/linuxgpio.c | 0 {xs/src => src}/avrdude/linuxgpio.h | 0 {xs/src => src}/avrdude/lists.c | 0 {xs/src => src}/avrdude/main-standalone.c | 0 {xs/src => src}/avrdude/main.c | 0 {xs/src => src}/avrdude/my_ddk_hidsdi.h | 0 {xs/src => src}/avrdude/par.c | 0 {xs/src => src}/avrdude/par.h | 0 {xs/src => src}/avrdude/pgm.c | 0 {xs/src => src}/avrdude/pgm_type.c | 0 {xs/src => src}/avrdude/pickit2.c | 0 {xs/src => src}/avrdude/pickit2.h | 0 {xs/src => src}/avrdude/pindefs.c | 0 {xs/src => src}/avrdude/ppi.c | 0 {xs/src => src}/avrdude/ppi.h | 0 {xs/src => src}/avrdude/ppiwin.c | 0 {xs/src => src}/avrdude/safemode.c | 0 {xs/src => src}/avrdude/ser_avrdoper.c | 0 {xs/src => src}/avrdude/ser_posix.c | 0 {xs/src => src}/avrdude/ser_win32.c | 0 {xs/src => src}/avrdude/serbb.h | 0 {xs/src => src}/avrdude/serbb_posix.c | 0 {xs/src => src}/avrdude/serbb_win32.c | 0 {xs/src => src}/avrdude/solaris_ecpp.h | 0 {xs/src => src}/avrdude/stk500.c | 0 {xs/src => src}/avrdude/stk500.h | 0 {xs/src => src}/avrdude/stk500_private.h | 0 {xs/src => src}/avrdude/stk500generic.c | 0 {xs/src => src}/avrdude/stk500generic.h | 0 {xs/src => src}/avrdude/stk500v2.c | 0 {xs/src => src}/avrdude/stk500v2.h | 0 {xs/src => src}/avrdude/stk500v2_private.h | 0 {xs/src => src}/avrdude/term.c | 0 {xs/src => src}/avrdude/term.h | 0 .../avrdude/tools/build-mingw32.sh | 0 .../avrdude/tools/get-dw-params.xsl | 0 .../avrdude/tools/get-hv-params.xsl | 0 .../avrdude/tools/get-stk600-cards.xsl | 0 .../avrdude/tools/get-stk600-devices.xsl | 0 {xs/src => src}/avrdude/tpi.h | 0 {xs/src => src}/avrdude/update.c | 0 {xs/src => src}/avrdude/usb_hidapi.c | 0 {xs/src => src}/avrdude/usb_libusb.c | 0 {xs/src => src}/avrdude/usbasp.c | 0 {xs/src => src}/avrdude/usbasp.h | 0 {xs/src => src}/avrdude/usbdevs.h | 0 {xs/src => src}/avrdude/usbtiny.c | 0 {xs/src => src}/avrdude/usbtiny.h | 0 {xs/src => src}/avrdude/windows/.cvsignore | 0 {xs/src => src}/avrdude/windows/Makefile.am | 0 {xs/src => src}/avrdude/windows/getopt.c | 0 {xs/src => src}/avrdude/windows/getopt.h | 0 {xs/src => src}/avrdude/windows/giveio.c | 0 {xs/src => src}/avrdude/windows/giveio.sys | Bin .../avrdude/windows/install_giveio.bat | 0 {xs/src => src}/avrdude/windows/loaddrv.c | 0 {xs/src => src}/avrdude/windows/loaddrv.h | 0 .../avrdude/windows/remove_giveio.bat | 0 .../avrdude/windows/status_giveio.bat | 0 {xs/src => src}/avrdude/windows/unistd.cpp | 0 {xs/src => src}/avrdude/windows/unistd.h | 0 {xs/src => src}/avrdude/wiring.c | 0 {xs/src => src}/avrdude/wiring.h | 0 src/boost/CMakeLists.txt | 20 + {xs/src => src}/boost/nowide/args.hpp | 0 {xs/src => src}/boost/nowide/cenv.hpp | 0 {xs/src => src}/boost/nowide/config.hpp | 0 {xs/src => src}/boost/nowide/convert.hpp | 0 {xs/src => src}/boost/nowide/cstdio.hpp | 0 {xs/src => src}/boost/nowide/cstdlib.hpp | 0 {xs/src => src}/boost/nowide/filebuf.hpp | 0 {xs/src => src}/boost/nowide/fstream.hpp | 0 .../boost/nowide/integration/filesystem.hpp | 0 {xs/src => src}/boost/nowide/iostream.cpp | 0 {xs/src => src}/boost/nowide/iostream.hpp | 0 {xs/src => src}/boost/nowide/stackstring.hpp | 0 {xs/src => src}/boost/nowide/system.hpp | 0 {xs/src => src}/boost/nowide/utf8_codecvt.hpp | 0 {xs/src => src}/boost/nowide/windows.hpp | 0 src/clipper/CMakeLists.txt | 7 + {xs/src => src/clipper}/clipper.cpp | 8360 ++++++++--------- {xs/src => src/clipper}/clipper.hpp | 974 +- {xs/src => src}/eigen/COPYING.README | 0 {xs/src => src}/eigen/Eigen/CMakeLists.txt | 0 {xs/src => src}/eigen/Eigen/Cholesky | 0 {xs/src => src}/eigen/Eigen/CholmodSupport | 0 {xs/src => src}/eigen/Eigen/Core | 0 {xs/src => src}/eigen/Eigen/Dense | 0 {xs/src => src}/eigen/Eigen/Eigen | 0 {xs/src => src}/eigen/Eigen/Eigenvalues | 0 {xs/src => src}/eigen/Eigen/Geometry | 0 {xs/src => src}/eigen/Eigen/Householder | 0 .../eigen/Eigen/IterativeLinearSolvers | 0 {xs/src => src}/eigen/Eigen/Jacobi | 0 {xs/src => src}/eigen/Eigen/LU | 0 {xs/src => src}/eigen/Eigen/MetisSupport | 0 {xs/src => src}/eigen/Eigen/OrderingMethods | 0 {xs/src => src}/eigen/Eigen/PaStiXSupport | 0 {xs/src => src}/eigen/Eigen/PardisoSupport | 0 {xs/src => src}/eigen/Eigen/QR | 0 {xs/src => src}/eigen/Eigen/QtAlignedMalloc | 0 {xs/src => src}/eigen/Eigen/SPQRSupport | 0 {xs/src => src}/eigen/Eigen/SVD | 0 {xs/src => src}/eigen/Eigen/Sparse | 0 {xs/src => src}/eigen/Eigen/SparseCholesky | 0 {xs/src => src}/eigen/Eigen/SparseCore | 0 {xs/src => src}/eigen/Eigen/SparseLU | 0 {xs/src => src}/eigen/Eigen/SparseQR | 0 {xs/src => src}/eigen/Eigen/StdDeque | 0 {xs/src => src}/eigen/Eigen/StdList | 0 {xs/src => src}/eigen/Eigen/StdVector | 0 {xs/src => src}/eigen/Eigen/SuperLUSupport | 0 {xs/src => src}/eigen/Eigen/UmfPackSupport | 0 .../eigen/Eigen/src/Cholesky/LDLT.h | 0 .../eigen/Eigen/src/Cholesky/LLT.h | 0 .../eigen/Eigen/src/Cholesky/LLT_LAPACKE.h | 0 .../Eigen/src/CholmodSupport/CholmodSupport.h | 0 {xs/src => src}/eigen/Eigen/src/Core/Array.h | 0 .../eigen/Eigen/src/Core/ArrayBase.h | 0 .../eigen/Eigen/src/Core/ArrayWrapper.h | 0 {xs/src => src}/eigen/Eigen/src/Core/Assign.h | 0 .../eigen/Eigen/src/Core/AssignEvaluator.h | 0 .../eigen/Eigen/src/Core/Assign_MKL.h | 0 .../eigen/Eigen/src/Core/BandMatrix.h | 0 {xs/src => src}/eigen/Eigen/src/Core/Block.h | 0 .../eigen/Eigen/src/Core/BooleanRedux.h | 0 .../eigen/Eigen/src/Core/CommaInitializer.h | 0 .../eigen/Eigen/src/Core/ConditionEstimator.h | 0 .../eigen/Eigen/src/Core/CoreEvaluators.h | 0 .../eigen/Eigen/src/Core/CoreIterators.h | 0 .../eigen/Eigen/src/Core/CwiseBinaryOp.h | 0 .../eigen/Eigen/src/Core/CwiseNullaryOp.h | 0 .../eigen/Eigen/src/Core/CwiseTernaryOp.h | 0 .../eigen/Eigen/src/Core/CwiseUnaryOp.h | 0 .../eigen/Eigen/src/Core/CwiseUnaryView.h | 0 .../eigen/Eigen/src/Core/DenseBase.h | 0 .../eigen/Eigen/src/Core/DenseCoeffsBase.h | 0 .../eigen/Eigen/src/Core/DenseStorage.h | 0 .../eigen/Eigen/src/Core/Diagonal.h | 0 .../eigen/Eigen/src/Core/DiagonalMatrix.h | 0 .../eigen/Eigen/src/Core/DiagonalProduct.h | 0 {xs/src => src}/eigen/Eigen/src/Core/Dot.h | 0 .../eigen/Eigen/src/Core/EigenBase.h | 0 .../eigen/Eigen/src/Core/ForceAlignedAccess.h | 0 {xs/src => src}/eigen/Eigen/src/Core/Fuzzy.h | 0 .../eigen/Eigen/src/Core/GeneralProduct.h | 0 .../eigen/Eigen/src/Core/GenericPacketMath.h | 0 .../eigen/Eigen/src/Core/GlobalFunctions.h | 0 {xs/src => src}/eigen/Eigen/src/Core/IO.h | 0 .../eigen/Eigen/src/Core/Inverse.h | 0 {xs/src => src}/eigen/Eigen/src/Core/Map.h | 0 .../eigen/Eigen/src/Core/MapBase.h | 0 .../eigen/Eigen/src/Core/MathFunctions.h | 0 .../eigen/Eigen/src/Core/MathFunctionsImpl.h | 0 {xs/src => src}/eigen/Eigen/src/Core/Matrix.h | 0 .../eigen/Eigen/src/Core/MatrixBase.h | 0 .../eigen/Eigen/src/Core/NestByValue.h | 0 .../eigen/Eigen/src/Core/NoAlias.h | 0 .../eigen/Eigen/src/Core/NumTraits.h | 0 .../eigen/Eigen/src/Core/PermutationMatrix.h | 0 .../eigen/Eigen/src/Core/PlainObjectBase.h | 0 .../eigen/Eigen/src/Core/Product.h | 0 .../eigen/Eigen/src/Core/ProductEvaluators.h | 0 {xs/src => src}/eigen/Eigen/src/Core/Random.h | 0 {xs/src => src}/eigen/Eigen/src/Core/Redux.h | 0 {xs/src => src}/eigen/Eigen/src/Core/Ref.h | 0 .../eigen/Eigen/src/Core/Replicate.h | 0 .../eigen/Eigen/src/Core/ReturnByValue.h | 0 .../eigen/Eigen/src/Core/Reverse.h | 0 {xs/src => src}/eigen/Eigen/src/Core/Select.h | 0 .../eigen/Eigen/src/Core/SelfAdjointView.h | 0 .../eigen/Eigen/src/Core/SelfCwiseBinaryOp.h | 0 {xs/src => src}/eigen/Eigen/src/Core/Solve.h | 0 .../eigen/Eigen/src/Core/SolveTriangular.h | 0 .../eigen/Eigen/src/Core/SolverBase.h | 0 .../eigen/Eigen/src/Core/StableNorm.h | 0 {xs/src => src}/eigen/Eigen/src/Core/Stride.h | 0 {xs/src => src}/eigen/Eigen/src/Core/Swap.h | 0 .../eigen/Eigen/src/Core/Transpose.h | 0 .../eigen/Eigen/src/Core/Transpositions.h | 0 .../eigen/Eigen/src/Core/TriangularMatrix.h | 0 .../eigen/Eigen/src/Core/VectorBlock.h | 0 .../eigen/Eigen/src/Core/VectorwiseOp.h | 0 .../eigen/Eigen/src/Core/Visitor.h | 0 .../eigen/Eigen/src/Core/arch/AVX/Complex.h | 0 .../Eigen/src/Core/arch/AVX/MathFunctions.h | 0 .../Eigen/src/Core/arch/AVX/PacketMath.h | 0 .../Eigen/src/Core/arch/AVX/TypeCasting.h | 0 .../src/Core/arch/AVX512/MathFunctions.h | 0 .../Eigen/src/Core/arch/AVX512/PacketMath.h | 0 .../Eigen/src/Core/arch/AltiVec/Complex.h | 0 .../src/Core/arch/AltiVec/MathFunctions.h | 0 .../Eigen/src/Core/arch/AltiVec/PacketMath.h | 0 .../eigen/Eigen/src/Core/arch/CUDA/Complex.h | 0 .../eigen/Eigen/src/Core/arch/CUDA/Half.h | 0 .../Eigen/src/Core/arch/CUDA/MathFunctions.h | 0 .../Eigen/src/Core/arch/CUDA/PacketMath.h | 0 .../Eigen/src/Core/arch/CUDA/PacketMathHalf.h | 0 .../Eigen/src/Core/arch/CUDA/TypeCasting.h | 0 .../Eigen/src/Core/arch/Default/ConjHelper.h | 0 .../Eigen/src/Core/arch/Default/Settings.h | 0 .../eigen/Eigen/src/Core/arch/NEON/Complex.h | 0 .../Eigen/src/Core/arch/NEON/MathFunctions.h | 0 .../Eigen/src/Core/arch/NEON/PacketMath.h | 0 .../eigen/Eigen/src/Core/arch/SSE/Complex.h | 0 .../Eigen/src/Core/arch/SSE/MathFunctions.h | 0 .../Eigen/src/Core/arch/SSE/PacketMath.h | 0 .../Eigen/src/Core/arch/SSE/TypeCasting.h | 0 .../Eigen/src/Core/arch/ZVector/Complex.h | 0 .../src/Core/arch/ZVector/MathFunctions.h | 0 .../Eigen/src/Core/arch/ZVector/PacketMath.h | 0 .../src/Core/functors/AssignmentFunctors.h | 0 .../Eigen/src/Core/functors/BinaryFunctors.h | 0 .../Eigen/src/Core/functors/NullaryFunctors.h | 0 .../Eigen/src/Core/functors/StlFunctors.h | 0 .../Eigen/src/Core/functors/TernaryFunctors.h | 0 .../Eigen/src/Core/functors/UnaryFunctors.h | 0 .../Core/products/GeneralBlockPanelKernel.h | 0 .../src/Core/products/GeneralMatrixMatrix.h | 0 .../products/GeneralMatrixMatrixTriangular.h | 0 .../GeneralMatrixMatrixTriangular_BLAS.h | 0 .../Core/products/GeneralMatrixMatrix_BLAS.h | 0 .../src/Core/products/GeneralMatrixVector.h | 0 .../Core/products/GeneralMatrixVector_BLAS.h | 0 .../Eigen/src/Core/products/Parallelizer.h | 0 .../Core/products/SelfadjointMatrixMatrix.h | 0 .../products/SelfadjointMatrixMatrix_BLAS.h | 0 .../Core/products/SelfadjointMatrixVector.h | 0 .../products/SelfadjointMatrixVector_BLAS.h | 0 .../src/Core/products/SelfadjointProduct.h | 0 .../Core/products/SelfadjointRank2Update.h | 0 .../Core/products/TriangularMatrixMatrix.h | 0 .../products/TriangularMatrixMatrix_BLAS.h | 0 .../Core/products/TriangularMatrixVector.h | 0 .../products/TriangularMatrixVector_BLAS.h | 0 .../Core/products/TriangularSolverMatrix.h | 0 .../products/TriangularSolverMatrix_BLAS.h | 0 .../Core/products/TriangularSolverVector.h | 0 .../eigen/Eigen/src/Core/util/BlasUtil.h | 0 .../eigen/Eigen/src/Core/util/Constants.h | 0 .../src/Core/util/DisableStupidWarnings.h | 0 .../Eigen/src/Core/util/ForwardDeclarations.h | 0 .../eigen/Eigen/src/Core/util/MKL_support.h | 0 .../eigen/Eigen/src/Core/util/Macros.h | 0 .../eigen/Eigen/src/Core/util/Memory.h | 0 .../eigen/Eigen/src/Core/util/Meta.h | 0 .../eigen/Eigen/src/Core/util/NonMPL2.h | 0 .../src/Core/util/ReenableStupidWarnings.h | 0 .../eigen/Eigen/src/Core/util/StaticAssert.h | 0 .../eigen/Eigen/src/Core/util/XprHelper.h | 0 .../src/Eigenvalues/ComplexEigenSolver.h | 0 .../Eigen/src/Eigenvalues/ComplexSchur.h | 0 .../src/Eigenvalues/ComplexSchur_LAPACKE.h | 0 .../eigen/Eigen/src/Eigenvalues/EigenSolver.h | 0 .../src/Eigenvalues/GeneralizedEigenSolver.h | 0 .../GeneralizedSelfAdjointEigenSolver.h | 0 .../src/Eigenvalues/HessenbergDecomposition.h | 0 .../src/Eigenvalues/MatrixBaseEigenvalues.h | 0 .../eigen/Eigen/src/Eigenvalues/RealQZ.h | 0 .../eigen/Eigen/src/Eigenvalues/RealSchur.h | 0 .../Eigen/src/Eigenvalues/RealSchur_LAPACKE.h | 0 .../src/Eigenvalues/SelfAdjointEigenSolver.h | 0 .../SelfAdjointEigenSolver_LAPACKE.h | 0 .../src/Eigenvalues/Tridiagonalization.h | 0 .../eigen/Eigen/src/Geometry/AlignedBox.h | 0 .../eigen/Eigen/src/Geometry/AngleAxis.h | 0 .../eigen/Eigen/src/Geometry/EulerAngles.h | 0 .../eigen/Eigen/src/Geometry/Homogeneous.h | 0 .../eigen/Eigen/src/Geometry/Hyperplane.h | 0 .../eigen/Eigen/src/Geometry/OrthoMethods.h | 0 .../Eigen/src/Geometry/ParametrizedLine.h | 0 .../eigen/Eigen/src/Geometry/Quaternion.h | 0 .../eigen/Eigen/src/Geometry/Rotation2D.h | 0 .../eigen/Eigen/src/Geometry/RotationBase.h | 0 .../eigen/Eigen/src/Geometry/Scaling.h | 0 .../eigen/Eigen/src/Geometry/Transform.h | 0 .../eigen/Eigen/src/Geometry/Translation.h | 0 .../eigen/Eigen/src/Geometry/Umeyama.h | 0 .../Eigen/src/Geometry/arch/Geometry_SSE.h | 0 .../Eigen/src/Householder/BlockHouseholder.h | 0 .../eigen/Eigen/src/Householder/Householder.h | 0 .../src/Householder/HouseholderSequence.h | 0 .../BasicPreconditioners.h | 0 .../src/IterativeLinearSolvers/BiCGSTAB.h | 0 .../ConjugateGradient.h | 0 .../IncompleteCholesky.h | 0 .../IterativeLinearSolvers/IncompleteLUT.h | 0 .../IterativeSolverBase.h | 0 .../LeastSquareConjugateGradient.h | 0 .../IterativeLinearSolvers/SolveWithGuess.h | 0 .../eigen/Eigen/src/Jacobi/Jacobi.h | 0 .../eigen/Eigen/src/LU/Determinant.h | 0 .../eigen/Eigen/src/LU/FullPivLU.h | 0 .../eigen/Eigen/src/LU/InverseImpl.h | 0 .../eigen/Eigen/src/LU/PartialPivLU.h | 0 .../eigen/Eigen/src/LU/PartialPivLU_LAPACKE.h | 0 .../eigen/Eigen/src/LU/arch/Inverse_SSE.h | 0 .../Eigen/src/MetisSupport/MetisSupport.h | 0 .../eigen/Eigen/src/OrderingMethods/Amd.h | 0 .../Eigen/src/OrderingMethods/Eigen_Colamd.h | 0 .../Eigen/src/OrderingMethods/Ordering.h | 0 .../Eigen/src/PaStiXSupport/PaStiXSupport.h | 0 .../Eigen/src/PardisoSupport/PardisoSupport.h | 0 .../eigen/Eigen/src/QR/ColPivHouseholderQR.h | 0 .../src/QR/ColPivHouseholderQR_LAPACKE.h | 0 .../src/QR/CompleteOrthogonalDecomposition.h | 0 .../eigen/Eigen/src/QR/FullPivHouseholderQR.h | 0 .../eigen/Eigen/src/QR/HouseholderQR.h | 0 .../Eigen/src/QR/HouseholderQR_LAPACKE.h | 0 .../src/SPQRSupport/SuiteSparseQRSupport.h | 0 {xs/src => src}/eigen/Eigen/src/SVD/BDCSVD.h | 0 .../eigen/Eigen/src/SVD/JacobiSVD.h | 0 .../eigen/Eigen/src/SVD/JacobiSVD_LAPACKE.h | 0 {xs/src => src}/eigen/Eigen/src/SVD/SVDBase.h | 0 .../Eigen/src/SVD/UpperBidiagonalization.h | 0 .../src/SparseCholesky/SimplicialCholesky.h | 0 .../SparseCholesky/SimplicialCholesky_impl.h | 0 .../eigen/Eigen/src/SparseCore/AmbiVector.h | 0 .../Eigen/src/SparseCore/CompressedStorage.h | 0 .../ConservativeSparseSparseProduct.h | 0 .../Eigen/src/SparseCore/MappedSparseMatrix.h | 0 .../eigen/Eigen/src/SparseCore/SparseAssign.h | 0 .../eigen/Eigen/src/SparseCore/SparseBlock.h | 0 .../Eigen/src/SparseCore/SparseColEtree.h | 0 .../src/SparseCore/SparseCompressedBase.h | 0 .../src/SparseCore/SparseCwiseBinaryOp.h | 0 .../Eigen/src/SparseCore/SparseCwiseUnaryOp.h | 0 .../Eigen/src/SparseCore/SparseDenseProduct.h | 0 .../src/SparseCore/SparseDiagonalProduct.h | 0 .../eigen/Eigen/src/SparseCore/SparseDot.h | 0 .../eigen/Eigen/src/SparseCore/SparseFuzzy.h | 0 .../eigen/Eigen/src/SparseCore/SparseMap.h | 0 .../eigen/Eigen/src/SparseCore/SparseMatrix.h | 0 .../Eigen/src/SparseCore/SparseMatrixBase.h | 0 .../Eigen/src/SparseCore/SparsePermutation.h | 0 .../Eigen/src/SparseCore/SparseProduct.h | 0 .../eigen/Eigen/src/SparseCore/SparseRedux.h | 0 .../eigen/Eigen/src/SparseCore/SparseRef.h | 0 .../src/SparseCore/SparseSelfAdjointView.h | 0 .../Eigen/src/SparseCore/SparseSolverBase.h | 0 .../SparseSparseProductWithPruning.h | 0 .../Eigen/src/SparseCore/SparseTranspose.h | 0 .../src/SparseCore/SparseTriangularView.h | 0 .../eigen/Eigen/src/SparseCore/SparseUtil.h | 0 .../eigen/Eigen/src/SparseCore/SparseVector.h | 0 .../eigen/Eigen/src/SparseCore/SparseView.h | 0 .../Eigen/src/SparseCore/TriangularSolver.h | 0 .../eigen/Eigen/src/SparseLU/SparseLU.h | 0 .../eigen/Eigen/src/SparseLU/SparseLUImpl.h | 0 .../Eigen/src/SparseLU/SparseLU_Memory.h | 0 .../Eigen/src/SparseLU/SparseLU_Structs.h | 0 .../src/SparseLU/SparseLU_SupernodalMatrix.h | 0 .../eigen/Eigen/src/SparseLU/SparseLU_Utils.h | 0 .../Eigen/src/SparseLU/SparseLU_column_bmod.h | 0 .../Eigen/src/SparseLU/SparseLU_column_dfs.h | 0 .../src/SparseLU/SparseLU_copy_to_ucol.h | 0 .../Eigen/src/SparseLU/SparseLU_gemm_kernel.h | 0 .../src/SparseLU/SparseLU_heap_relax_snode.h | 0 .../Eigen/src/SparseLU/SparseLU_kernel_bmod.h | 0 .../Eigen/src/SparseLU/SparseLU_panel_bmod.h | 0 .../Eigen/src/SparseLU/SparseLU_panel_dfs.h | 0 .../Eigen/src/SparseLU/SparseLU_pivotL.h | 0 .../Eigen/src/SparseLU/SparseLU_pruneL.h | 0 .../Eigen/src/SparseLU/SparseLU_relax_snode.h | 0 .../eigen/Eigen/src/SparseQR/SparseQR.h | 0 .../eigen/Eigen/src/StlSupport/StdDeque.h | 0 .../eigen/Eigen/src/StlSupport/StdList.h | 0 .../eigen/Eigen/src/StlSupport/StdVector.h | 0 .../eigen/Eigen/src/StlSupport/details.h | 0 .../Eigen/src/SuperLUSupport/SuperLUSupport.h | 0 .../Eigen/src/UmfPackSupport/UmfPackSupport.h | 0 {xs/src => src}/eigen/Eigen/src/misc/Image.h | 0 {xs/src => src}/eigen/Eigen/src/misc/Kernel.h | 0 .../eigen/Eigen/src/misc/RealSvd2x2.h | 0 {xs/src => src}/eigen/Eigen/src/misc/blas.h | 0 {xs/src => src}/eigen/Eigen/src/misc/lapack.h | 0 .../eigen/Eigen/src/misc/lapacke.h | 0 .../eigen/Eigen/src/misc/lapacke_mangling.h | 0 .../Eigen/src/plugins/ArrayCwiseBinaryOps.h | 0 .../Eigen/src/plugins/ArrayCwiseUnaryOps.h | 0 .../eigen/Eigen/src/plugins/BlockMethods.h | 0 .../Eigen/src/plugins/CommonCwiseBinaryOps.h | 0 .../Eigen/src/plugins/CommonCwiseUnaryOps.h | 0 .../Eigen/src/plugins/MatrixCwiseBinaryOps.h | 0 .../Eigen/src/plugins/MatrixCwiseUnaryOps.h | 0 {xs/src => src}/eigen/README.md | 0 {xs/src => src}/expat/COPYING | 0 {xs/src => src}/expat/README | 0 {xs/src => src}/expat/ascii.h | 0 {xs/src => src}/expat/asciitab.h | 0 {xs/src => src}/expat/expat.h | 0 {xs/src => src}/expat/expat_config.h | 0 {xs/src => src}/expat/expat_external.h | 0 {xs/src => src}/expat/iasciitab.h | 0 {xs/src => src}/expat/internal.h | 0 {xs/src => src}/expat/latin1tab.h | 0 {xs/src => src}/expat/nametab.h | 0 {xs/src => src}/expat/utf8tab.h | 0 {xs/src => src}/expat/xmlparse.c | 0 {xs/src => src}/expat/xmlrole.c | 0 {xs/src => src}/expat/xmlrole.h | 0 {xs/src => src}/expat/xmltok.c | 0 {xs/src => src}/expat/xmltok.h | 0 {xs/src => src}/expat/xmltok_impl.h | 0 {xs/src => src}/expat/xmltok_impl.inc | 0 {xs/src => src}/expat/xmltok_ns.inc | 0 {xs/src => src}/glew/LICENSE.txt | 0 {xs/src => src}/glew/README.md | 0 {xs/src => src}/glew/include/GL/glew.h | 0 {xs/src => src}/glew/include/GL/glxew.h | 0 {xs/src => src}/glew/include/GL/wglew.h | 0 {xs/src => src}/glew/src/glew.c | 0 {xs/src => src}/libnest2d/CMakeLists.txt | 0 {xs/src => src}/libnest2d/LICENSE.txt | 0 {xs/src => src}/libnest2d/README.md | 0 .../cmake_modules/DownloadNLopt.cmake | 0 .../DownloadProject.CMakeLists.cmake.in | 0 .../cmake_modules/DownloadProject.cmake | 0 .../libnest2d/cmake_modules/FindClipper.cmake | 0 .../libnest2d/cmake_modules/FindNLopt.cmake | 0 .../libnest2d/cmake_modules/FindTBB.cmake | 0 {xs/src => src}/libnest2d/examples/main.cpp | 0 {xs/src => src}/libnest2d/libnest2d.h | 0 .../libnest2d/libnest2d/boost_alg.hpp | 0 .../libnest2d/clipper_backend/CMakeLists.txt | 0 .../clipper_backend/clipper_backend.hpp | 0 .../libnest2d/libnest2d/common.hpp | 0 .../libnest2d/libnest2d/geometry_traits.hpp | 0 .../libnest2d/geometry_traits_nfp.hpp | 0 .../libnest2d/libnest2d/libnest2d.hpp | 0 .../libnest2d/libnest2d/metaloop.hpp | 0 .../libnest2d/libnest2d/optimizer.hpp | 0 .../libnest2d/optimizers/genetic.hpp | 0 .../optimizers/nlopt_boilerplate.hpp | 0 .../libnest2d/optimizers/simplex.hpp | 0 .../libnest2d/optimizers/subplex.hpp | 0 .../libnest2d/placers/bottomleftplacer.hpp | 0 .../libnest2d/libnest2d/placers/nfpplacer.hpp | 0 .../libnest2d/placers/placer_boilerplate.hpp | 0 .../libnest2d/libnest2d/rotfinder.hpp | 0 .../libnest2d/selections/djd_heuristic.hpp | 0 .../libnest2d/libnest2d/selections/filler.hpp | 0 .../libnest2d/selections/firstfit.hpp | 0 .../selections/selection_boilerplate.hpp | 0 .../libnest2d/tests/CMakeLists.txt | 0 .../libnest2d/tests/printer_parts.cpp | 0 .../libnest2d/tests/printer_parts.h | 0 {xs/src => src}/libnest2d/tests/test.cpp | 0 {xs/src => src/libnest2d/tools}/benchmark.h | 0 .../libnest2d/tools/libnfpglue.cpp | 0 .../libnest2d/tools/libnfpglue.hpp | 0 .../libnest2d/tools/libnfporb/LICENSE | 0 .../libnest2d/tools/libnfporb/ORIGIN | 0 .../libnest2d/tools/libnfporb/README.md | 0 .../libnest2d/tools/libnfporb/libnfporb.hpp | 0 .../libnest2d/tools/nfp_svgnest.hpp | 0 .../libnest2d/tools/nfp_svgnest_glue.hpp | 0 {xs/src => src}/libnest2d/tools/svgtools.hpp | 0 {xs/src => src}/libslic3r/BoundingBox.cpp | 0 {xs/src => src}/libslic3r/BoundingBox.hpp | 0 {xs/src => src}/libslic3r/BridgeDetector.cpp | 0 {xs/src => src}/libslic3r/BridgeDetector.hpp | 0 src/libslic3r/CMakeLists.txt | 173 + {xs/src => src}/libslic3r/ClipperUtils.cpp | 0 {xs/src => src}/libslic3r/ClipperUtils.hpp | 0 {xs/src => src}/libslic3r/Config.cpp | 0 {xs/src => src}/libslic3r/Config.hpp | 0 {xs/src => src}/libslic3r/EdgeGrid.cpp | 0 {xs/src => src}/libslic3r/EdgeGrid.hpp | 0 {xs/src => src}/libslic3r/ExPolygon.cpp | 0 {xs/src => src}/libslic3r/ExPolygon.hpp | 0 .../libslic3r/ExPolygonCollection.cpp | 0 .../libslic3r/ExPolygonCollection.hpp | 0 {xs/src => src}/libslic3r/Extruder.cpp | 0 {xs/src => src}/libslic3r/Extruder.hpp | 0 {xs/src => src}/libslic3r/ExtrusionEntity.cpp | 0 {xs/src => src}/libslic3r/ExtrusionEntity.hpp | 0 .../libslic3r/ExtrusionEntityCollection.cpp | 0 .../libslic3r/ExtrusionEntityCollection.hpp | 0 .../libslic3r/ExtrusionSimulator.cpp | 0 .../libslic3r/ExtrusionSimulator.hpp | 0 {xs/src => src}/libslic3r/FileParserError.hpp | 0 {xs/src => src}/libslic3r/Fill/Fill.cpp | 0 {xs/src => src}/libslic3r/Fill/Fill.hpp | 0 .../libslic3r/Fill/Fill3DHoneycomb.cpp | 0 .../libslic3r/Fill/Fill3DHoneycomb.hpp | 0 {xs/src => src}/libslic3r/Fill/FillBase.cpp | 0 {xs/src => src}/libslic3r/Fill/FillBase.hpp | 0 .../libslic3r/Fill/FillConcentric.cpp | 0 .../libslic3r/Fill/FillConcentric.hpp | 0 {xs/src => src}/libslic3r/Fill/FillGyroid.cpp | 0 {xs/src => src}/libslic3r/Fill/FillGyroid.hpp | 0 .../libslic3r/Fill/FillHoneycomb.cpp | 0 .../libslic3r/Fill/FillHoneycomb.hpp | 0 .../libslic3r/Fill/FillPlanePath.cpp | 0 .../libslic3r/Fill/FillPlanePath.hpp | 0 .../libslic3r/Fill/FillRectilinear.cpp | 0 .../libslic3r/Fill/FillRectilinear.hpp | 0 .../libslic3r/Fill/FillRectilinear2.cpp | 0 .../libslic3r/Fill/FillRectilinear2.hpp | 0 .../libslic3r/Fill/FillRectilinear3.cpp | 0 .../libslic3r/Fill/FillRectilinear3.hpp | 0 {xs/src => src}/libslic3r/Flow.cpp | 0 {xs/src => src}/libslic3r/Flow.hpp | 0 {xs/src => src}/libslic3r/Format/3mf.cpp | 0 {xs/src => src}/libslic3r/Format/3mf.hpp | 0 {xs/src => src}/libslic3r/Format/AMF.cpp | 0 {xs/src => src}/libslic3r/Format/AMF.hpp | 0 {xs/src => src}/libslic3r/Format/OBJ.cpp | 0 {xs/src => src}/libslic3r/Format/OBJ.hpp | 0 {xs/src => src}/libslic3r/Format/PRUS.cpp | 0 {xs/src => src}/libslic3r/Format/PRUS.hpp | 0 {xs/src => src}/libslic3r/Format/STL.cpp | 0 {xs/src => src}/libslic3r/Format/STL.hpp | 0 .../libslic3r/Format/objparser.cpp | 0 .../libslic3r/Format/objparser.hpp | 0 {xs/src => src}/libslic3r/GCode.cpp | 0 {xs/src => src}/libslic3r/GCode.hpp | 0 {xs/src => src}/libslic3r/GCode/Analyzer.cpp | 0 {xs/src => src}/libslic3r/GCode/Analyzer.hpp | 0 .../libslic3r/GCode/CoolingBuffer.cpp | 0 .../libslic3r/GCode/CoolingBuffer.hpp | 0 .../libslic3r/GCode/PostProcessor.cpp | 0 .../libslic3r/GCode/PostProcessor.hpp | 0 .../libslic3r/GCode/PressureEqualizer.cpp | 0 .../libslic3r/GCode/PressureEqualizer.hpp | 0 .../libslic3r/GCode/PreviewData.cpp | 0 .../libslic3r/GCode/PreviewData.hpp | 0 .../libslic3r/GCode/PrintExtents.cpp | 0 .../libslic3r/GCode/PrintExtents.hpp | 0 .../libslic3r/GCode/SpiralVase.cpp | 0 .../libslic3r/GCode/SpiralVase.hpp | 0 .../libslic3r/GCode/ToolOrdering.cpp | 0 .../libslic3r/GCode/ToolOrdering.hpp | 0 {xs/src => src}/libslic3r/GCode/WipeTower.hpp | 0 .../libslic3r/GCode/WipeTowerPrusaMM.cpp | 0 .../libslic3r/GCode/WipeTowerPrusaMM.hpp | 0 {xs/src => src}/libslic3r/GCodeReader.cpp | 0 {xs/src => src}/libslic3r/GCodeReader.hpp | 0 {xs/src => src}/libslic3r/GCodeSender.cpp | 0 {xs/src => src}/libslic3r/GCodeSender.hpp | 0 .../libslic3r/GCodeTimeEstimator.cpp | 0 .../libslic3r/GCodeTimeEstimator.hpp | 0 {xs/src => src}/libslic3r/GCodeWriter.cpp | 0 {xs/src => src}/libslic3r/GCodeWriter.hpp | 0 {xs/src => src}/libslic3r/Geometry.cpp | 0 {xs/src => src}/libslic3r/Geometry.hpp | 0 {xs/src => src}/libslic3r/I18N.hpp | 0 {xs/src => src}/libslic3r/Int128.hpp | 0 {xs/src => src}/libslic3r/Layer.cpp | 0 {xs/src => src}/libslic3r/Layer.hpp | 0 {xs/src => src}/libslic3r/LayerRegion.cpp | 0 {xs/src => src}/libslic3r/Line.cpp | 0 {xs/src => src}/libslic3r/Line.hpp | 0 {xs/src => src}/libslic3r/Model.cpp | 0 {xs/src => src}/libslic3r/Model.hpp | 0 {xs/src => src}/libslic3r/ModelArrange.hpp | 0 {xs/src => src}/libslic3r/MotionPlanner.cpp | 0 {xs/src => src}/libslic3r/MotionPlanner.hpp | 0 {xs/src => src}/libslic3r/MultiPoint.cpp | 0 {xs/src => src}/libslic3r/MultiPoint.hpp | 0 .../libslic3r/MutablePriorityQueue.hpp | 0 .../libslic3r/PerimeterGenerator.cpp | 0 .../libslic3r/PerimeterGenerator.hpp | 0 .../libslic3r/PlaceholderParser.cpp | 0 .../libslic3r/PlaceholderParser.hpp | 0 {xs/src => src}/libslic3r/Point.cpp | 0 {xs/src => src}/libslic3r/Point.hpp | 0 {xs/src => src}/libslic3r/Polygon.cpp | 0 {xs/src => src}/libslic3r/Polygon.hpp | 0 {xs/src => src}/libslic3r/Polyline.cpp | 0 {xs/src => src}/libslic3r/Polyline.hpp | 0 .../libslic3r/PolylineCollection.cpp | 0 .../libslic3r/PolylineCollection.hpp | 0 {xs/src => src}/libslic3r/Print.cpp | 32 +- {xs/src => src}/libslic3r/Print.hpp | 0 {xs/src => src}/libslic3r/PrintConfig.cpp | 0 {xs/src => src}/libslic3r/PrintConfig.hpp | 0 {xs/src => src}/libslic3r/PrintExport.hpp | 0 {xs/src => src}/libslic3r/PrintObject.cpp | 0 {xs/src => src}/libslic3r/PrintRegion.cpp | 0 .../libslic3r/Rasterizer/Rasterizer.cpp | 0 .../libslic3r/Rasterizer/Rasterizer.hpp | 0 {xs/src => src}/libslic3r/SLABasePool.cpp | 0 {xs/src => src}/libslic3r/SLABasePool.hpp | 0 {xs/src => src}/libslic3r/SVG.cpp | 0 {xs/src => src}/libslic3r/SVG.hpp | 0 {xs/src => src}/libslic3r/Slicing.cpp | 0 {xs/src => src}/libslic3r/Slicing.hpp | 0 {xs/src => src}/libslic3r/SlicingAdaptive.cpp | 0 {xs/src => src}/libslic3r/SlicingAdaptive.hpp | 0 {xs/src => src}/libslic3r/SupportMaterial.cpp | 0 {xs/src => src}/libslic3r/SupportMaterial.hpp | 0 {xs/src => src}/libslic3r/Surface.cpp | 0 {xs/src => src}/libslic3r/Surface.hpp | 0 .../libslic3r/SurfaceCollection.cpp | 0 .../libslic3r/SurfaceCollection.hpp | 0 {xs/src => src}/libslic3r/Technologies.hpp | 0 {xs/src => src}/libslic3r/TriangleMesh.cpp | 0 {xs/src => src}/libslic3r/TriangleMesh.hpp | 0 {xs/src => src}/libslic3r/Utils.hpp | 0 {xs/src => src}/libslic3r/libslic3r.h | 0 {xs/src => src}/libslic3r/utils.cpp | 0 src/miniz/CMakeLists.txt | 14 + {xs/src => src}/miniz/miniz.cpp | 0 {xs/src => src}/miniz/miniz.h | 0 {xs/src => src}/miniz/miniz_common.h | 0 {xs/src => src}/miniz/miniz_tdef.cpp | 0 {xs/src => src}/miniz/miniz_tdef.h | 0 {xs/src => src}/miniz/miniz_tinfl.cpp | 0 {xs/src => src}/miniz/miniz_tinfl.h | 0 {xs/src => src}/miniz/miniz_zip.cpp | 0 {xs/src => src}/miniz/miniz_zip.h | 0 {xs/src => src}/png/AUTHORS | 0 {xs/src => src}/png/COPYING | 0 {xs/src => src}/png/NEWS | 0 {xs/src => src}/png/color.hpp | 0 {xs/src => src}/png/end_info.hpp | 0 {xs/src => src}/png/error.hpp | 0 {xs/src => src}/png/image_info.hpp | 0 {xs/src => src}/png/info.hpp | 0 {xs/src => src}/png/info_base.hpp | 0 {xs/src => src}/png/io_base.hpp | 0 {xs/src => src}/png/libpng/ANNOUNCE | 0 {xs/src => src}/png/libpng/CMakeLists.txt | 26 +- {xs/src => src}/png/libpng/LICENSE | 0 {xs/src => src}/png/libpng/arm/arm_init.c | 0 {xs/src => src}/png/libpng/arm/filter_neon.S | 0 .../png/libpng/arm/filter_neon_intrinsics.c | 0 .../png/libpng/intel/filter_sse2_intrinsics.c | 0 {xs/src => src}/png/libpng/intel/intel_init.c | 0 {xs/src => src}/png/libpng/libpng-config.in | 0 {xs/src => src}/png/libpng/libpng.pc.in | 0 .../png/libpng/mips/filter_msa_intrinsics.c | 0 {xs/src => src}/png/libpng/mips/mips_init.c | 0 {xs/src => src}/png/libpng/png.c | 0 {xs/src => src}/png/libpng/png.h | 0 {xs/src => src}/png/libpng/pngconf.h | 0 {xs/src => src}/png/libpng/pngdebug.h | 0 {xs/src => src}/png/libpng/pngerror.c | 0 {xs/src => src}/png/libpng/pngget.c | 0 {xs/src => src}/png/libpng/pnginfo.h | 0 {xs/src => src}/png/libpng/pngmem.c | 0 {xs/src => src}/png/libpng/pngpread.c | 0 {xs/src => src}/png/libpng/pngpriv.h | 0 {xs/src => src}/png/libpng/pngread.c | 0 {xs/src => src}/png/libpng/pngrio.c | 0 {xs/src => src}/png/libpng/pngrtran.c | 0 {xs/src => src}/png/libpng/pngrutil.c | 0 {xs/src => src}/png/libpng/pngset.c | 0 {xs/src => src}/png/libpng/pngstruct.h | 0 {xs/src => src}/png/libpng/pngtest.c | 0 {xs/src => src}/png/libpng/pngtrans.c | 0 {xs/src => src}/png/libpng/pngusr.dfa | 0 {xs/src => src}/png/libpng/pngwio.c | 0 {xs/src => src}/png/libpng/pngwrite.c | 0 {xs/src => src}/png/libpng/pngwtran.c | 0 {xs/src => src}/png/libpng/pngwutil.c | 0 .../libpng/powerpc/filter_vsx_intrinsics.c | 0 .../png/libpng/powerpc/powerpc_init.c | 0 .../png/libpng/scripts/checksym.awk | 0 {xs/src => src}/png/libpng/scripts/def.c | 0 {xs/src => src}/png/libpng/scripts/dfn.awk | 0 .../png/libpng/scripts/genchk.cmake.in | 0 .../png/libpng/scripts/genout.cmake.in | 0 .../png/libpng/scripts/gensrc.cmake.in | 0 .../png/libpng/scripts/intprefix.c | 0 .../png/libpng/scripts/libpng-config-body.in | 0 .../png/libpng/scripts/libpng-config-head.in | 0 .../png/libpng/scripts/libpng.pc.in | 0 .../png/libpng/scripts/options.awk | 0 .../png/libpng/scripts/pnglibconf.dfa | 0 .../png/libpng/scripts/pnglibconf.h.prebuilt | 0 {xs/src => src}/png/libpng/scripts/prefix.c | 0 {xs/src => src}/png/libpng/scripts/sym.c | 0 {xs/src => src}/png/libpng/scripts/symbols.c | 0 .../png/libpng/scripts/symbols.def | 0 .../png/libpng/scripts/test.cmake.in | 0 {xs/src => src}/png/libpng/scripts/vers.c | 0 {xs/src => src}/png/palette.hpp | 0 {xs/src => src}/png/pixel_traits.hpp | 0 {xs/src => src}/png/tRNS.hpp | 0 {xs/src => src}/png/types.hpp | 0 {xs/src => src}/png/writer.hpp | 0 {xs/src => src}/png/zlib/CMakeLists.txt | 0 {xs/src => src}/png/zlib/ChangeLog | 0 {xs/src => src}/png/zlib/FAQ | 0 {xs/src => src}/png/zlib/INDEX | 0 {xs/src => src}/png/zlib/Makefile | 0 {xs/src => src}/png/zlib/Makefile.in | 0 {xs/src => src}/png/zlib/README | 0 {xs/src => src}/png/zlib/adler32.c | 0 {xs/src => src}/png/zlib/amiga/Makefile.pup | 0 {xs/src => src}/png/zlib/amiga/Makefile.sas | 0 {xs/src => src}/png/zlib/compress.c | 0 {xs/src => src}/png/zlib/configure | 0 .../png/zlib/contrib/README.contrib | 0 .../png/zlib/contrib/ada/buffer_demo.adb | 0 .../png/zlib/contrib/ada/mtest.adb | 0 {xs/src => src}/png/zlib/contrib/ada/read.adb | 0 .../png/zlib/contrib/ada/readme.txt | 0 {xs/src => src}/png/zlib/contrib/ada/test.adb | 0 .../png/zlib/contrib/ada/zlib-streams.adb | 0 .../png/zlib/contrib/ada/zlib-streams.ads | 0 .../png/zlib/contrib/ada/zlib-thin.adb | 0 .../png/zlib/contrib/ada/zlib-thin.ads | 0 {xs/src => src}/png/zlib/contrib/ada/zlib.adb | 0 {xs/src => src}/png/zlib/contrib/ada/zlib.ads | 0 {xs/src => src}/png/zlib/contrib/ada/zlib.gpr | 0 .../png/zlib/contrib/amd64/amd64-match.S | 0 .../png/zlib/contrib/asm686/README.686 | 0 .../png/zlib/contrib/asm686/match.S | 0 .../png/zlib/contrib/blast/Makefile | 0 {xs/src => src}/png/zlib/contrib/blast/README | 0 .../png/zlib/contrib/blast/blast.c | 0 .../png/zlib/contrib/blast/blast.h | 0 .../png/zlib/contrib/blast/test.pk | Bin .../png/zlib/contrib/blast/test.txt | 0 .../png/zlib/contrib/delphi/ZLib.pas | 0 .../png/zlib/contrib/delphi/ZLibConst.pas | 0 .../png/zlib/contrib/delphi/readme.txt | 0 .../png/zlib/contrib/delphi/zlibd32.mak | 0 .../png/zlib/contrib/dotzlib/DotZLib.build | 0 .../png/zlib/contrib/dotzlib/DotZLib.chm | Bin .../png/zlib/contrib/dotzlib/DotZLib.sln | 0 .../contrib/dotzlib/DotZLib/AssemblyInfo.cs | 0 .../contrib/dotzlib/DotZLib/ChecksumImpl.cs | 0 .../contrib/dotzlib/DotZLib/CircularBuffer.cs | 0 .../zlib/contrib/dotzlib/DotZLib/CodecBase.cs | 0 .../zlib/contrib/dotzlib/DotZLib/Deflater.cs | 0 .../zlib/contrib/dotzlib/DotZLib/DotZLib.cs | 0 .../contrib/dotzlib/DotZLib/DotZLib.csproj | 0 .../contrib/dotzlib/DotZLib/GZipStream.cs | 0 .../zlib/contrib/dotzlib/DotZLib/Inflater.cs | 0 .../zlib/contrib/dotzlib/DotZLib/UnitTests.cs | 0 .../png/zlib/contrib/dotzlib/LICENSE_1_0.txt | 0 .../png/zlib/contrib/dotzlib/readme.txt | 0 .../png/zlib/contrib/gcc_gvmat64/gvmat64.S | 0 .../png/zlib/contrib/infback9/README | 0 .../png/zlib/contrib/infback9/infback9.c | 0 .../png/zlib/contrib/infback9/infback9.h | 0 .../png/zlib/contrib/infback9/inffix9.h | 0 .../png/zlib/contrib/infback9/inflate9.h | 0 .../png/zlib/contrib/infback9/inftree9.c | 0 .../png/zlib/contrib/infback9/inftree9.h | 0 .../png/zlib/contrib/inflate86/inffas86.c | 0 .../png/zlib/contrib/inflate86/inffast.S | 0 .../png/zlib/contrib/iostream/test.cpp | 0 .../png/zlib/contrib/iostream/zfstream.cpp | 0 .../png/zlib/contrib/iostream/zfstream.h | 0 .../png/zlib/contrib/iostream2/zstream.h | 0 .../zlib/contrib/iostream2/zstream_test.cpp | 0 .../png/zlib/contrib/iostream3/README | 0 .../png/zlib/contrib/iostream3/TODO | 0 .../png/zlib/contrib/iostream3/test.cc | 0 .../png/zlib/contrib/iostream3/zfstream.cc | 0 .../png/zlib/contrib/iostream3/zfstream.h | 0 .../png/zlib/contrib/masmx64/bld_ml64.bat | 0 .../png/zlib/contrib/masmx64/gvmat64.asm | 0 .../png/zlib/contrib/masmx64/inffas8664.c | 0 .../png/zlib/contrib/masmx64/inffasx64.asm | 0 .../png/zlib/contrib/masmx64/readme.txt | 0 .../png/zlib/contrib/masmx86/bld_ml32.bat | 0 .../png/zlib/contrib/masmx86/inffas32.asm | 0 .../png/zlib/contrib/masmx86/match686.asm | 0 .../png/zlib/contrib/masmx86/readme.txt | 0 .../png/zlib/contrib/minizip/Makefile | 0 .../png/zlib/contrib/minizip/Makefile.am | 0 .../contrib/minizip/MiniZip64_Changes.txt | 0 .../zlib/contrib/minizip/MiniZip64_info.txt | 0 .../png/zlib/contrib/minizip/configure.ac | 0 .../png/zlib/contrib/minizip/crypt.h | 0 .../png/zlib/contrib/minizip/ioapi.c | 0 .../png/zlib/contrib/minizip/ioapi.h | 0 .../png/zlib/contrib/minizip/iowin32.c | 0 .../png/zlib/contrib/minizip/iowin32.h | 0 .../png/zlib/contrib/minizip/make_vms.com | 0 .../png/zlib/contrib/minizip/miniunz.c | 0 .../png/zlib/contrib/minizip/miniunzip.1 | 0 .../png/zlib/contrib/minizip/minizip.1 | 0 .../png/zlib/contrib/minizip/minizip.c | 0 .../png/zlib/contrib/minizip/minizip.pc.in | 0 .../png/zlib/contrib/minizip/mztools.c | 0 .../png/zlib/contrib/minizip/mztools.h | 0 .../png/zlib/contrib/minizip/unzip.c | 0 .../png/zlib/contrib/minizip/unzip.h | 0 .../png/zlib/contrib/minizip/zip.c | 0 .../png/zlib/contrib/minizip/zip.h | 0 .../png/zlib/contrib/pascal/example.pas | 0 .../png/zlib/contrib/pascal/readme.txt | 0 .../png/zlib/contrib/pascal/zlibd32.mak | 0 .../png/zlib/contrib/pascal/zlibpas.pas | 0 .../png/zlib/contrib/puff/Makefile | 0 {xs/src => src}/png/zlib/contrib/puff/README | 0 {xs/src => src}/png/zlib/contrib/puff/puff.c | 0 {xs/src => src}/png/zlib/contrib/puff/puff.h | 0 .../png/zlib/contrib/puff/pufftest.c | 0 .../png/zlib/contrib/puff/zeros.raw | Bin .../png/zlib/contrib/testzlib/testzlib.c | 0 .../png/zlib/contrib/testzlib/testzlib.txt | 0 .../png/zlib/contrib/untgz/Makefile | 0 .../png/zlib/contrib/untgz/Makefile.msc | 0 .../png/zlib/contrib/untgz/untgz.c | 0 .../png/zlib/contrib/vstudio/readme.txt | 0 .../zlib/contrib/vstudio/vc10/miniunz.vcxproj | 0 .../vstudio/vc10/miniunz.vcxproj.filters | 0 .../zlib/contrib/vstudio/vc10/minizip.vcxproj | 0 .../vstudio/vc10/minizip.vcxproj.filters | 0 .../contrib/vstudio/vc10/testzlib.vcxproj | 0 .../vstudio/vc10/testzlib.vcxproj.filters | 0 .../contrib/vstudio/vc10/testzlibdll.vcxproj | 0 .../vstudio/vc10/testzlibdll.vcxproj.filters | 0 .../png/zlib/contrib/vstudio/vc10/zlib.rc | 0 .../contrib/vstudio/vc10/zlibstat.vcxproj | 0 .../vstudio/vc10/zlibstat.vcxproj.filters | 0 .../png/zlib/contrib/vstudio/vc10/zlibvc.def | 0 .../png/zlib/contrib/vstudio/vc10/zlibvc.sln | 0 .../zlib/contrib/vstudio/vc10/zlibvc.vcxproj | 0 .../vstudio/vc10/zlibvc.vcxproj.filters | 0 .../zlib/contrib/vstudio/vc11/miniunz.vcxproj | 0 .../zlib/contrib/vstudio/vc11/minizip.vcxproj | 0 .../contrib/vstudio/vc11/testzlib.vcxproj | 0 .../contrib/vstudio/vc11/testzlibdll.vcxproj | 0 .../png/zlib/contrib/vstudio/vc11/zlib.rc | 0 .../contrib/vstudio/vc11/zlibstat.vcxproj | 0 .../png/zlib/contrib/vstudio/vc11/zlibvc.def | 0 .../png/zlib/contrib/vstudio/vc11/zlibvc.sln | 0 .../zlib/contrib/vstudio/vc11/zlibvc.vcxproj | 0 .../zlib/contrib/vstudio/vc12/miniunz.vcxproj | 0 .../zlib/contrib/vstudio/vc12/minizip.vcxproj | 0 .../contrib/vstudio/vc12/testzlib.vcxproj | 0 .../contrib/vstudio/vc12/testzlibdll.vcxproj | 0 .../png/zlib/contrib/vstudio/vc12/zlib.rc | 0 .../contrib/vstudio/vc12/zlibstat.vcxproj | 0 .../png/zlib/contrib/vstudio/vc12/zlibvc.def | 0 .../png/zlib/contrib/vstudio/vc12/zlibvc.sln | 0 .../zlib/contrib/vstudio/vc12/zlibvc.vcxproj | 0 .../zlib/contrib/vstudio/vc14/miniunz.vcxproj | 0 .../zlib/contrib/vstudio/vc14/minizip.vcxproj | 0 .../contrib/vstudio/vc14/testzlib.vcxproj | 0 .../contrib/vstudio/vc14/testzlibdll.vcxproj | 0 .../png/zlib/contrib/vstudio/vc14/zlib.rc | 0 .../contrib/vstudio/vc14/zlibstat.vcxproj | 0 .../png/zlib/contrib/vstudio/vc14/zlibvc.def | 0 .../png/zlib/contrib/vstudio/vc14/zlibvc.sln | 0 .../zlib/contrib/vstudio/vc14/zlibvc.vcxproj | 0 .../zlib/contrib/vstudio/vc9/miniunz.vcproj | 0 .../zlib/contrib/vstudio/vc9/minizip.vcproj | 0 .../zlib/contrib/vstudio/vc9/testzlib.vcproj | 0 .../contrib/vstudio/vc9/testzlibdll.vcproj | 0 .../png/zlib/contrib/vstudio/vc9/zlib.rc | 0 .../zlib/contrib/vstudio/vc9/zlibstat.vcproj | 0 .../png/zlib/contrib/vstudio/vc9/zlibvc.def | 0 .../png/zlib/contrib/vstudio/vc9/zlibvc.sln | 0 .../zlib/contrib/vstudio/vc9/zlibvc.vcproj | 0 {xs/src => src}/png/zlib/crc32.c | 0 {xs/src => src}/png/zlib/crc32.h | 0 {xs/src => src}/png/zlib/deflate.c | 0 {xs/src => src}/png/zlib/deflate.h | 0 {xs/src => src}/png/zlib/gzclose.c | 0 {xs/src => src}/png/zlib/gzguts.h | 0 {xs/src => src}/png/zlib/gzlib.c | 0 {xs/src => src}/png/zlib/gzread.c | 0 {xs/src => src}/png/zlib/gzwrite.c | 0 {xs/src => src}/png/zlib/infback.c | 0 {xs/src => src}/png/zlib/inffast.c | 0 {xs/src => src}/png/zlib/inffast.h | 0 {xs/src => src}/png/zlib/inffixed.h | 0 {xs/src => src}/png/zlib/inflate.c | 0 {xs/src => src}/png/zlib/inflate.h | 0 {xs/src => src}/png/zlib/inftrees.c | 0 {xs/src => src}/png/zlib/inftrees.h | 0 {xs/src => src}/png/zlib/make_vms.com | 0 {xs/src => src}/png/zlib/msdos/Makefile.bor | 0 {xs/src => src}/png/zlib/msdos/Makefile.dj2 | 0 {xs/src => src}/png/zlib/msdos/Makefile.emx | 0 {xs/src => src}/png/zlib/msdos/Makefile.msc | 0 {xs/src => src}/png/zlib/msdos/Makefile.tc | 0 {xs/src => src}/png/zlib/nintendods/Makefile | 0 {xs/src => src}/png/zlib/nintendods/README | 0 {xs/src => src}/png/zlib/old/Makefile.emx | 0 {xs/src => src}/png/zlib/old/Makefile.riscos | 0 {xs/src => src}/png/zlib/old/README | 0 {xs/src => src}/png/zlib/old/descrip.mms | 0 {xs/src => src}/png/zlib/old/os2/Makefile.os2 | 0 {xs/src => src}/png/zlib/old/os2/zlib.def | 0 {xs/src => src}/png/zlib/old/visual-basic.txt | 0 {xs/src => src}/png/zlib/os400/README400 | 0 {xs/src => src}/png/zlib/os400/bndsrc | 0 {xs/src => src}/png/zlib/os400/make.sh | 0 {xs/src => src}/png/zlib/os400/zlib.inc | 0 {xs/src => src}/png/zlib/qnx/package.qpg | 0 {xs/src => src}/png/zlib/treebuild.xml | 0 {xs/src => src}/png/zlib/trees.c | 0 {xs/src => src}/png/zlib/trees.h | 0 {xs/src => src}/png/zlib/uncompr.c | 0 {xs/src => src}/png/zlib/watcom/watcom_f.mak | 0 {xs/src => src}/png/zlib/watcom/watcom_l.mak | 0 {xs/src => src}/png/zlib/win32/DLL_FAQ.txt | 0 {xs/src => src}/png/zlib/win32/Makefile.bor | 0 {xs/src => src}/png/zlib/win32/Makefile.gcc | 0 {xs/src => src}/png/zlib/win32/Makefile.msc | 0 .../png/zlib/win32/README-WIN32.txt | 0 {xs/src => src}/png/zlib/win32/VisualC.txt | 0 {xs/src => src}/png/zlib/win32/zlib.def | 0 {xs/src => src}/png/zlib/win32/zlib1.rc | 0 {xs/src => src}/png/zlib/zconf.h.cmakein | 0 {xs/src => src}/png/zlib/zconf.h.in | 0 {xs/src => src}/png/zlib/zconf.h.included | 0 {xs/src => src}/png/zlib/zlib.3 | 0 {xs/src => src}/png/zlib/zlib.3.pdf | Bin {xs/src => src}/png/zlib/zlib.h | 0 {xs/src => src}/png/zlib/zlib.map | 0 {xs/src => src}/png/zlib/zlib.pc.cmakein | 0 {xs/src => src}/png/zlib/zlib.pc.in | 0 {xs/src => src}/png/zlib/zlib2ansi | 0 {xs/src => src}/png/zlib/zutil.c | 0 {xs/src => src}/png/zlib/zutil.h | 0 src/poly2tri/CMakeLists.txt | 17 + {xs/src => src}/poly2tri/common/shapes.cc | 0 {xs/src => src}/poly2tri/common/shapes.h | 0 {xs/src => src}/poly2tri/common/utils.h | 0 {xs/src => src}/poly2tri/poly2tri.h | 0 .../poly2tri/sweep/advancing_front.cc | 0 .../poly2tri/sweep/advancing_front.h | 0 {xs/src => src}/poly2tri/sweep/cdt.cc | 0 {xs/src => src}/poly2tri/sweep/cdt.h | 0 {xs/src => src}/poly2tri/sweep/sweep.cc | 0 {xs/src => src}/poly2tri/sweep/sweep.h | 0 .../poly2tri/sweep/sweep_context.cc | 0 .../poly2tri/sweep/sweep_context.h | 0 src/polypartition/CMakeLists.txt | 7 + .../polypartition}/polypartition.cpp | 3126 +++--- {xs/src => src/polypartition}/polypartition.h | 686 +- {xs/src => src}/qhull/Announce.txt | 0 {xs/src => src}/qhull/CMakeLists.txt | 0 {xs/src => src}/qhull/COPYING.txt | 0 {xs/src => src}/qhull/README.txt | 0 {xs/src => src}/qhull/REGISTER.txt | 0 {xs/src => src}/qhull/html/index.htm | 0 .../html/normal_voronoi_knauss_oesterle.jpg | Bin {xs/src => src}/qhull/html/qconvex.htm | 0 {xs/src => src}/qhull/html/qdelau_f.htm | 0 {xs/src => src}/qhull/html/qdelaun.htm | 0 {xs/src => src}/qhull/html/qh--4d.gif | Bin {xs/src => src}/qhull/html/qh--cone.gif | Bin {xs/src => src}/qhull/html/qh--dt.gif | Bin {xs/src => src}/qhull/html/qh--geom.gif | Bin {xs/src => src}/qhull/html/qh--half.gif | Bin {xs/src => src}/qhull/html/qh--rand.gif | Bin {xs/src => src}/qhull/html/qh-code.htm | 0 {xs/src => src}/qhull/html/qh-eg.htm | 0 {xs/src => src}/qhull/html/qh-faq.htm | 0 {xs/src => src}/qhull/html/qh-get.htm | 0 {xs/src => src}/qhull/html/qh-impre.htm | 0 {xs/src => src}/qhull/html/qh-optc.htm | 0 {xs/src => src}/qhull/html/qh-optf.htm | 0 {xs/src => src}/qhull/html/qh-optg.htm | 0 {xs/src => src}/qhull/html/qh-opto.htm | 0 {xs/src => src}/qhull/html/qh-optp.htm | 0 {xs/src => src}/qhull/html/qh-optq.htm | 0 {xs/src => src}/qhull/html/qh-optt.htm | 0 {xs/src => src}/qhull/html/qh-quick.htm | 0 {xs/src => src}/qhull/html/qhalf.htm | 0 {xs/src => src}/qhull/html/qhull-cpp.xml | 0 {xs/src => src}/qhull/html/qhull.htm | 0 {xs/src => src}/qhull/html/qhull.man | 0 {xs/src => src}/qhull/html/qhull.txt | 0 {xs/src => src}/qhull/html/qvoron_f.htm | 0 {xs/src => src}/qhull/html/qvoronoi.htm | 0 {xs/src => src}/qhull/html/rbox.htm | 0 {xs/src => src}/qhull/html/rbox.man | 0 {xs/src => src}/qhull/html/rbox.txt | 0 {xs/src => src}/qhull/index.htm | 0 {xs/src => src}/qhull/origCMakeLists.txt | 0 {xs/src => src}/qhull/src/Changes.txt | 0 .../qhull/src/libqhull/DEPRECATED.txt | 0 {xs/src => src}/qhull/src/libqhull/Makefile | 0 {xs/src => src}/qhull/src/libqhull/Mborland | 0 {xs/src => src}/qhull/src/libqhull/geom.c | 0 {xs/src => src}/qhull/src/libqhull/geom.h | 0 {xs/src => src}/qhull/src/libqhull/geom2.c | 0 {xs/src => src}/qhull/src/libqhull/global.c | 0 {xs/src => src}/qhull/src/libqhull/index.htm | 0 {xs/src => src}/qhull/src/libqhull/io.c | 0 {xs/src => src}/qhull/src/libqhull/io.h | 0 {xs/src => src}/qhull/src/libqhull/libqhull.c | 0 {xs/src => src}/qhull/src/libqhull/libqhull.h | 0 .../qhull/src/libqhull/libqhull.pro | 0 {xs/src => src}/qhull/src/libqhull/mem.c | 0 {xs/src => src}/qhull/src/libqhull/mem.h | 0 {xs/src => src}/qhull/src/libqhull/merge.c | 0 {xs/src => src}/qhull/src/libqhull/merge.h | 0 {xs/src => src}/qhull/src/libqhull/poly.c | 0 {xs/src => src}/qhull/src/libqhull/poly.h | 0 {xs/src => src}/qhull/src/libqhull/poly2.c | 0 .../qhull/src/libqhull/qh-geom.htm | 0 .../qhull/src/libqhull/qh-globa.htm | 0 {xs/src => src}/qhull/src/libqhull/qh-io.htm | 0 {xs/src => src}/qhull/src/libqhull/qh-mem.htm | 0 .../qhull/src/libqhull/qh-merge.htm | 0 .../qhull/src/libqhull/qh-poly.htm | 0 .../qhull/src/libqhull/qh-qhull.htm | 0 {xs/src => src}/qhull/src/libqhull/qh-set.htm | 0 .../qhull/src/libqhull/qh-stat.htm | 0 .../qhull/src/libqhull/qh-user.htm | 0 .../qhull/src/libqhull/qhull-exports.def | 0 {xs/src => src}/qhull/src/libqhull/qhull_a.h | 0 .../qhull/src/libqhull/qhull_p-exports.def | 0 {xs/src => src}/qhull/src/libqhull/qset.c | 0 {xs/src => src}/qhull/src/libqhull/qset.h | 0 {xs/src => src}/qhull/src/libqhull/random.c | 0 {xs/src => src}/qhull/src/libqhull/random.h | 0 {xs/src => src}/qhull/src/libqhull/rboxlib.c | 0 {xs/src => src}/qhull/src/libqhull/stat.c | 0 {xs/src => src}/qhull/src/libqhull/stat.h | 0 {xs/src => src}/qhull/src/libqhull/user.c | 0 {xs/src => src}/qhull/src/libqhull/user.h | 0 {xs/src => src}/qhull/src/libqhull/usermem.c | 0 .../qhull/src/libqhull/userprintf.c | 0 .../qhull/src/libqhull/userprintf_rbox.c | 0 {xs/src => src}/qhull/src/libqhull_r/Makefile | 0 .../qhull/src/libqhull_r/geom2_r.c | 0 {xs/src => src}/qhull/src/libqhull_r/geom_r.c | 0 {xs/src => src}/qhull/src/libqhull_r/geom_r.h | 0 .../qhull/src/libqhull_r/global_r.c | 0 .../qhull/src/libqhull_r/index.htm | 0 {xs/src => src}/qhull/src/libqhull_r/io_r.c | 0 {xs/src => src}/qhull/src/libqhull_r/io_r.h | 0 .../qhull/src/libqhull_r/libqhull_r.c | 0 .../qhull/src/libqhull_r/libqhull_r.h | 0 .../qhull/src/libqhull_r/libqhull_r.pro | 0 {xs/src => src}/qhull/src/libqhull_r/mem_r.c | 0 {xs/src => src}/qhull/src/libqhull_r/mem_r.h | 0 .../qhull/src/libqhull_r/merge_r.c | 0 .../qhull/src/libqhull_r/merge_r.h | 0 .../qhull/src/libqhull_r/poly2_r.c | 0 {xs/src => src}/qhull/src/libqhull_r/poly_r.c | 0 {xs/src => src}/qhull/src/libqhull_r/poly_r.h | 0 .../qhull/src/libqhull_r/qh-geom_r.htm | 0 .../qhull/src/libqhull_r/qh-globa_r.htm | 0 .../qhull/src/libqhull_r/qh-io_r.htm | 0 .../qhull/src/libqhull_r/qh-mem_r.htm | 0 .../qhull/src/libqhull_r/qh-merge_r.htm | 0 .../qhull/src/libqhull_r/qh-poly_r.htm | 0 .../qhull/src/libqhull_r/qh-qhull_r.htm | 0 .../qhull/src/libqhull_r/qh-set_r.htm | 0 .../qhull/src/libqhull_r/qh-stat_r.htm | 0 .../qhull/src/libqhull_r/qh-user_r.htm | 0 .../qhull/src/libqhull_r/qhull_r-exports.def | 0 .../qhull/src/libqhull_r/qhull_ra.h | 0 {xs/src => src}/qhull/src/libqhull_r/qset_r.c | 0 {xs/src => src}/qhull/src/libqhull_r/qset_r.h | 0 .../qhull/src/libqhull_r/random_r.c | 0 .../qhull/src/libqhull_r/random_r.h | 0 .../qhull/src/libqhull_r/rboxlib_r.c | 0 {xs/src => src}/qhull/src/libqhull_r/stat_r.c | 0 {xs/src => src}/qhull/src/libqhull_r/stat_r.h | 0 {xs/src => src}/qhull/src/libqhull_r/user_r.c | 0 {xs/src => src}/qhull/src/libqhull_r/user_r.h | 0 .../qhull/src/libqhull_r/usermem_r.c | 0 .../qhull/src/libqhull_r/userprintf_r.c | 0 .../qhull/src/libqhull_r/userprintf_rbox_r.c | 0 .../qhull/src/libqhullcpp/Coordinates.cpp | 0 .../qhull/src/libqhullcpp/Coordinates.h | 0 .../src/libqhullcpp/PointCoordinates.cpp | 0 .../qhull/src/libqhullcpp/PointCoordinates.h | 0 .../qhull/src/libqhullcpp/Qhull.cpp | 0 {xs/src => src}/qhull/src/libqhullcpp/Qhull.h | 0 .../qhull/src/libqhullcpp/QhullError.h | 0 .../qhull/src/libqhullcpp/QhullFacet.cpp | 0 .../qhull/src/libqhullcpp/QhullFacet.h | 0 .../qhull/src/libqhullcpp/QhullFacetList.cpp | 0 .../qhull/src/libqhullcpp/QhullFacetList.h | 0 .../qhull/src/libqhullcpp/QhullFacetSet.cpp | 0 .../qhull/src/libqhullcpp/QhullFacetSet.h | 0 .../qhull/src/libqhullcpp/QhullHyperplane.cpp | 0 .../qhull/src/libqhullcpp/QhullHyperplane.h | 0 .../qhull/src/libqhullcpp/QhullIterator.h | 0 .../qhull/src/libqhullcpp/QhullLinkedList.h | 0 .../qhull/src/libqhullcpp/QhullPoint.cpp | 0 .../qhull/src/libqhullcpp/QhullPoint.h | 0 .../qhull/src/libqhullcpp/QhullPointSet.cpp | 0 .../qhull/src/libqhullcpp/QhullPointSet.h | 0 .../qhull/src/libqhullcpp/QhullPoints.cpp | 0 .../qhull/src/libqhullcpp/QhullPoints.h | 0 .../qhull/src/libqhullcpp/QhullQh.cpp | 0 .../qhull/src/libqhullcpp/QhullQh.h | 0 .../qhull/src/libqhullcpp/QhullRidge.cpp | 0 .../qhull/src/libqhullcpp/QhullRidge.h | 0 .../qhull/src/libqhullcpp/QhullSet.cpp | 0 .../qhull/src/libqhullcpp/QhullSet.h | 0 .../qhull/src/libqhullcpp/QhullSets.h | 0 .../qhull/src/libqhullcpp/QhullStat.cpp | 0 .../qhull/src/libqhullcpp/QhullStat.h | 0 .../qhull/src/libqhullcpp/QhullVertex.cpp | 0 .../qhull/src/libqhullcpp/QhullVertex.h | 0 .../qhull/src/libqhullcpp/QhullVertexSet.cpp | 0 .../qhull/src/libqhullcpp/QhullVertexSet.h | 0 .../qhull/src/libqhullcpp/RboxPoints.cpp | 0 .../qhull/src/libqhullcpp/RboxPoints.h | 0 .../qhull/src/libqhullcpp/RoadError.cpp | 0 .../qhull/src/libqhullcpp/RoadError.h | 0 .../qhull/src/libqhullcpp/RoadLogEvent.cpp | 0 .../qhull/src/libqhullcpp/RoadLogEvent.h | 0 .../qhull/src/libqhullcpp/functionObjects.h | 0 .../qhull/src/libqhullcpp/libqhullcpp.pro | 0 .../qhull/src/libqhullcpp/qt-qhull.cpp | 0 .../qhull/src/libqhullcpp/usermem_r-cpp.cpp | 0 .../src/libqhullstatic/libqhullstatic.pro | 0 .../src/libqhullstatic_r/libqhullstatic_r.pro | 0 {xs/src => src}/qhull/src/qconvex/qconvex.c | 0 {xs/src => src}/qhull/src/qconvex/qconvex.pro | 0 {xs/src => src}/qhull/src/qconvex/qconvex_r.c | 0 {xs/src => src}/qhull/src/qdelaunay/qdelaun.c | 0 .../qhull/src/qdelaunay/qdelaun_r.c | 0 .../qhull/src/qdelaunay/qdelaunay.pro | 0 {xs/src => src}/qhull/src/qhalf/qhalf.c | 0 {xs/src => src}/qhull/src/qhalf/qhalf.pro | 0 {xs/src => src}/qhull/src/qhalf/qhalf_r.c | 0 {xs/src => src}/qhull/src/qhull-all.pro | 0 {xs/src => src}/qhull/src/qhull-app-c.pri | 0 {xs/src => src}/qhull/src/qhull-app-c_r.pri | 0 {xs/src => src}/qhull/src/qhull-app-cpp.pri | 0 .../qhull/src/qhull-app-shared.pri | 0 .../qhull/src/qhull-app-shared_r.pri | 0 .../qhull/src/qhull-libqhull-src.pri | 0 .../qhull/src/qhull-libqhull-src_r.pri | 0 {xs/src => src}/qhull/src/qhull-warn.pri | 0 {xs/src => src}/qhull/src/qhull/qhull.pro | 0 {xs/src => src}/qhull/src/qhull/unix.c | 0 {xs/src => src}/qhull/src/qhull/unix_r.c | 0 .../qhull/src/qhulltest/Coordinates_test.cpp | 0 .../src/qhulltest/PointCoordinates_test.cpp | 0 .../src/qhulltest/QhullFacetList_test.cpp | 0 .../src/qhulltest/QhullFacetSet_test.cpp | 0 .../qhull/src/qhulltest/QhullFacet_test.cpp | 0 .../src/qhulltest/QhullHyperplane_test.cpp | 0 .../src/qhulltest/QhullLinkedList_test.cpp | 0 .../src/qhulltest/QhullPointSet_test.cpp | 0 .../qhull/src/qhulltest/QhullPoint_test.cpp | 0 .../qhull/src/qhulltest/QhullPoints_test.cpp | 0 .../qhull/src/qhulltest/QhullRidge_test.cpp | 0 .../qhull/src/qhulltest/QhullSet_test.cpp | 0 .../src/qhulltest/QhullVertexSet_test.cpp | 0 .../qhull/src/qhulltest/QhullVertex_test.cpp | 0 .../qhull/src/qhulltest/Qhull_test.cpp | 0 .../qhull/src/qhulltest/RboxPoints_test.cpp | 0 .../qhull/src/qhulltest/RoadTest.cpp | 0 .../qhull/src/qhulltest/RoadTest.h | 0 .../qhull/src/qhulltest/qhulltest.cpp | 0 .../qhull/src/qhulltest/qhulltest.pro | 0 {xs/src => src}/qhull/src/qvoronoi/qvoronoi.c | 0 .../qhull/src/qvoronoi/qvoronoi.pro | 0 .../qhull/src/qvoronoi/qvoronoi_r.c | 0 {xs/src => src}/qhull/src/rbox/rbox.c | 0 {xs/src => src}/qhull/src/rbox/rbox.pro | 0 {xs/src => src}/qhull/src/rbox/rbox_r.c | 0 {xs/src => src}/qhull/src/testqset/testqset.c | 0 .../qhull/src/testqset/testqset.pro | 0 .../qhull/src/testqset_r/testqset_r.c | 0 .../qhull/src/testqset_r/testqset_r.pro | 0 {xs/src => src}/qhull/src/user_eg/user_eg.c | 0 {xs/src => src}/qhull/src/user_eg/user_eg.pro | 0 {xs/src => src}/qhull/src/user_eg/user_eg_r.c | 0 {xs/src => src}/qhull/src/user_eg2/user_eg2.c | 0 .../qhull/src/user_eg2/user_eg2.pro | 0 .../qhull/src/user_eg2/user_eg2_r.c | 0 .../qhull/src/user_eg3/user_eg3.pro | 0 .../qhull/src/user_eg3/user_eg3_r.cpp | 0 src/semver/CMakeLists.txt | 7 + {xs/src => src}/semver/semver.c | 0 {xs/src => src}/semver/semver.h | 0 src/slic3r.cpp | 81 + {xs/src => src}/slic3r/AppController.cpp | 0 {xs/src => src}/slic3r/AppController.hpp | 0 {xs/src => src}/slic3r/AppControllerWx.cpp | 0 src/slic3r/CMakeLists.txt | 106 + {xs/src => src}/slic3r/Config/Snapshot.cpp | 0 {xs/src => src}/slic3r/Config/Snapshot.hpp | 0 {xs/src => src}/slic3r/Config/Version.cpp | 0 {xs/src => src}/slic3r/Config/Version.hpp | 0 {xs/src => src}/slic3r/GUI/2DBed.cpp | 0 {xs/src => src}/slic3r/GUI/2DBed.hpp | 0 {xs/src => src}/slic3r/GUI/3DScene.cpp | 0 {xs/src => src}/slic3r/GUI/3DScene.hpp | 0 {xs/src => src}/slic3r/GUI/AboutDialog.cpp | 0 {xs/src => src}/slic3r/GUI/AboutDialog.hpp | 0 {xs/src => src}/slic3r/GUI/AppConfig.cpp | 0 {xs/src => src}/slic3r/GUI/AppConfig.hpp | 0 .../slic3r/GUI/BackgroundSlicingProcess.cpp | 0 .../slic3r/GUI/BackgroundSlicingProcess.hpp | 0 {xs/src => src}/slic3r/GUI/BedShapeDialog.cpp | 0 {xs/src => src}/slic3r/GUI/BedShapeDialog.hpp | 0 {xs/src => src}/slic3r/GUI/BitmapCache.cpp | 0 {xs/src => src}/slic3r/GUI/BitmapCache.hpp | 0 {xs/src => src}/slic3r/GUI/BonjourDialog.cpp | 0 {xs/src => src}/slic3r/GUI/BonjourDialog.hpp | 0 .../slic3r/GUI/ButtonsDescription.cpp | 0 .../slic3r/GUI/ButtonsDescription.hpp | 0 .../slic3r/GUI/ConfigExceptions.hpp | 0 .../slic3r/GUI/ConfigSnapshotDialog.cpp | 0 .../slic3r/GUI/ConfigSnapshotDialog.hpp | 0 {xs/src => src}/slic3r/GUI/ConfigWizard.cpp | 0 {xs/src => src}/slic3r/GUI/ConfigWizard.hpp | 0 .../slic3r/GUI/ConfigWizard_private.hpp | 0 {xs/src => src}/slic3r/GUI/Field.cpp | 0 {xs/src => src}/slic3r/GUI/Field.hpp | 0 {xs/src => src}/slic3r/GUI/FirmwareDialog.cpp | 0 {xs/src => src}/slic3r/GUI/FirmwareDialog.hpp | 0 {xs/src => src}/slic3r/GUI/GLCanvas3D.cpp | 0 {xs/src => src}/slic3r/GUI/GLCanvas3D.hpp | 0 .../slic3r/GUI/GLCanvas3DManager.cpp | 0 .../slic3r/GUI/GLCanvas3DManager.hpp | 0 {xs/src => src}/slic3r/GUI/GLGizmo.cpp | 0 {xs/src => src}/slic3r/GUI/GLGizmo.hpp | 0 {xs/src => src}/slic3r/GUI/GLShader.cpp | 0 {xs/src => src}/slic3r/GUI/GLShader.hpp | 0 {xs/src => src}/slic3r/GUI/GLTexture.cpp | 0 {xs/src => src}/slic3r/GUI/GLTexture.hpp | 0 {xs/src => src}/slic3r/GUI/GLToolbar.cpp | 0 {xs/src => src}/slic3r/GUI/GLToolbar.hpp | 0 {xs/src => src}/slic3r/GUI/GUI.cpp | 15 + {xs/src => src}/slic3r/GUI/GUI.hpp | 5 + .../slic3r/GUI/GUI_ObjectParts.cpp | 0 .../slic3r/GUI/GUI_ObjectParts.hpp | 0 .../slic3r/GUI/LambdaObjectDialog.cpp | 0 .../slic3r/GUI/LambdaObjectDialog.hpp | 0 {xs/src => src}/slic3r/GUI/MsgDialog.cpp | 0 {xs/src => src}/slic3r/GUI/MsgDialog.hpp | 0 {xs/src => src}/slic3r/GUI/OptionsGroup.cpp | 0 {xs/src => src}/slic3r/GUI/OptionsGroup.hpp | 0 {xs/src => src}/slic3r/GUI/Preferences.cpp | 0 {xs/src => src}/slic3r/GUI/Preferences.hpp | 0 {xs/src => src}/slic3r/GUI/Preset.cpp | 0 {xs/src => src}/slic3r/GUI/Preset.hpp | 0 {xs/src => src}/slic3r/GUI/PresetBundle.cpp | 0 {xs/src => src}/slic3r/GUI/PresetBundle.hpp | 0 {xs/src => src}/slic3r/GUI/PresetHints.cpp | 0 {xs/src => src}/slic3r/GUI/PresetHints.hpp | 0 .../slic3r/GUI/ProgressIndicator.hpp | 0 .../slic3r/GUI/ProgressStatusBar.cpp | 0 .../slic3r/GUI/ProgressStatusBar.hpp | 2 +- {xs/src => src}/slic3r/GUI/RammingChart.cpp | 0 {xs/src => src}/slic3r/GUI/RammingChart.hpp | 0 {xs/src => src}/slic3r/GUI/Tab.cpp | 0 {xs/src => src}/slic3r/GUI/Tab.hpp | 0 {xs/src => src}/slic3r/GUI/TabIface.cpp | 0 {xs/src => src}/slic3r/GUI/TabIface.hpp | 0 {xs/src => src}/slic3r/GUI/UpdateDialogs.cpp | 0 {xs/src => src}/slic3r/GUI/UpdateDialogs.hpp | 0 {xs/src => src}/slic3r/GUI/Widget.hpp | 0 .../slic3r/GUI/WipeTowerDialog.cpp | 0 .../slic3r/GUI/WipeTowerDialog.hpp | 0 src/slic3r/GUI/callback.hpp | 30 + {xs/src => src}/slic3r/GUI/wxExtensions.cpp | 0 {xs/src => src}/slic3r/GUI/wxExtensions.hpp | 0 {xs/src => src}/slic3r/GUI/wxinit.h | 0 {xs/src => src}/slic3r/Utils/ASCIIFolding.cpp | 0 {xs/src => src}/slic3r/Utils/ASCIIFolding.hpp | 0 {xs/src => src}/slic3r/Utils/Bonjour.cpp | 0 {xs/src => src}/slic3r/Utils/Bonjour.hpp | 0 {xs/src => src}/slic3r/Utils/Duet.cpp | 0 {xs/src => src}/slic3r/Utils/Duet.hpp | 0 .../slic3r/Utils/FixModelByWin10.cpp | 0 .../slic3r/Utils/FixModelByWin10.hpp | 0 {xs/src => src}/slic3r/Utils/HexFile.cpp | 0 {xs/src => src}/slic3r/Utils/HexFile.hpp | 0 {xs/src => src}/slic3r/Utils/Http.cpp | 0 {xs/src => src}/slic3r/Utils/Http.hpp | 0 {xs/src => src}/slic3r/Utils/OctoPrint.cpp | 0 {xs/src => src}/slic3r/Utils/OctoPrint.hpp | 0 .../slic3r/Utils/PresetUpdater.cpp | 0 .../slic3r/Utils/PresetUpdater.hpp | 0 {xs/src => src}/slic3r/Utils/PrintHost.cpp | 0 {xs/src => src}/slic3r/Utils/PrintHost.hpp | 0 .../slic3r/Utils/PrintHostSendDialog.cpp | 0 .../slic3r/Utils/PrintHostSendDialog.hpp | 0 {xs/src => src}/slic3r/Utils/Semver.hpp | 0 {xs/src => src}/slic3r/Utils/Serial.cpp | 0 {xs/src => src}/slic3r/Utils/Serial.hpp | 0 {xs/src => src}/slic3r/Utils/Time.cpp | 0 {xs/src => src}/slic3r/Utils/Time.hpp | 0 xs/CMakeLists.txt | 685 +- .../EDBG/protocoldocs/ch03s01s01.html~ | 215 - xs/src/libnest2d/tools/benchmark.h | 58 - xs/src/slic3r/GUI/wxPerlIface.cpp | 97 - 1706 files changed, 7413 insertions(+), 7638 deletions(-) create mode 100644 resources/localization/CMakeLists.txt create mode 100644 src/CMakeLists.txt create mode 100644 src/Shiny/CMakeLists.txt rename {xs/src => src}/Shiny/Shiny.h (100%) rename {xs/src => src}/Shiny/ShinyConfig.h (100%) rename {xs/src => src}/Shiny/ShinyData.h (100%) rename {xs/src => src}/Shiny/ShinyMacros.h (100%) rename {xs/src => src}/Shiny/ShinyManager.c (100%) rename {xs/src => src}/Shiny/ShinyManager.h (100%) rename {xs/src => src}/Shiny/ShinyNode.c (100%) rename {xs/src => src}/Shiny/ShinyNode.h (100%) rename {xs/src => src}/Shiny/ShinyNodePool.c (100%) rename {xs/src => src}/Shiny/ShinyNodePool.h (100%) rename {xs/src => src}/Shiny/ShinyNodeState.c (100%) rename {xs/src => src}/Shiny/ShinyNodeState.h (100%) rename {xs/src => src}/Shiny/ShinyOutput.c (100%) rename {xs/src => src}/Shiny/ShinyOutput.h (100%) rename {xs/src => src}/Shiny/ShinyPrereqs.h (100%) rename {xs/src => src}/Shiny/ShinyTools.c (100%) rename {xs/src => src}/Shiny/ShinyTools.h (100%) rename {xs/src => src}/Shiny/ShinyVersion.h (100%) rename {xs/src => src}/Shiny/ShinyZone.c (100%) rename {xs/src => src}/Shiny/ShinyZone.h (100%) create mode 100644 src/admesh/CMakeLists.txt rename {xs/src => src}/admesh/connect.cpp (100%) rename {xs/src => src}/admesh/normals.cpp (100%) rename {xs/src => src}/admesh/shared.cpp (100%) rename {xs/src => src}/admesh/stl.h (100%) rename {xs/src => src}/admesh/stl_io.cpp (100%) rename {xs/src => src}/admesh/stlinit.cpp (100%) rename {xs/src => src}/admesh/util.cpp (100%) rename {xs/src => src}/agg/AUTHORS (100%) rename {xs/src => src}/agg/VERSION (100%) rename {xs/src => src}/agg/agg_array.h (100%) rename {xs/src => src}/agg/agg_basics.h (100%) rename {xs/src => src}/agg/agg_bezier_arc.h (100%) rename {xs/src => src}/agg/agg_clip_liang_barsky.h (100%) rename {xs/src => src}/agg/agg_color_gray.h (100%) rename {xs/src => src}/agg/agg_color_rgba.h (100%) rename {xs/src => src}/agg/agg_config.h (100%) rename {xs/src => src}/agg/agg_conv_transform.h (100%) rename {xs/src => src}/agg/agg_gamma_functions.h (100%) rename {xs/src => src}/agg/agg_gamma_lut.h (100%) rename {xs/src => src}/agg/agg_math.h (100%) rename {xs/src => src}/agg/agg_path_storage.h (100%) rename {xs/src => src}/agg/agg_pixfmt_base.h (100%) rename {xs/src => src}/agg/agg_pixfmt_gray.h (100%) rename {xs/src => src}/agg/agg_pixfmt_rgb.h (100%) rename {xs/src => src}/agg/agg_rasterizer_cells_aa.h (100%) rename {xs/src => src}/agg/agg_rasterizer_scanline_aa.h (100%) rename {xs/src => src}/agg/agg_rasterizer_scanline_aa_nogamma.h (100%) rename {xs/src => src}/agg/agg_rasterizer_sl_clip.h (100%) rename {xs/src => src}/agg/agg_renderer_base.h (100%) rename {xs/src => src}/agg/agg_renderer_scanline.h (100%) rename {xs/src => src}/agg/agg_rendering_buffer.h (100%) rename {xs/src => src}/agg/agg_scanline_p.h (100%) rename {xs/src => src}/agg/agg_trans_affine.h (100%) rename {xs/src => src}/agg/copying (100%) rename {xs/src => src}/avrdude/AUTHORS (100%) rename {xs/src => src}/avrdude/BUILD-FROM-SVN (100%) rename {xs/src => src}/avrdude/CMakeLists.txt (100%) rename {xs/src => src}/avrdude/COPYING (100%) rename {xs/src => src}/avrdude/ChangeLog (100%) rename {xs/src => src}/avrdude/ChangeLog-2001 (100%) rename {xs/src => src}/avrdude/ChangeLog-2002 (100%) rename {xs/src => src}/avrdude/ChangeLog-2003 (100%) rename {xs/src => src}/avrdude/ChangeLog-2004-2006 (100%) rename {xs/src => src}/avrdude/ChangeLog-2007 (100%) rename {xs/src => src}/avrdude/ChangeLog-2008 (100%) rename {xs/src => src}/avrdude/ChangeLog-2009 (100%) rename {xs/src => src}/avrdude/ChangeLog-2010 (100%) rename {xs/src => src}/avrdude/ChangeLog-2011 (100%) rename {xs/src => src}/avrdude/ChangeLog-2012 (100%) rename {xs/src => src}/avrdude/ChangeLog-2013 (100%) rename {xs/src => src}/avrdude/ChangeLog-2014 (100%) rename {xs/src => src}/avrdude/ChangeLog-2015 (100%) rename {xs/src => src}/avrdude/Makefile.am (100%) rename {xs/src => src}/avrdude/Makefile.standalone (100%) rename {xs/src => src}/avrdude/NEWS (100%) rename {xs/src => src}/avrdude/README (100%) rename {xs/src => src}/avrdude/ac_cfg.h (100%) rename {xs/src => src}/avrdude/ac_cfg.h.in (100%) rename {xs/src => src}/avrdude/arduino.c (100%) rename {xs/src => src}/avrdude/arduino.h (100%) rename {xs/src => src}/avrdude/atmel-docs/AVR109.pdf (100%) rename {xs/src => src}/avrdude/atmel-docs/AVR910.pdf (100%) rename {xs/src => src}/avrdude/atmel-docs/AVRISPmkII-AVR069.pdf (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/browserDetect.js (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/css/960.css (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/css/docbook.css (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/css/fluid_grid.css (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/css/index.css (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/css/positioning.css (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/css/print.css (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/css/reset.css (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/css/text.css (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/fonts/DroidSansMono.eot (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/fonts/DroidSansMono.ttf (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/images/Book_Closed.png (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/images/Book_Open.png (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/images/Document_Text.png (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/images/Library.png (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/images/external_link.gif (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/images/loading.gif (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/images/logo.png (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/images/minus.png (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/images/next-arrow.png (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/images/plus.png (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/images/previous-arrow.png (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/images/search-icon.png (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/images/sidebar.png (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/images/starsSmall.png (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/images/toc-icon.png (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/images/ui-icons_217bc0_256x240.png (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/jquery/jquery-1.7.2.min.js (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/jquery/jquery.cookie.js (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/jquery/jquery.ui.all.js (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/jquery/layout/jquery.layout.js (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-anim_basic_16x16.gif (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-bg_flat_0_aaaaaa_40x100.png (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-bg_flat_55_fbec88_40x100.png (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-bg_glass_75_d0e5f5_1x400.png (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-bg_glass_85_dfeffc_1x400.png (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-bg_glass_95_fef1ec_1x400.png (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-bg_inset-hard_100_f5f8f9_1x100.png (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-bg_inset-hard_100_fcfdfd_1x100.png (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-icons_217bc0_256x240.png (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-icons_2e83ff_256x240.png (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-icons_469bdd_256x240.png (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-icons_6da8d5_256x240.png (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-icons_cd0a0a_256x240.png (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-icons_d8e7f3_256x240.png (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-icons_f9bd01_256x240.png (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/jquery-ui-1.8.2.custom.css (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/file.gif (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/folder-closed.gif (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/folder.gif (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/treeview-black-line.gif (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/treeview-black.gif (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/treeview-default-line.gif (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/treeview-default.gif (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/treeview-famfamfam-line.gif (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/treeview-famfamfam.gif (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/treeview-gray-line.gif (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/treeview-gray.gif (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/treeview-red-line.gif (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/treeview-red.gif (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/jquery/treeview/jquery.treeview.css (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/jquery/treeview/jquery.treeview.min.js (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/main.js (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/common/splitterInit.js (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch01s01.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch01s02.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch02s01.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch02s02.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch02s02s01.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch02s02s02.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch02s02s02s01.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch02s02s02s02.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch02s02s03.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch02s02s03s01.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch02s02s03s02.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch02s02s03s03.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch02s02s03s04.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch02s03s01.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch02s03s02.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch02s03s03.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch02s03s04.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch02s03s05.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch02s03s06.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch02s03s07.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch02s03s08.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch02s03s09.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch02s04.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch02s04s01.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch02s04s02.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch02s04s03.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch03s01.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch03s01s01.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch03s01s02.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch03s01s03.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch03s01s03s01.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch03s02.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch03s02s01.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch03s02s02.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch03s02s03.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch03s02s04.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch04s01.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch04s02.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch04s03.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch04s04.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch04s04s01.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch04s04s03.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch04s04s04.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch04s04s05.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s01.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s03.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s04.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s06.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s06s02.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s06s03.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s06s04.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s06s05.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s07.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s07s01.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s07s02.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s07s03.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s07s04.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s08.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s08s01.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s08s02.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s08s03.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s09.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s10.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s01.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s02.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s03.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s04.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s05.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s06.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s07.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s08.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s09.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s10.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s11.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s12.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s13.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s14.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s15.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch05s02.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch05s02s01.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch05s02s02.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch05s02s03.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch05s02s04.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch05s02s05.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch05s02s06.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch05s03.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch05s03s01.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch05s03s02.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch05s03s03.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch05s04.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s01.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s02.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s03.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s04.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s05.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s06.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s07.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s08.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s09.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s10.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s11.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s12.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s13.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s14.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s15.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s16.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s17.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s18.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s19.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s20.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s21.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s22.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s23.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s24.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s25.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s26.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s27.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s28.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s29.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch06s02.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch06s02s01.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch06s02s02.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch06s02s03.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch06s02s04.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch06s02s05.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch06s03.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch06s03s01.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch06s03s02.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch06s04s01.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch06s04s02.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch06s04s03.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch06s05.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch06s05s01.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch06s05s02.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch06s05s03.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch06s05s04.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch06s05s05.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch06s06.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s01.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s02.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s03.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s04.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s05.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s06.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s07.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s08.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s09.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s10.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s11.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s12.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s13.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s14.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s15.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s16.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s17.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch07s02.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch07s03.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch08s01.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch08s01s01.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch08s01s02.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch08s01s03.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch08s01s04.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch08s01s05.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch08s01s06.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch08s02.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/ch08s03.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/document.revisions.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/index.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/pr01.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/protocoldocs.Introduction.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/protocoldocs.avr32protocol.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/protocoldocs.avr8protocol.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/protocoldocs.avrispprotocol.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/protocoldocs.avrprotocol.Overview.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/protocoldocs.cmsis_dap.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/protocoldocs.edbg_ctrl_protocol.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/protocoldocs.tpiprotocol.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/search/htmlFileInfoList.js (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/search/index-1.js (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/search/index-2.js (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/search/index-3.js (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/search/l10n.js (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/search/nwSearchFnt.js (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/search/stemmers/en_stemmer.js (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/section_avr32_memtypes.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/section_avr32_setget_params.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/section_avr8_memtypes.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/section_avr8_query_contexts.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/section_avr8_setget_params.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/section_edbg_ctrl_setget_params.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/section_edbg_query_contexts.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/section_housekeeping_start_session.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/section_i5v_3yz_rl.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/section_jdx_m11_sl.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/section_qhb_x1c_sl.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/section_serial_trace.html (100%) rename {xs/src => src}/avrdude/atmel-docs/EDBG/protocoldocs/section_t1f_hb1_sl.html (100%) rename {xs/src => src}/avrdude/atmel-docs/JTAGICE-AVR060.pdf (100%) rename {xs/src => src}/avrdude/atmel-docs/JTAGICEmkII-AVR067.pdf (100%) rename {xs/src => src}/avrdude/atmel-docs/STK500-AVR061.pdf (100%) rename {xs/src => src}/avrdude/atmel-docs/STK500v2-AVR068.pdf (100%) rename {xs/src => src}/avrdude/avr.c (100%) rename {xs/src => src}/avrdude/avr910.c (100%) rename {xs/src => src}/avrdude/avr910.h (100%) rename {xs/src => src}/avrdude/avrdude-slic3r.cpp (100%) rename {xs/src => src}/avrdude/avrdude-slic3r.hpp (100%) rename {xs/src => src}/avrdude/avrdude.1 (100%) rename {xs/src => src}/avrdude/avrdude.conf (100%) rename {xs/src => src}/avrdude/avrdude.conf.in (100%) rename {xs/src => src}/avrdude/avrdude.conf.tmp (100%) rename {xs/src => src}/avrdude/avrdude.h (100%) rename {xs/src => src}/avrdude/avrdude.spec.in (100%) rename {xs/src => src}/avrdude/avrftdi.c (100%) rename {xs/src => src}/avrdude/avrftdi.h (100%) rename {xs/src => src}/avrdude/avrftdi_private.h (100%) rename {xs/src => src}/avrdude/avrftdi_tpi.c (100%) rename {xs/src => src}/avrdude/avrftdi_tpi.h (100%) rename {xs/src => src}/avrdude/avrpart.c (100%) rename {xs/src => src}/avrdude/bitbang.c (100%) rename {xs/src => src}/avrdude/bitbang.h (100%) rename {xs/src => src}/avrdude/bootstrap (100%) mode change 100755 => 100644 rename {xs/src => src}/avrdude/buspirate.c (100%) rename {xs/src => src}/avrdude/buspirate.h (100%) rename {xs/src => src}/avrdude/butterfly.c (100%) rename {xs/src => src}/avrdude/butterfly.h (100%) rename {xs/src => src}/avrdude/config.c (100%) rename {xs/src => src}/avrdude/config.h (100%) rename {xs/src => src}/avrdude/config_gram.c (100%) rename {xs/src => src}/avrdude/config_gram.h (100%) rename {xs/src => src}/avrdude/config_gram.y (100%) rename {xs/src => src}/avrdude/configure.ac (100%) rename {xs/src => src}/avrdude/confwin.c (100%) rename {xs/src => src}/avrdude/crc16.c (100%) rename {xs/src => src}/avrdude/crc16.h (100%) rename {xs/src => src}/avrdude/dfu.c (100%) rename {xs/src => src}/avrdude/dfu.h (100%) rename {xs/src => src}/avrdude/doc/.cvsignore (100%) rename {xs/src => src}/avrdude/doc/Makefile.am (100%) rename {xs/src => src}/avrdude/doc/TODO (100%) rename {xs/src => src}/avrdude/doc/avrdude.texi (100%) rename {xs/src => src}/avrdude/doc/parts_comments.txt (100%) rename {xs/src => src}/avrdude/fileio.c (100%) rename {xs/src => src}/avrdude/flip1.c (100%) rename {xs/src => src}/avrdude/flip1.h (100%) rename {xs/src => src}/avrdude/flip2.c (100%) rename {xs/src => src}/avrdude/flip2.h (100%) rename {xs/src => src}/avrdude/freebsd_ppi.h (100%) rename {xs/src => src}/avrdude/ft245r.c (100%) rename {xs/src => src}/avrdude/ft245r.h (100%) rename {xs/src => src}/avrdude/jtag3.c (100%) rename {xs/src => src}/avrdude/jtag3.h (100%) rename {xs/src => src}/avrdude/jtag3_private.h (100%) rename {xs/src => src}/avrdude/jtagmkI.c (100%) rename {xs/src => src}/avrdude/jtagmkI.h (100%) rename {xs/src => src}/avrdude/jtagmkII.c (100%) rename {xs/src => src}/avrdude/jtagmkII.h (100%) rename {xs/src => src}/avrdude/jtagmkII_private.h (100%) rename {xs/src => src}/avrdude/jtagmkI_private.h (100%) rename {xs/src => src}/avrdude/lexer.c (100%) rename {xs/src => src}/avrdude/lexer.l (100%) rename {xs/src => src}/avrdude/libavrdude.h (100%) rename {xs/src => src}/avrdude/linux_ppdev.h (100%) rename {xs/src => src}/avrdude/linuxgpio.c (100%) rename {xs/src => src}/avrdude/linuxgpio.h (100%) rename {xs/src => src}/avrdude/lists.c (100%) rename {xs/src => src}/avrdude/main-standalone.c (100%) rename {xs/src => src}/avrdude/main.c (100%) rename {xs/src => src}/avrdude/my_ddk_hidsdi.h (100%) rename {xs/src => src}/avrdude/par.c (100%) rename {xs/src => src}/avrdude/par.h (100%) rename {xs/src => src}/avrdude/pgm.c (100%) rename {xs/src => src}/avrdude/pgm_type.c (100%) rename {xs/src => src}/avrdude/pickit2.c (100%) rename {xs/src => src}/avrdude/pickit2.h (100%) rename {xs/src => src}/avrdude/pindefs.c (100%) rename {xs/src => src}/avrdude/ppi.c (100%) rename {xs/src => src}/avrdude/ppi.h (100%) rename {xs/src => src}/avrdude/ppiwin.c (100%) rename {xs/src => src}/avrdude/safemode.c (100%) rename {xs/src => src}/avrdude/ser_avrdoper.c (100%) rename {xs/src => src}/avrdude/ser_posix.c (100%) rename {xs/src => src}/avrdude/ser_win32.c (100%) rename {xs/src => src}/avrdude/serbb.h (100%) rename {xs/src => src}/avrdude/serbb_posix.c (100%) rename {xs/src => src}/avrdude/serbb_win32.c (100%) rename {xs/src => src}/avrdude/solaris_ecpp.h (100%) rename {xs/src => src}/avrdude/stk500.c (100%) rename {xs/src => src}/avrdude/stk500.h (100%) rename {xs/src => src}/avrdude/stk500_private.h (100%) rename {xs/src => src}/avrdude/stk500generic.c (100%) rename {xs/src => src}/avrdude/stk500generic.h (100%) rename {xs/src => src}/avrdude/stk500v2.c (100%) rename {xs/src => src}/avrdude/stk500v2.h (100%) rename {xs/src => src}/avrdude/stk500v2_private.h (100%) rename {xs/src => src}/avrdude/term.c (100%) rename {xs/src => src}/avrdude/term.h (100%) rename {xs/src => src}/avrdude/tools/build-mingw32.sh (100%) mode change 100755 => 100644 rename {xs/src => src}/avrdude/tools/get-dw-params.xsl (100%) rename {xs/src => src}/avrdude/tools/get-hv-params.xsl (100%) rename {xs/src => src}/avrdude/tools/get-stk600-cards.xsl (100%) rename {xs/src => src}/avrdude/tools/get-stk600-devices.xsl (100%) rename {xs/src => src}/avrdude/tpi.h (100%) rename {xs/src => src}/avrdude/update.c (100%) rename {xs/src => src}/avrdude/usb_hidapi.c (100%) rename {xs/src => src}/avrdude/usb_libusb.c (100%) rename {xs/src => src}/avrdude/usbasp.c (100%) rename {xs/src => src}/avrdude/usbasp.h (100%) rename {xs/src => src}/avrdude/usbdevs.h (100%) rename {xs/src => src}/avrdude/usbtiny.c (100%) rename {xs/src => src}/avrdude/usbtiny.h (100%) rename {xs/src => src}/avrdude/windows/.cvsignore (100%) rename {xs/src => src}/avrdude/windows/Makefile.am (100%) rename {xs/src => src}/avrdude/windows/getopt.c (100%) rename {xs/src => src}/avrdude/windows/getopt.h (100%) rename {xs/src => src}/avrdude/windows/giveio.c (100%) rename {xs/src => src}/avrdude/windows/giveio.sys (100%) rename {xs/src => src}/avrdude/windows/install_giveio.bat (100%) mode change 100755 => 100644 rename {xs/src => src}/avrdude/windows/loaddrv.c (100%) rename {xs/src => src}/avrdude/windows/loaddrv.h (100%) rename {xs/src => src}/avrdude/windows/remove_giveio.bat (100%) mode change 100755 => 100644 rename {xs/src => src}/avrdude/windows/status_giveio.bat (100%) mode change 100755 => 100644 rename {xs/src => src}/avrdude/windows/unistd.cpp (100%) rename {xs/src => src}/avrdude/windows/unistd.h (100%) rename {xs/src => src}/avrdude/wiring.c (100%) rename {xs/src => src}/avrdude/wiring.h (100%) create mode 100644 src/boost/CMakeLists.txt rename {xs/src => src}/boost/nowide/args.hpp (100%) rename {xs/src => src}/boost/nowide/cenv.hpp (100%) rename {xs/src => src}/boost/nowide/config.hpp (100%) rename {xs/src => src}/boost/nowide/convert.hpp (100%) rename {xs/src => src}/boost/nowide/cstdio.hpp (100%) rename {xs/src => src}/boost/nowide/cstdlib.hpp (100%) rename {xs/src => src}/boost/nowide/filebuf.hpp (100%) rename {xs/src => src}/boost/nowide/fstream.hpp (100%) rename {xs/src => src}/boost/nowide/integration/filesystem.hpp (100%) rename {xs/src => src}/boost/nowide/iostream.cpp (100%) rename {xs/src => src}/boost/nowide/iostream.hpp (100%) rename {xs/src => src}/boost/nowide/stackstring.hpp (100%) rename {xs/src => src}/boost/nowide/system.hpp (100%) rename {xs/src => src}/boost/nowide/utf8_codecvt.hpp (100%) rename {xs/src => src}/boost/nowide/windows.hpp (100%) create mode 100644 src/clipper/CMakeLists.txt rename {xs/src => src/clipper}/clipper.cpp (96%) rename {xs/src => src/clipper}/clipper.hpp (97%) rename {xs/src => src}/eigen/COPYING.README (100%) rename {xs/src => src}/eigen/Eigen/CMakeLists.txt (100%) rename {xs/src => src}/eigen/Eigen/Cholesky (100%) rename {xs/src => src}/eigen/Eigen/CholmodSupport (100%) rename {xs/src => src}/eigen/Eigen/Core (100%) rename {xs/src => src}/eigen/Eigen/Dense (100%) rename {xs/src => src}/eigen/Eigen/Eigen (100%) rename {xs/src => src}/eigen/Eigen/Eigenvalues (100%) rename {xs/src => src}/eigen/Eigen/Geometry (100%) rename {xs/src => src}/eigen/Eigen/Householder (100%) rename {xs/src => src}/eigen/Eigen/IterativeLinearSolvers (100%) rename {xs/src => src}/eigen/Eigen/Jacobi (100%) rename {xs/src => src}/eigen/Eigen/LU (100%) rename {xs/src => src}/eigen/Eigen/MetisSupport (100%) rename {xs/src => src}/eigen/Eigen/OrderingMethods (100%) rename {xs/src => src}/eigen/Eigen/PaStiXSupport (100%) rename {xs/src => src}/eigen/Eigen/PardisoSupport (100%) rename {xs/src => src}/eigen/Eigen/QR (100%) rename {xs/src => src}/eigen/Eigen/QtAlignedMalloc (100%) rename {xs/src => src}/eigen/Eigen/SPQRSupport (100%) rename {xs/src => src}/eigen/Eigen/SVD (100%) rename {xs/src => src}/eigen/Eigen/Sparse (100%) rename {xs/src => src}/eigen/Eigen/SparseCholesky (100%) rename {xs/src => src}/eigen/Eigen/SparseCore (100%) rename {xs/src => src}/eigen/Eigen/SparseLU (100%) rename {xs/src => src}/eigen/Eigen/SparseQR (100%) rename {xs/src => src}/eigen/Eigen/StdDeque (100%) rename {xs/src => src}/eigen/Eigen/StdList (100%) rename {xs/src => src}/eigen/Eigen/StdVector (100%) rename {xs/src => src}/eigen/Eigen/SuperLUSupport (100%) rename {xs/src => src}/eigen/Eigen/UmfPackSupport (100%) rename {xs/src => src}/eigen/Eigen/src/Cholesky/LDLT.h (100%) rename {xs/src => src}/eigen/Eigen/src/Cholesky/LLT.h (100%) rename {xs/src => src}/eigen/Eigen/src/Cholesky/LLT_LAPACKE.h (100%) rename {xs/src => src}/eigen/Eigen/src/CholmodSupport/CholmodSupport.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/Array.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/ArrayBase.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/ArrayWrapper.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/Assign.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/AssignEvaluator.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/Assign_MKL.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/BandMatrix.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/Block.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/BooleanRedux.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/CommaInitializer.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/ConditionEstimator.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/CoreEvaluators.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/CoreIterators.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/CwiseBinaryOp.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/CwiseNullaryOp.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/CwiseTernaryOp.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/CwiseUnaryOp.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/CwiseUnaryView.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/DenseBase.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/DenseCoeffsBase.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/DenseStorage.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/Diagonal.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/DiagonalMatrix.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/DiagonalProduct.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/Dot.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/EigenBase.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/ForceAlignedAccess.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/Fuzzy.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/GeneralProduct.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/GenericPacketMath.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/GlobalFunctions.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/IO.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/Inverse.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/Map.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/MapBase.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/MathFunctions.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/MathFunctionsImpl.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/Matrix.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/MatrixBase.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/NestByValue.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/NoAlias.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/NumTraits.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/PermutationMatrix.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/PlainObjectBase.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/Product.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/ProductEvaluators.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/Random.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/Redux.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/Ref.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/Replicate.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/ReturnByValue.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/Reverse.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/Select.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/SelfAdjointView.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/SelfCwiseBinaryOp.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/Solve.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/SolveTriangular.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/SolverBase.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/StableNorm.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/Stride.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/Swap.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/Transpose.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/Transpositions.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/TriangularMatrix.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/VectorBlock.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/VectorwiseOp.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/Visitor.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/arch/AVX/Complex.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/arch/AVX/MathFunctions.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/arch/AVX/PacketMath.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/arch/AVX/TypeCasting.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/arch/AVX512/MathFunctions.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/arch/AVX512/PacketMath.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/arch/AltiVec/Complex.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/arch/AltiVec/MathFunctions.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/arch/AltiVec/PacketMath.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/arch/CUDA/Complex.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/arch/CUDA/Half.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/arch/CUDA/MathFunctions.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/arch/CUDA/PacketMath.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/arch/CUDA/PacketMathHalf.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/arch/CUDA/TypeCasting.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/arch/Default/ConjHelper.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/arch/Default/Settings.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/arch/NEON/Complex.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/arch/NEON/MathFunctions.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/arch/NEON/PacketMath.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/arch/SSE/Complex.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/arch/SSE/MathFunctions.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/arch/SSE/PacketMath.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/arch/SSE/TypeCasting.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/arch/ZVector/Complex.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/arch/ZVector/MathFunctions.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/arch/ZVector/PacketMath.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/functors/AssignmentFunctors.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/functors/BinaryFunctors.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/functors/NullaryFunctors.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/functors/StlFunctors.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/functors/TernaryFunctors.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/functors/UnaryFunctors.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/products/GeneralBlockPanelKernel.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/products/GeneralMatrixMatrix.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/products/GeneralMatrixMatrixTriangular_BLAS.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/products/GeneralMatrixMatrix_BLAS.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/products/GeneralMatrixVector.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/products/GeneralMatrixVector_BLAS.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/products/Parallelizer.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/products/SelfadjointMatrixMatrix.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/products/SelfadjointMatrixMatrix_BLAS.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/products/SelfadjointMatrixVector.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/products/SelfadjointMatrixVector_BLAS.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/products/SelfadjointProduct.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/products/SelfadjointRank2Update.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/products/TriangularMatrixMatrix.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/products/TriangularMatrixMatrix_BLAS.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/products/TriangularMatrixVector.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/products/TriangularMatrixVector_BLAS.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/products/TriangularSolverMatrix.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/products/TriangularSolverMatrix_BLAS.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/products/TriangularSolverVector.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/util/BlasUtil.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/util/Constants.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/util/DisableStupidWarnings.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/util/ForwardDeclarations.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/util/MKL_support.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/util/Macros.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/util/Memory.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/util/Meta.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/util/NonMPL2.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/util/ReenableStupidWarnings.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/util/StaticAssert.h (100%) rename {xs/src => src}/eigen/Eigen/src/Core/util/XprHelper.h (100%) rename {xs/src => src}/eigen/Eigen/src/Eigenvalues/ComplexEigenSolver.h (100%) rename {xs/src => src}/eigen/Eigen/src/Eigenvalues/ComplexSchur.h (100%) rename {xs/src => src}/eigen/Eigen/src/Eigenvalues/ComplexSchur_LAPACKE.h (100%) rename {xs/src => src}/eigen/Eigen/src/Eigenvalues/EigenSolver.h (100%) rename {xs/src => src}/eigen/Eigen/src/Eigenvalues/GeneralizedEigenSolver.h (100%) rename {xs/src => src}/eigen/Eigen/src/Eigenvalues/GeneralizedSelfAdjointEigenSolver.h (100%) rename {xs/src => src}/eigen/Eigen/src/Eigenvalues/HessenbergDecomposition.h (100%) rename {xs/src => src}/eigen/Eigen/src/Eigenvalues/MatrixBaseEigenvalues.h (100%) rename {xs/src => src}/eigen/Eigen/src/Eigenvalues/RealQZ.h (100%) rename {xs/src => src}/eigen/Eigen/src/Eigenvalues/RealSchur.h (100%) rename {xs/src => src}/eigen/Eigen/src/Eigenvalues/RealSchur_LAPACKE.h (100%) rename {xs/src => src}/eigen/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h (100%) rename {xs/src => src}/eigen/Eigen/src/Eigenvalues/SelfAdjointEigenSolver_LAPACKE.h (100%) rename {xs/src => src}/eigen/Eigen/src/Eigenvalues/Tridiagonalization.h (100%) rename {xs/src => src}/eigen/Eigen/src/Geometry/AlignedBox.h (100%) rename {xs/src => src}/eigen/Eigen/src/Geometry/AngleAxis.h (100%) rename {xs/src => src}/eigen/Eigen/src/Geometry/EulerAngles.h (100%) rename {xs/src => src}/eigen/Eigen/src/Geometry/Homogeneous.h (100%) rename {xs/src => src}/eigen/Eigen/src/Geometry/Hyperplane.h (100%) rename {xs/src => src}/eigen/Eigen/src/Geometry/OrthoMethods.h (100%) rename {xs/src => src}/eigen/Eigen/src/Geometry/ParametrizedLine.h (100%) rename {xs/src => src}/eigen/Eigen/src/Geometry/Quaternion.h (100%) rename {xs/src => src}/eigen/Eigen/src/Geometry/Rotation2D.h (100%) rename {xs/src => src}/eigen/Eigen/src/Geometry/RotationBase.h (100%) rename {xs/src => src}/eigen/Eigen/src/Geometry/Scaling.h (100%) rename {xs/src => src}/eigen/Eigen/src/Geometry/Transform.h (100%) rename {xs/src => src}/eigen/Eigen/src/Geometry/Translation.h (100%) rename {xs/src => src}/eigen/Eigen/src/Geometry/Umeyama.h (100%) rename {xs/src => src}/eigen/Eigen/src/Geometry/arch/Geometry_SSE.h (100%) rename {xs/src => src}/eigen/Eigen/src/Householder/BlockHouseholder.h (100%) rename {xs/src => src}/eigen/Eigen/src/Householder/Householder.h (100%) rename {xs/src => src}/eigen/Eigen/src/Householder/HouseholderSequence.h (100%) rename {xs/src => src}/eigen/Eigen/src/IterativeLinearSolvers/BasicPreconditioners.h (100%) rename {xs/src => src}/eigen/Eigen/src/IterativeLinearSolvers/BiCGSTAB.h (100%) rename {xs/src => src}/eigen/Eigen/src/IterativeLinearSolvers/ConjugateGradient.h (100%) rename {xs/src => src}/eigen/Eigen/src/IterativeLinearSolvers/IncompleteCholesky.h (100%) rename {xs/src => src}/eigen/Eigen/src/IterativeLinearSolvers/IncompleteLUT.h (100%) rename {xs/src => src}/eigen/Eigen/src/IterativeLinearSolvers/IterativeSolverBase.h (100%) rename {xs/src => src}/eigen/Eigen/src/IterativeLinearSolvers/LeastSquareConjugateGradient.h (100%) rename {xs/src => src}/eigen/Eigen/src/IterativeLinearSolvers/SolveWithGuess.h (100%) rename {xs/src => src}/eigen/Eigen/src/Jacobi/Jacobi.h (100%) rename {xs/src => src}/eigen/Eigen/src/LU/Determinant.h (100%) rename {xs/src => src}/eigen/Eigen/src/LU/FullPivLU.h (100%) rename {xs/src => src}/eigen/Eigen/src/LU/InverseImpl.h (100%) rename {xs/src => src}/eigen/Eigen/src/LU/PartialPivLU.h (100%) rename {xs/src => src}/eigen/Eigen/src/LU/PartialPivLU_LAPACKE.h (100%) rename {xs/src => src}/eigen/Eigen/src/LU/arch/Inverse_SSE.h (100%) rename {xs/src => src}/eigen/Eigen/src/MetisSupport/MetisSupport.h (100%) rename {xs/src => src}/eigen/Eigen/src/OrderingMethods/Amd.h (100%) rename {xs/src => src}/eigen/Eigen/src/OrderingMethods/Eigen_Colamd.h (100%) rename {xs/src => src}/eigen/Eigen/src/OrderingMethods/Ordering.h (100%) rename {xs/src => src}/eigen/Eigen/src/PaStiXSupport/PaStiXSupport.h (100%) rename {xs/src => src}/eigen/Eigen/src/PardisoSupport/PardisoSupport.h (100%) rename {xs/src => src}/eigen/Eigen/src/QR/ColPivHouseholderQR.h (100%) rename {xs/src => src}/eigen/Eigen/src/QR/ColPivHouseholderQR_LAPACKE.h (100%) rename {xs/src => src}/eigen/Eigen/src/QR/CompleteOrthogonalDecomposition.h (100%) rename {xs/src => src}/eigen/Eigen/src/QR/FullPivHouseholderQR.h (100%) rename {xs/src => src}/eigen/Eigen/src/QR/HouseholderQR.h (100%) rename {xs/src => src}/eigen/Eigen/src/QR/HouseholderQR_LAPACKE.h (100%) rename {xs/src => src}/eigen/Eigen/src/SPQRSupport/SuiteSparseQRSupport.h (100%) rename {xs/src => src}/eigen/Eigen/src/SVD/BDCSVD.h (100%) rename {xs/src => src}/eigen/Eigen/src/SVD/JacobiSVD.h (100%) rename {xs/src => src}/eigen/Eigen/src/SVD/JacobiSVD_LAPACKE.h (100%) rename {xs/src => src}/eigen/Eigen/src/SVD/SVDBase.h (100%) rename {xs/src => src}/eigen/Eigen/src/SVD/UpperBidiagonalization.h (100%) rename {xs/src => src}/eigen/Eigen/src/SparseCholesky/SimplicialCholesky.h (100%) rename {xs/src => src}/eigen/Eigen/src/SparseCholesky/SimplicialCholesky_impl.h (100%) rename {xs/src => src}/eigen/Eigen/src/SparseCore/AmbiVector.h (100%) rename {xs/src => src}/eigen/Eigen/src/SparseCore/CompressedStorage.h (100%) rename {xs/src => src}/eigen/Eigen/src/SparseCore/ConservativeSparseSparseProduct.h (100%) rename {xs/src => src}/eigen/Eigen/src/SparseCore/MappedSparseMatrix.h (100%) rename {xs/src => src}/eigen/Eigen/src/SparseCore/SparseAssign.h (100%) rename {xs/src => src}/eigen/Eigen/src/SparseCore/SparseBlock.h (100%) rename {xs/src => src}/eigen/Eigen/src/SparseCore/SparseColEtree.h (100%) rename {xs/src => src}/eigen/Eigen/src/SparseCore/SparseCompressedBase.h (100%) rename {xs/src => src}/eigen/Eigen/src/SparseCore/SparseCwiseBinaryOp.h (100%) rename {xs/src => src}/eigen/Eigen/src/SparseCore/SparseCwiseUnaryOp.h (100%) rename {xs/src => src}/eigen/Eigen/src/SparseCore/SparseDenseProduct.h (100%) rename {xs/src => src}/eigen/Eigen/src/SparseCore/SparseDiagonalProduct.h (100%) rename {xs/src => src}/eigen/Eigen/src/SparseCore/SparseDot.h (100%) rename {xs/src => src}/eigen/Eigen/src/SparseCore/SparseFuzzy.h (100%) rename {xs/src => src}/eigen/Eigen/src/SparseCore/SparseMap.h (100%) rename {xs/src => src}/eigen/Eigen/src/SparseCore/SparseMatrix.h (100%) rename {xs/src => src}/eigen/Eigen/src/SparseCore/SparseMatrixBase.h (100%) rename {xs/src => src}/eigen/Eigen/src/SparseCore/SparsePermutation.h (100%) rename {xs/src => src}/eigen/Eigen/src/SparseCore/SparseProduct.h (100%) rename {xs/src => src}/eigen/Eigen/src/SparseCore/SparseRedux.h (100%) rename {xs/src => src}/eigen/Eigen/src/SparseCore/SparseRef.h (100%) rename {xs/src => src}/eigen/Eigen/src/SparseCore/SparseSelfAdjointView.h (100%) rename {xs/src => src}/eigen/Eigen/src/SparseCore/SparseSolverBase.h (100%) rename {xs/src => src}/eigen/Eigen/src/SparseCore/SparseSparseProductWithPruning.h (100%) rename {xs/src => src}/eigen/Eigen/src/SparseCore/SparseTranspose.h (100%) rename {xs/src => src}/eigen/Eigen/src/SparseCore/SparseTriangularView.h (100%) rename {xs/src => src}/eigen/Eigen/src/SparseCore/SparseUtil.h (100%) rename {xs/src => src}/eigen/Eigen/src/SparseCore/SparseVector.h (100%) rename {xs/src => src}/eigen/Eigen/src/SparseCore/SparseView.h (100%) rename {xs/src => src}/eigen/Eigen/src/SparseCore/TriangularSolver.h (100%) rename {xs/src => src}/eigen/Eigen/src/SparseLU/SparseLU.h (100%) rename {xs/src => src}/eigen/Eigen/src/SparseLU/SparseLUImpl.h (100%) rename {xs/src => src}/eigen/Eigen/src/SparseLU/SparseLU_Memory.h (100%) rename {xs/src => src}/eigen/Eigen/src/SparseLU/SparseLU_Structs.h (100%) rename {xs/src => src}/eigen/Eigen/src/SparseLU/SparseLU_SupernodalMatrix.h (100%) rename {xs/src => src}/eigen/Eigen/src/SparseLU/SparseLU_Utils.h (100%) rename {xs/src => src}/eigen/Eigen/src/SparseLU/SparseLU_column_bmod.h (100%) rename {xs/src => src}/eigen/Eigen/src/SparseLU/SparseLU_column_dfs.h (100%) rename {xs/src => src}/eigen/Eigen/src/SparseLU/SparseLU_copy_to_ucol.h (100%) rename {xs/src => src}/eigen/Eigen/src/SparseLU/SparseLU_gemm_kernel.h (100%) rename {xs/src => src}/eigen/Eigen/src/SparseLU/SparseLU_heap_relax_snode.h (100%) rename {xs/src => src}/eigen/Eigen/src/SparseLU/SparseLU_kernel_bmod.h (100%) rename {xs/src => src}/eigen/Eigen/src/SparseLU/SparseLU_panel_bmod.h (100%) rename {xs/src => src}/eigen/Eigen/src/SparseLU/SparseLU_panel_dfs.h (100%) rename {xs/src => src}/eigen/Eigen/src/SparseLU/SparseLU_pivotL.h (100%) rename {xs/src => src}/eigen/Eigen/src/SparseLU/SparseLU_pruneL.h (100%) rename {xs/src => src}/eigen/Eigen/src/SparseLU/SparseLU_relax_snode.h (100%) rename {xs/src => src}/eigen/Eigen/src/SparseQR/SparseQR.h (100%) rename {xs/src => src}/eigen/Eigen/src/StlSupport/StdDeque.h (100%) rename {xs/src => src}/eigen/Eigen/src/StlSupport/StdList.h (100%) rename {xs/src => src}/eigen/Eigen/src/StlSupport/StdVector.h (100%) rename {xs/src => src}/eigen/Eigen/src/StlSupport/details.h (100%) rename {xs/src => src}/eigen/Eigen/src/SuperLUSupport/SuperLUSupport.h (100%) rename {xs/src => src}/eigen/Eigen/src/UmfPackSupport/UmfPackSupport.h (100%) rename {xs/src => src}/eigen/Eigen/src/misc/Image.h (100%) rename {xs/src => src}/eigen/Eigen/src/misc/Kernel.h (100%) rename {xs/src => src}/eigen/Eigen/src/misc/RealSvd2x2.h (100%) rename {xs/src => src}/eigen/Eigen/src/misc/blas.h (100%) rename {xs/src => src}/eigen/Eigen/src/misc/lapack.h (100%) rename {xs/src => src}/eigen/Eigen/src/misc/lapacke.h (100%) rename {xs/src => src}/eigen/Eigen/src/misc/lapacke_mangling.h (100%) rename {xs/src => src}/eigen/Eigen/src/plugins/ArrayCwiseBinaryOps.h (100%) rename {xs/src => src}/eigen/Eigen/src/plugins/ArrayCwiseUnaryOps.h (100%) rename {xs/src => src}/eigen/Eigen/src/plugins/BlockMethods.h (100%) rename {xs/src => src}/eigen/Eigen/src/plugins/CommonCwiseBinaryOps.h (100%) rename {xs/src => src}/eigen/Eigen/src/plugins/CommonCwiseUnaryOps.h (100%) rename {xs/src => src}/eigen/Eigen/src/plugins/MatrixCwiseBinaryOps.h (100%) rename {xs/src => src}/eigen/Eigen/src/plugins/MatrixCwiseUnaryOps.h (100%) rename {xs/src => src}/eigen/README.md (100%) rename {xs/src => src}/expat/COPYING (100%) rename {xs/src => src}/expat/README (100%) rename {xs/src => src}/expat/ascii.h (100%) rename {xs/src => src}/expat/asciitab.h (100%) rename {xs/src => src}/expat/expat.h (100%) rename {xs/src => src}/expat/expat_config.h (100%) rename {xs/src => src}/expat/expat_external.h (100%) rename {xs/src => src}/expat/iasciitab.h (100%) rename {xs/src => src}/expat/internal.h (100%) rename {xs/src => src}/expat/latin1tab.h (100%) rename {xs/src => src}/expat/nametab.h (100%) rename {xs/src => src}/expat/utf8tab.h (100%) rename {xs/src => src}/expat/xmlparse.c (100%) rename {xs/src => src}/expat/xmlrole.c (100%) rename {xs/src => src}/expat/xmlrole.h (100%) rename {xs/src => src}/expat/xmltok.c (100%) rename {xs/src => src}/expat/xmltok.h (100%) rename {xs/src => src}/expat/xmltok_impl.h (100%) rename {xs/src => src}/expat/xmltok_impl.inc (100%) rename {xs/src => src}/expat/xmltok_ns.inc (100%) rename {xs/src => src}/glew/LICENSE.txt (100%) rename {xs/src => src}/glew/README.md (100%) rename {xs/src => src}/glew/include/GL/glew.h (100%) rename {xs/src => src}/glew/include/GL/glxew.h (100%) rename {xs/src => src}/glew/include/GL/wglew.h (100%) rename {xs/src => src}/glew/src/glew.c (100%) rename {xs/src => src}/libnest2d/CMakeLists.txt (100%) rename {xs/src => src}/libnest2d/LICENSE.txt (100%) rename {xs/src => src}/libnest2d/README.md (100%) rename {xs/src => src}/libnest2d/cmake_modules/DownloadNLopt.cmake (100%) rename {xs/src => src}/libnest2d/cmake_modules/DownloadProject.CMakeLists.cmake.in (100%) rename {xs/src => src}/libnest2d/cmake_modules/DownloadProject.cmake (100%) rename {xs/src => src}/libnest2d/cmake_modules/FindClipper.cmake (100%) rename {xs/src => src}/libnest2d/cmake_modules/FindNLopt.cmake (100%) rename {xs/src => src}/libnest2d/cmake_modules/FindTBB.cmake (100%) rename {xs/src => src}/libnest2d/examples/main.cpp (100%) rename {xs/src => src}/libnest2d/libnest2d.h (100%) rename {xs/src => src}/libnest2d/libnest2d/boost_alg.hpp (100%) rename {xs/src => src}/libnest2d/libnest2d/clipper_backend/CMakeLists.txt (100%) rename {xs/src => src}/libnest2d/libnest2d/clipper_backend/clipper_backend.hpp (100%) rename {xs/src => src}/libnest2d/libnest2d/common.hpp (100%) rename {xs/src => src}/libnest2d/libnest2d/geometry_traits.hpp (100%) rename {xs/src => src}/libnest2d/libnest2d/geometry_traits_nfp.hpp (100%) rename {xs/src => src}/libnest2d/libnest2d/libnest2d.hpp (100%) rename {xs/src => src}/libnest2d/libnest2d/metaloop.hpp (100%) rename {xs/src => src}/libnest2d/libnest2d/optimizer.hpp (100%) rename {xs/src => src}/libnest2d/libnest2d/optimizers/genetic.hpp (100%) rename {xs/src => src}/libnest2d/libnest2d/optimizers/nlopt_boilerplate.hpp (100%) rename {xs/src => src}/libnest2d/libnest2d/optimizers/simplex.hpp (100%) rename {xs/src => src}/libnest2d/libnest2d/optimizers/subplex.hpp (100%) rename {xs/src => src}/libnest2d/libnest2d/placers/bottomleftplacer.hpp (100%) rename {xs/src => src}/libnest2d/libnest2d/placers/nfpplacer.hpp (100%) rename {xs/src => src}/libnest2d/libnest2d/placers/placer_boilerplate.hpp (100%) rename {xs/src => src}/libnest2d/libnest2d/rotfinder.hpp (100%) rename {xs/src => src}/libnest2d/libnest2d/selections/djd_heuristic.hpp (100%) rename {xs/src => src}/libnest2d/libnest2d/selections/filler.hpp (100%) rename {xs/src => src}/libnest2d/libnest2d/selections/firstfit.hpp (100%) rename {xs/src => src}/libnest2d/libnest2d/selections/selection_boilerplate.hpp (100%) rename {xs/src => src}/libnest2d/tests/CMakeLists.txt (100%) rename {xs/src => src}/libnest2d/tests/printer_parts.cpp (100%) rename {xs/src => src}/libnest2d/tests/printer_parts.h (100%) rename {xs/src => src}/libnest2d/tests/test.cpp (100%) rename {xs/src => src/libnest2d/tools}/benchmark.h (100%) rename {xs/src => src}/libnest2d/tools/libnfpglue.cpp (100%) rename {xs/src => src}/libnest2d/tools/libnfpglue.hpp (100%) rename {xs/src => src}/libnest2d/tools/libnfporb/LICENSE (100%) rename {xs/src => src}/libnest2d/tools/libnfporb/ORIGIN (100%) rename {xs/src => src}/libnest2d/tools/libnfporb/README.md (100%) rename {xs/src => src}/libnest2d/tools/libnfporb/libnfporb.hpp (100%) rename {xs/src => src}/libnest2d/tools/nfp_svgnest.hpp (100%) rename {xs/src => src}/libnest2d/tools/nfp_svgnest_glue.hpp (100%) rename {xs/src => src}/libnest2d/tools/svgtools.hpp (100%) rename {xs/src => src}/libslic3r/BoundingBox.cpp (100%) rename {xs/src => src}/libslic3r/BoundingBox.hpp (100%) rename {xs/src => src}/libslic3r/BridgeDetector.cpp (100%) rename {xs/src => src}/libslic3r/BridgeDetector.hpp (100%) create mode 100644 src/libslic3r/CMakeLists.txt rename {xs/src => src}/libslic3r/ClipperUtils.cpp (100%) rename {xs/src => src}/libslic3r/ClipperUtils.hpp (100%) rename {xs/src => src}/libslic3r/Config.cpp (100%) rename {xs/src => src}/libslic3r/Config.hpp (100%) rename {xs/src => src}/libslic3r/EdgeGrid.cpp (100%) rename {xs/src => src}/libslic3r/EdgeGrid.hpp (100%) rename {xs/src => src}/libslic3r/ExPolygon.cpp (100%) rename {xs/src => src}/libslic3r/ExPolygon.hpp (100%) rename {xs/src => src}/libslic3r/ExPolygonCollection.cpp (100%) rename {xs/src => src}/libslic3r/ExPolygonCollection.hpp (100%) rename {xs/src => src}/libslic3r/Extruder.cpp (100%) rename {xs/src => src}/libslic3r/Extruder.hpp (100%) rename {xs/src => src}/libslic3r/ExtrusionEntity.cpp (100%) rename {xs/src => src}/libslic3r/ExtrusionEntity.hpp (100%) rename {xs/src => src}/libslic3r/ExtrusionEntityCollection.cpp (100%) rename {xs/src => src}/libslic3r/ExtrusionEntityCollection.hpp (100%) rename {xs/src => src}/libslic3r/ExtrusionSimulator.cpp (100%) rename {xs/src => src}/libslic3r/ExtrusionSimulator.hpp (100%) rename {xs/src => src}/libslic3r/FileParserError.hpp (100%) rename {xs/src => src}/libslic3r/Fill/Fill.cpp (100%) rename {xs/src => src}/libslic3r/Fill/Fill.hpp (100%) rename {xs/src => src}/libslic3r/Fill/Fill3DHoneycomb.cpp (100%) rename {xs/src => src}/libslic3r/Fill/Fill3DHoneycomb.hpp (100%) rename {xs/src => src}/libslic3r/Fill/FillBase.cpp (100%) rename {xs/src => src}/libslic3r/Fill/FillBase.hpp (100%) rename {xs/src => src}/libslic3r/Fill/FillConcentric.cpp (100%) rename {xs/src => src}/libslic3r/Fill/FillConcentric.hpp (100%) rename {xs/src => src}/libslic3r/Fill/FillGyroid.cpp (100%) rename {xs/src => src}/libslic3r/Fill/FillGyroid.hpp (100%) rename {xs/src => src}/libslic3r/Fill/FillHoneycomb.cpp (100%) rename {xs/src => src}/libslic3r/Fill/FillHoneycomb.hpp (100%) rename {xs/src => src}/libslic3r/Fill/FillPlanePath.cpp (100%) rename {xs/src => src}/libslic3r/Fill/FillPlanePath.hpp (100%) rename {xs/src => src}/libslic3r/Fill/FillRectilinear.cpp (100%) rename {xs/src => src}/libslic3r/Fill/FillRectilinear.hpp (100%) rename {xs/src => src}/libslic3r/Fill/FillRectilinear2.cpp (100%) rename {xs/src => src}/libslic3r/Fill/FillRectilinear2.hpp (100%) rename {xs/src => src}/libslic3r/Fill/FillRectilinear3.cpp (100%) rename {xs/src => src}/libslic3r/Fill/FillRectilinear3.hpp (100%) rename {xs/src => src}/libslic3r/Flow.cpp (100%) rename {xs/src => src}/libslic3r/Flow.hpp (100%) rename {xs/src => src}/libslic3r/Format/3mf.cpp (100%) rename {xs/src => src}/libslic3r/Format/3mf.hpp (100%) rename {xs/src => src}/libslic3r/Format/AMF.cpp (100%) rename {xs/src => src}/libslic3r/Format/AMF.hpp (100%) rename {xs/src => src}/libslic3r/Format/OBJ.cpp (100%) rename {xs/src => src}/libslic3r/Format/OBJ.hpp (100%) rename {xs/src => src}/libslic3r/Format/PRUS.cpp (100%) rename {xs/src => src}/libslic3r/Format/PRUS.hpp (100%) rename {xs/src => src}/libslic3r/Format/STL.cpp (100%) rename {xs/src => src}/libslic3r/Format/STL.hpp (100%) rename {xs/src => src}/libslic3r/Format/objparser.cpp (100%) rename {xs/src => src}/libslic3r/Format/objparser.hpp (100%) rename {xs/src => src}/libslic3r/GCode.cpp (100%) rename {xs/src => src}/libslic3r/GCode.hpp (100%) rename {xs/src => src}/libslic3r/GCode/Analyzer.cpp (100%) rename {xs/src => src}/libslic3r/GCode/Analyzer.hpp (100%) rename {xs/src => src}/libslic3r/GCode/CoolingBuffer.cpp (100%) rename {xs/src => src}/libslic3r/GCode/CoolingBuffer.hpp (100%) rename {xs/src => src}/libslic3r/GCode/PostProcessor.cpp (100%) rename {xs/src => src}/libslic3r/GCode/PostProcessor.hpp (100%) rename {xs/src => src}/libslic3r/GCode/PressureEqualizer.cpp (100%) rename {xs/src => src}/libslic3r/GCode/PressureEqualizer.hpp (100%) rename {xs/src => src}/libslic3r/GCode/PreviewData.cpp (100%) rename {xs/src => src}/libslic3r/GCode/PreviewData.hpp (100%) rename {xs/src => src}/libslic3r/GCode/PrintExtents.cpp (100%) rename {xs/src => src}/libslic3r/GCode/PrintExtents.hpp (100%) rename {xs/src => src}/libslic3r/GCode/SpiralVase.cpp (100%) rename {xs/src => src}/libslic3r/GCode/SpiralVase.hpp (100%) rename {xs/src => src}/libslic3r/GCode/ToolOrdering.cpp (100%) rename {xs/src => src}/libslic3r/GCode/ToolOrdering.hpp (100%) rename {xs/src => src}/libslic3r/GCode/WipeTower.hpp (100%) rename {xs/src => src}/libslic3r/GCode/WipeTowerPrusaMM.cpp (100%) rename {xs/src => src}/libslic3r/GCode/WipeTowerPrusaMM.hpp (100%) rename {xs/src => src}/libslic3r/GCodeReader.cpp (100%) rename {xs/src => src}/libslic3r/GCodeReader.hpp (100%) rename {xs/src => src}/libslic3r/GCodeSender.cpp (100%) rename {xs/src => src}/libslic3r/GCodeSender.hpp (100%) rename {xs/src => src}/libslic3r/GCodeTimeEstimator.cpp (100%) rename {xs/src => src}/libslic3r/GCodeTimeEstimator.hpp (100%) rename {xs/src => src}/libslic3r/GCodeWriter.cpp (100%) rename {xs/src => src}/libslic3r/GCodeWriter.hpp (100%) rename {xs/src => src}/libslic3r/Geometry.cpp (100%) rename {xs/src => src}/libslic3r/Geometry.hpp (100%) rename {xs/src => src}/libslic3r/I18N.hpp (100%) rename {xs/src => src}/libslic3r/Int128.hpp (100%) rename {xs/src => src}/libslic3r/Layer.cpp (100%) rename {xs/src => src}/libslic3r/Layer.hpp (100%) rename {xs/src => src}/libslic3r/LayerRegion.cpp (100%) rename {xs/src => src}/libslic3r/Line.cpp (100%) rename {xs/src => src}/libslic3r/Line.hpp (100%) rename {xs/src => src}/libslic3r/Model.cpp (100%) rename {xs/src => src}/libslic3r/Model.hpp (100%) rename {xs/src => src}/libslic3r/ModelArrange.hpp (100%) rename {xs/src => src}/libslic3r/MotionPlanner.cpp (100%) rename {xs/src => src}/libslic3r/MotionPlanner.hpp (100%) rename {xs/src => src}/libslic3r/MultiPoint.cpp (100%) rename {xs/src => src}/libslic3r/MultiPoint.hpp (100%) rename {xs/src => src}/libslic3r/MutablePriorityQueue.hpp (100%) rename {xs/src => src}/libslic3r/PerimeterGenerator.cpp (100%) rename {xs/src => src}/libslic3r/PerimeterGenerator.hpp (100%) rename {xs/src => src}/libslic3r/PlaceholderParser.cpp (100%) rename {xs/src => src}/libslic3r/PlaceholderParser.hpp (100%) rename {xs/src => src}/libslic3r/Point.cpp (100%) rename {xs/src => src}/libslic3r/Point.hpp (100%) rename {xs/src => src}/libslic3r/Polygon.cpp (100%) rename {xs/src => src}/libslic3r/Polygon.hpp (100%) rename {xs/src => src}/libslic3r/Polyline.cpp (100%) rename {xs/src => src}/libslic3r/Polyline.hpp (100%) rename {xs/src => src}/libslic3r/PolylineCollection.cpp (100%) rename {xs/src => src}/libslic3r/PolylineCollection.hpp (100%) rename {xs/src => src}/libslic3r/Print.cpp (98%) rename {xs/src => src}/libslic3r/Print.hpp (100%) rename {xs/src => src}/libslic3r/PrintConfig.cpp (100%) rename {xs/src => src}/libslic3r/PrintConfig.hpp (100%) rename {xs/src => src}/libslic3r/PrintExport.hpp (100%) rename {xs/src => src}/libslic3r/PrintObject.cpp (100%) rename {xs/src => src}/libslic3r/PrintRegion.cpp (100%) rename {xs/src => src}/libslic3r/Rasterizer/Rasterizer.cpp (100%) rename {xs/src => src}/libslic3r/Rasterizer/Rasterizer.hpp (100%) rename {xs/src => src}/libslic3r/SLABasePool.cpp (100%) rename {xs/src => src}/libslic3r/SLABasePool.hpp (100%) rename {xs/src => src}/libslic3r/SVG.cpp (100%) rename {xs/src => src}/libslic3r/SVG.hpp (100%) rename {xs/src => src}/libslic3r/Slicing.cpp (100%) rename {xs/src => src}/libslic3r/Slicing.hpp (100%) rename {xs/src => src}/libslic3r/SlicingAdaptive.cpp (100%) rename {xs/src => src}/libslic3r/SlicingAdaptive.hpp (100%) rename {xs/src => src}/libslic3r/SupportMaterial.cpp (100%) rename {xs/src => src}/libslic3r/SupportMaterial.hpp (100%) rename {xs/src => src}/libslic3r/Surface.cpp (100%) rename {xs/src => src}/libslic3r/Surface.hpp (100%) rename {xs/src => src}/libslic3r/SurfaceCollection.cpp (100%) rename {xs/src => src}/libslic3r/SurfaceCollection.hpp (100%) rename {xs/src => src}/libslic3r/Technologies.hpp (100%) rename {xs/src => src}/libslic3r/TriangleMesh.cpp (100%) rename {xs/src => src}/libslic3r/TriangleMesh.hpp (100%) rename {xs/src => src}/libslic3r/Utils.hpp (100%) rename {xs/src => src}/libslic3r/libslic3r.h (100%) rename {xs/src => src}/libslic3r/utils.cpp (100%) create mode 100644 src/miniz/CMakeLists.txt rename {xs/src => src}/miniz/miniz.cpp (100%) rename {xs/src => src}/miniz/miniz.h (100%) rename {xs/src => src}/miniz/miniz_common.h (100%) rename {xs/src => src}/miniz/miniz_tdef.cpp (100%) rename {xs/src => src}/miniz/miniz_tdef.h (100%) rename {xs/src => src}/miniz/miniz_tinfl.cpp (100%) rename {xs/src => src}/miniz/miniz_tinfl.h (100%) rename {xs/src => src}/miniz/miniz_zip.cpp (100%) rename {xs/src => src}/miniz/miniz_zip.h (100%) rename {xs/src => src}/png/AUTHORS (100%) rename {xs/src => src}/png/COPYING (100%) rename {xs/src => src}/png/NEWS (100%) rename {xs/src => src}/png/color.hpp (100%) rename {xs/src => src}/png/end_info.hpp (100%) rename {xs/src => src}/png/error.hpp (100%) rename {xs/src => src}/png/image_info.hpp (100%) rename {xs/src => src}/png/info.hpp (100%) rename {xs/src => src}/png/info_base.hpp (100%) rename {xs/src => src}/png/io_base.hpp (100%) rename {xs/src => src}/png/libpng/ANNOUNCE (100%) rename {xs/src => src}/png/libpng/CMakeLists.txt (98%) rename {xs/src => src}/png/libpng/LICENSE (100%) rename {xs/src => src}/png/libpng/arm/arm_init.c (100%) rename {xs/src => src}/png/libpng/arm/filter_neon.S (100%) rename {xs/src => src}/png/libpng/arm/filter_neon_intrinsics.c (100%) rename {xs/src => src}/png/libpng/intel/filter_sse2_intrinsics.c (100%) rename {xs/src => src}/png/libpng/intel/intel_init.c (100%) rename {xs/src => src}/png/libpng/libpng-config.in (100%) rename {xs/src => src}/png/libpng/libpng.pc.in (100%) rename {xs/src => src}/png/libpng/mips/filter_msa_intrinsics.c (100%) rename {xs/src => src}/png/libpng/mips/mips_init.c (100%) rename {xs/src => src}/png/libpng/png.c (100%) rename {xs/src => src}/png/libpng/png.h (100%) rename {xs/src => src}/png/libpng/pngconf.h (100%) rename {xs/src => src}/png/libpng/pngdebug.h (100%) rename {xs/src => src}/png/libpng/pngerror.c (100%) rename {xs/src => src}/png/libpng/pngget.c (100%) rename {xs/src => src}/png/libpng/pnginfo.h (100%) rename {xs/src => src}/png/libpng/pngmem.c (100%) rename {xs/src => src}/png/libpng/pngpread.c (100%) rename {xs/src => src}/png/libpng/pngpriv.h (100%) rename {xs/src => src}/png/libpng/pngread.c (100%) rename {xs/src => src}/png/libpng/pngrio.c (100%) rename {xs/src => src}/png/libpng/pngrtran.c (100%) rename {xs/src => src}/png/libpng/pngrutil.c (100%) rename {xs/src => src}/png/libpng/pngset.c (100%) rename {xs/src => src}/png/libpng/pngstruct.h (100%) rename {xs/src => src}/png/libpng/pngtest.c (100%) rename {xs/src => src}/png/libpng/pngtrans.c (100%) rename {xs/src => src}/png/libpng/pngusr.dfa (100%) rename {xs/src => src}/png/libpng/pngwio.c (100%) rename {xs/src => src}/png/libpng/pngwrite.c (100%) rename {xs/src => src}/png/libpng/pngwtran.c (100%) rename {xs/src => src}/png/libpng/pngwutil.c (100%) rename {xs/src => src}/png/libpng/powerpc/filter_vsx_intrinsics.c (100%) rename {xs/src => src}/png/libpng/powerpc/powerpc_init.c (100%) rename {xs/src => src}/png/libpng/scripts/checksym.awk (100%) mode change 100755 => 100644 rename {xs/src => src}/png/libpng/scripts/def.c (100%) rename {xs/src => src}/png/libpng/scripts/dfn.awk (100%) mode change 100755 => 100644 rename {xs/src => src}/png/libpng/scripts/genchk.cmake.in (100%) rename {xs/src => src}/png/libpng/scripts/genout.cmake.in (100%) rename {xs/src => src}/png/libpng/scripts/gensrc.cmake.in (100%) rename {xs/src => src}/png/libpng/scripts/intprefix.c (100%) rename {xs/src => src}/png/libpng/scripts/libpng-config-body.in (100%) rename {xs/src => src}/png/libpng/scripts/libpng-config-head.in (100%) rename {xs/src => src}/png/libpng/scripts/libpng.pc.in (100%) rename {xs/src => src}/png/libpng/scripts/options.awk (100%) mode change 100755 => 100644 rename {xs/src => src}/png/libpng/scripts/pnglibconf.dfa (100%) rename {xs/src => src}/png/libpng/scripts/pnglibconf.h.prebuilt (100%) rename {xs/src => src}/png/libpng/scripts/prefix.c (100%) rename {xs/src => src}/png/libpng/scripts/sym.c (100%) rename {xs/src => src}/png/libpng/scripts/symbols.c (100%) rename {xs/src => src}/png/libpng/scripts/symbols.def (100%) rename {xs/src => src}/png/libpng/scripts/test.cmake.in (100%) rename {xs/src => src}/png/libpng/scripts/vers.c (100%) rename {xs/src => src}/png/palette.hpp (100%) rename {xs/src => src}/png/pixel_traits.hpp (100%) rename {xs/src => src}/png/tRNS.hpp (100%) rename {xs/src => src}/png/types.hpp (100%) rename {xs/src => src}/png/writer.hpp (100%) rename {xs/src => src}/png/zlib/CMakeLists.txt (100%) rename {xs/src => src}/png/zlib/ChangeLog (100%) rename {xs/src => src}/png/zlib/FAQ (100%) rename {xs/src => src}/png/zlib/INDEX (100%) rename {xs/src => src}/png/zlib/Makefile (100%) rename {xs/src => src}/png/zlib/Makefile.in (100%) rename {xs/src => src}/png/zlib/README (100%) rename {xs/src => src}/png/zlib/adler32.c (100%) rename {xs/src => src}/png/zlib/amiga/Makefile.pup (100%) rename {xs/src => src}/png/zlib/amiga/Makefile.sas (100%) rename {xs/src => src}/png/zlib/compress.c (100%) rename {xs/src => src}/png/zlib/configure (100%) rename {xs/src => src}/png/zlib/contrib/README.contrib (100%) rename {xs/src => src}/png/zlib/contrib/ada/buffer_demo.adb (100%) rename {xs/src => src}/png/zlib/contrib/ada/mtest.adb (100%) rename {xs/src => src}/png/zlib/contrib/ada/read.adb (100%) rename {xs/src => src}/png/zlib/contrib/ada/readme.txt (100%) rename {xs/src => src}/png/zlib/contrib/ada/test.adb (100%) rename {xs/src => src}/png/zlib/contrib/ada/zlib-streams.adb (100%) rename {xs/src => src}/png/zlib/contrib/ada/zlib-streams.ads (100%) rename {xs/src => src}/png/zlib/contrib/ada/zlib-thin.adb (100%) rename {xs/src => src}/png/zlib/contrib/ada/zlib-thin.ads (100%) rename {xs/src => src}/png/zlib/contrib/ada/zlib.adb (100%) rename {xs/src => src}/png/zlib/contrib/ada/zlib.ads (100%) rename {xs/src => src}/png/zlib/contrib/ada/zlib.gpr (100%) rename {xs/src => src}/png/zlib/contrib/amd64/amd64-match.S (100%) rename {xs/src => src}/png/zlib/contrib/asm686/README.686 (100%) rename {xs/src => src}/png/zlib/contrib/asm686/match.S (100%) rename {xs/src => src}/png/zlib/contrib/blast/Makefile (100%) rename {xs/src => src}/png/zlib/contrib/blast/README (100%) rename {xs/src => src}/png/zlib/contrib/blast/blast.c (100%) rename {xs/src => src}/png/zlib/contrib/blast/blast.h (100%) rename {xs/src => src}/png/zlib/contrib/blast/test.pk (100%) rename {xs/src => src}/png/zlib/contrib/blast/test.txt (100%) rename {xs/src => src}/png/zlib/contrib/delphi/ZLib.pas (100%) rename {xs/src => src}/png/zlib/contrib/delphi/ZLibConst.pas (100%) rename {xs/src => src}/png/zlib/contrib/delphi/readme.txt (100%) rename {xs/src => src}/png/zlib/contrib/delphi/zlibd32.mak (100%) rename {xs/src => src}/png/zlib/contrib/dotzlib/DotZLib.build (100%) rename {xs/src => src}/png/zlib/contrib/dotzlib/DotZLib.chm (100%) rename {xs/src => src}/png/zlib/contrib/dotzlib/DotZLib.sln (100%) rename {xs/src => src}/png/zlib/contrib/dotzlib/DotZLib/AssemblyInfo.cs (100%) rename {xs/src => src}/png/zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs (100%) rename {xs/src => src}/png/zlib/contrib/dotzlib/DotZLib/CircularBuffer.cs (100%) rename {xs/src => src}/png/zlib/contrib/dotzlib/DotZLib/CodecBase.cs (100%) rename {xs/src => src}/png/zlib/contrib/dotzlib/DotZLib/Deflater.cs (100%) rename {xs/src => src}/png/zlib/contrib/dotzlib/DotZLib/DotZLib.cs (100%) rename {xs/src => src}/png/zlib/contrib/dotzlib/DotZLib/DotZLib.csproj (100%) rename {xs/src => src}/png/zlib/contrib/dotzlib/DotZLib/GZipStream.cs (100%) rename {xs/src => src}/png/zlib/contrib/dotzlib/DotZLib/Inflater.cs (100%) rename {xs/src => src}/png/zlib/contrib/dotzlib/DotZLib/UnitTests.cs (100%) rename {xs/src => src}/png/zlib/contrib/dotzlib/LICENSE_1_0.txt (100%) rename {xs/src => src}/png/zlib/contrib/dotzlib/readme.txt (100%) rename {xs/src => src}/png/zlib/contrib/gcc_gvmat64/gvmat64.S (100%) rename {xs/src => src}/png/zlib/contrib/infback9/README (100%) rename {xs/src => src}/png/zlib/contrib/infback9/infback9.c (100%) rename {xs/src => src}/png/zlib/contrib/infback9/infback9.h (100%) rename {xs/src => src}/png/zlib/contrib/infback9/inffix9.h (100%) rename {xs/src => src}/png/zlib/contrib/infback9/inflate9.h (100%) rename {xs/src => src}/png/zlib/contrib/infback9/inftree9.c (100%) rename {xs/src => src}/png/zlib/contrib/infback9/inftree9.h (100%) rename {xs/src => src}/png/zlib/contrib/inflate86/inffas86.c (100%) rename {xs/src => src}/png/zlib/contrib/inflate86/inffast.S (100%) rename {xs/src => src}/png/zlib/contrib/iostream/test.cpp (100%) rename {xs/src => src}/png/zlib/contrib/iostream/zfstream.cpp (100%) rename {xs/src => src}/png/zlib/contrib/iostream/zfstream.h (100%) rename {xs/src => src}/png/zlib/contrib/iostream2/zstream.h (100%) rename {xs/src => src}/png/zlib/contrib/iostream2/zstream_test.cpp (100%) rename {xs/src => src}/png/zlib/contrib/iostream3/README (100%) rename {xs/src => src}/png/zlib/contrib/iostream3/TODO (100%) rename {xs/src => src}/png/zlib/contrib/iostream3/test.cc (100%) rename {xs/src => src}/png/zlib/contrib/iostream3/zfstream.cc (100%) rename {xs/src => src}/png/zlib/contrib/iostream3/zfstream.h (100%) rename {xs/src => src}/png/zlib/contrib/masmx64/bld_ml64.bat (100%) rename {xs/src => src}/png/zlib/contrib/masmx64/gvmat64.asm (100%) rename {xs/src => src}/png/zlib/contrib/masmx64/inffas8664.c (100%) rename {xs/src => src}/png/zlib/contrib/masmx64/inffasx64.asm (100%) rename {xs/src => src}/png/zlib/contrib/masmx64/readme.txt (100%) rename {xs/src => src}/png/zlib/contrib/masmx86/bld_ml32.bat (100%) rename {xs/src => src}/png/zlib/contrib/masmx86/inffas32.asm (100%) rename {xs/src => src}/png/zlib/contrib/masmx86/match686.asm (100%) rename {xs/src => src}/png/zlib/contrib/masmx86/readme.txt (100%) rename {xs/src => src}/png/zlib/contrib/minizip/Makefile (100%) rename {xs/src => src}/png/zlib/contrib/minizip/Makefile.am (100%) rename {xs/src => src}/png/zlib/contrib/minizip/MiniZip64_Changes.txt (100%) rename {xs/src => src}/png/zlib/contrib/minizip/MiniZip64_info.txt (100%) rename {xs/src => src}/png/zlib/contrib/minizip/configure.ac (100%) rename {xs/src => src}/png/zlib/contrib/minizip/crypt.h (100%) rename {xs/src => src}/png/zlib/contrib/minizip/ioapi.c (100%) rename {xs/src => src}/png/zlib/contrib/minizip/ioapi.h (100%) rename {xs/src => src}/png/zlib/contrib/minizip/iowin32.c (100%) rename {xs/src => src}/png/zlib/contrib/minizip/iowin32.h (100%) rename {xs/src => src}/png/zlib/contrib/minizip/make_vms.com (100%) rename {xs/src => src}/png/zlib/contrib/minizip/miniunz.c (100%) rename {xs/src => src}/png/zlib/contrib/minizip/miniunzip.1 (100%) rename {xs/src => src}/png/zlib/contrib/minizip/minizip.1 (100%) rename {xs/src => src}/png/zlib/contrib/minizip/minizip.c (100%) rename {xs/src => src}/png/zlib/contrib/minizip/minizip.pc.in (100%) rename {xs/src => src}/png/zlib/contrib/minizip/mztools.c (100%) rename {xs/src => src}/png/zlib/contrib/minizip/mztools.h (100%) rename {xs/src => src}/png/zlib/contrib/minizip/unzip.c (100%) rename {xs/src => src}/png/zlib/contrib/minizip/unzip.h (100%) rename {xs/src => src}/png/zlib/contrib/minizip/zip.c (100%) rename {xs/src => src}/png/zlib/contrib/minizip/zip.h (100%) rename {xs/src => src}/png/zlib/contrib/pascal/example.pas (100%) rename {xs/src => src}/png/zlib/contrib/pascal/readme.txt (100%) rename {xs/src => src}/png/zlib/contrib/pascal/zlibd32.mak (100%) rename {xs/src => src}/png/zlib/contrib/pascal/zlibpas.pas (100%) rename {xs/src => src}/png/zlib/contrib/puff/Makefile (100%) rename {xs/src => src}/png/zlib/contrib/puff/README (100%) rename {xs/src => src}/png/zlib/contrib/puff/puff.c (100%) rename {xs/src => src}/png/zlib/contrib/puff/puff.h (100%) rename {xs/src => src}/png/zlib/contrib/puff/pufftest.c (100%) rename {xs/src => src}/png/zlib/contrib/puff/zeros.raw (100%) rename {xs/src => src}/png/zlib/contrib/testzlib/testzlib.c (100%) rename {xs/src => src}/png/zlib/contrib/testzlib/testzlib.txt (100%) rename {xs/src => src}/png/zlib/contrib/untgz/Makefile (100%) rename {xs/src => src}/png/zlib/contrib/untgz/Makefile.msc (100%) rename {xs/src => src}/png/zlib/contrib/untgz/untgz.c (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/readme.txt (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc10/miniunz.vcxproj (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc10/miniunz.vcxproj.filters (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc10/minizip.vcxproj (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc10/minizip.vcxproj.filters (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc10/testzlib.vcxproj (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc10/testzlib.vcxproj.filters (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc10/testzlibdll.vcxproj (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc10/testzlibdll.vcxproj.filters (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc10/zlib.rc (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc10/zlibstat.vcxproj (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc10/zlibstat.vcxproj.filters (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc10/zlibvc.def (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc10/zlibvc.sln (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc10/zlibvc.vcxproj (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc10/zlibvc.vcxproj.filters (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc11/miniunz.vcxproj (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc11/minizip.vcxproj (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc11/testzlib.vcxproj (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc11/testzlibdll.vcxproj (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc11/zlib.rc (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc11/zlibstat.vcxproj (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc11/zlibvc.def (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc11/zlibvc.sln (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc11/zlibvc.vcxproj (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc12/miniunz.vcxproj (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc12/minizip.vcxproj (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc12/testzlib.vcxproj (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc12/testzlibdll.vcxproj (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc12/zlib.rc (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc12/zlibstat.vcxproj (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc12/zlibvc.def (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc12/zlibvc.sln (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc12/zlibvc.vcxproj (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc14/miniunz.vcxproj (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc14/minizip.vcxproj (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc14/testzlib.vcxproj (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc14/testzlibdll.vcxproj (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc14/zlib.rc (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc14/zlibstat.vcxproj (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc14/zlibvc.def (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc14/zlibvc.sln (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc14/zlibvc.vcxproj (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc9/miniunz.vcproj (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc9/minizip.vcproj (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc9/testzlib.vcproj (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc9/testzlibdll.vcproj (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc9/zlib.rc (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc9/zlibstat.vcproj (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc9/zlibvc.def (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc9/zlibvc.sln (100%) rename {xs/src => src}/png/zlib/contrib/vstudio/vc9/zlibvc.vcproj (100%) rename {xs/src => src}/png/zlib/crc32.c (100%) rename {xs/src => src}/png/zlib/crc32.h (100%) rename {xs/src => src}/png/zlib/deflate.c (100%) rename {xs/src => src}/png/zlib/deflate.h (100%) rename {xs/src => src}/png/zlib/gzclose.c (100%) rename {xs/src => src}/png/zlib/gzguts.h (100%) rename {xs/src => src}/png/zlib/gzlib.c (100%) rename {xs/src => src}/png/zlib/gzread.c (100%) rename {xs/src => src}/png/zlib/gzwrite.c (100%) rename {xs/src => src}/png/zlib/infback.c (100%) rename {xs/src => src}/png/zlib/inffast.c (100%) rename {xs/src => src}/png/zlib/inffast.h (100%) rename {xs/src => src}/png/zlib/inffixed.h (100%) rename {xs/src => src}/png/zlib/inflate.c (100%) rename {xs/src => src}/png/zlib/inflate.h (100%) rename {xs/src => src}/png/zlib/inftrees.c (100%) rename {xs/src => src}/png/zlib/inftrees.h (100%) rename {xs/src => src}/png/zlib/make_vms.com (100%) rename {xs/src => src}/png/zlib/msdos/Makefile.bor (100%) rename {xs/src => src}/png/zlib/msdos/Makefile.dj2 (100%) rename {xs/src => src}/png/zlib/msdos/Makefile.emx (100%) rename {xs/src => src}/png/zlib/msdos/Makefile.msc (100%) rename {xs/src => src}/png/zlib/msdos/Makefile.tc (100%) rename {xs/src => src}/png/zlib/nintendods/Makefile (100%) rename {xs/src => src}/png/zlib/nintendods/README (100%) rename {xs/src => src}/png/zlib/old/Makefile.emx (100%) rename {xs/src => src}/png/zlib/old/Makefile.riscos (100%) rename {xs/src => src}/png/zlib/old/README (100%) rename {xs/src => src}/png/zlib/old/descrip.mms (100%) rename {xs/src => src}/png/zlib/old/os2/Makefile.os2 (100%) rename {xs/src => src}/png/zlib/old/os2/zlib.def (100%) rename {xs/src => src}/png/zlib/old/visual-basic.txt (100%) rename {xs/src => src}/png/zlib/os400/README400 (100%) rename {xs/src => src}/png/zlib/os400/bndsrc (100%) rename {xs/src => src}/png/zlib/os400/make.sh (100%) rename {xs/src => src}/png/zlib/os400/zlib.inc (100%) rename {xs/src => src}/png/zlib/qnx/package.qpg (100%) rename {xs/src => src}/png/zlib/treebuild.xml (100%) rename {xs/src => src}/png/zlib/trees.c (100%) rename {xs/src => src}/png/zlib/trees.h (100%) rename {xs/src => src}/png/zlib/uncompr.c (100%) rename {xs/src => src}/png/zlib/watcom/watcom_f.mak (100%) rename {xs/src => src}/png/zlib/watcom/watcom_l.mak (100%) rename {xs/src => src}/png/zlib/win32/DLL_FAQ.txt (100%) rename {xs/src => src}/png/zlib/win32/Makefile.bor (100%) rename {xs/src => src}/png/zlib/win32/Makefile.gcc (100%) rename {xs/src => src}/png/zlib/win32/Makefile.msc (100%) rename {xs/src => src}/png/zlib/win32/README-WIN32.txt (100%) rename {xs/src => src}/png/zlib/win32/VisualC.txt (100%) rename {xs/src => src}/png/zlib/win32/zlib.def (100%) rename {xs/src => src}/png/zlib/win32/zlib1.rc (100%) rename {xs/src => src}/png/zlib/zconf.h.cmakein (100%) rename {xs/src => src}/png/zlib/zconf.h.in (100%) rename {xs/src => src}/png/zlib/zconf.h.included (100%) rename {xs/src => src}/png/zlib/zlib.3 (100%) rename {xs/src => src}/png/zlib/zlib.3.pdf (100%) rename {xs/src => src}/png/zlib/zlib.h (100%) rename {xs/src => src}/png/zlib/zlib.map (100%) rename {xs/src => src}/png/zlib/zlib.pc.cmakein (100%) rename {xs/src => src}/png/zlib/zlib.pc.in (100%) rename {xs/src => src}/png/zlib/zlib2ansi (100%) rename {xs/src => src}/png/zlib/zutil.c (100%) rename {xs/src => src}/png/zlib/zutil.h (100%) create mode 100644 src/poly2tri/CMakeLists.txt rename {xs/src => src}/poly2tri/common/shapes.cc (100%) rename {xs/src => src}/poly2tri/common/shapes.h (100%) rename {xs/src => src}/poly2tri/common/utils.h (100%) rename {xs/src => src}/poly2tri/poly2tri.h (100%) rename {xs/src => src}/poly2tri/sweep/advancing_front.cc (100%) rename {xs/src => src}/poly2tri/sweep/advancing_front.h (100%) rename {xs/src => src}/poly2tri/sweep/cdt.cc (100%) rename {xs/src => src}/poly2tri/sweep/cdt.h (100%) rename {xs/src => src}/poly2tri/sweep/sweep.cc (100%) rename {xs/src => src}/poly2tri/sweep/sweep.h (100%) rename {xs/src => src}/poly2tri/sweep/sweep_context.cc (100%) rename {xs/src => src}/poly2tri/sweep/sweep_context.h (100%) create mode 100644 src/polypartition/CMakeLists.txt rename {xs/src => src/polypartition}/polypartition.cpp (96%) rename {xs/src => src/polypartition}/polypartition.h (97%) rename {xs/src => src}/qhull/Announce.txt (100%) rename {xs/src => src}/qhull/CMakeLists.txt (100%) rename {xs/src => src}/qhull/COPYING.txt (100%) rename {xs/src => src}/qhull/README.txt (100%) rename {xs/src => src}/qhull/REGISTER.txt (100%) rename {xs/src => src}/qhull/html/index.htm (100%) rename {xs/src => src}/qhull/html/normal_voronoi_knauss_oesterle.jpg (100%) rename {xs/src => src}/qhull/html/qconvex.htm (100%) rename {xs/src => src}/qhull/html/qdelau_f.htm (100%) rename {xs/src => src}/qhull/html/qdelaun.htm (100%) rename {xs/src => src}/qhull/html/qh--4d.gif (100%) rename {xs/src => src}/qhull/html/qh--cone.gif (100%) rename {xs/src => src}/qhull/html/qh--dt.gif (100%) rename {xs/src => src}/qhull/html/qh--geom.gif (100%) rename {xs/src => src}/qhull/html/qh--half.gif (100%) rename {xs/src => src}/qhull/html/qh--rand.gif (100%) rename {xs/src => src}/qhull/html/qh-code.htm (100%) rename {xs/src => src}/qhull/html/qh-eg.htm (100%) rename {xs/src => src}/qhull/html/qh-faq.htm (100%) rename {xs/src => src}/qhull/html/qh-get.htm (100%) rename {xs/src => src}/qhull/html/qh-impre.htm (100%) rename {xs/src => src}/qhull/html/qh-optc.htm (100%) rename {xs/src => src}/qhull/html/qh-optf.htm (100%) rename {xs/src => src}/qhull/html/qh-optg.htm (100%) rename {xs/src => src}/qhull/html/qh-opto.htm (100%) rename {xs/src => src}/qhull/html/qh-optp.htm (100%) rename {xs/src => src}/qhull/html/qh-optq.htm (100%) rename {xs/src => src}/qhull/html/qh-optt.htm (100%) rename {xs/src => src}/qhull/html/qh-quick.htm (100%) rename {xs/src => src}/qhull/html/qhalf.htm (100%) rename {xs/src => src}/qhull/html/qhull-cpp.xml (100%) rename {xs/src => src}/qhull/html/qhull.htm (100%) rename {xs/src => src}/qhull/html/qhull.man (100%) rename {xs/src => src}/qhull/html/qhull.txt (100%) rename {xs/src => src}/qhull/html/qvoron_f.htm (100%) rename {xs/src => src}/qhull/html/qvoronoi.htm (100%) rename {xs/src => src}/qhull/html/rbox.htm (100%) rename {xs/src => src}/qhull/html/rbox.man (100%) rename {xs/src => src}/qhull/html/rbox.txt (100%) rename {xs/src => src}/qhull/index.htm (100%) rename {xs/src => src}/qhull/origCMakeLists.txt (100%) rename {xs/src => src}/qhull/src/Changes.txt (100%) rename {xs/src => src}/qhull/src/libqhull/DEPRECATED.txt (100%) rename {xs/src => src}/qhull/src/libqhull/Makefile (100%) rename {xs/src => src}/qhull/src/libqhull/Mborland (100%) rename {xs/src => src}/qhull/src/libqhull/geom.c (100%) rename {xs/src => src}/qhull/src/libqhull/geom.h (100%) rename {xs/src => src}/qhull/src/libqhull/geom2.c (100%) rename {xs/src => src}/qhull/src/libqhull/global.c (100%) rename {xs/src => src}/qhull/src/libqhull/index.htm (100%) rename {xs/src => src}/qhull/src/libqhull/io.c (100%) rename {xs/src => src}/qhull/src/libqhull/io.h (100%) rename {xs/src => src}/qhull/src/libqhull/libqhull.c (100%) rename {xs/src => src}/qhull/src/libqhull/libqhull.h (100%) rename {xs/src => src}/qhull/src/libqhull/libqhull.pro (100%) rename {xs/src => src}/qhull/src/libqhull/mem.c (100%) rename {xs/src => src}/qhull/src/libqhull/mem.h (100%) rename {xs/src => src}/qhull/src/libqhull/merge.c (100%) rename {xs/src => src}/qhull/src/libqhull/merge.h (100%) rename {xs/src => src}/qhull/src/libqhull/poly.c (100%) rename {xs/src => src}/qhull/src/libqhull/poly.h (100%) rename {xs/src => src}/qhull/src/libqhull/poly2.c (100%) rename {xs/src => src}/qhull/src/libqhull/qh-geom.htm (100%) rename {xs/src => src}/qhull/src/libqhull/qh-globa.htm (100%) rename {xs/src => src}/qhull/src/libqhull/qh-io.htm (100%) rename {xs/src => src}/qhull/src/libqhull/qh-mem.htm (100%) rename {xs/src => src}/qhull/src/libqhull/qh-merge.htm (100%) rename {xs/src => src}/qhull/src/libqhull/qh-poly.htm (100%) rename {xs/src => src}/qhull/src/libqhull/qh-qhull.htm (100%) rename {xs/src => src}/qhull/src/libqhull/qh-set.htm (100%) rename {xs/src => src}/qhull/src/libqhull/qh-stat.htm (100%) rename {xs/src => src}/qhull/src/libqhull/qh-user.htm (100%) rename {xs/src => src}/qhull/src/libqhull/qhull-exports.def (100%) rename {xs/src => src}/qhull/src/libqhull/qhull_a.h (100%) rename {xs/src => src}/qhull/src/libqhull/qhull_p-exports.def (100%) rename {xs/src => src}/qhull/src/libqhull/qset.c (100%) rename {xs/src => src}/qhull/src/libqhull/qset.h (100%) rename {xs/src => src}/qhull/src/libqhull/random.c (100%) rename {xs/src => src}/qhull/src/libqhull/random.h (100%) rename {xs/src => src}/qhull/src/libqhull/rboxlib.c (100%) rename {xs/src => src}/qhull/src/libqhull/stat.c (100%) rename {xs/src => src}/qhull/src/libqhull/stat.h (100%) rename {xs/src => src}/qhull/src/libqhull/user.c (100%) rename {xs/src => src}/qhull/src/libqhull/user.h (100%) rename {xs/src => src}/qhull/src/libqhull/usermem.c (100%) rename {xs/src => src}/qhull/src/libqhull/userprintf.c (100%) rename {xs/src => src}/qhull/src/libqhull/userprintf_rbox.c (100%) rename {xs/src => src}/qhull/src/libqhull_r/Makefile (100%) rename {xs/src => src}/qhull/src/libqhull_r/geom2_r.c (100%) rename {xs/src => src}/qhull/src/libqhull_r/geom_r.c (100%) rename {xs/src => src}/qhull/src/libqhull_r/geom_r.h (100%) rename {xs/src => src}/qhull/src/libqhull_r/global_r.c (100%) rename {xs/src => src}/qhull/src/libqhull_r/index.htm (100%) rename {xs/src => src}/qhull/src/libqhull_r/io_r.c (100%) rename {xs/src => src}/qhull/src/libqhull_r/io_r.h (100%) rename {xs/src => src}/qhull/src/libqhull_r/libqhull_r.c (100%) rename {xs/src => src}/qhull/src/libqhull_r/libqhull_r.h (100%) rename {xs/src => src}/qhull/src/libqhull_r/libqhull_r.pro (100%) rename {xs/src => src}/qhull/src/libqhull_r/mem_r.c (100%) rename {xs/src => src}/qhull/src/libqhull_r/mem_r.h (100%) rename {xs/src => src}/qhull/src/libqhull_r/merge_r.c (100%) rename {xs/src => src}/qhull/src/libqhull_r/merge_r.h (100%) rename {xs/src => src}/qhull/src/libqhull_r/poly2_r.c (100%) rename {xs/src => src}/qhull/src/libqhull_r/poly_r.c (100%) rename {xs/src => src}/qhull/src/libqhull_r/poly_r.h (100%) rename {xs/src => src}/qhull/src/libqhull_r/qh-geom_r.htm (100%) rename {xs/src => src}/qhull/src/libqhull_r/qh-globa_r.htm (100%) rename {xs/src => src}/qhull/src/libqhull_r/qh-io_r.htm (100%) rename {xs/src => src}/qhull/src/libqhull_r/qh-mem_r.htm (100%) rename {xs/src => src}/qhull/src/libqhull_r/qh-merge_r.htm (100%) rename {xs/src => src}/qhull/src/libqhull_r/qh-poly_r.htm (100%) rename {xs/src => src}/qhull/src/libqhull_r/qh-qhull_r.htm (100%) rename {xs/src => src}/qhull/src/libqhull_r/qh-set_r.htm (100%) rename {xs/src => src}/qhull/src/libqhull_r/qh-stat_r.htm (100%) rename {xs/src => src}/qhull/src/libqhull_r/qh-user_r.htm (100%) rename {xs/src => src}/qhull/src/libqhull_r/qhull_r-exports.def (100%) rename {xs/src => src}/qhull/src/libqhull_r/qhull_ra.h (100%) rename {xs/src => src}/qhull/src/libqhull_r/qset_r.c (100%) rename {xs/src => src}/qhull/src/libqhull_r/qset_r.h (100%) rename {xs/src => src}/qhull/src/libqhull_r/random_r.c (100%) rename {xs/src => src}/qhull/src/libqhull_r/random_r.h (100%) rename {xs/src => src}/qhull/src/libqhull_r/rboxlib_r.c (100%) rename {xs/src => src}/qhull/src/libqhull_r/stat_r.c (100%) rename {xs/src => src}/qhull/src/libqhull_r/stat_r.h (100%) rename {xs/src => src}/qhull/src/libqhull_r/user_r.c (100%) rename {xs/src => src}/qhull/src/libqhull_r/user_r.h (100%) rename {xs/src => src}/qhull/src/libqhull_r/usermem_r.c (100%) rename {xs/src => src}/qhull/src/libqhull_r/userprintf_r.c (100%) rename {xs/src => src}/qhull/src/libqhull_r/userprintf_rbox_r.c (100%) rename {xs/src => src}/qhull/src/libqhullcpp/Coordinates.cpp (100%) rename {xs/src => src}/qhull/src/libqhullcpp/Coordinates.h (100%) rename {xs/src => src}/qhull/src/libqhullcpp/PointCoordinates.cpp (100%) rename {xs/src => src}/qhull/src/libqhullcpp/PointCoordinates.h (100%) rename {xs/src => src}/qhull/src/libqhullcpp/Qhull.cpp (100%) rename {xs/src => src}/qhull/src/libqhullcpp/Qhull.h (100%) rename {xs/src => src}/qhull/src/libqhullcpp/QhullError.h (100%) rename {xs/src => src}/qhull/src/libqhullcpp/QhullFacet.cpp (100%) rename {xs/src => src}/qhull/src/libqhullcpp/QhullFacet.h (100%) rename {xs/src => src}/qhull/src/libqhullcpp/QhullFacetList.cpp (100%) rename {xs/src => src}/qhull/src/libqhullcpp/QhullFacetList.h (100%) rename {xs/src => src}/qhull/src/libqhullcpp/QhullFacetSet.cpp (100%) rename {xs/src => src}/qhull/src/libqhullcpp/QhullFacetSet.h (100%) rename {xs/src => src}/qhull/src/libqhullcpp/QhullHyperplane.cpp (100%) rename {xs/src => src}/qhull/src/libqhullcpp/QhullHyperplane.h (100%) rename {xs/src => src}/qhull/src/libqhullcpp/QhullIterator.h (100%) rename {xs/src => src}/qhull/src/libqhullcpp/QhullLinkedList.h (100%) rename {xs/src => src}/qhull/src/libqhullcpp/QhullPoint.cpp (100%) rename {xs/src => src}/qhull/src/libqhullcpp/QhullPoint.h (100%) rename {xs/src => src}/qhull/src/libqhullcpp/QhullPointSet.cpp (100%) rename {xs/src => src}/qhull/src/libqhullcpp/QhullPointSet.h (100%) rename {xs/src => src}/qhull/src/libqhullcpp/QhullPoints.cpp (100%) rename {xs/src => src}/qhull/src/libqhullcpp/QhullPoints.h (100%) rename {xs/src => src}/qhull/src/libqhullcpp/QhullQh.cpp (100%) rename {xs/src => src}/qhull/src/libqhullcpp/QhullQh.h (100%) rename {xs/src => src}/qhull/src/libqhullcpp/QhullRidge.cpp (100%) rename {xs/src => src}/qhull/src/libqhullcpp/QhullRidge.h (100%) rename {xs/src => src}/qhull/src/libqhullcpp/QhullSet.cpp (100%) rename {xs/src => src}/qhull/src/libqhullcpp/QhullSet.h (100%) rename {xs/src => src}/qhull/src/libqhullcpp/QhullSets.h (100%) rename {xs/src => src}/qhull/src/libqhullcpp/QhullStat.cpp (100%) rename {xs/src => src}/qhull/src/libqhullcpp/QhullStat.h (100%) rename {xs/src => src}/qhull/src/libqhullcpp/QhullVertex.cpp (100%) rename {xs/src => src}/qhull/src/libqhullcpp/QhullVertex.h (100%) rename {xs/src => src}/qhull/src/libqhullcpp/QhullVertexSet.cpp (100%) rename {xs/src => src}/qhull/src/libqhullcpp/QhullVertexSet.h (100%) rename {xs/src => src}/qhull/src/libqhullcpp/RboxPoints.cpp (100%) rename {xs/src => src}/qhull/src/libqhullcpp/RboxPoints.h (100%) rename {xs/src => src}/qhull/src/libqhullcpp/RoadError.cpp (100%) rename {xs/src => src}/qhull/src/libqhullcpp/RoadError.h (100%) rename {xs/src => src}/qhull/src/libqhullcpp/RoadLogEvent.cpp (100%) rename {xs/src => src}/qhull/src/libqhullcpp/RoadLogEvent.h (100%) rename {xs/src => src}/qhull/src/libqhullcpp/functionObjects.h (100%) rename {xs/src => src}/qhull/src/libqhullcpp/libqhullcpp.pro (100%) rename {xs/src => src}/qhull/src/libqhullcpp/qt-qhull.cpp (100%) rename {xs/src => src}/qhull/src/libqhullcpp/usermem_r-cpp.cpp (100%) rename {xs/src => src}/qhull/src/libqhullstatic/libqhullstatic.pro (100%) rename {xs/src => src}/qhull/src/libqhullstatic_r/libqhullstatic_r.pro (100%) rename {xs/src => src}/qhull/src/qconvex/qconvex.c (100%) rename {xs/src => src}/qhull/src/qconvex/qconvex.pro (100%) rename {xs/src => src}/qhull/src/qconvex/qconvex_r.c (100%) rename {xs/src => src}/qhull/src/qdelaunay/qdelaun.c (100%) rename {xs/src => src}/qhull/src/qdelaunay/qdelaun_r.c (100%) rename {xs/src => src}/qhull/src/qdelaunay/qdelaunay.pro (100%) rename {xs/src => src}/qhull/src/qhalf/qhalf.c (100%) rename {xs/src => src}/qhull/src/qhalf/qhalf.pro (100%) rename {xs/src => src}/qhull/src/qhalf/qhalf_r.c (100%) rename {xs/src => src}/qhull/src/qhull-all.pro (100%) rename {xs/src => src}/qhull/src/qhull-app-c.pri (100%) rename {xs/src => src}/qhull/src/qhull-app-c_r.pri (100%) rename {xs/src => src}/qhull/src/qhull-app-cpp.pri (100%) rename {xs/src => src}/qhull/src/qhull-app-shared.pri (100%) rename {xs/src => src}/qhull/src/qhull-app-shared_r.pri (100%) rename {xs/src => src}/qhull/src/qhull-libqhull-src.pri (100%) rename {xs/src => src}/qhull/src/qhull-libqhull-src_r.pri (100%) rename {xs/src => src}/qhull/src/qhull-warn.pri (100%) rename {xs/src => src}/qhull/src/qhull/qhull.pro (100%) rename {xs/src => src}/qhull/src/qhull/unix.c (100%) rename {xs/src => src}/qhull/src/qhull/unix_r.c (100%) rename {xs/src => src}/qhull/src/qhulltest/Coordinates_test.cpp (100%) rename {xs/src => src}/qhull/src/qhulltest/PointCoordinates_test.cpp (100%) rename {xs/src => src}/qhull/src/qhulltest/QhullFacetList_test.cpp (100%) rename {xs/src => src}/qhull/src/qhulltest/QhullFacetSet_test.cpp (100%) rename {xs/src => src}/qhull/src/qhulltest/QhullFacet_test.cpp (100%) rename {xs/src => src}/qhull/src/qhulltest/QhullHyperplane_test.cpp (100%) rename {xs/src => src}/qhull/src/qhulltest/QhullLinkedList_test.cpp (100%) rename {xs/src => src}/qhull/src/qhulltest/QhullPointSet_test.cpp (100%) rename {xs/src => src}/qhull/src/qhulltest/QhullPoint_test.cpp (100%) rename {xs/src => src}/qhull/src/qhulltest/QhullPoints_test.cpp (100%) rename {xs/src => src}/qhull/src/qhulltest/QhullRidge_test.cpp (100%) rename {xs/src => src}/qhull/src/qhulltest/QhullSet_test.cpp (100%) rename {xs/src => src}/qhull/src/qhulltest/QhullVertexSet_test.cpp (100%) rename {xs/src => src}/qhull/src/qhulltest/QhullVertex_test.cpp (100%) rename {xs/src => src}/qhull/src/qhulltest/Qhull_test.cpp (100%) rename {xs/src => src}/qhull/src/qhulltest/RboxPoints_test.cpp (100%) rename {xs/src => src}/qhull/src/qhulltest/RoadTest.cpp (100%) rename {xs/src => src}/qhull/src/qhulltest/RoadTest.h (100%) rename {xs/src => src}/qhull/src/qhulltest/qhulltest.cpp (100%) rename {xs/src => src}/qhull/src/qhulltest/qhulltest.pro (100%) rename {xs/src => src}/qhull/src/qvoronoi/qvoronoi.c (100%) rename {xs/src => src}/qhull/src/qvoronoi/qvoronoi.pro (100%) rename {xs/src => src}/qhull/src/qvoronoi/qvoronoi_r.c (100%) rename {xs/src => src}/qhull/src/rbox/rbox.c (100%) rename {xs/src => src}/qhull/src/rbox/rbox.pro (100%) rename {xs/src => src}/qhull/src/rbox/rbox_r.c (100%) rename {xs/src => src}/qhull/src/testqset/testqset.c (100%) rename {xs/src => src}/qhull/src/testqset/testqset.pro (100%) rename {xs/src => src}/qhull/src/testqset_r/testqset_r.c (100%) rename {xs/src => src}/qhull/src/testqset_r/testqset_r.pro (100%) rename {xs/src => src}/qhull/src/user_eg/user_eg.c (100%) rename {xs/src => src}/qhull/src/user_eg/user_eg.pro (100%) rename {xs/src => src}/qhull/src/user_eg/user_eg_r.c (100%) rename {xs/src => src}/qhull/src/user_eg2/user_eg2.c (100%) rename {xs/src => src}/qhull/src/user_eg2/user_eg2.pro (100%) rename {xs/src => src}/qhull/src/user_eg2/user_eg2_r.c (100%) rename {xs/src => src}/qhull/src/user_eg3/user_eg3.pro (100%) rename {xs/src => src}/qhull/src/user_eg3/user_eg3_r.cpp (100%) create mode 100644 src/semver/CMakeLists.txt rename {xs/src => src}/semver/semver.c (100%) rename {xs/src => src}/semver/semver.h (100%) rename {xs/src => src}/slic3r/AppController.cpp (100%) rename {xs/src => src}/slic3r/AppController.hpp (100%) rename {xs/src => src}/slic3r/AppControllerWx.cpp (100%) create mode 100644 src/slic3r/CMakeLists.txt rename {xs/src => src}/slic3r/Config/Snapshot.cpp (100%) rename {xs/src => src}/slic3r/Config/Snapshot.hpp (100%) rename {xs/src => src}/slic3r/Config/Version.cpp (100%) rename {xs/src => src}/slic3r/Config/Version.hpp (100%) rename {xs/src => src}/slic3r/GUI/2DBed.cpp (100%) rename {xs/src => src}/slic3r/GUI/2DBed.hpp (100%) rename {xs/src => src}/slic3r/GUI/3DScene.cpp (100%) rename {xs/src => src}/slic3r/GUI/3DScene.hpp (100%) rename {xs/src => src}/slic3r/GUI/AboutDialog.cpp (100%) rename {xs/src => src}/slic3r/GUI/AboutDialog.hpp (100%) rename {xs/src => src}/slic3r/GUI/AppConfig.cpp (100%) rename {xs/src => src}/slic3r/GUI/AppConfig.hpp (100%) rename {xs/src => src}/slic3r/GUI/BackgroundSlicingProcess.cpp (100%) rename {xs/src => src}/slic3r/GUI/BackgroundSlicingProcess.hpp (100%) rename {xs/src => src}/slic3r/GUI/BedShapeDialog.cpp (100%) rename {xs/src => src}/slic3r/GUI/BedShapeDialog.hpp (100%) rename {xs/src => src}/slic3r/GUI/BitmapCache.cpp (100%) rename {xs/src => src}/slic3r/GUI/BitmapCache.hpp (100%) rename {xs/src => src}/slic3r/GUI/BonjourDialog.cpp (100%) rename {xs/src => src}/slic3r/GUI/BonjourDialog.hpp (100%) rename {xs/src => src}/slic3r/GUI/ButtonsDescription.cpp (100%) rename {xs/src => src}/slic3r/GUI/ButtonsDescription.hpp (100%) rename {xs/src => src}/slic3r/GUI/ConfigExceptions.hpp (100%) rename {xs/src => src}/slic3r/GUI/ConfigSnapshotDialog.cpp (100%) rename {xs/src => src}/slic3r/GUI/ConfigSnapshotDialog.hpp (100%) rename {xs/src => src}/slic3r/GUI/ConfigWizard.cpp (100%) rename {xs/src => src}/slic3r/GUI/ConfigWizard.hpp (100%) rename {xs/src => src}/slic3r/GUI/ConfigWizard_private.hpp (100%) rename {xs/src => src}/slic3r/GUI/Field.cpp (100%) rename {xs/src => src}/slic3r/GUI/Field.hpp (100%) rename {xs/src => src}/slic3r/GUI/FirmwareDialog.cpp (100%) rename {xs/src => src}/slic3r/GUI/FirmwareDialog.hpp (100%) rename {xs/src => src}/slic3r/GUI/GLCanvas3D.cpp (100%) rename {xs/src => src}/slic3r/GUI/GLCanvas3D.hpp (100%) rename {xs/src => src}/slic3r/GUI/GLCanvas3DManager.cpp (100%) rename {xs/src => src}/slic3r/GUI/GLCanvas3DManager.hpp (100%) rename {xs/src => src}/slic3r/GUI/GLGizmo.cpp (100%) rename {xs/src => src}/slic3r/GUI/GLGizmo.hpp (100%) rename {xs/src => src}/slic3r/GUI/GLShader.cpp (100%) rename {xs/src => src}/slic3r/GUI/GLShader.hpp (100%) rename {xs/src => src}/slic3r/GUI/GLTexture.cpp (100%) rename {xs/src => src}/slic3r/GUI/GLTexture.hpp (100%) rename {xs/src => src}/slic3r/GUI/GLToolbar.cpp (100%) rename {xs/src => src}/slic3r/GUI/GLToolbar.hpp (100%) rename {xs/src => src}/slic3r/GUI/GUI.cpp (99%) rename {xs/src => src}/slic3r/GUI/GUI.hpp (97%) rename {xs/src => src}/slic3r/GUI/GUI_ObjectParts.cpp (100%) rename {xs/src => src}/slic3r/GUI/GUI_ObjectParts.hpp (100%) rename {xs/src => src}/slic3r/GUI/LambdaObjectDialog.cpp (100%) rename {xs/src => src}/slic3r/GUI/LambdaObjectDialog.hpp (100%) rename {xs/src => src}/slic3r/GUI/MsgDialog.cpp (100%) rename {xs/src => src}/slic3r/GUI/MsgDialog.hpp (100%) rename {xs/src => src}/slic3r/GUI/OptionsGroup.cpp (100%) rename {xs/src => src}/slic3r/GUI/OptionsGroup.hpp (100%) rename {xs/src => src}/slic3r/GUI/Preferences.cpp (100%) rename {xs/src => src}/slic3r/GUI/Preferences.hpp (100%) rename {xs/src => src}/slic3r/GUI/Preset.cpp (100%) rename {xs/src => src}/slic3r/GUI/Preset.hpp (100%) rename {xs/src => src}/slic3r/GUI/PresetBundle.cpp (100%) rename {xs/src => src}/slic3r/GUI/PresetBundle.hpp (100%) rename {xs/src => src}/slic3r/GUI/PresetHints.cpp (100%) rename {xs/src => src}/slic3r/GUI/PresetHints.hpp (100%) rename {xs/src => src}/slic3r/GUI/ProgressIndicator.hpp (100%) rename {xs/src => src}/slic3r/GUI/ProgressStatusBar.cpp (100%) rename {xs/src => src}/slic3r/GUI/ProgressStatusBar.hpp (98%) rename {xs/src => src}/slic3r/GUI/RammingChart.cpp (100%) rename {xs/src => src}/slic3r/GUI/RammingChart.hpp (100%) rename {xs/src => src}/slic3r/GUI/Tab.cpp (100%) rename {xs/src => src}/slic3r/GUI/Tab.hpp (100%) rename {xs/src => src}/slic3r/GUI/TabIface.cpp (100%) rename {xs/src => src}/slic3r/GUI/TabIface.hpp (100%) rename {xs/src => src}/slic3r/GUI/UpdateDialogs.cpp (100%) rename {xs/src => src}/slic3r/GUI/UpdateDialogs.hpp (100%) rename {xs/src => src}/slic3r/GUI/Widget.hpp (100%) rename {xs/src => src}/slic3r/GUI/WipeTowerDialog.cpp (100%) rename {xs/src => src}/slic3r/GUI/WipeTowerDialog.hpp (100%) create mode 100644 src/slic3r/GUI/callback.hpp rename {xs/src => src}/slic3r/GUI/wxExtensions.cpp (100%) rename {xs/src => src}/slic3r/GUI/wxExtensions.hpp (100%) rename {xs/src => src}/slic3r/GUI/wxinit.h (100%) rename {xs/src => src}/slic3r/Utils/ASCIIFolding.cpp (100%) rename {xs/src => src}/slic3r/Utils/ASCIIFolding.hpp (100%) rename {xs/src => src}/slic3r/Utils/Bonjour.cpp (100%) rename {xs/src => src}/slic3r/Utils/Bonjour.hpp (100%) rename {xs/src => src}/slic3r/Utils/Duet.cpp (100%) rename {xs/src => src}/slic3r/Utils/Duet.hpp (100%) rename {xs/src => src}/slic3r/Utils/FixModelByWin10.cpp (100%) rename {xs/src => src}/slic3r/Utils/FixModelByWin10.hpp (100%) rename {xs/src => src}/slic3r/Utils/HexFile.cpp (100%) rename {xs/src => src}/slic3r/Utils/HexFile.hpp (100%) rename {xs/src => src}/slic3r/Utils/Http.cpp (100%) rename {xs/src => src}/slic3r/Utils/Http.hpp (100%) rename {xs/src => src}/slic3r/Utils/OctoPrint.cpp (100%) rename {xs/src => src}/slic3r/Utils/OctoPrint.hpp (100%) rename {xs/src => src}/slic3r/Utils/PresetUpdater.cpp (100%) rename {xs/src => src}/slic3r/Utils/PresetUpdater.hpp (100%) rename {xs/src => src}/slic3r/Utils/PrintHost.cpp (100%) rename {xs/src => src}/slic3r/Utils/PrintHost.hpp (100%) rename {xs/src => src}/slic3r/Utils/PrintHostSendDialog.cpp (100%) rename {xs/src => src}/slic3r/Utils/PrintHostSendDialog.hpp (100%) rename {xs/src => src}/slic3r/Utils/Semver.hpp (100%) rename {xs/src => src}/slic3r/Utils/Serial.cpp (100%) rename {xs/src => src}/slic3r/Utils/Serial.hpp (100%) rename {xs/src => src}/slic3r/Utils/Time.cpp (100%) rename {xs/src => src}/slic3r/Utils/Time.hpp (100%) delete mode 100644 xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch03s01s01.html~ delete mode 100644 xs/src/libnest2d/tools/benchmark.h delete mode 100644 xs/src/slic3r/GUI/wxPerlIface.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 8e3d8ad4df..1e1817f542 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,5 @@ -cmake_minimum_required(VERSION 3.2) - project(Slic3r) +cmake_minimum_required(VERSION 3.2) if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) message(STATUS "No build type selected, default to Release") @@ -48,7 +47,6 @@ else() set(PERL5LIB_ENV_CMD ${CMAKE_COMMAND} -E env PERL5LIB=${PERL_INCLUDE}) endif() - # CMAKE_PREFIX_PATH is used to point CMake to the remaining dependencies (Boost, TBB, ...) # We pick it from environment if it is not defined in another way if(NOT DEFINED CMAKE_PREFIX_PATH) @@ -57,8 +55,19 @@ if(NOT DEFINED CMAKE_PREFIX_PATH) endif() endif() +# Add our own cmake module path. +list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/modules/) + enable_testing () +# Enable C++11 language standard. +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# Enable C11 language standard. +set(CMAKE_C_STANDARD 11) +set(CMAKE_C_STANDARD_REQUIRED ON) + # WIN10SDK_PATH is used to point CMake to the WIN10 SDK installation directory. # We pick it from environment if it is not defined in another way if(WIN32) @@ -75,6 +84,187 @@ if(WIN32) endif() endif() +if (CMAKE_SYSTEM_NAME STREQUAL "Linux") + # Workaround for an old CMake, which does not understand CMAKE_CXX_STANDARD. + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Wno-reorder" ) + find_package(PkgConfig REQUIRED) +endif() + +if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUXX) + # Adding -fext-numeric-literals to enable GCC extensions on definitions of quad float literals, which are required by Boost. + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fext-numeric-literals" ) +endif() + +# Where all the bundled libraries reside? +set(LIBDIR ${CMAKE_CURRENT_SOURCE_DIR}/src/) +# For the bundled boost libraries (boost::nowide) +include_directories(${LIBDIR}) +# For libslic3r.h +include_directories(${LIBDIR}/libslic3r ${LIBDIR}/clipper ${LIBDIR}/polypartition) +#set(CMAKE_INCLUDE_CURRENT_DIR ON) + +if(WIN32) + # BOOST_ALL_NO_LIB: Avoid the automatic linking of Boost libraries on Windows. Rather rely on explicit linking. + add_definitions(-D_USE_MATH_DEFINES -D_WIN32 -DBOOST_ALL_NO_LIB -DBOOST_USE_WINAPI_VERSION=0x601) +endif() + +add_definitions(-DwxUSE_UNICODE -D_UNICODE -DUNICODE -DWXINTL_NO_GETTEXT_MACRO) + +if (SLIC3R_PROFILE) + message("Slic3r will be built with a Shiny invasive profiler") + add_definitions(-DSLIC3R_PROFILE) +endif () + +# Perl specific stuff +find_package(PerlLibs REQUIRED) +set(PerlEmbed_DEBUG 1) +find_package(PerlEmbed REQUIRED) +# If the Perl is compiled with optimization off, disable optimization over the whole project. +if (WIN32 AND ";${PerlEmbed_CCFLAGS};" MATCHES ";[-/]Od;") + message(STATUS "Perl compiled without optimization. Disabling optimization for the Slic3r build.") + message("Old CMAKE_CXX_FLAGS_RELEASE: ${CMAKE_CXX_FLAGS_RELEASE}") + message("Old CMAKE_CXX_FLAGS_RELWITHDEBINFO: ${CMAKE_CXX_FLAGS_RELEASE}") + message("Old CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS_RELEASE}") + set(CMAKE_CXX_FLAGS_RELEASE "/MD /Od /Zi /EHsc /DNDEBUG /DWIN32 /DTBB_USE_ASSERT") + set(CMAKE_C_FLAGS_RELEASE "/MD /Od /Zi /DNDEBUG /DWIN32 /DTBB_USE_ASSERT") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "/MD /Od /Zi /EHsc /DNDEBUG /DWIN32 /DTBB_USE_ASSERT") + set(CMAKE_C_FLAGS_RELWITHDEBINFO "/MD /Od /Zi /DNDEBUG /DWIN32 /DTBB_USE_ASSERT") + set(CMAKE_CXX_FLAGS "/MD /Od /Zi /EHsc /DNDEBUG /DWIN32 /DTBB_USE_ASSERT") + set(CMAKE_C_FLAGS "/MD /Od /Zi /DNDEBUG /DWIN32 /DTBB_USE_ASSERT") +endif() +# The following line will add -fPIC on Linux to make the XS.so rellocable. +add_definitions(${PerlEmbed_CCCDLFLAGS}) + +# Find and configure boost +if(SLIC3R_STATIC) + # Use static boost libraries. + set(Boost_USE_STATIC_LIBS ON) + # Use boost libraries linked statically to the C++ runtime. + # set(Boost_USE_STATIC_RUNTIME ON) +endif() +#set(Boost_DEBUG ON) +find_package(Boost REQUIRED COMPONENTS system filesystem thread log locale regex) +if(Boost_FOUND) + include_directories(${Boost_INCLUDE_DIRS}) + if (APPLE) + # BOOST_ASIO_DISABLE_KQUEUE : prevents a Boost ASIO bug on OS X: https://svn.boost.org/trac/boost/ticket/5339 + add_definitions(-DBOOST_ASIO_DISABLE_KQUEUE) + endif() + if(NOT SLIC3R_STATIC) + add_definitions(-DBOOST_LOG_DYN_LINK) + endif() +endif() + +# Find and configure intel-tbb +if(SLIC3R_STATIC) + set(TBB_STATIC 1) +endif() +set(TBB_DEBUG 1) +find_package(TBB REQUIRED) +include_directories(${TBB_INCLUDE_DIRS}) +add_definitions(${TBB_DEFINITIONS}) +if(MSVC) + # Suppress implicit linking of the TBB libraries by the Visual Studio compiler. + add_definitions(-D__TBB_NO_IMPLICIT_LINKAGE) +endif() +# The Intel TBB library will use the std::exception_ptr feature of C++11. +add_definitions(-DTBB_USE_CAPTURED_EXCEPTION=0) + +# Find and configure wxWidgets +if (SLIC3R_PRUSACONTROL) + set(wxWidgets_UseAlienWx 1) + if (wxWidgets_UseAlienWx) + set(AlienWx_DEBUG 1) + find_package(AlienWx REQUIRED COMPONENTS base core adv html gl) + include_directories(${AlienWx_INCLUDE_DIRS}) + #add_compile_options(${AlienWx_CXX_FLAGS}) + add_definitions(${AlienWx_DEFINITIONS}) + set(wxWidgets_LIBRARIES ${AlienWx_LIBRARIES}) + # On Linux / gtk, we need to have a direct access to gtk+ for some workarounds. + if (AlienWx_GUI_TOOLKIT STREQUAL "gtk2") + pkg_check_modules(GTK2 gtk+-2.0) + include_directories(${GTK2_INCLUDE_DIRS}) + endif() + if (AlienWx_GUI_TOOLKIT STREQUAL "gtk3") + pkg_check_modules(GTK3 gtk+-3.0) + include_directories(${GTK3_INCLUDE_DIRS}) + endif() + else () + find_package(wxWidgets REQUIRED COMPONENTS base core adv html gl) + include(${wxWidgets_USE_FILE}) + endif () +#FIXME rewrite the PRUS format to miniz! +# add_definitions(-DSLIC3R_GUI -DSLIC3R_PRUS) +endif() + +find_package(CURL REQUIRED) +include_directories(${CURL_INCLUDE_DIRS}) + +if (SLIC3R_STATIC) + if (NOT APPLE) + # libcurl is always linked dynamically to the system libcurl on OSX. + # On other systems, libcurl is linked statically if SLIC3R_STATIC is set. + add_definitions(-DCURL_STATICLIB) + endif() + if (CMAKE_SYSTEM_NAME STREQUAL "Linux") + # As of now, our build system produces a statically linked libcurl, + # which links the OpenSSL library dynamically. + find_package(OpenSSL REQUIRED) + message("OpenSSL include dir: ${OPENSSL_INCLUDE_DIR}") + message("OpenSSL libraries: ${OPENSSL_LIBRARIES}") + include_directories(${OPENSSL_INCLUDE_DIR}) + endif() +endif() + +## OPTIONAL packages + +# Find eigen3 or use bundled version +if (NOT SLIC3R_STATIC) + find_package(Eigen3) +endif () +if (NOT Eigen3_FOUND) + set(Eigen3_FOUND 1) + set(EIGEN3_INCLUDE_DIR ${LIBDIR}/eigen/) +endif () +include_directories(${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 () +if (NOT EXPAT_FOUND) + add_library(expat STATIC + ${LIBDIR}/expat/xmlparse.c + ${LIBDIR}/expat/xmlrole.c + ${LIBDIR}/expat/xmltok.c + ) + set(EXPAT_FOUND 1) + set(EXPAT_INCLUDE_DIRS ${LIBDIR}/expat/) + set(EXPAT_LIBRARIES expat) +endif () +include_directories(${EXPAT_INCLUDE_DIRS}) + +# Find glew or use bundled version +if (NOT SLIC3R_STATIC) + find_package(GLEW) +endif () +if (NOT GLEW_FOUND) + add_library(glew STATIC ${LIBDIR}/glew/src/glew.c) + set(GLEW_FOUND 1) + set(GLEW_INCLUDE_DIRS ${LIBDIR}/glew/include/) + set(GLEW_LIBRARIES glew) + add_definitions(-DGLEW_STATIC) +endif () +include_directories(${GLEW_INCLUDE_DIRS}) + +# l10n +add_subdirectory(resources/localization) + +# libslic3r, Slic3r GUI and the slic3r executable. +add_subdirectory(src) + +# Perl bindings, currently only used for the unit / integration tests of libslic3r. add_subdirectory(xs) get_filename_component(PERL_BIN_PATH "${PERL_EXECUTABLE}" DIRECTORY) @@ -92,7 +282,7 @@ endif () add_test (NAME xs COMMAND "${PERL_EXECUTABLE}" ${PERL_PROVE} -I ${PROJECT_SOURCE_DIR}/local-lib/lib/perl5 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/xs) add_test (NAME integration COMMAND "${PERL_EXECUTABLE}" ${PERL_PROVE} WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}) -install(PROGRAMS slic3r.pl DESTINATION bin RENAME slic3r-prusa3d) +#install(PROGRAMS slic3r.pl DESTINATION bin RENAME slic3r-prusa3d) file(GLOB MyVar var/*.png) install(FILES ${MyVar} DESTINATION share/slic3r-prusa3d) diff --git a/resources/localization/CMakeLists.txt b/resources/localization/CMakeLists.txt new file mode 100644 index 0000000000..8a7fba068f --- /dev/null +++ b/resources/localization/CMakeLists.txt @@ -0,0 +1,8 @@ +set(L10N_DIR "${PROJECT_SOURCE_DIR}/resources/localization") +add_custom_target(pot + COMMAND xgettext --keyword=L --from-code=UTF-8 --debug + -f "${L10N_DIR}/list.txt" + -o "${L10N_DIR}/Slic3rPE.pot" + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} + COMMENT "Generate pot file from strings in the source tree" +) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000000..d0c0082937 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,65 @@ +project(Slic3r-native) + +add_subdirectory(admesh) +add_subdirectory(avrdude) +# boost/nowide +add_subdirectory(boost) +add_subdirectory(clipper) +add_subdirectory(miniz) +add_subdirectory(polypartition) +add_subdirectory(poly2tri) +add_subdirectory(qhull) +add_subdirectory(Shiny) +add_subdirectory(semver) + +# Adding libnest2d project for bin packing... +set(LIBNEST2D_UNITTESTS ON CACHE BOOL "Force generating unittests for libnest2d") +add_subdirectory(libnest2d) + +include_directories(${LIBDIR}/qhull/src) +#message(STATUS ${LIBDIR}/qhull/src) + + +# ############################################################################## +# Configure rasterizer target +# ############################################################################## + +find_package(PNG QUIET) + +option(RASTERIZER_FORCE_BUILTIN_LIBPNG "Force the usage of builting libpng instead of the system version." OFF) + +if(PNG_FOUND AND NOT RASTERIZER_FORCE_BUILTIN_LIBPNG) + message(STATUS "Using system libpng.") +else() + set(ZLIB_LIBRARY "") + message(WARNING "Using builtin libpng. This can cause crashes on some platforms.") + add_subdirectory(png/zlib) + set(ZLIB_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/png/zlib ${CMAKE_CURRENT_BINARY_DIR}/png/zlib) + include_directories(${ZLIB_INCLUDE_DIR}) + message(STATUS "ZLIB_INCLUDE_DIR ${ZLIB_INCLUDE_DIR}") + add_subdirectory(png/libpng) + set_target_properties(zlibstatic PROPERTIES POSITION_INDEPENDENT_CODE ON) + set_target_properties(png_static PROPERTIES POSITION_INDEPENDENT_CODE ON) +# target_include_directories(png_static PRIVATE ${ZLIB_INCLUDE_DIR}) + set(PNG_LIBRARIES png_static zlibstatic) + set(PNG_INCLUDE_DIRS ${ZLIB_INCLUDE_DIR} ${PROJECT_SOURCE_DIR}/png/libpng ${CMAKE_CURRENT_BINARY_DIR}/png/libpng) +endif() + +add_subdirectory(libslic3r) +add_subdirectory(slic3r) + +# Create a slic3r executable +add_executable(slic3r slic3r.cpp) +target_link_libraries(slic3r libslic3r libslic3r_gui ${wxWidgets_LIBRARIES} ${CURL_LIBRARIES}) +# Add the OpenGL and GLU libraries. +if (SLIC3R_GUI) + if (MSVC) + target_link_libraries(slic3r user32.lib Setupapi.lib OpenGL32.Lib GlU32.Lib) + elseif (MINGW) + target_link_libraries(slic3r -lopengl32) + elseif (APPLE) + target_link_libraries(slic3r "-framework OpenGL") + else () + target_link_libraries(slic3r -lGL -lGLU) + endif () +endif () diff --git a/src/Shiny/CMakeLists.txt b/src/Shiny/CMakeLists.txt new file mode 100644 index 0000000000..8be7592ae5 --- /dev/null +++ b/src/Shiny/CMakeLists.txt @@ -0,0 +1,25 @@ +project(Shiny) +cmake_minimum_required(VERSION 2.6) + +add_library(Shiny STATIC + Shiny.h + ShinyConfig.h + ShinyData.h + ShinyMacros.h + ShinyManager.c + ShinyManager.h + ShinyNode.c + ShinyNode.h + ShinyNodePool.c + ShinyNodePool.h + ShinyNodeState.c + ShinyNodeState.h + ShinyOutput.c + ShinyOutput.h + ShinyPrereqs.h + ShinyTools.c + ShinyTools.h + ShinyVersion.h + ShinyZone.c + ShinyZone.h +) diff --git a/xs/src/Shiny/Shiny.h b/src/Shiny/Shiny.h similarity index 100% rename from xs/src/Shiny/Shiny.h rename to src/Shiny/Shiny.h diff --git a/xs/src/Shiny/ShinyConfig.h b/src/Shiny/ShinyConfig.h similarity index 100% rename from xs/src/Shiny/ShinyConfig.h rename to src/Shiny/ShinyConfig.h diff --git a/xs/src/Shiny/ShinyData.h b/src/Shiny/ShinyData.h similarity index 100% rename from xs/src/Shiny/ShinyData.h rename to src/Shiny/ShinyData.h diff --git a/xs/src/Shiny/ShinyMacros.h b/src/Shiny/ShinyMacros.h similarity index 100% rename from xs/src/Shiny/ShinyMacros.h rename to src/Shiny/ShinyMacros.h diff --git a/xs/src/Shiny/ShinyManager.c b/src/Shiny/ShinyManager.c similarity index 100% rename from xs/src/Shiny/ShinyManager.c rename to src/Shiny/ShinyManager.c diff --git a/xs/src/Shiny/ShinyManager.h b/src/Shiny/ShinyManager.h similarity index 100% rename from xs/src/Shiny/ShinyManager.h rename to src/Shiny/ShinyManager.h diff --git a/xs/src/Shiny/ShinyNode.c b/src/Shiny/ShinyNode.c similarity index 100% rename from xs/src/Shiny/ShinyNode.c rename to src/Shiny/ShinyNode.c diff --git a/xs/src/Shiny/ShinyNode.h b/src/Shiny/ShinyNode.h similarity index 100% rename from xs/src/Shiny/ShinyNode.h rename to src/Shiny/ShinyNode.h diff --git a/xs/src/Shiny/ShinyNodePool.c b/src/Shiny/ShinyNodePool.c similarity index 100% rename from xs/src/Shiny/ShinyNodePool.c rename to src/Shiny/ShinyNodePool.c diff --git a/xs/src/Shiny/ShinyNodePool.h b/src/Shiny/ShinyNodePool.h similarity index 100% rename from xs/src/Shiny/ShinyNodePool.h rename to src/Shiny/ShinyNodePool.h diff --git a/xs/src/Shiny/ShinyNodeState.c b/src/Shiny/ShinyNodeState.c similarity index 100% rename from xs/src/Shiny/ShinyNodeState.c rename to src/Shiny/ShinyNodeState.c diff --git a/xs/src/Shiny/ShinyNodeState.h b/src/Shiny/ShinyNodeState.h similarity index 100% rename from xs/src/Shiny/ShinyNodeState.h rename to src/Shiny/ShinyNodeState.h diff --git a/xs/src/Shiny/ShinyOutput.c b/src/Shiny/ShinyOutput.c similarity index 100% rename from xs/src/Shiny/ShinyOutput.c rename to src/Shiny/ShinyOutput.c diff --git a/xs/src/Shiny/ShinyOutput.h b/src/Shiny/ShinyOutput.h similarity index 100% rename from xs/src/Shiny/ShinyOutput.h rename to src/Shiny/ShinyOutput.h diff --git a/xs/src/Shiny/ShinyPrereqs.h b/src/Shiny/ShinyPrereqs.h similarity index 100% rename from xs/src/Shiny/ShinyPrereqs.h rename to src/Shiny/ShinyPrereqs.h diff --git a/xs/src/Shiny/ShinyTools.c b/src/Shiny/ShinyTools.c similarity index 100% rename from xs/src/Shiny/ShinyTools.c rename to src/Shiny/ShinyTools.c diff --git a/xs/src/Shiny/ShinyTools.h b/src/Shiny/ShinyTools.h similarity index 100% rename from xs/src/Shiny/ShinyTools.h rename to src/Shiny/ShinyTools.h diff --git a/xs/src/Shiny/ShinyVersion.h b/src/Shiny/ShinyVersion.h similarity index 100% rename from xs/src/Shiny/ShinyVersion.h rename to src/Shiny/ShinyVersion.h diff --git a/xs/src/Shiny/ShinyZone.c b/src/Shiny/ShinyZone.c similarity index 100% rename from xs/src/Shiny/ShinyZone.c rename to src/Shiny/ShinyZone.c diff --git a/xs/src/Shiny/ShinyZone.h b/src/Shiny/ShinyZone.h similarity index 100% rename from xs/src/Shiny/ShinyZone.h rename to src/Shiny/ShinyZone.h diff --git a/src/admesh/CMakeLists.txt b/src/admesh/CMakeLists.txt new file mode 100644 index 0000000000..44c97c3f1b --- /dev/null +++ b/src/admesh/CMakeLists.txt @@ -0,0 +1,12 @@ +project(admesh) +cmake_minimum_required(VERSION 2.6) + +add_library(admesh STATIC + connect.cpp + normals.cpp + shared.cpp + stl.h + stl_io.cpp + stlinit.cpp + util.cpp +) diff --git a/xs/src/admesh/connect.cpp b/src/admesh/connect.cpp similarity index 100% rename from xs/src/admesh/connect.cpp rename to src/admesh/connect.cpp diff --git a/xs/src/admesh/normals.cpp b/src/admesh/normals.cpp similarity index 100% rename from xs/src/admesh/normals.cpp rename to src/admesh/normals.cpp diff --git a/xs/src/admesh/shared.cpp b/src/admesh/shared.cpp similarity index 100% rename from xs/src/admesh/shared.cpp rename to src/admesh/shared.cpp diff --git a/xs/src/admesh/stl.h b/src/admesh/stl.h similarity index 100% rename from xs/src/admesh/stl.h rename to src/admesh/stl.h diff --git a/xs/src/admesh/stl_io.cpp b/src/admesh/stl_io.cpp similarity index 100% rename from xs/src/admesh/stl_io.cpp rename to src/admesh/stl_io.cpp diff --git a/xs/src/admesh/stlinit.cpp b/src/admesh/stlinit.cpp similarity index 100% rename from xs/src/admesh/stlinit.cpp rename to src/admesh/stlinit.cpp diff --git a/xs/src/admesh/util.cpp b/src/admesh/util.cpp similarity index 100% rename from xs/src/admesh/util.cpp rename to src/admesh/util.cpp diff --git a/xs/src/agg/AUTHORS b/src/agg/AUTHORS similarity index 100% rename from xs/src/agg/AUTHORS rename to src/agg/AUTHORS diff --git a/xs/src/agg/VERSION b/src/agg/VERSION similarity index 100% rename from xs/src/agg/VERSION rename to src/agg/VERSION diff --git a/xs/src/agg/agg_array.h b/src/agg/agg_array.h similarity index 100% rename from xs/src/agg/agg_array.h rename to src/agg/agg_array.h diff --git a/xs/src/agg/agg_basics.h b/src/agg/agg_basics.h similarity index 100% rename from xs/src/agg/agg_basics.h rename to src/agg/agg_basics.h diff --git a/xs/src/agg/agg_bezier_arc.h b/src/agg/agg_bezier_arc.h similarity index 100% rename from xs/src/agg/agg_bezier_arc.h rename to src/agg/agg_bezier_arc.h diff --git a/xs/src/agg/agg_clip_liang_barsky.h b/src/agg/agg_clip_liang_barsky.h similarity index 100% rename from xs/src/agg/agg_clip_liang_barsky.h rename to src/agg/agg_clip_liang_barsky.h diff --git a/xs/src/agg/agg_color_gray.h b/src/agg/agg_color_gray.h similarity index 100% rename from xs/src/agg/agg_color_gray.h rename to src/agg/agg_color_gray.h diff --git a/xs/src/agg/agg_color_rgba.h b/src/agg/agg_color_rgba.h similarity index 100% rename from xs/src/agg/agg_color_rgba.h rename to src/agg/agg_color_rgba.h diff --git a/xs/src/agg/agg_config.h b/src/agg/agg_config.h similarity index 100% rename from xs/src/agg/agg_config.h rename to src/agg/agg_config.h diff --git a/xs/src/agg/agg_conv_transform.h b/src/agg/agg_conv_transform.h similarity index 100% rename from xs/src/agg/agg_conv_transform.h rename to src/agg/agg_conv_transform.h diff --git a/xs/src/agg/agg_gamma_functions.h b/src/agg/agg_gamma_functions.h similarity index 100% rename from xs/src/agg/agg_gamma_functions.h rename to src/agg/agg_gamma_functions.h diff --git a/xs/src/agg/agg_gamma_lut.h b/src/agg/agg_gamma_lut.h similarity index 100% rename from xs/src/agg/agg_gamma_lut.h rename to src/agg/agg_gamma_lut.h diff --git a/xs/src/agg/agg_math.h b/src/agg/agg_math.h similarity index 100% rename from xs/src/agg/agg_math.h rename to src/agg/agg_math.h diff --git a/xs/src/agg/agg_path_storage.h b/src/agg/agg_path_storage.h similarity index 100% rename from xs/src/agg/agg_path_storage.h rename to src/agg/agg_path_storage.h diff --git a/xs/src/agg/agg_pixfmt_base.h b/src/agg/agg_pixfmt_base.h similarity index 100% rename from xs/src/agg/agg_pixfmt_base.h rename to src/agg/agg_pixfmt_base.h diff --git a/xs/src/agg/agg_pixfmt_gray.h b/src/agg/agg_pixfmt_gray.h similarity index 100% rename from xs/src/agg/agg_pixfmt_gray.h rename to src/agg/agg_pixfmt_gray.h diff --git a/xs/src/agg/agg_pixfmt_rgb.h b/src/agg/agg_pixfmt_rgb.h similarity index 100% rename from xs/src/agg/agg_pixfmt_rgb.h rename to src/agg/agg_pixfmt_rgb.h diff --git a/xs/src/agg/agg_rasterizer_cells_aa.h b/src/agg/agg_rasterizer_cells_aa.h similarity index 100% rename from xs/src/agg/agg_rasterizer_cells_aa.h rename to src/agg/agg_rasterizer_cells_aa.h diff --git a/xs/src/agg/agg_rasterizer_scanline_aa.h b/src/agg/agg_rasterizer_scanline_aa.h similarity index 100% rename from xs/src/agg/agg_rasterizer_scanline_aa.h rename to src/agg/agg_rasterizer_scanline_aa.h diff --git a/xs/src/agg/agg_rasterizer_scanline_aa_nogamma.h b/src/agg/agg_rasterizer_scanline_aa_nogamma.h similarity index 100% rename from xs/src/agg/agg_rasterizer_scanline_aa_nogamma.h rename to src/agg/agg_rasterizer_scanline_aa_nogamma.h diff --git a/xs/src/agg/agg_rasterizer_sl_clip.h b/src/agg/agg_rasterizer_sl_clip.h similarity index 100% rename from xs/src/agg/agg_rasterizer_sl_clip.h rename to src/agg/agg_rasterizer_sl_clip.h diff --git a/xs/src/agg/agg_renderer_base.h b/src/agg/agg_renderer_base.h similarity index 100% rename from xs/src/agg/agg_renderer_base.h rename to src/agg/agg_renderer_base.h diff --git a/xs/src/agg/agg_renderer_scanline.h b/src/agg/agg_renderer_scanline.h similarity index 100% rename from xs/src/agg/agg_renderer_scanline.h rename to src/agg/agg_renderer_scanline.h diff --git a/xs/src/agg/agg_rendering_buffer.h b/src/agg/agg_rendering_buffer.h similarity index 100% rename from xs/src/agg/agg_rendering_buffer.h rename to src/agg/agg_rendering_buffer.h diff --git a/xs/src/agg/agg_scanline_p.h b/src/agg/agg_scanline_p.h similarity index 100% rename from xs/src/agg/agg_scanline_p.h rename to src/agg/agg_scanline_p.h diff --git a/xs/src/agg/agg_trans_affine.h b/src/agg/agg_trans_affine.h similarity index 100% rename from xs/src/agg/agg_trans_affine.h rename to src/agg/agg_trans_affine.h diff --git a/xs/src/agg/copying b/src/agg/copying similarity index 100% rename from xs/src/agg/copying rename to src/agg/copying diff --git a/xs/src/avrdude/AUTHORS b/src/avrdude/AUTHORS similarity index 100% rename from xs/src/avrdude/AUTHORS rename to src/avrdude/AUTHORS diff --git a/xs/src/avrdude/BUILD-FROM-SVN b/src/avrdude/BUILD-FROM-SVN similarity index 100% rename from xs/src/avrdude/BUILD-FROM-SVN rename to src/avrdude/BUILD-FROM-SVN diff --git a/xs/src/avrdude/CMakeLists.txt b/src/avrdude/CMakeLists.txt similarity index 100% rename from xs/src/avrdude/CMakeLists.txt rename to src/avrdude/CMakeLists.txt diff --git a/xs/src/avrdude/COPYING b/src/avrdude/COPYING similarity index 100% rename from xs/src/avrdude/COPYING rename to src/avrdude/COPYING diff --git a/xs/src/avrdude/ChangeLog b/src/avrdude/ChangeLog similarity index 100% rename from xs/src/avrdude/ChangeLog rename to src/avrdude/ChangeLog diff --git a/xs/src/avrdude/ChangeLog-2001 b/src/avrdude/ChangeLog-2001 similarity index 100% rename from xs/src/avrdude/ChangeLog-2001 rename to src/avrdude/ChangeLog-2001 diff --git a/xs/src/avrdude/ChangeLog-2002 b/src/avrdude/ChangeLog-2002 similarity index 100% rename from xs/src/avrdude/ChangeLog-2002 rename to src/avrdude/ChangeLog-2002 diff --git a/xs/src/avrdude/ChangeLog-2003 b/src/avrdude/ChangeLog-2003 similarity index 100% rename from xs/src/avrdude/ChangeLog-2003 rename to src/avrdude/ChangeLog-2003 diff --git a/xs/src/avrdude/ChangeLog-2004-2006 b/src/avrdude/ChangeLog-2004-2006 similarity index 100% rename from xs/src/avrdude/ChangeLog-2004-2006 rename to src/avrdude/ChangeLog-2004-2006 diff --git a/xs/src/avrdude/ChangeLog-2007 b/src/avrdude/ChangeLog-2007 similarity index 100% rename from xs/src/avrdude/ChangeLog-2007 rename to src/avrdude/ChangeLog-2007 diff --git a/xs/src/avrdude/ChangeLog-2008 b/src/avrdude/ChangeLog-2008 similarity index 100% rename from xs/src/avrdude/ChangeLog-2008 rename to src/avrdude/ChangeLog-2008 diff --git a/xs/src/avrdude/ChangeLog-2009 b/src/avrdude/ChangeLog-2009 similarity index 100% rename from xs/src/avrdude/ChangeLog-2009 rename to src/avrdude/ChangeLog-2009 diff --git a/xs/src/avrdude/ChangeLog-2010 b/src/avrdude/ChangeLog-2010 similarity index 100% rename from xs/src/avrdude/ChangeLog-2010 rename to src/avrdude/ChangeLog-2010 diff --git a/xs/src/avrdude/ChangeLog-2011 b/src/avrdude/ChangeLog-2011 similarity index 100% rename from xs/src/avrdude/ChangeLog-2011 rename to src/avrdude/ChangeLog-2011 diff --git a/xs/src/avrdude/ChangeLog-2012 b/src/avrdude/ChangeLog-2012 similarity index 100% rename from xs/src/avrdude/ChangeLog-2012 rename to src/avrdude/ChangeLog-2012 diff --git a/xs/src/avrdude/ChangeLog-2013 b/src/avrdude/ChangeLog-2013 similarity index 100% rename from xs/src/avrdude/ChangeLog-2013 rename to src/avrdude/ChangeLog-2013 diff --git a/xs/src/avrdude/ChangeLog-2014 b/src/avrdude/ChangeLog-2014 similarity index 100% rename from xs/src/avrdude/ChangeLog-2014 rename to src/avrdude/ChangeLog-2014 diff --git a/xs/src/avrdude/ChangeLog-2015 b/src/avrdude/ChangeLog-2015 similarity index 100% rename from xs/src/avrdude/ChangeLog-2015 rename to src/avrdude/ChangeLog-2015 diff --git a/xs/src/avrdude/Makefile.am b/src/avrdude/Makefile.am similarity index 100% rename from xs/src/avrdude/Makefile.am rename to src/avrdude/Makefile.am diff --git a/xs/src/avrdude/Makefile.standalone b/src/avrdude/Makefile.standalone similarity index 100% rename from xs/src/avrdude/Makefile.standalone rename to src/avrdude/Makefile.standalone diff --git a/xs/src/avrdude/NEWS b/src/avrdude/NEWS similarity index 100% rename from xs/src/avrdude/NEWS rename to src/avrdude/NEWS diff --git a/xs/src/avrdude/README b/src/avrdude/README similarity index 100% rename from xs/src/avrdude/README rename to src/avrdude/README diff --git a/xs/src/avrdude/ac_cfg.h b/src/avrdude/ac_cfg.h similarity index 100% rename from xs/src/avrdude/ac_cfg.h rename to src/avrdude/ac_cfg.h diff --git a/xs/src/avrdude/ac_cfg.h.in b/src/avrdude/ac_cfg.h.in similarity index 100% rename from xs/src/avrdude/ac_cfg.h.in rename to src/avrdude/ac_cfg.h.in diff --git a/xs/src/avrdude/arduino.c b/src/avrdude/arduino.c similarity index 100% rename from xs/src/avrdude/arduino.c rename to src/avrdude/arduino.c diff --git a/xs/src/avrdude/arduino.h b/src/avrdude/arduino.h similarity index 100% rename from xs/src/avrdude/arduino.h rename to src/avrdude/arduino.h diff --git a/xs/src/avrdude/atmel-docs/AVR109.pdf b/src/avrdude/atmel-docs/AVR109.pdf similarity index 100% rename from xs/src/avrdude/atmel-docs/AVR109.pdf rename to src/avrdude/atmel-docs/AVR109.pdf diff --git a/xs/src/avrdude/atmel-docs/AVR910.pdf b/src/avrdude/atmel-docs/AVR910.pdf similarity index 100% rename from xs/src/avrdude/atmel-docs/AVR910.pdf rename to src/avrdude/atmel-docs/AVR910.pdf diff --git a/xs/src/avrdude/atmel-docs/AVRISPmkII-AVR069.pdf b/src/avrdude/atmel-docs/AVRISPmkII-AVR069.pdf similarity index 100% rename from xs/src/avrdude/atmel-docs/AVRISPmkII-AVR069.pdf rename to src/avrdude/atmel-docs/AVRISPmkII-AVR069.pdf diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/browserDetect.js b/src/avrdude/atmel-docs/EDBG/common/browserDetect.js similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/browserDetect.js rename to src/avrdude/atmel-docs/EDBG/common/browserDetect.js diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/css/960.css b/src/avrdude/atmel-docs/EDBG/common/css/960.css similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/css/960.css rename to src/avrdude/atmel-docs/EDBG/common/css/960.css diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/css/docbook.css b/src/avrdude/atmel-docs/EDBG/common/css/docbook.css similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/css/docbook.css rename to src/avrdude/atmel-docs/EDBG/common/css/docbook.css diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/css/fluid_grid.css b/src/avrdude/atmel-docs/EDBG/common/css/fluid_grid.css similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/css/fluid_grid.css rename to src/avrdude/atmel-docs/EDBG/common/css/fluid_grid.css diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/css/index.css b/src/avrdude/atmel-docs/EDBG/common/css/index.css similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/css/index.css rename to src/avrdude/atmel-docs/EDBG/common/css/index.css diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/css/positioning.css b/src/avrdude/atmel-docs/EDBG/common/css/positioning.css similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/css/positioning.css rename to src/avrdude/atmel-docs/EDBG/common/css/positioning.css diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/css/print.css b/src/avrdude/atmel-docs/EDBG/common/css/print.css similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/css/print.css rename to src/avrdude/atmel-docs/EDBG/common/css/print.css diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/css/reset.css b/src/avrdude/atmel-docs/EDBG/common/css/reset.css similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/css/reset.css rename to src/avrdude/atmel-docs/EDBG/common/css/reset.css diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/css/text.css b/src/avrdude/atmel-docs/EDBG/common/css/text.css similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/css/text.css rename to src/avrdude/atmel-docs/EDBG/common/css/text.css diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/fonts/DroidSansMono.eot b/src/avrdude/atmel-docs/EDBG/common/fonts/DroidSansMono.eot similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/fonts/DroidSansMono.eot rename to src/avrdude/atmel-docs/EDBG/common/fonts/DroidSansMono.eot diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/fonts/DroidSansMono.ttf b/src/avrdude/atmel-docs/EDBG/common/fonts/DroidSansMono.ttf similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/fonts/DroidSansMono.ttf rename to src/avrdude/atmel-docs/EDBG/common/fonts/DroidSansMono.ttf diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/images/Book_Closed.png b/src/avrdude/atmel-docs/EDBG/common/images/Book_Closed.png similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/images/Book_Closed.png rename to src/avrdude/atmel-docs/EDBG/common/images/Book_Closed.png diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/images/Book_Open.png b/src/avrdude/atmel-docs/EDBG/common/images/Book_Open.png similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/images/Book_Open.png rename to src/avrdude/atmel-docs/EDBG/common/images/Book_Open.png diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/images/Document_Text.png b/src/avrdude/atmel-docs/EDBG/common/images/Document_Text.png similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/images/Document_Text.png rename to src/avrdude/atmel-docs/EDBG/common/images/Document_Text.png diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/images/Library.png b/src/avrdude/atmel-docs/EDBG/common/images/Library.png similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/images/Library.png rename to src/avrdude/atmel-docs/EDBG/common/images/Library.png diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/images/external_link.gif b/src/avrdude/atmel-docs/EDBG/common/images/external_link.gif similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/images/external_link.gif rename to src/avrdude/atmel-docs/EDBG/common/images/external_link.gif diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/images/loading.gif b/src/avrdude/atmel-docs/EDBG/common/images/loading.gif similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/images/loading.gif rename to src/avrdude/atmel-docs/EDBG/common/images/loading.gif diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/images/logo.png b/src/avrdude/atmel-docs/EDBG/common/images/logo.png similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/images/logo.png rename to src/avrdude/atmel-docs/EDBG/common/images/logo.png diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/images/minus.png b/src/avrdude/atmel-docs/EDBG/common/images/minus.png similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/images/minus.png rename to src/avrdude/atmel-docs/EDBG/common/images/minus.png diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/images/next-arrow.png b/src/avrdude/atmel-docs/EDBG/common/images/next-arrow.png similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/images/next-arrow.png rename to src/avrdude/atmel-docs/EDBG/common/images/next-arrow.png diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/images/plus.png b/src/avrdude/atmel-docs/EDBG/common/images/plus.png similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/images/plus.png rename to src/avrdude/atmel-docs/EDBG/common/images/plus.png diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/images/previous-arrow.png b/src/avrdude/atmel-docs/EDBG/common/images/previous-arrow.png similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/images/previous-arrow.png rename to src/avrdude/atmel-docs/EDBG/common/images/previous-arrow.png diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/images/search-icon.png b/src/avrdude/atmel-docs/EDBG/common/images/search-icon.png similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/images/search-icon.png rename to src/avrdude/atmel-docs/EDBG/common/images/search-icon.png diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/images/sidebar.png b/src/avrdude/atmel-docs/EDBG/common/images/sidebar.png similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/images/sidebar.png rename to src/avrdude/atmel-docs/EDBG/common/images/sidebar.png diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/images/starsSmall.png b/src/avrdude/atmel-docs/EDBG/common/images/starsSmall.png similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/images/starsSmall.png rename to src/avrdude/atmel-docs/EDBG/common/images/starsSmall.png diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/images/toc-icon.png b/src/avrdude/atmel-docs/EDBG/common/images/toc-icon.png similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/images/toc-icon.png rename to src/avrdude/atmel-docs/EDBG/common/images/toc-icon.png diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/images/ui-icons_217bc0_256x240.png b/src/avrdude/atmel-docs/EDBG/common/images/ui-icons_217bc0_256x240.png similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/images/ui-icons_217bc0_256x240.png rename to src/avrdude/atmel-docs/EDBG/common/images/ui-icons_217bc0_256x240.png diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/jquery/jquery-1.7.2.min.js b/src/avrdude/atmel-docs/EDBG/common/jquery/jquery-1.7.2.min.js similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/jquery/jquery-1.7.2.min.js rename to src/avrdude/atmel-docs/EDBG/common/jquery/jquery-1.7.2.min.js diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/jquery/jquery.cookie.js b/src/avrdude/atmel-docs/EDBG/common/jquery/jquery.cookie.js similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/jquery/jquery.cookie.js rename to src/avrdude/atmel-docs/EDBG/common/jquery/jquery.cookie.js diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/jquery/jquery.ui.all.js b/src/avrdude/atmel-docs/EDBG/common/jquery/jquery.ui.all.js similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/jquery/jquery.ui.all.js rename to src/avrdude/atmel-docs/EDBG/common/jquery/jquery.ui.all.js diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/jquery/layout/jquery.layout.js b/src/avrdude/atmel-docs/EDBG/common/jquery/layout/jquery.layout.js similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/jquery/layout/jquery.layout.js rename to src/avrdude/atmel-docs/EDBG/common/jquery/layout/jquery.layout.js diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-anim_basic_16x16.gif b/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-anim_basic_16x16.gif similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-anim_basic_16x16.gif rename to src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-anim_basic_16x16.gif diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-bg_flat_0_aaaaaa_40x100.png b/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-bg_flat_0_aaaaaa_40x100.png similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-bg_flat_0_aaaaaa_40x100.png rename to src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-bg_flat_0_aaaaaa_40x100.png diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-bg_flat_55_fbec88_40x100.png b/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-bg_flat_55_fbec88_40x100.png similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-bg_flat_55_fbec88_40x100.png rename to src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-bg_flat_55_fbec88_40x100.png diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-bg_glass_75_d0e5f5_1x400.png b/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-bg_glass_75_d0e5f5_1x400.png similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-bg_glass_75_d0e5f5_1x400.png rename to src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-bg_glass_75_d0e5f5_1x400.png diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-bg_glass_85_dfeffc_1x400.png b/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-bg_glass_85_dfeffc_1x400.png similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-bg_glass_85_dfeffc_1x400.png rename to src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-bg_glass_85_dfeffc_1x400.png diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-bg_glass_95_fef1ec_1x400.png b/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-bg_glass_95_fef1ec_1x400.png similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-bg_glass_95_fef1ec_1x400.png rename to src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-bg_glass_95_fef1ec_1x400.png diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png b/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png rename to src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-bg_inset-hard_100_f5f8f9_1x100.png b/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-bg_inset-hard_100_f5f8f9_1x100.png similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-bg_inset-hard_100_f5f8f9_1x100.png rename to src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-bg_inset-hard_100_f5f8f9_1x100.png diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-bg_inset-hard_100_fcfdfd_1x100.png b/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-bg_inset-hard_100_fcfdfd_1x100.png similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-bg_inset-hard_100_fcfdfd_1x100.png rename to src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-bg_inset-hard_100_fcfdfd_1x100.png diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-icons_217bc0_256x240.png b/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-icons_217bc0_256x240.png similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-icons_217bc0_256x240.png rename to src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-icons_217bc0_256x240.png diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-icons_2e83ff_256x240.png b/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-icons_2e83ff_256x240.png similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-icons_2e83ff_256x240.png rename to src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-icons_2e83ff_256x240.png diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-icons_469bdd_256x240.png b/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-icons_469bdd_256x240.png similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-icons_469bdd_256x240.png rename to src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-icons_469bdd_256x240.png diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-icons_6da8d5_256x240.png b/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-icons_6da8d5_256x240.png similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-icons_6da8d5_256x240.png rename to src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-icons_6da8d5_256x240.png diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-icons_cd0a0a_256x240.png b/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-icons_cd0a0a_256x240.png similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-icons_cd0a0a_256x240.png rename to src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-icons_cd0a0a_256x240.png diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-icons_d8e7f3_256x240.png b/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-icons_d8e7f3_256x240.png similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-icons_d8e7f3_256x240.png rename to src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-icons_d8e7f3_256x240.png diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-icons_f9bd01_256x240.png b/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-icons_f9bd01_256x240.png similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-icons_f9bd01_256x240.png rename to src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/images/ui-icons_f9bd01_256x240.png diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/jquery-ui-1.8.2.custom.css b/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/jquery-ui-1.8.2.custom.css similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/jquery-ui-1.8.2.custom.css rename to src/avrdude/atmel-docs/EDBG/common/jquery/theme-redmond/jquery-ui-1.8.2.custom.css diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/file.gif b/src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/file.gif similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/file.gif rename to src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/file.gif diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/folder-closed.gif b/src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/folder-closed.gif similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/folder-closed.gif rename to src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/folder-closed.gif diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/folder.gif b/src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/folder.gif similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/folder.gif rename to src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/folder.gif diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/treeview-black-line.gif b/src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/treeview-black-line.gif similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/treeview-black-line.gif rename to src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/treeview-black-line.gif diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/treeview-black.gif b/src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/treeview-black.gif similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/treeview-black.gif rename to src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/treeview-black.gif diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/treeview-default-line.gif b/src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/treeview-default-line.gif similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/treeview-default-line.gif rename to src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/treeview-default-line.gif diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/treeview-default.gif b/src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/treeview-default.gif similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/treeview-default.gif rename to src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/treeview-default.gif diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/treeview-famfamfam-line.gif b/src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/treeview-famfamfam-line.gif similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/treeview-famfamfam-line.gif rename to src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/treeview-famfamfam-line.gif diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/treeview-famfamfam.gif b/src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/treeview-famfamfam.gif similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/treeview-famfamfam.gif rename to src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/treeview-famfamfam.gif diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/treeview-gray-line.gif b/src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/treeview-gray-line.gif similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/treeview-gray-line.gif rename to src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/treeview-gray-line.gif diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/treeview-gray.gif b/src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/treeview-gray.gif similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/treeview-gray.gif rename to src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/treeview-gray.gif diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/treeview-red-line.gif b/src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/treeview-red-line.gif similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/treeview-red-line.gif rename to src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/treeview-red-line.gif diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/treeview-red.gif b/src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/treeview-red.gif similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/treeview-red.gif rename to src/avrdude/atmel-docs/EDBG/common/jquery/treeview/images/treeview-red.gif diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/jquery/treeview/jquery.treeview.css b/src/avrdude/atmel-docs/EDBG/common/jquery/treeview/jquery.treeview.css similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/jquery/treeview/jquery.treeview.css rename to src/avrdude/atmel-docs/EDBG/common/jquery/treeview/jquery.treeview.css diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/jquery/treeview/jquery.treeview.min.js b/src/avrdude/atmel-docs/EDBG/common/jquery/treeview/jquery.treeview.min.js similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/jquery/treeview/jquery.treeview.min.js rename to src/avrdude/atmel-docs/EDBG/common/jquery/treeview/jquery.treeview.min.js diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/main.js b/src/avrdude/atmel-docs/EDBG/common/main.js similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/main.js rename to src/avrdude/atmel-docs/EDBG/common/main.js diff --git a/xs/src/avrdude/atmel-docs/EDBG/common/splitterInit.js b/src/avrdude/atmel-docs/EDBG/common/splitterInit.js similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/common/splitterInit.js rename to src/avrdude/atmel-docs/EDBG/common/splitterInit.js diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch01s01.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch01s01.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch01s01.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch01s01.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch01s02.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch01s02.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch01s02.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch01s02.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s01.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s01.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s01.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s01.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s02.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s02.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s02.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s02.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s02s01.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s02s01.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s02s01.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s02s01.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s02s02.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s02s02.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s02s02.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s02s02.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s02s02s01.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s02s02s01.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s02s02s01.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s02s02s01.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s02s02s02.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s02s02s02.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s02s02s02.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s02s02s02.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s02s03.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s02s03.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s02s03.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s02s03.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s02s03s01.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s02s03s01.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s02s03s01.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s02s03s01.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s02s03s02.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s02s03s02.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s02s03s02.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s02s03s02.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s02s03s03.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s02s03s03.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s02s03s03.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s02s03s03.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s02s03s04.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s02s03s04.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s02s03s04.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s02s03s04.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s03s01.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s03s01.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s03s01.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s03s01.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s03s02.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s03s02.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s03s02.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s03s02.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s03s03.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s03s03.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s03s03.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s03s03.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s03s04.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s03s04.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s03s04.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s03s04.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s03s05.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s03s05.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s03s05.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s03s05.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s03s06.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s03s06.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s03s06.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s03s06.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s03s07.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s03s07.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s03s07.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s03s07.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s03s08.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s03s08.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s03s08.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s03s08.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s03s09.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s03s09.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s03s09.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s03s09.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s04.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s04.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s04.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s04.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s04s01.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s04s01.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s04s01.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s04s01.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s04s02.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s04s02.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s04s02.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s04s02.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s04s03.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s04s03.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s04s03.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch02s04s03.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch03s01.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch03s01.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch03s01.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch03s01.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch03s01s01.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch03s01s01.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch03s01s01.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch03s01s01.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch03s01s02.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch03s01s02.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch03s01s02.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch03s01s02.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch03s01s03.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch03s01s03.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch03s01s03.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch03s01s03.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch03s01s03s01.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch03s01s03s01.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch03s01s03s01.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch03s01s03s01.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch03s02.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch03s02.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch03s02.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch03s02.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch03s02s01.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch03s02s01.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch03s02s01.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch03s02s01.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch03s02s02.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch03s02s02.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch03s02s02.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch03s02s02.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch03s02s03.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch03s02s03.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch03s02s03.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch03s02s03.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch03s02s04.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch03s02s04.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch03s02s04.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch03s02s04.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s01.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s01.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s01.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s01.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s02.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s02.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s02.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s02.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s03.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s03.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s03.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s03.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s04.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s04.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s04.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s04.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s04s01.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s04s01.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s04s01.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s04s01.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s04s03.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s04s03.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s04s03.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s04s03.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s04s04.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s04s04.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s04s04.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s04s04.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s04s05.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s04s05.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s04s05.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s04s05.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s01.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s01.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s01.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s01.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s03.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s03.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s03.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s03.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s04.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s04.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s04.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s04.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s06.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s06.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s06.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s06.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s06s02.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s06s02.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s06s02.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s06s02.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s06s03.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s06s03.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s06s03.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s06s03.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s06s04.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s06s04.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s06s04.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s06s04.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s06s05.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s06s05.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s06s05.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s06s05.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s07.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s07.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s07.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s07.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s07s01.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s07s01.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s07s01.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s07s01.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s07s02.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s07s02.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s07s02.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s07s02.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s07s03.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s07s03.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s07s03.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s07s03.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s07s04.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s07s04.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s07s04.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s07s04.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s08.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s08.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s08.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s08.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s08s01.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s08s01.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s08s01.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s08s01.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s08s02.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s08s02.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s08s02.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s08s02.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s08s03.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s08s03.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s08s03.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s08s03.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s09.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s09.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s09.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s09.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s10.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s10.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s10.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch04s05s10.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s01.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s01.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s01.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s01.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s02.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s02.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s02.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s02.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s03.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s03.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s03.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s03.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s04.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s04.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s04.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s04.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s05.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s05.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s05.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s05.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s06.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s06.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s06.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s06.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s07.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s07.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s07.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s07.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s08.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s08.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s08.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s08.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s09.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s09.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s09.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s09.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s10.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s10.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s10.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s10.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s11.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s11.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s11.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s11.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s12.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s12.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s12.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s12.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s13.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s13.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s13.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s13.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s14.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s14.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s14.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s14.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s15.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s15.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s15.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s01s15.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s02.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s02.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s02.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s02.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s02s01.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s02s01.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s02s01.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s02s01.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s02s02.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s02s02.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s02s02.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s02s02.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s02s03.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s02s03.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s02s03.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s02s03.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s02s04.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s02s04.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s02s04.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s02s04.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s02s05.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s02s05.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s02s05.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s02s05.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s02s06.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s02s06.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s02s06.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s02s06.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s03.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s03.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s03.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s03.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s03s01.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s03s01.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s03s01.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s03s01.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s03s02.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s03s02.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s03s02.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s03s02.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s03s03.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s03s03.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s03s03.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s03s03.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s04.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s04.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s04.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch05s04.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s01.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s01.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s01.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s01.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s02.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s02.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s02.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s02.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s03.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s03.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s03.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s03.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s04.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s04.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s04.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s04.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s05.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s05.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s05.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s05.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s06.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s06.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s06.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s06.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s07.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s07.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s07.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s07.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s08.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s08.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s08.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s08.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s09.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s09.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s09.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s09.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s10.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s10.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s10.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s10.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s11.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s11.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s11.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s11.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s12.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s12.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s12.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s12.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s13.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s13.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s13.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s13.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s14.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s14.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s14.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s14.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s15.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s15.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s15.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s15.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s16.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s16.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s16.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s16.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s17.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s17.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s17.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s17.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s18.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s18.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s18.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s18.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s19.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s19.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s19.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s19.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s20.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s20.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s20.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s20.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s21.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s21.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s21.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s21.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s22.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s22.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s22.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s22.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s23.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s23.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s23.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s23.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s24.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s24.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s24.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s24.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s25.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s25.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s25.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s25.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s26.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s26.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s26.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s26.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s27.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s27.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s27.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s27.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s28.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s28.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s28.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s28.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s29.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s29.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s29.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s01s29.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s02.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s02.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s02.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s02.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s02s01.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s02s01.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s02s01.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s02s01.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s02s02.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s02s02.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s02s02.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s02s02.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s02s03.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s02s03.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s02s03.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s02s03.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s02s04.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s02s04.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s02s04.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s02s04.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s02s05.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s02s05.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s02s05.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s02s05.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s03.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s03.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s03.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s03.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s03s01.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s03s01.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s03s01.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s03s01.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s03s02.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s03s02.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s03s02.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s03s02.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s04s01.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s04s01.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s04s01.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s04s01.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s04s02.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s04s02.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s04s02.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s04s02.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s04s03.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s04s03.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s04s03.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s04s03.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s05.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s05.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s05.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s05.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s05s01.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s05s01.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s05s01.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s05s01.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s05s02.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s05s02.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s05s02.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s05s02.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s05s03.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s05s03.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s05s03.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s05s03.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s05s04.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s05s04.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s05s04.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s05s04.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s05s05.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s05s05.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s05s05.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s05s05.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s06.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s06.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s06.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch06s06.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s01.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s01.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s01.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s01.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s02.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s02.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s02.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s02.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s03.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s03.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s03.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s03.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s04.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s04.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s04.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s04.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s05.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s05.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s05.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s05.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s06.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s06.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s06.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s06.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s07.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s07.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s07.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s07.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s08.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s08.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s08.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s08.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s09.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s09.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s09.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s09.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s10.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s10.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s10.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s10.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s11.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s11.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s11.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s11.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s12.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s12.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s12.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s12.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s13.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s13.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s13.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s13.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s14.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s14.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s14.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s14.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s15.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s15.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s15.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s15.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s16.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s16.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s16.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s16.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s17.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s17.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s17.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s01s17.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s02.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s02.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s02.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s02.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s03.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s03.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s03.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch07s03.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch08s01.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch08s01.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch08s01.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch08s01.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch08s01s01.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch08s01s01.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch08s01s01.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch08s01s01.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch08s01s02.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch08s01s02.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch08s01s02.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch08s01s02.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch08s01s03.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch08s01s03.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch08s01s03.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch08s01s03.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch08s01s04.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch08s01s04.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch08s01s04.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch08s01s04.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch08s01s05.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch08s01s05.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch08s01s05.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch08s01s05.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch08s01s06.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch08s01s06.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch08s01s06.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch08s01s06.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch08s02.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch08s02.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch08s02.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch08s02.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch08s03.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/ch08s03.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch08s03.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/ch08s03.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/document.revisions.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/document.revisions.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/document.revisions.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/document.revisions.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/index.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/index.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/index.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/index.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/pr01.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/pr01.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/pr01.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/pr01.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/protocoldocs.Introduction.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/protocoldocs.Introduction.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/protocoldocs.Introduction.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/protocoldocs.Introduction.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/protocoldocs.avr32protocol.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/protocoldocs.avr32protocol.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/protocoldocs.avr32protocol.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/protocoldocs.avr32protocol.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/protocoldocs.avr8protocol.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/protocoldocs.avr8protocol.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/protocoldocs.avr8protocol.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/protocoldocs.avr8protocol.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/protocoldocs.avrispprotocol.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/protocoldocs.avrispprotocol.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/protocoldocs.avrispprotocol.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/protocoldocs.avrispprotocol.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/protocoldocs.avrprotocol.Overview.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/protocoldocs.avrprotocol.Overview.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/protocoldocs.avrprotocol.Overview.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/protocoldocs.avrprotocol.Overview.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/protocoldocs.cmsis_dap.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/protocoldocs.cmsis_dap.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/protocoldocs.cmsis_dap.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/protocoldocs.cmsis_dap.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/protocoldocs.edbg_ctrl_protocol.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/protocoldocs.edbg_ctrl_protocol.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/protocoldocs.edbg_ctrl_protocol.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/protocoldocs.edbg_ctrl_protocol.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/protocoldocs.tpiprotocol.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/protocoldocs.tpiprotocol.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/protocoldocs.tpiprotocol.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/protocoldocs.tpiprotocol.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/search/htmlFileInfoList.js b/src/avrdude/atmel-docs/EDBG/protocoldocs/search/htmlFileInfoList.js similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/search/htmlFileInfoList.js rename to src/avrdude/atmel-docs/EDBG/protocoldocs/search/htmlFileInfoList.js diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/search/index-1.js b/src/avrdude/atmel-docs/EDBG/protocoldocs/search/index-1.js similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/search/index-1.js rename to src/avrdude/atmel-docs/EDBG/protocoldocs/search/index-1.js diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/search/index-2.js b/src/avrdude/atmel-docs/EDBG/protocoldocs/search/index-2.js similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/search/index-2.js rename to src/avrdude/atmel-docs/EDBG/protocoldocs/search/index-2.js diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/search/index-3.js b/src/avrdude/atmel-docs/EDBG/protocoldocs/search/index-3.js similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/search/index-3.js rename to src/avrdude/atmel-docs/EDBG/protocoldocs/search/index-3.js diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/search/l10n.js b/src/avrdude/atmel-docs/EDBG/protocoldocs/search/l10n.js similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/search/l10n.js rename to src/avrdude/atmel-docs/EDBG/protocoldocs/search/l10n.js diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/search/nwSearchFnt.js b/src/avrdude/atmel-docs/EDBG/protocoldocs/search/nwSearchFnt.js similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/search/nwSearchFnt.js rename to src/avrdude/atmel-docs/EDBG/protocoldocs/search/nwSearchFnt.js diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/search/stemmers/en_stemmer.js b/src/avrdude/atmel-docs/EDBG/protocoldocs/search/stemmers/en_stemmer.js similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/search/stemmers/en_stemmer.js rename to src/avrdude/atmel-docs/EDBG/protocoldocs/search/stemmers/en_stemmer.js diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/section_avr32_memtypes.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/section_avr32_memtypes.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/section_avr32_memtypes.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/section_avr32_memtypes.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/section_avr32_setget_params.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/section_avr32_setget_params.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/section_avr32_setget_params.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/section_avr32_setget_params.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/section_avr8_memtypes.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/section_avr8_memtypes.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/section_avr8_memtypes.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/section_avr8_memtypes.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/section_avr8_query_contexts.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/section_avr8_query_contexts.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/section_avr8_query_contexts.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/section_avr8_query_contexts.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/section_avr8_setget_params.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/section_avr8_setget_params.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/section_avr8_setget_params.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/section_avr8_setget_params.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/section_edbg_ctrl_setget_params.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/section_edbg_ctrl_setget_params.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/section_edbg_ctrl_setget_params.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/section_edbg_ctrl_setget_params.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/section_edbg_query_contexts.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/section_edbg_query_contexts.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/section_edbg_query_contexts.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/section_edbg_query_contexts.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/section_housekeeping_start_session.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/section_housekeeping_start_session.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/section_housekeeping_start_session.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/section_housekeeping_start_session.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/section_i5v_3yz_rl.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/section_i5v_3yz_rl.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/section_i5v_3yz_rl.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/section_i5v_3yz_rl.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/section_jdx_m11_sl.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/section_jdx_m11_sl.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/section_jdx_m11_sl.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/section_jdx_m11_sl.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/section_qhb_x1c_sl.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/section_qhb_x1c_sl.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/section_qhb_x1c_sl.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/section_qhb_x1c_sl.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/section_serial_trace.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/section_serial_trace.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/section_serial_trace.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/section_serial_trace.html diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/section_t1f_hb1_sl.html b/src/avrdude/atmel-docs/EDBG/protocoldocs/section_t1f_hb1_sl.html similarity index 100% rename from xs/src/avrdude/atmel-docs/EDBG/protocoldocs/section_t1f_hb1_sl.html rename to src/avrdude/atmel-docs/EDBG/protocoldocs/section_t1f_hb1_sl.html diff --git a/xs/src/avrdude/atmel-docs/JTAGICE-AVR060.pdf b/src/avrdude/atmel-docs/JTAGICE-AVR060.pdf similarity index 100% rename from xs/src/avrdude/atmel-docs/JTAGICE-AVR060.pdf rename to src/avrdude/atmel-docs/JTAGICE-AVR060.pdf diff --git a/xs/src/avrdude/atmel-docs/JTAGICEmkII-AVR067.pdf b/src/avrdude/atmel-docs/JTAGICEmkII-AVR067.pdf similarity index 100% rename from xs/src/avrdude/atmel-docs/JTAGICEmkII-AVR067.pdf rename to src/avrdude/atmel-docs/JTAGICEmkII-AVR067.pdf diff --git a/xs/src/avrdude/atmel-docs/STK500-AVR061.pdf b/src/avrdude/atmel-docs/STK500-AVR061.pdf similarity index 100% rename from xs/src/avrdude/atmel-docs/STK500-AVR061.pdf rename to src/avrdude/atmel-docs/STK500-AVR061.pdf diff --git a/xs/src/avrdude/atmel-docs/STK500v2-AVR068.pdf b/src/avrdude/atmel-docs/STK500v2-AVR068.pdf similarity index 100% rename from xs/src/avrdude/atmel-docs/STK500v2-AVR068.pdf rename to src/avrdude/atmel-docs/STK500v2-AVR068.pdf diff --git a/xs/src/avrdude/avr.c b/src/avrdude/avr.c similarity index 100% rename from xs/src/avrdude/avr.c rename to src/avrdude/avr.c diff --git a/xs/src/avrdude/avr910.c b/src/avrdude/avr910.c similarity index 100% rename from xs/src/avrdude/avr910.c rename to src/avrdude/avr910.c diff --git a/xs/src/avrdude/avr910.h b/src/avrdude/avr910.h similarity index 100% rename from xs/src/avrdude/avr910.h rename to src/avrdude/avr910.h diff --git a/xs/src/avrdude/avrdude-slic3r.cpp b/src/avrdude/avrdude-slic3r.cpp similarity index 100% rename from xs/src/avrdude/avrdude-slic3r.cpp rename to src/avrdude/avrdude-slic3r.cpp diff --git a/xs/src/avrdude/avrdude-slic3r.hpp b/src/avrdude/avrdude-slic3r.hpp similarity index 100% rename from xs/src/avrdude/avrdude-slic3r.hpp rename to src/avrdude/avrdude-slic3r.hpp diff --git a/xs/src/avrdude/avrdude.1 b/src/avrdude/avrdude.1 similarity index 100% rename from xs/src/avrdude/avrdude.1 rename to src/avrdude/avrdude.1 diff --git a/xs/src/avrdude/avrdude.conf b/src/avrdude/avrdude.conf similarity index 100% rename from xs/src/avrdude/avrdude.conf rename to src/avrdude/avrdude.conf diff --git a/xs/src/avrdude/avrdude.conf.in b/src/avrdude/avrdude.conf.in similarity index 100% rename from xs/src/avrdude/avrdude.conf.in rename to src/avrdude/avrdude.conf.in diff --git a/xs/src/avrdude/avrdude.conf.tmp b/src/avrdude/avrdude.conf.tmp similarity index 100% rename from xs/src/avrdude/avrdude.conf.tmp rename to src/avrdude/avrdude.conf.tmp diff --git a/xs/src/avrdude/avrdude.h b/src/avrdude/avrdude.h similarity index 100% rename from xs/src/avrdude/avrdude.h rename to src/avrdude/avrdude.h diff --git a/xs/src/avrdude/avrdude.spec.in b/src/avrdude/avrdude.spec.in similarity index 100% rename from xs/src/avrdude/avrdude.spec.in rename to src/avrdude/avrdude.spec.in diff --git a/xs/src/avrdude/avrftdi.c b/src/avrdude/avrftdi.c similarity index 100% rename from xs/src/avrdude/avrftdi.c rename to src/avrdude/avrftdi.c diff --git a/xs/src/avrdude/avrftdi.h b/src/avrdude/avrftdi.h similarity index 100% rename from xs/src/avrdude/avrftdi.h rename to src/avrdude/avrftdi.h diff --git a/xs/src/avrdude/avrftdi_private.h b/src/avrdude/avrftdi_private.h similarity index 100% rename from xs/src/avrdude/avrftdi_private.h rename to src/avrdude/avrftdi_private.h diff --git a/xs/src/avrdude/avrftdi_tpi.c b/src/avrdude/avrftdi_tpi.c similarity index 100% rename from xs/src/avrdude/avrftdi_tpi.c rename to src/avrdude/avrftdi_tpi.c diff --git a/xs/src/avrdude/avrftdi_tpi.h b/src/avrdude/avrftdi_tpi.h similarity index 100% rename from xs/src/avrdude/avrftdi_tpi.h rename to src/avrdude/avrftdi_tpi.h diff --git a/xs/src/avrdude/avrpart.c b/src/avrdude/avrpart.c similarity index 100% rename from xs/src/avrdude/avrpart.c rename to src/avrdude/avrpart.c diff --git a/xs/src/avrdude/bitbang.c b/src/avrdude/bitbang.c similarity index 100% rename from xs/src/avrdude/bitbang.c rename to src/avrdude/bitbang.c diff --git a/xs/src/avrdude/bitbang.h b/src/avrdude/bitbang.h similarity index 100% rename from xs/src/avrdude/bitbang.h rename to src/avrdude/bitbang.h diff --git a/xs/src/avrdude/bootstrap b/src/avrdude/bootstrap old mode 100755 new mode 100644 similarity index 100% rename from xs/src/avrdude/bootstrap rename to src/avrdude/bootstrap diff --git a/xs/src/avrdude/buspirate.c b/src/avrdude/buspirate.c similarity index 100% rename from xs/src/avrdude/buspirate.c rename to src/avrdude/buspirate.c diff --git a/xs/src/avrdude/buspirate.h b/src/avrdude/buspirate.h similarity index 100% rename from xs/src/avrdude/buspirate.h rename to src/avrdude/buspirate.h diff --git a/xs/src/avrdude/butterfly.c b/src/avrdude/butterfly.c similarity index 100% rename from xs/src/avrdude/butterfly.c rename to src/avrdude/butterfly.c diff --git a/xs/src/avrdude/butterfly.h b/src/avrdude/butterfly.h similarity index 100% rename from xs/src/avrdude/butterfly.h rename to src/avrdude/butterfly.h diff --git a/xs/src/avrdude/config.c b/src/avrdude/config.c similarity index 100% rename from xs/src/avrdude/config.c rename to src/avrdude/config.c diff --git a/xs/src/avrdude/config.h b/src/avrdude/config.h similarity index 100% rename from xs/src/avrdude/config.h rename to src/avrdude/config.h diff --git a/xs/src/avrdude/config_gram.c b/src/avrdude/config_gram.c similarity index 100% rename from xs/src/avrdude/config_gram.c rename to src/avrdude/config_gram.c diff --git a/xs/src/avrdude/config_gram.h b/src/avrdude/config_gram.h similarity index 100% rename from xs/src/avrdude/config_gram.h rename to src/avrdude/config_gram.h diff --git a/xs/src/avrdude/config_gram.y b/src/avrdude/config_gram.y similarity index 100% rename from xs/src/avrdude/config_gram.y rename to src/avrdude/config_gram.y diff --git a/xs/src/avrdude/configure.ac b/src/avrdude/configure.ac similarity index 100% rename from xs/src/avrdude/configure.ac rename to src/avrdude/configure.ac diff --git a/xs/src/avrdude/confwin.c b/src/avrdude/confwin.c similarity index 100% rename from xs/src/avrdude/confwin.c rename to src/avrdude/confwin.c diff --git a/xs/src/avrdude/crc16.c b/src/avrdude/crc16.c similarity index 100% rename from xs/src/avrdude/crc16.c rename to src/avrdude/crc16.c diff --git a/xs/src/avrdude/crc16.h b/src/avrdude/crc16.h similarity index 100% rename from xs/src/avrdude/crc16.h rename to src/avrdude/crc16.h diff --git a/xs/src/avrdude/dfu.c b/src/avrdude/dfu.c similarity index 100% rename from xs/src/avrdude/dfu.c rename to src/avrdude/dfu.c diff --git a/xs/src/avrdude/dfu.h b/src/avrdude/dfu.h similarity index 100% rename from xs/src/avrdude/dfu.h rename to src/avrdude/dfu.h diff --git a/xs/src/avrdude/doc/.cvsignore b/src/avrdude/doc/.cvsignore similarity index 100% rename from xs/src/avrdude/doc/.cvsignore rename to src/avrdude/doc/.cvsignore diff --git a/xs/src/avrdude/doc/Makefile.am b/src/avrdude/doc/Makefile.am similarity index 100% rename from xs/src/avrdude/doc/Makefile.am rename to src/avrdude/doc/Makefile.am diff --git a/xs/src/avrdude/doc/TODO b/src/avrdude/doc/TODO similarity index 100% rename from xs/src/avrdude/doc/TODO rename to src/avrdude/doc/TODO diff --git a/xs/src/avrdude/doc/avrdude.texi b/src/avrdude/doc/avrdude.texi similarity index 100% rename from xs/src/avrdude/doc/avrdude.texi rename to src/avrdude/doc/avrdude.texi diff --git a/xs/src/avrdude/doc/parts_comments.txt b/src/avrdude/doc/parts_comments.txt similarity index 100% rename from xs/src/avrdude/doc/parts_comments.txt rename to src/avrdude/doc/parts_comments.txt diff --git a/xs/src/avrdude/fileio.c b/src/avrdude/fileio.c similarity index 100% rename from xs/src/avrdude/fileio.c rename to src/avrdude/fileio.c diff --git a/xs/src/avrdude/flip1.c b/src/avrdude/flip1.c similarity index 100% rename from xs/src/avrdude/flip1.c rename to src/avrdude/flip1.c diff --git a/xs/src/avrdude/flip1.h b/src/avrdude/flip1.h similarity index 100% rename from xs/src/avrdude/flip1.h rename to src/avrdude/flip1.h diff --git a/xs/src/avrdude/flip2.c b/src/avrdude/flip2.c similarity index 100% rename from xs/src/avrdude/flip2.c rename to src/avrdude/flip2.c diff --git a/xs/src/avrdude/flip2.h b/src/avrdude/flip2.h similarity index 100% rename from xs/src/avrdude/flip2.h rename to src/avrdude/flip2.h diff --git a/xs/src/avrdude/freebsd_ppi.h b/src/avrdude/freebsd_ppi.h similarity index 100% rename from xs/src/avrdude/freebsd_ppi.h rename to src/avrdude/freebsd_ppi.h diff --git a/xs/src/avrdude/ft245r.c b/src/avrdude/ft245r.c similarity index 100% rename from xs/src/avrdude/ft245r.c rename to src/avrdude/ft245r.c diff --git a/xs/src/avrdude/ft245r.h b/src/avrdude/ft245r.h similarity index 100% rename from xs/src/avrdude/ft245r.h rename to src/avrdude/ft245r.h diff --git a/xs/src/avrdude/jtag3.c b/src/avrdude/jtag3.c similarity index 100% rename from xs/src/avrdude/jtag3.c rename to src/avrdude/jtag3.c diff --git a/xs/src/avrdude/jtag3.h b/src/avrdude/jtag3.h similarity index 100% rename from xs/src/avrdude/jtag3.h rename to src/avrdude/jtag3.h diff --git a/xs/src/avrdude/jtag3_private.h b/src/avrdude/jtag3_private.h similarity index 100% rename from xs/src/avrdude/jtag3_private.h rename to src/avrdude/jtag3_private.h diff --git a/xs/src/avrdude/jtagmkI.c b/src/avrdude/jtagmkI.c similarity index 100% rename from xs/src/avrdude/jtagmkI.c rename to src/avrdude/jtagmkI.c diff --git a/xs/src/avrdude/jtagmkI.h b/src/avrdude/jtagmkI.h similarity index 100% rename from xs/src/avrdude/jtagmkI.h rename to src/avrdude/jtagmkI.h diff --git a/xs/src/avrdude/jtagmkII.c b/src/avrdude/jtagmkII.c similarity index 100% rename from xs/src/avrdude/jtagmkII.c rename to src/avrdude/jtagmkII.c diff --git a/xs/src/avrdude/jtagmkII.h b/src/avrdude/jtagmkII.h similarity index 100% rename from xs/src/avrdude/jtagmkII.h rename to src/avrdude/jtagmkII.h diff --git a/xs/src/avrdude/jtagmkII_private.h b/src/avrdude/jtagmkII_private.h similarity index 100% rename from xs/src/avrdude/jtagmkII_private.h rename to src/avrdude/jtagmkII_private.h diff --git a/xs/src/avrdude/jtagmkI_private.h b/src/avrdude/jtagmkI_private.h similarity index 100% rename from xs/src/avrdude/jtagmkI_private.h rename to src/avrdude/jtagmkI_private.h diff --git a/xs/src/avrdude/lexer.c b/src/avrdude/lexer.c similarity index 100% rename from xs/src/avrdude/lexer.c rename to src/avrdude/lexer.c diff --git a/xs/src/avrdude/lexer.l b/src/avrdude/lexer.l similarity index 100% rename from xs/src/avrdude/lexer.l rename to src/avrdude/lexer.l diff --git a/xs/src/avrdude/libavrdude.h b/src/avrdude/libavrdude.h similarity index 100% rename from xs/src/avrdude/libavrdude.h rename to src/avrdude/libavrdude.h diff --git a/xs/src/avrdude/linux_ppdev.h b/src/avrdude/linux_ppdev.h similarity index 100% rename from xs/src/avrdude/linux_ppdev.h rename to src/avrdude/linux_ppdev.h diff --git a/xs/src/avrdude/linuxgpio.c b/src/avrdude/linuxgpio.c similarity index 100% rename from xs/src/avrdude/linuxgpio.c rename to src/avrdude/linuxgpio.c diff --git a/xs/src/avrdude/linuxgpio.h b/src/avrdude/linuxgpio.h similarity index 100% rename from xs/src/avrdude/linuxgpio.h rename to src/avrdude/linuxgpio.h diff --git a/xs/src/avrdude/lists.c b/src/avrdude/lists.c similarity index 100% rename from xs/src/avrdude/lists.c rename to src/avrdude/lists.c diff --git a/xs/src/avrdude/main-standalone.c b/src/avrdude/main-standalone.c similarity index 100% rename from xs/src/avrdude/main-standalone.c rename to src/avrdude/main-standalone.c diff --git a/xs/src/avrdude/main.c b/src/avrdude/main.c similarity index 100% rename from xs/src/avrdude/main.c rename to src/avrdude/main.c diff --git a/xs/src/avrdude/my_ddk_hidsdi.h b/src/avrdude/my_ddk_hidsdi.h similarity index 100% rename from xs/src/avrdude/my_ddk_hidsdi.h rename to src/avrdude/my_ddk_hidsdi.h diff --git a/xs/src/avrdude/par.c b/src/avrdude/par.c similarity index 100% rename from xs/src/avrdude/par.c rename to src/avrdude/par.c diff --git a/xs/src/avrdude/par.h b/src/avrdude/par.h similarity index 100% rename from xs/src/avrdude/par.h rename to src/avrdude/par.h diff --git a/xs/src/avrdude/pgm.c b/src/avrdude/pgm.c similarity index 100% rename from xs/src/avrdude/pgm.c rename to src/avrdude/pgm.c diff --git a/xs/src/avrdude/pgm_type.c b/src/avrdude/pgm_type.c similarity index 100% rename from xs/src/avrdude/pgm_type.c rename to src/avrdude/pgm_type.c diff --git a/xs/src/avrdude/pickit2.c b/src/avrdude/pickit2.c similarity index 100% rename from xs/src/avrdude/pickit2.c rename to src/avrdude/pickit2.c diff --git a/xs/src/avrdude/pickit2.h b/src/avrdude/pickit2.h similarity index 100% rename from xs/src/avrdude/pickit2.h rename to src/avrdude/pickit2.h diff --git a/xs/src/avrdude/pindefs.c b/src/avrdude/pindefs.c similarity index 100% rename from xs/src/avrdude/pindefs.c rename to src/avrdude/pindefs.c diff --git a/xs/src/avrdude/ppi.c b/src/avrdude/ppi.c similarity index 100% rename from xs/src/avrdude/ppi.c rename to src/avrdude/ppi.c diff --git a/xs/src/avrdude/ppi.h b/src/avrdude/ppi.h similarity index 100% rename from xs/src/avrdude/ppi.h rename to src/avrdude/ppi.h diff --git a/xs/src/avrdude/ppiwin.c b/src/avrdude/ppiwin.c similarity index 100% rename from xs/src/avrdude/ppiwin.c rename to src/avrdude/ppiwin.c diff --git a/xs/src/avrdude/safemode.c b/src/avrdude/safemode.c similarity index 100% rename from xs/src/avrdude/safemode.c rename to src/avrdude/safemode.c diff --git a/xs/src/avrdude/ser_avrdoper.c b/src/avrdude/ser_avrdoper.c similarity index 100% rename from xs/src/avrdude/ser_avrdoper.c rename to src/avrdude/ser_avrdoper.c diff --git a/xs/src/avrdude/ser_posix.c b/src/avrdude/ser_posix.c similarity index 100% rename from xs/src/avrdude/ser_posix.c rename to src/avrdude/ser_posix.c diff --git a/xs/src/avrdude/ser_win32.c b/src/avrdude/ser_win32.c similarity index 100% rename from xs/src/avrdude/ser_win32.c rename to src/avrdude/ser_win32.c diff --git a/xs/src/avrdude/serbb.h b/src/avrdude/serbb.h similarity index 100% rename from xs/src/avrdude/serbb.h rename to src/avrdude/serbb.h diff --git a/xs/src/avrdude/serbb_posix.c b/src/avrdude/serbb_posix.c similarity index 100% rename from xs/src/avrdude/serbb_posix.c rename to src/avrdude/serbb_posix.c diff --git a/xs/src/avrdude/serbb_win32.c b/src/avrdude/serbb_win32.c similarity index 100% rename from xs/src/avrdude/serbb_win32.c rename to src/avrdude/serbb_win32.c diff --git a/xs/src/avrdude/solaris_ecpp.h b/src/avrdude/solaris_ecpp.h similarity index 100% rename from xs/src/avrdude/solaris_ecpp.h rename to src/avrdude/solaris_ecpp.h diff --git a/xs/src/avrdude/stk500.c b/src/avrdude/stk500.c similarity index 100% rename from xs/src/avrdude/stk500.c rename to src/avrdude/stk500.c diff --git a/xs/src/avrdude/stk500.h b/src/avrdude/stk500.h similarity index 100% rename from xs/src/avrdude/stk500.h rename to src/avrdude/stk500.h diff --git a/xs/src/avrdude/stk500_private.h b/src/avrdude/stk500_private.h similarity index 100% rename from xs/src/avrdude/stk500_private.h rename to src/avrdude/stk500_private.h diff --git a/xs/src/avrdude/stk500generic.c b/src/avrdude/stk500generic.c similarity index 100% rename from xs/src/avrdude/stk500generic.c rename to src/avrdude/stk500generic.c diff --git a/xs/src/avrdude/stk500generic.h b/src/avrdude/stk500generic.h similarity index 100% rename from xs/src/avrdude/stk500generic.h rename to src/avrdude/stk500generic.h diff --git a/xs/src/avrdude/stk500v2.c b/src/avrdude/stk500v2.c similarity index 100% rename from xs/src/avrdude/stk500v2.c rename to src/avrdude/stk500v2.c diff --git a/xs/src/avrdude/stk500v2.h b/src/avrdude/stk500v2.h similarity index 100% rename from xs/src/avrdude/stk500v2.h rename to src/avrdude/stk500v2.h diff --git a/xs/src/avrdude/stk500v2_private.h b/src/avrdude/stk500v2_private.h similarity index 100% rename from xs/src/avrdude/stk500v2_private.h rename to src/avrdude/stk500v2_private.h diff --git a/xs/src/avrdude/term.c b/src/avrdude/term.c similarity index 100% rename from xs/src/avrdude/term.c rename to src/avrdude/term.c diff --git a/xs/src/avrdude/term.h b/src/avrdude/term.h similarity index 100% rename from xs/src/avrdude/term.h rename to src/avrdude/term.h diff --git a/xs/src/avrdude/tools/build-mingw32.sh b/src/avrdude/tools/build-mingw32.sh old mode 100755 new mode 100644 similarity index 100% rename from xs/src/avrdude/tools/build-mingw32.sh rename to src/avrdude/tools/build-mingw32.sh diff --git a/xs/src/avrdude/tools/get-dw-params.xsl b/src/avrdude/tools/get-dw-params.xsl similarity index 100% rename from xs/src/avrdude/tools/get-dw-params.xsl rename to src/avrdude/tools/get-dw-params.xsl diff --git a/xs/src/avrdude/tools/get-hv-params.xsl b/src/avrdude/tools/get-hv-params.xsl similarity index 100% rename from xs/src/avrdude/tools/get-hv-params.xsl rename to src/avrdude/tools/get-hv-params.xsl diff --git a/xs/src/avrdude/tools/get-stk600-cards.xsl b/src/avrdude/tools/get-stk600-cards.xsl similarity index 100% rename from xs/src/avrdude/tools/get-stk600-cards.xsl rename to src/avrdude/tools/get-stk600-cards.xsl diff --git a/xs/src/avrdude/tools/get-stk600-devices.xsl b/src/avrdude/tools/get-stk600-devices.xsl similarity index 100% rename from xs/src/avrdude/tools/get-stk600-devices.xsl rename to src/avrdude/tools/get-stk600-devices.xsl diff --git a/xs/src/avrdude/tpi.h b/src/avrdude/tpi.h similarity index 100% rename from xs/src/avrdude/tpi.h rename to src/avrdude/tpi.h diff --git a/xs/src/avrdude/update.c b/src/avrdude/update.c similarity index 100% rename from xs/src/avrdude/update.c rename to src/avrdude/update.c diff --git a/xs/src/avrdude/usb_hidapi.c b/src/avrdude/usb_hidapi.c similarity index 100% rename from xs/src/avrdude/usb_hidapi.c rename to src/avrdude/usb_hidapi.c diff --git a/xs/src/avrdude/usb_libusb.c b/src/avrdude/usb_libusb.c similarity index 100% rename from xs/src/avrdude/usb_libusb.c rename to src/avrdude/usb_libusb.c diff --git a/xs/src/avrdude/usbasp.c b/src/avrdude/usbasp.c similarity index 100% rename from xs/src/avrdude/usbasp.c rename to src/avrdude/usbasp.c diff --git a/xs/src/avrdude/usbasp.h b/src/avrdude/usbasp.h similarity index 100% rename from xs/src/avrdude/usbasp.h rename to src/avrdude/usbasp.h diff --git a/xs/src/avrdude/usbdevs.h b/src/avrdude/usbdevs.h similarity index 100% rename from xs/src/avrdude/usbdevs.h rename to src/avrdude/usbdevs.h diff --git a/xs/src/avrdude/usbtiny.c b/src/avrdude/usbtiny.c similarity index 100% rename from xs/src/avrdude/usbtiny.c rename to src/avrdude/usbtiny.c diff --git a/xs/src/avrdude/usbtiny.h b/src/avrdude/usbtiny.h similarity index 100% rename from xs/src/avrdude/usbtiny.h rename to src/avrdude/usbtiny.h diff --git a/xs/src/avrdude/windows/.cvsignore b/src/avrdude/windows/.cvsignore similarity index 100% rename from xs/src/avrdude/windows/.cvsignore rename to src/avrdude/windows/.cvsignore diff --git a/xs/src/avrdude/windows/Makefile.am b/src/avrdude/windows/Makefile.am similarity index 100% rename from xs/src/avrdude/windows/Makefile.am rename to src/avrdude/windows/Makefile.am diff --git a/xs/src/avrdude/windows/getopt.c b/src/avrdude/windows/getopt.c similarity index 100% rename from xs/src/avrdude/windows/getopt.c rename to src/avrdude/windows/getopt.c diff --git a/xs/src/avrdude/windows/getopt.h b/src/avrdude/windows/getopt.h similarity index 100% rename from xs/src/avrdude/windows/getopt.h rename to src/avrdude/windows/getopt.h diff --git a/xs/src/avrdude/windows/giveio.c b/src/avrdude/windows/giveio.c similarity index 100% rename from xs/src/avrdude/windows/giveio.c rename to src/avrdude/windows/giveio.c diff --git a/xs/src/avrdude/windows/giveio.sys b/src/avrdude/windows/giveio.sys similarity index 100% rename from xs/src/avrdude/windows/giveio.sys rename to src/avrdude/windows/giveio.sys diff --git a/xs/src/avrdude/windows/install_giveio.bat b/src/avrdude/windows/install_giveio.bat old mode 100755 new mode 100644 similarity index 100% rename from xs/src/avrdude/windows/install_giveio.bat rename to src/avrdude/windows/install_giveio.bat diff --git a/xs/src/avrdude/windows/loaddrv.c b/src/avrdude/windows/loaddrv.c similarity index 100% rename from xs/src/avrdude/windows/loaddrv.c rename to src/avrdude/windows/loaddrv.c diff --git a/xs/src/avrdude/windows/loaddrv.h b/src/avrdude/windows/loaddrv.h similarity index 100% rename from xs/src/avrdude/windows/loaddrv.h rename to src/avrdude/windows/loaddrv.h diff --git a/xs/src/avrdude/windows/remove_giveio.bat b/src/avrdude/windows/remove_giveio.bat old mode 100755 new mode 100644 similarity index 100% rename from xs/src/avrdude/windows/remove_giveio.bat rename to src/avrdude/windows/remove_giveio.bat diff --git a/xs/src/avrdude/windows/status_giveio.bat b/src/avrdude/windows/status_giveio.bat old mode 100755 new mode 100644 similarity index 100% rename from xs/src/avrdude/windows/status_giveio.bat rename to src/avrdude/windows/status_giveio.bat diff --git a/xs/src/avrdude/windows/unistd.cpp b/src/avrdude/windows/unistd.cpp similarity index 100% rename from xs/src/avrdude/windows/unistd.cpp rename to src/avrdude/windows/unistd.cpp diff --git a/xs/src/avrdude/windows/unistd.h b/src/avrdude/windows/unistd.h similarity index 100% rename from xs/src/avrdude/windows/unistd.h rename to src/avrdude/windows/unistd.h diff --git a/xs/src/avrdude/wiring.c b/src/avrdude/wiring.c similarity index 100% rename from xs/src/avrdude/wiring.c rename to src/avrdude/wiring.c diff --git a/xs/src/avrdude/wiring.h b/src/avrdude/wiring.h similarity index 100% rename from xs/src/avrdude/wiring.h rename to src/avrdude/wiring.h diff --git a/src/boost/CMakeLists.txt b/src/boost/CMakeLists.txt new file mode 100644 index 0000000000..2b23ec3b20 --- /dev/null +++ b/src/boost/CMakeLists.txt @@ -0,0 +1,20 @@ +project(nowide) +cmake_minimum_required(VERSION 2.6) + +add_library(nowide STATIC + nowide/args.hpp + nowide/cenv.hpp + nowide/config.hpp + nowide/convert.hpp + nowide/cstdio.hpp + nowide/cstdlib.hpp + nowide/filebuf.hpp + nowide/fstream.hpp + nowide/integration/filesystem.hpp + nowide/iostream.cpp + nowide/iostream.hpp + nowide/stackstring.hpp + nowide/system.hpp + nowide/utf8_codecvt.hpp + nowide/windows.hpp +) diff --git a/xs/src/boost/nowide/args.hpp b/src/boost/nowide/args.hpp similarity index 100% rename from xs/src/boost/nowide/args.hpp rename to src/boost/nowide/args.hpp diff --git a/xs/src/boost/nowide/cenv.hpp b/src/boost/nowide/cenv.hpp similarity index 100% rename from xs/src/boost/nowide/cenv.hpp rename to src/boost/nowide/cenv.hpp diff --git a/xs/src/boost/nowide/config.hpp b/src/boost/nowide/config.hpp similarity index 100% rename from xs/src/boost/nowide/config.hpp rename to src/boost/nowide/config.hpp diff --git a/xs/src/boost/nowide/convert.hpp b/src/boost/nowide/convert.hpp similarity index 100% rename from xs/src/boost/nowide/convert.hpp rename to src/boost/nowide/convert.hpp diff --git a/xs/src/boost/nowide/cstdio.hpp b/src/boost/nowide/cstdio.hpp similarity index 100% rename from xs/src/boost/nowide/cstdio.hpp rename to src/boost/nowide/cstdio.hpp diff --git a/xs/src/boost/nowide/cstdlib.hpp b/src/boost/nowide/cstdlib.hpp similarity index 100% rename from xs/src/boost/nowide/cstdlib.hpp rename to src/boost/nowide/cstdlib.hpp diff --git a/xs/src/boost/nowide/filebuf.hpp b/src/boost/nowide/filebuf.hpp similarity index 100% rename from xs/src/boost/nowide/filebuf.hpp rename to src/boost/nowide/filebuf.hpp diff --git a/xs/src/boost/nowide/fstream.hpp b/src/boost/nowide/fstream.hpp similarity index 100% rename from xs/src/boost/nowide/fstream.hpp rename to src/boost/nowide/fstream.hpp diff --git a/xs/src/boost/nowide/integration/filesystem.hpp b/src/boost/nowide/integration/filesystem.hpp similarity index 100% rename from xs/src/boost/nowide/integration/filesystem.hpp rename to src/boost/nowide/integration/filesystem.hpp diff --git a/xs/src/boost/nowide/iostream.cpp b/src/boost/nowide/iostream.cpp similarity index 100% rename from xs/src/boost/nowide/iostream.cpp rename to src/boost/nowide/iostream.cpp diff --git a/xs/src/boost/nowide/iostream.hpp b/src/boost/nowide/iostream.hpp similarity index 100% rename from xs/src/boost/nowide/iostream.hpp rename to src/boost/nowide/iostream.hpp diff --git a/xs/src/boost/nowide/stackstring.hpp b/src/boost/nowide/stackstring.hpp similarity index 100% rename from xs/src/boost/nowide/stackstring.hpp rename to src/boost/nowide/stackstring.hpp diff --git a/xs/src/boost/nowide/system.hpp b/src/boost/nowide/system.hpp similarity index 100% rename from xs/src/boost/nowide/system.hpp rename to src/boost/nowide/system.hpp diff --git a/xs/src/boost/nowide/utf8_codecvt.hpp b/src/boost/nowide/utf8_codecvt.hpp similarity index 100% rename from xs/src/boost/nowide/utf8_codecvt.hpp rename to src/boost/nowide/utf8_codecvt.hpp diff --git a/xs/src/boost/nowide/windows.hpp b/src/boost/nowide/windows.hpp similarity index 100% rename from xs/src/boost/nowide/windows.hpp rename to src/boost/nowide/windows.hpp diff --git a/src/clipper/CMakeLists.txt b/src/clipper/CMakeLists.txt new file mode 100644 index 0000000000..d6f3861dce --- /dev/null +++ b/src/clipper/CMakeLists.txt @@ -0,0 +1,7 @@ +project(clipper) +cmake_minimum_required(VERSION 2.6) + +add_library(clipper STATIC + clipper.cpp + clipper.hpp +) diff --git a/xs/src/clipper.cpp b/src/clipper/clipper.cpp similarity index 96% rename from xs/src/clipper.cpp rename to src/clipper/clipper.cpp index e865288fb1..228e0c6ef6 100644 --- a/xs/src/clipper.cpp +++ b/src/clipper/clipper.cpp @@ -1,4180 +1,4180 @@ -/******************************************************************************* -* * -* Author : Angus Johnson * -* Version : 6.2.9 * -* Date : 16 February 2015 * -* Website : http://www.angusj.com * -* Copyright : Angus Johnson 2010-2015 * -* * -* License: * -* Use, modification & distribution is subject to Boost Software License Ver 1. * -* http://www.boost.org/LICENSE_1_0.txt * -* * -* Attributions: * -* The code in this library is an extension of Bala Vatti's clipping algorithm: * -* "A generic solution to polygon clipping" * -* Communications of the ACM, Vol 35, Issue 7 (July 1992) pp 56-63. * -* http://portal.acm.org/citation.cfm?id=129906 * -* * -* Computer graphics and geometric modeling: implementation and algorithms * -* By Max K. Agoston * -* Springer; 1 edition (January 4, 2005) * -* http://books.google.com/books?q=vatti+clipping+agoston * -* * -* See also: * -* "Polygon Offsetting by Computing Winding Numbers" * -* Paper no. DETC2005-85513 pp. 565-575 * -* ASME 2005 International Design Engineering Technical Conferences * -* and Computers and Information in Engineering Conference (IDETC/CIE2005) * -* September 24-28, 2005 , Long Beach, California, USA * -* http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf * -* * -*******************************************************************************/ - -/******************************************************************************* -* * -* This is a translation of the Delphi Clipper library and the naming style * -* used has retained a Delphi flavour. * -* * -*******************************************************************************/ - -#include "clipper.hpp" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace ClipperLib { - -static double const pi = 3.141592653589793238; -static double const two_pi = pi *2; -static double const def_arc_tolerance = 0.25; - -enum Direction { dRightToLeft, dLeftToRight }; - -static int const Unassigned = -1; //edge not currently 'owning' a solution -static int const Skip = -2; //edge that would otherwise close a path - -#define HORIZONTAL (-1.0E+40) -#define TOLERANCE (1.0e-20) -#define NEAR_ZERO(val) (((val) > -TOLERANCE) && ((val) < TOLERANCE)) - -// Output polygon. -struct OutRec { - int Idx; - bool IsHole; - bool IsOpen; - //The 'FirstLeft' field points to another OutRec that contains or is the - //'parent' of OutRec. It is 'first left' because the ActiveEdgeList (AEL) is - //parsed left from the current edge (owning OutRec) until the owner OutRec - //is found. This field simplifies sorting the polygons into a tree structure - //which reflects the parent/child relationships of all polygons. - //This field should be renamed Parent, and will be later. - OutRec *FirstLeft; - // Used only by void Clipper::BuildResult2(PolyTree& polytree) - PolyNode *PolyNd; - // Linked list of output points, dynamically allocated. - OutPt *Pts; - OutPt *BottomPt; -}; - -//------------------------------------------------------------------------------ - -inline cInt Round(double val) -{ - return static_cast((val < 0) ? (val - 0.5) : (val + 0.5)); -} - -//------------------------------------------------------------------------------ -// PolyTree methods ... -//------------------------------------------------------------------------------ - -int PolyTree::Total() const -{ - int result = (int)AllNodes.size(); - //with negative offsets, ignore the hidden outer polygon ... - if (result > 0 && Childs.front() != &AllNodes.front()) result--; - return result; -} - -//------------------------------------------------------------------------------ -// PolyNode methods ... -//------------------------------------------------------------------------------ - -void PolyNode::AddChild(PolyNode& child) -{ - unsigned cnt = (unsigned)Childs.size(); - Childs.push_back(&child); - child.Parent = this; - child.Index = cnt; -} -//------------------------------------------------------------------------------ - -// Edge delimits a hole if it has an odd number of parent loops. -bool PolyNode::IsHole() const -{ - bool result = true; - PolyNode* node = Parent; - while (node) - { - result = !result; - node = node->Parent; - } - return result; -} - -//------------------------------------------------------------------------------ -// Miscellaneous global functions -//------------------------------------------------------------------------------ - -double Area(const Path &poly) -{ - int size = (int)poly.size(); - if (size < 3) return 0; - - double a = 0; - for (int i = 0, j = size -1; i < size; ++i) - { - a += ((double)poly[j].X + poly[i].X) * ((double)poly[j].Y - poly[i].Y); - j = i; - } - return -a * 0.5; -} -//------------------------------------------------------------------------------ - -double Area(const OutRec &outRec) -{ - OutPt *op = outRec.Pts; - if (!op) return 0; - double a = 0; - do { - a += (double)(op->Prev->Pt.X + op->Pt.X) * (double)(op->Prev->Pt.Y - op->Pt.Y); - op = op->Next; - } while (op != outRec.Pts); - return a * 0.5; -} -//------------------------------------------------------------------------------ - -bool PointIsVertex(const IntPoint &Pt, OutPt *pp) -{ - OutPt *pp2 = pp; - do - { - if (pp2->Pt == Pt) return true; - pp2 = pp2->Next; - } - while (pp2 != pp); - return false; -} -//------------------------------------------------------------------------------ - -//See "The Point in Polygon Problem for Arbitrary Polygons" by Hormann & Agathos -//http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.88.5498&rep=rep1&type=pdf -int PointInPolygon(const IntPoint &pt, const Path &path) -{ - //returns 0 if false, +1 if true, -1 if pt ON polygon boundary - int result = 0; - size_t cnt = path.size(); - if (cnt < 3) return 0; - IntPoint ip = path[0]; - for(size_t i = 1; i <= cnt; ++i) - { - IntPoint ipNext = (i == cnt ? path[0] : path[i]); - if (ipNext.Y == pt.Y && ((ipNext.X == pt.X) || (ip.Y == pt.Y && ((ipNext.X > pt.X) == (ip.X < pt.X))))) - return -1; - if ((ip.Y < pt.Y) != (ipNext.Y < pt.Y)) - { - if (ip.X >= pt.X) - { - if (ipNext.X > pt.X) result = 1 - result; - else - { - double d = (double)(ip.X - pt.X) * (ipNext.Y - pt.Y) - (double)(ipNext.X - pt.X) * (ip.Y - pt.Y); - if (!d) return -1; - if ((d > 0) == (ipNext.Y > ip.Y)) result = 1 - result; - } - } else - { - if (ipNext.X > pt.X) - { - double d = (double)(ip.X - pt.X) * (ipNext.Y - pt.Y) - (double)(ipNext.X - pt.X) * (ip.Y - pt.Y); - if (!d) return -1; - if ((d > 0) == (ipNext.Y > ip.Y)) result = 1 - result; - } - } - } - ip = ipNext; - } - return result; -} -//------------------------------------------------------------------------------ - -// Called by Poly2ContainsPoly1() -int PointInPolygon (const IntPoint &pt, OutPt *op) -{ - //returns 0 if false, +1 if true, -1 if pt ON polygon boundary - int result = 0; - OutPt* startOp = op; - do - { - if (op->Next->Pt.Y == pt.Y) - { - if ((op->Next->Pt.X == pt.X) || (op->Pt.Y == pt.Y && - ((op->Next->Pt.X > pt.X) == (op->Pt.X < pt.X)))) return -1; - } - if ((op->Pt.Y < pt.Y) != (op->Next->Pt.Y < pt.Y)) - { - if (op->Pt.X >= pt.X) - { - if (op->Next->Pt.X > pt.X) result = 1 - result; - else - { - double d = (double)(op->Pt.X - pt.X) * (op->Next->Pt.Y - pt.Y) - (double)(op->Next->Pt.X - pt.X) * (op->Pt.Y - pt.Y); - if (!d) return -1; - if ((d > 0) == (op->Next->Pt.Y > op->Pt.Y)) result = 1 - result; - } - } else - { - if (op->Next->Pt.X > pt.X) - { - double d = (double)(op->Pt.X - pt.X) * (op->Next->Pt.Y - pt.Y) - (double)(op->Next->Pt.X - pt.X) * (op->Pt.Y - pt.Y); - if (!d) return -1; - if ((d > 0) == (op->Next->Pt.Y > op->Pt.Y)) result = 1 - result; - } - } - } - op = op->Next; - } while (startOp != op); - return result; -} -//------------------------------------------------------------------------------ - -// This is potentially very expensive! O(n^2)! -bool Poly2ContainsPoly1(OutPt *OutPt1, OutPt *OutPt2) -{ - PROFILE_FUNC(); - OutPt* op = OutPt1; - do - { - //nb: PointInPolygon returns 0 if false, +1 if true, -1 if pt on polygon - int res = PointInPolygon(op->Pt, OutPt2); - if (res >= 0) return res > 0; - op = op->Next; - } - while (op != OutPt1); - return true; -} -//---------------------------------------------------------------------- - -inline bool SlopesEqual(const cInt dx1, const cInt dy1, const cInt dx2, const cInt dy2, bool UseFullInt64Range) { - return (UseFullInt64Range) ? - // |dx1| < 2^63, |dx2| < 2^63 etc, - Int128::sign_determinant_2x2_filtered(dx1, dy1, dx2, dy2) == 0 : -// Int128::sign_determinant_2x2(dx1, dy1, dx2, dy2) == 0 : - // |dx1| < 2^31, |dx2| < 2^31 etc, - // therefore the following computation could be done with 64bit arithmetics. - dy1 * dx2 == dx1 * dy2; -} -inline bool SlopesEqual(const TEdge &e1, const TEdge &e2, bool UseFullInt64Range) - { return SlopesEqual(e1.Delta.X, e1.Delta.Y, e2.Delta.X, e2.Delta.Y, UseFullInt64Range); } -inline bool SlopesEqual(const IntPoint &pt1, const IntPoint &pt2, const IntPoint &pt3, bool UseFullInt64Range) - { return SlopesEqual(pt1.X-pt2.X, pt1.Y-pt2.Y, pt2.X-pt3.X, pt2.Y-pt3.Y, UseFullInt64Range); } -inline bool SlopesEqual(const IntPoint &pt1, const IntPoint &pt2, const IntPoint &pt3, const IntPoint &pt4, bool UseFullInt64Range) - { return SlopesEqual(pt1.X-pt2.X, pt1.Y-pt2.Y, pt3.X-pt4.X, pt3.Y-pt4.Y, UseFullInt64Range); } - -//------------------------------------------------------------------------------ - -inline bool IsHorizontal(TEdge &e) -{ - return e.Delta.Y == 0; -} -//------------------------------------------------------------------------------ - -inline double GetDx(const IntPoint &pt1, const IntPoint &pt2) -{ - return (pt1.Y == pt2.Y) ? - HORIZONTAL : (double)(pt2.X - pt1.X) / (pt2.Y - pt1.Y); -} -//--------------------------------------------------------------------------- - -inline cInt TopX(TEdge &edge, const cInt currentY) -{ - return (currentY == edge.Top.Y) ? - edge.Top.X : - edge.Bot.X + Round(edge.Dx *(currentY - edge.Bot.Y)); -} -//------------------------------------------------------------------------------ - -void IntersectPoint(TEdge &Edge1, TEdge &Edge2, IntPoint &ip) -{ -#ifdef use_xyz - ip.Z = 0; -#endif - - double b1, b2; - if (Edge1.Dx == Edge2.Dx) - { - ip.Y = Edge1.Curr.Y; - ip.X = TopX(Edge1, ip.Y); - return; - } - else if (Edge1.Delta.X == 0) - { - ip.X = Edge1.Bot.X; - if (IsHorizontal(Edge2)) - ip.Y = Edge2.Bot.Y; - else - { - b2 = Edge2.Bot.Y - (Edge2.Bot.X / Edge2.Dx); - ip.Y = Round(ip.X / Edge2.Dx + b2); - } - } - else if (Edge2.Delta.X == 0) - { - ip.X = Edge2.Bot.X; - if (IsHorizontal(Edge1)) - ip.Y = Edge1.Bot.Y; - else - { - b1 = Edge1.Bot.Y - (Edge1.Bot.X / Edge1.Dx); - ip.Y = Round(ip.X / Edge1.Dx + b1); - } - } - else - { - b1 = Edge1.Bot.X - Edge1.Bot.Y * Edge1.Dx; - b2 = Edge2.Bot.X - Edge2.Bot.Y * Edge2.Dx; - double q = (b2-b1) / (Edge1.Dx - Edge2.Dx); - ip.Y = Round(q); - ip.X = (std::fabs(Edge1.Dx) < std::fabs(Edge2.Dx)) ? - Round(Edge1.Dx * q + b1) : - Round(Edge2.Dx * q + b2); - } - - if (ip.Y < Edge1.Top.Y || ip.Y < Edge2.Top.Y) - { - if (Edge1.Top.Y > Edge2.Top.Y) - ip.Y = Edge1.Top.Y; - else - ip.Y = Edge2.Top.Y; - if (std::fabs(Edge1.Dx) < std::fabs(Edge2.Dx)) - ip.X = TopX(Edge1, ip.Y); - else - ip.X = TopX(Edge2, ip.Y); - } - //finally, don't allow 'ip' to be BELOW curr.Y (ie bottom of scanbeam) ... - if (ip.Y > Edge1.Curr.Y) - { - ip.Y = Edge1.Curr.Y; - //use the more vertical edge to derive X ... - if (std::fabs(Edge1.Dx) > std::fabs(Edge2.Dx)) - ip.X = TopX(Edge2, ip.Y); else - ip.X = TopX(Edge1, ip.Y); - } -} -//------------------------------------------------------------------------------ - -// Reverse a linked loop of points representing a closed polygon. -// This has a time complexity of O(n) -void ReversePolyPtLinks(OutPt *pp) -{ - if (!pp) return; - OutPt *pp1 = pp; - do { - OutPt *pp2 = pp1->Next; - pp1->Next = pp1->Prev; - pp1->Prev = pp2; - pp1 = pp2; - } while( pp1 != pp ); -} -//------------------------------------------------------------------------------ - -inline void InitEdge(TEdge* e, TEdge* eNext, TEdge* ePrev, const IntPoint& Pt) -{ - std::memset(e, 0, sizeof(TEdge)); - e->Next = eNext; - e->Prev = ePrev; - e->Curr = Pt; - e->OutIdx = Unassigned; -} -//------------------------------------------------------------------------------ - -void InitEdge2(TEdge& e, PolyType Pt) -{ - if (e.Curr.Y >= e.Next->Curr.Y) - { - e.Bot = e.Curr; - e.Top = e.Next->Curr; - } else - { - e.Top = e.Curr; - e.Bot = e.Next->Curr; - } - - e.Delta.X = (e.Top.X - e.Bot.X); - e.Delta.Y = (e.Top.Y - e.Bot.Y); - - if (e.Delta.Y == 0) e.Dx = HORIZONTAL; - else e.Dx = (double)(e.Delta.X) / e.Delta.Y; - - e.PolyTyp = Pt; -} -//------------------------------------------------------------------------------ - -// Called from ClipperBase::AddPathInternal() to remove collinear and duplicate points. -inline TEdge* RemoveEdge(TEdge* e) -{ - //removes e from double_linked_list (but without removing from memory) - e->Prev->Next = e->Next; - e->Next->Prev = e->Prev; - TEdge* result = e->Next; - e->Prev = 0; //flag as removed (see ClipperBase.Clear) - return result; -} -//------------------------------------------------------------------------------ - -inline void ReverseHorizontal(TEdge &e) -{ - //swap horizontal edges' Top and Bottom x's so they follow the natural - //progression of the bounds - ie so their xbots will align with the - //adjoining lower edge. [Helpful in the ProcessHorizontal() method.] - std::swap(e.Top.X, e.Bot.X); -#ifdef use_xyz - std::swap(e.Top.Z, e.Bot.Z); -#endif -} -//------------------------------------------------------------------------------ - -bool GetOverlapSegment(IntPoint pt1a, IntPoint pt1b, IntPoint pt2a, - IntPoint pt2b, IntPoint &pt1, IntPoint &pt2) -{ - //precondition: segments are Collinear. - if (std::abs(pt1a.X - pt1b.X) > std::abs(pt1a.Y - pt1b.Y)) - { - if (pt1a.X > pt1b.X) std::swap(pt1a, pt1b); - if (pt2a.X > pt2b.X) std::swap(pt2a, pt2b); - if (pt1a.X > pt2a.X) pt1 = pt1a; else pt1 = pt2a; - if (pt1b.X < pt2b.X) pt2 = pt1b; else pt2 = pt2b; - return pt1.X < pt2.X; - } else - { - if (pt1a.Y < pt1b.Y) std::swap(pt1a, pt1b); - if (pt2a.Y < pt2b.Y) std::swap(pt2a, pt2b); - if (pt1a.Y < pt2a.Y) pt1 = pt1a; else pt1 = pt2a; - if (pt1b.Y > pt2b.Y) pt2 = pt1b; else pt2 = pt2b; - return pt1.Y > pt2.Y; - } -} -//------------------------------------------------------------------------------ - -bool FirstIsBottomPt(const OutPt* btmPt1, const OutPt* btmPt2) -{ - OutPt *p = btmPt1->Prev; - while ((p->Pt == btmPt1->Pt) && (p != btmPt1)) p = p->Prev; - double dx1p = std::fabs(GetDx(btmPt1->Pt, p->Pt)); - p = btmPt1->Next; - while ((p->Pt == btmPt1->Pt) && (p != btmPt1)) p = p->Next; - double dx1n = std::fabs(GetDx(btmPt1->Pt, p->Pt)); - - p = btmPt2->Prev; - while ((p->Pt == btmPt2->Pt) && (p != btmPt2)) p = p->Prev; - double dx2p = std::fabs(GetDx(btmPt2->Pt, p->Pt)); - p = btmPt2->Next; - while ((p->Pt == btmPt2->Pt) && (p != btmPt2)) p = p->Next; - double dx2n = std::fabs(GetDx(btmPt2->Pt, p->Pt)); - return (dx1p >= dx2p && dx1p >= dx2n) || (dx1n >= dx2p && dx1n >= dx2n); -} -//------------------------------------------------------------------------------ - -// Called by GetLowermostRec() -OutPt* GetBottomPt(OutPt *pp) -{ - OutPt* dups = 0; - OutPt* p = pp->Next; - while (p != pp) - { - if (p->Pt.Y > pp->Pt.Y) - { - pp = p; - dups = 0; - } - else if (p->Pt.Y == pp->Pt.Y && p->Pt.X <= pp->Pt.X) - { - if (p->Pt.X < pp->Pt.X) - { - dups = 0; - pp = p; - } else - { - if (p->Next != pp && p->Prev != pp) dups = p; - } - } - p = p->Next; - } - if (dups) - { - //there appears to be at least 2 vertices at BottomPt so ... - while (dups != p) - { - if (!FirstIsBottomPt(p, dups)) pp = dups; - dups = dups->Next; - while (dups->Pt != pp->Pt) dups = dups->Next; - } - } - return pp; -} -//------------------------------------------------------------------------------ - -bool Pt2IsBetweenPt1AndPt3(const IntPoint &pt1, - const IntPoint &pt2, const IntPoint &pt3) -{ - if ((pt1 == pt3) || (pt1 == pt2) || (pt3 == pt2)) - return false; - else if (pt1.X != pt3.X) - return (pt2.X > pt1.X) == (pt2.X < pt3.X); - else - return (pt2.Y > pt1.Y) == (pt2.Y < pt3.Y); -} -//------------------------------------------------------------------------------ - -bool HorzSegmentsOverlap(cInt seg1a, cInt seg1b, cInt seg2a, cInt seg2b) -{ - if (seg1a > seg1b) std::swap(seg1a, seg1b); - if (seg2a > seg2b) std::swap(seg2a, seg2b); - return (seg1a < seg2b) && (seg2a < seg1b); -} - -//------------------------------------------------------------------------------ -// ClipperBase class methods ... -//------------------------------------------------------------------------------ - -// Called from ClipperBase::AddPath() to verify the scale of the input polygon coordinates. -inline void RangeTest(const IntPoint& Pt, bool& useFullRange) -{ - if (useFullRange) - { - if (Pt.X > hiRange || Pt.Y > hiRange || -Pt.X > hiRange || -Pt.Y > hiRange) - throw clipperException("Coordinate outside allowed range"); - } - else if (Pt.X > loRange|| Pt.Y > loRange || -Pt.X > loRange || -Pt.Y > loRange) - { - useFullRange = true; - RangeTest(Pt, useFullRange); - } -} -//------------------------------------------------------------------------------ - -// Called from ClipperBase::AddPath() to construct the Local Minima List. -// Find a local minimum edge on the path starting with E. -inline TEdge* FindNextLocMin(TEdge* E) -{ - for (;;) - { - while (E->Bot != E->Prev->Bot || E->Curr == E->Top) E = E->Next; - if (!IsHorizontal(*E) && !IsHorizontal(*E->Prev)) break; - while (IsHorizontal(*E->Prev)) E = E->Prev; - TEdge* E2 = E; - while (IsHorizontal(*E)) E = E->Next; - if (E->Top.Y == E->Prev->Bot.Y) continue; //ie just an intermediate horz. - if (E2->Prev->Bot.X < E->Bot.X) E = E2; - break; - } - return E; -} -//------------------------------------------------------------------------------ - -// Called from ClipperBase::AddPath(). -TEdge* ClipperBase::ProcessBound(TEdge* E, bool NextIsForward) -{ - TEdge *Result = E; - TEdge *Horz = 0; - - if (E->OutIdx == Skip) - { - //if edges still remain in the current bound beyond the skip edge then - //create another LocMin and call ProcessBound once more - if (NextIsForward) - { - while (E->Top.Y == E->Next->Bot.Y) E = E->Next; - //don't include top horizontals when parsing a bound a second time, - //they will be contained in the opposite bound ... - while (E != Result && IsHorizontal(*E)) E = E->Prev; - } - else - { - while (E->Top.Y == E->Prev->Bot.Y) E = E->Prev; - while (E != Result && IsHorizontal(*E)) E = E->Next; - } - - if (E == Result) - { - if (NextIsForward) Result = E->Next; - else Result = E->Prev; - } - else - { - //there are more edges in the bound beyond result starting with E - if (NextIsForward) - E = Result->Next; - else - E = Result->Prev; - LocalMinimum locMin; - locMin.Y = E->Bot.Y; - locMin.LeftBound = 0; - locMin.RightBound = E; - E->WindDelta = 0; - Result = ProcessBound(E, NextIsForward); - m_MinimaList.push_back(locMin); - } - return Result; - } - - TEdge *EStart; - - if (IsHorizontal(*E)) - { - //We need to be careful with open paths because this may not be a - //true local minima (ie E may be following a skip edge). - //Also, consecutive horz. edges may start heading left before going right. - if (NextIsForward) - EStart = E->Prev; - else - EStart = E->Next; - if (IsHorizontal(*EStart)) //ie an adjoining horizontal skip edge - { - if (EStart->Bot.X != E->Bot.X && EStart->Top.X != E->Bot.X) - ReverseHorizontal(*E); - } - else if (EStart->Bot.X != E->Bot.X) - ReverseHorizontal(*E); - } - - EStart = E; - if (NextIsForward) - { - while (Result->Top.Y == Result->Next->Bot.Y && Result->Next->OutIdx != Skip) - Result = Result->Next; - if (IsHorizontal(*Result) && Result->Next->OutIdx != Skip) - { - //nb: at the top of a bound, horizontals are added to the bound - //only when the preceding edge attaches to the horizontal's left vertex - //unless a Skip edge is encountered when that becomes the top divide - Horz = Result; - while (IsHorizontal(*Horz->Prev)) Horz = Horz->Prev; - if (Horz->Prev->Top.X > Result->Next->Top.X) Result = Horz->Prev; - } - while (E != Result) - { - E->NextInLML = E->Next; - if (IsHorizontal(*E) && E != EStart && - E->Bot.X != E->Prev->Top.X) ReverseHorizontal(*E); - E = E->Next; - } - if (IsHorizontal(*E) && E != EStart && E->Bot.X != E->Prev->Top.X) - ReverseHorizontal(*E); - Result = Result->Next; //move to the edge just beyond current bound - } else - { - while (Result->Top.Y == Result->Prev->Bot.Y && Result->Prev->OutIdx != Skip) - Result = Result->Prev; - if (IsHorizontal(*Result) && Result->Prev->OutIdx != Skip) - { - Horz = Result; - while (IsHorizontal(*Horz->Next)) Horz = Horz->Next; - if (Horz->Next->Top.X == Result->Prev->Top.X || - Horz->Next->Top.X > Result->Prev->Top.X) Result = Horz->Next; - } - - while (E != Result) - { - E->NextInLML = E->Prev; - if (IsHorizontal(*E) && E != EStart && E->Bot.X != E->Next->Top.X) - ReverseHorizontal(*E); - E = E->Prev; - } - if (IsHorizontal(*E) && E != EStart && E->Bot.X != E->Next->Top.X) - ReverseHorizontal(*E); - Result = Result->Prev; //move to the edge just beyond current bound - } - - return Result; -} -//------------------------------------------------------------------------------ - -bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed) -{ - PROFILE_FUNC(); - // Remove duplicate end point from a closed input path. - // Remove duplicate points from the end of the input path. - int highI = (int)pg.size() -1; - if (Closed) - while (highI > 0 && (pg[highI] == pg[0])) - --highI; - while (highI > 0 && (pg[highI] == pg[highI -1])) - --highI; - if ((Closed && highI < 2) || (!Closed && highI < 1)) - return false; - - // Allocate a new edge array. - std::vector edges(highI + 1); - // Fill in the edge array. - bool result = AddPathInternal(pg, highI, PolyTyp, Closed, edges.data()); - if (result) - // Success, remember the edge array. - m_edges.emplace_back(std::move(edges)); - return result; -} - -bool ClipperBase::AddPaths(const Paths &ppg, PolyType PolyTyp, bool Closed) -{ - PROFILE_FUNC(); - std::vector num_edges(ppg.size(), 0); - int num_edges_total = 0; - for (size_t i = 0; i < ppg.size(); ++ i) { - const Path &pg = ppg[i]; - // Remove duplicate end point from a closed input path. - // Remove duplicate points from the end of the input path. - int highI = (int)pg.size() -1; - if (Closed) - while (highI > 0 && (pg[highI] == pg[0])) - --highI; - while (highI > 0 && (pg[highI] == pg[highI -1])) - --highI; - if ((Closed && highI < 2) || (!Closed && highI < 1)) - highI = -1; - num_edges[i] = highI + 1; - num_edges_total += highI + 1; - } - if (num_edges_total == 0) - return false; - - // Allocate a new edge array. - std::vector edges(num_edges_total); - // Fill in the edge array. - bool result = false; - TEdge *p_edge = edges.data(); - for (Paths::size_type i = 0; i < ppg.size(); ++i) - if (num_edges[i]) { - bool res = AddPathInternal(ppg[i], num_edges[i] - 1, PolyTyp, Closed, p_edge); - if (res) { - p_edge += num_edges[i]; - result = true; - } - } - if (result) - // At least some edges were generated. Remember the edge array. - m_edges.emplace_back(std::move(edges)); - return result; -} - -bool ClipperBase::AddPathInternal(const Path &pg, int highI, PolyType PolyTyp, bool Closed, TEdge* edges) -{ - PROFILE_FUNC(); -#ifdef use_lines - if (!Closed && PolyTyp == ptClip) - throw clipperException("AddPath: Open paths must be subject."); -#else - if (!Closed) - throw clipperException("AddPath: Open paths have been disabled."); -#endif - - assert(highI >= 0 && highI < pg.size()); - - //1. Basic (first) edge initialization ... - try - { - edges[1].Curr = pg[1]; - RangeTest(pg[0], m_UseFullRange); - RangeTest(pg[highI], m_UseFullRange); - InitEdge(&edges[0], &edges[1], &edges[highI], pg[0]); - InitEdge(&edges[highI], &edges[0], &edges[highI-1], pg[highI]); - for (int i = highI - 1; i >= 1; --i) - { - RangeTest(pg[i], m_UseFullRange); - InitEdge(&edges[i], &edges[i+1], &edges[i-1], pg[i]); - } - } - catch(...) - { - throw; //range test fails - } - TEdge *eStart = &edges[0]; - - //2. Remove duplicate vertices, and (when closed) collinear edges ... - TEdge *E = eStart, *eLoopStop = eStart; - for (;;) - { - //nb: allows matching start and end points when not Closed ... - if (E->Curr == E->Next->Curr && (Closed || E->Next != eStart)) - { - if (E == E->Next) break; - if (E == eStart) eStart = E->Next; - E = RemoveEdge(E); - eLoopStop = E; - continue; - } - if (E->Prev == E->Next) - break; //only two vertices - else if (Closed && - SlopesEqual(E->Prev->Curr, E->Curr, E->Next->Curr, m_UseFullRange) && - (!m_PreserveCollinear || - !Pt2IsBetweenPt1AndPt3(E->Prev->Curr, E->Curr, E->Next->Curr))) - { - //Collinear edges are allowed for open paths but in closed paths - //the default is to merge adjacent collinear edges into a single edge. - //However, if the PreserveCollinear property is enabled, only overlapping - //collinear edges (ie spikes) will be removed from closed paths. - if (E == eStart) eStart = E->Next; - E = RemoveEdge(E); - E = E->Prev; - eLoopStop = E; - continue; - } - E = E->Next; - if ((E == eLoopStop) || (!Closed && E->Next == eStart)) break; - } - - if ((!Closed && (E == E->Next)) || (Closed && (E->Prev == E->Next))) - { - return false; - } - - if (!Closed) - { - m_HasOpenPaths = true; - eStart->Prev->OutIdx = Skip; - } - - //3. Do second stage of edge initialization ... - // IsFlat means all vertices have the same Y coordinate. - bool IsFlat = true; - E = eStart; - do - { - InitEdge2(*E, PolyTyp); - E = E->Next; - if (IsFlat && E->Curr.Y != eStart->Curr.Y) IsFlat = false; - } - while (E != eStart); - - //4. Finally, add edge bounds to LocalMinima list ... - - //Totally flat paths must be handled differently when adding them - //to LocalMinima list to avoid endless loops etc ... - if (IsFlat) - { - if (Closed) - { - return false; - } - E->Prev->OutIdx = Skip; - LocalMinimum locMin; - locMin.Y = E->Bot.Y; - locMin.LeftBound = 0; - locMin.RightBound = E; - locMin.RightBound->Side = esRight; - locMin.RightBound->WindDelta = 0; - for (;;) - { - if (E->Bot.X != E->Prev->Top.X) ReverseHorizontal(*E); - if (E->Next->OutIdx == Skip) break; - E->NextInLML = E->Next; - E = E->Next; - } - m_MinimaList.push_back(locMin); - return true; - } - - bool leftBoundIsForward; - TEdge* EMin = 0; - - //workaround to avoid an endless loop in the while loop below when - //open paths have matching start and end points ... - if (E->Prev->Bot == E->Prev->Top) E = E->Next; - - // Find local minima and store them into a Local Minima List. - // Multiple Local Minima could be created for a single path. - for (;;) - { - E = FindNextLocMin(E); - if (E == EMin) break; - else if (!EMin) EMin = E; - - //E and E.Prev now share a local minima (left aligned if horizontal). - //Compare their slopes to find which starts which bound ... - LocalMinimum locMin; - locMin.Y = E->Bot.Y; - if (E->Dx < E->Prev->Dx) - { - locMin.LeftBound = E->Prev; - locMin.RightBound = E; - leftBoundIsForward = false; //Q.nextInLML = Q.prev - } else - { - locMin.LeftBound = E; - locMin.RightBound = E->Prev; - leftBoundIsForward = true; //Q.nextInLML = Q.next - } - locMin.LeftBound->Side = esLeft; - locMin.RightBound->Side = esRight; - - if (!Closed) locMin.LeftBound->WindDelta = 0; - else if (locMin.LeftBound->Next == locMin.RightBound) - locMin.LeftBound->WindDelta = -1; - else locMin.LeftBound->WindDelta = 1; - locMin.RightBound->WindDelta = -locMin.LeftBound->WindDelta; - - E = ProcessBound(locMin.LeftBound, leftBoundIsForward); - if (E->OutIdx == Skip) E = ProcessBound(E, leftBoundIsForward); - - TEdge* E2 = ProcessBound(locMin.RightBound, !leftBoundIsForward); - if (E2->OutIdx == Skip) E2 = ProcessBound(E2, !leftBoundIsForward); - - if (locMin.LeftBound->OutIdx == Skip) - locMin.LeftBound = 0; - else if (locMin.RightBound->OutIdx == Skip) - locMin.RightBound = 0; - m_MinimaList.push_back(locMin); - if (!leftBoundIsForward) E = E2; - } - return true; -} -//------------------------------------------------------------------------------ - -void ClipperBase::Clear() -{ - PROFILE_FUNC(); - m_MinimaList.clear(); - m_edges.clear(); - m_UseFullRange = false; - m_HasOpenPaths = false; -} -//------------------------------------------------------------------------------ - -// Initialize the Local Minima List: -// Sort the LML entries, initialize the left / right bound edges of each Local Minima. -void ClipperBase::Reset() -{ - PROFILE_FUNC(); - if (m_MinimaList.empty()) return; //ie nothing to process - std::sort(m_MinimaList.begin(), m_MinimaList.end(), [](const LocalMinimum& lm1, const LocalMinimum& lm2){ return lm1.Y < lm2.Y; }); - - //reset all edges ... - for (LocalMinimum &lm : m_MinimaList) { - TEdge* e = lm.LeftBound; - if (e) - { - e->Curr = e->Bot; - e->Side = esLeft; - e->OutIdx = Unassigned; - } - - e = lm.RightBound; - if (e) - { - e->Curr = e->Bot; - e->Side = esRight; - e->OutIdx = Unassigned; - } - } -} -//------------------------------------------------------------------------------ - -// Get bounds of the edges referenced by the Local Minima List. -// Returns (0,0,0,0) for an empty rectangle. -IntRect ClipperBase::GetBounds() -{ - PROFILE_FUNC(); - IntRect result; - auto lm = m_MinimaList.begin(); - if (lm == m_MinimaList.end()) - { - result.left = result.top = result.right = result.bottom = 0; - return result; - } - result.left = lm->LeftBound->Bot.X; - result.top = lm->LeftBound->Bot.Y; - result.right = lm->LeftBound->Bot.X; - result.bottom = lm->LeftBound->Bot.Y; - while (lm != m_MinimaList.end()) - { - result.bottom = std::max(result.bottom, lm->LeftBound->Bot.Y); - TEdge* e = lm->LeftBound; - for (;;) { - TEdge* bottomE = e; - while (e->NextInLML) - { - if (e->Bot.X < result.left) result.left = e->Bot.X; - if (e->Bot.X > result.right) result.right = e->Bot.X; - e = e->NextInLML; - } - result.left = std::min(result.left, e->Bot.X); - result.right = std::max(result.right, e->Bot.X); - result.left = std::min(result.left, e->Top.X); - result.right = std::max(result.right, e->Top.X); - result.top = std::min(result.top, e->Top.Y); - if (bottomE == lm->LeftBound) e = lm->RightBound; - else break; - } - ++lm; - } - return result; -} - -//------------------------------------------------------------------------------ -// TClipper methods ... -//------------------------------------------------------------------------------ - -Clipper::Clipper(int initOptions) : - ClipperBase(), - m_OutPtsFree(nullptr), - m_OutPtsChunkSize(32), - m_OutPtsChunkLast(32), - m_ActiveEdges(nullptr), - m_SortedEdges(nullptr) -{ - m_ReverseOutput = ((initOptions & ioReverseSolution) != 0); - m_StrictSimple = ((initOptions & ioStrictlySimple) != 0); - m_PreserveCollinear = ((initOptions & ioPreserveCollinear) != 0); - m_HasOpenPaths = false; -#ifdef use_xyz - m_ZFill = 0; -#endif -} -//------------------------------------------------------------------------------ - -void Clipper::Reset() -{ - PROFILE_FUNC(); - ClipperBase::Reset(); - m_Scanbeam = std::priority_queue(); - m_Maxima.clear(); - m_ActiveEdges = 0; - m_SortedEdges = 0; - for (auto lm = m_MinimaList.rbegin(); lm != m_MinimaList.rend(); ++lm) - m_Scanbeam.push(lm->Y); -} - -//------------------------------------------------------------------------------ - -bool Clipper::Execute(ClipType clipType, Paths &solution, - PolyFillType subjFillType, PolyFillType clipFillType) -{ - PROFILE_FUNC(); - if (m_HasOpenPaths) - throw clipperException("Error: PolyTree struct is needed for open path clipping."); - solution.resize(0); - m_SubjFillType = subjFillType; - m_ClipFillType = clipFillType; - m_ClipType = clipType; - m_UsingPolyTree = false; - bool succeeded = ExecuteInternal(); - if (succeeded) BuildResult(solution); - DisposeAllOutRecs(); - return succeeded; -} -//------------------------------------------------------------------------------ - -bool Clipper::Execute(ClipType clipType, PolyTree& polytree, - PolyFillType subjFillType, PolyFillType clipFillType) -{ - PROFILE_FUNC(); - m_SubjFillType = subjFillType; - m_ClipFillType = clipFillType; - m_ClipType = clipType; - m_UsingPolyTree = true; - bool succeeded = ExecuteInternal(); - if (succeeded) BuildResult2(polytree); - DisposeAllOutRecs(); - return succeeded; -} -//------------------------------------------------------------------------------ - -bool Clipper::ExecuteInternal() -{ - PROFILE_FUNC(); - bool succeeded = true; - try { - PROFILE_BLOCK(Clipper_ExecuteInternal_Process); - Reset(); - if (m_MinimaList.empty()) return true; - cInt botY = m_Scanbeam.top(); - do { m_Scanbeam.pop(); } while (! m_Scanbeam.empty() && botY == m_Scanbeam.top()); - do { - InsertLocalMinimaIntoAEL(botY); - ProcessHorizontals(); - m_GhostJoins.clear(); - if (m_Scanbeam.empty()) break; - cInt topY = m_Scanbeam.top(); - do { m_Scanbeam.pop(); } while (! m_Scanbeam.empty() && topY == m_Scanbeam.top()); - succeeded = ProcessIntersections(topY); - if (!succeeded) break; - ProcessEdgesAtTopOfScanbeam(topY); - botY = topY; - } while (!m_Scanbeam.empty() || !m_MinimaList.empty()); - } - catch(...) - { - succeeded = false; - } - - if (succeeded) - { - PROFILE_BLOCK(Clipper_ExecuteInternal_Fix); - - //fix orientations ... - //FIXME Vojtech: Does it not invalidate the loop hierarchy maintained as OutRec::FirstLeft pointers? - //FIXME Vojtech: The area is calculated with floats, it may not be numerically stable! - { - PROFILE_BLOCK(Clipper_ExecuteInternal_Fix_orientations); - for (OutRec *outRec : m_PolyOuts) - if (outRec->Pts && !outRec->IsOpen && (outRec->IsHole ^ m_ReverseOutput) == (Area(*outRec) > 0)) - ReversePolyPtLinks(outRec->Pts); - } - - JoinCommonEdges(); - - //unfortunately FixupOutPolygon() must be done after JoinCommonEdges() - { - PROFILE_BLOCK(Clipper_ExecuteInternal_Fix_fixup); - for (OutRec *outRec : m_PolyOuts) - if (outRec->Pts) { - if (outRec->IsOpen) - // Removes duplicate points. - FixupOutPolyline(*outRec); - else - // Removes duplicate points and simplifies consecutive parallel edges by removing the middle vertex. - FixupOutPolygon(*outRec); - } - } - // For each polygon, search for exactly duplicate non-successive points. - // If such a point is found, the loop is split into two pieces. - // Search for the duplicate points is O(n^2)! - // http://www.angusj.com/delphi/clipper/documentation/Docs/Units/ClipperLib/Classes/Clipper/Properties/StrictlySimple.htm - if (m_StrictSimple) DoSimplePolygons(); - } - - m_Joins.clear(); - m_GhostJoins.clear(); - return succeeded; -} -//------------------------------------------------------------------------------ - -OutPt* Clipper::AllocateOutPt() -{ - OutPt *pt; - if (m_OutPtsFree) { - // Recycle some of the already released points. - pt = m_OutPtsFree; - m_OutPtsFree = pt->Next; - } else if (m_OutPtsChunkLast < m_OutPtsChunkSize) { - // Get a point from the last chunk. - pt = m_OutPts.back() + (m_OutPtsChunkLast ++); - } else { - // The last chunk is full. Allocate a new one. - m_OutPts.push_back(new OutPt[m_OutPtsChunkSize]); - m_OutPtsChunkLast = 1; - pt = m_OutPts.back(); - } - return pt; -} - -void Clipper::DisposeAllOutRecs() -{ - for (OutPt *pts : m_OutPts) - delete[] pts; - for (OutRec *rec : m_PolyOuts) - delete rec; - m_OutPts.clear(); - m_OutPtsFree = nullptr; - m_OutPtsChunkLast = m_OutPtsChunkSize; - m_PolyOuts.clear(); -} -//------------------------------------------------------------------------------ - -void Clipper::SetWindingCount(TEdge &edge) const -{ - TEdge *e = edge.PrevInAEL; - //find the edge of the same polytype that immediately preceeds 'edge' in AEL - while (e && ((e->PolyTyp != edge.PolyTyp) || (e->WindDelta == 0))) e = e->PrevInAEL; - if (!e) - { - edge.WindCnt = (edge.WindDelta == 0 ? 1 : edge.WindDelta); - edge.WindCnt2 = 0; - e = m_ActiveEdges; //ie get ready to calc WindCnt2 - } - else if (edge.WindDelta == 0 && m_ClipType != ctUnion) - { - edge.WindCnt = 1; - edge.WindCnt2 = e->WindCnt2; - e = e->NextInAEL; //ie get ready to calc WindCnt2 - } - else if (IsEvenOddFillType(edge)) - { - //EvenOdd filling ... - if (edge.WindDelta == 0) - { - //are we inside a subj polygon ... - bool Inside = true; - TEdge *e2 = e->PrevInAEL; - while (e2) - { - if (e2->PolyTyp == e->PolyTyp && e2->WindDelta != 0) - Inside = !Inside; - e2 = e2->PrevInAEL; - } - edge.WindCnt = (Inside ? 0 : 1); - } - else - { - edge.WindCnt = edge.WindDelta; - } - edge.WindCnt2 = e->WindCnt2; - e = e->NextInAEL; //ie get ready to calc WindCnt2 - } - else - { - //nonZero, Positive or Negative filling ... - if (e->WindCnt * e->WindDelta < 0) - { - //prev edge is 'decreasing' WindCount (WC) toward zero - //so we're outside the previous polygon ... - if (std::abs(e->WindCnt) > 1) - { - //outside prev poly but still inside another. - //when reversing direction of prev poly use the same WC - if (e->WindDelta * edge.WindDelta < 0) edge.WindCnt = e->WindCnt; - //otherwise continue to 'decrease' WC ... - else edge.WindCnt = e->WindCnt + edge.WindDelta; - } - else - //now outside all polys of same polytype so set own WC ... - edge.WindCnt = (edge.WindDelta == 0 ? 1 : edge.WindDelta); - } else - { - //prev edge is 'increasing' WindCount (WC) away from zero - //so we're inside the previous polygon ... - if (edge.WindDelta == 0) - edge.WindCnt = (e->WindCnt < 0 ? e->WindCnt - 1 : e->WindCnt + 1); - //if wind direction is reversing prev then use same WC - else if (e->WindDelta * edge.WindDelta < 0) edge.WindCnt = e->WindCnt; - //otherwise add to WC ... - else edge.WindCnt = e->WindCnt + edge.WindDelta; - } - edge.WindCnt2 = e->WindCnt2; - e = e->NextInAEL; //ie get ready to calc WindCnt2 - } - - //update WindCnt2 ... - if (IsEvenOddAltFillType(edge)) - { - //EvenOdd filling ... - while (e != &edge) - { - if (e->WindDelta != 0) - edge.WindCnt2 = (edge.WindCnt2 == 0 ? 1 : 0); - e = e->NextInAEL; - } - } else - { - //nonZero, Positive or Negative filling ... - while ( e != &edge ) - { - edge.WindCnt2 += e->WindDelta; - e = e->NextInAEL; - } - } -} -//------------------------------------------------------------------------------ - -bool Clipper::IsContributing(const TEdge& edge) const -{ - PolyFillType pft, pft2; - if (edge.PolyTyp == ptSubject) - { - pft = m_SubjFillType; - pft2 = m_ClipFillType; - } else - { - pft = m_ClipFillType; - pft2 = m_SubjFillType; - } - - switch(pft) - { - case pftEvenOdd: - //return false if a subj line has been flagged as inside a subj polygon - if (edge.WindDelta == 0 && edge.WindCnt != 1) return false; - break; - case pftNonZero: - if (std::abs(edge.WindCnt) != 1) return false; - break; - case pftPositive: - if (edge.WindCnt != 1) return false; - break; - default: //pftNegative - if (edge.WindCnt != -1) return false; - } - - switch(m_ClipType) - { - case ctIntersection: - switch(pft2) - { - case pftEvenOdd: - case pftNonZero: - return (edge.WindCnt2 != 0); - case pftPositive: - return (edge.WindCnt2 > 0); - default: - return (edge.WindCnt2 < 0); - } - break; - case ctUnion: - switch(pft2) - { - case pftEvenOdd: - case pftNonZero: - return (edge.WindCnt2 == 0); - case pftPositive: - return (edge.WindCnt2 <= 0); - default: - return (edge.WindCnt2 >= 0); - } - break; - case ctDifference: - if (edge.PolyTyp == ptSubject) - switch(pft2) - { - case pftEvenOdd: - case pftNonZero: - return (edge.WindCnt2 == 0); - case pftPositive: - return (edge.WindCnt2 <= 0); - default: - return (edge.WindCnt2 >= 0); - } - else - switch(pft2) - { - case pftEvenOdd: - case pftNonZero: - return (edge.WindCnt2 != 0); - case pftPositive: - return (edge.WindCnt2 > 0); - default: - return (edge.WindCnt2 < 0); - } - break; - case ctXor: - if (edge.WindDelta == 0) //XOr always contributing unless open - switch(pft2) - { - case pftEvenOdd: - case pftNonZero: - return (edge.WindCnt2 == 0); - case pftPositive: - return (edge.WindCnt2 <= 0); - default: - return (edge.WindCnt2 >= 0); - } - else - return true; - break; - default: - return true; - } -} -//------------------------------------------------------------------------------ - -// Called from Clipper::InsertLocalMinimaIntoAEL() and Clipper::IntersectEdges(). -OutPt* Clipper::AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &Pt) -{ - PROFILE_FUNC(); - OutPt* result; - TEdge *e, *prevE; - if (IsHorizontal(*e2) || ( e1->Dx > e2->Dx )) - { - result = AddOutPt(e1, Pt); - e2->OutIdx = e1->OutIdx; - e1->Side = esLeft; - e2->Side = esRight; - e = e1; - if (e->PrevInAEL == e2) - prevE = e2->PrevInAEL; - else - prevE = e->PrevInAEL; - } else - { - result = AddOutPt(e2, Pt); - e1->OutIdx = e2->OutIdx; - e1->Side = esRight; - e2->Side = esLeft; - e = e2; - if (e->PrevInAEL == e1) - prevE = e1->PrevInAEL; - else - prevE = e->PrevInAEL; - } - - if (prevE && prevE->OutIdx >= 0 && - (TopX(*prevE, Pt.Y) == TopX(*e, Pt.Y)) && - SlopesEqual(*e, *prevE, m_UseFullRange) && - (e->WindDelta != 0) && (prevE->WindDelta != 0)) - { - OutPt* outPt = AddOutPt(prevE, Pt); - m_Joins.emplace_back(Join(result, outPt, e->Top)); - } - return result; -} -//------------------------------------------------------------------------------ - -void Clipper::AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &Pt) -{ - AddOutPt( e1, Pt ); - if (e2->WindDelta == 0) AddOutPt(e2, Pt); - if( e1->OutIdx == e2->OutIdx ) - { - e1->OutIdx = Unassigned; - e2->OutIdx = Unassigned; - } - else if (e1->OutIdx < e2->OutIdx) - AppendPolygon(e1, e2); - else - AppendPolygon(e2, e1); -} -//------------------------------------------------------------------------------ - -void Clipper::AddEdgeToSEL(TEdge *edge) -{ - //SEL pointers in PEdge are reused to build a list of horizontal edges. - //However, we don't need to worry about order with horizontal edge processing. - if( !m_SortedEdges ) - { - m_SortedEdges = edge; - edge->PrevInSEL = 0; - edge->NextInSEL = 0; - } - else - { - edge->NextInSEL = m_SortedEdges; - edge->PrevInSEL = 0; - m_SortedEdges->PrevInSEL = edge; - m_SortedEdges = edge; - } -} -//------------------------------------------------------------------------------ - -void Clipper::CopyAELToSEL() -{ - TEdge* e = m_ActiveEdges; - m_SortedEdges = e; - while ( e ) - { - e->PrevInSEL = e->PrevInAEL; - e->NextInSEL = e->NextInAEL; - e = e->NextInAEL; - } -} - -//------------------------------------------------------------------------------ - -// Called from Clipper::ExecuteInternal() -void Clipper::InsertLocalMinimaIntoAEL(const cInt botY) -{ - PROFILE_FUNC(); - while (!m_MinimaList.empty() && m_MinimaList.back().Y == botY) - { - TEdge* lb = m_MinimaList.back().LeftBound; - TEdge* rb = m_MinimaList.back().RightBound; - m_MinimaList.pop_back(); - - OutPt *Op1 = 0; - if (!lb) - { - //nb: don't insert LB into either AEL or SEL - InsertEdgeIntoAEL(rb, 0); - SetWindingCount(*rb); - if (IsContributing(*rb)) - Op1 = AddOutPt(rb, rb->Bot); - } - else if (!rb) - { - InsertEdgeIntoAEL(lb, 0); - SetWindingCount(*lb); - if (IsContributing(*lb)) - Op1 = AddOutPt(lb, lb->Bot); - m_Scanbeam.push(lb->Top.Y); - } - else - { - InsertEdgeIntoAEL(lb, 0); - InsertEdgeIntoAEL(rb, lb); - SetWindingCount( *lb ); - rb->WindCnt = lb->WindCnt; - rb->WindCnt2 = lb->WindCnt2; - if (IsContributing(*lb)) - Op1 = AddLocalMinPoly(lb, rb, lb->Bot); - m_Scanbeam.push(lb->Top.Y); - } - - if (rb) - { - if(IsHorizontal(*rb)) AddEdgeToSEL(rb); - else m_Scanbeam.push(rb->Top.Y); - } - - if (!lb || !rb) continue; - - //if any output polygons share an edge, they'll need joining later ... - if (Op1 && IsHorizontal(*rb) && - m_GhostJoins.size() > 0 && (rb->WindDelta != 0)) - { - for (Join &jr : m_GhostJoins) - //if the horizontal Rb and a 'ghost' horizontal overlap, then convert - //the 'ghost' join to a real join ready for later ... - if (HorzSegmentsOverlap(jr.OutPt1->Pt.X, jr.OffPt.X, rb->Bot.X, rb->Top.X)) - m_Joins.emplace_back(Join(jr.OutPt1, Op1, jr.OffPt)); - } - - if (lb->OutIdx >= 0 && lb->PrevInAEL && - lb->PrevInAEL->Curr.X == lb->Bot.X && - lb->PrevInAEL->OutIdx >= 0 && - SlopesEqual(*lb->PrevInAEL, *lb, m_UseFullRange) && - (lb->WindDelta != 0) && (lb->PrevInAEL->WindDelta != 0)) - { - OutPt *Op2 = AddOutPt(lb->PrevInAEL, lb->Bot); - m_Joins.emplace_back(Join(Op1, Op2, lb->Top)); - } - - if(lb->NextInAEL != rb) - { - - if (rb->OutIdx >= 0 && rb->PrevInAEL->OutIdx >= 0 && - SlopesEqual(*rb->PrevInAEL, *rb, m_UseFullRange) && - (rb->WindDelta != 0) && (rb->PrevInAEL->WindDelta != 0)) - { - OutPt *Op2 = AddOutPt(rb->PrevInAEL, rb->Bot); - m_Joins.emplace_back(Join(Op1, Op2, rb->Top)); - } - - TEdge* e = lb->NextInAEL; - if (e) - { - while( e != rb ) - { - //nb: For calculating winding counts etc, IntersectEdges() assumes - //that param1 will be to the Right of param2 ABOVE the intersection ... - IntersectEdges(rb , e , lb->Curr); //order important here - e = e->NextInAEL; - } - } - } - - } -} -//------------------------------------------------------------------------------ - -void Clipper::DeleteFromAEL(TEdge *e) -{ - TEdge* AelPrev = e->PrevInAEL; - TEdge* AelNext = e->NextInAEL; - if( !AelPrev && !AelNext && (e != m_ActiveEdges) ) return; //already deleted - if( AelPrev ) AelPrev->NextInAEL = AelNext; - else m_ActiveEdges = AelNext; - if( AelNext ) AelNext->PrevInAEL = AelPrev; - e->NextInAEL = 0; - e->PrevInAEL = 0; -} -//------------------------------------------------------------------------------ - -void Clipper::DeleteFromSEL(TEdge *e) -{ - TEdge* SelPrev = e->PrevInSEL; - TEdge* SelNext = e->NextInSEL; - if( !SelPrev && !SelNext && (e != m_SortedEdges) ) return; //already deleted - if( SelPrev ) SelPrev->NextInSEL = SelNext; - else m_SortedEdges = SelNext; - if( SelNext ) SelNext->PrevInSEL = SelPrev; - e->NextInSEL = 0; - e->PrevInSEL = 0; -} -//------------------------------------------------------------------------------ - -#ifdef use_xyz -void Clipper::SetZ(IntPoint& pt, TEdge& e1, TEdge& e2) -{ - if (pt.Z != 0 || !m_ZFill) return; - else if (pt == e1.Bot) pt.Z = e1.Bot.Z; - else if (pt == e1.Top) pt.Z = e1.Top.Z; - else if (pt == e2.Bot) pt.Z = e2.Bot.Z; - else if (pt == e2.Top) pt.Z = e2.Top.Z; - else (*m_ZFill)(e1.Bot, e1.Top, e2.Bot, e2.Top, pt); -} -//------------------------------------------------------------------------------ -#endif - -void Clipper::IntersectEdges(TEdge *e1, TEdge *e2, IntPoint &Pt) -{ - bool e1Contributing = ( e1->OutIdx >= 0 ); - bool e2Contributing = ( e2->OutIdx >= 0 ); - -#ifdef use_xyz - SetZ(Pt, *e1, *e2); -#endif - -#ifdef use_lines - //if either edge is on an OPEN path ... - if (e1->WindDelta == 0 || e2->WindDelta == 0) - { - //ignore subject-subject open path intersections UNLESS they - //are both open paths, AND they are both 'contributing maximas' ... - if (e1->WindDelta == 0 && e2->WindDelta == 0) return; - - //if intersecting a subj line with a subj poly ... - else if (e1->PolyTyp == e2->PolyTyp && - e1->WindDelta != e2->WindDelta && m_ClipType == ctUnion) - { - if (e1->WindDelta == 0) - { - if (e2Contributing) - { - AddOutPt(e1, Pt); - if (e1Contributing) e1->OutIdx = Unassigned; - } - } - else - { - if (e1Contributing) - { - AddOutPt(e2, Pt); - if (e2Contributing) e2->OutIdx = Unassigned; - } - } - } - else if (e1->PolyTyp != e2->PolyTyp) - { - //toggle subj open path OutIdx on/off when Abs(clip.WndCnt) == 1 ... - if ((e1->WindDelta == 0) && std::abs(e2->WindCnt) == 1 && - (m_ClipType != ctUnion || e2->WindCnt2 == 0)) - { - AddOutPt(e1, Pt); - if (e1Contributing) e1->OutIdx = Unassigned; - } - else if ((e2->WindDelta == 0) && (std::abs(e1->WindCnt) == 1) && - (m_ClipType != ctUnion || e1->WindCnt2 == 0)) - { - AddOutPt(e2, Pt); - if (e2Contributing) e2->OutIdx = Unassigned; - } - } - return; - } -#endif - - //update winding counts... - //assumes that e1 will be to the Right of e2 ABOVE the intersection - if ( e1->PolyTyp == e2->PolyTyp ) - { - if ( IsEvenOddFillType( *e1) ) - { - int oldE1WindCnt = e1->WindCnt; - e1->WindCnt = e2->WindCnt; - e2->WindCnt = oldE1WindCnt; - } else - { - if (e1->WindCnt + e2->WindDelta == 0 ) e1->WindCnt = -e1->WindCnt; - else e1->WindCnt += e2->WindDelta; - if ( e2->WindCnt - e1->WindDelta == 0 ) e2->WindCnt = -e2->WindCnt; - else e2->WindCnt -= e1->WindDelta; - } - } else - { - if (!IsEvenOddFillType(*e2)) e1->WindCnt2 += e2->WindDelta; - else e1->WindCnt2 = ( e1->WindCnt2 == 0 ) ? 1 : 0; - if (!IsEvenOddFillType(*e1)) e2->WindCnt2 -= e1->WindDelta; - else e2->WindCnt2 = ( e2->WindCnt2 == 0 ) ? 1 : 0; - } - - PolyFillType e1FillType, e2FillType, e1FillType2, e2FillType2; - if (e1->PolyTyp == ptSubject) - { - e1FillType = m_SubjFillType; - e1FillType2 = m_ClipFillType; - } else - { - e1FillType = m_ClipFillType; - e1FillType2 = m_SubjFillType; - } - if (e2->PolyTyp == ptSubject) - { - e2FillType = m_SubjFillType; - e2FillType2 = m_ClipFillType; - } else - { - e2FillType = m_ClipFillType; - e2FillType2 = m_SubjFillType; - } - - cInt e1Wc, e2Wc; - switch (e1FillType) - { - case pftPositive: e1Wc = e1->WindCnt; break; - case pftNegative: e1Wc = -e1->WindCnt; break; - default: e1Wc = std::abs(e1->WindCnt); - } - switch(e2FillType) - { - case pftPositive: e2Wc = e2->WindCnt; break; - case pftNegative: e2Wc = -e2->WindCnt; break; - default: e2Wc = std::abs(e2->WindCnt); - } - - if ( e1Contributing && e2Contributing ) - { - if ((e1Wc != 0 && e1Wc != 1) || (e2Wc != 0 && e2Wc != 1) || - (e1->PolyTyp != e2->PolyTyp && m_ClipType != ctXor) ) - { - AddLocalMaxPoly(e1, e2, Pt); - } - else - { - AddOutPt(e1, Pt); - AddOutPt(e2, Pt); - std::swap(e1->Side, e2->Side); - std::swap(e1->OutIdx, e2->OutIdx); - } - } - else if ( e1Contributing ) - { - if (e2Wc == 0 || e2Wc == 1) - { - AddOutPt(e1, Pt); - std::swap(e1->Side, e2->Side); - std::swap(e1->OutIdx, e2->OutIdx); - } - } - else if ( e2Contributing ) - { - if (e1Wc == 0 || e1Wc == 1) - { - AddOutPt(e2, Pt); - std::swap(e1->Side, e2->Side); - std::swap(e1->OutIdx, e2->OutIdx); - } - } - else if ( (e1Wc == 0 || e1Wc == 1) && (e2Wc == 0 || e2Wc == 1)) - { - //neither edge is currently contributing ... - - cInt e1Wc2, e2Wc2; - switch (e1FillType2) - { - case pftPositive: e1Wc2 = e1->WindCnt2; break; - case pftNegative : e1Wc2 = -e1->WindCnt2; break; - default: e1Wc2 = std::abs(e1->WindCnt2); - } - switch (e2FillType2) - { - case pftPositive: e2Wc2 = e2->WindCnt2; break; - case pftNegative: e2Wc2 = -e2->WindCnt2; break; - default: e2Wc2 = std::abs(e2->WindCnt2); - } - - if (e1->PolyTyp != e2->PolyTyp) - { - AddLocalMinPoly(e1, e2, Pt); - } - else if (e1Wc == 1 && e2Wc == 1) - switch( m_ClipType ) { - case ctIntersection: - if (e1Wc2 > 0 && e2Wc2 > 0) - AddLocalMinPoly(e1, e2, Pt); - break; - case ctUnion: - if ( e1Wc2 <= 0 && e2Wc2 <= 0 ) - AddLocalMinPoly(e1, e2, Pt); - break; - case ctDifference: - if (((e1->PolyTyp == ptClip) && (e1Wc2 > 0) && (e2Wc2 > 0)) || - ((e1->PolyTyp == ptSubject) && (e1Wc2 <= 0) && (e2Wc2 <= 0))) - AddLocalMinPoly(e1, e2, Pt); - break; - case ctXor: - AddLocalMinPoly(e1, e2, Pt); - } - else - std::swap(e1->Side, e2->Side); - } -} -//------------------------------------------------------------------------------ - -void Clipper::SetHoleState(TEdge *e, OutRec *outrec) const -{ - bool IsHole = false; - TEdge *e2 = e->PrevInAEL; - while (e2) - { - if (e2->OutIdx >= 0 && e2->WindDelta != 0) - { - IsHole = !IsHole; - if (! outrec->FirstLeft) - outrec->FirstLeft = m_PolyOuts[e2->OutIdx]; - } - e2 = e2->PrevInAEL; - } - if (IsHole) outrec->IsHole = true; -} -//------------------------------------------------------------------------------ - -OutRec* GetLowermostRec(OutRec *outRec1, OutRec *outRec2) -{ - //work out which polygon fragment has the correct hole state ... - if (!outRec1->BottomPt) - outRec1->BottomPt = GetBottomPt(outRec1->Pts); - if (!outRec2->BottomPt) - outRec2->BottomPt = GetBottomPt(outRec2->Pts); - OutPt *OutPt1 = outRec1->BottomPt; - OutPt *OutPt2 = outRec2->BottomPt; - if (OutPt1->Pt.Y > OutPt2->Pt.Y) return outRec1; - else if (OutPt1->Pt.Y < OutPt2->Pt.Y) return outRec2; - else if (OutPt1->Pt.X < OutPt2->Pt.X) return outRec1; - else if (OutPt1->Pt.X > OutPt2->Pt.X) return outRec2; - else if (OutPt1->Next == OutPt1) return outRec2; - else if (OutPt2->Next == OutPt2) return outRec1; - else if (FirstIsBottomPt(OutPt1, OutPt2)) return outRec1; - else return outRec2; -} -//------------------------------------------------------------------------------ - -bool Param1RightOfParam2(OutRec* outRec1, OutRec* outRec2) -{ - do - { - outRec1 = outRec1->FirstLeft; - if (outRec1 == outRec2) return true; - } while (outRec1); - return false; -} -//------------------------------------------------------------------------------ - -OutRec* Clipper::GetOutRec(int Idx) -{ - OutRec* outrec = m_PolyOuts[Idx]; - while (outrec != m_PolyOuts[outrec->Idx]) - outrec = m_PolyOuts[outrec->Idx]; - return outrec; -} -//------------------------------------------------------------------------------ - -void Clipper::AppendPolygon(TEdge *e1, TEdge *e2) const -{ - //get the start and ends of both output polygons ... - OutRec *outRec1 = m_PolyOuts[e1->OutIdx]; - OutRec *outRec2 = m_PolyOuts[e2->OutIdx]; - - OutRec *holeStateRec; - if (Param1RightOfParam2(outRec1, outRec2)) - holeStateRec = outRec2; - else if (Param1RightOfParam2(outRec2, outRec1)) - holeStateRec = outRec1; - else - holeStateRec = GetLowermostRec(outRec1, outRec2); - - //get the start and ends of both output polygons and - //join e2 poly onto e1 poly and delete pointers to e2 ... - - OutPt* p1_lft = outRec1->Pts; - OutPt* p1_rt = p1_lft->Prev; - OutPt* p2_lft = outRec2->Pts; - OutPt* p2_rt = p2_lft->Prev; - - EdgeSide Side; - //join e2 poly onto e1 poly and delete pointers to e2 ... - if( e1->Side == esLeft ) - { - if( e2->Side == esLeft ) - { - //z y x a b c - ReversePolyPtLinks(p2_lft); - p2_lft->Next = p1_lft; - p1_lft->Prev = p2_lft; - p1_rt->Next = p2_rt; - p2_rt->Prev = p1_rt; - outRec1->Pts = p2_rt; - } else - { - //x y z a b c - p2_rt->Next = p1_lft; - p1_lft->Prev = p2_rt; - p2_lft->Prev = p1_rt; - p1_rt->Next = p2_lft; - outRec1->Pts = p2_lft; - } - Side = esLeft; - } else - { - if( e2->Side == esRight ) - { - //a b c z y x - ReversePolyPtLinks(p2_lft); - p1_rt->Next = p2_rt; - p2_rt->Prev = p1_rt; - p2_lft->Next = p1_lft; - p1_lft->Prev = p2_lft; - } else - { - //a b c x y z - p1_rt->Next = p2_lft; - p2_lft->Prev = p1_rt; - p1_lft->Prev = p2_rt; - p2_rt->Next = p1_lft; - } - Side = esRight; - } - - outRec1->BottomPt = 0; - if (holeStateRec == outRec2) - { - if (outRec2->FirstLeft != outRec1) - outRec1->FirstLeft = outRec2->FirstLeft; - outRec1->IsHole = outRec2->IsHole; - } - outRec2->Pts = 0; - outRec2->BottomPt = 0; - outRec2->FirstLeft = outRec1; - - int OKIdx = e1->OutIdx; - int ObsoleteIdx = e2->OutIdx; - - e1->OutIdx = Unassigned; //nb: safe because we only get here via AddLocalMaxPoly - e2->OutIdx = Unassigned; - - TEdge* e = m_ActiveEdges; - while( e ) - { - if( e->OutIdx == ObsoleteIdx ) - { - e->OutIdx = OKIdx; - e->Side = Side; - break; - } - e = e->NextInAEL; - } - - outRec2->Idx = outRec1->Idx; -} -//------------------------------------------------------------------------------ - -OutRec* Clipper::CreateOutRec() -{ - OutRec* result = new OutRec; - result->IsHole = false; - result->IsOpen = false; - result->FirstLeft = 0; - result->Pts = 0; - result->BottomPt = 0; - result->PolyNd = 0; - m_PolyOuts.push_back(result); - result->Idx = (int)m_PolyOuts.size()-1; - return result; -} -//------------------------------------------------------------------------------ - -OutPt* Clipper::AddOutPt(TEdge *e, const IntPoint &pt) -{ - if( e->OutIdx < 0 ) - { - OutRec *outRec = CreateOutRec(); - outRec->IsOpen = (e->WindDelta == 0); - OutPt* newOp = this->AllocateOutPt(); - outRec->Pts = newOp; - newOp->Idx = outRec->Idx; - newOp->Pt = pt; - newOp->Next = newOp; - newOp->Prev = newOp; - if (!outRec->IsOpen) - SetHoleState(e, outRec); - e->OutIdx = outRec->Idx; - return newOp; - } else - { - OutRec *outRec = m_PolyOuts[e->OutIdx]; - //OutRec.Pts is the 'Left-most' point & OutRec.Pts.Prev is the 'Right-most' - OutPt* op = outRec->Pts; - - bool ToFront = (e->Side == esLeft); - if (ToFront && (pt == op->Pt)) return op; - else if (!ToFront && (pt == op->Prev->Pt)) return op->Prev; - - OutPt* newOp = this->AllocateOutPt(); - newOp->Idx = outRec->Idx; - newOp->Pt = pt; - newOp->Next = op; - newOp->Prev = op->Prev; - newOp->Prev->Next = newOp; - op->Prev = newOp; - if (ToFront) outRec->Pts = newOp; - return newOp; - } -} -//------------------------------------------------------------------------------ - -OutPt* Clipper::GetLastOutPt(TEdge *e) -{ - OutRec *outRec = m_PolyOuts[e->OutIdx]; - if (e->Side == esLeft) - return outRec->Pts; - else - return outRec->Pts->Prev; -} -//------------------------------------------------------------------------------ - -void Clipper::ProcessHorizontals() -{ - PROFILE_FUNC(); - TEdge* horzEdge = m_SortedEdges; - while(horzEdge) - { - DeleteFromSEL(horzEdge); - ProcessHorizontal(horzEdge); - horzEdge = m_SortedEdges; - } -} -//------------------------------------------------------------------------------ - -inline bool IsMaxima(TEdge *e, const cInt Y) -{ - return e && e->Top.Y == Y && !e->NextInLML; -} -//------------------------------------------------------------------------------ - -inline bool IsIntermediate(TEdge *e, const cInt Y) -{ - return e->Top.Y == Y && e->NextInLML; -} -//------------------------------------------------------------------------------ - -inline TEdge *GetMaximaPair(TEdge *e) -{ - TEdge* result = 0; - if ((e->Next->Top == e->Top) && !e->Next->NextInLML) - result = e->Next; - else if ((e->Prev->Top == e->Top) && !e->Prev->NextInLML) - result = e->Prev; - - if (result && (result->OutIdx == Skip || - //result is false if both NextInAEL & PrevInAEL are nil & not horizontal ... - (result->NextInAEL == result->PrevInAEL && !IsHorizontal(*result)))) - return 0; - return result; -} -//------------------------------------------------------------------------------ - -void Clipper::SwapPositionsInAEL(TEdge *Edge1, TEdge *Edge2) -{ - //check that one or other edge hasn't already been removed from AEL ... - if (Edge1->NextInAEL == Edge1->PrevInAEL || - Edge2->NextInAEL == Edge2->PrevInAEL) return; - - if( Edge1->NextInAEL == Edge2 ) - { - TEdge* Next = Edge2->NextInAEL; - if( Next ) Next->PrevInAEL = Edge1; - TEdge* Prev = Edge1->PrevInAEL; - if( Prev ) Prev->NextInAEL = Edge2; - Edge2->PrevInAEL = Prev; - Edge2->NextInAEL = Edge1; - Edge1->PrevInAEL = Edge2; - Edge1->NextInAEL = Next; - } - else if( Edge2->NextInAEL == Edge1 ) - { - TEdge* Next = Edge1->NextInAEL; - if( Next ) Next->PrevInAEL = Edge2; - TEdge* Prev = Edge2->PrevInAEL; - if( Prev ) Prev->NextInAEL = Edge1; - Edge1->PrevInAEL = Prev; - Edge1->NextInAEL = Edge2; - Edge2->PrevInAEL = Edge1; - Edge2->NextInAEL = Next; - } - else - { - TEdge* Next = Edge1->NextInAEL; - TEdge* Prev = Edge1->PrevInAEL; - Edge1->NextInAEL = Edge2->NextInAEL; - if( Edge1->NextInAEL ) Edge1->NextInAEL->PrevInAEL = Edge1; - Edge1->PrevInAEL = Edge2->PrevInAEL; - if( Edge1->PrevInAEL ) Edge1->PrevInAEL->NextInAEL = Edge1; - Edge2->NextInAEL = Next; - if( Edge2->NextInAEL ) Edge2->NextInAEL->PrevInAEL = Edge2; - Edge2->PrevInAEL = Prev; - if( Edge2->PrevInAEL ) Edge2->PrevInAEL->NextInAEL = Edge2; - } - - if( !Edge1->PrevInAEL ) m_ActiveEdges = Edge1; - else if( !Edge2->PrevInAEL ) m_ActiveEdges = Edge2; -} -//------------------------------------------------------------------------------ - -void Clipper::SwapPositionsInSEL(TEdge *Edge1, TEdge *Edge2) -{ - if( !( Edge1->NextInSEL ) && !( Edge1->PrevInSEL ) ) return; - if( !( Edge2->NextInSEL ) && !( Edge2->PrevInSEL ) ) return; - - if( Edge1->NextInSEL == Edge2 ) - { - TEdge* Next = Edge2->NextInSEL; - if( Next ) Next->PrevInSEL = Edge1; - TEdge* Prev = Edge1->PrevInSEL; - if( Prev ) Prev->NextInSEL = Edge2; - Edge2->PrevInSEL = Prev; - Edge2->NextInSEL = Edge1; - Edge1->PrevInSEL = Edge2; - Edge1->NextInSEL = Next; - } - else if( Edge2->NextInSEL == Edge1 ) - { - TEdge* Next = Edge1->NextInSEL; - if( Next ) Next->PrevInSEL = Edge2; - TEdge* Prev = Edge2->PrevInSEL; - if( Prev ) Prev->NextInSEL = Edge1; - Edge1->PrevInSEL = Prev; - Edge1->NextInSEL = Edge2; - Edge2->PrevInSEL = Edge1; - Edge2->NextInSEL = Next; - } - else - { - TEdge* Next = Edge1->NextInSEL; - TEdge* Prev = Edge1->PrevInSEL; - Edge1->NextInSEL = Edge2->NextInSEL; - if( Edge1->NextInSEL ) Edge1->NextInSEL->PrevInSEL = Edge1; - Edge1->PrevInSEL = Edge2->PrevInSEL; - if( Edge1->PrevInSEL ) Edge1->PrevInSEL->NextInSEL = Edge1; - Edge2->NextInSEL = Next; - if( Edge2->NextInSEL ) Edge2->NextInSEL->PrevInSEL = Edge2; - Edge2->PrevInSEL = Prev; - if( Edge2->PrevInSEL ) Edge2->PrevInSEL->NextInSEL = Edge2; - } - - if( !Edge1->PrevInSEL ) m_SortedEdges = Edge1; - else if( !Edge2->PrevInSEL ) m_SortedEdges = Edge2; -} -//------------------------------------------------------------------------------ - -inline void GetHorzDirection(TEdge& HorzEdge, Direction& Dir, cInt& Left, cInt& Right) -{ - if (HorzEdge.Bot.X < HorzEdge.Top.X) - { - Left = HorzEdge.Bot.X; - Right = HorzEdge.Top.X; - Dir = dLeftToRight; - } else - { - Left = HorzEdge.Top.X; - Right = HorzEdge.Bot.X; - Dir = dRightToLeft; - } -} -//------------------------------------------------------------------------ - -/******************************************************************************* -* Notes: Horizontal edges (HEs) at scanline intersections (ie at the Top or * -* Bottom of a scanbeam) are processed as if layered. The order in which HEs * -* are processed doesn't matter. HEs intersect with other HE Bot.Xs only [#] * -* (or they could intersect with Top.Xs only, ie EITHER Bot.Xs OR Top.Xs), * -* and with other non-horizontal edges [*]. Once these intersections are * -* processed, intermediate HEs then 'promote' the Edge above (NextInLML) into * -* the AEL. These 'promoted' edges may in turn intersect [%] with other HEs. * -*******************************************************************************/ - -void Clipper::ProcessHorizontal(TEdge *horzEdge) -{ - Direction dir; - cInt horzLeft, horzRight; - bool IsOpen = (horzEdge->OutIdx >= 0 && m_PolyOuts[horzEdge->OutIdx]->IsOpen); - - GetHorzDirection(*horzEdge, dir, horzLeft, horzRight); - - TEdge* eLastHorz = horzEdge, *eMaxPair = 0; - while (eLastHorz->NextInLML && IsHorizontal(*eLastHorz->NextInLML)) - eLastHorz = eLastHorz->NextInLML; - if (!eLastHorz->NextInLML) - eMaxPair = GetMaximaPair(eLastHorz); - - std::vector::const_iterator maxIt; - std::vector::const_reverse_iterator maxRit; - if (!m_Maxima.empty()) - { - //get the first maxima in range (X) ... - if (dir == dLeftToRight) - { - maxIt = m_Maxima.begin(); - while (maxIt != m_Maxima.end() && *maxIt <= horzEdge->Bot.X) ++maxIt; - if (maxIt != m_Maxima.end() && *maxIt >= eLastHorz->Top.X) - maxIt = m_Maxima.end(); - } - else - { - maxRit = m_Maxima.rbegin(); - while (maxRit != m_Maxima.rend() && *maxRit > horzEdge->Bot.X) ++maxRit; - if (maxRit != m_Maxima.rend() && *maxRit <= eLastHorz->Top.X) - maxRit = m_Maxima.rend(); - } - } - - OutPt* op1 = 0; - - for (;;) //loop through consec. horizontal edges - { - - bool IsLastHorz = (horzEdge == eLastHorz); - TEdge* e = (dir == dLeftToRight) ? horzEdge->NextInAEL : horzEdge->PrevInAEL; - while(e) - { - - //this code block inserts extra coords into horizontal edges (in output - //polygons) whereever maxima touch these horizontal edges. This helps - //'simplifying' polygons (ie if the Simplify property is set). - if (!m_Maxima.empty()) - { - if (dir == dLeftToRight) - { - while (maxIt != m_Maxima.end() && *maxIt < e->Curr.X) - { - if (horzEdge->OutIdx >= 0 && !IsOpen) - AddOutPt(horzEdge, IntPoint(*maxIt, horzEdge->Bot.Y)); - ++maxIt; - } - } - else - { - while (maxRit != m_Maxima.rend() && *maxRit > e->Curr.X) - { - if (horzEdge->OutIdx >= 0 && !IsOpen) - AddOutPt(horzEdge, IntPoint(*maxRit, horzEdge->Bot.Y)); - ++maxRit; - } - } - }; - - if ((dir == dLeftToRight && e->Curr.X > horzRight) || - (dir == dRightToLeft && e->Curr.X < horzLeft)) break; - - //Also break if we've got to the end of an intermediate horizontal edge ... - //nb: Smaller Dx's are to the right of larger Dx's ABOVE the horizontal. - if (e->Curr.X == horzEdge->Top.X && horzEdge->NextInLML && - e->Dx < horzEdge->NextInLML->Dx) break; - - if (horzEdge->OutIdx >= 0 && !IsOpen) //note: may be done multiple times - { - op1 = AddOutPt(horzEdge, e->Curr); - TEdge* eNextHorz = m_SortedEdges; - while (eNextHorz) - { - if (eNextHorz->OutIdx >= 0 && - HorzSegmentsOverlap(horzEdge->Bot.X, - horzEdge->Top.X, eNextHorz->Bot.X, eNextHorz->Top.X)) - { - OutPt* op2 = GetLastOutPt(eNextHorz); - m_Joins.emplace_back(Join(op2, op1, eNextHorz->Top)); - } - eNextHorz = eNextHorz->NextInSEL; - } - m_GhostJoins.emplace_back(Join(op1, 0, horzEdge->Bot)); - } - - //OK, so far we're still in range of the horizontal Edge but make sure - //we're at the last of consec. horizontals when matching with eMaxPair - if(e == eMaxPair && IsLastHorz) - { - if (horzEdge->OutIdx >= 0) - AddLocalMaxPoly(horzEdge, eMaxPair, horzEdge->Top); - DeleteFromAEL(horzEdge); - DeleteFromAEL(eMaxPair); - return; - } - - if(dir == dLeftToRight) - { - IntPoint Pt = IntPoint(e->Curr.X, horzEdge->Curr.Y); - IntersectEdges(horzEdge, e, Pt); - } - else - { - IntPoint Pt = IntPoint(e->Curr.X, horzEdge->Curr.Y); - IntersectEdges( e, horzEdge, Pt); - } - TEdge* eNext = (dir == dLeftToRight) ? e->NextInAEL : e->PrevInAEL; - SwapPositionsInAEL( horzEdge, e ); - e = eNext; - } //end while(e) - - //Break out of loop if HorzEdge.NextInLML is not also horizontal ... - if (!horzEdge->NextInLML || !IsHorizontal(*horzEdge->NextInLML)) break; - - UpdateEdgeIntoAEL(horzEdge); - if (horzEdge->OutIdx >= 0) AddOutPt(horzEdge, horzEdge->Bot); - GetHorzDirection(*horzEdge, dir, horzLeft, horzRight); - - } //end for (;;) - - if (horzEdge->OutIdx >= 0 && !op1) - { - op1 = GetLastOutPt(horzEdge); - TEdge* eNextHorz = m_SortedEdges; - while (eNextHorz) - { - if (eNextHorz->OutIdx >= 0 && - HorzSegmentsOverlap(horzEdge->Bot.X, - horzEdge->Top.X, eNextHorz->Bot.X, eNextHorz->Top.X)) - { - OutPt* op2 = GetLastOutPt(eNextHorz); - m_Joins.emplace_back(Join(op2, op1, eNextHorz->Top)); - } - eNextHorz = eNextHorz->NextInSEL; - } - m_GhostJoins.emplace_back(Join(op1, 0, horzEdge->Top)); - } - - if (horzEdge->NextInLML) - { - if(horzEdge->OutIdx >= 0) - { - op1 = AddOutPt( horzEdge, horzEdge->Top); - UpdateEdgeIntoAEL(horzEdge); - if (horzEdge->WindDelta == 0) return; - //nb: HorzEdge is no longer horizontal here - TEdge* ePrev = horzEdge->PrevInAEL; - TEdge* eNext = horzEdge->NextInAEL; - if (ePrev && ePrev->Curr.X == horzEdge->Bot.X && - ePrev->Curr.Y == horzEdge->Bot.Y && ePrev->WindDelta != 0 && - (ePrev->OutIdx >= 0 && ePrev->Curr.Y > ePrev->Top.Y && - SlopesEqual(*horzEdge, *ePrev, m_UseFullRange))) - { - OutPt* op2 = AddOutPt(ePrev, horzEdge->Bot); - m_Joins.emplace_back(Join(op1, op2, horzEdge->Top)); - } - else if (eNext && eNext->Curr.X == horzEdge->Bot.X && - eNext->Curr.Y == horzEdge->Bot.Y && eNext->WindDelta != 0 && - eNext->OutIdx >= 0 && eNext->Curr.Y > eNext->Top.Y && - SlopesEqual(*horzEdge, *eNext, m_UseFullRange)) - { - OutPt* op2 = AddOutPt(eNext, horzEdge->Bot); - m_Joins.emplace_back(Join(op1, op2, horzEdge->Top)); - } - } - else - UpdateEdgeIntoAEL(horzEdge); - } - else - { - if (horzEdge->OutIdx >= 0) AddOutPt(horzEdge, horzEdge->Top); - DeleteFromAEL(horzEdge); - } -} -//------------------------------------------------------------------------------ - -void Clipper::UpdateEdgeIntoAEL(TEdge *&e) -{ - if( !e->NextInLML ) - throw clipperException("UpdateEdgeIntoAEL: invalid call"); - - e->NextInLML->OutIdx = e->OutIdx; - TEdge* AelPrev = e->PrevInAEL; - TEdge* AelNext = e->NextInAEL; - if (AelPrev) AelPrev->NextInAEL = e->NextInLML; - else m_ActiveEdges = e->NextInLML; - if (AelNext) AelNext->PrevInAEL = e->NextInLML; - e->NextInLML->Side = e->Side; - e->NextInLML->WindDelta = e->WindDelta; - e->NextInLML->WindCnt = e->WindCnt; - e->NextInLML->WindCnt2 = e->WindCnt2; - e = e->NextInLML; - e->Curr = e->Bot; - e->PrevInAEL = AelPrev; - e->NextInAEL = AelNext; - if (!IsHorizontal(*e)) - m_Scanbeam.push(e->Top.Y); -} -//------------------------------------------------------------------------------ - -bool Clipper::ProcessIntersections(const cInt topY) -{ - PROFILE_FUNC(); - if( !m_ActiveEdges ) return true; - try { - BuildIntersectList(topY); - size_t IlSize = m_IntersectList.size(); - if (IlSize == 0) return true; - if (IlSize == 1 || FixupIntersectionOrder()) { - for (IntersectNode &iNode : m_IntersectList) { - IntersectEdges( iNode.Edge1, iNode.Edge2, iNode.Pt); - SwapPositionsInAEL( iNode.Edge1 , iNode.Edge2 ); - } - m_IntersectList.clear(); - } - else return false; - } - catch(...) - { - m_SortedEdges = 0; - m_IntersectList.clear(); - throw clipperException("ProcessIntersections error"); - } - m_SortedEdges = 0; - return true; -} -//------------------------------------------------------------------------------ - -void Clipper::BuildIntersectList(const cInt topY) -{ - if ( !m_ActiveEdges ) return; - - //prepare for sorting ... - TEdge* e = m_ActiveEdges; - m_SortedEdges = e; - while( e ) - { - e->PrevInSEL = e->PrevInAEL; - e->NextInSEL = e->NextInAEL; - e->Curr.X = TopX( *e, topY ); - e = e->NextInAEL; - } - - //bubblesort ... - bool isModified; - do - { - isModified = false; - e = m_SortedEdges; - while( e->NextInSEL ) - { - TEdge *eNext = e->NextInSEL; - IntPoint Pt; - if(e->Curr.X > eNext->Curr.X) - { - IntersectPoint(*e, *eNext, Pt); - m_IntersectList.emplace_back(IntersectNode(e, eNext, Pt)); - SwapPositionsInSEL(e, eNext); - isModified = true; - } - else - e = eNext; - } - if( e->PrevInSEL ) e->PrevInSEL->NextInSEL = 0; - else break; - } - while ( isModified ); - m_SortedEdges = 0; //important -} -//------------------------------------------------------------------------------ - - -inline bool EdgesAdjacent(const IntersectNode &inode) -{ - return (inode.Edge1->NextInSEL == inode.Edge2) || - (inode.Edge1->PrevInSEL == inode.Edge2); -} -//------------------------------------------------------------------------------ - -bool Clipper::FixupIntersectionOrder() -{ - //pre-condition: intersections are sorted Bottom-most first. - //Now it's crucial that intersections are made only between adjacent edges, - //so to ensure this the order of intersections may need adjusting ... - CopyAELToSEL(); - std::sort(m_IntersectList.begin(), m_IntersectList.end(), [](const IntersectNode &node1, const IntersectNode &node2) { return node2.Pt.Y < node1.Pt.Y; }); - - size_t cnt = m_IntersectList.size(); - for (size_t i = 0; i < cnt; ++i) - { - if (!EdgesAdjacent(m_IntersectList[i])) - { - size_t j = i + 1; - while (j < cnt && !EdgesAdjacent(m_IntersectList[j])) j++; - if (j == cnt) return false; - std::swap(m_IntersectList[i], m_IntersectList[j]); - } - SwapPositionsInSEL(m_IntersectList[i].Edge1, m_IntersectList[i].Edge2); - } - return true; -} -//------------------------------------------------------------------------------ - -void Clipper::DoMaxima(TEdge *e) -{ - TEdge* eMaxPair = GetMaximaPair(e); - if (!eMaxPair) - { - if (e->OutIdx >= 0) - AddOutPt(e, e->Top); - DeleteFromAEL(e); - return; - } - - TEdge* eNext = e->NextInAEL; - while(eNext && eNext != eMaxPair) - { - IntersectEdges(e, eNext, e->Top); - SwapPositionsInAEL(e, eNext); - eNext = e->NextInAEL; - } - - if(e->OutIdx == Unassigned && eMaxPair->OutIdx == Unassigned) - { - DeleteFromAEL(e); - DeleteFromAEL(eMaxPair); - } - else if( e->OutIdx >= 0 && eMaxPair->OutIdx >= 0 ) - { - if (e->OutIdx >= 0) AddLocalMaxPoly(e, eMaxPair, e->Top); - DeleteFromAEL(e); - DeleteFromAEL(eMaxPair); - } -#ifdef use_lines - else if (e->WindDelta == 0) - { - if (e->OutIdx >= 0) - { - AddOutPt(e, e->Top); - e->OutIdx = Unassigned; - } - DeleteFromAEL(e); - - if (eMaxPair->OutIdx >= 0) - { - AddOutPt(eMaxPair, e->Top); - eMaxPair->OutIdx = Unassigned; - } - DeleteFromAEL(eMaxPair); - } -#endif - else throw clipperException("DoMaxima error"); -} -//------------------------------------------------------------------------------ - -void Clipper::ProcessEdgesAtTopOfScanbeam(const cInt topY) -{ - PROFILE_FUNC(); - TEdge* e = m_ActiveEdges; - while( e ) - { - //1. process maxima, treating them as if they're 'bent' horizontal edges, - // but exclude maxima with horizontal edges. nb: e can't be a horizontal. - bool IsMaximaEdge = IsMaxima(e, topY); - - if(IsMaximaEdge) - { - TEdge* eMaxPair = GetMaximaPair(e); - IsMaximaEdge = (!eMaxPair || !IsHorizontal(*eMaxPair)); - } - - if(IsMaximaEdge) - { - if (m_StrictSimple) m_Maxima.push_back(e->Top.X); - TEdge* ePrev = e->PrevInAEL; - DoMaxima(e); - if( !ePrev ) e = m_ActiveEdges; - else e = ePrev->NextInAEL; - } - else - { - //2. promote horizontal edges, otherwise update Curr.X and Curr.Y ... - if (IsIntermediate(e, topY) && IsHorizontal(*e->NextInLML)) - { - UpdateEdgeIntoAEL(e); - if (e->OutIdx >= 0) - AddOutPt(e, e->Bot); - AddEdgeToSEL(e); - } - else - { - e->Curr.X = TopX( *e, topY ); - e->Curr.Y = topY; - } - - //When StrictlySimple and 'e' is being touched by another edge, then - //make sure both edges have a vertex here ... - if (m_StrictSimple) - { - TEdge* ePrev = e->PrevInAEL; - if ((e->OutIdx >= 0) && (e->WindDelta != 0) && ePrev && (ePrev->OutIdx >= 0) && - (ePrev->Curr.X == e->Curr.X) && (ePrev->WindDelta != 0)) - { - IntPoint pt = e->Curr; -#ifdef use_xyz - SetZ(pt, *ePrev, *e); -#endif - OutPt* op = AddOutPt(ePrev, pt); - OutPt* op2 = AddOutPt(e, pt); - m_Joins.emplace_back(Join(op, op2, pt)); //StrictlySimple (type-3) join - } - } - - e = e->NextInAEL; - } - } - - //3. Process horizontals at the Top of the scanbeam ... - std::sort(m_Maxima.begin(), m_Maxima.end()); - ProcessHorizontals(); - m_Maxima.clear(); - - //4. Promote intermediate vertices ... - e = m_ActiveEdges; - while(e) - { - if(IsIntermediate(e, topY)) - { - OutPt* op = 0; - if( e->OutIdx >= 0 ) - op = AddOutPt(e, e->Top); - UpdateEdgeIntoAEL(e); - - //if output polygons share an edge, they'll need joining later ... - TEdge* ePrev = e->PrevInAEL; - TEdge* eNext = e->NextInAEL; - if (ePrev && ePrev->Curr.X == e->Bot.X && - ePrev->Curr.Y == e->Bot.Y && op && - ePrev->OutIdx >= 0 && ePrev->Curr.Y > ePrev->Top.Y && - SlopesEqual(*e, *ePrev, m_UseFullRange) && - (e->WindDelta != 0) && (ePrev->WindDelta != 0)) - { - OutPt* op2 = AddOutPt(ePrev, e->Bot); - m_Joins.emplace_back(Join(op, op2, e->Top)); - } - else if (eNext && eNext->Curr.X == e->Bot.X && - eNext->Curr.Y == e->Bot.Y && op && - eNext->OutIdx >= 0 && eNext->Curr.Y > eNext->Top.Y && - SlopesEqual(*e, *eNext, m_UseFullRange) && - (e->WindDelta != 0) && (eNext->WindDelta != 0)) - { - OutPt* op2 = AddOutPt(eNext, e->Bot); - m_Joins.emplace_back(Join(op, op2, e->Top)); - } - } - e = e->NextInAEL; - } -} -//------------------------------------------------------------------------------ - -void Clipper::FixupOutPolyline(OutRec &outrec) -{ - OutPt *pp = outrec.Pts; - OutPt *lastPP = pp->Prev; - while (pp != lastPP) - { - pp = pp->Next; - if (pp->Pt == pp->Prev->Pt) - { - if (pp == lastPP) lastPP = pp->Prev; - OutPt *tmpPP = pp->Prev; - tmpPP->Next = pp->Next; - pp->Next->Prev = tmpPP; - this->DisposeOutPt(pp); - pp = tmpPP; - } - } - - if (pp == pp->Prev) - { - this->DisposeOutPts(pp); - outrec.Pts = 0; - return; - } -} -//------------------------------------------------------------------------------ - -void Clipper::FixupOutPolygon(OutRec &outrec) -{ - //FixupOutPolygon() - removes duplicate points and simplifies consecutive - //parallel edges by removing the middle vertex. - OutPt *lastOK = nullptr; - outrec.BottomPt = nullptr; - OutPt *pp = outrec.Pts; - bool preserveCol = m_PreserveCollinear || m_StrictSimple; - - for (;;) - { - if (pp->Prev == pp || pp->Prev == pp->Next) - { - // Empty loop or a stick. Release the polygon. - this->DisposeOutPts(pp); - outrec.Pts = nullptr; - return; - } - - //test for duplicate points and collinear edges ... - if ((pp->Pt == pp->Next->Pt) || (pp->Pt == pp->Prev->Pt) || - (SlopesEqual(pp->Prev->Pt, pp->Pt, pp->Next->Pt, m_UseFullRange) && - (!preserveCol || !Pt2IsBetweenPt1AndPt3(pp->Prev->Pt, pp->Pt, pp->Next->Pt)))) - { - lastOK = nullptr; - OutPt *tmp = pp; - pp->Prev->Next = pp->Next; - pp->Next->Prev = pp->Prev; - pp = pp->Prev; - this->DisposeOutPt(tmp); - } - else if (pp == lastOK) break; - else - { - if (!lastOK) lastOK = pp; - pp = pp->Next; - } - } - outrec.Pts = pp; -} -//------------------------------------------------------------------------------ - -// Count the number of points in a closed linked loop starting with Pts. -int PointCount(OutPt *Pts) -{ - if (!Pts) return 0; - int result = 0; - OutPt* p = Pts; - do - { - result++; - p = p->Next; - } - while (p != Pts); - return result; -} -//------------------------------------------------------------------------------ - -void Clipper::BuildResult(Paths &polys) -{ - polys.reserve(m_PolyOuts.size()); - for (OutRec* outRec : m_PolyOuts) - { - assert(! outRec->IsOpen); - if (!outRec->Pts) continue; - Path pg; - OutPt* p = outRec->Pts->Prev; - int cnt = PointCount(p); - if (cnt < 2) continue; - pg.reserve(cnt); - for (int i = 0; i < cnt; ++i) - { - pg.emplace_back(p->Pt); - p = p->Prev; - } - polys.emplace_back(std::move(pg)); - } -} -//------------------------------------------------------------------------------ - -void Clipper::BuildResult2(PolyTree& polytree) -{ - polytree.Clear(); - polytree.AllNodes.reserve(m_PolyOuts.size()); - //add each output polygon/contour to polytree ... - for (OutRec* outRec : m_PolyOuts) - { - int cnt = PointCount(outRec->Pts); - if ((outRec->IsOpen && cnt < 2) || (!outRec->IsOpen && cnt < 3)) - // Ignore an invalid output loop or a polyline. - continue; - - //skip OutRecs that (a) contain outermost polygons or - //(b) already have the correct owner/child linkage ... - if (outRec->FirstLeft && - (outRec->IsHole == outRec->FirstLeft->IsHole || ! outRec->FirstLeft->Pts)) { - OutRec* orfl = outRec->FirstLeft; - while (orfl && ((orfl->IsHole == outRec->IsHole) || !orfl->Pts)) - orfl = orfl->FirstLeft; - outRec->FirstLeft = orfl; - } - - //nb: polytree takes ownership of all the PolyNodes - polytree.AllNodes.emplace_back(PolyNode()); - PolyNode* pn = &polytree.AllNodes.back(); - outRec->PolyNd = pn; - pn->Parent = 0; - pn->Index = 0; - pn->Contour.reserve(cnt); - OutPt *op = outRec->Pts->Prev; - for (int j = 0; j < cnt; j++) - { - pn->Contour.emplace_back(op->Pt); - op = op->Prev; - } - } - - //fixup PolyNode links etc ... - polytree.Childs.reserve(m_PolyOuts.size()); - for (OutRec* outRec : m_PolyOuts) - { - if (!outRec->PolyNd) continue; - if (outRec->IsOpen) - { - outRec->PolyNd->m_IsOpen = true; - polytree.AddChild(*outRec->PolyNd); - } - else if (outRec->FirstLeft && outRec->FirstLeft->PolyNd) - outRec->FirstLeft->PolyNd->AddChild(*outRec->PolyNd); - else - polytree.AddChild(*outRec->PolyNd); - } -} -//------------------------------------------------------------------------------ - -inline bool E2InsertsBeforeE1(TEdge &e1, TEdge &e2) -{ - if (e2.Curr.X == e1.Curr.X) - { - if (e2.Top.Y > e1.Top.Y) - return e2.Top.X < TopX(e1, e2.Top.Y); - else return e1.Top.X > TopX(e2, e1.Top.Y); - } - else return e2.Curr.X < e1.Curr.X; -} -//------------------------------------------------------------------------------ - -bool GetOverlap(const cInt a1, const cInt a2, const cInt b1, const cInt b2, - cInt& Left, cInt& Right) -{ - if (a1 < a2) - { - if (b1 < b2) {Left = std::max(a1,b1); Right = std::min(a2,b2);} - else {Left = std::max(a1,b2); Right = std::min(a2,b1);} - } - else - { - if (b1 < b2) {Left = std::max(a2,b1); Right = std::min(a1,b2);} - else {Left = std::max(a2,b2); Right = std::min(a1,b1);} - } - return Left < Right; -} -//------------------------------------------------------------------------------ - -// Make all points of outrec point to outrec.Idx -inline void UpdateOutPtIdxs(OutRec& outrec) -{ - OutPt* op = outrec.Pts; - do - { - op->Idx = outrec.Idx; - op = op->Prev; - } - while(op != outrec.Pts); -} -//------------------------------------------------------------------------------ - -void Clipper::InsertEdgeIntoAEL(TEdge *edge, TEdge* startEdge) -{ - if(!m_ActiveEdges) - { - edge->PrevInAEL = 0; - edge->NextInAEL = 0; - m_ActiveEdges = edge; - } - else if(!startEdge && E2InsertsBeforeE1(*m_ActiveEdges, *edge)) - { - edge->PrevInAEL = 0; - edge->NextInAEL = m_ActiveEdges; - m_ActiveEdges->PrevInAEL = edge; - m_ActiveEdges = edge; - } - else - { - if(!startEdge) startEdge = m_ActiveEdges; - while(startEdge->NextInAEL && - !E2InsertsBeforeE1(*startEdge->NextInAEL , *edge)) - startEdge = startEdge->NextInAEL; - edge->NextInAEL = startEdge->NextInAEL; - if(startEdge->NextInAEL) startEdge->NextInAEL->PrevInAEL = edge; - edge->PrevInAEL = startEdge; - startEdge->NextInAEL = edge; - } -} -//---------------------------------------------------------------------- - -OutPt* Clipper::DupOutPt(OutPt* outPt, bool InsertAfter) -{ - OutPt* result = this->AllocateOutPt(); - result->Pt = outPt->Pt; - result->Idx = outPt->Idx; - if (InsertAfter) - { - result->Next = outPt->Next; - result->Prev = outPt; - outPt->Next->Prev = result; - outPt->Next = result; - } - else - { - result->Prev = outPt->Prev; - result->Next = outPt; - outPt->Prev->Next = result; - outPt->Prev = result; - } - return result; -} -//------------------------------------------------------------------------------ - -bool Clipper::JoinHorz(OutPt* op1, OutPt* op1b, OutPt* op2, OutPt* op2b, - const IntPoint &Pt, bool DiscardLeft) -{ - Direction Dir1 = (op1->Pt.X > op1b->Pt.X ? dRightToLeft : dLeftToRight); - Direction Dir2 = (op2->Pt.X > op2b->Pt.X ? dRightToLeft : dLeftToRight); - if (Dir1 == Dir2) return false; - - //When DiscardLeft, we want Op1b to be on the Left of Op1, otherwise we - //want Op1b to be on the Right. (And likewise with Op2 and Op2b.) - //So, to facilitate this while inserting Op1b and Op2b ... - //when DiscardLeft, make sure we're AT or RIGHT of Pt before adding Op1b, - //otherwise make sure we're AT or LEFT of Pt. (Likewise with Op2b.) - if (Dir1 == dLeftToRight) - { - while (op1->Next->Pt.X <= Pt.X && - op1->Next->Pt.X >= op1->Pt.X && op1->Next->Pt.Y == Pt.Y) - op1 = op1->Next; - if (DiscardLeft && (op1->Pt.X != Pt.X)) op1 = op1->Next; - op1b = this->DupOutPt(op1, !DiscardLeft); - if (op1b->Pt != Pt) - { - op1 = op1b; - op1->Pt = Pt; - op1b = this->DupOutPt(op1, !DiscardLeft); - } - } - else - { - while (op1->Next->Pt.X >= Pt.X && - op1->Next->Pt.X <= op1->Pt.X && op1->Next->Pt.Y == Pt.Y) - op1 = op1->Next; - if (!DiscardLeft && (op1->Pt.X != Pt.X)) op1 = op1->Next; - op1b = this->DupOutPt(op1, DiscardLeft); - if (op1b->Pt != Pt) - { - op1 = op1b; - op1->Pt = Pt; - op1b = this->DupOutPt(op1, DiscardLeft); - } - } - - if (Dir2 == dLeftToRight) - { - while (op2->Next->Pt.X <= Pt.X && - op2->Next->Pt.X >= op2->Pt.X && op2->Next->Pt.Y == Pt.Y) - op2 = op2->Next; - if (DiscardLeft && (op2->Pt.X != Pt.X)) op2 = op2->Next; - op2b = this->DupOutPt(op2, !DiscardLeft); - if (op2b->Pt != Pt) - { - op2 = op2b; - op2->Pt = Pt; - op2b = this->DupOutPt(op2, !DiscardLeft); - }; - } else - { - while (op2->Next->Pt.X >= Pt.X && - op2->Next->Pt.X <= op2->Pt.X && op2->Next->Pt.Y == Pt.Y) - op2 = op2->Next; - if (!DiscardLeft && (op2->Pt.X != Pt.X)) op2 = op2->Next; - op2b = this->DupOutPt(op2, DiscardLeft); - if (op2b->Pt != Pt) - { - op2 = op2b; - op2->Pt = Pt; - op2b = this->DupOutPt(op2, DiscardLeft); - }; - }; - - if ((Dir1 == dLeftToRight) == DiscardLeft) - { - op1->Prev = op2; - op2->Next = op1; - op1b->Next = op2b; - op2b->Prev = op1b; - } - else - { - op1->Next = op2; - op2->Prev = op1; - op1b->Prev = op2b; - op2b->Next = op1b; - } - return true; -} -//------------------------------------------------------------------------------ - -bool Clipper::JoinPoints(Join *j, OutRec* outRec1, OutRec* outRec2) -{ - OutPt *op1 = j->OutPt1, *op1b; - OutPt *op2 = j->OutPt2, *op2b; - - //There are 3 kinds of joins for output polygons ... - //1. Horizontal joins where Join.OutPt1 & Join.OutPt2 are vertices anywhere - //along (horizontal) collinear edges (& Join.OffPt is on the same horizontal). - //2. Non-horizontal joins where Join.OutPt1 & Join.OutPt2 are at the same - //location at the Bottom of the overlapping segment (& Join.OffPt is above). - //3. StrictSimple joins where edges touch but are not collinear and where - //Join.OutPt1, Join.OutPt2 & Join.OffPt all share the same point. - bool isHorizontal = (j->OutPt1->Pt.Y == j->OffPt.Y); - - if (isHorizontal && (j->OffPt == j->OutPt1->Pt) && - (j->OffPt == j->OutPt2->Pt)) - { - //Strictly Simple join ... - if (outRec1 != outRec2) return false; - op1b = j->OutPt1->Next; - while (op1b != op1 && (op1b->Pt == j->OffPt)) - op1b = op1b->Next; - bool reverse1 = (op1b->Pt.Y > j->OffPt.Y); - op2b = j->OutPt2->Next; - while (op2b != op2 && (op2b->Pt == j->OffPt)) - op2b = op2b->Next; - bool reverse2 = (op2b->Pt.Y > j->OffPt.Y); - if (reverse1 == reverse2) return false; - if (reverse1) - { - op1b = this->DupOutPt(op1, false); - op2b = this->DupOutPt(op2, true); - op1->Prev = op2; - op2->Next = op1; - op1b->Next = op2b; - op2b->Prev = op1b; - j->OutPt1 = op1; - j->OutPt2 = op1b; - return true; - } else - { - op1b = this->DupOutPt(op1, true); - op2b = this->DupOutPt(op2, false); - op1->Next = op2; - op2->Prev = op1; - op1b->Prev = op2b; - op2b->Next = op1b; - j->OutPt1 = op1; - j->OutPt2 = op1b; - return true; - } - } - else if (isHorizontal) - { - //treat horizontal joins differently to non-horizontal joins since with - //them we're not yet sure where the overlapping is. OutPt1.Pt & OutPt2.Pt - //may be anywhere along the horizontal edge. - op1b = op1; - while (op1->Prev->Pt.Y == op1->Pt.Y && op1->Prev != op1b && op1->Prev != op2) - op1 = op1->Prev; - while (op1b->Next->Pt.Y == op1b->Pt.Y && op1b->Next != op1 && op1b->Next != op2) - op1b = op1b->Next; - if (op1b->Next == op1 || op1b->Next == op2) return false; //a flat 'polygon' - - op2b = op2; - while (op2->Prev->Pt.Y == op2->Pt.Y && op2->Prev != op2b && op2->Prev != op1b) - op2 = op2->Prev; - while (op2b->Next->Pt.Y == op2b->Pt.Y && op2b->Next != op2 && op2b->Next != op1) - op2b = op2b->Next; - if (op2b->Next == op2 || op2b->Next == op1) return false; //a flat 'polygon' - - cInt Left, Right; - //Op1 --> Op1b & Op2 --> Op2b are the extremites of the horizontal edges - if (!GetOverlap(op1->Pt.X, op1b->Pt.X, op2->Pt.X, op2b->Pt.X, Left, Right)) - return false; - - //DiscardLeftSide: when overlapping edges are joined, a spike will created - //which needs to be cleaned up. However, we don't want Op1 or Op2 caught up - //on the discard Side as either may still be needed for other joins ... - IntPoint Pt; - bool DiscardLeftSide; - if (op1->Pt.X >= Left && op1->Pt.X <= Right) - { - Pt = op1->Pt; DiscardLeftSide = (op1->Pt.X > op1b->Pt.X); - } - else if (op2->Pt.X >= Left&& op2->Pt.X <= Right) - { - Pt = op2->Pt; DiscardLeftSide = (op2->Pt.X > op2b->Pt.X); - } - else if (op1b->Pt.X >= Left && op1b->Pt.X <= Right) - { - Pt = op1b->Pt; DiscardLeftSide = op1b->Pt.X > op1->Pt.X; - } - else - { - Pt = op2b->Pt; DiscardLeftSide = (op2b->Pt.X > op2->Pt.X); - } - j->OutPt1 = op1; j->OutPt2 = op2; - return JoinHorz(op1, op1b, op2, op2b, Pt, DiscardLeftSide); - } else - { - //nb: For non-horizontal joins ... - // 1. Jr.OutPt1.Pt.Y == Jr.OutPt2.Pt.Y - // 2. Jr.OutPt1.Pt > Jr.OffPt.Y - - //make sure the polygons are correctly oriented ... - op1b = op1->Next; - while ((op1b->Pt == op1->Pt) && (op1b != op1)) op1b = op1b->Next; - bool Reverse1 = ((op1b->Pt.Y > op1->Pt.Y) || - !SlopesEqual(op1->Pt, op1b->Pt, j->OffPt, m_UseFullRange)); - if (Reverse1) - { - op1b = op1->Prev; - while ((op1b->Pt == op1->Pt) && (op1b != op1)) op1b = op1b->Prev; - if ((op1b->Pt.Y > op1->Pt.Y) || - !SlopesEqual(op1->Pt, op1b->Pt, j->OffPt, m_UseFullRange)) return false; - }; - op2b = op2->Next; - while ((op2b->Pt == op2->Pt) && (op2b != op2))op2b = op2b->Next; - bool Reverse2 = ((op2b->Pt.Y > op2->Pt.Y) || - !SlopesEqual(op2->Pt, op2b->Pt, j->OffPt, m_UseFullRange)); - if (Reverse2) - { - op2b = op2->Prev; - while ((op2b->Pt == op2->Pt) && (op2b != op2)) op2b = op2b->Prev; - if ((op2b->Pt.Y > op2->Pt.Y) || - !SlopesEqual(op2->Pt, op2b->Pt, j->OffPt, m_UseFullRange)) return false; - } - - if ((op1b == op1) || (op2b == op2) || (op1b == op2b) || - ((outRec1 == outRec2) && (Reverse1 == Reverse2))) return false; - - if (Reverse1) - { - op1b = this->DupOutPt(op1, false); - op2b = this->DupOutPt(op2, true); - op1->Prev = op2; - op2->Next = op1; - op1b->Next = op2b; - op2b->Prev = op1b; - j->OutPt1 = op1; - j->OutPt2 = op1b; - return true; - } else - { - op1b = this->DupOutPt(op1, true); - op2b = this->DupOutPt(op2, false); - op1->Next = op2; - op2->Prev = op1; - op1b->Prev = op2b; - op2b->Next = op1b; - j->OutPt1 = op1; - j->OutPt2 = op1b; - return true; - } - } -} -//---------------------------------------------------------------------- - -// This is potentially very expensive! O(n^3)! -void Clipper::FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec) const -{ - PROFILE_FUNC(); - //tests if NewOutRec contains the polygon before reassigning FirstLeft - for (OutRec *outRec : m_PolyOuts) - { - if (!outRec->Pts || !outRec->FirstLeft) continue; - OutRec* firstLeft = outRec->FirstLeft; - // Skip empty polygons. - while (firstLeft && !firstLeft->Pts) firstLeft = firstLeft->FirstLeft; - if (firstLeft == OldOutRec && Poly2ContainsPoly1(outRec->Pts, NewOutRec->Pts)) - outRec->FirstLeft = NewOutRec; - } -} -//---------------------------------------------------------------------- - -void Clipper::FixupFirstLefts2(OutRec* OldOutRec, OutRec* NewOutRec) const -{ - //reassigns FirstLeft WITHOUT testing if NewOutRec contains the polygon - for (OutRec *outRec : m_PolyOuts) - if (outRec->FirstLeft == OldOutRec) outRec->FirstLeft = NewOutRec; -} -//---------------------------------------------------------------------- - -void Clipper::JoinCommonEdges() -{ - PROFILE_FUNC(); - for (Join &join : m_Joins) - { - OutRec *outRec1 = GetOutRec(join.OutPt1->Idx); - OutRec *outRec2 = GetOutRec(join.OutPt2->Idx); - - if (!outRec1->Pts || !outRec2->Pts) continue; - if (outRec1->IsOpen || outRec2->IsOpen) continue; - - //get the polygon fragment with the correct hole state (FirstLeft) - //before calling JoinPoints() ... - OutRec *holeStateRec; - if (outRec1 == outRec2) holeStateRec = outRec1; - else if (Param1RightOfParam2(outRec1, outRec2)) holeStateRec = outRec2; - else if (Param1RightOfParam2(outRec2, outRec1)) holeStateRec = outRec1; - else holeStateRec = GetLowermostRec(outRec1, outRec2); - - if (!JoinPoints(&join, outRec1, outRec2)) continue; - - if (outRec1 == outRec2) - { - //instead of joining two polygons, we've just created a new one by - //splitting one polygon into two. - outRec1->Pts = join.OutPt1; - outRec1->BottomPt = 0; - outRec2 = CreateOutRec(); - outRec2->Pts = join.OutPt2; - - //update all OutRec2.Pts Idx's ... - UpdateOutPtIdxs(*outRec2); - - //We now need to check every OutRec.FirstLeft pointer. If it points - //to OutRec1 it may need to point to OutRec2 instead ... - if (m_UsingPolyTree) - for (size_t j = 0; j < m_PolyOuts.size() - 1; j++) - { - OutRec* oRec = m_PolyOuts[j]; - OutRec* firstLeft = oRec->FirstLeft; - while (firstLeft && !firstLeft->Pts) firstLeft = firstLeft->FirstLeft; - if (!oRec->Pts || firstLeft != outRec1 || - oRec->IsHole == outRec1->IsHole) continue; - if (Poly2ContainsPoly1(oRec->Pts, join.OutPt2)) - oRec->FirstLeft = outRec2; - } - - if (Poly2ContainsPoly1(outRec2->Pts, outRec1->Pts)) - { - //outRec2 is contained by outRec1 ... - outRec2->IsHole = !outRec1->IsHole; - outRec2->FirstLeft = outRec1; - - // For each m_PolyOuts, replace FirstLeft from outRec2 to outRec1. - if (m_UsingPolyTree) FixupFirstLefts2(outRec2, outRec1); - - if ((outRec2->IsHole ^ m_ReverseOutput) == (Area(*outRec2) > 0)) - ReversePolyPtLinks(outRec2->Pts); - - } else if (Poly2ContainsPoly1(outRec1->Pts, outRec2->Pts)) - { - //outRec1 is contained by outRec2 ... - outRec2->IsHole = outRec1->IsHole; - outRec1->IsHole = !outRec2->IsHole; - outRec2->FirstLeft = outRec1->FirstLeft; - outRec1->FirstLeft = outRec2; - - // For each m_PolyOuts, replace FirstLeft from outRec1 to outRec2. - if (m_UsingPolyTree) FixupFirstLefts2(outRec1, outRec2); - - if ((outRec1->IsHole ^ m_ReverseOutput) == (Area(*outRec1) > 0)) - ReversePolyPtLinks(outRec1->Pts); - } - else - { - //the 2 polygons are completely separate ... - outRec2->IsHole = outRec1->IsHole; - outRec2->FirstLeft = outRec1->FirstLeft; - - //fixup FirstLeft pointers that may need reassigning to OutRec2 - // For each polygon of m_PolyOuts, replace FirstLeft from outRec1 to outRec2 if the polygon is inside outRec2. - //FIXME This is potentially very expensive! O(n^3)! - if (m_UsingPolyTree) FixupFirstLefts1(outRec1, outRec2); - } - - } else - { - //joined 2 polygons together ... - - outRec2->Pts = 0; - outRec2->BottomPt = 0; - outRec2->Idx = outRec1->Idx; - - outRec1->IsHole = holeStateRec->IsHole; - if (holeStateRec == outRec2) - outRec1->FirstLeft = outRec2->FirstLeft; - outRec2->FirstLeft = outRec1; - - // For each m_PolyOuts, replace FirstLeft from outRec2 to outRec1. - if (m_UsingPolyTree) FixupFirstLefts2(outRec2, outRec1); - } - } -} - -//------------------------------------------------------------------------------ -// ClipperOffset support functions ... -//------------------------------------------------------------------------------ - -DoublePoint GetUnitNormal(const IntPoint &pt1, const IntPoint &pt2) -{ - if(pt2.X == pt1.X && pt2.Y == pt1.Y) - return DoublePoint(0, 0); - - double Dx = (double)(pt2.X - pt1.X); - double dy = (double)(pt2.Y - pt1.Y); - double f = 1 *1.0/ std::sqrt( Dx*Dx + dy*dy ); - Dx *= f; - dy *= f; - return DoublePoint(dy, -Dx); -} - -//------------------------------------------------------------------------------ -// ClipperOffset class -//------------------------------------------------------------------------------ - -void ClipperOffset::Clear() -{ - for (int i = 0; i < m_polyNodes.ChildCount(); ++i) - delete m_polyNodes.Childs[i]; - m_polyNodes.Childs.clear(); - m_lowest.X = -1; -} -//------------------------------------------------------------------------------ - -void ClipperOffset::AddPath(const Path& path, JoinType joinType, EndType endType) -{ - int highI = (int)path.size() - 1; - if (highI < 0) return; - PolyNode* newNode = new PolyNode(); - newNode->m_jointype = joinType; - newNode->m_endtype = endType; - - //strip duplicate points from path and also get index to the lowest point ... - bool has_shortest_edge_length = ShortestEdgeLength > 0.; - double shortest_edge_length2 = has_shortest_edge_length ? ShortestEdgeLength * ShortestEdgeLength : 0.; - if (endType == etClosedLine || endType == etClosedPolygon) - for (; highI > 0; -- highI) { - bool same = false; - if (has_shortest_edge_length) { - double dx = double(path[highI].X - path[0].X); - double dy = double(path[highI].Y - path[0].Y); - same = dx*dx + dy*dy < shortest_edge_length2; - } else - same = path[0] == path[highI]; - if (! same) - break; - } - newNode->Contour.reserve(highI + 1); - newNode->Contour.push_back(path[0]); - int j = 0, k = 0; - for (int i = 1; i <= highI; i++) { - bool same = false; - if (has_shortest_edge_length) { - double dx = double(path[i].X - newNode->Contour[j].X); - double dy = double(path[i].Y - newNode->Contour[j].Y); - same = dx*dx + dy*dy < shortest_edge_length2; - } else - same = newNode->Contour[j] == path[i]; - if (same) - continue; - j++; - newNode->Contour.push_back(path[i]); - if (path[i].Y > newNode->Contour[k].Y || - (path[i].Y == newNode->Contour[k].Y && - path[i].X < newNode->Contour[k].X)) k = j; - } - if (endType == etClosedPolygon && j < 2) - { - delete newNode; - return; - } - m_polyNodes.AddChild(*newNode); - - //if this path's lowest pt is lower than all the others then update m_lowest - if (endType != etClosedPolygon) return; - if (m_lowest.X < 0) - m_lowest = IntPoint(m_polyNodes.ChildCount() - 1, k); - else - { - IntPoint ip = m_polyNodes.Childs[(int)m_lowest.X]->Contour[(int)m_lowest.Y]; - if (newNode->Contour[k].Y > ip.Y || - (newNode->Contour[k].Y == ip.Y && - newNode->Contour[k].X < ip.X)) - m_lowest = IntPoint(m_polyNodes.ChildCount() - 1, k); - } -} -//------------------------------------------------------------------------------ - -void ClipperOffset::AddPaths(const Paths& paths, JoinType joinType, EndType endType) -{ - for (const Path &path : paths) - AddPath(path, joinType, endType); -} -//------------------------------------------------------------------------------ - -void ClipperOffset::FixOrientations() -{ - //fixup orientations of all closed paths if the orientation of the - //closed path with the lowermost vertex is wrong ... - if (m_lowest.X >= 0 && - !Orientation(m_polyNodes.Childs[(int)m_lowest.X]->Contour)) - { - for (int i = 0; i < m_polyNodes.ChildCount(); ++i) - { - PolyNode& node = *m_polyNodes.Childs[i]; - if (node.m_endtype == etClosedPolygon || - (node.m_endtype == etClosedLine && Orientation(node.Contour))) - ReversePath(node.Contour); - } - } else - { - for (int i = 0; i < m_polyNodes.ChildCount(); ++i) - { - PolyNode& node = *m_polyNodes.Childs[i]; - if (node.m_endtype == etClosedLine && !Orientation(node.Contour)) - ReversePath(node.Contour); - } - } -} -//------------------------------------------------------------------------------ - -void ClipperOffset::Execute(Paths& solution, double delta) -{ - solution.clear(); - FixOrientations(); - DoOffset(delta); - - //now clean up 'corners' ... - Clipper clpr; - clpr.AddPaths(m_destPolys, ptSubject, true); - if (delta > 0) - { - clpr.Execute(ctUnion, solution, pftPositive, pftPositive); - } - else - { - IntRect r = clpr.GetBounds(); - Path outer(4); - outer[0] = IntPoint(r.left - 10, r.bottom + 10); - outer[1] = IntPoint(r.right + 10, r.bottom + 10); - outer[2] = IntPoint(r.right + 10, r.top - 10); - outer[3] = IntPoint(r.left - 10, r.top - 10); - - clpr.AddPath(outer, ptSubject, true); - clpr.ReverseSolution(true); - clpr.Execute(ctUnion, solution, pftNegative, pftNegative); - if (solution.size() > 0) solution.erase(solution.begin()); - } -} -//------------------------------------------------------------------------------ - -void ClipperOffset::Execute(PolyTree& solution, double delta) -{ - solution.Clear(); - FixOrientations(); - DoOffset(delta); - - //now clean up 'corners' ... - Clipper clpr; - clpr.AddPaths(m_destPolys, ptSubject, true); - if (delta > 0) - { - clpr.Execute(ctUnion, solution, pftPositive, pftPositive); - } - else - { - IntRect r = clpr.GetBounds(); - Path outer(4); - outer[0] = IntPoint(r.left - 10, r.bottom + 10); - outer[1] = IntPoint(r.right + 10, r.bottom + 10); - outer[2] = IntPoint(r.right + 10, r.top - 10); - outer[3] = IntPoint(r.left - 10, r.top - 10); - - clpr.AddPath(outer, ptSubject, true); - clpr.ReverseSolution(true); - clpr.Execute(ctUnion, solution, pftNegative, pftNegative); - //remove the outer PolyNode rectangle ... - if (solution.ChildCount() == 1 && solution.Childs[0]->ChildCount() > 0) - { - PolyNode* outerNode = solution.Childs[0]; - solution.Childs.reserve(outerNode->ChildCount()); - solution.Childs[0] = outerNode->Childs[0]; - solution.Childs[0]->Parent = outerNode->Parent; - for (int i = 1; i < outerNode->ChildCount(); ++i) - solution.AddChild(*outerNode->Childs[i]); - } - else - solution.Clear(); - } -} -//------------------------------------------------------------------------------ - -void ClipperOffset::DoOffset(double delta) -{ - m_destPolys.clear(); - m_delta = delta; - - //if Zero offset, just copy any CLOSED polygons to m_p and return ... - if (NEAR_ZERO(delta)) - { - m_destPolys.reserve(m_polyNodes.ChildCount()); - for (int i = 0; i < m_polyNodes.ChildCount(); i++) - { - PolyNode& node = *m_polyNodes.Childs[i]; - if (node.m_endtype == etClosedPolygon) - m_destPolys.push_back(node.Contour); - } - return; - } - - //see offset_triginometry3.svg in the documentation folder ... - if (MiterLimit > 2) m_miterLim = 2/(MiterLimit * MiterLimit); - else m_miterLim = 0.5; - - double y; - if (ArcTolerance <= 0.0) y = def_arc_tolerance; - else if (ArcTolerance > std::fabs(delta) * def_arc_tolerance) - y = std::fabs(delta) * def_arc_tolerance; - else y = ArcTolerance; - //see offset_triginometry2.svg in the documentation folder ... - double steps = pi / std::acos(1 - y / std::fabs(delta)); - if (steps > std::fabs(delta) * pi) - steps = std::fabs(delta) * pi; //ie excessive precision check - m_sin = std::sin(two_pi / steps); - m_cos = std::cos(two_pi / steps); - m_StepsPerRad = steps / two_pi; - if (delta < 0.0) m_sin = -m_sin; - - m_destPolys.reserve(m_polyNodes.ChildCount() * 2); - for (int i = 0; i < m_polyNodes.ChildCount(); i++) - { - PolyNode& node = *m_polyNodes.Childs[i]; - m_srcPoly = node.Contour; - - int len = (int)m_srcPoly.size(); - if (len == 0 || (delta <= 0 && (len < 3 || node.m_endtype != etClosedPolygon))) - continue; - - m_destPoly.clear(); - if (len == 1) - { - if (node.m_jointype == jtRound) - { - double X = 1.0, Y = 0.0; - for (cInt j = 1; j <= steps; j++) - { - m_destPoly.push_back(IntPoint( - Round(m_srcPoly[0].X + X * delta), - Round(m_srcPoly[0].Y + Y * delta))); - double X2 = X; - X = X * m_cos - m_sin * Y; - Y = X2 * m_sin + Y * m_cos; - } - } - else - { - double X = -1.0, Y = -1.0; - for (int j = 0; j < 4; ++j) - { - m_destPoly.push_back(IntPoint( - Round(m_srcPoly[0].X + X * delta), - Round(m_srcPoly[0].Y + Y * delta))); - if (X < 0) X = 1; - else if (Y < 0) Y = 1; - else X = -1; - } - } - m_destPolys.push_back(m_destPoly); - continue; - } - //build m_normals ... - m_normals.clear(); - m_normals.reserve(len); - for (int j = 0; j < len - 1; ++j) - m_normals.push_back(GetUnitNormal(m_srcPoly[j], m_srcPoly[j + 1])); - if (node.m_endtype == etClosedLine || node.m_endtype == etClosedPolygon) - m_normals.push_back(GetUnitNormal(m_srcPoly[len - 1], m_srcPoly[0])); - else - m_normals.push_back(DoublePoint(m_normals[len - 2])); - - if (node.m_endtype == etClosedPolygon) - { - int k = len - 1; - for (int j = 0; j < len; ++j) - OffsetPoint(j, k, node.m_jointype); - m_destPolys.push_back(m_destPoly); - } - else if (node.m_endtype == etClosedLine) - { - int k = len - 1; - for (int j = 0; j < len; ++j) - OffsetPoint(j, k, node.m_jointype); - m_destPolys.push_back(m_destPoly); - m_destPoly.clear(); - //re-build m_normals ... - DoublePoint n = m_normals[len -1]; - for (int j = len - 1; j > 0; j--) - m_normals[j] = DoublePoint(-m_normals[j - 1].X, -m_normals[j - 1].Y); - m_normals[0] = DoublePoint(-n.X, -n.Y); - k = 0; - for (int j = len - 1; j >= 0; j--) - OffsetPoint(j, k, node.m_jointype); - m_destPolys.push_back(m_destPoly); - } - else - { - int k = 0; - for (int j = 1; j < len - 1; ++j) - OffsetPoint(j, k, node.m_jointype); - - IntPoint pt1; - if (node.m_endtype == etOpenButt) - { - int j = len - 1; - pt1 = IntPoint(Round(m_srcPoly[j].X + m_normals[j].X * - delta), Round(m_srcPoly[j].Y + m_normals[j].Y * delta)); - m_destPoly.push_back(pt1); - pt1 = IntPoint(Round(m_srcPoly[j].X - m_normals[j].X * - delta), Round(m_srcPoly[j].Y - m_normals[j].Y * delta)); - m_destPoly.push_back(pt1); - } - else - { - int j = len - 1; - k = len - 2; - m_sinA = 0; - m_normals[j] = DoublePoint(-m_normals[j].X, -m_normals[j].Y); - if (node.m_endtype == etOpenSquare) - DoSquare(j, k); - else - DoRound(j, k); - } - - //re-build m_normals ... - for (int j = len - 1; j > 0; j--) - m_normals[j] = DoublePoint(-m_normals[j - 1].X, -m_normals[j - 1].Y); - m_normals[0] = DoublePoint(-m_normals[1].X, -m_normals[1].Y); - - k = len - 1; - for (int j = k - 1; j > 0; --j) OffsetPoint(j, k, node.m_jointype); - - if (node.m_endtype == etOpenButt) - { - pt1 = IntPoint(Round(m_srcPoly[0].X - m_normals[0].X * delta), - Round(m_srcPoly[0].Y - m_normals[0].Y * delta)); - m_destPoly.push_back(pt1); - pt1 = IntPoint(Round(m_srcPoly[0].X + m_normals[0].X * delta), - Round(m_srcPoly[0].Y + m_normals[0].Y * delta)); - m_destPoly.push_back(pt1); - } - else - { - k = 1; - m_sinA = 0; - if (node.m_endtype == etOpenSquare) - DoSquare(0, 1); - else - DoRound(0, 1); - } - m_destPolys.push_back(m_destPoly); - } - } -} -//------------------------------------------------------------------------------ - -void ClipperOffset::OffsetPoint(int j, int& k, JoinType jointype) -{ - //cross product ... - m_sinA = (m_normals[k].X * m_normals[j].Y - m_normals[j].X * m_normals[k].Y); - if (std::fabs(m_sinA * m_delta) < 1.0) - { - //dot product ... - double cosA = (m_normals[k].X * m_normals[j].X + m_normals[j].Y * m_normals[k].Y ); - if (cosA > 0) // angle => 0 degrees - { - m_destPoly.push_back(IntPoint(Round(m_srcPoly[j].X + m_normals[k].X * m_delta), - Round(m_srcPoly[j].Y + m_normals[k].Y * m_delta))); - return; - } - //else angle => 180 degrees - } - else if (m_sinA > 1.0) m_sinA = 1.0; - else if (m_sinA < -1.0) m_sinA = -1.0; - - if (m_sinA * m_delta < 0) - { - m_destPoly.push_back(IntPoint(Round(m_srcPoly[j].X + m_normals[k].X * m_delta), - Round(m_srcPoly[j].Y + m_normals[k].Y * m_delta))); - m_destPoly.push_back(m_srcPoly[j]); - m_destPoly.push_back(IntPoint(Round(m_srcPoly[j].X + m_normals[j].X * m_delta), - Round(m_srcPoly[j].Y + m_normals[j].Y * m_delta))); - } - else - switch (jointype) - { - case jtMiter: - { - double r = 1 + (m_normals[j].X * m_normals[k].X + - m_normals[j].Y * m_normals[k].Y); - if (r >= m_miterLim) DoMiter(j, k, r); else DoSquare(j, k); - break; - } - case jtSquare: DoSquare(j, k); break; - case jtRound: DoRound(j, k); break; - } - k = j; -} -//------------------------------------------------------------------------------ - -void ClipperOffset::DoSquare(int j, int k) -{ - double dx = std::tan(std::atan2(m_sinA, - m_normals[k].X * m_normals[j].X + m_normals[k].Y * m_normals[j].Y) / 4); - m_destPoly.push_back(IntPoint( - Round(m_srcPoly[j].X + m_delta * (m_normals[k].X - m_normals[k].Y * dx)), - Round(m_srcPoly[j].Y + m_delta * (m_normals[k].Y + m_normals[k].X * dx)))); - m_destPoly.push_back(IntPoint( - Round(m_srcPoly[j].X + m_delta * (m_normals[j].X + m_normals[j].Y * dx)), - Round(m_srcPoly[j].Y + m_delta * (m_normals[j].Y - m_normals[j].X * dx)))); -} -//------------------------------------------------------------------------------ - -void ClipperOffset::DoMiter(int j, int k, double r) -{ - double q = m_delta / r; - m_destPoly.push_back(IntPoint(Round(m_srcPoly[j].X + (m_normals[k].X + m_normals[j].X) * q), - Round(m_srcPoly[j].Y + (m_normals[k].Y + m_normals[j].Y) * q))); -} -//------------------------------------------------------------------------------ - -void ClipperOffset::DoRound(int j, int k) -{ - double a = std::atan2(m_sinA, - m_normals[k].X * m_normals[j].X + m_normals[k].Y * m_normals[j].Y); - int steps = std::max((int)Round(m_StepsPerRad * std::fabs(a)), 1); - - double X = m_normals[k].X, Y = m_normals[k].Y, X2; - for (int i = 0; i < steps; ++i) - { - m_destPoly.push_back(IntPoint( - Round(m_srcPoly[j].X + X * m_delta), - Round(m_srcPoly[j].Y + Y * m_delta))); - X2 = X; - X = X * m_cos - m_sin * Y; - Y = X2 * m_sin + Y * m_cos; - } - m_destPoly.push_back(IntPoint( - Round(m_srcPoly[j].X + m_normals[j].X * m_delta), - Round(m_srcPoly[j].Y + m_normals[j].Y * m_delta))); -} - -//------------------------------------------------------------------------------ -// Miscellaneous public functions -//------------------------------------------------------------------------------ - -// Called by Clipper::ExecuteInternal() -// For each polygon, search for exactly duplicate non-successive points. -// If such a point is found, the loop is split into two pieces. -// Search for the duplicate points is O(n^2)! -// http://www.angusj.com/delphi/clipper/documentation/Docs/Units/ClipperLib/Classes/Clipper/Properties/StrictlySimple.htm -void Clipper::DoSimplePolygons() -{ - PROFILE_FUNC(); - size_t i = 0; - while (i < m_PolyOuts.size()) - { - OutRec* outrec = m_PolyOuts[i++]; - OutPt* op = outrec->Pts; - if (!op || outrec->IsOpen) continue; - do //for each Pt in Polygon until duplicate found do ... - { - OutPt* op2 = op->Next; - while (op2 != outrec->Pts) - { - if ((op->Pt == op2->Pt) && op2->Next != op && op2->Prev != op) - { - //split the polygon into two ... - OutPt* op3 = op->Prev; - OutPt* op4 = op2->Prev; - op->Prev = op4; - op4->Next = op; - op2->Prev = op3; - op3->Next = op2; - - outrec->Pts = op; - OutRec* outrec2 = CreateOutRec(); - outrec2->Pts = op2; - UpdateOutPtIdxs(*outrec2); - if (Poly2ContainsPoly1(outrec2->Pts, outrec->Pts)) - { - //OutRec2 is contained by OutRec1 ... - outrec2->IsHole = !outrec->IsHole; - outrec2->FirstLeft = outrec; - // For each m_PolyOuts, replace FirstLeft from outRec2 to outrec. - if (m_UsingPolyTree) FixupFirstLefts2(outrec2, outrec); - } - else - if (Poly2ContainsPoly1(outrec->Pts, outrec2->Pts)) - { - //OutRec1 is contained by OutRec2 ... - outrec2->IsHole = outrec->IsHole; - outrec->IsHole = !outrec2->IsHole; - outrec2->FirstLeft = outrec->FirstLeft; - outrec->FirstLeft = outrec2; - // For each m_PolyOuts, replace FirstLeft from outrec to outrec2. - if (m_UsingPolyTree) FixupFirstLefts2(outrec, outrec2); - } - else - { - //the 2 polygons are separate ... - outrec2->IsHole = outrec->IsHole; - outrec2->FirstLeft = outrec->FirstLeft; - // For each polygon of m_PolyOuts, replace FirstLeft from outrec to outrec2 if the polygon is inside outRec2. - //FIXME This is potentially very expensive! O(n^3)! - if (m_UsingPolyTree) FixupFirstLefts1(outrec, outrec2); - } - op2 = op; //ie get ready for the Next iteration - } - op2 = op2->Next; - } - op = op->Next; - } - while (op != outrec->Pts); - } -} -//------------------------------------------------------------------------------ - -void ReversePath(Path& p) -{ - std::reverse(p.begin(), p.end()); -} -//------------------------------------------------------------------------------ - -void ReversePaths(Paths& p) -{ - for (Paths::size_type i = 0; i < p.size(); ++i) - ReversePath(p[i]); -} -//------------------------------------------------------------------------------ - -void SimplifyPolygon(const Path &in_poly, Paths &out_polys, PolyFillType fillType) -{ - Clipper c; - c.StrictlySimple(true); - c.AddPath(in_poly, ptSubject, true); - c.Execute(ctUnion, out_polys, fillType, fillType); -} -//------------------------------------------------------------------------------ - -void SimplifyPolygons(const Paths &in_polys, Paths &out_polys, PolyFillType fillType) -{ - Clipper c; - c.StrictlySimple(true); - c.AddPaths(in_polys, ptSubject, true); - c.Execute(ctUnion, out_polys, fillType, fillType); -} -//------------------------------------------------------------------------------ - -void SimplifyPolygons(Paths &polys, PolyFillType fillType) -{ - SimplifyPolygons(polys, polys, fillType); -} -//------------------------------------------------------------------------------ - -inline double DistanceSqrd(const IntPoint& pt1, const IntPoint& pt2) -{ - double Dx = ((double)pt1.X - pt2.X); - double dy = ((double)pt1.Y - pt2.Y); - return (Dx*Dx + dy*dy); -} -//------------------------------------------------------------------------------ - -double DistanceFromLineSqrd( - const IntPoint& pt, const IntPoint& ln1, const IntPoint& ln2) -{ - //The equation of a line in general form (Ax + By + C = 0) - //given 2 points (x¹,y¹) & (x²,y²) is ... - //(y¹ - y²)x + (x² - x¹)y + (y² - y¹)x¹ - (x² - x¹)y¹ = 0 - //A = (y¹ - y²); B = (x² - x¹); C = (y² - y¹)x¹ - (x² - x¹)y¹ - //perpendicular distance of point (x³,y³) = (Ax³ + By³ + C)/Sqrt(A² + B²) - //see http://en.wikipedia.org/wiki/Perpendicular_distance - double A = double(ln1.Y - ln2.Y); - double B = double(ln2.X - ln1.X); - double C = A * ln1.X + B * ln1.Y; - C = A * pt.X + B * pt.Y - C; - return (C * C) / (A * A + B * B); -} -//--------------------------------------------------------------------------- - -bool SlopesNearCollinear(const IntPoint& pt1, - const IntPoint& pt2, const IntPoint& pt3, double distSqrd) -{ - //this function is more accurate when the point that's geometrically - //between the other 2 points is the one that's tested for distance. - //ie makes it more likely to pick up 'spikes' ... - if (std::abs(pt1.X - pt2.X) > std::abs(pt1.Y - pt2.Y)) - { - if ((pt1.X > pt2.X) == (pt1.X < pt3.X)) - return DistanceFromLineSqrd(pt1, pt2, pt3) < distSqrd; - else if ((pt2.X > pt1.X) == (pt2.X < pt3.X)) - return DistanceFromLineSqrd(pt2, pt1, pt3) < distSqrd; - else - return DistanceFromLineSqrd(pt3, pt1, pt2) < distSqrd; - } - else - { - if ((pt1.Y > pt2.Y) == (pt1.Y < pt3.Y)) - return DistanceFromLineSqrd(pt1, pt2, pt3) < distSqrd; - else if ((pt2.Y > pt1.Y) == (pt2.Y < pt3.Y)) - return DistanceFromLineSqrd(pt2, pt1, pt3) < distSqrd; - else - return DistanceFromLineSqrd(pt3, pt1, pt2) < distSqrd; - } -} -//------------------------------------------------------------------------------ - -bool PointsAreClose(IntPoint pt1, IntPoint pt2, double distSqrd) -{ - double Dx = (double)pt1.X - pt2.X; - double dy = (double)pt1.Y - pt2.Y; - return ((Dx * Dx) + (dy * dy) <= distSqrd); -} -//------------------------------------------------------------------------------ - -OutPt* ExcludeOp(OutPt* op) -{ - OutPt* result = op->Prev; - result->Next = op->Next; - op->Next->Prev = result; - result->Idx = 0; - return result; -} -//------------------------------------------------------------------------------ - -// Simplify a polygon using a linked list of points. -void CleanPolygon(const Path& in_poly, Path& out_poly, double distance) -{ - //distance = proximity in units/pixels below which vertices - //will be stripped. Default ~= sqrt(2). - - size_t size = in_poly.size(); - - if (size == 0) - { - out_poly.clear(); - return; - } - - std::vector outPts(size); - for (size_t i = 0; i < size; ++i) - { - outPts[i].Pt = in_poly[i]; - outPts[i].Next = &outPts[(i + 1) % size]; - outPts[i].Next->Prev = &outPts[i]; - outPts[i].Idx = 0; - } - - double distSqrd = distance * distance; - OutPt* op = &outPts[0]; - while (op->Idx == 0 && op->Next != op->Prev) - { - if (PointsAreClose(op->Pt, op->Prev->Pt, distSqrd)) - { - op = ExcludeOp(op); - size--; - } - else if (PointsAreClose(op->Prev->Pt, op->Next->Pt, distSqrd)) - { - ExcludeOp(op->Next); - op = ExcludeOp(op); - size -= 2; - } - else if (SlopesNearCollinear(op->Prev->Pt, op->Pt, op->Next->Pt, distSqrd)) - { - op = ExcludeOp(op); - size--; - } - else - { - op->Idx = 1; - op = op->Next; - } - } - - if (size < 3) size = 0; - out_poly.resize(size); - for (size_t i = 0; i < size; ++i) - { - out_poly[i] = op->Pt; - op = op->Next; - } -} -//------------------------------------------------------------------------------ - -void CleanPolygon(Path& poly, double distance) -{ - CleanPolygon(poly, poly, distance); -} -//------------------------------------------------------------------------------ - -void CleanPolygons(const Paths& in_polys, Paths& out_polys, double distance) -{ - for (Paths::size_type i = 0; i < in_polys.size(); ++i) - CleanPolygon(in_polys[i], out_polys[i], distance); -} -//------------------------------------------------------------------------------ - -void CleanPolygons(Paths& polys, double distance) -{ - CleanPolygons(polys, polys, distance); -} -//------------------------------------------------------------------------------ - -void Minkowski(const Path& poly, const Path& path, - Paths& solution, bool isSum, bool isClosed) -{ - int delta = (isClosed ? 1 : 0); - size_t polyCnt = poly.size(); - size_t pathCnt = path.size(); - Paths pp; - pp.reserve(pathCnt); - if (isSum) - for (size_t i = 0; i < pathCnt; ++i) - { - Path p; - p.reserve(polyCnt); - for (size_t j = 0; j < poly.size(); ++j) - p.push_back(IntPoint(path[i].X + poly[j].X, path[i].Y + poly[j].Y)); - pp.push_back(p); - } - else - for (size_t i = 0; i < pathCnt; ++i) - { - Path p; - p.reserve(polyCnt); - for (size_t j = 0; j < poly.size(); ++j) - p.push_back(IntPoint(path[i].X - poly[j].X, path[i].Y - poly[j].Y)); - pp.push_back(p); - } - - solution.clear(); - solution.reserve((pathCnt + delta) * (polyCnt + 1)); - for (size_t i = 0; i < pathCnt - 1 + delta; ++i) - for (size_t j = 0; j < polyCnt; ++j) - { - Path quad; - quad.reserve(4); - quad.push_back(pp[i % pathCnt][j % polyCnt]); - quad.push_back(pp[(i + 1) % pathCnt][j % polyCnt]); - quad.push_back(pp[(i + 1) % pathCnt][(j + 1) % polyCnt]); - quad.push_back(pp[i % pathCnt][(j + 1) % polyCnt]); - if (!Orientation(quad)) ReversePath(quad); - solution.push_back(quad); - } -} -//------------------------------------------------------------------------------ - -void MinkowskiSum(const Path& pattern, const Path& path, Paths& solution, bool pathIsClosed) -{ - Minkowski(pattern, path, solution, true, pathIsClosed); - Clipper c; - c.AddPaths(solution, ptSubject, true); - c.Execute(ctUnion, solution, pftNonZero, pftNonZero); -} -//------------------------------------------------------------------------------ - -void TranslatePath(const Path& input, Path& output, const IntPoint& delta) -{ - //precondition: input != output - output.resize(input.size()); - for (size_t i = 0; i < input.size(); ++i) - output[i] = IntPoint(input[i].X + delta.X, input[i].Y + delta.Y); -} -//------------------------------------------------------------------------------ - -void MinkowskiSum(const Path& pattern, const Paths& paths, Paths& solution, bool pathIsClosed) -{ - Clipper c; - for (size_t i = 0; i < paths.size(); ++i) - { - Paths tmp; - Minkowski(pattern, paths[i], tmp, true, pathIsClosed); - c.AddPaths(tmp, ptSubject, true); - if (pathIsClosed) - { - Path tmp2; - TranslatePath(paths[i], tmp2, pattern[0]); - c.AddPath(tmp2, ptClip, true); - } - } - c.Execute(ctUnion, solution, pftNonZero, pftNonZero); -} -//------------------------------------------------------------------------------ - -void MinkowskiDiff(const Path& poly1, const Path& poly2, Paths& solution) -{ - Minkowski(poly1, poly2, solution, false, true); - Clipper c; - c.AddPaths(solution, ptSubject, true); - c.Execute(ctUnion, solution, pftNonZero, pftNonZero); -} -//------------------------------------------------------------------------------ - -enum NodeType {ntAny, ntOpen, ntClosed}; - -void AddPolyNodeToPaths(const PolyNode& polynode, NodeType nodetype, Paths& paths) -{ - bool match = true; - if (nodetype == ntClosed) match = !polynode.IsOpen(); - else if (nodetype == ntOpen) return; - - if (!polynode.Contour.empty() && match) - paths.push_back(polynode.Contour); - for (int i = 0; i < polynode.ChildCount(); ++i) - AddPolyNodeToPaths(*polynode.Childs[i], nodetype, paths); -} -//------------------------------------------------------------------------------ - -void PolyTreeToPaths(const PolyTree& polytree, Paths& paths) -{ - paths.resize(0); - paths.reserve(polytree.Total()); - AddPolyNodeToPaths(polytree, ntAny, paths); -} -//------------------------------------------------------------------------------ - -void ClosedPathsFromPolyTree(const PolyTree& polytree, Paths& paths) -{ - paths.resize(0); - paths.reserve(polytree.Total()); - AddPolyNodeToPaths(polytree, ntClosed, paths); -} -//------------------------------------------------------------------------------ - -void OpenPathsFromPolyTree(PolyTree& polytree, Paths& paths) -{ - paths.resize(0); - paths.reserve(polytree.Total()); - //Open paths are top level only, so ... - for (int i = 0; i < polytree.ChildCount(); ++i) - if (polytree.Childs[i]->IsOpen()) - paths.push_back(polytree.Childs[i]->Contour); -} -//------------------------------------------------------------------------------ - -std::ostream& operator <<(std::ostream &s, const IntPoint &p) -{ - s << "(" << p.X << "," << p.Y << ")"; - return s; -} -//------------------------------------------------------------------------------ - -std::ostream& operator <<(std::ostream &s, const Path &p) -{ - if (p.empty()) return s; - Path::size_type last = p.size() -1; - for (Path::size_type i = 0; i < last; i++) - s << "(" << p[i].X << "," << p[i].Y << "), "; - s << "(" << p[last].X << "," << p[last].Y << ")\n"; - return s; -} -//------------------------------------------------------------------------------ - -std::ostream& operator <<(std::ostream &s, const Paths &p) -{ - for (Paths::size_type i = 0; i < p.size(); i++) - s << p[i]; - s << "\n"; - return s; -} -//------------------------------------------------------------------------------ - -} //ClipperLib namespace +/******************************************************************************* +* * +* Author : Angus Johnson * +* Version : 6.2.9 * +* Date : 16 February 2015 * +* Website : http://www.angusj.com * +* Copyright : Angus Johnson 2010-2015 * +* * +* License: * +* Use, modification & distribution is subject to Boost Software License Ver 1. * +* http://www.boost.org/LICENSE_1_0.txt * +* * +* Attributions: * +* The code in this library is an extension of Bala Vatti's clipping algorithm: * +* "A generic solution to polygon clipping" * +* Communications of the ACM, Vol 35, Issue 7 (July 1992) pp 56-63. * +* http://portal.acm.org/citation.cfm?id=129906 * +* * +* Computer graphics and geometric modeling: implementation and algorithms * +* By Max K. Agoston * +* Springer; 1 edition (January 4, 2005) * +* http://books.google.com/books?q=vatti+clipping+agoston * +* * +* See also: * +* "Polygon Offsetting by Computing Winding Numbers" * +* Paper no. DETC2005-85513 pp. 565-575 * +* ASME 2005 International Design Engineering Technical Conferences * +* and Computers and Information in Engineering Conference (IDETC/CIE2005) * +* September 24-28, 2005 , Long Beach, California, USA * +* http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf * +* * +*******************************************************************************/ + +/******************************************************************************* +* * +* This is a translation of the Delphi Clipper library and the naming style * +* used has retained a Delphi flavour. * +* * +*******************************************************************************/ + +#include "clipper.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace ClipperLib { + +static double const pi = 3.141592653589793238; +static double const two_pi = pi *2; +static double const def_arc_tolerance = 0.25; + +enum Direction { dRightToLeft, dLeftToRight }; + +static int const Unassigned = -1; //edge not currently 'owning' a solution +static int const Skip = -2; //edge that would otherwise close a path + +#define HORIZONTAL (-1.0E+40) +#define TOLERANCE (1.0e-20) +#define NEAR_ZERO(val) (((val) > -TOLERANCE) && ((val) < TOLERANCE)) + +// Output polygon. +struct OutRec { + int Idx; + bool IsHole; + bool IsOpen; + //The 'FirstLeft' field points to another OutRec that contains or is the + //'parent' of OutRec. It is 'first left' because the ActiveEdgeList (AEL) is + //parsed left from the current edge (owning OutRec) until the owner OutRec + //is found. This field simplifies sorting the polygons into a tree structure + //which reflects the parent/child relationships of all polygons. + //This field should be renamed Parent, and will be later. + OutRec *FirstLeft; + // Used only by void Clipper::BuildResult2(PolyTree& polytree) + PolyNode *PolyNd; + // Linked list of output points, dynamically allocated. + OutPt *Pts; + OutPt *BottomPt; +}; + +//------------------------------------------------------------------------------ + +inline cInt Round(double val) +{ + return static_cast((val < 0) ? (val - 0.5) : (val + 0.5)); +} + +//------------------------------------------------------------------------------ +// PolyTree methods ... +//------------------------------------------------------------------------------ + +int PolyTree::Total() const +{ + int result = (int)AllNodes.size(); + //with negative offsets, ignore the hidden outer polygon ... + if (result > 0 && Childs.front() != &AllNodes.front()) result--; + return result; +} + +//------------------------------------------------------------------------------ +// PolyNode methods ... +//------------------------------------------------------------------------------ + +void PolyNode::AddChild(PolyNode& child) +{ + unsigned cnt = (unsigned)Childs.size(); + Childs.push_back(&child); + child.Parent = this; + child.Index = cnt; +} +//------------------------------------------------------------------------------ + +// Edge delimits a hole if it has an odd number of parent loops. +bool PolyNode::IsHole() const +{ + bool result = true; + PolyNode* node = Parent; + while (node) + { + result = !result; + node = node->Parent; + } + return result; +} + +//------------------------------------------------------------------------------ +// Miscellaneous global functions +//------------------------------------------------------------------------------ + +double Area(const Path &poly) +{ + int size = (int)poly.size(); + if (size < 3) return 0; + + double a = 0; + for (int i = 0, j = size -1; i < size; ++i) + { + a += ((double)poly[j].X + poly[i].X) * ((double)poly[j].Y - poly[i].Y); + j = i; + } + return -a * 0.5; +} +//------------------------------------------------------------------------------ + +double Area(const OutRec &outRec) +{ + OutPt *op = outRec.Pts; + if (!op) return 0; + double a = 0; + do { + a += (double)(op->Prev->Pt.X + op->Pt.X) * (double)(op->Prev->Pt.Y - op->Pt.Y); + op = op->Next; + } while (op != outRec.Pts); + return a * 0.5; +} +//------------------------------------------------------------------------------ + +bool PointIsVertex(const IntPoint &Pt, OutPt *pp) +{ + OutPt *pp2 = pp; + do + { + if (pp2->Pt == Pt) return true; + pp2 = pp2->Next; + } + while (pp2 != pp); + return false; +} +//------------------------------------------------------------------------------ + +//See "The Point in Polygon Problem for Arbitrary Polygons" by Hormann & Agathos +//http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.88.5498&rep=rep1&type=pdf +int PointInPolygon(const IntPoint &pt, const Path &path) +{ + //returns 0 if false, +1 if true, -1 if pt ON polygon boundary + int result = 0; + size_t cnt = path.size(); + if (cnt < 3) return 0; + IntPoint ip = path[0]; + for(size_t i = 1; i <= cnt; ++i) + { + IntPoint ipNext = (i == cnt ? path[0] : path[i]); + if (ipNext.Y == pt.Y && ((ipNext.X == pt.X) || (ip.Y == pt.Y && ((ipNext.X > pt.X) == (ip.X < pt.X))))) + return -1; + if ((ip.Y < pt.Y) != (ipNext.Y < pt.Y)) + { + if (ip.X >= pt.X) + { + if (ipNext.X > pt.X) result = 1 - result; + else + { + double d = (double)(ip.X - pt.X) * (ipNext.Y - pt.Y) - (double)(ipNext.X - pt.X) * (ip.Y - pt.Y); + if (!d) return -1; + if ((d > 0) == (ipNext.Y > ip.Y)) result = 1 - result; + } + } else + { + if (ipNext.X > pt.X) + { + double d = (double)(ip.X - pt.X) * (ipNext.Y - pt.Y) - (double)(ipNext.X - pt.X) * (ip.Y - pt.Y); + if (!d) return -1; + if ((d > 0) == (ipNext.Y > ip.Y)) result = 1 - result; + } + } + } + ip = ipNext; + } + return result; +} +//------------------------------------------------------------------------------ + +// Called by Poly2ContainsPoly1() +int PointInPolygon (const IntPoint &pt, OutPt *op) +{ + //returns 0 if false, +1 if true, -1 if pt ON polygon boundary + int result = 0; + OutPt* startOp = op; + do + { + if (op->Next->Pt.Y == pt.Y) + { + if ((op->Next->Pt.X == pt.X) || (op->Pt.Y == pt.Y && + ((op->Next->Pt.X > pt.X) == (op->Pt.X < pt.X)))) return -1; + } + if ((op->Pt.Y < pt.Y) != (op->Next->Pt.Y < pt.Y)) + { + if (op->Pt.X >= pt.X) + { + if (op->Next->Pt.X > pt.X) result = 1 - result; + else + { + double d = (double)(op->Pt.X - pt.X) * (op->Next->Pt.Y - pt.Y) - (double)(op->Next->Pt.X - pt.X) * (op->Pt.Y - pt.Y); + if (!d) return -1; + if ((d > 0) == (op->Next->Pt.Y > op->Pt.Y)) result = 1 - result; + } + } else + { + if (op->Next->Pt.X > pt.X) + { + double d = (double)(op->Pt.X - pt.X) * (op->Next->Pt.Y - pt.Y) - (double)(op->Next->Pt.X - pt.X) * (op->Pt.Y - pt.Y); + if (!d) return -1; + if ((d > 0) == (op->Next->Pt.Y > op->Pt.Y)) result = 1 - result; + } + } + } + op = op->Next; + } while (startOp != op); + return result; +} +//------------------------------------------------------------------------------ + +// This is potentially very expensive! O(n^2)! +bool Poly2ContainsPoly1(OutPt *OutPt1, OutPt *OutPt2) +{ + PROFILE_FUNC(); + OutPt* op = OutPt1; + do + { + //nb: PointInPolygon returns 0 if false, +1 if true, -1 if pt on polygon + int res = PointInPolygon(op->Pt, OutPt2); + if (res >= 0) return res > 0; + op = op->Next; + } + while (op != OutPt1); + return true; +} +//---------------------------------------------------------------------- + +inline bool SlopesEqual(const cInt dx1, const cInt dy1, const cInt dx2, const cInt dy2, bool UseFullInt64Range) { + return (UseFullInt64Range) ? + // |dx1| < 2^63, |dx2| < 2^63 etc, + Int128::sign_determinant_2x2_filtered(dx1, dy1, dx2, dy2) == 0 : +// Int128::sign_determinant_2x2(dx1, dy1, dx2, dy2) == 0 : + // |dx1| < 2^31, |dx2| < 2^31 etc, + // therefore the following computation could be done with 64bit arithmetics. + dy1 * dx2 == dx1 * dy2; +} +inline bool SlopesEqual(const TEdge &e1, const TEdge &e2, bool UseFullInt64Range) + { return SlopesEqual(e1.Delta.X, e1.Delta.Y, e2.Delta.X, e2.Delta.Y, UseFullInt64Range); } +inline bool SlopesEqual(const IntPoint &pt1, const IntPoint &pt2, const IntPoint &pt3, bool UseFullInt64Range) + { return SlopesEqual(pt1.X-pt2.X, pt1.Y-pt2.Y, pt2.X-pt3.X, pt2.Y-pt3.Y, UseFullInt64Range); } +inline bool SlopesEqual(const IntPoint &pt1, const IntPoint &pt2, const IntPoint &pt3, const IntPoint &pt4, bool UseFullInt64Range) + { return SlopesEqual(pt1.X-pt2.X, pt1.Y-pt2.Y, pt3.X-pt4.X, pt3.Y-pt4.Y, UseFullInt64Range); } + +//------------------------------------------------------------------------------ + +inline bool IsHorizontal(TEdge &e) +{ + return e.Delta.Y == 0; +} +//------------------------------------------------------------------------------ + +inline double GetDx(const IntPoint &pt1, const IntPoint &pt2) +{ + return (pt1.Y == pt2.Y) ? + HORIZONTAL : (double)(pt2.X - pt1.X) / (pt2.Y - pt1.Y); +} +//--------------------------------------------------------------------------- + +inline cInt TopX(TEdge &edge, const cInt currentY) +{ + return (currentY == edge.Top.Y) ? + edge.Top.X : + edge.Bot.X + Round(edge.Dx *(currentY - edge.Bot.Y)); +} +//------------------------------------------------------------------------------ + +void IntersectPoint(TEdge &Edge1, TEdge &Edge2, IntPoint &ip) +{ +#ifdef use_xyz + ip.Z = 0; +#endif + + double b1, b2; + if (Edge1.Dx == Edge2.Dx) + { + ip.Y = Edge1.Curr.Y; + ip.X = TopX(Edge1, ip.Y); + return; + } + else if (Edge1.Delta.X == 0) + { + ip.X = Edge1.Bot.X; + if (IsHorizontal(Edge2)) + ip.Y = Edge2.Bot.Y; + else + { + b2 = Edge2.Bot.Y - (Edge2.Bot.X / Edge2.Dx); + ip.Y = Round(ip.X / Edge2.Dx + b2); + } + } + else if (Edge2.Delta.X == 0) + { + ip.X = Edge2.Bot.X; + if (IsHorizontal(Edge1)) + ip.Y = Edge1.Bot.Y; + else + { + b1 = Edge1.Bot.Y - (Edge1.Bot.X / Edge1.Dx); + ip.Y = Round(ip.X / Edge1.Dx + b1); + } + } + else + { + b1 = Edge1.Bot.X - Edge1.Bot.Y * Edge1.Dx; + b2 = Edge2.Bot.X - Edge2.Bot.Y * Edge2.Dx; + double q = (b2-b1) / (Edge1.Dx - Edge2.Dx); + ip.Y = Round(q); + ip.X = (std::fabs(Edge1.Dx) < std::fabs(Edge2.Dx)) ? + Round(Edge1.Dx * q + b1) : + Round(Edge2.Dx * q + b2); + } + + if (ip.Y < Edge1.Top.Y || ip.Y < Edge2.Top.Y) + { + if (Edge1.Top.Y > Edge2.Top.Y) + ip.Y = Edge1.Top.Y; + else + ip.Y = Edge2.Top.Y; + if (std::fabs(Edge1.Dx) < std::fabs(Edge2.Dx)) + ip.X = TopX(Edge1, ip.Y); + else + ip.X = TopX(Edge2, ip.Y); + } + //finally, don't allow 'ip' to be BELOW curr.Y (ie bottom of scanbeam) ... + if (ip.Y > Edge1.Curr.Y) + { + ip.Y = Edge1.Curr.Y; + //use the more vertical edge to derive X ... + if (std::fabs(Edge1.Dx) > std::fabs(Edge2.Dx)) + ip.X = TopX(Edge2, ip.Y); else + ip.X = TopX(Edge1, ip.Y); + } +} +//------------------------------------------------------------------------------ + +// Reverse a linked loop of points representing a closed polygon. +// This has a time complexity of O(n) +void ReversePolyPtLinks(OutPt *pp) +{ + if (!pp) return; + OutPt *pp1 = pp; + do { + OutPt *pp2 = pp1->Next; + pp1->Next = pp1->Prev; + pp1->Prev = pp2; + pp1 = pp2; + } while( pp1 != pp ); +} +//------------------------------------------------------------------------------ + +inline void InitEdge(TEdge* e, TEdge* eNext, TEdge* ePrev, const IntPoint& Pt) +{ + std::memset(e, 0, sizeof(TEdge)); + e->Next = eNext; + e->Prev = ePrev; + e->Curr = Pt; + e->OutIdx = Unassigned; +} +//------------------------------------------------------------------------------ + +void InitEdge2(TEdge& e, PolyType Pt) +{ + if (e.Curr.Y >= e.Next->Curr.Y) + { + e.Bot = e.Curr; + e.Top = e.Next->Curr; + } else + { + e.Top = e.Curr; + e.Bot = e.Next->Curr; + } + + e.Delta.X = (e.Top.X - e.Bot.X); + e.Delta.Y = (e.Top.Y - e.Bot.Y); + + if (e.Delta.Y == 0) e.Dx = HORIZONTAL; + else e.Dx = (double)(e.Delta.X) / e.Delta.Y; + + e.PolyTyp = Pt; +} +//------------------------------------------------------------------------------ + +// Called from ClipperBase::AddPathInternal() to remove collinear and duplicate points. +inline TEdge* RemoveEdge(TEdge* e) +{ + //removes e from double_linked_list (but without removing from memory) + e->Prev->Next = e->Next; + e->Next->Prev = e->Prev; + TEdge* result = e->Next; + e->Prev = 0; //flag as removed (see ClipperBase.Clear) + return result; +} +//------------------------------------------------------------------------------ + +inline void ReverseHorizontal(TEdge &e) +{ + //swap horizontal edges' Top and Bottom x's so they follow the natural + //progression of the bounds - ie so their xbots will align with the + //adjoining lower edge. [Helpful in the ProcessHorizontal() method.] + std::swap(e.Top.X, e.Bot.X); +#ifdef use_xyz + std::swap(e.Top.Z, e.Bot.Z); +#endif +} +//------------------------------------------------------------------------------ + +bool GetOverlapSegment(IntPoint pt1a, IntPoint pt1b, IntPoint pt2a, + IntPoint pt2b, IntPoint &pt1, IntPoint &pt2) +{ + //precondition: segments are Collinear. + if (std::abs(pt1a.X - pt1b.X) > std::abs(pt1a.Y - pt1b.Y)) + { + if (pt1a.X > pt1b.X) std::swap(pt1a, pt1b); + if (pt2a.X > pt2b.X) std::swap(pt2a, pt2b); + if (pt1a.X > pt2a.X) pt1 = pt1a; else pt1 = pt2a; + if (pt1b.X < pt2b.X) pt2 = pt1b; else pt2 = pt2b; + return pt1.X < pt2.X; + } else + { + if (pt1a.Y < pt1b.Y) std::swap(pt1a, pt1b); + if (pt2a.Y < pt2b.Y) std::swap(pt2a, pt2b); + if (pt1a.Y < pt2a.Y) pt1 = pt1a; else pt1 = pt2a; + if (pt1b.Y > pt2b.Y) pt2 = pt1b; else pt2 = pt2b; + return pt1.Y > pt2.Y; + } +} +//------------------------------------------------------------------------------ + +bool FirstIsBottomPt(const OutPt* btmPt1, const OutPt* btmPt2) +{ + OutPt *p = btmPt1->Prev; + while ((p->Pt == btmPt1->Pt) && (p != btmPt1)) p = p->Prev; + double dx1p = std::fabs(GetDx(btmPt1->Pt, p->Pt)); + p = btmPt1->Next; + while ((p->Pt == btmPt1->Pt) && (p != btmPt1)) p = p->Next; + double dx1n = std::fabs(GetDx(btmPt1->Pt, p->Pt)); + + p = btmPt2->Prev; + while ((p->Pt == btmPt2->Pt) && (p != btmPt2)) p = p->Prev; + double dx2p = std::fabs(GetDx(btmPt2->Pt, p->Pt)); + p = btmPt2->Next; + while ((p->Pt == btmPt2->Pt) && (p != btmPt2)) p = p->Next; + double dx2n = std::fabs(GetDx(btmPt2->Pt, p->Pt)); + return (dx1p >= dx2p && dx1p >= dx2n) || (dx1n >= dx2p && dx1n >= dx2n); +} +//------------------------------------------------------------------------------ + +// Called by GetLowermostRec() +OutPt* GetBottomPt(OutPt *pp) +{ + OutPt* dups = 0; + OutPt* p = pp->Next; + while (p != pp) + { + if (p->Pt.Y > pp->Pt.Y) + { + pp = p; + dups = 0; + } + else if (p->Pt.Y == pp->Pt.Y && p->Pt.X <= pp->Pt.X) + { + if (p->Pt.X < pp->Pt.X) + { + dups = 0; + pp = p; + } else + { + if (p->Next != pp && p->Prev != pp) dups = p; + } + } + p = p->Next; + } + if (dups) + { + //there appears to be at least 2 vertices at BottomPt so ... + while (dups != p) + { + if (!FirstIsBottomPt(p, dups)) pp = dups; + dups = dups->Next; + while (dups->Pt != pp->Pt) dups = dups->Next; + } + } + return pp; +} +//------------------------------------------------------------------------------ + +bool Pt2IsBetweenPt1AndPt3(const IntPoint &pt1, + const IntPoint &pt2, const IntPoint &pt3) +{ + if ((pt1 == pt3) || (pt1 == pt2) || (pt3 == pt2)) + return false; + else if (pt1.X != pt3.X) + return (pt2.X > pt1.X) == (pt2.X < pt3.X); + else + return (pt2.Y > pt1.Y) == (pt2.Y < pt3.Y); +} +//------------------------------------------------------------------------------ + +bool HorzSegmentsOverlap(cInt seg1a, cInt seg1b, cInt seg2a, cInt seg2b) +{ + if (seg1a > seg1b) std::swap(seg1a, seg1b); + if (seg2a > seg2b) std::swap(seg2a, seg2b); + return (seg1a < seg2b) && (seg2a < seg1b); +} + +//------------------------------------------------------------------------------ +// ClipperBase class methods ... +//------------------------------------------------------------------------------ + +// Called from ClipperBase::AddPath() to verify the scale of the input polygon coordinates. +inline void RangeTest(const IntPoint& Pt, bool& useFullRange) +{ + if (useFullRange) + { + if (Pt.X > hiRange || Pt.Y > hiRange || -Pt.X > hiRange || -Pt.Y > hiRange) + throw clipperException("Coordinate outside allowed range"); + } + else if (Pt.X > loRange|| Pt.Y > loRange || -Pt.X > loRange || -Pt.Y > loRange) + { + useFullRange = true; + RangeTest(Pt, useFullRange); + } +} +//------------------------------------------------------------------------------ + +// Called from ClipperBase::AddPath() to construct the Local Minima List. +// Find a local minimum edge on the path starting with E. +inline TEdge* FindNextLocMin(TEdge* E) +{ + for (;;) + { + while (E->Bot != E->Prev->Bot || E->Curr == E->Top) E = E->Next; + if (!IsHorizontal(*E) && !IsHorizontal(*E->Prev)) break; + while (IsHorizontal(*E->Prev)) E = E->Prev; + TEdge* E2 = E; + while (IsHorizontal(*E)) E = E->Next; + if (E->Top.Y == E->Prev->Bot.Y) continue; //ie just an intermediate horz. + if (E2->Prev->Bot.X < E->Bot.X) E = E2; + break; + } + return E; +} +//------------------------------------------------------------------------------ + +// Called from ClipperBase::AddPath(). +TEdge* ClipperBase::ProcessBound(TEdge* E, bool NextIsForward) +{ + TEdge *Result = E; + TEdge *Horz = 0; + + if (E->OutIdx == Skip) + { + //if edges still remain in the current bound beyond the skip edge then + //create another LocMin and call ProcessBound once more + if (NextIsForward) + { + while (E->Top.Y == E->Next->Bot.Y) E = E->Next; + //don't include top horizontals when parsing a bound a second time, + //they will be contained in the opposite bound ... + while (E != Result && IsHorizontal(*E)) E = E->Prev; + } + else + { + while (E->Top.Y == E->Prev->Bot.Y) E = E->Prev; + while (E != Result && IsHorizontal(*E)) E = E->Next; + } + + if (E == Result) + { + if (NextIsForward) Result = E->Next; + else Result = E->Prev; + } + else + { + //there are more edges in the bound beyond result starting with E + if (NextIsForward) + E = Result->Next; + else + E = Result->Prev; + LocalMinimum locMin; + locMin.Y = E->Bot.Y; + locMin.LeftBound = 0; + locMin.RightBound = E; + E->WindDelta = 0; + Result = ProcessBound(E, NextIsForward); + m_MinimaList.push_back(locMin); + } + return Result; + } + + TEdge *EStart; + + if (IsHorizontal(*E)) + { + //We need to be careful with open paths because this may not be a + //true local minima (ie E may be following a skip edge). + //Also, consecutive horz. edges may start heading left before going right. + if (NextIsForward) + EStart = E->Prev; + else + EStart = E->Next; + if (IsHorizontal(*EStart)) //ie an adjoining horizontal skip edge + { + if (EStart->Bot.X != E->Bot.X && EStart->Top.X != E->Bot.X) + ReverseHorizontal(*E); + } + else if (EStart->Bot.X != E->Bot.X) + ReverseHorizontal(*E); + } + + EStart = E; + if (NextIsForward) + { + while (Result->Top.Y == Result->Next->Bot.Y && Result->Next->OutIdx != Skip) + Result = Result->Next; + if (IsHorizontal(*Result) && Result->Next->OutIdx != Skip) + { + //nb: at the top of a bound, horizontals are added to the bound + //only when the preceding edge attaches to the horizontal's left vertex + //unless a Skip edge is encountered when that becomes the top divide + Horz = Result; + while (IsHorizontal(*Horz->Prev)) Horz = Horz->Prev; + if (Horz->Prev->Top.X > Result->Next->Top.X) Result = Horz->Prev; + } + while (E != Result) + { + E->NextInLML = E->Next; + if (IsHorizontal(*E) && E != EStart && + E->Bot.X != E->Prev->Top.X) ReverseHorizontal(*E); + E = E->Next; + } + if (IsHorizontal(*E) && E != EStart && E->Bot.X != E->Prev->Top.X) + ReverseHorizontal(*E); + Result = Result->Next; //move to the edge just beyond current bound + } else + { + while (Result->Top.Y == Result->Prev->Bot.Y && Result->Prev->OutIdx != Skip) + Result = Result->Prev; + if (IsHorizontal(*Result) && Result->Prev->OutIdx != Skip) + { + Horz = Result; + while (IsHorizontal(*Horz->Next)) Horz = Horz->Next; + if (Horz->Next->Top.X == Result->Prev->Top.X || + Horz->Next->Top.X > Result->Prev->Top.X) Result = Horz->Next; + } + + while (E != Result) + { + E->NextInLML = E->Prev; + if (IsHorizontal(*E) && E != EStart && E->Bot.X != E->Next->Top.X) + ReverseHorizontal(*E); + E = E->Prev; + } + if (IsHorizontal(*E) && E != EStart && E->Bot.X != E->Next->Top.X) + ReverseHorizontal(*E); + Result = Result->Prev; //move to the edge just beyond current bound + } + + return Result; +} +//------------------------------------------------------------------------------ + +bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed) +{ + PROFILE_FUNC(); + // Remove duplicate end point from a closed input path. + // Remove duplicate points from the end of the input path. + int highI = (int)pg.size() -1; + if (Closed) + while (highI > 0 && (pg[highI] == pg[0])) + --highI; + while (highI > 0 && (pg[highI] == pg[highI -1])) + --highI; + if ((Closed && highI < 2) || (!Closed && highI < 1)) + return false; + + // Allocate a new edge array. + std::vector edges(highI + 1); + // Fill in the edge array. + bool result = AddPathInternal(pg, highI, PolyTyp, Closed, edges.data()); + if (result) + // Success, remember the edge array. + m_edges.emplace_back(std::move(edges)); + return result; +} + +bool ClipperBase::AddPaths(const Paths &ppg, PolyType PolyTyp, bool Closed) +{ + PROFILE_FUNC(); + std::vector num_edges(ppg.size(), 0); + int num_edges_total = 0; + for (size_t i = 0; i < ppg.size(); ++ i) { + const Path &pg = ppg[i]; + // Remove duplicate end point from a closed input path. + // Remove duplicate points from the end of the input path. + int highI = (int)pg.size() -1; + if (Closed) + while (highI > 0 && (pg[highI] == pg[0])) + --highI; + while (highI > 0 && (pg[highI] == pg[highI -1])) + --highI; + if ((Closed && highI < 2) || (!Closed && highI < 1)) + highI = -1; + num_edges[i] = highI + 1; + num_edges_total += highI + 1; + } + if (num_edges_total == 0) + return false; + + // Allocate a new edge array. + std::vector edges(num_edges_total); + // Fill in the edge array. + bool result = false; + TEdge *p_edge = edges.data(); + for (Paths::size_type i = 0; i < ppg.size(); ++i) + if (num_edges[i]) { + bool res = AddPathInternal(ppg[i], num_edges[i] - 1, PolyTyp, Closed, p_edge); + if (res) { + p_edge += num_edges[i]; + result = true; + } + } + if (result) + // At least some edges were generated. Remember the edge array. + m_edges.emplace_back(std::move(edges)); + return result; +} + +bool ClipperBase::AddPathInternal(const Path &pg, int highI, PolyType PolyTyp, bool Closed, TEdge* edges) +{ + PROFILE_FUNC(); +#ifdef use_lines + if (!Closed && PolyTyp == ptClip) + throw clipperException("AddPath: Open paths must be subject."); +#else + if (!Closed) + throw clipperException("AddPath: Open paths have been disabled."); +#endif + + assert(highI >= 0 && highI < pg.size()); + + //1. Basic (first) edge initialization ... + try + { + edges[1].Curr = pg[1]; + RangeTest(pg[0], m_UseFullRange); + RangeTest(pg[highI], m_UseFullRange); + InitEdge(&edges[0], &edges[1], &edges[highI], pg[0]); + InitEdge(&edges[highI], &edges[0], &edges[highI-1], pg[highI]); + for (int i = highI - 1; i >= 1; --i) + { + RangeTest(pg[i], m_UseFullRange); + InitEdge(&edges[i], &edges[i+1], &edges[i-1], pg[i]); + } + } + catch(...) + { + throw; //range test fails + } + TEdge *eStart = &edges[0]; + + //2. Remove duplicate vertices, and (when closed) collinear edges ... + TEdge *E = eStart, *eLoopStop = eStart; + for (;;) + { + //nb: allows matching start and end points when not Closed ... + if (E->Curr == E->Next->Curr && (Closed || E->Next != eStart)) + { + if (E == E->Next) break; + if (E == eStart) eStart = E->Next; + E = RemoveEdge(E); + eLoopStop = E; + continue; + } + if (E->Prev == E->Next) + break; //only two vertices + else if (Closed && + SlopesEqual(E->Prev->Curr, E->Curr, E->Next->Curr, m_UseFullRange) && + (!m_PreserveCollinear || + !Pt2IsBetweenPt1AndPt3(E->Prev->Curr, E->Curr, E->Next->Curr))) + { + //Collinear edges are allowed for open paths but in closed paths + //the default is to merge adjacent collinear edges into a single edge. + //However, if the PreserveCollinear property is enabled, only overlapping + //collinear edges (ie spikes) will be removed from closed paths. + if (E == eStart) eStart = E->Next; + E = RemoveEdge(E); + E = E->Prev; + eLoopStop = E; + continue; + } + E = E->Next; + if ((E == eLoopStop) || (!Closed && E->Next == eStart)) break; + } + + if ((!Closed && (E == E->Next)) || (Closed && (E->Prev == E->Next))) + { + return false; + } + + if (!Closed) + { + m_HasOpenPaths = true; + eStart->Prev->OutIdx = Skip; + } + + //3. Do second stage of edge initialization ... + // IsFlat means all vertices have the same Y coordinate. + bool IsFlat = true; + E = eStart; + do + { + InitEdge2(*E, PolyTyp); + E = E->Next; + if (IsFlat && E->Curr.Y != eStart->Curr.Y) IsFlat = false; + } + while (E != eStart); + + //4. Finally, add edge bounds to LocalMinima list ... + + //Totally flat paths must be handled differently when adding them + //to LocalMinima list to avoid endless loops etc ... + if (IsFlat) + { + if (Closed) + { + return false; + } + E->Prev->OutIdx = Skip; + LocalMinimum locMin; + locMin.Y = E->Bot.Y; + locMin.LeftBound = 0; + locMin.RightBound = E; + locMin.RightBound->Side = esRight; + locMin.RightBound->WindDelta = 0; + for (;;) + { + if (E->Bot.X != E->Prev->Top.X) ReverseHorizontal(*E); + if (E->Next->OutIdx == Skip) break; + E->NextInLML = E->Next; + E = E->Next; + } + m_MinimaList.push_back(locMin); + return true; + } + + bool leftBoundIsForward; + TEdge* EMin = 0; + + //workaround to avoid an endless loop in the while loop below when + //open paths have matching start and end points ... + if (E->Prev->Bot == E->Prev->Top) E = E->Next; + + // Find local minima and store them into a Local Minima List. + // Multiple Local Minima could be created for a single path. + for (;;) + { + E = FindNextLocMin(E); + if (E == EMin) break; + else if (!EMin) EMin = E; + + //E and E.Prev now share a local minima (left aligned if horizontal). + //Compare their slopes to find which starts which bound ... + LocalMinimum locMin; + locMin.Y = E->Bot.Y; + if (E->Dx < E->Prev->Dx) + { + locMin.LeftBound = E->Prev; + locMin.RightBound = E; + leftBoundIsForward = false; //Q.nextInLML = Q.prev + } else + { + locMin.LeftBound = E; + locMin.RightBound = E->Prev; + leftBoundIsForward = true; //Q.nextInLML = Q.next + } + locMin.LeftBound->Side = esLeft; + locMin.RightBound->Side = esRight; + + if (!Closed) locMin.LeftBound->WindDelta = 0; + else if (locMin.LeftBound->Next == locMin.RightBound) + locMin.LeftBound->WindDelta = -1; + else locMin.LeftBound->WindDelta = 1; + locMin.RightBound->WindDelta = -locMin.LeftBound->WindDelta; + + E = ProcessBound(locMin.LeftBound, leftBoundIsForward); + if (E->OutIdx == Skip) E = ProcessBound(E, leftBoundIsForward); + + TEdge* E2 = ProcessBound(locMin.RightBound, !leftBoundIsForward); + if (E2->OutIdx == Skip) E2 = ProcessBound(E2, !leftBoundIsForward); + + if (locMin.LeftBound->OutIdx == Skip) + locMin.LeftBound = 0; + else if (locMin.RightBound->OutIdx == Skip) + locMin.RightBound = 0; + m_MinimaList.push_back(locMin); + if (!leftBoundIsForward) E = E2; + } + return true; +} +//------------------------------------------------------------------------------ + +void ClipperBase::Clear() +{ + PROFILE_FUNC(); + m_MinimaList.clear(); + m_edges.clear(); + m_UseFullRange = false; + m_HasOpenPaths = false; +} +//------------------------------------------------------------------------------ + +// Initialize the Local Minima List: +// Sort the LML entries, initialize the left / right bound edges of each Local Minima. +void ClipperBase::Reset() +{ + PROFILE_FUNC(); + if (m_MinimaList.empty()) return; //ie nothing to process + std::sort(m_MinimaList.begin(), m_MinimaList.end(), [](const LocalMinimum& lm1, const LocalMinimum& lm2){ return lm1.Y < lm2.Y; }); + + //reset all edges ... + for (LocalMinimum &lm : m_MinimaList) { + TEdge* e = lm.LeftBound; + if (e) + { + e->Curr = e->Bot; + e->Side = esLeft; + e->OutIdx = Unassigned; + } + + e = lm.RightBound; + if (e) + { + e->Curr = e->Bot; + e->Side = esRight; + e->OutIdx = Unassigned; + } + } +} +//------------------------------------------------------------------------------ + +// Get bounds of the edges referenced by the Local Minima List. +// Returns (0,0,0,0) for an empty rectangle. +IntRect ClipperBase::GetBounds() +{ + PROFILE_FUNC(); + IntRect result; + auto lm = m_MinimaList.begin(); + if (lm == m_MinimaList.end()) + { + result.left = result.top = result.right = result.bottom = 0; + return result; + } + result.left = lm->LeftBound->Bot.X; + result.top = lm->LeftBound->Bot.Y; + result.right = lm->LeftBound->Bot.X; + result.bottom = lm->LeftBound->Bot.Y; + while (lm != m_MinimaList.end()) + { + result.bottom = std::max(result.bottom, lm->LeftBound->Bot.Y); + TEdge* e = lm->LeftBound; + for (;;) { + TEdge* bottomE = e; + while (e->NextInLML) + { + if (e->Bot.X < result.left) result.left = e->Bot.X; + if (e->Bot.X > result.right) result.right = e->Bot.X; + e = e->NextInLML; + } + result.left = std::min(result.left, e->Bot.X); + result.right = std::max(result.right, e->Bot.X); + result.left = std::min(result.left, e->Top.X); + result.right = std::max(result.right, e->Top.X); + result.top = std::min(result.top, e->Top.Y); + if (bottomE == lm->LeftBound) e = lm->RightBound; + else break; + } + ++lm; + } + return result; +} + +//------------------------------------------------------------------------------ +// TClipper methods ... +//------------------------------------------------------------------------------ + +Clipper::Clipper(int initOptions) : + ClipperBase(), + m_OutPtsFree(nullptr), + m_OutPtsChunkSize(32), + m_OutPtsChunkLast(32), + m_ActiveEdges(nullptr), + m_SortedEdges(nullptr) +{ + m_ReverseOutput = ((initOptions & ioReverseSolution) != 0); + m_StrictSimple = ((initOptions & ioStrictlySimple) != 0); + m_PreserveCollinear = ((initOptions & ioPreserveCollinear) != 0); + m_HasOpenPaths = false; +#ifdef use_xyz + m_ZFill = 0; +#endif +} +//------------------------------------------------------------------------------ + +void Clipper::Reset() +{ + PROFILE_FUNC(); + ClipperBase::Reset(); + m_Scanbeam = std::priority_queue(); + m_Maxima.clear(); + m_ActiveEdges = 0; + m_SortedEdges = 0; + for (auto lm = m_MinimaList.rbegin(); lm != m_MinimaList.rend(); ++lm) + m_Scanbeam.push(lm->Y); +} + +//------------------------------------------------------------------------------ + +bool Clipper::Execute(ClipType clipType, Paths &solution, + PolyFillType subjFillType, PolyFillType clipFillType) +{ + PROFILE_FUNC(); + if (m_HasOpenPaths) + throw clipperException("Error: PolyTree struct is needed for open path clipping."); + solution.resize(0); + m_SubjFillType = subjFillType; + m_ClipFillType = clipFillType; + m_ClipType = clipType; + m_UsingPolyTree = false; + bool succeeded = ExecuteInternal(); + if (succeeded) BuildResult(solution); + DisposeAllOutRecs(); + return succeeded; +} +//------------------------------------------------------------------------------ + +bool Clipper::Execute(ClipType clipType, PolyTree& polytree, + PolyFillType subjFillType, PolyFillType clipFillType) +{ + PROFILE_FUNC(); + m_SubjFillType = subjFillType; + m_ClipFillType = clipFillType; + m_ClipType = clipType; + m_UsingPolyTree = true; + bool succeeded = ExecuteInternal(); + if (succeeded) BuildResult2(polytree); + DisposeAllOutRecs(); + return succeeded; +} +//------------------------------------------------------------------------------ + +bool Clipper::ExecuteInternal() +{ + PROFILE_FUNC(); + bool succeeded = true; + try { + PROFILE_BLOCK(Clipper_ExecuteInternal_Process); + Reset(); + if (m_MinimaList.empty()) return true; + cInt botY = m_Scanbeam.top(); + do { m_Scanbeam.pop(); } while (! m_Scanbeam.empty() && botY == m_Scanbeam.top()); + do { + InsertLocalMinimaIntoAEL(botY); + ProcessHorizontals(); + m_GhostJoins.clear(); + if (m_Scanbeam.empty()) break; + cInt topY = m_Scanbeam.top(); + do { m_Scanbeam.pop(); } while (! m_Scanbeam.empty() && topY == m_Scanbeam.top()); + succeeded = ProcessIntersections(topY); + if (!succeeded) break; + ProcessEdgesAtTopOfScanbeam(topY); + botY = topY; + } while (!m_Scanbeam.empty() || !m_MinimaList.empty()); + } + catch(...) + { + succeeded = false; + } + + if (succeeded) + { + PROFILE_BLOCK(Clipper_ExecuteInternal_Fix); + + //fix orientations ... + //FIXME Vojtech: Does it not invalidate the loop hierarchy maintained as OutRec::FirstLeft pointers? + //FIXME Vojtech: The area is calculated with floats, it may not be numerically stable! + { + PROFILE_BLOCK(Clipper_ExecuteInternal_Fix_orientations); + for (OutRec *outRec : m_PolyOuts) + if (outRec->Pts && !outRec->IsOpen && (outRec->IsHole ^ m_ReverseOutput) == (Area(*outRec) > 0)) + ReversePolyPtLinks(outRec->Pts); + } + + JoinCommonEdges(); + + //unfortunately FixupOutPolygon() must be done after JoinCommonEdges() + { + PROFILE_BLOCK(Clipper_ExecuteInternal_Fix_fixup); + for (OutRec *outRec : m_PolyOuts) + if (outRec->Pts) { + if (outRec->IsOpen) + // Removes duplicate points. + FixupOutPolyline(*outRec); + else + // Removes duplicate points and simplifies consecutive parallel edges by removing the middle vertex. + FixupOutPolygon(*outRec); + } + } + // For each polygon, search for exactly duplicate non-successive points. + // If such a point is found, the loop is split into two pieces. + // Search for the duplicate points is O(n^2)! + // http://www.angusj.com/delphi/clipper/documentation/Docs/Units/ClipperLib/Classes/Clipper/Properties/StrictlySimple.htm + if (m_StrictSimple) DoSimplePolygons(); + } + + m_Joins.clear(); + m_GhostJoins.clear(); + return succeeded; +} +//------------------------------------------------------------------------------ + +OutPt* Clipper::AllocateOutPt() +{ + OutPt *pt; + if (m_OutPtsFree) { + // Recycle some of the already released points. + pt = m_OutPtsFree; + m_OutPtsFree = pt->Next; + } else if (m_OutPtsChunkLast < m_OutPtsChunkSize) { + // Get a point from the last chunk. + pt = m_OutPts.back() + (m_OutPtsChunkLast ++); + } else { + // The last chunk is full. Allocate a new one. + m_OutPts.push_back(new OutPt[m_OutPtsChunkSize]); + m_OutPtsChunkLast = 1; + pt = m_OutPts.back(); + } + return pt; +} + +void Clipper::DisposeAllOutRecs() +{ + for (OutPt *pts : m_OutPts) + delete[] pts; + for (OutRec *rec : m_PolyOuts) + delete rec; + m_OutPts.clear(); + m_OutPtsFree = nullptr; + m_OutPtsChunkLast = m_OutPtsChunkSize; + m_PolyOuts.clear(); +} +//------------------------------------------------------------------------------ + +void Clipper::SetWindingCount(TEdge &edge) const +{ + TEdge *e = edge.PrevInAEL; + //find the edge of the same polytype that immediately preceeds 'edge' in AEL + while (e && ((e->PolyTyp != edge.PolyTyp) || (e->WindDelta == 0))) e = e->PrevInAEL; + if (!e) + { + edge.WindCnt = (edge.WindDelta == 0 ? 1 : edge.WindDelta); + edge.WindCnt2 = 0; + e = m_ActiveEdges; //ie get ready to calc WindCnt2 + } + else if (edge.WindDelta == 0 && m_ClipType != ctUnion) + { + edge.WindCnt = 1; + edge.WindCnt2 = e->WindCnt2; + e = e->NextInAEL; //ie get ready to calc WindCnt2 + } + else if (IsEvenOddFillType(edge)) + { + //EvenOdd filling ... + if (edge.WindDelta == 0) + { + //are we inside a subj polygon ... + bool Inside = true; + TEdge *e2 = e->PrevInAEL; + while (e2) + { + if (e2->PolyTyp == e->PolyTyp && e2->WindDelta != 0) + Inside = !Inside; + e2 = e2->PrevInAEL; + } + edge.WindCnt = (Inside ? 0 : 1); + } + else + { + edge.WindCnt = edge.WindDelta; + } + edge.WindCnt2 = e->WindCnt2; + e = e->NextInAEL; //ie get ready to calc WindCnt2 + } + else + { + //nonZero, Positive or Negative filling ... + if (e->WindCnt * e->WindDelta < 0) + { + //prev edge is 'decreasing' WindCount (WC) toward zero + //so we're outside the previous polygon ... + if (std::abs(e->WindCnt) > 1) + { + //outside prev poly but still inside another. + //when reversing direction of prev poly use the same WC + if (e->WindDelta * edge.WindDelta < 0) edge.WindCnt = e->WindCnt; + //otherwise continue to 'decrease' WC ... + else edge.WindCnt = e->WindCnt + edge.WindDelta; + } + else + //now outside all polys of same polytype so set own WC ... + edge.WindCnt = (edge.WindDelta == 0 ? 1 : edge.WindDelta); + } else + { + //prev edge is 'increasing' WindCount (WC) away from zero + //so we're inside the previous polygon ... + if (edge.WindDelta == 0) + edge.WindCnt = (e->WindCnt < 0 ? e->WindCnt - 1 : e->WindCnt + 1); + //if wind direction is reversing prev then use same WC + else if (e->WindDelta * edge.WindDelta < 0) edge.WindCnt = e->WindCnt; + //otherwise add to WC ... + else edge.WindCnt = e->WindCnt + edge.WindDelta; + } + edge.WindCnt2 = e->WindCnt2; + e = e->NextInAEL; //ie get ready to calc WindCnt2 + } + + //update WindCnt2 ... + if (IsEvenOddAltFillType(edge)) + { + //EvenOdd filling ... + while (e != &edge) + { + if (e->WindDelta != 0) + edge.WindCnt2 = (edge.WindCnt2 == 0 ? 1 : 0); + e = e->NextInAEL; + } + } else + { + //nonZero, Positive or Negative filling ... + while ( e != &edge ) + { + edge.WindCnt2 += e->WindDelta; + e = e->NextInAEL; + } + } +} +//------------------------------------------------------------------------------ + +bool Clipper::IsContributing(const TEdge& edge) const +{ + PolyFillType pft, pft2; + if (edge.PolyTyp == ptSubject) + { + pft = m_SubjFillType; + pft2 = m_ClipFillType; + } else + { + pft = m_ClipFillType; + pft2 = m_SubjFillType; + } + + switch(pft) + { + case pftEvenOdd: + //return false if a subj line has been flagged as inside a subj polygon + if (edge.WindDelta == 0 && edge.WindCnt != 1) return false; + break; + case pftNonZero: + if (std::abs(edge.WindCnt) != 1) return false; + break; + case pftPositive: + if (edge.WindCnt != 1) return false; + break; + default: //pftNegative + if (edge.WindCnt != -1) return false; + } + + switch(m_ClipType) + { + case ctIntersection: + switch(pft2) + { + case pftEvenOdd: + case pftNonZero: + return (edge.WindCnt2 != 0); + case pftPositive: + return (edge.WindCnt2 > 0); + default: + return (edge.WindCnt2 < 0); + } + break; + case ctUnion: + switch(pft2) + { + case pftEvenOdd: + case pftNonZero: + return (edge.WindCnt2 == 0); + case pftPositive: + return (edge.WindCnt2 <= 0); + default: + return (edge.WindCnt2 >= 0); + } + break; + case ctDifference: + if (edge.PolyTyp == ptSubject) + switch(pft2) + { + case pftEvenOdd: + case pftNonZero: + return (edge.WindCnt2 == 0); + case pftPositive: + return (edge.WindCnt2 <= 0); + default: + return (edge.WindCnt2 >= 0); + } + else + switch(pft2) + { + case pftEvenOdd: + case pftNonZero: + return (edge.WindCnt2 != 0); + case pftPositive: + return (edge.WindCnt2 > 0); + default: + return (edge.WindCnt2 < 0); + } + break; + case ctXor: + if (edge.WindDelta == 0) //XOr always contributing unless open + switch(pft2) + { + case pftEvenOdd: + case pftNonZero: + return (edge.WindCnt2 == 0); + case pftPositive: + return (edge.WindCnt2 <= 0); + default: + return (edge.WindCnt2 >= 0); + } + else + return true; + break; + default: + return true; + } +} +//------------------------------------------------------------------------------ + +// Called from Clipper::InsertLocalMinimaIntoAEL() and Clipper::IntersectEdges(). +OutPt* Clipper::AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &Pt) +{ + PROFILE_FUNC(); + OutPt* result; + TEdge *e, *prevE; + if (IsHorizontal(*e2) || ( e1->Dx > e2->Dx )) + { + result = AddOutPt(e1, Pt); + e2->OutIdx = e1->OutIdx; + e1->Side = esLeft; + e2->Side = esRight; + e = e1; + if (e->PrevInAEL == e2) + prevE = e2->PrevInAEL; + else + prevE = e->PrevInAEL; + } else + { + result = AddOutPt(e2, Pt); + e1->OutIdx = e2->OutIdx; + e1->Side = esRight; + e2->Side = esLeft; + e = e2; + if (e->PrevInAEL == e1) + prevE = e1->PrevInAEL; + else + prevE = e->PrevInAEL; + } + + if (prevE && prevE->OutIdx >= 0 && + (TopX(*prevE, Pt.Y) == TopX(*e, Pt.Y)) && + SlopesEqual(*e, *prevE, m_UseFullRange) && + (e->WindDelta != 0) && (prevE->WindDelta != 0)) + { + OutPt* outPt = AddOutPt(prevE, Pt); + m_Joins.emplace_back(Join(result, outPt, e->Top)); + } + return result; +} +//------------------------------------------------------------------------------ + +void Clipper::AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &Pt) +{ + AddOutPt( e1, Pt ); + if (e2->WindDelta == 0) AddOutPt(e2, Pt); + if( e1->OutIdx == e2->OutIdx ) + { + e1->OutIdx = Unassigned; + e2->OutIdx = Unassigned; + } + else if (e1->OutIdx < e2->OutIdx) + AppendPolygon(e1, e2); + else + AppendPolygon(e2, e1); +} +//------------------------------------------------------------------------------ + +void Clipper::AddEdgeToSEL(TEdge *edge) +{ + //SEL pointers in PEdge are reused to build a list of horizontal edges. + //However, we don't need to worry about order with horizontal edge processing. + if( !m_SortedEdges ) + { + m_SortedEdges = edge; + edge->PrevInSEL = 0; + edge->NextInSEL = 0; + } + else + { + edge->NextInSEL = m_SortedEdges; + edge->PrevInSEL = 0; + m_SortedEdges->PrevInSEL = edge; + m_SortedEdges = edge; + } +} +//------------------------------------------------------------------------------ + +void Clipper::CopyAELToSEL() +{ + TEdge* e = m_ActiveEdges; + m_SortedEdges = e; + while ( e ) + { + e->PrevInSEL = e->PrevInAEL; + e->NextInSEL = e->NextInAEL; + e = e->NextInAEL; + } +} + +//------------------------------------------------------------------------------ + +// Called from Clipper::ExecuteInternal() +void Clipper::InsertLocalMinimaIntoAEL(const cInt botY) +{ + PROFILE_FUNC(); + while (!m_MinimaList.empty() && m_MinimaList.back().Y == botY) + { + TEdge* lb = m_MinimaList.back().LeftBound; + TEdge* rb = m_MinimaList.back().RightBound; + m_MinimaList.pop_back(); + + OutPt *Op1 = 0; + if (!lb) + { + //nb: don't insert LB into either AEL or SEL + InsertEdgeIntoAEL(rb, 0); + SetWindingCount(*rb); + if (IsContributing(*rb)) + Op1 = AddOutPt(rb, rb->Bot); + } + else if (!rb) + { + InsertEdgeIntoAEL(lb, 0); + SetWindingCount(*lb); + if (IsContributing(*lb)) + Op1 = AddOutPt(lb, lb->Bot); + m_Scanbeam.push(lb->Top.Y); + } + else + { + InsertEdgeIntoAEL(lb, 0); + InsertEdgeIntoAEL(rb, lb); + SetWindingCount( *lb ); + rb->WindCnt = lb->WindCnt; + rb->WindCnt2 = lb->WindCnt2; + if (IsContributing(*lb)) + Op1 = AddLocalMinPoly(lb, rb, lb->Bot); + m_Scanbeam.push(lb->Top.Y); + } + + if (rb) + { + if(IsHorizontal(*rb)) AddEdgeToSEL(rb); + else m_Scanbeam.push(rb->Top.Y); + } + + if (!lb || !rb) continue; + + //if any output polygons share an edge, they'll need joining later ... + if (Op1 && IsHorizontal(*rb) && + m_GhostJoins.size() > 0 && (rb->WindDelta != 0)) + { + for (Join &jr : m_GhostJoins) + //if the horizontal Rb and a 'ghost' horizontal overlap, then convert + //the 'ghost' join to a real join ready for later ... + if (HorzSegmentsOverlap(jr.OutPt1->Pt.X, jr.OffPt.X, rb->Bot.X, rb->Top.X)) + m_Joins.emplace_back(Join(jr.OutPt1, Op1, jr.OffPt)); + } + + if (lb->OutIdx >= 0 && lb->PrevInAEL && + lb->PrevInAEL->Curr.X == lb->Bot.X && + lb->PrevInAEL->OutIdx >= 0 && + SlopesEqual(*lb->PrevInAEL, *lb, m_UseFullRange) && + (lb->WindDelta != 0) && (lb->PrevInAEL->WindDelta != 0)) + { + OutPt *Op2 = AddOutPt(lb->PrevInAEL, lb->Bot); + m_Joins.emplace_back(Join(Op1, Op2, lb->Top)); + } + + if(lb->NextInAEL != rb) + { + + if (rb->OutIdx >= 0 && rb->PrevInAEL->OutIdx >= 0 && + SlopesEqual(*rb->PrevInAEL, *rb, m_UseFullRange) && + (rb->WindDelta != 0) && (rb->PrevInAEL->WindDelta != 0)) + { + OutPt *Op2 = AddOutPt(rb->PrevInAEL, rb->Bot); + m_Joins.emplace_back(Join(Op1, Op2, rb->Top)); + } + + TEdge* e = lb->NextInAEL; + if (e) + { + while( e != rb ) + { + //nb: For calculating winding counts etc, IntersectEdges() assumes + //that param1 will be to the Right of param2 ABOVE the intersection ... + IntersectEdges(rb , e , lb->Curr); //order important here + e = e->NextInAEL; + } + } + } + + } +} +//------------------------------------------------------------------------------ + +void Clipper::DeleteFromAEL(TEdge *e) +{ + TEdge* AelPrev = e->PrevInAEL; + TEdge* AelNext = e->NextInAEL; + if( !AelPrev && !AelNext && (e != m_ActiveEdges) ) return; //already deleted + if( AelPrev ) AelPrev->NextInAEL = AelNext; + else m_ActiveEdges = AelNext; + if( AelNext ) AelNext->PrevInAEL = AelPrev; + e->NextInAEL = 0; + e->PrevInAEL = 0; +} +//------------------------------------------------------------------------------ + +void Clipper::DeleteFromSEL(TEdge *e) +{ + TEdge* SelPrev = e->PrevInSEL; + TEdge* SelNext = e->NextInSEL; + if( !SelPrev && !SelNext && (e != m_SortedEdges) ) return; //already deleted + if( SelPrev ) SelPrev->NextInSEL = SelNext; + else m_SortedEdges = SelNext; + if( SelNext ) SelNext->PrevInSEL = SelPrev; + e->NextInSEL = 0; + e->PrevInSEL = 0; +} +//------------------------------------------------------------------------------ + +#ifdef use_xyz +void Clipper::SetZ(IntPoint& pt, TEdge& e1, TEdge& e2) +{ + if (pt.Z != 0 || !m_ZFill) return; + else if (pt == e1.Bot) pt.Z = e1.Bot.Z; + else if (pt == e1.Top) pt.Z = e1.Top.Z; + else if (pt == e2.Bot) pt.Z = e2.Bot.Z; + else if (pt == e2.Top) pt.Z = e2.Top.Z; + else (*m_ZFill)(e1.Bot, e1.Top, e2.Bot, e2.Top, pt); +} +//------------------------------------------------------------------------------ +#endif + +void Clipper::IntersectEdges(TEdge *e1, TEdge *e2, IntPoint &Pt) +{ + bool e1Contributing = ( e1->OutIdx >= 0 ); + bool e2Contributing = ( e2->OutIdx >= 0 ); + +#ifdef use_xyz + SetZ(Pt, *e1, *e2); +#endif + +#ifdef use_lines + //if either edge is on an OPEN path ... + if (e1->WindDelta == 0 || e2->WindDelta == 0) + { + //ignore subject-subject open path intersections UNLESS they + //are both open paths, AND they are both 'contributing maximas' ... + if (e1->WindDelta == 0 && e2->WindDelta == 0) return; + + //if intersecting a subj line with a subj poly ... + else if (e1->PolyTyp == e2->PolyTyp && + e1->WindDelta != e2->WindDelta && m_ClipType == ctUnion) + { + if (e1->WindDelta == 0) + { + if (e2Contributing) + { + AddOutPt(e1, Pt); + if (e1Contributing) e1->OutIdx = Unassigned; + } + } + else + { + if (e1Contributing) + { + AddOutPt(e2, Pt); + if (e2Contributing) e2->OutIdx = Unassigned; + } + } + } + else if (e1->PolyTyp != e2->PolyTyp) + { + //toggle subj open path OutIdx on/off when Abs(clip.WndCnt) == 1 ... + if ((e1->WindDelta == 0) && std::abs(e2->WindCnt) == 1 && + (m_ClipType != ctUnion || e2->WindCnt2 == 0)) + { + AddOutPt(e1, Pt); + if (e1Contributing) e1->OutIdx = Unassigned; + } + else if ((e2->WindDelta == 0) && (std::abs(e1->WindCnt) == 1) && + (m_ClipType != ctUnion || e1->WindCnt2 == 0)) + { + AddOutPt(e2, Pt); + if (e2Contributing) e2->OutIdx = Unassigned; + } + } + return; + } +#endif + + //update winding counts... + //assumes that e1 will be to the Right of e2 ABOVE the intersection + if ( e1->PolyTyp == e2->PolyTyp ) + { + if ( IsEvenOddFillType( *e1) ) + { + int oldE1WindCnt = e1->WindCnt; + e1->WindCnt = e2->WindCnt; + e2->WindCnt = oldE1WindCnt; + } else + { + if (e1->WindCnt + e2->WindDelta == 0 ) e1->WindCnt = -e1->WindCnt; + else e1->WindCnt += e2->WindDelta; + if ( e2->WindCnt - e1->WindDelta == 0 ) e2->WindCnt = -e2->WindCnt; + else e2->WindCnt -= e1->WindDelta; + } + } else + { + if (!IsEvenOddFillType(*e2)) e1->WindCnt2 += e2->WindDelta; + else e1->WindCnt2 = ( e1->WindCnt2 == 0 ) ? 1 : 0; + if (!IsEvenOddFillType(*e1)) e2->WindCnt2 -= e1->WindDelta; + else e2->WindCnt2 = ( e2->WindCnt2 == 0 ) ? 1 : 0; + } + + PolyFillType e1FillType, e2FillType, e1FillType2, e2FillType2; + if (e1->PolyTyp == ptSubject) + { + e1FillType = m_SubjFillType; + e1FillType2 = m_ClipFillType; + } else + { + e1FillType = m_ClipFillType; + e1FillType2 = m_SubjFillType; + } + if (e2->PolyTyp == ptSubject) + { + e2FillType = m_SubjFillType; + e2FillType2 = m_ClipFillType; + } else + { + e2FillType = m_ClipFillType; + e2FillType2 = m_SubjFillType; + } + + cInt e1Wc, e2Wc; + switch (e1FillType) + { + case pftPositive: e1Wc = e1->WindCnt; break; + case pftNegative: e1Wc = -e1->WindCnt; break; + default: e1Wc = std::abs(e1->WindCnt); + } + switch(e2FillType) + { + case pftPositive: e2Wc = e2->WindCnt; break; + case pftNegative: e2Wc = -e2->WindCnt; break; + default: e2Wc = std::abs(e2->WindCnt); + } + + if ( e1Contributing && e2Contributing ) + { + if ((e1Wc != 0 && e1Wc != 1) || (e2Wc != 0 && e2Wc != 1) || + (e1->PolyTyp != e2->PolyTyp && m_ClipType != ctXor) ) + { + AddLocalMaxPoly(e1, e2, Pt); + } + else + { + AddOutPt(e1, Pt); + AddOutPt(e2, Pt); + std::swap(e1->Side, e2->Side); + std::swap(e1->OutIdx, e2->OutIdx); + } + } + else if ( e1Contributing ) + { + if (e2Wc == 0 || e2Wc == 1) + { + AddOutPt(e1, Pt); + std::swap(e1->Side, e2->Side); + std::swap(e1->OutIdx, e2->OutIdx); + } + } + else if ( e2Contributing ) + { + if (e1Wc == 0 || e1Wc == 1) + { + AddOutPt(e2, Pt); + std::swap(e1->Side, e2->Side); + std::swap(e1->OutIdx, e2->OutIdx); + } + } + else if ( (e1Wc == 0 || e1Wc == 1) && (e2Wc == 0 || e2Wc == 1)) + { + //neither edge is currently contributing ... + + cInt e1Wc2, e2Wc2; + switch (e1FillType2) + { + case pftPositive: e1Wc2 = e1->WindCnt2; break; + case pftNegative : e1Wc2 = -e1->WindCnt2; break; + default: e1Wc2 = std::abs(e1->WindCnt2); + } + switch (e2FillType2) + { + case pftPositive: e2Wc2 = e2->WindCnt2; break; + case pftNegative: e2Wc2 = -e2->WindCnt2; break; + default: e2Wc2 = std::abs(e2->WindCnt2); + } + + if (e1->PolyTyp != e2->PolyTyp) + { + AddLocalMinPoly(e1, e2, Pt); + } + else if (e1Wc == 1 && e2Wc == 1) + switch( m_ClipType ) { + case ctIntersection: + if (e1Wc2 > 0 && e2Wc2 > 0) + AddLocalMinPoly(e1, e2, Pt); + break; + case ctUnion: + if ( e1Wc2 <= 0 && e2Wc2 <= 0 ) + AddLocalMinPoly(e1, e2, Pt); + break; + case ctDifference: + if (((e1->PolyTyp == ptClip) && (e1Wc2 > 0) && (e2Wc2 > 0)) || + ((e1->PolyTyp == ptSubject) && (e1Wc2 <= 0) && (e2Wc2 <= 0))) + AddLocalMinPoly(e1, e2, Pt); + break; + case ctXor: + AddLocalMinPoly(e1, e2, Pt); + } + else + std::swap(e1->Side, e2->Side); + } +} +//------------------------------------------------------------------------------ + +void Clipper::SetHoleState(TEdge *e, OutRec *outrec) const +{ + bool IsHole = false; + TEdge *e2 = e->PrevInAEL; + while (e2) + { + if (e2->OutIdx >= 0 && e2->WindDelta != 0) + { + IsHole = !IsHole; + if (! outrec->FirstLeft) + outrec->FirstLeft = m_PolyOuts[e2->OutIdx]; + } + e2 = e2->PrevInAEL; + } + if (IsHole) outrec->IsHole = true; +} +//------------------------------------------------------------------------------ + +OutRec* GetLowermostRec(OutRec *outRec1, OutRec *outRec2) +{ + //work out which polygon fragment has the correct hole state ... + if (!outRec1->BottomPt) + outRec1->BottomPt = GetBottomPt(outRec1->Pts); + if (!outRec2->BottomPt) + outRec2->BottomPt = GetBottomPt(outRec2->Pts); + OutPt *OutPt1 = outRec1->BottomPt; + OutPt *OutPt2 = outRec2->BottomPt; + if (OutPt1->Pt.Y > OutPt2->Pt.Y) return outRec1; + else if (OutPt1->Pt.Y < OutPt2->Pt.Y) return outRec2; + else if (OutPt1->Pt.X < OutPt2->Pt.X) return outRec1; + else if (OutPt1->Pt.X > OutPt2->Pt.X) return outRec2; + else if (OutPt1->Next == OutPt1) return outRec2; + else if (OutPt2->Next == OutPt2) return outRec1; + else if (FirstIsBottomPt(OutPt1, OutPt2)) return outRec1; + else return outRec2; +} +//------------------------------------------------------------------------------ + +bool Param1RightOfParam2(OutRec* outRec1, OutRec* outRec2) +{ + do + { + outRec1 = outRec1->FirstLeft; + if (outRec1 == outRec2) return true; + } while (outRec1); + return false; +} +//------------------------------------------------------------------------------ + +OutRec* Clipper::GetOutRec(int Idx) +{ + OutRec* outrec = m_PolyOuts[Idx]; + while (outrec != m_PolyOuts[outrec->Idx]) + outrec = m_PolyOuts[outrec->Idx]; + return outrec; +} +//------------------------------------------------------------------------------ + +void Clipper::AppendPolygon(TEdge *e1, TEdge *e2) const +{ + //get the start and ends of both output polygons ... + OutRec *outRec1 = m_PolyOuts[e1->OutIdx]; + OutRec *outRec2 = m_PolyOuts[e2->OutIdx]; + + OutRec *holeStateRec; + if (Param1RightOfParam2(outRec1, outRec2)) + holeStateRec = outRec2; + else if (Param1RightOfParam2(outRec2, outRec1)) + holeStateRec = outRec1; + else + holeStateRec = GetLowermostRec(outRec1, outRec2); + + //get the start and ends of both output polygons and + //join e2 poly onto e1 poly and delete pointers to e2 ... + + OutPt* p1_lft = outRec1->Pts; + OutPt* p1_rt = p1_lft->Prev; + OutPt* p2_lft = outRec2->Pts; + OutPt* p2_rt = p2_lft->Prev; + + EdgeSide Side; + //join e2 poly onto e1 poly and delete pointers to e2 ... + if( e1->Side == esLeft ) + { + if( e2->Side == esLeft ) + { + //z y x a b c + ReversePolyPtLinks(p2_lft); + p2_lft->Next = p1_lft; + p1_lft->Prev = p2_lft; + p1_rt->Next = p2_rt; + p2_rt->Prev = p1_rt; + outRec1->Pts = p2_rt; + } else + { + //x y z a b c + p2_rt->Next = p1_lft; + p1_lft->Prev = p2_rt; + p2_lft->Prev = p1_rt; + p1_rt->Next = p2_lft; + outRec1->Pts = p2_lft; + } + Side = esLeft; + } else + { + if( e2->Side == esRight ) + { + //a b c z y x + ReversePolyPtLinks(p2_lft); + p1_rt->Next = p2_rt; + p2_rt->Prev = p1_rt; + p2_lft->Next = p1_lft; + p1_lft->Prev = p2_lft; + } else + { + //a b c x y z + p1_rt->Next = p2_lft; + p2_lft->Prev = p1_rt; + p1_lft->Prev = p2_rt; + p2_rt->Next = p1_lft; + } + Side = esRight; + } + + outRec1->BottomPt = 0; + if (holeStateRec == outRec2) + { + if (outRec2->FirstLeft != outRec1) + outRec1->FirstLeft = outRec2->FirstLeft; + outRec1->IsHole = outRec2->IsHole; + } + outRec2->Pts = 0; + outRec2->BottomPt = 0; + outRec2->FirstLeft = outRec1; + + int OKIdx = e1->OutIdx; + int ObsoleteIdx = e2->OutIdx; + + e1->OutIdx = Unassigned; //nb: safe because we only get here via AddLocalMaxPoly + e2->OutIdx = Unassigned; + + TEdge* e = m_ActiveEdges; + while( e ) + { + if( e->OutIdx == ObsoleteIdx ) + { + e->OutIdx = OKIdx; + e->Side = Side; + break; + } + e = e->NextInAEL; + } + + outRec2->Idx = outRec1->Idx; +} +//------------------------------------------------------------------------------ + +OutRec* Clipper::CreateOutRec() +{ + OutRec* result = new OutRec; + result->IsHole = false; + result->IsOpen = false; + result->FirstLeft = 0; + result->Pts = 0; + result->BottomPt = 0; + result->PolyNd = 0; + m_PolyOuts.push_back(result); + result->Idx = (int)m_PolyOuts.size()-1; + return result; +} +//------------------------------------------------------------------------------ + +OutPt* Clipper::AddOutPt(TEdge *e, const IntPoint &pt) +{ + if( e->OutIdx < 0 ) + { + OutRec *outRec = CreateOutRec(); + outRec->IsOpen = (e->WindDelta == 0); + OutPt* newOp = this->AllocateOutPt(); + outRec->Pts = newOp; + newOp->Idx = outRec->Idx; + newOp->Pt = pt; + newOp->Next = newOp; + newOp->Prev = newOp; + if (!outRec->IsOpen) + SetHoleState(e, outRec); + e->OutIdx = outRec->Idx; + return newOp; + } else + { + OutRec *outRec = m_PolyOuts[e->OutIdx]; + //OutRec.Pts is the 'Left-most' point & OutRec.Pts.Prev is the 'Right-most' + OutPt* op = outRec->Pts; + + bool ToFront = (e->Side == esLeft); + if (ToFront && (pt == op->Pt)) return op; + else if (!ToFront && (pt == op->Prev->Pt)) return op->Prev; + + OutPt* newOp = this->AllocateOutPt(); + newOp->Idx = outRec->Idx; + newOp->Pt = pt; + newOp->Next = op; + newOp->Prev = op->Prev; + newOp->Prev->Next = newOp; + op->Prev = newOp; + if (ToFront) outRec->Pts = newOp; + return newOp; + } +} +//------------------------------------------------------------------------------ + +OutPt* Clipper::GetLastOutPt(TEdge *e) +{ + OutRec *outRec = m_PolyOuts[e->OutIdx]; + if (e->Side == esLeft) + return outRec->Pts; + else + return outRec->Pts->Prev; +} +//------------------------------------------------------------------------------ + +void Clipper::ProcessHorizontals() +{ + PROFILE_FUNC(); + TEdge* horzEdge = m_SortedEdges; + while(horzEdge) + { + DeleteFromSEL(horzEdge); + ProcessHorizontal(horzEdge); + horzEdge = m_SortedEdges; + } +} +//------------------------------------------------------------------------------ + +inline bool IsMaxima(TEdge *e, const cInt Y) +{ + return e && e->Top.Y == Y && !e->NextInLML; +} +//------------------------------------------------------------------------------ + +inline bool IsIntermediate(TEdge *e, const cInt Y) +{ + return e->Top.Y == Y && e->NextInLML; +} +//------------------------------------------------------------------------------ + +inline TEdge *GetMaximaPair(TEdge *e) +{ + TEdge* result = 0; + if ((e->Next->Top == e->Top) && !e->Next->NextInLML) + result = e->Next; + else if ((e->Prev->Top == e->Top) && !e->Prev->NextInLML) + result = e->Prev; + + if (result && (result->OutIdx == Skip || + //result is false if both NextInAEL & PrevInAEL are nil & not horizontal ... + (result->NextInAEL == result->PrevInAEL && !IsHorizontal(*result)))) + return 0; + return result; +} +//------------------------------------------------------------------------------ + +void Clipper::SwapPositionsInAEL(TEdge *Edge1, TEdge *Edge2) +{ + //check that one or other edge hasn't already been removed from AEL ... + if (Edge1->NextInAEL == Edge1->PrevInAEL || + Edge2->NextInAEL == Edge2->PrevInAEL) return; + + if( Edge1->NextInAEL == Edge2 ) + { + TEdge* Next = Edge2->NextInAEL; + if( Next ) Next->PrevInAEL = Edge1; + TEdge* Prev = Edge1->PrevInAEL; + if( Prev ) Prev->NextInAEL = Edge2; + Edge2->PrevInAEL = Prev; + Edge2->NextInAEL = Edge1; + Edge1->PrevInAEL = Edge2; + Edge1->NextInAEL = Next; + } + else if( Edge2->NextInAEL == Edge1 ) + { + TEdge* Next = Edge1->NextInAEL; + if( Next ) Next->PrevInAEL = Edge2; + TEdge* Prev = Edge2->PrevInAEL; + if( Prev ) Prev->NextInAEL = Edge1; + Edge1->PrevInAEL = Prev; + Edge1->NextInAEL = Edge2; + Edge2->PrevInAEL = Edge1; + Edge2->NextInAEL = Next; + } + else + { + TEdge* Next = Edge1->NextInAEL; + TEdge* Prev = Edge1->PrevInAEL; + Edge1->NextInAEL = Edge2->NextInAEL; + if( Edge1->NextInAEL ) Edge1->NextInAEL->PrevInAEL = Edge1; + Edge1->PrevInAEL = Edge2->PrevInAEL; + if( Edge1->PrevInAEL ) Edge1->PrevInAEL->NextInAEL = Edge1; + Edge2->NextInAEL = Next; + if( Edge2->NextInAEL ) Edge2->NextInAEL->PrevInAEL = Edge2; + Edge2->PrevInAEL = Prev; + if( Edge2->PrevInAEL ) Edge2->PrevInAEL->NextInAEL = Edge2; + } + + if( !Edge1->PrevInAEL ) m_ActiveEdges = Edge1; + else if( !Edge2->PrevInAEL ) m_ActiveEdges = Edge2; +} +//------------------------------------------------------------------------------ + +void Clipper::SwapPositionsInSEL(TEdge *Edge1, TEdge *Edge2) +{ + if( !( Edge1->NextInSEL ) && !( Edge1->PrevInSEL ) ) return; + if( !( Edge2->NextInSEL ) && !( Edge2->PrevInSEL ) ) return; + + if( Edge1->NextInSEL == Edge2 ) + { + TEdge* Next = Edge2->NextInSEL; + if( Next ) Next->PrevInSEL = Edge1; + TEdge* Prev = Edge1->PrevInSEL; + if( Prev ) Prev->NextInSEL = Edge2; + Edge2->PrevInSEL = Prev; + Edge2->NextInSEL = Edge1; + Edge1->PrevInSEL = Edge2; + Edge1->NextInSEL = Next; + } + else if( Edge2->NextInSEL == Edge1 ) + { + TEdge* Next = Edge1->NextInSEL; + if( Next ) Next->PrevInSEL = Edge2; + TEdge* Prev = Edge2->PrevInSEL; + if( Prev ) Prev->NextInSEL = Edge1; + Edge1->PrevInSEL = Prev; + Edge1->NextInSEL = Edge2; + Edge2->PrevInSEL = Edge1; + Edge2->NextInSEL = Next; + } + else + { + TEdge* Next = Edge1->NextInSEL; + TEdge* Prev = Edge1->PrevInSEL; + Edge1->NextInSEL = Edge2->NextInSEL; + if( Edge1->NextInSEL ) Edge1->NextInSEL->PrevInSEL = Edge1; + Edge1->PrevInSEL = Edge2->PrevInSEL; + if( Edge1->PrevInSEL ) Edge1->PrevInSEL->NextInSEL = Edge1; + Edge2->NextInSEL = Next; + if( Edge2->NextInSEL ) Edge2->NextInSEL->PrevInSEL = Edge2; + Edge2->PrevInSEL = Prev; + if( Edge2->PrevInSEL ) Edge2->PrevInSEL->NextInSEL = Edge2; + } + + if( !Edge1->PrevInSEL ) m_SortedEdges = Edge1; + else if( !Edge2->PrevInSEL ) m_SortedEdges = Edge2; +} +//------------------------------------------------------------------------------ + +inline void GetHorzDirection(TEdge& HorzEdge, Direction& Dir, cInt& Left, cInt& Right) +{ + if (HorzEdge.Bot.X < HorzEdge.Top.X) + { + Left = HorzEdge.Bot.X; + Right = HorzEdge.Top.X; + Dir = dLeftToRight; + } else + { + Left = HorzEdge.Top.X; + Right = HorzEdge.Bot.X; + Dir = dRightToLeft; + } +} +//------------------------------------------------------------------------ + +/******************************************************************************* +* Notes: Horizontal edges (HEs) at scanline intersections (ie at the Top or * +* Bottom of a scanbeam) are processed as if layered. The order in which HEs * +* are processed doesn't matter. HEs intersect with other HE Bot.Xs only [#] * +* (or they could intersect with Top.Xs only, ie EITHER Bot.Xs OR Top.Xs), * +* and with other non-horizontal edges [*]. Once these intersections are * +* processed, intermediate HEs then 'promote' the Edge above (NextInLML) into * +* the AEL. These 'promoted' edges may in turn intersect [%] with other HEs. * +*******************************************************************************/ + +void Clipper::ProcessHorizontal(TEdge *horzEdge) +{ + Direction dir; + cInt horzLeft, horzRight; + bool IsOpen = (horzEdge->OutIdx >= 0 && m_PolyOuts[horzEdge->OutIdx]->IsOpen); + + GetHorzDirection(*horzEdge, dir, horzLeft, horzRight); + + TEdge* eLastHorz = horzEdge, *eMaxPair = 0; + while (eLastHorz->NextInLML && IsHorizontal(*eLastHorz->NextInLML)) + eLastHorz = eLastHorz->NextInLML; + if (!eLastHorz->NextInLML) + eMaxPair = GetMaximaPair(eLastHorz); + + std::vector::const_iterator maxIt; + std::vector::const_reverse_iterator maxRit; + if (!m_Maxima.empty()) + { + //get the first maxima in range (X) ... + if (dir == dLeftToRight) + { + maxIt = m_Maxima.begin(); + while (maxIt != m_Maxima.end() && *maxIt <= horzEdge->Bot.X) ++maxIt; + if (maxIt != m_Maxima.end() && *maxIt >= eLastHorz->Top.X) + maxIt = m_Maxima.end(); + } + else + { + maxRit = m_Maxima.rbegin(); + while (maxRit != m_Maxima.rend() && *maxRit > horzEdge->Bot.X) ++maxRit; + if (maxRit != m_Maxima.rend() && *maxRit <= eLastHorz->Top.X) + maxRit = m_Maxima.rend(); + } + } + + OutPt* op1 = 0; + + for (;;) //loop through consec. horizontal edges + { + + bool IsLastHorz = (horzEdge == eLastHorz); + TEdge* e = (dir == dLeftToRight) ? horzEdge->NextInAEL : horzEdge->PrevInAEL; + while(e) + { + + //this code block inserts extra coords into horizontal edges (in output + //polygons) whereever maxima touch these horizontal edges. This helps + //'simplifying' polygons (ie if the Simplify property is set). + if (!m_Maxima.empty()) + { + if (dir == dLeftToRight) + { + while (maxIt != m_Maxima.end() && *maxIt < e->Curr.X) + { + if (horzEdge->OutIdx >= 0 && !IsOpen) + AddOutPt(horzEdge, IntPoint(*maxIt, horzEdge->Bot.Y)); + ++maxIt; + } + } + else + { + while (maxRit != m_Maxima.rend() && *maxRit > e->Curr.X) + { + if (horzEdge->OutIdx >= 0 && !IsOpen) + AddOutPt(horzEdge, IntPoint(*maxRit, horzEdge->Bot.Y)); + ++maxRit; + } + } + }; + + if ((dir == dLeftToRight && e->Curr.X > horzRight) || + (dir == dRightToLeft && e->Curr.X < horzLeft)) break; + + //Also break if we've got to the end of an intermediate horizontal edge ... + //nb: Smaller Dx's are to the right of larger Dx's ABOVE the horizontal. + if (e->Curr.X == horzEdge->Top.X && horzEdge->NextInLML && + e->Dx < horzEdge->NextInLML->Dx) break; + + if (horzEdge->OutIdx >= 0 && !IsOpen) //note: may be done multiple times + { + op1 = AddOutPt(horzEdge, e->Curr); + TEdge* eNextHorz = m_SortedEdges; + while (eNextHorz) + { + if (eNextHorz->OutIdx >= 0 && + HorzSegmentsOverlap(horzEdge->Bot.X, + horzEdge->Top.X, eNextHorz->Bot.X, eNextHorz->Top.X)) + { + OutPt* op2 = GetLastOutPt(eNextHorz); + m_Joins.emplace_back(Join(op2, op1, eNextHorz->Top)); + } + eNextHorz = eNextHorz->NextInSEL; + } + m_GhostJoins.emplace_back(Join(op1, 0, horzEdge->Bot)); + } + + //OK, so far we're still in range of the horizontal Edge but make sure + //we're at the last of consec. horizontals when matching with eMaxPair + if(e == eMaxPair && IsLastHorz) + { + if (horzEdge->OutIdx >= 0) + AddLocalMaxPoly(horzEdge, eMaxPair, horzEdge->Top); + DeleteFromAEL(horzEdge); + DeleteFromAEL(eMaxPair); + return; + } + + if(dir == dLeftToRight) + { + IntPoint Pt = IntPoint(e->Curr.X, horzEdge->Curr.Y); + IntersectEdges(horzEdge, e, Pt); + } + else + { + IntPoint Pt = IntPoint(e->Curr.X, horzEdge->Curr.Y); + IntersectEdges( e, horzEdge, Pt); + } + TEdge* eNext = (dir == dLeftToRight) ? e->NextInAEL : e->PrevInAEL; + SwapPositionsInAEL( horzEdge, e ); + e = eNext; + } //end while(e) + + //Break out of loop if HorzEdge.NextInLML is not also horizontal ... + if (!horzEdge->NextInLML || !IsHorizontal(*horzEdge->NextInLML)) break; + + UpdateEdgeIntoAEL(horzEdge); + if (horzEdge->OutIdx >= 0) AddOutPt(horzEdge, horzEdge->Bot); + GetHorzDirection(*horzEdge, dir, horzLeft, horzRight); + + } //end for (;;) + + if (horzEdge->OutIdx >= 0 && !op1) + { + op1 = GetLastOutPt(horzEdge); + TEdge* eNextHorz = m_SortedEdges; + while (eNextHorz) + { + if (eNextHorz->OutIdx >= 0 && + HorzSegmentsOverlap(horzEdge->Bot.X, + horzEdge->Top.X, eNextHorz->Bot.X, eNextHorz->Top.X)) + { + OutPt* op2 = GetLastOutPt(eNextHorz); + m_Joins.emplace_back(Join(op2, op1, eNextHorz->Top)); + } + eNextHorz = eNextHorz->NextInSEL; + } + m_GhostJoins.emplace_back(Join(op1, 0, horzEdge->Top)); + } + + if (horzEdge->NextInLML) + { + if(horzEdge->OutIdx >= 0) + { + op1 = AddOutPt( horzEdge, horzEdge->Top); + UpdateEdgeIntoAEL(horzEdge); + if (horzEdge->WindDelta == 0) return; + //nb: HorzEdge is no longer horizontal here + TEdge* ePrev = horzEdge->PrevInAEL; + TEdge* eNext = horzEdge->NextInAEL; + if (ePrev && ePrev->Curr.X == horzEdge->Bot.X && + ePrev->Curr.Y == horzEdge->Bot.Y && ePrev->WindDelta != 0 && + (ePrev->OutIdx >= 0 && ePrev->Curr.Y > ePrev->Top.Y && + SlopesEqual(*horzEdge, *ePrev, m_UseFullRange))) + { + OutPt* op2 = AddOutPt(ePrev, horzEdge->Bot); + m_Joins.emplace_back(Join(op1, op2, horzEdge->Top)); + } + else if (eNext && eNext->Curr.X == horzEdge->Bot.X && + eNext->Curr.Y == horzEdge->Bot.Y && eNext->WindDelta != 0 && + eNext->OutIdx >= 0 && eNext->Curr.Y > eNext->Top.Y && + SlopesEqual(*horzEdge, *eNext, m_UseFullRange)) + { + OutPt* op2 = AddOutPt(eNext, horzEdge->Bot); + m_Joins.emplace_back(Join(op1, op2, horzEdge->Top)); + } + } + else + UpdateEdgeIntoAEL(horzEdge); + } + else + { + if (horzEdge->OutIdx >= 0) AddOutPt(horzEdge, horzEdge->Top); + DeleteFromAEL(horzEdge); + } +} +//------------------------------------------------------------------------------ + +void Clipper::UpdateEdgeIntoAEL(TEdge *&e) +{ + if( !e->NextInLML ) + throw clipperException("UpdateEdgeIntoAEL: invalid call"); + + e->NextInLML->OutIdx = e->OutIdx; + TEdge* AelPrev = e->PrevInAEL; + TEdge* AelNext = e->NextInAEL; + if (AelPrev) AelPrev->NextInAEL = e->NextInLML; + else m_ActiveEdges = e->NextInLML; + if (AelNext) AelNext->PrevInAEL = e->NextInLML; + e->NextInLML->Side = e->Side; + e->NextInLML->WindDelta = e->WindDelta; + e->NextInLML->WindCnt = e->WindCnt; + e->NextInLML->WindCnt2 = e->WindCnt2; + e = e->NextInLML; + e->Curr = e->Bot; + e->PrevInAEL = AelPrev; + e->NextInAEL = AelNext; + if (!IsHorizontal(*e)) + m_Scanbeam.push(e->Top.Y); +} +//------------------------------------------------------------------------------ + +bool Clipper::ProcessIntersections(const cInt topY) +{ + PROFILE_FUNC(); + if( !m_ActiveEdges ) return true; + try { + BuildIntersectList(topY); + size_t IlSize = m_IntersectList.size(); + if (IlSize == 0) return true; + if (IlSize == 1 || FixupIntersectionOrder()) { + for (IntersectNode &iNode : m_IntersectList) { + IntersectEdges( iNode.Edge1, iNode.Edge2, iNode.Pt); + SwapPositionsInAEL( iNode.Edge1 , iNode.Edge2 ); + } + m_IntersectList.clear(); + } + else return false; + } + catch(...) + { + m_SortedEdges = 0; + m_IntersectList.clear(); + throw clipperException("ProcessIntersections error"); + } + m_SortedEdges = 0; + return true; +} +//------------------------------------------------------------------------------ + +void Clipper::BuildIntersectList(const cInt topY) +{ + if ( !m_ActiveEdges ) return; + + //prepare for sorting ... + TEdge* e = m_ActiveEdges; + m_SortedEdges = e; + while( e ) + { + e->PrevInSEL = e->PrevInAEL; + e->NextInSEL = e->NextInAEL; + e->Curr.X = TopX( *e, topY ); + e = e->NextInAEL; + } + + //bubblesort ... + bool isModified; + do + { + isModified = false; + e = m_SortedEdges; + while( e->NextInSEL ) + { + TEdge *eNext = e->NextInSEL; + IntPoint Pt; + if(e->Curr.X > eNext->Curr.X) + { + IntersectPoint(*e, *eNext, Pt); + m_IntersectList.emplace_back(IntersectNode(e, eNext, Pt)); + SwapPositionsInSEL(e, eNext); + isModified = true; + } + else + e = eNext; + } + if( e->PrevInSEL ) e->PrevInSEL->NextInSEL = 0; + else break; + } + while ( isModified ); + m_SortedEdges = 0; //important +} +//------------------------------------------------------------------------------ + + +inline bool EdgesAdjacent(const IntersectNode &inode) +{ + return (inode.Edge1->NextInSEL == inode.Edge2) || + (inode.Edge1->PrevInSEL == inode.Edge2); +} +//------------------------------------------------------------------------------ + +bool Clipper::FixupIntersectionOrder() +{ + //pre-condition: intersections are sorted Bottom-most first. + //Now it's crucial that intersections are made only between adjacent edges, + //so to ensure this the order of intersections may need adjusting ... + CopyAELToSEL(); + std::sort(m_IntersectList.begin(), m_IntersectList.end(), [](const IntersectNode &node1, const IntersectNode &node2) { return node2.Pt.Y < node1.Pt.Y; }); + + size_t cnt = m_IntersectList.size(); + for (size_t i = 0; i < cnt; ++i) + { + if (!EdgesAdjacent(m_IntersectList[i])) + { + size_t j = i + 1; + while (j < cnt && !EdgesAdjacent(m_IntersectList[j])) j++; + if (j == cnt) return false; + std::swap(m_IntersectList[i], m_IntersectList[j]); + } + SwapPositionsInSEL(m_IntersectList[i].Edge1, m_IntersectList[i].Edge2); + } + return true; +} +//------------------------------------------------------------------------------ + +void Clipper::DoMaxima(TEdge *e) +{ + TEdge* eMaxPair = GetMaximaPair(e); + if (!eMaxPair) + { + if (e->OutIdx >= 0) + AddOutPt(e, e->Top); + DeleteFromAEL(e); + return; + } + + TEdge* eNext = e->NextInAEL; + while(eNext && eNext != eMaxPair) + { + IntersectEdges(e, eNext, e->Top); + SwapPositionsInAEL(e, eNext); + eNext = e->NextInAEL; + } + + if(e->OutIdx == Unassigned && eMaxPair->OutIdx == Unassigned) + { + DeleteFromAEL(e); + DeleteFromAEL(eMaxPair); + } + else if( e->OutIdx >= 0 && eMaxPair->OutIdx >= 0 ) + { + if (e->OutIdx >= 0) AddLocalMaxPoly(e, eMaxPair, e->Top); + DeleteFromAEL(e); + DeleteFromAEL(eMaxPair); + } +#ifdef use_lines + else if (e->WindDelta == 0) + { + if (e->OutIdx >= 0) + { + AddOutPt(e, e->Top); + e->OutIdx = Unassigned; + } + DeleteFromAEL(e); + + if (eMaxPair->OutIdx >= 0) + { + AddOutPt(eMaxPair, e->Top); + eMaxPair->OutIdx = Unassigned; + } + DeleteFromAEL(eMaxPair); + } +#endif + else throw clipperException("DoMaxima error"); +} +//------------------------------------------------------------------------------ + +void Clipper::ProcessEdgesAtTopOfScanbeam(const cInt topY) +{ + PROFILE_FUNC(); + TEdge* e = m_ActiveEdges; + while( e ) + { + //1. process maxima, treating them as if they're 'bent' horizontal edges, + // but exclude maxima with horizontal edges. nb: e can't be a horizontal. + bool IsMaximaEdge = IsMaxima(e, topY); + + if(IsMaximaEdge) + { + TEdge* eMaxPair = GetMaximaPair(e); + IsMaximaEdge = (!eMaxPair || !IsHorizontal(*eMaxPair)); + } + + if(IsMaximaEdge) + { + if (m_StrictSimple) m_Maxima.push_back(e->Top.X); + TEdge* ePrev = e->PrevInAEL; + DoMaxima(e); + if( !ePrev ) e = m_ActiveEdges; + else e = ePrev->NextInAEL; + } + else + { + //2. promote horizontal edges, otherwise update Curr.X and Curr.Y ... + if (IsIntermediate(e, topY) && IsHorizontal(*e->NextInLML)) + { + UpdateEdgeIntoAEL(e); + if (e->OutIdx >= 0) + AddOutPt(e, e->Bot); + AddEdgeToSEL(e); + } + else + { + e->Curr.X = TopX( *e, topY ); + e->Curr.Y = topY; + } + + //When StrictlySimple and 'e' is being touched by another edge, then + //make sure both edges have a vertex here ... + if (m_StrictSimple) + { + TEdge* ePrev = e->PrevInAEL; + if ((e->OutIdx >= 0) && (e->WindDelta != 0) && ePrev && (ePrev->OutIdx >= 0) && + (ePrev->Curr.X == e->Curr.X) && (ePrev->WindDelta != 0)) + { + IntPoint pt = e->Curr; +#ifdef use_xyz + SetZ(pt, *ePrev, *e); +#endif + OutPt* op = AddOutPt(ePrev, pt); + OutPt* op2 = AddOutPt(e, pt); + m_Joins.emplace_back(Join(op, op2, pt)); //StrictlySimple (type-3) join + } + } + + e = e->NextInAEL; + } + } + + //3. Process horizontals at the Top of the scanbeam ... + std::sort(m_Maxima.begin(), m_Maxima.end()); + ProcessHorizontals(); + m_Maxima.clear(); + + //4. Promote intermediate vertices ... + e = m_ActiveEdges; + while(e) + { + if(IsIntermediate(e, topY)) + { + OutPt* op = 0; + if( e->OutIdx >= 0 ) + op = AddOutPt(e, e->Top); + UpdateEdgeIntoAEL(e); + + //if output polygons share an edge, they'll need joining later ... + TEdge* ePrev = e->PrevInAEL; + TEdge* eNext = e->NextInAEL; + if (ePrev && ePrev->Curr.X == e->Bot.X && + ePrev->Curr.Y == e->Bot.Y && op && + ePrev->OutIdx >= 0 && ePrev->Curr.Y > ePrev->Top.Y && + SlopesEqual(*e, *ePrev, m_UseFullRange) && + (e->WindDelta != 0) && (ePrev->WindDelta != 0)) + { + OutPt* op2 = AddOutPt(ePrev, e->Bot); + m_Joins.emplace_back(Join(op, op2, e->Top)); + } + else if (eNext && eNext->Curr.X == e->Bot.X && + eNext->Curr.Y == e->Bot.Y && op && + eNext->OutIdx >= 0 && eNext->Curr.Y > eNext->Top.Y && + SlopesEqual(*e, *eNext, m_UseFullRange) && + (e->WindDelta != 0) && (eNext->WindDelta != 0)) + { + OutPt* op2 = AddOutPt(eNext, e->Bot); + m_Joins.emplace_back(Join(op, op2, e->Top)); + } + } + e = e->NextInAEL; + } +} +//------------------------------------------------------------------------------ + +void Clipper::FixupOutPolyline(OutRec &outrec) +{ + OutPt *pp = outrec.Pts; + OutPt *lastPP = pp->Prev; + while (pp != lastPP) + { + pp = pp->Next; + if (pp->Pt == pp->Prev->Pt) + { + if (pp == lastPP) lastPP = pp->Prev; + OutPt *tmpPP = pp->Prev; + tmpPP->Next = pp->Next; + pp->Next->Prev = tmpPP; + this->DisposeOutPt(pp); + pp = tmpPP; + } + } + + if (pp == pp->Prev) + { + this->DisposeOutPts(pp); + outrec.Pts = 0; + return; + } +} +//------------------------------------------------------------------------------ + +void Clipper::FixupOutPolygon(OutRec &outrec) +{ + //FixupOutPolygon() - removes duplicate points and simplifies consecutive + //parallel edges by removing the middle vertex. + OutPt *lastOK = nullptr; + outrec.BottomPt = nullptr; + OutPt *pp = outrec.Pts; + bool preserveCol = m_PreserveCollinear || m_StrictSimple; + + for (;;) + { + if (pp->Prev == pp || pp->Prev == pp->Next) + { + // Empty loop or a stick. Release the polygon. + this->DisposeOutPts(pp); + outrec.Pts = nullptr; + return; + } + + //test for duplicate points and collinear edges ... + if ((pp->Pt == pp->Next->Pt) || (pp->Pt == pp->Prev->Pt) || + (SlopesEqual(pp->Prev->Pt, pp->Pt, pp->Next->Pt, m_UseFullRange) && + (!preserveCol || !Pt2IsBetweenPt1AndPt3(pp->Prev->Pt, pp->Pt, pp->Next->Pt)))) + { + lastOK = nullptr; + OutPt *tmp = pp; + pp->Prev->Next = pp->Next; + pp->Next->Prev = pp->Prev; + pp = pp->Prev; + this->DisposeOutPt(tmp); + } + else if (pp == lastOK) break; + else + { + if (!lastOK) lastOK = pp; + pp = pp->Next; + } + } + outrec.Pts = pp; +} +//------------------------------------------------------------------------------ + +// Count the number of points in a closed linked loop starting with Pts. +int PointCount(OutPt *Pts) +{ + if (!Pts) return 0; + int result = 0; + OutPt* p = Pts; + do + { + result++; + p = p->Next; + } + while (p != Pts); + return result; +} +//------------------------------------------------------------------------------ + +void Clipper::BuildResult(Paths &polys) +{ + polys.reserve(m_PolyOuts.size()); + for (OutRec* outRec : m_PolyOuts) + { + assert(! outRec->IsOpen); + if (!outRec->Pts) continue; + Path pg; + OutPt* p = outRec->Pts->Prev; + int cnt = PointCount(p); + if (cnt < 2) continue; + pg.reserve(cnt); + for (int i = 0; i < cnt; ++i) + { + pg.emplace_back(p->Pt); + p = p->Prev; + } + polys.emplace_back(std::move(pg)); + } +} +//------------------------------------------------------------------------------ + +void Clipper::BuildResult2(PolyTree& polytree) +{ + polytree.Clear(); + polytree.AllNodes.reserve(m_PolyOuts.size()); + //add each output polygon/contour to polytree ... + for (OutRec* outRec : m_PolyOuts) + { + int cnt = PointCount(outRec->Pts); + if ((outRec->IsOpen && cnt < 2) || (!outRec->IsOpen && cnt < 3)) + // Ignore an invalid output loop or a polyline. + continue; + + //skip OutRecs that (a) contain outermost polygons or + //(b) already have the correct owner/child linkage ... + if (outRec->FirstLeft && + (outRec->IsHole == outRec->FirstLeft->IsHole || ! outRec->FirstLeft->Pts)) { + OutRec* orfl = outRec->FirstLeft; + while (orfl && ((orfl->IsHole == outRec->IsHole) || !orfl->Pts)) + orfl = orfl->FirstLeft; + outRec->FirstLeft = orfl; + } + + //nb: polytree takes ownership of all the PolyNodes + polytree.AllNodes.emplace_back(PolyNode()); + PolyNode* pn = &polytree.AllNodes.back(); + outRec->PolyNd = pn; + pn->Parent = 0; + pn->Index = 0; + pn->Contour.reserve(cnt); + OutPt *op = outRec->Pts->Prev; + for (int j = 0; j < cnt; j++) + { + pn->Contour.emplace_back(op->Pt); + op = op->Prev; + } + } + + //fixup PolyNode links etc ... + polytree.Childs.reserve(m_PolyOuts.size()); + for (OutRec* outRec : m_PolyOuts) + { + if (!outRec->PolyNd) continue; + if (outRec->IsOpen) + { + outRec->PolyNd->m_IsOpen = true; + polytree.AddChild(*outRec->PolyNd); + } + else if (outRec->FirstLeft && outRec->FirstLeft->PolyNd) + outRec->FirstLeft->PolyNd->AddChild(*outRec->PolyNd); + else + polytree.AddChild(*outRec->PolyNd); + } +} +//------------------------------------------------------------------------------ + +inline bool E2InsertsBeforeE1(TEdge &e1, TEdge &e2) +{ + if (e2.Curr.X == e1.Curr.X) + { + if (e2.Top.Y > e1.Top.Y) + return e2.Top.X < TopX(e1, e2.Top.Y); + else return e1.Top.X > TopX(e2, e1.Top.Y); + } + else return e2.Curr.X < e1.Curr.X; +} +//------------------------------------------------------------------------------ + +bool GetOverlap(const cInt a1, const cInt a2, const cInt b1, const cInt b2, + cInt& Left, cInt& Right) +{ + if (a1 < a2) + { + if (b1 < b2) {Left = std::max(a1,b1); Right = std::min(a2,b2);} + else {Left = std::max(a1,b2); Right = std::min(a2,b1);} + } + else + { + if (b1 < b2) {Left = std::max(a2,b1); Right = std::min(a1,b2);} + else {Left = std::max(a2,b2); Right = std::min(a1,b1);} + } + return Left < Right; +} +//------------------------------------------------------------------------------ + +// Make all points of outrec point to outrec.Idx +inline void UpdateOutPtIdxs(OutRec& outrec) +{ + OutPt* op = outrec.Pts; + do + { + op->Idx = outrec.Idx; + op = op->Prev; + } + while(op != outrec.Pts); +} +//------------------------------------------------------------------------------ + +void Clipper::InsertEdgeIntoAEL(TEdge *edge, TEdge* startEdge) +{ + if(!m_ActiveEdges) + { + edge->PrevInAEL = 0; + edge->NextInAEL = 0; + m_ActiveEdges = edge; + } + else if(!startEdge && E2InsertsBeforeE1(*m_ActiveEdges, *edge)) + { + edge->PrevInAEL = 0; + edge->NextInAEL = m_ActiveEdges; + m_ActiveEdges->PrevInAEL = edge; + m_ActiveEdges = edge; + } + else + { + if(!startEdge) startEdge = m_ActiveEdges; + while(startEdge->NextInAEL && + !E2InsertsBeforeE1(*startEdge->NextInAEL , *edge)) + startEdge = startEdge->NextInAEL; + edge->NextInAEL = startEdge->NextInAEL; + if(startEdge->NextInAEL) startEdge->NextInAEL->PrevInAEL = edge; + edge->PrevInAEL = startEdge; + startEdge->NextInAEL = edge; + } +} +//---------------------------------------------------------------------- + +OutPt* Clipper::DupOutPt(OutPt* outPt, bool InsertAfter) +{ + OutPt* result = this->AllocateOutPt(); + result->Pt = outPt->Pt; + result->Idx = outPt->Idx; + if (InsertAfter) + { + result->Next = outPt->Next; + result->Prev = outPt; + outPt->Next->Prev = result; + outPt->Next = result; + } + else + { + result->Prev = outPt->Prev; + result->Next = outPt; + outPt->Prev->Next = result; + outPt->Prev = result; + } + return result; +} +//------------------------------------------------------------------------------ + +bool Clipper::JoinHorz(OutPt* op1, OutPt* op1b, OutPt* op2, OutPt* op2b, + const IntPoint &Pt, bool DiscardLeft) +{ + Direction Dir1 = (op1->Pt.X > op1b->Pt.X ? dRightToLeft : dLeftToRight); + Direction Dir2 = (op2->Pt.X > op2b->Pt.X ? dRightToLeft : dLeftToRight); + if (Dir1 == Dir2) return false; + + //When DiscardLeft, we want Op1b to be on the Left of Op1, otherwise we + //want Op1b to be on the Right. (And likewise with Op2 and Op2b.) + //So, to facilitate this while inserting Op1b and Op2b ... + //when DiscardLeft, make sure we're AT or RIGHT of Pt before adding Op1b, + //otherwise make sure we're AT or LEFT of Pt. (Likewise with Op2b.) + if (Dir1 == dLeftToRight) + { + while (op1->Next->Pt.X <= Pt.X && + op1->Next->Pt.X >= op1->Pt.X && op1->Next->Pt.Y == Pt.Y) + op1 = op1->Next; + if (DiscardLeft && (op1->Pt.X != Pt.X)) op1 = op1->Next; + op1b = this->DupOutPt(op1, !DiscardLeft); + if (op1b->Pt != Pt) + { + op1 = op1b; + op1->Pt = Pt; + op1b = this->DupOutPt(op1, !DiscardLeft); + } + } + else + { + while (op1->Next->Pt.X >= Pt.X && + op1->Next->Pt.X <= op1->Pt.X && op1->Next->Pt.Y == Pt.Y) + op1 = op1->Next; + if (!DiscardLeft && (op1->Pt.X != Pt.X)) op1 = op1->Next; + op1b = this->DupOutPt(op1, DiscardLeft); + if (op1b->Pt != Pt) + { + op1 = op1b; + op1->Pt = Pt; + op1b = this->DupOutPt(op1, DiscardLeft); + } + } + + if (Dir2 == dLeftToRight) + { + while (op2->Next->Pt.X <= Pt.X && + op2->Next->Pt.X >= op2->Pt.X && op2->Next->Pt.Y == Pt.Y) + op2 = op2->Next; + if (DiscardLeft && (op2->Pt.X != Pt.X)) op2 = op2->Next; + op2b = this->DupOutPt(op2, !DiscardLeft); + if (op2b->Pt != Pt) + { + op2 = op2b; + op2->Pt = Pt; + op2b = this->DupOutPt(op2, !DiscardLeft); + }; + } else + { + while (op2->Next->Pt.X >= Pt.X && + op2->Next->Pt.X <= op2->Pt.X && op2->Next->Pt.Y == Pt.Y) + op2 = op2->Next; + if (!DiscardLeft && (op2->Pt.X != Pt.X)) op2 = op2->Next; + op2b = this->DupOutPt(op2, DiscardLeft); + if (op2b->Pt != Pt) + { + op2 = op2b; + op2->Pt = Pt; + op2b = this->DupOutPt(op2, DiscardLeft); + }; + }; + + if ((Dir1 == dLeftToRight) == DiscardLeft) + { + op1->Prev = op2; + op2->Next = op1; + op1b->Next = op2b; + op2b->Prev = op1b; + } + else + { + op1->Next = op2; + op2->Prev = op1; + op1b->Prev = op2b; + op2b->Next = op1b; + } + return true; +} +//------------------------------------------------------------------------------ + +bool Clipper::JoinPoints(Join *j, OutRec* outRec1, OutRec* outRec2) +{ + OutPt *op1 = j->OutPt1, *op1b; + OutPt *op2 = j->OutPt2, *op2b; + + //There are 3 kinds of joins for output polygons ... + //1. Horizontal joins where Join.OutPt1 & Join.OutPt2 are vertices anywhere + //along (horizontal) collinear edges (& Join.OffPt is on the same horizontal). + //2. Non-horizontal joins where Join.OutPt1 & Join.OutPt2 are at the same + //location at the Bottom of the overlapping segment (& Join.OffPt is above). + //3. StrictSimple joins where edges touch but are not collinear and where + //Join.OutPt1, Join.OutPt2 & Join.OffPt all share the same point. + bool isHorizontal = (j->OutPt1->Pt.Y == j->OffPt.Y); + + if (isHorizontal && (j->OffPt == j->OutPt1->Pt) && + (j->OffPt == j->OutPt2->Pt)) + { + //Strictly Simple join ... + if (outRec1 != outRec2) return false; + op1b = j->OutPt1->Next; + while (op1b != op1 && (op1b->Pt == j->OffPt)) + op1b = op1b->Next; + bool reverse1 = (op1b->Pt.Y > j->OffPt.Y); + op2b = j->OutPt2->Next; + while (op2b != op2 && (op2b->Pt == j->OffPt)) + op2b = op2b->Next; + bool reverse2 = (op2b->Pt.Y > j->OffPt.Y); + if (reverse1 == reverse2) return false; + if (reverse1) + { + op1b = this->DupOutPt(op1, false); + op2b = this->DupOutPt(op2, true); + op1->Prev = op2; + op2->Next = op1; + op1b->Next = op2b; + op2b->Prev = op1b; + j->OutPt1 = op1; + j->OutPt2 = op1b; + return true; + } else + { + op1b = this->DupOutPt(op1, true); + op2b = this->DupOutPt(op2, false); + op1->Next = op2; + op2->Prev = op1; + op1b->Prev = op2b; + op2b->Next = op1b; + j->OutPt1 = op1; + j->OutPt2 = op1b; + return true; + } + } + else if (isHorizontal) + { + //treat horizontal joins differently to non-horizontal joins since with + //them we're not yet sure where the overlapping is. OutPt1.Pt & OutPt2.Pt + //may be anywhere along the horizontal edge. + op1b = op1; + while (op1->Prev->Pt.Y == op1->Pt.Y && op1->Prev != op1b && op1->Prev != op2) + op1 = op1->Prev; + while (op1b->Next->Pt.Y == op1b->Pt.Y && op1b->Next != op1 && op1b->Next != op2) + op1b = op1b->Next; + if (op1b->Next == op1 || op1b->Next == op2) return false; //a flat 'polygon' + + op2b = op2; + while (op2->Prev->Pt.Y == op2->Pt.Y && op2->Prev != op2b && op2->Prev != op1b) + op2 = op2->Prev; + while (op2b->Next->Pt.Y == op2b->Pt.Y && op2b->Next != op2 && op2b->Next != op1) + op2b = op2b->Next; + if (op2b->Next == op2 || op2b->Next == op1) return false; //a flat 'polygon' + + cInt Left, Right; + //Op1 --> Op1b & Op2 --> Op2b are the extremites of the horizontal edges + if (!GetOverlap(op1->Pt.X, op1b->Pt.X, op2->Pt.X, op2b->Pt.X, Left, Right)) + return false; + + //DiscardLeftSide: when overlapping edges are joined, a spike will created + //which needs to be cleaned up. However, we don't want Op1 or Op2 caught up + //on the discard Side as either may still be needed for other joins ... + IntPoint Pt; + bool DiscardLeftSide; + if (op1->Pt.X >= Left && op1->Pt.X <= Right) + { + Pt = op1->Pt; DiscardLeftSide = (op1->Pt.X > op1b->Pt.X); + } + else if (op2->Pt.X >= Left&& op2->Pt.X <= Right) + { + Pt = op2->Pt; DiscardLeftSide = (op2->Pt.X > op2b->Pt.X); + } + else if (op1b->Pt.X >= Left && op1b->Pt.X <= Right) + { + Pt = op1b->Pt; DiscardLeftSide = op1b->Pt.X > op1->Pt.X; + } + else + { + Pt = op2b->Pt; DiscardLeftSide = (op2b->Pt.X > op2->Pt.X); + } + j->OutPt1 = op1; j->OutPt2 = op2; + return JoinHorz(op1, op1b, op2, op2b, Pt, DiscardLeftSide); + } else + { + //nb: For non-horizontal joins ... + // 1. Jr.OutPt1.Pt.Y == Jr.OutPt2.Pt.Y + // 2. Jr.OutPt1.Pt > Jr.OffPt.Y + + //make sure the polygons are correctly oriented ... + op1b = op1->Next; + while ((op1b->Pt == op1->Pt) && (op1b != op1)) op1b = op1b->Next; + bool Reverse1 = ((op1b->Pt.Y > op1->Pt.Y) || + !SlopesEqual(op1->Pt, op1b->Pt, j->OffPt, m_UseFullRange)); + if (Reverse1) + { + op1b = op1->Prev; + while ((op1b->Pt == op1->Pt) && (op1b != op1)) op1b = op1b->Prev; + if ((op1b->Pt.Y > op1->Pt.Y) || + !SlopesEqual(op1->Pt, op1b->Pt, j->OffPt, m_UseFullRange)) return false; + }; + op2b = op2->Next; + while ((op2b->Pt == op2->Pt) && (op2b != op2))op2b = op2b->Next; + bool Reverse2 = ((op2b->Pt.Y > op2->Pt.Y) || + !SlopesEqual(op2->Pt, op2b->Pt, j->OffPt, m_UseFullRange)); + if (Reverse2) + { + op2b = op2->Prev; + while ((op2b->Pt == op2->Pt) && (op2b != op2)) op2b = op2b->Prev; + if ((op2b->Pt.Y > op2->Pt.Y) || + !SlopesEqual(op2->Pt, op2b->Pt, j->OffPt, m_UseFullRange)) return false; + } + + if ((op1b == op1) || (op2b == op2) || (op1b == op2b) || + ((outRec1 == outRec2) && (Reverse1 == Reverse2))) return false; + + if (Reverse1) + { + op1b = this->DupOutPt(op1, false); + op2b = this->DupOutPt(op2, true); + op1->Prev = op2; + op2->Next = op1; + op1b->Next = op2b; + op2b->Prev = op1b; + j->OutPt1 = op1; + j->OutPt2 = op1b; + return true; + } else + { + op1b = this->DupOutPt(op1, true); + op2b = this->DupOutPt(op2, false); + op1->Next = op2; + op2->Prev = op1; + op1b->Prev = op2b; + op2b->Next = op1b; + j->OutPt1 = op1; + j->OutPt2 = op1b; + return true; + } + } +} +//---------------------------------------------------------------------- + +// This is potentially very expensive! O(n^3)! +void Clipper::FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec) const +{ + PROFILE_FUNC(); + //tests if NewOutRec contains the polygon before reassigning FirstLeft + for (OutRec *outRec : m_PolyOuts) + { + if (!outRec->Pts || !outRec->FirstLeft) continue; + OutRec* firstLeft = outRec->FirstLeft; + // Skip empty polygons. + while (firstLeft && !firstLeft->Pts) firstLeft = firstLeft->FirstLeft; + if (firstLeft == OldOutRec && Poly2ContainsPoly1(outRec->Pts, NewOutRec->Pts)) + outRec->FirstLeft = NewOutRec; + } +} +//---------------------------------------------------------------------- + +void Clipper::FixupFirstLefts2(OutRec* OldOutRec, OutRec* NewOutRec) const +{ + //reassigns FirstLeft WITHOUT testing if NewOutRec contains the polygon + for (OutRec *outRec : m_PolyOuts) + if (outRec->FirstLeft == OldOutRec) outRec->FirstLeft = NewOutRec; +} +//---------------------------------------------------------------------- + +void Clipper::JoinCommonEdges() +{ + PROFILE_FUNC(); + for (Join &join : m_Joins) + { + OutRec *outRec1 = GetOutRec(join.OutPt1->Idx); + OutRec *outRec2 = GetOutRec(join.OutPt2->Idx); + + if (!outRec1->Pts || !outRec2->Pts) continue; + if (outRec1->IsOpen || outRec2->IsOpen) continue; + + //get the polygon fragment with the correct hole state (FirstLeft) + //before calling JoinPoints() ... + OutRec *holeStateRec; + if (outRec1 == outRec2) holeStateRec = outRec1; + else if (Param1RightOfParam2(outRec1, outRec2)) holeStateRec = outRec2; + else if (Param1RightOfParam2(outRec2, outRec1)) holeStateRec = outRec1; + else holeStateRec = GetLowermostRec(outRec1, outRec2); + + if (!JoinPoints(&join, outRec1, outRec2)) continue; + + if (outRec1 == outRec2) + { + //instead of joining two polygons, we've just created a new one by + //splitting one polygon into two. + outRec1->Pts = join.OutPt1; + outRec1->BottomPt = 0; + outRec2 = CreateOutRec(); + outRec2->Pts = join.OutPt2; + + //update all OutRec2.Pts Idx's ... + UpdateOutPtIdxs(*outRec2); + + //We now need to check every OutRec.FirstLeft pointer. If it points + //to OutRec1 it may need to point to OutRec2 instead ... + if (m_UsingPolyTree) + for (size_t j = 0; j < m_PolyOuts.size() - 1; j++) + { + OutRec* oRec = m_PolyOuts[j]; + OutRec* firstLeft = oRec->FirstLeft; + while (firstLeft && !firstLeft->Pts) firstLeft = firstLeft->FirstLeft; + if (!oRec->Pts || firstLeft != outRec1 || + oRec->IsHole == outRec1->IsHole) continue; + if (Poly2ContainsPoly1(oRec->Pts, join.OutPt2)) + oRec->FirstLeft = outRec2; + } + + if (Poly2ContainsPoly1(outRec2->Pts, outRec1->Pts)) + { + //outRec2 is contained by outRec1 ... + outRec2->IsHole = !outRec1->IsHole; + outRec2->FirstLeft = outRec1; + + // For each m_PolyOuts, replace FirstLeft from outRec2 to outRec1. + if (m_UsingPolyTree) FixupFirstLefts2(outRec2, outRec1); + + if ((outRec2->IsHole ^ m_ReverseOutput) == (Area(*outRec2) > 0)) + ReversePolyPtLinks(outRec2->Pts); + + } else if (Poly2ContainsPoly1(outRec1->Pts, outRec2->Pts)) + { + //outRec1 is contained by outRec2 ... + outRec2->IsHole = outRec1->IsHole; + outRec1->IsHole = !outRec2->IsHole; + outRec2->FirstLeft = outRec1->FirstLeft; + outRec1->FirstLeft = outRec2; + + // For each m_PolyOuts, replace FirstLeft from outRec1 to outRec2. + if (m_UsingPolyTree) FixupFirstLefts2(outRec1, outRec2); + + if ((outRec1->IsHole ^ m_ReverseOutput) == (Area(*outRec1) > 0)) + ReversePolyPtLinks(outRec1->Pts); + } + else + { + //the 2 polygons are completely separate ... + outRec2->IsHole = outRec1->IsHole; + outRec2->FirstLeft = outRec1->FirstLeft; + + //fixup FirstLeft pointers that may need reassigning to OutRec2 + // For each polygon of m_PolyOuts, replace FirstLeft from outRec1 to outRec2 if the polygon is inside outRec2. + //FIXME This is potentially very expensive! O(n^3)! + if (m_UsingPolyTree) FixupFirstLefts1(outRec1, outRec2); + } + + } else + { + //joined 2 polygons together ... + + outRec2->Pts = 0; + outRec2->BottomPt = 0; + outRec2->Idx = outRec1->Idx; + + outRec1->IsHole = holeStateRec->IsHole; + if (holeStateRec == outRec2) + outRec1->FirstLeft = outRec2->FirstLeft; + outRec2->FirstLeft = outRec1; + + // For each m_PolyOuts, replace FirstLeft from outRec2 to outRec1. + if (m_UsingPolyTree) FixupFirstLefts2(outRec2, outRec1); + } + } +} + +//------------------------------------------------------------------------------ +// ClipperOffset support functions ... +//------------------------------------------------------------------------------ + +DoublePoint GetUnitNormal(const IntPoint &pt1, const IntPoint &pt2) +{ + if(pt2.X == pt1.X && pt2.Y == pt1.Y) + return DoublePoint(0, 0); + + double Dx = (double)(pt2.X - pt1.X); + double dy = (double)(pt2.Y - pt1.Y); + double f = 1 *1.0/ std::sqrt( Dx*Dx + dy*dy ); + Dx *= f; + dy *= f; + return DoublePoint(dy, -Dx); +} + +//------------------------------------------------------------------------------ +// ClipperOffset class +//------------------------------------------------------------------------------ + +void ClipperOffset::Clear() +{ + for (int i = 0; i < m_polyNodes.ChildCount(); ++i) + delete m_polyNodes.Childs[i]; + m_polyNodes.Childs.clear(); + m_lowest.X = -1; +} +//------------------------------------------------------------------------------ + +void ClipperOffset::AddPath(const Path& path, JoinType joinType, EndType endType) +{ + int highI = (int)path.size() - 1; + if (highI < 0) return; + PolyNode* newNode = new PolyNode(); + newNode->m_jointype = joinType; + newNode->m_endtype = endType; + + //strip duplicate points from path and also get index to the lowest point ... + bool has_shortest_edge_length = ShortestEdgeLength > 0.; + double shortest_edge_length2 = has_shortest_edge_length ? ShortestEdgeLength * ShortestEdgeLength : 0.; + if (endType == etClosedLine || endType == etClosedPolygon) + for (; highI > 0; -- highI) { + bool same = false; + if (has_shortest_edge_length) { + double dx = double(path[highI].X - path[0].X); + double dy = double(path[highI].Y - path[0].Y); + same = dx*dx + dy*dy < shortest_edge_length2; + } else + same = path[0] == path[highI]; + if (! same) + break; + } + newNode->Contour.reserve(highI + 1); + newNode->Contour.push_back(path[0]); + int j = 0, k = 0; + for (int i = 1; i <= highI; i++) { + bool same = false; + if (has_shortest_edge_length) { + double dx = double(path[i].X - newNode->Contour[j].X); + double dy = double(path[i].Y - newNode->Contour[j].Y); + same = dx*dx + dy*dy < shortest_edge_length2; + } else + same = newNode->Contour[j] == path[i]; + if (same) + continue; + j++; + newNode->Contour.push_back(path[i]); + if (path[i].Y > newNode->Contour[k].Y || + (path[i].Y == newNode->Contour[k].Y && + path[i].X < newNode->Contour[k].X)) k = j; + } + if (endType == etClosedPolygon && j < 2) + { + delete newNode; + return; + } + m_polyNodes.AddChild(*newNode); + + //if this path's lowest pt is lower than all the others then update m_lowest + if (endType != etClosedPolygon) return; + if (m_lowest.X < 0) + m_lowest = IntPoint(m_polyNodes.ChildCount() - 1, k); + else + { + IntPoint ip = m_polyNodes.Childs[(int)m_lowest.X]->Contour[(int)m_lowest.Y]; + if (newNode->Contour[k].Y > ip.Y || + (newNode->Contour[k].Y == ip.Y && + newNode->Contour[k].X < ip.X)) + m_lowest = IntPoint(m_polyNodes.ChildCount() - 1, k); + } +} +//------------------------------------------------------------------------------ + +void ClipperOffset::AddPaths(const Paths& paths, JoinType joinType, EndType endType) +{ + for (const Path &path : paths) + AddPath(path, joinType, endType); +} +//------------------------------------------------------------------------------ + +void ClipperOffset::FixOrientations() +{ + //fixup orientations of all closed paths if the orientation of the + //closed path with the lowermost vertex is wrong ... + if (m_lowest.X >= 0 && + !Orientation(m_polyNodes.Childs[(int)m_lowest.X]->Contour)) + { + for (int i = 0; i < m_polyNodes.ChildCount(); ++i) + { + PolyNode& node = *m_polyNodes.Childs[i]; + if (node.m_endtype == etClosedPolygon || + (node.m_endtype == etClosedLine && Orientation(node.Contour))) + ReversePath(node.Contour); + } + } else + { + for (int i = 0; i < m_polyNodes.ChildCount(); ++i) + { + PolyNode& node = *m_polyNodes.Childs[i]; + if (node.m_endtype == etClosedLine && !Orientation(node.Contour)) + ReversePath(node.Contour); + } + } +} +//------------------------------------------------------------------------------ + +void ClipperOffset::Execute(Paths& solution, double delta) +{ + solution.clear(); + FixOrientations(); + DoOffset(delta); + + //now clean up 'corners' ... + Clipper clpr; + clpr.AddPaths(m_destPolys, ptSubject, true); + if (delta > 0) + { + clpr.Execute(ctUnion, solution, pftPositive, pftPositive); + } + else + { + IntRect r = clpr.GetBounds(); + Path outer(4); + outer[0] = IntPoint(r.left - 10, r.bottom + 10); + outer[1] = IntPoint(r.right + 10, r.bottom + 10); + outer[2] = IntPoint(r.right + 10, r.top - 10); + outer[3] = IntPoint(r.left - 10, r.top - 10); + + clpr.AddPath(outer, ptSubject, true); + clpr.ReverseSolution(true); + clpr.Execute(ctUnion, solution, pftNegative, pftNegative); + if (solution.size() > 0) solution.erase(solution.begin()); + } +} +//------------------------------------------------------------------------------ + +void ClipperOffset::Execute(PolyTree& solution, double delta) +{ + solution.Clear(); + FixOrientations(); + DoOffset(delta); + + //now clean up 'corners' ... + Clipper clpr; + clpr.AddPaths(m_destPolys, ptSubject, true); + if (delta > 0) + { + clpr.Execute(ctUnion, solution, pftPositive, pftPositive); + } + else + { + IntRect r = clpr.GetBounds(); + Path outer(4); + outer[0] = IntPoint(r.left - 10, r.bottom + 10); + outer[1] = IntPoint(r.right + 10, r.bottom + 10); + outer[2] = IntPoint(r.right + 10, r.top - 10); + outer[3] = IntPoint(r.left - 10, r.top - 10); + + clpr.AddPath(outer, ptSubject, true); + clpr.ReverseSolution(true); + clpr.Execute(ctUnion, solution, pftNegative, pftNegative); + //remove the outer PolyNode rectangle ... + if (solution.ChildCount() == 1 && solution.Childs[0]->ChildCount() > 0) + { + PolyNode* outerNode = solution.Childs[0]; + solution.Childs.reserve(outerNode->ChildCount()); + solution.Childs[0] = outerNode->Childs[0]; + solution.Childs[0]->Parent = outerNode->Parent; + for (int i = 1; i < outerNode->ChildCount(); ++i) + solution.AddChild(*outerNode->Childs[i]); + } + else + solution.Clear(); + } +} +//------------------------------------------------------------------------------ + +void ClipperOffset::DoOffset(double delta) +{ + m_destPolys.clear(); + m_delta = delta; + + //if Zero offset, just copy any CLOSED polygons to m_p and return ... + if (NEAR_ZERO(delta)) + { + m_destPolys.reserve(m_polyNodes.ChildCount()); + for (int i = 0; i < m_polyNodes.ChildCount(); i++) + { + PolyNode& node = *m_polyNodes.Childs[i]; + if (node.m_endtype == etClosedPolygon) + m_destPolys.push_back(node.Contour); + } + return; + } + + //see offset_triginometry3.svg in the documentation folder ... + if (MiterLimit > 2) m_miterLim = 2/(MiterLimit * MiterLimit); + else m_miterLim = 0.5; + + double y; + if (ArcTolerance <= 0.0) y = def_arc_tolerance; + else if (ArcTolerance > std::fabs(delta) * def_arc_tolerance) + y = std::fabs(delta) * def_arc_tolerance; + else y = ArcTolerance; + //see offset_triginometry2.svg in the documentation folder ... + double steps = pi / std::acos(1 - y / std::fabs(delta)); + if (steps > std::fabs(delta) * pi) + steps = std::fabs(delta) * pi; //ie excessive precision check + m_sin = std::sin(two_pi / steps); + m_cos = std::cos(two_pi / steps); + m_StepsPerRad = steps / two_pi; + if (delta < 0.0) m_sin = -m_sin; + + m_destPolys.reserve(m_polyNodes.ChildCount() * 2); + for (int i = 0; i < m_polyNodes.ChildCount(); i++) + { + PolyNode& node = *m_polyNodes.Childs[i]; + m_srcPoly = node.Contour; + + int len = (int)m_srcPoly.size(); + if (len == 0 || (delta <= 0 && (len < 3 || node.m_endtype != etClosedPolygon))) + continue; + + m_destPoly.clear(); + if (len == 1) + { + if (node.m_jointype == jtRound) + { + double X = 1.0, Y = 0.0; + for (cInt j = 1; j <= steps; j++) + { + m_destPoly.push_back(IntPoint( + Round(m_srcPoly[0].X + X * delta), + Round(m_srcPoly[0].Y + Y * delta))); + double X2 = X; + X = X * m_cos - m_sin * Y; + Y = X2 * m_sin + Y * m_cos; + } + } + else + { + double X = -1.0, Y = -1.0; + for (int j = 0; j < 4; ++j) + { + m_destPoly.push_back(IntPoint( + Round(m_srcPoly[0].X + X * delta), + Round(m_srcPoly[0].Y + Y * delta))); + if (X < 0) X = 1; + else if (Y < 0) Y = 1; + else X = -1; + } + } + m_destPolys.push_back(m_destPoly); + continue; + } + //build m_normals ... + m_normals.clear(); + m_normals.reserve(len); + for (int j = 0; j < len - 1; ++j) + m_normals.push_back(GetUnitNormal(m_srcPoly[j], m_srcPoly[j + 1])); + if (node.m_endtype == etClosedLine || node.m_endtype == etClosedPolygon) + m_normals.push_back(GetUnitNormal(m_srcPoly[len - 1], m_srcPoly[0])); + else + m_normals.push_back(DoublePoint(m_normals[len - 2])); + + if (node.m_endtype == etClosedPolygon) + { + int k = len - 1; + for (int j = 0; j < len; ++j) + OffsetPoint(j, k, node.m_jointype); + m_destPolys.push_back(m_destPoly); + } + else if (node.m_endtype == etClosedLine) + { + int k = len - 1; + for (int j = 0; j < len; ++j) + OffsetPoint(j, k, node.m_jointype); + m_destPolys.push_back(m_destPoly); + m_destPoly.clear(); + //re-build m_normals ... + DoublePoint n = m_normals[len -1]; + for (int j = len - 1; j > 0; j--) + m_normals[j] = DoublePoint(-m_normals[j - 1].X, -m_normals[j - 1].Y); + m_normals[0] = DoublePoint(-n.X, -n.Y); + k = 0; + for (int j = len - 1; j >= 0; j--) + OffsetPoint(j, k, node.m_jointype); + m_destPolys.push_back(m_destPoly); + } + else + { + int k = 0; + for (int j = 1; j < len - 1; ++j) + OffsetPoint(j, k, node.m_jointype); + + IntPoint pt1; + if (node.m_endtype == etOpenButt) + { + int j = len - 1; + pt1 = IntPoint(Round(m_srcPoly[j].X + m_normals[j].X * + delta), Round(m_srcPoly[j].Y + m_normals[j].Y * delta)); + m_destPoly.push_back(pt1); + pt1 = IntPoint(Round(m_srcPoly[j].X - m_normals[j].X * + delta), Round(m_srcPoly[j].Y - m_normals[j].Y * delta)); + m_destPoly.push_back(pt1); + } + else + { + int j = len - 1; + k = len - 2; + m_sinA = 0; + m_normals[j] = DoublePoint(-m_normals[j].X, -m_normals[j].Y); + if (node.m_endtype == etOpenSquare) + DoSquare(j, k); + else + DoRound(j, k); + } + + //re-build m_normals ... + for (int j = len - 1; j > 0; j--) + m_normals[j] = DoublePoint(-m_normals[j - 1].X, -m_normals[j - 1].Y); + m_normals[0] = DoublePoint(-m_normals[1].X, -m_normals[1].Y); + + k = len - 1; + for (int j = k - 1; j > 0; --j) OffsetPoint(j, k, node.m_jointype); + + if (node.m_endtype == etOpenButt) + { + pt1 = IntPoint(Round(m_srcPoly[0].X - m_normals[0].X * delta), + Round(m_srcPoly[0].Y - m_normals[0].Y * delta)); + m_destPoly.push_back(pt1); + pt1 = IntPoint(Round(m_srcPoly[0].X + m_normals[0].X * delta), + Round(m_srcPoly[0].Y + m_normals[0].Y * delta)); + m_destPoly.push_back(pt1); + } + else + { + k = 1; + m_sinA = 0; + if (node.m_endtype == etOpenSquare) + DoSquare(0, 1); + else + DoRound(0, 1); + } + m_destPolys.push_back(m_destPoly); + } + } +} +//------------------------------------------------------------------------------ + +void ClipperOffset::OffsetPoint(int j, int& k, JoinType jointype) +{ + //cross product ... + m_sinA = (m_normals[k].X * m_normals[j].Y - m_normals[j].X * m_normals[k].Y); + if (std::fabs(m_sinA * m_delta) < 1.0) + { + //dot product ... + double cosA = (m_normals[k].X * m_normals[j].X + m_normals[j].Y * m_normals[k].Y ); + if (cosA > 0) // angle => 0 degrees + { + m_destPoly.push_back(IntPoint(Round(m_srcPoly[j].X + m_normals[k].X * m_delta), + Round(m_srcPoly[j].Y + m_normals[k].Y * m_delta))); + return; + } + //else angle => 180 degrees + } + else if (m_sinA > 1.0) m_sinA = 1.0; + else if (m_sinA < -1.0) m_sinA = -1.0; + + if (m_sinA * m_delta < 0) + { + m_destPoly.push_back(IntPoint(Round(m_srcPoly[j].X + m_normals[k].X * m_delta), + Round(m_srcPoly[j].Y + m_normals[k].Y * m_delta))); + m_destPoly.push_back(m_srcPoly[j]); + m_destPoly.push_back(IntPoint(Round(m_srcPoly[j].X + m_normals[j].X * m_delta), + Round(m_srcPoly[j].Y + m_normals[j].Y * m_delta))); + } + else + switch (jointype) + { + case jtMiter: + { + double r = 1 + (m_normals[j].X * m_normals[k].X + + m_normals[j].Y * m_normals[k].Y); + if (r >= m_miterLim) DoMiter(j, k, r); else DoSquare(j, k); + break; + } + case jtSquare: DoSquare(j, k); break; + case jtRound: DoRound(j, k); break; + } + k = j; +} +//------------------------------------------------------------------------------ + +void ClipperOffset::DoSquare(int j, int k) +{ + double dx = std::tan(std::atan2(m_sinA, + m_normals[k].X * m_normals[j].X + m_normals[k].Y * m_normals[j].Y) / 4); + m_destPoly.push_back(IntPoint( + Round(m_srcPoly[j].X + m_delta * (m_normals[k].X - m_normals[k].Y * dx)), + Round(m_srcPoly[j].Y + m_delta * (m_normals[k].Y + m_normals[k].X * dx)))); + m_destPoly.push_back(IntPoint( + Round(m_srcPoly[j].X + m_delta * (m_normals[j].X + m_normals[j].Y * dx)), + Round(m_srcPoly[j].Y + m_delta * (m_normals[j].Y - m_normals[j].X * dx)))); +} +//------------------------------------------------------------------------------ + +void ClipperOffset::DoMiter(int j, int k, double r) +{ + double q = m_delta / r; + m_destPoly.push_back(IntPoint(Round(m_srcPoly[j].X + (m_normals[k].X + m_normals[j].X) * q), + Round(m_srcPoly[j].Y + (m_normals[k].Y + m_normals[j].Y) * q))); +} +//------------------------------------------------------------------------------ + +void ClipperOffset::DoRound(int j, int k) +{ + double a = std::atan2(m_sinA, + m_normals[k].X * m_normals[j].X + m_normals[k].Y * m_normals[j].Y); + int steps = std::max((int)Round(m_StepsPerRad * std::fabs(a)), 1); + + double X = m_normals[k].X, Y = m_normals[k].Y, X2; + for (int i = 0; i < steps; ++i) + { + m_destPoly.push_back(IntPoint( + Round(m_srcPoly[j].X + X * m_delta), + Round(m_srcPoly[j].Y + Y * m_delta))); + X2 = X; + X = X * m_cos - m_sin * Y; + Y = X2 * m_sin + Y * m_cos; + } + m_destPoly.push_back(IntPoint( + Round(m_srcPoly[j].X + m_normals[j].X * m_delta), + Round(m_srcPoly[j].Y + m_normals[j].Y * m_delta))); +} + +//------------------------------------------------------------------------------ +// Miscellaneous public functions +//------------------------------------------------------------------------------ + +// Called by Clipper::ExecuteInternal() +// For each polygon, search for exactly duplicate non-successive points. +// If such a point is found, the loop is split into two pieces. +// Search for the duplicate points is O(n^2)! +// http://www.angusj.com/delphi/clipper/documentation/Docs/Units/ClipperLib/Classes/Clipper/Properties/StrictlySimple.htm +void Clipper::DoSimplePolygons() +{ + PROFILE_FUNC(); + size_t i = 0; + while (i < m_PolyOuts.size()) + { + OutRec* outrec = m_PolyOuts[i++]; + OutPt* op = outrec->Pts; + if (!op || outrec->IsOpen) continue; + do //for each Pt in Polygon until duplicate found do ... + { + OutPt* op2 = op->Next; + while (op2 != outrec->Pts) + { + if ((op->Pt == op2->Pt) && op2->Next != op && op2->Prev != op) + { + //split the polygon into two ... + OutPt* op3 = op->Prev; + OutPt* op4 = op2->Prev; + op->Prev = op4; + op4->Next = op; + op2->Prev = op3; + op3->Next = op2; + + outrec->Pts = op; + OutRec* outrec2 = CreateOutRec(); + outrec2->Pts = op2; + UpdateOutPtIdxs(*outrec2); + if (Poly2ContainsPoly1(outrec2->Pts, outrec->Pts)) + { + //OutRec2 is contained by OutRec1 ... + outrec2->IsHole = !outrec->IsHole; + outrec2->FirstLeft = outrec; + // For each m_PolyOuts, replace FirstLeft from outRec2 to outrec. + if (m_UsingPolyTree) FixupFirstLefts2(outrec2, outrec); + } + else + if (Poly2ContainsPoly1(outrec->Pts, outrec2->Pts)) + { + //OutRec1 is contained by OutRec2 ... + outrec2->IsHole = outrec->IsHole; + outrec->IsHole = !outrec2->IsHole; + outrec2->FirstLeft = outrec->FirstLeft; + outrec->FirstLeft = outrec2; + // For each m_PolyOuts, replace FirstLeft from outrec to outrec2. + if (m_UsingPolyTree) FixupFirstLefts2(outrec, outrec2); + } + else + { + //the 2 polygons are separate ... + outrec2->IsHole = outrec->IsHole; + outrec2->FirstLeft = outrec->FirstLeft; + // For each polygon of m_PolyOuts, replace FirstLeft from outrec to outrec2 if the polygon is inside outRec2. + //FIXME This is potentially very expensive! O(n^3)! + if (m_UsingPolyTree) FixupFirstLefts1(outrec, outrec2); + } + op2 = op; //ie get ready for the Next iteration + } + op2 = op2->Next; + } + op = op->Next; + } + while (op != outrec->Pts); + } +} +//------------------------------------------------------------------------------ + +void ReversePath(Path& p) +{ + std::reverse(p.begin(), p.end()); +} +//------------------------------------------------------------------------------ + +void ReversePaths(Paths& p) +{ + for (Paths::size_type i = 0; i < p.size(); ++i) + ReversePath(p[i]); +} +//------------------------------------------------------------------------------ + +void SimplifyPolygon(const Path &in_poly, Paths &out_polys, PolyFillType fillType) +{ + Clipper c; + c.StrictlySimple(true); + c.AddPath(in_poly, ptSubject, true); + c.Execute(ctUnion, out_polys, fillType, fillType); +} +//------------------------------------------------------------------------------ + +void SimplifyPolygons(const Paths &in_polys, Paths &out_polys, PolyFillType fillType) +{ + Clipper c; + c.StrictlySimple(true); + c.AddPaths(in_polys, ptSubject, true); + c.Execute(ctUnion, out_polys, fillType, fillType); +} +//------------------------------------------------------------------------------ + +void SimplifyPolygons(Paths &polys, PolyFillType fillType) +{ + SimplifyPolygons(polys, polys, fillType); +} +//------------------------------------------------------------------------------ + +inline double DistanceSqrd(const IntPoint& pt1, const IntPoint& pt2) +{ + double Dx = ((double)pt1.X - pt2.X); + double dy = ((double)pt1.Y - pt2.Y); + return (Dx*Dx + dy*dy); +} +//------------------------------------------------------------------------------ + +double DistanceFromLineSqrd( + const IntPoint& pt, const IntPoint& ln1, const IntPoint& ln2) +{ + //The equation of a line in general form (Ax + By + C = 0) + //given 2 points (x¹,y¹) & (x²,y²) is ... + //(y¹ - y²)x + (x² - x¹)y + (y² - y¹)x¹ - (x² - x¹)y¹ = 0 + //A = (y¹ - y²); B = (x² - x¹); C = (y² - y¹)x¹ - (x² - x¹)y¹ + //perpendicular distance of point (x³,y³) = (Ax³ + By³ + C)/Sqrt(A² + B²) + //see http://en.wikipedia.org/wiki/Perpendicular_distance + double A = double(ln1.Y - ln2.Y); + double B = double(ln2.X - ln1.X); + double C = A * ln1.X + B * ln1.Y; + C = A * pt.X + B * pt.Y - C; + return (C * C) / (A * A + B * B); +} +//--------------------------------------------------------------------------- + +bool SlopesNearCollinear(const IntPoint& pt1, + const IntPoint& pt2, const IntPoint& pt3, double distSqrd) +{ + //this function is more accurate when the point that's geometrically + //between the other 2 points is the one that's tested for distance. + //ie makes it more likely to pick up 'spikes' ... + if (std::abs(pt1.X - pt2.X) > std::abs(pt1.Y - pt2.Y)) + { + if ((pt1.X > pt2.X) == (pt1.X < pt3.X)) + return DistanceFromLineSqrd(pt1, pt2, pt3) < distSqrd; + else if ((pt2.X > pt1.X) == (pt2.X < pt3.X)) + return DistanceFromLineSqrd(pt2, pt1, pt3) < distSqrd; + else + return DistanceFromLineSqrd(pt3, pt1, pt2) < distSqrd; + } + else + { + if ((pt1.Y > pt2.Y) == (pt1.Y < pt3.Y)) + return DistanceFromLineSqrd(pt1, pt2, pt3) < distSqrd; + else if ((pt2.Y > pt1.Y) == (pt2.Y < pt3.Y)) + return DistanceFromLineSqrd(pt2, pt1, pt3) < distSqrd; + else + return DistanceFromLineSqrd(pt3, pt1, pt2) < distSqrd; + } +} +//------------------------------------------------------------------------------ + +bool PointsAreClose(IntPoint pt1, IntPoint pt2, double distSqrd) +{ + double Dx = (double)pt1.X - pt2.X; + double dy = (double)pt1.Y - pt2.Y; + return ((Dx * Dx) + (dy * dy) <= distSqrd); +} +//------------------------------------------------------------------------------ + +OutPt* ExcludeOp(OutPt* op) +{ + OutPt* result = op->Prev; + result->Next = op->Next; + op->Next->Prev = result; + result->Idx = 0; + return result; +} +//------------------------------------------------------------------------------ + +// Simplify a polygon using a linked list of points. +void CleanPolygon(const Path& in_poly, Path& out_poly, double distance) +{ + //distance = proximity in units/pixels below which vertices + //will be stripped. Default ~= sqrt(2). + + size_t size = in_poly.size(); + + if (size == 0) + { + out_poly.clear(); + return; + } + + std::vector outPts(size); + for (size_t i = 0; i < size; ++i) + { + outPts[i].Pt = in_poly[i]; + outPts[i].Next = &outPts[(i + 1) % size]; + outPts[i].Next->Prev = &outPts[i]; + outPts[i].Idx = 0; + } + + double distSqrd = distance * distance; + OutPt* op = &outPts[0]; + while (op->Idx == 0 && op->Next != op->Prev) + { + if (PointsAreClose(op->Pt, op->Prev->Pt, distSqrd)) + { + op = ExcludeOp(op); + size--; + } + else if (PointsAreClose(op->Prev->Pt, op->Next->Pt, distSqrd)) + { + ExcludeOp(op->Next); + op = ExcludeOp(op); + size -= 2; + } + else if (SlopesNearCollinear(op->Prev->Pt, op->Pt, op->Next->Pt, distSqrd)) + { + op = ExcludeOp(op); + size--; + } + else + { + op->Idx = 1; + op = op->Next; + } + } + + if (size < 3) size = 0; + out_poly.resize(size); + for (size_t i = 0; i < size; ++i) + { + out_poly[i] = op->Pt; + op = op->Next; + } +} +//------------------------------------------------------------------------------ + +void CleanPolygon(Path& poly, double distance) +{ + CleanPolygon(poly, poly, distance); +} +//------------------------------------------------------------------------------ + +void CleanPolygons(const Paths& in_polys, Paths& out_polys, double distance) +{ + for (Paths::size_type i = 0; i < in_polys.size(); ++i) + CleanPolygon(in_polys[i], out_polys[i], distance); +} +//------------------------------------------------------------------------------ + +void CleanPolygons(Paths& polys, double distance) +{ + CleanPolygons(polys, polys, distance); +} +//------------------------------------------------------------------------------ + +void Minkowski(const Path& poly, const Path& path, + Paths& solution, bool isSum, bool isClosed) +{ + int delta = (isClosed ? 1 : 0); + size_t polyCnt = poly.size(); + size_t pathCnt = path.size(); + Paths pp; + pp.reserve(pathCnt); + if (isSum) + for (size_t i = 0; i < pathCnt; ++i) + { + Path p; + p.reserve(polyCnt); + for (size_t j = 0; j < poly.size(); ++j) + p.push_back(IntPoint(path[i].X + poly[j].X, path[i].Y + poly[j].Y)); + pp.push_back(p); + } + else + for (size_t i = 0; i < pathCnt; ++i) + { + Path p; + p.reserve(polyCnt); + for (size_t j = 0; j < poly.size(); ++j) + p.push_back(IntPoint(path[i].X - poly[j].X, path[i].Y - poly[j].Y)); + pp.push_back(p); + } + + solution.clear(); + solution.reserve((pathCnt + delta) * (polyCnt + 1)); + for (size_t i = 0; i < pathCnt - 1 + delta; ++i) + for (size_t j = 0; j < polyCnt; ++j) + { + Path quad; + quad.reserve(4); + quad.push_back(pp[i % pathCnt][j % polyCnt]); + quad.push_back(pp[(i + 1) % pathCnt][j % polyCnt]); + quad.push_back(pp[(i + 1) % pathCnt][(j + 1) % polyCnt]); + quad.push_back(pp[i % pathCnt][(j + 1) % polyCnt]); + if (!Orientation(quad)) ReversePath(quad); + solution.push_back(quad); + } +} +//------------------------------------------------------------------------------ + +void MinkowskiSum(const Path& pattern, const Path& path, Paths& solution, bool pathIsClosed) +{ + Minkowski(pattern, path, solution, true, pathIsClosed); + Clipper c; + c.AddPaths(solution, ptSubject, true); + c.Execute(ctUnion, solution, pftNonZero, pftNonZero); +} +//------------------------------------------------------------------------------ + +void TranslatePath(const Path& input, Path& output, const IntPoint& delta) +{ + //precondition: input != output + output.resize(input.size()); + for (size_t i = 0; i < input.size(); ++i) + output[i] = IntPoint(input[i].X + delta.X, input[i].Y + delta.Y); +} +//------------------------------------------------------------------------------ + +void MinkowskiSum(const Path& pattern, const Paths& paths, Paths& solution, bool pathIsClosed) +{ + Clipper c; + for (size_t i = 0; i < paths.size(); ++i) + { + Paths tmp; + Minkowski(pattern, paths[i], tmp, true, pathIsClosed); + c.AddPaths(tmp, ptSubject, true); + if (pathIsClosed) + { + Path tmp2; + TranslatePath(paths[i], tmp2, pattern[0]); + c.AddPath(tmp2, ptClip, true); + } + } + c.Execute(ctUnion, solution, pftNonZero, pftNonZero); +} +//------------------------------------------------------------------------------ + +void MinkowskiDiff(const Path& poly1, const Path& poly2, Paths& solution) +{ + Minkowski(poly1, poly2, solution, false, true); + Clipper c; + c.AddPaths(solution, ptSubject, true); + c.Execute(ctUnion, solution, pftNonZero, pftNonZero); +} +//------------------------------------------------------------------------------ + +enum NodeType {ntAny, ntOpen, ntClosed}; + +void AddPolyNodeToPaths(const PolyNode& polynode, NodeType nodetype, Paths& paths) +{ + bool match = true; + if (nodetype == ntClosed) match = !polynode.IsOpen(); + else if (nodetype == ntOpen) return; + + if (!polynode.Contour.empty() && match) + paths.push_back(polynode.Contour); + for (int i = 0; i < polynode.ChildCount(); ++i) + AddPolyNodeToPaths(*polynode.Childs[i], nodetype, paths); +} +//------------------------------------------------------------------------------ + +void PolyTreeToPaths(const PolyTree& polytree, Paths& paths) +{ + paths.resize(0); + paths.reserve(polytree.Total()); + AddPolyNodeToPaths(polytree, ntAny, paths); +} +//------------------------------------------------------------------------------ + +void ClosedPathsFromPolyTree(const PolyTree& polytree, Paths& paths) +{ + paths.resize(0); + paths.reserve(polytree.Total()); + AddPolyNodeToPaths(polytree, ntClosed, paths); +} +//------------------------------------------------------------------------------ + +void OpenPathsFromPolyTree(PolyTree& polytree, Paths& paths) +{ + paths.resize(0); + paths.reserve(polytree.Total()); + //Open paths are top level only, so ... + for (int i = 0; i < polytree.ChildCount(); ++i) + if (polytree.Childs[i]->IsOpen()) + paths.push_back(polytree.Childs[i]->Contour); +} +//------------------------------------------------------------------------------ + +std::ostream& operator <<(std::ostream &s, const IntPoint &p) +{ + s << "(" << p.X << "," << p.Y << ")"; + return s; +} +//------------------------------------------------------------------------------ + +std::ostream& operator <<(std::ostream &s, const Path &p) +{ + if (p.empty()) return s; + Path::size_type last = p.size() -1; + for (Path::size_type i = 0; i < last; i++) + s << "(" << p[i].X << "," << p[i].Y << "), "; + s << "(" << p[last].X << "," << p[last].Y << ")\n"; + return s; +} +//------------------------------------------------------------------------------ + +std::ostream& operator <<(std::ostream &s, const Paths &p) +{ + for (Paths::size_type i = 0; i < p.size(); i++) + s << p[i]; + s << "\n"; + return s; +} +//------------------------------------------------------------------------------ + +} //ClipperLib namespace diff --git a/xs/src/clipper.hpp b/src/clipper/clipper.hpp similarity index 97% rename from xs/src/clipper.hpp rename to src/clipper/clipper.hpp index 2e70696197..8a28fe46f7 100644 --- a/xs/src/clipper.hpp +++ b/src/clipper/clipper.hpp @@ -1,487 +1,487 @@ -/******************************************************************************* -* * -* Author : Angus Johnson * -* Version : 6.2.9 * -* Date : 16 February 2015 * -* Website : http://www.angusj.com * -* Copyright : Angus Johnson 2010-2015 * -* * -* License: * -* Use, modification & distribution is subject to Boost Software License Ver 1. * -* http://www.boost.org/LICENSE_1_0.txt * -* * -* Attributions: * -* The code in this library is an extension of Bala Vatti's clipping algorithm: * -* "A generic solution to polygon clipping" * -* Communications of the ACM, Vol 35, Issue 7 (July 1992) pp 56-63. * -* http://portal.acm.org/citation.cfm?id=129906 * -* * -* Computer graphics and geometric modeling: implementation and algorithms * -* By Max K. Agoston * -* Springer; 1 edition (January 4, 2005) * -* http://books.google.com/books?q=vatti+clipping+agoston * -* * -* See also: * -* "Polygon Offsetting by Computing Winding Numbers" * -* Paper no. DETC2005-85513 pp. 565-575 * -* ASME 2005 International Design Engineering Technical Conferences * -* and Computers and Information in Engineering Conference (IDETC/CIE2005) * -* September 24-28, 2005 , Long Beach, California, USA * -* http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf * -* * -*******************************************************************************/ - -#ifndef clipper_hpp -#define clipper_hpp - -#include - -#define CLIPPER_VERSION "6.2.6" - -//use_xyz: adds a Z member to IntPoint. Adds a minor cost to perfomance. -//#define use_xyz - -//use_lines: Enables line clipping. Adds a very minor cost to performance. -#define use_lines - -//use_deprecated: Enables temporary support for the obsolete functions -//#define use_deprecated - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace ClipperLib { - -enum ClipType { ctIntersection, ctUnion, ctDifference, ctXor }; -enum PolyType { ptSubject, ptClip }; -//By far the most widely used winding rules for polygon filling are -//EvenOdd & NonZero (GDI, GDI+, XLib, OpenGL, Cairo, AGG, Quartz, SVG, Gr32) -//Others rules include Positive, Negative and ABS_GTR_EQ_TWO (only in OpenGL) -//see http://glprogramming.com/red/chapter11.html -enum PolyFillType { pftEvenOdd, pftNonZero, pftPositive, pftNegative }; - -// Point coordinate type -typedef int64_t cInt; -// Maximum cInt value to allow a cross product calculation using 32bit expressions. -static cInt const loRange = 0x3FFFFFFF; -// Maximum allowed cInt value. -static cInt const hiRange = 0x3FFFFFFFFFFFFFFFLL; - -struct IntPoint { - cInt X; - cInt Y; -#ifdef use_xyz - cInt Z; - IntPoint(cInt x = 0, cInt y = 0, cInt z = 0): X(x), Y(y), Z(z) {}; -#else - IntPoint(cInt x = 0, cInt y = 0): X(x), Y(y) {}; -#endif - - friend inline bool operator== (const IntPoint& a, const IntPoint& b) - { - return a.X == b.X && a.Y == b.Y; - } - friend inline bool operator!= (const IntPoint& a, const IntPoint& b) - { - return a.X != b.X || a.Y != b.Y; - } -}; -//------------------------------------------------------------------------------ - -typedef std::vector< IntPoint > Path; -typedef std::vector< Path > Paths; - -inline Path& operator <<(Path& poly, const IntPoint& p) {poly.push_back(p); return poly;} -inline Paths& operator <<(Paths& polys, const Path& p) {polys.push_back(p); return polys;} - -std::ostream& operator <<(std::ostream &s, const IntPoint &p); -std::ostream& operator <<(std::ostream &s, const Path &p); -std::ostream& operator <<(std::ostream &s, const Paths &p); - -struct DoublePoint -{ - double X; - double Y; - DoublePoint(double x = 0, double y = 0) : X(x), Y(y) {} - DoublePoint(IntPoint ip) : X((double)ip.X), Y((double)ip.Y) {} -}; -//------------------------------------------------------------------------------ - -#ifdef use_xyz -typedef void (*ZFillCallback)(IntPoint& e1bot, IntPoint& e1top, IntPoint& e2bot, IntPoint& e2top, IntPoint& pt); -#endif - -enum InitOptions {ioReverseSolution = 1, ioStrictlySimple = 2, ioPreserveCollinear = 4}; -enum JoinType {jtSquare, jtRound, jtMiter}; -enum EndType {etClosedPolygon, etClosedLine, etOpenButt, etOpenSquare, etOpenRound}; - -class PolyNode; -typedef std::vector< PolyNode* > PolyNodes; - -class PolyNode -{ -public: - PolyNode() : Childs(), Parent(0), Index(0), m_IsOpen(false) {} - virtual ~PolyNode(){}; - Path Contour; - PolyNodes Childs; - PolyNode* Parent; - // Traversal of the polygon tree in a depth first fashion. - PolyNode* GetNext() const { return Childs.empty() ? GetNextSiblingUp() : Childs.front(); } - bool IsHole() const; - bool IsOpen() const { return m_IsOpen; } - int ChildCount() const { return (int)Childs.size(); } -private: - unsigned Index; //node index in Parent.Childs - bool m_IsOpen; - JoinType m_jointype; - EndType m_endtype; - PolyNode* GetNextSiblingUp() const { return Parent ? ((Index == Parent->Childs.size() - 1) ? Parent->GetNextSiblingUp() : Parent->Childs[Index + 1]) : nullptr; } - void AddChild(PolyNode& child); - friend class Clipper; //to access Index - friend class ClipperOffset; - friend class PolyTree; //to implement the PolyTree::move operator -}; - -class PolyTree: public PolyNode -{ -public: - PolyTree() {} - PolyTree(PolyTree &&src) { *this = std::move(src); } - virtual ~PolyTree(){Clear();}; - PolyTree& operator=(PolyTree &&src) { - AllNodes = std::move(src.AllNodes); - Contour = std::move(src.Contour); - Childs = std::move(src.Childs); - Parent = nullptr; - Index = src.Index; - m_IsOpen = src.m_IsOpen; - m_jointype = src.m_jointype; - m_endtype = src.m_endtype; - for (size_t i = 0; i < Childs.size(); ++ i) - Childs[i]->Parent = this; - return *this; - } - PolyNode* GetFirst() const { return Childs.empty() ? nullptr : Childs.front(); } - void Clear() { AllNodes.clear(); Childs.clear(); } - int Total() const; -private: - PolyTree(const PolyTree &src) = delete; - PolyTree& operator=(const PolyTree &src) = delete; - std::vector AllNodes; - friend class Clipper; //to access AllNodes -}; - -double Area(const Path &poly); -inline bool Orientation(const Path &poly) { return Area(poly) >= 0; } -int PointInPolygon(const IntPoint &pt, const Path &path); - -void SimplifyPolygon(const Path &in_poly, Paths &out_polys, PolyFillType fillType = pftEvenOdd); -void SimplifyPolygons(const Paths &in_polys, Paths &out_polys, PolyFillType fillType = pftEvenOdd); -void SimplifyPolygons(Paths &polys, PolyFillType fillType = pftEvenOdd); - -void CleanPolygon(const Path& in_poly, Path& out_poly, double distance = 1.415); -void CleanPolygon(Path& poly, double distance = 1.415); -void CleanPolygons(const Paths& in_polys, Paths& out_polys, double distance = 1.415); -void CleanPolygons(Paths& polys, double distance = 1.415); - -void MinkowskiSum(const Path& pattern, const Path& path, Paths& solution, bool pathIsClosed); -void MinkowskiSum(const Path& pattern, const Paths& paths, Paths& solution, bool pathIsClosed); -void MinkowskiDiff(const Path& poly1, const Path& poly2, Paths& solution); - -void PolyTreeToPaths(const PolyTree& polytree, Paths& paths); -void ClosedPathsFromPolyTree(const PolyTree& polytree, Paths& paths); -void OpenPathsFromPolyTree(PolyTree& polytree, Paths& paths); - -void ReversePath(Path& p); -void ReversePaths(Paths& p); - -struct IntRect { cInt left; cInt top; cInt right; cInt bottom; }; - -//enums that are used internally ... -enum EdgeSide { esLeft = 1, esRight = 2}; - -// namespace Internal { - //forward declarations (for stuff used internally) ... - struct TEdge { - // Bottom point of this edge (with minimum Y). - IntPoint Bot; - // Current position. - IntPoint Curr; - // Top point of this edge (with maximum Y). - IntPoint Top; - // Vector from Bot to Top. - IntPoint Delta; - // Slope (dx/dy). For horiontal edges, the slope is set to HORIZONTAL (-1.0E+40). - double Dx; - PolyType PolyTyp; - EdgeSide Side; - // Winding number delta. 1 or -1 depending on winding direction, 0 for open paths and flat closed paths. - int WindDelta; - int WindCnt; - int WindCnt2; //winding count of the opposite polytype - int OutIdx; - // Next edge in the input path. - TEdge *Next; - // Previous edge in the input path. - TEdge *Prev; - // Next edge in the Local Minima List chain. - TEdge *NextInLML; - TEdge *NextInAEL; - TEdge *PrevInAEL; - TEdge *NextInSEL; - TEdge *PrevInSEL; - }; - - struct IntersectNode { - IntersectNode(TEdge *Edge1, TEdge *Edge2, IntPoint Pt) : - Edge1(Edge1), Edge2(Edge2), Pt(Pt) {} - TEdge *Edge1; - TEdge *Edge2; - IntPoint Pt; - }; - - struct LocalMinimum { - cInt Y; - TEdge *LeftBound; - TEdge *RightBound; - }; - - // Point of an output polygon. - // 36B on 64bit system without use_xyz. - struct OutPt { - // 4B - int Idx; - // 16B without use_xyz / 24B with use_xyz - IntPoint Pt; - // 4B on 32bit system, 8B on 64bit system - OutPt *Next; - // 4B on 32bit system, 8B on 64bit system - OutPt *Prev; - }; - - struct OutRec; - struct Join { - Join(OutPt *OutPt1, OutPt *OutPt2, IntPoint OffPt) : - OutPt1(OutPt1), OutPt2(OutPt2), OffPt(OffPt) {} - OutPt *OutPt1; - OutPt *OutPt2; - IntPoint OffPt; - }; -// }; // namespace Internal - -//------------------------------------------------------------------------------ - -//ClipperBase is the ancestor to the Clipper class. It should not be -//instantiated directly. This class simply abstracts the conversion of sets of -//polygon coordinates into edge objects that are stored in a LocalMinima list. -class ClipperBase -{ -public: - ClipperBase() : m_UseFullRange(false), m_HasOpenPaths(false) {} - ~ClipperBase() { Clear(); } - bool AddPath(const Path &pg, PolyType PolyTyp, bool Closed); - bool AddPaths(const Paths &ppg, PolyType PolyTyp, bool Closed); - void Clear(); - IntRect GetBounds(); - // By default, when three or more vertices are collinear in input polygons (subject or clip), the Clipper object removes the 'inner' vertices before clipping. - // When enabled the PreserveCollinear property prevents this default behavior to allow these inner vertices to appear in the solution. - bool PreserveCollinear() const {return m_PreserveCollinear;}; - void PreserveCollinear(bool value) {m_PreserveCollinear = value;}; -protected: - bool AddPathInternal(const Path &pg, int highI, PolyType PolyTyp, bool Closed, TEdge* edges); - TEdge* AddBoundsToLML(TEdge *e, bool IsClosed); - void Reset(); - TEdge* ProcessBound(TEdge* E, bool IsClockwise); - TEdge* DescendToMin(TEdge *&E); - void AscendToMax(TEdge *&E, bool Appending, bool IsClosed); - - // Local minima (Y, left edge, right edge) sorted by ascending Y. - std::vector m_MinimaList; - - // True if the input polygons have abs values higher than loRange, but lower than hiRange. - // False if the input polygons have abs values lower or equal to loRange. - bool m_UseFullRange; - // A vector of edges per each input path. - std::vector> m_edges; - // Don't remove intermediate vertices of a collinear sequence of points. - bool m_PreserveCollinear; - // Is any of the paths inserted by AddPath() or AddPaths() open? - bool m_HasOpenPaths; -}; -//------------------------------------------------------------------------------ - -class Clipper : public ClipperBase -{ -public: - Clipper(int initOptions = 0); - ~Clipper() { Clear(); } - void Clear() { ClipperBase::Clear(); DisposeAllOutRecs(); } - bool Execute(ClipType clipType, - Paths &solution, - PolyFillType fillType = pftEvenOdd) - { return Execute(clipType, solution, fillType, fillType); } - bool Execute(ClipType clipType, - Paths &solution, - PolyFillType subjFillType, - PolyFillType clipFillType); - bool Execute(ClipType clipType, - PolyTree &polytree, - PolyFillType fillType = pftEvenOdd) - { return Execute(clipType, polytree, fillType, fillType); } - bool Execute(ClipType clipType, - PolyTree &polytree, - PolyFillType subjFillType, - PolyFillType clipFillType); - bool ReverseSolution() const { return m_ReverseOutput; }; - void ReverseSolution(bool value) {m_ReverseOutput = value;}; - bool StrictlySimple() const {return m_StrictSimple;}; - void StrictlySimple(bool value) {m_StrictSimple = value;}; - //set the callback function for z value filling on intersections (otherwise Z is 0) -#ifdef use_xyz - void ZFillFunction(ZFillCallback zFillFunc) { m_ZFill = zFillFunc; } -#endif -protected: - void Reset(); - virtual bool ExecuteInternal(); -private: - - // Output polygons. - std::vector m_PolyOuts; - // Output points, allocated by a continuous sets of m_OutPtsChunkSize. - std::vector m_OutPts; - // List of free output points, to be used before taking a point from m_OutPts or allocating a new chunk. - OutPt *m_OutPtsFree; - size_t m_OutPtsChunkSize; - size_t m_OutPtsChunkLast; - - std::vector m_Joins; - std::vector m_GhostJoins; - std::vector m_IntersectList; - ClipType m_ClipType; - // A priority queue (a binary heap) of Y coordinates. - std::priority_queue m_Scanbeam; - // Maxima are collected by ProcessEdgesAtTopOfScanbeam(), consumed by ProcessHorizontal(). - std::vector m_Maxima; - TEdge *m_ActiveEdges; - TEdge *m_SortedEdges; - PolyFillType m_ClipFillType; - PolyFillType m_SubjFillType; - bool m_ReverseOutput; - // Does the result go to a PolyTree or Paths? - bool m_UsingPolyTree; - bool m_StrictSimple; -#ifdef use_xyz - ZFillCallback m_ZFill; //custom callback -#endif - void SetWindingCount(TEdge& edge) const; - bool IsEvenOddFillType(const TEdge& edge) const - { return (edge.PolyTyp == ptSubject) ? m_SubjFillType == pftEvenOdd : m_ClipFillType == pftEvenOdd; } - bool IsEvenOddAltFillType(const TEdge& edge) const - { return (edge.PolyTyp == ptSubject) ? m_ClipFillType == pftEvenOdd : m_SubjFillType == pftEvenOdd; } - void InsertLocalMinimaIntoAEL(const cInt botY); - void InsertEdgeIntoAEL(TEdge *edge, TEdge* startEdge); - void AddEdgeToSEL(TEdge *edge); - void CopyAELToSEL(); - void DeleteFromSEL(TEdge *e); - void DeleteFromAEL(TEdge *e); - void UpdateEdgeIntoAEL(TEdge *&e); - void SwapPositionsInSEL(TEdge *edge1, TEdge *edge2); - bool IsContributing(const TEdge& edge) const; - bool IsTopHorz(const cInt XPos); - void SwapPositionsInAEL(TEdge *edge1, TEdge *edge2); - void DoMaxima(TEdge *e); - void ProcessHorizontals(); - void ProcessHorizontal(TEdge *horzEdge); - void AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &pt); - OutPt* AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &pt); - OutRec* GetOutRec(int idx); - void AppendPolygon(TEdge *e1, TEdge *e2) const; - void IntersectEdges(TEdge *e1, TEdge *e2, IntPoint &pt); - OutRec* CreateOutRec(); - OutPt* AddOutPt(TEdge *e, const IntPoint &pt); - OutPt* GetLastOutPt(TEdge *e); - OutPt* AllocateOutPt(); - OutPt* DupOutPt(OutPt* outPt, bool InsertAfter); - // Add the point to a list of free points. - void DisposeOutPt(OutPt *pt) { pt->Next = m_OutPtsFree; m_OutPtsFree = pt; } - void DisposeOutPts(OutPt*& pp) { if (pp != nullptr) { pp->Prev->Next = m_OutPtsFree; m_OutPtsFree = pp; } } - void DisposeAllOutRecs(); - bool ProcessIntersections(const cInt topY); - void BuildIntersectList(const cInt topY); - void ProcessEdgesAtTopOfScanbeam(const cInt topY); - void BuildResult(Paths& polys); - void BuildResult2(PolyTree& polytree); - void SetHoleState(TEdge *e, OutRec *outrec) const; - bool FixupIntersectionOrder(); - void FixupOutPolygon(OutRec &outrec); - void FixupOutPolyline(OutRec &outrec); - bool FindOwnerFromSplitRecs(OutRec &outRec, OutRec *&currOrfl); - void FixHoleLinkage(OutRec &outrec); - bool JoinPoints(Join *j, OutRec* outRec1, OutRec* outRec2); - bool JoinHorz(OutPt* op1, OutPt* op1b, OutPt* op2, OutPt* op2b, const IntPoint &Pt, bool DiscardLeft); - void JoinCommonEdges(); - void DoSimplePolygons(); - void FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec) const; - void FixupFirstLefts2(OutRec* OldOutRec, OutRec* NewOutRec) const; -#ifdef use_xyz - void SetZ(IntPoint& pt, TEdge& e1, TEdge& e2); -#endif -}; -//------------------------------------------------------------------------------ - -class ClipperOffset -{ -public: - ClipperOffset(double miterLimit = 2.0, double roundPrecision = 0.25, double shortestEdgeLength = 0.) : - MiterLimit(miterLimit), ArcTolerance(roundPrecision), ShortestEdgeLength(shortestEdgeLength), m_lowest(-1, 0) {} - ~ClipperOffset() { Clear(); } - void AddPath(const Path& path, JoinType joinType, EndType endType); - void AddPaths(const Paths& paths, JoinType joinType, EndType endType); - void Execute(Paths& solution, double delta); - void Execute(PolyTree& solution, double delta); - void Clear(); - double MiterLimit; - double ArcTolerance; - double ShortestEdgeLength; -private: - Paths m_destPolys; - Path m_srcPoly; - Path m_destPoly; - std::vector m_normals; - double m_delta, m_sinA, m_sin, m_cos; - double m_miterLim, m_StepsPerRad; - IntPoint m_lowest; - PolyNode m_polyNodes; - - void FixOrientations(); - void DoOffset(double delta); - void OffsetPoint(int j, int& k, JoinType jointype); - void DoSquare(int j, int k); - void DoMiter(int j, int k, double r); - void DoRound(int j, int k); -}; -//------------------------------------------------------------------------------ - -class clipperException : public std::exception -{ - public: - clipperException(const char* description): m_descr(description) {} - virtual ~clipperException() throw() {} - virtual const char* what() const throw() {return m_descr.c_str();} - private: - std::string m_descr; -}; -//------------------------------------------------------------------------------ - -} //ClipperLib namespace - -#endif //clipper_hpp - - +/******************************************************************************* +* * +* Author : Angus Johnson * +* Version : 6.2.9 * +* Date : 16 February 2015 * +* Website : http://www.angusj.com * +* Copyright : Angus Johnson 2010-2015 * +* * +* License: * +* Use, modification & distribution is subject to Boost Software License Ver 1. * +* http://www.boost.org/LICENSE_1_0.txt * +* * +* Attributions: * +* The code in this library is an extension of Bala Vatti's clipping algorithm: * +* "A generic solution to polygon clipping" * +* Communications of the ACM, Vol 35, Issue 7 (July 1992) pp 56-63. * +* http://portal.acm.org/citation.cfm?id=129906 * +* * +* Computer graphics and geometric modeling: implementation and algorithms * +* By Max K. Agoston * +* Springer; 1 edition (January 4, 2005) * +* http://books.google.com/books?q=vatti+clipping+agoston * +* * +* See also: * +* "Polygon Offsetting by Computing Winding Numbers" * +* Paper no. DETC2005-85513 pp. 565-575 * +* ASME 2005 International Design Engineering Technical Conferences * +* and Computers and Information in Engineering Conference (IDETC/CIE2005) * +* September 24-28, 2005 , Long Beach, California, USA * +* http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf * +* * +*******************************************************************************/ + +#ifndef clipper_hpp +#define clipper_hpp + +#include + +#define CLIPPER_VERSION "6.2.6" + +//use_xyz: adds a Z member to IntPoint. Adds a minor cost to perfomance. +//#define use_xyz + +//use_lines: Enables line clipping. Adds a very minor cost to performance. +#define use_lines + +//use_deprecated: Enables temporary support for the obsolete functions +//#define use_deprecated + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace ClipperLib { + +enum ClipType { ctIntersection, ctUnion, ctDifference, ctXor }; +enum PolyType { ptSubject, ptClip }; +//By far the most widely used winding rules for polygon filling are +//EvenOdd & NonZero (GDI, GDI+, XLib, OpenGL, Cairo, AGG, Quartz, SVG, Gr32) +//Others rules include Positive, Negative and ABS_GTR_EQ_TWO (only in OpenGL) +//see http://glprogramming.com/red/chapter11.html +enum PolyFillType { pftEvenOdd, pftNonZero, pftPositive, pftNegative }; + +// Point coordinate type +typedef int64_t cInt; +// Maximum cInt value to allow a cross product calculation using 32bit expressions. +static cInt const loRange = 0x3FFFFFFF; +// Maximum allowed cInt value. +static cInt const hiRange = 0x3FFFFFFFFFFFFFFFLL; + +struct IntPoint { + cInt X; + cInt Y; +#ifdef use_xyz + cInt Z; + IntPoint(cInt x = 0, cInt y = 0, cInt z = 0): X(x), Y(y), Z(z) {}; +#else + IntPoint(cInt x = 0, cInt y = 0): X(x), Y(y) {}; +#endif + + friend inline bool operator== (const IntPoint& a, const IntPoint& b) + { + return a.X == b.X && a.Y == b.Y; + } + friend inline bool operator!= (const IntPoint& a, const IntPoint& b) + { + return a.X != b.X || a.Y != b.Y; + } +}; +//------------------------------------------------------------------------------ + +typedef std::vector< IntPoint > Path; +typedef std::vector< Path > Paths; + +inline Path& operator <<(Path& poly, const IntPoint& p) {poly.push_back(p); return poly;} +inline Paths& operator <<(Paths& polys, const Path& p) {polys.push_back(p); return polys;} + +std::ostream& operator <<(std::ostream &s, const IntPoint &p); +std::ostream& operator <<(std::ostream &s, const Path &p); +std::ostream& operator <<(std::ostream &s, const Paths &p); + +struct DoublePoint +{ + double X; + double Y; + DoublePoint(double x = 0, double y = 0) : X(x), Y(y) {} + DoublePoint(IntPoint ip) : X((double)ip.X), Y((double)ip.Y) {} +}; +//------------------------------------------------------------------------------ + +#ifdef use_xyz +typedef void (*ZFillCallback)(IntPoint& e1bot, IntPoint& e1top, IntPoint& e2bot, IntPoint& e2top, IntPoint& pt); +#endif + +enum InitOptions {ioReverseSolution = 1, ioStrictlySimple = 2, ioPreserveCollinear = 4}; +enum JoinType {jtSquare, jtRound, jtMiter}; +enum EndType {etClosedPolygon, etClosedLine, etOpenButt, etOpenSquare, etOpenRound}; + +class PolyNode; +typedef std::vector< PolyNode* > PolyNodes; + +class PolyNode +{ +public: + PolyNode() : Childs(), Parent(0), Index(0), m_IsOpen(false) {} + virtual ~PolyNode(){}; + Path Contour; + PolyNodes Childs; + PolyNode* Parent; + // Traversal of the polygon tree in a depth first fashion. + PolyNode* GetNext() const { return Childs.empty() ? GetNextSiblingUp() : Childs.front(); } + bool IsHole() const; + bool IsOpen() const { return m_IsOpen; } + int ChildCount() const { return (int)Childs.size(); } +private: + unsigned Index; //node index in Parent.Childs + bool m_IsOpen; + JoinType m_jointype; + EndType m_endtype; + PolyNode* GetNextSiblingUp() const { return Parent ? ((Index == Parent->Childs.size() - 1) ? Parent->GetNextSiblingUp() : Parent->Childs[Index + 1]) : nullptr; } + void AddChild(PolyNode& child); + friend class Clipper; //to access Index + friend class ClipperOffset; + friend class PolyTree; //to implement the PolyTree::move operator +}; + +class PolyTree: public PolyNode +{ +public: + PolyTree() {} + PolyTree(PolyTree &&src) { *this = std::move(src); } + virtual ~PolyTree(){Clear();}; + PolyTree& operator=(PolyTree &&src) { + AllNodes = std::move(src.AllNodes); + Contour = std::move(src.Contour); + Childs = std::move(src.Childs); + Parent = nullptr; + Index = src.Index; + m_IsOpen = src.m_IsOpen; + m_jointype = src.m_jointype; + m_endtype = src.m_endtype; + for (size_t i = 0; i < Childs.size(); ++ i) + Childs[i]->Parent = this; + return *this; + } + PolyNode* GetFirst() const { return Childs.empty() ? nullptr : Childs.front(); } + void Clear() { AllNodes.clear(); Childs.clear(); } + int Total() const; +private: + PolyTree(const PolyTree &src) = delete; + PolyTree& operator=(const PolyTree &src) = delete; + std::vector AllNodes; + friend class Clipper; //to access AllNodes +}; + +double Area(const Path &poly); +inline bool Orientation(const Path &poly) { return Area(poly) >= 0; } +int PointInPolygon(const IntPoint &pt, const Path &path); + +void SimplifyPolygon(const Path &in_poly, Paths &out_polys, PolyFillType fillType = pftEvenOdd); +void SimplifyPolygons(const Paths &in_polys, Paths &out_polys, PolyFillType fillType = pftEvenOdd); +void SimplifyPolygons(Paths &polys, PolyFillType fillType = pftEvenOdd); + +void CleanPolygon(const Path& in_poly, Path& out_poly, double distance = 1.415); +void CleanPolygon(Path& poly, double distance = 1.415); +void CleanPolygons(const Paths& in_polys, Paths& out_polys, double distance = 1.415); +void CleanPolygons(Paths& polys, double distance = 1.415); + +void MinkowskiSum(const Path& pattern, const Path& path, Paths& solution, bool pathIsClosed); +void MinkowskiSum(const Path& pattern, const Paths& paths, Paths& solution, bool pathIsClosed); +void MinkowskiDiff(const Path& poly1, const Path& poly2, Paths& solution); + +void PolyTreeToPaths(const PolyTree& polytree, Paths& paths); +void ClosedPathsFromPolyTree(const PolyTree& polytree, Paths& paths); +void OpenPathsFromPolyTree(PolyTree& polytree, Paths& paths); + +void ReversePath(Path& p); +void ReversePaths(Paths& p); + +struct IntRect { cInt left; cInt top; cInt right; cInt bottom; }; + +//enums that are used internally ... +enum EdgeSide { esLeft = 1, esRight = 2}; + +// namespace Internal { + //forward declarations (for stuff used internally) ... + struct TEdge { + // Bottom point of this edge (with minimum Y). + IntPoint Bot; + // Current position. + IntPoint Curr; + // Top point of this edge (with maximum Y). + IntPoint Top; + // Vector from Bot to Top. + IntPoint Delta; + // Slope (dx/dy). For horiontal edges, the slope is set to HORIZONTAL (-1.0E+40). + double Dx; + PolyType PolyTyp; + EdgeSide Side; + // Winding number delta. 1 or -1 depending on winding direction, 0 for open paths and flat closed paths. + int WindDelta; + int WindCnt; + int WindCnt2; //winding count of the opposite polytype + int OutIdx; + // Next edge in the input path. + TEdge *Next; + // Previous edge in the input path. + TEdge *Prev; + // Next edge in the Local Minima List chain. + TEdge *NextInLML; + TEdge *NextInAEL; + TEdge *PrevInAEL; + TEdge *NextInSEL; + TEdge *PrevInSEL; + }; + + struct IntersectNode { + IntersectNode(TEdge *Edge1, TEdge *Edge2, IntPoint Pt) : + Edge1(Edge1), Edge2(Edge2), Pt(Pt) {} + TEdge *Edge1; + TEdge *Edge2; + IntPoint Pt; + }; + + struct LocalMinimum { + cInt Y; + TEdge *LeftBound; + TEdge *RightBound; + }; + + // Point of an output polygon. + // 36B on 64bit system without use_xyz. + struct OutPt { + // 4B + int Idx; + // 16B without use_xyz / 24B with use_xyz + IntPoint Pt; + // 4B on 32bit system, 8B on 64bit system + OutPt *Next; + // 4B on 32bit system, 8B on 64bit system + OutPt *Prev; + }; + + struct OutRec; + struct Join { + Join(OutPt *OutPt1, OutPt *OutPt2, IntPoint OffPt) : + OutPt1(OutPt1), OutPt2(OutPt2), OffPt(OffPt) {} + OutPt *OutPt1; + OutPt *OutPt2; + IntPoint OffPt; + }; +// }; // namespace Internal + +//------------------------------------------------------------------------------ + +//ClipperBase is the ancestor to the Clipper class. It should not be +//instantiated directly. This class simply abstracts the conversion of sets of +//polygon coordinates into edge objects that are stored in a LocalMinima list. +class ClipperBase +{ +public: + ClipperBase() : m_UseFullRange(false), m_HasOpenPaths(false) {} + ~ClipperBase() { Clear(); } + bool AddPath(const Path &pg, PolyType PolyTyp, bool Closed); + bool AddPaths(const Paths &ppg, PolyType PolyTyp, bool Closed); + void Clear(); + IntRect GetBounds(); + // By default, when three or more vertices are collinear in input polygons (subject or clip), the Clipper object removes the 'inner' vertices before clipping. + // When enabled the PreserveCollinear property prevents this default behavior to allow these inner vertices to appear in the solution. + bool PreserveCollinear() const {return m_PreserveCollinear;}; + void PreserveCollinear(bool value) {m_PreserveCollinear = value;}; +protected: + bool AddPathInternal(const Path &pg, int highI, PolyType PolyTyp, bool Closed, TEdge* edges); + TEdge* AddBoundsToLML(TEdge *e, bool IsClosed); + void Reset(); + TEdge* ProcessBound(TEdge* E, bool IsClockwise); + TEdge* DescendToMin(TEdge *&E); + void AscendToMax(TEdge *&E, bool Appending, bool IsClosed); + + // Local minima (Y, left edge, right edge) sorted by ascending Y. + std::vector m_MinimaList; + + // True if the input polygons have abs values higher than loRange, but lower than hiRange. + // False if the input polygons have abs values lower or equal to loRange. + bool m_UseFullRange; + // A vector of edges per each input path. + std::vector> m_edges; + // Don't remove intermediate vertices of a collinear sequence of points. + bool m_PreserveCollinear; + // Is any of the paths inserted by AddPath() or AddPaths() open? + bool m_HasOpenPaths; +}; +//------------------------------------------------------------------------------ + +class Clipper : public ClipperBase +{ +public: + Clipper(int initOptions = 0); + ~Clipper() { Clear(); } + void Clear() { ClipperBase::Clear(); DisposeAllOutRecs(); } + bool Execute(ClipType clipType, + Paths &solution, + PolyFillType fillType = pftEvenOdd) + { return Execute(clipType, solution, fillType, fillType); } + bool Execute(ClipType clipType, + Paths &solution, + PolyFillType subjFillType, + PolyFillType clipFillType); + bool Execute(ClipType clipType, + PolyTree &polytree, + PolyFillType fillType = pftEvenOdd) + { return Execute(clipType, polytree, fillType, fillType); } + bool Execute(ClipType clipType, + PolyTree &polytree, + PolyFillType subjFillType, + PolyFillType clipFillType); + bool ReverseSolution() const { return m_ReverseOutput; }; + void ReverseSolution(bool value) {m_ReverseOutput = value;}; + bool StrictlySimple() const {return m_StrictSimple;}; + void StrictlySimple(bool value) {m_StrictSimple = value;}; + //set the callback function for z value filling on intersections (otherwise Z is 0) +#ifdef use_xyz + void ZFillFunction(ZFillCallback zFillFunc) { m_ZFill = zFillFunc; } +#endif +protected: + void Reset(); + virtual bool ExecuteInternal(); +private: + + // Output polygons. + std::vector m_PolyOuts; + // Output points, allocated by a continuous sets of m_OutPtsChunkSize. + std::vector m_OutPts; + // List of free output points, to be used before taking a point from m_OutPts or allocating a new chunk. + OutPt *m_OutPtsFree; + size_t m_OutPtsChunkSize; + size_t m_OutPtsChunkLast; + + std::vector m_Joins; + std::vector m_GhostJoins; + std::vector m_IntersectList; + ClipType m_ClipType; + // A priority queue (a binary heap) of Y coordinates. + std::priority_queue m_Scanbeam; + // Maxima are collected by ProcessEdgesAtTopOfScanbeam(), consumed by ProcessHorizontal(). + std::vector m_Maxima; + TEdge *m_ActiveEdges; + TEdge *m_SortedEdges; + PolyFillType m_ClipFillType; + PolyFillType m_SubjFillType; + bool m_ReverseOutput; + // Does the result go to a PolyTree or Paths? + bool m_UsingPolyTree; + bool m_StrictSimple; +#ifdef use_xyz + ZFillCallback m_ZFill; //custom callback +#endif + void SetWindingCount(TEdge& edge) const; + bool IsEvenOddFillType(const TEdge& edge) const + { return (edge.PolyTyp == ptSubject) ? m_SubjFillType == pftEvenOdd : m_ClipFillType == pftEvenOdd; } + bool IsEvenOddAltFillType(const TEdge& edge) const + { return (edge.PolyTyp == ptSubject) ? m_ClipFillType == pftEvenOdd : m_SubjFillType == pftEvenOdd; } + void InsertLocalMinimaIntoAEL(const cInt botY); + void InsertEdgeIntoAEL(TEdge *edge, TEdge* startEdge); + void AddEdgeToSEL(TEdge *edge); + void CopyAELToSEL(); + void DeleteFromSEL(TEdge *e); + void DeleteFromAEL(TEdge *e); + void UpdateEdgeIntoAEL(TEdge *&e); + void SwapPositionsInSEL(TEdge *edge1, TEdge *edge2); + bool IsContributing(const TEdge& edge) const; + bool IsTopHorz(const cInt XPos); + void SwapPositionsInAEL(TEdge *edge1, TEdge *edge2); + void DoMaxima(TEdge *e); + void ProcessHorizontals(); + void ProcessHorizontal(TEdge *horzEdge); + void AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &pt); + OutPt* AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &pt); + OutRec* GetOutRec(int idx); + void AppendPolygon(TEdge *e1, TEdge *e2) const; + void IntersectEdges(TEdge *e1, TEdge *e2, IntPoint &pt); + OutRec* CreateOutRec(); + OutPt* AddOutPt(TEdge *e, const IntPoint &pt); + OutPt* GetLastOutPt(TEdge *e); + OutPt* AllocateOutPt(); + OutPt* DupOutPt(OutPt* outPt, bool InsertAfter); + // Add the point to a list of free points. + void DisposeOutPt(OutPt *pt) { pt->Next = m_OutPtsFree; m_OutPtsFree = pt; } + void DisposeOutPts(OutPt*& pp) { if (pp != nullptr) { pp->Prev->Next = m_OutPtsFree; m_OutPtsFree = pp; } } + void DisposeAllOutRecs(); + bool ProcessIntersections(const cInt topY); + void BuildIntersectList(const cInt topY); + void ProcessEdgesAtTopOfScanbeam(const cInt topY); + void BuildResult(Paths& polys); + void BuildResult2(PolyTree& polytree); + void SetHoleState(TEdge *e, OutRec *outrec) const; + bool FixupIntersectionOrder(); + void FixupOutPolygon(OutRec &outrec); + void FixupOutPolyline(OutRec &outrec); + bool FindOwnerFromSplitRecs(OutRec &outRec, OutRec *&currOrfl); + void FixHoleLinkage(OutRec &outrec); + bool JoinPoints(Join *j, OutRec* outRec1, OutRec* outRec2); + bool JoinHorz(OutPt* op1, OutPt* op1b, OutPt* op2, OutPt* op2b, const IntPoint &Pt, bool DiscardLeft); + void JoinCommonEdges(); + void DoSimplePolygons(); + void FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec) const; + void FixupFirstLefts2(OutRec* OldOutRec, OutRec* NewOutRec) const; +#ifdef use_xyz + void SetZ(IntPoint& pt, TEdge& e1, TEdge& e2); +#endif +}; +//------------------------------------------------------------------------------ + +class ClipperOffset +{ +public: + ClipperOffset(double miterLimit = 2.0, double roundPrecision = 0.25, double shortestEdgeLength = 0.) : + MiterLimit(miterLimit), ArcTolerance(roundPrecision), ShortestEdgeLength(shortestEdgeLength), m_lowest(-1, 0) {} + ~ClipperOffset() { Clear(); } + void AddPath(const Path& path, JoinType joinType, EndType endType); + void AddPaths(const Paths& paths, JoinType joinType, EndType endType); + void Execute(Paths& solution, double delta); + void Execute(PolyTree& solution, double delta); + void Clear(); + double MiterLimit; + double ArcTolerance; + double ShortestEdgeLength; +private: + Paths m_destPolys; + Path m_srcPoly; + Path m_destPoly; + std::vector m_normals; + double m_delta, m_sinA, m_sin, m_cos; + double m_miterLim, m_StepsPerRad; + IntPoint m_lowest; + PolyNode m_polyNodes; + + void FixOrientations(); + void DoOffset(double delta); + void OffsetPoint(int j, int& k, JoinType jointype); + void DoSquare(int j, int k); + void DoMiter(int j, int k, double r); + void DoRound(int j, int k); +}; +//------------------------------------------------------------------------------ + +class clipperException : public std::exception +{ + public: + clipperException(const char* description): m_descr(description) {} + virtual ~clipperException() throw() {} + virtual const char* what() const throw() {return m_descr.c_str();} + private: + std::string m_descr; +}; +//------------------------------------------------------------------------------ + +} //ClipperLib namespace + +#endif //clipper_hpp + + diff --git a/xs/src/eigen/COPYING.README b/src/eigen/COPYING.README similarity index 100% rename from xs/src/eigen/COPYING.README rename to src/eigen/COPYING.README diff --git a/xs/src/eigen/Eigen/CMakeLists.txt b/src/eigen/Eigen/CMakeLists.txt similarity index 100% rename from xs/src/eigen/Eigen/CMakeLists.txt rename to src/eigen/Eigen/CMakeLists.txt diff --git a/xs/src/eigen/Eigen/Cholesky b/src/eigen/Eigen/Cholesky similarity index 100% rename from xs/src/eigen/Eigen/Cholesky rename to src/eigen/Eigen/Cholesky diff --git a/xs/src/eigen/Eigen/CholmodSupport b/src/eigen/Eigen/CholmodSupport similarity index 100% rename from xs/src/eigen/Eigen/CholmodSupport rename to src/eigen/Eigen/CholmodSupport diff --git a/xs/src/eigen/Eigen/Core b/src/eigen/Eigen/Core similarity index 100% rename from xs/src/eigen/Eigen/Core rename to src/eigen/Eigen/Core diff --git a/xs/src/eigen/Eigen/Dense b/src/eigen/Eigen/Dense similarity index 100% rename from xs/src/eigen/Eigen/Dense rename to src/eigen/Eigen/Dense diff --git a/xs/src/eigen/Eigen/Eigen b/src/eigen/Eigen/Eigen similarity index 100% rename from xs/src/eigen/Eigen/Eigen rename to src/eigen/Eigen/Eigen diff --git a/xs/src/eigen/Eigen/Eigenvalues b/src/eigen/Eigen/Eigenvalues similarity index 100% rename from xs/src/eigen/Eigen/Eigenvalues rename to src/eigen/Eigen/Eigenvalues diff --git a/xs/src/eigen/Eigen/Geometry b/src/eigen/Eigen/Geometry similarity index 100% rename from xs/src/eigen/Eigen/Geometry rename to src/eigen/Eigen/Geometry diff --git a/xs/src/eigen/Eigen/Householder b/src/eigen/Eigen/Householder similarity index 100% rename from xs/src/eigen/Eigen/Householder rename to src/eigen/Eigen/Householder diff --git a/xs/src/eigen/Eigen/IterativeLinearSolvers b/src/eigen/Eigen/IterativeLinearSolvers similarity index 100% rename from xs/src/eigen/Eigen/IterativeLinearSolvers rename to src/eigen/Eigen/IterativeLinearSolvers diff --git a/xs/src/eigen/Eigen/Jacobi b/src/eigen/Eigen/Jacobi similarity index 100% rename from xs/src/eigen/Eigen/Jacobi rename to src/eigen/Eigen/Jacobi diff --git a/xs/src/eigen/Eigen/LU b/src/eigen/Eigen/LU similarity index 100% rename from xs/src/eigen/Eigen/LU rename to src/eigen/Eigen/LU diff --git a/xs/src/eigen/Eigen/MetisSupport b/src/eigen/Eigen/MetisSupport similarity index 100% rename from xs/src/eigen/Eigen/MetisSupport rename to src/eigen/Eigen/MetisSupport diff --git a/xs/src/eigen/Eigen/OrderingMethods b/src/eigen/Eigen/OrderingMethods similarity index 100% rename from xs/src/eigen/Eigen/OrderingMethods rename to src/eigen/Eigen/OrderingMethods diff --git a/xs/src/eigen/Eigen/PaStiXSupport b/src/eigen/Eigen/PaStiXSupport similarity index 100% rename from xs/src/eigen/Eigen/PaStiXSupport rename to src/eigen/Eigen/PaStiXSupport diff --git a/xs/src/eigen/Eigen/PardisoSupport b/src/eigen/Eigen/PardisoSupport similarity index 100% rename from xs/src/eigen/Eigen/PardisoSupport rename to src/eigen/Eigen/PardisoSupport diff --git a/xs/src/eigen/Eigen/QR b/src/eigen/Eigen/QR similarity index 100% rename from xs/src/eigen/Eigen/QR rename to src/eigen/Eigen/QR diff --git a/xs/src/eigen/Eigen/QtAlignedMalloc b/src/eigen/Eigen/QtAlignedMalloc similarity index 100% rename from xs/src/eigen/Eigen/QtAlignedMalloc rename to src/eigen/Eigen/QtAlignedMalloc diff --git a/xs/src/eigen/Eigen/SPQRSupport b/src/eigen/Eigen/SPQRSupport similarity index 100% rename from xs/src/eigen/Eigen/SPQRSupport rename to src/eigen/Eigen/SPQRSupport diff --git a/xs/src/eigen/Eigen/SVD b/src/eigen/Eigen/SVD similarity index 100% rename from xs/src/eigen/Eigen/SVD rename to src/eigen/Eigen/SVD diff --git a/xs/src/eigen/Eigen/Sparse b/src/eigen/Eigen/Sparse similarity index 100% rename from xs/src/eigen/Eigen/Sparse rename to src/eigen/Eigen/Sparse diff --git a/xs/src/eigen/Eigen/SparseCholesky b/src/eigen/Eigen/SparseCholesky similarity index 100% rename from xs/src/eigen/Eigen/SparseCholesky rename to src/eigen/Eigen/SparseCholesky diff --git a/xs/src/eigen/Eigen/SparseCore b/src/eigen/Eigen/SparseCore similarity index 100% rename from xs/src/eigen/Eigen/SparseCore rename to src/eigen/Eigen/SparseCore diff --git a/xs/src/eigen/Eigen/SparseLU b/src/eigen/Eigen/SparseLU similarity index 100% rename from xs/src/eigen/Eigen/SparseLU rename to src/eigen/Eigen/SparseLU diff --git a/xs/src/eigen/Eigen/SparseQR b/src/eigen/Eigen/SparseQR similarity index 100% rename from xs/src/eigen/Eigen/SparseQR rename to src/eigen/Eigen/SparseQR diff --git a/xs/src/eigen/Eigen/StdDeque b/src/eigen/Eigen/StdDeque similarity index 100% rename from xs/src/eigen/Eigen/StdDeque rename to src/eigen/Eigen/StdDeque diff --git a/xs/src/eigen/Eigen/StdList b/src/eigen/Eigen/StdList similarity index 100% rename from xs/src/eigen/Eigen/StdList rename to src/eigen/Eigen/StdList diff --git a/xs/src/eigen/Eigen/StdVector b/src/eigen/Eigen/StdVector similarity index 100% rename from xs/src/eigen/Eigen/StdVector rename to src/eigen/Eigen/StdVector diff --git a/xs/src/eigen/Eigen/SuperLUSupport b/src/eigen/Eigen/SuperLUSupport similarity index 100% rename from xs/src/eigen/Eigen/SuperLUSupport rename to src/eigen/Eigen/SuperLUSupport diff --git a/xs/src/eigen/Eigen/UmfPackSupport b/src/eigen/Eigen/UmfPackSupport similarity index 100% rename from xs/src/eigen/Eigen/UmfPackSupport rename to src/eigen/Eigen/UmfPackSupport diff --git a/xs/src/eigen/Eigen/src/Cholesky/LDLT.h b/src/eigen/Eigen/src/Cholesky/LDLT.h similarity index 100% rename from xs/src/eigen/Eigen/src/Cholesky/LDLT.h rename to src/eigen/Eigen/src/Cholesky/LDLT.h diff --git a/xs/src/eigen/Eigen/src/Cholesky/LLT.h b/src/eigen/Eigen/src/Cholesky/LLT.h similarity index 100% rename from xs/src/eigen/Eigen/src/Cholesky/LLT.h rename to src/eigen/Eigen/src/Cholesky/LLT.h diff --git a/xs/src/eigen/Eigen/src/Cholesky/LLT_LAPACKE.h b/src/eigen/Eigen/src/Cholesky/LLT_LAPACKE.h similarity index 100% rename from xs/src/eigen/Eigen/src/Cholesky/LLT_LAPACKE.h rename to src/eigen/Eigen/src/Cholesky/LLT_LAPACKE.h diff --git a/xs/src/eigen/Eigen/src/CholmodSupport/CholmodSupport.h b/src/eigen/Eigen/src/CholmodSupport/CholmodSupport.h similarity index 100% rename from xs/src/eigen/Eigen/src/CholmodSupport/CholmodSupport.h rename to src/eigen/Eigen/src/CholmodSupport/CholmodSupport.h diff --git a/xs/src/eigen/Eigen/src/Core/Array.h b/src/eigen/Eigen/src/Core/Array.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/Array.h rename to src/eigen/Eigen/src/Core/Array.h diff --git a/xs/src/eigen/Eigen/src/Core/ArrayBase.h b/src/eigen/Eigen/src/Core/ArrayBase.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/ArrayBase.h rename to src/eigen/Eigen/src/Core/ArrayBase.h diff --git a/xs/src/eigen/Eigen/src/Core/ArrayWrapper.h b/src/eigen/Eigen/src/Core/ArrayWrapper.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/ArrayWrapper.h rename to src/eigen/Eigen/src/Core/ArrayWrapper.h diff --git a/xs/src/eigen/Eigen/src/Core/Assign.h b/src/eigen/Eigen/src/Core/Assign.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/Assign.h rename to src/eigen/Eigen/src/Core/Assign.h diff --git a/xs/src/eigen/Eigen/src/Core/AssignEvaluator.h b/src/eigen/Eigen/src/Core/AssignEvaluator.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/AssignEvaluator.h rename to src/eigen/Eigen/src/Core/AssignEvaluator.h diff --git a/xs/src/eigen/Eigen/src/Core/Assign_MKL.h b/src/eigen/Eigen/src/Core/Assign_MKL.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/Assign_MKL.h rename to src/eigen/Eigen/src/Core/Assign_MKL.h diff --git a/xs/src/eigen/Eigen/src/Core/BandMatrix.h b/src/eigen/Eigen/src/Core/BandMatrix.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/BandMatrix.h rename to src/eigen/Eigen/src/Core/BandMatrix.h diff --git a/xs/src/eigen/Eigen/src/Core/Block.h b/src/eigen/Eigen/src/Core/Block.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/Block.h rename to src/eigen/Eigen/src/Core/Block.h diff --git a/xs/src/eigen/Eigen/src/Core/BooleanRedux.h b/src/eigen/Eigen/src/Core/BooleanRedux.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/BooleanRedux.h rename to src/eigen/Eigen/src/Core/BooleanRedux.h diff --git a/xs/src/eigen/Eigen/src/Core/CommaInitializer.h b/src/eigen/Eigen/src/Core/CommaInitializer.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/CommaInitializer.h rename to src/eigen/Eigen/src/Core/CommaInitializer.h diff --git a/xs/src/eigen/Eigen/src/Core/ConditionEstimator.h b/src/eigen/Eigen/src/Core/ConditionEstimator.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/ConditionEstimator.h rename to src/eigen/Eigen/src/Core/ConditionEstimator.h diff --git a/xs/src/eigen/Eigen/src/Core/CoreEvaluators.h b/src/eigen/Eigen/src/Core/CoreEvaluators.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/CoreEvaluators.h rename to src/eigen/Eigen/src/Core/CoreEvaluators.h diff --git a/xs/src/eigen/Eigen/src/Core/CoreIterators.h b/src/eigen/Eigen/src/Core/CoreIterators.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/CoreIterators.h rename to src/eigen/Eigen/src/Core/CoreIterators.h diff --git a/xs/src/eigen/Eigen/src/Core/CwiseBinaryOp.h b/src/eigen/Eigen/src/Core/CwiseBinaryOp.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/CwiseBinaryOp.h rename to src/eigen/Eigen/src/Core/CwiseBinaryOp.h diff --git a/xs/src/eigen/Eigen/src/Core/CwiseNullaryOp.h b/src/eigen/Eigen/src/Core/CwiseNullaryOp.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/CwiseNullaryOp.h rename to src/eigen/Eigen/src/Core/CwiseNullaryOp.h diff --git a/xs/src/eigen/Eigen/src/Core/CwiseTernaryOp.h b/src/eigen/Eigen/src/Core/CwiseTernaryOp.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/CwiseTernaryOp.h rename to src/eigen/Eigen/src/Core/CwiseTernaryOp.h diff --git a/xs/src/eigen/Eigen/src/Core/CwiseUnaryOp.h b/src/eigen/Eigen/src/Core/CwiseUnaryOp.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/CwiseUnaryOp.h rename to src/eigen/Eigen/src/Core/CwiseUnaryOp.h diff --git a/xs/src/eigen/Eigen/src/Core/CwiseUnaryView.h b/src/eigen/Eigen/src/Core/CwiseUnaryView.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/CwiseUnaryView.h rename to src/eigen/Eigen/src/Core/CwiseUnaryView.h diff --git a/xs/src/eigen/Eigen/src/Core/DenseBase.h b/src/eigen/Eigen/src/Core/DenseBase.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/DenseBase.h rename to src/eigen/Eigen/src/Core/DenseBase.h diff --git a/xs/src/eigen/Eigen/src/Core/DenseCoeffsBase.h b/src/eigen/Eigen/src/Core/DenseCoeffsBase.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/DenseCoeffsBase.h rename to src/eigen/Eigen/src/Core/DenseCoeffsBase.h diff --git a/xs/src/eigen/Eigen/src/Core/DenseStorage.h b/src/eigen/Eigen/src/Core/DenseStorage.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/DenseStorage.h rename to src/eigen/Eigen/src/Core/DenseStorage.h diff --git a/xs/src/eigen/Eigen/src/Core/Diagonal.h b/src/eigen/Eigen/src/Core/Diagonal.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/Diagonal.h rename to src/eigen/Eigen/src/Core/Diagonal.h diff --git a/xs/src/eigen/Eigen/src/Core/DiagonalMatrix.h b/src/eigen/Eigen/src/Core/DiagonalMatrix.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/DiagonalMatrix.h rename to src/eigen/Eigen/src/Core/DiagonalMatrix.h diff --git a/xs/src/eigen/Eigen/src/Core/DiagonalProduct.h b/src/eigen/Eigen/src/Core/DiagonalProduct.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/DiagonalProduct.h rename to src/eigen/Eigen/src/Core/DiagonalProduct.h diff --git a/xs/src/eigen/Eigen/src/Core/Dot.h b/src/eigen/Eigen/src/Core/Dot.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/Dot.h rename to src/eigen/Eigen/src/Core/Dot.h diff --git a/xs/src/eigen/Eigen/src/Core/EigenBase.h b/src/eigen/Eigen/src/Core/EigenBase.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/EigenBase.h rename to src/eigen/Eigen/src/Core/EigenBase.h diff --git a/xs/src/eigen/Eigen/src/Core/ForceAlignedAccess.h b/src/eigen/Eigen/src/Core/ForceAlignedAccess.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/ForceAlignedAccess.h rename to src/eigen/Eigen/src/Core/ForceAlignedAccess.h diff --git a/xs/src/eigen/Eigen/src/Core/Fuzzy.h b/src/eigen/Eigen/src/Core/Fuzzy.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/Fuzzy.h rename to src/eigen/Eigen/src/Core/Fuzzy.h diff --git a/xs/src/eigen/Eigen/src/Core/GeneralProduct.h b/src/eigen/Eigen/src/Core/GeneralProduct.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/GeneralProduct.h rename to src/eigen/Eigen/src/Core/GeneralProduct.h diff --git a/xs/src/eigen/Eigen/src/Core/GenericPacketMath.h b/src/eigen/Eigen/src/Core/GenericPacketMath.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/GenericPacketMath.h rename to src/eigen/Eigen/src/Core/GenericPacketMath.h diff --git a/xs/src/eigen/Eigen/src/Core/GlobalFunctions.h b/src/eigen/Eigen/src/Core/GlobalFunctions.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/GlobalFunctions.h rename to src/eigen/Eigen/src/Core/GlobalFunctions.h diff --git a/xs/src/eigen/Eigen/src/Core/IO.h b/src/eigen/Eigen/src/Core/IO.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/IO.h rename to src/eigen/Eigen/src/Core/IO.h diff --git a/xs/src/eigen/Eigen/src/Core/Inverse.h b/src/eigen/Eigen/src/Core/Inverse.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/Inverse.h rename to src/eigen/Eigen/src/Core/Inverse.h diff --git a/xs/src/eigen/Eigen/src/Core/Map.h b/src/eigen/Eigen/src/Core/Map.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/Map.h rename to src/eigen/Eigen/src/Core/Map.h diff --git a/xs/src/eigen/Eigen/src/Core/MapBase.h b/src/eigen/Eigen/src/Core/MapBase.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/MapBase.h rename to src/eigen/Eigen/src/Core/MapBase.h diff --git a/xs/src/eigen/Eigen/src/Core/MathFunctions.h b/src/eigen/Eigen/src/Core/MathFunctions.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/MathFunctions.h rename to src/eigen/Eigen/src/Core/MathFunctions.h diff --git a/xs/src/eigen/Eigen/src/Core/MathFunctionsImpl.h b/src/eigen/Eigen/src/Core/MathFunctionsImpl.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/MathFunctionsImpl.h rename to src/eigen/Eigen/src/Core/MathFunctionsImpl.h diff --git a/xs/src/eigen/Eigen/src/Core/Matrix.h b/src/eigen/Eigen/src/Core/Matrix.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/Matrix.h rename to src/eigen/Eigen/src/Core/Matrix.h diff --git a/xs/src/eigen/Eigen/src/Core/MatrixBase.h b/src/eigen/Eigen/src/Core/MatrixBase.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/MatrixBase.h rename to src/eigen/Eigen/src/Core/MatrixBase.h diff --git a/xs/src/eigen/Eigen/src/Core/NestByValue.h b/src/eigen/Eigen/src/Core/NestByValue.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/NestByValue.h rename to src/eigen/Eigen/src/Core/NestByValue.h diff --git a/xs/src/eigen/Eigen/src/Core/NoAlias.h b/src/eigen/Eigen/src/Core/NoAlias.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/NoAlias.h rename to src/eigen/Eigen/src/Core/NoAlias.h diff --git a/xs/src/eigen/Eigen/src/Core/NumTraits.h b/src/eigen/Eigen/src/Core/NumTraits.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/NumTraits.h rename to src/eigen/Eigen/src/Core/NumTraits.h diff --git a/xs/src/eigen/Eigen/src/Core/PermutationMatrix.h b/src/eigen/Eigen/src/Core/PermutationMatrix.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/PermutationMatrix.h rename to src/eigen/Eigen/src/Core/PermutationMatrix.h diff --git a/xs/src/eigen/Eigen/src/Core/PlainObjectBase.h b/src/eigen/Eigen/src/Core/PlainObjectBase.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/PlainObjectBase.h rename to src/eigen/Eigen/src/Core/PlainObjectBase.h diff --git a/xs/src/eigen/Eigen/src/Core/Product.h b/src/eigen/Eigen/src/Core/Product.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/Product.h rename to src/eigen/Eigen/src/Core/Product.h diff --git a/xs/src/eigen/Eigen/src/Core/ProductEvaluators.h b/src/eigen/Eigen/src/Core/ProductEvaluators.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/ProductEvaluators.h rename to src/eigen/Eigen/src/Core/ProductEvaluators.h diff --git a/xs/src/eigen/Eigen/src/Core/Random.h b/src/eigen/Eigen/src/Core/Random.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/Random.h rename to src/eigen/Eigen/src/Core/Random.h diff --git a/xs/src/eigen/Eigen/src/Core/Redux.h b/src/eigen/Eigen/src/Core/Redux.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/Redux.h rename to src/eigen/Eigen/src/Core/Redux.h diff --git a/xs/src/eigen/Eigen/src/Core/Ref.h b/src/eigen/Eigen/src/Core/Ref.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/Ref.h rename to src/eigen/Eigen/src/Core/Ref.h diff --git a/xs/src/eigen/Eigen/src/Core/Replicate.h b/src/eigen/Eigen/src/Core/Replicate.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/Replicate.h rename to src/eigen/Eigen/src/Core/Replicate.h diff --git a/xs/src/eigen/Eigen/src/Core/ReturnByValue.h b/src/eigen/Eigen/src/Core/ReturnByValue.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/ReturnByValue.h rename to src/eigen/Eigen/src/Core/ReturnByValue.h diff --git a/xs/src/eigen/Eigen/src/Core/Reverse.h b/src/eigen/Eigen/src/Core/Reverse.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/Reverse.h rename to src/eigen/Eigen/src/Core/Reverse.h diff --git a/xs/src/eigen/Eigen/src/Core/Select.h b/src/eigen/Eigen/src/Core/Select.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/Select.h rename to src/eigen/Eigen/src/Core/Select.h diff --git a/xs/src/eigen/Eigen/src/Core/SelfAdjointView.h b/src/eigen/Eigen/src/Core/SelfAdjointView.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/SelfAdjointView.h rename to src/eigen/Eigen/src/Core/SelfAdjointView.h diff --git a/xs/src/eigen/Eigen/src/Core/SelfCwiseBinaryOp.h b/src/eigen/Eigen/src/Core/SelfCwiseBinaryOp.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/SelfCwiseBinaryOp.h rename to src/eigen/Eigen/src/Core/SelfCwiseBinaryOp.h diff --git a/xs/src/eigen/Eigen/src/Core/Solve.h b/src/eigen/Eigen/src/Core/Solve.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/Solve.h rename to src/eigen/Eigen/src/Core/Solve.h diff --git a/xs/src/eigen/Eigen/src/Core/SolveTriangular.h b/src/eigen/Eigen/src/Core/SolveTriangular.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/SolveTriangular.h rename to src/eigen/Eigen/src/Core/SolveTriangular.h diff --git a/xs/src/eigen/Eigen/src/Core/SolverBase.h b/src/eigen/Eigen/src/Core/SolverBase.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/SolverBase.h rename to src/eigen/Eigen/src/Core/SolverBase.h diff --git a/xs/src/eigen/Eigen/src/Core/StableNorm.h b/src/eigen/Eigen/src/Core/StableNorm.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/StableNorm.h rename to src/eigen/Eigen/src/Core/StableNorm.h diff --git a/xs/src/eigen/Eigen/src/Core/Stride.h b/src/eigen/Eigen/src/Core/Stride.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/Stride.h rename to src/eigen/Eigen/src/Core/Stride.h diff --git a/xs/src/eigen/Eigen/src/Core/Swap.h b/src/eigen/Eigen/src/Core/Swap.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/Swap.h rename to src/eigen/Eigen/src/Core/Swap.h diff --git a/xs/src/eigen/Eigen/src/Core/Transpose.h b/src/eigen/Eigen/src/Core/Transpose.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/Transpose.h rename to src/eigen/Eigen/src/Core/Transpose.h diff --git a/xs/src/eigen/Eigen/src/Core/Transpositions.h b/src/eigen/Eigen/src/Core/Transpositions.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/Transpositions.h rename to src/eigen/Eigen/src/Core/Transpositions.h diff --git a/xs/src/eigen/Eigen/src/Core/TriangularMatrix.h b/src/eigen/Eigen/src/Core/TriangularMatrix.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/TriangularMatrix.h rename to src/eigen/Eigen/src/Core/TriangularMatrix.h diff --git a/xs/src/eigen/Eigen/src/Core/VectorBlock.h b/src/eigen/Eigen/src/Core/VectorBlock.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/VectorBlock.h rename to src/eigen/Eigen/src/Core/VectorBlock.h diff --git a/xs/src/eigen/Eigen/src/Core/VectorwiseOp.h b/src/eigen/Eigen/src/Core/VectorwiseOp.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/VectorwiseOp.h rename to src/eigen/Eigen/src/Core/VectorwiseOp.h diff --git a/xs/src/eigen/Eigen/src/Core/Visitor.h b/src/eigen/Eigen/src/Core/Visitor.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/Visitor.h rename to src/eigen/Eigen/src/Core/Visitor.h diff --git a/xs/src/eigen/Eigen/src/Core/arch/AVX/Complex.h b/src/eigen/Eigen/src/Core/arch/AVX/Complex.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/arch/AVX/Complex.h rename to src/eigen/Eigen/src/Core/arch/AVX/Complex.h diff --git a/xs/src/eigen/Eigen/src/Core/arch/AVX/MathFunctions.h b/src/eigen/Eigen/src/Core/arch/AVX/MathFunctions.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/arch/AVX/MathFunctions.h rename to src/eigen/Eigen/src/Core/arch/AVX/MathFunctions.h diff --git a/xs/src/eigen/Eigen/src/Core/arch/AVX/PacketMath.h b/src/eigen/Eigen/src/Core/arch/AVX/PacketMath.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/arch/AVX/PacketMath.h rename to src/eigen/Eigen/src/Core/arch/AVX/PacketMath.h diff --git a/xs/src/eigen/Eigen/src/Core/arch/AVX/TypeCasting.h b/src/eigen/Eigen/src/Core/arch/AVX/TypeCasting.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/arch/AVX/TypeCasting.h rename to src/eigen/Eigen/src/Core/arch/AVX/TypeCasting.h diff --git a/xs/src/eigen/Eigen/src/Core/arch/AVX512/MathFunctions.h b/src/eigen/Eigen/src/Core/arch/AVX512/MathFunctions.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/arch/AVX512/MathFunctions.h rename to src/eigen/Eigen/src/Core/arch/AVX512/MathFunctions.h diff --git a/xs/src/eigen/Eigen/src/Core/arch/AVX512/PacketMath.h b/src/eigen/Eigen/src/Core/arch/AVX512/PacketMath.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/arch/AVX512/PacketMath.h rename to src/eigen/Eigen/src/Core/arch/AVX512/PacketMath.h diff --git a/xs/src/eigen/Eigen/src/Core/arch/AltiVec/Complex.h b/src/eigen/Eigen/src/Core/arch/AltiVec/Complex.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/arch/AltiVec/Complex.h rename to src/eigen/Eigen/src/Core/arch/AltiVec/Complex.h diff --git a/xs/src/eigen/Eigen/src/Core/arch/AltiVec/MathFunctions.h b/src/eigen/Eigen/src/Core/arch/AltiVec/MathFunctions.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/arch/AltiVec/MathFunctions.h rename to src/eigen/Eigen/src/Core/arch/AltiVec/MathFunctions.h diff --git a/xs/src/eigen/Eigen/src/Core/arch/AltiVec/PacketMath.h b/src/eigen/Eigen/src/Core/arch/AltiVec/PacketMath.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/arch/AltiVec/PacketMath.h rename to src/eigen/Eigen/src/Core/arch/AltiVec/PacketMath.h diff --git a/xs/src/eigen/Eigen/src/Core/arch/CUDA/Complex.h b/src/eigen/Eigen/src/Core/arch/CUDA/Complex.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/arch/CUDA/Complex.h rename to src/eigen/Eigen/src/Core/arch/CUDA/Complex.h diff --git a/xs/src/eigen/Eigen/src/Core/arch/CUDA/Half.h b/src/eigen/Eigen/src/Core/arch/CUDA/Half.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/arch/CUDA/Half.h rename to src/eigen/Eigen/src/Core/arch/CUDA/Half.h diff --git a/xs/src/eigen/Eigen/src/Core/arch/CUDA/MathFunctions.h b/src/eigen/Eigen/src/Core/arch/CUDA/MathFunctions.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/arch/CUDA/MathFunctions.h rename to src/eigen/Eigen/src/Core/arch/CUDA/MathFunctions.h diff --git a/xs/src/eigen/Eigen/src/Core/arch/CUDA/PacketMath.h b/src/eigen/Eigen/src/Core/arch/CUDA/PacketMath.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/arch/CUDA/PacketMath.h rename to src/eigen/Eigen/src/Core/arch/CUDA/PacketMath.h diff --git a/xs/src/eigen/Eigen/src/Core/arch/CUDA/PacketMathHalf.h b/src/eigen/Eigen/src/Core/arch/CUDA/PacketMathHalf.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/arch/CUDA/PacketMathHalf.h rename to src/eigen/Eigen/src/Core/arch/CUDA/PacketMathHalf.h diff --git a/xs/src/eigen/Eigen/src/Core/arch/CUDA/TypeCasting.h b/src/eigen/Eigen/src/Core/arch/CUDA/TypeCasting.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/arch/CUDA/TypeCasting.h rename to src/eigen/Eigen/src/Core/arch/CUDA/TypeCasting.h diff --git a/xs/src/eigen/Eigen/src/Core/arch/Default/ConjHelper.h b/src/eigen/Eigen/src/Core/arch/Default/ConjHelper.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/arch/Default/ConjHelper.h rename to src/eigen/Eigen/src/Core/arch/Default/ConjHelper.h diff --git a/xs/src/eigen/Eigen/src/Core/arch/Default/Settings.h b/src/eigen/Eigen/src/Core/arch/Default/Settings.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/arch/Default/Settings.h rename to src/eigen/Eigen/src/Core/arch/Default/Settings.h diff --git a/xs/src/eigen/Eigen/src/Core/arch/NEON/Complex.h b/src/eigen/Eigen/src/Core/arch/NEON/Complex.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/arch/NEON/Complex.h rename to src/eigen/Eigen/src/Core/arch/NEON/Complex.h diff --git a/xs/src/eigen/Eigen/src/Core/arch/NEON/MathFunctions.h b/src/eigen/Eigen/src/Core/arch/NEON/MathFunctions.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/arch/NEON/MathFunctions.h rename to src/eigen/Eigen/src/Core/arch/NEON/MathFunctions.h diff --git a/xs/src/eigen/Eigen/src/Core/arch/NEON/PacketMath.h b/src/eigen/Eigen/src/Core/arch/NEON/PacketMath.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/arch/NEON/PacketMath.h rename to src/eigen/Eigen/src/Core/arch/NEON/PacketMath.h diff --git a/xs/src/eigen/Eigen/src/Core/arch/SSE/Complex.h b/src/eigen/Eigen/src/Core/arch/SSE/Complex.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/arch/SSE/Complex.h rename to src/eigen/Eigen/src/Core/arch/SSE/Complex.h diff --git a/xs/src/eigen/Eigen/src/Core/arch/SSE/MathFunctions.h b/src/eigen/Eigen/src/Core/arch/SSE/MathFunctions.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/arch/SSE/MathFunctions.h rename to src/eigen/Eigen/src/Core/arch/SSE/MathFunctions.h diff --git a/xs/src/eigen/Eigen/src/Core/arch/SSE/PacketMath.h b/src/eigen/Eigen/src/Core/arch/SSE/PacketMath.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/arch/SSE/PacketMath.h rename to src/eigen/Eigen/src/Core/arch/SSE/PacketMath.h diff --git a/xs/src/eigen/Eigen/src/Core/arch/SSE/TypeCasting.h b/src/eigen/Eigen/src/Core/arch/SSE/TypeCasting.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/arch/SSE/TypeCasting.h rename to src/eigen/Eigen/src/Core/arch/SSE/TypeCasting.h diff --git a/xs/src/eigen/Eigen/src/Core/arch/ZVector/Complex.h b/src/eigen/Eigen/src/Core/arch/ZVector/Complex.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/arch/ZVector/Complex.h rename to src/eigen/Eigen/src/Core/arch/ZVector/Complex.h diff --git a/xs/src/eigen/Eigen/src/Core/arch/ZVector/MathFunctions.h b/src/eigen/Eigen/src/Core/arch/ZVector/MathFunctions.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/arch/ZVector/MathFunctions.h rename to src/eigen/Eigen/src/Core/arch/ZVector/MathFunctions.h diff --git a/xs/src/eigen/Eigen/src/Core/arch/ZVector/PacketMath.h b/src/eigen/Eigen/src/Core/arch/ZVector/PacketMath.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/arch/ZVector/PacketMath.h rename to src/eigen/Eigen/src/Core/arch/ZVector/PacketMath.h diff --git a/xs/src/eigen/Eigen/src/Core/functors/AssignmentFunctors.h b/src/eigen/Eigen/src/Core/functors/AssignmentFunctors.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/functors/AssignmentFunctors.h rename to src/eigen/Eigen/src/Core/functors/AssignmentFunctors.h diff --git a/xs/src/eigen/Eigen/src/Core/functors/BinaryFunctors.h b/src/eigen/Eigen/src/Core/functors/BinaryFunctors.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/functors/BinaryFunctors.h rename to src/eigen/Eigen/src/Core/functors/BinaryFunctors.h diff --git a/xs/src/eigen/Eigen/src/Core/functors/NullaryFunctors.h b/src/eigen/Eigen/src/Core/functors/NullaryFunctors.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/functors/NullaryFunctors.h rename to src/eigen/Eigen/src/Core/functors/NullaryFunctors.h diff --git a/xs/src/eigen/Eigen/src/Core/functors/StlFunctors.h b/src/eigen/Eigen/src/Core/functors/StlFunctors.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/functors/StlFunctors.h rename to src/eigen/Eigen/src/Core/functors/StlFunctors.h diff --git a/xs/src/eigen/Eigen/src/Core/functors/TernaryFunctors.h b/src/eigen/Eigen/src/Core/functors/TernaryFunctors.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/functors/TernaryFunctors.h rename to src/eigen/Eigen/src/Core/functors/TernaryFunctors.h diff --git a/xs/src/eigen/Eigen/src/Core/functors/UnaryFunctors.h b/src/eigen/Eigen/src/Core/functors/UnaryFunctors.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/functors/UnaryFunctors.h rename to src/eigen/Eigen/src/Core/functors/UnaryFunctors.h diff --git a/xs/src/eigen/Eigen/src/Core/products/GeneralBlockPanelKernel.h b/src/eigen/Eigen/src/Core/products/GeneralBlockPanelKernel.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/products/GeneralBlockPanelKernel.h rename to src/eigen/Eigen/src/Core/products/GeneralBlockPanelKernel.h diff --git a/xs/src/eigen/Eigen/src/Core/products/GeneralMatrixMatrix.h b/src/eigen/Eigen/src/Core/products/GeneralMatrixMatrix.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/products/GeneralMatrixMatrix.h rename to src/eigen/Eigen/src/Core/products/GeneralMatrixMatrix.h diff --git a/xs/src/eigen/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h b/src/eigen/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h rename to src/eigen/Eigen/src/Core/products/GeneralMatrixMatrixTriangular.h diff --git a/xs/src/eigen/Eigen/src/Core/products/GeneralMatrixMatrixTriangular_BLAS.h b/src/eigen/Eigen/src/Core/products/GeneralMatrixMatrixTriangular_BLAS.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/products/GeneralMatrixMatrixTriangular_BLAS.h rename to src/eigen/Eigen/src/Core/products/GeneralMatrixMatrixTriangular_BLAS.h diff --git a/xs/src/eigen/Eigen/src/Core/products/GeneralMatrixMatrix_BLAS.h b/src/eigen/Eigen/src/Core/products/GeneralMatrixMatrix_BLAS.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/products/GeneralMatrixMatrix_BLAS.h rename to src/eigen/Eigen/src/Core/products/GeneralMatrixMatrix_BLAS.h diff --git a/xs/src/eigen/Eigen/src/Core/products/GeneralMatrixVector.h b/src/eigen/Eigen/src/Core/products/GeneralMatrixVector.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/products/GeneralMatrixVector.h rename to src/eigen/Eigen/src/Core/products/GeneralMatrixVector.h diff --git a/xs/src/eigen/Eigen/src/Core/products/GeneralMatrixVector_BLAS.h b/src/eigen/Eigen/src/Core/products/GeneralMatrixVector_BLAS.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/products/GeneralMatrixVector_BLAS.h rename to src/eigen/Eigen/src/Core/products/GeneralMatrixVector_BLAS.h diff --git a/xs/src/eigen/Eigen/src/Core/products/Parallelizer.h b/src/eigen/Eigen/src/Core/products/Parallelizer.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/products/Parallelizer.h rename to src/eigen/Eigen/src/Core/products/Parallelizer.h diff --git a/xs/src/eigen/Eigen/src/Core/products/SelfadjointMatrixMatrix.h b/src/eigen/Eigen/src/Core/products/SelfadjointMatrixMatrix.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/products/SelfadjointMatrixMatrix.h rename to src/eigen/Eigen/src/Core/products/SelfadjointMatrixMatrix.h diff --git a/xs/src/eigen/Eigen/src/Core/products/SelfadjointMatrixMatrix_BLAS.h b/src/eigen/Eigen/src/Core/products/SelfadjointMatrixMatrix_BLAS.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/products/SelfadjointMatrixMatrix_BLAS.h rename to src/eigen/Eigen/src/Core/products/SelfadjointMatrixMatrix_BLAS.h diff --git a/xs/src/eigen/Eigen/src/Core/products/SelfadjointMatrixVector.h b/src/eigen/Eigen/src/Core/products/SelfadjointMatrixVector.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/products/SelfadjointMatrixVector.h rename to src/eigen/Eigen/src/Core/products/SelfadjointMatrixVector.h diff --git a/xs/src/eigen/Eigen/src/Core/products/SelfadjointMatrixVector_BLAS.h b/src/eigen/Eigen/src/Core/products/SelfadjointMatrixVector_BLAS.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/products/SelfadjointMatrixVector_BLAS.h rename to src/eigen/Eigen/src/Core/products/SelfadjointMatrixVector_BLAS.h diff --git a/xs/src/eigen/Eigen/src/Core/products/SelfadjointProduct.h b/src/eigen/Eigen/src/Core/products/SelfadjointProduct.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/products/SelfadjointProduct.h rename to src/eigen/Eigen/src/Core/products/SelfadjointProduct.h diff --git a/xs/src/eigen/Eigen/src/Core/products/SelfadjointRank2Update.h b/src/eigen/Eigen/src/Core/products/SelfadjointRank2Update.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/products/SelfadjointRank2Update.h rename to src/eigen/Eigen/src/Core/products/SelfadjointRank2Update.h diff --git a/xs/src/eigen/Eigen/src/Core/products/TriangularMatrixMatrix.h b/src/eigen/Eigen/src/Core/products/TriangularMatrixMatrix.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/products/TriangularMatrixMatrix.h rename to src/eigen/Eigen/src/Core/products/TriangularMatrixMatrix.h diff --git a/xs/src/eigen/Eigen/src/Core/products/TriangularMatrixMatrix_BLAS.h b/src/eigen/Eigen/src/Core/products/TriangularMatrixMatrix_BLAS.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/products/TriangularMatrixMatrix_BLAS.h rename to src/eigen/Eigen/src/Core/products/TriangularMatrixMatrix_BLAS.h diff --git a/xs/src/eigen/Eigen/src/Core/products/TriangularMatrixVector.h b/src/eigen/Eigen/src/Core/products/TriangularMatrixVector.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/products/TriangularMatrixVector.h rename to src/eigen/Eigen/src/Core/products/TriangularMatrixVector.h diff --git a/xs/src/eigen/Eigen/src/Core/products/TriangularMatrixVector_BLAS.h b/src/eigen/Eigen/src/Core/products/TriangularMatrixVector_BLAS.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/products/TriangularMatrixVector_BLAS.h rename to src/eigen/Eigen/src/Core/products/TriangularMatrixVector_BLAS.h diff --git a/xs/src/eigen/Eigen/src/Core/products/TriangularSolverMatrix.h b/src/eigen/Eigen/src/Core/products/TriangularSolverMatrix.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/products/TriangularSolverMatrix.h rename to src/eigen/Eigen/src/Core/products/TriangularSolverMatrix.h diff --git a/xs/src/eigen/Eigen/src/Core/products/TriangularSolverMatrix_BLAS.h b/src/eigen/Eigen/src/Core/products/TriangularSolverMatrix_BLAS.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/products/TriangularSolverMatrix_BLAS.h rename to src/eigen/Eigen/src/Core/products/TriangularSolverMatrix_BLAS.h diff --git a/xs/src/eigen/Eigen/src/Core/products/TriangularSolverVector.h b/src/eigen/Eigen/src/Core/products/TriangularSolverVector.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/products/TriangularSolverVector.h rename to src/eigen/Eigen/src/Core/products/TriangularSolverVector.h diff --git a/xs/src/eigen/Eigen/src/Core/util/BlasUtil.h b/src/eigen/Eigen/src/Core/util/BlasUtil.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/util/BlasUtil.h rename to src/eigen/Eigen/src/Core/util/BlasUtil.h diff --git a/xs/src/eigen/Eigen/src/Core/util/Constants.h b/src/eigen/Eigen/src/Core/util/Constants.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/util/Constants.h rename to src/eigen/Eigen/src/Core/util/Constants.h diff --git a/xs/src/eigen/Eigen/src/Core/util/DisableStupidWarnings.h b/src/eigen/Eigen/src/Core/util/DisableStupidWarnings.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/util/DisableStupidWarnings.h rename to src/eigen/Eigen/src/Core/util/DisableStupidWarnings.h diff --git a/xs/src/eigen/Eigen/src/Core/util/ForwardDeclarations.h b/src/eigen/Eigen/src/Core/util/ForwardDeclarations.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/util/ForwardDeclarations.h rename to src/eigen/Eigen/src/Core/util/ForwardDeclarations.h diff --git a/xs/src/eigen/Eigen/src/Core/util/MKL_support.h b/src/eigen/Eigen/src/Core/util/MKL_support.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/util/MKL_support.h rename to src/eigen/Eigen/src/Core/util/MKL_support.h diff --git a/xs/src/eigen/Eigen/src/Core/util/Macros.h b/src/eigen/Eigen/src/Core/util/Macros.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/util/Macros.h rename to src/eigen/Eigen/src/Core/util/Macros.h diff --git a/xs/src/eigen/Eigen/src/Core/util/Memory.h b/src/eigen/Eigen/src/Core/util/Memory.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/util/Memory.h rename to src/eigen/Eigen/src/Core/util/Memory.h diff --git a/xs/src/eigen/Eigen/src/Core/util/Meta.h b/src/eigen/Eigen/src/Core/util/Meta.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/util/Meta.h rename to src/eigen/Eigen/src/Core/util/Meta.h diff --git a/xs/src/eigen/Eigen/src/Core/util/NonMPL2.h b/src/eigen/Eigen/src/Core/util/NonMPL2.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/util/NonMPL2.h rename to src/eigen/Eigen/src/Core/util/NonMPL2.h diff --git a/xs/src/eigen/Eigen/src/Core/util/ReenableStupidWarnings.h b/src/eigen/Eigen/src/Core/util/ReenableStupidWarnings.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/util/ReenableStupidWarnings.h rename to src/eigen/Eigen/src/Core/util/ReenableStupidWarnings.h diff --git a/xs/src/eigen/Eigen/src/Core/util/StaticAssert.h b/src/eigen/Eigen/src/Core/util/StaticAssert.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/util/StaticAssert.h rename to src/eigen/Eigen/src/Core/util/StaticAssert.h diff --git a/xs/src/eigen/Eigen/src/Core/util/XprHelper.h b/src/eigen/Eigen/src/Core/util/XprHelper.h similarity index 100% rename from xs/src/eigen/Eigen/src/Core/util/XprHelper.h rename to src/eigen/Eigen/src/Core/util/XprHelper.h diff --git a/xs/src/eigen/Eigen/src/Eigenvalues/ComplexEigenSolver.h b/src/eigen/Eigen/src/Eigenvalues/ComplexEigenSolver.h similarity index 100% rename from xs/src/eigen/Eigen/src/Eigenvalues/ComplexEigenSolver.h rename to src/eigen/Eigen/src/Eigenvalues/ComplexEigenSolver.h diff --git a/xs/src/eigen/Eigen/src/Eigenvalues/ComplexSchur.h b/src/eigen/Eigen/src/Eigenvalues/ComplexSchur.h similarity index 100% rename from xs/src/eigen/Eigen/src/Eigenvalues/ComplexSchur.h rename to src/eigen/Eigen/src/Eigenvalues/ComplexSchur.h diff --git a/xs/src/eigen/Eigen/src/Eigenvalues/ComplexSchur_LAPACKE.h b/src/eigen/Eigen/src/Eigenvalues/ComplexSchur_LAPACKE.h similarity index 100% rename from xs/src/eigen/Eigen/src/Eigenvalues/ComplexSchur_LAPACKE.h rename to src/eigen/Eigen/src/Eigenvalues/ComplexSchur_LAPACKE.h diff --git a/xs/src/eigen/Eigen/src/Eigenvalues/EigenSolver.h b/src/eigen/Eigen/src/Eigenvalues/EigenSolver.h similarity index 100% rename from xs/src/eigen/Eigen/src/Eigenvalues/EigenSolver.h rename to src/eigen/Eigen/src/Eigenvalues/EigenSolver.h diff --git a/xs/src/eigen/Eigen/src/Eigenvalues/GeneralizedEigenSolver.h b/src/eigen/Eigen/src/Eigenvalues/GeneralizedEigenSolver.h similarity index 100% rename from xs/src/eigen/Eigen/src/Eigenvalues/GeneralizedEigenSolver.h rename to src/eigen/Eigen/src/Eigenvalues/GeneralizedEigenSolver.h diff --git a/xs/src/eigen/Eigen/src/Eigenvalues/GeneralizedSelfAdjointEigenSolver.h b/src/eigen/Eigen/src/Eigenvalues/GeneralizedSelfAdjointEigenSolver.h similarity index 100% rename from xs/src/eigen/Eigen/src/Eigenvalues/GeneralizedSelfAdjointEigenSolver.h rename to src/eigen/Eigen/src/Eigenvalues/GeneralizedSelfAdjointEigenSolver.h diff --git a/xs/src/eigen/Eigen/src/Eigenvalues/HessenbergDecomposition.h b/src/eigen/Eigen/src/Eigenvalues/HessenbergDecomposition.h similarity index 100% rename from xs/src/eigen/Eigen/src/Eigenvalues/HessenbergDecomposition.h rename to src/eigen/Eigen/src/Eigenvalues/HessenbergDecomposition.h diff --git a/xs/src/eigen/Eigen/src/Eigenvalues/MatrixBaseEigenvalues.h b/src/eigen/Eigen/src/Eigenvalues/MatrixBaseEigenvalues.h similarity index 100% rename from xs/src/eigen/Eigen/src/Eigenvalues/MatrixBaseEigenvalues.h rename to src/eigen/Eigen/src/Eigenvalues/MatrixBaseEigenvalues.h diff --git a/xs/src/eigen/Eigen/src/Eigenvalues/RealQZ.h b/src/eigen/Eigen/src/Eigenvalues/RealQZ.h similarity index 100% rename from xs/src/eigen/Eigen/src/Eigenvalues/RealQZ.h rename to src/eigen/Eigen/src/Eigenvalues/RealQZ.h diff --git a/xs/src/eigen/Eigen/src/Eigenvalues/RealSchur.h b/src/eigen/Eigen/src/Eigenvalues/RealSchur.h similarity index 100% rename from xs/src/eigen/Eigen/src/Eigenvalues/RealSchur.h rename to src/eigen/Eigen/src/Eigenvalues/RealSchur.h diff --git a/xs/src/eigen/Eigen/src/Eigenvalues/RealSchur_LAPACKE.h b/src/eigen/Eigen/src/Eigenvalues/RealSchur_LAPACKE.h similarity index 100% rename from xs/src/eigen/Eigen/src/Eigenvalues/RealSchur_LAPACKE.h rename to src/eigen/Eigen/src/Eigenvalues/RealSchur_LAPACKE.h diff --git a/xs/src/eigen/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h b/src/eigen/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h similarity index 100% rename from xs/src/eigen/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h rename to src/eigen/Eigen/src/Eigenvalues/SelfAdjointEigenSolver.h diff --git a/xs/src/eigen/Eigen/src/Eigenvalues/SelfAdjointEigenSolver_LAPACKE.h b/src/eigen/Eigen/src/Eigenvalues/SelfAdjointEigenSolver_LAPACKE.h similarity index 100% rename from xs/src/eigen/Eigen/src/Eigenvalues/SelfAdjointEigenSolver_LAPACKE.h rename to src/eigen/Eigen/src/Eigenvalues/SelfAdjointEigenSolver_LAPACKE.h diff --git a/xs/src/eigen/Eigen/src/Eigenvalues/Tridiagonalization.h b/src/eigen/Eigen/src/Eigenvalues/Tridiagonalization.h similarity index 100% rename from xs/src/eigen/Eigen/src/Eigenvalues/Tridiagonalization.h rename to src/eigen/Eigen/src/Eigenvalues/Tridiagonalization.h diff --git a/xs/src/eigen/Eigen/src/Geometry/AlignedBox.h b/src/eigen/Eigen/src/Geometry/AlignedBox.h similarity index 100% rename from xs/src/eigen/Eigen/src/Geometry/AlignedBox.h rename to src/eigen/Eigen/src/Geometry/AlignedBox.h diff --git a/xs/src/eigen/Eigen/src/Geometry/AngleAxis.h b/src/eigen/Eigen/src/Geometry/AngleAxis.h similarity index 100% rename from xs/src/eigen/Eigen/src/Geometry/AngleAxis.h rename to src/eigen/Eigen/src/Geometry/AngleAxis.h diff --git a/xs/src/eigen/Eigen/src/Geometry/EulerAngles.h b/src/eigen/Eigen/src/Geometry/EulerAngles.h similarity index 100% rename from xs/src/eigen/Eigen/src/Geometry/EulerAngles.h rename to src/eigen/Eigen/src/Geometry/EulerAngles.h diff --git a/xs/src/eigen/Eigen/src/Geometry/Homogeneous.h b/src/eigen/Eigen/src/Geometry/Homogeneous.h similarity index 100% rename from xs/src/eigen/Eigen/src/Geometry/Homogeneous.h rename to src/eigen/Eigen/src/Geometry/Homogeneous.h diff --git a/xs/src/eigen/Eigen/src/Geometry/Hyperplane.h b/src/eigen/Eigen/src/Geometry/Hyperplane.h similarity index 100% rename from xs/src/eigen/Eigen/src/Geometry/Hyperplane.h rename to src/eigen/Eigen/src/Geometry/Hyperplane.h diff --git a/xs/src/eigen/Eigen/src/Geometry/OrthoMethods.h b/src/eigen/Eigen/src/Geometry/OrthoMethods.h similarity index 100% rename from xs/src/eigen/Eigen/src/Geometry/OrthoMethods.h rename to src/eigen/Eigen/src/Geometry/OrthoMethods.h diff --git a/xs/src/eigen/Eigen/src/Geometry/ParametrizedLine.h b/src/eigen/Eigen/src/Geometry/ParametrizedLine.h similarity index 100% rename from xs/src/eigen/Eigen/src/Geometry/ParametrizedLine.h rename to src/eigen/Eigen/src/Geometry/ParametrizedLine.h diff --git a/xs/src/eigen/Eigen/src/Geometry/Quaternion.h b/src/eigen/Eigen/src/Geometry/Quaternion.h similarity index 100% rename from xs/src/eigen/Eigen/src/Geometry/Quaternion.h rename to src/eigen/Eigen/src/Geometry/Quaternion.h diff --git a/xs/src/eigen/Eigen/src/Geometry/Rotation2D.h b/src/eigen/Eigen/src/Geometry/Rotation2D.h similarity index 100% rename from xs/src/eigen/Eigen/src/Geometry/Rotation2D.h rename to src/eigen/Eigen/src/Geometry/Rotation2D.h diff --git a/xs/src/eigen/Eigen/src/Geometry/RotationBase.h b/src/eigen/Eigen/src/Geometry/RotationBase.h similarity index 100% rename from xs/src/eigen/Eigen/src/Geometry/RotationBase.h rename to src/eigen/Eigen/src/Geometry/RotationBase.h diff --git a/xs/src/eigen/Eigen/src/Geometry/Scaling.h b/src/eigen/Eigen/src/Geometry/Scaling.h similarity index 100% rename from xs/src/eigen/Eigen/src/Geometry/Scaling.h rename to src/eigen/Eigen/src/Geometry/Scaling.h diff --git a/xs/src/eigen/Eigen/src/Geometry/Transform.h b/src/eigen/Eigen/src/Geometry/Transform.h similarity index 100% rename from xs/src/eigen/Eigen/src/Geometry/Transform.h rename to src/eigen/Eigen/src/Geometry/Transform.h diff --git a/xs/src/eigen/Eigen/src/Geometry/Translation.h b/src/eigen/Eigen/src/Geometry/Translation.h similarity index 100% rename from xs/src/eigen/Eigen/src/Geometry/Translation.h rename to src/eigen/Eigen/src/Geometry/Translation.h diff --git a/xs/src/eigen/Eigen/src/Geometry/Umeyama.h b/src/eigen/Eigen/src/Geometry/Umeyama.h similarity index 100% rename from xs/src/eigen/Eigen/src/Geometry/Umeyama.h rename to src/eigen/Eigen/src/Geometry/Umeyama.h diff --git a/xs/src/eigen/Eigen/src/Geometry/arch/Geometry_SSE.h b/src/eigen/Eigen/src/Geometry/arch/Geometry_SSE.h similarity index 100% rename from xs/src/eigen/Eigen/src/Geometry/arch/Geometry_SSE.h rename to src/eigen/Eigen/src/Geometry/arch/Geometry_SSE.h diff --git a/xs/src/eigen/Eigen/src/Householder/BlockHouseholder.h b/src/eigen/Eigen/src/Householder/BlockHouseholder.h similarity index 100% rename from xs/src/eigen/Eigen/src/Householder/BlockHouseholder.h rename to src/eigen/Eigen/src/Householder/BlockHouseholder.h diff --git a/xs/src/eigen/Eigen/src/Householder/Householder.h b/src/eigen/Eigen/src/Householder/Householder.h similarity index 100% rename from xs/src/eigen/Eigen/src/Householder/Householder.h rename to src/eigen/Eigen/src/Householder/Householder.h diff --git a/xs/src/eigen/Eigen/src/Householder/HouseholderSequence.h b/src/eigen/Eigen/src/Householder/HouseholderSequence.h similarity index 100% rename from xs/src/eigen/Eigen/src/Householder/HouseholderSequence.h rename to src/eigen/Eigen/src/Householder/HouseholderSequence.h diff --git a/xs/src/eigen/Eigen/src/IterativeLinearSolvers/BasicPreconditioners.h b/src/eigen/Eigen/src/IterativeLinearSolvers/BasicPreconditioners.h similarity index 100% rename from xs/src/eigen/Eigen/src/IterativeLinearSolvers/BasicPreconditioners.h rename to src/eigen/Eigen/src/IterativeLinearSolvers/BasicPreconditioners.h diff --git a/xs/src/eigen/Eigen/src/IterativeLinearSolvers/BiCGSTAB.h b/src/eigen/Eigen/src/IterativeLinearSolvers/BiCGSTAB.h similarity index 100% rename from xs/src/eigen/Eigen/src/IterativeLinearSolvers/BiCGSTAB.h rename to src/eigen/Eigen/src/IterativeLinearSolvers/BiCGSTAB.h diff --git a/xs/src/eigen/Eigen/src/IterativeLinearSolvers/ConjugateGradient.h b/src/eigen/Eigen/src/IterativeLinearSolvers/ConjugateGradient.h similarity index 100% rename from xs/src/eigen/Eigen/src/IterativeLinearSolvers/ConjugateGradient.h rename to src/eigen/Eigen/src/IterativeLinearSolvers/ConjugateGradient.h diff --git a/xs/src/eigen/Eigen/src/IterativeLinearSolvers/IncompleteCholesky.h b/src/eigen/Eigen/src/IterativeLinearSolvers/IncompleteCholesky.h similarity index 100% rename from xs/src/eigen/Eigen/src/IterativeLinearSolvers/IncompleteCholesky.h rename to src/eigen/Eigen/src/IterativeLinearSolvers/IncompleteCholesky.h diff --git a/xs/src/eigen/Eigen/src/IterativeLinearSolvers/IncompleteLUT.h b/src/eigen/Eigen/src/IterativeLinearSolvers/IncompleteLUT.h similarity index 100% rename from xs/src/eigen/Eigen/src/IterativeLinearSolvers/IncompleteLUT.h rename to src/eigen/Eigen/src/IterativeLinearSolvers/IncompleteLUT.h diff --git a/xs/src/eigen/Eigen/src/IterativeLinearSolvers/IterativeSolverBase.h b/src/eigen/Eigen/src/IterativeLinearSolvers/IterativeSolverBase.h similarity index 100% rename from xs/src/eigen/Eigen/src/IterativeLinearSolvers/IterativeSolverBase.h rename to src/eigen/Eigen/src/IterativeLinearSolvers/IterativeSolverBase.h diff --git a/xs/src/eigen/Eigen/src/IterativeLinearSolvers/LeastSquareConjugateGradient.h b/src/eigen/Eigen/src/IterativeLinearSolvers/LeastSquareConjugateGradient.h similarity index 100% rename from xs/src/eigen/Eigen/src/IterativeLinearSolvers/LeastSquareConjugateGradient.h rename to src/eigen/Eigen/src/IterativeLinearSolvers/LeastSquareConjugateGradient.h diff --git a/xs/src/eigen/Eigen/src/IterativeLinearSolvers/SolveWithGuess.h b/src/eigen/Eigen/src/IterativeLinearSolvers/SolveWithGuess.h similarity index 100% rename from xs/src/eigen/Eigen/src/IterativeLinearSolvers/SolveWithGuess.h rename to src/eigen/Eigen/src/IterativeLinearSolvers/SolveWithGuess.h diff --git a/xs/src/eigen/Eigen/src/Jacobi/Jacobi.h b/src/eigen/Eigen/src/Jacobi/Jacobi.h similarity index 100% rename from xs/src/eigen/Eigen/src/Jacobi/Jacobi.h rename to src/eigen/Eigen/src/Jacobi/Jacobi.h diff --git a/xs/src/eigen/Eigen/src/LU/Determinant.h b/src/eigen/Eigen/src/LU/Determinant.h similarity index 100% rename from xs/src/eigen/Eigen/src/LU/Determinant.h rename to src/eigen/Eigen/src/LU/Determinant.h diff --git a/xs/src/eigen/Eigen/src/LU/FullPivLU.h b/src/eigen/Eigen/src/LU/FullPivLU.h similarity index 100% rename from xs/src/eigen/Eigen/src/LU/FullPivLU.h rename to src/eigen/Eigen/src/LU/FullPivLU.h diff --git a/xs/src/eigen/Eigen/src/LU/InverseImpl.h b/src/eigen/Eigen/src/LU/InverseImpl.h similarity index 100% rename from xs/src/eigen/Eigen/src/LU/InverseImpl.h rename to src/eigen/Eigen/src/LU/InverseImpl.h diff --git a/xs/src/eigen/Eigen/src/LU/PartialPivLU.h b/src/eigen/Eigen/src/LU/PartialPivLU.h similarity index 100% rename from xs/src/eigen/Eigen/src/LU/PartialPivLU.h rename to src/eigen/Eigen/src/LU/PartialPivLU.h diff --git a/xs/src/eigen/Eigen/src/LU/PartialPivLU_LAPACKE.h b/src/eigen/Eigen/src/LU/PartialPivLU_LAPACKE.h similarity index 100% rename from xs/src/eigen/Eigen/src/LU/PartialPivLU_LAPACKE.h rename to src/eigen/Eigen/src/LU/PartialPivLU_LAPACKE.h diff --git a/xs/src/eigen/Eigen/src/LU/arch/Inverse_SSE.h b/src/eigen/Eigen/src/LU/arch/Inverse_SSE.h similarity index 100% rename from xs/src/eigen/Eigen/src/LU/arch/Inverse_SSE.h rename to src/eigen/Eigen/src/LU/arch/Inverse_SSE.h diff --git a/xs/src/eigen/Eigen/src/MetisSupport/MetisSupport.h b/src/eigen/Eigen/src/MetisSupport/MetisSupport.h similarity index 100% rename from xs/src/eigen/Eigen/src/MetisSupport/MetisSupport.h rename to src/eigen/Eigen/src/MetisSupport/MetisSupport.h diff --git a/xs/src/eigen/Eigen/src/OrderingMethods/Amd.h b/src/eigen/Eigen/src/OrderingMethods/Amd.h similarity index 100% rename from xs/src/eigen/Eigen/src/OrderingMethods/Amd.h rename to src/eigen/Eigen/src/OrderingMethods/Amd.h diff --git a/xs/src/eigen/Eigen/src/OrderingMethods/Eigen_Colamd.h b/src/eigen/Eigen/src/OrderingMethods/Eigen_Colamd.h similarity index 100% rename from xs/src/eigen/Eigen/src/OrderingMethods/Eigen_Colamd.h rename to src/eigen/Eigen/src/OrderingMethods/Eigen_Colamd.h diff --git a/xs/src/eigen/Eigen/src/OrderingMethods/Ordering.h b/src/eigen/Eigen/src/OrderingMethods/Ordering.h similarity index 100% rename from xs/src/eigen/Eigen/src/OrderingMethods/Ordering.h rename to src/eigen/Eigen/src/OrderingMethods/Ordering.h diff --git a/xs/src/eigen/Eigen/src/PaStiXSupport/PaStiXSupport.h b/src/eigen/Eigen/src/PaStiXSupport/PaStiXSupport.h similarity index 100% rename from xs/src/eigen/Eigen/src/PaStiXSupport/PaStiXSupport.h rename to src/eigen/Eigen/src/PaStiXSupport/PaStiXSupport.h diff --git a/xs/src/eigen/Eigen/src/PardisoSupport/PardisoSupport.h b/src/eigen/Eigen/src/PardisoSupport/PardisoSupport.h similarity index 100% rename from xs/src/eigen/Eigen/src/PardisoSupport/PardisoSupport.h rename to src/eigen/Eigen/src/PardisoSupport/PardisoSupport.h diff --git a/xs/src/eigen/Eigen/src/QR/ColPivHouseholderQR.h b/src/eigen/Eigen/src/QR/ColPivHouseholderQR.h similarity index 100% rename from xs/src/eigen/Eigen/src/QR/ColPivHouseholderQR.h rename to src/eigen/Eigen/src/QR/ColPivHouseholderQR.h diff --git a/xs/src/eigen/Eigen/src/QR/ColPivHouseholderQR_LAPACKE.h b/src/eigen/Eigen/src/QR/ColPivHouseholderQR_LAPACKE.h similarity index 100% rename from xs/src/eigen/Eigen/src/QR/ColPivHouseholderQR_LAPACKE.h rename to src/eigen/Eigen/src/QR/ColPivHouseholderQR_LAPACKE.h diff --git a/xs/src/eigen/Eigen/src/QR/CompleteOrthogonalDecomposition.h b/src/eigen/Eigen/src/QR/CompleteOrthogonalDecomposition.h similarity index 100% rename from xs/src/eigen/Eigen/src/QR/CompleteOrthogonalDecomposition.h rename to src/eigen/Eigen/src/QR/CompleteOrthogonalDecomposition.h diff --git a/xs/src/eigen/Eigen/src/QR/FullPivHouseholderQR.h b/src/eigen/Eigen/src/QR/FullPivHouseholderQR.h similarity index 100% rename from xs/src/eigen/Eigen/src/QR/FullPivHouseholderQR.h rename to src/eigen/Eigen/src/QR/FullPivHouseholderQR.h diff --git a/xs/src/eigen/Eigen/src/QR/HouseholderQR.h b/src/eigen/Eigen/src/QR/HouseholderQR.h similarity index 100% rename from xs/src/eigen/Eigen/src/QR/HouseholderQR.h rename to src/eigen/Eigen/src/QR/HouseholderQR.h diff --git a/xs/src/eigen/Eigen/src/QR/HouseholderQR_LAPACKE.h b/src/eigen/Eigen/src/QR/HouseholderQR_LAPACKE.h similarity index 100% rename from xs/src/eigen/Eigen/src/QR/HouseholderQR_LAPACKE.h rename to src/eigen/Eigen/src/QR/HouseholderQR_LAPACKE.h diff --git a/xs/src/eigen/Eigen/src/SPQRSupport/SuiteSparseQRSupport.h b/src/eigen/Eigen/src/SPQRSupport/SuiteSparseQRSupport.h similarity index 100% rename from xs/src/eigen/Eigen/src/SPQRSupport/SuiteSparseQRSupport.h rename to src/eigen/Eigen/src/SPQRSupport/SuiteSparseQRSupport.h diff --git a/xs/src/eigen/Eigen/src/SVD/BDCSVD.h b/src/eigen/Eigen/src/SVD/BDCSVD.h similarity index 100% rename from xs/src/eigen/Eigen/src/SVD/BDCSVD.h rename to src/eigen/Eigen/src/SVD/BDCSVD.h diff --git a/xs/src/eigen/Eigen/src/SVD/JacobiSVD.h b/src/eigen/Eigen/src/SVD/JacobiSVD.h similarity index 100% rename from xs/src/eigen/Eigen/src/SVD/JacobiSVD.h rename to src/eigen/Eigen/src/SVD/JacobiSVD.h diff --git a/xs/src/eigen/Eigen/src/SVD/JacobiSVD_LAPACKE.h b/src/eigen/Eigen/src/SVD/JacobiSVD_LAPACKE.h similarity index 100% rename from xs/src/eigen/Eigen/src/SVD/JacobiSVD_LAPACKE.h rename to src/eigen/Eigen/src/SVD/JacobiSVD_LAPACKE.h diff --git a/xs/src/eigen/Eigen/src/SVD/SVDBase.h b/src/eigen/Eigen/src/SVD/SVDBase.h similarity index 100% rename from xs/src/eigen/Eigen/src/SVD/SVDBase.h rename to src/eigen/Eigen/src/SVD/SVDBase.h diff --git a/xs/src/eigen/Eigen/src/SVD/UpperBidiagonalization.h b/src/eigen/Eigen/src/SVD/UpperBidiagonalization.h similarity index 100% rename from xs/src/eigen/Eigen/src/SVD/UpperBidiagonalization.h rename to src/eigen/Eigen/src/SVD/UpperBidiagonalization.h diff --git a/xs/src/eigen/Eigen/src/SparseCholesky/SimplicialCholesky.h b/src/eigen/Eigen/src/SparseCholesky/SimplicialCholesky.h similarity index 100% rename from xs/src/eigen/Eigen/src/SparseCholesky/SimplicialCholesky.h rename to src/eigen/Eigen/src/SparseCholesky/SimplicialCholesky.h diff --git a/xs/src/eigen/Eigen/src/SparseCholesky/SimplicialCholesky_impl.h b/src/eigen/Eigen/src/SparseCholesky/SimplicialCholesky_impl.h similarity index 100% rename from xs/src/eigen/Eigen/src/SparseCholesky/SimplicialCholesky_impl.h rename to src/eigen/Eigen/src/SparseCholesky/SimplicialCholesky_impl.h diff --git a/xs/src/eigen/Eigen/src/SparseCore/AmbiVector.h b/src/eigen/Eigen/src/SparseCore/AmbiVector.h similarity index 100% rename from xs/src/eigen/Eigen/src/SparseCore/AmbiVector.h rename to src/eigen/Eigen/src/SparseCore/AmbiVector.h diff --git a/xs/src/eigen/Eigen/src/SparseCore/CompressedStorage.h b/src/eigen/Eigen/src/SparseCore/CompressedStorage.h similarity index 100% rename from xs/src/eigen/Eigen/src/SparseCore/CompressedStorage.h rename to src/eigen/Eigen/src/SparseCore/CompressedStorage.h diff --git a/xs/src/eigen/Eigen/src/SparseCore/ConservativeSparseSparseProduct.h b/src/eigen/Eigen/src/SparseCore/ConservativeSparseSparseProduct.h similarity index 100% rename from xs/src/eigen/Eigen/src/SparseCore/ConservativeSparseSparseProduct.h rename to src/eigen/Eigen/src/SparseCore/ConservativeSparseSparseProduct.h diff --git a/xs/src/eigen/Eigen/src/SparseCore/MappedSparseMatrix.h b/src/eigen/Eigen/src/SparseCore/MappedSparseMatrix.h similarity index 100% rename from xs/src/eigen/Eigen/src/SparseCore/MappedSparseMatrix.h rename to src/eigen/Eigen/src/SparseCore/MappedSparseMatrix.h diff --git a/xs/src/eigen/Eigen/src/SparseCore/SparseAssign.h b/src/eigen/Eigen/src/SparseCore/SparseAssign.h similarity index 100% rename from xs/src/eigen/Eigen/src/SparseCore/SparseAssign.h rename to src/eigen/Eigen/src/SparseCore/SparseAssign.h diff --git a/xs/src/eigen/Eigen/src/SparseCore/SparseBlock.h b/src/eigen/Eigen/src/SparseCore/SparseBlock.h similarity index 100% rename from xs/src/eigen/Eigen/src/SparseCore/SparseBlock.h rename to src/eigen/Eigen/src/SparseCore/SparseBlock.h diff --git a/xs/src/eigen/Eigen/src/SparseCore/SparseColEtree.h b/src/eigen/Eigen/src/SparseCore/SparseColEtree.h similarity index 100% rename from xs/src/eigen/Eigen/src/SparseCore/SparseColEtree.h rename to src/eigen/Eigen/src/SparseCore/SparseColEtree.h diff --git a/xs/src/eigen/Eigen/src/SparseCore/SparseCompressedBase.h b/src/eigen/Eigen/src/SparseCore/SparseCompressedBase.h similarity index 100% rename from xs/src/eigen/Eigen/src/SparseCore/SparseCompressedBase.h rename to src/eigen/Eigen/src/SparseCore/SparseCompressedBase.h diff --git a/xs/src/eigen/Eigen/src/SparseCore/SparseCwiseBinaryOp.h b/src/eigen/Eigen/src/SparseCore/SparseCwiseBinaryOp.h similarity index 100% rename from xs/src/eigen/Eigen/src/SparseCore/SparseCwiseBinaryOp.h rename to src/eigen/Eigen/src/SparseCore/SparseCwiseBinaryOp.h diff --git a/xs/src/eigen/Eigen/src/SparseCore/SparseCwiseUnaryOp.h b/src/eigen/Eigen/src/SparseCore/SparseCwiseUnaryOp.h similarity index 100% rename from xs/src/eigen/Eigen/src/SparseCore/SparseCwiseUnaryOp.h rename to src/eigen/Eigen/src/SparseCore/SparseCwiseUnaryOp.h diff --git a/xs/src/eigen/Eigen/src/SparseCore/SparseDenseProduct.h b/src/eigen/Eigen/src/SparseCore/SparseDenseProduct.h similarity index 100% rename from xs/src/eigen/Eigen/src/SparseCore/SparseDenseProduct.h rename to src/eigen/Eigen/src/SparseCore/SparseDenseProduct.h diff --git a/xs/src/eigen/Eigen/src/SparseCore/SparseDiagonalProduct.h b/src/eigen/Eigen/src/SparseCore/SparseDiagonalProduct.h similarity index 100% rename from xs/src/eigen/Eigen/src/SparseCore/SparseDiagonalProduct.h rename to src/eigen/Eigen/src/SparseCore/SparseDiagonalProduct.h diff --git a/xs/src/eigen/Eigen/src/SparseCore/SparseDot.h b/src/eigen/Eigen/src/SparseCore/SparseDot.h similarity index 100% rename from xs/src/eigen/Eigen/src/SparseCore/SparseDot.h rename to src/eigen/Eigen/src/SparseCore/SparseDot.h diff --git a/xs/src/eigen/Eigen/src/SparseCore/SparseFuzzy.h b/src/eigen/Eigen/src/SparseCore/SparseFuzzy.h similarity index 100% rename from xs/src/eigen/Eigen/src/SparseCore/SparseFuzzy.h rename to src/eigen/Eigen/src/SparseCore/SparseFuzzy.h diff --git a/xs/src/eigen/Eigen/src/SparseCore/SparseMap.h b/src/eigen/Eigen/src/SparseCore/SparseMap.h similarity index 100% rename from xs/src/eigen/Eigen/src/SparseCore/SparseMap.h rename to src/eigen/Eigen/src/SparseCore/SparseMap.h diff --git a/xs/src/eigen/Eigen/src/SparseCore/SparseMatrix.h b/src/eigen/Eigen/src/SparseCore/SparseMatrix.h similarity index 100% rename from xs/src/eigen/Eigen/src/SparseCore/SparseMatrix.h rename to src/eigen/Eigen/src/SparseCore/SparseMatrix.h diff --git a/xs/src/eigen/Eigen/src/SparseCore/SparseMatrixBase.h b/src/eigen/Eigen/src/SparseCore/SparseMatrixBase.h similarity index 100% rename from xs/src/eigen/Eigen/src/SparseCore/SparseMatrixBase.h rename to src/eigen/Eigen/src/SparseCore/SparseMatrixBase.h diff --git a/xs/src/eigen/Eigen/src/SparseCore/SparsePermutation.h b/src/eigen/Eigen/src/SparseCore/SparsePermutation.h similarity index 100% rename from xs/src/eigen/Eigen/src/SparseCore/SparsePermutation.h rename to src/eigen/Eigen/src/SparseCore/SparsePermutation.h diff --git a/xs/src/eigen/Eigen/src/SparseCore/SparseProduct.h b/src/eigen/Eigen/src/SparseCore/SparseProduct.h similarity index 100% rename from xs/src/eigen/Eigen/src/SparseCore/SparseProduct.h rename to src/eigen/Eigen/src/SparseCore/SparseProduct.h diff --git a/xs/src/eigen/Eigen/src/SparseCore/SparseRedux.h b/src/eigen/Eigen/src/SparseCore/SparseRedux.h similarity index 100% rename from xs/src/eigen/Eigen/src/SparseCore/SparseRedux.h rename to src/eigen/Eigen/src/SparseCore/SparseRedux.h diff --git a/xs/src/eigen/Eigen/src/SparseCore/SparseRef.h b/src/eigen/Eigen/src/SparseCore/SparseRef.h similarity index 100% rename from xs/src/eigen/Eigen/src/SparseCore/SparseRef.h rename to src/eigen/Eigen/src/SparseCore/SparseRef.h diff --git a/xs/src/eigen/Eigen/src/SparseCore/SparseSelfAdjointView.h b/src/eigen/Eigen/src/SparseCore/SparseSelfAdjointView.h similarity index 100% rename from xs/src/eigen/Eigen/src/SparseCore/SparseSelfAdjointView.h rename to src/eigen/Eigen/src/SparseCore/SparseSelfAdjointView.h diff --git a/xs/src/eigen/Eigen/src/SparseCore/SparseSolverBase.h b/src/eigen/Eigen/src/SparseCore/SparseSolverBase.h similarity index 100% rename from xs/src/eigen/Eigen/src/SparseCore/SparseSolverBase.h rename to src/eigen/Eigen/src/SparseCore/SparseSolverBase.h diff --git a/xs/src/eigen/Eigen/src/SparseCore/SparseSparseProductWithPruning.h b/src/eigen/Eigen/src/SparseCore/SparseSparseProductWithPruning.h similarity index 100% rename from xs/src/eigen/Eigen/src/SparseCore/SparseSparseProductWithPruning.h rename to src/eigen/Eigen/src/SparseCore/SparseSparseProductWithPruning.h diff --git a/xs/src/eigen/Eigen/src/SparseCore/SparseTranspose.h b/src/eigen/Eigen/src/SparseCore/SparseTranspose.h similarity index 100% rename from xs/src/eigen/Eigen/src/SparseCore/SparseTranspose.h rename to src/eigen/Eigen/src/SparseCore/SparseTranspose.h diff --git a/xs/src/eigen/Eigen/src/SparseCore/SparseTriangularView.h b/src/eigen/Eigen/src/SparseCore/SparseTriangularView.h similarity index 100% rename from xs/src/eigen/Eigen/src/SparseCore/SparseTriangularView.h rename to src/eigen/Eigen/src/SparseCore/SparseTriangularView.h diff --git a/xs/src/eigen/Eigen/src/SparseCore/SparseUtil.h b/src/eigen/Eigen/src/SparseCore/SparseUtil.h similarity index 100% rename from xs/src/eigen/Eigen/src/SparseCore/SparseUtil.h rename to src/eigen/Eigen/src/SparseCore/SparseUtil.h diff --git a/xs/src/eigen/Eigen/src/SparseCore/SparseVector.h b/src/eigen/Eigen/src/SparseCore/SparseVector.h similarity index 100% rename from xs/src/eigen/Eigen/src/SparseCore/SparseVector.h rename to src/eigen/Eigen/src/SparseCore/SparseVector.h diff --git a/xs/src/eigen/Eigen/src/SparseCore/SparseView.h b/src/eigen/Eigen/src/SparseCore/SparseView.h similarity index 100% rename from xs/src/eigen/Eigen/src/SparseCore/SparseView.h rename to src/eigen/Eigen/src/SparseCore/SparseView.h diff --git a/xs/src/eigen/Eigen/src/SparseCore/TriangularSolver.h b/src/eigen/Eigen/src/SparseCore/TriangularSolver.h similarity index 100% rename from xs/src/eigen/Eigen/src/SparseCore/TriangularSolver.h rename to src/eigen/Eigen/src/SparseCore/TriangularSolver.h diff --git a/xs/src/eigen/Eigen/src/SparseLU/SparseLU.h b/src/eigen/Eigen/src/SparseLU/SparseLU.h similarity index 100% rename from xs/src/eigen/Eigen/src/SparseLU/SparseLU.h rename to src/eigen/Eigen/src/SparseLU/SparseLU.h diff --git a/xs/src/eigen/Eigen/src/SparseLU/SparseLUImpl.h b/src/eigen/Eigen/src/SparseLU/SparseLUImpl.h similarity index 100% rename from xs/src/eigen/Eigen/src/SparseLU/SparseLUImpl.h rename to src/eigen/Eigen/src/SparseLU/SparseLUImpl.h diff --git a/xs/src/eigen/Eigen/src/SparseLU/SparseLU_Memory.h b/src/eigen/Eigen/src/SparseLU/SparseLU_Memory.h similarity index 100% rename from xs/src/eigen/Eigen/src/SparseLU/SparseLU_Memory.h rename to src/eigen/Eigen/src/SparseLU/SparseLU_Memory.h diff --git a/xs/src/eigen/Eigen/src/SparseLU/SparseLU_Structs.h b/src/eigen/Eigen/src/SparseLU/SparseLU_Structs.h similarity index 100% rename from xs/src/eigen/Eigen/src/SparseLU/SparseLU_Structs.h rename to src/eigen/Eigen/src/SparseLU/SparseLU_Structs.h diff --git a/xs/src/eigen/Eigen/src/SparseLU/SparseLU_SupernodalMatrix.h b/src/eigen/Eigen/src/SparseLU/SparseLU_SupernodalMatrix.h similarity index 100% rename from xs/src/eigen/Eigen/src/SparseLU/SparseLU_SupernodalMatrix.h rename to src/eigen/Eigen/src/SparseLU/SparseLU_SupernodalMatrix.h diff --git a/xs/src/eigen/Eigen/src/SparseLU/SparseLU_Utils.h b/src/eigen/Eigen/src/SparseLU/SparseLU_Utils.h similarity index 100% rename from xs/src/eigen/Eigen/src/SparseLU/SparseLU_Utils.h rename to src/eigen/Eigen/src/SparseLU/SparseLU_Utils.h diff --git a/xs/src/eigen/Eigen/src/SparseLU/SparseLU_column_bmod.h b/src/eigen/Eigen/src/SparseLU/SparseLU_column_bmod.h similarity index 100% rename from xs/src/eigen/Eigen/src/SparseLU/SparseLU_column_bmod.h rename to src/eigen/Eigen/src/SparseLU/SparseLU_column_bmod.h diff --git a/xs/src/eigen/Eigen/src/SparseLU/SparseLU_column_dfs.h b/src/eigen/Eigen/src/SparseLU/SparseLU_column_dfs.h similarity index 100% rename from xs/src/eigen/Eigen/src/SparseLU/SparseLU_column_dfs.h rename to src/eigen/Eigen/src/SparseLU/SparseLU_column_dfs.h diff --git a/xs/src/eigen/Eigen/src/SparseLU/SparseLU_copy_to_ucol.h b/src/eigen/Eigen/src/SparseLU/SparseLU_copy_to_ucol.h similarity index 100% rename from xs/src/eigen/Eigen/src/SparseLU/SparseLU_copy_to_ucol.h rename to src/eigen/Eigen/src/SparseLU/SparseLU_copy_to_ucol.h diff --git a/xs/src/eigen/Eigen/src/SparseLU/SparseLU_gemm_kernel.h b/src/eigen/Eigen/src/SparseLU/SparseLU_gemm_kernel.h similarity index 100% rename from xs/src/eigen/Eigen/src/SparseLU/SparseLU_gemm_kernel.h rename to src/eigen/Eigen/src/SparseLU/SparseLU_gemm_kernel.h diff --git a/xs/src/eigen/Eigen/src/SparseLU/SparseLU_heap_relax_snode.h b/src/eigen/Eigen/src/SparseLU/SparseLU_heap_relax_snode.h similarity index 100% rename from xs/src/eigen/Eigen/src/SparseLU/SparseLU_heap_relax_snode.h rename to src/eigen/Eigen/src/SparseLU/SparseLU_heap_relax_snode.h diff --git a/xs/src/eigen/Eigen/src/SparseLU/SparseLU_kernel_bmod.h b/src/eigen/Eigen/src/SparseLU/SparseLU_kernel_bmod.h similarity index 100% rename from xs/src/eigen/Eigen/src/SparseLU/SparseLU_kernel_bmod.h rename to src/eigen/Eigen/src/SparseLU/SparseLU_kernel_bmod.h diff --git a/xs/src/eigen/Eigen/src/SparseLU/SparseLU_panel_bmod.h b/src/eigen/Eigen/src/SparseLU/SparseLU_panel_bmod.h similarity index 100% rename from xs/src/eigen/Eigen/src/SparseLU/SparseLU_panel_bmod.h rename to src/eigen/Eigen/src/SparseLU/SparseLU_panel_bmod.h diff --git a/xs/src/eigen/Eigen/src/SparseLU/SparseLU_panel_dfs.h b/src/eigen/Eigen/src/SparseLU/SparseLU_panel_dfs.h similarity index 100% rename from xs/src/eigen/Eigen/src/SparseLU/SparseLU_panel_dfs.h rename to src/eigen/Eigen/src/SparseLU/SparseLU_panel_dfs.h diff --git a/xs/src/eigen/Eigen/src/SparseLU/SparseLU_pivotL.h b/src/eigen/Eigen/src/SparseLU/SparseLU_pivotL.h similarity index 100% rename from xs/src/eigen/Eigen/src/SparseLU/SparseLU_pivotL.h rename to src/eigen/Eigen/src/SparseLU/SparseLU_pivotL.h diff --git a/xs/src/eigen/Eigen/src/SparseLU/SparseLU_pruneL.h b/src/eigen/Eigen/src/SparseLU/SparseLU_pruneL.h similarity index 100% rename from xs/src/eigen/Eigen/src/SparseLU/SparseLU_pruneL.h rename to src/eigen/Eigen/src/SparseLU/SparseLU_pruneL.h diff --git a/xs/src/eigen/Eigen/src/SparseLU/SparseLU_relax_snode.h b/src/eigen/Eigen/src/SparseLU/SparseLU_relax_snode.h similarity index 100% rename from xs/src/eigen/Eigen/src/SparseLU/SparseLU_relax_snode.h rename to src/eigen/Eigen/src/SparseLU/SparseLU_relax_snode.h diff --git a/xs/src/eigen/Eigen/src/SparseQR/SparseQR.h b/src/eigen/Eigen/src/SparseQR/SparseQR.h similarity index 100% rename from xs/src/eigen/Eigen/src/SparseQR/SparseQR.h rename to src/eigen/Eigen/src/SparseQR/SparseQR.h diff --git a/xs/src/eigen/Eigen/src/StlSupport/StdDeque.h b/src/eigen/Eigen/src/StlSupport/StdDeque.h similarity index 100% rename from xs/src/eigen/Eigen/src/StlSupport/StdDeque.h rename to src/eigen/Eigen/src/StlSupport/StdDeque.h diff --git a/xs/src/eigen/Eigen/src/StlSupport/StdList.h b/src/eigen/Eigen/src/StlSupport/StdList.h similarity index 100% rename from xs/src/eigen/Eigen/src/StlSupport/StdList.h rename to src/eigen/Eigen/src/StlSupport/StdList.h diff --git a/xs/src/eigen/Eigen/src/StlSupport/StdVector.h b/src/eigen/Eigen/src/StlSupport/StdVector.h similarity index 100% rename from xs/src/eigen/Eigen/src/StlSupport/StdVector.h rename to src/eigen/Eigen/src/StlSupport/StdVector.h diff --git a/xs/src/eigen/Eigen/src/StlSupport/details.h b/src/eigen/Eigen/src/StlSupport/details.h similarity index 100% rename from xs/src/eigen/Eigen/src/StlSupport/details.h rename to src/eigen/Eigen/src/StlSupport/details.h diff --git a/xs/src/eigen/Eigen/src/SuperLUSupport/SuperLUSupport.h b/src/eigen/Eigen/src/SuperLUSupport/SuperLUSupport.h similarity index 100% rename from xs/src/eigen/Eigen/src/SuperLUSupport/SuperLUSupport.h rename to src/eigen/Eigen/src/SuperLUSupport/SuperLUSupport.h diff --git a/xs/src/eigen/Eigen/src/UmfPackSupport/UmfPackSupport.h b/src/eigen/Eigen/src/UmfPackSupport/UmfPackSupport.h similarity index 100% rename from xs/src/eigen/Eigen/src/UmfPackSupport/UmfPackSupport.h rename to src/eigen/Eigen/src/UmfPackSupport/UmfPackSupport.h diff --git a/xs/src/eigen/Eigen/src/misc/Image.h b/src/eigen/Eigen/src/misc/Image.h similarity index 100% rename from xs/src/eigen/Eigen/src/misc/Image.h rename to src/eigen/Eigen/src/misc/Image.h diff --git a/xs/src/eigen/Eigen/src/misc/Kernel.h b/src/eigen/Eigen/src/misc/Kernel.h similarity index 100% rename from xs/src/eigen/Eigen/src/misc/Kernel.h rename to src/eigen/Eigen/src/misc/Kernel.h diff --git a/xs/src/eigen/Eigen/src/misc/RealSvd2x2.h b/src/eigen/Eigen/src/misc/RealSvd2x2.h similarity index 100% rename from xs/src/eigen/Eigen/src/misc/RealSvd2x2.h rename to src/eigen/Eigen/src/misc/RealSvd2x2.h diff --git a/xs/src/eigen/Eigen/src/misc/blas.h b/src/eigen/Eigen/src/misc/blas.h similarity index 100% rename from xs/src/eigen/Eigen/src/misc/blas.h rename to src/eigen/Eigen/src/misc/blas.h diff --git a/xs/src/eigen/Eigen/src/misc/lapack.h b/src/eigen/Eigen/src/misc/lapack.h similarity index 100% rename from xs/src/eigen/Eigen/src/misc/lapack.h rename to src/eigen/Eigen/src/misc/lapack.h diff --git a/xs/src/eigen/Eigen/src/misc/lapacke.h b/src/eigen/Eigen/src/misc/lapacke.h similarity index 100% rename from xs/src/eigen/Eigen/src/misc/lapacke.h rename to src/eigen/Eigen/src/misc/lapacke.h diff --git a/xs/src/eigen/Eigen/src/misc/lapacke_mangling.h b/src/eigen/Eigen/src/misc/lapacke_mangling.h similarity index 100% rename from xs/src/eigen/Eigen/src/misc/lapacke_mangling.h rename to src/eigen/Eigen/src/misc/lapacke_mangling.h diff --git a/xs/src/eigen/Eigen/src/plugins/ArrayCwiseBinaryOps.h b/src/eigen/Eigen/src/plugins/ArrayCwiseBinaryOps.h similarity index 100% rename from xs/src/eigen/Eigen/src/plugins/ArrayCwiseBinaryOps.h rename to src/eigen/Eigen/src/plugins/ArrayCwiseBinaryOps.h diff --git a/xs/src/eigen/Eigen/src/plugins/ArrayCwiseUnaryOps.h b/src/eigen/Eigen/src/plugins/ArrayCwiseUnaryOps.h similarity index 100% rename from xs/src/eigen/Eigen/src/plugins/ArrayCwiseUnaryOps.h rename to src/eigen/Eigen/src/plugins/ArrayCwiseUnaryOps.h diff --git a/xs/src/eigen/Eigen/src/plugins/BlockMethods.h b/src/eigen/Eigen/src/plugins/BlockMethods.h similarity index 100% rename from xs/src/eigen/Eigen/src/plugins/BlockMethods.h rename to src/eigen/Eigen/src/plugins/BlockMethods.h diff --git a/xs/src/eigen/Eigen/src/plugins/CommonCwiseBinaryOps.h b/src/eigen/Eigen/src/plugins/CommonCwiseBinaryOps.h similarity index 100% rename from xs/src/eigen/Eigen/src/plugins/CommonCwiseBinaryOps.h rename to src/eigen/Eigen/src/plugins/CommonCwiseBinaryOps.h diff --git a/xs/src/eigen/Eigen/src/plugins/CommonCwiseUnaryOps.h b/src/eigen/Eigen/src/plugins/CommonCwiseUnaryOps.h similarity index 100% rename from xs/src/eigen/Eigen/src/plugins/CommonCwiseUnaryOps.h rename to src/eigen/Eigen/src/plugins/CommonCwiseUnaryOps.h diff --git a/xs/src/eigen/Eigen/src/plugins/MatrixCwiseBinaryOps.h b/src/eigen/Eigen/src/plugins/MatrixCwiseBinaryOps.h similarity index 100% rename from xs/src/eigen/Eigen/src/plugins/MatrixCwiseBinaryOps.h rename to src/eigen/Eigen/src/plugins/MatrixCwiseBinaryOps.h diff --git a/xs/src/eigen/Eigen/src/plugins/MatrixCwiseUnaryOps.h b/src/eigen/Eigen/src/plugins/MatrixCwiseUnaryOps.h similarity index 100% rename from xs/src/eigen/Eigen/src/plugins/MatrixCwiseUnaryOps.h rename to src/eigen/Eigen/src/plugins/MatrixCwiseUnaryOps.h diff --git a/xs/src/eigen/README.md b/src/eigen/README.md similarity index 100% rename from xs/src/eigen/README.md rename to src/eigen/README.md diff --git a/xs/src/expat/COPYING b/src/expat/COPYING similarity index 100% rename from xs/src/expat/COPYING rename to src/expat/COPYING diff --git a/xs/src/expat/README b/src/expat/README similarity index 100% rename from xs/src/expat/README rename to src/expat/README diff --git a/xs/src/expat/ascii.h b/src/expat/ascii.h similarity index 100% rename from xs/src/expat/ascii.h rename to src/expat/ascii.h diff --git a/xs/src/expat/asciitab.h b/src/expat/asciitab.h similarity index 100% rename from xs/src/expat/asciitab.h rename to src/expat/asciitab.h diff --git a/xs/src/expat/expat.h b/src/expat/expat.h similarity index 100% rename from xs/src/expat/expat.h rename to src/expat/expat.h diff --git a/xs/src/expat/expat_config.h b/src/expat/expat_config.h similarity index 100% rename from xs/src/expat/expat_config.h rename to src/expat/expat_config.h diff --git a/xs/src/expat/expat_external.h b/src/expat/expat_external.h similarity index 100% rename from xs/src/expat/expat_external.h rename to src/expat/expat_external.h diff --git a/xs/src/expat/iasciitab.h b/src/expat/iasciitab.h similarity index 100% rename from xs/src/expat/iasciitab.h rename to src/expat/iasciitab.h diff --git a/xs/src/expat/internal.h b/src/expat/internal.h similarity index 100% rename from xs/src/expat/internal.h rename to src/expat/internal.h diff --git a/xs/src/expat/latin1tab.h b/src/expat/latin1tab.h similarity index 100% rename from xs/src/expat/latin1tab.h rename to src/expat/latin1tab.h diff --git a/xs/src/expat/nametab.h b/src/expat/nametab.h similarity index 100% rename from xs/src/expat/nametab.h rename to src/expat/nametab.h diff --git a/xs/src/expat/utf8tab.h b/src/expat/utf8tab.h similarity index 100% rename from xs/src/expat/utf8tab.h rename to src/expat/utf8tab.h diff --git a/xs/src/expat/xmlparse.c b/src/expat/xmlparse.c similarity index 100% rename from xs/src/expat/xmlparse.c rename to src/expat/xmlparse.c diff --git a/xs/src/expat/xmlrole.c b/src/expat/xmlrole.c similarity index 100% rename from xs/src/expat/xmlrole.c rename to src/expat/xmlrole.c diff --git a/xs/src/expat/xmlrole.h b/src/expat/xmlrole.h similarity index 100% rename from xs/src/expat/xmlrole.h rename to src/expat/xmlrole.h diff --git a/xs/src/expat/xmltok.c b/src/expat/xmltok.c similarity index 100% rename from xs/src/expat/xmltok.c rename to src/expat/xmltok.c diff --git a/xs/src/expat/xmltok.h b/src/expat/xmltok.h similarity index 100% rename from xs/src/expat/xmltok.h rename to src/expat/xmltok.h diff --git a/xs/src/expat/xmltok_impl.h b/src/expat/xmltok_impl.h similarity index 100% rename from xs/src/expat/xmltok_impl.h rename to src/expat/xmltok_impl.h diff --git a/xs/src/expat/xmltok_impl.inc b/src/expat/xmltok_impl.inc similarity index 100% rename from xs/src/expat/xmltok_impl.inc rename to src/expat/xmltok_impl.inc diff --git a/xs/src/expat/xmltok_ns.inc b/src/expat/xmltok_ns.inc similarity index 100% rename from xs/src/expat/xmltok_ns.inc rename to src/expat/xmltok_ns.inc diff --git a/xs/src/glew/LICENSE.txt b/src/glew/LICENSE.txt similarity index 100% rename from xs/src/glew/LICENSE.txt rename to src/glew/LICENSE.txt diff --git a/xs/src/glew/README.md b/src/glew/README.md similarity index 100% rename from xs/src/glew/README.md rename to src/glew/README.md diff --git a/xs/src/glew/include/GL/glew.h b/src/glew/include/GL/glew.h similarity index 100% rename from xs/src/glew/include/GL/glew.h rename to src/glew/include/GL/glew.h diff --git a/xs/src/glew/include/GL/glxew.h b/src/glew/include/GL/glxew.h similarity index 100% rename from xs/src/glew/include/GL/glxew.h rename to src/glew/include/GL/glxew.h diff --git a/xs/src/glew/include/GL/wglew.h b/src/glew/include/GL/wglew.h similarity index 100% rename from xs/src/glew/include/GL/wglew.h rename to src/glew/include/GL/wglew.h diff --git a/xs/src/glew/src/glew.c b/src/glew/src/glew.c similarity index 100% rename from xs/src/glew/src/glew.c rename to src/glew/src/glew.c diff --git a/xs/src/libnest2d/CMakeLists.txt b/src/libnest2d/CMakeLists.txt similarity index 100% rename from xs/src/libnest2d/CMakeLists.txt rename to src/libnest2d/CMakeLists.txt diff --git a/xs/src/libnest2d/LICENSE.txt b/src/libnest2d/LICENSE.txt similarity index 100% rename from xs/src/libnest2d/LICENSE.txt rename to src/libnest2d/LICENSE.txt diff --git a/xs/src/libnest2d/README.md b/src/libnest2d/README.md similarity index 100% rename from xs/src/libnest2d/README.md rename to src/libnest2d/README.md diff --git a/xs/src/libnest2d/cmake_modules/DownloadNLopt.cmake b/src/libnest2d/cmake_modules/DownloadNLopt.cmake similarity index 100% rename from xs/src/libnest2d/cmake_modules/DownloadNLopt.cmake rename to src/libnest2d/cmake_modules/DownloadNLopt.cmake diff --git a/xs/src/libnest2d/cmake_modules/DownloadProject.CMakeLists.cmake.in b/src/libnest2d/cmake_modules/DownloadProject.CMakeLists.cmake.in similarity index 100% rename from xs/src/libnest2d/cmake_modules/DownloadProject.CMakeLists.cmake.in rename to src/libnest2d/cmake_modules/DownloadProject.CMakeLists.cmake.in diff --git a/xs/src/libnest2d/cmake_modules/DownloadProject.cmake b/src/libnest2d/cmake_modules/DownloadProject.cmake similarity index 100% rename from xs/src/libnest2d/cmake_modules/DownloadProject.cmake rename to src/libnest2d/cmake_modules/DownloadProject.cmake diff --git a/xs/src/libnest2d/cmake_modules/FindClipper.cmake b/src/libnest2d/cmake_modules/FindClipper.cmake similarity index 100% rename from xs/src/libnest2d/cmake_modules/FindClipper.cmake rename to src/libnest2d/cmake_modules/FindClipper.cmake diff --git a/xs/src/libnest2d/cmake_modules/FindNLopt.cmake b/src/libnest2d/cmake_modules/FindNLopt.cmake similarity index 100% rename from xs/src/libnest2d/cmake_modules/FindNLopt.cmake rename to src/libnest2d/cmake_modules/FindNLopt.cmake diff --git a/xs/src/libnest2d/cmake_modules/FindTBB.cmake b/src/libnest2d/cmake_modules/FindTBB.cmake similarity index 100% rename from xs/src/libnest2d/cmake_modules/FindTBB.cmake rename to src/libnest2d/cmake_modules/FindTBB.cmake diff --git a/xs/src/libnest2d/examples/main.cpp b/src/libnest2d/examples/main.cpp similarity index 100% rename from xs/src/libnest2d/examples/main.cpp rename to src/libnest2d/examples/main.cpp diff --git a/xs/src/libnest2d/libnest2d.h b/src/libnest2d/libnest2d.h similarity index 100% rename from xs/src/libnest2d/libnest2d.h rename to src/libnest2d/libnest2d.h diff --git a/xs/src/libnest2d/libnest2d/boost_alg.hpp b/src/libnest2d/libnest2d/boost_alg.hpp similarity index 100% rename from xs/src/libnest2d/libnest2d/boost_alg.hpp rename to src/libnest2d/libnest2d/boost_alg.hpp diff --git a/xs/src/libnest2d/libnest2d/clipper_backend/CMakeLists.txt b/src/libnest2d/libnest2d/clipper_backend/CMakeLists.txt similarity index 100% rename from xs/src/libnest2d/libnest2d/clipper_backend/CMakeLists.txt rename to src/libnest2d/libnest2d/clipper_backend/CMakeLists.txt diff --git a/xs/src/libnest2d/libnest2d/clipper_backend/clipper_backend.hpp b/src/libnest2d/libnest2d/clipper_backend/clipper_backend.hpp similarity index 100% rename from xs/src/libnest2d/libnest2d/clipper_backend/clipper_backend.hpp rename to src/libnest2d/libnest2d/clipper_backend/clipper_backend.hpp diff --git a/xs/src/libnest2d/libnest2d/common.hpp b/src/libnest2d/libnest2d/common.hpp similarity index 100% rename from xs/src/libnest2d/libnest2d/common.hpp rename to src/libnest2d/libnest2d/common.hpp diff --git a/xs/src/libnest2d/libnest2d/geometry_traits.hpp b/src/libnest2d/libnest2d/geometry_traits.hpp similarity index 100% rename from xs/src/libnest2d/libnest2d/geometry_traits.hpp rename to src/libnest2d/libnest2d/geometry_traits.hpp diff --git a/xs/src/libnest2d/libnest2d/geometry_traits_nfp.hpp b/src/libnest2d/libnest2d/geometry_traits_nfp.hpp similarity index 100% rename from xs/src/libnest2d/libnest2d/geometry_traits_nfp.hpp rename to src/libnest2d/libnest2d/geometry_traits_nfp.hpp diff --git a/xs/src/libnest2d/libnest2d/libnest2d.hpp b/src/libnest2d/libnest2d/libnest2d.hpp similarity index 100% rename from xs/src/libnest2d/libnest2d/libnest2d.hpp rename to src/libnest2d/libnest2d/libnest2d.hpp diff --git a/xs/src/libnest2d/libnest2d/metaloop.hpp b/src/libnest2d/libnest2d/metaloop.hpp similarity index 100% rename from xs/src/libnest2d/libnest2d/metaloop.hpp rename to src/libnest2d/libnest2d/metaloop.hpp diff --git a/xs/src/libnest2d/libnest2d/optimizer.hpp b/src/libnest2d/libnest2d/optimizer.hpp similarity index 100% rename from xs/src/libnest2d/libnest2d/optimizer.hpp rename to src/libnest2d/libnest2d/optimizer.hpp diff --git a/xs/src/libnest2d/libnest2d/optimizers/genetic.hpp b/src/libnest2d/libnest2d/optimizers/genetic.hpp similarity index 100% rename from xs/src/libnest2d/libnest2d/optimizers/genetic.hpp rename to src/libnest2d/libnest2d/optimizers/genetic.hpp diff --git a/xs/src/libnest2d/libnest2d/optimizers/nlopt_boilerplate.hpp b/src/libnest2d/libnest2d/optimizers/nlopt_boilerplate.hpp similarity index 100% rename from xs/src/libnest2d/libnest2d/optimizers/nlopt_boilerplate.hpp rename to src/libnest2d/libnest2d/optimizers/nlopt_boilerplate.hpp diff --git a/xs/src/libnest2d/libnest2d/optimizers/simplex.hpp b/src/libnest2d/libnest2d/optimizers/simplex.hpp similarity index 100% rename from xs/src/libnest2d/libnest2d/optimizers/simplex.hpp rename to src/libnest2d/libnest2d/optimizers/simplex.hpp diff --git a/xs/src/libnest2d/libnest2d/optimizers/subplex.hpp b/src/libnest2d/libnest2d/optimizers/subplex.hpp similarity index 100% rename from xs/src/libnest2d/libnest2d/optimizers/subplex.hpp rename to src/libnest2d/libnest2d/optimizers/subplex.hpp diff --git a/xs/src/libnest2d/libnest2d/placers/bottomleftplacer.hpp b/src/libnest2d/libnest2d/placers/bottomleftplacer.hpp similarity index 100% rename from xs/src/libnest2d/libnest2d/placers/bottomleftplacer.hpp rename to src/libnest2d/libnest2d/placers/bottomleftplacer.hpp diff --git a/xs/src/libnest2d/libnest2d/placers/nfpplacer.hpp b/src/libnest2d/libnest2d/placers/nfpplacer.hpp similarity index 100% rename from xs/src/libnest2d/libnest2d/placers/nfpplacer.hpp rename to src/libnest2d/libnest2d/placers/nfpplacer.hpp diff --git a/xs/src/libnest2d/libnest2d/placers/placer_boilerplate.hpp b/src/libnest2d/libnest2d/placers/placer_boilerplate.hpp similarity index 100% rename from xs/src/libnest2d/libnest2d/placers/placer_boilerplate.hpp rename to src/libnest2d/libnest2d/placers/placer_boilerplate.hpp diff --git a/xs/src/libnest2d/libnest2d/rotfinder.hpp b/src/libnest2d/libnest2d/rotfinder.hpp similarity index 100% rename from xs/src/libnest2d/libnest2d/rotfinder.hpp rename to src/libnest2d/libnest2d/rotfinder.hpp diff --git a/xs/src/libnest2d/libnest2d/selections/djd_heuristic.hpp b/src/libnest2d/libnest2d/selections/djd_heuristic.hpp similarity index 100% rename from xs/src/libnest2d/libnest2d/selections/djd_heuristic.hpp rename to src/libnest2d/libnest2d/selections/djd_heuristic.hpp diff --git a/xs/src/libnest2d/libnest2d/selections/filler.hpp b/src/libnest2d/libnest2d/selections/filler.hpp similarity index 100% rename from xs/src/libnest2d/libnest2d/selections/filler.hpp rename to src/libnest2d/libnest2d/selections/filler.hpp diff --git a/xs/src/libnest2d/libnest2d/selections/firstfit.hpp b/src/libnest2d/libnest2d/selections/firstfit.hpp similarity index 100% rename from xs/src/libnest2d/libnest2d/selections/firstfit.hpp rename to src/libnest2d/libnest2d/selections/firstfit.hpp diff --git a/xs/src/libnest2d/libnest2d/selections/selection_boilerplate.hpp b/src/libnest2d/libnest2d/selections/selection_boilerplate.hpp similarity index 100% rename from xs/src/libnest2d/libnest2d/selections/selection_boilerplate.hpp rename to src/libnest2d/libnest2d/selections/selection_boilerplate.hpp diff --git a/xs/src/libnest2d/tests/CMakeLists.txt b/src/libnest2d/tests/CMakeLists.txt similarity index 100% rename from xs/src/libnest2d/tests/CMakeLists.txt rename to src/libnest2d/tests/CMakeLists.txt diff --git a/xs/src/libnest2d/tests/printer_parts.cpp b/src/libnest2d/tests/printer_parts.cpp similarity index 100% rename from xs/src/libnest2d/tests/printer_parts.cpp rename to src/libnest2d/tests/printer_parts.cpp diff --git a/xs/src/libnest2d/tests/printer_parts.h b/src/libnest2d/tests/printer_parts.h similarity index 100% rename from xs/src/libnest2d/tests/printer_parts.h rename to src/libnest2d/tests/printer_parts.h diff --git a/xs/src/libnest2d/tests/test.cpp b/src/libnest2d/tests/test.cpp similarity index 100% rename from xs/src/libnest2d/tests/test.cpp rename to src/libnest2d/tests/test.cpp diff --git a/xs/src/benchmark.h b/src/libnest2d/tools/benchmark.h similarity index 100% rename from xs/src/benchmark.h rename to src/libnest2d/tools/benchmark.h diff --git a/xs/src/libnest2d/tools/libnfpglue.cpp b/src/libnest2d/tools/libnfpglue.cpp similarity index 100% rename from xs/src/libnest2d/tools/libnfpglue.cpp rename to src/libnest2d/tools/libnfpglue.cpp diff --git a/xs/src/libnest2d/tools/libnfpglue.hpp b/src/libnest2d/tools/libnfpglue.hpp similarity index 100% rename from xs/src/libnest2d/tools/libnfpglue.hpp rename to src/libnest2d/tools/libnfpglue.hpp diff --git a/xs/src/libnest2d/tools/libnfporb/LICENSE b/src/libnest2d/tools/libnfporb/LICENSE similarity index 100% rename from xs/src/libnest2d/tools/libnfporb/LICENSE rename to src/libnest2d/tools/libnfporb/LICENSE diff --git a/xs/src/libnest2d/tools/libnfporb/ORIGIN b/src/libnest2d/tools/libnfporb/ORIGIN similarity index 100% rename from xs/src/libnest2d/tools/libnfporb/ORIGIN rename to src/libnest2d/tools/libnfporb/ORIGIN diff --git a/xs/src/libnest2d/tools/libnfporb/README.md b/src/libnest2d/tools/libnfporb/README.md similarity index 100% rename from xs/src/libnest2d/tools/libnfporb/README.md rename to src/libnest2d/tools/libnfporb/README.md diff --git a/xs/src/libnest2d/tools/libnfporb/libnfporb.hpp b/src/libnest2d/tools/libnfporb/libnfporb.hpp similarity index 100% rename from xs/src/libnest2d/tools/libnfporb/libnfporb.hpp rename to src/libnest2d/tools/libnfporb/libnfporb.hpp diff --git a/xs/src/libnest2d/tools/nfp_svgnest.hpp b/src/libnest2d/tools/nfp_svgnest.hpp similarity index 100% rename from xs/src/libnest2d/tools/nfp_svgnest.hpp rename to src/libnest2d/tools/nfp_svgnest.hpp diff --git a/xs/src/libnest2d/tools/nfp_svgnest_glue.hpp b/src/libnest2d/tools/nfp_svgnest_glue.hpp similarity index 100% rename from xs/src/libnest2d/tools/nfp_svgnest_glue.hpp rename to src/libnest2d/tools/nfp_svgnest_glue.hpp diff --git a/xs/src/libnest2d/tools/svgtools.hpp b/src/libnest2d/tools/svgtools.hpp similarity index 100% rename from xs/src/libnest2d/tools/svgtools.hpp rename to src/libnest2d/tools/svgtools.hpp diff --git a/xs/src/libslic3r/BoundingBox.cpp b/src/libslic3r/BoundingBox.cpp similarity index 100% rename from xs/src/libslic3r/BoundingBox.cpp rename to src/libslic3r/BoundingBox.cpp diff --git a/xs/src/libslic3r/BoundingBox.hpp b/src/libslic3r/BoundingBox.hpp similarity index 100% rename from xs/src/libslic3r/BoundingBox.hpp rename to src/libslic3r/BoundingBox.hpp diff --git a/xs/src/libslic3r/BridgeDetector.cpp b/src/libslic3r/BridgeDetector.cpp similarity index 100% rename from xs/src/libslic3r/BridgeDetector.cpp rename to src/libslic3r/BridgeDetector.cpp diff --git a/xs/src/libslic3r/BridgeDetector.hpp b/src/libslic3r/BridgeDetector.hpp similarity index 100% rename from xs/src/libslic3r/BridgeDetector.hpp rename to src/libslic3r/BridgeDetector.hpp diff --git a/src/libslic3r/CMakeLists.txt b/src/libslic3r/CMakeLists.txt new file mode 100644 index 0000000000..6955dd1e7e --- /dev/null +++ b/src/libslic3r/CMakeLists.txt @@ -0,0 +1,173 @@ +project(libslic3r) +cmake_minimum_required(VERSION 2.6) + +add_library(libslic3r STATIC + BoundingBox.cpp + BoundingBox.hpp + BridgeDetector.cpp + BridgeDetector.hpp + ClipperUtils.cpp + ClipperUtils.hpp + Config.cpp + Config.hpp + EdgeGrid.cpp + EdgeGrid.hpp + ExPolygon.cpp + ExPolygon.hpp + ExPolygonCollection.cpp + ExPolygonCollection.hpp + Extruder.cpp + Extruder.hpp + ExtrusionEntity.cpp + ExtrusionEntity.hpp + ExtrusionEntityCollection.cpp + ExtrusionEntityCollection.hpp + ExtrusionSimulator.cpp + ExtrusionSimulator.hpp + FileParserError.hpp + Fill/Fill.cpp + Fill/Fill.hpp + Fill/Fill3DHoneycomb.cpp + Fill/Fill3DHoneycomb.hpp + Fill/FillBase.cpp + Fill/FillBase.hpp + Fill/FillConcentric.cpp + Fill/FillConcentric.hpp + Fill/FillHoneycomb.cpp + Fill/FillHoneycomb.hpp + Fill/FillGyroid.cpp + Fill/FillGyroid.hpp + Fill/FillPlanePath.cpp + Fill/FillPlanePath.hpp + Fill/FillRectilinear.cpp + Fill/FillRectilinear.hpp + Fill/FillRectilinear2.cpp + Fill/FillRectilinear2.hpp + Fill/FillRectilinear3.cpp + Fill/FillRectilinear3.hpp + Flow.cpp + Flow.hpp + Format/3mf.cpp + Format/3mf.hpp + Format/AMF.cpp + Format/AMF.hpp + Format/OBJ.cpp + Format/OBJ.hpp + Format/objparser.cpp + Format/objparser.hpp + Format/PRUS.cpp + Format/PRUS.hpp + Format/STL.cpp + Format/STL.hpp + GCode/Analyzer.cpp + GCode/Analyzer.hpp + GCode/CoolingBuffer.cpp + GCode/CoolingBuffer.hpp + GCode/PostProcessor.cpp + GCode/PostProcessor.hpp + GCode/PressureEqualizer.cpp + GCode/PressureEqualizer.hpp + GCode/PreviewData.cpp + GCode/PreviewData.hpp + GCode/PrintExtents.cpp + GCode/PrintExtents.hpp + GCode/SpiralVase.cpp + GCode/SpiralVase.hpp + GCode/ToolOrdering.cpp + GCode/ToolOrdering.hpp + GCode/WipeTower.hpp + GCode/WipeTowerPrusaMM.cpp + GCode/WipeTowerPrusaMM.hpp + GCode.cpp + GCode.hpp + GCodeReader.cpp + GCodeReader.hpp + GCodeSender.cpp + GCodeSender.hpp + GCodeTimeEstimator.cpp + GCodeTimeEstimator.hpp + GCodeWriter.cpp + GCodeWriter.hpp + Geometry.cpp + Geometry.hpp + Int128.hpp +# KdTree.hpp + Layer.cpp + Layer.hpp + LayerRegion.cpp + libslic3r.h + Line.cpp + Line.hpp + Model.cpp + Model.hpp + ModelArrange.hpp + MotionPlanner.cpp + MotionPlanner.hpp + MultiPoint.cpp + MultiPoint.hpp + MutablePriorityQueue.hpp + PerimeterGenerator.cpp + PerimeterGenerator.hpp + PlaceholderParser.cpp + PlaceholderParser.hpp + Point.cpp + Point.hpp + Polygon.cpp + Polygon.hpp + Polyline.cpp + Polyline.hpp + PolylineCollection.cpp + PolylineCollection.hpp + Print.cpp + Print.hpp + PrintExport.hpp + PrintConfig.cpp + PrintConfig.hpp + PrintObject.cpp + PrintRegion.cpp + Rasterizer/Rasterizer.hpp + Rasterizer/Rasterizer.cpp + Slicing.cpp + Slicing.hpp + SlicingAdaptive.cpp + SlicingAdaptive.hpp + SupportMaterial.cpp + SupportMaterial.hpp + Surface.cpp + Surface.hpp + SurfaceCollection.cpp + SurfaceCollection.hpp + SVG.cpp + SVG.hpp + Technologies.hpp + TriangleMesh.cpp + TriangleMesh.hpp + SLABasePool.hpp + SLABasePool.cpp + utils.cpp + Utils.hpp +) + +target_compile_definitions(libslic3r PUBLIC -DUSE_TBB ${PNG_DEFINITIONS}) +target_include_directories(libslic3r PUBLIC BEFORE ${LIBNEST2D_INCLUDES} ${PNG_INCLUDE_DIRS}) +target_link_libraries(libslic3r + ${LIBNEST2D_LIBRARIES} + admesh + miniz + ${Boost_LIBRARIES} + clipper + nowide + ${EXPAT_LIBRARIES} + ${GLEW_LIBRARIES} + ${PNG_LIBRARIES} + polypartition + poly2tri + qhull + semver + ${TBB_LIBRARIES} +# ${wxWidgets_LIBRARIES} + ) + +if(SLIC3R_PROFILE) + target_link_libraries(slic3r Shiny) +endif() diff --git a/xs/src/libslic3r/ClipperUtils.cpp b/src/libslic3r/ClipperUtils.cpp similarity index 100% rename from xs/src/libslic3r/ClipperUtils.cpp rename to src/libslic3r/ClipperUtils.cpp diff --git a/xs/src/libslic3r/ClipperUtils.hpp b/src/libslic3r/ClipperUtils.hpp similarity index 100% rename from xs/src/libslic3r/ClipperUtils.hpp rename to src/libslic3r/ClipperUtils.hpp diff --git a/xs/src/libslic3r/Config.cpp b/src/libslic3r/Config.cpp similarity index 100% rename from xs/src/libslic3r/Config.cpp rename to src/libslic3r/Config.cpp diff --git a/xs/src/libslic3r/Config.hpp b/src/libslic3r/Config.hpp similarity index 100% rename from xs/src/libslic3r/Config.hpp rename to src/libslic3r/Config.hpp diff --git a/xs/src/libslic3r/EdgeGrid.cpp b/src/libslic3r/EdgeGrid.cpp similarity index 100% rename from xs/src/libslic3r/EdgeGrid.cpp rename to src/libslic3r/EdgeGrid.cpp diff --git a/xs/src/libslic3r/EdgeGrid.hpp b/src/libslic3r/EdgeGrid.hpp similarity index 100% rename from xs/src/libslic3r/EdgeGrid.hpp rename to src/libslic3r/EdgeGrid.hpp diff --git a/xs/src/libslic3r/ExPolygon.cpp b/src/libslic3r/ExPolygon.cpp similarity index 100% rename from xs/src/libslic3r/ExPolygon.cpp rename to src/libslic3r/ExPolygon.cpp diff --git a/xs/src/libslic3r/ExPolygon.hpp b/src/libslic3r/ExPolygon.hpp similarity index 100% rename from xs/src/libslic3r/ExPolygon.hpp rename to src/libslic3r/ExPolygon.hpp diff --git a/xs/src/libslic3r/ExPolygonCollection.cpp b/src/libslic3r/ExPolygonCollection.cpp similarity index 100% rename from xs/src/libslic3r/ExPolygonCollection.cpp rename to src/libslic3r/ExPolygonCollection.cpp diff --git a/xs/src/libslic3r/ExPolygonCollection.hpp b/src/libslic3r/ExPolygonCollection.hpp similarity index 100% rename from xs/src/libslic3r/ExPolygonCollection.hpp rename to src/libslic3r/ExPolygonCollection.hpp diff --git a/xs/src/libslic3r/Extruder.cpp b/src/libslic3r/Extruder.cpp similarity index 100% rename from xs/src/libslic3r/Extruder.cpp rename to src/libslic3r/Extruder.cpp diff --git a/xs/src/libslic3r/Extruder.hpp b/src/libslic3r/Extruder.hpp similarity index 100% rename from xs/src/libslic3r/Extruder.hpp rename to src/libslic3r/Extruder.hpp diff --git a/xs/src/libslic3r/ExtrusionEntity.cpp b/src/libslic3r/ExtrusionEntity.cpp similarity index 100% rename from xs/src/libslic3r/ExtrusionEntity.cpp rename to src/libslic3r/ExtrusionEntity.cpp diff --git a/xs/src/libslic3r/ExtrusionEntity.hpp b/src/libslic3r/ExtrusionEntity.hpp similarity index 100% rename from xs/src/libslic3r/ExtrusionEntity.hpp rename to src/libslic3r/ExtrusionEntity.hpp diff --git a/xs/src/libslic3r/ExtrusionEntityCollection.cpp b/src/libslic3r/ExtrusionEntityCollection.cpp similarity index 100% rename from xs/src/libslic3r/ExtrusionEntityCollection.cpp rename to src/libslic3r/ExtrusionEntityCollection.cpp diff --git a/xs/src/libslic3r/ExtrusionEntityCollection.hpp b/src/libslic3r/ExtrusionEntityCollection.hpp similarity index 100% rename from xs/src/libslic3r/ExtrusionEntityCollection.hpp rename to src/libslic3r/ExtrusionEntityCollection.hpp diff --git a/xs/src/libslic3r/ExtrusionSimulator.cpp b/src/libslic3r/ExtrusionSimulator.cpp similarity index 100% rename from xs/src/libslic3r/ExtrusionSimulator.cpp rename to src/libslic3r/ExtrusionSimulator.cpp diff --git a/xs/src/libslic3r/ExtrusionSimulator.hpp b/src/libslic3r/ExtrusionSimulator.hpp similarity index 100% rename from xs/src/libslic3r/ExtrusionSimulator.hpp rename to src/libslic3r/ExtrusionSimulator.hpp diff --git a/xs/src/libslic3r/FileParserError.hpp b/src/libslic3r/FileParserError.hpp similarity index 100% rename from xs/src/libslic3r/FileParserError.hpp rename to src/libslic3r/FileParserError.hpp diff --git a/xs/src/libslic3r/Fill/Fill.cpp b/src/libslic3r/Fill/Fill.cpp similarity index 100% rename from xs/src/libslic3r/Fill/Fill.cpp rename to src/libslic3r/Fill/Fill.cpp diff --git a/xs/src/libslic3r/Fill/Fill.hpp b/src/libslic3r/Fill/Fill.hpp similarity index 100% rename from xs/src/libslic3r/Fill/Fill.hpp rename to src/libslic3r/Fill/Fill.hpp diff --git a/xs/src/libslic3r/Fill/Fill3DHoneycomb.cpp b/src/libslic3r/Fill/Fill3DHoneycomb.cpp similarity index 100% rename from xs/src/libslic3r/Fill/Fill3DHoneycomb.cpp rename to src/libslic3r/Fill/Fill3DHoneycomb.cpp diff --git a/xs/src/libslic3r/Fill/Fill3DHoneycomb.hpp b/src/libslic3r/Fill/Fill3DHoneycomb.hpp similarity index 100% rename from xs/src/libslic3r/Fill/Fill3DHoneycomb.hpp rename to src/libslic3r/Fill/Fill3DHoneycomb.hpp diff --git a/xs/src/libslic3r/Fill/FillBase.cpp b/src/libslic3r/Fill/FillBase.cpp similarity index 100% rename from xs/src/libslic3r/Fill/FillBase.cpp rename to src/libslic3r/Fill/FillBase.cpp diff --git a/xs/src/libslic3r/Fill/FillBase.hpp b/src/libslic3r/Fill/FillBase.hpp similarity index 100% rename from xs/src/libslic3r/Fill/FillBase.hpp rename to src/libslic3r/Fill/FillBase.hpp diff --git a/xs/src/libslic3r/Fill/FillConcentric.cpp b/src/libslic3r/Fill/FillConcentric.cpp similarity index 100% rename from xs/src/libslic3r/Fill/FillConcentric.cpp rename to src/libslic3r/Fill/FillConcentric.cpp diff --git a/xs/src/libslic3r/Fill/FillConcentric.hpp b/src/libslic3r/Fill/FillConcentric.hpp similarity index 100% rename from xs/src/libslic3r/Fill/FillConcentric.hpp rename to src/libslic3r/Fill/FillConcentric.hpp diff --git a/xs/src/libslic3r/Fill/FillGyroid.cpp b/src/libslic3r/Fill/FillGyroid.cpp similarity index 100% rename from xs/src/libslic3r/Fill/FillGyroid.cpp rename to src/libslic3r/Fill/FillGyroid.cpp diff --git a/xs/src/libslic3r/Fill/FillGyroid.hpp b/src/libslic3r/Fill/FillGyroid.hpp similarity index 100% rename from xs/src/libslic3r/Fill/FillGyroid.hpp rename to src/libslic3r/Fill/FillGyroid.hpp diff --git a/xs/src/libslic3r/Fill/FillHoneycomb.cpp b/src/libslic3r/Fill/FillHoneycomb.cpp similarity index 100% rename from xs/src/libslic3r/Fill/FillHoneycomb.cpp rename to src/libslic3r/Fill/FillHoneycomb.cpp diff --git a/xs/src/libslic3r/Fill/FillHoneycomb.hpp b/src/libslic3r/Fill/FillHoneycomb.hpp similarity index 100% rename from xs/src/libslic3r/Fill/FillHoneycomb.hpp rename to src/libslic3r/Fill/FillHoneycomb.hpp diff --git a/xs/src/libslic3r/Fill/FillPlanePath.cpp b/src/libslic3r/Fill/FillPlanePath.cpp similarity index 100% rename from xs/src/libslic3r/Fill/FillPlanePath.cpp rename to src/libslic3r/Fill/FillPlanePath.cpp diff --git a/xs/src/libslic3r/Fill/FillPlanePath.hpp b/src/libslic3r/Fill/FillPlanePath.hpp similarity index 100% rename from xs/src/libslic3r/Fill/FillPlanePath.hpp rename to src/libslic3r/Fill/FillPlanePath.hpp diff --git a/xs/src/libslic3r/Fill/FillRectilinear.cpp b/src/libslic3r/Fill/FillRectilinear.cpp similarity index 100% rename from xs/src/libslic3r/Fill/FillRectilinear.cpp rename to src/libslic3r/Fill/FillRectilinear.cpp diff --git a/xs/src/libslic3r/Fill/FillRectilinear.hpp b/src/libslic3r/Fill/FillRectilinear.hpp similarity index 100% rename from xs/src/libslic3r/Fill/FillRectilinear.hpp rename to src/libslic3r/Fill/FillRectilinear.hpp diff --git a/xs/src/libslic3r/Fill/FillRectilinear2.cpp b/src/libslic3r/Fill/FillRectilinear2.cpp similarity index 100% rename from xs/src/libslic3r/Fill/FillRectilinear2.cpp rename to src/libslic3r/Fill/FillRectilinear2.cpp diff --git a/xs/src/libslic3r/Fill/FillRectilinear2.hpp b/src/libslic3r/Fill/FillRectilinear2.hpp similarity index 100% rename from xs/src/libslic3r/Fill/FillRectilinear2.hpp rename to src/libslic3r/Fill/FillRectilinear2.hpp diff --git a/xs/src/libslic3r/Fill/FillRectilinear3.cpp b/src/libslic3r/Fill/FillRectilinear3.cpp similarity index 100% rename from xs/src/libslic3r/Fill/FillRectilinear3.cpp rename to src/libslic3r/Fill/FillRectilinear3.cpp diff --git a/xs/src/libslic3r/Fill/FillRectilinear3.hpp b/src/libslic3r/Fill/FillRectilinear3.hpp similarity index 100% rename from xs/src/libslic3r/Fill/FillRectilinear3.hpp rename to src/libslic3r/Fill/FillRectilinear3.hpp diff --git a/xs/src/libslic3r/Flow.cpp b/src/libslic3r/Flow.cpp similarity index 100% rename from xs/src/libslic3r/Flow.cpp rename to src/libslic3r/Flow.cpp diff --git a/xs/src/libslic3r/Flow.hpp b/src/libslic3r/Flow.hpp similarity index 100% rename from xs/src/libslic3r/Flow.hpp rename to src/libslic3r/Flow.hpp diff --git a/xs/src/libslic3r/Format/3mf.cpp b/src/libslic3r/Format/3mf.cpp similarity index 100% rename from xs/src/libslic3r/Format/3mf.cpp rename to src/libslic3r/Format/3mf.cpp diff --git a/xs/src/libslic3r/Format/3mf.hpp b/src/libslic3r/Format/3mf.hpp similarity index 100% rename from xs/src/libslic3r/Format/3mf.hpp rename to src/libslic3r/Format/3mf.hpp diff --git a/xs/src/libslic3r/Format/AMF.cpp b/src/libslic3r/Format/AMF.cpp similarity index 100% rename from xs/src/libslic3r/Format/AMF.cpp rename to src/libslic3r/Format/AMF.cpp diff --git a/xs/src/libslic3r/Format/AMF.hpp b/src/libslic3r/Format/AMF.hpp similarity index 100% rename from xs/src/libslic3r/Format/AMF.hpp rename to src/libslic3r/Format/AMF.hpp diff --git a/xs/src/libslic3r/Format/OBJ.cpp b/src/libslic3r/Format/OBJ.cpp similarity index 100% rename from xs/src/libslic3r/Format/OBJ.cpp rename to src/libslic3r/Format/OBJ.cpp diff --git a/xs/src/libslic3r/Format/OBJ.hpp b/src/libslic3r/Format/OBJ.hpp similarity index 100% rename from xs/src/libslic3r/Format/OBJ.hpp rename to src/libslic3r/Format/OBJ.hpp diff --git a/xs/src/libslic3r/Format/PRUS.cpp b/src/libslic3r/Format/PRUS.cpp similarity index 100% rename from xs/src/libslic3r/Format/PRUS.cpp rename to src/libslic3r/Format/PRUS.cpp diff --git a/xs/src/libslic3r/Format/PRUS.hpp b/src/libslic3r/Format/PRUS.hpp similarity index 100% rename from xs/src/libslic3r/Format/PRUS.hpp rename to src/libslic3r/Format/PRUS.hpp diff --git a/xs/src/libslic3r/Format/STL.cpp b/src/libslic3r/Format/STL.cpp similarity index 100% rename from xs/src/libslic3r/Format/STL.cpp rename to src/libslic3r/Format/STL.cpp diff --git a/xs/src/libslic3r/Format/STL.hpp b/src/libslic3r/Format/STL.hpp similarity index 100% rename from xs/src/libslic3r/Format/STL.hpp rename to src/libslic3r/Format/STL.hpp diff --git a/xs/src/libslic3r/Format/objparser.cpp b/src/libslic3r/Format/objparser.cpp similarity index 100% rename from xs/src/libslic3r/Format/objparser.cpp rename to src/libslic3r/Format/objparser.cpp diff --git a/xs/src/libslic3r/Format/objparser.hpp b/src/libslic3r/Format/objparser.hpp similarity index 100% rename from xs/src/libslic3r/Format/objparser.hpp rename to src/libslic3r/Format/objparser.hpp diff --git a/xs/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp similarity index 100% rename from xs/src/libslic3r/GCode.cpp rename to src/libslic3r/GCode.cpp diff --git a/xs/src/libslic3r/GCode.hpp b/src/libslic3r/GCode.hpp similarity index 100% rename from xs/src/libslic3r/GCode.hpp rename to src/libslic3r/GCode.hpp diff --git a/xs/src/libslic3r/GCode/Analyzer.cpp b/src/libslic3r/GCode/Analyzer.cpp similarity index 100% rename from xs/src/libslic3r/GCode/Analyzer.cpp rename to src/libslic3r/GCode/Analyzer.cpp diff --git a/xs/src/libslic3r/GCode/Analyzer.hpp b/src/libslic3r/GCode/Analyzer.hpp similarity index 100% rename from xs/src/libslic3r/GCode/Analyzer.hpp rename to src/libslic3r/GCode/Analyzer.hpp diff --git a/xs/src/libslic3r/GCode/CoolingBuffer.cpp b/src/libslic3r/GCode/CoolingBuffer.cpp similarity index 100% rename from xs/src/libslic3r/GCode/CoolingBuffer.cpp rename to src/libslic3r/GCode/CoolingBuffer.cpp diff --git a/xs/src/libslic3r/GCode/CoolingBuffer.hpp b/src/libslic3r/GCode/CoolingBuffer.hpp similarity index 100% rename from xs/src/libslic3r/GCode/CoolingBuffer.hpp rename to src/libslic3r/GCode/CoolingBuffer.hpp diff --git a/xs/src/libslic3r/GCode/PostProcessor.cpp b/src/libslic3r/GCode/PostProcessor.cpp similarity index 100% rename from xs/src/libslic3r/GCode/PostProcessor.cpp rename to src/libslic3r/GCode/PostProcessor.cpp diff --git a/xs/src/libslic3r/GCode/PostProcessor.hpp b/src/libslic3r/GCode/PostProcessor.hpp similarity index 100% rename from xs/src/libslic3r/GCode/PostProcessor.hpp rename to src/libslic3r/GCode/PostProcessor.hpp diff --git a/xs/src/libslic3r/GCode/PressureEqualizer.cpp b/src/libslic3r/GCode/PressureEqualizer.cpp similarity index 100% rename from xs/src/libslic3r/GCode/PressureEqualizer.cpp rename to src/libslic3r/GCode/PressureEqualizer.cpp diff --git a/xs/src/libslic3r/GCode/PressureEqualizer.hpp b/src/libslic3r/GCode/PressureEqualizer.hpp similarity index 100% rename from xs/src/libslic3r/GCode/PressureEqualizer.hpp rename to src/libslic3r/GCode/PressureEqualizer.hpp diff --git a/xs/src/libslic3r/GCode/PreviewData.cpp b/src/libslic3r/GCode/PreviewData.cpp similarity index 100% rename from xs/src/libslic3r/GCode/PreviewData.cpp rename to src/libslic3r/GCode/PreviewData.cpp diff --git a/xs/src/libslic3r/GCode/PreviewData.hpp b/src/libslic3r/GCode/PreviewData.hpp similarity index 100% rename from xs/src/libslic3r/GCode/PreviewData.hpp rename to src/libslic3r/GCode/PreviewData.hpp diff --git a/xs/src/libslic3r/GCode/PrintExtents.cpp b/src/libslic3r/GCode/PrintExtents.cpp similarity index 100% rename from xs/src/libslic3r/GCode/PrintExtents.cpp rename to src/libslic3r/GCode/PrintExtents.cpp diff --git a/xs/src/libslic3r/GCode/PrintExtents.hpp b/src/libslic3r/GCode/PrintExtents.hpp similarity index 100% rename from xs/src/libslic3r/GCode/PrintExtents.hpp rename to src/libslic3r/GCode/PrintExtents.hpp diff --git a/xs/src/libslic3r/GCode/SpiralVase.cpp b/src/libslic3r/GCode/SpiralVase.cpp similarity index 100% rename from xs/src/libslic3r/GCode/SpiralVase.cpp rename to src/libslic3r/GCode/SpiralVase.cpp diff --git a/xs/src/libslic3r/GCode/SpiralVase.hpp b/src/libslic3r/GCode/SpiralVase.hpp similarity index 100% rename from xs/src/libslic3r/GCode/SpiralVase.hpp rename to src/libslic3r/GCode/SpiralVase.hpp diff --git a/xs/src/libslic3r/GCode/ToolOrdering.cpp b/src/libslic3r/GCode/ToolOrdering.cpp similarity index 100% rename from xs/src/libslic3r/GCode/ToolOrdering.cpp rename to src/libslic3r/GCode/ToolOrdering.cpp diff --git a/xs/src/libslic3r/GCode/ToolOrdering.hpp b/src/libslic3r/GCode/ToolOrdering.hpp similarity index 100% rename from xs/src/libslic3r/GCode/ToolOrdering.hpp rename to src/libslic3r/GCode/ToolOrdering.hpp diff --git a/xs/src/libslic3r/GCode/WipeTower.hpp b/src/libslic3r/GCode/WipeTower.hpp similarity index 100% rename from xs/src/libslic3r/GCode/WipeTower.hpp rename to src/libslic3r/GCode/WipeTower.hpp diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/src/libslic3r/GCode/WipeTowerPrusaMM.cpp similarity index 100% rename from xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp rename to src/libslic3r/GCode/WipeTowerPrusaMM.cpp diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp b/src/libslic3r/GCode/WipeTowerPrusaMM.hpp similarity index 100% rename from xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp rename to src/libslic3r/GCode/WipeTowerPrusaMM.hpp diff --git a/xs/src/libslic3r/GCodeReader.cpp b/src/libslic3r/GCodeReader.cpp similarity index 100% rename from xs/src/libslic3r/GCodeReader.cpp rename to src/libslic3r/GCodeReader.cpp diff --git a/xs/src/libslic3r/GCodeReader.hpp b/src/libslic3r/GCodeReader.hpp similarity index 100% rename from xs/src/libslic3r/GCodeReader.hpp rename to src/libslic3r/GCodeReader.hpp diff --git a/xs/src/libslic3r/GCodeSender.cpp b/src/libslic3r/GCodeSender.cpp similarity index 100% rename from xs/src/libslic3r/GCodeSender.cpp rename to src/libslic3r/GCodeSender.cpp diff --git a/xs/src/libslic3r/GCodeSender.hpp b/src/libslic3r/GCodeSender.hpp similarity index 100% rename from xs/src/libslic3r/GCodeSender.hpp rename to src/libslic3r/GCodeSender.hpp diff --git a/xs/src/libslic3r/GCodeTimeEstimator.cpp b/src/libslic3r/GCodeTimeEstimator.cpp similarity index 100% rename from xs/src/libslic3r/GCodeTimeEstimator.cpp rename to src/libslic3r/GCodeTimeEstimator.cpp diff --git a/xs/src/libslic3r/GCodeTimeEstimator.hpp b/src/libslic3r/GCodeTimeEstimator.hpp similarity index 100% rename from xs/src/libslic3r/GCodeTimeEstimator.hpp rename to src/libslic3r/GCodeTimeEstimator.hpp diff --git a/xs/src/libslic3r/GCodeWriter.cpp b/src/libslic3r/GCodeWriter.cpp similarity index 100% rename from xs/src/libslic3r/GCodeWriter.cpp rename to src/libslic3r/GCodeWriter.cpp diff --git a/xs/src/libslic3r/GCodeWriter.hpp b/src/libslic3r/GCodeWriter.hpp similarity index 100% rename from xs/src/libslic3r/GCodeWriter.hpp rename to src/libslic3r/GCodeWriter.hpp diff --git a/xs/src/libslic3r/Geometry.cpp b/src/libslic3r/Geometry.cpp similarity index 100% rename from xs/src/libslic3r/Geometry.cpp rename to src/libslic3r/Geometry.cpp diff --git a/xs/src/libslic3r/Geometry.hpp b/src/libslic3r/Geometry.hpp similarity index 100% rename from xs/src/libslic3r/Geometry.hpp rename to src/libslic3r/Geometry.hpp diff --git a/xs/src/libslic3r/I18N.hpp b/src/libslic3r/I18N.hpp similarity index 100% rename from xs/src/libslic3r/I18N.hpp rename to src/libslic3r/I18N.hpp diff --git a/xs/src/libslic3r/Int128.hpp b/src/libslic3r/Int128.hpp similarity index 100% rename from xs/src/libslic3r/Int128.hpp rename to src/libslic3r/Int128.hpp diff --git a/xs/src/libslic3r/Layer.cpp b/src/libslic3r/Layer.cpp similarity index 100% rename from xs/src/libslic3r/Layer.cpp rename to src/libslic3r/Layer.cpp diff --git a/xs/src/libslic3r/Layer.hpp b/src/libslic3r/Layer.hpp similarity index 100% rename from xs/src/libslic3r/Layer.hpp rename to src/libslic3r/Layer.hpp diff --git a/xs/src/libslic3r/LayerRegion.cpp b/src/libslic3r/LayerRegion.cpp similarity index 100% rename from xs/src/libslic3r/LayerRegion.cpp rename to src/libslic3r/LayerRegion.cpp diff --git a/xs/src/libslic3r/Line.cpp b/src/libslic3r/Line.cpp similarity index 100% rename from xs/src/libslic3r/Line.cpp rename to src/libslic3r/Line.cpp diff --git a/xs/src/libslic3r/Line.hpp b/src/libslic3r/Line.hpp similarity index 100% rename from xs/src/libslic3r/Line.hpp rename to src/libslic3r/Line.hpp diff --git a/xs/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp similarity index 100% rename from xs/src/libslic3r/Model.cpp rename to src/libslic3r/Model.cpp diff --git a/xs/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp similarity index 100% rename from xs/src/libslic3r/Model.hpp rename to src/libslic3r/Model.hpp diff --git a/xs/src/libslic3r/ModelArrange.hpp b/src/libslic3r/ModelArrange.hpp similarity index 100% rename from xs/src/libslic3r/ModelArrange.hpp rename to src/libslic3r/ModelArrange.hpp diff --git a/xs/src/libslic3r/MotionPlanner.cpp b/src/libslic3r/MotionPlanner.cpp similarity index 100% rename from xs/src/libslic3r/MotionPlanner.cpp rename to src/libslic3r/MotionPlanner.cpp diff --git a/xs/src/libslic3r/MotionPlanner.hpp b/src/libslic3r/MotionPlanner.hpp similarity index 100% rename from xs/src/libslic3r/MotionPlanner.hpp rename to src/libslic3r/MotionPlanner.hpp diff --git a/xs/src/libslic3r/MultiPoint.cpp b/src/libslic3r/MultiPoint.cpp similarity index 100% rename from xs/src/libslic3r/MultiPoint.cpp rename to src/libslic3r/MultiPoint.cpp diff --git a/xs/src/libslic3r/MultiPoint.hpp b/src/libslic3r/MultiPoint.hpp similarity index 100% rename from xs/src/libslic3r/MultiPoint.hpp rename to src/libslic3r/MultiPoint.hpp diff --git a/xs/src/libslic3r/MutablePriorityQueue.hpp b/src/libslic3r/MutablePriorityQueue.hpp similarity index 100% rename from xs/src/libslic3r/MutablePriorityQueue.hpp rename to src/libslic3r/MutablePriorityQueue.hpp diff --git a/xs/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp similarity index 100% rename from xs/src/libslic3r/PerimeterGenerator.cpp rename to src/libslic3r/PerimeterGenerator.cpp diff --git a/xs/src/libslic3r/PerimeterGenerator.hpp b/src/libslic3r/PerimeterGenerator.hpp similarity index 100% rename from xs/src/libslic3r/PerimeterGenerator.hpp rename to src/libslic3r/PerimeterGenerator.hpp diff --git a/xs/src/libslic3r/PlaceholderParser.cpp b/src/libslic3r/PlaceholderParser.cpp similarity index 100% rename from xs/src/libslic3r/PlaceholderParser.cpp rename to src/libslic3r/PlaceholderParser.cpp diff --git a/xs/src/libslic3r/PlaceholderParser.hpp b/src/libslic3r/PlaceholderParser.hpp similarity index 100% rename from xs/src/libslic3r/PlaceholderParser.hpp rename to src/libslic3r/PlaceholderParser.hpp diff --git a/xs/src/libslic3r/Point.cpp b/src/libslic3r/Point.cpp similarity index 100% rename from xs/src/libslic3r/Point.cpp rename to src/libslic3r/Point.cpp diff --git a/xs/src/libslic3r/Point.hpp b/src/libslic3r/Point.hpp similarity index 100% rename from xs/src/libslic3r/Point.hpp rename to src/libslic3r/Point.hpp diff --git a/xs/src/libslic3r/Polygon.cpp b/src/libslic3r/Polygon.cpp similarity index 100% rename from xs/src/libslic3r/Polygon.cpp rename to src/libslic3r/Polygon.cpp diff --git a/xs/src/libslic3r/Polygon.hpp b/src/libslic3r/Polygon.hpp similarity index 100% rename from xs/src/libslic3r/Polygon.hpp rename to src/libslic3r/Polygon.hpp diff --git a/xs/src/libslic3r/Polyline.cpp b/src/libslic3r/Polyline.cpp similarity index 100% rename from xs/src/libslic3r/Polyline.cpp rename to src/libslic3r/Polyline.cpp diff --git a/xs/src/libslic3r/Polyline.hpp b/src/libslic3r/Polyline.hpp similarity index 100% rename from xs/src/libslic3r/Polyline.hpp rename to src/libslic3r/Polyline.hpp diff --git a/xs/src/libslic3r/PolylineCollection.cpp b/src/libslic3r/PolylineCollection.cpp similarity index 100% rename from xs/src/libslic3r/PolylineCollection.cpp rename to src/libslic3r/PolylineCollection.cpp diff --git a/xs/src/libslic3r/PolylineCollection.hpp b/src/libslic3r/PolylineCollection.hpp similarity index 100% rename from xs/src/libslic3r/PolylineCollection.hpp rename to src/libslic3r/PolylineCollection.hpp diff --git a/xs/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp similarity index 98% rename from xs/src/libslic3r/Print.cpp rename to src/libslic3r/Print.cpp index f8f6537ca8..cdc12d2d15 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -1341,22 +1341,22 @@ std::string Print::output_filepath(const std::string &path) const void Print::export_png(const std::string &dirpath) { - size_t idx = 0; - for (PrintObject *obj : m_objects) { - obj->slice(); - this->set_status(int(floor(idx * 100. / m_objects.size() + 0.5)), "Slicing..."); - ++ idx; - } - this->set_status(90, "Exporting zipped archive..."); - print_to(*this, - dirpath, - float(m_config.bed_size_x.value), - float(m_config.bed_size_y.value), - int(m_config.pixel_width.value), - int(m_config.pixel_height.value), - float(m_config.exp_time.value), - float(m_config.exp_time_first.value)); - this->set_status(100, "Done."); +// size_t idx = 0; +// for (PrintObject *obj : m_objects) { +// obj->slice(); +// this->set_status(int(floor(idx * 100. / m_objects.size() + 0.5)), "Slicing..."); +// ++ idx; +// } +// this->set_status(90, "Exporting zipped archive..."); +// print_to(*this, +// dirpath, +// float(m_config.bed_size_x.value), +// float(m_config.bed_size_y.value), +// int(m_config.pixel_width.value), +// int(m_config.pixel_height.value), +// float(m_config.exp_time.value), +// float(m_config.exp_time_first.value)); +// this->set_status(100, "Done."); } // Returns extruder this eec should be printed with, according to PrintRegion config diff --git a/xs/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp similarity index 100% rename from xs/src/libslic3r/Print.hpp rename to src/libslic3r/Print.hpp diff --git a/xs/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp similarity index 100% rename from xs/src/libslic3r/PrintConfig.cpp rename to src/libslic3r/PrintConfig.cpp diff --git a/xs/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp similarity index 100% rename from xs/src/libslic3r/PrintConfig.hpp rename to src/libslic3r/PrintConfig.hpp diff --git a/xs/src/libslic3r/PrintExport.hpp b/src/libslic3r/PrintExport.hpp similarity index 100% rename from xs/src/libslic3r/PrintExport.hpp rename to src/libslic3r/PrintExport.hpp diff --git a/xs/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp similarity index 100% rename from xs/src/libslic3r/PrintObject.cpp rename to src/libslic3r/PrintObject.cpp diff --git a/xs/src/libslic3r/PrintRegion.cpp b/src/libslic3r/PrintRegion.cpp similarity index 100% rename from xs/src/libslic3r/PrintRegion.cpp rename to src/libslic3r/PrintRegion.cpp diff --git a/xs/src/libslic3r/Rasterizer/Rasterizer.cpp b/src/libslic3r/Rasterizer/Rasterizer.cpp similarity index 100% rename from xs/src/libslic3r/Rasterizer/Rasterizer.cpp rename to src/libslic3r/Rasterizer/Rasterizer.cpp diff --git a/xs/src/libslic3r/Rasterizer/Rasterizer.hpp b/src/libslic3r/Rasterizer/Rasterizer.hpp similarity index 100% rename from xs/src/libslic3r/Rasterizer/Rasterizer.hpp rename to src/libslic3r/Rasterizer/Rasterizer.hpp diff --git a/xs/src/libslic3r/SLABasePool.cpp b/src/libslic3r/SLABasePool.cpp similarity index 100% rename from xs/src/libslic3r/SLABasePool.cpp rename to src/libslic3r/SLABasePool.cpp diff --git a/xs/src/libslic3r/SLABasePool.hpp b/src/libslic3r/SLABasePool.hpp similarity index 100% rename from xs/src/libslic3r/SLABasePool.hpp rename to src/libslic3r/SLABasePool.hpp diff --git a/xs/src/libslic3r/SVG.cpp b/src/libslic3r/SVG.cpp similarity index 100% rename from xs/src/libslic3r/SVG.cpp rename to src/libslic3r/SVG.cpp diff --git a/xs/src/libslic3r/SVG.hpp b/src/libslic3r/SVG.hpp similarity index 100% rename from xs/src/libslic3r/SVG.hpp rename to src/libslic3r/SVG.hpp diff --git a/xs/src/libslic3r/Slicing.cpp b/src/libslic3r/Slicing.cpp similarity index 100% rename from xs/src/libslic3r/Slicing.cpp rename to src/libslic3r/Slicing.cpp diff --git a/xs/src/libslic3r/Slicing.hpp b/src/libslic3r/Slicing.hpp similarity index 100% rename from xs/src/libslic3r/Slicing.hpp rename to src/libslic3r/Slicing.hpp diff --git a/xs/src/libslic3r/SlicingAdaptive.cpp b/src/libslic3r/SlicingAdaptive.cpp similarity index 100% rename from xs/src/libslic3r/SlicingAdaptive.cpp rename to src/libslic3r/SlicingAdaptive.cpp diff --git a/xs/src/libslic3r/SlicingAdaptive.hpp b/src/libslic3r/SlicingAdaptive.hpp similarity index 100% rename from xs/src/libslic3r/SlicingAdaptive.hpp rename to src/libslic3r/SlicingAdaptive.hpp diff --git a/xs/src/libslic3r/SupportMaterial.cpp b/src/libslic3r/SupportMaterial.cpp similarity index 100% rename from xs/src/libslic3r/SupportMaterial.cpp rename to src/libslic3r/SupportMaterial.cpp diff --git a/xs/src/libslic3r/SupportMaterial.hpp b/src/libslic3r/SupportMaterial.hpp similarity index 100% rename from xs/src/libslic3r/SupportMaterial.hpp rename to src/libslic3r/SupportMaterial.hpp diff --git a/xs/src/libslic3r/Surface.cpp b/src/libslic3r/Surface.cpp similarity index 100% rename from xs/src/libslic3r/Surface.cpp rename to src/libslic3r/Surface.cpp diff --git a/xs/src/libslic3r/Surface.hpp b/src/libslic3r/Surface.hpp similarity index 100% rename from xs/src/libslic3r/Surface.hpp rename to src/libslic3r/Surface.hpp diff --git a/xs/src/libslic3r/SurfaceCollection.cpp b/src/libslic3r/SurfaceCollection.cpp similarity index 100% rename from xs/src/libslic3r/SurfaceCollection.cpp rename to src/libslic3r/SurfaceCollection.cpp diff --git a/xs/src/libslic3r/SurfaceCollection.hpp b/src/libslic3r/SurfaceCollection.hpp similarity index 100% rename from xs/src/libslic3r/SurfaceCollection.hpp rename to src/libslic3r/SurfaceCollection.hpp diff --git a/xs/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp similarity index 100% rename from xs/src/libslic3r/Technologies.hpp rename to src/libslic3r/Technologies.hpp diff --git a/xs/src/libslic3r/TriangleMesh.cpp b/src/libslic3r/TriangleMesh.cpp similarity index 100% rename from xs/src/libslic3r/TriangleMesh.cpp rename to src/libslic3r/TriangleMesh.cpp diff --git a/xs/src/libslic3r/TriangleMesh.hpp b/src/libslic3r/TriangleMesh.hpp similarity index 100% rename from xs/src/libslic3r/TriangleMesh.hpp rename to src/libslic3r/TriangleMesh.hpp diff --git a/xs/src/libslic3r/Utils.hpp b/src/libslic3r/Utils.hpp similarity index 100% rename from xs/src/libslic3r/Utils.hpp rename to src/libslic3r/Utils.hpp diff --git a/xs/src/libslic3r/libslic3r.h b/src/libslic3r/libslic3r.h similarity index 100% rename from xs/src/libslic3r/libslic3r.h rename to src/libslic3r/libslic3r.h diff --git a/xs/src/libslic3r/utils.cpp b/src/libslic3r/utils.cpp similarity index 100% rename from xs/src/libslic3r/utils.cpp rename to src/libslic3r/utils.cpp diff --git a/src/miniz/CMakeLists.txt b/src/miniz/CMakeLists.txt new file mode 100644 index 0000000000..da92b1252e --- /dev/null +++ b/src/miniz/CMakeLists.txt @@ -0,0 +1,14 @@ +project(miniz) +cmake_minimum_required(VERSION 2.6) + +add_library(miniz STATIC + miniz.h + miniz_common.h + miniz_tdef.h + miniz_tinfl.h + miniz_zip.h + miniz.cpp + miniz_tdef.cpp + miniz_tinfl.cpp + miniz_zip.cpp +) diff --git a/xs/src/miniz/miniz.cpp b/src/miniz/miniz.cpp similarity index 100% rename from xs/src/miniz/miniz.cpp rename to src/miniz/miniz.cpp diff --git a/xs/src/miniz/miniz.h b/src/miniz/miniz.h similarity index 100% rename from xs/src/miniz/miniz.h rename to src/miniz/miniz.h diff --git a/xs/src/miniz/miniz_common.h b/src/miniz/miniz_common.h similarity index 100% rename from xs/src/miniz/miniz_common.h rename to src/miniz/miniz_common.h diff --git a/xs/src/miniz/miniz_tdef.cpp b/src/miniz/miniz_tdef.cpp similarity index 100% rename from xs/src/miniz/miniz_tdef.cpp rename to src/miniz/miniz_tdef.cpp diff --git a/xs/src/miniz/miniz_tdef.h b/src/miniz/miniz_tdef.h similarity index 100% rename from xs/src/miniz/miniz_tdef.h rename to src/miniz/miniz_tdef.h diff --git a/xs/src/miniz/miniz_tinfl.cpp b/src/miniz/miniz_tinfl.cpp similarity index 100% rename from xs/src/miniz/miniz_tinfl.cpp rename to src/miniz/miniz_tinfl.cpp diff --git a/xs/src/miniz/miniz_tinfl.h b/src/miniz/miniz_tinfl.h similarity index 100% rename from xs/src/miniz/miniz_tinfl.h rename to src/miniz/miniz_tinfl.h diff --git a/xs/src/miniz/miniz_zip.cpp b/src/miniz/miniz_zip.cpp similarity index 100% rename from xs/src/miniz/miniz_zip.cpp rename to src/miniz/miniz_zip.cpp diff --git a/xs/src/miniz/miniz_zip.h b/src/miniz/miniz_zip.h similarity index 100% rename from xs/src/miniz/miniz_zip.h rename to src/miniz/miniz_zip.h diff --git a/xs/src/png/AUTHORS b/src/png/AUTHORS similarity index 100% rename from xs/src/png/AUTHORS rename to src/png/AUTHORS diff --git a/xs/src/png/COPYING b/src/png/COPYING similarity index 100% rename from xs/src/png/COPYING rename to src/png/COPYING diff --git a/xs/src/png/NEWS b/src/png/NEWS similarity index 100% rename from xs/src/png/NEWS rename to src/png/NEWS diff --git a/xs/src/png/color.hpp b/src/png/color.hpp similarity index 100% rename from xs/src/png/color.hpp rename to src/png/color.hpp diff --git a/xs/src/png/end_info.hpp b/src/png/end_info.hpp similarity index 100% rename from xs/src/png/end_info.hpp rename to src/png/end_info.hpp diff --git a/xs/src/png/error.hpp b/src/png/error.hpp similarity index 100% rename from xs/src/png/error.hpp rename to src/png/error.hpp diff --git a/xs/src/png/image_info.hpp b/src/png/image_info.hpp similarity index 100% rename from xs/src/png/image_info.hpp rename to src/png/image_info.hpp diff --git a/xs/src/png/info.hpp b/src/png/info.hpp similarity index 100% rename from xs/src/png/info.hpp rename to src/png/info.hpp diff --git a/xs/src/png/info_base.hpp b/src/png/info_base.hpp similarity index 100% rename from xs/src/png/info_base.hpp rename to src/png/info_base.hpp diff --git a/xs/src/png/io_base.hpp b/src/png/io_base.hpp similarity index 100% rename from xs/src/png/io_base.hpp rename to src/png/io_base.hpp diff --git a/xs/src/png/libpng/ANNOUNCE b/src/png/libpng/ANNOUNCE similarity index 100% rename from xs/src/png/libpng/ANNOUNCE rename to src/png/libpng/ANNOUNCE diff --git a/xs/src/png/libpng/CMakeLists.txt b/src/png/libpng/CMakeLists.txt similarity index 98% rename from xs/src/png/libpng/CMakeLists.txt rename to src/png/libpng/CMakeLists.txt index 266b67d0e2..7697110c72 100644 --- a/xs/src/png/libpng/CMakeLists.txt +++ b/src/png/libpng/CMakeLists.txt @@ -107,7 +107,7 @@ endif() # set definitions and sources for powerpc if(CMAKE_SYSTEM_PROCESSOR MATCHES "^powerpc*" OR - CMAKE_SYSTEM_PROCESSOR MATCHES "^ppc64*" ) + CMAKE_SYSTEM_PROCESSOR MATCHES "^ppc64*" ) set(PNG_POWERPC_VSX_POSSIBLE_VALUES on off) set(PNG_POWERPC_VSX "on" CACHE STRING "Enable POWERPC VSX optimizations: off: disable the optimizations.") @@ -131,7 +131,7 @@ endif() # set definitions and sources for intel if(CMAKE_SYSTEM_PROCESSOR MATCHES "^i?86" OR - CMAKE_SYSTEM_PROCESSOR MATCHES "^x86_64*" ) + CMAKE_SYSTEM_PROCESSOR MATCHES "^x86_64*" ) set(PNG_INTEL_SSE_POSSIBLE_VALUES on off) set(PNG_INTEL_SSE "on" CACHE STRING "Enable INTEL_SSE optimizations: off: disable the optimizations") @@ -155,7 +155,7 @@ endif() # set definitions and sources for MIPS if(CMAKE_SYSTEM_PROCESSOR MATCHES "mipsel*" OR - CMAKE_SYSTEM_PROCESSOR MATCHES "mips64el*" ) + CMAKE_SYSTEM_PROCESSOR MATCHES "mips64el*" ) set(PNG_MIPS_MSA_POSSIBLE_VALUES on off) set(PNG_MIPS_MSA "on" CACHE STRING "Enable MIPS_MSA optimizations: off: disable the optimizations") @@ -770,14 +770,14 @@ function(CREATE_SYMLINK DEST_FILE) if(CMAKE_HOST_WIN32 AND NOT CYGWIN AND NOT MSYS) execute_process( - COMMAND "${CMAKE_COMMAND}" -E copy_if_different ${S_FILE} ${DEST_FILE} - WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" - ) + COMMAND "${CMAKE_COMMAND}" -E copy_if_different ${S_FILE} ${DEST_FILE} + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" + ) else(CMAKE_HOST_WIN32 AND NOT CYGWIN AND NOT MSYS) execute_process( - COMMAND ${CMAKE_COMMAND} -E create_symlink ${S_FILE} ${DEST_FILE} - WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" - ) + COMMAND ${CMAKE_COMMAND} -E create_symlink ${S_FILE} ${DEST_FILE} + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" + ) endif(CMAKE_HOST_WIN32 AND NOT CYGWIN AND NOT MSYS) endif(S_FILE) @@ -788,12 +788,12 @@ function(CREATE_SYMLINK DEST_FILE) if(CMAKE_HOST_WIN32 AND NOT CYGWIN AND NOT MSYS) add_custom_command(TARGET ${S_TARGET} POST_BUILD - COMMAND "${CMAKE_COMMAND}" -E copy_if_different $ $/${DEST_FILE} - ) + COMMAND "${CMAKE_COMMAND}" -E copy_if_different $ $/${DEST_FILE} + ) else(CMAKE_HOST_WIN32 AND NOT CYGWIN AND NOT MSYS) add_custom_command(TARGET ${S_TARGET} POST_BUILD - COMMAND "${CMAKE_COMMAND}" -E create_symlink $ $/${DEST_FILE} - ) + COMMAND "${CMAKE_COMMAND}" -E create_symlink $ $/${DEST_FILE} + ) endif(CMAKE_HOST_WIN32 AND NOT CYGWIN AND NOT MSYS) endif(S_TARGET) diff --git a/xs/src/png/libpng/LICENSE b/src/png/libpng/LICENSE similarity index 100% rename from xs/src/png/libpng/LICENSE rename to src/png/libpng/LICENSE diff --git a/xs/src/png/libpng/arm/arm_init.c b/src/png/libpng/arm/arm_init.c similarity index 100% rename from xs/src/png/libpng/arm/arm_init.c rename to src/png/libpng/arm/arm_init.c diff --git a/xs/src/png/libpng/arm/filter_neon.S b/src/png/libpng/arm/filter_neon.S similarity index 100% rename from xs/src/png/libpng/arm/filter_neon.S rename to src/png/libpng/arm/filter_neon.S diff --git a/xs/src/png/libpng/arm/filter_neon_intrinsics.c b/src/png/libpng/arm/filter_neon_intrinsics.c similarity index 100% rename from xs/src/png/libpng/arm/filter_neon_intrinsics.c rename to src/png/libpng/arm/filter_neon_intrinsics.c diff --git a/xs/src/png/libpng/intel/filter_sse2_intrinsics.c b/src/png/libpng/intel/filter_sse2_intrinsics.c similarity index 100% rename from xs/src/png/libpng/intel/filter_sse2_intrinsics.c rename to src/png/libpng/intel/filter_sse2_intrinsics.c diff --git a/xs/src/png/libpng/intel/intel_init.c b/src/png/libpng/intel/intel_init.c similarity index 100% rename from xs/src/png/libpng/intel/intel_init.c rename to src/png/libpng/intel/intel_init.c diff --git a/xs/src/png/libpng/libpng-config.in b/src/png/libpng/libpng-config.in similarity index 100% rename from xs/src/png/libpng/libpng-config.in rename to src/png/libpng/libpng-config.in diff --git a/xs/src/png/libpng/libpng.pc.in b/src/png/libpng/libpng.pc.in similarity index 100% rename from xs/src/png/libpng/libpng.pc.in rename to src/png/libpng/libpng.pc.in diff --git a/xs/src/png/libpng/mips/filter_msa_intrinsics.c b/src/png/libpng/mips/filter_msa_intrinsics.c similarity index 100% rename from xs/src/png/libpng/mips/filter_msa_intrinsics.c rename to src/png/libpng/mips/filter_msa_intrinsics.c diff --git a/xs/src/png/libpng/mips/mips_init.c b/src/png/libpng/mips/mips_init.c similarity index 100% rename from xs/src/png/libpng/mips/mips_init.c rename to src/png/libpng/mips/mips_init.c diff --git a/xs/src/png/libpng/png.c b/src/png/libpng/png.c similarity index 100% rename from xs/src/png/libpng/png.c rename to src/png/libpng/png.c diff --git a/xs/src/png/libpng/png.h b/src/png/libpng/png.h similarity index 100% rename from xs/src/png/libpng/png.h rename to src/png/libpng/png.h diff --git a/xs/src/png/libpng/pngconf.h b/src/png/libpng/pngconf.h similarity index 100% rename from xs/src/png/libpng/pngconf.h rename to src/png/libpng/pngconf.h diff --git a/xs/src/png/libpng/pngdebug.h b/src/png/libpng/pngdebug.h similarity index 100% rename from xs/src/png/libpng/pngdebug.h rename to src/png/libpng/pngdebug.h diff --git a/xs/src/png/libpng/pngerror.c b/src/png/libpng/pngerror.c similarity index 100% rename from xs/src/png/libpng/pngerror.c rename to src/png/libpng/pngerror.c diff --git a/xs/src/png/libpng/pngget.c b/src/png/libpng/pngget.c similarity index 100% rename from xs/src/png/libpng/pngget.c rename to src/png/libpng/pngget.c diff --git a/xs/src/png/libpng/pnginfo.h b/src/png/libpng/pnginfo.h similarity index 100% rename from xs/src/png/libpng/pnginfo.h rename to src/png/libpng/pnginfo.h diff --git a/xs/src/png/libpng/pngmem.c b/src/png/libpng/pngmem.c similarity index 100% rename from xs/src/png/libpng/pngmem.c rename to src/png/libpng/pngmem.c diff --git a/xs/src/png/libpng/pngpread.c b/src/png/libpng/pngpread.c similarity index 100% rename from xs/src/png/libpng/pngpread.c rename to src/png/libpng/pngpread.c diff --git a/xs/src/png/libpng/pngpriv.h b/src/png/libpng/pngpriv.h similarity index 100% rename from xs/src/png/libpng/pngpriv.h rename to src/png/libpng/pngpriv.h diff --git a/xs/src/png/libpng/pngread.c b/src/png/libpng/pngread.c similarity index 100% rename from xs/src/png/libpng/pngread.c rename to src/png/libpng/pngread.c diff --git a/xs/src/png/libpng/pngrio.c b/src/png/libpng/pngrio.c similarity index 100% rename from xs/src/png/libpng/pngrio.c rename to src/png/libpng/pngrio.c diff --git a/xs/src/png/libpng/pngrtran.c b/src/png/libpng/pngrtran.c similarity index 100% rename from xs/src/png/libpng/pngrtran.c rename to src/png/libpng/pngrtran.c diff --git a/xs/src/png/libpng/pngrutil.c b/src/png/libpng/pngrutil.c similarity index 100% rename from xs/src/png/libpng/pngrutil.c rename to src/png/libpng/pngrutil.c diff --git a/xs/src/png/libpng/pngset.c b/src/png/libpng/pngset.c similarity index 100% rename from xs/src/png/libpng/pngset.c rename to src/png/libpng/pngset.c diff --git a/xs/src/png/libpng/pngstruct.h b/src/png/libpng/pngstruct.h similarity index 100% rename from xs/src/png/libpng/pngstruct.h rename to src/png/libpng/pngstruct.h diff --git a/xs/src/png/libpng/pngtest.c b/src/png/libpng/pngtest.c similarity index 100% rename from xs/src/png/libpng/pngtest.c rename to src/png/libpng/pngtest.c diff --git a/xs/src/png/libpng/pngtrans.c b/src/png/libpng/pngtrans.c similarity index 100% rename from xs/src/png/libpng/pngtrans.c rename to src/png/libpng/pngtrans.c diff --git a/xs/src/png/libpng/pngusr.dfa b/src/png/libpng/pngusr.dfa similarity index 100% rename from xs/src/png/libpng/pngusr.dfa rename to src/png/libpng/pngusr.dfa diff --git a/xs/src/png/libpng/pngwio.c b/src/png/libpng/pngwio.c similarity index 100% rename from xs/src/png/libpng/pngwio.c rename to src/png/libpng/pngwio.c diff --git a/xs/src/png/libpng/pngwrite.c b/src/png/libpng/pngwrite.c similarity index 100% rename from xs/src/png/libpng/pngwrite.c rename to src/png/libpng/pngwrite.c diff --git a/xs/src/png/libpng/pngwtran.c b/src/png/libpng/pngwtran.c similarity index 100% rename from xs/src/png/libpng/pngwtran.c rename to src/png/libpng/pngwtran.c diff --git a/xs/src/png/libpng/pngwutil.c b/src/png/libpng/pngwutil.c similarity index 100% rename from xs/src/png/libpng/pngwutil.c rename to src/png/libpng/pngwutil.c diff --git a/xs/src/png/libpng/powerpc/filter_vsx_intrinsics.c b/src/png/libpng/powerpc/filter_vsx_intrinsics.c similarity index 100% rename from xs/src/png/libpng/powerpc/filter_vsx_intrinsics.c rename to src/png/libpng/powerpc/filter_vsx_intrinsics.c diff --git a/xs/src/png/libpng/powerpc/powerpc_init.c b/src/png/libpng/powerpc/powerpc_init.c similarity index 100% rename from xs/src/png/libpng/powerpc/powerpc_init.c rename to src/png/libpng/powerpc/powerpc_init.c diff --git a/xs/src/png/libpng/scripts/checksym.awk b/src/png/libpng/scripts/checksym.awk old mode 100755 new mode 100644 similarity index 100% rename from xs/src/png/libpng/scripts/checksym.awk rename to src/png/libpng/scripts/checksym.awk diff --git a/xs/src/png/libpng/scripts/def.c b/src/png/libpng/scripts/def.c similarity index 100% rename from xs/src/png/libpng/scripts/def.c rename to src/png/libpng/scripts/def.c diff --git a/xs/src/png/libpng/scripts/dfn.awk b/src/png/libpng/scripts/dfn.awk old mode 100755 new mode 100644 similarity index 100% rename from xs/src/png/libpng/scripts/dfn.awk rename to src/png/libpng/scripts/dfn.awk diff --git a/xs/src/png/libpng/scripts/genchk.cmake.in b/src/png/libpng/scripts/genchk.cmake.in similarity index 100% rename from xs/src/png/libpng/scripts/genchk.cmake.in rename to src/png/libpng/scripts/genchk.cmake.in diff --git a/xs/src/png/libpng/scripts/genout.cmake.in b/src/png/libpng/scripts/genout.cmake.in similarity index 100% rename from xs/src/png/libpng/scripts/genout.cmake.in rename to src/png/libpng/scripts/genout.cmake.in diff --git a/xs/src/png/libpng/scripts/gensrc.cmake.in b/src/png/libpng/scripts/gensrc.cmake.in similarity index 100% rename from xs/src/png/libpng/scripts/gensrc.cmake.in rename to src/png/libpng/scripts/gensrc.cmake.in diff --git a/xs/src/png/libpng/scripts/intprefix.c b/src/png/libpng/scripts/intprefix.c similarity index 100% rename from xs/src/png/libpng/scripts/intprefix.c rename to src/png/libpng/scripts/intprefix.c diff --git a/xs/src/png/libpng/scripts/libpng-config-body.in b/src/png/libpng/scripts/libpng-config-body.in similarity index 100% rename from xs/src/png/libpng/scripts/libpng-config-body.in rename to src/png/libpng/scripts/libpng-config-body.in diff --git a/xs/src/png/libpng/scripts/libpng-config-head.in b/src/png/libpng/scripts/libpng-config-head.in similarity index 100% rename from xs/src/png/libpng/scripts/libpng-config-head.in rename to src/png/libpng/scripts/libpng-config-head.in diff --git a/xs/src/png/libpng/scripts/libpng.pc.in b/src/png/libpng/scripts/libpng.pc.in similarity index 100% rename from xs/src/png/libpng/scripts/libpng.pc.in rename to src/png/libpng/scripts/libpng.pc.in diff --git a/xs/src/png/libpng/scripts/options.awk b/src/png/libpng/scripts/options.awk old mode 100755 new mode 100644 similarity index 100% rename from xs/src/png/libpng/scripts/options.awk rename to src/png/libpng/scripts/options.awk diff --git a/xs/src/png/libpng/scripts/pnglibconf.dfa b/src/png/libpng/scripts/pnglibconf.dfa similarity index 100% rename from xs/src/png/libpng/scripts/pnglibconf.dfa rename to src/png/libpng/scripts/pnglibconf.dfa diff --git a/xs/src/png/libpng/scripts/pnglibconf.h.prebuilt b/src/png/libpng/scripts/pnglibconf.h.prebuilt similarity index 100% rename from xs/src/png/libpng/scripts/pnglibconf.h.prebuilt rename to src/png/libpng/scripts/pnglibconf.h.prebuilt diff --git a/xs/src/png/libpng/scripts/prefix.c b/src/png/libpng/scripts/prefix.c similarity index 100% rename from xs/src/png/libpng/scripts/prefix.c rename to src/png/libpng/scripts/prefix.c diff --git a/xs/src/png/libpng/scripts/sym.c b/src/png/libpng/scripts/sym.c similarity index 100% rename from xs/src/png/libpng/scripts/sym.c rename to src/png/libpng/scripts/sym.c diff --git a/xs/src/png/libpng/scripts/symbols.c b/src/png/libpng/scripts/symbols.c similarity index 100% rename from xs/src/png/libpng/scripts/symbols.c rename to src/png/libpng/scripts/symbols.c diff --git a/xs/src/png/libpng/scripts/symbols.def b/src/png/libpng/scripts/symbols.def similarity index 100% rename from xs/src/png/libpng/scripts/symbols.def rename to src/png/libpng/scripts/symbols.def diff --git a/xs/src/png/libpng/scripts/test.cmake.in b/src/png/libpng/scripts/test.cmake.in similarity index 100% rename from xs/src/png/libpng/scripts/test.cmake.in rename to src/png/libpng/scripts/test.cmake.in diff --git a/xs/src/png/libpng/scripts/vers.c b/src/png/libpng/scripts/vers.c similarity index 100% rename from xs/src/png/libpng/scripts/vers.c rename to src/png/libpng/scripts/vers.c diff --git a/xs/src/png/palette.hpp b/src/png/palette.hpp similarity index 100% rename from xs/src/png/palette.hpp rename to src/png/palette.hpp diff --git a/xs/src/png/pixel_traits.hpp b/src/png/pixel_traits.hpp similarity index 100% rename from xs/src/png/pixel_traits.hpp rename to src/png/pixel_traits.hpp diff --git a/xs/src/png/tRNS.hpp b/src/png/tRNS.hpp similarity index 100% rename from xs/src/png/tRNS.hpp rename to src/png/tRNS.hpp diff --git a/xs/src/png/types.hpp b/src/png/types.hpp similarity index 100% rename from xs/src/png/types.hpp rename to src/png/types.hpp diff --git a/xs/src/png/writer.hpp b/src/png/writer.hpp similarity index 100% rename from xs/src/png/writer.hpp rename to src/png/writer.hpp diff --git a/xs/src/png/zlib/CMakeLists.txt b/src/png/zlib/CMakeLists.txt similarity index 100% rename from xs/src/png/zlib/CMakeLists.txt rename to src/png/zlib/CMakeLists.txt diff --git a/xs/src/png/zlib/ChangeLog b/src/png/zlib/ChangeLog similarity index 100% rename from xs/src/png/zlib/ChangeLog rename to src/png/zlib/ChangeLog diff --git a/xs/src/png/zlib/FAQ b/src/png/zlib/FAQ similarity index 100% rename from xs/src/png/zlib/FAQ rename to src/png/zlib/FAQ diff --git a/xs/src/png/zlib/INDEX b/src/png/zlib/INDEX similarity index 100% rename from xs/src/png/zlib/INDEX rename to src/png/zlib/INDEX diff --git a/xs/src/png/zlib/Makefile b/src/png/zlib/Makefile similarity index 100% rename from xs/src/png/zlib/Makefile rename to src/png/zlib/Makefile diff --git a/xs/src/png/zlib/Makefile.in b/src/png/zlib/Makefile.in similarity index 100% rename from xs/src/png/zlib/Makefile.in rename to src/png/zlib/Makefile.in diff --git a/xs/src/png/zlib/README b/src/png/zlib/README similarity index 100% rename from xs/src/png/zlib/README rename to src/png/zlib/README diff --git a/xs/src/png/zlib/adler32.c b/src/png/zlib/adler32.c similarity index 100% rename from xs/src/png/zlib/adler32.c rename to src/png/zlib/adler32.c diff --git a/xs/src/png/zlib/amiga/Makefile.pup b/src/png/zlib/amiga/Makefile.pup similarity index 100% rename from xs/src/png/zlib/amiga/Makefile.pup rename to src/png/zlib/amiga/Makefile.pup diff --git a/xs/src/png/zlib/amiga/Makefile.sas b/src/png/zlib/amiga/Makefile.sas similarity index 100% rename from xs/src/png/zlib/amiga/Makefile.sas rename to src/png/zlib/amiga/Makefile.sas diff --git a/xs/src/png/zlib/compress.c b/src/png/zlib/compress.c similarity index 100% rename from xs/src/png/zlib/compress.c rename to src/png/zlib/compress.c diff --git a/xs/src/png/zlib/configure b/src/png/zlib/configure similarity index 100% rename from xs/src/png/zlib/configure rename to src/png/zlib/configure diff --git a/xs/src/png/zlib/contrib/README.contrib b/src/png/zlib/contrib/README.contrib similarity index 100% rename from xs/src/png/zlib/contrib/README.contrib rename to src/png/zlib/contrib/README.contrib diff --git a/xs/src/png/zlib/contrib/ada/buffer_demo.adb b/src/png/zlib/contrib/ada/buffer_demo.adb similarity index 100% rename from xs/src/png/zlib/contrib/ada/buffer_demo.adb rename to src/png/zlib/contrib/ada/buffer_demo.adb diff --git a/xs/src/png/zlib/contrib/ada/mtest.adb b/src/png/zlib/contrib/ada/mtest.adb similarity index 100% rename from xs/src/png/zlib/contrib/ada/mtest.adb rename to src/png/zlib/contrib/ada/mtest.adb diff --git a/xs/src/png/zlib/contrib/ada/read.adb b/src/png/zlib/contrib/ada/read.adb similarity index 100% rename from xs/src/png/zlib/contrib/ada/read.adb rename to src/png/zlib/contrib/ada/read.adb diff --git a/xs/src/png/zlib/contrib/ada/readme.txt b/src/png/zlib/contrib/ada/readme.txt similarity index 100% rename from xs/src/png/zlib/contrib/ada/readme.txt rename to src/png/zlib/contrib/ada/readme.txt diff --git a/xs/src/png/zlib/contrib/ada/test.adb b/src/png/zlib/contrib/ada/test.adb similarity index 100% rename from xs/src/png/zlib/contrib/ada/test.adb rename to src/png/zlib/contrib/ada/test.adb diff --git a/xs/src/png/zlib/contrib/ada/zlib-streams.adb b/src/png/zlib/contrib/ada/zlib-streams.adb similarity index 100% rename from xs/src/png/zlib/contrib/ada/zlib-streams.adb rename to src/png/zlib/contrib/ada/zlib-streams.adb diff --git a/xs/src/png/zlib/contrib/ada/zlib-streams.ads b/src/png/zlib/contrib/ada/zlib-streams.ads similarity index 100% rename from xs/src/png/zlib/contrib/ada/zlib-streams.ads rename to src/png/zlib/contrib/ada/zlib-streams.ads diff --git a/xs/src/png/zlib/contrib/ada/zlib-thin.adb b/src/png/zlib/contrib/ada/zlib-thin.adb similarity index 100% rename from xs/src/png/zlib/contrib/ada/zlib-thin.adb rename to src/png/zlib/contrib/ada/zlib-thin.adb diff --git a/xs/src/png/zlib/contrib/ada/zlib-thin.ads b/src/png/zlib/contrib/ada/zlib-thin.ads similarity index 100% rename from xs/src/png/zlib/contrib/ada/zlib-thin.ads rename to src/png/zlib/contrib/ada/zlib-thin.ads diff --git a/xs/src/png/zlib/contrib/ada/zlib.adb b/src/png/zlib/contrib/ada/zlib.adb similarity index 100% rename from xs/src/png/zlib/contrib/ada/zlib.adb rename to src/png/zlib/contrib/ada/zlib.adb diff --git a/xs/src/png/zlib/contrib/ada/zlib.ads b/src/png/zlib/contrib/ada/zlib.ads similarity index 100% rename from xs/src/png/zlib/contrib/ada/zlib.ads rename to src/png/zlib/contrib/ada/zlib.ads diff --git a/xs/src/png/zlib/contrib/ada/zlib.gpr b/src/png/zlib/contrib/ada/zlib.gpr similarity index 100% rename from xs/src/png/zlib/contrib/ada/zlib.gpr rename to src/png/zlib/contrib/ada/zlib.gpr diff --git a/xs/src/png/zlib/contrib/amd64/amd64-match.S b/src/png/zlib/contrib/amd64/amd64-match.S similarity index 100% rename from xs/src/png/zlib/contrib/amd64/amd64-match.S rename to src/png/zlib/contrib/amd64/amd64-match.S diff --git a/xs/src/png/zlib/contrib/asm686/README.686 b/src/png/zlib/contrib/asm686/README.686 similarity index 100% rename from xs/src/png/zlib/contrib/asm686/README.686 rename to src/png/zlib/contrib/asm686/README.686 diff --git a/xs/src/png/zlib/contrib/asm686/match.S b/src/png/zlib/contrib/asm686/match.S similarity index 100% rename from xs/src/png/zlib/contrib/asm686/match.S rename to src/png/zlib/contrib/asm686/match.S diff --git a/xs/src/png/zlib/contrib/blast/Makefile b/src/png/zlib/contrib/blast/Makefile similarity index 100% rename from xs/src/png/zlib/contrib/blast/Makefile rename to src/png/zlib/contrib/blast/Makefile diff --git a/xs/src/png/zlib/contrib/blast/README b/src/png/zlib/contrib/blast/README similarity index 100% rename from xs/src/png/zlib/contrib/blast/README rename to src/png/zlib/contrib/blast/README diff --git a/xs/src/png/zlib/contrib/blast/blast.c b/src/png/zlib/contrib/blast/blast.c similarity index 100% rename from xs/src/png/zlib/contrib/blast/blast.c rename to src/png/zlib/contrib/blast/blast.c diff --git a/xs/src/png/zlib/contrib/blast/blast.h b/src/png/zlib/contrib/blast/blast.h similarity index 100% rename from xs/src/png/zlib/contrib/blast/blast.h rename to src/png/zlib/contrib/blast/blast.h diff --git a/xs/src/png/zlib/contrib/blast/test.pk b/src/png/zlib/contrib/blast/test.pk similarity index 100% rename from xs/src/png/zlib/contrib/blast/test.pk rename to src/png/zlib/contrib/blast/test.pk diff --git a/xs/src/png/zlib/contrib/blast/test.txt b/src/png/zlib/contrib/blast/test.txt similarity index 100% rename from xs/src/png/zlib/contrib/blast/test.txt rename to src/png/zlib/contrib/blast/test.txt diff --git a/xs/src/png/zlib/contrib/delphi/ZLib.pas b/src/png/zlib/contrib/delphi/ZLib.pas similarity index 100% rename from xs/src/png/zlib/contrib/delphi/ZLib.pas rename to src/png/zlib/contrib/delphi/ZLib.pas diff --git a/xs/src/png/zlib/contrib/delphi/ZLibConst.pas b/src/png/zlib/contrib/delphi/ZLibConst.pas similarity index 100% rename from xs/src/png/zlib/contrib/delphi/ZLibConst.pas rename to src/png/zlib/contrib/delphi/ZLibConst.pas diff --git a/xs/src/png/zlib/contrib/delphi/readme.txt b/src/png/zlib/contrib/delphi/readme.txt similarity index 100% rename from xs/src/png/zlib/contrib/delphi/readme.txt rename to src/png/zlib/contrib/delphi/readme.txt diff --git a/xs/src/png/zlib/contrib/delphi/zlibd32.mak b/src/png/zlib/contrib/delphi/zlibd32.mak similarity index 100% rename from xs/src/png/zlib/contrib/delphi/zlibd32.mak rename to src/png/zlib/contrib/delphi/zlibd32.mak diff --git a/xs/src/png/zlib/contrib/dotzlib/DotZLib.build b/src/png/zlib/contrib/dotzlib/DotZLib.build similarity index 100% rename from xs/src/png/zlib/contrib/dotzlib/DotZLib.build rename to src/png/zlib/contrib/dotzlib/DotZLib.build diff --git a/xs/src/png/zlib/contrib/dotzlib/DotZLib.chm b/src/png/zlib/contrib/dotzlib/DotZLib.chm similarity index 100% rename from xs/src/png/zlib/contrib/dotzlib/DotZLib.chm rename to src/png/zlib/contrib/dotzlib/DotZLib.chm diff --git a/xs/src/png/zlib/contrib/dotzlib/DotZLib.sln b/src/png/zlib/contrib/dotzlib/DotZLib.sln similarity index 100% rename from xs/src/png/zlib/contrib/dotzlib/DotZLib.sln rename to src/png/zlib/contrib/dotzlib/DotZLib.sln diff --git a/xs/src/png/zlib/contrib/dotzlib/DotZLib/AssemblyInfo.cs b/src/png/zlib/contrib/dotzlib/DotZLib/AssemblyInfo.cs similarity index 100% rename from xs/src/png/zlib/contrib/dotzlib/DotZLib/AssemblyInfo.cs rename to src/png/zlib/contrib/dotzlib/DotZLib/AssemblyInfo.cs diff --git a/xs/src/png/zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs b/src/png/zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs similarity index 100% rename from xs/src/png/zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs rename to src/png/zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs diff --git a/xs/src/png/zlib/contrib/dotzlib/DotZLib/CircularBuffer.cs b/src/png/zlib/contrib/dotzlib/DotZLib/CircularBuffer.cs similarity index 100% rename from xs/src/png/zlib/contrib/dotzlib/DotZLib/CircularBuffer.cs rename to src/png/zlib/contrib/dotzlib/DotZLib/CircularBuffer.cs diff --git a/xs/src/png/zlib/contrib/dotzlib/DotZLib/CodecBase.cs b/src/png/zlib/contrib/dotzlib/DotZLib/CodecBase.cs similarity index 100% rename from xs/src/png/zlib/contrib/dotzlib/DotZLib/CodecBase.cs rename to src/png/zlib/contrib/dotzlib/DotZLib/CodecBase.cs diff --git a/xs/src/png/zlib/contrib/dotzlib/DotZLib/Deflater.cs b/src/png/zlib/contrib/dotzlib/DotZLib/Deflater.cs similarity index 100% rename from xs/src/png/zlib/contrib/dotzlib/DotZLib/Deflater.cs rename to src/png/zlib/contrib/dotzlib/DotZLib/Deflater.cs diff --git a/xs/src/png/zlib/contrib/dotzlib/DotZLib/DotZLib.cs b/src/png/zlib/contrib/dotzlib/DotZLib/DotZLib.cs similarity index 100% rename from xs/src/png/zlib/contrib/dotzlib/DotZLib/DotZLib.cs rename to src/png/zlib/contrib/dotzlib/DotZLib/DotZLib.cs diff --git a/xs/src/png/zlib/contrib/dotzlib/DotZLib/DotZLib.csproj b/src/png/zlib/contrib/dotzlib/DotZLib/DotZLib.csproj similarity index 100% rename from xs/src/png/zlib/contrib/dotzlib/DotZLib/DotZLib.csproj rename to src/png/zlib/contrib/dotzlib/DotZLib/DotZLib.csproj diff --git a/xs/src/png/zlib/contrib/dotzlib/DotZLib/GZipStream.cs b/src/png/zlib/contrib/dotzlib/DotZLib/GZipStream.cs similarity index 100% rename from xs/src/png/zlib/contrib/dotzlib/DotZLib/GZipStream.cs rename to src/png/zlib/contrib/dotzlib/DotZLib/GZipStream.cs diff --git a/xs/src/png/zlib/contrib/dotzlib/DotZLib/Inflater.cs b/src/png/zlib/contrib/dotzlib/DotZLib/Inflater.cs similarity index 100% rename from xs/src/png/zlib/contrib/dotzlib/DotZLib/Inflater.cs rename to src/png/zlib/contrib/dotzlib/DotZLib/Inflater.cs diff --git a/xs/src/png/zlib/contrib/dotzlib/DotZLib/UnitTests.cs b/src/png/zlib/contrib/dotzlib/DotZLib/UnitTests.cs similarity index 100% rename from xs/src/png/zlib/contrib/dotzlib/DotZLib/UnitTests.cs rename to src/png/zlib/contrib/dotzlib/DotZLib/UnitTests.cs diff --git a/xs/src/png/zlib/contrib/dotzlib/LICENSE_1_0.txt b/src/png/zlib/contrib/dotzlib/LICENSE_1_0.txt similarity index 100% rename from xs/src/png/zlib/contrib/dotzlib/LICENSE_1_0.txt rename to src/png/zlib/contrib/dotzlib/LICENSE_1_0.txt diff --git a/xs/src/png/zlib/contrib/dotzlib/readme.txt b/src/png/zlib/contrib/dotzlib/readme.txt similarity index 100% rename from xs/src/png/zlib/contrib/dotzlib/readme.txt rename to src/png/zlib/contrib/dotzlib/readme.txt diff --git a/xs/src/png/zlib/contrib/gcc_gvmat64/gvmat64.S b/src/png/zlib/contrib/gcc_gvmat64/gvmat64.S similarity index 100% rename from xs/src/png/zlib/contrib/gcc_gvmat64/gvmat64.S rename to src/png/zlib/contrib/gcc_gvmat64/gvmat64.S diff --git a/xs/src/png/zlib/contrib/infback9/README b/src/png/zlib/contrib/infback9/README similarity index 100% rename from xs/src/png/zlib/contrib/infback9/README rename to src/png/zlib/contrib/infback9/README diff --git a/xs/src/png/zlib/contrib/infback9/infback9.c b/src/png/zlib/contrib/infback9/infback9.c similarity index 100% rename from xs/src/png/zlib/contrib/infback9/infback9.c rename to src/png/zlib/contrib/infback9/infback9.c diff --git a/xs/src/png/zlib/contrib/infback9/infback9.h b/src/png/zlib/contrib/infback9/infback9.h similarity index 100% rename from xs/src/png/zlib/contrib/infback9/infback9.h rename to src/png/zlib/contrib/infback9/infback9.h diff --git a/xs/src/png/zlib/contrib/infback9/inffix9.h b/src/png/zlib/contrib/infback9/inffix9.h similarity index 100% rename from xs/src/png/zlib/contrib/infback9/inffix9.h rename to src/png/zlib/contrib/infback9/inffix9.h diff --git a/xs/src/png/zlib/contrib/infback9/inflate9.h b/src/png/zlib/contrib/infback9/inflate9.h similarity index 100% rename from xs/src/png/zlib/contrib/infback9/inflate9.h rename to src/png/zlib/contrib/infback9/inflate9.h diff --git a/xs/src/png/zlib/contrib/infback9/inftree9.c b/src/png/zlib/contrib/infback9/inftree9.c similarity index 100% rename from xs/src/png/zlib/contrib/infback9/inftree9.c rename to src/png/zlib/contrib/infback9/inftree9.c diff --git a/xs/src/png/zlib/contrib/infback9/inftree9.h b/src/png/zlib/contrib/infback9/inftree9.h similarity index 100% rename from xs/src/png/zlib/contrib/infback9/inftree9.h rename to src/png/zlib/contrib/infback9/inftree9.h diff --git a/xs/src/png/zlib/contrib/inflate86/inffas86.c b/src/png/zlib/contrib/inflate86/inffas86.c similarity index 100% rename from xs/src/png/zlib/contrib/inflate86/inffas86.c rename to src/png/zlib/contrib/inflate86/inffas86.c diff --git a/xs/src/png/zlib/contrib/inflate86/inffast.S b/src/png/zlib/contrib/inflate86/inffast.S similarity index 100% rename from xs/src/png/zlib/contrib/inflate86/inffast.S rename to src/png/zlib/contrib/inflate86/inffast.S diff --git a/xs/src/png/zlib/contrib/iostream/test.cpp b/src/png/zlib/contrib/iostream/test.cpp similarity index 100% rename from xs/src/png/zlib/contrib/iostream/test.cpp rename to src/png/zlib/contrib/iostream/test.cpp diff --git a/xs/src/png/zlib/contrib/iostream/zfstream.cpp b/src/png/zlib/contrib/iostream/zfstream.cpp similarity index 100% rename from xs/src/png/zlib/contrib/iostream/zfstream.cpp rename to src/png/zlib/contrib/iostream/zfstream.cpp diff --git a/xs/src/png/zlib/contrib/iostream/zfstream.h b/src/png/zlib/contrib/iostream/zfstream.h similarity index 100% rename from xs/src/png/zlib/contrib/iostream/zfstream.h rename to src/png/zlib/contrib/iostream/zfstream.h diff --git a/xs/src/png/zlib/contrib/iostream2/zstream.h b/src/png/zlib/contrib/iostream2/zstream.h similarity index 100% rename from xs/src/png/zlib/contrib/iostream2/zstream.h rename to src/png/zlib/contrib/iostream2/zstream.h diff --git a/xs/src/png/zlib/contrib/iostream2/zstream_test.cpp b/src/png/zlib/contrib/iostream2/zstream_test.cpp similarity index 100% rename from xs/src/png/zlib/contrib/iostream2/zstream_test.cpp rename to src/png/zlib/contrib/iostream2/zstream_test.cpp diff --git a/xs/src/png/zlib/contrib/iostream3/README b/src/png/zlib/contrib/iostream3/README similarity index 100% rename from xs/src/png/zlib/contrib/iostream3/README rename to src/png/zlib/contrib/iostream3/README diff --git a/xs/src/png/zlib/contrib/iostream3/TODO b/src/png/zlib/contrib/iostream3/TODO similarity index 100% rename from xs/src/png/zlib/contrib/iostream3/TODO rename to src/png/zlib/contrib/iostream3/TODO diff --git a/xs/src/png/zlib/contrib/iostream3/test.cc b/src/png/zlib/contrib/iostream3/test.cc similarity index 100% rename from xs/src/png/zlib/contrib/iostream3/test.cc rename to src/png/zlib/contrib/iostream3/test.cc diff --git a/xs/src/png/zlib/contrib/iostream3/zfstream.cc b/src/png/zlib/contrib/iostream3/zfstream.cc similarity index 100% rename from xs/src/png/zlib/contrib/iostream3/zfstream.cc rename to src/png/zlib/contrib/iostream3/zfstream.cc diff --git a/xs/src/png/zlib/contrib/iostream3/zfstream.h b/src/png/zlib/contrib/iostream3/zfstream.h similarity index 100% rename from xs/src/png/zlib/contrib/iostream3/zfstream.h rename to src/png/zlib/contrib/iostream3/zfstream.h diff --git a/xs/src/png/zlib/contrib/masmx64/bld_ml64.bat b/src/png/zlib/contrib/masmx64/bld_ml64.bat similarity index 100% rename from xs/src/png/zlib/contrib/masmx64/bld_ml64.bat rename to src/png/zlib/contrib/masmx64/bld_ml64.bat diff --git a/xs/src/png/zlib/contrib/masmx64/gvmat64.asm b/src/png/zlib/contrib/masmx64/gvmat64.asm similarity index 100% rename from xs/src/png/zlib/contrib/masmx64/gvmat64.asm rename to src/png/zlib/contrib/masmx64/gvmat64.asm diff --git a/xs/src/png/zlib/contrib/masmx64/inffas8664.c b/src/png/zlib/contrib/masmx64/inffas8664.c similarity index 100% rename from xs/src/png/zlib/contrib/masmx64/inffas8664.c rename to src/png/zlib/contrib/masmx64/inffas8664.c diff --git a/xs/src/png/zlib/contrib/masmx64/inffasx64.asm b/src/png/zlib/contrib/masmx64/inffasx64.asm similarity index 100% rename from xs/src/png/zlib/contrib/masmx64/inffasx64.asm rename to src/png/zlib/contrib/masmx64/inffasx64.asm diff --git a/xs/src/png/zlib/contrib/masmx64/readme.txt b/src/png/zlib/contrib/masmx64/readme.txt similarity index 100% rename from xs/src/png/zlib/contrib/masmx64/readme.txt rename to src/png/zlib/contrib/masmx64/readme.txt diff --git a/xs/src/png/zlib/contrib/masmx86/bld_ml32.bat b/src/png/zlib/contrib/masmx86/bld_ml32.bat similarity index 100% rename from xs/src/png/zlib/contrib/masmx86/bld_ml32.bat rename to src/png/zlib/contrib/masmx86/bld_ml32.bat diff --git a/xs/src/png/zlib/contrib/masmx86/inffas32.asm b/src/png/zlib/contrib/masmx86/inffas32.asm similarity index 100% rename from xs/src/png/zlib/contrib/masmx86/inffas32.asm rename to src/png/zlib/contrib/masmx86/inffas32.asm diff --git a/xs/src/png/zlib/contrib/masmx86/match686.asm b/src/png/zlib/contrib/masmx86/match686.asm similarity index 100% rename from xs/src/png/zlib/contrib/masmx86/match686.asm rename to src/png/zlib/contrib/masmx86/match686.asm diff --git a/xs/src/png/zlib/contrib/masmx86/readme.txt b/src/png/zlib/contrib/masmx86/readme.txt similarity index 100% rename from xs/src/png/zlib/contrib/masmx86/readme.txt rename to src/png/zlib/contrib/masmx86/readme.txt diff --git a/xs/src/png/zlib/contrib/minizip/Makefile b/src/png/zlib/contrib/minizip/Makefile similarity index 100% rename from xs/src/png/zlib/contrib/minizip/Makefile rename to src/png/zlib/contrib/minizip/Makefile diff --git a/xs/src/png/zlib/contrib/minizip/Makefile.am b/src/png/zlib/contrib/minizip/Makefile.am similarity index 100% rename from xs/src/png/zlib/contrib/minizip/Makefile.am rename to src/png/zlib/contrib/minizip/Makefile.am diff --git a/xs/src/png/zlib/contrib/minizip/MiniZip64_Changes.txt b/src/png/zlib/contrib/minizip/MiniZip64_Changes.txt similarity index 100% rename from xs/src/png/zlib/contrib/minizip/MiniZip64_Changes.txt rename to src/png/zlib/contrib/minizip/MiniZip64_Changes.txt diff --git a/xs/src/png/zlib/contrib/minizip/MiniZip64_info.txt b/src/png/zlib/contrib/minizip/MiniZip64_info.txt similarity index 100% rename from xs/src/png/zlib/contrib/minizip/MiniZip64_info.txt rename to src/png/zlib/contrib/minizip/MiniZip64_info.txt diff --git a/xs/src/png/zlib/contrib/minizip/configure.ac b/src/png/zlib/contrib/minizip/configure.ac similarity index 100% rename from xs/src/png/zlib/contrib/minizip/configure.ac rename to src/png/zlib/contrib/minizip/configure.ac diff --git a/xs/src/png/zlib/contrib/minizip/crypt.h b/src/png/zlib/contrib/minizip/crypt.h similarity index 100% rename from xs/src/png/zlib/contrib/minizip/crypt.h rename to src/png/zlib/contrib/minizip/crypt.h diff --git a/xs/src/png/zlib/contrib/minizip/ioapi.c b/src/png/zlib/contrib/minizip/ioapi.c similarity index 100% rename from xs/src/png/zlib/contrib/minizip/ioapi.c rename to src/png/zlib/contrib/minizip/ioapi.c diff --git a/xs/src/png/zlib/contrib/minizip/ioapi.h b/src/png/zlib/contrib/minizip/ioapi.h similarity index 100% rename from xs/src/png/zlib/contrib/minizip/ioapi.h rename to src/png/zlib/contrib/minizip/ioapi.h diff --git a/xs/src/png/zlib/contrib/minizip/iowin32.c b/src/png/zlib/contrib/minizip/iowin32.c similarity index 100% rename from xs/src/png/zlib/contrib/minizip/iowin32.c rename to src/png/zlib/contrib/minizip/iowin32.c diff --git a/xs/src/png/zlib/contrib/minizip/iowin32.h b/src/png/zlib/contrib/minizip/iowin32.h similarity index 100% rename from xs/src/png/zlib/contrib/minizip/iowin32.h rename to src/png/zlib/contrib/minizip/iowin32.h diff --git a/xs/src/png/zlib/contrib/minizip/make_vms.com b/src/png/zlib/contrib/minizip/make_vms.com similarity index 100% rename from xs/src/png/zlib/contrib/minizip/make_vms.com rename to src/png/zlib/contrib/minizip/make_vms.com diff --git a/xs/src/png/zlib/contrib/minizip/miniunz.c b/src/png/zlib/contrib/minizip/miniunz.c similarity index 100% rename from xs/src/png/zlib/contrib/minizip/miniunz.c rename to src/png/zlib/contrib/minizip/miniunz.c diff --git a/xs/src/png/zlib/contrib/minizip/miniunzip.1 b/src/png/zlib/contrib/minizip/miniunzip.1 similarity index 100% rename from xs/src/png/zlib/contrib/minizip/miniunzip.1 rename to src/png/zlib/contrib/minizip/miniunzip.1 diff --git a/xs/src/png/zlib/contrib/minizip/minizip.1 b/src/png/zlib/contrib/minizip/minizip.1 similarity index 100% rename from xs/src/png/zlib/contrib/minizip/minizip.1 rename to src/png/zlib/contrib/minizip/minizip.1 diff --git a/xs/src/png/zlib/contrib/minizip/minizip.c b/src/png/zlib/contrib/minizip/minizip.c similarity index 100% rename from xs/src/png/zlib/contrib/minizip/minizip.c rename to src/png/zlib/contrib/minizip/minizip.c diff --git a/xs/src/png/zlib/contrib/minizip/minizip.pc.in b/src/png/zlib/contrib/minizip/minizip.pc.in similarity index 100% rename from xs/src/png/zlib/contrib/minizip/minizip.pc.in rename to src/png/zlib/contrib/minizip/minizip.pc.in diff --git a/xs/src/png/zlib/contrib/minizip/mztools.c b/src/png/zlib/contrib/minizip/mztools.c similarity index 100% rename from xs/src/png/zlib/contrib/minizip/mztools.c rename to src/png/zlib/contrib/minizip/mztools.c diff --git a/xs/src/png/zlib/contrib/minizip/mztools.h b/src/png/zlib/contrib/minizip/mztools.h similarity index 100% rename from xs/src/png/zlib/contrib/minizip/mztools.h rename to src/png/zlib/contrib/minizip/mztools.h diff --git a/xs/src/png/zlib/contrib/minizip/unzip.c b/src/png/zlib/contrib/minizip/unzip.c similarity index 100% rename from xs/src/png/zlib/contrib/minizip/unzip.c rename to src/png/zlib/contrib/minizip/unzip.c diff --git a/xs/src/png/zlib/contrib/minizip/unzip.h b/src/png/zlib/contrib/minizip/unzip.h similarity index 100% rename from xs/src/png/zlib/contrib/minizip/unzip.h rename to src/png/zlib/contrib/minizip/unzip.h diff --git a/xs/src/png/zlib/contrib/minizip/zip.c b/src/png/zlib/contrib/minizip/zip.c similarity index 100% rename from xs/src/png/zlib/contrib/minizip/zip.c rename to src/png/zlib/contrib/minizip/zip.c diff --git a/xs/src/png/zlib/contrib/minizip/zip.h b/src/png/zlib/contrib/minizip/zip.h similarity index 100% rename from xs/src/png/zlib/contrib/minizip/zip.h rename to src/png/zlib/contrib/minizip/zip.h diff --git a/xs/src/png/zlib/contrib/pascal/example.pas b/src/png/zlib/contrib/pascal/example.pas similarity index 100% rename from xs/src/png/zlib/contrib/pascal/example.pas rename to src/png/zlib/contrib/pascal/example.pas diff --git a/xs/src/png/zlib/contrib/pascal/readme.txt b/src/png/zlib/contrib/pascal/readme.txt similarity index 100% rename from xs/src/png/zlib/contrib/pascal/readme.txt rename to src/png/zlib/contrib/pascal/readme.txt diff --git a/xs/src/png/zlib/contrib/pascal/zlibd32.mak b/src/png/zlib/contrib/pascal/zlibd32.mak similarity index 100% rename from xs/src/png/zlib/contrib/pascal/zlibd32.mak rename to src/png/zlib/contrib/pascal/zlibd32.mak diff --git a/xs/src/png/zlib/contrib/pascal/zlibpas.pas b/src/png/zlib/contrib/pascal/zlibpas.pas similarity index 100% rename from xs/src/png/zlib/contrib/pascal/zlibpas.pas rename to src/png/zlib/contrib/pascal/zlibpas.pas diff --git a/xs/src/png/zlib/contrib/puff/Makefile b/src/png/zlib/contrib/puff/Makefile similarity index 100% rename from xs/src/png/zlib/contrib/puff/Makefile rename to src/png/zlib/contrib/puff/Makefile diff --git a/xs/src/png/zlib/contrib/puff/README b/src/png/zlib/contrib/puff/README similarity index 100% rename from xs/src/png/zlib/contrib/puff/README rename to src/png/zlib/contrib/puff/README diff --git a/xs/src/png/zlib/contrib/puff/puff.c b/src/png/zlib/contrib/puff/puff.c similarity index 100% rename from xs/src/png/zlib/contrib/puff/puff.c rename to src/png/zlib/contrib/puff/puff.c diff --git a/xs/src/png/zlib/contrib/puff/puff.h b/src/png/zlib/contrib/puff/puff.h similarity index 100% rename from xs/src/png/zlib/contrib/puff/puff.h rename to src/png/zlib/contrib/puff/puff.h diff --git a/xs/src/png/zlib/contrib/puff/pufftest.c b/src/png/zlib/contrib/puff/pufftest.c similarity index 100% rename from xs/src/png/zlib/contrib/puff/pufftest.c rename to src/png/zlib/contrib/puff/pufftest.c diff --git a/xs/src/png/zlib/contrib/puff/zeros.raw b/src/png/zlib/contrib/puff/zeros.raw similarity index 100% rename from xs/src/png/zlib/contrib/puff/zeros.raw rename to src/png/zlib/contrib/puff/zeros.raw diff --git a/xs/src/png/zlib/contrib/testzlib/testzlib.c b/src/png/zlib/contrib/testzlib/testzlib.c similarity index 100% rename from xs/src/png/zlib/contrib/testzlib/testzlib.c rename to src/png/zlib/contrib/testzlib/testzlib.c diff --git a/xs/src/png/zlib/contrib/testzlib/testzlib.txt b/src/png/zlib/contrib/testzlib/testzlib.txt similarity index 100% rename from xs/src/png/zlib/contrib/testzlib/testzlib.txt rename to src/png/zlib/contrib/testzlib/testzlib.txt diff --git a/xs/src/png/zlib/contrib/untgz/Makefile b/src/png/zlib/contrib/untgz/Makefile similarity index 100% rename from xs/src/png/zlib/contrib/untgz/Makefile rename to src/png/zlib/contrib/untgz/Makefile diff --git a/xs/src/png/zlib/contrib/untgz/Makefile.msc b/src/png/zlib/contrib/untgz/Makefile.msc similarity index 100% rename from xs/src/png/zlib/contrib/untgz/Makefile.msc rename to src/png/zlib/contrib/untgz/Makefile.msc diff --git a/xs/src/png/zlib/contrib/untgz/untgz.c b/src/png/zlib/contrib/untgz/untgz.c similarity index 100% rename from xs/src/png/zlib/contrib/untgz/untgz.c rename to src/png/zlib/contrib/untgz/untgz.c diff --git a/xs/src/png/zlib/contrib/vstudio/readme.txt b/src/png/zlib/contrib/vstudio/readme.txt similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/readme.txt rename to src/png/zlib/contrib/vstudio/readme.txt diff --git a/xs/src/png/zlib/contrib/vstudio/vc10/miniunz.vcxproj b/src/png/zlib/contrib/vstudio/vc10/miniunz.vcxproj similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc10/miniunz.vcxproj rename to src/png/zlib/contrib/vstudio/vc10/miniunz.vcxproj diff --git a/xs/src/png/zlib/contrib/vstudio/vc10/miniunz.vcxproj.filters b/src/png/zlib/contrib/vstudio/vc10/miniunz.vcxproj.filters similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc10/miniunz.vcxproj.filters rename to src/png/zlib/contrib/vstudio/vc10/miniunz.vcxproj.filters diff --git a/xs/src/png/zlib/contrib/vstudio/vc10/minizip.vcxproj b/src/png/zlib/contrib/vstudio/vc10/minizip.vcxproj similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc10/minizip.vcxproj rename to src/png/zlib/contrib/vstudio/vc10/minizip.vcxproj diff --git a/xs/src/png/zlib/contrib/vstudio/vc10/minizip.vcxproj.filters b/src/png/zlib/contrib/vstudio/vc10/minizip.vcxproj.filters similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc10/minizip.vcxproj.filters rename to src/png/zlib/contrib/vstudio/vc10/minizip.vcxproj.filters diff --git a/xs/src/png/zlib/contrib/vstudio/vc10/testzlib.vcxproj b/src/png/zlib/contrib/vstudio/vc10/testzlib.vcxproj similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc10/testzlib.vcxproj rename to src/png/zlib/contrib/vstudio/vc10/testzlib.vcxproj diff --git a/xs/src/png/zlib/contrib/vstudio/vc10/testzlib.vcxproj.filters b/src/png/zlib/contrib/vstudio/vc10/testzlib.vcxproj.filters similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc10/testzlib.vcxproj.filters rename to src/png/zlib/contrib/vstudio/vc10/testzlib.vcxproj.filters diff --git a/xs/src/png/zlib/contrib/vstudio/vc10/testzlibdll.vcxproj b/src/png/zlib/contrib/vstudio/vc10/testzlibdll.vcxproj similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc10/testzlibdll.vcxproj rename to src/png/zlib/contrib/vstudio/vc10/testzlibdll.vcxproj diff --git a/xs/src/png/zlib/contrib/vstudio/vc10/testzlibdll.vcxproj.filters b/src/png/zlib/contrib/vstudio/vc10/testzlibdll.vcxproj.filters similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc10/testzlibdll.vcxproj.filters rename to src/png/zlib/contrib/vstudio/vc10/testzlibdll.vcxproj.filters diff --git a/xs/src/png/zlib/contrib/vstudio/vc10/zlib.rc b/src/png/zlib/contrib/vstudio/vc10/zlib.rc similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc10/zlib.rc rename to src/png/zlib/contrib/vstudio/vc10/zlib.rc diff --git a/xs/src/png/zlib/contrib/vstudio/vc10/zlibstat.vcxproj b/src/png/zlib/contrib/vstudio/vc10/zlibstat.vcxproj similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc10/zlibstat.vcxproj rename to src/png/zlib/contrib/vstudio/vc10/zlibstat.vcxproj diff --git a/xs/src/png/zlib/contrib/vstudio/vc10/zlibstat.vcxproj.filters b/src/png/zlib/contrib/vstudio/vc10/zlibstat.vcxproj.filters similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc10/zlibstat.vcxproj.filters rename to src/png/zlib/contrib/vstudio/vc10/zlibstat.vcxproj.filters diff --git a/xs/src/png/zlib/contrib/vstudio/vc10/zlibvc.def b/src/png/zlib/contrib/vstudio/vc10/zlibvc.def similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc10/zlibvc.def rename to src/png/zlib/contrib/vstudio/vc10/zlibvc.def diff --git a/xs/src/png/zlib/contrib/vstudio/vc10/zlibvc.sln b/src/png/zlib/contrib/vstudio/vc10/zlibvc.sln similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc10/zlibvc.sln rename to src/png/zlib/contrib/vstudio/vc10/zlibvc.sln diff --git a/xs/src/png/zlib/contrib/vstudio/vc10/zlibvc.vcxproj b/src/png/zlib/contrib/vstudio/vc10/zlibvc.vcxproj similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc10/zlibvc.vcxproj rename to src/png/zlib/contrib/vstudio/vc10/zlibvc.vcxproj diff --git a/xs/src/png/zlib/contrib/vstudio/vc10/zlibvc.vcxproj.filters b/src/png/zlib/contrib/vstudio/vc10/zlibvc.vcxproj.filters similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc10/zlibvc.vcxproj.filters rename to src/png/zlib/contrib/vstudio/vc10/zlibvc.vcxproj.filters diff --git a/xs/src/png/zlib/contrib/vstudio/vc11/miniunz.vcxproj b/src/png/zlib/contrib/vstudio/vc11/miniunz.vcxproj similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc11/miniunz.vcxproj rename to src/png/zlib/contrib/vstudio/vc11/miniunz.vcxproj diff --git a/xs/src/png/zlib/contrib/vstudio/vc11/minizip.vcxproj b/src/png/zlib/contrib/vstudio/vc11/minizip.vcxproj similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc11/minizip.vcxproj rename to src/png/zlib/contrib/vstudio/vc11/minizip.vcxproj diff --git a/xs/src/png/zlib/contrib/vstudio/vc11/testzlib.vcxproj b/src/png/zlib/contrib/vstudio/vc11/testzlib.vcxproj similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc11/testzlib.vcxproj rename to src/png/zlib/contrib/vstudio/vc11/testzlib.vcxproj diff --git a/xs/src/png/zlib/contrib/vstudio/vc11/testzlibdll.vcxproj b/src/png/zlib/contrib/vstudio/vc11/testzlibdll.vcxproj similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc11/testzlibdll.vcxproj rename to src/png/zlib/contrib/vstudio/vc11/testzlibdll.vcxproj diff --git a/xs/src/png/zlib/contrib/vstudio/vc11/zlib.rc b/src/png/zlib/contrib/vstudio/vc11/zlib.rc similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc11/zlib.rc rename to src/png/zlib/contrib/vstudio/vc11/zlib.rc diff --git a/xs/src/png/zlib/contrib/vstudio/vc11/zlibstat.vcxproj b/src/png/zlib/contrib/vstudio/vc11/zlibstat.vcxproj similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc11/zlibstat.vcxproj rename to src/png/zlib/contrib/vstudio/vc11/zlibstat.vcxproj diff --git a/xs/src/png/zlib/contrib/vstudio/vc11/zlibvc.def b/src/png/zlib/contrib/vstudio/vc11/zlibvc.def similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc11/zlibvc.def rename to src/png/zlib/contrib/vstudio/vc11/zlibvc.def diff --git a/xs/src/png/zlib/contrib/vstudio/vc11/zlibvc.sln b/src/png/zlib/contrib/vstudio/vc11/zlibvc.sln similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc11/zlibvc.sln rename to src/png/zlib/contrib/vstudio/vc11/zlibvc.sln diff --git a/xs/src/png/zlib/contrib/vstudio/vc11/zlibvc.vcxproj b/src/png/zlib/contrib/vstudio/vc11/zlibvc.vcxproj similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc11/zlibvc.vcxproj rename to src/png/zlib/contrib/vstudio/vc11/zlibvc.vcxproj diff --git a/xs/src/png/zlib/contrib/vstudio/vc12/miniunz.vcxproj b/src/png/zlib/contrib/vstudio/vc12/miniunz.vcxproj similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc12/miniunz.vcxproj rename to src/png/zlib/contrib/vstudio/vc12/miniunz.vcxproj diff --git a/xs/src/png/zlib/contrib/vstudio/vc12/minizip.vcxproj b/src/png/zlib/contrib/vstudio/vc12/minizip.vcxproj similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc12/minizip.vcxproj rename to src/png/zlib/contrib/vstudio/vc12/minizip.vcxproj diff --git a/xs/src/png/zlib/contrib/vstudio/vc12/testzlib.vcxproj b/src/png/zlib/contrib/vstudio/vc12/testzlib.vcxproj similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc12/testzlib.vcxproj rename to src/png/zlib/contrib/vstudio/vc12/testzlib.vcxproj diff --git a/xs/src/png/zlib/contrib/vstudio/vc12/testzlibdll.vcxproj b/src/png/zlib/contrib/vstudio/vc12/testzlibdll.vcxproj similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc12/testzlibdll.vcxproj rename to src/png/zlib/contrib/vstudio/vc12/testzlibdll.vcxproj diff --git a/xs/src/png/zlib/contrib/vstudio/vc12/zlib.rc b/src/png/zlib/contrib/vstudio/vc12/zlib.rc similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc12/zlib.rc rename to src/png/zlib/contrib/vstudio/vc12/zlib.rc diff --git a/xs/src/png/zlib/contrib/vstudio/vc12/zlibstat.vcxproj b/src/png/zlib/contrib/vstudio/vc12/zlibstat.vcxproj similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc12/zlibstat.vcxproj rename to src/png/zlib/contrib/vstudio/vc12/zlibstat.vcxproj diff --git a/xs/src/png/zlib/contrib/vstudio/vc12/zlibvc.def b/src/png/zlib/contrib/vstudio/vc12/zlibvc.def similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc12/zlibvc.def rename to src/png/zlib/contrib/vstudio/vc12/zlibvc.def diff --git a/xs/src/png/zlib/contrib/vstudio/vc12/zlibvc.sln b/src/png/zlib/contrib/vstudio/vc12/zlibvc.sln similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc12/zlibvc.sln rename to src/png/zlib/contrib/vstudio/vc12/zlibvc.sln diff --git a/xs/src/png/zlib/contrib/vstudio/vc12/zlibvc.vcxproj b/src/png/zlib/contrib/vstudio/vc12/zlibvc.vcxproj similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc12/zlibvc.vcxproj rename to src/png/zlib/contrib/vstudio/vc12/zlibvc.vcxproj diff --git a/xs/src/png/zlib/contrib/vstudio/vc14/miniunz.vcxproj b/src/png/zlib/contrib/vstudio/vc14/miniunz.vcxproj similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc14/miniunz.vcxproj rename to src/png/zlib/contrib/vstudio/vc14/miniunz.vcxproj diff --git a/xs/src/png/zlib/contrib/vstudio/vc14/minizip.vcxproj b/src/png/zlib/contrib/vstudio/vc14/minizip.vcxproj similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc14/minizip.vcxproj rename to src/png/zlib/contrib/vstudio/vc14/minizip.vcxproj diff --git a/xs/src/png/zlib/contrib/vstudio/vc14/testzlib.vcxproj b/src/png/zlib/contrib/vstudio/vc14/testzlib.vcxproj similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc14/testzlib.vcxproj rename to src/png/zlib/contrib/vstudio/vc14/testzlib.vcxproj diff --git a/xs/src/png/zlib/contrib/vstudio/vc14/testzlibdll.vcxproj b/src/png/zlib/contrib/vstudio/vc14/testzlibdll.vcxproj similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc14/testzlibdll.vcxproj rename to src/png/zlib/contrib/vstudio/vc14/testzlibdll.vcxproj diff --git a/xs/src/png/zlib/contrib/vstudio/vc14/zlib.rc b/src/png/zlib/contrib/vstudio/vc14/zlib.rc similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc14/zlib.rc rename to src/png/zlib/contrib/vstudio/vc14/zlib.rc diff --git a/xs/src/png/zlib/contrib/vstudio/vc14/zlibstat.vcxproj b/src/png/zlib/contrib/vstudio/vc14/zlibstat.vcxproj similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc14/zlibstat.vcxproj rename to src/png/zlib/contrib/vstudio/vc14/zlibstat.vcxproj diff --git a/xs/src/png/zlib/contrib/vstudio/vc14/zlibvc.def b/src/png/zlib/contrib/vstudio/vc14/zlibvc.def similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc14/zlibvc.def rename to src/png/zlib/contrib/vstudio/vc14/zlibvc.def diff --git a/xs/src/png/zlib/contrib/vstudio/vc14/zlibvc.sln b/src/png/zlib/contrib/vstudio/vc14/zlibvc.sln similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc14/zlibvc.sln rename to src/png/zlib/contrib/vstudio/vc14/zlibvc.sln diff --git a/xs/src/png/zlib/contrib/vstudio/vc14/zlibvc.vcxproj b/src/png/zlib/contrib/vstudio/vc14/zlibvc.vcxproj similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc14/zlibvc.vcxproj rename to src/png/zlib/contrib/vstudio/vc14/zlibvc.vcxproj diff --git a/xs/src/png/zlib/contrib/vstudio/vc9/miniunz.vcproj b/src/png/zlib/contrib/vstudio/vc9/miniunz.vcproj similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc9/miniunz.vcproj rename to src/png/zlib/contrib/vstudio/vc9/miniunz.vcproj diff --git a/xs/src/png/zlib/contrib/vstudio/vc9/minizip.vcproj b/src/png/zlib/contrib/vstudio/vc9/minizip.vcproj similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc9/minizip.vcproj rename to src/png/zlib/contrib/vstudio/vc9/minizip.vcproj diff --git a/xs/src/png/zlib/contrib/vstudio/vc9/testzlib.vcproj b/src/png/zlib/contrib/vstudio/vc9/testzlib.vcproj similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc9/testzlib.vcproj rename to src/png/zlib/contrib/vstudio/vc9/testzlib.vcproj diff --git a/xs/src/png/zlib/contrib/vstudio/vc9/testzlibdll.vcproj b/src/png/zlib/contrib/vstudio/vc9/testzlibdll.vcproj similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc9/testzlibdll.vcproj rename to src/png/zlib/contrib/vstudio/vc9/testzlibdll.vcproj diff --git a/xs/src/png/zlib/contrib/vstudio/vc9/zlib.rc b/src/png/zlib/contrib/vstudio/vc9/zlib.rc similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc9/zlib.rc rename to src/png/zlib/contrib/vstudio/vc9/zlib.rc diff --git a/xs/src/png/zlib/contrib/vstudio/vc9/zlibstat.vcproj b/src/png/zlib/contrib/vstudio/vc9/zlibstat.vcproj similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc9/zlibstat.vcproj rename to src/png/zlib/contrib/vstudio/vc9/zlibstat.vcproj diff --git a/xs/src/png/zlib/contrib/vstudio/vc9/zlibvc.def b/src/png/zlib/contrib/vstudio/vc9/zlibvc.def similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc9/zlibvc.def rename to src/png/zlib/contrib/vstudio/vc9/zlibvc.def diff --git a/xs/src/png/zlib/contrib/vstudio/vc9/zlibvc.sln b/src/png/zlib/contrib/vstudio/vc9/zlibvc.sln similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc9/zlibvc.sln rename to src/png/zlib/contrib/vstudio/vc9/zlibvc.sln diff --git a/xs/src/png/zlib/contrib/vstudio/vc9/zlibvc.vcproj b/src/png/zlib/contrib/vstudio/vc9/zlibvc.vcproj similarity index 100% rename from xs/src/png/zlib/contrib/vstudio/vc9/zlibvc.vcproj rename to src/png/zlib/contrib/vstudio/vc9/zlibvc.vcproj diff --git a/xs/src/png/zlib/crc32.c b/src/png/zlib/crc32.c similarity index 100% rename from xs/src/png/zlib/crc32.c rename to src/png/zlib/crc32.c diff --git a/xs/src/png/zlib/crc32.h b/src/png/zlib/crc32.h similarity index 100% rename from xs/src/png/zlib/crc32.h rename to src/png/zlib/crc32.h diff --git a/xs/src/png/zlib/deflate.c b/src/png/zlib/deflate.c similarity index 100% rename from xs/src/png/zlib/deflate.c rename to src/png/zlib/deflate.c diff --git a/xs/src/png/zlib/deflate.h b/src/png/zlib/deflate.h similarity index 100% rename from xs/src/png/zlib/deflate.h rename to src/png/zlib/deflate.h diff --git a/xs/src/png/zlib/gzclose.c b/src/png/zlib/gzclose.c similarity index 100% rename from xs/src/png/zlib/gzclose.c rename to src/png/zlib/gzclose.c diff --git a/xs/src/png/zlib/gzguts.h b/src/png/zlib/gzguts.h similarity index 100% rename from xs/src/png/zlib/gzguts.h rename to src/png/zlib/gzguts.h diff --git a/xs/src/png/zlib/gzlib.c b/src/png/zlib/gzlib.c similarity index 100% rename from xs/src/png/zlib/gzlib.c rename to src/png/zlib/gzlib.c diff --git a/xs/src/png/zlib/gzread.c b/src/png/zlib/gzread.c similarity index 100% rename from xs/src/png/zlib/gzread.c rename to src/png/zlib/gzread.c diff --git a/xs/src/png/zlib/gzwrite.c b/src/png/zlib/gzwrite.c similarity index 100% rename from xs/src/png/zlib/gzwrite.c rename to src/png/zlib/gzwrite.c diff --git a/xs/src/png/zlib/infback.c b/src/png/zlib/infback.c similarity index 100% rename from xs/src/png/zlib/infback.c rename to src/png/zlib/infback.c diff --git a/xs/src/png/zlib/inffast.c b/src/png/zlib/inffast.c similarity index 100% rename from xs/src/png/zlib/inffast.c rename to src/png/zlib/inffast.c diff --git a/xs/src/png/zlib/inffast.h b/src/png/zlib/inffast.h similarity index 100% rename from xs/src/png/zlib/inffast.h rename to src/png/zlib/inffast.h diff --git a/xs/src/png/zlib/inffixed.h b/src/png/zlib/inffixed.h similarity index 100% rename from xs/src/png/zlib/inffixed.h rename to src/png/zlib/inffixed.h diff --git a/xs/src/png/zlib/inflate.c b/src/png/zlib/inflate.c similarity index 100% rename from xs/src/png/zlib/inflate.c rename to src/png/zlib/inflate.c diff --git a/xs/src/png/zlib/inflate.h b/src/png/zlib/inflate.h similarity index 100% rename from xs/src/png/zlib/inflate.h rename to src/png/zlib/inflate.h diff --git a/xs/src/png/zlib/inftrees.c b/src/png/zlib/inftrees.c similarity index 100% rename from xs/src/png/zlib/inftrees.c rename to src/png/zlib/inftrees.c diff --git a/xs/src/png/zlib/inftrees.h b/src/png/zlib/inftrees.h similarity index 100% rename from xs/src/png/zlib/inftrees.h rename to src/png/zlib/inftrees.h diff --git a/xs/src/png/zlib/make_vms.com b/src/png/zlib/make_vms.com similarity index 100% rename from xs/src/png/zlib/make_vms.com rename to src/png/zlib/make_vms.com diff --git a/xs/src/png/zlib/msdos/Makefile.bor b/src/png/zlib/msdos/Makefile.bor similarity index 100% rename from xs/src/png/zlib/msdos/Makefile.bor rename to src/png/zlib/msdos/Makefile.bor diff --git a/xs/src/png/zlib/msdos/Makefile.dj2 b/src/png/zlib/msdos/Makefile.dj2 similarity index 100% rename from xs/src/png/zlib/msdos/Makefile.dj2 rename to src/png/zlib/msdos/Makefile.dj2 diff --git a/xs/src/png/zlib/msdos/Makefile.emx b/src/png/zlib/msdos/Makefile.emx similarity index 100% rename from xs/src/png/zlib/msdos/Makefile.emx rename to src/png/zlib/msdos/Makefile.emx diff --git a/xs/src/png/zlib/msdos/Makefile.msc b/src/png/zlib/msdos/Makefile.msc similarity index 100% rename from xs/src/png/zlib/msdos/Makefile.msc rename to src/png/zlib/msdos/Makefile.msc diff --git a/xs/src/png/zlib/msdos/Makefile.tc b/src/png/zlib/msdos/Makefile.tc similarity index 100% rename from xs/src/png/zlib/msdos/Makefile.tc rename to src/png/zlib/msdos/Makefile.tc diff --git a/xs/src/png/zlib/nintendods/Makefile b/src/png/zlib/nintendods/Makefile similarity index 100% rename from xs/src/png/zlib/nintendods/Makefile rename to src/png/zlib/nintendods/Makefile diff --git a/xs/src/png/zlib/nintendods/README b/src/png/zlib/nintendods/README similarity index 100% rename from xs/src/png/zlib/nintendods/README rename to src/png/zlib/nintendods/README diff --git a/xs/src/png/zlib/old/Makefile.emx b/src/png/zlib/old/Makefile.emx similarity index 100% rename from xs/src/png/zlib/old/Makefile.emx rename to src/png/zlib/old/Makefile.emx diff --git a/xs/src/png/zlib/old/Makefile.riscos b/src/png/zlib/old/Makefile.riscos similarity index 100% rename from xs/src/png/zlib/old/Makefile.riscos rename to src/png/zlib/old/Makefile.riscos diff --git a/xs/src/png/zlib/old/README b/src/png/zlib/old/README similarity index 100% rename from xs/src/png/zlib/old/README rename to src/png/zlib/old/README diff --git a/xs/src/png/zlib/old/descrip.mms b/src/png/zlib/old/descrip.mms similarity index 100% rename from xs/src/png/zlib/old/descrip.mms rename to src/png/zlib/old/descrip.mms diff --git a/xs/src/png/zlib/old/os2/Makefile.os2 b/src/png/zlib/old/os2/Makefile.os2 similarity index 100% rename from xs/src/png/zlib/old/os2/Makefile.os2 rename to src/png/zlib/old/os2/Makefile.os2 diff --git a/xs/src/png/zlib/old/os2/zlib.def b/src/png/zlib/old/os2/zlib.def similarity index 100% rename from xs/src/png/zlib/old/os2/zlib.def rename to src/png/zlib/old/os2/zlib.def diff --git a/xs/src/png/zlib/old/visual-basic.txt b/src/png/zlib/old/visual-basic.txt similarity index 100% rename from xs/src/png/zlib/old/visual-basic.txt rename to src/png/zlib/old/visual-basic.txt diff --git a/xs/src/png/zlib/os400/README400 b/src/png/zlib/os400/README400 similarity index 100% rename from xs/src/png/zlib/os400/README400 rename to src/png/zlib/os400/README400 diff --git a/xs/src/png/zlib/os400/bndsrc b/src/png/zlib/os400/bndsrc similarity index 100% rename from xs/src/png/zlib/os400/bndsrc rename to src/png/zlib/os400/bndsrc diff --git a/xs/src/png/zlib/os400/make.sh b/src/png/zlib/os400/make.sh similarity index 100% rename from xs/src/png/zlib/os400/make.sh rename to src/png/zlib/os400/make.sh diff --git a/xs/src/png/zlib/os400/zlib.inc b/src/png/zlib/os400/zlib.inc similarity index 100% rename from xs/src/png/zlib/os400/zlib.inc rename to src/png/zlib/os400/zlib.inc diff --git a/xs/src/png/zlib/qnx/package.qpg b/src/png/zlib/qnx/package.qpg similarity index 100% rename from xs/src/png/zlib/qnx/package.qpg rename to src/png/zlib/qnx/package.qpg diff --git a/xs/src/png/zlib/treebuild.xml b/src/png/zlib/treebuild.xml similarity index 100% rename from xs/src/png/zlib/treebuild.xml rename to src/png/zlib/treebuild.xml diff --git a/xs/src/png/zlib/trees.c b/src/png/zlib/trees.c similarity index 100% rename from xs/src/png/zlib/trees.c rename to src/png/zlib/trees.c diff --git a/xs/src/png/zlib/trees.h b/src/png/zlib/trees.h similarity index 100% rename from xs/src/png/zlib/trees.h rename to src/png/zlib/trees.h diff --git a/xs/src/png/zlib/uncompr.c b/src/png/zlib/uncompr.c similarity index 100% rename from xs/src/png/zlib/uncompr.c rename to src/png/zlib/uncompr.c diff --git a/xs/src/png/zlib/watcom/watcom_f.mak b/src/png/zlib/watcom/watcom_f.mak similarity index 100% rename from xs/src/png/zlib/watcom/watcom_f.mak rename to src/png/zlib/watcom/watcom_f.mak diff --git a/xs/src/png/zlib/watcom/watcom_l.mak b/src/png/zlib/watcom/watcom_l.mak similarity index 100% rename from xs/src/png/zlib/watcom/watcom_l.mak rename to src/png/zlib/watcom/watcom_l.mak diff --git a/xs/src/png/zlib/win32/DLL_FAQ.txt b/src/png/zlib/win32/DLL_FAQ.txt similarity index 100% rename from xs/src/png/zlib/win32/DLL_FAQ.txt rename to src/png/zlib/win32/DLL_FAQ.txt diff --git a/xs/src/png/zlib/win32/Makefile.bor b/src/png/zlib/win32/Makefile.bor similarity index 100% rename from xs/src/png/zlib/win32/Makefile.bor rename to src/png/zlib/win32/Makefile.bor diff --git a/xs/src/png/zlib/win32/Makefile.gcc b/src/png/zlib/win32/Makefile.gcc similarity index 100% rename from xs/src/png/zlib/win32/Makefile.gcc rename to src/png/zlib/win32/Makefile.gcc diff --git a/xs/src/png/zlib/win32/Makefile.msc b/src/png/zlib/win32/Makefile.msc similarity index 100% rename from xs/src/png/zlib/win32/Makefile.msc rename to src/png/zlib/win32/Makefile.msc diff --git a/xs/src/png/zlib/win32/README-WIN32.txt b/src/png/zlib/win32/README-WIN32.txt similarity index 100% rename from xs/src/png/zlib/win32/README-WIN32.txt rename to src/png/zlib/win32/README-WIN32.txt diff --git a/xs/src/png/zlib/win32/VisualC.txt b/src/png/zlib/win32/VisualC.txt similarity index 100% rename from xs/src/png/zlib/win32/VisualC.txt rename to src/png/zlib/win32/VisualC.txt diff --git a/xs/src/png/zlib/win32/zlib.def b/src/png/zlib/win32/zlib.def similarity index 100% rename from xs/src/png/zlib/win32/zlib.def rename to src/png/zlib/win32/zlib.def diff --git a/xs/src/png/zlib/win32/zlib1.rc b/src/png/zlib/win32/zlib1.rc similarity index 100% rename from xs/src/png/zlib/win32/zlib1.rc rename to src/png/zlib/win32/zlib1.rc diff --git a/xs/src/png/zlib/zconf.h.cmakein b/src/png/zlib/zconf.h.cmakein similarity index 100% rename from xs/src/png/zlib/zconf.h.cmakein rename to src/png/zlib/zconf.h.cmakein diff --git a/xs/src/png/zlib/zconf.h.in b/src/png/zlib/zconf.h.in similarity index 100% rename from xs/src/png/zlib/zconf.h.in rename to src/png/zlib/zconf.h.in diff --git a/xs/src/png/zlib/zconf.h.included b/src/png/zlib/zconf.h.included similarity index 100% rename from xs/src/png/zlib/zconf.h.included rename to src/png/zlib/zconf.h.included diff --git a/xs/src/png/zlib/zlib.3 b/src/png/zlib/zlib.3 similarity index 100% rename from xs/src/png/zlib/zlib.3 rename to src/png/zlib/zlib.3 diff --git a/xs/src/png/zlib/zlib.3.pdf b/src/png/zlib/zlib.3.pdf similarity index 100% rename from xs/src/png/zlib/zlib.3.pdf rename to src/png/zlib/zlib.3.pdf diff --git a/xs/src/png/zlib/zlib.h b/src/png/zlib/zlib.h similarity index 100% rename from xs/src/png/zlib/zlib.h rename to src/png/zlib/zlib.h diff --git a/xs/src/png/zlib/zlib.map b/src/png/zlib/zlib.map similarity index 100% rename from xs/src/png/zlib/zlib.map rename to src/png/zlib/zlib.map diff --git a/xs/src/png/zlib/zlib.pc.cmakein b/src/png/zlib/zlib.pc.cmakein similarity index 100% rename from xs/src/png/zlib/zlib.pc.cmakein rename to src/png/zlib/zlib.pc.cmakein diff --git a/xs/src/png/zlib/zlib.pc.in b/src/png/zlib/zlib.pc.in similarity index 100% rename from xs/src/png/zlib/zlib.pc.in rename to src/png/zlib/zlib.pc.in diff --git a/xs/src/png/zlib/zlib2ansi b/src/png/zlib/zlib2ansi similarity index 100% rename from xs/src/png/zlib/zlib2ansi rename to src/png/zlib/zlib2ansi diff --git a/xs/src/png/zlib/zutil.c b/src/png/zlib/zutil.c similarity index 100% rename from xs/src/png/zlib/zutil.c rename to src/png/zlib/zutil.c diff --git a/xs/src/png/zlib/zutil.h b/src/png/zlib/zutil.h similarity index 100% rename from xs/src/png/zlib/zutil.h rename to src/png/zlib/zutil.h diff --git a/src/poly2tri/CMakeLists.txt b/src/poly2tri/CMakeLists.txt new file mode 100644 index 0000000000..3cdff1221d --- /dev/null +++ b/src/poly2tri/CMakeLists.txt @@ -0,0 +1,17 @@ +project(poly2tri) +cmake_minimum_required(VERSION 2.6) + +add_library(poly2tri STATIC + common/shapes.cc + common/shapes.h + common/utils.h + poly2tri.h + sweep/advancing_front.cc + sweep/advancing_front.h + sweep/cdt.cc + sweep/cdt.h + sweep/sweep.cc + sweep/sweep.h + sweep/sweep_context.cc + sweep/sweep_context.h +) diff --git a/xs/src/poly2tri/common/shapes.cc b/src/poly2tri/common/shapes.cc similarity index 100% rename from xs/src/poly2tri/common/shapes.cc rename to src/poly2tri/common/shapes.cc diff --git a/xs/src/poly2tri/common/shapes.h b/src/poly2tri/common/shapes.h similarity index 100% rename from xs/src/poly2tri/common/shapes.h rename to src/poly2tri/common/shapes.h diff --git a/xs/src/poly2tri/common/utils.h b/src/poly2tri/common/utils.h similarity index 100% rename from xs/src/poly2tri/common/utils.h rename to src/poly2tri/common/utils.h diff --git a/xs/src/poly2tri/poly2tri.h b/src/poly2tri/poly2tri.h similarity index 100% rename from xs/src/poly2tri/poly2tri.h rename to src/poly2tri/poly2tri.h diff --git a/xs/src/poly2tri/sweep/advancing_front.cc b/src/poly2tri/sweep/advancing_front.cc similarity index 100% rename from xs/src/poly2tri/sweep/advancing_front.cc rename to src/poly2tri/sweep/advancing_front.cc diff --git a/xs/src/poly2tri/sweep/advancing_front.h b/src/poly2tri/sweep/advancing_front.h similarity index 100% rename from xs/src/poly2tri/sweep/advancing_front.h rename to src/poly2tri/sweep/advancing_front.h diff --git a/xs/src/poly2tri/sweep/cdt.cc b/src/poly2tri/sweep/cdt.cc similarity index 100% rename from xs/src/poly2tri/sweep/cdt.cc rename to src/poly2tri/sweep/cdt.cc diff --git a/xs/src/poly2tri/sweep/cdt.h b/src/poly2tri/sweep/cdt.h similarity index 100% rename from xs/src/poly2tri/sweep/cdt.h rename to src/poly2tri/sweep/cdt.h diff --git a/xs/src/poly2tri/sweep/sweep.cc b/src/poly2tri/sweep/sweep.cc similarity index 100% rename from xs/src/poly2tri/sweep/sweep.cc rename to src/poly2tri/sweep/sweep.cc diff --git a/xs/src/poly2tri/sweep/sweep.h b/src/poly2tri/sweep/sweep.h similarity index 100% rename from xs/src/poly2tri/sweep/sweep.h rename to src/poly2tri/sweep/sweep.h diff --git a/xs/src/poly2tri/sweep/sweep_context.cc b/src/poly2tri/sweep/sweep_context.cc similarity index 100% rename from xs/src/poly2tri/sweep/sweep_context.cc rename to src/poly2tri/sweep/sweep_context.cc diff --git a/xs/src/poly2tri/sweep/sweep_context.h b/src/poly2tri/sweep/sweep_context.h similarity index 100% rename from xs/src/poly2tri/sweep/sweep_context.h rename to src/poly2tri/sweep/sweep_context.h diff --git a/src/polypartition/CMakeLists.txt b/src/polypartition/CMakeLists.txt new file mode 100644 index 0000000000..07b92840b8 --- /dev/null +++ b/src/polypartition/CMakeLists.txt @@ -0,0 +1,7 @@ +project(polypartition) +cmake_minimum_required(VERSION 2.6) + +add_library(polypartition STATIC + polypartition.cpp + polypartition.h +) diff --git a/xs/src/polypartition.cpp b/src/polypartition/polypartition.cpp similarity index 96% rename from xs/src/polypartition.cpp rename to src/polypartition/polypartition.cpp index 700cd09743..9c59172514 100644 --- a/xs/src/polypartition.cpp +++ b/src/polypartition/polypartition.cpp @@ -1,1563 +1,1563 @@ -//Copyright (C) 2011 by Ivan Fratric -// -//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. - - -#include -#include -#include -#include -#include -#include - -using namespace std; - -#include "polypartition.h" - -#define TPPL_VERTEXTYPE_REGULAR 0 -#define TPPL_VERTEXTYPE_START 1 -#define TPPL_VERTEXTYPE_END 2 -#define TPPL_VERTEXTYPE_SPLIT 3 -#define TPPL_VERTEXTYPE_MERGE 4 - -TPPLPoly::TPPLPoly() { - hole = false; - numpoints = 0; - points = NULL; -} - -TPPLPoly::~TPPLPoly() { - if(points) delete [] points; -} - -void TPPLPoly::Clear() { - if(points) delete [] points; - hole = false; - numpoints = 0; - points = NULL; -} - -void TPPLPoly::Init(long numpoints) { - Clear(); - this->numpoints = numpoints; - points = new TPPLPoint[numpoints]; -} - -void TPPLPoly::Triangle(TPPLPoint &p1, TPPLPoint &p2, TPPLPoint &p3) { - Init(3); - points[0] = p1; - points[1] = p2; - points[2] = p3; -} - -TPPLPoly::TPPLPoly(const TPPLPoly &src) { - hole = src.hole; - numpoints = src.numpoints; - points = new TPPLPoint[numpoints]; - memcpy(points, src.points, numpoints*sizeof(TPPLPoint)); -} - -TPPLPoly& TPPLPoly::operator=(const TPPLPoly &src) { - if(&src != this) { - Clear(); - hole = src.hole; - numpoints = src.numpoints; - points = new TPPLPoint[numpoints]; - memcpy(points, src.points, numpoints*sizeof(TPPLPoint)); - } - return *this; -} - -int TPPLPoly::GetOrientation() const { - long i1,i2; - tppl_float area = 0; - for(i1=0; i10) return TPPL_CCW; - if(area<0) return TPPL_CW; - return 0; -} - -void TPPLPoly::SetOrientation(int orientation) { - int polyorientation = GetOrientation(); - if(polyorientation&&(polyorientation!=orientation)) { - Invert(); - } -} - -void TPPLPoly::Invert() { - long i; - TPPLPoint *invpoints; - - invpoints = new TPPLPoint[numpoints]; - for(i=0;i0) return 0; - if(dot21*dot22>0) return 0; - - return 1; -} - -//removes holes from inpolys by merging them with non-holes -int TPPLPartition::RemoveHoles(list *inpolys, list *outpolys) { - list polys; - list::iterator holeiter,polyiter,iter,iter2; - long i,i2,holepointindex,polypointindex = 0; - TPPLPoint holepoint,polypoint,bestpolypoint; - TPPLPoint linep1,linep2; - TPPLPoint v1,v2; - TPPLPoly newpoly; - bool hasholes; - bool pointvisible; - bool pointfound; - - //check for trivial case (no holes) - hasholes = false; - for(iter = inpolys->begin(); iter!=inpolys->end(); ++iter) { - if(iter->IsHole()) { - hasholes = true; - break; - } - } - if(!hasholes) { - for(iter = inpolys->begin(); iter!=inpolys->end(); ++iter) { - outpolys->push_back(*iter); - } - return 1; - } - - polys = *inpolys; - - while(1) { - //find the hole point with the largest x - hasholes = false; - for(iter = polys.begin(); iter!=polys.end(); ++iter) { - if(!iter->IsHole()) continue; - - if(!hasholes) { - hasholes = true; - holeiter = iter; - holepointindex = 0; - } - - for(i=0; i < iter->GetNumPoints(); i++) { - if(iter->GetPoint(i).x > holeiter->GetPoint(holepointindex).x) { - holeiter = iter; - holepointindex = i; - } - } - } - if(!hasholes) break; - holepoint = holeiter->GetPoint(holepointindex); - - pointfound = false; - for(iter = polys.begin(); iter!=polys.end(); ++iter) { - if(iter->IsHole()) continue; - for(i=0; i < iter->GetNumPoints(); i++) { - if(iter->GetPoint(i).x <= holepoint.x) continue; - if(!InCone(iter->GetPoint((i+iter->GetNumPoints()-1)%(iter->GetNumPoints())), - iter->GetPoint(i), - iter->GetPoint((i+1)%(iter->GetNumPoints())), - holepoint)) - continue; - polypoint = iter->GetPoint(i); - if(pointfound) { - v1 = Normalize(polypoint-holepoint); - v2 = Normalize(bestpolypoint-holepoint); - if(v2.x > v1.x) continue; - } - pointvisible = true; - for(iter2 = polys.begin(); iter2!=polys.end(); ++iter2) { - if(iter2->IsHole()) continue; - for(i2=0; i2 < iter2->GetNumPoints(); i2++) { - linep1 = iter2->GetPoint(i2); - linep2 = iter2->GetPoint((i2+1)%(iter2->GetNumPoints())); - if(Intersects(holepoint,polypoint,linep1,linep2)) { - pointvisible = false; - break; - } - } - if(!pointvisible) break; - } - if(pointvisible) { - pointfound = true; - bestpolypoint = polypoint; - polyiter = iter; - polypointindex = i; - } - } - } - - if(!pointfound) return 0; - - newpoly.Init(holeiter->GetNumPoints() + polyiter->GetNumPoints() + 2); - i2 = 0; - for(i=0;i<=polypointindex;i++) { - newpoly[i2] = polyiter->GetPoint(i); - i2++; - } - for(i=0;i<=holeiter->GetNumPoints();i++) { - newpoly[i2] = holeiter->GetPoint((i+holepointindex)%holeiter->GetNumPoints()); - i2++; - } - for(i=polypointindex;iGetNumPoints();i++) { - newpoly[i2] = polyiter->GetPoint(i); - i2++; - } - - polys.erase(holeiter); - polys.erase(polyiter); - polys.push_back(newpoly); - } - - for(iter = polys.begin(); iter!=polys.end(); ++iter) { - outpolys->push_back(*iter); - } - - return 1; -} - -bool TPPLPartition::IsConvex(TPPLPoint& p1, TPPLPoint& p2, TPPLPoint& p3) { - tppl_float tmp; - tmp = (p3.y-p1.y)*(p2.x-p1.x)-(p3.x-p1.x)*(p2.y-p1.y); - if(tmp>0) return 1; - else return 0; -} - -bool TPPLPartition::IsReflex(TPPLPoint& p1, TPPLPoint& p2, TPPLPoint& p3) { - tppl_float tmp; - tmp = (p3.y-p1.y)*(p2.x-p1.x)-(p3.x-p1.x)*(p2.y-p1.y); - if(tmp<0) return 1; - else return 0; -} - -bool TPPLPartition::IsInside(TPPLPoint& p1, TPPLPoint& p2, TPPLPoint& p3, TPPLPoint &p) { - if(IsConvex(p1,p,p2)) return false; - if(IsConvex(p2,p,p3)) return false; - if(IsConvex(p3,p,p1)) return false; - return true; -} - -bool TPPLPartition::InCone(TPPLPoint &p1, TPPLPoint &p2, TPPLPoint &p3, TPPLPoint &p) { - bool convex; - - convex = IsConvex(p1,p2,p3); - - if(convex) { - if(!IsConvex(p1,p2,p)) return false; - if(!IsConvex(p2,p3,p)) return false; - return true; - } else { - if(IsConvex(p1,p2,p)) return true; - if(IsConvex(p2,p3,p)) return true; - return false; - } -} - -bool TPPLPartition::InCone(PartitionVertex *v, TPPLPoint &p) { - TPPLPoint p1,p2,p3; - - p1 = v->previous->p; - p2 = v->p; - p3 = v->next->p; - - return InCone(p1,p2,p3,p); -} - -void TPPLPartition::UpdateVertexReflexity(PartitionVertex *v) { - PartitionVertex *v1,*v3; - v1 = v->previous; - v3 = v->next; - v->isConvex = !IsReflex(v1->p,v->p,v3->p); -} - -void TPPLPartition::UpdateVertex(PartitionVertex *v, PartitionVertex *vertices, long numvertices) { - long i; - PartitionVertex *v1,*v3; - TPPLPoint vec1,vec3; - - v1 = v->previous; - v3 = v->next; - - v->isConvex = IsConvex(v1->p,v->p,v3->p); - - vec1 = Normalize(v1->p - v->p); - vec3 = Normalize(v3->p - v->p); - v->angle = vec1.x*vec3.x + vec1.y*vec3.y; - - if(v->isConvex) { - v->isEar = true; - for(i=0;ip.x)&&(vertices[i].p.y==v->p.y)) continue; - if((vertices[i].p.x==v1->p.x)&&(vertices[i].p.y==v1->p.y)) continue; - if((vertices[i].p.x==v3->p.x)&&(vertices[i].p.y==v3->p.y)) continue; - if(IsInside(v1->p,v->p,v3->p,vertices[i].p)) { - v->isEar = false; - break; - } - } - } else { - v->isEar = false; - } -} - -//triangulation by ear removal -int TPPLPartition::Triangulate_EC(TPPLPoly *poly, list *triangles) { - long numvertices; - PartitionVertex *vertices; - PartitionVertex *ear; - TPPLPoly triangle; - long i,j; - bool earfound; - - if(poly->GetNumPoints() < 3) return 0; - if(poly->GetNumPoints() == 3) { - triangles->push_back(*poly); - return 1; - } - - numvertices = poly->GetNumPoints(); - - vertices = new PartitionVertex[numvertices]; - for(i=0;iGetPoint(i); - if(i==(numvertices-1)) vertices[i].next=&(vertices[0]); - else vertices[i].next=&(vertices[i+1]); - if(i==0) vertices[i].previous = &(vertices[numvertices-1]); - else vertices[i].previous = &(vertices[i-1]); - } - for(i=0;i ear->angle) { - ear = &(vertices[j]); - } - } - } - if(!earfound) { - delete [] vertices; - return 0; - } - - triangle.Triangle(ear->previous->p,ear->p,ear->next->p); - triangles->push_back(triangle); - - ear->isActive = false; - ear->previous->next = ear->next; - ear->next->previous = ear->previous; - - if(i==numvertices-4) break; - - UpdateVertex(ear->previous,vertices,numvertices); - UpdateVertex(ear->next,vertices,numvertices); - } - for(i=0;ip,vertices[i].p,vertices[i].next->p); - triangles->push_back(triangle); - break; - } - } - - delete [] vertices; - - return 1; -} - -int TPPLPartition::Triangulate_EC(list *inpolys, list *triangles) { - list outpolys; - list::iterator iter; - - if(!RemoveHoles(inpolys,&outpolys)) return 0; - for(iter=outpolys.begin();iter!=outpolys.end();++iter) { - if(!Triangulate_EC(&(*iter),triangles)) return 0; - } - return 1; -} - -int TPPLPartition::ConvexPartition_HM(TPPLPoly *poly, list *parts) { - list triangles; - list::iterator iter1,iter2; - TPPLPoly *poly1,*poly2; - TPPLPoly newpoly; - TPPLPoint d1,d2,p1,p2,p3; - long i11,i12,i21,i22,i13,i23,j,k; - bool isdiagonal; - long numreflex; - - //check if the poly is already convex - numreflex = 0; - for(i11=0;i11GetNumPoints();i11++) { - if(i11==0) i12 = poly->GetNumPoints()-1; - else i12=i11-1; - if(i11==(poly->GetNumPoints()-1)) i13=0; - else i13=i11+1; - if(IsReflex(poly->GetPoint(i12),poly->GetPoint(i11),poly->GetPoint(i13))) { - numreflex = 1; - break; - } - } - if(numreflex == 0) { - parts->push_back(*poly); - return 1; - } - - if(!Triangulate_EC(poly,&triangles)) return 0; - - for(iter1 = triangles.begin(); iter1 != triangles.end(); ++iter1) { - poly1 = &(*iter1); - for(i11=0;i11GetNumPoints();i11++) { - d1 = poly1->GetPoint(i11); - i12 = (i11+1)%(poly1->GetNumPoints()); - d2 = poly1->GetPoint(i12); - - isdiagonal = false; - for(iter2 = iter1; iter2 != triangles.end(); ++iter2) { - if(iter1 == iter2) continue; - poly2 = &(*iter2); - - for(i21=0;i21GetNumPoints();i21++) { - if((d2.x != poly2->GetPoint(i21).x)||(d2.y != poly2->GetPoint(i21).y)) continue; - i22 = (i21+1)%(poly2->GetNumPoints()); - if((d1.x != poly2->GetPoint(i22).x)||(d1.y != poly2->GetPoint(i22).y)) continue; - isdiagonal = true; - break; - } - if(isdiagonal) break; - } - - if(!isdiagonal) continue; - - p2 = poly1->GetPoint(i11); - if(i11 == 0) i13 = poly1->GetNumPoints()-1; - else i13 = i11-1; - p1 = poly1->GetPoint(i13); - if(i22 == (poly2->GetNumPoints()-1)) i23 = 0; - else i23 = i22+1; - p3 = poly2->GetPoint(i23); - - if(!IsConvex(p1,p2,p3)) continue; - - p2 = poly1->GetPoint(i12); - if(i12 == (poly1->GetNumPoints()-1)) i13 = 0; - else i13 = i12+1; - p3 = poly1->GetPoint(i13); - if(i21 == 0) i23 = poly2->GetNumPoints()-1; - else i23 = i21-1; - p1 = poly2->GetPoint(i23); - - if(!IsConvex(p1,p2,p3)) continue; - - newpoly.Init(poly1->GetNumPoints()+poly2->GetNumPoints()-2); - k = 0; - for(j=i12;j!=i11;j=(j+1)%(poly1->GetNumPoints())) { - newpoly[k] = poly1->GetPoint(j); - k++; - } - for(j=i22;j!=i21;j=(j+1)%(poly2->GetNumPoints())) { - newpoly[k] = poly2->GetPoint(j); - k++; - } - - triangles.erase(iter2); - *iter1 = newpoly; - poly1 = &(*iter1); - i11 = -1; - - continue; - } - } - - for(iter1 = triangles.begin(); iter1 != triangles.end(); ++iter1) { - parts->push_back(*iter1); - } - - return 1; -} - -int TPPLPartition::ConvexPartition_HM(list *inpolys, list *parts) { - list outpolys; - list::iterator iter; - - if(!RemoveHoles(inpolys,&outpolys)) return 0; - for(iter=outpolys.begin();iter!=outpolys.end();++iter) { - if(!ConvexPartition_HM(&(*iter),parts)) return 0; - } - return 1; -} - -//minimum-weight polygon triangulation by dynamic programming -//O(n^3) time complexity -//O(n^2) space complexity -int TPPLPartition::Triangulate_OPT(TPPLPoly *poly, list *triangles) { - long i,j,k,gap,n; - DPState **dpstates; - TPPLPoint p1,p2,p3,p4; - long bestvertex; - tppl_float weight,minweight,d1,d2; - Diagonal diagonal,newdiagonal; - list diagonals; - TPPLPoly triangle; - int ret = 1; - - n = poly->GetNumPoints(); - dpstates = new DPState *[n]; - for(i=1;iGetPoint(i); - for(j=i+1;jGetPoint(j); - - //visibility check - if(i==0) p3 = poly->GetPoint(n-1); - else p3 = poly->GetPoint(i-1); - if(i==(n-1)) p4 = poly->GetPoint(0); - else p4 = poly->GetPoint(i+1); - if(!InCone(p3,p1,p4,p2)) { - dpstates[j][i].visible = false; - continue; - } - - if(j==0) p3 = poly->GetPoint(n-1); - else p3 = poly->GetPoint(j-1); - if(j==(n-1)) p4 = poly->GetPoint(0); - else p4 = poly->GetPoint(j+1); - if(!InCone(p3,p2,p4,p1)) { - dpstates[j][i].visible = false; - continue; - } - - for(k=0;kGetPoint(k); - if(k==(n-1)) p4 = poly->GetPoint(0); - else p4 = poly->GetPoint(k+1); - if(Intersects(p1,p2,p3,p4)) { - dpstates[j][i].visible = false; - break; - } - } - } - } - } - dpstates[n-1][0].visible = true; - dpstates[n-1][0].weight = 0; - dpstates[n-1][0].bestvertex = -1; - - for(gap = 2; gapGetPoint(i),poly->GetPoint(k)); - if(j<=(k+1)) d2=0; - else d2 = Distance(poly->GetPoint(k),poly->GetPoint(j)); - - weight = dpstates[k][i].weight + dpstates[j][k].weight + d1 + d2; - - if((bestvertex == -1)||(weightGetPoint(diagonal.index1),poly->GetPoint(bestvertex),poly->GetPoint(diagonal.index2)); - triangles->push_back(triangle); - if(bestvertex > (diagonal.index1+1)) { - newdiagonal.index1 = diagonal.index1; - newdiagonal.index2 = bestvertex; - diagonals.push_back(newdiagonal); - } - if(diagonal.index2 > (bestvertex+1)) { - newdiagonal.index1 = bestvertex; - newdiagonal.index2 = diagonal.index2; - diagonals.push_back(newdiagonal); - } - } - - for(i=1;i *pairs; - long w2; - - w2 = dpstates[a][b].weight; - if(w>w2) return; - - pairs = &(dpstates[a][b].pairs); - newdiagonal.index1 = i; - newdiagonal.index2 = j; - - if(wclear(); - pairs->push_front(newdiagonal); - dpstates[a][b].weight = w; - } else { - if((!pairs->empty())&&(i <= pairs->begin()->index1)) return; - while((!pairs->empty())&&(pairs->begin()->index2 >= j)) pairs->pop_front(); - pairs->push_front(newdiagonal); - } -} - -void TPPLPartition::TypeA(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates) { - list *pairs; - list::iterator iter,lastiter; - long top; - long w; - - if(!dpstates[i][j].visible) return; - top = j; - w = dpstates[i][j].weight; - if(k-j > 1) { - if (!dpstates[j][k].visible) return; - w += dpstates[j][k].weight + 1; - } - if(j-i > 1) { - pairs = &(dpstates[i][j].pairs); - iter = pairs->end(); - lastiter = pairs->end(); - while(iter!=pairs->begin()) { - --iter; - if(!IsReflex(vertices[iter->index2].p,vertices[j].p,vertices[k].p)) lastiter = iter; - else break; - } - if(lastiter == pairs->end()) w++; - else { - if(IsReflex(vertices[k].p,vertices[i].p,vertices[lastiter->index1].p)) w++; - else top = lastiter->index1; - } - } - UpdateState(i,k,w,top,j,dpstates); -} - -void TPPLPartition::TypeB(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates) { - list *pairs; - list::iterator iter,lastiter; - long top; - long w; - - if(!dpstates[j][k].visible) return; - top = j; - w = dpstates[j][k].weight; - - if (j-i > 1) { - if (!dpstates[i][j].visible) return; - w += dpstates[i][j].weight + 1; - } - if (k-j > 1) { - pairs = &(dpstates[j][k].pairs); - - iter = pairs->begin(); - if((!pairs->empty())&&(!IsReflex(vertices[i].p,vertices[j].p,vertices[iter->index1].p))) { - lastiter = iter; - while(iter!=pairs->end()) { - if(!IsReflex(vertices[i].p,vertices[j].p,vertices[iter->index1].p)) { - lastiter = iter; - ++iter; - } - else break; - } - if(IsReflex(vertices[lastiter->index2].p,vertices[k].p,vertices[i].p)) w++; - else top = lastiter->index2; - } else w++; - } - UpdateState(i,k,w,j,top,dpstates); -} - -int TPPLPartition::ConvexPartition_OPT(TPPLPoly *poly, list *parts) { - TPPLPoint p1,p2,p3,p4; - PartitionVertex *vertices; - DPState2 **dpstates; - long i,j,k,n,gap; - list diagonals,diagonals2; - Diagonal diagonal,newdiagonal; - list *pairs,*pairs2; - list::iterator iter,iter2; - int ret; - TPPLPoly newpoly; - list indices; - list::iterator iiter; - bool ijreal,jkreal; - - n = poly->GetNumPoints(); - vertices = new PartitionVertex[n]; - - dpstates = new DPState2 *[n]; - for(i=0;iGetPoint(i); - vertices[i].isActive = true; - if(i==0) vertices[i].previous = &(vertices[n-1]); - else vertices[i].previous = &(vertices[i-1]); - if(i==(poly->GetNumPoints()-1)) vertices[i].next = &(vertices[0]); - else vertices[i].next = &(vertices[i+1]); - } - for(i=1;iGetPoint(i); - for(j=i+1;jGetPoint(j); - - //visibility check - if(!InCone(&vertices[i],p2)) { - dpstates[i][j].visible = false; - continue; - } - if(!InCone(&vertices[j],p1)) { - dpstates[i][j].visible = false; - continue; - } - - for(k=0;kGetPoint(k); - if(k==(n-1)) p4 = poly->GetPoint(0); - else p4 = poly->GetPoint(k+1); - if(Intersects(p1,p2,p3,p4)) { - dpstates[i][j].visible = false; - break; - } - } - } - } - } - for(i=0;i<(n-2);i++) { - j = i+2; - if(dpstates[i][j].visible) { - dpstates[i][j].weight = 0; - newdiagonal.index1 = i+1; - newdiagonal.index2 = i+1; - dpstates[i][j].pairs.push_back(newdiagonal); - } - } - - dpstates[0][n-1].visible = true; - vertices[0].isConvex = false; //by convention - - for(gap=3; gapempty()) { - ret = 0; - break; - } - if(!vertices[diagonal.index1].isConvex) { - iter = pairs->end(); - --iter; - j = iter->index2; - newdiagonal.index1 = j; - newdiagonal.index2 = diagonal.index2; - diagonals.push_front(newdiagonal); - if((j - diagonal.index1)>1) { - if(iter->index1 != iter->index2) { - pairs2 = &(dpstates[diagonal.index1][j].pairs); - while(1) { - if(pairs2->empty()) { - ret = 0; - break; - } - iter2 = pairs2->end(); - --iter2; - if(iter->index1 != iter2->index1) pairs2->pop_back(); - else break; - } - if(ret == 0) break; - } - newdiagonal.index1 = diagonal.index1; - newdiagonal.index2 = j; - diagonals.push_front(newdiagonal); - } - } else { - iter = pairs->begin(); - j = iter->index1; - newdiagonal.index1 = diagonal.index1; - newdiagonal.index2 = j; - diagonals.push_front(newdiagonal); - if((diagonal.index2 - j) > 1) { - if(iter->index1 != iter->index2) { - pairs2 = &(dpstates[j][diagonal.index2].pairs); - while(1) { - if(pairs2->empty()) { - ret = 0; - break; - } - iter2 = pairs2->begin(); - if(iter->index2 != iter2->index2) pairs2->pop_front(); - else break; - } - if(ret == 0) break; - } - newdiagonal.index1 = j; - newdiagonal.index2 = diagonal.index2; - diagonals.push_front(newdiagonal); - } - } - } - - if(ret == 0) { - for(i=0;iend(); - --iter; - j = iter->index2; - if(iter->index1 != iter->index2) ijreal = false; - } else { - iter = pairs->begin(); - j = iter->index1; - if(iter->index1 != iter->index2) jkreal = false; - } - - newdiagonal.index1 = diagonal.index1; - newdiagonal.index2 = j; - if(ijreal) { - diagonals.push_back(newdiagonal); - } else { - diagonals2.push_back(newdiagonal); - } - - newdiagonal.index1 = j; - newdiagonal.index2 = diagonal.index2; - if(jkreal) { - diagonals.push_back(newdiagonal); - } else { - diagonals2.push_back(newdiagonal); - } - - indices.push_back(j); - } - - indices.sort(); - newpoly.Init((long)indices.size()); - k=0; - for(iiter = indices.begin();iiter!=indices.end(); ++iiter) { - newpoly[k] = vertices[*iiter].p; - k++; - } - parts->push_back(newpoly); - } - - for(i=0;i *inpolys, list *monotonePolys) { - list::iterator iter; - MonotoneVertex *vertices; - long i,numvertices,vindex,vindex2,newnumvertices,maxnumvertices; - long polystartindex, polyendindex; - TPPLPoly *poly; - MonotoneVertex *v,*v2,*vprev,*vnext; - ScanLineEdge newedge; - bool error = false; - - numvertices = 0; - for(iter = inpolys->begin(); iter != inpolys->end(); ++iter) { - numvertices += iter->GetNumPoints(); - } - - maxnumvertices = numvertices*3; - vertices = new MonotoneVertex[maxnumvertices]; - newnumvertices = numvertices; - - polystartindex = 0; - for(iter = inpolys->begin(); iter != inpolys->end(); ++iter) { - poly = &(*iter); - polyendindex = polystartindex + poly->GetNumPoints()-1; - for(i=0;iGetNumPoints();i++) { - vertices[i+polystartindex].p = poly->GetPoint(i); - if(i==0) vertices[i+polystartindex].previous = polyendindex; - else vertices[i+polystartindex].previous = i+polystartindex-1; - if(i==(poly->GetNumPoints()-1)) vertices[i+polystartindex].next = polystartindex; - else vertices[i+polystartindex].next = i+polystartindex+1; - } - polystartindex = polyendindex+1; - } - - //construct the priority queue - long *priority = new long [numvertices]; - for(i=0;iprevious]); - vnext = &(vertices[v->next]); - - if(Below(vprev->p,v->p)&&Below(vnext->p,v->p)) { - if(IsConvex(vnext->p,vprev->p,v->p)) { - vertextypes[i] = TPPL_VERTEXTYPE_START; - } else { - vertextypes[i] = TPPL_VERTEXTYPE_SPLIT; - } - } else if(Below(v->p,vprev->p)&&Below(v->p,vnext->p)) { - if(IsConvex(vnext->p,vprev->p,v->p)) - { - vertextypes[i] = TPPL_VERTEXTYPE_END; - } else { - vertextypes[i] = TPPL_VERTEXTYPE_MERGE; - } - } else { - vertextypes[i] = TPPL_VERTEXTYPE_REGULAR; - } - } - - //helpers - long *helpers = new long[maxnumvertices]; - - //binary search tree that holds edges intersecting the scanline - //note that while set doesn't actually have to be implemented as a tree - //complexity requirements for operations are the same as for the balanced binary search tree - set edgeTree; - //store iterators to the edge tree elements - //this makes deleting existing edges much faster - set::iterator *edgeTreeIterators,edgeIter; - edgeTreeIterators = new set::iterator[maxnumvertices]; - pair::iterator,bool> edgeTreeRet; - - //for each vertex - for(i=0;ip; - newedge.p2 = vertices[v->next].p; - newedge.index = vindex; - edgeTreeRet = edgeTree.insert(newedge); - edgeTreeIterators[vindex] = edgeTreeRet.first; - helpers[vindex] = vindex; - break; - - case TPPL_VERTEXTYPE_END: - //if helper(ei-1) is a merge vertex - if(vertextypes[helpers[v->previous]]==TPPL_VERTEXTYPE_MERGE) { - //Insert the diagonal connecting vi to helper(ei-1) in D. - AddDiagonal(vertices,&newnumvertices,vindex,helpers[v->previous]); - vertextypes[newnumvertices-2] = vertextypes[vindex]; - edgeTreeIterators[newnumvertices-2] = edgeTreeIterators[vindex]; - helpers[newnumvertices-2] = helpers[vindex]; - vertextypes[newnumvertices-1] = vertextypes[helpers[v->previous]]; - edgeTreeIterators[newnumvertices-1] = edgeTreeIterators[helpers[v->previous]]; - helpers[newnumvertices-1] = helpers[helpers[v->previous]]; - } - //Delete ei-1 from T - edgeTree.erase(edgeTreeIterators[v->previous]); - break; - - case TPPL_VERTEXTYPE_SPLIT: - //Search in T to find the edge e j directly left of vi. - newedge.p1 = v->p; - newedge.p2 = v->p; - edgeIter = edgeTree.lower_bound(newedge); - if(edgeIter == edgeTree.begin()) { - error = true; - break; - } - --edgeIter; - //Insert the diagonal connecting vi to helper(ej) in D. - AddDiagonal(vertices,&newnumvertices,vindex,helpers[edgeIter->index]); - vertextypes[newnumvertices-2] = vertextypes[vindex]; - edgeTreeIterators[newnumvertices-2] = edgeTreeIterators[vindex]; - helpers[newnumvertices-2] = helpers[vindex]; - vertextypes[newnumvertices-1] = vertextypes[helpers[edgeIter->index]]; - edgeTreeIterators[newnumvertices-1] = edgeTreeIterators[helpers[edgeIter->index]]; - helpers[newnumvertices-1] = helpers[helpers[edgeIter->index]]; - vindex2 = newnumvertices-2; - v2 = &(vertices[vindex2]); - //helper(e j)�vi - helpers[edgeIter->index] = vindex; - //Insert ei in T and set helper(ei) to vi. - newedge.p1 = v2->p; - newedge.p2 = vertices[v2->next].p; - newedge.index = vindex2; - edgeTreeRet = edgeTree.insert(newedge); - edgeTreeIterators[vindex2] = edgeTreeRet.first; - helpers[vindex2] = vindex2; - break; - - case TPPL_VERTEXTYPE_MERGE: - //if helper(ei-1) is a merge vertex - if(vertextypes[helpers[v->previous]]==TPPL_VERTEXTYPE_MERGE) { - //Insert the diagonal connecting vi to helper(ei-1) in D. - AddDiagonal(vertices,&newnumvertices,vindex,helpers[v->previous]); - vertextypes[newnumvertices-2] = vertextypes[vindex]; - edgeTreeIterators[newnumvertices-2] = edgeTreeIterators[vindex]; - helpers[newnumvertices-2] = helpers[vindex]; - vertextypes[newnumvertices-1] = vertextypes[helpers[v->previous]]; - edgeTreeIterators[newnumvertices-1] = edgeTreeIterators[helpers[v->previous]]; - helpers[newnumvertices-1] = helpers[helpers[v->previous]]; - vindex2 = newnumvertices-2; - v2 = &(vertices[vindex2]); - } - //Delete ei-1 from T. - edgeTree.erase(edgeTreeIterators[v->previous]); - //Search in T to find the edge e j directly left of vi. - newedge.p1 = v->p; - newedge.p2 = v->p; - edgeIter = edgeTree.lower_bound(newedge); - if(edgeIter == edgeTree.begin()) { - error = true; - break; - } - --edgeIter; - //if helper(ej) is a merge vertex - if(vertextypes[helpers[edgeIter->index]]==TPPL_VERTEXTYPE_MERGE) { - //Insert the diagonal connecting vi to helper(e j) in D. - AddDiagonal(vertices,&newnumvertices,vindex2,helpers[edgeIter->index]); - vertextypes[newnumvertices-2] = vertextypes[vindex2]; - edgeTreeIterators[newnumvertices-2] = edgeTreeIterators[vindex2]; - helpers[newnumvertices-2] = helpers[vindex2]; - vertextypes[newnumvertices-1] = vertextypes[helpers[edgeIter->index]]; - edgeTreeIterators[newnumvertices-1] = edgeTreeIterators[helpers[edgeIter->index]]; - helpers[newnumvertices-1] = helpers[helpers[edgeIter->index]]; - } - //helper(e j)�vi - helpers[edgeIter->index] = vindex2; - break; - - case TPPL_VERTEXTYPE_REGULAR: - //if the interior of P lies to the right of vi - if(Below(v->p,vertices[v->previous].p)) { - //if helper(ei-1) is a merge vertex - if(vertextypes[helpers[v->previous]]==TPPL_VERTEXTYPE_MERGE) { - //Insert the diagonal connecting vi to helper(ei-1) in D. - AddDiagonal(vertices,&newnumvertices,vindex,helpers[v->previous]); - vertextypes[newnumvertices-2] = vertextypes[vindex]; - edgeTreeIterators[newnumvertices-2] = edgeTreeIterators[vindex]; - helpers[newnumvertices-2] = helpers[vindex]; - vertextypes[newnumvertices-1] = vertextypes[helpers[v->previous]]; - edgeTreeIterators[newnumvertices-1] = edgeTreeIterators[helpers[v->previous]]; - helpers[newnumvertices-1] = helpers[helpers[v->previous]]; - vindex2 = newnumvertices-2; - v2 = &(vertices[vindex2]); - } - //Delete ei-1 from T. - edgeTree.erase(edgeTreeIterators[v->previous]); - //Insert ei in T and set helper(ei) to vi. - newedge.p1 = v2->p; - newedge.p2 = vertices[v2->next].p; - newedge.index = vindex2; - edgeTreeRet = edgeTree.insert(newedge); - edgeTreeIterators[vindex2] = edgeTreeRet.first; - helpers[vindex2] = vindex; - } else { - //Search in T to find the edge ej directly left of vi. - newedge.p1 = v->p; - newedge.p2 = v->p; - edgeIter = edgeTree.lower_bound(newedge); - if(edgeIter == edgeTree.begin()) { - error = true; - break; - } - --edgeIter; - //if helper(ej) is a merge vertex - if(vertextypes[helpers[edgeIter->index]]==TPPL_VERTEXTYPE_MERGE) { - //Insert the diagonal connecting vi to helper(e j) in D. - AddDiagonal(vertices,&newnumvertices,vindex,helpers[edgeIter->index]); - vertextypes[newnumvertices-2] = vertextypes[vindex]; - edgeTreeIterators[newnumvertices-2] = edgeTreeIterators[vindex]; - helpers[newnumvertices-2] = helpers[vindex]; - vertextypes[newnumvertices-1] = vertextypes[helpers[edgeIter->index]]; - edgeTreeIterators[newnumvertices-1] = edgeTreeIterators[helpers[edgeIter->index]]; - helpers[newnumvertices-1] = helpers[helpers[edgeIter->index]]; - } - //helper(e j)�vi - helpers[edgeIter->index] = vindex; - } - break; - } - - if(error) break; - } - - char *used = new char[newnumvertices]; - memset(used,0,newnumvertices*sizeof(char)); - - if(!error) { - //return result - long size; - TPPLPoly mpoly; - for(i=0;inext]); - size = 1; - while(vnext!=v) { - vnext = &(vertices[vnext->next]); - size++; - } - mpoly.Init(size); - v = &(vertices[i]); - mpoly[0] = v->p; - vnext = &(vertices[v->next]); - size = 1; - used[i] = 1; - used[v->next] = 1; - while(vnext!=v) { - mpoly[size] = vnext->p; - used[vnext->next] = 1; - vnext = &(vertices[vnext->next]); - size++; - } - monotonePolys->push_back(mpoly); - } - } - - //cleanup - delete [] vertices; - delete [] priority; - delete [] vertextypes; - delete [] edgeTreeIterators; - delete [] helpers; - delete [] used; - - if(error) { - return 0; - } else { - return 1; - } -} - -//adds a diagonal to the doubly-connected list of vertices -void TPPLPartition::AddDiagonal(MonotoneVertex *vertices, long *numvertices, long index1, long index2) { - long newindex1,newindex2; - - newindex1 = *numvertices; - (*numvertices)++; - newindex2 = *numvertices; - (*numvertices)++; - - vertices[newindex1].p = vertices[index1].p; - vertices[newindex2].p = vertices[index2].p; - - vertices[newindex2].next = vertices[index2].next; - vertices[newindex1].next = vertices[index1].next; - - vertices[vertices[index2].next].previous = newindex2; - vertices[vertices[index1].next].previous = newindex1; - - vertices[index1].next = newindex2; - vertices[newindex2].previous = index1; - - vertices[index2].next = newindex1; - vertices[newindex1].previous = index2; -} - -bool TPPLPartition::Below(TPPLPoint &p1, TPPLPoint &p2) { - if(p1.y < p2.y) return true; - else if(p1.y == p2.y) { - if(p1.x < p2.x) return true; - } - return false; -} - -//sorts in the falling order of y values, if y is equal, x is used instead -bool TPPLPartition::VertexSorter::operator() (long index1, long index2) const { - if(vertices[index1].p.y > vertices[index2].p.y) return true; - else if(vertices[index1].p.y == vertices[index2].p.y) { - if(vertices[index1].p.x > vertices[index2].p.x) return true; - } - return false; -} - -bool TPPLPartition::ScanLineEdge::IsConvex(const TPPLPoint& p1, const TPPLPoint& p2, const TPPLPoint& p3) const { - tppl_float tmp; - tmp = (p3.y-p1.y)*(p2.x-p1.x)-(p3.x-p1.x)*(p2.y-p1.y); - if(tmp>0) return 1; - else return 0; -} - -bool TPPLPartition::ScanLineEdge::operator < (const ScanLineEdge & other) const { - if(other.p1.y == other.p2.y) { - if(p1.y == p2.y) { - if(p1.y < other.p1.y) return true; - else return false; - } - if(IsConvex(p1,p2,other.p1)) return true; - else return false; - } else if(p1.y == p2.y) { - if(IsConvex(other.p1,other.p2,p1)) return false; - else return true; - } else if(p1.y < other.p1.y) { - if(IsConvex(other.p1,other.p2,p1)) return false; - else return true; - } else { - if(IsConvex(p1,p2,other.p1)) return true; - else return false; - } -} - -//triangulates monotone polygon -//O(n) time, O(n) space complexity -int TPPLPartition::TriangulateMonotone(TPPLPoly *inPoly, list *triangles) { - long i,i2,j,topindex,bottomindex,leftindex,rightindex,vindex; - TPPLPoint *points; - long numpoints; - TPPLPoly triangle; - - numpoints = inPoly->GetNumPoints(); - points = inPoly->GetPoints(); - - //trivial calses - if(numpoints < 3) return 0; - if(numpoints == 3) { - triangles->push_back(*inPoly); - } - - topindex = 0; bottomindex=0; - for(i=1;i=numpoints) i2 = 0; - if(!Below(points[i2],points[i])) return 0; - i = i2; - } - i = bottomindex; - while(i!=topindex) { - i2 = i+1; if(i2>=numpoints) i2 = 0; - if(!Below(points[i],points[i2])) return 0; - i = i2; - } - - char *vertextypes = new char[numpoints]; - long *priority = new long[numpoints]; - - //merge left and right vertex chains - priority[0] = topindex; - vertextypes[topindex] = 0; - leftindex = topindex+1; if(leftindex>=numpoints) leftindex = 0; - rightindex = topindex-1; if(rightindex<0) rightindex = numpoints-1; - for(i=1;i<(numpoints-1);i++) { - if(leftindex==bottomindex) { - priority[i] = rightindex; - rightindex--; if(rightindex<0) rightindex = numpoints-1; - vertextypes[priority[i]] = -1; - } else if(rightindex==bottomindex) { - priority[i] = leftindex; - leftindex++; if(leftindex>=numpoints) leftindex = 0; - vertextypes[priority[i]] = 1; - } else { - if(Below(points[leftindex],points[rightindex])) { - priority[i] = rightindex; - rightindex--; if(rightindex<0) rightindex = numpoints-1; - vertextypes[priority[i]] = -1; - } else { - priority[i] = leftindex; - leftindex++; if(leftindex>=numpoints) leftindex = 0; - vertextypes[priority[i]] = 1; - } - } - } - priority[i] = bottomindex; - vertextypes[bottomindex] = 0; - - long *stack = new long[numpoints]; - long stackptr = 0; - - stack[0] = priority[0]; - stack[1] = priority[1]; - stackptr = 2; - - //for each vertex from top to bottom trim as many triangles as possible - for(i=2;i<(numpoints-1);i++) { - vindex = priority[i]; - if(vertextypes[vindex]!=vertextypes[stack[stackptr-1]]) { - for(j=0;j<(stackptr-1);j++) { - if(vertextypes[vindex]==1) { - triangle.Triangle(points[stack[j+1]],points[stack[j]],points[vindex]); - } else { - triangle.Triangle(points[stack[j]],points[stack[j+1]],points[vindex]); - } - triangles->push_back(triangle); - } - stack[0] = priority[i-1]; - stack[1] = priority[i]; - stackptr = 2; - } else { - stackptr--; - while(stackptr>0) { - if(vertextypes[vindex]==1) { - if(IsConvex(points[vindex],points[stack[stackptr-1]],points[stack[stackptr]])) { - triangle.Triangle(points[vindex],points[stack[stackptr-1]],points[stack[stackptr]]); - triangles->push_back(triangle); - stackptr--; - } else { - break; - } - } else { - if(IsConvex(points[vindex],points[stack[stackptr]],points[stack[stackptr-1]])) { - triangle.Triangle(points[vindex],points[stack[stackptr]],points[stack[stackptr-1]]); - triangles->push_back(triangle); - stackptr--; - } else { - break; - } - } - } - stackptr++; - stack[stackptr] = vindex; - stackptr++; - } - } - vindex = priority[i]; - for(j=0;j<(stackptr-1);j++) { - if(vertextypes[stack[j+1]]==1) { - triangle.Triangle(points[stack[j]],points[stack[j+1]],points[vindex]); - } else { - triangle.Triangle(points[stack[j+1]],points[stack[j]],points[vindex]); - } - triangles->push_back(triangle); - } - - delete [] priority; - delete [] vertextypes; - delete [] stack; - - return 1; -} - -int TPPLPartition::Triangulate_MONO(list *inpolys, list *triangles) { - list monotone; - list::iterator iter; - - if(!MonotonePartition(inpolys,&monotone)) return 0; - for(iter = monotone.begin(); iter!=monotone.end(); ++iter) { - if(!TriangulateMonotone(&(*iter),triangles)) return 0; - } - return 1; -} - -int TPPLPartition::Triangulate_MONO(TPPLPoly *poly, list *triangles) { - list polys; - polys.push_back(*poly); - - return Triangulate_MONO(&polys, triangles); -} +//Copyright (C) 2011 by Ivan Fratric +// +//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. + + +#include +#include +#include +#include +#include +#include + +using namespace std; + +#include "polypartition.h" + +#define TPPL_VERTEXTYPE_REGULAR 0 +#define TPPL_VERTEXTYPE_START 1 +#define TPPL_VERTEXTYPE_END 2 +#define TPPL_VERTEXTYPE_SPLIT 3 +#define TPPL_VERTEXTYPE_MERGE 4 + +TPPLPoly::TPPLPoly() { + hole = false; + numpoints = 0; + points = NULL; +} + +TPPLPoly::~TPPLPoly() { + if(points) delete [] points; +} + +void TPPLPoly::Clear() { + if(points) delete [] points; + hole = false; + numpoints = 0; + points = NULL; +} + +void TPPLPoly::Init(long numpoints) { + Clear(); + this->numpoints = numpoints; + points = new TPPLPoint[numpoints]; +} + +void TPPLPoly::Triangle(TPPLPoint &p1, TPPLPoint &p2, TPPLPoint &p3) { + Init(3); + points[0] = p1; + points[1] = p2; + points[2] = p3; +} + +TPPLPoly::TPPLPoly(const TPPLPoly &src) { + hole = src.hole; + numpoints = src.numpoints; + points = new TPPLPoint[numpoints]; + memcpy(points, src.points, numpoints*sizeof(TPPLPoint)); +} + +TPPLPoly& TPPLPoly::operator=(const TPPLPoly &src) { + if(&src != this) { + Clear(); + hole = src.hole; + numpoints = src.numpoints; + points = new TPPLPoint[numpoints]; + memcpy(points, src.points, numpoints*sizeof(TPPLPoint)); + } + return *this; +} + +int TPPLPoly::GetOrientation() const { + long i1,i2; + tppl_float area = 0; + for(i1=0; i10) return TPPL_CCW; + if(area<0) return TPPL_CW; + return 0; +} + +void TPPLPoly::SetOrientation(int orientation) { + int polyorientation = GetOrientation(); + if(polyorientation&&(polyorientation!=orientation)) { + Invert(); + } +} + +void TPPLPoly::Invert() { + long i; + TPPLPoint *invpoints; + + invpoints = new TPPLPoint[numpoints]; + for(i=0;i0) return 0; + if(dot21*dot22>0) return 0; + + return 1; +} + +//removes holes from inpolys by merging them with non-holes +int TPPLPartition::RemoveHoles(list *inpolys, list *outpolys) { + list polys; + list::iterator holeiter,polyiter,iter,iter2; + long i,i2,holepointindex,polypointindex = 0; + TPPLPoint holepoint,polypoint,bestpolypoint; + TPPLPoint linep1,linep2; + TPPLPoint v1,v2; + TPPLPoly newpoly; + bool hasholes; + bool pointvisible; + bool pointfound; + + //check for trivial case (no holes) + hasholes = false; + for(iter = inpolys->begin(); iter!=inpolys->end(); ++iter) { + if(iter->IsHole()) { + hasholes = true; + break; + } + } + if(!hasholes) { + for(iter = inpolys->begin(); iter!=inpolys->end(); ++iter) { + outpolys->push_back(*iter); + } + return 1; + } + + polys = *inpolys; + + while(1) { + //find the hole point with the largest x + hasholes = false; + for(iter = polys.begin(); iter!=polys.end(); ++iter) { + if(!iter->IsHole()) continue; + + if(!hasholes) { + hasholes = true; + holeiter = iter; + holepointindex = 0; + } + + for(i=0; i < iter->GetNumPoints(); i++) { + if(iter->GetPoint(i).x > holeiter->GetPoint(holepointindex).x) { + holeiter = iter; + holepointindex = i; + } + } + } + if(!hasholes) break; + holepoint = holeiter->GetPoint(holepointindex); + + pointfound = false; + for(iter = polys.begin(); iter!=polys.end(); ++iter) { + if(iter->IsHole()) continue; + for(i=0; i < iter->GetNumPoints(); i++) { + if(iter->GetPoint(i).x <= holepoint.x) continue; + if(!InCone(iter->GetPoint((i+iter->GetNumPoints()-1)%(iter->GetNumPoints())), + iter->GetPoint(i), + iter->GetPoint((i+1)%(iter->GetNumPoints())), + holepoint)) + continue; + polypoint = iter->GetPoint(i); + if(pointfound) { + v1 = Normalize(polypoint-holepoint); + v2 = Normalize(bestpolypoint-holepoint); + if(v2.x > v1.x) continue; + } + pointvisible = true; + for(iter2 = polys.begin(); iter2!=polys.end(); ++iter2) { + if(iter2->IsHole()) continue; + for(i2=0; i2 < iter2->GetNumPoints(); i2++) { + linep1 = iter2->GetPoint(i2); + linep2 = iter2->GetPoint((i2+1)%(iter2->GetNumPoints())); + if(Intersects(holepoint,polypoint,linep1,linep2)) { + pointvisible = false; + break; + } + } + if(!pointvisible) break; + } + if(pointvisible) { + pointfound = true; + bestpolypoint = polypoint; + polyiter = iter; + polypointindex = i; + } + } + } + + if(!pointfound) return 0; + + newpoly.Init(holeiter->GetNumPoints() + polyiter->GetNumPoints() + 2); + i2 = 0; + for(i=0;i<=polypointindex;i++) { + newpoly[i2] = polyiter->GetPoint(i); + i2++; + } + for(i=0;i<=holeiter->GetNumPoints();i++) { + newpoly[i2] = holeiter->GetPoint((i+holepointindex)%holeiter->GetNumPoints()); + i2++; + } + for(i=polypointindex;iGetNumPoints();i++) { + newpoly[i2] = polyiter->GetPoint(i); + i2++; + } + + polys.erase(holeiter); + polys.erase(polyiter); + polys.push_back(newpoly); + } + + for(iter = polys.begin(); iter!=polys.end(); ++iter) { + outpolys->push_back(*iter); + } + + return 1; +} + +bool TPPLPartition::IsConvex(TPPLPoint& p1, TPPLPoint& p2, TPPLPoint& p3) { + tppl_float tmp; + tmp = (p3.y-p1.y)*(p2.x-p1.x)-(p3.x-p1.x)*(p2.y-p1.y); + if(tmp>0) return 1; + else return 0; +} + +bool TPPLPartition::IsReflex(TPPLPoint& p1, TPPLPoint& p2, TPPLPoint& p3) { + tppl_float tmp; + tmp = (p3.y-p1.y)*(p2.x-p1.x)-(p3.x-p1.x)*(p2.y-p1.y); + if(tmp<0) return 1; + else return 0; +} + +bool TPPLPartition::IsInside(TPPLPoint& p1, TPPLPoint& p2, TPPLPoint& p3, TPPLPoint &p) { + if(IsConvex(p1,p,p2)) return false; + if(IsConvex(p2,p,p3)) return false; + if(IsConvex(p3,p,p1)) return false; + return true; +} + +bool TPPLPartition::InCone(TPPLPoint &p1, TPPLPoint &p2, TPPLPoint &p3, TPPLPoint &p) { + bool convex; + + convex = IsConvex(p1,p2,p3); + + if(convex) { + if(!IsConvex(p1,p2,p)) return false; + if(!IsConvex(p2,p3,p)) return false; + return true; + } else { + if(IsConvex(p1,p2,p)) return true; + if(IsConvex(p2,p3,p)) return true; + return false; + } +} + +bool TPPLPartition::InCone(PartitionVertex *v, TPPLPoint &p) { + TPPLPoint p1,p2,p3; + + p1 = v->previous->p; + p2 = v->p; + p3 = v->next->p; + + return InCone(p1,p2,p3,p); +} + +void TPPLPartition::UpdateVertexReflexity(PartitionVertex *v) { + PartitionVertex *v1,*v3; + v1 = v->previous; + v3 = v->next; + v->isConvex = !IsReflex(v1->p,v->p,v3->p); +} + +void TPPLPartition::UpdateVertex(PartitionVertex *v, PartitionVertex *vertices, long numvertices) { + long i; + PartitionVertex *v1,*v3; + TPPLPoint vec1,vec3; + + v1 = v->previous; + v3 = v->next; + + v->isConvex = IsConvex(v1->p,v->p,v3->p); + + vec1 = Normalize(v1->p - v->p); + vec3 = Normalize(v3->p - v->p); + v->angle = vec1.x*vec3.x + vec1.y*vec3.y; + + if(v->isConvex) { + v->isEar = true; + for(i=0;ip.x)&&(vertices[i].p.y==v->p.y)) continue; + if((vertices[i].p.x==v1->p.x)&&(vertices[i].p.y==v1->p.y)) continue; + if((vertices[i].p.x==v3->p.x)&&(vertices[i].p.y==v3->p.y)) continue; + if(IsInside(v1->p,v->p,v3->p,vertices[i].p)) { + v->isEar = false; + break; + } + } + } else { + v->isEar = false; + } +} + +//triangulation by ear removal +int TPPLPartition::Triangulate_EC(TPPLPoly *poly, list *triangles) { + long numvertices; + PartitionVertex *vertices; + PartitionVertex *ear; + TPPLPoly triangle; + long i,j; + bool earfound; + + if(poly->GetNumPoints() < 3) return 0; + if(poly->GetNumPoints() == 3) { + triangles->push_back(*poly); + return 1; + } + + numvertices = poly->GetNumPoints(); + + vertices = new PartitionVertex[numvertices]; + for(i=0;iGetPoint(i); + if(i==(numvertices-1)) vertices[i].next=&(vertices[0]); + else vertices[i].next=&(vertices[i+1]); + if(i==0) vertices[i].previous = &(vertices[numvertices-1]); + else vertices[i].previous = &(vertices[i-1]); + } + for(i=0;i ear->angle) { + ear = &(vertices[j]); + } + } + } + if(!earfound) { + delete [] vertices; + return 0; + } + + triangle.Triangle(ear->previous->p,ear->p,ear->next->p); + triangles->push_back(triangle); + + ear->isActive = false; + ear->previous->next = ear->next; + ear->next->previous = ear->previous; + + if(i==numvertices-4) break; + + UpdateVertex(ear->previous,vertices,numvertices); + UpdateVertex(ear->next,vertices,numvertices); + } + for(i=0;ip,vertices[i].p,vertices[i].next->p); + triangles->push_back(triangle); + break; + } + } + + delete [] vertices; + + return 1; +} + +int TPPLPartition::Triangulate_EC(list *inpolys, list *triangles) { + list outpolys; + list::iterator iter; + + if(!RemoveHoles(inpolys,&outpolys)) return 0; + for(iter=outpolys.begin();iter!=outpolys.end();++iter) { + if(!Triangulate_EC(&(*iter),triangles)) return 0; + } + return 1; +} + +int TPPLPartition::ConvexPartition_HM(TPPLPoly *poly, list *parts) { + list triangles; + list::iterator iter1,iter2; + TPPLPoly *poly1,*poly2; + TPPLPoly newpoly; + TPPLPoint d1,d2,p1,p2,p3; + long i11,i12,i21,i22,i13,i23,j,k; + bool isdiagonal; + long numreflex; + + //check if the poly is already convex + numreflex = 0; + for(i11=0;i11GetNumPoints();i11++) { + if(i11==0) i12 = poly->GetNumPoints()-1; + else i12=i11-1; + if(i11==(poly->GetNumPoints()-1)) i13=0; + else i13=i11+1; + if(IsReflex(poly->GetPoint(i12),poly->GetPoint(i11),poly->GetPoint(i13))) { + numreflex = 1; + break; + } + } + if(numreflex == 0) { + parts->push_back(*poly); + return 1; + } + + if(!Triangulate_EC(poly,&triangles)) return 0; + + for(iter1 = triangles.begin(); iter1 != triangles.end(); ++iter1) { + poly1 = &(*iter1); + for(i11=0;i11GetNumPoints();i11++) { + d1 = poly1->GetPoint(i11); + i12 = (i11+1)%(poly1->GetNumPoints()); + d2 = poly1->GetPoint(i12); + + isdiagonal = false; + for(iter2 = iter1; iter2 != triangles.end(); ++iter2) { + if(iter1 == iter2) continue; + poly2 = &(*iter2); + + for(i21=0;i21GetNumPoints();i21++) { + if((d2.x != poly2->GetPoint(i21).x)||(d2.y != poly2->GetPoint(i21).y)) continue; + i22 = (i21+1)%(poly2->GetNumPoints()); + if((d1.x != poly2->GetPoint(i22).x)||(d1.y != poly2->GetPoint(i22).y)) continue; + isdiagonal = true; + break; + } + if(isdiagonal) break; + } + + if(!isdiagonal) continue; + + p2 = poly1->GetPoint(i11); + if(i11 == 0) i13 = poly1->GetNumPoints()-1; + else i13 = i11-1; + p1 = poly1->GetPoint(i13); + if(i22 == (poly2->GetNumPoints()-1)) i23 = 0; + else i23 = i22+1; + p3 = poly2->GetPoint(i23); + + if(!IsConvex(p1,p2,p3)) continue; + + p2 = poly1->GetPoint(i12); + if(i12 == (poly1->GetNumPoints()-1)) i13 = 0; + else i13 = i12+1; + p3 = poly1->GetPoint(i13); + if(i21 == 0) i23 = poly2->GetNumPoints()-1; + else i23 = i21-1; + p1 = poly2->GetPoint(i23); + + if(!IsConvex(p1,p2,p3)) continue; + + newpoly.Init(poly1->GetNumPoints()+poly2->GetNumPoints()-2); + k = 0; + for(j=i12;j!=i11;j=(j+1)%(poly1->GetNumPoints())) { + newpoly[k] = poly1->GetPoint(j); + k++; + } + for(j=i22;j!=i21;j=(j+1)%(poly2->GetNumPoints())) { + newpoly[k] = poly2->GetPoint(j); + k++; + } + + triangles.erase(iter2); + *iter1 = newpoly; + poly1 = &(*iter1); + i11 = -1; + + continue; + } + } + + for(iter1 = triangles.begin(); iter1 != triangles.end(); ++iter1) { + parts->push_back(*iter1); + } + + return 1; +} + +int TPPLPartition::ConvexPartition_HM(list *inpolys, list *parts) { + list outpolys; + list::iterator iter; + + if(!RemoveHoles(inpolys,&outpolys)) return 0; + for(iter=outpolys.begin();iter!=outpolys.end();++iter) { + if(!ConvexPartition_HM(&(*iter),parts)) return 0; + } + return 1; +} + +//minimum-weight polygon triangulation by dynamic programming +//O(n^3) time complexity +//O(n^2) space complexity +int TPPLPartition::Triangulate_OPT(TPPLPoly *poly, list *triangles) { + long i,j,k,gap,n; + DPState **dpstates; + TPPLPoint p1,p2,p3,p4; + long bestvertex; + tppl_float weight,minweight,d1,d2; + Diagonal diagonal,newdiagonal; + list diagonals; + TPPLPoly triangle; + int ret = 1; + + n = poly->GetNumPoints(); + dpstates = new DPState *[n]; + for(i=1;iGetPoint(i); + for(j=i+1;jGetPoint(j); + + //visibility check + if(i==0) p3 = poly->GetPoint(n-1); + else p3 = poly->GetPoint(i-1); + if(i==(n-1)) p4 = poly->GetPoint(0); + else p4 = poly->GetPoint(i+1); + if(!InCone(p3,p1,p4,p2)) { + dpstates[j][i].visible = false; + continue; + } + + if(j==0) p3 = poly->GetPoint(n-1); + else p3 = poly->GetPoint(j-1); + if(j==(n-1)) p4 = poly->GetPoint(0); + else p4 = poly->GetPoint(j+1); + if(!InCone(p3,p2,p4,p1)) { + dpstates[j][i].visible = false; + continue; + } + + for(k=0;kGetPoint(k); + if(k==(n-1)) p4 = poly->GetPoint(0); + else p4 = poly->GetPoint(k+1); + if(Intersects(p1,p2,p3,p4)) { + dpstates[j][i].visible = false; + break; + } + } + } + } + } + dpstates[n-1][0].visible = true; + dpstates[n-1][0].weight = 0; + dpstates[n-1][0].bestvertex = -1; + + for(gap = 2; gapGetPoint(i),poly->GetPoint(k)); + if(j<=(k+1)) d2=0; + else d2 = Distance(poly->GetPoint(k),poly->GetPoint(j)); + + weight = dpstates[k][i].weight + dpstates[j][k].weight + d1 + d2; + + if((bestvertex == -1)||(weightGetPoint(diagonal.index1),poly->GetPoint(bestvertex),poly->GetPoint(diagonal.index2)); + triangles->push_back(triangle); + if(bestvertex > (diagonal.index1+1)) { + newdiagonal.index1 = diagonal.index1; + newdiagonal.index2 = bestvertex; + diagonals.push_back(newdiagonal); + } + if(diagonal.index2 > (bestvertex+1)) { + newdiagonal.index1 = bestvertex; + newdiagonal.index2 = diagonal.index2; + diagonals.push_back(newdiagonal); + } + } + + for(i=1;i *pairs; + long w2; + + w2 = dpstates[a][b].weight; + if(w>w2) return; + + pairs = &(dpstates[a][b].pairs); + newdiagonal.index1 = i; + newdiagonal.index2 = j; + + if(wclear(); + pairs->push_front(newdiagonal); + dpstates[a][b].weight = w; + } else { + if((!pairs->empty())&&(i <= pairs->begin()->index1)) return; + while((!pairs->empty())&&(pairs->begin()->index2 >= j)) pairs->pop_front(); + pairs->push_front(newdiagonal); + } +} + +void TPPLPartition::TypeA(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates) { + list *pairs; + list::iterator iter,lastiter; + long top; + long w; + + if(!dpstates[i][j].visible) return; + top = j; + w = dpstates[i][j].weight; + if(k-j > 1) { + if (!dpstates[j][k].visible) return; + w += dpstates[j][k].weight + 1; + } + if(j-i > 1) { + pairs = &(dpstates[i][j].pairs); + iter = pairs->end(); + lastiter = pairs->end(); + while(iter!=pairs->begin()) { + --iter; + if(!IsReflex(vertices[iter->index2].p,vertices[j].p,vertices[k].p)) lastiter = iter; + else break; + } + if(lastiter == pairs->end()) w++; + else { + if(IsReflex(vertices[k].p,vertices[i].p,vertices[lastiter->index1].p)) w++; + else top = lastiter->index1; + } + } + UpdateState(i,k,w,top,j,dpstates); +} + +void TPPLPartition::TypeB(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates) { + list *pairs; + list::iterator iter,lastiter; + long top; + long w; + + if(!dpstates[j][k].visible) return; + top = j; + w = dpstates[j][k].weight; + + if (j-i > 1) { + if (!dpstates[i][j].visible) return; + w += dpstates[i][j].weight + 1; + } + if (k-j > 1) { + pairs = &(dpstates[j][k].pairs); + + iter = pairs->begin(); + if((!pairs->empty())&&(!IsReflex(vertices[i].p,vertices[j].p,vertices[iter->index1].p))) { + lastiter = iter; + while(iter!=pairs->end()) { + if(!IsReflex(vertices[i].p,vertices[j].p,vertices[iter->index1].p)) { + lastiter = iter; + ++iter; + } + else break; + } + if(IsReflex(vertices[lastiter->index2].p,vertices[k].p,vertices[i].p)) w++; + else top = lastiter->index2; + } else w++; + } + UpdateState(i,k,w,j,top,dpstates); +} + +int TPPLPartition::ConvexPartition_OPT(TPPLPoly *poly, list *parts) { + TPPLPoint p1,p2,p3,p4; + PartitionVertex *vertices; + DPState2 **dpstates; + long i,j,k,n,gap; + list diagonals,diagonals2; + Diagonal diagonal,newdiagonal; + list *pairs,*pairs2; + list::iterator iter,iter2; + int ret; + TPPLPoly newpoly; + list indices; + list::iterator iiter; + bool ijreal,jkreal; + + n = poly->GetNumPoints(); + vertices = new PartitionVertex[n]; + + dpstates = new DPState2 *[n]; + for(i=0;iGetPoint(i); + vertices[i].isActive = true; + if(i==0) vertices[i].previous = &(vertices[n-1]); + else vertices[i].previous = &(vertices[i-1]); + if(i==(poly->GetNumPoints()-1)) vertices[i].next = &(vertices[0]); + else vertices[i].next = &(vertices[i+1]); + } + for(i=1;iGetPoint(i); + for(j=i+1;jGetPoint(j); + + //visibility check + if(!InCone(&vertices[i],p2)) { + dpstates[i][j].visible = false; + continue; + } + if(!InCone(&vertices[j],p1)) { + dpstates[i][j].visible = false; + continue; + } + + for(k=0;kGetPoint(k); + if(k==(n-1)) p4 = poly->GetPoint(0); + else p4 = poly->GetPoint(k+1); + if(Intersects(p1,p2,p3,p4)) { + dpstates[i][j].visible = false; + break; + } + } + } + } + } + for(i=0;i<(n-2);i++) { + j = i+2; + if(dpstates[i][j].visible) { + dpstates[i][j].weight = 0; + newdiagonal.index1 = i+1; + newdiagonal.index2 = i+1; + dpstates[i][j].pairs.push_back(newdiagonal); + } + } + + dpstates[0][n-1].visible = true; + vertices[0].isConvex = false; //by convention + + for(gap=3; gapempty()) { + ret = 0; + break; + } + if(!vertices[diagonal.index1].isConvex) { + iter = pairs->end(); + --iter; + j = iter->index2; + newdiagonal.index1 = j; + newdiagonal.index2 = diagonal.index2; + diagonals.push_front(newdiagonal); + if((j - diagonal.index1)>1) { + if(iter->index1 != iter->index2) { + pairs2 = &(dpstates[diagonal.index1][j].pairs); + while(1) { + if(pairs2->empty()) { + ret = 0; + break; + } + iter2 = pairs2->end(); + --iter2; + if(iter->index1 != iter2->index1) pairs2->pop_back(); + else break; + } + if(ret == 0) break; + } + newdiagonal.index1 = diagonal.index1; + newdiagonal.index2 = j; + diagonals.push_front(newdiagonal); + } + } else { + iter = pairs->begin(); + j = iter->index1; + newdiagonal.index1 = diagonal.index1; + newdiagonal.index2 = j; + diagonals.push_front(newdiagonal); + if((diagonal.index2 - j) > 1) { + if(iter->index1 != iter->index2) { + pairs2 = &(dpstates[j][diagonal.index2].pairs); + while(1) { + if(pairs2->empty()) { + ret = 0; + break; + } + iter2 = pairs2->begin(); + if(iter->index2 != iter2->index2) pairs2->pop_front(); + else break; + } + if(ret == 0) break; + } + newdiagonal.index1 = j; + newdiagonal.index2 = diagonal.index2; + diagonals.push_front(newdiagonal); + } + } + } + + if(ret == 0) { + for(i=0;iend(); + --iter; + j = iter->index2; + if(iter->index1 != iter->index2) ijreal = false; + } else { + iter = pairs->begin(); + j = iter->index1; + if(iter->index1 != iter->index2) jkreal = false; + } + + newdiagonal.index1 = diagonal.index1; + newdiagonal.index2 = j; + if(ijreal) { + diagonals.push_back(newdiagonal); + } else { + diagonals2.push_back(newdiagonal); + } + + newdiagonal.index1 = j; + newdiagonal.index2 = diagonal.index2; + if(jkreal) { + diagonals.push_back(newdiagonal); + } else { + diagonals2.push_back(newdiagonal); + } + + indices.push_back(j); + } + + indices.sort(); + newpoly.Init((long)indices.size()); + k=0; + for(iiter = indices.begin();iiter!=indices.end(); ++iiter) { + newpoly[k] = vertices[*iiter].p; + k++; + } + parts->push_back(newpoly); + } + + for(i=0;i *inpolys, list *monotonePolys) { + list::iterator iter; + MonotoneVertex *vertices; + long i,numvertices,vindex,vindex2,newnumvertices,maxnumvertices; + long polystartindex, polyendindex; + TPPLPoly *poly; + MonotoneVertex *v,*v2,*vprev,*vnext; + ScanLineEdge newedge; + bool error = false; + + numvertices = 0; + for(iter = inpolys->begin(); iter != inpolys->end(); ++iter) { + numvertices += iter->GetNumPoints(); + } + + maxnumvertices = numvertices*3; + vertices = new MonotoneVertex[maxnumvertices]; + newnumvertices = numvertices; + + polystartindex = 0; + for(iter = inpolys->begin(); iter != inpolys->end(); ++iter) { + poly = &(*iter); + polyendindex = polystartindex + poly->GetNumPoints()-1; + for(i=0;iGetNumPoints();i++) { + vertices[i+polystartindex].p = poly->GetPoint(i); + if(i==0) vertices[i+polystartindex].previous = polyendindex; + else vertices[i+polystartindex].previous = i+polystartindex-1; + if(i==(poly->GetNumPoints()-1)) vertices[i+polystartindex].next = polystartindex; + else vertices[i+polystartindex].next = i+polystartindex+1; + } + polystartindex = polyendindex+1; + } + + //construct the priority queue + long *priority = new long [numvertices]; + for(i=0;iprevious]); + vnext = &(vertices[v->next]); + + if(Below(vprev->p,v->p)&&Below(vnext->p,v->p)) { + if(IsConvex(vnext->p,vprev->p,v->p)) { + vertextypes[i] = TPPL_VERTEXTYPE_START; + } else { + vertextypes[i] = TPPL_VERTEXTYPE_SPLIT; + } + } else if(Below(v->p,vprev->p)&&Below(v->p,vnext->p)) { + if(IsConvex(vnext->p,vprev->p,v->p)) + { + vertextypes[i] = TPPL_VERTEXTYPE_END; + } else { + vertextypes[i] = TPPL_VERTEXTYPE_MERGE; + } + } else { + vertextypes[i] = TPPL_VERTEXTYPE_REGULAR; + } + } + + //helpers + long *helpers = new long[maxnumvertices]; + + //binary search tree that holds edges intersecting the scanline + //note that while set doesn't actually have to be implemented as a tree + //complexity requirements for operations are the same as for the balanced binary search tree + set edgeTree; + //store iterators to the edge tree elements + //this makes deleting existing edges much faster + set::iterator *edgeTreeIterators,edgeIter; + edgeTreeIterators = new set::iterator[maxnumvertices]; + pair::iterator,bool> edgeTreeRet; + + //for each vertex + for(i=0;ip; + newedge.p2 = vertices[v->next].p; + newedge.index = vindex; + edgeTreeRet = edgeTree.insert(newedge); + edgeTreeIterators[vindex] = edgeTreeRet.first; + helpers[vindex] = vindex; + break; + + case TPPL_VERTEXTYPE_END: + //if helper(ei-1) is a merge vertex + if(vertextypes[helpers[v->previous]]==TPPL_VERTEXTYPE_MERGE) { + //Insert the diagonal connecting vi to helper(ei-1) in D. + AddDiagonal(vertices,&newnumvertices,vindex,helpers[v->previous]); + vertextypes[newnumvertices-2] = vertextypes[vindex]; + edgeTreeIterators[newnumvertices-2] = edgeTreeIterators[vindex]; + helpers[newnumvertices-2] = helpers[vindex]; + vertextypes[newnumvertices-1] = vertextypes[helpers[v->previous]]; + edgeTreeIterators[newnumvertices-1] = edgeTreeIterators[helpers[v->previous]]; + helpers[newnumvertices-1] = helpers[helpers[v->previous]]; + } + //Delete ei-1 from T + edgeTree.erase(edgeTreeIterators[v->previous]); + break; + + case TPPL_VERTEXTYPE_SPLIT: + //Search in T to find the edge e j directly left of vi. + newedge.p1 = v->p; + newedge.p2 = v->p; + edgeIter = edgeTree.lower_bound(newedge); + if(edgeIter == edgeTree.begin()) { + error = true; + break; + } + --edgeIter; + //Insert the diagonal connecting vi to helper(ej) in D. + AddDiagonal(vertices,&newnumvertices,vindex,helpers[edgeIter->index]); + vertextypes[newnumvertices-2] = vertextypes[vindex]; + edgeTreeIterators[newnumvertices-2] = edgeTreeIterators[vindex]; + helpers[newnumvertices-2] = helpers[vindex]; + vertextypes[newnumvertices-1] = vertextypes[helpers[edgeIter->index]]; + edgeTreeIterators[newnumvertices-1] = edgeTreeIterators[helpers[edgeIter->index]]; + helpers[newnumvertices-1] = helpers[helpers[edgeIter->index]]; + vindex2 = newnumvertices-2; + v2 = &(vertices[vindex2]); + //helper(e j)�vi + helpers[edgeIter->index] = vindex; + //Insert ei in T and set helper(ei) to vi. + newedge.p1 = v2->p; + newedge.p2 = vertices[v2->next].p; + newedge.index = vindex2; + edgeTreeRet = edgeTree.insert(newedge); + edgeTreeIterators[vindex2] = edgeTreeRet.first; + helpers[vindex2] = vindex2; + break; + + case TPPL_VERTEXTYPE_MERGE: + //if helper(ei-1) is a merge vertex + if(vertextypes[helpers[v->previous]]==TPPL_VERTEXTYPE_MERGE) { + //Insert the diagonal connecting vi to helper(ei-1) in D. + AddDiagonal(vertices,&newnumvertices,vindex,helpers[v->previous]); + vertextypes[newnumvertices-2] = vertextypes[vindex]; + edgeTreeIterators[newnumvertices-2] = edgeTreeIterators[vindex]; + helpers[newnumvertices-2] = helpers[vindex]; + vertextypes[newnumvertices-1] = vertextypes[helpers[v->previous]]; + edgeTreeIterators[newnumvertices-1] = edgeTreeIterators[helpers[v->previous]]; + helpers[newnumvertices-1] = helpers[helpers[v->previous]]; + vindex2 = newnumvertices-2; + v2 = &(vertices[vindex2]); + } + //Delete ei-1 from T. + edgeTree.erase(edgeTreeIterators[v->previous]); + //Search in T to find the edge e j directly left of vi. + newedge.p1 = v->p; + newedge.p2 = v->p; + edgeIter = edgeTree.lower_bound(newedge); + if(edgeIter == edgeTree.begin()) { + error = true; + break; + } + --edgeIter; + //if helper(ej) is a merge vertex + if(vertextypes[helpers[edgeIter->index]]==TPPL_VERTEXTYPE_MERGE) { + //Insert the diagonal connecting vi to helper(e j) in D. + AddDiagonal(vertices,&newnumvertices,vindex2,helpers[edgeIter->index]); + vertextypes[newnumvertices-2] = vertextypes[vindex2]; + edgeTreeIterators[newnumvertices-2] = edgeTreeIterators[vindex2]; + helpers[newnumvertices-2] = helpers[vindex2]; + vertextypes[newnumvertices-1] = vertextypes[helpers[edgeIter->index]]; + edgeTreeIterators[newnumvertices-1] = edgeTreeIterators[helpers[edgeIter->index]]; + helpers[newnumvertices-1] = helpers[helpers[edgeIter->index]]; + } + //helper(e j)�vi + helpers[edgeIter->index] = vindex2; + break; + + case TPPL_VERTEXTYPE_REGULAR: + //if the interior of P lies to the right of vi + if(Below(v->p,vertices[v->previous].p)) { + //if helper(ei-1) is a merge vertex + if(vertextypes[helpers[v->previous]]==TPPL_VERTEXTYPE_MERGE) { + //Insert the diagonal connecting vi to helper(ei-1) in D. + AddDiagonal(vertices,&newnumvertices,vindex,helpers[v->previous]); + vertextypes[newnumvertices-2] = vertextypes[vindex]; + edgeTreeIterators[newnumvertices-2] = edgeTreeIterators[vindex]; + helpers[newnumvertices-2] = helpers[vindex]; + vertextypes[newnumvertices-1] = vertextypes[helpers[v->previous]]; + edgeTreeIterators[newnumvertices-1] = edgeTreeIterators[helpers[v->previous]]; + helpers[newnumvertices-1] = helpers[helpers[v->previous]]; + vindex2 = newnumvertices-2; + v2 = &(vertices[vindex2]); + } + //Delete ei-1 from T. + edgeTree.erase(edgeTreeIterators[v->previous]); + //Insert ei in T and set helper(ei) to vi. + newedge.p1 = v2->p; + newedge.p2 = vertices[v2->next].p; + newedge.index = vindex2; + edgeTreeRet = edgeTree.insert(newedge); + edgeTreeIterators[vindex2] = edgeTreeRet.first; + helpers[vindex2] = vindex; + } else { + //Search in T to find the edge ej directly left of vi. + newedge.p1 = v->p; + newedge.p2 = v->p; + edgeIter = edgeTree.lower_bound(newedge); + if(edgeIter == edgeTree.begin()) { + error = true; + break; + } + --edgeIter; + //if helper(ej) is a merge vertex + if(vertextypes[helpers[edgeIter->index]]==TPPL_VERTEXTYPE_MERGE) { + //Insert the diagonal connecting vi to helper(e j) in D. + AddDiagonal(vertices,&newnumvertices,vindex,helpers[edgeIter->index]); + vertextypes[newnumvertices-2] = vertextypes[vindex]; + edgeTreeIterators[newnumvertices-2] = edgeTreeIterators[vindex]; + helpers[newnumvertices-2] = helpers[vindex]; + vertextypes[newnumvertices-1] = vertextypes[helpers[edgeIter->index]]; + edgeTreeIterators[newnumvertices-1] = edgeTreeIterators[helpers[edgeIter->index]]; + helpers[newnumvertices-1] = helpers[helpers[edgeIter->index]]; + } + //helper(e j)�vi + helpers[edgeIter->index] = vindex; + } + break; + } + + if(error) break; + } + + char *used = new char[newnumvertices]; + memset(used,0,newnumvertices*sizeof(char)); + + if(!error) { + //return result + long size; + TPPLPoly mpoly; + for(i=0;inext]); + size = 1; + while(vnext!=v) { + vnext = &(vertices[vnext->next]); + size++; + } + mpoly.Init(size); + v = &(vertices[i]); + mpoly[0] = v->p; + vnext = &(vertices[v->next]); + size = 1; + used[i] = 1; + used[v->next] = 1; + while(vnext!=v) { + mpoly[size] = vnext->p; + used[vnext->next] = 1; + vnext = &(vertices[vnext->next]); + size++; + } + monotonePolys->push_back(mpoly); + } + } + + //cleanup + delete [] vertices; + delete [] priority; + delete [] vertextypes; + delete [] edgeTreeIterators; + delete [] helpers; + delete [] used; + + if(error) { + return 0; + } else { + return 1; + } +} + +//adds a diagonal to the doubly-connected list of vertices +void TPPLPartition::AddDiagonal(MonotoneVertex *vertices, long *numvertices, long index1, long index2) { + long newindex1,newindex2; + + newindex1 = *numvertices; + (*numvertices)++; + newindex2 = *numvertices; + (*numvertices)++; + + vertices[newindex1].p = vertices[index1].p; + vertices[newindex2].p = vertices[index2].p; + + vertices[newindex2].next = vertices[index2].next; + vertices[newindex1].next = vertices[index1].next; + + vertices[vertices[index2].next].previous = newindex2; + vertices[vertices[index1].next].previous = newindex1; + + vertices[index1].next = newindex2; + vertices[newindex2].previous = index1; + + vertices[index2].next = newindex1; + vertices[newindex1].previous = index2; +} + +bool TPPLPartition::Below(TPPLPoint &p1, TPPLPoint &p2) { + if(p1.y < p2.y) return true; + else if(p1.y == p2.y) { + if(p1.x < p2.x) return true; + } + return false; +} + +//sorts in the falling order of y values, if y is equal, x is used instead +bool TPPLPartition::VertexSorter::operator() (long index1, long index2) const { + if(vertices[index1].p.y > vertices[index2].p.y) return true; + else if(vertices[index1].p.y == vertices[index2].p.y) { + if(vertices[index1].p.x > vertices[index2].p.x) return true; + } + return false; +} + +bool TPPLPartition::ScanLineEdge::IsConvex(const TPPLPoint& p1, const TPPLPoint& p2, const TPPLPoint& p3) const { + tppl_float tmp; + tmp = (p3.y-p1.y)*(p2.x-p1.x)-(p3.x-p1.x)*(p2.y-p1.y); + if(tmp>0) return 1; + else return 0; +} + +bool TPPLPartition::ScanLineEdge::operator < (const ScanLineEdge & other) const { + if(other.p1.y == other.p2.y) { + if(p1.y == p2.y) { + if(p1.y < other.p1.y) return true; + else return false; + } + if(IsConvex(p1,p2,other.p1)) return true; + else return false; + } else if(p1.y == p2.y) { + if(IsConvex(other.p1,other.p2,p1)) return false; + else return true; + } else if(p1.y < other.p1.y) { + if(IsConvex(other.p1,other.p2,p1)) return false; + else return true; + } else { + if(IsConvex(p1,p2,other.p1)) return true; + else return false; + } +} + +//triangulates monotone polygon +//O(n) time, O(n) space complexity +int TPPLPartition::TriangulateMonotone(TPPLPoly *inPoly, list *triangles) { + long i,i2,j,topindex,bottomindex,leftindex,rightindex,vindex; + TPPLPoint *points; + long numpoints; + TPPLPoly triangle; + + numpoints = inPoly->GetNumPoints(); + points = inPoly->GetPoints(); + + //trivial calses + if(numpoints < 3) return 0; + if(numpoints == 3) { + triangles->push_back(*inPoly); + } + + topindex = 0; bottomindex=0; + for(i=1;i=numpoints) i2 = 0; + if(!Below(points[i2],points[i])) return 0; + i = i2; + } + i = bottomindex; + while(i!=topindex) { + i2 = i+1; if(i2>=numpoints) i2 = 0; + if(!Below(points[i],points[i2])) return 0; + i = i2; + } + + char *vertextypes = new char[numpoints]; + long *priority = new long[numpoints]; + + //merge left and right vertex chains + priority[0] = topindex; + vertextypes[topindex] = 0; + leftindex = topindex+1; if(leftindex>=numpoints) leftindex = 0; + rightindex = topindex-1; if(rightindex<0) rightindex = numpoints-1; + for(i=1;i<(numpoints-1);i++) { + if(leftindex==bottomindex) { + priority[i] = rightindex; + rightindex--; if(rightindex<0) rightindex = numpoints-1; + vertextypes[priority[i]] = -1; + } else if(rightindex==bottomindex) { + priority[i] = leftindex; + leftindex++; if(leftindex>=numpoints) leftindex = 0; + vertextypes[priority[i]] = 1; + } else { + if(Below(points[leftindex],points[rightindex])) { + priority[i] = rightindex; + rightindex--; if(rightindex<0) rightindex = numpoints-1; + vertextypes[priority[i]] = -1; + } else { + priority[i] = leftindex; + leftindex++; if(leftindex>=numpoints) leftindex = 0; + vertextypes[priority[i]] = 1; + } + } + } + priority[i] = bottomindex; + vertextypes[bottomindex] = 0; + + long *stack = new long[numpoints]; + long stackptr = 0; + + stack[0] = priority[0]; + stack[1] = priority[1]; + stackptr = 2; + + //for each vertex from top to bottom trim as many triangles as possible + for(i=2;i<(numpoints-1);i++) { + vindex = priority[i]; + if(vertextypes[vindex]!=vertextypes[stack[stackptr-1]]) { + for(j=0;j<(stackptr-1);j++) { + if(vertextypes[vindex]==1) { + triangle.Triangle(points[stack[j+1]],points[stack[j]],points[vindex]); + } else { + triangle.Triangle(points[stack[j]],points[stack[j+1]],points[vindex]); + } + triangles->push_back(triangle); + } + stack[0] = priority[i-1]; + stack[1] = priority[i]; + stackptr = 2; + } else { + stackptr--; + while(stackptr>0) { + if(vertextypes[vindex]==1) { + if(IsConvex(points[vindex],points[stack[stackptr-1]],points[stack[stackptr]])) { + triangle.Triangle(points[vindex],points[stack[stackptr-1]],points[stack[stackptr]]); + triangles->push_back(triangle); + stackptr--; + } else { + break; + } + } else { + if(IsConvex(points[vindex],points[stack[stackptr]],points[stack[stackptr-1]])) { + triangle.Triangle(points[vindex],points[stack[stackptr]],points[stack[stackptr-1]]); + triangles->push_back(triangle); + stackptr--; + } else { + break; + } + } + } + stackptr++; + stack[stackptr] = vindex; + stackptr++; + } + } + vindex = priority[i]; + for(j=0;j<(stackptr-1);j++) { + if(vertextypes[stack[j+1]]==1) { + triangle.Triangle(points[stack[j]],points[stack[j+1]],points[vindex]); + } else { + triangle.Triangle(points[stack[j+1]],points[stack[j]],points[vindex]); + } + triangles->push_back(triangle); + } + + delete [] priority; + delete [] vertextypes; + delete [] stack; + + return 1; +} + +int TPPLPartition::Triangulate_MONO(list *inpolys, list *triangles) { + list monotone; + list::iterator iter; + + if(!MonotonePartition(inpolys,&monotone)) return 0; + for(iter = monotone.begin(); iter!=monotone.end(); ++iter) { + if(!TriangulateMonotone(&(*iter),triangles)) return 0; + } + return 1; +} + +int TPPLPartition::Triangulate_MONO(TPPLPoly *poly, list *triangles) { + list polys; + polys.push_back(*poly); + + return Triangulate_MONO(&polys, triangles); +} diff --git a/xs/src/polypartition.h b/src/polypartition/polypartition.h similarity index 97% rename from xs/src/polypartition.h rename to src/polypartition/polypartition.h index 2596243ae4..20ec0e24f6 100644 --- a/xs/src/polypartition.h +++ b/src/polypartition/polypartition.h @@ -1,343 +1,343 @@ -//Copyright (C) 2011 by Ivan Fratric -// -//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. - - -#include -using namespace std; - -typedef double tppl_float; - -#define TPPL_CCW 1 -#define TPPL_CW -1 - -//2D point structure -struct TPPLPoint { - tppl_float x; - tppl_float y; - - TPPLPoint operator + (const TPPLPoint& p) const { - TPPLPoint r; - r.x = x + p.x; - r.y = y + p.y; - return r; - } - - TPPLPoint operator - (const TPPLPoint& p) const { - TPPLPoint r; - r.x = x - p.x; - r.y = y - p.y; - return r; - } - - TPPLPoint operator * (const tppl_float f ) const { - TPPLPoint r; - r.x = x*f; - r.y = y*f; - return r; - } - - TPPLPoint operator / (const tppl_float f ) const { - TPPLPoint r; - r.x = x/f; - r.y = y/f; - return r; - } - - bool operator==(const TPPLPoint& p) const { - if((x == p.x)&&(y==p.y)) return true; - else return false; - } - - bool operator!=(const TPPLPoint& p) const { - if((x == p.x)&&(y==p.y)) return false; - else return true; - } -}; - -//Polygon implemented as an array of points with a 'hole' flag -class TPPLPoly { -protected: - - TPPLPoint *points; - long numpoints; - bool hole; - -public: - - //constructors/destructors - TPPLPoly(); - ~TPPLPoly(); - - TPPLPoly(const TPPLPoly &src); - TPPLPoly& operator=(const TPPLPoly &src); - - //getters and setters - long GetNumPoints() const { - return numpoints; - } - - bool IsHole() const { - return hole; - } - - void SetHole(bool hole) { - this->hole = hole; - } - - TPPLPoint &GetPoint(long i) { - return points[i]; - } - - TPPLPoint *GetPoints() { - return points; - } - - TPPLPoint& operator[] (int i) { - return points[i]; - } - - //clears the polygon points - void Clear(); - - //inits the polygon with numpoints vertices - void Init(long numpoints); - - //creates a triangle with points p1,p2,p3 - void Triangle(TPPLPoint &p1, TPPLPoint &p2, TPPLPoint &p3); - - //inverts the orfer of vertices - void Invert(); - - //returns the orientation of the polygon - //possible values: - // TPPL_CCW : polygon vertices are in counter-clockwise order - // TPPL_CW : polygon vertices are in clockwise order - // 0 : the polygon has no (measurable) area - int GetOrientation() const; - - //sets the polygon orientation - //orientation can be - // TPPL_CCW : sets vertices in counter-clockwise order - // TPPL_CW : sets vertices in clockwise order - void SetOrientation(int orientation); -}; - -class TPPLPartition { -protected: - struct PartitionVertex { - bool isActive; - bool isConvex; - bool isEar; - - TPPLPoint p; - tppl_float angle; - PartitionVertex *previous; - PartitionVertex *next; - }; - - struct MonotoneVertex { - TPPLPoint p; - long previous; - long next; - }; - - class VertexSorter{ - MonotoneVertex *vertices; - public: - VertexSorter(MonotoneVertex *v) : vertices(v) {} - bool operator() (long index1, long index2) const; - }; - - struct Diagonal { - long index1; - long index2; - }; - - //dynamic programming state for minimum-weight triangulation - struct DPState { - bool visible; - tppl_float weight; - long bestvertex; - }; - - //dynamic programming state for convex partitioning - struct DPState2 { - bool visible; - long weight; - list pairs; - }; - - //edge that intersects the scanline - struct ScanLineEdge { - long index; - TPPLPoint p1; - TPPLPoint p2; - - //determines if the edge is to the left of another edge - bool operator< (const ScanLineEdge & other) const; - - bool IsConvex(const TPPLPoint& p1, const TPPLPoint& p2, const TPPLPoint& p3) const; - }; - - //standard helper functions - bool IsConvex(TPPLPoint& p1, TPPLPoint& p2, TPPLPoint& p3); - bool IsReflex(TPPLPoint& p1, TPPLPoint& p2, TPPLPoint& p3); - bool IsInside(TPPLPoint& p1, TPPLPoint& p2, TPPLPoint& p3, TPPLPoint &p); - - bool InCone(TPPLPoint &p1, TPPLPoint &p2, TPPLPoint &p3, TPPLPoint &p); - bool InCone(PartitionVertex *v, TPPLPoint &p); - - int Intersects(TPPLPoint &p11, TPPLPoint &p12, TPPLPoint &p21, TPPLPoint &p22); - - TPPLPoint Normalize(const TPPLPoint &p); - tppl_float Distance(const TPPLPoint &p1, const TPPLPoint &p2); - - //helper functions for Triangulate_EC - void UpdateVertexReflexity(PartitionVertex *v); - void UpdateVertex(PartitionVertex *v,PartitionVertex *vertices, long numvertices); - - //helper functions for ConvexPartition_OPT - void UpdateState(long a, long b, long w, long i, long j, DPState2 **dpstates); - void TypeA(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates); - void TypeB(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates); - - //helper functions for MonotonePartition - bool Below(TPPLPoint &p1, TPPLPoint &p2); - void AddDiagonal(MonotoneVertex *vertices, long *numvertices, long index1, long index2); - - //triangulates a monotone polygon, used in Triangulate_MONO - int TriangulateMonotone(TPPLPoly *inPoly, list *triangles); - -public: - - //simple heuristic procedure for removing holes from a list of polygons - //works by creating a diagonal from the rightmost hole vertex to some visible vertex - //time complexity: O(h*(n^2)), h is the number of holes, n is the number of vertices - //space complexity: O(n) - //params: - // inpolys : a list of polygons that can contain holes - // vertices of all non-hole polys have to be in counter-clockwise order - // vertices of all hole polys have to be in clockwise order - // outpolys : a list of polygons without holes - //returns 1 on success, 0 on failure - int RemoveHoles(list *inpolys, list *outpolys); - - //triangulates a polygon by ear clipping - //time complexity O(n^2), n is the number of vertices - //space complexity: O(n) - //params: - // poly : an input polygon to be triangulated - // vertices have to be in counter-clockwise order - // triangles : a list of triangles (result) - //returns 1 on success, 0 on failure - int Triangulate_EC(TPPLPoly *poly, list *triangles); - - //triangulates a list of polygons that may contain holes by ear clipping algorithm - //first calls RemoveHoles to get rid of the holes, and then Triangulate_EC for each resulting polygon - //time complexity: O(h*(n^2)), h is the number of holes, n is the number of vertices - //space complexity: O(n) - //params: - // inpolys : a list of polygons to be triangulated (can contain holes) - // vertices of all non-hole polys have to be in counter-clockwise order - // vertices of all hole polys have to be in clockwise order - // triangles : a list of triangles (result) - //returns 1 on success, 0 on failure - int Triangulate_EC(list *inpolys, list *triangles); - - //creates an optimal polygon triangulation in terms of minimal edge length - //time complexity: O(n^3), n is the number of vertices - //space complexity: O(n^2) - //params: - // poly : an input polygon to be triangulated - // vertices have to be in counter-clockwise order - // triangles : a list of triangles (result) - //returns 1 on success, 0 on failure - int Triangulate_OPT(TPPLPoly *poly, list *triangles); - - //triangulates a polygons by firstly partitioning it into monotone polygons - //time complexity: O(n*log(n)), n is the number of vertices - //space complexity: O(n) - //params: - // poly : an input polygon to be triangulated - // vertices have to be in counter-clockwise order - // triangles : a list of triangles (result) - //returns 1 on success, 0 on failure - int Triangulate_MONO(TPPLPoly *poly, list *triangles); - - //triangulates a list of polygons by firstly partitioning them into monotone polygons - //time complexity: O(n*log(n)), n is the number of vertices - //space complexity: O(n) - //params: - // inpolys : a list of polygons to be triangulated (can contain holes) - // vertices of all non-hole polys have to be in counter-clockwise order - // vertices of all hole polys have to be in clockwise order - // triangles : a list of triangles (result) - //returns 1 on success, 0 on failure - int Triangulate_MONO(list *inpolys, list *triangles); - - //creates a monotone partition of a list of polygons that can contain holes - //time complexity: O(n*log(n)), n is the number of vertices - //space complexity: O(n) - //params: - // inpolys : a list of polygons to be triangulated (can contain holes) - // vertices of all non-hole polys have to be in counter-clockwise order - // vertices of all hole polys have to be in clockwise order - // monotonePolys : a list of monotone polygons (result) - //returns 1 on success, 0 on failure - int MonotonePartition(list *inpolys, list *monotonePolys); - - //partitions a polygon into convex polygons by using Hertel-Mehlhorn algorithm - //the algorithm gives at most four times the number of parts as the optimal algorithm - //however, in practice it works much better than that and often gives optimal partition - //uses triangulation obtained by ear clipping as intermediate result - //time complexity O(n^2), n is the number of vertices - //space complexity: O(n) - //params: - // poly : an input polygon to be partitioned - // vertices have to be in counter-clockwise order - // parts : resulting list of convex polygons - //returns 1 on success, 0 on failure - int ConvexPartition_HM(TPPLPoly *poly, list *parts); - - //partitions a list of polygons into convex parts by using Hertel-Mehlhorn algorithm - //the algorithm gives at most four times the number of parts as the optimal algorithm - //however, in practice it works much better than that and often gives optimal partition - //uses triangulation obtained by ear clipping as intermediate result - //time complexity O(n^2), n is the number of vertices - //space complexity: O(n) - //params: - // inpolys : an input list of polygons to be partitioned - // vertices of all non-hole polys have to be in counter-clockwise order - // vertices of all hole polys have to be in clockwise order - // parts : resulting list of convex polygons - //returns 1 on success, 0 on failure - int ConvexPartition_HM(list *inpolys, list *parts); - - //optimal convex partitioning (in terms of number of resulting convex polygons) - //using the Keil-Snoeyink algorithm - //M. Keil, J. Snoeyink, "On the time bound for convex decomposition of simple polygons", 1998 - //time complexity O(n^3), n is the number of vertices - //space complexity: O(n^3) - // poly : an input polygon to be partitioned - // vertices have to be in counter-clockwise order - // parts : resulting list of convex polygons - //returns 1 on success, 0 on failure - int ConvexPartition_OPT(TPPLPoly *poly, list *parts); -}; +//Copyright (C) 2011 by Ivan Fratric +// +//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. + + +#include +using namespace std; + +typedef double tppl_float; + +#define TPPL_CCW 1 +#define TPPL_CW -1 + +//2D point structure +struct TPPLPoint { + tppl_float x; + tppl_float y; + + TPPLPoint operator + (const TPPLPoint& p) const { + TPPLPoint r; + r.x = x + p.x; + r.y = y + p.y; + return r; + } + + TPPLPoint operator - (const TPPLPoint& p) const { + TPPLPoint r; + r.x = x - p.x; + r.y = y - p.y; + return r; + } + + TPPLPoint operator * (const tppl_float f ) const { + TPPLPoint r; + r.x = x*f; + r.y = y*f; + return r; + } + + TPPLPoint operator / (const tppl_float f ) const { + TPPLPoint r; + r.x = x/f; + r.y = y/f; + return r; + } + + bool operator==(const TPPLPoint& p) const { + if((x == p.x)&&(y==p.y)) return true; + else return false; + } + + bool operator!=(const TPPLPoint& p) const { + if((x == p.x)&&(y==p.y)) return false; + else return true; + } +}; + +//Polygon implemented as an array of points with a 'hole' flag +class TPPLPoly { +protected: + + TPPLPoint *points; + long numpoints; + bool hole; + +public: + + //constructors/destructors + TPPLPoly(); + ~TPPLPoly(); + + TPPLPoly(const TPPLPoly &src); + TPPLPoly& operator=(const TPPLPoly &src); + + //getters and setters + long GetNumPoints() const { + return numpoints; + } + + bool IsHole() const { + return hole; + } + + void SetHole(bool hole) { + this->hole = hole; + } + + TPPLPoint &GetPoint(long i) { + return points[i]; + } + + TPPLPoint *GetPoints() { + return points; + } + + TPPLPoint& operator[] (int i) { + return points[i]; + } + + //clears the polygon points + void Clear(); + + //inits the polygon with numpoints vertices + void Init(long numpoints); + + //creates a triangle with points p1,p2,p3 + void Triangle(TPPLPoint &p1, TPPLPoint &p2, TPPLPoint &p3); + + //inverts the orfer of vertices + void Invert(); + + //returns the orientation of the polygon + //possible values: + // TPPL_CCW : polygon vertices are in counter-clockwise order + // TPPL_CW : polygon vertices are in clockwise order + // 0 : the polygon has no (measurable) area + int GetOrientation() const; + + //sets the polygon orientation + //orientation can be + // TPPL_CCW : sets vertices in counter-clockwise order + // TPPL_CW : sets vertices in clockwise order + void SetOrientation(int orientation); +}; + +class TPPLPartition { +protected: + struct PartitionVertex { + bool isActive; + bool isConvex; + bool isEar; + + TPPLPoint p; + tppl_float angle; + PartitionVertex *previous; + PartitionVertex *next; + }; + + struct MonotoneVertex { + TPPLPoint p; + long previous; + long next; + }; + + class VertexSorter{ + MonotoneVertex *vertices; + public: + VertexSorter(MonotoneVertex *v) : vertices(v) {} + bool operator() (long index1, long index2) const; + }; + + struct Diagonal { + long index1; + long index2; + }; + + //dynamic programming state for minimum-weight triangulation + struct DPState { + bool visible; + tppl_float weight; + long bestvertex; + }; + + //dynamic programming state for convex partitioning + struct DPState2 { + bool visible; + long weight; + list pairs; + }; + + //edge that intersects the scanline + struct ScanLineEdge { + long index; + TPPLPoint p1; + TPPLPoint p2; + + //determines if the edge is to the left of another edge + bool operator< (const ScanLineEdge & other) const; + + bool IsConvex(const TPPLPoint& p1, const TPPLPoint& p2, const TPPLPoint& p3) const; + }; + + //standard helper functions + bool IsConvex(TPPLPoint& p1, TPPLPoint& p2, TPPLPoint& p3); + bool IsReflex(TPPLPoint& p1, TPPLPoint& p2, TPPLPoint& p3); + bool IsInside(TPPLPoint& p1, TPPLPoint& p2, TPPLPoint& p3, TPPLPoint &p); + + bool InCone(TPPLPoint &p1, TPPLPoint &p2, TPPLPoint &p3, TPPLPoint &p); + bool InCone(PartitionVertex *v, TPPLPoint &p); + + int Intersects(TPPLPoint &p11, TPPLPoint &p12, TPPLPoint &p21, TPPLPoint &p22); + + TPPLPoint Normalize(const TPPLPoint &p); + tppl_float Distance(const TPPLPoint &p1, const TPPLPoint &p2); + + //helper functions for Triangulate_EC + void UpdateVertexReflexity(PartitionVertex *v); + void UpdateVertex(PartitionVertex *v,PartitionVertex *vertices, long numvertices); + + //helper functions for ConvexPartition_OPT + void UpdateState(long a, long b, long w, long i, long j, DPState2 **dpstates); + void TypeA(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates); + void TypeB(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates); + + //helper functions for MonotonePartition + bool Below(TPPLPoint &p1, TPPLPoint &p2); + void AddDiagonal(MonotoneVertex *vertices, long *numvertices, long index1, long index2); + + //triangulates a monotone polygon, used in Triangulate_MONO + int TriangulateMonotone(TPPLPoly *inPoly, list *triangles); + +public: + + //simple heuristic procedure for removing holes from a list of polygons + //works by creating a diagonal from the rightmost hole vertex to some visible vertex + //time complexity: O(h*(n^2)), h is the number of holes, n is the number of vertices + //space complexity: O(n) + //params: + // inpolys : a list of polygons that can contain holes + // vertices of all non-hole polys have to be in counter-clockwise order + // vertices of all hole polys have to be in clockwise order + // outpolys : a list of polygons without holes + //returns 1 on success, 0 on failure + int RemoveHoles(list *inpolys, list *outpolys); + + //triangulates a polygon by ear clipping + //time complexity O(n^2), n is the number of vertices + //space complexity: O(n) + //params: + // poly : an input polygon to be triangulated + // vertices have to be in counter-clockwise order + // triangles : a list of triangles (result) + //returns 1 on success, 0 on failure + int Triangulate_EC(TPPLPoly *poly, list *triangles); + + //triangulates a list of polygons that may contain holes by ear clipping algorithm + //first calls RemoveHoles to get rid of the holes, and then Triangulate_EC for each resulting polygon + //time complexity: O(h*(n^2)), h is the number of holes, n is the number of vertices + //space complexity: O(n) + //params: + // inpolys : a list of polygons to be triangulated (can contain holes) + // vertices of all non-hole polys have to be in counter-clockwise order + // vertices of all hole polys have to be in clockwise order + // triangles : a list of triangles (result) + //returns 1 on success, 0 on failure + int Triangulate_EC(list *inpolys, list *triangles); + + //creates an optimal polygon triangulation in terms of minimal edge length + //time complexity: O(n^3), n is the number of vertices + //space complexity: O(n^2) + //params: + // poly : an input polygon to be triangulated + // vertices have to be in counter-clockwise order + // triangles : a list of triangles (result) + //returns 1 on success, 0 on failure + int Triangulate_OPT(TPPLPoly *poly, list *triangles); + + //triangulates a polygons by firstly partitioning it into monotone polygons + //time complexity: O(n*log(n)), n is the number of vertices + //space complexity: O(n) + //params: + // poly : an input polygon to be triangulated + // vertices have to be in counter-clockwise order + // triangles : a list of triangles (result) + //returns 1 on success, 0 on failure + int Triangulate_MONO(TPPLPoly *poly, list *triangles); + + //triangulates a list of polygons by firstly partitioning them into monotone polygons + //time complexity: O(n*log(n)), n is the number of vertices + //space complexity: O(n) + //params: + // inpolys : a list of polygons to be triangulated (can contain holes) + // vertices of all non-hole polys have to be in counter-clockwise order + // vertices of all hole polys have to be in clockwise order + // triangles : a list of triangles (result) + //returns 1 on success, 0 on failure + int Triangulate_MONO(list *inpolys, list *triangles); + + //creates a monotone partition of a list of polygons that can contain holes + //time complexity: O(n*log(n)), n is the number of vertices + //space complexity: O(n) + //params: + // inpolys : a list of polygons to be triangulated (can contain holes) + // vertices of all non-hole polys have to be in counter-clockwise order + // vertices of all hole polys have to be in clockwise order + // monotonePolys : a list of monotone polygons (result) + //returns 1 on success, 0 on failure + int MonotonePartition(list *inpolys, list *monotonePolys); + + //partitions a polygon into convex polygons by using Hertel-Mehlhorn algorithm + //the algorithm gives at most four times the number of parts as the optimal algorithm + //however, in practice it works much better than that and often gives optimal partition + //uses triangulation obtained by ear clipping as intermediate result + //time complexity O(n^2), n is the number of vertices + //space complexity: O(n) + //params: + // poly : an input polygon to be partitioned + // vertices have to be in counter-clockwise order + // parts : resulting list of convex polygons + //returns 1 on success, 0 on failure + int ConvexPartition_HM(TPPLPoly *poly, list *parts); + + //partitions a list of polygons into convex parts by using Hertel-Mehlhorn algorithm + //the algorithm gives at most four times the number of parts as the optimal algorithm + //however, in practice it works much better than that and often gives optimal partition + //uses triangulation obtained by ear clipping as intermediate result + //time complexity O(n^2), n is the number of vertices + //space complexity: O(n) + //params: + // inpolys : an input list of polygons to be partitioned + // vertices of all non-hole polys have to be in counter-clockwise order + // vertices of all hole polys have to be in clockwise order + // parts : resulting list of convex polygons + //returns 1 on success, 0 on failure + int ConvexPartition_HM(list *inpolys, list *parts); + + //optimal convex partitioning (in terms of number of resulting convex polygons) + //using the Keil-Snoeyink algorithm + //M. Keil, J. Snoeyink, "On the time bound for convex decomposition of simple polygons", 1998 + //time complexity O(n^3), n is the number of vertices + //space complexity: O(n^3) + // poly : an input polygon to be partitioned + // vertices have to be in counter-clockwise order + // parts : resulting list of convex polygons + //returns 1 on success, 0 on failure + int ConvexPartition_OPT(TPPLPoly *poly, list *parts); +}; diff --git a/xs/src/qhull/Announce.txt b/src/qhull/Announce.txt similarity index 100% rename from xs/src/qhull/Announce.txt rename to src/qhull/Announce.txt diff --git a/xs/src/qhull/CMakeLists.txt b/src/qhull/CMakeLists.txt similarity index 100% rename from xs/src/qhull/CMakeLists.txt rename to src/qhull/CMakeLists.txt diff --git a/xs/src/qhull/COPYING.txt b/src/qhull/COPYING.txt similarity index 100% rename from xs/src/qhull/COPYING.txt rename to src/qhull/COPYING.txt diff --git a/xs/src/qhull/README.txt b/src/qhull/README.txt similarity index 100% rename from xs/src/qhull/README.txt rename to src/qhull/README.txt diff --git a/xs/src/qhull/REGISTER.txt b/src/qhull/REGISTER.txt similarity index 100% rename from xs/src/qhull/REGISTER.txt rename to src/qhull/REGISTER.txt diff --git a/xs/src/qhull/html/index.htm b/src/qhull/html/index.htm similarity index 100% rename from xs/src/qhull/html/index.htm rename to src/qhull/html/index.htm diff --git a/xs/src/qhull/html/normal_voronoi_knauss_oesterle.jpg b/src/qhull/html/normal_voronoi_knauss_oesterle.jpg similarity index 100% rename from xs/src/qhull/html/normal_voronoi_knauss_oesterle.jpg rename to src/qhull/html/normal_voronoi_knauss_oesterle.jpg diff --git a/xs/src/qhull/html/qconvex.htm b/src/qhull/html/qconvex.htm similarity index 100% rename from xs/src/qhull/html/qconvex.htm rename to src/qhull/html/qconvex.htm diff --git a/xs/src/qhull/html/qdelau_f.htm b/src/qhull/html/qdelau_f.htm similarity index 100% rename from xs/src/qhull/html/qdelau_f.htm rename to src/qhull/html/qdelau_f.htm diff --git a/xs/src/qhull/html/qdelaun.htm b/src/qhull/html/qdelaun.htm similarity index 100% rename from xs/src/qhull/html/qdelaun.htm rename to src/qhull/html/qdelaun.htm diff --git a/xs/src/qhull/html/qh--4d.gif b/src/qhull/html/qh--4d.gif similarity index 100% rename from xs/src/qhull/html/qh--4d.gif rename to src/qhull/html/qh--4d.gif diff --git a/xs/src/qhull/html/qh--cone.gif b/src/qhull/html/qh--cone.gif similarity index 100% rename from xs/src/qhull/html/qh--cone.gif rename to src/qhull/html/qh--cone.gif diff --git a/xs/src/qhull/html/qh--dt.gif b/src/qhull/html/qh--dt.gif similarity index 100% rename from xs/src/qhull/html/qh--dt.gif rename to src/qhull/html/qh--dt.gif diff --git a/xs/src/qhull/html/qh--geom.gif b/src/qhull/html/qh--geom.gif similarity index 100% rename from xs/src/qhull/html/qh--geom.gif rename to src/qhull/html/qh--geom.gif diff --git a/xs/src/qhull/html/qh--half.gif b/src/qhull/html/qh--half.gif similarity index 100% rename from xs/src/qhull/html/qh--half.gif rename to src/qhull/html/qh--half.gif diff --git a/xs/src/qhull/html/qh--rand.gif b/src/qhull/html/qh--rand.gif similarity index 100% rename from xs/src/qhull/html/qh--rand.gif rename to src/qhull/html/qh--rand.gif diff --git a/xs/src/qhull/html/qh-code.htm b/src/qhull/html/qh-code.htm similarity index 100% rename from xs/src/qhull/html/qh-code.htm rename to src/qhull/html/qh-code.htm diff --git a/xs/src/qhull/html/qh-eg.htm b/src/qhull/html/qh-eg.htm similarity index 100% rename from xs/src/qhull/html/qh-eg.htm rename to src/qhull/html/qh-eg.htm diff --git a/xs/src/qhull/html/qh-faq.htm b/src/qhull/html/qh-faq.htm similarity index 100% rename from xs/src/qhull/html/qh-faq.htm rename to src/qhull/html/qh-faq.htm diff --git a/xs/src/qhull/html/qh-get.htm b/src/qhull/html/qh-get.htm similarity index 100% rename from xs/src/qhull/html/qh-get.htm rename to src/qhull/html/qh-get.htm diff --git a/xs/src/qhull/html/qh-impre.htm b/src/qhull/html/qh-impre.htm similarity index 100% rename from xs/src/qhull/html/qh-impre.htm rename to src/qhull/html/qh-impre.htm diff --git a/xs/src/qhull/html/qh-optc.htm b/src/qhull/html/qh-optc.htm similarity index 100% rename from xs/src/qhull/html/qh-optc.htm rename to src/qhull/html/qh-optc.htm diff --git a/xs/src/qhull/html/qh-optf.htm b/src/qhull/html/qh-optf.htm similarity index 100% rename from xs/src/qhull/html/qh-optf.htm rename to src/qhull/html/qh-optf.htm diff --git a/xs/src/qhull/html/qh-optg.htm b/src/qhull/html/qh-optg.htm similarity index 100% rename from xs/src/qhull/html/qh-optg.htm rename to src/qhull/html/qh-optg.htm diff --git a/xs/src/qhull/html/qh-opto.htm b/src/qhull/html/qh-opto.htm similarity index 100% rename from xs/src/qhull/html/qh-opto.htm rename to src/qhull/html/qh-opto.htm diff --git a/xs/src/qhull/html/qh-optp.htm b/src/qhull/html/qh-optp.htm similarity index 100% rename from xs/src/qhull/html/qh-optp.htm rename to src/qhull/html/qh-optp.htm diff --git a/xs/src/qhull/html/qh-optq.htm b/src/qhull/html/qh-optq.htm similarity index 100% rename from xs/src/qhull/html/qh-optq.htm rename to src/qhull/html/qh-optq.htm diff --git a/xs/src/qhull/html/qh-optt.htm b/src/qhull/html/qh-optt.htm similarity index 100% rename from xs/src/qhull/html/qh-optt.htm rename to src/qhull/html/qh-optt.htm diff --git a/xs/src/qhull/html/qh-quick.htm b/src/qhull/html/qh-quick.htm similarity index 100% rename from xs/src/qhull/html/qh-quick.htm rename to src/qhull/html/qh-quick.htm diff --git a/xs/src/qhull/html/qhalf.htm b/src/qhull/html/qhalf.htm similarity index 100% rename from xs/src/qhull/html/qhalf.htm rename to src/qhull/html/qhalf.htm diff --git a/xs/src/qhull/html/qhull-cpp.xml b/src/qhull/html/qhull-cpp.xml similarity index 100% rename from xs/src/qhull/html/qhull-cpp.xml rename to src/qhull/html/qhull-cpp.xml diff --git a/xs/src/qhull/html/qhull.htm b/src/qhull/html/qhull.htm similarity index 100% rename from xs/src/qhull/html/qhull.htm rename to src/qhull/html/qhull.htm diff --git a/xs/src/qhull/html/qhull.man b/src/qhull/html/qhull.man similarity index 100% rename from xs/src/qhull/html/qhull.man rename to src/qhull/html/qhull.man diff --git a/xs/src/qhull/html/qhull.txt b/src/qhull/html/qhull.txt similarity index 100% rename from xs/src/qhull/html/qhull.txt rename to src/qhull/html/qhull.txt diff --git a/xs/src/qhull/html/qvoron_f.htm b/src/qhull/html/qvoron_f.htm similarity index 100% rename from xs/src/qhull/html/qvoron_f.htm rename to src/qhull/html/qvoron_f.htm diff --git a/xs/src/qhull/html/qvoronoi.htm b/src/qhull/html/qvoronoi.htm similarity index 100% rename from xs/src/qhull/html/qvoronoi.htm rename to src/qhull/html/qvoronoi.htm diff --git a/xs/src/qhull/html/rbox.htm b/src/qhull/html/rbox.htm similarity index 100% rename from xs/src/qhull/html/rbox.htm rename to src/qhull/html/rbox.htm diff --git a/xs/src/qhull/html/rbox.man b/src/qhull/html/rbox.man similarity index 100% rename from xs/src/qhull/html/rbox.man rename to src/qhull/html/rbox.man diff --git a/xs/src/qhull/html/rbox.txt b/src/qhull/html/rbox.txt similarity index 100% rename from xs/src/qhull/html/rbox.txt rename to src/qhull/html/rbox.txt diff --git a/xs/src/qhull/index.htm b/src/qhull/index.htm similarity index 100% rename from xs/src/qhull/index.htm rename to src/qhull/index.htm diff --git a/xs/src/qhull/origCMakeLists.txt b/src/qhull/origCMakeLists.txt similarity index 100% rename from xs/src/qhull/origCMakeLists.txt rename to src/qhull/origCMakeLists.txt diff --git a/xs/src/qhull/src/Changes.txt b/src/qhull/src/Changes.txt similarity index 100% rename from xs/src/qhull/src/Changes.txt rename to src/qhull/src/Changes.txt diff --git a/xs/src/qhull/src/libqhull/DEPRECATED.txt b/src/qhull/src/libqhull/DEPRECATED.txt similarity index 100% rename from xs/src/qhull/src/libqhull/DEPRECATED.txt rename to src/qhull/src/libqhull/DEPRECATED.txt diff --git a/xs/src/qhull/src/libqhull/Makefile b/src/qhull/src/libqhull/Makefile similarity index 100% rename from xs/src/qhull/src/libqhull/Makefile rename to src/qhull/src/libqhull/Makefile diff --git a/xs/src/qhull/src/libqhull/Mborland b/src/qhull/src/libqhull/Mborland similarity index 100% rename from xs/src/qhull/src/libqhull/Mborland rename to src/qhull/src/libqhull/Mborland diff --git a/xs/src/qhull/src/libqhull/geom.c b/src/qhull/src/libqhull/geom.c similarity index 100% rename from xs/src/qhull/src/libqhull/geom.c rename to src/qhull/src/libqhull/geom.c diff --git a/xs/src/qhull/src/libqhull/geom.h b/src/qhull/src/libqhull/geom.h similarity index 100% rename from xs/src/qhull/src/libqhull/geom.h rename to src/qhull/src/libqhull/geom.h diff --git a/xs/src/qhull/src/libqhull/geom2.c b/src/qhull/src/libqhull/geom2.c similarity index 100% rename from xs/src/qhull/src/libqhull/geom2.c rename to src/qhull/src/libqhull/geom2.c diff --git a/xs/src/qhull/src/libqhull/global.c b/src/qhull/src/libqhull/global.c similarity index 100% rename from xs/src/qhull/src/libqhull/global.c rename to src/qhull/src/libqhull/global.c diff --git a/xs/src/qhull/src/libqhull/index.htm b/src/qhull/src/libqhull/index.htm similarity index 100% rename from xs/src/qhull/src/libqhull/index.htm rename to src/qhull/src/libqhull/index.htm diff --git a/xs/src/qhull/src/libqhull/io.c b/src/qhull/src/libqhull/io.c similarity index 100% rename from xs/src/qhull/src/libqhull/io.c rename to src/qhull/src/libqhull/io.c diff --git a/xs/src/qhull/src/libqhull/io.h b/src/qhull/src/libqhull/io.h similarity index 100% rename from xs/src/qhull/src/libqhull/io.h rename to src/qhull/src/libqhull/io.h diff --git a/xs/src/qhull/src/libqhull/libqhull.c b/src/qhull/src/libqhull/libqhull.c similarity index 100% rename from xs/src/qhull/src/libqhull/libqhull.c rename to src/qhull/src/libqhull/libqhull.c diff --git a/xs/src/qhull/src/libqhull/libqhull.h b/src/qhull/src/libqhull/libqhull.h similarity index 100% rename from xs/src/qhull/src/libqhull/libqhull.h rename to src/qhull/src/libqhull/libqhull.h diff --git a/xs/src/qhull/src/libqhull/libqhull.pro b/src/qhull/src/libqhull/libqhull.pro similarity index 100% rename from xs/src/qhull/src/libqhull/libqhull.pro rename to src/qhull/src/libqhull/libqhull.pro diff --git a/xs/src/qhull/src/libqhull/mem.c b/src/qhull/src/libqhull/mem.c similarity index 100% rename from xs/src/qhull/src/libqhull/mem.c rename to src/qhull/src/libqhull/mem.c diff --git a/xs/src/qhull/src/libqhull/mem.h b/src/qhull/src/libqhull/mem.h similarity index 100% rename from xs/src/qhull/src/libqhull/mem.h rename to src/qhull/src/libqhull/mem.h diff --git a/xs/src/qhull/src/libqhull/merge.c b/src/qhull/src/libqhull/merge.c similarity index 100% rename from xs/src/qhull/src/libqhull/merge.c rename to src/qhull/src/libqhull/merge.c diff --git a/xs/src/qhull/src/libqhull/merge.h b/src/qhull/src/libqhull/merge.h similarity index 100% rename from xs/src/qhull/src/libqhull/merge.h rename to src/qhull/src/libqhull/merge.h diff --git a/xs/src/qhull/src/libqhull/poly.c b/src/qhull/src/libqhull/poly.c similarity index 100% rename from xs/src/qhull/src/libqhull/poly.c rename to src/qhull/src/libqhull/poly.c diff --git a/xs/src/qhull/src/libqhull/poly.h b/src/qhull/src/libqhull/poly.h similarity index 100% rename from xs/src/qhull/src/libqhull/poly.h rename to src/qhull/src/libqhull/poly.h diff --git a/xs/src/qhull/src/libqhull/poly2.c b/src/qhull/src/libqhull/poly2.c similarity index 100% rename from xs/src/qhull/src/libqhull/poly2.c rename to src/qhull/src/libqhull/poly2.c diff --git a/xs/src/qhull/src/libqhull/qh-geom.htm b/src/qhull/src/libqhull/qh-geom.htm similarity index 100% rename from xs/src/qhull/src/libqhull/qh-geom.htm rename to src/qhull/src/libqhull/qh-geom.htm diff --git a/xs/src/qhull/src/libqhull/qh-globa.htm b/src/qhull/src/libqhull/qh-globa.htm similarity index 100% rename from xs/src/qhull/src/libqhull/qh-globa.htm rename to src/qhull/src/libqhull/qh-globa.htm diff --git a/xs/src/qhull/src/libqhull/qh-io.htm b/src/qhull/src/libqhull/qh-io.htm similarity index 100% rename from xs/src/qhull/src/libqhull/qh-io.htm rename to src/qhull/src/libqhull/qh-io.htm diff --git a/xs/src/qhull/src/libqhull/qh-mem.htm b/src/qhull/src/libqhull/qh-mem.htm similarity index 100% rename from xs/src/qhull/src/libqhull/qh-mem.htm rename to src/qhull/src/libqhull/qh-mem.htm diff --git a/xs/src/qhull/src/libqhull/qh-merge.htm b/src/qhull/src/libqhull/qh-merge.htm similarity index 100% rename from xs/src/qhull/src/libqhull/qh-merge.htm rename to src/qhull/src/libqhull/qh-merge.htm diff --git a/xs/src/qhull/src/libqhull/qh-poly.htm b/src/qhull/src/libqhull/qh-poly.htm similarity index 100% rename from xs/src/qhull/src/libqhull/qh-poly.htm rename to src/qhull/src/libqhull/qh-poly.htm diff --git a/xs/src/qhull/src/libqhull/qh-qhull.htm b/src/qhull/src/libqhull/qh-qhull.htm similarity index 100% rename from xs/src/qhull/src/libqhull/qh-qhull.htm rename to src/qhull/src/libqhull/qh-qhull.htm diff --git a/xs/src/qhull/src/libqhull/qh-set.htm b/src/qhull/src/libqhull/qh-set.htm similarity index 100% rename from xs/src/qhull/src/libqhull/qh-set.htm rename to src/qhull/src/libqhull/qh-set.htm diff --git a/xs/src/qhull/src/libqhull/qh-stat.htm b/src/qhull/src/libqhull/qh-stat.htm similarity index 100% rename from xs/src/qhull/src/libqhull/qh-stat.htm rename to src/qhull/src/libqhull/qh-stat.htm diff --git a/xs/src/qhull/src/libqhull/qh-user.htm b/src/qhull/src/libqhull/qh-user.htm similarity index 100% rename from xs/src/qhull/src/libqhull/qh-user.htm rename to src/qhull/src/libqhull/qh-user.htm diff --git a/xs/src/qhull/src/libqhull/qhull-exports.def b/src/qhull/src/libqhull/qhull-exports.def similarity index 100% rename from xs/src/qhull/src/libqhull/qhull-exports.def rename to src/qhull/src/libqhull/qhull-exports.def diff --git a/xs/src/qhull/src/libqhull/qhull_a.h b/src/qhull/src/libqhull/qhull_a.h similarity index 100% rename from xs/src/qhull/src/libqhull/qhull_a.h rename to src/qhull/src/libqhull/qhull_a.h diff --git a/xs/src/qhull/src/libqhull/qhull_p-exports.def b/src/qhull/src/libqhull/qhull_p-exports.def similarity index 100% rename from xs/src/qhull/src/libqhull/qhull_p-exports.def rename to src/qhull/src/libqhull/qhull_p-exports.def diff --git a/xs/src/qhull/src/libqhull/qset.c b/src/qhull/src/libqhull/qset.c similarity index 100% rename from xs/src/qhull/src/libqhull/qset.c rename to src/qhull/src/libqhull/qset.c diff --git a/xs/src/qhull/src/libqhull/qset.h b/src/qhull/src/libqhull/qset.h similarity index 100% rename from xs/src/qhull/src/libqhull/qset.h rename to src/qhull/src/libqhull/qset.h diff --git a/xs/src/qhull/src/libqhull/random.c b/src/qhull/src/libqhull/random.c similarity index 100% rename from xs/src/qhull/src/libqhull/random.c rename to src/qhull/src/libqhull/random.c diff --git a/xs/src/qhull/src/libqhull/random.h b/src/qhull/src/libqhull/random.h similarity index 100% rename from xs/src/qhull/src/libqhull/random.h rename to src/qhull/src/libqhull/random.h diff --git a/xs/src/qhull/src/libqhull/rboxlib.c b/src/qhull/src/libqhull/rboxlib.c similarity index 100% rename from xs/src/qhull/src/libqhull/rboxlib.c rename to src/qhull/src/libqhull/rboxlib.c diff --git a/xs/src/qhull/src/libqhull/stat.c b/src/qhull/src/libqhull/stat.c similarity index 100% rename from xs/src/qhull/src/libqhull/stat.c rename to src/qhull/src/libqhull/stat.c diff --git a/xs/src/qhull/src/libqhull/stat.h b/src/qhull/src/libqhull/stat.h similarity index 100% rename from xs/src/qhull/src/libqhull/stat.h rename to src/qhull/src/libqhull/stat.h diff --git a/xs/src/qhull/src/libqhull/user.c b/src/qhull/src/libqhull/user.c similarity index 100% rename from xs/src/qhull/src/libqhull/user.c rename to src/qhull/src/libqhull/user.c diff --git a/xs/src/qhull/src/libqhull/user.h b/src/qhull/src/libqhull/user.h similarity index 100% rename from xs/src/qhull/src/libqhull/user.h rename to src/qhull/src/libqhull/user.h diff --git a/xs/src/qhull/src/libqhull/usermem.c b/src/qhull/src/libqhull/usermem.c similarity index 100% rename from xs/src/qhull/src/libqhull/usermem.c rename to src/qhull/src/libqhull/usermem.c diff --git a/xs/src/qhull/src/libqhull/userprintf.c b/src/qhull/src/libqhull/userprintf.c similarity index 100% rename from xs/src/qhull/src/libqhull/userprintf.c rename to src/qhull/src/libqhull/userprintf.c diff --git a/xs/src/qhull/src/libqhull/userprintf_rbox.c b/src/qhull/src/libqhull/userprintf_rbox.c similarity index 100% rename from xs/src/qhull/src/libqhull/userprintf_rbox.c rename to src/qhull/src/libqhull/userprintf_rbox.c diff --git a/xs/src/qhull/src/libqhull_r/Makefile b/src/qhull/src/libqhull_r/Makefile similarity index 100% rename from xs/src/qhull/src/libqhull_r/Makefile rename to src/qhull/src/libqhull_r/Makefile diff --git a/xs/src/qhull/src/libqhull_r/geom2_r.c b/src/qhull/src/libqhull_r/geom2_r.c similarity index 100% rename from xs/src/qhull/src/libqhull_r/geom2_r.c rename to src/qhull/src/libqhull_r/geom2_r.c diff --git a/xs/src/qhull/src/libqhull_r/geom_r.c b/src/qhull/src/libqhull_r/geom_r.c similarity index 100% rename from xs/src/qhull/src/libqhull_r/geom_r.c rename to src/qhull/src/libqhull_r/geom_r.c diff --git a/xs/src/qhull/src/libqhull_r/geom_r.h b/src/qhull/src/libqhull_r/geom_r.h similarity index 100% rename from xs/src/qhull/src/libqhull_r/geom_r.h rename to src/qhull/src/libqhull_r/geom_r.h diff --git a/xs/src/qhull/src/libqhull_r/global_r.c b/src/qhull/src/libqhull_r/global_r.c similarity index 100% rename from xs/src/qhull/src/libqhull_r/global_r.c rename to src/qhull/src/libqhull_r/global_r.c diff --git a/xs/src/qhull/src/libqhull_r/index.htm b/src/qhull/src/libqhull_r/index.htm similarity index 100% rename from xs/src/qhull/src/libqhull_r/index.htm rename to src/qhull/src/libqhull_r/index.htm diff --git a/xs/src/qhull/src/libqhull_r/io_r.c b/src/qhull/src/libqhull_r/io_r.c similarity index 100% rename from xs/src/qhull/src/libqhull_r/io_r.c rename to src/qhull/src/libqhull_r/io_r.c diff --git a/xs/src/qhull/src/libqhull_r/io_r.h b/src/qhull/src/libqhull_r/io_r.h similarity index 100% rename from xs/src/qhull/src/libqhull_r/io_r.h rename to src/qhull/src/libqhull_r/io_r.h diff --git a/xs/src/qhull/src/libqhull_r/libqhull_r.c b/src/qhull/src/libqhull_r/libqhull_r.c similarity index 100% rename from xs/src/qhull/src/libqhull_r/libqhull_r.c rename to src/qhull/src/libqhull_r/libqhull_r.c diff --git a/xs/src/qhull/src/libqhull_r/libqhull_r.h b/src/qhull/src/libqhull_r/libqhull_r.h similarity index 100% rename from xs/src/qhull/src/libqhull_r/libqhull_r.h rename to src/qhull/src/libqhull_r/libqhull_r.h diff --git a/xs/src/qhull/src/libqhull_r/libqhull_r.pro b/src/qhull/src/libqhull_r/libqhull_r.pro similarity index 100% rename from xs/src/qhull/src/libqhull_r/libqhull_r.pro rename to src/qhull/src/libqhull_r/libqhull_r.pro diff --git a/xs/src/qhull/src/libqhull_r/mem_r.c b/src/qhull/src/libqhull_r/mem_r.c similarity index 100% rename from xs/src/qhull/src/libqhull_r/mem_r.c rename to src/qhull/src/libqhull_r/mem_r.c diff --git a/xs/src/qhull/src/libqhull_r/mem_r.h b/src/qhull/src/libqhull_r/mem_r.h similarity index 100% rename from xs/src/qhull/src/libqhull_r/mem_r.h rename to src/qhull/src/libqhull_r/mem_r.h diff --git a/xs/src/qhull/src/libqhull_r/merge_r.c b/src/qhull/src/libqhull_r/merge_r.c similarity index 100% rename from xs/src/qhull/src/libqhull_r/merge_r.c rename to src/qhull/src/libqhull_r/merge_r.c diff --git a/xs/src/qhull/src/libqhull_r/merge_r.h b/src/qhull/src/libqhull_r/merge_r.h similarity index 100% rename from xs/src/qhull/src/libqhull_r/merge_r.h rename to src/qhull/src/libqhull_r/merge_r.h diff --git a/xs/src/qhull/src/libqhull_r/poly2_r.c b/src/qhull/src/libqhull_r/poly2_r.c similarity index 100% rename from xs/src/qhull/src/libqhull_r/poly2_r.c rename to src/qhull/src/libqhull_r/poly2_r.c diff --git a/xs/src/qhull/src/libqhull_r/poly_r.c b/src/qhull/src/libqhull_r/poly_r.c similarity index 100% rename from xs/src/qhull/src/libqhull_r/poly_r.c rename to src/qhull/src/libqhull_r/poly_r.c diff --git a/xs/src/qhull/src/libqhull_r/poly_r.h b/src/qhull/src/libqhull_r/poly_r.h similarity index 100% rename from xs/src/qhull/src/libqhull_r/poly_r.h rename to src/qhull/src/libqhull_r/poly_r.h diff --git a/xs/src/qhull/src/libqhull_r/qh-geom_r.htm b/src/qhull/src/libqhull_r/qh-geom_r.htm similarity index 100% rename from xs/src/qhull/src/libqhull_r/qh-geom_r.htm rename to src/qhull/src/libqhull_r/qh-geom_r.htm diff --git a/xs/src/qhull/src/libqhull_r/qh-globa_r.htm b/src/qhull/src/libqhull_r/qh-globa_r.htm similarity index 100% rename from xs/src/qhull/src/libqhull_r/qh-globa_r.htm rename to src/qhull/src/libqhull_r/qh-globa_r.htm diff --git a/xs/src/qhull/src/libqhull_r/qh-io_r.htm b/src/qhull/src/libqhull_r/qh-io_r.htm similarity index 100% rename from xs/src/qhull/src/libqhull_r/qh-io_r.htm rename to src/qhull/src/libqhull_r/qh-io_r.htm diff --git a/xs/src/qhull/src/libqhull_r/qh-mem_r.htm b/src/qhull/src/libqhull_r/qh-mem_r.htm similarity index 100% rename from xs/src/qhull/src/libqhull_r/qh-mem_r.htm rename to src/qhull/src/libqhull_r/qh-mem_r.htm diff --git a/xs/src/qhull/src/libqhull_r/qh-merge_r.htm b/src/qhull/src/libqhull_r/qh-merge_r.htm similarity index 100% rename from xs/src/qhull/src/libqhull_r/qh-merge_r.htm rename to src/qhull/src/libqhull_r/qh-merge_r.htm diff --git a/xs/src/qhull/src/libqhull_r/qh-poly_r.htm b/src/qhull/src/libqhull_r/qh-poly_r.htm similarity index 100% rename from xs/src/qhull/src/libqhull_r/qh-poly_r.htm rename to src/qhull/src/libqhull_r/qh-poly_r.htm diff --git a/xs/src/qhull/src/libqhull_r/qh-qhull_r.htm b/src/qhull/src/libqhull_r/qh-qhull_r.htm similarity index 100% rename from xs/src/qhull/src/libqhull_r/qh-qhull_r.htm rename to src/qhull/src/libqhull_r/qh-qhull_r.htm diff --git a/xs/src/qhull/src/libqhull_r/qh-set_r.htm b/src/qhull/src/libqhull_r/qh-set_r.htm similarity index 100% rename from xs/src/qhull/src/libqhull_r/qh-set_r.htm rename to src/qhull/src/libqhull_r/qh-set_r.htm diff --git a/xs/src/qhull/src/libqhull_r/qh-stat_r.htm b/src/qhull/src/libqhull_r/qh-stat_r.htm similarity index 100% rename from xs/src/qhull/src/libqhull_r/qh-stat_r.htm rename to src/qhull/src/libqhull_r/qh-stat_r.htm diff --git a/xs/src/qhull/src/libqhull_r/qh-user_r.htm b/src/qhull/src/libqhull_r/qh-user_r.htm similarity index 100% rename from xs/src/qhull/src/libqhull_r/qh-user_r.htm rename to src/qhull/src/libqhull_r/qh-user_r.htm diff --git a/xs/src/qhull/src/libqhull_r/qhull_r-exports.def b/src/qhull/src/libqhull_r/qhull_r-exports.def similarity index 100% rename from xs/src/qhull/src/libqhull_r/qhull_r-exports.def rename to src/qhull/src/libqhull_r/qhull_r-exports.def diff --git a/xs/src/qhull/src/libqhull_r/qhull_ra.h b/src/qhull/src/libqhull_r/qhull_ra.h similarity index 100% rename from xs/src/qhull/src/libqhull_r/qhull_ra.h rename to src/qhull/src/libqhull_r/qhull_ra.h diff --git a/xs/src/qhull/src/libqhull_r/qset_r.c b/src/qhull/src/libqhull_r/qset_r.c similarity index 100% rename from xs/src/qhull/src/libqhull_r/qset_r.c rename to src/qhull/src/libqhull_r/qset_r.c diff --git a/xs/src/qhull/src/libqhull_r/qset_r.h b/src/qhull/src/libqhull_r/qset_r.h similarity index 100% rename from xs/src/qhull/src/libqhull_r/qset_r.h rename to src/qhull/src/libqhull_r/qset_r.h diff --git a/xs/src/qhull/src/libqhull_r/random_r.c b/src/qhull/src/libqhull_r/random_r.c similarity index 100% rename from xs/src/qhull/src/libqhull_r/random_r.c rename to src/qhull/src/libqhull_r/random_r.c diff --git a/xs/src/qhull/src/libqhull_r/random_r.h b/src/qhull/src/libqhull_r/random_r.h similarity index 100% rename from xs/src/qhull/src/libqhull_r/random_r.h rename to src/qhull/src/libqhull_r/random_r.h diff --git a/xs/src/qhull/src/libqhull_r/rboxlib_r.c b/src/qhull/src/libqhull_r/rboxlib_r.c similarity index 100% rename from xs/src/qhull/src/libqhull_r/rboxlib_r.c rename to src/qhull/src/libqhull_r/rboxlib_r.c diff --git a/xs/src/qhull/src/libqhull_r/stat_r.c b/src/qhull/src/libqhull_r/stat_r.c similarity index 100% rename from xs/src/qhull/src/libqhull_r/stat_r.c rename to src/qhull/src/libqhull_r/stat_r.c diff --git a/xs/src/qhull/src/libqhull_r/stat_r.h b/src/qhull/src/libqhull_r/stat_r.h similarity index 100% rename from xs/src/qhull/src/libqhull_r/stat_r.h rename to src/qhull/src/libqhull_r/stat_r.h diff --git a/xs/src/qhull/src/libqhull_r/user_r.c b/src/qhull/src/libqhull_r/user_r.c similarity index 100% rename from xs/src/qhull/src/libqhull_r/user_r.c rename to src/qhull/src/libqhull_r/user_r.c diff --git a/xs/src/qhull/src/libqhull_r/user_r.h b/src/qhull/src/libqhull_r/user_r.h similarity index 100% rename from xs/src/qhull/src/libqhull_r/user_r.h rename to src/qhull/src/libqhull_r/user_r.h diff --git a/xs/src/qhull/src/libqhull_r/usermem_r.c b/src/qhull/src/libqhull_r/usermem_r.c similarity index 100% rename from xs/src/qhull/src/libqhull_r/usermem_r.c rename to src/qhull/src/libqhull_r/usermem_r.c diff --git a/xs/src/qhull/src/libqhull_r/userprintf_r.c b/src/qhull/src/libqhull_r/userprintf_r.c similarity index 100% rename from xs/src/qhull/src/libqhull_r/userprintf_r.c rename to src/qhull/src/libqhull_r/userprintf_r.c diff --git a/xs/src/qhull/src/libqhull_r/userprintf_rbox_r.c b/src/qhull/src/libqhull_r/userprintf_rbox_r.c similarity index 100% rename from xs/src/qhull/src/libqhull_r/userprintf_rbox_r.c rename to src/qhull/src/libqhull_r/userprintf_rbox_r.c diff --git a/xs/src/qhull/src/libqhullcpp/Coordinates.cpp b/src/qhull/src/libqhullcpp/Coordinates.cpp similarity index 100% rename from xs/src/qhull/src/libqhullcpp/Coordinates.cpp rename to src/qhull/src/libqhullcpp/Coordinates.cpp diff --git a/xs/src/qhull/src/libqhullcpp/Coordinates.h b/src/qhull/src/libqhullcpp/Coordinates.h similarity index 100% rename from xs/src/qhull/src/libqhullcpp/Coordinates.h rename to src/qhull/src/libqhullcpp/Coordinates.h diff --git a/xs/src/qhull/src/libqhullcpp/PointCoordinates.cpp b/src/qhull/src/libqhullcpp/PointCoordinates.cpp similarity index 100% rename from xs/src/qhull/src/libqhullcpp/PointCoordinates.cpp rename to src/qhull/src/libqhullcpp/PointCoordinates.cpp diff --git a/xs/src/qhull/src/libqhullcpp/PointCoordinates.h b/src/qhull/src/libqhullcpp/PointCoordinates.h similarity index 100% rename from xs/src/qhull/src/libqhullcpp/PointCoordinates.h rename to src/qhull/src/libqhullcpp/PointCoordinates.h diff --git a/xs/src/qhull/src/libqhullcpp/Qhull.cpp b/src/qhull/src/libqhullcpp/Qhull.cpp similarity index 100% rename from xs/src/qhull/src/libqhullcpp/Qhull.cpp rename to src/qhull/src/libqhullcpp/Qhull.cpp diff --git a/xs/src/qhull/src/libqhullcpp/Qhull.h b/src/qhull/src/libqhullcpp/Qhull.h similarity index 100% rename from xs/src/qhull/src/libqhullcpp/Qhull.h rename to src/qhull/src/libqhullcpp/Qhull.h diff --git a/xs/src/qhull/src/libqhullcpp/QhullError.h b/src/qhull/src/libqhullcpp/QhullError.h similarity index 100% rename from xs/src/qhull/src/libqhullcpp/QhullError.h rename to src/qhull/src/libqhullcpp/QhullError.h diff --git a/xs/src/qhull/src/libqhullcpp/QhullFacet.cpp b/src/qhull/src/libqhullcpp/QhullFacet.cpp similarity index 100% rename from xs/src/qhull/src/libqhullcpp/QhullFacet.cpp rename to src/qhull/src/libqhullcpp/QhullFacet.cpp diff --git a/xs/src/qhull/src/libqhullcpp/QhullFacet.h b/src/qhull/src/libqhullcpp/QhullFacet.h similarity index 100% rename from xs/src/qhull/src/libqhullcpp/QhullFacet.h rename to src/qhull/src/libqhullcpp/QhullFacet.h diff --git a/xs/src/qhull/src/libqhullcpp/QhullFacetList.cpp b/src/qhull/src/libqhullcpp/QhullFacetList.cpp similarity index 100% rename from xs/src/qhull/src/libqhullcpp/QhullFacetList.cpp rename to src/qhull/src/libqhullcpp/QhullFacetList.cpp diff --git a/xs/src/qhull/src/libqhullcpp/QhullFacetList.h b/src/qhull/src/libqhullcpp/QhullFacetList.h similarity index 100% rename from xs/src/qhull/src/libqhullcpp/QhullFacetList.h rename to src/qhull/src/libqhullcpp/QhullFacetList.h diff --git a/xs/src/qhull/src/libqhullcpp/QhullFacetSet.cpp b/src/qhull/src/libqhullcpp/QhullFacetSet.cpp similarity index 100% rename from xs/src/qhull/src/libqhullcpp/QhullFacetSet.cpp rename to src/qhull/src/libqhullcpp/QhullFacetSet.cpp diff --git a/xs/src/qhull/src/libqhullcpp/QhullFacetSet.h b/src/qhull/src/libqhullcpp/QhullFacetSet.h similarity index 100% rename from xs/src/qhull/src/libqhullcpp/QhullFacetSet.h rename to src/qhull/src/libqhullcpp/QhullFacetSet.h diff --git a/xs/src/qhull/src/libqhullcpp/QhullHyperplane.cpp b/src/qhull/src/libqhullcpp/QhullHyperplane.cpp similarity index 100% rename from xs/src/qhull/src/libqhullcpp/QhullHyperplane.cpp rename to src/qhull/src/libqhullcpp/QhullHyperplane.cpp diff --git a/xs/src/qhull/src/libqhullcpp/QhullHyperplane.h b/src/qhull/src/libqhullcpp/QhullHyperplane.h similarity index 100% rename from xs/src/qhull/src/libqhullcpp/QhullHyperplane.h rename to src/qhull/src/libqhullcpp/QhullHyperplane.h diff --git a/xs/src/qhull/src/libqhullcpp/QhullIterator.h b/src/qhull/src/libqhullcpp/QhullIterator.h similarity index 100% rename from xs/src/qhull/src/libqhullcpp/QhullIterator.h rename to src/qhull/src/libqhullcpp/QhullIterator.h diff --git a/xs/src/qhull/src/libqhullcpp/QhullLinkedList.h b/src/qhull/src/libqhullcpp/QhullLinkedList.h similarity index 100% rename from xs/src/qhull/src/libqhullcpp/QhullLinkedList.h rename to src/qhull/src/libqhullcpp/QhullLinkedList.h diff --git a/xs/src/qhull/src/libqhullcpp/QhullPoint.cpp b/src/qhull/src/libqhullcpp/QhullPoint.cpp similarity index 100% rename from xs/src/qhull/src/libqhullcpp/QhullPoint.cpp rename to src/qhull/src/libqhullcpp/QhullPoint.cpp diff --git a/xs/src/qhull/src/libqhullcpp/QhullPoint.h b/src/qhull/src/libqhullcpp/QhullPoint.h similarity index 100% rename from xs/src/qhull/src/libqhullcpp/QhullPoint.h rename to src/qhull/src/libqhullcpp/QhullPoint.h diff --git a/xs/src/qhull/src/libqhullcpp/QhullPointSet.cpp b/src/qhull/src/libqhullcpp/QhullPointSet.cpp similarity index 100% rename from xs/src/qhull/src/libqhullcpp/QhullPointSet.cpp rename to src/qhull/src/libqhullcpp/QhullPointSet.cpp diff --git a/xs/src/qhull/src/libqhullcpp/QhullPointSet.h b/src/qhull/src/libqhullcpp/QhullPointSet.h similarity index 100% rename from xs/src/qhull/src/libqhullcpp/QhullPointSet.h rename to src/qhull/src/libqhullcpp/QhullPointSet.h diff --git a/xs/src/qhull/src/libqhullcpp/QhullPoints.cpp b/src/qhull/src/libqhullcpp/QhullPoints.cpp similarity index 100% rename from xs/src/qhull/src/libqhullcpp/QhullPoints.cpp rename to src/qhull/src/libqhullcpp/QhullPoints.cpp diff --git a/xs/src/qhull/src/libqhullcpp/QhullPoints.h b/src/qhull/src/libqhullcpp/QhullPoints.h similarity index 100% rename from xs/src/qhull/src/libqhullcpp/QhullPoints.h rename to src/qhull/src/libqhullcpp/QhullPoints.h diff --git a/xs/src/qhull/src/libqhullcpp/QhullQh.cpp b/src/qhull/src/libqhullcpp/QhullQh.cpp similarity index 100% rename from xs/src/qhull/src/libqhullcpp/QhullQh.cpp rename to src/qhull/src/libqhullcpp/QhullQh.cpp diff --git a/xs/src/qhull/src/libqhullcpp/QhullQh.h b/src/qhull/src/libqhullcpp/QhullQh.h similarity index 100% rename from xs/src/qhull/src/libqhullcpp/QhullQh.h rename to src/qhull/src/libqhullcpp/QhullQh.h diff --git a/xs/src/qhull/src/libqhullcpp/QhullRidge.cpp b/src/qhull/src/libqhullcpp/QhullRidge.cpp similarity index 100% rename from xs/src/qhull/src/libqhullcpp/QhullRidge.cpp rename to src/qhull/src/libqhullcpp/QhullRidge.cpp diff --git a/xs/src/qhull/src/libqhullcpp/QhullRidge.h b/src/qhull/src/libqhullcpp/QhullRidge.h similarity index 100% rename from xs/src/qhull/src/libqhullcpp/QhullRidge.h rename to src/qhull/src/libqhullcpp/QhullRidge.h diff --git a/xs/src/qhull/src/libqhullcpp/QhullSet.cpp b/src/qhull/src/libqhullcpp/QhullSet.cpp similarity index 100% rename from xs/src/qhull/src/libqhullcpp/QhullSet.cpp rename to src/qhull/src/libqhullcpp/QhullSet.cpp diff --git a/xs/src/qhull/src/libqhullcpp/QhullSet.h b/src/qhull/src/libqhullcpp/QhullSet.h similarity index 100% rename from xs/src/qhull/src/libqhullcpp/QhullSet.h rename to src/qhull/src/libqhullcpp/QhullSet.h diff --git a/xs/src/qhull/src/libqhullcpp/QhullSets.h b/src/qhull/src/libqhullcpp/QhullSets.h similarity index 100% rename from xs/src/qhull/src/libqhullcpp/QhullSets.h rename to src/qhull/src/libqhullcpp/QhullSets.h diff --git a/xs/src/qhull/src/libqhullcpp/QhullStat.cpp b/src/qhull/src/libqhullcpp/QhullStat.cpp similarity index 100% rename from xs/src/qhull/src/libqhullcpp/QhullStat.cpp rename to src/qhull/src/libqhullcpp/QhullStat.cpp diff --git a/xs/src/qhull/src/libqhullcpp/QhullStat.h b/src/qhull/src/libqhullcpp/QhullStat.h similarity index 100% rename from xs/src/qhull/src/libqhullcpp/QhullStat.h rename to src/qhull/src/libqhullcpp/QhullStat.h diff --git a/xs/src/qhull/src/libqhullcpp/QhullVertex.cpp b/src/qhull/src/libqhullcpp/QhullVertex.cpp similarity index 100% rename from xs/src/qhull/src/libqhullcpp/QhullVertex.cpp rename to src/qhull/src/libqhullcpp/QhullVertex.cpp diff --git a/xs/src/qhull/src/libqhullcpp/QhullVertex.h b/src/qhull/src/libqhullcpp/QhullVertex.h similarity index 100% rename from xs/src/qhull/src/libqhullcpp/QhullVertex.h rename to src/qhull/src/libqhullcpp/QhullVertex.h diff --git a/xs/src/qhull/src/libqhullcpp/QhullVertexSet.cpp b/src/qhull/src/libqhullcpp/QhullVertexSet.cpp similarity index 100% rename from xs/src/qhull/src/libqhullcpp/QhullVertexSet.cpp rename to src/qhull/src/libqhullcpp/QhullVertexSet.cpp diff --git a/xs/src/qhull/src/libqhullcpp/QhullVertexSet.h b/src/qhull/src/libqhullcpp/QhullVertexSet.h similarity index 100% rename from xs/src/qhull/src/libqhullcpp/QhullVertexSet.h rename to src/qhull/src/libqhullcpp/QhullVertexSet.h diff --git a/xs/src/qhull/src/libqhullcpp/RboxPoints.cpp b/src/qhull/src/libqhullcpp/RboxPoints.cpp similarity index 100% rename from xs/src/qhull/src/libqhullcpp/RboxPoints.cpp rename to src/qhull/src/libqhullcpp/RboxPoints.cpp diff --git a/xs/src/qhull/src/libqhullcpp/RboxPoints.h b/src/qhull/src/libqhullcpp/RboxPoints.h similarity index 100% rename from xs/src/qhull/src/libqhullcpp/RboxPoints.h rename to src/qhull/src/libqhullcpp/RboxPoints.h diff --git a/xs/src/qhull/src/libqhullcpp/RoadError.cpp b/src/qhull/src/libqhullcpp/RoadError.cpp similarity index 100% rename from xs/src/qhull/src/libqhullcpp/RoadError.cpp rename to src/qhull/src/libqhullcpp/RoadError.cpp diff --git a/xs/src/qhull/src/libqhullcpp/RoadError.h b/src/qhull/src/libqhullcpp/RoadError.h similarity index 100% rename from xs/src/qhull/src/libqhullcpp/RoadError.h rename to src/qhull/src/libqhullcpp/RoadError.h diff --git a/xs/src/qhull/src/libqhullcpp/RoadLogEvent.cpp b/src/qhull/src/libqhullcpp/RoadLogEvent.cpp similarity index 100% rename from xs/src/qhull/src/libqhullcpp/RoadLogEvent.cpp rename to src/qhull/src/libqhullcpp/RoadLogEvent.cpp diff --git a/xs/src/qhull/src/libqhullcpp/RoadLogEvent.h b/src/qhull/src/libqhullcpp/RoadLogEvent.h similarity index 100% rename from xs/src/qhull/src/libqhullcpp/RoadLogEvent.h rename to src/qhull/src/libqhullcpp/RoadLogEvent.h diff --git a/xs/src/qhull/src/libqhullcpp/functionObjects.h b/src/qhull/src/libqhullcpp/functionObjects.h similarity index 100% rename from xs/src/qhull/src/libqhullcpp/functionObjects.h rename to src/qhull/src/libqhullcpp/functionObjects.h diff --git a/xs/src/qhull/src/libqhullcpp/libqhullcpp.pro b/src/qhull/src/libqhullcpp/libqhullcpp.pro similarity index 100% rename from xs/src/qhull/src/libqhullcpp/libqhullcpp.pro rename to src/qhull/src/libqhullcpp/libqhullcpp.pro diff --git a/xs/src/qhull/src/libqhullcpp/qt-qhull.cpp b/src/qhull/src/libqhullcpp/qt-qhull.cpp similarity index 100% rename from xs/src/qhull/src/libqhullcpp/qt-qhull.cpp rename to src/qhull/src/libqhullcpp/qt-qhull.cpp diff --git a/xs/src/qhull/src/libqhullcpp/usermem_r-cpp.cpp b/src/qhull/src/libqhullcpp/usermem_r-cpp.cpp similarity index 100% rename from xs/src/qhull/src/libqhullcpp/usermem_r-cpp.cpp rename to src/qhull/src/libqhullcpp/usermem_r-cpp.cpp diff --git a/xs/src/qhull/src/libqhullstatic/libqhullstatic.pro b/src/qhull/src/libqhullstatic/libqhullstatic.pro similarity index 100% rename from xs/src/qhull/src/libqhullstatic/libqhullstatic.pro rename to src/qhull/src/libqhullstatic/libqhullstatic.pro diff --git a/xs/src/qhull/src/libqhullstatic_r/libqhullstatic_r.pro b/src/qhull/src/libqhullstatic_r/libqhullstatic_r.pro similarity index 100% rename from xs/src/qhull/src/libqhullstatic_r/libqhullstatic_r.pro rename to src/qhull/src/libqhullstatic_r/libqhullstatic_r.pro diff --git a/xs/src/qhull/src/qconvex/qconvex.c b/src/qhull/src/qconvex/qconvex.c similarity index 100% rename from xs/src/qhull/src/qconvex/qconvex.c rename to src/qhull/src/qconvex/qconvex.c diff --git a/xs/src/qhull/src/qconvex/qconvex.pro b/src/qhull/src/qconvex/qconvex.pro similarity index 100% rename from xs/src/qhull/src/qconvex/qconvex.pro rename to src/qhull/src/qconvex/qconvex.pro diff --git a/xs/src/qhull/src/qconvex/qconvex_r.c b/src/qhull/src/qconvex/qconvex_r.c similarity index 100% rename from xs/src/qhull/src/qconvex/qconvex_r.c rename to src/qhull/src/qconvex/qconvex_r.c diff --git a/xs/src/qhull/src/qdelaunay/qdelaun.c b/src/qhull/src/qdelaunay/qdelaun.c similarity index 100% rename from xs/src/qhull/src/qdelaunay/qdelaun.c rename to src/qhull/src/qdelaunay/qdelaun.c diff --git a/xs/src/qhull/src/qdelaunay/qdelaun_r.c b/src/qhull/src/qdelaunay/qdelaun_r.c similarity index 100% rename from xs/src/qhull/src/qdelaunay/qdelaun_r.c rename to src/qhull/src/qdelaunay/qdelaun_r.c diff --git a/xs/src/qhull/src/qdelaunay/qdelaunay.pro b/src/qhull/src/qdelaunay/qdelaunay.pro similarity index 100% rename from xs/src/qhull/src/qdelaunay/qdelaunay.pro rename to src/qhull/src/qdelaunay/qdelaunay.pro diff --git a/xs/src/qhull/src/qhalf/qhalf.c b/src/qhull/src/qhalf/qhalf.c similarity index 100% rename from xs/src/qhull/src/qhalf/qhalf.c rename to src/qhull/src/qhalf/qhalf.c diff --git a/xs/src/qhull/src/qhalf/qhalf.pro b/src/qhull/src/qhalf/qhalf.pro similarity index 100% rename from xs/src/qhull/src/qhalf/qhalf.pro rename to src/qhull/src/qhalf/qhalf.pro diff --git a/xs/src/qhull/src/qhalf/qhalf_r.c b/src/qhull/src/qhalf/qhalf_r.c similarity index 100% rename from xs/src/qhull/src/qhalf/qhalf_r.c rename to src/qhull/src/qhalf/qhalf_r.c diff --git a/xs/src/qhull/src/qhull-all.pro b/src/qhull/src/qhull-all.pro similarity index 100% rename from xs/src/qhull/src/qhull-all.pro rename to src/qhull/src/qhull-all.pro diff --git a/xs/src/qhull/src/qhull-app-c.pri b/src/qhull/src/qhull-app-c.pri similarity index 100% rename from xs/src/qhull/src/qhull-app-c.pri rename to src/qhull/src/qhull-app-c.pri diff --git a/xs/src/qhull/src/qhull-app-c_r.pri b/src/qhull/src/qhull-app-c_r.pri similarity index 100% rename from xs/src/qhull/src/qhull-app-c_r.pri rename to src/qhull/src/qhull-app-c_r.pri diff --git a/xs/src/qhull/src/qhull-app-cpp.pri b/src/qhull/src/qhull-app-cpp.pri similarity index 100% rename from xs/src/qhull/src/qhull-app-cpp.pri rename to src/qhull/src/qhull-app-cpp.pri diff --git a/xs/src/qhull/src/qhull-app-shared.pri b/src/qhull/src/qhull-app-shared.pri similarity index 100% rename from xs/src/qhull/src/qhull-app-shared.pri rename to src/qhull/src/qhull-app-shared.pri diff --git a/xs/src/qhull/src/qhull-app-shared_r.pri b/src/qhull/src/qhull-app-shared_r.pri similarity index 100% rename from xs/src/qhull/src/qhull-app-shared_r.pri rename to src/qhull/src/qhull-app-shared_r.pri diff --git a/xs/src/qhull/src/qhull-libqhull-src.pri b/src/qhull/src/qhull-libqhull-src.pri similarity index 100% rename from xs/src/qhull/src/qhull-libqhull-src.pri rename to src/qhull/src/qhull-libqhull-src.pri diff --git a/xs/src/qhull/src/qhull-libqhull-src_r.pri b/src/qhull/src/qhull-libqhull-src_r.pri similarity index 100% rename from xs/src/qhull/src/qhull-libqhull-src_r.pri rename to src/qhull/src/qhull-libqhull-src_r.pri diff --git a/xs/src/qhull/src/qhull-warn.pri b/src/qhull/src/qhull-warn.pri similarity index 100% rename from xs/src/qhull/src/qhull-warn.pri rename to src/qhull/src/qhull-warn.pri diff --git a/xs/src/qhull/src/qhull/qhull.pro b/src/qhull/src/qhull/qhull.pro similarity index 100% rename from xs/src/qhull/src/qhull/qhull.pro rename to src/qhull/src/qhull/qhull.pro diff --git a/xs/src/qhull/src/qhull/unix.c b/src/qhull/src/qhull/unix.c similarity index 100% rename from xs/src/qhull/src/qhull/unix.c rename to src/qhull/src/qhull/unix.c diff --git a/xs/src/qhull/src/qhull/unix_r.c b/src/qhull/src/qhull/unix_r.c similarity index 100% rename from xs/src/qhull/src/qhull/unix_r.c rename to src/qhull/src/qhull/unix_r.c diff --git a/xs/src/qhull/src/qhulltest/Coordinates_test.cpp b/src/qhull/src/qhulltest/Coordinates_test.cpp similarity index 100% rename from xs/src/qhull/src/qhulltest/Coordinates_test.cpp rename to src/qhull/src/qhulltest/Coordinates_test.cpp diff --git a/xs/src/qhull/src/qhulltest/PointCoordinates_test.cpp b/src/qhull/src/qhulltest/PointCoordinates_test.cpp similarity index 100% rename from xs/src/qhull/src/qhulltest/PointCoordinates_test.cpp rename to src/qhull/src/qhulltest/PointCoordinates_test.cpp diff --git a/xs/src/qhull/src/qhulltest/QhullFacetList_test.cpp b/src/qhull/src/qhulltest/QhullFacetList_test.cpp similarity index 100% rename from xs/src/qhull/src/qhulltest/QhullFacetList_test.cpp rename to src/qhull/src/qhulltest/QhullFacetList_test.cpp diff --git a/xs/src/qhull/src/qhulltest/QhullFacetSet_test.cpp b/src/qhull/src/qhulltest/QhullFacetSet_test.cpp similarity index 100% rename from xs/src/qhull/src/qhulltest/QhullFacetSet_test.cpp rename to src/qhull/src/qhulltest/QhullFacetSet_test.cpp diff --git a/xs/src/qhull/src/qhulltest/QhullFacet_test.cpp b/src/qhull/src/qhulltest/QhullFacet_test.cpp similarity index 100% rename from xs/src/qhull/src/qhulltest/QhullFacet_test.cpp rename to src/qhull/src/qhulltest/QhullFacet_test.cpp diff --git a/xs/src/qhull/src/qhulltest/QhullHyperplane_test.cpp b/src/qhull/src/qhulltest/QhullHyperplane_test.cpp similarity index 100% rename from xs/src/qhull/src/qhulltest/QhullHyperplane_test.cpp rename to src/qhull/src/qhulltest/QhullHyperplane_test.cpp diff --git a/xs/src/qhull/src/qhulltest/QhullLinkedList_test.cpp b/src/qhull/src/qhulltest/QhullLinkedList_test.cpp similarity index 100% rename from xs/src/qhull/src/qhulltest/QhullLinkedList_test.cpp rename to src/qhull/src/qhulltest/QhullLinkedList_test.cpp diff --git a/xs/src/qhull/src/qhulltest/QhullPointSet_test.cpp b/src/qhull/src/qhulltest/QhullPointSet_test.cpp similarity index 100% rename from xs/src/qhull/src/qhulltest/QhullPointSet_test.cpp rename to src/qhull/src/qhulltest/QhullPointSet_test.cpp diff --git a/xs/src/qhull/src/qhulltest/QhullPoint_test.cpp b/src/qhull/src/qhulltest/QhullPoint_test.cpp similarity index 100% rename from xs/src/qhull/src/qhulltest/QhullPoint_test.cpp rename to src/qhull/src/qhulltest/QhullPoint_test.cpp diff --git a/xs/src/qhull/src/qhulltest/QhullPoints_test.cpp b/src/qhull/src/qhulltest/QhullPoints_test.cpp similarity index 100% rename from xs/src/qhull/src/qhulltest/QhullPoints_test.cpp rename to src/qhull/src/qhulltest/QhullPoints_test.cpp diff --git a/xs/src/qhull/src/qhulltest/QhullRidge_test.cpp b/src/qhull/src/qhulltest/QhullRidge_test.cpp similarity index 100% rename from xs/src/qhull/src/qhulltest/QhullRidge_test.cpp rename to src/qhull/src/qhulltest/QhullRidge_test.cpp diff --git a/xs/src/qhull/src/qhulltest/QhullSet_test.cpp b/src/qhull/src/qhulltest/QhullSet_test.cpp similarity index 100% rename from xs/src/qhull/src/qhulltest/QhullSet_test.cpp rename to src/qhull/src/qhulltest/QhullSet_test.cpp diff --git a/xs/src/qhull/src/qhulltest/QhullVertexSet_test.cpp b/src/qhull/src/qhulltest/QhullVertexSet_test.cpp similarity index 100% rename from xs/src/qhull/src/qhulltest/QhullVertexSet_test.cpp rename to src/qhull/src/qhulltest/QhullVertexSet_test.cpp diff --git a/xs/src/qhull/src/qhulltest/QhullVertex_test.cpp b/src/qhull/src/qhulltest/QhullVertex_test.cpp similarity index 100% rename from xs/src/qhull/src/qhulltest/QhullVertex_test.cpp rename to src/qhull/src/qhulltest/QhullVertex_test.cpp diff --git a/xs/src/qhull/src/qhulltest/Qhull_test.cpp b/src/qhull/src/qhulltest/Qhull_test.cpp similarity index 100% rename from xs/src/qhull/src/qhulltest/Qhull_test.cpp rename to src/qhull/src/qhulltest/Qhull_test.cpp diff --git a/xs/src/qhull/src/qhulltest/RboxPoints_test.cpp b/src/qhull/src/qhulltest/RboxPoints_test.cpp similarity index 100% rename from xs/src/qhull/src/qhulltest/RboxPoints_test.cpp rename to src/qhull/src/qhulltest/RboxPoints_test.cpp diff --git a/xs/src/qhull/src/qhulltest/RoadTest.cpp b/src/qhull/src/qhulltest/RoadTest.cpp similarity index 100% rename from xs/src/qhull/src/qhulltest/RoadTest.cpp rename to src/qhull/src/qhulltest/RoadTest.cpp diff --git a/xs/src/qhull/src/qhulltest/RoadTest.h b/src/qhull/src/qhulltest/RoadTest.h similarity index 100% rename from xs/src/qhull/src/qhulltest/RoadTest.h rename to src/qhull/src/qhulltest/RoadTest.h diff --git a/xs/src/qhull/src/qhulltest/qhulltest.cpp b/src/qhull/src/qhulltest/qhulltest.cpp similarity index 100% rename from xs/src/qhull/src/qhulltest/qhulltest.cpp rename to src/qhull/src/qhulltest/qhulltest.cpp diff --git a/xs/src/qhull/src/qhulltest/qhulltest.pro b/src/qhull/src/qhulltest/qhulltest.pro similarity index 100% rename from xs/src/qhull/src/qhulltest/qhulltest.pro rename to src/qhull/src/qhulltest/qhulltest.pro diff --git a/xs/src/qhull/src/qvoronoi/qvoronoi.c b/src/qhull/src/qvoronoi/qvoronoi.c similarity index 100% rename from xs/src/qhull/src/qvoronoi/qvoronoi.c rename to src/qhull/src/qvoronoi/qvoronoi.c diff --git a/xs/src/qhull/src/qvoronoi/qvoronoi.pro b/src/qhull/src/qvoronoi/qvoronoi.pro similarity index 100% rename from xs/src/qhull/src/qvoronoi/qvoronoi.pro rename to src/qhull/src/qvoronoi/qvoronoi.pro diff --git a/xs/src/qhull/src/qvoronoi/qvoronoi_r.c b/src/qhull/src/qvoronoi/qvoronoi_r.c similarity index 100% rename from xs/src/qhull/src/qvoronoi/qvoronoi_r.c rename to src/qhull/src/qvoronoi/qvoronoi_r.c diff --git a/xs/src/qhull/src/rbox/rbox.c b/src/qhull/src/rbox/rbox.c similarity index 100% rename from xs/src/qhull/src/rbox/rbox.c rename to src/qhull/src/rbox/rbox.c diff --git a/xs/src/qhull/src/rbox/rbox.pro b/src/qhull/src/rbox/rbox.pro similarity index 100% rename from xs/src/qhull/src/rbox/rbox.pro rename to src/qhull/src/rbox/rbox.pro diff --git a/xs/src/qhull/src/rbox/rbox_r.c b/src/qhull/src/rbox/rbox_r.c similarity index 100% rename from xs/src/qhull/src/rbox/rbox_r.c rename to src/qhull/src/rbox/rbox_r.c diff --git a/xs/src/qhull/src/testqset/testqset.c b/src/qhull/src/testqset/testqset.c similarity index 100% rename from xs/src/qhull/src/testqset/testqset.c rename to src/qhull/src/testqset/testqset.c diff --git a/xs/src/qhull/src/testqset/testqset.pro b/src/qhull/src/testqset/testqset.pro similarity index 100% rename from xs/src/qhull/src/testqset/testqset.pro rename to src/qhull/src/testqset/testqset.pro diff --git a/xs/src/qhull/src/testqset_r/testqset_r.c b/src/qhull/src/testqset_r/testqset_r.c similarity index 100% rename from xs/src/qhull/src/testqset_r/testqset_r.c rename to src/qhull/src/testqset_r/testqset_r.c diff --git a/xs/src/qhull/src/testqset_r/testqset_r.pro b/src/qhull/src/testqset_r/testqset_r.pro similarity index 100% rename from xs/src/qhull/src/testqset_r/testqset_r.pro rename to src/qhull/src/testqset_r/testqset_r.pro diff --git a/xs/src/qhull/src/user_eg/user_eg.c b/src/qhull/src/user_eg/user_eg.c similarity index 100% rename from xs/src/qhull/src/user_eg/user_eg.c rename to src/qhull/src/user_eg/user_eg.c diff --git a/xs/src/qhull/src/user_eg/user_eg.pro b/src/qhull/src/user_eg/user_eg.pro similarity index 100% rename from xs/src/qhull/src/user_eg/user_eg.pro rename to src/qhull/src/user_eg/user_eg.pro diff --git a/xs/src/qhull/src/user_eg/user_eg_r.c b/src/qhull/src/user_eg/user_eg_r.c similarity index 100% rename from xs/src/qhull/src/user_eg/user_eg_r.c rename to src/qhull/src/user_eg/user_eg_r.c diff --git a/xs/src/qhull/src/user_eg2/user_eg2.c b/src/qhull/src/user_eg2/user_eg2.c similarity index 100% rename from xs/src/qhull/src/user_eg2/user_eg2.c rename to src/qhull/src/user_eg2/user_eg2.c diff --git a/xs/src/qhull/src/user_eg2/user_eg2.pro b/src/qhull/src/user_eg2/user_eg2.pro similarity index 100% rename from xs/src/qhull/src/user_eg2/user_eg2.pro rename to src/qhull/src/user_eg2/user_eg2.pro diff --git a/xs/src/qhull/src/user_eg2/user_eg2_r.c b/src/qhull/src/user_eg2/user_eg2_r.c similarity index 100% rename from xs/src/qhull/src/user_eg2/user_eg2_r.c rename to src/qhull/src/user_eg2/user_eg2_r.c diff --git a/xs/src/qhull/src/user_eg3/user_eg3.pro b/src/qhull/src/user_eg3/user_eg3.pro similarity index 100% rename from xs/src/qhull/src/user_eg3/user_eg3.pro rename to src/qhull/src/user_eg3/user_eg3.pro diff --git a/xs/src/qhull/src/user_eg3/user_eg3_r.cpp b/src/qhull/src/user_eg3/user_eg3_r.cpp similarity index 100% rename from xs/src/qhull/src/user_eg3/user_eg3_r.cpp rename to src/qhull/src/user_eg3/user_eg3_r.cpp diff --git a/src/semver/CMakeLists.txt b/src/semver/CMakeLists.txt new file mode 100644 index 0000000000..e3457bf291 --- /dev/null +++ b/src/semver/CMakeLists.txt @@ -0,0 +1,7 @@ +project(semver) +cmake_minimum_required(VERSION 2.6) + +add_library(semver STATIC + semver.c + semver.h +) diff --git a/xs/src/semver/semver.c b/src/semver/semver.c similarity index 100% rename from xs/src/semver/semver.c rename to src/semver/semver.c diff --git a/xs/src/semver/semver.h b/src/semver/semver.h similarity index 100% rename from xs/src/semver/semver.h rename to src/semver/semver.h diff --git a/src/slic3r.cpp b/src/slic3r.cpp index 085b396862..8174ba0a2b 100644 --- a/src/slic3r.cpp +++ b/src/slic3r.cpp @@ -12,8 +12,83 @@ #include #include +#include "slic3r/GUI/GUI.hpp" + using namespace Slic3r; +// wxWidgets "Hello world" Program +// For compilers that support precompilation, includes "wx/wx.h". +#include +#ifndef WX_PRECOMP + #include +#endif +class MyApp: public wxApp +{ +public: + virtual bool OnInit(); +}; +class MyFrame: public wxFrame +{ +public: + MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size); +private: + void OnHello(wxCommandEvent& event); + void OnExit(wxCommandEvent& event); + void OnAbout(wxCommandEvent& event); + wxDECLARE_EVENT_TABLE(); +}; +enum +{ + ID_Hello = 1 +}; +wxBEGIN_EVENT_TABLE(MyFrame, wxFrame) + EVT_MENU(ID_Hello, MyFrame::OnHello) + EVT_MENU(wxID_EXIT, MyFrame::OnExit) + EVT_MENU(wxID_ABOUT, MyFrame::OnAbout) +wxEND_EVENT_TABLE() +bool MyApp::OnInit() +{ + MyFrame *frame = new MyFrame( "Hello World", wxPoint(50, 50), wxSize(450, 340) ); + frame->Show( true ); + return true; +} +MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size) + : wxFrame(NULL, wxID_ANY, title, pos, size) +{ + wxMenu *menuFile = new wxMenu; + menuFile->Append(ID_Hello, "&Hello...\tCtrl-H", + "Help string shown in status bar for this menu item"); + menuFile->AppendSeparator(); + menuFile->Append(wxID_EXIT); + wxMenu *menuHelp = new wxMenu; + menuHelp->Append(wxID_ABOUT); + wxMenuBar *menuBar = new wxMenuBar; + menuBar->Append( menuFile, "&File" ); + menuBar->Append( menuHelp, "&Help" ); + SetMenuBar( menuBar ); + CreateStatusBar(); + SetStatusText( "Welcome to wxWidgets!" ); + Slic3r::Model model; + ModelObject *object = model.add_object(); + SetStatusText(Slic3r::GUI::from_u8("HHuhuh")); +} + +void MyFrame::OnExit(wxCommandEvent& event) +{ + Close( true ); +} +void MyFrame::OnAbout(wxCommandEvent& event) +{ + wxMessageBox( "This is a wxWidgets' Hello world sample", + "About Hello World", wxOK | wxICON_INFORMATION ); +} +void MyFrame::OnHello(wxCommandEvent& event) +{ + wxLogMessage("Hello world from wxWidgets!"); +} + + +#if 1 int main(int argc, char **argv) { @@ -176,5 +251,11 @@ main(int argc, char **argv) } #endif + + MyApp *gui = new MyApp(); + + MyApp::SetInstance(gui); + wxEntry(argc, argv); return 0; } +#endif diff --git a/xs/src/slic3r/AppController.cpp b/src/slic3r/AppController.cpp similarity index 100% rename from xs/src/slic3r/AppController.cpp rename to src/slic3r/AppController.cpp diff --git a/xs/src/slic3r/AppController.hpp b/src/slic3r/AppController.hpp similarity index 100% rename from xs/src/slic3r/AppController.hpp rename to src/slic3r/AppController.hpp diff --git a/xs/src/slic3r/AppControllerWx.cpp b/src/slic3r/AppControllerWx.cpp similarity index 100% rename from xs/src/slic3r/AppControllerWx.cpp rename to src/slic3r/AppControllerWx.cpp diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt new file mode 100644 index 0000000000..e4dfd35ea5 --- /dev/null +++ b/src/slic3r/CMakeLists.txt @@ -0,0 +1,106 @@ +add_library(libslic3r_gui STATIC + ${LIBDIR}/slic3r/GUI/AboutDialog.cpp + ${LIBDIR}/slic3r/GUI/AboutDialog.hpp + ${LIBDIR}/slic3r/GUI/AppConfig.cpp + ${LIBDIR}/slic3r/GUI/AppConfig.hpp + ${LIBDIR}/slic3r/GUI/BackgroundSlicingProcess.cpp + ${LIBDIR}/slic3r/GUI/BackgroundSlicingProcess.hpp + ${LIBDIR}/slic3r/GUI/BitmapCache.cpp + ${LIBDIR}/slic3r/GUI/BitmapCache.hpp + ${LIBDIR}/slic3r/GUI/ConfigSnapshotDialog.cpp + ${LIBDIR}/slic3r/GUI/ConfigSnapshotDialog.hpp + ${LIBDIR}/slic3r/GUI/3DScene.cpp + ${LIBDIR}/slic3r/GUI/3DScene.hpp + ${LIBDIR}/slic3r/GUI/GLShader.cpp + ${LIBDIR}/slic3r/GUI/GLShader.hpp + ${LIBDIR}/slic3r/GUI/GLCanvas3D.hpp + ${LIBDIR}/slic3r/GUI/GLCanvas3D.cpp + ${LIBDIR}/slic3r/GUI/GLCanvas3DManager.hpp + ${LIBDIR}/slic3r/GUI/GLCanvas3DManager.cpp + ${LIBDIR}/slic3r/GUI/GLGizmo.hpp + ${LIBDIR}/slic3r/GUI/GLGizmo.cpp + ${LIBDIR}/slic3r/GUI/GLTexture.hpp + ${LIBDIR}/slic3r/GUI/GLTexture.cpp + ${LIBDIR}/slic3r/GUI/GLToolbar.hpp + ${LIBDIR}/slic3r/GUI/GLToolbar.cpp + ${LIBDIR}/slic3r/GUI/Preferences.cpp + ${LIBDIR}/slic3r/GUI/Preferences.hpp + ${LIBDIR}/slic3r/GUI/Preset.cpp + ${LIBDIR}/slic3r/GUI/Preset.hpp + ${LIBDIR}/slic3r/GUI/PresetBundle.cpp + ${LIBDIR}/slic3r/GUI/PresetBundle.hpp + ${LIBDIR}/slic3r/GUI/PresetHints.cpp + ${LIBDIR}/slic3r/GUI/PresetHints.hpp + ${LIBDIR}/slic3r/GUI/GUI.cpp + ${LIBDIR}/slic3r/GUI/GUI.hpp + ${LIBDIR}/slic3r/GUI/GUI_ObjectParts.cpp + ${LIBDIR}/slic3r/GUI/GUI_ObjectParts.hpp + ${LIBDIR}/slic3r/GUI/LambdaObjectDialog.cpp + ${LIBDIR}/slic3r/GUI/LambdaObjectDialog.hpp + ${LIBDIR}/slic3r/GUI/Tab.cpp + ${LIBDIR}/slic3r/GUI/Tab.hpp + ${LIBDIR}/slic3r/GUI/TabIface.cpp + ${LIBDIR}/slic3r/GUI/TabIface.hpp + ${LIBDIR}/slic3r/GUI/Field.cpp + ${LIBDIR}/slic3r/GUI/Field.hpp + ${LIBDIR}/slic3r/GUI/OptionsGroup.cpp + ${LIBDIR}/slic3r/GUI/OptionsGroup.hpp + ${LIBDIR}/slic3r/GUI/BedShapeDialog.cpp + ${LIBDIR}/slic3r/GUI/BedShapeDialog.hpp + ${LIBDIR}/slic3r/GUI/2DBed.cpp + ${LIBDIR}/slic3r/GUI/2DBed.hpp + ${LIBDIR}/slic3r/GUI/wxExtensions.cpp + ${LIBDIR}/slic3r/GUI/wxExtensions.hpp + ${LIBDIR}/slic3r/GUI/WipeTowerDialog.cpp + ${LIBDIR}/slic3r/GUI/WipeTowerDialog.hpp + ${LIBDIR}/slic3r/GUI/RammingChart.cpp + ${LIBDIR}/slic3r/GUI/RammingChart.hpp + ${LIBDIR}/slic3r/GUI/BonjourDialog.cpp + ${LIBDIR}/slic3r/GUI/BonjourDialog.hpp + ${LIBDIR}/slic3r/GUI/ButtonsDescription.cpp + ${LIBDIR}/slic3r/GUI/ButtonsDescription.hpp + ${LIBDIR}/slic3r/Config/Snapshot.cpp + ${LIBDIR}/slic3r/Config/Snapshot.hpp + ${LIBDIR}/slic3r/Config/Version.cpp + ${LIBDIR}/slic3r/Config/Version.hpp + ${LIBDIR}/slic3r/Utils/ASCIIFolding.cpp + ${LIBDIR}/slic3r/Utils/ASCIIFolding.hpp + ${LIBDIR}/slic3r/Utils/Serial.cpp + ${LIBDIR}/slic3r/Utils/Serial.hpp + ${LIBDIR}/slic3r/GUI/ConfigWizard.cpp + ${LIBDIR}/slic3r/GUI/ConfigWizard.hpp + ${LIBDIR}/slic3r/GUI/MsgDialog.cpp + ${LIBDIR}/slic3r/GUI/MsgDialog.hpp + ${LIBDIR}/slic3r/GUI/UpdateDialogs.cpp + ${LIBDIR}/slic3r/GUI/UpdateDialogs.hpp + ${LIBDIR}/slic3r/GUI/FirmwareDialog.cpp + ${LIBDIR}/slic3r/GUI/FirmwareDialog.hpp + ${LIBDIR}/slic3r/GUI/ProgressIndicator.hpp + ${LIBDIR}/slic3r/GUI/ProgressStatusBar.hpp + ${LIBDIR}/slic3r/GUI/ProgressStatusBar.cpp + ${LIBDIR}/slic3r/Utils/Http.cpp + ${LIBDIR}/slic3r/Utils/Http.hpp + ${LIBDIR}/slic3r/Utils/FixModelByWin10.cpp + ${LIBDIR}/slic3r/Utils/FixModelByWin10.hpp + ${LIBDIR}/slic3r/Utils/PrintHostSendDialog.cpp + ${LIBDIR}/slic3r/Utils/PrintHostSendDialog.hpp + ${LIBDIR}/slic3r/Utils/OctoPrint.cpp + ${LIBDIR}/slic3r/Utils/OctoPrint.hpp + ${LIBDIR}/slic3r/Utils/Duet.cpp + ${LIBDIR}/slic3r/Utils/Duet.hpp + ${LIBDIR}/slic3r/Utils/PrintHost.cpp + ${LIBDIR}/slic3r/Utils/PrintHost.hpp + ${LIBDIR}/slic3r/Utils/Bonjour.cpp + ${LIBDIR}/slic3r/Utils/Bonjour.hpp + ${LIBDIR}/slic3r/Utils/PresetUpdater.cpp + ${LIBDIR}/slic3r/Utils/PresetUpdater.hpp + ${LIBDIR}/slic3r/Utils/Time.cpp + ${LIBDIR}/slic3r/Utils/Time.hpp + ${LIBDIR}/slic3r/Utils/HexFile.cpp + ${LIBDIR}/slic3r/Utils/HexFile.hpp + ${LIBDIR}/slic3r/AppController.hpp + ${LIBDIR}/slic3r/AppController.cpp + ${LIBDIR}/slic3r/AppControllerWx.cpp +) + +target_link_libraries(libslic3r_gui libslic3r avrdude) diff --git a/xs/src/slic3r/Config/Snapshot.cpp b/src/slic3r/Config/Snapshot.cpp similarity index 100% rename from xs/src/slic3r/Config/Snapshot.cpp rename to src/slic3r/Config/Snapshot.cpp diff --git a/xs/src/slic3r/Config/Snapshot.hpp b/src/slic3r/Config/Snapshot.hpp similarity index 100% rename from xs/src/slic3r/Config/Snapshot.hpp rename to src/slic3r/Config/Snapshot.hpp diff --git a/xs/src/slic3r/Config/Version.cpp b/src/slic3r/Config/Version.cpp similarity index 100% rename from xs/src/slic3r/Config/Version.cpp rename to src/slic3r/Config/Version.cpp diff --git a/xs/src/slic3r/Config/Version.hpp b/src/slic3r/Config/Version.hpp similarity index 100% rename from xs/src/slic3r/Config/Version.hpp rename to src/slic3r/Config/Version.hpp diff --git a/xs/src/slic3r/GUI/2DBed.cpp b/src/slic3r/GUI/2DBed.cpp similarity index 100% rename from xs/src/slic3r/GUI/2DBed.cpp rename to src/slic3r/GUI/2DBed.cpp diff --git a/xs/src/slic3r/GUI/2DBed.hpp b/src/slic3r/GUI/2DBed.hpp similarity index 100% rename from xs/src/slic3r/GUI/2DBed.hpp rename to src/slic3r/GUI/2DBed.hpp diff --git a/xs/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp similarity index 100% rename from xs/src/slic3r/GUI/3DScene.cpp rename to src/slic3r/GUI/3DScene.cpp diff --git a/xs/src/slic3r/GUI/3DScene.hpp b/src/slic3r/GUI/3DScene.hpp similarity index 100% rename from xs/src/slic3r/GUI/3DScene.hpp rename to src/slic3r/GUI/3DScene.hpp diff --git a/xs/src/slic3r/GUI/AboutDialog.cpp b/src/slic3r/GUI/AboutDialog.cpp similarity index 100% rename from xs/src/slic3r/GUI/AboutDialog.cpp rename to src/slic3r/GUI/AboutDialog.cpp diff --git a/xs/src/slic3r/GUI/AboutDialog.hpp b/src/slic3r/GUI/AboutDialog.hpp similarity index 100% rename from xs/src/slic3r/GUI/AboutDialog.hpp rename to src/slic3r/GUI/AboutDialog.hpp diff --git a/xs/src/slic3r/GUI/AppConfig.cpp b/src/slic3r/GUI/AppConfig.cpp similarity index 100% rename from xs/src/slic3r/GUI/AppConfig.cpp rename to src/slic3r/GUI/AppConfig.cpp diff --git a/xs/src/slic3r/GUI/AppConfig.hpp b/src/slic3r/GUI/AppConfig.hpp similarity index 100% rename from xs/src/slic3r/GUI/AppConfig.hpp rename to src/slic3r/GUI/AppConfig.hpp diff --git a/xs/src/slic3r/GUI/BackgroundSlicingProcess.cpp b/src/slic3r/GUI/BackgroundSlicingProcess.cpp similarity index 100% rename from xs/src/slic3r/GUI/BackgroundSlicingProcess.cpp rename to src/slic3r/GUI/BackgroundSlicingProcess.cpp diff --git a/xs/src/slic3r/GUI/BackgroundSlicingProcess.hpp b/src/slic3r/GUI/BackgroundSlicingProcess.hpp similarity index 100% rename from xs/src/slic3r/GUI/BackgroundSlicingProcess.hpp rename to src/slic3r/GUI/BackgroundSlicingProcess.hpp diff --git a/xs/src/slic3r/GUI/BedShapeDialog.cpp b/src/slic3r/GUI/BedShapeDialog.cpp similarity index 100% rename from xs/src/slic3r/GUI/BedShapeDialog.cpp rename to src/slic3r/GUI/BedShapeDialog.cpp diff --git a/xs/src/slic3r/GUI/BedShapeDialog.hpp b/src/slic3r/GUI/BedShapeDialog.hpp similarity index 100% rename from xs/src/slic3r/GUI/BedShapeDialog.hpp rename to src/slic3r/GUI/BedShapeDialog.hpp diff --git a/xs/src/slic3r/GUI/BitmapCache.cpp b/src/slic3r/GUI/BitmapCache.cpp similarity index 100% rename from xs/src/slic3r/GUI/BitmapCache.cpp rename to src/slic3r/GUI/BitmapCache.cpp diff --git a/xs/src/slic3r/GUI/BitmapCache.hpp b/src/slic3r/GUI/BitmapCache.hpp similarity index 100% rename from xs/src/slic3r/GUI/BitmapCache.hpp rename to src/slic3r/GUI/BitmapCache.hpp diff --git a/xs/src/slic3r/GUI/BonjourDialog.cpp b/src/slic3r/GUI/BonjourDialog.cpp similarity index 100% rename from xs/src/slic3r/GUI/BonjourDialog.cpp rename to src/slic3r/GUI/BonjourDialog.cpp diff --git a/xs/src/slic3r/GUI/BonjourDialog.hpp b/src/slic3r/GUI/BonjourDialog.hpp similarity index 100% rename from xs/src/slic3r/GUI/BonjourDialog.hpp rename to src/slic3r/GUI/BonjourDialog.hpp diff --git a/xs/src/slic3r/GUI/ButtonsDescription.cpp b/src/slic3r/GUI/ButtonsDescription.cpp similarity index 100% rename from xs/src/slic3r/GUI/ButtonsDescription.cpp rename to src/slic3r/GUI/ButtonsDescription.cpp diff --git a/xs/src/slic3r/GUI/ButtonsDescription.hpp b/src/slic3r/GUI/ButtonsDescription.hpp similarity index 100% rename from xs/src/slic3r/GUI/ButtonsDescription.hpp rename to src/slic3r/GUI/ButtonsDescription.hpp diff --git a/xs/src/slic3r/GUI/ConfigExceptions.hpp b/src/slic3r/GUI/ConfigExceptions.hpp similarity index 100% rename from xs/src/slic3r/GUI/ConfigExceptions.hpp rename to src/slic3r/GUI/ConfigExceptions.hpp diff --git a/xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp b/src/slic3r/GUI/ConfigSnapshotDialog.cpp similarity index 100% rename from xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp rename to src/slic3r/GUI/ConfigSnapshotDialog.cpp diff --git a/xs/src/slic3r/GUI/ConfigSnapshotDialog.hpp b/src/slic3r/GUI/ConfigSnapshotDialog.hpp similarity index 100% rename from xs/src/slic3r/GUI/ConfigSnapshotDialog.hpp rename to src/slic3r/GUI/ConfigSnapshotDialog.hpp diff --git a/xs/src/slic3r/GUI/ConfigWizard.cpp b/src/slic3r/GUI/ConfigWizard.cpp similarity index 100% rename from xs/src/slic3r/GUI/ConfigWizard.cpp rename to src/slic3r/GUI/ConfigWizard.cpp diff --git a/xs/src/slic3r/GUI/ConfigWizard.hpp b/src/slic3r/GUI/ConfigWizard.hpp similarity index 100% rename from xs/src/slic3r/GUI/ConfigWizard.hpp rename to src/slic3r/GUI/ConfigWizard.hpp diff --git a/xs/src/slic3r/GUI/ConfigWizard_private.hpp b/src/slic3r/GUI/ConfigWizard_private.hpp similarity index 100% rename from xs/src/slic3r/GUI/ConfigWizard_private.hpp rename to src/slic3r/GUI/ConfigWizard_private.hpp diff --git a/xs/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp similarity index 100% rename from xs/src/slic3r/GUI/Field.cpp rename to src/slic3r/GUI/Field.cpp diff --git a/xs/src/slic3r/GUI/Field.hpp b/src/slic3r/GUI/Field.hpp similarity index 100% rename from xs/src/slic3r/GUI/Field.hpp rename to src/slic3r/GUI/Field.hpp diff --git a/xs/src/slic3r/GUI/FirmwareDialog.cpp b/src/slic3r/GUI/FirmwareDialog.cpp similarity index 100% rename from xs/src/slic3r/GUI/FirmwareDialog.cpp rename to src/slic3r/GUI/FirmwareDialog.cpp diff --git a/xs/src/slic3r/GUI/FirmwareDialog.hpp b/src/slic3r/GUI/FirmwareDialog.hpp similarity index 100% rename from xs/src/slic3r/GUI/FirmwareDialog.hpp rename to src/slic3r/GUI/FirmwareDialog.hpp diff --git a/xs/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp similarity index 100% rename from xs/src/slic3r/GUI/GLCanvas3D.cpp rename to src/slic3r/GUI/GLCanvas3D.cpp diff --git a/xs/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp similarity index 100% rename from xs/src/slic3r/GUI/GLCanvas3D.hpp rename to src/slic3r/GUI/GLCanvas3D.hpp diff --git a/xs/src/slic3r/GUI/GLCanvas3DManager.cpp b/src/slic3r/GUI/GLCanvas3DManager.cpp similarity index 100% rename from xs/src/slic3r/GUI/GLCanvas3DManager.cpp rename to src/slic3r/GUI/GLCanvas3DManager.cpp diff --git a/xs/src/slic3r/GUI/GLCanvas3DManager.hpp b/src/slic3r/GUI/GLCanvas3DManager.hpp similarity index 100% rename from xs/src/slic3r/GUI/GLCanvas3DManager.hpp rename to src/slic3r/GUI/GLCanvas3DManager.hpp diff --git a/xs/src/slic3r/GUI/GLGizmo.cpp b/src/slic3r/GUI/GLGizmo.cpp similarity index 100% rename from xs/src/slic3r/GUI/GLGizmo.cpp rename to src/slic3r/GUI/GLGizmo.cpp diff --git a/xs/src/slic3r/GUI/GLGizmo.hpp b/src/slic3r/GUI/GLGizmo.hpp similarity index 100% rename from xs/src/slic3r/GUI/GLGizmo.hpp rename to src/slic3r/GUI/GLGizmo.hpp diff --git a/xs/src/slic3r/GUI/GLShader.cpp b/src/slic3r/GUI/GLShader.cpp similarity index 100% rename from xs/src/slic3r/GUI/GLShader.cpp rename to src/slic3r/GUI/GLShader.cpp diff --git a/xs/src/slic3r/GUI/GLShader.hpp b/src/slic3r/GUI/GLShader.hpp similarity index 100% rename from xs/src/slic3r/GUI/GLShader.hpp rename to src/slic3r/GUI/GLShader.hpp diff --git a/xs/src/slic3r/GUI/GLTexture.cpp b/src/slic3r/GUI/GLTexture.cpp similarity index 100% rename from xs/src/slic3r/GUI/GLTexture.cpp rename to src/slic3r/GUI/GLTexture.cpp diff --git a/xs/src/slic3r/GUI/GLTexture.hpp b/src/slic3r/GUI/GLTexture.hpp similarity index 100% rename from xs/src/slic3r/GUI/GLTexture.hpp rename to src/slic3r/GUI/GLTexture.hpp diff --git a/xs/src/slic3r/GUI/GLToolbar.cpp b/src/slic3r/GUI/GLToolbar.cpp similarity index 100% rename from xs/src/slic3r/GUI/GLToolbar.cpp rename to src/slic3r/GUI/GLToolbar.cpp diff --git a/xs/src/slic3r/GUI/GLToolbar.hpp b/src/slic3r/GUI/GLToolbar.hpp similarity index 100% rename from xs/src/slic3r/GUI/GLToolbar.hpp rename to src/slic3r/GUI/GLToolbar.hpp diff --git a/xs/src/slic3r/GUI/GUI.cpp b/src/slic3r/GUI/GUI.cpp similarity index 99% rename from xs/src/slic3r/GUI/GUI.cpp rename to src/slic3r/GUI/GUI.cpp index decdb5691d..24d459921d 100644 --- a/xs/src/slic3r/GUI/GUI.cpp +++ b/src/slic3r/GUI/GUI.cpp @@ -46,6 +46,8 @@ #include "Tab.hpp" #include "TabIface.hpp" +#include "GUI_Preview.hpp" +#include "GUI_PreviewIface.hpp" #include "AboutDialog.hpp" #include "AppConfig.hpp" #include "ConfigSnapshotDialog.hpp" @@ -148,6 +150,8 @@ wxStaticBitmap *g_manifold_warning_icon = nullptr; bool g_show_print_info = false; bool g_show_manifold_warning_icon = false; +PreviewIface* g_preview = nullptr; + static void init_label_colours() { auto luma = get_colour_approx_luma(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); @@ -665,6 +669,17 @@ TabIface* get_preset_tab_iface(char *name) return new TabIface(nullptr); } +PreviewIface* create_preview_iface(wxNotebook* parent, DynamicPrintConfig* config, Print* print, GCodePreviewData* gcode_preview_data) +{ + if (g_preview == nullptr) + { + Preview* panel = new Preview(parent, config, print, gcode_preview_data); + g_preview = new PreviewIface(panel); + } + + return g_preview; +} + // opt_index = 0, by the reason of zero-index in ConfigOptionVector by default (in case only one element) void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt_key, const boost::any& value, int opt_index /*= 0*/) { diff --git a/xs/src/slic3r/GUI/GUI.hpp b/src/slic3r/GUI/GUI.hpp similarity index 97% rename from xs/src/slic3r/GUI/GUI.hpp rename to src/slic3r/GUI/GUI.hpp index 998b572b98..8dfaf42c66 100644 --- a/xs/src/slic3r/GUI/GUI.hpp +++ b/src/slic3r/GUI/GUI.hpp @@ -39,6 +39,9 @@ class AppConfig; class PresetUpdater; class DynamicPrintConfig; class TabIface; +class PreviewIface; +class Print; +class GCodePreviewData; #define _(s) Slic3r::GUI::I18N::translate((s)) @@ -165,6 +168,8 @@ extern void open_preferences_dialog(int event_preferences); void create_preset_tabs(int event_value_change, int event_presets_changed); TabIface* get_preset_tab_iface(char *name); +PreviewIface* create_preview_iface(wxNotebook* notebook, DynamicPrintConfig* config, Print* print, GCodePreviewData* gcode_preview_data); + // add it at the end of the tab panel. void add_created_tab(Tab* panel, int event_value_change, int event_presets_changed); // Change option value in config diff --git a/xs/src/slic3r/GUI/GUI_ObjectParts.cpp b/src/slic3r/GUI/GUI_ObjectParts.cpp similarity index 100% rename from xs/src/slic3r/GUI/GUI_ObjectParts.cpp rename to src/slic3r/GUI/GUI_ObjectParts.cpp diff --git a/xs/src/slic3r/GUI/GUI_ObjectParts.hpp b/src/slic3r/GUI/GUI_ObjectParts.hpp similarity index 100% rename from xs/src/slic3r/GUI/GUI_ObjectParts.hpp rename to src/slic3r/GUI/GUI_ObjectParts.hpp diff --git a/xs/src/slic3r/GUI/LambdaObjectDialog.cpp b/src/slic3r/GUI/LambdaObjectDialog.cpp similarity index 100% rename from xs/src/slic3r/GUI/LambdaObjectDialog.cpp rename to src/slic3r/GUI/LambdaObjectDialog.cpp diff --git a/xs/src/slic3r/GUI/LambdaObjectDialog.hpp b/src/slic3r/GUI/LambdaObjectDialog.hpp similarity index 100% rename from xs/src/slic3r/GUI/LambdaObjectDialog.hpp rename to src/slic3r/GUI/LambdaObjectDialog.hpp diff --git a/xs/src/slic3r/GUI/MsgDialog.cpp b/src/slic3r/GUI/MsgDialog.cpp similarity index 100% rename from xs/src/slic3r/GUI/MsgDialog.cpp rename to src/slic3r/GUI/MsgDialog.cpp diff --git a/xs/src/slic3r/GUI/MsgDialog.hpp b/src/slic3r/GUI/MsgDialog.hpp similarity index 100% rename from xs/src/slic3r/GUI/MsgDialog.hpp rename to src/slic3r/GUI/MsgDialog.hpp diff --git a/xs/src/slic3r/GUI/OptionsGroup.cpp b/src/slic3r/GUI/OptionsGroup.cpp similarity index 100% rename from xs/src/slic3r/GUI/OptionsGroup.cpp rename to src/slic3r/GUI/OptionsGroup.cpp diff --git a/xs/src/slic3r/GUI/OptionsGroup.hpp b/src/slic3r/GUI/OptionsGroup.hpp similarity index 100% rename from xs/src/slic3r/GUI/OptionsGroup.hpp rename to src/slic3r/GUI/OptionsGroup.hpp diff --git a/xs/src/slic3r/GUI/Preferences.cpp b/src/slic3r/GUI/Preferences.cpp similarity index 100% rename from xs/src/slic3r/GUI/Preferences.cpp rename to src/slic3r/GUI/Preferences.cpp diff --git a/xs/src/slic3r/GUI/Preferences.hpp b/src/slic3r/GUI/Preferences.hpp similarity index 100% rename from xs/src/slic3r/GUI/Preferences.hpp rename to src/slic3r/GUI/Preferences.hpp diff --git a/xs/src/slic3r/GUI/Preset.cpp b/src/slic3r/GUI/Preset.cpp similarity index 100% rename from xs/src/slic3r/GUI/Preset.cpp rename to src/slic3r/GUI/Preset.cpp diff --git a/xs/src/slic3r/GUI/Preset.hpp b/src/slic3r/GUI/Preset.hpp similarity index 100% rename from xs/src/slic3r/GUI/Preset.hpp rename to src/slic3r/GUI/Preset.hpp diff --git a/xs/src/slic3r/GUI/PresetBundle.cpp b/src/slic3r/GUI/PresetBundle.cpp similarity index 100% rename from xs/src/slic3r/GUI/PresetBundle.cpp rename to src/slic3r/GUI/PresetBundle.cpp diff --git a/xs/src/slic3r/GUI/PresetBundle.hpp b/src/slic3r/GUI/PresetBundle.hpp similarity index 100% rename from xs/src/slic3r/GUI/PresetBundle.hpp rename to src/slic3r/GUI/PresetBundle.hpp diff --git a/xs/src/slic3r/GUI/PresetHints.cpp b/src/slic3r/GUI/PresetHints.cpp similarity index 100% rename from xs/src/slic3r/GUI/PresetHints.cpp rename to src/slic3r/GUI/PresetHints.cpp diff --git a/xs/src/slic3r/GUI/PresetHints.hpp b/src/slic3r/GUI/PresetHints.hpp similarity index 100% rename from xs/src/slic3r/GUI/PresetHints.hpp rename to src/slic3r/GUI/PresetHints.hpp diff --git a/xs/src/slic3r/GUI/ProgressIndicator.hpp b/src/slic3r/GUI/ProgressIndicator.hpp similarity index 100% rename from xs/src/slic3r/GUI/ProgressIndicator.hpp rename to src/slic3r/GUI/ProgressIndicator.hpp diff --git a/xs/src/slic3r/GUI/ProgressStatusBar.cpp b/src/slic3r/GUI/ProgressStatusBar.cpp similarity index 100% rename from xs/src/slic3r/GUI/ProgressStatusBar.cpp rename to src/slic3r/GUI/ProgressStatusBar.cpp diff --git a/xs/src/slic3r/GUI/ProgressStatusBar.hpp b/src/slic3r/GUI/ProgressStatusBar.hpp similarity index 98% rename from xs/src/slic3r/GUI/ProgressStatusBar.hpp rename to src/slic3r/GUI/ProgressStatusBar.hpp index 9a7f58eee7..7c2171a5e3 100644 --- a/xs/src/slic3r/GUI/ProgressStatusBar.hpp +++ b/src/slic3r/GUI/ProgressStatusBar.hpp @@ -4,7 +4,7 @@ #include #include -#include "../../callback.hpp" +#include "callback.hpp" class wxTimer; class wxGauge; diff --git a/xs/src/slic3r/GUI/RammingChart.cpp b/src/slic3r/GUI/RammingChart.cpp similarity index 100% rename from xs/src/slic3r/GUI/RammingChart.cpp rename to src/slic3r/GUI/RammingChart.cpp diff --git a/xs/src/slic3r/GUI/RammingChart.hpp b/src/slic3r/GUI/RammingChart.hpp similarity index 100% rename from xs/src/slic3r/GUI/RammingChart.hpp rename to src/slic3r/GUI/RammingChart.hpp diff --git a/xs/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp similarity index 100% rename from xs/src/slic3r/GUI/Tab.cpp rename to src/slic3r/GUI/Tab.cpp diff --git a/xs/src/slic3r/GUI/Tab.hpp b/src/slic3r/GUI/Tab.hpp similarity index 100% rename from xs/src/slic3r/GUI/Tab.hpp rename to src/slic3r/GUI/Tab.hpp diff --git a/xs/src/slic3r/GUI/TabIface.cpp b/src/slic3r/GUI/TabIface.cpp similarity index 100% rename from xs/src/slic3r/GUI/TabIface.cpp rename to src/slic3r/GUI/TabIface.cpp diff --git a/xs/src/slic3r/GUI/TabIface.hpp b/src/slic3r/GUI/TabIface.hpp similarity index 100% rename from xs/src/slic3r/GUI/TabIface.hpp rename to src/slic3r/GUI/TabIface.hpp diff --git a/xs/src/slic3r/GUI/UpdateDialogs.cpp b/src/slic3r/GUI/UpdateDialogs.cpp similarity index 100% rename from xs/src/slic3r/GUI/UpdateDialogs.cpp rename to src/slic3r/GUI/UpdateDialogs.cpp diff --git a/xs/src/slic3r/GUI/UpdateDialogs.hpp b/src/slic3r/GUI/UpdateDialogs.hpp similarity index 100% rename from xs/src/slic3r/GUI/UpdateDialogs.hpp rename to src/slic3r/GUI/UpdateDialogs.hpp diff --git a/xs/src/slic3r/GUI/Widget.hpp b/src/slic3r/GUI/Widget.hpp similarity index 100% rename from xs/src/slic3r/GUI/Widget.hpp rename to src/slic3r/GUI/Widget.hpp diff --git a/xs/src/slic3r/GUI/WipeTowerDialog.cpp b/src/slic3r/GUI/WipeTowerDialog.cpp similarity index 100% rename from xs/src/slic3r/GUI/WipeTowerDialog.cpp rename to src/slic3r/GUI/WipeTowerDialog.cpp diff --git a/xs/src/slic3r/GUI/WipeTowerDialog.hpp b/src/slic3r/GUI/WipeTowerDialog.hpp similarity index 100% rename from xs/src/slic3r/GUI/WipeTowerDialog.hpp rename to src/slic3r/GUI/WipeTowerDialog.hpp diff --git a/src/slic3r/GUI/callback.hpp b/src/slic3r/GUI/callback.hpp new file mode 100644 index 0000000000..ac92721a5b --- /dev/null +++ b/src/slic3r/GUI/callback.hpp @@ -0,0 +1,30 @@ +// I AM A PHONY PLACEHOLDER FOR THE PERL CALLBACK. +// GET RID OF ME! + +#ifndef slic3r_GUI_PerlCallback_phony_hpp_ +#define slic3r_GUI_PerlCallback_phony_hpp_ + +#include + +namespace Slic3r { + +class PerlCallback { +public: + PerlCallback(void *) {} + PerlCallback() {} + void register_callback(void *) {} + void deregister_callback() {} + void call() const {} + void call(int) const {} + void call(int, int) const {} + void call(const std::vector&) const {} + void call(double) const {} + void call(double, double) const {} + void call(double, double, double) const {} + void call(double, double, double, double) const {} + void call(bool b) const {} +}; + +} // namespace Slic3r + +#endif /* slic3r_GUI_PerlCallback_phony_hpp_ */ diff --git a/xs/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp similarity index 100% rename from xs/src/slic3r/GUI/wxExtensions.cpp rename to src/slic3r/GUI/wxExtensions.cpp diff --git a/xs/src/slic3r/GUI/wxExtensions.hpp b/src/slic3r/GUI/wxExtensions.hpp similarity index 100% rename from xs/src/slic3r/GUI/wxExtensions.hpp rename to src/slic3r/GUI/wxExtensions.hpp diff --git a/xs/src/slic3r/GUI/wxinit.h b/src/slic3r/GUI/wxinit.h similarity index 100% rename from xs/src/slic3r/GUI/wxinit.h rename to src/slic3r/GUI/wxinit.h diff --git a/xs/src/slic3r/Utils/ASCIIFolding.cpp b/src/slic3r/Utils/ASCIIFolding.cpp similarity index 100% rename from xs/src/slic3r/Utils/ASCIIFolding.cpp rename to src/slic3r/Utils/ASCIIFolding.cpp diff --git a/xs/src/slic3r/Utils/ASCIIFolding.hpp b/src/slic3r/Utils/ASCIIFolding.hpp similarity index 100% rename from xs/src/slic3r/Utils/ASCIIFolding.hpp rename to src/slic3r/Utils/ASCIIFolding.hpp diff --git a/xs/src/slic3r/Utils/Bonjour.cpp b/src/slic3r/Utils/Bonjour.cpp similarity index 100% rename from xs/src/slic3r/Utils/Bonjour.cpp rename to src/slic3r/Utils/Bonjour.cpp diff --git a/xs/src/slic3r/Utils/Bonjour.hpp b/src/slic3r/Utils/Bonjour.hpp similarity index 100% rename from xs/src/slic3r/Utils/Bonjour.hpp rename to src/slic3r/Utils/Bonjour.hpp diff --git a/xs/src/slic3r/Utils/Duet.cpp b/src/slic3r/Utils/Duet.cpp similarity index 100% rename from xs/src/slic3r/Utils/Duet.cpp rename to src/slic3r/Utils/Duet.cpp diff --git a/xs/src/slic3r/Utils/Duet.hpp b/src/slic3r/Utils/Duet.hpp similarity index 100% rename from xs/src/slic3r/Utils/Duet.hpp rename to src/slic3r/Utils/Duet.hpp diff --git a/xs/src/slic3r/Utils/FixModelByWin10.cpp b/src/slic3r/Utils/FixModelByWin10.cpp similarity index 100% rename from xs/src/slic3r/Utils/FixModelByWin10.cpp rename to src/slic3r/Utils/FixModelByWin10.cpp diff --git a/xs/src/slic3r/Utils/FixModelByWin10.hpp b/src/slic3r/Utils/FixModelByWin10.hpp similarity index 100% rename from xs/src/slic3r/Utils/FixModelByWin10.hpp rename to src/slic3r/Utils/FixModelByWin10.hpp diff --git a/xs/src/slic3r/Utils/HexFile.cpp b/src/slic3r/Utils/HexFile.cpp similarity index 100% rename from xs/src/slic3r/Utils/HexFile.cpp rename to src/slic3r/Utils/HexFile.cpp diff --git a/xs/src/slic3r/Utils/HexFile.hpp b/src/slic3r/Utils/HexFile.hpp similarity index 100% rename from xs/src/slic3r/Utils/HexFile.hpp rename to src/slic3r/Utils/HexFile.hpp diff --git a/xs/src/slic3r/Utils/Http.cpp b/src/slic3r/Utils/Http.cpp similarity index 100% rename from xs/src/slic3r/Utils/Http.cpp rename to src/slic3r/Utils/Http.cpp diff --git a/xs/src/slic3r/Utils/Http.hpp b/src/slic3r/Utils/Http.hpp similarity index 100% rename from xs/src/slic3r/Utils/Http.hpp rename to src/slic3r/Utils/Http.hpp diff --git a/xs/src/slic3r/Utils/OctoPrint.cpp b/src/slic3r/Utils/OctoPrint.cpp similarity index 100% rename from xs/src/slic3r/Utils/OctoPrint.cpp rename to src/slic3r/Utils/OctoPrint.cpp diff --git a/xs/src/slic3r/Utils/OctoPrint.hpp b/src/slic3r/Utils/OctoPrint.hpp similarity index 100% rename from xs/src/slic3r/Utils/OctoPrint.hpp rename to src/slic3r/Utils/OctoPrint.hpp diff --git a/xs/src/slic3r/Utils/PresetUpdater.cpp b/src/slic3r/Utils/PresetUpdater.cpp similarity index 100% rename from xs/src/slic3r/Utils/PresetUpdater.cpp rename to src/slic3r/Utils/PresetUpdater.cpp diff --git a/xs/src/slic3r/Utils/PresetUpdater.hpp b/src/slic3r/Utils/PresetUpdater.hpp similarity index 100% rename from xs/src/slic3r/Utils/PresetUpdater.hpp rename to src/slic3r/Utils/PresetUpdater.hpp diff --git a/xs/src/slic3r/Utils/PrintHost.cpp b/src/slic3r/Utils/PrintHost.cpp similarity index 100% rename from xs/src/slic3r/Utils/PrintHost.cpp rename to src/slic3r/Utils/PrintHost.cpp diff --git a/xs/src/slic3r/Utils/PrintHost.hpp b/src/slic3r/Utils/PrintHost.hpp similarity index 100% rename from xs/src/slic3r/Utils/PrintHost.hpp rename to src/slic3r/Utils/PrintHost.hpp diff --git a/xs/src/slic3r/Utils/PrintHostSendDialog.cpp b/src/slic3r/Utils/PrintHostSendDialog.cpp similarity index 100% rename from xs/src/slic3r/Utils/PrintHostSendDialog.cpp rename to src/slic3r/Utils/PrintHostSendDialog.cpp diff --git a/xs/src/slic3r/Utils/PrintHostSendDialog.hpp b/src/slic3r/Utils/PrintHostSendDialog.hpp similarity index 100% rename from xs/src/slic3r/Utils/PrintHostSendDialog.hpp rename to src/slic3r/Utils/PrintHostSendDialog.hpp diff --git a/xs/src/slic3r/Utils/Semver.hpp b/src/slic3r/Utils/Semver.hpp similarity index 100% rename from xs/src/slic3r/Utils/Semver.hpp rename to src/slic3r/Utils/Semver.hpp diff --git a/xs/src/slic3r/Utils/Serial.cpp b/src/slic3r/Utils/Serial.cpp similarity index 100% rename from xs/src/slic3r/Utils/Serial.cpp rename to src/slic3r/Utils/Serial.cpp diff --git a/xs/src/slic3r/Utils/Serial.hpp b/src/slic3r/Utils/Serial.hpp similarity index 100% rename from xs/src/slic3r/Utils/Serial.hpp rename to src/slic3r/Utils/Serial.hpp diff --git a/xs/src/slic3r/Utils/Time.cpp b/src/slic3r/Utils/Time.cpp similarity index 100% rename from xs/src/slic3r/Utils/Time.cpp rename to src/slic3r/Utils/Time.cpp diff --git a/xs/src/slic3r/Utils/Time.hpp b/src/slic3r/Utils/Time.hpp similarity index 100% rename from xs/src/slic3r/Utils/Time.hpp rename to src/slic3r/Utils/Time.hpp diff --git a/xs/CMakeLists.txt b/xs/CMakeLists.txt index 69e03779a2..92964c900a 100644 --- a/xs/CMakeLists.txt +++ b/xs/CMakeLists.txt @@ -1,435 +1,4 @@ -# Enable C++11 language standard. -set(CMAKE_CXX_STANDARD 11) -set(CMAKE_CXX_STANDARD_REQUIRED ON) - -# Enable C11 language standard. -set(CMAKE_C_STANDARD 11) -set(CMAKE_C_STANDARD_REQUIRED ON) - -# Add our own cmake module path. -list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/modules/) - -if (CMAKE_SYSTEM_NAME STREQUAL "Linux") - # Workaround for an old CMake, which does not understand CMAKE_CXX_STANDARD. - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Wno-reorder" ) - find_package(PkgConfig REQUIRED) -endif() - -if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUXX) - # Adding -fext-numeric-literals to enable GCC extensions on definitions of quad float literals, which are required by Boost. - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fext-numeric-literals" ) -endif() - -# Where all the bundled libraries reside? -set(LIBDIR ${CMAKE_CURRENT_SOURCE_DIR}/src/) -# For the bundled boost libraries (boost::nowide) -include_directories(${LIBDIR}) -# For libslic3r.h -include_directories(${LIBDIR}/libslic3r) -#set(CMAKE_INCLUDE_CURRENT_DIR ON) - -if(WIN32) - # BOOST_ALL_NO_LIB: Avoid the automatic linking of Boost libraries on Windows. Rather rely on explicit linking. - add_definitions(-D_USE_MATH_DEFINES -D_WIN32 -DBOOST_ALL_NO_LIB -DBOOST_USE_WINAPI_VERSION=0x601) - # -D_ITERATOR_DEBUG_LEVEL) - if(WIN10SDK_PATH) - message("Building with Win10 Netfabb STL fixing service support") - add_definitions(-DHAS_WIN10SDK) - include_directories("${WIN10SDK_PATH}/Include") - else() - message("Building without Win10 Netfabb STL fixing service support") - endif() -endif() - -add_definitions(-DwxUSE_UNICODE -D_UNICODE -DUNICODE -DWXINTL_NO_GETTEXT_MACRO) - -add_library(libslic3r STATIC - ${LIBDIR}/libslic3r/BoundingBox.cpp - ${LIBDIR}/libslic3r/BoundingBox.hpp - ${LIBDIR}/libslic3r/BridgeDetector.cpp - ${LIBDIR}/libslic3r/BridgeDetector.hpp - ${LIBDIR}/libslic3r/ClipperUtils.cpp - ${LIBDIR}/libslic3r/ClipperUtils.hpp - ${LIBDIR}/libslic3r/Config.cpp - ${LIBDIR}/libslic3r/Config.hpp - ${LIBDIR}/libslic3r/EdgeGrid.cpp - ${LIBDIR}/libslic3r/EdgeGrid.hpp - ${LIBDIR}/libslic3r/ExPolygon.cpp - ${LIBDIR}/libslic3r/ExPolygon.hpp - ${LIBDIR}/libslic3r/ExPolygonCollection.cpp - ${LIBDIR}/libslic3r/ExPolygonCollection.hpp - ${LIBDIR}/libslic3r/Extruder.cpp - ${LIBDIR}/libslic3r/Extruder.hpp - ${LIBDIR}/libslic3r/ExtrusionEntity.cpp - ${LIBDIR}/libslic3r/ExtrusionEntity.hpp - ${LIBDIR}/libslic3r/ExtrusionEntityCollection.cpp - ${LIBDIR}/libslic3r/ExtrusionEntityCollection.hpp - ${LIBDIR}/libslic3r/ExtrusionSimulator.cpp - ${LIBDIR}/libslic3r/ExtrusionSimulator.hpp - ${LIBDIR}/libslic3r/FileParserError.hpp - ${LIBDIR}/libslic3r/Fill/Fill.cpp - ${LIBDIR}/libslic3r/Fill/Fill.hpp - ${LIBDIR}/libslic3r/Fill/Fill3DHoneycomb.cpp - ${LIBDIR}/libslic3r/Fill/Fill3DHoneycomb.hpp - ${LIBDIR}/libslic3r/Fill/FillBase.cpp - ${LIBDIR}/libslic3r/Fill/FillBase.hpp - ${LIBDIR}/libslic3r/Fill/FillConcentric.cpp - ${LIBDIR}/libslic3r/Fill/FillConcentric.hpp - ${LIBDIR}/libslic3r/Fill/FillHoneycomb.cpp - ${LIBDIR}/libslic3r/Fill/FillHoneycomb.hpp - ${LIBDIR}/libslic3r/Fill/FillGyroid.cpp - ${LIBDIR}/libslic3r/Fill/FillGyroid.hpp - ${LIBDIR}/libslic3r/Fill/FillPlanePath.cpp - ${LIBDIR}/libslic3r/Fill/FillPlanePath.hpp - ${LIBDIR}/libslic3r/Fill/FillRectilinear.cpp - ${LIBDIR}/libslic3r/Fill/FillRectilinear.hpp - ${LIBDIR}/libslic3r/Fill/FillRectilinear2.cpp - ${LIBDIR}/libslic3r/Fill/FillRectilinear2.hpp - ${LIBDIR}/libslic3r/Fill/FillRectilinear3.cpp - ${LIBDIR}/libslic3r/Fill/FillRectilinear3.hpp - ${LIBDIR}/libslic3r/Flow.cpp - ${LIBDIR}/libslic3r/Flow.hpp - ${LIBDIR}/libslic3r/Format/3mf.cpp - ${LIBDIR}/libslic3r/Format/3mf.hpp - ${LIBDIR}/libslic3r/Format/AMF.cpp - ${LIBDIR}/libslic3r/Format/AMF.hpp - ${LIBDIR}/libslic3r/Format/OBJ.cpp - ${LIBDIR}/libslic3r/Format/OBJ.hpp - ${LIBDIR}/libslic3r/Format/objparser.cpp - ${LIBDIR}/libslic3r/Format/objparser.hpp - ${LIBDIR}/libslic3r/Format/PRUS.cpp - ${LIBDIR}/libslic3r/Format/PRUS.hpp - ${LIBDIR}/libslic3r/Format/STL.cpp - ${LIBDIR}/libslic3r/Format/STL.hpp - ${LIBDIR}/libslic3r/GCode/Analyzer.cpp - ${LIBDIR}/libslic3r/GCode/Analyzer.hpp - ${LIBDIR}/libslic3r/GCode/CoolingBuffer.cpp - ${LIBDIR}/libslic3r/GCode/CoolingBuffer.hpp - ${LIBDIR}/libslic3r/GCode/PostProcessor.cpp - ${LIBDIR}/libslic3r/GCode/PostProcessor.hpp - ${LIBDIR}/libslic3r/GCode/PressureEqualizer.cpp - ${LIBDIR}/libslic3r/GCode/PressureEqualizer.hpp - ${LIBDIR}/libslic3r/GCode/PreviewData.cpp - ${LIBDIR}/libslic3r/GCode/PreviewData.hpp - ${LIBDIR}/libslic3r/GCode/PrintExtents.cpp - ${LIBDIR}/libslic3r/GCode/PrintExtents.hpp - ${LIBDIR}/libslic3r/GCode/SpiralVase.cpp - ${LIBDIR}/libslic3r/GCode/SpiralVase.hpp - ${LIBDIR}/libslic3r/GCode/ToolOrdering.cpp - ${LIBDIR}/libslic3r/GCode/ToolOrdering.hpp - ${LIBDIR}/libslic3r/GCode/WipeTower.hpp - ${LIBDIR}/libslic3r/GCode/WipeTowerPrusaMM.cpp - ${LIBDIR}/libslic3r/GCode/WipeTowerPrusaMM.hpp - ${LIBDIR}/libslic3r/GCode.cpp - ${LIBDIR}/libslic3r/GCode.hpp - ${LIBDIR}/libslic3r/GCodeReader.cpp - ${LIBDIR}/libslic3r/GCodeReader.hpp - ${LIBDIR}/libslic3r/GCodeSender.cpp - ${LIBDIR}/libslic3r/GCodeSender.hpp - ${LIBDIR}/libslic3r/GCodeTimeEstimator.cpp - ${LIBDIR}/libslic3r/GCodeTimeEstimator.hpp - ${LIBDIR}/libslic3r/GCodeWriter.cpp - ${LIBDIR}/libslic3r/GCodeWriter.hpp - ${LIBDIR}/libslic3r/Geometry.cpp - ${LIBDIR}/libslic3r/Geometry.hpp - ${LIBDIR}/libslic3r/Int128.hpp -# ${LIBDIR}/libslic3r/KdTree.hpp - ${LIBDIR}/libslic3r/Layer.cpp - ${LIBDIR}/libslic3r/Layer.hpp - ${LIBDIR}/libslic3r/LayerRegion.cpp - ${LIBDIR}/libslic3r/libslic3r.h - ${LIBDIR}/libslic3r/Line.cpp - ${LIBDIR}/libslic3r/Line.hpp - ${LIBDIR}/libslic3r/Model.cpp - ${LIBDIR}/libslic3r/Model.hpp - ${LIBDIR}/libslic3r/ModelArrange.hpp - ${LIBDIR}/libslic3r/MotionPlanner.cpp - ${LIBDIR}/libslic3r/MotionPlanner.hpp - ${LIBDIR}/libslic3r/MultiPoint.cpp - ${LIBDIR}/libslic3r/MultiPoint.hpp - ${LIBDIR}/libslic3r/MutablePriorityQueue.hpp - ${LIBDIR}/libslic3r/PerimeterGenerator.cpp - ${LIBDIR}/libslic3r/PerimeterGenerator.hpp - ${LIBDIR}/libslic3r/PlaceholderParser.cpp - ${LIBDIR}/libslic3r/PlaceholderParser.hpp - ${LIBDIR}/libslic3r/Point.cpp - ${LIBDIR}/libslic3r/Point.hpp - ${LIBDIR}/libslic3r/Polygon.cpp - ${LIBDIR}/libslic3r/Polygon.hpp - ${LIBDIR}/libslic3r/Polyline.cpp - ${LIBDIR}/libslic3r/Polyline.hpp - ${LIBDIR}/libslic3r/PolylineCollection.cpp - ${LIBDIR}/libslic3r/PolylineCollection.hpp - ${LIBDIR}/libslic3r/Print.cpp - ${LIBDIR}/libslic3r/Print.hpp - ${LIBDIR}/libslic3r/PrintExport.hpp - ${LIBDIR}/libslic3r/PrintConfig.cpp - ${LIBDIR}/libslic3r/PrintConfig.hpp - ${LIBDIR}/libslic3r/PrintObject.cpp - ${LIBDIR}/libslic3r/PrintRegion.cpp - ${LIBDIR}/libslic3r/Slicing.cpp - ${LIBDIR}/libslic3r/Slicing.hpp - ${LIBDIR}/libslic3r/SlicingAdaptive.cpp - ${LIBDIR}/libslic3r/SlicingAdaptive.hpp - ${LIBDIR}/libslic3r/SupportMaterial.cpp - ${LIBDIR}/libslic3r/SupportMaterial.hpp - ${LIBDIR}/libslic3r/Surface.cpp - ${LIBDIR}/libslic3r/Surface.hpp - ${LIBDIR}/libslic3r/SurfaceCollection.cpp - ${LIBDIR}/libslic3r/SurfaceCollection.hpp - ${LIBDIR}/libslic3r/SVG.cpp - ${LIBDIR}/libslic3r/SVG.hpp - ${LIBDIR}/libslic3r/Technologies.hpp - ${LIBDIR}/libslic3r/TriangleMesh.cpp - ${LIBDIR}/libslic3r/TriangleMesh.hpp - ${LIBDIR}/libslic3r/SLABasePool.hpp - ${LIBDIR}/libslic3r/SLABasePool.cpp -# ${LIBDIR}/libslic3r/utils.cpp - ${LIBDIR}/libslic3r/Utils.hpp - -) - -add_library(libslic3r_gui STATIC - ${LIBDIR}/slic3r/GUI/AboutDialog.cpp - ${LIBDIR}/slic3r/GUI/AboutDialog.hpp - ${LIBDIR}/slic3r/GUI/AppConfig.cpp - ${LIBDIR}/slic3r/GUI/AppConfig.hpp - ${LIBDIR}/slic3r/GUI/BackgroundSlicingProcess.cpp - ${LIBDIR}/slic3r/GUI/BackgroundSlicingProcess.hpp - ${LIBDIR}/slic3r/GUI/BitmapCache.cpp - ${LIBDIR}/slic3r/GUI/BitmapCache.hpp - ${LIBDIR}/slic3r/GUI/ConfigSnapshotDialog.cpp - ${LIBDIR}/slic3r/GUI/ConfigSnapshotDialog.hpp - ${LIBDIR}/slic3r/GUI/3DScene.cpp - ${LIBDIR}/slic3r/GUI/3DScene.hpp - ${LIBDIR}/slic3r/GUI/GLShader.cpp - ${LIBDIR}/slic3r/GUI/GLShader.hpp - ${LIBDIR}/slic3r/GUI/GLCanvas3D.hpp - ${LIBDIR}/slic3r/GUI/GLCanvas3D.cpp - ${LIBDIR}/slic3r/GUI/GLCanvas3DManager.hpp - ${LIBDIR}/slic3r/GUI/GLCanvas3DManager.cpp - ${LIBDIR}/slic3r/GUI/GLGizmo.hpp - ${LIBDIR}/slic3r/GUI/GLGizmo.cpp - ${LIBDIR}/slic3r/GUI/GLTexture.hpp - ${LIBDIR}/slic3r/GUI/GLTexture.cpp - ${LIBDIR}/slic3r/GUI/GLToolbar.hpp - ${LIBDIR}/slic3r/GUI/GLToolbar.cpp - ${LIBDIR}/slic3r/GUI/Preferences.cpp - ${LIBDIR}/slic3r/GUI/Preferences.hpp - ${LIBDIR}/slic3r/GUI/Preset.cpp - ${LIBDIR}/slic3r/GUI/Preset.hpp - ${LIBDIR}/slic3r/GUI/PresetBundle.cpp - ${LIBDIR}/slic3r/GUI/PresetBundle.hpp - ${LIBDIR}/slic3r/GUI/PresetHints.cpp - ${LIBDIR}/slic3r/GUI/PresetHints.hpp - ${LIBDIR}/slic3r/GUI/GUI.cpp - ${LIBDIR}/slic3r/GUI/GUI.hpp - ${LIBDIR}/slic3r/GUI/GUI_ObjectParts.cpp - ${LIBDIR}/slic3r/GUI/GUI_ObjectParts.hpp - ${LIBDIR}/slic3r/GUI/LambdaObjectDialog.cpp - ${LIBDIR}/slic3r/GUI/LambdaObjectDialog.hpp - ${LIBDIR}/slic3r/GUI/Tab.cpp - ${LIBDIR}/slic3r/GUI/Tab.hpp - ${LIBDIR}/slic3r/GUI/TabIface.cpp - ${LIBDIR}/slic3r/GUI/TabIface.hpp - ${LIBDIR}/slic3r/GUI/Field.cpp - ${LIBDIR}/slic3r/GUI/Field.hpp - ${LIBDIR}/slic3r/GUI/OptionsGroup.cpp - ${LIBDIR}/slic3r/GUI/OptionsGroup.hpp - ${LIBDIR}/slic3r/GUI/BedShapeDialog.cpp - ${LIBDIR}/slic3r/GUI/BedShapeDialog.hpp - ${LIBDIR}/slic3r/GUI/2DBed.cpp - ${LIBDIR}/slic3r/GUI/2DBed.hpp - ${LIBDIR}/slic3r/GUI/wxExtensions.cpp - ${LIBDIR}/slic3r/GUI/wxExtensions.hpp - ${LIBDIR}/slic3r/GUI/WipeTowerDialog.cpp - ${LIBDIR}/slic3r/GUI/WipeTowerDialog.hpp - ${LIBDIR}/slic3r/GUI/RammingChart.cpp - ${LIBDIR}/slic3r/GUI/RammingChart.hpp - ${LIBDIR}/slic3r/GUI/BonjourDialog.cpp - ${LIBDIR}/slic3r/GUI/BonjourDialog.hpp - ${LIBDIR}/slic3r/GUI/ButtonsDescription.cpp - ${LIBDIR}/slic3r/GUI/ButtonsDescription.hpp - ${LIBDIR}/slic3r/Config/Snapshot.cpp - ${LIBDIR}/slic3r/Config/Snapshot.hpp - ${LIBDIR}/slic3r/Config/Version.cpp - ${LIBDIR}/slic3r/Config/Version.hpp - ${LIBDIR}/slic3r/Utils/ASCIIFolding.cpp - ${LIBDIR}/slic3r/Utils/ASCIIFolding.hpp - ${LIBDIR}/slic3r/Utils/Serial.cpp - ${LIBDIR}/slic3r/Utils/Serial.hpp - ${LIBDIR}/slic3r/GUI/ConfigWizard.cpp - ${LIBDIR}/slic3r/GUI/ConfigWizard.hpp - ${LIBDIR}/slic3r/GUI/MsgDialog.cpp - ${LIBDIR}/slic3r/GUI/MsgDialog.hpp - ${LIBDIR}/slic3r/GUI/UpdateDialogs.cpp - ${LIBDIR}/slic3r/GUI/UpdateDialogs.hpp - ${LIBDIR}/slic3r/GUI/FirmwareDialog.cpp - ${LIBDIR}/slic3r/GUI/FirmwareDialog.hpp - ${LIBDIR}/slic3r/GUI/ProgressIndicator.hpp - ${LIBDIR}/slic3r/GUI/ProgressStatusBar.hpp - ${LIBDIR}/slic3r/GUI/ProgressStatusBar.cpp - ${LIBDIR}/slic3r/Utils/Http.cpp - ${LIBDIR}/slic3r/Utils/Http.hpp - ${LIBDIR}/slic3r/Utils/FixModelByWin10.cpp - ${LIBDIR}/slic3r/Utils/FixModelByWin10.hpp - ${LIBDIR}/slic3r/Utils/PrintHostSendDialog.cpp - ${LIBDIR}/slic3r/Utils/PrintHostSendDialog.hpp - ${LIBDIR}/slic3r/Utils/OctoPrint.cpp - ${LIBDIR}/slic3r/Utils/OctoPrint.hpp - ${LIBDIR}/slic3r/Utils/Duet.cpp - ${LIBDIR}/slic3r/Utils/Duet.hpp - ${LIBDIR}/slic3r/Utils/PrintHost.cpp - ${LIBDIR}/slic3r/Utils/PrintHost.hpp - ${LIBDIR}/slic3r/Utils/Bonjour.cpp - ${LIBDIR}/slic3r/Utils/Bonjour.hpp - ${LIBDIR}/slic3r/Utils/PresetUpdater.cpp - ${LIBDIR}/slic3r/Utils/PresetUpdater.hpp - ${LIBDIR}/slic3r/Utils/Time.cpp - ${LIBDIR}/slic3r/Utils/Time.hpp - ${LIBDIR}/slic3r/Utils/HexFile.cpp - ${LIBDIR}/slic3r/Utils/HexFile.hpp - ${LIBDIR}/slic3r/AppController.hpp - ${LIBDIR}/slic3r/AppController.cpp - ${LIBDIR}/slic3r/AppControllerWx.cpp -) - -add_library(admesh STATIC - ${LIBDIR}/admesh/connect.cpp - ${LIBDIR}/admesh/normals.cpp - ${LIBDIR}/admesh/shared.cpp - ${LIBDIR}/admesh/stl.h - ${LIBDIR}/admesh/stl_io.cpp - ${LIBDIR}/admesh/stlinit.cpp - ${LIBDIR}/admesh/util.cpp -) - -add_library(miniz STATIC - ${LIBDIR}/miniz/miniz.h - ${LIBDIR}/miniz/miniz_common.h - ${LIBDIR}/miniz/miniz_tdef.h - ${LIBDIR}/miniz/miniz_tinfl.h - ${LIBDIR}/miniz/miniz_zip.h - ${LIBDIR}/miniz/miniz.cpp - ${LIBDIR}/miniz/miniz_tdef.cpp - ${LIBDIR}/miniz/miniz_tinfl.cpp - ${LIBDIR}/miniz/miniz_zip.cpp -) - -add_library(clipper STATIC - ${LIBDIR}/clipper.cpp - ${LIBDIR}/clipper.hpp -) - -add_library(polypartition STATIC - ${LIBDIR}/polypartition.cpp - ${LIBDIR}/polypartition.h -) - -add_library(poly2tri STATIC - ${LIBDIR}/poly2tri/common/shapes.cc - ${LIBDIR}/poly2tri/common/shapes.h - ${LIBDIR}/poly2tri/common/utils.h - ${LIBDIR}/poly2tri/poly2tri.h - ${LIBDIR}/poly2tri/sweep/advancing_front.cc - ${LIBDIR}/poly2tri/sweep/advancing_front.h - ${LIBDIR}/poly2tri/sweep/cdt.cc - ${LIBDIR}/poly2tri/sweep/cdt.h - ${LIBDIR}/poly2tri/sweep/sweep.cc - ${LIBDIR}/poly2tri/sweep/sweep.h - ${LIBDIR}/poly2tri/sweep/sweep_context.cc - ${LIBDIR}/poly2tri/sweep/sweep_context.h -) - -add_library(nowide STATIC - ${LIBDIR}/boost/nowide/args.hpp - ${LIBDIR}/boost/nowide/cenv.hpp - ${LIBDIR}/boost/nowide/config.hpp - ${LIBDIR}/boost/nowide/convert.hpp - ${LIBDIR}/boost/nowide/cstdio.hpp - ${LIBDIR}/boost/nowide/cstdlib.hpp - ${LIBDIR}/boost/nowide/filebuf.hpp - ${LIBDIR}/boost/nowide/fstream.hpp - ${LIBDIR}/boost/nowide/integration/filesystem.hpp - ${LIBDIR}/boost/nowide/iostream.cpp - ${LIBDIR}/boost/nowide/iostream.hpp - ${LIBDIR}/boost/nowide/stackstring.hpp - ${LIBDIR}/boost/nowide/system.hpp - ${LIBDIR}/boost/nowide/utf8_codecvt.hpp - ${LIBDIR}/boost/nowide/windows.hpp -) - -add_library(Shiny STATIC - ${LIBDIR}/Shiny/Shiny.h - ${LIBDIR}/Shiny/ShinyConfig.h - ${LIBDIR}/Shiny/ShinyData.h - ${LIBDIR}/Shiny/ShinyMacros.h - ${LIBDIR}/Shiny/ShinyManager.c - ${LIBDIR}/Shiny/ShinyManager.h - ${LIBDIR}/Shiny/ShinyNode.c - ${LIBDIR}/Shiny/ShinyNode.h - ${LIBDIR}/Shiny/ShinyNodePool.c - ${LIBDIR}/Shiny/ShinyNodePool.h - ${LIBDIR}/Shiny/ShinyNodeState.c - ${LIBDIR}/Shiny/ShinyNodeState.h - ${LIBDIR}/Shiny/ShinyOutput.c - ${LIBDIR}/Shiny/ShinyOutput.h - ${LIBDIR}/Shiny/ShinyPrereqs.h - ${LIBDIR}/Shiny/ShinyTools.c - ${LIBDIR}/Shiny/ShinyTools.h - ${LIBDIR}/Shiny/ShinyVersion.h - ${LIBDIR}/Shiny/ShinyZone.c - ${LIBDIR}/Shiny/ShinyZone.h -) - -add_library(semver STATIC - ${LIBDIR}/semver/semver.h - ${LIBDIR}/semver/semver.c -) - -# ############################################################################## -# Configure rasterizer target -# ############################################################################## - -find_package(PNG QUIET) - -option(RASTERIZER_FORCE_BUILTIN_LIBPNG "Force the usage of builting libpng instead of the system version." OFF) - -add_library(rasterizer STATIC - ${LIBDIR}/libslic3r/Rasterizer/Rasterizer.hpp - ${LIBDIR}/libslic3r/Rasterizer/Rasterizer.cpp -) - -if(PNG_FOUND AND NOT RASTERIZER_FORCE_BUILTIN_LIBPNG) - message(STATUS "Using system libpng.") - target_link_libraries(rasterizer PRIVATE ${PNG_LIBRARIES}) - target_include_directories(rasterizer PRIVATE ${PNG_INCLUDE_DIRS}) - target_compile_definitions(rasterizer PRIVATE ${PNG_DEFINITIONS}) -else() - set(ZLIB_LIBRARY "") - message(WARNING "Using builtin libpng. This can cause crashes on some platforms.") - add_subdirectory( ${LIBDIR}/png/zlib) - - set(ZLIB_INCLUDE_DIR - ${LIBDIR}/png/zlib - ${CMAKE_CURRENT_BINARY_DIR}/src/png/zlib - ) - - add_subdirectory( ${LIBDIR}/png/libpng ) - set_target_properties(zlibstatic PROPERTIES POSITION_INDEPENDENT_CODE ON) - set_target_properties(png_static PROPERTIES POSITION_INDEPENDENT_CODE ON) - - target_include_directories(rasterizer PRIVATE - ${LIBDIR}/png/libpng - ${CMAKE_CURRENT_BINARY_DIR}/src/png/libpng - ) - target_link_libraries(rasterizer PRIVATE png_static zlibstatic) - -endif() - -target_link_libraries(libslic3r rasterizer ) - -# ############################################################################## +project(XS) # Generate the Slic3r Perl module (XS) typemap file. set(MyTypemap ${CMAKE_CURRENT_BINARY_DIR}/typemap) @@ -461,12 +30,6 @@ set(XS_XSP_FILES ${XSP_DIR}/GCode.xsp ${XSP_DIR}/GCodeSender.xsp ${XSP_DIR}/Geometry.xsp - ${XSP_DIR}/GUI.xsp - ${XSP_DIR}/GUI_AppConfig.xsp - ${XSP_DIR}/GUI_BackgroundSlicingProcess.xsp - ${XSP_DIR}/GUI_3DScene.xsp - ${XSP_DIR}/GUI_Preset.xsp - ${XSP_DIR}/GUI_Tab.xsp ${XSP_DIR}/Layer.xsp ${XSP_DIR}/Line.xsp ${XSP_DIR}/Model.xsp @@ -481,10 +44,6 @@ set(XS_XSP_FILES ${XSP_DIR}/Surface.xsp ${XSP_DIR}/SurfaceCollection.xsp ${XSP_DIR}/TriangleMesh.xsp - ${XSP_DIR}/Utils_PrintHost.xsp - ${XSP_DIR}/Utils_PresetUpdater.xsp - ${XSP_DIR}/AppController.xsp - ${XSP_DIR}/ProgressStatusBar.xsp ${XSP_DIR}/XS.xsp ) foreach (file ${XS_XSP_FILES}) @@ -515,46 +74,38 @@ else() endif() add_library(XS ${XS_SHARED_LIBRARY_TYPE} ${XS_MAIN_CPP} - ${LIBDIR}/libslic3r/utils.cpp - ${LIBDIR}/slic3r/GUI/wxPerlIface.cpp - ${LIBDIR}/perlglue.cpp - ${LIBDIR}/callback.cpp - ${LIBDIR}/callback.hpp - ${LIBDIR}/ppport.h - ${LIBDIR}/xsinit.h - ${CMAKE_CURRENT_LIST_DIR}/xsp/my.map +# ${LIBDIR}/libslic3r/utils.cpp +# ${LIBDIR}/slic3r/GUI/wxPerlIface.cpp + src/perlglue.cpp +# src/callback.cpp +# src/callback.hpp + src/ppport.h + src/xsinit.h + xsp/my.map # mytype.map is empty. Is it required by Build.PL or the Perl xspp module? - ${CMAKE_CURRENT_LIST_DIR}/xsp/mytype.map + xsp/mytype.map # Used by Perl xsubpp to generate XS.cpp - ${CMAKE_CURRENT_LIST_DIR}/xsp/typemap.xspt + xsp/typemap.xspt ) if(APPLE) set_target_properties(XS PROPERTIES BUNDLE TRUE) # Ignore undefined symbols of the perl interpreter, they will be found in the caller image. target_link_libraries(XS "-undefined dynamic_lookup") endif() -target_link_libraries(XS libslic3r libslic3r_gui admesh miniz clipper nowide polypartition poly2tri semver avrdude qhull) +target_link_libraries(XS libslic3r admesh miniz clipper nowide polypartition poly2tri semver avrdude qhull) if(SLIC3R_PROFILE) target_link_libraries(XS Shiny) endif() -# Add the OpenGL and GLU libraries. -if (SLIC3R_GUI) - if (MSVC) - target_link_libraries(XS user32.lib Setupapi.lib OpenGL32.Lib GlU32.Lib) - elseif (MINGW) - target_link_libraries(XS -lopengl32) - elseif (APPLE) - target_link_libraries(XS "-framework OpenGL") - else () - target_link_libraries(XS -lGL -lGLU) - endif () -endif () - target_include_directories(XS PRIVATE src src/libslic3r) # Local include directories target_compile_definitions(XS PRIVATE -DSLIC3RXS) set_target_properties(XS PROPERTIES PREFIX "") # Prevent cmake from generating libXS.so instead of XS.so +target_link_libraries(XS ${Boost_LIBRARIES}) +# target_link_libraries(XS ${wxWidgets_LIBRARIES}) +# target_link_libraries(XS ${CURL_LIBRARIES}) +# target_link_libraries(XS ${OPENSSL_LIBRARIES}) + if (APPLE) # add_compile_options(-stdlib=libc++) # add_definitions(-DBOOST_THREAD_DONT_USE_CHRONO -DBOOST_NO_CXX11_RVALUE_REFERENCES -DBOOST_THREAD_USES_MOVE) @@ -578,56 +129,19 @@ if (MSVC AND SLIC3R_MSVC_PDB AND "${CMAKE_BUILD_TYPE}" STREQUAL "Release") ) endif() -## Configuration flags -if (SLIC3R_GUI) - message("Slic3r will be built with GUI support") - target_compile_definitions(XS PRIVATE -DSLIC3R_GUI) -endif () - -if (SLIC3R_PROFILE) - message("Slic3r will be built with a Shiny invasive profiler") - add_definitions(-DSLIC3R_PROFILE) -endif () - if (CMAKE_BUILD_TYPE MATCHES DEBUG) target_compile_definitions(XS PRIVATE -DSLIC3R_DEBUG -DDEBUG -D_DEBUG) else () target_compile_definitions(XS PRIVATE -DNDEBUG) endif () -# Perl specific stuff -find_package(PerlLibs REQUIRED) -set(PerlEmbed_DEBUG 1) -find_package(PerlEmbed REQUIRED) target_include_directories(XS PRIVATE ${PERL_INCLUDE_PATH}) target_compile_options(XS PRIVATE ${PerlEmbed_CCFLAGS}) -# If the Perl is compiled with optimization off, disable optimization over the whole project. -if (WIN32 AND ";${PerlEmbed_CCFLAGS};" MATCHES ";[-/]Od;") - message(STATUS "Perl compiled without optimization. Disabling optimization for the Slic3r build.") - message("Old CMAKE_CXX_FLAGS_RELEASE: ${CMAKE_CXX_FLAGS_RELEASE}") - message("Old CMAKE_CXX_FLAGS_RELWITHDEBINFO: ${CMAKE_CXX_FLAGS_RELEASE}") - message("Old CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS_RELEASE}") - set(CMAKE_CXX_FLAGS_RELEASE "/MD /Od /Zi /EHsc /DNDEBUG /DWIN32 /DTBB_USE_ASSERT") - set(CMAKE_C_FLAGS_RELEASE "/MD /Od /Zi /DNDEBUG /DWIN32 /DTBB_USE_ASSERT") - set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "/MD /Od /Zi /EHsc /DNDEBUG /DWIN32 /DTBB_USE_ASSERT") - set(CMAKE_C_FLAGS_RELWITHDEBINFO "/MD /Od /Zi /DNDEBUG /DWIN32 /DTBB_USE_ASSERT") - set(CMAKE_CXX_FLAGS "/MD /Od /Zi /EHsc /DNDEBUG /DWIN32 /DTBB_USE_ASSERT") - set(CMAKE_C_FLAGS "/MD /Od /Zi /DNDEBUG /DWIN32 /DTBB_USE_ASSERT") -endif() -# The following line will add -fPIC on Linux to make the XS.so rellocable. -add_definitions(${PerlEmbed_CCCDLFLAGS}) + if (WIN32) target_link_libraries(XS ${PERL_LIBRARY}) endif() -add_subdirectory(src/avrdude) - -add_subdirectory(src/qhull) -include_directories(${LIBDIR}/qhull/src) -message(STATUS ${LIBDIR}/qhull/src) - -## REQUIRED packages - # Find and configure boost if(SLIC3R_STATIC) # Use static boost libraries. @@ -635,136 +149,22 @@ if(SLIC3R_STATIC) # Use boost libraries linked statically to the C++ runtime. # set(Boost_USE_STATIC_RUNTIME ON) endif() -#set(Boost_DEBUG ON) -find_package(Boost REQUIRED COMPONENTS system filesystem thread log locale regex) -if(Boost_FOUND) - include_directories(${Boost_INCLUDE_DIRS}) - target_link_libraries(XS ${Boost_LIBRARIES}) - if (APPLE) - # BOOST_ASIO_DISABLE_KQUEUE : prevents a Boost ASIO bug on OS X: https://svn.boost.org/trac/boost/ticket/5339 - add_definitions(-DBOOST_ASIO_DISABLE_KQUEUE) - endif() - if(NOT SLIC3R_STATIC) - add_definitions(-DBOOST_LOG_DYN_LINK) - endif() -endif() -# Find and configure intel-tbb -if(SLIC3R_STATIC) - set(TBB_STATIC 1) -endif() -set(TBB_DEBUG 1) -find_package(TBB REQUIRED) -include_directories(${TBB_INCLUDE_DIRS}) -add_definitions(${TBB_DEFINITIONS}) -if(MSVC) - # Suppress implicit linking of the TBB libraries by the Visual Studio compiler. - add_definitions(-D__TBB_NO_IMPLICIT_LINKAGE) -endif() -# The Intel TBB library will use the std::exception_ptr feature of C++11. -add_definitions(-DTBB_USE_CAPTURED_EXCEPTION=0) +target_link_libraries(XS ${Boost_LIBRARIES}) target_link_libraries(XS ${TBB_LIBRARIES}) - -# Find and configure wxWidgets -if (SLIC3R_PRUSACONTROL) - set(wxWidgets_UseAlienWx 1) - if (wxWidgets_UseAlienWx) - set(AlienWx_DEBUG 1) - find_package(AlienWx REQUIRED COMPONENTS base core adv html gl) - include_directories(${AlienWx_INCLUDE_DIRS}) - #add_compile_options(${AlienWx_CXX_FLAGS}) - add_definitions(${AlienWx_DEFINITIONS}) - set(wxWidgets_LIBRARIES ${AlienWx_LIBRARIES}) - # On Linux / gtk, we need to have a direct access to gtk+ for some workarounds. - if (AlienWx_GUI_TOOLKIT STREQUAL "gtk2") - pkg_check_modules(GTK2 gtk+-2.0) - include_directories(${GTK2_INCLUDE_DIRS}) - endif() - if (AlienWx_GUI_TOOLKIT STREQUAL "gtk3") - pkg_check_modules(GTK3 gtk+-3.0) - include_directories(${GTK3_INCLUDE_DIRS}) - endif() - else () - find_package(wxWidgets REQUIRED COMPONENTS base core adv html gl) - include(${wxWidgets_USE_FILE}) - endif () - add_definitions(-DSLIC3R_GUI -DSLIC3R_PRUS) - target_link_libraries(XS ${wxWidgets_LIBRARIES}) -endif() - -find_package(CURL REQUIRED) -include_directories(${CURL_INCLUDE_DIRS}) -target_link_libraries(XS ${CURL_LIBRARIES}) - -if (SLIC3R_STATIC) - if (NOT APPLE) - # libcurl is always linked dynamically to the system libcurl on OSX. - # On other systems, libcurl is linked statically if SLIC3R_STATIC is set. - add_definitions(-DCURL_STATICLIB) - endif() - if (CMAKE_SYSTEM_NAME STREQUAL "Linux") - # As of now, our build system produces a statically linked libcurl, - # which links the OpenSSL library dynamically. - find_package(OpenSSL REQUIRED) - message("OpenSSL include dir: ${OPENSSL_INCLUDE_DIR}") - message("OpenSSL libraries: ${OPENSSL_LIBRARIES}") - include_directories(${OPENSSL_INCLUDE_DIR}) - target_link_libraries(XS ${OPENSSL_LIBRARIES}) - endif() -endif() - -## OPTIONAL packages - -# Find eigen3 or use bundled version -if (NOT SLIC3R_STATIC) - find_package(Eigen3) -endif () -if (NOT Eigen3_FOUND) - set(Eigen3_FOUND 1) - set(EIGEN3_INCLUDE_DIR ${LIBDIR}/eigen/) -endif () -include_directories(${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 () -if (NOT EXPAT_FOUND) - add_library(expat STATIC - ${LIBDIR}/expat/xmlparse.c - ${LIBDIR}/expat/xmlrole.c - ${LIBDIR}/expat/xmltok.c - ) - set(EXPAT_FOUND 1) - set(EXPAT_INCLUDE_DIRS ${LIBDIR}/expat/) - set(EXPAT_LIBRARIES expat) -endif () -include_directories(${EXPAT_INCLUDE_DIRS}) +# target_link_libraries(XS ${wxWidgets_LIBRARIES}) target_link_libraries(XS ${EXPAT_LIBRARIES}) +# target_link_libraries(XS ${GLEW_LIBRARIES}) -# Find glew or use bundled version -if (NOT SLIC3R_STATIC) - find_package(GLEW) -endif () -if (NOT GLEW_FOUND) - add_library(glew STATIC ${LIBDIR}/glew/src/glew.c) - set(GLEW_FOUND 1) - set(GLEW_INCLUDE_DIRS ${LIBDIR}/glew/include/) - set(GLEW_LIBRARIES glew) - add_definitions(-DGLEW_STATIC) -endif () -include_directories(${GLEW_INCLUDE_DIRS}) -target_link_libraries(XS ${GLEW_LIBRARIES}) # Install the XS.pm and XS.{so,dll,bundle} into the local-lib directory. -set(PERL_LOCAL_LIB_DIR "${PROJECT_SOURCE_DIR}/local-lib/lib/perl5/${PerlEmbed_ARCHNAME}") +set(PERL_LOCAL_LIB_DIR "../local-lib/lib/perl5/${PerlEmbed_ARCHNAME}") add_custom_command( TARGET XS POST_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory "${PERL_LOCAL_LIB_DIR}/auto/Slic3r/XS/" COMMAND ${CMAKE_COMMAND} -E copy "$" "${PERL_LOCAL_LIB_DIR}/auto/Slic3r/XS/" COMMAND ${CMAKE_COMMAND} -E make_directory "${PERL_LOCAL_LIB_DIR}/Slic3r/" - COMMAND ${CMAKE_COMMAND} -E copy "${PROJECT_SOURCE_DIR}/xs/lib/Slic3r/XS.pm" "${PERL_LOCAL_LIB_DIR}/Slic3r/" + COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/lib/Slic3r/XS.pm" "${PERL_LOCAL_LIB_DIR}/Slic3r/" COMMENT "Installing XS.pm and XS.{so,dll,bundle} into the local-lib directory ..." ) if(APPLE) @@ -775,23 +175,11 @@ if(APPLE) ) endif() -# Create a slic3r executable -add_executable(slic3r EXCLUDE_FROM_ALL ${PROJECT_SOURCE_DIR}/src/slic3r.cpp) target_include_directories(XS PRIVATE src src/libslic3r) -target_link_libraries(slic3r libslic3r libslic3r_gui admesh miniz ${Boost_LIBRARIES} clipper ${EXPAT_LIBRARIES} ${GLEW_LIBRARIES} polypartition poly2tri ${TBB_LIBRARIES} ${wxWidgets_LIBRARIES}) - -add_executable(slabasebed EXCLUDE_FROM_ALL ${PROJECT_SOURCE_DIR}/src/slabasebed.cpp) -target_include_directories(slabasebed PRIVATE src src/libslic3r) -target_link_libraries(slabasebed libslic3r libslic3r_gui qhull admesh miniz ${Boost_LIBRARIES} clipper ${EXPAT_LIBRARIES} ${GLEW_LIBRARIES} polypartition poly2tri ${TBB_LIBRARIES} ${wxWidgets_LIBRARIES} ${CMAKE_DL_LIBS}) if(SLIC3R_PROFILE) target_link_libraries(Shiny) endif() -if (APPLE) - target_link_libraries(slic3r "-framework IOKit" "-framework CoreFoundation" -lc++) -elseif (NOT MSVC) - target_link_libraries(slic3r -lstdc++) -endif () if (MSVC) # Here we associate some additional properties with the MSVC project to enable compilation and debugging out of the box. @@ -799,35 +187,10 @@ if (MSVC) string(REPLACE "/" "\\" PROPS_PERL_BIN_PATH "${PROPS_PERL_BIN_PATH}") string(REPLACE "/" "\\" PROPS_PERL_EXECUTABLE "${PERL_EXECUTABLE}") string(REPLACE "/" "\\" PROPS_CMAKE_SOURCE_DIR "${CMAKE_SOURCE_DIR}") - configure_file("${PROJECT_SOURCE_DIR}/cmake/msvc/xs.wperl.props.in" "${CMAKE_BINARY_DIR}/xs.wperl.props" NEWLINE_STYLE CRLF) + configure_file("../cmake/msvc/xs.wperl.props.in" "${CMAKE_BINARY_DIR}/xs.wperl.props" NEWLINE_STYLE CRLF) set_target_properties(XS PROPERTIES VS_USER_PROPS "${CMAKE_BINARY_DIR}/xs.wperl.props") endif() -# l10n -set(L10N_DIR "${PROJECT_SOURCE_DIR}/resources/localization") -add_custom_target(pot - COMMAND xgettext --keyword=L --from-code=UTF-8 --debug - -f "${L10N_DIR}/list.txt" - -o "${L10N_DIR}/Slic3rPE.pot" - WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} - COMMENT "Generate pot file from strings in the source tree" -) - -# ############################################################################## -# Adding libnest2d project for bin packing... -# ############################################################################## - -set(LIBNEST2D_UNITTESTS ON CACHE BOOL "Force generating unittests for libnest2d") - -add_subdirectory(${LIBDIR}/libnest2d) -target_compile_definitions(libslic3r PUBLIC -DUSE_TBB) -target_include_directories(libslic3r PUBLIC BEFORE ${LIBNEST2D_INCLUDES}) -target_include_directories(libslic3r_gui PUBLIC BEFORE ${LIBNEST2D_INCLUDES}) - -message(STATUS "Libnest2D Libraries: ${LIBNEST2D_LIBRARIES}") -target_link_libraries(libslic3r ${LIBNEST2D_LIBRARIES}) -# ############################################################################## - # Installation install(TARGETS XS DESTINATION ${PERL_VENDORARCH}/auto/Slic3r/XS) install(FILES lib/Slic3r/XS.pm DESTINATION ${PERL_VENDORLIB}/Slic3r) diff --git a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch03s01s01.html~ b/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch03s01s01.html~ deleted file mode 100644 index 20b5c4514d..0000000000 --- a/xs/src/avrdude/atmel-docs/EDBG/protocoldocs/ch03s01s01.html~ +++ /dev/null @@ -1,215 +0,0 @@ - - - - -QUERY - - Atmel EDBG-based Tools Protocols \ No newline at end of file diff --git a/xs/src/libnest2d/tools/benchmark.h b/xs/src/libnest2d/tools/benchmark.h deleted file mode 100644 index 19870b37b1..0000000000 --- a/xs/src/libnest2d/tools/benchmark.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) Tamás Mészáros - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -#ifndef INCLUDE_BENCHMARK_H_ -#define INCLUDE_BENCHMARK_H_ - -#include -#include - -/** - * A class for doing benchmarks. - */ -class Benchmark { - typedef std::chrono::high_resolution_clock Clock; - typedef Clock::duration Duration; - typedef Clock::time_point TimePoint; - - TimePoint t1, t2; - Duration d; - - inline double to_sec(Duration d) { - return d.count() * double(Duration::period::num) / Duration::period::den; - } - -public: - - /** - * Measure time from the moment of this call. - */ - void start() { t1 = Clock::now(); } - - /** - * Measure time to the moment of this call. - */ - void stop() { t2 = Clock::now(); } - - /** - * Get the time elapsed between a start() end a stop() call. - * @return Returns the elapsed time in seconds. - */ - double getElapsedSec() { d = t2 - t1; return to_sec(d); } -}; - - -#endif /* INCLUDE_BENCHMARK_H_ */ diff --git a/xs/src/slic3r/GUI/wxPerlIface.cpp b/xs/src/slic3r/GUI/wxPerlIface.cpp deleted file mode 100644 index 216ca4b3b8..0000000000 --- a/xs/src/slic3r/GUI/wxPerlIface.cpp +++ /dev/null @@ -1,97 +0,0 @@ -// Derived from the following: - -///////////////////////////////////////////////////////////////////////////// -// Name: cpp/helpers.cpp -// Purpose: implementation for helpers.h -// Author: Mattia Barbon -// Modified by: -// Created: 29/10/2000 -// RCS-ID: $Id: helpers.cpp 3397 2012-09-30 02:26:07Z mdootson $ -// Copyright: (c) 2000-2011 Mattia Barbon -// Licence: This program is free software; you can redistribute it and/or -// modify it under the same terms as Perl itself -///////////////////////////////////////////////////////////////////////////// - -#ifdef __cplusplus -extern "C" { -#endif -#include "EXTERN.h" -#include "perl.h" -#include "XSUB.h" -#include "ppport.h" -#undef do_open -#undef do_close -#ifdef __cplusplus -} -#endif - -//#include - -// ---------------------------------------------------------------------------- -// Utility functions for working with MAGIC -// ---------------------------------------------------------------------------- - -struct my_magic -{ - my_magic() : object( NULL ), deleteable( true ) { } - - void* object; - bool deleteable; -}; - -//STATIC MGVTBL my_vtbl = { 0, 0, 0, 0, 0, 0, 0, 0 }; - -my_magic* wxPli_get_magic( pTHX_ SV* rv ) -{ - // check for reference - if( !SvROK( rv ) ) - return NULL; - SV* ref = SvRV( rv ); - - // if it isn't a SvPVMG, then it can't have MAGIC - // so it is deleteable - if( !ref || SvTYPE( ref ) < SVt_PVMG ) - return NULL; - - // search for '~' / PERL_MAGIC_ext magic, and check the value -// MAGIC* magic = mg_findext( ref, PERL_MAGIC_ext, &my_vtbl ); - MAGIC* magic = mg_find( ref, '~' ); - if( !magic ) - return NULL; - - return (my_magic*)magic->mg_ptr; -} - -// gets 'this' pointer from a blessed scalar/hash reference -void* wxPli_sv_2_object( pTHX_ SV* scalar, const char* classname ) -{ - // is it correct to use undef as 'NULL'? - if( !SvOK( scalar ) ) - { - return NULL; - } - - if( !SvROK( scalar ) ) - croak( "variable is not an object: it must have type %s", classname ); - - if( !classname || sv_derived_from( scalar, (char*) classname ) ) - { - SV* ref = SvRV( scalar ); - - my_magic* mg = wxPli_get_magic( aTHX_ scalar ); - - // rationale: if this is an hash-ish object, it always - // has both mg and mg->object; if however this is a - // scalar-ish object that has been marked/unmarked deletable - // it has mg, but not mg->object - if( !mg || !mg->object ) - return INT2PTR( void*, SvOK( ref ) ? SvIV( ref ) : 0 ); - - return mg->object; - } - else - { - croak( "variable is not of type %s", classname ); - return NULL; // dummy, for compiler - } -} From 6bd92a819805946e97b614df4f1e9e4d7a9142e9 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Wed, 19 Sep 2018 11:27:04 +0200 Subject: [PATCH 002/186] Disabling calls from libslic3r to slic3r gui. --- CMakeLists.txt | 5 +++++ src/libslic3r/Format/3mf.cpp | 3 ++- src/libslic3r/Format/AMF.cpp | 3 ++- src/slic3r/GUI/GLToolbar.hpp | 2 +- src/slic3r/GUI/GUI.hpp | 2 +- 5 files changed, 11 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1e1817f542..80aa7ff083 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -95,6 +95,11 @@ if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUXX) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fext-numeric-literals" ) endif() +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + # On GCC and Clang, no return from a non-void function is a warning only. Here, we make it an error. + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror=return-type" ) +endif() + # Where all the bundled libraries reside? set(LIBDIR ${CMAKE_CURRENT_SOURCE_DIR}/src/) # For the bundled boost libraries (boost::nowide) diff --git a/src/libslic3r/Format/3mf.cpp b/src/libslic3r/Format/3mf.cpp index 43c99f19fd..c9b4989f56 100644 --- a/src/libslic3r/Format/3mf.cpp +++ b/src/libslic3r/Format/3mf.cpp @@ -667,7 +667,8 @@ namespace Slic3r { add_error("Error while reading config data to buffer"); return; } - bundle.load_config_string(buffer.data(), archive_filename.c_str()); +//FIXME Get rid of the dependencies on slic3r GUI library! +// bundle.load_config_string(buffer.data(), archive_filename.c_str()); } } diff --git a/src/libslic3r/Format/AMF.cpp b/src/libslic3r/Format/AMF.cpp index 458ce79de7..89a0eacbe6 100644 --- a/src/libslic3r/Format/AMF.cpp +++ b/src/libslic3r/Format/AMF.cpp @@ -467,7 +467,8 @@ void AMFParserContext::endElement(const char * /* name */) case NODE_TYPE_METADATA: if ((m_preset_bundle != nullptr) && strncmp(m_value[0].c_str(), SLIC3R_CONFIG_TYPE, strlen(SLIC3R_CONFIG_TYPE)) == 0) { - m_preset_bundle->load_config_string(m_value[1].c_str(), m_archive_filename.c_str()); +//FIXME Get rid of the dependencies on slic3r GUI library! +// m_preset_bundle->load_config_string(m_value[1].c_str(), m_archive_filename.c_str()); } else if (strncmp(m_value[0].c_str(), "slic3r.", 7) == 0) { const char *opt_key = m_value[0].c_str() + 7; diff --git a/src/slic3r/GUI/GLToolbar.hpp b/src/slic3r/GUI/GLToolbar.hpp index 65d6748ffe..c67e78f58c 100644 --- a/src/slic3r/GUI/GLToolbar.hpp +++ b/src/slic3r/GUI/GLToolbar.hpp @@ -2,7 +2,7 @@ #define slic3r_GLToolbar_hpp_ #include "../../slic3r/GUI/GLTexture.hpp" -#include "../../callback.hpp" +#include "callback.hpp" #include #include diff --git a/src/slic3r/GUI/GUI.hpp b/src/slic3r/GUI/GUI.hpp index 8dfaf42c66..9539cd7cc3 100644 --- a/src/slic3r/GUI/GUI.hpp +++ b/src/slic3r/GUI/GUI.hpp @@ -4,7 +4,7 @@ #include #include #include "PrintConfig.hpp" -#include "../../callback.hpp" +#include "callback.hpp" #include "GUI_ObjectParts.hpp" #include From 7374eafc13aed19757bc5c982ea172f89a91bf8e Mon Sep 17 00:00:00 2001 From: bubnikv Date: Wed, 19 Sep 2018 11:34:26 +0200 Subject: [PATCH 003/186] Moved the newly added GUI_Preview files. --- {xs/src => src}/slic3r/GUI/GUI_Preview.cpp | 0 {xs/src => src}/slic3r/GUI/GUI_Preview.hpp | 0 {xs/src => src}/slic3r/GUI/GUI_PreviewIface.cpp | 0 {xs/src => src}/slic3r/GUI/GUI_PreviewIface.hpp | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename {xs/src => src}/slic3r/GUI/GUI_Preview.cpp (100%) rename {xs/src => src}/slic3r/GUI/GUI_Preview.hpp (100%) rename {xs/src => src}/slic3r/GUI/GUI_PreviewIface.cpp (100%) rename {xs/src => src}/slic3r/GUI/GUI_PreviewIface.hpp (100%) diff --git a/xs/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp similarity index 100% rename from xs/src/slic3r/GUI/GUI_Preview.cpp rename to src/slic3r/GUI/GUI_Preview.cpp diff --git a/xs/src/slic3r/GUI/GUI_Preview.hpp b/src/slic3r/GUI/GUI_Preview.hpp similarity index 100% rename from xs/src/slic3r/GUI/GUI_Preview.hpp rename to src/slic3r/GUI/GUI_Preview.hpp diff --git a/xs/src/slic3r/GUI/GUI_PreviewIface.cpp b/src/slic3r/GUI/GUI_PreviewIface.cpp similarity index 100% rename from xs/src/slic3r/GUI/GUI_PreviewIface.cpp rename to src/slic3r/GUI/GUI_PreviewIface.cpp diff --git a/xs/src/slic3r/GUI/GUI_PreviewIface.hpp b/src/slic3r/GUI/GUI_PreviewIface.hpp similarity index 100% rename from xs/src/slic3r/GUI/GUI_PreviewIface.hpp rename to src/slic3r/GUI/GUI_PreviewIface.hpp From 7ef894e074441f7998909cc9b557c4868a1016f9 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Wed, 19 Sep 2018 11:46:24 +0200 Subject: [PATCH 004/186] Fixed GUI CMakeFile --- src/slic3r/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt index e4dfd35ea5..4a0c316364 100644 --- a/src/slic3r/CMakeLists.txt +++ b/src/slic3r/CMakeLists.txt @@ -35,6 +35,10 @@ add_library(libslic3r_gui STATIC ${LIBDIR}/slic3r/GUI/GUI.hpp ${LIBDIR}/slic3r/GUI/GUI_ObjectParts.cpp ${LIBDIR}/slic3r/GUI/GUI_ObjectParts.hpp + ${LIBDIR}/slic3r/GUI/GUI_Preview.cpp + ${LIBDIR}/slic3r/GUI/GUI_Preview.hpp + ${LIBDIR}/slic3r/GUI/GUI_PreviewIface.cpp + ${LIBDIR}/slic3r/GUI/GUI_PreviewIface.hpp ${LIBDIR}/slic3r/GUI/LambdaObjectDialog.cpp ${LIBDIR}/slic3r/GUI/LambdaObjectDialog.hpp ${LIBDIR}/slic3r/GUI/Tab.cpp From 58a0c41713a43641143fac157219966d3f38c4c8 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Wed, 19 Sep 2018 13:12:57 +0200 Subject: [PATCH 005/186] Fixed compilation on OSX & Linux --- CMakeLists.txt | 4 ---- src/CMakeLists.txt | 9 +++++++-- xs/CMakeLists.txt | 6 ++---- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 80aa7ff083..84f6bcbd5d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -287,9 +287,5 @@ endif () add_test (NAME xs COMMAND "${PERL_EXECUTABLE}" ${PERL_PROVE} -I ${PROJECT_SOURCE_DIR}/local-lib/lib/perl5 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/xs) add_test (NAME integration COMMAND "${PERL_EXECUTABLE}" ${PERL_PROVE} WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}) -#install(PROGRAMS slic3r.pl DESTINATION bin RENAME slic3r-prusa3d) - file(GLOB MyVar var/*.png) install(FILES ${MyVar} DESTINATION share/slic3r-prusa3d) -install(FILES lib/Slic3r.pm DESTINATION lib/slic3r-prusa3d) -install(DIRECTORY lib/Slic3r DESTINATION lib/slic3r-prusa3d) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d0c0082937..7d184c59fe 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -36,11 +36,9 @@ else() add_subdirectory(png/zlib) set(ZLIB_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/png/zlib ${CMAKE_CURRENT_BINARY_DIR}/png/zlib) include_directories(${ZLIB_INCLUDE_DIR}) - message(STATUS "ZLIB_INCLUDE_DIR ${ZLIB_INCLUDE_DIR}") add_subdirectory(png/libpng) set_target_properties(zlibstatic PROPERTIES POSITION_INDEPENDENT_CODE ON) set_target_properties(png_static PROPERTIES POSITION_INDEPENDENT_CODE ON) -# target_include_directories(png_static PRIVATE ${ZLIB_INCLUDE_DIR}) set(PNG_LIBRARIES png_static zlibstatic) set(PNG_INCLUDE_DIRS ${ZLIB_INCLUDE_DIR} ${PROJECT_SOURCE_DIR}/png/libpng ${CMAKE_CURRENT_BINARY_DIR}/png/libpng) endif() @@ -51,6 +49,13 @@ add_subdirectory(slic3r) # Create a slic3r executable add_executable(slic3r slic3r.cpp) target_link_libraries(slic3r libslic3r libslic3r_gui ${wxWidgets_LIBRARIES} ${CURL_LIBRARIES}) +if (APPLE) +# add_compile_options(-stdlib=libc++) +# add_definitions(-DBOOST_THREAD_DONT_USE_CHRONO -DBOOST_NO_CXX11_RVALUE_REFERENCES -DBOOST_THREAD_USES_MOVE) + target_link_libraries(XS "-framework IOKit" "-framework CoreFoundation" -lc++) +elseif (NOT MSVC) + target_link_libraries(XS -lstdc++) +endif () # Add the OpenGL and GLU libraries. if (SLIC3R_GUI) if (MSVC) diff --git a/xs/CMakeLists.txt b/xs/CMakeLists.txt index 92964c900a..8756d98ebd 100644 --- a/xs/CMakeLists.txt +++ b/xs/CMakeLists.txt @@ -97,7 +97,7 @@ if(SLIC3R_PROFILE) target_link_libraries(XS Shiny) endif() -target_include_directories(XS PRIVATE src src/libslic3r) # Local include directories +target_include_directories(XS PRIVATE src) target_compile_definitions(XS PRIVATE -DSLIC3RXS) set_target_properties(XS PROPERTIES PREFIX "") # Prevent cmake from generating libXS.so instead of XS.so @@ -157,7 +157,7 @@ target_link_libraries(XS ${EXPAT_LIBRARIES}) # target_link_libraries(XS ${GLEW_LIBRARIES}) # Install the XS.pm and XS.{so,dll,bundle} into the local-lib directory. -set(PERL_LOCAL_LIB_DIR "../local-lib/lib/perl5/${PerlEmbed_ARCHNAME}") +set(PERL_LOCAL_LIB_DIR "../../local-lib/lib/perl5/${PerlEmbed_ARCHNAME}") add_custom_command( TARGET XS POST_BUILD @@ -175,8 +175,6 @@ if(APPLE) ) endif() -target_include_directories(XS PRIVATE src src/libslic3r) - if(SLIC3R_PROFILE) target_link_libraries(Shiny) endif() From 681e9f03b31d9f31ef3724953dbf6b87b8b33346 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Wed, 19 Sep 2018 13:16:20 +0200 Subject: [PATCH 006/186] Yet another fix of build process --- src/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7d184c59fe..d7eb474472 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -52,9 +52,9 @@ target_link_libraries(slic3r libslic3r libslic3r_gui ${wxWidgets_LIBRARIES} ${CU if (APPLE) # add_compile_options(-stdlib=libc++) # add_definitions(-DBOOST_THREAD_DONT_USE_CHRONO -DBOOST_NO_CXX11_RVALUE_REFERENCES -DBOOST_THREAD_USES_MOVE) - target_link_libraries(XS "-framework IOKit" "-framework CoreFoundation" -lc++) + target_link_libraries(slic3r "-framework IOKit" "-framework CoreFoundation" -lc++) elseif (NOT MSVC) - target_link_libraries(XS -lstdc++) + target_link_libraries(slic3r -lstdc++) endif () # Add the OpenGL and GLU libraries. if (SLIC3R_GUI) From 8f01266ca4bfb78bd40425d80e8526d0a1a7c478 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Wed, 19 Sep 2018 14:22:48 +0200 Subject: [PATCH 007/186] Fix of compilation on Linux & OSX: Cannot create a "slic3r" executable next to a "slic3r" directory. --- src/CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d7eb474472..f3a4fe1e15 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -48,6 +48,11 @@ add_subdirectory(slic3r) # Create a slic3r executable add_executable(slic3r slic3r.cpp) +if(SLIC3R_GUI) + set_target_properties(slic3r PROPERTIES OUTPUT_NAME "slic3r-gui") +else() + set_target_properties(slic3r PROPERTIES OUTPUT_NAME "slic3r-console") +endif() target_link_libraries(slic3r libslic3r libslic3r_gui ${wxWidgets_LIBRARIES} ${CURL_LIBRARIES}) if (APPLE) # add_compile_options(-stdlib=libc++) From ffac360439fe9942831c6d0556dfdef31b60ac62 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Wed, 19 Sep 2018 14:43:38 +0200 Subject: [PATCH 008/186] Yet another build system fix --- src/CMakeLists.txt | 2 +- xs/CMakeLists.txt | 11 ++--------- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f3a4fe1e15..f133e2532b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -70,6 +70,6 @@ if (SLIC3R_GUI) elseif (APPLE) target_link_libraries(slic3r "-framework OpenGL") else () - target_link_libraries(slic3r -lGL -lGLU) + target_link_libraries(slic3r -ldl -lGL -lGLU) endif () endif () diff --git a/xs/CMakeLists.txt b/xs/CMakeLists.txt index 8756d98ebd..3f37213ae5 100644 --- a/xs/CMakeLists.txt +++ b/xs/CMakeLists.txt @@ -109,7 +109,8 @@ target_link_libraries(XS ${Boost_LIBRARIES}) if (APPLE) # add_compile_options(-stdlib=libc++) # add_definitions(-DBOOST_THREAD_DONT_USE_CHRONO -DBOOST_NO_CXX11_RVALUE_REFERENCES -DBOOST_THREAD_USES_MOVE) - target_link_libraries(XS "-framework IOKit" "-framework CoreFoundation" -lc++) + # -liconv: boost links to libiconv by default + target_link_libraries(XS "-liconv -framework IOKit" "-framework CoreFoundation" -lc++) elseif (MSVC) target_link_libraries(XS ) else () @@ -142,14 +143,6 @@ if (WIN32) target_link_libraries(XS ${PERL_LIBRARY}) endif() -# Find and configure boost -if(SLIC3R_STATIC) - # Use static boost libraries. - set(Boost_USE_STATIC_LIBS ON) - # Use boost libraries linked statically to the C++ runtime. - # set(Boost_USE_STATIC_RUNTIME ON) -endif() - target_link_libraries(XS ${Boost_LIBRARIES}) target_link_libraries(XS ${TBB_LIBRARIES}) # target_link_libraries(XS ${wxWidgets_LIBRARIES}) From cc3572f3cee83937235fc54180d06fa258207dc2 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Wed, 19 Sep 2018 15:47:32 +0200 Subject: [PATCH 009/186] Another step to fix the build system. --- src/CMakeLists.txt | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f133e2532b..ea3d350180 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -19,7 +19,6 @@ add_subdirectory(libnest2d) include_directories(${LIBDIR}/qhull/src) #message(STATUS ${LIBDIR}/qhull/src) - # ############################################################################## # Configure rasterizer target # ############################################################################## @@ -53,16 +52,41 @@ if(SLIC3R_GUI) else() set_target_properties(slic3r PROPERTIES OUTPUT_NAME "slic3r-console") endif() -target_link_libraries(slic3r libslic3r libslic3r_gui ${wxWidgets_LIBRARIES} ${CURL_LIBRARIES}) +target_link_libraries(slic3r libslic3r) if (APPLE) # add_compile_options(-stdlib=libc++) # add_definitions(-DBOOST_THREAD_DONT_USE_CHRONO -DBOOST_NO_CXX11_RVALUE_REFERENCES -DBOOST_THREAD_USES_MOVE) - target_link_libraries(slic3r "-framework IOKit" "-framework CoreFoundation" -lc++) + # -liconv: boost links to libiconv by default + target_link_libraries(slic3r "-liconv -framework IOKit" "-framework CoreFoundation" -lc++) elseif (NOT MSVC) - target_link_libraries(slic3r -lstdc++) + target_link_libraries(slic3r -ldl -lstdc++) endif () -# Add the OpenGL and GLU libraries. + +# Add the Slic3r GUI library, libcurl, OpenGL and GLU libraries. if (SLIC3R_GUI) + target_link_libraries(slic3r libslic3r_gui ${wxWidgets_LIBRARIES} ${CURL_LIBRARIES}) + + # Configure libcurl & OpenSSL + find_package(CURL REQUIRED) + target_include_directories(slic3r PRIVATE ${CURL_INCLUDE_DIRS}) + target_link_libraries(slic3r ${CURL_LIBRARIES}) + if (SLIC3R_STATIC) + if (NOT APPLE) + # libcurl is always linked dynamically to the system libcurl on OSX. + # On other systems, libcurl is linked statically if SLIC3R_STATIC is set. + target_compile_definitions(slic3r PRIVATE CURL_STATICLIB) + endif() + if (CMAKE_SYSTEM_NAME STREQUAL "Linux") + # As of now, our build system produces a statically linked libcurl, + # which links the OpenSSL library dynamically. + find_package(OpenSSL REQUIRED) + message("OpenSSL include dir: ${OPENSSL_INCLUDE_DIR}") + message("OpenSSL libraries: ${OPENSSL_LIBRARIES}") + target_include_directories(slic3r PRIVATE ${OPENSSL_INCLUDE_DIR}) + target_link_libraries(slic3r ${OPENSSL_LIBRARIES}) + endif() + endif() + if (MSVC) target_link_libraries(slic3r user32.lib Setupapi.lib OpenGL32.Lib GlU32.Lib) elseif (MINGW) From 6003005812ec68eab3b321107f7a6c1d4dbae935 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Wed, 19 Sep 2018 17:19:06 +0200 Subject: [PATCH 010/186] Removed dependency on wxWidgets from Alien. Updated source code to wxWidgets 3.1.1 Moved invocation of perl unit / integration tests to the xs project. --- CMakeLists.txt | 44 ++---------------------------- src/CMakeLists.txt | 3 ++ src/slic3r/GUI/GUI_ObjectParts.cpp | 2 +- src/slic3r/GUI/Tab.cpp | 4 +-- src/slic3r/GUI/wxExtensions.hpp | 1 + xs/CMakeLists.txt | 16 +++++++++++ 6 files changed, 25 insertions(+), 45 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 84f6bcbd5d..65a1240556 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -175,33 +175,6 @@ endif() # The Intel TBB library will use the std::exception_ptr feature of C++11. add_definitions(-DTBB_USE_CAPTURED_EXCEPTION=0) -# Find and configure wxWidgets -if (SLIC3R_PRUSACONTROL) - set(wxWidgets_UseAlienWx 1) - if (wxWidgets_UseAlienWx) - set(AlienWx_DEBUG 1) - find_package(AlienWx REQUIRED COMPONENTS base core adv html gl) - include_directories(${AlienWx_INCLUDE_DIRS}) - #add_compile_options(${AlienWx_CXX_FLAGS}) - add_definitions(${AlienWx_DEFINITIONS}) - set(wxWidgets_LIBRARIES ${AlienWx_LIBRARIES}) - # On Linux / gtk, we need to have a direct access to gtk+ for some workarounds. - if (AlienWx_GUI_TOOLKIT STREQUAL "gtk2") - pkg_check_modules(GTK2 gtk+-2.0) - include_directories(${GTK2_INCLUDE_DIRS}) - endif() - if (AlienWx_GUI_TOOLKIT STREQUAL "gtk3") - pkg_check_modules(GTK3 gtk+-3.0) - include_directories(${GTK3_INCLUDE_DIRS}) - endif() - else () - find_package(wxWidgets REQUIRED COMPONENTS base core adv html gl) - include(${wxWidgets_USE_FILE}) - endif () -#FIXME rewrite the PRUS format to miniz! -# add_definitions(-DSLIC3R_GUI -DSLIC3R_PRUS) -endif() - find_package(CURL REQUIRED) include_directories(${CURL_INCLUDE_DIRS}) @@ -270,22 +243,9 @@ add_subdirectory(resources/localization) add_subdirectory(src) # Perl bindings, currently only used for the unit / integration tests of libslic3r. +# Also runs the unit / integration tests. +#FIXME Port the tests into C++ to finally get rid of the Perl! add_subdirectory(xs) -get_filename_component(PERL_BIN_PATH "${PERL_EXECUTABLE}" DIRECTORY) -if (MSVC) - # By default the startup project in MSVC is the 'ALL_BUILD' cmake-created project, - # but we want 'slic3r' as the startup one because debugging run command is associated with it. - # (Unfortunatelly it cannot be associated with ALL_BUILD using CMake.) - # Note: For some reason this needs to be set in the top-level CMakeLists.txt - set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT XS) - set(PERL_PROVE "${PERL_BIN_PATH}/prove.bat") -else () - set(PERL_PROVE "${PERL_BIN_PATH}/prove") -endif () - -add_test (NAME xs COMMAND "${PERL_EXECUTABLE}" ${PERL_PROVE} -I ${PROJECT_SOURCE_DIR}/local-lib/lib/perl5 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/xs) -add_test (NAME integration COMMAND "${PERL_EXECUTABLE}" ${PERL_PROVE} WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}) - file(GLOB MyVar var/*.png) install(FILES ${MyVar} DESTINATION share/slic3r-prusa3d) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ea3d350180..d2b79ae788 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -64,6 +64,9 @@ endif () # Add the Slic3r GUI library, libcurl, OpenGL and GLU libraries. if (SLIC3R_GUI) + find_package(wxWidgets REQUIRED COMPONENTS base core adv html gl) + include(${wxWidgets_USE_FILE}) + target_link_libraries(slic3r libslic3r_gui ${wxWidgets_LIBRARIES} ${CURL_LIBRARIES}) # Configure libcurl & OpenSSL diff --git a/src/slic3r/GUI/GUI_ObjectParts.cpp b/src/slic3r/GUI/GUI_ObjectParts.cpp index ae34359ce9..4fc3b88c0f 100644 --- a/src/slic3r/GUI/GUI_ObjectParts.cpp +++ b/src/slic3r/GUI/GUI_ObjectParts.cpp @@ -1008,7 +1008,7 @@ void get_settings_choice(wxMenu *menu, int id, bool is_part) if (!settings_list) return; - if (wxGetMultipleChoices(selections, _(L("Select showing settings")), category_name, names) ==0 ) + if (wxGetSelectedChoices(selections, _(L("Select showing settings")), category_name, names) == -1) return; std::vector selected_options; diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index e0db63803d..5b438d4a19 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -2645,7 +2645,7 @@ void Tab::update_presetsctrl(wxDataViewTreeCtrl* ui, bool show_incompatible) wxDataViewTreeStoreContainerNode *node = ui->GetStore()->FindContainerNode(root_sys); if (node) { - wxDataViewTreeStoreNodeList::iterator iter; + wxDataViewTreeStoreNodes::iterator iter; for (iter = node->GetChildren().begin(); iter != node->GetChildren().end(); iter++) { wxDataViewTreeStoreNode* child = *iter; @@ -2731,7 +2731,7 @@ void Tab::update_tab_presets(wxComboCtrl* ui, bool show_incompatible) wxDataViewTreeStoreContainerNode *node = popup->GetStore()->FindContainerNode(root_sys); if (node) { - wxDataViewTreeStoreNodeList::iterator iter; + wxDataViewTreeStoreNodes::iterator iter; for (iter = node->GetChildren().begin(); iter != node->GetChildren().end(); iter++) { wxDataViewTreeStoreNode* child = *iter; diff --git a/src/slic3r/GUI/wxExtensions.hpp b/src/slic3r/GUI/wxExtensions.hpp index 51c02035c0..a6cbf1773b 100644 --- a/src/slic3r/GUI/wxExtensions.hpp +++ b/src/slic3r/GUI/wxExtensions.hpp @@ -111,6 +111,7 @@ class PrusaCollapsiblePaneMSW : public PrusaCollapsiblePane//wxCollapsiblePane wxButton* m_pDisclosureTriangleButton = nullptr; wxBitmap m_bmp_close; wxBitmap m_bmp_open; + wxString m_strLabel; public: PrusaCollapsiblePaneMSW() {} PrusaCollapsiblePaneMSW( wxWindow *parent, diff --git a/xs/CMakeLists.txt b/xs/CMakeLists.txt index 3f37213ae5..b3bda1877f 100644 --- a/xs/CMakeLists.txt +++ b/xs/CMakeLists.txt @@ -185,3 +185,19 @@ endif() # Installation install(TARGETS XS DESTINATION ${PERL_VENDORARCH}/auto/Slic3r/XS) install(FILES lib/Slic3r/XS.pm DESTINATION ${PERL_VENDORLIB}/Slic3r) + +# Unit / integration tests +enable_testing() +get_filename_component(PERL_BIN_PATH "${PERL_EXECUTABLE}" DIRECTORY) +if (MSVC) + # By default the startup project in MSVC is the 'ALL_BUILD' cmake-created project, + # but we want 'slic3r' as the startup one because debugging run command is associated with it. + # (Unfortunatelly it cannot be associated with ALL_BUILD using CMake.) + # Note: For some reason this needs to be set in the top-level CMakeLists.txt + set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT XS) + set(PERL_PROVE "${PERL_BIN_PATH}/prove.bat") +else () + set(PERL_PROVE "${PERL_BIN_PATH}/prove") +endif () +add_test (NAME xs COMMAND "${PERL_EXECUTABLE}" ${PERL_PROVE} -I ${PROJECT_SOURCE_DIR}/local-lib/lib/perl5 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}) +add_test (NAME integration COMMAND "${PERL_EXECUTABLE}" ${PERL_PROVE} WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/..) From d7f1c8670f6a26792008baaeaf638bf051f963ab Mon Sep 17 00:00:00 2001 From: bubnikv Date: Wed, 19 Sep 2018 17:55:17 +0200 Subject: [PATCH 011/186] Removed wrong dependency on wxWidgets from libslic3r. Added cmake message for WXWIN environment variable. --- src/CMakeLists.txt | 1 + src/libslic3r/GCode/PreviewData.cpp | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d2b79ae788..cf37a82c91 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -64,6 +64,7 @@ endif () # Add the Slic3r GUI library, libcurl, OpenGL and GLU libraries. if (SLIC3R_GUI) + message(STATUS "WXWIN environment set to: $ENV{WXWIN}") find_package(wxWidgets REQUIRED COMPONENTS base core adv html gl) include(${wxWidgets_USE_FILE}) diff --git a/src/libslic3r/GCode/PreviewData.cpp b/src/libslic3r/GCode/PreviewData.cpp index 9cf9716e0a..564fc34dce 100644 --- a/src/libslic3r/GCode/PreviewData.cpp +++ b/src/libslic3r/GCode/PreviewData.cpp @@ -1,7 +1,6 @@ #include "Analyzer.hpp" #include "PreviewData.hpp" #include -#include #include #include From ad54266395a46cb226637cbd8deb3a68ebfaf539 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Wed, 19 Sep 2018 18:05:58 +0200 Subject: [PATCH 012/186] Fixed GUI build --- src/CMakeLists.txt | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cf37a82c91..fcf7c17dcc 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -43,6 +43,13 @@ else() endif() add_subdirectory(libslic3r) + +if (SLIC3R_GUI) + message(STATUS "WXWIN environment set to: $ENV{WXWIN}") + find_package(wxWidgets REQUIRED COMPONENTS base core adv html gl) + include(${wxWidgets_USE_FILE}) +endif() + add_subdirectory(slic3r) # Create a slic3r executable @@ -64,10 +71,6 @@ endif () # Add the Slic3r GUI library, libcurl, OpenGL and GLU libraries. if (SLIC3R_GUI) - message(STATUS "WXWIN environment set to: $ENV{WXWIN}") - find_package(wxWidgets REQUIRED COMPONENTS base core adv html gl) - include(${wxWidgets_USE_FILE}) - target_link_libraries(slic3r libslic3r_gui ${wxWidgets_LIBRARIES} ${CURL_LIBRARIES}) # Configure libcurl & OpenSSL From 9c085dfcc5f854c90246a3300c96f8e42ee89364 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Wed, 19 Sep 2018 18:31:41 +0200 Subject: [PATCH 013/186] Fixed Perl unit tests. --- xs/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xs/CMakeLists.txt b/xs/CMakeLists.txt index b3bda1877f..f3afca619b 100644 --- a/xs/CMakeLists.txt +++ b/xs/CMakeLists.txt @@ -199,5 +199,5 @@ if (MSVC) else () set(PERL_PROVE "${PERL_BIN_PATH}/prove") endif () -add_test (NAME xs COMMAND "${PERL_EXECUTABLE}" ${PERL_PROVE} -I ${PROJECT_SOURCE_DIR}/local-lib/lib/perl5 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}) +add_test (NAME xs COMMAND "${PERL_EXECUTABLE}" ${PERL_PROVE} -I ${PROJECT_SOURCE_DIR}/../local-lib/lib/perl5 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}) add_test (NAME integration COMMAND "${PERL_EXECUTABLE}" ${PERL_PROVE} WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/..) From 6ca5a18d05761e6e60fd9ef31e1e701a62d1c88e Mon Sep 17 00:00:00 2001 From: bubnikv Date: Wed, 19 Sep 2018 18:54:23 +0200 Subject: [PATCH 014/186] Commented out wxPixelData.UseAlpha(), as it is missing from wxWidgets 3.1.1. --- src/slic3r/GUI/BitmapCache.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/BitmapCache.cpp b/src/slic3r/GUI/BitmapCache.cpp index 93853458e4..16baa1629e 100644 --- a/src/slic3r/GUI/BitmapCache.cpp +++ b/src/slic3r/GUI/BitmapCache.cpp @@ -97,7 +97,9 @@ wxBitmap* BitmapCache::insert(const std::string &bitmap_key, const wxBitmap *beg if (bmp->GetWidth() > 0) { if (bmp->GetDepth() == 32) { wxAlphaPixelData data(*const_cast(bmp)); - data.UseAlpha(); + //FIXME The following method is missing from wxWidgets 3.1.1. + // It looks like the wxWidgets 3.0.3 called the wrapped bitmap's UseAlpha(). + //data.UseAlpha(); if (data) { for (int r = 0; r < bmp->GetHeight(); ++ r) { wxAlphaPixelData::Iterator src(data); From ebb6f47f501c83cf7720430f45ff7851e285af39 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Thu, 20 Sep 2018 08:40:22 +0200 Subject: [PATCH 015/186] Added GUI_App and MainFrame --- src/slic3r.cpp | 8 +- src/slic3r/CMakeLists.txt | 4 + src/slic3r/GUI/BedShapeDialog.cpp | 6 - src/slic3r/GUI/GUI.cpp | 10 +- src/slic3r/GUI/GUI.hpp | 33 +- src/slic3r/GUI/GUI_App.cpp | 350 ++++++++++++++ src/slic3r/GUI/GUI_App.hpp | 77 +++ src/slic3r/GUI/MainFrame.cpp | 757 ++++++++++++++++++++++++++++++ src/slic3r/GUI/MainFrame.hpp | 101 ++++ 9 files changed, 1314 insertions(+), 32 deletions(-) create mode 100644 src/slic3r/GUI/GUI_App.cpp create mode 100644 src/slic3r/GUI/GUI_App.hpp create mode 100644 src/slic3r/GUI/MainFrame.cpp create mode 100644 src/slic3r/GUI/MainFrame.hpp diff --git a/src/slic3r.cpp b/src/slic3r.cpp index 8174ba0a2b..bd071ee369 100644 --- a/src/slic3r.cpp +++ b/src/slic3r.cpp @@ -13,6 +13,7 @@ #include #include "slic3r/GUI/GUI.hpp" +#include "slic3r/GUI/GUI_App.hpp" using namespace Slic3r; @@ -252,9 +253,12 @@ main(int argc, char **argv) #endif - MyApp *gui = new MyApp(); +// MyApp *gui = new MyApp(); + GUI::GUI_App *gui = new GUI::GUI_App(); + +// MyApp::SetInstance(gui); + GUI::GUI_App::SetInstance(gui); - MyApp::SetInstance(gui); wxEntry(argc, argv); return 0; } diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt index 4a0c316364..a8888701c3 100644 --- a/src/slic3r/CMakeLists.txt +++ b/src/slic3r/CMakeLists.txt @@ -39,6 +39,10 @@ add_library(libslic3r_gui STATIC ${LIBDIR}/slic3r/GUI/GUI_Preview.hpp ${LIBDIR}/slic3r/GUI/GUI_PreviewIface.cpp ${LIBDIR}/slic3r/GUI/GUI_PreviewIface.hpp + ${LIBDIR}/slic3r/GUI/GUI_App.cpp + ${LIBDIR}/slic3r/GUI/GUI_App.hpp + ${LIBDIR}/slic3r/GUI/MainFrame.cpp + ${LIBDIR}/slic3r/GUI/MainFrame.hpp ${LIBDIR}/slic3r/GUI/LambdaObjectDialog.cpp ${LIBDIR}/slic3r/GUI/LambdaObjectDialog.hpp ${LIBDIR}/slic3r/GUI/Tab.cpp diff --git a/src/slic3r/GUI/BedShapeDialog.cpp b/src/slic3r/GUI/BedShapeDialog.cpp index e04f2b3700..7c019599af 100644 --- a/src/slic3r/GUI/BedShapeDialog.cpp +++ b/src/slic3r/GUI/BedShapeDialog.cpp @@ -291,12 +291,6 @@ void BedShapePanel::update_shape() // Loads an stl file, projects it to the XY plane and calculates a polygon. void BedShapePanel::load_stl() { - t_file_wild_card vec_FILE_WILDCARDS = get_file_wild_card(); - std::vector file_types = { "known", "stl", "obj", "amf", "3mf", "prusa" }; - wxString MODEL_WILDCARD; - for (auto file_type: file_types) - MODEL_WILDCARD += vec_FILE_WILDCARDS.at(file_type) + "|"; - auto dialog = new wxFileDialog(this, _(L("Choose a file to import bed shape from (STL/OBJ/AMF/3MF/PRUSA):")), "", "", MODEL_WILDCARD, wxFD_OPEN | wxFD_FILE_MUST_EXIST); if (dialog->ShowModal() != wxID_OK) { diff --git a/src/slic3r/GUI/GUI.cpp b/src/slic3r/GUI/GUI.cpp index e5ed917b35..4201e33f74 100644 --- a/src/slic3r/GUI/GUI.cpp +++ b/src/slic3r/GUI/GUI.cpp @@ -545,14 +545,8 @@ void add_menus(wxMenuBar *menu, int event_preferences_changed, int event_languag } void open_model(wxWindow *parent, wxArrayString& input_files){ - t_file_wild_card vec_FILE_WILDCARDS = get_file_wild_card(); - std::vector file_types = { "known", "stl", "obj", "amf", "3mf", "prusa" }; - wxString MODEL_WILDCARD; - for (auto file_type : file_types) - MODEL_WILDCARD += vec_FILE_WILDCARDS.at(file_type) + "|"; - - auto dlg_title = _(L("Choose one or more files (STL/OBJ/AMF/3MF/PRUSA):")); - auto dialog = new wxFileDialog(parent /*? parent : GetTopWindow(g_wxMainFrame)*/, dlg_title, + auto dialog = new wxFileDialog(parent ? parent : GetTopWindow(), + _(L("Choose one or more files (STL/OBJ/AMF/3MF/PRUSA):")), g_AppConfig->get_last_dir(), "", MODEL_WILDCARD, wxFD_OPEN | wxFD_MULTIPLE | wxFD_FILE_MUST_EXIST); if (dialog->ShowModal() != wxID_OK) { diff --git a/src/slic3r/GUI/GUI.hpp b/src/slic3r/GUI/GUI.hpp index 9b2fce5b4d..878689bf30 100644 --- a/src/slic3r/GUI/GUI.hpp +++ b/src/slic3r/GUI/GUI.hpp @@ -71,23 +71,24 @@ namespace GUI { class Tab; class ConfigOptionsGroup; // Map from an file_type name to full file wildcard name. -typedef std::map t_file_wild_card; -inline t_file_wild_card& get_file_wild_card() { - static t_file_wild_card FILE_WILDCARDS; - if (FILE_WILDCARDS.empty()){ - FILE_WILDCARDS["known"] = "Known files (*.stl, *.obj, *.amf, *.xml, *.prusa)|*.stl;*.STL;*.obj;*.OBJ;*.amf;*.AMF;*.xml;*.XML;*.prusa;*.PRUSA"; - FILE_WILDCARDS["stl"] = "STL files (*.stl)|*.stl;*.STL"; - FILE_WILDCARDS["obj"] = "OBJ files (*.obj)|*.obj;*.OBJ"; - FILE_WILDCARDS["amf"] = "AMF files (*.amf)|*.zip.amf;*.amf;*.AMF;*.xml;*.XML"; - FILE_WILDCARDS["3mf"] = "3MF files (*.3mf)|*.3mf;*.3MF;"; - FILE_WILDCARDS["prusa"] = "Prusa Control files (*.prusa)|*.prusa;*.PRUSA"; - FILE_WILDCARDS["ini"] = "INI files *.ini|*.ini;*.INI"; - FILE_WILDCARDS["gcode"] = "G-code files (*.gcode, *.gco, *.g, *.ngc)|*.gcode;*.GCODE;*.gco;*.GCO;*.g;*.G;*.ngc;*.NGC"; - FILE_WILDCARDS["svg"] = "SVG files *.svg|*.svg;*.SVG"; - } - return FILE_WILDCARDS; -} +const std::map FILE_WILDCARDS{ + std::make_pair("known", "Known files (*.stl, *.obj, *.amf, *.xml, *.prusa)|*.stl;*.STL;*.obj;*.OBJ;*.amf;*.AMF;*.xml;*.XML;*.prusa;*.PRUSA"), + std::make_pair("stl", "STL files (*.stl)|*.stl;*.STL"), + std::make_pair("obj", "OBJ files (*.obj)|*.obj;*.OBJ"), + std::make_pair("amf", "AMF files (*.amf)|*.zip.amf;*.amf;*.AMF;*.xml;*.XML"), + std::make_pair("3mf", "3MF files (*.3mf)|*.3mf;*.3MF;"), + std::make_pair("prusa", "Prusa Control files (*.prusa)|*.prusa;*.PRUSA"), + std::make_pair("ini", "INI files *.ini|*.ini;*.INI"), + std::make_pair("gcode", "G-code files (*.gcode, *.gco, *.g, *.ngc)|*.gcode;*.GCODE;*.gco;*.GCO;*.g;*.G;*.ngc;*.NGC"), + std::make_pair("svg", "SVG files *.svg|*.svg;*.SVG") +}; +const std::string MODEL_WILDCARD{ FILE_WILDCARDS.at("known") + std::string("|") + + FILE_WILDCARDS.at("stl") + std::string("|") + + FILE_WILDCARDS.at("obj") + std::string("|") + + FILE_WILDCARDS.at("amf") + std::string("|") + + FILE_WILDCARDS.at("3mf") + std::string("|") + + FILE_WILDCARDS.at("prusa") }; struct PresetTab { std::string name; Tab* panel; diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp new file mode 100644 index 0000000000..2c1930a113 --- /dev/null +++ b/src/slic3r/GUI/GUI_App.cpp @@ -0,0 +1,350 @@ +#include "GUI_App.hpp" + +#include +#include + +#include +#include +#include +#include +#include + +#include "Utils.hpp" +#include "GUI.hpp" +#include "MainFrame.hpp" +#include "AppConfig.hpp" +#include "PresetBundle.hpp" +#include "3DScene.hpp" + +#include "../Utils/PresetUpdater.hpp" + +namespace Slic3r { +namespace GUI { + +// IMPLEMENT_APP(GUI_App) +bool GUI_App::OnInit() +{ + SetAppName("Slic3rPE"); + SetAppDisplayName("Slic3r Prusa Edition"); + + // Slic3r::debugf "wxWidgets version %s, Wx version %s\n", &Wx::wxVERSION_STRING, $Wx::VERSION; + // + // 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" +// datadir.empty() ? +// Slic3r::set_data_dir(wxStandardPaths::Get().GetUserDataDir().ToStdString()) : +// Slic3r::set_data_dir(datadir); + // set_wxapp(this); // #ys_FIXME + +// app_config = new AppConfig(); + // set_app_config(app_config);// #ys_FIXME +// preset_bundle = new PresetBundle(); + // set_preset_bundle(preset_bundle);// #ys_FIXME + + // just checking for existence of Slic3r::data_dir is not enough : it may be an empty directory + // supplied as argument to --datadir; in that case we should still run the wizard + // eval{ +// preset_bundle->setup_directories(); + // }; + // if ($@) { + // warn $@ . "\n"; + // fatal_error(undef, $@); + // } +// app_conf_exists = app_config->exists(); + // load settings +// if (app_conf_exists) app_config->load(); + // app_config->set("version", Slic3r::VERSION); +// app_config->save(); + +// preset_updater = new PresetUpdater(VERSION_ONLINE_EVENT); + // set_preset_updater(preset_updater); // #ys_FIXME + +// Slic3r::GUI::load_language(); + + // Suppress the '- default -' presets. +// preset_bundle->set_default_suppressed(app_config->get("no_defaults").empty() ? false : true); + // eval{ +// preset_bundle->load_presets(*app_config); + // }; + // if ($@) { + // warn $@ . "\n"; + // show_error(undef, $@); + // } + + // application frame + // print STDERR "Creating main frame...\n"; + // wxImage::FindHandlerType(wxBITMAP_TYPE_PNG) || + wxImage::AddHandler(new wxPNGHandler()); + mainframe = new Slic3r::GUI::MainFrame(no_plater, false); + SetTopWindow(mainframe); + + // This makes CallAfter() work + // /*mainframe->*/Bind(wxEVT_IDLE, +// [this](wxIdleEvent& event) +// { +// std::function cur_cb{ nullptr }; +// // try to get the mutex. If we can't, just skip this idle event and get the next one. +// if (!callback_register.try_lock()) return; +// // pop callback +// if (m_cb.size() != 0){ +// cur_cb = m_cb.top(); +// m_cb.pop(); +// } +// // unlock mutex +// this->callback_register.unlock(); +// +// try { // call the function if it's not nullptr; +// if (cur_cb != nullptr) cur_cb(); +// } +// catch (std::exception& e) { +// // Slic3r::Log::error(LogChannel, LOG_WSTRING("Exception thrown: " << e.what())); // #ys_FIXME +// } +// +// if (app_config->dirty()) +// app_config->save(); +// } + ;// #ys_FIXME + // ); + + // On OS X the UI tends to freeze in weird ways if modal dialogs(config wizard, update notifications, ...) + // are shown before or in the same event callback with the main frame creation. + // Therefore we schedule them for later using CallAfter. +// CallAfter([this](){ +// // eval{ +// if (!preset_updater->config_update()) +// mainframe->Close(); +// // }; +// // if ($@) { +// // show_error(undef, $@); +// // mainframe->Close(); +// // } +// }); +// +// CallAfter([this](){ +// if (!Slic3r::GUI::config_wizard_startup(app_conf_exists)) { +// // Only notify if there was not wizard so as not to bother too much ... +// preset_updater->slic3r_update_notify(); +// } +// preset_updater->sync(preset_bundle); +// }); +// + + // #ys_FIXME All of this should to be removed + // # The following event is emited by the C++ menu implementation of application language change. + // EVT_COMMAND($self, -1, $LANGUAGE_CHANGE_EVENT, sub{ + // print STDERR "LANGUAGE_CHANGE_EVENT\n"; + // $self->recreate_GUI; + // }); + // + // # The following event is emited by the C++ menu implementation of preferences change. + // EVT_COMMAND($self, -1, $PREFERENCES_EVENT, sub{ + // $self->update_ui_from_settings; + // }); + // + // # The following event is emited by PresetUpdater(C++) to inform about + // # the newer Slic3r application version avaiable online. + // EVT_COMMAND($self, -1, $VERSION_ONLINE_EVENT, sub { + // my($self, $event) = @_; + // my $version = $event->GetString; + // $self->{app_config}->set('version_online', $version); + // $self->{app_config}->save; + // }); + + mainframe->Show(true); + + return true; +} + +void GUI_App::recreate_GUI() +{ +// print STDERR "recreate_GUI\n"; + + auto topwindow = GetTopWindow(); + mainframe = new Slic3r::GUI::MainFrame(no_plater,false); + + if (topwindow) { + SetTopWindow(mainframe); + topwindow->Destroy(); + } + + // On OSX the UI was not initialized correctly if the wizard was called + // before the UI was up and running. + CallAfter([](){ + // Run the config wizard, don't offer the "reset user profile" checkbox. + Slic3r::GUI::config_wizard_startup(true); + }); +} + +void GUI_App::system_info() +{ +// auto slic3r_info = Slic3r::slic3r_info(format = > 'html'); +// auto copyright_info = Slic3r::copyright_info(format = > 'html'); +// auto system_info = Slic3r::system_info(format = > 'html'); + std::string opengl_info = ""; + std::string opengl_info_txt = ""; + if (mainframe && mainframe->m_plater /*&& mainframe->m_plater->canvas3D*/) { + opengl_info = _3DScene::get_gl_info(true, true); + opengl_info_txt = _3DScene::get_gl_info(false, true); + } +// auto about = new SystemInfo(nullptr, slic3r_info, /*copyright_info,*/system_info, opengl_info, +// text_info = > Slic3r::slic3r_info.Slic3r::system_info.$opengl_info_txt, +// ); +// about->ShowModal(); +// about->Destroy(); +} + +// static method accepting a wxWindow object as first parameter +bool GUI_App::catch_error(std::function cb, + // wxMessageDialog* message_dialog, + const std::string& err /*= ""*/){ + if (!err.empty()) { + if (cb) + cb(); + // if (message_dialog) + // message_dialog->(err, "Error", wxOK | wxICON_ERROR); + show_error(/*this*/nullptr, err); + return true; + } + return false; +} + +// static method accepting a wxWindow object as first parameter +void fatal_error(wxWindow* parent){ + show_error(parent, ""); + // exit 1; // #ys_FIXME +} + +// Called after the Preferences dialog is closed and the program settings are saved. +// Update the UI based on the current preferences. +void GUI_App::update_ui_from_settings(){ + mainframe->update_ui_from_settings(); +} + +// wxArrayString GUI::open_model(wxWindow* window){ +// auto dialog = new wxFileDialog(window ? window : GetTopWindow(), +// _(L("Choose one or more files (STL/OBJ/AMF/3MF/PRUSA):")), +// app_config->get_last_dir(), "", get_model_wildcard(), +// wxFD_OPEN | wxFD_MULTIPLE | wxFD_FILE_MUST_EXIST); +// if (dialog->ShowModal() != wxID_OK) { +// dialog->Destroy; +// return; +// } +// wxArrayString input_files; +// dialog->GetPaths(input_files); +// dialog->Destroy(); +// return input_files; +// } + +void GUI_App::CallAfter(std::function cb) +{ + // set mutex + callback_register.lock(); + // push function onto stack + m_cb.emplace(cb); + // unset mutex + callback_register.unlock(); +} + +wxMenuItem* GUI_App::append_menu_item(wxMenu* menu, + int id, + const wxString& string, + const wxString& description, + const std::string& icon, + std::function cb, + wxItemKind kind/* = wxITEM_NORMAL*/) +{ + if (id == wxID_ANY) + id = wxNewId(); + auto item = new wxMenuItem(menu, id, string, description, kind); + if (!icon.empty()) + item->SetBitmap(wxBitmap(Slic3r::var(icon), wxBITMAP_TYPE_PNG)); + menu->Append(item); + + menu->Bind(wxEVT_MENU, /*[cb](wxCommandEvent& event){cb; }*/cb); + return item; +} + +wxMenuItem* GUI_App::append_submenu(wxMenu* menu, + wxMenu* sub_menu, + int id, + const wxString& string, + const wxString& description, + const std::string& icon) +{ + if (id == wxID_ANY) + id = wxNewId(); + auto item = new wxMenuItem(menu, id, string, description); + if (!icon.empty()) + item->SetBitmap(wxBitmap(Slic3r::var(icon), wxBITMAP_TYPE_PNG)); + item->SetSubMenu(sub_menu); + menu->Append(item); + + return item; +} + +void GUI_App::save_window_pos(wxTopLevelWindow* window, const std::string& name){ + int x, y; + window->GetScreenPosition(&x, &y); + app_config->set(name + "_pos", wxString::Format("%d,%d", x, y).ToStdString()); + + window->GetSize(&x, &y); + app_config->set(name + "_size", wxString::Format("%d,%d", x, y).ToStdString()); + + app_config->set(name + "_maximized", window->IsMaximized() ? "1" : "0"); + + app_config->save(); +} + +void GUI_App::restore_window_pos(wxTopLevelWindow* window, const std::string& name){ + if (!app_config->has(name + "_pos")) + return; + + std::string str = app_config->get(name + "_size"); + std::vector values; + boost::split(values, str, boost::is_any_of(",")); + wxSize size = wxSize(atoi(values[0].c_str()), atoi(values[1].c_str())); + window->SetSize(size); + + auto display = (new wxDisplay())->GetClientArea(); + str = app_config->get(name + "_pos"); + values.resize(0); + boost::split(values, str, boost::is_any_of(",")); + wxPoint pos = wxPoint(atoi(values[0].c_str()), atoi(values[1].c_str())); + if (pos.x + 0.5*size.GetWidth() < display.GetRight() && + pos.y + 0.5*size.GetHeight() < display.GetBottom()) + window->Move(pos); + + if (app_config->get(name + "_maximized") == "1") + window->Maximize(); +} + +// static method accepting a wxWindow object as first parameter +// void warning_catcher{ +// my($self, $message_dialog) = @_; +// return sub{ +// my $message = shift; +// return if $message = ~/ GLUquadricObjPtr | Attempt to free unreferenced scalar / ; +// my @params = ($message, 'Warning', wxOK | wxICON_WARNING); +// $message_dialog +// ? $message_dialog->(@params) +// : Wx::MessageDialog->new($self, @params)->ShowModal; +// }; +// } + +// Do we need this function??? +// void GUI_App::notify(message){ +// auto frame = GetTopWindow(); +// // try harder to attract user attention on OS X +// if (!frame->IsActive()) +// frame->RequestUserAttention(defined(__WXOSX__/*&Wx::wxMAC */)? wxUSER_ATTENTION_ERROR : wxUSER_ATTENTION_INFO); +// +// // There used to be notifier using a Growl application for OSX, but Growl is dead. +// // The notifier also supported the Linux X D - bus notifications, but that support was broken. +// //TODO use wxNotificationMessage ? +// } + + +} // GUI +} //Slic3r \ No newline at end of file diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp new file mode 100644 index 0000000000..874c63fdee --- /dev/null +++ b/src/slic3r/GUI/GUI_App.hpp @@ -0,0 +1,77 @@ +#ifndef slic3r_GUI_App_hpp_ +#define slic3r_GUI_App_hpp_ + +#include +// #include +// #include "PrintConfig.hpp" +// #include "../../libslic3r/Utils.hpp" +// #include "GUI.hpp" + +#include + +#include +#include + +class wxMenuItem; +class wxTopLevelWindow; + +namespace Slic3r { +class AppConfig; +class PresetBundle; +class PresetUpdater; + +namespace GUI +{ +class MainFrame; + +class GUI_App : public wxApp +{ + // Datadir provided on the command line. + std::string datadir = ""; + bool no_plater{ true }; + bool app_conf_exists{ false }; + + // Lock to guard the callback stack + std::mutex callback_register; + // callbacks registered to run during idle event. + std::stack> m_cb{}; + +public: + bool OnInit() override; + GUI_App() : wxApp() {} + + void recreate_GUI(); + void system_info(); + static bool catch_error(std::function cb, +// wxMessageDialog* message_dialog, + const std::string& err); +// void notify(/*message*/); + void update_ui_from_settings(); + void CallAfter(std::function cb); + wxMenuItem* append_menu_item( wxMenu* menu, + int id, + const wxString& string, + const wxString& description, + const std::string& icon, + std::function cb, + wxItemKind kind = wxITEM_NORMAL); + wxMenuItem* append_submenu( wxMenu* menu, + wxMenu* sub_menu, + int id, + const wxString& string, + const wxString& description, + const std::string& icon); + void save_window_pos(wxTopLevelWindow* window, const std::string& name); + void restore_window_pos(wxTopLevelWindow* window, const std::string& name); + + AppConfig* app_config{ nullptr }; + PresetBundle* preset_bundle{ nullptr }; + PresetUpdater* preset_updater{ nullptr }; + MainFrame* mainframe{ nullptr }; +}; +// DECLARE_APP(GUI_App) + +} // GUI +} //Slic3r + +#endif // slic3r_GUI_App_hpp_ \ No newline at end of file diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp new file mode 100644 index 0000000000..c3b89b533f --- /dev/null +++ b/src/slic3r/GUI/MainFrame.cpp @@ -0,0 +1,757 @@ +#include "MainFrame.hpp" + +#include +#include +#include +#include +#include +#include + +#include "Tab.hpp" +#include "PresetBundle.hpp" +#include "..\AppController.hpp" +#include "ProgressStatusBar.hpp" +#include "3DScene.hpp" +#include "Print.hpp" +#include "Polygon.hpp" +#include "AppConfig.hpp" + +#include +#include + +namespace Slic3r { +namespace GUI +{ +MainFrame::MainFrame(const bool no_plater, const bool loaded) : +wxFrame(NULL, wxID_ANY, "FORK_NAME-VERSION", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE), + m_no_plater(no_plater), + m_loaded(loaded) +{ +// Slic3r::GUI::set_main_frame(this); +// m_appController = new Slic3r::AppController(); + +// #if _WIN32 +// // Load the icon either from the exe, or from the ico file. +// // auto iconfile = Slic3r::decode_path($FindBin::Bin) . '\slic3r.exe'; +// auto iconfile = Slic3r::var("Slic3r.ico");// unless - f iconfile; +// SetIcon(wxIcon(iconfile, wxBITMAP_TYPE_ICO)); +// #else +// SetIcon(wxIcon(Slic3r::var("Slic3r_128px.png"), wxBITMAP_TYPE_PNG)); + SetIcon(wxIcon("c:\\src\\Slic3r_TMP\\resources\\icons\\Slic3r_128px.png", wxBITMAP_TYPE_PNG)); +// #ifdef // _WIN32 + + // initialize tabpanel and menubar +// init_tabpanel(); +// init_menubar(); + + // set default tooltip timer in msec + // SetAutoPop supposedly accepts long integers but some bug doesn't allow for larger values + // (SetAutoPop is not available on GTK.) +// wxToolTip::SetAutoPop(32767); + + // initialize status bar +// m_statusbar = new Slic3r::GUI::ProgressStatusBar(this); +// m_statusbar->embed(); +// m_statusbar->set_status_text(L("Version ").Slic3r::VERSION.L(" - Remember to check for updates at http://github.com/prusa3d/slic3r/releases")); + // Make the global status bar and its progress indicator available in C++ +// m_appController->set_global_progress_indicator(m_statusbar); + +// m_appController->set_model(m_plater->model); +// m_appController->set_print(m_plater->print); +// +// m_plater->appController = m_appController; + +// m_loaded = true; +// +// // initialize layout +// auto sizer = new wxBoxSizer(wxVERTICAL); +// if (m_tabpanel) +// sizer->Add(m_tabpanel, 1, wxEXPAND); +// sizer->SetSizeHints(this); +// SetSizer(sizer); +// Fit(); +// SetMinSize(wxSize(760, 490)); +// SetSize(GetMinSize()); +// // wxTheApp->restore_window_pos(this, "main_frame"); +// Show(); +// Layout(); + + // declare events +// Bind(wxEVT_CLOSE_WINDOW, [](wxEvent& event){ +// if (event.CanVeto() && !Slic3r::GUI::check_unsaved_changes) { +// event.Veto(); +// return; +// } +// // save window size +// wxTheApp->save_window_pos(this, "main_frame"); +// // 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. +// wxTheApp->{app_config}->save(); +// if (m_plater) +// m_plater->print = undef; +// _3DScene::remove_all_canvases(); +// Slic3r::GUI::deregister_on_request_update_callback(); +// // propagate event +// event.Skip(); +// }); + +// update_ui_from_settings(); +// +// Slic3r::GUI::update_mode(); + wxMenu *menuHelp = new wxMenu; + menuHelp->Append(wxID_ABOUT); + wxMenuBar *menuBar = new wxMenuBar; + menuBar->Append(menuHelp, "&Help"); + SetMenuBar(menuBar); + + return; +} + +void MainFrame::init_tabpanel() +{ + m_tabpanel = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_TOP | wxTAB_TRAVERSAL); + Slic3r::GUI::set_tab_panel(m_tabpanel); + +// m_tabpanel->Bind(wxEVT_NOTEBOOK_PAGE_CHANGED, [m_tabpanel](wxEvent&){ +// auto panel = m_tabpanel->GetCurrentPage(); +// // panel->OnActivate(); if panel->can('OnActivate'); +// +// std::vector tab_names = { "print", "filament", "printer" }; +// for (auto& tab_name : tab_names) { +// if (tab_name == panel->GetName()) +// Slic3r::GUI::get_preset_tab(tab_name.c_str())->OnActivate(); +// } +// }); + + if (!m_no_plater) { +// m_plater = new Slic3r::GUI::Plater(m_tabpanel, +// event_object_selection_changed = > $OBJECT_SELECTION_CHANGED_EVENT, +// event_object_settings_changed = > $OBJECT_SETTINGS_CHANGED_EVENT, +// event_remove_object = > $OBJECT_REMOVE_EVENT, +// event_update_scene = > $UPDATE_SCENE_EVENT, +// ), L("Plater") +// m_tabpanel->AddPage(plater); + } + + // The following event is emited by the C++ Tab implementation on config value change. +// EVT_COMMAND($self, -1, $VALUE_CHANGE_EVENT, sub { +// my($self, $event) = @_; +// auto str = event->GetString; +// my($opt_key, $name) = ($str = ~/ (.*) (.*) / ); +// auto tab = Slic3r::GUI::get_preset_tab(name); +// auto config = tab->get_config(); +// if (m_plater) { +// m_plater->on_config_change(config); // propagate config change events to the plater +// if (opt_key == "extruders_count"){ +// auto value = event->GetInt(); +// m_plater->on_extruders_change(value); +// } +// if (opt_key == "printer_technology"){ +// auto value = event->GetInt(); // 0 ~"ptFFF"; 1 ~"ptSLA" +// m_plater->show_preset_comboboxes(value); +// } +// } +// // don't save while loading for the first time +// if (Slic3r::GUI::autosave && m_loaded) +// m_config->save(Slic3r::GUI::autosave) ; +// }); + + // The following event is emited by the C++ Tab implementation on preset selection, + // or when the preset's "modified" status changes. +// EVT_COMMAND($self, -1, $PRESETS_CHANGED_EVENT, sub { +// my($self, $event) = @_; +// auto tab_name = event->GetString; +// +// Tab* tab = Slic3r::GUI::get_preset_tab(tab_name); +// if (m_plater) { +// // Update preset combo boxes(Print settings, Filament, Material, Printer) from their respective tabs. +// auto presets = tab->get_presets(); +// if (presets){ +// auto reload_dependent_tabs = tab->get_dependent_tabs(); +// m_plater->update_presets(tab_name, reload_dependent_tabs, presets); +// m_plater->{"selected_item_$tab_name"} = tab->get_selected_preset_item(); +// if (tab_name == "printer") { +// // Printer selected at the Printer tab, update "compatible" marks at the print and filament selectors. +// std::vector tab_names_other = { "print", "filament", "sla_materialprinter" }; +// for (const auto tab_name_other : tab_names_other) { +// Tab* cur_tab = m_options_tabs[tab_name_other]; +// // If the printer tells us that the print or filament preset has been switched or invalidated, +// // refresh the print or filament tab page.Otherwise just refresh the combo box. +// if (reload_dependent_tabs.empty() || +// find(reload_dependent_tabs.begin(), reload_dependent_tabs.end(), tab_name_other) == +// reload_dependent_tabs.end() ) +// cur_tab->update_tab_ui(); +// else +// cur_tab->load_current_preset(); +// +// } +// } +// m_plater->on_config_change(tab->get_config()); +// } +// } +// }); + + // The following event is emited by the C++ Tab implementation on object selection change. +// EVT_COMMAND($self, -1, $OBJECT_SELECTION_CHANGED_EVENT, sub { +// auto obj_idx = event->GetId(); +// // my $child = $event->GetInt == 1 ? 1 : undef; +// // $self->{plater}->select_object($obj_idx < 0 ? undef : $obj_idx, $child); +// // $self->{plater}->item_changed_selection($obj_idx); +// +// auto vol_idx = event->GetInt(); +// m_plater->select_object_from_cpp(obj_idx < 0 ? undef : obj_idx, vol_idx < 0 ? -1 : vol_idx); +// }); + + // The following event is emited by the C++ GUI implementation on object settings change. +// EVT_COMMAND($self, -1, $OBJECT_SETTINGS_CHANGED_EVENT, sub { +// auto line = event->GetString(); +// my($obj_idx, $parts_changed, $part_settings_changed) = split('', $line); +// +// m_plater->changed_object_settings(obj_idx, parts_changed, part_settings_changed); +// }); + + // The following event is emited by the C++ GUI implementation on object remove. +// EVT_COMMAND($self, -1, $OBJECT_REMOVE_EVENT, sub { +// m_plater->remove(); +// }); +// +// // The following event is emited by the C++ GUI implementation on extruder change for object. +// EVT_COMMAND($self, -1, $UPDATE_SCENE_EVENT, sub { +// m_plater->update(); +// }); + + +// Slic3r::GUI::create_preset_tabs(true, VALUE_CHANGE_EVENT, PRESETS_CHANGED_EVENT); + std::vector tab_names = { "print", "filament", "sla_material", "printer" }; +// for (auto tab_name : tab_names) +// m_options_tabs[tab_name] = Slic3r::GUI::get_preset_tab(tab_name.c_str()); // + + if (m_plater) { +// m_plater->on_select_preset(sub{ +// my($group, $name) = @_; +// $self->{options_tabs}{$group}->select_preset($name); +// }); + // load initial config + auto full_config = Slic3r::GUI::get_preset_bundle()->full_config(); +// m_plater->on_config_change(full_config); + + // Show a correct number of filament fields. +// if (defined full_config->nozzle_diameter){ +// // nozzle_diameter is undefined when SLA printer is selected +// m_plater->on_extruders_change(int(@{$full_config->nozzle_diameter})); +// } + + // Show correct preset comboboxes according to the printer_technology +// m_plater->show_preset_comboboxes(full_config.printer_technology() == "FFF" ? 0 : 1); + } +} + +void MainFrame::init_menubar() +{ + // File menu + auto fileMenu = new wxMenu(); + { +// wxTheApp->append_menu_item(fileMenu, L("Open STL/OBJ/AMF/3MF…\tCtrl+O"), L('Open a model'), [](wxCommandEvent&){ +// if (m_plater) m_plater->add(); +// }, undef, undef); //'brick_add.png'); + append_menu_item(fileMenu, wxID_ANY, _(L("&Load Config…\tCtrl+L")), _(L("Load exported configuration file")), + [this](wxCommandEvent&){ load_config_file(); }, "plugin_add.png"); + append_menu_item(fileMenu, wxID_ANY, _(L("&Export Config…\tCtrl+E")), _(L("Export current configuration to file")), + [this](wxCommandEvent&){ export_config(); }, "plugin_go.png"); + append_menu_item(fileMenu, wxID_ANY, _(L("&Load Config Bundle…")), _(L("Load presets from a bundle")), + [this](wxCommandEvent&){ load_configbundle(); }, "lorry_add.png"); + append_menu_item(fileMenu, wxID_ANY, _(L("&Export Config Bundle…")), _(L("Export all presets to file")), + [this](wxCommandEvent&){ export_configbundle(); }, "lorry_go.png"); + fileMenu->AppendSeparator(); + wxMenuItem* repeat = nullptr; + append_menu_item(fileMenu, wxID_ANY, _(L("Q&uick Slice…\tCtrl+U")), _(L("Slice a file into a G-code")), + [this, repeat](wxCommandEvent&){ + wxTheApp->CallAfter([this, repeat](){ + quick_slice(); + repeat->Enable(is_last_input_file()/*defined $Slic3r::GUI::MainFrame::last_input_file*/); + }); }, "cog_go.png"); + append_menu_item(fileMenu, wxID_ANY, _(L("Quick Slice and Save &As…\tCtrl+Alt+U")), _(L("Slice a file into a G-code, save as")), + [this, repeat](wxCommandEvent&){ + wxTheApp->CallAfter([this, repeat](){ + quick_slice(/*save_as = > 1*/qsSaveAs); + repeat->Enable(is_last_input_file()/*defined $Slic3r::GUI::MainFrame::last_input_file*/); + }); }, "cog_go.png"); + repeat = append_menu_item(fileMenu, wxID_ANY, _(L("&Repeat Last Quick Slice\tCtrl+Shift+U")), _(L("Repeat last quick slice")), + [this](wxCommandEvent&){ + wxTheApp->CallAfter([this](){ + quick_slice(/*reslice = > 1*/qsReslice); + }); }, "cog_go.png"); + repeat->Enable(0); + fileMenu->AppendSeparator(); + append_menu_item(fileMenu, wxID_ANY, _(L("Slice to SV&G…\tCtrl+G")), _(L("Slice file to a multi-layer SVG")), + [this](wxCommandEvent&){ quick_slice(/*save_as = > 1, export_svg = > 1*/qsSaveAs | qsExportSVG); }, "shape_handles.png"); + append_menu_item(fileMenu, wxID_ANY, _(L("Slice to PNG…")), _(L("Slice file to a set of PNG files")), + [this](wxCommandEvent&){ slice_to_png(); /*$self->quick_slice(save_as = > 0, export_png = > 1);*/ }, "shape_handles.png"); + m_menu_item_reslice_now = append_menu_item(fileMenu, wxID_ANY, _(L("(&Re)Slice Now\tCtrl+S")), _(L("Start new slicing process")), + [this](wxCommandEvent&){ reslice_now(); }, "shape_handles.png"); + fileMenu->AppendSeparator(); + append_menu_item(fileMenu, wxID_ANY, _(L("Repair STL file…")), _(L("Automatically repair an STL file")), + [this](wxCommandEvent&){ repair_stl(); }, "wrench.png"); + fileMenu->AppendSeparator(); + append_menu_item(fileMenu, wxID_EXIT, _(L("&Quit")), _(L("Quit Slic3r")), + [this](wxCommandEvent&){ Close(false); } ); + } + + // Plater menu + if(m_plater) { + auto plater_menu = new wxMenu(); + append_menu_item(plater_menu, wxID_ANY, L("Export G-code..."), L("Export current plate as G-code"), + [this](wxCommandEvent&){ /*m_plater->export_gcode(); */}, "cog_go.png"); + append_menu_item(plater_menu, wxID_ANY, L("Export plate as STL..."), L("Export current plate as STL"), + [this](wxCommandEvent&){ /*m_plater->export_stl(); */}, "brick_go.png"); + append_menu_item(plater_menu, wxID_ANY, L("Export plate as AMF..."), L("Export current plate as AMF"), + [this](wxCommandEvent&){ /*m_plater->export_amf();*/ }, "brick_go.png"); + append_menu_item(plater_menu, wxID_ANY, L("Export plate as 3MF..."), L("Export current plate as 3MF"), + [this](wxCommandEvent&){ /*m_plater->export_3mf(); */}, "brick_go.png"); + +// m_object_menu = m_plater->object_menu; + on_plater_selection_changed(false); + } + + // Window menu + auto windowMenu = new wxMenu(); + { + size_t tab_offset = 0; + if (m_plater) { + append_menu_item(windowMenu, wxID_ANY, L("Select &Plater Tab\tCtrl+1"), L("Show the plater"), + [this](wxCommandEvent&){ select_tab(0); }, "application_view_tile.png"); + tab_offset += 1; + } + if (tab_offset > 0) { + windowMenu->AppendSeparator(); + } + append_menu_item(windowMenu, wxID_ANY, L("Select P&rint Settings Tab\tCtrl+2"), L("Show the print settings"), + [this, tab_offset](wxCommandEvent&){ select_tab(tab_offset + 0); }, "cog.png"); + append_menu_item(windowMenu, wxID_ANY, L("Select &Filament Settings Tab\tCtrl+3"), L("Show the filament settings"), + [this, tab_offset](wxCommandEvent&){ select_tab(tab_offset + 1); }, "spool.png"); + append_menu_item(windowMenu, wxID_ANY, L("Select Print&er Settings Tab\tCtrl+4"), L("Show the printer settings"), + [this, tab_offset](wxCommandEvent&){ select_tab(tab_offset + 2); }, "printer_empty.png"); + } + + // View menu + if (m_plater) { + m_viewMenu = new wxMenu(); +// \xA0 is a non-breaing space. It is entered here to spoil the automatic accelerators, + // as the simple numeric accelerators spoil all numeric data entry. + // The camera control accelerators are captured by 3DScene Perl module instead. + auto accel = [](const wxString& st1, const wxString& st2) { +// if ($^O eq "MSWin32") +// return st1 + "\t\xA0" + st2; +// else + return st1; + }; + + append_menu_item(m_viewMenu, wxID_ANY, accel(_(L("Iso")), "0"), L("Iso View"), [this](wxCommandEvent&){ select_view("iso"); }); + append_menu_item(m_viewMenu, wxID_ANY, accel(_(L("Top")), "1"), L("Top View"), [this](wxCommandEvent&){ select_view("top"); }); + append_menu_item(m_viewMenu, wxID_ANY, accel(_(L("Bottom")), "2"), L("Bottom View"),[this](wxCommandEvent&){ select_view("bottom"); }); + append_menu_item(m_viewMenu, wxID_ANY, accel(_(L("Front")), "3"), L("Front View"), [this](wxCommandEvent&){ select_view("front"); }); + append_menu_item(m_viewMenu, wxID_ANY, accel(_(L("Rear")), "4"), L("Rear View"), [this](wxCommandEvent&){ select_view("rear"); }); + append_menu_item(m_viewMenu, wxID_ANY, accel(_(L("Left")), "5"), L("Left View"), [this](wxCommandEvent&){ select_view("left"); }); + append_menu_item(m_viewMenu, wxID_ANY, accel(_(L("Right")), "6"), L("Right View"), [this](wxCommandEvent&){ select_view("right"); }); + } + + // Help menu + auto helpMenu = new wxMenu(); + { + append_menu_item(helpMenu, wxID_ANY, _(L("Prusa 3D Drivers")), _(L("Open the Prusa3D drivers download page in your browser")), + [this](wxCommandEvent&){ wxLaunchDefaultBrowser("http://www.prusa3d.com/drivers/"); }); + append_menu_item(helpMenu, wxID_ANY, _(L("Prusa Edition Releases")), _(L("Open the Prusa Edition releases page in your browser")), + [this](wxCommandEvent&){ wxLaunchDefaultBrowser("http://github.com/prusa3d/slic3r/releases"); }); +//# my $versioncheck = $self->_append_menu_item($helpMenu, "Check for &Updates...", "Check for new Slic3r versions", sub{ +//# wxTheApp->check_version(1); +//# }); +//# $versioncheck->Enable(wxTheApp->have_version_check); + append_menu_item(helpMenu, wxID_ANY, _(L("Slic3r &Website")), _(L("Open the Slic3r website in your browser")), + [this](wxCommandEvent&){ wxLaunchDefaultBrowser("http://slic3r.org/"); }); + append_menu_item(helpMenu, wxID_ANY, _(L("Slic3r &Manual")), _(L("Open the Slic3r manual in your browser")), + [this](wxCommandEvent&){ wxLaunchDefaultBrowser("http://manual.slic3r.org/"); }); + helpMenu->AppendSeparator(); + append_menu_item(helpMenu, wxID_ANY, _(L("System Info")), _(L("Show system information")), + [this](wxCommandEvent&){ /*wxTheApp->system_info();*/ }); + append_menu_item(helpMenu, wxID_ANY, _(L("Show &Configuration Folder")), _(L("Show user configuration folder (datadir)")), + [this](wxCommandEvent&){ Slic3r::GUI::desktop_open_datadir_folder(); }); + append_menu_item(helpMenu, wxID_ANY, _(L("Report an Issue")), _(L("Report an issue on the Slic3r Prusa Edition")), + [this](wxCommandEvent&){ wxLaunchDefaultBrowser("http://github.com/prusa3d/slic3r/issues/new"); }); + append_menu_item(helpMenu, wxID_ANY, _(L("&About Slic3r")), _(L("Show about dialog")), + [this](wxCommandEvent&){ Slic3r::GUI::about(); }); + } + + // menubar + // assign menubar to frame after appending items, otherwise special items + // will not be handled correctly + { + auto menubar = new wxMenuBar(); + menubar->Append(fileMenu, L("&File")); + if (m_plater_menu) menubar->Append(m_plater_menu, L("&Plater")) ; + if (m_object_menu) menubar->Append(m_object_menu, L("&Object")) ; + menubar->Append(windowMenu, L("&Window")); + if (m_viewMenu) menubar->Append(m_viewMenu, L("&View")); + // Add additional menus from C++ +// Slic3r::GUI::add_menus(menubar, preferences_event, lang_ch_event); + menubar->Append(helpMenu, L("&Help")); + SetMenuBar(menubar); + } +} + +// Selection of a 3D object changed on the platter. +void MainFrame::on_plater_selection_changed(const bool have_selection) +{ + if (!m_object_menu) return; + + for (auto item : m_object_menu->GetMenuItems()) + m_object_menu->Enable(item->GetId(), have_selection); +} + +void MainFrame::slice_to_png(){ +// m_plater->stop_background_process(); +// m_plater->async_apply_config(); + m_appController->print_ctl()->slice_to_png(); +} + +// To perform the "Quck Slice", "Quick Slice and Save As", "Repeat last Quick Slice" and "Slice to SVG". +void MainFrame::quick_slice(const /*QuickSlice*/int qs/* = qsUndef const bool reslice, + const bool export_svg, + const bool export_png, + const bool save_as*/){ +// my $progress_dialog; + wxString input_file; +// eval +// { + // validate configuration + auto config = get_preset_bundle()->full_config(); + config.validate(); + + // select input file + if (/*!reslice*/(qs & qsReslice) == 0) { + auto dlg = new wxFileDialog(this, _(L("Choose a file to slice (STL/OBJ/AMF/3MF/PRUSA):")), + get_app_config()->get_last_dir(), "", + MODEL_WILDCARD, wxFD_OPEN | wxFD_FILE_MUST_EXIST); + if (dlg->ShowModal() != wxID_OK) { + dlg->Destroy(); + return; + } + input_file = dlg->GetPath(); + dlg->Destroy(); + if (/*!export_svg*/(qs & qsExportSVG) == 0) + m_qs_last_input_file = input_file; + } + else { + if (m_qs_last_input_file.IsEmpty()) { + auto dlg = new wxMessageDialog(this, _(L("No previously sliced file.")), + _(L("Error")), wxICON_ERROR | wxOK); + dlg->ShowModal(); + return; + } + if (std::ifstream(m_qs_last_input_file.char_str())) { + auto dlg = new wxMessageDialog(this, _(L("Previously sliced file ("))+m_qs_last_input_file+_(L(") not found.")), + _(L("File Not Found")), wxICON_ERROR | wxOK); + dlg->ShowModal(); + return; + } + input_file = m_qs_last_input_file; + } + auto input_file_basename = get_base_name(input_file); + get_app_config()->update_skein_dir(get_dir_name(input_file)); + + auto bed_shape = Slic3r::Polygon::new_scale(config.option("bed_shape")->values); +// auto print_center = Slic3r::Pointf->new_unscale(bed_shape.bounding_box().center()); +// +// auto sprint = new Slic3r::Print::Simple( +// print_center = > print_center, +// status_cb = > [](int percent, const wxString& msg){ +// m_progress_dialog->Update(percent, msg+"…"); +// }); + + // keep model around + auto model = Slic3r::Model::read_from_file(input_file.ToStdString()); + +// sprint->apply_config(config); +// sprint->set_model(model); + + // Copy the names of active presets into the placeholder parser. +// get_preset_bundle()->export_selections(sprint->placeholder_parser); + + // select output file + wxString output_file; + if (/*reslice*/(qs & qsReslice)/* != 0*/) { + if (!m_qs_last_output_file.IsEmpty()) + output_file = m_qs_last_output_file; + } + else if (/*save_as*/(qs & qsSaveAs)/* != 0*/) { + // The following line may die if the output_filename_format template substitution fails. +// output_file = sprint->output_filepath; +// if (export_svg) +// output_file = ~s / \.[gG][cC][oO][dD][eE]$ / .svg /; + auto dlg = new wxFileDialog(this, _(L("Save ")) + (qs & qsExportSVG/*export_svg*/ ? _(L("SVG")) : _(L("G-code"))) + _(L(" file as:")), + get_app_config()->get_last_output_dir(get_dir_name(output_file)), get_base_name(input_file), + qs & qsExportSVG/*export_svg*/ ? FILE_WILDCARDS.at("svg") : FILE_WILDCARDS.at("gcode"), + wxFD_SAVE | wxFD_OVERWRITE_PROMPT); + if (dlg->ShowModal() != wxID_OK) { + dlg->Destroy(); + return; + } + output_file = dlg->GetPath(); + dlg->Destroy(); + if (/*!export_svg*/!(qs & qsExportSVG)) + m_qs_last_output_file = output_file; + get_app_config()->update_last_output_dir(get_dir_name(output_file)); + } + else if (/*export_png*/qs & qsExportPNG) { +// output_file = sprint->output_filepath; +// output_file = ~s / \.[gG][cC][oO][dD][eE]$ / .zip / ; + auto dlg = new wxFileDialog(this, _(L("Save zip file as:")), + get_app_config()->get_last_output_dir(get_dir_name(output_file)), + get_base_name(output_file), "*.zip", wxFD_SAVE | wxFD_OVERWRITE_PROMPT); + if (dlg->ShowModal() != wxID_OK) { + dlg->Destroy(); + return; + } + output_file = dlg->GetPath(); + dlg->Destroy(); + } + + // show processbar dialog + m_progress_dialog = new wxProgressDialog(_(L("Slicing…")), _(L("Processing ")) + input_file_basename + "…", + 100, this, 4); + m_progress_dialog->Pulse(); + { +// my @warnings = (); +// local $SIG{ __WARN__ } = sub{ push @warnings, $_[0] }; + +// sprint->output_file(output_file); +// if (export_svg) { +// sprint->export_svg(); +// } +// else if(export_png) { +// sprint->export_png(); +// } +// else { +// sprint->export_gcode(); +// } +// sprint->status_cb(undef); +// Slic3r::GUI::warning_catcher($self)->($_) for @warnings; + } + m_progress_dialog->Destroy(); + m_progress_dialog = nullptr; + + auto message = input_file_basename + _(L(" was successfully sliced.")); +// wxTheApp->notify(message); + wxMessageDialog(this, message, _(L("Slicing Done!")), wxOK | wxICON_INFORMATION).ShowModal(); +// }; +// Slic3r::GUI::catch_error(this, [](){ if (m_progress_dialog) m_progress_dialog->Destroy(); }); +} + +void MainFrame::reslice_now(){ +// if (m_plater) +// m_plater->reslice(); +} + +void MainFrame::repair_stl() +{ + wxString input_file; + { + auto dlg = new wxFileDialog(this, _(L("Select the STL file to repair:")), + get_app_config()->get_last_dir(), "", + FILE_WILDCARDS.at("stl"), wxFD_OPEN | wxFD_FILE_MUST_EXIST); + if (dlg->ShowModal() != wxID_OK) { + dlg->Destroy(); + return; + } + input_file = dlg->GetPath(); + dlg->Destroy(); + } + + auto output_file = input_file; + { +// output_file = ~s / \.[sS][tT][lL]$ / _fixed.obj / ; + auto dlg = new wxFileDialog( this, L("Save OBJ file (less prone to coordinate errors than STL) as:"), + get_dir_name(output_file), get_base_name(output_file), + FILE_WILDCARDS.at("obj"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT); + if (dlg->ShowModal() != wxID_OK) { + dlg->Destroy(); + return /*undef*/; + } + output_file = dlg->GetPath(); + dlg->Destroy(); + } + + auto tmesh = new Slic3r::TriangleMesh(); + tmesh->ReadSTLFile(input_file.char_str()); + tmesh->repair(); + tmesh->WriteOBJFile(output_file.char_str()); + Slic3r::GUI::show_info(this, L("Your file was repaired."), L("Repair")); +} + +void MainFrame::export_config() +{ + // Generate a cummulative configuration for the selected print, filaments and printer. + auto config = get_preset_bundle()->full_config(); + // Validate the cummulative configuration. + auto valid = config.validate(); + if (!valid.empty()) { +// Slic3r::GUI::catch_error(this); + return; + } + // Ask user for the file name for the config file. + auto dlg = new wxFileDialog(this, _(L("Save configuration as:")), + !m_last_config.IsEmpty() ? get_dir_name(m_last_config) : get_app_config()->get_last_dir(), + !m_last_config.IsEmpty() ? get_base_name(m_last_config) : "config.ini", + FILE_WILDCARDS.at("ini"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT); + wxString file = dlg->ShowModal() == wxID_OK ? dlg->GetPath() : wxEmptyString; + dlg->Destroy(); + if (!file.IsEmpty()) { + get_app_config()->update_config_dir(get_dir_name(file)); + m_last_config = file; + config.save(file.ToStdString()); + } +} + +// Load a config file containing a Print, Filament & Printer preset. +void MainFrame::load_config_file(wxString file/* = wxEmptyString*/) +{ + if (file.IsEmpty()) { + if (!Slic3r::GUI::check_unsaved_changes()) + return; + auto dlg = new wxFileDialog(this, _(L("Select configuration to load:")), + !m_last_config.IsEmpty() ? get_dir_name(m_last_config) : get_app_config()->get_last_dir(), + "config.ini", "INI files (*.ini, *.gcode)|*.ini;*.INI;*.gcode;*.g", wxFD_OPEN | wxFD_FILE_MUST_EXIST); + if (dlg->ShowModal() != wxID_OK) + return; + file = dlg->GetPath(); + dlg->Destroy(); + } +// eval{ + get_preset_bundle()->load_config_file(file.ToStdString()); +// }; + // Dont proceed further if the config file cannot be loaded. +// if (Slic3r::GUI::catch_error(this)) +// return; + for (auto tab : m_options_tabs ) + tab.second->load_current_preset(); + get_app_config()->update_config_dir(get_dir_name(file)); + m_last_config = file; +} + +void MainFrame::export_configbundle() +{ + if (!Slic3r::GUI::check_unsaved_changes()) + return; + // validate current configuration in case it's dirty + auto valid = get_preset_bundle()->full_config().validate(); + if (!valid.empty()) { +// Slic3r::GUI::catch_error(this); + return; + } + // Ask user for a file name. + auto dlg = new wxFileDialog(this, _(L("Save presets bundle as:")), + !m_last_config.IsEmpty() ? get_dir_name(m_last_config) : get_app_config()->get_last_dir(), + "Slic3r_config_bundle.ini", + FILE_WILDCARDS.at("ini"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT); + wxString file = dlg->ShowModal() == wxID_OK ? dlg->GetPath() : wxEmptyString; + dlg->Destroy(); + if (!file.IsEmpty()) { + // Export the config bundle. + get_app_config()->update_config_dir(get_dir_name(file)); +// eval{ + get_preset_bundle()->export_configbundle(file.ToStdString()); +// }; +// Slic3r::GUI::catch_error(this); + } +} + +// Loading a config bundle with an external file name used to be used +// to auto - install a config bundle on a fresh user account, +// but that behavior was not documented and likely buggy. +void MainFrame::load_configbundle(wxString file/* = wxEmptyString, const bool reset_user_profile*/){ + if (!Slic3r::GUI::check_unsaved_changes()) + return; + if (file.IsEmpty()) { + auto dlg = new wxFileDialog(this, _(L("Select configuration to load:")), + !m_last_config.IsEmpty() ? get_dir_name(m_last_config) : get_app_config()->get_last_dir(), + "config.ini", FILE_WILDCARDS.at("ini"), wxFD_OPEN | wxFD_FILE_MUST_EXIST); + if (dlg->ShowModal() != wxID_OK) + return; + file = dlg->GetPath(); + dlg->Destroy(); + } + + get_app_config()->update_config_dir(get_dir_name(file)); + + auto presets_imported = 0; +// eval{ + presets_imported = get_preset_bundle()->load_configbundle(file.ToStdString()); +// }; +// Slic3r::GUI::catch_error(this) and return; + + // Load the currently selected preset into the GUI, update the preset selection box. + for (auto tab : m_options_tabs) + tab.second->load_current_preset(); + + const auto message = wxString::Format(_(L("%d presets successfully imported.")), presets_imported); + Slic3r::GUI::show_info(this, message, "Info"); +} + +// Load a provied DynamicConfig into the Print / Filament / Printer tabs, thus modifying the active preset. +// Also update the platter with the new presets. +void MainFrame::load_config(const DynamicPrintConfig& config){ + for (auto tab : m_options_tabs) + tab.second->load_config(config); +// if (m_plater) m_plater->on_config_change(config); +} + +void MainFrame::select_tab(size_t tab) const{ + m_tabpanel->SetSelection(tab); +} + +// Set a camera direction, zoom to all objects. +void MainFrame::select_view(const std::string& direction){ +// if (m_plater) +// m_plater->select_view(direction); +} + +wxMenuItem* MainFrame::append_menu_item(wxMenu* menu, + int id, + const wxString& string, + const wxString& description, + std::function cb, + const std::string& icon /*= ""*/) +{ + if (id == wxID_ANY) + id = wxNewId(); + auto item = menu->Append(id, string, description); + if (!icon.empty()) + item->SetBitmap(wxBitmap(Slic3r::var(icon), wxBITMAP_TYPE_PNG)); + menu->Bind(wxEVT_MENU, /*[cb](wxCommandEvent& event){cb; }*/cb); + return item; +} + +// Called after the Preferences dialog is closed and the program settings are saved. +// Update the UI based on the current preferences. +void MainFrame::update_ui_from_settings() +{ +// m_menu_item_reslice_now->Enable(get_app_config()->get("background_processing")); +// if (m_plater) m_plater->update_ui_from_settings(); + std::vector tab_names = { "print", "filament", "printer" }; + for (auto tab_name: tab_names) + m_options_tabs[tab_name]->update_ui_from_settings(); +} + + +std::string MainFrame::get_base_name(const wxString full_name) const +{ + return boost::filesystem::path(full_name).filename().string(); +} + +std::string MainFrame::get_dir_name(const wxString full_name) const +{ + return boost::filesystem::path(full_name).parent_path().string(); +} + + +} // GUI +} //Slic3r diff --git a/src/slic3r/GUI/MainFrame.hpp b/src/slic3r/GUI/MainFrame.hpp new file mode 100644 index 0000000000..2156db6912 --- /dev/null +++ b/src/slic3r/GUI/MainFrame.hpp @@ -0,0 +1,101 @@ +#ifndef slic3r_MainFrame_hpp_ +#define slic3r_MainFrame_hpp_ + +#include "PrintConfig.hpp" + +#include + +#include +#include + +class wxMenuBar; +class wxNotebook; +class wxPanel; +class wxMenu; +class wxProgressDialog; + +namespace Slic3r { + +class ProgressStatusBar; +class AppController; + +// #define _(s) Slic3r::GUI::I18N::translate((s)) + +namespace GUI +{ +class Tab; + +enum QuickSlice +{ + qsUndef, + qsReslice, + qsSaveAs, + qsExportSVG, + qsExportPNG +}; + +class MainFrame : public wxFrame +{ + bool m_no_plater; + bool m_loaded; + int m_lang_ch_event; + int m_preferences_event; + + wxString m_qs_last_input_file = wxEmptyString; + wxString m_qs_last_output_file = wxEmptyString; + wxString m_last_config = wxEmptyString; + + ProgressStatusBar* m_statusbar; + AppController* m_appController = nullptr; + std::map m_options_tabs; + + wxMenuItem* append_menu_item(wxMenu* menu, + int id, + const wxString& string, + const wxString& description, + std::function cb, + const std::string& icon = ""); + + wxMenuItem* m_menu_item_reslice_now = nullptr; + wxMenu* m_plater_menu = nullptr; + wxMenu* m_object_menu = nullptr; + wxMenu* m_viewMenu = nullptr; + + std::string get_base_name(const wxString full_name) const ; + std::string get_dir_name(const wxString full_name) const ; +public: + MainFrame() {} + MainFrame(const bool no_plater, const bool loaded); + ~MainFrame() {} + + + void init_tabpanel(); + void init_menubar(); + + void update_ui_from_settings(); + bool is_loaded() const { return m_loaded; } + bool is_last_input_file() const { return !m_qs_last_input_file.IsEmpty(); } + + void on_plater_selection_changed(const bool have_selection); + void slice_to_png(); + void quick_slice(const int qs = qsUndef); + void reslice_now(); + void repair_stl(); + void export_config(); + void load_config_file(wxString file = wxEmptyString); + void export_configbundle(); + void load_configbundle(wxString file = wxEmptyString); + void load_config(const DynamicPrintConfig& config); + void select_tab(size_t tab) const; + void select_view(const std::string& direction); + + + wxPanel* m_plater = nullptr; + wxNotebook* m_tabpanel = nullptr; + wxProgressDialog* m_progress_dialog = nullptr; +}; + +} // GUI +} //Slic3r + +#endif // slic3r_MainFrame_hpp_ \ No newline at end of file From e86f149cbd0ccb09b4477fb44c87ea39517199ad Mon Sep 17 00:00:00 2001 From: YuSanka Date: Thu, 20 Sep 2018 13:12:35 +0200 Subject: [PATCH 016/186] Moved back open_model to GUI_App --- src/slic3r/GUI/GUI.cpp | 2 +- src/slic3r/GUI/GUI_App.cpp | 30 ++++++++++++++++-------------- src/slic3r/GUI/GUI_App.hpp | 1 + 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/src/slic3r/GUI/GUI.cpp b/src/slic3r/GUI/GUI.cpp index 4201e33f74..80362533f2 100644 --- a/src/slic3r/GUI/GUI.cpp +++ b/src/slic3r/GUI/GUI.cpp @@ -545,7 +545,7 @@ void add_menus(wxMenuBar *menu, int event_preferences_changed, int event_languag } void open_model(wxWindow *parent, wxArrayString& input_files){ - auto dialog = new wxFileDialog(parent ? parent : GetTopWindow(), + auto dialog = new wxFileDialog(parent /*? parent : GetTopWindow()*/, _(L("Choose one or more files (STL/OBJ/AMF/3MF/PRUSA):")), g_AppConfig->get_last_dir(), "", MODEL_WILDCARD, wxFD_OPEN | wxFD_MULTIPLE | wxFD_FILE_MUST_EXIST); diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 2c1930a113..f1fa29e146 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include "Utils.hpp" #include "GUI.hpp" @@ -222,20 +223,21 @@ void GUI_App::update_ui_from_settings(){ mainframe->update_ui_from_settings(); } -// wxArrayString GUI::open_model(wxWindow* window){ -// auto dialog = new wxFileDialog(window ? window : GetTopWindow(), -// _(L("Choose one or more files (STL/OBJ/AMF/3MF/PRUSA):")), -// app_config->get_last_dir(), "", get_model_wildcard(), -// wxFD_OPEN | wxFD_MULTIPLE | wxFD_FILE_MUST_EXIST); -// if (dialog->ShowModal() != wxID_OK) { -// dialog->Destroy; -// return; -// } -// wxArrayString input_files; -// dialog->GetPaths(input_files); -// dialog->Destroy(); -// return input_files; -// } + +void GUI_App::open_model(wxWindow *parent, wxArrayString& input_files) +{ + auto dialog = new wxFileDialog(parent ? parent : GetTopWindow(), + _(L("Choose one or more files (STL/OBJ/AMF/3MF/PRUSA):")), + app_config->get_last_dir(), "", + MODEL_WILDCARD, wxFD_OPEN | wxFD_MULTIPLE | wxFD_FILE_MUST_EXIST); + if (dialog->ShowModal() != wxID_OK) { + dialog->Destroy(); + return; + } + + dialog->GetPaths(input_files); + dialog->Destroy(); +} void GUI_App::CallAfter(std::function cb) { diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 874c63fdee..6f09f03a9e 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -42,6 +42,7 @@ public: void recreate_GUI(); void system_info(); + void open_model(wxWindow *parent, wxArrayString& input_files); static bool catch_error(std::function cb, // wxMessageDialog* message_dialog, const std::string& err); From add45a8f6e656fdf4af2cfe5d5ce82457e08e2be Mon Sep 17 00:00:00 2001 From: bubnikv Date: Thu, 20 Sep 2018 16:48:13 +0200 Subject: [PATCH 017/186] Added C++ command line processing, thanks @alexrj and @loh --- CMakeLists.txt | 1 + src/libslic3r/Config.cpp | 97 +++++++++++++++++ src/libslic3r/Config.hpp | 29 +++-- src/libslic3r/Model.cpp | 12 +++ src/libslic3r/Model.hpp | 12 ++- src/libslic3r/PrintConfig.cpp | 133 ++++++++++++++++++++++- src/libslic3r/PrintConfig.hpp | 86 ++++++++++++++- src/libslic3r/PrintObject.cpp | 4 +- src/slic3r.cpp | 186 ++++++++++++++++++-------------- src/slic3r/GUI/ConfigWizard.cpp | 10 +- xs/xsp/Config.xsp | 2 +- 11 files changed, 467 insertions(+), 105 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 65a1240556..24fae45c6f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -241,6 +241,7 @@ add_subdirectory(resources/localization) # libslic3r, Slic3r GUI and the slic3r executable. add_subdirectory(src) +set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT slic3r) # Perl bindings, currently only used for the unit / integration tests of libslic3r. # Also runs the unit / integration tests. diff --git a/src/libslic3r/Config.cpp b/src/libslic3r/Config.cpp index e7442d7730..bf8be7feb4 100644 --- a/src/libslic3r/Config.cpp +++ b/src/libslic3r/Config.cpp @@ -566,6 +566,103 @@ ConfigOption* DynamicConfig::optptr(const t_config_option_key &opt_key, bool cre return opt; } +void DynamicConfig::read_cli(const std::vector &tokens, t_config_option_keys* extra) +{ + std::vector args; + // push a bogus executable name (argv[0]) + args.emplace_back(const_cast("")); + for (size_t i = 0; i < tokens.size(); ++ i) + args.emplace_back(const_cast(tokens[i].c_str())); + this->read_cli(args.size(), &args[0], extra); +} + +bool DynamicConfig::read_cli(int argc, char** argv, t_config_option_keys* extra) +{ + // cache the CLI option => opt_key mapping + std::map opts; + for (const auto &oit : this->def()->options) { + std::string cli = oit.second.cli; + cli = cli.substr(0, cli.find("=")); + boost::trim_right_if(cli, boost::is_any_of("!")); + std::vector tokens; + boost::split(tokens, cli, boost::is_any_of("|")); + for (const std::string &t : tokens) + opts[t] = oit.first; + } + + bool parse_options = true; + for (int i = 1; i < argc; ++ i) { + std::string token = argv[i]; + // Store non-option arguments in the provided vector. + if (! parse_options || ! boost::starts_with(token, "-")) { + extra->push_back(token); + continue; + } + // Stop parsing tokens as options when -- is supplied. + if (token == "--") { + parse_options = false; + continue; + } + // Remove leading dashes + boost::trim_left_if(token, boost::is_any_of("-")); + // Remove the "no-" prefix used to negate boolean options. + bool no = false; + if (boost::starts_with(token, "no-")) { + no = true; + boost::replace_first(token, "no-", ""); + } + // Read value when supplied in the --key=value form. + std::string value; + { + size_t equals_pos = token.find("="); + if (equals_pos != std::string::npos) { + value = token.substr(equals_pos+1); + token.erase(equals_pos); + } + } + // Look for the cli -> option mapping. + const auto it = opts.find(token); + if (it == opts.end()) { + printf("Warning: unknown option --%s\n", token.c_str()); + // instead of continuing, return false to caller + // to stop execution and print usage + return false; + //continue; + } + const t_config_option_key opt_key = it->second; + const ConfigOptionDef &optdef = this->def()->options.at(opt_key); + // If the option type expects a value and it was not already provided, + // look for it in the next token. + if (optdef.type != coBool && optdef.type != coBools && value.empty()) { + if (i == (argc-1)) { + printf("No value supplied for --%s\n", token.c_str()); + continue; + } + value = argv[++ i]; + } + // Store the option value. + const bool existing = this->has(opt_key); + if (ConfigOptionBool* opt = this->opt(opt_key, true)) { + opt->value = !no; + } else if (ConfigOptionBools* opt = this->opt(opt_key, true)) { + if (!existing) opt->values.clear(); // remove the default values + opt->values.push_back(!no); + } else if (ConfigOptionStrings* opt = this->opt(opt_key, true)) { + if (!existing) opt->values.clear(); // remove the default values + opt->deserialize(value, true); + } else if (ConfigOptionFloats* opt = this->opt(opt_key, true)) { + if (!existing) opt->values.clear(); // remove the default values + opt->deserialize(value, true); + } else if (ConfigOptionPoints* opt = this->opt(opt_key, true)) { + if (!existing) opt->values.clear(); // remove the default values + opt->deserialize(value, true); + } else { + this->set_deserialize(opt_key, value, true); + } + } + return true; +} + t_config_option_keys DynamicConfig::keys() const { t_config_option_keys keys; diff --git a/src/libslic3r/Config.hpp b/src/libslic3r/Config.hpp index e3cd14335a..2704bbcf3b 100644 --- a/src/libslic3r/Config.hpp +++ b/src/libslic3r/Config.hpp @@ -976,7 +976,7 @@ public: // Map from a config option name to its definition. // The definition does not carry an actual value of the config option, only its constant default value. // t_config_option_key is std::string -typedef std::map t_optiondef_map; +typedef std::map t_optiondef_map; // Definition of configuration values for the purpose of GUI presentation, editing, value mapping and config file handling. // The configuration definition is static: It does not carry the actual configuration values, @@ -984,18 +984,27 @@ typedef std::map t_optiondef_map; class ConfigDef { public: - t_optiondef_map options; - ~ConfigDef() { for (auto &opt : this->options) delete opt.second.default_value; } - ConfigOptionDef* add(const t_config_option_key &opt_key, ConfigOptionType type) { - ConfigOptionDef* opt = &this->options[opt_key]; - opt->type = type; - return opt; - } + t_optiondef_map options; + bool has(const t_config_option_key &opt_key) const { return this->options.count(opt_key) > 0; } const ConfigOptionDef* get(const t_config_option_key &opt_key) const { t_optiondef_map::iterator it = const_cast(this)->options.find(opt_key); return (it == this->options.end()) ? nullptr : &it->second; } + std::vector keys() const { + std::vector out; + out.reserve(options.size()); + for(auto const& kvp : options) + out.push_back(kvp.first); + return out; + } + +protected: + ConfigOptionDef* add(const t_config_option_key &opt_key, ConfigOptionType type) { + ConfigOptionDef* opt = &this->options[opt_key]; + opt->type = type; + return opt; + } }; // An abstract configuration store. @@ -1219,6 +1228,10 @@ public: bool opt_bool(const t_config_option_key &opt_key) const { return this->option(opt_key)->value != 0; } bool opt_bool(const t_config_option_key &opt_key, unsigned int idx) const { return this->option(opt_key)->get_at(idx) != 0; } + // Command line processing + void read_cli(const std::vector &tokens, t_config_option_keys* extra); + bool read_cli(int argc, char** argv, t_config_option_keys* extra); + private: typedef std::map t_options_map; t_options_map options; diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index ec7447352b..ed705e0077 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -113,6 +113,12 @@ Model Model::read_from_archive(const std::string &input_file, PresetBundle* bund return model; } +void Model::repair() +{ + for (ModelObject *o : this->objects) + o->repair(); +} + ModelObject* Model::add_object() { this->objects.emplace_back(new ModelObject(this)); @@ -886,6 +892,12 @@ void ModelObject::split(ModelObjectPtrs* new_objects) return; } +void ModelObject::repair() +{ + for (ModelVolume *v : this->volumes) + v->mesh.repair(); +} + // Called by Print::validate() from the UI thread. void ModelObject::check_instances_print_volume_state(const BoundingBoxf3& print_volume) { diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index 4c2356429a..3acf9b8d23 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -120,6 +120,7 @@ public: void translate(const Vec3d &vector) { this->translate(vector(0), vector(1), vector(2)); } void translate(coordf_t x, coordf_t y, coordf_t z); void scale(const Vec3d &versor); + void scale(const double s) { this->scale(Vec3d(s, s, s)); } void rotate(float angle, const Axis &axis); void rotate(float angle, const Vec3d& axis); void mirror(const Axis &axis); @@ -128,6 +129,7 @@ public: bool needed_repair() const; void cut(coordf_t z, Model* model) const; void split(ModelObjectPtrs* new_objects); + void repair(); // Called by Print::validate() from the UI thread. void check_instances_print_volume_state(const BoundingBoxf3& print_volume); @@ -190,11 +192,11 @@ public: // Split this volume, append the result to the object owning this volume. // Return the number of volumes created from this one. // This is useful to assign different materials to different volumes of an object. - size_t split(unsigned int max_extruders); + size_t split(unsigned int max_extruders); - ModelMaterial* assign_unique_material(); + ModelMaterial* assign_unique_material(); - void calculate_convex_hull(); + void calculate_convex_hull(); const TriangleMesh& get_convex_hull() const; // Helpers for loading / storing into AMF / 3MF files. @@ -325,6 +327,10 @@ public: static Model read_from_file(const std::string &input_file, bool add_default_instances = true); static Model read_from_archive(const std::string &input_file, PresetBundle* bundle, bool add_default_instances = true); + /// Repair the ModelObjects of the current Model. + /// This function calls repair function on each TriangleMesh of each model object volume + void repair(); + ModelObject* add_object(); ModelObject* add_object(const char *name, const char *path, const TriangleMesh &mesh); ModelObject* add_object(const char *name, const char *path, TriangleMesh &&mesh); diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index ed02f6d439..0612330691 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -2345,7 +2345,7 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va } } -PrintConfigDef print_config_def; +const PrintConfigDef print_config_def; DynamicPrintConfig* DynamicPrintConfig::new_from_defaults() { @@ -2601,4 +2601,135 @@ StaticPrintConfig::StaticCache SLAMaterialConf StaticPrintConfig::StaticCache SLAPrinterConfig::s_cache_SLAPrinterConfig; StaticPrintConfig::StaticCache SLAFullPrintConfig::s_cache_SLAFullPrintConfig; + +CLIConfigDef::CLIConfigDef() +{ + ConfigOptionDef *def; + + def = this->add("cut", coFloat); + def->label = L("Cut"); + def->tooltip = L("Cut model at the given Z."); + def->cli = "cut"; + def->default_value = new ConfigOptionFloat(0); + + def = this->add("export_3mf", coBool); + def->label = L("Export 3MF"); + def->tooltip = L("Slice the model and export slices as 3MF."); + def->cli = "export-3mf"; + def->default_value = new ConfigOptionBool(false); + + def = this->add("slice", coBool); + def->label = L("Slice"); + def->tooltip = L("Slice the model and export gcode."); + def->cli = "slice"; + def->default_value = new ConfigOptionBool(false); + + def = this->add("help", coBool); + def->label = L("Help"); + def->tooltip = L("Show this help."); + def->cli = "help"; + def->default_value = new ConfigOptionBool(false); + + def = this->add("gui", coBool); + def->label = L("Use GUI"); + def->tooltip = L("Start the Slic3r GUI."); + def->cli = "gui"; + def->default_value = new ConfigOptionBool(false); + + def = this->add("info", coBool); + def->label = L("Output Model Info"); + def->tooltip = L("Write information about the model to the console."); + def->cli = "info"; + def->default_value = new ConfigOptionBool(false); + + def = this->add("load", coStrings); + def->label = L("Load config file"); + def->tooltip = L("Load configuration from the specified file. It can be used more than once to load options from multiple files."); + def->cli = "load"; + def->default_value = new ConfigOptionStrings(); + + def = this->add("output", coString); + def->label = L("Output File"); + def->tooltip = L("The file where the output will be written (if not specified, it will be based on the input file)."); + def->cli = "output"; + def->default_value = new ConfigOptionString(""); + + def = this->add("rotate", coFloat); + def->label = L("Rotate"); + def->tooltip = L("Rotation angle around the Z axis in degrees (0-360, default: 0)."); + def->cli = "rotate"; + def->default_value = new ConfigOptionFloat(0); + + def = this->add("rotate_x", coFloat); + def->label = L("Rotate around X"); + def->tooltip = L("Rotation angle around the X axis in degrees (0-360, default: 0)."); + def->cli = "rotate-x"; + def->default_value = new ConfigOptionFloat(0); + + def = this->add("rotate_y", coFloat); + def->label = L("Rotate around Y"); + def->tooltip = L("Rotation angle around the Y axis in degrees (0-360, default: 0)."); + def->cli = "rotate-y"; + def->default_value = new ConfigOptionFloat(0); + + def = this->add("save", coString); + def->label = L("Save config file"); + def->tooltip = L("Save configuration to the specified file."); + def->cli = "save"; + def->default_value = new ConfigOptionString(); + + def = this->add("scale", coFloat); + def->label = L("Scale"); + def->tooltip = L("Scaling factor (default: 1)."); + def->cli = "scale"; + def->default_value = new ConfigOptionFloat(1); + +/* + def = this->add("scale_to_fit", coPoint3); + def->label = L("Scale to Fit"); + def->tooltip = L("Scale to fit the given volume."); + def->cli = "scale-to-fit"; + def->default_value = new ConfigOptionPoint3(Pointf3(0,0,0)); +*/ + + def = this->add("center", coPoint); + def->label = L("Center"); + def->tooltip = L("Center the print around the given center (default: 100, 100)."); + def->cli = "center"; + def->default_value = new ConfigOptionPoint(Vec2d(100,100)); +} + +const CLIConfigDef cli_config_def; +DynamicPrintAndCLIConfig::PrintAndCLIConfigDef DynamicPrintAndCLIConfig::s_def; + +std::ostream& print_cli_options(std::ostream& out) +{ + for (const auto& opt : cli_config_def.options) { + if (opt.second.cli.size() != 0) { + out << "\t" << std::left << std::setw(40) << std::string("--") + opt.second.cli; + out << "\t" << opt.second.tooltip << "\n"; + if (opt.second.default_value != nullptr) + out << "\t" << std::setw(40) << " " << "\t" << " (default: " << opt.second.default_value->serialize() << ")"; + out << "\n"; + } + } + std::cerr << std::endl; + return out; +} + +std::ostream& print_print_options(std::ostream& out) +{ + for (const auto& opt : print_config_def.options) { + if (opt.second.cli.size() != 0) { + out << "\t" << std::left << std::setw(40) << std::string("--") + opt.second.cli; + out << "\t" << opt.second.tooltip << "\n"; + if (opt.second.default_value != nullptr) + out << "\t" << std::setw(40) << " " << "\t" << " (default: " << opt.second.default_value->serialize() << ")"; + out << "\n"; + } + } + std::cerr << std::endl; + return out; +} + } diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index bc3b0ef490..0475f4ecba 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -165,7 +165,7 @@ private: // The one and only global definition of SLic3r configuration options. // This definition is constant. -extern PrintConfigDef print_config_def; +extern const PrintConfigDef print_config_def; // Slic3r dynamic configuration, used to override the configuration // per object, per modification volume or per printing material. @@ -968,6 +968,88 @@ protected: #undef STATIC_PRINT_CONFIG_CACHE_DERIVED #undef OPT_PTR -} +class CLIConfigDef : public ConfigDef +{ +public: + CLIConfigDef(); +}; + +extern const CLIConfigDef cli_config_def; + +#define OPT_PTR(KEY) if (opt_key == #KEY) return &this->KEY + +class CLIConfig : public virtual ConfigBase, public StaticConfig +{ +public: + ConfigOptionFloat cut; + ConfigOptionBool export_3mf; + ConfigOptionBool gui; + ConfigOptionBool info; + ConfigOptionBool help; + ConfigOptionStrings load; + ConfigOptionString output; + ConfigOptionFloat rotate; + ConfigOptionFloat rotate_x; + ConfigOptionFloat rotate_y; + ConfigOptionString save; + ConfigOptionFloat scale; +// ConfigOptionPoint3 scale_to_fit; + ConfigOptionPoint center; + ConfigOptionBool slice; + + CLIConfig() : ConfigBase(), StaticConfig() + { + this->set_defaults(); + }; + + // Overrides ConfigBase::def(). Static configuration definition. Any value stored into this ConfigBase shall have its definition here. + const ConfigDef* def() const override { return &cli_config_def; } + + ConfigOption* optptr(const t_config_option_key &opt_key, bool create = false) override + { + OPT_PTR(cut); + OPT_PTR(export_3mf); + OPT_PTR(gui); + OPT_PTR(help); + OPT_PTR(info); + OPT_PTR(load); + OPT_PTR(output); + OPT_PTR(rotate); + OPT_PTR(rotate_x); + OPT_PTR(rotate_y); + OPT_PTR(save); + OPT_PTR(scale); +// OPT_PTR(scale_to_fit); + OPT_PTR(slice); + return NULL; + } +}; + +#undef OPT_PTR + +class DynamicPrintAndCLIConfig : public DynamicPrintConfig +{ +public: + DynamicPrintAndCLIConfig() { this->apply(FullPrintConfig::defaults()); this->apply(CLIConfig()); } + DynamicPrintAndCLIConfig(const DynamicPrintAndCLIConfig &other) : DynamicPrintConfig(other) {} + + // Overrides ConfigBase::def(). Static configuration definition. Any value stored into this ConfigBase shall have its definition here. + const ConfigDef* def() const override { return &s_def; } + +private: + class PrintAndCLIConfigDef : public PrintConfigDef + { + public: + PrintAndCLIConfigDef() { this->options.insert(cli_config_def.options.begin(), cli_config_def.options.end()); } + }; + static PrintAndCLIConfigDef s_def; +}; + +/// Iterate through all of the print options and write them to a stream. +std::ostream& print_print_options(std::ostream& out); +/// Iterate through all of the CLI options and write them to a stream. +std::ostream& print_cli_options(std::ostream& out); + +} // namespace Slic3r #endif diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index ef2364dc41..280b30e533 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -1591,7 +1591,7 @@ std::vector PrintObject::slice_support_enforcers() const std::vector zs; zs.reserve(this->layers().size()); for (const Layer *l : this->layers()) - zs.emplace_back(l->slice_z); + zs.emplace_back((float)l->slice_z); return this->_slice_volumes(zs, volumes); } @@ -1604,7 +1604,7 @@ std::vector PrintObject::slice_support_blockers() const std::vector zs; zs.reserve(this->layers().size()); for (const Layer *l : this->layers()) - zs.emplace_back(l->slice_z); + zs.emplace_back((float)l->slice_z); return this->_slice_volumes(zs, volumes); } diff --git a/src/slic3r.cpp b/src/slic3r.cpp index 8174ba0a2b..5840ac0c1d 100644 --- a/src/slic3r.cpp +++ b/src/slic3r.cpp @@ -1,7 +1,12 @@ +//#include "ConfigBase.hpp" #include "Config.hpp" #include "Geometry.hpp" +//#include "IO.hpp" #include "Model.hpp" +//#include "SLAPrint.hpp" +#include "Print.hpp" #include "TriangleMesh.hpp" +#include "Format/3mf.hpp" #include "libslic3r.h" #include #include @@ -12,6 +17,9 @@ #include #include +#ifdef USE_WX +// #include "GUI/GUI.hpp" +#endif #include "slic3r/GUI/GUI.hpp" using namespace Slic3r; @@ -87,37 +95,55 @@ void MyFrame::OnHello(wxCommandEvent& event) wxLogMessage("Hello world from wxWidgets!"); } +/// utility function for displaying CLI usage +void printUsage(); -#if 1 -int -main(int argc, char **argv) +using namespace Slic3r; + +int main(int argc, char **argv) { - // Convert arguments to UTF-8 (needed on Windows). - // argv then points to memory owned by a. + // Convert arguments to UTF-8 (needed on Windows). argv then points to memory owned by a. boost::nowide::args a(argc, argv); - -#if 0 + // parse all command line options into a DynamicConfig - ConfigDef config_def; - config_def.merge(cli_config_def); - config_def.merge(print_config_def); - DynamicConfig config(&config_def); + DynamicPrintAndCLIConfig config; t_config_option_keys input_files; - config.read_cli(argc, argv, &input_files); - + // if any option is unsupported, print usage and abort immediately + if (! config.read_cli(argc, argv, &input_files)) { + printUsage(); + return 0; + } + // apply command line options to a more handy CLIConfig CLIConfig cli_config; cli_config.apply(config, true); DynamicPrintConfig print_config; - + +#if 1 + MyApp *gui = new MyApp(); + + MyApp::SetInstance(gui); + wxEntry(argc, argv); +#endif + +#ifdef USE_WX + if (cli_config.gui) { + GUI::App *gui = new GUI::App(); + GUI::App::SetInstance(gui); + wxEntry(argc, argv); + } +#else + if (cli_config.gui) { + std::cout << "GUI support has not been built." << "\n"; + } +#endif // load config files supplied via --load for (const std::string &file : cli_config.load.values) { if (!boost::filesystem::exists(file)) { boost::nowide::cout << "No such file: " << file << std::endl; exit(1); } - DynamicPrintConfig c; try { c.load(file); @@ -135,12 +161,13 @@ main(int argc, char **argv) print_config.normalize(); // write config if requested - if (!cli_config.save.value.empty()) print_config.save(cli_config.save.value); - + if (! cli_config.save.value.empty()) + print_config.save(cli_config.save.value); + // read input file(s) if any std::vector models; for (const t_config_option_key &file : input_files) { - if (!boost::filesystem::exists(file)) { + if (! boost::filesystem::exists(file)) { boost::nowide::cerr << "No such file: " << file << std::endl; exit(1); } @@ -162,9 +189,10 @@ main(int argc, char **argv) // apply command line transform options for (ModelObject* o : model.objects) { +/* if (cli_config.scale_to_fit.is_positive_volume()) o->scale_to_fit(cli_config.scale_to_fit.value); - +*/ // TODO: honor option order? o->scale(cli_config.scale.value); o->rotate(Geometry::deg2rad(cli_config.rotate_x.value), X); @@ -175,87 +203,79 @@ main(int argc, char **argv) // TODO: handle --merge models.push_back(model); } + if (cli_config.help) { + printUsage(); + return 0; + } for (Model &model : models) { if (cli_config.info) { // --info works on unrepaired model model.print_info(); - } else if (cli_config.export_obj) { + } else if (cli_config.export_3mf) { std::string outfile = cli_config.output.value; - if (outfile.empty()) outfile = model.objects.front()->input_file + ".obj"; - - TriangleMesh mesh = model.mesh(); - mesh.repair(); - IO::OBJ::write(mesh, outfile); - boost::nowide::cout << "File exported to " << outfile << std::endl; - } else if (cli_config.export_pov) { - std::string outfile = cli_config.output.value; - if (outfile.empty()) outfile = model.objects.front()->input_file + ".pov"; - - TriangleMesh mesh = model.mesh(); - mesh.repair(); - IO::POV::write(mesh, outfile); - boost::nowide::cout << "File exported to " << outfile << std::endl; - } else if (cli_config.export_svg) { - std::string outfile = cli_config.output.value; - if (outfile.empty()) outfile = model.objects.front()->input_file + ".svg"; - - SLAPrint print(&model); - print.config.apply(print_config, true); - print.slice(); - print.write_svg(outfile); - boost::nowide::cout << "SVG file exported to " << outfile << std::endl; - } else if (cli_config.cut_x > 0 || cli_config.cut_y > 0 || cli_config.cut > 0) { + if (outfile.empty()) outfile = model.objects.front()->input_file; + // Check if the file is already a 3mf. + if(outfile.substr(outfile.find_last_of('.'), outfile.length()) == ".3mf") + outfile = outfile.substr(0, outfile.find_last_of('.')) + "_2" + ".3mf"; + else + // Remove the previous extension and add .3mf extention. + outfile = outfile.substr(0, outfile.find_last_of('.')) + ".3mf"; + store_3mf(outfile.c_str(), &model, nullptr, false); + boost::nowide::cout << "File file exported to " << outfile << std::endl; + } else if (cli_config.cut > 0) { model.repair(); - model.translate(0, 0, -model.bounding_box().min.z); - - if (!model.objects.empty()) { - // FIXME: cut all objects + model.translate(0, 0, - model.bounding_box().min(2)); + if (! model.objects.empty()) { Model out; - if (cli_config.cut_x > 0) { - model.objects.front()->cut(X, cli_config.cut_x, &out); - } else if (cli_config.cut_y > 0) { - model.objects.front()->cut(Y, cli_config.cut_y, &out); - } else { - model.objects.front()->cut(Z, cli_config.cut, &out); - } - + model.objects.front()->cut(cli_config.cut, &out); ModelObject &upper = *out.objects[0]; ModelObject &lower = *out.objects[1]; - - if (upper.facets_count() > 0) { - TriangleMesh m = upper.mesh(); - IO::STL::write(m, upper.input_file + "_upper.stl"); - } - if (lower.facets_count() > 0) { - TriangleMesh m = lower.mesh(); - IO::STL::write(m, lower.input_file + "_lower.stl"); - } + // Use the input name and trim off the extension. + std::string outfile = cli_config.output.value; + if (outfile.empty()) + outfile = model.objects.front()->input_file; + outfile = outfile.substr(0, outfile.find_last_of('.')); + std::cerr << outfile << "\n"; + if (upper.facets_count() > 0) + upper.mesh().write_binary((outfile + "_upper.stl").c_str()); + if (lower.facets_count() > 0) + lower.mesh().write_binary((outfile + "_lower.stl").c_str()); } - } else if (cli_config.cut_grid.value.x > 0 && cli_config.cut_grid.value.y > 0) { - TriangleMesh mesh = model.mesh(); - mesh.repair(); - - TriangleMeshPtrs meshes = mesh.cut_by_grid(cli_config.cut_grid.value); - size_t i = 0; - for (TriangleMesh* m : meshes) { - std::ostringstream ss; - ss << model.objects.front()->input_file << "_" << i++ << ".stl"; - IO::STL::write(*m, ss.str()); - delete m; + } else if (cli_config.slice) { + std::string outfile = cli_config.output.value; + Print print; + model.arrange_objects(print.config().min_object_distance()); + model.center_instances_around_point(cli_config.center); + if (outfile.empty()) outfile = model.objects.front()->input_file + ".gcode"; + print.apply_config(print_config); + for (auto* mo : model.objects) { + print.auto_assign_extruders(mo); + print.add_model_object(mo); } + print.validate(); + print.export_gcode(outfile, nullptr); } else { boost::nowide::cerr << "error: command not supported" << std::endl; return 1; } } -#endif - - MyApp *gui = new MyApp(); - - MyApp::SetInstance(gui); - wxEntry(argc, argv); return 0; } -#endif + +void printUsage() +{ + std::cout << "Slic3r " << SLIC3R_VERSION << " is a STL-to-GCODE translator for RepRap 3D printers" << "\n" + << "written by Alessandro Ranellucci - http://slic3r.org/ - https://github.com/slic3r/Slic3r" << "\n" +// << "Git Version " << BUILD_COMMIT << "\n\n" + << "Usage: ./slic3r [ OPTIONS ] [ file.stl ] [ file2.stl ] ..." << "\n"; + // CLI Options + std::cout << "** CLI OPTIONS **\n"; + print_cli_options(boost::nowide::cout); + std::cout << "****\n"; + // Print options + std::cout << "** PRINT OPTIONS **\n"; + print_print_options(boost::nowide::cout); + std::cout << "****\n"; +} diff --git a/src/slic3r/GUI/ConfigWizard.cpp b/src/slic3r/GUI/ConfigWizard.cpp index e784d85256..e7b1868d01 100644 --- a/src/slic3r/GUI/ConfigWizard.cpp +++ b/src/slic3r/GUI/ConfigWizard.cpp @@ -380,7 +380,7 @@ void PageVendors::on_variant_checked() PageFirmware::PageFirmware(ConfigWizard *parent) : ConfigWizardPage(parent, _(L("Firmware Type")), _(L("Firmware"))), - gcode_opt(print_config_def.options["gcode_flavor"]), + gcode_opt(*print_config_def.get("gcode_flavor")), gcode_picker(nullptr) { append_text(_(L("Choose the type of firmware used by your printer."))); @@ -440,13 +440,13 @@ PageDiameters::PageDiameters(ConfigWizard *parent) : { spin_nozzle->SetDigits(2); spin_nozzle->SetIncrement(0.1); - const auto &def_nozzle = print_config_def.options["nozzle_diameter"]; + const auto &def_nozzle = *print_config_def.get("nozzle_diameter"); auto *default_nozzle = dynamic_cast(def_nozzle.default_value); spin_nozzle->SetValue(default_nozzle != nullptr && default_nozzle->size() > 0 ? default_nozzle->get_at(0) : 0.5); spin_filam->SetDigits(2); spin_filam->SetIncrement(0.25); - const auto &def_filam = print_config_def.options["filament_diameter"]; + const auto &def_filam = *print_config_def.get("filament_diameter"); auto *default_filam = dynamic_cast(def_filam.default_value); spin_filam->SetValue(default_filam != nullptr && default_filam->size() > 0 ? default_filam->get_at(0) : 3.0); @@ -490,13 +490,13 @@ PageTemperatures::PageTemperatures(ConfigWizard *parent) : spin_bed(new wxSpinCtrlDouble(this, wxID_ANY)) { spin_extr->SetIncrement(5.0); - const auto &def_extr = print_config_def.options["temperature"]; + const auto &def_extr = *print_config_def.get("temperature"); spin_extr->SetRange(def_extr.min, def_extr.max); auto *default_extr = dynamic_cast(def_extr.default_value); spin_extr->SetValue(default_extr != nullptr && default_extr->size() > 0 ? default_extr->get_at(0) : 200); spin_bed->SetIncrement(5.0); - const auto &def_bed = print_config_def.options["bed_temperature"]; + const auto &def_bed = *print_config_def.get("bed_temperature"); spin_bed->SetRange(def_bed.min, def_bed.max); auto *default_bed = dynamic_cast(def_bed.default_value); spin_bed->SetValue(default_bed != nullptr && default_bed->size() > 0 ? default_bed->get_at(0) : 0); diff --git a/xs/xsp/Config.xsp b/xs/xsp/Config.xsp index b8ad84ba46..d5d2958397 100644 --- a/xs/xsp/Config.xsp +++ b/xs/xsp/Config.xsp @@ -137,7 +137,7 @@ PROTOTYPES: DISABLE SV* print_config_def() CODE: - t_optiondef_map &def = Slic3r::print_config_def.options; + t_optiondef_map &def = *const_cast(&Slic3r::print_config_def.options); HV* options_hv = newHV(); for (t_optiondef_map::iterator oit = def.begin(); oit != def.end(); ++oit) { From 8b582bbcd1f1f470eee468c658e70bc67d910ae7 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Fri, 21 Sep 2018 01:33:41 +0200 Subject: [PATCH 018/186] Menu_bar and preset_tabs are in main window now --- src/slic3r/GUI/GUI.cpp | 22 ++- src/slic3r/GUI/GUI.hpp | 3 +- src/slic3r/GUI/GUI_App.cpp | 245 ++++++++++++++++++++--- src/slic3r/GUI/GUI_App.hpp | 30 ++- src/slic3r/GUI/GUI_ObjectParts.cpp | 18 +- src/slic3r/GUI/MainFrame.cpp | 283 +++++++++++++++------------ src/slic3r/GUI/MainFrame.hpp | 21 +- src/slic3r/GUI/OptionsGroup.cpp | 8 +- src/slic3r/GUI/ProgressStatusBar.cpp | 2 +- src/slic3r/GUI/Tab.cpp | 43 ++-- src/slic3r/Utils/PresetUpdater.cpp | 31 +-- src/slic3r/Utils/PresetUpdater.hpp | 2 +- 12 files changed, 489 insertions(+), 219 deletions(-) diff --git a/src/slic3r/GUI/GUI.cpp b/src/slic3r/GUI/GUI.cpp index 80362533f2..176bb794d9 100644 --- a/src/slic3r/GUI/GUI.cpp +++ b/src/slic3r/GUI/GUI.cpp @@ -128,9 +128,10 @@ wxColour g_color_label_modified; wxColour g_color_label_sys; wxColour g_color_label_default; +// #ys_FIXME_for_delete std::vector g_tabs_list; -wxLocale* g_wxLocale; +wxLocale* g_wxLocale {nullptr}; wxFont g_small_font; wxFont g_bold_font; @@ -346,6 +347,11 @@ bool select_language(wxArrayString & names, return false; } +wxLocale* get_locale() { + return g_wxLocale; +} + +// #ys_FIXME_for_delete bool load_language() { wxString language = wxEmptyString; @@ -428,7 +434,8 @@ enum ConfigMenuIDs { ConfigMenuFlashFirmware, ConfigMenuCnt, }; - + +// #ys_FIXME_for_delete ConfigMenuIDs get_view_mode() { if (!g_AppConfig->has("view_mode")) @@ -439,7 +446,7 @@ ConfigMenuIDs get_view_mode() } static wxString dots("…", wxConvUTF8); - +// #ys_FIXME_for_delete void add_config_menu(wxMenuBar *menu, int event_preferences_changed, int event_language_change) { auto local_menu = new wxMenu(); @@ -560,6 +567,7 @@ void open_model(wxWindow *parent, wxArrayString& input_files){ // This is called when closing the application, when loading a config file or when starting the config wizard // to notify the user whether he is aware that some preset changes will be lost. +// #ys_FIXME_for_delete bool check_unsaved_changes() { std::string dirty; @@ -636,8 +644,8 @@ std::vector preset_tabs = { { "filament", nullptr, ptFFF }, { "sla_material", nullptr, ptSLA } }; -const std::vector& get_preset_tabs() { - return preset_tabs; +std::vector* get_preset_tabs() { + return &preset_tabs; } Tab* get_tab(const std::string& name) @@ -781,7 +789,7 @@ void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt int i = 0;//no reason, just experiment } } - +// #ys_FIXME_for_delete void add_created_tab(Tab* panel, int event_value_change, int event_presets_changed) { panel->create_preset_tab(g_PresetBundle); @@ -1212,7 +1220,7 @@ bool is_expert_mode(){ ConfigOptionsGroup* get_optgroup(size_t i) { - return m_optgroups[i].get(); + return m_optgroups.empty() ? nullptr : m_optgroups[i].get(); } std::vector >& get_optgroups() { diff --git a/src/slic3r/GUI/GUI.hpp b/src/slic3r/GUI/GUI.hpp index 878689bf30..94be072214 100644 --- a/src/slic3r/GUI/GUI.hpp +++ b/src/slic3r/GUI/GUI.hpp @@ -146,7 +146,7 @@ wxWindow* get_right_panel(); const size_t& label_width(); Tab* get_tab(const std::string& name); -const std::vector& get_preset_tabs(); +std::vector* get_preset_tabs(); extern void add_menus(wxMenuBar *menu, int event_preferences_changed, int event_language_change); @@ -189,6 +189,7 @@ void warning_catcher(wxWindow* parent, const wxString& message); void set_print_callback_event(Print *print, int id); // load language saved at application config +wxLocale* get_locale(); bool load_language(); // save language at application config void save_language(); diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index f1fa29e146..282391d429 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -18,56 +18,68 @@ #include "3DScene.hpp" #include "../Utils/PresetUpdater.hpp" +#include "ConfigWizard_private.hpp" +#include "slic3r/Config/Snapshot.hpp" +#include "ConfigSnapshotDialog.hpp" +#include "FirmwareDialog.hpp" +#include "Preferences.hpp" +#include "Tab.hpp" namespace Slic3r { namespace GUI { -// IMPLEMENT_APP(GUI_App) +IMPLEMENT_APP(GUI_App) bool GUI_App::OnInit() { SetAppName("Slic3rPE"); SetAppDisplayName("Slic3r Prusa Edition"); - // Slic3r::debugf "wxWidgets version %s, Wx version %s\n", &Wx::wxVERSION_STRING, $Wx::VERSION; - // +// 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" -// datadir.empty() ? -// Slic3r::set_data_dir(wxStandardPaths::Get().GetUserDataDir().ToStdString()) : -// Slic3r::set_data_dir(datadir); + datadir.empty() ? + Slic3r::set_data_dir(wxStandardPaths::Get().GetUserDataDir().ToStdString()) : + Slic3r::set_data_dir(datadir); // set_wxapp(this); // #ys_FIXME -// app_config = new AppConfig(); + // #ys_FIXME temporary workaround + if (var_dir().empty()) + set_var_dir("c:\\src\\Slic3r_TMP\\resources\\icons"); + if (localization_dir().empty()) + set_local_dir("c:\\src\\Slic3r_TMP\\resources\\localization"); + + app_config = new AppConfig(); // set_app_config(app_config);// #ys_FIXME -// preset_bundle = new PresetBundle(); + preset_bundle = new PresetBundle(); // set_preset_bundle(preset_bundle);// #ys_FIXME // just checking for existence of Slic3r::data_dir is not enough : it may be an empty directory // supplied as argument to --datadir; in that case we should still run the wizard // eval{ -// preset_bundle->setup_directories(); + preset_bundle->setup_directories(); // }; // if ($@) { // warn $@ . "\n"; // fatal_error(undef, $@); // } -// app_conf_exists = app_config->exists(); + app_conf_exists = app_config->exists(); // load settings -// if (app_conf_exists) app_config->load(); - // app_config->set("version", Slic3r::VERSION); -// app_config->save(); + if (app_conf_exists) app_config->load(); + app_config->set("version", "Slic3r_VERSION"/*Slic3r::VERSION*/); + app_config->save(); -// preset_updater = new PresetUpdater(VERSION_ONLINE_EVENT); - // set_preset_updater(preset_updater); // #ys_FIXME +// preset_updater = new PresetUpdater(); +// set_preset_updater(preset_updater); // #ys_FIXME -// Slic3r::GUI::load_language(); + load_language(); // Suppress the '- default -' presets. -// preset_bundle->set_default_suppressed(app_config->get("no_defaults").empty() ? false : true); + preset_bundle->set_default_suppressed(app_config->get("no_defaults").empty() ? false : true); // eval{ -// preset_bundle->load_presets(*app_config); + preset_bundle->load_presets(*app_config); // }; // if ($@) { // warn $@ . "\n"; @@ -133,12 +145,6 @@ bool GUI_App::OnInit() // // #ys_FIXME All of this should to be removed - // # The following event is emited by the C++ menu implementation of application language change. - // EVT_COMMAND($self, -1, $LANGUAGE_CHANGE_EVENT, sub{ - // print STDERR "LANGUAGE_CHANGE_EVENT\n"; - // $self->recreate_GUI; - // }); - // // # The following event is emited by the C++ menu implementation of preferences change. // EVT_COMMAND($self, -1, $PREFERENCES_EVENT, sub{ // $self->update_ui_from_settings; @@ -154,7 +160,6 @@ bool GUI_App::OnInit() // }); mainframe->Show(true); - return true; } @@ -249,13 +254,13 @@ void GUI_App::CallAfter(std::function cb) callback_register.unlock(); } -wxMenuItem* GUI_App::append_menu_item(wxMenu* menu, - int id, - const wxString& string, - const wxString& description, - const std::string& icon, - std::function cb, - wxItemKind kind/* = wxITEM_NORMAL*/) +wxMenuItem* GUI_App::append_menu_item( wxMenu* menu, + int id, + const wxString& string, + const wxString& description, + const std::string& icon, + std::function cb, + wxItemKind kind/* = wxITEM_NORMAL*/) { if (id == wxID_ANY) id = wxNewId(); @@ -322,6 +327,182 @@ void GUI_App::restore_window_pos(wxTopLevelWindow* window, const std::string& na window->Maximize(); } +bool GUI_App::load_language() +{ + wxString language = wxEmptyString; + if (app_config->has("translation_language")) + language = app_config->get("translation_language"); + + if (language.IsEmpty()) + return false; + wxArrayString names; + wxArrayLong identifiers; + get_installed_languages(names, identifiers); + for (size_t i = 0; i < identifiers.Count(); i++) + { + if (wxLocale::GetLanguageCanonicalName(identifiers[i]) == language) + { + auto locale = get_locale(); + locale = new wxLocale; + locale->Init(identifiers[i]); + locale->AddCatalogLookupPathPrefix(wxPathOnly(localization_dir())); + locale->AddCatalog(GetAppName()); + wxSetlocale(LC_NUMERIC, "C"); + Preset::update_suffix_modified(); + return true; + } + } + return false; +} + +ConfigMenuIDs GUI_App::get_view_mode() +{ + if (!app_config->has("view_mode")) + return ConfigMenuModeSimple; + + const auto mode = app_config->get("view_mode"); + return mode == "expert" ? ConfigMenuModeExpert : ConfigMenuModeSimple; +} + +static wxString dots("…", wxConvUTF8); + +void GUI_App::add_config_menu(wxMenuBar *menu) +{ + auto local_menu = new wxMenu(); + wxWindowID config_id_base = wxWindow::NewControlId((int)ConfigMenuCnt); + + const auto config_wizard_name = _(ConfigWizard::name().wx_str()); + const auto config_wizard_tooltip = wxString::Format(_(L("Run %s")), config_wizard_name); + // Cmd+, is standard on OS X - what about other operating systems? + local_menu->Append(config_id_base + ConfigMenuWizard, config_wizard_name + dots, config_wizard_tooltip); + local_menu->Append(config_id_base + ConfigMenuSnapshots, _(L("Configuration Snapshots")) + dots, _(L("Inspect / activate configuration snapshots"))); + local_menu->Append(config_id_base + ConfigMenuTakeSnapshot, _(L("Take Configuration Snapshot")), _(L("Capture a configuration snapshot"))); + // local_menu->Append(config_id_base + ConfigMenuUpdate, _(L("Check for updates")), _(L("Check for configuration updates"))); + local_menu->AppendSeparator(); + local_menu->Append(config_id_base + ConfigMenuPreferences, _(L("Preferences")) + dots + "\tCtrl+,", _(L("Application preferences"))); + local_menu->AppendSeparator(); + auto mode_menu = new wxMenu(); + mode_menu->AppendRadioItem(config_id_base + ConfigMenuModeSimple, _(L("&Simple")), _(L("Simple View Mode"))); + mode_menu->AppendRadioItem(config_id_base + ConfigMenuModeExpert, _(L("&Expert")), _(L("Expert View Mode"))); + mode_menu->Check(config_id_base + get_view_mode(), true); + local_menu->AppendSubMenu(mode_menu, _(L("&Mode")), _(L("Slic3r View Mode"))); + local_menu->AppendSeparator(); + local_menu->Append(config_id_base + ConfigMenuLanguage, _(L("Change Application Language"))); + local_menu->AppendSeparator(); + local_menu->Append(config_id_base + ConfigMenuFlashFirmware, _(L("Flash printer firmware")), _(L("Upload a firmware image into an Arduino based printer"))); + // TODO: for when we're able to flash dictionaries + // local_menu->Append(config_id_base + FirmwareMenuDict, _(L("Flash language file")), _(L("Upload a language dictionary file into a Prusa printer"))); + + local_menu->Bind(wxEVT_MENU, [this, config_id_base](wxEvent &event){ + switch (event.GetId() - config_id_base) { + case ConfigMenuWizard: + config_wizard(ConfigWizard::RR_USER); + break; + case ConfigMenuTakeSnapshot: + // Take a configuration snapshot. + if (check_unsaved_changes()) { + wxTextEntryDialog dlg(nullptr, _(L("Taking configuration snapshot")), _(L("Snapshot name"))); + if (dlg.ShowModal() == wxID_OK) + app_config->set("on_snapshot", + Slic3r::GUI::Config::SnapshotDB::singleton().take_snapshot( + *app_config, Slic3r::GUI::Config::Snapshot::SNAPSHOT_USER, dlg.GetValue().ToUTF8().data()).id); + } + break; + case ConfigMenuSnapshots: + if (check_unsaved_changes()) { + std::string on_snapshot; + if (Config::SnapshotDB::singleton().is_on_snapshot(*app_config)) + on_snapshot = app_config->get("on_snapshot"); + ConfigSnapshotDialog dlg(Slic3r::GUI::Config::SnapshotDB::singleton(), on_snapshot); + dlg.ShowModal(); + if (!dlg.snapshot_to_activate().empty()) { + if (!Config::SnapshotDB::singleton().is_on_snapshot(*app_config)) + Config::SnapshotDB::singleton().take_snapshot(*app_config, Config::Snapshot::SNAPSHOT_BEFORE_ROLLBACK); + app_config->set("on_snapshot", + Config::SnapshotDB::singleton().restore_snapshot(dlg.snapshot_to_activate(), *app_config).id); + preset_bundle->load_presets(*app_config); + // Load the currently selected preset into the GUI, update the preset selection box. + load_current_presets(); + } + } + break; + case ConfigMenuPreferences: + { +// PreferencesDialog dlg(mainframe, event_preferences_changed); +// dlg.ShowModal(); + break; + } + case ConfigMenuLanguage: + { + wxArrayString names; + wxArrayLong identifiers; + get_installed_languages(names, identifiers); + if (select_language(names, identifiers)) { + save_language(); + show_info(mainframe->m_tabpanel, _(L("Application will be restarted")), _(L("Attention!"))); + _3DScene::remove_all_canvases();// remove all canvas before recreate GUI + recreate_GUI(); + } + break; + } + case ConfigMenuFlashFirmware: + FirmwareDialog::run(mainframe); + break; + default: + break; + } + }); + mode_menu->Bind(wxEVT_MENU, [this, config_id_base](wxEvent& event) { + std::string mode = event.GetId() - config_id_base == ConfigMenuModeExpert ? + "expert" : "simple"; + app_config->set("view_mode", mode); + app_config->save(); + update_mode(); + }); + menu->Append(local_menu, _(L("&Configuration"))); +} + +// This is called when closing the application, when loading a config file or when starting the config wizard +// to notify the user whether he is aware that some preset changes will be lost. +bool GUI_App::check_unsaved_changes() +{ + std::string dirty; + for (Tab *tab : tabs_list) + if (tab->current_preset_is_dirty()) + if (dirty.empty()) + dirty = tab->name(); + else + dirty += std::string(", ") + tab->name(); + if (dirty.empty()) + // No changes, the application may close or reload presets. + return true; + // Ask the user. + auto dialog = new wxMessageDialog(mainframe, + _(L("You have unsaved changes ")) + dirty + _(L(". Discard changes and continue anyway?")), + _(L("Unsaved Presets")), + wxICON_QUESTION | wxYES_NO | wxNO_DEFAULT); + return dialog->ShowModal() == wxID_YES; +} + +wxNotebook* GUI_App::tab_panel() const +{ + return mainframe->m_tabpanel; +} + +// std::vector preset_tabs = { +// { "print", nullptr, ptFFF }, +// { "filament", nullptr, ptFFF }, +// { "sla_material", nullptr, ptSLA } +// }; +// +// Tab* GUI_App::get_tab(const std::string& name) +// { +// std::vector::iterator it = std::find_if(preset_tabs.begin(), preset_tabs.end(), +// [name](PresetTab& tab){ return name == tab.name; }); +// return it != preset_tabs.end() ? it->panel : nullptr; +// } + + // static method accepting a wxWindow object as first parameter // void warning_catcher{ // my($self, $message_dialog) = @_; diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 6f09f03a9e..880b5039f4 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -3,7 +3,7 @@ #include // #include -// #include "PrintConfig.hpp" +#include "PrintConfig.hpp" // #include "../../libslic3r/Utils.hpp" // #include "GUI.hpp" @@ -13,7 +13,9 @@ #include class wxMenuItem; +class wxMenuBar; class wxTopLevelWindow; +class wxNotebook; namespace Slic3r { class AppConfig; @@ -22,7 +24,21 @@ class PresetUpdater; namespace GUI { +enum ConfigMenuIDs { + ConfigMenuWizard, + ConfigMenuSnapshots, + ConfigMenuTakeSnapshot, + ConfigMenuUpdate, + ConfigMenuPreferences, + ConfigMenuModeSimple, + ConfigMenuModeExpert, + ConfigMenuLanguage, + ConfigMenuFlashFirmware, + ConfigMenuCnt, +}; + class MainFrame; +class Tab; class GUI_App : public wxApp { @@ -64,13 +80,23 @@ public: const std::string& icon); void save_window_pos(wxTopLevelWindow* window, const std::string& name); void restore_window_pos(wxTopLevelWindow* window, const std::string& name); + bool load_language(); + ConfigMenuIDs get_view_mode(); + void add_config_menu(wxMenuBar *menu); + bool check_unsaved_changes(); + // Tab* get_tab(const std::string& name); AppConfig* app_config{ nullptr }; PresetBundle* preset_bundle{ nullptr }; PresetUpdater* preset_updater{ nullptr }; MainFrame* mainframe{ nullptr }; + + wxNotebook* tab_panel() const ; + + std::vector tabs_list; + }; -// DECLARE_APP(GUI_App) +DECLARE_APP(GUI_App) } // GUI } //Slic3r diff --git a/src/slic3r/GUI/GUI_ObjectParts.cpp b/src/slic3r/GUI/GUI_ObjectParts.cpp index 4fc3b88c0f..a6e9d1a01e 100644 --- a/src/slic3r/GUI/GUI_ObjectParts.cpp +++ b/src/slic3r/GUI/GUI_ObjectParts.cpp @@ -15,6 +15,7 @@ #include #include "3DScene.hpp" +#include "GUI_App.hpp" namespace Slic3r { @@ -103,8 +104,8 @@ void get_options_menu(settings_menu_hierarchy& settings_menu, bool is_part) { auto options = get_options(is_part); - auto extruders_cnt = get_preset_bundle()->printers.get_selected_preset().printer_technology() == ptSLA ? 1 : - get_preset_bundle()->printers.get_edited_preset().config.option("nozzle_diameter")->values.size(); + auto extruders_cnt = wxGetApp().preset_bundle->printers.get_selected_preset().printer_technology() == ptSLA ? 1 : + wxGetApp().preset_bundle->printers.get_edited_preset().config.option("nozzle_diameter")->values.size(); DynamicPrintConfig config; for (auto& option : options) @@ -398,7 +399,7 @@ void update_after_moving() wxSizer* object_movers(wxWindow *win) { -// DynamicPrintConfig* config = &get_preset_bundle()->/*full_config();//*/printers.get_edited_preset().config; // TODO get config from Model_volume +// DynamicPrintConfig* config = &wxGetApp().preset_bundle->/*full_config();//*/printers.get_edited_preset().config; // TODO get config from Model_volume std::shared_ptr optgroup = std::make_shared(win, "Move"/*, config*/); optgroup->label_width = 20; optgroup->m_on_change = [](t_config_option_key opt_key, boost::any value){ @@ -453,7 +454,7 @@ wxSizer* object_movers(wxWindow *win) wxBoxSizer* content_settings(wxWindow *win) { - DynamicPrintConfig* config = &get_preset_bundle()->/*full_config();//*/printers.get_edited_preset().config; // TODO get config from Model_volume + DynamicPrintConfig* config = &wxGetApp().preset_bundle->/*full_config();//*/printers.get_edited_preset().config; // TODO get config from Model_volume std::shared_ptr optgroup = std::make_shared(win, "Extruders", config); optgroup->label_width = label_width(); @@ -915,8 +916,8 @@ void update_settings_list() std::vector categories; if (!(opt_keys.size() == 1 && opt_keys[0] == "extruder"))// return; { - auto extruders_cnt = get_preset_bundle()->printers.get_selected_preset().printer_technology() == ptSLA ? 1 : - get_preset_bundle()->printers.get_edited_preset().config.option("nozzle_diameter")->values.size(); + auto extruders_cnt = wxGetApp().preset_bundle->printers.get_selected_preset().printer_technology() == ptSLA ? 1 : + wxGetApp().preset_bundle->printers.get_edited_preset().config.option("nozzle_diameter")->values.size(); for (auto& opt_key : opt_keys) { auto category = (*m_config)->def()->get(opt_key)->category; @@ -1461,7 +1462,7 @@ void on_btn_split(const bool split_part) return; ModelVolume* volume; if (!get_volume_by_item(split_part, item, volume)) return; - DynamicPrintConfig& config = get_preset_bundle()->printers.get_edited_preset().config; + DynamicPrintConfig& config = wxGetApp().preset_bundle->printers.get_edited_preset().config; const auto nozzle_dmrs_cnt = config.option("nozzle_diameter")->values.size(); if (volume->split(nozzle_dmrs_cnt) == 1) { wxMessageBox(_(L("The selected object couldn't be split because it contains only one part."))); @@ -1916,7 +1917,8 @@ void on_drop(wxDataViewEvent &event) void update_objects_list_extruder_column(int extruders_count) { - if (get_preset_bundle()->printers.get_selected_preset().printer_technology() == ptSLA) + if (!m_objects_ctrl) return; // #ys_FIXME + if (wxGetApp().preset_bundle->printers.get_selected_preset().printer_technology() == ptSLA) extruders_count = 1; // delete old 3rd column diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index c3b89b533f..48fb382a1a 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -18,17 +18,20 @@ #include #include +#include "GUI_App.hpp" namespace Slic3r { -namespace GUI -{ +namespace GUI { + +static wxString dots("…", wxConvUTF8); + MainFrame::MainFrame(const bool no_plater, const bool loaded) : wxFrame(NULL, wxID_ANY, "FORK_NAME-VERSION", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE), m_no_plater(no_plater), m_loaded(loaded) { // Slic3r::GUI::set_main_frame(this); -// m_appController = new Slic3r::AppController(); + m_appController = new Slic3r::AppController(); // #if _WIN32 // // Load the icon either from the exe, or from the ico file. @@ -36,73 +39,68 @@ wxFrame(NULL, wxID_ANY, "FORK_NAME-VERSION", wxDefaultPosition, wxDefaultSize, w // auto iconfile = Slic3r::var("Slic3r.ico");// unless - f iconfile; // SetIcon(wxIcon(iconfile, wxBITMAP_TYPE_ICO)); // #else -// SetIcon(wxIcon(Slic3r::var("Slic3r_128px.png"), wxBITMAP_TYPE_PNG)); - SetIcon(wxIcon("c:\\src\\Slic3r_TMP\\resources\\icons\\Slic3r_128px.png", wxBITMAP_TYPE_PNG)); + SetIcon(wxIcon(Slic3r::var("Slic3r_128px.png"), wxBITMAP_TYPE_PNG)); // #ifdef // _WIN32 // initialize tabpanel and menubar -// init_tabpanel(); -// init_menubar(); + init_tabpanel(); + init_menubar(); // set default tooltip timer in msec // SetAutoPop supposedly accepts long integers but some bug doesn't allow for larger values // (SetAutoPop is not available on GTK.) -// wxToolTip::SetAutoPop(32767); + wxToolTip::SetAutoPop(32767); // initialize status bar -// m_statusbar = new Slic3r::GUI::ProgressStatusBar(this); -// m_statusbar->embed(); -// m_statusbar->set_status_text(L("Version ").Slic3r::VERSION.L(" - Remember to check for updates at http://github.com/prusa3d/slic3r/releases")); + m_statusbar = new Slic3r::GUI::ProgressStatusBar(this); + m_statusbar->embed(this); + m_statusbar->set_status_text(_(L("Version ")) + + "Slic3r_VERSION" + // Slic3r::VERSION + + _(L(" - Remember to check for updates at http://github.com/prusa3d/slic3r/releases"))); // Make the global status bar and its progress indicator available in C++ -// m_appController->set_global_progress_indicator(m_statusbar); + m_appController->set_global_progress_indicator(m_statusbar); // m_appController->set_model(m_plater->model); // m_appController->set_print(m_plater->print); -// // m_plater->appController = m_appController; -// m_loaded = true; -// -// // initialize layout -// auto sizer = new wxBoxSizer(wxVERTICAL); -// if (m_tabpanel) -// sizer->Add(m_tabpanel, 1, wxEXPAND); -// sizer->SetSizeHints(this); -// SetSizer(sizer); -// Fit(); -// SetMinSize(wxSize(760, 490)); -// SetSize(GetMinSize()); -// // wxTheApp->restore_window_pos(this, "main_frame"); -// Show(); -// Layout(); + m_loaded = true; + + // initialize layout + auto sizer = new wxBoxSizer(wxVERTICAL); + if (m_tabpanel) + sizer->Add(m_tabpanel, 1, wxEXPAND); + sizer->SetSizeHints(this); + SetSizer(sizer); + Fit(); + SetMinSize(wxSize(760, 490)); + SetSize(GetMinSize()); + wxGetApp().restore_window_pos(this, "main_frame"); + Show(); + Layout(); // declare events -// Bind(wxEVT_CLOSE_WINDOW, [](wxEvent& event){ -// if (event.CanVeto() && !Slic3r::GUI::check_unsaved_changes) { -// event.Veto(); -// return; -// } -// // save window size -// wxTheApp->save_window_pos(this, "main_frame"); -// // 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. -// wxTheApp->{app_config}->save(); + Bind(wxEVT_CLOSE_WINDOW, [this](wxCloseEvent& event){ + if (event.CanVeto() && !wxGetApp().check_unsaved_changes()) { + event.Veto(); + return; + } + // save window size + wxGetApp().save_window_pos(this, "main_frame"); + // 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(); // if (m_plater) // m_plater->print = undef; -// _3DScene::remove_all_canvases(); + _3DScene::remove_all_canvases(); // Slic3r::GUI::deregister_on_request_update_callback(); -// // propagate event -// event.Skip(); -// }); + // propagate event + event.Skip(); + }); // update_ui_from_settings(); // // Slic3r::GUI::update_mode(); - wxMenu *menuHelp = new wxMenu; - menuHelp->Append(wxID_ABOUT); - wxMenuBar *menuBar = new wxMenuBar; - menuBar->Append(menuHelp, "&Help"); - SetMenuBar(menuBar); return; } @@ -110,18 +108,18 @@ wxFrame(NULL, wxID_ANY, "FORK_NAME-VERSION", wxDefaultPosition, wxDefaultSize, w void MainFrame::init_tabpanel() { m_tabpanel = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_TOP | wxTAB_TRAVERSAL); - Slic3r::GUI::set_tab_panel(m_tabpanel); +// Slic3r::GUI::set_tab_panel(m_tabpanel); -// m_tabpanel->Bind(wxEVT_NOTEBOOK_PAGE_CHANGED, [m_tabpanel](wxEvent&){ -// auto panel = m_tabpanel->GetCurrentPage(); -// // panel->OnActivate(); if panel->can('OnActivate'); -// -// std::vector tab_names = { "print", "filament", "printer" }; -// for (auto& tab_name : tab_names) { -// if (tab_name == panel->GetName()) -// Slic3r::GUI::get_preset_tab(tab_name.c_str())->OnActivate(); -// } -// }); + m_tabpanel->Bind(wxEVT_NOTEBOOK_PAGE_CHANGED, [this](wxEvent&){ + auto panel = m_tabpanel->GetCurrentPage(); +// panel->OnActivate(); if panel->can('OnActivate'); + + std::vector tab_names = { "print", "filament", "printer" }; + for (auto& tab_name : tab_names) { + if (tab_name == panel->GetName()) + m_options_tabs.at(tab_name)->OnActivate(); + } + }); if (!m_no_plater) { // m_plater = new Slic3r::GUI::Plater(m_tabpanel, @@ -221,10 +219,10 @@ void MainFrame::init_tabpanel() // }); -// Slic3r::GUI::create_preset_tabs(true, VALUE_CHANGE_EVENT, PRESETS_CHANGED_EVENT); + create_preset_tabs(); std::vector tab_names = { "print", "filament", "sla_material", "printer" }; -// for (auto tab_name : tab_names) -// m_options_tabs[tab_name] = Slic3r::GUI::get_preset_tab(tab_name.c_str()); // + for (auto tab_name : tab_names) + m_options_tabs[tab_name] = get_preset_tab(tab_name.c_str()); if (m_plater) { // m_plater->on_select_preset(sub{ @@ -232,7 +230,7 @@ void MainFrame::init_tabpanel() // $self->{options_tabs}{$group}->select_preset($name); // }); // load initial config - auto full_config = Slic3r::GUI::get_preset_bundle()->full_config(); + auto full_config = wxGetApp().preset_bundle->full_config(); // m_plater->on_config_change(full_config); // Show a correct number of filament fields. @@ -246,51 +244,99 @@ void MainFrame::init_tabpanel() } } +Tab* MainFrame::get_preset_tab(const std::string& name) +{ + Tab* tab = get_tab(name); + if (tab) return tab; + + for (size_t i = 0; i < m_tabpanel->GetPageCount(); ++i) { + tab = dynamic_cast(m_tabpanel->GetPage(i)); + if (!tab) + continue; + if (tab->name() == name) { + return tab; + } + } + return nullptr; +} + +void MainFrame::create_preset_tabs() +{ +// update_label_colours_from_appconfig(); + add_created_tab(new TabPrint(m_tabpanel)); + add_created_tab(new TabFilament(m_tabpanel)); + add_created_tab(new TabSLAMaterial(m_tabpanel)); + add_created_tab(new TabPrinter(m_tabpanel)); +} + +void MainFrame::add_created_tab(Tab* panel) +{ + panel->create_preset_tab(wxGetApp().preset_bundle); + + // Load the currently selected preset into the GUI, update the preset selection box. + panel->load_current_preset(); + + const wxString& tab_name = panel->GetName(); + bool add_panel = true; + + auto preset_tabs = get_preset_tabs(); + auto it = std::find_if(preset_tabs->begin(), preset_tabs->end(), + [tab_name](PresetTab& tab){return tab.name == tab_name; }); + if (it != preset_tabs->end()) { + it->panel = panel; + add_panel = it->technology == wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology(); + } + + if (add_panel) + m_tabpanel->AddPage(panel, panel->title()); +} + void MainFrame::init_menubar() { // File menu - auto fileMenu = new wxMenu(); + wxMenu* fileMenu = new wxMenu; { -// wxTheApp->append_menu_item(fileMenu, L("Open STL/OBJ/AMF/3MF…\tCtrl+O"), L('Open a model'), [](wxCommandEvent&){ + wxGetApp().append_menu_item(fileMenu, wxID_ANY, _(L("Open STL/OBJ/AMF/3MF…\tCtrl+O")), _(L("Open a model")), + "", [](wxCommandEvent&){ // if (m_plater) m_plater->add(); -// }, undef, undef); //'brick_add.png'); - append_menu_item(fileMenu, wxID_ANY, _(L("&Load Config…\tCtrl+L")), _(L("Load exported configuration file")), + }); //'brick_add.png'); + append_menu_item(fileMenu, wxID_ANY, _(L("&Load Config…\tCtrl+L")), _(L("Load exported configuration file")), [this](wxCommandEvent&){ load_config_file(); }, "plugin_add.png"); - append_menu_item(fileMenu, wxID_ANY, _(L("&Export Config…\tCtrl+E")), _(L("Export current configuration to file")), + append_menu_item(fileMenu, wxID_ANY, _(L("&Export Config…\tCtrl+E")), _(L("Export current configuration to file")), [this](wxCommandEvent&){ export_config(); }, "plugin_go.png"); - append_menu_item(fileMenu, wxID_ANY, _(L("&Load Config Bundle…")), _(L("Load presets from a bundle")), + append_menu_item(fileMenu, wxID_ANY, _(L("&Load Config Bundle…")), _(L("Load presets from a bundle")), [this](wxCommandEvent&){ load_configbundle(); }, "lorry_add.png"); - append_menu_item(fileMenu, wxID_ANY, _(L("&Export Config Bundle…")), _(L("Export all presets to file")), + append_menu_item(fileMenu, wxID_ANY, _(L("&Export Config Bundle…")), _(L("Export all presets to file")), [this](wxCommandEvent&){ export_configbundle(); }, "lorry_go.png"); fileMenu->AppendSeparator(); wxMenuItem* repeat = nullptr; - append_menu_item(fileMenu, wxID_ANY, _(L("Q&uick Slice…\tCtrl+U")), _(L("Slice a file into a G-code")), + append_menu_item(fileMenu, wxID_ANY, _(L("Q&uick Slice…\tCtrl+U")), _(L("Slice a file into a G-code")), [this, repeat](wxCommandEvent&){ wxTheApp->CallAfter([this, repeat](){ quick_slice(); - repeat->Enable(is_last_input_file()/*defined $Slic3r::GUI::MainFrame::last_input_file*/); + repeat->Enable(is_last_input_file()); }); }, "cog_go.png"); - append_menu_item(fileMenu, wxID_ANY, _(L("Quick Slice and Save &As…\tCtrl+Alt+U")), _(L("Slice a file into a G-code, save as")), + append_menu_item(fileMenu, wxID_ANY, _(L("Quick Slice and Save &As…\tCtrl+Alt+U")), _(L("Slice a file into a G-code, save as")), [this, repeat](wxCommandEvent&){ wxTheApp->CallAfter([this, repeat](){ - quick_slice(/*save_as = > 1*/qsSaveAs); - repeat->Enable(is_last_input_file()/*defined $Slic3r::GUI::MainFrame::last_input_file*/); + quick_slice(qsSaveAs); + repeat->Enable(is_last_input_file()); }); }, "cog_go.png"); repeat = append_menu_item(fileMenu, wxID_ANY, _(L("&Repeat Last Quick Slice\tCtrl+Shift+U")), _(L("Repeat last quick slice")), [this](wxCommandEvent&){ wxTheApp->CallAfter([this](){ - quick_slice(/*reslice = > 1*/qsReslice); + quick_slice(qsReslice); }); }, "cog_go.png"); repeat->Enable(0); fileMenu->AppendSeparator(); - append_menu_item(fileMenu, wxID_ANY, _(L("Slice to SV&G…\tCtrl+G")), _(L("Slice file to a multi-layer SVG")), - [this](wxCommandEvent&){ quick_slice(/*save_as = > 1, export_svg = > 1*/qsSaveAs | qsExportSVG); }, "shape_handles.png"); - append_menu_item(fileMenu, wxID_ANY, _(L("Slice to PNG…")), _(L("Slice file to a set of PNG files")), + append_menu_item(fileMenu, wxID_ANY, _(L("Slice to SV&G…\tCtrl+G")), _(L("Slice file to a multi-layer SVG")), + [this](wxCommandEvent&){ quick_slice(qsSaveAs | qsExportSVG); }, "shape_handles.png"); + append_menu_item(fileMenu, wxID_ANY, _(L("Slice to PNG…")), _(L("Slice file to a set of PNG files")), [this](wxCommandEvent&){ slice_to_png(); /*$self->quick_slice(save_as = > 0, export_png = > 1);*/ }, "shape_handles.png"); m_menu_item_reslice_now = append_menu_item(fileMenu, wxID_ANY, _(L("(&Re)Slice Now\tCtrl+S")), _(L("Start new slicing process")), [this](wxCommandEvent&){ reslice_now(); }, "shape_handles.png"); fileMenu->AppendSeparator(); - append_menu_item(fileMenu, wxID_ANY, _(L("Repair STL file…")), _(L("Automatically repair an STL file")), + append_menu_item(fileMenu, wxID_ANY, _(L("Repair STL file…")), _(L("Automatically repair an STL file")), [this](wxCommandEvent&){ repair_stl(); }, "wrench.png"); fileMenu->AppendSeparator(); append_menu_item(fileMenu, wxID_EXIT, _(L("&Quit")), _(L("Quit Slic3r")), @@ -372,7 +418,7 @@ void MainFrame::init_menubar() [this](wxCommandEvent&){ wxLaunchDefaultBrowser("http://manual.slic3r.org/"); }); helpMenu->AppendSeparator(); append_menu_item(helpMenu, wxID_ANY, _(L("System Info")), _(L("Show system information")), - [this](wxCommandEvent&){ /*wxTheApp->system_info();*/ }); + [this](wxCommandEvent&){ wxGetApp().system_info(); }); append_menu_item(helpMenu, wxID_ANY, _(L("Show &Configuration Folder")), _(L("Show user configuration folder (datadir)")), [this](wxCommandEvent&){ Slic3r::GUI::desktop_open_datadir_folder(); }); append_menu_item(helpMenu, wxID_ANY, _(L("Report an Issue")), _(L("Report an issue on the Slic3r Prusa Edition")), @@ -392,7 +438,7 @@ void MainFrame::init_menubar() menubar->Append(windowMenu, L("&Window")); if (m_viewMenu) menubar->Append(m_viewMenu, L("&View")); // Add additional menus from C++ -// Slic3r::GUI::add_menus(menubar, preferences_event, lang_ch_event); + wxGetApp().add_config_menu(menubar); menubar->Append(helpMenu, L("&Help")); SetMenuBar(menubar); } @@ -414,22 +460,19 @@ void MainFrame::slice_to_png(){ } // To perform the "Quck Slice", "Quick Slice and Save As", "Repeat last Quick Slice" and "Slice to SVG". -void MainFrame::quick_slice(const /*QuickSlice*/int qs/* = qsUndef const bool reslice, - const bool export_svg, - const bool export_png, - const bool save_as*/){ +void MainFrame::quick_slice(const int qs){ // my $progress_dialog; wxString input_file; // eval // { // validate configuration - auto config = get_preset_bundle()->full_config(); + auto config = wxGetApp().preset_bundle->full_config(); config.validate(); // select input file - if (/*!reslice*/(qs & qsReslice) == 0) { + if (!(qs & qsReslice)) { auto dlg = new wxFileDialog(this, _(L("Choose a file to slice (STL/OBJ/AMF/3MF/PRUSA):")), - get_app_config()->get_last_dir(), "", + wxGetApp().app_config->get_last_dir(), "", MODEL_WILDCARD, wxFD_OPEN | wxFD_FILE_MUST_EXIST); if (dlg->ShowModal() != wxID_OK) { dlg->Destroy(); @@ -437,7 +480,7 @@ void MainFrame::quick_slice(const /*QuickSlice*/int qs/* = qsUndef const bool re } input_file = dlg->GetPath(); dlg->Destroy(); - if (/*!export_svg*/(qs & qsExportSVG) == 0) + if (!(qs & qsExportSVG)) m_qs_last_input_file = input_file; } else { @@ -456,7 +499,7 @@ void MainFrame::quick_slice(const /*QuickSlice*/int qs/* = qsUndef const bool re input_file = m_qs_last_input_file; } auto input_file_basename = get_base_name(input_file); - get_app_config()->update_skein_dir(get_dir_name(input_file)); + wxGetApp().app_config->update_skein_dir(get_dir_name(input_file)); auto bed_shape = Slic3r::Polygon::new_scale(config.option("bed_shape")->values); // auto print_center = Slic3r::Pointf->new_unscale(bed_shape.bounding_box().center()); @@ -464,7 +507,7 @@ void MainFrame::quick_slice(const /*QuickSlice*/int qs/* = qsUndef const bool re // auto sprint = new Slic3r::Print::Simple( // print_center = > print_center, // status_cb = > [](int percent, const wxString& msg){ -// m_progress_dialog->Update(percent, msg+"…"); +// m_progress_dialog->Update(percent, msg+"…"); // }); // keep model around @@ -474,22 +517,22 @@ void MainFrame::quick_slice(const /*QuickSlice*/int qs/* = qsUndef const bool re // sprint->set_model(model); // Copy the names of active presets into the placeholder parser. -// get_preset_bundle()->export_selections(sprint->placeholder_parser); +// wxGetApp().preset_bundle->export_selections(sprint->placeholder_parser); // select output file wxString output_file; - if (/*reslice*/(qs & qsReslice)/* != 0*/) { + if (qs & qsReslice) { if (!m_qs_last_output_file.IsEmpty()) output_file = m_qs_last_output_file; } - else if (/*save_as*/(qs & qsSaveAs)/* != 0*/) { + else if (qs & qsSaveAs) { // The following line may die if the output_filename_format template substitution fails. // output_file = sprint->output_filepath; // if (export_svg) // output_file = ~s / \.[gG][cC][oO][dD][eE]$ / .svg /; - auto dlg = new wxFileDialog(this, _(L("Save ")) + (qs & qsExportSVG/*export_svg*/ ? _(L("SVG")) : _(L("G-code"))) + _(L(" file as:")), - get_app_config()->get_last_output_dir(get_dir_name(output_file)), get_base_name(input_file), - qs & qsExportSVG/*export_svg*/ ? FILE_WILDCARDS.at("svg") : FILE_WILDCARDS.at("gcode"), + auto dlg = new wxFileDialog(this, _(L("Save ")) + (qs & qsExportSVG ? _(L("SVG")) : _(L("G-code"))) + _(L(" file as:")), + wxGetApp().app_config->get_last_output_dir(get_dir_name(output_file)), get_base_name(input_file), + qs & qsExportSVG ? FILE_WILDCARDS.at("svg") : FILE_WILDCARDS.at("gcode"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT); if (dlg->ShowModal() != wxID_OK) { dlg->Destroy(); @@ -497,15 +540,15 @@ void MainFrame::quick_slice(const /*QuickSlice*/int qs/* = qsUndef const bool re } output_file = dlg->GetPath(); dlg->Destroy(); - if (/*!export_svg*/!(qs & qsExportSVG)) + if (!(qs & qsExportSVG)) m_qs_last_output_file = output_file; - get_app_config()->update_last_output_dir(get_dir_name(output_file)); + wxGetApp().app_config->update_last_output_dir(get_dir_name(output_file)); } - else if (/*export_png*/qs & qsExportPNG) { + else if (qs & qsExportPNG) { // output_file = sprint->output_filepath; // output_file = ~s / \.[gG][cC][oO][dD][eE]$ / .zip / ; auto dlg = new wxFileDialog(this, _(L("Save zip file as:")), - get_app_config()->get_last_output_dir(get_dir_name(output_file)), + wxGetApp().app_config->get_last_output_dir(get_dir_name(output_file)), get_base_name(output_file), "*.zip", wxFD_SAVE | wxFD_OVERWRITE_PROMPT); if (dlg->ShowModal() != wxID_OK) { dlg->Destroy(); @@ -516,7 +559,7 @@ void MainFrame::quick_slice(const /*QuickSlice*/int qs/* = qsUndef const bool re } // show processbar dialog - m_progress_dialog = new wxProgressDialog(_(L("Slicing…")), _(L("Processing ")) + input_file_basename + "…", + m_progress_dialog = new wxProgressDialog(_(L("Slicing…")), _(L("Processing ")) + input_file_basename + "…", 100, this, 4); m_progress_dialog->Pulse(); { @@ -556,7 +599,7 @@ void MainFrame::repair_stl() wxString input_file; { auto dlg = new wxFileDialog(this, _(L("Select the STL file to repair:")), - get_app_config()->get_last_dir(), "", + wxGetApp().app_config->get_last_dir(), "", FILE_WILDCARDS.at("stl"), wxFD_OPEN | wxFD_FILE_MUST_EXIST); if (dlg->ShowModal() != wxID_OK) { dlg->Destroy(); @@ -590,7 +633,7 @@ void MainFrame::repair_stl() void MainFrame::export_config() { // Generate a cummulative configuration for the selected print, filaments and printer. - auto config = get_preset_bundle()->full_config(); + auto config = wxGetApp().preset_bundle->full_config(); // Validate the cummulative configuration. auto valid = config.validate(); if (!valid.empty()) { @@ -599,13 +642,13 @@ void MainFrame::export_config() } // Ask user for the file name for the config file. auto dlg = new wxFileDialog(this, _(L("Save configuration as:")), - !m_last_config.IsEmpty() ? get_dir_name(m_last_config) : get_app_config()->get_last_dir(), + !m_last_config.IsEmpty() ? get_dir_name(m_last_config) : wxGetApp().app_config->get_last_dir(), !m_last_config.IsEmpty() ? get_base_name(m_last_config) : "config.ini", FILE_WILDCARDS.at("ini"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT); wxString file = dlg->ShowModal() == wxID_OK ? dlg->GetPath() : wxEmptyString; dlg->Destroy(); if (!file.IsEmpty()) { - get_app_config()->update_config_dir(get_dir_name(file)); + wxGetApp().app_config->update_config_dir(get_dir_name(file)); m_last_config = file; config.save(file.ToStdString()); } @@ -615,10 +658,10 @@ void MainFrame::export_config() void MainFrame::load_config_file(wxString file/* = wxEmptyString*/) { if (file.IsEmpty()) { - if (!Slic3r::GUI::check_unsaved_changes()) + if (!wxGetApp().check_unsaved_changes()) return; auto dlg = new wxFileDialog(this, _(L("Select configuration to load:")), - !m_last_config.IsEmpty() ? get_dir_name(m_last_config) : get_app_config()->get_last_dir(), + !m_last_config.IsEmpty() ? get_dir_name(m_last_config) : wxGetApp().app_config->get_last_dir(), "config.ini", "INI files (*.ini, *.gcode)|*.ini;*.INI;*.gcode;*.g", wxFD_OPEN | wxFD_FILE_MUST_EXIST); if (dlg->ShowModal() != wxID_OK) return; @@ -626,39 +669,39 @@ void MainFrame::load_config_file(wxString file/* = wxEmptyString*/) dlg->Destroy(); } // eval{ - get_preset_bundle()->load_config_file(file.ToStdString()); + wxGetApp().preset_bundle->load_config_file(file.ToStdString()); // }; // Dont proceed further if the config file cannot be loaded. // if (Slic3r::GUI::catch_error(this)) // return; for (auto tab : m_options_tabs ) tab.second->load_current_preset(); - get_app_config()->update_config_dir(get_dir_name(file)); + wxGetApp().app_config->update_config_dir(get_dir_name(file)); m_last_config = file; } void MainFrame::export_configbundle() { - if (!Slic3r::GUI::check_unsaved_changes()) + if (!wxGetApp().check_unsaved_changes()) return; // validate current configuration in case it's dirty - auto valid = get_preset_bundle()->full_config().validate(); + auto valid = wxGetApp().preset_bundle->full_config().validate(); if (!valid.empty()) { // Slic3r::GUI::catch_error(this); return; } // Ask user for a file name. auto dlg = new wxFileDialog(this, _(L("Save presets bundle as:")), - !m_last_config.IsEmpty() ? get_dir_name(m_last_config) : get_app_config()->get_last_dir(), + !m_last_config.IsEmpty() ? get_dir_name(m_last_config) : wxGetApp().app_config->get_last_dir(), "Slic3r_config_bundle.ini", FILE_WILDCARDS.at("ini"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT); wxString file = dlg->ShowModal() == wxID_OK ? dlg->GetPath() : wxEmptyString; dlg->Destroy(); if (!file.IsEmpty()) { // Export the config bundle. - get_app_config()->update_config_dir(get_dir_name(file)); + wxGetApp().app_config->update_config_dir(get_dir_name(file)); // eval{ - get_preset_bundle()->export_configbundle(file.ToStdString()); + wxGetApp().preset_bundle->export_configbundle(file.ToStdString()); // }; // Slic3r::GUI::catch_error(this); } @@ -668,11 +711,11 @@ void MainFrame::export_configbundle() // to auto - install a config bundle on a fresh user account, // but that behavior was not documented and likely buggy. void MainFrame::load_configbundle(wxString file/* = wxEmptyString, const bool reset_user_profile*/){ - if (!Slic3r::GUI::check_unsaved_changes()) + if (!wxGetApp().check_unsaved_changes()) return; if (file.IsEmpty()) { auto dlg = new wxFileDialog(this, _(L("Select configuration to load:")), - !m_last_config.IsEmpty() ? get_dir_name(m_last_config) : get_app_config()->get_last_dir(), + !m_last_config.IsEmpty() ? get_dir_name(m_last_config) : wxGetApp().app_config->get_last_dir(), "config.ini", FILE_WILDCARDS.at("ini"), wxFD_OPEN | wxFD_FILE_MUST_EXIST); if (dlg->ShowModal() != wxID_OK) return; @@ -680,11 +723,11 @@ void MainFrame::load_configbundle(wxString file/* = wxEmptyString, const bool re dlg->Destroy(); } - get_app_config()->update_config_dir(get_dir_name(file)); + wxGetApp().app_config->update_config_dir(get_dir_name(file)); auto presets_imported = 0; // eval{ - presets_imported = get_preset_bundle()->load_configbundle(file.ToStdString()); + presets_imported = wxGetApp().preset_bundle->load_configbundle(file.ToStdString()); // }; // Slic3r::GUI::catch_error(this) and return; @@ -734,7 +777,7 @@ wxMenuItem* MainFrame::append_menu_item(wxMenu* menu, // Update the UI based on the current preferences. void MainFrame::update_ui_from_settings() { -// m_menu_item_reslice_now->Enable(get_app_config()->get("background_processing")); + m_menu_item_reslice_now->Enable(wxGetApp().app_config->get("background_processing") == "1"); // if (m_plater) m_plater->update_ui_from_settings(); std::vector tab_names = { "print", "filament", "printer" }; for (auto tab_name: tab_names) @@ -754,4 +797,4 @@ std::string MainFrame::get_dir_name(const wxString full_name) const } // GUI -} //Slic3r +} // Slic3r diff --git a/src/slic3r/GUI/MainFrame.hpp b/src/slic3r/GUI/MainFrame.hpp index 2156db6912..aff8a59859 100644 --- a/src/slic3r/GUI/MainFrame.hpp +++ b/src/slic3r/GUI/MainFrame.hpp @@ -45,8 +45,8 @@ class MainFrame : public wxFrame wxString m_qs_last_output_file = wxEmptyString; wxString m_last_config = wxEmptyString; - ProgressStatusBar* m_statusbar; - AppController* m_appController = nullptr; + ProgressStatusBar* m_statusbar { nullptr }; + AppController* m_appController { nullptr }; std::map m_options_tabs; wxMenuItem* append_menu_item(wxMenu* menu, @@ -56,10 +56,10 @@ class MainFrame : public wxFrame std::function cb, const std::string& icon = ""); - wxMenuItem* m_menu_item_reslice_now = nullptr; - wxMenu* m_plater_menu = nullptr; - wxMenu* m_object_menu = nullptr; - wxMenu* m_viewMenu = nullptr; + wxMenuItem* m_menu_item_reslice_now { nullptr }; + wxMenu* m_plater_menu { nullptr }; + wxMenu* m_object_menu { nullptr }; + wxMenu* m_viewMenu { nullptr }; std::string get_base_name(const wxString full_name) const ; std::string get_dir_name(const wxString full_name) const ; @@ -70,6 +70,9 @@ public: void init_tabpanel(); + Tab* get_preset_tab(const std::string& name); + void create_preset_tabs(); + void add_created_tab(Tab* panel); void init_menubar(); void update_ui_from_settings(); @@ -90,9 +93,9 @@ public: void select_view(const std::string& direction); - wxPanel* m_plater = nullptr; - wxNotebook* m_tabpanel = nullptr; - wxProgressDialog* m_progress_dialog = nullptr; + wxPanel* m_plater {nullptr}; + wxNotebook* m_tabpanel { nullptr }; + wxProgressDialog* m_progress_dialog { nullptr }; }; } // GUI diff --git a/src/slic3r/GUI/OptionsGroup.cpp b/src/slic3r/GUI/OptionsGroup.cpp index ea22b2cb5a..bfe54c3ced 100644 --- a/src/slic3r/GUI/OptionsGroup.cpp +++ b/src/slic3r/GUI/OptionsGroup.cpp @@ -218,10 +218,10 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** colored_Label/* add_undo_buttuns_to_sizer(sizer, field); if (is_window_field(field)) - sizer->Add(field->getWindow(), option.opt.full_width ? 1 : 0, (option.opt.full_width ? wxEXPAND : 0) | - wxBOTTOM | wxTOP | wxALIGN_CENTER_VERTICAL, (wxOSX||!staticbox) ? 0 : 2); + sizer->Add(field->getWindow(), option.opt.full_width ? 1 : 0, //(option.opt.full_width ? wxEXPAND : 0) | + wxBOTTOM | wxTOP | (option.opt.full_width ? wxEXPAND : wxALIGN_CENTER_VERTICAL), (wxOSX || !staticbox) ? 0 : 2); if (is_sizer_field(field)) - sizer->Add(field->getSizer(), 1, (option.opt.full_width ? wxEXPAND : 0) | wxALIGN_CENTER_VERTICAL, 0); + sizer->Add(field->getSizer(), 1, /*(*/option.opt.full_width ? wxEXPAND : /*0) |*/ wxALIGN_CENTER_VERTICAL, 0); return; } @@ -244,7 +244,7 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** colored_Label/* // L_str(option.label); label = new wxStaticText(parent(), wxID_ANY, str_label + ":", wxDefaultPosition, wxDefaultSize); label->SetFont(label_font); - sizer_tmp->Add(label, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL, 0); + sizer_tmp->Add(label, 0, /*wxALIGN_RIGHT |*/ wxALIGN_CENTER_VERTICAL, 0); } // add field diff --git a/src/slic3r/GUI/ProgressStatusBar.cpp b/src/slic3r/GUI/ProgressStatusBar.cpp index 363e34cb2b..1b308034bf 100644 --- a/src/slic3r/GUI/ProgressStatusBar.cpp +++ b/src/slic3r/GUI/ProgressStatusBar.cpp @@ -130,7 +130,7 @@ void ProgressStatusBar::run(int rate) void ProgressStatusBar::embed(wxFrame *frame) { - wxFrame* mf = frame? frame : GUI::get_main_frame(); + wxFrame* mf = frame ? frame : GUI::get_main_frame(); mf->SetStatusBar(self); } diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 5b438d4a19..def9ea5b55 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -28,6 +28,7 @@ #include #include +#include "GUI_App.hpp" namespace Slic3r { namespace GUI { @@ -513,8 +514,8 @@ void Tab::update_changed_tree_ui() } break; } - auto next_item = m_treectrl->GetNextVisible(cur_item); - cur_item = next_item; + auto next_item = m_treectrl->GetNextVisible(cur_item); + cur_item = !m_treectrl->IsVisible(cur_item) ? m_treectrl->GetNextVisible(cur_item) : nullptr;// next_item; } update_undo_buttons(); } @@ -713,15 +714,16 @@ void Tab::on_value_change(const std::string& opt_key, const boost::any& value) // Show/hide the 'purging volumes' button void Tab::update_wiping_button_visibility() { - if (get_preset_bundle()->printers.get_selected_preset().printer_technology() == ptSLA) + if (wxGetApp().preset_bundle->printers.get_selected_preset().printer_technology() == ptSLA) return; // ys_FIXME bool wipe_tower_enabled = dynamic_cast( (m_preset_bundle->prints.get_edited_preset().config ).option("wipe_tower"))->value; bool multiple_extruders = dynamic_cast((m_preset_bundle->printers.get_edited_preset().config).option("nozzle_diameter"))->values.size() > 1; bool single_extruder_mm = dynamic_cast( (m_preset_bundle->printers.get_edited_preset().config).option("single_extruder_multi_material"))->value; - get_wiping_dialog_button()->Show(wipe_tower_enabled && multiple_extruders && single_extruder_mm); - + if (get_wiping_dialog_button()) { + get_wiping_dialog_button()->Show(wipe_tower_enabled && multiple_extruders && single_extruder_mm); (get_wiping_dialog_button()->GetParent())->Layout(); + } } @@ -787,6 +789,7 @@ void Tab::update_preset_description_line() void Tab::update_frequently_changed_parameters() { + if (!get_optgroup(ogFrequentlyChangingParameters)) return; boost::any value = get_optgroup(ogFrequentlyChangingParameters)->get_config_value(*m_config, "fill_density"); get_optgroup(ogFrequentlyChangingParameters)->set_value("fill_density", value); @@ -1041,7 +1044,7 @@ void TabPrint::reload_config(){ void TabPrint::update() { - if (get_preset_bundle()->printers.get_selected_preset().printer_technology() == ptSLA) + if (wxGetApp().preset_bundle->printers.get_selected_preset().printer_technology() == ptSLA) return; // ys_FIXME Freeze(); @@ -1407,7 +1410,7 @@ void TabFilament::reload_config(){ void TabFilament::update() { - if (get_preset_bundle()->printers.get_selected_preset().printer_technology() == ptSLA) + if (wxGetApp().preset_bundle->printers.get_selected_preset().printer_technology() == ptSLA) return; // ys_FIXME Freeze(); @@ -2189,15 +2192,15 @@ void Tab::load_current_preset() PrinterTechnology& printer_technology = m_presets->get_edited_preset().printer_technology(); if (printer_technology != static_cast(this)->m_printer_technology) { - for (auto& tab : get_preset_tabs()){ + for (auto& tab : *get_preset_tabs()){ if (tab.technology != printer_technology) { - int page_id = get_tab_panel()->FindPage(tab.panel); - get_tab_panel()->GetPage(page_id)->Show(false); - get_tab_panel()->RemovePage(page_id); + int page_id = wxGetApp().tab_panel()->FindPage(tab.panel); + wxGetApp().tab_panel()->GetPage(page_id)->Show(false); + wxGetApp().tab_panel()->RemovePage(page_id); } else - get_tab_panel()->InsertPage(get_tab_panel()->FindPage(this), tab.panel, tab.panel->title()); + wxGetApp().tab_panel()->InsertPage(wxGetApp().tab_panel()->FindPage(this), tab.panel, tab.panel->title()); } static_cast(this)->m_printer_technology = printer_technology; @@ -2225,8 +2228,9 @@ void Tab::rebuild_page_tree(bool tree_sel_change_event /*= false*/) { Freeze(); // get label of the currently selected item - auto selected = m_treectrl->GetItemText(m_treectrl->GetSelection()); - auto rootItem = m_treectrl->GetRootItem(); + const auto sel_item = m_treectrl->GetSelection(); + const auto selected = sel_item ? m_treectrl->GetItemText(sel_item) : ""; + const auto rootItem = m_treectrl->GetRootItem(); auto have_selection = 0; m_treectrl->DeleteChildren(rootItem); @@ -2375,7 +2379,8 @@ void Tab::OnTreeSelChange(wxTreeEvent& event) #endif Page* page = nullptr; - auto selection = m_treectrl->GetItemText(m_treectrl->GetSelection()); + const auto sel_item = m_treectrl->GetSelection(); + const auto selection = sel_item ? m_treectrl->GetItemText(sel_item) : ""; for (auto p : m_pages) if (p->title() == selection) { @@ -2517,7 +2522,7 @@ void Tab::update_ui_from_settings() { // Show the 'show / hide presets' button only for the print and filament tabs, and only if enabled // in application preferences. - m_show_btn_incompatible_presets = get_app_config()->get("show_incompatible_presets")[0] == '1' ? true : false; + m_show_btn_incompatible_presets = wxGetApp().app_config->get("show_incompatible_presets")[0] == '1' ? true : false; bool show = m_show_btn_incompatible_presets && m_presets->name().compare("printer") != 0; show ? m_btn_hide_incompatible_presets->Show() : m_btn_hide_incompatible_presets->Hide(); // If the 'show / hide presets' button is hidden, hide the incompatible presets. @@ -2616,7 +2621,7 @@ void Tab::update_presetsctrl(wxDataViewTreeCtrl* ui, bool show_incompatible) auto root_sys = ui->AppendContainer(wxDataViewItem(0), _(L("System presets"))); auto root_def = ui->AppendContainer(wxDataViewItem(0), _(L("Default presets"))); - auto show_def = get_app_config()->get("no_defaults")[0] != '1'; + auto show_def = wxGetApp().app_config->get("no_defaults")[0] != '1'; for (size_t i = presets.front().is_visible ? 0 : 1; i < presets.size(); ++i) { const Preset &preset = presets[i]; @@ -2702,7 +2707,7 @@ void Tab::update_tab_presets(wxComboCtrl* ui, bool show_incompatible) auto root_sys = popup->AppendContainer(wxDataViewItem(0), _(L("System presets"))); auto root_def = popup->AppendContainer(wxDataViewItem(0), _(L("Default presets"))); - auto show_def = get_app_config()->get("no_defaults")[0] != '1'; + auto show_def = wxGetApp().app_config->get("no_defaults")[0] != '1'; for (size_t i = presets.front().is_visible ? 0 : 1; i < presets.size(); ++i) { const Preset &preset = presets[i]; @@ -3025,7 +3030,7 @@ void TabSLAMaterial::build() void TabSLAMaterial::update() { - if (get_preset_bundle()->printers.get_selected_preset().printer_technology() == ptFFF) + if (wxGetApp().preset_bundle->printers.get_selected_preset().printer_technology() == ptFFF) return; // ys_FIXME } diff --git a/src/slic3r/Utils/PresetUpdater.cpp b/src/slic3r/Utils/PresetUpdater.cpp index 2e423dc5ee..617afb68db 100644 --- a/src/slic3r/Utils/PresetUpdater.cpp +++ b/src/slic3r/Utils/PresetUpdater.cpp @@ -24,6 +24,7 @@ #include "slic3r/Utils/Http.hpp" #include "slic3r/Config/Version.hpp" #include "slic3r/Config/Snapshot.hpp" +#include "slic3r/GUI/GUI_App.hpp" namespace fs = boost::filesystem; using Slic3r::GUI::Config::Index; @@ -90,7 +91,6 @@ struct Updates struct PresetUpdater::priv { - int version_online_event; std::vector index_db; bool enabled_version_check; @@ -105,7 +105,7 @@ struct PresetUpdater::priv bool cancel; std::thread thread; - priv(int version_online_event); + priv(); void set_download_prefs(AppConfig *app_config); bool get_file(const std::string &url, const fs::path &target_path) const; @@ -120,15 +120,14 @@ struct PresetUpdater::priv static void copy_file(const fs::path &from, const fs::path &to); }; -PresetUpdater::priv::priv(int version_online_event) : - version_online_event(version_online_event), +PresetUpdater::priv::priv() : had_config_update(false), cache_path(fs::path(Slic3r::data_dir()) / "cache"), rsrc_path(fs::path(resources_dir()) / "profiles"), vendor_path(fs::path(Slic3r::data_dir()) / "vendor"), cancel(false) { - set_download_prefs(GUI::get_app_config()); + set_download_prefs(GUI::wxGetApp().app_config); check_install_indices(); index_db = std::move(Index::load_db()); } @@ -209,9 +208,11 @@ void PresetUpdater::priv::sync_version() const .on_complete([&](std::string body, unsigned /* http_status */) { boost::trim(body); BOOST_LOG_TRIVIAL(info) << boost::format("Got Slic3rPE online version: `%1%`. Sending to GUI thread...") % body; - wxCommandEvent* evt = new wxCommandEvent(version_online_event); - evt->SetString(body); - GUI::get_app()->QueueEvent(evt); +// wxCommandEvent* evt = new wxCommandEvent(version_online_event); +// evt->SetString(body); +// GUI::get_app()->QueueEvent(evt); + GUI::wxGetApp().app_config->set("version_online", body); + GUI::wxGetApp().app_config->save(); }) .perform_sync(); } @@ -395,7 +396,7 @@ void PresetUpdater::priv::perform_updates(Updates &&updates, bool snapshot) cons if (updates.incompats.size() > 0) { if (snapshot) { BOOST_LOG_TRIVIAL(info) << "Taking a snapshot..."; - SnapshotDB::singleton().take_snapshot(*GUI::get_app_config(), Snapshot::SNAPSHOT_DOWNGRADE); + SnapshotDB::singleton().take_snapshot(*GUI::wxGetApp().app_config, Snapshot::SNAPSHOT_DOWNGRADE); } BOOST_LOG_TRIVIAL(info) << boost::format("Deleting %1% incompatible bundles") % updates.incompats.size(); @@ -408,7 +409,7 @@ void PresetUpdater::priv::perform_updates(Updates &&updates, bool snapshot) cons else if (updates.updates.size() > 0) { if (snapshot) { BOOST_LOG_TRIVIAL(info) << "Taking a snapshot..."; - SnapshotDB::singleton().take_snapshot(*GUI::get_app_config(), Snapshot::SNAPSHOT_UPGRADE); + SnapshotDB::singleton().take_snapshot(*GUI::wxGetApp().app_config, Snapshot::SNAPSHOT_UPGRADE); } BOOST_LOG_TRIVIAL(info) << boost::format("Performing %1% updates") % updates.updates.size(); @@ -466,8 +467,8 @@ void PresetUpdater::priv::copy_file(const fs::path &source, const fs::path &targ } -PresetUpdater::PresetUpdater(int version_online_event) : - p(new priv(version_online_event)) +PresetUpdater::PresetUpdater() : + p(new priv()) {} @@ -485,7 +486,7 @@ PresetUpdater::~PresetUpdater() void PresetUpdater::sync(PresetBundle *preset_bundle) { - p->set_download_prefs(GUI::get_app_config()); + p->set_download_prefs(GUI::wxGetApp().app_config); if (!p->enabled_version_check && !p->enabled_config_update) { return; } // Copy the whole vendors data for use in the background thread @@ -509,7 +510,7 @@ void PresetUpdater::slic3r_update_notify() return; } - auto* app_config = GUI::get_app_config(); + auto* app_config = GUI::wxGetApp().app_config; const auto ver_slic3r = Semver::parse(SLIC3R_VERSION); const auto ver_online_str = app_config->get("version_online"); const auto ver_online = Semver::parse(ver_online_str); @@ -601,7 +602,7 @@ bool PresetUpdater::config_update() const p->perform_updates(std::move(updates)); // Reload global configuration - auto *app_config = GUI::get_app_config(); + auto *app_config = GUI::wxGetApp().app_config; GUI::get_preset_bundle()->load_presets(*app_config); GUI::load_current_presets(); } else { diff --git a/src/slic3r/Utils/PresetUpdater.hpp b/src/slic3r/Utils/PresetUpdater.hpp index 6a53cca816..451e8b2cf5 100644 --- a/src/slic3r/Utils/PresetUpdater.hpp +++ b/src/slic3r/Utils/PresetUpdater.hpp @@ -13,7 +13,7 @@ class PresetBundle; class PresetUpdater { public: - PresetUpdater(int version_online_event); + PresetUpdater(); PresetUpdater(PresetUpdater &&) = delete; PresetUpdater(const PresetUpdater &) = delete; PresetUpdater &operator=(PresetUpdater &&) = delete; From 6b2a4ffe03097e586a633cf1d6ab95f9f2d13a29 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Fri, 21 Sep 2018 11:40:32 +0200 Subject: [PATCH 019/186] Paths to resources / icons / images are set. --- src/libslic3r/PrintConfig.cpp | 19 ++++++++++++++++-- src/libslic3r/PrintConfig.hpp | 4 ++++ src/slic3r.cpp | 37 +++++++++++++++++++++++------------ src/slic3r/GUI/GUI_App.cpp | 12 +++--------- src/slic3r/GUI/GUI_App.hpp | 2 -- src/slic3r/GUI/MainFrame.cpp | 12 +++++++----- 6 files changed, 55 insertions(+), 31 deletions(-) diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 0612330691..4ed37a1531 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -2612,6 +2612,14 @@ CLIConfigDef::CLIConfigDef() def->cli = "cut"; def->default_value = new ConfigOptionFloat(0); + def = this->add("datadir", coString); + def->label = L("User data directory"); + def->tooltip = L("Load and store settings at the given directory. " + "This is useful for maintaining different profiles or including " + "configurations from a network storage."); + def->cli = "datadir"; + def->default_value = new ConfigOptionString(); + def = this->add("export_3mf", coBool); def->label = L("Export 3MF"); def->tooltip = L("Slice the model and export slices as 3MF."); @@ -2632,9 +2640,10 @@ CLIConfigDef::CLIConfigDef() def = this->add("gui", coBool); def->label = L("Use GUI"); - def->tooltip = L("Start the Slic3r GUI."); + def->tooltip = L("Forces the GUI launch instead of command line slicing " + "(if you supply a model file, it will be loaded into the plater)"); def->cli = "gui"; - def->default_value = new ConfigOptionBool(false); + def->default_value = new ConfigOptionBool(true); def = this->add("info", coBool); def->label = L("Output Model Info"); @@ -2647,6 +2656,12 @@ CLIConfigDef::CLIConfigDef() def->tooltip = L("Load configuration from the specified file. It can be used more than once to load options from multiple files."); def->cli = "load"; def->default_value = new ConfigOptionStrings(); + + def = this->add("no_gui", coBool); + def->label = L("Do not use GUI"); + def->tooltip = L("Forces the command line slicing instead of gui. This takes precedence over --gui if both are present."); + def->cli = "no-gui"; + def->default_value = new ConfigOptionBool(false); def = this->add("output", coString); def->label = L("Output File"); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 0475f4ecba..dec528d58b 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -982,11 +982,13 @@ class CLIConfig : public virtual ConfigBase, public StaticConfig { public: ConfigOptionFloat cut; + ConfigOptionString datadir; ConfigOptionBool export_3mf; ConfigOptionBool gui; ConfigOptionBool info; ConfigOptionBool help; ConfigOptionStrings load; + ConfigOptionBool no_gui; ConfigOptionString output; ConfigOptionFloat rotate; ConfigOptionFloat rotate_x; @@ -1008,11 +1010,13 @@ public: ConfigOption* optptr(const t_config_option_key &opt_key, bool create = false) override { OPT_PTR(cut); + OPT_PTR(datadir); OPT_PTR(export_3mf); OPT_PTR(gui); OPT_PTR(help); OPT_PTR(info); OPT_PTR(load); + OPT_PTR(no_gui); OPT_PTR(output); OPT_PTR(rotate); OPT_PTR(rotate_x); diff --git a/src/slic3r.cpp b/src/slic3r.cpp index a8d9d61b04..e836bb90d8 100644 --- a/src/slic3r.cpp +++ b/src/slic3r.cpp @@ -5,6 +5,7 @@ #include "TriangleMesh.hpp" #include "Format/3mf.hpp" #include "libslic3r.h" +#include "Utils.hpp" #include #include #include @@ -30,6 +31,7 @@ using namespace Slic3r; int main(int argc, char **argv) { // Convert arguments to UTF-8 (needed on Windows). argv then points to memory owned by a. + //FIXME On Windows, we want to receive the arguments as 16bit characters! boost::nowide::args a(argc, argv); // parse all command line options into a DynamicConfig @@ -41,29 +43,38 @@ int main(int argc, char **argv) return 0; } + boost::filesystem::path path_to_binary = boost::filesystem::system_complete(argv[0]); + boost::filesystem::path path_resources = path_to_binary.parent_path(); + path_resources /= (path_to_binary.stem().string() == "slic3r-gui") ? + // Running from the build directory: + "../../resources" : + // Running from an installation directory: +#if APPLE + '/../Resources' +#else + "resources" +#endif + ; + set_resources_dir(path_resources.string()); + set_var_dir((path_resources / "icons").string()); + set_local_dir((path_resources / "localization").string()); + // apply command line options to a more handy CLIConfig CLIConfig cli_config; cli_config.apply(config, true); - + set_local_dir(cli_config.datadir.value); + DynamicPrintConfig print_config; + if ((argc == 1 || cli_config.gui.value) && ! cli_config.no_gui.value && ! cli_config.help.value && cli_config.save.value.empty()) { #if 1 - GUI::GUI_App *gui = new GUI::GUI_App(); - GUI::GUI_App::SetInstance(gui); - wxEntry(argc, argv); -#endif - -#ifdef USE_WX - if (cli_config.gui) { - GUI::App *gui = new GUI::App(); - GUI::App::SetInstance(gui); + GUI::GUI_App *gui = new GUI::GUI_App(); + GUI::GUI_App::SetInstance(gui); wxEntry(argc, argv); - } #else - if (cli_config.gui) { std::cout << "GUI support has not been built." << "\n"; - } #endif + } // load config files supplied via --load for (const std::string &file : cli_config.load.values) { if (!boost::filesystem::exists(file)) { diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 282391d429..17f3b53b2d 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -40,17 +41,10 @@ bool GUI_App::OnInit() // Unix: ~/ .Slic3r // Windows : "C:\Users\username\AppData\Roaming\Slic3r" or "C:\Documents and Settings\username\Application Data\Slic3r" // Mac : "~/Library/Application Support/Slic3r" - datadir.empty() ? - Slic3r::set_data_dir(wxStandardPaths::Get().GetUserDataDir().ToStdString()) : - Slic3r::set_data_dir(datadir); + if (data_dir().empty()) + Slic3r::set_data_dir(wxStandardPaths::Get().GetUserDataDir().ToUTF8().data()); // set_wxapp(this); // #ys_FIXME - // #ys_FIXME temporary workaround - if (var_dir().empty()) - set_var_dir("c:\\src\\Slic3r_TMP\\resources\\icons"); - if (localization_dir().empty()) - set_local_dir("c:\\src\\Slic3r_TMP\\resources\\localization"); - app_config = new AppConfig(); // set_app_config(app_config);// #ys_FIXME preset_bundle = new PresetBundle(); diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 880b5039f4..91a7b2742f 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -42,8 +42,6 @@ class Tab; class GUI_App : public wxApp { - // Datadir provided on the command line. - std::string datadir = ""; bool no_plater{ true }; bool app_conf_exists{ false }; diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 48fb382a1a..801c08a5f7 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -57,12 +57,14 @@ wxFrame(NULL, wxID_ANY, "FORK_NAME-VERSION", wxDefaultPosition, wxDefaultSize, w m_statusbar->set_status_text(_(L("Version ")) + "Slic3r_VERSION" + // Slic3r::VERSION + _(L(" - Remember to check for updates at http://github.com/prusa3d/slic3r/releases"))); - // Make the global status bar and its progress indicator available in C++ - m_appController->set_global_progress_indicator(m_statusbar); -// m_appController->set_model(m_plater->model); -// m_appController->set_print(m_plater->print); -// m_plater->appController = m_appController; + // m_appController->set_model(m_plater->model); + // m_appController->set_print(m_plater->print); + // m_plater->appController = m_appController; + GUI::set_gui_appctl(); + + // Make the global status bar and its progress indicator available in C++ + m_appController->set_global_progress_indicator(m_statusbar); m_loaded = true; From e4373b6edd19d9c1a5aed16c47a0efac139e7e32 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Fri, 21 Sep 2018 12:54:40 +0200 Subject: [PATCH 020/186] Fix of incorrect path separator in include. --- src/slic3r/GUI/GUI_ObjectParts.cpp | 2 +- src/slic3r/GUI/MainFrame.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectParts.cpp b/src/slic3r/GUI/GUI_ObjectParts.cpp index ab07374ee0..4b3198926c 100644 --- a/src/slic3r/GUI/GUI_ObjectParts.cpp +++ b/src/slic3r/GUI/GUI_ObjectParts.cpp @@ -158,7 +158,7 @@ void init_mesh_icons(){ bool is_parts_changed(){return m_parts_changed;} bool is_part_settings_changed(){ return m_part_settings_changed; } -static wxString dots("…", wxConvUTF8); +static wxString dots("…", wxConvUTF8); void set_tooltip_for_item(const wxPoint& pt) { diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 801c08a5f7..ba80aca714 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -9,7 +9,7 @@ #include "Tab.hpp" #include "PresetBundle.hpp" -#include "..\AppController.hpp" +#include "../AppController.hpp" #include "ProgressStatusBar.hpp" #include "3DScene.hpp" #include "Print.hpp" From 3658f96b162bca4d100fac0533d42456364dc94d Mon Sep 17 00:00:00 2001 From: bubnikv Date: Fri, 21 Sep 2018 15:42:31 +0200 Subject: [PATCH 021/186] Fixed compilation on Linux / OSX. --- src/slic3r/GUI/MainFrame.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index ba80aca714..abad304248 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include "Tab.hpp" #include "PresetBundle.hpp" @@ -647,7 +648,9 @@ void MainFrame::export_config() !m_last_config.IsEmpty() ? get_dir_name(m_last_config) : wxGetApp().app_config->get_last_dir(), !m_last_config.IsEmpty() ? get_base_name(m_last_config) : "config.ini", FILE_WILDCARDS.at("ini"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT); - wxString file = dlg->ShowModal() == wxID_OK ? dlg->GetPath() : wxEmptyString; + wxString file; + if (dlg->ShowModal() == wxID_OK) + file = dlg->GetPath(); dlg->Destroy(); if (!file.IsEmpty()) { wxGetApp().app_config->update_config_dir(get_dir_name(file)); @@ -697,7 +700,9 @@ void MainFrame::export_configbundle() !m_last_config.IsEmpty() ? get_dir_name(m_last_config) : wxGetApp().app_config->get_last_dir(), "Slic3r_config_bundle.ini", FILE_WILDCARDS.at("ini"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT); - wxString file = dlg->ShowModal() == wxID_OK ? dlg->GetPath() : wxEmptyString; + wxString file; + if (dlg->ShowModal() == wxID_OK) + file = dlg->GetPath(); dlg->Destroy(); if (!file.IsEmpty()) { // Export the config bundle. From 8841b7ae2c5fdcfa93adf7565a8428bdc3b8b582 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Fri, 21 Sep 2018 15:59:39 +0200 Subject: [PATCH 022/186] Another compilation fix --- src/slic3r/GUI/MainFrame.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index abad304248..c8a32208f6 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -18,7 +18,6 @@ #include "AppConfig.hpp" #include -#include #include "GUI_App.hpp" namespace Slic3r { From 0a7646cd946900198280caf33a18b1d979e27d26 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Fri, 21 Sep 2018 16:10:16 +0200 Subject: [PATCH 023/186] Fixed path to resources on OSX. --- src/slic3r.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/slic3r.cpp b/src/slic3r.cpp index e836bb90d8..73bf49b273 100644 --- a/src/slic3r.cpp +++ b/src/slic3r.cpp @@ -50,7 +50,7 @@ int main(int argc, char **argv) "../../resources" : // Running from an installation directory: #if APPLE - '/../Resources' + "../Resources" #else "resources" #endif From c37dc44ec4c7868d2cc31f885f52c1c8be1f0670 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Fri, 21 Sep 2018 16:38:42 +0200 Subject: [PATCH 024/186] Modified resources directory in Linux installation. --- src/slic3r.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/slic3r.cpp b/src/slic3r.cpp index 73bf49b273..2c430d7b0c 100644 --- a/src/slic3r.cpp +++ b/src/slic3r.cpp @@ -45,14 +45,27 @@ int main(int argc, char **argv) boost::filesystem::path path_to_binary = boost::filesystem::system_complete(argv[0]); boost::filesystem::path path_resources = path_to_binary.parent_path(); + // Path from the Slic3r binary to its resources. path_resources /= (path_to_binary.stem().string() == "slic3r-gui") ? // Running from the build directory: - "../../resources" : + "../../resources" : // Running from an installation directory: #if APPLE + // The application is packed in the .dmg archive as 'Slic3r.app/Contents/MacOS/Slic3r' + // The resources are packed to 'Slic3r.app/Contents/Resources' "../Resources" #else + #if WIN32 + // The application is packed in the .zip archive in the root, + // The resources are packed to 'resources' + // Path from Slic3r binary to resources: "resources" + #else + // The application is packed in the .tar.bz archive (or in AppImage) as 'bin/slic3r', + // The resources are packed to 'resources' + // Path from Slic3r binary to resources: + "../resources" + #endif #endif ; set_resources_dir(path_resources.string()); From b28047af5e9b0e39edaf840a3801eb5549344c53 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Fri, 21 Sep 2018 17:16:44 +0200 Subject: [PATCH 025/186] Yet another fix of platform specific paths to resources. --- src/slic3r.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/slic3r.cpp b/src/slic3r.cpp index 2c430d7b0c..95ba4dfb6d 100644 --- a/src/slic3r.cpp +++ b/src/slic3r.cpp @@ -50,12 +50,12 @@ int main(int argc, char **argv) // Running from the build directory: "../../resources" : // Running from an installation directory: -#if APPLE +#ifdef __APPLE__ // The application is packed in the .dmg archive as 'Slic3r.app/Contents/MacOS/Slic3r' // The resources are packed to 'Slic3r.app/Contents/Resources' "../Resources" #else - #if WIN32 + #ifdef _WIN32 // The application is packed in the .zip archive in the root, // The resources are packed to 'resources' // Path from Slic3r binary to resources: From 8e1b5157b4f9be6dc4fbab4a2179b3ce29902b12 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Fri, 21 Sep 2018 19:37:35 +0200 Subject: [PATCH 026/186] Moved the remaining Perl dependencies to xs/CMakeLists.txt --- CMakeLists.txt | 31 ++++--------------------------- src/slic3r.cpp | 14 ++++++++++++++ src/slic3r.manifest | 37 +++++++++++++++++++++++++++++++++++++ src/slic3r.rc | 25 +++++++++++++++++++++++++ xs/CMakeLists.txt | 25 +++++++++++++++++++++++++ 5 files changed, 105 insertions(+), 27 deletions(-) create mode 100644 src/slic3r.manifest create mode 100644 src/slic3r.rc diff --git a/CMakeLists.txt b/CMakeLists.txt index 24fae45c6f..cd1854304c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,26 +27,6 @@ if (MSVC AND SLIC3R_MSVC_COMPILE_PARALLEL) add_compile_options(/MP) endif () -# Find the Perl interpreter, add local-lib to PATH and PERL5LIB environment variables, -# so the locally installed modules (mainly the Alien::wxPerl) will be reached. -if (WIN32) - set(ENV_PATH_SEPARATOR ";") -else() - set(ENV_PATH_SEPARATOR ":") -endif() -set(ENV{PATH} "${PROJECT_SOURCE_DIR}/local-lib/bin${ENV_PATH_SEPARATOR}$ENV{PATH}") -set(PERL_INCLUDE "${PROJECT_SOURCE_DIR}/local-lib/lib/perl5${ENV_PATH_SEPARATOR}$ENV{PERL5LIB}") -message("PATH: $ENV{PATH}") -message("PERL_INCLUDE: ${PERL_INCLUDE}") -find_package(Perl REQUIRED) -if (WIN32) - # On Windows passing the PERL5LIB variable causes various problems (such as with MAX_PATH and others), - # basically I've found no good way to do it on Windows. - set(PERL5LIB_ENV_CMD "") -else() - set(PERL5LIB_ENV_CMD ${CMAKE_COMMAND} -E env PERL5LIB=${PERL_INCLUDE}) -endif() - # CMAKE_PREFIX_PATH is used to point CMake to the remaining dependencies (Boost, TBB, ...) # We pick it from environment if it is not defined in another way if(NOT DEFINED CMAKE_PREFIX_PATH) @@ -110,7 +90,7 @@ include_directories(${LIBDIR}/libslic3r ${LIBDIR}/clipper ${LIBDIR}/polypartitio if(WIN32) # BOOST_ALL_NO_LIB: Avoid the automatic linking of Boost libraries on Windows. Rather rely on explicit linking. - add_definitions(-D_USE_MATH_DEFINES -D_WIN32 -DBOOST_ALL_NO_LIB -DBOOST_USE_WINAPI_VERSION=0x601) + add_definitions(-D_USE_MATH_DEFINES -D_WIN32 -DBOOST_ALL_NO_LIB -DBOOST_USE_WINAPI_VERSION=0x601 -D_CRT_SECURE_NO_WARNINGS) endif() add_definitions(-DwxUSE_UNICODE -D_UNICODE -DUNICODE -DWXINTL_NO_GETTEXT_MACRO) @@ -120,12 +100,9 @@ if (SLIC3R_PROFILE) add_definitions(-DSLIC3R_PROFILE) endif () -# Perl specific stuff -find_package(PerlLibs REQUIRED) -set(PerlEmbed_DEBUG 1) -find_package(PerlEmbed REQUIRED) # If the Perl is compiled with optimization off, disable optimization over the whole project. -if (WIN32 AND ";${PerlEmbed_CCFLAGS};" MATCHES ";[-/]Od;") +if (0) +#if (WIN32 AND ";${PerlEmbed_CCFLAGS};" MATCHES ";[-/]Od;") message(STATUS "Perl compiled without optimization. Disabling optimization for the Slic3r build.") message("Old CMAKE_CXX_FLAGS_RELEASE: ${CMAKE_CXX_FLAGS_RELEASE}") message("Old CMAKE_CXX_FLAGS_RELWITHDEBINFO: ${CMAKE_CXX_FLAGS_RELEASE}") @@ -138,7 +115,7 @@ if (WIN32 AND ";${PerlEmbed_CCFLAGS};" MATCHES ";[-/]Od;") set(CMAKE_C_FLAGS "/MD /Od /Zi /DNDEBUG /DWIN32 /DTBB_USE_ASSERT") endif() # The following line will add -fPIC on Linux to make the XS.so rellocable. -add_definitions(${PerlEmbed_CCCDLFLAGS}) +#add_definitions(${PerlEmbed_CCCDLFLAGS}) # Find and configure boost if(SLIC3R_STATIC) diff --git a/src/slic3r.cpp b/src/slic3r.cpp index 95ba4dfb6d..35ec623167 100644 --- a/src/slic3r.cpp +++ b/src/slic3r.cpp @@ -1,3 +1,17 @@ +#ifdef WIN32 + // Why? + #define _WIN32_WINNT 0x0502 + // The standard Windows includes. + #define WIN32_LEAN_AND_MEAN + #define NOMINMAX + #include + #include + // Let the NVIDIA and AMD know we want to use their graphics card + // on a dual graphics card system. + __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001; + __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1; +#endif /* WIN32 */ + #include "Config.hpp" #include "Geometry.hpp" #include "Model.hpp" diff --git a/src/slic3r.manifest b/src/slic3r.manifest new file mode 100644 index 0000000000..c480ca3374 --- /dev/null +++ b/src/slic3r.manifest @@ -0,0 +1,37 @@ + + + + Perl + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/slic3r.rc b/src/slic3r.rc new file mode 100644 index 0000000000..7ae8653dd8 --- /dev/null +++ b/src/slic3r.rc @@ -0,0 +1,25 @@ +1 VERSIONINFO +FILEVERSION SLIC3R_RC_VERSION +PRODUCTVERSION SLIC3R_RC_VERSION +{ + BLOCK "StringFileInfo" + { + BLOCK "040904E4" + { + VALUE "CompanyName", "Prusa Research" + VALUE "FileDescription", "Slic3r Prusa Edition" + VALUE "FileVersion", "SLIC3R_BUILD_ID" + VALUE "ProductName", "Slic3r Prusa Edition" + VALUE "ProductVersion", "SLIC3R_BUILD_ID" + VALUE "InternalName", "Slic3r Prusa Edition" + VALUE "LegalCopyright", "Copyright \251 2011-2017 Alessandro Ranelucci, \251 2016 Prusa Research" + VALUE "OriginalFilename", "slic3r.exe" + } + } + BLOCK "VarFileInfo" + { + VALUE "Translation", 0x409, 1252 + } +} +2 ICON "../resources/icons/Slic3r.ico" +1 24 "slic3r.manifest" diff --git a/xs/CMakeLists.txt b/xs/CMakeLists.txt index f3afca619b..4ea8bb4d2d 100644 --- a/xs/CMakeLists.txt +++ b/xs/CMakeLists.txt @@ -1,5 +1,30 @@ project(XS) +# Find the Perl interpreter, add local-lib to PATH and PERL5LIB environment variables, +# so the locally installed modules (mainly the Alien::wxPerl) will be reached. +if (WIN32) + set(ENV_PATH_SEPARATOR ";") +else() + set(ENV_PATH_SEPARATOR ":") +endif() +set(ENV{PATH} "${PROJECT_SOURCE_DIR}/local-lib/bin${ENV_PATH_SEPARATOR}$ENV{PATH}") +set(PERL_INCLUDE "${PROJECT_SOURCE_DIR}/local-lib/lib/perl5${ENV_PATH_SEPARATOR}$ENV{PERL5LIB}") +message("PATH: $ENV{PATH}") +message("PERL_INCLUDE: ${PERL_INCLUDE}") +find_package(Perl REQUIRED) +if (WIN32) + # On Windows passing the PERL5LIB variable causes various problems (such as with MAX_PATH and others), + # basically I've found no good way to do it on Windows. + set(PERL5LIB_ENV_CMD "") +else() + set(PERL5LIB_ENV_CMD ${CMAKE_COMMAND} -E env PERL5LIB=${PERL_INCLUDE}) +endif() + +# Perl specific stuff +find_package(PerlLibs REQUIRED) +set(PerlEmbed_DEBUG 1) +find_package(PerlEmbed REQUIRED) + # Generate the Slic3r Perl module (XS) typemap file. set(MyTypemap ${CMAKE_CURRENT_BINARY_DIR}/typemap) add_custom_command( From 49c3d5989710fa251d5baa1ee3a626cce4a2056e Mon Sep 17 00:00:00 2001 From: bubnikv Date: Fri, 21 Sep 2018 20:11:33 +0200 Subject: [PATCH 027/186] Further reduction of Perl dependencies. Now the Perl dependencies only influence the XS project (and the unit / integration tests). --- CMakeLists.txt | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cd1854304c..45463abdd5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,11 +43,13 @@ enable_testing () # Enable C++11 language standard. set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) - -# Enable C11 language standard. set(CMAKE_C_STANDARD 11) set(CMAKE_C_STANDARD_REQUIRED ON) +# To be able to link libslic3r with the Perl XS module. +# Once we get rid of Perl and libslic3r is linked statically, we can get rid of -fPIC +set(CMAKE_POSITION_INDEPENDENT_CODE ON) + # WIN10SDK_PATH is used to point CMake to the WIN10 SDK installation directory. # We pick it from environment if it is not defined in another way if(WIN32) @@ -100,9 +102,8 @@ if (SLIC3R_PROFILE) add_definitions(-DSLIC3R_PROFILE) endif () -# If the Perl is compiled with optimization off, disable optimization over the whole project. +# Disable optimization even with debugging on. if (0) -#if (WIN32 AND ";${PerlEmbed_CCFLAGS};" MATCHES ";[-/]Od;") message(STATUS "Perl compiled without optimization. Disabling optimization for the Slic3r build.") message("Old CMAKE_CXX_FLAGS_RELEASE: ${CMAKE_CXX_FLAGS_RELEASE}") message("Old CMAKE_CXX_FLAGS_RELWITHDEBINFO: ${CMAKE_CXX_FLAGS_RELEASE}") @@ -114,8 +115,6 @@ if (0) set(CMAKE_CXX_FLAGS "/MD /Od /Zi /EHsc /DNDEBUG /DWIN32 /DTBB_USE_ASSERT") set(CMAKE_C_FLAGS "/MD /Od /Zi /DNDEBUG /DWIN32 /DTBB_USE_ASSERT") endif() -# The following line will add -fPIC on Linux to make the XS.so rellocable. -#add_definitions(${PerlEmbed_CCCDLFLAGS}) # Find and configure boost if(SLIC3R_STATIC) From bb386bb148eaf8d41819270ba555c126728d650e Mon Sep 17 00:00:00 2001 From: bubnikv Date: Fri, 21 Sep 2018 21:16:09 +0200 Subject: [PATCH 028/186] Simplified dependencies. --- src/CMakeLists.txt | 4 +++- src/libslic3r/CMakeLists.txt | 1 - src/libslic3r/Layer.cpp | 2 +- xs/CMakeLists.txt | 10 +--------- 4 files changed, 5 insertions(+), 12 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fcf7c17dcc..40bda7aad8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -53,6 +53,8 @@ endif() add_subdirectory(slic3r) # Create a slic3r executable +#FIXME add Windows resource file +#add_executable(slic3r slic3r.cpp slic3r.rc) add_executable(slic3r slic3r.cpp) if(SLIC3R_GUI) set_target_properties(slic3r PROPERTIES OUTPUT_NAME "slic3r-gui") @@ -71,7 +73,7 @@ endif () # Add the Slic3r GUI library, libcurl, OpenGL and GLU libraries. if (SLIC3R_GUI) - target_link_libraries(slic3r libslic3r_gui ${wxWidgets_LIBRARIES} ${CURL_LIBRARIES}) + target_link_libraries(slic3r libslic3r_gui ${wxWidgets_LIBRARIES}) # Configure libcurl & OpenSSL find_package(CURL REQUIRED) diff --git a/src/libslic3r/CMakeLists.txt b/src/libslic3r/CMakeLists.txt index 6955dd1e7e..16b70a8da4 100644 --- a/src/libslic3r/CMakeLists.txt +++ b/src/libslic3r/CMakeLists.txt @@ -165,7 +165,6 @@ target_link_libraries(libslic3r qhull semver ${TBB_LIBRARIES} -# ${wxWidgets_LIBRARIES} ) if(SLIC3R_PROFILE) diff --git a/src/libslic3r/Layer.cpp b/src/libslic3r/Layer.cpp index 6c2bd0da90..afdde1852d 100644 --- a/src/libslic3r/Layer.cpp +++ b/src/libslic3r/Layer.cpp @@ -154,7 +154,7 @@ void Layer::make_fills() layerm->fills.clear(); make_fill(*layerm, layerm->fills); #ifndef NDEBUG - for (size_t i = 0; i < layerm.fills.entities.size(); ++ i) + for (size_t i = 0; i < layerm->fills.entities.size(); ++ i) assert(dynamic_cast(layerm->fills.entities[i]) != NULL); #endif } diff --git a/xs/CMakeLists.txt b/xs/CMakeLists.txt index 4ea8bb4d2d..9a08beadc7 100644 --- a/xs/CMakeLists.txt +++ b/xs/CMakeLists.txt @@ -117,23 +117,15 @@ if(APPLE) # Ignore undefined symbols of the perl interpreter, they will be found in the caller image. target_link_libraries(XS "-undefined dynamic_lookup") endif() -target_link_libraries(XS libslic3r admesh miniz clipper nowide polypartition poly2tri semver avrdude qhull) -if(SLIC3R_PROFILE) - target_link_libraries(XS Shiny) -endif() +target_link_libraries(XS libslic3r) target_include_directories(XS PRIVATE src) target_compile_definitions(XS PRIVATE -DSLIC3RXS) set_target_properties(XS PROPERTIES PREFIX "") # Prevent cmake from generating libXS.so instead of XS.so target_link_libraries(XS ${Boost_LIBRARIES}) -# target_link_libraries(XS ${wxWidgets_LIBRARIES}) -# target_link_libraries(XS ${CURL_LIBRARIES}) -# target_link_libraries(XS ${OPENSSL_LIBRARIES}) if (APPLE) -# add_compile_options(-stdlib=libc++) -# add_definitions(-DBOOST_THREAD_DONT_USE_CHRONO -DBOOST_NO_CXX11_RVALUE_REFERENCES -DBOOST_THREAD_USES_MOVE) # -liconv: boost links to libiconv by default target_link_libraries(XS "-liconv -framework IOKit" "-framework CoreFoundation" -lc++) elseif (MSVC) From 60a192ef34aaae4103fc97a32506d3b3bc19d2b2 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Fri, 21 Sep 2018 21:54:54 +0200 Subject: [PATCH 029/186] Removed duplicate definition of QHull debug printfs --- src/qhull/CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/qhull/CMakeLists.txt b/src/qhull/CMakeLists.txt index d798b018fa..e25da35e3e 100644 --- a/src/qhull/CMakeLists.txt +++ b/src/qhull/CMakeLists.txt @@ -80,11 +80,9 @@ set(libqhull_SOURCES src/libqhull_r/mem_r.c src/libqhull_r/random_r.c src/libqhull_r/usermem_r.c - src/libqhull_r/userprintf_r.c src/libqhull_r/io_r.c src/libqhull_r/user_r.c src/libqhull_r/rboxlib_r.c - src/libqhull_r/userprintf_rbox_r.c # C++ interface to reentrant Qhull SOURCES: src/libqhullcpp/Coordinates.cpp From 9f2cd347e37e46c4b5a2cb1871a9d26fce3abc74 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Fri, 21 Sep 2018 23:00:49 +0200 Subject: [PATCH 030/186] Fix of a set method to make ConfigOptionEnum compatible with ConfigOptionEnumGeneric. --- src/libslic3r/Config.hpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/libslic3r/Config.hpp b/src/libslic3r/Config.hpp index 2704bbcf3b..e8ed433561 100644 --- a/src/libslic3r/Config.hpp +++ b/src/libslic3r/Config.hpp @@ -810,6 +810,14 @@ public: ConfigOption* clone() const override { return new ConfigOptionEnum(*this); } ConfigOptionEnum& operator=(const ConfigOption *opt) { this->set(opt); return *this; } bool operator==(const ConfigOptionEnum &rhs) const { return this->value == rhs.value; } + int getInt() const override { return (int)this->value; } + + void set(const ConfigOption *rhs) override { + if (rhs->type() != this->type()) + throw std::runtime_error("ConfigOptionEnum: Assigning an incompatible type"); + // rhs could be of the following type: ConfigOptionEnumGeneric or ConfigOptionEnum + this->value = (T)rhs->getInt(); + } std::string serialize() const override { @@ -879,6 +887,13 @@ public: ConfigOptionEnumGeneric& operator=(const ConfigOption *opt) { this->set(opt); return *this; } bool operator==(const ConfigOptionEnumGeneric &rhs) const { return this->value == rhs.value; } + void set(const ConfigOption *rhs) override { + if (rhs->type() != this->type()) + throw std::runtime_error("ConfigOptionEnumGeneric: Assigning an incompatible type"); + // rhs could be of the following type: ConfigOptionEnumGeneric or ConfigOptionEnum + this->value = rhs->getInt(); + } + std::string serialize() const override { for (const auto &kvp : *this->keys_map) From 96e035b2f83f851126a4cf9583ff5b5d4b7f1e5d Mon Sep 17 00:00:00 2001 From: bubnikv Date: Mon, 24 Sep 2018 11:53:05 +0200 Subject: [PATCH 031/186] Added various manifests, added auto generation of includes and manifests from version and build variables, resurrected SLIC3R_LOGLEVEL env var. --- CMakeLists.txt | 15 +++++---- src/CMakeLists.txt | 13 +++++--- src/libslic3r/CMakeLists.txt | 5 ++- src/libslic3r/libslic3r.h | 6 ++-- src/libslic3r/libslic3r_version.h.in | 8 +++++ .../msw/slic3r.manifest.in} | 2 +- src/{slic3r.rc => platform/msw/slic3r.rc.in} | 10 +++--- src/platform/osx/Info.plist.in | 32 +++++++++++++++++++ src/slic3r.cpp | 13 +++++++- src/slic3r/GUI/MainFrame.cpp | 13 +++++--- version.inc | 9 ++++++ 11 files changed, 100 insertions(+), 26 deletions(-) create mode 100644 src/libslic3r/libslic3r_version.h.in rename src/{slic3r.manifest => platform/msw/slic3r.manifest.in} (95%) rename src/{slic3r.rc => platform/msw/slic3r.rc.in} (70%) create mode 100644 src/platform/osx/Info.plist.in create mode 100644 version.inc diff --git a/CMakeLists.txt b/CMakeLists.txt index 45463abdd5..ac2e642228 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,9 @@ project(Slic3r) cmake_minimum_required(VERSION 3.2) +include("version.inc") +set(SLIC3R_RESOURCES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/resources") + if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) message(STATUS "No build type selected, default to Release") set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build type (default Release)" FORCE) @@ -108,12 +111,12 @@ if (0) message("Old CMAKE_CXX_FLAGS_RELEASE: ${CMAKE_CXX_FLAGS_RELEASE}") message("Old CMAKE_CXX_FLAGS_RELWITHDEBINFO: ${CMAKE_CXX_FLAGS_RELEASE}") message("Old CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS_RELEASE}") - set(CMAKE_CXX_FLAGS_RELEASE "/MD /Od /Zi /EHsc /DNDEBUG /DWIN32 /DTBB_USE_ASSERT") - set(CMAKE_C_FLAGS_RELEASE "/MD /Od /Zi /DNDEBUG /DWIN32 /DTBB_USE_ASSERT") - set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "/MD /Od /Zi /EHsc /DNDEBUG /DWIN32 /DTBB_USE_ASSERT") - set(CMAKE_C_FLAGS_RELWITHDEBINFO "/MD /Od /Zi /DNDEBUG /DWIN32 /DTBB_USE_ASSERT") - set(CMAKE_CXX_FLAGS "/MD /Od /Zi /EHsc /DNDEBUG /DWIN32 /DTBB_USE_ASSERT") - set(CMAKE_C_FLAGS "/MD /Od /Zi /DNDEBUG /DWIN32 /DTBB_USE_ASSERT") + set(CMAKE_CXX_FLAGS_RELEASE "/MD /Od /Zi /EHsc /DWIN32 /DTBB_USE_ASSERT") + set(CMAKE_C_FLAGS_RELEASE "/MD /Od /Zi /DWIN32 /DTBB_USE_ASSERT") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "/MD /Od /Zi /EHsc /DWIN32 /DTBB_USE_ASSERT") + set(CMAKE_C_FLAGS_RELWITHDEBINFO "/MD /Od /Zi /DWIN32 /DTBB_USE_ASSERT") + set(CMAKE_CXX_FLAGS "/MD /Od /Zi /EHsc /DWIN32 /DTBB_USE_ASSERT") + set(CMAKE_C_FLAGS "/MD /Od /Zi /DWIN32 /DTBB_USE_ASSERT") endif() # Find and configure boost diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 40bda7aad8..b19c5cd022 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -53,9 +53,11 @@ endif() add_subdirectory(slic3r) # Create a slic3r executable -#FIXME add Windows resource file -#add_executable(slic3r slic3r.cpp slic3r.rc) -add_executable(slic3r slic3r.cpp) +# Process mainfests for various platforms. +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/platform/msw/slic3r.rc.in ${CMAKE_CURRENT_BINARY_DIR}/slic3r.rc @ONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/platform/msw/slic3r.manifest.in ${CMAKE_CURRENT_BINARY_DIR}/slic3r.manifest @ONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/platform/osx/Info.plist.in ${CMAKE_CURRENT_BINARY_DIR}/Info.plist @ONLY) +add_executable(slic3r slic3r.cpp ${CMAKE_CURRENT_BINARY_DIR}/slic3r.rc) if(SLIC3R_GUI) set_target_properties(slic3r PROPERTIES OUTPUT_NAME "slic3r-gui") else() @@ -67,7 +69,10 @@ if (APPLE) # add_definitions(-DBOOST_THREAD_DONT_USE_CHRONO -DBOOST_NO_CXX11_RVALUE_REFERENCES -DBOOST_THREAD_USES_MOVE) # -liconv: boost links to libiconv by default target_link_libraries(slic3r "-liconv -framework IOKit" "-framework CoreFoundation" -lc++) -elseif (NOT MSVC) +elseif (MSVC) + # Manifest is provided through slic3r.rc, don't generate your own. + set(CMAKE_EXE_LINKER_FLAGS /MANIFEST:NO) +else () target_link_libraries(slic3r -ldl -lstdc++) endif () diff --git a/src/libslic3r/CMakeLists.txt b/src/libslic3r/CMakeLists.txt index 16b70a8da4..b5974489d0 100644 --- a/src/libslic3r/CMakeLists.txt +++ b/src/libslic3r/CMakeLists.txt @@ -1,6 +1,8 @@ project(libslic3r) cmake_minimum_required(VERSION 2.6) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libslic3r_version.h.in ${CMAKE_CURRENT_BINARY_DIR}/libslic3r_version.h @ONLY) + add_library(libslic3r STATIC BoundingBox.cpp BoundingBox.hpp @@ -96,6 +98,7 @@ add_library(libslic3r STATIC Layer.hpp LayerRegion.cpp libslic3r.h + "${CMAKE_CURRENT_BINARY_DIR}/libslic3r_version.h" Line.cpp Line.hpp Model.cpp @@ -149,7 +152,7 @@ add_library(libslic3r STATIC ) target_compile_definitions(libslic3r PUBLIC -DUSE_TBB ${PNG_DEFINITIONS}) -target_include_directories(libslic3r PUBLIC BEFORE ${LIBNEST2D_INCLUDES} ${PNG_INCLUDE_DIRS}) +target_include_directories(libslic3r PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${LIBNEST2D_INCLUDES} ${PNG_INCLUDE_DIRS}) target_link_libraries(libslic3r ${LIBNEST2D_LIBRARIES} admesh diff --git a/src/libslic3r/libslic3r.h b/src/libslic3r/libslic3r.h index 5f2f3fba17..a2ee3fc9fa 100644 --- a/src/libslic3r/libslic3r.h +++ b/src/libslic3r/libslic3r.h @@ -1,6 +1,8 @@ #ifndef _libslic3r_h_ #define _libslic3r_h_ +#include "libslic3r_version.h" + // this needs to be included early for MSVC (listing it in Build.PL is not enough) #include #include @@ -15,10 +17,6 @@ #include "Technologies.hpp" -#define SLIC3R_FORK_NAME "Slic3r Prusa Edition" -#define SLIC3R_VERSION "1.41.0" -#define SLIC3R_BUILD "UNKNOWN" - typedef int32_t coord_t; typedef double coordf_t; diff --git a/src/libslic3r/libslic3r_version.h.in b/src/libslic3r/libslic3r_version.h.in new file mode 100644 index 0000000000..2259b2302b --- /dev/null +++ b/src/libslic3r/libslic3r_version.h.in @@ -0,0 +1,8 @@ +#ifndef __SLIC3R_VERSION_H +#define __SLIC3R_VERSION_H + +#define SLIC3R_FORK_NAME "@SLIC3R_FORK_NAME@" +#define SLIC3R_VERSION "@SLIC3R_VERSION@" +#define SLIC3R_BUILD "@SLIC3R_BUILD@" + +#endif /* __SLIC3R_VERSION_H */ diff --git a/src/slic3r.manifest b/src/platform/msw/slic3r.manifest.in similarity index 95% rename from src/slic3r.manifest rename to src/platform/msw/slic3r.manifest.in index c480ca3374..ab1cc5ae21 100644 --- a/src/slic3r.manifest +++ b/src/platform/msw/slic3r.manifest.in @@ -1,6 +1,6 @@ - + Perl diff --git a/src/slic3r.rc b/src/platform/msw/slic3r.rc.in similarity index 70% rename from src/slic3r.rc rename to src/platform/msw/slic3r.rc.in index 7ae8653dd8..493f9f7520 100644 --- a/src/slic3r.rc +++ b/src/platform/msw/slic3r.rc.in @@ -1,6 +1,6 @@ 1 VERSIONINFO -FILEVERSION SLIC3R_RC_VERSION -PRODUCTVERSION SLIC3R_RC_VERSION +FILEVERSION @SLIC3R_RC_VERSION@ +PRODUCTVERSION @SLIC3R_RC_VERSION@ { BLOCK "StringFileInfo" { @@ -8,9 +8,9 @@ PRODUCTVERSION SLIC3R_RC_VERSION { VALUE "CompanyName", "Prusa Research" VALUE "FileDescription", "Slic3r Prusa Edition" - VALUE "FileVersion", "SLIC3R_BUILD_ID" + VALUE "FileVersion", "@SLIC3R_BUILD_ID@" VALUE "ProductName", "Slic3r Prusa Edition" - VALUE "ProductVersion", "SLIC3R_BUILD_ID" + VALUE "ProductVersion", "@SLIC3R_BUILD_ID@" VALUE "InternalName", "Slic3r Prusa Edition" VALUE "LegalCopyright", "Copyright \251 2011-2017 Alessandro Ranelucci, \251 2016 Prusa Research" VALUE "OriginalFilename", "slic3r.exe" @@ -21,5 +21,5 @@ PRODUCTVERSION SLIC3R_RC_VERSION VALUE "Translation", 0x409, 1252 } } -2 ICON "../resources/icons/Slic3r.ico" +2 ICON "@SLIC3R_RESOURCES_DIR@/icons/Slic3r.ico" 1 24 "slic3r.manifest" diff --git a/src/platform/osx/Info.plist.in b/src/platform/osx/Info.plist.in new file mode 100644 index 0000000000..099cb5c375 --- /dev/null +++ b/src/platform/osx/Info.plist.in @@ -0,0 +1,32 @@ + + + + + CFBundleExecutable + Slic3r + CFBundleGetInfoString + Slic3r Copyright (C) 2011-2017 Alessandro Ranellucci, (C) 2016-2018 Prusa Reseach + CFBundleIconFile + Slic3r.icns + CFBundleName + Slic3r + CFBundleShortVersionString + Slic3r @SLIC3R_BUILD_ID@ + CFBundleIdentifier + com.prusa3d.slic3r/ + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleVersion + @SLIC3R_BUILD_ID@ + CGDisableCoalescedUpdates + + NSPrincipalClass + NSApplication + NSHighResolutionCapable + + + diff --git a/src/slic3r.cpp b/src/slic3r.cpp index 35ec623167..29e1e28e9e 100644 --- a/src/slic3r.cpp +++ b/src/slic3r.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #ifdef USE_WX @@ -48,6 +49,16 @@ int main(int argc, char **argv) //FIXME On Windows, we want to receive the arguments as 16bit characters! boost::nowide::args a(argc, argv); + { + const char *loglevel = boost::nowide::getenv("SLIC3R_LOGLEVEL"); + if (loglevel != nullptr) { + if (loglevel[0] >= '0' && loglevel[0] <= '9' && loglevel[1] == 0) + set_logging_level(loglevel[0] - '0'); + else + boost::nowide::cerr << "Invalid SLIC3R_LOGLEVEL environment variable: " << loglevel << std::endl; + } + } + // parse all command line options into a DynamicConfig DynamicPrintAndCLIConfig config; t_config_option_keys input_files; @@ -89,7 +100,7 @@ int main(int argc, char **argv) // apply command line options to a more handy CLIConfig CLIConfig cli_config; cli_config.apply(config, true); - set_local_dir(cli_config.datadir.value); + set_data_dir(cli_config.datadir.value); DynamicPrintConfig print_config; diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index c8a32208f6..e97eab7ae9 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -116,10 +116,15 @@ void MainFrame::init_tabpanel() auto panel = m_tabpanel->GetCurrentPage(); // panel->OnActivate(); if panel->can('OnActivate'); - std::vector tab_names = { "print", "filament", "printer" }; - for (auto& tab_name : tab_names) { - if (tab_name == panel->GetName()) - m_options_tabs.at(tab_name)->OnActivate(); + for (auto& tab_name : { "print", "filament", "printer" }) { + if (tab_name == panel->GetName()) { + // On GTK, the wxEVT_NOTEBOOK_PAGE_CHANGED event is triggered + // before the MainFrame is fully set up. + auto it = m_options_tabs.find(tab_name); + assert(it != m_options_tabs.end()); + if (it != m_options_tabs.end()) + it->second->OnActivate(); + } } }); diff --git a/version.inc b/version.inc new file mode 100644 index 0000000000..5a23105a8d --- /dev/null +++ b/version.inc @@ -0,0 +1,9 @@ +# Included by CMakeLists, edited by the build script +# (the version numbers are generated by the build script from the git current label) + +set(SLIC3R_FORK_NAME "Slic3r Prusa Edition") +set(SLIC3R_VERSION "1.42.0-alpha") +set(SLIC3R_BUILD "UNKNOWN") +set(SLIC3R_RC_VERSION "1,42,0,0") +set(SLIC3R_RC_VERSION_DOTS "1.42.0.0") +set(SLIC3R_BUILD_ID "${SLIC3R_VERSION}+${SLIC3R_BUILD}") From 8296cbe0463387b9c0b3e23e8f60f6da536d4bcf Mon Sep 17 00:00:00 2001 From: bubnikv Date: Mon, 24 Sep 2018 13:07:50 +0200 Subject: [PATCH 032/186] Compile Slic3r versions into slic3r binary --- src/slic3r/GUI/MainFrame.cpp | 6 +++--- version.inc | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index e97eab7ae9..270320f391 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -26,7 +26,7 @@ namespace GUI { static wxString dots("…", wxConvUTF8); MainFrame::MainFrame(const bool no_plater, const bool loaded) : -wxFrame(NULL, wxID_ANY, "FORK_NAME-VERSION", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE), +wxFrame(NULL, wxID_ANY, SLIC3R_BUILD, wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE), m_no_plater(no_plater), m_loaded(loaded) { @@ -54,8 +54,8 @@ wxFrame(NULL, wxID_ANY, "FORK_NAME-VERSION", wxDefaultPosition, wxDefaultSize, w // initialize status bar m_statusbar = new Slic3r::GUI::ProgressStatusBar(this); m_statusbar->embed(this); - m_statusbar->set_status_text(_(L("Version ")) + - "Slic3r_VERSION" + // Slic3r::VERSION + + m_statusbar->set_status_text(_(L("Version ")) + + SLIC3R_VERSION + _(L(" - Remember to check for updates at http://github.com/prusa3d/slic3r/releases"))); // m_appController->set_model(m_plater->model); diff --git a/version.inc b/version.inc index 5a23105a8d..95e2741dd2 100644 --- a/version.inc +++ b/version.inc @@ -3,7 +3,7 @@ set(SLIC3R_FORK_NAME "Slic3r Prusa Edition") set(SLIC3R_VERSION "1.42.0-alpha") -set(SLIC3R_BUILD "UNKNOWN") +set(SLIC3R_BUILD "${SLIC3R_VERSION}+UNKNOWN") +set(SLIC3R_BUILD_ID "${SLIC3R_BUILD_ID}") set(SLIC3R_RC_VERSION "1,42,0,0") set(SLIC3R_RC_VERSION_DOTS "1.42.0.0") -set(SLIC3R_BUILD_ID "${SLIC3R_VERSION}+${SLIC3R_BUILD}") From a9f52955a0b16618c97a857fdf4e4ad092691ffa Mon Sep 17 00:00:00 2001 From: bubnikv Date: Mon, 24 Sep 2018 14:27:03 +0200 Subject: [PATCH 033/186] Fixed app icon on Windows --- src/slic3r/GUI/MainFrame.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 270320f391..6aefb93851 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -33,14 +33,16 @@ wxFrame(NULL, wxID_ANY, SLIC3R_BUILD, wxDefaultPosition, wxDefaultSize, wxDEFAUL // Slic3r::GUI::set_main_frame(this); m_appController = new Slic3r::AppController(); -// #if _WIN32 -// // Load the icon either from the exe, or from the ico file. -// // auto iconfile = Slic3r::decode_path($FindBin::Bin) . '\slic3r.exe'; -// auto iconfile = Slic3r::var("Slic3r.ico");// unless - f iconfile; -// SetIcon(wxIcon(iconfile, wxBITMAP_TYPE_ICO)); -// #else + // Load the icon either from the exe, or from the ico file. +#if _WIN32 + { + TCHAR szExeFileName[MAX_PATH]; + GetModuleFileName(nullptr, szExeFileName, MAX_PATH); + SetIcon(wxIcon(szExeFileName, wxBITMAP_TYPE_ICO)); + } +#else SetIcon(wxIcon(Slic3r::var("Slic3r_128px.png"), wxBITMAP_TYPE_PNG)); -// #ifdef // _WIN32 +#endif // _WIN32 // initialize tabpanel and menubar init_tabpanel(); From c3dc562ab09aaa2db6aeda7690f75db2f930aae1 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Tue, 25 Sep 2018 09:55:15 +0200 Subject: [PATCH 034/186] Resurrected --dont-arrange command line parameter, fixed command line print parameter validation. --- src/libslic3r/Config.hpp | 16 ++++++++++++++++ src/libslic3r/PrintConfig.cpp | 13 ++++++++++--- src/libslic3r/PrintConfig.hpp | 5 ++++- src/slic3r.cpp | 36 ++++++++++++++++++----------------- 4 files changed, 49 insertions(+), 21 deletions(-) diff --git a/src/libslic3r/Config.hpp b/src/libslic3r/Config.hpp index e8ed433561..281591596f 100644 --- a/src/libslic3r/Config.hpp +++ b/src/libslic3r/Config.hpp @@ -812,6 +812,14 @@ public: bool operator==(const ConfigOptionEnum &rhs) const { return this->value == rhs.value; } int getInt() const override { return (int)this->value; } + bool operator==(const ConfigOption &rhs) const override + { + if (rhs.type() != this->type()) + throw std::runtime_error("ConfigOptionEnum: Comparing incompatible types"); + // rhs could be of the following type: ConfigOptionEnumGeneric or ConfigOptionEnum + return this->value == (T)rhs.getInt(); + } + void set(const ConfigOption *rhs) override { if (rhs->type() != this->type()) throw std::runtime_error("ConfigOptionEnum: Assigning an incompatible type"); @@ -887,6 +895,14 @@ public: ConfigOptionEnumGeneric& operator=(const ConfigOption *opt) { this->set(opt); return *this; } bool operator==(const ConfigOptionEnumGeneric &rhs) const { return this->value == rhs.value; } + bool operator==(const ConfigOption &rhs) const override + { + if (rhs.type() != this->type()) + throw std::runtime_error("ConfigOptionEnumGeneric: Comparing incompatible types"); + // rhs could be of the following type: ConfigOptionEnumGeneric or ConfigOptionEnum + return this->value == rhs.getInt(); + } + void set(const ConfigOption *rhs) override { if (rhs->type() != this->type()) throw std::runtime_error("ConfigOptionEnumGeneric: Assigning an incompatible type"); diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 4ed37a1531..05b1b4bb58 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -2612,6 +2612,13 @@ CLIConfigDef::CLIConfigDef() def->cli = "cut"; def->default_value = new ConfigOptionFloat(0); + def = this->add("dont_arrange", coBool); + def->label = L("Dont arrange"); + def->tooltip = L("Don't arrange the objects on the build plate. The model coordinates " + "define the absolute positions on the build plate. " + "The option --center will be ignored."); + def->default_value = new ConfigOptionBool(false); + def = this->add("datadir", coString); def->label = L("User data directory"); def->tooltip = L("Load and store settings at the given directory. " @@ -2707,10 +2714,10 @@ CLIConfigDef::CLIConfigDef() def->default_value = new ConfigOptionPoint3(Pointf3(0,0,0)); */ - def = this->add("center", coPoint); - def->label = L("Center"); + def = this->add("print_center", coPoint); + def->label = L("Print center"); def->tooltip = L("Center the print around the given center (default: 100, 100)."); - def->cli = "center"; + def->cli = "print-center"; def->default_value = new ConfigOptionPoint(Vec2d(100,100)); } diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index dec528d58b..c03ed25724 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -983,6 +983,7 @@ class CLIConfig : public virtual ConfigBase, public StaticConfig public: ConfigOptionFloat cut; ConfigOptionString datadir; + ConfigOptionBool dont_arrange; ConfigOptionBool export_3mf; ConfigOptionBool gui; ConfigOptionBool info; @@ -990,13 +991,13 @@ public: ConfigOptionStrings load; ConfigOptionBool no_gui; ConfigOptionString output; + ConfigOptionPoint print_center; ConfigOptionFloat rotate; ConfigOptionFloat rotate_x; ConfigOptionFloat rotate_y; ConfigOptionString save; ConfigOptionFloat scale; // ConfigOptionPoint3 scale_to_fit; - ConfigOptionPoint center; ConfigOptionBool slice; CLIConfig() : ConfigBase(), StaticConfig() @@ -1011,6 +1012,7 @@ public: { OPT_PTR(cut); OPT_PTR(datadir); + OPT_PTR(dont_arrange); OPT_PTR(export_3mf); OPT_PTR(gui); OPT_PTR(help); @@ -1018,6 +1020,7 @@ public: OPT_PTR(load); OPT_PTR(no_gui); OPT_PTR(output); + OPT_PTR(print_center); OPT_PTR(rotate); OPT_PTR(rotate_x); OPT_PTR(rotate_y); diff --git a/src/slic3r.cpp b/src/slic3r.cpp index 29e1e28e9e..a31c23f911 100644 --- a/src/slic3r.cpp +++ b/src/slic3r.cpp @@ -139,6 +139,11 @@ int main(int argc, char **argv) if (! cli_config.save.value.empty()) print_config.save(cli_config.save.value); + if (cli_config.help) { + printUsage(); + return 0; + } + // read input file(s) if any std::vector models; for (const t_config_option_key &file : input_files) { @@ -146,7 +151,6 @@ int main(int argc, char **argv) boost::nowide::cerr << "No such file: " << file << std::endl; exit(1); } - Model model; try { model = Model::read_from_file(file); @@ -154,14 +158,11 @@ int main(int argc, char **argv) boost::nowide::cerr << file << ": " << e.what() << std::endl; exit(1); } - if (model.objects.empty()) { boost::nowide::cerr << "Error: file is empty: " << file << std::endl; continue; } - - model.add_default_instances(); - + model.add_default_instances(); // apply command line transform options for (ModelObject* o : model.objects) { /* @@ -174,15 +175,10 @@ int main(int argc, char **argv) o->rotate(Geometry::deg2rad(cli_config.rotate_y.value), Y); o->rotate(Geometry::deg2rad(cli_config.rotate.value), Z); } - // TODO: handle --merge models.push_back(model); } - if (cli_config.help) { - printUsage(); - return 0; - } - + for (Model &model : models) { if (cli_config.info) { // --info works on unrepaired model @@ -220,16 +216,22 @@ int main(int argc, char **argv) } else if (cli_config.slice) { std::string outfile = cli_config.output.value; Print print; - model.arrange_objects(print.config().min_object_distance()); - model.center_instances_around_point(cli_config.center); - if (outfile.empty()) outfile = model.objects.front()->input_file + ".gcode"; - print.apply_config(print_config); + if (! cli_config.dont_arrange) { + model.arrange_objects(print.config().min_object_distance()); + model.center_instances_around_point(cli_config.print_center); + } + if (outfile.empty()) + outfile = model.objects.front()->input_file + ".gcode"; for (auto* mo : model.objects) { print.auto_assign_extruders(mo); print.add_model_object(mo); } - print.validate(); - print.export_gcode(outfile, nullptr); + print.apply_config(print_config); + std::string err = print.validate(); + if (err.empty()) + print.export_gcode(outfile, nullptr); + else + std::cerr << err << "\n"; } else { boost::nowide::cerr << "error: command not supported" << std::endl; return 1; From 1398d5d09a02adb1826b382c10a2812631baa279 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Tue, 25 Sep 2018 11:47:14 +0200 Subject: [PATCH 035/186] Removed utilities depending on Perl (post processing scripts), removed non-maintained utilities. --- Build.PL | 20 - serial.txt | 642 ------------------- utils/amf-to-stl.pl | 54 -- utils/dump-stl.pl | 49 -- utils/modifier_helpers/layer_generator.jscad | 19 - utils/modifier_helpers/solid_layers.scad | 24 - utils/pdf-slices.pl | 106 --- utils/post-processing/decimate.pl | 53 -- utils/post-processing/fan_kickstart.py | 13 - utils/post-processing/filament-weight.pl | 31 - utils/post-processing/flowrate.pl | 53 -- utils/post-processing/prowl-notification.pl | 21 - utils/post-processing/z-every-line.pl | 24 - utils/send-gcode.pl | 37 -- utils/split_stl.pl | 65 -- utils/stl-to-amf.pl | 74 --- utils/zsh/README.markdown | 21 - utils/zsh/functions/_slic3r | 118 ---- 18 files changed, 1424 deletions(-) delete mode 100644 serial.txt delete mode 100755 utils/amf-to-stl.pl delete mode 100644 utils/dump-stl.pl delete mode 100644 utils/modifier_helpers/layer_generator.jscad delete mode 100644 utils/modifier_helpers/solid_layers.scad delete mode 100755 utils/pdf-slices.pl delete mode 100755 utils/post-processing/decimate.pl delete mode 100644 utils/post-processing/fan_kickstart.py delete mode 100755 utils/post-processing/filament-weight.pl delete mode 100755 utils/post-processing/flowrate.pl delete mode 100755 utils/post-processing/prowl-notification.pl delete mode 100755 utils/post-processing/z-every-line.pl delete mode 100644 utils/send-gcode.pl delete mode 100755 utils/split_stl.pl delete mode 100755 utils/stl-to-amf.pl delete mode 100644 utils/zsh/README.markdown delete mode 100644 utils/zsh/functions/_slic3r diff --git a/Build.PL b/Build.PL index 4c7fa412af..98920731c6 100644 --- a/Build.PL +++ b/Build.PL @@ -30,20 +30,7 @@ my %recommends = qw( ); my $sudo = grep { $_ eq '--sudo' } @ARGV; -my $gui = grep { $_ eq '--gui' } @ARGV; my $nolocal = grep { $_ eq '--nolocal' } @ARGV; -if ($gui) { - %prereqs = qw( - Class::Accessor 0 - Wx 0.9918 - ); - %recommends = qw( - Wx::GLCanvas 0 - ); - if ($^O eq 'MSWin32') { - $recommends{"Win32::TieRegistry"} = 0; - } -} my @missing_prereqs = (); if ($ENV{SLIC3R_NO_AUTO}) { @@ -129,13 +116,6 @@ EOF } } -print "\n"; -if ($gui) { - print "Perl dependencies for the Slic3r GUI were installed.\n"; -} else { - print "Perl dependencies for Slic3r were installed.\n"; - print "If you also want to use the GUI you can now run `perl Build.PL --gui` to install the required modules.\n"; -} print "\n"; print "In the next step, you need to build the Slic3r C++ library.\n"; print "1) Create a build directory and change to it\n"; diff --git a/serial.txt b/serial.txt deleted file mode 100644 index 7c6816d430..0000000000 --- a/serial.txt +++ /dev/null @@ -1,642 +0,0 @@ -<< start -<< echo: 3.1.1-RC5-150z -<< echo: Last Updated: Feb 7 2018 15:28:23 | Author: (none, default config) -<< Compiled: Feb 7 2018 -<< echo: Free Memory: 1777 PlannerBufferBytes: 1312 -<< echo:Hardcoded Default Settings Loaded -<< adc_init ->> N0 M105*39 -<< CrashDetect ENABLED! -<< tmc2130_init(), mode=NORMAL -<< PAT9125_init:1 -<< FSensor -<< ENABLED -<< echo:SD card ok -<< echo:busy: processing -<< Error:Line Number is not Last Line Number+1, Last Line: 0 -<< Resend: 1 -<< ok ->> N1 M107*36 -<< ok ->> N2 M115 U3.1.1-RC5*107 -<< ok ->> N3 M201 X1000 Y1000 Z200 E5000*10 -<< ok ->> N4 M203 X200 Y200 Z12 E120*8 -<< ok ->> N5 M204 S1250 T1250*39 -<< ok ->> N6 M205 X10 Y10 Z0.4 E2.5*63 -<< ok ->> N7 M205 S0 T0*36 -<< ok ->> N8 M83*16 -<< ok ->> N9 M104 S215*106 -<< ok ->> N10 M140 S60*98 -<< ok ->> N11 M190 S60*110 -<< T:158.08 E:0 B:57.1 -<< T:157.04 E:0 B:57.1 -<< T:156.77 E:0 B:56.9 -<< T:156.97 E:0 B:57.0 -<< T:158.14 E:0 B:57.0 -<< T:159.62 E:0 B:56.9 -<< T:161.25 E:0 B:56.8 -<< T:163.64 E:0 B:56.8 -<< T:165.94 E:0 B:56.7 -<< T:168.40 E:0 B:56.8 -<< T:170.79 E:0 B:56.7 -<< T:173.68 E:0 B:56.7 -<< T:175.53 E:0 B:56.6 -<< T:178.40 E:0 B:56.6 -<< T:180.94 E:0 B:56.5 -<< T:183.92 E:0 B:56.4 -<< T:186.73 E:0 B:56.4 -<< T:189.20 E:0 B:56.4 -<< T:191.32 E:0 B:56.3 -<< T:193.91 E:0 B:56.3 -<< T:196.38 E:0 B:56.2 -<< T:198.75 E:0 B:56.2 -<< T:201.65 E:0 B:56.3 -<< T:203.57 E:0 B:56.4 -<< T:206.38 E:0 B:56.5 -<< T:208.71 E:0 B:56.6 -<< T:211.04 E:0 B:56.6 -<< T:212.86 E:0 B:56.8 -<< T:214.84 E:0 B:57.0 -<< T:215.52 E:0 B:57.2 -<< T:215.78 E:0 B:57.4 -<< T:216.30 E:0 B:57.6 -<< T:216.51 E:0 B:57.7 -<< T:215.73 E:0 B:58.0 -<< T:215.47 E:0 B:58.2 -<< T:214.95 E:0 B:58.5 -<< T:214.22 E:0 B:58.7 -<< T:213.65 E:0 B:59.0 -<< T:212.24 E:0 B:59.2 -<< T:212.14 E:0 B:59.4 -<< T:212.03 E:0 B:59.7 -<< T:211.51 E:0 B:59.8 -<< ok ->> N12 M105*20 -<< ok T:211.0 /215.0 B:60.0 /60.0 T0:211.0 /215.0 @:60 B@:0 P:46.3 A:36.2 ->> N13 M105*21 -<< ok T:211.0 /215.0 B:60.0 /60.0 T0:211.0 /215.0 @:60 B@:0 P:46.3 A:36.2 ->> N14 M105*18 -<< ok T:211.0 /215.0 B:60.0 /60.0 T0:211.0 /215.0 @:60 B@:0 P:46.3 A:36.2 ->> N15 M105*19 -<< ok T:211.0 /215.0 B:60.0 /60.0 T0:211.0 /215.0 @:60 B@:0 P:46.3 A:36.2 ->> N16 M105*16 -<< ok T:211.0 /215.0 B:60.0 /60.0 T0:211.0 /215.0 @:60 B@:0 P:46.3 A:36.2 ->> N17 M105*17 -<< ok T:211.0 /215.0 B:60.0 /60.0 T0:211.0 /215.0 @:60 B@:0 P:46.3 A:36.2 ->> N18 M105*30 -<< ok T:211.0 /215.0 B:60.0 /60.0 T0:211.0 /215.0 @:60 B@:0 P:46.3 A:36.2 ->> N19 M105*31 -<< ok T:211.0 /215.0 B:60.0 /60.0 T0:211.0 /215.0 @:60 B@:0 P:46.3 A:36.2 ->> N20 M105*21 -<< ok T:211.0 /215.0 B:60.0 /60.0 T0:211.0 /215.0 @:60 B@:0 P:46.3 A:36.2 ->> N21 M109 S215*93 -<< T:211.3 E:0 W:? -<< T:211.8 E:0 W:? -<< T:211.8 E:0 W:? -<< T:212.1 E:0 W:? -<< T:212.4 E:0 W:? -<< T:213.3 E:0 W:? -<< T:213.3 E:0 W:? -<< T:213.8 E:0 W:? -<< T:214.1 E:0 W:2 -<< T:214.1 E:0 W:1 -<< T:214.2 E:0 W:0 -<< ok ->> N22 M105*23 -<< ok T:214.3 /215.0 B:60.8 /60.0 T0:214.3 /215.0 @:20 B@:7 P:46.4 A:36.0 ->> N23 M105*22 -<< ok T:214.3 /215.0 B:60.8 /60.0 T0:214.3 /215.0 @:20 B@:7 P:46.4 A:36.0 ->> N24 G28 W*82 -<< 0 step=62 mscnt= 993 -<< tmc2130_goto_step 0 0 2 1000 -<< step 61 mscnt = 984 -<< dir=0 steps=-61 -<< dir=1 steps=61 -<< dir=0 steps=3 -<< cnt 2 step 61 mscnt = 986 -<< cnt 1 step 62 mscnt = 1005 -<< cnt 0 step 63 mscnt = 1021 -<< echo:busy: processing -<< echo:busy: processing -<< 0 step=34 mscnt= 547 -<< tmc2130_goto_step 1 0 2 1000 -<< step 34 mscnt = 552 -<< dir=1 steps=-34 -<< dir=0 steps=34 -<< dir=1 steps=30 -<< cnt 29 step 34 mscnt = 554 -<< cnt 28 step 35 mscnt = 572 -<< cnt 27 step 36 mscnt = 588 -<< cnt 26 step 37 mscnt = 604 -<< cnt 25 step 38 mscnt = 620 -<< cnt 24 step 39 mscnt = 637 -<< cnt 23 step 40 mscnt = 653 -<< cnt 22 step 41 mscnt = 668 -<< cnt 21 step 42 mscnt = 684 -<< cnt 20 step 43 mscnt = 701 -<< cnt 19 step 44 mscnt = 717 -<< cnt 18 step 45 mscnt = 733 -<< cnt 17 step 46 mscnt = 748 -<< cnt 16 step 47 mscnt = 765 -<< cnt 15 step 48 mscnt = 780 -<< cnt 14 step 49 mscnt = 796 -<< cnt 13 step 50 mscnt = 812 -<< cnt 12 step 51 mscnt = 828 -<< cnt 11 step 52 mscnt = 844 -<< cnt 10 step 53 mscnt = 860 -<< cnt 9 step 54 mscnt = 876 -<< cnt 8 step 55 mscnt = 893 -<< cnt 7 step 56 mscnt = 909 -<< cnt 6 step 57 mscnt = 925 -<< cnt 5 step 58 mscnt = 941 -<< cnt 4 step 59 mscnt = 956 -<< cnt 3 step 60 mscnt = 972 -<< cnt 2 step 61 mscnt = 988 -<< cnt 1 step 62 mscnt = 1005 -<< cnt 0 step 63 mscnt = 1021 -<< echo:busy: processing -<< ok ->> N25 M105*16 -<< ok T:213.1 /215.0 B:60.8 /60.0 T0:213.1 /215.0 @:44 B@:35 P:46.5 A:35.6 ->> N26 G80*37 -<< echo:busy: processing -<< echo:busy: processing -<< echo:busy: processing -<< echo:busy: processing -<< echo:busy: processing -<< echo:busy: processing -<< echo:busy: processing -<< echo:busy: processing -<< echo:busy: processing -<< echo:busy: processing -<< echo:busy: processing -<< echo:busy: processing -<< echo:busy: processing -<< ok ->> N27 M105*18 -<< ok T:214.8 /215.0 B:60.9 /60.0 T0:214.8 /215.0 @:31 B@:25 P:46.3 A:35.7 ->> N28 M105*29 -<< ok T:214.8 /215.0 B:60.9 /60.0 T0:214.8 /215.0 @:31 B@:25 P:46.3 A:35.7 ->> N29 M105*28 -<< ok T:214.8 /215.0 B:60.9 /60.0 T0:214.8 /215.0 @:31 B@:25 P:46.3 A:35.7 ->> N30 M105*20 -<< ok T:214.8 /215.0 B:60.9 /60.0 T0:214.8 /215.0 @:31 B@:25 P:46.3 A:35.7 ->> N31 M105*21 -<< ok T:214.8 /215.0 B:60.9 /60.0 T0:214.8 /215.0 @:31 B@:25 P:46.3 A:35.7 ->> N32 M105*22 -<< ok T:214.8 /215.0 B:60.9 /60.0 T0:214.8 /215.0 @:31 B@:25 P:46.3 A:35.7 ->> N33 G1 Y-3.0 F1000.0*24 -<< ok ->> N34 G92 E0.0*110 -<< ok ->> N35 G1 X60.0 E9.0 F1000.0*101 -<< ok ->> N36 G1 X100.0 E12.5 F1000.0*110 -<< ok ->> N37 G92 E0.0*109 -<< ok ->> N38 M221 S95*102 -<< ok ->> N39 M900 K30*120 -<< Invalid M code. -<< ok ->> N40 G21*46 -<< ok ->> N41 G90*37 -<< ok ->> N42 M83*46 -<< ok ->> N43 G1 E-0.80000 F2100.00000*10 -<< ok ->> N44 G1 Z0.600 F10200.000*1 -<< ok ->> N45 G1 X112.437 Y93.991 F10200.000*106 -<< ok ->> N46 G1 Z0.200 F10200.000*7 -<< ok ->> N47 G1 E0.80000 F2100.00000*35 -<< ok ->> N48 M204 S1000*107 -<< ok ->> N49 G1 F1800*122 -<< ok ->> N50 G1 X112.930 Y93.183 E0.02968*106 -<< ok ->> N51 G1 X113.335 Y92.806 E0.01733*99 -<< ok ->> N52 G1 X113.810 Y92.516 E0.01745*97 -<< ok ->> N53 G1 X114.334 Y92.328 E0.01745*97 -<< ok ->> N54 G1 X114.885 Y92.248 E0.01745*96 -<< ok ->> N55 M105*23 -<< ok T:214.9 /215.0 B:60.8 /60.0 T0:214.9 /215.0 @:30 B@:28 P:46.2 A:35.7 ->> N56 G1 X135.004 Y92.246 E0.63084*96 -<< ok ->> N57 G1 X136.005 Y92.436 E0.03195*101 -<< ok ->> N58 G1 X136.866 Y92.974 E0.03183*107 -<< ok ->> N59 G1 X137.473 Y93.788 E0.03183*111 -<< ok ->> N60 G1 X137.745 Y94.770 E0.03195*100 -<< ok ->> N61 G1 X137.753 Y115.086 E0.63700*88 -<< ok ->> N62 G1 X137.563 Y116.009 E0.02955*87 -<< ok ->> N63 G1 X137.070 Y116.817 E0.02968*88 -<< ok ->> N64 G1 X136.646 Y117.208 E0.01809*93 -<< ok ->> N65 G1 X136.149 Y117.503 E0.01809*88 -<< ok ->> N66 G1 X135.603 Y117.687 E0.01809*94 -<< ok ->> N67 G1 X135.029 Y117.754 E0.01809*94 -<< ok ->> N68 G1 X114.914 Y117.753 E0.63071*81 -<< ok ->> N69 G1 X113.991 Y117.563 E0.02955*83 -<< ok ->> N70 G1 X113.183 Y117.070 E0.02968*89 -<< ok ->> N71 G1 X112.792 Y116.646 E0.01809*88 -<< ok ->> N72 M105*18 -<< ok T:214.0 /215.0 B:60.8 /60.0 T0:214.0 /215.0 @:45 B@:16 P:46.2 A:35.5 ->> N73 G1 X112.497 Y116.149 E0.01809*84 -<< ok ->> N74 G1 X112.313 Y115.603 E0.01809*82 -<< ok ->> N75 G1 X112.246 Y115.029 E0.01809*92 -<< ok ->> N76 G1 X112.247 Y94.914 E0.63071*98 -<< ok ->> N77 G1 X112.425 Y94.050 E0.02767*111 -<< ok ->> N78 G1 F8160*126 -<< ok ->> N79 G1 X112.930 Y93.183 E-0.24526*78 -<< ok ->> N80 G1 F8160*121 -<< ok ->> N81 G1 X113.335 Y92.806 E-0.13510*67 -<< ok ->> N82 G1 F8160*123 -<< ok ->> N83 G1 X113.810 Y92.516 E-0.13609*74 -<< ok ->> N84 G1 F8160*125 -<< ok ->> N85 G1 X114.334 Y92.328 E-0.13609*77 -<< ok ->> N86 G1 F8160*127 -<< ok ->> N87 G1 X114.769 Y92.265 E-0.10746*66 -<< ok ->> N88 G1 E-0.04000 F2100.00000*1 -<< ok ->> N89 G1 Z0.800 F10200.000*14 -<< ok ->> N90 G1 X113.989 Y92.849 F10200.000*110 -<< ok ->> N91 G1 Z0.200 F10200.000*13 -<< ok ->> N92 G1 E0.80000 F2100.00000*43 -<< ok ->> N93 G1 F1800*125 -<< ok ->> N94 G1 X114.911 Y92.625 E0.02977*99 -<< ok ->> N95 G1 X135.004 Y92.623 E0.62999*108 -<< ok ->> N96 G1 X135.871 Y92.788 E0.02767*108 -<< ok ->> N97 G1 X136.617 Y93.258 E0.02767*105 -<< ok ->> N98 G1 X137.141 Y93.968 E0.02767*107 -<< ok ->> N99 G1 X137.371 Y94.824 E0.02778*107 -<< ok ->> N100 G1 X137.376 Y115.065 E0.63464*97 -<< ok ->> N101 G1 X137.209 Y115.878 E0.02602*104 -<< ok ->> N102 G1 X136.773 Y116.584 E0.02602*111 -<< ok ->> N103 G1 X136.407 Y116.916 E0.01550*110 -<< ok ->> N104 G1 X135.980 Y117.166 E0.01550*102 -<< ok ->> N105 G1 X135.511 Y117.321 E0.01550*98 -<< ok ->> N106 G1 X135.020 Y117.377 E0.01550*101 -<< ok ->> N107 G1 X114.935 Y117.376 E0.62975*101 -<< ok ->> N108 G1 X114.122 Y117.209 E0.02602*100 -<< ok ->> N109 G1 X113.416 Y116.773 E0.02602*105 -<< ok ->> N110 G1 X113.084 Y116.407 E0.01550*105 -<< ok ->> N111 G1 X112.834 Y115.980 E0.01550*107 -<< ok ->> N112 G1 X112.679 Y115.511 E0.01550*107 -<< ok ->> N113 G1 X112.623 Y115.020 E0.01550*98 -<< ok ->> N114 G1 X112.624 Y94.935 E0.62975*89 -<< ok ->> N115 G1 X112.791 Y94.122 E0.02602*80 -<< ok ->> N116 G1 X113.227 Y93.416 E0.02602*95 -<< ok ->> N117 G1 X113.940 Y92.885 E0.02789*81 -<< ok ->> N118 G1 F8160*73 -<< ok ->> N119 G1 X114.911 Y92.625 E-0.24574*113 -<< ok ->> N120 G1 F8160*66 -<< ok ->> N121 G1 X117.015 Y92.624 E-0.51426*113 -<< ok ->> N122 G1 E-0.04000 F2100.00000*48 -<< ok ->> N123 G1 Z0.800 F10200.000*63 -<< ok ->> N124 G1 X115.587 Y95.587 F10200.000*92 -<< ok ->> N125 M105*33 -<< ok T:214.2 /215.0 B:60.7 /60.0 T0:214.2 /215.0 @:41 B@:24 P:46.2 A:36.0 ->> N126 G1 Z0.200 F10200.000*48 -<< ok ->> N127 G1 E0.80000 F2100.00000*20 -<< ok ->> N128 G1 F1800*76 -<< ok ->> N129 G1 X134.413 Y95.587 E0.59027*87 -<< ok ->> N130 G1 X134.413 Y114.413 E0.59027*107 -<< ok ->> N131 G1 X115.587 Y114.413 E0.59027*101 -<< ok ->> N132 G1 X115.587 Y95.647 E0.58839*91 -<< ok ->> N133 G1 X115.210 Y95.210 F10200.000*90 -<< ok ->> N134 G1 F1800*65 -<< ok ->> N135 G1 X134.790 Y95.210 E0.61392*93 -<< ok ->> N136 G1 X134.790 Y114.790 E0.61392*107 -<< ok ->> N137 G1 X115.210 Y114.790 E0.61392*100 -<< ok ->> N138 G1 X115.210 Y95.270 E0.61204*86 -<< ok ->> N139 G1 X115.596 Y95.314 F10200.000*92 -<< ok ->> N140 G1 F8160*68 -<< ok ->> N141 G1 X118.319 Y95.260 E-0.76000*113 -<< ok ->> N142 G1 E-0.04000 F2100.00000*54 -<< ok ->> N143 G1 Z0.800 F10200.000*57 -<< ok ->> N144 G1 X115.700 Y113.527 F10200.000*98 -<< ok ->> N145 G1 Z0.200 F10200.000*53 -<< ok ->> N146 G1 E0.80000 F2100.00000*19 -<< ok ->> N147 G1 F1800*69 -<< ok ->> N148 G1 X116.303 Y114.130 E0.02708*98 -<< ok ->> N149 G1 X116.843 Y114.130 E0.01716*96 -<< ok ->> N150 G1 X115.870 Y113.157 E0.04372*110 -<< ok ->> N151 G1 X115.870 Y112.617 E0.01716*110 -<< ok ->> N152 G1 X117.383 Y114.130 E0.06799*108 -<< ok ->> N153 G1 X117.924 Y114.130 E0.01716*106 -<< ok ->> N154 M105*39 -<< ok T:215.1 /215.0 B:60.7 /60.0 T0:215.1 /215.0 @:29 B@:12 P:46.2 A:35.7 ->> N155 G1 X115.870 Y112.076 E0.09225*102 -<< ok ->> N156 G1 X115.870 Y111.536 E0.01716*106 -<< ok ->> N157 G1 X118.464 Y114.130 E0.11652*104 -<< ok ->> N158 G1 X119.004 Y114.130 E0.01716*100 -<< ok ->> N159 G1 X115.870 Y110.996 E0.14079*104 -<< ok ->> N160 G1 X115.870 Y110.456 E0.01716*105 -<< ok ->> N161 G1 X119.544 Y114.130 E0.16505*105 -<< ok ->> N162 G1 X120.085 Y114.130 E0.01716*110 -<< ok ->> N163 G1 X115.870 Y109.915 E0.18932*104 -<< ok ->> N164 G1 X115.870 Y109.375 E0.01716*99 -<< ok ->> N165 G1 X120.625 Y114.130 E0.21358*105 -<< ok ->> N166 G1 X121.165 Y114.130 E0.01716*100 -<< ok ->> N167 G1 X115.870 Y108.835 E0.23785*100 -<< ok ->> N168 G1 X115.870 Y108.295 E0.01716*97 -<< ok ->> N169 G1 X121.705 Y114.130 E0.26212*111 -<< ok ->> N170 G1 X122.245 Y114.130 E0.01716*97 -<< ok ->> N171 G1 X115.870 Y107.755 E0.28638*105 -<< ok ->> N172 G1 X115.870 Y107.214 E0.01716*108 -<< ok ->> N173 G1 X122.786 Y114.130 E0.31065*104 -<< ok ->> N174 G1 X123.326 Y114.130 E0.01716*96 -<< ok ->> N175 G1 X115.870 Y106.674 E0.33491*101 -<< ok ->> N176 G1 X115.870 Y106.134 E0.01716*104 -<< ok ->> N177 G1 X123.866 Y114.130 E0.35918*107 -<< ok ->> N178 G1 X124.406 Y114.130 E0.01716*110 -<< ok ->> N179 G1 X115.870 Y105.594 E0.38344*99 -<< ok ->> N180 G1 X115.870 Y105.054 E0.01716*101 -<< ok ->> N181 G1 X124.946 Y114.130 E0.40771*101 -<< ok ->> N182 G1 X125.487 Y114.130 E0.01716*99 -<< ok ->> N183 G1 X115.870 Y104.513 E0.43198*103 -<< ok ->> N184 G1 X115.870 Y103.973 E0.01716*107 -<< ok ->> N185 G1 X126.027 Y114.130 E0.45624*105 -<< ok ->> N186 G1 X126.567 Y114.130 E0.01716*107 -<< ok ->> N187 G1 X115.870 Y103.433 E0.48051*104 -<< ok ->> N188 G1 X115.870 Y102.893 E0.01716*105 -<< ok ->> N189 G1 X127.107 Y114.130 E0.50477*103 -<< ok ->> N190 M105*47 -<< ok T:215.3 /215.0 B:60.7 /60.0 T0:215.3 /215.0 @:28 B@:18 P:46.3 A:35.5 ->> N191 G1 X127.648 Y114.130 E0.01716*98 -<< ok ->> N192 G1 X115.870 Y102.352 E0.52904*111 -<< ok ->> N193 G1 X115.870 Y101.812 E0.01716*105 -<< ok ->> N194 G1 X128.188 Y114.130 E0.55330*98 -<< ok ->> N195 G1 X128.728 Y114.130 E0.01716*110 -<< ok ->> N196 G1 X115.870 Y101.272 E0.57757*102 -<< ok ->> N197 G1 X115.870 Y100.732 E0.01716*97 -<< ok ->> N198 G1 X129.268 Y114.130 E0.60184*105 -<< ok ->> N199 G1 X129.808 Y114.130 E0.01716*110 -<< ok ->> N200 G1 X115.870 Y100.192 E0.62610*98 -<< ok ->> N201 G1 X115.870 Y99.651 E0.01716*88 -<< ok ->> N202 G1 X130.349 Y114.130 E0.65037*111 -<< ok ->> N203 G1 X130.889 Y114.130 E0.01716*111 -<< ok ->> N204 G1 X115.870 Y99.111 E0.67463*95 -<< ok ->> N205 G1 X115.870 Y98.571 E0.01716*92 -<< ok ->> N206 G1 X131.429 Y114.130 E0.69890*98 -<< ok ->> N207 G1 X131.969 Y114.130 E0.01716*101 -<< ok ->> N208 M105*45 -<< ok T:214.7 /215.0 B:60.6 /60.0 T0:214.7 /215.0 @:38 B@:12 P:46.2 A:35.9 ->> N209 G1 X115.870 Y98.031 E0.72316*81 -<< ok ->> N210 G1 X115.870 Y97.491 E0.01716*88 -<< ok ->> N211 G1 X132.509 Y114.130 E0.74743*105 -<< ok ->> N212 G1 X133.050 Y114.130 E0.01716*96 -<< ok ->> N213 M105*39 -<< ok T:215.1 /215.0 B:60.4 /60.0 T0:215.1 /215.0 @:32 B@:39 P:46.3 A:35.8 ->> N214 M105*32 -<< ok T:214.6 /215.0 B:60.5 /60.0 T0:214.6 /215.0 @:39 B@:14 P:46.3 A:36.3 ->> N215 G28*21 -<< echo:busy: processing -<< 0 step=61 mscnt= 989 -<< tmc2130_goto_step 0 0 2 1000 -<< step 61 mscnt = 984 -<< dir=0 steps=-61 -<< dir=1 steps=61 -<< dir=0 steps=3 -<< cnt 2 step 61 mscnt = 986 -<< cnt 1 step 62 mscnt = 1004 -<< cnt 0 step 63 mscnt = 1021 -<< echo:busy: processing -<< echo:busy: processing -<< 0 step=34 mscnt= 547 -<< tmc2130_goto_step 1 0 2 1000 -<< step 34 mscnt = 552 -<< dir=1 steps=-34 -<< dir=0 steps=34 -<< dir=1 steps=30 -<< cnt 29 step 34 mscnt = 554 -<< cnt 28 step 35 mscnt = 573 -<< cnt 27 step 36 mscnt = 589 -<< cnt 26 step 37 mscnt = 604 -<< cnt 25 step 38 mscnt = 621 -<< cnt 24 step 39 mscnt = 636 -<< cnt 23 step 40 mscnt = 652 -<< cnt 22 step 41 mscnt = 668 -<< cnt 21 step 42 mscnt = 684 -<< cnt 20 step 43 mscnt = 701 -<< cnt 19 step 44 mscnt = 717 -<< cnt 18 step 45 mscnt = 733 -<< cnt 17 step 46 mscnt = 749 -<< cnt 16 step 47 mscnt = 765 -<< cnt 15 step 48 mscnt = 781 -<< cnt 14 step 49 mscnt = 796 -<< cnt 13 step 50 mscnt = 812 -<< cnt 12 step 51 mscnt = 829 -<< cnt 11 step 52 mscnt = 844 -<< cnt 10 step 53 mscnt = 860 -<< cnt 9 step 54 mscnt = 876 -<< cnt 8 step 55 mscnt = 893 -<< cnt 7 step 56 mscnt = 909 -<< cnt 6 step 57 mscnt = 925 -<< cnt 5 step 58 mscnt = 941 -<< cnt 4 step 59 mscnt = 957 -<< cnt 3 step 60 mscnt = 973 -<< cnt 2 step 61 mscnt = 989 -<< cnt 1 step 62 mscnt = 1005 -<< cnt 0 step 63 mscnt = 1021 -<< echo:busy: processing -<< echo:busy: processing -<< echo:busy: processing -<< echo:busy: processing -<< echo:busy: processing -<< echo:busy: processing -<< echo:busy: processing -<< echo:busy: processing -<< echo:busy: processing -<< echo:busy: processing -<< echo:busy: processing -<< echo:busy: processing -<< echo:busy: processing -<< echo:busy: processing -<< ok ->> N216 M105*34 -<< ok T:214.8 /215.0 B:60.2 /60.0 T0:214.8 /215.0 @:33 B@:27 P:46.0 A:36.1 ->> N217 M105*35 -<< ok T:214.8 /215.0 B:60.2 /60.0 T0:214.8 /215.0 @:33 B@:27 P:46.0 A:36.1 ->> N218 M105*44 -<< ok T:214.9 /215.0 B:60.1 /60.0 T0:214.9 /215.0 @:31 B@:33 P:45.9 A:36.1 ->> N219 M105*45 -<< ok T:214.9 /215.0 B:60.1 /60.0 T0:214.9 /215.0 @:31 B@:33 P:45.9 A:36.1 ->> N220 M105*39 -<< ok T:214.9 /215.0 B:60.1 /60.0 T0:214.9 /215.0 @:31 B@:33 P:45.9 A:36.1 ->> N221 M105*38 -<< ok T:214.9 /215.0 B:60.1 /60.0 T0:214.9 /215.0 @:31 B@:33 P:45.9 A:36.1 ->> N222 M105*37 -<< ok T:214.9 /215.0 B:60.1 /60.0 T0:214.9 /215.0 @:31 B@:33 P:45.9 A:36.1 ->> N223 M105*36 -<< ok T:214.5 /215.0 B:60.1 /60.0 T0:214.5 /215.0 @:38 B@:31 P:46.0 A:36.3 -DISCONNECTED diff --git a/utils/amf-to-stl.pl b/utils/amf-to-stl.pl deleted file mode 100755 index 802fd9a536..0000000000 --- a/utils/amf-to-stl.pl +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/perl -# This script converts an AMF file to STL - -use strict; -use warnings; - -BEGIN { - use FindBin; - use lib "$FindBin::Bin/../lib"; - use local::lib "$FindBin::Bin/../local-lib"; -} - -use File::Basename qw(basename); -use Getopt::Long qw(:config no_auto_abbrev); -use Slic3r; -$|++; - -# Convert all parameters from the local code page to utf8 on Windows. -@ARGV = map Slic3r::decode_path($_), @ARGV if $^O eq 'MSWin32'; - -my %opt = (); -{ - my %options = ( - 'help' => sub { usage() }, - 'ascii' => \$opt{ascii}, - ); - GetOptions(%options) or usage(1); - $ARGV[0] or usage(1); -} - -{ - my $model = Slic3r::Model->load_amf($ARGV[0]); - my $output_file = $ARGV[0]; - $output_file =~ s/\.[aA][mM][fF](?:\.[xX][mM][lL])?$/\.stl/; - - printf "Writing to %s\n", basename($output_file); - $model->store_stl($output_file, binary => !$opt{ascii}); -} - - -sub usage { - my ($exit_code) = @_; - - print <<"EOF"; -Usage: amf-to-stl.pl [ OPTIONS ] file.amf - - --help Output this usage screen and exit - --ascii Generate ASCII STL files (default: binary) - -EOF - exit ($exit_code || 0); -} - -__END__ diff --git a/utils/dump-stl.pl b/utils/dump-stl.pl deleted file mode 100644 index eee3c73dc1..0000000000 --- a/utils/dump-stl.pl +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/perl -# This script dumps a STL file into Perl syntax for writing tests -# or dumps a test model into a STL file - -use strict; -use warnings; - -BEGIN { - use FindBin; - use lib "$FindBin::Bin/../lib"; - use local::lib "$FindBin::Bin/../local-lib"; -} - -use Slic3r; -use Slic3r::Test; -use File::Basename qw(basename); -$|++; - -$ARGV[0] or usage(1); - -if (-e $ARGV[0]) { - my $model = Slic3r::Model->load_stl($ARGV[0], basename($ARGV[0])); - $model->objects->[0]->add_instance(offset => Slic3r::Pointf->new(0,0)); - my $mesh = $model->mesh; - $mesh->repair; - printf "VERTICES = %s\n", join ',', map "[$_->[0],$_->[1],$_->[2]]", @{$mesh->vertices}; - printf "FACETS = %s\n", join ',', map "[$_->[0],$_->[1],$_->[2]]", @{$mesh->facets}; - exit 0; -} elsif ((my $model = Slic3r::Test::model($ARGV[0]))) { - $ARGV[1] or die "Missing writeable destination as second argument\n"; - $model->store_stl($ARGV[1], 1); - printf "Model $ARGV[0] written to $ARGV[1]\n"; - exit 0; -} else { - die "No such model exists\n"; -} - - -sub usage { - my ($exit_code) = @_; - - print <<"EOF"; -Usage: dump-stl.pl file.stl - dump-stl.pl modelname file.stl -EOF - exit ($exit_code || 0); -} - -__END__ diff --git a/utils/modifier_helpers/layer_generator.jscad b/utils/modifier_helpers/layer_generator.jscad deleted file mode 100644 index fc193a53f9..0000000000 --- a/utils/modifier_helpers/layer_generator.jscad +++ /dev/null @@ -1,19 +0,0 @@ -// title: Layer_generator -// written by: Joseph Lenox -// Used for generating cubes oriented about the center -// for making simple modifier meshes. - -var width = 100; -var layer_height = 0.3; -var z = 30; -function main() { - - return cube(size=[width,width,layer_height], center=true).translate([0,0,z]); -} -function getParameterDefinitions() { - return [ - { name: 'width', type: 'float', initial: 100, caption: "Width of the cube:" }, - { name: 'layer_height', type: 'float', initial: 0.3, caption: "Layer height used:" }, - { name: 'z', type: 'float', initial: 0, caption: "Z:" } - ]; -} diff --git a/utils/modifier_helpers/solid_layers.scad b/utils/modifier_helpers/solid_layers.scad deleted file mode 100644 index 3782949495..0000000000 --- a/utils/modifier_helpers/solid_layers.scad +++ /dev/null @@ -1,24 +0,0 @@ -// Used to generate a modifier mesh to do something every few layers. -// Load into OpenSCAD, tweak the variables below, export as STL and load as -// a modifier mesh. Then change settings for the modifier mesh. - -// Written by Joseph Lenox; in public domain. - -layer_height = 0.3; // set to layer height in slic3r for "best" results. -number_of_solid_layers = 2; -N = 4; // N > number_of_solid_layers or else the whole thing will be solid -model_height = 300.0; -model_width = 300.0; // these two should be at least as big as the model -model_depth = 300.0; // but bigger isn't a problem -initial_offset=0; // don't generate below this - -position_on_bed=[0,0,0]; // in case you need to move it around - -// don't touch below unless you know what you are doing. -simple_layers = round(model_height/layer_height); -translate(position_on_bed) - for (i = [initial_offset:N:simple_layers]) { - translate([0,0,i*layer_height]) - translate([0,0,(layer_height*number_of_solid_layers)/2]) - cube([model_width,model_depth,layer_height*number_of_solid_layers], center=true); - } diff --git a/utils/pdf-slices.pl b/utils/pdf-slices.pl deleted file mode 100755 index ca61da08e9..0000000000 --- a/utils/pdf-slices.pl +++ /dev/null @@ -1,106 +0,0 @@ -#!/usr/bin/perl -# This script exports model slices to a PDF file as solid fills, one per page - -use strict; -use warnings; - -BEGIN { - use FindBin; - use lib "$FindBin::Bin/../lib"; - use local::lib "$FindBin::Bin/../local-lib"; -} - -use Getopt::Long qw(:config no_auto_abbrev); -use PDF::API2; -use Slic3r; -use Slic3r::Geometry qw(scale unscale X Y); - -use constant mm => 25.4 / 72; - -my %opt = (); -{ - my %options = ( - 'help' => sub { usage() }, - 'output|o=s' => \$opt{output_file}, - 'layer-height|h=f' => \$opt{layer_height}, - ); - GetOptions(%options) or usage(1); - $ARGV[0] or usage(1); -} - -{ - # prepare config - my $config = Slic3r::Config->new; - $config->set('layer_height', $opt{layer_height}) if $opt{layer_height}; - - # read model - my $model = Slic3r::Model->read_from_file(my $input_file = $ARGV[0]); - - # init print object - my $sprint = Slic3r::Print::Simple->new( - print_center => [0,0], - ); - $sprint->apply_config($config); - $sprint->set_model($model); - my $print = $sprint->_print; - - # compute sizes - my $bb = $print->bounding_box; - my $size = $bb->size; - my $mediabox = [ map unscale($_)/mm, @{$size} ]; - - # init PDF - my $pdf = PDF::API2->new(); - my $color = $pdf->colorspace_separation('RDG_GLOSS', 'darkblue'); - - # slice and build output geometry - $_->slice for @{$print->objects}; - foreach my $object (@{ $print->objects }) { - my $shift = $object->_shifted_copies->[0]; - $shift->translate(map $_/2, @$size); - - foreach my $layer (@{ $object->layers }) { - my $page = $pdf->page(); - $page->mediabox(@$mediabox); - my $content = $page->gfx; - $content->fillcolor($color, 1); - - foreach my $expolygon (@{$layer->slices}) { - $expolygon = $expolygon->clone; - $expolygon->translate(@$shift); - $content->poly(map { unscale($_->x)/mm, unscale($_->y)/mm } @{$expolygon->contour}); #) - $content->close; - foreach my $hole (@{$expolygon->holes}) { - $content->poly(map { unscale($_->x)/mm, unscale($_->y)/mm } @$hole); #) - $content->close; - } - $content->fill; # non-zero by default - } - } - } - - # write output file - my $output_file = $opt{output_file}; - if (!defined $output_file) { - $output_file = $input_file; - $output_file =~ s/\.(?:[sS][tT][lL])$/.pdf/; - } - $pdf->saveas($output_file); - printf "PDF file written to %s\n", $output_file; -} - -sub usage { - my ($exit_code) = @_; - - print <<"EOF"; -Usage: pdf-slices.pl [ OPTIONS ] file.stl - - --help Output this usage screen and exit - --output, -o Write to the specified file - --layer-height, -h Use the specified layer height - -EOF - exit ($exit_code || 0); -} - -__END__ diff --git a/utils/post-processing/decimate.pl b/utils/post-processing/decimate.pl deleted file mode 100755 index 9e2938c5f2..0000000000 --- a/utils/post-processing/decimate.pl +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/perl -i~ - -use strict; -use warnings; - -my %lastpos = (X => 10000, Y => 10000, Z => 10000, E => 10000, F => 10000); -my %pos = (X => 0, Y => 0, Z => 0, E => 0, F => 0); - -my $mindist = 0.33; - -my $mindistz = 0.005; - -my $mindistsq = $mindist * $mindist; - -sub dist { - my $sq = 0; - for (qw/X Y Z E/) { - $sq += ($pos{$_} - $lastpos{$_}) ** 2; - } - return $sq; -} - -while (<>) { - if (m#\bG[01]\b#) { - while (m#([XYZEF])(\d+(\.\d+)?)#gi) { - $pos{uc $1} = $2; - } - if ( - ( - /X/ && - /Y/ && - (dist() >= $mindistsq) - ) || - (abs($pos{Z} - $lastpos{Z}) > $mindistz) || - (!/X/ || !/Y/) - ) { - print; - %lastpos = %pos; - } - elsif (($pos{F} - $lastpos{F}) != 0) { - printf "G1 F%s\n", $pos{F}; - $lastpos{F} = $pos{F}; - } - } - else { - if (m#\bG92\b#) { - while (m#([XYZEF])(\d+(\.\d+)?)#gi) { - $lastpos{uc $1} = $2; - } - } - print; - } -} diff --git a/utils/post-processing/fan_kickstart.py b/utils/post-processing/fan_kickstart.py deleted file mode 100644 index 9ee1bc0a4a..0000000000 --- a/utils/post-processing/fan_kickstart.py +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/python -import sys -import re - -sea = re.compile("M106 S[1-9]+[0-9]*") -rep = re.compile("M106 S255\n\g<0>") -out = open(sys.argv[1]+"_fixed", 'w') - with open(sys.argv[1]) as f: - for r in f: - if re.search(sea, r) is not None: - out.write(re.sub(sea,"M106 S255\n\g<0>",r)) - else: - out.write(r) diff --git a/utils/post-processing/filament-weight.pl b/utils/post-processing/filament-weight.pl deleted file mode 100755 index 5ed8364612..0000000000 --- a/utils/post-processing/filament-weight.pl +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/perl -i -# -# Post-processing script for adding weight and cost of required -# filament to G-code output. - -use strict; -use warnings; - -# example densities, adjust according to filament specifications -use constant PLA_P => 1.25; # g/cm3 -use constant ABS_P => 1.05; # g/cm3 - -# example costs, adjust according to filament prices -use constant PLA_PRICE => 0.05; # EUR/g -use constant ABS_PRICE => 0.02; # EUR/g -use constant CURRENCY => "EUR"; - -while (<>) { - if (/^(;\s+filament\s+used\s+=\s.*\((\d+(?:\.\d+)?)cm3)\)/) { - my $pla_weight = $2 * PLA_P; - my $abs_weight = $2 * ABS_P; - - my $pla_costs = $pla_weight * PLA_PRICE; - my $abs_costs = $abs_weight * ABS_PRICE; - - printf "%s or %.2fg PLA/%.2fg ABS)\n", $1, $pla_weight, $abs_weight; - printf "; costs = %s %.2f (PLA), %s %.2f (ABS)\n", CURRENCY, $pla_costs, CURRENCY, $abs_costs; - } else { - print; - } -} diff --git a/utils/post-processing/flowrate.pl b/utils/post-processing/flowrate.pl deleted file mode 100755 index f29d2312d4..0000000000 --- a/utils/post-processing/flowrate.pl +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/perl -i - -# -# Post-processing script for calculating flow rate for each move - -use strict; -use warnings; - -use constant PI => 3.141592653589793238; -my @filament_diameter = split /,/, $ENV{SLIC3R_FILAMENT_DIAMETER}; - -my $E = 0; -my $T = 0; -my ($X, $Y, $F); -while (<>) { - if (/^G1.*? F([0-9.]+)/) { - $F = $1; - } - if (/^G1 X([0-9.]+) Y([0-9.]+).*? E([0-9.]+)/) { - my ($x, $y, $e) = ($1, $2, $3); - my $e_length = $e - $E; - if ($e_length > 0 && defined $X && defined $Y) { - my $dist = sqrt( (($x-$X)**2) + (($y-$Y)**2) ); - if ($dist > 0) { - my $mm_per_mm = $e_length / $dist; # dE/dXY - my $mm3_per_mm = ($filament_diameter[$T] ** 2) * PI/4 * $mm_per_mm; - my $vol_speed = $F/60 * $mm3_per_mm; - my $comment = sprintf ' ; dXY = %.3fmm ; dE = %.5fmm ; dE/XY = %.5fmm/mm; volspeed = %.5fmm\x{00B3}/sec', - $dist, $e_length, $mm_per_mm, $vol_speed; - s/(\R+)/$comment$1/; - } - } - $E = $e; - $X = $x; - $Y = $y; - } - if (/^G1 X([0-9.]+) Y([0-9.]+)/) { - $X = $1; - $Y = $2; - } - if (/^G1.*? E([0-9.]+)/) { - $E = $1; - } - if (/^G92 E0/) { - $E = 0; - } - if (/^T(\d+)/) { - $T = $1; - } - print; -} - -__END__ diff --git a/utils/post-processing/prowl-notification.pl b/utils/post-processing/prowl-notification.pl deleted file mode 100755 index 5a5e1ca539..0000000000 --- a/utils/post-processing/prowl-notification.pl +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/perl -# -# Example post-processing script for sending a Prowl notification upon -# completion. See http://www.prowlapp.com/ for more info. - -use strict; -use warnings; - -use File::Basename qw(basename); -use WebService::Prowl; - -# set your Prowl API key here -my $apikey = ''; - -my $file = basename $ARGV[0]; -my $prowl = WebService::Prowl->new(apikey => $apikey); -my %options = (application => 'Slic3r', - event =>'Slicing Done!', - description => "$file was successfully generated"); -printf STDERR "Error sending Prowl notification: %s\n", $prowl->error - unless $prowl->add(%options); diff --git a/utils/post-processing/z-every-line.pl b/utils/post-processing/z-every-line.pl deleted file mode 100755 index aaf57e172a..0000000000 --- a/utils/post-processing/z-every-line.pl +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/perl -i - -use strict; -use warnings; - -my $z = 0; - -# read stdin and any/all files passed as parameters one line at a time -while (<>) { - # if we find a Z word, save it - $z = $1 if /Z\s*(\d+(\.\d+)?)/; - - # if we don't have Z, but we do have X and Y - if (!/Z/ && /X/ && /Y/ && $z > 0) { - # chop off the end of the line (incl. comments), saving chopped section in $1 - s/\s*([\r\n\;\(].*)/" Z$z $1"/es; - # print start of line, insert our Z value then re-add the chopped end of line - # print "$_ Z$z $1"; - } - #else { - # nothing interesting, print line as-is - print or die $!; - #} -} diff --git a/utils/send-gcode.pl b/utils/send-gcode.pl deleted file mode 100644 index 0b803baa6d..0000000000 --- a/utils/send-gcode.pl +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env perl - -use strict; -use warnings; - -BEGIN { - use FindBin; - use lib "$FindBin::Bin/../lib"; - use local::lib "$FindBin::Bin/../local-lib"; -} - -use Slic3r; - -die "Usage: send-gcode.pl SERIALPORT BAUDRATE GCODE_FILE\n" - if @ARGV != 3; - -my $serial = Slic3r::GCode::Sender->new($ARGV[0], $ARGV[1]); -1 until $serial->is_connected; -print "Connected to printer\n"; - -{ - local $/ = "\n"; - Slic3r::open(\my $fh, '<', $ARGV[2]) - or die "Unable to open $ARGV[2]: $!\n"; - binmode $fh, ':utf8'; - while (<$fh>) { - $serial->send($_); - } - close $fh; -} - -while ((my $queue_size = $serial->queue_size) > 0) { - printf "Queue size: %d\n", $queue_size; -} -$serial->disconnect; - -__END__ diff --git a/utils/split_stl.pl b/utils/split_stl.pl deleted file mode 100755 index 56217de4bd..0000000000 --- a/utils/split_stl.pl +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/perl -# This script splits a STL plate into individual files - -use strict; -use warnings; - -BEGIN { - use FindBin; - use lib "$FindBin::Bin/../lib"; - use local::lib "$FindBin::Bin/../local-lib"; -} - -use File::Basename qw(basename); -use Getopt::Long qw(:config no_auto_abbrev); -use Slic3r; -$|++; - -my %opt = (); -{ - my %options = ( - 'help' => sub { usage() }, - 'ascii' => \$opt{ascii}, - ); - GetOptions(%options) or usage(1); - $ARGV[0] or usage(1); -} - -{ - my $model = Slic3r::Model->load_stl($ARGV[0], basename($ARGV[0])); - my $basename = $ARGV[0]; - $basename =~ s/\.[sS][tT][lL]$//; - - my $part_count = 0; - my $mesh = $model->objects->[0]->volumes->[0]->mesh; - foreach my $new_mesh (@{$mesh->split}) { - $new_mesh->repair; - - my $new_model = Slic3r::Model->new; - $new_model - ->add_object() - ->add_volume(mesh => $new_mesh); - - $new_model->add_default_instances; - - my $output_file = sprintf '%s_%02d.stl', $basename, ++$part_count; - printf "Writing to %s\n", basename($output_file); - $new_model->store_stl($output_file, !$opt{ascii}); - } -} - - -sub usage { - my ($exit_code) = @_; - - print <<"EOF"; -Usage: split_stl.pl [ OPTIONS ] file.stl - - --help Output this usage screen and exit - --ascii Generate ASCII STL files (default: binary) - -EOF - exit ($exit_code || 0); -} - -__END__ diff --git a/utils/stl-to-amf.pl b/utils/stl-to-amf.pl deleted file mode 100755 index bb88b21617..0000000000 --- a/utils/stl-to-amf.pl +++ /dev/null @@ -1,74 +0,0 @@ -#!/usr/bin/perl -# This script converts a STL file to AMF - -use strict; -use warnings; - -BEGIN { - use FindBin; - use lib "$FindBin::Bin/../lib"; - use local::lib "$FindBin::Bin/../local-lib"; -} - -use File::Basename qw(basename); -use Getopt::Long qw(:config no_auto_abbrev); -use Slic3r; -$|++; - -my %opt = (); -{ - my %options = ( - 'help' => sub { usage() }, - 'distinct-materials' => \$opt{distinct_materials}, - ); - GetOptions(%options) or usage(1); - $ARGV[0] or usage(1); -} - -{ - my @models = map Slic3r::Model->load_stl($_, basename($_)), @ARGV; - my $output_file = $ARGV[0]; - $output_file =~ s/\.[sS][tT][lL]$/.amf.xml/; - - my $new_model = Slic3r::Model->new; - - if ($opt{distinct_materials} && @models > 1) { - my $new_object = $new_model->add_object; - for my $m (0 .. $#models) { - my $model = $models[$m]; - $new_model->set_material($m, { Name => basename($ARGV[$m]) }); - $new_object->add_volume( - material_id => $m, - facets => $model->objects->[0]->volumes->[0]->facets, - vertices => $model->objects->[0]->vertices, - ); - } - } else { - foreach my $model (@models) { - $new_model->add_object( - vertices => $model->objects->[0]->vertices, - )->add_volume( - facets => $model->objects->[0]->volumes->[0]->facets, - ); - } - } - - printf "Writing to %s\n", basename($output_file); - $new_model->store_amf($output_file); -} - - -sub usage { - my ($exit_code) = @_; - - print <<"EOF"; -Usage: amf-to-stl.pl [ OPTIONS ] file.stl [ file2.stl [ file3.stl ] ] - - --help Output this usage screen and exit - --distinct-materials Assign each STL file to a different material - -EOF - exit ($exit_code || 0); -} - -__END__ diff --git a/utils/zsh/README.markdown b/utils/zsh/README.markdown deleted file mode 100644 index e84b943104..0000000000 --- a/utils/zsh/README.markdown +++ /dev/null @@ -1,21 +0,0 @@ -# ZSH Completions for Slic3r - -To enable zsh(1) completions for Slic3r, add the following to your -``~/.zshrc`` file, replacing ``/path/to/Slic3r/`` with the actual path -to your Slic3r directory: - - typeset -U fpath - - if [[ -d /path/to/Slic3r/utils/zsh/functions ]]; then - fpath=(/path/to/Slic3r/utils/zsh/functions $fpath) - fi - - autoload -Uz compinit - compinit - zstyle ':completion:*' verbose true - zstyle ':completion:*:descriptions' format '%B%d%b' - zstyle ':completion:*:messages' format '%d' - zstyle ':completion:*:warnings' format 'No matches for %d' - zstyle ':completion:*' group-name '%d' - -See the zshcompsys(1) man page for further details. diff --git a/utils/zsh/functions/_slic3r b/utils/zsh/functions/_slic3r deleted file mode 100644 index cea887cc61..0000000000 --- a/utils/zsh/functions/_slic3r +++ /dev/null @@ -1,118 +0,0 @@ -#compdef -P slic3r(|.pl|.exe) -# -# Slic3r completions configuration for zsh(1). - -# Currently undocumented options: -# --debug, --gui, --ignore-nonexistent-config -# --acceleration, --perimeter-acceleration, --infill-acceleration - -_arguments -S \ - '(- *)--help[output usage screen and exit]' \ - '(- *)--version[output the version of Slic3r and exit]' \ - '--save[save configuration to file]:config output file:_files -g "*.(#i)ini(-.)"' \ - '*--load[load configuration from file]:config input file:_files -g "*.(#i)ini(-.)"' \ - '(--output -o)'{--output,-o}'[specify output file]:output file:_files -g "*.(#i)(gcode|svg)(-.)"' \ - '(--threads -j)'{--threads,-j}'[specify number of threads to use]:number of threads' \ - \ - '--output-filename-format[specify output filename format]:output filename format' \ - '*--post-process[specify post-processing script]:post-processing script file:_files' \ - '--export-svg[export SVG containing slices instead of G-code]' \ - '(--merge -m)'{--merge,-m}'[merge multiple input files into a single print]' \ - \ - '*--nozzle-diameter[specify nozzle diameter]:nozzle diameter in mm' \ - '--print-center[specify print center coordinates]:print center coordinates in mm,mm' \ - '--z-offset[specify Z-axis offset]:Z-axis offset in mm' \ - '--gcode-flavor[specify the type of G-code to generate]:G-code flavor:(reprap teacup repetier makerware sailfish mach3 machinekit smoothie no-extrusion)' \ - '(--use-relative-e-distances --no-use-relative-e-distances)'--{no-,}use-relative-e-distances'[disable/enable relative E values]' \ - '--extrusion-axis[specify letter associated with the extrusion axis]:extrusion axis letter' \ - '(--gcode-arcs --no-gcode-arcs)'--{no-,}gcode-arcs'[disable/enable G2/G3 commands for native arcs]' \ - '(--gcode-comments --no-gcode-comments)'--{no-,}gcode-comments'[disable/enable verbose G-code comments]' \ - \ - '*--filament-diameter[specify raw filament diameter]:raw filament diameter in mm' \ - '*--extrusion-multiplier[specify multiplier for amount of plastic extruded]:extrusion multiplier' \ - '*--temperature[specify extrusion temperature]:extrusion temperature in Celsius' \ - '*--first-layer-temperature[specify extrusion temperature for the first layer]:first layer extrusion temperature in Celsius' \ - '--bed-temperature[specify heated bed temperature]:heated bed temperature in Celsius' \ - '--first-layer-bed-temperature[specify heated bed temperature for the first layer]:first layer heated bed temperature in Celsius' \ - \ - '--perimeter-extruder[specify extruder to use for printing perimeters]:extruder number' \ - '--infill-extruder[specify extruder to use for printing infill]:extruder number' \ - '--support-material-extruder[specify extruder to use for printing support material]:extruder number' \ - \ - '--travel-speed[specify speed of non-print moves]:speed of non-print moves in mm/s' \ - '--perimeter-speed[specify speed of print moves for perimeters]:speed of print moves for perimeters in mm/s' \ - '--external-perimeter-speed[specify speed of print moves for external perimeters]:speed of print moves for external perimeters in mm/s or % of --perimeter-speed' \ - '--small-perimeter-speed[specify speed of print moves for small perimeters]:speed of print moves for small perimeters in mm/s or % of --perimeter-speed' \ - '--infill-speed[specify speed of infill print moves]:speed of infill print moves in mm/s' \ - '--solid-infill-speed[specify speed of solid surface print moves]:speed of solid surface print moves in mm/s or % of --infill-speed' \ - '--top-solid-infill-speed[specify speed of top surface print moves]:speed of top surface print moves in mm/s or % of --solid-infill-speed' \ - '--bridge-speed[specify speed of bridge print moves]:speed of bridge print moves in mm/s' \ - '--first-layer-speed[specify speed of bottom layer print moves]:speed of bottom layer print moves in mm/s or % of normal speeds' \ - \ - '--layer-height[specify layer height]:layer height in mm' \ - '--first-layer-height[specify layer height for bottom layer]:layer height for bottom layer in mm or % of --layer-height' \ - '--infill-every-layers[specify infill for every N layers]:N layers' \ - \ - '--perimeters[specify number of perimeters]:number of perimeters' \ - '--solid-layers[specify number of solid layers to do for top/bottom surfaces]:number of layers for top/bottom surfaces' \ - '--fill-density[specify infill density]:infill density in percent' \ - '--fill-angle[specify infill angle]:infill angle in degrees' \ - '--fill-pattern[specify pattern used for infill]:infill pattern:(rectilinear line concentric honeycomb hilbertcurve archimedeanchords octagramspiral)' \ - '--solid-fill-pattern[specify pattern used for solid layers]:solid fill pattern:(rectilinear concentric hilbertcurve archimedeanchords octagramspiral)' \ - '--start-gcode[load initial G-code from file]:start G-code file:_files -g "*.(#i)(gcode)(-.)"' \ - '--end-gcode[load final G-code from file]:end G-code file:_files -g "*.(#i)(gcode)(-.)"' \ - '--layer-gcode[load layer-change G-code from file]:layer-change G-code file:_files -g "*.(#i)(gcode)(-.)"' \ - '(--support-material --no-support-material)'--{no-,}support-material'[disable/enable generation of support material for overhangs]' \ - '--support-material-threshold[specify support material threshold]:maximum slope angle for generating support material' \ - '--support-material-pattern[specify pattern used for support material]:support material pattern:(rectilinear honeycomb)' \ - '--support-material-spacing[specify spacing between support material lines]:spacing between support material lines in mm' \ - '--support-material-angle[specify support material angle]:support material angle in degrees' \ - '(--randomize-start --no-randomize-start)'--{no-,}randomize-start'[disable/enable randomization of starting point across layers]' \ - '(--extra-perimeters --no-extra-perimeters)'--{no-,}extra-perimeters'[disable/enable generation of extra perimeters when needed]' \ - \ - '--retract-length[specify filament retraction length when pausing extrusion]:filament retraction length in mm' \ - '--retract-speed[specify filament retraction speed]:filament retraction speed in mm/s' \ - '--retract-restart-extra[specify filament length to extrude for compensating retraction]: filament lenght in mm' \ - '--retract-before-travel[specify minimum travel length for activating retraction]:minimum travel length for activating retraction in mm' \ - '--retract-lift[specify Z-axis lift for use when retracting]:Z-axis lift in mm' \ - \ - '(--cooling --no-cooling)'--{no-,}cooling'[disable/enable fan and cooling control]' \ - '--min-fan-speed[specify minimum fan speed]:minimum fan speed in percent' \ - '--max-fan-speed[specify maximum fan speed]:maximum fan speed in percent' \ - '--bridge-fan-speed[specify fan speed to use for bridging]:bridging fan speed in percent' \ - '--fan-below-layer-time[specify maximum layer print time before activating fan]:maximum layer print time in seconds' \ - '--slowdown-below-layer-time[specify maximum layer print time before slowing down printing]:maximum layer print time in seconds' \ - '--min-print-speed[specify minimum print speed]:minimum print speed in mm/s' \ - '--disable-fan-first-layers[specify number of bottom layers to print before activating fan]:number of bottom layers' \ - '(--fan-always-on --no-fan-always-on)'--{no-,}fan-always-on'[disable/enable deactivation of fan]' \ - \ - '--skirts[specify number of skirts]:number of skirts' \ - '--skirt-distance[specify distance between innermost skirt and object]:distance between innermost skirt and object in mm' \ - '--skirt-height[specify number of skirt layers]:number of skirt layers' \ - '--brim-width[specify brim width]:width of brim in mm' \ - \ - '--scale[specify object scaling factor]:object scaling factor in percent' \ - '--rotate[specify object rotation angle]:object rotation angle in degrees' \ - '(--duplicate-grid)--duplicate[specify number of duplicates for auto-arrange]:number of duplicates for auto-arrange' \ - '(--duplicate-grid)--bed-size[specify bed size for auto-arrange]:bed size for auto-arrange in mm,mm' \ - '(--duplicate --bed-size)--duplicate-grid[specify number of duplicates for grid arrangement]:number of duplicates for grid arrangement as x,y' \ - '--duplicate-distance[specify distance between duplicates]:distance between duplicates in mm' \ - \ - '(--complete-objects --no-complete-objects)'--{no-,}complete-objects'[disable/enable completion of each object before starting a new one]' \ - '--extruder-clearance-radius[specify radius above which extruder will not collide with anything]:radius in mm' \ - '--extruder-clearance-height[specify maximum vertical extruder depth]:maximum vertical extruder depth in mm' \ - \ - '--notes[specify notes to be added as comments to the output file]:notes' \ - \ - '--extrusion-width[specify extrusion width]:extrusion width in mm or % of --layer-height' \ - '--first-layer-extrusion-width[specify extrusion width for first layer]:first layer extrusion width in mm or % og --layer-height' \ - '--perimeters-extrusion-width[specify extrusion width for perimeters]:perimeter extrusion width in mm or % of --layer-height' \ - '--infill-extrusion-width[specify extrusion width for infill]:infill extrusion width in mm or % of --layer-height' \ - '--support-material-extrusion-width[specify extrusion width for support material]:support material extrusion width in mm or % of --layer-height' \ - '--bridge-flow-ratio[specify multiplier for extrusion when bridging]:bridge extrusion multiplier' \ - \ - '*:input file:_files -g "*.(#i)(stl|obj|amf|xml|prusa)(-.)"' - -# Local Variables: *** -# mode:sh *** -# End: *** From 9a3db200a56b926ba464795e1e95568ab47eccfb Mon Sep 17 00:00:00 2001 From: bubnikv Date: Tue, 25 Sep 2018 11:53:05 +0200 Subject: [PATCH 036/186] Updated AMF/3MF import to pass configuration into a DynamicPrintConfig instead of PresetBundle. --- src/libslic3r/Format/3mf.cpp | 26 ++++++------- src/libslic3r/Format/3mf.hpp | 3 +- src/libslic3r/Format/AMF.cpp | 39 +++++++++---------- src/libslic3r/Format/AMF.hpp | 7 ++-- src/libslic3r/Model.cpp | 18 ++++++--- src/libslic3r/Model.hpp | 4 +- src/libslic3r/Utils.hpp | 37 +++++++++++++----- src/slic3r.cpp | 8 ++-- src/slic3r/GUI/GLCanvas3D.cpp | 2 +- xs/xsp/Model.xsp | 71 +---------------------------------- 10 files changed, 81 insertions(+), 134 deletions(-) diff --git a/src/libslic3r/Format/3mf.cpp b/src/libslic3r/Format/3mf.cpp index c4a0f300ad..6ae84028e9 100644 --- a/src/libslic3r/Format/3mf.cpp +++ b/src/libslic3r/Format/3mf.cpp @@ -2,7 +2,6 @@ #include "../Model.hpp" #include "../Utils.hpp" #include "../GCode.hpp" -#include "../slic3r/GUI/PresetBundle.hpp" #include "3mf.hpp" @@ -344,16 +343,16 @@ namespace Slic3r { _3MF_Importer(); ~_3MF_Importer(); - bool load_model_from_file(const std::string& filename, Model& model, PresetBundle& bundle); + bool load_model_from_file(const std::string& filename, Model& model, DynamicPrintConfig& config); private: void _destroy_xml_parser(); void _stop_xml_parser(); - bool _load_model_from_file(const std::string& filename, Model& model, PresetBundle& bundle); + bool _load_model_from_file(const std::string& filename, Model& model, DynamicPrintConfig& config); bool _extract_model_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat); void _extract_layer_heights_profile_config_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat); - void _extract_print_config_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat, PresetBundle& bundle, const std::string& archive_filename); + void _extract_print_config_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat, DynamicPrintConfig& config, const std::string& archive_filename); bool _extract_model_config_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat, Model& model); // handlers to parse the .model file @@ -447,7 +446,7 @@ namespace Slic3r { _destroy_xml_parser(); } - bool _3MF_Importer::load_model_from_file(const std::string& filename, Model& model, PresetBundle& bundle) + bool _3MF_Importer::load_model_from_file(const std::string& filename, Model& model, DynamicPrintConfig& config) { m_version = 0; m_model = &model; @@ -465,7 +464,7 @@ namespace Slic3r { m_curr_characters.clear(); clear_errors(); - return _load_model_from_file(filename, model, bundle); + return _load_model_from_file(filename, model, config); } void _3MF_Importer::_destroy_xml_parser() @@ -483,7 +482,7 @@ namespace Slic3r { XML_StopParser(m_xml_parser, false); } - bool _3MF_Importer::_load_model_from_file(const std::string& filename, Model& model, PresetBundle& bundle) + bool _3MF_Importer::_load_model_from_file(const std::string& filename, Model& model, DynamicPrintConfig& config) { mz_zip_archive archive; mz_zip_zero_struct(&archive); @@ -536,7 +535,7 @@ namespace Slic3r { else if (boost::algorithm::iequals(name, PRINT_CONFIG_FILE)) { // extract slic3r print config file - _extract_print_config_from_archive(archive, stat, bundle, filename); + _extract_print_config_from_archive(archive, stat, config, filename); } else if (boost::algorithm::iequals(name, MODEL_CONFIG_FILE)) { @@ -656,7 +655,7 @@ namespace Slic3r { return true; } - void _3MF_Importer::_extract_print_config_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat, PresetBundle& bundle, const std::string& archive_filename) + void _3MF_Importer::_extract_print_config_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat, DynamicPrintConfig& config, const std::string& archive_filename) { if (stat.m_uncomp_size > 0) { @@ -667,8 +666,7 @@ namespace Slic3r { add_error("Error while reading config data to buffer"); return; } -//FIXME Get rid of the dependencies on slic3r GUI library! -// bundle.load_config_string(buffer.data(), archive_filename.c_str()); + config.load_from_gcode_string(buffer.data()); } } @@ -2004,13 +2002,13 @@ namespace Slic3r { return true; } - bool load_3mf(const char* path, PresetBundle* bundle, Model* model) + bool load_3mf(const char* path, DynamicPrintConfig* config, Model* model) { - if ((path == nullptr) || (bundle == nullptr) || (model == nullptr)) + if ((path == nullptr) || (config == nullptr) || (model == nullptr)) return false; _3MF_Importer importer; - bool res = importer.load_model_from_file(path, *model, *bundle); + bool res = importer.load_model_from_file(path, *model, *config); importer.log_errors(); return res; } diff --git a/src/libslic3r/Format/3mf.hpp b/src/libslic3r/Format/3mf.hpp index 85bc812e38..cfab1c6007 100644 --- a/src/libslic3r/Format/3mf.hpp +++ b/src/libslic3r/Format/3mf.hpp @@ -5,10 +5,9 @@ namespace Slic3r { class Model; class Print; - class PresetBundle; // Load the content of a 3mf file into the given model and preset bundle. - extern bool load_3mf(const char* path, PresetBundle* bundle, Model* model); + extern bool load_3mf(const char* path, DynamicPrintConfig* config, Model* model); // Save the given model and the config data contained in the given Print into a 3mf file. // The model could be modified during the export process if meshes are not repaired or have no shared vertices diff --git a/src/libslic3r/Format/AMF.cpp b/src/libslic3r/Format/AMF.cpp index 3e0eb54de5..f24146a59d 100644 --- a/src/libslic3r/Format/AMF.cpp +++ b/src/libslic3r/Format/AMF.cpp @@ -8,8 +8,8 @@ #include "../libslic3r.h" #include "../Model.hpp" #include "../GCode.hpp" +#include "../PrintConfig.hpp" #include "../Utils.hpp" -#include "../slic3r/GUI/PresetBundle.hpp" #include "AMF.hpp" #include @@ -49,7 +49,7 @@ namespace Slic3r struct AMFParserContext { - AMFParserContext(XML_Parser parser, const std::string& archive_filename, PresetBundle* preset_bundle, Model *model) : + AMFParserContext(XML_Parser parser, DynamicPrintConfig *config, Model *model) : m_version(0), m_parser(parser), m_model(*model), @@ -57,8 +57,7 @@ struct AMFParserContext m_volume(nullptr), m_material(nullptr), m_instance(nullptr), - m_preset_bundle(preset_bundle), - m_archive_filename(archive_filename) + m_config(config) { m_path.reserve(12); } @@ -208,10 +207,8 @@ struct AMFParserContext Instance *m_instance; // Generic string buffer for vertices, face indices, metadata etc. std::string m_value[3]; - // Pointer to preset bundle to update if config data are stored inside the amf file - PresetBundle* m_preset_bundle; - // Fullpath name of the amf file - std::string m_archive_filename; + // Pointer to config to update if config data are stored inside the amf file + DynamicPrintConfig *m_config; private: AMFParserContext& operator=(AMFParserContext&); @@ -511,10 +508,8 @@ void AMFParserContext::endElement(const char * /* name */) break; case NODE_TYPE_METADATA: - if ((m_preset_bundle != nullptr) && strncmp(m_value[0].c_str(), SLIC3R_CONFIG_TYPE, strlen(SLIC3R_CONFIG_TYPE)) == 0) { -//FIXME Get rid of the dependencies on slic3r GUI library! -// m_preset_bundle->load_config_string(m_value[1].c_str(), m_archive_filename.c_str()); - } + if ((m_config != nullptr) && strncmp(m_value[0].c_str(), SLIC3R_CONFIG_TYPE, strlen(SLIC3R_CONFIG_TYPE)) == 0) + m_config->load_from_gcode_string(m_value[1].c_str()); else if (strncmp(m_value[0].c_str(), "slic3r.", 7) == 0) { const char *opt_key = m_value[0].c_str() + 7; if (print_config_def.options.find(opt_key) != print_config_def.options.end()) { @@ -603,7 +598,7 @@ void AMFParserContext::endDocument() } // Load an AMF file into a provided model. -bool load_amf_file(const char *path, PresetBundle* bundle, Model *model) +bool load_amf_file(const char *path, DynamicPrintConfig *config, Model *model) { if ((path == nullptr) || (model == nullptr)) return false; @@ -620,7 +615,7 @@ bool load_amf_file(const char *path, PresetBundle* bundle, Model *model) return false; } - AMFParserContext ctx(parser, path, bundle, model); + AMFParserContext ctx(parser, config, model); XML_SetUserData(parser, (void*)&ctx); XML_SetElementHandler(parser, AMFParserContext::startElement, AMFParserContext::endElement); XML_SetCharacterDataHandler(parser, AMFParserContext::characters); @@ -655,7 +650,7 @@ bool load_amf_file(const char *path, PresetBundle* bundle, Model *model) return result; } -bool extract_model_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat, const char* path, PresetBundle* bundle, Model* model, unsigned int& version) +bool extract_model_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat, DynamicPrintConfig* config, Model* model, unsigned int& version) { if (stat.m_uncomp_size == 0) { @@ -671,7 +666,7 @@ bool extract_model_from_archive(mz_zip_archive& archive, const mz_zip_archive_fi return false; } - AMFParserContext ctx(parser, path, bundle, model); + AMFParserContext ctx(parser, config, model); XML_SetUserData(parser, (void*)&ctx); XML_SetElementHandler(parser, AMFParserContext::startElement, AMFParserContext::endElement); XML_SetCharacterDataHandler(parser, AMFParserContext::characters); @@ -707,7 +702,7 @@ bool extract_model_from_archive(mz_zip_archive& archive, const mz_zip_archive_fi } // Load an AMF archive into a provided model. -bool load_amf_archive(const char *path, PresetBundle* bundle, Model *model) +bool load_amf_archive(const char *path, DynamicPrintConfig *config, Model *model) { if ((path == nullptr) || (model == nullptr)) return false; @@ -734,7 +729,7 @@ bool load_amf_archive(const char *path, PresetBundle* bundle, Model *model) { if (boost::iends_with(stat.m_filename, ".amf")) { - if (!extract_model_from_archive(archive, stat, path, bundle, model, version)) + if (!extract_model_from_archive(archive, stat, config, model, version)) { mz_zip_reader_end(&archive); printf("Archive does not contain a valid model"); @@ -762,12 +757,12 @@ bool load_amf_archive(const char *path, PresetBundle* bundle, Model *model) } // Load an AMF file into a provided model. -// If bundle is not a null pointer, updates it if the amf file/archive contains config data -bool load_amf(const char *path, PresetBundle* bundle, Model *model) +// If config is not a null pointer, updates it if the amf file/archive contains config data +bool load_amf(const char *path, DynamicPrintConfig *config, Model *model) { if (boost::iends_with(path, ".amf.xml")) // backward compatibility with older slic3r output - return load_amf_file(path, bundle, model); + return load_amf_file(path, config, model); else if (boost::iends_with(path, ".amf")) { boost::nowide::ifstream file(path, boost::nowide::ifstream::binary); @@ -778,7 +773,7 @@ bool load_amf(const char *path, PresetBundle* bundle, Model *model) file.read(const_cast(zip_mask.data()), 2); file.close(); - return (zip_mask == "PK") ? load_amf_archive(path, bundle, model) : load_amf_file(path, bundle, model); + return (zip_mask == "PK") ? load_amf_archive(path, config, model) : load_amf_file(path, config, model); } else return false; diff --git a/src/libslic3r/Format/AMF.hpp b/src/libslic3r/Format/AMF.hpp index 4779e9a51c..ae8863e02f 100644 --- a/src/libslic3r/Format/AMF.hpp +++ b/src/libslic3r/Format/AMF.hpp @@ -5,10 +5,9 @@ namespace Slic3r { class Model; class Print; -class PresetBundle; -// Load the content of an amf file into the given model and preset bundle. -extern bool load_amf(const char *path, PresetBundle* bundle, Model *model); +// Load the content of an amf file into the given model and configuration. +extern bool load_amf(const char *path, DynamicPrintConfig *config, Model *model); // Save the given model and the config data contained in the given Print into an amf file. // The model could be modified during the export process if meshes are not repaired or have no shared vertices @@ -16,4 +15,4 @@ extern bool store_amf(const char *path, Model *model, Print* print, bool export_ }; // namespace Slic3r -#endif /* slic3r_Format_AMF_hpp_ */ \ No newline at end of file +#endif /* slic3r_Format_AMF_hpp_ */ diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 2d23c69b7c..ae74ab18e3 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -44,10 +44,14 @@ void Model::swap(Model &other) std::swap(this->objects, other.objects); } -Model Model::read_from_file(const std::string &input_file, bool add_default_instances) +Model Model::read_from_file(const std::string &input_file, DynamicPrintConfig *config, bool add_default_instances) { Model model; - + + DynamicPrintConfig temp_config; + if (config == nullptr) + config = &temp_config; + bool result = false; if (boost::algorithm::iends_with(input_file, ".stl")) result = load_stl(input_file.c_str(), &model); @@ -55,7 +59,9 @@ Model Model::read_from_file(const std::string &input_file, bool add_default_inst result = load_obj(input_file.c_str(), &model); else if (!boost::algorithm::iends_with(input_file, ".zip.amf") && (boost::algorithm::iends_with(input_file, ".amf") || boost::algorithm::iends_with(input_file, ".amf.xml"))) - result = load_amf(input_file.c_str(), nullptr, &model); + result = load_amf(input_file.c_str(), config, &model); + else if (boost::algorithm::iends_with(input_file, ".3mf")) + result = load_3mf(input_file.c_str(), config, &model); #ifdef SLIC3R_PRUS else if (boost::algorithm::iends_with(input_file, ".prusa")) result = load_prus(input_file.c_str(), &model); @@ -78,15 +84,15 @@ Model Model::read_from_file(const std::string &input_file, bool add_default_inst return model; } -Model Model::read_from_archive(const std::string &input_file, PresetBundle* bundle, bool add_default_instances) +Model Model::read_from_archive(const std::string &input_file, DynamicPrintConfig *config, bool add_default_instances) { Model model; bool result = false; if (boost::algorithm::iends_with(input_file, ".3mf")) - result = load_3mf(input_file.c_str(), bundle, &model); + result = load_3mf(input_file.c_str(), config, &model); else if (boost::algorithm::iends_with(input_file, ".zip.amf")) - result = load_amf(input_file.c_str(), bundle, &model); + result = load_amf(input_file.c_str(), config, &model); else throw std::runtime_error("Unknown file format. Input file must have .3mf or .zip.amf extension."); diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index 062efdb855..020bf69ac2 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -343,8 +343,8 @@ public: void swap(Model &other); ~Model() { this->clear_objects(); this->clear_materials(); } - static Model read_from_file(const std::string &input_file, bool add_default_instances = true); - static Model read_from_archive(const std::string &input_file, PresetBundle* bundle, bool add_default_instances = true); + static Model read_from_file(const std::string &input_file, DynamicPrintConfig *config = nullptr, bool add_default_instances = true); + static Model read_from_archive(const std::string &input_file, DynamicPrintConfig *config, bool add_default_instances = true); /// Repair the ModelObjects of the current Model. /// This function calls repair function on each TriangleMesh of each model object volume diff --git a/src/libslic3r/Utils.hpp b/src/libslic3r/Utils.hpp index c90ad76508..f7d9e68c15 100644 --- a/src/libslic3r/Utils.hpp +++ b/src/libslic3r/Utils.hpp @@ -76,20 +76,37 @@ extern unsigned get_current_pid(); // Compute the next highest power of 2 of 32-bit v // http://graphics.stanford.edu/~seander/bithacks.html -template -inline T next_highest_power_of_2(T v) +inline uint16_t next_highest_power_of_2(uint16_t v) { - if (v != 0) - -- v; + if (v != 0) + -- v; v |= v >> 1; v |= v >> 2; v |= v >> 4; - if (sizeof(T) >= sizeof(uint16_t)) - v |= v >> 8; - if (sizeof(T) >= sizeof(uint32_t)) - v |= v >> 16; - if (sizeof(T) >= sizeof(uint64_t)) - v |= v >> 32; + v |= v >> 8; + return ++ v; +} +inline uint32_t next_highest_power_of_2(uint32_t v) +{ + if (v != 0) + -- v; + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + return ++ v; +} +inline uint64_t next_highest_power_of_2(uint64_t v) +{ + if (v != 0) + -- v; + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + v |= v >> 32; return ++ v; } diff --git a/src/slic3r.cpp b/src/slic3r.cpp index a31c23f911..4cd833e2f7 100644 --- a/src/slic3r.cpp +++ b/src/slic3r.cpp @@ -133,11 +133,12 @@ int main(int argc, char **argv) // apply command line options to a more specific DynamicPrintConfig which provides normalize() // (command line options override --load files) print_config.apply(config, true); - print_config.normalize(); // write config if requested - if (! cli_config.save.value.empty()) + if (! cli_config.save.value.empty()) { + print_config.normalize(); print_config.save(cli_config.save.value); + } if (cli_config.help) { printUsage(); @@ -153,7 +154,7 @@ int main(int argc, char **argv) } Model model; try { - model = Model::read_from_file(file); + model = Model::read_from_file(file, &print_config, true); } catch (std::exception &e) { boost::nowide::cerr << file << ": " << e.what() << std::endl; exit(1); @@ -226,6 +227,7 @@ int main(int argc, char **argv) print.auto_assign_extruders(mo); print.add_model_object(mo); } + print_config.normalize(); print.apply_config(print_config); std::string err = print.validate(); if (err.empty()) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 658e1731aa..771b397662 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1762,7 +1762,7 @@ bool GLCanvas3D::LegendTexture::generate(const GCodePreviewData& preview_data, c if (items_count > 1) m_original_height += (items_count - 1) * Px_Square_Contour; - int pow_of_two_size = next_highest_power_of_2(std::max(m_original_width, m_original_height)); + int pow_of_two_size = (int)next_highest_power_of_2(std::max(m_original_width, m_original_height)); m_width = pow_of_two_size; m_height = pow_of_two_size; diff --git a/xs/xsp/Model.xsp b/xs/xsp/Model.xsp index 892ecd861d..8764b9e436 100644 --- a/xs/xsp/Model.xsp +++ b/xs/xsp/Model.xsp @@ -21,21 +21,12 @@ %name{read_from_file} Model(std::string input_file, bool add_default_instances = true) %code%{ try { - RETVAL = new Model(Model::read_from_file(input_file, add_default_instances)); + RETVAL = new Model(Model::read_from_file(input_file, nullptr, add_default_instances)); } catch (std::exception& e) { croak("Error while opening %s: %s\n", input_file.c_str(), e.what()); } %}; - %name{read_from_archive} Model(std::string input_file, PresetBundle* bundle, bool add_default_instances = true) - %code%{ - try { - RETVAL = new Model(Model::read_from_archive(input_file, bundle, add_default_instances)); - } catch (std::exception& e) { - croak("Error while opening %s: %s\n", input_file.c_str(), e.what()); - } - %}; - Clone clone() %code%{ RETVAL = THIS; %}; @@ -122,67 +113,7 @@ load_stl(CLASS, path, object_name) OUTPUT: RETVAL -Model* -load_obj(CLASS, path, object_name) - char* CLASS; - char* path; - char* object_name; - CODE: - RETVAL = new Model(); - if (! load_obj(path, RETVAL, object_name)) { - delete RETVAL; - RETVAL = NULL; - } - OUTPUT: - RETVAL - -Model* -load_amf(CLASS, bundle, path) - char* CLASS; - PresetBundle* bundle; - char* path; - CODE: - RETVAL = new Model(); - if (! load_amf(path, bundle, RETVAL)) { - delete RETVAL; - RETVAL = NULL; - } - OUTPUT: - RETVAL - -Model* -load_3mf(CLASS, bundle, path) - char* CLASS; - PresetBundle* bundle; - char* path; - CODE: - RETVAL = new Model(); - if (! load_3mf(path, bundle, RETVAL)) { - delete RETVAL; - RETVAL = NULL; - } - OUTPUT: - RETVAL - -Model* -load_prus(CLASS, path) - char* CLASS; - char* path; - CODE: -#ifdef SLIC3R_PRUS - RETVAL = new Model(); - if (! load_prus(path, RETVAL)) { - delete RETVAL; - RETVAL = NULL; - } -#else - RETVAL = nullptr; -#endif - OUTPUT: - RETVAL - %} - }; %name{Slic3r::Model::Material} class ModelMaterial { From d00fc9a0a8e94893006619cb6c0c499524421aaa Mon Sep 17 00:00:00 2001 From: bubnikv Date: Tue, 25 Sep 2018 12:26:14 +0200 Subject: [PATCH 037/186] Fixed compilation on Linxu --- src/libslic3r/MotionPlanner.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libslic3r/MotionPlanner.cpp b/src/libslic3r/MotionPlanner.cpp index ff3475ed8f..198c39f311 100644 --- a/src/libslic3r/MotionPlanner.cpp +++ b/src/libslic3r/MotionPlanner.cpp @@ -297,7 +297,7 @@ void MotionPlannerGraph::add_edge(size_t from, size_t to, double weight) // Extend adjacency list until this start node. if (m_adjacency_list.size() < from + 1) { // Reserve in powers of two to avoid repeated reallocation. - m_adjacency_list.reserve(std::max(8, next_highest_power_of_2(from + 1))); + m_adjacency_list.reserve(std::max(8, next_highest_power_of_2((uint32_t)(from + 1)))); // Allocate new empty adjacency vectors. m_adjacency_list.resize(from + 1); } From c7621669743bb08c79af06ee6f72efc2654c40d7 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Tue, 25 Sep 2018 12:43:53 +0200 Subject: [PATCH 038/186] size_t is not uint32_t or uint64_t on GCC --- src/libslic3r/Utils.hpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/libslic3r/Utils.hpp b/src/libslic3r/Utils.hpp index f7d9e68c15..3e4437fcc1 100644 --- a/src/libslic3r/Utils.hpp +++ b/src/libslic3r/Utils.hpp @@ -110,6 +110,17 @@ inline uint64_t next_highest_power_of_2(uint64_t v) return ++ v; } +#ifdef __GNUC__ +inline size_t next_highest_power_of_2(size_t v) +{ +#if sizeof(size_t) == sizeof(uint32_t) + return next_highest_power_of_2(uint32_t(v)); +#else + return next_highest_power_of_2(uint64_t(v)); +#endif +} +#endif + extern std::string xml_escape(std::string text); } // namespace Slic3r From 1c06a170c477c56fbe75d235d37b0f25631b5a48 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Tue, 25 Sep 2018 12:48:36 +0200 Subject: [PATCH 039/186] Fix compilation on clang --- src/libslic3r/Utils.hpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/libslic3r/Utils.hpp b/src/libslic3r/Utils.hpp index 3e4437fcc1..98c15db3c4 100644 --- a/src/libslic3r/Utils.hpp +++ b/src/libslic3r/Utils.hpp @@ -110,7 +110,10 @@ inline uint64_t next_highest_power_of_2(uint64_t v) return ++ v; } -#ifdef __GNUC__ +#ifdef __clang__ +// On clang, the size_t is a type of its own, so we need to overload for size_t. +// On MSC, the size_t type aliases to uint64_t / uint32_t, so the following code +// gives a duplicate symbol error. inline size_t next_highest_power_of_2(size_t v) { #if sizeof(size_t) == sizeof(uint32_t) From 85bc3af88a1814a89d190a98fbaeab5df115fc6e Mon Sep 17 00:00:00 2001 From: bubnikv Date: Tue, 25 Sep 2018 13:19:50 +0200 Subject: [PATCH 040/186] Yet another fix of next_highest_power_of_2() on clang --- src/libslic3r/Utils.hpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/libslic3r/Utils.hpp b/src/libslic3r/Utils.hpp index 98c15db3c4..8feb177479 100644 --- a/src/libslic3r/Utils.hpp +++ b/src/libslic3r/Utils.hpp @@ -116,10 +116,12 @@ inline uint64_t next_highest_power_of_2(uint64_t v) // gives a duplicate symbol error. inline size_t next_highest_power_of_2(size_t v) { -#if sizeof(size_t) == sizeof(uint32_t) - return next_highest_power_of_2(uint32_t(v)); -#else +#if SSIZE_MAX == 9223372036854775807 + static_assert(sizeof(size_t) == sizeof(uint64_t)); return next_highest_power_of_2(uint64_t(v)); +#else + static_assert(sizeof(size_t) == sizeof(uint32_t)); + return next_highest_power_of_2(uint32_t(v)); #endif } #endif From 8945763221089899dfdc397e07cb2fba9c117297 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Tue, 25 Sep 2018 14:30:57 +0200 Subject: [PATCH 041/186] Rewrote .PRUSA file parser from wxWidgets zip to miniz. Added tracing for mesh repair. --- src/libslic3r/Format/PRUS.cpp | 665 ++++++++++++++++----------------- src/libslic3r/Format/PRUS.hpp | 3 - src/libslic3r/Model.cpp | 2 - src/libslic3r/TriangleMesh.cpp | 6 + src/libslic3r/Utils.hpp | 4 +- 5 files changed, 327 insertions(+), 353 deletions(-) diff --git a/src/libslic3r/Format/PRUS.cpp b/src/libslic3r/Format/PRUS.cpp index 27095acef4..bd6beeb21d 100644 --- a/src/libslic3r/Format/PRUS.cpp +++ b/src/libslic3r/Format/PRUS.cpp @@ -1,12 +1,10 @@ -#ifdef SLIC3R_PRUS - #include +#include +#include #include -#include -#include -#include +#include #include @@ -35,64 +33,28 @@ struct StlHeader static_assert(sizeof(StlHeader) == 84, "StlHeader size not correct"); -// Buffered line reader for the wxInputStream. +// Buffered line reader to a string buffer. class LineReader { public: - LineReader(wxInputStream &input_stream, const char *initial_data, int initial_len) : - m_input_stream(input_stream), - m_pos(0), - m_len(initial_len) - { - assert(initial_len >= 0 && initial_len < m_bufsize); - memcpy(m_buffer, initial_data, initial_len); - } + LineReader(std::vector &data) : m_buffer(data), m_pos(0), m_len(data.size()) {} const char* next_line() { - for (;;) { - // Skip empty lines. - while (m_pos < m_len && (m_buffer[m_pos] == '\r' || m_buffer[m_pos] == '\n')) - ++ m_pos; - if (m_pos == m_len) { - // Empty buffer, fill it from the input stream. - m_pos = 0; - m_input_stream.Read(m_buffer, m_bufsize - 1); - m_len = m_input_stream.LastRead(); - assert(m_len >= 0 && m_len < m_bufsize); - if (m_len == 0) - // End of file. - return nullptr; - // Skip empty lines etc. - continue; - } - // The buffer is nonempty and it does not start with end of lines. Find the first end of line. - int end = m_pos + 1; - while (end < m_len && m_buffer[end] != '\r' && m_buffer[end] != '\n') - ++ end; - if (end == m_len && ! m_input_stream.Eof() && m_len < m_bufsize) { - // Move the buffer content to the buffer start and fill the rest of the buffer. - assert(m_pos > 0); - memmove(m_buffer, m_buffer + m_pos, m_len - m_pos); - m_len -= m_pos; - assert(m_len >= 0 && m_len < m_bufsize); - m_pos = 0; - m_input_stream.Read(m_buffer + m_len, m_bufsize - 1 - m_len); - int new_data = m_input_stream.LastRead(); - if (new_data > 0) { - m_len += new_data; - assert(m_len >= 0 && m_len < m_bufsize); - continue; - } - } - char *ptr_out = m_buffer + m_pos; - m_pos = end + 1; - m_buffer[end] = 0; - if (m_pos >= m_len) { - m_pos = 0; - m_len = 0; - } - return ptr_out; + // Skip empty lines. + while (m_pos < m_len && (m_buffer[m_pos] == '\r' || m_buffer[m_pos] == '\n')) + ++ m_pos; + if (m_pos == m_len) { + // End of file. + return nullptr; } + // The buffer is nonempty and it does not start with end of lines. Find the first end of line. + int end = m_pos + 1; + while (end < m_len && m_buffer[end] != '\r' && m_buffer[end] != '\n') + ++ end; + char *ptr_out = m_buffer.data() + m_pos; + m_pos = end + 1; + m_buffer[end] = 0; + return ptr_out; } int next_line_scanf(const char *format, ...) @@ -109,303 +71,314 @@ public: } private: - wxInputStream &m_input_stream; - static const int m_bufsize = 4096; - char m_buffer[m_bufsize]; - int m_pos = 0; - int m_len = 0; + std::vector &m_buffer; + int m_pos; + int m_len; }; +static void extract_model_from_archive( + // name of the model file + const char *name, + // path to the archive + const char *path, + // content of scene.xml + const std::vector &scene_xml_data, + // loaded data of this STL + std::vector &data, + // Model, to which the newly loaded objects will be added + Model *model, + // To map multiple STLs into a single model object for multi-material prints. + std::map &group_to_model_object) +{ + // Find the model entry in the XML data. + char model_name_tag[1024]; + sprintf(model_name_tag, "", name); + const char *model_xml = strstr(scene_xml_data.data(), model_name_tag); + const char *zero_tag = ""; + const char *zero_xml = strstr(scene_xml_data.data(), zero_tag); + float trafo[3][4] = { 0 }; +#if ENABLE_MODELINSTANCE_3D_ROTATION + Vec3d instance_rotation = Vec3d::Zero(); +#else + double instance_rotation = 0.; +#endif // ENABLE_MODELINSTANCE_3D_ROTATION + double instance_scaling_factor = 1.f; +#if ENABLE_MODELINSTANCE_3D_OFFSET + Vec3d instance_offset = Vec3d::Zero(); +#else + Vec2d instance_offset(0., 0.); +#endif // ENABLE_MODELINSTANCE_3D_OFFSET + bool trafo_set = false; + unsigned int group_id = (unsigned int)-1; + unsigned int extruder_id = (unsigned int)-1; + ModelObject *model_object = nullptr; + if (model_xml != nullptr) { + model_xml += strlen(model_name_tag); + const char *position_tag = ""; + const char *position_xml = strstr(model_xml, position_tag); + const char *rotation_tag = ""; + const char *rotation_xml = strstr(model_xml, rotation_tag); + const char *scale_tag = ""; + const char *scale_xml = strstr(model_xml, scale_tag); + float position[3], rotation[3], scale[3], zero[3]; + if (position_xml != nullptr && rotation_xml != nullptr && scale_xml != nullptr && zero_xml != nullptr && + sscanf(position_xml+strlen(position_tag), + "[%f, %f, %f]", position, position+1, position+2) == 3 && + sscanf(rotation_xml+strlen(rotation_tag), + "[%f, %f, %f]", rotation, rotation+1, rotation+2) == 3 && + sscanf(scale_xml+strlen(scale_tag), + "[%f, %f, %f]", scale, scale+1, scale+2) == 3 && + sscanf(zero_xml+strlen(zero_tag), + "[%f, %f, %f]", zero, zero+1, zero+2) == 3) { + if (scale[0] == scale[1] && scale[1] == scale[2]) { + instance_scaling_factor = scale[0]; + scale[0] = scale[1] = scale[2] = 1.; + } +#if ENABLE_MODELINSTANCE_3D_ROTATION + instance_rotation = Vec3d(-(double)rotation[0], -(double)rotation[1], -(double)rotation[2]); +#else + if (rotation[0] == 0. && rotation[1] == 0.) { + instance_rotation = - rotation[2]; + rotation[2] = 0.; + } +#endif // ENABLE_MODELINSTANCE_3D_ROTATION + Eigen::Matrix3f mat_rot, mat_scale, mat_trafo; + mat_rot = Eigen::AngleAxisf(-rotation[2], Eigen::Vector3f::UnitZ()) * + Eigen::AngleAxisf(-rotation[1], Eigen::Vector3f::UnitY()) * + Eigen::AngleAxisf(-rotation[0], Eigen::Vector3f::UnitX()); + mat_scale = Eigen::Scaling(scale[0], scale[1], scale[2]); + mat_trafo = mat_rot * mat_scale; + for (size_t r = 0; r < 3; ++ r) { + for (size_t c = 0; c < 3; ++ c) + trafo[r][c] += mat_trafo(r, c); + } +#if ENABLE_MODELINSTANCE_3D_OFFSET + instance_offset = Vec3d((double)(position[0] - zero[0]), (double)(position[1] - zero[1]), (double)(position[2] - zero[2])); +#else + instance_offset(0) = position[0] - zero[0]; + instance_offset(1) = position[1] - zero[1]; +#endif // ENABLE_MODELINSTANCE_3D_OFFSET + trafo[2][3] = position[2] / instance_scaling_factor; + trafo_set = true; + } + const char *group_tag = ""; + const char *group_xml = strstr(model_xml, group_tag); + const char *extruder_tag = ""; + const char *extruder_xml = strstr(model_xml, extruder_tag); + if (group_xml != nullptr) { + int group = atoi(group_xml + strlen(group_tag)); + if (group > 0) { + group_id = group; + auto it = group_to_model_object.find(group_id); + if (it != group_to_model_object.end()) + model_object = it->second; + } + } + if (extruder_xml != nullptr) { + int e = atoi(extruder_xml + strlen(extruder_tag)); + if (e > 0) + extruder_id = e; + } + } + if (! trafo_set) + throw std::runtime_error(std::string("Archive ") + path + " does not contain a valid entry in scene.xml for " + name); + + // Extract the STL. + StlHeader header; + TriangleMesh mesh; + bool mesh_valid = false; + bool stl_ascii = false; + if (data.size() > sizeof(StlHeader)) { + memcpy((char*)&header, data.data(), sizeof(StlHeader)); + if (strncmp(header.comment, "solid ", 6) == 0) + stl_ascii = true; + else { + // Header has been extracted. Now read the faces. + stl_file &stl = mesh.stl; + stl.error = 0; + stl.stats.type = inmemory; + stl.stats.number_of_facets = header.nTriangles; + stl.stats.original_num_facets = header.nTriangles; + stl_allocate(&stl); + if (header.nTriangles > 0 && data.size() == 50 * header.nTriangles + sizeof(StlHeader)) { + memcpy((char*)stl.facet_start, data.data() + sizeof(StlHeader), 50 * header.nTriangles); + if (sizeof(stl_facet) > SIZEOF_STL_FACET) { + // The stl.facet_start is not packed tightly. Unpack the array of stl_facets. + unsigned char *data = (unsigned char*)stl.facet_start; + for (size_t i = header.nTriangles - 1; i > 0; -- i) + memmove(data + i * sizeof(stl_facet), data + i * SIZEOF_STL_FACET, SIZEOF_STL_FACET); + } + // All the faces have been read. + stl_get_size(&stl); + mesh.repair(); + // Transform the model. + stl_transform(&stl, &trafo[0][0]); + if (std::abs(stl.stats.min(2)) < EPSILON) + stl.stats.min(2) = 0.; + // Add a mesh to a model. + if (mesh.facets_count() > 0) + mesh_valid = true; + } + } + } else + stl_ascii = true; + + if (stl_ascii) { + // Try to parse ASCII STL. + char normal_buf[3][32]; + stl_facet facet; + std::vector facets; + LineReader line_reader(data); + std::string solid_name; + facet.extra[0] = facet.extra[1] = 0; + for (;;) { + const char *line = line_reader.next_line(); + if (line == nullptr) + // End of file. + break; + if (strncmp(line, "solid", 5) == 0) { + // Opening the "solid" block. + if (! solid_name.empty()) { + // Error, solid block is already open. + facets.clear(); + break; + } + solid_name = line + 5; + if (solid_name.empty()) + solid_name = "unknown"; + continue; + } + if (strncmp(line, "endsolid", 8) == 0) { + // Closing the "solid" block. + if (solid_name.empty()) { + // Error, no solid block is open. + facets.clear(); + break; + } + solid_name.clear(); + continue; + } + // Line has to start with the word solid. + int res_normal = sscanf(line, " facet normal %31s %31s %31s", normal_buf[0], normal_buf[1], normal_buf[2]); + assert(res_normal == 3); + int res_outer_loop = line_reader.next_line_scanf(" outer loop"); + assert(res_outer_loop == 0); + int res_vertex1 = line_reader.next_line_scanf(" vertex %f %f %f", &facet.vertex[0](0), &facet.vertex[0](1), &facet.vertex[0](2)); + assert(res_vertex1 == 3); + int res_vertex2 = line_reader.next_line_scanf(" vertex %f %f %f", &facet.vertex[1](0), &facet.vertex[1](1), &facet.vertex[1](2)); + assert(res_vertex2 == 3); + int res_vertex3 = line_reader.next_line_scanf(" vertex %f %f %f", &facet.vertex[2](0), &facet.vertex[2](1), &facet.vertex[2](2)); + assert(res_vertex3 == 3); + int res_endloop = line_reader.next_line_scanf(" endloop"); + assert(res_endloop == 0); + int res_endfacet = line_reader.next_line_scanf(" endfacet"); + if (res_normal != 3 || res_outer_loop != 0 || res_vertex1 != 3 || res_vertex2 != 3 || res_vertex3 != 3 || res_endloop != 0 || res_endfacet != 0) { + // perror("Something is syntactically very wrong with this ASCII STL!"); + facets.clear(); + break; + } + // The facet normal has been parsed as a single string as to workaround for not a numbers in the normal definition. + if (sscanf(normal_buf[0], "%f", &facet.normal(0)) != 1 || + sscanf(normal_buf[1], "%f", &facet.normal(1)) != 1 || + sscanf(normal_buf[2], "%f", &facet.normal(2)) != 1) { + // Normal was mangled. Maybe denormals or "not a number" were stored? + // Just reset the normal and silently ignore it. + memset(&facet.normal, 0, sizeof(facet.normal)); + } + facets.emplace_back(facet); + } + if (! facets.empty() && solid_name.empty()) { + stl_file &stl = mesh.stl; + stl.stats.type = inmemory; + stl.stats.number_of_facets = facets.size(); + stl.stats.original_num_facets = facets.size(); + stl_allocate(&stl); + memcpy((void*)stl.facet_start, facets.data(), facets.size() * 50); + stl_get_size(&stl); + mesh.repair(); + // Transform the model. + stl_transform(&stl, &trafo[0][0]); + // Add a mesh to a model. + if (mesh.facets_count() > 0) + mesh_valid = true; + } + } + + if (! mesh_valid) + throw std::runtime_error(std::string("Archive ") + path + " does not contain a valid mesh for " + name); + + // Add this mesh to the model. + ModelVolume *volume = nullptr; + if (model_object == nullptr) { + // This is a first mesh of a group. Create a new object & volume. + model_object = model->add_object(name, path, std::move(mesh)); + volume = model_object->volumes.front(); + ModelInstance *instance = model_object->add_instance(); +#if ENABLE_MODELINSTANCE_3D_ROTATION + instance->set_rotation(instance_rotation); +#else + instance->rotation = instance_rotation; +#endif // ENABLE_MODELINSTANCE_3D_ROTATION + instance->scaling_factor = instance_scaling_factor; +#if ENABLE_MODELINSTANCE_3D_OFFSET + instance->set_offset(instance_offset); +#else + instance->offset = instance_offset; +#endif // ENABLE_MODELINSTANCE_3D_OFFSET + if (group_id != (size_t)-1) + group_to_model_object[group_id] = model_object; + } else { + // This is not the 1st mesh of a group. Add it to the ModelObject. + volume = model_object->add_volume(std::move(mesh)); + volume->name = name; + } + // Set the extruder to the volume. + if (extruder_id != (unsigned int)-1) { + char str_extruder[64]; + sprintf(str_extruder, "%ud", extruder_id); + volume->config.set_deserialize("extruder", str_extruder); + } +} + // Load a PrusaControl project file into a provided model. bool load_prus(const char *path, Model *model) { - // To receive the content of the zipped 'scene.xml' file. - std::vector scene_xml_data; - wxFFileInputStream in( -#ifdef WIN32 - // On Windows, convert to a 16bit unicode string. - boost::nowide::widen(path).c_str() -#else - path -#endif - ); - wxZipInputStream zip(in); - std::unique_ptr entry; - size_t num_models = 0; - std::map group_to_model_object; - while (entry.reset(zip.GetNextEntry()), entry.get() != NULL) { - wxString name = entry->GetName(); - if (name == "scene.xml") { - if (! scene_xml_data.empty()) { - // scene.xml has been found more than once in the archive. - return false; - } - size_t size_last = 0; - size_t size_incr = 4096; - scene_xml_data.resize(size_incr); - while (! zip.Read(scene_xml_data.data() + size_last, size_incr).Eof()) { - size_last += zip.LastRead(); - if (scene_xml_data.size() < size_last + size_incr) - scene_xml_data.resize(size_last + size_incr); - } - size_last += zip.LastRead(); - if (scene_xml_data.size() == size_last) - scene_xml_data.resize(size_last + 1); - else if (scene_xml_data.size() > size_last + 1) - scene_xml_data.erase(scene_xml_data.begin() + size_last + 1, scene_xml_data.end()); - scene_xml_data[size_last] = 0; - } - else if (name.EndsWith(".stl") || name.EndsWith(".STL")) { - // Find the model entry in the XML data. - const wxScopedCharBuffer name_utf8 = name.ToUTF8(); - char model_name_tag[1024]; - sprintf(model_name_tag, "", name_utf8.data()); - const char *model_xml = strstr(scene_xml_data.data(), model_name_tag); - const char *zero_tag = ""; - const char *zero_xml = strstr(scene_xml_data.data(), zero_tag); - float trafo[3][4] = { 0 }; -#if ENABLE_MODELINSTANCE_3D_ROTATION - Vec3d instance_rotation = Vec3d::Zero(); -#else - double instance_rotation = 0.; -#endif // ENABLE_MODELINSTANCE_3D_ROTATION - double instance_scaling_factor = 1.f; -#if ENABLE_MODELINSTANCE_3D_OFFSET - Vec3d instance_offset = Vec3d::Zero(); -#else - Vec2d instance_offset(0., 0.); -#endif // ENABLE_MODELINSTANCE_3D_OFFSET - bool trafo_set = false; - unsigned int group_id = (unsigned int)-1; - unsigned int extruder_id = (unsigned int)-1; - ModelObject *model_object = nullptr; - if (model_xml != nullptr) { - model_xml += strlen(model_name_tag); - const char *position_tag = ""; - const char *position_xml = strstr(model_xml, position_tag); - const char *rotation_tag = ""; - const char *rotation_xml = strstr(model_xml, rotation_tag); - const char *scale_tag = ""; - const char *scale_xml = strstr(model_xml, scale_tag); - float position[3], rotation[3], scale[3], zero[3]; - if (position_xml != nullptr && rotation_xml != nullptr && scale_xml != nullptr && zero_xml != nullptr && - sscanf(position_xml+strlen(position_tag), - "[%f, %f, %f]", position, position+1, position+2) == 3 && - sscanf(rotation_xml+strlen(rotation_tag), - "[%f, %f, %f]", rotation, rotation+1, rotation+2) == 3 && - sscanf(scale_xml+strlen(scale_tag), - "[%f, %f, %f]", scale, scale+1, scale+2) == 3 && - sscanf(zero_xml+strlen(zero_tag), - "[%f, %f, %f]", zero, zero+1, zero+2) == 3) { - if (scale[0] == scale[1] && scale[1] == scale[2]) { - instance_scaling_factor = scale[0]; - scale[0] = scale[1] = scale[2] = 1.; - } -#if ENABLE_MODELINSTANCE_3D_ROTATION - instance_rotation = Vec3d(-(double)rotation[0], -(double)rotation[1], -(double)rotation[2]); -#else - if (rotation[0] == 0. && rotation[1] == 0.) { - instance_rotation = - rotation[2]; - rotation[2] = 0.; - } -#endif // ENABLE_MODELINSTANCE_3D_ROTATION - Eigen::Matrix3f mat_rot, mat_scale, mat_trafo; - mat_rot = Eigen::AngleAxisf(-rotation[2], Eigen::Vector3f::UnitZ()) * - Eigen::AngleAxisf(-rotation[1], Eigen::Vector3f::UnitY()) * - Eigen::AngleAxisf(-rotation[0], Eigen::Vector3f::UnitX()); - mat_scale = Eigen::Scaling(scale[0], scale[1], scale[2]); - mat_trafo = mat_rot * mat_scale; - for (size_t r = 0; r < 3; ++ r) { - for (size_t c = 0; c < 3; ++ c) - trafo[r][c] += mat_trafo(r, c); - } -#if ENABLE_MODELINSTANCE_3D_OFFSET - instance_offset = Vec3d((double)(position[0] - zero[0]), (double)(position[1] - zero[1]), (double)(position[2] - zero[2])); -#else - instance_offset(0) = position[0] - zero[0]; - instance_offset(1) = position[1] - zero[1]; -#endif // ENABLE_MODELINSTANCE_3D_OFFSET - trafo[2][3] = position[2] / instance_scaling_factor; - trafo_set = true; - } - const char *group_tag = ""; - const char *group_xml = strstr(model_xml, group_tag); - const char *extruder_tag = ""; - const char *extruder_xml = strstr(model_xml, extruder_tag); - if (group_xml != nullptr) { - int group = atoi(group_xml + strlen(group_tag)); - if (group > 0) { - group_id = group; - auto it = group_to_model_object.find(group_id); - if (it != group_to_model_object.end()) - model_object = it->second; - } - } - if (extruder_xml != nullptr) { - int e = atoi(extruder_xml + strlen(extruder_tag)); - if (e > 0) - extruder_id = e; - } - } - if (trafo_set) { - // Extract the STL. - StlHeader header; - TriangleMesh mesh; - bool mesh_valid = false; - bool stl_ascii = false; - if (!zip.Read((void*)&header, sizeof(StlHeader)).Eof()) { - if (strncmp(header.comment, "solid ", 6) == 0) - stl_ascii = true; - else { - // Header has been extracted. Now read the faces. - stl_file &stl = mesh.stl; - stl.error = 0; - stl.stats.type = inmemory; - stl.stats.number_of_facets = header.nTriangles; - stl.stats.original_num_facets = header.nTriangles; - stl_allocate(&stl); - if (header.nTriangles > 0 && zip.ReadAll((void*)stl.facet_start, 50 * header.nTriangles)) { - if (sizeof(stl_facet) > SIZEOF_STL_FACET) { - // The stl.facet_start is not packed tightly. Unpack the array of stl_facets. - unsigned char *data = (unsigned char*)stl.facet_start; - for (size_t i = header.nTriangles - 1; i > 0; -- i) - memmove(data + i * sizeof(stl_facet), data + i * SIZEOF_STL_FACET, SIZEOF_STL_FACET); - } - // All the faces have been read. - stl_get_size(&stl); - mesh.repair(); - // Transform the model. - stl_transform(&stl, &trafo[0][0]); - if (std::abs(stl.stats.min(2)) < EPSILON) - stl.stats.min(2) = 0.; - // Add a mesh to a model. - if (mesh.facets_count() > 0) - mesh_valid = true; - } - } - } else - stl_ascii = true; - if (stl_ascii) { - // Try to parse ASCII STL. - char normal_buf[3][32]; - stl_facet facet; - std::vector facets; - LineReader line_reader(zip, (char*)&header, zip.LastRead()); - std::string solid_name; - facet.extra[0] = facet.extra[1] = 0; - for (;;) { - const char *line = line_reader.next_line(); - if (line == nullptr) - // End of file. - break; - if (strncmp(line, "solid", 5) == 0) { - // Opening the "solid" block. - if (! solid_name.empty()) { - // Error, solid block is already open. - facets.clear(); - break; - } - solid_name = line + 5; - if (solid_name.empty()) - solid_name = "unknown"; - continue; - } - if (strncmp(line, "endsolid", 8) == 0) { - // Closing the "solid" block. - if (solid_name.empty()) { - // Error, no solid block is open. - facets.clear(); - break; - } - solid_name.clear(); - continue; - } - // Line has to start with the word solid. - int res_normal = sscanf(line, " facet normal %31s %31s %31s", normal_buf[0], normal_buf[1], normal_buf[2]); - assert(res_normal == 3); - int res_outer_loop = line_reader.next_line_scanf(" outer loop"); - assert(res_outer_loop == 0); - int res_vertex1 = line_reader.next_line_scanf(" vertex %f %f %f", &facet.vertex[0](0), &facet.vertex[0](1), &facet.vertex[0](2)); - assert(res_vertex1 == 3); - int res_vertex2 = line_reader.next_line_scanf(" vertex %f %f %f", &facet.vertex[1](0), &facet.vertex[1](1), &facet.vertex[1](2)); - assert(res_vertex2 == 3); - int res_vertex3 = line_reader.next_line_scanf(" vertex %f %f %f", &facet.vertex[2](0), &facet.vertex[2](1), &facet.vertex[2](2)); - assert(res_vertex3 == 3); - int res_endloop = line_reader.next_line_scanf(" endloop"); - assert(res_endloop == 0); - int res_endfacet = line_reader.next_line_scanf(" endfacet"); - if (res_normal != 3 || res_outer_loop != 0 || res_vertex1 != 3 || res_vertex2 != 3 || res_vertex3 != 3 || res_endloop != 0 || res_endfacet != 0) { - // perror("Something is syntactically very wrong with this ASCII STL!"); - facets.clear(); - break; - } - // The facet normal has been parsed as a single string as to workaround for not a numbers in the normal definition. - if (sscanf(normal_buf[0], "%f", &facet.normal(0)) != 1 || - sscanf(normal_buf[1], "%f", &facet.normal(1)) != 1 || - sscanf(normal_buf[2], "%f", &facet.normal(2)) != 1) { - // Normal was mangled. Maybe denormals or "not a number" were stored? - // Just reset the normal and silently ignore it. - memset(&facet.normal, 0, sizeof(facet.normal)); - } - facets.emplace_back(facet); - } - if (! facets.empty() && solid_name.empty()) { - stl_file &stl = mesh.stl; - stl.stats.type = inmemory; - stl.stats.number_of_facets = facets.size(); - stl.stats.original_num_facets = facets.size(); - stl_allocate(&stl); - memcpy((void*)stl.facet_start, facets.data(), facets.size() * 50); - stl_get_size(&stl); - mesh.repair(); - // Transform the model. - stl_transform(&stl, &trafo[0][0]); - // Add a mesh to a model. - if (mesh.facets_count() > 0) - mesh_valid = true; - } - } - - if (mesh_valid) { - // Add this mesh to the model. - ModelVolume *volume = nullptr; - if (model_object == nullptr) { - // This is a first mesh of a group. Create a new object & volume. - model_object = model->add_object(name_utf8.data(), path, std::move(mesh)); - volume = model_object->volumes.front(); - ModelInstance *instance = model_object->add_instance(); -#if ENABLE_MODELINSTANCE_3D_ROTATION - instance->set_rotation(instance_rotation); -#else - instance->rotation = instance_rotation; -#endif // ENABLE_MODELINSTANCE_3D_ROTATION - instance->scaling_factor = instance_scaling_factor; -#if ENABLE_MODELINSTANCE_3D_OFFSET - instance->set_offset(instance_offset); -#else - instance->offset = instance_offset; -#endif // ENABLE_MODELINSTANCE_3D_OFFSET - ++num_models; - if (group_id != (size_t)-1) - group_to_model_object[group_id] = model_object; - } else { - // This is not the 1st mesh of a group. Add it to the ModelObject. - volume = model_object->add_volume(std::move(mesh)); - volume->name = name_utf8.data(); - } - // Set the extruder to the volume. - if (extruder_id != (unsigned int)-1) { - char str_extruder[64]; - sprintf(str_extruder, "%ud", extruder_id); - volume->config.set_deserialize("extruder", str_extruder); - } - } + mz_zip_archive archive; + mz_zip_zero_struct(&archive); + mz_bool res = mz_zip_reader_init_file(&archive, path, 0); + size_t n_models_initial = model->objects.size(); + try { + if (res == MZ_FALSE) + throw std::runtime_error(std::string("Unable to init zip reader for ") + path); + std::vector scene_xml_data; + // For grouping multiple STLs into a single ModelObject for multi-material prints. + std::map group_to_model_object; + mz_uint num_entries = mz_zip_reader_get_num_files(&archive); + for (mz_uint i = 0; i < num_entries; ++ i) { + mz_zip_archive_file_stat stat; + if (! mz_zip_reader_file_stat(&archive, i, &stat)) + continue; + std::vector buffer; + buffer.assign((size_t)stat.m_uncomp_size + 1, 0); + res = mz_zip_reader_extract_file_to_mem(&archive, stat.m_filename, (char*)buffer.data(), (size_t)stat.m_uncomp_size, 0); + if (res == MZ_FALSE) + std::runtime_error(std::string("Error while extracting a file from ") + path); + if (strcmp(stat.m_filename, "scene.xml") == 0) { + if (! scene_xml_data.empty()) + throw std::runtime_error(std::string("Multiple scene.xml were found in the archive.") + path); + scene_xml_data = std::move(buffer); + } else if (boost::iends_with(stat.m_filename, ".stl")) { + // May throw std::exception + extract_model_from_archive(stat.m_filename, path, scene_xml_data, buffer, model, group_to_model_object); } } + } catch (std::exception &ex) { + mz_zip_reader_end(&archive); + throw ex; } - return num_models > 0; + + mz_zip_reader_end(&archive); + return model->objects.size() > n_models_initial; } }; // namespace Slic3r - -#endif /* SLIC3R_PRUS */ diff --git a/src/libslic3r/Format/PRUS.hpp b/src/libslic3r/Format/PRUS.hpp index 8559a70d65..be5c5c61ac 100644 --- a/src/libslic3r/Format/PRUS.hpp +++ b/src/libslic3r/Format/PRUS.hpp @@ -1,4 +1,3 @@ -#if defined(SLIC3R_PRUS) && ! defined(slic3r_Format_PRUS_hpp_) #define slic3r_Format_PRUS_hpp_ namespace Slic3r { @@ -10,5 +9,3 @@ class Model; extern bool load_prus(const char *path, Model *model); }; // namespace Slic3r - -#endif /* SLIC3R_PRUS && ! defined(slic3r_Format_PRUS_hpp_) */ diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index ae74ab18e3..1128e57fc1 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -62,10 +62,8 @@ Model Model::read_from_file(const std::string &input_file, DynamicPrintConfig *c result = load_amf(input_file.c_str(), config, &model); else if (boost::algorithm::iends_with(input_file, ".3mf")) result = load_3mf(input_file.c_str(), config, &model); -#ifdef SLIC3R_PRUS else if (boost::algorithm::iends_with(input_file, ".prusa")) result = load_prus(input_file.c_str(), &model); -#endif /* SLIC3R_PRUS */ else throw std::runtime_error("Unknown file format. Input file must have .stl, .obj, .amf(.xml) or .prusa extension."); diff --git a/src/libslic3r/TriangleMesh.cpp b/src/libslic3r/TriangleMesh.cpp index 4bf13330f6..c56b66de32 100644 --- a/src/libslic3r/TriangleMesh.cpp +++ b/src/libslic3r/TriangleMesh.cpp @@ -134,25 +134,31 @@ void TriangleMesh::repair() // remove_unconnected if (stl.stats.connected_facets_3_edge < stl.stats.number_of_facets) { + BOOST_LOG_TRIVIAL(trace) << "\tstl_remove_unconnected_facets"; stl_remove_unconnected_facets(&stl); } // fill_holes if (stl.stats.connected_facets_3_edge < stl.stats.number_of_facets) { + BOOST_LOG_TRIVIAL(trace) << "\tstl_fill_holes"; stl_fill_holes(&stl); stl_clear_error(&stl); } // normal_directions + BOOST_LOG_TRIVIAL(trace) << "\tstl_fix_normal_directions"; stl_fix_normal_directions(&stl); // normal_values + BOOST_LOG_TRIVIAL(trace) << "\tstl_fix_normal_values"; stl_fix_normal_values(&stl); // always calculate the volume and reverse all normals if volume is negative + BOOST_LOG_TRIVIAL(trace) << "\tstl_calculate_volume"; stl_calculate_volume(&stl); // neighbors + BOOST_LOG_TRIVIAL(trace) << "\tstl_verify_neighbors"; stl_verify_neighbors(&stl); this->repaired = true; diff --git a/src/libslic3r/Utils.hpp b/src/libslic3r/Utils.hpp index 8feb177479..863ca6b2fd 100644 --- a/src/libslic3r/Utils.hpp +++ b/src/libslic3r/Utils.hpp @@ -117,10 +117,10 @@ inline uint64_t next_highest_power_of_2(uint64_t v) inline size_t next_highest_power_of_2(size_t v) { #if SSIZE_MAX == 9223372036854775807 - static_assert(sizeof(size_t) == sizeof(uint64_t)); + static_assert(sizeof(size_t) == sizeof(uint64_t), "sizeof(size_t) == sizeof(uint64_t)"); return next_highest_power_of_2(uint64_t(v)); #else - static_assert(sizeof(size_t) == sizeof(uint32_t)); + static_assert(sizeof(size_t) == sizeof(uint32_t), "sizeof(size_t) == sizeof(uint32_t)"); return next_highest_power_of_2(uint32_t(v)); #endif } From 4cee4f0e0ec5dbd4fc0d0a056b5949b479f6284d Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Tue, 25 Sep 2018 15:54:39 +0200 Subject: [PATCH 042/186] changing defaultly downloaded nlopt version to 2.5.0 --- src/libnest2d/cmake_modules/DownloadNLopt.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libnest2d/cmake_modules/DownloadNLopt.cmake b/src/libnest2d/cmake_modules/DownloadNLopt.cmake index 0f5392596e..65b1866dbe 100644 --- a/src/libnest2d/cmake_modules/DownloadNLopt.cmake +++ b/src/libnest2d/cmake_modules/DownloadNLopt.cmake @@ -10,7 +10,7 @@ endif() include(DownloadProject) download_project( PROJ nlopt GIT_REPOSITORY https://github.com/stevengj/nlopt.git - GIT_TAG 1fcbcbf2fe8e34234e016cc43a6c41d3e8453e1f #master #nlopt-2.4.2 + GIT_TAG v2.5.0 #1fcbcbf2fe8e34234e016cc43a6c41d3e8453e1f #master #nlopt-2.4.2 # CMAKE_CACHE_ARGS -DBUILD_SHARED_LIBS:BOOL=OFF -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX=${NLopt_DIR} ${UPDATE_DISCONNECTED_IF_AVAILABLE} ) From 47b2d363f058c326eb3f7c4aa4ef0405d808d97a Mon Sep 17 00:00:00 2001 From: bubnikv Date: Tue, 25 Sep 2018 16:05:26 +0200 Subject: [PATCH 043/186] Fixed a regression bug in admesh: bad hashing. Also the hash table size for admesh was made adaptive based on the number of faces. --- src/admesh/connect.cpp | 34 +++++++++++++++++++++++----------- src/admesh/stl.h | 4 ++-- src/libslic3r/TriangleMesh.cpp | 8 +++++--- 3 files changed, 30 insertions(+), 16 deletions(-) diff --git a/src/admesh/connect.cpp b/src/admesh/connect.cpp index da5b667209..166eec3302 100644 --- a/src/admesh/connect.cpp +++ b/src/admesh/connect.cpp @@ -25,6 +25,9 @@ #include #include +#include +#include + #include #include "stl.h" @@ -125,11 +128,11 @@ stl_load_edge_exact(stl_file *stl, stl_hash_edge *edge, std::swap(a, b); edge->which_edge += 3; /* this edge is loaded backwards */ } - memcpy(&edge->key[0], a->data(), sizeof(stl_vertex)); - memcpy(&edge->key[sizeof(stl_vertex)], b->data(), sizeof(stl_vertex)); + memcpy(&edge->key[0], a->data(), sizeof(stl_vertex)); + memcpy(&edge->key[3], b->data(), sizeof(stl_vertex)); // Switch negative zeros to positive zeros, so memcmp will consider them to be equal. for (size_t i = 0; i < 6; ++ i) { - unsigned char *p = edge->key + i * 4; + unsigned char *p = (unsigned char*)(edge->key + i); #ifdef BOOST_LITTLE_ENDIAN if (p[0] == 0 && p[1] == 0 && p[2] == 0 && p[3] == 0x80) // Negative zero, switch to positive zero. @@ -142,6 +145,16 @@ stl_load_edge_exact(stl_file *stl, stl_hash_edge *edge, } } +static inline size_t hash_size_from_nr_faces(const size_t nr_faces) +{ + // Good primes for addressing a cca. 30 bit space. + // https://planetmath.org/goodhashtableprimes + static std::vector primes{ 98317, 196613, 393241, 786433, 1572869, 3145739, 6291469, 12582917, 25165843, 50331653, 100663319, 201326611, 402653189, 805306457, 1610612741 }; + // Find a prime number for 50% filling of the shared triangle edges in the mesh. + auto it = std::upper_bound(primes.begin(), primes.end(), nr_faces * 3 * 2 - 1); + return (it == primes.end()) ? primes.back() : *it; +} + static void stl_initialize_facet_check_exact(stl_file *stl) { int i; @@ -152,10 +165,9 @@ stl_initialize_facet_check_exact(stl_file *stl) { stl->stats.freed = 0; stl->stats.collisions = 0; + stl->M = hash_size_from_nr_faces(stl->stats.number_of_facets); - stl->M = 81397; - - for(i = 0; i < stl->stats.number_of_facets ; i++) { + for (i = 0; i < stl->stats.number_of_facets ; i++) { /* initialize neighbors list to -1 to mark unconnected edges */ stl->neighbors_start[i].neighbor[0] = -1; stl->neighbors_start[i].neighbor[1] = -1; @@ -296,11 +308,11 @@ static int stl_load_edge_nearby(stl_file *stl, stl_hash_edge *edge, stl_vertex * ((vertex1[1] != vertex2[1]) ? (vertex1[1] < vertex2[1]) : (vertex1[2] < vertex2[2]))) { - memcpy(&edge->key[0], vertex1.data(), sizeof(stl_vertex)); - memcpy(&edge->key[sizeof(stl_vertex)], vertex2.data(), sizeof(stl_vertex)); + memcpy(&edge->key[0], vertex1.data(), sizeof(stl_vertex)); + memcpy(&edge->key[3], vertex2.data(), sizeof(stl_vertex)); } else { - memcpy(&edge->key[0], vertex2.data(), sizeof(stl_vertex)); - memcpy(&edge->key[sizeof(stl_vertex)], vertex1.data(), sizeof(stl_vertex)); + memcpy(&edge->key[0], vertex2.data(), sizeof(stl_vertex)); + memcpy(&edge->key[3], vertex1.data(), sizeof(stl_vertex)); edge->which_edge += 3; /* this edge is loaded backwards */ } return 1; @@ -338,7 +350,7 @@ static void stl_initialize_facet_check_nearby(stl_file *stl) /* tolerance = STL_MAX((stl->stats.bounding_diameter / 500000.0), tolerance);*/ /* tolerance *= 0.5;*/ - stl->M = 81397; + stl->M = hash_size_from_nr_faces(stl->stats.number_of_facets); stl->heads = (stl_hash_edge**)calloc(stl->M, sizeof(*stl->heads)); if(stl->heads == NULL) perror("stl_initialize_facet_check_nearby"); diff --git a/src/admesh/stl.h b/src/admesh/stl.h index 096430d150..9898f3e643 100644 --- a/src/admesh/stl.h +++ b/src/admesh/stl.h @@ -65,11 +65,11 @@ typedef struct { typedef struct stl_hash_edge { // Key of a hash edge: sorted vertices of the edge. - unsigned char key[2 * sizeof(stl_vertex)]; + uint32_t key[6]; // Compare two keys. bool operator==(const stl_hash_edge &rhs) { return memcmp(key, rhs.key, sizeof(key)) == 0; } bool operator!=(const stl_hash_edge &rhs) { return ! (*this == rhs); } - int hash(int M) const { return ((key[0] / 23 + key[1] / 19 + key[2] / 17 + key[3] /13 + key[4] / 11 + key[5] / 7 ) % M); } + int hash(int M) const { return ((key[0] / 11 + key[1] / 7 + key[2] / 3) ^ (key[3] / 11 + key[4] / 7 + key[5] / 3)) % M; } // Index of a facet owning this edge. int facet_number; // Index of this edge inside the facet with an index of facet_number. diff --git a/src/libslic3r/TriangleMesh.cpp b/src/libslic3r/TriangleMesh.cpp index c56b66de32..665351c393 100644 --- a/src/libslic3r/TriangleMesh.cpp +++ b/src/libslic3r/TriangleMesh.cpp @@ -108,21 +108,23 @@ void TriangleMesh::repair() BOOST_LOG_TRIVIAL(debug) << "TriangleMesh::repair() started"; // checking exact - stl_check_facets_exact(&stl); + BOOST_LOG_TRIVIAL(trace) << "\tstl_check_faces_exact"; + stl_check_facets_exact(&stl); stl.stats.facets_w_1_bad_edge = (stl.stats.connected_facets_2_edge - stl.stats.connected_facets_3_edge); stl.stats.facets_w_2_bad_edge = (stl.stats.connected_facets_1_edge - stl.stats.connected_facets_2_edge); stl.stats.facets_w_3_bad_edge = (stl.stats.number_of_facets - stl.stats.connected_facets_1_edge); // checking nearby //int last_edges_fixed = 0; - float tolerance = stl.stats.shortest_edge; + float tolerance = stl.stats.shortest_edge; float increment = stl.stats.bounding_diameter / 10000.0; int iterations = 2; if (stl.stats.connected_facets_3_edge < stl.stats.number_of_facets) { for (int i = 0; i < iterations; i++) { if (stl.stats.connected_facets_3_edge < stl.stats.number_of_facets) { //printf("Checking nearby. Tolerance= %f Iteration=%d of %d...", tolerance, i + 1, iterations); - stl_check_facets_nearby(&stl, tolerance); + BOOST_LOG_TRIVIAL(trace) << "\tstl_check_faces_nearby"; + stl_check_facets_nearby(&stl, tolerance); //printf(" Fixed %d edges.\n", stl.stats.edges_fixed - last_edges_fixed); //last_edges_fixed = stl.stats.edges_fixed; tolerance += increment; From 722fdd7cd57977124331b4fde4fd234e9c48c8e0 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Tue, 25 Sep 2018 16:22:28 +0200 Subject: [PATCH 044/186] Fixed CLI --dont-arrange command --- src/libslic3r/PrintConfig.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 05b1b4bb58..46df2b1c08 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -2617,6 +2617,7 @@ CLIConfigDef::CLIConfigDef() def->tooltip = L("Don't arrange the objects on the build plate. The model coordinates " "define the absolute positions on the build plate. " "The option --center will be ignored."); + def->cli = "dont-arrange"; def->default_value = new ConfigOptionBool(false); def = this->add("datadir", coString); From 1f4c758e7107c93e8571b45449bdd70eab290689 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Tue, 25 Sep 2018 16:57:18 +0200 Subject: [PATCH 045/186] Logging of G-code processing --- src/libslic3r/GCode.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index d10705c183..0acbdd1230 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -455,9 +455,12 @@ void GCode::do_export(Print *print, const char *path, GCodePreviewData *preview_ fclose(file); if (print->config().remaining_times.value) { + BOOST_LOG_TRIVIAL(debug) << "Processing remaining times for normal mode"; m_normal_time_estimator.post_process_remaining_times(path_tmp, 60.0f); - if (m_silent_time_estimator_enabled) + if (m_silent_time_estimator_enabled) { + BOOST_LOG_TRIVIAL(debug) << "Processing remaining times for silent mode"; m_silent_time_estimator.post_process_remaining_times(path_tmp, 60.0f); + } } if (! m_placeholder_parser_failed_templates.empty()) { @@ -1033,9 +1036,11 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data) } print.throw_if_canceled(); - // starts analizer calculations - if (preview_data != nullptr) + // starts analyzer calculations + if (preview_data != nullptr) { + BOOST_LOG_TRIVIAL(debug) << "Preparing G-code preview data"; m_analyzer.calc_gcode_preview_data(*preview_data); + } } std::string GCode::placeholder_parser_process(const std::string &name, const std::string &templ, unsigned int current_extruder_id, const DynamicConfig *config_override) From 746d06fe3eb4604272e648645f6610f00ef277e8 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Thu, 27 Sep 2018 13:47:35 +0200 Subject: [PATCH 046/186] Removed SLIC3R_PRUSACONTROL switch from CMake --- CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ac2e642228..6f4e89283b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,7 +21,6 @@ endif() option(SLIC3R_STATIC "Compile Slic3r with static libraries (Boost, TBB, glew)" ${SLIC3R_STATIC_INITIAL}) option(SLIC3R_GUI "Compile Slic3r with GUI components (OpenGL, wxWidgets)" 1) -option(SLIC3R_PRUSACONTROL "Compile Slic3r with the PrusaControl prject file format (requires wxWidgets base library)" 1) option(SLIC3R_PROFILE "Compile Slic3r with an invasive Shiny profiler" 0) option(SLIC3R_MSVC_COMPILE_PARALLEL "Compile on Visual Studio in parallel" 1) option(SLIC3R_MSVC_PDB "Generate PDB files on MSVC in Release mode" 1) From 342b584399cb14d648599bd7e950ac87bff6f9b1 Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Mon, 17 Sep 2018 12:15:11 +0200 Subject: [PATCH 047/186] WIP: Plater --- doc/deps-build/unix-static/Makefile | 31 +- lib/Slic3r/GUI/Plater.pm | 9 +- src/libslic3r/Model.hpp | 3 +- src/libslic3r/Point.hpp | 5 + src/slic3r/CMakeLists.txt | 2 + src/slic3r/GUI/GLCanvas3D.cpp | 36 +- src/slic3r/GUI/GLCanvas3D.hpp | 11 +- src/slic3r/GUI/GLToolbar.cpp | 20 +- src/slic3r/GUI/GLToolbar.hpp | 23 +- src/slic3r/GUI/GUI_App.cpp | 2 +- src/slic3r/GUI/GUI_App.hpp | 2 +- src/slic3r/GUI/MainFrame.cpp | 19 +- src/slic3r/GUI/MainFrame.hpp | 7 +- src/slic3r/GUI/Plater.cpp | 908 ++++++++++++++++++++++++++++ src/slic3r/GUI/Plater.hpp | 60 ++ src/slic3r/GUI/Preset.hpp | 2 +- src/slic3r/GUI/PresetBundle.hpp | 5 + src/slic3r/GUI/callback.hpp | 2 +- 18 files changed, 1104 insertions(+), 43 deletions(-) create mode 100644 src/slic3r/GUI/Plater.cpp create mode 100644 src/slic3r/GUI/Plater.hpp diff --git a/doc/deps-build/unix-static/Makefile b/doc/deps-build/unix-static/Makefile index 21740bc532..90d5083bba 100644 --- a/doc/deps-build/unix-static/Makefile +++ b/doc/deps-build/unix-static/Makefile @@ -26,10 +26,11 @@ TBB_SHA = a0dc9bf76d0120f917b641ed095360448cabc85b TBB = tbb-$(TBB_SHA) OPENSSL = openssl-OpenSSL_1_1_0g CURL = curl-7.58.0 +WXWIDGETS = wxWidgets-3.1.1 .PHONY: all destdir boost libcurl libopenssl libtbb -all: destdir boost libtbb libcurl +all: destdir boost libtbb libcurl wxwidgets @echo @echo "All done!" @echo @@ -131,5 +132,33 @@ $(CURL).tar.gz: curl -L -o $@ https://curl.haxx.se/download/$@ + +wxwidgets: $(WXWIDGETS).tar.bz2 + # tar -jxvf $(WXWIDGETS).tar.bz2 + cd $(WXWIDGETS) && ./configure \ + --prefix=$(DESTDIR)/usr/local \ + --disable-shared \ + --with-gtk=2 \ + --with-opengl \ + --enable-unicode \ + --enable-graphics_ctx \ + --with-regex=builtin \ + --with-libpng=builtin \ + --with-libxpm=builtin \ + --with-libjpeg=builtin \ + --with-libtiff=builtin \ + --with-zlib=builtin \ + --with-expat=builtin \ + --disable-precomp-headers \ + --enable-debug_info \ + --enable-debug_gdb + $(MAKE) -C $(WXWIDGETS) -j$(NPROC) + $(MAKE) -C $(WXWIDGETS)/locale allmo # XXX: ? + $(MAKE) -C $(WXWIDGETS) install #DESTDIR=$(DESTDIR) + +$(WXWIDGETS).tar.bz2: + curl -L -o $@ https://github.com/wxWidgets/wxWidgets/releases/download/v3.1.1/$@ + + clean: rm -rf $(BOOST) $(BOOST).tar.gz $(TBB) $(TBB).tar.gz $(OPENSSL) $(OPENSSL).tar.gz $(CURL) $(CURL).tar.gz diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index c7d4260d26..b834bc202a 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -593,6 +593,7 @@ sub new { $self->on_process_completed($event->GetInt ? undef : $event->GetString); }); +# XXX: ??? { my $timer_id = Wx::NewId(); $self->{apply_config_timer} = Wx::Timer->new($self, $timer_id); @@ -872,7 +873,7 @@ sub on_layer_editing_toggled { $self->{canvas3D}->Update; } -sub GetFrame { +sub GetFrame { # XXX: main_frame in C++ Plater my ($self) = @_; return &Wx::GetTopLevelParent($self); } @@ -960,7 +961,7 @@ sub load_files { # Object indices for the UI. my @obj_idx = (); # Collected file names to display the final message on the status bar. - my @loaded_files = (); + my @loaded_files = (); # XXX: used??? # For all input files. for (my $i = 0; $i < @$input_files; $i += 1) { my $input_file = $input_files->[$i]; @@ -996,7 +997,7 @@ sub load_files { # objects imported from 3mf require a call to center_around_origin to have gizmos working properly and this call # need to be done after looks_like_multipart_object detection - if ($input_file =~ /.3[mM][fF]$/) + if ($input_file =~ /[.]3[mM][fF]$/) { foreach my $model_object (@{$model->objects}) { $model_object->center_around_origin; # also aligns object to Z = 0 @@ -1241,7 +1242,7 @@ sub set_number_of_copies { } } -sub _get_number_from_user { +sub _get_number_from_user { # XXX: Enrico my ($self, $title, $prompt_message, $error_message, $default, $only_positive) = @_; for (;;) { my $value = Wx::GetTextFromUser($prompt_message, $title, $default, $self); diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index dc7de94b18..e2405fc83f 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -61,7 +61,7 @@ class ModelObject friend class Model; public: std::string name; - std::string input_file; + std::string input_file; // XXX: consider fs::path // Instances of this ModelObject. Each instance defines a shift on the print bed, rotation around the Z axis and a uniform scaling. // Instances are owned by this ModelObject. ModelInstancePtrs instances; @@ -336,6 +336,7 @@ public: void swap(Model &other); ~Model() { this->clear_objects(); this->clear_materials(); } + // XXX: use fs::path ? static Model read_from_file(const std::string &input_file, DynamicPrintConfig *config = nullptr, bool add_default_instances = true); static Model read_from_archive(const std::string &input_file, DynamicPrintConfig *config, bool add_default_instances = true); diff --git a/src/libslic3r/Point.hpp b/src/libslic3r/Point.hpp index 6d9d82d25a..87cdc3777f 100644 --- a/src/libslic3r/Point.hpp +++ b/src/libslic3r/Point.hpp @@ -56,6 +56,11 @@ inline Vec2i64 to_2d(const Vec3i64 &pt3) { return Vec2i64(pt3(0), pt3(1)); } inline Vec2f to_2d(const Vec3f &pt3) { return Vec2f (pt3(0), pt3(1)); } inline Vec2d to_2d(const Vec3d &pt3) { return Vec2d (pt3(0), pt3(1)); } +// inline Vec3crd to_3d(const Vec2crd &pt2, coord_t z) { return Vec3crd(pt2(0), pt2(1), z); } +// inline Vec3i64 to_3d(const Vec2i64 &pt2, int64_t z) { return Vec3i64(pt2(0), pt2(1), z); } +// inline Vec3f to_3d(const Vec2f &pt2, float z) { return Vec3f (pt2(0), pt2(1), z); } +// inline Vec3d to_3d(const Vec2d &pt2, double z) { return Vec3d (pt2(0), pt2(1), z); } + inline Vec2d unscale(coord_t x, coord_t y) { return Vec2d(unscale(x), unscale(y)); } inline Vec2d unscale(const Vec2crd &pt) { return Vec2d(unscale(pt(0)), unscale(pt(1))); } inline Vec2d unscale(const Vec2d &pt) { return Vec2d(unscale(pt(0)), unscale(pt(1))); } diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt index a8888701c3..06fb79a503 100644 --- a/src/slic3r/CMakeLists.txt +++ b/src/slic3r/CMakeLists.txt @@ -43,6 +43,8 @@ add_library(libslic3r_gui STATIC ${LIBDIR}/slic3r/GUI/GUI_App.hpp ${LIBDIR}/slic3r/GUI/MainFrame.cpp ${LIBDIR}/slic3r/GUI/MainFrame.hpp + ${LIBDIR}/slic3r/GUI/Plater.cpp + ${LIBDIR}/slic3r/GUI/Plater.hpp ${LIBDIR}/slic3r/GUI/LambdaObjectDialog.cpp ${LIBDIR}/slic3r/GUI/LambdaObjectDialog.hpp ${LIBDIR}/slic3r/GUI/Tab.cpp diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 16477a884a..5e4e71881e 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -2876,10 +2876,13 @@ void GLCanvas3D::register_on_update_geometry_info_callback(void* callback) } #endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM +// void GLCanvas3D::register_action_add_callback(GLToolbarItem::Callback callback) void GLCanvas3D::register_action_add_callback(void* callback) { if (callback != nullptr) m_action_add_callback.register_callback(callback); + // if (callback) + // m_action_add_callback = std::move(callback); } void GLCanvas3D::register_action_delete_callback(void* callback) @@ -3729,7 +3732,8 @@ bool GLCanvas3D::_init_toolbar() item.tooltip = GUI::L_str("Add..."); item.sprite_id = 0; item.is_toggable = false; - item.action_callback = &m_action_add_callback; + // item.action_callback = &m_action_add_callback; + item.action_event = EVT_GLTOOLBAR_ADD; if (!m_toolbar.add_item(item)) return false; @@ -3737,7 +3741,8 @@ bool GLCanvas3D::_init_toolbar() item.tooltip = GUI::L_str("Delete"); item.sprite_id = 1; item.is_toggable = false; - item.action_callback = &m_action_delete_callback; + // item.action_callback = &m_action_delete_callback; + item.action_event = EVT_GLTOOLBAR_DELETE; if (!m_toolbar.add_item(item)) return false; @@ -3745,7 +3750,8 @@ bool GLCanvas3D::_init_toolbar() item.tooltip = GUI::L_str("Delete all"); item.sprite_id = 2; item.is_toggable = false; - item.action_callback = &m_action_deleteall_callback; + // item.action_callback = &m_action_deleteall_callback; + item.action_event = EVT_GLTOOLBAR_TODO_MORE; if (!m_toolbar.add_item(item)) return false; @@ -3753,7 +3759,8 @@ bool GLCanvas3D::_init_toolbar() item.tooltip = GUI::L_str("Arrange"); item.sprite_id = 3; item.is_toggable = false; - item.action_callback = &m_action_arrange_callback; + // item.action_callback = &m_action_arrange_callback; + item.action_event = EVT_GLTOOLBAR_TODO_MORE; if (!m_toolbar.add_item(item)) return false; @@ -3764,7 +3771,8 @@ bool GLCanvas3D::_init_toolbar() item.tooltip = GUI::L_str("Add instance"); item.sprite_id = 4; item.is_toggable = false; - item.action_callback = &m_action_more_callback; + // item.action_callback = &m_action_more_callback; + item.action_event = EVT_GLTOOLBAR_TODO_MORE; if (!m_toolbar.add_item(item)) return false; @@ -3772,7 +3780,8 @@ bool GLCanvas3D::_init_toolbar() item.tooltip = GUI::L_str("Remove instance"); item.sprite_id = 5; item.is_toggable = false; - item.action_callback = &m_action_fewer_callback; + // item.action_callback = &m_action_fewer_callback; + item.action_event = EVT_GLTOOLBAR_TODO_MORE; if (!m_toolbar.add_item(item)) return false; @@ -3783,7 +3792,8 @@ bool GLCanvas3D::_init_toolbar() item.tooltip = GUI::L_str("Split"); item.sprite_id = 6; item.is_toggable = false; - item.action_callback = &m_action_split_callback; + // item.action_callback = &m_action_split_callback; + item.action_event = EVT_GLTOOLBAR_TODO_MORE; if (!m_toolbar.add_item(item)) return false; @@ -3791,7 +3801,8 @@ bool GLCanvas3D::_init_toolbar() item.tooltip = GUI::L_str("Cut..."); item.sprite_id = 7; item.is_toggable = false; - item.action_callback = &m_action_cut_callback; + // item.action_callback = &m_action_cut_callback; + item.action_event = EVT_GLTOOLBAR_TODO_MORE; if (!m_toolbar.add_item(item)) return false; @@ -3802,7 +3813,8 @@ bool GLCanvas3D::_init_toolbar() item.tooltip = GUI::L_str("Settings..."); item.sprite_id = 8; item.is_toggable = false; - item.action_callback = &m_action_settings_callback; + // item.action_callback = &m_action_settings_callback; + item.action_event = EVT_GLTOOLBAR_TODO_MORE; if (!m_toolbar.add_item(item)) return false; @@ -3810,7 +3822,8 @@ bool GLCanvas3D::_init_toolbar() item.tooltip = GUI::L_str("Layers editing"); item.sprite_id = 9; item.is_toggable = true; - item.action_callback = &m_action_layersediting_callback; + // item.action_callback = &m_action_layersediting_callback; + item.action_event = EVT_GLTOOLBAR_TODO_MORE; if (!m_toolbar.add_item(item)) return false; @@ -3821,7 +3834,8 @@ bool GLCanvas3D::_init_toolbar() item.tooltip = GUI::L_str("Select by parts"); item.sprite_id = 10; item.is_toggable = true; - item.action_callback = &m_action_selectbyparts_callback; + // item.action_callback = &m_action_selectbyparts_callback; + item.action_event = EVT_GLTOOLBAR_TODO_MORE; if (!m_toolbar.add_item(item)) return false; diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 4511901611..7c0a7fe2e2 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -1,8 +1,11 @@ #ifndef slic3r_GLCanvas3D_hpp_ #define slic3r_GLCanvas3D_hpp_ -#include "../../slic3r/GUI/3DScene.hpp" -#include "../../slic3r/GUI/GLToolbar.hpp" +#include + +#include "3DScene.hpp" +#include "GLToolbar.hpp" +#include "callback.hpp" class wxTimer; class wxSizeEvent; @@ -529,6 +532,7 @@ class GLCanvas3D PerlCallback m_on_update_geometry_info_callback; #endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM + // TODO: Remove these PerlCallback m_action_add_callback; PerlCallback m_action_delete_callback; PerlCallback m_action_deleteall_callback; @@ -545,6 +549,8 @@ public: GLCanvas3D(wxGLCanvas* canvas); ~GLCanvas3D(); + wxGLCanvas* widget() { return m_canvas; } + bool init(bool useVBOs, bool use_legacy_opengl); bool set_current(); @@ -661,6 +667,7 @@ public: void register_on_update_geometry_info_callback(void* callback); #endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM + // void register_action_add_callback(GLToolbarItem::Callback); void register_action_add_callback(void* callback); void register_action_delete_callback(void* callback); void register_action_deleteall_callback(void* callback); diff --git a/src/slic3r/GUI/GLToolbar.cpp b/src/slic3r/GUI/GLToolbar.cpp index 388868b12f..196dc663f2 100644 --- a/src/slic3r/GUI/GLToolbar.cpp +++ b/src/slic3r/GUI/GLToolbar.cpp @@ -6,19 +6,25 @@ #include +#include #include #include #include +#include namespace Slic3r { namespace GUI { + +wxDEFINE_EVENT(EVT_GLTOOLBAR_ADD, wxCommandEvent); +wxDEFINE_EVENT(EVT_GLTOOLBAR_DELETE, wxCommandEvent); +wxDEFINE_EVENT(EVT_GLTOOLBAR_TODO_MORE, wxCommandEvent); + GLToolbarItem::Data::Data() : name("") , tooltip("") , sprite_id(-1) , is_toggable(false) - , action_callback(nullptr) { } @@ -49,10 +55,12 @@ const std::string& GLToolbarItem::get_tooltip() const return m_data.tooltip; } -void GLToolbarItem::do_action() +void GLToolbarItem::do_action(wxEvtHandler *target) { - if (m_data.action_callback != nullptr) - m_data.action_callback->call(); + // if (m_data.action_callback != nullptr) + // m_data.action_callback->call(); + + wxPostEvent(target, wxCommandEvent(m_data.action_event)); } bool GLToolbarItem::is_enabled() const @@ -325,13 +333,13 @@ void GLToolbar::do_action(unsigned int item_id) item->set_state(GLToolbarItem::Hover); m_parent.render(); - item->do_action(); + item->do_action(m_parent.widget()); } else { item->set_state(GLToolbarItem::HoverPressed); m_parent.render(); - item->do_action(); + item->do_action(m_parent.widget()); if (item->get_state() != GLToolbarItem::Disabled) { // the item may get disabled during the action, if not, set it back to hover state diff --git a/src/slic3r/GUI/GLToolbar.hpp b/src/slic3r/GUI/GLToolbar.hpp index c67e78f58c..45d22e785a 100644 --- a/src/slic3r/GUI/GLToolbar.hpp +++ b/src/slic3r/GUI/GLToolbar.hpp @@ -1,17 +1,26 @@ #ifndef slic3r_GLToolbar_hpp_ #define slic3r_GLToolbar_hpp_ -#include "../../slic3r/GUI/GLTexture.hpp" -#include "callback.hpp" - +#include #include #include +#include + +#include "../../slic3r/GUI/GLTexture.hpp" +// #include "callback.hpp" + +class wxEvtHandler; + namespace Slic3r { namespace GUI { class GLCanvas3D; +wxDECLARE_EVENT(EVT_GLTOOLBAR_ADD, wxCommandEvent); +wxDECLARE_EVENT(EVT_GLTOOLBAR_DELETE, wxCommandEvent); +wxDECLARE_EVENT(EVT_GLTOOLBAR_TODO_MORE, wxCommandEvent); + class GLToolbarItem { public: @@ -32,13 +41,17 @@ public: Num_States }; + // typedef std::function Callback; + // typedef PerlCallback Callback; + struct Data { std::string name; std::string tooltip; unsigned int sprite_id; bool is_toggable; - PerlCallback* action_callback; + // Callback *action_callback; + wxEventType action_event; Data(); }; @@ -57,7 +70,7 @@ public: const std::string& get_name() const; const std::string& get_tooltip() const; - void do_action(); + void do_action(wxEvtHandler *target); bool is_enabled() const; bool is_hovered() const; diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 17f3b53b2d..6aeea4a74b 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -48,7 +48,7 @@ bool GUI_App::OnInit() app_config = new AppConfig(); // set_app_config(app_config);// #ys_FIXME preset_bundle = new PresetBundle(); - // set_preset_bundle(preset_bundle);// #ys_FIXME + set_preset_bundle(preset_bundle); // #ys_FIXME // just checking for existence of Slic3r::data_dir is not enough : it may be an empty directory // supplied as argument to --datadir; in that case we should still run the wizard diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 91a7b2742f..99c3d2c1ef 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -42,7 +42,7 @@ class Tab; class GUI_App : public wxApp { - bool no_plater{ true }; + bool no_plater{ false }; bool app_conf_exists{ false }; // Lock to guard the callback stack diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 6aefb93851..ee90cf297f 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -118,6 +118,10 @@ void MainFrame::init_tabpanel() auto panel = m_tabpanel->GetCurrentPage(); // panel->OnActivate(); if panel->can('OnActivate'); + if (panel == nullptr) { + return; + } + for (auto& tab_name : { "print", "filament", "printer" }) { if (tab_name == panel->GetName()) { // On GTK, the wxEVT_NOTEBOOK_PAGE_CHANGED event is triggered @@ -131,13 +135,14 @@ void MainFrame::init_tabpanel() }); if (!m_no_plater) { -// m_plater = new Slic3r::GUI::Plater(m_tabpanel, -// event_object_selection_changed = > $OBJECT_SELECTION_CHANGED_EVENT, -// event_object_settings_changed = > $OBJECT_SETTINGS_CHANGED_EVENT, -// event_remove_object = > $OBJECT_REMOVE_EVENT, -// event_update_scene = > $UPDATE_SCENE_EVENT, -// ), L("Plater") -// m_tabpanel->AddPage(plater); + m_plater = new Slic3r::GUI::Plater(m_tabpanel, this); + // m_plater = new Slic3r::GUI::Plater(m_tabpanel, + // event_object_selection_changed = > $OBJECT_SELECTION_CHANGED_EVENT, + // event_object_settings_changed = > $OBJECT_SETTINGS_CHANGED_EVENT, + // event_remove_object = > $OBJECT_REMOVE_EVENT, + // event_update_scene = > $UPDATE_SCENE_EVENT, + // ), L("Plater") + m_tabpanel->AddPage(m_plater, _(L("Plater"))); } // The following event is emited by the C++ Tab implementation on config value change. diff --git a/src/slic3r/GUI/MainFrame.hpp b/src/slic3r/GUI/MainFrame.hpp index aff8a59859..f4c75de659 100644 --- a/src/slic3r/GUI/MainFrame.hpp +++ b/src/slic3r/GUI/MainFrame.hpp @@ -8,6 +8,8 @@ #include #include +#include "Plater.hpp" + class wxMenuBar; class wxNotebook; class wxPanel; @@ -45,7 +47,6 @@ class MainFrame : public wxFrame wxString m_qs_last_output_file = wxEmptyString; wxString m_last_config = wxEmptyString; - ProgressStatusBar* m_statusbar { nullptr }; AppController* m_appController { nullptr }; std::map m_options_tabs; @@ -70,6 +71,7 @@ public: void init_tabpanel(); + const std::map& options_tabs() const { return m_options_tabs; } Tab* get_preset_tab(const std::string& name); void create_preset_tabs(); void add_created_tab(Tab* panel); @@ -93,9 +95,10 @@ public: void select_view(const std::string& direction); - wxPanel* m_plater {nullptr}; + Plater* m_plater { nullptr }; wxNotebook* m_tabpanel { nullptr }; wxProgressDialog* m_progress_dialog { nullptr }; + ProgressStatusBar* m_statusbar { nullptr }; }; } // GUI diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp new file mode 100644 index 0000000000..e48ae031b4 --- /dev/null +++ b/src/slic3r/GUI/Plater.cpp @@ -0,0 +1,908 @@ +#include "Plater.hpp" + +#include // XXX +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "libslic3r/PrintConfig.hpp" +#include "libslic3r/Model.hpp" +#include "libslic3r/Print.hpp" +#include "libslic3r/GCode/PreviewData.hpp" +#include "libslic3r/Utils.hpp" +#include "libslic3r/Polygon.hpp" +// #include "libslic3r/BoundingBox.hpp" +#include "GUI.hpp" +#include "GUI_App.hpp" +#include "MainFrame.hpp" +#include "3DScene.hpp" +#include "GLToolbar.hpp" +#include "GUI_Preview.hpp" +#include "Tab.hpp" +#include "PresetBundle.hpp" +#include "BackgroundSlicingProcess.hpp" +#include "ProgressStatusBar.hpp" +#include "slic3r/Utils/ASCIIFolding.hpp" + +#include // Needs to be last because reasons :-/ + +namespace fs = boost::filesystem; +using Slic3r::_3DScene; +using Slic3r::Preset; + + +namespace Slic3r { +namespace GUI { + + +wxDEFINE_EVENT(EVT_SLICING_COMPLETED, wxCommandEvent); +wxDEFINE_EVENT(EVT_PROCESS_COMPLETED, wxCommandEvent); + + +// Sidebar widgets + +// struct InfoBox : public wxStaticBox +// { +// InfoBox(wxWindow *parent, const wxString &label) : +// wxStaticBox(parent, wxID_ANY, label) +// { +// SetFont(GUI::small_font().Bold()); +// } +// }; + +class ObjectInfo : public wxStaticBoxSizer +{ +public: + ObjectInfo(wxWindow *parent); + +private: + wxStaticText *info_size; + wxStaticText *info_volume; + wxStaticText *info_facets; + wxStaticText *info_materials; + wxStaticText *info_manifold; + wxStaticBitmap *manifold_warning_icon; +}; + +ObjectInfo::ObjectInfo(wxWindow *parent) : + wxStaticBoxSizer(new wxStaticBox(parent, wxID_ANY, _(L("Info"))), wxVERTICAL) +{ + // GetStaticBox()->SetFont(GUI::bold_font()); // XXX: ? + + auto *grid_sizer = new wxFlexGridSizer(4, 5, 5); + grid_sizer->SetFlexibleDirection(wxHORIZONTAL); + grid_sizer->AddGrowableCol(1, 1); + grid_sizer->AddGrowableCol(3, 1); + + auto init_info_label = [parent, grid_sizer](wxStaticText **info_label, wxString text_label) { + auto *text = new wxStaticText(parent, wxID_ANY, text_label); + text->SetFont(GUI::small_font()); + *info_label = new wxStaticText(parent, wxID_ANY, ""); + (*info_label)->SetFont(GUI::small_font()); + grid_sizer->Add(text, 0); + grid_sizer->Add(*info_label, 0); + }; + + init_info_label(&info_size, _(L("Size"))); + init_info_label(&info_volume, _(L("Volume"))); + init_info_label(&info_facets, _(L("Facets"))); + init_info_label(&info_materials, _(L("Materials"))); + + auto *info_manifold_text = new wxStaticText(parent, wxID_ANY, _(L("Manifold"))); + info_manifold_text->SetFont(GUI::small_font()); + info_manifold = new wxStaticText(parent, wxID_ANY, ""); + info_manifold->SetFont(GUI::small_font()); + wxBitmap bitmap(GUI::from_u8(Slic3r::var("error.png")), wxBITMAP_TYPE_PNG); + manifold_warning_icon = new wxStaticBitmap(parent, wxID_ANY, bitmap); + auto *sizer_manifold = new wxBoxSizer(wxHORIZONTAL); + sizer_manifold->Add(info_manifold_text, 0); + sizer_manifold->Add(manifold_warning_icon, 0, wxLEFT, 2); + sizer_manifold->Add(info_manifold, 0, wxLEFT, 2); + grid_sizer->Add(sizer_manifold, 0, wxEXPAND | wxTOP, 4); + + Add(grid_sizer, 0, wxEXPAND); +} + +class SlicedInfo : public wxStaticBoxSizer +{ +public: + SlicedInfo(wxWindow *parent); + +private: + wxStaticText *info_filament_m; + wxStaticText *info_filament_mm3; + wxStaticText *info_filament_g; + wxStaticText *info_cost; + wxStaticText *info_time_normal; + wxStaticText *info_time_silent; +}; + +SlicedInfo::SlicedInfo(wxWindow *parent) : + wxStaticBoxSizer(new wxStaticBox(parent, wxID_ANY, _(L("Sliced Info"))), wxVERTICAL) +{ + // GetStaticBox()->SetFont(GUI::bold_font()); // XXX: ? + + auto *grid_sizer = new wxFlexGridSizer(2, 5, 5); + grid_sizer->SetFlexibleDirection(wxHORIZONTAL); + grid_sizer->AddGrowableCol(1, 1); + grid_sizer->AddGrowableCol(3, 1); + + auto init_info_label = [parent, grid_sizer](wxStaticText *&info_label, wxString text_label) { + auto *text = new wxStaticText(parent, wxID_ANY, text_label); + text->SetFont(GUI::small_font()); + info_label = new wxStaticText(parent, wxID_ANY, "N/A"); + info_label->SetFont(GUI::small_font()); + grid_sizer->Add(text, 0); + grid_sizer->Add(info_label, 0); + }; + + init_info_label(info_filament_m, _(L("Used Filament (m)"))); + init_info_label(info_filament_mm3, _(L("Used Filament (mm³)"))); + init_info_label(info_filament_g, _(L("Used Filament (g)"))); + init_info_label(info_cost, _(L("Cost"))); + init_info_label(info_time_normal, _(L("Estimated printing time (normal mode)"))); + init_info_label(info_time_silent, _(L("Estimated printing time (silent mode)"))); + + Add(grid_sizer, 0, wxEXPAND); +} + + +class PresetComboBox : public wxBitmapComboBox +{ +public: + PresetComboBox(wxWindow *parent, Preset::Type preset_type); + ~PresetComboBox(); + +private: + typedef std::size_t Marker; + enum { LABEL_ITEM_MARKER = 0x4d }; + + Preset::Type preset_type; + int last_selected; +}; + +PresetComboBox::PresetComboBox(wxWindow *parent, Preset::Type preset_type) : + wxBitmapComboBox(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, nullptr, wxCB_READONLY), + preset_type(preset_type), + last_selected(wxNOT_FOUND) +{ + Bind(wxEVT_COMBOBOX, [this](wxCommandEvent &evt) { + auto selected_item = this->GetSelection(); + + auto marker = reinterpret_cast(this->GetClientData(selected_item)); + if (marker == LABEL_ITEM_MARKER) { + this->SetSelection(this->last_selected); + evt.StopPropagation(); + } else if (this->last_selected != selected_item) { + this->last_selected = selected_item; + evt.SetInt(this->preset_type); + } else { + evt.StopPropagation(); + } + }); +} + +PresetComboBox::~PresetComboBox() {} + + +// Sidebar / private + +struct Sidebar::priv +{ + // Sidebar *q; // PIMPL back pointer ("Q-Pointer") + + wxScrolledWindow *scrolled; + + wxFlexGridSizer *sizer_presets; + PresetComboBox *combo_print; + std::vector combos_filament; + wxBoxSizer *sizer_filaments; + PresetComboBox *combo_sla_material; + PresetComboBox *combo_printer; + + wxBoxSizer *sizer_params; + ObjectInfo *object_info; + SlicedInfo *sliced_info; + + wxButton *btn_export_gcode; + wxButton *btn_reslice; + // wxButton *btn_print; // XXX: remove + wxButton *btn_send_gcode; +}; + + +// Sidebar / public + +Sidebar::Sidebar(wxWindow *parent) + : wxPanel(parent), p(new priv) +{ + p->scrolled = new wxScrolledWindow(this); + p->scrolled->SetScrollbars(0, 1, 1, 1); // XXX + + // The preset chooser + p->sizer_presets = new wxFlexGridSizer(4, 2, 1, 2); + p->sizer_presets->AddGrowableCol(1, 1); + p->sizer_presets->SetFlexibleDirection(wxHORIZONTAL); + p->sizer_filaments = new wxBoxSizer(wxVERTICAL); + + auto init_combo = [this](PresetComboBox **combo, wxString label, Preset::Type preset_type, bool filament) { + auto *text = new wxStaticText(this, wxID_ANY, label); + text->SetFont(GUI::small_font()); + // combo = new wxBitmapComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, nullptr, wxCB_READONLY); + *combo = new PresetComboBox(this, preset_type); + + auto *sizer_presets = this->p->sizer_presets; + auto *sizer_filaments = this->p->sizer_filaments; + sizer_presets->Add(text, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL | wxRIGHT, 4); + if (! filament) { + sizer_presets->Add(*combo, 1, wxALIGN_CENTER_VERTICAL | wxEXPAND | wxBOTTOM, 1); + } else { + sizer_filaments->Add(*combo, 1, wxEXPAND | wxBOTTOM, 1); + sizer_presets->Add(sizer_filaments, 1, wxEXPAND); + } + }; + + p->combos_filament.push_back(nullptr); + init_combo(&p->combo_print, _(L("Print settings")), Preset::TYPE_PRINT, false); + init_combo(&p->combos_filament[0], _(L("Filament")), Preset::TYPE_FILAMENT, true); + init_combo(&p->combo_sla_material, _(L("SLA material")), Preset::TYPE_SLA_MATERIAL, false); + init_combo(&p->combo_printer, _(L("Printer")), Preset::TYPE_PRINTER, false); + + // Frequently changed parameters + p->sizer_params = new wxBoxSizer(wxVERTICAL); + // GUI::add_frequently_changed_parameters(this, p->sizer_params, p->sizer_presets); + + // Buttons in the scrolled area + wxBitmap arrow_up(GUI::from_u8(Slic3r::var("brick_go.png")), wxBITMAP_TYPE_PNG); + p->btn_send_gcode = new wxButton(this, wxID_ANY, _(L("Send to printer"))); + p->btn_send_gcode->SetBitmap(arrow_up); + p->btn_send_gcode->Hide(); + auto *btns_sizer_scrolled = new wxBoxSizer(wxHORIZONTAL); + std::cerr << "btns_sizer_scrolled: " << btns_sizer_scrolled << std::endl; + btns_sizer_scrolled->Add(p->btn_send_gcode); + + // Info boxes + p->object_info = new ObjectInfo(this); + p->sliced_info = new SlicedInfo(this); + + // Sizer in the scrolled area + auto *scrolled_sizer = new wxBoxSizer(wxVERTICAL); + std::cerr << "scrolled_sizer: " << scrolled_sizer << std::endl; + scrolled_sizer->Add(p->sizer_presets, 0, wxEXPAND | wxLEFT, 2); + scrolled_sizer->Add(p->object_info, 1, wxEXPAND); + scrolled_sizer->Add(btns_sizer_scrolled, 0, wxEXPAND, 0); + scrolled_sizer->Add(p->sliced_info, 0, wxEXPAND); + + // Buttons underneath the scrolled area + p->btn_export_gcode = new wxButton(this, wxID_ANY, _(L("Export G-code…"))); + p->btn_reslice = new wxButton(this, wxID_ANY, _(L("Slice now"))); + + auto *btns_sizer = new wxBoxSizer(wxVERTICAL); + std::cerr << "btns_sizer: " << btns_sizer << std::endl; + btns_sizer->Add(p->btn_reslice); + btns_sizer->Add(p->btn_export_gcode); + + auto *sizer = new wxBoxSizer(wxVERTICAL); + std::cerr << "sizer: " << sizer << std::endl; + sizer->Add(scrolled_sizer); + sizer->Add(btns_sizer); + SetSizer(sizer); + SetMinSize(wxSize(320, -1)); +} + +Sidebar::~Sidebar() {} + +void Sidebar::update_presets(Preset::Type preset_type) +{ + // TODO: wxApp access + + switch (preset_type) { + case Preset::TYPE_FILAMENT: + // my $choice_idx = 0; + if (p->combos_filament.size() == 1) { + // Single filament printer, synchronize the filament presets. + // wxTheApp->{preset_bundle}->set_filament_preset(0, wxTheApp->{preset_bundle}->filament->get_selected_preset->name); + } + + for (size_t i = 0; i < p->combos_filament.size(); i++) { + // wxTheApp->{preset_bundle}->update_platter_filament_ui($choice_idx, $choice); + } + break; + + case Preset::TYPE_PRINT: + // wxTheApp->{preset_bundle}->print->update_platter_ui($choosers[0]); + break; + + case Preset::TYPE_SLA_MATERIAL: + // wxTheApp->{preset_bundle}->sla_material->update_platter_ui($choosers[0]); + break; + + case Preset::TYPE_PRINTER: + // Update the print choosers to only contain the compatible presets, update the dirty flags. + // wxTheApp->{preset_bundle}->print->update_platter_ui($self->{preset_choosers}{print}->[0]); + // Update the printer choosers, update the dirty flags. + // wxTheApp->{preset_bundle}->printer->update_platter_ui($choosers[0]); + // Update the filament choosers to only contain the compatible presets, update the color preview, + // update the dirty flags. + for (size_t i = 0; i < p->combos_filament.size(); i++) { + // wxTheApp->{preset_bundle}->update_platter_filament_ui($choice_idx, $choice); + } + break; + + default: break; + } + + // Synchronize config.ini with the current selections. + // wxTheApp->{preset_bundle}->export_selections(wxTheApp->{app_config}); +} + + +// Plater::Object + +struct PlaterObject +{ + std::string name; + bool selected; + + PlaterObject(std::string name) : name(std::move(name)), selected(false) {} +}; + +// Plater::DropTarget + +class PlaterDropTarget : public wxFileDropTarget +{ +public: + PlaterDropTarget(Plater *plater) : plater(plater) {} + + virtual bool OnDropFiles(wxCoord x, wxCoord y, const wxArrayString &filenames); + +private: + Plater *plater; +}; + +bool PlaterDropTarget::OnDropFiles(wxCoord x, wxCoord y, const wxArrayString &filenames) +{ + // TODO + // return false; + throw 0; +} + +// Plater / private + +struct Plater::priv +{ + // PIMPL back pointer ("Q-Pointer") + Plater *q; + MainFrame *main_frame; + + // Data + Slic3r::DynamicPrintConfig *config; + Slic3r::Print print; + Slic3r::Model model; + Slic3r::GCodePreviewData gcode_preview_data; + std::vector objects; + + std::string export_gcode_output_file; + std::string send_gcode_file; + + // GUI elements + wxNotebook *notebook; + Sidebar *sidebar; + wxGLCanvas *canvas3D; // TODO: Use GLCanvas3D when we can + GUI::Preview *preview; + BackgroundSlicingProcess background_process; + + static const int gl_attrs[]; + static const std::regex pattern_bundle; + static const std::regex pattern_3mf; + static const std::regex pattern_zip_amf; + + priv(Plater *q, MainFrame *main_frame); + + std::vector collect_selections(); + void update(bool force_autocenter = false); + void update_ui_from_settings(); + ProgressStatusBar* statusbar(); + std::vector load_files(const std::vector &input_files); + size_t load_model_objects(const ModelObjectPtrs &model_objects); + + void on_notebook_changed(wxBookCtrlEvent &); + void on_select_preset(wxCommandEvent &); + void on_update_print_preview(wxCommandEvent &); + void on_process_completed(wxCommandEvent &); + void on_layer_editing_toggled(bool enable); + void on_action_add(const wxCommandEvent&); +}; + +// TODO: multisample, see 3DScene.pm +const int Plater::priv::gl_attrs[] = {WX_GL_RGBA, WX_GL_DOUBLEBUFFER, WX_GL_DEPTH_SIZE, 24, 0}; +const std::regex Plater::priv::pattern_bundle("[.](amf|amf[.]xml|zip[.]amf|3mf|prusa)$", std::regex::icase); +const std::regex Plater::priv::pattern_3mf("[.]3mf$", std::regex::icase); +const std::regex Plater::priv::pattern_zip_amf("[.]zip[.]amf$", std::regex::icase); + +Plater::priv::priv(Plater *q, MainFrame *main_frame) : + q(q), + main_frame(main_frame), + config(Slic3r::DynamicPrintConfig::new_from_defaults_keys({ + "bed_shape", "complete_objects", "extruder_clearance_radius", "skirts", "skirt_distance", + "brim_width", "variable_layer_height", "serial_port", "serial_speed", "host_type", "print_host", + "printhost_apikey", "printhost_cafile", "nozzle_diameter", "single_extruder_multi_material", + "wipe_tower", "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_rotation_angle", + "extruder_colour", "filament_colour", "max_print_height", "printer_model" + })), + notebook(new wxNotebook(q, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_BOTTOM)), + sidebar(new Sidebar(q)), + canvas3D(new wxGLCanvas(notebook, wxID_ANY, gl_attrs)) +{ + background_process.set_print(&print); + background_process.set_gcode_preview_data(&gcode_preview_data); + background_process.set_sliced_event(EVT_SLICING_COMPLETED); + background_process.set_finished_event(EVT_PROCESS_COMPLETED); + + _3DScene::add_canvas(canvas3D); + notebook->AddPage(canvas3D, _(L("3D"))); + preview = new GUI::Preview(notebook, config, &print, &gcode_preview_data); + + // XXX: If have OpenGL + _3DScene::enable_picking(canvas3D, true); + _3DScene::enable_moving(canvas3D, true); + // XXX: more config from 3D.pm + // Slic3r::GUI::_3DScene::set_select_by($self, 'object'); + // Slic3r::GUI::_3DScene::set_drag_by($self, 'instance'); + // Slic3r::GUI::_3DScene::set_model($self, $model); + // Slic3r::GUI::_3DScene::set_print($self, $print); + // Slic3r::GUI::_3DScene::set_config($self, $config); + _3DScene::enable_gizmos(canvas3D, true); + _3DScene::enable_toolbar(canvas3D, true); + _3DScene::enable_shader(canvas3D, true); + _3DScene::enable_force_zoom_to_bed(canvas3D, true); + + // XXX: apply_config_timer + // { + // my $timer_id = Wx::NewId(); + // $self->{apply_config_timer} = Wx::Timer->new($self, $timer_id); + // EVT_TIMER($self, $timer_id, sub { + // my ($self, $event) = @_; + // $self->async_apply_config; + // }); + // } + + auto *bed_shape = config->opt("bed_shape"); + _3DScene::set_bed_shape(canvas3D, bed_shape->values); + _3DScene::zoom_to_bed(canvas3D); + preview->set_bed_shape(bed_shape->values); + + update(); + + // TODO: Preview::register_on_viewport_changed_callback is Perl-only + + auto *hsizer = new wxBoxSizer(wxHORIZONTAL); + hsizer->Add(notebook, 1, wxEXPAND | wxTOP, 1); + hsizer->Add(sidebar, 0, wxEXPAND | wxLEFT | wxRIGHT, 0); + q->SetSizer(hsizer); + + // Events: + + // Notebook page change event + notebook->Bind(wxEVT_NOTEBOOK_PAGE_CHANGED, &priv::on_notebook_changed, this); + + // Preset change event + sidebar->Bind(wxEVT_COMBOBOX, &priv::on_select_preset, this); + + // Sidebar button events + sidebar->p->btn_export_gcode->Bind(wxEVT_BUTTON, [q](wxCommandEvent&) { q->export_gcode(""); }); + sidebar->p->btn_reslice->Bind(wxEVT_BUTTON, [q](wxCommandEvent&) { q->reslice(); }); + sidebar->p->btn_send_gcode->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { + this->send_gcode_file = this->q->export_gcode(""); + }); + + // 3DScene events: + // TODO: (?) + // on_layer_editing_toggled + // on_action_add + canvas3D->Bind(EVT_GLTOOLBAR_ADD, &priv::on_action_add, this); + + q->Bind(EVT_SLICING_COMPLETED, &priv::on_update_print_preview, this); + q->Bind(EVT_PROCESS_COMPLETED, &priv::on_process_completed, this); + + // Drop target: + q->SetDropTarget(new PlaterDropTarget(q)); // if my understanding is right, wxWindow takes the owenership + + // TODO: ? + // # Send sizers/buttons to C++ + // Slic3r::GUI::set_objects_from_perl( $self->{scrolled_window_panel}, + // $frequently_changed_parameters_sizer, + // $info_sizer, + // $self->{btn_export_gcode}, + // # $self->{btn_export_stl}, + // $self->{btn_reslice}, + // $self->{btn_print}, + // $self->{btn_send_gcode}, + // $self->{object_info_manifold_warning_icon} ); + + // Slic3r::GUI::set_model_events_from_perl( $self->{model}, + // $self->{event_object_selection_changed}, + // $self->{event_object_settings_changed}, + // $self->{event_remove_object}, + // $self->{event_update_scene}); + + update_ui_from_settings(); + q->Layout(); +} + +std::vector Plater::priv::collect_selections() +{ + std::vector res; + for (const auto &obj : objects) { + res.push_back(obj.selected); + } + return res; +} + +void Plater::priv::update(bool force_autocenter) +{ + // TODO +} + +void Plater::priv::update_ui_from_settings() +{ + // TODO: (?) + // my ($self) = @_; + // if (defined($self->{btn_reslice}) && $self->{buttons_sizer}->IsShown($self->{btn_reslice}) != (! wxTheApp->{app_config}->get("background_processing"))) { + // $self->{buttons_sizer}->Show($self->{btn_reslice}, ! wxTheApp->{app_config}->get("background_processing")); + // $self->{buttons_sizer}->Layout; + // } +} + +ProgressStatusBar* Plater::priv::statusbar() +{ + return main_frame->m_statusbar; +} + +std::vector Plater::priv::load_files(const std::vector &input_files) +{ + if (input_files.size() < 1) { return std::vector(); } + + auto *nozzle_dmrs = config->opt("nozzle_diameter"); + + bool one_by_one = input_files.size() == 1 || nozzle_dmrs->values.size() <= 1; + if (! one_by_one) { + for (const auto &path : input_files) { + if (std::regex_match(path.string(), pattern_bundle)) { + one_by_one = true; + break; + } + } + } + + const auto loading = _(L("Loading…")); + wxProgressDialog dlg(loading, loading); + dlg.Pulse(); + + auto *new_model = one_by_one ? nullptr : new Slic3r::Model(); + std::vector obj_idx; // XXX: ? + + for (size_t i = 0; i < input_files.size(); i++) { + const auto &path = input_files[i]; + const auto filename = path.filename(); + const auto dlg_info = wxString::Format(_(L("Processing input file %s\n")), filename.string()); + dlg.Update(100 * i / input_files.size(), dlg_info); + + const bool type_3mf = std::regex_match(path.string(), pattern_3mf); + const bool type_zip_amf = !type_3mf && std::regex_match(path.string(), pattern_zip_amf); + + Slic3r::Model model; + try { + if (type_3mf || type_zip_amf) { + DynamicPrintConfig config; + config.apply(FullPrintConfig::defaults()); + model = Slic3r::Model::read_from_archive(path.string(), &config, false); + Preset::normalize(config); + wxGetApp().preset_bundle->load_config_model(filename.string(), std::move(config)); + for (const auto &kv : main_frame->options_tabs()) { kv.second->load_current_preset(); } + wxGetApp().app_config->update_config_dir(path.parent_path().string()); + // forces the update of the config here, or it will invalidate the imported layer heights profile if done using the timer + // and if the config contains a "layer_height" different from the current defined one + // TODO: + // $self->async_apply_config; + } else { + model = Slic3r::Model::read_from_file(path.string(), nullptr, false); + } + } + catch (const std::runtime_error &e) { + GUI::show_error(q, e.what()); + continue; + } + + // The model should now be initialized + + if (model.looks_like_multipart_object()) { + wxMessageDialog dlg(q, _(L( + "This file contains several objects positioned at multiple heights. " + "Instead of considering them as multiple objects, should I consider\n" + "this file as a single object having multiple parts?\n" + )), _(L("Multi-part object detected")), wxICON_WARNING | wxYES | wxNO); + if (dlg.ShowModal() == wxID_YES) { + model.convert_multipart_object(nozzle_dmrs->values.size()); + } + } + + if (type_3mf) { + for (ModelObject* model_object : model.objects) { + model_object->center_around_origin(); + } + } + + if (one_by_one) { + // TODO: + // push @obj_idx, $self->load_model_objects(@{$model->objects}); + // obj_idx.push_back(load_model_objects(model.objects); + } else { + // This must be an .stl or .obj file, which may contain a maximum of one volume. + for (const ModelObject* model_object : model.objects) { + new_model->add_object(*model_object); + } + } + } + + if (new_model != nullptr) { + wxMessageDialog dlg(q, _(L( + "Multiple objects were loaded for a multi-material printer.\n" + "Instead of considering them as multiple objects, should I consider\n" + "these files to represent a single object having multiple parts?\n" + )), _(L("Multi-part object detected")), wxICON_WARNING | wxYES | wxNO); + if (dlg.ShowModal() == wxID_YES) { + new_model->convert_multipart_object(nozzle_dmrs->values.size()); + } + + // TODO: + // push @obj_idx, $self->load_model_objects(@{$new_model->objects}); + // obj_idx.push_back(load_model_objects(new_model->objects); + } + + wxGetApp().app_config->update_skein_dir(input_files[input_files.size() - 1].parent_path().string()); + // XXX: Plater.pm had @loaded_files, but didn't seem to fill them with the filenames... + statusbar()->set_status_text(_(L("Loaded"))); + return obj_idx; +} + + +// TODO: move to Point.hpp +// inline Vec3crd to_3d(const Vec2crd &pt2, coord_t z) { return Vec3crd(pt2(0), pt2(1), z); } +// inline Vec3i64 to_3d(const Vec2i64 &pt2, int64_t z) { return Vec3i64(pt2(0), pt2(1), z); } +// inline Vec3f to_3d(const Vec2f &pt2, float z) { return Vec3f (pt2(0), pt2(1), z); } +// inline Vec3d to_3d(const Vec2d &pt2, double z) { return Vec3d (pt2(0), pt2(1), z); } +// typedef Eigen::Matrix Vec2crd; +template Eigen::Matrix to_3d(const Eigen::Matrix &m, T z) +{ + return Eigen::Matrix(m(0), m(1), z); +} + +Vec3crd to_3d(const Point &p, coord_t z) +{ + return Vec3crd(p(0), p(1), z); +} + +size_t Plater::priv::load_model_objects(const ModelObjectPtrs &model_objects) +{ + // TODO + + auto *bed_shape_opt = config->opt("bed_shape"); + const auto bed_shape = Slic3r::Polygon::new_scale(bed_shape_opt->values); + const BoundingBox bed_shape_bb = bed_shape.bounding_box(); + // const Point bed_center_2 = bed_shape_bb.center(); + // const Vec3d bed_center(bed_center_2(0), bed_center_2(1), 0.0); + // const Vec3d bed_center = to_3d(bed_shape_bb.center(), 0).cast(); + const Vec3d bed_center = to_3d(bed_shape_bb.center().cast(), 0.0); + const Vec2d bed_size = bed_shape_bb.size().cast(); + + bool need_arrange = false; + bool scaled_down = false; + // my @obj_idx = (); // XXX + std::vector obj_idx; + + for (const ModelObject *model_object : model_objects) { + auto *object = model.add_object(*model_object); + std::string object_name = object->name.empty() ? fs::path(object->input_file).filename().string() : object->name; + objects.emplace_back(std::move(object_name)); + obj_idx.push_back(objects.size() - 1); + + if (model_object->instances.size() == 0) { + // if object has no defined position(s) we need to rearrange everything after loading + need_arrange = true; + + // add a default instance and center object around origin + object->center_around_origin(); // also aligns object to Z = 0 + auto *instance = object->add_instance(); + instance->set_offset(bed_center); + } + + // my $size = $o->bounding_box->size; + // const auto size = object->bounding_box().size(); + // my $ratio = max($size->x / unscale($bed_size->x), $size->y / unscale($bed_size->y)); + // size.cwiseQuotient(bed_size); + // const auto = size / bed_size; + // const auto ratio = std::max(size.x / Slic3r::unscale(bed_size(0)), size.y / Slic3r::unscale(bed_size(1))); + // if ($ratio > 10000) { + // # the size of the object is too big -> this could lead to overflow when moving to clipper coordinates, + // # so scale down the mesh + // $o->scale_xyz(Slic3r::Pointf3->new(1/$ratio, 1/$ratio, 1/$ratio)); + // $scaled_down = 1; + // } + // elsif ($ratio > 5) { + // $_->set_scaling_factor(1/$ratio) for @{$o->instances}; + // $scaled_down = 1; + // } + } + + throw 0; + return 0; +} + +void Plater::priv::on_notebook_changed(wxBookCtrlEvent&) +{ + const auto current_id = notebook->GetCurrentPage()->GetId(); + if (current_id == canvas3D->GetId()) { + if (_3DScene::is_reload_delayed(canvas3D)) { + _3DScene::set_objects_selections(canvas3D, collect_selections()); + _3DScene::reload_scene(canvas3D, true); + } + // sets the canvas as dirty to force a render at the 1st idle event (wxWidgets IsShownOnScreen() is buggy and cannot be used reliably) + _3DScene::set_as_dirty(canvas3D); + } else if (current_id == preview->GetId()) { + preview->reload_print(); + preview->set_canvas_as_dirty(); + } +} + +void Plater::priv::on_select_preset(wxCommandEvent &evt) +{ + auto preset_type = static_cast(evt.GetInt()); + auto *combo = static_cast(evt.GetEventObject()); + + if (preset_type == Preset::TYPE_FILAMENT) { + // FIXME: + // wxTheApp->{preset_bundle}->set_filament_preset($idx, $choice->GetStringSelection); + } + + // TODO: ? + if (false) { + // if ($group eq 'filament' && @{$self->{preset_choosers}{filament}} > 1) { + // # Only update the platter UI for the 2nd and other filaments. + // wxTheApp->{preset_bundle}->update_platter_filament_ui($idx, $choice); + // } + } else { + auto selected_item = combo->GetSelection(); + + // TODO: Handle by an event handler in MainFrame, if needed + } + + // TODO: + // # Synchronize config.ini with the current selections. + // wxTheApp->{preset_bundle}->export_selections(wxTheApp->{app_config}); + // # get new config and generate on_config_change() event for updating plater and other things + // $self->on_config_change(wxTheApp->{preset_bundle}->full_config); +} + +void Plater::priv::on_update_print_preview(wxCommandEvent &) +{ + // TODO +} + +void Plater::priv::on_process_completed(wxCommandEvent &) +{ + // TODO +} + +void Plater::priv::on_layer_editing_toggled(bool enable) +{ + _3DScene::enable_layers_editing(canvas3D, enable); + if (enable && !_3DScene::is_layers_editing_enabled(canvas3D)) { + // Initialization of the OpenGL shaders failed. Disable the tool. + _3DScene::enable_toolbar_item(canvas3D, "layersediting", false); + } + canvas3D->Refresh(); + canvas3D->Update(); +} + +void Plater::priv::on_action_add(const wxCommandEvent&) +{ + wxArrayString input_files; + wxGetApp().open_model(q, input_files); + + std::vector input_paths; + for (const auto &file : input_files) { + input_paths.push_back(file.wx_str()); + } + load_files(input_paths); +} + +// Plater / Public + +Plater::Plater(wxWindow *parent, MainFrame *main_frame) + : wxPanel(parent), p(new priv(this, main_frame)) +{ + // Initialization performed in the private c-tor +} + +Plater::~Plater() +{ + _3DScene::remove_canvas(p->canvas3D); +} + +Sidebar& Plater::sidebar() { return *p->sidebar; } + +std::string Plater::export_gcode(const std::string &output_path) +{ + if (p->objects.size() == 0) { return ""; } + + if (! p->export_gcode_output_file.empty()) { + GUI::show_error(this, _(L("Another export job is currently running."))); + return ""; + } + + // wxTheApp->{preset_bundle}->full_config->validate; // FIXME + const std::string err = p->print.validate(); + if (! err.empty()) { + // The config is not valid + GUI::show_error(this, _(err)); + return ""; + } + + // Copy the names of active presets into the placeholder parser. + // wxTheApp->{preset_bundle}->export_selections_pp($self->{print}->placeholder_parser); // FIXME + + // select output file + if (! output_path.empty()) { + p->export_gcode_output_file = p->print.output_filepath(output_path); + // FIXME: ^ errors to handle? + } else { + // FIXME: + std::string default_output_file; // FIXME: tmp + // my $default_output_file = eval { $self->{print}->output_filepath($main::opt{output} // '') }; + // Slic3r::GUI::catch_error($self) and return; + + // If possible, remove accents from accented latin characters. + // This function is useful for generating file names to be processed by legacy firmwares. + default_output_file = Slic3r::fold_utf8_to_ascii(default_output_file); + wxFileDialog dlg(this, _(L("Save G-code file as:")), + wxEmptyString, + wxEmptyString, + Slic3r::GUI::FILE_WILDCARDS.at("gcode"), + wxFD_SAVE | wxFD_OVERWRITE_PROMPT + ); + // FIXME: ^ defaultDir: + // wxTheApp->{app_config}->get_last_output_dir(dirname($default_output_file)), + // FIXME: ^ defaultFile: + // basename($default_output_file), &Slic3r::GUI::FILE_WILDCARDS->{gcode}, wxFD_SAVE | wxFD_OVERWRITE_PROMPT); + + if (dlg.ShowModal() != wxID_OK) { return ""; } + auto path = dlg.GetPath(); + // wxTheApp->{app_config}->update_last_output_dir(dirname($path)); // FIXME + p->export_gcode_output_file = path; + } + + return p->export_gcode_output_file; +} + +void Plater::reslice() +{ + // TODO +} + + +}} // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp new file mode 100644 index 0000000000..415e9faab7 --- /dev/null +++ b/src/slic3r/GUI/Plater.hpp @@ -0,0 +1,60 @@ +#ifndef slic3r_Plater_hpp_ +#define slic3r_Plater_hpp_ + +#include + +#include +#include + +#include "Preset.hpp" + + +namespace Slic3r { +namespace GUI { + +class MainFrame; + +class Sidebar : public wxPanel +{ +public: + Sidebar(wxWindow *parent); + Sidebar(Sidebar &&) = delete; + Sidebar(const Sidebar &) = delete; + Sidebar &operator=(Sidebar &&) = delete; + Sidebar &operator=(const Sidebar &) = delete; + ~Sidebar(); + + void update_presets(Slic3r::Preset::Type preset_type); +private: + struct priv; + std::unique_ptr p; + + friend class Plater; // XXX: better encapsulation? +}; + + +class Plater: public wxPanel +{ +public: + Plater(wxWindow *parent, MainFrame *main_frame); + Plater(Plater &&) = delete; + Plater(const Plater &) = delete; + Plater &operator=(Plater &&) = delete; + Plater &operator=(const Plater &) = delete; + ~Plater(); + + Sidebar& sidebar(); + + // TODO: use fs::path + // Note: empty string means request default path + std::string export_gcode(const std::string &output_path); + void reslice(); +private: + struct priv; + std::unique_ptr p; +}; + + +}} + +#endif diff --git a/src/slic3r/GUI/Preset.hpp b/src/slic3r/GUI/Preset.hpp index 821d7dc543..bed9364110 100644 --- a/src/slic3r/GUI/Preset.hpp +++ b/src/slic3r/GUI/Preset.hpp @@ -177,11 +177,11 @@ public: static const std::vector& sla_material_options(); static void update_suffix_modified(); + static void normalize(DynamicPrintConfig &config); protected: friend class PresetCollection; friend class PresetBundle; - static void normalize(DynamicPrintConfig &config); // Resize the extruder specific vectors () static void set_num_extruders(DynamicPrintConfig &config, unsigned int n); static const std::string& suffix_modified(); diff --git a/src/slic3r/GUI/PresetBundle.hpp b/src/slic3r/GUI/PresetBundle.hpp index 68ec534dae..3cd8df54b6 100644 --- a/src/slic3r/GUI/PresetBundle.hpp +++ b/src/slic3r/GUI/PresetBundle.hpp @@ -73,6 +73,11 @@ public: void load_config(const std::string &name, DynamicPrintConfig config) { this->load_config_file_config(name, false, std::move(config)); } + // Load configuration that comes from a model file containing configuration, such as 3MF et al. + // This method is called by the Plater. + void load_config_model(const std::string &name, DynamicPrintConfig config) + { this->load_config_file_config(name, true, std::move(config)); } + // Load an external config file containing the print, filament and printer presets. // Instead of a config file, a G-code may be loaded containing the full set of parameters. // In the future the configuration will likely be read from an AMF file as well. diff --git a/src/slic3r/GUI/callback.hpp b/src/slic3r/GUI/callback.hpp index e031e32608..53f750e16c 100644 --- a/src/slic3r/GUI/callback.hpp +++ b/src/slic3r/GUI/callback.hpp @@ -10,7 +10,7 @@ namespace Slic3r { class PerlCallback { public: - PerlCallback(void *) {} + // PerlCallback(void *) {} PerlCallback() {} void register_callback(void *) {} void deregister_callback() {} From 08c69057516dfb90a83ec17099c545748855dbc8 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Mon, 1 Oct 2018 15:09:31 +0200 Subject: [PATCH 048/186] Moved functions and variables (for fonts and labels color) to GUI_App + corrected Sidebar layouts + deleted get_preset_bundle + actions with tabs_list moved to GUI_App --- src/slic3r.cpp | 4 +- src/slic3r/AppController.cpp | 9 +- src/slic3r/GUI/ButtonsDescription.cpp | 13 +- src/slic3r/GUI/Field.cpp | 3 +- src/slic3r/GUI/FirmwareDialog.cpp | 3 +- src/slic3r/GUI/GLCanvas3D.cpp | 3 +- src/slic3r/GUI/GUI.cpp | 217 +++++--------------------- src/slic3r/GUI/GUI.hpp | 25 +-- src/slic3r/GUI/GUI_App.cpp | 117 ++++++++++++-- src/slic3r/GUI/GUI_App.hpp | 30 ++++ src/slic3r/GUI/GUI_ObjectParts.cpp | 14 +- src/slic3r/GUI/MainFrame.cpp | 2 +- src/slic3r/GUI/OptionsGroup.hpp | 3 +- src/slic3r/GUI/Plater.cpp | 53 ++++--- src/slic3r/GUI/Tab.cpp | 18 +-- src/slic3r/GUI/Tab.hpp | 6 +- src/slic3r/Utils/PresetUpdater.cpp | 8 +- 17 files changed, 252 insertions(+), 276 deletions(-) diff --git a/src/slic3r.cpp b/src/slic3r.cpp index 4cd833e2f7..296d994147 100644 --- a/src/slic3r.cpp +++ b/src/slic3r.cpp @@ -12,6 +12,7 @@ __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1; #endif /* WIN32 */ +#include "libslic3r/libslic3r_version.h.in" #include "Config.hpp" #include "Geometry.hpp" #include "Model.hpp" @@ -73,7 +74,8 @@ int main(int argc, char **argv) // Path from the Slic3r binary to its resources. path_resources /= (path_to_binary.stem().string() == "slic3r-gui") ? // Running from the build directory: - "../../resources" : +// "../../resources" : // ? #ys_FIXME + "../../../resources" : // ! #ys_FIXME // Running from an installation directory: #ifdef __APPLE__ // The application is packed in the .dmg archive as 'Slic3r.app/Contents/MacOS/Slic3r' diff --git a/src/slic3r/AppController.cpp b/src/slic3r/AppController.cpp index 2bb79cec1a..0d6d07c28d 100644 --- a/src/slic3r/AppController.cpp +++ b/src/slic3r/AppController.cpp @@ -17,6 +17,7 @@ #include #include #include +#include "GUI/GUI_App.hpp" namespace Slic3r { @@ -41,9 +42,9 @@ bool AppControllerGui::is_main_thread() const return m_pri_data->ui_thread == std::this_thread::get_id(); } -namespace GUI { -PresetBundle* get_preset_bundle(); -} +// namespace GUI { +// PresetBundle* get_preset_bundle(); +// } static const PrintObjectStep STEP_SLICE = posSlice; static const PrintObjectStep STEP_PERIMETERS = posPerimeters; @@ -142,7 +143,7 @@ void PrintController::slice_to_png() using Pointf3 = Vec3d; auto ctl = GUI::get_appctl(); - auto presetbundle = GUI::get_preset_bundle(); + auto presetbundle = GUI::wxGetApp().preset_bundle; assert(presetbundle); diff --git a/src/slic3r/GUI/ButtonsDescription.cpp b/src/slic3r/GUI/ButtonsDescription.cpp index 5739fc90e3..8018382169 100644 --- a/src/slic3r/GUI/ButtonsDescription.cpp +++ b/src/slic3r/GUI/ButtonsDescription.cpp @@ -5,6 +5,7 @@ #include #include "GUI.hpp" +#include "GUI_App.hpp" namespace Slic3r { namespace GUI { @@ -36,8 +37,8 @@ ButtonsDescription::ButtonsDescription(wxWindow* parent, t_icon_descriptions* ic // Text color description auto sys_label = new wxStaticText(this, wxID_ANY, _(L("Value is the same as the system value"))); - sys_label->SetForegroundColour(get_label_clr_sys()); - auto sys_colour = new wxColourPickerCtrl(this, wxID_ANY, get_label_clr_sys()); + sys_label->SetForegroundColour(wxGetApp().get_label_clr_sys()); + auto sys_colour = new wxColourPickerCtrl(this, wxID_ANY, wxGetApp().get_label_clr_sys()); sys_colour->Bind(wxEVT_COLOURPICKER_CHANGED, ([sys_colour, sys_label](wxCommandEvent e) { sys_label->SetForegroundColour(sys_colour->GetColour()); @@ -53,8 +54,8 @@ ButtonsDescription::ButtonsDescription(wxWindow* parent, t_icon_descriptions* ic grid_sizer->Add(sys_label, -1, wxALIGN_CENTRE_VERTICAL | wxEXPAND); auto mod_label = new wxStaticText(this, wxID_ANY, _(L("Value was changed and is not equal to the system value or the last saved preset"))); - mod_label->SetForegroundColour(get_label_clr_modified()); - auto mod_colour = new wxColourPickerCtrl(this, wxID_ANY, get_label_clr_modified()); + mod_label->SetForegroundColour(wxGetApp().get_label_clr_modified()); + auto mod_colour = new wxColourPickerCtrl(this, wxID_ANY, wxGetApp().get_label_clr_modified()); mod_colour->Bind(wxEVT_COLOURPICKER_CHANGED, ([mod_colour, mod_label](wxCommandEvent e) { mod_label->SetForegroundColour(mod_colour->GetColour()); @@ -70,8 +71,8 @@ ButtonsDescription::ButtonsDescription(wxWindow* parent, t_icon_descriptions* ic wxButton* btn = static_cast(FindWindowById(wxID_OK, this)); btn->Bind(wxEVT_BUTTON, [sys_colour, mod_colour, this](wxCommandEvent&) { - set_label_clr_sys(sys_colour->GetColour()); - set_label_clr_modified(mod_colour->GetColour()); + wxGetApp().set_label_clr_sys(sys_colour->GetColour()); + wxGetApp().set_label_clr_modified(mod_colour->GetColour()); EndModal(wxID_OK); }); diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index f143e8bc6a..02fc9b8b6c 100644 --- a/src/slic3r/GUI/Field.cpp +++ b/src/slic3r/GUI/Field.cpp @@ -7,6 +7,7 @@ #include #include "PrintConfig.hpp" #include +#include "GUI_App.hpp" namespace Slic3r { namespace GUI { @@ -707,7 +708,7 @@ void StaticText::BUILD() wxString legend(static_cast(m_opt.default_value)->value); auto temp = new wxStaticText(m_parent, wxID_ANY, legend, wxDefaultPosition, size); - temp->SetFont(bold_font()); + temp->SetFont(wxGetApp().bold_font()); // // recast as a wxWindow to fit the calling convention window = dynamic_cast(temp); diff --git a/src/slic3r/GUI/FirmwareDialog.cpp b/src/slic3r/GUI/FirmwareDialog.cpp index d5ac64d900..b836b8e65e 100644 --- a/src/slic3r/GUI/FirmwareDialog.cpp +++ b/src/slic3r/GUI/FirmwareDialog.cpp @@ -35,6 +35,7 @@ #include #include #include +#include "GUI_App.hpp" namespace fs = boost::filesystem; @@ -213,7 +214,7 @@ void FirmwareDialog::priv::flashing_start(unsigned tasks) modal_response = wxID_NONE; txt_stdout->Clear(); set_txt_status(label_status_flashing); - txt_status->SetForegroundColour(GUI::get_label_clr_modified()); + txt_status->SetForegroundColour(GUI::wxGetApp().get_label_clr_modified()); port_picker->Disable(); btn_rescan->Disable(); hex_picker->Disable(); diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 5e4e71881e..89f092017e 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -10,6 +10,7 @@ #include "../../libslic3r/ClipperUtils.hpp" #include "../../libslic3r/PrintConfig.hpp" #include "../../libslic3r/GCode/PreviewData.hpp" +#include "GUI_App.hpp" #include @@ -424,7 +425,7 @@ GLCanvas3D::Bed::EType GLCanvas3D::Bed::_detect_type() const { EType type = Custom; - const PresetBundle* bundle = get_preset_bundle(); + auto bundle = wxGetApp().preset_bundle; if (bundle != nullptr) { const Preset* curr = &bundle->printers.get_selected_preset(); diff --git a/src/slic3r/GUI/GUI.cpp b/src/slic3r/GUI/GUI.cpp index ca79becf7d..1a4fbb833b 100644 --- a/src/slic3r/GUI/GUI.cpp +++ b/src/slic3r/GUI/GUI.cpp @@ -125,18 +125,12 @@ wxPanel *g_wxPlater = nullptr; AppConfig *g_AppConfig = nullptr; PresetBundle *g_PresetBundle= nullptr; PresetUpdater *g_PresetUpdater = nullptr; -wxColour g_color_label_modified; -wxColour g_color_label_sys; -wxColour g_color_label_default; // #ys_FIXME_for_delete std::vector g_tabs_list; wxLocale* g_wxLocale {nullptr}; -wxFont g_small_font; -wxFont g_bold_font; - std::vector > m_optgroups; double m_brim_width = 0.0; size_t m_label_width = 100; @@ -154,53 +148,13 @@ bool g_show_manifold_warning_icon = false; PreviewIface* g_preview = nullptr; -static void init_label_colours() -{ - auto luma = get_colour_approx_luma(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); - if (luma >= 128) { - g_color_label_modified = wxColour(252, 77, 1); - g_color_label_sys = wxColour(26, 132, 57); - } else { - g_color_label_modified = wxColour(253, 111, 40); - g_color_label_sys = wxColour(115, 220, 103); - } - g_color_label_default = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT); -} - -void update_label_colours_from_appconfig() -{ - if (g_AppConfig->has("label_clr_sys")){ - auto str = g_AppConfig->get("label_clr_sys"); - if (str != "") - g_color_label_sys = wxColour(str); - } - - if (g_AppConfig->has("label_clr_modified")){ - auto str = g_AppConfig->get("label_clr_modified"); - if (str != "") - g_color_label_modified = wxColour(str); - } -} - -static void init_fonts() -{ - g_small_font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); - g_bold_font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT).Bold(); -#ifdef __WXMAC__ - g_small_font.SetPointSize(11); - g_bold_font.SetPointSize(13); -#endif /*__WXMAC__*/ -} - -static std::string libslic3r_translate_callback(const char *s) { return wxGetTranslation(wxString(s, wxConvUTF8)).utf8_str().data(); } +// static std::string libslic3r_translate_callback(const char *s) { return wxGetTranslation(wxString(s, wxConvUTF8)).utf8_str().data(); } void set_wxapp(wxApp *app) { g_wxApp = app; // Let the libslic3r know the callback, which will translate messages on demand. - Slic3r::I18N::set_translate_callback(libslic3r_translate_callback); - init_label_colours(); - init_fonts(); +// Slic3r::I18N::set_translate_callback(libslic3r_translate_callback); } void set_main_frame(wxFrame *main_frame) @@ -269,8 +223,8 @@ void set_objects_from_perl( wxWindow* parent, g_buttons.push_back(btn_send_gcode); // Update font style for buttons - for (auto btn : g_buttons) - btn->SetFont(bold_font()); +// for (auto btn : g_buttons) +// btn->SetFont(bold_font()); g_manifold_warning_icon = manifold_warning_icon; } @@ -298,26 +252,6 @@ void set_objects_list_sizer(wxBoxSizer *objects_list_sizer){ g_object_list_sizer = objects_list_sizer; } -std::vector& get_tabs_list() -{ - return g_tabs_list; -} - -bool checked_tab(Tab* tab) -{ - bool ret = true; - if (find(g_tabs_list.begin(), g_tabs_list.end(), tab) == g_tabs_list.end()) - ret = false; - return ret; -} - -void delete_tab_from_list(Tab* tab) -{ - std::vector::iterator itr = find(g_tabs_list.begin(), g_tabs_list.end(), tab); - if (itr != g_tabs_list.end()) - g_tabs_list.erase(itr); -} - bool select_language(wxArrayString & names, wxArrayLong & identifiers) { @@ -423,31 +357,32 @@ void get_installed_languages(wxArrayString & names, } } -enum ConfigMenuIDs { - ConfigMenuWizard, - ConfigMenuSnapshots, - ConfigMenuTakeSnapshot, - ConfigMenuUpdate, - ConfigMenuPreferences, - ConfigMenuModeSimple, - ConfigMenuModeExpert, - ConfigMenuLanguage, - ConfigMenuFlashFirmware, - ConfigMenuCnt, -}; +// enum ConfigMenuIDs { +// ConfigMenuWizard, +// ConfigMenuSnapshots, +// ConfigMenuTakeSnapshot, +// ConfigMenuUpdate, +// ConfigMenuPreferences, +// ConfigMenuModeSimple, +// ConfigMenuModeExpert, +// ConfigMenuLanguage, +// ConfigMenuFlashFirmware, +// ConfigMenuCnt, +// }; // #ys_FIXME_for_delete -ConfigMenuIDs get_view_mode() -{ - if (!g_AppConfig->has("view_mode")) - return ConfigMenuModeSimple; - - const auto mode = g_AppConfig->get("view_mode"); - return mode == "expert" ? ConfigMenuModeExpert : ConfigMenuModeSimple; -} +// ConfigMenuIDs get_view_mode() +// { +// if (!g_AppConfig->has("view_mode")) +// return ConfigMenuModeSimple; +// +// const auto mode = g_AppConfig->get("view_mode"); +// return mode == "expert" ? ConfigMenuModeExpert : ConfigMenuModeSimple; +// } static wxString dots("…", wxConvUTF8); // #ys_FIXME_for_delete +/* void add_config_menu(wxMenuBar *menu, int event_preferences_changed, int event_language_change) { auto local_menu = new wxMenu(); @@ -551,7 +486,7 @@ void add_menus(wxMenuBar *menu, int event_preferences_changed, int event_languag { add_config_menu(menu, event_preferences_changed, event_language_change); } - +*/ void open_model(wxWindow *parent, wxArrayString& input_files){ auto dialog = new wxFileDialog(parent /*? parent : GetTopWindow()*/, _(L("Choose one or more files (STL/OBJ/AMF/3MF/PRUSA):")), @@ -569,6 +504,7 @@ void open_model(wxWindow *parent, wxArrayString& input_files){ // This is called when closing the application, when loading a config file or when starting the config wizard // to notify the user whether he is aware that some preset changes will be lost. // #ys_FIXME_for_delete +/* bool check_unsaved_changes() { std::string dirty; @@ -588,7 +524,7 @@ bool check_unsaved_changes() wxICON_QUESTION | wxYES_NO | wxNO_DEFAULT); return dialog->ShowModal() == wxID_YES; } - +*/ bool config_wizard_startup(bool app_config_exists) { if (! app_config_exists || g_PresetBundle->printers.size() <= 1) { @@ -610,7 +546,7 @@ bool config_wizard_startup(bool app_config_exists) void config_wizard(int reason) { // Exit wizard if there are unsaved changes and the user cancels the action. - if (! check_unsaved_changes()) + if (! wxGetApp().check_unsaved_changes()) return; try { @@ -622,7 +558,7 @@ void config_wizard(int reason) } // Load the currently selected preset into the GUI, update the preset selection box. - load_current_presets(); + wxGetApp().load_current_presets(); } void open_preferences_dialog(int event_preferences) @@ -631,6 +567,8 @@ void open_preferences_dialog(int event_preferences) dlg->ShowModal(); } +// #ys_FIXME_for_delete +/* void create_preset_tabs(int event_value_change, int event_presets_changed) { update_label_colours_from_appconfig(); @@ -639,7 +577,7 @@ void create_preset_tabs(int event_value_change, int event_presets_changed) add_created_tab(new TabSLAMaterial (g_wxTabPanel), event_value_change, event_presets_changed); add_created_tab(new TabPrinter (g_wxTabPanel), event_value_change, event_presets_changed); } - +*/ std::vector preset_tabs = { { "print", nullptr, ptFFF }, { "filament", nullptr, ptFFF }, @@ -790,37 +728,6 @@ void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt int i = 0;//no reason, just experiment } } -// #ys_FIXME_for_delete -void add_created_tab(Tab* panel, int event_value_change, int event_presets_changed) -{ - panel->create_preset_tab(g_PresetBundle); - - // Load the currently selected preset into the GUI, update the preset selection box. - panel->load_current_preset(); - - panel->set_event_value_change(wxEventType(event_value_change)); - panel->set_event_presets_changed(wxEventType(event_presets_changed)); - - const wxString& tab_name = panel->GetName(); - bool add_panel = true; - - auto it = std::find_if( preset_tabs.begin(), preset_tabs.end(), - [tab_name](PresetTab& tab){return tab.name == tab_name; }); - if (it != preset_tabs.end()) { - it->panel = panel; - add_panel = it->technology == g_PresetBundle->printers.get_edited_preset().printer_technology(); - } - - if (add_panel) - g_wxTabPanel->AddPage(panel, panel->title()); -} - -void load_current_presets() -{ - for (Tab *tab : g_tabs_list) { - tab->load_current_preset(); - } -} void show_error(wxWindow* parent, const wxString& message) { ErrorDialog msg(parent, message); @@ -860,60 +767,6 @@ wxApp* get_app(){ return g_wxApp; } -PresetBundle* get_preset_bundle() -{ - return g_PresetBundle; -} - -const wxColour& get_label_clr_modified() { - return g_color_label_modified; -} - -const wxColour& get_label_clr_sys() { - return g_color_label_sys; -} - -void set_label_clr_modified(const wxColour& clr) { - g_color_label_modified = clr; - auto clr_str = wxString::Format(wxT("#%02X%02X%02X"), clr.Red(), clr.Green(), clr.Blue()); - std::string str = clr_str.ToStdString(); - g_AppConfig->set("label_clr_modified", str); - g_AppConfig->save(); -} - -void set_label_clr_sys(const wxColour& clr) { - g_color_label_sys = clr; - auto clr_str = wxString::Format(wxT("#%02X%02X%02X"), clr.Red(), clr.Green(), clr.Blue()); - std::string str = clr_str.ToStdString(); - g_AppConfig->set("label_clr_sys", str); - g_AppConfig->save(); -} - -const wxFont& small_font(){ - return g_small_font; -} - -const wxFont& bold_font(){ - return g_bold_font; -} - -const wxColour& get_label_clr_default() { - return g_color_label_default; -} - -unsigned get_colour_approx_luma(const wxColour &colour) -{ - double r = colour.Red(); - double g = colour.Green(); - double b = colour.Blue(); - - return std::round(std::sqrt( - r * r * .241 + - g * g * .691 + - b * b * .068 - )); -} - wxWindow* get_right_panel(){ return g_right_panel; } @@ -1199,7 +1052,7 @@ void update_mode() { wxWindowUpdateLocker noUpdates(g_right_panel->GetParent()); - ConfigMenuIDs mode = get_view_mode(); + ConfigMenuIDs mode = wxGetApp().get_view_mode(); g_object_list_sizer->Show(mode == ConfigMenuModeExpert); show_info_sizer(mode == ConfigMenuModeExpert); @@ -1216,7 +1069,7 @@ void update_mode() } bool is_expert_mode(){ - return get_view_mode() == ConfigMenuModeExpert; + return wxGetApp().get_view_mode() == ConfigMenuModeExpert; } ConfigOptionsGroup* get_optgroup(size_t i) diff --git a/src/slic3r/GUI/GUI.hpp b/src/slic3r/GUI/GUI.hpp index 3ef662222d..83f9542486 100644 --- a/src/slic3r/GUI/GUI.hpp +++ b/src/slic3r/GUI/GUI.hpp @@ -127,26 +127,14 @@ void set_objects_list_sizer(wxBoxSizer *objects_list_sizer); AppConfig* get_app_config(); wxApp* get_app(); -PresetBundle* get_preset_bundle(); wxFrame* get_main_frame(); ProgressStatusBar* get_progress_status_bar(); -wxNotebook * get_tab_panel(); wxNotebook* get_tab_panel(); AppControllerPtr get_appctl(); void set_cli_appctl(); void set_gui_appctl(); -const wxColour& get_label_clr_modified(); -const wxColour& get_label_clr_sys(); -const wxColour& get_label_clr_default(); -unsigned get_colour_approx_luma(const wxColour &colour); -void set_label_clr_modified(const wxColour& clr); -void set_label_clr_sys(const wxColour& clr); - -const wxFont& small_font(); -const wxFont& bold_font(); - void open_model(wxWindow *parent, wxArrayString& input_files); wxWindow* get_right_panel(); @@ -159,7 +147,7 @@ extern void add_menus(wxMenuBar *menu, int event_preferences_changed, int event_ // This is called when closing the application, when loading a config file or when starting the config wizard // to notify the user whether he is aware that some preset changes will be lost. -extern bool check_unsaved_changes(); +// extern bool check_unsaved_changes(); // Checks if configuration wizard needs to run, calls config_wizard if so. // Returns whether the Wizard ran. @@ -173,19 +161,16 @@ extern void config_wizard(int run_reason); extern void open_preferences_dialog(int event_preferences); // Create a new preset tab (print, filament and printer), -void create_preset_tabs(int event_value_change, int event_presets_changed); +// void create_preset_tabs(int event_value_change, int event_presets_changed); TabIface* get_preset_tab_iface(char *name); PreviewIface* create_preview_iface(wxNotebook* notebook, DynamicPrintConfig* config, Print* print, GCodePreviewData* gcode_preview_data); // add it at the end of the tab panel. -void add_created_tab(Tab* panel, int event_value_change, int event_presets_changed); +// void add_created_tab(Tab* panel, int event_value_change, int event_presets_changed); // Change option value in config void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt_key, const boost::any& value, int opt_index = 0); -// Update UI / Tabs to reflect changes in the currently loaded presets -void load_current_presets(); - void show_error(wxWindow* parent, const wxString& message); void show_error_id(int id, const std::string& message); // For Perl void show_info(wxWindow* parent, const wxString& message, const wxString& title); @@ -209,10 +194,6 @@ void update_mode(); void show_info_sizer(const bool show); -std::vector& get_tabs_list(); -bool checked_tab(Tab* tab); -void delete_tab_from_list(Tab* tab); - // Creates a wxCheckListBoxComboPopup inside the given wxComboCtrl, filled with the given text and items. // Items are all initialized to the given value. // Items must be separated by '|', for example "Item1|Item2|Item3", and so on. diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 6aeea4a74b..6bca605686 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -25,10 +25,13 @@ #include "FirmwareDialog.hpp" #include "Preferences.hpp" #include "Tab.hpp" +#include namespace Slic3r { namespace GUI { +static std::string libslic3r_translate_callback(const char *s) { return wxGetTranslation(wxString(s, wxConvUTF8)).utf8_str().data(); } + IMPLEMENT_APP(GUI_App) bool GUI_App::OnInit() { @@ -42,13 +45,12 @@ bool GUI_App::OnInit() // 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()) - Slic3r::set_data_dir(wxStandardPaths::Get().GetUserDataDir().ToUTF8().data()); - // set_wxapp(this); // #ys_FIXME + set_data_dir(wxStandardPaths::Get().GetUserDataDir().ToUTF8().data()); app_config = new AppConfig(); - // set_app_config(app_config);// #ys_FIXME + set_app_config(app_config); preset_bundle = new PresetBundle(); - set_preset_bundle(preset_bundle); // #ys_FIXME + set_preset_bundle(preset_bundle); // just checking for existence of Slic3r::data_dir is not enough : it may be an empty directory // supplied as argument to --datadir; in that case we should still run the wizard @@ -62,11 +64,11 @@ bool GUI_App::OnInit() app_conf_exists = app_config->exists(); // load settings if (app_conf_exists) app_config->load(); - app_config->set("version", "Slic3r_VERSION"/*Slic3r::VERSION*/); + app_config->set("version", SLIC3R_VERSION); app_config->save(); -// preset_updater = new PresetUpdater(); -// set_preset_updater(preset_updater); // #ys_FIXME + preset_updater = new PresetUpdater(); + set_preset_updater(preset_updater); load_language(); @@ -80,8 +82,14 @@ bool GUI_App::OnInit() // show_error(undef, $@); // } + // Let the libslic3r know the callback, which will translate messages on demand. + Slic3r::I18N::set_translate_callback(libslic3r_translate_callback); + // initialize label colors and fonts + init_label_colours(); + init_fonts(); + // application frame - // print STDERR "Creating main frame...\n"; + std::cerr << "Creating main frame..." << std::endl; // wxImage::FindHandlerType(wxBITMAP_TYPE_PNG) || wxImage::AddHandler(new wxPNGHandler()); mainframe = new Slic3r::GUI::MainFrame(no_plater, false); @@ -157,9 +165,77 @@ bool GUI_App::OnInit() return true; } +unsigned GUI_App::get_colour_approx_luma(const wxColour &colour) +{ + double r = colour.Red(); + double g = colour.Green(); + double b = colour.Blue(); + + return std::round(std::sqrt( + r * r * .241 + + g * g * .691 + + b * b * .068 + )); +} + +void GUI_App::init_label_colours() +{ + auto luma = get_colour_approx_luma(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); + if (luma >= 128) { + m_color_label_modified = wxColour(252, 77, 1); + m_color_label_sys = wxColour(26, 132, 57); + } + else { + m_color_label_modified = wxColour(253, 111, 40); + m_color_label_sys = wxColour(115, 220, 103); + } + m_color_label_default = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT); +} + +void GUI_App::update_label_colours_from_appconfig() +{ + if (app_config->has("label_clr_sys")){ + auto str = app_config->get("label_clr_sys"); + if (str != "") + m_color_label_sys = wxColour(str); + } + + if (app_config->has("label_clr_modified")){ + auto str = app_config->get("label_clr_modified"); + if (str != "") + m_color_label_modified = wxColour(str); + } +} + +void GUI_App::init_fonts() +{ + m_small_font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); + m_bold_font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT).Bold(); +#ifdef __WXMAC__ + m_small_font.SetPointSize(11); + m_bold_font.SetPointSize(13); +#endif /*__WXMAC__*/ +} + +void GUI_App::set_label_clr_modified(const wxColour& clr) { + m_color_label_modified = clr; + auto clr_str = wxString::Format(wxT("#%02X%02X%02X"), clr.Red(), clr.Green(), clr.Blue()); + std::string str = clr_str.ToStdString(); + app_config->set("label_clr_modified", str); + app_config->save(); +} + +void GUI_App::set_label_clr_sys(const wxColour& clr) { + m_color_label_sys = clr; + auto clr_str = wxString::Format(wxT("#%02X%02X%02X"), clr.Red(), clr.Green(), clr.Blue()); + std::string str = clr_str.ToStdString(); + app_config->set("label_clr_sys", str); + app_config->save(); +} + void GUI_App::recreate_GUI() { -// print STDERR "recreate_GUI\n"; + std::cerr << "recreate_GUI" << std::endl; auto topwindow = GetTopWindow(); mainframe = new Slic3r::GUI::MainFrame(no_plater,false); @@ -478,6 +554,29 @@ bool GUI_App::check_unsaved_changes() return dialog->ShowModal() == wxID_YES; } +bool GUI_App::checked_tab(Tab* tab) +{ + bool ret = true; + if (find(tabs_list.begin(), tabs_list.end(), tab) == tabs_list.end()) + ret = false; + return ret; +} + +void GUI_App::delete_tab_from_list(Tab* tab) +{ + std::vector::iterator itr = find(tabs_list.begin(), tabs_list.end(), tab); + if (itr != tabs_list.end()) + tabs_list.erase(itr); +} + +// Update UI / Tabs to reflect changes in the currently loaded presets +void GUI_App::load_current_presets() +{ + for (Tab *tab : tabs_list) { + tab->load_current_preset(); + } +} + wxNotebook* GUI_App::tab_panel() const { return mainframe->m_tabpanel; diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 99c3d2c1ef..a6e2cdc7a9 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -8,6 +8,8 @@ // #include "GUI.hpp" #include +#include +#include #include #include @@ -50,10 +52,35 @@ class GUI_App : public wxApp // callbacks registered to run during idle event. std::stack> m_cb{}; + wxColour m_color_label_modified; + wxColour m_color_label_sys; + wxColour m_color_label_default; + + wxFont m_small_font; + wxFont m_bold_font; + + // #ys_FIXME +// std::vector g_tabs_list; +// wxLocale* g_wxLocale{ nullptr }; + public: bool OnInit() override; GUI_App() : wxApp() {} + unsigned get_colour_approx_luma(const wxColour &colour); + void init_label_colours(); + void update_label_colours_from_appconfig(); + void init_fonts(); + void set_label_clr_modified(const wxColour& clr); + void set_label_clr_sys(const wxColour& clr); + + const wxColour& get_label_clr_modified(){ return m_color_label_modified; } + const wxColour& get_label_clr_sys() { return m_color_label_sys; } + const wxColour& get_label_clr_default() { return m_color_label_default; } + + const wxFont& small_font() { return m_small_font; } + const wxFont& bold_font() { return m_bold_font; } + void recreate_GUI(); void system_info(); void open_model(wxWindow *parent, wxArrayString& input_files); @@ -82,7 +109,10 @@ public: ConfigMenuIDs get_view_mode(); void add_config_menu(wxMenuBar *menu); bool check_unsaved_changes(); + bool checked_tab(Tab* tab); + void delete_tab_from_list(Tab* tab); // Tab* get_tab(const std::string& name); + void load_current_presets(); AppConfig* app_config{ nullptr }; PresetBundle* preset_bundle{ nullptr }; diff --git a/src/slic3r/GUI/GUI_ObjectParts.cpp b/src/slic3r/GUI/GUI_ObjectParts.cpp index bcc3282b88..d27494617a 100644 --- a/src/slic3r/GUI/GUI_ObjectParts.cpp +++ b/src/slic3r/GUI/GUI_ObjectParts.cpp @@ -365,13 +365,13 @@ wxBoxSizer* create_edit_object_buttons(wxWindow* win) } m_sizer_part_buttons->Show(false); - btn_load_part->SetFont(Slic3r::GUI::small_font()); - btn_load_modifier->SetFont(Slic3r::GUI::small_font()); - btn_load_lambda_modifier->SetFont(Slic3r::GUI::small_font()); - btn_delete->SetFont(Slic3r::GUI::small_font()); - btn_split->SetFont(Slic3r::GUI::small_font()); - m_btn_move_up->SetFont(Slic3r::GUI::small_font()); - m_btn_move_down->SetFont(Slic3r::GUI::small_font()); + btn_load_part->SetFont(wxGetApp().small_font()); + btn_load_modifier->SetFont(wxGetApp().small_font()); + btn_load_lambda_modifier->SetFont(wxGetApp().small_font()); + btn_delete->SetFont(wxGetApp().small_font()); + btn_split->SetFont(wxGetApp().small_font()); + m_btn_move_up->SetFont(wxGetApp().small_font()); + m_btn_move_down->SetFont(wxGetApp().small_font()); sizer->Add(m_sizer_object_buttons, 0, wxEXPAND | wxLEFT, 20); sizer->Add(m_sizer_part_buttons, 0, wxEXPAND | wxLEFT, 20); diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index ee90cf297f..1aba0f7c7f 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -276,7 +276,7 @@ Tab* MainFrame::get_preset_tab(const std::string& name) void MainFrame::create_preset_tabs() { -// update_label_colours_from_appconfig(); + wxGetApp().update_label_colours_from_appconfig(); add_created_tab(new TabPrint(m_tabpanel)); add_created_tab(new TabFilament(m_tabpanel)); add_created_tab(new TabSLAMaterial(m_tabpanel)); diff --git a/src/slic3r/GUI/OptionsGroup.hpp b/src/slic3r/GUI/OptionsGroup.hpp index 4941e54539..3e196f70c8 100644 --- a/src/slic3r/GUI/OptionsGroup.hpp +++ b/src/slic3r/GUI/OptionsGroup.hpp @@ -14,6 +14,7 @@ #include "libslic3r/libslic3r.h" #include "Field.hpp" +#include "GUI_App.hpp" // Translate the ifdef #ifdef __WXOSX__ @@ -163,7 +164,7 @@ public: staticbox(title!=""), m_flag(flag), extra_column(extra_clmn){ if (staticbox) { stb = new wxStaticBox(_parent, wxID_ANY, title); - stb->SetFont(bold_font()); + stb->SetFont(wxGetApp().bold_font()); } sizer = (staticbox ? new wxStaticBoxSizer(stb, wxVERTICAL) : new wxBoxSizer(wxVERTICAL)); auto num_columns = 1U; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index e48ae031b4..1652a059cb 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -81,7 +81,7 @@ private: ObjectInfo::ObjectInfo(wxWindow *parent) : wxStaticBoxSizer(new wxStaticBox(parent, wxID_ANY, _(L("Info"))), wxVERTICAL) { - // GetStaticBox()->SetFont(GUI::bold_font()); // XXX: ? + GetStaticBox()->SetFont(wxGetApp().bold_font()); auto *grid_sizer = new wxFlexGridSizer(4, 5, 5); grid_sizer->SetFlexibleDirection(wxHORIZONTAL); @@ -90,9 +90,9 @@ ObjectInfo::ObjectInfo(wxWindow *parent) : auto init_info_label = [parent, grid_sizer](wxStaticText **info_label, wxString text_label) { auto *text = new wxStaticText(parent, wxID_ANY, text_label); - text->SetFont(GUI::small_font()); + text->SetFont(wxGetApp().small_font()); *info_label = new wxStaticText(parent, wxID_ANY, ""); - (*info_label)->SetFont(GUI::small_font()); + (*info_label)->SetFont(wxGetApp().small_font()); grid_sizer->Add(text, 0); grid_sizer->Add(*info_label, 0); }; @@ -103,9 +103,9 @@ ObjectInfo::ObjectInfo(wxWindow *parent) : init_info_label(&info_materials, _(L("Materials"))); auto *info_manifold_text = new wxStaticText(parent, wxID_ANY, _(L("Manifold"))); - info_manifold_text->SetFont(GUI::small_font()); + info_manifold_text->SetFont(wxGetApp().small_font()); info_manifold = new wxStaticText(parent, wxID_ANY, ""); - info_manifold->SetFont(GUI::small_font()); + info_manifold->SetFont(wxGetApp().small_font()); wxBitmap bitmap(GUI::from_u8(Slic3r::var("error.png")), wxBITMAP_TYPE_PNG); manifold_warning_icon = new wxStaticBitmap(parent, wxID_ANY, bitmap); auto *sizer_manifold = new wxBoxSizer(wxHORIZONTAL); @@ -134,18 +134,17 @@ private: SlicedInfo::SlicedInfo(wxWindow *parent) : wxStaticBoxSizer(new wxStaticBox(parent, wxID_ANY, _(L("Sliced Info"))), wxVERTICAL) { - // GetStaticBox()->SetFont(GUI::bold_font()); // XXX: ? + GetStaticBox()->SetFont(wxGetApp().bold_font()); auto *grid_sizer = new wxFlexGridSizer(2, 5, 5); grid_sizer->SetFlexibleDirection(wxHORIZONTAL); grid_sizer->AddGrowableCol(1, 1); - grid_sizer->AddGrowableCol(3, 1); auto init_info_label = [parent, grid_sizer](wxStaticText *&info_label, wxString text_label) { auto *text = new wxStaticText(parent, wxID_ANY, text_label); - text->SetFont(GUI::small_font()); + text->SetFont(wxGetApp().small_font()); info_label = new wxStaticText(parent, wxID_ANY, "N/A"); - info_label->SetFont(GUI::small_font()); + info_label->SetFont(wxGetApp().small_font()); grid_sizer->Add(text, 0); grid_sizer->Add(info_label, 0); }; @@ -231,7 +230,6 @@ Sidebar::Sidebar(wxWindow *parent) : wxPanel(parent), p(new priv) { p->scrolled = new wxScrolledWindow(this); - p->scrolled->SetScrollbars(0, 1, 1, 1); // XXX // The preset chooser p->sizer_presets = new wxFlexGridSizer(4, 2, 1, 2); @@ -240,10 +238,10 @@ Sidebar::Sidebar(wxWindow *parent) p->sizer_filaments = new wxBoxSizer(wxVERTICAL); auto init_combo = [this](PresetComboBox **combo, wxString label, Preset::Type preset_type, bool filament) { - auto *text = new wxStaticText(this, wxID_ANY, label); - text->SetFont(GUI::small_font()); + auto *text = new wxStaticText(p->scrolled, wxID_ANY, label); + text->SetFont(wxGetApp().small_font()); // combo = new wxBitmapComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, nullptr, wxCB_READONLY); - *combo = new PresetComboBox(this, preset_type); + *combo = new PresetComboBox(p->scrolled, preset_type); auto *sizer_presets = this->p->sizer_presets; auto *sizer_filaments = this->p->sizer_filaments; @@ -262,13 +260,15 @@ Sidebar::Sidebar(wxWindow *parent) init_combo(&p->combo_sla_material, _(L("SLA material")), Preset::TYPE_SLA_MATERIAL, false); init_combo(&p->combo_printer, _(L("Printer")), Preset::TYPE_PRINTER, false); + p->sizer_presets->Layout(); + // Frequently changed parameters p->sizer_params = new wxBoxSizer(wxVERTICAL); - // GUI::add_frequently_changed_parameters(this, p->sizer_params, p->sizer_presets); + GUI::add_frequently_changed_parameters(p->scrolled, p->sizer_params, p->sizer_presets); // Buttons in the scrolled area wxBitmap arrow_up(GUI::from_u8(Slic3r::var("brick_go.png")), wxBITMAP_TYPE_PNG); - p->btn_send_gcode = new wxButton(this, wxID_ANY, _(L("Send to printer"))); + p->btn_send_gcode = new wxButton(p->scrolled, wxID_ANY, _(L("Send to printer"))); p->btn_send_gcode->SetBitmap(arrow_up); p->btn_send_gcode->Hide(); auto *btns_sizer_scrolled = new wxBoxSizer(wxHORIZONTAL); @@ -276,32 +276,37 @@ Sidebar::Sidebar(wxWindow *parent) btns_sizer_scrolled->Add(p->btn_send_gcode); // Info boxes - p->object_info = new ObjectInfo(this); - p->sliced_info = new SlicedInfo(this); + p->object_info = new ObjectInfo(p->scrolled); + p->sliced_info = new SlicedInfo(p->scrolled); // Sizer in the scrolled area auto *scrolled_sizer = new wxBoxSizer(wxVERTICAL); + scrolled_sizer->SetMinSize(320, -1); + p->scrolled->SetSizer(scrolled_sizer); + p->scrolled->SetScrollbars(0, 1, 1, 1); std::cerr << "scrolled_sizer: " << scrolled_sizer << std::endl; scrolled_sizer->Add(p->sizer_presets, 0, wxEXPAND | wxLEFT, 2); - scrolled_sizer->Add(p->object_info, 1, wxEXPAND); + scrolled_sizer->Add(p->sizer_params, 1, wxEXPAND); + scrolled_sizer->Add(p->object_info, 0, wxEXPAND | wxTOP | wxLEFT, 20); scrolled_sizer->Add(btns_sizer_scrolled, 0, wxEXPAND, 0); - scrolled_sizer->Add(p->sliced_info, 0, wxEXPAND); + scrolled_sizer->Add(p->sliced_info, 0, wxEXPAND | wxTOP | wxLEFT, 20); // Buttons underneath the scrolled area p->btn_export_gcode = new wxButton(this, wxID_ANY, _(L("Export G-code…"))); + p->btn_export_gcode->SetFont(wxGetApp().bold_font()); p->btn_reslice = new wxButton(this, wxID_ANY, _(L("Slice now"))); + p->btn_reslice->SetFont(wxGetApp().bold_font()); auto *btns_sizer = new wxBoxSizer(wxVERTICAL); std::cerr << "btns_sizer: " << btns_sizer << std::endl; - btns_sizer->Add(p->btn_reslice); - btns_sizer->Add(p->btn_export_gcode); + btns_sizer->Add(p->btn_reslice, 0, wxEXPAND | wxTOP, 5); + btns_sizer->Add(p->btn_export_gcode, 0, wxEXPAND | wxTOP, 5); auto *sizer = new wxBoxSizer(wxVERTICAL); std::cerr << "sizer: " << sizer << std::endl; - sizer->Add(scrolled_sizer); - sizer->Add(btns_sizer); + sizer->Add(p->scrolled, 1, wxEXPAND | wxTOP, 5); + sizer->Add(btns_sizer, 0, wxEXPAND | wxLEFT, 20); SetSizer(sizer); - SetMinSize(wxSize(320, -1)); } Sidebar::~Sidebar() {} diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index def9ea5b55..e4a1f5933b 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -99,7 +99,7 @@ void Tab::create_preset_tab(PresetBundle *preset_bundle) "or click this button."))); // Determine the theme color of OS (dark or light) - auto luma = get_colour_approx_luma(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); + auto luma = wxGetApp().get_colour_approx_luma(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); // Bitmaps to be shown on the "Revert to system" aka "Lock to system" button next to each input field. m_bmp_value_lock .LoadFile(from_u8(var("sys_lock.png")), wxBITMAP_TYPE_PNG); m_bmp_value_unlock .LoadFile(from_u8(var(luma >= 128 ? "sys_unlock.png" : "sys_unlock_grey.png")), wxBITMAP_TYPE_PNG); @@ -122,18 +122,18 @@ void Tab::create_preset_tab(PresetBundle *preset_bundle) auto dlg = new ButtonsDescription(this, &m_icon_descriptions); if (dlg->ShowModal() == wxID_OK){ // Colors for ui "decoration" - for (Tab *tab : get_tabs_list()){ - tab->m_sys_label_clr = get_label_clr_sys(); - tab->m_modified_label_clr = get_label_clr_modified(); + for (Tab *tab : wxGetApp().tabs_list){ + tab->m_sys_label_clr = wxGetApp().get_label_clr_sys(); + tab->m_modified_label_clr = wxGetApp().get_label_clr_modified(); tab->update_labels_colour(); } } })); // Colors for ui "decoration" - m_sys_label_clr = get_label_clr_sys(); - m_modified_label_clr = get_label_clr_modified(); - m_default_text_clr = get_label_clr_default(); + m_sys_label_clr = wxGetApp().get_label_clr_sys(); + m_modified_label_clr = wxGetApp().get_label_clr_modified(); + m_default_text_clr = wxGetApp().get_label_clr_default(); m_hsizer = new wxBoxSizer(wxHORIZONTAL); sizer->Add(m_hsizer, 0, wxBOTTOM, 3); @@ -1484,7 +1484,7 @@ void TabPrinter::build_fff() Line line{ _(L("Bed shape")), "" }; line.widget = [this](wxWindow* parent){ auto btn = new wxButton(parent, wxID_ANY, _(L(" Set "))+dots, wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT); - btn->SetFont(Slic3r::GUI::small_font()); + btn->SetFont(wxGetApp().small_font()); btn->SetBitmap(wxBitmap(from_u8(Slic3r::var("printer_empty.png")), wxBITMAP_TYPE_PNG)); auto sizer = new wxBoxSizer(wxHORIZONTAL); @@ -2183,7 +2183,7 @@ void Tab::load_current_preset() // (not sure this is true anymore now that update_dirty is idempotent) wxTheApp->CallAfter([this]{ // checking out if this Tab exists till this moment - if (!checked_tab(this)) + if (!wxGetApp().checked_tab(this)) return; update_tab_ui(); diff --git a/src/slic3r/GUI/Tab.hpp b/src/slic3r/GUI/Tab.hpp index e4e37d4eb8..afdf2008b2 100644 --- a/src/slic3r/GUI/Tab.hpp +++ b/src/slic3r/GUI/Tab.hpp @@ -57,7 +57,7 @@ public: { Create(m_parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL); m_vsizer = new wxBoxSizer(wxVERTICAL); - m_item_color = &get_label_clr_default(); + m_item_color = &wxGetApp().get_label_clr_default(); SetSizer(m_vsizer); } ~Page(){} @@ -201,10 +201,10 @@ public: Tab(wxNotebook* parent, const wxString& title, const char* name) : m_parent(parent), m_title(title), m_name(name) { Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBK_LEFT | wxTAB_TRAVERSAL, name); - get_tabs_list().push_back(this); + wxGetApp().tabs_list.push_back(this); } ~Tab(){ - delete_tab_from_list(this); + wxGetApp().delete_tab_from_list(this); } wxWindow* parent() const { return m_parent; } diff --git a/src/slic3r/Utils/PresetUpdater.cpp b/src/slic3r/Utils/PresetUpdater.cpp index 617afb68db..026e340da5 100644 --- a/src/slic3r/Utils/PresetUpdater.cpp +++ b/src/slic3r/Utils/PresetUpdater.cpp @@ -570,10 +570,10 @@ bool PresetUpdater::config_update() const BOOST_LOG_TRIVIAL(info) << "User wants to re-configure..."; p->perform_updates(std::move(updates)); GUI::ConfigWizard wizard(nullptr, GUI::ConfigWizard::RR_DATA_INCOMPAT); - if (! wizard.run(GUI::get_preset_bundle(), this)) { + if (! wizard.run(GUI::wxGetApp().preset_bundle, this)) { return false; } - GUI::load_current_presets(); + GUI::wxGetApp().load_current_presets(); } else { BOOST_LOG_TRIVIAL(info) << "User wants to exit Slic3r, bye..."; return false; @@ -603,8 +603,8 @@ bool PresetUpdater::config_update() const // Reload global configuration auto *app_config = GUI::wxGetApp().app_config; - GUI::get_preset_bundle()->load_presets(*app_config); - GUI::load_current_presets(); + GUI::wxGetApp().preset_bundle->load_presets(*app_config); + GUI::wxGetApp().load_current_presets(); } else { BOOST_LOG_TRIVIAL(info) << "User refused the update"; } From 9021bd07a33c8daf3decbf2ebf85a90909157c89 Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Mon, 1 Oct 2018 16:48:08 +0200 Subject: [PATCH 049/186] WIP: Plater --- src/slic3r/GUI/GLCanvas3D.hpp | 1 + src/slic3r/GUI/GLCanvas3DManager.cpp | 25 ++++ src/slic3r/GUI/GLCanvas3DManager.hpp | 3 + src/slic3r/GUI/GUI_Preview.cpp | 29 ++--- src/slic3r/GUI/Plater.cpp | 168 ++++++++++++++++++--------- 5 files changed, 155 insertions(+), 71 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 7c0a7fe2e2..aba2b07c1d 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -7,6 +7,7 @@ #include "GLToolbar.hpp" #include "callback.hpp" +class wxWindow; class wxTimer; class wxSizeEvent; class wxIdleEvent; diff --git a/src/slic3r/GUI/GLCanvas3DManager.cpp b/src/slic3r/GUI/GLCanvas3DManager.cpp index 1fef7ffe99..643171a17d 100644 --- a/src/slic3r/GUI/GLCanvas3DManager.cpp +++ b/src/slic3r/GUI/GLCanvas3DManager.cpp @@ -827,6 +827,31 @@ void GLCanvas3DManager::register_action_selectbyparts_callback(wxGLCanvas* canva it->second->register_action_selectbyparts_callback(callback); } +bool GLCanvas3DManager::can_multisample() +{ + int wxVersion = wxMAJOR_VERSION * 10000 + wxMINOR_VERSION * 100 + wxRELEASE_NUMBER; + const AppConfig* app_config = GUI::get_app_config(); + bool enable_multisample = app_config != nullptr + && app_config->get("use_legacy_opengl") != "1" + && wxVersion >= 30003; + + // if multisample is not enabled or supported by the graphic card, remove it from the attributes list + return enable_multisample && wxGLCanvas::IsExtensionSupported("WGL_ARB_multisample"); + // <<< Alternative method: but IsDisplaySupported() seems not to work + // bool return enable_multisample && wxGLCanvas::IsDisplaySupported(attribList); +} + +wxGLCanvas* GLCanvas3DManager::create_wxglcanvas(wxWindow *parent) +{ + int attribList[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER, WX_GL_DEPTH_SIZE, 24, WX_GL_SAMPLE_BUFFERS, GL_TRUE, WX_GL_SAMPLES, 4, 0 }; + + if (! can_multisample()) { + attribList[4] = 0; + } + + return new wxGLCanvas(parent, wxID_ANY, attribList); +} + GLCanvas3DManager::CanvasesMap::iterator GLCanvas3DManager::_get_canvas(wxGLCanvas* canvas) { return (canvas == nullptr) ? m_canvases.end() : m_canvases.find(canvas); diff --git a/src/slic3r/GUI/GLCanvas3DManager.hpp b/src/slic3r/GUI/GLCanvas3DManager.hpp index 1c376cb293..c833de397f 100644 --- a/src/slic3r/GUI/GLCanvas3DManager.hpp +++ b/src/slic3r/GUI/GLCanvas3DManager.hpp @@ -6,6 +6,7 @@ #include #include +class wxWindow; class wxGLCanvas; class wxGLContext; @@ -186,6 +187,8 @@ public: void register_action_layersediting_callback(wxGLCanvas* canvas, void* callback); void register_action_selectbyparts_callback(wxGLCanvas* canvas, void* callback); + static bool can_multisample(); + static wxGLCanvas* create_wxglcanvas(wxWindow *parent); private: CanvasesMap::iterator _get_canvas(wxGLCanvas* canvas); CanvasesMap::const_iterator _get_canvas(wxGLCanvas* canvas) const; diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index c66d1fd1f2..c70a6080c2 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -3,6 +3,7 @@ #include "GUI.hpp" #include "AppConfig.hpp" #include "3DScene.hpp" +#include "GLCanvas3DManager.hpp" #include "../../libslic3r/GCode/PreviewData.hpp" #include "PresetBundle.hpp" @@ -57,24 +58,26 @@ bool Preview::init(wxNotebook* notebook, DynamicPrintConfig* config, Print* prin if (!Create(notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize)) return false; - int attribList[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER, WX_GL_DEPTH_SIZE, 24, WX_GL_SAMPLE_BUFFERS, GL_TRUE, WX_GL_SAMPLES, 4, 0 }; +// int attribList[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER, WX_GL_DEPTH_SIZE, 24, WX_GL_SAMPLE_BUFFERS, GL_TRUE, WX_GL_SAMPLES, 4, 0 }; - int wxVersion = wxMAJOR_VERSION * 10000 + wxMINOR_VERSION * 100 + wxRELEASE_NUMBER; - const AppConfig* app_config = GUI::get_app_config(); - bool enable_multisample = (app_config != nullptr) && (app_config->get("use_legacy_opengl") != "1") && (wxVersion >= 30003); +// int wxVersion = wxMAJOR_VERSION * 10000 + wxMINOR_VERSION * 100 + wxRELEASE_NUMBER; +// const AppConfig* app_config = GUI::get_app_config(); +// bool enable_multisample = (app_config != nullptr) && (app_config->get("use_legacy_opengl") != "1") && (wxVersion >= 30003); - // if multisample is not enabled or supported by the graphic card, remove it from the attributes list - bool can_multisample = enable_multisample && wxGLCanvas::IsExtensionSupported("WGL_ARB_multisample"); -// bool can_multisample = enable_multisample && wxGLCanvas::IsDisplaySupported(attribList); // <<< Alternative method: but IsDisplaySupported() seems not to work - if (!can_multisample) - attribList[4] = 0; +// // if multisample is not enabled or supported by the graphic card, remove it from the attributes list +// bool can_multisample = enable_multisample && wxGLCanvas::IsExtensionSupported("WGL_ARB_multisample"); +// // bool can_multisample = enable_multisample && wxGLCanvas::IsDisplaySupported(attribList); // <<< Alternative method: but IsDisplaySupported() seems not to work +// if (!can_multisample) +// attribList[4] = 0; - m_canvas = new wxGLCanvas(this, wxID_ANY, attribList); - if (m_canvas == nullptr) - return false; +// m_canvas = new wxGLCanvas(this, wxID_ANY, attribList); +// if (m_canvas == nullptr) +// return false; + + m_canvas = GLCanvas3DManager::create_wxglcanvas(this); _3DScene::add_canvas(m_canvas); - _3DScene::allow_multisample(m_canvas, can_multisample); + _3DScene::allow_multisample(m_canvas, GLCanvas3DManager::can_multisample()); _3DScene::enable_shader(m_canvas, true); _3DScene::set_config(m_canvas, m_config); _3DScene::set_print(m_canvas, m_print); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 1652a059cb..b13b5b65d2 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include "libslic3r/PrintConfig.hpp" #include "libslic3r/Model.hpp" @@ -25,11 +26,11 @@ #include "libslic3r/GCode/PreviewData.hpp" #include "libslic3r/Utils.hpp" #include "libslic3r/Polygon.hpp" -// #include "libslic3r/BoundingBox.hpp" #include "GUI.hpp" #include "GUI_App.hpp" #include "MainFrame.hpp" #include "3DScene.hpp" +#include "GUI_ObjectParts.hpp" #include "GLToolbar.hpp" #include "GUI_Preview.hpp" #include "Tab.hpp" @@ -422,8 +423,10 @@ struct Plater::priv void update(bool force_autocenter = false); void update_ui_from_settings(); ProgressStatusBar* statusbar(); + std::string get_config(const std::string &key) const; + BoundingBox bed_shape_bb() const; std::vector load_files(const std::vector &input_files); - size_t load_model_objects(const ModelObjectPtrs &model_objects); + std::vector load_model_objects(const ModelObjectPtrs &model_objects); void on_notebook_changed(wxBookCtrlEvent &); void on_select_preset(wxCommandEvent &); @@ -451,7 +454,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) : })), notebook(new wxNotebook(q, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_BOTTOM)), sidebar(new Sidebar(q)), - canvas3D(new wxGLCanvas(notebook, wxID_ANY, gl_attrs)) + canvas3D(GLCanvas3DManager::create_wxglcanvas(notebook)) { background_process.set_print(&print); background_process.set_gcode_preview_data(&gcode_preview_data); @@ -459,6 +462,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) : background_process.set_finished_event(EVT_PROCESS_COMPLETED); _3DScene::add_canvas(canvas3D); + _3DScene::allow_multisample(canvas3D, GLCanvas3DManager::can_multisample()); notebook->AddPage(canvas3D, _(L("3D"))); preview = new GUI::Preview(notebook, config, &print, &gcode_preview_data); @@ -466,11 +470,11 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) : _3DScene::enable_picking(canvas3D, true); _3DScene::enable_moving(canvas3D, true); // XXX: more config from 3D.pm - // Slic3r::GUI::_3DScene::set_select_by($self, 'object'); - // Slic3r::GUI::_3DScene::set_drag_by($self, 'instance'); - // Slic3r::GUI::_3DScene::set_model($self, $model); - // Slic3r::GUI::_3DScene::set_print($self, $print); - // Slic3r::GUI::_3DScene::set_config($self, $config); + _3DScene::set_select_by(canvas3D, "object"); + _3DScene::set_drag_by(canvas3D, "instance"); + _3DScene::set_model(canvas3D, &model); + _3DScene::set_print(canvas3D, &print); + _3DScene::set_config(canvas3D, config); _3DScene::enable_gizmos(canvas3D, true); _3DScene::enable_toolbar(canvas3D, true); _3DScene::enable_shader(canvas3D, true); @@ -527,6 +531,9 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) : // Drop target: q->SetDropTarget(new PlaterDropTarget(q)); // if my understanding is right, wxWindow takes the owenership + // Setting of global access pointers + // FIXME: We really should get rid of these once Perl code is gone... + set_objects_from_model(model); // TODO: ? // # Send sizers/buttons to C++ // Slic3r::GUI::set_objects_from_perl( $self->{scrolled_window_panel}, @@ -560,7 +567,26 @@ std::vector Plater::priv::collect_selections() void Plater::priv::update(bool force_autocenter) { - // TODO + + wxWindowUpdateLocker freeze_guard(q); + if (get_config("autocenter") == "1" || force_autocenter) { + // auto *bed_shape_opt = config->opt("bed_shape"); + // const auto bed_shape = Slic3r::Polygon::new_scale(bed_shape_opt->values); + // const BoundingBox bed_shape_bb = bed_shape.bounding_box(); + const Vec2d bed_center = bed_shape_bb().center().cast(); + model.center_instances_around_point(bed_center); + } + + // stop_background_process(); // TODO + print.reload_model_instances(); + + const auto selections = collect_selections(); + _3DScene::set_objects_selections(canvas3D, selections); + _3DScene::reload_scene(canvas3D, false); + preview->reset_gcode_preview_data(); + preview->reload_print(); + + // schedule_background_process(); // TODO } void Plater::priv::update_ui_from_settings() @@ -578,6 +604,18 @@ ProgressStatusBar* Plater::priv::statusbar() return main_frame->m_statusbar; } +std::string Plater::priv::get_config(const std::string &key) const +{ + return wxGetApp().app_config->get(key); +} + +BoundingBox Plater::priv::bed_shape_bb() const +{ + const auto *bed_shape_opt = config->opt("bed_shape"); + const auto bed_shape = Slic3r::Polygon::new_scale(bed_shape_opt->values); + return bed_shape.bounding_box(); +} + std::vector Plater::priv::load_files(const std::vector &input_files) { if (input_files.size() < 1) { return std::vector(); } @@ -599,7 +637,7 @@ std::vector Plater::priv::load_files(const std::vector &input_ dlg.Pulse(); auto *new_model = one_by_one ? nullptr : new Slic3r::Model(); - std::vector obj_idx; // XXX: ? + std::vector obj_idxs; for (size_t i = 0; i < input_files.size(); i++) { const auto &path = input_files[i]; @@ -656,6 +694,8 @@ std::vector Plater::priv::load_files(const std::vector &input_ // TODO: // push @obj_idx, $self->load_model_objects(@{$model->objects}); // obj_idx.push_back(load_model_objects(model.objects); + auto loaded_idxs = load_model_objects(model.objects); + obj_idxs.insert(obj_idxs.end(), loaded_idxs.begin(), loaded_idxs.end()); } else { // This must be an .stl or .obj file, which may contain a maximum of one volume. for (const ModelObject* model_object : model.objects) { @@ -677,54 +717,38 @@ std::vector Plater::priv::load_files(const std::vector &input_ // TODO: // push @obj_idx, $self->load_model_objects(@{$new_model->objects}); // obj_idx.push_back(load_model_objects(new_model->objects); + auto loaded_idxs = load_model_objects(model.objects); + obj_idxs.insert(obj_idxs.end(), loaded_idxs.begin(), loaded_idxs.end()); } wxGetApp().app_config->update_skein_dir(input_files[input_files.size() - 1].parent_path().string()); // XXX: Plater.pm had @loaded_files, but didn't seem to fill them with the filenames... statusbar()->set_status_text(_(L("Loaded"))); - return obj_idx; + return obj_idxs; } // TODO: move to Point.hpp -// inline Vec3crd to_3d(const Vec2crd &pt2, coord_t z) { return Vec3crd(pt2(0), pt2(1), z); } -// inline Vec3i64 to_3d(const Vec2i64 &pt2, int64_t z) { return Vec3i64(pt2(0), pt2(1), z); } -// inline Vec3f to_3d(const Vec2f &pt2, float z) { return Vec3f (pt2(0), pt2(1), z); } -// inline Vec3d to_3d(const Vec2d &pt2, double z) { return Vec3d (pt2(0), pt2(1), z); } -// typedef Eigen::Matrix Vec2crd; -template Eigen::Matrix to_3d(const Eigen::Matrix &m, T z) -{ - return Eigen::Matrix(m(0), m(1), z); -} +Vec3d to_3d(const Vec2d &v, double z) { return Vec3d(v(0), v(1), z); } +Vec3f to_3d(const Vec2f &v, float z) { return Vec3f(v(0), v(1), z); } +Vec3i64 to_3d(const Vec2i64 &v, float z) { return Vec3i64(v(0), v(1), z); } +Vec3crd to_3d(const Point &p, coord_t z) { return Vec3crd(p(0), p(1), z); } -Vec3crd to_3d(const Point &p, coord_t z) +std::vector Plater::priv::load_model_objects(const ModelObjectPtrs &model_objects) { - return Vec3crd(p(0), p(1), z); -} - -size_t Plater::priv::load_model_objects(const ModelObjectPtrs &model_objects) -{ - // TODO - - auto *bed_shape_opt = config->opt("bed_shape"); - const auto bed_shape = Slic3r::Polygon::new_scale(bed_shape_opt->values); - const BoundingBox bed_shape_bb = bed_shape.bounding_box(); - // const Point bed_center_2 = bed_shape_bb.center(); - // const Vec3d bed_center(bed_center_2(0), bed_center_2(1), 0.0); - // const Vec3d bed_center = to_3d(bed_shape_bb.center(), 0).cast(); - const Vec3d bed_center = to_3d(bed_shape_bb.center().cast(), 0.0); - const Vec2d bed_size = bed_shape_bb.size().cast(); + const BoundingBox bed_shape = bed_shape_bb(); + const Vec3d bed_center = to_3d(bed_shape.center().cast(), 0.0); + const Vec3d bed_size = to_3d(bed_shape.size().cast(), 1.0); bool need_arrange = false; bool scaled_down = false; - // my @obj_idx = (); // XXX - std::vector obj_idx; + std::vector obj_idxs; - for (const ModelObject *model_object : model_objects) { + for (ModelObject *model_object : model_objects) { auto *object = model.add_object(*model_object); std::string object_name = object->name.empty() ? fs::path(object->input_file).filename().string() : object->name; objects.emplace_back(std::move(object_name)); - obj_idx.push_back(objects.size() - 1); + obj_idxs.push_back(objects.size() - 1); if (model_object->instances.size() == 0) { // if object has no defined position(s) we need to rearrange everything after loading @@ -736,26 +760,54 @@ size_t Plater::priv::load_model_objects(const ModelObjectPtrs &model_objects) instance->set_offset(bed_center); } - // my $size = $o->bounding_box->size; - // const auto size = object->bounding_box().size(); - // my $ratio = max($size->x / unscale($bed_size->x), $size->y / unscale($bed_size->y)); - // size.cwiseQuotient(bed_size); - // const auto = size / bed_size; - // const auto ratio = std::max(size.x / Slic3r::unscale(bed_size(0)), size.y / Slic3r::unscale(bed_size(1))); - // if ($ratio > 10000) { - // # the size of the object is too big -> this could lead to overflow when moving to clipper coordinates, - // # so scale down the mesh - // $o->scale_xyz(Slic3r::Pointf3->new(1/$ratio, 1/$ratio, 1/$ratio)); - // $scaled_down = 1; - // } - // elsif ($ratio > 5) { - // $_->set_scaling_factor(1/$ratio) for @{$o->instances}; - // $scaled_down = 1; - // } + const Vec3d size = object->bounding_box().size(); + const Vec3d ratio = size.cwiseQuotient(bed_size); + const double max_ratio = std::max(ratio(0), ratio(1)); + if (max_ratio > 10000) { + // the size of the object is too big -> this could lead to overflow when moving to clipper coordinates, + // so scale down the mesh + // const Vec3d inverse = ratio.cwiseInverse(); + // object->scale(inverse); + object->scale(ratio.cwiseInverse()); + scaled_down = true; + } else if (max_ratio > 5) { + const Vec3d inverse = ratio.cwiseInverse(); + for (ModelInstance *instance : model_object->instances) { + instance->set_scaling_factor(inverse); + } + } } - throw 0; - return 0; + // if user turned autocentering off, automatic arranging would disappoint them + if (get_config("autocenter") != "1") { + need_arrange = false; + } + + if (scaled_down) { + GUI::show_info(q, + _(L("Your object appears to be too large, so it was automatically scaled down to fit your print bed.")), + _(L("Object too large?"))); + } + + for (const size_t idx : obj_idxs) { + const PlaterObject &object = objects[idx]; + ModelObject *model_object = model.objects[idx]; + + // FIXME: ObjetParts not initialized (via add_frequently_changed_parameters) + // GUI::add_object_to_list(object.name, model_object); + } + + if (need_arrange) { + // arrange(); // TODO + } + + update(); + _3DScene::zoom_to_volumes(canvas3D); + // TODO + // $self->object_list_changed; + // $self->schedule_background_process; + + return obj_idxs; } void Plater::priv::on_notebook_changed(wxBookCtrlEvent&) From 40022861c8031bcdf25031d41bd29042a48ca22d Mon Sep 17 00:00:00 2001 From: YuSanka Date: Tue, 2 Oct 2018 13:23:38 +0200 Subject: [PATCH 050/186] Removed Localization to GUI_App + cleaned code from some global variables (App, AppConfig, PresetBundle, MainFrame, tab_panels..) --- src/slic3r/GUI/BackgroundSlicingProcess.cpp | 10 +- src/slic3r/GUI/GUI.cpp | 386 ++------------------ src/slic3r/GUI/GUI.hpp | 39 -- src/slic3r/GUI/GUI_App.cpp | 202 ++++++---- src/slic3r/GUI/GUI_App.hpp | 10 +- src/slic3r/GUI/GUI_ObjectParts.cpp | 15 +- src/slic3r/GUI/MainFrame.cpp | 17 +- src/slic3r/GUI/Preferences.cpp | 14 +- src/slic3r/GUI/Preferences.hpp | 3 +- src/slic3r/GUI/ProgressStatusBar.cpp | 6 +- src/slic3r/GUI/Tab.cpp | 8 +- 11 files changed, 185 insertions(+), 525 deletions(-) diff --git a/src/slic3r/GUI/BackgroundSlicingProcess.cpp b/src/slic3r/GUI/BackgroundSlicingProcess.cpp index 99997e3905..aa6c922aaf 100644 --- a/src/slic3r/GUI/BackgroundSlicingProcess.cpp +++ b/src/slic3r/GUI/BackgroundSlicingProcess.cpp @@ -1,5 +1,5 @@ #include "BackgroundSlicingProcess.hpp" -#include "GUI.hpp" +#include "GUI_App.hpp" #include #include @@ -19,10 +19,6 @@ namespace Slic3r { -namespace GUI { - extern wxPanel *g_wxPlater; -}; - BackgroundSlicingProcess::BackgroundSlicingProcess() { m_temp_output_path = wxStandardPaths::Get().GetTempDir().utf8_str().data(); @@ -59,7 +55,7 @@ void BackgroundSlicingProcess::thread_proc() assert(m_print != nullptr); m_print->process(); if (! m_print->canceled()) { - wxQueueEvent(GUI::g_wxPlater, new wxCommandEvent(m_event_sliced_id)); + wxQueueEvent(GUI::wxGetApp().mainframe->m_plater, new wxCommandEvent(m_event_sliced_id)); m_print->export_gcode(m_temp_output_path, m_gcode_preview_data); if (! m_print->canceled() && ! m_output_path.empty()) { if (copy_file(m_temp_output_path, m_output_path) != 0) @@ -81,7 +77,7 @@ void BackgroundSlicingProcess::thread_proc() wxCommandEvent evt(m_event_finished_id); evt.SetString(error); evt.SetInt(m_print->canceled() ? -1 : (error.empty() ? 1 : 0)); - wxQueueEvent(GUI::g_wxPlater, evt.Clone()); + wxQueueEvent(GUI::wxGetApp().mainframe->m_plater, evt.Clone()); m_print->restart(); lck.unlock(); // Let the UI thread wake up if it is waiting for the background task to finish. diff --git a/src/slic3r/GUI/GUI.cpp b/src/slic3r/GUI/GUI.cpp index 1a4fbb833b..8313f3bdab 100644 --- a/src/slic3r/GUI/GUI.cpp +++ b/src/slic3r/GUI/GUI.cpp @@ -116,21 +116,9 @@ void break_to_debugger() #endif /* _WIN32 */ } -// Passing the wxWidgets GUI classes instantiated by the Perl part to C++. -wxApp *g_wxApp = nullptr; -wxFrame *g_wxMainFrame = nullptr; -ProgressStatusBar *g_progress_status_bar = nullptr; -wxNotebook *g_wxTabPanel = nullptr; -wxPanel *g_wxPlater = nullptr; -AppConfig *g_AppConfig = nullptr; -PresetBundle *g_PresetBundle= nullptr; -PresetUpdater *g_PresetUpdater = nullptr; - // #ys_FIXME_for_delete std::vector g_tabs_list; -wxLocale* g_wxLocale {nullptr}; - std::vector > m_optgroups; double m_brim_width = 0.0; size_t m_label_width = 100; @@ -148,54 +136,6 @@ bool g_show_manifold_warning_icon = false; PreviewIface* g_preview = nullptr; -// static std::string libslic3r_translate_callback(const char *s) { return wxGetTranslation(wxString(s, wxConvUTF8)).utf8_str().data(); } - -void set_wxapp(wxApp *app) -{ - g_wxApp = app; - // Let the libslic3r know the callback, which will translate messages on demand. -// Slic3r::I18N::set_translate_callback(libslic3r_translate_callback); -} - -void set_main_frame(wxFrame *main_frame) -{ - g_wxMainFrame = main_frame; -} - -wxFrame* get_main_frame() { return g_wxMainFrame; } - -void set_progress_status_bar(ProgressStatusBar *prsb) -{ - g_progress_status_bar = prsb; -} - -ProgressStatusBar* get_progress_status_bar() { return g_progress_status_bar; } - -void set_tab_panel(wxNotebook *tab_panel) -{ - g_wxTabPanel = tab_panel; -} - -void set_plater(wxPanel *plater) -{ - g_wxPlater = plater; -} - -void set_app_config(AppConfig *app_config) -{ - g_AppConfig = app_config; -} - -void set_preset_bundle(PresetBundle *preset_bundle) -{ - g_PresetBundle = preset_bundle; -} - -void set_preset_updater(PresetUpdater *updater) -{ - g_PresetUpdater = updater; -} - enum ActionButtons { abExportGCode, @@ -252,245 +192,12 @@ void set_objects_list_sizer(wxBoxSizer *objects_list_sizer){ g_object_list_sizer = objects_list_sizer; } -bool select_language(wxArrayString & names, - wxArrayLong & identifiers) -{ - wxCHECK_MSG(names.Count() == identifiers.Count(), false, - _(L("Array of language names and identifiers should have the same size."))); - int init_selection = 0; - long current_language = g_wxLocale ? g_wxLocale->GetLanguage() : wxLANGUAGE_UNKNOWN; - for (auto lang : identifiers){ - if (lang == current_language) - break; - else - ++init_selection; - } - if (init_selection == identifiers.size()) - init_selection = 0; - long index = wxGetSingleChoiceIndex(_(L("Select the language")), _(L("Language")), - names, init_selection); - if (index != -1) - { - g_wxLocale = new wxLocale; - g_wxLocale->Init(identifiers[index]); - g_wxLocale->AddCatalogLookupPathPrefix(wxPathOnly(localization_dir())); - g_wxLocale->AddCatalog(g_wxApp->GetAppName()); - wxSetlocale(LC_NUMERIC, "C"); - Preset::update_suffix_modified(); - return true; - } - return false; -} - -wxLocale* get_locale() { - return g_wxLocale; -} - -// #ys_FIXME_for_delete -bool load_language() -{ - wxString language = wxEmptyString; - if (g_AppConfig->has("translation_language")) - language = g_AppConfig->get("translation_language"); - - if (language.IsEmpty()) - return false; - wxArrayString names; - wxArrayLong identifiers; - get_installed_languages(names, identifiers); - for (size_t i = 0; i < identifiers.Count(); i++) - { - if (wxLocale::GetLanguageCanonicalName(identifiers[i]) == language) - { - g_wxLocale = new wxLocale; - g_wxLocale->Init(identifiers[i]); - g_wxLocale->AddCatalogLookupPathPrefix(wxPathOnly(localization_dir())); - g_wxLocale->AddCatalog(g_wxApp->GetAppName()); - wxSetlocale(LC_NUMERIC, "C"); - Preset::update_suffix_modified(); - return true; - } - } - return false; -} - -void save_language() -{ - wxString language = wxEmptyString; - if (g_wxLocale) - language = g_wxLocale->GetCanonicalName(); - - g_AppConfig->set("translation_language", language.ToStdString()); - g_AppConfig->save(); -} - -void get_installed_languages(wxArrayString & names, - wxArrayLong & identifiers) -{ - names.Clear(); - identifiers.Clear(); - - wxDir dir(wxPathOnly(localization_dir())); - wxString filename; - const wxLanguageInfo * langinfo; - wxString name = wxLocale::GetLanguageName(wxLANGUAGE_DEFAULT); - if (!name.IsEmpty()) - { - names.Add(_(L("Default"))); - identifiers.Add(wxLANGUAGE_DEFAULT); - } - for (bool cont = dir.GetFirst(&filename, wxEmptyString, wxDIR_DIRS); - cont; cont = dir.GetNext(&filename)) - { - langinfo = wxLocale::FindLanguageInfo(filename); - if (langinfo != NULL) - { - auto full_file_name = dir.GetName() + wxFileName::GetPathSeparator() + - filename + wxFileName::GetPathSeparator() + - g_wxApp->GetAppName() + wxT(".mo"); - if (wxFileExists(full_file_name)) - { - names.Add(langinfo->Description); - identifiers.Add(langinfo->Language); - } - } - } -} - -// enum ConfigMenuIDs { -// ConfigMenuWizard, -// ConfigMenuSnapshots, -// ConfigMenuTakeSnapshot, -// ConfigMenuUpdate, -// ConfigMenuPreferences, -// ConfigMenuModeSimple, -// ConfigMenuModeExpert, -// ConfigMenuLanguage, -// ConfigMenuFlashFirmware, -// ConfigMenuCnt, -// }; - -// #ys_FIXME_for_delete -// ConfigMenuIDs get_view_mode() -// { -// if (!g_AppConfig->has("view_mode")) -// return ConfigMenuModeSimple; -// -// const auto mode = g_AppConfig->get("view_mode"); -// return mode == "expert" ? ConfigMenuModeExpert : ConfigMenuModeSimple; -// } - static wxString dots("…", wxConvUTF8); -// #ys_FIXME_for_delete -/* -void add_config_menu(wxMenuBar *menu, int event_preferences_changed, int event_language_change) -{ - auto local_menu = new wxMenu(); - wxWindowID config_id_base = wxWindow::NewControlId((int)ConfigMenuCnt); - const auto config_wizard_name = _(ConfigWizard::name().wx_str()); - const auto config_wizard_tooltip = wxString::Format(_(L("Run %s")), config_wizard_name); - // Cmd+, is standard on OS X - what about other operating systems? - local_menu->Append(config_id_base + ConfigMenuWizard, config_wizard_name + dots, config_wizard_tooltip); - local_menu->Append(config_id_base + ConfigMenuSnapshots, _(L("Configuration Snapshots"))+dots, _(L("Inspect / activate configuration snapshots"))); - local_menu->Append(config_id_base + ConfigMenuTakeSnapshot, _(L("Take Configuration Snapshot")), _(L("Capture a configuration snapshot"))); -// local_menu->Append(config_id_base + ConfigMenuUpdate, _(L("Check for updates")), _(L("Check for configuration updates"))); - local_menu->AppendSeparator(); - local_menu->Append(config_id_base + ConfigMenuPreferences, _(L("Preferences"))+dots+"\tCtrl+,", _(L("Application preferences"))); - local_menu->AppendSeparator(); - auto mode_menu = new wxMenu(); - mode_menu->AppendRadioItem(config_id_base + ConfigMenuModeSimple, _(L("&Simple")), _(L("Simple View Mode"))); - mode_menu->AppendRadioItem(config_id_base + ConfigMenuModeExpert, _(L("&Expert")), _(L("Expert View Mode"))); - mode_menu->Check(config_id_base + get_view_mode(), true); - local_menu->AppendSubMenu(mode_menu, _(L("&Mode")), _(L("Slic3r View Mode"))); - local_menu->AppendSeparator(); - local_menu->Append(config_id_base + ConfigMenuLanguage, _(L("Change Application Language"))); - local_menu->AppendSeparator(); - local_menu->Append(config_id_base + ConfigMenuFlashFirmware, _(L("Flash printer firmware")), _(L("Upload a firmware image into an Arduino based printer"))); - // TODO: for when we're able to flash dictionaries - // local_menu->Append(config_id_base + FirmwareMenuDict, _(L("Flash language file")), _(L("Upload a language dictionary file into a Prusa printer"))); - - local_menu->Bind(wxEVT_MENU, [config_id_base, event_language_change, event_preferences_changed](wxEvent &event){ - switch (event.GetId() - config_id_base) { - case ConfigMenuWizard: - config_wizard(ConfigWizard::RR_USER); - break; - case ConfigMenuTakeSnapshot: - // Take a configuration snapshot. - if (check_unsaved_changes()) { - wxTextEntryDialog dlg(nullptr, _(L("Taking configuration snapshot")), _(L("Snapshot name"))); - if (dlg.ShowModal() == wxID_OK) - g_AppConfig->set("on_snapshot", - Slic3r::GUI::Config::SnapshotDB::singleton().take_snapshot( - *g_AppConfig, Slic3r::GUI::Config::Snapshot::SNAPSHOT_USER, dlg.GetValue().ToUTF8().data()).id); - } - break; - case ConfigMenuSnapshots: - if (check_unsaved_changes()) { - std::string on_snapshot; - if (Config::SnapshotDB::singleton().is_on_snapshot(*g_AppConfig)) - on_snapshot = g_AppConfig->get("on_snapshot"); - ConfigSnapshotDialog dlg(Slic3r::GUI::Config::SnapshotDB::singleton(), on_snapshot); - dlg.ShowModal(); - if (! dlg.snapshot_to_activate().empty()) { - if (! Config::SnapshotDB::singleton().is_on_snapshot(*g_AppConfig)) - Config::SnapshotDB::singleton().take_snapshot(*g_AppConfig, Config::Snapshot::SNAPSHOT_BEFORE_ROLLBACK); - g_AppConfig->set("on_snapshot", - Config::SnapshotDB::singleton().restore_snapshot(dlg.snapshot_to_activate(), *g_AppConfig).id); - g_PresetBundle->load_presets(*g_AppConfig); - // Load the currently selected preset into the GUI, update the preset selection box. - load_current_presets(); - } - } - break; - case ConfigMenuPreferences: - { - PreferencesDialog dlg(g_wxMainFrame, event_preferences_changed); - dlg.ShowModal(); - break; - } - case ConfigMenuLanguage: - { - wxArrayString names; - wxArrayLong identifiers; - get_installed_languages(names, identifiers); - if (select_language(names, identifiers)) { - save_language(); - show_info(g_wxTabPanel, _(L("Application will be restarted")), _(L("Attention!"))); - if (event_language_change > 0) { - _3DScene::remove_all_canvases();// remove all canvas before recreate GUI - wxCommandEvent event(event_language_change); - g_wxApp->ProcessEvent(event); - } - } - break; - } - case ConfigMenuFlashFirmware: - FirmwareDialog::run(g_wxMainFrame); - break; - default: - break; - } - }); - mode_menu->Bind(wxEVT_MENU, [config_id_base](wxEvent& event) { - std::string mode = event.GetId() - config_id_base == ConfigMenuModeExpert ? - "expert" : "simple"; - g_AppConfig->set("view_mode", mode); - g_AppConfig->save(); - update_mode(); - }); - menu->Append(local_menu, _(L("&Configuration"))); -} - -void add_menus(wxMenuBar *menu, int event_preferences_changed, int event_language_change) -{ - add_config_menu(menu, event_preferences_changed, event_language_change); -} -*/ void open_model(wxWindow *parent, wxArrayString& input_files){ auto dialog = new wxFileDialog(parent /*? parent : GetTopWindow()*/, _(L("Choose one or more files (STL/OBJ/AMF/3MF/PRUSA):")), - g_AppConfig->get_last_dir(), "", + get_app_config()->get_last_dir(), "", MODEL_WILDCARD, wxFD_OPEN | wxFD_MULTIPLE | wxFD_FILE_MUST_EXIST); if (dialog->ShowModal() != wxID_OK) { dialog->Destroy(); @@ -501,36 +208,12 @@ void open_model(wxWindow *parent, wxArrayString& input_files){ dialog->Destroy(); } -// This is called when closing the application, when loading a config file or when starting the config wizard -// to notify the user whether he is aware that some preset changes will be lost. -// #ys_FIXME_for_delete -/* -bool check_unsaved_changes() -{ - std::string dirty; - for (Tab *tab : g_tabs_list) - if (tab->current_preset_is_dirty()) - if (dirty.empty()) - dirty = tab->name(); - else - dirty += std::string(", ") + tab->name(); - if (dirty.empty()) - // No changes, the application may close or reload presets. - return true; - // Ask the user. - auto dialog = new wxMessageDialog(g_wxMainFrame, - _(L("You have unsaved changes ")) + dirty + _(L(". Discard changes and continue anyway?")), - _(L("Unsaved Presets")), - wxICON_QUESTION | wxYES_NO | wxNO_DEFAULT); - return dialog->ShowModal() == wxID_YES; -} -*/ bool config_wizard_startup(bool app_config_exists) { - if (! app_config_exists || g_PresetBundle->printers.size() <= 1) { + if (!app_config_exists || wxGetApp().preset_bundle->printers.size() <= 1) { config_wizard(ConfigWizard::RR_DATA_EMPTY); return true; - } else if (g_AppConfig->legacy_datadir()) { + } else if (get_app_config()->legacy_datadir()) { // Looks like user has legacy pre-vendorbundle data directory, // explain what this is and run the wizard @@ -551,7 +234,7 @@ void config_wizard(int reason) try { ConfigWizard wizard(nullptr, static_cast(reason)); - wizard.run(g_PresetBundle, g_PresetUpdater); + wizard.run(wxGetApp().preset_bundle, wxGetApp().preset_updater); } catch (const std::exception &e) { show_error(nullptr, e.what()); @@ -560,24 +243,7 @@ void config_wizard(int reason) // Load the currently selected preset into the GUI, update the preset selection box. wxGetApp().load_current_presets(); } - -void open_preferences_dialog(int event_preferences) -{ - auto dlg = new PreferencesDialog(g_wxMainFrame, event_preferences); - dlg->ShowModal(); -} - // #ys_FIXME_for_delete -/* -void create_preset_tabs(int event_value_change, int event_presets_changed) -{ - update_label_colours_from_appconfig(); - add_created_tab(new TabPrint (g_wxTabPanel), event_value_change, event_presets_changed); - add_created_tab(new TabFilament (g_wxTabPanel), event_value_change, event_presets_changed); - add_created_tab(new TabSLAMaterial (g_wxTabPanel), event_value_change, event_presets_changed); - add_created_tab(new TabPrinter (g_wxTabPanel), event_value_change, event_presets_changed); -} -*/ std::vector preset_tabs = { { "print", nullptr, ptFFF }, { "filament", nullptr, ptFFF }, @@ -599,8 +265,8 @@ TabIface* get_preset_tab_iface(char *name) Tab* tab = get_tab(name); if (tab) return new TabIface(tab); - for (size_t i = 0; i < g_wxTabPanel->GetPageCount(); ++ i) { - Tab *tab = dynamic_cast(g_wxTabPanel->GetPage(i)); + for (size_t i = 0; i < wxGetApp().tab_panel()->GetPageCount(); ++i) { + Tab *tab = dynamic_cast(wxGetApp().tab_panel()->GetPage(i)); if (! tab) continue; if (tab->name() == name) { @@ -759,22 +425,14 @@ void set_print_callback_event(Print *print, int id) wxCommandEvent event(id); event.SetInt(percent); event.SetString(message); - wxQueueEvent(g_wxMainFrame, event.Clone()); + wxQueueEvent(wxGetApp().mainframe, event.Clone()); }); } -wxApp* get_app(){ - return g_wxApp; -} - wxWindow* get_right_panel(){ return g_right_panel; } -wxNotebook * get_tab_panel() { - return g_wxTabPanel; -} - const size_t& label_width(){ return m_label_width; } @@ -833,7 +491,7 @@ int combochecklist_get_flags(wxComboCtrl* comboCtrl) AppConfig* get_app_config() { - return g_AppConfig; + return wxGetApp().app_config; } wxString L_str(const std::string &str) @@ -875,7 +533,7 @@ void set_model_events_from_perl(Model &model, void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFlexGridSizer* preset_sizer) { - DynamicPrintConfig* config = &g_PresetBundle->prints.get_edited_preset().config; + DynamicPrintConfig* config = &wxGetApp().preset_bundle->prints.get_edited_preset().config; std::shared_ptr optgroup = std::make_shared(parent, "", config); const wxArrayInt& ar = preset_sizer->GetColWidths(); m_label_width = ar.IsEmpty() ? 100 : ar.front()-4; @@ -884,8 +542,8 @@ void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFl //Frequently changed parameters optgroup->m_on_change = [config](t_config_option_key opt_key, boost::any value){ TabPrint* tab_print = nullptr; - for (size_t i = 0; i < g_wxTabPanel->GetPageCount(); ++i) { - Tab *tab = dynamic_cast(g_wxTabPanel->GetPage(i)); + for (size_t i = 0; i < wxGetApp().tab_panel()->GetPageCount(); ++i) { + Tab *tab = dynamic_cast(wxGetApp().tab_panel()->GetPage(i)); if (!tab) continue; if (tab->name() == "print"){ @@ -976,7 +634,7 @@ void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFl sizer->Add(g_wiping_dialog_button); g_wiping_dialog_button->Bind(wxEVT_BUTTON, ([parent](wxCommandEvent& e) { - auto &config = g_PresetBundle->project_config; + auto &config = wxGetApp().preset_bundle->project_config; const std::vector &init_matrix = (config.option("wiping_volumes_matrix"))->values; const std::vector &init_extruders = (config.option("wiping_volumes_extruders"))->values; @@ -1010,8 +668,8 @@ void show_frequently_changed_parameters(bool show) g_frequently_changed_parameters_sizer->Show(show); if (!show) return; - for (size_t i = 0; i < g_wxTabPanel->GetPageCount(); ++i) { - Tab *tab = dynamic_cast(g_wxTabPanel->GetPage(i)); + for (size_t i = 0; i < wxGetApp().tab_panel()->GetPageCount(); ++i) { + Tab *tab = dynamic_cast(wxGetApp().tab_panel()->GetPage(i)); if (!tab) continue; tab->update_wiping_button_visibility(); @@ -1022,11 +680,11 @@ void show_frequently_changed_parameters(bool show) void show_buttons(bool show) { g_buttons[abReslice]->Show(show); - for (size_t i = 0; i < g_wxTabPanel->GetPageCount(); ++i) { - TabPrinter *tab = dynamic_cast(g_wxTabPanel->GetPage(i)); + for (size_t i = 0; i < wxGetApp().tab_panel()->GetPageCount(); ++i) { + TabPrinter *tab = dynamic_cast(wxGetApp().tab_panel()->GetPage(i)); if (!tab) continue; - if (g_PresetBundle->printers.get_selected_preset().printer_technology() == ptFFF) { + if (wxGetApp().preset_bundle->printers.get_selected_preset().printer_technology() == ptFFF) { g_buttons[abPrint]->Show(show && !tab->m_config->opt_string("serial_port").empty()); g_buttons[abSendGCode]->Show(show && !tab->m_config->opt_string("print_host").empty()); } @@ -1154,8 +812,8 @@ void save_window_size(wxTopLevelWindow *window, const std::string &name) const wxPoint pos = window->GetPosition(); const auto maximized = window->IsMaximized() ? "1" : "0"; - g_AppConfig->set((boost::format("window_%1%_size") % name).str(), (boost::format("%1%;%2%") % size.GetWidth() % size.GetHeight()).str()); - g_AppConfig->set((boost::format("window_%1%_maximized") % name).str(), maximized); + get_app_config()->set((boost::format("window_%1%_size") % name).str(), (boost::format("%1%;%2%") % size.GetWidth() % size.GetHeight()).str()); + get_app_config()->set((boost::format("window_%1%_maximized") % name).str(), maximized); } void restore_window_size(wxTopLevelWindow *window, const std::string &name) @@ -1174,8 +832,8 @@ void restore_window_size(wxTopLevelWindow *window, const std::string &name) try { const auto key_size = (boost::format("window_%1%_size") % name).str(); - if (g_AppConfig->has(key_size)) { - if (unescape_strings_cstyle(g_AppConfig->get(key_size), pair) && pair.size() == 2) { + if (get_app_config()->has(key_size)) { + if (unescape_strings_cstyle(get_app_config()->get(key_size), pair) && pair.size() == 2) { auto width = boost::lexical_cast(pair[0]); auto height = boost::lexical_cast(pair[1]); @@ -1187,7 +845,7 @@ void restore_window_size(wxTopLevelWindow *window, const std::string &name) // Maximizing should be the last thing to do. // This ensure the size and position are sane when the user un-maximizes the window. const auto key_maximized = (boost::format("window_%1%_maximized") % name).str(); - if (g_AppConfig->get(key_maximized) == "1") { + if (get_app_config()->get(key_maximized) == "1") { window->Maximize(true); } } diff --git a/src/slic3r/GUI/GUI.hpp b/src/slic3r/GUI/GUI.hpp index 83f9542486..215a72b608 100644 --- a/src/slic3r/GUI/GUI.hpp +++ b/src/slic3r/GUI/GUI.hpp @@ -104,32 +104,11 @@ void enable_screensaver(); bool debugged(); void break_to_debugger(); -// Passing the wxWidgets GUI classes instantiated by the Perl part to C++. -void set_wxapp(wxApp *app); -void set_main_frame(wxFrame *main_frame); -void set_progress_status_bar(ProgressStatusBar *prsb); -void set_tab_panel(wxNotebook *tab_panel); -void set_plater(wxPanel *plater); -void set_app_config(AppConfig *app_config); -void set_preset_bundle(PresetBundle *preset_bundle); -void set_preset_updater(PresetUpdater *updater); -void set_objects_from_perl( wxWindow* parent, - wxBoxSizer *frequently_changed_parameters_sizer, - wxBoxSizer *info_sizer, - wxButton *btn_export_gcode, - wxButton *btn_reslice, - wxButton *btn_print, - wxButton *btn_send_gcode, - wxStaticBitmap *manifold_warning_icon); void set_show_print_info(bool show); void set_show_manifold_warning_icon(bool show); void set_objects_list_sizer(wxBoxSizer *objects_list_sizer); AppConfig* get_app_config(); -wxApp* get_app(); -wxFrame* get_main_frame(); -ProgressStatusBar* get_progress_status_bar(); -wxNotebook* get_tab_panel(); AppControllerPtr get_appctl(); void set_cli_appctl(); @@ -145,10 +124,6 @@ std::vector* get_preset_tabs(); extern void add_menus(wxMenuBar *menu, int event_preferences_changed, int event_language_change); -// This is called when closing the application, when loading a config file or when starting the config wizard -// to notify the user whether he is aware that some preset changes will be lost. -// extern bool check_unsaved_changes(); - // Checks if configuration wizard needs to run, calls config_wizard if so. // Returns whether the Wizard ran. extern bool config_wizard_startup(bool app_config_exists); @@ -157,11 +132,6 @@ extern bool config_wizard_startup(bool app_config_exists); // The run_reason argument is actually ConfigWizard::RunReason, but int is used here because of Perl. extern void config_wizard(int run_reason); -// Create "Preferences" dialog after selecting menu "Preferences" in Perl part -extern void open_preferences_dialog(int event_preferences); - -// Create a new preset tab (print, filament and printer), -// void create_preset_tabs(int event_value_change, int event_presets_changed); TabIface* get_preset_tab_iface(char *name); PreviewIface* create_preview_iface(wxNotebook* notebook, DynamicPrintConfig* config, Print* print, GCodePreviewData* gcode_preview_data); @@ -180,15 +150,6 @@ void warning_catcher(wxWindow* parent, const wxString& message); // to deliver a progress status message. void set_print_callback_event(Print *print, int id); -// load language saved at application config -wxLocale* get_locale(); -bool load_language(); -// save language at application config -void save_language(); -// get list of installed languages -void get_installed_languages(wxArrayString & names, wxArrayLong & identifiers); -// select language from the list of installed languages -bool select_language(wxArrayString & names, wxArrayLong & identifiers); // update right panel of the Plater according to view mode void update_mode(); diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 6bca605686..4407c44c1d 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -10,10 +10,10 @@ #include #include #include +#include #include "Utils.hpp" #include "GUI.hpp" -#include "MainFrame.hpp" #include "AppConfig.hpp" #include "PresetBundle.hpp" #include "3DScene.hpp" @@ -48,9 +48,7 @@ bool GUI_App::OnInit() set_data_dir(wxStandardPaths::Get().GetUserDataDir().ToUTF8().data()); app_config = new AppConfig(); - set_app_config(app_config); preset_bundle = new PresetBundle(); - set_preset_bundle(preset_bundle); // just checking for existence of Slic3r::data_dir is not enough : it may be an empty directory // supplied as argument to --datadir; in that case we should still run the wizard @@ -68,7 +66,6 @@ bool GUI_App::OnInit() app_config->save(); preset_updater = new PresetUpdater(); - set_preset_updater(preset_updater); load_language(); @@ -92,74 +89,56 @@ bool GUI_App::OnInit() std::cerr << "Creating main frame..." << std::endl; // wxImage::FindHandlerType(wxBITMAP_TYPE_PNG) || wxImage::AddHandler(new wxPNGHandler()); - mainframe = new Slic3r::GUI::MainFrame(no_plater, false); + mainframe = new MainFrame(no_plater, false); SetTopWindow(mainframe); // This makes CallAfter() work - // /*mainframe->*/Bind(wxEVT_IDLE, -// [this](wxIdleEvent& event) -// { -// std::function cur_cb{ nullptr }; -// // try to get the mutex. If we can't, just skip this idle event and get the next one. -// if (!callback_register.try_lock()) return; -// // pop callback -// if (m_cb.size() != 0){ -// cur_cb = m_cb.top(); -// m_cb.pop(); -// } -// // unlock mutex -// this->callback_register.unlock(); -// -// try { // call the function if it's not nullptr; -// if (cur_cb != nullptr) cur_cb(); -// } -// catch (std::exception& e) { -// // Slic3r::Log::error(LogChannel, LOG_WSTRING("Exception thrown: " << e.what())); // #ys_FIXME -// } -// -// if (app_config->dirty()) -// app_config->save(); -// } - ;// #ys_FIXME - // ); + Bind(wxEVT_IDLE, [this](wxIdleEvent& event) + { + std::function cur_cb{ nullptr }; + // try to get the mutex. If we can't, just skip this idle event and get the next one. + if (!callback_register.try_lock()) return; + // pop callback + if (m_cb.size() != 0){ + cur_cb = m_cb.top(); + m_cb.pop(); + } + // unlock mutex + this->callback_register.unlock(); + + try { // call the function if it's not nullptr; + if (cur_cb != nullptr) cur_cb(); + } + catch (std::exception& e) { + std::cerr << "Exception thrown: " << e.what() << std::endl; + } + + if (app_config->dirty()) + app_config->save(); + }); // On OS X the UI tends to freeze in weird ways if modal dialogs(config wizard, update notifications, ...) // are shown before or in the same event callback with the main frame creation. // Therefore we schedule them for later using CallAfter. -// CallAfter([this](){ -// // eval{ -// if (!preset_updater->config_update()) -// mainframe->Close(); -// // }; -// // if ($@) { -// // show_error(undef, $@); -// // mainframe->Close(); -// // } -// }); -// -// CallAfter([this](){ -// if (!Slic3r::GUI::config_wizard_startup(app_conf_exists)) { -// // Only notify if there was not wizard so as not to bother too much ... -// preset_updater->slic3r_update_notify(); -// } -// preset_updater->sync(preset_bundle); -// }); -// + CallAfter([this](){ + // eval{ + if (!preset_updater->config_update()) + mainframe->Close(); + // }; + // if ($@) { + // show_error(undef, $@); + // mainframe->Close(); + // } + }); + + CallAfter([this](){ + if (!config_wizard_startup(app_conf_exists)) { + // Only notify if there was not wizard so as not to bother too much ... + preset_updater->slic3r_update_notify(); + } + preset_updater->sync(preset_bundle); + }); - // #ys_FIXME All of this should to be removed - // # The following event is emited by the C++ menu implementation of preferences change. - // EVT_COMMAND($self, -1, $PREFERENCES_EVENT, sub{ - // $self->update_ui_from_settings; - // }); - // - // # The following event is emited by PresetUpdater(C++) to inform about - // # the newer Slic3r application version avaiable online. - // EVT_COMMAND($self, -1, $VERSION_ONLINE_EVENT, sub { - // my($self, $event) = @_; - // my $version = $event->GetString; - // $self->{app_config}->set('version_online', $version); - // $self->{app_config}->save; - // }); mainframe->Show(true); return true; @@ -238,7 +217,7 @@ void GUI_App::recreate_GUI() std::cerr << "recreate_GUI" << std::endl; auto topwindow = GetTopWindow(); - mainframe = new Slic3r::GUI::MainFrame(no_plater,false); + mainframe = new MainFrame(no_plater,false); if (topwindow) { SetTopWindow(mainframe); @@ -249,7 +228,7 @@ void GUI_App::recreate_GUI() // before the UI was up and running. CallAfter([](){ // Run the config wizard, don't offer the "reset user profile" checkbox. - Slic3r::GUI::config_wizard_startup(true); + config_wizard_startup(true); }); } @@ -374,7 +353,8 @@ void GUI_App::save_window_pos(wxTopLevelWindow* window, const std::string& name) app_config->save(); } -void GUI_App::restore_window_pos(wxTopLevelWindow* window, const std::string& name){ +void GUI_App::restore_window_pos(wxTopLevelWindow* window, const std::string& name) +{ if (!app_config->has(name + "_pos")) return; @@ -397,6 +377,37 @@ void GUI_App::restore_window_pos(wxTopLevelWindow* window, const std::string& na window->Maximize(); } +// select language from the list of installed languages +bool GUI_App::select_language( wxArrayString & names, + wxArrayLong & identifiers) +{ + wxCHECK_MSG(names.Count() == identifiers.Count(), false, + _(L("Array of language names and identifiers should have the same size."))); + int init_selection = 0; + long current_language = m_wxLocale ? m_wxLocale->GetLanguage() : wxLANGUAGE_UNKNOWN; + for (auto lang : identifiers){ + if (lang == current_language) + break; + ++init_selection; + } + if (init_selection == identifiers.size()) + init_selection = 0; + long index = wxGetSingleChoiceIndex(_(L("Select the language")), _(L("Language")), + names, init_selection); + if (index != -1) + { + m_wxLocale = new wxLocale; + m_wxLocale->Init(identifiers[index]); + m_wxLocale->AddCatalogLookupPathPrefix(localization_dir()); + m_wxLocale->AddCatalog(GetAppName()); + wxSetlocale(LC_NUMERIC, "C"); + Preset::update_suffix_modified(); + return true; + } + return false; +} + +// load language saved at application config bool GUI_App::load_language() { wxString language = wxEmptyString; @@ -412,11 +423,10 @@ bool GUI_App::load_language() { if (wxLocale::GetLanguageCanonicalName(identifiers[i]) == language) { - auto locale = get_locale(); - locale = new wxLocale; - locale->Init(identifiers[i]); - locale->AddCatalogLookupPathPrefix(wxPathOnly(localization_dir())); - locale->AddCatalog(GetAppName()); + m_wxLocale = new wxLocale; + m_wxLocale->Init(identifiers[i]); + m_wxLocale->AddCatalogLookupPathPrefix(localization_dir()); + m_wxLocale->AddCatalog(GetAppName()); wxSetlocale(LC_NUMERIC, "C"); Preset::update_suffix_modified(); return true; @@ -425,6 +435,50 @@ bool GUI_App::load_language() return false; } +// save language at application config +void GUI_App::save_language() +{ + wxString language = wxEmptyString; + if (m_wxLocale) + language = m_wxLocale->GetCanonicalName(); + + app_config->set("translation_language", language.ToStdString()); + app_config->save(); +} + +// get list of installed languages +void GUI_App::get_installed_languages(wxArrayString & names, wxArrayLong & identifiers) +{ + names.Clear(); + identifiers.Clear(); + + wxDir dir(localization_dir()); + wxString filename; + const wxLanguageInfo * langinfo; + wxString name = wxLocale::GetLanguageName(wxLANGUAGE_DEFAULT); + if (!name.IsEmpty()) + { + names.Add(_(L("Default"))); + identifiers.Add(wxLANGUAGE_DEFAULT); + } + for (bool cont = dir.GetFirst(&filename, wxEmptyString, wxDIR_DIRS); + cont; cont = dir.GetNext(&filename)) + { + langinfo = wxLocale::FindLanguageInfo(filename); + if (langinfo != NULL) + { + auto full_file_name = dir.GetName() + wxFileName::GetPathSeparator() + + filename + wxFileName::GetPathSeparator() + + GetAppName() + wxT(".mo"); + if (wxFileExists(full_file_name)) + { + names.Add(langinfo->Description); + identifiers.Add(langinfo->Language); + } + } + } +} + ConfigMenuIDs GUI_App::get_view_mode() { if (!app_config->has("view_mode")) @@ -498,8 +552,8 @@ void GUI_App::add_config_menu(wxMenuBar *menu) break; case ConfigMenuPreferences: { -// PreferencesDialog dlg(mainframe, event_preferences_changed); -// dlg.ShowModal(); + PreferencesDialog dlg(mainframe); + dlg.ShowModal(); break; } case ConfigMenuLanguage: diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index a6e2cdc7a9..d6d085166b 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -4,6 +4,7 @@ #include // #include #include "PrintConfig.hpp" +#include "MainFrame.hpp" // #include "../../libslic3r/Utils.hpp" // #include "GUI.hpp" @@ -39,7 +40,6 @@ enum ConfigMenuIDs { ConfigMenuCnt, }; -class MainFrame; class Tab; class GUI_App : public wxApp @@ -61,7 +61,7 @@ class GUI_App : public wxApp // #ys_FIXME // std::vector g_tabs_list; -// wxLocale* g_wxLocale{ nullptr }; + wxLocale* m_wxLocale{ nullptr }; public: bool OnInit() override; @@ -105,8 +105,14 @@ public: const std::string& icon); void save_window_pos(wxTopLevelWindow* window, const std::string& name); void restore_window_pos(wxTopLevelWindow* window, const std::string& name); + + bool select_language(wxArrayString & names, wxArrayLong & identifiers); bool load_language(); + void save_language(); + void get_installed_languages(wxArrayString & names, wxArrayLong & identifiers); + ConfigMenuIDs get_view_mode(); + void add_config_menu(wxMenuBar *menu); bool check_unsaved_changes(); bool checked_tab(Tab* tab); diff --git a/src/slic3r/GUI/GUI_ObjectParts.cpp b/src/slic3r/GUI/GUI_ObjectParts.cpp index d27494617a..fc36e7fdb5 100644 --- a/src/slic3r/GUI/GUI_ObjectParts.cpp +++ b/src/slic3r/GUI/GUI_ObjectParts.cpp @@ -758,9 +758,8 @@ void remove() if (m_objects_model->GetParent(item) == wxDataViewItem(0)) { if (m_event_remove_object > 0) { wxCommandEvent event(m_event_remove_object); - get_main_frame()->ProcessWindowEvent(event); +// get_main_frame()->ProcessWindowEvent(event); // #ys_FIXME } -// delete_object_from_list(); } else on_btn_del(); @@ -785,7 +784,7 @@ void object_ctrl_selection_changed() else event.SetInt(vol_idx); } - get_main_frame()->ProcessWindowEvent(event); +// get_main_frame()->ProcessWindowEvent(event); // #ys_FIXME } #ifdef __WXOSX__ @@ -1194,8 +1193,8 @@ void show_context_menu() const auto menu = m_objects_model->GetParent(item) == wxDataViewItem(0) ? create_add_part_popupmenu() : create_part_settings_popupmenu(); - get_tab_panel()->GetPage(0)->PopupMenu(menu); - } + wxGetApp().tab_panel()->GetPage(0)->PopupMenu(menu); + } } // ****** @@ -1203,7 +1202,7 @@ void show_context_menu() void load_part( ModelObject* model_object, wxArrayString& part_names, const bool is_modifier) { - wxWindow* parent = get_tab_panel()->GetPage(0); + wxWindow* parent = wxGetApp().tab_panel()->GetPage(0); wxArrayString input_files; open_model(parent, input_files); @@ -1550,7 +1549,7 @@ void parts_changed(int obj_idx) is_parts_changed() ? 1 : 0, is_part_settings_changed() ? 1 : 0); e.SetString(event_str); - get_main_frame()->ProcessWindowEvent(e); +// get_main_frame()->ProcessWindowEvent(e); // #ys_FIXME } void update_settings_value() @@ -1741,7 +1740,7 @@ void update_extruder_in_config(const wxString& selection) if (m_event_update_scene > 0) { wxCommandEvent e(m_event_update_scene); - get_main_frame()->ProcessWindowEvent(e); +// get_main_frame()->ProcessWindowEvent(e); // #ys_FIXME } } diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 1aba0f7c7f..23e7e07933 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -30,7 +30,6 @@ wxFrame(NULL, wxID_ANY, SLIC3R_BUILD, wxDefaultPosition, wxDefaultSize, wxDEFAUL m_no_plater(no_plater), m_loaded(loaded) { -// Slic3r::GUI::set_main_frame(this); m_appController = new Slic3r::AppController(); // Load the icon either from the exe, or from the ico file. @@ -54,7 +53,7 @@ wxFrame(NULL, wxID_ANY, SLIC3R_BUILD, wxDefaultPosition, wxDefaultSize, wxDEFAUL wxToolTip::SetAutoPop(32767); // initialize status bar - m_statusbar = new Slic3r::GUI::ProgressStatusBar(this); + m_statusbar = new ProgressStatusBar(this); m_statusbar->embed(this); m_statusbar->set_status_text(_(L("Version ")) + SLIC3R_VERSION + @@ -102,8 +101,8 @@ wxFrame(NULL, wxID_ANY, SLIC3R_BUILD, wxDefaultPosition, wxDefaultSize, wxDEFAUL event.Skip(); }); -// update_ui_from_settings(); -// + update_ui_from_settings(); + // Slic3r::GUI::update_mode(); return; @@ -112,15 +111,13 @@ wxFrame(NULL, wxID_ANY, SLIC3R_BUILD, wxDefaultPosition, wxDefaultSize, wxDEFAUL void MainFrame::init_tabpanel() { m_tabpanel = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_TOP | wxTAB_TRAVERSAL); -// Slic3r::GUI::set_tab_panel(m_tabpanel); m_tabpanel->Bind(wxEVT_NOTEBOOK_PAGE_CHANGED, [this](wxEvent&){ auto panel = m_tabpanel->GetCurrentPage(); // panel->OnActivate(); if panel->can('OnActivate'); - if (panel == nullptr) { + if (panel == nullptr) return; - } for (auto& tab_name : { "print", "filament", "printer" }) { if (tab_name == panel->GetName()) { @@ -136,12 +133,6 @@ void MainFrame::init_tabpanel() if (!m_no_plater) { m_plater = new Slic3r::GUI::Plater(m_tabpanel, this); - // m_plater = new Slic3r::GUI::Plater(m_tabpanel, - // event_object_selection_changed = > $OBJECT_SELECTION_CHANGED_EVENT, - // event_object_settings_changed = > $OBJECT_SETTINGS_CHANGED_EVENT, - // event_remove_object = > $OBJECT_REMOVE_EVENT, - // event_update_scene = > $UPDATE_SCENE_EVENT, - // ), L("Plater") m_tabpanel->AddPage(m_plater, _(L("Plater"))); } diff --git a/src/slic3r/GUI/Preferences.cpp b/src/slic3r/GUI/Preferences.cpp index 89a8ead925..2037572da3 100644 --- a/src/slic3r/GUI/Preferences.cpp +++ b/src/slic3r/GUI/Preferences.cpp @@ -5,11 +5,10 @@ namespace Slic3r { namespace GUI { -PreferencesDialog::PreferencesDialog(wxWindow* parent, int event_preferences) : - wxDialog(parent, wxID_ANY, _(L("Preferences")), wxDefaultPosition, wxDefaultSize), - m_event_preferences(event_preferences) { - build(); - } +PreferencesDialog::PreferencesDialog(wxWindow* parent) : + wxDialog(parent, wxID_ANY, _(L("Preferences")), wxDefaultPosition, wxDefaultSize) { + build(); +} void PreferencesDialog::build() { @@ -124,10 +123,7 @@ void PreferencesDialog::accept() Close(); // needed on Linux // Nothify the UI to update itself from the ini file. - if (m_event_preferences > 0) { - wxCommandEvent event(m_event_preferences); - get_app()->ProcessEvent(event); - } + wxGetApp().update_ui_from_settings(); } } // GUI diff --git a/src/slic3r/GUI/Preferences.hpp b/src/slic3r/GUI/Preferences.hpp index d01d78b70b..0b1dd57308 100644 --- a/src/slic3r/GUI/Preferences.hpp +++ b/src/slic3r/GUI/Preferences.hpp @@ -15,9 +15,8 @@ class PreferencesDialog : public wxDialog { std::map m_values; std::shared_ptr m_optgroup; - int m_event_preferences; public: - PreferencesDialog(wxWindow* parent, int event_preferences); + PreferencesDialog(wxWindow* parent); ~PreferencesDialog(){ } void build(); diff --git a/src/slic3r/GUI/ProgressStatusBar.cpp b/src/slic3r/GUI/ProgressStatusBar.cpp index d92b63cfe5..45c3aaa76b 100644 --- a/src/slic3r/GUI/ProgressStatusBar.cpp +++ b/src/slic3r/GUI/ProgressStatusBar.cpp @@ -5,14 +5,14 @@ #include #include #include -#include "GUI.hpp" +#include "GUI_App.hpp" #include namespace Slic3r { ProgressStatusBar::ProgressStatusBar(wxWindow *parent, int id): - self(new wxStatusBar(parent ? parent : GUI::get_main_frame(), + self(new wxStatusBar(parent ? parent : GUI::wxGetApp().mainframe, id == -1? wxID_ANY : id)), m_timer(new wxTimer(self)), m_prog (new wxGauge(self, @@ -130,7 +130,7 @@ void ProgressStatusBar::run(int rate) void ProgressStatusBar::embed(wxFrame *frame) { - wxFrame* mf = frame ? frame : GUI::get_main_frame(); + wxFrame* mf = frame ? frame : GUI::wxGetApp().mainframe; mf->SetStatusBar(self); } diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index e4a1f5933b..c83fd6df5b 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -662,7 +662,7 @@ void Tab::load_key_value(const std::string& opt_key, const boost::any& value, bo update(); } -extern wxFrame *g_wxMainFrame; +// extern wxFrame *g_wxMainFrame; // #ys_FIXME void Tab::on_value_change(const std::string& opt_key, const boost::any& value) { @@ -680,11 +680,11 @@ void Tab::on_value_change(const std::string& opt_key, const boost::any& value) { int val = boost::any_cast(value); event.SetInt(val); - g_wxMainFrame->ProcessWindowEvent(event); +// g_wxMainFrame->ProcessWindowEvent(event);// #ys_FIXME return; } - g_wxMainFrame->ProcessWindowEvent(event); +// g_wxMainFrame->ProcessWindowEvent(event);// #ys_FIXME } if (opt_key == "fill_density") { @@ -737,7 +737,7 @@ void Tab::on_presets_changed() if (m_event_presets_changed > 0) { wxCommandEvent event(m_event_presets_changed); event.SetString(m_name); - g_wxMainFrame->ProcessWindowEvent(event); +// g_wxMainFrame->ProcessWindowEvent(event); // #ys_FIXME } update_preset_description_line(); } From 01ba59158df082de5219c37b1406c49fe0e9aa37 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Tue, 2 Oct 2018 14:01:22 +0200 Subject: [PATCH 051/186] Multisample detection --- src/slic3r/GUI/GLCanvas3DManager.cpp | 36 +++++++++++++++++----------- src/slic3r/GUI/GLCanvas3DManager.hpp | 12 +++++++++- 2 files changed, 33 insertions(+), 15 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3DManager.cpp b/src/slic3r/GUI/GLCanvas3DManager.cpp index 643171a17d..09821f8539 100644 --- a/src/slic3r/GUI/GLCanvas3DManager.cpp +++ b/src/slic3r/GUI/GLCanvas3DManager.cpp @@ -110,6 +110,8 @@ std::string GLCanvas3DManager::GLInfo::to_string(bool format_as_html, bool exten return out.str(); } +GLCanvas3DManager::EMultisampleState GLCanvas3DManager::s_multisample = GLCanvas3DManager::MS_Unknown; + GLCanvas3DManager::GLCanvas3DManager() : m_current(nullptr) , m_gl_initialized(false) @@ -827,24 +829,17 @@ void GLCanvas3DManager::register_action_selectbyparts_callback(wxGLCanvas* canva it->second->register_action_selectbyparts_callback(callback); } -bool GLCanvas3DManager::can_multisample() -{ - int wxVersion = wxMAJOR_VERSION * 10000 + wxMINOR_VERSION * 100 + wxRELEASE_NUMBER; - const AppConfig* app_config = GUI::get_app_config(); - bool enable_multisample = app_config != nullptr - && app_config->get("use_legacy_opengl") != "1" - && wxVersion >= 30003; - - // if multisample is not enabled or supported by the graphic card, remove it from the attributes list - return enable_multisample && wxGLCanvas::IsExtensionSupported("WGL_ARB_multisample"); - // <<< Alternative method: but IsDisplaySupported() seems not to work - // bool return enable_multisample && wxGLCanvas::IsDisplaySupported(attribList); -} - wxGLCanvas* GLCanvas3DManager::create_wxglcanvas(wxWindow *parent) { int attribList[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER, WX_GL_DEPTH_SIZE, 24, WX_GL_SAMPLE_BUFFERS, GL_TRUE, WX_GL_SAMPLES, 4, 0 }; + if (s_multisample == MS_Unknown) + { + _detect_multisample(attribList); + // debug output + std::cout << "Multisample " << (can_multisample() ? "enabled" : "disabled") << std::endl; + } + if (! can_multisample()) { attribList[4] = 0; } @@ -870,5 +865,18 @@ bool GLCanvas3DManager::_init(GLCanvas3D& canvas) return canvas.init(m_use_VBOs, m_use_legacy_opengl); } +void GLCanvas3DManager::_detect_multisample(int* attribList) +{ + int wxVersion = wxMAJOR_VERSION * 10000 + wxMINOR_VERSION * 100 + wxRELEASE_NUMBER; + const AppConfig* app_config = GUI::get_app_config(); + bool enable_multisample = app_config != nullptr + && app_config->get("use_legacy_opengl") != "1" + && wxVersion >= 30003; + + s_multisample = (enable_multisample && wxGLCanvas::IsDisplaySupported(attribList)) ? MS_Enabled : MS_Disabled; + // Alternative method: it was working on previous version of wxWidgets but not with the latest, at least on Windows + // s_multisample = enable_multisample && wxGLCanvas::IsExtensionSupported("WGL_ARB_multisample"); +} + } // namespace GUI } // namespace Slic3r diff --git a/src/slic3r/GUI/GLCanvas3DManager.hpp b/src/slic3r/GUI/GLCanvas3DManager.hpp index c833de397f..4525845502 100644 --- a/src/slic3r/GUI/GLCanvas3DManager.hpp +++ b/src/slic3r/GUI/GLCanvas3DManager.hpp @@ -42,6 +42,13 @@ class GLCanvas3DManager std::string to_string(bool format_as_html, bool extensions) const; }; + enum EMultisampleState : unsigned char + { + MS_Unknown, + MS_Enabled, + MS_Disabled + }; + typedef std::map CanvasesMap; CanvasesMap m_canvases; @@ -50,6 +57,7 @@ class GLCanvas3DManager bool m_gl_initialized; bool m_use_legacy_opengl; bool m_use_VBOs; + static EMultisampleState s_multisample; public: GLCanvas3DManager(); @@ -187,13 +195,15 @@ public: void register_action_layersediting_callback(wxGLCanvas* canvas, void* callback); void register_action_selectbyparts_callback(wxGLCanvas* canvas, void* callback); - static bool can_multisample(); + static bool can_multisample() { return s_multisample == MS_Enabled; } static wxGLCanvas* create_wxglcanvas(wxWindow *parent); + private: CanvasesMap::iterator _get_canvas(wxGLCanvas* canvas); CanvasesMap::const_iterator _get_canvas(wxGLCanvas* canvas) const; bool _init(GLCanvas3D& canvas); + static void _detect_multisample(int* attribList); }; } // namespace GUI From 7977bce98d6d85a93af52a12d3aab41e6e7c483f Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Tue, 2 Oct 2018 14:12:23 +0200 Subject: [PATCH 052/186] Fixed call to reset_legend_texture() made on hidden canvas --- src/slic3r/GUI/3DScene.cpp | 4 ++-- src/slic3r/GUI/3DScene.hpp | 2 +- src/slic3r/GUI/GLCanvas3DManager.cpp | 10 ++++------ src/slic3r/GUI/GLCanvas3DManager.hpp | 2 +- src/slic3r/GUI/GUI_Preview.cpp | 10 ++++++---- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index 3eb1746941..744275e227 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -2293,9 +2293,9 @@ void _3DScene::load_preview(wxGLCanvas* canvas, const std::vector& s_canvas_mgr.load_preview(canvas, str_tool_colors); } -void _3DScene::reset_legend_texture() +void _3DScene::reset_legend_texture(wxGLCanvas* canvas) { - s_canvas_mgr.reset_legend_texture(); + s_canvas_mgr.reset_legend_texture(canvas); } } // namespace Slic3r diff --git a/src/slic3r/GUI/3DScene.hpp b/src/slic3r/GUI/3DScene.hpp index 484d6028d1..a5f4c51899 100644 --- a/src/slic3r/GUI/3DScene.hpp +++ b/src/slic3r/GUI/3DScene.hpp @@ -602,7 +602,7 @@ public: static void load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* preview_data, const std::vector& str_tool_colors); static void load_preview(wxGLCanvas* canvas, const std::vector& str_tool_colors); - static void reset_legend_texture(); + static void reset_legend_texture(wxGLCanvas* canvas); static void thick_lines_to_verts(const Lines& lines, const std::vector& widths, const std::vector& heights, bool closed, double top_z, GLVolume& volume); static void thick_lines_to_verts(const Lines3& lines, const std::vector& widths, const std::vector& heights, bool closed, GLVolume& volume); diff --git a/src/slic3r/GUI/GLCanvas3DManager.cpp b/src/slic3r/GUI/GLCanvas3DManager.cpp index 09821f8539..771aa159e0 100644 --- a/src/slic3r/GUI/GLCanvas3DManager.cpp +++ b/src/slic3r/GUI/GLCanvas3DManager.cpp @@ -580,13 +580,11 @@ void GLCanvas3DManager::load_preview(wxGLCanvas* canvas, const std::vectorsecond->load_preview(str_tool_colors); } -void GLCanvas3DManager::reset_legend_texture() +void GLCanvas3DManager::reset_legend_texture(wxGLCanvas* canvas) { - for (CanvasesMap::value_type& canvas : m_canvases) - { - if (canvas.second != nullptr) - canvas.second->reset_legend_texture(); - } + CanvasesMap::iterator it = _get_canvas(canvas); + if (it != m_canvases.end()) + it->second->reset_legend_texture(); } void GLCanvas3DManager::register_on_viewport_changed_callback(wxGLCanvas* canvas, void* callback) diff --git a/src/slic3r/GUI/GLCanvas3DManager.hpp b/src/slic3r/GUI/GLCanvas3DManager.hpp index 4525845502..d3b7b177cc 100644 --- a/src/slic3r/GUI/GLCanvas3DManager.hpp +++ b/src/slic3r/GUI/GLCanvas3DManager.hpp @@ -154,7 +154,7 @@ public: void load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* preview_data, const std::vector& str_tool_colors); void load_preview(wxGLCanvas* canvas, const std::vector& str_tool_colors); - void reset_legend_texture(); + void reset_legend_texture(wxGLCanvas* canvas); void register_on_viewport_changed_callback(wxGLCanvas* canvas, void* callback); void register_on_double_click_callback(wxGLCanvas* canvas, void* callback); diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index c70a6080c2..fc3d362e96 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -214,7 +214,8 @@ void Preview::set_number_extruders(unsigned int number_extruders) void Preview::reset_gcode_preview_data() { m_gcode_preview_data->reset(); - _3DScene::reset_legend_texture(); + if (m_canvas != nullptr) + _3DScene::reset_legend_texture(m_canvas); } void Preview::set_canvas_as_dirty() @@ -290,10 +291,11 @@ void Preview::load_print() if (n_layers == 0) { reset_sliders(); - _3DScene::reset_legend_texture(); - if (m_canvas) + if (m_canvas != nullptr) + { + _3DScene::reset_legend_texture(m_canvas); m_canvas->Refresh(); - + } return; } From e9d26d1a8efdbff8d422c2ea109d886f3da6cfd6 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Tue, 2 Oct 2018 14:30:01 +0200 Subject: [PATCH 053/186] Fixed wxWidgets warnings due to invalid alignement flags at startup --- src/slic3r/GUI/GUI_Preview.cpp | 28 ++++++---------------------- 1 file changed, 6 insertions(+), 22 deletions(-) diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index fc3d362e96..870867218d 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -58,22 +58,6 @@ bool Preview::init(wxNotebook* notebook, DynamicPrintConfig* config, Print* prin if (!Create(notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize)) return false; -// int attribList[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER, WX_GL_DEPTH_SIZE, 24, WX_GL_SAMPLE_BUFFERS, GL_TRUE, WX_GL_SAMPLES, 4, 0 }; - -// int wxVersion = wxMAJOR_VERSION * 10000 + wxMINOR_VERSION * 100 + wxRELEASE_NUMBER; -// const AppConfig* app_config = GUI::get_app_config(); -// bool enable_multisample = (app_config != nullptr) && (app_config->get("use_legacy_opengl") != "1") && (wxVersion >= 30003); - -// // if multisample is not enabled or supported by the graphic card, remove it from the attributes list -// bool can_multisample = enable_multisample && wxGLCanvas::IsExtensionSupported("WGL_ARB_multisample"); -// // bool can_multisample = enable_multisample && wxGLCanvas::IsDisplaySupported(attribList); // <<< Alternative method: but IsDisplaySupported() seems not to work -// if (!can_multisample) -// attribList[4] = 0; - -// m_canvas = new wxGLCanvas(this, wxID_ANY, attribList); -// if (m_canvas == nullptr) -// return false; - m_canvas = GLCanvas3DManager::create_wxglcanvas(this); _3DScene::add_canvas(m_canvas); @@ -131,18 +115,18 @@ bool Preview::init(wxNotebook* notebook, DynamicPrintConfig* config, Print* prin wxBoxSizer* bottom_sizer = new wxBoxSizer(wxHORIZONTAL); bottom_sizer->Add(m_label_view_type, 0, wxALIGN_CENTER_VERTICAL, 5); - bottom_sizer->Add(m_choice_view_type, 0, wxEXPAND | wxALL | wxALIGN_CENTER_VERTICAL, 5); + bottom_sizer->Add(m_choice_view_type, 0, wxEXPAND | wxALL, 5); bottom_sizer->AddSpacer(10); bottom_sizer->Add(m_label_show_features, 0, wxALIGN_CENTER_VERTICAL, 5); - bottom_sizer->Add(m_combochecklist_features, 0, wxEXPAND | wxALL | wxALIGN_CENTER_VERTICAL, 5); + bottom_sizer->Add(m_combochecklist_features, 0, wxEXPAND | wxALL, 5); bottom_sizer->AddSpacer(20); - bottom_sizer->Add(m_checkbox_travel, 0, wxEXPAND | wxALL | wxALIGN_CENTER_VERTICAL, 5); + bottom_sizer->Add(m_checkbox_travel, 0, wxEXPAND | wxALL, 5); bottom_sizer->AddSpacer(10); - bottom_sizer->Add(m_checkbox_retractions, 0, wxEXPAND | wxALL | wxALIGN_CENTER_VERTICAL, 5); + bottom_sizer->Add(m_checkbox_retractions, 0, wxEXPAND | wxALL, 5); bottom_sizer->AddSpacer(10); - bottom_sizer->Add(m_checkbox_unretractions, 0, wxEXPAND | wxALL | wxALIGN_CENTER_VERTICAL, 5); + bottom_sizer->Add(m_checkbox_unretractions, 0, wxEXPAND | wxALL, 5); bottom_sizer->AddSpacer(10); - bottom_sizer->Add(m_checkbox_shells, 0, wxEXPAND | wxALL | wxALIGN_CENTER_VERTICAL, 5); + bottom_sizer->Add(m_checkbox_shells, 0, wxEXPAND | wxALL, 5); wxBoxSizer* main_sizer = new wxBoxSizer(wxVERTICAL); main_sizer->Add(top_sizer, 1, wxALL | wxEXPAND, 0); From 770d944283cda7c90ea7aa614be824aaa3de3519 Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Wed, 3 Oct 2018 11:34:39 +0200 Subject: [PATCH 054/186] Replace PerlCallbacks with events in GLCanvas3d et al. --- src/slic3r/GUI/3DScene.cpp | 186 -------------- src/slic3r/GUI/3DScene.hpp | 36 --- src/slic3r/GUI/Event.hpp | 55 ++++ src/slic3r/GUI/GLCanvas3D.cpp | 371 +++++---------------------- src/slic3r/GUI/GLCanvas3D.hpp | 128 ++++----- src/slic3r/GUI/GLCanvas3DManager.cpp | 240 ----------------- src/slic3r/GUI/GLCanvas3DManager.hpp | 41 +-- src/slic3r/GUI/GLToolbar.cpp | 20 +- src/slic3r/GUI/GLToolbar.hpp | 23 +- src/slic3r/GUI/GUI_Preview.cpp | 6 - src/slic3r/GUI/GUI_Preview.hpp | 3 +- src/slic3r/GUI/GUI_PreviewIface.cpp | 5 - src/slic3r/GUI/GUI_PreviewIface.hpp | 1 - src/slic3r/GUI/Plater.cpp | 15 +- 14 files changed, 197 insertions(+), 933 deletions(-) create mode 100644 src/slic3r/GUI/Event.hpp diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index 744275e227..44a068303c 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -2045,192 +2045,6 @@ void _3DScene::set_toolpaths_range(wxGLCanvas* canvas, double low, double high) s_canvas_mgr.set_toolpaths_range(canvas, low, high); } -void _3DScene::register_on_viewport_changed_callback(wxGLCanvas* canvas, void* callback) -{ - s_canvas_mgr.register_on_viewport_changed_callback(canvas, callback); -} - -void _3DScene::register_on_double_click_callback(wxGLCanvas* canvas, void* callback) -{ - s_canvas_mgr.register_on_double_click_callback(canvas, callback); -} - -void _3DScene::register_on_right_click_callback(wxGLCanvas* canvas, void* callback) -{ - s_canvas_mgr.register_on_right_click_callback(canvas, callback); -} - -void _3DScene::register_on_select_object_callback(wxGLCanvas* canvas, void* callback) -{ - s_canvas_mgr.register_on_select_object_callback(canvas, callback); -} - -void _3DScene::register_on_model_update_callback(wxGLCanvas* canvas, void* callback) -{ - s_canvas_mgr.register_on_model_update_callback(canvas, callback); -} - -void _3DScene::register_on_remove_object_callback(wxGLCanvas* canvas, void* callback) -{ - s_canvas_mgr.register_on_remove_object_callback(canvas, callback); -} - -void _3DScene::register_on_arrange_callback(wxGLCanvas* canvas, void* callback) -{ - s_canvas_mgr.register_on_arrange_callback(canvas, callback); -} - -void _3DScene::register_on_rotate_object_left_callback(wxGLCanvas* canvas, void* callback) -{ - s_canvas_mgr.register_on_rotate_object_left_callback(canvas, callback); -} - -void _3DScene::register_on_rotate_object_right_callback(wxGLCanvas* canvas, void* callback) -{ - s_canvas_mgr.register_on_rotate_object_right_callback(canvas, callback); -} - -void _3DScene::register_on_scale_object_uniformly_callback(wxGLCanvas* canvas, void* callback) -{ - s_canvas_mgr.register_on_scale_object_uniformly_callback(canvas, callback); -} - -void _3DScene::register_on_increase_objects_callback(wxGLCanvas* canvas, void* callback) -{ - s_canvas_mgr.register_on_increase_objects_callback(canvas, callback); -} - -void _3DScene::register_on_decrease_objects_callback(wxGLCanvas* canvas, void* callback) -{ - s_canvas_mgr.register_on_decrease_objects_callback(canvas, callback); -} - -void _3DScene::register_on_instance_moved_callback(wxGLCanvas* canvas, void* callback) -{ - s_canvas_mgr.register_on_instance_moved_callback(canvas, callback); -} - -void _3DScene::register_on_wipe_tower_moved_callback(wxGLCanvas* canvas, void* callback) -{ - s_canvas_mgr.register_on_wipe_tower_moved_callback(canvas, callback); -} - -void _3DScene::register_on_enable_action_buttons_callback(wxGLCanvas* canvas, void* callback) -{ - s_canvas_mgr.register_on_enable_action_buttons_callback(canvas, callback); -} - -void _3DScene::register_on_gizmo_scale_uniformly_callback(wxGLCanvas* canvas, void* callback) -{ -#if !ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - s_canvas_mgr.register_on_gizmo_scale_uniformly_callback(canvas, callback); -#endif // !ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM -} - -void _3DScene::register_on_gizmo_scale_3D_callback(wxGLCanvas* canvas, void* callback) -{ -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - s_canvas_mgr.register_on_gizmo_scale_3D_callback(canvas, callback); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM -} - -void _3DScene::register_on_gizmo_rotate_callback(wxGLCanvas* canvas, void* callback) -{ -#if !ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - s_canvas_mgr.register_on_gizmo_rotate_callback(canvas, callback); -#endif // !ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM -} - -void _3DScene::register_on_gizmo_rotate_3D_callback(wxGLCanvas* canvas, void* callback) -{ -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - s_canvas_mgr.register_on_gizmo_rotate_3D_callback(canvas, callback); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM -} - -void _3DScene::register_on_gizmo_flatten_callback(wxGLCanvas* canvas, void* callback) -{ -#if !ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - s_canvas_mgr.register_on_gizmo_flatten_callback(canvas, callback); -#endif // !ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM -} - -void _3DScene::register_on_gizmo_flatten_3D_callback(wxGLCanvas* canvas, void* callback) -{ -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - s_canvas_mgr.register_on_gizmo_flatten_3D_callback(canvas, callback); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM -} - -void _3DScene::register_on_update_geometry_info_callback(wxGLCanvas* canvas, void* callback) -{ -#if !ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - s_canvas_mgr.register_on_update_geometry_info_callback(canvas, callback); -#endif // !ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM -} - -void _3DScene::register_on_update_geometry_3D_info_callback(wxGLCanvas* canvas, void* callback) -{ -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - s_canvas_mgr.register_on_update_geometry_3D_info_callback(canvas, callback); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM -} - -void _3DScene::register_action_add_callback(wxGLCanvas* canvas, void* callback) -{ - s_canvas_mgr.register_action_add_callback(canvas, callback); -} - -void _3DScene::register_action_delete_callback(wxGLCanvas* canvas, void* callback) -{ - s_canvas_mgr.register_action_delete_callback(canvas, callback); -} - -void _3DScene::register_action_deleteall_callback(wxGLCanvas* canvas, void* callback) -{ - s_canvas_mgr.register_action_deleteall_callback(canvas, callback); -} - -void _3DScene::register_action_arrange_callback(wxGLCanvas* canvas, void* callback) -{ - s_canvas_mgr.register_action_arrange_callback(canvas, callback); -} - -void _3DScene::register_action_more_callback(wxGLCanvas* canvas, void* callback) -{ - s_canvas_mgr.register_action_more_callback(canvas, callback); -} - -void _3DScene::register_action_fewer_callback(wxGLCanvas* canvas, void* callback) -{ - s_canvas_mgr.register_action_fewer_callback(canvas, callback); -} - -void _3DScene::register_action_split_callback(wxGLCanvas* canvas, void* callback) -{ - s_canvas_mgr.register_action_split_callback(canvas, callback); -} - -void _3DScene::register_action_cut_callback(wxGLCanvas* canvas, void* callback) -{ - s_canvas_mgr.register_action_cut_callback(canvas, callback); -} - -void _3DScene::register_action_settings_callback(wxGLCanvas* canvas, void* callback) -{ - s_canvas_mgr.register_action_settings_callback(canvas, callback); -} - -void _3DScene::register_action_layersediting_callback(wxGLCanvas* canvas, void* callback) -{ - s_canvas_mgr.register_action_layersediting_callback(canvas, callback); -} - -void _3DScene::register_action_selectbyparts_callback(wxGLCanvas* canvas, void* callback) -{ - s_canvas_mgr.register_action_selectbyparts_callback(canvas, callback); -} - static inline int hex_digit_to_int(const char c) { return diff --git a/src/slic3r/GUI/3DScene.hpp b/src/slic3r/GUI/3DScene.hpp index a5f4c51899..971083ab62 100644 --- a/src/slic3r/GUI/3DScene.hpp +++ b/src/slic3r/GUI/3DScene.hpp @@ -555,42 +555,6 @@ public: static std::vector get_current_print_zs(wxGLCanvas* canvas, bool active_only); static void set_toolpaths_range(wxGLCanvas* canvas, double low, double high); - static void register_on_viewport_changed_callback(wxGLCanvas* canvas, void* callback); - static void register_on_double_click_callback(wxGLCanvas* canvas, void* callback); - static void register_on_right_click_callback(wxGLCanvas* canvas, void* callback); - static void register_on_select_object_callback(wxGLCanvas* canvas, void* callback); - static void register_on_model_update_callback(wxGLCanvas* canvas, void* callback); - static void register_on_remove_object_callback(wxGLCanvas* canvas, void* callback); - static void register_on_arrange_callback(wxGLCanvas* canvas, void* callback); - static void register_on_rotate_object_left_callback(wxGLCanvas* canvas, void* callback); - static void register_on_rotate_object_right_callback(wxGLCanvas* canvas, void* callback); - static void register_on_scale_object_uniformly_callback(wxGLCanvas* canvas, void* callback); - static void register_on_increase_objects_callback(wxGLCanvas* canvas, void* callback); - static void register_on_decrease_objects_callback(wxGLCanvas* canvas, void* callback); - static void register_on_instance_moved_callback(wxGLCanvas* canvas, void* callback); - static void register_on_wipe_tower_moved_callback(wxGLCanvas* canvas, void* callback); - static void register_on_enable_action_buttons_callback(wxGLCanvas* canvas, void* callback); - static void register_on_gizmo_scale_uniformly_callback(wxGLCanvas* canvas, void* callback); - static void register_on_gizmo_scale_3D_callback(wxGLCanvas* canvas, void* callback); - static void register_on_gizmo_rotate_callback(wxGLCanvas* canvas, void* callback); - static void register_on_gizmo_rotate_3D_callback(wxGLCanvas* canvas, void* callback); - static void register_on_gizmo_flatten_callback(wxGLCanvas* canvas, void* callback); - static void register_on_gizmo_flatten_3D_callback(wxGLCanvas* canvas, void* callback); - static void register_on_update_geometry_info_callback(wxGLCanvas* canvas, void* callback); - static void register_on_update_geometry_3D_info_callback(wxGLCanvas* canvas, void* callback); - - static void register_action_add_callback(wxGLCanvas* canvas, void* callback); - static void register_action_delete_callback(wxGLCanvas* canvas, void* callback); - static void register_action_deleteall_callback(wxGLCanvas* canvas, void* callback); - static void register_action_arrange_callback(wxGLCanvas* canvas, void* callback); - static void register_action_more_callback(wxGLCanvas* canvas, void* callback); - static void register_action_fewer_callback(wxGLCanvas* canvas, void* callback); - static void register_action_split_callback(wxGLCanvas* canvas, void* callback); - static void register_action_cut_callback(wxGLCanvas* canvas, void* callback); - static void register_action_settings_callback(wxGLCanvas* canvas, void* callback); - static void register_action_layersediting_callback(wxGLCanvas* canvas, void* callback); - static void register_action_selectbyparts_callback(wxGLCanvas* canvas, void* callback); - static std::vector load_object(wxGLCanvas* canvas, const ModelObject* model_object, int obj_idx, std::vector instance_idxs); static std::vector load_object(wxGLCanvas* canvas, const Model* model, int obj_idx); diff --git a/src/slic3r/GUI/Event.hpp b/src/slic3r/GUI/Event.hpp new file mode 100644 index 0000000000..ffcad7f9f0 --- /dev/null +++ b/src/slic3r/GUI/Event.hpp @@ -0,0 +1,55 @@ +#ifndef slic3r_Events_hpp_ +#define slic3r_Events_hpp_ + +#include + + +namespace Slic3r { + +namespace GUI { + + +struct SimpleEvent : public wxEvent +{ + SimpleEvent(wxEventType type, int id = 0) : wxEvent(id, type) {} + + virtual wxEvent* Clone() const + { + return new SimpleEvent(GetEventType(), GetId()); + } +}; + +template struct ArrayEvent : public wxEvent +{ + std::array data; + + ArrayEvent(wxEventType type, std::array data, int id = 0) + : wxEvent(id, type), data(std::move(data)) + {} + + virtual wxEvent* Clone() const + { + return new ArrayEvent(GetEventType(), data, GetId()); + } +}; +template struct ArrayEvent : public wxEvent +{ + T data; + + ArrayEvent(wxEventType type, T data, int id = 0) + : wxEvent(id, type), data(std::move(data)) + {} + + virtual wxEvent* Clone() const + { + return new ArrayEvent(GetEventType(), data, GetId()); + } +}; + +template using Event = ArrayEvent; + + +} +} + +#endif // slic3r_Events_hpp_ diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 89f092017e..b6de0d820b 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1936,6 +1936,26 @@ GLGizmoBase* GLCanvas3D::Gizmos::_get_current() const return (it != m_gizmos.end()) ? it->second : nullptr; } +wxDEFINE_EVENT(EVT_GLCANVAS_OBJECT_SELECT, ObjectSelectEvent); +wxDEFINE_EVENT(EVT_GLCANVAS_VIEWPORT_CHANGED, SimpleEvent); +wxDEFINE_EVENT(EVT_GLCANVAS_DOUBLE_CLICK, SimpleEvent); +wxDEFINE_EVENT(EVT_GLCANVAS_RIGHT_CLICK, Vec2dEvent); +wxDEFINE_EVENT(EVT_GLCANVAS_MODEL_UPDATE, SimpleEvent); +wxDEFINE_EVENT(EVT_GLCANVAS_REMOVE_OBJECT, SimpleEvent); +wxDEFINE_EVENT(EVT_GLCANVAS_ARRANGE, SimpleEvent); +wxDEFINE_EVENT(EVT_GLCANVAS_ROTATE_OBJECT, Event); +wxDEFINE_EVENT(EVT_GLCANVAS_SCALE_UNIFORMLY, SimpleEvent); +wxDEFINE_EVENT(EVT_GLCANVAS_INCREASE_OBJECTS, Event); +wxDEFINE_EVENT(EVT_GLCANVAS_INSTANCE_MOVES, SimpleEvent); +wxDEFINE_EVENT(EVT_GLCANVAS_WIPETOWER_MOVED, Vec3dEvent); +wxDEFINE_EVENT(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, Event); +wxDEFINE_EVENT(EVT_GLCANVAS_UPDATE_GEOMETRY, Vec3dsEvent<2>); + +wxDEFINE_EVENT(EVT_GIZMO_SCALE, Vec3dEvent); +wxDEFINE_EVENT(EVT_GIZMO_ROTATE, Vec3dEvent); +wxDEFINE_EVENT(EVT_GIZMO_FLATTEN, Vec3dEvent); + + GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas) : m_canvas(canvas) , m_context(nullptr) @@ -1985,8 +2005,16 @@ GLCanvas3D::~GLCanvas3D() delete m_context; m_context = nullptr; } +} - _deregister_callbacks(); +void GLCanvas3D::post_event(const wxEvent &event) +{ + wxPostEvent(m_canvas, event); +} + +void GLCanvas3D::viewport_changed() +{ + post_event(SimpleEvent(EVT_GLCANVAS_VIEWPORT_CHANGED)); } bool GLCanvas3D::init(bool useVBOs, bool use_legacy_opengl) @@ -2412,7 +2440,7 @@ void GLCanvas3D::select_view(const std::string& direction) m_camera.phi = dir_vec[0]; m_camera.set_theta(dir_vec[1]); - m_on_viewport_changed_callback.call(); + viewport_changed(); if (m_canvas != nullptr) m_canvas->Refresh(); @@ -2657,21 +2685,21 @@ void GLCanvas3D::reload_scene(bool force) { enable_warning_texture(true); _generate_warning_texture(L("Detected object outside print volume")); - m_on_enable_action_buttons_callback.call(state == ModelInstance::PVS_Fully_Outside); + post_event(Event(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, state == ModelInstance::PVS_Fully_Outside)); } else { enable_warning_texture(false); m_volumes.reset_outside_state(); _reset_warning_texture(); - m_on_enable_action_buttons_callback.call(!m_model->objects.empty()); + post_event(Event(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, !m_model->objects.empty())); } } else { enable_warning_texture(false); _reset_warning_texture(); - m_on_enable_action_buttons_callback.call(false); + post_event(Event(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, false)); } } @@ -2737,215 +2765,6 @@ void GLCanvas3D::load_preview(const std::vector& str_tool_colors) reset_legend_texture(); } -void GLCanvas3D::register_on_viewport_changed_callback(void* callback) -{ - if (callback != nullptr) - m_on_viewport_changed_callback.register_callback(callback); -} - -void GLCanvas3D::register_on_double_click_callback(void* callback) -{ - if (callback != nullptr) - m_on_double_click_callback.register_callback(callback); -} - -void GLCanvas3D::register_on_right_click_callback(void* callback) -{ - if (callback != nullptr) - m_on_right_click_callback.register_callback(callback); -} - -void GLCanvas3D::register_on_select_object_callback(void* callback) -{ - if (callback != nullptr) - m_on_select_object_callback.register_callback(callback); -} - -void GLCanvas3D::register_on_model_update_callback(void* callback) -{ - if (callback != nullptr) - m_on_model_update_callback.register_callback(callback); -} - -void GLCanvas3D::register_on_remove_object_callback(void* callback) -{ - if (callback != nullptr) - m_on_remove_object_callback.register_callback(callback); -} - -void GLCanvas3D::register_on_arrange_callback(void* callback) -{ - if (callback != nullptr) - m_on_arrange_callback.register_callback(callback); -} - -void GLCanvas3D::register_on_rotate_object_left_callback(void* callback) -{ - if (callback != nullptr) - m_on_rotate_object_left_callback.register_callback(callback); -} - -void GLCanvas3D::register_on_rotate_object_right_callback(void* callback) -{ - if (callback != nullptr) - m_on_rotate_object_right_callback.register_callback(callback); -} - -void GLCanvas3D::register_on_scale_object_uniformly_callback(void* callback) -{ - if (callback != nullptr) - m_on_scale_object_uniformly_callback.register_callback(callback); -} - -void GLCanvas3D::register_on_increase_objects_callback(void* callback) -{ - if (callback != nullptr) - m_on_increase_objects_callback.register_callback(callback); -} - -void GLCanvas3D::register_on_decrease_objects_callback(void* callback) -{ - if (callback != nullptr) - m_on_decrease_objects_callback.register_callback(callback); -} - -void GLCanvas3D::register_on_instance_moved_callback(void* callback) -{ - if (callback != nullptr) - m_on_instance_moved_callback.register_callback(callback); -} - -void GLCanvas3D::register_on_wipe_tower_moved_callback(void* callback) -{ - if (callback != nullptr) - m_on_wipe_tower_moved_callback.register_callback(callback); -} - -void GLCanvas3D::register_on_enable_action_buttons_callback(void* callback) -{ - if (callback != nullptr) - m_on_enable_action_buttons_callback.register_callback(callback); -} - -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM -void GLCanvas3D::register_on_gizmo_scale_3D_callback(void* callback) -{ - if (callback != nullptr) - m_on_gizmo_scale_3D_callback.register_callback(callback); -} - -void GLCanvas3D::register_on_gizmo_rotate_3D_callback(void* callback) -{ - if (callback != nullptr) - m_on_gizmo_rotate_3D_callback.register_callback(callback); -} - -void GLCanvas3D::register_on_gizmo_flatten_3D_callback(void* callback) -{ - if (callback != nullptr) - m_on_gizmo_flatten_3D_callback.register_callback(callback); -} - -void GLCanvas3D::register_on_update_geometry_3D_info_callback(void* callback) -{ - if (callback != nullptr) - m_on_update_geometry_3D_info_callback.register_callback(callback); -} -#else -void GLCanvas3D::register_on_gizmo_scale_uniformly_callback(void* callback) -{ - if (callback != nullptr) - m_on_gizmo_scale_uniformly_callback.register_callback(callback); -} - -void GLCanvas3D::register_on_gizmo_rotate_callback(void* callback) -{ - if (callback != nullptr) - m_on_gizmo_rotate_callback.register_callback(callback); -} - -void GLCanvas3D::register_on_gizmo_flatten_callback(void* callback) -{ - if (callback != nullptr) - m_on_gizmo_flatten_callback.register_callback(callback); -} - -void GLCanvas3D::register_on_update_geometry_info_callback(void* callback) -{ - if (callback != nullptr) - m_on_update_geometry_info_callback.register_callback(callback); -} -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - -// void GLCanvas3D::register_action_add_callback(GLToolbarItem::Callback callback) -void GLCanvas3D::register_action_add_callback(void* callback) -{ - if (callback != nullptr) - m_action_add_callback.register_callback(callback); - // if (callback) - // m_action_add_callback = std::move(callback); -} - -void GLCanvas3D::register_action_delete_callback(void* callback) -{ - if (callback != nullptr) - m_action_delete_callback.register_callback(callback); -} - -void GLCanvas3D::register_action_deleteall_callback(void* callback) -{ - if (callback != nullptr) - m_action_deleteall_callback.register_callback(callback); -} - -void GLCanvas3D::register_action_arrange_callback(void* callback) -{ - if (callback != nullptr) - m_action_arrange_callback.register_callback(callback); -} - -void GLCanvas3D::register_action_more_callback(void* callback) -{ - if (callback != nullptr) - m_action_more_callback.register_callback(callback); -} - -void GLCanvas3D::register_action_fewer_callback(void* callback) -{ - if (callback != nullptr) - m_action_fewer_callback.register_callback(callback); -} - -void GLCanvas3D::register_action_split_callback(void* callback) -{ - if (callback != nullptr) - m_action_split_callback.register_callback(callback); -} - -void GLCanvas3D::register_action_cut_callback(void* callback) -{ - if (callback != nullptr) - m_action_cut_callback.register_callback(callback); -} - -void GLCanvas3D::register_action_settings_callback(void* callback) -{ - if (callback != nullptr) - m_action_settings_callback.register_callback(callback); -} - -void GLCanvas3D::register_action_layersediting_callback(void* callback) -{ - if (callback != nullptr) - m_action_layersediting_callback.register_callback(callback); -} - -void GLCanvas3D::register_action_selectbyparts_callback(void* callback) -{ - if (callback != nullptr) - m_action_selectbyparts_callback.register_callback(callback); -} - void GLCanvas3D::bind_event_handlers() { if (m_canvas != nullptr) @@ -3034,24 +2853,24 @@ void GLCanvas3D::on_char(wxKeyEvent& evt) switch (keyCode) { // key + - case 43: { m_on_increase_objects_callback.call(); break; } + case 43: { post_event(Event(EVT_GLCANVAS_INCREASE_OBJECTS, +1)); break; } // key - - case 45: { m_on_decrease_objects_callback.call(); break; } + case 45: { post_event(Event(EVT_GLCANVAS_INCREASE_OBJECTS, -1)); break; } // key A/a case 65: - case 97: { m_on_arrange_callback.call(); break; } + case 97: { post_event(SimpleEvent(EVT_GLCANVAS_ARRANGE)); break; } // key B/b case 66: case 98: { zoom_to_bed(); break; } // key L/l case 76: - case 108: { m_on_rotate_object_left_callback.call(); break; } + case 108: { post_event(Event(EVT_GLCANVAS_ROTATE_OBJECT, -1)); break; } // key R/r case 82: - case 114: { m_on_rotate_object_right_callback.call(); break; } + case 114: { post_event(Event(EVT_GLCANVAS_ROTATE_OBJECT, +1)); break; } // key S/s case 83: - case 115: { m_on_scale_object_uniformly_callback.call(); break; } + case 115: { post_event(SimpleEvent(EVT_GLCANVAS_SCALE_UNIFORMLY)); break; } // key Z/z case 90: case 122: { zoom_to_volumes(); break; } @@ -3102,7 +2921,7 @@ void GLCanvas3D::on_mouse_wheel(wxMouseEvent& evt) zoom = std::max(zoom, zoom_min * 0.8f); m_camera.zoom = zoom; - m_on_viewport_changed_callback.call(); + viewport_changed(); _refresh_if_shown_on_screen(); } @@ -3142,7 +2961,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) m_dirty = true; } else if (evt.LeftDClick() && (m_hover_volume_id != -1) && !gizmos_overlay_contains_mouse && (toolbar_contains_mouse == -1)) - m_on_double_click_callback.call(); + post_event(SimpleEvent(EVT_GLCANVAS_DOUBLE_CLICK)); else if (evt.LeftDClick() && (toolbar_contains_mouse != -1)) { m_toolbar_action_running = true; @@ -3158,8 +2977,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) case Gizmos::Scale: { #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - const Vec3d& scale = m_gizmos.get_scale(); - m_on_gizmo_scale_3D_callback.call(scale(0), scale(1), scale(2)); + post_event(Vec3dEvent(EVT_GIZMO_SCALE, m_gizmos.get_scale())); #else m_on_gizmo_scale_uniformly_callback.call((double)m_gizmos.get_scale()); #endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM @@ -3170,8 +2988,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) case Gizmos::Rotate: { #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - const Vec3d& rotation = m_gizmos.get_rotation(); - m_on_gizmo_rotate_3D_callback.call(rotation(0), rotation(1), rotation(2)); + post_event(Vec3dEvent(EVT_GIZMO_ROTATE, std::move(m_gizmos.get_rotation()))); #else m_on_gizmo_rotate_callback.call((double)m_gizmos.get_angle_z()); #endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM @@ -3228,8 +3045,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) if (m_gizmos.get_current_type() == Gizmos::Flatten) { #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM // Rotate the object so the normal points downward: - const Vec3d& rotation = m_gizmos.get_flattening_rotation(); - m_on_gizmo_flatten_3D_callback.call(rotation(0), rotation(1), rotation(2)); + post_event(Vec3dEvent(EVT_GIZMO_FLATTEN, m_gizmos.get_flattening_rotation())); #else // Rotate the object so the normal points downward: Vec3d normal = m_gizmos.get_flattening_normal(); @@ -3311,7 +3127,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) { // if right clicking on volume, propagate event through callback (shows context menu) if (m_volumes.volumes[volume_idx]->hover) - m_on_right_click_callback.call(pos(0), pos(1)); + post_event(Vec2dEvent(EVT_GLCANVAS_RIGHT_CLICK, pos.cast())); } } } @@ -3464,7 +3280,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) const Vec3d& size = bb.size(); #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM const Vec3d& scale = m_gizmos.get_scale(); - m_on_update_geometry_3D_info_callback.call(size(0), size(1), size(2), scale(0), scale(1), scale(2)); + post_event(Vec3dsEvent<2>(EVT_GLCANVAS_UPDATE_GEOMETRY, {size, scale})); #else m_on_update_geometry_info_callback.call(size(0), size(1), size(2), m_gizmos.get_scale()); #endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM @@ -3490,7 +3306,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) m_camera.phi += (((float)pos(0) - (float)orig(0)) * TRACKBALLSIZE); m_camera.set_theta(m_camera.get_theta() - ((float)pos(1) - (float)orig(1)) * TRACKBALLSIZE); - m_on_viewport_changed_callback.call(); + viewport_changed(); m_dirty = true; } @@ -3507,7 +3323,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) Vec3d orig = _mouse_to_3d(m_mouse.drag.start_position_2D, &z); m_camera.target += orig - cur_pos; - m_on_viewport_changed_callback.call(); + viewport_changed(); m_dirty = true; } @@ -3523,7 +3339,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) _stop_timer(); if (layer_editing_object_idx != -1) - m_on_model_update_callback.call(); + post_event(SimpleEvent(EVT_GLCANVAS_MODEL_UPDATE)); } else if ((m_mouse.drag.move_volume_idx != -1) && m_mouse.dragging) { @@ -3594,8 +3410,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) case Gizmos::Scale: { #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - const Vec3d& scale = m_gizmos.get_scale(); - m_on_gizmo_scale_3D_callback.call(scale(0), scale(1), scale(2)); + post_event(Vec3dEvent(EVT_GIZMO_SCALE, m_gizmos.get_scale())); #else m_on_gizmo_scale_uniformly_callback.call((double)m_gizmos.get_scale()); #endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM @@ -3604,8 +3419,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) case Gizmos::Rotate: { #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - const Vec3d& rotation = m_gizmos.get_rotation(); - m_on_gizmo_rotate_3D_callback.call(rotation(0), rotation(1), rotation(2)); + post_event(Vec3dEvent(EVT_GIZMO_ROTATE, m_gizmos.get_rotation())); #else m_on_gizmo_rotate_callback.call((double)m_gizmos.get_angle_z()); #endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM @@ -3653,12 +3467,12 @@ void GLCanvas3D::on_key_down(wxKeyEvent& evt) { int key = evt.GetKeyCode(); if (key == WXK_DELETE) - m_on_remove_object_callback.call(); + post_event(SimpleEvent(EVT_GLCANVAS_REMOVE_OBJECT)); else { #ifdef __WXOSX__ if (key == WXK_BACK) - m_on_remove_object_callback.call(); + post_event(SimpleEvent(EVT_GLCANVAS_REMOVE_OBJECT)); #endif evt.Skip(); } @@ -3733,7 +3547,6 @@ bool GLCanvas3D::_init_toolbar() item.tooltip = GUI::L_str("Add..."); item.sprite_id = 0; item.is_toggable = false; - // item.action_callback = &m_action_add_callback; item.action_event = EVT_GLTOOLBAR_ADD; if (!m_toolbar.add_item(item)) return false; @@ -3742,7 +3555,6 @@ bool GLCanvas3D::_init_toolbar() item.tooltip = GUI::L_str("Delete"); item.sprite_id = 1; item.is_toggable = false; - // item.action_callback = &m_action_delete_callback; item.action_event = EVT_GLTOOLBAR_DELETE; if (!m_toolbar.add_item(item)) return false; @@ -3751,8 +3563,7 @@ bool GLCanvas3D::_init_toolbar() item.tooltip = GUI::L_str("Delete all"); item.sprite_id = 2; item.is_toggable = false; - // item.action_callback = &m_action_deleteall_callback; - item.action_event = EVT_GLTOOLBAR_TODO_MORE; + item.action_event = EVT_GLTOOLBAR_DELETE_ALL; if (!m_toolbar.add_item(item)) return false; @@ -3760,8 +3571,7 @@ bool GLCanvas3D::_init_toolbar() item.tooltip = GUI::L_str("Arrange"); item.sprite_id = 3; item.is_toggable = false; - // item.action_callback = &m_action_arrange_callback; - item.action_event = EVT_GLTOOLBAR_TODO_MORE; + item.action_event = EVT_GLTOOLBAR_ARRANGE; if (!m_toolbar.add_item(item)) return false; @@ -3772,8 +3582,7 @@ bool GLCanvas3D::_init_toolbar() item.tooltip = GUI::L_str("Add instance"); item.sprite_id = 4; item.is_toggable = false; - // item.action_callback = &m_action_more_callback; - item.action_event = EVT_GLTOOLBAR_TODO_MORE; + item.action_event = EVT_GLTOOLBAR_MORE; if (!m_toolbar.add_item(item)) return false; @@ -3781,8 +3590,7 @@ bool GLCanvas3D::_init_toolbar() item.tooltip = GUI::L_str("Remove instance"); item.sprite_id = 5; item.is_toggable = false; - // item.action_callback = &m_action_fewer_callback; - item.action_event = EVT_GLTOOLBAR_TODO_MORE; + item.action_event = EVT_GLTOOLBAR_FEWER; if (!m_toolbar.add_item(item)) return false; @@ -3793,8 +3601,7 @@ bool GLCanvas3D::_init_toolbar() item.tooltip = GUI::L_str("Split"); item.sprite_id = 6; item.is_toggable = false; - // item.action_callback = &m_action_split_callback; - item.action_event = EVT_GLTOOLBAR_TODO_MORE; + item.action_event = EVT_GLTOOLBAR_SPLIT; if (!m_toolbar.add_item(item)) return false; @@ -3802,8 +3609,7 @@ bool GLCanvas3D::_init_toolbar() item.tooltip = GUI::L_str("Cut..."); item.sprite_id = 7; item.is_toggable = false; - // item.action_callback = &m_action_cut_callback; - item.action_event = EVT_GLTOOLBAR_TODO_MORE; + item.action_event = EVT_GLTOOLBAR_CUT; if (!m_toolbar.add_item(item)) return false; @@ -3814,8 +3620,7 @@ bool GLCanvas3D::_init_toolbar() item.tooltip = GUI::L_str("Settings..."); item.sprite_id = 8; item.is_toggable = false; - // item.action_callback = &m_action_settings_callback; - item.action_event = EVT_GLTOOLBAR_TODO_MORE; + item.action_event = EVT_GLTOOLBAR_SETTINGS; if (!m_toolbar.add_item(item)) return false; @@ -3823,8 +3628,7 @@ bool GLCanvas3D::_init_toolbar() item.tooltip = GUI::L_str("Layers editing"); item.sprite_id = 9; item.is_toggable = true; - // item.action_callback = &m_action_layersediting_callback; - item.action_event = EVT_GLTOOLBAR_TODO_MORE; + item.action_event = EVT_GLTOOLBAR_LAYERSEDITING; if (!m_toolbar.add_item(item)) return false; @@ -3835,8 +3639,7 @@ bool GLCanvas3D::_init_toolbar() item.tooltip = GUI::L_str("Select by parts"); item.sprite_id = 10; item.is_toggable = true; - // item.action_callback = &m_action_selectbyparts_callback; - item.action_event = EVT_GLTOOLBAR_TODO_MORE; + item.action_event = EVT_GLTOOLBAR_SELECTBYPARTS; if (!m_toolbar.add_item(item)) return false; @@ -3975,7 +3778,7 @@ void GLCanvas3D::_zoom_to_bounding_box(const BoundingBoxf3& bbox) // center view around bounding box center m_camera.target = bbox.center(); - m_on_viewport_changed_callback.call(); + viewport_changed(); _refresh_if_shown_on_screen(); } @@ -4048,48 +3851,6 @@ float GLCanvas3D::_get_zoom_to_bounding_box_factor(const BoundingBoxf3& bbox) co return (float)std::min((double)cnv_size.get_width() / max_x, (double)cnv_size.get_height() / max_y); } -void GLCanvas3D::_deregister_callbacks() -{ - m_on_viewport_changed_callback.deregister_callback(); - m_on_double_click_callback.deregister_callback(); - m_on_right_click_callback.deregister_callback(); - m_on_select_object_callback.deregister_callback(); - m_on_model_update_callback.deregister_callback(); - m_on_remove_object_callback.deregister_callback(); - m_on_arrange_callback.deregister_callback(); - m_on_rotate_object_left_callback.deregister_callback(); - m_on_rotate_object_right_callback.deregister_callback(); - m_on_scale_object_uniformly_callback.deregister_callback(); - m_on_increase_objects_callback.deregister_callback(); - m_on_decrease_objects_callback.deregister_callback(); - m_on_instance_moved_callback.deregister_callback(); - m_on_wipe_tower_moved_callback.deregister_callback(); - m_on_enable_action_buttons_callback.deregister_callback(); -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - m_on_gizmo_scale_3D_callback.deregister_callback(); - m_on_gizmo_rotate_3D_callback.deregister_callback(); - m_on_gizmo_flatten_3D_callback.deregister_callback(); - m_on_update_geometry_3D_info_callback.deregister_callback(); -#else - m_on_gizmo_scale_uniformly_callback.deregister_callback(); - m_on_gizmo_rotate_callback.deregister_callback(); - m_on_gizmo_flatten_callback.deregister_callback(); - m_on_update_geometry_info_callback.deregister_callback(); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - - m_action_add_callback.deregister_callback(); - m_action_delete_callback.deregister_callback(); - m_action_deleteall_callback.deregister_callback(); - m_action_arrange_callback.deregister_callback(); - m_action_more_callback.deregister_callback(); - m_action_fewer_callback.deregister_callback(); - m_action_split_callback.deregister_callback(); - m_action_cut_callback.deregister_callback(); - m_action_settings_callback.deregister_callback(); - m_action_layersediting_callback.deregister_callback(); - m_action_selectbyparts_callback.deregister_callback(); -} - void GLCanvas3D::_mark_volumes_for_layer_height() const { if (m_print == nullptr) @@ -5599,10 +5360,10 @@ void GLCanvas3D::_on_move(const std::vector& volume_idxs) } if (object_moved) - m_on_instance_moved_callback.call(); + post_event(SimpleEvent(EVT_GLCANVAS_WIPETOWER_MOVED)); if (wipe_tower_origin != Vec3d::Zero()) - m_on_wipe_tower_moved_callback.call(wipe_tower_origin(0), wipe_tower_origin(1)); + post_event(Vec3dEvent(EVT_GLCANVAS_WIPETOWER_MOVED, std::move(wipe_tower_origin))); } void GLCanvas3D::_on_select(int volume_idx, int object_idx) @@ -5633,7 +5394,7 @@ void GLCanvas3D::_on_select(int volume_idx, int object_idx) } } - m_on_select_object_callback.call(obj_id, vol_id); + post_event(ObjectSelectEvent(obj_id, vol_id)); Slic3r::GUI::select_current_volume(obj_id, vol_id); } diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index aba2b07c1d..055d62b6a2 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -1,11 +1,11 @@ #ifndef slic3r_GLCanvas3D_hpp_ #define slic3r_GLCanvas3D_hpp_ -#include +#include #include "3DScene.hpp" #include "GLToolbar.hpp" -#include "callback.hpp" +#include "Event.hpp" class wxWindow; class wxTimer; @@ -16,6 +16,7 @@ class wxMouseEvent; class wxTimerEvent; class wxPaintEvent; + namespace Slic3r { class GLShader; @@ -80,6 +81,45 @@ public: void set_bottom(float bottom); }; + +struct ObjectSelectEvent; +wxDECLARE_EVENT(EVT_GLCANVAS_OBJECT_SELECT, ObjectSelectEvent); +struct ObjectSelectEvent : public ArrayEvent +{ + ObjectSelectEvent(ptrdiff_t object_id, ptrdiff_t volume_id, int id = 0) + : ArrayEvent(EVT_GLCANVAS_OBJECT_SELECT, {object_id, volume_id}, id) + {} + + ptrdiff_t object_id() const { return data[0]; } + ptrdiff_t volume_id() const { return data[1]; } +}; + +using Vec2dEvent = Event; +template using Vec2dsEvent = ArrayEvent; + +using Vec3dEvent = Event; +template using Vec3dsEvent = ArrayEvent; + + +wxDECLARE_EVENT(EVT_GLCANVAS_VIEWPORT_CHANGED, SimpleEvent); +wxDECLARE_EVENT(EVT_GLCANVAS_DOUBLE_CLICK, SimpleEvent); +wxDECLARE_EVENT(EVT_GLCANVAS_RIGHT_CLICK, Vec2dEvent); +wxDECLARE_EVENT(EVT_GLCANVAS_MODEL_UPDATE, SimpleEvent); +wxDECLARE_EVENT(EVT_GLCANVAS_REMOVE_OBJECT, SimpleEvent); +wxDECLARE_EVENT(EVT_GLCANVAS_ARRANGE, SimpleEvent); +wxDECLARE_EVENT(EVT_GLCANVAS_ROTATE_OBJECT, Event); // data: -1 => rotate left, +1 => rotate right +wxDECLARE_EVENT(EVT_GLCANVAS_SCALE_UNIFORMLY, SimpleEvent); +wxDECLARE_EVENT(EVT_GLCANVAS_INCREASE_OBJECTS, Event); // data: +1 => increase, -1 => decrease +wxDECLARE_EVENT(EVT_GLCANVAS_INSTANCE_MOVES, SimpleEvent); +wxDECLARE_EVENT(EVT_GLCANVAS_WIPETOWER_MOVED, Vec3dEvent); +wxDECLARE_EVENT(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, Event); +wxDECLARE_EVENT(EVT_GLCANVAS_UPDATE_GEOMETRY, Vec3dsEvent<2>); + +wxDECLARE_EVENT(EVT_GIZMO_SCALE, Vec3dEvent); +wxDECLARE_EVENT(EVT_GIZMO_ROTATE, Vec3dEvent); +wxDECLARE_EVENT(EVT_GIZMO_FLATTEN, Vec3dEvent); + + class GLCanvas3D { struct GCodePreviewVolumeIndex @@ -506,46 +546,8 @@ class GLCanvas3D GCodePreviewVolumeIndex m_gcode_preview_volume_index; - PerlCallback m_on_viewport_changed_callback; - PerlCallback m_on_double_click_callback; - PerlCallback m_on_right_click_callback; - PerlCallback m_on_select_object_callback; - PerlCallback m_on_model_update_callback; - PerlCallback m_on_remove_object_callback; - PerlCallback m_on_arrange_callback; - PerlCallback m_on_rotate_object_left_callback; - PerlCallback m_on_rotate_object_right_callback; - PerlCallback m_on_scale_object_uniformly_callback; - PerlCallback m_on_increase_objects_callback; - PerlCallback m_on_decrease_objects_callback; - PerlCallback m_on_instance_moved_callback; - PerlCallback m_on_wipe_tower_moved_callback; - PerlCallback m_on_enable_action_buttons_callback; -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - PerlCallback m_on_gizmo_rotate_3D_callback; - PerlCallback m_on_gizmo_flatten_3D_callback; - PerlCallback m_on_gizmo_scale_3D_callback; - PerlCallback m_on_update_geometry_3D_info_callback; -#else - PerlCallback m_on_gizmo_scale_uniformly_callback; - PerlCallback m_on_gizmo_rotate_callback; - PerlCallback m_on_gizmo_flatten_callback; - PerlCallback m_on_update_geometry_info_callback; -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - - // TODO: Remove these - PerlCallback m_action_add_callback; - PerlCallback m_action_delete_callback; - PerlCallback m_action_deleteall_callback; - PerlCallback m_action_arrange_callback; - PerlCallback m_action_more_callback; - PerlCallback m_action_fewer_callback; - PerlCallback m_action_split_callback; - PerlCallback m_action_cut_callback; - PerlCallback m_action_settings_callback; - PerlCallback m_action_layersediting_callback; - PerlCallback m_action_selectbyparts_callback; - + void post_event(const wxEvent &event); + void viewport_changed(); public: GLCanvas3D(wxGLCanvas* canvas); ~GLCanvas3D(); @@ -641,46 +643,6 @@ public: void load_gcode_preview(const GCodePreviewData& preview_data, const std::vector& str_tool_colors); void load_preview(const std::vector& str_tool_colors); - void register_on_viewport_changed_callback(void* callback); - void register_on_double_click_callback(void* callback); - void register_on_right_click_callback(void* callback); - void register_on_select_object_callback(void* callback); - void register_on_model_update_callback(void* callback); - void register_on_remove_object_callback(void* callback); - void register_on_arrange_callback(void* callback); - void register_on_rotate_object_left_callback(void* callback); - void register_on_rotate_object_right_callback(void* callback); - void register_on_scale_object_uniformly_callback(void* callback); - void register_on_increase_objects_callback(void* callback); - void register_on_decrease_objects_callback(void* callback); - void register_on_instance_moved_callback(void* callback); - void register_on_wipe_tower_moved_callback(void* callback); - void register_on_enable_action_buttons_callback(void* callback); -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - void register_on_gizmo_scale_3D_callback(void* callback); - void register_on_gizmo_rotate_3D_callback(void* callback); - void register_on_gizmo_flatten_3D_callback(void* callback); - void register_on_update_geometry_3D_info_callback(void* callback); -#else - void register_on_gizmo_scale_uniformly_callback(void* callback); - void register_on_gizmo_rotate_callback(void* callback); - void register_on_gizmo_flatten_callback(void* callback); - void register_on_update_geometry_info_callback(void* callback); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - - // void register_action_add_callback(GLToolbarItem::Callback); - void register_action_add_callback(void* callback); - void register_action_delete_callback(void* callback); - void register_action_deleteall_callback(void* callback); - void register_action_arrange_callback(void* callback); - void register_action_more_callback(void* callback); - void register_action_fewer_callback(void* callback); - void register_action_split_callback(void* callback); - void register_action_cut_callback(void* callback); - void register_action_settings_callback(void* callback); - void register_action_layersediting_callback(void* callback); - void register_action_selectbyparts_callback(void* callback); - void bind_event_handlers(); void unbind_event_handlers(); @@ -714,8 +676,6 @@ private: void _zoom_to_bounding_box(const BoundingBoxf3& bbox); float _get_zoom_to_bounding_box_factor(const BoundingBoxf3& bbox) const; - void _deregister_callbacks(); - void _mark_volumes_for_layer_height() const; void _refresh_if_shown_on_screen(); diff --git a/src/slic3r/GUI/GLCanvas3DManager.cpp b/src/slic3r/GUI/GLCanvas3DManager.cpp index 771aa159e0..41f5ef22a8 100644 --- a/src/slic3r/GUI/GLCanvas3DManager.cpp +++ b/src/slic3r/GUI/GLCanvas3DManager.cpp @@ -587,246 +587,6 @@ void GLCanvas3DManager::reset_legend_texture(wxGLCanvas* canvas) it->second->reset_legend_texture(); } -void GLCanvas3DManager::register_on_viewport_changed_callback(wxGLCanvas* canvas, void* callback) -{ - CanvasesMap::iterator it = _get_canvas(canvas); - if (it != m_canvases.end()) - it->second->register_on_viewport_changed_callback(callback); -} - -void GLCanvas3DManager::register_on_double_click_callback(wxGLCanvas* canvas, void* callback) -{ - CanvasesMap::iterator it = _get_canvas(canvas); - if (it != m_canvases.end()) - it->second->register_on_double_click_callback(callback); -} - -void GLCanvas3DManager::register_on_right_click_callback(wxGLCanvas* canvas, void* callback) -{ - CanvasesMap::iterator it = _get_canvas(canvas); - if (it != m_canvases.end()) - it->second->register_on_right_click_callback(callback); -} - -void GLCanvas3DManager::register_on_select_object_callback(wxGLCanvas* canvas, void* callback) -{ - CanvasesMap::iterator it = _get_canvas(canvas); - if (it != m_canvases.end()) - it->second->register_on_select_object_callback(callback); -} - -void GLCanvas3DManager::register_on_model_update_callback(wxGLCanvas* canvas, void* callback) -{ - CanvasesMap::iterator it = _get_canvas(canvas); - if (it != m_canvases.end()) - it->second->register_on_model_update_callback(callback); -} - -void GLCanvas3DManager::register_on_remove_object_callback(wxGLCanvas* canvas, void* callback) -{ - CanvasesMap::iterator it = _get_canvas(canvas); - if (it != m_canvases.end()) - it->second->register_on_remove_object_callback(callback); -} - -void GLCanvas3DManager::register_on_arrange_callback(wxGLCanvas* canvas, void* callback) -{ - CanvasesMap::iterator it = _get_canvas(canvas); - if (it != m_canvases.end()) - it->second->register_on_arrange_callback(callback); -} - -void GLCanvas3DManager::register_on_rotate_object_left_callback(wxGLCanvas* canvas, void* callback) -{ - CanvasesMap::iterator it = _get_canvas(canvas); - if (it != m_canvases.end()) - it->second->register_on_rotate_object_left_callback(callback); -} - -void GLCanvas3DManager::register_on_rotate_object_right_callback(wxGLCanvas* canvas, void* callback) -{ - CanvasesMap::iterator it = _get_canvas(canvas); - if (it != m_canvases.end()) - it->second->register_on_rotate_object_right_callback(callback); -} - -void GLCanvas3DManager::register_on_scale_object_uniformly_callback(wxGLCanvas* canvas, void* callback) -{ - CanvasesMap::iterator it = _get_canvas(canvas); - if (it != m_canvases.end()) - it->second->register_on_scale_object_uniformly_callback(callback); -} - -void GLCanvas3DManager::register_on_increase_objects_callback(wxGLCanvas* canvas, void* callback) -{ - CanvasesMap::iterator it = _get_canvas(canvas); - if (it != m_canvases.end()) - it->second->register_on_increase_objects_callback(callback); -} - -void GLCanvas3DManager::register_on_decrease_objects_callback(wxGLCanvas* canvas, void* callback) -{ - CanvasesMap::iterator it = _get_canvas(canvas); - if (it != m_canvases.end()) - it->second->register_on_decrease_objects_callback(callback); -} - -void GLCanvas3DManager::register_on_instance_moved_callback(wxGLCanvas* canvas, void* callback) -{ - CanvasesMap::iterator it = _get_canvas(canvas); - if (it != m_canvases.end()) - it->second->register_on_instance_moved_callback(callback); -} - -void GLCanvas3DManager::register_on_wipe_tower_moved_callback(wxGLCanvas* canvas, void* callback) -{ - CanvasesMap::iterator it = _get_canvas(canvas); - if (it != m_canvases.end()) - it->second->register_on_wipe_tower_moved_callback(callback); -} - -void GLCanvas3DManager::register_on_enable_action_buttons_callback(wxGLCanvas* canvas, void* callback) -{ - CanvasesMap::iterator it = _get_canvas(canvas); - if (it != m_canvases.end()) - it->second->register_on_enable_action_buttons_callback(callback); -} - -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM -void GLCanvas3DManager::register_on_gizmo_scale_3D_callback(wxGLCanvas* canvas, void* callback) -{ - CanvasesMap::iterator it = _get_canvas(canvas); - if (it != m_canvases.end()) - it->second->register_on_gizmo_scale_3D_callback(callback); -} - -void GLCanvas3DManager::register_on_gizmo_rotate_3D_callback(wxGLCanvas* canvas, void* callback) -{ - CanvasesMap::iterator it = _get_canvas(canvas); - if (it != m_canvases.end()) - it->second->register_on_gizmo_rotate_3D_callback(callback); -} - -void GLCanvas3DManager::register_on_gizmo_flatten_3D_callback(wxGLCanvas* canvas, void* callback) -{ - CanvasesMap::iterator it = _get_canvas(canvas); - if (it != m_canvases.end()) - it->second->register_on_gizmo_flatten_3D_callback(callback); -} - -void GLCanvas3DManager::register_on_update_geometry_3D_info_callback(wxGLCanvas* canvas, void* callback) -{ - CanvasesMap::iterator it = _get_canvas(canvas); - if (it != m_canvases.end()) - it->second->register_on_update_geometry_3D_info_callback(callback); -} -#else -void GLCanvas3DManager::register_on_gizmo_scale_uniformly_callback(wxGLCanvas* canvas, void* callback) -{ - CanvasesMap::iterator it = _get_canvas(canvas); - if (it != m_canvases.end()) - it->second->register_on_gizmo_scale_uniformly_callback(callback); -} - -void GLCanvas3DManager::register_on_gizmo_rotate_callback(wxGLCanvas* canvas, void* callback) -{ - CanvasesMap::iterator it = _get_canvas(canvas); - if (it != m_canvases.end()) - it->second->register_on_gizmo_rotate_callback(callback); -} - -void GLCanvas3DManager::register_on_gizmo_flatten_callback(wxGLCanvas* canvas, void* callback) -{ - CanvasesMap::iterator it = _get_canvas(canvas); - if (it != m_canvases.end()) - it->second->register_on_gizmo_flatten_callback(callback); -} - -void GLCanvas3DManager::register_on_update_geometry_info_callback(wxGLCanvas* canvas, void* callback) -{ - CanvasesMap::iterator it = _get_canvas(canvas); - if (it != m_canvases.end()) - it->second->register_on_update_geometry_info_callback(callback); -} -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - -void GLCanvas3DManager::register_action_add_callback(wxGLCanvas* canvas, void* callback) -{ - CanvasesMap::iterator it = _get_canvas(canvas); - if (it != m_canvases.end()) - it->second->register_action_add_callback(callback); -} - -void GLCanvas3DManager::register_action_delete_callback(wxGLCanvas* canvas, void* callback) -{ - CanvasesMap::iterator it = _get_canvas(canvas); - if (it != m_canvases.end()) - it->second->register_action_delete_callback(callback); -} - -void GLCanvas3DManager::register_action_deleteall_callback(wxGLCanvas* canvas, void* callback) -{ - CanvasesMap::iterator it = _get_canvas(canvas); - if (it != m_canvases.end()) - it->second->register_action_deleteall_callback(callback); -} - -void GLCanvas3DManager::register_action_arrange_callback(wxGLCanvas* canvas, void* callback) -{ - CanvasesMap::iterator it = _get_canvas(canvas); - if (it != m_canvases.end()) - it->second->register_action_arrange_callback(callback); -} - -void GLCanvas3DManager::register_action_more_callback(wxGLCanvas* canvas, void* callback) -{ - CanvasesMap::iterator it = _get_canvas(canvas); - if (it != m_canvases.end()) - it->second->register_action_more_callback(callback); -} - -void GLCanvas3DManager::register_action_fewer_callback(wxGLCanvas* canvas, void* callback) -{ - CanvasesMap::iterator it = _get_canvas(canvas); - if (it != m_canvases.end()) - it->second->register_action_fewer_callback(callback); -} - -void GLCanvas3DManager::register_action_split_callback(wxGLCanvas* canvas, void* callback) -{ - CanvasesMap::iterator it = _get_canvas(canvas); - if (it != m_canvases.end()) - it->second->register_action_split_callback(callback); -} - -void GLCanvas3DManager::register_action_cut_callback(wxGLCanvas* canvas, void* callback) -{ - CanvasesMap::iterator it = _get_canvas(canvas); - if (it != m_canvases.end()) - it->second->register_action_cut_callback(callback); -} - -void GLCanvas3DManager::register_action_settings_callback(wxGLCanvas* canvas, void* callback) -{ - CanvasesMap::iterator it = _get_canvas(canvas); - if (it != m_canvases.end()) - it->second->register_action_settings_callback(callback); -} - -void GLCanvas3DManager::register_action_layersediting_callback(wxGLCanvas* canvas, void* callback) -{ - CanvasesMap::iterator it = _get_canvas(canvas); - if (it != m_canvases.end()) - it->second->register_action_layersediting_callback(callback); -} - -void GLCanvas3DManager::register_action_selectbyparts_callback(wxGLCanvas* canvas, void* callback) -{ - CanvasesMap::iterator it = _get_canvas(canvas); - if (it != m_canvases.end()) - it->second->register_action_selectbyparts_callback(callback); -} - wxGLCanvas* GLCanvas3DManager::create_wxglcanvas(wxWindow *parent) { int attribList[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER, WX_GL_DEPTH_SIZE, 24, WX_GL_SAMPLE_BUFFERS, GL_TRUE, WX_GL_SAMPLES, 4, 0 }; diff --git a/src/slic3r/GUI/GLCanvas3DManager.hpp b/src/slic3r/GUI/GLCanvas3DManager.hpp index d3b7b177cc..1a3036f9fb 100644 --- a/src/slic3r/GUI/GLCanvas3DManager.hpp +++ b/src/slic3r/GUI/GLCanvas3DManager.hpp @@ -20,7 +20,7 @@ typedef std::vector ExPolygons; class ModelObject; class PrintObject; class GCodePreviewData; - + namespace GUI { class GLCanvas3D; @@ -156,45 +156,6 @@ public: void reset_legend_texture(wxGLCanvas* canvas); - void register_on_viewport_changed_callback(wxGLCanvas* canvas, void* callback); - void register_on_double_click_callback(wxGLCanvas* canvas, void* callback); - void register_on_right_click_callback(wxGLCanvas* canvas, void* callback); - void register_on_select_object_callback(wxGLCanvas* canvas, void* callback); - void register_on_model_update_callback(wxGLCanvas* canvas, void* callback); - void register_on_remove_object_callback(wxGLCanvas* canvas, void* callback); - void register_on_arrange_callback(wxGLCanvas* canvas, void* callback); - void register_on_rotate_object_left_callback(wxGLCanvas* canvas, void* callback); - void register_on_rotate_object_right_callback(wxGLCanvas* canvas, void* callback); - void register_on_scale_object_uniformly_callback(wxGLCanvas* canvas, void* callback); - void register_on_increase_objects_callback(wxGLCanvas* canvas, void* callback); - void register_on_decrease_objects_callback(wxGLCanvas* canvas, void* callback); - void register_on_instance_moved_callback(wxGLCanvas* canvas, void* callback); - void register_on_wipe_tower_moved_callback(wxGLCanvas* canvas, void* callback); - void register_on_enable_action_buttons_callback(wxGLCanvas* canvas, void* callback); -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - void register_on_gizmo_scale_3D_callback(wxGLCanvas* canvas, void* callback); - void register_on_gizmo_rotate_3D_callback(wxGLCanvas* canvas, void* callback); - void register_on_gizmo_flatten_3D_callback(wxGLCanvas* canvas, void* callback); - void register_on_update_geometry_3D_info_callback(wxGLCanvas* canvas, void* callback); -#else - void register_on_gizmo_scale_uniformly_callback(wxGLCanvas* canvas, void* callback); - void register_on_gizmo_rotate_callback(wxGLCanvas* canvas, void* callback); - void register_on_gizmo_flatten_callback(wxGLCanvas* canvas, void* callback); - void register_on_update_geometry_info_callback(wxGLCanvas* canvas, void* callback); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - - void register_action_add_callback(wxGLCanvas* canvas, void* callback); - void register_action_delete_callback(wxGLCanvas* canvas, void* callback); - void register_action_deleteall_callback(wxGLCanvas* canvas, void* callback); - void register_action_arrange_callback(wxGLCanvas* canvas, void* callback); - void register_action_more_callback(wxGLCanvas* canvas, void* callback); - void register_action_fewer_callback(wxGLCanvas* canvas, void* callback); - void register_action_split_callback(wxGLCanvas* canvas, void* callback); - void register_action_cut_callback(wxGLCanvas* canvas, void* callback); - void register_action_settings_callback(wxGLCanvas* canvas, void* callback); - void register_action_layersediting_callback(wxGLCanvas* canvas, void* callback); - void register_action_selectbyparts_callback(wxGLCanvas* canvas, void* callback); - static bool can_multisample() { return s_multisample == MS_Enabled; } static wxGLCanvas* create_wxglcanvas(wxWindow *parent); diff --git a/src/slic3r/GUI/GLToolbar.cpp b/src/slic3r/GUI/GLToolbar.cpp index 196dc663f2..e1566e9440 100644 --- a/src/slic3r/GUI/GLToolbar.cpp +++ b/src/slic3r/GUI/GLToolbar.cpp @@ -16,9 +16,18 @@ namespace Slic3r { namespace GUI { -wxDEFINE_EVENT(EVT_GLTOOLBAR_ADD, wxCommandEvent); -wxDEFINE_EVENT(EVT_GLTOOLBAR_DELETE, wxCommandEvent); -wxDEFINE_EVENT(EVT_GLTOOLBAR_TODO_MORE, wxCommandEvent); +wxDEFINE_EVENT(EVT_GLTOOLBAR_ADD, SimpleEvent); +wxDEFINE_EVENT(EVT_GLTOOLBAR_DELETE, SimpleEvent); +wxDEFINE_EVENT(EVT_GLTOOLBAR_DELETE_ALL, SimpleEvent); +wxDEFINE_EVENT(EVT_GLTOOLBAR_ARRANGE, SimpleEvent); +wxDEFINE_EVENT(EVT_GLTOOLBAR_MORE, SimpleEvent); +wxDEFINE_EVENT(EVT_GLTOOLBAR_FEWER, SimpleEvent); +wxDEFINE_EVENT(EVT_GLTOOLBAR_SPLIT, SimpleEvent); +wxDEFINE_EVENT(EVT_GLTOOLBAR_CUT, SimpleEvent); +wxDEFINE_EVENT(EVT_GLTOOLBAR_SETTINGS, SimpleEvent); +wxDEFINE_EVENT(EVT_GLTOOLBAR_LAYERSEDITING, SimpleEvent); +wxDEFINE_EVENT(EVT_GLTOOLBAR_SELECTBYPARTS, SimpleEvent); + GLToolbarItem::Data::Data() : name("") @@ -57,10 +66,7 @@ const std::string& GLToolbarItem::get_tooltip() const void GLToolbarItem::do_action(wxEvtHandler *target) { - // if (m_data.action_callback != nullptr) - // m_data.action_callback->call(); - - wxPostEvent(target, wxCommandEvent(m_data.action_event)); + wxPostEvent(target, SimpleEvent(m_data.action_event)); } bool GLToolbarItem::is_enabled() const diff --git a/src/slic3r/GUI/GLToolbar.hpp b/src/slic3r/GUI/GLToolbar.hpp index 45d22e785a..43097c007c 100644 --- a/src/slic3r/GUI/GLToolbar.hpp +++ b/src/slic3r/GUI/GLToolbar.hpp @@ -5,10 +5,9 @@ #include #include -#include +#include "GLTexture.hpp" +#include "Event.hpp" -#include "../../slic3r/GUI/GLTexture.hpp" -// #include "callback.hpp" class wxEvtHandler; @@ -17,9 +16,17 @@ namespace GUI { class GLCanvas3D; -wxDECLARE_EVENT(EVT_GLTOOLBAR_ADD, wxCommandEvent); -wxDECLARE_EVENT(EVT_GLTOOLBAR_DELETE, wxCommandEvent); -wxDECLARE_EVENT(EVT_GLTOOLBAR_TODO_MORE, wxCommandEvent); +wxDECLARE_EVENT(EVT_GLTOOLBAR_ADD, SimpleEvent); +wxDECLARE_EVENT(EVT_GLTOOLBAR_DELETE, SimpleEvent); +wxDECLARE_EVENT(EVT_GLTOOLBAR_DELETE_ALL, SimpleEvent); +wxDECLARE_EVENT(EVT_GLTOOLBAR_ARRANGE, SimpleEvent); +wxDECLARE_EVENT(EVT_GLTOOLBAR_MORE, SimpleEvent); +wxDECLARE_EVENT(EVT_GLTOOLBAR_FEWER, SimpleEvent); +wxDECLARE_EVENT(EVT_GLTOOLBAR_SPLIT, SimpleEvent); +wxDECLARE_EVENT(EVT_GLTOOLBAR_CUT, SimpleEvent); +wxDECLARE_EVENT(EVT_GLTOOLBAR_SETTINGS, SimpleEvent); +wxDECLARE_EVENT(EVT_GLTOOLBAR_LAYERSEDITING, SimpleEvent); +wxDECLARE_EVENT(EVT_GLTOOLBAR_SELECTBYPARTS, SimpleEvent); class GLToolbarItem { @@ -41,16 +48,12 @@ public: Num_States }; - // typedef std::function Callback; - // typedef PerlCallback Callback; - struct Data { std::string name; std::string tooltip; unsigned int sprite_id; bool is_toggable; - // Callback *action_callback; wxEventType action_event; Data(); diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index 870867218d..988f6e507d 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -170,12 +170,6 @@ Preview::~Preview() } } -void Preview::register_on_viewport_changed_callback(void* callback) -{ - if ((m_canvas != nullptr) && (callback != nullptr)) - _3DScene::register_on_viewport_changed_callback(m_canvas, callback); -} - void Preview::set_number_extruders(unsigned int number_extruders) { if (m_number_extruders != number_extruders) diff --git a/src/slic3r/GUI/GUI_Preview.hpp b/src/slic3r/GUI/GUI_Preview.hpp index bdd69a0754..ed6d9cba32 100644 --- a/src/slic3r/GUI/GUI_Preview.hpp +++ b/src/slic3r/GUI/GUI_Preview.hpp @@ -50,7 +50,6 @@ public: Preview(wxNotebook* notebook, DynamicPrintConfig* config, Print* print, GCodePreviewData* gcode_preview_data); virtual ~Preview(); - void register_on_viewport_changed_callback(void* callback); void set_number_extruders(unsigned int number_extruders); void reset_gcode_preview_data(); void set_canvas_as_dirty(); @@ -64,7 +63,7 @@ public: void load_print(); void reload_print(bool force = false); void refresh_print(); - + private: bool init(wxNotebook* notebook, DynamicPrintConfig* config, Print* print, GCodePreviewData* gcode_preview_data); diff --git a/src/slic3r/GUI/GUI_PreviewIface.cpp b/src/slic3r/GUI/GUI_PreviewIface.cpp index 9048beb338..cbec512059 100644 --- a/src/slic3r/GUI/GUI_PreviewIface.cpp +++ b/src/slic3r/GUI/GUI_PreviewIface.cpp @@ -4,11 +4,6 @@ namespace Slic3r { -void PreviewIface::register_on_viewport_changed_callback(void* callback) -{ - m_preview->register_on_viewport_changed_callback(callback); -} - void PreviewIface::set_number_extruders(unsigned int number_extruders) { m_preview->set_number_extruders(number_extruders); diff --git a/src/slic3r/GUI/GUI_PreviewIface.hpp b/src/slic3r/GUI/GUI_PreviewIface.hpp index 86f155bd5a..df5fccaaf5 100644 --- a/src/slic3r/GUI/GUI_PreviewIface.hpp +++ b/src/slic3r/GUI/GUI_PreviewIface.hpp @@ -19,7 +19,6 @@ class PreviewIface public: explicit PreviewIface(GUI::Preview* preview) : m_preview(preview) {} - void register_on_viewport_changed_callback(void* callback); void set_number_extruders(unsigned int number_extruders); void reset_gcode_preview_data(); void reload_print(bool force = false); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index b13b5b65d2..e366e12b54 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1,6 +1,5 @@ #include "Plater.hpp" -#include // XXX #include #include #include @@ -30,6 +29,7 @@ #include "GUI_App.hpp" #include "MainFrame.hpp" #include "3DScene.hpp" +#include "GLCanvas3D.hpp" #include "GUI_ObjectParts.hpp" #include "GLToolbar.hpp" #include "GUI_Preview.hpp" @@ -273,7 +273,6 @@ Sidebar::Sidebar(wxWindow *parent) p->btn_send_gcode->SetBitmap(arrow_up); p->btn_send_gcode->Hide(); auto *btns_sizer_scrolled = new wxBoxSizer(wxHORIZONTAL); - std::cerr << "btns_sizer_scrolled: " << btns_sizer_scrolled << std::endl; btns_sizer_scrolled->Add(p->btn_send_gcode); // Info boxes @@ -285,7 +284,6 @@ Sidebar::Sidebar(wxWindow *parent) scrolled_sizer->SetMinSize(320, -1); p->scrolled->SetSizer(scrolled_sizer); p->scrolled->SetScrollbars(0, 1, 1, 1); - std::cerr << "scrolled_sizer: " << scrolled_sizer << std::endl; scrolled_sizer->Add(p->sizer_presets, 0, wxEXPAND | wxLEFT, 2); scrolled_sizer->Add(p->sizer_params, 1, wxEXPAND); scrolled_sizer->Add(p->object_info, 0, wxEXPAND | wxTOP | wxLEFT, 20); @@ -299,12 +297,10 @@ Sidebar::Sidebar(wxWindow *parent) p->btn_reslice->SetFont(wxGetApp().bold_font()); auto *btns_sizer = new wxBoxSizer(wxVERTICAL); - std::cerr << "btns_sizer: " << btns_sizer << std::endl; btns_sizer->Add(p->btn_reslice, 0, wxEXPAND | wxTOP, 5); btns_sizer->Add(p->btn_export_gcode, 0, wxEXPAND | wxTOP, 5); auto *sizer = new wxBoxSizer(wxVERTICAL); - std::cerr << "sizer: " << sizer << std::endl; sizer->Add(p->scrolled, 1, wxEXPAND | wxTOP, 5); sizer->Add(btns_sizer, 0, wxEXPAND | wxLEFT, 20); SetSizer(sizer); @@ -433,7 +429,7 @@ struct Plater::priv void on_update_print_preview(wxCommandEvent &); void on_process_completed(wxCommandEvent &); void on_layer_editing_toggled(bool enable); - void on_action_add(const wxCommandEvent&); + void on_action_add(SimpleEvent&); }; // TODO: multisample, see 3DScene.pm @@ -520,9 +516,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) : }); // 3DScene events: - // TODO: (?) - // on_layer_editing_toggled - // on_action_add + // TODO: more canvas3D->Bind(EVT_GLTOOLBAR_ADD, &priv::on_action_add, this); q->Bind(EVT_SLICING_COMPLETED, &priv::on_update_print_preview, this); @@ -567,7 +561,6 @@ std::vector Plater::priv::collect_selections() void Plater::priv::update(bool force_autocenter) { - wxWindowUpdateLocker freeze_guard(q); if (get_config("autocenter") == "1" || force_autocenter) { // auto *bed_shape_opt = config->opt("bed_shape"); @@ -876,7 +869,7 @@ void Plater::priv::on_layer_editing_toggled(bool enable) canvas3D->Update(); } -void Plater::priv::on_action_add(const wxCommandEvent&) +void Plater::priv::on_action_add(SimpleEvent&) { wxArrayString input_files; wxGetApp().open_model(q, input_files); From 83f55b608c49993ee3279f5b598748a36b04d979 Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Wed, 3 Oct 2018 14:07:10 +0200 Subject: [PATCH 055/186] Event.hpp: Set event object --- src/slic3r/GUI/Event.hpp | 28 ++++++++++++++++++---------- src/slic3r/GUI/GLCanvas3D.cpp | 3 ++- src/slic3r/GUI/GLCanvas3D.hpp | 6 +++--- 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/src/slic3r/GUI/Event.hpp b/src/slic3r/GUI/Event.hpp index ffcad7f9f0..63800fa00a 100644 --- a/src/slic3r/GUI/Event.hpp +++ b/src/slic3r/GUI/Event.hpp @@ -1,6 +1,7 @@ #ifndef slic3r_Events_hpp_ #define slic3r_Events_hpp_ + #include @@ -11,11 +12,14 @@ namespace GUI { struct SimpleEvent : public wxEvent { - SimpleEvent(wxEventType type, int id = 0) : wxEvent(id, type) {} + SimpleEvent(wxEventType type, wxObject* origin = nullptr) : wxEvent(0, type) + { + SetEventObject(origin); + } virtual wxEvent* Clone() const { - return new SimpleEvent(GetEventType(), GetId()); + return new SimpleEvent(GetEventType(), GetEventObject()); } }; @@ -23,26 +27,30 @@ template struct ArrayEvent : public wxEvent { std::array data; - ArrayEvent(wxEventType type, std::array data, int id = 0) - : wxEvent(id, type), data(std::move(data)) - {} + ArrayEvent(wxEventType type, std::array data, wxObject* origin = nullptr) + : wxEvent(0, type), data(std::move(data)) + { + SetEventObject(origin); + } virtual wxEvent* Clone() const { - return new ArrayEvent(GetEventType(), data, GetId()); + return new ArrayEvent(GetEventType(), data, GetEventObject()); } }; template struct ArrayEvent : public wxEvent { T data; - ArrayEvent(wxEventType type, T data, int id = 0) - : wxEvent(id, type), data(std::move(data)) - {} + ArrayEvent(wxEventType type, T data, wxObject* origin = nullptr) + : wxEvent(0, type), data(std::move(data)) + { + SetEventObject(origin); + } virtual wxEvent* Clone() const { - return new ArrayEvent(GetEventType(), data, GetId()); + return new ArrayEvent(GetEventType(), data, GetEventObject()); } }; diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index b6de0d820b..328d5af39e 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -2007,8 +2007,9 @@ GLCanvas3D::~GLCanvas3D() } } -void GLCanvas3D::post_event(const wxEvent &event) +void GLCanvas3D::post_event(wxEvent &&event) { + event.SetEventObject(m_canvas); wxPostEvent(m_canvas, event); } diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 055d62b6a2..04da729954 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -86,8 +86,8 @@ struct ObjectSelectEvent; wxDECLARE_EVENT(EVT_GLCANVAS_OBJECT_SELECT, ObjectSelectEvent); struct ObjectSelectEvent : public ArrayEvent { - ObjectSelectEvent(ptrdiff_t object_id, ptrdiff_t volume_id, int id = 0) - : ArrayEvent(EVT_GLCANVAS_OBJECT_SELECT, {object_id, volume_id}, id) + ObjectSelectEvent(ptrdiff_t object_id, ptrdiff_t volume_id, wxObject *origin = nullptr) + : ArrayEvent(EVT_GLCANVAS_OBJECT_SELECT, {object_id, volume_id}, origin) {} ptrdiff_t object_id() const { return data[0]; } @@ -546,7 +546,7 @@ class GLCanvas3D GCodePreviewVolumeIndex m_gcode_preview_volume_index; - void post_event(const wxEvent &event); + void post_event(wxEvent &&event); void viewport_changed(); public: GLCanvas3D(wxGLCanvas* canvas); From 6369e469c0160c46c918708bcbd28c8ef540b82f Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Wed, 3 Oct 2018 14:25:35 +0200 Subject: [PATCH 056/186] on_viewport_changed event handler --- src/slic3r/GUI/GUI_Preview.hpp | 2 ++ src/slic3r/GUI/Plater.cpp | 16 ++++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/GUI_Preview.hpp b/src/slic3r/GUI/GUI_Preview.hpp index ed6d9cba32..e7b7f4c941 100644 --- a/src/slic3r/GUI/GUI_Preview.hpp +++ b/src/slic3r/GUI/GUI_Preview.hpp @@ -50,6 +50,8 @@ public: Preview(wxNotebook* notebook, DynamicPrintConfig* config, Print* print, GCodePreviewData* gcode_preview_data); virtual ~Preview(); + wxGLCanvas* get_canvas() { return m_canvas; } + void set_number_extruders(unsigned int number_extruders); void reset_gcode_preview_data(); void set_canvas_as_dirty(); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index e366e12b54..9778df45c0 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -430,6 +430,8 @@ struct Plater::priv void on_process_completed(wxCommandEvent &); void on_layer_editing_toggled(bool enable); void on_action_add(SimpleEvent&); + + void on_viewport_changed(SimpleEvent& evt); }; // TODO: multisample, see 3DScene.pm @@ -493,8 +495,6 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) : update(); - // TODO: Preview::register_on_viewport_changed_callback is Perl-only - auto *hsizer = new wxBoxSizer(wxHORIZONTAL); hsizer->Add(notebook, 1, wxEXPAND | wxTOP, 1); hsizer->Add(sidebar, 0, wxEXPAND | wxLEFT | wxRIGHT, 0); @@ -518,6 +518,9 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) : // 3DScene events: // TODO: more canvas3D->Bind(EVT_GLTOOLBAR_ADD, &priv::on_action_add, this); + canvas3D->Bind(EVT_GLCANVAS_VIEWPORT_CHANGED, &priv::on_viewport_changed, this); + + preview->get_canvas()->Bind(EVT_GLCANVAS_VIEWPORT_CHANGED, &priv::on_viewport_changed, this); q->Bind(EVT_SLICING_COMPLETED, &priv::on_update_print_preview, this); q->Bind(EVT_PROCESS_COMPLETED, &priv::on_process_completed, this); @@ -881,6 +884,15 @@ void Plater::priv::on_action_add(SimpleEvent&) load_files(input_paths); } +void Plater::priv::on_viewport_changed(SimpleEvent& evt) +{ + wxObject* o = evt.GetEventObject(); + if (o == preview->get_canvas()) + preview->set_viewport_into_scene(canvas3D); + else if (o == canvas3D) + preview->set_viewport_from_scene(canvas3D); +} + // Plater / Public Plater::Plater(wxWindow *parent, MainFrame *main_frame) From 8f6e3cc43bf5de6c021f5df4b80bc68969ab84f0 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Wed, 3 Oct 2018 15:14:52 +0200 Subject: [PATCH 057/186] Temporary changes and code cleaning --- src/slic3r/GUI/GUI.cpp | 91 +++---------- src/slic3r/GUI/GUI.hpp | 8 -- src/slic3r/GUI/GUI_App.cpp | 18 ++- src/slic3r/GUI/GUI_App.hpp | 3 + src/slic3r/GUI/GUI_ObjectParts.cpp | 184 +------------------------- src/slic3r/GUI/GUI_ObjectParts.hpp | 13 +- src/slic3r/GUI/LambdaObjectDialog.cpp | 1 - src/slic3r/GUI/MainFrame.cpp | 2 - src/slic3r/GUI/Plater.cpp | 28 +++- src/slic3r/GUI/Plater.hpp | 13 ++ src/slic3r/GUI/Tab.cpp | 12 +- 11 files changed, 92 insertions(+), 281 deletions(-) diff --git a/src/slic3r/GUI/GUI.cpp b/src/slic3r/GUI/GUI.cpp index 8313f3bdab..2ec5028f5a 100644 --- a/src/slic3r/GUI/GUI.cpp +++ b/src/slic3r/GUI/GUI.cpp @@ -119,11 +119,6 @@ void break_to_debugger() // #ys_FIXME_for_delete std::vector g_tabs_list; -std::vector > m_optgroups; -double m_brim_width = 0.0; -size_t m_label_width = 100; -wxButton* g_wiping_dialog_button = nullptr; - //showed/hided controls according to the view mode wxWindow *g_right_panel = nullptr; wxBoxSizer *g_frequently_changed_parameters_sizer = nullptr; @@ -192,8 +187,6 @@ void set_objects_list_sizer(wxBoxSizer *objects_list_sizer){ g_object_list_sizer = objects_list_sizer; } -static wxString dots("…", wxConvUTF8); - void open_model(wxWindow *parent, wxArrayString& input_files){ auto dialog = new wxFileDialog(parent /*? parent : GetTopWindow()*/, _(L("Choose one or more files (STL/OBJ/AMF/3MF/PRUSA):")), @@ -432,11 +425,6 @@ void set_print_callback_event(Print *print, int id) wxWindow* get_right_panel(){ return g_right_panel; } - -const size_t& label_width(){ - return m_label_width; -} - void create_combochecklist(wxComboCtrl* comboCtrl, std::string text, std::string items, bool initial_value) { if (comboCtrl == nullptr) @@ -531,16 +519,18 @@ void set_model_events_from_perl(Model &model, // add_collapsible_panes(parent, sizer); } -void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFlexGridSizer* preset_sizer) +void Sidebar::add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer/*, wxFlexGridSizer* preset_sizer*/) { DynamicPrintConfig* config = &wxGetApp().preset_bundle->prints.get_edited_preset().config; std::shared_ptr optgroup = std::make_shared(parent, "", config); - const wxArrayInt& ar = preset_sizer->GetColWidths(); - m_label_width = ar.IsEmpty() ? 100 : ar.front()-4; - optgroup->label_width = m_label_width; +// const wxArrayInt& ar = preset_sizer->GetColWidths(); +// m_label_width = ar.IsEmpty() ? 100 : ar.front()-4; + optgroup->label_width = 100;// m_label_width; + + auto m_optgroups = get_optgroups(); //Frequently changed parameters - optgroup->m_on_change = [config](t_config_option_key opt_key, boost::any value){ + optgroup->m_on_change = [config, m_optgroups](t_config_option_key opt_key, boost::any value){ TabPrint* tab_print = nullptr; for (size_t i = 0; i < wxGetApp().tab_panel()->GetPageCount(); ++i) { Tab *tab = dynamic_cast(wxGetApp().tab_panel()->GetPage(i)); @@ -566,12 +556,12 @@ void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFl double brim_width = config->opt_float("brim_width"); if (boost::any_cast(value) == true) { - new_val = m_brim_width == 0.0 ? 10 : - m_brim_width < 0.0 ? m_brim_width * (-1) : - m_brim_width; + new_val = 10;// m_brim_width == 0.0 ? 10 : +// m_brim_width < 0.0 ? m_brim_width * (-1) : +// m_brim_width; } else{ - m_brim_width = brim_width * (-1); +// m_brim_width = brim_width * (-1); new_val = 0; } new_conf.set_key_value("brim_width", new ConfigOptionFloat(new_val)); @@ -617,7 +607,7 @@ void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFl option.opt.full_width = true; optgroup->append_single_option_line(option); - m_brim_width = config->opt_float("brim_width"); + auto m_brim_width = config->opt_float("brim_width"); def.label = L("Brim"); def.type = coBool; def.tooltip = L("This flag enables the brim that will be printed around each object on the first layer."); @@ -628,7 +618,8 @@ void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFl Line line = { "", "" }; - line.widget = [config](wxWindow* parent){ + line.widget = [config, this](wxWindow* parent){ + auto g_wiping_dialog_button = get_wiping_dialog_button(); g_wiping_dialog_button = new wxButton(parent, wxID_ANY, _(L("Purging volumes")) + dots, wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT); auto sizer = new wxBoxSizer(wxHORIZONTAL); sizer->Add(g_wiping_dialog_button); @@ -655,26 +646,6 @@ void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFl sizer->Add(optgroup->sizer, 0, wxEXPAND | wxBOTTOM | wxLEFT, 2); m_optgroups.push_back(optgroup);// ogFrequentlyChangingParameters - - // Object List - add_objects_list(parent, sizer); - - // Frequently Object Settings - add_object_settings(parent, sizer); -} - -void show_frequently_changed_parameters(bool show) -{ - g_frequently_changed_parameters_sizer->Show(show); - if (!show) return; - - for (size_t i = 0; i < wxGetApp().tab_panel()->GetPageCount(); ++i) { - Tab *tab = dynamic_cast(wxGetApp().tab_panel()->GetPage(i)); - if (!tab) - continue; - tab->update_wiping_button_visibility(); - break; - } } void show_buttons(bool show) @@ -706,42 +677,14 @@ void show_object_name(bool show) grid_sizer->Show(static_cast(1), show); } -void update_mode() -{ - wxWindowUpdateLocker noUpdates(g_right_panel->GetParent()); - - ConfigMenuIDs mode = wxGetApp().get_view_mode(); - - g_object_list_sizer->Show(mode == ConfigMenuModeExpert); - show_info_sizer(mode == ConfigMenuModeExpert); - show_buttons(mode == ConfigMenuModeExpert); - show_object_name(mode == ConfigMenuModeSimple); - show_manipulation_sizer(mode == ConfigMenuModeSimple); - - // TODO There is a not the best place of it! - // *** Update showing of the collpane_settings -// show_collpane_settings(mode == ConfigMenuModeExpert); - // ************************* - g_right_panel->Layout(); - g_right_panel->GetParent()->Layout(); -} - -bool is_expert_mode(){ - return wxGetApp().get_view_mode() == ConfigMenuModeExpert; -} - ConfigOptionsGroup* get_optgroup(size_t i) { - return m_optgroups.empty() ? nullptr : m_optgroups[i].get(); + return wxGetApp().mainframe->m_plater->sidebar().get_optgroup(i); +// return m_optgroups.empty() ? nullptr : m_optgroups[i].get(); } std::vector >& get_optgroups() { - return m_optgroups; -} - -wxButton* get_wiping_dialog_button() -{ - return g_wiping_dialog_button; + return wxGetApp().mainframe->m_plater->sidebar().get_optgroups();//m_optgroups; } wxWindow* export_option_creator(wxWindow* parent) diff --git a/src/slic3r/GUI/GUI.hpp b/src/slic3r/GUI/GUI.hpp index 215a72b608..de17ff7a28 100644 --- a/src/slic3r/GUI/GUI.hpp +++ b/src/slic3r/GUI/GUI.hpp @@ -117,7 +117,6 @@ void set_gui_appctl(); void open_model(wxWindow *parent, wxArrayString& input_files); wxWindow* get_right_panel(); -const size_t& label_width(); Tab* get_tab(const std::string& name); std::vector* get_preset_tabs(); @@ -150,9 +149,6 @@ void warning_catcher(wxWindow* parent, const wxString& message); // to deliver a progress status message. void set_print_callback_event(Print *print, int id); -// update right panel of the Plater according to view mode -void update_mode(); - void show_info_sizer(const bool show); // Creates a wxCheckListBoxComboPopup inside the given wxComboCtrl, filled with the given text and items. @@ -177,16 +173,12 @@ void set_model_events_from_perl(Model &model, int event_remove_object, int event_update_scene); void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFlexGridSizer* preset_sizer); -// Update view mode according to selected menu -void update_mode(); -bool is_expert_mode(); // Callback to trigger a configuration update timer on the Plater. static PerlCallback g_on_request_update_callback; ConfigOptionsGroup* get_optgroup(size_t i); std::vector >& get_optgroups(); -wxButton* get_wiping_dialog_button(); void add_export_option(wxFileDialog* dlg, const std::string& format); int get_export_option(wxFileDialog* dlg); diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 4407c44c1d..00071f01d8 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -26,6 +26,7 @@ #include "Preferences.hpp" #include "Tab.hpp" #include +#include namespace Slic3r { namespace GUI { @@ -488,7 +489,22 @@ ConfigMenuIDs GUI_App::get_view_mode() return mode == "expert" ? ConfigMenuModeExpert : ConfigMenuModeSimple; } -static wxString dots("…", wxConvUTF8); +// Update view mode according to selected menu +void GUI_App::update_mode() +{ + wxWindowUpdateLocker noUpdates(/*g_right_panel->GetParent()*/mainframe); + + ConfigMenuIDs mode = wxGetApp().get_view_mode(); + +// g_object_list_sizer->Show(mode == ConfigMenuModeExpert); + show_info_sizer(mode == ConfigMenuModeExpert); +// show_buttons(mode == ConfigMenuModeExpert); +// show_object_name(mode == ConfigMenuModeSimple); + show_manipulation_sizer(mode == ConfigMenuModeSimple); + + /*g_right_panel*/mainframe->m_plater->Layout(); + /*g_right_panel->GetParent()*/mainframe->Layout(); +} void GUI_App::add_config_menu(wxMenuBar *menu) { diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index d6d085166b..e084481dd3 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -42,6 +42,8 @@ enum ConfigMenuIDs { class Tab; +static wxString dots("…", wxConvUTF8); + class GUI_App : public wxApp { bool no_plater{ false }; @@ -112,6 +114,7 @@ public: void get_installed_languages(wxArrayString & names, wxArrayLong & identifiers); ConfigMenuIDs get_view_mode(); + void update_mode(); void add_config_menu(wxMenuBar *menu); bool check_unsaved_changes(); diff --git a/src/slic3r/GUI/GUI_ObjectParts.cpp b/src/slic3r/GUI/GUI_ObjectParts.cpp index fc36e7fdb5..6e6b1cf983 100644 --- a/src/slic3r/GUI/GUI_ObjectParts.cpp +++ b/src/slic3r/GUI/GUI_ObjectParts.cpp @@ -158,8 +158,6 @@ void init_mesh_icons(){ bool is_parts_changed(){return m_parts_changed;} bool is_part_settings_changed(){ return m_part_settings_changed; } -static wxString dots("…", wxConvUTF8); - void set_tooltip_for_item(const wxPoint& pt) { wxDataViewItem item; @@ -452,34 +450,7 @@ wxSizer* object_movers(wxWindow *win) return optgroup->sizer; } -wxBoxSizer* content_settings(wxWindow *win) -{ - DynamicPrintConfig* config = &wxGetApp().preset_bundle->/*full_config();//*/printers.get_edited_preset().config; // TODO get config from Model_volume - std::shared_ptr optgroup = std::make_shared(win, "Extruders", config); - optgroup->label_width = label_width(); - - Option option = optgroup->get_option("extruder"); - option.opt.default_value = new ConfigOptionInt(1); - optgroup->append_single_option_line(option); - - get_optgroups().push_back(optgroup); // ogObjectSettings - - auto sizer = new wxBoxSizer(wxVERTICAL); - sizer->Add(create_edit_object_buttons(win), 0, wxEXPAND, 0); // *** Edit Object Buttons*** - - sizer->Add(optgroup->sizer, 1, wxEXPAND | wxLEFT, 20); - - auto add_btn = new wxButton(win, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER); - if (wxMSW) add_btn->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); - add_btn->SetBitmap(wxBitmap(from_u8(Slic3r::var("add.png")), wxBITMAP_TYPE_PNG)); - sizer->Add(add_btn, 0, wxALIGN_LEFT | wxLEFT, 20); - - sizer->Add(object_movers(win), 0, wxEXPAND | wxLEFT, 20); - - return sizer; -} - -void add_objects_list(wxWindow* parent, wxBoxSizer* sizer) +void Sidebar::add_objects_list(wxWindow* parent, wxBoxSizer* sizer) { const auto ol_sizer = create_objects_list(parent); sizer->Add(ol_sizer, 1, wxEXPAND | wxTOP, 20); @@ -535,13 +506,13 @@ Line add_og_to_object_settings(const std::string& option_name, const std::string return line; } -void add_object_settings(wxWindow* parent, wxBoxSizer* sizer) +void Sidebar::add_object_settings(wxWindow* parent, wxBoxSizer* sizer, t_optgroups& optgroups) { auto optgroup = std::make_shared(parent, _(L("Object Settings"))); optgroup->label_width = 100; optgroup->set_grid_vgap(5); - optgroup->m_on_change = [](t_config_option_key opt_key, boost::any value){ + optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value){ if (opt_key == "scale_unit"){ const wxString& selection = boost::any_cast(value); std::vector axes{ "x", "y", "z" }; @@ -566,7 +537,6 @@ void add_object_settings(wxWindow* parent, wxBoxSizer* sizer) def.default_value = new ConfigOptionString{ " " }; optgroup->append_single_option_line(Option(def, "object_name")); - // Legend for object modification auto line = Line{ "", "" }; def.label = ""; @@ -604,54 +574,7 @@ void add_object_settings(wxWindow* parent, wxBoxSizer* sizer) optgroup->disable(); - get_optgroups().push_back(optgroup); // ogFrequentlyObjectSettings -} - - -// add Collapsible Pane to sizer -wxCollapsiblePane* add_collapsible_pane(wxWindow* parent, wxBoxSizer* sizer_parent, const wxString& name, std::function content_function) -{ -#ifdef __WXMSW__ - auto *collpane = new PrusaCollapsiblePaneMSW(parent, wxID_ANY, name); -#else - auto *collpane = new PrusaCollapsiblePane/*wxCollapsiblePane*/(parent, wxID_ANY, name); -#endif // __WXMSW__ - // add the pane with a zero proportion value to the sizer which contains it - sizer_parent->Add(collpane, 0, wxGROW | wxALL, 0); - - wxWindow *win = collpane->GetPane(); - - wxSizer *sizer = content_function(win); - - wxSizer *sizer_pane = new wxBoxSizer(wxVERTICAL); - sizer_pane->Add(sizer, 1, wxGROW | wxEXPAND | wxBOTTOM, 2); - win->SetSizer(sizer_pane); - // sizer_pane->SetSizeHints(win); - return collpane; -} - -void add_collapsible_panes(wxWindow* parent, wxBoxSizer* sizer) -{ - // *** Objects List *** - auto collpane = add_collapsible_pane(parent, sizer, "Objects List:", create_objects_list); - collpane->Bind(wxEVT_COLLAPSIBLEPANE_CHANGED, ([collpane](wxCommandEvent& e){ - // wxWindowUpdateLocker noUpdates(g_right_panel); - if (collpane->IsCollapsed()) { - m_sizer_object_buttons->Show(false); - m_sizer_part_buttons->Show(false); - m_sizer_object_movers->Show(false); - if (!m_objects_ctrl->HasSelection()) - m_collpane_settings->Show(false); - } - })); - - // *** Object/Part Settings *** - m_collpane_settings = add_collapsible_pane(parent, sizer, "Object Settings", content_settings); -} - -void show_collpane_settings(bool expert_mode) -{ - m_collpane_settings->Show(expert_mode && !m_objects_model->IsEmpty()); + optgroups.push_back(optgroup); // ogFrequentlyObjectSettings } void add_object_to_list(const std::string &name, ModelObject* model_object) @@ -695,17 +618,12 @@ void delete_object_from_list() m_objects_model->Delete(item); part_selection_changed(); - -// if (m_objects_model->IsEmpty()) -// m_collpane_settings->Show(false); } void delete_all_objects_from_list() { m_objects_model->DeleteAll(); - part_selection_changed(); -// m_collpane_settings->Show(false); } void set_object_count(int idx, int count) @@ -1629,100 +1547,6 @@ void part_selection_changed() m_selected_object_id = obj_idx; update_settings_value(); - -/* wxWindowUpdateLocker noUpdates(get_right_panel()); - - m_move_options = Point3(0, 0, 0); - m_last_coords = Point3(0, 0, 0); - // reset move sliders - std::vector opt_keys = {"x", "y", "z"}; - auto og = get_optgroup(ogObjectMovers); - for (auto opt_key: opt_keys) - og->set_value(opt_key, int(0)); - -// if (!item || m_selected_object_id < 0){ - if (m_selected_object_id < 0){ - m_sizer_object_buttons->Show(false); - m_sizer_part_buttons->Show(false); - m_sizer_object_movers->Show(false); - m_collpane_settings->Show(false); - return; - } - - m_collpane_settings->Show(true); - - auto volume_id = m_objects_model->GetVolumeIdByItem(item); - if (volume_id < 0){ - m_sizer_object_buttons->Show(true); - m_sizer_part_buttons->Show(false); - m_sizer_object_movers->Show(false); - m_collpane_settings->SetLabelText(_(L("Object Settings")) + ":"); - -// elsif($itemData->{type} eq 'object') { -// # select nothing in 3D preview -// -// # attach object config to settings panel -// $self->{optgroup_movers}->disable; -// $self->{staticbox}->SetLabel('Object Settings'); -// @opt_keys = (map @{$_->get_keys}, Slic3r::Config::PrintObject->new, Slic3r::Config::PrintRegion->new); -// $config = $self->{model_object}->config; -// } - - return; - } - - m_collpane_settings->SetLabelText(_(L("Part Settings")) + ":"); - - m_sizer_object_buttons->Show(false); - m_sizer_part_buttons->Show(true); - m_sizer_object_movers->Show(true); - - auto bb_size = m_objects[m_selected_object_id]->bounding_box().size(); - int scale = 10; //?? - - m_mover_x->SetMin(-bb_size.x * 4 * scale); - m_mover_x->SetMax(bb_size.x * 4 * scale); - - m_mover_y->SetMin(-bb_size.y * 4 * scale); - m_mover_y->SetMax(bb_size.y * 4 * scale); - - m_mover_z->SetMin(-bb_size.z * 4 * scale); - m_mover_z->SetMax(bb_size.z * 4 * scale); - - - -// my ($config, @opt_keys); - m_btn_move_up->Enable(volume_id > 0); - m_btn_move_down->Enable(volume_id + 1 < m_objects[m_selected_object_id]->volumes.size()); - - // attach volume config to settings panel - auto volume = m_objects[m_selected_object_id]->volumes[volume_id]; - - if (volume->modifier) - og->enable(); - else - og->disable(); - -// auto config = volume->config; - - // get default values -// @opt_keys = @{Slic3r::Config::PrintRegion->new->get_keys}; -// } -/* - # get default values - my $default_config = Slic3r::Config::new_from_defaults_keys(\@opt_keys); - - # append default extruder - push @opt_keys, 'extruder'; - $default_config->set('extruder', 0); - $config->set_ifndef('extruder', 0); - $self->{settings_panel}->set_default_config($default_config); - $self->{settings_panel}->set_config($config); - $self->{settings_panel}->set_opt_keys(\@opt_keys); - $self->{settings_panel}->set_fixed_options([qw(extruder)]); - $self->{settings_panel}->enable; - } - */ } void set_extruder_column_hidden(bool hide) diff --git a/src/slic3r/GUI/GUI_ObjectParts.hpp b/src/slic3r/GUI/GUI_ObjectParts.hpp index 8189238f02..01011d2c4e 100644 --- a/src/slic3r/GUI/GUI_ObjectParts.hpp +++ b/src/slic3r/GUI/GUI_ObjectParts.hpp @@ -1,5 +1,6 @@ #ifndef slic3r_GUI_ObjectParts_hpp_ #define slic3r_GUI_ObjectParts_hpp_ +// #include "OptionsGroup.hpp" class wxWindow; class wxSizer; @@ -17,15 +18,13 @@ class ModelObject; class Model; namespace GUI { -//class wxGLCanvas; +class ConfigOptionsGroup; +using t_optgroups = std::vector >; enum ogGroup{ ogFrequentlyChangingParameters, ogFrequentlyObjectSettings, - ogCurrentSettings -// ogObjectSettings, -// ogObjectMovers, -// ogPartSettings + ogObjectSettings }; enum LambdaTypeIDs{ @@ -49,10 +48,8 @@ struct OBJECT_PARAMETERS typedef std::map t_category_icon; inline t_category_icon& get_category_icon(); -void add_collapsible_panes(wxWindow* parent, wxBoxSizer* sizer); void add_objects_list(wxWindow* parent, wxBoxSizer* sizer); -void add_object_settings(wxWindow* parent, wxBoxSizer* sizer); -void show_collpane_settings(bool expert_mode); +void add_object_settings(wxWindow* parent, wxBoxSizer* sizer, t_optgroups& optgroups); wxMenu *create_add_settings_popupmenu(bool is_part); wxMenu *create_add_part_popupmenu(); diff --git a/src/slic3r/GUI/LambdaObjectDialog.cpp b/src/slic3r/GUI/LambdaObjectDialog.cpp index 7d741be7ff..d1d8e60467 100644 --- a/src/slic3r/GUI/LambdaObjectDialog.cpp +++ b/src/slic3r/GUI/LambdaObjectDialog.cpp @@ -8,7 +8,6 @@ namespace Slic3r { namespace GUI { -static wxString dots("…", wxConvUTF8); LambdaObjectDialog::LambdaObjectDialog(wxWindow* parent, const wxString type_name): diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 23e7e07933..502394aca8 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -23,8 +23,6 @@ namespace Slic3r { namespace GUI { -static wxString dots("…", wxConvUTF8); - MainFrame::MainFrame(const bool no_plater, const bool loaded) : wxFrame(NULL, wxID_ANY, SLIC3R_BUILD, wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE), m_no_plater(no_plater), diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index b13b5b65d2..241fda0c0f 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -40,6 +40,7 @@ #include "slic3r/Utils/ASCIIFolding.hpp" #include // Needs to be last because reasons :-/ +#include "WipeTowerDialog.hpp" namespace fs = boost::filesystem; using Slic3r::_3DScene; @@ -222,6 +223,12 @@ struct Sidebar::priv wxButton *btn_reslice; // wxButton *btn_print; // XXX: remove wxButton *btn_send_gcode; + + std::vector > optgroups {}; + double brim_width = 0.0; + size_t label_width = 100; + wxButton* btn_wiping_dialog {nullptr}; + }; @@ -265,7 +272,12 @@ Sidebar::Sidebar(wxWindow *parent) // Frequently changed parameters p->sizer_params = new wxBoxSizer(wxVERTICAL); - GUI::add_frequently_changed_parameters(p->scrolled, p->sizer_params, p->sizer_presets); + add_frequently_changed_parameters(p->scrolled, p->sizer_params/*, p->sizer_presets*/); + + // Object List + add_objects_list(p->scrolled, p->sizer_params); + // Frequently Object Settings + add_object_settings(p->scrolled, p->sizer_params, p->optgroups); // Buttons in the scrolled area wxBitmap arrow_up(GUI::from_u8(Slic3r::var("brick_go.png")), wxBITMAP_TYPE_PNG); @@ -356,6 +368,20 @@ void Sidebar::update_presets(Preset::Type preset_type) // wxTheApp->{preset_bundle}->export_selections(wxTheApp->{app_config}); } +ConfigOptionsGroup* Sidebar::get_optgroup(size_t i) +{ + return p->optgroups.empty() ? nullptr : p->optgroups[i].get(); +} + +t_optgroups& Sidebar::get_optgroups() { + return p->optgroups; +} + +wxButton* Sidebar::get_wiping_dialog_button() +{ + return p->btn_wiping_dialog; +} + // Plater::Object diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 415e9faab7..14de626741 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -8,11 +8,15 @@ #include "Preset.hpp" +class wxBoxSizer; namespace Slic3r { namespace GUI { class MainFrame; +class ConfigOptionsGroup; + +using t_optgroups = std::vector >; class Sidebar : public wxPanel { @@ -25,6 +29,15 @@ public: ~Sidebar(); void update_presets(Slic3r::Preset::Type preset_type); + + void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer); + void add_objects_list(wxWindow* parent, wxBoxSizer* sizer); + void add_object_settings(wxWindow* parent, wxBoxSizer* sizer, t_optgroups& optgroups); + + + ConfigOptionsGroup* get_optgroup(size_t i); + t_optgroups& get_optgroups(); + wxButton* get_wiping_dialog_button(); private: struct priv; std::unique_ptr p; diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index c83fd6df5b..07063a6bb4 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -33,9 +33,6 @@ namespace Slic3r { namespace GUI { -static wxString dots("…", wxConvUTF8); - -// sub new void Tab::create_preset_tab(PresetBundle *preset_bundle) { m_preset_bundle = preset_bundle; @@ -720,9 +717,12 @@ void Tab::update_wiping_button_visibility() { bool multiple_extruders = dynamic_cast((m_preset_bundle->printers.get_edited_preset().config).option("nozzle_diameter"))->values.size() > 1; bool single_extruder_mm = dynamic_cast( (m_preset_bundle->printers.get_edited_preset().config).option("single_extruder_multi_material"))->value; - if (get_wiping_dialog_button()) { - get_wiping_dialog_button()->Show(wipe_tower_enabled && multiple_extruders && single_extruder_mm); - (get_wiping_dialog_button()->GetParent())->Layout(); + if (!wxGetApp().mainframe) + return; + auto wiping_dialog_button = wxGetApp().mainframe->m_plater->sidebar().get_wiping_dialog_button(); + if (wiping_dialog_button) { + wiping_dialog_button->Show(wipe_tower_enabled && multiple_extruders && single_extruder_mm); + wiping_dialog_button->GetParent()->Layout(); } } From b3c09a9254a7b05ea03c2bcd4fbcf78ee5ec8766 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Wed, 3 Oct 2018 16:18:23 +0200 Subject: [PATCH 058/186] Fixed object position after loading --- src/slic3r/GUI/GLCanvas3D.cpp | 1 + src/slic3r/GUI/Plater.cpp | 15 +++++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 328d5af39e..2414e8c9b5 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -315,6 +315,7 @@ bool GLCanvas3D::Bed::set_shape(const Pointfs& shape) if (m_shape == shape && m_type == new_type) // No change, no need to update the UI. return false; + m_shape = shape; m_type = new_type; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 9778df45c0..5ac4b2d84c 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -420,7 +420,8 @@ struct Plater::priv void update_ui_from_settings(); ProgressStatusBar* statusbar(); std::string get_config(const std::string &key) const; - BoundingBox bed_shape_bb() const; + BoundingBoxf bed_shape_bb() const; + BoundingBox scaled_bed_shape_bb() const; std::vector load_files(const std::vector &input_files); std::vector load_model_objects(const ModelObjectPtrs &model_objects); @@ -569,7 +570,7 @@ void Plater::priv::update(bool force_autocenter) // auto *bed_shape_opt = config->opt("bed_shape"); // const auto bed_shape = Slic3r::Polygon::new_scale(bed_shape_opt->values); // const BoundingBox bed_shape_bb = bed_shape.bounding_box(); - const Vec2d bed_center = bed_shape_bb().center().cast(); + const Vec2d& bed_center = bed_shape_bb().center(); model.center_instances_around_point(bed_center); } @@ -605,7 +606,13 @@ std::string Plater::priv::get_config(const std::string &key) const return wxGetApp().app_config->get(key); } -BoundingBox Plater::priv::bed_shape_bb() const +BoundingBoxf Plater::priv::bed_shape_bb() const +{ + BoundingBox bb = scaled_bed_shape_bb(); + return BoundingBoxf(unscale(bb.min), unscale(bb.max)); +} + +BoundingBox Plater::priv::scaled_bed_shape_bb() const { const auto *bed_shape_opt = config->opt("bed_shape"); const auto bed_shape = Slic3r::Polygon::new_scale(bed_shape_opt->values); @@ -732,7 +739,7 @@ Vec3crd to_3d(const Point &p, coord_t z) { return Vec3crd(p(0), p(1), z); } std::vector Plater::priv::load_model_objects(const ModelObjectPtrs &model_objects) { - const BoundingBox bed_shape = bed_shape_bb(); + const BoundingBoxf bed_shape = bed_shape_bb(); const Vec3d bed_center = to_3d(bed_shape.center().cast(), 0.0); const Vec3d bed_size = to_3d(bed_shape.size().cast(), 1.0); From f31cf684cb8ca19ec723218753fc346490ce0701 Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Wed, 3 Oct 2018 16:27:02 +0200 Subject: [PATCH 059/186] Tab preset & value change events --- src/slic3r/GUI/Event.hpp | 3 ++ src/slic3r/GUI/MainFrame.cpp | 87 ++++++++++++++++++++++-------------- src/slic3r/GUI/MainFrame.hpp | 3 ++ src/slic3r/GUI/Plater.cpp | 21 +++++---- src/slic3r/GUI/Tab.cpp | 52 ++++++++++----------- src/slic3r/GUI/Tab.hpp | 16 +++---- 6 files changed, 102 insertions(+), 80 deletions(-) diff --git a/src/slic3r/GUI/Event.hpp b/src/slic3r/GUI/Event.hpp index 63800fa00a..2ae9fd154d 100644 --- a/src/slic3r/GUI/Event.hpp +++ b/src/slic3r/GUI/Event.hpp @@ -14,6 +14,7 @@ struct SimpleEvent : public wxEvent { SimpleEvent(wxEventType type, wxObject* origin = nullptr) : wxEvent(0, type) { + m_propagationLevel = wxEVENT_PROPAGATE_MAX; SetEventObject(origin); } @@ -30,6 +31,7 @@ template struct ArrayEvent : public wxEvent ArrayEvent(wxEventType type, std::array data, wxObject* origin = nullptr) : wxEvent(0, type), data(std::move(data)) { + m_propagationLevel = wxEVENT_PROPAGATE_MAX; SetEventObject(origin); } @@ -45,6 +47,7 @@ template struct ArrayEvent : public wxEvent ArrayEvent(wxEventType type, T data, wxObject* origin = nullptr) : wxEvent(0, type), data(std::move(data)) { + m_propagationLevel = wxEVENT_PROPAGATE_MAX; SetEventObject(origin); } diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 1aba0f7c7f..d24a2d5df9 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include "Tab.hpp" #include "PresetBundle.hpp" @@ -168,40 +169,10 @@ void MainFrame::init_tabpanel() // m_config->save(Slic3r::GUI::autosave) ; // }); - // The following event is emited by the C++ Tab implementation on preset selection, + // The following event is emited by Tab on preset selection, // or when the preset's "modified" status changes. -// EVT_COMMAND($self, -1, $PRESETS_CHANGED_EVENT, sub { -// my($self, $event) = @_; -// auto tab_name = event->GetString; -// -// Tab* tab = Slic3r::GUI::get_preset_tab(tab_name); -// if (m_plater) { -// // Update preset combo boxes(Print settings, Filament, Material, Printer) from their respective tabs. -// auto presets = tab->get_presets(); -// if (presets){ -// auto reload_dependent_tabs = tab->get_dependent_tabs(); -// m_plater->update_presets(tab_name, reload_dependent_tabs, presets); -// m_plater->{"selected_item_$tab_name"} = tab->get_selected_preset_item(); -// if (tab_name == "printer") { -// // Printer selected at the Printer tab, update "compatible" marks at the print and filament selectors. -// std::vector tab_names_other = { "print", "filament", "sla_materialprinter" }; -// for (const auto tab_name_other : tab_names_other) { -// Tab* cur_tab = m_options_tabs[tab_name_other]; -// // If the printer tells us that the print or filament preset has been switched or invalidated, -// // refresh the print or filament tab page.Otherwise just refresh the combo box. -// if (reload_dependent_tabs.empty() || -// find(reload_dependent_tabs.begin(), reload_dependent_tabs.end(), tab_name_other) == -// reload_dependent_tabs.end() ) -// cur_tab->update_tab_ui(); -// else -// cur_tab->load_current_preset(); -// -// } -// } -// m_plater->on_config_change(tab->get_config()); -// } -// } -// }); + Bind(EVT_TAB_PRESETS_CHANGED, &MainFrame::on_presets_changed, this); + // The following event is emited by the C++ Tab implementation on object selection change. // EVT_COMMAND($self, -1, $OBJECT_SELECTION_CHANGED_EVENT, sub { @@ -791,6 +762,56 @@ wxMenuItem* MainFrame::append_menu_item(wxMenu* menu, return item; } +void MainFrame::on_presets_changed(SimpleEvent &event) +{ + auto *tab = dynamic_cast(event.GetEventObject()); + wxASSERT(tab != nullptr); + if (tab == nullptr) { + return; + } + + // Update preset combo boxes(Print settings, Filament, Material, Printer) from their respective tabs. + auto presets = tab->get_presets(); + if (presets) { + auto reload_dependent_tabs = tab->get_dependent_tabs(); + + // FIXME: The preset type really should be a property of Tab instead + Slic3r::Preset::Type preset_type; + if (tab == m_options_tabs["print"]) { preset_type = Slic3r::Preset::TYPE_PRINT; } + else if (tab == m_options_tabs["filament"]) { preset_type = Slic3r::Preset::TYPE_FILAMENT; } + else if (tab == m_options_tabs["sla_material"]) { preset_type = Slic3r::Preset::TYPE_SLA_MATERIAL; } + else if (tab == m_options_tabs["printer"]) { preset_type = Slic3r::Preset::TYPE_PRINTER; } + else { + wxASSERT(false); + return; + } + + m_plater->sidebar().update_presets(preset_type); + + // XXX: ??? + // m_plater->{"selected_item_$tab_name"} = tab->get_selected_preset_item(); + + if (preset_type == Slic3r::Preset::TYPE_PRINTER) { + // Printer selected at the Printer tab, update "compatible" marks at the print and filament selectors. + // XXX: Do this in a more C++ way + std::vector tab_names_other = { "print", "filament", "sla_material" }; + for (const auto tab_name_other : tab_names_other) { + Tab* cur_tab = m_options_tabs[tab_name_other]; + // If the printer tells us that the print or filament preset has been switched or invalidated, + // refresh the print or filament tab page.Otherwise just refresh the combo box. + if (reload_dependent_tabs.empty() || + find(reload_dependent_tabs.begin(), reload_dependent_tabs.end(), tab_name_other) == + reload_dependent_tabs.end() ) + cur_tab->update_tab_ui(); + else + cur_tab->load_current_preset(); + } + } + // XXX: ? + // m_plater->on_config_change(tab->get_config()); + } +} + // Called after the Preferences dialog is closed and the program settings are saved. // Update the UI based on the current preferences. void MainFrame::update_ui_from_settings() diff --git a/src/slic3r/GUI/MainFrame.hpp b/src/slic3r/GUI/MainFrame.hpp index f4c75de659..638c122e80 100644 --- a/src/slic3r/GUI/MainFrame.hpp +++ b/src/slic3r/GUI/MainFrame.hpp @@ -9,6 +9,7 @@ #include #include "Plater.hpp" +#include "Event.hpp" class wxMenuBar; class wxNotebook; @@ -64,6 +65,8 @@ class MainFrame : public wxFrame std::string get_base_name(const wxString full_name) const ; std::string get_dir_name(const wxString full_name) const ; + + void on_presets_changed(SimpleEvent&); public: MainFrame() {} MainFrame(const bool no_plater, const bool loaded); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 5ac4b2d84c..bbbdba0845 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -310,38 +310,37 @@ Sidebar::~Sidebar() {} void Sidebar::update_presets(Preset::Type preset_type) { - // TODO: wxApp access - switch (preset_type) { case Preset::TYPE_FILAMENT: - // my $choice_idx = 0; if (p->combos_filament.size() == 1) { // Single filament printer, synchronize the filament presets. - // wxTheApp->{preset_bundle}->set_filament_preset(0, wxTheApp->{preset_bundle}->filament->get_selected_preset->name); + const std::string &name = wxGetApp().preset_bundle->filaments.get_selected_preset().name; + wxGetApp().preset_bundle->set_filament_preset(0, name); } for (size_t i = 0; i < p->combos_filament.size(); i++) { - // wxTheApp->{preset_bundle}->update_platter_filament_ui($choice_idx, $choice); + wxGetApp().preset_bundle->update_platter_filament_ui(i, p->combos_filament[i]); } + break; case Preset::TYPE_PRINT: - // wxTheApp->{preset_bundle}->print->update_platter_ui($choosers[0]); + wxGetApp().preset_bundle->prints.update_platter_ui(p->combo_print); break; case Preset::TYPE_SLA_MATERIAL: - // wxTheApp->{preset_bundle}->sla_material->update_platter_ui($choosers[0]); + wxGetApp().preset_bundle->sla_materials.update_platter_ui(p->combo_sla_material); break; case Preset::TYPE_PRINTER: // Update the print choosers to only contain the compatible presets, update the dirty flags. - // wxTheApp->{preset_bundle}->print->update_platter_ui($self->{preset_choosers}{print}->[0]); + wxGetApp().preset_bundle->prints.update_platter_ui(p->combo_print); // Update the printer choosers, update the dirty flags. - // wxTheApp->{preset_bundle}->printer->update_platter_ui($choosers[0]); + wxGetApp().preset_bundle->printers.update_platter_ui(p->combo_printer); // Update the filament choosers to only contain the compatible presets, update the color preview, // update the dirty flags. for (size_t i = 0; i < p->combos_filament.size(); i++) { - // wxTheApp->{preset_bundle}->update_platter_filament_ui($choice_idx, $choice); + wxGetApp().preset_bundle->update_platter_filament_ui(i, p->combos_filament[i]); } break; @@ -349,7 +348,7 @@ void Sidebar::update_presets(Preset::Type preset_type) } // Synchronize config.ini with the current selections. - // wxTheApp->{preset_bundle}->export_selections(wxTheApp->{app_config}); + wxGetApp().preset_bundle->export_selections(*wxGetApp().app_config); } diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index e4a1f5933b..1f29fb5bb3 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -35,6 +35,11 @@ namespace GUI { static wxString dots("…", wxConvUTF8); + +wxDEFINE_EVENT(EVT_TAB_VALUE_CHANGED, wxCommandEvent); +wxDEFINE_EVENT(EVT_TAB_PRESETS_CHANGED, SimpleEvent); + + // sub new void Tab::create_preset_tab(PresetBundle *preset_bundle) { @@ -662,30 +667,27 @@ void Tab::load_key_value(const std::string& opt_key, const boost::any& value, bo update(); } -extern wxFrame *g_wxMainFrame; - void Tab::on_value_change(const std::string& opt_key, const boost::any& value) { - if (m_event_value_change > 0) { - wxCommandEvent event(m_event_value_change); - std::string str_out = opt_key + " " + m_name; - event.SetString(str_out); - if (opt_key == "extruders_count") - { - int val = boost::any_cast(value); - event.SetInt(val); - } - - if (opt_key == "printer_technology") - { - int val = boost::any_cast(value); - event.SetInt(val); - g_wxMainFrame->ProcessWindowEvent(event); - return; - } - - g_wxMainFrame->ProcessWindowEvent(event); + wxCommandEvent event(EVT_TAB_VALUE_CHANGED); + event.SetEventObject(this); + event.SetString(opt_key); + if (opt_key == "extruders_count") + { + int val = boost::any_cast(value); + event.SetInt(val); } + + if (opt_key == "printer_technology") + { + int val = boost::any_cast(value); + event.SetInt(val); + wxPostEvent(this, event); + return; + } + + wxPostEvent(this, event); + if (opt_key == "fill_density") { boost::any val = get_optgroup(ogFrequentlyChangingParameters)->get_config_value(*m_config, opt_key); @@ -734,11 +736,9 @@ void Tab::update_wiping_button_visibility() { // to uddate number of "filament" selection boxes when the number of extruders change. void Tab::on_presets_changed() { - if (m_event_presets_changed > 0) { - wxCommandEvent event(m_event_presets_changed); - event.SetString(m_name); - g_wxMainFrame->ProcessWindowEvent(event); - } + wxCommandEvent event(EVT_TAB_PRESETS_CHANGED); + event.SetEventObject(this); + wxPostEvent(this, event); update_preset_description_line(); } diff --git a/src/slic3r/GUI/Tab.hpp b/src/slic3r/GUI/Tab.hpp index afdf2008b2..f105cc9502 100644 --- a/src/slic3r/GUI/Tab.hpp +++ b/src/slic3r/GUI/Tab.hpp @@ -25,14 +25,15 @@ #include #include #include +#include #include #include #include #include "BedShapeDialog.hpp" +#include "Event.hpp" -//!enum { ID_TAB_TREE = wxID_HIGHEST + 1 }; namespace Slic3r { namespace GUI { @@ -96,7 +97,10 @@ protected: const wxColour* m_item_color; }; -// Slic3r::GUI::Tab; + +wxDECLARE_EVENT(EVT_TAB_VALUE_CHANGED, wxCommandEvent); +wxDECLARE_EVENT(EVT_TAB_PRESETS_CHANGED, SimpleEvent); + using PageShp = std::shared_ptr; class Tab: public wxPanel @@ -178,10 +182,6 @@ protected: t_icon_descriptions m_icon_descriptions = {}; - // The two following two event IDs are generated at Plater.pm by calling Wx::NewEventType. - wxEventType m_event_value_change = 0; - wxEventType m_event_presets_changed = 0; - bool m_is_modified_values{ false }; bool m_is_nonsys_values{ true }; bool m_postpone_update_ui {false}; @@ -211,10 +211,6 @@ public: wxString title() const { return m_title; } std::string name() const { return m_name; } - // Set the events to the callbacks posted to the main frame window (currently implemented in Perl). - void set_event_value_change(wxEventType evt) { m_event_value_change = evt; } - void set_event_presets_changed(wxEventType evt) { m_event_presets_changed = evt; } - void create_preset_tab(PresetBundle *preset_bundle); void load_current_preset(); void rebuild_page_tree(bool tree_sel_change_event = false); From 96745e12d764f957884032ddf24f64dcd3303d89 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Thu, 4 Oct 2018 10:41:11 +0200 Subject: [PATCH 060/186] Use an unique opengl context --- src/libslic3r/Technologies.hpp | 2 ++ src/slic3r/GUI/GLCanvas3D.cpp | 41 +++++++++++++++++++++++++++- src/slic3r/GUI/GLCanvas3D.hpp | 11 +++++++- src/slic3r/GUI/GLCanvas3DManager.cpp | 28 +++++++++++++++++++ src/slic3r/GUI/GLCanvas3DManager.hpp | 6 ++++ src/slic3r/GUI/GLToolbar.cpp | 4 +-- src/slic3r/GUI/GUI_Preview.hpp | 2 +- src/slic3r/GUI/Plater.cpp | 4 +-- 8 files changed, 91 insertions(+), 7 deletions(-) diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index 14e2a8bde3..9b9067af3e 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -10,6 +10,8 @@ #define ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM (1 && ENABLE_1_42_0) // Add double click on gizmo grabbers to reset transformation components to their default value #define ENABLE_GIZMOS_RESET (1 && ENABLE_1_42_0) +// Uses a unique opengl context +#define ENABLE_USE_UNIQUE_GLCONTEXT (1 && ENABLE_1_42_0) #endif // _technologies_h_ diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 2414e8c9b5..d78fb9c1f1 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1956,7 +1956,6 @@ wxDEFINE_EVENT(EVT_GIZMO_SCALE, Vec3dEvent); wxDEFINE_EVENT(EVT_GIZMO_ROTATE, Vec3dEvent); wxDEFINE_EVENT(EVT_GIZMO_FLATTEN, Vec3dEvent); - GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas) : m_canvas(canvas) , m_context(nullptr) @@ -1986,7 +1985,9 @@ GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas) { if (m_canvas != nullptr) { +#if !ENABLE_USE_UNIQUE_GLCONTEXT m_context = new wxGLContext(m_canvas); +#endif // !ENABLE_USE_UNIQUE_GLCONTEXT m_timer = new wxTimer(m_canvas); } } @@ -2001,11 +2002,13 @@ GLCanvas3D::~GLCanvas3D() m_timer = nullptr; } +#if !ENABLE_USE_UNIQUE_GLCONTEXT if (m_context != nullptr) { delete m_context; m_context = nullptr; } +#endif // !ENABLE_USE_UNIQUE_GLCONTEXT } void GLCanvas3D::post_event(wxEvent &&event) @@ -2095,6 +2098,7 @@ bool GLCanvas3D::init(bool useVBOs, bool use_legacy_opengl) return true; } +#if !ENABLE_USE_UNIQUE_GLCONTEXT bool GLCanvas3D::set_current() { if ((m_canvas != nullptr) && (m_context != nullptr)) @@ -2102,6 +2106,7 @@ bool GLCanvas3D::set_current() return false; } +#endif // !ENABLE_USE_UNIQUE_GLCONTEXT void GLCanvas3D::set_as_dirty() { @@ -2117,9 +2122,11 @@ void GLCanvas3D::reset_volumes() { if (!m_volumes.empty()) { +#if !ENABLE_USE_UNIQUE_GLCONTEXT // ensures this canvas is current if (!set_current()) return; +#endif // !ENABLE_USE_UNIQUE_GLCONTEXT m_volumes.release_geometry(); m_volumes.clear(); @@ -2514,7 +2521,11 @@ void GLCanvas3D::render() return; // ensures this canvas is current and initialized +#if ENABLE_USE_UNIQUE_GLCONTEXT + if (!_set_current() || !_3DScene::init(m_canvas)) +#else if (!set_current() || !_3DScene::init(m_canvas)) +#endif // ENABLE_USE_UNIQUE_GLCONTEXT return; if (m_force_zoom_to_bed_enabled) @@ -2619,9 +2630,11 @@ void GLCanvas3D::reload_scene(bool force) reset_volumes(); +#if !ENABLE_USE_UNIQUE_GLCONTEXT // ensures this canvas is current if (!set_current()) return; +#endif // !ENABLE_USE_UNIQUE_GLCONTEXT set_bed_shape(dynamic_cast(m_config->option("bed_shape"))->values); @@ -2709,9 +2722,11 @@ void GLCanvas3D::load_gcode_preview(const GCodePreviewData& preview_data, const { if ((m_canvas != nullptr) && (m_print != nullptr)) { +#if !ENABLE_USE_UNIQUE_GLCONTEXT // ensures that this canvas is current if (!set_current()) return; +#endif // !ENABLE_USE_UNIQUE_GLCONTEXT if (m_volumes.empty()) { @@ -3503,8 +3518,10 @@ Point GLCanvas3D::get_local_mouse_position() const void GLCanvas3D::reset_legend_texture() { +#if !ENABLE_USE_UNIQUE_GLCONTEXT if (!set_current()) return; +#endif // !ENABLE_USE_UNIQUE_GLCONTEXT m_legend_texture.reset(); } @@ -3650,13 +3667,27 @@ bool GLCanvas3D::_init_toolbar() return true; } +#if ENABLE_USE_UNIQUE_GLCONTEXT +bool GLCanvas3D::_set_current() +{ + if ((m_canvas != nullptr) && (m_context != nullptr)) + return m_canvas->SetCurrent(*m_context); + + return false; +} +#endif ENABLE_USE_UNIQUE_GLCONTEXT + void GLCanvas3D::_resize(unsigned int w, unsigned int h) { if ((m_canvas == nullptr) && (m_context == nullptr)) return; // ensures that this canvas is current +#if ENABLE_USE_UNIQUE_GLCONTEXT + _set_current(); +#else set_current(); +#endif // ENABLE_USE_UNIQUE_GLCONTEXT ::glViewport(0, 0, w, h); ::glMatrixMode(GL_PROJECTION); @@ -4315,9 +4346,11 @@ int GLCanvas3D::_get_first_selected_volume_id(int object_id) const void GLCanvas3D::_load_print_toolpaths() { +#if !ENABLE_USE_UNIQUE_GLCONTEXT // ensures this canvas is current if (!set_current()) return; +#endif // !ENABLE_USE_UNIQUE_GLCONTEXT if (m_print == nullptr) return; @@ -5427,24 +5460,30 @@ std::vector GLCanvas3D::_parse_colors(const std::vector& col void GLCanvas3D::_generate_legend_texture(const GCodePreviewData& preview_data, const std::vector& tool_colors) { +#if !ENABLE_USE_UNIQUE_GLCONTEXT if (!set_current()) return; +#endif // !ENABLE_USE_UNIQUE_GLCONTEXT m_legend_texture.generate(preview_data, tool_colors); } void GLCanvas3D::_generate_warning_texture(const std::string& msg) { +#if !ENABLE_USE_UNIQUE_GLCONTEXT if (!set_current()) return; +#endif // !ENABLE_USE_UNIQUE_GLCONTEXT m_warning_texture.generate(msg); } void GLCanvas3D::_reset_warning_texture() { +#if !ENABLE_USE_UNIQUE_GLCONTEXT if (!set_current()) return; +#endif // !ENABLE_USE_UNIQUE_GLCONTEXT m_warning_texture.reset(); } diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 04da729954..59893368ec 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -552,11 +552,17 @@ public: GLCanvas3D(wxGLCanvas* canvas); ~GLCanvas3D(); - wxGLCanvas* widget() { return m_canvas; } +#if ENABLE_USE_UNIQUE_GLCONTEXT + void set_context(wxGLContext* context) { m_context = context; } +#endif // ENABLE_USE_UNIQUE_GLCONTEXT + + wxGLCanvas* get_wxglcanvas() { return m_canvas; } bool init(bool useVBOs, bool use_legacy_opengl); +#if !ENABLE_USE_UNIQUE_GLCONTEXT bool set_current(); +#endif // !ENABLE_USE_UNIQUE_GLCONTEXT void set_as_dirty(); @@ -668,6 +674,9 @@ private: bool _init_toolbar(); +#if ENABLE_USE_UNIQUE_GLCONTEXT + bool _set_current(); +#endif // ENABLE_USE_UNIQUE_GLCONTEXT void _resize(unsigned int w, unsigned int h); BoundingBoxf3 _max_bounding_box() const; diff --git a/src/slic3r/GUI/GLCanvas3DManager.cpp b/src/slic3r/GUI/GLCanvas3DManager.cpp index 41f5ef22a8..8720caba59 100644 --- a/src/slic3r/GUI/GLCanvas3DManager.cpp +++ b/src/slic3r/GUI/GLCanvas3DManager.cpp @@ -113,13 +113,29 @@ std::string GLCanvas3DManager::GLInfo::to_string(bool format_as_html, bool exten GLCanvas3DManager::EMultisampleState GLCanvas3DManager::s_multisample = GLCanvas3DManager::MS_Unknown; GLCanvas3DManager::GLCanvas3DManager() +#if ENABLE_USE_UNIQUE_GLCONTEXT + : m_context(nullptr) + , m_current(nullptr) +#else : m_current(nullptr) +#endif // ENABLE_USE_UNIQUE_GLCONTEXT , m_gl_initialized(false) , m_use_legacy_opengl(false) , m_use_VBOs(false) { } +#if ENABLE_USE_UNIQUE_GLCONTEXT +GLCanvas3DManager::~GLCanvas3DManager() +{ + if (m_context != nullptr) + { + delete m_context; + m_context = nullptr; + } +} +#endif // ENABLE_USE_UNIQUE_GLCONTEXT + bool GLCanvas3DManager::add(wxGLCanvas* canvas) { if (canvas == nullptr) @@ -133,6 +149,18 @@ bool GLCanvas3DManager::add(wxGLCanvas* canvas) return false; canvas3D->bind_event_handlers(); + +#if ENABLE_USE_UNIQUE_GLCONTEXT + if (m_context == nullptr) + { + m_context = new wxGLContext(canvas); + if (m_context == nullptr) + return false; + } + + canvas3D->set_context(m_context); +#endif // ENABLE_USE_UNIQUE_GLCONTEXT + m_canvases.insert(CanvasesMap::value_type(canvas, canvas3D)); return true; diff --git a/src/slic3r/GUI/GLCanvas3DManager.hpp b/src/slic3r/GUI/GLCanvas3DManager.hpp index 1a3036f9fb..960bb6d2aa 100644 --- a/src/slic3r/GUI/GLCanvas3DManager.hpp +++ b/src/slic3r/GUI/GLCanvas3DManager.hpp @@ -52,6 +52,9 @@ class GLCanvas3DManager typedef std::map CanvasesMap; CanvasesMap m_canvases; +#if ENABLE_USE_UNIQUE_GLCONTEXT + wxGLContext* m_context; +#endif // ENABLE_USE_UNIQUE_GLCONTEXT wxGLCanvas* m_current; GLInfo m_gl_info; bool m_gl_initialized; @@ -61,6 +64,9 @@ class GLCanvas3DManager public: GLCanvas3DManager(); +#if ENABLE_USE_UNIQUE_GLCONTEXT + ~GLCanvas3DManager(); +#endif // ENABLE_USE_UNIQUE_GLCONTEXT bool add(wxGLCanvas* canvas); bool remove(wxGLCanvas* canvas); diff --git a/src/slic3r/GUI/GLToolbar.cpp b/src/slic3r/GUI/GLToolbar.cpp index e1566e9440..f2d882e22b 100644 --- a/src/slic3r/GUI/GLToolbar.cpp +++ b/src/slic3r/GUI/GLToolbar.cpp @@ -339,13 +339,13 @@ void GLToolbar::do_action(unsigned int item_id) item->set_state(GLToolbarItem::Hover); m_parent.render(); - item->do_action(m_parent.widget()); + item->do_action(m_parent.get_wxglcanvas()); } else { item->set_state(GLToolbarItem::HoverPressed); m_parent.render(); - item->do_action(m_parent.widget()); + item->do_action(m_parent.get_wxglcanvas()); if (item->get_state() != GLToolbarItem::Disabled) { // the item may get disabled during the action, if not, set it back to hover state diff --git a/src/slic3r/GUI/GUI_Preview.hpp b/src/slic3r/GUI/GUI_Preview.hpp index e7b7f4c941..9c28985582 100644 --- a/src/slic3r/GUI/GUI_Preview.hpp +++ b/src/slic3r/GUI/GUI_Preview.hpp @@ -50,7 +50,7 @@ public: Preview(wxNotebook* notebook, DynamicPrintConfig* config, Print* print, GCodePreviewData* gcode_preview_data); virtual ~Preview(); - wxGLCanvas* get_canvas() { return m_canvas; } + wxGLCanvas* get_wxglcanvas() { return m_canvas; } void set_number_extruders(unsigned int number_extruders); void reset_gcode_preview_data(); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index bbbdba0845..c510258ab8 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -520,7 +520,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) : canvas3D->Bind(EVT_GLTOOLBAR_ADD, &priv::on_action_add, this); canvas3D->Bind(EVT_GLCANVAS_VIEWPORT_CHANGED, &priv::on_viewport_changed, this); - preview->get_canvas()->Bind(EVT_GLCANVAS_VIEWPORT_CHANGED, &priv::on_viewport_changed, this); + preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_VIEWPORT_CHANGED, &priv::on_viewport_changed, this); q->Bind(EVT_SLICING_COMPLETED, &priv::on_update_print_preview, this); q->Bind(EVT_PROCESS_COMPLETED, &priv::on_process_completed, this); @@ -893,7 +893,7 @@ void Plater::priv::on_action_add(SimpleEvent&) void Plater::priv::on_viewport_changed(SimpleEvent& evt) { wxObject* o = evt.GetEventObject(); - if (o == preview->get_canvas()) + if (o == preview->get_wxglcanvas()) preview->set_viewport_into_scene(canvas3D); else if (o == canvas3D) preview->set_viewport_from_scene(canvas3D); From bcedd71e999c0ec423291aa46f1215b424549b17 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Thu, 4 Oct 2018 16:43:10 +0200 Subject: [PATCH 061/186] Start to Split GUI_ObjectParts: + created GUI_ObjectList & GUI_ObjectManipulation classes --- src/slic3r/CMakeLists.txt | 4 + src/slic3r/GUI/GLCanvas3D.cpp | 17 +- src/slic3r/GUI/GUI.cpp | 129 ----- src/slic3r/GUI/GUI_App.cpp | 13 +- src/slic3r/GUI/GUI_App.hpp | 9 + src/slic3r/GUI/GUI_ObjectList.cpp | 188 +++++++ src/slic3r/GUI/GUI_ObjectList.hpp | 50 ++ src/slic3r/GUI/GUI_ObjectManipulation.cpp | 304 ++++++++++ src/slic3r/GUI/GUI_ObjectManipulation.hpp | 64 +++ src/slic3r/GUI/GUI_ObjectParts.cpp | 652 +--------------------- src/slic3r/GUI/GUI_ObjectParts.hpp | 19 +- src/slic3r/GUI/MainFrame.cpp | 2 +- src/slic3r/GUI/OptionsGroup.hpp | 1 + src/slic3r/GUI/Plater.cpp | 181 +++++- src/slic3r/GUI/Plater.hpp | 20 +- src/slic3r/GUI/Tab.cpp | 15 +- src/slic3r/GUI/Tab.hpp | 2 +- 17 files changed, 836 insertions(+), 834 deletions(-) create mode 100644 src/slic3r/GUI/GUI_ObjectList.cpp create mode 100644 src/slic3r/GUI/GUI_ObjectList.hpp create mode 100644 src/slic3r/GUI/GUI_ObjectManipulation.cpp create mode 100644 src/slic3r/GUI/GUI_ObjectManipulation.hpp diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt index 06fb79a503..4974d66fc4 100644 --- a/src/slic3r/CMakeLists.txt +++ b/src/slic3r/CMakeLists.txt @@ -45,6 +45,10 @@ add_library(libslic3r_gui STATIC ${LIBDIR}/slic3r/GUI/MainFrame.hpp ${LIBDIR}/slic3r/GUI/Plater.cpp ${LIBDIR}/slic3r/GUI/Plater.hpp + ${LIBDIR}/slic3r/GUI/GUI_ObjectList.cpp + ${LIBDIR}/slic3r/GUI/GUI_ObjectList.hpp + ${LIBDIR}/slic3r/GUI/GUI_ObjectManipulation.cpp + ${LIBDIR}/slic3r/GUI/GUI_ObjectManipulation.hpp ${LIBDIR}/slic3r/GUI/LambdaObjectDialog.cpp ${LIBDIR}/slic3r/GUI/LambdaObjectDialog.hpp ${LIBDIR}/slic3r/GUI/Tab.cpp diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 328d5af39e..f65e380e5f 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -11,6 +11,7 @@ #include "../../libslic3r/PrintConfig.hpp" #include "../../libslic3r/GCode/PreviewData.hpp" #include "GUI_App.hpp" +#include "GUI_ObjectManipulation.hpp" #include @@ -2982,7 +2983,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) #else m_on_gizmo_scale_uniformly_callback.call((double)m_gizmos.get_scale()); #endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - update_scale_values(); + wxGetApp().obj_manipul()->update_scale_values(); m_dirty = true; break; } @@ -2993,7 +2994,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) #else m_on_gizmo_rotate_callback.call((double)m_gizmos.get_angle_z()); #endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - update_rotation_values(); + wxGetApp().obj_manipul()->update_rotation_values(); m_dirty = true; break; } @@ -3181,7 +3182,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) v->set_offset(v->get_offset() + Vec3d(vector(0), vector(1), 0.0)); } - update_position_values(volume->get_offset()); + wxGetApp().obj_manipul()->update_position_values(volume->get_offset()); m_mouse.drag.start_position_3D = cur_pos; m_dirty = true; @@ -3222,7 +3223,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) { v->set_offset(v->get_offset() + offset); } - update_position_values(volume->get_offset()); + wxGetApp().obj_manipul()->update_position_values(volume->get_offset()); break; } case Gizmos::Scale: @@ -3234,7 +3235,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) { v->set_scaling_factor(scale); } - update_scale_values(scale); + wxGetApp().obj_manipul()->update_scale_values(scale); #else // Apply new temporary scale factor float scale_factor = m_gizmos.get_scale(); @@ -3255,7 +3256,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) { v->set_rotation(rotation); } - update_rotation_value(rotation); + wxGetApp().obj_manipul()->update_rotation_value(rotation); #else // Apply new temporary angle_z float angle_z = m_gizmos.get_angle_z(); @@ -3430,7 +3431,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) break; } m_gizmos.stop_dragging(); - update_settings_value(); + wxGetApp().obj_manipul()->update_values(); } m_mouse.drag.move_volume_idx = -1; @@ -5351,7 +5352,7 @@ void GLCanvas3D::_on_move(const std::vector& volume_idxs) model_object->instances[instance_idx]->offset = Vec2d(offset(0), offset(1)); #endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM model_object->invalidate_bounding_box(); - update_position_values(); + wxGetApp().obj_manipul()->update_position_values(); object_moved = true; } } diff --git a/src/slic3r/GUI/GUI.cpp b/src/slic3r/GUI/GUI.cpp index 2ec5028f5a..34889b809d 100644 --- a/src/slic3r/GUI/GUI.cpp +++ b/src/slic3r/GUI/GUI.cpp @@ -519,135 +519,6 @@ void set_model_events_from_perl(Model &model, // add_collapsible_panes(parent, sizer); } -void Sidebar::add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer/*, wxFlexGridSizer* preset_sizer*/) -{ - DynamicPrintConfig* config = &wxGetApp().preset_bundle->prints.get_edited_preset().config; - std::shared_ptr optgroup = std::make_shared(parent, "", config); -// const wxArrayInt& ar = preset_sizer->GetColWidths(); -// m_label_width = ar.IsEmpty() ? 100 : ar.front()-4; - optgroup->label_width = 100;// m_label_width; - - auto m_optgroups = get_optgroups(); - - //Frequently changed parameters - optgroup->m_on_change = [config, m_optgroups](t_config_option_key opt_key, boost::any value){ - TabPrint* tab_print = nullptr; - for (size_t i = 0; i < wxGetApp().tab_panel()->GetPageCount(); ++i) { - Tab *tab = dynamic_cast(wxGetApp().tab_panel()->GetPage(i)); - if (!tab) - continue; - if (tab->name() == "print"){ - tab_print = static_cast(tab); - break; - } - } - if (tab_print == nullptr) - return; - - if (opt_key == "fill_density"){ - value = m_optgroups[ogFrequentlyChangingParameters]->get_config_value(*config, opt_key); - tab_print->set_value(opt_key, value); - tab_print->update(); - } - else{ - DynamicPrintConfig new_conf = *config; - if (opt_key == "brim"){ - double new_val; - double brim_width = config->opt_float("brim_width"); - if (boost::any_cast(value) == true) - { - new_val = 10;// m_brim_width == 0.0 ? 10 : -// m_brim_width < 0.0 ? m_brim_width * (-1) : -// m_brim_width; - } - else{ -// m_brim_width = brim_width * (-1); - new_val = 0; - } - new_conf.set_key_value("brim_width", new ConfigOptionFloat(new_val)); - } - else{ //(opt_key == "support") - const wxString& selection = boost::any_cast(value); - - auto support_material = selection == _("None") ? false : true; - new_conf.set_key_value("support_material", new ConfigOptionBool(support_material)); - - if (selection == _("Everywhere")) - new_conf.set_key_value("support_material_buildplate_only", new ConfigOptionBool(false)); - else if (selection == _("Support on build plate only")) - new_conf.set_key_value("support_material_buildplate_only", new ConfigOptionBool(true)); - } - tab_print->load_config(new_conf); - } - - tab_print->update_dirty(); - }; - - Option option = optgroup->get_option("fill_density"); - option.opt.sidetext = ""; - option.opt.full_width = true; - optgroup->append_single_option_line(option); - - ConfigOptionDef def; - - def.label = L("Support"); - def.type = coStrings; - def.gui_type = "select_open"; - def.tooltip = L("Select what kind of support do you need"); - def.enum_labels.push_back(L("None")); - def.enum_labels.push_back(L("Support on build plate only")); - def.enum_labels.push_back(L("Everywhere")); - std::string selection = !config->opt_bool("support_material") ? - "None" : - config->opt_bool("support_material_buildplate_only") ? - "Support on build plate only" : - "Everywhere"; - def.default_value = new ConfigOptionStrings { selection }; - option = Option(def, "support"); - option.opt.full_width = true; - optgroup->append_single_option_line(option); - - auto m_brim_width = config->opt_float("brim_width"); - def.label = L("Brim"); - def.type = coBool; - def.tooltip = L("This flag enables the brim that will be printed around each object on the first layer."); - def.gui_type = ""; - def.default_value = new ConfigOptionBool{ m_brim_width > 0.0 ? true : false }; - option = Option(def, "brim"); - optgroup->append_single_option_line(option); - - - Line line = { "", "" }; - line.widget = [config, this](wxWindow* parent){ - auto g_wiping_dialog_button = get_wiping_dialog_button(); - g_wiping_dialog_button = new wxButton(parent, wxID_ANY, _(L("Purging volumes")) + dots, wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT); - auto sizer = new wxBoxSizer(wxHORIZONTAL); - sizer->Add(g_wiping_dialog_button); - g_wiping_dialog_button->Bind(wxEVT_BUTTON, ([parent](wxCommandEvent& e) - { - auto &config = wxGetApp().preset_bundle->project_config; - const std::vector &init_matrix = (config.option("wiping_volumes_matrix"))->values; - const std::vector &init_extruders = (config.option("wiping_volumes_extruders"))->values; - - WipingDialog dlg(parent,cast(init_matrix),cast(init_extruders)); - - if (dlg.ShowModal() == wxID_OK) { - std::vector matrix = dlg.get_matrix(); - std::vector extruders = dlg.get_extruders(); - (config.option("wiping_volumes_matrix"))->values = std::vector(matrix.begin(),matrix.end()); - (config.option("wiping_volumes_extruders"))->values = std::vector(extruders.begin(),extruders.end()); - g_on_request_update_callback.call(); - } - })); - return sizer; - }; - optgroup->append_line(line); - - sizer->Add(optgroup->sizer, 0, wxEXPAND | wxBOTTOM | wxLEFT, 2); - - m_optgroups.push_back(optgroup);// ogFrequentlyChangingParameters -} - void show_buttons(bool show) { g_buttons[abReslice]->Show(show); diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 00071f01d8..8fdef00cd3 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -1,4 +1,5 @@ #include "GUI_App.hpp" +#include "GUI_ObjectManipulation.hpp" #include #include @@ -647,7 +648,17 @@ void GUI_App::load_current_presets() } } -wxNotebook* GUI_App::tab_panel() const +Sidebar& GUI_App::sidebar() +{ + return mainframe->m_plater->sidebar(); +} + +ObjectManipulation* GUI_App::obj_manipul() +{ + return sidebar().obj_manipul(); +} + +wxNotebook* GUI_App::tab_panel() const { return mainframe->m_tabpanel; } diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index e084481dd3..022fd0d371 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -123,6 +123,15 @@ public: // Tab* get_tab(const std::string& name); void load_current_presets(); + + Sidebar& sidebar(); + ObjectManipulation* obj_manipul(); +// ObjectList& get_obj_list(); + + // Functions for updating of the object manipulation values + void update_position_values(); + void update_position_values(const Vec3d& position); + AppConfig* app_config{ nullptr }; PresetBundle* preset_bundle{ nullptr }; PresetUpdater* preset_updater{ nullptr }; diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp new file mode 100644 index 0000000000..f44c5be8e8 --- /dev/null +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -0,0 +1,188 @@ +#include "GUI_ObjectList.hpp" +#include "GUI_App.hpp" + +#include "OptionsGroup.hpp" +#include "PresetBundle.hpp" +#include "Tab.hpp" +#include "wxExtensions.hpp" + +// #include "Model.hpp" +// #include "LambdaObjectDialog.hpp" +// #include "../../libslic3r/Utils.hpp" +// +// #include +// #include +#include +// #include "Geometry.hpp" +#include "slic3r/Utils/FixModelByWin10.hpp" + +// +// #include +// #include "3DScene.hpp" + +namespace Slic3r +{ +namespace GUI +{ + +ObjectList::ObjectList(wxWindow* parent) : + m_parent(parent) +{ +// wxBoxSizer* sizer; + // create control + create_objects_ctrl(); + + // describe control behavior + m_objects_ctrl->Bind(wxEVT_DATAVIEW_SELECTION_CHANGED, [](wxEvent& event) { + object_ctrl_selection_changed(); +#ifndef __WXMSW__ + set_tooltip_for_item(get_mouse_position_in_control()); +#endif //__WXMSW__ + }); + + m_objects_ctrl->Bind(wxEVT_DATAVIEW_ITEM_CONTEXT_MENU, [](wxDataViewEvent& event) { + object_ctrl_context_menu(); + // event.Skip(); + }); + + m_objects_ctrl->Bind(wxEVT_CHAR, [](wxKeyEvent& event) { object_ctrl_key_event(event); }); // doesn't work on OSX + +#ifdef __WXMSW__ + // Extruder value changed + m_objects_ctrl->Bind(wxEVT_CHOICE, [](wxCommandEvent& event) { update_extruder_in_config(event.GetString()); }); + + m_objects_ctrl->GetMainWindow()->Bind(wxEVT_MOTION, [this](wxMouseEvent& event) { + set_tooltip_for_item(event.GetPosition()); + event.Skip(); + }); +#else + // equivalent to wxEVT_CHOICE on __WXMSW__ + m_objects_ctrl->Bind(wxEVT_DATAVIEW_ITEM_VALUE_CHANGED, [](wxDataViewEvent& event) { object_ctrl_item_value_change(event); }); +#endif //__WXMSW__ + + m_objects_ctrl->Bind(wxEVT_DATAVIEW_ITEM_BEGIN_DRAG, [](wxDataViewEvent& e) {on_begin_drag(e); }); + m_objects_ctrl->Bind(wxEVT_DATAVIEW_ITEM_DROP_POSSIBLE, [](wxDataViewEvent& e) {on_drop_possible(e); }); + m_objects_ctrl->Bind(wxEVT_DATAVIEW_ITEM_DROP, [](wxDataViewEvent& e) {on_drop(e); }); +} + +void ObjectList::create_objects_ctrl() +{ + m_objects_ctrl = new wxDataViewCtrl(m_parent, wxID_ANY, wxDefaultPosition, wxDefaultSize); + m_objects_ctrl->SetMinSize(wxSize(-1, 150)); // TODO - Set correct height according to the opened/closed objects + + m_sizer = new wxBoxSizer(wxVERTICAL); + m_sizer->Add(m_objects_ctrl, 1, wxGROW | wxLEFT, 20); + + m_objects_model = new PrusaObjectDataViewModel; + m_objects_ctrl->AssociateModel(m_objects_model); +#if wxUSE_DRAG_AND_DROP && wxUSE_UNICODE + m_objects_ctrl->EnableDragSource(wxDF_UNICODETEXT); + m_objects_ctrl->EnableDropTarget(wxDF_UNICODETEXT); +#endif // wxUSE_DRAG_AND_DROP && wxUSE_UNICODE + + // column 0(Icon+Text) of the view control: + // And Icon can be consisting of several bitmaps + m_objects_ctrl->AppendColumn(new wxDataViewColumn(_(L("Name")), new PrusaBitmapTextRenderer(), + 0, 200, wxALIGN_LEFT, wxDATAVIEW_COL_RESIZABLE)); + + // column 1 of the view control: + m_objects_ctrl->AppendTextColumn(_(L("Copy")), 1, wxDATAVIEW_CELL_INERT, 45, + wxALIGN_CENTER_HORIZONTAL, wxDATAVIEW_COL_RESIZABLE); + + // column 2 of the view control: + m_objects_ctrl->AppendColumn(create_objects_list_extruder_column(4)); + + // column 3 of the view control: + m_objects_ctrl->AppendBitmapColumn(" ", 3, wxDATAVIEW_CELL_INERT, 25, + wxALIGN_CENTER_HORIZONTAL, wxDATAVIEW_COL_RESIZABLE); +} + +// ModelObjectPtrs& ObjectList::get_objects() +// { +// return wxGetApp().mainframe->m_plater->model().objects; +// } + + +void ObjectList::set_tooltip_for_item(const wxPoint& pt) +{ + wxDataViewItem item; + wxDataViewColumn* col; + m_objects_ctrl->HitTest(pt, item, col); + if (!item) return; + + if (col->GetTitle() == " ") + m_objects_ctrl->GetMainWindow()->SetToolTip(_(L("Right button click the icon to change the object settings"))); +// else if (col->GetTitle() == _("Name") && +// m_objects_model->GetIcon(item).GetRefData() == m_icon_manifold_warning.GetRefData()) { +// int obj_idx = m_objects_model->GetIdByItem(item); +// auto& stats = (*m_objects)[obj_idx]->volumes[0]->mesh.stl.stats; +// int errors = stats.degenerate_facets + stats.edges_fixed + stats.facets_removed + +// stats.facets_added + stats.facets_reversed + stats.backwards_edges; +// +// wxString tooltip = wxString::Format(_(L("Auto-repaired (%d errors):\n")), errors); +// +// std::map error_msg; +// error_msg[L("degenerate facets")] = stats.degenerate_facets; +// error_msg[L("edges fixed")] = stats.edges_fixed; +// error_msg[L("facets removed")] = stats.facets_removed; +// error_msg[L("facets added")] = stats.facets_added; +// error_msg[L("facets reversed")] = stats.facets_reversed; +// error_msg[L("backwards edges")] = stats.backwards_edges; +// +// for (auto error : error_msg) +// { +// if (error.second > 0) +// tooltip += wxString::Format(_("\t%d %s\n"), error.second, error.first); +// } +// // OR +// // tooltip += wxString::Format(_(L("%d degenerate facets, %d edges fixed, %d facets removed, " +// // "%d facets added, %d facets reversed, %d backwards edges")), +// // stats.degenerate_facets, stats.edges_fixed, stats.facets_removed, +// // stats.facets_added, stats.facets_reversed, stats.backwards_edges); +// +// if (is_windows10()) +// tooltip += _(L("Right button click the icon to fix STL through Netfabb")); +// +// m_objects_ctrl->GetMainWindow()->SetToolTip(tooltip); +// } + else + m_objects_ctrl->GetMainWindow()->SetToolTip(""); // hide tooltip +} + +wxPoint ObjectList::get_mouse_position_in_control() { + const wxPoint& pt = wxGetMousePosition(); + wxWindow* win = m_objects_ctrl->GetMainWindow(); + return wxPoint(pt.x - win->GetScreenPosition().x, + pt.y - win->GetScreenPosition().y); +} + +wxDataViewColumn* ObjectList::create_objects_list_extruder_column(int extruders_count) +{ + wxArrayString choices; + choices.Add("default"); + for (int i = 1; i <= extruders_count; ++i) + choices.Add(wxString::Format("%d", i)); + wxDataViewChoiceRenderer *c = + new wxDataViewChoiceRenderer(choices, wxDATAVIEW_CELL_EDITABLE, wxALIGN_CENTER_HORIZONTAL); + wxDataViewColumn* column = new wxDataViewColumn(_(L("Extruder")), c, 2, 60, wxALIGN_CENTER_HORIZONTAL, wxDATAVIEW_COL_RESIZABLE); + return column; +} + +void ObjectList::update_objects_list_extruder_column(int extruders_count) +{ + if (!m_objects_ctrl) return; // #ys_FIXME + if (wxGetApp().preset_bundle->printers.get_selected_preset().printer_technology() == ptSLA) + extruders_count = 1; + + // delete old 3rd column + m_objects_ctrl->DeleteColumn(m_objects_ctrl->GetColumn(2)); + // insert new created 3rd column + m_objects_ctrl->InsertColumn(2, create_objects_list_extruder_column(extruders_count)); + // set show/hide for this column + set_extruder_column_hidden(extruders_count <= 1); +} + + + +} //namespace GUI +} //namespace Slic3r \ No newline at end of file diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp new file mode 100644 index 0000000000..77530a590c --- /dev/null +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -0,0 +1,50 @@ +#ifndef slic3r_GUI_ObjectList_hpp_ +#define slic3r_GUI_ObjectList_hpp_ + +#include +#include + +class wxBoxSizer; +class wxDataViewCtrl; +class wxDataViewColumn; +class PrusaObjectDataViewModel; + +namespace Slic3r { +namespace GUI { + +class ConfigOptionsGroup; + +class ObjectList +{ + wxBoxSizer *m_sizer {nullptr}; + wxDataViewCtrl *m_objects_ctrl{ nullptr }; + PrusaObjectDataViewModel *m_objects_model{ nullptr }; + wxWindow *m_parent{ nullptr }; + + wxBitmap m_icon_modifiermesh; + wxBitmap m_icon_solidmesh; + wxBitmap m_icon_manifold_warning; + wxBitmap m_bmp_cog; + wxBitmap m_bmp_split; + + int m_selected_object_id = -1; + +public: + ObjectList(wxWindow* parent); + ~ObjectList() {} + + void create_objects_ctrl(); + wxDataViewColumn* create_objects_list_extruder_column(int extruders_count); + void update_objects_list_extruder_column(int extruders_count); + + void set_tooltip_for_item(const wxPoint& pt); + + wxPoint get_mouse_position_in_control(); + wxBoxSizer* get_sizer(){return m_sizer;} + int get_sel_obj_id() { return m_selected_object_id; } +}; + + +}} + +#endif //slic3r_GUI_ObjectList_hpp_ diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp new file mode 100644 index 0000000000..86e657d8e3 --- /dev/null +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -0,0 +1,304 @@ +#include "GUI_ObjectManipulation.hpp" + +#include "OptionsGroup.hpp" +#include "wxExtensions.hpp" +#include "Model.hpp" +#include "Geometry.hpp" + +#include + +namespace Slic3r +{ +namespace GUI +{ + +OG_Settings::OG_Settings(wxWindow* parent, const bool staticbox) +{ + wxString title = staticbox ? " " : ""; // temporary workaround - #ys_FIXME + m_og = std::make_shared(parent, title); +} + +wxSizer* OG_Settings::get_sizer() +{ + return m_og->sizer; +} + +ObjectManipulation::ObjectManipulation(wxWindow* parent): + OG_Settings(parent, true) +{ + m_og->set_name(_(L("Object Manipulation"))); + m_og->label_width = 100; + m_og->set_grid_vgap(5); + + m_og->m_on_change = [this](t_config_option_key opt_key, boost::any value){ + if (opt_key == "scale_unit"){ + const wxString& selection = boost::any_cast(value); + std::vector axes{ "x", "y", "z" }; + for (auto axis : axes) { + std::string key = "scale_" + axis; + get_optgroup(ogFrequentlyObjectSettings)->set_side_text(key, selection); + } + + m_is_percent_scale = selection == _("%"); + update_scale_values(); + } + }; + + ConfigOptionDef def; + + // Objects(sub-objects) name + def.label = L("Name"); + // def.type = coString; + def.gui_type = "legend"; + def.tooltip = L("Object name"); + def.full_width = true; + def.default_value = new ConfigOptionString{ " " }; + m_og->append_single_option_line(Option(def, "object_name")); + + // Legend for object modification + auto line = Line{ "", "" }; + def.label = ""; + def.type = coString; + def.width = 55; + + std::vector axes{ "x", "y", "z" }; + for (const auto axis : axes) { + const auto label = boost::algorithm::to_upper_copy(axis); + def.default_value = new ConfigOptionString{ " " + label }; + Option option = Option(def, axis + "_axis_legend"); + line.append_option(option); + } + m_og->append_line(line); + + + auto add_og_to_object_settings = [](const std::string& option_name, const std::string& sidetext) + { + int def_value = 0; + Line line = { _(option_name), "" }; + if (option_name == "Scale") { + line.near_label_widget = [](wxWindow* parent) { + auto btn = new PrusaLockButton(parent, wxID_ANY); + btn->Bind(wxEVT_BUTTON, [btn](wxCommandEvent &event){ + event.Skip(); + wxTheApp->CallAfter([btn]() { set_uniform_scaling(btn->IsLocked()); }); + }); + return btn; + }; + } + + ConfigOptionDef def; + def.type = coInt; + def.default_value = new ConfigOptionInt(def_value); + def.width = 55; + + if (option_name == "Rotation") + def.min = -360; + + const std::string lower_name = boost::algorithm::to_lower_copy(option_name); + + std::vector axes{ "x", "y", "z" }; + for (auto axis : axes) { + if (axis == "z" && option_name != "Scale") + def.sidetext = sidetext; + Option option = Option(def, lower_name + "_" + axis); + option.opt.full_width = true; + line.append_option(option); + } + + if (option_name == "Scale") + { + def.width = 45; + def.type = coStrings; + def.gui_type = "select_open"; + def.enum_labels.push_back(L("%")); + def.enum_labels.push_back(L("mm")); + def.default_value = new ConfigOptionStrings{ "mm" }; + + const Option option = Option(def, lower_name + "_unit"); + line.append_option(option); + } + + return line; + }; + + + // Settings table + m_og->append_line(add_og_to_object_settings(L("Position"), L("mm"))); + m_og->append_line(add_og_to_object_settings(L("Rotation"), "°")); + m_og->append_line(add_og_to_object_settings(L("Scale"), "mm")); + + + def.label = L("Place on bed"); + def.type = coBool; + def.tooltip = L("Automatic placing of models on printing bed in Y axis"); + def.gui_type = ""; + def.sidetext = ""; + def.default_value = new ConfigOptionBool{ false }; + m_og->append_single_option_line(Option(def, "place_on_bed")); + + m_extra_settings_sizer = new wxBoxSizer(wxVERTICAL); + m_og->sizer->Add(m_extra_settings_sizer, 1, wxEXPAND | wxLEFT, 5); + + m_og->disable(); +} + +int ObjectManipulation::ol_selection() +{ + return wxGetApp().sidebar().get_ol_selection(); +} + +void ObjectManipulation::update_values() +{ + int selection = ol_selection(); + if (selection < 0 || wxGetApp().mainframe->m_plater->model().objects.size() <= selection) { + m_og->set_value("position_x", 0); + m_og->set_value("position_y", 0); + m_og->set_value("position_z", 0); + m_og->set_value("scale_x", 0); + m_og->set_value("scale_y", 0); + m_og->set_value("scale_z", 0); + m_og->set_value("rotation_x", 0); + m_og->set_value("rotation_y", 0); + m_og->set_value("rotation_z", 0); + m_og->disable(); + return; + } + m_is_percent_scale = boost::any_cast(m_og->get_value("scale_unit")) == _("%"); + + update_position_values(); + update_scale_values(); + update_rotation_values(); + m_og->enable(); +} + +void ObjectManipulation::update_scale_values() +{ + int selection = ol_selection(); + ModelObjectPtrs& objects = wxGetApp().mainframe->m_plater->model().objects; + + auto instance = objects[selection]->instances.front(); + auto size = objects[selection]->instance_bounding_box(0).size(); + +#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM + if (m_is_percent_scale) { + m_og->set_value("scale_x", int(instance->get_scaling_factor(X) * 100)); + m_og->set_value("scale_y", int(instance->get_scaling_factor(Y) * 100)); + m_og->set_value("scale_z", int(instance->get_scaling_factor(Z) * 100)); + } + else { + m_og->set_value("scale_x", int(instance->get_scaling_factor(X) * size(0) + 0.5)); + m_og->set_value("scale_y", int(instance->get_scaling_factor(Y) * size(1) + 0.5)); + m_og->set_value("scale_z", int(instance->get_scaling_factor(Z) * size(2) + 0.5)); + } +#else + if (m_is_percent_scale) { + auto scale = instance->scaling_factor * 100.0; + m_og->set_value("scale_x", int(scale)); + m_og->set_value("scale_y", int(scale)); + m_og->set_value("scale_z", int(scale)); + } + else { + m_og->set_value("scale_x", int(instance->scaling_factor * size(0) + 0.5)); + m_og->set_value("scale_y", int(instance->scaling_factor * size(1) + 0.5)); + m_og->set_value("scale_z", int(instance->scaling_factor * size(2) + 0.5)); + } +#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM +} + +void ObjectManipulation::update_position_values() +{ + auto instance = wxGetApp().mainframe->m_plater->model().objects[ol_selection()]->instances.front(); + +#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM + m_og->set_value("position_x", int(instance->get_offset(X))); + m_og->set_value("position_y", int(instance->get_offset(Y))); + m_og->set_value("position_z", int(instance->get_offset(Z))); +#else + m_og->set_value("position_x", int(instance->offset(0))); + m_og->set_value("position_y", int(instance->offset(1))); + m_og->set_value("position_z", 0); +#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM +} + +void ObjectManipulation::update_position_values(const Vec3d& position) +{ + m_og->set_value("position_x", int(position(0))); + m_og->set_value("position_y", int(position(1))); + m_og->set_value("position_z", int(position(2))); +} + +#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM +void ObjectManipulation::update_scale_values(const Vec3d& scaling_factor) +{ + // this is temporary + // to be able to update the values as size + // we need to store somewhere the original size + // or have it passed as parameter + if (!m_is_percent_scale) + m_og->set_value("scale_unit", _("%")); + + auto scale = scaling_factor * 100.0; + m_og->set_value("scale_x", int(scale(0))); + m_og->set_value("scale_y", int(scale(1))); + m_og->set_value("scale_z", int(scale(2))); +} +#else +void ObjectManipulation::update_scale_values(double scaling_factor) +{ + // this is temporary + // to be able to update the values as size + // we need to store somewhere the original size + // or have it passed as parameter + if (!m_is_percent_scale) + m_og->set_value("scale_unit", _("%")); + + auto scale = scaling_factor * 100.0; + m_og->set_value("scale_x", int(scale)); + m_og->set_value("scale_y", int(scale)); + m_og->set_value("scale_z", int(scale)); +} +#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM + +void ObjectManipulation::update_rotation_values() +{ +#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM + update_rotation_value(wxGetApp().mainframe->m_plater->model().objects[ol_selection()]->instances.front()->get_rotation()); +#else + auto instance = wxGetApp().mainframe->m_plater->model().objects[ol_selection()]->instances.front(); + m_og->set_value("rotation_x", 0); + m_og->set_value("rotation_y", 0); + m_og->set_value("rotation_z", int(Geometry::rad2deg(instance->rotation))); +#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM +} + +void ObjectManipulation::update_rotation_value(double angle, Axis axis) +{ + std::string axis_str; + switch (axis) { + case X: { + axis_str = "rotation_x"; + break; } + case Y: { + axis_str = "rotation_y"; + break; } + case Z: { + axis_str = "rotation_z"; + break; } + } + + m_og->set_value(axis_str, round_nearest(int(Geometry::rad2deg(angle)), 0)); +} + +#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM +void ObjectManipulation::update_rotation_value(const Vec3d& rotation) +{ + m_og->set_value("rotation_x", int(round_nearest(Geometry::rad2deg(rotation(0)), 0))); + m_og->set_value("rotation_y", int(round_nearest(Geometry::rad2deg(rotation(1)), 0))); + m_og->set_value("rotation_z", int(round_nearest(Geometry::rad2deg(rotation(2)), 0))); +} +#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM + + + +} //namespace GUI +} //namespace Slic3r \ No newline at end of file diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.hpp b/src/slic3r/GUI/GUI_ObjectManipulation.hpp new file mode 100644 index 0000000000..feeaeb3abc --- /dev/null +++ b/src/slic3r/GUI/GUI_ObjectManipulation.hpp @@ -0,0 +1,64 @@ +#ifndef slic3r_GUI_ObjectManipulation_hpp_ +#define slic3r_GUI_ObjectManipulation_hpp_ + +#include + +#include + +#include "Preset.hpp" + +class wxBoxSizer; + +namespace Slic3r { +namespace GUI { +class ConfigOptionsGroup; + + +class OG_Settings +{ +protected: + std::shared_ptr m_og; +public: + OG_Settings(wxWindow* parent, const bool staticbox); + ~OG_Settings() {} + + wxSizer* get_sizer(); +}; + + +class ObjectManipulation : public OG_Settings +{ + bool m_is_percent_scale = false; // true -> percentage scale unit + // false -> uniform scale unit + wxBoxSizer* m_extra_settings_sizer{ nullptr }; // sizer for extra Object/Part's settings + +public: + ObjectManipulation(wxWindow* parent); + ~ObjectManipulation() {} + + int ol_selection(); + + void update_values(); + // update position values displacements or "gizmos" + void update_position_values(); + void update_position_values(const Vec3d& position); + // update scale values after scale unit changing or "gizmos" + void update_scale_values(); +#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM + void update_scale_values(const Vec3d& scaling_factor); +#else + void update_scale_values(double scaling_factor); +#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM + // update rotation values object selection changing + void update_rotation_values(); + // update rotation value after "gizmos" + void update_rotation_value(double angle, Axis axis); +#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM + void update_rotation_value(const Vec3d& rotation); +#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM + +}; + +}} + +#endif // slic3r_GUI_ObjectManipulation_hpp_ diff --git a/src/slic3r/GUI/GUI_ObjectParts.cpp b/src/slic3r/GUI/GUI_ObjectParts.cpp index ae1f5a2768..f578f64660 100644 --- a/src/slic3r/GUI/GUI_ObjectParts.cpp +++ b/src/slic3r/GUI/GUI_ObjectParts.cpp @@ -21,12 +21,8 @@ namespace Slic3r { namespace GUI { -wxSizer *m_sizer_object_buttons = nullptr; -wxSizer *m_sizer_part_buttons = nullptr; -wxSizer *m_sizer_object_movers = nullptr; wxDataViewCtrl *m_objects_ctrl = nullptr; PrusaObjectDataViewModel *m_objects_model = nullptr; -wxCollapsiblePane *m_collpane_settings = nullptr; PrusaDoubleSlider *m_slider = nullptr; wxGLCanvas *m_preview_canvas = nullptr; @@ -36,19 +32,12 @@ wxBitmap m_icon_manifold_warning; wxBitmap m_bmp_cog; wxBitmap m_bmp_split; -wxSlider* m_mover_x = nullptr; -wxSlider* m_mover_y = nullptr; -wxSlider* m_mover_z = nullptr; -wxButton* m_btn_move_up = nullptr; -wxButton* m_btn_move_down = nullptr; -Vec3d m_move_options; -Vec3d m_last_coords; int m_selected_object_id = -1; bool g_prevent_list_events = false; // We use this flag to avoid circular event handling Select() // happens to fire a wxEVT_LIST_ITEM_SELECTED on OSX, whose event handler // calls this method again and again and again -bool g_is_percent_scale = false; // It indicates if scale unit is percentage +// bool g_is_percent_scale = false; // It indicates if scale unit is percentage bool g_is_uniform_scale = false; // It indicates if scale is uniform ModelObjectPtrs* m_objects; std::shared_ptr m_config; @@ -158,457 +147,6 @@ void init_mesh_icons(){ bool is_parts_changed(){return m_parts_changed;} bool is_part_settings_changed(){ return m_part_settings_changed; } -void set_tooltip_for_item(const wxPoint& pt) -{ - wxDataViewItem item; - wxDataViewColumn* col; - m_objects_ctrl->HitTest(pt, item, col); - if (!item) return; - - if (col->GetTitle() == " ") - m_objects_ctrl->GetMainWindow()->SetToolTip(_(L("Right button click the icon to change the object settings"))); - else if (col->GetTitle() == _("Name") && - m_objects_model->GetIcon(item).GetRefData() == m_icon_manifold_warning.GetRefData()) { - int obj_idx = m_objects_model->GetIdByItem(item); - auto& stats = (*m_objects)[obj_idx]->volumes[0]->mesh.stl.stats; - int errors = stats.degenerate_facets + stats.edges_fixed + stats.facets_removed + - stats.facets_added + stats.facets_reversed + stats.backwards_edges; - - wxString tooltip = wxString::Format(_(L("Auto-repaired (%d errors):\n")), errors); - - std::map error_msg; - error_msg[L("degenerate facets")] = stats.degenerate_facets; - error_msg[L("edges fixed")] = stats.edges_fixed; - error_msg[L("facets removed")] = stats.facets_removed; - error_msg[L("facets added")] = stats.facets_added; - error_msg[L("facets reversed")] = stats.facets_reversed; - error_msg[L("backwards edges")] = stats.backwards_edges; - - for (auto error : error_msg) - { - if (error.second > 0) - tooltip += wxString::Format(_("\t%d %s\n"), error.second, error.first); - } -// OR -// tooltip += wxString::Format(_(L("%d degenerate facets, %d edges fixed, %d facets removed, " -// "%d facets added, %d facets reversed, %d backwards edges")), -// stats.degenerate_facets, stats.edges_fixed, stats.facets_removed, -// stats.facets_added, stats.facets_reversed, stats.backwards_edges); - - if (is_windows10()) - tooltip += _(L("Right button click the icon to fix STL through Netfabb")); - - m_objects_ctrl->GetMainWindow()->SetToolTip(tooltip); - } - else - m_objects_ctrl->GetMainWindow()->SetToolTip(""); // hide tooltip -} - -wxPoint get_mouse_position_in_control() { - const wxPoint& pt = wxGetMousePosition(); - wxWindow* win = m_objects_ctrl->GetMainWindow(); - return wxPoint(pt.x - win->GetScreenPosition().x, - pt.y - win->GetScreenPosition().y); -} - -bool is_mouse_position_in_control(wxPoint& pt) { - pt = get_mouse_position_in_control(); - const wxSize& cz = m_objects_ctrl->GetSize(); - if (pt.x > 0 && pt.x < cz.x && - pt.y > 0 && pt.y < cz.y) - return true; - return false; -} - -wxDataViewColumn* object_ctrl_create_extruder_column(int extruders_count) -{ - wxArrayString choices; - choices.Add("default"); - for (int i = 1; i <= extruders_count; ++i) - choices.Add(wxString::Format("%d", i)); - wxDataViewChoiceRenderer *c = - new wxDataViewChoiceRenderer(choices, wxDATAVIEW_CELL_EDITABLE, wxALIGN_CENTER_HORIZONTAL); - wxDataViewColumn* column = new wxDataViewColumn(_(L("Extruder")), c, 2, 60, wxALIGN_CENTER_HORIZONTAL, wxDATAVIEW_COL_RESIZABLE); - return column; -} - -void create_objects_ctrl(wxWindow* win, wxBoxSizer*& objects_sz) -{ - m_objects_ctrl = new wxDataViewCtrl(win, wxID_ANY, wxDefaultPosition, wxDefaultSize); - m_objects_ctrl->SetMinSize(wxSize(-1, 150)); // TODO - Set correct height according to the opened/closed objects - - objects_sz = new wxBoxSizer(wxVERTICAL); - objects_sz->Add(m_objects_ctrl, 1, wxGROW | wxLEFT, 20); - - m_objects_model = new PrusaObjectDataViewModel; - m_objects_ctrl->AssociateModel(m_objects_model); -#if wxUSE_DRAG_AND_DROP && wxUSE_UNICODE - m_objects_ctrl->EnableDragSource(wxDF_UNICODETEXT); - m_objects_ctrl->EnableDropTarget(wxDF_UNICODETEXT); -#endif // wxUSE_DRAG_AND_DROP && wxUSE_UNICODE - - // column 0(Icon+Text) of the view control: - // And Icon can be consisting of several bitmaps - m_objects_ctrl->AppendColumn(new wxDataViewColumn(_(L("Name")), new PrusaBitmapTextRenderer(), - 0, 200, wxALIGN_LEFT, wxDATAVIEW_COL_RESIZABLE)); - - // column 1 of the view control: - m_objects_ctrl->AppendTextColumn(_(L("Copy")), 1, wxDATAVIEW_CELL_INERT, 45, - wxALIGN_CENTER_HORIZONTAL, wxDATAVIEW_COL_RESIZABLE); - - // column 2 of the view control: - m_objects_ctrl->AppendColumn(object_ctrl_create_extruder_column(4)); - - // column 3 of the view control: - m_objects_ctrl->AppendBitmapColumn(" ", 3, wxDATAVIEW_CELL_INERT, 25, - wxALIGN_CENTER_HORIZONTAL, wxDATAVIEW_COL_RESIZABLE); -} - -// ****** from GUI.cpp -wxBoxSizer* create_objects_list(wxWindow *win) -{ - wxBoxSizer* objects_sz; - // create control - create_objects_ctrl(win, objects_sz); - - // describe control behavior - m_objects_ctrl->Bind(wxEVT_DATAVIEW_SELECTION_CHANGED, [](wxEvent& event) { - object_ctrl_selection_changed(); -#ifndef __WXMSW__ - set_tooltip_for_item(get_mouse_position_in_control()); -#endif //__WXMSW__ - }); - - m_objects_ctrl->Bind(wxEVT_DATAVIEW_ITEM_CONTEXT_MENU, [](wxDataViewEvent& event) { - object_ctrl_context_menu(); -// event.Skip(); - }); - - m_objects_ctrl->Bind(wxEVT_CHAR, [](wxKeyEvent& event) { object_ctrl_key_event(event); }); // doesn't work on OSX - -#ifdef __WXMSW__ - // Extruder value changed - m_objects_ctrl->Bind(wxEVT_CHOICE, [](wxCommandEvent& event) { update_extruder_in_config(event.GetString()); }); - - m_objects_ctrl->GetMainWindow()->Bind(wxEVT_MOTION, [](wxMouseEvent& event) { - set_tooltip_for_item(event.GetPosition()); - event.Skip(); - }); -#else - // equivalent to wxEVT_CHOICE on __WXMSW__ - m_objects_ctrl->Bind(wxEVT_DATAVIEW_ITEM_VALUE_CHANGED, [](wxDataViewEvent& event) { object_ctrl_item_value_change(event); }); -#endif //__WXMSW__ - - m_objects_ctrl->Bind(wxEVT_DATAVIEW_ITEM_BEGIN_DRAG, [](wxDataViewEvent& e) {on_begin_drag(e);}); - m_objects_ctrl->Bind(wxEVT_DATAVIEW_ITEM_DROP_POSSIBLE, [](wxDataViewEvent& e) {on_drop_possible(e); }); - m_objects_ctrl->Bind(wxEVT_DATAVIEW_ITEM_DROP, [](wxDataViewEvent& e) {on_drop(e);}); - return objects_sz; -} - -wxBoxSizer* create_edit_object_buttons(wxWindow* win) -{ - auto sizer = new wxBoxSizer(wxVERTICAL); - - auto btn_load_part = new wxButton(win, wxID_ANY, /*Load */"part" + dots, wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER/*wxBU_LEFT*/); - auto btn_load_modifier = new wxButton(win, wxID_ANY, /*Load */"modifier" + dots, wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER/*wxBU_LEFT*/); - auto btn_load_lambda_modifier = new wxButton(win, wxID_ANY, /*Load */"generic" + dots, wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER/*wxBU_LEFT*/); - auto btn_delete = new wxButton(win, wxID_ANY, "Delete"/*" part"*/, wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER/*wxBU_LEFT*/); - auto btn_split = new wxButton(win, wxID_ANY, "Split"/*" part"*/, wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT | wxNO_BORDER/*wxBU_LEFT*/); - m_btn_move_up = new wxButton(win, wxID_ANY, "", wxDefaultPosition, wxDefaultSize/*wxSize(30, -1)*/, wxBU_LEFT); - m_btn_move_down = new wxButton(win, wxID_ANY, "", wxDefaultPosition, wxDefaultSize/*wxSize(30, -1)*/, wxBU_LEFT); - - //*** button's functions - btn_load_part->Bind(wxEVT_BUTTON, [win](wxEvent&) { -// on_btn_load(win); - }); - - btn_load_modifier->Bind(wxEVT_BUTTON, [win](wxEvent&) { -// on_btn_load(win, true); - }); - - btn_load_lambda_modifier->Bind(wxEVT_BUTTON, [win](wxEvent&) { -// on_btn_load(win, true, true); - }); - - btn_delete ->Bind(wxEVT_BUTTON, [](wxEvent&) { on_btn_del(); }); - btn_split ->Bind(wxEVT_BUTTON, [](wxEvent&) { on_btn_split(true); }); - m_btn_move_up ->Bind(wxEVT_BUTTON, [](wxEvent&) { on_btn_move_up(); }); - m_btn_move_down ->Bind(wxEVT_BUTTON, [](wxEvent&) { on_btn_move_down(); }); - //*** - - m_btn_move_up->SetMinSize(wxSize(20, -1)); - m_btn_move_down->SetMinSize(wxSize(20, -1)); - btn_load_part->SetBitmap(wxBitmap(from_u8(Slic3r::var("brick_add.png")), wxBITMAP_TYPE_PNG)); - btn_load_modifier->SetBitmap(wxBitmap(from_u8(Slic3r::var("brick_add.png")), wxBITMAP_TYPE_PNG)); - btn_load_lambda_modifier->SetBitmap(wxBitmap(from_u8(Slic3r::var("brick_add.png")), wxBITMAP_TYPE_PNG)); - btn_delete->SetBitmap(wxBitmap(from_u8(Slic3r::var("brick_delete.png")), wxBITMAP_TYPE_PNG)); - btn_split->SetBitmap(wxBitmap(from_u8(Slic3r::var("shape_ungroup.png")), wxBITMAP_TYPE_PNG)); - m_btn_move_up->SetBitmap(wxBitmap(from_u8(Slic3r::var("bullet_arrow_up.png")), wxBITMAP_TYPE_PNG)); - m_btn_move_down->SetBitmap(wxBitmap(from_u8(Slic3r::var("bullet_arrow_down.png")), wxBITMAP_TYPE_PNG)); - - m_sizer_object_buttons = new wxGridSizer(1, 3, 0, 0); - m_sizer_object_buttons->Add(btn_load_part, 0, wxEXPAND); - m_sizer_object_buttons->Add(btn_load_modifier, 0, wxEXPAND); - m_sizer_object_buttons->Add(btn_load_lambda_modifier, 0, wxEXPAND); - m_sizer_object_buttons->Show(false); - - m_sizer_part_buttons = new wxGridSizer(1, 3, 0, 0); - m_sizer_part_buttons->Add(btn_delete, 0, wxEXPAND); - m_sizer_part_buttons->Add(btn_split, 0, wxEXPAND); - { - auto up_down_sizer = new wxGridSizer(1, 2, 0, 0); - up_down_sizer->Add(m_btn_move_up, 1, wxEXPAND); - up_down_sizer->Add(m_btn_move_down, 1, wxEXPAND); - m_sizer_part_buttons->Add(up_down_sizer, 0, wxEXPAND); - } - m_sizer_part_buttons->Show(false); - - btn_load_part->SetFont(wxGetApp().small_font()); - btn_load_modifier->SetFont(wxGetApp().small_font()); - btn_load_lambda_modifier->SetFont(wxGetApp().small_font()); - btn_delete->SetFont(wxGetApp().small_font()); - btn_split->SetFont(wxGetApp().small_font()); - m_btn_move_up->SetFont(wxGetApp().small_font()); - m_btn_move_down->SetFont(wxGetApp().small_font()); - - sizer->Add(m_sizer_object_buttons, 0, wxEXPAND | wxLEFT, 20); - sizer->Add(m_sizer_part_buttons, 0, wxEXPAND | wxLEFT, 20); - return sizer; -} - -void update_after_moving() -{ - auto item = m_objects_ctrl->GetSelection(); - if (!item || m_selected_object_id<0) - return; - - auto volume_id = m_objects_model->GetVolumeIdByItem(item); - if (volume_id < 0) - return; - - auto d = m_move_options - m_last_coords; - auto volume = (*m_objects)[m_selected_object_id]->volumes[volume_id]; - volume->mesh.translate(d(0), d(1), d(2)); - m_last_coords = m_move_options; - - m_parts_changed = true; - parts_changed(m_selected_object_id); -} - -wxSizer* object_movers(wxWindow *win) -{ -// DynamicPrintConfig* config = &wxGetApp().preset_bundle->/*full_config();//*/printers.get_edited_preset().config; // TODO get config from Model_volume - std::shared_ptr optgroup = std::make_shared(win, "Move"/*, config*/); - optgroup->label_width = 20; - optgroup->m_on_change = [](t_config_option_key opt_key, boost::any value){ - int val = boost::any_cast(value); - bool update = false; - if (opt_key == "x" && m_move_options(0) != val){ - update = true; - m_move_options(0) = val; - } - else if (opt_key == "y" && m_move_options(1) != val){ - update = true; - m_move_options(1) = val; - } - else if (opt_key == "z" && m_move_options(2) != val){ - update = true; - m_move_options(2) = val; - } - if (update) update_after_moving(); - }; - - ConfigOptionDef def; - def.label = L("X"); - def.type = coInt; - def.gui_type = "slider"; - def.default_value = new ConfigOptionInt(0); - - Option option = Option(def, "x"); - option.opt.full_width = true; - optgroup->append_single_option_line(option); - m_mover_x = dynamic_cast(optgroup->get_field("x")->getWindow()); - - def.label = L("Y"); - option = Option(def, "y"); - optgroup->append_single_option_line(option); - m_mover_y = dynamic_cast(optgroup->get_field("y")->getWindow()); - - def.label = L("Z"); - option = Option(def, "z"); - optgroup->append_single_option_line(option); - m_mover_z = dynamic_cast(optgroup->get_field("z")->getWindow()); - - get_optgroups().push_back(optgroup); // ogObjectMovers - - m_sizer_object_movers = optgroup->sizer; - m_sizer_object_movers->Show(false); - - m_move_options = Vec3d(0, 0, 0); - m_last_coords = Vec3d(0, 0, 0); - - return optgroup->sizer; -} - -void Sidebar::add_objects_list(wxWindow* parent, wxBoxSizer* sizer) -{ - const auto ol_sizer = create_objects_list(parent); - sizer->Add(ol_sizer, 1, wxEXPAND | wxTOP, 20); - set_objects_list_sizer(ol_sizer); -} - -Line add_og_to_object_settings(const std::string& option_name, const std::string& sidetext, int def_value = 0) -{ - Line line = { _(option_name), "" }; - if (option_name == "Scale") { - line.near_label_widget = [](wxWindow* parent) { - auto btn = new PrusaLockButton(parent, wxID_ANY); - btn->Bind(wxEVT_BUTTON, [btn](wxCommandEvent &event){ - event.Skip(); - wxTheApp->CallAfter([btn]() { set_uniform_scaling(btn->IsLocked()); }); - }); - return btn; - }; - } - - ConfigOptionDef def; - def.type = coInt; - def.default_value = new ConfigOptionInt(def_value); - def.width = 55; - - if (option_name == "Rotation") - def.min = -360; - - const std::string lower_name = boost::algorithm::to_lower_copy(option_name); - - std::vector axes{ "x", "y", "z" }; - for (auto axis : axes) { - if (axis == "z" && option_name != "Scale") - def.sidetext = sidetext; - Option option = Option(def, lower_name + "_" + axis); - option.opt.full_width = true; - line.append_option(option); - } - - if (option_name == "Scale") - { - def.width = 45; - def.type = coStrings; - def.gui_type = "select_open"; - def.enum_labels.push_back(L("%")); - def.enum_labels.push_back(L("mm")); - def.default_value = new ConfigOptionStrings{ "mm" }; - - const Option option = Option(def, lower_name + "_unit"); - line.append_option(option); - } - - return line; -} - -void Sidebar::add_object_settings(wxWindow* parent, wxBoxSizer* sizer, t_optgroups& optgroups) -{ - auto optgroup = std::make_shared(parent, _(L("Object Settings"))); - optgroup->label_width = 100; - optgroup->set_grid_vgap(5); - - optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value){ - if (opt_key == "scale_unit"){ - const wxString& selection = boost::any_cast(value); - std::vector axes{ "x", "y", "z" }; - for (auto axis : axes) { - std::string key = "scale_" + axis; - get_optgroup(ogFrequentlyObjectSettings)->set_side_text(key, selection); - } - - g_is_percent_scale = selection == _("%"); - update_scale_values(); - } - }; - - ConfigOptionDef def; - - // Objects(sub-objects) name - def.label = L("Name"); -// def.type = coString; - def.gui_type = "legend"; - def.tooltip = L("Object name"); - def.full_width = true; - def.default_value = new ConfigOptionString{ " " }; - optgroup->append_single_option_line(Option(def, "object_name")); - - // Legend for object modification - auto line = Line{ "", "" }; - def.label = ""; - def.type = coString; - def.width = 55; - - std::vector axes{ "x", "y", "z" }; - for (const auto axis : axes) { - const auto label = boost::algorithm::to_upper_copy(axis); - def.default_value = new ConfigOptionString{ " "+label }; - Option option = Option(def, axis + "_axis_legend"); - line.append_option(option); - } - optgroup->append_line(line); - - - // Settings table - optgroup->append_line(add_og_to_object_settings(L("Position"), L("mm"))); - optgroup->append_line(add_og_to_object_settings(L("Rotation"), "°")); - optgroup->append_line(add_og_to_object_settings(L("Scale"), "mm")); - - - def.label = L("Place on bed"); - def.type = coBool; - def.tooltip = L("Automatic placing of models on printing bed in Y axis"); - def.gui_type = ""; - def.sidetext = ""; - def.default_value = new ConfigOptionBool{ false }; - optgroup->append_single_option_line(Option(def, "place_on_bed")); - - m_option_sizer = new wxBoxSizer(wxVERTICAL); - optgroup->sizer->Add(m_option_sizer, 1, wxEXPAND | wxLEFT, 5); - - sizer->Add(optgroup->sizer, 0, wxEXPAND | wxLEFT | wxTOP, 20); - - optgroup->disable(); - - optgroups.push_back(optgroup); // ogFrequentlyObjectSettings -} - -void add_object_to_list(const std::string &name, ModelObject* model_object) -{ - wxString item_name = name; - auto item = m_objects_model->Add(item_name, model_object->instances.size()); - m_objects_ctrl->Select(item); - - // Add error icon if detected auto-repaire - auto stats = model_object->volumes[0]->mesh.stl.stats; - int errors = stats.degenerate_facets + stats.edges_fixed + stats.facets_removed + - stats.facets_added + stats.facets_reversed + stats.backwards_edges; - if (errors > 0) { - const PrusaDataViewBitmapText data(item_name, m_icon_manifold_warning); - wxVariant variant; - variant << data; - m_objects_model->SetValue(variant, item, 0); - } - - if (model_object->volumes.size() > 1) { - for (auto id = 0; id < model_object->volumes.size(); id++) - m_objects_model->AddChild(item, - model_object->volumes[id]->name, - m_icon_solidmesh, - model_object->volumes[id]->config.option("extruder")->value, - false); - m_objects_ctrl->Expand(item); - } - -#ifndef __WXOSX__ - object_ctrl_selection_changed(); -#endif //__WXMSW__ -} - void delete_object_from_list() { auto item = m_objects_ctrl->GetSelection(); @@ -714,9 +252,7 @@ void object_ctrl_context_menu() { wxDataViewItem item; wxDataViewColumn* col; -// printf("object_ctrl_context_menu\n"); - const wxPoint pt = get_mouse_position_in_control(); -// printf("mouse_position_in_control: x = %d, y = %d\n", pt.x, pt.y); + const wxPoint pt;//!!! = get_mouse_position_in_control(); m_objects_ctrl->HitTest(pt, item, col); if (!item) #ifdef __WXOSX__ // #ys_FIXME temporary workaround for OSX @@ -730,9 +266,7 @@ void object_ctrl_context_menu() #else return; #endif // __WXOSX__ -// printf("item exists\n"); const wxString title = col->GetTitle(); -// printf("title = *%s*\n", title.data().AsChar()); if (title == " ") show_context_menu(); @@ -1472,29 +1006,6 @@ void parts_changed(int obj_idx) e.SetString(event_str); // get_main_frame()->ProcessWindowEvent(e); // #ys_FIXME } - -void update_settings_value() -{ - auto og = get_optgroup(ogFrequentlyObjectSettings); - if (m_selected_object_id < 0 || m_objects->size() <= m_selected_object_id) { - og->set_value("position_x", 0); - og->set_value("position_y", 0); - og->set_value("position_z", 0); - og->set_value("scale_x", 0); - og->set_value("scale_y", 0); - og->set_value("scale_z", 0); - og->set_value("rotation_x", 0); - og->set_value("rotation_y", 0); - og->set_value("rotation_z", 0); - og->disable(); - return; - } - g_is_percent_scale = boost::any_cast(og->get_value("scale_unit")) == _("%"); - update_position_values(); - update_scale_values(); - update_rotation_values(); - og->enable(); -} void part_selection_changed() { @@ -1549,7 +1060,7 @@ void part_selection_changed() m_selected_object_id = obj_idx; - update_settings_value(); +// update_values(); } void set_extruder_column_hidden(bool hide) @@ -1571,149 +1082,6 @@ void update_extruder_in_config(const wxString& selection) } } -void update_scale_values() -{ - auto og = get_optgroup(ogFrequentlyObjectSettings); - auto instance = (*m_objects)[m_selected_object_id]->instances.front(); - auto size = (*m_objects)[m_selected_object_id]->instance_bounding_box(0).size(); - -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - if (g_is_percent_scale) { - og->set_value("scale_x", int(instance->get_scaling_factor(X) * 100)); - og->set_value("scale_y", int(instance->get_scaling_factor(Y) * 100)); - og->set_value("scale_z", int(instance->get_scaling_factor(Z) * 100)); - } - else { - og->set_value("scale_x", int(instance->get_scaling_factor(X) * size(0) + 0.5)); - og->set_value("scale_y", int(instance->get_scaling_factor(Y) * size(1) + 0.5)); - og->set_value("scale_z", int(instance->get_scaling_factor(Z) * size(2) + 0.5)); - } -#else - if (g_is_percent_scale) { - auto scale = instance->scaling_factor * 100.0; - og->set_value("scale_x", int(scale)); - og->set_value("scale_y", int(scale)); - og->set_value("scale_z", int(scale)); - } - else { - og->set_value("scale_x", int(instance->scaling_factor * size(0) + 0.5)); - og->set_value("scale_y", int(instance->scaling_factor * size(1) + 0.5)); - og->set_value("scale_z", int(instance->scaling_factor * size(2) + 0.5)); - } -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM -} - -void update_position_values() -{ - auto og = get_optgroup(ogFrequentlyObjectSettings); - auto instance = (*m_objects)[m_selected_object_id]->instances.front(); - -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - og->set_value("position_x", int(instance->get_offset(X))); - og->set_value("position_y", int(instance->get_offset(Y))); - og->set_value("position_z", int(instance->get_offset(Z))); -#else - og->set_value("position_x", int(instance->offset(0))); - og->set_value("position_y", int(instance->offset(1))); - og->set_value("position_z", 0); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM -} - -void update_position_values(const Vec3d& position) -{ - auto og = get_optgroup(ogFrequentlyObjectSettings); - - og->set_value("position_x", int(position(0))); - og->set_value("position_y", int(position(1))); - og->set_value("position_z", int(position(2))); -} - -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM -void update_scale_values(const Vec3d& scaling_factor) -{ - auto og = get_optgroup(ogFrequentlyObjectSettings); - - // this is temporary - // to be able to update the values as size - // we need to store somewhere the original size - // or have it passed as parameter - if (!g_is_percent_scale) - og->set_value("scale_unit", _("%")); - - auto scale = scaling_factor * 100.0; - og->set_value("scale_x", int(scale(0))); - og->set_value("scale_y", int(scale(1))); - og->set_value("scale_z", int(scale(2))); -} -#else -void update_scale_values(double scaling_factor) -{ - auto og = get_optgroup(ogFrequentlyObjectSettings); - - // this is temporary - // to be able to update the values as size - // we need to store somewhere the original size - // or have it passed as parameter - if (!g_is_percent_scale) - og->set_value("scale_unit", _("%")); - - auto scale = scaling_factor * 100.0; - og->set_value("scale_x", int(scale)); - og->set_value("scale_y", int(scale)); - og->set_value("scale_z", int(scale)); -} -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - -void update_rotation_values() -{ -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - update_rotation_value((*m_objects)[m_selected_object_id]->instances.front()->get_rotation()); -#else - auto og = get_optgroup(ogFrequentlyObjectSettings); - auto instance = (*m_objects)[m_selected_object_id]->instances.front(); - og->set_value("rotation_x", 0); - og->set_value("rotation_y", 0); - og->set_value("rotation_z", int(Geometry::rad2deg(instance->rotation))); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM -} - -void update_rotation_value(double angle, Axis axis) -{ - auto og = get_optgroup(ogFrequentlyObjectSettings); - - std::string axis_str; - switch (axis) - { - case X: - { - axis_str = "rotation_x"; - break; - } - case Y: - { - axis_str = "rotation_y"; - break; - } - case Z: - { - axis_str = "rotation_z"; - break; - } - } - - og->set_value(axis_str, round_nearest(int(Geometry::rad2deg(angle)), 0)); -} - -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM -void update_rotation_value(const Vec3d& rotation) -{ - auto og = get_optgroup(ogFrequentlyObjectSettings); - og->set_value("rotation_x", int(round_nearest(Geometry::rad2deg(rotation(0)), 0))); - og->set_value("rotation_y", int(round_nearest(Geometry::rad2deg(rotation(1)), 0))); - og->set_value("rotation_z", int(round_nearest(Geometry::rad2deg(rotation(2)), 0))); -} -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - void set_uniform_scaling(const bool uniform_scale) { g_is_uniform_scale = uniform_scale; @@ -1792,20 +1160,6 @@ void on_drop(wxDataViewEvent &event) g_prevent_list_events = false; } -void update_objects_list_extruder_column(int extruders_count) -{ - if (!m_objects_ctrl) return; // #ys_FIXME - if (wxGetApp().preset_bundle->printers.get_selected_preset().printer_technology() == ptSLA) - extruders_count = 1; - - // delete old 3rd column - m_objects_ctrl->DeleteColumn(m_objects_ctrl->GetColumn(2)); - // insert new created 3rd column - m_objects_ctrl->InsertColumn(2, object_ctrl_create_extruder_column(extruders_count)); - // set show/hide for this column - set_extruder_column_hidden(extruders_count <= 1); -} - void create_double_slider(wxWindow* parent, wxBoxSizer* sizer, wxGLCanvas* canvas) { m_slider = new PrusaDoubleSlider(parent, wxID_ANY, 0, 0, 0, 100); diff --git a/src/slic3r/GUI/GUI_ObjectParts.hpp b/src/slic3r/GUI/GUI_ObjectParts.hpp index 01011d2c4e..18614c4ee9 100644 --- a/src/slic3r/GUI/GUI_ObjectParts.hpp +++ b/src/slic3r/GUI/GUI_ObjectParts.hpp @@ -106,28 +106,11 @@ void on_btn_move_down(); void parts_changed(int obj_idx); void part_selection_changed(); -void update_settings_value(); // show/hide "Extruder" column for Objects List void set_extruder_column_hidden(bool hide); // update extruder in current config void update_extruder_in_config(const wxString& selection); -// update position values displacements or "gizmos" -void update_position_values(); -void update_position_values(const Vec3d& position); -// update scale values after scale unit changing or "gizmos" -void update_scale_values(); -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM -void update_scale_values(const Vec3d& scaling_factor); -#else -void update_scale_values(double scaling_factor); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM -// update rotation values object selection changing -void update_rotation_values(); -// update rotation value after "gizmos" -void update_rotation_value(double angle, Axis axis); -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM -void update_rotation_value(const Vec3d& rotation); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM + void set_uniform_scaling(const bool uniform_scale); void on_begin_drag(wxDataViewEvent &event); diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 502394aca8..07f4c5e8e4 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -274,7 +274,7 @@ void MainFrame::create_preset_tabs() void MainFrame::add_created_tab(Tab* panel) { - panel->create_preset_tab(wxGetApp().preset_bundle); + panel->create_preset_tab(); // Load the currently selected preset into the GUI, update the preset selection box. panel->load_current_preset(); diff --git a/src/slic3r/GUI/OptionsGroup.hpp b/src/slic3r/GUI/OptionsGroup.hpp index 3e196f70c8..8ee2ee1671 100644 --- a/src/slic3r/GUI/OptionsGroup.hpp +++ b/src/slic3r/GUI/OptionsGroup.hpp @@ -231,6 +231,7 @@ public: bool m_full_labels {0}; t_opt_map m_opt_map; + 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*/{ Option option = get_option(title, idx); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 2133533ebc..29e79b79db 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -27,10 +27,11 @@ #include "libslic3r/Polygon.hpp" #include "GUI.hpp" #include "GUI_App.hpp" +#include "GUI_ObjectList.hpp" +#include "GUI_ObjectManipulation.hpp" #include "MainFrame.hpp" #include "3DScene.hpp" #include "GLCanvas3D.hpp" -#include "GUI_ObjectParts.hpp" #include "GLToolbar.hpp" #include "GUI_Preview.hpp" #include "Tab.hpp" @@ -200,6 +201,141 @@ PresetComboBox::PresetComboBox(wxWindow *parent, Preset::Type preset_type) : PresetComboBox::~PresetComboBox() {} +// Frequently changed parameters + +class FreqChangedParams : public OG_Settings +{ + double m_brim_width = 0.0; + wxButton* m_wiping_dialog_button{ nullptr }; +public: + FreqChangedParams(wxWindow* parent, const int label_width); + ~FreqChangedParams() {} + + wxButton* get_wiping_dialog_button() { return m_wiping_dialog_button; } +}; + +FreqChangedParams::FreqChangedParams(wxWindow* parent, const int label_width) : + OG_Settings(parent, false) +{ + DynamicPrintConfig* config = &wxGetApp().preset_bundle->prints.get_edited_preset().config; + + m_og->set_config(config); + m_og->label_width = label_width; + + m_og->m_on_change = [config, this](t_config_option_key opt_key, boost::any value){ + TabPrint* tab_print = nullptr; + for (size_t i = 0; i < wxGetApp().tab_panel()->GetPageCount(); ++i) { + Tab *tab = dynamic_cast(wxGetApp().tab_panel()->GetPage(i)); + if (!tab) + continue; + if (tab->name() == "print"){ + tab_print = static_cast(tab); + break; + } + } + if (tab_print == nullptr) + return; + + if (opt_key == "fill_density"){ + value = m_og->get_config_value(*config, opt_key); + tab_print->set_value(opt_key, value); + tab_print->update(); + } + else{ + DynamicPrintConfig new_conf = *config; + if (opt_key == "brim"){ + double new_val; + double brim_width = config->opt_float("brim_width"); + if (boost::any_cast(value) == true) + { + new_val = m_brim_width == 0.0 ? 10 : + m_brim_width < 0.0 ? m_brim_width * (-1) : + m_brim_width; + } + else{ + m_brim_width = brim_width * (-1); + new_val = 0; + } + new_conf.set_key_value("brim_width", new ConfigOptionFloat(new_val)); + } + else{ //(opt_key == "support") + const wxString& selection = boost::any_cast(value); + + auto support_material = selection == _("None") ? false : true; + new_conf.set_key_value("support_material", new ConfigOptionBool(support_material)); + + if (selection == _("Everywhere")) + new_conf.set_key_value("support_material_buildplate_only", new ConfigOptionBool(false)); + else if (selection == _("Support on build plate only")) + new_conf.set_key_value("support_material_buildplate_only", new ConfigOptionBool(true)); + } + tab_print->load_config(new_conf); + } + + tab_print->update_dirty(); + }; + + Option option = m_og->get_option("fill_density"); + option.opt.sidetext = ""; + option.opt.full_width = true; + m_og->append_single_option_line(option); + + ConfigOptionDef def; + + def.label = L("Support"); + def.type = coStrings; + def.gui_type = "select_open"; + def.tooltip = L("Select what kind of support do you need"); + def.enum_labels.push_back(L("None")); + def.enum_labels.push_back(L("Support on build plate only")); + def.enum_labels.push_back(L("Everywhere")); + std::string selection = !config->opt_bool("support_material") ? + "None" : + config->opt_bool("support_material_buildplate_only") ? + "Support on build plate only" : + "Everywhere"; + def.default_value = new ConfigOptionStrings{ selection }; + option = Option(def, "support"); + option.opt.full_width = true; + m_og->append_single_option_line(option); + + m_brim_width = config->opt_float("brim_width"); + def.label = L("Brim"); + def.type = coBool; + def.tooltip = L("This flag enables the brim that will be printed around each object on the first layer."); + def.gui_type = ""; + def.default_value = new ConfigOptionBool{ m_brim_width > 0.0 ? true : false }; + option = Option(def, "brim"); + m_og->append_single_option_line(option); + + + Line line = { "", "" }; + line.widget = [config, this](wxWindow* parent){ + m_wiping_dialog_button = new wxButton(parent, wxID_ANY, _(L("Purging volumes")) + dots, wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT); + auto sizer = new wxBoxSizer(wxHORIZONTAL); + sizer->Add(m_wiping_dialog_button); + m_wiping_dialog_button->Bind(wxEVT_BUTTON, ([parent](wxCommandEvent& e) + { + auto &config = wxGetApp().preset_bundle->project_config; + const std::vector &init_matrix = (config.option("wiping_volumes_matrix"))->values; + const std::vector &init_extruders = (config.option("wiping_volumes_extruders"))->values; + + WipingDialog dlg(parent, cast(init_matrix), cast(init_extruders)); + + if (dlg.ShowModal() == wxID_OK) { + std::vector matrix = dlg.get_matrix(); + std::vector extruders = dlg.get_extruders(); + (config.option("wiping_volumes_matrix"))->values = std::vector(matrix.begin(), matrix.end()); + (config.option("wiping_volumes_extruders"))->values = std::vector(extruders.begin(), extruders.end()); + g_on_request_update_callback.call(); + } + })); + return sizer; + }; + m_og->append_line(line); +} + + // Sidebar / private struct Sidebar::priv @@ -216,6 +352,9 @@ struct Sidebar::priv PresetComboBox *combo_printer; wxBoxSizer *sizer_params; + FreqChangedParams *frequently_changed_parameters; + ObjectList *object_list; + ObjectManipulation *object_manipulation; ObjectInfo *object_info; SlicedInfo *sliced_info; @@ -225,10 +364,6 @@ struct Sidebar::priv wxButton *btn_send_gcode; std::vector > optgroups {}; - double brim_width = 0.0; - size_t label_width = 100; - wxButton* btn_wiping_dialog {nullptr}; - }; @@ -268,16 +403,24 @@ Sidebar::Sidebar(wxWindow *parent) init_combo(&p->combo_sla_material, _(L("SLA material")), Preset::TYPE_SLA_MATERIAL, false); init_combo(&p->combo_printer, _(L("Printer")), Preset::TYPE_PRINTER, false); + // calculate width of the preset labels p->sizer_presets->Layout(); + const wxArrayInt& ar = p->sizer_presets->GetColWidths(); + int label_width = ar.IsEmpty() ? 100 : ar.front()-4; + + p->sizer_params = new wxBoxSizer(wxVERTICAL); // Frequently changed parameters - p->sizer_params = new wxBoxSizer(wxVERTICAL); - add_frequently_changed_parameters(p->scrolled, p->sizer_params/*, p->sizer_presets*/); + p->frequently_changed_parameters = new FreqChangedParams(p->scrolled, label_width); + p->sizer_params->Add(p->frequently_changed_parameters->get_sizer(), 0, wxEXPAND | wxBOTTOM | wxLEFT, 2); // Object List - add_objects_list(p->scrolled, p->sizer_params); + p->object_list = new ObjectList(p->scrolled); + p->sizer_params->Add(p->object_list->get_sizer(), 1, wxEXPAND | wxTOP, 20); + // Frequently Object Settings - add_object_settings(p->scrolled, p->sizer_params, p->optgroups); + p->object_manipulation = new ObjectManipulation(p->scrolled); + p->sizer_params->Add(p->object_manipulation->get_sizer(), 0, wxEXPAND | wxLEFT | wxTOP, 20); // Buttons in the scrolled area wxBitmap arrow_up(GUI::from_u8(Slic3r::var("brick_go.png")), wxBITMAP_TYPE_PNG); @@ -364,6 +507,11 @@ void Sidebar::update_presets(Preset::Type preset_type) // wxTheApp->{preset_bundle}->export_selections(wxTheApp->{app_config}); } +ObjectManipulation* Sidebar::obj_manipul() +{ + return p->object_manipulation; +} + ConfigOptionsGroup* Sidebar::get_optgroup(size_t i) { return p->optgroups.empty() ? nullptr : p->optgroups[i].get(); @@ -375,7 +523,17 @@ t_optgroups& Sidebar::get_optgroups() { wxButton* Sidebar::get_wiping_dialog_button() { - return p->btn_wiping_dialog; + return p->frequently_changed_parameters->get_wiping_dialog_button(); +} + +void Sidebar::update_objects_list_extruder_column(int extruders_count) +{ + p->object_list->update_objects_list_extruder_column(extruders_count); +} + +int Sidebar::get_ol_selection() +{ + return p->object_list->get_sel_obj_id(); } @@ -431,7 +589,7 @@ struct Plater::priv wxNotebook *notebook; Sidebar *sidebar; wxGLCanvas *canvas3D; // TODO: Use GLCanvas3D when we can - GUI::Preview *preview; + Preview *preview; BackgroundSlicingProcess background_process; static const int gl_attrs[]; @@ -933,6 +1091,7 @@ Plater::~Plater() } Sidebar& Plater::sidebar() { return *p->sidebar; } +Model& Plater::model() { return p->model; } std::string Plater::export_gcode(const std::string &output_path) { diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 14de626741..1d9022350c 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -4,17 +4,18 @@ #include #include -#include #include "Preset.hpp" -class wxBoxSizer; - namespace Slic3r { + +class Model; + namespace GUI { class MainFrame; class ConfigOptionsGroup; +class ObjectManipulation; using t_optgroups = std::vector >; @@ -30,14 +31,14 @@ public: void update_presets(Slic3r::Preset::Type preset_type); - void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer); - void add_objects_list(wxWindow* parent, wxBoxSizer* sizer); - void add_object_settings(wxWindow* parent, wxBoxSizer* sizer, t_optgroups& optgroups); + ObjectManipulation* obj_manipul(); - - ConfigOptionsGroup* get_optgroup(size_t i); - t_optgroups& get_optgroups(); + ConfigOptionsGroup* get_optgroup(size_t i); // #ys_FIXME_for_delete + t_optgroups& get_optgroups();// #ys_FIXME_for_delete wxButton* get_wiping_dialog_button(); + void update_objects_list_extruder_column(int extruders_count); + int get_ol_selection(); + private: struct priv; std::unique_ptr p; @@ -57,6 +58,7 @@ public: ~Plater(); Sidebar& sidebar(); + Model& model(); // TODO: use fs::path // Note: empty string means request default path diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 07063a6bb4..7a13f6df76 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -33,9 +33,9 @@ namespace Slic3r { namespace GUI { -void Tab::create_preset_tab(PresetBundle *preset_bundle) +void Tab::create_preset_tab() { - m_preset_bundle = preset_bundle; + m_preset_bundle = wxGetApp().preset_bundle; // Vertical sizer to hold the choice menu and the rest of the page. #ifdef __WXOSX__ @@ -711,7 +711,7 @@ void Tab::on_value_change(const std::string& opt_key, const boost::any& value) // Show/hide the 'purging volumes' button void Tab::update_wiping_button_visibility() { - if (wxGetApp().preset_bundle->printers.get_selected_preset().printer_technology() == ptSLA) + if (m_preset_bundle->printers.get_selected_preset().printer_technology() == ptSLA) return; // ys_FIXME bool wipe_tower_enabled = dynamic_cast( (m_preset_bundle->prints.get_edited_preset().config ).option("wipe_tower"))->value; bool multiple_extruders = dynamic_cast((m_preset_bundle->printers.get_edited_preset().config).option("nozzle_diameter"))->values.size() > 1; @@ -1044,7 +1044,7 @@ void TabPrint::reload_config(){ void TabPrint::update() { - if (wxGetApp().preset_bundle->printers.get_selected_preset().printer_technology() == ptSLA) + if (m_preset_bundle->printers.get_selected_preset().printer_technology() == ptSLA) return; // ys_FIXME Freeze(); @@ -1410,7 +1410,7 @@ void TabFilament::reload_config(){ void TabFilament::update() { - if (wxGetApp().preset_bundle->printers.get_selected_preset().printer_technology() == ptSLA) + if (m_preset_bundle->printers.get_selected_preset().printer_technology() == ptSLA) return; // ys_FIXME Freeze(); @@ -1842,7 +1842,8 @@ void TabPrinter::extruders_count_changed(size_t extruders_count){ build_extruder_pages(); reload_config(); on_value_change("extruders_count", extruders_count); - update_objects_list_extruder_column(extruders_count); + if (wxGetApp().mainframe) + wxGetApp().mainframe->m_plater->sidebar().update_objects_list_extruder_column(extruders_count); } void TabPrinter::append_option_line(ConfigOptionsGroupShp optgroup, const std::string opt_key) @@ -3030,7 +3031,7 @@ void TabSLAMaterial::build() void TabSLAMaterial::update() { - if (wxGetApp().preset_bundle->printers.get_selected_preset().printer_technology() == ptFFF) + if (m_preset_bundle->printers.get_selected_preset().printer_technology() == ptFFF) return; // ys_FIXME } diff --git a/src/slic3r/GUI/Tab.hpp b/src/slic3r/GUI/Tab.hpp index afdf2008b2..c9fb1764c8 100644 --- a/src/slic3r/GUI/Tab.hpp +++ b/src/slic3r/GUI/Tab.hpp @@ -215,7 +215,7 @@ public: void set_event_value_change(wxEventType evt) { m_event_value_change = evt; } void set_event_presets_changed(wxEventType evt) { m_event_presets_changed = evt; } - void create_preset_tab(PresetBundle *preset_bundle); + void create_preset_tab(); void load_current_preset(); void rebuild_page_tree(bool tree_sel_change_event = false); void select_preset(std::string preset_name = ""); From ea30385fd0fe85b368c03ec3fb359bf8b75d36d0 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Fri, 5 Oct 2018 23:29:15 +0200 Subject: [PATCH 062/186] Completed split of the GUI_ObjectParts --- src/slic3r/CMakeLists.txt | 2 - src/slic3r/GUI/GLCanvas3D.cpp | 5 +- src/slic3r/GUI/GUI.cpp | 229 +--- src/slic3r/GUI/GUI.hpp | 82 +- src/slic3r/GUI/GUI_App.cpp | 46 +- src/slic3r/GUI/GUI_App.hpp | 36 +- src/slic3r/GUI/GUI_ObjectList.cpp | 1077 ++++++++++++++++- src/slic3r/GUI/GUI_ObjectList.hpp | 101 +- src/slic3r/GUI/GUI_ObjectManipulation.cpp | 137 ++- src/slic3r/GUI/GUI_ObjectManipulation.hpp | 14 +- src/slic3r/GUI/GUI_ObjectParts.cpp | 1274 --------------------- src/slic3r/GUI/GUI_ObjectParts.hpp | 134 --- src/slic3r/GUI/GUI_Preview.cpp | 102 +- src/slic3r/GUI/GUI_Preview.hpp | 16 + src/slic3r/GUI/LambdaObjectDialog.hpp | 18 + src/slic3r/GUI/MainFrame.cpp | 25 +- src/slic3r/GUI/MainFrame.hpp | 10 + src/slic3r/GUI/Plater.cpp | 54 +- src/slic3r/GUI/Plater.hpp | 9 +- src/slic3r/GUI/Tab.cpp | 28 +- src/slic3r/GUI/wxExtensions.cpp | 5 +- 21 files changed, 1524 insertions(+), 1880 deletions(-) delete mode 100644 src/slic3r/GUI/GUI_ObjectParts.cpp delete mode 100644 src/slic3r/GUI/GUI_ObjectParts.hpp diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt index 4974d66fc4..54c90c20ef 100644 --- a/src/slic3r/CMakeLists.txt +++ b/src/slic3r/CMakeLists.txt @@ -33,8 +33,6 @@ add_library(libslic3r_gui STATIC ${LIBDIR}/slic3r/GUI/PresetHints.hpp ${LIBDIR}/slic3r/GUI/GUI.cpp ${LIBDIR}/slic3r/GUI/GUI.hpp - ${LIBDIR}/slic3r/GUI/GUI_ObjectParts.cpp - ${LIBDIR}/slic3r/GUI/GUI_ObjectParts.hpp ${LIBDIR}/slic3r/GUI/GUI_Preview.cpp ${LIBDIR}/slic3r/GUI/GUI_Preview.hpp ${LIBDIR}/slic3r/GUI/GUI_PreviewIface.cpp diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index f65e380e5f..5a28ee5c08 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -11,6 +11,7 @@ #include "../../libslic3r/PrintConfig.hpp" #include "../../libslic3r/GCode/PreviewData.hpp" #include "GUI_App.hpp" +#include "GUI_ObjectList.hpp" #include "GUI_ObjectManipulation.hpp" #include @@ -3243,7 +3244,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) { v->set_scaling_factor((double)scale_factor); } - update_scale_values((double)scale_factor); + wxGetApp().obj_manipul()->update_scale_values((double)scale_factor); #endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM break; } @@ -5397,7 +5398,7 @@ void GLCanvas3D::_on_select(int volume_idx, int object_idx) } post_event(ObjectSelectEvent(obj_id, vol_id)); - Slic3r::GUI::select_current_volume(obj_id, vol_id); + wxGetApp().obj_list()->select_current_volume(obj_id, vol_id); } std::vector GLCanvas3D::_parse_colors(const std::vector& colors) diff --git a/src/slic3r/GUI/GUI.cpp b/src/slic3r/GUI/GUI.cpp index 34889b809d..e06f6b7215 100644 --- a/src/slic3r/GUI/GUI.cpp +++ b/src/slic3r/GUI/GUI.cpp @@ -1,14 +1,12 @@ #include "GUI.hpp" +#include "GUI_App.hpp" #include "../AppController.hpp" #include "WipeTowerDialog.hpp" #include -#include #include #include -#include -#include #if __APPLE__ #import @@ -26,50 +24,18 @@ #include "boost/nowide/convert.hpp" #endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include #include "wxExtensions.hpp" - -#include "Tab.hpp" -#include "TabIface.hpp" #include "GUI_Preview.hpp" #include "GUI_PreviewIface.hpp" #include "AboutDialog.hpp" #include "AppConfig.hpp" -#include "ConfigSnapshotDialog.hpp" -#include "ProgressStatusBar.hpp" -#include "Utils.hpp" -#include "MsgDialog.hpp" #include "ConfigWizard.hpp" -#include "Preferences.hpp" #include "PresetBundle.hpp" #include "UpdateDialogs.hpp" -#include "FirmwareDialog.hpp" -#include "GUI_ObjectParts.hpp" - -#include "../Utils/PresetUpdater.hpp" -#include "../Config/Snapshot.hpp" - -#include "3DScene.hpp" -#include "libslic3r/I18N.hpp" -#include "Model.hpp" -#include "LambdaObjectDialog.hpp" +#include "../../libslic3r/Utils.hpp" #include "../../libslic3r/Print.hpp" namespace Slic3r { namespace GUI { @@ -116,91 +82,8 @@ void break_to_debugger() #endif /* _WIN32 */ } -// #ys_FIXME_for_delete -std::vector g_tabs_list; - -//showed/hided controls according to the view mode -wxWindow *g_right_panel = nullptr; -wxBoxSizer *g_frequently_changed_parameters_sizer = nullptr; -wxBoxSizer *g_info_sizer = nullptr; -wxBoxSizer *g_object_list_sizer = nullptr; -std::vector g_buttons; -wxStaticBitmap *g_manifold_warning_icon = nullptr; -bool g_show_print_info = false; -bool g_show_manifold_warning_icon = false; - PreviewIface* g_preview = nullptr; -enum ActionButtons -{ - abExportGCode, - abReslice, - abPrint, - abSendGCode, -}; - -void set_objects_from_perl( wxWindow* parent, - wxBoxSizer *frequently_changed_parameters_sizer, - wxBoxSizer *info_sizer, - wxButton *btn_export_gcode, - wxButton *btn_reslice, - wxButton *btn_print, - wxButton *btn_send_gcode, - wxStaticBitmap *manifold_warning_icon) -{ - g_right_panel = parent->GetParent(); - g_frequently_changed_parameters_sizer = frequently_changed_parameters_sizer; - g_info_sizer = info_sizer; - - g_buttons.push_back(btn_export_gcode); - g_buttons.push_back(btn_reslice); - g_buttons.push_back(btn_print); - g_buttons.push_back(btn_send_gcode); - - // Update font style for buttons -// for (auto btn : g_buttons) -// btn->SetFont(bold_font()); - - g_manifold_warning_icon = manifold_warning_icon; -} - -void set_show_print_info(bool show) -{ - g_show_print_info = show; -} - -void set_show_manifold_warning_icon(bool show) -{ - g_show_manifold_warning_icon = show; - if (!g_manifold_warning_icon) - return; - - // update manifold_warning_icon showing - if (show && !g_info_sizer->IsShown(static_cast(0))) - g_show_manifold_warning_icon = false; - - g_manifold_warning_icon->Show(g_show_manifold_warning_icon); - g_manifold_warning_icon->GetParent()->Layout(); -} - -void set_objects_list_sizer(wxBoxSizer *objects_list_sizer){ - g_object_list_sizer = objects_list_sizer; -} - -void open_model(wxWindow *parent, wxArrayString& input_files){ - auto dialog = new wxFileDialog(parent /*? parent : GetTopWindow()*/, - _(L("Choose one or more files (STL/OBJ/AMF/3MF/PRUSA):")), - get_app_config()->get_last_dir(), "", - MODEL_WILDCARD, wxFD_OPEN | wxFD_MULTIPLE | wxFD_FILE_MUST_EXIST); - if (dialog->ShowModal() != wxID_OK) { - dialog->Destroy(); - return ; - } - - dialog->GetPaths(input_files); - dialog->Destroy(); -} - bool config_wizard_startup(bool app_config_exists) { if (!app_config_exists || wxGetApp().preset_bundle->printers.size() <= 1) { @@ -236,38 +119,6 @@ void config_wizard(int reason) // Load the currently selected preset into the GUI, update the preset selection box. wxGetApp().load_current_presets(); } -// #ys_FIXME_for_delete -std::vector preset_tabs = { - { "print", nullptr, ptFFF }, - { "filament", nullptr, ptFFF }, - { "sla_material", nullptr, ptSLA } -}; -std::vector* get_preset_tabs() { - return &preset_tabs; -} - -Tab* get_tab(const std::string& name) -{ - std::vector::iterator it = std::find_if(preset_tabs.begin(), preset_tabs.end(), - [name](PresetTab& tab){ return name == tab.name; }); - return it != preset_tabs.end() ? it->panel : nullptr; -} - -TabIface* get_preset_tab_iface(char *name) -{ - Tab* tab = get_tab(name); - if (tab) return new TabIface(tab); - - for (size_t i = 0; i < wxGetApp().tab_panel()->GetPageCount(); ++i) { - Tab *tab = dynamic_cast(wxGetApp().tab_panel()->GetPage(i)); - if (! tab) - continue; - if (tab->name() == name) { - return new TabIface(tab); - } - } - return new TabIface(nullptr); -} PreviewIface* create_preview_iface(wxNotebook* parent, DynamicPrintConfig* config, Print* print, GCodePreviewData* gcode_preview_data) { @@ -422,9 +273,6 @@ void set_print_callback_event(Print *print, int id) }); } -wxWindow* get_right_panel(){ - return g_right_panel; -} void create_combochecklist(wxComboCtrl* comboCtrl, std::string text, std::string items, bool initial_value) { if (comboCtrl == nullptr) @@ -499,65 +347,6 @@ std::string into_u8(const wxString &str) return std::string(buffer_utf8.data()); } -void set_model_events_from_perl(Model &model, - int event_object_selection_changed, - int event_object_settings_changed, - int event_remove_object, - int event_update_scene) -{ - set_event_object_selection_changed(event_object_selection_changed); - set_event_object_settings_changed(event_object_settings_changed); - set_event_remove_object(event_remove_object); - set_event_update_scene(event_update_scene); - set_objects_from_model(model); - init_mesh_icons(); - -// wxWindowUpdateLocker noUpdates(parent); - -// add_objects_list(parent, sizer); - -// add_collapsible_panes(parent, sizer); -} - -void show_buttons(bool show) -{ - g_buttons[abReslice]->Show(show); - for (size_t i = 0; i < wxGetApp().tab_panel()->GetPageCount(); ++i) { - TabPrinter *tab = dynamic_cast(wxGetApp().tab_panel()->GetPage(i)); - if (!tab) - continue; - if (wxGetApp().preset_bundle->printers.get_selected_preset().printer_technology() == ptFFF) { - g_buttons[abPrint]->Show(show && !tab->m_config->opt_string("serial_port").empty()); - g_buttons[abSendGCode]->Show(show && !tab->m_config->opt_string("print_host").empty()); - } - break; - } -} - -void show_info_sizer(const bool show) -{ - g_info_sizer->Show(static_cast(0), show); - g_info_sizer->Show(1, show && g_show_print_info); - g_manifold_warning_icon->Show(show && g_show_manifold_warning_icon); -} - -void show_object_name(bool show) -{ - wxGridSizer* grid_sizer = get_optgroup(ogFrequentlyObjectSettings)->get_grid_sizer(); - grid_sizer->Show(static_cast(0), show); - grid_sizer->Show(static_cast(1), show); -} - -ConfigOptionsGroup* get_optgroup(size_t i) -{ - return wxGetApp().mainframe->m_plater->sidebar().get_optgroup(i); -// return m_optgroups.empty() ? nullptr : m_optgroups[i].get(); -} - -std::vector >& get_optgroups() { - return wxGetApp().mainframe->m_plater->sidebar().get_optgroups();//m_optgroups; -} - wxWindow* export_option_creator(wxWindow* parent) { wxPanel* panel = new wxPanel(parent, -1); @@ -664,20 +453,6 @@ void restore_window_size(wxTopLevelWindow *window, const std::string &name) } } -void enable_action_buttons(bool enable) -{ - if (g_buttons.empty()) - return; - - // Update background colour for buttons - const wxColour bgrd_color = enable ? wxColour(224, 224, 224/*255, 96, 0*/) : wxColour(204, 204, 204); - - for (auto btn : g_buttons) { - btn->Enable(enable); - btn->SetBackgroundColour(bgrd_color); - } -} - void about() { AboutDialog dlg; diff --git a/src/slic3r/GUI/GUI.hpp b/src/slic3r/GUI/GUI.hpp index de17ff7a28..1f2107d599 100644 --- a/src/slic3r/GUI/GUI.hpp +++ b/src/slic3r/GUI/GUI.hpp @@ -1,44 +1,22 @@ #ifndef slic3r_GUI_hpp_ #define slic3r_GUI_hpp_ -#include -#include -#include "PrintConfig.hpp" +#include "Config.hpp" #include "callback.hpp" -#include "GUI_ObjectParts.hpp" #include -#include -class wxApp; class wxWindow; -class wxFrame; class wxMenuBar; class wxNotebook; -class wxPanel; class wxComboCtrl; -class wxString; -class wxArrayString; -class wxArrayLong; -class wxColour; -class wxBoxSizer; -class wxFlexGridSizer; -class wxButton; class wxFileDialog; -class wxStaticBitmap; -class wxFont; class wxTopLevelWindow; namespace Slic3r { -class PresetBundle; -class PresetCollection; -class Print; -class ProgressStatusBar; class AppConfig; -class PresetUpdater; class DynamicPrintConfig; -class TabIface; class PreviewIface; class Print; class GCodePreviewData; @@ -71,56 +49,17 @@ namespace GUI { namespace I18N { namespace GUI { -class Tab; -class ConfigOptionsGroup; -// Map from an file_type name to full file wildcard name. -const std::map FILE_WILDCARDS{ - std::make_pair("known", "Known files (*.stl, *.obj, *.amf, *.xml, *.prusa)|*.stl;*.STL;*.obj;*.OBJ;*.amf;*.AMF;*.xml;*.XML;*.prusa;*.PRUSA"), - std::make_pair("stl", "STL files (*.stl)|*.stl;*.STL"), - std::make_pair("obj", "OBJ files (*.obj)|*.obj;*.OBJ"), - std::make_pair("amf", "AMF files (*.amf)|*.zip.amf;*.amf;*.AMF;*.xml;*.XML"), - std::make_pair("3mf", "3MF files (*.3mf)|*.3mf;*.3MF;"), - std::make_pair("prusa", "Prusa Control files (*.prusa)|*.prusa;*.PRUSA"), - std::make_pair("ini", "INI files *.ini|*.ini;*.INI"), - std::make_pair("gcode", "G-code files (*.gcode, *.gco, *.g, *.ngc)|*.gcode;*.GCODE;*.gco;*.GCO;*.g;*.G;*.ngc;*.NGC"), - std::make_pair("svg", "SVG files *.svg|*.svg;*.SVG") -}; - -const std::string MODEL_WILDCARD{ FILE_WILDCARDS.at("known") + std::string("|") + - FILE_WILDCARDS.at("stl") + std::string("|") + - FILE_WILDCARDS.at("obj") + std::string("|") + - FILE_WILDCARDS.at("amf") + std::string("|") + - FILE_WILDCARDS.at("3mf") + std::string("|") + - FILE_WILDCARDS.at("prusa") }; -struct PresetTab { - std::string name; - Tab* panel; - PrinterTechnology technology; -}; - - void disable_screensaver(); void enable_screensaver(); bool debugged(); void break_to_debugger(); -void set_show_print_info(bool show); -void set_show_manifold_warning_icon(bool show); -void set_objects_list_sizer(wxBoxSizer *objects_list_sizer); - AppConfig* get_app_config(); AppControllerPtr get_appctl(); void set_cli_appctl(); void set_gui_appctl(); -void open_model(wxWindow *parent, wxArrayString& input_files); - -wxWindow* get_right_panel(); - -Tab* get_tab(const std::string& name); -std::vector* get_preset_tabs(); - extern void add_menus(wxMenuBar *menu, int event_preferences_changed, int event_language_change); // Checks if configuration wizard needs to run, calls config_wizard if so. @@ -131,12 +70,8 @@ extern bool config_wizard_startup(bool app_config_exists); // The run_reason argument is actually ConfigWizard::RunReason, but int is used here because of Perl. extern void config_wizard(int run_reason); -TabIface* get_preset_tab_iface(char *name); - PreviewIface* create_preview_iface(wxNotebook* notebook, DynamicPrintConfig* config, Print* print, GCodePreviewData* gcode_preview_data); -// add it at the end of the tab panel. -// void add_created_tab(Tab* panel, int event_value_change, int event_presets_changed); // Change option value in config void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt_key, const boost::any& value, int opt_index = 0); @@ -149,8 +84,6 @@ void warning_catcher(wxWindow* parent, const wxString& message); // to deliver a progress status message. void set_print_callback_event(Print *print, int id); -void show_info_sizer(const bool show); - // Creates a wxCheckListBoxComboPopup inside the given wxComboCtrl, filled with the given text and items. // Items are all initialized to the given value. // Items must be separated by '|', for example "Item1|Item2|Item3", and so on. @@ -167,19 +100,9 @@ wxString from_u8(const std::string &str); // Return std::string in UTF8 from wxString std::string into_u8(const wxString &str); -void set_model_events_from_perl(Model &model, - int event_object_selection_changed, - int event_object_settings_changed, - int event_remove_object, - int event_update_scene); -void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFlexGridSizer* preset_sizer); - // Callback to trigger a configuration update timer on the Plater. static PerlCallback g_on_request_update_callback; -ConfigOptionsGroup* get_optgroup(size_t i); -std::vector >& get_optgroups(); - void add_export_option(wxFileDialog* dlg, const std::string& format); int get_export_option(wxFileDialog* dlg); @@ -191,9 +114,6 @@ void save_window_size(wxTopLevelWindow *window, const std::string &name); // Restore the above void restore_window_size(wxTopLevelWindow *window, const std::string &name); -// Update buttons view according to enable/disable -void enable_action_buttons(bool enable); - // Display an About dialog extern void about(); // Ask the destop to open the datadir using the default file explorer. diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 8fdef00cd3..1862bab8a5 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -1,4 +1,5 @@ #include "GUI_App.hpp" +#include "GUI_ObjectList.hpp" #include "GUI_ObjectManipulation.hpp" #include @@ -18,6 +19,7 @@ #include "AppConfig.hpp" #include "PresetBundle.hpp" #include "3DScene.hpp" +#include "Model.hpp" #include "../Utils/PresetUpdater.hpp" #include "ConfigWizard_private.hpp" @@ -92,6 +94,8 @@ bool GUI_App::OnInit() // wxImage::FindHandlerType(wxBITMAP_TYPE_PNG) || wxImage::AddHandler(new wxPNGHandler()); mainframe = new MainFrame(no_plater, false); + sidebar().obj_list()->init_objects(); // propagate model objects to object list + update_mode(); SetTopWindow(mainframe); // This makes CallAfter() work @@ -220,6 +224,8 @@ void GUI_App::recreate_GUI() auto topwindow = GetTopWindow(); mainframe = new MainFrame(no_plater,false); + sidebar().obj_list()->init_objects(); // propagate model objects to object list + update_mode(); if (topwindow) { SetTopWindow(mainframe); @@ -493,18 +499,18 @@ ConfigMenuIDs GUI_App::get_view_mode() // Update view mode according to selected menu void GUI_App::update_mode() { - wxWindowUpdateLocker noUpdates(/*g_right_panel->GetParent()*/mainframe); + wxWindowUpdateLocker noUpdates(mainframe->m_plater); ConfigMenuIDs mode = wxGetApp().get_view_mode(); -// g_object_list_sizer->Show(mode == ConfigMenuModeExpert); - show_info_sizer(mode == ConfigMenuModeExpert); -// show_buttons(mode == ConfigMenuModeExpert); -// show_object_name(mode == ConfigMenuModeSimple); - show_manipulation_sizer(mode == ConfigMenuModeSimple); + obj_list()->get_sizer()->Show(mode == ConfigMenuModeExpert); + sidebar().show_info_sizers(mode == ConfigMenuModeExpert); + sidebar().show_buttons(mode == ConfigMenuModeExpert); + obj_manipul()->show_object_name(mode == ConfigMenuModeSimple); + obj_list()->update_manipulation_sizer(mode == ConfigMenuModeSimple); - /*g_right_panel*/mainframe->m_plater->Layout(); - /*g_right_panel->GetParent()*/mainframe->Layout(); + sidebar().Layout(); + mainframe->m_plater->Layout(); } void GUI_App::add_config_menu(wxMenuBar *menu) @@ -658,25 +664,21 @@ ObjectManipulation* GUI_App::obj_manipul() return sidebar().obj_manipul(); } +ObjectList* GUI_App::obj_list() +{ + return sidebar().obj_list(); +} + +ModelObjectPtrs* GUI_App::model_objects() +{ + return &mainframe->m_plater->model().objects; +} + wxNotebook* GUI_App::tab_panel() const { return mainframe->m_tabpanel; } -// std::vector preset_tabs = { -// { "print", nullptr, ptFFF }, -// { "filament", nullptr, ptFFF }, -// { "sla_material", nullptr, ptSLA } -// }; -// -// Tab* GUI_App::get_tab(const std::string& name) -// { -// std::vector::iterator it = std::find_if(preset_tabs.begin(), preset_tabs.end(), -// [name](PresetTab& tab){ return name == tab.name; }); -// return it != preset_tabs.end() ? it->panel : nullptr; -// } - - // static method accepting a wxWindow object as first parameter // void warning_catcher{ // my($self, $message_dialog) = @_; diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 022fd0d371..e5ea77a38c 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -2,11 +2,8 @@ #define slic3r_GUI_App_hpp_ #include -// #include #include "PrintConfig.hpp" #include "MainFrame.hpp" -// #include "../../libslic3r/Utils.hpp" -// #include "GUI.hpp" #include #include @@ -24,9 +21,31 @@ namespace Slic3r { class AppConfig; class PresetBundle; class PresetUpdater; +class ModelObject; namespace GUI { +// Map from an file_type name to full file wildcard name. +const std::map FILE_WILDCARDS{ + std::make_pair("known", "Known files (*.stl, *.obj, *.amf, *.xml, *.prusa)|*.stl;*.STL;*.obj;*.OBJ;*.amf;*.AMF;*.xml;*.XML;*.prusa;*.PRUSA"), + std::make_pair("stl", "STL files (*.stl)|*.stl;*.STL"), + std::make_pair("obj", "OBJ files (*.obj)|*.obj;*.OBJ"), + std::make_pair("amf", "AMF files (*.amf)|*.zip.amf;*.amf;*.AMF;*.xml;*.XML"), + std::make_pair("3mf", "3MF files (*.3mf)|*.3mf;*.3MF;"), + std::make_pair("prusa", "Prusa Control files (*.prusa)|*.prusa;*.PRUSA"), + std::make_pair("ini", "INI files *.ini|*.ini;*.INI"), + std::make_pair("gcode", "G-code files (*.gcode, *.gco, *.g, *.ngc)|*.gcode;*.GCODE;*.gco;*.GCO;*.g;*.G;*.ngc;*.NGC"), + std::make_pair("svg", "SVG files *.svg|*.svg;*.SVG") +}; + +const std::string MODEL_WILDCARD{ FILE_WILDCARDS.at("known") + std::string("|") + + FILE_WILDCARDS.at("stl") + std::string("|") + + FILE_WILDCARDS.at("obj") + std::string("|") + + FILE_WILDCARDS.at("amf") + std::string("|") + + FILE_WILDCARDS.at("3mf") + std::string("|") + + FILE_WILDCARDS.at("prusa") }; + + enum ConfigMenuIDs { ConfigMenuWizard, ConfigMenuSnapshots, @@ -61,8 +80,6 @@ class GUI_App : public wxApp wxFont m_small_font; wxFont m_bold_font; - // #ys_FIXME -// std::vector g_tabs_list; wxLocale* m_wxLocale{ nullptr }; public: @@ -120,17 +137,12 @@ public: bool check_unsaved_changes(); bool checked_tab(Tab* tab); void delete_tab_from_list(Tab* tab); - // Tab* get_tab(const std::string& name); void load_current_presets(); - Sidebar& sidebar(); ObjectManipulation* obj_manipul(); -// ObjectList& get_obj_list(); - - // Functions for updating of the object manipulation values - void update_position_values(); - void update_position_values(const Vec3d& position); + ObjectList* obj_list(); + std::vector *model_objects(); AppConfig* app_config{ nullptr }; PresetBundle* preset_bundle{ nullptr }; diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index f44c5be8e8..e9fc6a3d00 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -1,25 +1,17 @@ #include "GUI_ObjectList.hpp" +#include "GUI_ObjectManipulation.hpp" #include "GUI_App.hpp" #include "OptionsGroup.hpp" #include "PresetBundle.hpp" #include "Tab.hpp" #include "wxExtensions.hpp" +#include "Model.hpp" +#include "LambdaObjectDialog.hpp" -// #include "Model.hpp" -// #include "LambdaObjectDialog.hpp" -// #include "../../libslic3r/Utils.hpp" -// -// #include -// #include #include -// #include "Geometry.hpp" #include "slic3r/Utils/FixModelByWin10.hpp" -// -// #include -// #include "3DScene.hpp" - namespace Slic3r { namespace GUI @@ -28,28 +20,41 @@ namespace GUI ObjectList::ObjectList(wxWindow* parent) : m_parent(parent) { -// wxBoxSizer* sizer; + // Fill CATEGORY_ICON + { + CATEGORY_ICON[L("Layers and Perimeters")] = wxBitmap(from_u8(var("layers.png")), wxBITMAP_TYPE_PNG); + CATEGORY_ICON[L("Infill")] = wxBitmap(from_u8(var("infill.png")), wxBITMAP_TYPE_PNG); + CATEGORY_ICON[L("Support material")] = wxBitmap(from_u8(var("building.png")), wxBITMAP_TYPE_PNG); + CATEGORY_ICON[L("Speed")] = wxBitmap(from_u8(var("time.png")), wxBITMAP_TYPE_PNG); + CATEGORY_ICON[L("Extruders")] = wxBitmap(from_u8(var("funnel.png")), wxBITMAP_TYPE_PNG); + CATEGORY_ICON[L("Extrusion Width")] = wxBitmap(from_u8(var("funnel.png")), wxBITMAP_TYPE_PNG); +// CATEGORY_ICON[L("Skirt and brim")] = wxBitmap(from_u8(var("box.png")), wxBITMAP_TYPE_PNG); +// CATEGORY_ICON[L("Speed > Acceleration")] = wxBitmap(from_u8(var("time.png")), wxBITMAP_TYPE_PNG); + CATEGORY_ICON[L("Advanced")] = wxBitmap(from_u8(var("wand.png")), wxBITMAP_TYPE_PNG); + } + + init_icons(); + // create control create_objects_ctrl(); // describe control behavior - m_objects_ctrl->Bind(wxEVT_DATAVIEW_SELECTION_CHANGED, [](wxEvent& event) { + m_objects_ctrl->Bind(wxEVT_DATAVIEW_SELECTION_CHANGED, [this](wxEvent& event) { object_ctrl_selection_changed(); #ifndef __WXMSW__ set_tooltip_for_item(get_mouse_position_in_control()); #endif //__WXMSW__ }); - m_objects_ctrl->Bind(wxEVT_DATAVIEW_ITEM_CONTEXT_MENU, [](wxDataViewEvent& event) { + m_objects_ctrl->Bind(wxEVT_DATAVIEW_ITEM_CONTEXT_MENU, [this](wxDataViewEvent& event) { object_ctrl_context_menu(); - // event.Skip(); }); - m_objects_ctrl->Bind(wxEVT_CHAR, [](wxKeyEvent& event) { object_ctrl_key_event(event); }); // doesn't work on OSX + m_objects_ctrl->Bind(wxEVT_CHAR, [this](wxKeyEvent& event) { object_ctrl_key_event(event); }); // doesn't work on OSX #ifdef __WXMSW__ // Extruder value changed - m_objects_ctrl->Bind(wxEVT_CHOICE, [](wxCommandEvent& event) { update_extruder_in_config(event.GetString()); }); + m_objects_ctrl->Bind(wxEVT_CHOICE, [this](wxCommandEvent& event) { update_extruder_in_config(event.GetString()); }); m_objects_ctrl->GetMainWindow()->Bind(wxEVT_MOTION, [this](wxMouseEvent& event) { set_tooltip_for_item(event.GetPosition()); @@ -57,12 +62,18 @@ ObjectList::ObjectList(wxWindow* parent) : }); #else // equivalent to wxEVT_CHOICE on __WXMSW__ - m_objects_ctrl->Bind(wxEVT_DATAVIEW_ITEM_VALUE_CHANGED, [](wxDataViewEvent& event) { object_ctrl_item_value_change(event); }); + m_objects_ctrl->Bind(wxEVT_DATAVIEW_ITEM_VALUE_CHANGED, [this](wxDataViewEvent& e) { object_ctrl_item_value_change(e); }); #endif //__WXMSW__ - m_objects_ctrl->Bind(wxEVT_DATAVIEW_ITEM_BEGIN_DRAG, [](wxDataViewEvent& e) {on_begin_drag(e); }); - m_objects_ctrl->Bind(wxEVT_DATAVIEW_ITEM_DROP_POSSIBLE, [](wxDataViewEvent& e) {on_drop_possible(e); }); - m_objects_ctrl->Bind(wxEVT_DATAVIEW_ITEM_DROP, [](wxDataViewEvent& e) {on_drop(e); }); + m_objects_ctrl->Bind(wxEVT_DATAVIEW_ITEM_BEGIN_DRAG, [this](wxDataViewEvent& e) {on_begin_drag(e); }); + m_objects_ctrl->Bind(wxEVT_DATAVIEW_ITEM_DROP_POSSIBLE, [this](wxDataViewEvent& e) {on_drop_possible(e); }); + m_objects_ctrl->Bind(wxEVT_DATAVIEW_ITEM_DROP, [this](wxDataViewEvent& e) {on_drop(e); }); +} + +ObjectList::~ObjectList() +{ + if (m_default_config) + delete m_default_config; } void ObjectList::create_objects_ctrl() @@ -97,12 +108,6 @@ void ObjectList::create_objects_ctrl() wxALIGN_CENTER_HORIZONTAL, wxDATAVIEW_COL_RESIZABLE); } -// ModelObjectPtrs& ObjectList::get_objects() -// { -// return wxGetApp().mainframe->m_plater->model().objects; -// } - - void ObjectList::set_tooltip_for_item(const wxPoint& pt) { wxDataViewItem item; @@ -112,39 +117,39 @@ void ObjectList::set_tooltip_for_item(const wxPoint& pt) if (col->GetTitle() == " ") m_objects_ctrl->GetMainWindow()->SetToolTip(_(L("Right button click the icon to change the object settings"))); -// else if (col->GetTitle() == _("Name") && -// m_objects_model->GetIcon(item).GetRefData() == m_icon_manifold_warning.GetRefData()) { -// int obj_idx = m_objects_model->GetIdByItem(item); -// auto& stats = (*m_objects)[obj_idx]->volumes[0]->mesh.stl.stats; -// int errors = stats.degenerate_facets + stats.edges_fixed + stats.facets_removed + -// stats.facets_added + stats.facets_reversed + stats.backwards_edges; -// -// wxString tooltip = wxString::Format(_(L("Auto-repaired (%d errors):\n")), errors); -// -// std::map error_msg; -// error_msg[L("degenerate facets")] = stats.degenerate_facets; -// error_msg[L("edges fixed")] = stats.edges_fixed; -// error_msg[L("facets removed")] = stats.facets_removed; -// error_msg[L("facets added")] = stats.facets_added; -// error_msg[L("facets reversed")] = stats.facets_reversed; -// error_msg[L("backwards edges")] = stats.backwards_edges; -// -// for (auto error : error_msg) -// { -// if (error.second > 0) -// tooltip += wxString::Format(_("\t%d %s\n"), error.second, error.first); -// } -// // OR -// // tooltip += wxString::Format(_(L("%d degenerate facets, %d edges fixed, %d facets removed, " -// // "%d facets added, %d facets reversed, %d backwards edges")), -// // stats.degenerate_facets, stats.edges_fixed, stats.facets_removed, -// // stats.facets_added, stats.facets_reversed, stats.backwards_edges); -// -// if (is_windows10()) -// tooltip += _(L("Right button click the icon to fix STL through Netfabb")); -// -// m_objects_ctrl->GetMainWindow()->SetToolTip(tooltip); -// } + else if (col->GetTitle() == _("Name") && + m_objects_model->GetIcon(item).GetRefData() == m_icon_manifold_warning.GetRefData()) { + int obj_idx = m_objects_model->GetIdByItem(item); + auto& stats = (*m_objects)[obj_idx]->volumes[0]->mesh.stl.stats; + int errors = stats.degenerate_facets + stats.edges_fixed + stats.facets_removed + + stats.facets_added + stats.facets_reversed + stats.backwards_edges; + + wxString tooltip = wxString::Format(_(L("Auto-repaired (%d errors):\n")), errors); + + std::map error_msg; + error_msg[L("degenerate facets")] = stats.degenerate_facets; + error_msg[L("edges fixed")] = stats.edges_fixed; + error_msg[L("facets removed")] = stats.facets_removed; + error_msg[L("facets added")] = stats.facets_added; + error_msg[L("facets reversed")] = stats.facets_reversed; + error_msg[L("backwards edges")] = stats.backwards_edges; + + for (auto error : error_msg) + { + if (error.second > 0) + tooltip += wxString::Format(_("\t%d %s\n"), error.second, error.first); + } +// OR +// tooltip += wxString::Format(_(L("%d degenerate facets, %d edges fixed, %d facets removed, " +// "%d facets added, %d facets reversed, %d backwards edges")), +// stats.degenerate_facets, stats.edges_fixed, stats.facets_removed, +// stats.facets_added, stats.facets_reversed, stats.backwards_edges); + + if (is_windows10()) + tooltip += _(L("Right button click the icon to fix STL through Netfabb")); + + m_objects_ctrl->GetMainWindow()->SetToolTip(tooltip); + } else m_objects_ctrl->GetMainWindow()->SetToolTip(""); // hide tooltip } @@ -182,7 +187,959 @@ void ObjectList::update_objects_list_extruder_column(int extruders_count) set_extruder_column_hidden(extruders_count <= 1); } +void ObjectList::set_extruder_column_hidden(bool hide) +{ + m_objects_ctrl->GetColumn(2)->SetHidden(hide); +} +void ObjectList::update_extruder_in_config(const wxString& selection) +{ + if (!m_config || selection.empty()) + return; + + int extruder = selection.size() > 1 ? 0 : atoi(selection.c_str()); + m_config->set_key_value("extruder", new ConfigOptionInt(extruder)); + +// #ys_FIXME_events + // call function to update the scene after extruder changing +} + +void ObjectList::init_icons(){ + m_icon_modifiermesh = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("lambda.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("plugin.png")), wxBITMAP_TYPE_PNG); + m_icon_solidmesh = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("object.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("package.png")), wxBITMAP_TYPE_PNG); + + // init icon for manifold warning + m_icon_manifold_warning = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("exclamation_mark_.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("error.png")), wxBITMAP_TYPE_PNG); + + // init bitmap for "Split to sub-objects" context menu + m_bmp_split = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("split.png")), wxBITMAP_TYPE_PNG); + + // init bitmap for "Add Settings" context menu + m_bmp_cog = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("cog.png")), wxBITMAP_TYPE_PNG); +} + + +void ObjectList::object_ctrl_selection_changed() +{ + if (m_prevent_list_events) return; + + part_selection_changed(); + +// #ys_FIXME_events +// call function to update object selection on Plater +// using obj_idx and vol_idx values + int obj_idx, vol_idx = -1; + obj_idx = m_selected_object_id; + + const wxDataViewItem item = m_objects_ctrl->GetSelection(); + if (!item || m_objects_model->GetParent(item) == wxDataViewItem(0)) + vol_idx = -1; + else { + vol_idx = m_objects_model->GetVolumeIdByItem(item); + if (vol_idx == -2) // is settings item + vol_idx = m_objects_model->GetVolumeIdByItem(m_objects_model->GetParent(item)); + } + +#ifdef __WXOSX__ + update_extruder_in_config(m_selected_extruder); +#endif //__WXOSX__ +} + +void ObjectList::object_ctrl_context_menu() +{ + wxDataViewItem item; + wxDataViewColumn* col; + const wxPoint pt = get_mouse_position_in_control(); + m_objects_ctrl->HitTest(pt, item, col); + if (!item) +#ifdef __WXOSX__ // #ys_FIXME temporary workaround for OSX + // after Yosemite OS X version, HitTest return undefined item + item = m_objects_ctrl->GetSelection(); + if (item) + show_context_menu(); + else + printf("undefined item\n"); + return; +#else + return; +#endif // __WXOSX__ + const wxString title = col->GetTitle(); + + if (title == " ") + show_context_menu(); + + else if (title == _("Name") && pt.x >15 && + m_objects_model->GetIcon(item).GetRefData() == m_icon_manifold_warning.GetRefData()) + { + if (is_windows10()) + /*fix_through_netfabb()*/;// #ys_FIXME + } +#ifndef __WXMSW__ + m_objects_ctrl->GetMainWindow()->SetToolTip(""); // hide tooltip +#endif //__WXMSW__ +} + +void ObjectList::show_context_menu() +{ + const auto item = m_objects_ctrl->GetSelection(); + if (item) + { + if (m_objects_model->IsSettingsItem(item)) + return; + const auto menu = m_objects_model->GetParent(item) == wxDataViewItem(0) ? + create_add_part_popupmenu() : + create_part_settings_popupmenu(); + wxGetApp().tab_panel()->GetPage(0)->PopupMenu(menu); + } +} + + +void ObjectList::object_ctrl_key_event(wxKeyEvent& event) +{ + if (event.GetKeyCode() == WXK_TAB) + m_objects_ctrl->Navigate(event.ShiftDown() ? wxNavigationKeyEvent::IsBackward : wxNavigationKeyEvent::IsForward); + else if (event.GetKeyCode() == WXK_DELETE +#ifdef __WXOSX__ + || event.GetKeyCode() == WXK_BACK +#endif //__WXOSX__ + ){ + printf("WXK_BACK\n"); + remove(); + } + else + event.Skip(); +} + +void ObjectList::object_ctrl_item_value_change(wxDataViewEvent& event) +{ + if (event.GetColumn() == 2) + { + wxVariant variant; + m_objects_model->GetValue(variant, event.GetItem(), 2); +#ifdef __WXOSX__ + m_selected_extruder = variant.GetString(); +#else // --> for Linux + update_extruder_in_config(variant.GetString()); +#endif //__WXOSX__ + } +} + +void ObjectList::on_begin_drag(wxDataViewEvent &event) +{ + wxDataViewItem item(event.GetItem()); + + // only allow drags for item, not containers + if (m_objects_model->GetParent(item) == wxDataViewItem(0) || m_objects_model->IsSettingsItem(item)) { + event.Veto(); + return; + } + + /* Under MSW or OSX, DnD moves an item to the place of another selected item + * But under GTK, DnD moves an item between another two items. + * And as a result - call EVT_CHANGE_SELECTION to unselect all items. + * To prevent such behavior use g_prevent_list_events + **/ + m_prevent_list_events = true;//it's needed for GTK + + wxTextDataObject *obj = new wxTextDataObject; + obj->SetText(wxString::Format("%d", m_objects_model->GetVolumeIdByItem(item))); + event.SetDataObject(obj); + event.SetDragFlags(/*wxDrag_AllowMove*/wxDrag_DefaultMove); // allows both copy and move; +} + +void ObjectList::on_drop_possible(wxDataViewEvent &event) +{ + wxDataViewItem item(event.GetItem()); + + // only allow drags for item or background, not containers + if (item.IsOk() && m_objects_model->GetParent(item) == wxDataViewItem(0) || + event.GetDataFormat() != wxDF_UNICODETEXT || m_objects_model->IsSettingsItem(item)) + event.Veto(); +} + +void ObjectList::on_drop(wxDataViewEvent &event) +{ + wxDataViewItem item(event.GetItem()); + + // only allow drops for item, not containers + if (item.IsOk() && m_objects_model->GetParent(item) == wxDataViewItem(0) || + event.GetDataFormat() != wxDF_UNICODETEXT || m_objects_model->IsSettingsItem(item)) { + event.Veto(); + return; + } + + wxTextDataObject obj; + obj.SetData(wxDF_UNICODETEXT, event.GetDataSize(), event.GetDataBuffer()); + + int from_volume_id = std::stoi(obj.GetText().ToStdString()); + int to_volume_id = m_objects_model->GetVolumeIdByItem(item); + +#ifdef __WXGTK__ + /* Under GTK, DnD moves an item between another two items. + * And event.GetItem() return item, which is under "insertion line" + * So, if we move item down we should to decrease the to_volume_id value + **/ + if (to_volume_id > from_volume_id) to_volume_id--; +#endif // __WXGTK__ + + m_objects_ctrl->Select(m_objects_model->ReorganizeChildren(from_volume_id, to_volume_id, + m_objects_model->GetParent(item))); + + auto& volumes = (*m_objects)[m_selected_object_id]->volumes; + auto delta = to_volume_id < from_volume_id ? -1 : 1; + int cnt = 0; + for (int id = from_volume_id; cnt < abs(from_volume_id - to_volume_id); id += delta, cnt++) + std::swap(volumes[id], volumes[id + delta]); + + m_parts_changed = true; + parts_changed(m_selected_object_id); + + m_prevent_list_events = false; +} + + +// Context Menu + +std::vector get_options(const bool is_part) +{ + PrintRegionConfig reg_config; + auto options = reg_config.keys(); + if (!is_part) { + PrintObjectConfig obj_config; + std::vector obj_options = obj_config.keys(); + options.insert(options.end(), obj_options.begin(), obj_options.end()); + } + return options; +} + +// category -> vector ( option ; label ) +typedef std::map< std::string, std::vector< std::pair > > settings_menu_hierarchy; +void get_options_menu(settings_menu_hierarchy& settings_menu, bool is_part) +{ + auto options = get_options(is_part); + + auto extruders_cnt = wxGetApp().preset_bundle->printers.get_selected_preset().printer_technology() == ptSLA ? 1 : + wxGetApp().preset_bundle->printers.get_edited_preset().config.option("nozzle_diameter")->values.size(); + + DynamicPrintConfig config; + for (auto& option : options) + { + auto const opt = config.def()->get(option); + auto category = opt->category; + if (category.empty() || + (category == "Extruders" && extruders_cnt == 1)) continue; + + std::pair option_label(option, opt->label); + std::vector< std::pair > new_category; + auto& cat_opt_label = settings_menu.find(category) == settings_menu.end() ? new_category : settings_menu.at(category); + cat_opt_label.push_back(option_label); + if (cat_opt_label.size() == 1) + settings_menu[category] = cat_opt_label; + } +} + +void ObjectList::get_settings_choice(wxMenu *menu, int id, bool is_part) +{ + const auto category_name = menu->GetLabel(id); + + wxArrayString names; + wxArrayInt selections; + + settings_menu_hierarchy settings_menu; + get_options_menu(settings_menu, is_part); + std::vector< std::pair > *settings_list = nullptr; + + auto opt_keys = m_config->keys(); + + for (auto& cat : settings_menu) + { + if (_(cat.first) == category_name) { + int sel = 0; + for (auto& pair : cat.second) { + names.Add(_(pair.second)); + if (find(opt_keys.begin(), opt_keys.end(), pair.first) != opt_keys.end()) + selections.Add(sel); + sel++; + } + settings_list = &cat.second; + break; + } + } + + if (!settings_list) + return; + + if (wxGetSelectedChoices(selections, _(L("Select showing settings")), category_name, names) == -1) + return; + + std::vector selected_options; + for (auto sel : selections) + selected_options.push_back((*settings_list)[sel].first); + + for (auto& setting : (*settings_list)) + { + auto& opt_key = setting.first; + if (find(opt_keys.begin(), opt_keys.end(), opt_key) != opt_keys.end() && + find(selected_options.begin(), selected_options.end(), opt_key) == selected_options.end()) + m_config->erase(opt_key); + + if (find(opt_keys.begin(), opt_keys.end(), opt_key) == opt_keys.end() && + find(selected_options.begin(), selected_options.end(), opt_key) != selected_options.end()) + m_config->set_key_value(opt_key, m_default_config->option(opt_key)->clone()); + } + + + // Add settings item for object + const auto item = m_objects_ctrl->GetSelection(); + if (item) { + const auto settings_item = m_objects_model->HasSettings(item); + m_objects_ctrl->Select(settings_item ? settings_item : + m_objects_model->AddSettingsChild(item)); +#ifndef __WXOSX__ + part_selection_changed(); +#endif //no __WXOSX__ + } + else + wxGetApp().obj_manipul()->update_settings_list(); +} + +void ObjectList::menu_item_add_generic(wxMenuItem* &menu, int id) { + auto sub_menu = new wxMenu; + + std::vector menu_items = { L("Box"), L("Cylinder"), L("Sphere"), L("Slab") }; + for (auto& item : menu_items) + sub_menu->Append(new wxMenuItem(sub_menu, ++id, _(item))); + +#ifndef __WXMSW__ + sub_menu->Bind(wxEVT_MENU, [sub_menu](wxEvent &event) { + load_lambda(sub_menu->GetLabel(event.GetId()).ToStdString()); + }); +#endif //no __WXMSW__ + + menu->SetSubMenu(sub_menu); +} + +wxMenuItem* ObjectList::menu_item_split(wxMenu* menu, int id) { + auto menu_item = new wxMenuItem(menu, id, _(L("Split to parts"))); + menu_item->SetBitmap(m_bmp_split); + return menu_item; +} + +wxMenuItem* ObjectList::menu_item_settings(wxMenu* menu, int id, const bool is_part) { + auto menu_item = new wxMenuItem(menu, id, _(L("Add settings"))); + menu_item->SetBitmap(m_bmp_cog); + + auto sub_menu = create_add_settings_popupmenu(is_part); + menu_item->SetSubMenu(sub_menu); + return menu_item; +} + +wxMenu* ObjectList::create_add_part_popupmenu() +{ + wxMenu *menu = new wxMenu; + std::vector menu_items = { L("Add part"), L("Add modifier"), L("Add generic") }; + + wxWindowID config_id_base = wxWindow::NewControlId(menu_items.size() + 4 + 2); + + int i = 0; + for (auto& item : menu_items) { + auto menu_item = new wxMenuItem(menu, config_id_base + i, _(item)); + menu_item->SetBitmap(i == 0 ? m_icon_solidmesh : m_icon_modifiermesh); + if (item == "Add generic") + menu_item_add_generic(menu_item, config_id_base + i); + menu->Append(menu_item); + i++; + } + + menu->AppendSeparator(); + auto menu_item = menu_item_split(menu, config_id_base + i + 4); + menu->Append(menu_item); + menu_item->Enable(is_splittable_object(false)); + + menu->AppendSeparator(); + // Append settings popupmenu + menu->Append(menu_item_settings(menu, config_id_base + i + 5, false)); + + menu->Bind(wxEVT_MENU, [config_id_base, menu, this](wxEvent &event){ + switch (event.GetId() - config_id_base) { + case 0: + load_subobject(); + break; + case 1: + load_subobject(true); + break; + case 2: + case 3: + case 4: + case 5: + case 6: +#ifdef __WXMSW__ + load_lambda(menu->GetLabel(event.GetId()).ToStdString()); +#endif // __WXMSW__ + break; + case 7: //3: + split(false); + break; + default: +#ifdef __WXMSW__ + get_settings_choice(menu, event.GetId(), false); +#endif // __WXMSW__ + break; + } + }); + + return menu; +} + +wxMenu* ObjectList::create_part_settings_popupmenu() +{ + wxMenu *menu = new wxMenu; + wxWindowID config_id_base = wxWindow::NewControlId(2); + + auto menu_item = menu_item_split(menu, config_id_base); + menu->Append(menu_item); + menu_item->Enable(is_splittable_object(true)); + + menu->AppendSeparator(); + // Append settings popupmenu + menu->Append(menu_item_settings(menu, config_id_base + 1, true)); + + menu->Bind(wxEVT_MENU, [config_id_base, menu, this](wxEvent &event){ + switch (event.GetId() - config_id_base) { + case 0: + split(true); + break; + default:{ + get_settings_choice(menu, event.GetId(), true); + break; } + } + }); + + return menu; +} + +wxMenu* ObjectList::create_add_settings_popupmenu(bool is_part) +{ + wxMenu *menu = new wxMenu; + + settings_menu_hierarchy settings_menu; + get_options_menu(settings_menu, is_part); + + for (auto cat : settings_menu) + { + auto menu_item = new wxMenuItem(menu, wxID_ANY, _(cat.first)); + menu_item->SetBitmap(CATEGORY_ICON.find(cat.first) == CATEGORY_ICON.end() ? + wxNullBitmap : CATEGORY_ICON.at(cat.first)); + menu->Append(menu_item); + } +#ifndef __WXMSW__ + menu->Bind(wxEVT_MENU, [menu, is_part](wxEvent &event) { + get_settings_choice(menu, event.GetId(), is_part); + }); +#endif //no __WXMSW__ + return menu; +} + + +// Load SubObjects (parts and modifiers) +void ObjectList::load_subobject(bool is_modifier /*= false*/, bool is_lambda/* = false*/) +{ + auto item = m_objects_ctrl->GetSelection(); + if (!item) + return; + int obj_idx = -1; + if (m_objects_model->GetParent(item) == wxDataViewItem(0)) + obj_idx = m_objects_model->GetIdByItem(item); + else + return; + + if (obj_idx < 0) return; + wxArrayString part_names; + if (is_lambda) + load_lambda((*m_objects)[obj_idx], part_names, is_modifier); + else + load_part((*m_objects)[obj_idx], part_names, is_modifier); + + parts_changed(obj_idx); + + for (int i = 0; i < part_names.size(); ++i) + m_objects_ctrl->Select(m_objects_model->AddChild(item, part_names.Item(i), + is_modifier ? m_icon_modifiermesh : m_icon_solidmesh)); +#ifndef __WXOSX__ //#ifdef __WXMSW__ // #ys_FIXME + object_ctrl_selection_changed(); +#endif //no __WXOSX__//__WXMSW__ +} + +void ObjectList::load_part( ModelObject* model_object, + wxArrayString& part_names, + const bool is_modifier) +{ + wxWindow* parent = wxGetApp().tab_panel()->GetPage(0); + + wxArrayString input_files; + wxGetApp().open_model(parent, input_files); + for (int i = 0; i < input_files.size(); ++i) { + std::string input_file = input_files.Item(i).ToStdString(); + + Model model; + try { + model = Model::read_from_file(input_file); + } + catch (std::exception &e) { + auto msg = _(L("Error! ")) + input_file + " : " + e.what() + "."; + show_error(parent, msg); + exit(1); + } + + for (auto object : model.objects) { + Vec3d delta = Vec3d::Zero(); + if (model_object->origin_translation != Vec3d::Zero()) + { + object->center_around_origin(); + delta = model_object->origin_translation - object->origin_translation; + } + for (auto volume : object->volumes) { + auto new_volume = model_object->add_volume(*volume); + new_volume->set_type(is_modifier ? ModelVolume::PARAMETER_MODIFIER : ModelVolume::MODEL_PART); + boost::filesystem::path(input_file).filename().string(); + new_volume->name = boost::filesystem::path(input_file).filename().string(); + + part_names.Add(new_volume->name); + + if (delta != Vec3d::Zero()) + { + new_volume->mesh.translate((float)delta(0), (float)delta(1), (float)delta(2)); + new_volume->get_convex_hull().translate((float)delta(0), (float)delta(1), (float)delta(2)); + } + + // set a default extruder value, since user can't add it manually + new_volume->config.set_key_value("extruder", new ConfigOptionInt(0)); + + m_parts_changed = true; + } + } + } +} + +void ObjectList::load_lambda( ModelObject* model_object, + wxArrayString& part_names, + const bool is_modifier) +{ + auto dlg = new LambdaObjectDialog(m_objects_ctrl->GetMainWindow()); + if (dlg->ShowModal() == wxID_CANCEL) { + return; + } + + std::string name = "lambda-"; + TriangleMesh mesh; + + auto params = dlg->ObjectParameters(); + switch (params.type) + { + case LambdaTypeBox:{ + mesh = make_cube(params.dim[0], params.dim[1], params.dim[2]); + name += "Box"; + break; } + case LambdaTypeCylinder:{ + mesh = make_cylinder(params.cyl_r, params.cyl_h); + name += "Cylinder"; + break; } + case LambdaTypeSphere:{ + mesh = make_sphere(params.sph_rho); + name += "Sphere"; + break; } + case LambdaTypeSlab:{ + const auto& size = model_object->bounding_box().size(); + mesh = make_cube(size(0)*1.5, size(1)*1.5, params.slab_h); + // box sets the base coordinate at 0, 0, move to center of plate and move it up to initial_z + mesh.translate(-size(0)*1.5 / 2.0, -size(1)*1.5 / 2.0, params.slab_z); + name += "Slab"; + break; } + default: + break; + } + mesh.repair(); + + auto new_volume = model_object->add_volume(mesh); + new_volume->set_type(is_modifier ? ModelVolume::PARAMETER_MODIFIER : ModelVolume::MODEL_PART); + + new_volume->name = name; + // set a default extruder value, since user can't add it manually + new_volume->config.set_key_value("extruder", new ConfigOptionInt(0)); + + part_names.Add(name); + + m_parts_changed = true; +} + +void ObjectList::load_lambda(const std::string& type_name) +{ + if (m_selected_object_id < 0) return; + + auto dlg = new LambdaObjectDialog(m_objects_ctrl->GetMainWindow(), type_name); + if (dlg->ShowModal() == wxID_CANCEL) + return; + + const std::string name = "lambda-" + type_name; + TriangleMesh mesh; + + const auto params = dlg->ObjectParameters(); + if (type_name == _("Box")) + mesh = make_cube(params.dim[0], params.dim[1], params.dim[2]); + else if (type_name == _("Cylinder")) + mesh = make_cylinder(params.cyl_r, params.cyl_h); + else if (type_name == _("Sphere")) + mesh = make_sphere(params.sph_rho); + else if (type_name == _("Slab")){ + const auto& size = (*m_objects)[m_selected_object_id]->bounding_box().size(); + mesh = make_cube(size(0)*1.5, size(1)*1.5, params.slab_h); + // box sets the base coordinate at 0, 0, move to center of plate and move it up to initial_z + mesh.translate(-size(0)*1.5 / 2.0, -size(1)*1.5 / 2.0, params.slab_z); + } + mesh.repair(); + + auto new_volume = (*m_objects)[m_selected_object_id]->add_volume(mesh); + new_volume->set_type(ModelVolume::PARAMETER_MODIFIER); + + new_volume->name = name; + // set a default extruder value, since user can't add it manually + new_volume->config.set_key_value("extruder", new ConfigOptionInt(0)); + + m_parts_changed = true; + parts_changed(m_selected_object_id); + + m_objects_ctrl->Select(m_objects_model->AddChild(m_objects_ctrl->GetSelection(), + name, m_icon_modifiermesh)); +#ifndef __WXOSX__ //#ifdef __WXMSW__ // #ys_FIXME + object_ctrl_selection_changed(); +#endif //no __WXOSX__ //__WXMSW__ +} + + +// Delete subobject + +void ObjectList::del_subobject() +{ + auto item = m_objects_ctrl->GetSelection(); + if (!item) return; + + const auto volume_id = m_objects_model->GetVolumeIdByItem(item); + if (volume_id == -1) + return; + + if (volume_id == -2) + del_settings_from_config(); + else if (!del_subobject_from_object(volume_id)) + return; + + m_objects_ctrl->Select(m_objects_model->Delete(item)); + part_selection_changed(); +} + +void ObjectList::del_settings_from_config() +{ + auto opt_keys = m_config->keys(); + if (opt_keys.size() == 1 && opt_keys[0] == "extruder") + return; + int extruder = -1; + if (m_config->has("extruder")) + extruder = m_config->option("extruder")->value; + + m_config->clear(); + + if (extruder >= 0) + m_config->set_key_value("extruder", new ConfigOptionInt(extruder)); +} + + +bool ObjectList::del_subobject_from_object(const int volume_id) +{ + const auto volume = (*m_objects)[m_selected_object_id]->volumes[volume_id]; + + // if user is deleting the last solid part, throw error + int solid_cnt = 0; + for (auto vol : (*m_objects)[m_selected_object_id]->volumes) + if (vol->is_model_part()) + ++solid_cnt; + if (volume->is_model_part() && solid_cnt == 1) { + Slic3r::GUI::show_error(nullptr, _(L("You can't delete the last solid part from this object."))); + return false; + } + + (*m_objects)[m_selected_object_id]->delete_volume(volume_id); + m_parts_changed = true; + + parts_changed(m_selected_object_id); + return true; +} + +void ObjectList::split(const bool split_part) +{ + const auto item = m_objects_ctrl->GetSelection(); + if (!item || m_selected_object_id < 0) + return; + ModelVolume* volume; + if (!get_volume_by_item(split_part, item, volume)) return; + DynamicPrintConfig& config = wxGetApp().preset_bundle->printers.get_edited_preset().config; + const auto nozzle_dmrs_cnt = config.option("nozzle_diameter")->values.size(); + if (volume->split(nozzle_dmrs_cnt) == 1) { + wxMessageBox(_(L("The selected object couldn't be split because it contains only one part."))); + return; + } + + auto model_object = (*m_objects)[m_selected_object_id]; + + if (split_part) { + auto parent = m_objects_model->GetParent(item); + m_objects_model->DeleteChildren(parent); + + for (auto id = 0; id < model_object->volumes.size(); id++) + m_objects_model->AddChild(parent, model_object->volumes[id]->name, + model_object->volumes[id]->is_modifier() ? m_icon_modifiermesh : m_icon_solidmesh, + model_object->volumes[id]->config.has("extruder") ? + model_object->volumes[id]->config.option("extruder")->value : 0, + false); + + m_objects_ctrl->Expand(parent); + } + else { + for (auto id = 0; id < model_object->volumes.size(); id++) + m_objects_model->AddChild(item, model_object->volumes[id]->name, + m_icon_solidmesh, + model_object->volumes[id]->config.has("extruder") ? + model_object->volumes[id]->config.option("extruder")->value : 0, + false); + m_objects_ctrl->Expand(item); + } + + m_parts_changed = true; + parts_changed(m_selected_object_id); +} + +bool ObjectList::get_volume_by_item(const bool split_part, const wxDataViewItem& item, ModelVolume*& volume) +{ + if (!item || m_selected_object_id < 0) + return false; + const auto volume_id = m_objects_model->GetVolumeIdByItem(item); + if (volume_id < 0) { + if (split_part) return false; + volume = (*m_objects)[m_selected_object_id]->volumes[0]; + } + else + volume = (*m_objects)[m_selected_object_id]->volumes[volume_id]; + if (volume) + return true; + return false; +} + +bool ObjectList::is_splittable_object(const bool split_part) +{ + const wxDataViewItem item = m_objects_ctrl->GetSelection(); + if (!item) return false; + + wxDataViewItemArray children; + if (!split_part && m_objects_model->GetChildren(item, children) > 0) + return false; + + ModelVolume* volume; + if (!get_volume_by_item(split_part, item, volume) || !volume) + return false; + + TriangleMeshPtrs meshptrs = volume->mesh.split(); + bool splittable = meshptrs.size() > 1; + for (TriangleMesh* m : meshptrs) + { + delete m; + } + return splittable; +} + +void ObjectList::parts_changed(int obj_idx) +{ +// #ys_FIXME_events +// call function to update scene after some changes in ObjectList +// auto event_str = wxString::Format("%d %d %d", obj_idx, +// is_parts_changed() ? 1 : 0, +// is_part_settings_changed() ? 1 : 0); +} + +void ObjectList::part_selection_changed() +{ + auto item = m_objects_ctrl->GetSelection(); + int obj_idx = -1; + ConfigOptionsGroup* og = wxGetApp().obj_manipul()->get_og();// get_optgroup(ogFrequentlyObjectSettings); + m_config = nullptr; + wxString object_name = wxEmptyString; + if (item) + { + const bool is_settings_item = m_objects_model->IsSettingsItem(item); + bool is_part = false; + wxString og_name = wxEmptyString; + if (m_objects_model->GetParent(item) == wxDataViewItem(0)) { + obj_idx = m_objects_model->GetIdByItem(item); + og_name = _(L("Object manipulation")); + m_config = &(*m_objects)[obj_idx]->config; + } + else { + auto parent = m_objects_model->GetParent(item); + // Take ID of the parent object to "inform" perl-side which object have to be selected on the scene + obj_idx = m_objects_model->GetIdByItem(parent); + if (is_settings_item) { + if (m_objects_model->GetParent(parent) == wxDataViewItem(0)) { + og_name = _(L("Object Settings to modify")); + m_config = &(*m_objects)[obj_idx]->config; + } + else { + og_name = _(L("Part Settings to modify")); + is_part = true; + auto main_parent = m_objects_model->GetParent(parent); + obj_idx = m_objects_model->GetIdByItem(main_parent); + const auto volume_id = m_objects_model->GetVolumeIdByItem(parent); + m_config = &(*m_objects)[obj_idx]->volumes[volume_id]->config; + } + } + else { + og_name = _(L("Part manipulation")); + is_part = true; + const auto volume_id = m_objects_model->GetVolumeIdByItem(item); + m_config = &(*m_objects)[obj_idx]->volumes[volume_id]->config; + } + } + + og->set_name(" " + og_name + " "); + object_name = m_objects_model->GetName(item); + if (m_default_config) delete m_default_config; + m_default_config = DynamicPrintConfig::new_from_defaults_keys(get_options(is_part)); + } + og->set_value("object_name", object_name); + + wxGetApp().obj_manipul()->update_settings_list(); + + m_selected_object_id = obj_idx; + + wxGetApp().obj_manipul()->update_values(); +} + +void ObjectList::update_manipulation_sizer(const bool is_simple_mode) +{ + auto item = m_objects_ctrl->GetSelection(); + if (!item || !is_simple_mode) + return; + + if (m_objects_model->IsSettingsItem(item)) { + m_objects_ctrl->Select(m_objects_model->GetParent(item)); + part_selection_changed(); + } +} + +void ObjectList::add_object_to_list(const std::string &name, ModelObject* model_object) +{ + wxString item_name = name; + auto item = m_objects_model->Add(item_name, model_object->instances.size()); + m_objects_ctrl->Select(item); + + // Add error icon if detected auto-repaire + auto stats = model_object->volumes[0]->mesh.stl.stats; + int errors = stats.degenerate_facets + stats.edges_fixed + stats.facets_removed + + stats.facets_added + stats.facets_reversed + stats.backwards_edges; + if (errors > 0) { + const PrusaDataViewBitmapText data(item_name, m_icon_manifold_warning); + wxVariant variant; + variant << data; + m_objects_model->SetValue(variant, item, 0); + } + + if (model_object->volumes.size() > 1) { + for (auto id = 0; id < model_object->volumes.size(); id++) + m_objects_model->AddChild(item, + model_object->volumes[id]->name, + m_icon_solidmesh, + model_object->volumes[id]->config.option("extruder")->value, + false); + m_objects_ctrl->Expand(item); + } + +#ifndef __WXOSX__ + object_ctrl_selection_changed(); +#endif //__WXMSW__ +} + +void ObjectList::delete_object_from_list() +{ + auto item = m_objects_ctrl->GetSelection(); + if (!item || m_objects_model->GetParent(item) != wxDataViewItem(0)) + return; + // m_objects_ctrl->Select(m_objects_model->Delete(item)); + m_objects_model->Delete(item); + + part_selection_changed(); +} + +void ObjectList::delete_all_objects_from_list() +{ + m_objects_model->DeleteAll(); + part_selection_changed(); +} + +void ObjectList::set_object_count(int idx, int count) +{ + m_objects_model->SetValue(wxString::Format("%d", count), idx, 1); + m_objects_ctrl->Refresh(); +} + +void ObjectList::unselect_objects() +{ + if (!m_objects_ctrl->GetSelection()) + return; + + m_prevent_list_events = true; + m_objects_ctrl->UnselectAll(); + part_selection_changed(); + m_prevent_list_events = false; +} + +void ObjectList::select_current_object(int idx) +{ + m_prevent_list_events = true; + m_objects_ctrl->UnselectAll(); + if (idx >= 0) + m_objects_ctrl->Select(m_objects_model->GetItemById(idx)); + part_selection_changed(); + m_prevent_list_events = false; +} + +void ObjectList::select_current_volume(int idx, int vol_idx) +{ + if (vol_idx < 0) { + select_current_object(idx); + return; + } + m_prevent_list_events = true; + m_objects_ctrl->UnselectAll(); + if (idx >= 0) + m_objects_ctrl->Select(m_objects_model->GetItemByVolumeId(idx, vol_idx)); + part_selection_changed(); + m_prevent_list_events = false; +} + +void ObjectList::remove() +{ + auto item = m_objects_ctrl->GetSelection(); + if (!item) + return; + + if (m_objects_model->GetParent(item) == wxDataViewItem(0)) { +// #ys_FIXME_events +// call function to remove object from model and to update scene + } + else + del_subobject(); +} + +void ObjectList::init_objects() +{ + m_objects = wxGetApp().model_objects(); +} } //namespace GUI } //namespace Slic3r \ No newline at end of file diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index 77530a590c..a2702228d3 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -3,23 +3,29 @@ #include #include +#include class wxBoxSizer; class wxDataViewCtrl; class wxDataViewColumn; +class wxDataViewEvent; +class wxDataViewItem; class PrusaObjectDataViewModel; namespace Slic3r { -namespace GUI { - class ConfigOptionsGroup; +class DynamicPrintConfig; +class ModelObject; +class ModelVolume; + +namespace GUI { class ObjectList { - wxBoxSizer *m_sizer {nullptr}; - wxDataViewCtrl *m_objects_ctrl{ nullptr }; - PrusaObjectDataViewModel *m_objects_model{ nullptr }; - wxWindow *m_parent{ nullptr }; + wxBoxSizer *m_sizer {nullptr}; + wxWindow *m_parent{ nullptr }; + + DynamicPrintConfig *m_default_config {nullptr}; wxBitmap m_icon_modifiermesh; wxBitmap m_icon_solidmesh; @@ -28,20 +34,99 @@ class ObjectList wxBitmap m_bmp_split; int m_selected_object_id = -1; + bool m_prevent_list_events = false; // We use this flag to avoid circular event handling Select() + // happens to fire a wxEVT_LIST_ITEM_SELECTED on OSX, whose event handler + // calls this method again and again and again +#ifdef __WXOSX__ + wxString m_selected_extruder = ""; +#endif //__WXOSX__ + bool m_parts_changed = false; + bool m_part_settings_changed = false; public: ObjectList(wxWindow* parent); - ~ObjectList() {} + ~ObjectList(); + + + std::map CATEGORY_ICON; + + wxDataViewCtrl *m_objects_ctrl{ nullptr }; + PrusaObjectDataViewModel *m_objects_model{ nullptr }; + DynamicPrintConfig *m_config {nullptr}; + + std::vector *m_objects{ nullptr }; + void create_objects_ctrl(); wxDataViewColumn* create_objects_list_extruder_column(int extruders_count); void update_objects_list_extruder_column(int extruders_count); + // show/hide "Extruder" column for Objects List + void set_extruder_column_hidden(bool hide); + // update extruder in current config + void update_extruder_in_config(const wxString& selection); + + void init_icons(); void set_tooltip_for_item(const wxPoint& pt); + void object_ctrl_selection_changed(); + void object_ctrl_context_menu(); + void show_context_menu(); + void object_ctrl_key_event(wxKeyEvent& event); + void object_ctrl_item_value_change(wxDataViewEvent& event); + + void on_begin_drag(wxDataViewEvent &event); + void on_drop_possible(wxDataViewEvent &event); + void on_drop(wxDataViewEvent &event); + + void get_settings_choice(wxMenu *menu, int id, bool is_part); + void menu_item_add_generic(wxMenuItem* &menu, int id); + wxMenuItem* menu_item_split(wxMenu* menu, int id); + wxMenuItem* menu_item_settings(wxMenu* menu, int id, const bool is_part); + wxMenu* create_add_part_popupmenu(); + wxMenu* create_part_settings_popupmenu(); + wxMenu* create_add_settings_popupmenu(bool is_part); + + void load_subobject(bool is_modifier = false, bool is_lambda = false); + void load_part(ModelObject* model_object, wxArrayString& part_names, const bool is_modifier); + void load_lambda(ModelObject* model_object, wxArrayString& part_names, const bool is_modifier); + void load_lambda(const std::string& type_name); + void del_subobject(); + void del_settings_from_config(); + bool del_subobject_from_object(const int volume_id); + void split(const bool split_part); + bool get_volume_by_item(const bool split_part, const wxDataViewItem& item, ModelVolume*& volume); + bool is_splittable_object(const bool split_part); + wxPoint get_mouse_position_in_control(); wxBoxSizer* get_sizer(){return m_sizer;} - int get_sel_obj_id() { return m_selected_object_id; } + int get_sel_obj_id() const { return m_selected_object_id; } + bool is_parts_changed() const { return m_parts_changed; } + bool is_part_settings_changed() const{ return m_part_settings_changed; } + + void parts_changed(int obj_idx); + void part_selection_changed(); + + void update_manipulation_sizer(const bool is_simple_mode); + + // Add object to the list + void add_object_to_list(const std::string &name, ModelObject* model_object); + // Delete object from the list + void delete_object_from_list(); + // Delete all objects from the list + void delete_all_objects_from_list(); + // Set count of object on c++ side + void set_object_count(int idx, int count); + // Unselect all objects in the list on c++ side + void unselect_objects(); + // Select current object in the list on c++ side + void select_current_object(int idx); + // Select current volume in the list on c++ side + void select_current_volume(int idx, int vol_idx); + // Remove objects/sub-object from the list + void remove(); + + void init_objects(); }; diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index 86e657d8e3..2858cb1068 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -1,7 +1,9 @@ #include "GUI_ObjectManipulation.hpp" +#include "GUI_ObjectList.hpp" #include "OptionsGroup.hpp" #include "wxExtensions.hpp" +#include "PresetBundle.hpp" #include "Model.hpp" #include "Geometry.hpp" @@ -36,7 +38,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent): std::vector axes{ "x", "y", "z" }; for (auto axis : axes) { std::string key = "scale_" + axis; - get_optgroup(ogFrequentlyObjectSettings)->set_side_text(key, selection); + m_og->set_side_text(key, selection); } m_is_percent_scale = selection == _("%"); @@ -80,7 +82,9 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent): auto btn = new PrusaLockButton(parent, wxID_ANY); btn->Bind(wxEVT_BUTTON, [btn](wxCommandEvent &event){ event.Skip(); - wxTheApp->CallAfter([btn]() { set_uniform_scaling(btn->IsLocked()); }); + wxTheApp->CallAfter([btn]() { + wxGetApp().obj_manipul()->set_uniform_scaling(btn->IsLocked()); + }); }); return btn; }; @@ -136,8 +140,8 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent): def.default_value = new ConfigOptionBool{ false }; m_og->append_single_option_line(Option(def, "place_on_bed")); - m_extra_settings_sizer = new wxBoxSizer(wxVERTICAL); - m_og->sizer->Add(m_extra_settings_sizer, 1, wxEXPAND | wxLEFT, 5); + m_settings_list_sizer = new wxBoxSizer(wxVERTICAL); + m_og->sizer->Add(m_settings_list_sizer, 1, wxEXPAND | wxLEFT, 5); m_og->disable(); } @@ -147,6 +151,117 @@ int ObjectManipulation::ol_selection() return wxGetApp().sidebar().get_ol_selection(); } +void ObjectManipulation::update_settings_list() +{ +#ifdef __WXGTK__ + auto parent = m_og->get_parent(); +#else + auto parent = m_og->parent(); +#endif /* __WXGTK__ */ + +// There is a bug related to Ubuntu overlay scrollbars, see https://github.com/prusa3d/Slic3r/issues/898 and https://github.com/prusa3d/Slic3r/issues/952. +// The issue apparently manifests when Show()ing a window with overlay scrollbars while the UI is frozen. For this reason, +// we will Thaw the UI prematurely on Linux. This means destroing the no_updates object prematurely. +#ifdef __linux__ + std::unique_ptr no_updates(new wxWindowUpdateLocker(parent)); +#else + wxWindowUpdateLocker noUpdates(parent); +#endif + + m_settings_list_sizer->Clear(true); + bool show_manipulations = true; + + auto objects_ctrl = wxGetApp().obj_list()->m_objects_ctrl; + auto objects_model = wxGetApp().obj_list()->m_objects_model; + auto config = wxGetApp().obj_list()->m_config; + + const auto item = objects_ctrl->GetSelection(); + if (config && objects_model->IsSettingsItem(item)) + { + auto extra_column = [config](wxWindow* parent, const Line& line) + { + auto opt_key = (line.get_options())[0].opt_id; //we assume that we have one option per line + + auto btn = new wxBitmapButton(parent, wxID_ANY, wxBitmap(from_u8(var("colorchange_delete_on.png")), wxBITMAP_TYPE_PNG), + wxDefaultPosition, wxDefaultSize, wxBORDER_NONE); +#ifdef __WXMSW__ + btn->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); +#endif // __WXMSW__ + btn->Bind(wxEVT_BUTTON, [opt_key, config](wxEvent &event){ + config->erase(opt_key); + wxTheApp->CallAfter([]() { wxGetApp().obj_manipul()->update_settings_list(); }); + }); + return btn; + }; + + std::map> cat_options; + auto opt_keys = config->keys(); + m_og_settings.resize(0); + std::vector categories; + if (!(opt_keys.size() == 1 && opt_keys[0] == "extruder"))// return; + { + auto extruders_cnt = wxGetApp().preset_bundle->printers.get_selected_preset().printer_technology() == ptSLA ? 1 : + wxGetApp().preset_bundle->printers.get_edited_preset().config.option("nozzle_diameter")->values.size(); + + for (auto& opt_key : opt_keys) { + auto category = config->def()->get(opt_key)->category; + if (category.empty() || + (category == "Extruders" && extruders_cnt == 1)) continue; + + std::vector< std::string > new_category; + + auto& cat_opt = cat_options.find(category) == cat_options.end() ? new_category : cat_options.at(category); + cat_opt.push_back(opt_key); + if (cat_opt.size() == 1) + cat_options[category] = cat_opt; + } + + for (auto& cat : cat_options) { + if (cat.second.size() == 1 && cat.second[0] == "extruder") + continue; + + auto optgroup = std::make_shared(parent, cat.first, config, false, ogDEFAULT, extra_column); + optgroup->label_width = 150; + optgroup->sidetext_width = 70; + + for (auto& opt : cat.second) + { + if (opt == "extruder") + continue; + Option option = optgroup->get_option(opt); + option.opt.width = 70; + optgroup->append_single_option_line(option); + } + optgroup->reload_config(); + m_settings_list_sizer->Add(optgroup->sizer, 0, wxEXPAND | wxALL, 0); + m_og_settings.push_back(optgroup); + + categories.push_back(cat.first); + } + } + + if (m_og_settings.empty()) { + objects_ctrl->Select(objects_model->Delete(item)); + wxGetApp().obj_list()->part_selection_changed(); + } + else { + if (!categories.empty()) + objects_model->UpdateSettingsDigest(item, categories); + show_manipulations = false; + } + } + + show_manipulation_og(show_manipulations); + wxGetApp().sidebar().show_info_sizers(show_manipulations && item && objects_model->GetParent(item) == wxDataViewItem(0)); + +#ifdef __linux__ + no_updates.reset(nullptr); +#endif + + parent->Layout(); + /*wxGetApp().sidebar().*/parent->GetParent()->Layout(); +} + void ObjectManipulation::update_values() { int selection = ol_selection(); @@ -298,7 +413,21 @@ void ObjectManipulation::update_rotation_value(const Vec3d& rotation) } #endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM +void ObjectManipulation::show_object_name(bool show) +{ + wxGridSizer* grid_sizer = m_og->get_grid_sizer(); + grid_sizer->Show(static_cast(0), show); + grid_sizer->Show(static_cast(1), show); +} +void ObjectManipulation::show_manipulation_og(const bool show) +{ + wxGridSizer* grid_sizer = m_og->get_grid_sizer(); + if (show == grid_sizer->IsShown(2)) + return; + for (size_t id = 2; id < 12; id++) + grid_sizer->Show(id, show); +} } //namespace GUI } //namespace Slic3r \ No newline at end of file diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.hpp b/src/slic3r/GUI/GUI_ObjectManipulation.hpp index feeaeb3abc..19683362f6 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.hpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.hpp @@ -22,7 +22,8 @@ public: OG_Settings(wxWindow* parent, const bool staticbox); ~OG_Settings() {} - wxSizer* get_sizer(); + wxSizer* get_sizer(); + ConfigOptionsGroup* get_og() { return m_og.get(); } }; @@ -30,13 +31,18 @@ class ObjectManipulation : public OG_Settings { bool m_is_percent_scale = false; // true -> percentage scale unit // false -> uniform scale unit - wxBoxSizer* m_extra_settings_sizer{ nullptr }; // sizer for extra Object/Part's settings + bool m_is_uniform_scale = false; // It indicates if scale is uniform + // sizer for extra Object/Part's settings + wxBoxSizer* m_settings_list_sizer{ nullptr }; + // option groups for settings + std::vector > m_og_settings; public: ObjectManipulation(wxWindow* parent); ~ObjectManipulation() {} int ol_selection(); + void update_settings_list(); void update_values(); // update position values displacements or "gizmos" @@ -57,6 +63,10 @@ public: void update_rotation_value(const Vec3d& rotation); #endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM + void set_uniform_scaling(const bool uniform_scale) { m_is_uniform_scale = uniform_scale; } + + void show_object_name(bool show); + void show_manipulation_og(const bool show); }; }} diff --git a/src/slic3r/GUI/GUI_ObjectParts.cpp b/src/slic3r/GUI/GUI_ObjectParts.cpp deleted file mode 100644 index f578f64660..0000000000 --- a/src/slic3r/GUI/GUI_ObjectParts.cpp +++ /dev/null @@ -1,1274 +0,0 @@ -#include "GUI.hpp" -#include "OptionsGroup.hpp" -#include "PresetBundle.hpp" -#include "GUI_ObjectParts.hpp" -#include "Model.hpp" -#include "wxExtensions.hpp" -#include "LambdaObjectDialog.hpp" -#include "../../libslic3r/Utils.hpp" - -#include -#include -#include -#include "Geometry.hpp" -#include "slic3r/Utils/FixModelByWin10.hpp" - -#include -#include "3DScene.hpp" -#include "GUI_App.hpp" - -namespace Slic3r -{ -namespace GUI -{ -wxDataViewCtrl *m_objects_ctrl = nullptr; -PrusaObjectDataViewModel *m_objects_model = nullptr; -PrusaDoubleSlider *m_slider = nullptr; -wxGLCanvas *m_preview_canvas = nullptr; - -wxBitmap m_icon_modifiermesh; -wxBitmap m_icon_solidmesh; -wxBitmap m_icon_manifold_warning; -wxBitmap m_bmp_cog; -wxBitmap m_bmp_split; - -int m_selected_object_id = -1; - -bool g_prevent_list_events = false; // We use this flag to avoid circular event handling Select() - // happens to fire a wxEVT_LIST_ITEM_SELECTED on OSX, whose event handler - // calls this method again and again and again -// bool g_is_percent_scale = false; // It indicates if scale unit is percentage -bool g_is_uniform_scale = false; // It indicates if scale is uniform -ModelObjectPtrs* m_objects; -std::shared_ptr m_config; -std::shared_ptr m_default_config; -wxBoxSizer* m_option_sizer = nullptr; - -// option groups for settings -std::vector > m_og_settings; - -int m_event_object_selection_changed = 0; -int m_event_object_settings_changed = 0; -int m_event_remove_object = 0; -int m_event_update_scene = 0; - -bool m_parts_changed = false; -bool m_part_settings_changed = false; - -#ifdef __WXOSX__ - wxString g_selected_extruder = ""; -#endif //__WXOSX__ - -inline t_category_icon& get_category_icon() { - static t_category_icon CATEGORY_ICON; - if (CATEGORY_ICON.empty()){ - CATEGORY_ICON[L("Layers and Perimeters")] = wxBitmap(from_u8(Slic3r::var("layers.png")), wxBITMAP_TYPE_PNG); - CATEGORY_ICON[L("Infill")] = wxBitmap(from_u8(Slic3r::var("infill.png")), wxBITMAP_TYPE_PNG); - CATEGORY_ICON[L("Support material")] = wxBitmap(from_u8(Slic3r::var("building.png")), wxBITMAP_TYPE_PNG); - CATEGORY_ICON[L("Speed")] = wxBitmap(from_u8(Slic3r::var("time.png")), wxBITMAP_TYPE_PNG); - CATEGORY_ICON[L("Extruders")] = wxBitmap(from_u8(Slic3r::var("funnel.png")), wxBITMAP_TYPE_PNG); - CATEGORY_ICON[L("Extrusion Width")] = wxBitmap(from_u8(Slic3r::var("funnel.png")), wxBITMAP_TYPE_PNG); -// CATEGORY_ICON[L("Skirt and brim")] = wxBitmap(from_u8(Slic3r::var("box.png")), wxBITMAP_TYPE_PNG); -// CATEGORY_ICON[L("Speed > Acceleration")] = wxBitmap(from_u8(Slic3r::var("time.png")), wxBITMAP_TYPE_PNG); - CATEGORY_ICON[L("Advanced")] = wxBitmap(from_u8(Slic3r::var("wand.png")), wxBITMAP_TYPE_PNG); - } - return CATEGORY_ICON; -} - -std::vector get_options(const bool is_part) -{ - PrintRegionConfig reg_config; - auto options = reg_config.keys(); - if (!is_part) { - PrintObjectConfig obj_config; - std::vector obj_options = obj_config.keys(); - options.insert(options.end(), obj_options.begin(), obj_options.end()); - } - return options; -} - -// category -> vector ( option ; label ) -typedef std::map< std::string, std::vector< std::pair > > settings_menu_hierarchy; -void get_options_menu(settings_menu_hierarchy& settings_menu, bool is_part) -{ - auto options = get_options(is_part); - - auto extruders_cnt = wxGetApp().preset_bundle->printers.get_selected_preset().printer_technology() == ptSLA ? 1 : - wxGetApp().preset_bundle->printers.get_edited_preset().config.option("nozzle_diameter")->values.size(); - - DynamicPrintConfig config; - for (auto& option : options) - { - auto const opt = config.def()->get(option); - auto category = opt->category; - if (category.empty() || - (category == "Extruders" && extruders_cnt == 1)) continue; - - std::pair option_label(option, opt->label); - std::vector< std::pair > new_category; - auto& cat_opt_label = settings_menu.find(category) == settings_menu.end() ? new_category : settings_menu.at(category); - cat_opt_label.push_back(option_label); - if (cat_opt_label.size() == 1) - settings_menu[category] = cat_opt_label; - } -} - -void set_event_object_selection_changed(const int& event){ - m_event_object_selection_changed = event; -} -void set_event_object_settings_changed(const int& event){ - m_event_object_settings_changed = event; -} -void set_event_remove_object(const int& event){ - m_event_remove_object = event; -} -void set_event_update_scene(const int& event){ - m_event_update_scene = event; -} - -void set_objects_from_model(Model &model) { - m_objects = &(model.objects); -} - -void init_mesh_icons(){ - m_icon_modifiermesh = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("lambda.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("plugin.png")), wxBITMAP_TYPE_PNG); - m_icon_solidmesh = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("object.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("package.png")), wxBITMAP_TYPE_PNG); - - // init icon for manifold warning - m_icon_manifold_warning = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("exclamation_mark_.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("error.png")), wxBITMAP_TYPE_PNG); - - // init bitmap for "Split to sub-objects" context menu - m_bmp_split = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("split.png")), wxBITMAP_TYPE_PNG); - - // init bitmap for "Add Settings" context menu - m_bmp_cog = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("cog.png")), wxBITMAP_TYPE_PNG); -} - -bool is_parts_changed(){return m_parts_changed;} -bool is_part_settings_changed(){ return m_part_settings_changed; } - -void delete_object_from_list() -{ - auto item = m_objects_ctrl->GetSelection(); - if (!item || m_objects_model->GetParent(item) != wxDataViewItem(0)) - return; -// m_objects_ctrl->Select(m_objects_model->Delete(item)); - m_objects_model->Delete(item); - - part_selection_changed(); -} - -void delete_all_objects_from_list() -{ - m_objects_model->DeleteAll(); - part_selection_changed(); -} - -void set_object_count(int idx, int count) -{ - m_objects_model->SetValue(wxString::Format("%d", count), idx, 1); - m_objects_ctrl->Refresh(); -} - -void unselect_objects() -{ - if (!m_objects_ctrl->GetSelection()) - return; - - g_prevent_list_events = true; - m_objects_ctrl->UnselectAll(); - part_selection_changed(); - g_prevent_list_events = false; -} - -void select_current_object(int idx) -{ - g_prevent_list_events = true; - m_objects_ctrl->UnselectAll(); - if (idx>=0) - m_objects_ctrl->Select(m_objects_model->GetItemById(idx)); - part_selection_changed(); - g_prevent_list_events = false; -} - -void select_current_volume(int idx, int vol_idx) -{ - if (vol_idx < 0) { - select_current_object(idx); - return; - } - g_prevent_list_events = true; - m_objects_ctrl->UnselectAll(); - if (idx >= 0) - m_objects_ctrl->Select(m_objects_model->GetItemByVolumeId(idx, vol_idx)); - part_selection_changed(); - g_prevent_list_events = false; -} - -void remove() -{ - auto item = m_objects_ctrl->GetSelection(); - if (!item) - return; - - if (m_objects_model->GetParent(item) == wxDataViewItem(0)) { - if (m_event_remove_object > 0) { - wxCommandEvent event(m_event_remove_object); -// get_main_frame()->ProcessWindowEvent(event); // #ys_FIXME - } - } - else - on_btn_del(); -} - -void object_ctrl_selection_changed() -{ - if (g_prevent_list_events) return; - - part_selection_changed(); - - if (m_event_object_selection_changed > 0) { - wxCommandEvent event(m_event_object_selection_changed); - event.SetId(m_selected_object_id); // set $obj_idx - const wxDataViewItem item = m_objects_ctrl->GetSelection(); - if (!item || m_objects_model->GetParent(item) == wxDataViewItem(0)) - event.SetInt(-1); // set $vol_idx - else { - const int vol_idx = m_objects_model->GetVolumeIdByItem(item); - if (vol_idx == -2) // is settings item - event.SetInt(m_objects_model->GetVolumeIdByItem(m_objects_model->GetParent(item))); // set $vol_idx - else - event.SetInt(vol_idx); - } -// get_main_frame()->ProcessWindowEvent(event); // #ys_FIXME - } - -#ifdef __WXOSX__ - update_extruder_in_config(g_selected_extruder); -#endif //__WXOSX__ -} - -void object_ctrl_context_menu() -{ - wxDataViewItem item; - wxDataViewColumn* col; - const wxPoint pt;//!!! = get_mouse_position_in_control(); - m_objects_ctrl->HitTest(pt, item, col); - if (!item) -#ifdef __WXOSX__ // #ys_FIXME temporary workaround for OSX - // after Yosemite OS X version, HitTest return undefined item - item = m_objects_ctrl->GetSelection(); - if (item) - show_context_menu(); - else - printf("undefined item\n"); - return; -#else - return; -#endif // __WXOSX__ - const wxString title = col->GetTitle(); - - if (title == " ") - show_context_menu(); -// #ys_FIXME -// else if (title == _("Name") && pt.x >15 && -// m_objects_model->GetIcon(item).GetRefData() == m_icon_manifold_warning.GetRefData()) -// { -// if (is_windows10()) -// fix_through_netfabb(); -// } -#ifndef __WXMSW__ - m_objects_ctrl->GetMainWindow()->SetToolTip(""); // hide tooltip -#endif //__WXMSW__ -} - -void object_ctrl_key_event(wxKeyEvent& event) -{ - if (event.GetKeyCode() == WXK_TAB) - m_objects_ctrl->Navigate(event.ShiftDown() ? wxNavigationKeyEvent::IsBackward : wxNavigationKeyEvent::IsForward); - else if (event.GetKeyCode() == WXK_DELETE -#ifdef __WXOSX__ - || event.GetKeyCode() == WXK_BACK -#endif //__WXOSX__ - ){ - printf("WXK_BACK\n"); - remove(); - } - else - event.Skip(); -} - -void object_ctrl_item_value_change(wxDataViewEvent& event) -{ - if (event.GetColumn() == 2) - { - wxVariant variant; - m_objects_model->GetValue(variant, event.GetItem(), 2); -#ifdef __WXOSX__ - g_selected_extruder = variant.GetString(); -#else // --> for Linux - update_extruder_in_config(variant.GetString()); -#endif //__WXOSX__ - } -} - -void show_manipulation_og(const bool show) -{ - wxGridSizer* grid_sizer = get_optgroup(ogFrequentlyObjectSettings)->get_grid_sizer(); - if (show == grid_sizer->IsShown(2)) - return; - for (size_t id = 2; id < 12; id++) - grid_sizer->Show(id, show); -} - -//update_optgroup -void update_settings_list() -{ -#ifdef __WXGTK__ - auto parent = get_optgroup(ogFrequentlyObjectSettings)->get_parent(); -#else - auto parent = get_optgroup(ogFrequentlyObjectSettings)->parent(); -#endif /* __WXGTK__ */ - -// There is a bug related to Ubuntu overlay scrollbars, see https://github.com/prusa3d/Slic3r/issues/898 and https://github.com/prusa3d/Slic3r/issues/952. -// The issue apparently manifests when Show()ing a window with overlay scrollbars while the UI is frozen. For this reason, -// we will Thaw the UI prematurely on Linux. This means destroing the no_updates object prematurely. -#ifdef __linux__ - std::unique_ptr no_updates(new wxWindowUpdateLocker(parent)); -#else - wxWindowUpdateLocker noUpdates(parent); -#endif - - m_option_sizer->Clear(true); - - bool show_manipulations = true; - const auto item = m_objects_ctrl->GetSelection(); - if (m_config && m_objects_model->IsSettingsItem(item)) - { - auto extra_column = [](wxWindow* parent, const Line& line) - { - auto opt_key = (line.get_options())[0].opt_id; //we assume that we have one option per line - - auto btn = new wxBitmapButton(parent, wxID_ANY, wxBitmap(from_u8(var("colorchange_delete_on.png")), wxBITMAP_TYPE_PNG), - wxDefaultPosition, wxDefaultSize, wxBORDER_NONE); -#ifdef __WXMSW__ - btn->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); -#endif // __WXMSW__ - btn->Bind(wxEVT_BUTTON, [opt_key](wxEvent &event){ - (*m_config)->erase(opt_key); - wxTheApp->CallAfter([]() { update_settings_list(); }); - }); - return btn; - }; - - std::map> cat_options; - auto opt_keys = (*m_config)->keys(); - m_og_settings.resize(0); - std::vector categories; - if (!(opt_keys.size() == 1 && opt_keys[0] == "extruder"))// return; - { - auto extruders_cnt = wxGetApp().preset_bundle->printers.get_selected_preset().printer_technology() == ptSLA ? 1 : - wxGetApp().preset_bundle->printers.get_edited_preset().config.option("nozzle_diameter")->values.size(); - - for (auto& opt_key : opt_keys) { - auto category = (*m_config)->def()->get(opt_key)->category; - if (category.empty() || - (category == "Extruders" && extruders_cnt == 1)) continue; - - std::vector< std::string > new_category; - - auto& cat_opt = cat_options.find(category) == cat_options.end() ? new_category : cat_options.at(category); - cat_opt.push_back(opt_key); - if (cat_opt.size() == 1) - cat_options[category] = cat_opt; - } - - for (auto& cat : cat_options) { - if (cat.second.size() == 1 && cat.second[0] == "extruder") - continue; - - auto optgroup = std::make_shared(parent, cat.first, *m_config, false, ogDEFAULT, extra_column); - optgroup->label_width = 150; - optgroup->sidetext_width = 70; - - for (auto& opt : cat.second) - { - if (opt == "extruder") - continue; - Option option = optgroup->get_option(opt); - option.opt.width = 70; - optgroup->append_single_option_line(option); - } - optgroup->reload_config(); - m_option_sizer->Add(optgroup->sizer, 0, wxEXPAND | wxALL, 0); - m_og_settings.push_back(optgroup); - - categories.push_back(cat.first); - } - } - - if (m_og_settings.empty()) { - m_objects_ctrl->Select(m_objects_model->Delete(item)); - part_selection_changed(); - } - else { - if (!categories.empty()) - m_objects_model->UpdateSettingsDigest(item, categories); - show_manipulations = false; - } - } - - show_manipulation_og(show_manipulations); - show_info_sizer(show_manipulations && item && m_objects_model->GetParent(item) == wxDataViewItem(0)); - -#ifdef __linux__ - no_updates.reset(nullptr); -#endif - - parent->Layout(); - get_right_panel()->GetParent()->Layout(); -} - -void get_settings_choice(wxMenu *menu, int id, bool is_part) -{ - const auto category_name = menu->GetLabel(id); - - wxArrayString names; - wxArrayInt selections; - - settings_menu_hierarchy settings_menu; - get_options_menu(settings_menu, is_part); - std::vector< std::pair > *settings_list = nullptr; - - auto opt_keys = (*m_config)->keys(); - - for (auto& cat : settings_menu) - { - if (_(cat.first) == category_name) { - int sel = 0; - for (auto& pair : cat.second) { - names.Add(_(pair.second)); - if (find(opt_keys.begin(), opt_keys.end(), pair.first) != opt_keys.end()) - selections.Add(sel); - sel++; - } - settings_list = &cat.second; - break; - } - } - - if (!settings_list) - return; - - if (wxGetSelectedChoices(selections, _(L("Select showing settings")), category_name, names) == -1) - return; - - std::vector selected_options; - for (auto sel : selections) - selected_options.push_back((*settings_list)[sel].first); - - for (auto& setting:(*settings_list) ) - { - auto& opt_key = setting.first; - if (find(opt_keys.begin(), opt_keys.end(), opt_key) != opt_keys.end() && - find(selected_options.begin(), selected_options.end(), opt_key) == selected_options.end()) - (*m_config)->erase(opt_key); - - if(find(opt_keys.begin(), opt_keys.end(), opt_key) == opt_keys.end() && - find(selected_options.begin(), selected_options.end(), opt_key) != selected_options.end()) - (*m_config)->set_key_value(opt_key, m_default_config.get()->option(opt_key)->clone()); - } - - - // Add settings item for object - const auto item = m_objects_ctrl->GetSelection(); - if (item) { - const auto settings_item = m_objects_model->HasSettings(item); - m_objects_ctrl->Select(settings_item ? settings_item : - m_objects_model->AddSettingsChild(item)); -#ifndef __WXOSX__ - part_selection_changed(); -#endif //no __WXOSX__ - } - else - update_settings_list(); -} - -void menu_item_add_generic(wxMenuItem* &menu, int id) { - auto sub_menu = new wxMenu; - - std::vector menu_items = { L("Box"), L("Cylinder"), L("Sphere"), L("Slab") }; - for (auto& item : menu_items) - sub_menu->Append(new wxMenuItem(sub_menu, ++id, _(item))); - -#ifndef __WXMSW__ - sub_menu->Bind(wxEVT_MENU, [sub_menu](wxEvent &event) { - load_lambda(sub_menu->GetLabel(event.GetId()).ToStdString()); - }); -#endif //no __WXMSW__ - - menu->SetSubMenu(sub_menu); -} - -wxMenuItem* menu_item_split(wxMenu* menu, int id) { - auto menu_item = new wxMenuItem(menu, id, _(L("Split to parts"))); - menu_item->SetBitmap(m_bmp_split); - return menu_item; -} - -wxMenuItem* menu_item_settings(wxMenu* menu, int id, const bool is_part) { - auto menu_item = new wxMenuItem(menu, id, _(L("Add settings"))); - menu_item->SetBitmap(m_bmp_cog); - - auto sub_menu = create_add_settings_popupmenu(is_part); - menu_item->SetSubMenu(sub_menu); - return menu_item; -} - -wxMenu *create_add_part_popupmenu() -{ - wxMenu *menu = new wxMenu; - std::vector menu_items = { L("Add part"), L("Add modifier"), L("Add generic") }; - - wxWindowID config_id_base = wxWindow::NewControlId(menu_items.size()+4+2); - - int i = 0; - for (auto& item : menu_items) { - auto menu_item = new wxMenuItem(menu, config_id_base + i, _(item)); - menu_item->SetBitmap(i == 0 ? m_icon_solidmesh : m_icon_modifiermesh); - if (item == "Add generic") - menu_item_add_generic(menu_item, config_id_base + i); - menu->Append(menu_item); - i++; - } - - menu->AppendSeparator(); - auto menu_item = menu_item_split(menu, config_id_base + i + 4); - menu->Append(menu_item); - menu_item->Enable(is_splittable_object(false)); - - menu->AppendSeparator(); - // Append settings popupmenu - menu->Append(menu_item_settings(menu, config_id_base + i + 5, false)); - - menu->Bind(wxEVT_MENU, [config_id_base, menu](wxEvent &event){ - switch (event.GetId() - config_id_base) { - case 0: - on_btn_load(); - break; - case 1: - on_btn_load(true); - break; - case 2: -// on_btn_load(true, true); - break; - case 3: - case 4: - case 5: - case 6: -#ifdef __WXMSW__ - load_lambda(menu->GetLabel(event.GetId()).ToStdString()); -#endif // __WXMSW__ - break; - case 7: //3: - on_btn_split(false); - break; - default: -#ifdef __WXMSW__ - get_settings_choice(menu, event.GetId(), false); -#endif // __WXMSW__ - break; - } - }); - - return menu; -} - -wxMenu *create_part_settings_popupmenu() -{ - wxMenu *menu = new wxMenu; - wxWindowID config_id_base = wxWindow::NewControlId(2); - - auto menu_item = menu_item_split(menu, config_id_base); - menu->Append(menu_item); - menu_item->Enable(is_splittable_object(true)); - - menu->AppendSeparator(); - // Append settings popupmenu - menu->Append(menu_item_settings(menu, config_id_base + 1, true)); - - menu->Bind(wxEVT_MENU, [config_id_base, menu](wxEvent &event){ - switch (event.GetId() - config_id_base) { - case 0: - on_btn_split(true); - break; - default:{ - get_settings_choice(menu, event.GetId(), true); - break; } - } - }); - - return menu; -} - -wxMenu *create_add_settings_popupmenu(bool is_part) -{ - wxMenu *menu = new wxMenu; - - auto categories = get_category_icon(); - - settings_menu_hierarchy settings_menu; - get_options_menu(settings_menu, is_part); - - for (auto cat : settings_menu) - { - auto menu_item = new wxMenuItem(menu, wxID_ANY, _(cat.first)); - menu_item->SetBitmap(categories.find(cat.first) == categories.end() ? - wxNullBitmap : categories.at(cat.first)); - menu->Append(menu_item); - } -#ifndef __WXMSW__ - menu->Bind(wxEVT_MENU, [menu,is_part](wxEvent &event) { - get_settings_choice(menu, event.GetId(), is_part); - }); -#endif //no __WXMSW__ - return menu; -} - -void show_context_menu() -{ - const auto item = m_objects_ctrl->GetSelection(); - if (item) - { - if (m_objects_model->IsSettingsItem(item)) - return; - const auto menu = m_objects_model->GetParent(item) == wxDataViewItem(0) ? - create_add_part_popupmenu() : - create_part_settings_popupmenu(); - wxGetApp().tab_panel()->GetPage(0)->PopupMenu(menu); - } -} - -// ****** - -void load_part( ModelObject* model_object, - wxArrayString& part_names, const bool is_modifier) -{ - wxWindow* parent = wxGetApp().tab_panel()->GetPage(0); - - wxArrayString input_files; - open_model(parent, input_files); - for (int i = 0; i < input_files.size(); ++i) { - std::string input_file = input_files.Item(i).ToStdString(); - - Model model; - try { - model = Model::read_from_file(input_file); - } - catch (std::exception &e) { - auto msg = _(L("Error! ")) + input_file + " : " + e.what() + "."; - show_error(parent, msg); - exit(1); - } - - for ( auto object : model.objects) { - Vec3d delta = Vec3d::Zero(); - if (model_object->origin_translation != Vec3d::Zero()) - { - object->center_around_origin(); - delta = model_object->origin_translation - object->origin_translation; - } - for (auto volume : object->volumes) { - auto new_volume = model_object->add_volume(*volume); - new_volume->set_type(is_modifier ? ModelVolume::PARAMETER_MODIFIER : ModelVolume::MODEL_PART); - boost::filesystem::path(input_file).filename().string(); - new_volume->name = boost::filesystem::path(input_file).filename().string(); - - part_names.Add(new_volume->name); - - if (delta != Vec3d::Zero()) - { - new_volume->mesh.translate((float)delta(0), (float)delta(1), (float)delta(2)); - new_volume->get_convex_hull().translate((float)delta(0), (float)delta(1), (float)delta(2)); - } - - // set a default extruder value, since user can't add it manually - new_volume->config.set_key_value("extruder", new ConfigOptionInt(0)); - - m_parts_changed = true; - } - } - } -} - -void load_lambda( ModelObject* model_object, - wxArrayString& part_names, const bool is_modifier) -{ - auto dlg = new LambdaObjectDialog(m_objects_ctrl->GetMainWindow()); - if (dlg->ShowModal() == wxID_CANCEL) { - return; - } - - std::string name = "lambda-"; - TriangleMesh mesh; - - auto params = dlg->ObjectParameters(); - switch (params.type) - { - case LambdaTypeBox:{ - mesh = make_cube(params.dim[0], params.dim[1], params.dim[2]); - name += "Box"; - break;} - case LambdaTypeCylinder:{ - mesh = make_cylinder(params.cyl_r, params.cyl_h); - name += "Cylinder"; - break;} - case LambdaTypeSphere:{ - mesh = make_sphere(params.sph_rho); - name += "Sphere"; - break;} - case LambdaTypeSlab:{ - const auto& size = model_object->bounding_box().size(); - mesh = make_cube(size(0)*1.5, size(1)*1.5, params.slab_h); - // box sets the base coordinate at 0, 0, move to center of plate and move it up to initial_z - mesh.translate(-size(0)*1.5 / 2.0, -size(1)*1.5 / 2.0, params.slab_z); - name += "Slab"; - break; } - default: - break; - } - mesh.repair(); - - auto new_volume = model_object->add_volume(mesh); - new_volume->set_type(is_modifier ? ModelVolume::PARAMETER_MODIFIER : ModelVolume::MODEL_PART); - - new_volume->name = name; - // set a default extruder value, since user can't add it manually - new_volume->config.set_key_value("extruder", new ConfigOptionInt(0)); - - part_names.Add(name); - - m_parts_changed = true; -} - -void load_lambda(const std::string& type_name) -{ - if (m_selected_object_id < 0) return; - - auto dlg = new LambdaObjectDialog(m_objects_ctrl->GetMainWindow(), type_name); - if (dlg->ShowModal() == wxID_CANCEL) - return; - - const std::string name = "lambda-"+type_name; - TriangleMesh mesh; - - const auto params = dlg->ObjectParameters(); - if (type_name == _("Box")) - mesh = make_cube(params.dim[0], params.dim[1], params.dim[2]); - else if (type_name == _("Cylinder")) - mesh = make_cylinder(params.cyl_r, params.cyl_h); - else if (type_name == _("Sphere")) - mesh = make_sphere(params.sph_rho); - else if (type_name == _("Slab")){ - const auto& size = (*m_objects)[m_selected_object_id]->bounding_box().size(); - mesh = make_cube(size(0)*1.5, size(1)*1.5, params.slab_h); - // box sets the base coordinate at 0, 0, move to center of plate and move it up to initial_z - mesh.translate(-size(0)*1.5 / 2.0, -size(1)*1.5 / 2.0, params.slab_z); - } - mesh.repair(); - - auto new_volume = (*m_objects)[m_selected_object_id]->add_volume(mesh); - new_volume->set_type(ModelVolume::PARAMETER_MODIFIER); - - new_volume->name = name; - // set a default extruder value, since user can't add it manually - new_volume->config.set_key_value("extruder", new ConfigOptionInt(0)); - - m_parts_changed = true; - parts_changed(m_selected_object_id); - - m_objects_ctrl->Select(m_objects_model->AddChild(m_objects_ctrl->GetSelection(), - name, m_icon_modifiermesh)); -#ifndef __WXOSX__ //#ifdef __WXMSW__ // #ys_FIXME - object_ctrl_selection_changed(); -#endif //no __WXOSX__ //__WXMSW__ -} - -void on_btn_load(bool is_modifier /*= false*/, bool is_lambda/* = false*/) -{ - auto item = m_objects_ctrl->GetSelection(); - if (!item) - return; - int obj_idx = -1; - if (m_objects_model->GetParent(item) == wxDataViewItem(0)) - obj_idx = m_objects_model->GetIdByItem(item); - else - return; - - if (obj_idx < 0) return; - wxArrayString part_names; - if (is_lambda) - load_lambda((*m_objects)[obj_idx], part_names, is_modifier); - else - load_part((*m_objects)[obj_idx], part_names, is_modifier); - - parts_changed(obj_idx); - - for (int i = 0; i < part_names.size(); ++i) - m_objects_ctrl->Select( m_objects_model->AddChild(item, part_names.Item(i), - is_modifier ? m_icon_modifiermesh : m_icon_solidmesh)); -#ifndef __WXOSX__ //#ifdef __WXMSW__ // #ys_FIXME - object_ctrl_selection_changed(); -#endif //no __WXOSX__//__WXMSW__ -} - -void remove_settings_from_config() -{ - auto opt_keys = (*m_config)->keys(); - if (opt_keys.size() == 1 && opt_keys[0] == "extruder") - return; - int extruder = -1; - if ((*m_config)->has("extruder")) - extruder = (*m_config)->option("extruder")->value; - - (*m_config)->clear(); - - if (extruder >=0 ) - (*m_config)->set_key_value("extruder", new ConfigOptionInt(extruder)); -} - -bool remove_subobject_from_object(const int volume_id) -{ - const auto volume = (*m_objects)[m_selected_object_id]->volumes[volume_id]; - - // if user is deleting the last solid part, throw error - int solid_cnt = 0; - for (auto vol : (*m_objects)[m_selected_object_id]->volumes) - if (vol->is_model_part()) - ++solid_cnt; - if (volume->is_model_part() && solid_cnt == 1) { - Slic3r::GUI::show_error(nullptr, _(L("You can't delete the last solid part from this object."))); - return false; - } - - (*m_objects)[m_selected_object_id]->delete_volume(volume_id); - m_parts_changed = true; - - parts_changed(m_selected_object_id); - return true; -} - -void on_btn_del() -{ - auto item = m_objects_ctrl->GetSelection(); - if (!item) return; - - const auto volume_id = m_objects_model->GetVolumeIdByItem(item); - if (volume_id ==-1) - return; - - if (volume_id ==-2) - remove_settings_from_config(); - else if (!remove_subobject_from_object(volume_id)) - return; - - m_objects_ctrl->Select(m_objects_model->Delete(item)); - part_selection_changed(); -} - -bool get_volume_by_item(const bool split_part, const wxDataViewItem& item, ModelVolume*& volume) -{ - if (!item || m_selected_object_id < 0) - return false; - const auto volume_id = m_objects_model->GetVolumeIdByItem(item); - if (volume_id < 0) { - if (split_part) return false; - volume = (*m_objects)[m_selected_object_id]->volumes[0]; - } - else - volume = (*m_objects)[m_selected_object_id]->volumes[volume_id]; - if (volume) - return true; - return false; -} - -bool is_splittable_object(const bool split_part) -{ - const wxDataViewItem item = m_objects_ctrl->GetSelection(); - if (!item) return false; - - wxDataViewItemArray children; - if (!split_part && m_objects_model->GetChildren(item, children) > 0) - return false; - - ModelVolume* volume; - if (!get_volume_by_item(split_part, item, volume) || !volume) - return false; - - TriangleMeshPtrs meshptrs = volume->mesh.split(); - bool splittable = meshptrs.size() > 1; - for (TriangleMesh* m : meshptrs) - { - delete m; - } - return splittable; -} - -void on_btn_split(const bool split_part) -{ - const auto item = m_objects_ctrl->GetSelection(); - if (!item || m_selected_object_id<0) - return; - ModelVolume* volume; - if (!get_volume_by_item(split_part, item, volume)) return; - DynamicPrintConfig& config = wxGetApp().preset_bundle->printers.get_edited_preset().config; - const auto nozzle_dmrs_cnt = config.option("nozzle_diameter")->values.size(); - if (volume->split(nozzle_dmrs_cnt) == 1) { - wxMessageBox(_(L("The selected object couldn't be split because it contains only one part."))); - return; - } - - auto model_object = (*m_objects)[m_selected_object_id]; - - if (split_part) { - auto parent = m_objects_model->GetParent(item); - m_objects_model->DeleteChildren(parent); - - for (auto id = 0; id < model_object->volumes.size(); id++) - m_objects_model->AddChild(parent, model_object->volumes[id]->name, - model_object->volumes[id]->is_modifier() ? m_icon_modifiermesh : m_icon_solidmesh, - model_object->volumes[id]->config.has("extruder") ? - model_object->volumes[id]->config.option("extruder")->value : 0, - false); - - m_objects_ctrl->Expand(parent); - } - else { - for (auto id = 0; id < model_object->volumes.size(); id++) - m_objects_model->AddChild(item, model_object->volumes[id]->name, - m_icon_solidmesh, - model_object->volumes[id]->config.has("extruder") ? - model_object->volumes[id]->config.option("extruder")->value : 0, - false); - m_objects_ctrl->Expand(item); - } - - m_parts_changed = true; - parts_changed(m_selected_object_id); -} - -void on_btn_move_up(){ - auto item = m_objects_ctrl->GetSelection(); - if (!item) - return; - auto volume_id = m_objects_model->GetVolumeIdByItem(item); - if (volume_id < 0) - return; - auto& volumes = (*m_objects)[m_selected_object_id]->volumes; - if (0 < volume_id && volume_id < volumes.size()) { - std::swap(volumes[volume_id - 1], volumes[volume_id]); - m_parts_changed = true; - m_objects_ctrl->Select(m_objects_model->MoveChildUp(item)); - part_selection_changed(); -// #ifdef __WXMSW__ -// object_ctrl_selection_changed(); -// #endif //__WXMSW__ - } -} - -void on_btn_move_down(){ - auto item = m_objects_ctrl->GetSelection(); - if (!item) - return; - auto volume_id = m_objects_model->GetVolumeIdByItem(item); - if (volume_id < 0) - return; - auto& volumes = (*m_objects)[m_selected_object_id]->volumes; - if (0 <= volume_id && volume_id+1 < volumes.size()) { - std::swap(volumes[volume_id + 1], volumes[volume_id]); - m_parts_changed = true; - m_objects_ctrl->Select(m_objects_model->MoveChildDown(item)); - part_selection_changed(); -// #ifdef __WXMSW__ -// object_ctrl_selection_changed(); -// #endif //__WXMSW__ - } -} - -void parts_changed(int obj_idx) -{ - if (m_event_object_settings_changed <= 0) return; - - wxCommandEvent e(m_event_object_settings_changed); - auto event_str = wxString::Format("%d %d %d", obj_idx, - is_parts_changed() ? 1 : 0, - is_part_settings_changed() ? 1 : 0); - e.SetString(event_str); -// get_main_frame()->ProcessWindowEvent(e); // #ys_FIXME -} - -void part_selection_changed() -{ - auto item = m_objects_ctrl->GetSelection(); - int obj_idx = -1; - auto og = get_optgroup(ogFrequentlyObjectSettings); - m_config = nullptr; - wxString object_name = wxEmptyString; - if (item) - { - const bool is_settings_item = m_objects_model->IsSettingsItem(item); - bool is_part = false; - wxString og_name = wxEmptyString; - if (m_objects_model->GetParent(item) == wxDataViewItem(0)) { - obj_idx = m_objects_model->GetIdByItem(item); - og_name = _(L("Object manipulation")); - m_config = std::make_shared(&(*m_objects)[obj_idx]->config); - } - else { - auto parent = m_objects_model->GetParent(item); - // Take ID of the parent object to "inform" perl-side which object have to be selected on the scene - obj_idx = m_objects_model->GetIdByItem(parent); - if (is_settings_item) { - if (m_objects_model->GetParent(parent) == wxDataViewItem(0)) { - og_name = _(L("Object Settings to modify")); - m_config = std::make_shared(&(*m_objects)[obj_idx]->config); - } - else { - og_name = _(L("Part Settings to modify")); - is_part = true; - auto main_parent = m_objects_model->GetParent(parent); - obj_idx = m_objects_model->GetIdByItem(main_parent); - const auto volume_id = m_objects_model->GetVolumeIdByItem(parent); - m_config = std::make_shared(&(*m_objects)[obj_idx]->volumes[volume_id]->config); - } - } - else { - og_name = _(L("Part manipulation")); - is_part = true; - const auto volume_id = m_objects_model->GetVolumeIdByItem(item); - m_config = std::make_shared(&(*m_objects)[obj_idx]->volumes[volume_id]->config); - } - } - - og->set_name(" " + og_name + " "); - object_name = m_objects_model->GetName(item); - m_default_config = std::make_shared(*DynamicPrintConfig::new_from_defaults_keys(get_options(is_part))); - } - og->set_value("object_name", object_name); - - update_settings_list(); - - m_selected_object_id = obj_idx; - -// update_values(); -} - -void set_extruder_column_hidden(bool hide) -{ - m_objects_ctrl->GetColumn(2)->SetHidden(hide); -} - -void update_extruder_in_config(const wxString& selection) -{ - if (!m_config || selection.empty()) - return; - - int extruder = selection.size() > 1 ? 0 : atoi(selection.c_str()); - (*m_config)->set_key_value("extruder", new ConfigOptionInt(extruder)); - - if (m_event_update_scene > 0) { - wxCommandEvent e(m_event_update_scene); -// get_main_frame()->ProcessWindowEvent(e); // #ys_FIXME - } -} - -void set_uniform_scaling(const bool uniform_scale) -{ - g_is_uniform_scale = uniform_scale; -} - -void on_begin_drag(wxDataViewEvent &event) -{ - wxDataViewItem item(event.GetItem()); - - // only allow drags for item, not containers - if (m_objects_model->GetParent(item) == wxDataViewItem(0) || m_objects_model->IsSettingsItem(item)) { - event.Veto(); - return; - } - - /* Under MSW or OSX, DnD moves an item to the place of another selected item - * But under GTK, DnD moves an item between another two items. - * And as a result - call EVT_CHANGE_SELECTION to unselect all items. - * To prevent such behavior use g_prevent_list_events - **/ - g_prevent_list_events = true;//it's needed for GTK - - wxTextDataObject *obj = new wxTextDataObject; - obj->SetText(wxString::Format("%d", m_objects_model->GetVolumeIdByItem(item))); - event.SetDataObject(obj); - event.SetDragFlags(/*wxDrag_AllowMove*/wxDrag_DefaultMove); // allows both copy and move; -} - -void on_drop_possible(wxDataViewEvent &event) -{ - wxDataViewItem item(event.GetItem()); - - // only allow drags for item or background, not containers - if (item.IsOk() && m_objects_model->GetParent(item) == wxDataViewItem(0) || - event.GetDataFormat() != wxDF_UNICODETEXT || m_objects_model->IsSettingsItem(item)) - event.Veto(); -} - -void on_drop(wxDataViewEvent &event) -{ - wxDataViewItem item(event.GetItem()); - - // only allow drops for item, not containers - if (item.IsOk() && m_objects_model->GetParent(item) == wxDataViewItem(0) || - event.GetDataFormat() != wxDF_UNICODETEXT || m_objects_model->IsSettingsItem(item)) { - event.Veto(); - return; - } - - wxTextDataObject obj; - obj.SetData(wxDF_UNICODETEXT, event.GetDataSize(), event.GetDataBuffer()); - - int from_volume_id = std::stoi(obj.GetText().ToStdString()); - int to_volume_id = m_objects_model->GetVolumeIdByItem(item); - -#ifdef __WXGTK__ - /* Under GTK, DnD moves an item between another two items. - * And event.GetItem() return item, which is under "insertion line" - * So, if we move item down we should to decrease the to_volume_id value - **/ - if (to_volume_id > from_volume_id) to_volume_id--; -#endif // __WXGTK__ - - m_objects_ctrl->Select(m_objects_model->ReorganizeChildren(from_volume_id, to_volume_id, - m_objects_model->GetParent(item))); - - auto& volumes = (*m_objects)[m_selected_object_id]->volumes; - auto delta = to_volume_id < from_volume_id ? -1 : 1; - int cnt = 0; - for (int id = from_volume_id; cnt < abs(from_volume_id - to_volume_id); id+=delta, cnt++) - std::swap(volumes[id], volumes[id +delta]); - - m_parts_changed = true; - parts_changed(m_selected_object_id); - - g_prevent_list_events = false; -} - -void create_double_slider(wxWindow* parent, wxBoxSizer* sizer, wxGLCanvas* canvas) -{ - m_slider = new PrusaDoubleSlider(parent, wxID_ANY, 0, 0, 0, 100); - sizer->Add(m_slider, 0, wxEXPAND, 0); - - m_preview_canvas = canvas; - m_preview_canvas->Bind(wxEVT_KEY_DOWN, update_double_slider_from_canvas); - - m_slider->Bind(wxEVT_SCROLL_CHANGED, [parent](wxEvent& event) { - _3DScene::set_toolpaths_range(m_preview_canvas, m_slider->GetLowerValueD() - 1e-6, m_slider->GetHigherValueD() + 1e-6); - if (parent->IsShown()) - m_preview_canvas->Refresh(); - }); -} - -void fill_slider_values(std::vector> &values, - const std::vector &layers_z) -{ - std::vector layers_all_z = _3DScene::get_current_print_zs(m_preview_canvas, false); - if (layers_all_z.size() == layers_z.size()) - for (int i = 0; i < layers_z.size(); i++) - values.push_back(std::pair(i+1, layers_z[i])); - else if (layers_all_z.size() > layers_z.size()) { - int cur_id = 0; - for (int i = 0; i < layers_z.size(); i++) - for (int j = cur_id; j < layers_all_z.size(); j++) - if (layers_z[i] - 1e-6 < layers_all_z[j] && layers_all_z[j] < layers_z[i] + 1e-6) { - values.push_back(std::pair(j+1, layers_z[i])); - cur_id = j; - break; - } - } -} - -void set_double_slider_thumbs( const bool force_sliders_full_range, - const std::vector &layers_z, - const double z_low, const double z_high) -{ - // Force slider full range only when slider is created. - // Support selected diapason on the all next steps - if (/*force_sliders_full_range*/z_high == 0.0) { - m_slider->SetLowerValue(0); - m_slider->SetHigherValue(layers_z.size() - 1); - return; - } - - for (int i = layers_z.size() - 1; i >= 0; i--) - if (z_low >= layers_z[i]) { - m_slider->SetLowerValue(i); - break; - } - for (int i = layers_z.size() - 1; i >= 0 ; i--) - if (z_high >= layers_z[i]) { - m_slider->SetHigherValue(i); - break; - } -} - -void update_double_slider(bool force_sliders_full_range) -{ - std::vector> values; - std::vector layers_z = _3DScene::get_current_print_zs(m_preview_canvas, true); - fill_slider_values(values, layers_z); - - const double z_low = m_slider->GetLowerValueD(); - const double z_high = m_slider->GetHigherValueD(); - m_slider->SetMaxValue(layers_z.size() - 1); - m_slider->SetSliderValues(values); - - set_double_slider_thumbs(force_sliders_full_range, layers_z, z_low, z_high); -} - -void reset_double_slider() -{ - m_slider->SetHigherValue(0); - m_slider->SetLowerValue(0); -} - -void update_double_slider_from_canvas(wxKeyEvent& event) -{ - if (event.HasModifiers()) { - event.Skip(); - return; - } - - const auto key = event.GetKeyCode(); - - if (key == 'U' || key == 'D') { - const int new_pos = key == 'U' ? m_slider->GetHigherValue() + 1 : m_slider->GetHigherValue() - 1; - m_slider->SetHigherValue(new_pos); - if (event.ShiftDown()) m_slider->SetLowerValue(m_slider->GetHigherValue()); - } - else if (key == 'S') - m_slider->ChangeOneLayerLock(); - else - event.Skip(); -} - -void show_manipulation_sizer(const bool is_simple_mode) -{ - auto item = m_objects_ctrl->GetSelection(); - if (!item || !is_simple_mode) - return; - - if (m_objects_model->IsSettingsItem(item)) { - m_objects_ctrl->Select(m_objects_model->GetParent(item)); - part_selection_changed(); - } -} - -} //namespace GUI -} //namespace Slic3r \ No newline at end of file diff --git a/src/slic3r/GUI/GUI_ObjectParts.hpp b/src/slic3r/GUI/GUI_ObjectParts.hpp deleted file mode 100644 index 18614c4ee9..0000000000 --- a/src/slic3r/GUI/GUI_ObjectParts.hpp +++ /dev/null @@ -1,134 +0,0 @@ -#ifndef slic3r_GUI_ObjectParts_hpp_ -#define slic3r_GUI_ObjectParts_hpp_ -// #include "OptionsGroup.hpp" - -class wxWindow; -class wxSizer; -class wxBoxSizer; -class wxString; -class wxArrayString; -class wxMenu; -class wxDataViewEvent; -class wxKeyEvent; -class wxGLCanvas; -class wxBitmap; - -namespace Slic3r { -class ModelObject; -class Model; - -namespace GUI { -class ConfigOptionsGroup; -using t_optgroups = std::vector >; - -enum ogGroup{ - ogFrequentlyChangingParameters, - ogFrequentlyObjectSettings, - ogObjectSettings -}; - -enum LambdaTypeIDs{ - LambdaTypeBox, - LambdaTypeCylinder, - LambdaTypeSphere, - LambdaTypeSlab -}; - -struct OBJECT_PARAMETERS -{ - LambdaTypeIDs type = LambdaTypeBox; - double dim[3];// = { 1.0, 1.0, 1.0 }; - int cyl_r = 1; - int cyl_h = 1; - double sph_rho = 1.0; - double slab_h = 1.0; - double slab_z = 0.0; -}; - -typedef std::map t_category_icon; -inline t_category_icon& get_category_icon(); - -void add_objects_list(wxWindow* parent, wxBoxSizer* sizer); -void add_object_settings(wxWindow* parent, wxBoxSizer* sizer, t_optgroups& optgroups); - -wxMenu *create_add_settings_popupmenu(bool is_part); -wxMenu *create_add_part_popupmenu(); -wxMenu *create_part_settings_popupmenu(); - -// Add object to the list -//void add_object(const std::string &name); -void add_object_to_list(const std::string &name, ModelObject* model_object); -// Delete object from the list -void delete_object_from_list(); -// Delete all objects from the list -void delete_all_objects_from_list(); -// Set count of object on c++ side -void set_object_count(int idx, int count); -// Unselect all objects in the list on c++ side -void unselect_objects(); -// Select current object in the list on c++ side -void select_current_object(int idx); -// Select current volume in the list on c++ side -void select_current_volume(int idx, int vol_idx); -// Remove objects/sub-object from the list -void remove(); - -void object_ctrl_selection_changed(); -void object_ctrl_context_menu(); -void object_ctrl_key_event(wxKeyEvent& event); -void object_ctrl_item_value_change(wxDataViewEvent& event); -void show_context_menu(); -bool is_splittable_object(const bool split_part); - -void init_mesh_icons(); -void set_event_object_selection_changed(const int& event); -void set_event_object_settings_changed(const int& event); -void set_event_remove_object(const int& event); -void set_event_update_scene(const int& event); -void set_objects_from_model(Model &model); - -bool is_parts_changed(); -bool is_part_settings_changed(); - -void load_part( ModelObject* model_object, - wxArrayString& part_names, const bool is_modifier); - -void load_lambda( ModelObject* model_object, - wxArrayString& part_names, const bool is_modifier); -void load_lambda( const std::string& type_name); - -void on_btn_load(bool is_modifier = false, bool is_lambda = false); -void on_btn_del(); -void on_btn_split(const bool split_part); -void on_btn_move_up(); -void on_btn_move_down(); - -void parts_changed(int obj_idx); -void part_selection_changed(); - -// show/hide "Extruder" column for Objects List -void set_extruder_column_hidden(bool hide); -// update extruder in current config -void update_extruder_in_config(const wxString& selection); - -void set_uniform_scaling(const bool uniform_scale); - -void on_begin_drag(wxDataViewEvent &event); -void on_drop_possible(wxDataViewEvent &event); -void on_drop(wxDataViewEvent &event); - -// update extruder column for objects_ctrl according to extruders count -void update_objects_list_extruder_column(int extruders_count); - -// Create/Update/Reset double slider on 3dPreview -void create_double_slider(wxWindow* parent, wxBoxSizer* sizer, wxGLCanvas* canvas); -void update_double_slider(bool force_sliders_full_range); -void reset_double_slider(); -// update DoubleSlider after keyDown in canvas -void update_double_slider_from_canvas(wxKeyEvent& event); - -void show_manipulation_sizer(const bool is_simple_mode); - -} //namespace GUI -} //namespace Slic3r -#endif //slic3r_GUI_ObjectParts_hpp_ \ No newline at end of file diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index 988f6e507d..5618eab043 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -6,6 +6,7 @@ #include "GLCanvas3DManager.hpp" #include "../../libslic3r/GCode/PreviewData.hpp" #include "PresetBundle.hpp" +#include "wxExtensions.hpp" #include #include @@ -69,7 +70,7 @@ bool Preview::init(wxNotebook* notebook, DynamicPrintConfig* config, Print* prin _3DScene::enable_dynamic_background(m_canvas, true); m_double_slider_sizer = new wxBoxSizer(wxHORIZONTAL); - create_double_slider(this, m_double_slider_sizer, m_canvas); + create_double_slider(); m_label_view_type = new wxStaticText(this, wxID_ANY, _(L("View"))); @@ -468,5 +469,104 @@ void Preview::on_checkbox_shells(wxCommandEvent& evt) refresh_print(); } +void Preview::create_double_slider() +{ + m_slider = new PrusaDoubleSlider(this, wxID_ANY, 0, 0, 0, 100); + m_double_slider_sizer->Add(m_slider, 0, wxEXPAND, 0); + + // sizer, m_canvas + m_canvas->Bind(wxEVT_KEY_DOWN, &Preview::update_double_slider_from_canvas, this); + + m_slider->Bind(wxEVT_SCROLL_CHANGED, [this](wxEvent& event) { + _3DScene::set_toolpaths_range(m_canvas, m_slider->GetLowerValueD() - 1e-6, m_slider->GetHigherValueD() + 1e-6); + if (IsShown()) + m_canvas->Refresh(); + }); +} + +void Preview::update_double_slider(bool force_sliders_full_range) +{ + std::vector> values; + std::vector layers_z = _3DScene::get_current_print_zs(m_canvas, true); + fill_slider_values(values, layers_z); + + const double z_low = m_slider->GetLowerValueD(); + const double z_high = m_slider->GetHigherValueD(); + m_slider->SetMaxValue(layers_z.size() - 1); + m_slider->SetSliderValues(values); + + set_double_slider_thumbs(force_sliders_full_range, layers_z, z_low, z_high); +} + +void Preview::fill_slider_values(std::vector> &values, + const std::vector &layers_z) +{ + std::vector layers_all_z = _3DScene::get_current_print_zs(m_canvas, false); + if (layers_all_z.size() == layers_z.size()) + for (int i = 0; i < layers_z.size(); i++) + values.push_back(std::pair(i + 1, layers_z[i])); + else if (layers_all_z.size() > layers_z.size()) { + int cur_id = 0; + for (int i = 0; i < layers_z.size(); i++) + for (int j = cur_id; j < layers_all_z.size(); j++) + if (layers_z[i] - 1e-6 < layers_all_z[j] && layers_all_z[j] < layers_z[i] + 1e-6) { + values.push_back(std::pair(j + 1, layers_z[i])); + cur_id = j; + break; + } + } +} + +void Preview::set_double_slider_thumbs(const bool force_sliders_full_range, + const std::vector &layers_z, + const double z_low, + const double z_high) +{ + // Force slider full range only when slider is created. + // Support selected diapason on the all next steps + if (/*force_sliders_full_range*/z_high == 0.0) { + m_slider->SetLowerValue(0); + m_slider->SetHigherValue(layers_z.size() - 1); + return; + } + + for (int i = layers_z.size() - 1; i >= 0; i--) + if (z_low >= layers_z[i]) { + m_slider->SetLowerValue(i); + break; + } + for (int i = layers_z.size() - 1; i >= 0; i--) + if (z_high >= layers_z[i]) { + m_slider->SetHigherValue(i); + break; + } +} + +void Preview::reset_double_slider() +{ + m_slider->SetHigherValue(0); + m_slider->SetLowerValue(0); +} + +void Preview::update_double_slider_from_canvas(wxKeyEvent& event) +{ + if (event.HasModifiers()) { + event.Skip(); + return; + } + + const auto key = event.GetKeyCode(); + + if (key == 'U' || key == 'D') { + const int new_pos = key == 'U' ? m_slider->GetHigherValue() + 1 : m_slider->GetHigherValue() - 1; + m_slider->SetHigherValue(new_pos); + if (event.ShiftDown()) m_slider->SetLowerValue(m_slider->GetHigherValue()); + } + else if (key == 'S') + m_slider->ChangeOneLayerLock(); + else + event.Skip(); +} + } // namespace GUI } // namespace Slic3r diff --git a/src/slic3r/GUI/GUI_Preview.hpp b/src/slic3r/GUI/GUI_Preview.hpp index e7b7f4c941..7c7430c7cc 100644 --- a/src/slic3r/GUI/GUI_Preview.hpp +++ b/src/slic3r/GUI/GUI_Preview.hpp @@ -13,6 +13,7 @@ class wxStaticText; class wxChoice; class wxComboCtrl; class wxCheckBox; +class PrusaDoubleSlider; namespace Slic3r { @@ -46,6 +47,8 @@ class Preview : public wxPanel bool m_enabled; bool m_force_sliders_full_range; + PrusaDoubleSlider* m_slider {nullptr}; + public: Preview(wxNotebook* notebook, DynamicPrintConfig* config, Print* print, GCodePreviewData* gcode_preview_data); virtual ~Preview(); @@ -84,6 +87,19 @@ private: void on_checkbox_retractions(wxCommandEvent& evt); void on_checkbox_unretractions(wxCommandEvent& evt); void on_checkbox_shells(wxCommandEvent& evt); + + // Create/Update/Reset double slider on 3dPreview + void create_double_slider(); + void update_double_slider(bool force_sliders_full_range); + void fill_slider_values(std::vector> &values, + const std::vector &layers_z); + void set_double_slider_thumbs( const bool force_sliders_full_range, + const std::vector &layers_z, + const double z_low, + const double z_high); + void reset_double_slider(); + // update DoubleSlider after keyDown in canvas + void update_double_slider_from_canvas(wxKeyEvent& event); }; } // namespace GUI diff --git a/src/slic3r/GUI/LambdaObjectDialog.hpp b/src/slic3r/GUI/LambdaObjectDialog.hpp index 8f3e8cd80d..9ee7824fcb 100644 --- a/src/slic3r/GUI/LambdaObjectDialog.hpp +++ b/src/slic3r/GUI/LambdaObjectDialog.hpp @@ -13,6 +13,24 @@ namespace Slic3r { namespace GUI { +enum LambdaTypeIDs{ + LambdaTypeBox, + LambdaTypeCylinder, + LambdaTypeSphere, + LambdaTypeSlab +}; + +struct OBJECT_PARAMETERS +{ + LambdaTypeIDs type = LambdaTypeBox; + double dim[3];// = { 1.0, 1.0, 1.0 }; + int cyl_r = 1; + int cyl_h = 1; + double sph_rho = 1.0; + double slab_h = 1.0; + double slab_z = 0.0; +}; +class ConfigOptionsGroup; using ConfigOptionsGroupShp = std::shared_ptr; class LambdaObjectDialog : public wxDialog { diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 07f4c5e8e4..1c52d21554 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -100,9 +100,6 @@ wxFrame(NULL, wxID_ANY, SLIC3R_BUILD, wxDefaultPosition, wxDefaultSize, wxDEFAUL }); update_ui_from_settings(); - -// Slic3r::GUI::update_mode(); - return; } @@ -247,6 +244,23 @@ void MainFrame::init_tabpanel() } } +std::vector preset_tabs = { + { "print", nullptr, ptFFF }, + { "filament", nullptr, ptFFF }, + { "sla_material", nullptr, ptSLA } +}; + +std::vector& MainFrame::get_preset_tabs() { + return preset_tabs; +} + +Tab* MainFrame::get_tab(const std::string& name) +{ + std::vector::iterator it = std::find_if(preset_tabs.begin(), preset_tabs.end(), + [name](PresetTab& tab){ return name == tab.name; }); + return it != preset_tabs.end() ? it->panel : nullptr; +} + Tab* MainFrame::get_preset_tab(const std::string& name) { Tab* tab = get_tab(name); @@ -282,10 +296,9 @@ void MainFrame::add_created_tab(Tab* panel) const wxString& tab_name = panel->GetName(); bool add_panel = true; - auto preset_tabs = get_preset_tabs(); - auto it = std::find_if(preset_tabs->begin(), preset_tabs->end(), + auto it = std::find_if(preset_tabs.begin(), preset_tabs.end(), [tab_name](PresetTab& tab){return tab.name == tab_name; }); - if (it != preset_tabs->end()) { + if (it != preset_tabs.end()) { it->panel = panel; add_panel = it->technology == wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology(); } diff --git a/src/slic3r/GUI/MainFrame.hpp b/src/slic3r/GUI/MainFrame.hpp index f4c75de659..4063bd0c48 100644 --- a/src/slic3r/GUI/MainFrame.hpp +++ b/src/slic3r/GUI/MainFrame.hpp @@ -36,6 +36,12 @@ enum QuickSlice qsExportPNG }; +struct PresetTab { + std::string name; + Tab* panel; + PrinterTechnology technology; +}; + class MainFrame : public wxFrame { bool m_no_plater; @@ -64,6 +70,9 @@ class MainFrame : public wxFrame std::string get_base_name(const wxString full_name) const ; std::string get_dir_name(const wxString full_name) const ; + + Tab* get_tab(const std::string& name); + public: MainFrame() {} MainFrame(const bool no_plater, const bool loaded); @@ -94,6 +103,7 @@ public: void select_tab(size_t tab) const; void select_view(const std::string& direction); + std::vector& get_preset_tabs(); Plater* m_plater { nullptr }; wxNotebook* m_tabpanel { nullptr }; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 29e79b79db..522dfb471b 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -72,13 +72,13 @@ class ObjectInfo : public wxStaticBoxSizer public: ObjectInfo(wxWindow *parent); + wxStaticBitmap *manifold_warning_icon; private: wxStaticText *info_size; wxStaticText *info_volume; wxStaticText *info_facets; wxStaticText *info_materials; wxStaticText *info_manifold; - wxStaticBitmap *manifold_warning_icon; }; ObjectInfo::ObjectInfo(wxWindow *parent) : @@ -362,8 +362,6 @@ struct Sidebar::priv wxButton *btn_reslice; // wxButton *btn_print; // XXX: remove wxButton *btn_send_gcode; - - std::vector > optgroups {}; }; @@ -512,13 +510,14 @@ ObjectManipulation* Sidebar::obj_manipul() return p->object_manipulation; } -ConfigOptionsGroup* Sidebar::get_optgroup(size_t i) +ObjectList* Sidebar::obj_list() { - return p->optgroups.empty() ? nullptr : p->optgroups[i].get(); + return p->object_list; } -t_optgroups& Sidebar::get_optgroups() { - return p->optgroups; +ConfigOptionsGroup* Sidebar::og_freq_chng_params() +{ + return p->frequently_changed_parameters->get_og(); } wxButton* Sidebar::get_wiping_dialog_button() @@ -536,6 +535,26 @@ int Sidebar::get_ol_selection() return p->object_list->get_sel_obj_id(); } +void Sidebar::show_info_sizers(const bool show) +{ + p->object_info->Show(show); + p->object_info->manifold_warning_icon->Show(show/* && g_show_manifold_warning_icon*/); // where is g_show_manifold_warning_icon updating? #ys_FIXME + p->sliced_info->Show(show /*&& g_show_print_info*/); // where is g_show_print_info updating? #ys_FIXME +} + +void Sidebar::show_buttons(const bool show) +{ + p->btn_reslice->Show(show); + for (size_t i = 0; i < wxGetApp().tab_panel()->GetPageCount(); ++i) { + TabPrinter *tab = dynamic_cast(wxGetApp().tab_panel()->GetPage(i)); + if (!tab) + continue; + if (wxGetApp().preset_bundle->printers.get_selected_preset().printer_technology() == ptFFF) { + p->btn_send_gcode->Show(show && !tab->m_config->opt_string("print_host").empty()); + } + break; + } +} // Plater::Object @@ -712,27 +731,6 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) : // Drop target: q->SetDropTarget(new PlaterDropTarget(q)); // if my understanding is right, wxWindow takes the owenership - // Setting of global access pointers - // FIXME: We really should get rid of these once Perl code is gone... - set_objects_from_model(model); - // TODO: ? - // # Send sizers/buttons to C++ - // Slic3r::GUI::set_objects_from_perl( $self->{scrolled_window_panel}, - // $frequently_changed_parameters_sizer, - // $info_sizer, - // $self->{btn_export_gcode}, - // # $self->{btn_export_stl}, - // $self->{btn_reslice}, - // $self->{btn_print}, - // $self->{btn_send_gcode}, - // $self->{object_info_manifold_warning_icon} ); - - // Slic3r::GUI::set_model_events_from_perl( $self->{model}, - // $self->{event_object_selection_changed}, - // $self->{event_object_settings_changed}, - // $self->{event_remove_object}, - // $self->{event_update_scene}); - update_ui_from_settings(); q->Layout(); } diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 1d9022350c..a060eda9ca 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -16,6 +16,7 @@ namespace GUI { class MainFrame; class ConfigOptionsGroup; class ObjectManipulation; +class ObjectList; using t_optgroups = std::vector >; @@ -31,13 +32,15 @@ public: void update_presets(Slic3r::Preset::Type preset_type); - ObjectManipulation* obj_manipul(); + ObjectManipulation* obj_manipul(); + ObjectList* obj_list(); - ConfigOptionsGroup* get_optgroup(size_t i); // #ys_FIXME_for_delete - t_optgroups& get_optgroups();// #ys_FIXME_for_delete + ConfigOptionsGroup* og_freq_chng_params(); wxButton* get_wiping_dialog_button(); void update_objects_list_extruder_column(int extruders_count); int get_ol_selection(); + void show_info_sizers(const bool show); + void show_buttons(const bool show); private: struct priv; diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 7a13f6df76..1e39e2a70a 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -683,10 +683,12 @@ void Tab::on_value_change(const std::string& opt_key, const boost::any& value) // g_wxMainFrame->ProcessWindowEvent(event);// #ys_FIXME } + + auto og_freq_chng_params = wxGetApp().sidebar().og_freq_chng_params(); if (opt_key == "fill_density") { - boost::any val = get_optgroup(ogFrequentlyChangingParameters)->get_config_value(*m_config, opt_key); - get_optgroup(ogFrequentlyChangingParameters)->set_value(opt_key, val); + boost::any val = og_freq_chng_params->get_config_value(*m_config, opt_key); + og_freq_chng_params->set_value(opt_key, val); } if (opt_key == "support_material" || opt_key == "support_material_buildplate_only") { @@ -695,12 +697,12 @@ void Tab::on_value_change(const std::string& opt_key, const boost::any& value) m_config->opt_bool("support_material_buildplate_only") ? _("Support on build plate only") : _("Everywhere"); - get_optgroup(ogFrequentlyChangingParameters)->set_value("support", new_selection); + og_freq_chng_params->set_value("support", new_selection); } if (opt_key == "brim_width") { bool val = m_config->opt_float("brim_width") > 0.0 ? true : false; - get_optgroup(ogFrequentlyChangingParameters)->set_value("brim", val); + og_freq_chng_params->set_value("brim", val); } if (opt_key == "wipe_tower" || opt_key == "single_extruder_multi_material" || opt_key == "extruders_count" ) @@ -789,19 +791,20 @@ void Tab::update_preset_description_line() void Tab::update_frequently_changed_parameters() { - if (!get_optgroup(ogFrequentlyChangingParameters)) return; - boost::any value = get_optgroup(ogFrequentlyChangingParameters)->get_config_value(*m_config, "fill_density"); - get_optgroup(ogFrequentlyChangingParameters)->set_value("fill_density", value); + auto og_freq_chng_params = wxGetApp().sidebar().og_freq_chng_params(); + if (!og_freq_chng_params) return; + boost::any value = og_freq_chng_params->get_config_value(*m_config, "fill_density"); + og_freq_chng_params->set_value("fill_density", value); wxString new_selection = !m_config->opt_bool("support_material") ? _("None") : m_config->opt_bool("support_material_buildplate_only") ? _("Support on build plate only") : _("Everywhere"); - get_optgroup(ogFrequentlyChangingParameters)->set_value("support", new_selection); + og_freq_chng_params->set_value("support", new_selection); bool val = m_config->opt_float("brim_width") > 0.0 ? true : false; - get_optgroup(ogFrequentlyChangingParameters)->set_value("brim", val); + og_freq_chng_params->set_value("brim", val); update_wiping_button_visibility(); } @@ -1841,9 +1844,10 @@ void TabPrinter::extruders_count_changed(size_t extruders_count){ m_preset_bundle->update_multi_material_filament_presets(); build_extruder_pages(); reload_config(); + if (!wxGetApp().mainframe) + return; on_value_change("extruders_count", extruders_count); - if (wxGetApp().mainframe) - wxGetApp().mainframe->m_plater->sidebar().update_objects_list_extruder_column(extruders_count); + wxGetApp().mainframe->m_plater->sidebar().update_objects_list_extruder_column(extruders_count); } void TabPrinter::append_option_line(ConfigOptionsGroupShp optgroup, const std::string opt_key) @@ -2193,7 +2197,7 @@ void Tab::load_current_preset() PrinterTechnology& printer_technology = m_presets->get_edited_preset().printer_technology(); if (printer_technology != static_cast(this)->m_printer_technology) { - for (auto& tab : *get_preset_tabs()){ + for (auto& tab : wxGetApp().mainframe->get_preset_tabs()){ if (tab.technology != printer_technology) { int page_id = wxGetApp().tab_panel()->FindPage(tab.panel); diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp index 13730a497a..bae1055b80 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -1,6 +1,5 @@ #include "wxExtensions.hpp" -#include "GUI.hpp" #include "../../libslic3r/Utils.hpp" #include "BitmapCache.hpp" @@ -8,6 +7,8 @@ #include #include #include +#include "GUI_App.hpp" +#include "GUI_ObjectList.hpp" const unsigned int wxCheckListBoxComboPopup::DefaultWidth = 200; const unsigned int wxCheckListBoxComboPopup::DefaultHeight = 200; @@ -368,7 +369,7 @@ bool PrusaObjectDataViewModelNode::update_settings_digest(const std::vector& categories_icon = Slic3r::GUI::wxGetApp().obj_list()->CATEGORY_ICON;//Slic3r::GUI::get_category_icon(); for (auto& cat : m_opt_categories) m_name += cat + "; "; From 04e193011c5c59f3c98da7b5f16856c086738b80 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Mon, 8 Oct 2018 09:08:42 +0200 Subject: [PATCH 063/186] Fixed crash when selecting object --- src/slic3r/GUI/GLCanvas3D.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index b147ce9891..7eccf3af72 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -4115,7 +4115,7 @@ void GLCanvas3D::_render_legend_texture() const void GLCanvas3D::_render_layer_editing_overlay() const { - if (m_print == nullptr) + if ((m_print == nullptr) || m_print->objects().empty()) return; GLVolume* volume = nullptr; From 384cfa0e6d22cc90d9180ad96a2f312972c0276a Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Mon, 8 Oct 2018 14:02:12 +0200 Subject: [PATCH 064/186] 1st installment of new selections (disabled) --- src/libslic3r/Model.cpp | 7 + src/libslic3r/Technologies.hpp | 2 + src/slic3r/GUI/3DScene.cpp | 21 + src/slic3r/GUI/3DScene.hpp | 23 +- src/slic3r/GUI/GLCanvas3D.cpp | 914 +++++++++++++++++++++- src/slic3r/GUI/GLCanvas3D.hpp | 148 ++++ src/slic3r/GUI/GLCanvas3DManager.cpp | 4 + src/slic3r/GUI/GLCanvas3DManager.hpp | 4 + src/slic3r/GUI/GLGizmo.cpp | 32 + src/slic3r/GUI/GLGizmo.hpp | 16 + src/slic3r/GUI/GUI_ObjectList.cpp | 2 + src/slic3r/GUI/GUI_ObjectManipulation.cpp | 45 ++ src/slic3r/GUI/GUI_ObjectManipulation.hpp | 8 + src/slic3r/GUI/Plater.cpp | 10 + 14 files changed, 1204 insertions(+), 32 deletions(-) diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index aad94ee3c4..88e4c551aa 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -707,16 +707,23 @@ void ModelObject::center_around_origin() if (v->is_model_part()) bb.merge(v->mesh.bounding_box()); +#if ENABLE_EXTENDED_SELECTION + // Shift is the vector from the center of the bounding box to the origin + Vec3d shift = -bb.center(); +#else // Shift is the vector from the center of the bottom face of the bounding box to the origin Vec3d shift = -bb.center(); shift(2) = -bb.min(2); +#endif // ENABLE_EXTENDED_SELECTION this->translate(shift); this->origin_translation += shift; #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM +#if !ENABLE_EXTENDED_SELECTION // set z to zero, translation in z has already been done within the mesh shift(2) = 0.0; +#endif // !ENABLE_EXTENDED_SELECTION #endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM if (!this->instances.empty()) { diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index 9b9067af3e..877f365db5 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -12,6 +12,8 @@ #define ENABLE_GIZMOS_RESET (1 && ENABLE_1_42_0) // Uses a unique opengl context #define ENABLE_USE_UNIQUE_GLCONTEXT (1 && ENABLE_1_42_0) +// New selections +#define ENABLE_EXTENDED_SELECTION (0 && ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM) #endif // _technologies_h_ diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index 44a068303c..4907a5c360 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -209,8 +209,10 @@ GLVolume::GLVolume(float r, float g, float b, float a) , m_transformed_convex_hull_bounding_box_dirty(true) , m_convex_hull(nullptr) , composite_id(-1) +#if !ENABLE_EXTENDED_SELECTION , select_group_id(-1) , drag_group_id(-1) +#endif // !ENABLE_EXTENDED_SELECTION , extruder_id(0) , selected(false) , is_active(true) @@ -311,6 +313,13 @@ void GLVolume::set_offset(const Vec3d& offset) } #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM +#if ENABLE_EXTENDED_SELECTION +const Vec3d& GLVolume::get_scaling_factor() const +{ + return m_scaling_factor; +} +#endif // ENABLE_EXTENDED_SELECTION + void GLVolume::set_scaling_factor(const Vec3d& scaling_factor) { if (m_scaling_factor != scaling_factor) @@ -339,6 +348,7 @@ void GLVolume::set_convex_hull(const TriangleMesh& convex_hull) m_convex_hull = &convex_hull; } +#if !ENABLE_EXTENDED_SELECTION void GLVolume::set_select_group_id(const std::string& select_by) { if (select_by == "object") @@ -356,6 +366,7 @@ void GLVolume::set_drag_group_id(const std::string& drag_by) else if (drag_by == "instance") drag_group_id = object_idx() * 1000 + instance_idx(); } +#endif // !ENABLE_EXTENDED_SELECTION const Transform3f& GLVolume::world_matrix() const { @@ -740,8 +751,10 @@ std::vector GLVolumeCollection::load_object( v.bounding_box = v.indexed_vertex_array.bounding_box(); v.indexed_vertex_array.finalize_geometry(use_VBOs); v.composite_id = obj_idx * 1000000 + volume_idx * 1000 + instance_idx; +#if !ENABLE_EXTENDED_SELECTION v.set_select_group_id(select_by); v.set_drag_group_id(drag_by); +#endif // !ENABLE_EXTENDED_SELECTION if (model_volume->is_model_part()) { v.set_convex_hull(model_volume->get_convex_hull()); @@ -834,8 +847,10 @@ int GLVolumeCollection::load_wipe_tower_preview( v.bounding_box = v.indexed_vertex_array.bounding_box(); v.indexed_vertex_array.finalize_geometry(use_VBOs); v.composite_id = obj_idx * 1000000; +#if !ENABLE_EXTENDED_SELECTION v.select_group_id = obj_idx * 1000000; v.drag_group_id = obj_idx * 1000; +#endif // !ENABLE_EXTENDED_SELECTION v.is_wipe_tower = true; v.shader_outside_printer_detection_enabled = ! size_unknown; return int(this->volumes.size() - 1); @@ -1031,6 +1046,7 @@ void GLVolumeCollection::update_colors_by_extruder(const DynamicPrintConfig* con } } +#if !ENABLE_EXTENDED_SELECTION void GLVolumeCollection::set_select_by(const std::string& select_by) { for (GLVolume *vol : this->volumes) @@ -1048,6 +1064,7 @@ void GLVolumeCollection::set_drag_by(const std::string& drag_by) vol->set_drag_group_id(drag_by); } } +#endif // !ENABLE_EXTENDED_SELECTION std::vector GLVolumeCollection::get_current_print_zs(bool active_only) const { @@ -1850,10 +1867,12 @@ bool _3DScene::move_volume_down(wxGLCanvas* canvas, unsigned int id) return s_canvas_mgr.move_volume_down(canvas, id); } +#if !ENABLE_EXTENDED_SELECTION void _3DScene::set_objects_selections(wxGLCanvas* canvas, const std::vector& selections) { s_canvas_mgr.set_objects_selections(canvas, selections); } +#endif // !ENABLE_EXTENDED_SELECTION void _3DScene::set_config(wxGLCanvas* canvas, DynamicPrintConfig* config) { @@ -1900,6 +1919,7 @@ void _3DScene::set_color_by(wxGLCanvas* canvas, const std::string& value) s_canvas_mgr.set_color_by(canvas, value); } +#if !ENABLE_EXTENDED_SELECTION void _3DScene::set_select_by(wxGLCanvas* canvas, const std::string& value) { s_canvas_mgr.set_select_by(canvas, value); @@ -1914,6 +1934,7 @@ std::string _3DScene::get_select_by(wxGLCanvas* canvas) { return s_canvas_mgr.get_select_by(canvas); } +#endif // !ENABLE_EXTENDED_SELECTION bool _3DScene::is_layers_editing_enabled(wxGLCanvas* canvas) { diff --git a/src/slic3r/GUI/3DScene.hpp b/src/slic3r/GUI/3DScene.hpp index 971083ab62..f6b2b9c4e8 100644 --- a/src/slic3r/GUI/3DScene.hpp +++ b/src/slic3r/GUI/3DScene.hpp @@ -292,10 +292,12 @@ public: float render_color[4]; // An ID containing the object ID, volume ID and instance ID. int composite_id; +#if !ENABLE_EXTENDED_SELECTION // An ID for group selection. It may be the same for all meshes of all object instances, or for just a single object instance. int select_group_id; // An ID for group dragging. It may be the same for all meshes of all object instances, or for just a single object instance. int drag_group_id; +#endif // !ENABLE_EXTENDED_SELECTION // An ID containing the extruder ID (used to select color). int extruder_id; // Is this object selected? @@ -338,6 +340,9 @@ public: const Vec3d& get_rotation() const; void set_rotation(const Vec3d& rotation); +#if ENABLE_EXTENDED_SELECTION + const Vec3d& get_scaling_factor() const; +#endif // ENABLE_EXTENDED_SELECTION void set_scaling_factor(const Vec3d& scaling_factor); #else double get_rotation() const; @@ -351,8 +356,10 @@ public: void set_convex_hull(const TriangleMesh& convex_hull); +#if !ENABLE_EXTENDED_SELECTION void set_select_group_id(const std::string& select_by); void set_drag_group_id(const std::string& drag_by); +#endif // !ENABLE_EXTENDED_SELECTION int object_idx() const { return this->composite_id / 1000000; } int volume_idx() const { return (this->composite_id / 1000) % 1000; } @@ -410,6 +417,10 @@ public: void reset_layer_height_texture_data() { layer_height_texture_data.reset(); } }; +#if ENABLE_EXTENDED_SELECTION +typedef std::vector GLVolumePtrs; +#endif // ENABLE_EXTENDED_SELECTION + class GLVolumeCollection { // min and max vertex of the print box volume @@ -417,8 +428,12 @@ class GLVolumeCollection float print_box_max[3]; public: +#if ENABLE_EXTENDED_SELECTION + GLVolumePtrs volumes; +#else std::vector volumes; - +#endif // ENABLE_EXTENDED_SELECTION + GLVolumeCollection() {}; ~GLVolumeCollection() { clear(); }; @@ -463,8 +478,10 @@ public: void update_colors_by_extruder(const DynamicPrintConfig* config); +#if !ENABLE_EXTENDED_SELECTION void set_select_by(const std::string& select_by); void set_drag_by(const std::string& drag_by); +#endif // !ENABLE_EXTENDED_SELECTION // Returns a vector containing the sorted list of all the print_zs of the volumes contained in this collection std::vector get_current_print_zs(bool active_only) const; @@ -500,7 +517,9 @@ public: static bool move_volume_up(wxGLCanvas* canvas, unsigned int id); static bool move_volume_down(wxGLCanvas* canvas, unsigned int id); +#if !ENABLE_EXTENDED_SELECTION static void set_objects_selections(wxGLCanvas* canvas, const std::vector& selections); +#endif // !ENABLE_EXTENDED_SELECTION static void set_config(wxGLCanvas* canvas, DynamicPrintConfig* config); static void set_print(wxGLCanvas* canvas, Print* print); @@ -516,10 +535,12 @@ public: static void set_cutting_plane(wxGLCanvas* canvas, float z, const ExPolygons& polygons); static void set_color_by(wxGLCanvas* canvas, const std::string& value); +#if !ENABLE_EXTENDED_SELECTION static void set_select_by(wxGLCanvas* canvas, const std::string& value); static void set_drag_by(wxGLCanvas* canvas, const std::string& value); static std::string get_select_by(wxGLCanvas* canvas); +#endif // !ENABLE_EXTENDED_SELECTION static bool is_layers_editing_enabled(wxGLCanvas* canvas); static bool is_layers_editing_allowed(wxGLCanvas* canvas); diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 7eccf3af72..6191c1d63b 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1089,10 +1089,14 @@ const Vec3d GLCanvas3D::Mouse::Drag::Invalid_3D_Point(DBL_MAX, DBL_MAX, DBL_MAX) GLCanvas3D::Mouse::Drag::Drag() : start_position_2D(Invalid_2D_Point) , start_position_3D(Invalid_3D_Point) +#if !ENABLE_EXTENDED_SELECTION , volume_center_offset(0, 0, 0) , move_with_shift(false) +#endif // !ENABLE_EXTENDED_SELECTION , move_volume_idx(-1) +#if !ENABLE_EXTENDED_SELECTION , gizmo_volume_idx(-1) +#endif // !ENABLE_EXTENDED_SELECTION { } @@ -1125,6 +1129,421 @@ bool GLCanvas3D::Mouse::is_start_position_3D_defined() const return (drag.start_position_3D != Drag::Invalid_3D_Point); } +#if ENABLE_EXTENDED_SELECTION +GLCanvas3D::Selection::VolumeCache::VolumeCache() + : position(Vec3d::Zero()) + , rotation(Vec3d::Zero()) + , scaling_factor(Vec3d::Ones()) +{ + m_rotation_matrix = Transform3d::Identity(); +} + +GLCanvas3D::Selection::VolumeCache::VolumeCache(const Vec3d& position, const Vec3d& rotation, const Vec3d& scaling_factor) + : position(position) + , rotation(rotation) + , scaling_factor(scaling_factor) +{ + m_rotation_matrix = Transform3d::Identity(); + m_rotation_matrix.rotate(Eigen::AngleAxisd(rotation(2), Vec3d::UnitZ())); + m_rotation_matrix.rotate(Eigen::AngleAxisd(rotation(1), Vec3d::UnitY())); + m_rotation_matrix.rotate(Eigen::AngleAxisd(rotation(0), Vec3d::UnitX())); +} + +GLCanvas3D::Selection::Selection() + : m_volumes(nullptr) + , m_model(nullptr) + , m_mode(Instance) + , m_valid(false) + , m_bounding_box_dirty(true) +{ +} + +void GLCanvas3D::Selection::set_volumes(GLVolumePtrs* volumes) +{ + m_volumes = volumes; + update_valid(); +} + +void GLCanvas3D::Selection::set_model(Model* model) +{ + m_model = model; + update_valid(); +} + +void GLCanvas3D::Selection::add(unsigned int volume_idx, bool as_single_selection) +{ + if (!m_valid || ((unsigned int)m_volumes->size() <= volume_idx)) + return; + + // resets the current list if needed + const GLVolume* volume = (*m_volumes)[volume_idx]; + if (as_single_selection || volume->is_wipe_tower || is_wipe_tower() || volume->is_modifier || is_modifier()) + clear(); + + switch (m_mode) + { + case Volume: + { + add_volume(volume_idx); + break; + } + case Instance: + { + add_instance(volume_idx); + break; + } + case Object: + { + add_object(volume_idx); + break; + } + } + + m_bounding_box_dirty = true; +} + +void GLCanvas3D::Selection::remove(unsigned int volume_idx) +{ + if (!m_valid || ((unsigned int)m_volumes->size() <= volume_idx)) + return; + + switch (m_mode) + { + case Volume: + { + remove_volume(volume_idx); + break; + } + case Instance: + { + remove_instance(volume_idx); + break; + } + case Object: + { + remove_object(volume_idx); + break; + } + } + + m_bounding_box_dirty = true; +} + +void GLCanvas3D::Selection::clear() +{ + if (!m_valid) + return; + + for (unsigned int i : m_list) + { + (*m_volumes)[i]->selected = false; + } + + m_list.clear(); + m_bounding_box_dirty = true; +} + +bool GLCanvas3D::Selection::is_single_full_instance(int& object_idx_out, int& instance_idx_out) const +{ + if (!m_valid || is_empty() || is_wipe_tower()) + { + object_idx_out = -1; + instance_idx_out = -1; + return false; + } + + const GLVolume* first = (*m_volumes)[*m_list.begin()]; + int object_idx = first->object_idx(); + int instance_idx = first->instance_idx(); + unsigned int count = 0; + + for (unsigned int i : m_list) + { + const GLVolume* v = (*m_volumes)[i]; + if ((v->object_idx() != object_idx) || (v->instance_idx() != instance_idx)) + return false; + else + ++count; + } + + bool res = (count == (unsigned int)m_model->objects[object_idx]->volumes.size()); + object_idx_out = res ? object_idx : -1; + instance_idx_out = res ? instance_idx : -1; + return res; +} + +bool GLCanvas3D::Selection::is_single_full_object(int& object_idx_out) const +{ + if (!m_valid || is_empty() || is_wipe_tower()) + { + object_idx_out = -1; + return false; + } + + int object_idx = (*m_volumes)[*m_list.begin()]->object_idx(); + unsigned int count = 0; + + for (unsigned int i : m_list) + { + const GLVolume* v = (*m_volumes)[i]; + if (v->object_idx() != object_idx) + return false; + else + ++count; + } + + bool res = (count == (unsigned int)m_model->objects[object_idx]->volumes.size() * (unsigned int)m_model->objects[object_idx]->instances.size()); + object_idx_out = res ? object_idx : -1; + return res; +} + +bool GLCanvas3D::Selection::is_from_single_instance(int& object_idx_out, int& instance_idx_out) const +{ + if (!m_valid || is_empty() || is_wipe_tower()) + { + object_idx_out = -1; + instance_idx_out = -1; + return false; + } + + const GLVolume* first = (*m_volumes)[*m_list.begin()]; + int object_idx = first->object_idx(); + int instance_idx = first->instance_idx(); + + for (unsigned int i : m_list) + { + const GLVolume* v = (*m_volumes)[i]; + if ((v->object_idx() != object_idx) || (v->instance_idx() != instance_idx)) + return false; + } + + object_idx_out = object_idx; + instance_idx_out = instance_idx; + return true; +} + +bool GLCanvas3D::Selection::is_from_single_object(int& object_idx_out) const +{ + if (!m_valid || is_empty() || is_wipe_tower()) + { + object_idx_out = -1; + return false; + } + + int object_idx = (*m_volumes)[*m_list.begin()]->object_idx(); + + for (unsigned int i : m_list) + { + const GLVolume* v = (*m_volumes)[i]; + if (v->object_idx() != object_idx) + return false; + } + + object_idx_out = object_idx; + return true; +} + +const GLVolume* GLCanvas3D::Selection::get_volume(unsigned int volume_idx) const +{ + if (!m_valid) + return nullptr; + + return (volume_idx < (unsigned int)m_volumes->size()) ? (*m_volumes)[volume_idx] : nullptr; +} + +const BoundingBoxf3& GLCanvas3D::Selection::get_bounding_box() const +{ + if (m_bounding_box_dirty) + calc_bounding_box(); + + return m_bounding_box; +} + +void GLCanvas3D::Selection::start_dragging() +{ + if (!m_valid) + return; + + set_caches(); +} + +void GLCanvas3D::Selection::translate(const Vec3d& displacement) +{ + if (!m_valid) + return; + + for (unsigned int i : m_list) + { + (*m_volumes)[i]->set_offset(m_cache.volumes_data[i].position + displacement); + } + + m_bounding_box_dirty = true; +} + +void GLCanvas3D::Selection::render() const +{ + if (is_empty()) + return; + + float color[3] = { 1.0f, 1.0f, 1.0f }; + render_bounding_box(get_bounding_box(), color); +} + +void GLCanvas3D::Selection::update_valid() +{ + m_valid = (m_volumes != nullptr) && (m_model != nullptr); +} + +void GLCanvas3D::Selection::set_caches() +{ + m_cache.volumes_data.clear(); + for (unsigned int i : m_list) + { + const GLVolume* v = (*m_volumes)[i]; + m_cache.volumes_data.emplace(i, VolumeCache(v->get_offset(), v->get_rotation(), v->get_scaling_factor())); + } + m_cache.dragging_center = get_bounding_box().center(); +} + +void GLCanvas3D::Selection::add_volume(unsigned int volume_idx) +{ + // check if the given idx is already selected + if (m_list.find(volume_idx) != m_list.end()) + return; + + m_list.insert(volume_idx); + (*m_volumes)[volume_idx]->selected = true; +} + +void GLCanvas3D::Selection::add_instance(unsigned int volume_idx) +{ + GLVolume* volume = (*m_volumes)[volume_idx]; + int object_idx = volume->object_idx(); + int instance_idx = volume->instance_idx(); + + for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i) + { + GLVolume* v = (*m_volumes)[i]; + if ((v->object_idx() == object_idx) && (v->instance_idx() == instance_idx)) + add_volume(i); + } +} + +void GLCanvas3D::Selection::add_object(unsigned int volume_idx) +{ + GLVolume* volume = (*m_volumes)[volume_idx]; + int object_idx = volume->object_idx(); + + for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i) + { + GLVolume* v = (*m_volumes)[i]; + if (v->object_idx() == object_idx) + add_volume(i); + } +} + +void GLCanvas3D::Selection::remove_volume(unsigned int volume_idx) +{ + IndicesList::iterator v_it = m_list.find(volume_idx); + if (v_it == m_list.end()) + return; + + m_list.erase(v_it); + + (*m_volumes)[volume_idx]->selected = false; +} + +void GLCanvas3D::Selection::remove_instance(unsigned int volume_idx) +{ + GLVolume* volume = (*m_volumes)[volume_idx]; + int object_idx = volume->object_idx(); + int instance_idx = volume->instance_idx(); + + for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i) + { + GLVolume* v = (*m_volumes)[i]; + if ((v->object_idx() == object_idx) && (v->instance_idx() == instance_idx)) + remove_volume(i); + } +} + +void GLCanvas3D::Selection::remove_object(unsigned int volume_idx) +{ + GLVolume* volume = (*m_volumes)[volume_idx]; + int object_idx = volume->object_idx(); + + for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i) + { + GLVolume* v = (*m_volumes)[i]; + if (v->object_idx() == object_idx) + remove_volume(i); + } +} + +void GLCanvas3D::Selection::calc_bounding_box() const +{ + m_bounding_box = BoundingBoxf3(); + if (m_valid) + { + for (unsigned int i : m_list) + { + m_bounding_box.merge((*m_volumes)[i]->transformed_bounding_box()); + } + } + m_bounding_box_dirty = false; +} + +void GLCanvas3D::Selection::render_bounding_box(const BoundingBoxf3& box, float* color) const +{ + if (color == nullptr) + return; + + Vec3f b_min = box.min.cast(); + Vec3f b_max = box.max.cast(); + Vec3f size = 0.25f * box.size().cast(); + + ::glEnable(GL_DEPTH_TEST); + + ::glColor3fv(color); + + ::glBegin(GL_LINES); + + ::glVertex3f(b_min(0), b_min(1), b_min(2)); ::glVertex3f(b_min(0) + size(0), b_min(1), b_min(2)); + ::glVertex3f(b_min(0), b_min(1), b_min(2)); ::glVertex3f(b_min(0), b_min(1) + size(1), b_min(2)); + ::glVertex3f(b_min(0), b_min(1), b_min(2)); ::glVertex3f(b_min(0), b_min(1), b_min(2) + size(2)); + + ::glVertex3f(b_max(0), b_min(1), b_min(2)); ::glVertex3f(b_max(0) - size(0), b_min(1), b_min(2)); + ::glVertex3f(b_max(0), b_min(1), b_min(2)); ::glVertex3f(b_max(0), b_min(1) + size(1), b_min(2)); + ::glVertex3f(b_max(0), b_min(1), b_min(2)); ::glVertex3f(b_max(0), b_min(1), b_min(2) + size(2)); + + ::glVertex3f(b_max(0), b_max(1), b_min(2)); ::glVertex3f(b_max(0) - size(0), b_max(1), b_min(2)); + ::glVertex3f(b_max(0), b_max(1), b_min(2)); ::glVertex3f(b_max(0), b_max(1) - size(1), b_min(2)); + ::glVertex3f(b_max(0), b_max(1), b_min(2)); ::glVertex3f(b_max(0), b_max(1), b_min(2) + size(2)); + + ::glVertex3f(b_min(0), b_max(1), b_min(2)); ::glVertex3f(b_min(0) + size(0), b_max(1), b_min(2)); + ::glVertex3f(b_min(0), b_max(1), b_min(2)); ::glVertex3f(b_min(0), b_max(1) - size(1), b_min(2)); + ::glVertex3f(b_min(0), b_max(1), b_min(2)); ::glVertex3f(b_min(0), b_max(1), b_min(2) + size(2)); + + ::glVertex3f(b_min(0), b_min(1), b_max(2)); ::glVertex3f(b_min(0) + size(0), b_min(1), b_max(2)); + ::glVertex3f(b_min(0), b_min(1), b_max(2)); ::glVertex3f(b_min(0), b_min(1) + size(1), b_max(2)); + ::glVertex3f(b_min(0), b_min(1), b_max(2)); ::glVertex3f(b_min(0), b_min(1), b_max(2) - size(2)); + + ::glVertex3f(b_max(0), b_min(1), b_max(2)); ::glVertex3f(b_max(0) - size(0), b_min(1), b_max(2)); + ::glVertex3f(b_max(0), b_min(1), b_max(2)); ::glVertex3f(b_max(0), b_min(1) + size(1), b_max(2)); + ::glVertex3f(b_max(0), b_min(1), b_max(2)); ::glVertex3f(b_max(0), b_min(1), b_max(2) - size(2)); + + ::glVertex3f(b_max(0), b_max(1), b_max(2)); ::glVertex3f(b_max(0) - size(0), b_max(1), b_max(2)); + ::glVertex3f(b_max(0), b_max(1), b_max(2)); ::glVertex3f(b_max(0), b_max(1) - size(1), b_max(2)); + ::glVertex3f(b_max(0), b_max(1), b_max(2)); ::glVertex3f(b_max(0), b_max(1), b_max(2) - size(2)); + + ::glVertex3f(b_min(0), b_max(1), b_max(2)); ::glVertex3f(b_min(0) + size(0), b_max(1), b_max(2)); + ::glVertex3f(b_min(0), b_max(1), b_max(2)); ::glVertex3f(b_min(0), b_max(1) - size(1), b_max(2)); + ::glVertex3f(b_min(0), b_max(1), b_max(2)); ::glVertex3f(b_min(0), b_max(1), b_max(2) - size(2)); + + ::glEnd(); +} +#endif // ENABLE_EXTENDED_SELECTION + const float GLCanvas3D::Gizmos::OverlayTexturesScale = 0.75f; const float GLCanvas3D::Gizmos::OverlayOffsetX = 10.0f * OverlayTexturesScale; const float GLCanvas3D::Gizmos::OverlayGapY = 5.0f * OverlayTexturesScale; @@ -1223,7 +1642,11 @@ void GLCanvas3D::Gizmos::set_enabled(bool enable) m_enabled = enable; } +#if ENABLE_EXTENDED_SELECTION +void GLCanvas3D::Gizmos::update_hover_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos, const GLCanvas3D::Selection& selection) +#else void GLCanvas3D::Gizmos::update_hover_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos) +#endif // ENABLE_EXTENDED_SELECTION { if (!m_enabled) return; @@ -1240,7 +1663,12 @@ void GLCanvas3D::Gizmos::update_hover_state(const GLCanvas3D& canvas, const Vec2 float half_tex_size = 0.5f * tex_size; // we currently use circular icons for gizmo, so we check the radius +#if ENABLE_EXTENDED_SELECTION + bool no_wipe_tower = selection.is_wipe_tower() && !it->second->get_accept_wipe_tower(); + if (!no_wipe_tower && (it->second->get_state() != GLGizmoBase::On)) +#else if (it->second->get_state() != GLGizmoBase::On) +#endif // ENABLE_EXTENDED_SELECTION { bool inside = (mouse_pos - Vec2d(OverlayOffsetX + half_tex_size, top_y + half_tex_size)).norm() < half_tex_size; it->second->set_state(inside ? GLGizmoBase::Hover : GLGizmoBase::Off); @@ -1249,7 +1677,11 @@ void GLCanvas3D::Gizmos::update_hover_state(const GLCanvas3D& canvas, const Vec2 } } +#if ENABLE_EXTENDED_SELECTION +void GLCanvas3D::Gizmos::update_on_off_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos, const GLCanvas3D::Selection& selection) +#else void GLCanvas3D::Gizmos::update_on_off_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos) +#endif // ENABLE_EXTENDED_SELECTION { if (!m_enabled) return; @@ -1266,7 +1698,12 @@ void GLCanvas3D::Gizmos::update_on_off_state(const GLCanvas3D& canvas, const Vec float half_tex_size = 0.5f * tex_size; // we currently use circular icons for gizmo, so we check the radius +#if ENABLE_EXTENDED_SELECTION + bool no_wipe_tower = selection.is_wipe_tower() && !it->second->get_accept_wipe_tower(); + if (!no_wipe_tower && ((mouse_pos - Vec2d(OverlayOffsetX + half_tex_size, top_y + half_tex_size)).norm() < half_tex_size)) +#else if ((mouse_pos - Vec2d(OverlayOffsetX + half_tex_size, top_y + half_tex_size)).norm() < half_tex_size) +#endif // ENABLE_EXTENDED_SELECTION { if ((it->second->get_state() == GLGizmoBase::On)) { @@ -1315,6 +1752,28 @@ void GLCanvas3D::Gizmos::set_hover_id(int id) } } +#if ENABLE_EXTENDED_SELECTION +void GLCanvas3D::Gizmos::enable_grabber(EType type, unsigned int id) +{ + if (!m_enabled) + return; + + GizmosMap::const_iterator it = m_gizmos.find(type); + if (it != m_gizmos.end()) + it->second->enable_grabber(id); +} + +void GLCanvas3D::Gizmos::disable_grabber(EType type, unsigned int id) +{ + if (!m_enabled) + return; + + GizmosMap::const_iterator it = m_gizmos.find(type); + if (it != m_gizmos.end()) + it->second->disable_grabber(id); +} +#endif // ENABLE_EXTENDED_SELECTION + bool GLCanvas3D::Gizmos::overlay_contains_mouse(const GLCanvas3D& canvas, const Vec2d& mouse_pos) const { if (!m_enabled) @@ -1406,6 +1865,16 @@ void GLCanvas3D::Gizmos::stop_dragging() curr->stop_dragging(); } +#if ENABLE_EXTENDED_SELECTION +Vec3d GLCanvas3D::Gizmos::get_displacement() const +{ + if (!m_enabled) + return Vec3d::Zero(); + + GizmosMap::const_iterator it = m_gizmos.find(Move); + return (it != m_gizmos.end()) ? reinterpret_cast(it->second)->get_displacement() : Vec3d::Zero(); +} +#else Vec3d GLCanvas3D::Gizmos::get_position() const { if (!m_enabled) @@ -1424,6 +1893,7 @@ void GLCanvas3D::Gizmos::set_position(const Vec3d& position) if (it != m_gizmos.end()) reinterpret_cast(it->second)->set_position(position); } +#endif // ENABLE_EXTENDED_SELECTION #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM Vec3d GLCanvas3D::Gizmos::get_scale() const @@ -1620,6 +2090,12 @@ float GLCanvas3D::Gizmos::_get_total_overlay_height() const return height; } +GLGizmoBase* GLCanvas3D::Gizmos::_get_current() const +{ + GizmosMap::const_iterator it = m_gizmos.find(m_current); + return (it != m_gizmos.end()) ? it->second : nullptr; +} + const unsigned char GLCanvas3D::WarningTexture::Background_Color[3] = { 9, 91, 134 }; const unsigned char GLCanvas3D::WarningTexture::Opacity = 255; @@ -1933,12 +2409,6 @@ void GLCanvas3D::LegendTexture::render(const GLCanvas3D& canvas) const } } -GLGizmoBase* GLCanvas3D::Gizmos::_get_current() const -{ - GizmosMap::const_iterator it = m_gizmos.find(m_current); - return (it != m_gizmos.end()) ? it->second : nullptr; -} - wxDEFINE_EVENT(EVT_GLCANVAS_OBJECT_SELECT, ObjectSelectEvent); wxDEFINE_EVENT(EVT_GLCANVAS_VIEWPORT_CHANGED, SimpleEvent); wxDEFINE_EVENT(EVT_GLCANVAS_DOUBLE_CLICK, SimpleEvent); @@ -1980,9 +2450,14 @@ GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas) , m_shader_enabled(false) , m_dynamic_background_enabled(false) , m_multisample_allowed(false) +#if ENABLE_EXTENDED_SELECTION + , m_regenerate_volumes(true) +#endif // ENABLE_EXTENDED_SELECTION , m_color_by("volume") +#if !ENABLE_EXTENDED_SELECTION , m_select_by("object") , m_drag_by("instance") +#endif // !ENABLE_EXTENDED_SELECTION , m_reload_delayed(false) { if (m_canvas != nullptr) @@ -1992,6 +2467,10 @@ GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas) #endif // !ENABLE_USE_UNIQUE_GLCONTEXT m_timer = new wxTimer(m_canvas); } + +#if ENABLE_EXTENDED_SELECTION + m_selection.set_volumes(&m_volumes.volumes); +#endif // ENABLE_EXTENDED_SELECTION } GLCanvas3D::~GLCanvas3D() @@ -2132,6 +2611,9 @@ void GLCanvas3D::reset_volumes() m_volumes.release_geometry(); m_volumes.clear(); +#if ENABLE_EXTENDED_SELECTION + m_selection.clear(); +#endif // ENABLE_EXTENDED_SELECTION m_dirty = true; } @@ -2141,25 +2623,30 @@ void GLCanvas3D::reset_volumes() void GLCanvas3D::deselect_volumes() { +#if !ENABLE_EXTENDED_SELECTION for (GLVolume* vol : m_volumes.volumes) { if (vol != nullptr) vol->selected = false; } +#endif // !ENABLE_EXTENDED_SELECTION } void GLCanvas3D::select_volume(unsigned int id) { +#if !ENABLE_EXTENDED_SELECTION if (id < (unsigned int)m_volumes.volumes.size()) { GLVolume* vol = m_volumes.volumes[id]; if (vol != nullptr) vol->selected = true; } +#endif // !ENABLE_EXTENDED_SELECTION } void GLCanvas3D::update_volumes_selection(const std::vector& selections) { +#if !ENABLE_EXTENDED_SELECTION if (m_model == nullptr) return; @@ -2177,6 +2664,7 @@ void GLCanvas3D::update_volumes_selection(const std::vector& selections) } } } +#endif // !ENABLE_EXTENDED_SELECTION } int GLCanvas3D::check_volumes_outside_state(const DynamicPrintConfig* config) const @@ -2192,8 +2680,10 @@ bool GLCanvas3D::move_volume_up(unsigned int id) { std::swap(m_volumes.volumes[id - 1], m_volumes.volumes[id]); std::swap(m_volumes.volumes[id - 1]->composite_id, m_volumes.volumes[id]->composite_id); +#if !ENABLE_EXTENDED_SELECTION std::swap(m_volumes.volumes[id - 1]->select_group_id, m_volumes.volumes[id]->select_group_id); std::swap(m_volumes.volumes[id - 1]->drag_group_id, m_volumes.volumes[id]->drag_group_id); +#endif // !ENABLE_EXTENDED_SELECTION return true; } @@ -2206,18 +2696,22 @@ bool GLCanvas3D::move_volume_down(unsigned int id) { std::swap(m_volumes.volumes[id + 1], m_volumes.volumes[id]); std::swap(m_volumes.volumes[id + 1]->composite_id, m_volumes.volumes[id]->composite_id); +#if !ENABLE_EXTENDED_SELECTION std::swap(m_volumes.volumes[id + 1]->select_group_id, m_volumes.volumes[id]->select_group_id); std::swap(m_volumes.volumes[id + 1]->drag_group_id, m_volumes.volumes[id]->drag_group_id); +#endif // !ENABLE_EXTENDED_SELECTION return true; } return false; } +#if !ENABLE_EXTENDED_SELECTION void GLCanvas3D::set_objects_selections(const std::vector& selections) { m_objects_selections = selections; } +#endif // !ENABLE_EXTENDED_SELECTION void GLCanvas3D::set_config(DynamicPrintConfig* config) { @@ -2232,6 +2726,9 @@ void GLCanvas3D::set_print(Print* print) void GLCanvas3D::set_model(Model* model) { m_model = model; +#if ENABLE_EXTENDED_SELECTION + m_selection.set_model(m_model); +#endif // ENABLE_EXTENDED_SELECTION } void GLCanvas3D::set_bed_shape(const Pointfs& shape) @@ -2289,6 +2786,7 @@ void GLCanvas3D::set_color_by(const std::string& value) m_color_by = value; } +#if !ENABLE_EXTENDED_SELECTION void GLCanvas3D::set_select_by(const std::string& value) { m_select_by = value; @@ -2310,6 +2808,7 @@ const std::string& GLCanvas3D::get_drag_by() const { return m_drag_by; } +#endif // !ENABLE_EXTENDED_SELECTION float GLCanvas3D::get_camera_zoom() const { @@ -2365,6 +2864,9 @@ void GLCanvas3D::enable_legend_texture(bool enable) void GLCanvas3D::enable_picking(bool enable) { m_picking_enabled = enable; +#if ENABLE_EXTENDED_SELECTION + m_selection.set_mode(Selection::Instance); +#endif // ENABLE_EXTENDED_SELECTION } void GLCanvas3D::enable_moving(bool enable) @@ -2478,6 +2980,32 @@ void GLCanvas3D::update_gizmos_data() if (!m_gizmos.is_enabled()) return; +#if ENABLE_EXTENDED_SELECTION + if (m_gizmos.get_current_type() == Gizmos::Move) + { + if (m_selection.is_wipe_tower()) + m_gizmos.disable_grabber(Gizmos::Move, 2); + else + m_gizmos.enable_grabber(Gizmos::Move, 2); + } + + int object_idx = -1; + int instance_idx = -1; + if (m_selection.is_single_full_instance(object_idx, instance_idx)) + { + ModelObject* model_object = m_model->objects[object_idx]; + ModelInstance* model_instance = model_object->instances[instance_idx]; + m_gizmos.set_scale(model_instance->get_scaling_factor()); + m_gizmos.set_rotation(model_instance->get_rotation()); + m_gizmos.set_flattening_data(model_object); + } + else + { + m_gizmos.set_scale(Vec3d::Ones()); + m_gizmos.set_rotation(Vec3d::Zero()); + m_gizmos.set_flattening_data(nullptr); + } +#else int id = _get_first_selected_object_id(); if ((id != -1) && (m_model != nullptr)) { @@ -2512,6 +3040,7 @@ void GLCanvas3D::update_gizmos_data() #endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM m_gizmos.set_flattening_data(nullptr); } +#endif // ENABLE_EXTENDED_SELECTION } void GLCanvas3D::render() @@ -2556,6 +3085,9 @@ void GLCanvas3D::render() _render_axes(false); } _render_objects(); +#if ENABLE_EXTENDED_SELECTION + _render_selection(); +#endif // ENABLE_EXTENDED_SELECTION if (!is_custom_bed) // textured bed needs to be rendered after objects { _render_axes(true); @@ -2594,7 +3126,11 @@ std::vector GLCanvas3D::load_object(const ModelObject& model_object, int ob instance_idxs.push_back(i); } } +#if ENABLE_EXTENDED_SELECTION + return m_volumes.load_object(&model_object, obj_idx, instance_idxs, m_color_by, "object", "object", m_use_VBOs && m_initialized); +#else return m_volumes.load_object(&model_object, obj_idx, instance_idxs, m_color_by, m_select_by, m_drag_by, m_use_VBOs && m_initialized); +#endif // ENABLE_EXTENDED_SELECTION } std::vector GLCanvas3D::load_object(const Model& model, int obj_idx) @@ -2630,7 +3166,9 @@ void GLCanvas3D::reload_scene(bool force) if ((m_canvas == nullptr) || (m_config == nullptr) || (m_model == nullptr)) return; +#if !ENABLE_EXTENDED_SELECTION reset_volumes(); +#endif // !ENABLE_EXTENDED_SELECTION #if !ENABLE_USE_UNIQUE_GLCONTEXT // ensures this canvas is current @@ -2638,6 +3176,11 @@ void GLCanvas3D::reload_scene(bool force) return; #endif // !ENABLE_USE_UNIQUE_GLCONTEXT +#if ENABLE_EXTENDED_SELECTION + if (m_regenerate_volumes) + reset_volumes(); +#endif // ENABLE_EXTENDED_SELECTION + set_bed_shape(dynamic_cast(m_config->option("bed_shape"))->values); if (!m_canvas->IsShown() && !force) @@ -2648,6 +3191,17 @@ void GLCanvas3D::reload_scene(bool force) m_reload_delayed = false; +#if ENABLE_EXTENDED_SELECTION + if (m_regenerate_volumes) + { + for (unsigned int obj_idx = 0; obj_idx < (unsigned int)m_model->objects.size(); ++obj_idx) + { + load_object(*m_model, obj_idx); + } + } + + update_gizmos_data(); +#else m_objects_volumes_idxs.clear(); for (unsigned int obj_idx = 0; obj_idx < (unsigned int)m_model->objects.size(); ++obj_idx) @@ -2661,36 +3215,44 @@ void GLCanvas3D::reload_scene(bool force) // 2nd call to restore selection, if any if (!m_objects_selections.empty()) update_gizmos_data(); +#endif // ENABLE_EXTENDED_SELECTION - if (m_config->has("nozzle_diameter")) +#if ENABLE_EXTENDED_SELECTION + if (m_regenerate_volumes) { - // Should the wipe tower be visualized ? - unsigned int extruders_count = (unsigned int)dynamic_cast(m_config->option("nozzle_diameter"))->values.size(); - - bool semm = dynamic_cast(m_config->option("single_extruder_multi_material"))->value; - bool wt = dynamic_cast(m_config->option("wipe_tower"))->value; - bool co = dynamic_cast(m_config->option("complete_objects"))->value; - - if ((extruders_count > 1) && semm && wt && !co) +#endif // ENABLE_EXTENDED_SELECTION + if (m_config->has("nozzle_diameter")) { - // Height of a print (Show at least a slab) - double height = std::max(m_model->bounding_box().max(2), 10.0); + // Should the wipe tower be visualized ? + unsigned int extruders_count = (unsigned int)dynamic_cast(m_config->option("nozzle_diameter"))->values.size(); - float x = dynamic_cast(m_config->option("wipe_tower_x"))->value; - float y = dynamic_cast(m_config->option("wipe_tower_y"))->value; - float w = dynamic_cast(m_config->option("wipe_tower_width"))->value; - float a = dynamic_cast(m_config->option("wipe_tower_rotation_angle"))->value; + bool semm = dynamic_cast(m_config->option("single_extruder_multi_material"))->value; + bool wt = dynamic_cast(m_config->option("wipe_tower"))->value; + bool co = dynamic_cast(m_config->option("complete_objects"))->value; - float depth = m_print->get_wipe_tower_depth(); - if (!m_print->is_step_done(psWipeTower)) - depth = (900.f/w) * (float)(extruders_count - 1) ; + if ((extruders_count > 1) && semm && wt && !co) + { + // Height of a print (Show at least a slab) + double height = std::max(m_model->bounding_box().max(2), 10.0); - m_volumes.load_wipe_tower_preview(1000, x, y, w, depth, (float)height, a, m_use_VBOs && m_initialized, !m_print->is_step_done(psWipeTower), - m_print->config().nozzle_diameter.values[0] * 1.25f * 4.5f); + float x = dynamic_cast(m_config->option("wipe_tower_x"))->value; + float y = dynamic_cast(m_config->option("wipe_tower_y"))->value; + float w = dynamic_cast(m_config->option("wipe_tower_width"))->value; + float a = dynamic_cast(m_config->option("wipe_tower_rotation_angle"))->value; + + float depth = m_print->get_wipe_tower_depth(); + if (!m_print->is_step_done(psWipeTower)) + depth = (900.f/w) * (float)(extruders_count - 1) ; + + m_volumes.load_wipe_tower_preview(1000, x, y, w, depth, (float)height, a, m_use_VBOs && m_initialized, !m_print->is_step_done(psWipeTower), + m_print->config().nozzle_diameter.values[0] * 1.25f * 4.5f); + } } - } - update_volumes_colors_by_extruder(); + update_volumes_colors_by_extruder(); +#if ENABLE_EXTENDED_SELECTION + } +#endif // ENABLE_EXTENDED_SELECTION // checks for geometry outside the print volume to render it accordingly if (!m_volumes.empty()) @@ -2718,6 +3280,11 @@ void GLCanvas3D::reload_scene(bool force) _reset_warning_texture(); post_event(Event(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, false)); } + +#if ENABLE_EXTENDED_SELECTION + // restore to default value + m_regenerate_volumes = true; +#endif // ENABLE_EXTENDED_SELECTION } void GLCanvas3D::load_gcode_preview(const GCodePreviewData& preview_data, const std::vector& str_tool_colors) @@ -2913,7 +3480,12 @@ void GLCanvas3D::on_mouse_wheel(wxMouseEvent& evt) // Performs layers editing updates, if enabled if (is_layers_editing_enabled()) { +#if ENABLE_EXTENDED_SELECTION + int object_idx_selected = -1; + m_selection.is_from_single_object(object_idx_selected); +#else int object_idx_selected = _get_first_selected_object_id(); +#endif // ENABLE_EXTENDED_SELECTION if (object_idx_selected != -1) { // A volume is selected. Test, whether hovering over a layer thickness bar. @@ -2957,8 +3529,14 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) { Point pos(evt.GetX(), evt.GetY()); +#if ENABLE_EXTENDED_SELECTION + int selected_object_idx = -1; + m_selection.is_from_single_object(selected_object_idx); + int layer_editing_object_idx = is_layers_editing_enabled() ? selected_object_idx : -1; +#else int selected_object_idx = _get_first_selected_object_id(); int layer_editing_object_idx = is_layers_editing_enabled() ? selected_object_idx : -1; +#endif // ENABLE_EXTENDED_SELECTION m_layers_editing.last_object_id = layer_editing_object_idx; bool gizmos_overlay_contains_mouse = m_gizmos.overlay_contains_mouse(*this, m_mouse.position); int toolbar_contains_mouse = m_toolbar.contains_mouse(m_mouse.position); @@ -3026,7 +3604,9 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) { // If user pressed left or right button we first check whether this happened // on a volume or not. +#if !ENABLE_EXTENDED_SELECTION int volume_idx = m_hover_volume_id; +#endif // !ENABLE_EXTENDED_SELECTION m_layers_editing.state = LayersEditing::Unknown; if ((layer_editing_object_idx != -1) && m_layers_editing.bar_rect_contains(*this, pos(0), pos(1))) { @@ -3049,17 +3629,35 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) m_dirty = true; } } +#if ENABLE_EXTENDED_SELECTION + else if (!m_selection.is_empty() && gizmos_overlay_contains_mouse) + { + m_gizmos.update_on_off_state(*this, m_mouse.position, m_selection); + update_gizmos_data(); + m_dirty = true; + } +#else else if ((selected_object_idx != -1) && gizmos_overlay_contains_mouse) { update_gizmos_data(); m_gizmos.update_on_off_state(*this, m_mouse.position); m_dirty = true; } +#endif // ENABLE_EXTENDED_SELECTION +#if ENABLE_EXTENDED_SELECTION + else if (!m_selection.is_empty() && m_gizmos.grabber_contains_mouse()) +#else else if ((selected_object_idx != -1) && m_gizmos.grabber_contains_mouse()) +#endif // ENABLE_EXTENDED_SELECTION { update_gizmos_data(); +#if ENABLE_EXTENDED_SELECTION + m_selection.start_dragging(); + m_gizmos.start_dragging(m_selection.get_bounding_box()); +#else m_gizmos.start_dragging(_selected_volumes_bounding_box()); m_mouse.drag.gizmo_volume_idx = _get_first_selected_volume_id(selected_object_idx); +#endif // ENABLE_EXTENDED_SELECTION if (m_gizmos.get_current_type() == Gizmos::Flatten) { #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM @@ -3089,8 +3687,25 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) // Don't deselect a volume if layer editing is enabled. We want the object to stay selected // during the scene manipulation. +#if ENABLE_EXTENDED_SELECTION + if (m_picking_enabled && ((m_hover_volume_id != -1) || !is_layers_editing_enabled())) +#else if (m_picking_enabled && ((volume_idx != -1) || !is_layers_editing_enabled())) +#endif // ENABLE_EXTENDED_SELECTION { +#if ENABLE_EXTENDED_SELECTION + if (m_hover_volume_id != -1) + { + if (evt.ControlDown()) + m_selection.remove(m_hover_volume_id); + else + m_selection.add(m_hover_volume_id, !evt.ShiftDown()); + + update_gizmos_data(); + wxGetApp().obj_manipul()->update_settings_value(m_selection); + m_dirty = true; + } +#else if (volume_idx != -1) { deselect_volumes(); @@ -3108,32 +3723,61 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) update_gizmos_data(); m_dirty = true; } +#endif // ENABLE_EXTENDED_SELECTION } // propagate event through callback +#if ENABLE_EXTENDED_SELECTION + if (m_picking_enabled && (m_hover_volume_id != -1)) + { + int object_idx = -1; + m_selection.is_from_single_object(object_idx); + _on_select(m_hover_volume_id, object_idx); + } +#else if (m_picking_enabled && (volume_idx != -1)) _on_select(volume_idx, selected_object_idx); +#endif // ENABLE_EXTENDED_SELECTION +#if ENABLE_EXTENDED_SELECTION + if (m_hover_volume_id != -1) +#else if (volume_idx != -1) +#endif // ENABLE_EXTENDED_SELECTION { +#if ENABLE_EXTENDED_SELECTION + if (evt.LeftDown() && m_moving_enabled && (m_mouse.drag.move_volume_idx == -1)) +#else if (evt.LeftDown() && m_moving_enabled) +#endif // ENABLE_EXTENDED_SELECTION { // The mouse_to_3d gets the Z coordinate from the Z buffer at the screen coordinate pos x, y, // an converts the screen space coordinate to unscaled object space. - Vec3d pos3d = (volume_idx == -1) ? Vec3d(DBL_MAX, DBL_MAX, DBL_MAX) : _mouse_to_3d(pos); + Vec3d pos3d = _mouse_to_3d(pos); // Only accept the initial position, if it is inside the volume bounding box. +#if ENABLE_EXTENDED_SELECTION + BoundingBoxf3 volume_bbox = m_volumes.volumes[m_hover_volume_id]->transformed_bounding_box(); +#else BoundingBoxf3 volume_bbox = m_volumes.volumes[volume_idx]->transformed_bounding_box(); +#endif // ENABLE_EXTENDED_SELECTION volume_bbox.offset(1.0); if (volume_bbox.contains(pos3d)) { // The dragging operation is initiated. +#if ENABLE_EXTENDED_SELECTION + m_mouse.drag.move_volume_idx = m_hover_volume_id; + m_selection.start_dragging(); +#else m_mouse.drag.move_with_shift = evt.ShiftDown(); m_mouse.drag.move_volume_idx = volume_idx; +#endif // ENABLE_EXTENDED_SELECTION m_mouse.drag.start_position_3D = pos3d; +#if !ENABLE_EXTENDED_SELECTION // Remember the shift to to the object center.The object center will later be used // to limit the object placement close to the bed. m_mouse.drag.volume_center_offset = volume_bbox.center() - pos3d; +#endif // !ENABLE_EXTENDED_SELECTION } } else if (evt.RightDown()) @@ -3145,7 +3789,11 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) if (m_hover_volume_id != -1) { // if right clicking on volume, propagate event through callback (shows context menu) +#if ENABLE_EXTENDED_SELECTION + if (m_volumes.volumes[m_hover_volume_id]->hover) +#else if (m_volumes.volumes[volume_idx]->hover) +#endif // ENABLE_EXTENDED_SELECTION post_event(Vec2dEvent(EVT_GLCANVAS_RIGHT_CLICK, pos.cast())); } } @@ -3161,6 +3809,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) float z1 = 1.0f; Vec3d cur_pos = Linef3(_mouse_to_3d(pos, &z0), _mouse_to_3d(pos, &z1)).intersect_plane(m_mouse.drag.start_position_3D(2)); +#if !ENABLE_EXTENDED_SELECTION // Clip the new position, so the object center remains close to the bed. cur_pos += m_mouse.drag.volume_center_offset; Point cur_pos2(scale_(cur_pos(0)), scale_(cur_pos(1))); @@ -3171,9 +3820,14 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) cur_pos(1) = unscale(ip(1)); } cur_pos -= m_mouse.drag.volume_center_offset; +#endif // !ENABLE_EXTENDED_SELECTION // Calculate the translation vector. - Vec3d vector = cur_pos - m_mouse.drag.start_position_3D; + Vec3d displacement = cur_pos - m_mouse.drag.start_position_3D; +#if ENABLE_EXTENDED_SELECTION + m_selection.translate(displacement); + wxGetApp().obj_manipul()->update_settings_value(m_selection); +#else // Get the volume being dragged. GLVolume* volume = m_volumes.volumes[m_mouse.drag.move_volume_idx]; // Get all volumes belonging to the same group, if any. @@ -3196,11 +3850,12 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) // Apply new temporary volume origin and ignore Z. for (GLVolume* v : volumes) { - v->set_offset(v->get_offset() + Vec3d(vector(0), vector(1), 0.0)); + v->set_offset(v->get_offset() + Vec3d(displacement(0), displacement(1), 0.0)); } wxGetApp().obj_manipul()->update_position_values(volume->get_offset()); m_mouse.drag.start_position_3D = cur_pos; +#endif // ENABLE_EXTENDED_SELECTION m_dirty = true; } @@ -3212,6 +3867,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) m_mouse.dragging = true; m_gizmos.update(mouse_ray(pos)); +#if !ENABLE_EXTENDED_SELECTION std::vector volumes; if (m_mouse.drag.gizmo_volume_idx != -1) { @@ -3228,12 +3884,17 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) } } } +#endif // !ENABLE_EXTENDED_SELECTION switch (m_gizmos.get_current_type()) { case Gizmos::Move: { // Apply new temporary offset +#if ENABLE_EXTENDED_SELECTION + m_selection.translate(m_gizmos.get_displacement()); + wxGetApp().obj_manipul()->update_settings_value(m_selection); +#else GLVolume* volume = m_volumes.volumes[m_mouse.drag.gizmo_volume_idx]; Vec3d offset = m_gizmos.get_position() - volume->get_offset(); for (GLVolume* v : volumes) @@ -3241,11 +3902,14 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) v->set_offset(v->get_offset() + offset); } wxGetApp().obj_manipul()->update_position_values(volume->get_offset()); +#endif // ENABLE_EXTENDED_SELECTION break; } case Gizmos::Scale: { #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM +#if ENABLE_EXTENDED_SELECTION +#else // Apply new temporary scale factors const Vec3d& scale = m_gizmos.get_scale(); for (GLVolume* v : volumes) @@ -3253,6 +3917,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) v->set_scaling_factor(scale); } wxGetApp().obj_manipul()->update_scale_values(scale); +#endif // ENABLE_EXTENDED_SELECTION #else // Apply new temporary scale factor float scale_factor = m_gizmos.get_scale(); @@ -3267,6 +3932,8 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) case Gizmos::Rotate: { #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM +#if ENABLE_EXTENDED_SELECTION +#else // Apply new temporary rotation const Vec3d& rotation = m_gizmos.get_rotation(); for (GLVolume* v : volumes) @@ -3274,6 +3941,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) v->set_rotation(rotation); } wxGetApp().obj_manipul()->update_rotation_value(rotation); +#endif // ENABLE_EXTENDED_SELECTION #else // Apply new temporary angle_z float angle_z = m_gizmos.get_angle_z(); @@ -3289,6 +3957,8 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) break; } +#if ENABLE_EXTENDED_SELECTION +#else if (!volumes.empty()) { BoundingBoxf3 bb; @@ -3304,6 +3974,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) m_on_update_geometry_info_callback.call(size(0), size(1), size(2), m_gizmos.get_scale()); #endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM } +#endif // ENABLE_EXTENDED_SELECTION m_dirty = true; } @@ -3362,6 +4033,11 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) } else if ((m_mouse.drag.move_volume_idx != -1) && m_mouse.dragging) { +#if ENABLE_EXTENDED_SELECTION + m_regenerate_volumes = false; + _on_move(); + wxGetApp().obj_manipul()->update_settings_value(m_selection); +#else // get all volumes belonging to the same group, if any std::vector volume_idxs; int vol_id = m_mouse.drag.move_volume_idx; @@ -3382,6 +4058,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) // force re-selection of the wipe tower, if needed if ((volume_idxs.size() == 1) && m_volumes.volumes[volume_idxs[0]]->is_wipe_tower) select_volume(volume_idxs[0]); +#endif // ENABLE_EXTENDED_SELECTION } else if (evt.LeftUp() && !m_mouse.dragging && (m_hover_volume_id == -1) && !gizmos_overlay_contains_mouse && !m_gizmos.is_dragging() && !is_layers_editing_enabled()) { @@ -3392,7 +4069,12 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) if (m_picking_enabled && !m_toolbar_action_running) #endif // ENABLE_GIZMOS_RESET { +#if ENABLE_EXTENDED_SELECTION + m_selection.clear(); + wxGetApp().obj_manipul()->update_settings_value(m_selection); +#else deselect_volumes(); +#endif // ENABLE_EXTENDED_SELECTION _on_select(-1, -1); update_gizmos_data(); } @@ -3407,6 +4089,10 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) { case Gizmos::Move: { +#if ENABLE_EXTENDED_SELECTION + m_regenerate_volumes = false; + _on_move(); +#else // get all volumes belonging to the same group, if any std::vector volume_idxs; int vol_id = m_mouse.drag.gizmo_volume_idx; @@ -3423,6 +4109,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) } _on_move(volume_idxs); +#endif // ENABLE_EXTENDED_SELECTION break; } @@ -3448,11 +4135,17 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) break; } m_gizmos.stop_dragging(); +#if ENABLE_EXTENDED_SELECTION + wxGetApp().obj_manipul()->update_settings_value(m_selection); +#else wxGetApp().obj_manipul()->update_values(); +#endif // ENABLE_EXTENDED_SELECTION } m_mouse.drag.move_volume_idx = -1; +#if !ENABLE_EXTENDED_SELECTION m_mouse.drag.gizmo_volume_idx = -1; +#endif // !ENABLE_EXTENDED_SELECTION m_mouse.set_start_position_3D_as_invalid(); m_mouse.set_start_position_2D_as_invalid(); m_mouse.dragging = false; @@ -3656,6 +4349,7 @@ bool GLCanvas3D::_init_toolbar() if (!m_toolbar.add_separator()) return false; +#if !ENABLE_EXTENDED_SELECTION item.name = "selectbyparts"; item.tooltip = GUI::L_str("Select by parts"); item.sprite_id = 10; @@ -3663,6 +4357,7 @@ bool GLCanvas3D::_init_toolbar() item.action_event = EVT_GLTOOLBAR_SELECTBYPARTS; if (!m_toolbar.add_item(item)) return false; +#endif // !ENABLE_EXTENDED_SELECTION enable_toolbar_item("add", true); @@ -3758,6 +4453,7 @@ BoundingBoxf3 GLCanvas3D::_max_bounding_box() const return bb; } +#if !ENABLE_EXTENDED_SELECTION BoundingBoxf3 GLCanvas3D::_selected_volumes_bounding_box() const { BoundingBoxf3 bb; @@ -3802,6 +4498,7 @@ BoundingBoxf3 GLCanvas3D::_selected_volumes_bounding_box() const return bb; } +#endif // !ENABLE_EXTENDED_SELECTION void GLCanvas3D::_zoom_to_bounding_box(const BoundingBoxf3& bbox) { @@ -3893,7 +4590,11 @@ void GLCanvas3D::_mark_volumes_for_layer_height() const for (GLVolume* vol : m_volumes.volumes) { +#if ENABLE_EXTENDED_SELECTION + int object_id = vol->object_idx(); +#else int object_id = int(vol->select_group_id / 1000000); +#endif // ENABLE_EXTENDED_SELECTION int shader_id = m_layers_editing.get_shader_program_id(); if (is_layers_editing_enabled() && (shader_id != -1) && vol->selected && @@ -3949,16 +4650,22 @@ void GLCanvas3D::_picking_pass() const ::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); _render_volumes(true); +#if ENABLE_EXTENDED_SELECTION + m_gizmos.render_current_gizmo_for_picking_pass(m_selection.get_bounding_box()); +#else m_gizmos.render_current_gizmo_for_picking_pass(_selected_volumes_bounding_box()); +#endif // ENABLE_EXTENDED_SELECTION if (m_multisample_allowed) ::glEnable(GL_MULTISAMPLE); int volume_id = -1; +#if !ENABLE_EXTENDED_SELECTION for (GLVolume* vol : m_volumes.volumes) { vol->hover = false; } +#endif // !ENABLE_EXTENDED_SELECTION GLubyte color[4] = { 0, 0, 0, 0 }; const Size& cnv_size = get_canvas_size(); @@ -3972,6 +4679,7 @@ void GLCanvas3D::_picking_pass() const if ((0 <= volume_id) && (volume_id < (int)m_volumes.volumes.size())) { m_hover_volume_id = volume_id; +#if !ENABLE_EXTENDED_SELECTION m_volumes.volumes[volume_id]->hover = true; int group_id = m_volumes.volumes[volume_id]->select_group_id; if (group_id != -1) @@ -3982,6 +4690,7 @@ void GLCanvas3D::_picking_pass() const vol->hover = true; } } +#endif // !ENABLE_EXTENDED_SELECTION m_gizmos.set_hover_id(-1); } else @@ -3990,9 +4699,18 @@ void GLCanvas3D::_picking_pass() const m_gizmos.set_hover_id(inside ? (254 - (int)color[2]) : -1); } +#if ENABLE_EXTENDED_SELECTION + _update_volumes_hover_state(); +#endif // ENABLE_EXTENDED_SELECTION + // updates gizmos overlay +#if ENABLE_EXTENDED_SELECTION + if (!m_selection.is_empty()) + m_gizmos.update_hover_state(*this, pos, m_selection); +#else if (_get_first_selected_object_id() != -1) m_gizmos.update_hover_state(*this, pos); +#endif // ENABLE_EXTENDED_SELECTION else m_gizmos.reset_all_states(); @@ -4092,6 +4810,13 @@ void GLCanvas3D::_render_objects() const ::glDisable(GL_LIGHTING); } +#if ENABLE_EXTENDED_SELECTION +void GLCanvas3D::_render_selection() const +{ + m_selection.render(); +} +#endif // ENABLE_EXTENDED_SELECTION + void GLCanvas3D::_render_cutting_plane() const { m_cutting_plane.render(volumes_bounding_box()); @@ -4134,7 +4859,11 @@ void GLCanvas3D::_render_layer_editing_overlay() const // If the active object was not allocated at the Print, go away.This should only be a momentary case between an object addition / deletion // and an update by Platter::async_apply_config. +#if ENABLE_EXTENDED_SELECTION + int object_idx = volume->object_idx(); +#else int object_idx = int(volume->select_group_id / 1000000); +#endif // ENABLE_EXTENDED_SELECTION if ((int)m_print->objects().size() < object_idx) return; @@ -4194,7 +4923,11 @@ void GLCanvas3D::_render_volumes(bool fake_colors) const void GLCanvas3D::_render_current_gizmo() const { +#if ENABLE_EXTENDED_SELECTION + m_gizmos.render_current_gizmo(m_selection.get_bounding_box()); +#else m_gizmos.render_current_gizmo(_selected_volumes_bounding_box()); +#endif // ENABLE_EXTENDED_SELECTION } void GLCanvas3D::_render_gizmos_overlay() const @@ -4208,6 +4941,43 @@ void GLCanvas3D::_render_toolbar() const m_toolbar.render(); } +#if ENABLE_EXTENDED_SELECTION +void GLCanvas3D::_update_volumes_hover_state() const +{ + for (GLVolume* v : m_volumes.volumes) + { + v->hover = false; + } + + if (m_hover_volume_id == -1) + return; + + GLVolume* volume = m_volumes.volumes[m_hover_volume_id]; + + switch (m_selection.get_mode()) + { + case Selection::Volume: + { + volume->hover = true; + break; + } + case Selection::Instance: + { + int object_idx = volume->object_idx(); + int instance_idx = volume->instance_idx(); + + for (GLVolume* v : m_volumes.volumes) + { + if ((v->object_idx() == object_idx) && (v->instance_idx() == instance_idx)) + v->hover = true; + } + + break; + } + } +} +#endif // ENABLE_EXTENDED_SELECTION + float GLCanvas3D::_get_layers_editing_cursor_z_relative() const { return m_layers_editing.get_cursor_z_relative(*this); @@ -4312,6 +5082,7 @@ void GLCanvas3D::_stop_timer() m_timer->Stop(); } +#if !ENABLE_EXTENDED_SELECTION int GLCanvas3D::_get_first_selected_object_id() const { if (m_print != nullptr) @@ -4345,6 +5116,7 @@ int GLCanvas3D::_get_first_selected_volume_id(int object_id) const return -1; } +#endif // !ENABLE_EXTENDED_SELECTION void GLCanvas3D::_load_print_toolpaths() { @@ -4473,7 +5245,11 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c tbb::parallel_for( tbb::blocked_range(0, ctxt.layers.size(), grain_size), [&ctxt, &new_volume](const tbb::blocked_range& range) { +#if ENABLE_EXTENDED_SELECTION + GLVolumePtrs vols; +#else std::vector vols; +#endif // ENABLE_EXTENDED_SELECTION if (ctxt.color_by_tool()) { for (size_t i = 0; i < ctxt.number_tools(); ++i) vols.emplace_back(new_volume(ctxt.color_tool(i))); @@ -4632,7 +5408,11 @@ void GLCanvas3D::_load_wipe_tower_toolpaths(const std::vector& str_ tbb::blocked_range(0, n_items, grain_size), [&ctxt, &new_volume](const tbb::blocked_range& range) { // Bounding box of this slab of a wipe tower. +#if ENABLE_EXTENDED_SELECTION + GLVolumePtrs vols; +#else std::vector vols; +#endif // ENABLE_EXTENDED_SELECTION if (ctxt.color_by_tool()) { for (size_t i = 0; i < ctxt.number_tools(); ++i) vols.emplace_back(new_volume(ctxt.color_tool(i))); @@ -4858,9 +5638,15 @@ void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_dat m_gcode_preview_volume_index.first_volumes.pop_back(); if (initial_volumes_count != m_volumes.volumes.size()) { +#if ENABLE_EXTENDED_SELECTION + GLVolumePtrs::iterator begin = m_volumes.volumes.begin() + initial_volumes_count; + GLVolumePtrs::iterator end = m_volumes.volumes.end(); + for (GLVolumePtrs::iterator it = begin; it < end; ++it) +#else std::vector::iterator begin = m_volumes.volumes.begin() + initial_volumes_count; std::vector::iterator end = m_volumes.volumes.end(); for (std::vector::iterator it = begin; it < end; ++it) +#endif // ENABLE_EXTENDED_SELECTION { GLVolume* volume = *it; delete volume; @@ -4931,9 +5717,15 @@ void GLCanvas3D::_load_gcode_travel_paths(const GCodePreviewData& preview_data, // an error occourred - restore to previous state and return if (initial_volumes_count != m_volumes.volumes.size()) { +#if ENABLE_EXTENDED_SELECTION + GLVolumePtrs::iterator begin = m_volumes.volumes.begin() + initial_volumes_count; + GLVolumePtrs::iterator end = m_volumes.volumes.end(); + for (GLVolumePtrs::iterator it = begin; it < end; ++it) +#else std::vector::iterator begin = m_volumes.volumes.begin() + initial_volumes_count; std::vector::iterator end = m_volumes.volumes.end(); for (std::vector::iterator it = begin; it < end; ++it) +#endif // ENABLE_EXTENDED_SELECTION { GLVolume* volume = *it; delete volume; @@ -5260,10 +6052,17 @@ void GLCanvas3D::_update_gcode_volumes_visibility(const GCodePreviewData& previe unsigned int size = (unsigned int)m_gcode_preview_volume_index.first_volumes.size(); for (unsigned int i = 0; i < size; ++i) { +#if ENABLE_EXTENDED_SELECTION + GLVolumePtrs::iterator begin = m_volumes.volumes.begin() + m_gcode_preview_volume_index.first_volumes[i].id; + GLVolumePtrs::iterator end = (i + 1 < size) ? m_volumes.volumes.begin() + m_gcode_preview_volume_index.first_volumes[i + 1].id : m_volumes.volumes.end(); + + for (GLVolumePtrs::iterator it = begin; it != end; ++it) +#else std::vector::iterator begin = m_volumes.volumes.begin() + m_gcode_preview_volume_index.first_volumes[i].id; std::vector::iterator end = (i + 1 < size) ? m_volumes.volumes.begin() + m_gcode_preview_volume_index.first_volumes[i + 1].id : m_volumes.volumes.end(); for (std::vector::iterator it = begin; it != end; ++it) +#endif // ENABLE_EXTENDED_SELECTION { GLVolume* volume = *it; @@ -5352,6 +6151,54 @@ void GLCanvas3D::_show_warning_texture_if_needed() } } +#if ENABLE_EXTENDED_SELECTION +void GLCanvas3D::_on_move() +{ + if (m_model == nullptr) + return; + + std::set done; // prevent moving instances twice + bool object_moved = false; + Vec3d wipe_tower_origin = Vec3d::Zero(); + const Selection::IndicesList& selection = m_selection.get_volume_idxs(); + + for (unsigned int i : selection) + { + const GLVolume* v = m_volumes.volumes[i]; + int object_idx = v->object_idx(); + int instance_idx = v->instance_idx(); + + // prevent moving instances twice + char done_id[64]; + ::sprintf(done_id, "%d_%d", object_idx, instance_idx); + if (done.find(done_id) != done.end()) + continue; + + done.insert(done_id); + + if (object_idx < 1000) + { + // Move a regular object. + ModelObject* model_object = m_model->objects[object_idx]; + if (model_object != nullptr) + { + model_object->instances[instance_idx]->set_offset(v->get_offset()); + model_object->invalidate_bounding_box(); + object_moved = true; + } + } + else if (object_idx == 1000) + // Move a wipe tower proxy. + wipe_tower_origin = v->get_offset(); + } + + if (object_moved) + post_event(SimpleEvent(EVT_GLCANVAS_WIPETOWER_MOVED)); + + if (wipe_tower_origin != Vec3d::Zero()) + post_event(Vec3dEvent(EVT_GLCANVAS_WIPETOWER_MOVED, std::move(wipe_tower_origin))); +} +#else void GLCanvas3D::_on_move(const std::vector& volume_idxs) { if (m_model == nullptr) @@ -5402,9 +6249,13 @@ void GLCanvas3D::_on_move(const std::vector& volume_idxs) if (wipe_tower_origin != Vec3d::Zero()) post_event(Vec3dEvent(EVT_GLCANVAS_WIPETOWER_MOVED, std::move(wipe_tower_origin))); } +#endif // ENABLE_EXTENDED_SELECTION void GLCanvas3D::_on_select(int volume_idx, int object_idx) { +#if ENABLE_EXTENDED_SELECTION + post_event(ObjectSelectEvent(object_idx, -1)); +#else int vol_id = -1; int obj_id = -1; @@ -5433,6 +6284,7 @@ void GLCanvas3D::_on_select(int volume_idx, int object_idx) post_event(ObjectSelectEvent(obj_id, vol_id)); wxGetApp().obj_list()->select_current_volume(obj_id, vol_id); +#endif // !ENABLE_EXTENDED_SELECTION } std::vector GLCanvas3D::_parse_colors(const std::vector& colors) diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 59893368ec..5b5df1851d 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -346,11 +346,15 @@ class GLCanvas3D Point start_position_2D; Vec3d start_position_3D; +#if !ENABLE_EXTENDED_SELECTION Vec3d volume_center_offset; bool move_with_shift; +#endif // !ENABLE_EXTENDED_SELECTION int move_volume_idx; +#if !ENABLE_EXTENDED_SELECTION int gizmo_volume_idx; +#endif // !ENABLE_EXTENDED_SELECTION public: Drag(); @@ -372,6 +376,104 @@ class GLCanvas3D bool is_start_position_3D_defined() const; }; +#if ENABLE_EXTENDED_SELECTION +public: + class Selection + { + public: + typedef std::set IndicesList; + + enum EMode : unsigned char + { + Volume, + Instance, + Object + }; + + private: + struct VolumeCache + { + private: + Transform3d m_rotation_matrix; + + public: + Vec3d position; + Vec3d rotation; + Vec3d scaling_factor; + + VolumeCache(); + VolumeCache(const Vec3d& position, const Vec3d& rotation, const Vec3d& scaling_factor); + + const Transform3d& get_rotation_matrix() const { return m_rotation_matrix; } + }; + + typedef std::map VolumesCache; + + struct Cache + { + VolumesCache volumes_data; + Vec3d dragging_center; + }; + + GLVolumePtrs* m_volumes; + Model* m_model; + + bool m_valid; + EMode m_mode; + IndicesList m_list; + Cache m_cache; + mutable BoundingBoxf3 m_bounding_box; + mutable bool m_bounding_box_dirty; + + public: + Selection(); + + void set_volumes(GLVolumePtrs* volumes); + void set_model(Model* model); + + EMode get_mode() const { return m_mode; } + void set_mode(EMode mode) { m_mode = mode; } + + void add(unsigned int volume_idx, bool as_single_selection = true); + void remove(unsigned int volume_idx); + void clear(); + + bool is_empty() const { return m_list.empty(); } + bool is_wipe_tower() const { return m_valid && (m_list.size() == 1) && (*m_volumes)[*m_list.begin()]->is_wipe_tower; } + bool is_modifier() const { return m_valid && (m_list.size() == 1) && (*m_volumes)[*m_list.begin()]->is_modifier; } + bool is_single_full_instance(int& object_idx_out, int& instance_idx_out) const; + bool is_single_full_object(int& object_idx_out) const; + bool is_from_single_instance(int& object_idx_out, int& instance_idx_out) const; + bool is_from_single_object(int& object_idx_out) const; + + const IndicesList& get_volume_idxs() const { return m_list; } + const GLVolume* get_volume(unsigned int volume_idx) const; + + unsigned int volumes_count() const { return (unsigned int)m_list.size(); } + const BoundingBoxf3& get_bounding_box() const; + + void start_dragging(); + + void translate(const Vec3d& displacement); + + void render() const; + + private: + void update_valid(); + void set_caches(); + void add_volume(unsigned int volume_idx); + void add_instance(unsigned int volume_idx); + void add_object(unsigned int volume_idx); + void remove_volume(unsigned int volume_idx); + void remove_instance(unsigned int volume_idx); + void remove_object(unsigned int volume_idx); + void calc_bounding_box() const; + void render_bounding_box(const BoundingBoxf3& box, float* color) const; + }; + +private: +#endif // ENABLE_EXTENDED_SELECTION + class Gizmos { static const float OverlayTexturesScale; @@ -404,11 +506,20 @@ class GLCanvas3D bool is_enabled() const; void set_enabled(bool enable); +#if ENABLE_EXTENDED_SELECTION + void update_hover_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos, const Selection& selection); + void update_on_off_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos, const Selection& selection); +#else void update_hover_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos); void update_on_off_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos); +#endif // ENABLE_EXTENDED_SELECTION void reset_all_states(); void set_hover_id(int id); +#if ENABLE_EXTENDED_SELECTION + void enable_grabber(EType type, unsigned int id); + void disable_grabber(EType type, unsigned int id); +#endif // ENABLE_EXTENDED_SELECTION bool overlay_contains_mouse(const GLCanvas3D& canvas, const Vec2d& mouse_pos) const; bool grabber_contains_mouse() const; @@ -425,8 +536,12 @@ class GLCanvas3D void start_dragging(const BoundingBoxf3& box); void stop_dragging(); +#if ENABLE_EXTENDED_SELECTION + Vec3d get_displacement() const; +#else Vec3d get_position() const; void set_position(const Vec3d& position); +#endif // ENABLE_EXTENDED_SELECTION #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM Vec3d get_scale() const; @@ -517,6 +632,9 @@ class GLCanvas3D mutable GLToolbar m_toolbar; mutable GLVolumeCollection m_volumes; +#if ENABLE_EXTENDED_SELECTION + Selection m_selection; +#endif // ENABLE_EXTENDED_SELECTION DynamicPrintConfig* m_config; Print* m_print; Model* m_model; @@ -535,14 +653,21 @@ class GLCanvas3D bool m_shader_enabled; bool m_dynamic_background_enabled; bool m_multisample_allowed; +#if ENABLE_EXTENDED_SELECTION + bool m_regenerate_volumes; +#endif // ENABLE_EXTENDED_SELECTION std::string m_color_by; +#if !ENABLE_EXTENDED_SELECTION std::string m_select_by; std::string m_drag_by; +#endif // !ENABLE_EXTENDED_SELECTION bool m_reload_delayed; +#if !ENABLE_EXTENDED_SELECTION std::vector> m_objects_volumes_idxs; std::vector m_objects_selections; +#endif // !ENABLE_EXTENDED_SELECTION GCodePreviewVolumeIndex m_gcode_preview_volume_index; @@ -575,12 +700,18 @@ public: bool move_volume_up(unsigned int id); bool move_volume_down(unsigned int id); +#if !ENABLE_EXTENDED_SELECTION void set_objects_selections(const std::vector& selections); +#endif // !ENABLE_EXTENDED_SELECTION void set_config(DynamicPrintConfig* config); void set_print(Print* print); void set_model(Model* model); +#if ENABLE_EXTENDED_SELECTION + const Selection& get_selection() const { return m_selection; } +#endif // ENABLE_EXTENDED_SELECTION + // Set the bed shape to a single closed 2D polygon(array of two element arrays), // triangulate the bed and store the triangles into m_bed.m_triangles, // fills the m_bed.m_grid_lines and sets m_bed.m_origin. @@ -594,11 +725,13 @@ public: void set_cutting_plane(float z, const ExPolygons& polygons); void set_color_by(const std::string& value); +#if !ENABLE_EXTENDED_SELECTION void set_select_by(const std::string& value); void set_drag_by(const std::string& value); const std::string& get_select_by() const; const std::string& get_drag_by() const; +#endif // !ENABLE_EXTENDED_SELECTION float get_camera_zoom() const; @@ -680,7 +813,9 @@ private: void _resize(unsigned int w, unsigned int h); BoundingBoxf3 _max_bounding_box() const; +#if !ENABLE_EXTENDED_SELECTION BoundingBoxf3 _selected_volumes_bounding_box() const; +#endif // !ENABLE_EXTENDED_SELECTION void _zoom_to_bounding_box(const BoundingBoxf3& bbox); float _get_zoom_to_bounding_box_factor(const BoundingBoxf3& bbox) const; @@ -694,6 +829,9 @@ private: void _render_bed(float theta) const; void _render_axes(bool depth_test) const; void _render_objects() const; +#if ENABLE_EXTENDED_SELECTION + void _render_selection() const; +#endif // ENABLE_EXTENDED_SELECTION void _render_cutting_plane() const; void _render_warning_texture() const; void _render_legend_texture() const; @@ -703,6 +841,10 @@ private: void _render_gizmos_overlay() const; void _render_toolbar() const; +#if ENABLE_EXTENDED_SELECTION + void _update_volumes_hover_state() const; +#endif // ENABLE_EXTENDED_SELECTION + float _get_layers_editing_cursor_z_relative() const; void _perform_layer_editing_action(wxMouseEvent* evt = nullptr); @@ -719,8 +861,10 @@ private: void _start_timer(); void _stop_timer(); +#if !ENABLE_EXTENDED_SELECTION int _get_first_selected_object_id() const; int _get_first_selected_volume_id(int object_id) const; +#endif // !ENABLE_EXTENDED_SELECTION // Create 3D thick extrusion lines for a skirt and brim. // Adds a new Slic3r::GUI::3DScene::Volume to volumes. @@ -750,7 +894,11 @@ private: void _update_toolpath_volumes_outside_state(); void _show_warning_texture_if_needed(); +#if ENABLE_EXTENDED_SELECTION + void _on_move(); +#else void _on_move(const std::vector& volume_idxs); +#endif // ENABLE_EXTENDED_SELECTION void _on_select(int volume_idx, int object_idx); // generates the legend texture in dependence of the current shown view type diff --git a/src/slic3r/GUI/GLCanvas3DManager.cpp b/src/slic3r/GUI/GLCanvas3DManager.cpp index 8720caba59..1258c48947 100644 --- a/src/slic3r/GUI/GLCanvas3DManager.cpp +++ b/src/slic3r/GUI/GLCanvas3DManager.cpp @@ -285,12 +285,14 @@ bool GLCanvas3DManager::move_volume_down(wxGLCanvas* canvas, unsigned int id) return (it != m_canvases.end()) ? it->second->move_volume_down(id) : false; } +#if !ENABLE_EXTENDED_SELECTION void GLCanvas3DManager::set_objects_selections(wxGLCanvas* canvas, const std::vector& selections) { CanvasesMap::iterator it = _get_canvas(canvas); if (it != m_canvases.end()) it->second->set_objects_selections(selections); } +#endif // !ENABLE_EXTENDED_SELECTION void GLCanvas3DManager::set_config(wxGLCanvas* canvas, DynamicPrintConfig* config) { @@ -354,6 +356,7 @@ void GLCanvas3DManager::set_color_by(wxGLCanvas* canvas, const std::string& valu it->second->set_color_by(value); } +#if !ENABLE_EXTENDED_SELECTION void GLCanvas3DManager::set_select_by(wxGLCanvas* canvas, const std::string& value) { CanvasesMap::iterator it = _get_canvas(canvas); @@ -373,6 +376,7 @@ std::string GLCanvas3DManager::get_select_by(wxGLCanvas* canvas) const CanvasesMap::const_iterator it = _get_canvas(canvas); return (it != m_canvases.end()) ? it->second->get_select_by() : ""; } +#endif // !ENABLE_EXTENDED_SELECTION bool GLCanvas3DManager::is_layers_editing_enabled(wxGLCanvas* canvas) const { diff --git a/src/slic3r/GUI/GLCanvas3DManager.hpp b/src/slic3r/GUI/GLCanvas3DManager.hpp index 960bb6d2aa..c64e213503 100644 --- a/src/slic3r/GUI/GLCanvas3DManager.hpp +++ b/src/slic3r/GUI/GLCanvas3DManager.hpp @@ -94,7 +94,9 @@ public: bool move_volume_up(wxGLCanvas* canvas, unsigned int id); bool move_volume_down(wxGLCanvas* canvas, unsigned int id); +#if !ENABLE_EXTENDED_SELECTION void set_objects_selections(wxGLCanvas* canvas, const std::vector& selections); +#endif // !ENABLE_EXTENDED_SELECTION void set_config(wxGLCanvas* canvas, DynamicPrintConfig* config); void set_print(wxGLCanvas* canvas, Print* print); @@ -110,10 +112,12 @@ public: void set_cutting_plane(wxGLCanvas* canvas, float z, const ExPolygons& polygons); void set_color_by(wxGLCanvas* canvas, const std::string& value); +#if !ENABLE_EXTENDED_SELECTION void set_select_by(wxGLCanvas* canvas, const std::string& value); void set_drag_by(wxGLCanvas* canvas, const std::string& value); std::string get_select_by(wxGLCanvas* canvas) const; +#endif // !ENABLE_EXTENDED_SELECTION bool is_layers_editing_enabled(wxGLCanvas* canvas) const; bool is_layers_editing_allowed(wxGLCanvas* canvas) const; diff --git a/src/slic3r/GUI/GLGizmo.cpp b/src/slic3r/GUI/GLGizmo.cpp index 55729ac87d..72bf18de95 100644 --- a/src/slic3r/GUI/GLGizmo.cpp +++ b/src/slic3r/GUI/GLGizmo.cpp @@ -216,6 +216,9 @@ GLGizmoBase::GLGizmoBase(GLCanvas3D& parent) : m_parent(parent) , m_group_id(-1) , m_state(Off) +#if ENABLE_EXTENDED_SELECTION + , m_accept_wipe_tower(false) +#endif // ENABLE_EXTENDED_SELECTION , m_hover_id(-1) , m_dragging(false) { @@ -1050,7 +1053,11 @@ const double GLGizmoMove3D::Offset = 10.0; GLGizmoMove3D::GLGizmoMove3D(GLCanvas3D& parent) : GLGizmoBase(parent) +#if ENABLE_EXTENDED_SELECTION + , m_displacement(Vec3d::Zero()) +#else , m_position(Vec3d::Zero()) +#endif // ENABLE_EXTENDED_SELECTION , m_starting_drag_position(Vec3d::Zero()) , m_starting_box_center(Vec3d::Zero()) , m_starting_box_bottom_center(Vec3d::Zero()) @@ -1078,6 +1085,10 @@ bool GLGizmoMove3D::on_init() m_grabbers.push_back(Grabber()); } +#if ENABLE_EXTENDED_SELECTION + m_accept_wipe_tower = true; +#endif // ENABLE_EXTENDED_SELECTION + return true; } @@ -1085,6 +1096,9 @@ void GLGizmoMove3D::on_start_dragging(const BoundingBoxf3& box) { if (m_hover_id != -1) { +#if ENABLE_EXTENDED_SELECTION + m_displacement = Vec3d::Zero(); +#endif // ENABLE_EXTENDED_SELECTION m_starting_drag_position = m_grabbers[m_hover_id].center; m_starting_box_center = box.center(); m_starting_box_bottom_center = box.center(); @@ -1094,22 +1108,40 @@ void GLGizmoMove3D::on_start_dragging(const BoundingBoxf3& box) void GLGizmoMove3D::on_update(const Linef3& mouse_ray) { +#if ENABLE_EXTENDED_SELECTION + if (m_hover_id == 0) + m_displacement(0) = calc_projection(X, 1, mouse_ray) - (m_starting_drag_position(0) - m_starting_box_center(0)); + else if (m_hover_id == 1) + m_displacement(1) = calc_projection(Y, 2, mouse_ray) - (m_starting_drag_position(1) - m_starting_box_center(1)); + else if (m_hover_id == 2) + m_displacement(2) = calc_projection(Z, 1, mouse_ray) - (m_starting_drag_position(2) - m_starting_box_bottom_center(2)); +#else if (m_hover_id == 0) m_position(0) = 2.0 * m_starting_box_center(0) + calc_projection(X, 1, mouse_ray) - m_starting_drag_position(0); else if (m_hover_id == 1) m_position(1) = 2.0 * m_starting_box_center(1) + calc_projection(Y, 2, mouse_ray) - m_starting_drag_position(1); else if (m_hover_id == 2) m_position(2) = 2.0 * m_starting_box_bottom_center(2) + calc_projection(Z, 1, mouse_ray) - m_starting_drag_position(2); +#endif // ENABLE_EXTENDED_SELECTION } void GLGizmoMove3D::on_render(const BoundingBoxf3& box) const { +#if ENABLE_EXTENDED_SELECTION + if (m_grabbers[0].dragging) + set_tooltip("X: " + format(m_displacement(0), 2)); + else if (m_grabbers[1].dragging) + set_tooltip("Y: " + format(m_displacement(1), 2)); + else if (m_grabbers[2].dragging) + set_tooltip("Z: " + format(m_displacement(2), 2)); +#else if (m_grabbers[0].dragging) set_tooltip("X: " + format(m_position(0), 2)); else if (m_grabbers[1].dragging) set_tooltip("Y: " + format(m_position(1), 2)); else if (m_grabbers[2].dragging) set_tooltip("Z: " + format(m_position(2), 2)); +#endif // ENABLE_EXTENDED_SELECTION ::glEnable(GL_DEPTH_TEST); diff --git a/src/slic3r/GUI/GLGizmo.hpp b/src/slic3r/GUI/GLGizmo.hpp index ac85caa182..0ad40a8b39 100644 --- a/src/slic3r/GUI/GLGizmo.hpp +++ b/src/slic3r/GUI/GLGizmo.hpp @@ -56,6 +56,9 @@ protected: int m_group_id; EState m_state; +#if ENABLE_EXTENDED_SELECTION + bool m_accept_wipe_tower; +#endif // ENABLE_EXTENDED_SELECTION // textures are assumed to be square and all with the same size in pixels, no internal check is done GLTexture m_textures[Num_States]; int m_hover_id; @@ -77,6 +80,11 @@ public: EState get_state() const { return m_state; } void set_state(EState state) { m_state = state; on_set_state(); } +#if ENABLE_EXTENDED_SELECTION + bool get_accept_wipe_tower() { return m_accept_wipe_tower; } + void set_accept_wipe_tower(bool accept) { m_accept_wipe_tower = accept; } +#endif // ENABLE_EXTENDED_SELECTION + unsigned int get_texture_id() const { return m_textures[m_state].get_id(); } int get_textures_size() const { return m_textures[Off].get_width(); } @@ -318,7 +326,11 @@ class GLGizmoMove3D : public GLGizmoBase { static const double Offset; +#if ENABLE_EXTENDED_SELECTION + Vec3d m_displacement; +#else Vec3d m_position; +#endif // ENABLE_EXTENDED_SELECTION Vec3d m_starting_drag_position; Vec3d m_starting_box_center; Vec3d m_starting_box_bottom_center; @@ -326,8 +338,12 @@ class GLGizmoMove3D : public GLGizmoBase public: explicit GLGizmoMove3D(GLCanvas3D& parent); +#if ENABLE_EXTENDED_SELECTION + const Vec3d& get_displacement() const { return m_displacement; } +#else const Vec3d& get_position() const { return m_position; } void set_position(const Vec3d& position) { m_position = position; } +#endif // ENABLE_EXTENDED_SELECTION protected: virtual bool on_init(); diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index e9fc6a3d00..0ea56710c6 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -1036,7 +1036,9 @@ void ObjectList::add_object_to_list(const std::string &name, ModelObject* model_ { wxString item_name = name; auto item = m_objects_model->Add(item_name, model_object->instances.size()); +#if !ENABLE_EXTENDED_SELECTION m_objects_ctrl->Select(item); +#endif // !ENABLE_EXTENDED_SELECTION // Add error icon if detected auto-repaire auto stats = model_object->volumes[0]->mesh.stl.stats; diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index 2858cb1068..3522294826 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -262,6 +262,51 @@ void ObjectManipulation::update_settings_list() /*wxGetApp().sidebar().*/parent->GetParent()->Layout(); } +#if ENABLE_EXTENDED_SELECTION +void ObjectManipulation::update_settings_value(const GLCanvas3D::Selection& selection) +{ + int object_idx = -1; + int instance_idx = -1; + if (selection.is_single_full_instance(object_idx, instance_idx)) + { + // all volumes in the selection belongs to the same instance, any of them contains the needed data, so we take the first + const GLCanvas3D::Selection::IndicesList& idxs = selection.get_volume_idxs(); + update_position_values(selection.get_volume(*idxs.begin())->get_offset()); + m_og->enable(); + } + else if (selection.is_wipe_tower()) + { + // the selection contains a single volume + const GLCanvas3D::Selection::IndicesList& idxs = selection.get_volume_idxs(); + update_position_values(selection.get_volume(*idxs.begin())->get_offset()); + m_og->enable(); + } + else if (selection.is_modifier()) + { + // the selection contains a single volume + const GLCanvas3D::Selection::IndicesList& idxs = selection.get_volume_idxs(); + update_position_values(selection.get_volume(*idxs.begin())->get_offset()); + m_og->enable(); + } + else + reset_settings_value(); +} + +void ObjectManipulation::reset_settings_value() +{ + m_og->set_value("position_x", 0); + m_og->set_value("position_y", 0); + m_og->set_value("position_z", 0); + m_og->set_value("scale_x", 0); + m_og->set_value("scale_y", 0); + m_og->set_value("scale_z", 0); + m_og->set_value("rotation_x", 0); + m_og->set_value("rotation_y", 0); + m_og->set_value("rotation_z", 0); + m_og->disable(); +} +#endif // ENABLE_EXTENDED_SELECTION + void ObjectManipulation::update_values() { int selection = ol_selection(); diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.hpp b/src/slic3r/GUI/GUI_ObjectManipulation.hpp index 19683362f6..2a9ec004e1 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.hpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.hpp @@ -6,6 +6,9 @@ #include #include "Preset.hpp" +#if ENABLE_EXTENDED_SELECTION +#include "GLCanvas3D.hpp" +#endif // ENABLE_EXTENDED_SELECTION class wxBoxSizer; @@ -44,6 +47,11 @@ public: int ol_selection(); void update_settings_list(); +#if ENABLE_EXTENDED_SELECTION + void update_settings_value(const GLCanvas3D::Selection& selection); + void reset_settings_value(); +#endif // ENABLE_EXTENDED_SELECTION + void update_values(); // update position values displacements or "gizmos" void update_position_values(); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index d76a0ca1bf..cd5a1fc122 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -617,7 +617,9 @@ struct Plater::priv priv(Plater *q, MainFrame *main_frame); +#if !ENABLE_EXTENDED_SELECTION std::vector collect_selections(); +#endif // !ENABLE_EXTENDED_SELECTION void update(bool force_autocenter = false); void update_ui_from_settings(); ProgressStatusBar* statusbar(); @@ -671,8 +673,10 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) : _3DScene::enable_picking(canvas3D, true); _3DScene::enable_moving(canvas3D, true); // XXX: more config from 3D.pm +#if !ENABLE_EXTENDED_SELECTION _3DScene::set_select_by(canvas3D, "object"); _3DScene::set_drag_by(canvas3D, "instance"); +#endif // !ENABLE_EXTENDED_SELECTION _3DScene::set_model(canvas3D, &model); _3DScene::set_print(canvas3D, &print); _3DScene::set_config(canvas3D, config); @@ -735,6 +739,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) : q->Layout(); } +#if !ENABLE_EXTENDED_SELECTION std::vector Plater::priv::collect_selections() { std::vector res; @@ -743,6 +748,7 @@ std::vector Plater::priv::collect_selections() } return res; } +#endif // !ENABLE_EXTENDED_SELECTION void Plater::priv::update(bool force_autocenter) { @@ -758,8 +764,10 @@ void Plater::priv::update(bool force_autocenter) // stop_background_process(); // TODO print.reload_model_instances(); +#if !ENABLE_EXTENDED_SELECTION const auto selections = collect_selections(); _3DScene::set_objects_selections(canvas3D, selections); +#endif // !ENABLE_EXTENDED_SELECTION _3DScene::reload_scene(canvas3D, false); preview->reset_gcode_preview_data(); preview->reload_print(); @@ -999,7 +1007,9 @@ void Plater::priv::on_notebook_changed(wxBookCtrlEvent&) const auto current_id = notebook->GetCurrentPage()->GetId(); if (current_id == canvas3D->GetId()) { if (_3DScene::is_reload_delayed(canvas3D)) { +#if !ENABLE_EXTENDED_SELECTION _3DScene::set_objects_selections(canvas3D, collect_selections()); +#endif // !ENABLE_EXTENDED_SELECTION _3DScene::reload_scene(canvas3D, true); } // sets the canvas as dirty to force a render at the 1st idle event (wxWidgets IsShownOnScreen() is buggy and cannot be used reliably) From 9ae6d115a253e9ee186836f820dcc902c4ca3b42 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Mon, 8 Oct 2018 15:17:36 +0200 Subject: [PATCH 065/186] New selection -> removed obsolete methods\n+\nFixed a few compile warnings --- src/libslic3r/Format/3mf.cpp | 6 +++--- src/libslic3r/Format/AMF.cpp | 2 +- src/libslic3r/Format/PRUS.cpp | 8 ++++---- src/libslic3r/GCode/Analyzer.cpp | 2 +- src/libslic3r/GCodeTimeEstimator.cpp | 6 +++--- src/slic3r/GUI/3DScene.cpp | 16 +++++++++------- src/slic3r/GUI/3DScene.hpp | 2 ++ src/slic3r/GUI/GLCanvas3D.cpp | 12 ++++-------- src/slic3r/GUI/GLCanvas3D.hpp | 2 ++ src/slic3r/GUI/GLCanvas3DManager.cpp | 2 ++ src/slic3r/GUI/GLCanvas3DManager.hpp | 2 ++ src/slic3r/GUI/GLShader.cpp | 4 ++-- src/slic3r/GUI/GLToolbar.cpp | 2 ++ src/slic3r/GUI/GLToolbar.hpp | 2 ++ 14 files changed, 39 insertions(+), 29 deletions(-) diff --git a/src/libslic3r/Format/3mf.cpp b/src/libslic3r/Format/3mf.cpp index ee66fd293d..90817fadc9 100644 --- a/src/libslic3r/Format/3mf.cpp +++ b/src/libslic3r/Format/3mf.cpp @@ -1350,7 +1350,7 @@ namespace Slic3r { return false; } - m_curr_config.volume_id = object->second.volumes.size(); + m_curr_config.volume_id = (int)object->second.volumes.size(); unsigned int first_triangle_id = (unsigned int)get_attribute_value_int(attributes, num_attributes, FIRST_TRIANGLE_ID_ATTR); unsigned int last_triangle_id = (unsigned int)get_attribute_value_int(attributes, num_attributes, LAST_TRIANGLE_ID_ATTR); @@ -1408,7 +1408,7 @@ namespace Slic3r { return false; } - unsigned int geo_tri_count = geometry.triangles.size() / 3; + unsigned int geo_tri_count = (unsigned int)geometry.triangles.size() / 3; for (const ObjectMetadata::VolumeMetadata& volume_data : volumes) { @@ -1429,7 +1429,7 @@ namespace Slic3r { unsigned int src_start_id = volume_data.first_triangle_id * 3; - for (size_t i = 0; i < triangles_count; ++i) + for (unsigned int i = 0; i < triangles_count; ++i) { unsigned int ii = i * 3; stl_facet& facet = stl.facet_start[i]; diff --git a/src/libslic3r/Format/AMF.cpp b/src/libslic3r/Format/AMF.cpp index 68c747cdaf..96befdabfd 100644 --- a/src/libslic3r/Format/AMF.cpp +++ b/src/libslic3r/Format/AMF.cpp @@ -911,7 +911,7 @@ bool store_amf(const char *path, Model *model, Print* print, bool export_print_c if (volume->is_modifier()) stream << " 1\n"; stream << " " << ModelVolume::type_to_string(volume->type()) << "\n"; - for (int i = 0; i < volume->mesh.stl.stats.number_of_facets; ++i) { + for (int i = 0; i < (int)volume->mesh.stl.stats.number_of_facets; ++i) { stream << " \n"; for (int j = 0; j < 3; ++j) stream << " " << volume->mesh.stl.v_indices[i].vertex[j] + vertices_offset << "\n"; diff --git a/src/libslic3r/Format/PRUS.cpp b/src/libslic3r/Format/PRUS.cpp index d86016361a..b68726a377 100644 --- a/src/libslic3r/Format/PRUS.cpp +++ b/src/libslic3r/Format/PRUS.cpp @@ -37,7 +37,7 @@ static_assert(sizeof(StlHeader) == 84, "StlHeader size not correct"); class LineReader { public: - LineReader(std::vector &data) : m_buffer(data), m_pos(0), m_len(data.size()) {} + LineReader(std::vector &data) : m_buffer(data), m_pos(0), m_len((int)data.size()) {} const char* next_line() { // Skip empty lines. @@ -154,7 +154,7 @@ static void extract_model_from_archive( #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM instance_offset = Vec3d((double)(position[0] - zero[0]), (double)(position[1] - zero[1]), (double)(position[2] - zero[2])); // CHECK_ME -> Is the following correct ? - trafo[2][3] = position[2] / instance_scaling_factor(2); + trafo[2][3] = position[2] / (float)instance_scaling_factor(2); #else instance_offset(0) = position[0] - zero[0]; instance_offset(1) = position[1] - zero[1]; @@ -291,8 +291,8 @@ static void extract_model_from_archive( if (! facets.empty() && solid_name.empty()) { stl_file &stl = mesh.stl; stl.stats.type = inmemory; - stl.stats.number_of_facets = facets.size(); - stl.stats.original_num_facets = facets.size(); + stl.stats.number_of_facets = (uint32_t)facets.size(); + stl.stats.original_num_facets = (int)facets.size(); stl_allocate(&stl); memcpy((void*)stl.facet_start, facets.data(), facets.size() * 50); stl_get_size(&stl); diff --git a/src/libslic3r/GCode/Analyzer.cpp b/src/libslic3r/GCode/Analyzer.cpp index 51d5b1a067..e3cd67e7cc 100644 --- a/src/libslic3r/GCode/Analyzer.cpp +++ b/src/libslic3r/GCode/Analyzer.cpp @@ -698,7 +698,7 @@ void GCodeAnalyzer::_calc_gcode_preview_extrusion_layers(GCodePreviewData& previ // update current values data = move.data; - z = move.start_position.z(); + z = (float)move.start_position.z(); volumetric_rate = move.data.feedrate * (float)move.data.mm3_per_mm; height_range.update_from(move.data.height); width_range.update_from(move.data.width); diff --git a/src/libslic3r/GCodeTimeEstimator.cpp b/src/libslic3r/GCodeTimeEstimator.cpp index f97265ee3c..4bfd5d63fe 100644 --- a/src/libslic3r/GCodeTimeEstimator.cpp +++ b/src/libslic3r/GCodeTimeEstimator.cpp @@ -484,14 +484,14 @@ namespace Slic3r { { _state.filament_load_times.clear(); for (double t : filament_load_times) - _state.filament_load_times.push_back(t); + _state.filament_load_times.push_back((float)t); } void GCodeTimeEstimator::set_filament_unload_times(const std::vector &filament_unload_times) { _state.filament_unload_times.clear(); for (double t : filament_unload_times) - _state.filament_unload_times.push_back(t); + _state.filament_unload_times.push_back((float)t); } float GCodeTimeEstimator::get_filament_load_time(unsigned int id_extruder) @@ -731,7 +731,7 @@ namespace Slic3r { #endif // ENABLE_MOVE_STATS } - _last_st_synchronized_block_id = _blocks.size() - 1; + _last_st_synchronized_block_id = (int)_blocks.size() - 1; // The additional time has been consumed (added to the total time), reset it to zero. set_additional_time(0.); } diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index 4907a5c360..9ffff22856 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -36,7 +36,7 @@ void GLIndexedVertexArray::load_mesh_flat_shading(const TriangleMesh &mesh) this->vertices_and_normals_interleaved.reserve(this->vertices_and_normals_interleaved.size() + 3 * 3 * 2 * mesh.facets_count()); - for (int i = 0; i < mesh.stl.stats.number_of_facets; ++ i) { + for (int i = 0; i < (int)mesh.stl.stats.number_of_facets; ++i) { const stl_facet &facet = mesh.stl.facet_start[i]; for (int j = 0; j < 3; ++ j) this->push_geometry(facet.vertex[j](0), facet.vertex[j](1), facet.vertex[j](2), facet.normal(0), facet.normal(1), facet.normal(2)); @@ -52,7 +52,7 @@ void GLIndexedVertexArray::load_mesh_full_shading(const TriangleMesh &mesh) this->vertices_and_normals_interleaved.reserve(this->vertices_and_normals_interleaved.size() + 3 * 3 * 2 * mesh.facets_count()); unsigned int vertices_count = 0; - for (int i = 0; i < mesh.stl.stats.number_of_facets; ++i) { + for (int i = 0; i < (int)mesh.stl.stats.number_of_facets; ++i) { const stl_facet &facet = mesh.stl.facet_start[i]; for (int j = 0; j < 3; ++j) this->push_geometry(facet.vertex[j](0), facet.vertex[j](1), facet.vertex[j](2), facet.normal(0), facet.normal(1), facet.normal(2)); @@ -244,7 +244,7 @@ void GLVolume::set_render_color(float r, float g, float b, float a) void GLVolume::set_render_color(const float* rgba, unsigned int size) { size = std::min((unsigned int)4, size); - for (int i = 0; i < size; ++i) + for (unsigned int i = 0; i < size; ++i) { render_color[i] = rgba[i]; } @@ -802,9 +802,9 @@ int GLVolumeCollection::load_wipe_tower_preview( // edge has y=0 and centerline of the back edge has y=depth: Pointf3s points; std::vector facets; - float out_points_idx[][3] = {{0, -depth, 0}, {0, 0, 0}, {38.453, 0, 0}, {61.547, 0, 0}, {100, 0, 0}, {100, -depth, 0}, {55.7735, -10, 0}, {44.2265, 10, 0}, - {38.453, 0, 1}, {0, 0, 1}, {0, -depth, 1}, {100, -depth, 1}, {100, 0, 1}, {61.547, 0, 1}, {55.7735, -10, 1}, {44.2265, 10, 1}}; - int out_facets_idx[][3] = {{0, 1, 2}, {3, 4, 5}, {6, 5, 0}, {3, 5, 6}, {6, 2, 7}, {6, 0, 2}, {8, 9, 10}, {11, 12, 13}, {10, 11, 14}, {14, 11, 13}, {15, 8, 14}, + float out_points_idx[][3] = { { 0, -depth, 0 }, { 0, 0, 0 }, { 38.453f, 0, 0 }, { 61.547f, 0, 0 }, { 100.0f, 0, 0 }, { 100.0f, -depth, 0 }, { 55.7735f, -10.0f, 0 }, { 44.2265f, 10.0f, 0 }, + { 38.453f, 0, 1 }, { 0, 0, 1 }, { 0, -depth, 1 }, { 100.0f, -depth, 1 }, { 100.0f, 0, 1 }, { 61.547f, 0, 1 }, { 55.7735f, -10.0f, 1 }, { 44.2265f, 10.0f, 1 } }; + int out_facets_idx[][3] = { { 0, 1, 2 }, { 3, 4, 5 }, { 6, 5, 0 }, { 3, 5, 6 }, { 6, 2, 7 }, { 6, 0, 2 }, { 8, 9, 10 }, { 11, 12, 13 }, { 10, 11, 14 }, { 14, 11, 13 }, { 15, 8, 14 }, {8, 10, 14}, {3, 12, 4}, {3, 13, 12}, {6, 13, 3}, {6, 14, 13}, {7, 14, 6}, {7, 15, 14}, {2, 15, 7}, {2, 8, 15}, {1, 8, 2}, {1, 9, 8}, {0, 9, 1}, {0, 10, 9}, {5, 10, 0}, {5, 11, 10}, {4, 11, 5}, {4, 12, 11}}; for (int i=0;i<16;++i) @@ -1032,7 +1032,7 @@ void GLVolumeCollection::update_colors_by_extruder(const DynamicPrintConfig* con continue; int extruder_id = volume->extruder_id - 1; - if ((extruder_id < 0) || ((unsigned int)colors.size() <= extruder_id)) + if ((extruder_id < 0) || ((int)colors.size() <= extruder_id)) extruder_id = 0; const Color& color = colors[extruder_id]; @@ -1837,6 +1837,7 @@ void _3DScene::reset_volumes(wxGLCanvas* canvas) s_canvas_mgr.reset_volumes(canvas); } +#if !ENABLE_EXTENDED_SELECTION void _3DScene::deselect_volumes(wxGLCanvas* canvas) { s_canvas_mgr.deselect_volumes(canvas); @@ -1851,6 +1852,7 @@ void _3DScene::update_volumes_selection(wxGLCanvas* canvas, const std::vector& selections); +#endif // !ENABLE_EXTENDED_SELECTION static int check_volumes_outside_state(wxGLCanvas* canvas, const DynamicPrintConfig* config); static bool move_volume_up(wxGLCanvas* canvas, unsigned int id); static bool move_volume_down(wxGLCanvas* canvas, unsigned int id); diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 6191c1d63b..51229f1391 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -414,7 +414,7 @@ void GLCanvas3D::Bed::_calc_gridlines(const ExPolygon& poly, const BoundingBox& } // clip with a slightly grown expolygon because our lines lay on the contours and may get erroneously clipped - Lines gridlines = to_lines(intersection_pl(axes_lines, offset(poly, SCALED_EPSILON))); + Lines gridlines = to_lines(intersection_pl(axes_lines, offset(poly, (float)SCALED_EPSILON))); // append bed contours Lines contour_lines = to_lines(poly); @@ -644,7 +644,7 @@ bool GLCanvas3D::CuttingPlane::set(float z, const ExPolygons& polygons) m_z = z; // grow slices in order to display them better - ExPolygons expolygons = offset_ex(polygons, scale_(0.1)); + ExPolygons expolygons = offset_ex(polygons, (float)scale_(0.1)); Lines lines = to_lines(expolygons); return m_lines.set_from_lines(lines, m_z); } @@ -2621,32 +2621,28 @@ void GLCanvas3D::reset_volumes() _reset_warning_texture(); } +#if !ENABLE_EXTENDED_SELECTION void GLCanvas3D::deselect_volumes() { -#if !ENABLE_EXTENDED_SELECTION for (GLVolume* vol : m_volumes.volumes) { if (vol != nullptr) vol->selected = false; } -#endif // !ENABLE_EXTENDED_SELECTION } void GLCanvas3D::select_volume(unsigned int id) { -#if !ENABLE_EXTENDED_SELECTION if (id < (unsigned int)m_volumes.volumes.size()) { GLVolume* vol = m_volumes.volumes[id]; if (vol != nullptr) vol->selected = true; } -#endif // !ENABLE_EXTENDED_SELECTION } void GLCanvas3D::update_volumes_selection(const std::vector& selections) { -#if !ENABLE_EXTENDED_SELECTION if (m_model == nullptr) return; @@ -2664,8 +2660,8 @@ void GLCanvas3D::update_volumes_selection(const std::vector& selections) } } } -#endif // !ENABLE_EXTENDED_SELECTION } +#endif // !ENABLE_EXTENDED_SELECTION int GLCanvas3D::check_volumes_outside_state(const DynamicPrintConfig* config) const { diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 5b5df1851d..d900a2621f 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -693,9 +693,11 @@ public: unsigned int get_volumes_count() const; void reset_volumes(); +#if !ENABLE_EXTENDED_SELECTION void deselect_volumes(); void select_volume(unsigned int id); void update_volumes_selection(const std::vector& selections); +#endif // !ENABLE_EXTENDED_SELECTION int check_volumes_outside_state(const DynamicPrintConfig* config) const; bool move_volume_up(unsigned int id); bool move_volume_down(unsigned int id); diff --git a/src/slic3r/GUI/GLCanvas3DManager.cpp b/src/slic3r/GUI/GLCanvas3DManager.cpp index 1258c48947..87909110e1 100644 --- a/src/slic3r/GUI/GLCanvas3DManager.cpp +++ b/src/slic3r/GUI/GLCanvas3DManager.cpp @@ -246,6 +246,7 @@ void GLCanvas3DManager::reset_volumes(wxGLCanvas* canvas) it->second->reset_volumes(); } +#if !ENABLE_EXTENDED_SELECTION void GLCanvas3DManager::deselect_volumes(wxGLCanvas* canvas) { CanvasesMap::iterator it = _get_canvas(canvas); @@ -266,6 +267,7 @@ void GLCanvas3DManager::update_volumes_selection(wxGLCanvas* canvas, const std:: if (it != m_canvases.end()) it->second->update_volumes_selection(selections); } +#endif // !ENABLE_EXTENDED_SELECTION int GLCanvas3DManager::check_volumes_outside_state(wxGLCanvas* canvas, const DynamicPrintConfig* config) const { diff --git a/src/slic3r/GUI/GLCanvas3DManager.hpp b/src/slic3r/GUI/GLCanvas3DManager.hpp index c64e213503..ca882d4aef 100644 --- a/src/slic3r/GUI/GLCanvas3DManager.hpp +++ b/src/slic3r/GUI/GLCanvas3DManager.hpp @@ -87,9 +87,11 @@ public: unsigned int get_volumes_count(wxGLCanvas* canvas) const; void reset_volumes(wxGLCanvas* canvas); +#if !ENABLE_EXTENDED_SELECTION void deselect_volumes(wxGLCanvas* canvas); void select_volume(wxGLCanvas* canvas, unsigned int id); void update_volumes_selection(wxGLCanvas* canvas, const std::vector& selections); +#endif // !ENABLE_EXTENDED_SELECTION int check_volumes_outside_state(wxGLCanvas* canvas, const DynamicPrintConfig* config) const; bool move_volume_up(wxGLCanvas* canvas, unsigned int id); bool move_volume_down(wxGLCanvas* canvas, unsigned int id); diff --git a/src/slic3r/GUI/GLShader.cpp b/src/slic3r/GUI/GLShader.cpp index e2995f7c3e..623e02a057 100644 --- a/src/slic3r/GUI/GLShader.cpp +++ b/src/slic3r/GUI/GLShader.cpp @@ -135,7 +135,7 @@ bool GLShader::load_from_file(const char* fragment_shader_filename, const char* return false; vs.seekg(0, vs.end); - int file_length = vs.tellg(); + int file_length = (int)vs.tellg(); vs.seekg(0, vs.beg); std::string vertex_shader(file_length, '\0'); vs.read(const_cast(vertex_shader.data()), file_length); @@ -149,7 +149,7 @@ bool GLShader::load_from_file(const char* fragment_shader_filename, const char* return false; fs.seekg(0, fs.end); - file_length = fs.tellg(); + file_length = (int)fs.tellg(); fs.seekg(0, fs.beg); std::string fragment_shader(file_length, '\0'); fs.read(const_cast(fragment_shader.data()), file_length); diff --git a/src/slic3r/GUI/GLToolbar.cpp b/src/slic3r/GUI/GLToolbar.cpp index f2d882e22b..4792383688 100644 --- a/src/slic3r/GUI/GLToolbar.cpp +++ b/src/slic3r/GUI/GLToolbar.cpp @@ -26,7 +26,9 @@ wxDEFINE_EVENT(EVT_GLTOOLBAR_SPLIT, SimpleEvent); wxDEFINE_EVENT(EVT_GLTOOLBAR_CUT, SimpleEvent); wxDEFINE_EVENT(EVT_GLTOOLBAR_SETTINGS, SimpleEvent); wxDEFINE_EVENT(EVT_GLTOOLBAR_LAYERSEDITING, SimpleEvent); +#if !ENABLE_EXTENDED_SELECTION wxDEFINE_EVENT(EVT_GLTOOLBAR_SELECTBYPARTS, SimpleEvent); +#endif // !ENABLE_EXTENDED_SELECTION GLToolbarItem::Data::Data() diff --git a/src/slic3r/GUI/GLToolbar.hpp b/src/slic3r/GUI/GLToolbar.hpp index 43097c007c..dc4d10f376 100644 --- a/src/slic3r/GUI/GLToolbar.hpp +++ b/src/slic3r/GUI/GLToolbar.hpp @@ -26,7 +26,9 @@ wxDECLARE_EVENT(EVT_GLTOOLBAR_SPLIT, SimpleEvent); wxDECLARE_EVENT(EVT_GLTOOLBAR_CUT, SimpleEvent); wxDECLARE_EVENT(EVT_GLTOOLBAR_SETTINGS, SimpleEvent); wxDECLARE_EVENT(EVT_GLTOOLBAR_LAYERSEDITING, SimpleEvent); +#if !ENABLE_EXTENDED_SELECTION wxDECLARE_EVENT(EVT_GLTOOLBAR_SELECTBYPARTS, SimpleEvent); +#endif // !ENABLE_EXTENDED_SELECTION class GLToolbarItem { From 99fe5761d8fca6349b924cb5c02198aed39ddb94 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Mon, 8 Oct 2018 16:05:55 +0200 Subject: [PATCH 066/186] New selection -> removed obsolete parameters from GLVolumeCollection::load_object() --- src/libslic3r/Technologies.hpp | 2 +- src/slic3r/GUI/3DScene.cpp | 9 +++++++++ src/slic3r/GUI/3DScene.hpp | 9 +++++++++ src/slic3r/GUI/GLCanvas3D.cpp | 6 +++++- 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index 877f365db5..77802d811e 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -5,7 +5,7 @@ #define ENABLE_1_42_0 1 // Add z coordinate to model instances' offset -// Add x and y rotation components to model instances' offset +// Add x and y rotation components to model instances' rotation // Add scaling factors for all the three axes to model instances #define ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM (1 && ENABLE_1_42_0) // Add double click on gizmo grabbers to reset transformation components to their default value diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index 9ffff22856..2ae900e002 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -693,6 +693,14 @@ void GLVolume::generate_layer_height_texture(const PrintObject *print_object, bo #define LAYER_HEIGHT_TEXTURE_WIDTH 1024 #define LAYER_HEIGHT_TEXTURE_HEIGHT 1024 +#if ENABLE_EXTENDED_SELECTION +std::vector GLVolumeCollection::load_object( + const ModelObject *model_object, + int obj_idx, + const std::vector &instance_idxs, + const std::string &color_by, + bool use_VBOs) +#else std::vector GLVolumeCollection::load_object( const ModelObject *model_object, int obj_idx, @@ -701,6 +709,7 @@ std::vector GLVolumeCollection::load_object( const std::string &select_by, const std::string &drag_by, bool use_VBOs) +#endif // ENABLE_EXTENDED_SELECTION { static float colors[4][4] = { { 1.0f, 1.0f, 0.0f, 1.f }, diff --git a/src/slic3r/GUI/3DScene.hpp b/src/slic3r/GUI/3DScene.hpp index ffec0fae6a..09f425ba0b 100644 --- a/src/slic3r/GUI/3DScene.hpp +++ b/src/slic3r/GUI/3DScene.hpp @@ -437,6 +437,14 @@ public: GLVolumeCollection() {}; ~GLVolumeCollection() { clear(); }; +#if ENABLE_EXTENDED_SELECTION + std::vector load_object( + const ModelObject *model_object, + int obj_idx, + const std::vector &instance_idxs, + const std::string &color_by, + bool use_VBOs); +#else std::vector load_object( const ModelObject *model_object, int obj_idx, @@ -445,6 +453,7 @@ public: const std::string &select_by, const std::string &drag_by, bool use_VBOs); +#endif // ENABLE_EXTENDED_SELECTION int load_wipe_tower_preview( int obj_idx, float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool use_VBOs, bool size_unknown, float brim_width); diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 51229f1391..116d8cb3bd 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -3123,7 +3123,7 @@ std::vector GLCanvas3D::load_object(const ModelObject& model_object, int ob } } #if ENABLE_EXTENDED_SELECTION - return m_volumes.load_object(&model_object, obj_idx, instance_idxs, m_color_by, "object", "object", m_use_VBOs && m_initialized); + return m_volumes.load_object(&model_object, obj_idx, instance_idxs, m_color_by, m_use_VBOs && m_initialized); #else return m_volumes.load_object(&model_object, obj_idx, instance_idxs, m_color_by, m_select_by, m_drag_by, m_use_VBOs && m_initialized); #endif // ENABLE_EXTENDED_SELECTION @@ -6025,7 +6025,11 @@ void GLCanvas3D::_load_shells() instance_ids[i] = i; } +#if ENABLE_EXTENDED_SELECTION + m_volumes.load_object(model_obj, object_id, instance_ids, "object", m_use_VBOs && m_initialized); +#else m_volumes.load_object(model_obj, object_id, instance_ids, "object", "object", "object", m_use_VBOs && m_initialized); +#endif // ENABLE_EXTENDED_SELECTION ++object_id; } From 1006cd976e9df9b363123e8eb8fdf913398f6057 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Mon, 8 Oct 2018 16:27:38 +0200 Subject: [PATCH 067/186] Fixed events OBJECT_SETTINGS_CHANGED_EVENT , OBJECT_REMOVE_EVENT and UPDATE_SCENE_EVENT + changed ctor of ObjList + deleted unusable code from Tab.cpp --- src/slic3r/GUI/Event.hpp | 2 +- src/slic3r/GUI/GUI_App.cpp | 5 + src/slic3r/GUI/GUI_App.hpp | 1 + src/slic3r/GUI/GUI_ObjectList.cpp | 144 +++++++++--------- src/slic3r/GUI/GUI_ObjectList.hpp | 14 +- src/slic3r/GUI/GUI_ObjectManipulation.cpp | 4 +- src/slic3r/GUI/MainFrame.cpp | 19 --- src/slic3r/GUI/Plater.cpp | 45 +++++- src/slic3r/GUI/Plater.hpp | 1 + src/slic3r/GUI/Tab.cpp | 173 +--------------------- src/slic3r/GUI/Tab.hpp | 7 - 11 files changed, 123 insertions(+), 292 deletions(-) diff --git a/src/slic3r/GUI/Event.hpp b/src/slic3r/GUI/Event.hpp index 2ae9fd154d..429ef99b02 100644 --- a/src/slic3r/GUI/Event.hpp +++ b/src/slic3r/GUI/Event.hpp @@ -1,7 +1,7 @@ #ifndef slic3r_Events_hpp_ #define slic3r_Events_hpp_ - +#include #include diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 1862bab8a5..50de1cb4a2 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -669,6 +669,11 @@ ObjectList* GUI_App::obj_list() return sidebar().obj_list(); } +Plater* GUI_App::plater() +{ + return mainframe->m_plater; +} + ModelObjectPtrs* GUI_App::model_objects() { return &mainframe->m_plater->model().objects; diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index e5ea77a38c..1e4d130048 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -142,6 +142,7 @@ public: Sidebar& sidebar(); ObjectManipulation* obj_manipul(); ObjectList* obj_list(); + Plater* plater(); std::vector *model_objects(); AppConfig* app_config{ nullptr }; diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index e9fc6a3d00..589f4ce8bc 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -18,7 +18,7 @@ namespace GUI { ObjectList::ObjectList(wxWindow* parent) : - m_parent(parent) + wxDataViewCtrl(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize) { // Fill CATEGORY_ICON { @@ -39,24 +39,24 @@ ObjectList::ObjectList(wxWindow* parent) : create_objects_ctrl(); // describe control behavior - m_objects_ctrl->Bind(wxEVT_DATAVIEW_SELECTION_CHANGED, [this](wxEvent& event) { + Bind(wxEVT_DATAVIEW_SELECTION_CHANGED, [this](wxEvent& event) { object_ctrl_selection_changed(); #ifndef __WXMSW__ set_tooltip_for_item(get_mouse_position_in_control()); #endif //__WXMSW__ }); - m_objects_ctrl->Bind(wxEVT_DATAVIEW_ITEM_CONTEXT_MENU, [this](wxDataViewEvent& event) { + Bind(wxEVT_DATAVIEW_ITEM_CONTEXT_MENU, [this](wxDataViewEvent& event) { object_ctrl_context_menu(); }); - m_objects_ctrl->Bind(wxEVT_CHAR, [this](wxKeyEvent& event) { object_ctrl_key_event(event); }); // doesn't work on OSX + Bind(wxEVT_CHAR, [this](wxKeyEvent& event) { object_ctrl_key_event(event); }); // doesn't work on OSX #ifdef __WXMSW__ // Extruder value changed - m_objects_ctrl->Bind(wxEVT_CHOICE, [this](wxCommandEvent& event) { update_extruder_in_config(event.GetString()); }); + Bind(wxEVT_CHOICE, [this](wxCommandEvent& event) { update_extruder_in_config(event.GetString()); }); - m_objects_ctrl->GetMainWindow()->Bind(wxEVT_MOTION, [this](wxMouseEvent& event) { + GetMainWindow()->Bind(wxEVT_MOTION, [this](wxMouseEvent& event) { set_tooltip_for_item(event.GetPosition()); event.Skip(); }); @@ -65,9 +65,9 @@ ObjectList::ObjectList(wxWindow* parent) : m_objects_ctrl->Bind(wxEVT_DATAVIEW_ITEM_VALUE_CHANGED, [this](wxDataViewEvent& e) { object_ctrl_item_value_change(e); }); #endif //__WXMSW__ - m_objects_ctrl->Bind(wxEVT_DATAVIEW_ITEM_BEGIN_DRAG, [this](wxDataViewEvent& e) {on_begin_drag(e); }); - m_objects_ctrl->Bind(wxEVT_DATAVIEW_ITEM_DROP_POSSIBLE, [this](wxDataViewEvent& e) {on_drop_possible(e); }); - m_objects_ctrl->Bind(wxEVT_DATAVIEW_ITEM_DROP, [this](wxDataViewEvent& e) {on_drop(e); }); + Bind(wxEVT_DATAVIEW_ITEM_BEGIN_DRAG, [this](wxDataViewEvent& e) {on_begin_drag(e); }); + Bind(wxEVT_DATAVIEW_ITEM_DROP_POSSIBLE, [this](wxDataViewEvent& e) {on_drop_possible(e); }); + Bind(wxEVT_DATAVIEW_ITEM_DROP, [this](wxDataViewEvent& e) {on_drop(e); }); } ObjectList::~ObjectList() @@ -78,33 +78,32 @@ ObjectList::~ObjectList() void ObjectList::create_objects_ctrl() { - m_objects_ctrl = new wxDataViewCtrl(m_parent, wxID_ANY, wxDefaultPosition, wxDefaultSize); - m_objects_ctrl->SetMinSize(wxSize(-1, 150)); // TODO - Set correct height according to the opened/closed objects + SetMinSize(wxSize(-1, 150)); // TODO - Set correct height according to the opened/closed objects m_sizer = new wxBoxSizer(wxVERTICAL); - m_sizer->Add(m_objects_ctrl, 1, wxGROW | wxLEFT, 20); + m_sizer->Add(this, 1, wxGROW | wxLEFT, 20); m_objects_model = new PrusaObjectDataViewModel; - m_objects_ctrl->AssociateModel(m_objects_model); + AssociateModel(m_objects_model); #if wxUSE_DRAG_AND_DROP && wxUSE_UNICODE - m_objects_ctrl->EnableDragSource(wxDF_UNICODETEXT); - m_objects_ctrl->EnableDropTarget(wxDF_UNICODETEXT); + EnableDragSource(wxDF_UNICODETEXT); + EnableDropTarget(wxDF_UNICODETEXT); #endif // wxUSE_DRAG_AND_DROP && wxUSE_UNICODE // column 0(Icon+Text) of the view control: // And Icon can be consisting of several bitmaps - m_objects_ctrl->AppendColumn(new wxDataViewColumn(_(L("Name")), new PrusaBitmapTextRenderer(), + AppendColumn(new wxDataViewColumn(_(L("Name")), new PrusaBitmapTextRenderer(), 0, 200, wxALIGN_LEFT, wxDATAVIEW_COL_RESIZABLE)); // column 1 of the view control: - m_objects_ctrl->AppendTextColumn(_(L("Copy")), 1, wxDATAVIEW_CELL_INERT, 45, + AppendTextColumn(_(L("Copy")), 1, wxDATAVIEW_CELL_INERT, 45, wxALIGN_CENTER_HORIZONTAL, wxDATAVIEW_COL_RESIZABLE); // column 2 of the view control: - m_objects_ctrl->AppendColumn(create_objects_list_extruder_column(4)); + AppendColumn(create_objects_list_extruder_column(4)); // column 3 of the view control: - m_objects_ctrl->AppendBitmapColumn(" ", 3, wxDATAVIEW_CELL_INERT, 25, + AppendBitmapColumn(" ", 3, wxDATAVIEW_CELL_INERT, 25, wxALIGN_CENTER_HORIZONTAL, wxDATAVIEW_COL_RESIZABLE); } @@ -112,11 +111,11 @@ void ObjectList::set_tooltip_for_item(const wxPoint& pt) { wxDataViewItem item; wxDataViewColumn* col; - m_objects_ctrl->HitTest(pt, item, col); + HitTest(pt, item, col); if (!item) return; if (col->GetTitle() == " ") - m_objects_ctrl->GetMainWindow()->SetToolTip(_(L("Right button click the icon to change the object settings"))); + GetMainWindow()->SetToolTip(_(L("Right button click the icon to change the object settings"))); else if (col->GetTitle() == _("Name") && m_objects_model->GetIcon(item).GetRefData() == m_icon_manifold_warning.GetRefData()) { int obj_idx = m_objects_model->GetIdByItem(item); @@ -148,17 +147,17 @@ void ObjectList::set_tooltip_for_item(const wxPoint& pt) if (is_windows10()) tooltip += _(L("Right button click the icon to fix STL through Netfabb")); - m_objects_ctrl->GetMainWindow()->SetToolTip(tooltip); + GetMainWindow()->SetToolTip(tooltip); } else - m_objects_ctrl->GetMainWindow()->SetToolTip(""); // hide tooltip + GetMainWindow()->SetToolTip(""); // hide tooltip } wxPoint ObjectList::get_mouse_position_in_control() { const wxPoint& pt = wxGetMousePosition(); - wxWindow* win = m_objects_ctrl->GetMainWindow(); - return wxPoint(pt.x - win->GetScreenPosition().x, - pt.y - win->GetScreenPosition().y); +// wxWindow* win = GetMainWindow(); +// wxPoint screen_pos = win->GetScreenPosition(); + return wxPoint(pt.x - /*win->*/GetScreenPosition().x, pt.y - /*win->*/GetScreenPosition().y); } wxDataViewColumn* ObjectList::create_objects_list_extruder_column(int extruders_count) @@ -175,21 +174,21 @@ wxDataViewColumn* ObjectList::create_objects_list_extruder_column(int extruders_ void ObjectList::update_objects_list_extruder_column(int extruders_count) { - if (!m_objects_ctrl) return; // #ys_FIXME + if (!this) return; // #ys_FIXME if (wxGetApp().preset_bundle->printers.get_selected_preset().printer_technology() == ptSLA) extruders_count = 1; // delete old 3rd column - m_objects_ctrl->DeleteColumn(m_objects_ctrl->GetColumn(2)); + DeleteColumn(GetColumn(2)); // insert new created 3rd column - m_objects_ctrl->InsertColumn(2, create_objects_list_extruder_column(extruders_count)); + InsertColumn(2, create_objects_list_extruder_column(extruders_count)); // set show/hide for this column set_extruder_column_hidden(extruders_count <= 1); } void ObjectList::set_extruder_column_hidden(bool hide) { - m_objects_ctrl->GetColumn(2)->SetHidden(hide); + GetColumn(2)->SetHidden(hide); } void ObjectList::update_extruder_in_config(const wxString& selection) @@ -201,7 +200,7 @@ void ObjectList::update_extruder_in_config(const wxString& selection) m_config->set_key_value("extruder", new ConfigOptionInt(extruder)); // #ys_FIXME_events - // call function to update the scene after extruder changing +// wxGetApp().plater()->update(); } void ObjectList::init_icons(){ @@ -231,7 +230,7 @@ void ObjectList::object_ctrl_selection_changed() int obj_idx, vol_idx = -1; obj_idx = m_selected_object_id; - const wxDataViewItem item = m_objects_ctrl->GetSelection(); + const wxDataViewItem item = GetSelection(); if (!item || m_objects_model->GetParent(item) == wxDataViewItem(0)) vol_idx = -1; else { @@ -250,11 +249,11 @@ void ObjectList::object_ctrl_context_menu() wxDataViewItem item; wxDataViewColumn* col; const wxPoint pt = get_mouse_position_in_control(); - m_objects_ctrl->HitTest(pt, item, col); + HitTest(pt, item, col); if (!item) #ifdef __WXOSX__ // #ys_FIXME temporary workaround for OSX // after Yosemite OS X version, HitTest return undefined item - item = m_objects_ctrl->GetSelection(); + item = GetSelection(); if (item) show_context_menu(); else @@ -275,13 +274,13 @@ void ObjectList::object_ctrl_context_menu() /*fix_through_netfabb()*/;// #ys_FIXME } #ifndef __WXMSW__ - m_objects_ctrl->GetMainWindow()->SetToolTip(""); // hide tooltip + GetMainWindow()->SetToolTip(""); // hide tooltip #endif //__WXMSW__ } void ObjectList::show_context_menu() { - const auto item = m_objects_ctrl->GetSelection(); + const auto item = GetSelection(); if (item) { if (m_objects_model->IsSettingsItem(item)) @@ -297,7 +296,7 @@ void ObjectList::show_context_menu() void ObjectList::object_ctrl_key_event(wxKeyEvent& event) { if (event.GetKeyCode() == WXK_TAB) - m_objects_ctrl->Navigate(event.ShiftDown() ? wxNavigationKeyEvent::IsBackward : wxNavigationKeyEvent::IsForward); + Navigate(event.ShiftDown() ? wxNavigationKeyEvent::IsBackward : wxNavigationKeyEvent::IsForward); else if (event.GetKeyCode() == WXK_DELETE #ifdef __WXOSX__ || event.GetKeyCode() == WXK_BACK @@ -382,7 +381,7 @@ void ObjectList::on_drop(wxDataViewEvent &event) if (to_volume_id > from_volume_id) to_volume_id--; #endif // __WXGTK__ - m_objects_ctrl->Select(m_objects_model->ReorganizeChildren(from_volume_id, to_volume_id, + Select(m_objects_model->ReorganizeChildren(from_volume_id, to_volume_id, m_objects_model->GetParent(item))); auto& volumes = (*m_objects)[m_selected_object_id]->volumes; @@ -490,10 +489,10 @@ void ObjectList::get_settings_choice(wxMenu *menu, int id, bool is_part) // Add settings item for object - const auto item = m_objects_ctrl->GetSelection(); + const auto item = GetSelection(); if (item) { const auto settings_item = m_objects_model->HasSettings(item); - m_objects_ctrl->Select(settings_item ? settings_item : + Select(settings_item ? settings_item : m_objects_model->AddSettingsChild(item)); #ifndef __WXOSX__ part_selection_changed(); @@ -644,7 +643,7 @@ wxMenu* ObjectList::create_add_settings_popupmenu(bool is_part) // Load SubObjects (parts and modifiers) void ObjectList::load_subobject(bool is_modifier /*= false*/, bool is_lambda/* = false*/) { - auto item = m_objects_ctrl->GetSelection(); + auto item = GetSelection(); if (!item) return; int obj_idx = -1; @@ -663,7 +662,7 @@ void ObjectList::load_subobject(bool is_modifier /*= false*/, bool is_lambda/* = parts_changed(obj_idx); for (int i = 0; i < part_names.size(); ++i) - m_objects_ctrl->Select(m_objects_model->AddChild(item, part_names.Item(i), + Select(m_objects_model->AddChild(item, part_names.Item(i), is_modifier ? m_icon_modifiermesh : m_icon_solidmesh)); #ifndef __WXOSX__ //#ifdef __WXMSW__ // #ys_FIXME object_ctrl_selection_changed(); @@ -725,7 +724,7 @@ void ObjectList::load_lambda( ModelObject* model_object, wxArrayString& part_names, const bool is_modifier) { - auto dlg = new LambdaObjectDialog(m_objects_ctrl->GetMainWindow()); + auto dlg = new LambdaObjectDialog(GetMainWindow()); if (dlg->ShowModal() == wxID_CANCEL) { return; } @@ -776,7 +775,7 @@ void ObjectList::load_lambda(const std::string& type_name) { if (m_selected_object_id < 0) return; - auto dlg = new LambdaObjectDialog(m_objects_ctrl->GetMainWindow(), type_name); + auto dlg = new LambdaObjectDialog(GetMainWindow(), type_name); if (dlg->ShowModal() == wxID_CANCEL) return; @@ -808,7 +807,7 @@ void ObjectList::load_lambda(const std::string& type_name) m_parts_changed = true; parts_changed(m_selected_object_id); - m_objects_ctrl->Select(m_objects_model->AddChild(m_objects_ctrl->GetSelection(), + Select(m_objects_model->AddChild(GetSelection(), name, m_icon_modifiermesh)); #ifndef __WXOSX__ //#ifdef __WXMSW__ // #ys_FIXME object_ctrl_selection_changed(); @@ -820,7 +819,7 @@ void ObjectList::load_lambda(const std::string& type_name) void ObjectList::del_subobject() { - auto item = m_objects_ctrl->GetSelection(); + auto item = GetSelection(); if (!item) return; const auto volume_id = m_objects_model->GetVolumeIdByItem(item); @@ -832,7 +831,7 @@ void ObjectList::del_subobject() else if (!del_subobject_from_object(volume_id)) return; - m_objects_ctrl->Select(m_objects_model->Delete(item)); + Select(m_objects_model->Delete(item)); part_selection_changed(); } @@ -875,7 +874,7 @@ bool ObjectList::del_subobject_from_object(const int volume_id) void ObjectList::split(const bool split_part) { - const auto item = m_objects_ctrl->GetSelection(); + const auto item = GetSelection(); if (!item || m_selected_object_id < 0) return; ModelVolume* volume; @@ -900,7 +899,7 @@ void ObjectList::split(const bool split_part) model_object->volumes[id]->config.option("extruder")->value : 0, false); - m_objects_ctrl->Expand(parent); + Expand(parent); } else { for (auto id = 0; id < model_object->volumes.size(); id++) @@ -909,7 +908,7 @@ void ObjectList::split(const bool split_part) model_object->volumes[id]->config.has("extruder") ? model_object->volumes[id]->config.option("extruder")->value : 0, false); - m_objects_ctrl->Expand(item); + Expand(item); } m_parts_changed = true; @@ -934,7 +933,7 @@ bool ObjectList::get_volume_by_item(const bool split_part, const wxDataViewItem& bool ObjectList::is_splittable_object(const bool split_part) { - const wxDataViewItem item = m_objects_ctrl->GetSelection(); + const wxDataViewItem item = GetSelection(); if (!item) return false; wxDataViewItemArray children; @@ -956,18 +955,14 @@ bool ObjectList::is_splittable_object(const bool split_part) void ObjectList::parts_changed(int obj_idx) { -// #ys_FIXME_events -// call function to update scene after some changes in ObjectList -// auto event_str = wxString::Format("%d %d %d", obj_idx, -// is_parts_changed() ? 1 : 0, -// is_part_settings_changed() ? 1 : 0); + wxGetApp().mainframe->m_plater->changed_object_settings(obj_idx); } void ObjectList::part_selection_changed() { - auto item = m_objects_ctrl->GetSelection(); + auto item = GetSelection(); int obj_idx = -1; - ConfigOptionsGroup* og = wxGetApp().obj_manipul()->get_og();// get_optgroup(ogFrequentlyObjectSettings); + ConfigOptionsGroup* og = wxGetApp().obj_manipul()->get_og(); m_config = nullptr; wxString object_name = wxEmptyString; if (item) @@ -1022,21 +1017,22 @@ void ObjectList::part_selection_changed() void ObjectList::update_manipulation_sizer(const bool is_simple_mode) { - auto item = m_objects_ctrl->GetSelection(); + auto item = GetSelection(); if (!item || !is_simple_mode) return; if (m_objects_model->IsSettingsItem(item)) { - m_objects_ctrl->Select(m_objects_model->GetParent(item)); + Select(m_objects_model->GetParent(item)); part_selection_changed(); } } -void ObjectList::add_object_to_list(const std::string &name, ModelObject* model_object) +void ObjectList::add_object_to_list(size_t obj_idx) { - wxString item_name = name; + auto model_object = (*m_objects)[obj_idx]; + wxString item_name = model_object->name; auto item = m_objects_model->Add(item_name, model_object->instances.size()); - m_objects_ctrl->Select(item); + Select(item); // Add error icon if detected auto-repaire auto stats = model_object->volumes[0]->mesh.stl.stats; @@ -1056,7 +1052,7 @@ void ObjectList::add_object_to_list(const std::string &name, ModelObject* model_ m_icon_solidmesh, model_object->volumes[id]->config.option("extruder")->value, false); - m_objects_ctrl->Expand(item); + Expand(item); } #ifndef __WXOSX__ @@ -1066,10 +1062,10 @@ void ObjectList::add_object_to_list(const std::string &name, ModelObject* model_ void ObjectList::delete_object_from_list() { - auto item = m_objects_ctrl->GetSelection(); + auto item = GetSelection(); if (!item || m_objects_model->GetParent(item) != wxDataViewItem(0)) return; - // m_objects_ctrl->Select(m_objects_model->Delete(item)); + // Select(m_objects_model->Delete(item)); m_objects_model->Delete(item); part_selection_changed(); @@ -1084,16 +1080,16 @@ void ObjectList::delete_all_objects_from_list() void ObjectList::set_object_count(int idx, int count) { m_objects_model->SetValue(wxString::Format("%d", count), idx, 1); - m_objects_ctrl->Refresh(); + Refresh(); } void ObjectList::unselect_objects() { - if (!m_objects_ctrl->GetSelection()) + if (!GetSelection()) return; m_prevent_list_events = true; - m_objects_ctrl->UnselectAll(); + UnselectAll(); part_selection_changed(); m_prevent_list_events = false; } @@ -1101,9 +1097,9 @@ void ObjectList::unselect_objects() void ObjectList::select_current_object(int idx) { m_prevent_list_events = true; - m_objects_ctrl->UnselectAll(); + UnselectAll(); if (idx >= 0) - m_objects_ctrl->Select(m_objects_model->GetItemById(idx)); + Select(m_objects_model->GetItemById(idx)); part_selection_changed(); m_prevent_list_events = false; } @@ -1115,16 +1111,16 @@ void ObjectList::select_current_volume(int idx, int vol_idx) return; } m_prevent_list_events = true; - m_objects_ctrl->UnselectAll(); + UnselectAll(); if (idx >= 0) - m_objects_ctrl->Select(m_objects_model->GetItemByVolumeId(idx, vol_idx)); + Select(m_objects_model->GetItemByVolumeId(idx, vol_idx)); part_selection_changed(); m_prevent_list_events = false; } void ObjectList::remove() { - auto item = m_objects_ctrl->GetSelection(); + auto item = GetSelection(); if (!item) return; diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index a2702228d3..dc85b13afe 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -1,15 +1,11 @@ #ifndef slic3r_GUI_ObjectList_hpp_ #define slic3r_GUI_ObjectList_hpp_ -#include #include +#include #include class wxBoxSizer; -class wxDataViewCtrl; -class wxDataViewColumn; -class wxDataViewEvent; -class wxDataViewItem; class PrusaObjectDataViewModel; namespace Slic3r { @@ -20,10 +16,9 @@ class ModelVolume; namespace GUI { -class ObjectList +class ObjectList : public wxDataViewCtrl { wxBoxSizer *m_sizer {nullptr}; - wxWindow *m_parent{ nullptr }; DynamicPrintConfig *m_default_config {nullptr}; @@ -50,11 +45,10 @@ public: std::map CATEGORY_ICON; - wxDataViewCtrl *m_objects_ctrl{ nullptr }; PrusaObjectDataViewModel *m_objects_model{ nullptr }; DynamicPrintConfig *m_config {nullptr}; - std::vector *m_objects{ nullptr }; + std::vector *m_objects{ nullptr }; void create_objects_ctrl(); @@ -110,7 +104,7 @@ public: void update_manipulation_sizer(const bool is_simple_mode); // Add object to the list - void add_object_to_list(const std::string &name, ModelObject* model_object); + void add_object_to_list(size_t obj_idx); // Delete object from the list void delete_object_from_list(); // Delete all objects from the list diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index 2858cb1068..c37d1a1a71 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -171,7 +171,7 @@ void ObjectManipulation::update_settings_list() m_settings_list_sizer->Clear(true); bool show_manipulations = true; - auto objects_ctrl = wxGetApp().obj_list()->m_objects_ctrl; + auto objects_ctrl = wxGetApp().obj_list(); auto objects_model = wxGetApp().obj_list()->m_objects_model; auto config = wxGetApp().obj_list()->m_config; @@ -259,7 +259,7 @@ void ObjectManipulation::update_settings_list() #endif parent->Layout(); - /*wxGetApp().sidebar().*/parent->GetParent()->Layout(); + parent->GetParent()->Layout(); } void ObjectManipulation::update_values() diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index e2a4f9d541..1210d5faa0 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -171,25 +171,6 @@ void MainFrame::init_tabpanel() // m_plater->select_object_from_cpp(obj_idx < 0 ? undef : obj_idx, vol_idx < 0 ? -1 : vol_idx); // }); - // The following event is emited by the C++ GUI implementation on object settings change. -// EVT_COMMAND($self, -1, $OBJECT_SETTINGS_CHANGED_EVENT, sub { -// auto line = event->GetString(); -// my($obj_idx, $parts_changed, $part_settings_changed) = split('', $line); -// -// m_plater->changed_object_settings(obj_idx, parts_changed, part_settings_changed); -// }); - - // The following event is emited by the C++ GUI implementation on object remove. -// EVT_COMMAND($self, -1, $OBJECT_REMOVE_EVENT, sub { -// m_plater->remove(); -// }); -// -// // The following event is emited by the C++ GUI implementation on extruder change for object. -// EVT_COMMAND($self, -1, $UPDATE_SCENE_EVENT, sub { -// m_plater->update(); -// }); - - create_preset_tabs(); std::vector tab_names = { "print", "filament", "sla_material", "printer" }; for (auto tab_name : tab_names) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index d76a0ca1bf..2a185205e2 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -362,6 +362,9 @@ struct Sidebar::priv wxButton *btn_reslice; // wxButton *btn_print; // XXX: remove wxButton *btn_send_gcode; + + bool show_manifold_warning_icon = false; + bool show_print_info = false; }; @@ -537,8 +540,8 @@ int Sidebar::get_ol_selection() void Sidebar::show_info_sizers(const bool show) { p->object_info->Show(show); - p->object_info->manifold_warning_icon->Show(show/* && g_show_manifold_warning_icon*/); // where is g_show_manifold_warning_icon updating? #ys_FIXME - p->sliced_info->Show(show /*&& g_show_print_info*/); // where is g_show_print_info updating? #ys_FIXME + p->object_info->manifold_warning_icon->Show(show && p->show_manifold_warning_icon); // where is g_show_manifold_warning_icon updating? #ys_FIXME + p->sliced_info->Show(show && p->show_print_info); // where is g_show_print_info updating? #ys_FIXME } void Sidebar::show_buttons(const bool show) @@ -974,11 +977,7 @@ std::vector Plater::priv::load_model_objects(const ModelObjectPtrs &mod } for (const size_t idx : obj_idxs) { - const PlaterObject &object = objects[idx]; - ModelObject *model_object = model.objects[idx]; - - // FIXME: ObjetParts not initialized (via add_frequently_changed_parameters) - // GUI::add_object_to_list(object.name, model_object); + wxGetApp().obj_list()->add_object_to_list(idx); } if (need_arrange) { @@ -1155,5 +1154,37 @@ void Plater::reslice() // TODO } +void Plater::changed_object_settings(int obj_idx) +{ + if (obj_idx < 0) + return; + auto list = wxGetApp().obj_list(); + wxASSERT(list != nullptr); + if (list == nullptr) + return; + + + if (list->is_parts_changed()) { + // recenter and re - align to Z = 0 + auto model_object = p->model.objects[list->get_sel_obj_id()]; + model_object->center_around_origin(); + } + + // update print + if (list->is_parts_changed() || list->is_part_settings_changed()) { +// stop_background_process(); +// $self->{print}->reload_object($obj_idx); +// schedule_background_process(); + if (p->canvas3D) _3DScene::reload_scene(p->canvas3D, true); + auto selections = p->collect_selections(); + _3DScene::set_objects_selections(p->canvas3D, selections); + _3DScene::reload_scene(p->canvas3D, false); + } + else { +// schedule_background_process(); + } + +} + }} // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index a060eda9ca..c05b454ff0 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -67,6 +67,7 @@ public: // Note: empty string means request default path std::string export_gcode(const std::string &output_path); void reslice(); + void changed_object_settings(int obj_idx); private: struct priv; std::unique_ptr p; diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 6b0b89eeed..84a7972c4f 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -152,7 +152,6 @@ void Tab::create_preset_tab() m_hsizer->Add(m_undo_btn, 0, wxALIGN_CENTER_VERTICAL); m_hsizer->AddSpacer(32); m_hsizer->Add(m_question_btn, 0, wxALIGN_CENTER_VERTICAL); -// m_hsizer->Add(m_cc_presets_choice, 1, wxLEFT | wxRIGHT | wxTOP | wxALIGN_CENTER_VERTICAL, 3); //Horizontal sizer to hold the tree and the selected page. m_hsizer = new wxBoxSizer(wxHORIZONTAL); @@ -518,7 +517,7 @@ void Tab::update_changed_tree_ui() break; } auto next_item = m_treectrl->GetNextVisible(cur_item); - cur_item = !m_treectrl->IsVisible(cur_item) ? m_treectrl->GetNextVisible(cur_item) : nullptr;// next_item; + cur_item = next_item; } update_undo_buttons(); } @@ -590,14 +589,11 @@ void Tab::update_dirty(){ m_presets->update_dirty_ui(m_presets_choice); on_presets_changed(); update_changed_ui(); -// update_dirty_presets(m_cc_presets_choice); } void Tab::update_tab_ui() { m_selected_preset_item = m_presets->update_tab_ui(m_presets_choice, m_show_incompatible_presets); -// update_tab_presets(m_cc_presets_choice, m_show_incompatible_presets); -// update_presetsctrl(m_presetctrl, m_show_incompatible_presets); } // Load a provied DynamicConfig into the tab, modifying the active preset. @@ -2611,173 +2607,6 @@ wxSizer* Tab::compatible_printers_widget(wxWindow* parent, wxCheckBox** checkbox return sizer; } -void Tab::update_presetsctrl(wxDataViewTreeCtrl* ui, bool show_incompatible) -{ - if (ui == nullptr) - return; - ui->Freeze(); - ui->DeleteAllItems(); - auto presets = m_presets->get_presets(); - auto idx_selected = m_presets->get_idx_selected(); - auto suffix_modified = m_presets->get_suffix_modified(); - int icon_compatible = 0; - int icon_incompatible = 1; - int cnt_items = 0; - - auto root_sys = ui->AppendContainer(wxDataViewItem(0), _(L("System presets"))); - auto root_def = ui->AppendContainer(wxDataViewItem(0), _(L("Default presets"))); - - auto show_def = wxGetApp().app_config->get("no_defaults")[0] != '1'; - - for (size_t i = presets.front().is_visible ? 0 : 1; i < presets.size(); ++i) { - const Preset &preset = presets[i]; - if (!preset.is_visible || (!show_incompatible && !preset.is_compatible && i != idx_selected)) - continue; - - auto preset_name = wxString::FromUTF8((preset.name + (preset.is_dirty ? suffix_modified : "")).c_str()); - - wxDataViewItem item; - if (preset.is_system) - item = ui->AppendItem(root_sys, preset_name, - preset.is_compatible ? icon_compatible : icon_incompatible); - else if (show_def && preset.is_default) - item = ui->AppendItem(root_def, preset_name, - preset.is_compatible ? icon_compatible : icon_incompatible); - else - { - auto parent = m_presets->get_preset_parent(preset); - if (parent == nullptr) - item = ui->AppendItem(root_def, preset_name, - preset.is_compatible ? icon_compatible : icon_incompatible); - else - { - auto parent_name = parent->name; - - wxDataViewTreeStoreContainerNode *node = ui->GetStore()->FindContainerNode(root_sys); - if (node) - { - wxDataViewTreeStoreNodes::iterator iter; - for (iter = node->GetChildren().begin(); iter != node->GetChildren().end(); iter++) - { - wxDataViewTreeStoreNode* child = *iter; - auto child_item = child->GetItem(); - auto item_text = ui->GetItemText(child_item); - if (item_text == parent_name) - { - auto added_child = ui->AppendItem(child->GetItem(), preset_name, - preset.is_compatible ? icon_compatible : icon_incompatible); - if (!added_child){ - ui->DeleteItem(child->GetItem()); - auto new_parent = ui->AppendContainer(root_sys, parent_name, - preset.is_compatible ? icon_compatible : icon_incompatible); - ui->AppendItem(new_parent, preset_name, - preset.is_compatible ? icon_compatible : icon_incompatible); - } - break; - } - } - } - } - } - - cnt_items++; - if (i == idx_selected){ - ui->Select(item); - m_cc_presets_choice->SetText(preset_name); - } - } - if (ui->GetStore()->GetChildCount(root_def) == 0) - ui->DeleteItem(root_def); - - ui->Thaw(); -} - -void Tab::update_tab_presets(wxComboCtrl* ui, bool show_incompatible) -{ - if (ui == nullptr) - return; - ui->Freeze(); - ui->Clear(); - auto presets = m_presets->get_presets(); - auto idx_selected = m_presets->get_idx_selected(); - auto suffix_modified = m_presets->get_suffix_modified(); - int icon_compatible = 0; - int icon_incompatible = 1; - int cnt_items = 0; - - wxDataViewTreeCtrlComboPopup* popup = wxDynamicCast(m_cc_presets_choice->GetPopupControl(), wxDataViewTreeCtrlComboPopup); - if (popup != nullptr) - { - popup->DeleteAllItems(); - - auto root_sys = popup->AppendContainer(wxDataViewItem(0), _(L("System presets"))); - auto root_def = popup->AppendContainer(wxDataViewItem(0), _(L("Default presets"))); - - auto show_def = wxGetApp().app_config->get("no_defaults")[0] != '1'; - - for (size_t i = presets.front().is_visible ? 0 : 1; i < presets.size(); ++i) { - const Preset &preset = presets[i]; - if (!preset.is_visible || (!show_incompatible && !preset.is_compatible && i != idx_selected)) - continue; - - auto preset_name = wxString::FromUTF8((preset.name + (preset.is_dirty ? suffix_modified : "")).c_str()); - - wxDataViewItem item; - if (preset.is_system) - item = popup->AppendItem(root_sys, preset_name, - preset.is_compatible ? icon_compatible : icon_incompatible); - else if (show_def && preset.is_default) - item = popup->AppendItem(root_def, preset_name, - preset.is_compatible ? icon_compatible : icon_incompatible); - else - { - auto parent = m_presets->get_preset_parent(preset); - if (parent == nullptr) - item = popup->AppendItem(root_def, preset_name, - preset.is_compatible ? icon_compatible : icon_incompatible); - else - { - auto parent_name = parent->name; - - wxDataViewTreeStoreContainerNode *node = popup->GetStore()->FindContainerNode(root_sys); - if (node) - { - wxDataViewTreeStoreNodes::iterator iter; - for (iter = node->GetChildren().begin(); iter != node->GetChildren().end(); iter++) - { - wxDataViewTreeStoreNode* child = *iter; - auto child_item = child->GetItem(); - auto item_text = popup->GetItemText(child_item); - if (item_text == parent_name) - { - auto added_child = popup->AppendItem(child->GetItem(), preset_name, - preset.is_compatible ? icon_compatible : icon_incompatible); - if (!added_child){ - popup->DeleteItem(child->GetItem()); - auto new_parent = popup->AppendContainer(root_sys, parent_name, - preset.is_compatible ? icon_compatible : icon_incompatible); - popup->AppendItem(new_parent, preset_name, - preset.is_compatible ? icon_compatible : icon_incompatible); - } - break; - } - } - } - } - } - - cnt_items++; - if (i == idx_selected){ - popup->Select(item); - m_cc_presets_choice->SetText(preset_name); - } - } - if (popup->GetStore()->GetChildCount(root_def) == 0) - popup->DeleteItem(root_def); - } - ui->Thaw(); -} - void Tab::fill_icon_descriptions() { m_icon_descriptions.push_back(t_icon_description(&m_bmp_value_lock, L("LOCKED LOCK;" diff --git a/src/slic3r/GUI/Tab.hpp b/src/slic3r/GUI/Tab.hpp index 4c7f32e7e3..2e80c36a8e 100644 --- a/src/slic3r/GUI/Tab.hpp +++ b/src/slic3r/GUI/Tab.hpp @@ -23,9 +23,6 @@ #include #include #include -#include -#include -#include #include #include @@ -126,8 +123,6 @@ protected: wxButton* m_undo_btn; wxButton* m_undo_to_sys_btn; wxButton* m_question_btn; - wxComboCtrl* m_cc_presets_choice; - wxDataViewTreeCtrl* m_presetctrl; wxImageList* m_preset_icons; // Cached bitmaps. @@ -218,7 +213,6 @@ public: bool may_discard_current_dirty_preset(PresetCollection* presets = nullptr, const std::string& new_printer_name = ""); wxSizer* compatible_printers_widget(wxWindow* parent, wxCheckBox** checkbox, wxButton** btn); - void update_presetsctrl(wxDataViewTreeCtrl* ui, bool show_incompatible); void load_key_value(const std::string& opt_key, const boost::any& value, bool saved_value = false); void reload_compatible_printers_widget(); @@ -267,7 +261,6 @@ protected: void on_presets_changed(); void update_preset_description_line(); void update_frequently_changed_parameters(); - void update_tab_presets(wxComboCtrl* ui, bool show_incompatible); void fill_icon_descriptions(); void set_tooltips_text(); }; From 1f926964ee0d93ce0044c75f76aee52d5db15dfd Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Thu, 4 Oct 2018 11:12:55 +0200 Subject: [PATCH 068/186] WIP: Plater, build fixes --- src/libslic3r/Point.hpp | 8 +- src/libslic3r/Print.hpp | 1 + src/slic3r/CMakeLists.txt | 2 + src/slic3r/GUI/BedShapeDialog.cpp | 2 +- src/slic3r/GUI/Field.cpp | 3 +- src/slic3r/GUI/GUI.cpp | 47 ---- src/slic3r/GUI/GUI.hpp | 3 - src/slic3r/GUI/GUI_App.cpp | 17 +- src/slic3r/GUI/GUI_App.hpp | 34 ++- src/slic3r/GUI/GUI_ObjectList.cpp | 4 +- src/slic3r/GUI/GUI_Utils.cpp | 54 ++++ src/slic3r/GUI/GUI_Utils.hpp | 41 +++ src/slic3r/GUI/MainFrame.cpp | 16 +- src/slic3r/GUI/Plater.cpp | 399 ++++++++++++++++++++++++++---- src/slic3r/GUI/Plater.hpp | 23 +- 15 files changed, 511 insertions(+), 143 deletions(-) create mode 100644 src/slic3r/GUI/GUI_Utils.cpp create mode 100644 src/slic3r/GUI/GUI_Utils.hpp diff --git a/src/libslic3r/Point.hpp b/src/libslic3r/Point.hpp index 87cdc3777f..1001781080 100644 --- a/src/libslic3r/Point.hpp +++ b/src/libslic3r/Point.hpp @@ -56,10 +56,10 @@ inline Vec2i64 to_2d(const Vec3i64 &pt3) { return Vec2i64(pt3(0), pt3(1)); } inline Vec2f to_2d(const Vec3f &pt3) { return Vec2f (pt3(0), pt3(1)); } inline Vec2d to_2d(const Vec3d &pt3) { return Vec2d (pt3(0), pt3(1)); } -// inline Vec3crd to_3d(const Vec2crd &pt2, coord_t z) { return Vec3crd(pt2(0), pt2(1), z); } -// inline Vec3i64 to_3d(const Vec2i64 &pt2, int64_t z) { return Vec3i64(pt2(0), pt2(1), z); } -// inline Vec3f to_3d(const Vec2f &pt2, float z) { return Vec3f (pt2(0), pt2(1), z); } -// inline Vec3d to_3d(const Vec2d &pt2, double z) { return Vec3d (pt2(0), pt2(1), z); } +inline Vec3d to_3d(const Vec2d &v, double z) { return Vec3d(v(0), v(1), z); } +inline Vec3f to_3d(const Vec2f &v, float z) { return Vec3f(v(0), v(1), z); } +inline Vec3i64 to_3d(const Vec2i64 &v, float z) { return Vec3i64(v(0), v(1), z); } +inline Vec3crd to_3d(const Vec3crd &p, coord_t z) { return Vec3crd(p(0), p(1), z); } inline Vec2d unscale(coord_t x, coord_t y) { return Vec2d(unscale(x), unscale(y)); } inline Vec2d unscale(const Vec2crd &pt) { return Vec2d(unscale(pt(0)), unscale(pt(1))); } diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index 7f88110bc3..a646ab8fd1 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -419,6 +419,7 @@ public: const PrintObject* get_object(int idx) const { return m_objects[idx]; } const PrintRegionPtrs& regions() const { return m_regions; } const PlaceholderParser& placeholder_parser() const { return m_placeholder_parser; } + PlaceholderParser& placeholder_parser() { return m_placeholder_parser; } // Returns extruder this eec should be printed with, according to PrintRegion config: static int get_extruder(const ExtrusionEntityCollection& fill, const PrintRegion ®ion); diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt index 54c90c20ef..4e9edfbdc6 100644 --- a/src/slic3r/CMakeLists.txt +++ b/src/slic3r/CMakeLists.txt @@ -39,6 +39,8 @@ add_library(libslic3r_gui STATIC ${LIBDIR}/slic3r/GUI/GUI_PreviewIface.hpp ${LIBDIR}/slic3r/GUI/GUI_App.cpp ${LIBDIR}/slic3r/GUI/GUI_App.hpp + ${LIBDIR}/slic3r/GUI/GUI_Utils.cpp + ${LIBDIR}/slic3r/GUI/GUI_Utils.hpp ${LIBDIR}/slic3r/GUI/MainFrame.cpp ${LIBDIR}/slic3r/GUI/MainFrame.hpp ${LIBDIR}/slic3r/GUI/Plater.cpp diff --git a/src/slic3r/GUI/BedShapeDialog.cpp b/src/slic3r/GUI/BedShapeDialog.cpp index 7c019599af..407da7ae39 100644 --- a/src/slic3r/GUI/BedShapeDialog.cpp +++ b/src/slic3r/GUI/BedShapeDialog.cpp @@ -292,7 +292,7 @@ void BedShapePanel::update_shape() void BedShapePanel::load_stl() { auto dialog = new wxFileDialog(this, _(L("Choose a file to import bed shape from (STL/OBJ/AMF/3MF/PRUSA):")), "", "", - MODEL_WILDCARD, wxFD_OPEN | wxFD_FILE_MUST_EXIST); + file_wildcards[FT_MODEL], wxFD_OPEN | wxFD_FILE_MUST_EXIST); if (dialog->ShowModal() != wxID_OK) { dialog->Destroy(); return; diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index 02fc9b8b6c..5dbc658777 100644 --- a/src/slic3r/GUI/Field.cpp +++ b/src/slic3r/GUI/Field.cpp @@ -611,8 +611,9 @@ void ColourPicker::BUILD() if (m_opt.width >= 0) size.SetWidth(m_opt.width); wxString clr(static_cast(m_opt.default_value)->get_at(m_opt_idx)); + // FIXME: verify clr is valid, otherwise this causes an assert auto temp = new wxColourPickerCtrl(m_parent, wxID_ANY, clr, wxDefaultPosition, size); - + // // recast as a wxWindow to fit the calling convention window = dynamic_cast(temp); diff --git a/src/slic3r/GUI/GUI.cpp b/src/slic3r/GUI/GUI.cpp index e06f6b7215..0e23585f7b 100644 --- a/src/slic3r/GUI/GUI.cpp +++ b/src/slic3r/GUI/GUI.cpp @@ -347,53 +347,6 @@ std::string into_u8(const wxString &str) return std::string(buffer_utf8.data()); } -wxWindow* export_option_creator(wxWindow* parent) -{ - wxPanel* panel = new wxPanel(parent, -1); - wxSizer* sizer = new wxBoxSizer(wxHORIZONTAL); - wxCheckBox* cbox = new wxCheckBox(panel, wxID_HIGHEST + 1, L("Export print config")); - cbox->SetValue(true); - sizer->AddSpacer(5); - sizer->Add(cbox, 0, wxEXPAND | wxALL | wxALIGN_CENTER_VERTICAL, 5); - panel->SetSizer(sizer); - sizer->SetSizeHints(panel); - return panel; -} - -void add_export_option(wxFileDialog* dlg, const std::string& format) -{ - if ((dlg != nullptr) && (format == "AMF") || (format == "3MF")) - { - if (dlg->SupportsExtraControl()) - dlg->SetExtraControlCreator(export_option_creator); - } -} - -int get_export_option(wxFileDialog* dlg) -{ - if (dlg != nullptr) - { - wxWindow* wnd = dlg->GetExtraControl(); - if (wnd != nullptr) - { - wxPanel* panel = dynamic_cast(wnd); - if (panel != nullptr) - { - wxWindow* child = panel->FindWindow(wxID_HIGHEST + 1); - if (child != nullptr) - { - wxCheckBox* cbox = dynamic_cast(child); - if (cbox != nullptr) - return cbox->IsChecked() ? 1 : 0; - } - } - } - } - - return 0; - -} - bool get_current_screen_size(wxWindow *window, unsigned &width, unsigned &height) { const auto idx = wxDisplay::GetFromWindow(window); diff --git a/src/slic3r/GUI/GUI.hpp b/src/slic3r/GUI/GUI.hpp index 1f2107d599..3203fd8b25 100644 --- a/src/slic3r/GUI/GUI.hpp +++ b/src/slic3r/GUI/GUI.hpp @@ -102,9 +102,6 @@ std::string into_u8(const wxString &str); // Callback to trigger a configuration update timer on the Plater. static PerlCallback g_on_request_update_callback; - -void add_export_option(wxFileDialog* dlg, const std::string& format); -int get_export_option(wxFileDialog* dlg); // Returns the dimensions of the screen on which the main frame is displayed bool get_current_screen_size(wxWindow *window, unsigned &width, unsigned &height); diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 1862bab8a5..b619b1899d 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -34,6 +34,21 @@ namespace Slic3r { namespace GUI { + +const wxString file_wildcards[FT_SIZE] = { + /* FT_STL */ "STL files (*.stl)|*.stl;*.STL", + /* FT_OBJ */ "OBJ files (*.obj)|*.obj;*.OBJ", + /* FT_AMF */ "AMF files (*.amf)|*.zip.amf;*.amf;*.AMF;*.xml;*.XML", + /* FT_3MF */ "3MF files (*.3mf)|*.3mf;*.3MF;", + /* FT_PRUSA */ "Prusa Control files (*.prusa)|*.prusa;*.PRUSA", + /* FT_GCODE */ "G-code files (*.gcode, *.gco, *.g, *.ngc)|*.gcode;*.GCODE;*.gco;*.GCO;*.g;*.G;*.ngc;*.NGC", + /* FT_MODEL */ "Known files (*.stl, *.obj, *.amf, *.xml, *.3mf, *.prusa)|*.stl;*.STL;*.obj;*.OBJ;*.amf;*.AMF;*.xml;*.XML;*.3mf;*.3MF;*.prusa;*.PRUSA", + + /* FT_INI */ "INI files *.ini|*.ini;*.INI", + /* FT_SVG */ "SVG files *.svg|*.svg;*.SVG", +}; + + static std::string libslic3r_translate_callback(const char *s) { return wxGetTranslation(wxString(s, wxConvUTF8)).utf8_str().data(); } IMPLEMENT_APP(GUI_App) @@ -291,7 +306,7 @@ void GUI_App::open_model(wxWindow *parent, wxArrayString& input_files) auto dialog = new wxFileDialog(parent ? parent : GetTopWindow(), _(L("Choose one or more files (STL/OBJ/AMF/3MF/PRUSA):")), app_config->get_last_dir(), "", - MODEL_WILDCARD, wxFD_OPEN | wxFD_MULTIPLE | wxFD_FILE_MUST_EXIST); + file_wildcards[FT_MODEL], wxFD_OPEN | wxFD_MULTIPLE | wxFD_FILE_MUST_EXIST); if (dialog->ShowModal() != wxID_OK) { dialog->Destroy(); return; diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index e5ea77a38c..848a5a3707 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -25,26 +25,24 @@ class ModelObject; namespace GUI { -// Map from an file_type name to full file wildcard name. -const std::map FILE_WILDCARDS{ - std::make_pair("known", "Known files (*.stl, *.obj, *.amf, *.xml, *.prusa)|*.stl;*.STL;*.obj;*.OBJ;*.amf;*.AMF;*.xml;*.XML;*.prusa;*.PRUSA"), - std::make_pair("stl", "STL files (*.stl)|*.stl;*.STL"), - std::make_pair("obj", "OBJ files (*.obj)|*.obj;*.OBJ"), - std::make_pair("amf", "AMF files (*.amf)|*.zip.amf;*.amf;*.AMF;*.xml;*.XML"), - std::make_pair("3mf", "3MF files (*.3mf)|*.3mf;*.3MF;"), - std::make_pair("prusa", "Prusa Control files (*.prusa)|*.prusa;*.PRUSA"), - std::make_pair("ini", "INI files *.ini|*.ini;*.INI"), - std::make_pair("gcode", "G-code files (*.gcode, *.gco, *.g, *.ngc)|*.gcode;*.GCODE;*.gco;*.GCO;*.g;*.G;*.ngc;*.NGC"), - std::make_pair("svg", "SVG files *.svg|*.svg;*.SVG") + +enum FileType +{ + FT_STL, + FT_OBJ, + FT_AMF, + FT_3MF, + FT_PRUSA, + FT_GCODE, + FT_MODEL, + + FT_INI, + FT_SVG, + + FT_SIZE, }; -const std::string MODEL_WILDCARD{ FILE_WILDCARDS.at("known") + std::string("|") + - FILE_WILDCARDS.at("stl") + std::string("|") + - FILE_WILDCARDS.at("obj") + std::string("|") + - FILE_WILDCARDS.at("amf") + std::string("|") + - FILE_WILDCARDS.at("3mf") + std::string("|") + - FILE_WILDCARDS.at("prusa") }; - +extern const wxString file_wildcards[FT_SIZE]; enum ConfigMenuIDs { ConfigMenuWizard, diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 0ea56710c6..6451b50c53 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -511,7 +511,7 @@ void ObjectList::menu_item_add_generic(wxMenuItem* &menu, int id) { sub_menu->Append(new wxMenuItem(sub_menu, ++id, _(item))); #ifndef __WXMSW__ - sub_menu->Bind(wxEVT_MENU, [sub_menu](wxEvent &event) { + sub_menu->Bind(wxEVT_MENU, [this, sub_menu](wxEvent &event) { load_lambda(sub_menu->GetLabel(event.GetId()).ToStdString()); }); #endif //no __WXMSW__ @@ -633,7 +633,7 @@ wxMenu* ObjectList::create_add_settings_popupmenu(bool is_part) menu->Append(menu_item); } #ifndef __WXMSW__ - menu->Bind(wxEVT_MENU, [menu, is_part](wxEvent &event) { + menu->Bind(wxEVT_MENU, [this, menu, is_part](wxEvent &event) { get_settings_choice(menu, event.GetId(), is_part); }); #endif //no __WXMSW__ diff --git a/src/slic3r/GUI/GUI_Utils.cpp b/src/slic3r/GUI/GUI_Utils.cpp new file mode 100644 index 0000000000..b8cd60944d --- /dev/null +++ b/src/slic3r/GUI/GUI_Utils.cpp @@ -0,0 +1,54 @@ +#include "GUI_Utils.hpp" + +#include +#include +#include + + +namespace Slic3r { +namespace GUI { + + +CheckboxFileDialog::CheckboxFileDialog(wxWindow *parent, + const wxString &checkbox_label, + bool checkbox_value, + const wxString &message, + const wxString &default_dir, + const wxString &default_file, + const wxString &wildcard, + long style, + const wxPoint &pos, + const wxSize &size, + const wxString &name +) + : wxFileDialog(parent, message, default_dir, default_file, wildcard, style, pos, size, name) + , cbox(nullptr) +{ + if (checkbox_label.IsEmpty()) { + return; + } + + extra_control_creator = [this, checkbox_label](wxWindow *parent) -> wxWindow* { + wxPanel* panel = new wxPanel(parent, -1); + wxSizer* sizer = new wxBoxSizer(wxHORIZONTAL); + this->cbox = new wxCheckBox(panel, wxID_HIGHEST + 1, checkbox_label); + this->cbox->SetValue(true); + sizer->AddSpacer(5); + sizer->Add(this->cbox, 0, wxEXPAND | wxALL | wxALIGN_CENTER_VERTICAL, 5); + panel->SetSizer(sizer); + sizer->SetSizeHints(panel); + + return panel; + }; + + SetExtraControlCreator(*extra_control_creator.target()); +} + +bool CheckboxFileDialog::get_checkbox_value() const +{ + return this->cbox != nullptr ? cbox->IsChecked() : false; +} + + +} +} diff --git a/src/slic3r/GUI/GUI_Utils.hpp b/src/slic3r/GUI/GUI_Utils.hpp new file mode 100644 index 0000000000..bf2ee961f1 --- /dev/null +++ b/src/slic3r/GUI/GUI_Utils.hpp @@ -0,0 +1,41 @@ +#ifndef slic3r_GUI_Utils_hpp_ +#define slic3r_GUI_Utils_hpp_ + +#include + +#include + +class wxCheckBox; + + +namespace Slic3r { +namespace GUI { + + +class CheckboxFileDialog : public wxFileDialog +{ +public: + CheckboxFileDialog(wxWindow *parent, + const wxString &checkbox_label, + bool checkbox_value, + const wxString &message = wxFileSelectorPromptStr, + const wxString &default_dir = wxEmptyString, + const wxString &default_file = wxEmptyString, + const wxString &wildcard = wxFileSelectorDefaultWildcardStr, + long style = wxFD_DEFAULT_STYLE, + const wxPoint &pos = wxDefaultPosition, + const wxSize &size = wxDefaultSize, + const wxString &name = wxFileDialogNameStr + ); + + bool get_checkbox_value() const; + +private: + std::function extra_control_creator; + wxCheckBox *cbox; +}; + + +}} + +#endif diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index e2a4f9d541..a8282e6c4d 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -460,7 +460,7 @@ void MainFrame::quick_slice(const int qs){ if (!(qs & qsReslice)) { auto dlg = new wxFileDialog(this, _(L("Choose a file to slice (STL/OBJ/AMF/3MF/PRUSA):")), wxGetApp().app_config->get_last_dir(), "", - MODEL_WILDCARD, wxFD_OPEN | wxFD_FILE_MUST_EXIST); + file_wildcards[FT_MODEL], wxFD_OPEN | wxFD_FILE_MUST_EXIST); if (dlg->ShowModal() != wxID_OK) { dlg->Destroy(); return; @@ -519,7 +519,7 @@ void MainFrame::quick_slice(const int qs){ // output_file = ~s / \.[gG][cC][oO][dD][eE]$ / .svg /; auto dlg = new wxFileDialog(this, _(L("Save ")) + (qs & qsExportSVG ? _(L("SVG")) : _(L("G-code"))) + _(L(" file as:")), wxGetApp().app_config->get_last_output_dir(get_dir_name(output_file)), get_base_name(input_file), - qs & qsExportSVG ? FILE_WILDCARDS.at("svg") : FILE_WILDCARDS.at("gcode"), + qs & qsExportSVG ? file_wildcards[FT_SVG] : file_wildcards[FT_GCODE], wxFD_SAVE | wxFD_OVERWRITE_PROMPT); if (dlg->ShowModal() != wxID_OK) { dlg->Destroy(); @@ -587,7 +587,7 @@ void MainFrame::repair_stl() { auto dlg = new wxFileDialog(this, _(L("Select the STL file to repair:")), wxGetApp().app_config->get_last_dir(), "", - FILE_WILDCARDS.at("stl"), wxFD_OPEN | wxFD_FILE_MUST_EXIST); + file_wildcards[FT_STL], wxFD_OPEN | wxFD_FILE_MUST_EXIST); if (dlg->ShowModal() != wxID_OK) { dlg->Destroy(); return; @@ -601,7 +601,7 @@ void MainFrame::repair_stl() // output_file = ~s / \.[sS][tT][lL]$ / _fixed.obj / ; auto dlg = new wxFileDialog( this, L("Save OBJ file (less prone to coordinate errors than STL) as:"), get_dir_name(output_file), get_base_name(output_file), - FILE_WILDCARDS.at("obj"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT); + file_wildcards[FT_OBJ], wxFD_SAVE | wxFD_OVERWRITE_PROMPT); if (dlg->ShowModal() != wxID_OK) { dlg->Destroy(); return /*undef*/; @@ -631,7 +631,7 @@ void MainFrame::export_config() auto dlg = new wxFileDialog(this, _(L("Save configuration as:")), !m_last_config.IsEmpty() ? get_dir_name(m_last_config) : wxGetApp().app_config->get_last_dir(), !m_last_config.IsEmpty() ? get_base_name(m_last_config) : "config.ini", - FILE_WILDCARDS.at("ini"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT); + file_wildcards[FT_INI], wxFD_SAVE | wxFD_OVERWRITE_PROMPT); wxString file; if (dlg->ShowModal() == wxID_OK) file = dlg->GetPath(); @@ -683,7 +683,7 @@ void MainFrame::export_configbundle() auto dlg = new wxFileDialog(this, _(L("Save presets bundle as:")), !m_last_config.IsEmpty() ? get_dir_name(m_last_config) : wxGetApp().app_config->get_last_dir(), "Slic3r_config_bundle.ini", - FILE_WILDCARDS.at("ini"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT); + file_wildcards[FT_INI], wxFD_SAVE | wxFD_OVERWRITE_PROMPT); wxString file; if (dlg->ShowModal() == wxID_OK) file = dlg->GetPath(); @@ -707,7 +707,7 @@ void MainFrame::load_configbundle(wxString file/* = wxEmptyString, const bool re if (file.IsEmpty()) { auto dlg = new wxFileDialog(this, _(L("Select configuration to load:")), !m_last_config.IsEmpty() ? get_dir_name(m_last_config) : wxGetApp().app_config->get_last_dir(), - "config.ini", FILE_WILDCARDS.at("ini"), wxFD_OPEN | wxFD_FILE_MUST_EXIST); + "config.ini", file_wildcards[FT_INI], wxFD_OPEN | wxFD_FILE_MUST_EXIST); if (dlg->ShowModal() != wxID_OK) return; file = dlg->GetPath(); @@ -774,7 +774,7 @@ void MainFrame::on_presets_changed(SimpleEvent &event) // Update preset combo boxes(Print settings, Filament, Material, Printer) from their respective tabs. auto presets = tab->get_presets(); - if (presets) { + if (m_plater != nullptr && presets != nullptr) { auto reload_dependent_tabs = tab->get_dependent_tabs(); // FIXME: The preset type really should be a property of Tab instead diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index cd5a1fc122..b4b0cb726c 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -25,10 +26,12 @@ #include "libslic3r/GCode/PreviewData.hpp" #include "libslic3r/Utils.hpp" #include "libslic3r/Polygon.hpp" +#include "libslic3r/Format/STL.hpp" #include "GUI.hpp" #include "GUI_App.hpp" #include "GUI_ObjectList.hpp" #include "GUI_ObjectManipulation.hpp" +#include "GUI_Utils.hpp" #include "MainFrame.hpp" #include "3DScene.hpp" #include "GLCanvas3D.hpp" @@ -43,6 +46,7 @@ #include // Needs to be last because reasons :-/ #include "WipeTowerDialog.hpp" +using boost::optional; namespace fs = boost::filesystem; using Slic3r::_3DScene; using Slic3r::Preset; @@ -340,7 +344,7 @@ FreqChangedParams::FreqChangedParams(wxWindow* parent, const int label_width) : struct Sidebar::priv { - // Sidebar *q; // PIMPL back pointer ("Q-Pointer") + Plater *plater; wxScrolledWindow *scrolled; @@ -362,13 +366,15 @@ struct Sidebar::priv wxButton *btn_reslice; // wxButton *btn_print; // XXX: remove wxButton *btn_send_gcode; + + priv(Plater *plater) : plater(plater) {} }; // Sidebar / public -Sidebar::Sidebar(wxWindow *parent) - : wxPanel(parent), p(new priv) +Sidebar::Sidebar(Plater *parent) + : wxPanel(parent), p(new priv(parent)) { p->scrolled = new wxScrolledWindow(this); @@ -457,6 +463,11 @@ Sidebar::Sidebar(wxWindow *parent) sizer->Add(p->scrolled, 1, wxEXPAND | wxTOP, 5); sizer->Add(btns_sizer, 0, wxEXPAND | wxLEFT, 20); SetSizer(sizer); + + // Events + p->btn_export_gcode->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { p->plater->export_gcode(); }); + p->btn_reslice->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { p->plater->reslice(); }); + p->btn_send_gcode->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { p->plater->send_gcode(); }); } Sidebar::~Sidebar() {} @@ -600,8 +611,8 @@ struct Plater::priv Slic3r::GCodePreviewData gcode_preview_data; std::vector objects; - std::string export_gcode_output_file; - std::string send_gcode_file; + fs::path export_gcode_output_file; + fs::path send_gcode_file; // GUI elements wxNotebook *notebook; @@ -610,7 +621,6 @@ struct Plater::priv Preview *preview; BackgroundSlicingProcess background_process; - static const int gl_attrs[]; static const std::regex pattern_bundle; static const std::regex pattern_3mf; static const std::regex pattern_zip_amf; @@ -628,19 +638,33 @@ struct Plater::priv BoundingBox scaled_bed_shape_bb() const; std::vector load_files(const std::vector &input_files); std::vector load_model_objects(const ModelObjectPtrs &model_objects); + std::unique_ptr get_export_file(GUI::FileType file_type); + + void select_object(optional obj_idx); + optional selected_object() const; + void selection_changed(); + + void reset(); void on_notebook_changed(wxBookCtrlEvent &); void on_select_preset(wxCommandEvent &); void on_update_print_preview(wxCommandEvent &); void on_process_completed(wxCommandEvent &); void on_layer_editing_toggled(bool enable); + void on_action_add(SimpleEvent&); + void on_action_arrange(SimpleEvent&); + void on_action_more(SimpleEvent&); + void on_action_fewer(SimpleEvent&); + void on_action_split(SimpleEvent&); + void on_action_cut(SimpleEvent&); + void on_action_settings(SimpleEvent&); + void on_action_layersediting(SimpleEvent&); + void on_action_selectbyparts(SimpleEvent&); void on_viewport_changed(SimpleEvent& evt); }; -// TODO: multisample, see 3DScene.pm -const int Plater::priv::gl_attrs[] = {WX_GL_RGBA, WX_GL_DOUBLEBUFFER, WX_GL_DEPTH_SIZE, 24, 0}; const std::regex Plater::priv::pattern_bundle("[.](amf|amf[.]xml|zip[.]amf|3mf|prusa)$", std::regex::icase); const std::regex Plater::priv::pattern_3mf("[.]3mf$", std::regex::icase); const std::regex Plater::priv::pattern_zip_amf("[.]zip[.]amf$", std::regex::icase); @@ -716,15 +740,26 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) : sidebar->Bind(wxEVT_COMBOBOX, &priv::on_select_preset, this); // Sidebar button events - sidebar->p->btn_export_gcode->Bind(wxEVT_BUTTON, [q](wxCommandEvent&) { q->export_gcode(""); }); - sidebar->p->btn_reslice->Bind(wxEVT_BUTTON, [q](wxCommandEvent&) { q->reslice(); }); - sidebar->p->btn_send_gcode->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { - this->send_gcode_file = this->q->export_gcode(""); - }); + // sidebar->p->btn_export_gcode->Bind(wxEVT_BUTTON, [q](wxCommandEvent&) { q->export_gcode(); }); + // sidebar->p->btn_reslice->Bind(wxEVT_BUTTON, [q](wxCommandEvent&) { q->reslice(); }); + // sidebar->p->btn_send_gcode->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { + // this->send_gcode_file = this->q->export_gcode(); + // }); // 3DScene events: // TODO: more canvas3D->Bind(EVT_GLTOOLBAR_ADD, &priv::on_action_add, this); + canvas3D->Bind(EVT_GLTOOLBAR_DELETE, [q](SimpleEvent&) { q->remove_selected(); } ); + canvas3D->Bind(EVT_GLTOOLBAR_DELETE_ALL, [this](SimpleEvent&) { reset(); }); + canvas3D->Bind(EVT_GLTOOLBAR_ARRANGE, &priv::on_action_arrange, this); + canvas3D->Bind(EVT_GLTOOLBAR_MORE, &priv::on_action_more, this); + canvas3D->Bind(EVT_GLTOOLBAR_FEWER, &priv::on_action_fewer, this); + canvas3D->Bind(EVT_GLTOOLBAR_SPLIT, &priv::on_action_split, this); + canvas3D->Bind(EVT_GLTOOLBAR_CUT, &priv::on_action_cut, this); + canvas3D->Bind(EVT_GLTOOLBAR_SETTINGS, &priv::on_action_settings, this); + canvas3D->Bind(EVT_GLTOOLBAR_LAYERSEDITING, &priv::on_action_layersediting, this); + canvas3D->Bind(EVT_GLTOOLBAR_SELECTBYPARTS, &priv::on_action_selectbyparts, this); + canvas3D->Bind(EVT_GLCANVAS_VIEWPORT_CHANGED, &priv::on_viewport_changed, this); preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_VIEWPORT_CHANGED, &priv::on_viewport_changed, this); @@ -810,7 +845,7 @@ BoundingBox Plater::priv::scaled_bed_shape_bb() const std::vector Plater::priv::load_files(const std::vector &input_files) { - if (input_files.size() < 1) { return std::vector(); } + if (input_files.empty()) { return std::vector(); } auto *nozzle_dmrs = config->opt("nozzle_diameter"); @@ -883,9 +918,6 @@ std::vector Plater::priv::load_files(const std::vector &input_ } if (one_by_one) { - // TODO: - // push @obj_idx, $self->load_model_objects(@{$model->objects}); - // obj_idx.push_back(load_model_objects(model.objects); auto loaded_idxs = load_model_objects(model.objects); obj_idxs.insert(obj_idxs.end(), loaded_idxs.begin(), loaded_idxs.end()); } else { @@ -906,9 +938,6 @@ std::vector Plater::priv::load_files(const std::vector &input_ new_model->convert_multipart_object(nozzle_dmrs->values.size()); } - // TODO: - // push @obj_idx, $self->load_model_objects(@{$new_model->objects}); - // obj_idx.push_back(load_model_objects(new_model->objects); auto loaded_idxs = load_model_objects(model.objects); obj_idxs.insert(obj_idxs.end(), loaded_idxs.begin(), loaded_idxs.end()); } @@ -919,18 +948,11 @@ std::vector Plater::priv::load_files(const std::vector &input_ return obj_idxs; } - -// TODO: move to Point.hpp -Vec3d to_3d(const Vec2d &v, double z) { return Vec3d(v(0), v(1), z); } -Vec3f to_3d(const Vec2f &v, float z) { return Vec3f(v(0), v(1), z); } -Vec3i64 to_3d(const Vec2i64 &v, float z) { return Vec3i64(v(0), v(1), z); } -Vec3crd to_3d(const Point &p, coord_t z) { return Vec3crd(p(0), p(1), z); } - -std::vector Plater::priv::load_model_objects(const ModelObjectPtrs &model_objects) +std::vector Plater::priv::load_model_objects(const ModelObjectPtrs &model_objects) { const BoundingBoxf bed_shape = bed_shape_bb(); - const Vec3d bed_center = to_3d(bed_shape.center().cast(), 0.0); - const Vec3d bed_size = to_3d(bed_shape.size().cast(), 1.0); + const Vec3d bed_center = Slic3r::to_3d(bed_shape.center().cast(), 0.0); + const Vec3d bed_size = Slic3r::to_3d(bed_shape.size().cast(), 1.0); bool need_arrange = false; bool scaled_down = false; @@ -942,7 +964,7 @@ std::vector Plater::priv::load_model_objects(const ModelObjectPtrs &mod objects.emplace_back(std::move(object_name)); obj_idxs.push_back(objects.size() - 1); - if (model_object->instances.size() == 0) { + if (model_object->instances.empty()) { // if object has no defined position(s) we need to rearrange everything after loading need_arrange = true; @@ -1002,6 +1024,186 @@ std::vector Plater::priv::load_model_objects(const ModelObjectPtrs &mod return obj_idxs; } +std::unique_ptr Plater::priv::get_export_file(GUI::FileType file_type) +{ + wxString wildcard; + switch (file_type) { + case FT_STL: + case FT_AMF: + case FT_3MF: + wildcard = file_wildcards[FT_STL]; + break; + + default: + wildcard = file_wildcards[FT_MODEL]; + break; + } + + fs::path output_file(print.output_filepath(std::string())); + + switch (file_type) { + case FT_STL: output_file.replace_extension("stl"); break; + case FT_AMF: output_file.replace_extension("zip.amf"); break; // XXX: Problem on OS X with double extension? + case FT_3MF: output_file.replace_extension("3mf"); break; + default: break; + } + + wxGetApp().preset_bundle->export_selections(print.placeholder_parser()); + + auto dlg = Slic3r::make_unique(q, + _(L("Export print config")), + true, + _(L("Save file as:")), + output_file.parent_path().string(), + output_file.filename().string(), + wildcard, + wxFD_SAVE | wxFD_OVERWRITE_PROMPT + ); + + if (dlg->ShowModal() != wxID_OK) { + return nullptr; + } + + fs::path path(dlg->GetPath()); + wxGetApp().app_config->update_last_output_dir(path.parent_path().string()); + export_gcode_output_file = path; + + return dlg; +} + +void Plater::priv::select_object(optional obj_idx) +{ + for (auto &obj : objects) { + obj.selected = false; + } + + if (obj_idx) { + objects[*obj_idx].selected = true; + } + + // TODO: + // $self->selection_changed(1); +} + +void Plater::priv::selection_changed() +{ + // TODO + + const auto obj_idx = selected_object(); + const bool have_sel = !!obj_idx; + const bool layers_height_allowed = config->opt("variable_layer_height")->value; + + wxWindowUpdateLocker freeze_guard(sidebar); + + _3DScene::enable_toolbar_item(canvas3D, "delete", have_sel); + _3DScene::enable_toolbar_item(canvas3D, "more", have_sel); + _3DScene::enable_toolbar_item(canvas3D, "fewer", have_sel); + _3DScene::enable_toolbar_item(canvas3D, "split", have_sel); + _3DScene::enable_toolbar_item(canvas3D, "cut", have_sel); + _3DScene::enable_toolbar_item(canvas3D, "settings", have_sel); + + _3DScene::enable_toolbar_item(canvas3D, "layersediting", layers_height_allowed); + + bool can_select_by_parts = false; + + if (have_sel) { + // my $model_object = $self->{model}->objects->[$obj_idx]; + const auto *model_object = model.objects[*obj_idx]; + // $can_select_by_parts = ($obj_idx >= 0) && ($obj_idx < 1000) && ($model_object->volumes_count > 1); + // XXX: ? + can_select_by_parts = *obj_idx < 1000 && model_object->volumes.size() > 1; + // Slic3r::GUI::_3DScene::enable_toolbar_item($self->{canvas3D}, "fewer", $model_object->instances_count > 1); + _3DScene::enable_toolbar_item(canvas3D, "fewer", model_object->instances.size() > 1); + } + + if (can_select_by_parts) { + // first disable to let the item in the toolbar to switch to the unpressed state // XXX: ? + _3DScene::enable_toolbar_item(canvas3D, "selectbyparts", false); + _3DScene::enable_toolbar_item(canvas3D, "selectbyparts", true); + } else { + _3DScene::enable_toolbar_item(canvas3D, "selectbyparts", false); + _3DScene::set_select_by(canvas3D, "object"); + } + + if (have_sel) { + const auto *model_object = model.objects[*obj_idx]; + // FIXME print_info runs model fixing in two rounds, it is very slow, it should not be performed here! + // # $model_object->print_info; + + // my $model_instance = $model_object->instances->[0]; + const auto *model_instance = model_object->instances[0]; + // TODO + // $self->{object_info_size}->SetLabel(sprintf("%.2f x %.2f x %.2f", @{$model_object->instance_bounding_box(0)->size})); + // $self->{object_info_materials}->SetLabel($model_object->materials_count); + + // if (my $stats = $model_object->mesh_stats) { + // $self->{object_info_volume}->SetLabel(sprintf('%.2f', $stats->{volume} * ($model_instance->scaling_factor**3))); + // $self->{object_info_facets}->SetLabel(sprintf(L('%d (%d shells)'), $model_object->facets_count, $stats->{number_of_parts})); + // if (my $errors = sum(@$stats{qw(degenerate_facets edges_fixed facets_removed facets_added facets_reversed backwards_edges)})) { + // $self->{object_info_manifold}->SetLabel(sprintf(L("Auto-repaired (%d errors)"), $errors)); + // #$self->{object_info_manifold_warning_icon}->Show; + // $self->{"object_info_manifold_warning_icon_show"}->(1); + + // # we don't show normals_fixed because we never provide normals + // # to admesh, so it generates normals for all facets + // my $message = sprintf L('%d degenerate facets, %d edges fixed, %d facets removed, %d facets added, %d facets reversed, %d backwards edges'), + // @$stats{qw(degenerate_facets edges_fixed facets_removed facets_added facets_reversed backwards_edges)}; + // $self->{object_info_manifold}->SetToolTipString($message); + // $self->{object_info_manifold_warning_icon}->SetToolTipString($message); + // } else { + // $self->{object_info_manifold}->SetLabel(L("Yes")); + // #$self->{object_info_manifold_warning_icon}->Hide; + // $self->{"object_info_manifold_warning_icon_show"}->(0); + // $self->{object_info_manifold}->SetToolTipString(""); + // $self->{object_info_manifold_warning_icon}->SetToolTipString(""); + // } + // } else { + // $self->{object_info_facets}->SetLabel($object->facets); + // } + } else { + // $self->{"object_info_$_"}->SetLabel("") for qw(size volume facets materials manifold); + // $self->{"object_info_manifold_warning_icon_show"}->(0); + // $self->{object_info_manifold}->SetToolTipString(""); + // $self->{object_info_manifold_warning_icon}->SetToolTipString(""); + } + + q->Layout(); +} + +optional Plater::priv::selected_object() const +{ + for (size_t i = 0; i < objects.size(); i++) { + if (objects[i].selected) { return i; } + } + + return boost::none; +} + +void Plater::priv::reset() +{ + // TODO + + // $self->stop_background_process; + + // Prevent toolpaths preview from rendering while we modify the Print object + preview->set_enabled(false); + + objects.clear(); + model.clear_objects(); + print.clear_objects(); + + // Delete all objects from list on c++ side + // TODO + // Slic3r::GUI::delete_all_objects_from_list(); + sidebar->obj_list()->delete_all_objects_from_list(); + // $self->object_list_changed; + + // TODO + // $self->select_object(undef); + update(); +} + + void Plater::priv::on_notebook_changed(wxBookCtrlEvent&) { const auto current_id = notebook->GetCurrentPage()->GetId(); @@ -1082,6 +1284,47 @@ void Plater::priv::on_action_add(SimpleEvent&) load_files(input_paths); } +void Plater::priv::on_action_arrange(SimpleEvent&) +{ + // TODO +} + +void Plater::priv::on_action_more(SimpleEvent&) +{ + // TODO +} + +void Plater::priv::on_action_fewer(SimpleEvent&) +{ + // TODO +} + +void Plater::priv::on_action_split(SimpleEvent&) +{ + // TODO +} + +void Plater::priv::on_action_cut(SimpleEvent&) +{ + // TODO +} + +void Plater::priv::on_action_settings(SimpleEvent&) +{ + // TODO +} + +void Plater::priv::on_action_layersediting(SimpleEvent&) +{ + // TODO +} + +void Plater::priv::on_action_selectbyparts(SimpleEvent&) +{ + // TODO +} + + void Plater::priv::on_viewport_changed(SimpleEvent& evt) { wxObject* o = evt.GetEventObject(); @@ -1107,63 +1350,115 @@ Plater::~Plater() Sidebar& Plater::sidebar() { return *p->sidebar; } Model& Plater::model() { return p->model; } -std::string Plater::export_gcode(const std::string &output_path) +void Plater::update(bool force_autocenter) { - if (p->objects.size() == 0) { return ""; } + p->update(force_autocenter); +} + +void Plater::remove(size_t obj_idx) +{ + // TODO +} + +void Plater::remove_selected() +{ + const auto selected = p->selected_object(); + if (selected) { + remove(*selected); + } +} + + +fs::path Plater::export_gcode(const fs::path &output_path) +{ + if (p->objects.empty()) { return ""; } if (! p->export_gcode_output_file.empty()) { GUI::show_error(this, _(L("Another export job is currently running."))); return ""; } - // wxTheApp->{preset_bundle}->full_config->validate; // FIXME - const std::string err = p->print.validate(); + std::string err = wxGetApp().preset_bundle->full_config().validate(); + if (err.empty()) { + err = p->print.validate(); + } if (! err.empty()) { // The config is not valid GUI::show_error(this, _(err)); - return ""; + return fs::path(); } // Copy the names of active presets into the placeholder parser. - // wxTheApp->{preset_bundle}->export_selections_pp($self->{print}->placeholder_parser); // FIXME + wxGetApp().preset_bundle->export_selections(p->print.placeholder_parser()); // select output file if (! output_path.empty()) { - p->export_gcode_output_file = p->print.output_filepath(output_path); + p->export_gcode_output_file = fs::path(p->print.output_filepath(output_path.string())); // FIXME: ^ errors to handle? } else { - // FIXME: - std::string default_output_file; // FIXME: tmp - // my $default_output_file = eval { $self->{print}->output_filepath($main::opt{output} // '') }; - // Slic3r::GUI::catch_error($self) and return; + + // XXX: take output path from CLI opts? Ancient Slic3r versions used to do that... // If possible, remove accents from accented latin characters. // This function is useful for generating file names to be processed by legacy firmwares. - default_output_file = Slic3r::fold_utf8_to_ascii(default_output_file); + auto default_output_file = fs::path(Slic3r::fold_utf8_to_ascii( + p->print.output_filepath(output_path.string()) + // FIXME: ^ errors to handle? + )); + auto start_dir = wxGetApp().app_config->get_last_output_dir(default_output_file.parent_path().string()); wxFileDialog dlg(this, _(L("Save G-code file as:")), - wxEmptyString, - wxEmptyString, - Slic3r::GUI::FILE_WILDCARDS.at("gcode"), + start_dir, + default_output_file.filename().string(), + GUI::file_wildcards[FT_GCODE], wxFD_SAVE | wxFD_OVERWRITE_PROMPT ); - // FIXME: ^ defaultDir: - // wxTheApp->{app_config}->get_last_output_dir(dirname($default_output_file)), - // FIXME: ^ defaultFile: - // basename($default_output_file), &Slic3r::GUI::FILE_WILDCARDS->{gcode}, wxFD_SAVE | wxFD_OVERWRITE_PROMPT); if (dlg.ShowModal() != wxID_OK) { return ""; } - auto path = dlg.GetPath(); - // wxTheApp->{app_config}->update_last_output_dir(dirname($path)); // FIXME + fs::path path(dlg.GetPath()); + wxGetApp().app_config->update_last_output_dir(path.parent_path().string()); p->export_gcode_output_file = path; } return p->export_gcode_output_file; } +void Plater::export_stl() +{ + if (p->objects.empty()) { return; } + + auto dialog = p->get_export_file(FT_STL); + if (! dialog) { return; } + + // Store a binary STL + wxString path = dialog->GetPath(); + auto path_cstr = path.c_str(); + auto mesh = p->model.mesh(); + Slic3r::store_stl(path_cstr, &mesh, true); + p->statusbar()->set_status_text(wxString::Format(_(L("STL file exported to %s")), path)); +} + +void Plater::export_amf() +{ + // TODO + throw 0; +} + +void Plater::export_3mf() +{ + // TODO + throw 0; +} + + void Plater::reslice() { // TODO } +void Plater::send_gcode() +{ + p->send_gcode_file = export_gcode(); +} + }} // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index a060eda9ca..f449cc75f5 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -2,11 +2,15 @@ #define slic3r_Plater_hpp_ #include +#include #include #include "Preset.hpp" +class wxButton; + + namespace Slic3r { class Model; @@ -20,10 +24,12 @@ class ObjectList; using t_optgroups = std::vector >; +class Plater; + class Sidebar : public wxPanel { public: - Sidebar(wxWindow *parent); + Sidebar(Plater *parent); Sidebar(Sidebar &&) = delete; Sidebar(const Sidebar &) = delete; Sidebar &operator=(Sidebar &&) = delete; @@ -45,8 +51,6 @@ public: private: struct priv; std::unique_ptr p; - - friend class Plater; // XXX: better encapsulation? }; @@ -63,10 +67,17 @@ public: Sidebar& sidebar(); Model& model(); - // TODO: use fs::path - // Note: empty string means request default path - std::string export_gcode(const std::string &output_path); + void update(bool force_autocenter = false); + void remove(size_t obj_idx); + void remove_selected(); + + // Note: empty path means "use the default" + boost::filesystem::path export_gcode(const boost::filesystem::path &output_path = boost::filesystem::path()); + void export_stl(); + void export_amf(); + void export_3mf(); void reslice(); + void send_gcode(); private: struct priv; std::unique_ptr p; From ceb295944aa8d77c7b2b20b9ae0d178a1f588b7d Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Mon, 8 Oct 2018 19:14:55 +0200 Subject: [PATCH 069/186] WIP: Plater, tracking in Plater.pm --- lib/Slic3r/GUI/Plater.pm | 60 +++++++++++++++++++++- src/slic3r/GUI/Plater.cpp | 103 +++++++++++++++++++++++++++----------- src/slic3r/GUI/Plater.hpp | 4 ++ 3 files changed, 136 insertions(+), 31 deletions(-) diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index b834bc202a..de6b0d7262 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -41,6 +41,7 @@ our $PROCESS_COMPLETED_EVENT = Wx::NewEventType; my $PreventListEvents = 0; our $appController; +# XXX: VK: done, except callback handling and timer sub new { my ($class, $parent, %params) = @_; my $self = $class->SUPER::new($parent, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL); @@ -813,12 +814,14 @@ sub new { return $self; } +# XXX: VK: WIP # sets the callback sub on_select_preset { my ($self, $cb) = @_; $self->{on_select_preset} = $cb; } +# XXX: merged with on_select_preset # Called from the platter combo boxes selecting the active print, filament or printer. sub _on_select_preset { my ($self, $group, $choice, $idx) = @_; @@ -855,6 +858,7 @@ sub _on_select_preset { $self->on_config_change(wxTheApp->{preset_bundle}->full_config); } +# XXX: VK: done sub on_layer_editing_toggled { my ($self, $new_state) = @_; Slic3r::GUI::_3DScene::enable_layers_editing($self->{canvas3D}, $new_state); @@ -873,11 +877,13 @@ sub on_layer_editing_toggled { $self->{canvas3D}->Update; } -sub GetFrame { # XXX: main_frame in C++ Plater +# XXX: VK: done (Plater::priv::main_frame) +sub GetFrame { my ($self) = @_; return &Wx::GetTopLevelParent($self); } +# XXX: not done # Called after the Preferences dialog is closed and the program settings are saved. # Update the UI based on the current preferences. sub update_ui_from_settings @@ -889,6 +895,7 @@ sub update_ui_from_settings } } +# XXX: VK: done # Update preset combo boxes (Print settings, Filament, Material, Printer) from their respective tabs. # Called by # Slic3r::GUI::Tab::Print::_on_presets_changed @@ -934,12 +941,14 @@ sub update_presets { wxTheApp->{preset_bundle}->export_selections(wxTheApp->{app_config}); } +# XXX: VK: done, in on_action_add() sub add { my ($self) = @_; my @input_files = wxTheApp->open_model($self); $self->load_files(\@input_files); } +# XXX: VK: done sub load_files { my ($self, $input_files) = @_; @@ -1030,6 +1039,7 @@ sub load_files { return @obj_idx; } +# XXX: VK: done, except a few todos sub load_model_objects { my ($self, @model_objects) = @_; @@ -1112,6 +1122,7 @@ sub load_model_objects { return @obj_idx; } +# XXX: Removed sub bed_centerf { my ($self) = @_; @@ -1120,6 +1131,7 @@ sub bed_centerf { return Slic3r::Pointf->new(unscale($bed_center->x), unscale($bed_center->y)); #) } +# XXX: VK: done sub remove { my ($self, $obj_idx) = @_; @@ -1146,6 +1158,7 @@ sub remove { $self->update; } +# XXX: VK: done sub reset { my ($self) = @_; @@ -1166,6 +1179,7 @@ sub reset { $self->update; } +# XXX: not done sub increase { my ($self, $copies) = @_; $copies //= 1; @@ -1197,6 +1211,7 @@ sub increase { $self->schedule_background_process; } +# XXX: not done sub decrease { my ($self, $copies_asked) = @_; my $copies = $copies_asked // 1; @@ -1224,6 +1239,7 @@ sub decrease { $self->update; } +# XXX: not done sub set_number_of_copies { my ($self) = @_; # get current number of copies @@ -1242,6 +1258,7 @@ sub set_number_of_copies { } } +# XXX: not done (?) sub _get_number_from_user { # XXX: Enrico my ($self, $title, $prompt_message, $error_message, $default, $only_positive) = @_; for (;;) { @@ -1264,6 +1281,7 @@ sub _get_number_from_user { # XXX: Enrico } } +# XXX: not done sub rotate { my ($self, $angle, $axis, $relative_key, $axis_x, $axis_y, $axis_z) = @_; $relative_key //= 'absolute'; # relative or absolute coordinates @@ -1334,6 +1352,7 @@ sub rotate { $self->update; } +# XXX: not done sub mirror { my ($self, $axis) = @_; @@ -1363,6 +1382,7 @@ sub mirror { $self->update; } +# XXX: not done sub changescale { my ($self, $axis, $tosize) = @_; @@ -1437,6 +1457,7 @@ sub changescale { $self->update; } +# XXX: not done sub arrange { my ($self) = @_; @@ -1454,6 +1475,7 @@ sub arrange { $self->update(0); } +# XXX: not done sub split_object { my $self = shift; @@ -1485,6 +1507,7 @@ sub split_object { } } +# XXX: not done # Trigger $self->async_apply_config() after 500ms. # The call is delayed to avoid restarting the background processing during typing into an edit field. sub schedule_background_process { @@ -1492,6 +1515,7 @@ sub schedule_background_process { $self->{apply_config_timer}->Start(0.5 * 1000, 1); # 1 = one shot, every half a second. } +# XXX: not done # Executed asynchronously by a timer every PROCESS_DELAY (0.5 second). # The timer is started by schedule_background_process(), sub async_apply_config { @@ -1526,6 +1550,7 @@ sub async_apply_config { } } +# XXX: not done # Background processing is started either by the "Slice now" button, by the "Export G-code button" or by async_apply_config(). sub start_background_process { my ($self) = @_; @@ -1546,6 +1571,7 @@ sub start_background_process { $self->{background_slicing_process}->start; } +# XXX: not done # Stop the background processing sub stop_background_process { my ($self) = @_; @@ -1554,6 +1580,7 @@ sub stop_background_process { # $self->{preview3D}->reload_print if $self->{preview3D}; } +# XXX: not done # Called by the "Slice now" button, which is visible only if the background processing is disabled. sub reslice { # explicitly cancel a previous thread and start a new one. @@ -1574,6 +1601,7 @@ sub reslice { } } +# XXX: VK: done sub export_gcode { my ($self, $output_file) = @_; @@ -1654,6 +1682,7 @@ sub export_gcode { return $self->{export_gcode_output_file}; } +# XXX: not done # This message should be called by the background process synchronously. sub on_update_print_preview { my ($self) = @_; @@ -1666,6 +1695,7 @@ sub on_update_print_preview { Slic3r::GUI::_3DScene::reload_scene($self->{canvas3D}, 1); } +# XXX: not done # This gets called also if we have no threads. sub on_progress_event { my ($self, $percent, $message) = @_; @@ -1676,6 +1706,7 @@ sub on_progress_event { $self->statusbar->SetStatusText("$message..."); } +# XXX: not done # Called when the G-code export finishes, either successfully or with an error. # This gets called also if we don't have threads. sub on_process_completed { @@ -1743,6 +1774,7 @@ sub on_process_completed { # $self->{preview3D}->reload_print if $self->{preview3D}; } +# XXX: partially done in the Sidebar # Fill in the "Sliced info" box with the result of the G-code generator. sub print_info_box_show { my ($self, $show) = @_; @@ -1819,6 +1851,7 @@ sub print_info_box_show { $panel->Refresh; } +# XXX: not done - to be removed sub do_print { my ($self) = @_; @@ -1832,6 +1865,7 @@ sub do_print { $printer_panel->load_print_job($self->{print_file}, $filament_stats); } +# XXX: VK: done sub export_stl { my ($self) = @_; return if !@{$self->{objects}}; @@ -1842,6 +1876,7 @@ sub export_stl { $self->statusbar->SetStatusText(L("STL file exported to ").$output_file); } +# XXX: not done sub reload_from_disk { my ($self) = @_; @@ -1873,6 +1908,7 @@ sub reload_from_disk { $self->remove($obj_idx); } +# XXX: VK: done sub export_object_stl { my ($self) = @_; my ($obj_idx, $object) = $self->selected_object; @@ -1884,6 +1920,7 @@ sub export_object_stl { $self->statusbar->SetStatusText(L("STL file exported to ").$output_file); } +# XXX: not done sub fix_through_netfabb { my ($self) = @_; my ($obj_idx, $object) = $self->selected_object; @@ -1912,6 +1949,7 @@ sub fix_through_netfabb { $self->remove($obj_idx); } +# XXX: VK: WIP sub export_amf { my ($self) = @_; return if !@{$self->{objects}}; @@ -1928,6 +1966,7 @@ sub export_amf { } } +# XXX: VK: WIP sub export_3mf { my ($self) = @_; return if !@{$self->{objects}}; @@ -1944,6 +1983,7 @@ sub export_3mf { } } +# XXX: VK: done # Ask user to select an output file for a given file format (STl, AMF, 3MF). # Propose a default file name based on the 'output_filename_format' configuration value. sub _get_export_file { @@ -1993,6 +2033,7 @@ sub _get_export_file { # $self->{objects}[$obj_idx]->thumbnail(undef); #} +# XXX: VK: done # this method gets called whenever print center is changed or the objects' bounding box changes # (i.e. when an object is added/removed/moved/rotated/scaled) sub update { @@ -2016,6 +2057,7 @@ sub update { $self->Thaw; } +# XXX: done in sidebar? # When a printer technology is changed, the UI needs to be updated to show/hide needed preset combo boxes. sub show_preset_comboboxes{ my ($self, $showSLA) = @_; #if showSLA is oposite value to "ptFFF" @@ -2034,6 +2076,7 @@ sub show_preset_comboboxes{ $self->Layout; } +# XXX: not done # When a number of extruders changes, the UI needs to be updated to show a single filament selection combo box per extruder. # Also the wxTheApp->{preset_bundle}->filament_presets needs to be resized accordingly # and some reasonable default has to be selected for the additional extruders. @@ -2078,6 +2121,7 @@ sub on_extruders_change { $self->Layout; } +# XXX: not done sub on_config_change { my ($self, $config) = @_; @@ -2144,6 +2188,7 @@ sub on_config_change { $self->schedule_background_process; } +# XXX: not done sub item_changed_selection { my ($self, $obj_idx) = @_; @@ -2159,6 +2204,7 @@ sub item_changed_selection { } } +# XXX: VK: done sub collect_selections { my ($self) = @_; my $selections = []; @@ -2168,6 +2214,7 @@ sub collect_selections { return $selections; } +# XXX: not done # Called when clicked on the filament preset combo box. # When clicked on the icon, show the color picker. sub filament_color_box_lmouse_down @@ -2221,6 +2268,7 @@ sub filament_color_box_lmouse_down # } #} +# XXX: not done sub changed_object_settings { my ($self, $obj_idx, $parts_changed, $part_settings_changed) = @_; @@ -2246,6 +2294,7 @@ sub changed_object_settings { } } +# XXX: VK: done # Called to update various buttons depending on whether there are any objects or # whether background processing (export of a G-code, sending to Octoprint, forced background re-slicing) is active. sub object_list_changed { @@ -2276,6 +2325,7 @@ sub object_list_changed { for grep $self->{"btn_$_"}, qw(reslice export_gcode print send_gcode); } +# XXX: VK: WIP # Selection of an active 3D object changed. sub selection_changed { my ($self) = @_; @@ -2393,6 +2443,7 @@ sub selection_changed { $self->{right_panel}->Thaw; } +# XXX: VK: done sub select_object { my ($self, $obj_idx, $child) = @_; @@ -2413,6 +2464,7 @@ sub select_object { $self->selection_changed(1); } +# XXX: not done sub select_object_from_cpp { my ($self, $obj_idx, $vol_idx) = @_; @@ -2457,16 +2509,19 @@ sub select_object_from_cpp { $self->selection_changed(1); } +# XXX: VK: done sub selected_object { my ($self) = @_; my $obj_idx = first { $self->{objects}[$_]->selected } 0..$#{ $self->{objects} }; return defined $obj_idx ? ($obj_idx, $self->{objects}[$obj_idx]) : undef; } +# XXX: VK: done sub statusbar { return $_[0]->GetFrame->{statusbar}; } +# XXX: not done, to be removed (?) sub object_menu { my ($self) = @_; @@ -2577,6 +2632,7 @@ sub object_menu { return $menu; } +# XXX: not done # Set a camera direction, zoom to all objects. sub select_view { my ($self, $direction) = @_; @@ -2594,6 +2650,8 @@ sub select_view { } } + +# XXX: VK: done, in PlaterDropTarget package Slic3r::GUI::Plater::DropTarget; use Wx::DND; use base 'Wx::FileDropTarget'; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index b4b0cb726c..1b6f9ad0d3 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -566,6 +566,13 @@ void Sidebar::show_buttons(const bool show) } } +void Sidebar::enable_buttons(bool enable) +{ + p->btn_reslice->Enable(enable); + p->btn_export_gcode->Enable(enable); + p->btn_send_gcode->Enable(enable); +} + // Plater::Object struct PlaterObject @@ -587,13 +594,28 @@ public: private: Plater *plater; + + static const std::regex pattern_drop; }; +const std::regex PlaterDropTarget::pattern_drop("[.](stl|obj|amf|3mf|prusa)$", std::regex::icase); + bool PlaterDropTarget::OnDropFiles(wxCoord x, wxCoord y, const wxArrayString &filenames) { - // TODO - // return false; - throw 0; + std::vector paths; + + for (const auto &filename : filenames) { + fs::path path(filename); + + if (std::regex_match(path.string(), pattern_drop)) { + paths.push_back(std::move(path)); + } else { + return false; + } + } + + plater->load_files(paths); + return true; } // Plater / private @@ -643,7 +665,9 @@ struct Plater::priv void select_object(optional obj_idx); optional selected_object() const; void selection_changed(); + void object_list_changed(); + void remove(size_t obj_idx); void reset(); void on_notebook_changed(wxBookCtrlEvent &); @@ -1081,8 +1105,16 @@ void Plater::priv::select_object(optional obj_idx) objects[*obj_idx].selected = true; } - // TODO: - // $self->selection_changed(1); + selection_changed(); +} + +optional Plater::priv::selected_object() const +{ + for (size_t i = 0; i < objects.size(); i++) { + if (objects[i].selected) { return i; } + } + + return boost::none; } void Plater::priv::selection_changed() @@ -1107,12 +1139,9 @@ void Plater::priv::selection_changed() bool can_select_by_parts = false; if (have_sel) { - // my $model_object = $self->{model}->objects->[$obj_idx]; const auto *model_object = model.objects[*obj_idx]; - // $can_select_by_parts = ($obj_idx >= 0) && ($obj_idx < 1000) && ($model_object->volumes_count > 1); // XXX: ? can_select_by_parts = *obj_idx < 1000 && model_object->volumes.size() > 1; - // Slic3r::GUI::_3DScene::enable_toolbar_item($self->{canvas3D}, "fewer", $model_object->instances_count > 1); _3DScene::enable_toolbar_item(canvas3D, "fewer", model_object->instances.size() > 1); } @@ -1170,20 +1199,43 @@ void Plater::priv::selection_changed() q->Layout(); } -optional Plater::priv::selected_object() const +void Plater::priv::object_list_changed() { - for (size_t i = 0; i < objects.size(); i++) { - if (objects[i].selected) { return i; } - } + // Enable/disable buttons depending on whether there are any objects on the platter. + const bool have_objects = !objects.empty(); - return boost::none; + _3DScene::enable_toolbar_item(canvas3D, "deleteall", have_objects); + _3DScene::enable_toolbar_item(canvas3D, "arrange", have_objects); + + const bool export_in_progress = !(export_gcode_output_file.empty() && send_gcode_file.empty()); + // XXX: is this right? + const bool model_fits = _3DScene::check_volumes_outside_state(canvas3D, config) == ModelInstance::PVS_Inside; + + sidebar->enable_buttons(have_objects && !export_in_progress && model_fits); +} + +void Plater::priv::remove(size_t obj_idx) +{ + // $self->stop_background_process; // TODO + + // Prevent toolpaths preview from rendering while we modify the Print object + preview->set_enabled(false); + + objects.erase(objects.begin() + obj_idx); + model.delete_object(obj_idx); + print.delete_object(obj_idx); + // Delete object from Sidebar list + sidebar->obj_list()->delete_object_from_list(); + + object_list_changed(); + + select_object(boost::none); + update(); } void Plater::priv::reset() { - // TODO - - // $self->stop_background_process; + // $self->stop_background_process; // TODO // Prevent toolpaths preview from rendering while we modify the Print object preview->set_enabled(false); @@ -1193,13 +1245,10 @@ void Plater::priv::reset() print.clear_objects(); // Delete all objects from list on c++ side - // TODO - // Slic3r::GUI::delete_all_objects_from_list(); sidebar->obj_list()->delete_all_objects_from_list(); - // $self->object_list_changed; + object_list_changed(); - // TODO - // $self->select_object(undef); + select_object(boost::none); update(); } @@ -1350,15 +1399,8 @@ Plater::~Plater() Sidebar& Plater::sidebar() { return *p->sidebar; } Model& Plater::model() { return p->model; } -void Plater::update(bool force_autocenter) -{ - p->update(force_autocenter); -} - -void Plater::remove(size_t obj_idx) -{ - // TODO -} +void Plater::update(bool force_autocenter) { p->update(force_autocenter); } +void Plater::remove(size_t obj_idx) { p->remove(obj_idx); } void Plater::remove_selected() { @@ -1368,6 +1410,7 @@ void Plater::remove_selected() } } +void Plater::load_files(const std::vector &input_files) { p->load_files(input_files); } fs::path Plater::export_gcode(const fs::path &output_path) { diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index f449cc75f5..17b911c04b 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -2,6 +2,7 @@ #define slic3r_Plater_hpp_ #include +#include #include #include @@ -47,6 +48,7 @@ public: int get_ol_selection(); void show_info_sizers(const bool show); void show_buttons(const bool show); + void enable_buttons(bool enable); private: struct priv; @@ -71,6 +73,8 @@ public: void remove(size_t obj_idx); void remove_selected(); + void load_files(const std::vector &input_files); + // Note: empty path means "use the default" boost::filesystem::path export_gcode(const boost::filesystem::path &output_path = boost::filesystem::path()); void export_stl(); From 928c146aefa67d64f113e52f6895ab04971cb7c2 Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Mon, 8 Oct 2018 19:55:30 +0200 Subject: [PATCH 070/186] WIP: Plater: Event handling boilerplate / skeletons --- lib/Slic3r/GUI/Plater.pm | 4 +- src/slic3r/GUI/Plater.cpp | 141 +++++++++++++++++++++++++++++++++----- 2 files changed, 124 insertions(+), 21 deletions(-) diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index de6b0d7262..e9668225f7 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -1949,7 +1949,7 @@ sub fix_through_netfabb { $self->remove($obj_idx); } -# XXX: VK: WIP +# XXX: VK: done sub export_amf { my ($self) = @_; return if !@{$self->{objects}}; @@ -1966,7 +1966,7 @@ sub export_amf { } } -# XXX: VK: WIP +# XXX: VK: done sub export_3mf { my ($self) = @_; return if !@{$self->{objects}}; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 1b6f9ad0d3..040348a163 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -27,6 +27,8 @@ #include "libslic3r/Utils.hpp" #include "libslic3r/Polygon.hpp" #include "libslic3r/Format/STL.hpp" +#include "libslic3r/Format/AMF.hpp" +#include "libslic3r/Format/3mf.hpp" #include "GUI.hpp" #include "GUI_App.hpp" #include "GUI_ObjectList.hpp" @@ -669,13 +671,16 @@ struct Plater::priv void remove(size_t obj_idx); void reset(); + void increase(size_t num = 1); + void decrease(size_t num = 1); - void on_notebook_changed(wxBookCtrlEvent &); - void on_select_preset(wxCommandEvent &); - void on_update_print_preview(wxCommandEvent &); - void on_process_completed(wxCommandEvent &); + void on_notebook_changed(wxBookCtrlEvent&); + void on_select_preset(wxCommandEvent&); + void on_update_print_preview(wxCommandEvent&); + void on_process_completed(wxCommandEvent&); void on_layer_editing_toggled(bool enable); + void on_action_add(SimpleEvent&); void on_action_arrange(SimpleEvent&); void on_action_more(SimpleEvent&); @@ -686,7 +691,16 @@ struct Plater::priv void on_action_layersediting(SimpleEvent&); void on_action_selectbyparts(SimpleEvent&); - void on_viewport_changed(SimpleEvent& evt); + void on_viewport_changed(SimpleEvent&); + void on_right_click(Vec2dEvent&); + void on_model_update(SimpleEvent&); + void on_remove_object(SimpleEvent&); + void on_arrange(SimpleEvent&); + void on_scale_uniformly(SimpleEvent&); + void on_instance_moves(SimpleEvent&); + void on_wipetower_moved(Vec3dEvent&); + void on_enable_action_buttons(Event&); + void on_update_geometry(Vec3dsEvent<2>&); }; const std::regex Plater::priv::pattern_bundle("[.](amf|amf[.]xml|zip[.]amf|3mf|prusa)$", std::regex::icase); @@ -763,15 +777,22 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) : // Preset change event sidebar->Bind(wxEVT_COMBOBOX, &priv::on_select_preset, this); - // Sidebar button events - // sidebar->p->btn_export_gcode->Bind(wxEVT_BUTTON, [q](wxCommandEvent&) { q->export_gcode(); }); - // sidebar->p->btn_reslice->Bind(wxEVT_BUTTON, [q](wxCommandEvent&) { q->reslice(); }); - // sidebar->p->btn_send_gcode->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { - // this->send_gcode_file = this->q->export_gcode(); - // }); - // 3DScene events: - // TODO: more + canvas3D->Bind(EVT_GLCANVAS_OBJECT_SELECT, [](ObjectSelectEvent&) { /*TODO*/ }); + canvas3D->Bind(EVT_GLCANVAS_VIEWPORT_CHANGED, &priv::on_viewport_changed, this); + // canvas3D->Bind(EVT_GLCANVAS_DOUBLE_CLICK, [](SimpleEvent&) { }); // XXX: remove? + canvas3D->Bind(EVT_GLCANVAS_RIGHT_CLICK, &priv::on_right_click, this); + canvas3D->Bind(EVT_GLCANVAS_MODEL_UPDATE, &priv::on_model_update, this); + canvas3D->Bind(EVT_GLCANVAS_REMOVE_OBJECT, &priv::on_remove_object, this); + canvas3D->Bind(EVT_GLCANVAS_ARRANGE, &priv::on_arrange, this); + canvas3D->Bind(EVT_GLCANVAS_ROTATE_OBJECT, [this](Event &evt) { /*TODO: call rotate */ }); + canvas3D->Bind(EVT_GLCANVAS_SCALE_UNIFORMLY, &priv::on_scale_uniformly, this); + canvas3D->Bind(EVT_GLCANVAS_INCREASE_OBJECTS, [this](Event &evt) { evt.data == 1 ? increase() : decrease(); }); + canvas3D->Bind(EVT_GLCANVAS_INSTANCE_MOVES, &priv::on_instance_moves, this); + canvas3D->Bind(EVT_GLCANVAS_WIPETOWER_MOVED, &priv::on_wipetower_moved, this); + canvas3D->Bind(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, &priv::on_enable_action_buttons, this); + canvas3D->Bind(EVT_GLCANVAS_UPDATE_GEOMETRY, &priv::on_update_geometry, this); + // 3DScene/Toolbar: canvas3D->Bind(EVT_GLTOOLBAR_ADD, &priv::on_action_add, this); canvas3D->Bind(EVT_GLTOOLBAR_DELETE, [q](SimpleEvent&) { q->remove_selected(); } ); canvas3D->Bind(EVT_GLTOOLBAR_DELETE_ALL, [this](SimpleEvent&) { reset(); }); @@ -784,8 +805,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) : canvas3D->Bind(EVT_GLTOOLBAR_LAYERSEDITING, &priv::on_action_layersediting, this); canvas3D->Bind(EVT_GLTOOLBAR_SELECTBYPARTS, &priv::on_action_selectbyparts, this); - canvas3D->Bind(EVT_GLCANVAS_VIEWPORT_CHANGED, &priv::on_viewport_changed, this); - + // Preview events: preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_VIEWPORT_CHANGED, &priv::on_viewport_changed, this); q->Bind(EVT_SLICING_COMPLETED, &priv::on_update_print_preview, this); @@ -1252,6 +1272,16 @@ void Plater::priv::reset() update(); } +void Plater::priv::increase(size_t num) +{ + // TODO +} + +void Plater::priv::decrease(size_t num) +{ + // TODO +} + void Plater::priv::on_notebook_changed(wxBookCtrlEvent&) { @@ -1383,6 +1413,53 @@ void Plater::priv::on_viewport_changed(SimpleEvent& evt) preview->set_viewport_from_scene(canvas3D); } +void Plater::priv::on_right_click(Vec2dEvent&) +{ + // TODO +} + +void Plater::priv::on_model_update(SimpleEvent&) +{ + // TODO +} + +void Plater::priv::on_remove_object(SimpleEvent&) +{ + // TODO +} + +void Plater::priv::on_arrange(SimpleEvent&) +{ + // TODO +} + +void Plater::priv::on_scale_uniformly(SimpleEvent&) +{ + // TODO +} + +void Plater::priv::on_instance_moves(SimpleEvent&) +{ + // TODO +} + +void Plater::priv::on_wipetower_moved(Vec3dEvent&) +{ + // TODO +} + +void Plater::priv::on_enable_action_buttons(Event&) +{ + // TODO +} + +void Plater::priv::on_update_geometry(Vec3dsEvent<2>&) +{ + // TODO +} + + + // Plater / Public Plater::Plater(wxWindow *parent, MainFrame *main_frame) @@ -1482,14 +1559,40 @@ void Plater::export_stl() void Plater::export_amf() { - // TODO - throw 0; + if (p->objects.empty()) { return; } + + auto dialog = p->get_export_file(FT_AMF); + if (! dialog) { return; } + + wxString path = dialog->GetPath(); + auto path_cstr = path.c_str(); + + if (Slic3r::store_amf(path_cstr, &p->model, &p->print, dialog->get_checkbox_value())) { + // Success + p->statusbar()->set_status_text(wxString::Format(_(L("AMF file exported to %s")), path)); + } else { + // Failure + p->statusbar()->set_status_text(wxString::Format(_(L("Error exporting AMF file %s")), path)); + } } void Plater::export_3mf() { - // TODO - throw 0; + if (p->objects.empty()) { return; } + + auto dialog = p->get_export_file(FT_3MF); + if (! dialog) { return; } + + wxString path = dialog->GetPath(); + auto path_cstr = path.c_str(); + + if (Slic3r::store_3mf(path_cstr, &p->model, &p->print, dialog->get_checkbox_value())) { + // Success + p->statusbar()->set_status_text(wxString::Format(_(L("3MF file exported to %s")), path)); + } else { + // Failure + p->statusbar()->set_status_text(wxString::Format(_(L("Error exporting 3MF file %s")), path)); + } } From 47fc10983732b9485f7ab37df46e5af365b17026 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Tue, 9 Oct 2018 09:07:49 +0200 Subject: [PATCH 071/186] New selection -> removed select by parts --- src/slic3r/GUI/Plater.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 040348a163..4adea60677 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -689,7 +689,9 @@ struct Plater::priv void on_action_cut(SimpleEvent&); void on_action_settings(SimpleEvent&); void on_action_layersediting(SimpleEvent&); +#if !ENABLE_EXTENDED_SELECTION void on_action_selectbyparts(SimpleEvent&); +#endif // !ENABLE_EXTENDED_SELECTION void on_viewport_changed(SimpleEvent&); void on_right_click(Vec2dEvent&); @@ -803,7 +805,9 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) : canvas3D->Bind(EVT_GLTOOLBAR_CUT, &priv::on_action_cut, this); canvas3D->Bind(EVT_GLTOOLBAR_SETTINGS, &priv::on_action_settings, this); canvas3D->Bind(EVT_GLTOOLBAR_LAYERSEDITING, &priv::on_action_layersediting, this); +#if !ENABLE_EXTENDED_SELECTION canvas3D->Bind(EVT_GLTOOLBAR_SELECTBYPARTS, &priv::on_action_selectbyparts, this); +#endif // !ENABLE_EXTENDED_SELECTION // Preview events: preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_VIEWPORT_CHANGED, &priv::on_viewport_changed, this); @@ -1156,15 +1160,20 @@ void Plater::priv::selection_changed() _3DScene::enable_toolbar_item(canvas3D, "layersediting", layers_height_allowed); +#if !ENABLE_EXTENDED_SELECTION bool can_select_by_parts = false; +#endif // !ENABLE_EXTENDED_SELECTION if (have_sel) { const auto *model_object = model.objects[*obj_idx]; +#if !ENABLE_EXTENDED_SELECTION // XXX: ? can_select_by_parts = *obj_idx < 1000 && model_object->volumes.size() > 1; +#endif // !ENABLE_EXTENDED_SELECTION _3DScene::enable_toolbar_item(canvas3D, "fewer", model_object->instances.size() > 1); } +#if !ENABLE_EXTENDED_SELECTION if (can_select_by_parts) { // first disable to let the item in the toolbar to switch to the unpressed state // XXX: ? _3DScene::enable_toolbar_item(canvas3D, "selectbyparts", false); @@ -1173,6 +1182,7 @@ void Plater::priv::selection_changed() _3DScene::enable_toolbar_item(canvas3D, "selectbyparts", false); _3DScene::set_select_by(canvas3D, "object"); } +#endif // !ENABLE_EXTENDED_SELECTION if (have_sel) { const auto *model_object = model.objects[*obj_idx]; @@ -1398,11 +1408,12 @@ void Plater::priv::on_action_layersediting(SimpleEvent&) // TODO } +#if !ENABLE_EXTENDED_SELECTION void Plater::priv::on_action_selectbyparts(SimpleEvent&) { // TODO } - +#endif // !ENABLE_EXTENDED_SELECTION void Plater::priv::on_viewport_changed(SimpleEvent& evt) { From dffae0aa124f3f948430924c61071a043d6306b2 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Tue, 9 Oct 2018 09:12:38 +0200 Subject: [PATCH 072/186] Fixed new selection compile errors --- src/slic3r/GUI/Plater.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index befe67fac5..253c5174b6 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1636,10 +1636,12 @@ void Plater::changed_object_settings(int obj_idx) // stop_background_process(); // $self->{print}->reload_object($obj_idx); // schedule_background_process(); +#if !ENABLE_EXTENDED_SELECTION if (p->canvas3D) _3DScene::reload_scene(p->canvas3D, true); auto selections = p->collect_selections(); _3DScene::set_objects_selections(p->canvas3D, selections); _3DScene::reload_scene(p->canvas3D, false); +#endif // !ENABLE_EXTENDED_SELECTION } else { // schedule_background_process(); From 322e0a433cd6ad9315415072827334af7ebc2270 Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Tue, 9 Oct 2018 09:35:19 +0200 Subject: [PATCH 073/186] Plater: Add missing skeletons (un-typed for now) --- lib/Slic3r/GUI/Plater.pm | 4 +- src/slic3r/GUI/GUI_ObjectList.cpp | 2 +- src/slic3r/GUI/Plater.cpp | 146 +++++++++++++++++++++++++++++- 3 files changed, 148 insertions(+), 4 deletions(-) diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index e9668225f7..94f01e25d9 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -1122,7 +1122,7 @@ sub load_model_objects { return @obj_idx; } -# XXX: Removed +# XXX: Removed, replaced with bed_shape_bb() sub bed_centerf { my ($self) = @_; @@ -1382,7 +1382,7 @@ sub mirror { $self->update; } -# XXX: not done +# XXX: not done, renamed as Plater::priv::scale() sub changescale { my ($self, $axis, $tosize) = @_; diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index bad81a22e4..2583df975d 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -62,7 +62,7 @@ ObjectList::ObjectList(wxWindow* parent) : }); #else // equivalent to wxEVT_CHOICE on __WXMSW__ - m_objects_ctrl->Bind(wxEVT_DATAVIEW_ITEM_VALUE_CHANGED, [this](wxDataViewEvent& e) { object_ctrl_item_value_change(e); }); + Bind(wxEVT_DATAVIEW_ITEM_VALUE_CHANGED, [this](wxDataViewEvent& e) { object_ctrl_item_value_change(e); }); #endif //__WXMSW__ Bind(wxEVT_DATAVIEW_ITEM_BEGIN_DRAG, [this](wxDataViewEvent& e) {on_begin_drag(e); }); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 253c5174b6..d1a40edfc1 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -20,6 +20,7 @@ #include #include +#include "libslic3r/libslic3r.h" #include "libslic3r/PrintConfig.hpp" #include "libslic3r/Model.hpp" #include "libslic3r/Print.hpp" @@ -668,21 +669,41 @@ struct Plater::priv std::unique_ptr get_export_file(GUI::FileType file_type); void select_object(optional obj_idx); + void select_object_from_cpp(); optional selected_object() const; void selection_changed(); void object_list_changed(); + void select_view(); void remove(size_t obj_idx); void reset(); void increase(size_t num = 1); void decrease(size_t num = 1); + void set_number_of_copies(); + void rotate(); + void mirror(const Axis &axis); + void scale(); + void arrange(); + void split_object(); + void schedule_background_process(); + void async_apply_config(); + void start_background_process(); + void stop_background_process(); + void reload_from_disk(); + void export_object_stl(); + void fix_through_netfabb(); + void show_preset_comboboxes(); + void item_changed_selection(); + void filament_color_box_lmouse_down(); void on_notebook_changed(wxBookCtrlEvent&); void on_select_preset(wxCommandEvent&); + void on_progress_event(); void on_update_print_preview(wxCommandEvent&); void on_process_completed(wxCommandEvent&); void on_layer_editing_toggled(bool enable); - + void on_extruders_change(); + void on_config_change(); void on_action_add(SimpleEvent&); void on_action_arrange(SimpleEvent&); @@ -1131,6 +1152,11 @@ void Plater::priv::select_object(optional obj_idx) selection_changed(); } +void Plater::priv::select_object_from_cpp() +{ + // TODO +} + optional Plater::priv::selected_object() const { for (size_t i = 0; i < objects.size(); i++) { @@ -1243,6 +1269,11 @@ void Plater::priv::object_list_changed() sidebar->enable_buttons(have_objects && !export_in_progress && model_fits); } +void Plater::priv::select_view() +{ + // TODO +} + void Plater::priv::remove(size_t obj_idx) { // $self->stop_background_process; // TODO @@ -1291,6 +1322,104 @@ void Plater::priv::decrease(size_t num) // TODO } +void Plater::priv::set_number_of_copies() +{ + // TODO +} + +void Plater::priv::rotate() +{ + // TODO +} + +void Plater::priv::mirror(const Axis &axis) +{ + const auto obj_idx = selected_object(); + if (! obj_idx) { return; } + + auto *model_object = model.objects[*obj_idx]; + auto *model_instance = model_object->instances[0]; + + // XXX: ? + // # apply Z rotation before mirroring + // if ($model_instance->rotation != 0) { + // $model_object->rotate($model_instance->rotation, Slic3r::Pointf3->new(0, 0, 1)); + // $_->set_rotation(0) for @{ $model_object->instances }; + // } + + model_object->mirror(axis); + + // $self->stop_background_process; // TODO + print.add_model_object(model_object, *obj_idx); + selection_changed(); + update(); +} + +void Plater::priv::scale() +{ + // TODO +} + +void Plater::priv::arrange() +{ + // TODO +} + +void Plater::priv::split_object() +{ + // TODO +} + +void Plater::priv::schedule_background_process() +{ + // TODO +} + +void Plater::priv::async_apply_config() +{ + // TODO +} + +void Plater::priv::start_background_process() +{ + // TODO +} + +void Plater::priv::stop_background_process() +{ + // TODO +} + +void Plater::priv::reload_from_disk() +{ + // TODO +} + +void Plater::priv::export_object_stl() +{ + // TODO +} + +void Plater::priv::fix_through_netfabb() +{ + // TODO +} + +void Plater::priv::show_preset_comboboxes() +{ + // TODO +} + +void Plater::priv::item_changed_selection() +{ + // TODO +} + +void Plater::priv::filament_color_box_lmouse_down() +{ + // TODO +} + void Plater::priv::on_notebook_changed(wxBookCtrlEvent&) { @@ -1339,6 +1468,11 @@ void Plater::priv::on_select_preset(wxCommandEvent &evt) // $self->on_config_change(wxTheApp->{preset_bundle}->full_config); } +void Plater::priv::on_progress_event() +{ + // TODO +} + void Plater::priv::on_update_print_preview(wxCommandEvent &) { // TODO @@ -1360,6 +1494,16 @@ void Plater::priv::on_layer_editing_toggled(bool enable) canvas3D->Update(); } +void Plater::priv::on_extruders_change() +{ + // TODO +} + +void Plater::priv::on_config_change() +{ + // TODO +} + void Plater::priv::on_action_add(SimpleEvent&) { wxArrayString input_files; From 085020a8145d73dfebd65358c9c25406372cffad Mon Sep 17 00:00:00 2001 From: YuSanka Date: Tue, 9 Oct 2018 12:41:05 +0200 Subject: [PATCH 074/186] Ported show_preset_comboboxes function --- src/slic3r/GUI/MainFrame.cpp | 24 ++++++------- src/slic3r/GUI/MainFrame.hpp | 1 + src/slic3r/GUI/Plater.cpp | 67 ++++++++++++++++++++++-------------- src/slic3r/GUI/Plater.hpp | 21 ++++++++++- src/slic3r/GUI/Preset.cpp | 9 ++--- src/slic3r/GUI/Preset.hpp | 3 +- src/slic3r/GUI/Tab.cpp | 21 +++++------ src/slic3r/GUI/Tab.hpp | 5 +++ 8 files changed, 93 insertions(+), 58 deletions(-) diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 8df8e338a4..4dbaa9d09b 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -132,7 +132,8 @@ void MainFrame::init_tabpanel() m_tabpanel->AddPage(m_plater, _(L("Plater"))); } - // The following event is emited by the C++ Tab implementation on config value change. + // The following event is emited by Tab implementation on config value change. + Bind(EVT_TAB_VALUE_CHANGED, &MainFrame::on_value_changed, this); // EVT_COMMAND($self, -1, $VALUE_CHANGE_EVENT, sub { // my($self, $event) = @_; // auto str = event->GetString; @@ -145,10 +146,6 @@ void MainFrame::init_tabpanel() // auto value = event->GetInt(); // m_plater->on_extruders_change(value); // } -// if (opt_key == "printer_technology"){ -// auto value = event->GetInt(); // 0 ~"ptFFF"; 1 ~"ptSLA" -// m_plater->show_preset_comboboxes(value); -// } // } // // don't save while loading for the first time // if (Slic3r::GUI::autosave && m_loaded) @@ -759,21 +756,14 @@ void MainFrame::on_presets_changed(SimpleEvent &event) auto reload_dependent_tabs = tab->get_dependent_tabs(); // FIXME: The preset type really should be a property of Tab instead - Slic3r::Preset::Type preset_type; - if (tab == m_options_tabs["print"]) { preset_type = Slic3r::Preset::TYPE_PRINT; } - else if (tab == m_options_tabs["filament"]) { preset_type = Slic3r::Preset::TYPE_FILAMENT; } - else if (tab == m_options_tabs["sla_material"]) { preset_type = Slic3r::Preset::TYPE_SLA_MATERIAL; } - else if (tab == m_options_tabs["printer"]) { preset_type = Slic3r::Preset::TYPE_PRINTER; } - else { + Slic3r::Preset::Type preset_type = tab->type(); + if (preset_type == Slic3r::Preset::TYPE_INVALID){ wxASSERT(false); return; } m_plater->sidebar().update_presets(preset_type); - // XXX: ??? - // m_plater->{"selected_item_$tab_name"} = tab->get_selected_preset_item(); - if (preset_type == Slic3r::Preset::TYPE_PRINTER) { // Printer selected at the Printer tab, update "compatible" marks at the print and filament selectors. // XXX: Do this in a more C++ way @@ -789,12 +779,18 @@ void MainFrame::on_presets_changed(SimpleEvent &event) else cur_tab->load_current_preset(); } + m_plater->sidebar().show_preset_comboboxes(static_cast(tab)->m_printer_technology == ptSLA); } // XXX: ? // m_plater->on_config_change(tab->get_config()); } } +void MainFrame::on_value_changed(wxCommandEvent&) +{ + ; +} + // Called after the Preferences dialog is closed and the program settings are saved. // Update the UI based on the current preferences. void MainFrame::update_ui_from_settings() diff --git a/src/slic3r/GUI/MainFrame.hpp b/src/slic3r/GUI/MainFrame.hpp index 03b27a98b8..aa2041a368 100644 --- a/src/slic3r/GUI/MainFrame.hpp +++ b/src/slic3r/GUI/MainFrame.hpp @@ -73,6 +73,7 @@ class MainFrame : public wxFrame std::string get_dir_name(const wxString full_name) const ; void on_presets_changed(SimpleEvent&); + void on_value_changed(wxCommandEvent&); Tab* get_tab(const std::string& name); public: diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 23e26a73f8..7163219723 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -168,21 +168,6 @@ SlicedInfo::SlicedInfo(wxWindow *parent) : Add(grid_sizer, 0, wxEXPAND); } - -class PresetComboBox : public wxBitmapComboBox -{ -public: - PresetComboBox(wxWindow *parent, Preset::Type preset_type); - ~PresetComboBox(); - -private: - typedef std::size_t Marker; - enum { LABEL_ITEM_MARKER = 0x4d }; - - Preset::Type preset_type; - int last_selected; -}; - PresetComboBox::PresetComboBox(wxWindow *parent, Preset::Type preset_type) : wxBitmapComboBox(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, nullptr, wxCB_READONLY), preset_type(preset_type), @@ -198,6 +183,7 @@ PresetComboBox::PresetComboBox(wxWindow *parent, Preset::Type preset_type) : } else if (this->last_selected != selected_item) { this->last_selected = selected_item; evt.SetInt(this->preset_type); + evt.Skip(); } else { evt.StopPropagation(); } @@ -207,6 +193,11 @@ PresetComboBox::PresetComboBox(wxWindow *parent, Preset::Type preset_type) : PresetComboBox::~PresetComboBox() {} +void PresetComboBox::set_label_marker(int item) +{ + this->SetClientData(item, (void*)LABEL_ITEM_MARKER); +} + // Frequently changed parameters class FreqChangedParams : public OG_Settings @@ -520,6 +511,22 @@ void Sidebar::update_presets(Preset::Type preset_type) wxGetApp().preset_bundle->export_selections(*wxGetApp().app_config); } +void Sidebar::show_preset_comboboxes(bool showSLA) +{ +// wxWindowUpdateLocker noUpdates(wxGetApp().mainframe); + + for (size_t i = 0; i < 4; ++i) + p->sizer_presets->Show(i, !showSLA); + + p->sizer_presets->Show(4, showSLA); + p->sizer_presets->Show(5, showSLA); + + p->frequently_changed_parameters->get_sizer()->Show(!showSLA); + + wxGetApp().plater()->Layout(); + wxGetApp().mainframe->Layout(); +} + ObjectManipulation* Sidebar::obj_manipul() { return p->object_manipulation; @@ -578,6 +585,11 @@ void Sidebar::enable_buttons(bool enable) p->btn_send_gcode->Enable(enable); } +bool Sidebar::is_multifilament() +{ + return p->combos_filament.size() > 0; +} + // Plater::Object struct PlaterObject @@ -1305,26 +1317,29 @@ void Plater::priv::on_select_preset(wxCommandEvent &evt) auto preset_type = static_cast(evt.GetInt()); auto *combo = static_cast(evt.GetEventObject()); + auto idx = 0;// evt.GetId(); + if (preset_type == Preset::TYPE_FILAMENT) { - // FIXME: - // wxTheApp->{preset_bundle}->set_filament_preset($idx, $choice->GetStringSelection); + wxGetApp().preset_bundle->set_filament_preset(idx, combo->GetStringSelection().ToStdString()); } // TODO: ? - if (false) { - // if ($group eq 'filament' && @{$self->{preset_choosers}{filament}} > 1) { - // # Only update the platter UI for the 2nd and other filaments. - // wxTheApp->{preset_bundle}->update_platter_filament_ui($idx, $choice); + if (preset_type == Preset::TYPE_FILAMENT && sidebar->is_multifilament()) { + // Only update the platter UI for the 2nd and other filaments. + wxGetApp().preset_bundle->update_platter_filament_ui(idx, combo); // } } else { - auto selected_item = combo->GetSelection(); - - // TODO: Handle by an event handler in MainFrame, if needed + for (Tab* tab : wxGetApp().tabs_list) { + if (tab->type() == preset_type) { + tab->select_preset(combo->GetStringSelection().ToStdString()); + break; + } + } } + // Synchronize config.ini with the current selections. + wxGetApp().preset_bundle->export_selections(*wxGetApp().app_config); // TODO: - // # Synchronize config.ini with the current selections. - // wxTheApp->{preset_bundle}->export_selections(wxTheApp->{app_config}); // # get new config and generate on_config_change() event for updating plater and other things // $self->on_config_change(wxTheApp->{preset_bundle}->full_config); } diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 0592579dbe..51291ee226 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -6,6 +6,7 @@ #include #include +#include #include "Preset.hpp" @@ -27,6 +28,22 @@ using t_optgroups = std::vector >; class Plater; +class PresetComboBox : public wxBitmapComboBox +{ +public: + PresetComboBox(wxWindow *parent, Preset::Type preset_type); + ~PresetComboBox(); + + void set_label_marker(int item); + +private: + typedef std::size_t Marker; + enum { LABEL_ITEM_MARKER = 0x4d }; + + Preset::Type preset_type; + int last_selected; +}; + class Sidebar : public wxPanel { public: @@ -38,8 +55,9 @@ public: ~Sidebar(); void update_presets(Slic3r::Preset::Type preset_type); + void show_preset_comboboxes(bool showSLA); - ObjectManipulation* obj_manipul(); + ObjectManipulation* obj_manipul(); ObjectList* obj_list(); ConfigOptionsGroup* og_freq_chng_params(); @@ -49,6 +67,7 @@ public: void show_info_sizers(const bool show); void show_buttons(const bool show); void enable_buttons(bool enable); + bool is_multifilament(); private: struct priv; diff --git a/src/slic3r/GUI/Preset.cpp b/src/slic3r/GUI/Preset.cpp index 9911caa5b8..1a6063dc73 100644 --- a/src/slic3r/GUI/Preset.cpp +++ b/src/slic3r/GUI/Preset.cpp @@ -28,6 +28,7 @@ #include "../../libslic3r/libslic3r.h" #include "../../libslic3r/Utils.hpp" #include "../../libslic3r/PlaceholderParser.hpp" +#include "Plater.hpp" using boost::property_tree::ptree; @@ -734,7 +735,7 @@ size_t PresetCollection::update_compatible_with_printer_internal(const Preset &a // Update the wxChoice UI component from this list of presets. // Hide the -void PresetCollection::update_platter_ui(wxBitmapComboBox *ui) +void PresetCollection::update_platter_ui(GUI::PresetComboBox *ui) { if (ui == nullptr) return; @@ -751,7 +752,7 @@ void PresetCollection::update_platter_ui(wxBitmapComboBox *ui) std::map nonsys_presets; wxString selected = ""; if (!this->m_presets.front().is_visible) - ui->Append("------- " +_(L("System presets")) + " -------", wxNullBitmap); + ui->set_label_marker(ui->Append("------- " + _(L("System presets")) + " -------", wxNullBitmap)); for (size_t i = this->m_presets.front().is_visible ? 0 : m_num_default_presets; i < this->m_presets.size(); ++i) { const Preset &preset = this->m_presets[i]; if (! preset.is_visible || (! preset.is_compatible && i != m_idx_selected)) @@ -791,11 +792,11 @@ void PresetCollection::update_platter_ui(wxBitmapComboBox *ui) selected = wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str()); } if (i + 1 == m_num_default_presets) - ui->Append("------- " + _(L("System presets")) + " -------", wxNullBitmap); + ui->set_label_marker(ui->Append("------- " + _(L("System presets")) + " -------", wxNullBitmap)); } if (!nonsys_presets.empty()) { - ui->Append("------- " + _(L("User presets")) + " -------", wxNullBitmap); + ui->set_label_marker(ui->Append("------- " + _(L("User presets")) + " -------", wxNullBitmap)); for (std::map::iterator it = nonsys_presets.begin(); it != nonsys_presets.end(); ++it) { ui->Append(it->first, *it->second); if (it->first == selected) diff --git a/src/slic3r/GUI/Preset.hpp b/src/slic3r/GUI/Preset.hpp index bed9364110..2d56e96c2d 100644 --- a/src/slic3r/GUI/Preset.hpp +++ b/src/slic3r/GUI/Preset.hpp @@ -22,6 +22,7 @@ class PresetBundle; namespace GUI { class BitmapCache; + class PresetComboBox; } enum ConfigFileType @@ -355,7 +356,7 @@ public: // Update the choice UI from the list of presets. // Only the compatible presets are shown. // If an incompatible preset is selected, it is shown as well. - void update_platter_ui(wxBitmapComboBox *ui); + void update_platter_ui(GUI::PresetComboBox *ui); // Update a dirty floag of the current preset, update the labels of the UI component accordingly. // Return true if the dirty flag changed. diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 84a7972c4f..015e03b259 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -38,6 +38,15 @@ wxDEFINE_EVENT(EVT_TAB_VALUE_CHANGED, wxCommandEvent); wxDEFINE_EVENT(EVT_TAB_PRESETS_CHANGED, SimpleEvent); +void Tab::set_type() +{ + if (m_name == "print") { m_type = Slic3r::Preset::TYPE_PRINT; } + else if (m_name == "filament") { m_type = Slic3r::Preset::TYPE_FILAMENT; } + else if (m_name == "sla_material") { m_type = Slic3r::Preset::TYPE_SLA_MATERIAL; } + else if (m_name == "printer") { m_type = Slic3r::Preset::TYPE_PRINTER; } + else { m_type = Slic3r::Preset::TYPE_INVALID; } +} + // sub new void Tab::create_preset_tab() { @@ -672,14 +681,6 @@ void Tab::on_value_change(const std::string& opt_key, const boost::any& value) event.SetInt(val); } - if (opt_key == "printer_technology") - { - int val = boost::any_cast(value); - event.SetInt(val); - wxPostEvent(this, event); - return; - } - wxPostEvent(this, event); @@ -1461,8 +1462,6 @@ void TabPrinter::build() m_printer_technology = m_presets->get_selected_preset().printer_technology(); m_presets->get_selected_preset().printer_technology() == ptSLA ? build_sla() : build_fff(); - -// on_value_change("printer_technology", m_printer_technology); // to update show/hide preset ComboBoxes } void TabPrinter::build_fff() @@ -2044,8 +2043,6 @@ void TabPrinter::update_pages() m_pages_sla.empty() ? build_sla() : m_pages.swap(m_pages_sla); rebuild_page_tree(true); - - on_value_change("printer_technology", m_presets->get_edited_preset().printer_technology()); // to update show/hide preset ComboBoxes } void TabPrinter::update() diff --git a/src/slic3r/GUI/Tab.hpp b/src/slic3r/GUI/Tab.hpp index 2e80c36a8e..fecb642f4d 100644 --- a/src/slic3r/GUI/Tab.hpp +++ b/src/slic3r/GUI/Tab.hpp @@ -108,6 +108,7 @@ class Tab: public wxPanel int m_size_move = -1; #endif // __WXOSX__ protected: + Preset::Type m_type; std::string m_name; const wxString m_title; wxBitmapComboBox* m_presets_choice; @@ -183,6 +184,8 @@ protected: size_t m_selected_preset_item{ 0 }; + void set_type(); + public: PresetBundle* m_preset_bundle; bool m_show_btn_incompatible_presets = false; @@ -196,6 +199,7 @@ public: Tab(wxNotebook* parent, const wxString& title, const char* name) : m_parent(parent), m_title(title), m_name(name) { Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBK_LEFT | wxTAB_TRAVERSAL, name); + set_type(); wxGetApp().tabs_list.push_back(this); } ~Tab(){ @@ -205,6 +209,7 @@ public: wxWindow* parent() const { return m_parent; } wxString title() const { return m_title; } std::string name() const { return m_name; } + Preset::Type type() const { return m_type; } void create_preset_tab(); void load_current_preset(); From 895bdf79184b27756bcc5e9359c0d2aa2a3e2785 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Tue, 9 Oct 2018 15:56:34 +0200 Subject: [PATCH 075/186] New selection -> rotation wip --- src/slic3r/GUI/3DScene.cpp | 17 + src/slic3r/GUI/GLCanvas3D.cpp | 370 ++++++++++++++-------- src/slic3r/GUI/GLCanvas3D.hpp | 52 ++- src/slic3r/GUI/GUI_ObjectManipulation.cpp | 59 +++- src/slic3r/GUI/GUI_ObjectManipulation.hpp | 5 +- 5 files changed, 345 insertions(+), 158 deletions(-) diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index 2ae900e002..e5782f6567 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -270,9 +270,26 @@ const Vec3d& GLVolume::get_rotation() const void GLVolume::set_rotation(const Vec3d& rotation) { +#if ENABLE_EXTENDED_SELECTION + static const double TWO_PI = 2.0 * (double)PI; +#endif // ENABLE_EXTENDED_SELECTION + if (m_rotation != rotation) { m_rotation = rotation; +#if ENABLE_EXTENDED_SELECTION + for (int i = 0; i < 3; ++i) + { + while (m_rotation(i) < 0.0) + { + m_rotation(i) += TWO_PI; + } + while (TWO_PI < m_rotation(i)) + { + m_rotation(i) -= TWO_PI; + } + } +#endif // ENABLE_EXTENDED_SELECTION m_world_matrix_dirty = true; m_transformed_bounding_box_dirty = true; m_transformed_convex_hull_bounding_box_dirty = true; diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 116d8cb3bd..9192182f47 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1131,28 +1131,29 @@ bool GLCanvas3D::Mouse::is_start_position_3D_defined() const #if ENABLE_EXTENDED_SELECTION GLCanvas3D::Selection::VolumeCache::VolumeCache() - : position(Vec3d::Zero()) - , rotation(Vec3d::Zero()) - , scaling_factor(Vec3d::Ones()) + : m_position(Vec3d::Zero()) + , m_rotation(Vec3d::Zero()) + , m_scaling_factor(Vec3d::Ones()) { m_rotation_matrix = Transform3d::Identity(); } GLCanvas3D::Selection::VolumeCache::VolumeCache(const Vec3d& position, const Vec3d& rotation, const Vec3d& scaling_factor) - : position(position) - , rotation(rotation) - , scaling_factor(scaling_factor) + : m_position(position) + , m_rotation(rotation) + , m_scaling_factor(scaling_factor) { m_rotation_matrix = Transform3d::Identity(); - m_rotation_matrix.rotate(Eigen::AngleAxisd(rotation(2), Vec3d::UnitZ())); - m_rotation_matrix.rotate(Eigen::AngleAxisd(rotation(1), Vec3d::UnitY())); - m_rotation_matrix.rotate(Eigen::AngleAxisd(rotation(0), Vec3d::UnitX())); + m_rotation_matrix.rotate(Eigen::AngleAxisd(m_rotation(2), Vec3d::UnitZ())); + m_rotation_matrix.rotate(Eigen::AngleAxisd(m_rotation(1), Vec3d::UnitY())); + m_rotation_matrix.rotate(Eigen::AngleAxisd(m_rotation(0), Vec3d::UnitX())); } GLCanvas3D::Selection::Selection() : m_volumes(nullptr) , m_model(nullptr) , m_mode(Instance) + , m_type(Invalid) , m_valid(false) , m_bounding_box_dirty(true) { @@ -1199,6 +1200,7 @@ void GLCanvas3D::Selection::add(unsigned int volume_idx, bool as_single_selectio } } + update_type(); m_bounding_box_dirty = true; } @@ -1226,6 +1228,7 @@ void GLCanvas3D::Selection::remove(unsigned int volume_idx) } } + update_type(); m_bounding_box_dirty = true; } @@ -1240,115 +1243,45 @@ void GLCanvas3D::Selection::clear() } m_list.clear(); + update_type(); m_bounding_box_dirty = true; } -bool GLCanvas3D::Selection::is_single_full_instance(int& object_idx_out, int& instance_idx_out) const +bool GLCanvas3D::Selection::is_single_full_instance() const { - if (!m_valid || is_empty() || is_wipe_tower()) + if (m_type == SingleFullInstance) + return true; + + int object_idx = m_valid ? get_object_idx() : -1; + if (object_idx != -1) { - object_idx_out = -1; - instance_idx_out = -1; - return false; + if (get_instance_idx() != -1) + return m_model->objects[object_idx]->volumes.size() == m_list.size(); } - const GLVolume* first = (*m_volumes)[*m_list.begin()]; - int object_idx = first->object_idx(); - int instance_idx = first->instance_idx(); - unsigned int count = 0; - - for (unsigned int i : m_list) - { - const GLVolume* v = (*m_volumes)[i]; - if ((v->object_idx() != object_idx) || (v->instance_idx() != instance_idx)) - return false; - else - ++count; - } - - bool res = (count == (unsigned int)m_model->objects[object_idx]->volumes.size()); - object_idx_out = res ? object_idx : -1; - instance_idx_out = res ? instance_idx : -1; - return res; + return false; } -bool GLCanvas3D::Selection::is_single_full_object(int& object_idx_out) const +int GLCanvas3D::Selection::get_object_idx() const { - if (!m_valid || is_empty() || is_wipe_tower()) - { - object_idx_out = -1; - return false; - } - - int object_idx = (*m_volumes)[*m_list.begin()]->object_idx(); - unsigned int count = 0; - - for (unsigned int i : m_list) - { - const GLVolume* v = (*m_volumes)[i]; - if (v->object_idx() != object_idx) - return false; - else - ++count; - } - - bool res = (count == (unsigned int)m_model->objects[object_idx]->volumes.size() * (unsigned int)m_model->objects[object_idx]->instances.size()); - object_idx_out = res ? object_idx : -1; - return res; + return (m_cache.content.size() == 1) ? m_cache.content.begin()->first : -1; } -bool GLCanvas3D::Selection::is_from_single_instance(int& object_idx_out, int& instance_idx_out) const +int GLCanvas3D::Selection::get_instance_idx() const { - if (!m_valid || is_empty() || is_wipe_tower()) + if (m_cache.content.size() == 1) { - object_idx_out = -1; - instance_idx_out = -1; - return false; + const InstanceIdxsList& idxs = m_cache.content.begin()->second; + if (idxs.size() == 1) + return *idxs.begin(); } - const GLVolume* first = (*m_volumes)[*m_list.begin()]; - int object_idx = first->object_idx(); - int instance_idx = first->instance_idx(); - - for (unsigned int i : m_list) - { - const GLVolume* v = (*m_volumes)[i]; - if ((v->object_idx() != object_idx) || (v->instance_idx() != instance_idx)) - return false; - } - - object_idx_out = object_idx; - instance_idx_out = instance_idx; - return true; -} - -bool GLCanvas3D::Selection::is_from_single_object(int& object_idx_out) const -{ - if (!m_valid || is_empty() || is_wipe_tower()) - { - object_idx_out = -1; - return false; - } - - int object_idx = (*m_volumes)[*m_list.begin()]->object_idx(); - - for (unsigned int i : m_list) - { - const GLVolume* v = (*m_volumes)[i]; - if (v->object_idx() != object_idx) - return false; - } - - object_idx_out = object_idx; - return true; + return -1; } const GLVolume* GLCanvas3D::Selection::get_volume(unsigned int volume_idx) const { - if (!m_valid) - return nullptr; - - return (volume_idx < (unsigned int)m_volumes->size()) ? (*m_volumes)[volume_idx] : nullptr; + return (m_valid && (volume_idx < (unsigned int)m_volumes->size())) ? (*m_volumes)[volume_idx] : nullptr; } const BoundingBoxf3& GLCanvas3D::Selection::get_bounding_box() const @@ -1374,7 +1307,40 @@ void GLCanvas3D::Selection::translate(const Vec3d& displacement) for (unsigned int i : m_list) { - (*m_volumes)[i]->set_offset(m_cache.volumes_data[i].position + displacement); + (*m_volumes)[i]->set_offset(m_cache.volumes_data[i].get_position() + displacement); + } + + m_bounding_box_dirty = true; +} + +void GLCanvas3D::Selection::rotate(const Vec3d& rotation) +{ + if (!m_valid) + return; + + Transform3d m = Transform3d::Identity(); + if (rotation(2) != 0.0f) + m.rotate(Eigen::AngleAxisd(rotation(2), Vec3d::UnitZ())); + else if (rotation(1) != 0.0f) + m.rotate(Eigen::AngleAxisd(rotation(1), Vec3d::UnitY())); + else if (rotation(0) != 0.0f) + m.rotate(Eigen::AngleAxisd(rotation(0), Vec3d::UnitX())); + + bool single_full_instance = is_single_full_instance(); + + for (unsigned int i : m_list) + { + Vec3d radius = m * (m_cache.volumes_data[i].get_position() - m_cache.dragging_center); + (*m_volumes)[i]->set_offset(m_cache.dragging_center + radius); + + if (single_full_instance) + (*m_volumes)[i]->set_rotation(rotation); + else + { + Eigen::Matrix new_rotation_matrix = (m * m_cache.volumes_data[i].get_rotation_matrix()).matrix().block(0, 0, 3, 3); + Vec3d angles = new_rotation_matrix.eulerAngles(2, 1, 0); + (*m_volumes)[i]->set_rotation(Vec3d(angles(2), angles(1), angles(0))); + } } m_bounding_box_dirty = true; @@ -1394,6 +1360,102 @@ void GLCanvas3D::Selection::update_valid() m_valid = (m_volumes != nullptr) && (m_model != nullptr); } +void GLCanvas3D::Selection::update_type() +{ + m_cache.content.clear(); + m_type = Mixed; + + for (unsigned int i : m_list) + { + const GLVolume* volume = (*m_volumes)[i]; + int obj_idx = volume->object_idx(); + int inst_idx = volume->instance_idx(); + ObjectIdxsToInstanceIdxsMap::iterator obj_it = m_cache.content.find(obj_idx); + if (obj_it == m_cache.content.end()) + obj_it = m_cache.content.insert(ObjectIdxsToInstanceIdxsMap::value_type(obj_idx, InstanceIdxsList())).first; + + obj_it->second.insert(inst_idx); + } + + if (!m_valid) + m_type = Invalid; + else + { + if (m_list.empty()) + m_type = Empty; + else if (m_list.size() == 1) + { + const GLVolume* first = (*m_volumes)[*m_list.begin()]; + if (first->is_wipe_tower) + m_type = WipeTower; + else if (first->is_modifier) + m_type = Modifier; + else + { + const ModelObject* model_object = m_model->objects[first->object_idx()]; + unsigned int volumes_count = (unsigned int)model_object->volumes.size(); + unsigned int instances_count = (unsigned int)model_object->instances.size(); + if (volumes_count * instances_count == 1) + m_type = SingleFullObject; + else if (volumes_count == 1) // instances_count > 1 + m_type = SingleFullInstance; + } + } + else + { + if (m_cache.content.size() == 1) // single object + { + const ModelObject* model_object = m_model->objects[m_cache.content.begin()->first]; + unsigned int volumes_count = (unsigned int)model_object->volumes.size(); + unsigned int instances_count = (unsigned int)model_object->instances.size(); + if (volumes_count * instances_count == (unsigned int)m_list.size()) + m_type = SingleFullObject; + else if ((m_cache.content.begin()->second.size() == 1) && (volumes_count == (unsigned int)m_list.size())) + m_type = SingleFullInstance; + } + } + } + + switch (m_type) + { + case Invalid: + { + std::cout << "selection type: Invalid" << std::endl; + break; + } + case Empty: + { + std::cout << "selection type: Empty" << std::endl; + break; + } + case WipeTower: + { + std::cout << "selection type: WipeTower" << std::endl; + break; + } + case Modifier: + { + std::cout << "selection type: Modifier" << std::endl; + break; + } + case SingleFullObject: + { + std::cout << "selection type: SingleFullObject" << std::endl; + break; + } + case SingleFullInstance: + { + std::cout << "selection type: SingleFullInstance" << std::endl; + break; + } + case Mixed: + { + std::cout << "selection type: Mixed" << std::endl; + break; + } + } +} + void GLCanvas3D::Selection::set_caches() { m_cache.volumes_data.clear(); @@ -1753,24 +1815,19 @@ void GLCanvas3D::Gizmos::set_hover_id(int id) } #if ENABLE_EXTENDED_SELECTION -void GLCanvas3D::Gizmos::enable_grabber(EType type, unsigned int id) +void GLCanvas3D::Gizmos::enable_grabber(EType type, unsigned int id, bool enable) { if (!m_enabled) return; GizmosMap::const_iterator it = m_gizmos.find(type); if (it != m_gizmos.end()) - it->second->enable_grabber(id); -} - -void GLCanvas3D::Gizmos::disable_grabber(EType type, unsigned int id) -{ - if (!m_enabled) - return; - - GizmosMap::const_iterator it = m_gizmos.find(type); - if (it != m_gizmos.end()) - it->second->disable_grabber(id); + { + if (enable) + it->second->enable_grabber(id); + else + it->second->disable_grabber(id); + } } #endif // ENABLE_EXTENDED_SELECTION @@ -2425,7 +2482,9 @@ wxDEFINE_EVENT(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, Event); wxDEFINE_EVENT(EVT_GLCANVAS_UPDATE_GEOMETRY, Vec3dsEvent<2>); wxDEFINE_EVENT(EVT_GIZMO_SCALE, Vec3dEvent); +#if !ENABLE_EXTENDED_SELECTION wxDEFINE_EVENT(EVT_GIZMO_ROTATE, Vec3dEvent); +#endif // !ENABLE_EXTENDED_SELECTION wxDEFINE_EVENT(EVT_GIZMO_FLATTEN, Vec3dEvent); GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas) @@ -2977,20 +3036,21 @@ void GLCanvas3D::update_gizmos_data() return; #if ENABLE_EXTENDED_SELECTION - if (m_gizmos.get_current_type() == Gizmos::Move) + bool enable_move_z = !m_selection.is_wipe_tower(); + bool is_single_full_object = m_selection.is_single_full_object(); + bool is_single_full_instance = m_selection.is_single_full_instance(); + bool enable_rotate_xy = is_single_full_object && !is_single_full_instance; + + m_gizmos.enable_grabber(Gizmos::Move, 2, enable_move_z); + for (int i = 0; i < 2; ++i) { - if (m_selection.is_wipe_tower()) - m_gizmos.disable_grabber(Gizmos::Move, 2); - else - m_gizmos.enable_grabber(Gizmos::Move, 2); + m_gizmos.enable_grabber(Gizmos::Rotate, i, enable_rotate_xy); } - int object_idx = -1; - int instance_idx = -1; - if (m_selection.is_single_full_instance(object_idx, instance_idx)) + if (is_single_full_instance) { - ModelObject* model_object = m_model->objects[object_idx]; - ModelInstance* model_instance = model_object->instances[instance_idx]; + ModelObject* model_object = m_model->objects[m_selection.get_object_idx()]; + ModelInstance* model_instance = model_object->instances[m_selection.get_instance_idx()]; m_gizmos.set_scale(model_instance->get_scaling_factor()); m_gizmos.set_rotation(model_instance->get_rotation()); m_gizmos.set_flattening_data(model_object); @@ -3477,8 +3537,7 @@ void GLCanvas3D::on_mouse_wheel(wxMouseEvent& evt) if (is_layers_editing_enabled()) { #if ENABLE_EXTENDED_SELECTION - int object_idx_selected = -1; - m_selection.is_from_single_object(object_idx_selected); + int object_idx_selected = m_selection.get_object_idx(); #else int object_idx_selected = _get_first_selected_object_id(); #endif // ENABLE_EXTENDED_SELECTION @@ -3526,8 +3585,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) Point pos(evt.GetX(), evt.GetY()); #if ENABLE_EXTENDED_SELECTION - int selected_object_idx = -1; - m_selection.is_from_single_object(selected_object_idx); + int selected_object_idx = m_selection.get_object_idx(); int layer_editing_object_idx = is_layers_editing_enabled() ? selected_object_idx : -1; #else int selected_object_idx = _get_first_selected_object_id(); @@ -3581,11 +3639,22 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) case Gizmos::Rotate: { #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM +#if ENABLE_EXTENDED_SELECTION + m_regenerate_volumes = false; + const Vec3d& rotation = m_gizmos.get_rotation(); + m_selection.rotate(rotation); + _on_rotate(); +#else post_event(Vec3dEvent(EVT_GIZMO_ROTATE, std::move(m_gizmos.get_rotation()))); +#endif // ENABLE_EXTENDED_SELECTION #else m_on_gizmo_rotate_callback.call((double)m_gizmos.get_angle_z()); #endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM +#if ENABLE_EXTENDED_SELECTION + wxGetApp().obj_manipul()->update_settings_value(m_selection); +#else wxGetApp().obj_manipul()->update_rotation_values(); +#endif // ENABLE_EXTENDED_SELECTION m_dirty = true; break; } @@ -3726,8 +3795,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) #if ENABLE_EXTENDED_SELECTION if (m_picking_enabled && (m_hover_volume_id != -1)) { - int object_idx = -1; - m_selection.is_from_single_object(object_idx); + int object_idx = m_selection.get_object_idx(); _on_select(m_hover_volume_id, object_idx); } #else @@ -3849,7 +3917,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) v->set_offset(v->get_offset() + Vec3d(displacement(0), displacement(1), 0.0)); } - wxGetApp().obj_manipul()->update_position_values(volume->get_offset()); + wxGetApp().obj_manipul()->update_position_value(volume->get_offset()); m_mouse.drag.start_position_3D = cur_pos; #endif // ENABLE_EXTENDED_SELECTION @@ -3897,7 +3965,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) { v->set_offset(v->get_offset() + offset); } - wxGetApp().obj_manipul()->update_position_values(volume->get_offset()); + wxGetApp().obj_manipul()->update_position_value(volume->get_offset()); #endif // ENABLE_EXTENDED_SELECTION break; } @@ -3929,6 +3997,8 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) { #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM #if ENABLE_EXTENDED_SELECTION + m_selection.rotate(m_gizmos.get_rotation()); + wxGetApp().obj_manipul()->update_settings_value(m_selection); #else // Apply new temporary rotation const Vec3d& rotation = m_gizmos.get_rotation(); @@ -4121,7 +4191,12 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) case Gizmos::Rotate: { #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM +#if ENABLE_EXTENDED_SELECTION + m_regenerate_volumes = false; + _on_rotate(); +#else post_event(Vec3dEvent(EVT_GIZMO_ROTATE, m_gizmos.get_rotation())); +#endif // ENABLE_EXTENDED_SELECTION #else m_on_gizmo_rotate_callback.call((double)m_gizmos.get_angle_z()); #endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM @@ -6178,7 +6253,7 @@ void GLCanvas3D::_on_move() if (object_idx < 1000) { - // Move a regular object. + // Move instances. ModelObject* model_object = m_model->objects[object_idx]; if (model_object != nullptr) { @@ -6198,6 +6273,41 @@ void GLCanvas3D::_on_move() if (wipe_tower_origin != Vec3d::Zero()) post_event(Vec3dEvent(EVT_GLCANVAS_WIPETOWER_MOVED, std::move(wipe_tower_origin))); } + +void GLCanvas3D::_on_rotate() +{ + if (m_model == nullptr) + return; + + std::set done; // prevent rotating instances twice + const Selection::IndicesList& selection = m_selection.get_volume_idxs(); + + for (unsigned int i : selection) + { + const GLVolume* v = m_volumes.volumes[i]; + int object_idx = v->object_idx(); + int instance_idx = v->instance_idx(); + + // prevent rotating instances twice + char done_id[64]; + ::sprintf(done_id, "%d_%d", object_idx, instance_idx); + if (done.find(done_id) != done.end()) + continue; + + done.insert(done_id); + + if (object_idx < 1000) + { + // Rotate instances. + ModelObject* model_object = m_model->objects[object_idx]; + if (model_object != nullptr) + { + model_object->instances[instance_idx]->set_rotation(v->get_rotation()); + model_object->invalidate_bounding_box(); + } + } + } +} #else void GLCanvas3D::_on_move(const std::vector& volume_idxs) { diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index d900a2621f..d6fdf8930e 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -116,7 +116,9 @@ wxDECLARE_EVENT(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, Event); wxDECLARE_EVENT(EVT_GLCANVAS_UPDATE_GEOMETRY, Vec3dsEvent<2>); wxDECLARE_EVENT(EVT_GIZMO_SCALE, Vec3dEvent); +#if !ENABLE_EXTENDED_SELECTION wxDECLARE_EVENT(EVT_GIZMO_ROTATE, Vec3dEvent); +#endif // !ENABLE_EXTENDED_SELECTION wxDECLARE_EVENT(EVT_GIZMO_FLATTEN, Vec3dEvent); @@ -390,29 +392,45 @@ public: Object }; + enum EType : unsigned char + { + Invalid, + Empty, + WipeTower, + Modifier, + SingleFullObject, + SingleFullInstance, + Mixed + }; + private: struct VolumeCache { private: + Vec3d m_position; + Vec3d m_rotation; + Vec3d m_scaling_factor; Transform3d m_rotation_matrix; public: - Vec3d position; - Vec3d rotation; - Vec3d scaling_factor; - VolumeCache(); VolumeCache(const Vec3d& position, const Vec3d& rotation, const Vec3d& scaling_factor); + const Vec3d& get_position() const { return m_position; } + const Vec3d& get_rotation() const { return m_rotation; } + const Vec3d& get_scaling_factor() const { return m_scaling_factor; } const Transform3d& get_rotation_matrix() const { return m_rotation_matrix; } }; typedef std::map VolumesCache; + typedef std::set InstanceIdxsList; + typedef std::map ObjectIdxsToInstanceIdxsMap; struct Cache { VolumesCache volumes_data; Vec3d dragging_center; + ObjectIdxsToInstanceIdxsMap content; }; GLVolumePtrs* m_volumes; @@ -420,6 +438,7 @@ public: bool m_valid; EMode m_mode; + EType m_type; IndicesList m_list; Cache m_cache; mutable BoundingBoxf3 m_bounding_box; @@ -438,13 +457,18 @@ public: void remove(unsigned int volume_idx); void clear(); - bool is_empty() const { return m_list.empty(); } - bool is_wipe_tower() const { return m_valid && (m_list.size() == 1) && (*m_volumes)[*m_list.begin()]->is_wipe_tower; } - bool is_modifier() const { return m_valid && (m_list.size() == 1) && (*m_volumes)[*m_list.begin()]->is_modifier; } - bool is_single_full_instance(int& object_idx_out, int& instance_idx_out) const; - bool is_single_full_object(int& object_idx_out) const; - bool is_from_single_instance(int& object_idx_out, int& instance_idx_out) const; - bool is_from_single_object(int& object_idx_out) const; + bool is_empty() const { return m_type == Empty; } + bool is_wipe_tower() const { return m_type == WipeTower; } + bool is_modifier() const { return m_type == Modifier; } + bool is_single_full_instance() const; + bool is_single_full_object() const { return m_type == SingleFullObject; } + bool is_from_single_instance() const { return get_instance_idx() != -1; } + bool is_from_single_object() const { return get_object_idx() != -1; } + + // Returns the the object id if the selection is from a single object, otherwise is -1 + int get_object_idx() const; + // Returns the instance id if the selection is from a single object and from a single instance, otherwise is -1 + int get_instance_idx() const; const IndicesList& get_volume_idxs() const { return m_list; } const GLVolume* get_volume(unsigned int volume_idx) const; @@ -455,11 +479,13 @@ public: void start_dragging(); void translate(const Vec3d& displacement); + void rotate(const Vec3d& rotation); void render() const; private: void update_valid(); + void update_type(); void set_caches(); void add_volume(unsigned int volume_idx); void add_instance(unsigned int volume_idx); @@ -517,8 +543,7 @@ private: void set_hover_id(int id); #if ENABLE_EXTENDED_SELECTION - void enable_grabber(EType type, unsigned int id); - void disable_grabber(EType type, unsigned int id); + void enable_grabber(EType type, unsigned int id, bool enable); #endif // ENABLE_EXTENDED_SELECTION bool overlay_contains_mouse(const GLCanvas3D& canvas, const Vec2d& mouse_pos) const; @@ -898,6 +923,7 @@ private: #if ENABLE_EXTENDED_SELECTION void _on_move(); + void _on_rotate(); #else void _on_move(const std::vector& volume_idxs); #endif // ENABLE_EXTENDED_SELECTION diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index afdc608063..aaca076ed9 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -265,27 +265,41 @@ void ObjectManipulation::update_settings_list() #if ENABLE_EXTENDED_SELECTION void ObjectManipulation::update_settings_value(const GLCanvas3D::Selection& selection) { - int object_idx = -1; - int instance_idx = -1; - if (selection.is_single_full_instance(object_idx, instance_idx)) + if (selection.is_single_full_object()) + { + if (wxGetApp().mainframe->m_plater->model().objects[selection.get_object_idx()]->instances.size() == 1) + { + // all volumes in the selection belongs to the same instance, any of them contains the needed data, so we take the first + const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); + update_position_value(volume->get_offset()); + update_rotation_value(volume->get_rotation()); + m_og->enable(); + } + else + reset_settings_value(); + } + else if (selection.is_single_full_instance()) { // all volumes in the selection belongs to the same instance, any of them contains the needed data, so we take the first - const GLCanvas3D::Selection::IndicesList& idxs = selection.get_volume_idxs(); - update_position_values(selection.get_volume(*idxs.begin())->get_offset()); + const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); + update_position_value(volume->get_offset()); + update_rotation_value(volume->get_rotation()); m_og->enable(); } else if (selection.is_wipe_tower()) { // the selection contains a single volume - const GLCanvas3D::Selection::IndicesList& idxs = selection.get_volume_idxs(); - update_position_values(selection.get_volume(*idxs.begin())->get_offset()); + const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); + update_position_value(volume->get_offset()); + update_rotation_value(volume->get_rotation()); m_og->enable(); } else if (selection.is_modifier()) { // the selection contains a single volume - const GLCanvas3D::Selection::IndicesList& idxs = selection.get_volume_idxs(); - update_position_values(selection.get_volume(*idxs.begin())->get_offset()); + const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); + update_position_value(volume->get_offset()); + update_rotation_value(volume->get_rotation()); m_og->enable(); } else @@ -293,17 +307,34 @@ void ObjectManipulation::update_settings_value(const GLCanvas3D::Selection& sele } void ObjectManipulation::reset_settings_value() +{ + reset_position_value(); + reset_rotation_value(); + reset_scale_value(); + m_og->disable(); +} + +void ObjectManipulation::reset_position_value() { m_og->set_value("position_x", 0); m_og->set_value("position_y", 0); m_og->set_value("position_z", 0); - m_og->set_value("scale_x", 0); - m_og->set_value("scale_y", 0); - m_og->set_value("scale_z", 0); +} + +void ObjectManipulation::reset_rotation_value() +{ m_og->set_value("rotation_x", 0); m_og->set_value("rotation_y", 0); m_og->set_value("rotation_z", 0); - m_og->disable(); +} + +void ObjectManipulation::reset_scale_value() +{ + m_is_percent_scale = true; + m_og->set_value("scale_unit", _("%")); + m_og->set_value("scale_x", 100); + m_og->set_value("scale_y", 100); + m_og->set_value("scale_z", 100); } #endif // ENABLE_EXTENDED_SELECTION @@ -380,7 +411,7 @@ void ObjectManipulation::update_position_values() #endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM } -void ObjectManipulation::update_position_values(const Vec3d& position) +void ObjectManipulation::update_position_value(const Vec3d& position) { m_og->set_value("position_x", int(position(0))); m_og->set_value("position_y", int(position(1))); diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.hpp b/src/slic3r/GUI/GUI_ObjectManipulation.hpp index 2a9ec004e1..7cd5fce276 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.hpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.hpp @@ -50,12 +50,15 @@ public: #if ENABLE_EXTENDED_SELECTION void update_settings_value(const GLCanvas3D::Selection& selection); void reset_settings_value(); + void reset_position_value(); + void reset_rotation_value(); + void reset_scale_value(); #endif // ENABLE_EXTENDED_SELECTION void update_values(); // update position values displacements or "gizmos" void update_position_values(); - void update_position_values(const Vec3d& position); + void update_position_value(const Vec3d& position); // update scale values after scale unit changing or "gizmos" void update_scale_values(); #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM From bd85ca721e2a82b447a809d30062abb469f8c8a9 Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Tue, 9 Oct 2018 17:14:59 +0200 Subject: [PATCH 076/186] Plater & GLCanvas3D: Fix instance_moved event, add event handlers --- src/slic3r/GUI/GLCanvas3D.cpp | 6 +-- src/slic3r/GUI/GLCanvas3D.hpp | 2 +- src/slic3r/GUI/Plater.cpp | 82 +++++++++++++++++++++++------------ 3 files changed, 59 insertions(+), 31 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 9192182f47..a5ed6b1f1c 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -2476,7 +2476,7 @@ wxDEFINE_EVENT(EVT_GLCANVAS_ARRANGE, SimpleEvent); wxDEFINE_EVENT(EVT_GLCANVAS_ROTATE_OBJECT, Event); wxDEFINE_EVENT(EVT_GLCANVAS_SCALE_UNIFORMLY, SimpleEvent); wxDEFINE_EVENT(EVT_GLCANVAS_INCREASE_OBJECTS, Event); -wxDEFINE_EVENT(EVT_GLCANVAS_INSTANCE_MOVES, SimpleEvent); +wxDEFINE_EVENT(EVT_GLCANVAS_INSTANCE_MOVED, SimpleEvent); wxDEFINE_EVENT(EVT_GLCANVAS_WIPETOWER_MOVED, Vec3dEvent); wxDEFINE_EVENT(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, Event); wxDEFINE_EVENT(EVT_GLCANVAS_UPDATE_GEOMETRY, Vec3dsEvent<2>); @@ -6268,7 +6268,7 @@ void GLCanvas3D::_on_move() } if (object_moved) - post_event(SimpleEvent(EVT_GLCANVAS_WIPETOWER_MOVED)); + post_event(SimpleEvent(EVT_GLCANVAS_INSTANCE_MOVED)); if (wipe_tower_origin != Vec3d::Zero()) post_event(Vec3dEvent(EVT_GLCANVAS_WIPETOWER_MOVED, std::move(wipe_tower_origin))); @@ -6354,7 +6354,7 @@ void GLCanvas3D::_on_move(const std::vector& volume_idxs) } if (object_moved) - post_event(SimpleEvent(EVT_GLCANVAS_WIPETOWER_MOVED)); + post_event(SimpleEvent(EVT_GLCANVAS_INSTANCE_MOVED)); if (wipe_tower_origin != Vec3d::Zero()) post_event(Vec3dEvent(EVT_GLCANVAS_WIPETOWER_MOVED, std::move(wipe_tower_origin))); diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index d6fdf8930e..d3e762ca15 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -110,7 +110,7 @@ wxDECLARE_EVENT(EVT_GLCANVAS_ARRANGE, SimpleEvent); wxDECLARE_EVENT(EVT_GLCANVAS_ROTATE_OBJECT, Event); // data: -1 => rotate left, +1 => rotate right wxDECLARE_EVENT(EVT_GLCANVAS_SCALE_UNIFORMLY, SimpleEvent); wxDECLARE_EVENT(EVT_GLCANVAS_INCREASE_OBJECTS, Event); // data: +1 => increase, -1 => decrease -wxDECLARE_EVENT(EVT_GLCANVAS_INSTANCE_MOVES, SimpleEvent); +wxDECLARE_EVENT(EVT_GLCANVAS_INSTANCE_MOVED, SimpleEvent); wxDECLARE_EVENT(EVT_GLCANVAS_WIPETOWER_MOVED, Vec3dEvent); wxDECLARE_EVENT(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, Event); wxDECLARE_EVENT(EVT_GLCANVAS_UPDATE_GEOMETRY, Vec3dsEvent<2>); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 99395c826e..ff8592cfe3 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -729,13 +729,11 @@ struct Plater::priv void on_action_selectbyparts(SimpleEvent&); #endif // !ENABLE_EXTENDED_SELECTION + void on_object_select(ObjectSelectEvent&); void on_viewport_changed(SimpleEvent&); void on_right_click(Vec2dEvent&); void on_model_update(SimpleEvent&); - void on_remove_object(SimpleEvent&); - void on_arrange(SimpleEvent&); void on_scale_uniformly(SimpleEvent&); - void on_instance_moves(SimpleEvent&); void on_wipetower_moved(Vec3dEvent&); void on_enable_action_buttons(Event&); void on_update_geometry(Vec3dsEvent<2>&); @@ -816,17 +814,17 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) : sidebar->Bind(wxEVT_COMBOBOX, &priv::on_select_preset, this); // 3DScene events: - canvas3D->Bind(EVT_GLCANVAS_OBJECT_SELECT, [](ObjectSelectEvent&) { /*TODO*/ }); + canvas3D->Bind(EVT_GLCANVAS_OBJECT_SELECT, &priv::on_object_select, this); canvas3D->Bind(EVT_GLCANVAS_VIEWPORT_CHANGED, &priv::on_viewport_changed, this); // canvas3D->Bind(EVT_GLCANVAS_DOUBLE_CLICK, [](SimpleEvent&) { }); // XXX: remove? canvas3D->Bind(EVT_GLCANVAS_RIGHT_CLICK, &priv::on_right_click, this); canvas3D->Bind(EVT_GLCANVAS_MODEL_UPDATE, &priv::on_model_update, this); - canvas3D->Bind(EVT_GLCANVAS_REMOVE_OBJECT, &priv::on_remove_object, this); - canvas3D->Bind(EVT_GLCANVAS_ARRANGE, &priv::on_arrange, this); + canvas3D->Bind(EVT_GLCANVAS_REMOVE_OBJECT, [q](SimpleEvent&) { q->remove_selected(); }); + canvas3D->Bind(EVT_GLCANVAS_ARRANGE, [this](SimpleEvent&) { arrange(); }); canvas3D->Bind(EVT_GLCANVAS_ROTATE_OBJECT, [this](Event &evt) { /*TODO: call rotate */ }); - canvas3D->Bind(EVT_GLCANVAS_SCALE_UNIFORMLY, &priv::on_scale_uniformly, this); + canvas3D->Bind(EVT_GLCANVAS_SCALE_UNIFORMLY, [this](SimpleEvent&) { scale(); }); canvas3D->Bind(EVT_GLCANVAS_INCREASE_OBJECTS, [this](Event &evt) { evt.data == 1 ? increase() : decrease(); }); - canvas3D->Bind(EVT_GLCANVAS_INSTANCE_MOVES, &priv::on_instance_moves, this); + canvas3D->Bind(EVT_GLCANVAS_INSTANCE_MOVED, [this](SimpleEvent&) { update(); }); canvas3D->Bind(EVT_GLCANVAS_WIPETOWER_MOVED, &priv::on_wipetower_moved, this); canvas3D->Bind(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, &priv::on_enable_action_buttons, this); canvas3D->Bind(EVT_GLCANVAS_UPDATE_GEOMETRY, &priv::on_update_geometry, this); @@ -1573,6 +1571,19 @@ void Plater::priv::on_action_selectbyparts(SimpleEvent&) } #endif // !ENABLE_EXTENDED_SELECTION +void Plater::priv::on_object_select(ObjectSelectEvent &evt) +{ + const auto obj_idx = evt.object_id(); + const auto vol_idx = evt.volume_id(); + + // TODO: + // if (($obj_idx != -1) && ($vol_idx == -1)) { + // # Ignore the special objects (the wipe tower proxy and such). + // $self->select_object((defined($obj_idx) && $obj_idx >= 0 && $obj_idx < 1000) ? $obj_idx : undef); + // $self->item_changed_selection($obj_idx) if (defined($obj_idx)); + // } +} + void Plater::priv::on_viewport_changed(SimpleEvent& evt) { wxObject* o = evt.GetEventObject(); @@ -1592,29 +1603,47 @@ void Plater::priv::on_model_update(SimpleEvent&) // TODO } -void Plater::priv::on_remove_object(SimpleEvent&) -{ - // TODO -} - -void Plater::priv::on_arrange(SimpleEvent&) -{ - // TODO -} - void Plater::priv::on_scale_uniformly(SimpleEvent&) { - // TODO +// my ($scale) = @_; + +// my ($obj_idx, $object) = $self->selected_object; + const auto obj_idx = selected_object(); + if (! obj_idx) { return; } +// return if !defined $obj_idx; + +// my $model_object = $self->{model}->objects->[$obj_idx]; +// my $model_instance = $model_object->instances->[0]; + +// $self->stop_background_process; + +// my $variation = $scale / $model_instance->scaling_factor; +// #FIXME Scale the layer height profile? +// foreach my $range (@{ $model_object->layer_height_ranges }) { +// $range->[0] *= $variation; +// $range->[1] *= $variation; +// } +// $_->set_scaling_factor($scale) for @{ $model_object->instances }; + +// # Set object scale on c++ side +// # Slic3r::GUI::set_object_scale($obj_idx, $model_object->instances->[0]->scaling_factor * 100); + +// # $object->transform_thumbnail($self->{model}, $obj_idx); + +// #update print and start background processing +// $self->{print}->add_model_object($model_object, $obj_idx); + +// $self->selection_changed(1); # refresh info (size, volume etc.) +// $self->update; +// $self->schedule_background_process; } -void Plater::priv::on_instance_moves(SimpleEvent&) +void Plater::priv::on_wipetower_moved(Vec3dEvent &evt) { - // TODO -} - -void Plater::priv::on_wipetower_moved(Vec3dEvent&) -{ - // TODO + DynamicPrintConfig cfg; + cfg.opt("wipe_tower_x", true)->value = evt.data(0); + cfg.opt("wipe_tower_y", true)->value = evt.data(1); + main_frame->get_preset_tab("print")->load_config(cfg); } void Plater::priv::on_enable_action_buttons(Event&) @@ -1628,7 +1657,6 @@ void Plater::priv::on_update_geometry(Vec3dsEvent<2>&) } - // Plater / Public Plater::Plater(wxWindow *parent, MainFrame *main_frame) From 6d3307756430f9be075a8d51d935610042bd13d4 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Wed, 10 Oct 2018 11:04:04 +0200 Subject: [PATCH 077/186] New selection -> synchronization of indirectly selected instances --- src/slic3r/GUI/GLCanvas3D.cpp | 141 +++++++++++++++++++++++++++++----- src/slic3r/GUI/GLCanvas3D.hpp | 5 +- 2 files changed, 127 insertions(+), 19 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index a5ed6b1f1c..800a50b1c3 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1343,16 +1343,23 @@ void GLCanvas3D::Selection::rotate(const Vec3d& rotation) } } + if (m_mode == Instance) + synchronize_unselected_instances(); + m_bounding_box_dirty = true; } -void GLCanvas3D::Selection::render() const +void GLCanvas3D::Selection::render(bool show_indirect_selection) const { if (is_empty()) return; - float color[3] = { 1.0f, 1.0f, 1.0f }; - render_bounding_box(get_bounding_box(), color); + // render cumulative bounding box of selected volumes + render_selected_volumes(); + + // render bounding boxes of indirectly selected instances + if (show_indirect_selection && (m_mode == Instance)) + render_unselected_instances(); } void GLCanvas3D::Selection::update_valid() @@ -1555,6 +1562,62 @@ void GLCanvas3D::Selection::calc_bounding_box() const m_bounding_box_dirty = false; } +void GLCanvas3D::Selection::render_selected_volumes() const +{ + float color[3] = { 1.0f, 1.0f, 1.0f }; + render_bounding_box(get_bounding_box(), color); +} + +void GLCanvas3D::Selection::render_unselected_instances() const +{ + std::set done; // prevent processing volumes twice + done.insert(m_list.begin(), m_list.end()); + + typedef std::map, BoundingBoxf3> InstanceToBoxMap; + InstanceToBoxMap boxes; + for (unsigned int i : m_list) + { + if (done.size() == m_volumes->size()) + break; + + const GLVolume* volume = (*m_volumes)[i]; + int object_idx = volume->object_idx(); + if (object_idx >= 1000) + continue; + + int instance_idx = volume->instance_idx(); + + for (unsigned int j = 0; j < (unsigned int)m_volumes->size(); ++j) + { + if (done.size() == m_volumes->size()) + break; + + if (done.find(j) != done.end()) + continue; + + GLVolume* v = (*m_volumes)[j]; + int i_idx = v->instance_idx(); + if ((v->object_idx() != object_idx) || (i_idx == instance_idx)) + continue; + + std::pair box_id(object_idx, i_idx); + InstanceToBoxMap::iterator it = boxes.find(box_id); + if (it == boxes.end()) + it = boxes.insert(InstanceToBoxMap::value_type(box_id, BoundingBoxf3())).first; + + it->second.merge(v->transformed_bounding_box()); + + done.insert(j); + } + } + + float color[3] = { 1.0f, 1.0f, 0.0f }; + for (const InstanceToBoxMap::value_type& box : boxes) + { + render_bounding_box(box.second, color); + } +} + void GLCanvas3D::Selection::render_bounding_box(const BoundingBoxf3& box, float* color) const { if (color == nullptr) @@ -1604,6 +1667,46 @@ void GLCanvas3D::Selection::render_bounding_box(const BoundingBoxf3& box, float* ::glEnd(); } + +void GLCanvas3D::Selection::synchronize_unselected_instances() +{ + std::set done; // prevent processing volumes twice + done.insert(m_list.begin(), m_list.end()); + + for (unsigned int i : m_list) + { + if (done.size() == m_volumes->size()) + break; + + const GLVolume* volume = (*m_volumes)[i]; + int object_idx = volume->object_idx(); + if (object_idx >= 1000) + continue; + + int instance_idx = volume->instance_idx(); + const Vec3d& rotation = volume->get_rotation(); + const Vec3d& scaling_factor = volume->get_scaling_factor(); + + // Process unselected instances. + for (unsigned int j = 0; j < (unsigned int)m_volumes->size(); ++j) + { + if (done.size() == m_volumes->size()) + break; + + if (done.find(j) != done.end()) + continue; + + GLVolume* v = (*m_volumes)[j]; + if ((v->object_idx() != object_idx) || (v->instance_idx() == instance_idx)) + continue; + + v->set_rotation(rotation); + v->set_scaling_factor(scaling_factor); + + done.insert(j); + } + } +} #endif // ENABLE_EXTENDED_SELECTION const float GLCanvas3D::Gizmos::OverlayTexturesScale = 0.75f; @@ -4884,7 +4987,9 @@ void GLCanvas3D::_render_objects() const #if ENABLE_EXTENDED_SELECTION void GLCanvas3D::_render_selection() const { - m_selection.render(); + Gizmos::EType type = m_gizmos.get_current_type(); + bool show_indirect_selection = m_gizmos.is_running() && ((type == Gizmos::Rotate) || (type == Gizmos::Scale)); + m_selection.render(show_indirect_selection); } #endif // ENABLE_EXTENDED_SELECTION @@ -6232,7 +6337,7 @@ void GLCanvas3D::_on_move() if (m_model == nullptr) return; - std::set done; // prevent moving instances twice + std::set> done; // prevent moving instances twice bool object_moved = false; Vec3d wipe_tower_origin = Vec3d::Zero(); const Selection::IndicesList& selection = m_selection.get_volume_idxs(); @@ -6244,8 +6349,7 @@ void GLCanvas3D::_on_move() int instance_idx = v->instance_idx(); // prevent moving instances twice - char done_id[64]; - ::sprintf(done_id, "%d_%d", object_idx, instance_idx); + std::pair done_id(object_idx, instance_idx); if (done.find(done_id) != done.end()) continue; @@ -6279,34 +6383,35 @@ void GLCanvas3D::_on_rotate() if (m_model == nullptr) return; - std::set done; // prevent rotating instances twice + std::set> done; // prevent rotating instances twice const Selection::IndicesList& selection = m_selection.get_volume_idxs(); for (unsigned int i : selection) { const GLVolume* v = m_volumes.volumes[i]; int object_idx = v->object_idx(); + if (object_idx >= 1000) + continue; + int instance_idx = v->instance_idx(); // prevent rotating instances twice - char done_id[64]; - ::sprintf(done_id, "%d_%d", object_idx, instance_idx); + std::pair done_id(object_idx, instance_idx); if (done.find(done_id) != done.end()) continue; done.insert(done_id); - if (object_idx < 1000) + // Rotate instances. + ModelObject* model_object = m_model->objects[object_idx]; + if (model_object != nullptr) { - // Rotate instances. - ModelObject* model_object = m_model->objects[object_idx]; - if (model_object != nullptr) - { - model_object->instances[instance_idx]->set_rotation(v->get_rotation()); - model_object->invalidate_bounding_box(); - } + model_object->instances[instance_idx]->set_rotation(v->get_rotation()); + model_object->invalidate_bounding_box(); } } + +// schedule_background_process } #else void GLCanvas3D::_on_move(const std::vector& volume_idxs) diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index d3e762ca15..222b0137e4 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -481,7 +481,7 @@ public: void translate(const Vec3d& displacement); void rotate(const Vec3d& rotation); - void render() const; + void render(bool show_indirect_selection) const; private: void update_valid(); @@ -494,7 +494,10 @@ public: void remove_instance(unsigned int volume_idx); void remove_object(unsigned int volume_idx); void calc_bounding_box() const; + void render_selected_volumes() const; + void render_unselected_instances() const; void render_bounding_box(const BoundingBoxf3& box, float* color) const; + void synchronize_unselected_instances(); }; private: From 7672be64885aeff90e459b4ae788431c7f4d5d83 Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Wed, 10 Oct 2018 11:21:20 +0200 Subject: [PATCH 078/186] Plater: on_object_select --- src/slic3r/GUI/Plater.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index ff8592cfe3..c40108f311 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1576,12 +1576,11 @@ void Plater::priv::on_object_select(ObjectSelectEvent &evt) const auto obj_idx = evt.object_id(); const auto vol_idx = evt.volume_id(); - // TODO: - // if (($obj_idx != -1) && ($vol_idx == -1)) { - // # Ignore the special objects (the wipe tower proxy and such). - // $self->select_object((defined($obj_idx) && $obj_idx >= 0 && $obj_idx < 1000) ? $obj_idx : undef); - // $self->item_changed_selection($obj_idx) if (defined($obj_idx)); - // } + if (obj_idx >= 0 && obj_idx < 1000 && vol_idx == -1) { + // Ignore the special objects (the wipe tower proxy and such). + select_object(obj_idx); + item_changed_selection(); + } } void Plater::priv::on_viewport_changed(SimpleEvent& evt) From 3e5e72dafcbb8b3871a0fa58497cec1497ab88a9 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Wed, 10 Oct 2018 13:51:11 +0200 Subject: [PATCH 079/186] New selection -> changed calculation of euler angles for multivolume rotations --- src/slic3r/GUI/GLCanvas3D.cpp | 28 ++++++++++++++++++++++------ src/slic3r/GUI/GLCanvas3D.hpp | 1 + 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 800a50b1c3..496942e1bc 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1338,8 +1338,26 @@ void GLCanvas3D::Selection::rotate(const Vec3d& rotation) else { Eigen::Matrix new_rotation_matrix = (m * m_cache.volumes_data[i].get_rotation_matrix()).matrix().block(0, 0, 3, 3); - Vec3d angles = new_rotation_matrix.eulerAngles(2, 1, 0); - (*m_volumes)[i]->set_rotation(Vec3d(angles(2), angles(1), angles(0))); + // extracts euler angles from the composed transformation + // not using Eigen eulerAngles() method because it returns weird results + // see: https://www.learnopencv.com/rotation-matrix-to-euler-angles/ + double sy = ::sqrt(sqr(new_rotation_matrix(0, 0)) + sqr(new_rotation_matrix(1, 0))); + + Vec3d angles = Vec3d::Zero(); + if (sy >= 1e-6) + { + angles(0) = ::atan2(new_rotation_matrix(2, 1), new_rotation_matrix(2, 2)); + angles(1) = ::atan2(-new_rotation_matrix(2, 0), sy); + angles(2) = ::atan2(new_rotation_matrix(1, 0), new_rotation_matrix(0, 0)); + } + else + { + angles(0) = ::atan2(-new_rotation_matrix(1, 2), new_rotation_matrix(1, 1)); + angles(1) = ::atan2(-new_rotation_matrix(2, 0), sy); + angles(2) = 0.0; + } + + (*m_volumes)[i]->set_rotation(Vec3d(angles(0), angles(1), angles(2))); } } @@ -3140,9 +3158,7 @@ void GLCanvas3D::update_gizmos_data() #if ENABLE_EXTENDED_SELECTION bool enable_move_z = !m_selection.is_wipe_tower(); - bool is_single_full_object = m_selection.is_single_full_object(); - bool is_single_full_instance = m_selection.is_single_full_instance(); - bool enable_rotate_xy = is_single_full_object && !is_single_full_instance; + bool enable_rotate_xy = m_selection.is_single_full_object() || m_selection.is_mixed(); m_gizmos.enable_grabber(Gizmos::Move, 2, enable_move_z); for (int i = 0; i < 2; ++i) @@ -3150,7 +3166,7 @@ void GLCanvas3D::update_gizmos_data() m_gizmos.enable_grabber(Gizmos::Rotate, i, enable_rotate_xy); } - if (is_single_full_instance) + if (m_selection.is_single_full_instance()) { ModelObject* model_object = m_model->objects[m_selection.get_object_idx()]; ModelInstance* model_instance = model_object->instances[m_selection.get_instance_idx()]; diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 222b0137e4..73b877bfb7 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -462,6 +462,7 @@ public: bool is_modifier() const { return m_type == Modifier; } bool is_single_full_instance() const; bool is_single_full_object() const { return m_type == SingleFullObject; } + bool is_mixed() const { return m_type == Mixed; } bool is_from_single_instance() const { return get_instance_idx() != -1; } bool is_from_single_object() const { return get_object_idx() != -1; } From 94da98c9c4f39bdea7e8b537bbc13760bd59359f Mon Sep 17 00:00:00 2001 From: YuSanka Date: Wed, 10 Oct 2018 13:53:45 +0200 Subject: [PATCH 080/186] Ported on_extruders_change and filament_color_box_lmouse_down(like a lambda-f inside PresetComboBox) --- src/slic3r/GUI/GUI_App.cpp | 8 ++ src/slic3r/GUI/GUI_App.hpp | 1 + src/slic3r/GUI/MainFrame.cpp | 56 +++++------ src/slic3r/GUI/Plater.cpp | 166 +++++++++++++++++++++++--------- src/slic3r/GUI/Plater.hpp | 12 ++- src/slic3r/GUI/PresetBundle.cpp | 9 +- src/slic3r/GUI/PresetBundle.hpp | 2 +- 7 files changed, 167 insertions(+), 87 deletions(-) diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 3bf068b560..775114654c 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -502,6 +502,14 @@ void GUI_App::get_installed_languages(wxArrayString & names, wxArrayLong & ident } } +Tab* GUI_App::get_tab(Preset::Type type) +{ + for (Tab* tab: tabs_list) + if (tab->type() == type) + return tab; + return nullptr; +} + ConfigMenuIDs GUI_App::get_view_mode() { if (!app_config->has("view_mode")) diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 451b891471..55254ffd58 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -128,6 +128,7 @@ public: void save_language(); void get_installed_languages(wxArrayString & names, wxArrayLong & identifiers); + Tab* get_tab(Preset::Type type); ConfigMenuIDs get_view_mode(); void update_mode(); diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 4dbaa9d09b..ecd1ddea29 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -134,23 +134,6 @@ void MainFrame::init_tabpanel() // The following event is emited by Tab implementation on config value change. Bind(EVT_TAB_VALUE_CHANGED, &MainFrame::on_value_changed, this); -// EVT_COMMAND($self, -1, $VALUE_CHANGE_EVENT, sub { -// my($self, $event) = @_; -// auto str = event->GetString; -// my($opt_key, $name) = ($str = ~/ (.*) (.*) / ); -// auto tab = Slic3r::GUI::get_preset_tab(name); -// auto config = tab->get_config(); -// if (m_plater) { -// m_plater->on_config_change(config); // propagate config change events to the plater -// if (opt_key == "extruders_count"){ -// auto value = event->GetInt(); -// m_plater->on_extruders_change(value); -// } -// } -// // don't save while loading for the first time -// if (Slic3r::GUI::autosave && m_loaded) -// m_config->save(Slic3r::GUI::autosave) ; -// }); // The following event is emited by Tab on preset selection, // or when the preset's "modified" status changes. @@ -174,22 +157,15 @@ void MainFrame::init_tabpanel() m_options_tabs[tab_name] = get_preset_tab(tab_name.c_str()); if (m_plater) { -// m_plater->on_select_preset(sub{ -// my($group, $name) = @_; -// $self->{options_tabs}{$group}->select_preset($name); -// }); // load initial config auto full_config = wxGetApp().preset_bundle->full_config(); -// m_plater->on_config_change(full_config); + m_plater->on_config_change(&full_config); // Show a correct number of filament fields. -// if (defined full_config->nozzle_diameter){ -// // nozzle_diameter is undefined when SLA printer is selected -// m_plater->on_extruders_change(int(@{$full_config->nozzle_diameter})); -// } - - // Show correct preset comboboxes according to the printer_technology -// m_plater->show_preset_comboboxes(full_config.printer_technology() == "FFF" ? 0 : 1); + // nozzle_diameter is undefined when SLA printer is selected + if (full_config.has("nozzle_diameter")){ + m_plater->on_extruders_change(full_config.option("nozzle_diameter")->values.size()); + } } } @@ -779,16 +755,32 @@ void MainFrame::on_presets_changed(SimpleEvent &event) else cur_tab->load_current_preset(); } - m_plater->sidebar().show_preset_comboboxes(static_cast(tab)->m_printer_technology == ptSLA); } // XXX: ? // m_plater->on_config_change(tab->get_config()); } } -void MainFrame::on_value_changed(wxCommandEvent&) +void MainFrame::on_value_changed(wxCommandEvent& event) { - ; + auto *tab = dynamic_cast(event.GetEventObject()); + wxASSERT(tab != nullptr); + if (tab == nullptr) + return; + + auto opt_key = event.GetString(); + auto config = tab->get_config(); + if (m_plater) { + m_plater->on_config_change(config); // propagate config change events to the plater + if (opt_key == "extruders_count"){ + auto value = event.GetInt(); + m_plater->on_extruders_change(value); + } + } + // don't save while loading for the first time + // #ys_FIXME ?autosave? +// if (wxGetApp().autosave && m_loaded) +// m_config->save(wxGetApp().autosave); } // Called after the Preferences dialog is closed and the program settings are saved. diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 99395c826e..e0101f54c7 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include "libslic3r/libslic3r.h" #include "libslic3r/PrintConfig.hpp" @@ -45,6 +46,7 @@ #include "BackgroundSlicingProcess.hpp" #include "ProgressStatusBar.hpp" #include "slic3r/Utils/ASCIIFolding.hpp" +#include "PrintConfig.hpp" #include // Needs to be last because reasons :-/ #include "WipeTowerDialog.hpp" @@ -189,6 +191,34 @@ PresetComboBox::PresetComboBox(wxWindow *parent, Preset::Type preset_type) : evt.StopPropagation(); } }); + + if (preset_type == Slic3r::Preset::TYPE_FILAMENT) + { + Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent &event) { + if (extruder_idx < 0 || event.GetLogicalPosition(wxClientDC(this)).x > 24) { + // Let the combo box process the mouse click. + event.Skip(); + return; + } + + // Swallow the mouse click and open the color picker. + auto data = new wxColourData(); + data->SetChooseFull(1); + auto dialog = new wxColourDialog(wxGetApp().mainframe, data); + if (dialog->ShowModal() == wxID_OK) { + DynamicPrintConfig cfg = *wxGetApp().get_tab(Preset::TYPE_PRINTER)->get_config(); + + auto colors = static_cast(wxGetApp().preset_bundle->full_config().option("extruder_colour")->clone()); + colors->values[extruder_idx] = dialog->GetColourData().GetColour().GetAsString(wxC2S_HTML_SYNTAX); + + cfg.set_key_value("extruder_colour", colors); + + wxGetApp().get_tab(Preset::TYPE_PRINTER)->load_config(cfg); + wxGetApp().preset_bundle->update_platter_filament_ui(extruder_idx, this); + } + dialog->Destroy(); + }); + } } PresetComboBox::~PresetComboBox() {} @@ -365,8 +395,29 @@ struct Sidebar::priv bool show_manifold_warning_icon = false; bool show_print_info = false; + + + void show_preset_comboboxes(); }; +void Sidebar::priv::show_preset_comboboxes() +{ + const bool showSLA = wxGetApp().preset_bundle->printers.get_selected_preset().printer_technology() == ptSLA; + + wxWindowUpdateLocker noUpdates(wxGetApp().mainframe); + + for (size_t i = 0; i < 4; ++i) + sizer_presets->Show(i, !showSLA); + + sizer_presets->Show(4, showSLA); + sizer_presets->Show(5, showSLA); + + frequently_changed_parameters->get_sizer()->Show(!showSLA); + + wxGetApp().plater()->Layout(); + wxGetApp().mainframe->Layout(); +} + // Sidebar / public @@ -378,13 +429,12 @@ Sidebar::Sidebar(Plater *parent) // The preset chooser p->sizer_presets = new wxFlexGridSizer(4, 2, 1, 2); p->sizer_presets->AddGrowableCol(1, 1); - p->sizer_presets->SetFlexibleDirection(wxHORIZONTAL); + p->sizer_presets->SetFlexibleDirection(wxBOTH); p->sizer_filaments = new wxBoxSizer(wxVERTICAL); auto init_combo = [this](PresetComboBox **combo, wxString label, Preset::Type preset_type, bool filament) { auto *text = new wxStaticText(p->scrolled, wxID_ANY, label); text->SetFont(wxGetApp().small_font()); - // combo = new wxBitmapComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, nullptr, wxCB_READONLY); *combo = new PresetComboBox(p->scrolled, preset_type); auto *sizer_presets = this->p->sizer_presets; @@ -394,6 +444,7 @@ Sidebar::Sidebar(Plater *parent) sizer_presets->Add(*combo, 1, wxALIGN_CENTER_VERTICAL | wxEXPAND | wxBOTTOM, 1); } else { sizer_filaments->Add(*combo, 1, wxEXPAND | wxBOTTOM, 1); + (*combo)->set_extruder_idx(0); sizer_presets->Add(sizer_filaments, 1, wxEXPAND); } }; @@ -469,6 +520,30 @@ Sidebar::Sidebar(Plater *parent) Sidebar::~Sidebar() {} +void Sidebar::init_filament_combo(PresetComboBox **combo, const int extr_idx) { + *combo = new PresetComboBox(p->scrolled, Slic3r::Preset::TYPE_FILAMENT); +// # copy icons from first choice +// $choice->SetItemBitmap($_, $choices->[0]->GetItemBitmap($_)) for 0..$#presets; + + (*combo)->set_extruder_idx(extr_idx); + + auto /***/sizer_filaments = this->p->sizer_filaments; + sizer_filaments->Add(*combo, 1, wxEXPAND | wxBOTTOM, 1); +} + +void Sidebar::remove_unused_filament_combos(const int current_extruder_count) +{ + if (current_extruder_count >= p->combos_filament.size()) + return; + auto sizer_filaments = this->p->sizer_filaments; + while (p->combos_filament.size() > current_extruder_count) { + const int last = p->combos_filament.size() - 1; + sizer_filaments->Remove(last); + (*p->combos_filament[last]).Destroy(); + p->combos_filament.pop_back(); + } +} + void Sidebar::update_presets(Preset::Type preset_type) { switch (preset_type) { @@ -503,6 +578,7 @@ void Sidebar::update_presets(Preset::Type preset_type) for (size_t i = 0; i < p->combos_filament.size(); i++) { wxGetApp().preset_bundle->update_platter_filament_ui(i, p->combos_filament[i]); } + p->show_preset_comboboxes(); break; default: break; @@ -512,22 +588,6 @@ void Sidebar::update_presets(Preset::Type preset_type) wxGetApp().preset_bundle->export_selections(*wxGetApp().app_config); } -void Sidebar::show_preset_comboboxes(bool showSLA) -{ -// wxWindowUpdateLocker noUpdates(wxGetApp().mainframe); - - for (size_t i = 0; i < 4; ++i) - p->sizer_presets->Show(i, !showSLA); - - p->sizer_presets->Show(4, showSLA); - p->sizer_presets->Show(5, showSLA); - - p->frequently_changed_parameters->get_sizer()->Show(!showSLA); - - wxGetApp().plater()->Layout(); - wxGetApp().mainframe->Layout(); -} - ObjectManipulation* Sidebar::obj_manipul() { return p->object_manipulation; @@ -591,6 +651,13 @@ bool Sidebar::is_multifilament() return p->combos_filament.size() > 0; } + +std::vector& Sidebar::combos_filament() +{ + return p->combos_filament; +} + + // Plater::Object struct PlaterObject @@ -704,9 +771,7 @@ struct Plater::priv void reload_from_disk(); void export_object_stl(); void fix_through_netfabb(); - void show_preset_comboboxes(); void item_changed_selection(); - void filament_color_box_lmouse_down(); void on_notebook_changed(wxBookCtrlEvent&); void on_select_preset(wxCommandEvent&); @@ -714,8 +779,6 @@ struct Plater::priv void on_update_print_preview(wxCommandEvent&); void on_process_completed(wxCommandEvent&); void on_layer_editing_toggled(bool enable); - void on_extruders_change(); - void on_config_change(); void on_action_add(SimpleEvent&); void on_action_arrange(SimpleEvent&); @@ -1417,22 +1480,11 @@ void Plater::priv::fix_through_netfabb() // TODO } -void Plater::priv::show_preset_comboboxes() -{ - // TODO -} - void Plater::priv::item_changed_selection() { // TODO } -void Plater::priv::filament_color_box_lmouse_down() -{ - // TODO -} - - void Plater::priv::on_notebook_changed(wxBookCtrlEvent&) { const auto current_id = notebook->GetCurrentPage()->GetId(); @@ -1454,9 +1506,9 @@ void Plater::priv::on_notebook_changed(wxBookCtrlEvent&) void Plater::priv::on_select_preset(wxCommandEvent &evt) { auto preset_type = static_cast(evt.GetInt()); - auto *combo = static_cast(evt.GetEventObject()); + auto *combo = static_cast(evt.GetEventObject()); - auto idx = 0;// evt.GetId(); + auto idx = combo->get_extruder_idx(); if (preset_type == Preset::TYPE_FILAMENT) { wxGetApp().preset_bundle->set_filament_preset(idx, combo->GetStringSelection().ToStdString()); @@ -1464,10 +1516,10 @@ void Plater::priv::on_select_preset(wxCommandEvent &evt) // TODO: ? if (preset_type == Preset::TYPE_FILAMENT && sidebar->is_multifilament()) { - // Only update the platter UI for the 2nd and other filaments. + // Only update the platter UI for the 2nd and other filaments. wxGetApp().preset_bundle->update_platter_filament_ui(idx, combo); - // } - } else { + } + else { for (Tab* tab : wxGetApp().tabs_list) { if (tab->type() == preset_type) { tab->select_preset(combo->GetStringSelection().ToStdString()); @@ -1509,16 +1561,6 @@ void Plater::priv::on_layer_editing_toggled(bool enable) canvas3D->Update(); } -void Plater::priv::on_extruders_change() -{ - // TODO -} - -void Plater::priv::on_config_change() -{ - // TODO -} - void Plater::priv::on_action_add(SimpleEvent&) { wxArrayString input_files; @@ -1775,6 +1817,34 @@ void Plater::send_gcode() p->send_gcode_file = export_gcode(); } +void Plater::on_extruders_change(int num_extruders) +{ + auto& choices = sidebar().combos_filament(); + + int i = choices.size(); + while ( i < num_extruders ) + { + PresetComboBox* choice/*{ nullptr }*/; + sidebar().init_filament_combo(&choice, i); + choices.push_back(choice); + + // initialize selection + wxGetApp().preset_bundle->update_platter_filament_ui(i, choice); + ++i; + } + + // remove unused choices if any + sidebar().remove_unused_filament_combos(num_extruders); + + sidebar().Layout(); + GetParent()->Layout(); +} + +void Plater::on_config_change(DynamicPrintConfig* config) +{ + // TODO +} + void Plater::changed_object_settings(int obj_idx) { if (obj_idx < 0) diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 51291ee226..fd3c4e455d 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -11,7 +11,7 @@ #include "Preset.hpp" class wxButton; - +class wxBoxSizer; namespace Slic3r { @@ -35,6 +35,8 @@ public: ~PresetComboBox(); void set_label_marker(int item); + void set_extruder_idx(const int extr_idx) { extruder_idx = extr_idx; } + int get_extruder_idx() const { return extruder_idx; } private: typedef std::size_t Marker; @@ -42,6 +44,7 @@ private: Preset::Type preset_type; int last_selected; + int extruder_idx = -1; }; class Sidebar : public wxPanel @@ -54,8 +57,9 @@ public: Sidebar &operator=(const Sidebar &) = delete; ~Sidebar(); + void init_filament_combo(PresetComboBox **combo, const int extr_idx); + void remove_unused_filament_combos(const int current_extruder_count); void update_presets(Slic3r::Preset::Type preset_type); - void show_preset_comboboxes(bool showSLA); ObjectManipulation* obj_manipul(); ObjectList* obj_list(); @@ -69,6 +73,7 @@ public: void enable_buttons(bool enable); bool is_multifilament(); + std::vector& combos_filament(); private: struct priv; std::unique_ptr p; @@ -102,6 +107,9 @@ public: void reslice(); void changed_object_settings(int obj_idx); void send_gcode(); + + void on_extruders_change(int extruders_count); + void on_config_change(DynamicPrintConfig* config); private: struct priv; std::unique_ptr p; diff --git a/src/slic3r/GUI/PresetBundle.cpp b/src/slic3r/GUI/PresetBundle.cpp index cd3924dd0a..8d4ab194a3 100644 --- a/src/slic3r/GUI/PresetBundle.cpp +++ b/src/slic3r/GUI/PresetBundle.cpp @@ -3,6 +3,7 @@ #include "PresetBundle.hpp" #include "BitmapCache.hpp" +#include "Plater.hpp" #include #include @@ -1297,7 +1298,7 @@ bool PresetBundle::parse_color(const std::string &scolor, unsigned char *rgb_out return true; } -void PresetBundle::update_platter_filament_ui(unsigned int idx_extruder, wxBitmapComboBox *ui) +void PresetBundle::update_platter_filament_ui(unsigned int idx_extruder, GUI::PresetComboBox *ui) { if (ui == nullptr || this->printers.get_edited_preset().printer_technology() == ptSLA) return; @@ -1320,7 +1321,7 @@ void PresetBundle::update_platter_filament_ui(unsigned int idx_extruder, wxBitma std::map nonsys_presets; wxString selected_str = ""; if (!this->filaments().front().is_visible) - ui->Append("------- " + _(L("System presets")) + " -------", wxNullBitmap); + ui->set_label_marker(ui->Append("------- " + _(L("System presets")) + " -------", wxNullBitmap)); for (int i = this->filaments().front().is_visible ? 0 : 1; i < int(this->filaments().size()); ++i) { const Preset &preset = this->filaments.preset(i); bool selected = this->filament_presets[idx_extruder] == preset.name; @@ -1373,12 +1374,12 @@ void PresetBundle::update_platter_filament_ui(unsigned int idx_extruder, wxBitma selected_str = wxString::FromUTF8((preset.name + (preset.is_dirty ? Preset::suffix_modified() : "")).c_str()); } if (preset.is_default) - ui->Append("------- " + _(L("System presets")) + " -------", wxNullBitmap); + ui->set_label_marker(ui->Append("------- " + _(L("System presets")) + " -------", wxNullBitmap)); } if (!nonsys_presets.empty()) { - ui->Append("------- " + _(L("User presets")) + " -------", wxNullBitmap); + ui->set_label_marker(ui->Append("------- " + _(L("User presets")) + " -------", wxNullBitmap)); for (std::map::iterator it = nonsys_presets.begin(); it != nonsys_presets.end(); ++it) { ui->Append(it->first, *it->second); if (it->first == selected_str) diff --git a/src/slic3r/GUI/PresetBundle.hpp b/src/slic3r/GUI/PresetBundle.hpp index 3cd8df54b6..e116b0ff90 100644 --- a/src/slic3r/GUI/PresetBundle.hpp +++ b/src/slic3r/GUI/PresetBundle.hpp @@ -110,7 +110,7 @@ public: void export_configbundle(const std::string &path); // , const DynamicPrintConfig &settings); // Update a filament selection combo box on the platter for an idx_extruder. - void update_platter_filament_ui(unsigned int idx_extruder, wxBitmapComboBox *ui); + void update_platter_filament_ui(unsigned int idx_extruder, GUI::PresetComboBox *ui); // Enable / disable the "- default -" preset. void set_default_suppressed(bool default_suppressed); From a7425ec22963537799fffb1f5ede80318f2e6971 Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Wed, 10 Oct 2018 14:43:07 +0200 Subject: [PATCH 081/186] Plater: Fix in load_model_objects --- src/slic3r/GUI/Plater.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index e6c55e3a2c..3af670d59a 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1135,6 +1135,9 @@ std::vector Plater::priv::load_model_objects(const ModelObjectPtrs &mode instance->set_scaling_factor(inverse); } } + + print.auto_assign_extruders(object); + print.add_model_object(object); } // if user turned autocentering off, automatic arranging would disappoint them From 30f3ec3d1618260ba787c823d276312b4b98a619 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Wed, 10 Oct 2018 16:22:20 +0200 Subject: [PATCH 082/186] Changed mode of the OblectList to Multiple selection --- src/slic3r/GUI/GLCanvas3D.hpp | 1 + src/slic3r/GUI/GUI_ObjectList.cpp | 13 +++++++++++-- src/slic3r/GUI/GUI_ObjectList.hpp | 2 ++ src/slic3r/GUI/GUI_ObjectManipulation.cpp | 3 ++- 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 73b877bfb7..833f9d5316 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -741,6 +741,7 @@ public: #if ENABLE_EXTENDED_SELECTION const Selection& get_selection() const { return m_selection; } + Selection& get_selection() { return m_selection; } #endif // ENABLE_EXTENDED_SELECTION // Set the bed shape to a single closed 2D polygon(array of two element arrays), diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 2583df975d..0ee8f204b3 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -18,7 +18,7 @@ namespace GUI { ObjectList::ObjectList(wxWindow* parent) : - wxDataViewCtrl(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize) + wxDataViewCtrl(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxDV_MULTIPLE) { // Fill CATEGORY_ICON { @@ -328,7 +328,9 @@ void ObjectList::on_begin_drag(wxDataViewEvent &event) wxDataViewItem item(event.GetItem()); // only allow drags for item, not containers - if (m_objects_model->GetParent(item) == wxDataViewItem(0) || m_objects_model->IsSettingsItem(item)) { + if (multiple_selection() || + m_objects_model->GetParent(item) == wxDataViewItem(0) || + m_objects_model->IsSettingsItem(item) ) { event.Veto(); return; } @@ -1139,5 +1141,12 @@ void ObjectList::init_objects() m_objects = wxGetApp().model_objects(); } +bool ObjectList::multiple_selection() const +{ + wxDataViewItemArray sels; + GetSelections(sels); + return sels.size() > 1; +} + } //namespace GUI } //namespace Slic3r \ No newline at end of file diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index dc85b13afe..948a4a74b2 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -121,6 +121,8 @@ public: void remove(); void init_objects(); + + bool multiple_selection() const ; }; diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index aaca076ed9..5eb90054c0 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -176,7 +176,8 @@ void ObjectManipulation::update_settings_list() auto config = wxGetApp().obj_list()->m_config; const auto item = objects_ctrl->GetSelection(); - if (config && objects_model->IsSettingsItem(item)) + if (!objects_ctrl->multiple_selection() && + config && objects_model->IsSettingsItem(item)) { auto extra_column = [config](wxWindow* parent, const Line& line) { From 3bccb3b97c642d4c999df092f62706321ef780fb Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Thu, 11 Oct 2018 08:26:12 +0200 Subject: [PATCH 083/186] Extended interface for selections --- src/slic3r/GUI/GLCanvas3D.cpp | 176 ++++++++++++++++++++++++---------- src/slic3r/GUI/GLCanvas3D.hpp | 38 +++++--- 2 files changed, 150 insertions(+), 64 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 496942e1bc..f3fb9b0be4 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1162,13 +1162,13 @@ GLCanvas3D::Selection::Selection() void GLCanvas3D::Selection::set_volumes(GLVolumePtrs* volumes) { m_volumes = volumes; - update_valid(); + _update_valid(); } void GLCanvas3D::Selection::set_model(Model* model) { m_model = model; - update_valid(); + _update_valid(); } void GLCanvas3D::Selection::add(unsigned int volume_idx, bool as_single_selection) @@ -1185,22 +1185,22 @@ void GLCanvas3D::Selection::add(unsigned int volume_idx, bool as_single_selectio { case Volume: { - add_volume(volume_idx); + _add_volume(volume_idx); break; } case Instance: { - add_instance(volume_idx); + _add_instance(volume->object_idx(), volume->instance_idx()); break; } case Object: { - add_object(volume_idx); + _add_object(volume->object_idx()); break; } } - update_type(); + _update_type(); m_bounding_box_dirty = true; } @@ -1209,26 +1209,116 @@ void GLCanvas3D::Selection::remove(unsigned int volume_idx) if (!m_valid || ((unsigned int)m_volumes->size() <= volume_idx)) return; + GLVolume* volume = (*m_volumes)[volume_idx]; + switch (m_mode) { case Volume: { - remove_volume(volume_idx); + _remove_volume(volume_idx); break; } case Instance: { - remove_instance(volume_idx); + _remove_instance(volume->object_idx(), volume->instance_idx()); break; } case Object: { - remove_object(volume_idx); + _remove_object(volume->object_idx()); break; } } - update_type(); + _update_type(); + m_bounding_box_dirty = true; +} + +void GLCanvas3D::Selection::add_object(unsigned int object_idx, bool as_single_selection) +{ + if (!m_valid) + return; + + // resets the current list if needed + if (as_single_selection) + clear(); + + _add_object(object_idx); + + _update_type(); + m_bounding_box_dirty = true; +} + +void GLCanvas3D::Selection::remove_object(unsigned int object_idx) +{ + if (!m_valid) + return; + + _remove_object(object_idx); + + _update_type(); + m_bounding_box_dirty = true; +} + +void GLCanvas3D::Selection::add_instance(unsigned int object_idx, unsigned int instance_idx, bool as_single_selection) +{ + if (!m_valid) + return; + + // resets the current list if needed + if (as_single_selection) + clear(); + + _add_instance(object_idx, instance_idx); + + _update_type(); + m_bounding_box_dirty = true; +} + +void GLCanvas3D::Selection::remove_instance(unsigned int object_idx, unsigned int instance_idx) +{ + if (!m_valid) + return; + + _remove_instance(object_idx, instance_idx); + + _update_type(); + m_bounding_box_dirty = true; +} + +void GLCanvas3D::Selection::add_volume(unsigned int object_idx, unsigned int volume_idx, bool as_single_selection) +{ + if (!m_valid) + return; + + // resets the current list if needed + if (as_single_selection) + clear(); + + for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i) + { + GLVolume* v = (*m_volumes)[i]; + if ((v->object_idx() == object_idx) && (v->volume_idx() == volume_idx)) + _add_volume(i); + } + + _update_type(); + m_bounding_box_dirty = true; +} + +void GLCanvas3D::Selection::remove_volume(unsigned int object_idx, unsigned int volume_idx) +{ + if (!m_valid) + return; + + for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i) + { + GLVolume* v = (*m_volumes)[i]; + if ((v->object_idx() == object_idx) && (v->volume_idx() == volume_idx)) + _remove_volume(i); + } + + _update_type(); m_bounding_box_dirty = true; } @@ -1243,7 +1333,7 @@ void GLCanvas3D::Selection::clear() } m_list.clear(); - update_type(); + _update_type(); m_bounding_box_dirty = true; } @@ -1287,7 +1377,7 @@ const GLVolume* GLCanvas3D::Selection::get_volume(unsigned int volume_idx) const const BoundingBoxf3& GLCanvas3D::Selection::get_bounding_box() const { if (m_bounding_box_dirty) - calc_bounding_box(); + _calc_bounding_box(); return m_bounding_box; } @@ -1297,7 +1387,7 @@ void GLCanvas3D::Selection::start_dragging() if (!m_valid) return; - set_caches(); + _set_caches(); } void GLCanvas3D::Selection::translate(const Vec3d& displacement) @@ -1362,7 +1452,7 @@ void GLCanvas3D::Selection::rotate(const Vec3d& rotation) } if (m_mode == Instance) - synchronize_unselected_instances(); + _synchronize_unselected_instances(); m_bounding_box_dirty = true; } @@ -1373,19 +1463,19 @@ void GLCanvas3D::Selection::render(bool show_indirect_selection) const return; // render cumulative bounding box of selected volumes - render_selected_volumes(); + _render_selected_volumes(); // render bounding boxes of indirectly selected instances if (show_indirect_selection && (m_mode == Instance)) - render_unselected_instances(); + _render_unselected_instances(); } -void GLCanvas3D::Selection::update_valid() +void GLCanvas3D::Selection::_update_valid() { m_valid = (m_volumes != nullptr) && (m_model != nullptr); } -void GLCanvas3D::Selection::update_type() +void GLCanvas3D::Selection::_update_type() { m_cache.content.clear(); m_type = Mixed; @@ -1481,7 +1571,7 @@ void GLCanvas3D::Selection::update_type() } } -void GLCanvas3D::Selection::set_caches() +void GLCanvas3D::Selection::_set_caches() { m_cache.volumes_data.clear(); for (unsigned int i : m_list) @@ -1492,7 +1582,7 @@ void GLCanvas3D::Selection::set_caches() m_cache.dragging_center = get_bounding_box().center(); } -void GLCanvas3D::Selection::add_volume(unsigned int volume_idx) +void GLCanvas3D::Selection::_add_volume(unsigned int volume_idx) { // check if the given idx is already selected if (m_list.find(volume_idx) != m_list.end()) @@ -1502,34 +1592,27 @@ void GLCanvas3D::Selection::add_volume(unsigned int volume_idx) (*m_volumes)[volume_idx]->selected = true; } -void GLCanvas3D::Selection::add_instance(unsigned int volume_idx) +void GLCanvas3D::Selection::_add_instance(unsigned int object_idx, unsigned int instance_idx) { - GLVolume* volume = (*m_volumes)[volume_idx]; - int object_idx = volume->object_idx(); - int instance_idx = volume->instance_idx(); - for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i) { GLVolume* v = (*m_volumes)[i]; if ((v->object_idx() == object_idx) && (v->instance_idx() == instance_idx)) - add_volume(i); + _add_volume(i); } } -void GLCanvas3D::Selection::add_object(unsigned int volume_idx) +void GLCanvas3D::Selection::_add_object(unsigned int object_idx) { - GLVolume* volume = (*m_volumes)[volume_idx]; - int object_idx = volume->object_idx(); - for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i) { GLVolume* v = (*m_volumes)[i]; if (v->object_idx() == object_idx) - add_volume(i); + _add_volume(i); } } -void GLCanvas3D::Selection::remove_volume(unsigned int volume_idx) +void GLCanvas3D::Selection::_remove_volume(unsigned int volume_idx) { IndicesList::iterator v_it = m_list.find(volume_idx); if (v_it == m_list.end()) @@ -1540,34 +1623,27 @@ void GLCanvas3D::Selection::remove_volume(unsigned int volume_idx) (*m_volumes)[volume_idx]->selected = false; } -void GLCanvas3D::Selection::remove_instance(unsigned int volume_idx) +void GLCanvas3D::Selection::_remove_instance(unsigned int object_idx, unsigned int instance_idx) { - GLVolume* volume = (*m_volumes)[volume_idx]; - int object_idx = volume->object_idx(); - int instance_idx = volume->instance_idx(); - for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i) { GLVolume* v = (*m_volumes)[i]; if ((v->object_idx() == object_idx) && (v->instance_idx() == instance_idx)) - remove_volume(i); + _remove_volume(i); } } -void GLCanvas3D::Selection::remove_object(unsigned int volume_idx) +void GLCanvas3D::Selection::_remove_object(unsigned int object_idx) { - GLVolume* volume = (*m_volumes)[volume_idx]; - int object_idx = volume->object_idx(); - for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i) { GLVolume* v = (*m_volumes)[i]; if (v->object_idx() == object_idx) - remove_volume(i); + _remove_volume(i); } } -void GLCanvas3D::Selection::calc_bounding_box() const +void GLCanvas3D::Selection::_calc_bounding_box() const { m_bounding_box = BoundingBoxf3(); if (m_valid) @@ -1580,13 +1656,13 @@ void GLCanvas3D::Selection::calc_bounding_box() const m_bounding_box_dirty = false; } -void GLCanvas3D::Selection::render_selected_volumes() const +void GLCanvas3D::Selection::_render_selected_volumes() const { float color[3] = { 1.0f, 1.0f, 1.0f }; - render_bounding_box(get_bounding_box(), color); + _render_bounding_box(get_bounding_box(), color); } -void GLCanvas3D::Selection::render_unselected_instances() const +void GLCanvas3D::Selection::_render_unselected_instances() const { std::set done; // prevent processing volumes twice done.insert(m_list.begin(), m_list.end()); @@ -1632,11 +1708,11 @@ void GLCanvas3D::Selection::render_unselected_instances() const float color[3] = { 1.0f, 1.0f, 0.0f }; for (const InstanceToBoxMap::value_type& box : boxes) { - render_bounding_box(box.second, color); + _render_bounding_box(box.second, color); } } -void GLCanvas3D::Selection::render_bounding_box(const BoundingBoxf3& box, float* color) const +void GLCanvas3D::Selection::_render_bounding_box(const BoundingBoxf3& box, float* color) const { if (color == nullptr) return; @@ -1686,7 +1762,7 @@ void GLCanvas3D::Selection::render_bounding_box(const BoundingBoxf3& box, float* ::glEnd(); } -void GLCanvas3D::Selection::synchronize_unselected_instances() +void GLCanvas3D::Selection::_synchronize_unselected_instances() { std::set done; // prevent processing volumes twice done.insert(m_list.begin(), m_list.end()); diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 833f9d5316..d556ea54d5 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -455,6 +455,16 @@ public: void add(unsigned int volume_idx, bool as_single_selection = true); void remove(unsigned int volume_idx); + + void add_object(unsigned int object_idx, bool as_single_selection = true); + void remove_object(unsigned int object_idx); + + void add_instance(unsigned int object_idx, unsigned int instance_idx, bool as_single_selection = true); + void remove_instance(unsigned int object_idx, unsigned int instance_idx); + + void add_volume(unsigned int object_idx, unsigned int volume_idx, bool as_single_selection = true); + void remove_volume(unsigned int object_idx, unsigned int volume_idx); + void clear(); bool is_empty() const { return m_type == Empty; } @@ -485,20 +495,20 @@ public: void render(bool show_indirect_selection) const; private: - void update_valid(); - void update_type(); - void set_caches(); - void add_volume(unsigned int volume_idx); - void add_instance(unsigned int volume_idx); - void add_object(unsigned int volume_idx); - void remove_volume(unsigned int volume_idx); - void remove_instance(unsigned int volume_idx); - void remove_object(unsigned int volume_idx); - void calc_bounding_box() const; - void render_selected_volumes() const; - void render_unselected_instances() const; - void render_bounding_box(const BoundingBoxf3& box, float* color) const; - void synchronize_unselected_instances(); + void _update_valid(); + void _update_type(); + void _set_caches(); + void _add_volume(unsigned int volume_idx); + void _add_instance(unsigned int object_idx, unsigned int instance_idx); + void _add_object(unsigned int object_idx); + void _remove_volume(unsigned int volume_idx); + void _remove_instance(unsigned int object_idx, unsigned int instance_idx); + void _remove_object(unsigned int object_idx); + void _calc_bounding_box() const; + void _render_selected_volumes() const; + void _render_unselected_instances() const; + void _render_bounding_box(const BoundingBoxf3& box, float* color) const; + void _synchronize_unselected_instances(); }; private: From e201c5123c016d3510dcb282868681c1ad469851 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Thu, 11 Oct 2018 10:24:19 +0200 Subject: [PATCH 084/186] added method: static GUI::GLCanvas3D* _3DScene::get_canvas(wxGLCanvas* canvas) --- src/slic3r/GUI/3DScene.cpp | 9 +++++++-- src/slic3r/GUI/3DScene.hpp | 6 ++++-- src/slic3r/GUI/GLCanvas3DManager.cpp | 10 ++++++++-- src/slic3r/GUI/GLCanvas3DManager.hpp | 6 ++++-- 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index e5782f6567..68d4dac67e 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -1895,12 +1895,17 @@ bool _3DScene::move_volume_down(wxGLCanvas* canvas, unsigned int id) return s_canvas_mgr.move_volume_down(canvas, id); } -#if !ENABLE_EXTENDED_SELECTION +#if ENABLE_EXTENDED_SELECTION +GUI::GLCanvas3D* _3DScene::get_canvas(wxGLCanvas* canvas) +{ + return s_canvas_mgr.get_canvas(canvas); +} +#else void _3DScene::set_objects_selections(wxGLCanvas* canvas, const std::vector& selections) { s_canvas_mgr.set_objects_selections(canvas, selections); } -#endif // !ENABLE_EXTENDED_SELECTION +#endif // ENABLE_EXTENDED_SELECTION void _3DScene::set_config(wxGLCanvas* canvas, DynamicPrintConfig* config) { diff --git a/src/slic3r/GUI/3DScene.hpp b/src/slic3r/GUI/3DScene.hpp index 09f425ba0b..5eb349f096 100644 --- a/src/slic3r/GUI/3DScene.hpp +++ b/src/slic3r/GUI/3DScene.hpp @@ -528,9 +528,11 @@ public: static bool move_volume_up(wxGLCanvas* canvas, unsigned int id); static bool move_volume_down(wxGLCanvas* canvas, unsigned int id); -#if !ENABLE_EXTENDED_SELECTION +#if ENABLE_EXTENDED_SELECTION + static GUI::GLCanvas3D* get_canvas(wxGLCanvas* canvas); +#else static void set_objects_selections(wxGLCanvas* canvas, const std::vector& selections); -#endif // !ENABLE_EXTENDED_SELECTION +#endif // ENABLE_EXTENDED_SELECTION static void set_config(wxGLCanvas* canvas, DynamicPrintConfig* config); static void set_print(wxGLCanvas* canvas, Print* print); diff --git a/src/slic3r/GUI/GLCanvas3DManager.cpp b/src/slic3r/GUI/GLCanvas3DManager.cpp index 87909110e1..182298a690 100644 --- a/src/slic3r/GUI/GLCanvas3DManager.cpp +++ b/src/slic3r/GUI/GLCanvas3DManager.cpp @@ -287,14 +287,20 @@ bool GLCanvas3DManager::move_volume_down(wxGLCanvas* canvas, unsigned int id) return (it != m_canvases.end()) ? it->second->move_volume_down(id) : false; } -#if !ENABLE_EXTENDED_SELECTION +#if ENABLE_EXTENDED_SELECTION +GLCanvas3D* GLCanvas3DManager::get_canvas(wxGLCanvas* canvas) +{ + CanvasesMap::const_iterator it = _get_canvas(canvas); + return (it != m_canvases.end()) ? it->second : nullptr; +} +#else void GLCanvas3DManager::set_objects_selections(wxGLCanvas* canvas, const std::vector& selections) { CanvasesMap::iterator it = _get_canvas(canvas); if (it != m_canvases.end()) it->second->set_objects_selections(selections); } -#endif // !ENABLE_EXTENDED_SELECTION +#endif // ENABLE_EXTENDED_SELECTION void GLCanvas3DManager::set_config(wxGLCanvas* canvas, DynamicPrintConfig* config) { diff --git a/src/slic3r/GUI/GLCanvas3DManager.hpp b/src/slic3r/GUI/GLCanvas3DManager.hpp index ca882d4aef..2261a57b2b 100644 --- a/src/slic3r/GUI/GLCanvas3DManager.hpp +++ b/src/slic3r/GUI/GLCanvas3DManager.hpp @@ -96,9 +96,11 @@ public: bool move_volume_up(wxGLCanvas* canvas, unsigned int id); bool move_volume_down(wxGLCanvas* canvas, unsigned int id); -#if !ENABLE_EXTENDED_SELECTION +#if ENABLE_EXTENDED_SELECTION + GLCanvas3D* get_canvas(wxGLCanvas* canvas); +#else void set_objects_selections(wxGLCanvas* canvas, const std::vector& selections); -#endif // !ENABLE_EXTENDED_SELECTION +#endif // ENABLE_EXTENDED_SELECTION void set_config(wxGLCanvas* canvas, DynamicPrintConfig* config); void set_print(wxGLCanvas* canvas, Print* print); From bb2000d094599da4b50c4843783a6d560a8d01c1 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Thu, 11 Oct 2018 10:52:50 +0200 Subject: [PATCH 085/186] Simplified OpenGL calls --- src/slic3r/GUI/3DScene.cpp | 8 ++++---- src/slic3r/GUI/GLCanvas3D.cpp | 17 +++++++++-------- src/slic3r/GUI/GLGizmo.cpp | 32 ++++++++++++++++---------------- 3 files changed, 29 insertions(+), 28 deletions(-) diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index 68d4dac67e..92e9039115 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -572,7 +572,7 @@ void GLVolume::render_VBOs(int color_id, int detection_id, int worldmatrix_id) c ::glUniform4fv(color_id, 1, (const GLfloat*)color); } else - ::glColor4f(render_color[0], render_color[1], render_color[2], render_color[3]); + ::glColor4fv(render_color); if (detection_id != -1) ::glUniform1i(detection_id, shader_outside_printer_detection_enabled ? 1 : 0); @@ -591,7 +591,7 @@ void GLVolume::render_VBOs(int color_id, int detection_id, int worldmatrix_id) c if (color_id >= 0) ::glUniform4fv(color_id, 1, (const GLfloat*)render_color); else - ::glColor4f(render_color[0], render_color[1], render_color[2], render_color[3]); + ::glColor4fv(render_color); if (detection_id != -1) ::glUniform1i(detection_id, shader_outside_printer_detection_enabled ? 1 : 0); @@ -640,7 +640,7 @@ void GLVolume::render_legacy() const ::glDisableClientState(GL_VERTEX_ARRAY); ::glDisableClientState(GL_NORMAL_ARRAY); - ::glColor4f(render_color[0], render_color[1], render_color[2], render_color[3]); + ::glColor4fv(render_color); render(); ::glEnableClientState(GL_VERTEX_ARRAY); @@ -649,7 +649,7 @@ void GLVolume::render_legacy() const return; } - ::glColor4f(render_color[0], render_color[1], render_color[2], render_color[3]); + ::glColor4fv(render_color); ::glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), indexed_vertex_array.vertices_and_normals_interleaved.data() + 3); ::glNormalPointer(GL_FLOAT, 6 * sizeof(float), indexed_vertex_array.vertices_and_normals_interleaved.data()); diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index f3fb9b0be4..50b5c8d4c8 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -600,7 +600,8 @@ bool GLCanvas3D::Bed::_are_equal(const Pointfs& bed_1, const Pointfs& bed_2) } GLCanvas3D::Axes::Axes() - : origin(0, 0, 0), length(0.0f) + : origin(Vec3d::Zero()) + , length(0.0f) { } @@ -615,11 +616,11 @@ void GLCanvas3D::Axes::render(bool depth_test) const ::glBegin(GL_LINES); // draw line for x axis ::glColor3f(1.0f, 0.0f, 0.0f); - ::glVertex3f((GLfloat)origin(0), (GLfloat)origin(1), (GLfloat)origin(2)); + ::glVertex3dv(origin.data()); ::glVertex3f((GLfloat)origin(0) + length, (GLfloat)origin(1), (GLfloat)origin(2)); // draw line for y axis ::glColor3f(0.0f, 1.0f, 0.0f); - ::glVertex3f((GLfloat)origin(0), (GLfloat)origin(1), (GLfloat)origin(2)); + ::glVertex3dv(origin.data()); ::glVertex3f((GLfloat)origin(0), (GLfloat)origin(1) + length, (GLfloat)origin(2)); ::glEnd(); // draw line for Z axis @@ -629,7 +630,7 @@ void GLCanvas3D::Axes::render(bool depth_test) const ::glBegin(GL_LINES); ::glColor3f(0.0f, 0.0f, 1.0f); - ::glVertex3f((GLfloat)origin(0), (GLfloat)origin(1), (GLfloat)origin(2)); + ::glVertex3dv(origin.data()); ::glVertex3f((GLfloat)origin(0), (GLfloat)origin(1), (GLfloat)origin(2) + length); ::glEnd(); } @@ -4894,7 +4895,7 @@ void GLCanvas3D::_camera_tranform() const ::glRotatef(m_camera.phi, 0.0f, 0.0f, 1.0f); // yaw Vec3d neg_target = - m_camera.target; - ::glTranslatef((GLfloat)neg_target(0), (GLfloat)neg_target(1), (GLfloat)neg_target(2)); + ::glTranslated(neg_target(0), neg_target(1), neg_target(2)); } void GLCanvas3D::_picking_pass() const @@ -5003,9 +5004,9 @@ void GLCanvas3D::_render_background() const ::glVertex2f(1.0f, -1.0f); if (m_dynamic_background_enabled && _is_any_volume_outside()) - ::glColor3f(ERROR_BG_COLOR[0], ERROR_BG_COLOR[1], ERROR_BG_COLOR[2]); + ::glColor3fv(ERROR_BG_COLOR); else - ::glColor3f(DEFAULT_BG_COLOR[0], DEFAULT_BG_COLOR[1], DEFAULT_BG_COLOR[2]); + ::glColor3fv(DEFAULT_BG_COLOR); ::glVertex2f(1.0f, 1.0f); ::glVertex2f(-1.0f, 1.0f); @@ -5172,7 +5173,7 @@ void GLCanvas3D::_render_volumes(bool fake_colors) const else { vol->set_render_color(); - ::glColor4f(vol->render_color[0], vol->render_color[1], vol->render_color[2], vol->render_color[3]); + ::glColor4fv(vol->render_color); } vol->render(); diff --git a/src/slic3r/GUI/GLGizmo.cpp b/src/slic3r/GUI/GLGizmo.cpp index 72bf18de95..ced0ca85bd 100644 --- a/src/slic3r/GUI/GLGizmo.cpp +++ b/src/slic3r/GUI/GLGizmo.cpp @@ -142,15 +142,15 @@ void GLGizmoBase::Grabber::render(const BoundingBoxf3& box, const float* render_ if (use_lighting) ::glEnable(GL_LIGHTING); - ::glColor3f((GLfloat)render_color[0], (GLfloat)render_color[1], (GLfloat)render_color[2]); + ::glColor3fv(render_color); ::glPushMatrix(); - ::glTranslatef((GLfloat)center(0), (GLfloat)center(1), (GLfloat)center(2)); + ::glTranslated(center(0), center(1), center(2)); - float rad_to_deg = 180.0f / (GLfloat)PI; - ::glRotatef((GLfloat)angles(0) * rad_to_deg, 1.0f, 0.0f, 0.0f); - ::glRotatef((GLfloat)angles(1) * rad_to_deg, 0.0f, 1.0f, 0.0f); - ::glRotatef((GLfloat)angles(2) * rad_to_deg, 0.0f, 0.0f, 1.0f); + double rad_to_deg = 180.0 / (double)PI; + ::glRotated(angles(0) * rad_to_deg, 1.0, 0.0, 0.0); + ::glRotated(angles(1) * rad_to_deg, 0.0, 1.0, 0.0); + ::glRotated(angles(2) * rad_to_deg, 0.0, 0.0, 1.0); // face min x ::glPushMatrix(); @@ -568,7 +568,7 @@ void GLGizmoRotate::render_grabber(const BoundingBoxf3& box) const ::glBegin(GL_LINES); ::glVertex3f(0.0f, 0.0f, 0.0f); - ::glVertex3f((GLfloat)m_grabbers[0].center(0), (GLfloat)m_grabbers[0].center(1), (GLfloat)m_grabbers[0].center(2)); + ::glVertex3dv(m_grabbers[0].center.data()); ::glEnd(); ::memcpy((void*)m_grabbers[0].color, (const void*)m_highlight_color, 3 * sizeof(float)); @@ -577,7 +577,7 @@ void GLGizmoRotate::render_grabber(const BoundingBoxf3& box) const void GLGizmoRotate::transform_to_local() const { - ::glTranslatef((GLfloat)m_center(0), (GLfloat)m_center(1), (GLfloat)m_center(2)); + ::glTranslated(m_center(0), m_center(1), m_center(2)); switch (m_axis) { @@ -965,8 +965,8 @@ void GLGizmoScale3D::render_grabbers_connection(unsigned int id_1, unsigned int if ((id_1 < grabbers_count) && (id_2 < grabbers_count)) { ::glBegin(GL_LINES); - ::glVertex3f((GLfloat)m_grabbers[id_1].center(0), (GLfloat)m_grabbers[id_1].center(1), (GLfloat)m_grabbers[id_1].center(2)); - ::glVertex3f((GLfloat)m_grabbers[id_2].center(0), (GLfloat)m_grabbers[id_2].center(1), (GLfloat)m_grabbers[id_2].center(2)); + ::glVertex3dv(m_grabbers[id_1].center.data()); + ::glVertex3dv(m_grabbers[id_2].center.data()); ::glEnd(); } } @@ -1170,8 +1170,8 @@ void GLGizmoMove3D::on_render(const BoundingBoxf3& box) const { ::glColor3fv(AXES_COLOR[i]); ::glBegin(GL_LINES); - ::glVertex3f(center(0), center(1), center(2)); - ::glVertex3f((GLfloat)m_grabbers[i].center(0), (GLfloat)m_grabbers[i].center(1), (GLfloat)m_grabbers[i].center(2)); + ::glVertex3dv(center.data()); + ::glVertex3dv(m_grabbers[i].center.data()); ::glEnd(); } } @@ -1184,8 +1184,8 @@ void GLGizmoMove3D::on_render(const BoundingBoxf3& box) const // draw axis ::glColor3fv(AXES_COLOR[m_hover_id]); ::glBegin(GL_LINES); - ::glVertex3f(center(0), center(1), center(2)); - ::glVertex3f((GLfloat)m_grabbers[m_hover_id].center(0), (GLfloat)m_grabbers[m_hover_id].center(1), (GLfloat)m_grabbers[m_hover_id].center(2)); + ::glVertex3dv(center.data()); + ::glVertex3dv(m_grabbers[m_hover_id].center.data()); ::glEnd(); // draw grabber @@ -1303,7 +1303,7 @@ void GLGizmoFlatten::on_render(const BoundingBoxf3& box) const #endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM ::glBegin(GL_POLYGON); for (const Vec3d& vertex : m_planes[i].vertices) - ::glVertex3f((GLfloat)vertex(0), (GLfloat)vertex(1), (GLfloat)vertex(2)); + ::glVertex3dv(vertex.data()); ::glEnd(); ::glPopMatrix(); } @@ -1330,7 +1330,7 @@ void GLGizmoFlatten::on_render_for_picking(const BoundingBoxf3& box) const #endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM ::glBegin(GL_POLYGON); for (const Vec3d& vertex : m_planes[i].vertices) - ::glVertex3f((GLfloat)vertex(0), (GLfloat)vertex(1), (GLfloat)vertex(2)); + ::glVertex3dv(vertex.data()); ::glEnd(); ::glPopMatrix(); } From 6563cff246988e133d5ca72af9ea18ac08f4d595 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Thu, 11 Oct 2018 10:56:25 +0200 Subject: [PATCH 086/186] New selections -> allow all three rotations for single instance selection --- src/slic3r/GUI/GLCanvas3D.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 50b5c8d4c8..a2067bbf3e 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -3235,13 +3235,7 @@ void GLCanvas3D::update_gizmos_data() #if ENABLE_EXTENDED_SELECTION bool enable_move_z = !m_selection.is_wipe_tower(); - bool enable_rotate_xy = m_selection.is_single_full_object() || m_selection.is_mixed(); - m_gizmos.enable_grabber(Gizmos::Move, 2, enable_move_z); - for (int i = 0; i < 2; ++i) - { - m_gizmos.enable_grabber(Gizmos::Rotate, i, enable_rotate_xy); - } if (m_selection.is_single_full_instance()) { From 8337d4675f402b50d6fba25572e87f7a0c1467e0 Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Thu, 11 Oct 2018 10:03:38 +0200 Subject: [PATCH 087/186] Plater: increase, decrease, set_number_of_copies, arrange --- lib/Slic3r/GUI/Plater.pm | 26 ++++---- src/libslic3r/Model.cpp | 9 +++ src/libslic3r/Model.hpp | 1 + src/libslic3r/Print.hpp | 3 +- src/slic3r/GUI/MainFrame.hpp | 2 + src/slic3r/GUI/Plater.cpp | 120 +++++++++++++++++++++++------------ src/slic3r/GUI/Plater.hpp | 7 +- 7 files changed, 110 insertions(+), 58 deletions(-) diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index 94f01e25d9..d2a7a23b11 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -594,7 +594,7 @@ sub new { $self->on_process_completed($event->GetInt ? undef : $event->GetString); }); -# XXX: ??? +# XXX: not done { my $timer_id = Wx::NewId(); $self->{apply_config_timer} = Wx::Timer->new($self, $timer_id); @@ -1179,7 +1179,7 @@ sub reset { $self->update; } -# XXX: not done +# XXX: VK: done sub increase { my ($self, $copies) = @_; $copies //= 1; @@ -1211,7 +1211,7 @@ sub increase { $self->schedule_background_process; } -# XXX: not done +# XXX: VK: done sub decrease { my ($self, $copies_asked) = @_; my $copies = $copies_asked // 1; @@ -1239,7 +1239,7 @@ sub decrease { $self->update; } -# XXX: not done +# XXX: VK: done sub set_number_of_copies { my ($self) = @_; # get current number of copies @@ -1258,8 +1258,8 @@ sub set_number_of_copies { } } -# XXX: not done (?) -sub _get_number_from_user { # XXX: Enrico +# XXX: VK: removed +sub _get_number_from_user { my ($self, $title, $prompt_message, $error_message, $default, $only_positive) = @_; for (;;) { my $value = Wx::GetTextFromUser($prompt_message, $title, $default, $self); @@ -1457,7 +1457,7 @@ sub changescale { $self->update; } -# XXX: not done +# XXX: VK: WIP sub arrange { my ($self) = @_; @@ -2057,7 +2057,7 @@ sub update { $self->Thaw; } -# XXX: done in sidebar? +# XXX: YS: done # When a printer technology is changed, the UI needs to be updated to show/hide needed preset combo boxes. sub show_preset_comboboxes{ my ($self, $showSLA) = @_; #if showSLA is oposite value to "ptFFF" @@ -2076,7 +2076,7 @@ sub show_preset_comboboxes{ $self->Layout; } -# XXX: not done +# XXX: YS: done # When a number of extruders changes, the UI needs to be updated to show a single filament selection combo box per extruder. # Also the wxTheApp->{preset_bundle}->filament_presets needs to be resized accordingly # and some reasonable default has to be selected for the additional extruders. @@ -2188,7 +2188,7 @@ sub on_config_change { $self->schedule_background_process; } -# XXX: not done +# XXX: YS: WIP sub item_changed_selection { my ($self, $obj_idx) = @_; @@ -2214,7 +2214,7 @@ sub collect_selections { return $selections; } -# XXX: not done +# XXX: YS: done, lambda on LEFT_DOWN # Called when clicked on the filament preset combo box. # When clicked on the icon, show the color picker. sub filament_color_box_lmouse_down @@ -2268,7 +2268,7 @@ sub filament_color_box_lmouse_down # } #} -# XXX: not done +# XXX: YS: done sub changed_object_settings { my ($self, $obj_idx, $parts_changed, $part_settings_changed) = @_; @@ -2464,7 +2464,7 @@ sub select_object { $self->selection_changed(1); } -# XXX: not done +# XXX: YS: WIP sub select_object_from_cpp { my ($self, $obj_idx, $vol_idx) = @_; diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 88e4c551aa..e0cf14a57d 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -609,6 +609,15 @@ ModelInstance* ModelObject::add_instance(const ModelInstance &other) return i; } +ModelInstance* ModelObject::add_instance(const Vec3d &offset, const Vec3d &scaling_factor, const Vec3d &rotation) +{ + auto *instance = add_instance(); + instance->set_offset(offset); + instance->set_scaling_factor(scaling_factor); + instance->set_rotation(rotation); + return instance; +} + void ModelObject::delete_instance(size_t idx) { ModelInstancePtrs::iterator i = this->instances.begin() + idx; diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index d9abc109aa..695de61275 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -96,6 +96,7 @@ public: ModelInstance* add_instance(); ModelInstance* add_instance(const ModelInstance &instance); + ModelInstance* add_instance(const Vec3d &offset, const Vec3d &scaling_factor, const Vec3d &rotation); void delete_instance(size_t idx); void delete_last_instance(); void clear_instances(); diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index a646ab8fd1..5bbeb3f6ad 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -416,7 +416,8 @@ public: const PrintObjectConfig& default_object_config() const { return m_default_object_config; } const PrintRegionConfig& default_region_config() const { return m_default_region_config; } const PrintObjectPtrs& objects() const { return m_objects; } - const PrintObject* get_object(int idx) const { return m_objects[idx]; } + PrintObject* get_object(size_t idx) { return m_objects[idx]; } + const PrintObject* get_object(size_t idx) const { return m_objects[idx]; } const PrintRegionPtrs& regions() const { return m_regions; } const PlaceholderParser& placeholder_parser() const { return m_placeholder_parser; } PlaceholderParser& placeholder_parser() { return m_placeholder_parser; } diff --git a/src/slic3r/GUI/MainFrame.hpp b/src/slic3r/GUI/MainFrame.hpp index aa2041a368..ed2646b697 100644 --- a/src/slic3r/GUI/MainFrame.hpp +++ b/src/slic3r/GUI/MainFrame.hpp @@ -106,6 +106,8 @@ public: void select_tab(size_t tab) const; void select_view(const std::string& direction); + AppController* app_controller() { return m_appController; } + std::vector& get_preset_tabs(); Plater* m_plater { nullptr }; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 3af670d59a..f2d42806c7 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -31,6 +31,7 @@ #include "libslic3r/Format/STL.hpp" #include "libslic3r/Format/AMF.hpp" #include "libslic3r/Format/3mf.hpp" +#include "slic3r/AppController.hpp" #include "GUI.hpp" #include "GUI_App.hpp" #include "GUI_ObjectList.hpp" @@ -756,9 +757,6 @@ struct Plater::priv void remove(size_t obj_idx); void reset(); - void increase(size_t num = 1); - void decrease(size_t num = 1); - void set_number_of_copies(); void rotate(); void mirror(const Axis &axis); void scale(); @@ -781,9 +779,6 @@ struct Plater::priv void on_layer_editing_toggled(bool enable); void on_action_add(SimpleEvent&); - void on_action_arrange(SimpleEvent&); - void on_action_more(SimpleEvent&); - void on_action_fewer(SimpleEvent&); void on_action_split(SimpleEvent&); void on_action_cut(SimpleEvent&); void on_action_settings(SimpleEvent&); @@ -886,7 +881,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) : canvas3D->Bind(EVT_GLCANVAS_ARRANGE, [this](SimpleEvent&) { arrange(); }); canvas3D->Bind(EVT_GLCANVAS_ROTATE_OBJECT, [this](Event &evt) { /*TODO: call rotate */ }); canvas3D->Bind(EVT_GLCANVAS_SCALE_UNIFORMLY, [this](SimpleEvent&) { scale(); }); - canvas3D->Bind(EVT_GLCANVAS_INCREASE_OBJECTS, [this](Event &evt) { evt.data == 1 ? increase() : decrease(); }); + canvas3D->Bind(EVT_GLCANVAS_INCREASE_OBJECTS, [q](Event &evt) { evt.data == 1 ? q->increase() : q->decrease(); }); canvas3D->Bind(EVT_GLCANVAS_INSTANCE_MOVED, [this](SimpleEvent&) { update(); }); canvas3D->Bind(EVT_GLCANVAS_WIPETOWER_MOVED, &priv::on_wipetower_moved, this); canvas3D->Bind(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, &priv::on_enable_action_buttons, this); @@ -895,9 +890,9 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) : canvas3D->Bind(EVT_GLTOOLBAR_ADD, &priv::on_action_add, this); canvas3D->Bind(EVT_GLTOOLBAR_DELETE, [q](SimpleEvent&) { q->remove_selected(); } ); canvas3D->Bind(EVT_GLTOOLBAR_DELETE_ALL, [this](SimpleEvent&) { reset(); }); - canvas3D->Bind(EVT_GLTOOLBAR_ARRANGE, &priv::on_action_arrange, this); - canvas3D->Bind(EVT_GLTOOLBAR_MORE, &priv::on_action_more, this); - canvas3D->Bind(EVT_GLTOOLBAR_FEWER, &priv::on_action_fewer, this); + canvas3D->Bind(EVT_GLTOOLBAR_ARRANGE, [this](SimpleEvent&) { arrange(); }); + canvas3D->Bind(EVT_GLTOOLBAR_MORE, [q](SimpleEvent&) { q->increase(); }); + canvas3D->Bind(EVT_GLTOOLBAR_FEWER, [q](SimpleEvent&) { q->decrease(); }); canvas3D->Bind(EVT_GLTOOLBAR_SPLIT, &priv::on_action_split, this); canvas3D->Bind(EVT_GLTOOLBAR_CUT, &priv::on_action_cut, this); canvas3D->Bind(EVT_GLTOOLBAR_SETTINGS, &priv::on_action_settings, this); @@ -1388,21 +1383,6 @@ void Plater::priv::reset() update(); } -void Plater::priv::increase(size_t num) -{ - // TODO -} - -void Plater::priv::decrease(size_t num) -{ - // TODO -} - -void Plater::priv::set_number_of_copies() -{ - // TODO -} - void Plater::priv::rotate() { // TODO @@ -1438,7 +1418,14 @@ void Plater::priv::scale() void Plater::priv::arrange() { - // TODO + // $self->stop_background_process; + + main_frame->app_controller()->arrange_model(); + + // ignore arrange failures on purpose: user has visual feedback and we don't need to warn him + // when parts don't fit in print bed + + update(); } void Plater::priv::split_object() @@ -1574,21 +1561,6 @@ void Plater::priv::on_action_add(SimpleEvent&) load_files(input_paths); } -void Plater::priv::on_action_arrange(SimpleEvent&) -{ - // TODO -} - -void Plater::priv::on_action_more(SimpleEvent&) -{ - // TODO -} - -void Plater::priv::on_action_fewer(SimpleEvent&) -{ - // TODO -} - void Plater::priv::on_action_split(SimpleEvent&) { // TODO @@ -1717,6 +1689,8 @@ Plater::~Plater() Sidebar& Plater::sidebar() { return *p->sidebar; } Model& Plater::model() { return p->model; } +void Plater::load_files(const std::vector &input_files) { p->load_files(input_files); } + void Plater::update(bool force_autocenter) { p->update(force_autocenter); } void Plater::remove(size_t obj_idx) { p->remove(obj_idx); } @@ -1728,7 +1702,69 @@ void Plater::remove_selected() } } -void Plater::load_files(const std::vector &input_files) { p->load_files(input_files); } +void Plater::increase(size_t num) +{ + const auto obj_idx = p->selected_object(); + if (! obj_idx) { return; } + + auto *model_object = p->model.objects[*obj_idx]; + auto *model_instance = model_object->instances[model_object->instances.size() - 1]; + + // $self->stop_background_process; + + float offset = 10.0; + for (size_t i = 0; i < num; i++, offset += 10.0) { + Vec3d offset_vec = model_instance->get_offset() + Vec3d(offset, offset, 0.0); + auto *new_instance = model_object->add_instance(offset_vec, model_instance->get_scaling_factor(), model_instance->get_rotation()); + p->print.get_object(*obj_idx)->add_copy(Slic3r::to_2d(offset_vec)); + } + + sidebar().obj_list()->set_object_count(*obj_idx, model_object->instances.size()); + + if (p->get_config("autocenter") == "1") { + p->arrange(); + } else { + p->update(); + } + + p->selection_changed(); + + // $self->schedule_background_process; +} + +void Plater::decrease(size_t num) +{ + const auto obj_idx = p->selected_object(); + if (! obj_idx) { return; } + + auto *model_object = p->model.objects[*obj_idx]; + if (model_object->instances.size() > num) { + for (size_t i = 0; i < num; i++) { + model_object->delete_last_instance(); + p->print.get_object(*obj_idx)->delete_last_copy(); + } + sidebar().obj_list()->set_object_count(*obj_idx, model_object->instances.size()); + } else { + remove(*obj_idx); + } + + p->update(); +} + +void Plater::set_number_of_copies(size_t num) +{ + const auto obj_idx = p->selected_object(); + if (! obj_idx) { return; } + + auto *model_object = p->model.objects[*obj_idx]; + + auto diff = (ptrdiff_t)num - (ptrdiff_t)model_object->instances.size(); + if (diff > 0) { + increase(diff); + } else if (diff < 0) { + decrease(-diff); + } +} fs::path Plater::export_gcode(const fs::path &output_path) { diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index fd3c4e455d..f8f24e2bc8 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -93,11 +93,14 @@ public: Sidebar& sidebar(); Model& model(); + void load_files(const std::vector &input_files); + void update(bool force_autocenter = false); void remove(size_t obj_idx); void remove_selected(); - - void load_files(const std::vector &input_files); + void increase(size_t num = 1); + void decrease(size_t num = 1); + void set_number_of_copies(size_t num); // Note: empty path means "use the default" boost::filesystem::path export_gcode(const boost::filesystem::path &output_path = boost::filesystem::path()); From 20e1087d977c315f02de26afb099a412b89ed1a0 Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Thu, 11 Oct 2018 13:22:36 +0200 Subject: [PATCH 088/186] Plater: Fix arrange --- src/slic3r/GUI/MainFrame.cpp | 6 +++--- src/slic3r/GUI/Plater.cpp | 7 ++++--- src/slic3r/GUI/Plater.hpp | 4 +++- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index ecd1ddea29..505a451258 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -58,9 +58,9 @@ wxFrame(NULL, wxID_ANY, SLIC3R_BUILD, wxDefaultPosition, wxDefaultSize, wxDEFAUL SLIC3R_VERSION + _(L(" - Remember to check for updates at http://github.com/prusa3d/slic3r/releases"))); - // m_appController->set_model(m_plater->model); - // m_appController->set_print(m_plater->print); - // m_plater->appController = m_appController; + m_appController->set_model(&m_plater->model()); + m_appController->set_print(&m_plater->print()); + GUI::set_gui_appctl(); // Make the global status bar and its progress indicator available in C++ diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index f2d42806c7..4944ac6c69 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1156,8 +1156,8 @@ std::vector Plater::priv::load_model_objects(const ModelObjectPtrs &mode update(); _3DScene::zoom_to_volumes(canvas3D); - // TODO - // $self->object_list_changed; + object_list_changed(); + // $self->schedule_background_process; return obj_idxs; @@ -1687,7 +1687,8 @@ Plater::~Plater() } Sidebar& Plater::sidebar() { return *p->sidebar; } -Model& Plater::model() { return p->model; } +Model& Plater::model() { return p->model; } +Print& Plater::print() { return p->print; } void Plater::load_files(const std::vector &input_files) { p->load_files(input_files); } diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index f8f24e2bc8..ac641e6b1e 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -16,6 +16,7 @@ class wxBoxSizer; namespace Slic3r { class Model; +class Print; namespace GUI { @@ -91,7 +92,8 @@ public: ~Plater(); Sidebar& sidebar(); - Model& model(); + Model& model(); + Print& print(); void load_files(const std::vector &input_files); From 9cf80581d9de0d5a446be84c6a002c1706113bc7 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Thu, 11 Oct 2018 15:57:09 +0200 Subject: [PATCH 089/186] Added extended selection ObjectList -> to canvas3D --- src/slic3r/GUI/GUI_App.cpp | 5 + src/slic3r/GUI/GUI_App.hpp | 1 + src/slic3r/GUI/GUI_ObjectList.cpp | 192 ++++++++++++++++++++++-------- src/slic3r/GUI/GUI_ObjectList.hpp | 18 ++- src/slic3r/GUI/Plater.cpp | 10 +- src/slic3r/GUI/Plater.hpp | 3 + src/slic3r/GUI/wxExtensions.cpp | 3 + 7 files changed, 179 insertions(+), 53 deletions(-) diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 775114654c..a01825d2b9 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -697,6 +697,11 @@ Plater* GUI_App::plater() return mainframe->m_plater; } +wxGLCanvas* GUI_App::canvas3D() +{ + return mainframe->m_plater->canvas3D(); +} + ModelObjectPtrs* GUI_App::model_objects() { return &mainframe->m_plater->model().objects; diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 55254ffd58..4578f4c00c 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -142,6 +142,7 @@ public: ObjectManipulation* obj_manipul(); ObjectList* obj_list(); Plater* plater(); + wxGLCanvas* canvas3D(); std::vector *model_objects(); AppConfig* app_config{ nullptr }; diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 0ee8f204b3..24818c4f43 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -8,6 +8,7 @@ #include "wxExtensions.hpp" #include "Model.hpp" #include "LambdaObjectDialog.hpp" +#include "GLCanvas3D.hpp" #include #include "slic3r/Utils/FixModelByWin10.hpp" @@ -40,17 +41,17 @@ ObjectList::ObjectList(wxWindow* parent) : // describe control behavior Bind(wxEVT_DATAVIEW_SELECTION_CHANGED, [this](wxEvent& event) { - object_ctrl_selection_changed(); + selection_changed(); #ifndef __WXMSW__ set_tooltip_for_item(get_mouse_position_in_control()); #endif //__WXMSW__ }); Bind(wxEVT_DATAVIEW_ITEM_CONTEXT_MENU, [this](wxDataViewEvent& event) { - object_ctrl_context_menu(); + context_menu(); }); - Bind(wxEVT_CHAR, [this](wxKeyEvent& event) { object_ctrl_key_event(event); }); // doesn't work on OSX + Bind(wxEVT_CHAR, [this](wxKeyEvent& event) { key_event(event); }); // doesn't work on OSX #ifdef __WXMSW__ // Extruder value changed @@ -62,7 +63,7 @@ ObjectList::ObjectList(wxWindow* parent) : }); #else // equivalent to wxEVT_CHOICE on __WXMSW__ - Bind(wxEVT_DATAVIEW_ITEM_VALUE_CHANGED, [this](wxDataViewEvent& e) { object_ctrl_item_value_change(e); }); + Bind(wxEVT_DATAVIEW_ITEM_VALUE_CHANGED, [this](wxDataViewEvent& e) { item_value_change(e); }); #endif //__WXMSW__ Bind(wxEVT_DATAVIEW_ITEM_BEGIN_DRAG, [this](wxDataViewEvent& e) {on_begin_drag(e); }); @@ -218,33 +219,23 @@ void ObjectList::init_icons(){ } -void ObjectList::object_ctrl_selection_changed() +void ObjectList::selection_changed() { if (m_prevent_list_events) return; + fix_multiselection_conflicts(); + + // update object selection on Plater + update_selections_on_canvas(); + part_selection_changed(); -// #ys_FIXME_events -// call function to update object selection on Plater -// using obj_idx and vol_idx values - int obj_idx, vol_idx = -1; - obj_idx = m_selected_object_id; - - const wxDataViewItem item = GetSelection(); - if (!item || m_objects_model->GetParent(item) == wxDataViewItem(0)) - vol_idx = -1; - else { - vol_idx = m_objects_model->GetVolumeIdByItem(item); - if (vol_idx == -2) // is settings item - vol_idx = m_objects_model->GetVolumeIdByItem(m_objects_model->GetParent(item)); - } - #ifdef __WXOSX__ update_extruder_in_config(m_selected_extruder); #endif //__WXOSX__ } -void ObjectList::object_ctrl_context_menu() +void ObjectList::context_menu() { wxDataViewItem item; wxDataViewColumn* col; @@ -293,7 +284,7 @@ void ObjectList::show_context_menu() } -void ObjectList::object_ctrl_key_event(wxKeyEvent& event) +void ObjectList::key_event(wxKeyEvent& event) { if (event.GetKeyCode() == WXK_TAB) Navigate(event.ShiftDown() ? wxNavigationKeyEvent::IsBackward : wxNavigationKeyEvent::IsForward); @@ -309,7 +300,7 @@ void ObjectList::object_ctrl_key_event(wxKeyEvent& event) event.Skip(); } -void ObjectList::object_ctrl_item_value_change(wxDataViewEvent& event) +void ObjectList::item_value_change(wxDataViewEvent& event) { if (event.GetColumn() == 2) { @@ -383,19 +374,19 @@ void ObjectList::on_drop(wxDataViewEvent &event) if (to_volume_id > from_volume_id) to_volume_id--; #endif // __WXGTK__ - Select(m_objects_model->ReorganizeChildren(from_volume_id, to_volume_id, - m_objects_model->GetParent(item))); - auto& volumes = (*m_objects)[m_selected_object_id]->volumes; auto delta = to_volume_id < from_volume_id ? -1 : 1; int cnt = 0; for (int id = from_volume_id; cnt < abs(from_volume_id - to_volume_id); id += delta, cnt++) std::swap(volumes[id], volumes[id + delta]); + select_item(m_objects_model->ReorganizeChildren(from_volume_id, to_volume_id, + m_objects_model->GetParent(item))); + m_parts_changed = true; parts_changed(m_selected_object_id); - m_prevent_list_events = false; +// m_prevent_list_events = false; } @@ -494,10 +485,10 @@ void ObjectList::get_settings_choice(wxMenu *menu, int id, bool is_part) const auto item = GetSelection(); if (item) { const auto settings_item = m_objects_model->HasSettings(item); - Select(settings_item ? settings_item : + select_item(settings_item ? settings_item : m_objects_model->AddSettingsChild(item)); #ifndef __WXOSX__ - part_selection_changed(); +// part_selection_changed(); #endif //no __WXOSX__ } else @@ -663,11 +654,16 @@ void ObjectList::load_subobject(bool is_modifier /*= false*/, bool is_lambda/* = parts_changed(obj_idx); - for (int i = 0; i < part_names.size(); ++i) - Select(m_objects_model->AddChild(item, part_names.Item(i), - is_modifier ? m_icon_modifiermesh : m_icon_solidmesh)); + for (int i = 0; i < part_names.size(); ++i) { + const wxDataViewItem sel_item = m_objects_model->AddChild(item, part_names.Item(i), + is_modifier ? m_icon_modifiermesh : m_icon_solidmesh); + + if (i == part_names.size() - 1) + select_item(sel_item); + } + #ifndef __WXOSX__ //#ifdef __WXMSW__ // #ys_FIXME - object_ctrl_selection_changed(); +// selection_changed(); #endif //no __WXOSX__//__WXMSW__ } @@ -809,10 +805,10 @@ void ObjectList::load_lambda(const std::string& type_name) m_parts_changed = true; parts_changed(m_selected_object_id); - Select(m_objects_model->AddChild(GetSelection(), + select_item(m_objects_model->AddChild(GetSelection(), name, m_icon_modifiermesh)); #ifndef __WXOSX__ //#ifdef __WXMSW__ // #ys_FIXME - object_ctrl_selection_changed(); + selection_changed(); #endif //no __WXOSX__ //__WXMSW__ } @@ -821,7 +817,7 @@ void ObjectList::load_lambda(const std::string& type_name) void ObjectList::del_subobject() { - auto item = GetSelection(); + auto item = GetSelection(); // #ys_FIXME_to_multi_sel if (!item) return; const auto volume_id = m_objects_model->GetVolumeIdByItem(item); @@ -833,8 +829,7 @@ void ObjectList::del_subobject() else if (!del_subobject_from_object(volume_id)) return; - Select(m_objects_model->Delete(item)); - part_selection_changed(); + select_item(m_objects_model->Delete(item)); } void ObjectList::del_settings_from_config() @@ -1019,13 +1014,12 @@ void ObjectList::part_selection_changed() void ObjectList::update_manipulation_sizer(const bool is_simple_mode) { - auto item = GetSelection(); + auto item = GetSelection(); /// #ys_FIXME_to_multi_sel if (!item || !is_simple_mode) return; if (m_objects_model->IsSettingsItem(item)) { - Select(m_objects_model->GetParent(item)); - part_selection_changed(); + select_item(m_objects_model->GetParent(item)); } } @@ -1035,7 +1029,7 @@ void ObjectList::add_object_to_list(size_t obj_idx) wxString item_name = model_object->name; auto item = m_objects_model->Add(item_name, model_object->instances.size()); #if !ENABLE_EXTENDED_SELECTION - Select(item); + /*Select*/select_item(item); #endif // !ENABLE_EXTENDED_SELECTION // Add error icon if detected auto-repaire @@ -1060,7 +1054,7 @@ void ObjectList::add_object_to_list(size_t obj_idx) } #ifndef __WXOSX__ - object_ctrl_selection_changed(); + selection_changed(); #endif //__WXMSW__ } @@ -1124,13 +1118,12 @@ void ObjectList::select_current_volume(int idx, int vol_idx) void ObjectList::remove() { - auto item = GetSelection(); + auto item = GetSelection(); // #ys_FIXME_to_multi_sel if (!item) return; if (m_objects_model->GetParent(item) == wxDataViewItem(0)) { -// #ys_FIXME_events -// call function to remove object from model and to update scene + wxGetApp().plater()->remove_selected(); // #ys_TESTME } else del_subobject(); @@ -1143,9 +1136,114 @@ void ObjectList::init_objects() bool ObjectList::multiple_selection() const { + return GetSelectedItemsCount() > 1; +} + +void ObjectList::update_selections() +{ +#if ENABLE_EXTENDED_SELECTION + auto& selection = _3DScene::get_canvas(wxGetApp().canvas3D())->get_selection(); + wxDataViewItemArray sels; + + for (auto idx: selection.get_volume_idxs()) + { + const auto gl_vol = selection.get_volume(idx); + sels.Add(m_objects_model->GetItemByVolumeId(gl_vol->object_idx(), gl_vol->volume_idx())); + } + select_items(sels); + +#endif // ENABLE_EXTENDED_SELECTION +} + +void ObjectList::update_selections_on_canvas() +{ +#if ENABLE_EXTENDED_SELECTION + auto& selection = _3DScene::get_canvas(wxGetApp().canvas3D())->get_selection(); + + const int sel_cnt = GetSelectedItemsCount(); + if (sel_cnt == 0) { + selection.clear(); + _3DScene::render(wxGetApp().canvas3D()); + return; + } + + auto add_to_selection = [this](wxDataViewItem& item, GLCanvas3D::Selection& selection, bool as_single_selection) + { + if (m_objects_model->GetParent(item) == wxDataViewItem(0)){ + selection.add_object(m_objects_model->GetIdByItem(item), as_single_selection); + return; + } + + auto parent = m_objects_model->GetParent(item); + const int obj_idx = m_objects_model->GetIdByItem(parent); + const int vol_idx = m_objects_model->GetVolumeIdByItem(item); + selection.add_volume(obj_idx, vol_idx, as_single_selection); + }; + + if (sel_cnt == 1) { + wxDataViewItem item = GetSelection(); + if (m_objects_model->IsSettingsItem(item)) + selection.clear(); + else + add_to_selection(item, selection, true); + + _3DScene::render(wxGetApp().canvas3D()); + return; + } + wxDataViewItemArray sels; GetSelections(sels); - return sels.size() > 1; + + selection.clear(); + for (auto item: sels) + add_to_selection(item, selection, false); + + _3DScene::render(wxGetApp().canvas3D()); + +#endif // ENABLE_EXTENDED_SELECTION +} + +void ObjectList::select_item(const wxDataViewItem& item) +{ + m_prevent_list_events = true; + + UnselectAll(); + Select(item); + part_selection_changed(); + + m_prevent_list_events = false; +} + +void ObjectList::select_items(const wxDataViewItemArray& sels) +{ + m_prevent_list_events = true; + + UnselectAll(); + SetSelections(sels); + part_selection_changed(); + + m_prevent_list_events = false; +} + +void ObjectList::fix_multiselection_conflicts() +{ + const int sel_cnt = GetSelectedItemsCount(); + if (sel_cnt <= 1) + return; + + m_prevent_list_events = true; + + wxDataViewItemArray sels; + GetSelections(sels); + + for (auto item : sels) { + if (m_objects_model->IsSettingsItem(item)) + Unselect(item); + if (m_objects_model->GetParent(item) != wxDataViewItem(0)) + Unselect(m_objects_model->GetParent(item)); + } + + m_prevent_list_events = false; } } //namespace GUI diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index 948a4a74b2..6a9ef96ad0 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -63,11 +63,11 @@ public: void set_tooltip_for_item(const wxPoint& pt); - void object_ctrl_selection_changed(); - void object_ctrl_context_menu(); + void selection_changed(); + void context_menu(); void show_context_menu(); - void object_ctrl_key_event(wxKeyEvent& event); - void object_ctrl_item_value_change(wxDataViewEvent& event); + void key_event(wxKeyEvent& event); + void item_value_change(wxDataViewEvent& event); void on_begin_drag(wxDataViewEvent &event); void on_drop_possible(wxDataViewEvent &event); @@ -111,18 +111,26 @@ public: void delete_all_objects_from_list(); // Set count of object on c++ side void set_object_count(int idx, int count); + + // #ys_FIXME_to_delete // Unselect all objects in the list on c++ side void unselect_objects(); // Select current object in the list on c++ side void select_current_object(int idx); // Select current volume in the list on c++ side void select_current_volume(int idx, int vol_idx); + // Remove objects/sub-object from the list void remove(); void init_objects(); - bool multiple_selection() const ; + void update_selections(); + void update_selections_on_canvas(); + void select_item(const wxDataViewItem& item); + void select_items(const wxDataViewItemArray& sels); + // correct current selections to avoid of the possible conflicts + void fix_multiselection_conflicts(); }; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 3af670d59a..f130ef449e 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1626,6 +1626,9 @@ void Plater::priv::on_object_select(ObjectSelectEvent &evt) select_object(obj_idx); item_changed_selection(); } +#if ENABLE_EXTENDED_SELECTION + wxGetApp().obj_list()->update_selections(); +#endif // ENABLE_EXTENDED_SELECTION } void Plater::priv::on_viewport_changed(SimpleEvent& evt) @@ -1875,6 +1878,11 @@ void Plater::on_config_change(DynamicPrintConfig* config) // TODO } +wxGLCanvas* Plater::canvas3D() +{ + return p->canvas3D; +} + void Plater::changed_object_settings(int obj_idx) { if (obj_idx < 0) @@ -1899,8 +1907,8 @@ void Plater::changed_object_settings(int obj_idx) if (p->canvas3D) _3DScene::reload_scene(p->canvas3D, true); auto selections = p->collect_selections(); _3DScene::set_objects_selections(p->canvas3D, selections); - _3DScene::reload_scene(p->canvas3D, false); #endif // !ENABLE_EXTENDED_SELECTION + _3DScene::reload_scene(p->canvas3D, false); } else { // schedule_background_process(); diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index fd3c4e455d..bcc295043e 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -12,6 +12,7 @@ class wxButton; class wxBoxSizer; +class wxGLCanvas; namespace Slic3r { @@ -110,6 +111,8 @@ public: void on_extruders_change(int extruders_count); void on_config_change(DynamicPrintConfig* config); + + wxGLCanvas* canvas3D(); private: struct priv; std::unique_ptr p; diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp index bae1055b80..c91d894bb0 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -592,6 +592,9 @@ wxDataViewItem PrusaObjectDataViewModel::GetItemByVolumeId(int obj_idx, int volu auto parent = m_objects[obj_idx]; if (parent->GetChildCount() == 0) { + if (volume_idx == 0) + return GetItemById(obj_idx); + printf("Error! Object has no one volume.\n"); return wxDataViewItem(0); } From aa0c3bf2e3082295bd58b3d2712a3a8594f69afe Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Fri, 12 Oct 2018 10:09:16 +0200 Subject: [PATCH 090/186] Added helper functions to generate 3d transforms --- src/libslic3r/Geometry.cpp | 17 +++++++++++++++++ src/libslic3r/Geometry.hpp | 15 +++++++++++++++ src/libslic3r/Model.cpp | 22 +++++++--------------- src/slic3r/GUI/3DScene.cpp | 9 +++------ src/slic3r/GUI/GLCanvas3D.cpp | 16 ++++------------ 5 files changed, 46 insertions(+), 33 deletions(-) diff --git a/src/libslic3r/Geometry.cpp b/src/libslic3r/Geometry.cpp index 87b4e223d4..5d7b936795 100644 --- a/src/libslic3r/Geometry.cpp +++ b/src/libslic3r/Geometry.cpp @@ -1166,4 +1166,21 @@ MedialAxis::retrieve_endpoint(const VD::cell_type* cell) const } } +void assemble_transform(Transform3d& transform, const Vec3d& translation, const Vec3d& rotation, const Vec3d& scale) +{ + transform = Transform3d::Identity(); + transform.translate(translation); + transform.rotate(Eigen::AngleAxisd(rotation(2), Vec3d::UnitZ())); + transform.rotate(Eigen::AngleAxisd(rotation(1), Vec3d::UnitY())); + transform.rotate(Eigen::AngleAxisd(rotation(0), Vec3d::UnitX())); + transform.scale(scale); +} + +Transform3d assemble_transform(const Vec3d& translation, const Vec3d& rotation, const Vec3d& scale) +{ + Transform3d transform; + assemble_transform(transform, translation, rotation, scale); + return transform; +} + } } diff --git a/src/libslic3r/Geometry.hpp b/src/libslic3r/Geometry.hpp index 3698b996fd..57b9cad02f 100644 --- a/src/libslic3r/Geometry.hpp +++ b/src/libslic3r/Geometry.hpp @@ -157,6 +157,21 @@ class MedialAxis { const Point& retrieve_endpoint(const VD::cell_type* cell) const; }; +// Sets the given transform by assembling the given transformations in the following order: +// 1) scale +// 2) rotate X +// 3) rotate Y +// 4) rotate Z +// 5) translate +void assemble_transform(Transform3d& transform, const Vec3d& translation = Vec3d::Zero(), const Vec3d& rotation = Vec3d::Zero(), const Vec3d& scale = Vec3d::Ones()); + +// Returns the transform obtained by assembling the given transformations in the following order: +// 1) scale +// 2) rotate X +// 3) rotate Y +// 4) rotate Z +// 5) translate +Transform3d assemble_transform(const Vec3d& translation = Vec3d::Zero(), const Vec3d& rotation = Vec3d::Zero(), const Vec3d& scale = Vec3d::Ones()); } } #endif diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index e0cf14a57d..8ced1018db 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -1185,22 +1185,14 @@ void ModelInstance::transform_polygon(Polygon* polygon) const Transform3d ModelInstance::world_matrix(bool dont_translate, bool dont_rotate, bool dont_scale) const { +#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM + Vec3d translation = dont_translate ? Vec3d::Zero() : m_offset; + Vec3d rotation = dont_rotate ? Vec3d::Zero() : m_rotation; + Vec3d scale = dont_scale ? Vec3d::Ones() : m_scaling_factor; + return Geometry::assemble_transform(translation, rotation, scale); +#else Transform3d m = Transform3d::Identity(); -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - if (!dont_translate) - m.translate(m_offset); - - if (!dont_rotate) - { - m.rotate(Eigen::AngleAxisd(m_rotation(2), Vec3d::UnitZ())); - m.rotate(Eigen::AngleAxisd(m_rotation(1), Vec3d::UnitY())); - m.rotate(Eigen::AngleAxisd(m_rotation(0), Vec3d::UnitX())); - } - - if (!dont_scale) - m.scale(m_scaling_factor); -#else if (!dont_translate) m.translate(Vec3d(offset(0), offset(1), 0.0)); @@ -1209,9 +1201,9 @@ Transform3d ModelInstance::world_matrix(bool dont_translate, bool dont_rotate, b if (!dont_scale) m.scale(scaling_factor); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM return m; +#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM } } diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index 92e9039115..07f9b0fda4 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -389,14 +389,11 @@ const Transform3f& GLVolume::world_matrix() const { if (m_world_matrix_dirty) { +#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM + m_world_matrix = Geometry::assemble_transform(m_offset, m_rotation, m_scaling_factor).cast(); +#else m_world_matrix = Transform3f::Identity(); m_world_matrix.translate(m_offset.cast()); -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - m_world_matrix.rotate(Eigen::AngleAxisf((float)m_rotation(2), Vec3f::UnitZ())); - m_world_matrix.rotate(Eigen::AngleAxisf((float)m_rotation(1), Vec3f::UnitY())); - m_world_matrix.rotate(Eigen::AngleAxisf((float)m_rotation(0), Vec3f::UnitX())); - m_world_matrix.scale(m_scaling_factor.cast()); -#else m_world_matrix.rotate(Eigen::AngleAxisf((float)m_rotation, Vec3f::UnitZ())); m_world_matrix.scale((float)m_scaling_factor); #endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index a2067bbf3e..0925488704 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -10,6 +10,7 @@ #include "../../libslic3r/ClipperUtils.hpp" #include "../../libslic3r/PrintConfig.hpp" #include "../../libslic3r/GCode/PreviewData.hpp" +#include "../../libslic3r/Geometry.hpp" #include "GUI_App.hpp" #include "GUI_ObjectList.hpp" #include "GUI_ObjectManipulation.hpp" @@ -1144,17 +1145,14 @@ GLCanvas3D::Selection::VolumeCache::VolumeCache(const Vec3d& position, const Vec , m_rotation(rotation) , m_scaling_factor(scaling_factor) { - m_rotation_matrix = Transform3d::Identity(); - m_rotation_matrix.rotate(Eigen::AngleAxisd(m_rotation(2), Vec3d::UnitZ())); - m_rotation_matrix.rotate(Eigen::AngleAxisd(m_rotation(1), Vec3d::UnitY())); - m_rotation_matrix.rotate(Eigen::AngleAxisd(m_rotation(0), Vec3d::UnitX())); + m_rotation_matrix = Geometry::assemble_transform(Vec3d::Zero(), m_rotation); } GLCanvas3D::Selection::Selection() : m_volumes(nullptr) , m_model(nullptr) , m_mode(Instance) - , m_type(Invalid) + , m_type(Empty) , m_valid(false) , m_bounding_box_dirty(true) { @@ -1409,13 +1407,7 @@ void GLCanvas3D::Selection::rotate(const Vec3d& rotation) if (!m_valid) return; - Transform3d m = Transform3d::Identity(); - if (rotation(2) != 0.0f) - m.rotate(Eigen::AngleAxisd(rotation(2), Vec3d::UnitZ())); - else if (rotation(1) != 0.0f) - m.rotate(Eigen::AngleAxisd(rotation(1), Vec3d::UnitY())); - else if (rotation(0) != 0.0f) - m.rotate(Eigen::AngleAxisd(rotation(0), Vec3d::UnitX())); + Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), rotation); bool single_full_instance = is_single_full_instance(); From d843f1a76fe753d7ffdc6c53ed06f46a015d7139 Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Thu, 11 Oct 2018 15:19:53 +0200 Subject: [PATCH 091/186] Fix resources dir location, add wxWidgets to Windows deps build script --- CMakeLists.txt | 26 ++++++++++++++-- doc/deps-build/windows/slic3r-makedeps.ps1 | 32 ++++++++++++++++++-- resources/localization/CMakeLists.txt | 8 ----- src/slic3r.cpp | 35 +++++++++------------- 4 files changed, 67 insertions(+), 34 deletions(-) delete mode 100644 resources/localization/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 6f4e89283b..b0f908e906 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,6 +3,7 @@ cmake_minimum_required(VERSION 3.2) include("version.inc") set(SLIC3R_RESOURCES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/resources") +file(TO_NATIVE_PATH "${SLIC3R_RESOURCES_DIR}" SLIC3R_RESOURCES_DIR_WIN) if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) message(STATUS "No build type selected, default to Release") @@ -214,8 +215,29 @@ if (NOT GLEW_FOUND) endif () include_directories(${GLEW_INCLUDE_DIRS}) -# l10n -add_subdirectory(resources/localization) +# Resources and l10n +set(L10N_DIR "${SLIC3R_RESOURCES_DIR}/localization") +add_custom_target(pot + # FIXME: file list stale + COMMAND xgettext --keyword=L --from-code=UTF-8 --debug + -f "${L10N_DIR}/list.txt" + -o "${L10N_DIR}/Slic3rPE.pot" + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} + COMMENT "Generate pot file from strings in the source tree" +) +if (MSVC) + file(TO_NATIVE_PATH "${CMAKE_BINARY_DIR}/src/resources" WIN_RESOURCES_SYMLINK) + add_custom_target(resources_symlink ALL + COMMAND if not exist "${WIN_RESOURCES_SYMLINK}" ( mklink /J "${WIN_RESOURCES_SYMLINK}" "${SLIC3R_RESOURCES_DIR_WIN}" ) + VERBATIM + ) +else () + add_custom_target(resources_symlink ALL + COMMAND ln -sf "${SLIC3R_RESOURCES_DIR}" "${CMAKE_BINARY_DIR}/resources" + VERBATIM + ) +endif() + # libslic3r, Slic3r GUI and the slic3r executable. add_subdirectory(src) diff --git a/doc/deps-build/windows/slic3r-makedeps.ps1 b/doc/deps-build/windows/slic3r-makedeps.ps1 index e256d61e42..228244d0b4 100644 --- a/doc/deps-build/windows/slic3r-makedeps.ps1 +++ b/doc/deps-build/windows/slic3r-makedeps.ps1 @@ -40,6 +40,8 @@ $BOOST = 'boost_1_63_0' $CURL = 'curl-7.58.0' $TBB_SHA = 'a0dc9bf76d0120f917b641ed095360448cabc85b' $TBB = "tbb-$TBB_SHA" +$WXWIDGETS_VER = "3.1.1" +$WXWIDGETS = "wxWidgets-$WXWIDGETS_VER" try @@ -72,13 +74,21 @@ echo 'Downloading sources ...' if (!(Test-Path "$BOOST.zip")) { $webclient.DownloadFile("https://dl.bintray.com/boostorg/release/1.63.0/source/$BOOST.zip", "$BOOST.zip") } if (!(Test-Path "$TBB.zip")) { $webclient.DownloadFile("https://github.com/wjakob/tbb/archive/$TBB_SHA.zip", "$TBB.zip") } if (!(Test-Path "$CURL.zip")) { $webclient.DownloadFile("https://curl.haxx.se/download/$CURL.zip", ".\$CURL.zip") } +if (!(Test-Path "$WXWIDGETS.zip")) { $webclient.DownloadFile("https://github.com/wxWidgets/wxWidgets/releases/download/v$WXWIDGETS_VER/$WXWIDGETS.zip", ".\$WXWIDGETS.zip") } # Unpack sources: echo 'Unpacking ...' -if (!(Test-Path $BOOST)) { [IO.Compression.ZipFile]::ExtractToDirectory("$BOOST.zip", '.') } -if (!(Test-Path $TBB)) { [IO.Compression.ZipFile]::ExtractToDirectory("$TBB.zip", '.') } -if (!(Test-Path $CURL)) { [IO.Compression.ZipFile]::ExtractToDirectory("$CURL.zip", '.') } +if (!(Test-Path "$BOOST")) { [IO.Compression.ZipFile]::ExtractToDirectory("$BOOST.zip", '.') } +if (!(Test-Path "$TBB")) { [IO.Compression.ZipFile]::ExtractToDirectory("$TBB.zip", '.') } +if (!(Test-Path "$CURL")) { [IO.Compression.ZipFile]::ExtractToDirectory("$CURL.zip", '.') } +if (!(Test-Path "$WXWIDGETS")) { [IO.Compression.ZipFile]::ExtractToDirectory("$WXWIDGETS.zip", "$WXWIDGETS") } + + +# Patch PNG in wxWidgets +# PNG prefix is not applied properly to two functions +$pngprefix_h = "$WXWIDGETS\src\png\pngprefix.h" +"#define png_write_eXIf wx_png_write_eXIf`n#define png_handle_eXIf wx_png_handle_eXIf`n`n" + (Get-Content $pngprefix_h | Out-String) | Set-Content $pngprefix_h # Build libraries: @@ -127,6 +137,22 @@ Copy-Item -R -Force ..\builds\libcurl-*-winssl\include\* "$destdir\usr\local\inc Copy-Item -R -Force ..\builds\libcurl-*-winssl\lib\* "$destdir\usr\local\lib\" popd +# Build wxWidgets +pushd "$WXWIDGETS" +pushd "build\msw" +$target_cpu_opt = ("", "TARGET_CPU=X64")[!$b32] +$lib_dir = ("vc_lib", "vc_x64_lib")[!$b32] +nmake /f makefile.vc ` + BUILD=release ` + SHARED=0 ` + UNICODE=1 ` + USE_GUI=1 ` + "$target_cpu_opt" +popd +Copy-Item -R -Force include\* "$destdir\usr\local\include\" +Copy-Item -R -Force "lib\$lib_dir" "$destdir\usr\local\lib\" +popd + echo "" echo "All done!" diff --git a/resources/localization/CMakeLists.txt b/resources/localization/CMakeLists.txt deleted file mode 100644 index 8a7fba068f..0000000000 --- a/resources/localization/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -set(L10N_DIR "${PROJECT_SOURCE_DIR}/resources/localization") -add_custom_target(pot - COMMAND xgettext --keyword=L --from-code=UTF-8 --debug - -f "${L10N_DIR}/list.txt" - -o "${L10N_DIR}/Slic3rPE.pot" - WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} - COMMENT "Generate pot file from strings in the source tree" -) diff --git a/src/slic3r.cpp b/src/slic3r.cpp index 296d994147..03e337db56 100644 --- a/src/slic3r.cpp +++ b/src/slic3r.cpp @@ -70,31 +70,24 @@ int main(int argc, char **argv) } boost::filesystem::path path_to_binary = boost::filesystem::system_complete(argv[0]); - boost::filesystem::path path_resources = path_to_binary.parent_path(); + // Path from the Slic3r binary to its resources. - path_resources /= (path_to_binary.stem().string() == "slic3r-gui") ? - // Running from the build directory: -// "../../resources" : // ? #ys_FIXME - "../../../resources" : // ! #ys_FIXME - // Running from an installation directory: #ifdef __APPLE__ - // The application is packed in the .dmg archive as 'Slic3r.app/Contents/MacOS/Slic3r' - // The resources are packed to 'Slic3r.app/Contents/Resources' - "../Resources" + // The application is packed in the .dmg archive as 'Slic3r.app/Contents/MacOS/Slic3r' + // The resources are packed to 'Slic3r.app/Contents/Resources' + boost::filesystem::path path_resources = path_to_binary.parent_path() / "../Resources"; +#elif defined _WIN32 + // The application is packed in the .zip archive in the root, + // The resources are packed to 'resources' + // Path from Slic3r binary to resources: + boost::filesystem::path path_resources = path_to_binary.parent_path() / "resources"; #else - #ifdef _WIN32 - // The application is packed in the .zip archive in the root, - // The resources are packed to 'resources' - // Path from Slic3r binary to resources: - "resources" - #else - // The application is packed in the .tar.bz archive (or in AppImage) as 'bin/slic3r', - // The resources are packed to 'resources' - // Path from Slic3r binary to resources: - "../resources" - #endif + // The application is packed in the .tar.bz archive (or in AppImage) as 'bin/slic3r', + // The resources are packed to 'resources' + // Path from Slic3r binary to resources: + boost::filesystem::path path_resources = path_to_binary.parent_path() / "../resources"; #endif - ; + set_resources_dir(path_resources.string()); set_var_dir((path_resources / "icons").string()); set_local_dir((path_resources / "localization").string()); From b7980f6b9b34d194d5409d8c5c8b188f371b5772 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Fri, 12 Oct 2018 12:00:37 +0200 Subject: [PATCH 092/186] Added correct deleting of the selected objects(parts, mix) but only in "ObjectList->Scene" direction --- src/slic3r/GUI/GUI_ObjectList.cpp | 86 +++++++++++++++-------- src/slic3r/GUI/GUI_ObjectList.hpp | 9 ++- src/slic3r/GUI/GUI_ObjectManipulation.cpp | 2 +- src/slic3r/GUI/Plater.cpp | 9 +-- src/slic3r/GUI/Plater.hpp | 1 - src/slic3r/GUI/wxExtensions.cpp | 20 +++++- src/slic3r/GUI/wxExtensions.hpp | 3 +- 7 files changed, 88 insertions(+), 42 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 24818c4f43..a3d912c457 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -115,7 +115,7 @@ void ObjectList::set_tooltip_for_item(const wxPoint& pt) HitTest(pt, item, col); if (!item) return; - if (col->GetTitle() == " ") + if (col->GetTitle() == " " && GetSelectedItemsCount()<2) GetMainWindow()->SetToolTip(_(L("Right button click the icon to change the object settings"))); else if (col->GetTitle() == _("Name") && m_objects_model->GetIcon(item).GetRefData() == m_icon_manifold_warning.GetRefData()) { @@ -161,6 +161,15 @@ wxPoint ObjectList::get_mouse_position_in_control() { return wxPoint(pt.x - /*win->*/GetScreenPosition().x, pt.y - /*win->*/GetScreenPosition().y); } +int ObjectList::get_selected_obj_idx() const +{ + if (GetSelectedItemsCount() == 1) { + auto item = GetSelection(); + return m_objects_model->GetIdByItem(item); + } + return -1; +} + wxDataViewColumn* ObjectList::create_objects_list_extruder_column(int extruders_count) { wxArrayString choices; @@ -296,6 +305,8 @@ void ObjectList::key_event(wxKeyEvent& event) printf("WXK_BACK\n"); remove(); } + else if (wxGetKeyState(wxKeyCode('A')) && wxGetKeyState(WXK_CONTROL)) + select_all(); else event.Skip(); } @@ -815,21 +826,22 @@ void ObjectList::load_lambda(const std::string& type_name) // Delete subobject -void ObjectList::del_subobject() +void ObjectList::del_subobject_item(wxDataViewItem& item) { - auto item = GetSelection(); // #ys_FIXME_to_multi_sel if (!item) return; - const auto volume_id = m_objects_model->GetVolumeIdByItem(item); - if (volume_id == -1) + int obj_idx, vol_idx; + m_objects_model->GetObjectAndVolumeIdsByItem(item, obj_idx, vol_idx); + + if (vol_idx == -1) return; - if (volume_id == -2) + if (vol_idx == -2) del_settings_from_config(); - else if (!del_subobject_from_object(volume_id)) + else if (!del_subobject_from_object(obj_idx, vol_idx)) return; - select_item(m_objects_model->Delete(item)); + m_objects_model->Delete(item); } void ObjectList::del_settings_from_config() @@ -847,14 +859,13 @@ void ObjectList::del_settings_from_config() m_config->set_key_value("extruder", new ConfigOptionInt(extruder)); } - -bool ObjectList::del_subobject_from_object(const int volume_id) +bool ObjectList::del_subobject_from_object(const int obj_idx, const int vol_idx) { - const auto volume = (*m_objects)[m_selected_object_id]->volumes[volume_id]; + const auto volume = (*m_objects)[obj_idx]->volumes[vol_idx]; // if user is deleting the last solid part, throw error int solid_cnt = 0; - for (auto vol : (*m_objects)[m_selected_object_id]->volumes) + for (auto vol : (*m_objects)[obj_idx]->volumes) if (vol->is_model_part()) ++solid_cnt; if (volume->is_model_part() && solid_cnt == 1) { @@ -862,10 +873,10 @@ bool ObjectList::del_subobject_from_object(const int volume_id) return false; } - (*m_objects)[m_selected_object_id]->delete_volume(volume_id); + (*m_objects)[obj_idx]->delete_volume(vol_idx); m_parts_changed = true; + parts_changed(obj_idx); - parts_changed(m_selected_object_id); return true; } @@ -1061,12 +1072,22 @@ void ObjectList::add_object_to_list(size_t obj_idx) void ObjectList::delete_object_from_list() { auto item = GetSelection(); - if (!item || m_objects_model->GetParent(item) != wxDataViewItem(0)) + if (!item) return; - // Select(m_objects_model->Delete(item)); - m_objects_model->Delete(item); + if (m_objects_model->GetParent(item) == wxDataViewItem(0)) + select_item(m_objects_model->Delete(item)); + else + select_item(m_objects_model->Delete(m_objects_model->GetParent(item))); +} - part_selection_changed(); +void ObjectList::delete_object_from_list(const size_t obj_idx) +{ + select_item(m_objects_model->Delete(m_objects_model->GetItemById(obj_idx))); +} + +void ObjectList::delete_volume_from_list(const size_t obj_idx, const size_t vol_idx) +{ + select_item(m_objects_model->Delete(m_objects_model->GetItemByVolumeId(obj_idx, vol_idx))); } void ObjectList::delete_all_objects_from_list() @@ -1118,15 +1139,19 @@ void ObjectList::select_current_volume(int idx, int vol_idx) void ObjectList::remove() { - auto item = GetSelection(); // #ys_FIXME_to_multi_sel - if (!item) + if (GetSelectedItemsCount() == 0) return; - if (m_objects_model->GetParent(item) == wxDataViewItem(0)) { - wxGetApp().plater()->remove_selected(); // #ys_TESTME + wxDataViewItemArray sels; + GetSelections(sels); + + for (auto& item : sels) + { + if (m_objects_model->GetParent(item) == wxDataViewItem(0)) + wxGetApp().plater()->remove(m_objects_model->GetIdByItem(item)); + else + del_subobject_item(item); } - else - del_subobject(); } void ObjectList::init_objects() @@ -1183,7 +1208,7 @@ void ObjectList::update_selections_on_canvas() if (sel_cnt == 1) { wxDataViewItem item = GetSelection(); if (m_objects_model->IsSettingsItem(item)) - selection.clear(); + add_to_selection(m_objects_model->GetParent(item), selection, true); else add_to_selection(item, selection, true); @@ -1225,10 +1250,15 @@ void ObjectList::select_items(const wxDataViewItemArray& sels) m_prevent_list_events = false; } +void ObjectList::select_all() +{ + SelectAll(); + selection_changed(); +} + void ObjectList::fix_multiselection_conflicts() { - const int sel_cnt = GetSelectedItemsCount(); - if (sel_cnt <= 1) + if (GetSelectedItemsCount() <= 1) return; m_prevent_list_events = true; @@ -1239,7 +1269,7 @@ void ObjectList::fix_multiselection_conflicts() for (auto item : sels) { if (m_objects_model->IsSettingsItem(item)) Unselect(item); - if (m_objects_model->GetParent(item) != wxDataViewItem(0)) + else if (m_objects_model->GetParent(item) != wxDataViewItem(0)) Unselect(m_objects_model->GetParent(item)); } diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index 6a9ef96ad0..21b4a729fb 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -85,16 +85,16 @@ public: void load_part(ModelObject* model_object, wxArrayString& part_names, const bool is_modifier); void load_lambda(ModelObject* model_object, wxArrayString& part_names, const bool is_modifier); void load_lambda(const std::string& type_name); - void del_subobject(); + void del_subobject_item(wxDataViewItem& item); void del_settings_from_config(); - bool del_subobject_from_object(const int volume_id); + bool del_subobject_from_object(const int obj_idx, const int vol_idx); void split(const bool split_part); bool get_volume_by_item(const bool split_part, const wxDataViewItem& item, ModelVolume*& volume); bool is_splittable_object(const bool split_part); wxPoint get_mouse_position_in_control(); wxBoxSizer* get_sizer(){return m_sizer;} - int get_sel_obj_id() const { return m_selected_object_id; } + int get_selected_obj_idx() const; bool is_parts_changed() const { return m_parts_changed; } bool is_part_settings_changed() const{ return m_part_settings_changed; } @@ -107,6 +107,8 @@ public: void add_object_to_list(size_t obj_idx); // Delete object from the list void delete_object_from_list(); + void delete_object_from_list(const size_t obj_idx); + void delete_volume_from_list(const size_t obj_idx, const size_t vol_idx); // Delete all objects from the list void delete_all_objects_from_list(); // Set count of object on c++ side @@ -129,6 +131,7 @@ public: void update_selections_on_canvas(); void select_item(const wxDataViewItem& item); void select_items(const wxDataViewItemArray& sels); + void select_all(); // correct current selections to avoid of the possible conflicts void fix_multiselection_conflicts(); }; diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index 5eb90054c0..9873914132 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -148,7 +148,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent): int ObjectManipulation::ol_selection() { - return wxGetApp().sidebar().get_ol_selection(); + return wxGetApp().obj_list()->get_selected_obj_idx(); } void ObjectManipulation::update_settings_list() diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 72ef476707..57d887cca2 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -614,11 +614,6 @@ void Sidebar::update_objects_list_extruder_column(int extruders_count) p->object_list->update_objects_list_extruder_column(extruders_count); } -int Sidebar::get_ol_selection() -{ - return p->object_list->get_sel_obj_id(); -} - void Sidebar::show_info_sizers(const bool show) { p->object_info->Show(show); @@ -1356,7 +1351,7 @@ void Plater::priv::remove(size_t obj_idx) model.delete_object(obj_idx); print.delete_object(obj_idx); // Delete object from Sidebar list - sidebar->obj_list()->delete_object_from_list(); + sidebar->obj_list()->delete_object_from_list(obj_idx); object_list_changed(); @@ -1931,7 +1926,7 @@ void Plater::changed_object_settings(int obj_idx) if (list->is_parts_changed()) { // recenter and re - align to Z = 0 - auto model_object = p->model.objects[list->get_sel_obj_id()]; + auto model_object = p->model.objects[obj_idx]; model_object->center_around_origin(); } diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index b25b43b7d1..b174f5e211 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -69,7 +69,6 @@ public: ConfigOptionsGroup* og_freq_chng_params(); wxButton* get_wiping_dialog_button(); void update_objects_list_extruder_column(int extruders_count); - int get_ol_selection(); void show_info_sizers(const bool show); void show_buttons(const bool show); void enable_buttons(bool enable); diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp index c91d894bb0..23ad288b8a 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -591,7 +591,8 @@ wxDataViewItem PrusaObjectDataViewModel::GetItemByVolumeId(int obj_idx, int volu } auto parent = m_objects[obj_idx]; - if (parent->GetChildCount() == 0) { + if (parent->GetChildCount() == 0 || + (parent->GetChildCount() == 1 && parent->GetNthChild(0)->m_volume_id == -2)) { if (volume_idx == 0) return GetItemById(obj_idx); @@ -628,6 +629,23 @@ int PrusaObjectDataViewModel::GetVolumeIdByItem(const wxDataViewItem& item) return node->GetVolumeId(); } +void PrusaObjectDataViewModel::GetObjectAndVolumeIdsByItem(const wxDataViewItem& item, int& obj_idx, int& vol_idx) +{ + wxASSERT(item.IsOk()); + obj_idx = vol_idx = -1; + + PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID(); + if (!node) return; + vol_idx = node->GetVolumeId(); + + PrusaObjectDataViewModelNode *parent_node = node->GetParent(); + if (!parent_node) return; + + auto it = find(m_objects.begin(), m_objects.end(), parent_node); + if (it != m_objects.end()) + obj_idx = it - m_objects.begin(); +} + wxString PrusaObjectDataViewModel::GetName(const wxDataViewItem &item) const { PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID(); diff --git a/src/slic3r/GUI/wxExtensions.hpp b/src/slic3r/GUI/wxExtensions.hpp index a6cbf1773b..33315880ff 100644 --- a/src/slic3r/GUI/wxExtensions.hpp +++ b/src/slic3r/GUI/wxExtensions.hpp @@ -422,7 +422,8 @@ public: wxDataViewItem GetItemByVolumeId(int obj_idx, int volume_idx); int GetIdByItem(wxDataViewItem& item); int GetVolumeIdByItem(const wxDataViewItem& item); - bool IsEmpty() { return m_objects.empty(); } + void GetObjectAndVolumeIdsByItem(const wxDataViewItem& item, int& obj_idx, int& vol_idx); + bool IsEmpty() { return m_objects.empty(); } // helper method for wxLog From 9bb93cc4f4675ab0e9b0a5d77d3d19f2fc086848 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Fri, 12 Oct 2018 12:19:57 +0200 Subject: [PATCH 093/186] Added helper functions to extract euler angles from 3d transforms --- src/libslic3r/Format/3mf.cpp | 42 ++++++++++++++--------------------- src/libslic3r/Geometry.cpp | 34 ++++++++++++++++++++++++++++ src/libslic3r/Geometry.hpp | 8 +++++++ src/slic3r/GUI/GLCanvas3D.cpp | 23 ++----------------- 4 files changed, 61 insertions(+), 46 deletions(-) diff --git a/src/libslic3r/Format/3mf.cpp b/src/libslic3r/Format/3mf.cpp index 90817fadc9..4d749eb568 100644 --- a/src/libslic3r/Format/3mf.cpp +++ b/src/libslic3r/Format/3mf.cpp @@ -2,6 +2,7 @@ #include "../Model.hpp" #include "../Utils.hpp" #include "../GCode.hpp" +#include "../Geometry.hpp" #include "3mf.hpp" @@ -1253,7 +1254,7 @@ namespace Slic3r { // translation #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - Vec3d offset(transform(0, 3), transform(1, 3), transform(2, 3)); + Vec3d offset = transform.matrix().block(0, 3, 3, 1); #else double offset_x = transform(0, 3); double offset_y = transform(1, 3); @@ -1261,50 +1262,41 @@ namespace Slic3r { #endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM // scale - double sx = ::sqrt(sqr(transform(0, 0)) + sqr(transform(1, 0)) + sqr(transform(2, 0))); - double sy = ::sqrt(sqr(transform(0, 1)) + sqr(transform(1, 1)) + sqr(transform(2, 1))); - double sz = ::sqrt(sqr(transform(0, 2)) + sqr(transform(1, 2)) + sqr(transform(2, 2))); + Eigen::Matrix m3x3 = transform.matrix().block(0, 0, 3, 3); + Vec3d scale(m3x3.col(0).norm(), m3x3.col(1).norm(), m3x3.col(2).norm()); // invalid scale value, return - if ((sx == 0.0) || (sy == 0.0) || (sz == 0.0)) + if ((scale(0) == 0.0) || (scale(1) == 0.0) || (scale(2) == 0.0)) return; #if !ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM // non-uniform scale value, return - if ((std::abs(sx - sy) > 0.00001) || (std::abs(sx - sz) > 0.00001)) + if ((std::abs(scale(0) - scale(1)) > 0.00001) || (std::abs(scale(0) - scale(2)) > 0.00001)) return; #endif // !ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - double inv_sx = 1.0 / sx; - double inv_sy = 1.0 / sy; - double inv_sz = 1.0 / sz; - - Eigen::Matrix m3x3; - m3x3 << transform(0, 0) * inv_sx, transform(0, 1) * inv_sy, transform(0, 2) * inv_sz, - transform(1, 0) * inv_sx, transform(1, 1) * inv_sy, transform(1, 2) * inv_sz, - transform(2, 0) * inv_sx, transform(2, 1) * inv_sy, transform(2, 2) * inv_sz; + // remove scale + m3x3.col(0).normalize(); + m3x3.col(1).normalize(); + m3x3.col(2).normalize(); #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - Vec3d angles = m3x3.eulerAngles(2, 1, 0); - Vec3d rotation(angles(2), angles(1), angles(0)); + Vec3d rotation = Slic3r::Geometry::extract_euler_angles(m3x3); instance.set_offset(offset); - instance.set_scaling_factor(Vec3d(sx, sy, sz)); + instance.set_scaling_factor(scale); instance.set_rotation(rotation); #else - Eigen::AngleAxisd rotation; - rotation.fromRotationMatrix(m3x3); + Vec3d rotation = Slic3r::Geometry::extract_euler_angles(m3x3); - // invalid rotation axis, we currently handle only rotations around Z axis - if ((rotation.angle() != 0.0) && (rotation.axis() != Vec3d::UnitZ()) && (rotation.axis() != -Vec3d::UnitZ())) + // invalid rotation, we currently handle only rotations around Z axis + if ((rotation(0) != 0.0) || (rotation(1) != 0.0)) return; - double angle_z = (rotation.axis() == Vec3d::UnitZ()) ? rotation.angle() : -rotation.angle(); - instance.offset(0) = offset_x; instance.offset(1) = offset_y; - instance.scaling_factor = sx; - instance.rotation = angle_z; + instance.scaling_factor = scale(0); + instance.rotation = rotation(2); #endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM } diff --git a/src/libslic3r/Geometry.cpp b/src/libslic3r/Geometry.cpp index 5d7b936795..c45f087919 100644 --- a/src/libslic3r/Geometry.cpp +++ b/src/libslic3r/Geometry.cpp @@ -1183,4 +1183,38 @@ Transform3d assemble_transform(const Vec3d& translation, const Vec3d& rotation, return transform; } +Vec3d extract_euler_angles(const Eigen::Matrix& rotation_matrix) +{ + // see: https://www.learnopencv.com/rotation-matrix-to-euler-angles/ + double sy = ::sqrt(sqr(rotation_matrix(0, 0)) + sqr(rotation_matrix(1, 0))); + + Vec3d angles = Vec3d::Zero(); + + if (sy >= 1e-6) + { + angles(0) = ::atan2(rotation_matrix(2, 1), rotation_matrix(2, 2)); + angles(1) = ::atan2(-rotation_matrix(2, 0), sy); + angles(2) = ::atan2(rotation_matrix(1, 0), rotation_matrix(0, 0)); + } + else + { + angles(0) = ::atan2(-rotation_matrix(1, 2), rotation_matrix(1, 1)); + angles(1) = ::atan2(-rotation_matrix(2, 0), sy); + angles(2) = 0.0; + } + + return angles; +} + +Vec3d extract_euler_angles(const Transform3d& transform) +{ + // use only the non-translational part of the transform + Eigen::Matrix m = transform.matrix().block(0, 0, 3, 3); + // remove scale + m.col(0).normalize(); + m.col(1).normalize(); + m.col(2).normalize(); + return extract_euler_angles(m); +} + } } diff --git a/src/libslic3r/Geometry.hpp b/src/libslic3r/Geometry.hpp index 57b9cad02f..35f59bdfd7 100644 --- a/src/libslic3r/Geometry.hpp +++ b/src/libslic3r/Geometry.hpp @@ -172,6 +172,14 @@ void assemble_transform(Transform3d& transform, const Vec3d& translation = Vec3d // 4) rotate Z // 5) translate Transform3d assemble_transform(const Vec3d& translation = Vec3d::Zero(), const Vec3d& rotation = Vec3d::Zero(), const Vec3d& scale = Vec3d::Ones()); + +// Returns the euler angles extracted from the given rotation matrix +// Warning -> The matrix should not contain any scale or shear !!! +Vec3d extract_euler_angles(const Eigen::Matrix& rotation_matrix); + +// Returns the euler angles extracted from the given affine transform +// Warning -> The transform should not contain any shear !!! +Vec3d extract_euler_angles(const Transform3d& transform); } } #endif diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 0925488704..2df47519c5 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1413,33 +1413,14 @@ void GLCanvas3D::Selection::rotate(const Vec3d& rotation) for (unsigned int i : m_list) { - Vec3d radius = m * (m_cache.volumes_data[i].get_position() - m_cache.dragging_center); - (*m_volumes)[i]->set_offset(m_cache.dragging_center + radius); - if (single_full_instance) (*m_volumes)[i]->set_rotation(rotation); else { Eigen::Matrix new_rotation_matrix = (m * m_cache.volumes_data[i].get_rotation_matrix()).matrix().block(0, 0, 3, 3); - // extracts euler angles from the composed transformation - // not using Eigen eulerAngles() method because it returns weird results - // see: https://www.learnopencv.com/rotation-matrix-to-euler-angles/ - double sy = ::sqrt(sqr(new_rotation_matrix(0, 0)) + sqr(new_rotation_matrix(1, 0))); - - Vec3d angles = Vec3d::Zero(); - if (sy >= 1e-6) - { - angles(0) = ::atan2(new_rotation_matrix(2, 1), new_rotation_matrix(2, 2)); - angles(1) = ::atan2(-new_rotation_matrix(2, 0), sy); - angles(2) = ::atan2(new_rotation_matrix(1, 0), new_rotation_matrix(0, 0)); - } - else - { - angles(0) = ::atan2(-new_rotation_matrix(1, 2), new_rotation_matrix(1, 1)); - angles(1) = ::atan2(-new_rotation_matrix(2, 0), sy); - angles(2) = 0.0; - } + Vec3d angles = Geometry::extract_euler_angles(new_rotation_matrix); + (*m_volumes)[i]->set_offset(m_cache.dragging_center + m * (m_cache.volumes_data[i].get_position() - m_cache.dragging_center)); (*m_volumes)[i]->set_rotation(Vec3d(angles(0), angles(1), angles(2))); } } From 59208d79bece36e993e9be8a16fe6d0d9d0c3fde Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Fri, 12 Oct 2018 14:23:34 +0200 Subject: [PATCH 094/186] Modified rendering of gizmo scale 3D --- src/slic3r/GUI/GLGizmo.cpp | 85 +++++++------------------------------- src/slic3r/GUI/GLGizmo.hpp | 3 -- 2 files changed, 14 insertions(+), 74 deletions(-) diff --git a/src/slic3r/GUI/GLGizmo.cpp b/src/slic3r/GUI/GLGizmo.cpp index ced0ca85bd..706fd07394 100644 --- a/src/slic3r/GUI/GLGizmo.cpp +++ b/src/slic3r/GUI/GLGizmo.cpp @@ -709,7 +709,6 @@ GLGizmoScale3D::GLGizmoScale3D(GLCanvas3D& parent) : GLGizmoBase(parent) , m_scale(Vec3d::Ones()) , m_starting_scale(Vec3d::Ones()) - , m_show_starting_box(false) { } @@ -752,7 +751,6 @@ void GLGizmoScale3D::on_start_dragging(const BoundingBoxf3& box) if (m_hover_id != -1) { m_starting_drag_position = m_grabbers[m_hover_id].center; - m_show_starting_box = true; m_starting_box = BoundingBoxf3(box.min - OffsetVec, box.max + OffsetVec); } } @@ -817,10 +815,10 @@ void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const ::memcpy((void*)m_grabbers[5].color, (const void*)&AXES_COLOR[2], 3 * sizeof(float)); // uniform - m_grabbers[6].center = Vec3d(m_box.min(0), m_box.min(1), m_box.min(2)); - m_grabbers[7].center = Vec3d(m_box.max(0), m_box.min(1), m_box.min(2)); - m_grabbers[8].center = Vec3d(m_box.max(0), m_box.max(1), m_box.min(2)); - m_grabbers[9].center = Vec3d(m_box.min(0), m_box.max(1), m_box.min(2)); + m_grabbers[6].center = Vec3d(m_box.min(0), m_box.min(1), center(2)); + m_grabbers[7].center = Vec3d(m_box.max(0), m_box.min(1), center(2)); + m_grabbers[8].center = Vec3d(m_box.max(0), m_box.max(1), center(2)); + m_grabbers[9].center = Vec3d(m_box.min(0), m_box.max(1), center(2)); for (int i = 6; i < 10; ++i) { ::memcpy((void*)m_grabbers[i].color, (const void*)m_highlight_color, 3 * sizeof(float)); @@ -830,9 +828,6 @@ void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const if (m_hover_id == -1) { - // draw box - ::glColor3fv(m_base_color); - render_box(m_box); // draw connections if (m_grabbers[0].enabled && m_grabbers[1].enabled) { @@ -849,20 +844,16 @@ void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const ::glColor3fv(m_grabbers[4].color); render_grabbers_connection(4, 5); } + ::glColor3fv(m_base_color); + render_grabbers_connection(6, 7); + render_grabbers_connection(7, 8); + render_grabbers_connection(8, 9); + render_grabbers_connection(9, 6); // draw grabbers render_grabbers(m_box); } else if ((m_hover_id == 0) || (m_hover_id == 1)) { - // draw starting box - if (m_show_starting_box) - { - ::glColor3fv(m_base_color); - render_box(m_starting_box); - } - // draw current box - ::glColor3fv(m_drag_color); - render_box(m_box); // draw connection ::glColor3fv(m_grabbers[0].color); render_grabbers_connection(0, 1); @@ -872,15 +863,6 @@ void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const } else if ((m_hover_id == 2) || (m_hover_id == 3)) { - // draw starting box - if (m_show_starting_box) - { - ::glColor3fv(m_base_color); - render_box(m_starting_box); - } - // draw current box - ::glColor3fv(m_drag_color); - render_box(m_box); // draw connection ::glColor3fv(m_grabbers[2].color); render_grabbers_connection(2, 3); @@ -890,15 +872,6 @@ void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const } else if ((m_hover_id == 4) || (m_hover_id == 5)) { - // draw starting box - if (m_show_starting_box) - { - ::glColor3fv(m_base_color); - render_box(m_starting_box); - } - // draw current box - ::glColor3fv(m_drag_color); - render_box(m_box); // draw connection ::glColor3fv(m_grabbers[4].color); render_grabbers_connection(4, 5); @@ -908,15 +881,12 @@ void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const } else if (m_hover_id >= 6) { - // draw starting box - if (m_show_starting_box) - { - ::glColor3fv(m_base_color); - render_box(m_starting_box); - } - // draw current box + // draw connection ::glColor3fv(m_drag_color); - render_box(m_box); + render_grabbers_connection(6, 7); + render_grabbers_connection(7, 8); + render_grabbers_connection(8, 9); + render_grabbers_connection(9, 6); // draw grabbers for (int i = 6; i < 10; ++i) { @@ -932,33 +902,6 @@ void GLGizmoScale3D::on_render_for_picking(const BoundingBoxf3& box) const render_grabbers_for_picking(box); } -void GLGizmoScale3D::render_box(const BoundingBoxf3& box) const -{ - // bottom face - ::glBegin(GL_LINE_LOOP); - ::glVertex3f((GLfloat)box.min(0), (GLfloat)box.min(1), (GLfloat)box.min(2)); - ::glVertex3f((GLfloat)box.min(0), (GLfloat)box.max(1), (GLfloat)box.min(2)); - ::glVertex3f((GLfloat)box.max(0), (GLfloat)box.max(1), (GLfloat)box.min(2)); - ::glVertex3f((GLfloat)box.max(0), (GLfloat)box.min(1), (GLfloat)box.min(2)); - ::glEnd(); - - // top face - ::glBegin(GL_LINE_LOOP); - ::glVertex3f((GLfloat)box.min(0), (GLfloat)box.min(1), (GLfloat)box.max(2)); - ::glVertex3f((GLfloat)box.min(0), (GLfloat)box.max(1), (GLfloat)box.max(2)); - ::glVertex3f((GLfloat)box.max(0), (GLfloat)box.max(1), (GLfloat)box.max(2)); - ::glVertex3f((GLfloat)box.max(0), (GLfloat)box.min(1), (GLfloat)box.max(2)); - ::glEnd(); - - // vertical edges - ::glBegin(GL_LINES); - ::glVertex3f((GLfloat)box.min(0), (GLfloat)box.min(1), (GLfloat)box.min(2)); ::glVertex3f((GLfloat)box.min(0), (GLfloat)box.min(1), (GLfloat)box.max(2)); - ::glVertex3f((GLfloat)box.min(0), (GLfloat)box.max(1), (GLfloat)box.min(2)); ::glVertex3f((GLfloat)box.min(0), (GLfloat)box.max(1), (GLfloat)box.max(2)); - ::glVertex3f((GLfloat)box.max(0), (GLfloat)box.max(1), (GLfloat)box.min(2)); ::glVertex3f((GLfloat)box.max(0), (GLfloat)box.max(1), (GLfloat)box.max(2)); - ::glVertex3f((GLfloat)box.max(0), (GLfloat)box.min(1), (GLfloat)box.min(2)); ::glVertex3f((GLfloat)box.max(0), (GLfloat)box.min(1), (GLfloat)box.max(2)); - ::glEnd(); -} - void GLGizmoScale3D::render_grabbers_connection(unsigned int id_1, unsigned int id_2) const { unsigned int grabbers_count = (unsigned int)m_grabbers.size(); diff --git a/src/slic3r/GUI/GLGizmo.hpp b/src/slic3r/GUI/GLGizmo.hpp index 0ad40a8b39..aab16773f5 100644 --- a/src/slic3r/GUI/GLGizmo.hpp +++ b/src/slic3r/GUI/GLGizmo.hpp @@ -277,7 +277,6 @@ class GLGizmoScale3D : public GLGizmoBase Vec3d m_starting_scale; Vec3d m_starting_drag_position; - bool m_show_starting_box; BoundingBoxf3 m_starting_box; public: @@ -302,7 +301,6 @@ public: protected: virtual bool on_init(); virtual void on_start_dragging(const BoundingBoxf3& box); - virtual void on_stop_dragging() { m_show_starting_box = false; } virtual void on_update(const Linef3& mouse_ray); #if ENABLE_GIZMOS_RESET virtual void on_process_double_click(); @@ -311,7 +309,6 @@ protected: virtual void on_render_for_picking(const BoundingBoxf3& box) const; private: - void render_box(const BoundingBoxf3& box) const; void render_grabbers_connection(unsigned int id_1, unsigned int id_2) const; void do_scale_x(const Linef3& mouse_ray); From 76052d33bf7a1fb119b0c1982bb09fede59e1d24 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Fri, 12 Oct 2018 15:43:29 +0200 Subject: [PATCH 095/186] New selection -> scaling wip --- src/slic3r/GUI/GLCanvas3D.cpp | 109 +++++++++++++++++++--- src/slic3r/GUI/GLCanvas3D.hpp | 4 +- src/slic3r/GUI/GUI_ObjectManipulation.cpp | 6 +- src/slic3r/GUI/GUI_ObjectManipulation.hpp | 2 +- 4 files changed, 105 insertions(+), 16 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 2df47519c5..86ec79da81 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1409,19 +1409,46 @@ void GLCanvas3D::Selection::rotate(const Vec3d& rotation) Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), rotation); - bool single_full_instance = is_single_full_instance(); - for (unsigned int i : m_list) { - if (single_full_instance) + if (is_single_full_instance()) (*m_volumes)[i]->set_rotation(rotation); else { - Eigen::Matrix new_rotation_matrix = (m * m_cache.volumes_data[i].get_rotation_matrix()).matrix().block(0, 0, 3, 3); - Vec3d angles = Geometry::extract_euler_angles(new_rotation_matrix); + Eigen::Matrix new_matrix = (m * m_cache.volumes_data[i].get_rotation_matrix()).matrix().block(0, 0, 3, 3); + Vec3d new_rotation = Geometry::extract_euler_angles(new_matrix); (*m_volumes)[i]->set_offset(m_cache.dragging_center + m * (m_cache.volumes_data[i].get_position() - m_cache.dragging_center)); - (*m_volumes)[i]->set_rotation(Vec3d(angles(0), angles(1), angles(2))); + (*m_volumes)[i]->set_rotation(new_rotation); + } + } + + if (m_mode == Instance) + _synchronize_unselected_instances(); + + m_bounding_box_dirty = true; +} + +void GLCanvas3D::Selection::scale(const Vec3d& scale) +{ + if (!m_valid) + return; + + Transform3d m = Transform3d::Identity(); + m.scale(scale); + + for (unsigned int i : m_list) + { + if (is_single_full_instance()) + (*m_volumes)[i]->set_scaling_factor(scale); + else + { + Eigen::Matrix new_matrix = (m * m_cache.volumes_data[i].get_rotation_matrix()).matrix().block(0, 0, 3, 3); + // extracts scaling factors from the composed transformation + Vec3d new_scale(new_matrix.col(0).norm(), new_matrix.col(1).norm(), new_matrix.col(2).norm()); + + (*m_volumes)[i]->set_offset(m_cache.dragging_center + m * (m_cache.volumes_data[i].get_position() - m_cache.dragging_center)); + (*m_volumes)[i]->set_scaling_factor(new_scale); } } @@ -2652,8 +2679,8 @@ wxDEFINE_EVENT(EVT_GLCANVAS_WIPETOWER_MOVED, Vec3dEvent); wxDEFINE_EVENT(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, Event); wxDEFINE_EVENT(EVT_GLCANVAS_UPDATE_GEOMETRY, Vec3dsEvent<2>); -wxDEFINE_EVENT(EVT_GIZMO_SCALE, Vec3dEvent); #if !ENABLE_EXTENDED_SELECTION +wxDEFINE_EVENT(EVT_GIZMO_SCALE, Vec3dEvent); wxDEFINE_EVENT(EVT_GIZMO_ROTATE, Vec3dEvent); #endif // !ENABLE_EXTENDED_SELECTION wxDEFINE_EVENT(EVT_GIZMO_FLATTEN, Vec3dEvent); @@ -3209,6 +3236,11 @@ void GLCanvas3D::update_gizmos_data() #if ENABLE_EXTENDED_SELECTION bool enable_move_z = !m_selection.is_wipe_tower(); m_gizmos.enable_grabber(Gizmos::Move, 2, enable_move_z); + bool enable_scale_xyz = m_selection.is_single_full_instance(); + for (int i = 0; i < 6; ++i) + { + m_gizmos.enable_grabber(Gizmos::Scale, i, enable_scale_xyz); + } if (m_selection.is_single_full_instance()) { @@ -3791,11 +3823,21 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) case Gizmos::Scale: { #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM +#if ENABLE_EXTENDED_SELECTION + m_regenerate_volumes = false; + m_selection.scale(m_gizmos.get_scale()); + _on_scale(); +#else post_event(Vec3dEvent(EVT_GIZMO_SCALE, m_gizmos.get_scale())); +#endif // ENABLE_EXTENDED_SELECTION #else m_on_gizmo_scale_uniformly_callback.call((double)m_gizmos.get_scale()); #endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM +#if ENABLE_EXTENDED_SELECTION + wxGetApp().obj_manipul()->update_settings_value(m_selection); +#else wxGetApp().obj_manipul()->update_scale_values(); +#endif // ENABLE_EXTENDED_SELECTION m_dirty = true; break; } @@ -3804,8 +3846,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM #if ENABLE_EXTENDED_SELECTION m_regenerate_volumes = false; - const Vec3d& rotation = m_gizmos.get_rotation(); - m_selection.rotate(rotation); + m_selection.rotate(m_gizmos.get_rotation()); _on_rotate(); #else post_event(Vec3dEvent(EVT_GIZMO_ROTATE, std::move(m_gizmos.get_rotation()))); @@ -4135,15 +4176,17 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) case Gizmos::Scale: { #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM -#if ENABLE_EXTENDED_SELECTION -#else // Apply new temporary scale factors +#if ENABLE_EXTENDED_SELECTION + m_selection.scale(m_gizmos.get_scale()); + wxGetApp().obj_manipul()->update_settings_value(m_selection); +#else const Vec3d& scale = m_gizmos.get_scale(); for (GLVolume* v : volumes) { v->set_scaling_factor(scale); } - wxGetApp().obj_manipul()->update_scale_values(scale); + wxGetApp().obj_manipul()->update_scale_value(scale); #endif // ENABLE_EXTENDED_SELECTION #else // Apply new temporary scale factor @@ -4159,6 +4202,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) case Gizmos::Rotate: { #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM + // Apply new temporary rotations #if ENABLE_EXTENDED_SELECTION m_selection.rotate(m_gizmos.get_rotation()); wxGetApp().obj_manipul()->update_settings_value(m_selection); @@ -4345,7 +4389,10 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) case Gizmos::Scale: { #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - post_event(Vec3dEvent(EVT_GIZMO_SCALE, m_gizmos.get_scale())); +#if ENABLE_EXTENDED_SELECTION + m_regenerate_volumes = false; + _on_scale(); +#endif // ENABLE_EXTENDED_SELECTION #else m_on_gizmo_scale_uniformly_callback.call((double)m_gizmos.get_scale()); #endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM @@ -6473,6 +6520,42 @@ void GLCanvas3D::_on_rotate() // schedule_background_process } + +void GLCanvas3D::_on_scale() +{ + if (m_model == nullptr) + return; + + std::set> done; // prevent scaling instances twice + const Selection::IndicesList& selection = m_selection.get_volume_idxs(); + + for (unsigned int i : selection) + { + const GLVolume* v = m_volumes.volumes[i]; + int object_idx = v->object_idx(); + if (object_idx >= 1000) + continue; + + int instance_idx = v->instance_idx(); + + // prevent rotating instances twice + std::pair done_id(object_idx, instance_idx); + if (done.find(done_id) != done.end()) + continue; + + done.insert(done_id); + + // Rotate instances. + ModelObject* model_object = m_model->objects[object_idx]; + if (model_object != nullptr) + { + model_object->instances[instance_idx]->set_scaling_factor(v->get_scaling_factor()); + model_object->invalidate_bounding_box(); + } + } + + // schedule_background_process +} #else void GLCanvas3D::_on_move(const std::vector& volume_idxs) { diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index d556ea54d5..828e24fa6a 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -115,8 +115,8 @@ wxDECLARE_EVENT(EVT_GLCANVAS_WIPETOWER_MOVED, Vec3dEvent); wxDECLARE_EVENT(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, Event); wxDECLARE_EVENT(EVT_GLCANVAS_UPDATE_GEOMETRY, Vec3dsEvent<2>); -wxDECLARE_EVENT(EVT_GIZMO_SCALE, Vec3dEvent); #if !ENABLE_EXTENDED_SELECTION +wxDECLARE_EVENT(EVT_GIZMO_SCALE, Vec3dEvent); wxDECLARE_EVENT(EVT_GIZMO_ROTATE, Vec3dEvent); #endif // !ENABLE_EXTENDED_SELECTION wxDECLARE_EVENT(EVT_GIZMO_FLATTEN, Vec3dEvent); @@ -491,6 +491,7 @@ public: void translate(const Vec3d& displacement); void rotate(const Vec3d& rotation); + void scale(const Vec3d& scale); void render(bool show_indirect_selection) const; @@ -939,6 +940,7 @@ private: #if ENABLE_EXTENDED_SELECTION void _on_move(); void _on_rotate(); + void _on_scale(); #else void _on_move(const std::vector& volume_idxs); #endif // ENABLE_EXTENDED_SELECTION diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index 5eb90054c0..6eff84d92e 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -274,6 +274,7 @@ void ObjectManipulation::update_settings_value(const GLCanvas3D::Selection& sele const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); update_position_value(volume->get_offset()); update_rotation_value(volume->get_rotation()); + update_scale_value(volume->get_scaling_factor()); m_og->enable(); } else @@ -285,6 +286,7 @@ void ObjectManipulation::update_settings_value(const GLCanvas3D::Selection& sele const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); update_position_value(volume->get_offset()); update_rotation_value(volume->get_rotation()); + update_scale_value(volume->get_scaling_factor()); m_og->enable(); } else if (selection.is_wipe_tower()) @@ -293,6 +295,7 @@ void ObjectManipulation::update_settings_value(const GLCanvas3D::Selection& sele const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); update_position_value(volume->get_offset()); update_rotation_value(volume->get_rotation()); + update_scale_value(volume->get_scaling_factor()); m_og->enable(); } else if (selection.is_modifier()) @@ -301,6 +304,7 @@ void ObjectManipulation::update_settings_value(const GLCanvas3D::Selection& sele const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); update_position_value(volume->get_offset()); update_rotation_value(volume->get_rotation()); + update_scale_value(volume->get_scaling_factor()); m_og->enable(); } else @@ -420,7 +424,7 @@ void ObjectManipulation::update_position_value(const Vec3d& position) } #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM -void ObjectManipulation::update_scale_values(const Vec3d& scaling_factor) +void ObjectManipulation::update_scale_value(const Vec3d& scaling_factor) { // this is temporary // to be able to update the values as size diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.hpp b/src/slic3r/GUI/GUI_ObjectManipulation.hpp index 7cd5fce276..c0cd701603 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.hpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.hpp @@ -62,7 +62,7 @@ public: // update scale values after scale unit changing or "gizmos" void update_scale_values(); #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - void update_scale_values(const Vec3d& scaling_factor); + void update_scale_value(const Vec3d& scaling_factor); #else void update_scale_values(double scaling_factor); #endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM From 35c7c418e95399f8e2f1d7b4a4548b04534b663b Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Fri, 12 Oct 2018 16:18:37 +0200 Subject: [PATCH 096/186] Small refactoring into GLGizmoBase::Grabber --- src/slic3r/GUI/GLGizmo.cpp | 35 ++++++++++++++++++++--------------- src/slic3r/GUI/GLGizmo.hpp | 6 +++--- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/src/slic3r/GUI/GLGizmo.cpp b/src/slic3r/GUI/GLGizmo.cpp index 706fd07394..d5d7b39e98 100644 --- a/src/slic3r/GUI/GLGizmo.cpp +++ b/src/slic3r/GUI/GLGizmo.cpp @@ -118,7 +118,7 @@ GLGizmoBase::Grabber::Grabber() color[2] = 1.0f; } -void GLGizmoBase::Grabber::render(bool hover, const BoundingBoxf3& box) const +void GLGizmoBase::Grabber::render(bool hover, float size) const { float render_color[3]; if (hover) @@ -130,13 +130,12 @@ void GLGizmoBase::Grabber::render(bool hover, const BoundingBoxf3& box) const else ::memcpy((void*)render_color, (const void*)color, 3 * sizeof(float)); - render(box, render_color, true); + render(size, render_color, true); } -void GLGizmoBase::Grabber::render(const BoundingBoxf3& box, const float* render_color, bool use_lighting) const +void GLGizmoBase::Grabber::render(float size, const float* render_color, bool use_lighting) const { - float max_size = (float)box.max_size(); - float half_size = dragging ? max_size * SizeFactor * DraggingScaleFactor : max_size * SizeFactor; + float half_size = dragging ? size * SizeFactor * DraggingScaleFactor : size * SizeFactor; half_size = std::max(half_size, MinHalfSize); if (use_lighting) @@ -300,15 +299,19 @@ float GLGizmoBase::picking_color_component(unsigned int id) const void GLGizmoBase::render_grabbers(const BoundingBoxf3& box) const { + float size = (float)box.max_size(); + for (int i = 0; i < (int)m_grabbers.size(); ++i) { if (m_grabbers[i].enabled) - m_grabbers[i].render((m_hover_id == i), box); + m_grabbers[i].render((m_hover_id == i), size); } } void GLGizmoBase::render_grabbers_for_picking(const BoundingBoxf3& box) const { + float size = (float)box.max_size(); + for (unsigned int i = 0; i < (unsigned int)m_grabbers.size(); ++i) { if (m_grabbers[i].enabled) @@ -316,7 +319,7 @@ void GLGizmoBase::render_grabbers_for_picking(const BoundingBoxf3& box) const m_grabbers[i].color[0] = 1.0f; m_grabbers[i].color[1] = 1.0f; m_grabbers[i].color[2] = picking_color_component(i); - m_grabbers[i].render_for_picking(box); + m_grabbers[i].render_for_picking(size); } } } @@ -826,6 +829,8 @@ void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const ::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f); + float box_max_size = (float)m_box.max_size(); + if (m_hover_id == -1) { // draw connections @@ -858,8 +863,8 @@ void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const ::glColor3fv(m_grabbers[0].color); render_grabbers_connection(0, 1); // draw grabbers - m_grabbers[0].render(true, m_box); - m_grabbers[1].render(true, m_box); + m_grabbers[0].render(true, box_max_size); + m_grabbers[1].render(true, box_max_size); } else if ((m_hover_id == 2) || (m_hover_id == 3)) { @@ -867,8 +872,8 @@ void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const ::glColor3fv(m_grabbers[2].color); render_grabbers_connection(2, 3); // draw grabbers - m_grabbers[2].render(true, m_box); - m_grabbers[3].render(true, m_box); + m_grabbers[2].render(true, box_max_size); + m_grabbers[3].render(true, box_max_size); } else if ((m_hover_id == 4) || (m_hover_id == 5)) { @@ -876,8 +881,8 @@ void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const ::glColor3fv(m_grabbers[4].color); render_grabbers_connection(4, 5); // draw grabbers - m_grabbers[4].render(true, m_box); - m_grabbers[5].render(true, m_box); + m_grabbers[4].render(true, box_max_size); + m_grabbers[5].render(true, box_max_size); } else if (m_hover_id >= 6) { @@ -890,7 +895,7 @@ void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const // draw grabbers for (int i = 6; i < 10; ++i) { - m_grabbers[i].render(true, m_box); + m_grabbers[i].render(true, box_max_size); } } } @@ -1132,7 +1137,7 @@ void GLGizmoMove3D::on_render(const BoundingBoxf3& box) const ::glEnd(); // draw grabber - m_grabbers[m_hover_id].render(true, box); + m_grabbers[m_hover_id].render(true, box.max_size()); } } diff --git a/src/slic3r/GUI/GLGizmo.hpp b/src/slic3r/GUI/GLGizmo.hpp index aab16773f5..ef04112826 100644 --- a/src/slic3r/GUI/GLGizmo.hpp +++ b/src/slic3r/GUI/GLGizmo.hpp @@ -34,11 +34,11 @@ protected: Grabber(); - void render(bool hover, const BoundingBoxf3& box) const; - void render_for_picking(const BoundingBoxf3& box) const { render(box, color, false); } + void render(bool hover, float size) const; + void render_for_picking(float size) const { render(size, color, false); } private: - void render(const BoundingBoxf3& box, const float* render_color, bool use_lighting) const; + void render(float size, const float* render_color, bool use_lighting) const; void render_face(float half_size) const; }; From d654e35975c32d733def5cfc8a66701ddf0d3138 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Mon, 15 Oct 2018 10:53:47 +0200 Subject: [PATCH 097/186] Ported Plater->on_config_change --- src/slic3r/GUI/GUI_ObjectList.cpp | 4 +- src/slic3r/GUI/Plater.cpp | 71 ++++++++++++++++++++++++++++++- src/slic3r/GUI/Plater.hpp | 9 ++++ 3 files changed, 81 insertions(+), 3 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index a3d912c457..5644a0806d 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -209,8 +209,8 @@ void ObjectList::update_extruder_in_config(const wxString& selection) int extruder = selection.size() > 1 ? 0 : atoi(selection.c_str()); m_config->set_key_value("extruder", new ConfigOptionInt(extruder)); -// #ys_FIXME_events -// wxGetApp().plater()->update(); + // update scene + wxGetApp().plater()->update(); } void ObjectList::init_icons(){ diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 57d887cca2..6bae93b958 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -216,6 +216,7 @@ PresetComboBox::PresetComboBox(wxWindow *parent, Preset::Type preset_type) : wxGetApp().get_tab(Preset::TYPE_PRINTER)->load_config(cfg); wxGetApp().preset_bundle->update_platter_filament_ui(extruder_idx, this); + wxGetApp().plater()->on_config_change(&cfg); } dialog->Destroy(); }); @@ -642,6 +643,24 @@ void Sidebar::enable_buttons(bool enable) p->btn_send_gcode->Enable(enable); } +void Sidebar::show_button(ButtonAction but_action, bool show) +{ + switch (but_action) + { + case baReslice: + p->btn_reslice->Show(show); + break; + case baExportGcode: + p->btn_export_gcode->Show(show); + break; + case baSendGcode: + p->btn_send_gcode->Show(show); + break; + default: + break; + } +} + bool Sidebar::is_multifilament() { return p->combos_filament.size() > 0; @@ -1907,7 +1926,57 @@ void Plater::on_extruders_change(int num_extruders) void Plater::on_config_change(DynamicPrintConfig* config) { - // TODO + bool update_scheduled = false; + for ( auto opt_key: p->config->diff(*config)) { + p->config->set_key_value(opt_key, config->option(opt_key)->clone()); + if (opt_key == "bed_shape") { + if (p->canvas3D) _3DScene::set_bed_shape(p->canvas3D, p->config->option(opt_key)->values); + if (p->preview) p->preview->set_bed_shape(p->config->option(opt_key)->values); + update_scheduled = true; + } + else if(opt_key == "wipe_tower" /*|| opt_key == "filament_minimal_purge_on_wipe_tower"*/ || // ? #ys_FIXME + opt_key == "single_extruder_multi_material") { + update_scheduled = true; + } +// else if(opt_key == "serial_port") { +// sidebar()->p->btn_print->Show(config->get("serial_port")); // ???: btn_print is removed +// Layout(); +// } + else if (opt_key == "print_host") { + sidebar().show_button(baReslice, !p->config->option(opt_key)->value.empty()); + Layout(); + } + else if(opt_key == "variable_layer_height") { + if (p->config->opt_bool("variable_layer_height") != true) { + _3DScene::enable_toolbar_item(p->canvas3D, "layersediting", false); + _3DScene::enable_layers_editing(p->canvas3D, 0); + p->canvas3D->Refresh(); + p->canvas3D->Update(); + } + else if (_3DScene::is_layers_editing_allowed(p->canvas3D)) { + _3DScene::enable_toolbar_item(p->canvas3D, "layersediting", true); + } + } + else if(opt_key == "extruder_colour") { + update_scheduled = true; + p->preview->set_number_extruders(p->config->option(opt_key)->values.size()); + } else if(opt_key == "max_print_height") { + update_scheduled = true; + } else if(opt_key == "printer_model") { + // update to force bed selection(for texturing) + if (p->canvas3D) _3DScene::set_bed_shape(p->canvas3D, p->config->option("bed_shape")->values); + if (p->preview) p->preview->set_bed_shape(p->config->option("bed_shape")->values); + update_scheduled = true; + } + } + + if (update_scheduled) + update(); + + if (!p->main_frame->is_loaded()) return ; + + // (re)start timer +// schedule_background_process(); } wxGLCanvas* Plater::canvas3D() diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index b174f5e211..fba2e0dc0b 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -49,6 +49,14 @@ private: int extruder_idx = -1; }; +enum ButtonAction +{ + baUndef, + baReslice, + baExportGcode, + baSendGcode +}; + class Sidebar : public wxPanel { public: @@ -71,6 +79,7 @@ public: void update_objects_list_extruder_column(int extruders_count); void show_info_sizers(const bool show); void show_buttons(const bool show); + void show_button(ButtonAction but_action, bool show); void enable_buttons(bool enable); bool is_multifilament(); From f2486bd87d3336644872ccaaff66e3c9e8f1f99c Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Mon, 15 Oct 2018 11:30:50 +0200 Subject: [PATCH 098/186] New selection -> Gizmos methods refactored to accept selection instead of bounding box and scale gizmo in local system for single instance selections --- src/slic3r/GUI/GLCanvas3D.cpp | 44 ++++++++- src/slic3r/GUI/GLCanvas3D.hpp | 15 ++- src/slic3r/GUI/GLGizmo.cpp | 178 +++++++++++++++++++++++++++++++++- src/slic3r/GUI/GLGizmo.hpp | 72 ++++++++++++++ 4 files changed, 301 insertions(+), 8 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 86ec79da81..25b779d86f 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -2106,12 +2106,21 @@ bool GLCanvas3D::Gizmos::is_dragging() const return (curr != nullptr) ? curr->is_dragging() : false; } +#if ENABLE_EXTENDED_SELECTION +void GLCanvas3D::Gizmos::start_dragging(const GLCanvas3D::Selection& selection) +{ + GLGizmoBase* curr = _get_current(); + if (curr != nullptr) + curr->start_dragging(selection); +} +#else void GLCanvas3D::Gizmos::start_dragging(const BoundingBoxf3& box) { GLGizmoBase* curr = _get_current(); if (curr != nullptr) curr->start_dragging(box); } +#endif // ENABLE_EXTENDED_SELECTION void GLCanvas3D::Gizmos::stop_dragging() { @@ -2256,17 +2265,36 @@ void GLCanvas3D::Gizmos::set_flattening_data(const ModelObject* model_object) reinterpret_cast(it->second)->set_flattening_data(model_object); } +#if ENABLE_EXTENDED_SELECTION +void GLCanvas3D::Gizmos::render_current_gizmo(const GLCanvas3D::Selection& selection) const +#else void GLCanvas3D::Gizmos::render_current_gizmo(const BoundingBoxf3& box) const +#endif // ENABLE_EXTENDED_SELECTION { if (!m_enabled) return; ::glDisable(GL_DEPTH_TEST); +#if ENABLE_EXTENDED_SELECTION + _render_current_gizmo(selection); +#else if (box.radius() > 0.0) _render_current_gizmo(box); +#endif // ENABLE_EXTENDED_SELECTION } +#if ENABLE_EXTENDED_SELECTION +void GLCanvas3D::Gizmos::render_current_gizmo_for_picking_pass(const GLCanvas3D::Selection& selection) const +{ + if (!m_enabled) + return; + + GLGizmoBase* curr = _get_current(); + if (curr != nullptr) + curr->render_for_picking(selection); +} +#else void GLCanvas3D::Gizmos::render_current_gizmo_for_picking_pass(const BoundingBoxf3& box) const { if (!m_enabled) @@ -2276,6 +2304,7 @@ void GLCanvas3D::Gizmos::render_current_gizmo_for_picking_pass(const BoundingBox if (curr != nullptr) curr->render_for_picking(box); } +#endif // ENABLE_EXTENDED_SELECTION void GLCanvas3D::Gizmos::render_overlay(const GLCanvas3D& canvas) const { @@ -2324,12 +2353,21 @@ void GLCanvas3D::Gizmos::_render_overlay(const GLCanvas3D& canvas) const } } +#if ENABLE_EXTENDED_SELECTION +void GLCanvas3D::Gizmos::_render_current_gizmo(const GLCanvas3D::Selection& selection) const +{ + GLGizmoBase* curr = _get_current(); + if (curr != nullptr) + curr->render(selection); +} +#else void GLCanvas3D::Gizmos::_render_current_gizmo(const BoundingBoxf3& box) const { GLGizmoBase* curr = _get_current(); if (curr != nullptr) curr->render(box); } +#endif // ENABLE_EXTENDED_SELECTION float GLCanvas3D::Gizmos::_get_total_overlay_height() const { @@ -3922,7 +3960,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) update_gizmos_data(); #if ENABLE_EXTENDED_SELECTION m_selection.start_dragging(); - m_gizmos.start_dragging(m_selection.get_bounding_box()); + m_gizmos.start_dragging(m_selection); #else m_gizmos.start_dragging(_selected_volumes_bounding_box()); m_mouse.drag.gizmo_volume_idx = _get_first_selected_volume_id(selected_object_idx); @@ -4932,7 +4970,7 @@ void GLCanvas3D::_picking_pass() const _render_volumes(true); #if ENABLE_EXTENDED_SELECTION - m_gizmos.render_current_gizmo_for_picking_pass(m_selection.get_bounding_box()); + m_gizmos.render_current_gizmo_for_picking_pass(m_selection); #else m_gizmos.render_current_gizmo_for_picking_pass(_selected_volumes_bounding_box()); #endif // ENABLE_EXTENDED_SELECTION @@ -5207,7 +5245,7 @@ void GLCanvas3D::_render_volumes(bool fake_colors) const void GLCanvas3D::_render_current_gizmo() const { #if ENABLE_EXTENDED_SELECTION - m_gizmos.render_current_gizmo(m_selection.get_bounding_box()); + m_gizmos.render_current_gizmo(m_selection); #else m_gizmos.render_current_gizmo(_selected_volumes_bounding_box()); #endif // ENABLE_EXTENDED_SELECTION diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 828e24fa6a..9e34eb23d8 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -573,7 +573,11 @@ private: bool is_running() const; bool is_dragging() const; +#if ENABLE_EXTENDED_SELECTION + void start_dragging(const Selection& selection); +#else void start_dragging(const BoundingBoxf3& box); +#endif // ENABLE_EXTENDED_SELECTION void stop_dragging(); #if ENABLE_EXTENDED_SELECTION @@ -603,16 +607,25 @@ private: void set_flattening_data(const ModelObject* model_object); +#if ENABLE_EXTENDED_SELECTION + void render_current_gizmo(const Selection& selection) const; + void render_current_gizmo_for_picking_pass(const Selection& selection) const; +#else void render_current_gizmo(const BoundingBoxf3& box) const; - void render_current_gizmo_for_picking_pass(const BoundingBoxf3& box) const; +#endif // ENABLE_EXTENDED_SELECTION + void render_overlay(const GLCanvas3D& canvas) const; private: void _reset(); void _render_overlay(const GLCanvas3D& canvas) const; +#if ENABLE_EXTENDED_SELECTION + void _render_current_gizmo(const Selection& selection) const; +#else void _render_current_gizmo(const BoundingBoxf3& box) const; +#endif // ENABLE_EXTENDED_SELECTION float _get_total_overlay_height() const; GLGizmoBase* _get_current() const; diff --git a/src/slic3r/GUI/GLGizmo.cpp b/src/slic3r/GUI/GLGizmo.cpp index d5d7b39e98..2d5e8a64e1 100644 --- a/src/slic3r/GUI/GLGizmo.cpp +++ b/src/slic3r/GUI/GLGizmo.cpp @@ -1,7 +1,10 @@ +#include "../../libslic3r/libslic3r.h" #include "GLGizmo.hpp" #include "../../libslic3r/Utils.hpp" +#if !ENABLE_EXTENDED_SELECTION #include "../../slic3r/GUI/GLCanvas3D.hpp" +#endif // !ENABLE_EXTENDED_SELECTION #include #include "../../libslic3r/Geometry.hpp" @@ -146,10 +149,9 @@ void GLGizmoBase::Grabber::render(float size, const float* render_color, bool us ::glPushMatrix(); ::glTranslated(center(0), center(1), center(2)); - double rad_to_deg = 180.0 / (double)PI; - ::glRotated(angles(0) * rad_to_deg, 1.0, 0.0, 0.0); - ::glRotated(angles(1) * rad_to_deg, 0.0, 1.0, 0.0); - ::glRotated(angles(2) * rad_to_deg, 0.0, 0.0, 1.0); + ::glRotated(Geometry::rad2deg(angles(2)), 0.0, 0.0, 1.0); + ::glRotated(Geometry::rad2deg(angles(1)), 0.0, 1.0, 0.0); + ::glRotated(Geometry::rad2deg(angles(0)), 1.0, 0.0, 0.0); // face min x ::glPushMatrix(); @@ -257,7 +259,11 @@ void GLGizmoBase::disable_grabber(unsigned int id) on_disable_grabber(id); } +#if ENABLE_EXTENDED_SELECTION +void GLGizmoBase::start_dragging(const GLCanvas3D::Selection& selection) +#else void GLGizmoBase::start_dragging(const BoundingBoxf3& box) +#endif // ENABLE_EXTENDED_SELECTION { m_dragging = true; @@ -266,7 +272,11 @@ void GLGizmoBase::start_dragging(const BoundingBoxf3& box) m_grabbers[i].dragging = (m_hover_id == i); } +#if ENABLE_EXTENDED_SELECTION + on_start_dragging(selection); +#else on_start_dragging(box); +#endif // ENABLE_EXTENDED_SELECTION } void GLGizmoBase::stop_dragging() @@ -373,8 +383,15 @@ bool GLGizmoRotate::on_init() return true; } +#if ENABLE_EXTENDED_SELECTION +void GLGizmoRotate::on_start_dragging(const GLCanvas3D::Selection& selection) +#else void GLGizmoRotate::on_start_dragging(const BoundingBoxf3& box) +#endif // ENABLE_EXTENDED_SELECTION { +#if ENABLE_EXTENDED_SELECTION + const BoundingBoxf3& box = selection.get_bounding_box(); +#endif // ENABLE_EXTENDED_SELECTION m_center = box.center(); m_radius = Offset + box.radius(); m_snap_coarse_in_radius = m_radius / 3.0f; @@ -418,11 +435,19 @@ void GLGizmoRotate::on_update(const Linef3& mouse_ray) m_angle = theta; } +#if ENABLE_EXTENDED_SELECTION +void GLGizmoRotate::on_render(const GLCanvas3D::Selection& selection) const +#else void GLGizmoRotate::on_render(const BoundingBoxf3& box) const +#endif // ENABLE_EXTENDED_SELECTION { if (!m_grabbers[0].enabled) return; +#if ENABLE_EXTENDED_SELECTION + const BoundingBoxf3& box = selection.get_bounding_box(); +#endif // ENABLE_EXTENDED_SELECTION + if (m_dragging) set_tooltip(format(m_angle * 180.0f / (float)PI, 4)); else @@ -462,14 +487,22 @@ void GLGizmoRotate::on_render(const BoundingBoxf3& box) const ::glPopMatrix(); } +#if ENABLE_EXTENDED_SELECTION +void GLGizmoRotate::on_render_for_picking(const GLCanvas3D::Selection& selection) const +#else void GLGizmoRotate::on_render_for_picking(const BoundingBoxf3& box) const +#endif // ENABLE_EXTENDED_SELECTION { ::glDisable(GL_DEPTH_TEST); ::glPushMatrix(); transform_to_local(); +#if ENABLE_EXTENDED_SELECTION + render_grabbers_for_picking(selection.get_bounding_box()); +#else render_grabbers_for_picking(box); +#endif // ENABLE_EXTENDED_SELECTION ::glPopMatrix(); } @@ -681,11 +714,19 @@ bool GLGizmoRotate3D::on_init() return true; } +#if ENABLE_EXTENDED_SELECTION +void GLGizmoRotate3D::on_start_dragging(const GLCanvas3D::Selection& selection) +{ + if ((0 <= m_hover_id) && (m_hover_id < 3)) + m_gizmos[m_hover_id].start_dragging(selection); +} +#else void GLGizmoRotate3D::on_start_dragging(const BoundingBoxf3& box) { if ((0 <= m_hover_id) && (m_hover_id < 3)) m_gizmos[m_hover_id].start_dragging(box); } +#endif // ENABLE_EXTENDED_SELECTION void GLGizmoRotate3D::on_stop_dragging() { @@ -693,6 +734,19 @@ void GLGizmoRotate3D::on_stop_dragging() m_gizmos[m_hover_id].stop_dragging(); } +#if ENABLE_EXTENDED_SELECTION +void GLGizmoRotate3D::on_render(const GLCanvas3D::Selection& selection) const +{ + if ((m_hover_id == -1) || (m_hover_id == 0)) + m_gizmos[X].render(selection); + + if ((m_hover_id == -1) || (m_hover_id == 1)) + m_gizmos[Y].render(selection); + + if ((m_hover_id == -1) || (m_hover_id == 2)) + m_gizmos[Z].render(selection); +} +#else void GLGizmoRotate3D::on_render(const BoundingBoxf3& box) const { if ((m_hover_id == -1) || (m_hover_id == 0)) @@ -704,6 +758,7 @@ void GLGizmoRotate3D::on_render(const BoundingBoxf3& box) const if ((m_hover_id == -1) || (m_hover_id == 2)) m_gizmos[Z].render(box); } +#endif // ENABLE_EXTENDED_SELECTION const float GLGizmoScale3D::Offset = 5.0f; const Vec3d GLGizmoScale3D::OffsetVec = (double)GLGizmoScale3D::Offset * Vec3d::Ones(); @@ -749,11 +804,18 @@ bool GLGizmoScale3D::on_init() return true; } +#if ENABLE_EXTENDED_SELECTION +void GLGizmoScale3D::on_start_dragging(const GLCanvas3D::Selection& selection) +#else void GLGizmoScale3D::on_start_dragging(const BoundingBoxf3& box) +#endif // ENABLE_EXTENDED_SELECTION { if (m_hover_id != -1) { m_starting_drag_position = m_grabbers[m_hover_id].center; +#if ENABLE_EXTENDED_SELECTION + const BoundingBoxf3& box = selection.get_bounding_box(); +#endif // ENABLE_EXTENDED_SELECTION m_starting_box = BoundingBoxf3(box.min - OffsetVec, box.max + OffsetVec); } } @@ -778,7 +840,11 @@ void GLGizmoScale3D::on_process_double_click() } #endif // ENABLE_GIZMOS_RESET +#if ENABLE_EXTENDED_SELECTION +void GLGizmoScale3D::on_render(const GLCanvas3D::Selection& selection) const +#else void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const +#endif // ENABLE_EXTENDED_SELECTION { if (m_grabbers[0].dragging || m_grabbers[1].dragging) set_tooltip("X: " + format(100.0f * m_scale(0), 4) + "%"); @@ -796,37 +862,91 @@ void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const ::glEnable(GL_DEPTH_TEST); +#if ENABLE_EXTENDED_SELECTION + BoundingBoxf3 box; + Transform3d transform = Transform3d::Identity(); + Vec3d angles = Vec3d::Zero(); + + if (selection.is_from_single_instance()) + { + // calculate bounding box in instance local reference system + const GLCanvas3D::Selection::IndicesList& idxs = selection.get_volume_idxs(); + for (unsigned int idx : idxs) + { + box.merge(selection.get_volume(idx)->bounding_box); + } + + // gets transform from first selected volume + transform = selection.get_volume(*idxs.begin())->world_matrix().cast(); + + // extract angles from transform + angles = Slic3r::Geometry::extract_euler_angles(transform); + } + else + box = selection.get_bounding_box(); +#endif // ENABLE_EXTENDED_SELECTION + m_box = BoundingBoxf3(box.min - OffsetVec, box.max + OffsetVec); const Vec3d& center = m_box.center(); // x axis +#if ENABLE_EXTENDED_SELECTION + m_grabbers[0].center = transform * Vec3d(m_box.min(0), center(1), center(2)); + m_grabbers[1].center = transform * Vec3d(m_box.max(0), center(1), center(2)); +#else m_grabbers[0].center = Vec3d(m_box.min(0), center(1), center(2)); m_grabbers[1].center = Vec3d(m_box.max(0), center(1), center(2)); +#endif // ENABLE_EXTENDED_SELECTION ::memcpy((void*)m_grabbers[0].color, (const void*)&AXES_COLOR[0], 3 * sizeof(float)); ::memcpy((void*)m_grabbers[1].color, (const void*)&AXES_COLOR[0], 3 * sizeof(float)); // y axis +#if ENABLE_EXTENDED_SELECTION + m_grabbers[2].center = transform * Vec3d(center(0), m_box.min(1), center(2)); + m_grabbers[3].center = transform * Vec3d(center(0), m_box.max(1), center(2)); +#else m_grabbers[2].center = Vec3d(center(0), m_box.min(1), center(2)); m_grabbers[3].center = Vec3d(center(0), m_box.max(1), center(2)); +#endif // ENABLE_EXTENDED_SELECTION ::memcpy((void*)m_grabbers[2].color, (const void*)&AXES_COLOR[1], 3 * sizeof(float)); ::memcpy((void*)m_grabbers[3].color, (const void*)&AXES_COLOR[1], 3 * sizeof(float)); // z axis +#if ENABLE_EXTENDED_SELECTION + m_grabbers[4].center = transform * Vec3d(center(0), center(1), m_box.min(2)); + m_grabbers[5].center = transform * Vec3d(center(0), center(1), m_box.max(2)); +#else m_grabbers[4].center = Vec3d(center(0), center(1), m_box.min(2)); m_grabbers[5].center = Vec3d(center(0), center(1), m_box.max(2)); +#endif // ENABLE_EXTENDED_SELECTION ::memcpy((void*)m_grabbers[4].color, (const void*)&AXES_COLOR[2], 3 * sizeof(float)); ::memcpy((void*)m_grabbers[5].color, (const void*)&AXES_COLOR[2], 3 * sizeof(float)); // uniform +#if ENABLE_EXTENDED_SELECTION + m_grabbers[6].center = transform * Vec3d(m_box.min(0), m_box.min(1), center(2)); + m_grabbers[7].center = transform * Vec3d(m_box.max(0), m_box.min(1), center(2)); + m_grabbers[8].center = transform * Vec3d(m_box.max(0), m_box.max(1), center(2)); + m_grabbers[9].center = transform * Vec3d(m_box.min(0), m_box.max(1), center(2)); +#else m_grabbers[6].center = Vec3d(m_box.min(0), m_box.min(1), center(2)); m_grabbers[7].center = Vec3d(m_box.max(0), m_box.min(1), center(2)); m_grabbers[8].center = Vec3d(m_box.max(0), m_box.max(1), center(2)); m_grabbers[9].center = Vec3d(m_box.min(0), m_box.max(1), center(2)); +#endif // ENABLE_EXTENDED_SELECTION for (int i = 6; i < 10; ++i) { ::memcpy((void*)m_grabbers[i].color, (const void*)m_highlight_color, 3 * sizeof(float)); } +#if ENABLE_EXTENDED_SELECTION + // sets grabbers orientation + for (int i = 0; i < 10; ++i) + { + m_grabbers[i].angles = angles; + } +#endif // ENABLE_EXTENDED_SELECTION + ::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f); float box_max_size = (float)m_box.max_size(); @@ -900,12 +1020,21 @@ void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const } } +#if ENABLE_EXTENDED_SELECTION +void GLGizmoScale3D::on_render_for_picking(const GLCanvas3D::Selection& selection) const +{ + ::glDisable(GL_DEPTH_TEST); + + render_grabbers_for_picking(selection.get_bounding_box()); +} +#else void GLGizmoScale3D::on_render_for_picking(const BoundingBoxf3& box) const { ::glDisable(GL_DEPTH_TEST); render_grabbers_for_picking(box); } +#endif // ENABLE_EXTENDED_SELECTION void GLGizmoScale3D::render_grabbers_connection(unsigned int id_1, unsigned int id_2) const { @@ -1040,12 +1169,17 @@ bool GLGizmoMove3D::on_init() return true; } +#if ENABLE_EXTENDED_SELECTION +void GLGizmoMove3D::on_start_dragging(const GLCanvas3D::Selection& selection) +#else void GLGizmoMove3D::on_start_dragging(const BoundingBoxf3& box) +#endif // ENABLE_EXTENDED_SELECTION { if (m_hover_id != -1) { #if ENABLE_EXTENDED_SELECTION m_displacement = Vec3d::Zero(); + const BoundingBoxf3& box = selection.get_bounding_box(); #endif // ENABLE_EXTENDED_SELECTION m_starting_drag_position = m_grabbers[m_hover_id].center; m_starting_box_center = box.center(); @@ -1073,7 +1207,11 @@ void GLGizmoMove3D::on_update(const Linef3& mouse_ray) #endif // ENABLE_EXTENDED_SELECTION } +#if ENABLE_EXTENDED_SELECTION +void GLGizmoMove3D::on_render(const GLCanvas3D::Selection& selection) const +#else void GLGizmoMove3D::on_render(const BoundingBoxf3& box) const +#endif // ENABLE_EXTENDED_SELECTION { #if ENABLE_EXTENDED_SELECTION if (m_grabbers[0].dragging) @@ -1093,6 +1231,9 @@ void GLGizmoMove3D::on_render(const BoundingBoxf3& box) const ::glEnable(GL_DEPTH_TEST); +#if ENABLE_EXTENDED_SELECTION + const BoundingBoxf3& box = selection.get_bounding_box(); +#endif // ENABLE_EXTENDED_SELECTION const Vec3d& center = box.center(); // x axis @@ -1141,12 +1282,21 @@ void GLGizmoMove3D::on_render(const BoundingBoxf3& box) const } } +#if ENABLE_EXTENDED_SELECTION +void GLGizmoMove3D::on_render_for_picking(const GLCanvas3D::Selection& selection) const +{ + ::glDisable(GL_DEPTH_TEST); + + render_grabbers_for_picking(selection.get_bounding_box()); +} +#else void GLGizmoMove3D::on_render_for_picking(const BoundingBoxf3& box) const { ::glDisable(GL_DEPTH_TEST); render_grabbers_for_picking(box); } +#endif // ENABLE_EXTENDED_SELECTION double GLGizmoMove3D::calc_projection(Axis axis, unsigned int preferred_plane_id, const Linef3& mouse_ray) const { @@ -1210,23 +1360,39 @@ bool GLGizmoFlatten::on_init() return true; } +#if ENABLE_EXTENDED_SELECTION +void GLGizmoFlatten::on_start_dragging(const GLCanvas3D::Selection& selection) +#else void GLGizmoFlatten::on_start_dragging(const BoundingBoxf3& box) +#endif // ENABLE_EXTENDED_SELECTION { if (m_hover_id != -1) { m_normal = m_planes[m_hover_id].normal; +#if ENABLE_EXTENDED_SELECTION + m_starting_center = selection.get_bounding_box().center(); +#else m_starting_center = box.center(); +#endif // ENABLE_EXTENDED_SELECTION } } +#if ENABLE_EXTENDED_SELECTION +void GLGizmoFlatten::on_render(const GLCanvas3D::Selection& selection) const +#else void GLGizmoFlatten::on_render(const BoundingBoxf3& box) const +#endif // ENABLE_EXTENDED_SELECTION { // the dragged_offset is a vector measuring where was the object moved // with the gizmo being on. This is reset in set_flattening_data and // does not work correctly when there are multiple copies. Vec3d dragged_offset(Vec3d::Zero()); if (m_dragging) +#if ENABLE_EXTENDED_SELECTION + dragged_offset = selection.get_bounding_box().center() - m_starting_center; +#else dragged_offset = box.center() - m_starting_center; +#endif // ENABLE_EXTENDED_SELECTION ::glEnable(GL_BLEND); ::glEnable(GL_DEPTH_TEST); @@ -1260,7 +1426,11 @@ void GLGizmoFlatten::on_render(const BoundingBoxf3& box) const ::glDisable(GL_BLEND); } +#if ENABLE_EXTENDED_SELECTION +void GLGizmoFlatten::on_render_for_picking(const GLCanvas3D::Selection& selection) const +#else void GLGizmoFlatten::on_render_for_picking(const BoundingBoxf3& box) const +#endif // ENABLE_EXTENDED_SELECTION { ::glEnable(GL_DEPTH_TEST); diff --git a/src/slic3r/GUI/GLGizmo.hpp b/src/slic3r/GUI/GLGizmo.hpp index ef04112826..cb68b7e5dd 100644 --- a/src/slic3r/GUI/GLGizmo.hpp +++ b/src/slic3r/GUI/GLGizmo.hpp @@ -2,6 +2,9 @@ #define slic3r_GLGizmo_hpp_ #include "../../slic3r/GUI/GLTexture.hpp" +#if ENABLE_EXTENDED_SELECTION +#include "../../slic3r/GUI/GLCanvas3D.hpp" +#endif // ENABLE_EXTENDED_SELECTION #include "../../libslic3r/Point.hpp" #include "../../libslic3r/BoundingBox.hpp" @@ -96,7 +99,11 @@ public: void enable_grabber(unsigned int id); void disable_grabber(unsigned int id); +#if ENABLE_EXTENDED_SELECTION + void start_dragging(const GLCanvas3D::Selection& selection); +#else void start_dragging(const BoundingBoxf3& box); +#endif // ENABLE_EXTENDED_SELECTION void stop_dragging(); bool is_dragging() const { return m_dragging; } @@ -106,8 +113,13 @@ public: void process_double_click() { on_process_double_click(); } #endif // ENABLE_GIZMOS_RESET +#if ENABLE_EXTENDED_SELECTION + void render(const GLCanvas3D::Selection& selection) const { on_render(selection); } + void render_for_picking(const GLCanvas3D::Selection& selection) const { on_render_for_picking(selection); } +#else void render(const BoundingBoxf3& box) const { on_render(box); } void render_for_picking(const BoundingBoxf3& box) const { on_render_for_picking(box); } +#endif // ENABLE_EXTENDED_SELECTION protected: virtual bool on_init() = 0; @@ -115,14 +127,23 @@ protected: virtual void on_set_hover_id() {} virtual void on_enable_grabber(unsigned int id) {} virtual void on_disable_grabber(unsigned int id) {} +#if ENABLE_EXTENDED_SELECTION + virtual void on_start_dragging(const GLCanvas3D::Selection& selection) {} +#else virtual void on_start_dragging(const BoundingBoxf3& box) {} +#endif // ENABLE_EXTENDED_SELECTION virtual void on_stop_dragging() {} virtual void on_update(const Linef3& mouse_ray) = 0; #if ENABLE_GIZMOS_RESET virtual void on_process_double_click() {} #endif // ENABLE_GIZMOS_RESET +#if ENABLE_EXTENDED_SELECTION + virtual void on_render(const GLCanvas3D::Selection& selection) const = 0; + virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const = 0; +#else virtual void on_render(const BoundingBoxf3& box) const = 0; virtual void on_render_for_picking(const BoundingBoxf3& box) const = 0; +#endif // ENABLE_EXTENDED_SELECTION float picking_color_component(unsigned int id) const; void render_grabbers(const BoundingBoxf3& box) const; @@ -172,13 +193,22 @@ public: protected: virtual bool on_init(); +#if ENABLE_EXTENDED_SELECTION + virtual void on_start_dragging(const GLCanvas3D::Selection& selection); +#else virtual void on_start_dragging(const BoundingBoxf3& box); +#endif // ENABLE_EXTENDED_SELECTION virtual void on_update(const Linef3& mouse_ray); #if ENABLE_GIZMOS_RESET virtual void on_process_double_click() { m_angle = 0.0; } #endif // ENABLE_GIZMOS_RESET +#if ENABLE_EXTENDED_SELECTION + virtual void on_render(const GLCanvas3D::Selection& selection) const; + virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const; +#else virtual void on_render(const BoundingBoxf3& box) const; virtual void on_render_for_picking(const BoundingBoxf3& box) const; +#endif // ENABLE_EXTENDED_SELECTION private: void render_circle() const; @@ -240,7 +270,11 @@ protected: if ((0 <= id) && (id < 3)) m_gizmos[id].disable_grabber(0); } +#if ENABLE_EXTENDED_SELECTION + virtual void on_start_dragging(const GLCanvas3D::Selection& selection); +#else virtual void on_start_dragging(const BoundingBoxf3& box); +#endif // ENABLE_EXTENDED_SELECTION virtual void on_stop_dragging(); virtual void on_update(const Linef3& mouse_ray) { @@ -256,6 +290,16 @@ protected: m_gizmos[m_hover_id].process_double_click(); } #endif // ENABLE_GIZMOS_RESET +#if ENABLE_EXTENDED_SELECTION + virtual void on_render(const GLCanvas3D::Selection& selection) const; + virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const + { + for (const GLGizmoRotate& g : m_gizmos) + { + g.render_for_picking(selection); + } + } +#else virtual void on_render(const BoundingBoxf3& box) const; virtual void on_render_for_picking(const BoundingBoxf3& box) const { @@ -264,6 +308,7 @@ protected: g.render_for_picking(box); } } +#endif // ENABLE_EXTENDED_SELECTION }; class GLGizmoScale3D : public GLGizmoBase @@ -300,13 +345,22 @@ public: protected: virtual bool on_init(); +#if ENABLE_EXTENDED_SELECTION + virtual void on_start_dragging(const GLCanvas3D::Selection& selection); +#else virtual void on_start_dragging(const BoundingBoxf3& box); +#endif // ENABLE_EXTENDED_SELECTION virtual void on_update(const Linef3& mouse_ray); #if ENABLE_GIZMOS_RESET virtual void on_process_double_click(); #endif // ENABLE_GIZMOS_RESET +#if ENABLE_EXTENDED_SELECTION + virtual void on_render(const GLCanvas3D::Selection& selection) const; + virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const; +#else virtual void on_render(const BoundingBoxf3& box) const; virtual void on_render_for_picking(const BoundingBoxf3& box) const; +#endif // ENABLE_EXTENDED_SELECTION private: void render_grabbers_connection(unsigned int id_1, unsigned int id_2) const; @@ -344,10 +398,19 @@ public: protected: virtual bool on_init(); +#if ENABLE_EXTENDED_SELECTION + virtual void on_start_dragging(const GLCanvas3D::Selection& selection); +#else virtual void on_start_dragging(const BoundingBoxf3& box); +#endif // ENABLE_EXTENDED_SELECTION virtual void on_update(const Linef3& mouse_ray); +#if ENABLE_EXTENDED_SELECTION + virtual void on_render(const GLCanvas3D::Selection& selection) const; + virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const; +#else virtual void on_render(const BoundingBoxf3& box) const; virtual void on_render_for_picking(const BoundingBoxf3& box) const; +#endif // ENABLE_EXTENDED_SELECTION private: double calc_projection(Axis axis, unsigned int preferred_plane_id, const Linef3& mouse_ray) const; @@ -406,10 +469,19 @@ public: protected: virtual bool on_init(); +#if ENABLE_EXTENDED_SELECTION + virtual void on_start_dragging(const GLCanvas3D::Selection& selection); +#else virtual void on_start_dragging(const BoundingBoxf3& box); +#endif // ENABLE_EXTENDED_SELECTION virtual void on_update(const Linef3& mouse_ray) {} +#if ENABLE_EXTENDED_SELECTION + virtual void on_render(const GLCanvas3D::Selection& selection) const; + virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const; +#else virtual void on_render(const BoundingBoxf3& box) const; virtual void on_render_for_picking(const BoundingBoxf3& box) const; +#endif // ENABLE_EXTENDED_SELECTION virtual void on_set_state() { if (m_state == On && is_plane_update_necessary()) From b413cf4ef9828516daf4c151e453971d4870e999 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Mon, 15 Oct 2018 11:39:48 +0200 Subject: [PATCH 099/186] Fixed OSX compilation : GetStringSelection for PresetComboBox is changed to GetString(GetSelection) --- src/slic3r/GUI/Plater.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 6bae93b958..f22b700743 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1512,8 +1512,17 @@ void Plater::priv::on_select_preset(wxCommandEvent &evt) auto idx = combo->get_extruder_idx(); + //! Because of The MSW and GTK version of wxBitmapComboBox derived from wxComboBox, + //! but the OSX version derived from wxOwnerDrawnCombo. + //! So, to get selected string we do + //! combo->GetString(combo->GetSelection()) + //! instead of + //! combo->GetStringSelection().ToStdString()); + + std::string selected_string = combo->GetString(combo->GetSelection()).ToUTF8().data(); + if (preset_type == Preset::TYPE_FILAMENT) { - wxGetApp().preset_bundle->set_filament_preset(idx, combo->GetStringSelection().ToStdString()); + wxGetApp().preset_bundle->set_filament_preset(idx, selected_string); } // TODO: ? @@ -1524,7 +1533,7 @@ void Plater::priv::on_select_preset(wxCommandEvent &evt) else { for (Tab* tab : wxGetApp().tabs_list) { if (tab->type() == preset_type) { - tab->select_preset(combo->GetStringSelection().ToStdString()); + tab->select_preset(selected_string); break; } } @@ -1532,9 +1541,9 @@ void Plater::priv::on_select_preset(wxCommandEvent &evt) // Synchronize config.ini with the current selections. wxGetApp().preset_bundle->export_selections(*wxGetApp().app_config); - // TODO: - // # get new config and generate on_config_change() event for updating plater and other things - // $self->on_config_change(wxTheApp->{preset_bundle}->full_config); + // update plater with new config + auto config = wxGetApp().preset_bundle->full_config(); + wxGetApp().plater()->on_config_change(&config); } void Plater::priv::on_progress_event() From 27fd49d45923aebae959c7eaa3e30a5613aa88ad Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Mon, 15 Oct 2018 13:22:36 +0200 Subject: [PATCH 100/186] New selection -> Improved gizmo scale rendering and behavior --- src/slic3r/GUI/GLCanvas3D.cpp | 8 ++++--- src/slic3r/GUI/GLCanvas3D.hpp | 2 ++ src/slic3r/GUI/GLGizmo.cpp | 43 ++++++++++++++++++++++++----------- src/slic3r/GUI/GLGizmo.hpp | 6 +++++ 4 files changed, 43 insertions(+), 16 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 25b779d86f..42b1354483 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1138,6 +1138,7 @@ GLCanvas3D::Selection::VolumeCache::VolumeCache() , m_scaling_factor(Vec3d::Ones()) { m_rotation_matrix = Transform3d::Identity(); + m_scale_matrix = Transform3d::Identity(); } GLCanvas3D::Selection::VolumeCache::VolumeCache(const Vec3d& position, const Vec3d& rotation, const Vec3d& scaling_factor) @@ -1146,6 +1147,7 @@ GLCanvas3D::Selection::VolumeCache::VolumeCache(const Vec3d& position, const Vec , m_scaling_factor(scaling_factor) { m_rotation_matrix = Geometry::assemble_transform(Vec3d::Zero(), m_rotation); + m_scale_matrix = Geometry::assemble_transform(Vec3d::Zero(), Vec3d::Zero(), m_scaling_factor); } GLCanvas3D::Selection::Selection() @@ -1415,8 +1417,8 @@ void GLCanvas3D::Selection::rotate(const Vec3d& rotation) (*m_volumes)[i]->set_rotation(rotation); else { - Eigen::Matrix new_matrix = (m * m_cache.volumes_data[i].get_rotation_matrix()).matrix().block(0, 0, 3, 3); - Vec3d new_rotation = Geometry::extract_euler_angles(new_matrix); + // extracts rotations from the composed transformation + Vec3d new_rotation = Geometry::extract_euler_angles(m * m_cache.volumes_data[i].get_rotation_matrix()); (*m_volumes)[i]->set_offset(m_cache.dragging_center + m * (m_cache.volumes_data[i].get_position() - m_cache.dragging_center)); (*m_volumes)[i]->set_rotation(new_rotation); @@ -1443,7 +1445,7 @@ void GLCanvas3D::Selection::scale(const Vec3d& scale) (*m_volumes)[i]->set_scaling_factor(scale); else { - Eigen::Matrix new_matrix = (m * m_cache.volumes_data[i].get_rotation_matrix()).matrix().block(0, 0, 3, 3); + Eigen::Matrix new_matrix = (m * m_cache.volumes_data[i].get_scale_matrix()).matrix().block(0, 0, 3, 3); // extracts scaling factors from the composed transformation Vec3d new_scale(new_matrix.col(0).norm(), new_matrix.col(1).norm(), new_matrix.col(2).norm()); diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 9e34eb23d8..a6d84eaa34 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -411,6 +411,7 @@ public: Vec3d m_rotation; Vec3d m_scaling_factor; Transform3d m_rotation_matrix; + Transform3d m_scale_matrix; public: VolumeCache(); @@ -420,6 +421,7 @@ public: const Vec3d& get_rotation() const { return m_rotation; } const Vec3d& get_scaling_factor() const { return m_scaling_factor; } const Transform3d& get_rotation_matrix() const { return m_rotation_matrix; } + const Transform3d& get_scale_matrix() const { return m_scale_matrix; } }; typedef std::map VolumesCache; diff --git a/src/slic3r/GUI/GLGizmo.cpp b/src/slic3r/GUI/GLGizmo.cpp index 2d5e8a64e1..415a928222 100644 --- a/src/slic3r/GUI/GLGizmo.cpp +++ b/src/slic3r/GUI/GLGizmo.cpp @@ -761,7 +761,9 @@ void GLGizmoRotate3D::on_render(const BoundingBoxf3& box) const #endif // ENABLE_EXTENDED_SELECTION const float GLGizmoScale3D::Offset = 5.0f; +#if !ENABLE_EXTENDED_SELECTION const Vec3d GLGizmoScale3D::OffsetVec = (double)GLGizmoScale3D::Offset * Vec3d::Ones(); +#endif // !ENABLE_EXTENDED_SELECTION GLGizmoScale3D::GLGizmoScale3D(GLCanvas3D& parent) : GLGizmoBase(parent) @@ -814,9 +816,10 @@ void GLGizmoScale3D::on_start_dragging(const BoundingBoxf3& box) { m_starting_drag_position = m_grabbers[m_hover_id].center; #if ENABLE_EXTENDED_SELECTION - const BoundingBoxf3& box = selection.get_bounding_box(); -#endif // ENABLE_EXTENDED_SELECTION + m_starting_box = selection.get_bounding_box(); +#else m_starting_box = BoundingBoxf3(box.min - OffsetVec, box.max + OffsetVec); +#endif // ENABLE_EXTENDED_SELECTION } } @@ -866,6 +869,7 @@ void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const BoundingBoxf3 box; Transform3d transform = Transform3d::Identity(); Vec3d angles = Vec3d::Zero(); + Transform3d rotation = Transform3d::Identity(); if (selection.is_from_single_instance()) { @@ -881,18 +885,29 @@ void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const // extract angles from transform angles = Slic3r::Geometry::extract_euler_angles(transform); + + // set rotation-only component of transform + rotation = Geometry::assemble_transform(Vec3d::Zero(), angles); } else box = selection.get_bounding_box(); + + m_box = box; +#else + m_box = BoundingBoxf3(box.min - OffsetVec, box.max + OffsetVec); #endif // ENABLE_EXTENDED_SELECTION - m_box = BoundingBoxf3(box.min - OffsetVec, box.max + OffsetVec); const Vec3d& center = m_box.center(); +#if ENABLE_EXTENDED_SELECTION + Vec3d offset_x = rotation * Vec3d((double)Offset, 0.0, 0.0); + Vec3d offset_y = rotation * Vec3d(0.0, (double)Offset, 0.0); + Vec3d offset_z = rotation * Vec3d(0.0, 0.0, (double)Offset); +#endif // ENABLE_EXTENDED_SELECTION // x axis #if ENABLE_EXTENDED_SELECTION - m_grabbers[0].center = transform * Vec3d(m_box.min(0), center(1), center(2)); - m_grabbers[1].center = transform * Vec3d(m_box.max(0), center(1), center(2)); + m_grabbers[0].center = transform * Vec3d(m_box.min(0), center(1), center(2)) - offset_x; + m_grabbers[1].center = transform * Vec3d(m_box.max(0), center(1), center(2)) + offset_x; #else m_grabbers[0].center = Vec3d(m_box.min(0), center(1), center(2)); m_grabbers[1].center = Vec3d(m_box.max(0), center(1), center(2)); @@ -902,8 +917,8 @@ void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const // y axis #if ENABLE_EXTENDED_SELECTION - m_grabbers[2].center = transform * Vec3d(center(0), m_box.min(1), center(2)); - m_grabbers[3].center = transform * Vec3d(center(0), m_box.max(1), center(2)); + m_grabbers[2].center = transform * Vec3d(center(0), m_box.min(1), center(2)) - offset_y; + m_grabbers[3].center = transform * Vec3d(center(0), m_box.max(1), center(2)) + offset_y; #else m_grabbers[2].center = Vec3d(center(0), m_box.min(1), center(2)); m_grabbers[3].center = Vec3d(center(0), m_box.max(1), center(2)); @@ -913,8 +928,8 @@ void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const // z axis #if ENABLE_EXTENDED_SELECTION - m_grabbers[4].center = transform * Vec3d(center(0), center(1), m_box.min(2)); - m_grabbers[5].center = transform * Vec3d(center(0), center(1), m_box.max(2)); + m_grabbers[4].center = transform * Vec3d(center(0), center(1), m_box.min(2)) - offset_z; + m_grabbers[5].center = transform * Vec3d(center(0), center(1), m_box.max(2)) + offset_z; #else m_grabbers[4].center = Vec3d(center(0), center(1), m_box.min(2)); m_grabbers[5].center = Vec3d(center(0), center(1), m_box.max(2)); @@ -924,10 +939,10 @@ void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const // uniform #if ENABLE_EXTENDED_SELECTION - m_grabbers[6].center = transform * Vec3d(m_box.min(0), m_box.min(1), center(2)); - m_grabbers[7].center = transform * Vec3d(m_box.max(0), m_box.min(1), center(2)); - m_grabbers[8].center = transform * Vec3d(m_box.max(0), m_box.max(1), center(2)); - m_grabbers[9].center = transform * Vec3d(m_box.min(0), m_box.max(1), center(2)); + m_grabbers[6].center = transform * Vec3d(m_box.min(0), m_box.min(1), center(2)) - offset_x - offset_y; + m_grabbers[7].center = transform * Vec3d(m_box.max(0), m_box.min(1), center(2)) + offset_x - offset_y; + m_grabbers[8].center = transform * Vec3d(m_box.max(0), m_box.max(1), center(2)) + offset_x + offset_y; + m_grabbers[9].center = transform * Vec3d(m_box.min(0), m_box.max(1), center(2)) - offset_x + offset_y; #else m_grabbers[6].center = Vec3d(m_box.min(0), m_box.min(1), center(2)); m_grabbers[7].center = Vec3d(m_box.max(0), m_box.min(1), center(2)); @@ -1083,7 +1098,9 @@ void GLGizmoScale3D::do_scale_z(const Linef3& mouse_ray) void GLGizmoScale3D::do_scale_uniform(const Linef3& mouse_ray) { Vec3d center = m_starting_box.center(); +#if !ENABLE_EXTENDED_SELECTION center(2) = m_box.min(2); +#endif // !ENABLE_EXTENDED_SELECTION double ratio = calc_ratio(0, mouse_ray, center); if (ratio > 0.0) diff --git a/src/slic3r/GUI/GLGizmo.hpp b/src/slic3r/GUI/GLGizmo.hpp index cb68b7e5dd..3f0599ff0b 100644 --- a/src/slic3r/GUI/GLGizmo.hpp +++ b/src/slic3r/GUI/GLGizmo.hpp @@ -314,7 +314,9 @@ protected: class GLGizmoScale3D : public GLGizmoBase { static const float Offset; +#if !ENABLE_EXTENDED_SELECTION static const Vec3d OffsetVec; +#endif // !ENABLE_EXTENDED_SELECTION mutable BoundingBoxf3 m_box; @@ -329,7 +331,11 @@ public: #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM const Vec3d& get_scale() const { return m_scale; } +#if ENABLE_EXTENDED_SELECTION + void set_scale(const Vec3d& scale) { m_starting_scale = scale; m_scale = scale; } +#else void set_scale(const Vec3d& scale) { m_starting_scale = scale; } +#endif // ENABLE_EXTENDED_SELECTION #else double get_scale_x() const { return m_scale(0); } void set_scale_x(double scale) { m_starting_scale(0) = scale; } From 317fc45522ea8d894d3046fb9988dd8276874f6d Mon Sep 17 00:00:00 2001 From: YuSanka Date: Mon, 15 Oct 2018 13:25:22 +0200 Subject: [PATCH 101/186] Fixed wxASSERT( variant.GetType() == PrusaDataViewBitmapText ); --- src/slic3r/GUI/GUI_ObjectList.cpp | 3 +-- src/slic3r/GUI/wxExtensions.cpp | 10 ++++++++-- src/slic3r/GUI/wxExtensions.hpp | 5 +++-- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 5644a0806d..4d4de489e1 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -1048,9 +1048,8 @@ void ObjectList::add_object_to_list(size_t obj_idx) int errors = stats.degenerate_facets + stats.edges_fixed + stats.facets_removed + stats.facets_added + stats.facets_reversed + stats.backwards_edges; if (errors > 0) { - const PrusaDataViewBitmapText data(item_name, m_icon_manifold_warning); wxVariant variant; - variant << data; + variant << PrusaDataViewBitmapText(item_name, m_icon_manifold_warning); m_objects_model->SetValue(variant, item, 0); } diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp index 23ad288b8a..9c9bcdaeae 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -684,8 +684,7 @@ void PrusaObjectDataViewModel::GetValue(wxVariant &variant, const wxDataViewItem switch (col) { case 0:{ - const PrusaDataViewBitmapText data(node->m_name, node->m_bmp); - variant << data; + variant << PrusaDataViewBitmapText(node->m_name, node->m_bmp); break;} case 1: variant = node->m_copy; @@ -891,7 +890,14 @@ void PrusaObjectDataViewModel::UpdateSettingsDigest(const wxDataViewItem &item, ItemChanged(item); } +//----------------------------------------------------------------------------- +// PrusaDataViewBitmapText +//----------------------------------------------------------------------------- + +wxIMPLEMENT_DYNAMIC_CLASS(PrusaDataViewBitmapText, wxObject) + IMPLEMENT_VARIANT_OBJECT(PrusaDataViewBitmapText) + // --------------------------------------------------------- // PrusaIconTextRenderer // --------------------------------------------------------- diff --git a/src/slic3r/GUI/wxExtensions.hpp b/src/slic3r/GUI/wxExtensions.hpp index 33315880ff..43e5756a42 100644 --- a/src/slic3r/GUI/wxExtensions.hpp +++ b/src/slic3r/GUI/wxExtensions.hpp @@ -184,6 +184,8 @@ public: private: wxString m_text; wxBitmap m_bmp; + + wxDECLARE_DYNAMIC_CLASS(PrusaDataViewBitmapText); }; DECLARE_VARIANT_OBJECT(PrusaDataViewBitmapText) @@ -476,7 +478,7 @@ class PrusaBitmapTextRenderer : public wxDataViewCustomRenderer public: PrusaBitmapTextRenderer( wxDataViewCellMode mode = wxDATAVIEW_CELL_INERT, int align = wxDVR_DEFAULT_ALIGNMENT): - wxDataViewCustomRenderer(wxT("wxObject"), mode, align) {} + wxDataViewCustomRenderer(wxT("PrusaDataViewBitmapText"), mode, align) {} bool SetValue(const wxVariant &value); bool GetValue(wxVariant &value) const; @@ -487,7 +489,6 @@ public: virtual bool HasEditorCtrl() const { return false; } private: -// wxDataViewIconText m_value; PrusaDataViewBitmapText m_value; }; From adf739cd454bb905715ec83718b9b7074f84138a Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Mon, 15 Oct 2018 15:21:37 +0200 Subject: [PATCH 102/186] Simplified algorithm for update of gizmo move and scale --- src/libslic3r/Technologies.hpp | 2 +- src/slic3r/GUI/GLGizmo.cpp | 82 +++++++++++++++++++++++++++++++--- src/slic3r/GUI/GLGizmo.hpp | 8 ++++ 3 files changed, 85 insertions(+), 7 deletions(-) diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index 77802d811e..0b918d7c9d 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -13,7 +13,7 @@ // Uses a unique opengl context #define ENABLE_USE_UNIQUE_GLCONTEXT (1 && ENABLE_1_42_0) // New selections -#define ENABLE_EXTENDED_SELECTION (0 && ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM) +#define ENABLE_EXTENDED_SELECTION (1 && ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM) #endif // _technologies_h_ diff --git a/src/slic3r/GUI/GLGizmo.cpp b/src/slic3r/GUI/GLGizmo.cpp index 415a928222..b1e7473aa9 100644 --- a/src/slic3r/GUI/GLGizmo.cpp +++ b/src/slic3r/GUI/GLGizmo.cpp @@ -23,6 +23,7 @@ static const float AXES_COLOR[3][3] = { { 1.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f namespace Slic3r { namespace GUI { +#if !ENABLE_EXTENDED_SELECTION // returns the intersection of the given ray with the plane parallel to plane XY and passing through the given center // coordinates are local to the plane Vec3d intersection_on_plane_xy(const Linef3& ray, const Vec3d& center) @@ -105,7 +106,8 @@ unsigned int select_best_plane(const Vec3d& unit_vector, unsigned int preferred_ return ret; } - +#endif // !ENABLE_EXTENDED_SELECTION + const float GLGizmoBase::Grabber::SizeFactor = 0.025f; const float GLGizmoBase::Grabber::MinHalfSize = 1.5f; const float GLGizmoBase::Grabber::DraggingScaleFactor = 1.25f; @@ -1065,7 +1067,11 @@ void GLGizmoScale3D::render_grabbers_connection(unsigned int id_1, unsigned int void GLGizmoScale3D::do_scale_x(const Linef3& mouse_ray) { +#if ENABLE_EXTENDED_SELECTION + double ratio = calc_ratio(mouse_ray); +#else double ratio = calc_ratio(1, mouse_ray, m_starting_box.center()); +#endif // ENABLE_EXTENDED_SELECTION if (ratio > 0.0) m_scale(0) = m_starting_scale(0) * ratio; @@ -1073,7 +1079,11 @@ void GLGizmoScale3D::do_scale_x(const Linef3& mouse_ray) void GLGizmoScale3D::do_scale_y(const Linef3& mouse_ray) { +#if ENABLE_EXTENDED_SELECTION + double ratio = calc_ratio(mouse_ray); +#else double ratio = calc_ratio(2, mouse_ray, m_starting_box.center()); +#endif // ENABLE_EXTENDED_SELECTION if (ratio > 0.0) #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM @@ -1085,7 +1095,11 @@ void GLGizmoScale3D::do_scale_y(const Linef3& mouse_ray) void GLGizmoScale3D::do_scale_z(const Linef3& mouse_ray) { +#if ENABLE_EXTENDED_SELECTION + double ratio = calc_ratio(mouse_ray); +#else double ratio = calc_ratio(1, mouse_ray, m_starting_box.center()); +#endif // ENABLE_EXTENDED_SELECTION if (ratio > 0.0) #if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM @@ -1097,16 +1111,46 @@ void GLGizmoScale3D::do_scale_z(const Linef3& mouse_ray) void GLGizmoScale3D::do_scale_uniform(const Linef3& mouse_ray) { +#if ENABLE_EXTENDED_SELECTION + double ratio = calc_ratio(mouse_ray); +#else Vec3d center = m_starting_box.center(); -#if !ENABLE_EXTENDED_SELECTION center(2) = m_box.min(2); -#endif // !ENABLE_EXTENDED_SELECTION double ratio = calc_ratio(0, mouse_ray, center); +#endif // ENABLE_EXTENDED_SELECTION if (ratio > 0.0) m_scale = m_starting_scale * ratio; } +#if ENABLE_EXTENDED_SELECTION +double GLGizmoScale3D::calc_ratio(const Linef3& mouse_ray) const +{ + double ratio = 0.0; + + // vector from the center to the starting position + Vec3d starting_vec = m_starting_drag_position - m_starting_box.center(); + double len_starting_vec = starting_vec.norm(); + if (len_starting_vec != 0.0) + { + Vec3d mouse_dir = mouse_ray.unit_vector(); + // finds the intersection of the mouse ray with the plane parallel to the camera viewport and passing throught the starting position + // use ray-plane intersection see i.e. https://en.wikipedia.org/wiki/Line%E2%80%93plane_intersection algebric form + // in our case plane normal and ray direction are the same (orthogonal view) + // when moving to perspective camera the negative z unit axis of the camera needs to be transformed in world space and used as plane normal + Vec3d inters = mouse_ray.a + (m_starting_drag_position - mouse_ray.a).dot(mouse_dir) / mouse_dir.squaredNorm() * mouse_dir; + // vector from the starting position to the found intersection + Vec3d inters_vec = inters - m_starting_drag_position; + + // finds projection of the vector along the staring direction + double proj = inters_vec.dot(starting_vec.normalized()); + + return (len_starting_vec + proj) / len_starting_vec; + } + + return ratio; +} +#else double GLGizmoScale3D::calc_ratio(unsigned int preferred_plane_id, const Linef3& mouse_ray, const Vec3d& center) const { double ratio = 0.0; @@ -1142,6 +1186,7 @@ double GLGizmoScale3D::calc_ratio(unsigned int preferred_plane_id, const Linef3& return ratio; } +#endif // ENABLE_EXTENDED_SELECTION const double GLGizmoMove3D::Offset = 10.0; @@ -1209,11 +1254,11 @@ void GLGizmoMove3D::on_update(const Linef3& mouse_ray) { #if ENABLE_EXTENDED_SELECTION if (m_hover_id == 0) - m_displacement(0) = calc_projection(X, 1, mouse_ray) - (m_starting_drag_position(0) - m_starting_box_center(0)); + m_displacement(0) = calc_projection(mouse_ray); else if (m_hover_id == 1) - m_displacement(1) = calc_projection(Y, 2, mouse_ray) - (m_starting_drag_position(1) - m_starting_box_center(1)); + m_displacement(1) = calc_projection(mouse_ray); else if (m_hover_id == 2) - m_displacement(2) = calc_projection(Z, 1, mouse_ray) - (m_starting_drag_position(2) - m_starting_box_bottom_center(2)); + m_displacement(2) = calc_projection(mouse_ray); #else if (m_hover_id == 0) m_position(0) = 2.0 * m_starting_box_center(0) + calc_projection(X, 1, mouse_ray) - m_starting_drag_position(0); @@ -1315,6 +1360,30 @@ void GLGizmoMove3D::on_render_for_picking(const BoundingBoxf3& box) const } #endif // ENABLE_EXTENDED_SELECTION +#if ENABLE_EXTENDED_SELECTION +double GLGizmoMove3D::calc_projection(const Linef3& mouse_ray) const +{ + double projection = 0.0; + + Vec3d starting_vec = m_starting_drag_position - m_starting_box_center; + double len_starting_vec = starting_vec.norm(); + if (len_starting_vec != 0.0) + { + Vec3d mouse_dir = mouse_ray.unit_vector(); + // finds the intersection of the mouse ray with the plane parallel to the camera viewport and passing throught the starting position + // use ray-plane intersection see i.e. https://en.wikipedia.org/wiki/Line%E2%80%93plane_intersection algebric form + // in our case plane normal and ray direction are the same (orthogonal view) + // when moving to perspective camera the negative z unit axis of the camera needs to be transformed in world space and used as plane normal + Vec3d inters = mouse_ray.a + (m_starting_drag_position - mouse_ray.a).dot(mouse_dir) / mouse_dir.squaredNorm() * mouse_dir; + // vector from the starting position to the found intersection + Vec3d inters_vec = inters - m_starting_drag_position; + + // finds projection of the vector along the staring direction + projection = inters_vec.dot(starting_vec.normalized()); + } + return projection; +} +#else double GLGizmoMove3D::calc_projection(Axis axis, unsigned int preferred_plane_id, const Linef3& mouse_ray) const { double projection = 0.0; @@ -1350,6 +1419,7 @@ double GLGizmoMove3D::calc_projection(Axis axis, unsigned int preferred_plane_id return projection; } +#endif // ENABLE_EXTENDED_SELECTION GLGizmoFlatten::GLGizmoFlatten(GLCanvas3D& parent) : GLGizmoBase(parent) diff --git a/src/slic3r/GUI/GLGizmo.hpp b/src/slic3r/GUI/GLGizmo.hpp index 3f0599ff0b..8babd21e5d 100644 --- a/src/slic3r/GUI/GLGizmo.hpp +++ b/src/slic3r/GUI/GLGizmo.hpp @@ -376,7 +376,11 @@ private: void do_scale_z(const Linef3& mouse_ray); void do_scale_uniform(const Linef3& mouse_ray); +#if ENABLE_EXTENDED_SELECTION + double calc_ratio(const Linef3& mouse_ray) const; +#else double calc_ratio(unsigned int preferred_plane_id, const Linef3& mouse_ray, const Vec3d& center) const; +#endif // ENABLE_EXTENDED_SELECTION }; class GLGizmoMove3D : public GLGizmoBase @@ -419,7 +423,11 @@ protected: #endif // ENABLE_EXTENDED_SELECTION private: +#if ENABLE_EXTENDED_SELECTION + double calc_projection(const Linef3& mouse_ray) const; +#else double calc_projection(Axis axis, unsigned int preferred_plane_id, const Linef3& mouse_ray) const; +#endif // ENABLE_EXTENDED_SELECTION }; class GLGizmoFlatten : public GLGizmoBase From 0b0e65636fc696bcf9416ccccbec5f86eefae987 Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Fri, 12 Oct 2018 14:19:08 +0200 Subject: [PATCH 103/186] Build improvements: symlink resources properly with Visual Studio Convert dependencies into a CMake build script in the `deps` dir --- CMakeLists.txt | 15 +--- deps/CMakeLists.txt | 31 +++++++ deps/deps-unix-static.cmake | 133 ++++++++++++++++++++++++++++ deps/deps-windows.cmake | 93 ++++++++++++++++++++ deps/wxwidgets-pngprefix.h | 168 ++++++++++++++++++++++++++++++++++++ src/CMakeLists.txt | 33 +++++++ xs/CMakeLists.txt | 5 -- 7 files changed, 459 insertions(+), 19 deletions(-) create mode 100644 deps/CMakeLists.txt create mode 100644 deps/deps-unix-static.cmake create mode 100644 deps/deps-windows.cmake create mode 100644 deps/wxwidgets-pngprefix.h diff --git a/CMakeLists.txt b/CMakeLists.txt index b0f908e906..62c545fe14 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -215,7 +215,7 @@ if (NOT GLEW_FOUND) endif () include_directories(${GLEW_INCLUDE_DIRS}) -# Resources and l10n +# l10n set(L10N_DIR "${SLIC3R_RESOURCES_DIR}/localization") add_custom_target(pot # FIXME: file list stale @@ -225,19 +225,6 @@ add_custom_target(pot WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} COMMENT "Generate pot file from strings in the source tree" ) -if (MSVC) - file(TO_NATIVE_PATH "${CMAKE_BINARY_DIR}/src/resources" WIN_RESOURCES_SYMLINK) - add_custom_target(resources_symlink ALL - COMMAND if not exist "${WIN_RESOURCES_SYMLINK}" ( mklink /J "${WIN_RESOURCES_SYMLINK}" "${SLIC3R_RESOURCES_DIR_WIN}" ) - VERBATIM - ) -else () - add_custom_target(resources_symlink ALL - COMMAND ln -sf "${SLIC3R_RESOURCES_DIR}" "${CMAKE_BINARY_DIR}/resources" - VERBATIM - ) -endif() - # libslic3r, Slic3r GUI and the slic3r executable. add_subdirectory(src) diff --git a/deps/CMakeLists.txt b/deps/CMakeLists.txt new file mode 100644 index 0000000000..22d3f72362 --- /dev/null +++ b/deps/CMakeLists.txt @@ -0,0 +1,31 @@ +project(Slic3r-deps) +cmake_minimum_required(VERSION 3.2) + +include(ExternalProject) + +include(ProcessorCount) +ProcessorCount(NPROC) +if (NPROC EQUAL 0) + set(NPROC 1) +endif () + +if (MSVC) + set(DEPS_BITS 64) + set(DESTDIR "${CMAKE_CURRENT_BINARY_DIR}/destdir-64") + include("deps-windows.cmake") + set(DEPS_BITS 32) + set(DESTDIR "${CMAKE_CURRENT_BINARY_DIR}/destdir-32") + include("deps-windows.cmake") + + add_custom_target(deps ALL + DEPENDS dep_boost_64 dep_tbb_64 dep_libcurl_64 dep_wxwidgets_64 + # dep_boost_32 dep_tbb_32 dep_libcurl_32 dep_wxwidgets_32 + ) +else () + set(DESTDIR "${CMAKE_CURRENT_BINARY_DIR}/destdir") + include("deps-unix-static.cmake") + + add_custom_target(deps ALL + DEPENDS dep_boost dep_tbb dep_libcurl dep_wxwidgets + ) +endif() diff --git a/deps/deps-unix-static.cmake b/deps/deps-unix-static.cmake new file mode 100644 index 0000000000..6158845189 --- /dev/null +++ b/deps/deps-unix-static.cmake @@ -0,0 +1,133 @@ + +ExternalProject_Add(dep_boost + EXCLUDE_FROM_ALL 1 + URL "https://dl.bintray.com/boostorg/release/1.66.0/source/boost_1_66_0.tar.gz" + URL_HASH SHA256=bd0df411efd9a585e5a2212275f8762079fed8842264954675a4fddc46cfcf60 + BUILD_IN_SOURCE 1 + CONFIGURE_COMMAND ./bootstrap.sh + --with-libraries=system,filesystem,thread,log,locale,regex + "--prefix=${INSTALL_DIR}/usr/local" + BUILD_COMMAND ./b2 + -j ${NPROC} + link=static + variant=release + threading=multi + boost.locale.icu=off + cxxflags=-fPIC cflags=-fPIC + install + INSTALL_COMMAND "" # b2 does that already + LOG_CONFIGURE 1 + LOG_BUILD 1 +) + +ExternalProject_Add(dep_tbb + EXCLUDE_FROM_ALL 1 + URL "https://github.com/wjakob/tbb/archive/a0dc9bf76d0120f917b641ed095360448cabc85b.tar.gz" + URL_HASH SHA256=0545cb6033bd1873fcae3ea304def720a380a88292726943ae3b9b207f322efe + BUILD_IN_SOURCE 1 + CMAKE_ARGS -DTBB_BUILD_SHARED=OFF + -DTBB_BUILD_TESTS=OFF + -DCMAKE_POSITION_INDEPENDENT_CODE=ON + INSTALL_COMMAND make install "DESTDIR=${INSTALL_DIR}" + LOG_CONFIGURE 1 + LOG_BUILD 1 + LOG_INSTALL 1 +) + +ExternalProject_Add(dep_libopenssl + EXCLUDE_FROM_ALL 1 + URL "https://github.com/openssl/openssl/archive/OpenSSL_1_1_0g.tar.gz" + URL_HASH SHA256=8e9516b8635bb9113c51a7b5b27f9027692a56b104e75b709e588c3ffd6a0422 + BUILD_IN_SOURCE 1 + CONFIGURE_COMMAND ./config + "--prefix=${INSTALL_DIR}/usr/local" + no-shared + no-ssl3-method + no-dynamic-engine + -Wa,--noexecstack + BUILD_COMMAND make depend && make "-j${NPROC}" + INSTALL_COMMAND make install_sw + LOG_CONFIGURE 1 + LOG_BUILD 1 + LOG_INSTALL 1 +) + +ExternalProject_Add(dep_libcurl + EXCLUDE_FROM_ALL 1 + DEPENDS dep_libopenssl + URL "https://curl.haxx.se/download/curl-7.58.0.tar.gz" + URL_HASH SHA256=cc245bf9a1a42a45df491501d97d5593392a03f7b4f07b952793518d97666115 + BUILD_IN_SOURCE 1 + CONFIGURE_COMMAND ./configure + --enable-static + --disable-shared + "--with-ssl=${DESTDIR}/usr/local" + --with-pic + --enable-ipv6 + --enable-versioned-symbols + --enable-threaded-resolver + --with-random=/dev/urandom + --with-ca-bundle=/etc/ssl/certs/ca-certificates.crt + --disable-ldap + --disable-ldaps + --disable-manual + --disable-rtsp + --disable-dict + --disable-telnet + --disable-pop3 + --disable-imap + --disable-smb + --disable-smtp + --disable-gopher + --disable-crypto-auth + --without-gssapi + --without-libpsl + --without-libidn2 + --without-gnutls + --without-polarssl + --without-mbedtls + --without-cyassl + --without-nss + --without-axtls + --without-brotli + --without-libmetalink + --without-libssh + --without-libssh2 + --without-librtmp + --without-nghttp2 + --without-zsh-functions-dir + BUILD_COMMAND make "-j${NPROC}" + INSTALL_COMMAND make install "DESTDIR=${INSTALL_DIR}" + LOG_CONFIGURE 1 + LOG_BUILD 1 + LOG_INSTALL 1 +) + +ExternalProject_Add(dep_wxwidgets + EXCLUDE_FROM_ALL 1 + 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 + CONFIGURE_COMMAND ./configure + "--prefix=${INSTALL_DIR}/usr/local" + --disable-shared + --with-gtk=2 + --with-opengl + --enable-unicode + --enable-graphics_ctx + --with-regex=builtin + --with-libpng=builtin + --with-libxpm=builtin + --with-libjpeg=builtin + --with-libtiff=builtin + --with-zlib=builtin + --with-expat=builtin + --disable-precomp-headers + --enable-debug_info + --enable-debug_gdb + BUILD_COMMAND make "-j${NPROC}" && make -C locale allmo + INSTALL_COMMAND make install + LOG_CONFIGURE 1 + LOG_BUILD 1 + LOG_INSTALL 1 +) diff --git a/deps/deps-windows.cmake b/deps/deps-windows.cmake new file mode 100644 index 0000000000..834bdb9e3d --- /dev/null +++ b/deps/deps-windows.cmake @@ -0,0 +1,93 @@ + +# NB: I haven't enabled any of the LOG_xxx options because they tend to generate bogus build files, +# especially with compound commands like `cd foo && bar`. + +ExternalProject_Add("dep_boost_${DEPS_BITS}" + EXCLUDE_FROM_ALL 1 + URL "https://dl.bintray.com/boostorg/release/1.66.0/source/boost_1_66_0.tar.gz" + URL_HASH SHA256=bd0df411efd9a585e5a2212275f8762079fed8842264954675a4fddc46cfcf60 + BUILD_IN_SOURCE 1 + CONFIGURE_COMMAND bootstrap.bat + BUILD_COMMAND b2.exe + -j "${NPROC}" + --with-system + --with-filesystem + --with-thread + --with-log + --with-locale + --with-regex + "--prefix=${DESTDIR}/usr/local" + "address-model=${DEPS_BITS}" + toolset=msvc-12.0 + link=static + variant=release + threading=multi + boost.locale.icu=off + install + INSTALL_COMMAND "" # b2 does that already +) + + +if ($DEPS_BITS EQUAL 32) + set(DEP_TBB_GEN "Visual Studio 12") +else () + set(DEP_TBB_GEN "Visual Studio 12 Win64") +endif () + +ExternalProject_Add("dep_tbb_${DEPS_BITS}" + EXCLUDE_FROM_ALL 1 + URL "https://github.com/wjakob/tbb/archive/a0dc9bf76d0120f917b641ed095360448cabc85b.tar.gz" + URL_HASH SHA256=0545cb6033bd1873fcae3ea304def720a380a88292726943ae3b9b207f322efe + CMAKE_GENERATOR "${DEP_TBB_GEN}" + CMAKE_ARGS + -DCMAKE_CONFIGURATION_TYPES=Release + -DTBB_BUILD_SHARED=OFF + -DTBB_BUILD_TESTS=OFF + "-DCMAKE_INSTALL_PREFIX:PATH=${DESTDIR}\\usr\\local" + BUILD_COMMAND msbuild /P:Configuration=Release INSTALL.vcxproj + INSTALL_COMMAND "" +) + + +if ($DEPS_BITS EQUAL 32) + set(DEP_LIBCURL_TARGET "x86") +else () + set(DEP_LIBCURL_TARGET "x64") +endif () + +ExternalProject_Add("dep_libcurl_${DEPS_BITS}" + EXCLUDE_FROM_ALL 1 + URL "https://curl.haxx.se/download/curl-7.58.0.tar.gz" + URL_HASH SHA256=cc245bf9a1a42a45df491501d97d5593392a03f7b4f07b952793518d97666115 + BUILD_IN_SOURCE 1 + CONFIGURE_COMMAND "" + BUILD_COMMAND cd winbuild && nmake /f Makefile.vc mode=static VC=12 GEN_PDB=yes DEBUG=no "MACHINE=${DEP_LIBCURL_TARGET}" + INSTALL_COMMAND cd builds\\libcurl-*-winssl + && "${CMAKE_COMMAND}" -E copy_directory include "${DESTDIR}\\usr\\local\\include" + && "${CMAKE_COMMAND}" -E copy_directory lib "${DESTDIR}\\usr\\local\\lib" +) + +if ($DEPS_BITS EQUAL 32) + set(DEP_WXWIDGETS_TARGET "") + set(DEP_WXWIDGETS_LIBDIR "vc_lib") +else () + set(DEP_WXWIDGETS_TARGET "TARGET_CPU=X64") + set(DEP_WXWIDGETS_LIBDIR "vc_x64_lib") +endif () + +ExternalProject_Add("dep_wxwidgets_${DEPS_BITS}" + EXCLUDE_FROM_ALL 1 + 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}" +) diff --git a/deps/wxwidgets-pngprefix.h b/deps/wxwidgets-pngprefix.h new file mode 100644 index 0000000000..de62e310bd --- /dev/null +++ b/deps/wxwidgets-pngprefix.h @@ -0,0 +1,168 @@ +// Patched in Slic3r: These two were missing: +#define png_write_eXIf wx_png_write_eXIf +#define png_handle_eXIf wx_png_handle_eXIf + +#define png_sRGB_table wx_png_sRGB_table +#define png_sRGB_base wx_png_sRGB_base +#define png_sRGB_delta wx_png_sRGB_delta +#define png_zstream_error wx_png_zstream_error +#define png_free_buffer_list wx_png_free_buffer_list +#define png_fixed wx_png_fixed +#define png_user_version_check wx_png_user_version_check +#define png_malloc_base wx_png_malloc_base +#define png_malloc_array wx_png_malloc_array +#define png_realloc_array wx_png_realloc_array +#define png_create_png_struct wx_png_create_png_struct +#define png_destroy_png_struct wx_png_destroy_png_struct +#define png_free_jmpbuf wx_png_free_jmpbuf +#define png_zalloc wx_png_zalloc +#define png_zfree wx_png_zfree +#define png_default_read_data wx_png_default_read_data +#define png_push_fill_buffer wx_png_push_fill_buffer +#define png_default_write_data wx_png_default_write_data +#define png_default_flush wx_png_default_flush +#define png_reset_crc wx_png_reset_crc +#define png_write_data wx_png_write_data +#define png_read_sig wx_png_read_sig +#define png_read_chunk_header wx_png_read_chunk_header +#define png_read_data wx_png_read_data +#define png_crc_read wx_png_crc_read +#define png_crc_finish wx_png_crc_finish +#define png_crc_error wx_png_crc_error +#define png_calculate_crc wx_png_calculate_crc +#define png_flush wx_png_flush +#define png_write_IHDR wx_png_write_IHDR +#define png_write_PLTE wx_png_write_PLTE +#define png_compress_IDAT wx_png_compress_IDAT +#define png_write_IEND wx_png_write_IEND +#define png_write_gAMA_fixed wx_png_write_gAMA_fixed +#define png_write_sBIT wx_png_write_sBIT +#define png_write_cHRM_fixed wx_png_write_cHRM_fixed +#define png_write_sRGB wx_png_write_sRGB +#define png_write_iCCP wx_png_write_iCCP +#define png_write_sPLT wx_png_write_sPLT +#define png_write_tRNS wx_png_write_tRNS +#define png_write_bKGD wx_png_write_bKGD +#define png_write_hIST wx_png_write_hIST +#define png_write_tEXt wx_png_write_tEXt +#define png_write_zTXt wx_png_write_zTXt +#define png_write_iTXt wx_png_write_iTXt +#define png_set_text_2 wx_png_set_text_2 +#define png_write_oFFs wx_png_write_oFFs +#define png_write_pCAL wx_png_write_pCAL +#define png_write_pHYs wx_png_write_pHYs +#define png_write_tIME wx_png_write_tIME +#define png_write_sCAL_s wx_png_write_sCAL_s +#define png_write_finish_row wx_png_write_finish_row +#define png_write_start_row wx_png_write_start_row +#define png_combine_row wx_png_combine_row +#define png_do_read_interlace wx_png_do_read_interlace +#define png_do_write_interlace wx_png_do_write_interlace +#define png_read_filter_row wx_png_read_filter_row +#define png_write_find_filter wx_png_write_find_filter +#define png_read_IDAT_data wx_png_read_IDAT_data +#define png_read_finish_IDAT wx_png_read_finish_IDAT +#define png_read_finish_row wx_png_read_finish_row +#define png_read_start_row wx_png_read_start_row +#define png_zlib_inflate wx_png_zlib_inflate +#define png_read_transform_info wx_png_read_transform_info +#define png_do_strip_channel wx_png_do_strip_channel +#define png_do_swap wx_png_do_swap +#define png_do_packswap wx_png_do_packswap +#define png_do_invert wx_png_do_invert +#define png_do_bgr wx_png_do_bgr +#define png_handle_IHDR wx_png_handle_IHDR +#define png_handle_PLTE wx_png_handle_PLTE +#define png_handle_IEND wx_png_handle_IEND +#define png_handle_bKGD wx_png_handle_bKGD +#define png_handle_cHRM wx_png_handle_cHRM +#define png_handle_gAMA wx_png_handle_gAMA +#define png_handle_hIST wx_png_handle_hIST +#define png_handle_iCCP wx_png_handle_iCCP +#define png_handle_iTXt wx_png_handle_iTXt +#define png_handle_oFFs wx_png_handle_oFFs +#define png_handle_pCAL wx_png_handle_pCAL +#define png_handle_pHYs wx_png_handle_pHYs +#define png_handle_sBIT wx_png_handle_sBIT +#define png_handle_sCAL wx_png_handle_sCAL +#define png_handle_sPLT wx_png_handle_sPLT +#define png_handle_sRGB wx_png_handle_sRGB +#define png_handle_tEXt wx_png_handle_tEXt +#define png_handle_tIME wx_png_handle_tIME +#define png_handle_tRNS wx_png_handle_tRNS +#define png_handle_zTXt wx_png_handle_zTXt +#define png_check_chunk_name wx_png_check_chunk_name +#define png_check_chunk_length wx_png_check_chunk_length +#define png_handle_unknown wx_png_handle_unknown +#define png_chunk_unknown_handling wx_png_chunk_unknown_handling +#define png_do_read_transformations wx_png_do_read_transformations +#define png_do_write_transformations wx_png_do_write_transformations +#define png_init_read_transformations wx_png_init_read_transformations +#define png_push_read_chunk wx_png_push_read_chunk +#define png_push_read_sig wx_png_push_read_sig +#define png_push_check_crc wx_png_push_check_crc +#define png_push_save_buffer wx_png_push_save_buffer +#define png_push_restore_buffer wx_png_push_restore_buffer +#define png_push_read_IDAT wx_png_push_read_IDAT +#define png_process_IDAT_data wx_png_process_IDAT_data +#define png_push_process_row wx_png_push_process_row +#define png_push_handle_unknown wx_png_push_handle_unknown +#define png_push_have_info wx_png_push_have_info +#define png_push_have_end wx_png_push_have_end +#define png_push_have_row wx_png_push_have_row +#define png_push_read_end wx_png_push_read_end +#define png_process_some_data wx_png_process_some_data +#define png_read_push_finish_row wx_png_read_push_finish_row +#define png_push_handle_tEXt wx_png_push_handle_tEXt +#define png_push_read_tEXt wx_png_push_read_tEXt +#define png_push_handle_zTXt wx_png_push_handle_zTXt +#define png_push_read_zTXt wx_png_push_read_zTXt +#define png_push_handle_iTXt wx_png_push_handle_iTXt +#define png_push_read_iTXt wx_png_push_read_iTXt +#define png_colorspace_set_gamma wx_png_colorspace_set_gamma +#define png_colorspace_sync_info wx_png_colorspace_sync_info +#define png_colorspace_sync wx_png_colorspace_sync +#define png_colorspace_set_chromaticities wx_png_colorspace_set_chromaticities +#define png_colorspace_set_endpoints wx_png_colorspace_set_endpoints +#define png_colorspace_set_sRGB wx_png_colorspace_set_sRGB +#define png_colorspace_set_ICC wx_png_colorspace_set_ICC +#define png_icc_check_length wx_png_icc_check_length +#define png_icc_check_header wx_png_icc_check_header +#define png_icc_check_tag_table wx_png_icc_check_tag_table +#define png_icc_set_sRGB wx_png_icc_set_sRGB +#define png_colorspace_set_rgb_coefficients wx_png_colorspace_set_rgb_coefficients +#define png_check_IHDR wx_png_check_IHDR +#define png_do_check_palette_indexes wx_png_do_check_palette_indexes +#define png_fixed_error wx_png_fixed_error +#define png_safecat wx_png_safecat +#define png_format_number wx_png_format_number +#define png_warning_parameter wx_png_warning_parameter +#define png_warning_parameter_unsigned wx_png_warning_parameter_unsigned +#define png_warning_parameter_signed wx_png_warning_parameter_signed +#define png_formatted_warning wx_png_formatted_warning +#define png_app_warning wx_png_app_warning +#define png_app_error wx_png_app_error +#define png_chunk_report wx_png_chunk_report +#define png_ascii_from_fp wx_png_ascii_from_fp +#define png_ascii_from_fixed wx_png_ascii_from_fixed +#define png_check_fp_number wx_png_check_fp_number +#define png_check_fp_string wx_png_check_fp_string +#define png_muldiv wx_png_muldiv +#define png_muldiv_warn wx_png_muldiv_warn +#define png_reciprocal wx_png_reciprocal +#define png_reciprocal2 wx_png_reciprocal2 +#define png_gamma_significant wx_png_gamma_significant +#define png_gamma_correct wx_png_gamma_correct +#define png_gamma_16bit_correct wx_png_gamma_16bit_correct +#define png_gamma_8bit_correct wx_png_gamma_8bit_correct +#define png_destroy_gamma_table wx_png_destroy_gamma_table +#define png_build_gamma_table wx_png_build_gamma_table +#define png_safe_error wx_png_safe_error +#define png_safe_warning wx_png_safe_warning +#define png_safe_execute wx_png_safe_execute +#define png_image_error wx_png_image_error +#define png_check_keyword wx_png_check_keyword + + + + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b19c5cd022..3c295ec5a0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -63,6 +63,7 @@ if(SLIC3R_GUI) else() set_target_properties(slic3r PROPERTIES OUTPUT_NAME "slic3r-console") endif() + target_link_libraries(slic3r libslic3r) if (APPLE) # add_compile_options(-stdlib=libc++) @@ -111,3 +112,35 @@ if (SLIC3R_GUI) target_link_libraries(slic3r -ldl -lGL -lGLU) endif () endif () + +# Link the resources dir to where Slic3r GUI expects it +if (MSVC) + if (CMAKE_CONFIGURATION_TYPES) + foreach (CONF ${CMAKE_CONFIGURATION_TYPES}) + file(TO_NATIVE_PATH "${CMAKE_CURRENT_BINARY_DIR}/${CONF}" WIN_CONF_OUTPUT_DIR) + file(TO_NATIVE_PATH "${CMAKE_CURRENT_BINARY_DIR}/${CONF}/resources" WIN_RESOURCES_SYMLINK) + add_custom_target("resources_symlink_${CONF}" ALL + DEPENDS slic3r + COMMAND if exist "${WIN_CONF_OUTPUT_DIR}" "(" + if not exist "${WIN_RESOURCES_SYMLINK}" "(" + mklink /J "${WIN_RESOURCES_SYMLINK}" "${SLIC3R_RESOURCES_DIR_WIN}" + ")" + ")" + VERBATIM + ) + endforeach () + else () + file(TO_NATIVE_PATH "${CMAKE_CURRENT_BINARY_DIR}" OUTPUT_DIR) + add_custom_target(resources_symlink ALL + DEPENDS slic3r + COMMAND if not exist "${WIN_RESOURCES_SYMLINK}" "(" mklink /J "${WIN_RESOURCES_SYMLINK}" "${SLIC3R_RESOURCES_DIR_WIN}" ")" + VERBATIM + ) + endif () +else () + add_custom_target(resources_symlink ALL + DEPENDS slic3r + COMMAND ln -sf "${SLIC3R_RESOURCES_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/../resources" + VERBATIM + ) +endif() diff --git a/xs/CMakeLists.txt b/xs/CMakeLists.txt index 9a08beadc7..27228dacff 100644 --- a/xs/CMakeLists.txt +++ b/xs/CMakeLists.txt @@ -207,11 +207,6 @@ install(FILES lib/Slic3r/XS.pm DESTINATION ${PERL_VENDORLIB}/Slic3r) enable_testing() get_filename_component(PERL_BIN_PATH "${PERL_EXECUTABLE}" DIRECTORY) if (MSVC) - # By default the startup project in MSVC is the 'ALL_BUILD' cmake-created project, - # but we want 'slic3r' as the startup one because debugging run command is associated with it. - # (Unfortunatelly it cannot be associated with ALL_BUILD using CMake.) - # Note: For some reason this needs to be set in the top-level CMakeLists.txt - set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT XS) set(PERL_PROVE "${PERL_BIN_PATH}/prove.bat") else () set(PERL_PROVE "${PERL_BIN_PATH}/prove") From ce86fad28a5f239bb2314651c3de7273b0dc195f Mon Sep 17 00:00:00 2001 From: YuSanka Date: Mon, 15 Oct 2018 17:18:38 +0200 Subject: [PATCH 104/186] Fixed assert "IsVisible(item)" failed in wxTreeCtrl::GetNextVisible() --- src/slic3r/GUI/Tab.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 015e03b259..023a6a67d5 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -476,6 +476,8 @@ void Tab::get_sys_and_mod_flags(const std::string& opt_key, bool& sys_page, bool void Tab::update_changed_tree_ui() { auto cur_item = m_treectrl->GetFirstVisibleItem(); + if (!m_treectrl->IsVisible(cur_item)) + return; auto selection = m_treectrl->GetItemText(m_treectrl->GetSelection()); while (cur_item){ auto title = m_treectrl->GetItemText(cur_item); From fb6c1a885c8e6511a1a8807c2a67b1259adc5824 Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Mon, 15 Oct 2018 17:28:05 +0200 Subject: [PATCH 105/186] Build: Fix deps-unix-static.cmake --- deps/CMakeLists.txt | 3 +++ deps/deps-unix-static.cmake | 24 +++++------------------- deps/deps-windows.cmake | 3 --- 3 files changed, 8 insertions(+), 22 deletions(-) diff --git a/deps/CMakeLists.txt b/deps/CMakeLists.txt index 22d3f72362..a20c7aa18c 100644 --- a/deps/CMakeLists.txt +++ b/deps/CMakeLists.txt @@ -29,3 +29,6 @@ else () DEPENDS dep_boost dep_tbb dep_libcurl dep_wxwidgets ) endif() + +# Note: I'm not using any of the LOG_xxx options in ExternalProject_Add() commands +# because they seem to generate bogus build files (possibly a bug in ExternalProject). diff --git a/deps/deps-unix-static.cmake b/deps/deps-unix-static.cmake index 6158845189..f963f53569 100644 --- a/deps/deps-unix-static.cmake +++ b/deps/deps-unix-static.cmake @@ -6,7 +6,7 @@ ExternalProject_Add(dep_boost BUILD_IN_SOURCE 1 CONFIGURE_COMMAND ./bootstrap.sh --with-libraries=system,filesystem,thread,log,locale,regex - "--prefix=${INSTALL_DIR}/usr/local" + "--prefix=${DESTDIR}/usr/local" BUILD_COMMAND ./b2 -j ${NPROC} link=static @@ -16,8 +16,6 @@ ExternalProject_Add(dep_boost cxxflags=-fPIC cflags=-fPIC install INSTALL_COMMAND "" # b2 does that already - LOG_CONFIGURE 1 - LOG_BUILD 1 ) ExternalProject_Add(dep_tbb @@ -28,10 +26,7 @@ ExternalProject_Add(dep_tbb CMAKE_ARGS -DTBB_BUILD_SHARED=OFF -DTBB_BUILD_TESTS=OFF -DCMAKE_POSITION_INDEPENDENT_CODE=ON - INSTALL_COMMAND make install "DESTDIR=${INSTALL_DIR}" - LOG_CONFIGURE 1 - LOG_BUILD 1 - LOG_INSTALL 1 + INSTALL_COMMAND make install "DESTDIR=${DESTDIR}" ) ExternalProject_Add(dep_libopenssl @@ -40,16 +35,13 @@ ExternalProject_Add(dep_libopenssl URL_HASH SHA256=8e9516b8635bb9113c51a7b5b27f9027692a56b104e75b709e588c3ffd6a0422 BUILD_IN_SOURCE 1 CONFIGURE_COMMAND ./config - "--prefix=${INSTALL_DIR}/usr/local" + "--prefix=${DESTDIR}/usr/local" no-shared no-ssl3-method no-dynamic-engine -Wa,--noexecstack BUILD_COMMAND make depend && make "-j${NPROC}" INSTALL_COMMAND make install_sw - LOG_CONFIGURE 1 - LOG_BUILD 1 - LOG_INSTALL 1 ) ExternalProject_Add(dep_libcurl @@ -97,10 +89,7 @@ ExternalProject_Add(dep_libcurl --without-nghttp2 --without-zsh-functions-dir BUILD_COMMAND make "-j${NPROC}" - INSTALL_COMMAND make install "DESTDIR=${INSTALL_DIR}" - LOG_CONFIGURE 1 - LOG_BUILD 1 - LOG_INSTALL 1 + INSTALL_COMMAND make install "DESTDIR=${DESTDIR}" ) ExternalProject_Add(dep_wxwidgets @@ -109,7 +98,7 @@ ExternalProject_Add(dep_wxwidgets URL_HASH SHA256=c925dfe17e8f8b09eb7ea9bfdcfcc13696a3e14e92750effd839f5e10726159e BUILD_IN_SOURCE 1 CONFIGURE_COMMAND ./configure - "--prefix=${INSTALL_DIR}/usr/local" + "--prefix=${DESTDIR}/usr/local" --disable-shared --with-gtk=2 --with-opengl @@ -127,7 +116,4 @@ ExternalProject_Add(dep_wxwidgets --enable-debug_gdb BUILD_COMMAND make "-j${NPROC}" && make -C locale allmo INSTALL_COMMAND make install - LOG_CONFIGURE 1 - LOG_BUILD 1 - LOG_INSTALL 1 ) diff --git a/deps/deps-windows.cmake b/deps/deps-windows.cmake index 834bdb9e3d..eaf5b8e65b 100644 --- a/deps/deps-windows.cmake +++ b/deps/deps-windows.cmake @@ -1,7 +1,4 @@ -# NB: I haven't enabled any of the LOG_xxx options because they tend to generate bogus build files, -# especially with compound commands like `cd foo && bar`. - ExternalProject_Add("dep_boost_${DEPS_BITS}" EXCLUDE_FROM_ALL 1 URL "https://dl.bintray.com/boostorg/release/1.66.0/source/boost_1_66_0.tar.gz" From 059ab4a05c42dd47b621200f6a737c5534c02877 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Tue, 16 Oct 2018 09:51:30 +0200 Subject: [PATCH 106/186] ModelInstance's full 3D transform set as default --- src/libslic3r/Format/3mf.cpp | 25 ---- src/libslic3r/Format/AMF.cpp | 57 --------- src/libslic3r/Format/PRUS.cpp | 29 ----- src/libslic3r/Model.cpp | 68 ----------- src/libslic3r/Model.hpp | 15 --- src/libslic3r/ModelArrange.hpp | 29 ----- src/libslic3r/MultiPoint.cpp | 2 - src/libslic3r/MultiPoint.hpp | 2 - src/libslic3r/Print.cpp | 4 - src/libslic3r/PrintObject.cpp | 5 - src/libslic3r/Technologies.hpp | 6 +- src/slic3r/GUI/3DScene.cpp | 67 ----------- src/slic3r/GUI/3DScene.hpp | 14 --- src/slic3r/GUI/GLCanvas3D.cpp | 140 +--------------------- src/slic3r/GUI/GLCanvas3D.hpp | 10 -- src/slic3r/GUI/GLGizmo.cpp | 51 -------- src/slic3r/GUI/GLGizmo.hpp | 36 ------ src/slic3r/GUI/GUI_ObjectManipulation.cpp | 46 ------- src/slic3r/GUI/GUI_ObjectManipulation.hpp | 6 - xs/xsp/Model.xsp | 20 ---- 20 files changed, 2 insertions(+), 630 deletions(-) diff --git a/src/libslic3r/Format/3mf.cpp b/src/libslic3r/Format/3mf.cpp index 4d749eb568..bf94db6b14 100644 --- a/src/libslic3r/Format/3mf.cpp +++ b/src/libslic3r/Format/3mf.cpp @@ -1253,13 +1253,7 @@ namespace Slic3r { // we extract from the given matrix only the values currently used // translation -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM Vec3d offset = transform.matrix().block(0, 3, 3, 1); -#else - double offset_x = transform(0, 3); - double offset_y = transform(1, 3); - double offset_z = transform(2, 3); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM // scale Eigen::Matrix m3x3 = transform.matrix().block(0, 0, 3, 3); @@ -1269,35 +1263,16 @@ namespace Slic3r { if ((scale(0) == 0.0) || (scale(1) == 0.0) || (scale(2) == 0.0)) return; -#if !ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - // non-uniform scale value, return - if ((std::abs(scale(0) - scale(1)) > 0.00001) || (std::abs(scale(0) - scale(2)) > 0.00001)) - return; -#endif // !ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - // remove scale m3x3.col(0).normalize(); m3x3.col(1).normalize(); m3x3.col(2).normalize(); -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM Vec3d rotation = Slic3r::Geometry::extract_euler_angles(m3x3); instance.set_offset(offset); instance.set_scaling_factor(scale); instance.set_rotation(rotation); -#else - Vec3d rotation = Slic3r::Geometry::extract_euler_angles(m3x3); - - // invalid rotation, we currently handle only rotations around Z axis - if ((rotation(0) != 0.0) || (rotation(1) != 0.0)) - return; - - instance.offset(0) = offset_x; - instance.offset(1) = offset_y; - instance.scaling_factor = scale(0); - instance.rotation = rotation(2); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM } bool _3MF_Importer::_handle_start_config(const char** attributes, unsigned int num_attributes) diff --git a/src/libslic3r/Format/AMF.cpp b/src/libslic3r/Format/AMF.cpp index 96befdabfd..00ed0d9373 100644 --- a/src/libslic3r/Format/AMF.cpp +++ b/src/libslic3r/Format/AMF.cpp @@ -29,14 +29,10 @@ // VERSION NUMBERS // 0 : .amf, .amf.xml and .zip.amf files saved by older slic3r. No version definition in them. // 1 : Introduction of amf versioning. No other change in data saved into amf files. -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM // 2 : Added z component of offset // Added x and y components of rotation // Added x, y and z components of scale const unsigned int VERSION_AMF = 2; -#else -const unsigned int VERSION_AMF = 1; -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM const char* SLIC3RPE_AMF_VERSION = "slic3rpe_amf_version"; const char* SLIC3R_CONFIG_TYPE = "slic3rpe_config"; @@ -125,34 +121,25 @@ struct AMFParserContext NODE_TYPE_INSTANCE, // amf/constellation/instance NODE_TYPE_DELTAX, // amf/constellation/instance/deltax NODE_TYPE_DELTAY, // amf/constellation/instance/deltay -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM NODE_TYPE_DELTAZ, // amf/constellation/instance/deltaz NODE_TYPE_RX, // amf/constellation/instance/rx NODE_TYPE_RY, // amf/constellation/instance/ry -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM NODE_TYPE_RZ, // amf/constellation/instance/rz NODE_TYPE_SCALE, // amf/constellation/instance/scale -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM NODE_TYPE_SCALEX, // amf/constellation/instance/scalex NODE_TYPE_SCALEY, // amf/constellation/instance/scaley NODE_TYPE_SCALEZ, // amf/constellation/instance/scalez -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM NODE_TYPE_METADATA, // anywhere under amf/*/metadata }; struct Instance { -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM Instance() : deltax_set(false), deltay_set(false), deltaz_set(false), rx_set(false), ry_set(false), rz_set(false), scalex_set(false), scaley_set(false), scalez_set(false) {} -#else - Instance() : deltax_set(false), deltay_set(false), rz_set(false), scale_set(false) {} -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM // Shift in the X axis. float deltax; bool deltax_set; // Shift in the Y axis. float deltay; bool deltay_set; -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM // Shift in the Z axis. float deltaz; bool deltaz_set; @@ -162,11 +149,9 @@ struct AMFParserContext // Rotation around the Y axis. float ry; bool ry_set; -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM // Rotation around the Z axis. float rz; bool rz_set; -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM // Scaling factors float scalex; bool scalex_set; @@ -174,11 +159,6 @@ struct AMFParserContext bool scaley_set; float scalez; bool scalez_set; -#else - // Scaling factor - float scale; - bool scale_set; -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM }; struct Object { @@ -293,24 +273,20 @@ void AMFParserContext::startElement(const char *name, const char **atts) node_type_new = NODE_TYPE_DELTAX; else if (strcmp(name, "deltay") == 0) node_type_new = NODE_TYPE_DELTAY; -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM else if (strcmp(name, "deltaz") == 0) node_type_new = NODE_TYPE_DELTAZ; else if (strcmp(name, "rx") == 0) node_type_new = NODE_TYPE_RX; else if (strcmp(name, "ry") == 0) node_type_new = NODE_TYPE_RY; -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM else if (strcmp(name, "rz") == 0) node_type_new = NODE_TYPE_RZ; -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM else if (strcmp(name, "scalex") == 0) node_type_new = NODE_TYPE_SCALEX; else if (strcmp(name, "scaley") == 0) node_type_new = NODE_TYPE_SCALEY; else if (strcmp(name, "scalez") == 0) node_type_new = NODE_TYPE_SCALEZ; -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM else if (strcmp(name, "scale") == 0) node_type_new = NODE_TYPE_SCALE; } @@ -369,7 +345,6 @@ void AMFParserContext::characters(const XML_Char *s, int len) { switch (m_path.size()) { case 4: -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM if (m_path.back() == NODE_TYPE_DELTAX || m_path.back() == NODE_TYPE_DELTAY || m_path.back() == NODE_TYPE_DELTAZ || @@ -380,9 +355,6 @@ void AMFParserContext::characters(const XML_Char *s, int len) m_path.back() == NODE_TYPE_SCALEY || m_path.back() == NODE_TYPE_SCALEZ || m_path.back() == NODE_TYPE_SCALE) -#else - if (m_path.back() == NODE_TYPE_DELTAX || m_path.back() == NODE_TYPE_DELTAY || m_path.back() == NODE_TYPE_RZ || m_path.back() == NODE_TYPE_SCALE) -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM m_value[0].append(s, len); break; case 6: @@ -422,7 +394,6 @@ void AMFParserContext::endElement(const char * /* name */) m_instance->deltay_set = true; m_value[0].clear(); break; -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM case NODE_TYPE_DELTAZ: assert(m_instance); m_instance->deltaz = float(atof(m_value[0].c_str())); @@ -441,7 +412,6 @@ void AMFParserContext::endElement(const char * /* name */) m_instance->ry_set = true; m_value[0].clear(); break; -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM case NODE_TYPE_RZ: assert(m_instance); m_instance->rz = float(atof(m_value[0].c_str())); @@ -450,20 +420,14 @@ void AMFParserContext::endElement(const char * /* name */) break; case NODE_TYPE_SCALE: assert(m_instance); -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM m_instance->scalex = float(atof(m_value[0].c_str())); m_instance->scalex_set = true; m_instance->scaley = float(atof(m_value[0].c_str())); m_instance->scaley_set = true; m_instance->scalez = float(atof(m_value[0].c_str())); m_instance->scalez_set = true; -#else - m_instance->scale = float(atof(m_value[0].c_str())); - m_instance->scale_set = true; -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM m_value[0].clear(); break; -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM case NODE_TYPE_SCALEX: assert(m_instance); m_instance->scalex = float(atof(m_value[0].c_str())); @@ -482,7 +446,6 @@ void AMFParserContext::endElement(const char * /* name */) m_instance->scalez_set = true; m_value[0].clear(); break; -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM // Object vertices: case NODE_TYPE_VERTEX: @@ -619,16 +582,9 @@ void AMFParserContext::endDocument() for (const Instance &instance : object.second.instances) if (instance.deltax_set && instance.deltay_set) { ModelInstance *mi = m_model.objects[object.second.idx]->add_instance(); -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM mi->set_offset(Vec3d(instance.deltax_set ? (double)instance.deltax : 0.0, instance.deltay_set ? (double)instance.deltay : 0.0, instance.deltaz_set ? (double)instance.deltaz : 0.0)); mi->set_rotation(Vec3d(instance.rx_set ? (double)instance.rx : 0.0, instance.ry_set ? (double)instance.ry : 0.0, instance.rz_set ? (double)instance.rz : 0.0)); mi->set_scaling_factor(Vec3d(instance.scalex_set ? (double)instance.scalex : 1.0, instance.scaley_set ? (double)instance.scaley : 1.0, instance.scalez_set ? (double)instance.scalez : 1.0)); -#else - mi->offset(0) = instance.deltax; - mi->offset(1) = instance.deltay; - mi->rotation = instance.rz_set ? instance.rz : 0.f; - mi->scaling_factor = instance.scale_set ? instance.scale : 1.f; -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM } } } @@ -928,22 +884,15 @@ bool store_amf(const char *path, Model *model, Print* print, bool export_print_c " \n" " %lf\n" " %lf\n" -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM " %lf\n" " %lf\n" " %lf\n" -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM " %lf\n" -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM " %lf\n" " %lf\n" " %lf\n" -#else - " %lf\n" -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM " \n", object_id, -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM instance->get_offset(X), instance->get_offset(Y), instance->get_offset(Z), @@ -953,12 +902,6 @@ bool store_amf(const char *path, Model *model, Print* print, bool export_print_c instance->get_scaling_factor(X), instance->get_scaling_factor(Y), instance->get_scaling_factor(Z)); -#else - instance->offset(0), - instance->offset(1), - instance->rotation, - instance->scaling_factor); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM //FIXME missing instance->scaling_factor instances.append(buf); diff --git a/src/libslic3r/Format/PRUS.cpp b/src/libslic3r/Format/PRUS.cpp index b68726a377..f79721be71 100644 --- a/src/libslic3r/Format/PRUS.cpp +++ b/src/libslic3r/Format/PRUS.cpp @@ -97,15 +97,9 @@ static void extract_model_from_archive( const char *zero_tag = ""; const char *zero_xml = strstr(scene_xml_data.data(), zero_tag); float trafo[3][4] = { 0 }; -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM Vec3d instance_rotation = Vec3d::Zero(); Vec3d instance_scaling_factor = Vec3d::Ones(); Vec3d instance_offset = Vec3d::Zero(); -#else - double instance_rotation = 0.; - double instance_scaling_factor = 1.f; - Vec2d instance_offset(0., 0.); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM bool trafo_set = false; unsigned int group_id = (unsigned int)-1; unsigned int extruder_id = (unsigned int)-1; @@ -128,19 +122,8 @@ static void extract_model_from_archive( "[%f, %f, %f]", scale, scale+1, scale+2) == 3 && sscanf(zero_xml+strlen(zero_tag), "[%f, %f, %f]", zero, zero+1, zero+2) == 3) { -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM instance_scaling_factor = Vec3d((double)scale[0], (double)scale[1], (double)scale[2]); instance_rotation = Vec3d(-(double)rotation[0], -(double)rotation[1], -(double)rotation[2]); -#else - if (scale[0] == scale[1] && scale[1] == scale[2]) { - instance_scaling_factor = scale[0]; - scale[0] = scale[1] = scale[2] = 1.; - } - if (rotation[0] == 0. && rotation[1] == 0.) { - instance_rotation = -rotation[2]; - rotation[2] = 0.; - } -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM Eigen::Matrix3f mat_rot, mat_scale, mat_trafo; mat_rot = Eigen::AngleAxisf(-rotation[2], Eigen::Vector3f::UnitZ()) * Eigen::AngleAxisf(-rotation[1], Eigen::Vector3f::UnitY()) * @@ -151,15 +134,9 @@ static void extract_model_from_archive( for (size_t c = 0; c < 3; ++ c) trafo[r][c] += mat_trafo(r, c); } -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM instance_offset = Vec3d((double)(position[0] - zero[0]), (double)(position[1] - zero[1]), (double)(position[2] - zero[2])); // CHECK_ME -> Is the following correct ? trafo[2][3] = position[2] / (float)instance_scaling_factor(2); -#else - instance_offset(0) = position[0] - zero[0]; - instance_offset(1) = position[1] - zero[1]; - trafo[2][3] = position[2] / instance_scaling_factor; -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM trafo_set = true; } const char *group_tag = ""; @@ -315,15 +292,9 @@ static void extract_model_from_archive( model_object = model->add_object(name, path, std::move(mesh)); volume = model_object->volumes.front(); ModelInstance *instance = model_object->add_instance(); -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM instance->set_rotation(instance_rotation); instance->set_scaling_factor(instance_scaling_factor); instance->set_offset(instance_offset); -#else - instance->rotation = instance_rotation; - instance->scaling_factor = instance_scaling_factor; - instance->offset = instance_offset; -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM if (group_id != (size_t)-1) group_to_model_object[group_id] = model_object; } else { diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 8ced1018db..dc2c37c7fd 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -252,19 +252,11 @@ void Model::center_instances_around_point(const Vec2d &point) for (size_t i = 0; i < o->instances.size(); ++ i) bb.merge(o->instance_bounding_box(i, false)); -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM Vec2d shift2 = point - to_2d(bb.center()); Vec3d shift3 = Vec3d(shift2(0), shift2(1), 0.0); -#else - Vec2d shift = point - 0.5 * to_2d(bb.size()) - to_2d(bb.min); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM for (ModelObject *o : this->objects) { for (ModelInstance *i : o->instances) -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM i->set_offset(i->get_offset() + shift3); -#else - i->offset += shift; -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM o->invalidate_bounding_box(); } } @@ -330,12 +322,8 @@ bool Model::arrange_objects(coordf_t dist, const BoundingBoxf* bb) size_t idx = 0; for (ModelObject *o : this->objects) { for (ModelInstance *i : o->instances) { -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM Vec2d offset_xy = positions[idx] - instance_centers[idx]; i->set_offset(Vec3d(offset_xy(0), offset_xy(1), i->get_offset(Z))); -#else - i->offset = positions[idx] - instance_centers[idx]; -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM ++idx; } o->invalidate_bounding_box(); @@ -360,11 +348,7 @@ void Model::duplicate(size_t copies_num, coordf_t dist, const BoundingBoxf* bb) for (const ModelInstance *i : instances) { for (const Vec2d &pos : positions) { ModelInstance *instance = o->add_instance(*i); -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM instance->set_offset(instance->get_offset() + Vec3d(pos(0), pos(1), 0.0)); -#else - instance->offset += pos; -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM } } o->invalidate_bounding_box(); @@ -394,21 +378,12 @@ void Model::duplicate_objects_grid(size_t x, size_t y, coordf_t dist) ModelObject* object = this->objects.front(); object->clear_instances(); -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM Vec3d ext_size = object->bounding_box().size() + dist * Vec3d::Ones(); -#else - Vec3d size = object->bounding_box().size(); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM for (size_t x_copy = 1; x_copy <= x; ++x_copy) { for (size_t y_copy = 1; y_copy <= y; ++y_copy) { ModelInstance* instance = object->add_instance(); -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM instance->set_offset(Vec3d(ext_size(0) * (double)(x_copy - 1), ext_size(1) * (double)(y_copy - 1), 0.0)); -#else - instance->offset(0) = (size(0) + dist) * (x_copy - 1); - instance->offset(1) = (size(1) + dist) * (y_copy - 1); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM } } } @@ -728,23 +703,16 @@ void ModelObject::center_around_origin() this->translate(shift); this->origin_translation += shift; -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM #if !ENABLE_EXTENDED_SELECTION // set z to zero, translation in z has already been done within the mesh shift(2) = 0.0; #endif // !ENABLE_EXTENDED_SELECTION -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM if (!this->instances.empty()) { for (ModelInstance *i : this->instances) { // apply rotation and scaling to vector as well before translating instance, // in order to leave final position unaltered -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM i->set_offset(i->get_offset() + i->transform_vector(-shift, true)); -#else - Vec3d i_shift = i->world_matrix(true) * shift; - i->offset -= to_2d(i_shift); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM } this->invalidate_bounding_box(); } @@ -1091,7 +1059,6 @@ size_t ModelVolume::split(unsigned int max_extruders) return idx; } -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM void ModelInstance::set_rotation(const Vec3d& rotation) { set_rotation(X, rotation(0)); @@ -1112,7 +1079,6 @@ void ModelInstance::set_rotation(Axis axis, double rotation) } m_rotation(axis) = rotation; } -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM void ModelInstance::transform_mesh(TriangleMesh* mesh, bool dont_translate) const { @@ -1127,7 +1093,6 @@ BoundingBoxf3 ModelInstance::transform_mesh_bounding_box(const TriangleMesh* mes BoundingBoxf3 bbox = copy.bounding_box(); if (!empty(bbox)) { -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM // Scale the bounding box along the three axes. for (unsigned int i = 0; i < 3; ++i) { @@ -1143,19 +1108,6 @@ BoundingBoxf3 ModelInstance::transform_mesh_bounding_box(const TriangleMesh* mes bbox.min += this->m_offset; bbox.max += this->m_offset; } -#else - // Scale the bounding box uniformly. - if (std::abs(this->scaling_factor - 1.) > EPSILON) { - bbox.min *= this->scaling_factor; - bbox.max *= this->scaling_factor; - } - - // Translate the bounding box. - if (!dont_translate) { - Eigen::Map(bbox.min.data()) += this->offset; - Eigen::Map(bbox.max.data()) += this->offset; - } -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM } return bbox; } @@ -1172,38 +1124,18 @@ Vec3d ModelInstance::transform_vector(const Vec3d& v, bool dont_translate) const void ModelInstance::transform_polygon(Polygon* polygon) const { -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM // CHECK_ME -> Is the following correct or it should take in account all three rotations ? polygon->rotate(this->m_rotation(2)); // rotate around polygon origin // CHECK_ME -> Is the following correct ? polygon->scale(this->m_scaling_factor(0), this->m_scaling_factor(1)); // scale around polygon origin -#else - polygon->rotate(this->rotation); // rotate around polygon origin - polygon->scale(this->scaling_factor); // scale around polygon origin -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM } Transform3d ModelInstance::world_matrix(bool dont_translate, bool dont_rotate, bool dont_scale) const { -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM Vec3d translation = dont_translate ? Vec3d::Zero() : m_offset; Vec3d rotation = dont_rotate ? Vec3d::Zero() : m_rotation; Vec3d scale = dont_scale ? Vec3d::Ones() : m_scaling_factor; return Geometry::assemble_transform(translation, rotation, scale); -#else - Transform3d m = Transform3d::Identity(); - - if (!dont_translate) - m.translate(Vec3d(offset(0), offset(1), 0.0)); - - if (!dont_rotate) - m.rotate(Eigen::AngleAxisd(rotation, Vec3d::UnitZ())); - - if (!dont_scale) - m.scale(scaling_factor); - - return m; -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM } } diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index 695de61275..7fd889ffb8 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -247,25 +247,17 @@ public: friend class ModelObject; -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM private: Vec3d m_offset; // in unscaled coordinates Vec3d m_rotation; // Rotation around the three axes, in radians around mesh center point Vec3d m_scaling_factor; // Scaling factors along the three axes public: -#else - double rotation; // Rotation around the Z axis, in radians around mesh center point - double scaling_factor; - Vec2d offset; // in unscaled coordinates -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - // flag showing the position of this instance with respect to the print volume (set by Print::validate() using ModelObject::check_instances_print_volume_state()) EPrintVolumeState print_volume_state; ModelObject* get_object() const { return this->object; } -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM const Vec3d& get_offset() const { return m_offset; } double get_offset(Axis axis) const { return m_offset(axis); } @@ -283,7 +275,6 @@ public: void set_scaling_factor(const Vec3d& scaling_factor) { m_scaling_factor = scaling_factor; } void set_scaling_factor(Axis axis, double scaling_factor) { m_scaling_factor(axis) = scaling_factor; } -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM // To be called on an external mesh void transform_mesh(TriangleMesh* mesh, bool dont_translate = false) const; @@ -304,15 +295,9 @@ private: // Parent object, owning this instance. ModelObject* object; -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM ModelInstance(ModelObject *object) : m_rotation(Vec3d::Zero()), m_scaling_factor(Vec3d::Ones()), m_offset(Vec3d::Zero()), object(object), print_volume_state(PVS_Inside) {} ModelInstance(ModelObject *object, const ModelInstance &other) : m_rotation(other.m_rotation), m_scaling_factor(other.m_scaling_factor), m_offset(other.m_offset), object(object), print_volume_state(PVS_Inside) {} -#else - ModelInstance(ModelObject *object) : rotation(0), scaling_factor(1), offset(Vec2d::Zero()), object(object), print_volume_state(PVS_Inside) {} - ModelInstance(ModelObject *object, const ModelInstance &other) : - rotation(other.rotation), scaling_factor(other.scaling_factor), offset(other.offset), object(object), print_volume_state(PVS_Inside) {} -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM }; diff --git a/src/libslic3r/ModelArrange.hpp b/src/libslic3r/ModelArrange.hpp index f8beb668ae..dffb951ddf 100644 --- a/src/libslic3r/ModelArrange.hpp +++ b/src/libslic3r/ModelArrange.hpp @@ -29,12 +29,8 @@ std::string toString(const Model& model, bool holes = true) { if(!objinst) continue; Slic3r::TriangleMesh tmpmesh = rmesh; -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM // CHECK_ME -> Is the following correct ? tmpmesh.scale(objinst->get_scaling_factor()); -#else - tmpmesh.scale(objinst->scaling_factor); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM objinst->transform_mesh(&tmpmesh); ExPolygons expolys = tmpmesh.horizontal_projection(); for(auto& expoly_complex : expolys) { @@ -92,11 +88,7 @@ void toSVG(SVG& svg, const Model& model) { if(!objinst) continue; Slic3r::TriangleMesh tmpmesh = rmesh; -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM tmpmesh.scale(objinst->get_scaling_factor()); -#else - tmpmesh.scale(objinst->scaling_factor); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM objinst->transform_mesh(&tmpmesh); ExPolygons expolys = tmpmesh.horizontal_projection(); svg.draw(expolys); @@ -522,12 +514,8 @@ ShapeData2D projectModelFromTop(const Slic3r::Model &model) { Slic3r::TriangleMesh tmpmesh = rmesh; ClipperLib::PolygonImpl pn; -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM // CHECK_ME -> is the following correct ? tmpmesh.scale(objinst->get_scaling_factor()); -#else - tmpmesh.scale(objinst->scaling_factor); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM // TODO export the exact 2D projection auto p = tmpmesh.convex_hull(); @@ -541,20 +529,11 @@ ShapeData2D projectModelFromTop(const Slic3r::Model &model) { // Invalid geometries would throw exceptions when arranging if(item.vertexCount() > 3) { -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM // CHECK_ME -> is the following correct or it should take in account all three rotations ? item.rotation(objinst->get_rotation(Z)); -#else - item.rotation(objinst->rotation); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM item.translation({ -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM ClipperLib::cInt(objinst->get_offset(X)/SCALING_FACTOR), ClipperLib::cInt(objinst->get_offset(Y)/SCALING_FACTOR) -#else - ClipperLib::cInt(objinst->offset(0)/SCALING_FACTOR), - ClipperLib::cInt(objinst->offset(1)/SCALING_FACTOR) -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM }); ret.emplace_back(objinst, item); } @@ -691,7 +670,6 @@ void applyResult( // appropriately auto off = item.translation(); Radians rot = item.rotation(); -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM Vec3d foff(off.X*SCALING_FACTOR + batch_offset, off.Y*SCALING_FACTOR, 0.0); @@ -699,13 +677,6 @@ void applyResult( // write the transformation data into the model instance inst_ptr->set_rotation(Z, rot); inst_ptr->set_offset(foff); -#else - Vec2d foff(off.X*SCALING_FACTOR + batch_offset, off.Y*SCALING_FACTOR); - - // write the transformation data into the model instance - inst_ptr->rotation = rot; - inst_ptr->offset = foff; -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM } } diff --git a/src/libslic3r/MultiPoint.cpp b/src/libslic3r/MultiPoint.cpp index 45b354d63a..6e49be958f 100644 --- a/src/libslic3r/MultiPoint.cpp +++ b/src/libslic3r/MultiPoint.cpp @@ -14,7 +14,6 @@ void MultiPoint::scale(double factor) pt *= factor; } -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM void MultiPoint::scale(double factor_x, double factor_y) { for (Point &pt : points) @@ -23,7 +22,6 @@ void MultiPoint::scale(double factor_x, double factor_y) pt(1) *= factor_y; } } -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM void MultiPoint::translate(double x, double y) { diff --git a/src/libslic3r/MultiPoint.hpp b/src/libslic3r/MultiPoint.hpp index 288b3137ea..9a7bd83e56 100644 --- a/src/libslic3r/MultiPoint.hpp +++ b/src/libslic3r/MultiPoint.hpp @@ -26,9 +26,7 @@ public: MultiPoint& operator=(const MultiPoint &other) { points = other.points; return *this; } MultiPoint& operator=(MultiPoint &&other) { points = std::move(other.points); return *this; } void scale(double factor); -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM void scale(double factor_x, double factor_y); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM void translate(double x, double y); void translate(const Point &vector); void rotate(double angle) { this->rotate(cos(angle), sin(angle)); } diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 37b55f87df..5cd12f654c 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -431,14 +431,10 @@ void Print::add_model_object(ModelObject* model_object, int idx) std::vector v_scale; for (const PrintObject *object : m_objects) { const ModelObject &mobj = *object->model_object(); -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM // CHECK_ME -> Is the following correct ? v_scale.push_back("x:" + boost::lexical_cast(mobj.instances[0]->get_scaling_factor(X) * 100) + "% y:" + boost::lexical_cast(mobj.instances[0]->get_scaling_factor(Y) * 100) + "% z:" + boost::lexical_cast(mobj.instances[0]->get_scaling_factor(Z) * 100) + "%"); -#else - v_scale.push_back(boost::lexical_cast(mobj.instances[0]->scaling_factor * 100) + "%"); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM if (input_file.empty()) input_file = mobj.input_file; } diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 345cc9c5ef..c62dd000ca 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -113,16 +113,11 @@ bool PrintObject::reload_model_instances() copies.reserve(m_model_object->instances.size()); for (const ModelInstance *mi : m_model_object->instances) { -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM if (mi->is_printable()) { const Vec3d& offset = mi->get_offset(); copies.emplace_back(Point::new_scale(offset(0), offset(1))); } -#else - if (mi->is_printable()) - copies.emplace_back(Point::new_scale(mi->offset(0), mi->offset(1))); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM } return this->set_copies(copies); } diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index 0b918d7c9d..4c653e543e 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -4,16 +4,12 @@ // 1.42.0 techs #define ENABLE_1_42_0 1 -// Add z coordinate to model instances' offset -// Add x and y rotation components to model instances' rotation -// Add scaling factors for all the three axes to model instances -#define ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM (1 && ENABLE_1_42_0) // Add double click on gizmo grabbers to reset transformation components to their default value #define ENABLE_GIZMOS_RESET (1 && ENABLE_1_42_0) // Uses a unique opengl context #define ENABLE_USE_UNIQUE_GLCONTEXT (1 && ENABLE_1_42_0) // New selections -#define ENABLE_EXTENDED_SELECTION (1 && ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM) +#define ENABLE_EXTENDED_SELECTION (1 && ENABLE_1_42_0) #endif // _technologies_h_ diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index 07f9b0fda4..402d7b8ee9 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -196,13 +196,8 @@ const float GLVolume::SELECTED_OUTSIDE_COLOR[4] = { 0.19f, 0.58f, 1.0f, 1.0f }; GLVolume::GLVolume(float r, float g, float b, float a) : m_offset(Vec3d::Zero()) -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM , m_rotation(Vec3d::Zero()) , m_scaling_factor(Vec3d::Ones()) -#else - , m_rotation(0.0) - , m_scaling_factor(1.0) -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM , m_world_matrix(Transform3f::Identity()) , m_world_matrix_dirty(true) , m_transformed_bounding_box_dirty(true) @@ -262,7 +257,6 @@ void GLVolume::set_render_color() set_render_color(color, 4); } -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM const Vec3d& GLVolume::get_rotation() const { return m_rotation; @@ -295,23 +289,6 @@ void GLVolume::set_rotation(const Vec3d& rotation) m_transformed_convex_hull_bounding_box_dirty = true; } } -#else -double GLVolume::get_rotation() const -{ - return m_rotation; -} - -void GLVolume::set_rotation(double rotation) -{ - if (m_rotation != rotation) - { - m_rotation = rotation; - m_world_matrix_dirty = true; - m_transformed_bounding_box_dirty = true; - m_transformed_convex_hull_bounding_box_dirty = true; - } -} -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM const Vec3d& GLVolume::get_offset() const { @@ -329,7 +306,6 @@ void GLVolume::set_offset(const Vec3d& offset) } } -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM #if ENABLE_EXTENDED_SELECTION const Vec3d& GLVolume::get_scaling_factor() const { @@ -347,18 +323,6 @@ void GLVolume::set_scaling_factor(const Vec3d& scaling_factor) m_transformed_convex_hull_bounding_box_dirty = true; } } -#else -void GLVolume::set_scaling_factor(double factor) -{ - if (m_scaling_factor != factor) - { - m_scaling_factor = factor; - m_world_matrix_dirty = true; - m_transformed_bounding_box_dirty = true; - m_transformed_convex_hull_bounding_box_dirty = true; - } -} -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM void GLVolume::set_convex_hull(const TriangleMesh& convex_hull) { @@ -389,14 +353,7 @@ const Transform3f& GLVolume::world_matrix() const { if (m_world_matrix_dirty) { -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM m_world_matrix = Geometry::assemble_transform(m_offset, m_rotation, m_scaling_factor).cast(); -#else - m_world_matrix = Transform3f::Identity(); - m_world_matrix.translate(m_offset.cast()); - m_world_matrix.rotate(Eigen::AngleAxisf((float)m_rotation, Vec3f::UnitZ())); - m_world_matrix.scale((float)m_scaling_factor); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM m_world_matrix_dirty = false; } return m_world_matrix; @@ -471,13 +428,7 @@ void GLVolume::render() const ::glCullFace(GL_BACK); ::glPushMatrix(); -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM ::glMultMatrixf(world_matrix().data()); -#else - ::glTranslated(m_offset(0), m_offset(1), m_offset(2)); - ::glRotated(m_rotation * 180.0 / (double)PI, 0.0, 0.0, 1.0); - ::glScaled(m_scaling_factor, m_scaling_factor, m_scaling_factor); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM if (this->indexed_vertex_array.indexed()) this->indexed_vertex_array.render(this->tverts_range, this->qverts_range); else @@ -602,13 +553,7 @@ void GLVolume::render_VBOs(int color_id, int detection_id, int worldmatrix_id) c ::glPushMatrix(); -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM ::glMultMatrixf(world_matrix().data()); -#else - ::glTranslated(m_offset(0), m_offset(1), m_offset(2)); - ::glRotated(m_rotation * 180.0 / (double)PI, 0.0, 0.0, 1.0); - ::glScaled(m_scaling_factor, m_scaling_factor, m_scaling_factor); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM if (n_triangles > 0) { @@ -652,13 +597,7 @@ void GLVolume::render_legacy() const ::glPushMatrix(); -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM ::glMultMatrixf(world_matrix().data()); -#else - ::glTranslated(m_offset(0), m_offset(1), m_offset(2)); - ::glRotated(m_rotation * 180.0 / (double)PI, 0.0, 0.0, 1.0); - ::glScaled(m_scaling_factor, m_scaling_factor, m_scaling_factor); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM if (n_triangles > 0) ::glDrawElements(GL_TRIANGLES, n_triangles, GL_UNSIGNED_INT, indexed_vertex_array.triangle_indices.data() + tverts_range.first); @@ -787,15 +726,9 @@ std::vector GLVolumeCollection::load_object( } v.is_modifier = ! model_volume->is_model_part(); v.shader_outside_printer_detection_enabled = model_volume->is_model_part(); -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM v.set_offset(instance->get_offset()); v.set_rotation(instance->get_rotation()); v.set_scaling_factor(instance->get_scaling_factor()); -#else - v.set_offset(Vec3d(instance->offset(0), instance->offset(1), 0.0)); - v.set_rotation(instance->rotation); - v.set_scaling_factor(instance->scaling_factor); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM } } diff --git a/src/slic3r/GUI/3DScene.hpp b/src/slic3r/GUI/3DScene.hpp index 5eb349f096..e3f7ea0d36 100644 --- a/src/slic3r/GUI/3DScene.hpp +++ b/src/slic3r/GUI/3DScene.hpp @@ -256,17 +256,10 @@ public: private: // Offset of the volume to be rendered. Vec3d m_offset; -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM // Rotation around three axes of the volume to be rendered. Vec3d m_rotation; // Scale factor along the three axes of the volume to be rendered. Vec3d m_scaling_factor; -#else - // Rotation around Z axis of the volume to be rendered. - double m_rotation; - // Scale factor of the volume to be rendered. - double m_scaling_factor; -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM // World matrix of the volume to be rendered. mutable Transform3f m_world_matrix; // Whether or not is needed to recalculate the world matrix. @@ -336,7 +329,6 @@ public: // Sets render color in dependence of current state void set_render_color(); -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM const Vec3d& get_rotation() const; void set_rotation(const Vec3d& rotation); @@ -344,12 +336,6 @@ public: const Vec3d& get_scaling_factor() const; #endif // ENABLE_EXTENDED_SELECTION void set_scaling_factor(const Vec3d& scaling_factor); -#else - double get_rotation() const; - void set_rotation(double rotation); - - void set_scaling_factor(double factor); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM const Vec3d& get_offset() const; void set_offset(const Vec3d& offset); diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 42b1354483..47729cffb6 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1830,11 +1830,6 @@ bool GLCanvas3D::Gizmos::init(GLCanvas3D& parent) if (!gizmo->init()) return false; -#if !ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - // temporary disable z grabber - gizmo->disable_grabber(2); -#endif // !ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - m_gizmos.insert(GizmosMap::value_type(Move, gizmo)); gizmo = new GLGizmoScale3D(parent); @@ -1844,18 +1839,6 @@ bool GLCanvas3D::Gizmos::init(GLCanvas3D& parent) if (!gizmo->init()) return false; -#if !ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - // temporary disable x grabbers - gizmo->disable_grabber(0); - gizmo->disable_grabber(1); - // temporary disable y grabbers - gizmo->disable_grabber(2); - gizmo->disable_grabber(3); - // temporary disable z grabbers - gizmo->disable_grabber(4); - gizmo->disable_grabber(5); -#endif // !ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - m_gizmos.insert(GizmosMap::value_type(Scale, gizmo)); gizmo = new GLGizmoRotate3D(parent); @@ -1871,12 +1854,6 @@ bool GLCanvas3D::Gizmos::init(GLCanvas3D& parent) return false; } -#if !ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - // temporary disable x and y grabbers - gizmo->disable_grabber(0); - gizmo->disable_grabber(1); -#endif // !ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - m_gizmos.insert(GizmosMap::value_type(Rotate, gizmo)); gizmo = new GLGizmoFlatten(parent); @@ -2161,7 +2138,6 @@ void GLCanvas3D::Gizmos::set_position(const Vec3d& position) } #endif // ENABLE_EXTENDED_SELECTION -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM Vec3d GLCanvas3D::Gizmos::get_scale() const { if (!m_enabled) @@ -2208,54 +2184,6 @@ Vec3d GLCanvas3D::Gizmos::get_flattening_rotation() const GizmosMap::const_iterator it = m_gizmos.find(Flatten); return (it != m_gizmos.end()) ? reinterpret_cast(it->second)->get_flattening_rotation() : Vec3d::Zero(); } -#else -float GLCanvas3D::Gizmos::get_scale() const -{ - if (!m_enabled) - return 1.0f; - - GizmosMap::const_iterator it = m_gizmos.find(Scale); - return (it != m_gizmos.end()) ? reinterpret_cast(it->second)->get_scale_x() : 1.0f; -} - -void GLCanvas3D::Gizmos::set_scale(float scale) -{ - if (!m_enabled) - return; - - GizmosMap::const_iterator it = m_gizmos.find(Scale); - if (it != m_gizmos.end()) - reinterpret_cast(it->second)->set_scale(scale); -} - -float GLCanvas3D::Gizmos::get_angle_z() const -{ - if (!m_enabled) - return 0.0f; - - GizmosMap::const_iterator it = m_gizmos.find(Rotate); - return (it != m_gizmos.end()) ? reinterpret_cast(it->second)->get_angle_z() : 0.0f; -} - -void GLCanvas3D::Gizmos::set_angle_z(float angle_z) -{ - if (!m_enabled) - return; - - GizmosMap::const_iterator it = m_gizmos.find(Rotate); - if (it != m_gizmos.end()) - reinterpret_cast(it->second)->set_angle_z(angle_z); -} - -Vec3d GLCanvas3D::Gizmos::get_flattening_normal() const -{ - if (!m_enabled) - return Vec3d::Zero(); - - GizmosMap::const_iterator it = m_gizmos.find(Flatten); - return (it != m_gizmos.end()) ? reinterpret_cast(it->second)->get_flattening_normal() : Vec3d::Zero(); -} -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM void GLCanvas3D::Gizmos::set_flattening_data(const ModelObject* model_object) { @@ -3306,15 +3234,9 @@ void GLCanvas3D::update_gizmos_data() ModelInstance* model_instance = model_object->instances[0]; if (model_instance != nullptr) { -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM m_gizmos.set_position(model_instance->get_offset()); m_gizmos.set_scale(model_instance->get_scaling_factor()); m_gizmos.set_rotation(model_instance->get_rotation()); -#else - m_gizmos.set_position(Vec3d(model_instance->offset(0), model_instance->offset(1), 0.0)); - m_gizmos.set_scale(model_instance->scaling_factor); - m_gizmos.set_angle_z(model_instance->rotation); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM m_gizmos.set_flattening_data(model_object); } } @@ -3322,13 +3244,8 @@ void GLCanvas3D::update_gizmos_data() else { m_gizmos.set_position(Vec3d::Zero()); -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM m_gizmos.set_scale(Vec3d::Ones()); m_gizmos.set_rotation(Vec3d::Zero()); -#else - m_gizmos.set_scale(1.0f); - m_gizmos.set_angle_z(0.0f); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM m_gizmos.set_flattening_data(nullptr); } #endif // ENABLE_EXTENDED_SELECTION @@ -3862,17 +3779,13 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) { case Gizmos::Scale: { -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM #if ENABLE_EXTENDED_SELECTION m_regenerate_volumes = false; m_selection.scale(m_gizmos.get_scale()); _on_scale(); -#else - post_event(Vec3dEvent(EVT_GIZMO_SCALE, m_gizmos.get_scale())); -#endif // ENABLE_EXTENDED_SELECTION #else m_on_gizmo_scale_uniformly_callback.call((double)m_gizmos.get_scale()); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM +#endif // ENABLE_EXTENDED_SELECTION #if ENABLE_EXTENDED_SELECTION wxGetApp().obj_manipul()->update_settings_value(m_selection); #else @@ -3883,7 +3796,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) } case Gizmos::Rotate: { -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM #if ENABLE_EXTENDED_SELECTION m_regenerate_volumes = false; m_selection.rotate(m_gizmos.get_rotation()); @@ -3891,9 +3803,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) #else post_event(Vec3dEvent(EVT_GIZMO_ROTATE, std::move(m_gizmos.get_rotation()))); #endif // ENABLE_EXTENDED_SELECTION -#else - m_on_gizmo_rotate_callback.call((double)m_gizmos.get_angle_z()); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM #if ENABLE_EXTENDED_SELECTION wxGetApp().obj_manipul()->update_settings_value(m_selection); #else @@ -3969,18 +3878,8 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) #endif // ENABLE_EXTENDED_SELECTION if (m_gizmos.get_current_type() == Gizmos::Flatten) { -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM // Rotate the object so the normal points downward: post_event(Vec3dEvent(EVT_GIZMO_FLATTEN, m_gizmos.get_flattening_rotation())); -#else - // Rotate the object so the normal points downward: - Vec3d normal = m_gizmos.get_flattening_normal(); - if (normal(0) != 0.0 || normal(1) != 0.0 || normal(2) != 0.0) { - Vec3d axis = normal(2) > 0.999 ? Vec3d::UnitX() : normal.cross(-Vec3d::UnitZ()).normalized(); - float angle = acos(clamp(-1.0, 1.0, -normal(2))); - m_on_gizmo_flatten_callback.call(angle, (float)axis(0), (float)axis(1), (float)axis(2)); - } -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM } m_dirty = true; @@ -4215,7 +4114,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) } case Gizmos::Scale: { -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM // Apply new temporary scale factors #if ENABLE_EXTENDED_SELECTION m_selection.scale(m_gizmos.get_scale()); @@ -4228,20 +4126,10 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) } wxGetApp().obj_manipul()->update_scale_value(scale); #endif // ENABLE_EXTENDED_SELECTION -#else - // Apply new temporary scale factor - float scale_factor = m_gizmos.get_scale(); - for (GLVolume* v : volumes) - { - v->set_scaling_factor((double)scale_factor); - } - wxGetApp().obj_manipul()->update_scale_values((double)scale_factor); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM break; } case Gizmos::Rotate: { -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM // Apply new temporary rotations #if ENABLE_EXTENDED_SELECTION m_selection.rotate(m_gizmos.get_rotation()); @@ -4255,15 +4143,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) } wxGetApp().obj_manipul()->update_rotation_value(rotation); #endif // ENABLE_EXTENDED_SELECTION -#else - // Apply new temporary angle_z - float angle_z = m_gizmos.get_angle_z(); - for (GLVolume* v : volumes) - { - v->set_rotation((double)angle_z); - } - update_rotation_value((double)angle_z, Z); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM break; } default: @@ -4280,12 +4159,8 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) bb.merge(volume->transformed_bounding_box()); } const Vec3d& size = bb.size(); -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM const Vec3d& scale = m_gizmos.get_scale(); post_event(Vec3dsEvent<2>(EVT_GLCANVAS_UPDATE_GEOMETRY, {size, scale})); -#else - m_on_update_geometry_info_callback.call(size(0), size(1), size(2), m_gizmos.get_scale()); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM } #endif // ENABLE_EXTENDED_SELECTION @@ -4428,28 +4303,20 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) } case Gizmos::Scale: { -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM #if ENABLE_EXTENDED_SELECTION m_regenerate_volumes = false; _on_scale(); #endif // ENABLE_EXTENDED_SELECTION -#else - m_on_gizmo_scale_uniformly_callback.call((double)m_gizmos.get_scale()); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM break; } case Gizmos::Rotate: { -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM #if ENABLE_EXTENDED_SELECTION m_regenerate_volumes = false; _on_rotate(); #else post_event(Vec3dEvent(EVT_GIZMO_ROTATE, m_gizmos.get_rotation())); #endif // ENABLE_EXTENDED_SELECTION -#else - m_on_gizmo_rotate_callback.call((double)m_gizmos.get_angle_z()); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM break; } default: @@ -6625,12 +6492,7 @@ void GLCanvas3D::_on_move(const std::vector& volume_idxs) ModelObject* model_object = m_model->objects[obj_idx]; if (model_object != nullptr) { -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM model_object->instances[instance_idx]->set_offset(volume->get_offset()); -#else - const Vec3d& offset = volume->get_offset(); - model_object->instances[instance_idx]->offset = Vec2d(offset(0), offset(1)); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM model_object->invalidate_bounding_box(); wxGetApp().obj_manipul()->update_position_values(); object_moved = true; diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index a6d84eaa34..8029ed4c44 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -589,7 +589,6 @@ private: void set_position(const Vec3d& position); #endif // ENABLE_EXTENDED_SELECTION -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM Vec3d get_scale() const; void set_scale(const Vec3d& scale); @@ -597,15 +596,6 @@ private: void set_rotation(const Vec3d& rotation); Vec3d get_flattening_rotation() const; -#else - float get_scale() const; - void set_scale(float scale); - - float get_angle_z() const; - void set_angle_z(float angle_z); - - Vec3d get_flattening_normal() const; -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM void set_flattening_data(const ModelObject* model_object); diff --git a/src/slic3r/GUI/GLGizmo.cpp b/src/slic3r/GUI/GLGizmo.cpp index b1e7473aa9..88672f5061 100644 --- a/src/slic3r/GUI/GLGizmo.cpp +++ b/src/slic3r/GUI/GLGizmo.cpp @@ -1086,11 +1086,7 @@ void GLGizmoScale3D::do_scale_y(const Linef3& mouse_ray) #endif // ENABLE_EXTENDED_SELECTION if (ratio > 0.0) -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM m_scale(1) = m_starting_scale(1) * ratio; -#else - m_scale(0) = m_starting_scale(1) * ratio; -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM } void GLGizmoScale3D::do_scale_z(const Linef3& mouse_ray) @@ -1102,11 +1098,7 @@ void GLGizmoScale3D::do_scale_z(const Linef3& mouse_ray) #endif // ENABLE_EXTENDED_SELECTION if (ratio > 0.0) -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM m_scale(2) = m_starting_scale(2) * ratio; -#else - m_scale(0) = m_starting_scale(2) * ratio; // << this is temporary -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM } void GLGizmoScale3D::do_scale_uniform(const Linef3& mouse_ray) @@ -1490,18 +1482,11 @@ void GLGizmoFlatten::on_render(const BoundingBoxf3& box) const else ::glColor4f(0.9f, 0.9f, 0.9f, 0.5f); -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM for (const InstanceData& inst : m_instances) { Transform3d m = inst.matrix; m.pretranslate(dragged_offset); ::glPushMatrix(); ::glMultMatrixd(m.data()); -#else - for (Vec2d offset : m_instances_positions) { - offset += to_2d(dragged_offset); - ::glPushMatrix(); - ::glTranslatef((GLfloat)offset(0), (GLfloat)offset(1), 0.0f); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM ::glBegin(GL_POLYGON); for (const Vec3d& vertex : m_planes[i].vertices) ::glVertex3dv(vertex.data()); @@ -1524,15 +1509,9 @@ void GLGizmoFlatten::on_render_for_picking(const BoundingBoxf3& box) const for (unsigned int i = 0; i < m_planes.size(); ++i) { ::glColor3f(1.0f, 1.0f, picking_color_component(i)); -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM for (const InstanceData& inst : m_instances) { ::glPushMatrix(); ::glMultMatrixd(inst.matrix.data()); -#else - for (const Vec2d& offset : m_instances_positions) { - ::glPushMatrix(); - ::glTranslatef((GLfloat)offset(0), (GLfloat)offset(1), 0.0f); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM ::glBegin(GL_POLYGON); for (const Vec3d& vertex : m_planes[i].vertices) ::glVertex3dv(vertex.data()); @@ -1548,17 +1527,9 @@ void GLGizmoFlatten::set_flattening_data(const ModelObject* model_object) // ...and save the updated positions of the object instances: if (m_model_object && !m_model_object->instances.empty()) { -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM m_instances.clear(); -#else - m_instances_positions.clear(); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM for (const auto* instance : m_model_object->instances) -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM m_instances.emplace_back(instance->world_matrix()); -#else - m_instances_positions.emplace_back(instance->offset); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM } if (is_plane_update_necessary()) @@ -1572,10 +1543,6 @@ void GLGizmoFlatten::update_planes() ch.merge(vol->get_convex_hull()); ch = ch.convex_hull_3d(); -#if !ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - ch.scale(m_model_object->instances.front()->scaling_factor); - ch.rotate_z(m_model_object->instances.front()->rotation); -#endif // !ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM const Vec3d& bb_size = ch.bounding_box().size(); double min_bb_face_area = std::min(bb_size(0) * bb_size(1), std::min(bb_size(0) * bb_size(2), bb_size(1) * bb_size(2))); @@ -1741,10 +1708,6 @@ void GLGizmoFlatten::update_planes() m_source_data.bounding_boxes.clear(); for (const auto& vol : m_model_object->volumes) m_source_data.bounding_boxes.push_back(vol->get_convex_hull().bounding_box()); -#if !ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - m_source_data.scaling_factor = m_model_object->instances.front()->scaling_factor; - m_source_data.rotation = m_model_object->instances.front()->rotation; -#endif // !ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM const float* first_vertex = m_model_object->volumes.front()->get_convex_hull().first_vertex(); m_source_data.mesh_first_point = Vec3d((double)first_vertex[0], (double)first_vertex[1], (double)first_vertex[2]); } @@ -1756,13 +1719,7 @@ bool GLGizmoFlatten::is_plane_update_necessary() const if (m_state != On || !m_model_object || m_model_object->instances.empty()) return false; -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM if (m_model_object->volumes.size() != m_source_data.bounding_boxes.size()) -#else - if (m_model_object->volumes.size() != m_source_data.bounding_boxes.size() - || m_model_object->instances.front()->scaling_factor != m_source_data.scaling_factor - || m_model_object->instances.front()->rotation != m_source_data.rotation) -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM return true; // now compare the bounding boxes: @@ -1778,7 +1735,6 @@ bool GLGizmoFlatten::is_plane_update_necessary() const return false; } -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM Vec3d GLGizmoFlatten::get_flattening_rotation() const { // calculates the rotations in model space, taking in account the scaling factors @@ -1788,13 +1744,6 @@ Vec3d GLGizmoFlatten::get_flattening_rotation() const m_normal = Vec3d::Zero(); return Vec3d(angles(2), angles(1), angles(0)); } -#else -Vec3d GLGizmoFlatten::get_flattening_normal() const { - Vec3d normal = m_model_object->instances.front()->world_matrix(true).matrix().block(0, 0, 3, 3).inverse() * m_normal; - m_normal = Vec3d::Zero(); - return normal.normalized(); -} -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM } // namespace GUI } // namespace Slic3r diff --git a/src/slic3r/GUI/GLGizmo.hpp b/src/slic3r/GUI/GLGizmo.hpp index 8babd21e5d..7c0196a83c 100644 --- a/src/slic3r/GUI/GLGizmo.hpp +++ b/src/slic3r/GUI/GLGizmo.hpp @@ -230,19 +230,8 @@ class GLGizmoRotate3D : public GLGizmoBase public: explicit GLGizmoRotate3D(GLCanvas3D& parent); -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM Vec3d get_rotation() const { return Vec3d(m_gizmos[X].get_angle(), m_gizmos[Y].get_angle(), m_gizmos[Z].get_angle()); } void set_rotation(const Vec3d& rotation) { m_gizmos[X].set_angle(rotation(0)); m_gizmos[Y].set_angle(rotation(1)); m_gizmos[Z].set_angle(rotation(2)); } -#else - double get_angle_x() const { return m_gizmos[X].get_angle(); } - void set_angle_x(double angle) { m_gizmos[X].set_angle(angle); } - - double get_angle_y() const { return m_gizmos[Y].get_angle(); } - void set_angle_y(double angle) { m_gizmos[Y].set_angle(angle); } - - double get_angle_z() const { return m_gizmos[Z].get_angle(); } - void set_angle_z(double angle) { m_gizmos[Z].set_angle(angle); } -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM protected: virtual bool on_init(); @@ -329,25 +318,12 @@ class GLGizmoScale3D : public GLGizmoBase public: explicit GLGizmoScale3D(GLCanvas3D& parent); -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM const Vec3d& get_scale() const { return m_scale; } #if ENABLE_EXTENDED_SELECTION void set_scale(const Vec3d& scale) { m_starting_scale = scale; m_scale = scale; } #else void set_scale(const Vec3d& scale) { m_starting_scale = scale; } #endif // ENABLE_EXTENDED_SELECTION -#else - double get_scale_x() const { return m_scale(0); } - void set_scale_x(double scale) { m_starting_scale(0) = scale; } - - double get_scale_y() const { return m_scale(1); } - void set_scale_y(double scale) { m_starting_scale(1) = scale; } - - double get_scale_z() const { return m_scale(2); } - void set_scale_z(double scale) { m_starting_scale(2) = scale; } - - void set_scale(double scale) { m_starting_scale = scale * Vec3d::Ones(); } -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM protected: virtual bool on_init(); @@ -444,10 +420,6 @@ private: }; struct SourceDataSummary { std::vector bounding_boxes; // bounding boxes of convex hulls of individual volumes -#if !ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - float scaling_factor; - float rotation; -#endif // !ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM Vec3d mesh_first_point; }; @@ -455,16 +427,12 @@ private: SourceDataSummary m_source_data; std::vector m_planes; -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM struct InstanceData { Transform3d matrix; InstanceData(const Transform3d& matrix) : matrix(matrix) {} }; std::vector m_instances; -#else - std::vector m_instances_positions; -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM Vec3d m_starting_center; const ModelObject* m_model_object = nullptr; @@ -475,11 +443,7 @@ public: explicit GLGizmoFlatten(GLCanvas3D& parent); void set_flattening_data(const ModelObject* model_object); -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM Vec3d get_flattening_rotation() const; -#else - Vec3d get_flattening_normal() const; -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM protected: virtual bool on_init(); diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index 94425a5e8d..fc51b419ba 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -375,7 +375,6 @@ void ObjectManipulation::update_scale_values() auto instance = objects[selection]->instances.front(); auto size = objects[selection]->instance_bounding_box(0).size(); -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM if (m_is_percent_scale) { m_og->set_value("scale_x", int(instance->get_scaling_factor(X) * 100)); m_og->set_value("scale_y", int(instance->get_scaling_factor(Y) * 100)); @@ -386,34 +385,15 @@ void ObjectManipulation::update_scale_values() m_og->set_value("scale_y", int(instance->get_scaling_factor(Y) * size(1) + 0.5)); m_og->set_value("scale_z", int(instance->get_scaling_factor(Z) * size(2) + 0.5)); } -#else - if (m_is_percent_scale) { - auto scale = instance->scaling_factor * 100.0; - m_og->set_value("scale_x", int(scale)); - m_og->set_value("scale_y", int(scale)); - m_og->set_value("scale_z", int(scale)); - } - else { - m_og->set_value("scale_x", int(instance->scaling_factor * size(0) + 0.5)); - m_og->set_value("scale_y", int(instance->scaling_factor * size(1) + 0.5)); - m_og->set_value("scale_z", int(instance->scaling_factor * size(2) + 0.5)); - } -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM } void ObjectManipulation::update_position_values() { auto instance = wxGetApp().mainframe->m_plater->model().objects[ol_selection()]->instances.front(); -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM m_og->set_value("position_x", int(instance->get_offset(X))); m_og->set_value("position_y", int(instance->get_offset(Y))); m_og->set_value("position_z", int(instance->get_offset(Z))); -#else - m_og->set_value("position_x", int(instance->offset(0))); - m_og->set_value("position_y", int(instance->offset(1))); - m_og->set_value("position_z", 0); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM } void ObjectManipulation::update_position_value(const Vec3d& position) @@ -423,7 +403,6 @@ void ObjectManipulation::update_position_value(const Vec3d& position) m_og->set_value("position_z", int(position(2))); } -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM void ObjectManipulation::update_scale_value(const Vec3d& scaling_factor) { // this is temporary @@ -438,33 +417,10 @@ void ObjectManipulation::update_scale_value(const Vec3d& scaling_factor) m_og->set_value("scale_y", int(scale(1))); m_og->set_value("scale_z", int(scale(2))); } -#else -void ObjectManipulation::update_scale_values(double scaling_factor) -{ - // this is temporary - // to be able to update the values as size - // we need to store somewhere the original size - // or have it passed as parameter - if (!m_is_percent_scale) - m_og->set_value("scale_unit", _("%")); - - auto scale = scaling_factor * 100.0; - m_og->set_value("scale_x", int(scale)); - m_og->set_value("scale_y", int(scale)); - m_og->set_value("scale_z", int(scale)); -} -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM void ObjectManipulation::update_rotation_values() { -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM update_rotation_value(wxGetApp().mainframe->m_plater->model().objects[ol_selection()]->instances.front()->get_rotation()); -#else - auto instance = wxGetApp().mainframe->m_plater->model().objects[ol_selection()]->instances.front(); - m_og->set_value("rotation_x", 0); - m_og->set_value("rotation_y", 0); - m_og->set_value("rotation_z", int(Geometry::rad2deg(instance->rotation))); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM } void ObjectManipulation::update_rotation_value(double angle, Axis axis) @@ -485,14 +441,12 @@ void ObjectManipulation::update_rotation_value(double angle, Axis axis) m_og->set_value(axis_str, round_nearest(int(Geometry::rad2deg(angle)), 0)); } -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM void ObjectManipulation::update_rotation_value(const Vec3d& rotation) { m_og->set_value("rotation_x", int(round_nearest(Geometry::rad2deg(rotation(0)), 0))); m_og->set_value("rotation_y", int(round_nearest(Geometry::rad2deg(rotation(1)), 0))); m_og->set_value("rotation_z", int(round_nearest(Geometry::rad2deg(rotation(2)), 0))); } -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM void ObjectManipulation::show_object_name(bool show) { diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.hpp b/src/slic3r/GUI/GUI_ObjectManipulation.hpp index c0cd701603..13b9290a0a 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.hpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.hpp @@ -61,18 +61,12 @@ public: void update_position_value(const Vec3d& position); // update scale values after scale unit changing or "gizmos" void update_scale_values(); -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM void update_scale_value(const Vec3d& scaling_factor); -#else - void update_scale_values(double scaling_factor); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM // update rotation values object selection changing void update_rotation_values(); // update rotation value after "gizmos" void update_rotation_value(double angle, Axis axis); -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM void update_rotation_value(const Vec3d& rotation); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM void set_uniform_scaling(const bool uniform_scale) { m_is_uniform_scale = uniform_scale; } diff --git a/xs/xsp/Model.xsp b/xs/xsp/Model.xsp index 62ccf2b06c..cfe34a7943 100644 --- a/xs/xsp/Model.xsp +++ b/xs/xsp/Model.xsp @@ -295,7 +295,6 @@ ModelMaterial::attributes() Ref object() %code%{ RETVAL = THIS->get_object(); %}; -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM Vec3d* rotation() %code%{ RETVAL = new Vec3d(THIS->get_rotation(X), THIS->get_rotation(Y), THIS->get_rotation(Z)); %}; @@ -322,25 +321,6 @@ ModelMaterial::attributes() THIS->set_offset(X, (*offset)(0)); THIS->set_offset(Y, (*offset)(1)); %}; -#else - double rotation() - %code%{ RETVAL = THIS->rotation; %}; - - double scaling_factor() - %code%{ RETVAL = THIS->scaling_factor; %}; - - Ref offset() - %code%{ RETVAL = &THIS->offset; %}; - - void set_rotation(double val) - %code%{ THIS->rotation = val; THIS->get_object()->invalidate_bounding_box(); %}; - - void set_scaling_factor(double val) - %code%{ THIS->scaling_factor = val; THIS->get_object()->invalidate_bounding_box(); %}; - - void set_offset(Vec2d *offset) - %code%{ THIS->offset = *offset; %}; -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM void transform_mesh(TriangleMesh* mesh, bool dont_translate = false) const; void transform_polygon(Polygon* polygon) const; From 0263769d8f5462523cbf32899be5d4e4f3629ea1 Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Tue, 16 Oct 2018 09:20:56 +0200 Subject: [PATCH 107/186] deps: Back to Boost 1.63 on Windows as newer ones require newer CMake 32bit deps fix --- deps/CMakeLists.txt | 10 ++++++---- deps/deps-windows.cmake | 4 ++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/deps/CMakeLists.txt b/deps/CMakeLists.txt index a20c7aa18c..72df1a2fcb 100644 --- a/deps/CMakeLists.txt +++ b/deps/CMakeLists.txt @@ -13,13 +13,15 @@ if (MSVC) set(DEPS_BITS 64) set(DESTDIR "${CMAKE_CURRENT_BINARY_DIR}/destdir-64") include("deps-windows.cmake") + add_custom_target(deps_64 + DEPENDS dep_boost_64 dep_tbb_64 dep_libcurl_64 dep_wxwidgets_64 + ) + set(DEPS_BITS 32) set(DESTDIR "${CMAKE_CURRENT_BINARY_DIR}/destdir-32") include("deps-windows.cmake") - - add_custom_target(deps ALL - DEPENDS dep_boost_64 dep_tbb_64 dep_libcurl_64 dep_wxwidgets_64 - # dep_boost_32 dep_tbb_32 dep_libcurl_32 dep_wxwidgets_32 + add_custom_target(deps_32 + DEPENDS dep_boost_32 dep_tbb_32 dep_libcurl_32 dep_wxwidgets_32 ) else () set(DESTDIR "${CMAKE_CURRENT_BINARY_DIR}/destdir") diff --git a/deps/deps-windows.cmake b/deps/deps-windows.cmake index eaf5b8e65b..8a276c54e8 100644 --- a/deps/deps-windows.cmake +++ b/deps/deps-windows.cmake @@ -1,8 +1,8 @@ ExternalProject_Add("dep_boost_${DEPS_BITS}" EXCLUDE_FROM_ALL 1 - URL "https://dl.bintray.com/boostorg/release/1.66.0/source/boost_1_66_0.tar.gz" - URL_HASH SHA256=bd0df411efd9a585e5a2212275f8762079fed8842264954675a4fddc46cfcf60 + URL "https://dl.bintray.com/boostorg/release/1.63.0/source/boost_1_63_0.tar.gz" + URL_HASH SHA256=fe34a4e119798e10b8cc9e565b3b0284e9fd3977ec8a1b19586ad1dec397088b BUILD_IN_SOURCE 1 CONFIGURE_COMMAND bootstrap.bat BUILD_COMMAND b2.exe From 97e7b6f18b83100b25998ba737b5a1df0a8af529 Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Tue, 16 Oct 2018 11:06:26 +0200 Subject: [PATCH 108/186] deps: Fix arch resolution on Windows --- deps/CMakeLists.txt | 53 +++++++++++++++++++++++++++-------------- deps/deps-windows.cmake | 14 +++++------ 2 files changed, 42 insertions(+), 25 deletions(-) diff --git a/deps/CMakeLists.txt b/deps/CMakeLists.txt index 72df1a2fcb..852d17fa2c 100644 --- a/deps/CMakeLists.txt +++ b/deps/CMakeLists.txt @@ -1,3 +1,21 @@ +# +# This CMake project downloads, configures and builds Slic3r PE dependencies on Unix and Windows. +# +# When using this script, it's recommended to perform an out-of-source build using CMake. +# +# All the dependencies are installed in a `destdir` directory in the root of the build directory, +# in a traditional Unix-style prefix structure. The destdir can be used directly by CMake +# when building Slic3r - to do this, set the CMAKE_PREFIX_PATH to the destdir's location. +# +# For better clarity of console output, it's recommended to _not_ use a parallelized build +# for the top-level command, ie. use `make -j 1` or `ninja -j 1` to force single-threaded top-level +# build. This doesn't degrade performance as individual dependencies are built in parallel fashion +# as appropriate anyway (cf. the `NPROC` variable). +# +# On Windows, architecture (64 vs 32 bits) is judged based on the compiler variant. +# To build dependencies for either 64 or 32 bit OS, use the respective compiler command line. +# + project(Slic3r-deps) cmake_minimum_required(VERSION 3.2) @@ -9,28 +27,27 @@ if (NPROC EQUAL 0) set(NPROC 1) endif () +set(DESTDIR "${CMAKE_CURRENT_BINARY_DIR}/destdir") + if (MSVC) - set(DEPS_BITS 64) - set(DESTDIR "${CMAKE_CURRENT_BINARY_DIR}/destdir-64") - include("deps-windows.cmake") - add_custom_target(deps_64 - DEPENDS dep_boost_64 dep_tbb_64 dep_libcurl_64 dep_wxwidgets_64 - ) - - set(DEPS_BITS 32) - set(DESTDIR "${CMAKE_CURRENT_BINARY_DIR}/destdir-32") - include("deps-windows.cmake") - add_custom_target(deps_32 - DEPENDS dep_boost_32 dep_tbb_32 dep_libcurl_32 dep_wxwidgets_32 - ) + if ("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8") + message(STATUS "\nDetected 64-bit compiler => building 64-bit deps bundle\n") + set(DEPS_BITS 64) + include("deps-windows.cmake") + elseif ("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4") + message(STATUS "\nDetected 32-bit compiler => building 32-bit deps bundle\n") + set(DEPS_BITS 32) + include("deps-windows.cmake") + else () + message(FATAL_ERROR "Unable to detect architecture") + endif () else () - set(DESTDIR "${CMAKE_CURRENT_BINARY_DIR}/destdir") include("deps-unix-static.cmake") - - add_custom_target(deps ALL - DEPENDS dep_boost dep_tbb dep_libcurl dep_wxwidgets - ) endif() +add_custom_target(deps ALL + DEPENDS dep_boost dep_tbb dep_libcurl dep_wxwidgets +) + # Note: I'm not using any of the LOG_xxx options in ExternalProject_Add() commands # because they seem to generate bogus build files (possibly a bug in ExternalProject). diff --git a/deps/deps-windows.cmake b/deps/deps-windows.cmake index 8a276c54e8..2be0d448aa 100644 --- a/deps/deps-windows.cmake +++ b/deps/deps-windows.cmake @@ -1,5 +1,5 @@ -ExternalProject_Add("dep_boost_${DEPS_BITS}" +ExternalProject_Add(dep_boost EXCLUDE_FROM_ALL 1 URL "https://dl.bintray.com/boostorg/release/1.63.0/source/boost_1_63_0.tar.gz" URL_HASH SHA256=fe34a4e119798e10b8cc9e565b3b0284e9fd3977ec8a1b19586ad1dec397088b @@ -25,13 +25,13 @@ ExternalProject_Add("dep_boost_${DEPS_BITS}" ) -if ($DEPS_BITS EQUAL 32) +if (${DEPS_BITS} EQUAL 32) set(DEP_TBB_GEN "Visual Studio 12") else () set(DEP_TBB_GEN "Visual Studio 12 Win64") endif () -ExternalProject_Add("dep_tbb_${DEPS_BITS}" +ExternalProject_Add(dep_tbb EXCLUDE_FROM_ALL 1 URL "https://github.com/wjakob/tbb/archive/a0dc9bf76d0120f917b641ed095360448cabc85b.tar.gz" URL_HASH SHA256=0545cb6033bd1873fcae3ea304def720a380a88292726943ae3b9b207f322efe @@ -46,13 +46,13 @@ ExternalProject_Add("dep_tbb_${DEPS_BITS}" ) -if ($DEPS_BITS EQUAL 32) +if (${DEPS_BITS} EQUAL 32) set(DEP_LIBCURL_TARGET "x86") else () set(DEP_LIBCURL_TARGET "x64") endif () -ExternalProject_Add("dep_libcurl_${DEPS_BITS}" +ExternalProject_Add(dep_libcurl EXCLUDE_FROM_ALL 1 URL "https://curl.haxx.se/download/curl-7.58.0.tar.gz" URL_HASH SHA256=cc245bf9a1a42a45df491501d97d5593392a03f7b4f07b952793518d97666115 @@ -64,7 +64,7 @@ ExternalProject_Add("dep_libcurl_${DEPS_BITS}" && "${CMAKE_COMMAND}" -E copy_directory lib "${DESTDIR}\\usr\\local\\lib" ) -if ($DEPS_BITS EQUAL 32) +if (${DEPS_BITS} EQUAL 32) set(DEP_WXWIDGETS_TARGET "") set(DEP_WXWIDGETS_LIBDIR "vc_lib") else () @@ -72,7 +72,7 @@ else () set(DEP_WXWIDGETS_LIBDIR "vc_x64_lib") endif () -ExternalProject_Add("dep_wxwidgets_${DEPS_BITS}" +ExternalProject_Add(dep_wxwidgets EXCLUDE_FROM_ALL 1 URL "https://github.com/wxWidgets/wxWidgets/releases/download/v3.1.1/wxWidgets-3.1.1.tar.bz2" URL_HASH SHA256=c925dfe17e8f8b09eb7ea9bfdcfcc13696a3e14e92750effd839f5e10726159e From a8c459696f80ab696946ad16e44cd07cc9d884f0 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Tue, 16 Oct 2018 13:49:40 +0200 Subject: [PATCH 109/186] New selection -> Tighter bounding box for selections, tweaks to gizmo flatten and fix of instances update --- src/slic3r/GUI/GLCanvas3D.cpp | 51 ++++++++++++++++++++++++----------- src/slic3r/GUI/GLCanvas3D.hpp | 3 ++- src/slic3r/GUI/GLGizmo.cpp | 36 +++++++++++++++++++++++++ src/slic3r/GUI/GLGizmo.hpp | 2 ++ 4 files changed, 75 insertions(+), 17 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 47729cffb6..440ca5fc6f 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1346,7 +1346,7 @@ bool GLCanvas3D::Selection::is_single_full_instance() const int object_idx = m_valid ? get_object_idx() : -1; if (object_idx != -1) { - if (get_instance_idx() != -1) + if ((object_idx != -1) && (object_idx < 1000)) return m_model->objects[object_idx]->volumes.size() == m_list.size(); } @@ -1653,7 +1653,7 @@ void GLCanvas3D::Selection::_calc_bounding_box() const { for (unsigned int i : m_list) { - m_bounding_box.merge((*m_volumes)[i]->transformed_bounding_box()); + m_bounding_box.merge((*m_volumes)[i]->transformed_convex_hull_bounding_box()); } } m_bounding_box_dirty = false; @@ -1702,7 +1702,7 @@ void GLCanvas3D::Selection::_render_unselected_instances() const if (it == boxes.end()) it = boxes.insert(InstanceToBoxMap::value_type(box_id, BoundingBoxf3())).first; - it->second.merge(v->transformed_bounding_box()); + it->second.merge(v->transformed_convex_hull_bounding_box()); done.insert(j); } @@ -2081,6 +2081,9 @@ bool GLCanvas3D::Gizmos::is_running() const bool GLCanvas3D::Gizmos::is_dragging() const { + if (!m_enabled) + return false; + GLGizmoBase* curr = _get_current(); return (curr != nullptr) ? curr->is_dragging() : false; } @@ -2088,6 +2091,9 @@ bool GLCanvas3D::Gizmos::is_dragging() const #if ENABLE_EXTENDED_SELECTION void GLCanvas3D::Gizmos::start_dragging(const GLCanvas3D::Selection& selection) { + if (!m_enabled) + return; + GLGizmoBase* curr = _get_current(); if (curr != nullptr) curr->start_dragging(selection); @@ -2095,6 +2101,9 @@ void GLCanvas3D::Gizmos::start_dragging(const GLCanvas3D::Selection& selection) #else void GLCanvas3D::Gizmos::start_dragging(const BoundingBoxf3& box) { + if (!m_enabled) + return; + GLGizmoBase* curr = _get_current(); if (curr != nullptr) curr->start_dragging(box); @@ -2103,6 +2112,9 @@ void GLCanvas3D::Gizmos::start_dragging(const BoundingBoxf3& box) void GLCanvas3D::Gizmos::stop_dragging() { + if (!m_enabled) + return; + GLGizmoBase* curr = _get_current(); if (curr != nullptr) curr->stop_dragging(); @@ -2650,8 +2662,8 @@ wxDEFINE_EVENT(EVT_GLCANVAS_UPDATE_GEOMETRY, Vec3dsEvent<2>); #if !ENABLE_EXTENDED_SELECTION wxDEFINE_EVENT(EVT_GIZMO_SCALE, Vec3dEvent); wxDEFINE_EVENT(EVT_GIZMO_ROTATE, Vec3dEvent); -#endif // !ENABLE_EXTENDED_SELECTION wxDEFINE_EVENT(EVT_GIZMO_FLATTEN, Vec3dEvent); +#endif // !ENABLE_EXTENDED_SELECTION GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas) : m_canvas(canvas) @@ -3784,7 +3796,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) m_selection.scale(m_gizmos.get_scale()); _on_scale(); #else - m_on_gizmo_scale_uniformly_callback.call((double)m_gizmos.get_scale()); + post_event(Vec3dEvent(EVT_GIZMO_SCALE, m_gizmos.get_scale())); #endif // ENABLE_EXTENDED_SELECTION #if ENABLE_EXTENDED_SELECTION wxGetApp().obj_manipul()->update_settings_value(m_selection); @@ -3879,7 +3891,14 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) if (m_gizmos.get_current_type() == Gizmos::Flatten) { // Rotate the object so the normal points downward: +#if ENABLE_EXTENDED_SELECTION + m_regenerate_volumes = false; + m_selection.rotate(m_gizmos.get_flattening_rotation()); + _on_flatten(); + wxGetApp().obj_manipul()->update_settings_value(m_selection); +#else post_event(Vec3dEvent(EVT_GIZMO_FLATTEN, m_gizmos.get_flattening_rotation())); +#endif // ENABLE_EXTENDED_SELECTION } m_dirty = true; @@ -5002,7 +5021,7 @@ void GLCanvas3D::_render_objects() const void GLCanvas3D::_render_selection() const { Gizmos::EType type = m_gizmos.get_current_type(); - bool show_indirect_selection = m_gizmos.is_running() && ((type == Gizmos::Rotate) || (type == Gizmos::Scale)); + bool show_indirect_selection = m_gizmos.is_running() && ((type == Gizmos::Rotate) || (type == Gizmos::Scale) || (type == Gizmos::Flatten)); m_selection.render(show_indirect_selection); } #endif // ENABLE_EXTENDED_SELECTION @@ -6354,11 +6373,9 @@ void GLCanvas3D::_on_move() std::set> done; // prevent moving instances twice bool object_moved = false; Vec3d wipe_tower_origin = Vec3d::Zero(); - const Selection::IndicesList& selection = m_selection.get_volume_idxs(); - for (unsigned int i : selection) + for (const GLVolume* v : m_volumes.volumes) { - const GLVolume* v = m_volumes.volumes[i]; int object_idx = v->object_idx(); int instance_idx = v->instance_idx(); @@ -6398,11 +6415,9 @@ void GLCanvas3D::_on_rotate() return; std::set> done; // prevent rotating instances twice - const Selection::IndicesList& selection = m_selection.get_volume_idxs(); - for (unsigned int i : selection) + for (const GLVolume* v : m_volumes.volumes) { - const GLVolume* v = m_volumes.volumes[i]; int object_idx = v->object_idx(); if (object_idx >= 1000) continue; @@ -6434,18 +6449,16 @@ void GLCanvas3D::_on_scale() return; std::set> done; // prevent scaling instances twice - const Selection::IndicesList& selection = m_selection.get_volume_idxs(); - for (unsigned int i : selection) + for (const GLVolume* v : m_volumes.volumes) { - const GLVolume* v = m_volumes.volumes[i]; int object_idx = v->object_idx(); if (object_idx >= 1000) continue; int instance_idx = v->instance_idx(); - // prevent rotating instances twice + // prevent scaling instances twice std::pair done_id(object_idx, instance_idx); if (done.find(done_id) != done.end()) continue; @@ -6463,6 +6476,12 @@ void GLCanvas3D::_on_scale() // schedule_background_process } + +void GLCanvas3D::_on_flatten() +{ + _on_rotate(); +} + #else void GLCanvas3D::_on_move(const std::vector& volume_idxs) { diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 8029ed4c44..e4019e2a1d 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -118,8 +118,8 @@ wxDECLARE_EVENT(EVT_GLCANVAS_UPDATE_GEOMETRY, Vec3dsEvent<2>); #if !ENABLE_EXTENDED_SELECTION wxDECLARE_EVENT(EVT_GIZMO_SCALE, Vec3dEvent); wxDECLARE_EVENT(EVT_GIZMO_ROTATE, Vec3dEvent); -#endif // !ENABLE_EXTENDED_SELECTION wxDECLARE_EVENT(EVT_GIZMO_FLATTEN, Vec3dEvent); +#endif // !ENABLE_EXTENDED_SELECTION class GLCanvas3D @@ -946,6 +946,7 @@ private: void _on_move(); void _on_rotate(); void _on_scale(); + void _on_flatten(); #else void _on_move(const std::vector& volume_idxs); #endif // ENABLE_EXTENDED_SELECTION diff --git a/src/slic3r/GUI/GLGizmo.cpp b/src/slic3r/GUI/GLGizmo.cpp index 88672f5061..e01f57ff90 100644 --- a/src/slic3r/GUI/GLGizmo.cpp +++ b/src/slic3r/GUI/GLGizmo.cpp @@ -1482,6 +1482,23 @@ void GLGizmoFlatten::on_render(const BoundingBoxf3& box) const else ::glColor4f(0.9f, 0.9f, 0.9f, 0.5f); +#if ENABLE_EXTENDED_SELECTION + int instance_idx = selection.get_instance_idx(); + if ((instance_idx != -1) && (m_model_object != nullptr)) + { + Transform3d m = m_model_object->instances[instance_idx]->world_matrix(); + m.pretranslate(dragged_offset); + ::glPushMatrix(); + ::glMultMatrixd(m.data()); + ::glBegin(GL_POLYGON); + for (const Vec3d& vertex : m_planes[i].vertices) + { + ::glVertex3dv(vertex.data()); + } + ::glEnd(); + ::glPopMatrix(); + } +#else for (const InstanceData& inst : m_instances) { Transform3d m = inst.matrix; m.pretranslate(dragged_offset); @@ -1493,6 +1510,7 @@ void GLGizmoFlatten::on_render(const BoundingBoxf3& box) const ::glEnd(); ::glPopMatrix(); } +#endif // ENABLE_EXTENDED_SELECTION } ::glDisable(GL_BLEND); @@ -1509,6 +1527,21 @@ void GLGizmoFlatten::on_render_for_picking(const BoundingBoxf3& box) const for (unsigned int i = 0; i < m_planes.size(); ++i) { ::glColor3f(1.0f, 1.0f, picking_color_component(i)); +#if ENABLE_EXTENDED_SELECTION + int instance_idx = selection.get_instance_idx(); + if ((instance_idx != -1) && (m_model_object != nullptr)) + { + ::glPushMatrix(); + ::glMultMatrixd(m_model_object->instances[instance_idx]->world_matrix().data()); + ::glBegin(GL_POLYGON); + for (const Vec3d& vertex : m_planes[i].vertices) + { + ::glVertex3dv(vertex.data()); + } + ::glEnd(); + ::glPopMatrix(); + } +#else for (const InstanceData& inst : m_instances) { ::glPushMatrix(); ::glMultMatrixd(inst.matrix.data()); @@ -1518,6 +1551,7 @@ void GLGizmoFlatten::on_render_for_picking(const BoundingBoxf3& box) const ::glEnd(); ::glPopMatrix(); } +#endif // ENABLE_EXTENDED_SELECTION } } @@ -1525,12 +1559,14 @@ void GLGizmoFlatten::set_flattening_data(const ModelObject* model_object) { m_model_object = model_object; +#if !ENABLE_EXTENDED_SELECTION // ...and save the updated positions of the object instances: if (m_model_object && !m_model_object->instances.empty()) { m_instances.clear(); for (const auto* instance : m_model_object->instances) m_instances.emplace_back(instance->world_matrix()); } +#endif // !ENABLE_EXTENDED_SELECTION if (is_plane_update_necessary()) update_planes(); diff --git a/src/slic3r/GUI/GLGizmo.hpp b/src/slic3r/GUI/GLGizmo.hpp index 7c0196a83c..cb0ef4f50c 100644 --- a/src/slic3r/GUI/GLGizmo.hpp +++ b/src/slic3r/GUI/GLGizmo.hpp @@ -427,12 +427,14 @@ private: SourceDataSummary m_source_data; std::vector m_planes; +#if !ENABLE_EXTENDED_SELECTION struct InstanceData { Transform3d matrix; InstanceData(const Transform3d& matrix) : matrix(matrix) {} }; std::vector m_instances; +#endif // !ENABLE_EXTENDED_SELECTION Vec3d m_starting_center; const ModelObject* m_model_object = nullptr; From 561bbf5a804c24f3791c69cbaffc75fde578babb Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Tue, 16 Oct 2018 13:56:28 +0200 Subject: [PATCH 110/186] Fix build on non-MSVC --- src/slic3r/GUI/GUI_ObjectList.cpp | 2 +- src/slic3r/GUI/wxExtensions.cpp | 2 +- src/slic3r/GUI/wxExtensions.hpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 4d4de489e1..743ac19b40 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -1191,7 +1191,7 @@ void ObjectList::update_selections_on_canvas() return; } - auto add_to_selection = [this](wxDataViewItem& item, GLCanvas3D::Selection& selection, bool as_single_selection) + auto add_to_selection = [this](const wxDataViewItem& item, GLCanvas3D::Selection& selection, bool as_single_selection) { if (m_objects_model->GetParent(item) == wxDataViewItem(0)){ selection.add_object(m_objects_model->GetIdByItem(item), as_single_selection); diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp index 9c9bcdaeae..be37156410 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -607,7 +607,7 @@ wxDataViewItem PrusaObjectDataViewModel::GetItemByVolumeId(int obj_idx, int volu return wxDataViewItem(0); } -int PrusaObjectDataViewModel::GetIdByItem(wxDataViewItem& item) +int PrusaObjectDataViewModel::GetIdByItem(const wxDataViewItem& item) { wxASSERT(item.IsOk()); diff --git a/src/slic3r/GUI/wxExtensions.hpp b/src/slic3r/GUI/wxExtensions.hpp index 43e5756a42..e199a16489 100644 --- a/src/slic3r/GUI/wxExtensions.hpp +++ b/src/slic3r/GUI/wxExtensions.hpp @@ -422,7 +422,7 @@ public: void DeleteChildren(wxDataViewItem& parent); wxDataViewItem GetItemById(int obj_idx); wxDataViewItem GetItemByVolumeId(int obj_idx, int volume_idx); - int GetIdByItem(wxDataViewItem& item); + int GetIdByItem(const wxDataViewItem& item); int GetVolumeIdByItem(const wxDataViewItem& item); void GetObjectAndVolumeIdsByItem(const wxDataViewItem& item, int& obj_idx, int& vol_idx); bool IsEmpty() { return m_objects.empty(); } From af4570741c440ff47e3173a319947df2e6252344 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Tue, 16 Oct 2018 14:56:35 +0200 Subject: [PATCH 111/186] New selection -> Improved gizmos activation --- src/slic3r/GUI/GLCanvas3D.cpp | 34 ++++++++++++++++++++++++++-------- src/slic3r/GUI/GLCanvas3D.hpp | 1 + src/slic3r/GUI/GLGizmo.cpp | 7 ------- src/slic3r/GUI/GLGizmo.hpp | 18 +++++++++++++----- 4 files changed, 40 insertions(+), 20 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 440ca5fc6f..9ec8201d01 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1893,7 +1893,7 @@ void GLCanvas3D::Gizmos::update_hover_state(const GLCanvas3D& canvas, const Vec2 float cnv_h = (float)canvas.get_canvas_size().get_height(); float height = _get_total_overlay_height(); float top_y = 0.5f * (cnv_h - height); - for (GizmosMap::const_iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it) + for (GizmosMap::iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it) { if (it->second == nullptr) continue; @@ -1903,8 +1903,7 @@ void GLCanvas3D::Gizmos::update_hover_state(const GLCanvas3D& canvas, const Vec2 // we currently use circular icons for gizmo, so we check the radius #if ENABLE_EXTENDED_SELECTION - bool no_wipe_tower = selection.is_wipe_tower() && !it->second->get_accept_wipe_tower(); - if (!no_wipe_tower && (it->second->get_state() != GLGizmoBase::On)) + if (it->second->is_activable(selection) && (it->second->get_state() != GLGizmoBase::On)) #else if (it->second->get_state() != GLGizmoBase::On) #endif // ENABLE_EXTENDED_SELECTION @@ -1928,7 +1927,7 @@ void GLCanvas3D::Gizmos::update_on_off_state(const GLCanvas3D& canvas, const Vec float cnv_h = (float)canvas.get_canvas_size().get_height(); float height = _get_total_overlay_height(); float top_y = 0.5f * (cnv_h - height); - for (GizmosMap::const_iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it) + for (GizmosMap::iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it) { if (it->second == nullptr) continue; @@ -1938,18 +1937,17 @@ void GLCanvas3D::Gizmos::update_on_off_state(const GLCanvas3D& canvas, const Vec // we currently use circular icons for gizmo, so we check the radius #if ENABLE_EXTENDED_SELECTION - bool no_wipe_tower = selection.is_wipe_tower() && !it->second->get_accept_wipe_tower(); - if (!no_wipe_tower && ((mouse_pos - Vec2d(OverlayOffsetX + half_tex_size, top_y + half_tex_size)).norm() < half_tex_size)) + if (it->second->is_activable(selection) && ((mouse_pos - Vec2d(OverlayOffsetX + half_tex_size, top_y + half_tex_size)).norm() < half_tex_size)) #else if ((mouse_pos - Vec2d(OverlayOffsetX + half_tex_size, top_y + half_tex_size)).norm() < half_tex_size) #endif // ENABLE_EXTENDED_SELECTION { if ((it->second->get_state() == GLGizmoBase::On)) { - it->second->set_state(GLGizmoBase::Off); + it->second->set_state(GLGizmoBase::Hover); m_current = Undefined; } - else + else if ((it->second->get_state() == GLGizmoBase::Hover)) { it->second->set_state(GLGizmoBase::On); m_current = it->first; @@ -1960,8 +1958,27 @@ void GLCanvas3D::Gizmos::update_on_off_state(const GLCanvas3D& canvas, const Vec top_y += (tex_size + OverlayGapY); } + + GizmosMap::iterator it = m_gizmos.find(m_current); + if ((it != m_gizmos.end()) && (it->second != nullptr) && (it->second->get_state() != GLGizmoBase::On)) + it->second->set_state(GLGizmoBase::On); } +#if ENABLE_EXTENDED_SELECTION +void GLCanvas3D::Gizmos::update_on_off_state(const Selection& selection) +{ + GizmosMap::iterator it = m_gizmos.find(m_current); + if ((it != m_gizmos.end()) && (it->second != nullptr)) + { + if (!it->second->is_activable(selection)) + { + it->second->set_state(GLGizmoBase::Off); + m_current = Undefined; + } + } +} +#endif // ENABLE_EXTENDED_SELECTION + void GLCanvas3D::Gizmos::reset_all_states() { if (!m_enabled) @@ -3928,6 +3945,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) else m_selection.add(m_hover_volume_id, !evt.ShiftDown()); + m_gizmos.update_on_off_state(m_selection); update_gizmos_data(); wxGetApp().obj_manipul()->update_settings_value(m_selection); m_dirty = true; diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index e4019e2a1d..70de0361a5 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -552,6 +552,7 @@ private: #if ENABLE_EXTENDED_SELECTION void update_hover_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos, const Selection& selection); void update_on_off_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos, const Selection& selection); + void update_on_off_state(const Selection& selection); #else void update_hover_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos); void update_on_off_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos); diff --git a/src/slic3r/GUI/GLGizmo.cpp b/src/slic3r/GUI/GLGizmo.cpp index e01f57ff90..144301d2d1 100644 --- a/src/slic3r/GUI/GLGizmo.cpp +++ b/src/slic3r/GUI/GLGizmo.cpp @@ -219,9 +219,6 @@ GLGizmoBase::GLGizmoBase(GLCanvas3D& parent) : m_parent(parent) , m_group_id(-1) , m_state(Off) -#if ENABLE_EXTENDED_SELECTION - , m_accept_wipe_tower(false) -#endif // ENABLE_EXTENDED_SELECTION , m_hover_id(-1) , m_dragging(false) { @@ -1216,10 +1213,6 @@ bool GLGizmoMove3D::on_init() m_grabbers.push_back(Grabber()); } -#if ENABLE_EXTENDED_SELECTION - m_accept_wipe_tower = true; -#endif // ENABLE_EXTENDED_SELECTION - return true; } diff --git a/src/slic3r/GUI/GLGizmo.hpp b/src/slic3r/GUI/GLGizmo.hpp index cb0ef4f50c..1f2b77ab80 100644 --- a/src/slic3r/GUI/GLGizmo.hpp +++ b/src/slic3r/GUI/GLGizmo.hpp @@ -59,9 +59,6 @@ protected: int m_group_id; EState m_state; -#if ENABLE_EXTENDED_SELECTION - bool m_accept_wipe_tower; -#endif // ENABLE_EXTENDED_SELECTION // textures are assumed to be square and all with the same size in pixels, no internal check is done GLTexture m_textures[Num_States]; int m_hover_id; @@ -84,8 +81,7 @@ public: void set_state(EState state) { m_state = state; on_set_state(); } #if ENABLE_EXTENDED_SELECTION - bool get_accept_wipe_tower() { return m_accept_wipe_tower; } - void set_accept_wipe_tower(bool accept) { m_accept_wipe_tower = accept; } + bool is_activable(const GLCanvas3D::Selection& selection) const { return on_is_activable(selection); } #endif // ENABLE_EXTENDED_SELECTION unsigned int get_texture_id() const { return m_textures[m_state].get_id(); } @@ -125,6 +121,9 @@ protected: virtual bool on_init() = 0; virtual void on_set_state() {} virtual void on_set_hover_id() {} +#if ENABLE_EXTENDED_SELECTION + virtual bool on_is_activable(const GLCanvas3D::Selection& selection) const { return true; } +#endif // ENABLE_EXTENDED_SELECTION virtual void on_enable_grabber(unsigned int id) {} virtual void on_disable_grabber(unsigned int id) {} #if ENABLE_EXTENDED_SELECTION @@ -249,6 +248,9 @@ protected: m_gizmos[i].set_hover_id((m_hover_id == i) ? 0 : -1); } } +#if ENABLE_EXTENDED_SELECTION + virtual bool on_is_activable(const GLCanvas3D::Selection& selection) const { return !selection.is_wipe_tower(); } +#endif // ENABLE_EXTENDED_SELECTION virtual void on_enable_grabber(unsigned int id) { if ((0 <= id) && (id < 3)) @@ -327,6 +329,9 @@ public: protected: virtual bool on_init(); +#if ENABLE_EXTENDED_SELECTION + virtual bool on_is_activable(const GLCanvas3D::Selection& selection) const { return !selection.is_wipe_tower(); } +#endif // ENABLE_EXTENDED_SELECTION #if ENABLE_EXTENDED_SELECTION virtual void on_start_dragging(const GLCanvas3D::Selection& selection); #else @@ -449,6 +454,9 @@ public: protected: virtual bool on_init(); +#if ENABLE_EXTENDED_SELECTION + virtual bool on_is_activable(const GLCanvas3D::Selection& selection) const { return selection.is_single_full_instance(); } +#endif // ENABLE_EXTENDED_SELECTION #if ENABLE_EXTENDED_SELECTION virtual void on_start_dragging(const GLCanvas3D::Selection& selection); #else From b4a09d3d86bc12492452b4c732bc2060730acf25 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Tue, 16 Oct 2018 16:04:19 +0200 Subject: [PATCH 112/186] New selection -> Toolbar update --- src/slic3r/GUI/GLCanvas3D.cpp | 6 +++++- src/slic3r/GUI/GLCanvas3D.hpp | 5 ++++- src/slic3r/GUI/Plater.cpp | 40 +++++++++++++++++++++++++---------- 3 files changed, 38 insertions(+), 13 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 9ec8201d01..d41e59afe6 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -2661,7 +2661,11 @@ void GLCanvas3D::LegendTexture::render(const GLCanvas3D& canvas) const } } +#if ENABLE_EXTENDED_SELECTION +wxDEFINE_EVENT(EVT_GLCANVAS_OBJECT_SELECT, SimpleEvent); +#else wxDEFINE_EVENT(EVT_GLCANVAS_OBJECT_SELECT, ObjectSelectEvent); +#endif // ENABLE_EXTENDED_SELECTION wxDEFINE_EVENT(EVT_GLCANVAS_VIEWPORT_CHANGED, SimpleEvent); wxDEFINE_EVENT(EVT_GLCANVAS_DOUBLE_CLICK, SimpleEvent); wxDEFINE_EVENT(EVT_GLCANVAS_RIGHT_CLICK, Vec2dEvent); @@ -6551,7 +6555,7 @@ void GLCanvas3D::_on_move(const std::vector& volume_idxs) void GLCanvas3D::_on_select(int volume_idx, int object_idx) { #if ENABLE_EXTENDED_SELECTION - post_event(ObjectSelectEvent(object_idx, -1)); + post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT)); #else int vol_id = -1; int obj_id = -1; diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 70de0361a5..c887f2c196 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -81,7 +81,9 @@ public: void set_bottom(float bottom); }; - +#if ENABLE_EXTENDED_SELECTION +wxDECLARE_EVENT(EVT_GLCANVAS_OBJECT_SELECT, SimpleEvent); +#else struct ObjectSelectEvent; wxDECLARE_EVENT(EVT_GLCANVAS_OBJECT_SELECT, ObjectSelectEvent); struct ObjectSelectEvent : public ArrayEvent @@ -93,6 +95,7 @@ struct ObjectSelectEvent : public ArrayEvent ptrdiff_t object_id() const { return data[0]; } ptrdiff_t volume_id() const { return data[1]; } }; +#endif // ENABLE_EXTENDED_SELECTION using Vec2dEvent = Event; template using Vec2dsEvent = ArrayEvent; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index f22b700743..f757c4bab6 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -672,7 +672,6 @@ std::vector& Sidebar::combos_filament() return p->combos_filament; } - // Plater::Object struct PlaterObject @@ -801,7 +800,11 @@ struct Plater::priv void on_action_selectbyparts(SimpleEvent&); #endif // !ENABLE_EXTENDED_SELECTION +#if ENABLE_EXTENDED_SELECTION + void on_object_select(SimpleEvent&); +#else void on_object_select(ObjectSelectEvent&); +#endif // ENABLE_EXTENDED_SELECTION void on_viewport_changed(SimpleEvent&); void on_right_click(Vec2dEvent&); void on_model_update(SimpleEvent&); @@ -1253,17 +1256,27 @@ optional Plater::priv::selected_object() const void Plater::priv::selection_changed() { - // TODO +#if ENABLE_EXTENDED_SELECTION + const GUI::GLCanvas3D* canvas = _3DScene::get_canvas(this->canvas3D); + const GUI::GLCanvas3D::Selection& selection = canvas->get_selection(); + int obj_idx = selection.get_object_idx(); + bool have_sel = !selection.is_empty() && (0 <= obj_idx) && (obj_idx < 1000); +#else const auto obj_idx = selected_object(); const bool have_sel = !!obj_idx; +#endif // ENABLE_EXTENDED_SELECTION const bool layers_height_allowed = config->opt("variable_layer_height")->value; wxWindowUpdateLocker freeze_guard(sidebar); _3DScene::enable_toolbar_item(canvas3D, "delete", have_sel); _3DScene::enable_toolbar_item(canvas3D, "more", have_sel); +#if ENABLE_EXTENDED_SELECTION + _3DScene::enable_toolbar_item(canvas3D, "fewer", have_sel && (model.objects[obj_idx]->instances.size() > 1)); +#else _3DScene::enable_toolbar_item(canvas3D, "fewer", have_sel); +#endif // ENABLE_EXTENDED_SELECTION _3DScene::enable_toolbar_item(canvas3D, "split", have_sel); _3DScene::enable_toolbar_item(canvas3D, "cut", have_sel); _3DScene::enable_toolbar_item(canvas3D, "settings", have_sel); @@ -1272,18 +1285,14 @@ void Plater::priv::selection_changed() #if !ENABLE_EXTENDED_SELECTION bool can_select_by_parts = false; -#endif // !ENABLE_EXTENDED_SELECTION if (have_sel) { const auto *model_object = model.objects[*obj_idx]; -#if !ENABLE_EXTENDED_SELECTION // XXX: ? can_select_by_parts = *obj_idx < 1000 && model_object->volumes.size() > 1; -#endif // !ENABLE_EXTENDED_SELECTION _3DScene::enable_toolbar_item(canvas3D, "fewer", model_object->instances.size() > 1); } -#if !ENABLE_EXTENDED_SELECTION if (can_select_by_parts) { // first disable to let the item in the toolbar to switch to the unpressed state // XXX: ? _3DScene::enable_toolbar_item(canvas3D, "selectbyparts", false); @@ -1295,12 +1304,15 @@ void Plater::priv::selection_changed() #endif // !ENABLE_EXTENDED_SELECTION if (have_sel) { +#if ENABLE_EXTENDED_SELECTION + const ModelObject* model_object = model.objects[obj_idx]; +#else const auto *model_object = model.objects[*obj_idx]; +#endif // ENABLE_EXTENDED_SELECTION // FIXME print_info runs model fixing in two rounds, it is very slow, it should not be performed here! // # $model_object->print_info; - // my $model_instance = $model_object->instances->[0]; - const auto *model_instance = model_object->instances[0]; + const ModelInstance* model_instance = !model_object->instances.empty() ? model_object->instances.front() : nullptr; // TODO // $self->{object_info_size}->SetLabel(sprintf("%.2f x %.2f x %.2f", @{$model_object->instance_bounding_box(0)->size})); // $self->{object_info_materials}->SetLabel($model_object->materials_count); @@ -1611,6 +1623,14 @@ void Plater::priv::on_action_selectbyparts(SimpleEvent&) } #endif // !ENABLE_EXTENDED_SELECTION +#if ENABLE_EXTENDED_SELECTION +void Plater::priv::on_object_select(SimpleEvent& evt) +{ + selection_changed(); + item_changed_selection(); + wxGetApp().obj_list()->update_selections(); +} +#else void Plater::priv::on_object_select(ObjectSelectEvent &evt) { const auto obj_idx = evt.object_id(); @@ -1621,10 +1641,8 @@ void Plater::priv::on_object_select(ObjectSelectEvent &evt) select_object(obj_idx); item_changed_selection(); } -#if ENABLE_EXTENDED_SELECTION - wxGetApp().obj_list()->update_selections(); -#endif // ENABLE_EXTENDED_SELECTION } +#endif // ENABLE_EXTENDED_SELECTION void Plater::priv::on_viewport_changed(SimpleEvent& evt) { From 37a320c79e5542130f27f6a4befcff20df74d5be Mon Sep 17 00:00:00 2001 From: YuSanka Date: Tue, 16 Oct 2018 11:08:37 +0200 Subject: [PATCH 113/186] Changed logic of the PrusaObjectDataViewModelNode: now each node has: * name, * type, * id (-1, if type == itSettings OR itInstanceRoot), * bmp, * action_bmp * extruder --- src/slic3r/GUI/GUI_ObjectList.cpp | 101 ++++++++++++++++++++---------- src/slic3r/GUI/GUI_ObjectList.hpp | 9 +-- src/slic3r/GUI/Plater.cpp | 1 + src/slic3r/GUI/wxExtensions.cpp | 79 +++++++++++++---------- src/slic3r/GUI/wxExtensions.hpp | 89 ++++++++++++++------------ 5 files changed, 169 insertions(+), 110 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 4d4de489e1..14773b593b 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -58,7 +58,7 @@ ObjectList::ObjectList(wxWindow* parent) : Bind(wxEVT_CHOICE, [this](wxCommandEvent& event) { update_extruder_in_config(event.GetString()); }); GetMainWindow()->Bind(wxEVT_MOTION, [this](wxMouseEvent& event) { - set_tooltip_for_item(event.GetPosition()); + set_tooltip_for_item(/*event.GetPosition()*/get_mouse_position_in_control()); event.Skip(); }); #else @@ -118,7 +118,7 @@ void ObjectList::set_tooltip_for_item(const wxPoint& pt) if (col->GetTitle() == " " && GetSelectedItemsCount()<2) GetMainWindow()->SetToolTip(_(L("Right button click the icon to change the object settings"))); else if (col->GetTitle() == _("Name") && - m_objects_model->GetIcon(item).GetRefData() == m_icon_manifold_warning.GetRefData()) { + m_objects_model->GetBitmap(item).GetRefData() == m_bmp_manifold_warning.GetRefData()) { int obj_idx = m_objects_model->GetIdByItem(item); auto& stats = (*m_objects)[obj_idx]->volumes[0]->mesh.stl.stats; int errors = stats.degenerate_facets + stats.edges_fixed + stats.facets_removed + @@ -214,11 +214,11 @@ void ObjectList::update_extruder_in_config(const wxString& selection) } void ObjectList::init_icons(){ - m_icon_modifiermesh = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("lambda.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("plugin.png")), wxBITMAP_TYPE_PNG); - m_icon_solidmesh = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("object.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("package.png")), wxBITMAP_TYPE_PNG); + m_bmp_modifiermesh = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("lambda.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("plugin.png")), wxBITMAP_TYPE_PNG); + m_bmp_solidmesh = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("object.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("package.png")), wxBITMAP_TYPE_PNG); // init icon for manifold warning - m_icon_manifold_warning = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("exclamation_mark_.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("error.png")), wxBITMAP_TYPE_PNG); + m_bmp_manifold_warning = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("exclamation_mark_.png")), wxBITMAP_TYPE_PNG);//(Slic3r::var("error.png")), wxBITMAP_TYPE_PNG); // init bitmap for "Split to sub-objects" context menu m_bmp_split = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("split.png")), wxBITMAP_TYPE_PNG); @@ -268,7 +268,7 @@ void ObjectList::context_menu() show_context_menu(); else if (title == _("Name") && pt.x >15 && - m_objects_model->GetIcon(item).GetRefData() == m_icon_manifold_warning.GetRefData()) + m_objects_model->GetBitmap(item).GetRefData() == m_bmp_manifold_warning.GetRefData()) { if (is_windows10()) /*fix_through_netfabb()*/;// #ys_FIXME @@ -325,14 +325,20 @@ void ObjectList::item_value_change(wxDataViewEvent& event) } } +struct draging_item_data +{ + int obj_idx; + int vol_idx; +}; + void ObjectList::on_begin_drag(wxDataViewEvent &event) { wxDataViewItem item(event.GetItem()); // only allow drags for item, not containers if (multiple_selection() || - m_objects_model->GetParent(item) == wxDataViewItem(0) || - m_objects_model->IsSettingsItem(item) ) { + m_objects_model->GetParent(item) == wxDataViewItem(0) || + m_objects_model->GetItemType(item) != itVolume ) { event.Veto(); return; } @@ -356,7 +362,7 @@ void ObjectList::on_drop_possible(wxDataViewEvent &event) // only allow drags for item or background, not containers if (item.IsOk() && m_objects_model->GetParent(item) == wxDataViewItem(0) || - event.GetDataFormat() != wxDF_UNICODETEXT || m_objects_model->IsSettingsItem(item)) + event.GetDataFormat() != wxDF_UNICODETEXT || m_objects_model->GetItemType(item) != itVolume) event.Veto(); } @@ -366,7 +372,7 @@ void ObjectList::on_drop(wxDataViewEvent &event) // only allow drops for item, not containers if (item.IsOk() && m_objects_model->GetParent(item) == wxDataViewItem(0) || - event.GetDataFormat() != wxDF_UNICODETEXT || m_objects_model->IsSettingsItem(item)) { + event.GetDataFormat() != wxDF_UNICODETEXT || m_objects_model->GetItemType(item) != itVolume) { event.Veto(); return; } @@ -495,7 +501,7 @@ void ObjectList::get_settings_choice(wxMenu *menu, int id, bool is_part) // Add settings item for object const auto item = GetSelection(); if (item) { - const auto settings_item = m_objects_model->HasSettings(item); + const auto settings_item = m_objects_model->GetSettingsItem(item); select_item(settings_item ? settings_item : m_objects_model->AddSettingsChild(item)); #ifndef __WXOSX__ @@ -547,7 +553,7 @@ wxMenu* ObjectList::create_add_part_popupmenu() int i = 0; for (auto& item : menu_items) { auto menu_item = new wxMenuItem(menu, config_id_base + i, _(item)); - menu_item->SetBitmap(i == 0 ? m_icon_solidmesh : m_icon_modifiermesh); + menu_item->SetBitmap(i == 0 ? m_bmp_solidmesh : m_bmp_modifiermesh); if (item == "Add generic") menu_item_add_generic(menu_item, config_id_base + i); menu->Append(menu_item); @@ -667,7 +673,7 @@ void ObjectList::load_subobject(bool is_modifier /*= false*/, bool is_lambda/* = for (int i = 0; i < part_names.size(); ++i) { const wxDataViewItem sel_item = m_objects_model->AddChild(item, part_names.Item(i), - is_modifier ? m_icon_modifiermesh : m_icon_solidmesh); + is_modifier ? m_bmp_modifiermesh : m_bmp_solidmesh); if (i == part_names.size() - 1) select_item(sel_item); @@ -817,7 +823,7 @@ void ObjectList::load_lambda(const std::string& type_name) parts_changed(m_selected_object_id); select_item(m_objects_model->AddChild(GetSelection(), - name, m_icon_modifiermesh)); + name, m_bmp_modifiermesh)); #ifndef __WXOSX__ //#ifdef __WXMSW__ // #ys_FIXME selection_changed(); #endif //no __WXOSX__ //__WXMSW__ @@ -830,15 +836,20 @@ void ObjectList::del_subobject_item(wxDataViewItem& item) { if (!item) return; - int obj_idx, vol_idx; - m_objects_model->GetObjectAndVolumeIdsByItem(item, obj_idx, vol_idx); + int obj_idx, idx; + ItemType type; - if (vol_idx == -1) + m_objects_model->GetItemInfo(item, type, obj_idx, idx); + if (type == itUndef) return; - if (vol_idx == -2) + if (type == itSettings) del_settings_from_config(); - else if (!del_subobject_from_object(obj_idx, vol_idx)) + else if (type == itInstanceRoot && obj_idx != -1) + del_instances_from_object(obj_idx); + else if (idx == -1) + return; + else if (!del_subobject_from_object(obj_idx, idx, type)) return; m_objects_model->Delete(item); @@ -859,21 +870,43 @@ void ObjectList::del_settings_from_config() m_config->set_key_value("extruder", new ConfigOptionInt(extruder)); } -bool ObjectList::del_subobject_from_object(const int obj_idx, const int vol_idx) +void ObjectList::del_instances_from_object(const int obj_idx) { - const auto volume = (*m_objects)[obj_idx]->volumes[vol_idx]; + auto instances = (*m_objects)[obj_idx]->instances; + if (instances.size() <= 1) + return; - // if user is deleting the last solid part, throw error - int solid_cnt = 0; - for (auto vol : (*m_objects)[obj_idx]->volumes) - if (vol->is_model_part()) - ++solid_cnt; - if (volume->is_model_part() && solid_cnt == 1) { - Slic3r::GUI::show_error(nullptr, _(L("You can't delete the last solid part from this object."))); - return false; + while ( instances.size()> 1) + instances.pop_back(); + + (*m_objects)[obj_idx]->invalidate_bounding_box(); // ? #ys_FIXME + + m_parts_changed = true; + parts_changed(obj_idx); +} + +bool ObjectList::del_subobject_from_object(const int obj_idx, const int idx, const int type) +{ + if (type == itVolume) { + const auto volume = (*m_objects)[obj_idx]->volumes[idx]; + + // if user is deleting the last solid part, throw error + int solid_cnt = 0; + for (auto vol : (*m_objects)[obj_idx]->volumes) + if (vol->is_model_part()) + ++solid_cnt; + if (volume->is_model_part() && solid_cnt == 1) { + Slic3r::GUI::show_error(nullptr, _(L("You can't delete the last solid part from this object."))); + return false; + } + + (*m_objects)[obj_idx]->delete_volume(idx); } + else if (type == itInstance) + (*m_objects)[obj_idx]->delete_instance(idx); + else + return false; - (*m_objects)[obj_idx]->delete_volume(vol_idx); m_parts_changed = true; parts_changed(obj_idx); @@ -902,7 +935,7 @@ void ObjectList::split(const bool split_part) for (auto id = 0; id < model_object->volumes.size(); id++) m_objects_model->AddChild(parent, model_object->volumes[id]->name, - model_object->volumes[id]->is_modifier() ? m_icon_modifiermesh : m_icon_solidmesh, + model_object->volumes[id]->is_modifier() ? m_bmp_modifiermesh : m_bmp_solidmesh, model_object->volumes[id]->config.has("extruder") ? model_object->volumes[id]->config.option("extruder")->value : 0, false); @@ -912,7 +945,7 @@ void ObjectList::split(const bool split_part) else { for (auto id = 0; id < model_object->volumes.size(); id++) m_objects_model->AddChild(item, model_object->volumes[id]->name, - m_icon_solidmesh, + m_bmp_solidmesh, model_object->volumes[id]->config.has("extruder") ? model_object->volumes[id]->config.option("extruder")->value : 0, false); @@ -1049,7 +1082,7 @@ void ObjectList::add_object_to_list(size_t obj_idx) stats.facets_added + stats.facets_reversed + stats.backwards_edges; if (errors > 0) { wxVariant variant; - variant << PrusaDataViewBitmapText(item_name, m_icon_manifold_warning); + variant << PrusaDataViewBitmapText(item_name, m_bmp_manifold_warning); m_objects_model->SetValue(variant, item, 0); } @@ -1057,7 +1090,7 @@ void ObjectList::add_object_to_list(size_t obj_idx) for (auto id = 0; id < model_object->volumes.size(); id++) m_objects_model->AddChild(item, model_object->volumes[id]->name, - m_icon_solidmesh, + m_bmp_solidmesh, model_object->volumes[id]->config.option("extruder")->value, false); Expand(item); diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index 21b4a729fb..418e1e8779 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -22,9 +22,9 @@ class ObjectList : public wxDataViewCtrl DynamicPrintConfig *m_default_config {nullptr}; - wxBitmap m_icon_modifiermesh; - wxBitmap m_icon_solidmesh; - wxBitmap m_icon_manifold_warning; + wxBitmap m_bmp_modifiermesh; + wxBitmap m_bmp_solidmesh; + wxBitmap m_bmp_manifold_warning; wxBitmap m_bmp_cog; wxBitmap m_bmp_split; @@ -87,7 +87,8 @@ public: void load_lambda(const std::string& type_name); void del_subobject_item(wxDataViewItem& item); void del_settings_from_config(); - bool del_subobject_from_object(const int obj_idx, const int vol_idx); + void del_instances_from_object(const int obj_idx); + bool del_subobject_from_object(const int obj_idx, const int idx, const int type); void split(const bool split_part); bool get_volume_by_item(const bool split_part, const wxDataViewItem& item, ModelVolume*& volume); bool is_splittable_object(const bool split_part); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index f22b700743..9f0cdc89b8 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -2019,6 +2019,7 @@ void Plater::changed_object_settings(int obj_idx) _3DScene::set_objects_selections(p->canvas3D, selections); #endif // !ENABLE_EXTENDED_SELECTION _3DScene::reload_scene(p->canvas3D, false); + _3DScene::zoom_to_volumes(p->canvas3D); } else { // schedule_background_process(); diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp index 9c9bcdaeae..4b57540c2e 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -362,12 +362,13 @@ void PrusaObjectDataViewModelNode::set_part_action_icon() { Slic3r::GUI::BitmapCache *m_bitmap_cache = nullptr; bool PrusaObjectDataViewModelNode::update_settings_digest(const std::vector& categories) { - if (m_type != "settings" || m_opt_categories == categories) + if (m_type != itSettings || m_opt_categories == categories) return false; m_opt_categories = categories; m_name = wxEmptyString; - m_icon = m_empty_icon; +// m_icon = m_empty_icon; + m_bmp = m_empty_bmp; std::map& categories_icon = Slic3r::GUI::wxGetApp().obj_list()->CATEGORY_ICON;//Slic3r::GUI::get_category_icon(); @@ -440,7 +441,7 @@ wxDataViewItem PrusaObjectDataViewModel::AddChild( const wxDataViewItem &parent_ const wxString extruder_str = extruder == 0 ? "default" : wxString::Format("%d", extruder); if (create_frst_child && (root->GetChildren().Count() == 0 || - (root->GetChildren().Count() == 1 && root->GetNthChild(0)->m_type == "settings"))) + (root->GetChildren().Count() == 1 && root->GetNthChild(0)->m_type == itSettings))) { const auto icon_solid_mesh = wxIcon(Slic3r::GUI::from_u8(Slic3r::var("object.png")), wxBITMAP_TYPE_PNG); const auto node = new PrusaObjectDataViewModelNode(root, root->m_name, icon_solid_mesh, extruder_str, 0); @@ -450,7 +451,7 @@ wxDataViewItem PrusaObjectDataViewModel::AddChild( const wxDataViewItem &parent_ ItemAdded(parent_item, child); } - const auto volume_id = root->GetChildCount() > 0 && root->GetNthChild(0)->m_type == "settings" ? + const auto volume_id = root->GetChildCount() > 0 && root->GetNthChild(0)->m_type == itSettings ? root->GetChildCount() - 1 : root->GetChildCount(); const auto node = new PrusaObjectDataViewModelNode(root, name, icon, extruder_str, volume_id); @@ -489,20 +490,20 @@ wxDataViewItem PrusaObjectDataViewModel::Delete(const wxDataViewItem &item) // thus removing the node from it doesn't result in freeing it if (node_parent){ auto id = node_parent->GetChildren().Index(node); - auto v_id = node->GetVolumeId(); + auto idx = node->GetIdx(); node_parent->GetChildren().Remove(node); if (id > 0){ if(id == node_parent->GetChildCount()) id--; ret_item = wxDataViewItem(node_parent->GetChildren().Item(id)); } - //update volume_id value for remaining child-nodes + //update idx value for remaining child-nodes auto children = node_parent->GetChildren(); - for (size_t i = 0; i < node_parent->GetChildCount() && v_id>=0; i++) + for (size_t i = 0; i < node_parent->GetChildCount() && idx>=0; i++) { - auto volume_id = children[i]->GetVolumeId(); - if (volume_id > v_id) - children[i]->SetVolumeId(volume_id-1); + auto cur_idx = children[i]->GetIdx(); + if (cur_idx > idx) + children[i]->SetIdx(cur_idx-1); } } else @@ -592,7 +593,7 @@ wxDataViewItem PrusaObjectDataViewModel::GetItemByVolumeId(int obj_idx, int volu auto parent = m_objects[obj_idx]; if (parent->GetChildCount() == 0 || - (parent->GetChildCount() == 1 && parent->GetNthChild(0)->m_volume_id == -2)) { + (parent->GetChildCount() == 1 && parent->GetNthChild(0)->GetType() & itSettings )) { if (volume_idx == 0) return GetItemById(obj_idx); @@ -601,13 +602,13 @@ wxDataViewItem PrusaObjectDataViewModel::GetItemByVolumeId(int obj_idx, int volu } for (size_t i = 0; i < parent->GetChildCount(); i++) - if (parent->GetNthChild(i)->m_volume_id == volume_idx) + if (parent->GetNthChild(i)->m_idx == volume_idx && parent->GetNthChild(0)->GetType() & itVolume) return wxDataViewItem(parent->GetNthChild(i)); return wxDataViewItem(0); } -int PrusaObjectDataViewModel::GetIdByItem(wxDataViewItem& item) +int PrusaObjectDataViewModel::GetIdByItem(const wxDataViewItem& item) { wxASSERT(item.IsOk()); @@ -624,22 +625,27 @@ int PrusaObjectDataViewModel::GetVolumeIdByItem(const wxDataViewItem& item) wxASSERT(item.IsOk()); PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID(); - if (!node) // happens if item.IsOk()==false + if (!node || node->m_type != itVolume) return -1; - return node->GetVolumeId(); + return node->GetIdx(); } -void PrusaObjectDataViewModel::GetObjectAndVolumeIdsByItem(const wxDataViewItem& item, int& obj_idx, int& vol_idx) +void PrusaObjectDataViewModel::GetItemInfo(const wxDataViewItem& item, ItemType& type, int& obj_idx, int& idx) { wxASSERT(item.IsOk()); - obj_idx = vol_idx = -1; + type = itUndef; PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID(); if (!node) return; - vol_idx = node->GetVolumeId(); + + type = node->GetType(); + idx = node->GetIdx(); PrusaObjectDataViewModelNode *parent_node = node->GetParent(); if (!parent_node) return; + if (type == itInstance) + parent_node = node->GetParent()->GetParent(); + if (!parent_node) return; auto it = find(m_objects.begin(), m_objects.end(), parent_node); if (it != m_objects.end()) @@ -664,11 +670,11 @@ wxString PrusaObjectDataViewModel::GetCopy(const wxDataViewItem &item) const return node->m_copy; } -wxIcon& PrusaObjectDataViewModel::GetIcon(const wxDataViewItem &item) const -{ - PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID(); - return node->m_icon; -} +// wxIcon& PrusaObjectDataViewModel::GetIcon(const wxDataViewItem &item) const +// { +// PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID(); +// return node->m_icon; +// } wxBitmap& PrusaObjectDataViewModel::GetBitmap(const wxDataViewItem &item) const { @@ -715,7 +721,7 @@ bool PrusaObjectDataViewModel::SetValue(const wxVariant &variant, const int item return m_objects[item_idx]->SetValue(variant, col); } - +/* wxDataViewItem PrusaObjectDataViewModel::MoveChildUp(const wxDataViewItem &item) { auto ret_item = wxDataViewItem(0); @@ -763,7 +769,7 @@ wxDataViewItem PrusaObjectDataViewModel::MoveChildDown(const wxDataViewItem &ite ret_item = wxDataViewItem(node_parent->GetNthChild(node_parent->GetChildCount()-1)); return ret_item; } - +*/ wxDataViewItem PrusaObjectDataViewModel::ReorganizeChildren(int current_volume_id, int new_volume_id, const wxDataViewItem &parent) { auto ret_item = wxDataViewItem(0); @@ -774,14 +780,14 @@ wxDataViewItem PrusaObjectDataViewModel::ReorganizeChildren(int current_volume_i if (!node_parent) // happens if item.IsOk()==false return ret_item; - const size_t shift = node_parent->GetChildren().Item(0)->m_type == "settings" ? 1 : 0; + const size_t shift = node_parent->GetChildren().Item(0)->m_type == itSettings ? 1 : 0; PrusaObjectDataViewModelNode *deleted_node = node_parent->GetNthChild(current_volume_id+shift); node_parent->GetChildren().Remove(deleted_node); ItemDeleted(parent, wxDataViewItem(deleted_node)); node_parent->Insert(deleted_node, new_volume_id+shift); ItemAdded(parent, wxDataViewItem(deleted_node)); - const auto settings_item = HasSettings(wxDataViewItem(deleted_node)); + const auto settings_item = GetSettingsItem(wxDataViewItem(deleted_node)); if (settings_item) ItemAdded(wxDataViewItem(deleted_node), settings_item); @@ -790,7 +796,7 @@ wxDataViewItem PrusaObjectDataViewModel::ReorganizeChildren(int current_volume_i int id_frst = current_volume_id < new_volume_id ? current_volume_id : new_volume_id; int id_last = current_volume_id > new_volume_id ? current_volume_id : new_volume_id; for (int id = id_frst; id <= id_last; ++id) - children[id+shift]->SetVolumeId(id); + children[id+shift]->SetIdx(id); return wxDataViewItem(node_parent->GetNthChild(new_volume_id+shift)); } @@ -854,7 +860,15 @@ unsigned int PrusaObjectDataViewModel::GetChildren(const wxDataViewItem &parent, return count; } -wxDataViewItem PrusaObjectDataViewModel::HasSettings(const wxDataViewItem &item) const +ItemType PrusaObjectDataViewModel::GetItemType(const wxDataViewItem &item) const +{ + if (!item.IsOk()) + return itUndef; + PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID(); + return node->m_type; +} + +wxDataViewItem PrusaObjectDataViewModel::GetSettingsItem(const wxDataViewItem &item) const { if (!item.IsOk()) return wxDataViewItem(0); @@ -863,9 +877,8 @@ wxDataViewItem PrusaObjectDataViewModel::HasSettings(const wxDataViewItem &item) if (node->GetChildCount() == 0) return wxDataViewItem(0); - auto& children = node->GetChildren(); - if (children[0]->m_type == "settings") - return wxDataViewItem((void*)children[0]);; + if (node->GetNthChild(0)->m_type == itSettings) + return wxDataViewItem((void*)node->GetNthChild(0)); return wxDataViewItem(0); } @@ -875,7 +888,7 @@ bool PrusaObjectDataViewModel::IsSettingsItem(const wxDataViewItem &item) const if (!item.IsOk()) return false; PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID(); - return node->m_type == "settings"; + return node->m_type == itSettings; } diff --git a/src/slic3r/GUI/wxExtensions.hpp b/src/slic3r/GUI/wxExtensions.hpp index 43e5756a42..f3c417426f 100644 --- a/src/slic3r/GUI/wxExtensions.hpp +++ b/src/slic3r/GUI/wxExtensions.hpp @@ -194,6 +194,15 @@ DECLARE_VARIANT_OBJECT(PrusaDataViewBitmapText) // PrusaObjectDataViewModelNode: a node inside PrusaObjectDataViewModel // ---------------------------------------------------------------------------- +enum ItemType{ + itUndef, + itObject, + itVolume, + itInstanceRoot, + itInstance, + itSettings +}; + class PrusaObjectDataViewModelNode; WX_DEFINE_ARRAY_PTR(PrusaObjectDataViewModelNode*, MyObjectTreeModelNodePtrArray); @@ -201,7 +210,6 @@ class PrusaObjectDataViewModelNode { PrusaObjectDataViewModelNode* m_parent; MyObjectTreeModelNodePtrArray m_children; - wxIcon m_empty_icon; wxBitmap m_empty_bmp; std::vector< std::string > m_opt_categories; public: @@ -209,8 +217,7 @@ public: m_parent = NULL; m_name = name; m_copy = wxString::Format("%d", instances_count); - m_type = "object"; - m_volume_id = -1; + m_type = itObject; #ifdef __WXGTK__ // it's necessary on GTK because of control have to know if this item will be container // in another case you couldn't to add subitem for this item @@ -224,13 +231,13 @@ public: const wxString& sub_obj_name, const wxBitmap& bmp, const wxString& extruder, - const int volume_id=-1) { + const int idx = -1 ) { m_parent = parent; m_name = sub_obj_name; m_copy = wxEmptyString; m_bmp = bmp; - m_type = "volume"; - m_volume_id = volume_id; + m_type = itVolume; + m_idx = idx; m_extruder = extruder; #ifdef __WXGTK__ // it's necessary on GTK because of control have to know if this item will be container @@ -241,12 +248,23 @@ public: set_part_action_icon(); } - PrusaObjectDataViewModelNode( PrusaObjectDataViewModelNode* parent) : + PrusaObjectDataViewModelNode( PrusaObjectDataViewModelNode* parent, const ItemType type = itSettings) : m_parent(parent), - m_name("Settings to modified"), m_copy(wxEmptyString), - m_type("settings"), - m_extruder(wxEmptyString) {} + m_type(type), + m_extruder(wxEmptyString) + { + if (type == itSettings) { + m_name = "Settings to modified"; + } + else if (type == itInstanceRoot) { + m_name = "Instances"; + } + else if (type == itInstance) { + m_name = wxString::Format("Instances_%d", parent->GetChildCount() + 1); + m_idx = parent->GetChildCount(); + } + } ~PrusaObjectDataViewModelNode() { @@ -260,11 +278,10 @@ public: } wxString m_name; - wxIcon& m_icon = m_empty_icon; wxBitmap& m_bmp = m_empty_bmp; wxString m_copy; - std::string m_type; - int m_volume_id = -2; + ItemType m_type; + int m_idx = -1; bool m_container = false; wxString m_extruder = "default"; wxBitmap m_action_icon; @@ -341,28 +358,21 @@ public: } return false; } - void SetIcon(const wxIcon &icon) - { - m_icon = icon; - } void SetBitmap(const wxBitmap &icon) { m_bmp = icon; } - - void SetType(const std::string& type){ - m_type = type; - } - const std::string& GetType(){ - return m_type; - } - void SetVolumeId(const int& volume_id){ - m_volume_id = volume_id; + ItemType GetType() const { + return m_type; + } + + void SetIdx(const int& idx) { + m_idx = idx; } - const int& GetVolumeId(){ - return m_volume_id; + int GetIdx() const { + return m_idx; } // use this function only for childrens @@ -370,9 +380,10 @@ public: { // ! Don't overwrite other values because of equality of this values for all children -- m_name = from_node.m_name; - m_icon = from_node.m_icon; - m_volume_id = from_node.m_volume_id; - m_extruder = from_node.m_extruder; + m_bmp = from_node.m_bmp; + m_idx = from_node.m_idx; + m_extruder = from_node.m_extruder; + m_type = from_node.m_type; } bool SwapChildrens(int frst_id, int scnd_id) { @@ -384,8 +395,8 @@ public: PrusaObjectDataViewModelNode new_scnd = *GetNthChild(frst_id); PrusaObjectDataViewModelNode new_frst = *GetNthChild(scnd_id); - new_scnd.m_volume_id = m_children.Item(scnd_id)->m_volume_id; - new_frst.m_volume_id = m_children.Item(frst_id)->m_volume_id; + new_scnd.m_idx = m_children.Item(scnd_id)->m_idx; + new_frst.m_idx = m_children.Item(frst_id)->m_idx; m_children.Item(frst_id)->AssignAllVal(new_frst); m_children.Item(scnd_id)->AssignAllVal(new_scnd); @@ -422,16 +433,15 @@ public: void DeleteChildren(wxDataViewItem& parent); wxDataViewItem GetItemById(int obj_idx); wxDataViewItem GetItemByVolumeId(int obj_idx, int volume_idx); - int GetIdByItem(wxDataViewItem& item); + int GetIdByItem(const wxDataViewItem& item); int GetVolumeIdByItem(const wxDataViewItem& item); - void GetObjectAndVolumeIdsByItem(const wxDataViewItem& item, int& obj_idx, int& vol_idx); + void GetItemInfo(const wxDataViewItem& item, ItemType& type, int& obj_idx, int& idx); bool IsEmpty() { return m_objects.empty(); } // helper method for wxLog wxString GetName(const wxDataViewItem &item) const; wxString GetCopy(const wxDataViewItem &item) const; - wxIcon& GetIcon(const wxDataViewItem &item) const; wxBitmap& GetBitmap(const wxDataViewItem &item) const; // helper methods to change the model @@ -445,8 +455,8 @@ public: const wxDataViewItem &item, unsigned int col) override; bool SetValue(const wxVariant &variant, const int item_idx, unsigned int col); - wxDataViewItem MoveChildUp(const wxDataViewItem &item); - wxDataViewItem MoveChildDown(const wxDataViewItem &item); +// wxDataViewItem MoveChildUp(const wxDataViewItem &item); +// wxDataViewItem MoveChildDown(const wxDataViewItem &item); // For parent move child from cur_volume_id place to new_volume_id // Remaining items will moved up/down accordingly wxDataViewItem ReorganizeChildren(int cur_volume_id, @@ -464,7 +474,8 @@ public: // In our case it is an item with all columns virtual bool HasContainerColumns(const wxDataViewItem& WXUNUSED(item)) const override { return true; } - wxDataViewItem HasSettings(const wxDataViewItem &item) const; + ItemType GetItemType(const wxDataViewItem &item) const ; + wxDataViewItem GetSettingsItem(const wxDataViewItem &item) const; bool IsSettingsItem(const wxDataViewItem &item) const; void UpdateSettingsDigest(const wxDataViewItem &item, const std::vector& categories); }; From b8ec71ab28cb92283419331873899d136e4b9dd1 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Wed, 17 Oct 2018 09:30:07 +0200 Subject: [PATCH 114/186] New selection -> Removed old plater selection --- src/slic3r/GUI/Plater.cpp | 143 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 136 insertions(+), 7 deletions(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index f757c4bab6..f52b585658 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -672,6 +672,7 @@ std::vector& Sidebar::combos_filament() return p->combos_filament; } +#if !ENABLE_EXTENDED_SELECTION // Plater::Object struct PlaterObject @@ -681,6 +682,7 @@ struct PlaterObject PlaterObject(std::string name) : name(std::move(name)), selected(false) {} }; +#endif // !ENABLE_EXTENDED_SELECTION // Plater::DropTarget @@ -730,7 +732,9 @@ struct Plater::priv Slic3r::Print print; Slic3r::Model model; Slic3r::GCodePreviewData gcode_preview_data; +#if !ENABLE_EXTENDED_SELECTION std::vector objects; +#endif // !ENABLE_EXTENDED_SELECTION fs::path export_gcode_output_file; fs::path send_gcode_file; @@ -761,9 +765,15 @@ struct Plater::priv std::vector load_model_objects(const ModelObjectPtrs &model_objects); std::unique_ptr get_export_file(GUI::FileType file_type); +#if ENABLE_EXTENDED_SELECTION + const GLCanvas3D::Selection& get_selection() const; + GLCanvas3D::Selection& get_selection(); + int get_selected_object_idx() const; +#else void select_object(optional obj_idx); void select_object_from_cpp(); optional selected_object() const; +#endif // ENABLE_EXTENDED_SELECTION void selection_changed(); void object_list_changed(); void select_view(); @@ -808,7 +818,9 @@ struct Plater::priv void on_viewport_changed(SimpleEvent&); void on_right_click(Vec2dEvent&); void on_model_update(SimpleEvent&); +#if !ENABLE_EXTENDED_SELECTION void on_scale_uniformly(SimpleEvent&); +#endif // !ENABLE_EXTENDED_SELECTION void on_wipetower_moved(Vec3dEvent&); void on_enable_action_buttons(Event&); void on_update_geometry(Vec3dsEvent<2>&); @@ -1114,12 +1126,19 @@ std::vector Plater::priv::load_model_objects(const ModelObjectPtrs &mode bool need_arrange = false; bool scaled_down = false; std::vector obj_idxs; +#if ENABLE_EXTENDED_SELECTION + unsigned int obj_count = 0; +#endif // ENABLE_EXTENDED_SELECTION for (ModelObject *model_object : model_objects) { auto *object = model.add_object(*model_object); std::string object_name = object->name.empty() ? fs::path(object->input_file).filename().string() : object->name; +#if ENABLE_EXTENDED_SELECTION + obj_idxs.push_back(obj_count++); +#else objects.emplace_back(std::move(object_name)); obj_idxs.push_back(objects.size() - 1); +#endif // ENABLE_EXTENDED_SELECTION if (model_object->instances.empty()) { // if object has no defined position(s) we need to rearrange everything after loading @@ -1227,6 +1246,23 @@ std::unique_ptr Plater::priv::get_export_file(GUI::FileType return dlg; } +#if ENABLE_EXTENDED_SELECTION +const GLCanvas3D::Selection& Plater::priv::get_selection() const +{ + return _3DScene::get_canvas(canvas3D)->get_selection(); +} + +GLCanvas3D::Selection& Plater::priv::get_selection() +{ + return _3DScene::get_canvas(canvas3D)->get_selection(); +} + +int Plater::priv::get_selected_object_idx() const +{ + int idx = get_selection().get_object_idx(); + return ((0 <= idx) && (idx < 1000)) ? idx : -1; +} +#else void Plater::priv::select_object(optional obj_idx) { for (auto &obj : objects) { @@ -1253,15 +1289,13 @@ optional Plater::priv::selected_object() const return boost::none; } +#endif // ENABLE_EXTENDED_SELECTION void Plater::priv::selection_changed() { #if ENABLE_EXTENDED_SELECTION - const GUI::GLCanvas3D* canvas = _3DScene::get_canvas(this->canvas3D); - const GUI::GLCanvas3D::Selection& selection = canvas->get_selection(); - - int obj_idx = selection.get_object_idx(); - bool have_sel = !selection.is_empty() && (0 <= obj_idx) && (obj_idx < 1000); + int obj_idx = get_selected_object_idx(); + bool have_sel = (obj_idx != -1); #else const auto obj_idx = selected_object(); const bool have_sel = !!obj_idx; @@ -1354,7 +1388,11 @@ void Plater::priv::selection_changed() void Plater::priv::object_list_changed() { // Enable/disable buttons depending on whether there are any objects on the platter. +#if ENABLE_EXTENDED_SELECTION + const bool have_objects = !model.objects.empty(); +#else const bool have_objects = !objects.empty(); +#endif // ENABLE_EXTENDED_SELECTION _3DScene::enable_toolbar_item(canvas3D, "deleteall", have_objects); _3DScene::enable_toolbar_item(canvas3D, "arrange", have_objects); @@ -1378,7 +1416,9 @@ void Plater::priv::remove(size_t obj_idx) // Prevent toolpaths preview from rendering while we modify the Print object preview->set_enabled(false); +#if !ENABLE_EXTENDED_SELECTION objects.erase(objects.begin() + obj_idx); +#endif // !ENABLE_EXTENDED_SELECTION model.delete_object(obj_idx); print.delete_object(obj_idx); // Delete object from Sidebar list @@ -1386,7 +1426,9 @@ void Plater::priv::remove(size_t obj_idx) object_list_changed(); +#if !ENABLE_EXTENDED_SELECTION select_object(boost::none); +#endif // !ENABLE_EXTENDED_SELECTION update(); } @@ -1397,7 +1439,9 @@ void Plater::priv::reset() // Prevent toolpaths preview from rendering while we modify the Print object preview->set_enabled(false); +#if !ENABLE_EXTENDED_SELECTION objects.clear(); +#endif // !ENABLE_EXTENDED_SELECTION model.clear_objects(); print.clear_objects(); @@ -1405,7 +1449,9 @@ void Plater::priv::reset() sidebar->obj_list()->delete_all_objects_from_list(); object_list_changed(); +#if !ENABLE_EXTENDED_SELECTION select_object(boost::none); +#endif // !ENABLE_EXTENDED_SELECTION update(); } @@ -1416,11 +1462,20 @@ void Plater::priv::rotate() void Plater::priv::mirror(const Axis &axis) { +#if ENABLE_EXTENDED_SELECTION + int obj_idx = get_selected_object_idx(); + if (obj_idx == -1) + return; + + ModelObject* model_object = model.objects[obj_idx]; + ModelInstance* model_instance = model_object->instances.front(); +#else const auto obj_idx = selected_object(); if (! obj_idx) { return; } auto *model_object = model.objects[*obj_idx]; auto *model_instance = model_object->instances[0]; +#endif // ENABLE_EXTENDED_SELECTION // XXX: ? // # apply Z rotation before mirroring @@ -1432,7 +1487,11 @@ void Plater::priv::mirror(const Axis &axis) model_object->mirror(axis); // $self->stop_background_process; // TODO +#if ENABLE_EXTENDED_SELECTION + print.add_model_object(model_object, obj_idx); +#else print.add_model_object(model_object, *obj_idx); +#endif // ENABLE_EXTENDED_SELECTION selection_changed(); update(); } @@ -1663,6 +1722,7 @@ void Plater::priv::on_model_update(SimpleEvent&) // TODO } +#if !ENABLE_EXTENDED_SELECTION void Plater::priv::on_scale_uniformly(SimpleEvent&) { // my ($scale) = @_; @@ -1697,6 +1757,7 @@ void Plater::priv::on_scale_uniformly(SimpleEvent&) // $self->update; // $self->schedule_background_process; } +#endif // !ENABLE_EXTENDED_SELECTION void Plater::priv::on_wipetower_moved(Vec3dEvent &evt) { @@ -1741,19 +1802,34 @@ void Plater::remove(size_t obj_idx) { p->remove(obj_idx); } void Plater::remove_selected() { +#if ENABLE_EXTENDED_SELECTION + int obj_idx = p->get_selected_object_idx(); + if (obj_idx != -1) + remove((size_t)obj_idx); +#else const auto selected = p->selected_object(); if (selected) { remove(*selected); } +#endif // ENABLE_EXTENDED_SELECTION } void Plater::increase(size_t num) { +#if ENABLE_EXTENDED_SELECTION + int obj_idx = p->get_selected_object_idx(); + if (obj_idx == -1) + return; + + ModelObject* model_object = p->model.objects[obj_idx]; + ModelInstance* model_instance = model_object->instances.back(); +#else const auto obj_idx = p->selected_object(); if (! obj_idx) { return; } auto *model_object = p->model.objects[*obj_idx]; auto *model_instance = model_object->instances[model_object->instances.size() - 1]; +#endif // ENABLE_EXTENDED_SELECTION // $self->stop_background_process; @@ -1761,10 +1837,18 @@ void Plater::increase(size_t num) for (size_t i = 0; i < num; i++, offset += 10.0) { Vec3d offset_vec = model_instance->get_offset() + Vec3d(offset, offset, 0.0); auto *new_instance = model_object->add_instance(offset_vec, model_instance->get_scaling_factor(), model_instance->get_rotation()); +#if ENABLE_EXTENDED_SELECTION + p->print.get_object(obj_idx)->add_copy(Slic3r::to_2d(offset_vec)); +#else p->print.get_object(*obj_idx)->add_copy(Slic3r::to_2d(offset_vec)); +#endif // ENABLE_EXTENDED_SELECTION } +#if ENABLE_EXTENDED_SELECTION + sidebar().obj_list()->set_object_count(obj_idx, model_object->instances.size()); +#else sidebar().obj_list()->set_object_count(*obj_idx, model_object->instances.size()); +#endif // ENABLE_EXTENDED_SELECTION if (p->get_config("autocenter") == "1") { p->arrange(); @@ -1779,18 +1863,39 @@ void Plater::increase(size_t num) void Plater::decrease(size_t num) { +#if ENABLE_EXTENDED_SELECTION + int obj_idx = p->get_selected_object_idx(); + if (obj_idx == -1) + return; + + ModelObject* model_object = p->model.objects[obj_idx]; +#else const auto obj_idx = p->selected_object(); if (! obj_idx) { return; } auto *model_object = p->model.objects[*obj_idx]; +#endif // ENABLE_EXTENDED_SELECTION if (model_object->instances.size() > num) { for (size_t i = 0; i < num; i++) { model_object->delete_last_instance(); +#if ENABLE_EXTENDED_SELECTION + p->print.get_object(obj_idx)->delete_last_copy(); +#else p->print.get_object(*obj_idx)->delete_last_copy(); +#endif // ENABLE_EXTENDED_SELECTION } +#if ENABLE_EXTENDED_SELECTION + sidebar().obj_list()->set_object_count(obj_idx, model_object->instances.size()); +#else sidebar().obj_list()->set_object_count(*obj_idx, model_object->instances.size()); - } else { +#endif // ENABLE_EXTENDED_SELECTION + } + else { +#if ENABLE_EXTENDED_SELECTION + remove(obj_idx); +#else remove(*obj_idx); +#endif // ENABLE_EXTENDED_SELECTION } p->update(); @@ -1798,12 +1903,20 @@ void Plater::decrease(size_t num) void Plater::set_number_of_copies(size_t num) { +#if ENABLE_EXTENDED_SELECTION + int obj_idx = p->get_selected_object_idx(); + if (obj_idx == -1) + return; + + ModelObject* model_object = p->model.objects[obj_idx]; +#else const auto obj_idx = p->selected_object(); if (! obj_idx) { return; } auto *model_object = p->model.objects[*obj_idx]; +#endif // ENABLE_EXTENDED_SELECTION - auto diff = (ptrdiff_t)num - (ptrdiff_t)model_object->instances.size(); + int diff = (int)num - (int)model_object->instances.size(); if (diff > 0) { increase(diff); } else if (diff < 0) { @@ -1813,7 +1926,11 @@ void Plater::set_number_of_copies(size_t num) fs::path Plater::export_gcode(const fs::path &output_path) { +#if ENABLE_EXTENDED_SELECTION + if (p->model.objects.empty()) { return ""; } +#else if (p->objects.empty()) { return ""; } +#endif // ENABLE_EXTENDED_SELECTION if (! p->export_gcode_output_file.empty()) { GUI::show_error(this, _(L("Another export job is currently running."))); @@ -1866,7 +1983,11 @@ fs::path Plater::export_gcode(const fs::path &output_path) void Plater::export_stl() { +#if ENABLE_EXTENDED_SELECTION + if (p->model.objects.empty()) { return; } +#else if (p->objects.empty()) { return; } +#endif // ENABLE_EXTENDED_SELECTION auto dialog = p->get_export_file(FT_STL); if (! dialog) { return; } @@ -1881,7 +2002,11 @@ void Plater::export_stl() void Plater::export_amf() { +#if ENABLE_EXTENDED_SELECTION + if (p->model.objects.empty()) { return; } +#else if (p->objects.empty()) { return; } +#endif // ENABLE_EXTENDED_SELECTION auto dialog = p->get_export_file(FT_AMF); if (! dialog) { return; } @@ -1900,7 +2025,11 @@ void Plater::export_amf() void Plater::export_3mf() { +#if ENABLE_EXTENDED_SELECTION + if (p->model.objects.empty()) { return; } +#else if (p->objects.empty()) { return; } +#endif // ENABLE_EXTENDED_SELECTION auto dialog = p->get_export_file(FT_3MF); if (! dialog) { return; } From 3059438853cc75c6100a1a7b46c62a7e0eb3c95b Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Wed, 17 Oct 2018 09:40:04 +0200 Subject: [PATCH 115/186] Fixed toolbar update after reducing instances count --- src/slic3r/GUI/Plater.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index f52b585658..cd0dc278d9 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1899,6 +1899,9 @@ void Plater::decrease(size_t num) } p->update(); + p->selection_changed(); + + // $self->schedule_background_process; } void Plater::set_number_of_copies(size_t num) From 7ed2752b2b9d6c86ca13b1153541f80db8ecc0de Mon Sep 17 00:00:00 2001 From: bubnikv Date: Wed, 17 Oct 2018 11:12:38 +0200 Subject: [PATCH 116/186] WIP: Reconstruction of background processing update timer, added unique IDs to the Model / ModelObject / ModelVolume objects, added a copy of Model hierarchy at the Print, WIP: new Print::apply() method to update the Print's copy of Model, to update the Print's PrintObjects, to update status of the Print and PrintObjects, and to possibly stop the background processing. --- src/libslic3r/Model.cpp | 35 ++- src/libslic3r/Model.hpp | 100 ++++++--- src/libslic3r/Print.cpp | 409 +++++++++++++++++++++++++++++++++++ src/libslic3r/Print.hpp | 9 + src/slic3r/GUI/MainFrame.cpp | 78 ++++--- src/slic3r/GUI/Plater.cpp | 78 ++++--- src/slic3r/GUI/Plater.hpp | 2 +- xs/xsp/Model.xsp | 2 +- 8 files changed, 602 insertions(+), 111 deletions(-) diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 8ced1018db..747edc7d15 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -21,6 +21,8 @@ namespace Slic3r { unsigned int Model::s_auto_extruder_id = 1; +ModelID ModelBase::s_last_id = 0; + Model::Model(const Model &other) { // copy materials @@ -503,6 +505,7 @@ void Model::reset_auto_extruder_id() } ModelObject::ModelObject(Model *model, const ModelObject &other, bool copy_volumes) : + ModelBase(other), // copy the id name(other.name), input_file(other.input_file), instances(), @@ -518,13 +521,13 @@ ModelObject::ModelObject(Model *model, const ModelObject &other, bool copy_volum { if (copy_volumes) { this->volumes.reserve(other.volumes.size()); - for (ModelVolumePtrs::const_iterator i = other.volumes.begin(); i != other.volumes.end(); ++i) - this->add_volume(**i); + for (ModelVolume *model_volume : other.volumes) + this->add_volume(*model_volume); } this->instances.reserve(other.instances.size()); - for (ModelInstancePtrs::const_iterator i = other.instances.begin(); i != other.instances.end(); ++i) - this->add_instance(**i); + for (const ModelInstance *model_instance : other.instances) + this->add_instance(*model_instance); } ModelObject& ModelObject::operator=(ModelObject other) @@ -535,6 +538,7 @@ ModelObject& ModelObject::operator=(ModelObject other) void ModelObject::swap(ModelObject &other) { + std::swap(this->m_id, other.m_id); std::swap(this->input_file, other.input_file); std::swap(this->instances, other.instances); std::swap(this->volumes, other.volumes); @@ -553,6 +557,13 @@ ModelObject::~ModelObject() this->clear_instances(); } +// Clone this ModelObject including its volumes and instances, keep the IDs of the copies equal to the original. +// Called by Print::apply() to clone the Model / ModelObject hierarchy to the back end for background processing. +ModelObject* ModelObject::clone(Model *parent) +{ + return new ModelObject(parent, *this, true); +} + ModelVolume* ModelObject::add_volume(const TriangleMesh &mesh) { ModelVolume* v = new ModelVolume(this, mesh); @@ -903,7 +914,7 @@ void ModelObject::split(ModelObjectPtrs* new_objects) new_volume->name = volume->name; new_volume->config = volume->config; new_volume->set_type(volume->type()); - new_volume->material_id(volume->material_id()); + new_volume->set_material_id(volume->material_id()); new_objects->push_back(new_object); delete mesh; @@ -982,22 +993,22 @@ void ModelObject::print_info() const cout << "volume = " << mesh.volume() << endl; } -void ModelVolume::material_id(t_model_material_id material_id) +void ModelVolume::set_material_id(t_model_material_id material_id) { - this->_material_id = material_id; + m_material_id = material_id; - // ensure this->_material_id references an existing material + // ensure m_material_id references an existing material (void)this->object->get_model()->add_material(material_id); } ModelMaterial* ModelVolume::material() const { - return this->object->get_model()->get_material(this->_material_id); + return this->object->get_model()->get_material(m_material_id); } void ModelVolume::set_material(t_model_material_id material_id, const ModelMaterial &material) { - this->_material_id = material_id; + m_material_id = material_id; (void)this->object->get_model()->add_material(material_id, material); } @@ -1006,8 +1017,8 @@ ModelMaterial* ModelVolume::assign_unique_material() Model* model = this->get_object()->get_model(); // as material-id "0" is reserved by the AMF spec we start from 1 - this->_material_id = 1 + model->materials.size(); // watchout for implicit cast - return model->add_material(this->_material_id); + m_material_id = 1 + model->materials.size(); // watchout for implicit cast + return model->add_material(m_material_id); } void ModelVolume::calculate_convex_hull() diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index 695de61275..4c3c034260 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -20,6 +20,7 @@ class ModelMaterial; class ModelObject; class ModelVolume; class PresetBundle; +class Print; typedef std::string t_model_material_id; typedef std::string t_model_material_attribute; @@ -30,8 +31,27 @@ typedef std::vector ModelObjectPtrs; typedef std::vector ModelVolumePtrs; typedef std::vector ModelInstancePtrs; +// Unique identifier of a Model, ModelObject, ModelVolume, ModelInstance or ModelMaterial. +// Used to synchronize the front end (UI) with the back end (BackgroundSlicingProcess / Print / PrintObject) +typedef size_t ModelID; + +// Base for Model, ModelObject, ModelVolume, ModelInstance or ModelMaterial to provide a unique ID +// to synchronize the front end (UI) with the back end (BackgroundSlicingProcess / Print / PrintObject). +class ModelBase +{ +public: + ModelID id() const { return m_id; } + +protected: + ModelID m_id = generate_new_id(); + +private: + static inline ModelID generate_new_id() { return s_last_id ++; } + static ModelID s_last_id; +}; + // Material, which may be shared across multiple ModelObjects of a single Model. -class ModelMaterial +class ModelMaterial : public ModelBase { friend class Model; public: @@ -56,7 +76,7 @@ private: // and possibly having multiple modifier volumes, each modifier volume with its set of parameters and materials. // Each ModelObject may be instantiated mutliple times, each instance having different placement on the print bed, // different rotation and different uniform scaling. -class ModelObject +class ModelObject : public ModelBase { friend class Model; public: @@ -85,21 +105,21 @@ public: to new volumes before adding them to this object in order to preserve alignment when user expects that. */ Vec3d origin_translation; - - Model* get_model() const { return m_model; }; - - ModelVolume* add_volume(const TriangleMesh &mesh); - ModelVolume* add_volume(TriangleMesh &&mesh); - ModelVolume* add_volume(const ModelVolume &volume); - void delete_volume(size_t idx); - void clear_volumes(); - ModelInstance* add_instance(); - ModelInstance* add_instance(const ModelInstance &instance); - ModelInstance* add_instance(const Vec3d &offset, const Vec3d &scaling_factor, const Vec3d &rotation); - void delete_instance(size_t idx); - void delete_last_instance(); - void clear_instances(); + Model* get_model() const { return m_model; }; + + ModelVolume* add_volume(const TriangleMesh &mesh); + ModelVolume* add_volume(TriangleMesh &&mesh); + ModelVolume* add_volume(const ModelVolume &volume); + void delete_volume(size_t idx); + void clear_volumes(); + + ModelInstance* add_instance(); + ModelInstance* add_instance(const ModelInstance &instance); + ModelInstance* add_instance(const Vec3d &offset, const Vec3d &scaling_factor, const Vec3d &rotation); + void delete_instance(size_t idx); + void delete_last_instance(); + void clear_instances(); // Returns the bounding box of the transformed instances. // This bounding box is approximate and not snug. @@ -137,8 +157,15 @@ public: // Print object statistics to console. void print_info() const; - -private: + +protected: + friend class Print; + // Clone this ModelObject including its volumes and instances, keep the IDs of the copies equal to the original. + // Called by Print::apply() to clone the Model / ModelObject hierarchy to the back end for background processing. + ModelObject* clone(Model *parent); + void set_model(Model *model) { m_model = model; } + +private: ModelObject(Model *model) : layer_height_profile_valid(false), m_model(model), origin_translation(Vec3d::Zero()), m_bounding_box_valid(false) {} ModelObject(Model *model, const ModelObject &other, bool copy_volumes = true); ModelObject& operator= (ModelObject other); @@ -146,7 +173,7 @@ private: ~ModelObject(); // Parent object, owning this ModelObject. - Model *m_model; + Model *m_model; // Bounding box, cached. mutable BoundingBoxf3 m_bounding_box; @@ -155,20 +182,20 @@ private: // An object STL, or a modifier volume, over which a different set of parameters shall be applied. // ModelVolume instances are owned by a ModelObject. -class ModelVolume +class ModelVolume : public ModelBase { friend class ModelObject; // The convex hull of this model's mesh. - TriangleMesh m_convex_hull; + TriangleMesh m_convex_hull; public: - std::string name; + std::string name; // The triangular model. - TriangleMesh mesh; + TriangleMesh mesh; // Configuration parameters specific to an object model geometry or a modifier volume, // overriding the global Slic3r settings and the ModelObject settings. - DynamicPrintConfig config; + DynamicPrintConfig config; enum Type { MODEL_TYPE_INVALID = -1, @@ -178,6 +205,9 @@ public: SUPPORT_BLOCKER, }; + // Clone this ModelVolume, keep the ID identical, set the parent to the cloned volume. + ModelVolume* clone(ModelObject *parent) { return new ModelVolume(parent, *this); } + // A parent object owning this modifier volume. ModelObject* get_object() const { return this->object; }; Type type() const { return m_type; } @@ -186,8 +216,9 @@ public: bool is_modifier() const { return m_type == PARAMETER_MODIFIER; } bool is_support_enforcer() const { return m_type == SUPPORT_ENFORCER; } bool is_support_blocker() const { return m_type == SUPPORT_BLOCKER; } - t_model_material_id material_id() const { return this->_material_id; } - void material_id(t_model_material_id material_id); + bool is_support_modifier() const { return m_type == SUPPORT_BLOCKER || m_type == SUPPORT_ENFORCER; } + t_model_material_id material_id() const { return m_material_id; } + void set_material_id(t_model_material_id material_id); ModelMaterial* material() const; void set_material(t_model_material_id material_id, const ModelMaterial &material); // Split this volume, append the result to the object owning this volume. @@ -199,7 +230,7 @@ public: void calculate_convex_hull(); const TriangleMesh& get_convex_hull() const; - TriangleMesh& get_convex_hull(); + TriangleMesh& get_convex_hull(); // Helpers for loading / storing into AMF / 3MF files. static Type type_from_string(const std::string &s); @@ -210,23 +241,26 @@ private: ModelObject* object; // Is it an object to be printed, or a modifier volume? Type m_type; - t_model_material_id _material_id; + t_model_material_id m_material_id; ModelVolume(ModelObject *object, const TriangleMesh &mesh) : mesh(mesh), m_type(MODEL_PART), object(object) { if (mesh.stl.stats.number_of_facets > 1) calculate_convex_hull(); } - ModelVolume(ModelObject *object, TriangleMesh &&mesh, TriangleMesh &&convex_hull) : mesh(std::move(mesh)), m_convex_hull(std::move(convex_hull)), m_type(MODEL_PART), object(object) {} + ModelVolume(ModelObject *object, TriangleMesh &&mesh, TriangleMesh &&convex_hull) : + mesh(std::move(mesh)), m_convex_hull(std::move(convex_hull)), m_type(MODEL_PART), object(object) {} ModelVolume(ModelObject *object, const ModelVolume &other) : + ModelBase(other), // copy the ID name(other.name), mesh(other.mesh), m_convex_hull(other.m_convex_hull), config(other.config), m_type(other.m_type), object(object) { - this->material_id(other.material_id()); + this->set_material_id(other.material_id()); } ModelVolume(ModelObject *object, const ModelVolume &other, const TriangleMesh &&mesh) : + ModelBase(other), // copy the ID name(other.name), mesh(std::move(mesh)), config(other.config), m_type(other.m_type), object(object) { - this->material_id(other.material_id()); + this->set_material_id(other.material_id()); if (mesh.stl.stats.number_of_facets > 1) calculate_convex_hull(); } @@ -234,7 +268,7 @@ private: // A single instance of a ModelObject. // Knows the affine transformation of an object. -class ModelInstance +class ModelInstance : public ModelBase { public: enum EPrintVolumeState : unsigned char @@ -321,7 +355,7 @@ private: // and with multiple modifier meshes. // A model groups multiple objects, each object having possibly multiple instances, // all objects may share mutliple materials. -class Model +class Model : public ModelBase { static unsigned int s_auto_extruder_id; diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 37b55f87df..82dc089d4c 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -571,6 +571,415 @@ exit_for_rearrange_regions: return invalidated; } +// Test whether the two models contain the same number of ModelObjects with the same set of IDs +// ordered in the same order. In that case it is not necessary to kill the background processing. +static inline bool model_object_list_equal(const Model &model_old, const Model &model_new) +{ + if (model_old.objects.size() != model_new.objects.size()) + return false; + for (size_t i = 0; i < model_old.objects.size(); ++ i) + if (model_old.objects[i]->id() != model_new.objects[i]->id()) + return false; + return true; +} + +// Test whether the new model is just an extension of the old model (new objects were added +// to the end of the original list. In that case it is not necessary to kill the background processing. +static inline bool model_object_list_extended(const Model &model_old, const Model &model_new) +{ + if (model_old.objects.size() >= model_new.objects.size()) + return false; + for (size_t i = 0; i < model_old.objects.size(); ++ i) + if (model_old.objects[i]->id() != model_new.objects[i]->id()) + return false; + return true; +} + +static inline bool model_volume_list_changed(const ModelObject &model_object_old, const ModelObject &model_object_new, const ModelVolume::Type type) +{ + bool modifiers_differ = false; + size_t i_old, i_new; + for (i_old = 0, i_new = 0; i_old < model_object_old.volumes.size() && i_new < model_object_new.volumes.size();) { + const ModelVolume &mv_old = *model_object_old.volumes[i_old]; + const ModelVolume &mv_new = *model_object_new.volumes[i_old]; + if (mv_old.type() != type) { + ++ i_old; + continue; + } + if (mv_new.type() != type) { + ++ i_new; + continue; + } + if (mv_old.id() != mv_new.id()) + return true; + //FIXME test for the content of the mesh! + //FIXME test for the transformation matrices! + ++ i_old; + ++ i_new; + } + for (; i_old < model_object_old.volumes.size(); ++ i_old) { + const ModelVolume &mv_old = *model_object_old.volumes[i_old]; + if (mv_old.type() == type) + // ModelVolume was deleted. + return true; + } + for (; i_new < model_object_new.volumes.size(); ++ i_new) { + const ModelVolume &mv_new = *model_object_new.volumes[i_new]; + if (mv_new.type() == type) + // ModelVolume was added. + return true; + } + return false; +} + +static inline void model_volume_list_update_supports(ModelObject &model_object_dst, const ModelObject &model_object_src) +{ + // 1) Delete the support volumes from model_object_dst. + { + std::vector dst; + dst.reserve(model_object_dst.volumes.size()); + for (ModelVolume *vol : model_object_dst.volumes) { + if (vol->is_support_modifier()) + dst.emplace_back(vol); + else + delete vol; + } + model_object_dst.volumes = std::move(dst); + } + // 2) Copy the support volumes from model_object_src to the end of model_object_dst. + for (ModelVolume *vol : model_object_src.volumes) { + if (vol->is_support_modifier()) + model_object_dst.volumes.emplace_back(vol->clone(&model_object_dst)); + } +} + +static inline bool transform3d_lower(const Transform3d &lhs, const Transform3d &rhs) +{ + typedef Transform3d::Scalar T; + const T *lv = lhs.data(); + const T *rv = rhs.data(); + for (size_t i = 0; i < 16; ++ i, ++ lv, ++ rv) { + if (*lv < *rv) + return true; + else if (*lv > *rv) + return false; + } + return false; +} + +static inline bool transform3d_equal(const Transform3d &lhs, const Transform3d &rhs) +{ + typedef Transform3d::Scalar T; + const T *lv = lhs.data(); + const T *rv = rhs.data(); + for (size_t i = 0; i < 16; ++ i, ++ lv, ++ rv) + if (*lv != *rv) + return false; + return true; +} + +struct PrintInstances +{ + Transform3d trafo; + Points instances; + bool operator<(const PrintInstances &rhs) const { return transform3d_lower(this->trafo, rhs.trafo); } +}; + +// Generate a list of trafos and XY offsets for instances of a ModelObject +static std::vector print_objects_from_model_object(const ModelObject &model_object) +{ + std::set trafos; + PrintInstances trafo; + trafo.instances.assign(1, Point()); + for (ModelInstance *model_instance : model_object.instances) + if (model_instance->is_printable()) { + const Vec3d &offst = model_instance->get_offset(); + trafo.trafo = model_instance->world_matrix(true); + trafo.instances.front() = Point::new_scale(offst(0), offst(1)); + auto it = trafos.find(trafo); + if (it == trafos.end()) + trafos.emplace(trafo); + else + const_cast(*it).instances.emplace_back(trafo.instances.front()); + } + return std::vector(trafos.begin(), trafos.end()); +} + +bool Print::apply(const Model &model, const DynamicPrintConfig &config) +{ + // Grab the lock for the Print / PrintObject milestones. + tbb::mutex::scoped_lock lock(m_mutex); + + struct ModelObjectStatus { + enum Status { + Unknown, + Old, + New, + Moved, + Deleted, + }; + ModelObjectStatus(ModelID id, Status status = Unknown) : id(id), status(status) {} + ModelID id; + Status status; + // Search by id. + bool operator<(const ModelObjectStatus &rhs) const { return id < rhs.id; } + }; + std::set model_object_status; + + // 1) Synchronize model objects. + if (model.id() != m_model.id()) { + // Kill everything, initialize from scratch. + // The following call shall kill any computation if running. + this->invalidate_all_steps(); + for (PrintObject *object : m_objects) { + model_object_status.emplace(object->model_object()->id(), ModelObjectStatus::Deleted); + delete object; + } + m_objects.clear(); + for (PrintRegion *region : m_regions) + delete region; + m_regions.clear(); + m_model = model; + } else { + if (model_object_list_equal(m_model, model)) { + // The object list did not change. + } else if (model_object_list_extended(m_model, model)) { + // Add new objects. Their volumes and configs will be synchronized later. + this->invalidate_step(psGCodeExport); + for (size_t i = m_model.objects.size(); i < model.objects.size(); ++ i) { + model_object_status.emplace(model.objects[i]->id(), ModelObjectStatus::New); + m_model.objects.emplace_back(model.objects[i]->clone(&m_model)); + } + } else { + // Reorder the objects, add new objects. + // First stop background processing before shuffling or deleting the PrintObjects in the object list. + m_cancel_callback(); + this->invalidate_step(psGCodeExport); + // Second create a new list of objects. + std::vector old(std::move(m_model.objects)); + m_model.objects.clear(); + m_model.objects.reserve(model.objects.size()); + auto by_id_lower = [](const ModelObject *lhs, const ModelObject *rhs){ return lhs->id() < rhs->id(); }; + std::sort(old.begin(), old.end(), by_id_lower); + for (const ModelObject *mobj : model.objects) { + auto it = std::lower_bound(old.begin(), old.end(), mobj, by_id_lower); + if (it == old.end() || (*it)->id() != mobj->id()) { + // New ModelObject added. + m_model.objects.emplace_back((*it)->clone(&m_model)); + model_object_status.emplace(mobj->id(), ModelObjectStatus::New); + } else { + // Existing ModelObject re-added (possibly moved in the list). + m_model.objects.emplace_back(*it); + model_object_status.emplace(mobj->id(), ModelObjectStatus::Old); + } + } + bool deleted_any = false; + for (ModelObject *mobj : old) + if (model_object_status.find(ModelObjectStatus(mobj->id())) == model_object_status.end()) { + model_object_status.emplace(mobj->id(), ModelObjectStatus::Deleted); + delete mobj; + deleted_any = true; + } + if (deleted_any) { + // Delete PrintObjects of the deleted ModelObjects. + std::vector old = std::move(m_objects); + m_objects.clear(); + m_objects.reserve(old.size()); + for (PrintObject *print_object : old) { + auto it_status = model_object_status.find(ModelObjectStatus(print_object->model_object()->id())); + assert(it_status != model_object_status.end()); + if (it_status->status == ModelObjectStatus::Deleted) { + print_object->invalidate_all_steps(); + delete print_object; + } else + m_objects.emplace_back(print_object); + } + } + } + } + + // 2) Map print objects including their transformation matrices. + struct PrintObjectStatus { + enum Status { + Unknown, + Deleted, + New + }; + PrintObjectStatus(PrintObject *print_object, Status status = Unknown) : + id(print_object->model_object()->id()), + print_object(print_object), + trafo(print_object->trafo()), + status(status) {} + PrintObjectStatus(ModelID id) : id(id), print_object(nullptr), trafo(Transform3d::Identity()), status(Unknown) {} + // ID of the ModelObject & PrintObject + ModelID id; + // Pointer to the old PrintObject + PrintObject *print_object; + // Trafo generated with model_object->world_matrix(true) + Transform3d trafo; + Status status; + // Search by id. + bool operator<(const PrintObjectStatus &rhs) const { return id < rhs.id; } + }; + std::multiset print_object_status; + for (PrintObject *print_object : m_objects) + print_object_status.emplace(PrintObjectStatus(print_object)); + + // 3) Synchronize ModelObjects & PrintObjects. + for (size_t idx_model_object = 0; idx_model_object < model.objects.size(); ++ idx_model_object) { + ModelObject &model_object = *m_model.objects[idx_model_object]; + auto it_status = model_object_status.find(ModelObjectStatus(model_object.id())); + assert(it_status != model_object_status.end()); + assert(it_status->status != ModelObjectStatus::Deleted); + if (it_status->status == ModelObjectStatus::New) + // PrintObject instances will be added in the next loop. + continue; + // Update the ModelObject instance, possibly invalidate the linked PrintObjects. + assert(it_status->status == ModelObjectStatus::Moved); + const ModelObject &model_object_new = *model.objects[idx_model_object]; + // Check whether a model part volume was added or removed, their transformations or order changed. + bool model_parts_differ = model_volume_list_changed(model_object, model_object_new, ModelVolume::MODEL_PART); + bool modifiers_differ = model_volume_list_changed(model_object, model_object_new, ModelVolume::PARAMETER_MODIFIER); + bool support_blockers_differ = model_volume_list_changed(model_object, model_object_new, ModelVolume::SUPPORT_BLOCKER); + bool support_enforcers_differ = model_volume_list_changed(model_object, model_object_new, ModelVolume::SUPPORT_ENFORCER); + if (model_parts_differ || modifiers_differ) { + // The very first step (the slicing step) is invalidated. One may freely remove all associated PrintObjects. + auto range = print_object_status.equal_range(PrintObjectStatus(model_object.id())); + for (auto it = range.first; it != range.second; ++ it) { + it->print_object->invalidate_all_steps(); + const_cast(*it).status = PrintObjectStatus::Deleted; + } + // Copy content of the ModelObject including its ID, reset the parent. + model_object = model_object_new; + model_object.set_model(&m_model); + } else if (support_blockers_differ || support_enforcers_differ) { + // First stop background processing before shuffling or deleting the ModelVolumes in the ModelObject's list. + m_cancel_callback(); + // Invalidate just the supports step. + auto range = print_object_status.equal_range(PrintObjectStatus(model_object.id())); + for (auto it = range.first; it != range.second; ++ it) + it->print_object->invalidate_step(posSupportMaterial); + // Copy just the support volumes. + model_volume_list_update_supports(model_object, model_object_new); + } + if (! model_parts_differ && ! modifiers_differ) { + // Synchronize the remaining data of ModelVolumes (name, config, m_type, m_material_id) + } + } + + // 4) Generate PrintObjects from ModelObjects and their instances. + std::vector print_objects_new; + print_objects_new.reserve(std::max(m_objects.size(), m_model.objects.size())); + // Walk over all new model objects and check, whether there are matching PrintObjects. + for (ModelObject *model_object : m_model.objects) { + auto range = print_object_status.equal_range(PrintObjectStatus(model_object->id())); + std::vector old; + if (range.first != range.second) { + old.reserve(print_object_status.count(PrintObjectStatus(model_object->id()))); + for (auto it = range.first; it != range.second; ++ it) + if (it->status != PrintObjectStatus::Deleted) + old.emplace_back(&(*it)); + } + // Generate a list of trafos and XY offsets for instances of a ModelObject + std::vector new_print_instances = print_objects_from_model_object(*model_object); + if (old.empty()) { + // Simple case, just generate new instances. + for (const PrintInstances &print_instances : new_print_instances) { + PrintObject *print_object = new PrintObject(this, model_object, model_object->raw_bounding_box()); + print_objects_new.emplace_back(print_object); + print_object_status.emplace(PrintObjectStatus(print_object, PrintObjectStatus::New)); + } + continue; + } + // Complex case, try to merge the two lists. + // Sort the old lexicographically by their trafos. + std::sort(old.begin(), old.end(), [](const PrintObjectStatus *lhs, const PrintObjectStatus *rhs){ return transform3d_lower(lhs->trafo, rhs->trafo); }); + // Merge the old / new lists. + + } + if (m_objects != print_objects_new) { + m_cancel_callback(); + m_objects = print_objects_new; + } + + // Synchronize materials. + +#if 0 + { + m_model = model; + for (const ModelObject *model_object : m_model.objects) { + PrintObject *object = new PrintObject(this, model_object, model_object->raw_bounding_box()); + m_objects.emplace_back(object); + size_t volume_id = 0; + for (const ModelVolume *volume : model_object->volumes) { + if (! volume->is_model_part() && ! volume->is_modifier()) + continue; + // Get the config applied to this volume. + PrintRegionConfig config = this->_region_config_from_model_volume(*volume); + // Find an existing print region with the same config. + size_t region_id = size_t(-1); + for (size_t i = 0; i < m_regions.size(); ++ i) + if (config.equals(m_regions[i]->config())) { + region_id = i; + break; + } + // If no region exists with the same config, create a new one. + if (region_id == size_t(-1)) { + region_id = m_regions.size(); + this->add_region(config); + } + // Assign volume to a region. + object->add_region_volume(region_id, volume_id); + ++ volume_id; + } + // Apply config to print object. + object->config_apply(this->default_object_config()); + { + //normalize_and_apply_config(object->config(), model_object->config); + DynamicPrintConfig src_normalized(model_object->config); + src_normalized.normalize(); + object->config_apply(src_normalized, true); + } + } + } else { + // Synchronize m_model.objects with model.objects + } +#endif + + this->update_object_placeholders(); +} + +// Update "scale", "input_filename", "input_filename_base" placeholders from the current m_objects. +void Print::update_object_placeholders() +{ + // get the first input file name + std::string input_file; + std::vector v_scale; + for (const PrintObject *object : m_objects) { + const ModelObject &mobj = *object->model_object(); +#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM + // CHECK_ME -> Is the following correct ? + v_scale.push_back("x:" + boost::lexical_cast(mobj.instances[0]->get_scaling_factor(X) * 100) + + "% y:" + boost::lexical_cast(mobj.instances[0]->get_scaling_factor(Y) * 100) + + "% z:" + boost::lexical_cast(mobj.instances[0]->get_scaling_factor(Z) * 100) + "%"); +#else + v_scale.push_back(boost::lexical_cast(mobj.instances[0]->scaling_factor * 100) + "%"); +#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM + if (input_file.empty()) + input_file = mobj.input_file; + } + + PlaceholderParser &pp = m_placeholder_parser; + pp.set("scale", v_scale); + if (! input_file.empty()) { + // get basename with and without suffix + const std::string input_basename = boost::filesystem::path(input_file).filename().string(); + pp.set("input_filename", input_basename); + const std::string input_basename_base = input_basename.substr(0, input_basename.find_last_of(".")); + pp.set("input_filename_base", input_basename_base); + } +} + bool Print::has_infinite_skirt() const { return (m_config.skirt_height == -1 && m_config.skirts > 0) diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index 5bbeb3f6ad..d539053b37 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -194,6 +194,7 @@ public: void config_apply_only(const ConfigBase &other, const t_config_option_keys &keys, bool ignore_nonexistent = false) { this->m_config.apply_only(other, keys, ignore_nonexistent); } const LayerPtrs& layers() const { return m_layers; } const SupportLayerPtrs& support_layers() const { return m_support_layers; } + const Transform3d& trafo() const { return m_trafo; } const Points& copies() const { return m_copies; } bool add_copy(const Vec2d &point); @@ -285,6 +286,8 @@ private: Print *m_print; ModelObject *m_model_object; PrintObjectConfig m_config; + // Translation in Z + Rotation + Scaling / Mirroring. + Transform3d m_trafo = Transform3d::Identity(); // Slic3r::Point objects in scaled G-code coordinates Points m_copies; // scaled coordinates to add to copies (to compensate for the alignment @@ -382,6 +385,8 @@ public: bool reload_model_instances(); void add_model_object(ModelObject* model_object, int idx = -1); bool apply_config(DynamicPrintConfig config); + bool apply(const Model &model, const DynamicPrintConfig &config); + void process(); void export_gcode(const std::string &path_template, GCodePreviewData *preview_data); // SLA export, temporary. @@ -477,6 +482,9 @@ protected: PrintRegion* add_region(const PrintRegionConfig &config); private: + // Update "scale", "input_filename", "input_filename_base" placeholders from the current m_objects. + void update_object_placeholders(); + bool invalidate_state_by_config_options(const std::vector &opt_keys); PrintRegionConfig _region_config_from_model_volume(const ModelVolume &volume); @@ -503,6 +511,7 @@ private: // Callback to be evoked to stop the background processing before a state is updated. cancel_callback_type m_cancel_callback = [](){}; + Model m_model; PrintConfig m_config; PrintObjectConfig m_default_object_config; PrintRegionConfig m_default_region_config; diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 505a451258..2793cb876b 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -159,7 +159,7 @@ void MainFrame::init_tabpanel() if (m_plater) { // load initial config auto full_config = wxGetApp().preset_bundle->full_config(); - m_plater->on_config_change(&full_config); + m_plater->on_config_change(full_config); // Show a correct number of filament fields. // nozzle_diameter is undefined when SLA printer is selected @@ -530,9 +530,10 @@ void MainFrame::quick_slice(const int qs){ // Slic3r::GUI::catch_error(this, [](){ if (m_progress_dialog) m_progress_dialog->Destroy(); }); } -void MainFrame::reslice_now(){ -// if (m_plater) -// m_plater->reslice(); +void MainFrame::reslice_now() +{ + if (m_plater) + m_plater->reslice(); } void MainFrame::repair_stl() @@ -611,12 +612,13 @@ void MainFrame::load_config_file(wxString file/* = wxEmptyString*/) file = dlg->GetPath(); dlg->Destroy(); } -// eval{ + try { wxGetApp().preset_bundle->load_config_file(file.ToStdString()); -// }; - // Dont proceed further if the config file cannot be loaded. -// if (Slic3r::GUI::catch_error(this)) -// return; + } catch (std::exception & /* ex */) { + // Dont proceed further if the config file cannot be loaded. + // if (Slic3r::GUI::catch_error(this)) + // return; + } for (auto tab : m_options_tabs ) tab.second->load_current_preset(); wxGetApp().app_config->update_config_dir(get_dir_name(file)); @@ -644,18 +646,20 @@ void MainFrame::export_configbundle() dlg->Destroy(); if (!file.IsEmpty()) { // Export the config bundle. - wxGetApp().app_config->update_config_dir(get_dir_name(file)); -// eval{ + wxGetApp().app_config->update_config_dir(get_dir_name(file)); + try { wxGetApp().preset_bundle->export_configbundle(file.ToStdString()); -// }; + } catch (std::exception & /* ex */) { // Slic3r::GUI::catch_error(this); + } } } // Loading a config bundle with an external file name used to be used // to auto - install a config bundle on a fresh user account, // but that behavior was not documented and likely buggy. -void MainFrame::load_configbundle(wxString file/* = wxEmptyString, const bool reset_user_profile*/){ +void MainFrame::load_configbundle(wxString file/* = wxEmptyString, const bool reset_user_profile*/) +{ if (!wxGetApp().check_unsaved_changes()) return; if (file.IsEmpty()) { @@ -671,10 +675,11 @@ void MainFrame::load_configbundle(wxString file/* = wxEmptyString, const bool re wxGetApp().app_config->update_config_dir(get_dir_name(file)); auto presets_imported = 0; -// eval{ + try { presets_imported = wxGetApp().preset_bundle->load_configbundle(file.ToStdString()); -// }; + } catch (std::exception & /* ex */) { // Slic3r::GUI::catch_error(this) and return; + } // Load the currently selected preset into the GUI, update the preset selection box. for (auto tab : m_options_tabs) @@ -686,20 +691,24 @@ void MainFrame::load_configbundle(wxString file/* = wxEmptyString, const bool re // Load a provied DynamicConfig into the Print / Filament / Printer tabs, thus modifying the active preset. // Also update the platter with the new presets. -void MainFrame::load_config(const DynamicPrintConfig& config){ +void MainFrame::load_config(const DynamicPrintConfig& config) +{ for (auto tab : m_options_tabs) tab.second->load_config(config); -// if (m_plater) m_plater->on_config_change(config); + if (m_plater) + m_plater->on_config_change(config); } -void MainFrame::select_tab(size_t tab) const{ +void MainFrame::select_tab(size_t tab) const +{ m_tabpanel->SetSelection(tab); } // Set a camera direction, zoom to all objects. -void MainFrame::select_view(const std::string& direction){ -// if (m_plater) -// m_plater->select_view(direction); +void MainFrame::select_view(const std::string& direction) +{ +// if (m_plater) +// m_plater->select_view(direction); } wxMenuItem* MainFrame::append_menu_item(wxMenu* menu, @@ -743,8 +752,7 @@ void MainFrame::on_presets_changed(SimpleEvent &event) if (preset_type == Slic3r::Preset::TYPE_PRINTER) { // Printer selected at the Printer tab, update "compatible" marks at the print and filament selectors. // XXX: Do this in a more C++ way - std::vector tab_names_other = { "print", "filament", "sla_material" }; - for (const auto tab_name_other : tab_names_other) { + for (const auto tab_name_other : { "print", "filament", "sla_material" }) { Tab* cur_tab = m_options_tabs[tab_name_other]; // If the printer tells us that the print or filament preset has been switched or invalidated, // refresh the print or filament tab page.Otherwise just refresh the combo box. @@ -756,8 +764,7 @@ void MainFrame::on_presets_changed(SimpleEvent &event) cur_tab->load_current_preset(); } } - // XXX: ? - // m_plater->on_config_change(tab->get_config()); + m_plater->on_config_change(*tab->get_config()); } } @@ -769,18 +776,19 @@ void MainFrame::on_value_changed(wxCommandEvent& event) return; auto opt_key = event.GetString(); - auto config = tab->get_config(); if (m_plater) { - m_plater->on_config_change(config); // propagate config change events to the plater - if (opt_key == "extruders_count"){ - auto value = event.GetInt(); - m_plater->on_extruders_change(value); - } + m_plater->on_config_change(*tab->get_config()); // propagate config change events to the plater + if (opt_key == "extruders_count"){ + auto value = event.GetInt(); + m_plater->on_extruders_change(value); + } + } + // Don't save while loading for the first time. + if (m_loaded) { + AppConfig &cfg = *wxGetApp().app_config; + if (cfg.get("autosave") == "1") + cfg.save(); } - // don't save while loading for the first time - // #ys_FIXME ?autosave? -// if (wxGetApp().autosave && m_loaded) -// m_config->save(wxGetApp().autosave); } // Called after the Preferences dialog is closed and the program settings are saved. diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index f22b700743..9d8d3ce0f0 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -209,6 +209,7 @@ PresetComboBox::PresetComboBox(wxWindow *parent, Preset::Type preset_type) : if (dialog->ShowModal() == wxID_OK) { DynamicPrintConfig cfg = *wxGetApp().get_tab(Preset::TYPE_PRINTER)->get_config(); + //FIXME this is too expensive to call full_config to get just the extruder color! auto colors = static_cast(wxGetApp().preset_bundle->full_config().option("extruder_colour")->clone()); colors->values[extruder_idx] = dialog->GetColourData().GetColour().GetAsString(wxC2S_HTML_SYNTAX); @@ -216,7 +217,7 @@ PresetComboBox::PresetComboBox(wxWindow *parent, Preset::Type preset_type) : wxGetApp().get_tab(Preset::TYPE_PRINTER)->load_config(cfg); wxGetApp().preset_bundle->update_platter_filament_ui(extruder_idx, this); - wxGetApp().plater()->on_config_change(&cfg); + wxGetApp().plater()->on_config_change(cfg); } dialog->Destroy(); }); @@ -741,7 +742,8 @@ struct Plater::priv Sidebar *sidebar; wxGLCanvas *canvas3D; // TODO: Use GLCanvas3D when we can Preview *preview; - BackgroundSlicingProcess background_process; + BackgroundSlicingProcess background_process; + wxTimer background_process_timer; static const std::regex pattern_bundle; static const std::regex pattern_3mf; @@ -855,15 +857,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) : _3DScene::enable_shader(canvas3D, true); _3DScene::enable_force_zoom_to_bed(canvas3D, true); - // XXX: apply_config_timer - // { - // my $timer_id = Wx::NewId(); - // $self->{apply_config_timer} = Wx::Timer->new($self, $timer_id); - // EVT_TIMER($self, $timer_id, sub { - // my ($self, $event) = @_; - // $self->async_apply_config; - // }); - // } + background_process_timer.Bind(wxEVT_TIMER, [this](wxTimerEvent &evt){ this->async_apply_config(); }, 0); auto *bed_shape = config->opt("bed_shape"); _3DScene::set_bed_shape(canvas3D, bed_shape->values); @@ -961,7 +955,7 @@ void Plater::priv::update(bool force_autocenter) preview->reset_gcode_preview_data(); preview->reload_print(); - // schedule_background_process(); // TODO + schedule_background_process(); } void Plater::priv::update_ui_from_settings() @@ -1172,7 +1166,7 @@ std::vector Plater::priv::load_model_objects(const ModelObjectPtrs &mode _3DScene::zoom_to_volumes(canvas3D); object_list_changed(); - // $self->schedule_background_process; + this->schedule_background_process(); return obj_idxs; } @@ -1449,12 +1443,40 @@ void Plater::priv::split_object() void Plater::priv::schedule_background_process() { - // TODO + // Trigger the timer event after 0.5s + this->background_process_timer.Start(500, wxTIMER_ONE_SHOT); } void Plater::priv::async_apply_config() { - // TODO + // Apply new config to the possibly running background task. + bool was_running = this->background_process.running(); + bool invalidated = this->background_process.apply_config(wxGetApp().preset_bundle->full_config()); + // Just redraw the 3D canvas without reloading the scene to consume the update of the layer height profile. + if (Slic3r::_3DScene::is_layers_editing_enabled(this->canvas3D)) + this->canvas3D->Refresh(); + // If the apply_config caused the calculation to stop, or it was not running yet: + if (invalidated) { + if (was_running) { + // Hide the slicing results if the current slicing status is no more valid. + this->sidebar->show_info_sizers(false); + } + if (this->get_config("background_processing") == "1") + this->background_process.start(); + if (was_running) { + // Reset preview canvases. If the print has been invalidated, the preview canvases will be cleared. + // Otherwise they will be just refreshed. + this->gcode_preview_data.reset(); + if (this->preview != nullptr) + this->preview->reload_print(); + // We also need to reload 3D scene because of the wipe tower preview box + if (this->config->opt_bool("wipe_tower")) { + std::vector selections = this->collect_selections(); + Slic3r::_3DScene::set_objects_selections(this->canvas3D, selections); + Slic3r::_3DScene::reload_scene(this->canvas3D, 1); + } + } + } } void Plater::priv::start_background_process() @@ -1542,8 +1564,7 @@ void Plater::priv::on_select_preset(wxCommandEvent &evt) // Synchronize config.ini with the current selections. wxGetApp().preset_bundle->export_selections(*wxGetApp().app_config); // update plater with new config - auto config = wxGetApp().preset_bundle->full_config(); - wxGetApp().plater()->on_config_change(&config); + wxGetApp().plater()->on_config_change(wxGetApp().preset_bundle->full_config()); } void Plater::priv::on_progress_event() @@ -1677,7 +1698,8 @@ void Plater::priv::on_scale_uniformly(SimpleEvent&) // $self->selection_changed(1); # refresh info (size, volume etc.) // $self->update; -// $self->schedule_background_process; + + this->schedule_background_process(); } void Plater::priv::on_wipetower_moved(Vec3dEvent &evt) @@ -1756,7 +1778,7 @@ void Plater::increase(size_t num) p->selection_changed(); - // $self->schedule_background_process; + this->p->schedule_background_process(); } void Plater::decrease(size_t num) @@ -1933,11 +1955,11 @@ void Plater::on_extruders_change(int num_extruders) GetParent()->Layout(); } -void Plater::on_config_change(DynamicPrintConfig* config) +void Plater::on_config_change(const DynamicPrintConfig &config) { bool update_scheduled = false; - for ( auto opt_key: p->config->diff(*config)) { - p->config->set_key_value(opt_key, config->option(opt_key)->clone()); + for (auto opt_key : p->config->diff(config)) { + p->config->set_key_value(opt_key, config.option(opt_key)->clone()); if (opt_key == "bed_shape") { if (p->canvas3D) _3DScene::set_bed_shape(p->canvas3D, p->config->option(opt_key)->values); if (p->preview) p->preview->set_bed_shape(p->config->option(opt_key)->values); @@ -1948,7 +1970,7 @@ void Plater::on_config_change(DynamicPrintConfig* config) update_scheduled = true; } // else if(opt_key == "serial_port") { -// sidebar()->p->btn_print->Show(config->get("serial_port")); // ???: btn_print is removed +// sidebar()->p->btn_print->Show(config.get("serial_port")); // ???: btn_print is removed // Layout(); // } else if (opt_key == "print_host") { @@ -1982,10 +2004,8 @@ void Plater::on_config_change(DynamicPrintConfig* config) if (update_scheduled) update(); - if (!p->main_frame->is_loaded()) return ; - - // (re)start timer -// schedule_background_process(); + if (p->main_frame->is_loaded()) + this->p->schedule_background_process(); } wxGLCanvas* Plater::canvas3D() @@ -2012,7 +2032,7 @@ void Plater::changed_object_settings(int obj_idx) if (list->is_parts_changed() || list->is_part_settings_changed()) { // stop_background_process(); // $self->{print}->reload_object($obj_idx); -// schedule_background_process(); + this->p->schedule_background_process(); #if !ENABLE_EXTENDED_SELECTION if (p->canvas3D) _3DScene::reload_scene(p->canvas3D, true); auto selections = p->collect_selections(); @@ -2021,7 +2041,7 @@ void Plater::changed_object_settings(int obj_idx) _3DScene::reload_scene(p->canvas3D, false); } else { -// schedule_background_process(); + this->p->schedule_background_process(); } } diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index fba2e0dc0b..93c88e1316 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -123,7 +123,7 @@ public: void send_gcode(); void on_extruders_change(int extruders_count); - void on_config_change(DynamicPrintConfig* config); + void on_config_change(const DynamicPrintConfig &config); wxGLCanvas* canvas3D(); private: diff --git a/xs/xsp/Model.xsp b/xs/xsp/Model.xsp index 62ccf2b06c..f458a3b92a 100644 --- a/xs/xsp/Model.xsp +++ b/xs/xsp/Model.xsp @@ -262,7 +262,7 @@ ModelMaterial::attributes() %code%{ THIS->name = value; %}; t_model_material_id material_id(); void set_material_id(t_model_material_id material_id) - %code%{ THIS->material_id(material_id); %}; + %code%{ THIS->set_material_id(material_id); %}; Ref material(); Ref config() From 7d1828df05e9f18cc988a6f4913a3e39b428f909 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Wed, 17 Oct 2018 12:17:25 +0200 Subject: [PATCH 117/186] Object context menu wip / Removed links to settings dialog from user interface / Fixed and unified append_menu_item() function / Fixed File->Open menu item / Fixed Window menu items / Added Plater menu --- src/slic3r/GUI/GLCanvas3D.cpp | 9 ++++ src/slic3r/GUI/GLCanvas3D.hpp | 2 + src/slic3r/GUI/GLToolbar.cpp | 2 + src/slic3r/GUI/GLToolbar.hpp | 2 + src/slic3r/GUI/GUI_App.cpp | 19 --------- src/slic3r/GUI/GUI_App.hpp | 9 +--- src/slic3r/GUI/MainFrame.cpp | 48 ++++----------------- src/slic3r/GUI/MainFrame.hpp | 11 +---- src/slic3r/GUI/Plater.cpp | 74 ++++++++++++++++++++++++++++----- src/slic3r/GUI/Plater.hpp | 2 + src/slic3r/GUI/wxExtensions.cpp | 14 +++++++ src/slic3r/GUI/wxExtensions.hpp | 3 ++ 12 files changed, 109 insertions(+), 86 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index d41e59afe6..f0568c5f0b 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -2667,7 +2667,9 @@ wxDEFINE_EVENT(EVT_GLCANVAS_OBJECT_SELECT, SimpleEvent); wxDEFINE_EVENT(EVT_GLCANVAS_OBJECT_SELECT, ObjectSelectEvent); #endif // ENABLE_EXTENDED_SELECTION wxDEFINE_EVENT(EVT_GLCANVAS_VIEWPORT_CHANGED, SimpleEvent); +#if !ENABLE_EXTENDED_SELECTION wxDEFINE_EVENT(EVT_GLCANVAS_DOUBLE_CLICK, SimpleEvent); +#endif // !ENABLE_EXTENDED_SELECTION wxDEFINE_EVENT(EVT_GLCANVAS_RIGHT_CLICK, Vec2dEvent); wxDEFINE_EVENT(EVT_GLCANVAS_MODEL_UPDATE, SimpleEvent); wxDEFINE_EVENT(EVT_GLCANVAS_REMOVE_OBJECT, SimpleEvent); @@ -3439,6 +3441,9 @@ void GLCanvas3D::reload_scene(bool force) { load_object(*m_model, obj_idx); } + + // to update the toolbar + post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT)); } update_gizmos_data(); @@ -3796,8 +3801,10 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) m_mouse.position = Vec2d(-1.0, -1.0); m_dirty = true; } +#if !ENABLE_EXTENDED_SELECTION else if (evt.LeftDClick() && (m_hover_volume_id != -1) && !gizmos_overlay_contains_mouse && (toolbar_contains_mouse == -1)) post_event(SimpleEvent(EVT_GLCANVAS_DOUBLE_CLICK)); +#endif // !ENABLE_EXTENDED_SELECTION else if (evt.LeftDClick() && (toolbar_contains_mouse != -1)) { m_toolbar_action_running = true; @@ -4559,6 +4566,7 @@ bool GLCanvas3D::_init_toolbar() if (!m_toolbar.add_separator()) return false; +#if !ENABLE_EXTENDED_SELECTION item.name = "settings"; item.tooltip = GUI::L_str("Settings..."); item.sprite_id = 8; @@ -4566,6 +4574,7 @@ bool GLCanvas3D::_init_toolbar() item.action_event = EVT_GLTOOLBAR_SETTINGS; if (!m_toolbar.add_item(item)) return false; +#endif // !ENABLE_EXTENDED_SELECTION item.name = "layersediting"; item.tooltip = GUI::L_str("Layers editing"); diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index c887f2c196..be9548a494 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -105,7 +105,9 @@ template using Vec3dsEvent = ArrayEvent; wxDECLARE_EVENT(EVT_GLCANVAS_VIEWPORT_CHANGED, SimpleEvent); +#if !ENABLE_EXTENDED_SELECTION wxDECLARE_EVENT(EVT_GLCANVAS_DOUBLE_CLICK, SimpleEvent); +#endif // !ENABLE_EXTENDED_SELECTION wxDECLARE_EVENT(EVT_GLCANVAS_RIGHT_CLICK, Vec2dEvent); wxDECLARE_EVENT(EVT_GLCANVAS_MODEL_UPDATE, SimpleEvent); wxDECLARE_EVENT(EVT_GLCANVAS_REMOVE_OBJECT, SimpleEvent); diff --git a/src/slic3r/GUI/GLToolbar.cpp b/src/slic3r/GUI/GLToolbar.cpp index 4792383688..ec203541e9 100644 --- a/src/slic3r/GUI/GLToolbar.cpp +++ b/src/slic3r/GUI/GLToolbar.cpp @@ -24,7 +24,9 @@ wxDEFINE_EVENT(EVT_GLTOOLBAR_MORE, SimpleEvent); wxDEFINE_EVENT(EVT_GLTOOLBAR_FEWER, SimpleEvent); wxDEFINE_EVENT(EVT_GLTOOLBAR_SPLIT, SimpleEvent); wxDEFINE_EVENT(EVT_GLTOOLBAR_CUT, SimpleEvent); +#if !ENABLE_EXTENDED_SELECTION wxDEFINE_EVENT(EVT_GLTOOLBAR_SETTINGS, SimpleEvent); +#endif // !ENABLE_EXTENDED_SELECTION wxDEFINE_EVENT(EVT_GLTOOLBAR_LAYERSEDITING, SimpleEvent); #if !ENABLE_EXTENDED_SELECTION wxDEFINE_EVENT(EVT_GLTOOLBAR_SELECTBYPARTS, SimpleEvent); diff --git a/src/slic3r/GUI/GLToolbar.hpp b/src/slic3r/GUI/GLToolbar.hpp index dc4d10f376..7c0f5bf84e 100644 --- a/src/slic3r/GUI/GLToolbar.hpp +++ b/src/slic3r/GUI/GLToolbar.hpp @@ -24,7 +24,9 @@ wxDECLARE_EVENT(EVT_GLTOOLBAR_MORE, SimpleEvent); wxDECLARE_EVENT(EVT_GLTOOLBAR_FEWER, SimpleEvent); wxDECLARE_EVENT(EVT_GLTOOLBAR_SPLIT, SimpleEvent); wxDECLARE_EVENT(EVT_GLTOOLBAR_CUT, SimpleEvent); +#if !ENABLE_EXTENDED_SELECTION wxDECLARE_EVENT(EVT_GLTOOLBAR_SETTINGS, SimpleEvent); +#endif // !ENABLE_EXTENDED_SELECTION wxDECLARE_EVENT(EVT_GLTOOLBAR_LAYERSEDITING, SimpleEvent); #if !ENABLE_EXTENDED_SELECTION wxDECLARE_EVENT(EVT_GLTOOLBAR_SELECTBYPARTS, SimpleEvent); diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index a01825d2b9..fd4559a35a 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -326,25 +326,6 @@ void GUI_App::CallAfter(std::function cb) callback_register.unlock(); } -wxMenuItem* GUI_App::append_menu_item( wxMenu* menu, - int id, - const wxString& string, - const wxString& description, - const std::string& icon, - std::function cb, - wxItemKind kind/* = wxITEM_NORMAL*/) -{ - if (id == wxID_ANY) - id = wxNewId(); - auto item = new wxMenuItem(menu, id, string, description, kind); - if (!icon.empty()) - item->SetBitmap(wxBitmap(Slic3r::var(icon), wxBITMAP_TYPE_PNG)); - menu->Append(item); - - menu->Bind(wxEVT_MENU, /*[cb](wxCommandEvent& event){cb; }*/cb); - return item; -} - wxMenuItem* GUI_App::append_submenu(wxMenu* menu, wxMenu* sub_menu, int id, diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 4578f4c00c..ff910ed428 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -107,14 +107,7 @@ public: // void notify(/*message*/); void update_ui_from_settings(); void CallAfter(std::function cb); - wxMenuItem* append_menu_item( wxMenu* menu, - int id, - const wxString& string, - const wxString& description, - const std::string& icon, - std::function cb, - wxItemKind kind = wxITEM_NORMAL); - wxMenuItem* append_submenu( wxMenu* menu, + wxMenuItem* append_submenu(wxMenu* menu, wxMenu* sub_menu, int id, const wxString& string, diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 505a451258..767f629fd3 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -17,6 +17,7 @@ #include "Print.hpp" #include "Polygon.hpp" #include "AppConfig.hpp" +#include "wxExtensions.hpp" #include #include "GUI_App.hpp" @@ -237,10 +238,8 @@ void MainFrame::init_menubar() // File menu wxMenu* fileMenu = new wxMenu; { - wxGetApp().append_menu_item(fileMenu, wxID_ANY, _(L("Open STL/OBJ/AMF/3MF…\tCtrl+O")), _(L("Open a model")), - "", [](wxCommandEvent&){ -// if (m_plater) m_plater->add(); - }); //'brick_add.png'); + append_menu_item(fileMenu, wxID_ANY, _(L("Open STL/OBJ/AMF/3MF…\tCtrl+O")), _(L("Open a model")), + [this](wxCommandEvent&) { if (m_plater) m_plater->add(); }, "brick_add.png"); append_menu_item(fileMenu, wxID_ANY, _(L("&Load Config…\tCtrl+L")), _(L("Load exported configuration file")), [this](wxCommandEvent&){ load_config_file(); }, "plugin_add.png"); append_menu_item(fileMenu, wxID_ANY, _(L("&Export Config…\tCtrl+E")), _(L("Export current configuration to file")), @@ -285,19 +284,16 @@ void MainFrame::init_menubar() } // Plater menu - if(m_plater) { - auto plater_menu = new wxMenu(); - append_menu_item(plater_menu, wxID_ANY, L("Export G-code..."), L("Export current plate as G-code"), + if (m_plater) { + m_plater_menu = new wxMenu(); + append_menu_item(m_plater_menu, wxID_ANY, _(L("Export G-code...")), _(L("Export current plate as G-code")), [this](wxCommandEvent&){ /*m_plater->export_gcode(); */}, "cog_go.png"); - append_menu_item(plater_menu, wxID_ANY, L("Export plate as STL..."), L("Export current plate as STL"), + append_menu_item(m_plater_menu, wxID_ANY, _(L("Export plate as STL...")), _(L("Export current plate as STL")), [this](wxCommandEvent&){ /*m_plater->export_stl(); */}, "brick_go.png"); - append_menu_item(plater_menu, wxID_ANY, L("Export plate as AMF..."), L("Export current plate as AMF"), + append_menu_item(m_plater_menu, wxID_ANY, _(L("Export plate as AMF...")), _(L("Export current plate as AMF")), [this](wxCommandEvent&){ /*m_plater->export_amf();*/ }, "brick_go.png"); - append_menu_item(plater_menu, wxID_ANY, L("Export plate as 3MF..."), L("Export current plate as 3MF"), + append_menu_item(m_plater_menu, wxID_ANY, _(L("Export plate as 3MF...")), _(L("Export current plate as 3MF")), [this](wxCommandEvent&){ /*m_plater->export_3mf(); */}, "brick_go.png"); - -// m_object_menu = m_plater->object_menu; - on_plater_selection_changed(false); } // Window menu @@ -375,7 +371,6 @@ void MainFrame::init_menubar() auto menubar = new wxMenuBar(); menubar->Append(fileMenu, L("&File")); if (m_plater_menu) menubar->Append(m_plater_menu, L("&Plater")) ; - if (m_object_menu) menubar->Append(m_object_menu, L("&Object")) ; menubar->Append(windowMenu, L("&Window")); if (m_viewMenu) menubar->Append(m_viewMenu, L("&View")); // Add additional menus from C++ @@ -385,15 +380,6 @@ void MainFrame::init_menubar() } } -// Selection of a 3D object changed on the platter. -void MainFrame::on_plater_selection_changed(const bool have_selection) -{ - if (!m_object_menu) return; - - for (auto item : m_object_menu->GetMenuItems()) - m_object_menu->Enable(item->GetId(), have_selection); -} - void MainFrame::slice_to_png(){ // m_plater->stop_background_process(); // m_plater->async_apply_config(); @@ -702,22 +688,6 @@ void MainFrame::select_view(const std::string& direction){ // m_plater->select_view(direction); } -wxMenuItem* MainFrame::append_menu_item(wxMenu* menu, - int id, - const wxString& string, - const wxString& description, - std::function cb, - const std::string& icon /*= ""*/) -{ - if (id == wxID_ANY) - id = wxNewId(); - auto item = menu->Append(id, string, description); - if (!icon.empty()) - item->SetBitmap(wxBitmap(Slic3r::var(icon), wxBITMAP_TYPE_PNG)); - menu->Bind(wxEVT_MENU, /*[cb](wxCommandEvent& event){cb; }*/cb); - return item; -} - void MainFrame::on_presets_changed(SimpleEvent &event) { auto *tab = dynamic_cast(event.GetEventObject()); diff --git a/src/slic3r/GUI/MainFrame.hpp b/src/slic3r/GUI/MainFrame.hpp index ed2646b697..1015e783c3 100644 --- a/src/slic3r/GUI/MainFrame.hpp +++ b/src/slic3r/GUI/MainFrame.hpp @@ -57,17 +57,9 @@ class MainFrame : public wxFrame AppController* m_appController { nullptr }; std::map m_options_tabs; - wxMenuItem* append_menu_item(wxMenu* menu, - int id, - const wxString& string, - const wxString& description, - std::function cb, - const std::string& icon = ""); - wxMenuItem* m_menu_item_reslice_now { nullptr }; wxMenu* m_plater_menu { nullptr }; - wxMenu* m_object_menu { nullptr }; - wxMenu* m_viewMenu { nullptr }; + wxMenu* m_viewMenu{ nullptr }; std::string get_base_name(const wxString full_name) const ; std::string get_dir_name(const wxString full_name) const ; @@ -93,7 +85,6 @@ public: bool is_loaded() const { return m_loaded; } bool is_last_input_file() const { return !m_qs_last_input_file.IsEmpty(); } - void on_plater_selection_changed(const bool have_selection); void slice_to_png(); void quick_slice(const int qs = qsUndef); void reslice_now(); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index cd0dc278d9..f6e3983d9d 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -37,6 +37,7 @@ #include "GUI_ObjectList.hpp" #include "GUI_ObjectManipulation.hpp" #include "GUI_Utils.hpp" +#include "wxExtensions.hpp" #include "MainFrame.hpp" #include "3DScene.hpp" #include "GLCanvas3D.hpp" @@ -727,6 +728,9 @@ struct Plater::priv Plater *q; MainFrame *main_frame; + // Object popup menu + wxMenu* object_menu; + // Data Slic3r::DynamicPrintConfig *config; Slic3r::Print print; @@ -751,6 +755,7 @@ struct Plater::priv static const std::regex pattern_zip_amf; priv(Plater *q, MainFrame *main_frame); + ~priv(); #if !ENABLE_EXTENDED_SELECTION std::vector collect_selections(); @@ -804,7 +809,9 @@ struct Plater::priv void on_action_add(SimpleEvent&); void on_action_split(SimpleEvent&); void on_action_cut(SimpleEvent&); +#if !ENABLE_EXTENDED_SELECTION void on_action_settings(SimpleEvent&); +#endif // !ENABLE_EXTENDED_SELECTION void on_action_layersediting(SimpleEvent&); #if !ENABLE_EXTENDED_SELECTION void on_action_selectbyparts(SimpleEvent&); @@ -824,6 +831,9 @@ struct Plater::priv void on_wipetower_moved(Vec3dEvent&); void on_enable_action_buttons(Event&); void on_update_geometry(Vec3dsEvent<2>&); + +private: + bool init_object_menu(); }; const std::regex Plater::priv::pattern_bundle("[.](amf|amf[.]xml|zip[.]amf|3mf|prusa)$", std::regex::icase); @@ -833,6 +843,7 @@ const std::regex Plater::priv::pattern_zip_amf("[.]zip[.]amf$", std::regex::icas Plater::priv::priv(Plater *q, MainFrame *main_frame) : q(q), main_frame(main_frame), + object_menu(nullptr), config(Slic3r::DynamicPrintConfig::new_from_defaults_keys({ "bed_shape", "complete_objects", "extruder_clearance_radius", "skirts", "skirt_distance", "brim_width", "variable_layer_height", "serial_port", "serial_speed", "host_type", "print_host", @@ -892,6 +903,8 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) : hsizer->Add(sidebar, 0, wxEXPAND | wxLEFT | wxRIGHT, 0); q->SetSizer(hsizer); + init_object_menu(); + // Events: // Notebook page change event @@ -903,7 +916,9 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) : // 3DScene events: canvas3D->Bind(EVT_GLCANVAS_OBJECT_SELECT, &priv::on_object_select, this); canvas3D->Bind(EVT_GLCANVAS_VIEWPORT_CHANGED, &priv::on_viewport_changed, this); - // canvas3D->Bind(EVT_GLCANVAS_DOUBLE_CLICK, [](SimpleEvent&) { }); // XXX: remove? +#if !ENABLE_EXTENDED_SELECTION + canvas3D->Bind(EVT_GLCANVAS_DOUBLE_CLICK, [](SimpleEvent&) {}); // XXX: remove? +#endif // !ENABLE_EXTENDED_SELECTION canvas3D->Bind(EVT_GLCANVAS_RIGHT_CLICK, &priv::on_right_click, this); canvas3D->Bind(EVT_GLCANVAS_MODEL_UPDATE, &priv::on_model_update, this); canvas3D->Bind(EVT_GLCANVAS_REMOVE_OBJECT, [q](SimpleEvent&) { q->remove_selected(); }); @@ -924,7 +939,9 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) : canvas3D->Bind(EVT_GLTOOLBAR_FEWER, [q](SimpleEvent&) { q->decrease(); }); canvas3D->Bind(EVT_GLTOOLBAR_SPLIT, &priv::on_action_split, this); canvas3D->Bind(EVT_GLTOOLBAR_CUT, &priv::on_action_cut, this); +#if !ENABLE_EXTENDED_SELECTION canvas3D->Bind(EVT_GLTOOLBAR_SETTINGS, &priv::on_action_settings, this); +#endif // !ENABLE_EXTENDED_SELECTION canvas3D->Bind(EVT_GLTOOLBAR_LAYERSEDITING, &priv::on_action_layersediting, this); #if !ENABLE_EXTENDED_SELECTION canvas3D->Bind(EVT_GLTOOLBAR_SELECTBYPARTS, &priv::on_action_selectbyparts, this); @@ -943,6 +960,12 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) : q->Layout(); } +Plater::priv::~priv() +{ + if (object_menu != nullptr) + delete object_menu; +} + #if !ENABLE_EXTENDED_SELECTION std::vector Plater::priv::collect_selections() { @@ -1645,14 +1668,8 @@ void Plater::priv::on_layer_editing_toggled(bool enable) void Plater::priv::on_action_add(SimpleEvent&) { - wxArrayString input_files; - wxGetApp().open_model(q, input_files); - - std::vector input_paths; - for (const auto &file : input_files) { - input_paths.push_back(file.wx_str()); - } - load_files(input_paths); + if (q != nullptr) + q->add(); } void Plater::priv::on_action_split(SimpleEvent&) @@ -1665,10 +1682,12 @@ void Plater::priv::on_action_cut(SimpleEvent&) // TODO } +#if !ENABLE_EXTENDED_SELECTION void Plater::priv::on_action_settings(SimpleEvent&) { // TODO } +#endif // !ENABLE_EXTENDED_SELECTION void Plater::priv::on_action_layersediting(SimpleEvent&) { @@ -1712,9 +1731,18 @@ void Plater::priv::on_viewport_changed(SimpleEvent& evt) preview->set_viewport_from_scene(canvas3D); } -void Plater::priv::on_right_click(Vec2dEvent&) +void Plater::priv::on_right_click(Vec2dEvent& evt) { +#if ENABLE_EXTENDED_SELECTION + int obj_idx = get_selected_object_idx(); + if (obj_idx == -1) + return; + + if ((q != nullptr) && (object_menu != nullptr)) + q->PopupMenu(object_menu, (int)evt.data.x(), (int)evt.data.y()); +#else // TODO +#endif // ENABLE_EXTENDED_SELECTION } void Plater::priv::on_model_update(SimpleEvent&) @@ -1777,6 +1805,20 @@ void Plater::priv::on_update_geometry(Vec3dsEvent<2>&) // TODO } +bool Plater::priv::init_object_menu() +{ + if (main_frame == nullptr) + return false; + + object_menu = new wxMenu(); + if (object_menu == nullptr) + return false; + + append_menu_item(object_menu, wxID_ANY, _(L("Delete…\tDel")), _(L("Remove the selected object")), + [this](wxCommandEvent&){ q->remove_selected(); }, "brick_delete.png"); + + return true; +} // Plater / Public @@ -1795,6 +1837,18 @@ Sidebar& Plater::sidebar() { return *p->sidebar; } Model& Plater::model() { return p->model; } Print& Plater::print() { return p->print; } +void Plater::add() +{ + wxArrayString input_files; + wxGetApp().open_model(this, input_files); + + std::vector input_paths; + for (const auto &file : input_files) { + input_paths.push_back(file.wx_str()); + } + load_files(input_paths); +} + void Plater::load_files(const std::vector &input_files) { p->load_files(input_files); } void Plater::update(bool force_autocenter) { p->update(force_autocenter); } diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index fba2e0dc0b..135dcfcde6 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -104,6 +104,8 @@ public: Model& model(); Print& print(); + void add(); + void load_files(const std::vector &input_files); void update(bool force_autocenter = false); diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp index be37156410..4eaffe49f9 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -10,6 +10,20 @@ #include "GUI_App.hpp" #include "GUI_ObjectList.hpp" +wxMenuItem* append_menu_item(wxMenu* menu, int id, const wxString& string, const wxString& description, + std::function cb, const std::string& icon) +{ + if (id == wxID_ANY) + id = wxNewId(); + + wxMenuItem* item = menu->Append(id, string, description); + if (!icon.empty()) + item->SetBitmap(wxBitmap(Slic3r::var(icon), wxBITMAP_TYPE_PNG)); + + menu->Bind(wxEVT_MENU, cb, id); + return item; +} + const unsigned int wxCheckListBoxComboPopup::DefaultWidth = 200; const unsigned int wxCheckListBoxComboPopup::DefaultHeight = 200; const unsigned int wxCheckListBoxComboPopup::DefaultItemHeight = 18; diff --git a/src/slic3r/GUI/wxExtensions.hpp b/src/slic3r/GUI/wxExtensions.hpp index e199a16489..07f56e643f 100644 --- a/src/slic3r/GUI/wxExtensions.hpp +++ b/src/slic3r/GUI/wxExtensions.hpp @@ -13,6 +13,9 @@ #include #include +wxMenuItem* append_menu_item(wxMenu* menu, int id, const wxString& string, const wxString& description, + std::function cb, const std::string& icon = ""); + class wxCheckListBoxComboPopup : public wxCheckListBox, public wxComboPopup { static const unsigned int DefaultWidth; From 2e274b5646c938d76a3f3e9e7813cbc6aea5c884 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Wed, 17 Oct 2018 12:59:58 +0200 Subject: [PATCH 118/186] Plater -> View Menu --- src/slic3r/GUI/GLCanvas3D.cpp | 2 +- src/slic3r/GUI/MainFrame.cpp | 32 ++++++++++++-------------------- src/slic3r/GUI/Plater.cpp | 17 +++++++++++++++++ src/slic3r/GUI/Plater.hpp | 2 ++ 4 files changed, 32 insertions(+), 21 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index f0568c5f0b..813d10f7c6 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -3204,7 +3204,7 @@ void GLCanvas3D::select_view(const std::string& direction) else if (direction == "rear") dir_vec = VIEW_REAR; - if ((dir_vec != nullptr) && !empty(volumes_bounding_box())) + if (dir_vec != nullptr) { m_camera.phi = dir_vec[0]; m_camera.set_theta(dir_vec[1]); diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 767f629fd3..67f01ad424 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -319,23 +319,14 @@ void MainFrame::init_menubar() // View menu if (m_plater) { m_viewMenu = new wxMenu(); -// \xA0 is a non-breaing space. It is entered here to spoil the automatic accelerators, - // as the simple numeric accelerators spoil all numeric data entry. - // The camera control accelerators are captured by 3DScene Perl module instead. - auto accel = [](const wxString& st1, const wxString& st2) { -// if ($^O eq "MSWin32") -// return st1 + "\t\xA0" + st2; -// else - return st1; - }; - - append_menu_item(m_viewMenu, wxID_ANY, accel(_(L("Iso")), "0"), L("Iso View"), [this](wxCommandEvent&){ select_view("iso"); }); - append_menu_item(m_viewMenu, wxID_ANY, accel(_(L("Top")), "1"), L("Top View"), [this](wxCommandEvent&){ select_view("top"); }); - append_menu_item(m_viewMenu, wxID_ANY, accel(_(L("Bottom")), "2"), L("Bottom View"),[this](wxCommandEvent&){ select_view("bottom"); }); - append_menu_item(m_viewMenu, wxID_ANY, accel(_(L("Front")), "3"), L("Front View"), [this](wxCommandEvent&){ select_view("front"); }); - append_menu_item(m_viewMenu, wxID_ANY, accel(_(L("Rear")), "4"), L("Rear View"), [this](wxCommandEvent&){ select_view("rear"); }); - append_menu_item(m_viewMenu, wxID_ANY, accel(_(L("Left")), "5"), L("Left View"), [this](wxCommandEvent&){ select_view("left"); }); - append_menu_item(m_viewMenu, wxID_ANY, accel(_(L("Right")), "6"), L("Right View"), [this](wxCommandEvent&){ select_view("right"); }); + append_menu_item(m_viewMenu, wxID_ANY, _(L("Iso\t0")), _(L("Iso View")), [this](wxCommandEvent&){ select_view("iso"); }); + m_viewMenu->AppendSeparator(); + append_menu_item(m_viewMenu, wxID_ANY, _(L("Top\t1")), _(L("Top View")), [this](wxCommandEvent&){ select_view("top"); }); + append_menu_item(m_viewMenu, wxID_ANY, _(L("Bottom\t2")), _(L("Bottom View")), [this](wxCommandEvent&){ select_view("bottom"); }); + append_menu_item(m_viewMenu, wxID_ANY, _(L("Front\t3")), _(L("Front View")), [this](wxCommandEvent&){ select_view("front"); }); + append_menu_item(m_viewMenu, wxID_ANY, _(L("Rear\t4")), _(L("Rear View")), [this](wxCommandEvent&){ select_view("rear"); }); + append_menu_item(m_viewMenu, wxID_ANY, _(L("Left\t5")), _(L("Left View")), [this](wxCommandEvent&){ select_view("left"); }); + append_menu_item(m_viewMenu, wxID_ANY, _(L("Right\t6")), _(L("Right View")), [this](wxCommandEvent&){ select_view("right"); }); } // Help menu @@ -683,9 +674,10 @@ void MainFrame::select_tab(size_t tab) const{ } // Set a camera direction, zoom to all objects. -void MainFrame::select_view(const std::string& direction){ -// if (m_plater) -// m_plater->select_view(direction); +void MainFrame::select_view(const std::string& direction) +{ + if (m_plater) + m_plater->select_view(direction); } void MainFrame::on_presets_changed(SimpleEvent &event) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index f6e3983d9d..6eb2c217eb 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -761,6 +761,7 @@ struct Plater::priv std::vector collect_selections(); #endif // !ENABLE_EXTENDED_SELECTION void update(bool force_autocenter = false); + void select_view(const std::string& direction); void update_ui_from_settings(); ProgressStatusBar* statusbar(); std::string get_config(const std::string &key) const; @@ -1002,6 +1003,19 @@ void Plater::priv::update(bool force_autocenter) // schedule_background_process(); // TODO } +void Plater::priv::select_view(const std::string& direction) +{ + int page_id = notebook->GetSelection(); + if (page_id != wxNOT_FOUND) + { + const wxString& page_text = notebook->GetPageText(page_id); + if (page_text == _(L("3D"))) + _3DScene::select_view(canvas3D, direction); + else if (page_text == _(L("Preview"))) + preview->select_view(direction); + } +} + void Plater::priv::update_ui_from_settings() { // TODO: (?) @@ -1852,6 +1866,9 @@ void Plater::add() void Plater::load_files(const std::vector &input_files) { p->load_files(input_files); } void Plater::update(bool force_autocenter) { p->update(force_autocenter); } + +void Plater::select_view(const std::string& direction) { p->select_view(direction); } + void Plater::remove(size_t obj_idx) { p->remove(obj_idx); } void Plater::remove_selected() diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 135dcfcde6..eeb3123cd3 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -109,6 +109,8 @@ public: void load_files(const std::vector &input_files); void update(bool force_autocenter = false); + void select_view(const std::string& direction); + void remove(size_t obj_idx); void remove_selected(); void increase(size_t num = 1); From d4371b60897acc4d95a5b24d8a1a379338bb4375 Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Wed, 17 Oct 2018 14:01:10 +0200 Subject: [PATCH 119/186] Refactor window position & size persistence in a way that is hopefully robust wrt. platform quirks --- src/CMakeLists.txt | 6 +-- src/slic3r/GUI/GUI_App.cpp | 57 ++++++++++++---------- src/slic3r/GUI/GUI_App.hpp | 6 ++- src/slic3r/GUI/GUI_Utils.cpp | 95 ++++++++++++++++++++++++++++++------ src/slic3r/GUI/GUI_Utils.hpp | 25 ++++++++++ src/slic3r/GUI/MainFrame.cpp | 15 ++++-- 6 files changed, 153 insertions(+), 51 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3c295ec5a0..b2b3f4cf16 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -122,14 +122,14 @@ if (MSVC) add_custom_target("resources_symlink_${CONF}" ALL DEPENDS slic3r COMMAND if exist "${WIN_CONF_OUTPUT_DIR}" "(" - if not exist "${WIN_RESOURCES_SYMLINK}" "(" - mklink /J "${WIN_RESOURCES_SYMLINK}" "${SLIC3R_RESOURCES_DIR_WIN}" + if not exist "${WIN_RESOURCES_SYMLINK}" "(" + mklink /J "${WIN_RESOURCES_SYMLINK}" "${SLIC3R_RESOURCES_DIR_WIN}" ")" ")" VERBATIM ) endforeach () - else () + else () file(TO_NATIVE_PATH "${CMAKE_CURRENT_BINARY_DIR}" OUTPUT_DIR) add_custom_target(resources_symlink ALL DEPENDS slic3r diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index fd4559a35a..e58142f264 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -16,6 +16,7 @@ #include "Utils.hpp" #include "GUI.hpp" +#include "GUI_Utils.hpp" #include "AppConfig.hpp" #include "PresetBundle.hpp" #include "3DScene.hpp" @@ -344,41 +345,43 @@ wxMenuItem* GUI_App::append_submenu(wxMenu* menu, return item; } -void GUI_App::save_window_pos(wxTopLevelWindow* window, const std::string& name){ - int x, y; - window->GetScreenPosition(&x, &y); - app_config->set(name + "_pos", wxString::Format("%d,%d", x, y).ToStdString()); - - window->GetSize(&x, &y); - app_config->set(name + "_size", wxString::Format("%d,%d", x, y).ToStdString()); - - app_config->set(name + "_maximized", window->IsMaximized() ? "1" : "0"); +void GUI_App::window_pos_save(wxTopLevelWindow* window, const std::string &name) +{ + if (name.empty()) { return; } + const auto config_key = (boost::format("window_%1%") % name).str(); + WindowMetrics metrics = WindowMetrics::from_window(window); + app_config->set(config_key, metrics.serialize()); app_config->save(); } -void GUI_App::restore_window_pos(wxTopLevelWindow* window, const std::string& name) +void GUI_App::window_pos_restore(wxTopLevelWindow* window, const std::string &name) { - if (!app_config->has(name + "_pos")) - return; + if (name.empty()) { return; } + const auto config_key = (boost::format("window_%1%") % name).str(); - std::string str = app_config->get(name + "_size"); - std::vector values; - boost::split(values, str, boost::is_any_of(",")); - wxSize size = wxSize(atoi(values[0].c_str()), atoi(values[1].c_str())); - window->SetSize(size); + if (! app_config->has(config_key)) { return; } - auto display = (new wxDisplay())->GetClientArea(); - str = app_config->get(name + "_pos"); - values.resize(0); - boost::split(values, str, boost::is_any_of(",")); - wxPoint pos = wxPoint(atoi(values[0].c_str()), atoi(values[1].c_str())); - if (pos.x + 0.5*size.GetWidth() < display.GetRight() && - pos.y + 0.5*size.GetHeight() < display.GetBottom()) - window->Move(pos); + auto metrics = WindowMetrics::deserialize(app_config->get(config_key)); + if (! metrics) { return; } - if (app_config->get(name + "_maximized") == "1") - window->Maximize(); + window->SetSize(metrics->get_rect()); + window->Maximize(metrics->get_maximized()); +} + +void GUI_App::window_pos_sanitize(wxTopLevelWindow* window) +{ + const auto display_idx = wxDisplay::GetFromWindow(window); + if (display_idx == wxNOT_FOUND) { return; } + + const auto display = wxDisplay(display_idx).GetClientArea(); + + auto metrics = WindowMetrics::from_window(window); + + metrics.sanitize_for_display(display); + if (window->GetScreenRect() != metrics.get_rect()) { + window->SetSize(metrics.get_rect()); + } } // select language from the list of installed languages diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index ff910ed428..e1e48e9b9f 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -113,8 +113,10 @@ public: const wxString& string, const wxString& description, const std::string& icon); - void save_window_pos(wxTopLevelWindow* window, const std::string& name); - void restore_window_pos(wxTopLevelWindow* window, const std::string& name); + + void window_pos_save(wxTopLevelWindow* window, const std::string &name); + void window_pos_restore(wxTopLevelWindow* window, const std::string &name); + void window_pos_sanitize(wxTopLevelWindow* window); bool select_language(wxArrayString & names, wxArrayLong & identifiers); bool load_language(); diff --git a/src/slic3r/GUI/GUI_Utils.cpp b/src/slic3r/GUI/GUI_Utils.cpp index b8cd60944d..8fff2d2081 100644 --- a/src/slic3r/GUI/GUI_Utils.cpp +++ b/src/slic3r/GUI/GUI_Utils.cpp @@ -1,16 +1,23 @@ #include "GUI_Utils.hpp" +#include +#include +#include + +#include #include #include #include +#include "libslic3r/Config.hpp" + namespace Slic3r { namespace GUI { CheckboxFileDialog::CheckboxFileDialog(wxWindow *parent, - const wxString &checkbox_label, + const wxString &checkbox_label, bool checkbox_value, const wxString &message, const wxString &default_dir, @@ -24,31 +31,87 @@ CheckboxFileDialog::CheckboxFileDialog(wxWindow *parent, : wxFileDialog(parent, message, default_dir, default_file, wildcard, style, pos, size, name) , cbox(nullptr) { - if (checkbox_label.IsEmpty()) { - return; - } + if (checkbox_label.IsEmpty()) { + return; + } - extra_control_creator = [this, checkbox_label](wxWindow *parent) -> wxWindow* { - wxPanel* panel = new wxPanel(parent, -1); - wxSizer* sizer = new wxBoxSizer(wxHORIZONTAL); - this->cbox = new wxCheckBox(panel, wxID_HIGHEST + 1, checkbox_label); - this->cbox->SetValue(true); - sizer->AddSpacer(5); - sizer->Add(this->cbox, 0, wxEXPAND | wxALL | wxALIGN_CENTER_VERTICAL, 5); - panel->SetSizer(sizer); - sizer->SetSizeHints(panel); + extra_control_creator = [this, checkbox_label](wxWindow *parent) -> wxWindow* { + wxPanel* panel = new wxPanel(parent, -1); + wxSizer* sizer = new wxBoxSizer(wxHORIZONTAL); + this->cbox = new wxCheckBox(panel, wxID_HIGHEST + 1, checkbox_label); + this->cbox->SetValue(true); + sizer->AddSpacer(5); + sizer->Add(this->cbox, 0, wxEXPAND | wxALL | wxALIGN_CENTER_VERTICAL, 5); + panel->SetSizer(sizer); + sizer->SetSizeHints(panel); - return panel; - }; + return panel; + }; SetExtraControlCreator(*extra_control_creator.target()); } bool CheckboxFileDialog::get_checkbox_value() const { - return this->cbox != nullptr ? cbox->IsChecked() : false; + return this->cbox != nullptr ? cbox->IsChecked() : false; } + +WindowMetrics WindowMetrics::from_window(wxTopLevelWindow *window) +{ + WindowMetrics res; + res.rect = window->GetScreenRect(); + res.maximized = window->IsMaximized(); + return res; +} + +boost::optional WindowMetrics::deserialize(const std::string &str) +{ + std::vector metrics_str; + metrics_str.reserve(5); + + if (!unescape_strings_cstyle(str, metrics_str) || metrics_str.size() != 5) { + return boost::none; + } + + int metrics[5]; + try { + for (size_t i = 0; i < 5; i++) { + metrics[i] = boost::lexical_cast(metrics_str[i]); + } + } catch(const boost::bad_lexical_cast &) { + return boost::none; + } + + if ((metrics[4] & ~1) != 0) { // Checks if the maximized flag is 1 or 0 + metrics[4] = 0; + } + + WindowMetrics res; + res.rect = wxRect(metrics[0], metrics[1], metrics[2], metrics[3]); + res.maximized = metrics[4]; + + return res; +} + +void WindowMetrics::sanitize_for_display(const wxRect &screen_rect) +{ + rect = rect.Intersect(screen_rect); +} + +std::string WindowMetrics::serialize() +{ + return (boost::format("%1%; %2%; %3%; %4%; %5%") + % rect.GetX() + % rect.GetY() + % rect.GetWidth() + % rect.GetHeight() + % static_cast(maximized) + ).str(); +} + + + } } diff --git a/src/slic3r/GUI/GUI_Utils.hpp b/src/slic3r/GUI/GUI_Utils.hpp index bf2ee961f1..1c776df81e 100644 --- a/src/slic3r/GUI/GUI_Utils.hpp +++ b/src/slic3r/GUI/GUI_Utils.hpp @@ -2,10 +2,16 @@ #define slic3r_GUI_Utils_hpp_ #include +#include + +#include #include +#include class wxCheckBox; +class wxTopLevelWindow; +class wxRect; namespace Slic3r { @@ -36,6 +42,25 @@ private: }; +class WindowMetrics +{ +private: + wxRect rect; + bool maximized; + + WindowMetrics() : maximized(false) {} +public: + static WindowMetrics from_window(wxTopLevelWindow *window); + static boost::optional deserialize(const std::string &str); + + wxRect get_rect() const { return rect; } + bool get_maximized() const { return maximized; } + + void sanitize_for_display(const wxRect &screen_rect); + std::string serialize(); +}; + + }} #endif diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 67f01ad424..84b763a34e 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -78,8 +78,6 @@ wxFrame(NULL, wxID_ANY, SLIC3R_BUILD, wxDefaultPosition, wxDefaultSize, wxDEFAUL Fit(); SetMinSize(wxSize(760, 490)); SetSize(GetMinSize()); - wxGetApp().restore_window_pos(this, "main_frame"); - Show(); Layout(); // declare events @@ -89,7 +87,7 @@ wxFrame(NULL, wxID_ANY, SLIC3R_BUILD, wxDefaultPosition, wxDefaultSize, wxDEFAUL return; } // save window size - wxGetApp().save_window_pos(this, "main_frame"); + wxGetApp().window_pos_save(this, "mainframe"); // 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(); @@ -101,6 +99,17 @@ wxFrame(NULL, wxID_ANY, SLIC3R_BUILD, wxDefaultPosition, wxDefaultSize, wxDEFAUL event.Skip(); }); + // NB: Restoring the window position is done in a two-phase manner here, + // first the saved position is restored as-is and validation is done after the window is shown + // and initial round of events is complete, because on some platforms that is the only way + // to get an accurate window position & size. + wxGetApp().window_pos_restore(this, "mainframe"); + Bind(wxEVT_SHOW, [this](wxShowEvent&) { + CallAfter([this]() { + wxGetApp().window_pos_sanitize(this); + }); + }); + update_ui_from_settings(); return; } From 23123cac2e0f5528f584502e699d3896bba05c20 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Wed, 17 Oct 2018 14:26:13 +0200 Subject: [PATCH 120/186] Increase and decrease command in object's context menu --- src/slic3r/GUI/Plater.cpp | 41 +++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 6eb2c217eb..9fe5055b77 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -729,7 +729,7 @@ struct Plater::priv MainFrame *main_frame; // Object popup menu - wxMenu* object_menu; + wxMenu object_menu; // Data Slic3r::DynamicPrintConfig *config; @@ -755,7 +755,6 @@ struct Plater::priv static const std::regex pattern_zip_amf; priv(Plater *q, MainFrame *main_frame); - ~priv(); #if !ENABLE_EXTENDED_SELECTION std::vector collect_selections(); @@ -844,7 +843,6 @@ const std::regex Plater::priv::pattern_zip_amf("[.]zip[.]amf$", std::regex::icas Plater::priv::priv(Plater *q, MainFrame *main_frame) : q(q), main_frame(main_frame), - object_menu(nullptr), config(Slic3r::DynamicPrintConfig::new_from_defaults_keys({ "bed_shape", "complete_objects", "extruder_clearance_radius", "skirts", "skirt_distance", "brim_width", "variable_layer_height", "serial_port", "serial_speed", "host_type", "print_host", @@ -961,12 +959,6 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) : q->Layout(); } -Plater::priv::~priv() -{ - if (object_menu != nullptr) - delete object_menu; -} - #if !ENABLE_EXTENDED_SELECTION std::vector Plater::priv::collect_selections() { @@ -1752,8 +1744,8 @@ void Plater::priv::on_right_click(Vec2dEvent& evt) if (obj_idx == -1) return; - if ((q != nullptr) && (object_menu != nullptr)) - q->PopupMenu(object_menu, (int)evt.data.x(), (int)evt.data.y()); + if (q != nullptr) + q->PopupMenu(&object_menu, (int)evt.data.x(), (int)evt.data.y()); #else // TODO #endif // ENABLE_EXTENDED_SELECTION @@ -1821,15 +1813,26 @@ void Plater::priv::on_update_geometry(Vec3dsEvent<2>&) bool Plater::priv::init_object_menu() { - if (main_frame == nullptr) - return false; - - object_menu = new wxMenu(); - if (object_menu == nullptr) - return false; - - append_menu_item(object_menu, wxID_ANY, _(L("Delete…\tDel")), _(L("Remove the selected object")), + append_menu_item(&object_menu, wxID_ANY, _(L("Delete\tDel")), _(L("Remove the selected object")), [this](wxCommandEvent&){ q->remove_selected(); }, "brick_delete.png"); + append_menu_item(&object_menu, wxID_ANY, _(L("Increase copies\t+")), _(L("Place one more copy of the selected object")), + [this](wxCommandEvent&){ q->increase(); }, "add.png"); + wxMenuItem* item_decrease = append_menu_item(&object_menu, wxID_ANY, _(L("Decrease copies\t-")), _(L("Remove one copy of the selected object")), + [this](wxCommandEvent&){ q->decrease(); }, "delete.png"); + + // ui updates needs to be binded to the parent panel + if (q != nullptr) + { + q->Bind(wxEVT_UPDATE_UI, + [this](wxUpdateUIEvent& evt) + { +#if ENABLE_EXTENDED_SELECTION + int obj_idx = get_selected_object_idx(); + evt.Enable((obj_idx != -1) && (model.objects[obj_idx]->instances.size() > 1)); +#endif // ENABLE_EXTENDED_SELECTION + }, + item_decrease->GetId()); + } return true; } From 593eabd7c765e8f025ba15acffd0d51e2f2b749a Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Wed, 17 Oct 2018 15:22:45 +0200 Subject: [PATCH 121/186] Fix build --- src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b2b3f4cf16..330134c3bc 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -130,7 +130,7 @@ if (MSVC) ) endforeach () else () - file(TO_NATIVE_PATH "${CMAKE_CURRENT_BINARY_DIR}" OUTPUT_DIR) + file(TO_NATIVE_PATH "${CMAKE_CURRENT_BINARY_DIR}/resources" WIN_RESOURCES_SYMLINK) add_custom_target(resources_symlink ALL DEPENDS slic3r COMMAND if not exist "${WIN_RESOURCES_SYMLINK}" "(" mklink /J "${WIN_RESOURCES_SYMLINK}" "${SLIC3R_RESOURCES_DIR_WIN}" ")" From 143c23c54a971aa3ade1e13ea4f487d98be61dee Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Thu, 18 Oct 2018 08:51:06 +0200 Subject: [PATCH 122/186] New selection -> Force volume selection when right clicking to get the object context menu --- src/slic3r/GUI/GLCanvas3D.cpp | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 813d10f7c6..e8c79b1766 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -3949,7 +3949,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) #endif // ENABLE_EXTENDED_SELECTION { #if ENABLE_EXTENDED_SELECTION - if (m_hover_volume_id != -1) + if (evt.LeftDown() && (m_hover_volume_id != -1)) { if (evt.ControlDown()) m_selection.remove(m_hover_volume_id); @@ -4043,13 +4043,24 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) render(); if (m_hover_volume_id != -1) { - // if right clicking on volume, propagate event through callback (shows context menu) #if ENABLE_EXTENDED_SELECTION - if (m_volumes.volumes[m_hover_volume_id]->hover) -#else - if (m_volumes.volumes[volume_idx]->hover) -#endif // ENABLE_EXTENDED_SELECTION + // if right clicking on volume, propagate event through callback (shows context menu) + if (m_volumes.volumes[m_hover_volume_id]->hover && !m_volumes.volumes[m_hover_volume_id]->is_wipe_tower) + { + // forces the selection of the volume + m_selection.add(m_hover_volume_id); + m_gizmos.update_on_off_state(m_selection); + update_gizmos_data(); + wxGetApp().obj_manipul()->update_settings_value(m_selection); + // forces a frame render to update the view before the context menu is shown + render(); post_event(Vec2dEvent(EVT_GLCANVAS_RIGHT_CLICK, pos.cast())); + } +#else + // if right clicking on volume, propagate event through callback (shows context menu) + if (m_volumes.volumes[volume_idx]->hover) + post_event(Vec2dEvent(EVT_GLCANVAS_RIGHT_CLICK, pos.cast())); +#endif // ENABLE_EXTENDED_SELECTION } } } From 82ec5bf22e56006a3dc4b8a169cefbb06b201bc4 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Thu, 18 Oct 2018 09:27:37 +0200 Subject: [PATCH 123/186] New selection -> Unified methods to update menu items --- src/slic3r/GUI/Plater.cpp | 108 ++++++++++++++++++++++++++------------ 1 file changed, 75 insertions(+), 33 deletions(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 9fe5055b77..c58f02f838 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -834,6 +834,15 @@ struct Plater::priv private: bool init_object_menu(); + +#if ENABLE_EXTENDED_SELECTION + bool can_delete_object() const; + bool can_increase_instances() const; + bool can_decrease_instances() const; + bool can_split_object() const; + bool can_cut_object() const; + bool layers_height_allowed() const; +#endif // ENABLE_EXTENDED_SELECTION }; const std::regex Plater::priv::pattern_bundle("[.](amf|amf[.]xml|zip[.]amf|3mf|prusa)$", std::regex::icase); @@ -1322,31 +1331,30 @@ optional Plater::priv::selected_object() const void Plater::priv::selection_changed() { +#if !ENABLE_EXTENDED_SELECTION + const auto obj_idx = selected_object(); + const bool have_sel = !!obj_idx; +#endif // !ENABLE_EXTENDED_SELECTION + +#if ENABLE_EXTENDED_SELECTION + _3DScene::enable_toolbar_item(canvas3D, "delete", can_delete_object()); + _3DScene::enable_toolbar_item(canvas3D, "more", can_increase_instances()); + _3DScene::enable_toolbar_item(canvas3D, "fewer", can_decrease_instances()); + _3DScene::enable_toolbar_item(canvas3D, "split", can_split_object()); + _3DScene::enable_toolbar_item(canvas3D, "cut", can_cut_object()); + _3DScene::enable_toolbar_item(canvas3D, "layersediting", layers_height_allowed()); +#else + _3DScene::enable_toolbar_item(canvas3D, "fewer", have_sel); + _3DScene::enable_toolbar_item(canvas3D, "split", have_sel); + _3DScene::enable_toolbar_item(canvas3D, "cut", have_sel); + _3DScene::enable_toolbar_item(canvas3D, "settings", have_sel); + _3DScene::enable_toolbar_item(canvas3D, "layersediting", layers_height_allowed); +#endif // ENABLE_EXTENDED_SELECTION + #if ENABLE_EXTENDED_SELECTION int obj_idx = get_selected_object_idx(); bool have_sel = (obj_idx != -1); #else - const auto obj_idx = selected_object(); - const bool have_sel = !!obj_idx; -#endif // ENABLE_EXTENDED_SELECTION - const bool layers_height_allowed = config->opt("variable_layer_height")->value; - - wxWindowUpdateLocker freeze_guard(sidebar); - - _3DScene::enable_toolbar_item(canvas3D, "delete", have_sel); - _3DScene::enable_toolbar_item(canvas3D, "more", have_sel); -#if ENABLE_EXTENDED_SELECTION - _3DScene::enable_toolbar_item(canvas3D, "fewer", have_sel && (model.objects[obj_idx]->instances.size() > 1)); -#else - _3DScene::enable_toolbar_item(canvas3D, "fewer", have_sel); -#endif // ENABLE_EXTENDED_SELECTION - _3DScene::enable_toolbar_item(canvas3D, "split", have_sel); - _3DScene::enable_toolbar_item(canvas3D, "cut", have_sel); - _3DScene::enable_toolbar_item(canvas3D, "settings", have_sel); - - _3DScene::enable_toolbar_item(canvas3D, "layersediting", layers_height_allowed); - -#if !ENABLE_EXTENDED_SELECTION bool can_select_by_parts = false; if (have_sel) { @@ -1364,8 +1372,9 @@ void Plater::priv::selection_changed() _3DScene::enable_toolbar_item(canvas3D, "selectbyparts", false); _3DScene::set_select_by(canvas3D, "object"); } -#endif // !ENABLE_EXTENDED_SELECTION +#endif // ENABLE_EXTENDED_SELECTION + wxWindowUpdateLocker freeze_guard(sidebar); if (have_sel) { #if ENABLE_EXTENDED_SELECTION const ModelObject* model_object = model.objects[obj_idx]; @@ -1813,30 +1822,63 @@ void Plater::priv::on_update_geometry(Vec3dsEvent<2>&) bool Plater::priv::init_object_menu() { - append_menu_item(&object_menu, wxID_ANY, _(L("Delete\tDel")), _(L("Remove the selected object")), + wxMenuItem* item_delete = append_menu_item(&object_menu, wxID_ANY, _(L("Delete\tDel")), _(L("Remove the selected object")), [this](wxCommandEvent&){ q->remove_selected(); }, "brick_delete.png"); - append_menu_item(&object_menu, wxID_ANY, _(L("Increase copies\t+")), _(L("Place one more copy of the selected object")), + wxMenuItem* item_increase = append_menu_item(&object_menu, wxID_ANY, _(L("Increase copies\t+")), _(L("Place one more copy of the selected object")), [this](wxCommandEvent&){ q->increase(); }, "add.png"); wxMenuItem* item_decrease = append_menu_item(&object_menu, wxID_ANY, _(L("Decrease copies\t-")), _(L("Remove one copy of the selected object")), [this](wxCommandEvent&){ q->decrease(); }, "delete.png"); +#if ENABLE_EXTENDED_SELECTION // ui updates needs to be binded to the parent panel if (q != nullptr) { - q->Bind(wxEVT_UPDATE_UI, - [this](wxUpdateUIEvent& evt) - { -#if ENABLE_EXTENDED_SELECTION - int obj_idx = get_selected_object_idx(); - evt.Enable((obj_idx != -1) && (model.objects[obj_idx]->instances.size() > 1)); -#endif // ENABLE_EXTENDED_SELECTION - }, - item_decrease->GetId()); + q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_delete_object()); }, item_delete->GetId()); + q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_increase_instances()); }, item_increase->GetId()); + q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_decrease_instances()); }, item_decrease->GetId()); } +#endif // ENABLE_EXTENDED_SELECTION return true; } +#if ENABLE_EXTENDED_SELECTION +bool Plater::priv::can_delete_object() const +{ + int obj_idx = get_selected_object_idx(); + return (0 <= obj_idx) && (obj_idx < (int)model.objects.size()); +} + +bool Plater::priv::can_increase_instances() const +{ + int obj_idx = get_selected_object_idx(); + return (0 <= obj_idx) && (obj_idx < (int)model.objects.size()); +} + +bool Plater::priv::can_decrease_instances() const +{ + int obj_idx = get_selected_object_idx(); + return (0 <= obj_idx) && (obj_idx < (int)model.objects.size()) && (model.objects[obj_idx]->instances.size() > 1); +} + +bool Plater::priv::can_split_object() const +{ + int obj_idx = get_selected_object_idx(); + return (0 <= obj_idx) && (obj_idx < (int)model.objects.size()); +} + +bool Plater::priv::can_cut_object() const +{ + int obj_idx = get_selected_object_idx(); + return (0 <= obj_idx) && (obj_idx < (int)model.objects.size()); +} + +bool Plater::priv::layers_height_allowed() const +{ + return config->opt_bool("variable_layer_height") && _3DScene::is_layers_editing_allowed(canvas3D); +} +#endif // ENABLE_EXTENDED_SELECTION + // Plater / Public Plater::Plater(wxWindow *parent, MainFrame *main_frame) From e223120e7e88658ba5e13f21d5643507eeda9910 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Thu, 18 Oct 2018 10:40:26 +0200 Subject: [PATCH 124/186] Added instances to ObjectList --- src/slic3r/GUI/GUI_ObjectList.cpp | 49 +++++--- src/slic3r/GUI/GUI_ObjectList.hpp | 4 + src/slic3r/GUI/MainFrame.hpp | 10 +- src/slic3r/GUI/Plater.cpp | 2 + src/slic3r/GUI/wxExtensions.cpp | 184 +++++++++++++++++++++++++++--- src/slic3r/GUI/wxExtensions.hpp | 33 ++++-- 6 files changed, 238 insertions(+), 44 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 14773b593b..5a20756cef 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -283,7 +283,7 @@ void ObjectList::show_context_menu() const auto item = GetSelection(); if (item) { - if (m_objects_model->IsSettingsItem(item)) + if (!(m_objects_model->GetItemType(item) & (itObject | itVolume))) return; const auto menu = m_objects_model->GetParent(item) == wxDataViewItem(0) ? create_add_part_popupmenu() : @@ -672,7 +672,7 @@ void ObjectList::load_subobject(bool is_modifier /*= false*/, bool is_lambda/* = parts_changed(obj_idx); for (int i = 0; i < part_names.size(); ++i) { - const wxDataViewItem sel_item = m_objects_model->AddChild(item, part_names.Item(i), + const wxDataViewItem sel_item = m_objects_model->AddVolumeChild(item, part_names.Item(i), is_modifier ? m_bmp_modifiermesh : m_bmp_solidmesh); if (i == part_names.size() - 1) @@ -822,7 +822,7 @@ void ObjectList::load_lambda(const std::string& type_name) m_parts_changed = true; parts_changed(m_selected_object_id); - select_item(m_objects_model->AddChild(GetSelection(), + select_item(m_objects_model->AddVolumeChild(GetSelection(), name, m_bmp_modifiermesh)); #ifndef __WXOSX__ //#ifdef __WXMSW__ // #ys_FIXME selection_changed(); @@ -896,14 +896,19 @@ bool ObjectList::del_subobject_from_object(const int obj_idx, const int idx, con if (vol->is_model_part()) ++solid_cnt; if (volume->is_model_part() && solid_cnt == 1) { - Slic3r::GUI::show_error(nullptr, _(L("You can't delete the last solid part from this object."))); + Slic3r::GUI::show_error(nullptr, _(L("You can't delete the last solid part from object."))); return false; } (*m_objects)[obj_idx]->delete_volume(idx); } - else if (type == itInstance) + else if (type == itInstance) { + if ((*m_objects)[obj_idx]->instances.size() == 1) { + Slic3r::GUI::show_error(nullptr, _(L("You can't delete the last intance from object."))); + return false; + } (*m_objects)[obj_idx]->delete_instance(idx); + } else return false; @@ -934,7 +939,7 @@ void ObjectList::split(const bool split_part) m_objects_model->DeleteChildren(parent); for (auto id = 0; id < model_object->volumes.size(); id++) - m_objects_model->AddChild(parent, model_object->volumes[id]->name, + m_objects_model->AddVolumeChild(parent, model_object->volumes[id]->name, model_object->volumes[id]->is_modifier() ? m_bmp_modifiermesh : m_bmp_solidmesh, model_object->volumes[id]->config.has("extruder") ? model_object->volumes[id]->config.option("extruder")->value : 0, @@ -944,7 +949,7 @@ void ObjectList::split(const bool split_part) } else { for (auto id = 0; id < model_object->volumes.size(); id++) - m_objects_model->AddChild(item, model_object->volumes[id]->name, + m_objects_model->AddVolumeChild(item, model_object->volumes[id]->name, m_bmp_solidmesh, model_object->volumes[id]->config.has("extruder") ? model_object->volumes[id]->config.option("extruder")->value : 0, @@ -1034,7 +1039,7 @@ void ObjectList::part_selection_changed() m_config = &(*m_objects)[obj_idx]->volumes[volume_id]->config; } } - else { + else if (m_objects_model->GetItemType(item) == itVolume){ og_name = _(L("Part manipulation")); is_part = true; const auto volume_id = m_objects_model->GetVolumeIdByItem(item); @@ -1088,7 +1093,7 @@ void ObjectList::add_object_to_list(size_t obj_idx) if (model_object->volumes.size() > 1) { for (auto id = 0; id < model_object->volumes.size(); id++) - m_objects_model->AddChild(item, + m_objects_model->AddVolumeChild(item, model_object->volumes[id]->name, m_bmp_solidmesh, model_object->volumes[id]->config.option("extruder")->value, @@ -1128,6 +1133,16 @@ void ObjectList::delete_all_objects_from_list() part_selection_changed(); } +void ObjectList::increase_object_instances(const size_t obj_idx, const size_t num) +{ + select_item(m_objects_model->AddInstanceChild(m_objects_model->GetItemById(obj_idx), num)); +} + +void ObjectList::decrease_object_instances(const size_t obj_idx, const size_t num) +{ + select_item(m_objects_model->DeleteLastInstance(m_objects_model->GetItemById(obj_idx), num)); +} + void ObjectList::set_object_count(int idx, int count) { m_objects_model->SetValue(wxString::Format("%d", count), idx, 1); @@ -1231,15 +1246,21 @@ void ObjectList::update_selections_on_canvas() return; } - auto parent = m_objects_model->GetParent(item); - const int obj_idx = m_objects_model->GetIdByItem(parent); - const int vol_idx = m_objects_model->GetVolumeIdByItem(item); - selection.add_volume(obj_idx, vol_idx, as_single_selection); + if (m_objects_model->GetItemType(item) == itVolume) { + const int obj_idx = m_objects_model->GetIdByItem(m_objects_model->GetParent(item)); + const int vol_idx = m_objects_model->GetVolumeIdByItem(item); + selection.add_volume(obj_idx, vol_idx, as_single_selection); + } + else if (m_objects_model->GetItemType(item) == itInstance) { + const int obj_idx = m_objects_model->GetIdByItem(m_objects_model->GetTopParent(item)); + const int inst_idx = m_objects_model->GetInstanceIdByItem(item); + selection.add_instance(obj_idx, inst_idx, as_single_selection); + } }; if (sel_cnt == 1) { wxDataViewItem item = GetSelection(); - if (m_objects_model->IsSettingsItem(item)) + if (m_objects_model->GetItemType(item) & (itSettings|itInstanceRoot)) add_to_selection(m_objects_model->GetParent(item), selection, true); else add_to_selection(item, selection, true); diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index 418e1e8779..2325734bd7 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -112,6 +112,10 @@ public: void delete_volume_from_list(const size_t obj_idx, const size_t vol_idx); // Delete all objects from the list void delete_all_objects_from_list(); + // Increase instances count + void increase_object_instances(const size_t obj_idx, const size_t num); + // Decrease instances count + void decrease_object_instances(const size_t obj_idx, const size_t num); // Set count of object on c++ side void set_object_count(int idx, int count); diff --git a/src/slic3r/GUI/MainFrame.hpp b/src/slic3r/GUI/MainFrame.hpp index ed2646b697..f298dc034e 100644 --- a/src/slic3r/GUI/MainFrame.hpp +++ b/src/slic3r/GUI/MainFrame.hpp @@ -30,11 +30,11 @@ class Tab; enum QuickSlice { - qsUndef, - qsReslice, - qsSaveAs, - qsExportSVG, - qsExportPNG + qsUndef = 0, + qsReslice = 1, + qsSaveAs = 2, + qsExportSVG = 4, + qsExportPNG = 8 }; struct PresetTab { diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 9f0cdc89b8..7ef58d8bbc 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1747,6 +1747,7 @@ void Plater::increase(size_t num) } sidebar().obj_list()->set_object_count(*obj_idx, model_object->instances.size()); + sidebar().obj_list()->increase_object_instances(*obj_idx, num); if (p->get_config("autocenter") == "1") { p->arrange(); @@ -1771,6 +1772,7 @@ void Plater::decrease(size_t num) p->print.get_object(*obj_idx)->delete_last_copy(); } sidebar().obj_list()->set_object_count(*obj_idx, model_object->instances.size()); + sidebar().obj_list()->decrease_object_instances(*obj_idx, num); } else { remove(*obj_idx); } diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp index 4b57540c2e..cd5f339e0b 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -429,7 +429,7 @@ wxDataViewItem PrusaObjectDataViewModel::Add(const wxString &name, const int ins return child; } -wxDataViewItem PrusaObjectDataViewModel::AddChild( const wxDataViewItem &parent_item, +wxDataViewItem PrusaObjectDataViewModel::AddVolumeChild(const wxDataViewItem &parent_item, const wxString &name, const wxBitmap& icon, const int extruder/* = 0*/, @@ -440,8 +440,7 @@ wxDataViewItem PrusaObjectDataViewModel::AddChild( const wxDataViewItem &parent_ const wxString extruder_str = extruder == 0 ? "default" : wxString::Format("%d", extruder); - if (create_frst_child && (root->GetChildren().Count() == 0 || - (root->GetChildren().Count() == 1 && root->GetNthChild(0)->m_type == itSettings))) + if (create_frst_child && root->m_volumes_cnt == 0) { const auto icon_solid_mesh = wxIcon(Slic3r::GUI::from_u8(Slic3r::var("object.png")), wxBITMAP_TYPE_PNG); const auto node = new PrusaObjectDataViewModelNode(root, root->m_name, icon_solid_mesh, extruder_str, 0); @@ -449,16 +448,17 @@ wxDataViewItem PrusaObjectDataViewModel::AddChild( const wxDataViewItem &parent_ // notify control const wxDataViewItem child((void*)node); ItemAdded(parent_item, child); + + root->m_volumes_cnt++; } - const auto volume_id = root->GetChildCount() > 0 && root->GetNthChild(0)->m_type == itSettings ? - root->GetChildCount() - 1 : root->GetChildCount(); - - const auto node = new PrusaObjectDataViewModelNode(root, name, icon, extruder_str, volume_id); + const auto node = new PrusaObjectDataViewModelNode(root, name, icon, extruder_str, root->m_volumes_cnt); root->Append(node); // notify control const wxDataViewItem child((void*)node); - ItemAdded(parent_item, child); + ItemAdded(parent_item, child); + root->m_volumes_cnt++; + return child; } @@ -467,7 +467,7 @@ wxDataViewItem PrusaObjectDataViewModel::AddSettingsChild(const wxDataViewItem & PrusaObjectDataViewModelNode *root = (PrusaObjectDataViewModelNode*)parent_item.GetID(); if (!root) return wxDataViewItem(0); - const auto node = new PrusaObjectDataViewModelNode(root); + const auto node = new PrusaObjectDataViewModelNode(root, itSettings); root->Insert(node, 0); // notify control const wxDataViewItem child((void*)node); @@ -475,6 +475,55 @@ wxDataViewItem PrusaObjectDataViewModel::AddSettingsChild(const wxDataViewItem & return child; } +int get_istances_root_idx(PrusaObjectDataViewModelNode *parent_node) +{ + int inst_root_id = -1; + int stop_search_i = parent_node->GetChildCount(); + if (stop_search_i > 2) stop_search_i = 2; + for (int i = 0; i < stop_search_i; ++i) + if (parent_node->GetNthChild(i)->m_type & itInstanceRoot) { + inst_root_id = i; + break; + } + return inst_root_id; +} + +wxDataViewItem PrusaObjectDataViewModel::AddInstanceChild(const wxDataViewItem &parent_item, size_t num) +{ + PrusaObjectDataViewModelNode *parent_node = (PrusaObjectDataViewModelNode*)parent_item.GetID(); + if (!parent_node) return wxDataViewItem(0); + + // Check and create/get instances root node + const int inst_root_id = get_istances_root_idx(parent_node); + + PrusaObjectDataViewModelNode *inst_root_node = inst_root_id < 0 ? + new PrusaObjectDataViewModelNode(parent_node, itInstanceRoot) : + parent_node->GetNthChild(inst_root_id); + const wxDataViewItem inst_root_item((void*)inst_root_node); + + if (inst_root_id < 0) { + const unsigned insert_pos = parent_node->GetChildCount() == 0 || parent_node->GetNthChild(0)->m_type != itSettings ? 0 : 1; + parent_node->Insert(inst_root_node, insert_pos); + // notify control + ItemAdded(parent_item, inst_root_item); + num++; + } + + // Add instance nodes + PrusaObjectDataViewModelNode *instance_node = nullptr; + size_t counter = 0; + while (counter < num){ + instance_node = new PrusaObjectDataViewModelNode(inst_root_node, itInstance); + inst_root_node->Append(instance_node); + // notify control + const wxDataViewItem instance_item((void*)instance_node); + ItemAdded(inst_root_item, instance_item); + ++counter; + } + + return wxDataViewItem((void*)instance_node); +} + wxDataViewItem PrusaObjectDataViewModel::Delete(const wxDataViewItem &item) { auto ret_item = wxDataViewItem(0); @@ -505,6 +554,30 @@ wxDataViewItem PrusaObjectDataViewModel::Delete(const wxDataViewItem &item) if (cur_idx > idx) children[i]->SetIdx(cur_idx-1); } + + // if there is last instance item, delete both of it and instance root item + if (node_parent->GetChildCount() == 1 && node_parent->GetNthChild(0)->m_type == itInstance) + { + delete node; + ItemDeleted(parent, item); + + PrusaObjectDataViewModelNode *last_instance_node = node_parent->GetNthChild(0); + node_parent->GetChildren().Remove(last_instance_node); + delete last_instance_node; + ItemDeleted(parent, wxDataViewItem(last_instance_node)); + + PrusaObjectDataViewModelNode *obj_node = node_parent->GetParent(); + obj_node->GetChildren().Remove(node_parent); + delete node_parent; + ret_item = wxDataViewItem(obj_node); + ItemDeleted(ret_item, wxDataViewItem(node_parent)); + +#ifndef __WXGTK__ + if (obj_node->GetChildCount() == 0) + obj_node->m_container = false; +#endif //__WXGTK__ + return ret_item; + } } else { @@ -534,6 +607,54 @@ wxDataViewItem PrusaObjectDataViewModel::Delete(const wxDataViewItem &item) return ret_item; } +wxDataViewItem PrusaObjectDataViewModel::DeleteLastInstance(const wxDataViewItem &parent_item, size_t num) +{ + auto ret_item = wxDataViewItem(0); + PrusaObjectDataViewModelNode *parent_node = (PrusaObjectDataViewModelNode*)parent_item.GetID(); + if (!parent_node) return ret_item; + + const int inst_root_id = get_istances_root_idx(parent_node); + if (inst_root_id < 0) return ret_item; + + wxDataViewItemArray items; + PrusaObjectDataViewModelNode *inst_root_node = parent_node->GetNthChild(inst_root_id); + const wxDataViewItem inst_root_item((void*)inst_root_node); + + const int inst_cnt = inst_root_node->GetChildCount(); + const bool delete_inst_root_item = inst_cnt - num < 2 ? true : false; + + int stop = delete_inst_root_item ? 0 : inst_cnt - num; + for (int i = inst_cnt - 1; i >= stop;--i) { + PrusaObjectDataViewModelNode *last_instance_node = inst_root_node->GetNthChild(i); + inst_root_node->GetChildren().Remove(last_instance_node); + delete last_instance_node; + ItemDeleted(inst_root_item, wxDataViewItem(last_instance_node)); + } + +// for (int i = delete_inst_root_item ? 0 : inst_cnt - num; i < inst_cnt; ++i) +// items.Add(wxDataViewItem(inst_root_node->GetNthChild(i))); +// +// if (delete_inst_root_item) +// inst_root_node->GetChildren().RemoveAt(0, inst_cnt); +// else { +// ret_item = wxDataViewItem(inst_root_node->GetNthChild(inst_cnt - num - 1)); +// inst_root_node->GetChildren().RemoveAt(inst_cnt - num, num); +// } + +// ItemsDeleted(inst_root_item, items); + if (delete_inst_root_item) { + ret_item = parent_item; + parent_node->GetChildren().Remove(inst_root_node); + ItemDeleted(parent_item, inst_root_item); +#ifndef __WXGTK__ + if (parent_node->GetChildCount() == 0) + parent_node->m_container = false; +#endif //__WXGTK__ + } + + return ret_item; +} + void PrusaObjectDataViewModel::DeleteAll() { while (!m_objects.empty()) @@ -620,36 +741,49 @@ int PrusaObjectDataViewModel::GetIdByItem(const wxDataViewItem& item) return it - m_objects.begin(); } -int PrusaObjectDataViewModel::GetVolumeIdByItem(const wxDataViewItem& item) +int PrusaObjectDataViewModel::GetIdByItemAndType(const wxDataViewItem& item, const ItemType type) const { wxASSERT(item.IsOk()); PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID(); - if (!node || node->m_type != itVolume) + if (!node || node->m_type != type) return -1; return node->GetIdx(); } +int PrusaObjectDataViewModel::GetVolumeIdByItem(const wxDataViewItem& item) const +{ + return GetIdByItemAndType(item, itVolume); +} + +int PrusaObjectDataViewModel::GetInstanceIdByItem(const wxDataViewItem& item) const +{ + return GetIdByItemAndType(item, itInstance); +} + void PrusaObjectDataViewModel::GetItemInfo(const wxDataViewItem& item, ItemType& type, int& obj_idx, int& idx) { wxASSERT(item.IsOk()); type = itUndef; PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID(); - if (!node) return; + if (!node || node->GetIdx() < 0 && node->GetType() != itObject) + return; - type = node->GetType(); idx = node->GetIdx(); + type = node->GetType(); PrusaObjectDataViewModelNode *parent_node = node->GetParent(); if (!parent_node) return; if (type == itInstance) parent_node = node->GetParent()->GetParent(); - if (!parent_node) return; + if (!parent_node || parent_node->m_type != itObject) { type = itUndef; return; } auto it = find(m_objects.begin(), m_objects.end(), parent_node); if (it != m_objects.end()) obj_idx = it - m_objects.begin(); + else + type = itUndef; } wxString PrusaObjectDataViewModel::GetName(const wxDataViewItem &item) const @@ -819,12 +953,32 @@ wxDataViewItem PrusaObjectDataViewModel::GetParent(const wxDataViewItem &item) c PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID(); // objects nodes has no parent too - if (find(m_objects.begin(), m_objects.end(),node) != m_objects.end()) + if (node->m_type == itObject) return wxDataViewItem(0); return wxDataViewItem((void*)node->GetParent()); } +wxDataViewItem PrusaObjectDataViewModel::GetTopParent(const wxDataViewItem &item) const +{ + // the invisible root node has no parent + if (!item.IsOk()) + return wxDataViewItem(0); + + PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID(); + if (node->m_type == itObject) + return item; + + PrusaObjectDataViewModelNode *parent_node = node->GetParent(); + while (parent_node->m_type != itObject) + { + node = parent_node; + parent_node = node->GetParent(); + } + + return wxDataViewItem((void*)parent_node); +} + bool PrusaObjectDataViewModel::IsContainer(const wxDataViewItem &item) const { // the invisible root node can have children diff --git a/src/slic3r/GUI/wxExtensions.hpp b/src/slic3r/GUI/wxExtensions.hpp index f3c417426f..c1ff4074e2 100644 --- a/src/slic3r/GUI/wxExtensions.hpp +++ b/src/slic3r/GUI/wxExtensions.hpp @@ -195,12 +195,12 @@ DECLARE_VARIANT_OBJECT(PrusaDataViewBitmapText) // ---------------------------------------------------------------------------- enum ItemType{ - itUndef, - itObject, - itVolume, - itInstanceRoot, - itInstance, - itSettings + itUndef = 0, + itObject = 1, + itVolume = 2, + itInstanceRoot = 4, + itInstance = 8, + itSettings = 16 }; class PrusaObjectDataViewModelNode; @@ -211,6 +211,7 @@ class PrusaObjectDataViewModelNode PrusaObjectDataViewModelNode* m_parent; MyObjectTreeModelNodePtrArray m_children; wxBitmap m_empty_bmp; + size_t m_volumes_cnt = 0; std::vector< std::string > m_opt_categories; public: PrusaObjectDataViewModelNode(const wxString &name, const int instances_count=1) { @@ -248,7 +249,7 @@ public: set_part_action_icon(); } - PrusaObjectDataViewModelNode( PrusaObjectDataViewModelNode* parent, const ItemType type = itSettings) : + PrusaObjectDataViewModelNode( PrusaObjectDataViewModelNode* parent, const ItemType type) : m_parent(parent), m_copy(wxEmptyString), m_type(type), @@ -261,8 +262,8 @@ public: m_name = "Instances"; } else if (type == itInstance) { - m_name = wxString::Format("Instances_%d", parent->GetChildCount() + 1); m_idx = parent->GetChildCount(); + m_name = wxString::Format("Instance_%d", m_idx+1); } } @@ -370,7 +371,11 @@ public: void SetIdx(const int& idx) { m_idx = idx; + // update name if this node is instance + if (m_type == itInstance) + m_name = wxString::Format("Instance_%d", m_idx + 1); } + int GetIdx() const { return m_idx; } @@ -407,6 +412,8 @@ public: void set_object_action_icon(); void set_part_action_icon(); bool update_settings_digest(const std::vector& categories); +private: + friend class PrusaObjectDataViewModel; }; // ---------------------------------------------------------------------------- @@ -422,19 +429,23 @@ public: wxDataViewItem Add(const wxString &name); wxDataViewItem Add(const wxString &name, const int instances_count); - wxDataViewItem AddChild(const wxDataViewItem &parent_item, + wxDataViewItem AddVolumeChild(const wxDataViewItem &parent_item, const wxString &name, const wxBitmap& icon, const int extruder = 0, const bool create_frst_child = true); wxDataViewItem AddSettingsChild(const wxDataViewItem &parent_item); + wxDataViewItem AddInstanceChild(const wxDataViewItem &parent_item, size_t num); wxDataViewItem Delete(const wxDataViewItem &item); + wxDataViewItem DeleteLastInstance(const wxDataViewItem &parent_item, size_t num); void DeleteAll(); void DeleteChildren(wxDataViewItem& parent); wxDataViewItem GetItemById(int obj_idx); wxDataViewItem GetItemByVolumeId(int obj_idx, int volume_idx); int GetIdByItem(const wxDataViewItem& item); - int GetVolumeIdByItem(const wxDataViewItem& item); + int GetIdByItemAndType(const wxDataViewItem& item, const ItemType type) const; + int GetVolumeIdByItem(const wxDataViewItem& item) const; + int GetInstanceIdByItem(const wxDataViewItem& item) const; void GetItemInfo(const wxDataViewItem& item, ItemType& type, int& obj_idx, int& idx); bool IsEmpty() { return m_objects.empty(); } @@ -466,6 +477,8 @@ public: virtual bool IsEnabled(const wxDataViewItem &item, unsigned int col) const override; virtual wxDataViewItem GetParent(const wxDataViewItem &item) const override; + // get object item + wxDataViewItem GetTopParent(const wxDataViewItem &item) const; virtual bool IsContainer(const wxDataViewItem &item) const override; virtual unsigned int GetChildren(const wxDataViewItem &parent, wxDataViewItemArray &array) const override; From 33a0f5beff5d4ba91f4352741f99df303191cd8a Mon Sep 17 00:00:00 2001 From: YuSanka Date: Thu, 18 Oct 2018 11:28:31 +0200 Subject: [PATCH 125/186] Deleted "Copy" column from ObjectList --- src/slic3r/GUI/GUI_ObjectList.cpp | 32 +++++++++---------------- src/slic3r/GUI/GUI_ObjectList.hpp | 2 -- src/slic3r/GUI/Plater.cpp | 4 +--- src/slic3r/GUI/Tab.cpp | 2 +- src/slic3r/GUI/wxExtensions.cpp | 39 ++++--------------------------- src/slic3r/GUI/wxExtensions.hpp | 15 +++--------- 6 files changed, 21 insertions(+), 73 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 5a20756cef..ca54a3ca02 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -94,17 +94,13 @@ void ObjectList::create_objects_ctrl() // column 0(Icon+Text) of the view control: // And Icon can be consisting of several bitmaps AppendColumn(new wxDataViewColumn(_(L("Name")), new PrusaBitmapTextRenderer(), - 0, 200, wxALIGN_LEFT, wxDATAVIEW_COL_RESIZABLE)); + 0, 250, wxALIGN_LEFT, wxDATAVIEW_COL_RESIZABLE)); // column 1 of the view control: - AppendTextColumn(_(L("Copy")), 1, wxDATAVIEW_CELL_INERT, 45, - wxALIGN_CENTER_HORIZONTAL, wxDATAVIEW_COL_RESIZABLE); - - // column 2 of the view control: AppendColumn(create_objects_list_extruder_column(4)); - // column 3 of the view control: - AppendBitmapColumn(" ", 3, wxDATAVIEW_CELL_INERT, 25, + // column 2 of the view control: + AppendBitmapColumn(" ", 2, wxDATAVIEW_CELL_INERT, 25, wxALIGN_CENTER_HORIZONTAL, wxDATAVIEW_COL_RESIZABLE); } @@ -178,7 +174,7 @@ wxDataViewColumn* ObjectList::create_objects_list_extruder_column(int extruders_ choices.Add(wxString::Format("%d", i)); wxDataViewChoiceRenderer *c = new wxDataViewChoiceRenderer(choices, wxDATAVIEW_CELL_EDITABLE, wxALIGN_CENTER_HORIZONTAL); - wxDataViewColumn* column = new wxDataViewColumn(_(L("Extruder")), c, 2, 60, wxALIGN_CENTER_HORIZONTAL, wxDATAVIEW_COL_RESIZABLE); + wxDataViewColumn* column = new wxDataViewColumn(_(L("Extruder")), c, 1, 80, wxALIGN_CENTER_HORIZONTAL, wxDATAVIEW_COL_RESIZABLE); return column; } @@ -188,17 +184,17 @@ void ObjectList::update_objects_list_extruder_column(int extruders_count) if (wxGetApp().preset_bundle->printers.get_selected_preset().printer_technology() == ptSLA) extruders_count = 1; - // delete old 3rd column - DeleteColumn(GetColumn(2)); + // delete old 2nd column + DeleteColumn(GetColumn(1)); // insert new created 3rd column - InsertColumn(2, create_objects_list_extruder_column(extruders_count)); + InsertColumn(1, create_objects_list_extruder_column(extruders_count)); // set show/hide for this column set_extruder_column_hidden(extruders_count <= 1); } void ObjectList::set_extruder_column_hidden(bool hide) { - GetColumn(2)->SetHidden(hide); + GetColumn(1)->SetHidden(hide); } void ObjectList::update_extruder_in_config(const wxString& selection) @@ -313,10 +309,10 @@ void ObjectList::key_event(wxKeyEvent& event) void ObjectList::item_value_change(wxDataViewEvent& event) { - if (event.GetColumn() == 2) + if (event.GetColumn() == 1) { wxVariant variant; - m_objects_model->GetValue(variant, event.GetItem(), 2); + m_objects_model->GetValue(variant, event.GetItem(), 1); #ifdef __WXOSX__ m_selected_extruder = variant.GetString(); #else // --> for Linux @@ -1076,7 +1072,7 @@ void ObjectList::add_object_to_list(size_t obj_idx) { auto model_object = (*m_objects)[obj_idx]; wxString item_name = model_object->name; - auto item = m_objects_model->Add(item_name, model_object->instances.size()); + auto item = m_objects_model->Add(item_name); #if !ENABLE_EXTENDED_SELECTION /*Select*/select_item(item); #endif // !ENABLE_EXTENDED_SELECTION @@ -1143,12 +1139,6 @@ void ObjectList::decrease_object_instances(const size_t obj_idx, const size_t nu select_item(m_objects_model->DeleteLastInstance(m_objects_model->GetItemById(obj_idx), num)); } -void ObjectList::set_object_count(int idx, int count) -{ - m_objects_model->SetValue(wxString::Format("%d", count), idx, 1); - Refresh(); -} - void ObjectList::unselect_objects() { if (!GetSelection()) diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index 2325734bd7..c56e696700 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -116,8 +116,6 @@ public: void increase_object_instances(const size_t obj_idx, const size_t num); // Decrease instances count void decrease_object_instances(const size_t obj_idx, const size_t num); - // Set count of object on c++ side - void set_object_count(int idx, int count); // #ys_FIXME_to_delete // Unselect all objects in the list on c++ side diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 7ef58d8bbc..8238db65a7 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1742,11 +1742,10 @@ void Plater::increase(size_t num) float offset = 10.0; for (size_t i = 0; i < num; i++, offset += 10.0) { Vec3d offset_vec = model_instance->get_offset() + Vec3d(offset, offset, 0.0); - auto *new_instance = model_object->add_instance(offset_vec, model_instance->get_scaling_factor(), model_instance->get_rotation()); + model_object->add_instance(offset_vec, model_instance->get_scaling_factor(), model_instance->get_rotation()); p->print.get_object(*obj_idx)->add_copy(Slic3r::to_2d(offset_vec)); } - sidebar().obj_list()->set_object_count(*obj_idx, model_object->instances.size()); sidebar().obj_list()->increase_object_instances(*obj_idx, num); if (p->get_config("autocenter") == "1") { @@ -1771,7 +1770,6 @@ void Plater::decrease(size_t num) model_object->delete_last_instance(); p->print.get_object(*obj_idx)->delete_last_copy(); } - sidebar().obj_list()->set_object_count(*obj_idx, model_object->instances.size()); sidebar().obj_list()->decrease_object_instances(*obj_idx, num); } else { remove(*obj_idx); diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 023a6a67d5..3b9fe0bd39 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1845,7 +1845,7 @@ void TabPrinter::extruders_count_changed(size_t extruders_count){ if (!wxGetApp().mainframe) return; on_value_change("extruders_count", extruders_count); - wxGetApp().mainframe->m_plater->sidebar().update_objects_list_extruder_column(extruders_count); + wxGetApp().sidebar().update_objects_list_extruder_column(extruders_count); } void TabPrinter::append_option_line(ConfigOptionsGroupShp optgroup, const std::string opt_key) diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp index cd5f339e0b..f74aa02b40 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -418,17 +418,6 @@ wxDataViewItem PrusaObjectDataViewModel::Add(const wxString &name) return child; } -wxDataViewItem PrusaObjectDataViewModel::Add(const wxString &name, const int instances_count/*, int scale*/) -{ - auto root = new PrusaObjectDataViewModelNode(name, instances_count); - m_objects.push_back(root); - // notify control - wxDataViewItem child((void*)root); - wxDataViewItem parent((void*)NULL); - ItemAdded(parent, child); - return child; -} - wxDataViewItem PrusaObjectDataViewModel::AddVolumeChild(const wxDataViewItem &parent_item, const wxString &name, const wxBitmap& icon, @@ -442,8 +431,8 @@ wxDataViewItem PrusaObjectDataViewModel::AddVolumeChild(const wxDataViewItem &pa if (create_frst_child && root->m_volumes_cnt == 0) { - const auto icon_solid_mesh = wxIcon(Slic3r::GUI::from_u8(Slic3r::var("object.png")), wxBITMAP_TYPE_PNG); - const auto node = new PrusaObjectDataViewModelNode(root, root->m_name, icon_solid_mesh, extruder_str, 0); + const auto bmp_solid_mesh = wxBitmap(Slic3r::GUI::from_u8(Slic3r::var("object.png")), wxBITMAP_TYPE_PNG); + const auto node = new PrusaObjectDataViewModelNode(root, root->m_name, bmp_solid_mesh, extruder_str, 0); root->Append(node); // notify control const wxDataViewItem child((void*)node); @@ -795,21 +784,6 @@ wxString PrusaObjectDataViewModel::GetName(const wxDataViewItem &item) const return node->m_name; } -wxString PrusaObjectDataViewModel::GetCopy(const wxDataViewItem &item) const -{ - PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID(); - if (!node) // happens if item.IsOk()==false - return wxEmptyString; - - return node->m_copy; -} - -// wxIcon& PrusaObjectDataViewModel::GetIcon(const wxDataViewItem &item) const -// { -// PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID(); -// return node->m_icon; -// } - wxBitmap& PrusaObjectDataViewModel::GetBitmap(const wxDataViewItem &item) const { PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID(); @@ -823,16 +797,13 @@ void PrusaObjectDataViewModel::GetValue(wxVariant &variant, const wxDataViewItem PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID(); switch (col) { - case 0:{ + case 0: variant << PrusaDataViewBitmapText(node->m_name, node->m_bmp); - break;} - case 1: - variant = node->m_copy; break; - case 2: + case 1: variant = node->m_extruder; break; - case 3: + case 2: variant << node->m_action_icon; break; default: diff --git a/src/slic3r/GUI/wxExtensions.hpp b/src/slic3r/GUI/wxExtensions.hpp index c1ff4074e2..01677809d9 100644 --- a/src/slic3r/GUI/wxExtensions.hpp +++ b/src/slic3r/GUI/wxExtensions.hpp @@ -166,7 +166,7 @@ public: void SetText(const wxString &text) { m_text = text; } wxString GetText() const { return m_text; } - void SetBitmap(const wxIcon &icon) { m_bmp = icon; } + void SetBitmap(const wxBitmap &bmp) { m_bmp = bmp; } const wxBitmap &GetBitmap() const { return m_bmp; } bool IsSameAs(const PrusaDataViewBitmapText& other) const { @@ -214,10 +214,9 @@ class PrusaObjectDataViewModelNode size_t m_volumes_cnt = 0; std::vector< std::string > m_opt_categories; public: - PrusaObjectDataViewModelNode(const wxString &name, const int instances_count=1) { + PrusaObjectDataViewModelNode(const wxString &name) { m_parent = NULL; m_name = name; - m_copy = wxString::Format("%d", instances_count); m_type = itObject; #ifdef __WXGTK__ // it's necessary on GTK because of control have to know if this item will be container @@ -235,7 +234,6 @@ public: const int idx = -1 ) { m_parent = parent; m_name = sub_obj_name; - m_copy = wxEmptyString; m_bmp = bmp; m_type = itVolume; m_idx = idx; @@ -251,7 +249,6 @@ public: PrusaObjectDataViewModelNode( PrusaObjectDataViewModelNode* parent, const ItemType type) : m_parent(parent), - m_copy(wxEmptyString), m_type(type), m_extruder(wxEmptyString) { @@ -280,7 +277,6 @@ public: wxString m_name; wxBitmap& m_bmp = m_empty_bmp; - wxString m_copy; ItemType m_type; int m_idx = -1; bool m_container = false; @@ -346,12 +342,9 @@ public: m_name = data.GetText(); return true;} case 1: - m_copy = variant.GetString(); - return true; - case 2: m_extruder = variant.GetString(); return true; - case 3: + case 2: m_action_icon << variant; return true; default: @@ -428,7 +421,6 @@ public: ~PrusaObjectDataViewModel(); wxDataViewItem Add(const wxString &name); - wxDataViewItem Add(const wxString &name, const int instances_count); wxDataViewItem AddVolumeChild(const wxDataViewItem &parent_item, const wxString &name, const wxBitmap& icon, @@ -452,7 +444,6 @@ public: // helper method for wxLog wxString GetName(const wxDataViewItem &item) const; - wxString GetCopy(const wxDataViewItem &item) const; wxBitmap& GetBitmap(const wxDataViewItem &item) const; // helper methods to change the model From fef8d1fe51b96513dfcc18555eaa93f17bbe586c Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Thu, 18 Oct 2018 11:32:21 +0200 Subject: [PATCH 126/186] Fix a color value assert --- src/slic3r/GUI/Field.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index 5dbc658777..29d23eee58 100644 --- a/src/slic3r/GUI/Field.cpp +++ b/src/slic3r/GUI/Field.cpp @@ -610,8 +610,13 @@ void ColourPicker::BUILD() if (m_opt.height >= 0) size.SetHeight(m_opt.height); if (m_opt.width >= 0) size.SetWidth(m_opt.width); - wxString clr(static_cast(m_opt.default_value)->get_at(m_opt_idx)); - // FIXME: verify clr is valid, otherwise this causes an assert + // Validate the color + wxString clr_str(static_cast(m_opt.default_value)->get_at(m_opt_idx)); + wxColour clr(clr_str); + if (! clr.IsOk()) { + clr = wxTransparentColour; + } + auto temp = new wxColourPickerCtrl(m_parent, wxID_ANY, clr, wxDefaultPosition, size); // // recast as a wxWindow to fit the calling convention @@ -619,7 +624,7 @@ void ColourPicker::BUILD() temp->Bind(wxEVT_COLOURPICKER_CHANGED, ([this](wxCommandEvent e) { on_change_field(); }), temp->GetId()); - temp->SetToolTip(get_tooltip_text(clr)); + temp->SetToolTip(get_tooltip_text(clr_str)); } boost::any& ColourPicker::get_value(){ From bb1dfa352265da67d9678e83e4dfd951cc114d4b Mon Sep 17 00:00:00 2001 From: bubnikv Date: Thu, 18 Oct 2018 14:36:46 +0200 Subject: [PATCH 127/186] WIP: Synchronization of Model / ModelObject with Print / PrintObject --- src/libslic3r/Print.cpp | 326 ++++++++++++++++++++++++++-------------- src/libslic3r/Print.hpp | 28 ++-- 2 files changed, 228 insertions(+), 126 deletions(-) diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 82dc089d4c..e309e265ad 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -376,6 +376,16 @@ double Print::max_allowed_layer_height() const return nozzle_diameter_max; } +static PrintRegionConfig region_config_from_model_volume(const PrintRegionConfig &default_region_config, const ModelVolume &volume) +{ + PrintRegionConfig config = default_region_config; + normalize_and_apply_config(config, volume.get_object()->config); + normalize_and_apply_config(config, volume.config); + if (! volume.material_id().empty()) + normalize_and_apply_config(config, volume.material()->config); + return config; +} + // Caller is responsible for supplying models whose objects don't collide // and have explicit instance positions. void Print::add_model_object(ModelObject* model_object, int idx) @@ -397,7 +407,7 @@ void Print::add_model_object(ModelObject* model_object, int idx) if (! volume->is_model_part() && ! volume->is_modifier()) continue; // Get the config applied to this volume. - PrintRegionConfig config = this->_region_config_from_model_volume(*volume); + PrintRegionConfig config = region_config_from_model_volume(m_default_region_config, *volume); // Find an existing print region with the same config. size_t region_id = size_t(-1); for (size_t i = 0; i < m_regions.size(); ++ i) @@ -424,35 +434,7 @@ void Print::add_model_object(ModelObject* model_object, int idx) object->config_apply(src_normalized, true); } - // update placeholders - { - // get the first input file name - std::string input_file; - std::vector v_scale; - for (const PrintObject *object : m_objects) { - const ModelObject &mobj = *object->model_object(); -#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - // CHECK_ME -> Is the following correct ? - v_scale.push_back("x:" + boost::lexical_cast(mobj.instances[0]->get_scaling_factor(X) * 100) + - "% y:" + boost::lexical_cast(mobj.instances[0]->get_scaling_factor(Y) * 100) + - "% z:" + boost::lexical_cast(mobj.instances[0]->get_scaling_factor(Z) * 100) + "%"); -#else - v_scale.push_back(boost::lexical_cast(mobj.instances[0]->scaling_factor * 100) + "%"); -#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM - if (input_file.empty()) - input_file = mobj.input_file; - } - - PlaceholderParser &pp = m_placeholder_parser; - pp.set("scale", v_scale); - if (! input_file.empty()) { - // get basename with and without suffix - const std::string input_basename = boost::filesystem::path(input_file).filename().string(); - pp.set("input_filename", input_basename); - const std::string input_basename_base = input_basename.substr(0, input_basename.find_last_of(".")); - pp.set("input_filename_base", input_basename_base); - } - } + this->update_object_placeholders(); } bool Print::apply_config(DynamicPrintConfig config) @@ -514,12 +496,12 @@ bool Print::apply_config(DynamicPrintConfig config) // If the new config for this volume differs from the other // volume configs currently associated to this region, it means // the region subdivision does not make sense anymore. - if (! this_region_config.equals(this->_region_config_from_model_volume(volume))) { + if (! this_region_config.equals(region_config_from_model_volume(m_default_region_config, volume))) { rearrange_regions = true; goto exit_for_rearrange_regions; } } else { - this_region_config = this->_region_config_from_model_volume(volume); + this_region_config = region_config_from_model_volume(m_default_region_config, volume); this_region_config_set = true; } for (const PrintRegionConfig &cfg : other_region_configs) { @@ -681,7 +663,7 @@ static inline bool transform3d_equal(const Transform3d &lhs, const Transform3d & struct PrintInstances { Transform3d trafo; - Points instances; + Points copies; bool operator<(const PrintInstances &rhs) const { return transform3d_lower(this->trafo, rhs.trafo); } }; @@ -690,26 +672,46 @@ static std::vector print_objects_from_model_object(const ModelOb { std::set trafos; PrintInstances trafo; - trafo.instances.assign(1, Point()); + trafo.copies.assign(1, Point()); for (ModelInstance *model_instance : model_object.instances) if (model_instance->is_printable()) { const Vec3d &offst = model_instance->get_offset(); trafo.trafo = model_instance->world_matrix(true); - trafo.instances.front() = Point::new_scale(offst(0), offst(1)); + trafo.copies.front() = Point::new_scale(offst(0), offst(1)); auto it = trafos.find(trafo); if (it == trafos.end()) trafos.emplace(trafo); else - const_cast(*it).instances.emplace_back(trafo.instances.front()); + const_cast(*it).copies.emplace_back(trafo.copies.front()); } return std::vector(trafos.begin(), trafos.end()); } -bool Print::apply(const Model &model, const DynamicPrintConfig &config) +bool Print::apply(const Model &model, const DynamicPrintConfig &config_in) { + // Make a copy of the config, normalize it. + DynamicPrintConfig config(config_in); + config.normalize(); + // Collect changes to print config. + t_config_option_keys print_diff = m_config.diff(config); + t_config_option_keys object_diff = m_default_object_config.diff(config); + t_config_option_keys region_diff = m_default_region_config.diff(config); + // Grab the lock for the Print / PrintObject milestones. tbb::mutex::scoped_lock lock(m_mutex); + // The following call may stop the background processing. + bool invalidated = this->invalidate_state_by_config_options(print_diff); + // Apply variables to placeholder parser. The placeholder parser is used by G-code export, + // which should be stopped if print_diff is not empty. + m_placeholder_parser.apply_config(config); + // It is also safe to change m_config now after this->invalidate_state_by_config_options() call. + m_config.apply_only(config, print_diff, true); + // Handle changes to object config defaults + m_default_object_config.apply_only(config, object_diff, true); + // Handle changes to regions config defaults + m_default_region_config.apply_only(config, region_diff, true); + struct ModelObjectStatus { enum Status { Unknown, @@ -719,8 +721,9 @@ bool Print::apply(const Model &model, const DynamicPrintConfig &config) Deleted, }; ModelObjectStatus(ModelID id, Status status = Unknown) : id(id), status(status) {} - ModelID id; - Status status; + ModelID id; + Status status; + t_config_option_keys object_config_diff; // Search by id. bool operator<(const ModelObjectStatus &rhs) const { return id < rhs.id; } }; @@ -729,7 +732,8 @@ bool Print::apply(const Model &model, const DynamicPrintConfig &config) // 1) Synchronize model objects. if (model.id() != m_model.id()) { // Kill everything, initialize from scratch. - // The following call shall kill any computation if running. + // Stop background processing. + m_cancel_callback(); this->invalidate_all_steps(); for (PrintObject *object : m_objects) { model_object_status.emplace(object->model_object()->id(), ModelObjectStatus::Deleted); @@ -746,6 +750,8 @@ bool Print::apply(const Model &model, const DynamicPrintConfig &config) } else if (model_object_list_extended(m_model, model)) { // Add new objects. Their volumes and configs will be synchronized later. this->invalidate_step(psGCodeExport); + for (const ModelObject *model_object : m_model.objects) + model_object_status.emplace(model_object->id(), ModelObjectStatus::Old); for (size_t i = m_model.objects.size(); i < model.objects.size(); ++ i) { model_object_status.emplace(model.objects[i]->id(), ModelObjectStatus::New); m_model.objects.emplace_back(model.objects[i]->clone(&m_model)); @@ -770,7 +776,7 @@ bool Print::apply(const Model &model, const DynamicPrintConfig &config) } else { // Existing ModelObject re-added (possibly moved in the list). m_model.objects.emplace_back(*it); - model_object_status.emplace(mobj->id(), ModelObjectStatus::Old); + model_object_status.emplace(mobj->id(), ModelObjectStatus::Moved); } } bool deleted_any = false; @@ -835,7 +841,7 @@ bool Print::apply(const Model &model, const DynamicPrintConfig &config) // PrintObject instances will be added in the next loop. continue; // Update the ModelObject instance, possibly invalidate the linked PrintObjects. - assert(it_status->status == ModelObjectStatus::Moved); + assert(it_status->status == ModelObjectStatus::Old || it_status->status == ModelObjectStatus::Moved); const ModelObject &model_object_new = *model.objects[idx_model_object]; // Check whether a model part volume was added or removed, their transformations or order changed. bool model_parts_differ = model_volume_list_changed(model_object, model_object_new, ModelVolume::MODEL_PART); @@ -864,87 +870,187 @@ bool Print::apply(const Model &model, const DynamicPrintConfig &config) } if (! model_parts_differ && ! modifiers_differ) { // Synchronize the remaining data of ModelVolumes (name, config, m_type, m_material_id) + // Synchronize Object's config. + t_config_option_keys &this_object_config_diff = const_cast(*it_status).object_config_diff; + this_object_config_diff = model_object.config.diff(model_object_new.config); + if (! this_object_config_diff.empty()) + model_object.config.apply_only(model_object_new.config, this_object_config_diff, true); + if (! this_object_config_diff.empty() || ! this_object_config_diff.empty()) { + PrintObjectConfig new_config = m_default_object_config; + normalize_and_apply_config(new_config, model_object.config); + auto range = print_object_status.equal_range(PrintObjectStatus(model_object.id())); + for (auto it = range.first; it != range.second; ++ it) { + t_config_option_keys diff = it->print_object->config().diff(new_config); + invalidated |= it->print_object->invalidate_state_by_config_options(diff); + it->print_object->config_apply_only(new_config, diff, true); + } + } } } // 4) Generate PrintObjects from ModelObjects and their instances. - std::vector print_objects_new; - print_objects_new.reserve(std::max(m_objects.size(), m_model.objects.size())); - // Walk over all new model objects and check, whether there are matching PrintObjects. - for (ModelObject *model_object : m_model.objects) { - auto range = print_object_status.equal_range(PrintObjectStatus(model_object->id())); - std::vector old; - if (range.first != range.second) { - old.reserve(print_object_status.count(PrintObjectStatus(model_object->id()))); - for (auto it = range.first; it != range.second; ++ it) - if (it->status != PrintObjectStatus::Deleted) - old.emplace_back(&(*it)); + { + std::vector print_objects_new; + print_objects_new.reserve(std::max(m_objects.size(), m_model.objects.size())); + // Walk over all new model objects and check, whether there are matching PrintObjects. + for (ModelObject *model_object : m_model.objects) { + auto range = print_object_status.equal_range(PrintObjectStatus(model_object->id())); + std::vector old; + if (range.first != range.second) { + old.reserve(print_object_status.count(PrintObjectStatus(model_object->id()))); + for (auto it = range.first; it != range.second; ++ it) + if (it->status != PrintObjectStatus::Deleted) + old.emplace_back(&(*it)); + } + // Generate a list of trafos and XY offsets for instances of a ModelObject + PrintObjectConfig config = m_default_object_config; + normalize_and_apply_config(config, model_object->config); + std::vector new_print_instances = print_objects_from_model_object(*model_object); + if (old.empty()) { + // Simple case, just generate new instances. + for (const PrintInstances &print_instances : new_print_instances) { + PrintObject *print_object = new PrintObject(this, model_object, model_object->raw_bounding_box()); + print_object->set_copies(print_instances.copies); + print_object->config_apply(config); + print_objects_new.emplace_back(print_object); + print_object_status.emplace(PrintObjectStatus(print_object, PrintObjectStatus::New)); + } + continue; + } + // Complex case, try to merge the two lists. + // Sort the old lexicographically by their trafos. + std::sort(old.begin(), old.end(), [](const PrintObjectStatus *lhs, const PrintObjectStatus *rhs){ return transform3d_lower(lhs->trafo, rhs->trafo); }); + // Merge the old / new lists. + auto it_old = old.begin(); + for (const PrintInstances &new_instances : new_print_instances) { + for (; transform3d_lower((*it_old)->trafo, new_instances.trafo); ++ it_old); + if (! transform3d_equal((*it_old)->trafo, new_instances.trafo)) { + // This is a new instance (or a set of instances with the same trafo). Just add it. + PrintObject *print_object = new PrintObject(this, model_object, model_object->raw_bounding_box()); + print_object->set_copies(new_instances.copies); + print_object->config_apply(config); + print_objects_new.emplace_back(print_object); + print_object_status.emplace(PrintObjectStatus(print_object, PrintObjectStatus::New)); + } else if ((*it_old)->print_object->copies() != new_instances.copies) { + // The PrintObject already exists and the copies differ. The only step currently sensitive to the order is the G-code generator. + // Stop it. + this->invalidate_step(psGCodeExport); + (*it_old)->print_object->set_copies(new_instances.copies); + } + } } - // Generate a list of trafos and XY offsets for instances of a ModelObject - std::vector new_print_instances = print_objects_from_model_object(*model_object); - if (old.empty()) { - // Simple case, just generate new instances. - for (const PrintInstances &print_instances : new_print_instances) { - PrintObject *print_object = new PrintObject(this, model_object, model_object->raw_bounding_box()); - print_objects_new.emplace_back(print_object); - print_object_status.emplace(PrintObjectStatus(print_object, PrintObjectStatus::New)); + if (m_objects != print_objects_new) { + m_cancel_callback(); + m_objects = print_objects_new; + } + } + + // 5) Synchronize configs of ModelVolumes, synchronize AMF / 3MF materials (and their configs), refresh PrintRegions. + // Update reference counts of regions from the remaining PrintObjects and their volumes. + // Regions with zero references could and should be reused. + for (PrintRegion *region : m_regions) + region->m_refcnt = 0; + for (PrintObject *print_object : m_objects) { + int idx_region = 0; + for (const auto &volumes : print_object->region_volumes) { + if (! volumes.empty()) + ++ m_regions[idx_region]; + ++ idx_region; + } + } + + // All regions now have distinct settings. + // Check whether applying the new region config defaults we'd get different regions. + for (size_t region_id = 0; region_id < m_regions.size(); ++ region_id) { + PrintRegion ®ion = *m_regions[region_id]; + PrintRegionConfig this_region_config; + bool this_region_config_set = false; + for (PrintObject *print_object : m_objects) { + if (region_id < print_object->region_volumes.size()) { + for (int volume_id : print_object->region_volumes[region_id]) { + const ModelVolume &volume = *print_object->model_object()->volumes[volume_id]; + if (this_region_config_set) { + // If the new config for this volume differs from the other + // volume configs currently associated to this region, it means + // the region subdivision does not make sense anymore. + if (! this_region_config.equals(region_config_from_model_volume(m_default_region_config, volume))) + // Regions were split. Reset this print_object. + goto print_object_end; + } else { + this_region_config = region_config_from_model_volume(m_default_region_config, volume); + for (size_t i = 0; i < region_id; ++ i) + if (m_regions[i]->config().equals(this_region_config)) + // Regions were merged. Reset this print_object. + goto print_object_end; + this_region_config_set = true; + } + } } continue; + print_object_end: + print_object->invalidate_all_steps(); + // Decrease the references to regions from this volume. + int ireg = 0; + for (const std::vector &volumes : print_object->region_volumes) { + if (! volumes.empty()) + -- m_regions[ireg]; + ++ ireg; + } + print_object->region_volumes.clear(); + } + if (this_region_config_set) { + t_config_option_keys diff = region.config().diff(this_region_config); + if (! diff.empty()) { + region.config_apply_only(this_region_config, diff, false); + for (PrintObject *print_object : m_objects) + if (region_id < print_object->region_volumes.size() && ! print_object->region_volumes[region_id].empty()) + invalidated |= print_object->invalidate_state_by_config_options(diff); + } } - // Complex case, try to merge the two lists. - // Sort the old lexicographically by their trafos. - std::sort(old.begin(), old.end(), [](const PrintObjectStatus *lhs, const PrintObjectStatus *rhs){ return transform3d_lower(lhs->trafo, rhs->trafo); }); - // Merge the old / new lists. - - } - if (m_objects != print_objects_new) { - m_cancel_callback(); - m_objects = print_objects_new; } - // Synchronize materials. - -#if 0 - { - m_model = model; - for (const ModelObject *model_object : m_model.objects) { - PrintObject *object = new PrintObject(this, model_object, model_object->raw_bounding_box()); - m_objects.emplace_back(object); - size_t volume_id = 0; - for (const ModelVolume *volume : model_object->volumes) { + // Possibly add new regions for the newly added or resetted PrintObjects. + for (size_t idx_print_object = 0; idx_print_object < m_objects.size(); ++ idx_print_object) { + PrintObject &print_object0 = *m_objects[idx_print_object]; + const ModelObject &model_object = *print_object0.model_object(); + std::vector map_volume_to_region(model_object.volumes.size(), -1); + for (size_t i = idx_print_object; i < m_objects.size() && m_objects[i]->model_object() == &model_object; ++ i) { + PrintObject &print_object = *m_objects[i]; + unsigned int volume_id = 0; + for (const ModelVolume *volume : model_object.volumes) { if (! volume->is_model_part() && ! volume->is_modifier()) continue; - // Get the config applied to this volume. - PrintRegionConfig config = this->_region_config_from_model_volume(*volume); - // Find an existing print region with the same config. - size_t region_id = size_t(-1); - for (size_t i = 0; i < m_regions.size(); ++ i) - if (config.equals(m_regions[i]->config())) { - region_id = i; - break; + int region_id = -1; + if (&print_object == &print_object0) { + // Get the config applied to this volume. + PrintRegionConfig config = region_config_from_model_volume(m_default_region_config, *volume); + // Find an existing print region with the same config. + for (int i = 0; i < (int)m_regions.size(); ++ i) + if (config.equals(m_regions[i]->config())) { + region_id = i; + break; + } + // If no region exists with the same config, create a new one. + if (region_id == size_t(-1)) { + for (region_id = 0; region_id < m_regions.size(); ++ region_id) + if (m_regions[region_id]->m_refcnt == 0) { + // An empty slot was found. + m_regions[region_id]->set_config(std::move(config)); + break; + } + if (region_id == m_regions.size()) + this->add_region(config); } - // If no region exists with the same config, create a new one. - if (region_id == size_t(-1)) { - region_id = m_regions.size(); - this->add_region(config); - } + map_volume_to_region[volume_id] = region_id; + } else + region_id = map_volume_to_region[volume_id]; // Assign volume to a region. - object->add_region_volume(region_id, volume_id); + if (volume_id >= print_object.region_volumes.size()) + print_object.add_region_volume(region_id, volume_id); ++ volume_id; } - // Apply config to print object. - object->config_apply(this->default_object_config()); - { - //normalize_and_apply_config(object->config(), model_object->config); - DynamicPrintConfig src_normalized(model_object->config); - src_normalized.normalize(); - object->config_apply(src_normalized, true); - } } - } else { - // Synchronize m_model.objects with model.objects } -#endif this->update_object_placeholders(); } @@ -1284,16 +1390,6 @@ Flow Print::skirt_flow() const ); } -PrintRegionConfig Print::_region_config_from_model_volume(const ModelVolume &volume) -{ - PrintRegionConfig config = this->default_region_config(); - normalize_and_apply_config(config, volume.get_object()->config); - normalize_and_apply_config(config, volume.config); - if (! volume.material_id().empty()) - normalize_and_apply_config(config, volume.material()->config); - return config; -} - bool Print::has_support_material() const { for (const PrintObject *object : m_objects) diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index d539053b37..f4fd2235be 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -139,19 +139,25 @@ public: // Average diameter of nozzles participating on extruding this region. coordf_t nozzle_dmr_avg(const PrintConfig &print_config) const; // Average diameter of nozzles participating on extruding this region. - coordf_t bridging_height_avg(const PrintConfig &print_config) const; + coordf_t bridging_height_avg(const PrintConfig &print_config) const; // Methods modifying the PrintRegion's state: public: Print* print() { return m_print; } - void config_apply_only(const ConfigBase &other, const t_config_option_keys &keys, bool ignore_nonexistent = false) { this->m_config.apply_only(other, keys, ignore_nonexistent); } + void set_config(const PrintRegionConfig &config) { m_config = config; } + void set_config(PrintRegionConfig &&config) { m_config = std::move(config); } + void config_apply_only(const ConfigBase &other, const t_config_option_keys &keys, bool ignore_nonexistent = false) + { this->m_config.apply_only(other, keys, ignore_nonexistent); } + +protected: + size_t m_refcnt; private: Print *m_print; PrintRegionConfig m_config; - PrintRegion(Print* print) : m_print(print) {} - PrintRegion(Print* print, const PrintRegionConfig &config) : m_print(print), m_config(config) {} + PrintRegion(Print* print) : m_refcnt(0), m_print(print) {} + PrintRegion(Print* print, const PrintRegionConfig &config) : m_refcnt(0), m_print(print), m_config(config) {} ~PrintRegion() {} }; @@ -196,12 +202,13 @@ public: const SupportLayerPtrs& support_layers() const { return m_support_layers; } const Transform3d& trafo() const { return m_trafo; } - const Points& copies() const { return m_copies; } - bool add_copy(const Vec2d &point); - bool delete_last_copy(); - bool delete_all_copies() { return this->set_copies(Points()); } - bool set_copies(const Points &points); - bool reload_model_instances(); + const Points& copies() const { return m_copies; } + bool add_copy(const Vec2d &point); + bool delete_last_copy(); + bool delete_all_copies() { return this->set_copies(Points()); } + bool set_copies(const Points &points); + bool reload_model_instances(); + // since the object is aligned to origin, bounding box coincides with size BoundingBox bounding_box() const { return BoundingBox(Point(0,0), to_2d(this->size)); } @@ -486,7 +493,6 @@ private: void update_object_placeholders(); bool invalidate_state_by_config_options(const std::vector &opt_keys); - PrintRegionConfig _region_config_from_model_volume(const ModelVolume &volume); // If the background processing stop was requested, throw CanceledException. // To be called by the worker thread and its sub-threads (mostly launched on the TBB thread pool) regularly. From ea7216c0197ad2976e1c2e1bd7c48e1d459707f0 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Thu, 18 Oct 2018 14:42:21 +0200 Subject: [PATCH 128/186] Unified append_submenu() function and modified append_menu_item() function --- src/slic3r/GUI/GUI_App.cpp | 18 ------------------ src/slic3r/GUI/GUI_App.hpp | 6 ------ src/slic3r/GUI/Plater.cpp | 15 +++++++++++++++ src/slic3r/GUI/wxExtensions.cpp | 23 +++++++++++++++++++++-- src/slic3r/GUI/wxExtensions.hpp | 4 +++- 5 files changed, 39 insertions(+), 27 deletions(-) diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index e58142f264..ab7f2e13ec 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -327,24 +327,6 @@ void GUI_App::CallAfter(std::function cb) callback_register.unlock(); } -wxMenuItem* GUI_App::append_submenu(wxMenu* menu, - wxMenu* sub_menu, - int id, - const wxString& string, - const wxString& description, - const std::string& icon) -{ - if (id == wxID_ANY) - id = wxNewId(); - auto item = new wxMenuItem(menu, id, string, description); - if (!icon.empty()) - item->SetBitmap(wxBitmap(Slic3r::var(icon), wxBITMAP_TYPE_PNG)); - item->SetSubMenu(sub_menu); - menu->Append(item); - - return item; -} - void GUI_App::window_pos_save(wxTopLevelWindow* window, const std::string &name) { if (name.empty()) { return; } diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index e1e48e9b9f..502ce0ee17 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -107,12 +107,6 @@ public: // void notify(/*message*/); void update_ui_from_settings(); void CallAfter(std::function cb); - wxMenuItem* append_submenu(wxMenu* menu, - wxMenu* sub_menu, - int id, - const wxString& string, - const wxString& description, - const std::string& icon); void window_pos_save(wxTopLevelWindow* window, const std::string &name); void window_pos_restore(wxTopLevelWindow* window, const std::string &name); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 051b05598b..5db983623a 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1829,6 +1829,21 @@ bool Plater::priv::init_object_menu() wxMenuItem* item_decrease = append_menu_item(&object_menu, wxID_ANY, _(L("Decrease copies\t-")), _(L("Remove one copy of the selected object")), [this](wxCommandEvent&){ q->decrease(); }, "delete.png"); + object_menu.AppendSeparator(); + + wxMenu* mirror_menu = new wxMenu(); + if (mirror_menu == nullptr) + return false; + + append_menu_item(mirror_menu, wxID_ANY, _(L("Along X axis")), _(L("Mirror the selected object along the X axis")), + [this](wxCommandEvent&){ mirror(X); }, "bullet_red.png", &object_menu); + append_menu_item(mirror_menu, wxID_ANY, _(L("Along Y axis")), _(L("Mirror the selected object along the Y axis")), + [this](wxCommandEvent&){ mirror(Y); }, "bullet_green.png", &object_menu); + append_menu_item(mirror_menu, wxID_ANY, _(L("Along Z axis")), _(L("Mirror the selected object along the Z axis")), + [this](wxCommandEvent&){ mirror(Z); }, "bullet_blue.png", &object_menu); + + wxMenuItem* item_mirror = append_submenu(&object_menu, mirror_menu, wxID_ANY, _(L("Mirror")), _(L("Mirror the selected object"))); + #if ENABLE_EXTENDED_SELECTION // ui updates needs to be binded to the parent panel if (q != nullptr) diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp index 4f7f88602e..33e34137d2 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -11,7 +11,7 @@ #include "GUI_ObjectList.hpp" wxMenuItem* append_menu_item(wxMenu* menu, int id, const wxString& string, const wxString& description, - std::function cb, const std::string& icon) + std::function cb, const std::string& icon, wxEvtHandler* event_handler) { if (id == wxID_ANY) id = wxNewId(); @@ -20,7 +20,26 @@ wxMenuItem* append_menu_item(wxMenu* menu, int id, const wxString& string, const if (!icon.empty()) item->SetBitmap(wxBitmap(Slic3r::var(icon), wxBITMAP_TYPE_PNG)); - menu->Bind(wxEVT_MENU, cb, id); + if (event_handler != nullptr) + event_handler->Bind(wxEVT_MENU, cb, id); + else + menu->Bind(wxEVT_MENU, cb, id); + + return item; +} + +wxMenuItem* append_submenu(wxMenu* menu, wxMenu* sub_menu, int id, const wxString& string, const wxString& description, const std::string& icon) +{ + if (id == wxID_ANY) + id = wxNewId(); + + wxMenuItem* item = new wxMenuItem(menu, id, string, description); + if (!icon.empty()) + item->SetBitmap(wxBitmap(Slic3r::var(icon), wxBITMAP_TYPE_PNG)); + + item->SetSubMenu(sub_menu); + menu->Append(item); + return item; } diff --git a/src/slic3r/GUI/wxExtensions.hpp b/src/slic3r/GUI/wxExtensions.hpp index f39c38ab52..6f61ebee15 100644 --- a/src/slic3r/GUI/wxExtensions.hpp +++ b/src/slic3r/GUI/wxExtensions.hpp @@ -14,7 +14,9 @@ #include wxMenuItem* append_menu_item(wxMenu* menu, int id, const wxString& string, const wxString& description, - std::function cb, const std::string& icon = ""); + std::function cb, const std::string& icon = "", wxEvtHandler* event_handler = nullptr); + +wxMenuItem* append_submenu(wxMenu* menu, wxMenu* sub_menu, int id, const wxString& string, const wxString& description, const std::string& icon = ""); class wxCheckListBoxComboPopup : public wxCheckListBox, public wxComboPopup { From 2c9a82e582000215f4ce102b487a49b5a1834267 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Thu, 18 Oct 2018 15:09:41 +0200 Subject: [PATCH 129/186] New selection -> Removed unneeded methods and small refactor --- src/slic3r/GUI/GLCanvas3D.cpp | 21 ++++++----- src/slic3r/GUI/GLCanvas3D.hpp | 4 +- src/slic3r/GUI/Plater.cpp | 70 ++++++++++++++++++++++++++--------- src/slic3r/GUI/Plater.hpp | 4 +- 4 files changed, 69 insertions(+), 30 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index e8c79b1766..12cd32d560 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1409,14 +1409,13 @@ void GLCanvas3D::Selection::rotate(const Vec3d& rotation) if (!m_valid) return; - Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), rotation); - for (unsigned int i : m_list) { if (is_single_full_instance()) (*m_volumes)[i]->set_rotation(rotation); else { + Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), rotation); // extracts rotations from the composed transformation Vec3d new_rotation = Geometry::extract_euler_angles(m * m_cache.volumes_data[i].get_rotation_matrix()); @@ -1436,15 +1435,13 @@ void GLCanvas3D::Selection::scale(const Vec3d& scale) if (!m_valid) return; - Transform3d m = Transform3d::Identity(); - m.scale(scale); - for (unsigned int i : m_list) { if (is_single_full_instance()) (*m_volumes)[i]->set_scaling_factor(scale); else { + Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), Vec3d::Zero(), scale); Eigen::Matrix new_matrix = (m * m_cache.volumes_data[i].get_scale_matrix()).matrix().block(0, 0, 3, 3); // extracts scaling factors from the composed transformation Vec3d new_scale(new_matrix.col(0).norm(), new_matrix.col(1).norm(), new_matrix.col(2).norm()); @@ -2674,9 +2671,11 @@ wxDEFINE_EVENT(EVT_GLCANVAS_RIGHT_CLICK, Vec2dEvent); wxDEFINE_EVENT(EVT_GLCANVAS_MODEL_UPDATE, SimpleEvent); wxDEFINE_EVENT(EVT_GLCANVAS_REMOVE_OBJECT, SimpleEvent); wxDEFINE_EVENT(EVT_GLCANVAS_ARRANGE, SimpleEvent); +#if !ENABLE_EXTENDED_SELECTION wxDEFINE_EVENT(EVT_GLCANVAS_ROTATE_OBJECT, Event); wxDEFINE_EVENT(EVT_GLCANVAS_SCALE_UNIFORMLY, SimpleEvent); -wxDEFINE_EVENT(EVT_GLCANVAS_INCREASE_OBJECTS, Event); +#endif // !ENABLE_EXTENDED_SELECTION +wxDEFINE_EVENT(EVT_GLCANVAS_INCREASE_INSTANCES, Event); wxDEFINE_EVENT(EVT_GLCANVAS_INSTANCE_MOVED, SimpleEvent); wxDEFINE_EVENT(EVT_GLCANVAS_WIPETOWER_MOVED, Vec3dEvent); wxDEFINE_EVENT(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, Event); @@ -3685,24 +3684,26 @@ void GLCanvas3D::on_char(wxKeyEvent& evt) switch (keyCode) { // key + - case 43: { post_event(Event(EVT_GLCANVAS_INCREASE_OBJECTS, +1)); break; } + case 43: { post_event(Event(EVT_GLCANVAS_INCREASE_INSTANCES, +1)); break; } // key - - case 45: { post_event(Event(EVT_GLCANVAS_INCREASE_OBJECTS, -1)); break; } + case 45: { post_event(Event(EVT_GLCANVAS_INCREASE_INSTANCES, -1)); break; } // key A/a case 65: case 97: { post_event(SimpleEvent(EVT_GLCANVAS_ARRANGE)); break; } // key B/b case 66: case 98: { zoom_to_bed(); break; } +#if !ENABLE_EXTENDED_SELECTION // key L/l case 76: case 108: { post_event(Event(EVT_GLCANVAS_ROTATE_OBJECT, -1)); break; } - // key R/r + // key R/r case 82: case 114: { post_event(Event(EVT_GLCANVAS_ROTATE_OBJECT, +1)); break; } - // key S/s + // key S/s case 83: case 115: { post_event(SimpleEvent(EVT_GLCANVAS_SCALE_UNIFORMLY)); break; } +#endif // !ENABLE_EXTENDED_SELECTION // key Z/z case 90: case 122: { zoom_to_volumes(); break; } diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index be9548a494..c4e53cfe2f 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -112,9 +112,11 @@ wxDECLARE_EVENT(EVT_GLCANVAS_RIGHT_CLICK, Vec2dEvent); wxDECLARE_EVENT(EVT_GLCANVAS_MODEL_UPDATE, SimpleEvent); wxDECLARE_EVENT(EVT_GLCANVAS_REMOVE_OBJECT, SimpleEvent); wxDECLARE_EVENT(EVT_GLCANVAS_ARRANGE, SimpleEvent); +#if !ENABLE_EXTENDED_SELECTION wxDECLARE_EVENT(EVT_GLCANVAS_ROTATE_OBJECT, Event); // data: -1 => rotate left, +1 => rotate right wxDECLARE_EVENT(EVT_GLCANVAS_SCALE_UNIFORMLY, SimpleEvent); -wxDECLARE_EVENT(EVT_GLCANVAS_INCREASE_OBJECTS, Event); // data: +1 => increase, -1 => decrease +#endif // !ENABLE_EXTENDED_SELECTION +wxDECLARE_EVENT(EVT_GLCANVAS_INCREASE_INSTANCES, Event); // data: +1 => increase, -1 => decrease wxDECLARE_EVENT(EVT_GLCANVAS_INSTANCE_MOVED, SimpleEvent); wxDECLARE_EVENT(EVT_GLCANVAS_WIPETOWER_MOVED, Vec3dEvent); wxDECLARE_EVENT(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, Event); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 5db983623a..7981d66634 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -781,13 +781,19 @@ struct Plater::priv #endif // ENABLE_EXTENDED_SELECTION void selection_changed(); void object_list_changed(); +#if !ENABLE_EXTENDED_SELECTION void select_view(); +#endif // !ENABLE_EXTENDED_SELECTION void remove(size_t obj_idx); void reset(); +#if !ENABLE_EXTENDED_SELECTION void rotate(); - void mirror(const Axis &axis); +#endif // !ENABLE_EXTENDED_SELECTION + void mirror(Axis axis); +#if !ENABLE_EXTENDED_SELECTION void scale(); +#endif // !ENABLE_EXTENDED_SELECTION void arrange(); void split_object(); void schedule_background_process(); @@ -842,6 +848,9 @@ private: bool can_split_object() const; bool can_cut_object() const; bool layers_height_allowed() const; + bool can_delete_all() const; + bool can_arrange() const; + bool can_mirror() const; #endif // ENABLE_EXTENDED_SELECTION }; @@ -931,9 +940,11 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) : canvas3D->Bind(EVT_GLCANVAS_MODEL_UPDATE, &priv::on_model_update, this); canvas3D->Bind(EVT_GLCANVAS_REMOVE_OBJECT, [q](SimpleEvent&) { q->remove_selected(); }); canvas3D->Bind(EVT_GLCANVAS_ARRANGE, [this](SimpleEvent&) { arrange(); }); +#if !ENABLE_EXTENDED_SELECTION canvas3D->Bind(EVT_GLCANVAS_ROTATE_OBJECT, [this](Event &evt) { /*TODO: call rotate */ }); canvas3D->Bind(EVT_GLCANVAS_SCALE_UNIFORMLY, [this](SimpleEvent&) { scale(); }); - canvas3D->Bind(EVT_GLCANVAS_INCREASE_OBJECTS, [q](Event &evt) { evt.data == 1 ? q->increase() : q->decrease(); }); +#endif // !ENABLE_EXTENDED_SELECTION + canvas3D->Bind(EVT_GLCANVAS_INCREASE_INSTANCES, [q](Event &evt) { evt.data == 1 ? q->increase_instances() : q->decrease_instances(); }); canvas3D->Bind(EVT_GLCANVAS_INSTANCE_MOVED, [this](SimpleEvent&) { update(); }); canvas3D->Bind(EVT_GLCANVAS_WIPETOWER_MOVED, &priv::on_wipetower_moved, this); canvas3D->Bind(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, &priv::on_enable_action_buttons, this); @@ -943,8 +954,8 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) : canvas3D->Bind(EVT_GLTOOLBAR_DELETE, [q](SimpleEvent&) { q->remove_selected(); } ); canvas3D->Bind(EVT_GLTOOLBAR_DELETE_ALL, [this](SimpleEvent&) { reset(); }); canvas3D->Bind(EVT_GLTOOLBAR_ARRANGE, [this](SimpleEvent&) { arrange(); }); - canvas3D->Bind(EVT_GLTOOLBAR_MORE, [q](SimpleEvent&) { q->increase(); }); - canvas3D->Bind(EVT_GLTOOLBAR_FEWER, [q](SimpleEvent&) { q->decrease(); }); + canvas3D->Bind(EVT_GLTOOLBAR_MORE, [q](SimpleEvent&) { q->increase_instances(); }); + canvas3D->Bind(EVT_GLTOOLBAR_FEWER, [q](SimpleEvent&) { q->decrease_instances(); }); canvas3D->Bind(EVT_GLTOOLBAR_SPLIT, &priv::on_action_split, this); canvas3D->Bind(EVT_GLTOOLBAR_CUT, &priv::on_action_cut, this); #if !ENABLE_EXTENDED_SELECTION @@ -1427,25 +1438,31 @@ void Plater::priv::object_list_changed() { // Enable/disable buttons depending on whether there are any objects on the platter. #if ENABLE_EXTENDED_SELECTION - const bool have_objects = !model.objects.empty(); + _3DScene::enable_toolbar_item(canvas3D, "deleteall", can_delete_all()); + _3DScene::enable_toolbar_item(canvas3D, "arrange", can_arrange()); #else const bool have_objects = !objects.empty(); -#endif // ENABLE_EXTENDED_SELECTION - _3DScene::enable_toolbar_item(canvas3D, "deleteall", have_objects); _3DScene::enable_toolbar_item(canvas3D, "arrange", have_objects); +#endif // ENABLE_EXTENDED_SELECTION const bool export_in_progress = !(export_gcode_output_file.empty() && send_gcode_file.empty()); // XXX: is this right? const bool model_fits = _3DScene::check_volumes_outside_state(canvas3D, config) == ModelInstance::PVS_Inside; +#if ENABLE_EXTENDED_SELECTION + sidebar->enable_buttons(!model.objects.empty() && !export_in_progress && model_fits); +#else sidebar->enable_buttons(have_objects && !export_in_progress && model_fits); +#endif // ENABLE_EXTENDED_SELECTION } +#if !ENABLE_EXTENDED_SELECTION void Plater::priv::select_view() { // TODO } +#endif // !ENABLE_EXTENDED_SELECTION void Plater::priv::remove(size_t obj_idx) { @@ -1493,12 +1510,14 @@ void Plater::priv::reset() update(); } +#if !ENABLE_EXTENDED_SELECTION void Plater::priv::rotate() { // TODO } +#endif // !ENABLE_EXTENDED_SELECTION -void Plater::priv::mirror(const Axis &axis) +void Plater::priv::mirror(Axis axis) { #if ENABLE_EXTENDED_SELECTION int obj_idx = get_selected_object_idx(); @@ -1534,10 +1553,12 @@ void Plater::priv::mirror(const Axis &axis) update(); } +#if !ENABLE_EXTENDED_SELECTION void Plater::priv::scale() { // TODO } +#endif // !ENABLE_EXTENDED_SELECTION void Plater::priv::arrange() { @@ -1825,9 +1846,9 @@ bool Plater::priv::init_object_menu() wxMenuItem* item_delete = append_menu_item(&object_menu, wxID_ANY, _(L("Delete\tDel")), _(L("Remove the selected object")), [this](wxCommandEvent&){ q->remove_selected(); }, "brick_delete.png"); wxMenuItem* item_increase = append_menu_item(&object_menu, wxID_ANY, _(L("Increase copies\t+")), _(L("Place one more copy of the selected object")), - [this](wxCommandEvent&){ q->increase(); }, "add.png"); + [this](wxCommandEvent&){ q->increase_instances(); }, "add.png"); wxMenuItem* item_decrease = append_menu_item(&object_menu, wxID_ANY, _(L("Decrease copies\t-")), _(L("Remove one copy of the selected object")), - [this](wxCommandEvent&){ q->decrease(); }, "delete.png"); + [this](wxCommandEvent&){ q->decrease_instances(); }, "delete.png"); object_menu.AppendSeparator(); @@ -1848,6 +1869,7 @@ bool Plater::priv::init_object_menu() // ui updates needs to be binded to the parent panel if (q != nullptr) { + q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_mirror()); }, item_mirror->GetId()); q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_delete_object()); }, item_delete->GetId()); q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_increase_instances()); }, item_increase->GetId()); q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_decrease_instances()); }, item_decrease->GetId()); @@ -1892,6 +1914,21 @@ bool Plater::priv::layers_height_allowed() const { return config->opt_bool("variable_layer_height") && _3DScene::is_layers_editing_allowed(canvas3D); } + +bool Plater::priv::can_delete_all() const +{ + return !model.objects.empty(); +} + +bool Plater::priv::can_arrange() const +{ + return !model.objects.empty(); +} + +bool Plater::priv::can_mirror() const +{ + return get_selection().is_from_single_instance(); +} #endif // ENABLE_EXTENDED_SELECTION // Plater / Public @@ -1945,7 +1982,7 @@ void Plater::remove_selected() #endif // ENABLE_EXTENDED_SELECTION } -void Plater::increase(size_t num) +void Plater::increase_instances(size_t num) { #if ENABLE_EXTENDED_SELECTION int obj_idx = p->get_selected_object_idx(); @@ -1992,7 +2029,7 @@ void Plater::increase(size_t num) // $self->schedule_background_process; } -void Plater::decrease(size_t num) +void Plater::decrease_instances(size_t num) { #if ENABLE_EXTENDED_SELECTION int obj_idx = p->get_selected_object_idx(); @@ -2051,11 +2088,10 @@ void Plater::set_number_of_copies(size_t num) #endif // ENABLE_EXTENDED_SELECTION int diff = (int)num - (int)model_object->instances.size(); - if (diff > 0) { - increase(diff); - } else if (diff < 0) { - decrease(-diff); - } + if (diff > 0) + increase_instances(diff); + else if (diff < 0) + decrease_instances(-diff); } fs::path Plater::export_gcode(const fs::path &output_path) diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index eeb3123cd3..3beda1270b 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -113,8 +113,8 @@ public: void remove(size_t obj_idx); void remove_selected(); - void increase(size_t num = 1); - void decrease(size_t num = 1); + void increase_instances(size_t num = 1); + void decrease_instances(size_t num = 1); void set_number_of_copies(size_t num); // Note: empty path means "use the default" From fbbe1325b618b345679af3590857cc28a33f3e38 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Thu, 18 Oct 2018 15:50:51 +0200 Subject: [PATCH 130/186] Mirror transform components in ModelInstance and GLvolume - WIP and disabled --- src/libslic3r/Geometry.cpp | 15 ++++++ src/libslic3r/Geometry.hpp | 20 ++++++++ src/libslic3r/Model.cpp | 41 ++++++++++++++++ src/libslic3r/Model.hpp | 26 ++++++++++ src/libslic3r/Technologies.hpp | 2 + src/slic3r/GUI/3DScene.cpp | 53 ++++++++++++++++++++ src/slic3r/GUI/3DScene.hpp | 17 +++++++ src/slic3r/GUI/GLCanvas3D.cpp | 72 ++++++++++++++++++++++++++++ src/slic3r/GUI/GLCanvas3D.hpp | 12 +++++ src/slic3r/GUI/GLCanvas3DManager.cpp | 11 +++++ src/slic3r/GUI/GLCanvas3DManager.hpp | 6 +++ src/slic3r/GUI/Plater.cpp | 6 +++ 12 files changed, 281 insertions(+) diff --git a/src/libslic3r/Geometry.cpp b/src/libslic3r/Geometry.cpp index c45f087919..a100f520a9 100644 --- a/src/libslic3r/Geometry.cpp +++ b/src/libslic3r/Geometry.cpp @@ -1166,7 +1166,11 @@ MedialAxis::retrieve_endpoint(const VD::cell_type* cell) const } } +#if ENABLE_MIRROR +void assemble_transform(Transform3d& transform, const Vec3d& translation, const Vec3d& rotation, const Vec3d& scale, const Vec3d& mirror) +#else void assemble_transform(Transform3d& transform, const Vec3d& translation, const Vec3d& rotation, const Vec3d& scale) +#endif // ENABLE_MIRROR { transform = Transform3d::Identity(); transform.translate(translation); @@ -1174,12 +1178,23 @@ void assemble_transform(Transform3d& transform, const Vec3d& translation, const transform.rotate(Eigen::AngleAxisd(rotation(1), Vec3d::UnitY())); transform.rotate(Eigen::AngleAxisd(rotation(0), Vec3d::UnitX())); transform.scale(scale); +#if ENABLE_MIRROR + transform.scale(mirror); +#endif // ENABLE_MIRROR } +#if ENABLE_MIRROR +Transform3d assemble_transform(const Vec3d& translation, const Vec3d& rotation, const Vec3d& scale, const Vec3d& mirror) +#else Transform3d assemble_transform(const Vec3d& translation, const Vec3d& rotation, const Vec3d& scale) +#endif // ENABLE_MIRROR { Transform3d transform; +#if ENABLE_MIRROR + assemble_transform(transform, translation, rotation, scale, mirror); +#else assemble_transform(transform, translation, rotation, scale); +#endif // ENABLE_MIRROR return transform; } diff --git a/src/libslic3r/Geometry.hpp b/src/libslic3r/Geometry.hpp index 35f59bdfd7..9046add258 100644 --- a/src/libslic3r/Geometry.hpp +++ b/src/libslic3r/Geometry.hpp @@ -158,20 +158,40 @@ class MedialAxis { }; // Sets the given transform by assembling the given transformations in the following order: +#if ENABLE_MIRROR +// 1) mirror +// 2) scale +// 3) rotate X +// 4) rotate Y +// 5) rotate Z +// 6) translate +void assemble_transform(Transform3d& transform, const Vec3d& translation = Vec3d::Zero(), const Vec3d& rotation = Vec3d::Zero(), const Vec3d& scale = Vec3d::Ones(), const Vec3d& mirror = Vec3d::Ones()); +#else // 1) scale // 2) rotate X // 3) rotate Y // 4) rotate Z // 5) translate void assemble_transform(Transform3d& transform, const Vec3d& translation = Vec3d::Zero(), const Vec3d& rotation = Vec3d::Zero(), const Vec3d& scale = Vec3d::Ones()); +#endif // ENABLE_MIRROR // Returns the transform obtained by assembling the given transformations in the following order: +#if ENABLE_MIRROR +// 1) mirror +// 2) scale +// 3) rotate X +// 4) rotate Y +// 5) rotate Z +// 6) translate +Transform3d assemble_transform(const Vec3d& translation = Vec3d::Zero(), const Vec3d& rotation = Vec3d::Zero(), const Vec3d& scale = Vec3d::Ones(), const Vec3d& mirror = Vec3d::Ones()); +#else // 1) scale // 2) rotate X // 3) rotate Y // 4) rotate Z // 5) translate Transform3d assemble_transform(const Vec3d& translation = Vec3d::Zero(), const Vec3d& rotation = Vec3d::Zero(), const Vec3d& scale = Vec3d::Ones()); +#endif // ENABLE_MIRROR // Returns the euler angles extracted from the given rotation matrix // Warning -> The matrix should not contain any scale or shear !!! diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index dc2c37c7fd..8e2d1f391c 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -1080,6 +1080,38 @@ void ModelInstance::set_rotation(Axis axis, double rotation) m_rotation(axis) = rotation; } +#if ENABLE_MIRROR +void ModelInstance::set_scaling_factor(const Vec3d& scaling_factor) +{ + set_scaling_factor(X, scaling_factor(0)); + set_scaling_factor(Y, scaling_factor(1)); + set_scaling_factor(Z, scaling_factor(2)); +} + +void ModelInstance::set_scaling_factor(Axis axis, double scaling_factor) +{ + m_scaling_factor(axis) = std::abs(scaling_factor); +} + +void ModelInstance::set_mirror(const Vec3d& mirror) +{ + set_mirror(X, mirror(0)); + set_mirror(Y, mirror(1)); + set_mirror(Z, mirror(2)); +} + +void ModelInstance::set_mirror(Axis axis, double mirror) +{ + double abs_mirror = std::abs(mirror); + if (abs_mirror == 0.0) + mirror = 1.0; + else if (abs_mirror != 1.0) + mirror /= abs_mirror; + + m_mirror(axis) = mirror; +} +#endif // ENABLE_MIRROR + void ModelInstance::transform_mesh(TriangleMesh* mesh, bool dont_translate) const { mesh->transform(world_matrix(dont_translate).cast()); @@ -1130,12 +1162,21 @@ void ModelInstance::transform_polygon(Polygon* polygon) const polygon->scale(this->m_scaling_factor(0), this->m_scaling_factor(1)); // scale around polygon origin } +#if ENABLE_MIRROR +Transform3d ModelInstance::world_matrix(bool dont_translate, bool dont_rotate, bool dont_scale, bool dont_mirror) const +#else Transform3d ModelInstance::world_matrix(bool dont_translate, bool dont_rotate, bool dont_scale) const +#endif // ENABLE_MIRROR { Vec3d translation = dont_translate ? Vec3d::Zero() : m_offset; Vec3d rotation = dont_rotate ? Vec3d::Zero() : m_rotation; Vec3d scale = dont_scale ? Vec3d::Ones() : m_scaling_factor; +#if ENABLE_MIRROR + Vec3d mirror = dont_mirror ? Vec3d::Ones() : m_mirror; + return Geometry::assemble_transform(translation, rotation, scale, mirror); +#else return Geometry::assemble_transform(translation, rotation, scale); +#endif // ENABLE_MIRROR } } diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index 7fd889ffb8..6c34292d31 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -251,6 +251,9 @@ private: Vec3d m_offset; // in unscaled coordinates Vec3d m_rotation; // Rotation around the three axes, in radians around mesh center point Vec3d m_scaling_factor; // Scaling factors along the three axes +#if ENABLE_MIRROR + Vec3d m_mirror; // Mirroring along the three axes +#endif // ENABLE_MIRROR public: // flag showing the position of this instance with respect to the print volume (set by Print::validate() using ModelObject::check_instances_print_volume_state()) @@ -273,8 +276,21 @@ public: Vec3d get_scaling_factor() const { return m_scaling_factor; } double get_scaling_factor(Axis axis) const { return m_scaling_factor(axis); } +#if ENABLE_MIRROR + void set_scaling_factor(const Vec3d& scaling_factor); + void set_scaling_factor(Axis axis, double scaling_factor); +#else void set_scaling_factor(const Vec3d& scaling_factor) { m_scaling_factor = scaling_factor; } void set_scaling_factor(Axis axis, double scaling_factor) { m_scaling_factor(axis) = scaling_factor; } +#endif // ENABLE_MIRROR + +#if ENABLE_MIRROR + const Vec3d& get_mirror() const { return m_mirror; } + double get_mirror(Axis axis) const { return m_mirror(axis); } + + void set_mirror(const Vec3d& mirror); + void set_mirror(Axis axis, double mirror); +#endif // ENABLE_MIRROR // To be called on an external mesh void transform_mesh(TriangleMesh* mesh, bool dont_translate = false) const; @@ -287,7 +303,11 @@ public: // To be called on an external polygon. It does not translate the polygon, only rotates and scales. void transform_polygon(Polygon* polygon) const; +#if ENABLE_MIRROR + Transform3d world_matrix(bool dont_translate = false, bool dont_rotate = false, bool dont_scale = false, bool dont_mirror = false) const; +#else Transform3d world_matrix(bool dont_translate = false, bool dont_rotate = false, bool dont_scale = false) const; +#endif // ENABLE_MIRROR bool is_printable() const { return print_volume_state == PVS_Inside; } @@ -295,9 +315,15 @@ private: // Parent object, owning this instance. ModelObject* object; +#if ENABLE_MIRROR + ModelInstance(ModelObject *object) : m_offset(Vec3d::Zero()), m_rotation(Vec3d::Zero()), m_scaling_factor(Vec3d::Ones()), m_mirror(Vec3d::Ones()), object(object), print_volume_state(PVS_Inside) {} + ModelInstance(ModelObject *object, const ModelInstance &other) : + m_offset(other.m_offset), m_rotation(other.m_rotation), m_scaling_factor(other.m_scaling_factor), m_mirror(other.m_mirror), object(object), print_volume_state(PVS_Inside) {} +#else ModelInstance(ModelObject *object) : m_rotation(Vec3d::Zero()), m_scaling_factor(Vec3d::Ones()), m_offset(Vec3d::Zero()), object(object), print_volume_state(PVS_Inside) {} ModelInstance(ModelObject *object, const ModelInstance &other) : m_rotation(other.m_rotation), m_scaling_factor(other.m_scaling_factor), m_offset(other.m_offset), object(object), print_volume_state(PVS_Inside) {} +#endif // ENABLE_MIRROR }; diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index 4c653e543e..3f8fd80f0b 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -10,6 +10,8 @@ #define ENABLE_USE_UNIQUE_GLCONTEXT (1 && ENABLE_1_42_0) // New selections #define ENABLE_EXTENDED_SELECTION (1 && ENABLE_1_42_0) +// Add mirror components along the three axes in ModelInstance and GLVolume +#define ENABLE_MIRROR (0 && ENABLE_1_42_0) #endif // _technologies_h_ diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index 402d7b8ee9..91f60947c5 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -198,6 +198,9 @@ GLVolume::GLVolume(float r, float g, float b, float a) : m_offset(Vec3d::Zero()) , m_rotation(Vec3d::Zero()) , m_scaling_factor(Vec3d::Ones()) +#if ENABLE_MIRROR + , m_mirror(Vec3d::Ones()) +#endif // ENABLE_MIRROR , m_world_matrix(Transform3f::Identity()) , m_world_matrix_dirty(true) , m_transformed_bounding_box_dirty(true) @@ -324,6 +327,40 @@ void GLVolume::set_scaling_factor(const Vec3d& scaling_factor) } } +#if ENABLE_MIRROR +const Vec3d& GLVolume::get_mirror() const +{ + return m_mirror; +} + +double GLVolume::get_mirror(Axis axis) const +{ + return m_mirror(axis); +} + +void GLVolume::set_mirror(const Vec3d& mirror) +{ + if (m_mirror != mirror) + { + m_mirror = mirror; + m_world_matrix_dirty = true; + m_transformed_bounding_box_dirty = true; + m_transformed_convex_hull_bounding_box_dirty = true; + } +} + +void GLVolume::set_mirror(Axis axis, double mirror) +{ + if (m_mirror(axis) != mirror) + { + m_mirror(axis) = mirror; + m_world_matrix_dirty = true; + m_transformed_bounding_box_dirty = true; + m_transformed_convex_hull_bounding_box_dirty = true; + } +} +#endif // ENABLE_MIRROR + void GLVolume::set_convex_hull(const TriangleMesh& convex_hull) { m_convex_hull = &convex_hull; @@ -353,7 +390,11 @@ const Transform3f& GLVolume::world_matrix() const { if (m_world_matrix_dirty) { +#if ENABLE_MIRROR + m_world_matrix = Geometry::assemble_transform(m_offset, m_rotation, m_scaling_factor, m_mirror).cast(); +#else m_world_matrix = Geometry::assemble_transform(m_offset, m_rotation, m_scaling_factor).cast(); +#endif // ENABLE_MIRROR m_world_matrix_dirty = false; } return m_world_matrix; @@ -729,6 +770,9 @@ std::vector GLVolumeCollection::load_object( v.set_offset(instance->get_offset()); v.set_rotation(instance->get_rotation()); v.set_scaling_factor(instance->get_scaling_factor()); +#if ENABLE_MIRROR + v.set_mirror(instance->get_mirror()); +#endif // ENABLE_MIRROR } } @@ -2076,6 +2120,15 @@ int _3DScene::get_in_object_volume_id(wxGLCanvas* canvas, int scene_vol_idx) return s_canvas_mgr.get_in_object_volume_id(canvas, scene_vol_idx); } +#if ENABLE_MIRROR +#if ENABLE_EXTENDED_SELECTION +void _3DScene::mirror_selection(wxGLCanvas* canvas, Axis axis) +{ + s_canvas_mgr.mirror_selection(canvas, axis); +} +#endif // ENABLE_EXTENDED_SELECTION +#endif // ENABLE_MIRROR + void _3DScene::reload_scene(wxGLCanvas* canvas, bool force) { s_canvas_mgr.reload_scene(canvas, force); diff --git a/src/slic3r/GUI/3DScene.hpp b/src/slic3r/GUI/3DScene.hpp index e3f7ea0d36..7e74ff92f2 100644 --- a/src/slic3r/GUI/3DScene.hpp +++ b/src/slic3r/GUI/3DScene.hpp @@ -260,6 +260,10 @@ private: Vec3d m_rotation; // Scale factor along the three axes of the volume to be rendered. Vec3d m_scaling_factor; +#if ENABLE_MIRROR + // Mirroring along the three axes of the volume to be rendered. + Vec3d m_mirror; +#endif // ENABLE_MIRROR // World matrix of the volume to be rendered. mutable Transform3f m_world_matrix; // Whether or not is needed to recalculate the world matrix. @@ -337,6 +341,13 @@ public: #endif // ENABLE_EXTENDED_SELECTION void set_scaling_factor(const Vec3d& scaling_factor); +#if ENABLE_MIRROR + const Vec3d& get_mirror() const; + double get_mirror(Axis axis) const; + void set_mirror(const Vec3d& mirror); + void set_mirror(Axis axis, double mirror); +#endif // ENABLE_MIRROR + const Vec3d& get_offset() const; void set_offset(const Vec3d& offset); @@ -581,6 +592,12 @@ public: static int get_first_volume_id(wxGLCanvas* canvas, int obj_idx); static int get_in_object_volume_id(wxGLCanvas* canvas, int scene_vol_idx); +#if ENABLE_MIRROR +#if ENABLE_EXTENDED_SELECTION + static void mirror_selection(wxGLCanvas* canvas, Axis axis); +#endif // ENABLE_EXTENDED_SELECTION +#endif // ENABLE_MIRROR + static void reload_scene(wxGLCanvas* canvas, bool force); static void load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* preview_data, const std::vector& str_tool_colors); diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 12cd32d560..6dce5cd16c 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1457,6 +1457,25 @@ void GLCanvas3D::Selection::scale(const Vec3d& scale) m_bounding_box_dirty = true; } +#if ENABLE_MIRROR +void GLCanvas3D::Selection::mirror(Axis axis) +{ + if (!m_valid) + return; + + for (unsigned int i : m_list) + { + if (is_single_full_instance()) + (*m_volumes)[i]->set_mirror(axis, -(*m_volumes)[i]->get_mirror(axis)); + } + + if (m_mode == Instance) + _synchronize_unselected_instances(); + + m_bounding_box_dirty = true; +} +#endif // ENABLE_MIRROR + void GLCanvas3D::Selection::render(bool show_indirect_selection) const { if (is_empty()) @@ -1780,6 +1799,9 @@ void GLCanvas3D::Selection::_synchronize_unselected_instances() int instance_idx = volume->instance_idx(); const Vec3d& rotation = volume->get_rotation(); const Vec3d& scaling_factor = volume->get_scaling_factor(); +#if ENABLE_MIRROR + const Vec3d& mirror = volume->get_mirror(); +#endif // ENABLE_MIRROR // Process unselected instances. for (unsigned int j = 0; j < (unsigned int)m_volumes->size(); ++j) @@ -1796,6 +1818,9 @@ void GLCanvas3D::Selection::_synchronize_unselected_instances() v->set_rotation(rotation); v->set_scaling_factor(scaling_factor); +#if ENABLE_MIRROR + v->set_mirror(mirror); +#endif // ENABLE_MIRROR done.insert(j); } @@ -3403,6 +3428,18 @@ int GLCanvas3D::get_in_object_volume_id(int scene_vol_idx) const return ((0 <= scene_vol_idx) && (scene_vol_idx < (int)m_volumes.volumes.size())) ? m_volumes.volumes[scene_vol_idx]->volume_idx() : -1; } +#if ENABLE_MIRROR +#if ENABLE_EXTENDED_SELECTION +void GLCanvas3D::mirror_selection(Axis axis) +{ + m_regenerate_volumes = false; + m_selection.mirror(axis); + _on_mirror(); + wxGetApp().obj_manipul()->update_settings_value(m_selection); +} +#endif // ENABLE_EXTENDED_SELECTION +#endif // ENABLE_MIRROR + void GLCanvas3D::reload_scene(bool force) { if ((m_canvas == nullptr) || (m_config == nullptr) || (m_model == nullptr)) @@ -6525,6 +6562,41 @@ void GLCanvas3D::_on_flatten() _on_rotate(); } +#if ENABLE_MIRROR +void GLCanvas3D::_on_mirror() +{ + if (m_model == nullptr) + return; + + std::set> done; // prevent mirroring instances twice + + for (const GLVolume* v : m_volumes.volumes) + { + int object_idx = v->object_idx(); + if (object_idx >= 1000) + continue; + + int instance_idx = v->instance_idx(); + + // prevent mirroring instances twice + std::pair done_id(object_idx, instance_idx); + if (done.find(done_id) != done.end()) + continue; + + done.insert(done_id); + + // Mirror instances. + ModelObject* model_object = m_model->objects[object_idx]; + if (model_object != nullptr) + { + model_object->instances[instance_idx]->set_mirror(v->get_mirror()); + model_object->invalidate_bounding_box(); + } + } + + // schedule_background_process +} +#endif // ENABLE_MIRROR #else void GLCanvas3D::_on_move(const std::vector& volume_idxs) { diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index c4e53cfe2f..58b414c8d9 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -501,6 +501,9 @@ public: void translate(const Vec3d& displacement); void rotate(const Vec3d& rotation); void scale(const Vec3d& scale); +#if ENABLE_MIRROR + void mirror(Axis axis); +#endif // ENABLE_MIRROR void render(bool show_indirect_selection) const; @@ -833,6 +836,12 @@ public: int get_first_volume_id(int obj_idx) const; int get_in_object_volume_id(int scene_vol_idx) const; +#if ENABLE_MIRROR +#if ENABLE_EXTENDED_SELECTION + void mirror_selection(Axis axis); +#endif // ENABLE_EXTENDED_SELECTION +#endif // ENABLE_MIRROR + void reload_scene(bool force); void load_gcode_preview(const GCodePreviewData& preview_data, const std::vector& str_tool_colors); @@ -955,6 +964,9 @@ private: void _on_rotate(); void _on_scale(); void _on_flatten(); +#if ENABLE_MIRROR + void _on_mirror(); +#endif // ENABLE_MIRROR #else void _on_move(const std::vector& volume_idxs); #endif // ENABLE_EXTENDED_SELECTION diff --git a/src/slic3r/GUI/GLCanvas3DManager.cpp b/src/slic3r/GUI/GLCanvas3DManager.cpp index 182298a690..1d963e3b7b 100644 --- a/src/slic3r/GUI/GLCanvas3DManager.cpp +++ b/src/slic3r/GUI/GLCanvas3DManager.cpp @@ -596,6 +596,17 @@ int GLCanvas3DManager::get_in_object_volume_id(wxGLCanvas* canvas, int scene_vol return (it != m_canvases.end()) ? it->second->get_in_object_volume_id(scene_vol_idx) : -1; } +#if ENABLE_MIRROR +#if ENABLE_EXTENDED_SELECTION +void GLCanvas3DManager::mirror_selection(wxGLCanvas* canvas, Axis axis) +{ + CanvasesMap::iterator it = _get_canvas(canvas); + if (it != m_canvases.end()) + it->second->mirror_selection(axis); +} +#endif // ENABLE_EXTENDED_SELECTION +#endif // ENABLE_MIRROR + void GLCanvas3DManager::reload_scene(wxGLCanvas* canvas, bool force) { CanvasesMap::iterator it = _get_canvas(canvas); diff --git a/src/slic3r/GUI/GLCanvas3DManager.hpp b/src/slic3r/GUI/GLCanvas3DManager.hpp index 2261a57b2b..89cb09e7f0 100644 --- a/src/slic3r/GUI/GLCanvas3DManager.hpp +++ b/src/slic3r/GUI/GLCanvas3DManager.hpp @@ -163,6 +163,12 @@ public: int get_first_volume_id(wxGLCanvas* canvas, int obj_idx) const; int get_in_object_volume_id(wxGLCanvas* canvas, int scene_vol_idx) const; +#if ENABLE_MIRROR +#if ENABLE_EXTENDED_SELECTION + void mirror_selection(wxGLCanvas* canvas, Axis axis); +#endif // ENABLE_EXTENDED_SELECTION +#endif // ENABLE_MIRROR + void reload_scene(wxGLCanvas* canvas, bool force); void load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* preview_data, const std::vector& str_tool_colors); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 7981d66634..40fffc85ba 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1519,6 +1519,11 @@ void Plater::priv::rotate() void Plater::priv::mirror(Axis axis) { +#if ENABLE_MIRROR +#if ENABLE_EXTENDED_SELECTION + _3DScene::mirror_selection(canvas3D, axis); +#endif // ENABLE_EXTENDED_SELECTION +#else #if ENABLE_EXTENDED_SELECTION int obj_idx = get_selected_object_idx(); if (obj_idx == -1) @@ -1551,6 +1556,7 @@ void Plater::priv::mirror(Axis axis) #endif // ENABLE_EXTENDED_SELECTION selection_changed(); update(); +#endif // ENABLE_MIRROR } #if !ENABLE_EXTENDED_SELECTION From a45e9c0a03ef9eddd8adf84d8cb9efab6c795d38 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Thu, 18 Oct 2018 18:06:40 +0200 Subject: [PATCH 131/186] WIP: Slicing from GUI. --- src/libslic3r/GCode.cpp | 2 +- src/libslic3r/Model.cpp | 49 ++----- src/libslic3r/Model.hpp | 9 +- src/slic3r/GUI/BackgroundSlicingProcess.cpp | 11 +- src/slic3r/GUI/BackgroundSlicingProcess.hpp | 4 + src/slic3r/GUI/Plater.cpp | 148 ++++++++++++++++++-- 6 files changed, 167 insertions(+), 56 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 0acbdd1230..c4d0c1bd93 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -1238,7 +1238,7 @@ void GCode::process_layer( const size_t single_object_idx) { assert(! layers.empty()); - assert(! layer_tools.extruders.empty()); +// assert(! layer_tools.extruders.empty()); // Either printing all copies of all objects, or just a single copy of a single object. assert(single_object_idx == size_t(-1) || layers.size() == 1); diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index c8c1991d61..bc99350861 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -19,33 +19,28 @@ namespace Slic3r { - unsigned int Model::s_auto_extruder_id = 1; +unsigned int Model::s_auto_extruder_id = 1; ModelID ModelBase::s_last_id = 0; -Model::Model(const Model &other) +Model::Model(const Model &rhs) { + *this = rhs; +} + +Model& Model::operator=(const Model &rhs) +{ + m_id = rhs.m_id; // copy materials - for (const auto &m : other.materials) + for (const auto &m : rhs.materials) this->add_material(m.first, *m.second); // copy objects - this->objects.reserve(other.objects.size()); - for (const ModelObject *o : other.objects) + this->objects.reserve(rhs.objects.size()); + for (const ModelObject *o : rhs.objects) this->add_object(*o, true); -} - -Model& Model::operator=(Model other) -{ - this->swap(other); return *this; } -void Model::swap(Model &other) -{ - std::swap(this->materials, other.materials); - std::swap(this->objects, other.objects); -} - Model Model::read_from_file(const std::string &input_file, DynamicPrintConfig *config, bool add_default_instances) { Model model; @@ -499,33 +494,11 @@ ModelObject::ModelObject(Model *model, const ModelObject &other, bool copy_volum for (ModelVolume *model_volume : other.volumes) this->add_volume(*model_volume); } - this->instances.reserve(other.instances.size()); for (const ModelInstance *model_instance : other.instances) this->add_instance(*model_instance); } -ModelObject& ModelObject::operator=(ModelObject other) -{ - this->swap(other); - return *this; -} - -void ModelObject::swap(ModelObject &other) -{ - std::swap(this->m_id, other.m_id); - std::swap(this->input_file, other.input_file); - std::swap(this->instances, other.instances); - std::swap(this->volumes, other.volumes); - std::swap(this->config, other.config); - std::swap(this->layer_height_ranges, other.layer_height_ranges); - std::swap(this->layer_height_profile, other.layer_height_profile); - std::swap(this->layer_height_profile_valid, other.layer_height_profile_valid); - std::swap(this->origin_translation, other.origin_translation); - std::swap(m_bounding_box, other.m_bounding_box); - std::swap(m_bounding_box_valid, other.m_bounding_box_valid); -} - ModelObject::~ModelObject() { this->clear_volumes(); diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index ece52c3dc3..4ca7e140c9 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -37,6 +37,8 @@ typedef size_t ModelID; // Base for Model, ModelObject, ModelVolume, ModelInstance or ModelMaterial to provide a unique ID // to synchronize the front end (UI) with the back end (BackgroundSlicingProcess / Print / PrintObject). +// Achtung! The s_last_id counter is not thread safe, so it is expected, that the ModelBase derived instances +// are only instantiated from the main thread. class ModelBase { public: @@ -168,8 +170,6 @@ protected: private: ModelObject(Model *model) : layer_height_profile_valid(false), m_model(model), origin_translation(Vec3d::Zero()), m_bounding_box_valid(false) {} ModelObject(Model *model, const ModelObject &other, bool copy_volumes = true); - ModelObject& operator= (ModelObject other); - void swap(ModelObject &other); ~ModelObject(); // Parent object, owning this ModelObject. @@ -352,9 +352,8 @@ public: ModelObjectPtrs objects; Model() {} - Model(const Model &other); - Model& operator= (Model other); - void swap(Model &other); + Model(const Model &rhs); + Model& operator=(const Model &rhs); ~Model() { this->clear_objects(); this->clear_materials(); } // XXX: use fs::path ? diff --git a/src/slic3r/GUI/BackgroundSlicingProcess.cpp b/src/slic3r/GUI/BackgroundSlicingProcess.cpp index aa6c922aaf..7c4a4c0399 100644 --- a/src/slic3r/GUI/BackgroundSlicingProcess.cpp +++ b/src/slic3r/GUI/BackgroundSlicingProcess.cpp @@ -136,7 +136,7 @@ bool BackgroundSlicingProcess::stop() this->m_output_path.clear(); return false; } - assert(this->running()); +// assert(this->running()); if (m_state == STATE_STARTED || m_state == STATE_RUNNING) { m_print->cancel(); // Wait until the background processing stops by being canceled. @@ -160,4 +160,13 @@ bool BackgroundSlicingProcess::apply_config(const DynamicPrintConfig &config) return invalidated; } +// Apply config over the print. Returns false, if the new config values caused any of the already +// processed steps to be invalidated, therefore the task will need to be restarted. +bool BackgroundSlicingProcess::apply(const Model &model, const DynamicPrintConfig &config) +{ + this->stop(); + bool invalidated = m_print->apply(model, config); + return invalidated; +} + }; // namespace Slic3r diff --git a/src/slic3r/GUI/BackgroundSlicingProcess.hpp b/src/slic3r/GUI/BackgroundSlicingProcess.hpp index cc7a6db307..758acd682a 100644 --- a/src/slic3r/GUI/BackgroundSlicingProcess.hpp +++ b/src/slic3r/GUI/BackgroundSlicingProcess.hpp @@ -10,6 +10,7 @@ namespace Slic3r { class DynamicPrintConfig; class GCodePreviewData; +class Model; class Print; // Support for the GUI background processing (Slicing and G-code generation). @@ -42,6 +43,9 @@ public: // Apply config over the print. Returns false, if the new config values caused any of the already // processed steps to be invalidated, therefore the task will need to be restarted. bool apply_config(const DynamicPrintConfig &config); + // Apply config over the print. Returns false, if the new config values caused any of the already + // processed steps to be invalidated, therefore the task will need to be restarted. + bool apply(const Model &model, const DynamicPrintConfig &config); enum State { // m_thread is not running yet, or it did not reach the STATE_IDLE yet (it does not wait on the condition yet). diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 37b1aa400d..b62194b3dc 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1199,8 +1199,8 @@ std::vector Plater::priv::load_model_objects(const ModelObjectPtrs &mode } } - print.auto_assign_extruders(object); - print.add_model_object(object); + // print.auto_assign_extruders(object); + // print.add_model_object(object); } // if user turned autocentering off, automatic arranging would disappoint them @@ -1520,9 +1520,9 @@ void Plater::priv::mirror(const Axis &axis) // $self->stop_background_process; // TODO #if ENABLE_EXTENDED_SELECTION - print.add_model_object(model_object, obj_idx); +// print.add_model_object(model_object, obj_idx); #else - print.add_model_object(model_object, *obj_idx); +// print.add_model_object(model_object, *obj_idx); #endif // ENABLE_EXTENDED_SELECTION selection_changed(); update(); @@ -1560,7 +1560,7 @@ void Plater::priv::async_apply_config() { // Apply new config to the possibly running background task. bool was_running = this->background_process.running(); - bool invalidated = this->background_process.apply_config(wxGetApp().preset_bundle->full_config()); + bool invalidated = this->background_process.apply(this->q->model(), wxGetApp().preset_bundle->full_config()); // Just redraw the 3D canvas without reloading the scene to consume the update of the layer height profile. if (Slic3r::_3DScene::is_layers_editing_enabled(this->canvas3D)) this->canvas3D->Refresh(); @@ -1580,9 +1580,11 @@ void Plater::priv::async_apply_config() this->preview->reload_print(); // We also need to reload 3D scene because of the wipe tower preview box if (this->config->opt_bool("wipe_tower")) { +#if !ENABLE_EXTENDED_SELECTION std::vector selections = this->collect_selections(); Slic3r::_3DScene::set_objects_selections(this->canvas3D, selections); Slic3r::_3DScene::reload_scene(this->canvas3D, 1); +#endif /* !ENABLE_EXTENDED_SELECTION */ } } } @@ -1590,12 +1592,26 @@ void Plater::priv::async_apply_config() void Plater::priv::start_background_process() { - // TODO + // return if ! @{$self->{objects}} || $self->{background_slicing_process}->running; + // Don't start process thread if config is not valid. + std::string err = wxGetApp().preset_bundle->full_config().validate(); + if (err.empty()) + err = this->q->print().validate(); + if (! err.empty()) { + // $self->statusbar->SetStatusText(err); + return; + } + // Copy the names of active presets into the placeholder parser. + wxGetApp().preset_bundle->export_selections(this->q->print().placeholder_parser()); + // Start the background process. + this->background_process.start(); } void Plater::priv::stop_background_process() { - // TODO + this->background_process.stop(); + if (this->preview != nullptr) + this->preview->reload_print(); } void Plater::priv::reload_from_disk() @@ -1610,7 +1626,33 @@ void Plater::priv::export_object_stl() void Plater::priv::fix_through_netfabb() { - // TODO +/* + my ($self) = @_; + my ($obj_idx, $object) = $self->selected_object; + return if !defined $obj_idx; + my $model_object = $self->{model}->objects->[$obj_idx]; + my $model_fixed = Slic3r::Model->new; + Slic3r::GUI::fix_model_by_win10_sdk_gui($model_object, $self->{print}, $model_fixed); + + my @new_obj_idx = $self->load_model_objects(@{$model_fixed->objects}); + return if !@new_obj_idx; + + foreach my $new_obj_idx (@new_obj_idx) { + my $o = $self->{model}->objects->[$new_obj_idx]; + $o->clear_instances; + $o->add_instance($_) for @{$model_object->instances}; + #$o->invalidate_bounding_box; + + if ($o->volumes_count == $model_object->volumes_count) { + for my $i (0..($o->volumes_count-1)) { + $o->get_volume($i)->config->apply($model_object->get_volume($i)->config); + } + } + #FIXME restore volumes and their configs, layer_height_ranges, layer_height_profile, layer_height_profile_valid, + } + + $self->remove($obj_idx); +*/ } void Plater::priv::item_changed_selection() @@ -1683,12 +1725,81 @@ void Plater::priv::on_progress_event() void Plater::priv::on_update_print_preview(wxCommandEvent &) { - // TODO + if (this->preview != nullptr) + this->preview->reload_print(); + // in case this was MM print, wipe tower bounding box on 3D tab might need redrawing with exact depth: +#if !ENABLE_EXTENDED_SELECTION + auto selections = p->collect_selections(); + _3DScene::set_objects_selections(p->canvas3D, selections); + if (p->canvas3D) + _3DScene::reload_scene(p->canvas3D, true); +#endif // !ENABLE_EXTENDED_SELECTION } void Plater::priv::on_process_completed(wxCommandEvent &) { - // TODO + // Stop the background task, wait until the thread goes into the "Idle" state. + // At this point of time the thread should be either finished or canceled, + // so the following call just confirms, that the produced data were consumed. + this->background_process.stop(); + //$self->statusbar->ResetCancelCallback(); + //$self->statusbar->StopBusy; + //$self->statusbar->SetStatusText(""); + +/* + my $message; + my $send_gcode = 0; + my $do_print = 0; +# print "Process completed, message: ", $message, "\n"; + if (defined($result)) { + $message = L("Export failed"); + } else { + # G-code file exported successfully. + if ($self->{print_file}) { + $message = L("File added to print queue"); + $do_print = 1; + } elsif ($self->{send_gcode_file}) { + $message = L("Sending G-code file to the Printer Host ..."); + $send_gcode = 1; + } elsif (defined $self->{export_gcode_output_file}) { + $message = L("G-code file exported to ") . $self->{export_gcode_output_file}; + } else { + $message = L("Slicing complete"); + } + } + $self->{export_gcode_output_file} = undef; + wxTheApp->notify($message); + + $self->do_print if $do_print; + + # Send $self->{send_gcode_file} to OctoPrint. + if ($send_gcode) { + my $host = Slic3r::PrintHost::get_print_host($self->{config}); + if ($host->send_gcode($self->{send_gcode_file})) { + $message = L("Upload to host finished."); + } else { + $message = ""; + } + } +*/ + + // As of now, the BackgroundProcessing thread posts status bar update messages to a queue on the MainFrame.pm, + // but the "Processing finished" message is posted to this window. + // Delay the following status bar update, so it will be called later than what is received by MainFrame.pm. + //wxTheApp->CallAfter(sub { +// $self->statusbar->SetStatusText($message); +// }); + + //$self->{print_file} = undef; + //$self->{send_gcode_file} = undef; + //$self->print_info_box_show(1); + + // this updates buttons status + //$self->object_list_changed; + + // refresh preview + if (this->preview != nullptr) + this->preview->reload_print(); } void Plater::priv::on_layer_editing_toggled(bool enable) @@ -2190,7 +2301,22 @@ void Plater::export_3mf() void Plater::reslice() { - // TODO + // explicitly cancel a previous thread and start a new one. + // Don't reslice if export of G-code or sending to OctoPrint is running. +// if (! defined($self->{export_gcode_output_file}) && ! defined($self->{send_gcode_file})) { + // Stop the background processing threads, stop the async update timer. + this->p->stop_background_process(); + // Rather perform one additional unnecessary update of the print object instead of skipping a pending async update. + this->p->async_apply_config(); +/* + $self->statusbar->SetCancelCallback(sub { + $self->stop_background_process; + $self->statusbar->SetStatusText(L("Slicing cancelled")); + # this updates buttons status + $self->object_list_changed; + }); +*/ + this->p->start_background_process(); } void Plater::send_gcode() From d7f013ba196409bde808c61b575aa7d738990c32 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Fri, 19 Oct 2018 09:32:10 +0200 Subject: [PATCH 132/186] Fixed euler angles in gizmo flatten --- src/slic3r/GUI/GLGizmo.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/GLGizmo.cpp b/src/slic3r/GUI/GLGizmo.cpp index 144301d2d1..32594779f5 100644 --- a/src/slic3r/GUI/GLGizmo.cpp +++ b/src/slic3r/GUI/GLGizmo.cpp @@ -1769,9 +1769,9 @@ Vec3d GLGizmoFlatten::get_flattening_rotation() const // calculates the rotations in model space, taking in account the scaling factors Eigen::Matrix m = m_model_object->instances.front()->world_matrix(true, true).matrix().block(0, 0, 3, 3).inverse().transpose(); Eigen::Quaterniond q; - Vec3d angles = q.setFromTwoVectors(m * m_normal, -Vec3d::UnitZ()).toRotationMatrix().eulerAngles(2, 1, 0); + Vec3d angles = Geometry::extract_euler_angles(q.setFromTwoVectors(m * m_normal, -Vec3d::UnitZ()).toRotationMatrix()); m_normal = Vec3d::Zero(); - return Vec3d(angles(2), angles(1), angles(0)); + return angles; } } // namespace GUI From 5557ee3cd272184d044c53bbbd811c94a77d1113 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Fri, 19 Oct 2018 11:02:50 +0200 Subject: [PATCH 133/186] Fixed object adding to list with same object's name + Added name for main object for complex objects + Fixed incorrect Instances and Settings deleting from ObjectList --- src/libslic3r/Model.cpp | 1 + src/slic3r/GUI/GUI_ObjectList.cpp | 2 +- src/slic3r/GUI/Plater.cpp | 7 +++++-- src/slic3r/GUI/wxExtensions.cpp | 2 +- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 8e2d1f391c..d001acedb1 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -415,6 +415,7 @@ void Model::convert_multipart_object(unsigned int max_extruders) ModelObject* object = new ModelObject(this); object->input_file = this->objects.front()->input_file; + object->name = this->objects.front()->name; reset_auto_extruder_id(); diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 53066d7082..9bf1b03e54 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -868,7 +868,7 @@ void ObjectList::del_settings_from_config() void ObjectList::del_instances_from_object(const int obj_idx) { - auto instances = (*m_objects)[obj_idx]->instances; + auto& instances = (*m_objects)[obj_idx]->instances; if (instances.size() <= 1) return; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 40fffc85ba..41d9038a09 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1109,6 +1109,9 @@ std::vector Plater::priv::load_files(const std::vector &input_ // $self->async_apply_config; } else { model = Slic3r::Model::read_from_file(path.string(), nullptr, false); + for (auto obj : model.objects) + if (obj->name.empty()) + obj->name = fs::path(obj->input_file).filename().string(); } } catch (const std::runtime_error &e) { @@ -1156,7 +1159,7 @@ std::vector Plater::priv::load_files(const std::vector &input_ new_model->convert_multipart_object(nozzle_dmrs->values.size()); } - auto loaded_idxs = load_model_objects(model.objects); + auto loaded_idxs = load_model_objects(new_model->objects); obj_idxs.insert(obj_idxs.end(), loaded_idxs.begin(), loaded_idxs.end()); } @@ -1176,7 +1179,7 @@ std::vector Plater::priv::load_model_objects(const ModelObjectPtrs &mode bool scaled_down = false; std::vector obj_idxs; #if ENABLE_EXTENDED_SELECTION - unsigned int obj_count = 0; + unsigned int obj_count = model.objects.size(); #endif // ENABLE_EXTENDED_SELECTION for (ModelObject *model_object : model_objects) { diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp index 33e34137d2..27628c3db4 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -789,7 +789,7 @@ void PrusaObjectDataViewModel::GetItemInfo(const wxDataViewItem& item, ItemType& type = itUndef; PrusaObjectDataViewModelNode *node = (PrusaObjectDataViewModelNode*)item.GetID(); - if (!node || node->GetIdx() < 0 && node->GetType() != itObject) + if (!node || node->GetIdx() < 0 && !(node->GetType() & (itObject|itSettings|itInstanceRoot))) return; idx = node->GetIdx(); From bcffa8dbe257942f57e81a4f43b67c16b761927b Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Fri, 19 Oct 2018 11:24:27 +0200 Subject: [PATCH 134/186] New selection -> Fixed scale gizmo when mirror components are enabled --- src/slic3r/GUI/GLGizmo.cpp | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/slic3r/GUI/GLGizmo.cpp b/src/slic3r/GUI/GLGizmo.cpp index 32594779f5..8783e00462 100644 --- a/src/slic3r/GUI/GLGizmo.cpp +++ b/src/slic3r/GUI/GLGizmo.cpp @@ -868,7 +868,7 @@ void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const BoundingBoxf3 box; Transform3d transform = Transform3d::Identity(); Vec3d angles = Vec3d::Zero(); - Transform3d rotation = Transform3d::Identity(); + Transform3d offsets_transform = Transform3d::Identity(); if (selection.is_from_single_instance()) { @@ -880,13 +880,19 @@ void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const } // gets transform from first selected volume - transform = selection.get_volume(*idxs.begin())->world_matrix().cast(); + const GLVolume* v = selection.get_volume(*idxs.begin()); + transform = v->world_matrix().cast(); - // extract angles from transform - angles = Slic3r::Geometry::extract_euler_angles(transform); + // gets angles from first selected volume + angles = v->get_rotation(); +#if ENABLE_MIRROR + // consider rotation+mirror only components of the transform for offsets + offsets_transform = Geometry::assemble_transform(Vec3d::Zero(), angles, Vec3d::Ones(), v->get_mirror()); +#else // set rotation-only component of transform - rotation = Geometry::assemble_transform(Vec3d::Zero(), angles); + offsets_transform = Geometry::assemble_transform(Vec3d::Zero(), angles); +#endif // ENABLE_MIRROR } else box = selection.get_bounding_box(); @@ -898,9 +904,9 @@ void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const const Vec3d& center = m_box.center(); #if ENABLE_EXTENDED_SELECTION - Vec3d offset_x = rotation * Vec3d((double)Offset, 0.0, 0.0); - Vec3d offset_y = rotation * Vec3d(0.0, (double)Offset, 0.0); - Vec3d offset_z = rotation * Vec3d(0.0, 0.0, (double)Offset); + Vec3d offset_x = offsets_transform * Vec3d((double)Offset, 0.0, 0.0); + Vec3d offset_y = offsets_transform * Vec3d(0.0, (double)Offset, 0.0); + Vec3d offset_z = offsets_transform * Vec3d(0.0, 0.0, (double)Offset); #endif // ENABLE_EXTENDED_SELECTION // x axis From 42a77316ba58cae9f9cedb5e28ad6544c1304ad0 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Fri, 19 Oct 2018 13:26:42 +0200 Subject: [PATCH 135/186] Planes of gizmo flatten visible from both sides --- src/slic3r/GUI/GLCanvas3D.cpp | 4 ++-- src/slic3r/GUI/GLGizmo.cpp | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 6dce5cd16c..05ac0c74f2 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -3941,9 +3941,9 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) } #endif // ENABLE_EXTENDED_SELECTION #if ENABLE_EXTENDED_SELECTION - else if (!m_selection.is_empty() && m_gizmos.grabber_contains_mouse()) + else if (evt.LeftDown() && !m_selection.is_empty() && m_gizmos.grabber_contains_mouse()) #else - else if ((selected_object_idx != -1) && m_gizmos.grabber_contains_mouse()) + else if (evt.LeftDown() && (selected_object_idx != -1) && m_gizmos.grabber_contains_mouse()) #endif // ENABLE_EXTENDED_SELECTION { update_gizmos_data(); diff --git a/src/slic3r/GUI/GLGizmo.cpp b/src/slic3r/GUI/GLGizmo.cpp index 8783e00462..2f75d43fd0 100644 --- a/src/slic3r/GUI/GLGizmo.cpp +++ b/src/slic3r/GUI/GLGizmo.cpp @@ -1474,6 +1474,7 @@ void GLGizmoFlatten::on_render(const BoundingBoxf3& box) const ::glEnable(GL_BLEND); ::glEnable(GL_DEPTH_TEST); + ::glDisable(GL_CULL_FACE); for (int i=0; i<(int)m_planes.size(); ++i) { if (i == m_hover_id) @@ -1512,6 +1513,7 @@ void GLGizmoFlatten::on_render(const BoundingBoxf3& box) const #endif // ENABLE_EXTENDED_SELECTION } + ::glEnable(GL_CULL_FACE); ::glDisable(GL_BLEND); } @@ -1522,6 +1524,7 @@ void GLGizmoFlatten::on_render_for_picking(const BoundingBoxf3& box) const #endif // ENABLE_EXTENDED_SELECTION { ::glEnable(GL_DEPTH_TEST); + ::glDisable(GL_CULL_FACE); for (unsigned int i = 0; i < m_planes.size(); ++i) { @@ -1552,6 +1555,8 @@ void GLGizmoFlatten::on_render_for_picking(const BoundingBoxf3& box) const } #endif // ENABLE_EXTENDED_SELECTION } + + ::glEnable(GL_CULL_FACE); } void GLGizmoFlatten::set_flattening_data(const ModelObject* model_object) From b6251dd85bdca3c9483fc85247e2183ca75337cc Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Fri, 19 Oct 2018 13:38:35 +0200 Subject: [PATCH 136/186] Fix CheckboxFileDialog --- src/slic3r/GUI/GUI_Utils.cpp | 7 ++++++- src/slic3r/GUI/GUI_Utils.hpp | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/GUI_Utils.cpp b/src/slic3r/GUI/GUI_Utils.cpp index 8fff2d2081..b538718e18 100644 --- a/src/slic3r/GUI/GUI_Utils.cpp +++ b/src/slic3r/GUI/GUI_Utils.cpp @@ -48,7 +48,7 @@ CheckboxFileDialog::CheckboxFileDialog(wxWindow *parent, return panel; }; - SetExtraControlCreator(*extra_control_creator.target()); + SetExtraControlCreator(control_creator_trampoline); } bool CheckboxFileDialog::get_checkbox_value() const @@ -56,6 +56,11 @@ bool CheckboxFileDialog::get_checkbox_value() const return this->cbox != nullptr ? cbox->IsChecked() : false; } +wxWindow* CheckboxFileDialog::control_creator_trampoline(wxWindow *parent) +{ + auto *self = dynamic_cast(parent); + return self != nullptr ? self->extra_control_creator(parent) : nullptr; +} WindowMetrics WindowMetrics::from_window(wxTopLevelWindow *window) diff --git a/src/slic3r/GUI/GUI_Utils.hpp b/src/slic3r/GUI/GUI_Utils.hpp index 1c776df81e..827bacfcee 100644 --- a/src/slic3r/GUI/GUI_Utils.hpp +++ b/src/slic3r/GUI/GUI_Utils.hpp @@ -39,6 +39,8 @@ public: private: std::function extra_control_creator; wxCheckBox *cbox; + + static wxWindow* control_creator_trampoline(wxWindow *); }; From ec0c65a80a895b761476408be5922b0fbe741985 Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Fri, 19 Oct 2018 15:12:38 +0200 Subject: [PATCH 137/186] Fix CheckboxFileDialog, for real this time (I hope) --- src/slic3r/GUI/GUI_Utils.cpp | 50 +++++++++++++++++++----------------- src/slic3r/GUI/GUI_Utils.hpp | 12 ++++++--- 2 files changed, 36 insertions(+), 26 deletions(-) diff --git a/src/slic3r/GUI/GUI_Utils.cpp b/src/slic3r/GUI/GUI_Utils.cpp index b538718e18..d1437d9b87 100644 --- a/src/slic3r/GUI/GUI_Utils.cpp +++ b/src/slic3r/GUI/GUI_Utils.cpp @@ -6,7 +6,6 @@ #include #include -#include #include #include "libslic3r/Config.hpp" @@ -16,6 +15,29 @@ namespace Slic3r { namespace GUI { +CheckboxFileDialog::ExtraPanel::ExtraPanel(wxWindow *parent) + : wxPanel(parent, wxID_ANY) +{ + // WARN: wxMSW does some extra shenanigans to calc the extra control size. + // It first calls the create function with a dummy empty wxDialog parent and saves its size. + // Afterwards, the create function is called again with the real parent. + // Additionally there's no way to pass any extra data to the create function (no closure), + // which is why we have to this stuff here. Grrr! + auto *dlg = dynamic_cast(parent); + const wxString checkbox_label(dlg != nullptr ? dlg->checkbox_label : wxString()); + + auto* sizer = new wxBoxSizer(wxHORIZONTAL); + cbox = new wxCheckBox(this, wxID_ANY, checkbox_label); + sizer->AddSpacer(5); + sizer->Add(this->cbox, 0, wxEXPAND | wxALL, 5); + SetSizer(sizer); + sizer->SetSizeHints(this); +} + +wxWindow* CheckboxFileDialog::ExtraPanel::ctor(wxWindow *parent) { + return new ExtraPanel(parent); +} + CheckboxFileDialog::CheckboxFileDialog(wxWindow *parent, const wxString &checkbox_label, bool checkbox_value, @@ -29,37 +51,19 @@ CheckboxFileDialog::CheckboxFileDialog(wxWindow *parent, const wxString &name ) : wxFileDialog(parent, message, default_dir, default_file, wildcard, style, pos, size, name) - , cbox(nullptr) + , checkbox_label(checkbox_label) { if (checkbox_label.IsEmpty()) { return; } - extra_control_creator = [this, checkbox_label](wxWindow *parent) -> wxWindow* { - wxPanel* panel = new wxPanel(parent, -1); - wxSizer* sizer = new wxBoxSizer(wxHORIZONTAL); - this->cbox = new wxCheckBox(panel, wxID_HIGHEST + 1, checkbox_label); - this->cbox->SetValue(true); - sizer->AddSpacer(5); - sizer->Add(this->cbox, 0, wxEXPAND | wxALL | wxALIGN_CENTER_VERTICAL, 5); - panel->SetSizer(sizer); - sizer->SetSizeHints(panel); - - return panel; - }; - - SetExtraControlCreator(control_creator_trampoline); + SetExtraControlCreator(ExtraPanel::ctor); } bool CheckboxFileDialog::get_checkbox_value() const { - return this->cbox != nullptr ? cbox->IsChecked() : false; -} - -wxWindow* CheckboxFileDialog::control_creator_trampoline(wxWindow *parent) -{ - auto *self = dynamic_cast(parent); - return self != nullptr ? self->extra_control_creator(parent) : nullptr; + auto *extra_panel = dynamic_cast(GetExtraControl()); + return extra_panel != nullptr ? extra_panel->cbox->GetValue() : false; } diff --git a/src/slic3r/GUI/GUI_Utils.hpp b/src/slic3r/GUI/GUI_Utils.hpp index 827bacfcee..fe96e5a1b8 100644 --- a/src/slic3r/GUI/GUI_Utils.hpp +++ b/src/slic3r/GUI/GUI_Utils.hpp @@ -8,6 +8,7 @@ #include #include +#include class wxCheckBox; class wxTopLevelWindow; @@ -37,10 +38,15 @@ public: bool get_checkbox_value() const; private: - std::function extra_control_creator; - wxCheckBox *cbox; + struct ExtraPanel : public wxPanel + { + wxCheckBox *cbox; - static wxWindow* control_creator_trampoline(wxWindow *); + ExtraPanel(wxWindow *parent); + static wxWindow* ctor(wxWindow *parent); + }; + + wxString checkbox_label; }; From 0af4de4faab4024e330dfc5822db73c549c3235b Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Fri, 19 Oct 2018 15:27:19 +0200 Subject: [PATCH 138/186] New selection -> Split command --- src/libslic3r/Model.hpp | 2 ++ src/slic3r/GUI/MainFrame.cpp | 2 +- src/slic3r/GUI/Plater.cpp | 48 +++++++++++++++++++++++++++++++++--- 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index 6c34292d31..ac8c47174e 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -94,6 +94,8 @@ public: void delete_volume(size_t idx); void clear_volumes(); + bool is_multiparts() const { return volumes.size() > 1; } + ModelInstance* add_instance(); ModelInstance* add_instance(const ModelInstance &instance); ModelInstance* add_instance(const Vec3d &offset, const Vec3d &scaling_factor, const Vec3d &rotation); diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 84b763a34e..6a202ad4ce 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -302,7 +302,7 @@ void MainFrame::init_menubar() append_menu_item(m_plater_menu, wxID_ANY, _(L("Export plate as AMF...")), _(L("Export current plate as AMF")), [this](wxCommandEvent&){ /*m_plater->export_amf();*/ }, "brick_go.png"); append_menu_item(m_plater_menu, wxID_ANY, _(L("Export plate as 3MF...")), _(L("Export current plate as 3MF")), - [this](wxCommandEvent&){ /*m_plater->export_3mf(); */}, "brick_go.png"); + [this](wxCommandEvent&){ m_plater->export_3mf(); }, "brick_go.png"); } // Window menu diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 41d9038a09..b5cb216256 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1583,7 +1583,45 @@ void Plater::priv::arrange() void Plater::priv::split_object() { - // TODO +#if ENABLE_EXTENDED_SELECTION + int obj_idx = get_selected_object_idx(); + if (obj_idx == -1) + return; + + // we clone model object because split_object() adds the split volumes + // into the same model object, thus causing duplicates when we call load_model_objects() + Model new_model = model; + ModelObject* current_model_object = new_model.objects[obj_idx]; + + if (current_model_object->volumes.size() > 1) + { + Slic3r::GUI::warning_catcher(q, _(L("The selected object can't be split because it contains more than one volume/material."))); + return; + } + +// $self->stop_background_process; + + ModelObjectPtrs new_objects; + current_model_object->split(&new_objects); + if (new_objects.size() == 1) + { + Slic3r::GUI::warning_catcher(q, _(L("The selected object couldn't be split because it contains only one part."))); +// $self->schedule_background_process; + } + else + { + for (ModelObject* m : new_objects) + { + m->center_around_origin(); + } + + remove(obj_idx); + + // load all model objects at once, otherwise the plate would be rearranged after each one + // causing original positions not to be kept + load_model_objects(new_objects); + } +#endif // ENABLE_EXTENDED_SELECTION } void Plater::priv::schedule_background_process() @@ -1719,7 +1757,7 @@ void Plater::priv::on_action_add(SimpleEvent&) void Plater::priv::on_action_split(SimpleEvent&) { - // TODO + split_object(); } void Plater::priv::on_action_cut(SimpleEvent&) @@ -1874,6 +1912,9 @@ bool Plater::priv::init_object_menu() wxMenuItem* item_mirror = append_submenu(&object_menu, mirror_menu, wxID_ANY, _(L("Mirror")), _(L("Mirror the selected object"))); + wxMenuItem* item_split = append_menu_item(&object_menu, wxID_ANY, _(L("Split")), _(L("Split the selected object into individual parts")), + [this](wxCommandEvent&){ split_object(); }, "shape_ungroup.png"); + #if ENABLE_EXTENDED_SELECTION // ui updates needs to be binded to the parent panel if (q != nullptr) @@ -1882,6 +1923,7 @@ bool Plater::priv::init_object_menu() q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_delete_object()); }, item_delete->GetId()); q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_increase_instances()); }, item_increase->GetId()); q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_decrease_instances()); }, item_decrease->GetId()); + q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_split_object()); }, item_split->GetId()); } #endif // ENABLE_EXTENDED_SELECTION @@ -1910,7 +1952,7 @@ bool Plater::priv::can_decrease_instances() const bool Plater::priv::can_split_object() const { int obj_idx = get_selected_object_idx(); - return (0 <= obj_idx) && (obj_idx < (int)model.objects.size()); + return (0 <= obj_idx) && (obj_idx < (int)model.objects.size()) && !model.objects[obj_idx]->is_multiparts(); } bool Plater::priv::can_cut_object() const From cc5405e84d5de440a7aaa1220df14880b7b19da0 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Fri, 19 Oct 2018 15:35:39 +0200 Subject: [PATCH 139/186] Replaced dummy string in CheckboxFileDialog::ExtraPanel --- src/slic3r/GUI/GUI_Utils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/slic3r/GUI/GUI_Utils.cpp b/src/slic3r/GUI/GUI_Utils.cpp index d1437d9b87..fb494ed232 100644 --- a/src/slic3r/GUI/GUI_Utils.cpp +++ b/src/slic3r/GUI/GUI_Utils.cpp @@ -24,7 +24,7 @@ CheckboxFileDialog::ExtraPanel::ExtraPanel(wxWindow *parent) // Additionally there's no way to pass any extra data to the create function (no closure), // which is why we have to this stuff here. Grrr! auto *dlg = dynamic_cast(parent); - const wxString checkbox_label(dlg != nullptr ? dlg->checkbox_label : wxString()); + const wxString checkbox_label(dlg != nullptr ? dlg->checkbox_label : wxString("String long enough to contain dlg->checkbox_label")); auto* sizer = new wxBoxSizer(wxHORIZONTAL); cbox = new wxCheckBox(this, wxID_ANY, checkbox_label); From 5d94e6adb8d72102f7af28c0a56fc457f0677afd Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Fri, 19 Oct 2018 16:14:55 +0200 Subject: [PATCH 140/186] New selection -> Improved sychronization of instances selection between 3D scene and right panel --- src/slic3r/GUI/GLCanvas3D.cpp | 16 +++++++--------- src/slic3r/GUI/GLCanvas3D.hpp | 2 ++ src/slic3r/GUI/GUI_ObjectList.cpp | 4 ++++ 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 05ac0c74f2..7ffd6e0106 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -3997,6 +3997,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) m_gizmos.update_on_off_state(m_selection); update_gizmos_data(); wxGetApp().obj_manipul()->update_settings_value(m_selection); + post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT)); m_dirty = true; } #else @@ -4021,16 +4022,10 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) } // propagate event through callback -#if ENABLE_EXTENDED_SELECTION - if (m_picking_enabled && (m_hover_volume_id != -1)) - { - int object_idx = m_selection.get_object_idx(); - _on_select(m_hover_volume_id, object_idx); - } -#else +#if !ENABLE_EXTENDED_SELECTION if (m_picking_enabled && (volume_idx != -1)) _on_select(volume_idx, selected_object_idx); -#endif // ENABLE_EXTENDED_SELECTION +#endif // !ENABLE_EXTENDED_SELECTION #if ENABLE_EXTENDED_SELECTION if (m_hover_volume_id != -1) @@ -4357,10 +4352,11 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) #if ENABLE_EXTENDED_SELECTION m_selection.clear(); wxGetApp().obj_manipul()->update_settings_value(m_selection); + post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT)); #else deselect_volumes(); -#endif // ENABLE_EXTENDED_SELECTION _on_select(-1, -1); +#endif // ENABLE_EXTENDED_SELECTION update_gizmos_data(); } #if ENABLE_GIZMOS_RESET @@ -6645,6 +6641,7 @@ void GLCanvas3D::_on_move(const std::vector& volume_idxs) } #endif // ENABLE_EXTENDED_SELECTION +#if !ENABLE_EXTENDED_SELECTION void GLCanvas3D::_on_select(int volume_idx, int object_idx) { #if ENABLE_EXTENDED_SELECTION @@ -6680,6 +6677,7 @@ void GLCanvas3D::_on_select(int volume_idx, int object_idx) wxGetApp().obj_list()->select_current_volume(obj_id, vol_id); #endif // !ENABLE_EXTENDED_SELECTION } +#endif // !ENABLE_EXTENDED_SELECTION std::vector GLCanvas3D::_parse_colors(const std::vector& colors) { diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 58b414c8d9..844e826fef 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -970,7 +970,9 @@ private: #else void _on_move(const std::vector& volume_idxs); #endif // ENABLE_EXTENDED_SELECTION +#if !ENABLE_EXTENDED_SELECTION void _on_select(int volume_idx, int object_idx); +#endif // !ENABLE_EXTENDED_SELECTION // generates the legend texture in dependence of the current shown view type void _generate_legend_texture(const GCodePreviewData& preview_data, const std::vector& tool_colors); diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 9bf1b03e54..6c9077badf 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -1054,7 +1054,11 @@ void ObjectList::part_selection_changed() m_selected_object_id = obj_idx; +#if ENABLE_EXTENDED_SELECTION + wxGetApp().obj_manipul()->update_settings_value(_3DScene::get_canvas(wxGetApp().canvas3D())->get_selection()); +#else wxGetApp().obj_manipul()->update_values(); +#endif // ENABLE_EXTENDED_SELECTION } void ObjectList::update_manipulation_sizer(const bool is_simple_mode) From f47949504e0fa3efd7272dce57d03e8854644a80 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Fri, 19 Oct 2018 13:55:29 +0200 Subject: [PATCH 141/186] Prototype of the hiding according to view mode + Added mode icon near option's label + Fixed segmentation fault on Linux --- resources/icons/mode_expert.png | Bin 0 -> 3278 bytes resources/icons/mode_middle.png | Bin 0 -> 3262 bytes resources/icons/mode_simple.png | Bin 0 -> 3388 bytes src/libslic3r/Config.hpp | 7 ++ src/libslic3r/PrintConfig.cpp | 144 ++++++++++++++++++++++ src/slic3r/GUI/GUI_App.cpp | 14 ++- src/slic3r/GUI/GUI_App.hpp | 1 + src/slic3r/GUI/GUI_ObjectManipulation.cpp | 2 +- src/slic3r/GUI/OptionsGroup.cpp | 57 ++++----- src/slic3r/GUI/OptionsGroup.hpp | 22 ++-- src/slic3r/GUI/Tab.cpp | 41 +++++- src/slic3r/GUI/Tab.hpp | 2 + src/slic3r/GUI/wxExtensions.hpp | 5 +- 13 files changed, 242 insertions(+), 53 deletions(-) create mode 100644 resources/icons/mode_expert.png create mode 100644 resources/icons/mode_middle.png create mode 100644 resources/icons/mode_simple.png diff --git a/resources/icons/mode_expert.png b/resources/icons/mode_expert.png new file mode 100644 index 0000000000000000000000000000000000000000..1716bab44b489855cb5e454be397e70e2764e1a4 GIT binary patch literal 3278 zcmV;<3^DVGP)004&%004{+008|`004nN004b?008NW002DY000@xb3BE2000Uv zX+uL$Nkc;*P;zf(X>4Tx07%E3mUmQC*A|D*y?1({%`nm#dXp|Nfb=dP9RyJrW(F9_ z0K*JTY>22pL=h1IMUbF?0i&TvtcYSED5zi$NDxqBFp8+CWJcCXe0h2A<>mLsz2Dkr z?{oLrd!Mx~03=TzE-wX^0w9?u;0Jm*(^rK@(6Rjh26%u0rT{Qm>8ZX!?!iDLFE@L0LWj&=4?(nOT_siPRbOditRHZrp6?S8Agej zFG^6va$=5K|`EW#NwP&*~x4%_lS6VhL9s-#7D#h8C*`Lh;NHnGf9}t z74chfY%+(L4giWIwhK6{coCb3n8XhbbP@4#0C1$ZFF5847I3lz;zPNlq-OKEaq$AW zE=!MYYHiJ+dvY?9I0Av8Ka-Wn(gPeepdb@piwLhwjRWWeSr7baCBSDM=|p zK0Q5^$>Pur|2)M1IPkCYSQ^NQ`z*p zYmq4Rp8z$=2uR(a0_5jDfT9oq5_wSE_22vEgAWDbn-``!u{igi1^xT3aEbVl&W-yV z=Mor9X9@Wki)-R*3DAH5Bmou30~MeFbb%o-16IHmI084Y0{DSo5DwM?7KjJQfDbZ3 zF4znTKoQsl_JT@K1L{E|XaOfc2RIEbfXm=IxC!on2Vew@gXdrdyaDqN1YsdEM1kZX zRY(gmfXpBUWDmJPK2RVO4n;$85DyYUxzHA<2r7jtp<1XB`W89`U4X7a1JFHa6qn9`(3jA6(BtSg7z~Dn z(ZN_@JTc*z1k5^2G3EfK6>}alfEmNgVzF3xtO3>z>xX4x1=s@Ye(W*qIqV>I9QzhW z#Hr%UaPGJW91oX=E5|kA&f*4f6S#T26kZE&gZIO;@!9wid_BGke*-^`pC?EYbO?5Y zU_t_6GogaeLbybDNO(mg64i;;!~i0fxQSRnJWjkq93{RZ$&mC(E~H43khGI@gmj*C zkMxR6CTo)&$q{4$c_+D%e3AT^{8oY@VI<)t!Is!4Q6EtGo7CCWGzL)D>rQ4^>|)NiQ$)EQYB*=4e!vRSfKvS(yRXb4T4 z=0!`QmC#PmhG_4XC@*nZ!dbFoNz0PKC3A9$a*lEwxk9;CxjS<2<>~Tn@`>`hkG4N#KjNU~z;vi{c;cwx$aZXSoN&@}N^m;n^upQ1neW`@Jm+HLvfkyqE8^^jVTFG14;RpP@{Py@g^4IZC^Zz~o6W||E74S6BG%z=? zH;57x71R{;CfGT+B=|vyZiq0XJ5(|>GPE&tF3dHoG;Cy*@v8N!u7@jxbHh6$uo0mV z4H2`e-B#~iJsxQhSr9q2MrTddnyYIS)+Vhz6D1kNj5-;Ojt+}%ivGa#W7aWeW4vOj zV`f+`tbMHKY)5t(dx~SnDdkMW+QpW}PR7~A?TMR;cZe^KpXR!7E4eQdJQHdX<`Vr9 zk0dT6g(bBnMJ7e%MIVY;#n-+v{i@=tg`KfG`%5fK4(`J2;_VvR?Xdf3 zsdQ;h>DV6MJ?&-mvcj_0d!zPVEnik%vyZS(xNoGwr=oMe=Kfv#KUBt7-l=k~YOPkP z-cdbwfPG-_pyR=o8s(azn)ipehwj#T)V9}Y*Oec}9L_lWv_7=H_iM)2jSUJ7MGYU1 z@Q#ce4LsV@Xw}%*q|{W>3^xm#r;bG)yZMdlH=QkpEw!z*)}rI!xbXP1Z==5*I^lhy z`y}IJ%XeDeRku;v3frOf?DmPgz@Xmo#D^7KH*><&kZ}k0<(`u)y&d8oAIZHU3 ze|F(q&bit1spqFJ#9bKcj_Q7Jan;4!Jpn!am%J}sx$J)VVy{#0xhr;8PG7aTdg>bE zTE}(E>+O9OeQiHj{Lt2K+24M{>PF{H>ziEz%LmR5It*U8<$CM#ZLizc@2tEtFcdO$ zcQ|r*xkvZnNio#z9&IX9*nWZ zp8u5o(}(f=r{t&Q6RH!9lV+2rr`)G*K3n~4{CVp0`RRh6rGKt|q5I;yUmSnwn^`q8 z{*wQ4;n(6<@~@7(UiP|s)_?Z#o8&k1bA@l^-yVI(c-Q+r?ES=i<_GMDijR69yFPh; zdbp6hu<#rAg!B711SuW>000SaNLh0L01|Wn01|Wo-ewWdJfTF*iCfGCDFhATcyLGdDUkIdi>awEzGC+(|@1R5(wKlgmpRQ543%nKT*` z>&8t%>`HMX2)0#G3es%?uDjHQA{Mh0QVB&hrOG~&vH~=gQ;ie`;<8gc+A4e<_ z@lX2F3j)pe_j_|R?YzM@`9l_lhyBx!DrGR!(t@ttT|~KdWq3njaz$3!+Ay@fZfv%G z<_8AQNoOVZ(%B**@_{H)9r>2YU~zPmEAHp6uf4_ET6FN?-k6@Gh!^CH+>oMgt0#Np zr|TlrGZS6imGV5H?ri8Joq*Rxg^tHpy&HmG)(+N@Z_bAE% zvp;geR3zo0LKU?04(VJ&A_2=O6ujB$YW$$VA%BTlRY}TlllGs2>@@F%23d zGnN&kYo3y?V`FAr8s+Ksc6?b|GksTj<(&zn$Z|$^HwHO7QmNR#R#$PHOk#`cpeEWh zQOGUPY&0@*;4HoRoZVs(%TrT0004&%004{+008|`004nN004b?008NW002DY000@xb3BE2000Uv zX+uL$Nkc;*P;zf(X>4Tx07%E3mUmQC*A|D*y?1({%`nm#dXp|Nfb=dP9RyJrW(F9_ z0K*JTY>22pL=h1IMUbF?0i&TvtcYSED5zi$NDxqBFp8+CWJcCXe0h2A<>mLsz2Dkr z?{oLrd!Mx~03=TzE-wX^0w9?u;0Jm*(^rK@(6Rjh26%u0rT{Qm>8ZX!?!iDLFE@L0LWj&=4?(nOT_siPRbOditRHZrp6?S8Agej zFG^6va$=5K|`EW#NwP&*~x4%_lS6VhL9s-#7D#h8C*`Lh;NHnGf9}t z74chfY%+(L4giWIwhK6{coCb3n8XhbbP@4#0C1$ZFF5847I3lz;zPNlq-OKEaq$AW zE=!MYYHiJ+dvY?9I0Av8Ka-Wn(gPeepdb@piwLhwjRWWeSr7baCBSDM=|p zK0Q5^$>Pur|2)M1IPkCYSQ^NQ`z*p zYmq4Rp8z$=2uR(a0_5jDfT9oq5_wSE_22vEgAWDbn-``!u{igi1^xT3aEbVl&W-yV z=Mor9X9@Wki)-R*3DAH5Bmou30~MeFbb%o-16IHmI084Y0{DSo5DwM?7KjJQfDbZ3 zF4znTKoQsl_JT@K1L{E|XaOfc2RIEbfXm=IxC!on2Vew@gXdrdyaDqN1YsdEM1kZX zRY(gmfXpBUWDmJPK2RVO4n;$85DyYUxzHA<2r7jtp<1XB`W89`U4X7a1JFHa6qn9`(3jA6(BtSg7z~Dn z(ZN_@JTc*z1k5^2G3EfK6>}alfEmNgVzF3xtO3>z>xX4x1=s@Ye(W*qIqV>I9QzhW z#Hr%UaPGJW91oX=E5|kA&f*4f6S#T26kZE&gZIO;@!9wid_BGke*-^`pC?EYbO?5Y zU_t_6GogaeLbybDNO(mg64i;;!~i0fxQSRnJWjkq93{RZ$&mC(E~H43khGI@gmj*C zkMxR6CTo)&$q{4$c_+D%e3AT^{8oY@VI<)t!Is!4Q6EtGo7CCWGzL)D>rQ4^>|)NiQ$)EQYB*=4e!vRSfKvS(yRXb4T4 z=0!`QmC#PmhG_4XC@*nZ!dbFoNz0PKC3A9$a*lEwxk9;CxjS<2<>~Tn@`>`hkG4N#KjNU~z;vi{c;cwx$aZXSoN&@}N^m;n^upQ1neW`@Jm+HLvfkyqE8^^jVTFG14;RpP@{Py@g^4IZC^Zz~o6W||E74S6BG%z=? zH;57x71R{;CfGT+B=|vyZiq0XJ5(|>GPE&tF3dHoG;Cy*@v8N!u7@jxbHh6$uo0mV z4H2`e-B#~iJsxQhSr9q2MrTddnyYIS)+Vhz6D1kNj5-;Ojt+}%ivGa#W7aWeW4vOj zV`f+`tbMHKY)5t(dx~SnDdkMW+QpW}PR7~A?TMR;cZe^KpXR!7E4eQdJQHdX<`Vr9 zk0dT6g(bBnMJ7e%MIVY;#n-+v{i@=tg`KfG`%5fK4(`J2;_VvR?Xdf3 zsdQ;h>DV6MJ?&-mvcj_0d!zPVEnik%vyZS(xNoGwr=oMe=Kfv#KUBt7-l=k~YOPkP z-cdbwfPG-_pyR=o8s(azn)ipehwj#T)V9}Y*Oec}9L_lWv_7=H_iM)2jSUJ7MGYU1 z@Q#ce4LsV@Xw}%*q|{W>3^xm#r;bG)yZMdlH=QkpEw!z*)}rI!xbXP1Z==5*I^lhy z`y}IJ%XeDeRku;v3frOf?DmPgz@Xmo#D^7KH*><&kZ}k0<(`u)y&d8oAIZHU3 ze|F(q&bit1spqFJ#9bKcj_Q7Jan;4!Jpn!am%J}sx$J)VVy{#0xhr;8PG7aTdg>bE zTE}(E>+O9OeQiHj{Lt2K+24M{>PF{H>ziEz%LmR5It*U8<$CM#ZLizc@2tEtFcdO$ zcQ|r*xkvZnNio#z9&IX9*nWZ zp8u5o(}(f=r{t&Q6RH!9lV+2rr`)G*K3n~4{CVp0`RRh6rGKt|q5I;yUmSnwn^`q8 z{*wQ4;n(6<@~@7(UiP|s)_?Z#o8&k1bA@l^-yVI(c-Q+r?ES=i<_GMDijR69yFPh; zdbp6hu<#rAg!B711SuW>000SaNLh0L01FcU01FcV0GgZ_0000XbVXQnLvm$dbZKvH zAXI5>WdJfTF*iCfGCDFhATcyLGdDUkIdi>awEzGC%t=H+R5(wKlT9l`VHC&zmof4( z6IozkCJR}huu)1jijDFW_z+4d8w*+ZHnw78VdpI|N=67p80LMh-?{hB3S;c3mYZ1%zJ_;gLfKe$!GY_yUB2u@5LvLADw&SoqD!p#uz|u2i z1sG*c*aG6O;4F9L004&%004{+008|`004nN004b?008NW002DY000@xb3BE2000Uv zX+uL$Nkc;*P;zf(X>4Tx07%E3mUmQC*A|D*y?1({%`nm#dXp|Nfb=dP9RyJrW(F9_ z0K*JTY>22pL=h1IMUbF?0i&TvtcYSED5zi$NDxqBFp8+CWJcCXe0h2A<>mLsz2Dkr z?{oLrd!Mx~03=TzE-wX^0w9?u;0Jm*(^rK@(6Rjh26%u0rT{Qm>8ZX!?!iDLFE@L0LWj&=4?(nOT_siPRbOditRHZrp6?S8Agej zFG^6va$=5K|`EW#NwP&*~x4%_lS6VhL9s-#7D#h8C*`Lh;NHnGf9}t z74chfY%+(L4giWIwhK6{coCb3n8XhbbP@4#0C1$ZFF5847I3lz;zPNlq-OKEaq$AW zE=!MYYHiJ+dvY?9I0Av8Ka-Wn(gPeepdb@piwLhwjRWWeSr7baCBSDM=|p zK0Q5^$>Pur|2)M1IPkCYSQ^NQ`z*p zYmq4Rp8z$=2uR(a0_5jDfT9oq5_wSE_22vEgAWDbn-``!u{igi1^xT3aEbVl&W-yV z=Mor9X9@Wki)-R*3DAH5Bmou30~MeFbb%o-16IHmI084Y0{DSo5DwM?7KjJQfDbZ3 zF4znTKoQsl_JT@K1L{E|XaOfc2RIEbfXm=IxC!on2Vew@gXdrdyaDqN1YsdEM1kZX zRY(gmfXpBUWDmJPK2RVO4n;$85DyYUxzHA<2r7jtp<1XB`W89`U4X7a1JFHa6qn9`(3jA6(BtSg7z~Dn z(ZN_@JTc*z1k5^2G3EfK6>}alfEmNgVzF3xtO3>z>xX4x1=s@Ye(W*qIqV>I9QzhW z#Hr%UaPGJW91oX=E5|kA&f*4f6S#T26kZE&gZIO;@!9wid_BGke*-^`pC?EYbO?5Y zU_t_6GogaeLbybDNO(mg64i;;!~i0fxQSRnJWjkq93{RZ$&mC(E~H43khGI@gmj*C zkMxR6CTo)&$q{4$c_+D%e3AT^{8oY@VI<)t!Is!4Q6EtGo7CCWGzL)D>rQ4^>|)NiQ$)EQYB*=4e!vRSfKvS(yRXb4T4 z=0!`QmC#PmhG_4XC@*nZ!dbFoNz0PKC3A9$a*lEwxk9;CxjS<2<>~Tn@`>`hkG4N#KjNU~z;vi{c;cwx$aZXSoN&@}N^m;n^upQ1neW`@Jm+HLvfkyqE8^^jVTFG14;RpP@{Py@g^4IZC^Zz~o6W||E74S6BG%z=? zH;57x71R{;CfGT+B=|vyZiq0XJ5(|>GPE&tF3dHoG;Cy*@v8N!u7@jxbHh6$uo0mV z4H2`e-B#~iJsxQhSr9q2MrTddnyYIS)+Vhz6D1kNj5-;Ojt+}%ivGa#W7aWeW4vOj zV`f+`tbMHKY)5t(dx~SnDdkMW+QpW}PR7~A?TMR;cZe^KpXR!7E4eQdJQHdX<`Vr9 zk0dT6g(bBnMJ7e%MIVY;#n-+v{i@=tg`KfG`%5fK4(`J2;_VvR?Xdf3 zsdQ;h>DV6MJ?&-mvcj_0d!zPVEnik%vyZS(xNoGwr=oMe=Kfv#KUBt7-l=k~YOPkP z-cdbwfPG-_pyR=o8s(azn)ipehwj#T)V9}Y*Oec}9L_lWv_7=H_iM)2jSUJ7MGYU1 z@Q#ce4LsV@Xw}%*q|{W>3^xm#r;bG)yZMdlH=QkpEw!z*)}rI!xbXP1Z==5*I^lhy z`y}IJ%XeDeRku;v3frOf?DmPgz@Xmo#D^7KH*><&kZ}k0<(`u)y&d8oAIZHU3 ze|F(q&bit1spqFJ#9bKcj_Q7Jan;4!Jpn!am%J}sx$J)VVy{#0xhr;8PG7aTdg>bE zTE}(E>+O9OeQiHj{Lt2K+24M{>PF{H>ziEz%LmR5It*U8<$CM#ZLizc@2tEtFcdO$ zcQ|r*xkvZnNio#z9&IX9*nWZ zp8u5o(}(f=r{t&Q6RH!9lV+2rr`)G*K3n~4{CVp0`RRh6rGKt|q5I;yUmSnwn^`q8 z{*wQ4;n(6<@~@7(UiP|s)_?Z#o8&k1bA@l^-yVI(c-Q+r?ES=i<_GMDijR69yFPh; zdbp6hu<#rAg!B711SuW>000SaNLh0L01|Wn01|Wo-ewWdJfTF*iCfGCDFhATcyLGdDUkIdi>awEzGDN=ZaPR5(wCQ%h(QK^XpaW_OeA z65CKvj1_!<2Yax3Q5x()1rbjQBIw;>@!~t7Jg2&IUVBh`(`eO;o zqA8VIp{hDcl^k+Q>$rOEk(5b-7ju&^;}&A(F8IDD6(JNbC<>>S$$!Q;%GDg4${^01 zxDDns8(68%$jH6U3RGsmam!e--s9)mb1betr8Ncc8uF!=l&K5l)w_Gaz)pwC+-#1B z8qky7NWpHdf-BSy%0P5P$b-O#=iAt8+ypDz8E_^V7D9m^xL7DWq39Mg-bZO`V6qHO zt19hv&BU+bES1nI$%r91i(+wYii}lhEC~MwK~{6J!gF&Bgj2DWhU@>95x0XVg=st{ zwo)J>mg-;HHE)9;@L=kDz;+l1 aliases; diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 46df2b1c08..f6358906b4 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -39,6 +39,7 @@ void PrintConfigDef::init_common_params() def = this->add("bed_shape", coPoints); def->label = L("Bed shape"); + def->mode = comMiddle; def->default_value = new ConfigOptionPoints{ Vec2d(0, 0), Vec2d(200, 0), Vec2d(200, 200), Vec2d(0, 200) }; def = this->add("layer_height", coFloat); @@ -56,6 +57,7 @@ void PrintConfigDef::init_common_params() def->tooltip = L("Set this to the maximum height that can be reached by your extruder while printing."); def->sidetext = L("mm"); def->cli = "max-print-height=f"; + def->mode = comMiddle; def->default_value = new ConfigOptionFloat(200.0); } @@ -73,6 +75,7 @@ void PrintConfigDef::init_fff_params() "This is mostly useful with Bowden extruders which suffer from oozing. " "This feature slows down both the print and the G-code generation."); def->cli = "avoid-crossing-perimeters!"; + def->mode = comMiddle; def->default_value = new ConfigOptionBool(false); def = this->add("bed_temperature", coInts); @@ -121,6 +124,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm/s²"); def->cli = "bridge-acceleration=f"; def->min = 0; + def->mode = comExpert; def->default_value = new ConfigOptionFloat(0); def = this->add("bridge_angle", coFloat); @@ -132,6 +136,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("°"); def->cli = "bridge-angle=f"; def->min = 0; + def->mode = comMiddle; def->default_value = new ConfigOptionFloat(0.); def = this->add("bridge_fan_speed", coInts); @@ -141,6 +146,7 @@ void PrintConfigDef::init_fff_params() def->cli = "bridge-fan-speed=i@"; def->min = 0; def->max = 100; + def->mode = comExpert; def->default_value = new ConfigOptionInts { 100 }; def = this->add("bridge_flow_ratio", coFloat); @@ -153,6 +159,7 @@ void PrintConfigDef::init_fff_params() def->cli = "bridge-flow-ratio=f"; def->min = 0; def->max = 2; + def->mode = comMiddle; def->default_value = new ConfigOptionFloat(1); def = this->add("bridge_speed", coFloat); @@ -171,6 +178,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm"); def->cli = "brim-width=f"; def->min = 0; + def->mode = comMiddle; def->default_value = new ConfigOptionFloat(0); def = this->add("clip_multipart_objects", coBool); @@ -179,10 +187,12 @@ void PrintConfigDef::init_fff_params() "to clip the overlapping object parts one by the other " "(2nd part will be clipped by the 1st, 3rd part will be clipped by the 1st and 2nd etc)."); def->cli = "clip-multipart-objects!"; + def->mode = comExpert; def->default_value = new ConfigOptionBool(false); def = this->add("compatible_printers", coStrings); def->label = L("Compatible printers"); + def->mode = comMiddle; def->default_value = new ConfigOptionStrings(); def = this->add("compatible_printers_condition", coString); @@ -190,6 +200,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("A boolean expression using the configuration values of an active printer profile. " "If this expression evaluates to true, this profile is considered compatible " "with the active printer profile."); + def->mode = comExpert; def->default_value = new ConfigOptionString(); // The following value is to be stored into the project file (AMF, 3MF, Config ...) @@ -204,6 +215,7 @@ void PrintConfigDef::init_fff_params() "This feature is useful to avoid the risk of ruined prints. " "Slic3r should warn and prevent you from extruder collisions, but beware."); def->cli = "complete-objects!"; + def->mode = comMiddle; def->default_value = new ConfigOptionBool(false); def = this->add("cooling", coBools); @@ -219,6 +231,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm"); def->cli = "cooling_tube_retraction=f"; def->min = 0; + def->mode = comMiddle; def->default_value = new ConfigOptionFloat(91.5f); def = this->add("cooling_tube_length", coFloat); @@ -227,6 +240,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm"); def->cli = "cooling_tube_length=f"; def->min = 0; + def->mode = comMiddle; def->default_value = new ConfigOptionFloat(5.f); def = this->add("default_acceleration", coFloat); @@ -237,6 +251,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm/s²"); def->cli = "default-acceleration=f"; def->min = 0; + def->mode = comExpert; def->default_value = new ConfigOptionFloat(0); def = this->add("default_filament_profile", coStrings); @@ -259,6 +274,7 @@ void PrintConfigDef::init_fff_params() def->cli = "disable-fan-first-layers=i@"; def->min = 0; def->max = 1000; + def->mode = comExpert; def->default_value = new ConfigOptionInts { 3 }; def = this->add("dont_support_bridges", coBool); @@ -267,6 +283,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("Experimental option for preventing support material from being generated " "under bridged areas."); def->cli = "dont-support-bridges!"; + def->mode = comMiddle; def->default_value = new ConfigOptionBool(true); def = this->add("duplicate_distance", coFloat); @@ -286,6 +303,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm"); def->cli = "elefant-foot-compensation=f"; def->min = 0; + def->mode = comExpert; def->default_value = new ConfigOptionFloat(0); def = this->add("end_gcode", coString); @@ -315,6 +333,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("Add solid infill near sloping surfaces to guarantee the vertical shell thickness " "(top+bottom solid layers)."); def->cli = "ensure-vertical-shell-thickness!"; + def->mode = comMiddle; def->default_value = new ConfigOptionBool(false); def = this->add("external_fill_pattern", coEnum); @@ -346,6 +365,7 @@ void PrintConfigDef::init_fff_params() "If expressed as percentage (for example 200%), it will be computed over layer height."); def->sidetext = L("mm or % (leave 0 for default)"); def->cli = "external-perimeter-extrusion-width=s"; + def->mode = comMiddle; def->default_value = new ConfigOptionFloatOrPercent(0, false); def = this->add("external_perimeter_speed", coFloatOrPercent); @@ -366,6 +386,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("Print contour perimeters from the outermost one to the innermost one " "instead of the default inverse order."); def->cli = "external-perimeters-first!"; + def->mode = comExpert; def->default_value = new ConfigOptionBool(false); def = this->add("extra_perimeters", coBool); @@ -375,6 +396,7 @@ void PrintConfigDef::init_fff_params() "Slic3r keeps adding perimeters, until more than 70% of the loop immediately above " "is supported."); def->cli = "extra-perimeters!"; + def->mode = comMiddle; def->default_value = new ConfigOptionBool(true); def = this->add("extruder", coInt); @@ -401,6 +423,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm"); def->cli = "extruder-clearance-height=f"; def->min = 0; + def->mode = comExpert; def->default_value = new ConfigOptionFloat(20); def = this->add("extruder_clearance_radius", coFloat); @@ -412,6 +435,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm"); def->cli = "extruder-clearance-radius=f"; def->min = 0; + def->mode = comExpert; def->default_value = new ConfigOptionFloat(20); def = this->add("extruder_colour", coStrings); @@ -430,6 +454,7 @@ void PrintConfigDef::init_fff_params() "from the XY coordinate)."); def->sidetext = L("mm"); def->cli = "extruder-offset=s@"; + def->mode = comMiddle; def->default_value = new ConfigOptionPoints { Vec2d(0,0) }; def = this->add("extrusion_axis", coString); @@ -446,6 +471,7 @@ void PrintConfigDef::init_fff_params() "Usual values are between 0.9 and 1.1. If you think you need to change this more, " "check filament diameter and your firmware E steps."); def->cli = "extrusion-multiplier=f@"; + def->mode = comMiddle; def->default_value = new ConfigOptionFloats { 1. }; def = this->add("extrusion_width", coFloatOrPercent); @@ -457,6 +483,7 @@ void PrintConfigDef::init_fff_params() "If expressed as percentage (for example: 230%), it will be computed over layer height."); def->sidetext = L("mm or % (leave 0 for auto)"); def->cli = "extrusion-width=s"; + def->mode = comMiddle; def->default_value = new ConfigOptionFloatOrPercent(0, false); def = this->add("fan_always_on", coBools); @@ -475,6 +502,7 @@ void PrintConfigDef::init_fff_params() def->width = 60; def->min = 0; def->max = 1000; + def->mode = comExpert; def->default_value = new ConfigOptionInts { 60 }; def = this->add("filament_colour", coStrings); @@ -501,6 +529,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm³/s"); def->cli = "filament-max-volumetric-speed=f@"; def->min = 0; + def->mode = comMiddle; def->default_value = new ConfigOptionFloats { 0. }; def = this->add("filament_loading_speed", coFloats); @@ -509,6 +538,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm/s"); def->cli = "filament-loading-speed=f@"; def->min = 0; + def->mode = comExpert; def->default_value = new ConfigOptionFloats { 28. }; def = this->add("filament_loading_speed_start", coFloats); @@ -517,6 +547,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm/s"); def->cli = "filament-loading-speed-start=f@"; def->min = 0; + def->mode = comExpert; def->default_value = new ConfigOptionFloats { 3. }; def = this->add("filament_unloading_speed", coFloats); @@ -526,6 +557,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm/s"); def->cli = "filament-unloading-speed=f@"; def->min = 0; + def->mode = comExpert; def->default_value = new ConfigOptionFloats { 90. }; def = this->add("filament_unloading_speed_start", coFloats); @@ -534,6 +566,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm/s"); def->cli = "filament-unloading-speed-start=f@"; def->min = 0; + def->mode = comExpert; def->default_value = new ConfigOptionFloats { 100. }; def = this->add("filament_toolchange_delay", coFloats); @@ -544,6 +577,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("s"); def->cli = "filament-toolchange-delay=f@"; def->min = 0; + def->mode = comExpert; def->default_value = new ConfigOptionFloats { 0. }; def = this->add("filament_cooling_moves", coInts); @@ -553,6 +587,7 @@ void PrintConfigDef::init_fff_params() def->cli = "filament-cooling-moves=i@"; def->max = 0; def->max = 20; + def->mode = comExpert; def->default_value = new ConfigOptionInts { 4 }; def = this->add("filament_cooling_initial_speed", coFloats); @@ -561,6 +596,7 @@ void PrintConfigDef::init_fff_params() def->cli = "filament-cooling-initial-speed=f@"; def->sidetext = L("mm/s"); def->min = 0; + def->mode = comExpert; def->default_value = new ConfigOptionFloats { 2.2f }; def = this->add("filament_minimal_purge_on_wipe_tower", coFloats); @@ -572,6 +608,7 @@ void PrintConfigDef::init_fff_params() def->cli = "filament-minimal-purge-on-wipe-tower=f@"; def->sidetext = L("mm³"); def->min = 0; + def->mode = comExpert; def->default_value = new ConfigOptionFloats { 15.f }; def = this->add("filament_cooling_final_speed", coFloats); @@ -580,6 +617,7 @@ void PrintConfigDef::init_fff_params() def->cli = "filament-cooling-final-speed=f@"; def->sidetext = L("mm/s"); def->min = 0; + def->mode = comExpert; def->default_value = new ConfigOptionFloats { 3.4f }; def = this->add("filament_load_time", coFloats); @@ -588,12 +626,14 @@ void PrintConfigDef::init_fff_params() def->cli = "filament-load-time=i@"; def->sidetext = L("s"); def->min = 0; + def->mode = comExpert; def->default_value = new ConfigOptionFloats { 0.0f }; def = this->add("filament_ramming_parameters", coStrings); def->label = L("Ramming parameters"); def->tooltip = L("This string is edited by RammingDialog and contains ramming specific parameters "); def->cli = "filament-ramming-parameters=s@"; + def->mode = comExpert; def->default_value = new ConfigOptionStrings { "120 100 6.6 6.8 7.2 7.6 7.9 8.2 8.7 9.4 9.9 10.0|" " 0.05 6.6 0.45 6.8 0.95 7.8 1.45 8.3 1.95 9.7 2.45 10 2.95 7.6 3.45 7.6 3.95 7.6 4.45 7.6 4.95 7.6" }; @@ -603,6 +643,7 @@ void PrintConfigDef::init_fff_params() def->cli = "filament-unload-time=i@"; def->sidetext = L("s"); def->min = 0; + def->mode = comExpert; def->default_value = new ConfigOptionFloats { 0.0f }; def = this->add("filament_diameter", coFloats); @@ -668,6 +709,7 @@ void PrintConfigDef::init_fff_params() def->cli = "fill-angle=f"; def->min = 0; def->max = 360; + def->mode = comMiddle; def->default_value = new ConfigOptionFloat(45); def = this->add("fill_density", coPercent); @@ -751,6 +793,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm/s²"); def->cli = "first-layer-acceleration=f"; def->min = 0; + def->mode = comExpert; def->default_value = new ConfigOptionFloat(0); def = this->add("first_layer_bed_temperature", coInts); @@ -772,6 +815,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm or % (leave 0 for default)"); def->cli = "first-layer-extrusion-width=s"; def->ratio_over = "first_layer_height"; + def->mode = comMiddle; def->default_value = new ConfigOptionFloatOrPercent(200, true); def = this->add("first_layer_height", coFloatOrPercent); @@ -794,6 +838,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm/s or %"); def->cli = "first-layer-speed=s"; def->min = 0; + def->mode = comMiddle; def->default_value = new ConfigOptionFloatOrPercent(30, false); def = this->add("first_layer_temperature", coInts); @@ -821,6 +866,7 @@ void PrintConfigDef::init_fff_params() "If you print from SD card, the additional weight of the file could make your firmware " "slow down."); def->cli = "gcode-comments!"; + def->mode = comExpert; def->default_value = new ConfigOptionBool(0); def = this->add("gcode_flavor", coEnum); @@ -850,6 +896,7 @@ void PrintConfigDef::init_fff_params() def->enum_labels.push_back("Machinekit"); def->enum_labels.push_back("Smoothie"); def->enum_labels.push_back(L("No extrusion")); + def->mode = comExpert; def->default_value = new ConfigOptionEnum(gcfRepRap); def = this->add("infill_acceleration", coFloat); @@ -859,6 +906,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm/s²"); def->cli = "infill-acceleration=f"; def->min = 0; + def->mode = comExpert; def->default_value = new ConfigOptionFloat(0); def = this->add("infill_every_layers", coInt); @@ -870,6 +918,7 @@ void PrintConfigDef::init_fff_params() def->cli = "infill-every-layers=i"; def->full_label = L("Combine infill every n layers"); def->min = 1; + def->mode = comMiddle; def->default_value = new ConfigOptionInt(1); def = this->add("infill_extruder", coInt); @@ -878,6 +927,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("The extruder to use when printing infill."); def->cli = "infill-extruder=i"; def->min = 1; + def->mode = comMiddle; def->default_value = new ConfigOptionInt(1); def = this->add("infill_extrusion_width", coFloatOrPercent); @@ -889,12 +939,14 @@ void PrintConfigDef::init_fff_params() "If expressed as percentage (for example 90%) it will be computed over layer height."); def->sidetext = L("mm or % (leave 0 for default)"); def->cli = "infill-extrusion-width=s"; + def->mode = comMiddle; def->default_value = new ConfigOptionFloatOrPercent(0, false); def = this->add("infill_first", coBool); def->label = L("Infill before perimeters"); def->tooltip = L("This option will switch the print order of perimeters and infill, making the latter first."); def->cli = "infill-first!"; + def->mode = comExpert; def->default_value = new ConfigOptionBool(false); def = this->add("infill_only_where_needed", coBool); @@ -904,6 +956,7 @@ void PrintConfigDef::init_fff_params() "(it will act as internal support material). If enabled, slows down the G-code generation " "due to the multiple checks involved."); def->cli = "infill-only-where-needed!"; + def->mode = comMiddle; def->default_value = new ConfigOptionBool(false); def = this->add("infill_overlap", coFloatOrPercent); @@ -915,6 +968,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm or %"); def->cli = "infill-overlap=s"; def->ratio_over = "perimeter_extrusion_width"; + def->mode = comExpert; def->default_value = new ConfigOptionFloatOrPercent(25, true); def = this->add("infill_speed", coFloat); @@ -946,6 +1000,7 @@ void PrintConfigDef::init_fff_params() "support material."); def->cli = "interface-shells!"; def->category = L("Layers and Perimeters"); + def->mode = comExpert; def->default_value = new ConfigOptionBool(false); def = this->add("layer_gcode", coString); @@ -965,11 +1020,13 @@ void PrintConfigDef::init_fff_params() " intervals into the G-code to let the firmware show accurate remaining time." " As of now only the Prusa i3 MK3 firmware recognizes M73." " Also the i3 MK3 firmware supports M73 Qxx Sxx for the silent mode."); + def->mode = comExpert; def->default_value = new ConfigOptionBool(false); def = this->add("silent_mode", coBool); def->label = L("Supports silent mode"); def->tooltip = L("Set silent mode for the G-code flavor"); + def->mode = comExpert; def->default_value = new ConfigOptionBool(true); const int machine_limits_opt_width = 70; @@ -997,6 +1054,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm/s"); def->min = 0; def->width = machine_limits_opt_width; + def->mode = comMiddle; def->default_value = new ConfigOptionFloats(axis.max_feedrate); // Add the machine acceleration limits for XYZE axes (M201) def = this->add("machine_max_acceleration_" + axis.name, coFloats); @@ -1006,6 +1064,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm/s²"); def->min = 0; def->width = machine_limits_opt_width; + def->mode = comMiddle; def->default_value = new ConfigOptionFloats(axis.max_acceleration); // Add the machine jerk limits for XYZE axes (M205) def = this->add("machine_max_jerk_" + axis.name, coFloats); @@ -1015,6 +1074,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm/s"); def->min = 0; def->width = machine_limits_opt_width; + def->mode = comMiddle; def->default_value = new ConfigOptionFloats(axis.max_jerk); } } @@ -1027,6 +1087,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm/s"); def->min = 0; def->width = machine_limits_opt_width; + def->mode = comMiddle; def->default_value = new ConfigOptionFloats{ 0., 0. }; // M205 T... [mm/sec] @@ -1037,6 +1098,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm/s"); def->min = 0; def->width = machine_limits_opt_width; + def->mode = comMiddle; def->default_value = new ConfigOptionFloats{ 0., 0. }; // M204 S... [mm/sec^2] @@ -1047,6 +1109,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm/s²"); def->min = 0; def->width = machine_limits_opt_width; + def->mode = comMiddle; def->default_value = new ConfigOptionFloats{ 1500., 1250. }; // M204 T... [mm/sec^2] @@ -1057,6 +1120,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm/s²"); def->min = 0; def->width = machine_limits_opt_width; + def->mode = comMiddle; def->default_value = new ConfigOptionFloats{ 1500., 1250. }; def = this->add("max_fan_speed", coInts); @@ -1066,6 +1130,7 @@ void PrintConfigDef::init_fff_params() def->cli = "max-fan-speed=i@"; def->min = 0; def->max = 100; + def->mode = comExpert; def->default_value = new ConfigOptionInts { 100 }; def = this->add("max_layer_height", coFloats); @@ -1077,6 +1142,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm"); def->cli = "max-layer-height=f@"; def->min = 0; + def->mode = comMiddle; def->default_value = new ConfigOptionFloats { 0. }; def = this->add("max_print_speed", coFloat); @@ -1087,6 +1153,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm/s"); def->cli = "max-print-speed=f"; def->min = 1; + def->mode = comExpert; def->default_value = new ConfigOptionFloat(80); def = this->add("max_volumetric_speed", coFloat); @@ -1096,6 +1163,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm³/s"); def->cli = "max-volumetric-speed=f"; def->min = 0; + def->mode = comExpert; def->default_value = new ConfigOptionFloat(0); def = this->add("max_volumetric_extrusion_rate_slope_positive", coFloat); @@ -1107,6 +1175,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm³/s²"); def->cli = "max-volumetric-extrusion-rate-slope-positive=f"; def->min = 0; + def->mode = comExpert; def->default_value = new ConfigOptionFloat(0); def = this->add("max_volumetric_extrusion_rate_slope_negative", coFloat); @@ -1118,6 +1187,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm³/s²"); def->cli = "max-volumetric-extrusion-rate-slope-negative=f"; def->min = 0; + def->mode = comExpert; def->default_value = new ConfigOptionFloat(0); def = this->add("min_fan_speed", coInts); @@ -1127,6 +1197,7 @@ void PrintConfigDef::init_fff_params() def->cli = "min-fan-speed=i@"; def->min = 0; def->max = 100; + def->mode = comExpert; def->default_value = new ConfigOptionInts { 35 }; def = this->add("min_layer_height", coFloats); @@ -1136,6 +1207,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm"); def->cli = "min-layer-height=f@"; def->min = 0; + def->mode = comMiddle; def->default_value = new ConfigOptionFloats { 0.07 }; def = this->add("min_print_speed", coFloats); @@ -1144,6 +1216,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm/s"); def->cli = "min-print-speed=f@"; def->min = 0; + def->mode = comExpert; def->default_value = new ConfigOptionFloats { 10. }; def = this->add("min_skirt_length", coFloat); @@ -1154,6 +1227,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm"); def->cli = "min-skirt-length=f"; def->min = 0; + def->mode = comExpert; def->default_value = new ConfigOptionFloat(0); def = this->add("notes", coString); @@ -1183,6 +1257,7 @@ void PrintConfigDef::init_fff_params() def->enum_values.push_back("duet"); def->enum_labels.push_back("OctoPrint"); def->enum_labels.push_back("Duet"); + def->mode = comMiddle; def->default_value = new ConfigOptionEnum(htOctoPrint); def = this->add("printhost_apikey", coString); @@ -1190,6 +1265,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("Slic3r can upload G-code files to a printer host. This field should contain " "the API Key or the password required for authentication."); def->cli = "printhost-apikey=s"; + def->mode = comMiddle; def->default_value = new ConfigOptionString(""); def = this->add("printhost_cafile", coString); @@ -1204,6 +1280,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("Slic3r can upload G-code files to a printer host. This field should contain " "the hostname, IP address or URL of the printer host instance."); def->cli = "print-host=s"; + def->mode = comMiddle; def->default_value = new ConfigOptionString(""); def = this->add("only_retract_when_crossing_perimeters", coBool); @@ -1211,6 +1288,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("Disables retraction when the travel path does not exceed the upper layer's perimeters " "(and thus any ooze will be probably invisible)."); def->cli = "only-retract-when-crossing-perimeters!"; + def->mode = comExpert; def->default_value = new ConfigOptionBool(true); def = this->add("ooze_prevention", coBool); @@ -1219,6 +1297,7 @@ void PrintConfigDef::init_fff_params() "It will enable a tall skirt automatically and move extruders outside such " "skirt when changing temperatures."); def->cli = "ooze-prevention!"; + def->mode = comExpert; def->default_value = new ConfigOptionBool(false); def = this->add("output_filename_format", coString); @@ -1229,6 +1308,7 @@ void PrintConfigDef::init_fff_params() "[input_filename_base]."); def->cli = "output-filename-format=s"; def->full_width = true; + def->mode = comExpert; def->default_value = new ConfigOptionString("[input_filename_base].gcode"); def = this->add("overhangs", coBool); @@ -1237,6 +1317,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("Experimental option to adjust flow for overhangs (bridge flow will be used), " "to apply bridge speed to them and enable fan."); def->cli = "overhangs!"; + def->mode = comMiddle; def->default_value = new ConfigOptionBool(true); def = this->add("parking_pos_retraction", coFloat); @@ -1246,6 +1327,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm"); def->cli = "parking_pos_retraction=f"; def->min = 0; + def->mode = comMiddle; def->default_value = new ConfigOptionFloat(92.f); def = this->add("extra_loading_move", coFloat); @@ -1255,6 +1337,7 @@ void PrintConfigDef::init_fff_params() " if negative, the loading move is shorter than unloading. "); def->sidetext = L("mm"); def->cli = "extra_loading_move=f"; + def->mode = comMiddle; def->default_value = new ConfigOptionFloat(-2.f); def = this->add("perimeter_acceleration", coFloat); @@ -1264,6 +1347,7 @@ void PrintConfigDef::init_fff_params() "Set zero to disable acceleration control for perimeters."); def->sidetext = L("mm/s²"); def->cli = "perimeter-acceleration=f"; + def->mode = comExpert; def->default_value = new ConfigOptionFloat(0); def = this->add("perimeter_extruder", coInt); @@ -1273,6 +1357,7 @@ void PrintConfigDef::init_fff_params() def->cli = "perimeter-extruder=i"; def->aliases = { "perimeters_extruder" }; def->min = 1; + def->mode = comMiddle; def->default_value = new ConfigOptionInt(1); def = this->add("perimeter_extrusion_width", coFloatOrPercent); @@ -1285,6 +1370,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm or % (leave 0 for default)"); def->cli = "perimeter-extrusion-width=s"; def->aliases = { "perimeters_extrusion_width" }; + def->mode = comMiddle; def->default_value = new ConfigOptionFloatOrPercent(0, false); def = this->add("perimeter_speed", coFloat); @@ -1321,6 +1407,7 @@ void PrintConfigDef::init_fff_params() def->multiline = true; def->full_width = true; def->height = 60; + def->mode = comExpert; def->default_value = new ConfigOptionStrings(); def = this->add("printer_model", coString); @@ -1361,6 +1448,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("layers"); def->cli = "raft-layers=i"; def->min = 0; + def->mode = comMiddle; def->default_value = new ConfigOptionInt(0); def = this->add("resolution", coFloat); @@ -1372,6 +1460,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm"); def->cli = "resolution=f"; def->min = 0; + def->mode = comExpert; def->default_value = new ConfigOptionFloat(0); def = this->add("retract_before_travel", coFloats); @@ -1379,6 +1468,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("Retraction is not triggered when travel moves are shorter than this length."); def->sidetext = L("mm"); def->cli = "retract-before-travel=f@"; + def->mode = comMiddle; def->default_value = new ConfigOptionFloats { 2. }; def = this->add("retract_before_wipe", coPercents); @@ -1387,12 +1477,14 @@ void PrintConfigDef::init_fff_params() "before doing the wipe movement."); def->sidetext = L("%"); def->cli = "retract-before-wipe=s@"; + def->mode = comMiddle; def->default_value = new ConfigOptionPercents { 0. }; def = this->add("retract_layer_change", coBools); def->label = L("Retract on layer change"); def->tooltip = L("This flag enforces a retraction whenever a Z move is done."); def->cli = "retract-layer-change!"; + def->mode = comMiddle; def->default_value = new ConfigOptionBools { false }; def = this->add("retract_length", coFloats); @@ -1412,6 +1504,7 @@ void PrintConfigDef::init_fff_params() "the extruder)."); def->sidetext = L("mm (zero to disable)"); def->cli = "retract-length-toolchange=f@"; + def->mode = comExpert; def->default_value = new ConfigOptionFloats { 10. }; def = this->add("retract_lift", coFloats); @@ -1430,6 +1523,7 @@ void PrintConfigDef::init_fff_params() "absolute Z. You can tune this setting for skipping lift on the first layers."); def->sidetext = L("mm"); def->cli = "retract-lift-above=f@"; + def->mode = comMiddle; def->default_value = new ConfigOptionFloats { 0. }; def = this->add("retract_lift_below", coFloats); @@ -1440,6 +1534,7 @@ void PrintConfigDef::init_fff_params() "to the first layers."); def->sidetext = L("mm"); def->cli = "retract-lift-below=f@"; + def->mode = comMiddle; def->default_value = new ConfigOptionFloats { 0. }; def = this->add("retract_restart_extra", coFloats); @@ -1448,6 +1543,7 @@ void PrintConfigDef::init_fff_params() "this additional amount of filament. This setting is rarely needed."); def->sidetext = L("mm"); def->cli = "retract-restart-extra=f@"; + def->mode = comMiddle; def->default_value = new ConfigOptionFloats { 0. }; def = this->add("retract_restart_extra_toolchange", coFloats); @@ -1456,6 +1552,7 @@ void PrintConfigDef::init_fff_params() "this additional amount of filament."); def->sidetext = L("mm"); def->cli = "retract-restart-extra-toolchange=f@"; + def->mode = comExpert; def->default_value = new ConfigOptionFloats { 0. }; def = this->add("retract_speed", coFloats); @@ -1464,6 +1561,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("The speed for retractions (it only applies to the extruder motor)."); def->sidetext = L("mm/s"); def->cli = "retract-speed=f@"; + def->mode = comMiddle; def->default_value = new ConfigOptionFloats { 40. }; def = this->add("deretract_speed", coFloats); @@ -1473,6 +1571,7 @@ void PrintConfigDef::init_fff_params() "(it only applies to the extruder motor). If left to zero, the retraction speed is used."); def->sidetext = L("mm/s"); def->cli = "retract-speed=f@"; + def->mode = comMiddle; def->default_value = new ConfigOptionFloats { 0. }; def = this->add("seam_position", coEnum); @@ -1489,6 +1588,7 @@ void PrintConfigDef::init_fff_params() def->enum_labels.push_back(L("Nearest")); def->enum_labels.push_back(L("Aligned")); def->enum_labels.push_back(L("Rear")); + def->mode = comMiddle; def->default_value = new ConfigOptionEnum(spAligned); #if 0 @@ -1551,6 +1651,7 @@ void PrintConfigDef::init_fff_params() "as a shield against drafts."); def->sidetext = L("layers"); def->cli = "skirt-height=i"; + def->mode = comMiddle; def->default_value = new ConfigOptionInt(1); def = this->add("skirts", coInt); @@ -1561,6 +1662,7 @@ void PrintConfigDef::init_fff_params() "to disable skirt completely."); def->cli = "skirts=i"; def->min = 0; + def->mode = comMiddle; def->default_value = new ConfigOptionInt(1); def = this->add("slowdown_below_layer_time", coInts); @@ -1572,6 +1674,7 @@ void PrintConfigDef::init_fff_params() def->width = 60; def->min = 0; def->max = 1000; + def->mode = comExpert; def->default_value = new ConfigOptionInts { 5 }; def = this->add("small_perimeter_speed", coFloatOrPercent); @@ -1593,6 +1696,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm²"); def->cli = "solid-infill-below-area=f"; def->min = 0; + def->mode = comExpert; def->default_value = new ConfigOptionFloat(70); def = this->add("solid_infill_extruder", coInt); @@ -1601,6 +1705,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("The extruder to use when printing solid infill."); def->cli = "solid-infill-extruder=i"; def->min = 1; + def->mode = comMiddle; def->default_value = new ConfigOptionInt(1); def = this->add("solid_infill_every_layers", coInt); @@ -1613,6 +1718,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("layers"); def->cli = "solid-infill-every-layers=i"; def->min = 0; + def->mode = comExpert; def->default_value = new ConfigOptionInt(0); def = this->add("solid_infill_extrusion_width", coFloatOrPercent); @@ -1623,6 +1729,7 @@ void PrintConfigDef::init_fff_params() "If expressed as percentage (for example 90%) it will be computed over layer height."); def->sidetext = L("mm or % (leave 0 for default)"); def->cli = "solid-infill-extrusion-width=s"; + def->mode = comMiddle; def->default_value = new ConfigOptionFloatOrPercent(0, false); def = this->add("solid_infill_speed", coFloatOrPercent); @@ -1664,6 +1771,7 @@ void PrintConfigDef::init_fff_params() def->cli = "standby-temperature-delta=i"; def->min = -max_temp; def->max = max_temp; + def->mode = comExpert; def->default_value = new ConfigOptionInt(-5); def = this->add("start_gcode", coString); @@ -1701,12 +1809,14 @@ void PrintConfigDef::init_fff_params() def->label = L("Single Extruder Multi Material"); def->tooltip = L("The printer multiplexes filaments into a single hot end."); def->cli = "single-extruder-multi-material!"; + def->mode = comExpert; def->default_value = new ConfigOptionBool(false); def = this->add("single_extruder_multi_material_priming", coBool); def->label = L("Prime all printing extruders"); def->tooltip = L("If enabled, all printing extruders will be primed at the front edge of the print bed at the start of the print."); def->cli = "single-extruder-multi-material-priming!"; + def->mode = comMiddle; def->default_value = new ConfigOptionBool(true); def = this->add("support_material", coBool); @@ -1722,6 +1832,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("If checked, supports will be generated automatically based on the overhang threshold value."\ " If unchecked, supports will be generated inside the \"Support Enforcer\" volumes only."); def->cli = "support-material-auto!"; + def->mode = comMiddle; def->default_value = new ConfigOptionBool(true); def = this->add("support_material_xy_spacing", coFloatOrPercent); @@ -1733,6 +1844,7 @@ void PrintConfigDef::init_fff_params() def->cli = "support-material-xy-spacing=s"; def->ratio_over = "external_perimeter_extrusion_width"; def->min = 0; + def->mode = comMiddle; // Default is half the external perimeter width. def->default_value = new ConfigOptionFloatOrPercent(50, true); @@ -1744,6 +1856,7 @@ void PrintConfigDef::init_fff_params() def->cli = "support-material-angle=f"; def->min = 0; def->max = 359; + def->mode = comExpert; def->default_value = new ConfigOptionFloat(0); def = this->add("support_material_buildplate_only", coBool); @@ -1751,6 +1864,7 @@ void PrintConfigDef::init_fff_params() def->category = L("Support material"); def->tooltip = L("Only create support if it lies on a build plate. Don't create support on a print."); def->cli = "support-material-buildplate-only!"; + def->mode = comMiddle; def->default_value = new ConfigOptionBool(false); def = this->add("support_material_contact_distance", coFloat); @@ -1767,6 +1881,7 @@ void PrintConfigDef::init_fff_params() def->enum_values.push_back("0.2"); def->enum_labels.push_back((boost::format("0 (%1%)") % L("soluble")).str()); def->enum_labels.push_back((boost::format("0.2 (%1%)") % L("detachable")).str()); + def->mode = comMiddle; def->default_value = new ConfigOptionFloat(0.2); def = this->add("support_material_enforce_layers", coInt); @@ -1780,6 +1895,7 @@ void PrintConfigDef::init_fff_params() def->cli = "support-material-enforce-layers=f"; def->full_label = L("Enforce support for the first n layers"); def->min = 0; + def->mode = comExpert; def->default_value = new ConfigOptionInt(0); def = this->add("support_material_extruder", coInt); @@ -1789,6 +1905,7 @@ void PrintConfigDef::init_fff_params() "(1+, 0 to use the current extruder to minimize tool changes)."); def->cli = "support-material-extruder=i"; def->min = 0; + def->mode = comMiddle; def->default_value = new ConfigOptionInt(1); def = this->add("support_material_extrusion_width", coFloatOrPercent); @@ -1799,6 +1916,7 @@ void PrintConfigDef::init_fff_params() "If expressed as percentage (for example 90%) it will be computed over layer height."); def->sidetext = L("mm or % (leave 0 for default)"); def->cli = "support-material-extrusion-width=s"; + def->mode = comMiddle; def->default_value = new ConfigOptionFloatOrPercent(0, false); def = this->add("support_material_interface_contact_loops", coBool); @@ -1806,6 +1924,7 @@ void PrintConfigDef::init_fff_params() def->category = L("Support material"); def->tooltip = L("Cover the top contact layer of the supports with loops. Disabled by default."); def->cli = "support-material-interface-contact-loops!"; + def->mode = comExpert; def->default_value = new ConfigOptionBool(false); def = this->add("support_material_interface_extruder", coInt); @@ -1815,6 +1934,7 @@ void PrintConfigDef::init_fff_params() "(1+, 0 to use the current extruder to minimize tool changes). This affects raft too."); def->cli = "support-material-interface-extruder=i"; def->min = 0; + def->mode = comMiddle; def->default_value = new ConfigOptionInt(1); def = this->add("support_material_interface_layers", coInt); @@ -1824,6 +1944,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("layers"); def->cli = "support-material-interface-layers=i"; def->min = 0; + def->mode = comMiddle; def->default_value = new ConfigOptionInt(3); def = this->add("support_material_interface_spacing", coFloat); @@ -1833,6 +1954,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm"); def->cli = "support-material-interface-spacing=f"; def->min = 0; + def->mode = comMiddle; def->default_value = new ConfigOptionFloat(0); def = this->add("support_material_interface_speed", coFloatOrPercent); @@ -1858,6 +1980,7 @@ void PrintConfigDef::init_fff_params() def->enum_labels.push_back(L("Rectilinear")); def->enum_labels.push_back(L("Rectilinear grid")); def->enum_labels.push_back(L("Honeycomb")); + def->mode = comMiddle; def->default_value = new ConfigOptionEnum(smpRectilinear); def = this->add("support_material_spacing", coFloat); @@ -1867,6 +1990,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm"); def->cli = "support-material-spacing=f"; def->min = 0; + def->mode = comMiddle; def->default_value = new ConfigOptionFloat(2.5); def = this->add("support_material_speed", coFloat); @@ -1884,6 +2008,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("Synchronize support layers with the object print layers. This is useful " "with multi-material printers, where the extruder switch is expensive."); def->cli = "support-material-synchronize-layers!"; + def->mode = comExpert; def->default_value = new ConfigOptionBool(false); def = this->add("support_material_threshold", coInt); @@ -1898,6 +2023,7 @@ void PrintConfigDef::init_fff_params() def->cli = "support-material-threshold=i"; def->min = 0; def->max = 90; + def->mode = comMiddle; def->default_value = new ConfigOptionInt(0); def = this->add("support_material_with_sheath", coBool); @@ -1906,6 +2032,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("Add a sheath (a single perimeter line) around the base support. This makes " "the support more reliable, but also more difficult to remove."); def->cli = "support-material-with-sheath!"; + def->mode = comExpert; def->default_value = new ConfigOptionBool(true); def = this->add("temperature", coInts); @@ -1924,6 +2051,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("Detect single-width walls (parts where two extrusions don't fit and we need " "to collapse them into a single trace)."); def->cli = "thin-walls!"; + def->mode = comMiddle; def->default_value = new ConfigOptionBool(true); def = this->add("threads", coInt); @@ -1958,6 +2086,7 @@ void PrintConfigDef::init_fff_params() "If expressed as percentage (for example 90%) it will be computed over layer height."); def->sidetext = L("mm or % (leave 0 for default)"); def->cli = "top-infill-extrusion-width=s"; + def->mode = comMiddle; def->default_value = new ConfigOptionFloatOrPercent(0, false); def = this->add("top_solid_infill_speed", coFloatOrPercent); @@ -1990,6 +2119,7 @@ void PrintConfigDef::init_fff_params() def->cli = "travel-speed=f"; def->aliases = { "travel_feed_rate" }; def->min = 1; + def->mode = comMiddle; def->default_value = new ConfigOptionFloat(130); def = this->add("use_firmware_retraction", coBool); @@ -1997,6 +2127,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("This experimental setting uses G10 and G11 commands to have the firmware " "handle the retraction. This is only supported in recent Marlin."); def->cli = "use-firmware-retraction!"; + def->mode = comExpert; def->default_value = new ConfigOptionBool(false); def = this->add("use_relative_e_distances", coBool); @@ -2004,6 +2135,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("If your firmware requires relative E values, check this, " "otherwise leave it unchecked. Most firmwares use absolute values."); def->cli = "use-relative-e-distances!"; + def->mode = comExpert; def->default_value = new ConfigOptionBool(false); def = this->add("use_volumetric_e", coBool); @@ -2015,6 +2147,7 @@ void PrintConfigDef::init_fff_params() "diameter associated to the filament selected in Slic3r. This is only supported " "in recent Marlin."); def->cli = "use-volumetric-e!"; + def->mode = comExpert; def->default_value = new ConfigOptionBool(false); def = this->add("variable_layer_height", coBool); @@ -2022,6 +2155,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("Some printers or printer setups may have difficulties printing " "with a variable layer height. Enabled by default."); def->cli = "variable-layer-height!"; + def->mode = comExpert; def->default_value = new ConfigOptionBool(true); def = this->add("wipe", coBools); @@ -2029,6 +2163,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("This flag will move the nozzle while retracting to minimize the possible blob " "on leaky extruders."); def->cli = "wipe!"; + def->mode = comMiddle; def->default_value = new ConfigOptionBools { false }; def = this->add("wipe_tower", coBool); @@ -2036,6 +2171,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("Multi material printers may need to prime or purge extruders on tool changes. " "Extrude the excess material into the wipe tower."); def->cli = "wipe-tower!"; + def->mode = comMiddle; def->default_value = new ConfigOptionBool(false); def = this->add("wiping_volumes_extruders", coFloats); @@ -2062,6 +2198,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("X coordinate of the left front corner of a wipe tower"); def->sidetext = L("mm"); def->cli = "wipe-tower-x=f"; + def->mode = comMiddle; def->default_value = new ConfigOptionFloat(180.); def = this->add("wipe_tower_y", coFloat); @@ -2069,6 +2206,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("Y coordinate of the left front corner of a wipe tower"); def->sidetext = L("mm"); def->cli = "wipe-tower-y=f"; + def->mode = comMiddle; def->default_value = new ConfigOptionFloat(140.); def = this->add("wipe_tower_width", coFloat); @@ -2076,6 +2214,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("Width of a wipe tower"); def->sidetext = L("mm"); def->cli = "wipe-tower-width=f"; + def->mode = comMiddle; def->default_value = new ConfigOptionFloat(60.); def = this->add("wipe_tower_rotation_angle", coFloat); @@ -2083,6 +2222,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("Wipe tower rotation angle with respect to x-axis "); def->sidetext = L("degrees"); def->cli = "wipe-tower-rotation-angle=f"; + def->mode = comMiddle; def->default_value = new ConfigOptionFloat(0.); def = this->add("wipe_into_infill", coBool); @@ -2108,6 +2248,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("Maximal distance between supports on sparse infill sections. "); def->sidetext = L("mm"); def->cli = "wipe-tower-bridging=f"; + def->mode = comMiddle; def->default_value = new ConfigOptionFloat(10.); def = this->add("xy_size_compensation", coFloat); @@ -2118,6 +2259,7 @@ void PrintConfigDef::init_fff_params() "for fine-tuning hole sizes."); def->sidetext = L("mm"); def->cli = "xy-size-compensation=f"; + def->mode = comExpert; def->default_value = new ConfigOptionFloat(0); def = this->add("z_offset", coFloat); @@ -2128,6 +2270,7 @@ void PrintConfigDef::init_fff_params() "from the print bed, set this to -0.3 (or fix your endstop)."); def->sidetext = L("mm"); def->cli = "z-offset=f"; + def->mode = comMiddle; def->default_value = new ConfigOptionFloat(0); def = this->add("bed_size_x", coFloat); @@ -2150,6 +2293,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("px"); def->cli = "pixel-width=i"; def->min = 1; + def->mode = comExpert; def->default_value = new ConfigOptionInt(1440); def = this->add("pixel_height", coInt); diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index ab7f2e13ec..c1683bba34 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -482,7 +482,8 @@ ConfigMenuIDs GUI_App::get_view_mode() return ConfigMenuModeSimple; const auto mode = app_config->get("view_mode"); - return mode == "expert" ? ConfigMenuModeExpert : ConfigMenuModeSimple; + return mode == "expert" ? ConfigMenuModeExpert : + mode == "simple" ? ConfigMenuModeSimple : ConfigMenuModeMiddle; } // Update view mode according to selected menu @@ -500,6 +501,11 @@ void GUI_App::update_mode() sidebar().Layout(); mainframe->m_plater->Layout(); + + ConfigOptionMode opt_mode = mode == ConfigMenuModeSimple ? comSimple : + mode == ConfigMenuModeExpert ? comExpert : comMiddle; + for (auto tab : tabs_list) + tab->update_visibility(opt_mode); } void GUI_App::add_config_menu(wxMenuBar *menu) @@ -519,6 +525,7 @@ void GUI_App::add_config_menu(wxMenuBar *menu) local_menu->AppendSeparator(); auto mode_menu = new wxMenu(); mode_menu->AppendRadioItem(config_id_base + ConfigMenuModeSimple, _(L("&Simple")), _(L("Simple View Mode"))); + mode_menu->AppendRadioItem(config_id_base + ConfigMenuModeMiddle, _(L("&Middle")), _(L("Middle View Mode"))); mode_menu->AppendRadioItem(config_id_base + ConfigMenuModeExpert, _(L("&Expert")), _(L("Expert View Mode"))); mode_menu->Check(config_id_base + get_view_mode(), true); local_menu->AppendSubMenu(mode_menu, _(L("&Mode")), _(L("Slic3r View Mode"))); @@ -589,8 +596,9 @@ void GUI_App::add_config_menu(wxMenuBar *menu) } }); mode_menu->Bind(wxEVT_MENU, [this, config_id_base](wxEvent& event) { - std::string mode = event.GetId() - config_id_base == ConfigMenuModeExpert ? - "expert" : "simple"; + int id_mode = event.GetId() - config_id_base; + std::string mode = id_mode == ConfigMenuModeExpert ? "expert" : + id_mode == ConfigMenuModeSimple ? "simple" : "middle"; app_config->set("view_mode", mode); app_config->save(); update_mode(); diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 502ce0ee17..52d5826903 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -51,6 +51,7 @@ enum ConfigMenuIDs { ConfigMenuUpdate, ConfigMenuPreferences, ConfigMenuModeSimple, + ConfigMenuModeMiddle, ConfigMenuModeExpert, ConfigMenuLanguage, ConfigMenuFlashFirmware, diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp index fc51b419ba..ca35871187 100644 --- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp +++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp @@ -221,7 +221,7 @@ void ObjectManipulation::update_settings_list() if (cat.second.size() == 1 && cat.second[0] == "extruder") continue; - auto optgroup = std::make_shared(parent, cat.first, config, false, ogDEFAULT, extra_column); + auto optgroup = std::make_shared(parent, cat.first, config, false, extra_column); optgroup->label_width = 150; optgroup->sidetext_width = 70; diff --git a/src/slic3r/GUI/OptionsGroup.cpp b/src/slic3r/GUI/OptionsGroup.cpp index bfe54c3ced..828cf72d94 100644 --- a/src/slic3r/GUI/OptionsGroup.cpp +++ b/src/slic3r/GUI/OptionsGroup.cpp @@ -156,16 +156,8 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** colored_Label/* #endif /* __WXGTK__ */ // if we have an extra column, build it - if (extra_column) { - if (extra_column) { - grid_sizer->Add(extra_column(parent(), line), 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 3); - } - else { - // if the callback provides no sizer for the extra cell, put a spacer - grid_sizer->AddSpacer(1); - } - } - + if (extra_column) + grid_sizer->Add(extra_column(parent(), line), 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 3); // Build a label if we have it wxStaticText* label=nullptr; @@ -182,16 +174,14 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** colored_Label/* label->SetFont(label_font); label->Wrap(label_width); // avoid a Linux/GTK bug if (!line.near_label_widget) - grid_sizer->Add(label, 0, (staticbox ? 0 : wxALIGN_RIGHT | wxRIGHT) | - (m_flag == ogSIDE_OPTIONS_VERTICAL ? wxTOP : wxALIGN_CENTER_VERTICAL), 5); + grid_sizer->Add(label, 0, (staticbox ? 0 : wxALIGN_RIGHT | wxRIGHT) | wxALIGN_CENTER_VERTICAL, 5); else { // If we're here, we have some widget near the label // so we need a horizontal sizer to arrange these things auto sizer = new wxBoxSizer(wxHORIZONTAL); grid_sizer->Add(sizer, 0, wxEXPAND | (staticbox ? wxALL : wxBOTTOM | wxTOP | wxLEFT), staticbox ? 0 : 1); sizer->Add(line.near_label_widget(parent()), 0, wxRIGHT, 7); - sizer->Add(label, 0, (staticbox ? 0 : wxALIGN_RIGHT | wxRIGHT) | - (m_flag == ogSIDE_OPTIONS_VERTICAL ? wxTOP : wxALIGN_CENTER_VERTICAL), 5); + sizer->Add(label, 0, (staticbox ? 0 : wxALIGN_RIGHT | wxRIGHT) | wxALIGN_CENTER_VERTICAL, 5); } if (line.label_tooltip.compare("") != 0) label->SetToolTip(line.label_tooltip); @@ -208,7 +198,7 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** colored_Label/* // If we're here, we have more than one option or a single option with sidetext // so we need a horizontal sizer to arrange these things - auto sizer = new wxBoxSizer(m_flag == ogSIDE_OPTIONS_VERTICAL ? wxVERTICAL : wxHORIZONTAL); + auto sizer = new wxBoxSizer(wxHORIZONTAL); grid_sizer->Add(sizer, 0, wxEXPAND | (staticbox ? wxALL : wxBOTTOM | wxTOP | wxLEFT), staticbox ? 0 : 1); // If we have a single option with no sidetext just add it directly to the grid sizer if (option_set.size() == 1 && option_set.front().opt.sidetext.size() == 0 && @@ -227,14 +217,7 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** colored_Label/* for (auto opt : option_set) { ConfigOptionDef option = opt.opt; - wxSizer* sizer_tmp; - if (m_flag == ogSIDE_OPTIONS_VERTICAL){ - auto sz = new wxFlexGridSizer(1, 3, 2, 2); - sz->RemoveGrowableCol(2); - sizer_tmp = sz; - } - else - sizer_tmp = sizer; + wxSizer* sizer_tmp = sizer; // add label if any if (option.label != "") { wxString str_label = _(option.label); @@ -260,7 +243,7 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** colored_Label/* auto sidetext = new wxStaticText( parent(), wxID_ANY, _(option.sidetext), wxDefaultPosition, wxSize(sidetext_width, -1)/*wxDefaultSize*/, wxALIGN_LEFT); sidetext->SetFont(sidetext_font); - sizer_tmp->Add(sidetext, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, m_flag == ogSIDE_OPTIONS_VERTICAL ? 0 : 4); + sizer_tmp->Add(sidetext, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, 4); field->set_side_text_ptr(sidetext); } @@ -269,13 +252,10 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** colored_Label/* sizer_tmp->Add(opt.side_widget(parent())/*!.target()*/, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, 1); //! requires verification } - if (opt.opt_id != option_set.back().opt_id && m_flag != ogSIDE_OPTIONS_VERTICAL) //! istead of (opt != option_set.back()) + if (opt.opt_id != option_set.back().opt_id) //! istead of (opt != option_set.back()) { sizer_tmp->AddSpacer(6); } - - if (m_flag == ogSIDE_OPTIONS_VERTICAL) - sizer->Add(sizer_tmp, 0, wxALIGN_RIGHT|wxALL, 0); } // add extra sizers if any for (auto extra_widget : line.get_extra_widgets()) { @@ -403,6 +383,27 @@ void ConfigOptionsGroup::reload_config(){ } +void ConfigOptionsGroup::update_visibility(ConfigOptionMode mode) { + int rows = m_grid_sizer->GetEffectiveRowsCount(); + if (rows != m_options.size()) + return; + sizer->ShowItems(true); + + int coef = 0; + const int cols = m_grid_sizer->GetCols(); + for (std::map::iterator it = m_options.begin(); it != m_options.end(); ++it) { + const bool show = it->second.opt.mode <= mode; + if (!show) { + for (int i = 0; i < cols; ++i) + m_grid_sizer->Show(coef + i, show); + } + coef+= cols; + } + + if (!sizer->IsShown(m_grid_sizer)) + sizer->ShowItems(false); +} + boost::any ConfigOptionsGroup::config_value(const std::string& opt_key, int opt_index, bool deserialize){ if (deserialize) { diff --git a/src/slic3r/GUI/OptionsGroup.hpp b/src/slic3r/GUI/OptionsGroup.hpp index 8ee2ee1671..66f2d1d37e 100644 --- a/src/slic3r/GUI/OptionsGroup.hpp +++ b/src/slic3r/GUI/OptionsGroup.hpp @@ -27,11 +27,6 @@ namespace Slic3r { namespace GUI { -enum ogDrawFlag{ - ogDEFAULT, - ogSIDE_OPTIONS_VERTICAL -}; - /// Widget type describes a function object that returns a wxWindow (our widget) and accepts a wxWidget (parent window). using widget_t = std::function;//!std::function; @@ -151,7 +146,6 @@ public: inline void enable() { for (auto& field : m_fields) field.second->enable(); } inline void disable() { for (auto& field : m_fields) field.second->disable(); } - void set_flag(ogDrawFlag flag) { m_flag = flag; } void set_grid_vgap(int gap) { m_grid_sizer->SetVGap(gap); } void set_show_modified_btns_val(bool show) { @@ -159,9 +153,10 @@ public: } OptionsGroup( wxWindow* _parent, const wxString& title, bool is_tab_opt = false, - ogDrawFlag flag = ogDEFAULT, column_t extra_clmn = nullptr) : - m_parent(_parent), title(title), m_show_modified_btns(is_tab_opt), - staticbox(title!=""), m_flag(flag), extra_column(extra_clmn){ + column_t extra_clmn = nullptr) : + m_parent(_parent), title(title), + m_show_modified_btns(is_tab_opt), + staticbox(title!=""), extra_column(extra_clmn){ if (staticbox) { stb = new wxStaticBox(_parent, wxID_ANY, title); stb->SetFont(wxGetApp().bold_font()); @@ -172,7 +167,7 @@ public: if (extra_column != nullptr) num_columns++; m_grid_sizer = new wxFlexGridSizer(0, num_columns, 1,0); static_cast(m_grid_sizer)->SetFlexibleDirection(wxBOTH/*wxHORIZONTAL*/); - static_cast(m_grid_sizer)->AddGrowableCol(label_width != 0); + static_cast(m_grid_sizer)->AddGrowableCol(label_width == 0 ? 0 : !extra_column ? 1 : 2 ); #ifdef __WXGTK__ m_panel = new wxPanel( _parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); sizer->Fit(m_panel); @@ -197,8 +192,6 @@ protected: // "true" if option is created in preset tabs bool m_show_modified_btns{ false }; - ogDrawFlag m_flag{ ogDEFAULT }; - // This panel is needed for correct showing of the ToolTips for Button, StaticText and CheckBox // Tooltips on GTK doesn't work inside wxStaticBoxSizer unless you insert a panel // inside it before you insert the other controls. @@ -223,8 +216,8 @@ protected: class ConfigOptionsGroup: public OptionsGroup { public: ConfigOptionsGroup( wxWindow* parent, const wxString& title, DynamicPrintConfig* _config = nullptr, - bool is_tab_opt = false, ogDrawFlag flag = ogDEFAULT, column_t extra_clmn = nullptr) : - OptionsGroup(parent, title, is_tab_opt, flag, extra_clmn), m_config(_config) {} + bool is_tab_opt = false, column_t extra_clmn = nullptr) : + OptionsGroup(parent, title, is_tab_opt, extra_clmn), m_config(_config) {} /// reference to libslic3r config, non-owning pointer (?). DynamicPrintConfig* m_config {nullptr}; @@ -252,6 +245,7 @@ public: void back_to_config_value(const DynamicPrintConfig& config, const std::string& opt_key); void on_kill_focus() override{ reload_config();} void reload_config(); + void update_visibility(ConfigOptionMode mode); boost::any config_value(const std::string& opt_key, int opt_index, bool deserialize); // return option value from config boost::any get_config_value(const DynamicPrintConfig& config, const std::string& opt_key, int opt_index = -1); diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 3b9fe0bd39..3bcd05ffda 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -632,6 +632,14 @@ void Tab::reload_config(){ Thaw(); } +void Tab::update_visibility(ConfigOptionMode mode) +{ + Freeze(); + for (auto page : m_pages) + page->update_visibility(mode); + Thaw(); +} + Field* Tab::get_field(const t_config_option_key& opt_key, int opt_index/* = -1*/) const { Field* field = nullptr; @@ -1021,7 +1029,7 @@ void TabPrint::build() page = add_options_page(_(L("Dependencies")), "wrench.png"); optgroup = page->new_optgroup(_(L("Profile dependencies"))); - line = { _(L("Compatible printers")), "" }; + line = optgroup->create_single_option_line("compatible_printers");//{ _(L("Compatible printers")), "" }; line.widget = [this](wxWindow* parent){ return compatible_printers_widget(parent, &m_compatible_printers_checkbox, &m_compatible_printers_btn); }; @@ -1347,7 +1355,7 @@ void TabFilament::build() optgroup->append_single_option_line("filament_cooling_final_speed"); optgroup->append_single_option_line("filament_minimal_purge_on_wipe_tower"); - line = { _(L("Ramming")), "" }; + line = optgroup->create_single_option_line("filament_ramming_parameters");// { _(L("Ramming")), "" }; line.widget = [this](wxWindow* parent){ auto ramming_dialog_btn = new wxButton(parent, wxID_ANY, _(L("Ramming settings"))+dots, wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT); auto sizer = new wxBoxSizer(wxHORIZONTAL); @@ -1387,7 +1395,7 @@ void TabFilament::build() page = add_options_page(_(L("Dependencies")), "wrench.png"); optgroup = page->new_optgroup(_(L("Profile dependencies"))); - line = { _(L("Compatible printers")), "" }; + line = optgroup->create_single_option_line("compatible_printers");//{ _(L("Compatible printers")), "" }; line.widget = [this](wxWindow* parent){ return compatible_printers_widget(parent, &m_compatible_printers_checkbox, &m_compatible_printers_btn); }; @@ -1482,7 +1490,7 @@ void TabPrinter::build_fff() auto page = add_options_page(_(L("General")), "printer_empty.png"); auto optgroup = page->new_optgroup(_(L("Size and coordinates"))); - Line line{ _(L("Bed shape")), "" }; + Line line = optgroup->create_single_option_line("bed_shape");//{ _(L("Bed shape")), "" }; line.widget = [this](wxWindow* parent){ auto btn = new wxButton(parent, wxID_ANY, _(L(" Set "))+dots, wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT); btn->SetFont(wxGetApp().small_font()); @@ -1514,6 +1522,7 @@ void TabPrinter::build_fff() def.label = L("Extruders"); def.tooltip = L("Number of extruders of the printer."); def.min = 1; + def.mode = comExpert; Option option(def, "extruders_count"); optgroup->append_single_option_line(option); optgroup->append_single_option_line("single_extruder_multi_material"); @@ -2681,6 +2690,12 @@ void Page::reload_config() group->reload_config(); } +void Page::update_visibility(ConfigOptionMode mode) +{ + for (auto group : m_optgroups) + group->update_visibility(mode); +} + Field* Page::get_field(const t_config_option_key& opt_key, int opt_index /*= -1*/) const { Field* field = nullptr; @@ -2704,8 +2719,22 @@ bool Page::set_value(const t_config_option_key& opt_key, const boost::any& value // package Slic3r::GUI::Tab::Page; ConfigOptionsGroupShp Page::new_optgroup(const wxString& title, int noncommon_label_width /*= -1*/) { + auto extra_column = [](wxWindow* parent, const Line& line) + { + std::string bmp_name; + if (line.get_options().size() == 0) + bmp_name = "error.png"; + else { + auto mode = line.get_options()[0].opt.mode; //we assume that we have one option per line + bmp_name = mode == comExpert ? "mode_expert.png" : + mode == comMiddle ? "mode_middle.png" : "mode_simple.png"; + } + auto bmp = new wxStaticBitmap(parent, wxID_ANY, wxBitmap(from_u8(var(bmp_name)), wxBITMAP_TYPE_PNG)); + return bmp; + }; + //! config_ have to be "right" - ConfigOptionsGroupShp optgroup = std::make_shared(this, title, m_config, true); + ConfigOptionsGroupShp optgroup = std::make_shared(this, title, m_config, true, extra_column); if (noncommon_label_width >= 0) optgroup->label_width = noncommon_label_width; @@ -2844,7 +2873,7 @@ void TabSLAMaterial::build() page = add_options_page(_(L("Dependencies")), "wrench.png"); optgroup = page->new_optgroup(_(L("Profile dependencies"))); - auto line = Line { _(L("Compatible printers")), "" }; + Line line = optgroup->create_single_option_line("compatible_printers");//Line { _(L("Compatible printers")), "" }; line.widget = [this](wxWindow* parent){ return compatible_printers_widget(parent, &m_compatible_printers_checkbox, &m_compatible_printers_btn); }; diff --git a/src/slic3r/GUI/Tab.hpp b/src/slic3r/GUI/Tab.hpp index fecb642f4d..e0c6f318e4 100644 --- a/src/slic3r/GUI/Tab.hpp +++ b/src/slic3r/GUI/Tab.hpp @@ -73,6 +73,7 @@ public: size_t iconID() const { return m_iconID; } void set_config(DynamicPrintConfig* config_in) { m_config = config_in; } void reload_config(); + void update_visibility(ConfigOptionMode mode); Field* get_field(const t_config_option_key& opt_key, int opt_index = -1) const; bool set_value(const t_config_option_key& opt_key, const boost::any& value); ConfigOptionsGroupShp new_optgroup(const wxString& title, int noncommon_label_width = -1); @@ -249,6 +250,7 @@ public: void update_tab_ui(); void load_config(const DynamicPrintConfig& config); virtual void reload_config(); + void update_visibility(ConfigOptionMode mode); Field* get_field(const t_config_option_key& opt_key, int opt_index = -1) const; bool set_value(const t_config_option_key& opt_key, const boost::any& value); wxSizer* description_line_widget(wxWindow* parent, ogStaticText** StaticText); diff --git a/src/slic3r/GUI/wxExtensions.hpp b/src/slic3r/GUI/wxExtensions.hpp index 6f61ebee15..4ff73027c9 100644 --- a/src/slic3r/GUI/wxExtensions.hpp +++ b/src/slic3r/GUI/wxExtensions.hpp @@ -261,7 +261,10 @@ public: m_name = "Settings to modified"; } else if (type == itInstanceRoot) { - m_name = "Instances"; + m_name = "Instances"; +#ifdef __WXGTK__ + m_container = true; +#endif //__WXGTK__ } else if (type == itInstance) { m_idx = parent->GetChildCount(); From 70f4ca3f5b79a8f5b9eba8c046e8f8af717eb956 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Sun, 21 Oct 2018 23:09:24 +0200 Subject: [PATCH 142/186] Completed settings hiding according to view mode --- src/libslic3r/PrintConfig.cpp | 12 ++++++++++ src/slic3r/GUI/Field.hpp | 9 ++++--- src/slic3r/GUI/OptionsGroup.cpp | 26 +++++++++++++------- src/slic3r/GUI/OptionsGroup.hpp | 4 +++- src/slic3r/GUI/Tab.cpp | 42 ++++++++++++++++++++++++++++++--- src/slic3r/GUI/Tab.hpp | 3 +++ 6 files changed, 80 insertions(+), 16 deletions(-) diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index f6358906b4..2b21a760fe 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -97,6 +97,7 @@ void PrintConfigDef::init_fff_params() def->multiline = true; def->full_width = true; def->height = 50; + def->mode = comExpert; def->default_value = new ConfigOptionString(""); def = this->add("between_objects_gcode", coString); @@ -106,6 +107,7 @@ void PrintConfigDef::init_fff_params() def->multiline = true; def->full_width = true; def->height = 120; + def->mode = comExpert; def->default_value = new ConfigOptionString(""); def = this->add("bottom_solid_layers", coInt); @@ -314,6 +316,7 @@ void PrintConfigDef::init_fff_params() def->multiline = true; def->full_width = true; def->height = 120; + def->mode = comExpert; def->default_value = new ConfigOptionString("M104 S0 ; turn off temperature\nG28 X0 ; home X axis\nM84 ; disable motors\n"); def = this->add("end_filament_gcode", coStrings); @@ -325,6 +328,7 @@ void PrintConfigDef::init_fff_params() def->multiline = true; def->full_width = true; def->height = 120; + def->mode = comExpert; def->default_value = new ConfigOptionStrings { "; Filament-specific end gcode \n;END gcode for filament\n" }; def = this->add("ensure_vertical_shell_thickness", coBool); @@ -519,6 +523,7 @@ void PrintConfigDef::init_fff_params() def->multiline = true; def->full_width = true; def->height = 130; + def->mode = comMiddle; def->default_value = new ConfigOptionStrings { "" }; def = this->add("filament_max_volumetric_speed", coFloats); @@ -1012,6 +1017,7 @@ void PrintConfigDef::init_fff_params() def->multiline = true; def->full_width = true; def->height = 50; + def->mode = comExpert; def->default_value = new ConfigOptionString(""); def = this->add("remaining_times", coBool); @@ -1238,6 +1244,7 @@ void PrintConfigDef::init_fff_params() def->multiline = true; def->full_width = true; def->height = 130; + def->mode = comMiddle; def->default_value = new ConfigOptionString(""); def = this->add("nozzle_diameter", coFloats); @@ -1422,6 +1429,7 @@ void PrintConfigDef::init_fff_params() def->multiline = true; def->full_width = true; def->height = 130; + def->mode = comMiddle; def->default_value = new ConfigOptionString(""); def = this->add("printer_vendor", coString); @@ -1787,6 +1795,7 @@ void PrintConfigDef::init_fff_params() def->multiline = true; def->full_width = true; def->height = 120; + def->mode = comExpert; def->default_value = new ConfigOptionString("G28 ; home all axes\nG1 Z5 F5000 ; lift nozzle\n"); def = this->add("start_filament_gcode", coStrings); @@ -1803,6 +1812,7 @@ void PrintConfigDef::init_fff_params() def->multiline = true; def->full_width = true; def->height = 120; + def->mode = comExpert; def->default_value = new ConfigOptionStrings { "; Filament gcode\n" }; def = this->add("single_extruder_multi_material", coBool); @@ -2075,6 +2085,7 @@ void PrintConfigDef::init_fff_params() def->multiline = true; def->full_width = true; def->height = 50; + def->mode = comExpert; def->default_value = new ConfigOptionString(""); def = this->add("top_infill_extrusion_width", coFloatOrPercent); @@ -2406,6 +2417,7 @@ void PrintConfigDef::init_sla_params() def->multiline = true; def->full_width = true; def->height = 130; + def->mode = comMiddle; def->default_value = new ConfigOptionString(""); def = this->add("default_sla_material_profile", coString); diff --git a/src/slic3r/GUI/Field.hpp b/src/slic3r/GUI/Field.hpp index c38658e2b9..58c6afebe0 100644 --- a/src/slic3r/GUI/Field.hpp +++ b/src/slic3r/GUI/Field.hpp @@ -54,10 +54,13 @@ public: virtual bool AcceptsFocusFromKeyboard() const { return false; } + void set_as_hidden() { + Hide(); + hidden = true; + } + virtual bool Show(bool show = true) override { - if (!show) - hidden = true; - return wxButton::Show(!hidden); + return wxButton::Show(hidden ? false : show); } }; diff --git a/src/slic3r/GUI/OptionsGroup.cpp b/src/slic3r/GUI/OptionsGroup.cpp index 828cf72d94..8ee78cee6d 100644 --- a/src/slic3r/GUI/OptionsGroup.cpp +++ b/src/slic3r/GUI/OptionsGroup.cpp @@ -97,8 +97,8 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co void OptionsGroup::add_undo_buttuns_to_sizer(wxSizer* sizer, const t_field& field) { if (!m_show_modified_btns) { - field->m_Undo_btn->Hide(); - field->m_Undo_to_sys_btn->Hide(); + field->m_Undo_btn->set_as_hidden(); + field->m_Undo_to_sys_btn->set_as_hidden(); return; } @@ -123,6 +123,10 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** colored_Label/* for (auto opt : option_set) m_options.emplace(opt.opt_id, opt); + // add mode value for current line to m_options_mode + if (!option_set.empty()) + m_options_mode.push_back(option_set[0].opt.mode); + // if we have a single option with no label, no sidetext just add it directly to sizer if (option_set.size() == 1 && label_width == 0 && option_set.front().opt.full_width && option_set.front().opt.sidetext.size() == 0 && option_set.front().side_widget == nullptr && @@ -383,16 +387,17 @@ void ConfigOptionsGroup::reload_config(){ } -void ConfigOptionsGroup::update_visibility(ConfigOptionMode mode) { - int rows = m_grid_sizer->GetEffectiveRowsCount(); - if (rows != m_options.size()) - return; +bool ConfigOptionsGroup::update_visibility(ConfigOptionMode mode) { + if (m_grid_sizer->GetEffectiveRowsCount() != m_options_mode.size() && + m_options_mode.size() == 1) + return m_options_mode[0] <= mode; + sizer->ShowItems(true); int coef = 0; const int cols = m_grid_sizer->GetCols(); - for (std::map::iterator it = m_options.begin(); it != m_options.end(); ++it) { - const bool show = it->second.opt.mode <= mode; + for (auto opt_mode : m_options_mode) { + const bool show = opt_mode <= mode; if (!show) { for (int i = 0; i < cols; ++i) m_grid_sizer->Show(coef + i, show); @@ -400,8 +405,11 @@ void ConfigOptionsGroup::update_visibility(ConfigOptionMode mode) { coef+= cols; } - if (!sizer->IsShown(m_grid_sizer)) + if (!sizer->IsShown(m_grid_sizer)) { sizer->ShowItems(false); + return false; + } + return true; } boost::any ConfigOptionsGroup::config_value(const std::string& opt_key, int opt_index, bool deserialize){ diff --git a/src/slic3r/GUI/OptionsGroup.hpp b/src/slic3r/GUI/OptionsGroup.hpp index 66f2d1d37e..656ae1d722 100644 --- a/src/slic3r/GUI/OptionsGroup.hpp +++ b/src/slic3r/GUI/OptionsGroup.hpp @@ -182,6 +182,7 @@ public: protected: std::map m_options; wxWindow* m_parent {nullptr}; + std::vector m_options_mode; /// Field list, contains unique_ptrs of the derived type. /// using types that need to know what it is beyond the public interface @@ -245,7 +246,8 @@ public: void back_to_config_value(const DynamicPrintConfig& config, const std::string& opt_key); void on_kill_focus() override{ reload_config();} void reload_config(); - void update_visibility(ConfigOptionMode mode); + // return value shows visibility : false => all options are hidden + bool update_visibility(ConfigOptionMode mode); boost::any config_value(const std::string& opt_key, int opt_index, bool deserialize); // return option value from config boost::any get_config_value(const DynamicPrintConfig& config, const std::string& opt_key, int opt_index = -1); diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 3bcd05ffda..bb7aa3e9b6 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -635,9 +635,15 @@ void Tab::reload_config(){ void Tab::update_visibility(ConfigOptionMode mode) { Freeze(); + for (auto page : m_pages) page->update_visibility(mode); - Thaw(); + update_page_tree_visibility(); + + m_hsizer->Layout(); + Refresh(); + + Thaw(); } Field* Tab::get_field(const t_config_option_key& opt_key, int opt_index/* = -1*/) const @@ -2264,6 +2270,33 @@ void Tab::rebuild_page_tree(bool tree_sel_change_event /*= false*/) Thaw(); } +void Tab::update_page_tree_visibility() +{ + const auto sel_item = m_treectrl->GetSelection(); + const auto selected = sel_item ? m_treectrl->GetItemText(sel_item) : ""; + const auto rootItem = m_treectrl->GetRootItem(); + + auto have_selection = 0; + m_treectrl->DeleteChildren(rootItem); + for (auto p : m_pages) + { + if (!p->get_show()) + continue; + auto itemId = m_treectrl->AppendItem(rootItem, p->title(), p->iconID()); + m_treectrl->SetItemTextColour(itemId, p->get_item_colour()); + if (p->title() == selected) { + m_treectrl->SelectItem(itemId); + have_selection = 1; + } + } + + if (!have_selection) { + // this is triggered on first load, so we don't disable the sel change event + m_treectrl->SelectItem(m_treectrl->GetFirstVisibleItem());//! (treectrl->GetFirstChild(rootItem)); + } + +} + // Called by the UI combo box when the user switches profiles. // Select a preset by a name.If !defined(name), then the default preset is selected. // If the current profile is modified, user is asked to save the changes. @@ -2692,8 +2725,11 @@ void Page::reload_config() void Page::update_visibility(ConfigOptionMode mode) { - for (auto group : m_optgroups) - group->update_visibility(mode); + bool ret_val = false; + for (auto group : m_optgroups) + ret_val = group->update_visibility(mode) || ret_val; + + m_show = ret_val; } Field* Page::get_field(const t_config_option_key& opt_key, int opt_index /*= -1*/) const diff --git a/src/slic3r/GUI/Tab.hpp b/src/slic3r/GUI/Tab.hpp index e0c6f318e4..1961142563 100644 --- a/src/slic3r/GUI/Tab.hpp +++ b/src/slic3r/GUI/Tab.hpp @@ -47,6 +47,7 @@ class Page : public wxScrolledWindow wxString m_title; size_t m_iconID; wxBoxSizer* m_vsizer; + bool m_show = true; public: Page(wxWindow* parent, const wxString title, const int iconID) : m_parent(parent), @@ -89,6 +90,7 @@ public: const wxColour get_item_colour() { return *m_item_color; } + bool get_show() const { return m_show; } protected: // Color of TreeCtrlItem. The wxColour will be updated only if the new wxColour pointer differs from the currently rendered one. @@ -215,6 +217,7 @@ public: void create_preset_tab(); void load_current_preset(); void rebuild_page_tree(bool tree_sel_change_event = false); + void update_page_tree_visibility(); void select_preset(std::string preset_name = ""); bool may_discard_current_dirty_preset(PresetCollection* presets = nullptr, const std::string& new_printer_name = ""); wxSizer* compatible_printers_widget(wxWindow* parent, wxCheckBox** checkbox, wxButton** btn); From 68f77f103165594ac0801bbce3ab8308d4b0484e Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Mon, 22 Oct 2018 08:54:04 +0200 Subject: [PATCH 143/186] New selection -> Changed selection logic == Use SHIFT for both add to selection and remove from selection --- src/slic3r/GUI/GLCanvas3D.cpp | 10 +++------- src/slic3r/GUI/GLCanvas3D.hpp | 2 ++ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 7ffd6e0106..4bb0f499f4 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -3989,10 +3989,10 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) #if ENABLE_EXTENDED_SELECTION if (evt.LeftDown() && (m_hover_volume_id != -1)) { - if (evt.ControlDown()) - m_selection.remove(m_hover_volume_id); - else + if (!evt.ShiftDown() || !m_selection.contains_volume(m_hover_volume_id)) m_selection.add(m_hover_volume_id, !evt.ShiftDown()); + else + m_selection.remove(m_hover_volume_id); m_gizmos.update_on_off_state(m_selection); update_gizmos_data(); @@ -6644,9 +6644,6 @@ void GLCanvas3D::_on_move(const std::vector& volume_idxs) #if !ENABLE_EXTENDED_SELECTION void GLCanvas3D::_on_select(int volume_idx, int object_idx) { -#if ENABLE_EXTENDED_SELECTION - post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT)); -#else int vol_id = -1; int obj_id = -1; @@ -6675,7 +6672,6 @@ void GLCanvas3D::_on_select(int volume_idx, int object_idx) post_event(ObjectSelectEvent(obj_id, vol_id)); wxGetApp().obj_list()->select_current_volume(obj_id, vol_id); -#endif // !ENABLE_EXTENDED_SELECTION } #endif // !ENABLE_EXTENDED_SELECTION diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 844e826fef..c26dae098c 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -485,6 +485,8 @@ public: bool is_from_single_instance() const { return get_instance_idx() != -1; } bool is_from_single_object() const { return get_object_idx() != -1; } + bool contains_volume(unsigned int volume_idx) const { return std::find(m_list.begin(), m_list.end(), volume_idx) != m_list.end(); } + // Returns the the object id if the selection is from a single object, otherwise is -1 int get_object_idx() const; // Returns the instance id if the selection is from a single object and from a single instance, otherwise is -1 From 126f0e50734ce69b9961e6c0549a98bf2f308dcb Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Mon, 22 Oct 2018 11:45:03 +0200 Subject: [PATCH 144/186] Added mirroring factors to .amf import/export --- src/libslic3r/Format/AMF.cpp | 87 ++++++++++++++++++++++++++++++++--- src/slic3r/GUI/GLCanvas3D.cpp | 14 ++---- src/slic3r/GUI/GUI_Utils.cpp | 1 + src/slic3r/GUI/MainFrame.cpp | 2 +- src/slic3r/GUI/Plater.cpp | 21 +++++++-- 5 files changed, 104 insertions(+), 21 deletions(-) diff --git a/src/libslic3r/Format/AMF.cpp b/src/libslic3r/Format/AMF.cpp index 00ed0d9373..be02616346 100644 --- a/src/libslic3r/Format/AMF.cpp +++ b/src/libslic3r/Format/AMF.cpp @@ -32,6 +32,9 @@ // 2 : Added z component of offset // Added x and y components of rotation // Added x, y and z components of scale +#if ENABLE_MIRROR +// Added x, y and z components of mirror +#endif // ENABLE_MIRROR const unsigned int VERSION_AMF = 2; const char* SLIC3RPE_AMF_VERSION = "slic3rpe_amf_version"; @@ -126,14 +129,27 @@ struct AMFParserContext NODE_TYPE_RY, // amf/constellation/instance/ry NODE_TYPE_RZ, // amf/constellation/instance/rz NODE_TYPE_SCALE, // amf/constellation/instance/scale - NODE_TYPE_SCALEX, // amf/constellation/instance/scalex - NODE_TYPE_SCALEY, // amf/constellation/instance/scaley - NODE_TYPE_SCALEZ, // amf/constellation/instance/scalez + NODE_TYPE_SCALEX, // amf/constellation/instance/scalex + NODE_TYPE_SCALEY, // amf/constellation/instance/scaley + NODE_TYPE_SCALEZ, // amf/constellation/instance/scalez +#if ENABLE_MIRROR + NODE_TYPE_MIRRORX, // amf/constellation/instance/mirrorx + NODE_TYPE_MIRRORY, // amf/constellation/instance/mirrory + NODE_TYPE_MIRRORZ, // amf/constellation/instance/mirrorz +#endif // ENABLE_MIRROR NODE_TYPE_METADATA, // anywhere under amf/*/metadata }; struct Instance { +#if ENABLE_MIRROR + Instance() + : deltax_set(false), deltay_set(false), deltaz_set(false) + , rx_set(false), ry_set(false), rz_set(false) + , scalex_set(false), scaley_set(false), scalez_set(false) + , mirrorx_set(false), mirrory_set(false), mirrorz_set(false) {} +#else Instance() : deltax_set(false), deltay_set(false), deltaz_set(false), rx_set(false), ry_set(false), rz_set(false), scalex_set(false), scaley_set(false), scalez_set(false) {} +#endif // ENABLE_MIRROR // Shift in the X axis. float deltax; bool deltax_set; @@ -159,6 +175,15 @@ struct AMFParserContext bool scaley_set; float scalez; bool scalez_set; +#if ENABLE_MIRROR + // Mirroring factors + float mirrorx; + bool mirrorx_set; + float mirrory; + bool mirrory_set; + float mirrorz; + bool mirrorz_set; +#endif // ENABLE_MIRROR }; struct Object { @@ -289,6 +314,14 @@ void AMFParserContext::startElement(const char *name, const char **atts) node_type_new = NODE_TYPE_SCALEZ; else if (strcmp(name, "scale") == 0) node_type_new = NODE_TYPE_SCALE; +#if ENABLE_MIRROR + else if (strcmp(name, "mirrorx") == 0) + node_type_new = NODE_TYPE_MIRRORX; + else if (strcmp(name, "mirrory") == 0) + node_type_new = NODE_TYPE_MIRRORY; + else if (strcmp(name, "mirrorz") == 0) + node_type_new = NODE_TYPE_MIRRORZ; +#endif // ENABLE_MIRROR } break; case 4: @@ -345,16 +378,23 @@ void AMFParserContext::characters(const XML_Char *s, int len) { switch (m_path.size()) { case 4: - if (m_path.back() == NODE_TYPE_DELTAX || - m_path.back() == NODE_TYPE_DELTAY || - m_path.back() == NODE_TYPE_DELTAZ || + if (m_path.back() == NODE_TYPE_DELTAX || + m_path.back() == NODE_TYPE_DELTAY || + m_path.back() == NODE_TYPE_DELTAZ || m_path.back() == NODE_TYPE_RX || m_path.back() == NODE_TYPE_RY || m_path.back() == NODE_TYPE_RZ || m_path.back() == NODE_TYPE_SCALEX || m_path.back() == NODE_TYPE_SCALEY || m_path.back() == NODE_TYPE_SCALEZ || +#if ENABLE_MIRROR + m_path.back() == NODE_TYPE_SCALE || + m_path.back() == NODE_TYPE_MIRRORX || + m_path.back() == NODE_TYPE_MIRRORY || + m_path.back() == NODE_TYPE_MIRRORZ) +#else m_path.back() == NODE_TYPE_SCALE) +#endif // ENABLE_MIRROR m_value[0].append(s, len); break; case 6: @@ -446,6 +486,26 @@ void AMFParserContext::endElement(const char * /* name */) m_instance->scalez_set = true; m_value[0].clear(); break; +#if ENABLE_MIRROR + case NODE_TYPE_MIRRORX: + assert(m_instance); + m_instance->mirrorx = float(atof(m_value[0].c_str())); + m_instance->mirrorx_set = true; + m_value[0].clear(); + break; + case NODE_TYPE_MIRRORY: + assert(m_instance); + m_instance->mirrory = float(atof(m_value[0].c_str())); + m_instance->mirrory_set = true; + m_value[0].clear(); + break; + case NODE_TYPE_MIRRORZ: + assert(m_instance); + m_instance->mirrorz = float(atof(m_value[0].c_str())); + m_instance->mirrorz_set = true; + m_value[0].clear(); + break; +#endif // ENABLE_MIRROR // Object vertices: case NODE_TYPE_VERTEX: @@ -585,6 +645,9 @@ void AMFParserContext::endDocument() mi->set_offset(Vec3d(instance.deltax_set ? (double)instance.deltax : 0.0, instance.deltay_set ? (double)instance.deltay : 0.0, instance.deltaz_set ? (double)instance.deltaz : 0.0)); mi->set_rotation(Vec3d(instance.rx_set ? (double)instance.rx : 0.0, instance.ry_set ? (double)instance.ry : 0.0, instance.rz_set ? (double)instance.rz : 0.0)); mi->set_scaling_factor(Vec3d(instance.scalex_set ? (double)instance.scalex : 1.0, instance.scaley_set ? (double)instance.scaley : 1.0, instance.scalez_set ? (double)instance.scalez : 1.0)); +#if ENABLE_MIRROR + mi->set_mirror(Vec3d(instance.mirrorx_set ? (double)instance.mirrorx : 1.0, instance.mirrory_set ? (double)instance.mirrory : 1.0, instance.mirrorz_set ? (double)instance.mirrorz : 1.0)); +#endif // ENABLE_MIRROR } } } @@ -891,6 +954,11 @@ bool store_amf(const char *path, Model *model, Print* print, bool export_print_c " %lf\n" " %lf\n" " %lf\n" +#if ENABLE_MIRROR + " %lf\n" + " %lf\n" + " %lf\n" +#endif // ENABLE_MIRROR " \n", object_id, instance->get_offset(X), @@ -901,7 +969,14 @@ bool store_amf(const char *path, Model *model, Print* print, bool export_print_c instance->get_rotation(Z), instance->get_scaling_factor(X), instance->get_scaling_factor(Y), +#if ENABLE_MIRROR + instance->get_scaling_factor(Z), + instance->get_mirror(X), + instance->get_mirror(Y), + instance->get_mirror(Z)); +#else instance->get_scaling_factor(Z)); +#endif // ENABLE_MIRROR //FIXME missing instance->scaling_factor instances.append(buf); diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 4bb0f499f4..7d47ff8f6c 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -3432,7 +3432,6 @@ int GLCanvas3D::get_in_object_volume_id(int scene_vol_idx) const #if ENABLE_EXTENDED_SELECTION void GLCanvas3D::mirror_selection(Axis axis) { - m_regenerate_volumes = false; m_selection.mirror(axis); _on_mirror(); wxGetApp().obj_manipul()->update_settings_value(m_selection); @@ -3457,7 +3456,12 @@ void GLCanvas3D::reload_scene(bool force) #if ENABLE_EXTENDED_SELECTION if (m_regenerate_volumes) + { reset_volumes(); + + // to update the toolbar + post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT)); + } #endif // ENABLE_EXTENDED_SELECTION set_bed_shape(dynamic_cast(m_config->option("bed_shape"))->values); @@ -3477,9 +3481,6 @@ void GLCanvas3D::reload_scene(bool force) { load_object(*m_model, obj_idx); } - - // to update the toolbar - post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT)); } update_gizmos_data(); @@ -3858,7 +3859,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) case Gizmos::Scale: { #if ENABLE_EXTENDED_SELECTION - m_regenerate_volumes = false; m_selection.scale(m_gizmos.get_scale()); _on_scale(); #else @@ -3875,7 +3875,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) case Gizmos::Rotate: { #if ENABLE_EXTENDED_SELECTION - m_regenerate_volumes = false; m_selection.rotate(m_gizmos.get_rotation()); _on_rotate(); #else @@ -3958,7 +3957,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) if (m_gizmos.get_current_type() == Gizmos::Flatten) { // Rotate the object so the normal points downward: #if ENABLE_EXTENDED_SELECTION - m_regenerate_volumes = false; m_selection.rotate(m_gizmos.get_flattening_rotation()); _on_flatten(); wxGetApp().obj_manipul()->update_settings_value(m_selection); @@ -4397,7 +4395,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) case Gizmos::Scale: { #if ENABLE_EXTENDED_SELECTION - m_regenerate_volumes = false; _on_scale(); #endif // ENABLE_EXTENDED_SELECTION break; @@ -4405,7 +4402,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) case Gizmos::Rotate: { #if ENABLE_EXTENDED_SELECTION - m_regenerate_volumes = false; _on_rotate(); #else post_event(Vec3dEvent(EVT_GIZMO_ROTATE, m_gizmos.get_rotation())); diff --git a/src/slic3r/GUI/GUI_Utils.cpp b/src/slic3r/GUI/GUI_Utils.cpp index fb494ed232..5a7ece5865 100644 --- a/src/slic3r/GUI/GUI_Utils.cpp +++ b/src/slic3r/GUI/GUI_Utils.cpp @@ -28,6 +28,7 @@ CheckboxFileDialog::ExtraPanel::ExtraPanel(wxWindow *parent) auto* sizer = new wxBoxSizer(wxHORIZONTAL); cbox = new wxCheckBox(this, wxID_ANY, checkbox_label); + cbox->SetValue(true); sizer->AddSpacer(5); sizer->Add(this->cbox, 0, wxEXPAND | wxALL, 5); SetSizer(sizer); diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 6a202ad4ce..f1e6595f78 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -300,7 +300,7 @@ void MainFrame::init_menubar() append_menu_item(m_plater_menu, wxID_ANY, _(L("Export plate as STL...")), _(L("Export current plate as STL")), [this](wxCommandEvent&){ /*m_plater->export_stl(); */}, "brick_go.png"); append_menu_item(m_plater_menu, wxID_ANY, _(L("Export plate as AMF...")), _(L("Export current plate as AMF")), - [this](wxCommandEvent&){ /*m_plater->export_amf();*/ }, "brick_go.png"); + [this](wxCommandEvent&){ m_plater->export_amf(); }, "brick_go.png"); append_menu_item(m_plater_menu, wxID_ANY, _(L("Export plate as 3MF...")), _(L("Export current plate as 3MF")), [this](wxCommandEvent&){ m_plater->export_3mf(); }, "brick_go.png"); } diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index b5cb216256..bef4d5a868 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -850,7 +850,9 @@ private: bool layers_height_allowed() const; bool can_delete_all() const; bool can_arrange() const; +#if ENABLE_MIRROR bool can_mirror() const; +#endif // ENABLE_MIRROR #endif // ENABLE_EXTENDED_SELECTION }; @@ -1256,14 +1258,17 @@ std::unique_ptr Plater::priv::get_export_file(GUI::FileType wxString wildcard; switch (file_type) { case FT_STL: - case FT_AMF: - case FT_3MF: wildcard = file_wildcards[FT_STL]; - break; - + break; + case FT_AMF: + wildcard = file_wildcards[FT_AMF]; + break; + case FT_3MF: + wildcard = file_wildcards[FT_3MF]; + break; default: wildcard = file_wildcards[FT_MODEL]; - break; + break; } fs::path output_file(print.output_filepath(std::string())); @@ -1899,6 +1904,7 @@ bool Plater::priv::init_object_menu() object_menu.AppendSeparator(); +#if ENABLE_MIRROR wxMenu* mirror_menu = new wxMenu(); if (mirror_menu == nullptr) return false; @@ -1911,6 +1917,7 @@ bool Plater::priv::init_object_menu() [this](wxCommandEvent&){ mirror(Z); }, "bullet_blue.png", &object_menu); wxMenuItem* item_mirror = append_submenu(&object_menu, mirror_menu, wxID_ANY, _(L("Mirror")), _(L("Mirror the selected object"))); +#endif // ENABLE_MIRROR wxMenuItem* item_split = append_menu_item(&object_menu, wxID_ANY, _(L("Split")), _(L("Split the selected object into individual parts")), [this](wxCommandEvent&){ split_object(); }, "shape_ungroup.png"); @@ -1919,7 +1926,9 @@ bool Plater::priv::init_object_menu() // ui updates needs to be binded to the parent panel if (q != nullptr) { +#if ENABLE_MIRROR q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_mirror()); }, item_mirror->GetId()); +#endif // ENABLE_MIRROR q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_delete_object()); }, item_delete->GetId()); q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_increase_instances()); }, item_increase->GetId()); q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_decrease_instances()); }, item_decrease->GetId()); @@ -1976,10 +1985,12 @@ bool Plater::priv::can_arrange() const return !model.objects.empty(); } +#if ENABLE_MIRROR bool Plater::priv::can_mirror() const { return get_selection().is_from_single_instance(); } +#endif // ENABLE_MIRROR #endif // ENABLE_EXTENDED_SELECTION // Plater / Public From 974e2056fbc85cf19265523adfd2992277081003 Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Mon, 22 Oct 2018 11:52:13 +0200 Subject: [PATCH 145/186] Plater: Fix file patterns --- src/slic3r/GUI/Plater.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index bef4d5a868..8fd13cfe23 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -700,7 +700,7 @@ private: static const std::regex pattern_drop; }; -const std::regex PlaterDropTarget::pattern_drop("[.](stl|obj|amf|3mf|prusa)$", std::regex::icase); +const std::regex PlaterDropTarget::pattern_drop(".*[.](stl|obj|amf|3mf|prusa)", std::regex::icase); bool PlaterDropTarget::OnDropFiles(wxCoord x, wxCoord y, const wxArrayString &filenames) { @@ -856,9 +856,9 @@ private: #endif // ENABLE_EXTENDED_SELECTION }; -const std::regex Plater::priv::pattern_bundle("[.](amf|amf[.]xml|zip[.]amf|3mf|prusa)$", std::regex::icase); -const std::regex Plater::priv::pattern_3mf("[.]3mf$", std::regex::icase); -const std::regex Plater::priv::pattern_zip_amf("[.]zip[.]amf$", std::regex::icase); +const std::regex Plater::priv::pattern_bundle(".*[.](amf|amf[.]xml|zip[.]amf|3mf|prusa)", std::regex::icase); +const std::regex Plater::priv::pattern_3mf(".*3mf", std::regex::icase); +const std::regex Plater::priv::pattern_zip_amf(".*[.]zip[.]amf", std::regex::icase); Plater::priv::priv(Plater *q, MainFrame *main_frame) : q(q), From 37e165d82d89767dfd18b63592a2bab8c5dea11f Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Mon, 22 Oct 2018 11:50:05 +0200 Subject: [PATCH 146/186] Build: Fix resources symlink --- src/CMakeLists.txt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 330134c3bc..332649cf9d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -119,28 +119,28 @@ if (MSVC) foreach (CONF ${CMAKE_CONFIGURATION_TYPES}) file(TO_NATIVE_PATH "${CMAKE_CURRENT_BINARY_DIR}/${CONF}" WIN_CONF_OUTPUT_DIR) file(TO_NATIVE_PATH "${CMAKE_CURRENT_BINARY_DIR}/${CONF}/resources" WIN_RESOURCES_SYMLINK) - add_custom_target("resources_symlink_${CONF}" ALL - DEPENDS slic3r + add_custom_command(TARGET slic3r POST_BUILD COMMAND if exist "${WIN_CONF_OUTPUT_DIR}" "(" if not exist "${WIN_RESOURCES_SYMLINK}" "(" mklink /J "${WIN_RESOURCES_SYMLINK}" "${SLIC3R_RESOURCES_DIR_WIN}" ")" ")" + COMMENT "Symlinking the resources directory into the build tree" VERBATIM ) endforeach () else () file(TO_NATIVE_PATH "${CMAKE_CURRENT_BINARY_DIR}/resources" WIN_RESOURCES_SYMLINK) - add_custom_target(resources_symlink ALL - DEPENDS slic3r + add_custom_command(TARGET slic3r POST_BUILD COMMAND if not exist "${WIN_RESOURCES_SYMLINK}" "(" mklink /J "${WIN_RESOURCES_SYMLINK}" "${SLIC3R_RESOURCES_DIR_WIN}" ")" + COMMENT "Symlinking the resources directory into the build tree" VERBATIM ) endif () else () - add_custom_target(resources_symlink ALL - DEPENDS slic3r + add_custom_command(TARGET slic3r POST_BUILD COMMAND ln -sf "${SLIC3R_RESOURCES_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/../resources" + COMMENT "Symlinking the resources directory into the build tree" VERBATIM ) endif() From f6e6d9dc4ada0d8481884d8ad73c9bee2291f4c7 Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Fri, 19 Oct 2018 16:52:41 +0200 Subject: [PATCH 147/186] Fix Plater::priv::get_export_file() --- src/slic3r/GUI/MainFrame.cpp | 4 ++-- src/slic3r/GUI/Plater.cpp | 12 +++++------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index f1e6595f78..5df19df80a 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -296,9 +296,9 @@ void MainFrame::init_menubar() if (m_plater) { m_plater_menu = new wxMenu(); append_menu_item(m_plater_menu, wxID_ANY, _(L("Export G-code...")), _(L("Export current plate as G-code")), - [this](wxCommandEvent&){ /*m_plater->export_gcode(); */}, "cog_go.png"); + [this](wxCommandEvent&){ m_plater->export_gcode(); }, "cog_go.png"); append_menu_item(m_plater_menu, wxID_ANY, _(L("Export plate as STL...")), _(L("Export current plate as STL")), - [this](wxCommandEvent&){ /*m_plater->export_stl(); */}, "brick_go.png"); + [this](wxCommandEvent&){ m_plater->export_stl(); }, "brick_go.png"); append_menu_item(m_plater_menu, wxID_ANY, _(L("Export plate as AMF...")), _(L("Export current plate as AMF")), [this](wxCommandEvent&){ m_plater->export_amf(); }, "brick_go.png"); append_menu_item(m_plater_menu, wxID_ANY, _(L("Export plate as 3MF...")), _(L("Export current plate as 3MF")), diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 8fd13cfe23..8bdc43a376 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1258,17 +1258,15 @@ std::unique_ptr Plater::priv::get_export_file(GUI::FileType wxString wildcard; switch (file_type) { case FT_STL: - wildcard = file_wildcards[FT_STL]; - break; case FT_AMF: - wildcard = file_wildcards[FT_AMF]; - break; case FT_3MF: - wildcard = file_wildcards[FT_3MF]; - break; + case FT_GCODE: + wildcard = file_wildcards[file_type]; + break; + default: wildcard = file_wildcards[FT_MODEL]; - break; + break; } fs::path output_file(print.output_filepath(std::string())); From 84de664fb54fe87939c7072cc2f0932d82afb4a7 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Mon, 22 Oct 2018 12:07:40 +0200 Subject: [PATCH 148/186] Fixed TreeCtrl updating after mode change + Added another images for mode visualization --- resources/icons/mode_expert_.png | Bin 0 -> 1379 bytes resources/icons/mode_middle_.png | Bin 0 -> 1466 bytes resources/icons/mode_simple_.png | Bin 0 -> 1164 bytes src/slic3r/GUI/OptionsGroup.cpp | 2 ++ src/slic3r/GUI/Tab.cpp | 13 +++++++++---- 5 files changed, 11 insertions(+), 4 deletions(-) create mode 100644 resources/icons/mode_expert_.png create mode 100644 resources/icons/mode_middle_.png create mode 100644 resources/icons/mode_simple_.png diff --git a/resources/icons/mode_expert_.png b/resources/icons/mode_expert_.png new file mode 100644 index 0000000000000000000000000000000000000000..4d78bcccf511511455f4de48fca473bb2d0aa677 GIT binary patch literal 1379 zcmV-p1)TbcP) zaB^>EX>4U6ba`-PAZ2)IW&i+q+O3vrlIti8h5u_6vjhYPiRJLDnjOsY=is;#C!O&f zciL3^P%udPbTBmj`Fqk|IJ~G)#3|*J9FCY{_60ZQZpZD)E^gfxc$m2MlXwkDI-p?E?jWvwt~4d4I3OgX{Y*_sx07 zd#Bgus7OW^j2Arl5jZ%U)0!o~gJ7X78_qs>@Amr`63$`udzU-9rTKgE?sqS_b7i-O z=TwmU8YsQwXt%Sx&)t@xCu)zGpZ=Kj4*FZ}=Il1-xJ6fDLZ%Y!L4Ad?-JxSeD#P|# zLR0(%_qw%=W(cu?SO?9D)`&BEWOH)l&V?tB?b^7(#ps7uT)l5TY&Hw(vu_)exEfEd zA%{+2STKyEQu0jXQu1AShd!4FMKcZ$nh!M{R|Tb3i|Fk#0rrSo=NzQiQn$ z&Ts$$mpBL~cIv${Baa3?1)lp5eFXs)@ttXc4eB0n%&)oej`G&mi@%w%v;c%aA__D) z6u^p6P(KBoRrXVv?n#kYbXQlBTsr6%86yG^wg-)?&e;i6v7r%T}__0ZW+V zl$EmOoJ+x^1w$9SUC^VH>T9U6N=;R()m%$M`Lx)irKZhVZl(JkI^^F|SL)VtFM|h4 zX~ZET4IMV}C=<0d!;DjAnmTRfS?<($m+ccZej#^GjdyB`Sls&QgBr}LUqkR(PGm6y zF&`PkbrC>8`^C%|$LJTi#mr?7QHTdMmIbHtA_jtSu$Reqb`Nr=+(_ajZvMZ>(L(nd zwbj`a6EwIUYTce^(%HhyJtYXSH{oujE6-7# zc29+ojS*%~4o*N)C29(7mOk+@E#3;e%q9^ZDOYS1tfWpP##YK`fE|T_59`s$6Vk^} zu_Ot@&)Rfku~t*SqKisE2|Pkr5mY~JQGUf}#?&VYSUL(F9t-{FIKVa!WeV2;w z1|mWQve~?mqE}QYEK)H&fqIAOg%T~tH&D-*{sie8Bl;nvZ;a>)q(>TFoamG7-jNag(jFqvC)>RvC;DW&cceuB3lrw)**W?b z+PYSP@1brk00006VoOIv0RI600RN!9r;`8x010qNS#tmY5_A9n5_AFHW*>L}000Mc zNliru;tCcBE-rCcRgeGx05C~JK~yNuW8BWh_Fw1MF9t3d6^0K_?l7EXfB+^228K^O lJPb?>1i+|*Q3cdh002W22;H2eLIwZ;002ovPDHLkV1id3f^Pr- literal 0 HcmV?d00001 diff --git a/resources/icons/mode_middle_.png b/resources/icons/mode_middle_.png new file mode 100644 index 0000000000000000000000000000000000000000..d98d8f7091d0fcebd33a354a11feb8cd0a08f5bf GIT binary patch literal 1466 zcmV;r1x5OaP) zaB^>EX>4U6ba`-PAZ2)IW&i+q+O1Yww&N%a{MRaG2}VK)mc#R$-oY$?3hX>@uG@Wk zLSl>p0;-C#ssHa2<3@L;SAD?{UjGMUapS^aQU)Sf@Y`?_G`Qr~pNKnh( z4E^Yz5!c56JNmow8Yinqo_Hj>&3q)3IWyzt=ogPf!h8I-5K70m?4Oo?{8C$s-`vsZ zz3mNPG(|pP;x0}$T*I72umXvaXAD;s=IyxmVz`Q=&)Crp^H=chcW>Bj`H0Ia6tvwE zg*S|jxYN(rErecJd(8auhm1SXU$7ga#WDK6yX*sy3UqAhwv}~fg_d* z)&ya`uf?r-)0(fkh?$#1Pj*P=CY$etJ_UbL?uo{j(sgc&J5G=V*2PoPSjJ>-UeODL zxN%^r3*S}fNjKXQu>uBl!5p!{yp=sgQTNc6ES?4Zbn~=}esk821b_&0D;DDf3~a%P zy5KfrHs^q21V0%oXYpLXfK%n>Xn-4$0CFPFxiQAv>dVS|7}f$JR00l31Vb5Qd9Toq z`3MbV74@X5K~1A3%|U_>8bYuzJt~`+H??49(URpT(MOFTT8uHpoHz+AOjAfkDW;Ti z#-tgkGe&3h$hmNl;)|A0ti+N^u8>dlRcokLV@)+TZqji4TWCftw$yTW9a8GPYY*Le z?5XDgtqmD|=m^6`9BJe`YwkFDcrOZot%L&_705O zWB`KZ$=Md2_dJ=KoNbA5D3rmP(@9QqlQA&pyJH>h&fSB#Q{G7ZAMwWDF-McS|ART2 z)E&%y|2|92MxiqfcDo$R*o=rzD-bN`nu72!II@%VS z7Ce(Ica}{V~e6CF`7Y8>3M!AS8cF)pzi=nD7d8XGaqct#|Z3gbmQbTUTfl$U-0iGN) z7dT{`H!;u0|50P4?y2maYNE9_8z-v)iWv|?u?2O9vK#08L;|+FVfPX{#JQ(iXluNa z;ETi429JoqSwU`YZh*Ch(jPhe|!uz=l0Yb{k1S9s9avCh@sS%o^q#;djGB5ZxlQPPv0p1j|EQ;#V>`w9f9kD zr*9PhS?+IQe^P&;k9z-J?r&nhtH04lz5h<`AH+@{)czx})2rI=>h{m_zan<}p!RXI zmfy+!Zp#SJ;{ZJA{j%I24o?q@f71I8rZtv&rPS@@I+}-KAy`RgSuG{;$-08Z#p9`LT@;>v)-RZC2XAZg3b$dUT zJ6*T;bGg%Xdp{RD{q$Yt-Q8*Y&AZH#yVG@hKX-Tfq<0y3!%vX?fA%);>rHq<8UO$Q z24YJ`L;(K){{a7>y{D4^000SaNLh0L01|Wn01|Wo-ew zaB^>EX>4U6ba`-PAZ2)IW&i+q+O3vrlEfwqg#YUlIRX+0!EwMqRc?^ur?Hv0vx#Rj z)Y^=UCAq&gv(*3kbI>37h~q#(EyWz8!zbjBrC^fW@j1@y!hU>?&F?R9;;=3tt@Akh z<7@0|eL-9wH`rRw^)*hmtvqQZx>a5Y{j4mQtaWK6@^Zv)jZj|qmGIR1`pa!^-tk)W z{yiAPXo`GZNV;e5aE!BxM+ZLnGGjQ37jbJIyzTLLt{ojRe~NdXy=mvliu+e7$lVgf zH;q=D^<2AMp%-e8$}bnTbT9Ft-54#6(T}GqAwsE0>!EIsvd^%vLQ22i7BLKein;A0 zVNzJ?)!P;4J`)gVmOOz;`dncCRw%}N|=L(n9sfu7>VCN z%_A)LUU;vY_j(&ARBnuw!brxG=KG+t;5Xx*XpCuHW|t0~U<>pm)6-~UlAA}Y0uUZc zQ{DC52R-@5J%RNgsJqMw4_I71QdH%KxBSl8W1YG{hv^+#TL~Z$YAc#y4+1W-SB~sV z#F(LD0-u7;#RsV%z^c-i2H1EX0Vm0-B zUIVFWRMVtcOY|{BjWJrBdsH!R!PKIeCCgTlPa$cF$x=!=l`Pp~3)394QBFDMQc$!Y zb-~>QD@v(SeGOG>tX5OawQR7@7B=1DW?S0wR+=>5@cOsdj9O~BmChYj>Y;0o-FoV| zmjSO0Kf=%vhmADyD0gbSUfUOH{6_9)YP_gTVqsrr4{8XT-BR$}PINK@F$oOfHVMGc zGMTx=A;=^*nYk=@DO5m>b;4;piGg6~EIRnk?m_NHZlvK7H~A-WG|~MZRWtds8cwV;;SRF>2M3%U0w3fzW{81y@op*u0!Z zpoyd634F=KwfBr`$w_W);Jq%5@A=GTKAZWpS4$mRT9E`5us+S1TW546KlbCLC0DbG z>uHLZ@mtH9;DOZv_Uzde;ToE-m(s}m)?4cyJLOS(uHR=*=gM>|4%e<6kM07r`4?&K z%FvSLJ7J!5p-*A<-u|mJcV*~9nk&LQL7`vB@?seJl`v1b&~?Y08-}hs=G-v!wKQ*r zpx?|1_L)RU1ZW#Jnm^Z`Fcd~pMhORs2+%Ry9}$3|)83 zxnbzKW6ljj*Bx_i7`pD5bHmVe$DA96t~=)3Fm&B9=Z2x{jyX3BU3bijVLblP$@DkZ z+afZyIfuyr000JJOGiWi{{a60|De66lK=n!32;bRa{vGmbN~PnbOGLGA9w%&00(qQ zO+^Rd3Kj@25=Sf;RsaA1DoI2^R4C75oO43_zpx}T0~;$d!>`|e8Qwns%YY1+7zlt- e1)~b6s{jD4<_My71_K=c0000GetEffectiveRowsCount() != m_options_mode.size() && m_options_mode.size() == 1) return m_options_mode[0] <= mode; diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index bb7aa3e9b6..698c46d234 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -483,7 +483,7 @@ void Tab::update_changed_tree_ui() auto title = m_treectrl->GetItemText(cur_item); for (auto page : m_pages) { - if (page->title() != title) + if (page->title() != title) continue; bool sys_page = true; bool modified_page = false; @@ -644,6 +644,11 @@ void Tab::update_visibility(ConfigOptionMode mode) Refresh(); Thaw(); + + // to update tree items color + wxTheApp->CallAfter([this]() { + update_changed_tree_ui(); + }); } Field* Tab::get_field(const t_config_option_key& opt_key, int opt_index/* = -1*/) const @@ -1782,7 +1787,7 @@ void TabPrinter::build_sla() auto page = add_options_page(_(L("General")), "printer_empty.png"); auto optgroup = page->new_optgroup(_(L("Size and coordinates"))); - Line line{ _(L("Bed shape")), "" }; + Line line = optgroup->create_single_option_line("bed_shape");//{ _(L("Bed shape")), "" }; line.widget = [this](wxWindow* parent){ auto btn = new wxButton(parent, wxID_ANY, _(L(" Set ")) + dots, wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT); // btn->SetFont(Slic3r::GUI::small_font); @@ -2762,8 +2767,8 @@ ConfigOptionsGroupShp Page::new_optgroup(const wxString& title, int noncommon_la bmp_name = "error.png"; else { auto mode = line.get_options()[0].opt.mode; //we assume that we have one option per line - bmp_name = mode == comExpert ? "mode_expert.png" : - mode == comMiddle ? "mode_middle.png" : "mode_simple.png"; + bmp_name = mode == comExpert ? "mode_expert_.png" : + mode == comMiddle ? "mode_middle_.png" : "mode_simple_.png"; } auto bmp = new wxStaticBitmap(parent, wxID_ANY, wxBitmap(from_u8(var(bmp_name)), wxBITMAP_TYPE_PNG)); return bmp; From 2a2d1d85f8e1dcc46f2d97d3e2970e49824997c5 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Mon, 22 Oct 2018 13:27:53 +0200 Subject: [PATCH 149/186] Added mirror factors to .3mf import and enabled import factors --- src/libslic3r/Format/3mf.cpp | 22 ++++++++++++++++++---- src/libslic3r/Model.cpp | 4 ++++ src/libslic3r/Technologies.hpp | 2 +- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/libslic3r/Format/3mf.cpp b/src/libslic3r/Format/3mf.cpp index bf94db6b14..085f55b9bd 100644 --- a/src/libslic3r/Format/3mf.cpp +++ b/src/libslic3r/Format/3mf.cpp @@ -1249,14 +1249,25 @@ namespace Slic3r { void _3MF_Importer::_apply_transform(ModelInstance& instance, const Transform3d& transform) { - // slic3r ModelInstance cannot be transformed using a matrix - // we extract from the given matrix only the values currently used - // translation Vec3d offset = transform.matrix().block(0, 3, 3, 1); - // scale Eigen::Matrix m3x3 = transform.matrix().block(0, 0, 3, 3); +#if ENABLE_MIRROR + // mirror + // it is impossible to reconstruct the original mirroring factors from a matrix, + // we can only detect if the matrix contains a left handed reference system + // in which case we reorient it back to right handed by mirroring the x axis + Vec3d mirror = Vec3d::Ones(); + if (m3x3.col(0).dot(m3x3.col(1).cross(m3x3.col(2))) < 0.0) + { + mirror(0) = -1.0; + // remove mirror + m3x3.col(0) *= -1.0; + } + + // scale +#endif // ENABLE_MIRROR Vec3d scale(m3x3.col(0).norm(), m3x3.col(1).norm(), m3x3.col(2).norm()); // invalid scale value, return @@ -1273,6 +1284,9 @@ namespace Slic3r { instance.set_offset(offset); instance.set_scaling_factor(scale); instance.set_rotation(rotation); +#if ENABLE_MIRROR + instance.set_mirror(mirror); +#endif // ENABLE_MIRROR } bool _3MF_Importer::_handle_start_config(const char** attributes, unsigned int num_attributes) diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index d001acedb1..331d118337 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -711,9 +711,13 @@ void ModelObject::center_around_origin() if (!this->instances.empty()) { for (ModelInstance *i : this->instances) { +#if ENABLE_MIRROR + i->set_offset(i->get_offset() - shift); +#else // apply rotation and scaling to vector as well before translating instance, // in order to leave final position unaltered i->set_offset(i->get_offset() + i->transform_vector(-shift, true)); +#endif // ENABLE_MIRROR } this->invalidate_bounding_box(); } diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index 3f8fd80f0b..d80d6df0d7 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -11,7 +11,7 @@ // New selections #define ENABLE_EXTENDED_SELECTION (1 && ENABLE_1_42_0) // Add mirror components along the three axes in ModelInstance and GLVolume -#define ENABLE_MIRROR (0 && ENABLE_1_42_0) +#define ENABLE_MIRROR (1 && ENABLE_1_42_0) #endif // _technologies_h_ From 3ecb65d62c5f1509af8889de74fbe84452c26674 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Mon, 22 Oct 2018 15:18:05 +0200 Subject: [PATCH 150/186] Fixed mode updating under GTK --- src/slic3r/GUI/GUI_ObjectList.hpp | 1 + src/slic3r/GUI/OptionsGroup.cpp | 8 +++++++- src/slic3r/GUI/Tab.cpp | 2 +- src/slic3r/GUI/wxExtensions.hpp | 1 + 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index c56e696700..56d01b7f50 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -4,6 +4,7 @@ #include #include #include +#include class wxBoxSizer; class PrusaObjectDataViewModel; diff --git a/src/slic3r/GUI/OptionsGroup.cpp b/src/slic3r/GUI/OptionsGroup.cpp index b2f9cd2726..371747bc13 100644 --- a/src/slic3r/GUI/OptionsGroup.cpp +++ b/src/slic3r/GUI/OptionsGroup.cpp @@ -395,19 +395,25 @@ bool ConfigOptionsGroup::update_visibility(ConfigOptionMode mode) { return m_options_mode[0] <= mode; sizer->ShowItems(true); +#ifdef __WXGTK__ + m_panel->Show(true); + m_grid_sizer->Show(true); +#endif /* __WXGTK__ */ int coef = 0; + int hidden_row_cnt = 0; const int cols = m_grid_sizer->GetCols(); for (auto opt_mode : m_options_mode) { const bool show = opt_mode <= mode; if (!show) { + hidden_row_cnt++; for (int i = 0; i < cols; ++i) m_grid_sizer->Show(coef + i, show); } coef+= cols; } - if (!sizer->IsShown(m_grid_sizer)) { + if (hidden_row_cnt == m_options_mode.size()) { sizer->ShowItems(false); return false; } diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 698c46d234..d4249ea23b 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -476,7 +476,7 @@ void Tab::get_sys_and_mod_flags(const std::string& opt_key, bool& sys_page, bool void Tab::update_changed_tree_ui() { auto cur_item = m_treectrl->GetFirstVisibleItem(); - if (!m_treectrl->IsVisible(cur_item)) + if (!cur_item || !m_treectrl->IsVisible(cur_item)) return; auto selection = m_treectrl->GetItemText(m_treectrl->GetSelection()); while (cur_item){ diff --git a/src/slic3r/GUI/wxExtensions.hpp b/src/slic3r/GUI/wxExtensions.hpp index 4ff73027c9..80a564fd0f 100644 --- a/src/slic3r/GUI/wxExtensions.hpp +++ b/src/slic3r/GUI/wxExtensions.hpp @@ -12,6 +12,7 @@ #include #include +#include wxMenuItem* append_menu_item(wxMenu* menu, int id, const wxString& string, const wxString& description, std::function cb, const std::string& icon = "", wxEvtHandler* event_handler = nullptr); From 2f11df47ce28de70a4ae2c8919339356906ec608 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Mon, 22 Oct 2018 15:18:56 +0200 Subject: [PATCH 151/186] Layers editing --- src/slic3r/GUI/Plater.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 8bdc43a376..ecf36595ea 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1365,7 +1365,7 @@ void Plater::priv::selection_changed() _3DScene::enable_toolbar_item(canvas3D, "split", have_sel); _3DScene::enable_toolbar_item(canvas3D, "cut", have_sel); _3DScene::enable_toolbar_item(canvas3D, "settings", have_sel); - _3DScene::enable_toolbar_item(canvas3D, "layersediting", layers_height_allowed); + _3DScene::enable_toolbar_item(canvas3D, "layersediting", have_sel && config->opt_bool("variable_layer_height") && _3DScene::is_layers_editing_allowed(canvas3D)); #endif // ENABLE_EXTENDED_SELECTION #if ENABLE_EXTENDED_SELECTION @@ -1477,6 +1477,9 @@ void Plater::priv::remove(size_t obj_idx) // Prevent toolpaths preview from rendering while we modify the Print object preview->set_enabled(false); + if (_3DScene::is_layers_editing_enabled(canvas3D)) + _3DScene::enable_layers_editing(canvas3D, false); + #if !ENABLE_EXTENDED_SELECTION objects.erase(objects.begin() + obj_idx); #endif // !ENABLE_EXTENDED_SELECTION @@ -1500,6 +1503,9 @@ void Plater::priv::reset() // Prevent toolpaths preview from rendering while we modify the Print object preview->set_enabled(false); + if (_3DScene::is_layers_editing_enabled(canvas3D)) + _3DScene::enable_layers_editing(canvas3D, false); + #if !ENABLE_EXTENDED_SELECTION objects.clear(); #endif // !ENABLE_EXTENDED_SELECTION @@ -1777,7 +1783,10 @@ void Plater::priv::on_action_settings(SimpleEvent&) void Plater::priv::on_action_layersediting(SimpleEvent&) { - // TODO + bool enable = !_3DScene::is_layers_editing_enabled(canvas3D); + _3DScene::enable_layers_editing(canvas3D, enable); + if (enable && !_3DScene::is_layers_editing_enabled(canvas3D)) + _3DScene::enable_toolbar_item(canvas3D, "layersediting", false); } #if !ENABLE_EXTENDED_SELECTION @@ -1970,7 +1979,8 @@ bool Plater::priv::can_cut_object() const bool Plater::priv::layers_height_allowed() const { - return config->opt_bool("variable_layer_height") && _3DScene::is_layers_editing_allowed(canvas3D); + int obj_idx = get_selected_object_idx(); + return (0 <= obj_idx) && (obj_idx < (int)model.objects.size()) && config->opt_bool("variable_layer_height") && _3DScene::is_layers_editing_allowed(canvas3D); } bool Plater::priv::can_delete_all() const From 0799ca2099524c0936070d6327921c8d198a461b Mon Sep 17 00:00:00 2001 From: bubnikv Date: Mon, 22 Oct 2018 14:53:48 +0200 Subject: [PATCH 152/186] Fixes of the CMake build system to compile Release and Debug builds on MS Windows. --- CMakeLists.txt | 6 +- cmake/modules/FindCURL.cmake | 98 ++++- ...FindPackageHandleStandardArgs_SLIC3R.cmake | 392 ++++++++++++++++++ cmake/modules/FindPackageMessage_SLIC3R.cmake | 54 +++ cmake/modules/FindTBB.cmake | 5 +- .../SelectLibraryConfigurations_SLIC3R.cmake | 77 ++++ src/CMakeLists.txt | 2 +- src/libslic3r/CMakeLists.txt | 2 +- 8 files changed, 608 insertions(+), 28 deletions(-) create mode 100644 cmake/modules/FindPackageHandleStandardArgs_SLIC3R.cmake create mode 100644 cmake/modules/FindPackageMessage_SLIC3R.cmake create mode 100644 cmake/modules/SelectLibraryConfigurations_SLIC3R.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 62c545fe14..fbad4ca239 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,6 +25,7 @@ option(SLIC3R_GUI "Compile Slic3r with GUI components (OpenGL, wxWidgets)" option(SLIC3R_PROFILE "Compile Slic3r with an invasive Shiny profiler" 0) option(SLIC3R_MSVC_COMPILE_PARALLEL "Compile on Visual Studio in parallel" 1) option(SLIC3R_MSVC_PDB "Generate PDB files on MSVC in Release mode" 1) +option(SLIC3R_PERL_XS "Compile XS Perl module and enable Perl unit and integration tests" 0) if (MSVC AND SLIC3R_MSVC_COMPILE_PARALLEL) add_compile_options(/MP) @@ -154,6 +155,7 @@ endif() # The Intel TBB library will use the std::exception_ptr feature of C++11. add_definitions(-DTBB_USE_CAPTURED_EXCEPTION=0) +#set(CURL_DEBUG 1) find_package(CURL REQUIRED) include_directories(${CURL_INCLUDE_DIRS}) @@ -233,7 +235,9 @@ set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT s # Perl bindings, currently only used for the unit / integration tests of libslic3r. # Also runs the unit / integration tests. #FIXME Port the tests into C++ to finally get rid of the Perl! -add_subdirectory(xs) +if (SLIC3R_PERL_XS) + add_subdirectory(xs) +endif () file(GLOB MyVar var/*.png) install(FILES ${MyVar} DESTINATION share/slic3r-prusa3d) diff --git a/cmake/modules/FindCURL.cmake b/cmake/modules/FindCURL.cmake index b8724858c8..e0deafa45c 100644 --- a/cmake/modules/FindCURL.cmake +++ b/cmake/modules/FindCURL.cmake @@ -5,34 +5,62 @@ # FindCURL # -------- # -# Find curl -# # Find the native CURL headers and libraries. # -# :: +# IMPORTED Targets +# ^^^^^^^^^^^^^^^^ # -# CURL_INCLUDE_DIRS - where to find curl/curl.h, etc. -# CURL_LIBRARIES - List of libraries when using curl. -# CURL_FOUND - True if curl found. -# CURL_VERSION_STRING - the version of curl found (since CMake 2.8.8) +# This module defines :prop_tgt:`IMPORTED` target ``CURL::libcurl``, if +# curl has been found. +# +# Result Variables +# ^^^^^^^^^^^^^^^^ +# +# This module defines the following variables: +# +# ``CURL_FOUND`` +# True if curl found. +# +# ``CURL_INCLUDE_DIRS`` +# where to find curl/curl.h, etc. +# +# ``CURL_LIBRARIES`` +# List of libraries when using curl. +# +# ``CURL_VERSION_STRING`` +# The version of curl found. # Look for the header file. find_path(CURL_INCLUDE_DIR NAMES curl/curl.h) mark_as_advanced(CURL_INCLUDE_DIR) -# Look for the library (sorted from most current/relevant entry to least). -find_library(CURL_LIBRARY NAMES - curl - # Windows MSVC Makefile: - libcurl_a - # Windows MSVC prebuilts: - curllib - libcurl_imp - curllib_static - # Windows older "Win32 - MSVC" prebuilts (libcurl.lib, e.g. libcurl-7.15.5-win32-msvc.zip): - libcurl -) -mark_as_advanced(CURL_LIBRARY) +if(NOT CURL_LIBRARY) + # Look for the library (sorted from most current/relevant entry to least). + find_library(CURL_LIBRARY_RELEASE NAMES + curl + # Windows MSVC prebuilts: + curllib + libcurl_imp + curllib_static + # Windows older "Win32 - MSVC" prebuilts (libcurl.lib, e.g. libcurl-7.15.5-win32-msvc.zip): + libcurl + # Static library on Windows + libcurl_a + ) + mark_as_advanced(CURL_LIBRARY_RELEASE) + + find_library(CURL_LIBRARY_DEBUG NAMES + # Windows MSVC CMake builds in debug configuration on vcpkg: + libcurl-d_imp + libcurl-d + # Static library on Windows, compiled in debug mode + libcurl_a_debug + ) + mark_as_advanced(CURL_LIBRARY_DEBUG) + + include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations_SLIC3R.cmake) + select_library_configurations_SLIC3R(CURL) +endif() if(CURL_INCLUDE_DIR) foreach(_curl_version_header curlver.h curl.h) @@ -46,7 +74,8 @@ if(CURL_INCLUDE_DIR) endforeach() endif() -find_package_handle_standard_args(CURL +include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs_SLIC3R.cmake) +FIND_PACKAGE_HANDLE_STANDARD_ARGS_SLIC3R(CURL REQUIRED_VARS CURL_LIBRARY CURL_INCLUDE_DIR VERSION_VAR CURL_VERSION_STRING) @@ -54,6 +83,29 @@ if(CURL_FOUND) set(CURL_LIBRARIES ${CURL_LIBRARY}) set(CURL_INCLUDE_DIRS ${CURL_INCLUDE_DIR}) - message(STATUS " Curl libraries: = ${CURL_LIBRARIES}") - message(STATUS " Curl include dirs: = ${CURL_INCLUDE_DIRS}") + if(NOT TARGET CURL::libcurl) + add_library(CURL::libcurl UNKNOWN IMPORTED) + set_target_properties(CURL::libcurl PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${CURL_INCLUDE_DIRS}") + + if(EXISTS "${CURL_LIBRARY}") + set_target_properties(CURL::libcurl PROPERTIES + IMPORTED_LINK_INTERFACE_LANGUAGES "C" + IMPORTED_LOCATION "${CURL_LIBRARY}") + endif() + if(CURL_LIBRARY_RELEASE) + set_property(TARGET CURL::libcurl APPEND PROPERTY + IMPORTED_CONFIGURATIONS RELEASE) + set_target_properties(CURL::libcurl PROPERTIES + IMPORTED_LINK_INTERFACE_LANGUAGES "C" + IMPORTED_LOCATION_RELEASE "${CURL_LIBRARY_RELEASE}") + endif() + if(CURL_LIBRARY_DEBUG) + set_property(TARGET CURL::libcurl APPEND PROPERTY + IMPORTED_CONFIGURATIONS DEBUG) + set_target_properties(CURL::libcurl PROPERTIES + IMPORTED_LINK_INTERFACE_LANGUAGES "C" + IMPORTED_LOCATION_DEBUG "${CURL_LIBRARY_DEBUG}") + endif() + endif() endif() diff --git a/cmake/modules/FindPackageHandleStandardArgs_SLIC3R.cmake b/cmake/modules/FindPackageHandleStandardArgs_SLIC3R.cmake new file mode 100644 index 0000000000..eddfd001e4 --- /dev/null +++ b/cmake/modules/FindPackageHandleStandardArgs_SLIC3R.cmake @@ -0,0 +1,392 @@ +# Modified from the CMake github master, +# required by the bundled FindCURL.cmake + + + + +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#[=======================================================================[.rst: +FindPackageHandleStandardArgs +----------------------------- + +This module provides a function intended to be used in :ref:`Find Modules` +implementing :command:`find_package()` calls. It handles the +``REQUIRED``, ``QUIET`` and version-related arguments of ``find_package``. +It also sets the ``_FOUND`` variable. The package is +considered found if all variables listed contain valid results, e.g. +valid filepaths. + +.. command:: find_package_handle_standard_args + + There are two signatures:: + + find_package_handle_standard_args( + (DEFAULT_MSG|) + ... + ) + + find_package_handle_standard_args( + [FOUND_VAR ] + [REQUIRED_VARS ...] + [VERSION_VAR ] + [HANDLE_COMPONENTS] + [CONFIG_MODE] + [FAIL_MESSAGE ] + ) + + The ``_FOUND`` variable will be set to ``TRUE`` if all + the variables ``...`` are valid and any optional + constraints are satisfied, and ``FALSE`` otherwise. A success or + failure message may be displayed based on the results and on + whether the ``REQUIRED`` and/or ``QUIET`` option was given to + the :command:`find_package` call. + + The options are: + + ``(DEFAULT_MSG|)`` + In the simple signature this specifies the failure message. + Use ``DEFAULT_MSG`` to ask for a default message to be computed + (recommended). Not valid in the full signature. + + ``FOUND_VAR `` + Obsolete. Specifies either ``_FOUND`` or + ``_FOUND`` as the result variable. This exists only + for compatibility with older versions of CMake and is now ignored. + Result variables of both names are always set for compatibility. + + ``REQUIRED_VARS ...`` + Specify the variables which are required for this package. + These may be named in the generated failure message asking the + user to set the missing variable values. Therefore these should + typically be cache entries such as ``FOO_LIBRARY`` and not output + variables like ``FOO_LIBRARIES``. + + ``VERSION_VAR `` + Specify the name of a variable that holds the version of the package + that has been found. This version will be checked against the + (potentially) specified required version given to the + :command:`find_package` call, including its ``EXACT`` option. + The default messages include information about the required + version and the version which has been actually found, both + if the version is ok or not. + + ``HANDLE_COMPONENTS`` + Enable handling of package components. In this case, the command + will report which components have been found and which are missing, + and the ``_FOUND`` variable will be set to ``FALSE`` + if any of the required components (i.e. not the ones listed after + the ``OPTIONAL_COMPONENTS`` option of :command:`find_package`) are + missing. + + ``CONFIG_MODE`` + Specify that the calling find module is a wrapper around a + call to ``find_package( NO_MODULE)``. This implies + a ``VERSION_VAR`` value of ``_VERSION``. The command + will automatically check whether the package configuration file + was found. + + ``FAIL_MESSAGE `` + Specify a custom failure message instead of using the default + generated message. Not recommended. + +Example for the simple signature: + +.. code-block:: cmake + + find_package_handle_standard_args(LibXml2 DEFAULT_MSG + LIBXML2_LIBRARY LIBXML2_INCLUDE_DIR) + +The ``LibXml2`` package is considered to be found if both +``LIBXML2_LIBRARY`` and ``LIBXML2_INCLUDE_DIR`` are valid. +Then also ``LibXml2_FOUND`` is set to ``TRUE``. If it is not found +and ``REQUIRED`` was used, it fails with a +:command:`message(FATAL_ERROR)`, independent whether ``QUIET`` was +used or not. If it is found, success will be reported, including +the content of the first ````. On repeated CMake runs, +the same message will not be printed again. + +Example for the full signature: + +.. code-block:: cmake + + find_package_handle_standard_args(LibArchive + REQUIRED_VARS LibArchive_LIBRARY LibArchive_INCLUDE_DIR + VERSION_VAR LibArchive_VERSION) + +In this case, the ``LibArchive`` package is considered to be found if +both ``LibArchive_LIBRARY`` and ``LibArchive_INCLUDE_DIR`` are valid. +Also the version of ``LibArchive`` will be checked by using the version +contained in ``LibArchive_VERSION``. Since no ``FAIL_MESSAGE`` is given, +the default messages will be printed. + +Another example for the full signature: + +.. code-block:: cmake + + find_package(Automoc4 QUIET NO_MODULE HINTS /opt/automoc4) + find_package_handle_standard_args(Automoc4 CONFIG_MODE) + +In this case, a ``FindAutmoc4.cmake`` module wraps a call to +``find_package(Automoc4 NO_MODULE)`` and adds an additional search +directory for ``automoc4``. Then the call to +``find_package_handle_standard_args`` produces a proper success/failure +message. +#]=======================================================================] + +include(${CMAKE_CURRENT_LIST_DIR}/FindPackageMessage_SLIC3R.cmake) + +# internal helper macro +macro(_FPHSA_FAILURE_MESSAGE _msg) + if (${_NAME}_FIND_REQUIRED) + message(FATAL_ERROR "${_msg}") + else () + if (NOT ${_NAME}_FIND_QUIETLY) + message(STATUS "${_msg}") + endif () + endif () +endmacro() + + +# internal helper macro to generate the failure message when used in CONFIG_MODE: +macro(_FPHSA_HANDLE_FAILURE_CONFIG_MODE) + # _CONFIG is set, but FOUND is false, this means that some other of the REQUIRED_VARS was not found: + if(${_NAME}_CONFIG) + _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: missing:${MISSING_VARS} (found ${${_NAME}_CONFIG} ${VERSION_MSG})") + else() + # If _CONSIDERED_CONFIGS is set, the config-file has been found, but no suitable version. + # List them all in the error message: + if(${_NAME}_CONSIDERED_CONFIGS) + set(configsText "") + list(LENGTH ${_NAME}_CONSIDERED_CONFIGS configsCount) + math(EXPR configsCount "${configsCount} - 1") + foreach(currentConfigIndex RANGE ${configsCount}) + list(GET ${_NAME}_CONSIDERED_CONFIGS ${currentConfigIndex} filename) + list(GET ${_NAME}_CONSIDERED_VERSIONS ${currentConfigIndex} version) + string(APPEND configsText " ${filename} (version ${version})\n") + endforeach() + if (${_NAME}_NOT_FOUND_MESSAGE) + string(APPEND configsText " Reason given by package: ${${_NAME}_NOT_FOUND_MESSAGE}\n") + endif() + _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} ${VERSION_MSG}, checked the following files:\n${configsText}") + + else() + # Simple case: No Config-file was found at all: + _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: found neither ${_NAME}Config.cmake nor ${_NAME_LOWER}-config.cmake ${VERSION_MSG}") + endif() + endif() +endmacro() + + +function(FIND_PACKAGE_HANDLE_STANDARD_ARGS_SLIC3R _NAME _FIRST_ARG) + +# Set up the arguments for `cmake_parse_arguments`. + set(options CONFIG_MODE HANDLE_COMPONENTS) + set(oneValueArgs FAIL_MESSAGE VERSION_VAR FOUND_VAR) + set(multiValueArgs REQUIRED_VARS) + +# Check whether we are in 'simple' or 'extended' mode: + set(_KEYWORDS_FOR_EXTENDED_MODE ${options} ${oneValueArgs} ${multiValueArgs} ) + list(FIND _KEYWORDS_FOR_EXTENDED_MODE "${_FIRST_ARG}" INDEX) + + if(${INDEX} EQUAL -1) + set(FPHSA_FAIL_MESSAGE ${_FIRST_ARG}) + set(FPHSA_REQUIRED_VARS ${ARGN}) + set(FPHSA_VERSION_VAR) + else() + cmake_parse_arguments(FPHSA "${options}" "${oneValueArgs}" "${multiValueArgs}" ${_FIRST_ARG} ${ARGN}) + + if(FPHSA_UNPARSED_ARGUMENTS) + message(FATAL_ERROR "Unknown keywords given to FIND_PACKAGE_HANDLE_STANDARD_ARGS(): \"${FPHSA_UNPARSED_ARGUMENTS}\"") + endif() + + if(NOT FPHSA_FAIL_MESSAGE) + set(FPHSA_FAIL_MESSAGE "DEFAULT_MSG") + endif() + + # In config-mode, we rely on the variable _CONFIG, which is set by find_package() + # when it successfully found the config-file, including version checking: + if(FPHSA_CONFIG_MODE) + list(INSERT FPHSA_REQUIRED_VARS 0 ${_NAME}_CONFIG) + list(REMOVE_DUPLICATES FPHSA_REQUIRED_VARS) + set(FPHSA_VERSION_VAR ${_NAME}_VERSION) + endif() + + if(NOT FPHSA_REQUIRED_VARS) + message(FATAL_ERROR "No REQUIRED_VARS specified for FIND_PACKAGE_HANDLE_STANDARD_ARGS()") + endif() + endif() + +# now that we collected all arguments, process them + + if("x${FPHSA_FAIL_MESSAGE}" STREQUAL "xDEFAULT_MSG") + set(FPHSA_FAIL_MESSAGE "Could NOT find ${_NAME}") + endif() + + list(GET FPHSA_REQUIRED_VARS 0 _FIRST_REQUIRED_VAR) + + string(TOUPPER ${_NAME} _NAME_UPPER) + string(TOLOWER ${_NAME} _NAME_LOWER) + + if(FPHSA_FOUND_VAR) + if(FPHSA_FOUND_VAR MATCHES "^${_NAME}_FOUND$" OR FPHSA_FOUND_VAR MATCHES "^${_NAME_UPPER}_FOUND$") + set(_FOUND_VAR ${FPHSA_FOUND_VAR}) + else() + message(FATAL_ERROR "The argument for FOUND_VAR is \"${FPHSA_FOUND_VAR}\", but only \"${_NAME}_FOUND\" and \"${_NAME_UPPER}_FOUND\" are valid names.") + endif() + else() + set(_FOUND_VAR ${_NAME_UPPER}_FOUND) + endif() + + # collect all variables which were not found, so they can be printed, so the + # user knows better what went wrong (#6375) + set(MISSING_VARS "") + set(DETAILS "") + # check if all passed variables are valid + set(FPHSA_FOUND_${_NAME} TRUE) + foreach(_CURRENT_VAR ${FPHSA_REQUIRED_VARS}) + if(NOT ${_CURRENT_VAR}) + set(FPHSA_FOUND_${_NAME} FALSE) + string(APPEND MISSING_VARS " ${_CURRENT_VAR}") + else() + string(APPEND DETAILS "[${${_CURRENT_VAR}}]") + endif() + endforeach() + if(FPHSA_FOUND_${_NAME}) + set(${_NAME}_FOUND TRUE) + set(${_NAME_UPPER}_FOUND TRUE) + else() + set(${_NAME}_FOUND FALSE) + set(${_NAME_UPPER}_FOUND FALSE) + endif() + + # component handling + unset(FOUND_COMPONENTS_MSG) + unset(MISSING_COMPONENTS_MSG) + + if(FPHSA_HANDLE_COMPONENTS) + foreach(comp ${${_NAME}_FIND_COMPONENTS}) + if(${_NAME}_${comp}_FOUND) + + if(NOT DEFINED FOUND_COMPONENTS_MSG) + set(FOUND_COMPONENTS_MSG "found components: ") + endif() + string(APPEND FOUND_COMPONENTS_MSG " ${comp}") + + else() + + if(NOT DEFINED MISSING_COMPONENTS_MSG) + set(MISSING_COMPONENTS_MSG "missing components: ") + endif() + string(APPEND MISSING_COMPONENTS_MSG " ${comp}") + + if(${_NAME}_FIND_REQUIRED_${comp}) + set(${_NAME}_FOUND FALSE) + string(APPEND MISSING_VARS " ${comp}") + endif() + + endif() + endforeach() + set(COMPONENT_MSG "${FOUND_COMPONENTS_MSG} ${MISSING_COMPONENTS_MSG}") + string(APPEND DETAILS "[c${COMPONENT_MSG}]") + endif() + + # version handling: + set(VERSION_MSG "") + set(VERSION_OK TRUE) + + # check with DEFINED here as the requested or found version may be "0" + if (DEFINED ${_NAME}_FIND_VERSION) + if(DEFINED ${FPHSA_VERSION_VAR}) + set(_FOUND_VERSION ${${FPHSA_VERSION_VAR}}) + + if(${_NAME}_FIND_VERSION_EXACT) # exact version required + # count the dots in the version string + string(REGEX REPLACE "[^.]" "" _VERSION_DOTS "${_FOUND_VERSION}") + # add one dot because there is one dot more than there are components + string(LENGTH "${_VERSION_DOTS}." _VERSION_DOTS) + if (_VERSION_DOTS GREATER ${_NAME}_FIND_VERSION_COUNT) + # Because of the C++ implementation of find_package() ${_NAME}_FIND_VERSION_COUNT + # is at most 4 here. Therefore a simple lookup table is used. + if (${_NAME}_FIND_VERSION_COUNT EQUAL 1) + set(_VERSION_REGEX "[^.]*") + elseif (${_NAME}_FIND_VERSION_COUNT EQUAL 2) + set(_VERSION_REGEX "[^.]*\\.[^.]*") + elseif (${_NAME}_FIND_VERSION_COUNT EQUAL 3) + set(_VERSION_REGEX "[^.]*\\.[^.]*\\.[^.]*") + else () + set(_VERSION_REGEX "[^.]*\\.[^.]*\\.[^.]*\\.[^.]*") + endif () + string(REGEX REPLACE "^(${_VERSION_REGEX})\\..*" "\\1" _VERSION_HEAD "${_FOUND_VERSION}") + unset(_VERSION_REGEX) + if (NOT ${_NAME}_FIND_VERSION VERSION_EQUAL _VERSION_HEAD) + set(VERSION_MSG "Found unsuitable version \"${_FOUND_VERSION}\", but required is exact version \"${${_NAME}_FIND_VERSION}\"") + set(VERSION_OK FALSE) + else () + set(VERSION_MSG "(found suitable exact version \"${_FOUND_VERSION}\")") + endif () + unset(_VERSION_HEAD) + else () + if (NOT ${_NAME}_FIND_VERSION VERSION_EQUAL _FOUND_VERSION) + set(VERSION_MSG "Found unsuitable version \"${_FOUND_VERSION}\", but required is exact version \"${${_NAME}_FIND_VERSION}\"") + set(VERSION_OK FALSE) + else () + set(VERSION_MSG "(found suitable exact version \"${_FOUND_VERSION}\")") + endif () + endif () + unset(_VERSION_DOTS) + + else() # minimum version specified: + if (${_NAME}_FIND_VERSION VERSION_GREATER _FOUND_VERSION) + set(VERSION_MSG "Found unsuitable version \"${_FOUND_VERSION}\", but required is at least \"${${_NAME}_FIND_VERSION}\"") + set(VERSION_OK FALSE) + else () + set(VERSION_MSG "(found suitable version \"${_FOUND_VERSION}\", minimum required is \"${${_NAME}_FIND_VERSION}\")") + endif () + endif() + + else() + + # if the package was not found, but a version was given, add that to the output: + if(${_NAME}_FIND_VERSION_EXACT) + set(VERSION_MSG "(Required is exact version \"${${_NAME}_FIND_VERSION}\")") + else() + set(VERSION_MSG "(Required is at least version \"${${_NAME}_FIND_VERSION}\")") + endif() + + endif() + else () + # Check with DEFINED as the found version may be 0. + if(DEFINED ${FPHSA_VERSION_VAR}) + set(VERSION_MSG "(found version \"${${FPHSA_VERSION_VAR}}\")") + endif() + endif () + + if(VERSION_OK) + string(APPEND DETAILS "[v${${FPHSA_VERSION_VAR}}(${${_NAME}_FIND_VERSION})]") + else() + set(${_NAME}_FOUND FALSE) + endif() + + + # print the result: + if (${_NAME}_FOUND) + FIND_PACKAGE_MESSAGE_SLIC3R(${_NAME} "Found ${_NAME}: ${${_FIRST_REQUIRED_VAR}} ${VERSION_MSG} ${COMPONENT_MSG}" "${DETAILS}") + else () + + if(FPHSA_CONFIG_MODE) + _FPHSA_HANDLE_FAILURE_CONFIG_MODE() + else() + if(NOT VERSION_OK) + _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: ${VERSION_MSG} (found ${${_FIRST_REQUIRED_VAR}})") + else() + _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} (missing:${MISSING_VARS}) ${VERSION_MSG}") + endif() + endif() + + endif () + + set(${_NAME}_FOUND ${${_NAME}_FOUND} PARENT_SCOPE) + set(${_NAME_UPPER}_FOUND ${${_NAME}_FOUND} PARENT_SCOPE) +endfunction() diff --git a/cmake/modules/FindPackageMessage_SLIC3R.cmake b/cmake/modules/FindPackageMessage_SLIC3R.cmake new file mode 100644 index 0000000000..a7a5eb98fa --- /dev/null +++ b/cmake/modules/FindPackageMessage_SLIC3R.cmake @@ -0,0 +1,54 @@ +# Modified from the CMake github master. +# required by the bundled FindCURL.cmake + + + + + +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#.rst: +# FindPackageMessage +# ------------------ +# +# +# +# FIND_PACKAGE_MESSAGE( "message for user" "find result details") +# +# This macro is intended to be used in FindXXX.cmake modules files. It +# will print a message once for each unique find result. This is useful +# for telling the user where a package was found. The first argument +# specifies the name (XXX) of the package. The second argument +# specifies the message to display. The third argument lists details +# about the find result so that if they change the message will be +# displayed again. The macro also obeys the QUIET argument to the +# find_package command. +# +# Example: +# +# :: +# +# if(X11_FOUND) +# FIND_PACKAGE_MESSAGE(X11 "Found X11: ${X11_X11_LIB}" +# "[${X11_X11_LIB}][${X11_INCLUDE_DIR}]") +# else() +# ... +# endif() + +function(FIND_PACKAGE_MESSAGE_SLIC3R pkg msg details) + # Avoid printing a message repeatedly for the same find result. + if(NOT ${pkg}_FIND_QUIETLY) + string(REPLACE "\n" "" details "${details}") + set(DETAILS_VAR FIND_PACKAGE_MESSAGE_DETAILS_${pkg}) + if(NOT "${details}" STREQUAL "${${DETAILS_VAR}}") + # The message has not yet been printed. + message(STATUS "${msg}") + + # Save the find details in the cache to avoid printing the same + # message again. + set("${DETAILS_VAR}" "${details}" + CACHE INTERNAL "Details about finding ${pkg}") + endif() + endif() +endfunction() diff --git a/cmake/modules/FindTBB.cmake b/cmake/modules/FindTBB.cmake index 8b498d3ab1..e5115ab443 100644 --- a/cmake/modules/FindTBB.cmake +++ b/cmake/modules/FindTBB.cmake @@ -280,7 +280,7 @@ if(NOT TBB_FOUND) ################################## if(NOT CMAKE_VERSION VERSION_LESS 3.0 AND TBB_FOUND) - add_library(tbb SHARED IMPORTED) + add_library(tbb UNKNOWN IMPORTED) set_target_properties(tbb PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${TBB_INCLUDE_DIRS} IMPORTED_LOCATION ${TBB_LIBRARIES}) @@ -288,7 +288,7 @@ if(NOT TBB_FOUND) set_target_properties(tbb PROPERTIES INTERFACE_COMPILE_DEFINITIONS "$<$,$>:TBB_USE_DEBUG=1>" IMPORTED_LOCATION_DEBUG ${TBB_LIBRARIES_DEBUG} - IMPORTED_LOCATION_RELWITHDEBINFO ${TBB_LIBRARIES_DEBUG} + IMPORTED_LOCATION_RELWITHDEBINFO ${TBB_LIBRARIES_RELEASE} IMPORTED_LOCATION_RELEASE ${TBB_LIBRARIES_RELEASE} IMPORTED_LOCATION_MINSIZEREL ${TBB_LIBRARIES_RELEASE} ) @@ -310,6 +310,7 @@ if(NOT TBB_FOUND) unset(TBB_DEFAULT_SEARCH_DIR) if(TBB_DEBUG) + message(STATUS " TBB_FOUND = ${TBB_FOUND}") message(STATUS " TBB_INCLUDE_DIRS = ${TBB_INCLUDE_DIRS}") message(STATUS " TBB_DEFINITIONS = ${TBB_DEFINITIONS}") message(STATUS " TBB_LIBRARIES = ${TBB_LIBRARIES}") diff --git a/cmake/modules/SelectLibraryConfigurations_SLIC3R.cmake b/cmake/modules/SelectLibraryConfigurations_SLIC3R.cmake new file mode 100644 index 0000000000..d25ac86408 --- /dev/null +++ b/cmake/modules/SelectLibraryConfigurations_SLIC3R.cmake @@ -0,0 +1,77 @@ +# Modified from the CMake github master. +# required by the bundled FindCURL.cmake + + + + +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#.rst: +# SelectLibraryConfigurations +# --------------------------- +# +# +# +# select_library_configurations( basename ) +# +# This macro takes a library base name as an argument, and will choose +# good values for basename_LIBRARY, basename_LIBRARIES, +# basename_LIBRARY_DEBUG, and basename_LIBRARY_RELEASE depending on what +# has been found and set. If only basename_LIBRARY_RELEASE is defined, +# basename_LIBRARY will be set to the release value, and +# basename_LIBRARY_DEBUG will be set to basename_LIBRARY_DEBUG-NOTFOUND. +# If only basename_LIBRARY_DEBUG is defined, then basename_LIBRARY will +# take the debug value, and basename_LIBRARY_RELEASE will be set to +# basename_LIBRARY_RELEASE-NOTFOUND. +# +# If the generator supports configuration types, then basename_LIBRARY +# and basename_LIBRARIES will be set with debug and optimized flags +# specifying the library to be used for the given configuration. If no +# build type has been set or the generator in use does not support +# configuration types, then basename_LIBRARY and basename_LIBRARIES will +# take only the release value, or the debug value if the release one is +# not set. + +# This macro was adapted from the FindQt4 CMake module and is maintained by Will +# Dicharry . + +macro( select_library_configurations_SLIC3R basename ) + if(NOT ${basename}_LIBRARY_RELEASE) + set(${basename}_LIBRARY_RELEASE "${basename}_LIBRARY_RELEASE-NOTFOUND" CACHE FILEPATH "Path to a library.") + endif() + if(NOT ${basename}_LIBRARY_DEBUG) + set(${basename}_LIBRARY_DEBUG "${basename}_LIBRARY_DEBUG-NOTFOUND" CACHE FILEPATH "Path to a library.") + endif() + + get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) + if( ${basename}_LIBRARY_DEBUG AND ${basename}_LIBRARY_RELEASE AND + NOT ${basename}_LIBRARY_DEBUG STREQUAL ${basename}_LIBRARY_RELEASE AND + ( _isMultiConfig OR CMAKE_BUILD_TYPE ) ) + # if the generator is multi-config or if CMAKE_BUILD_TYPE is set for + # single-config generators, set optimized and debug libraries + set( ${basename}_LIBRARY "" ) + foreach( _libname IN LISTS ${basename}_LIBRARY_RELEASE ) + list( APPEND ${basename}_LIBRARY optimized "${_libname}" ) + endforeach() + foreach( _libname IN LISTS ${basename}_LIBRARY_DEBUG ) + list( APPEND ${basename}_LIBRARY debug "${_libname}" ) + endforeach() + elseif( ${basename}_LIBRARY_RELEASE ) + set( ${basename}_LIBRARY ${${basename}_LIBRARY_RELEASE} ) + elseif( ${basename}_LIBRARY_DEBUG ) + set( ${basename}_LIBRARY ${${basename}_LIBRARY_DEBUG} ) + else() + set( ${basename}_LIBRARY "${basename}_LIBRARY-NOTFOUND") + endif() + + set( ${basename}_LIBRARIES "${${basename}_LIBRARY}" ) + + if( ${basename}_LIBRARY ) + set( ${basename}_FOUND TRUE ) + endif() + + mark_as_advanced( ${basename}_LIBRARY_RELEASE + ${basename}_LIBRARY_DEBUG + ) +endmacro() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 330134c3bc..6b7d621a8f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -84,7 +84,7 @@ if (SLIC3R_GUI) # Configure libcurl & OpenSSL find_package(CURL REQUIRED) target_include_directories(slic3r PRIVATE ${CURL_INCLUDE_DIRS}) - target_link_libraries(slic3r ${CURL_LIBRARIES}) + target_link_libraries(slic3r CURL::libcurl) if (SLIC3R_STATIC) if (NOT APPLE) # libcurl is always linked dynamically to the system libcurl on OSX. diff --git a/src/libslic3r/CMakeLists.txt b/src/libslic3r/CMakeLists.txt index b5974489d0..574dc4301f 100644 --- a/src/libslic3r/CMakeLists.txt +++ b/src/libslic3r/CMakeLists.txt @@ -167,7 +167,7 @@ target_link_libraries(libslic3r poly2tri qhull semver - ${TBB_LIBRARIES} + tbb ) if(SLIC3R_PROFILE) From 1979ba0e0ff39ec86974384376470e795beecbc1 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Tue, 23 Oct 2018 09:19:41 +0200 Subject: [PATCH 153/186] New selection -> Keep selection after instance inscrease/decrease command --- src/slic3r/GUI/Plater.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index ecf36595ea..2762bf6f03 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -2094,6 +2094,10 @@ void Plater::increase_instances(size_t num) p->update(); } +#if ENABLE_EXTENDED_SELECTION + p->get_selection().add_instance(obj_idx, (int)model_object->instances.size() - 1); +#endif // ENABLE_EXTENDED_SELECTION + p->selection_changed(); // $self->schedule_background_process; @@ -2137,6 +2141,12 @@ void Plater::decrease_instances(size_t num) } p->update(); + +#if ENABLE_EXTENDED_SELECTION + if (!model_object->instances.empty()) + p->get_selection().add_instance(obj_idx, (int)model_object->instances.size() - 1); +#endif // ENABLE_EXTENDED_SELECTION + p->selection_changed(); // $self->schedule_background_process; From 6d5d4e7c24db3d5d5f33863b6b23304c80ae7756 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Tue, 23 Oct 2018 09:48:01 +0200 Subject: [PATCH 154/186] Fixed exception when closing Slic3r --- src/slic3r/GUI/Tab.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index d4249ea23b..55aeaa234d 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -2426,10 +2426,13 @@ void Tab::OnTreeSelChange(wxTreeEvent& event) wxWindowUpdateLocker noUpdates(this); #endif + if (m_pages.empty()) + return; + Page* page = nullptr; const auto sel_item = m_treectrl->GetSelection(); const auto selection = sel_item ? m_treectrl->GetItemText(sel_item) : ""; - for (auto p : m_pages) + for (auto p : m_pages) if (p->title() == selection) { page = p.get(); From 4c527776e7a812660d125ae83c5bf9c2cb323f8e Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Tue, 23 Oct 2018 11:44:46 +0200 Subject: [PATCH 155/186] Fixed memory leak in Tab::add_options_page() --- src/slic3r/GUI/Tab.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 55aeaa234d..1897b4779b 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -234,9 +234,9 @@ Slic3r::GUI::PageShp Tab::add_options_page(const wxString& title, const std::str icon_idx = (m_icon_index.find(icon) == m_icon_index.end()) ? -1 : m_icon_index.at(icon); if (icon_idx == -1) { // Add a new icon to the icon list. - const auto img_icon = new wxIcon(from_u8(Slic3r::var(icon)), wxBITMAP_TYPE_PNG); - m_icons->Add(*img_icon); - icon_idx = ++m_icon_count; + wxIcon img_icon(from_u8(Slic3r::var(icon)), wxBITMAP_TYPE_PNG); + m_icons->Add(img_icon); + icon_idx = ++m_icon_count; m_icon_index[icon] = icon_idx; } } From 9a4a41acbfe5dc44d51a0918f3eeabd1c4b45f0b Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Tue, 23 Oct 2018 11:50:30 +0200 Subject: [PATCH 156/186] New selection -> Fixed selection cleanup in GLCanvas3D::reset_volumes() --- src/slic3r/GUI/GLCanvas3D.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 7d47ff8f6c..5db94b95f6 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -2893,11 +2893,11 @@ void GLCanvas3D::reset_volumes() return; #endif // !ENABLE_USE_UNIQUE_GLCONTEXT - m_volumes.release_geometry(); - m_volumes.clear(); #if ENABLE_EXTENDED_SELECTION m_selection.clear(); #endif // ENABLE_EXTENDED_SELECTION + m_volumes.release_geometry(); + m_volumes.clear(); m_dirty = true; } From bded28f88805f37c40ccd0cc0f4a3e3a233bee50 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Tue, 23 Oct 2018 15:27:31 +0200 Subject: [PATCH 157/186] WIP: Reconstruction of background processing. --- src/libslic3r/Model.cpp | 42 +++-- src/libslic3r/Model.hpp | 5 +- src/libslic3r/Print.cpp | 36 ++-- src/libslic3r/Print.hpp | 1 + src/libslic3r/PrintObject.cpp | 36 ++-- src/libslic3r/TriangleMesh.cpp | 6 +- src/slic3r/GUI/BackgroundSlicingProcess.cpp | 73 +++++++- src/slic3r/GUI/BackgroundSlicingProcess.hpp | 29 +++- src/slic3r/GUI/GLCanvas3D.cpp | 2 +- src/slic3r/GUI/GUI.cpp | 12 -- src/slic3r/GUI/GUI.hpp | 4 - src/slic3r/GUI/Plater.cpp | 183 +++++++++----------- src/slic3r/GUI/Plater.hpp | 2 +- src/slic3r/GUI/Preset.cpp | 3 +- src/slic3r/GUI/ProgressStatusBar.cpp | 16 +- src/slic3r/GUI/ProgressStatusBar.hpp | 36 ++-- xs/xsp/Print.xsp | 16 -- 17 files changed, 273 insertions(+), 229 deletions(-) diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 1cd20c6fa6..2ff6a34435 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -242,6 +242,14 @@ BoundingBoxf3 Model::bounding_box() const return bb; } +unsigned int Model::update_print_volume_state(const BoundingBoxf3 &print_volume) +{ + unsigned int num_printable = 0; + for (ModelObject *model_object : this->objects) + num_printable += model_object->check_instances_print_volume_state(print_volume); + return num_printable; +} + void Model::center_instances_around_point(const Vec2d &point) { BoundingBoxf3 bb; @@ -875,26 +883,32 @@ void ModelObject::repair() v->mesh.repair(); } -// Called by Print::validate() from the UI thread. -void ModelObject::check_instances_print_volume_state(const BoundingBoxf3& print_volume) +unsigned int ModelObject::check_instances_print_volume_state(const BoundingBoxf3& print_volume) { - for (const ModelVolume* vol : this->volumes) - { - if (vol->is_model_part()) - { - for (ModelInstance* inst : this->instances) - { - BoundingBoxf3 bb = vol->get_convex_hull().transformed_bounding_box(inst->world_matrix()); - + unsigned int num_printable = 0; + enum { + INSIDE = 1, + OUTSIDE = 2 + }; + for (ModelInstance *model_instance : this->instances) { + unsigned int inside_outside = 0; + for (const ModelVolume *vol : this->volumes) + if (vol->is_model_part()) { + BoundingBoxf3 bb = vol->get_convex_hull().transformed_bounding_box(model_instance->world_matrix()); if (print_volume.contains(bb)) - inst->print_volume_state = ModelInstance::PVS_Inside; + inside_outside |= INSIDE; else if (print_volume.intersects(bb)) - inst->print_volume_state = ModelInstance::PVS_Partly_Outside; + inside_outside |= INSIDE | OUTSIDE; else - inst->print_volume_state = ModelInstance::PVS_Fully_Outside; + inside_outside |= OUTSIDE; } - } + model_instance->print_volume_state = + (inside_outside == (INSIDE | OUTSIDE)) ? ModelInstance::PVS_Partly_Outside : + (inside_outside == INSIDE) ? ModelInstance::PVS_Inside : ModelInstance::PVS_Fully_Outside; + if (inside_outside == INSIDE) + ++ num_printable; } + return num_printable; } void ModelObject::print_info() const diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index 81f101636d..9635c2fd2f 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -156,7 +156,7 @@ public: void repair(); // Called by Print::validate() from the UI thread. - void check_instances_print_volume_state(const BoundingBoxf3& print_volume); + unsigned int check_instances_print_volume_state(const BoundingBoxf3& print_volume); // Print object statistics to console. void print_info() const; @@ -411,6 +411,9 @@ public: bool add_default_instances(); // Returns approximate axis aligned bounding box of this model BoundingBoxf3 bounding_box() const; + // Set the print_volume_state of PrintObject::instances, + // return total number of printable objects. + unsigned int update_print_volume_state(const BoundingBoxf3 &print_volume); void center_instances_around_point(const Vec2d &point); void translate(coordf_t x, coordf_t y, coordf_t z) { for (ModelObject *o : this->objects) o->translate(x, y, z); } TriangleMesh mesh() const; diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index cfbbda44b4..d4fed0d5f9 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -852,7 +852,11 @@ bool Print::apply(const Model &model, const DynamicPrintConfig &config_in) bool modifiers_differ = model_volume_list_changed(model_object, model_object_new, ModelVolume::PARAMETER_MODIFIER); bool support_blockers_differ = model_volume_list_changed(model_object, model_object_new, ModelVolume::SUPPORT_BLOCKER); bool support_enforcers_differ = model_volume_list_changed(model_object, model_object_new, ModelVolume::SUPPORT_ENFORCER); - if (model_parts_differ || modifiers_differ) { + if (model_parts_differ || modifiers_differ || + model_object.origin_translation != model_object_new.origin_translation || + model_object.layer_height_ranges != model_object_new.layer_height_ranges || + model_object.layer_height_profile != model_object_new.layer_height_profile || + model_object.layer_height_profile_valid != model_object_new.layer_height_profile_valid) { // The very first step (the slicing step) is invalidated. One may freely remove all associated PrintObjects. auto range = print_object_status.equal_range(PrintObjectStatus(model_object.id())); for (auto it = range.first; it != range.second; ++ it) { @@ -889,6 +893,9 @@ bool Print::apply(const Model &model, const DynamicPrintConfig &config_in) it->print_object->config_apply_only(new_config, diff, true); } } + model_object.name = model_object_new.name; + model_object.input_file = model_object_new.input_file; + model_object.instances = model_object_new.instances; } } @@ -936,11 +943,10 @@ bool Print::apply(const Model &model, const DynamicPrintConfig &config_in) print_objects_new.emplace_back(print_object); print_object_status.emplace(PrintObjectStatus(print_object, PrintObjectStatus::New)); } else if ((*it_old)->print_object->copies() != new_instances.copies) { - // The PrintObject already exists and the copies differ. The only step currently sensitive to the order is the G-code generator. - // Stop it. - this->invalidate_step(psGCodeExport); + // The PrintObject already exists and the copies differ. (*it_old)->print_object->set_copies(new_instances.copies); - } + print_objects_new.emplace_back((*it_old)->print_object); + } } } if (m_objects != print_objects_new) { @@ -958,7 +964,7 @@ bool Print::apply(const Model &model, const DynamicPrintConfig &config_in) int idx_region = 0; for (const auto &volumes : print_object->region_volumes) { if (! volumes.empty()) - ++ m_regions[idx_region]; + ++ m_regions[idx_region]->m_refcnt; ++ idx_region; } } @@ -1110,23 +1116,7 @@ bool Print::has_skirt() const std::string Print::validate() const { - BoundingBox bed_box_2D = get_extents(Polygon::new_scale(m_config.bed_shape.values)); - BoundingBoxf3 print_volume(unscale(bed_box_2D.min(0), bed_box_2D.min(1), 0.0), unscale(bed_box_2D.max(0), bed_box_2D.max(1), scale_(m_config.max_print_height))); - // Allow the objects to protrude below the print bed, only the part of the object above the print bed will be sliced. - print_volume.min(2) = -1e10; - unsigned int printable_count = 0; - { - // Lock due to the po->reload_model_instances() - tbb::mutex::scoped_lock lock(m_mutex); - for (PrintObject *po : m_objects) { - po->model_object()->check_instances_print_volume_state(print_volume); - po->reload_model_instances(); - if (po->is_printable()) - ++ printable_count; - } - } - - if (printable_count == 0) + if (m_objects.empty()) return L("All objects are outside of the print volume."); if (m_config.complete_objects) { diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index f4fd2235be..e765b8801e 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -96,6 +96,7 @@ public: #endif mtx.unlock(); cancel(); + m_state[step] = INVALID; mtx.lock(); } return invalidated; diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index c62dd000ca..38b2e678b9 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -87,23 +87,25 @@ bool PrintObject::delete_last_copy() bool PrintObject::set_copies(const Points &points) { - bool copies_num_changed = m_copies.size() != points.size(); - - // order copies with a nearest neighbor search and translate them by _copies_shift - m_copies.clear(); - m_copies.reserve(points.size()); - - // order copies with a nearest-neighbor search - std::vector ordered_copies; - Slic3r::Geometry::chained_path(points, ordered_copies); - - for (size_t point_idx : ordered_copies) - m_copies.push_back(points[point_idx] + m_copies_shift); - - bool invalidated = m_print->invalidate_step(psSkirt); - invalidated |= m_print->invalidate_step(psBrim); - if (copies_num_changed) - invalidated |= m_print->invalidate_step(psWipeTower); + // Order copies with a nearest-neighbor search. + std::vector copies; + { + std::vector ordered_copies; + Slic3r::Geometry::chained_path(points, ordered_copies); + copies.reserve(ordered_copies.size()); + for (size_t point_idx : ordered_copies) + copies.emplace_back(points[point_idx] + m_copies_shift); + } + // Invalidate and set copies. + bool invalidated = false; + if (copies != m_copies) { + invalidated = m_print->invalidate_step(psSkirt); + invalidated |= m_print->invalidate_step(psBrim); + if (copies.size() != m_copies.size()) + invalidated |= m_print->invalidate_step(psWipeTower); + invalidated |= m_print->invalidate_step(psGCodeExport); + m_copies = copies; + } return invalidated; } diff --git a/src/libslic3r/TriangleMesh.cpp b/src/libslic3r/TriangleMesh.cpp index 665351c393..c8a6e2130b 100644 --- a/src/libslic3r/TriangleMesh.cpp +++ b/src/libslic3r/TriangleMesh.cpp @@ -858,12 +858,12 @@ void TriangleMeshSlicer::_slice_do(size_t facet_idx, std::vector::const_iterator min_layer, max_layer; min_layer = std::lower_bound(z.begin(), z.end(), min_z); // first layer whose slice_z is >= min_z - max_layer = std::upper_bound(z.begin() + (min_layer - z.begin()), z.end(), max_z) - 1; // last layer whose slice_z is <= max_z + max_layer = std::upper_bound(z.begin() + (min_layer - z.begin()), z.end(), max_z); // first layer, whose slice_z is > max_z #ifdef SLIC3R_TRIANGLEMESH_DEBUG - printf("layers: min = %d, max = %d\n", (int)(min_layer - z.begin()), (int)(max_layer - z.begin())); + printf("layers: min = %d, max = %d\n", (int)(min_layer - z.begin()), (int)(max_layer - z.begin()) - 1); #endif /* SLIC3R_TRIANGLEMESH_DEBUG */ - for (std::vector::const_iterator it = min_layer; it != max_layer + 1; ++it) { + for (std::vector::const_iterator it = min_layer; it != max_layer; ++it) { std::vector::size_type layer_idx = it - z.begin(); IntersectionLine il; if (this->slice_facet(*it / SCALING_FACTOR, facet, facet_idx, min_z, max_z, &il) == TriangleMeshSlicer::Slicing) { diff --git a/src/slic3r/GUI/BackgroundSlicingProcess.cpp b/src/slic3r/GUI/BackgroundSlicingProcess.cpp index 7c4a4c0399..71250598b7 100644 --- a/src/slic3r/GUI/BackgroundSlicingProcess.cpp +++ b/src/slic3r/GUI/BackgroundSlicingProcess.cpp @@ -57,12 +57,20 @@ void BackgroundSlicingProcess::thread_proc() if (! m_print->canceled()) { wxQueueEvent(GUI::wxGetApp().mainframe->m_plater, new wxCommandEvent(m_event_sliced_id)); m_print->export_gcode(m_temp_output_path, m_gcode_preview_data); - if (! m_print->canceled() && ! m_output_path.empty()) { - if (copy_file(m_temp_output_path, m_output_path) != 0) - throw std::runtime_error("Copying of the temporary G-code to the output G-code failed"); - m_print->set_status(95, "Running post-processing scripts"); - run_post_process_scripts(m_output_path, m_print->config()); - } + if (! m_print->canceled() && ! this->is_step_done(bspsGCodeFinalize)) { + this->set_step_started(bspsGCodeFinalize); + if (! m_export_path.empty()) { + //FIXME localize the messages + if (copy_file(m_temp_output_path, m_export_path) != 0) + throw std::runtime_error("Copying of the temporary G-code to the output G-code failed"); + m_print->set_status(95, "Running post-processing scripts"); + run_post_process_scripts(m_export_path, m_print->config()); + m_print->set_status(100, "G-code file exported to " + m_export_path); + } else { + m_print->set_status(100, "Slicing complete"); + } + this->set_step_done(bspsGCodeFinalize); + } } } catch (CanceledException &ex) { // Canceled, this is all right. @@ -133,7 +141,7 @@ bool BackgroundSlicingProcess::stop() { std::unique_lock lck(m_mutex); if (m_state == STATE_INITIAL) { - this->m_output_path.clear(); +// this->m_export_path.clear(); return false; } // assert(this->running()); @@ -147,7 +155,7 @@ bool BackgroundSlicingProcess::stop() // In the "Finished" or "Canceled" state. Reset the state to "Idle". m_state = STATE_IDLE; } - this->m_output_path.clear(); +// this->m_export_path.clear(); return true; } @@ -169,4 +177,53 @@ bool BackgroundSlicingProcess::apply(const Model &model, const DynamicPrintConfi return invalidated; } +// Set the output path of the G-code. +void BackgroundSlicingProcess::schedule_export(const std::string &path) +{ + assert(m_export_path.empty()); + if (! m_export_path.empty()) + return; + + // Guard against entering the export step before changing the export path. + tbb::mutex::scoped_lock lock(m_step_state_mutex); + this->invalidate_step(bspsGCodeFinalize); + m_export_path = path; +} + +void BackgroundSlicingProcess::reset_export() +{ + assert(! this->running()); + if (! this->running()) { + m_export_path.clear(); + // invalidate_step expects the mutex to be locked. + tbb::mutex::scoped_lock lock(m_step_state_mutex); + this->invalidate_step(bspsGCodeFinalize); + } +} + +void BackgroundSlicingProcess::set_step_started(BackgroundSlicingProcessStep step) +{ + m_step_state.set_started(step, m_step_state_mutex); + if (m_print->canceled()) + throw CanceledException(); +} + +void BackgroundSlicingProcess::set_step_done(BackgroundSlicingProcessStep step) +{ + m_step_state.set_done(step, m_step_state_mutex); + if (m_print->canceled()) + throw CanceledException(); +} + +bool BackgroundSlicingProcess::invalidate_step(BackgroundSlicingProcessStep step) +{ + bool invalidated = m_step_state.invalidate(step, m_step_state_mutex, [this](){ this->stop(); }); + return invalidated; +} + +bool BackgroundSlicingProcess::invalidate_all_steps() +{ + return m_step_state.invalidate_all(m_step_state_mutex, [this](){ this->stop(); }); +} + }; // namespace Slic3r diff --git a/src/slic3r/GUI/BackgroundSlicingProcess.hpp b/src/slic3r/GUI/BackgroundSlicingProcess.hpp index 758acd682a..4265d1227f 100644 --- a/src/slic3r/GUI/BackgroundSlicingProcess.hpp +++ b/src/slic3r/GUI/BackgroundSlicingProcess.hpp @@ -6,6 +6,8 @@ #include #include +#include "Print.hpp" + namespace Slic3r { class DynamicPrintConfig; @@ -13,6 +15,11 @@ class GCodePreviewData; class Model; class Print; +// Print step IDs for keeping track of the print state. +enum BackgroundSlicingProcessStep { + bspsGCodeFinalize, bspsCount, +}; + // Support for the GUI background processing (Slicing and G-code generation). // As of now this class is not declared in Slic3r::GUI due to the Perl bindings limits. class BackgroundSlicingProcess @@ -32,8 +39,6 @@ public: // The wxCommandEvent is sent to the UI thread asynchronously without waiting for the event to be processed. void set_finished_event(int event_id) { m_event_finished_id = event_id; } - // Set the output path of the G-code. - void set_output_path(const std::string &path) { m_output_path = path; } // Start the background processing. Returns false if the background processing was already running. bool start(); // Cancel the background processing. Returns false if the background processing was not running. @@ -46,6 +51,13 @@ public: // Apply config over the print. Returns false, if the new config values caused any of the already // processed steps to be invalidated, therefore the task will need to be restarted. bool apply(const Model &model, const DynamicPrintConfig &config); + // Set the export path of the G-code. + // Once the path is set, the G-code + void schedule_export(const std::string &path); + // Clear m_export_path. + void reset_export(); + // Once the G-code export is scheduled, the apply() methods will do nothing. + bool is_export_scheduled() const { return ! m_export_path.empty(); } enum State { // m_thread is not running yet, or it did not reach the STATE_IDLE yet (it does not wait on the condition yet). @@ -74,8 +86,11 @@ private: Print *m_print = nullptr; // Data structure, to which the G-code export writes its annotations. GCodePreviewData *m_gcode_preview_data = nullptr; + // Temporary G-code, there is one defined for the BackgroundSlicingProcess, differentiated from the other processes by a process ID. std::string m_temp_output_path; - std::string m_output_path; + // Output path provided by the user. The output path may be set even if the slicing is running, + // but once set, it cannot be re-set. + std::string m_export_path; // Thread, on which the background processing is executed. The thread will always be present // and ready to execute the slicing process. std::thread m_thread; @@ -84,6 +99,14 @@ private: std::condition_variable m_condition; State m_state = STATE_INITIAL; + PrintState m_step_state; + mutable tbb::mutex m_step_state_mutex; + void set_step_started(BackgroundSlicingProcessStep step); + void set_step_done(BackgroundSlicingProcessStep step); + bool is_step_done(BackgroundSlicingProcessStep step) const { return m_step_state.is_done(step); } + bool invalidate_step(BackgroundSlicingProcessStep step); + bool invalidate_all_steps(); + // wxWidgets command ID to be sent to the platter to inform that the slicing is finished, and the G-code export will continue. int m_event_sliced_id = 0; // wxWidgets command ID to be sent to the platter to inform that the task finished. diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 5db94b95f6..9928e43343 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -5145,7 +5145,7 @@ void GLCanvas3D::_render_layer_editing_overlay() const #else int object_idx = int(volume->select_group_id / 1000000); #endif // ENABLE_EXTENDED_SELECTION - if ((int)m_print->objects().size() < object_idx) + if ((int)m_print->objects().size() <= object_idx) return; const PrintObject* print_object = m_print->get_object(object_idx); diff --git a/src/slic3r/GUI/GUI.cpp b/src/slic3r/GUI/GUI.cpp index 0e23585f7b..9e18cac020 100644 --- a/src/slic3r/GUI/GUI.cpp +++ b/src/slic3r/GUI/GUI.cpp @@ -261,18 +261,6 @@ void warning_catcher(wxWindow* parent, const wxString& message){ msg.ShowModal(); } -// Assign a Lambda to the print object to emit a wxWidgets Command with the provided ID -// to deliver a progress status message. -void set_print_callback_event(Print *print, int id) -{ - print->set_status_callback([id](int percent, const std::string &message){ - wxCommandEvent event(id); - event.SetInt(percent); - event.SetString(message); - wxQueueEvent(wxGetApp().mainframe, event.Clone()); - }); -} - void create_combochecklist(wxComboCtrl* comboCtrl, std::string text, std::string items, bool initial_value) { if (comboCtrl == nullptr) diff --git a/src/slic3r/GUI/GUI.hpp b/src/slic3r/GUI/GUI.hpp index 3203fd8b25..cbc20c3c1a 100644 --- a/src/slic3r/GUI/GUI.hpp +++ b/src/slic3r/GUI/GUI.hpp @@ -80,10 +80,6 @@ void show_error_id(int id, const std::string& message); // For Perl void show_info(wxWindow* parent, const wxString& message, const wxString& title); void warning_catcher(wxWindow* parent, const wxString& message); -// Assign a Lambda to the print object to emit a wxWidgets Command with the provided ID -// to deliver a progress status message. -void set_print_callback_event(Print *print, int id); - // Creates a wxCheckListBoxComboPopup inside the given wxComboCtrl, filled with the given text and items. // Items are all initialized to the given value. // Items must be separated by '|', for example "Item1|Item2|Item3", and so on. diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index e5668732ac..fa8368b4dc 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -63,10 +63,10 @@ namespace Slic3r { namespace GUI { +wxDEFINE_EVENT(EVT_PROGRESS_BAR, wxCommandEvent); wxDEFINE_EVENT(EVT_SLICING_COMPLETED, wxCommandEvent); wxDEFINE_EVENT(EVT_PROCESS_COMPLETED, wxCommandEvent); - // Sidebar widgets // struct InfoBox : public wxStaticBox @@ -741,9 +741,6 @@ struct Plater::priv std::vector objects; #endif // !ENABLE_EXTENDED_SELECTION - fs::path export_gcode_output_file; - fs::path send_gcode_file; - // GUI elements wxNotebook *notebook; Sidebar *sidebar; @@ -809,7 +806,7 @@ struct Plater::priv void on_notebook_changed(wxBookCtrlEvent&); void on_select_preset(wxCommandEvent&); - void on_progress_event(); + void on_progress_event(wxCommandEvent&); void on_update_print_preview(wxCommandEvent&); void on_process_completed(wxCommandEvent&); void on_layer_editing_toggled(bool enable); @@ -880,6 +877,14 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) : background_process.set_gcode_preview_data(&gcode_preview_data); background_process.set_sliced_event(EVT_SLICING_COMPLETED); background_process.set_finished_event(EVT_PROCESS_COMPLETED); + // Register progress callback from the Print class to the Platter. + print.set_status_callback([this](int percent, const std::string &message){ + wxCommandEvent event(EVT_PROGRESS_BAR); + event.SetInt(percent); + event.SetString(message); + wxQueueEvent(this->q, event.Clone()); + }); + this->q->Bind(EVT_PROGRESS_BAR, &priv::on_progress_event, this); _3DScene::add_canvas(canvas3D); _3DScene::allow_multisample(canvas3D, GLCanvas3DManager::can_multisample()); @@ -902,7 +907,8 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) : _3DScene::enable_shader(canvas3D, true); _3DScene::enable_force_zoom_to_bed(canvas3D, true); - background_process_timer.Bind(wxEVT_TIMER, [this](wxTimerEvent &evt){ this->async_apply_config(); }, 0); + this->background_process_timer.SetOwner(this->q, 0); + this->q->Bind(wxEVT_TIMER, [this](wxTimerEvent &evt){ this->async_apply_config(); }); auto *bed_shape = config->opt("bed_shape"); _3DScene::set_bed_shape(canvas3D, bed_shape->values); @@ -938,7 +944,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) : canvas3D->Bind(EVT_GLCANVAS_ARRANGE, [this](SimpleEvent&) { arrange(); }); #if !ENABLE_EXTENDED_SELECTION canvas3D->Bind(EVT_GLCANVAS_ROTATE_OBJECT, [this](Event &evt) { /*TODO: call rotate */ }); - canvas3D->Bind(EVT_GLCANVAS_SCALE_UNIFORMLY, [this](SimpleEvent&) { scale(); }); + canvas3D->Bind(EVT_GLCANVAS_SCALE_UNIFORMLY, [this](SimpleEvent&) { this->scale(); }); #endif // !ENABLE_EXTENDED_SELECTION canvas3D->Bind(EVT_GLCANVAS_INCREASE_INSTANCES, [q](Event &evt) { evt.data == 1 ? q->increase_instances() : q->decrease_instances(); }); canvas3D->Bind(EVT_GLCANVAS_INSTANCE_MOVED, [this](SimpleEvent&) { update(); }); @@ -998,7 +1004,7 @@ void Plater::priv::update(bool force_autocenter) } // stop_background_process(); // TODO - print.reload_model_instances(); +// print.reload_model_instances(); #if !ENABLE_EXTENDED_SELECTION const auto selections = collect_selections(); @@ -1008,7 +1014,7 @@ void Plater::priv::update(bool force_autocenter) preview->reset_gcode_preview_data(); preview->reload_print(); - schedule_background_process(); + this->schedule_background_process(); } void Plater::priv::select_view(const std::string& direction) @@ -1034,7 +1040,7 @@ void Plater::priv::update_ui_from_settings() // } } -ProgressStatusBar* Plater::priv::statusbar() +ProgressStatusBar* Plater::priv::statusbar() { return main_frame->m_statusbar; } @@ -1257,7 +1263,7 @@ std::unique_ptr Plater::priv::get_export_file(GUI::FileType case FT_GCODE: wildcard = file_wildcards[file_type]; break; - +// FT_GCODE default: wildcard = file_wildcards[FT_MODEL]; break; @@ -1290,7 +1296,6 @@ std::unique_ptr Plater::priv::get_export_file(GUI::FileType fs::path path(dlg->GetPath()); wxGetApp().app_config->update_last_output_dir(path.parent_path().string()); - export_gcode_output_file = path; return dlg; } @@ -1446,7 +1451,7 @@ void Plater::priv::object_list_changed() _3DScene::enable_toolbar_item(canvas3D, "arrange", have_objects); #endif // ENABLE_EXTENDED_SELECTION - const bool export_in_progress = !(export_gcode_output_file.empty() && send_gcode_file.empty()); + const bool export_in_progress = this->background_process.is_export_scheduled(); // || ! send_gcode_file.empty()); // XXX: is this right? const bool model_fits = _3DScene::check_volumes_outside_state(canvas3D, config) == ModelInstance::PVS_Inside; @@ -1478,7 +1483,7 @@ void Plater::priv::remove(size_t obj_idx) objects.erase(objects.begin() + obj_idx); #endif // !ENABLE_EXTENDED_SELECTION model.delete_object(obj_idx); - print.delete_object(obj_idx); +// print.delete_object(obj_idx); // Delete object from Sidebar list sidebar->obj_list()->delete_object_from_list(obj_idx); @@ -1504,7 +1509,7 @@ void Plater::priv::reset() objects.clear(); #endif // !ENABLE_EXTENDED_SELECTION model.clear_objects(); - print.clear_objects(); +// print.clear_objects(); // Delete all objects from list on c++ side sidebar->obj_list()->delete_all_objects_from_list(); @@ -1609,7 +1614,6 @@ void Plater::priv::split_object() if (new_objects.size() == 1) { Slic3r::GUI::warning_catcher(q, _(L("The selected object couldn't be split because it contains only one part."))); -// $self->schedule_background_process; } else { @@ -1635,9 +1639,16 @@ void Plater::priv::schedule_background_process() void Plater::priv::async_apply_config() { + DynamicPrintConfig config = wxGetApp().preset_bundle->full_config(); + BoundingBox bed_box_2D = get_extents(Polygon::new_scale(config.opt("bed_shape")->values)); + BoundingBoxf3 print_volume(unscale(bed_box_2D.min(0), bed_box_2D.min(1), 0.0), unscale(bed_box_2D.max(0), bed_box_2D.max(1), scale_(config.opt_float("max_print_height")))); + // Allow the objects to protrude below the print bed, only the part of the object above the print bed will be sliced. + print_volume.min(2) = -1e10; + this->q->model().update_print_volume_state(print_volume); + // Apply new config to the possibly running background task. bool was_running = this->background_process.running(); - bool invalidated = this->background_process.apply(this->q->model(), wxGetApp().preset_bundle->full_config()); + bool invalidated = this->background_process.apply(this->q->model(), std::move(config)); // Just redraw the 3D canvas without reloading the scene to consume the update of the layer height profile. if (Slic3r::_3DScene::is_layers_editing_enabled(this->canvas3D)) this->canvas3D->Refresh(); @@ -1669,19 +1680,19 @@ void Plater::priv::async_apply_config() void Plater::priv::start_background_process() { + if (this->background_process.running()) + return; // return if ! @{$self->{objects}} || $self->{background_slicing_process}->running; - // Don't start process thread if config is not valid. - std::string err = wxGetApp().preset_bundle->full_config().validate(); - if (err.empty()) - err = this->q->print().validate(); + // Don't start process thread if Print is not valid. + std::string err = this->q->print().validate(); if (! err.empty()) { - // $self->statusbar->SetStatusText(err); - return; - } - // Copy the names of active presets into the placeholder parser. - wxGetApp().preset_bundle->export_selections(this->q->print().placeholder_parser()); - // Start the background process. - this->background_process.start(); + this->statusbar()->set_status_text(err); + } else { + // Copy the names of active presets into the placeholder parser. + wxGetApp().preset_bundle->export_selections(this->q->print().placeholder_parser()); + // Start the background process. + this->background_process.start(); + } } void Plater::priv::stop_background_process() @@ -1795,9 +1806,10 @@ void Plater::priv::on_select_preset(wxCommandEvent &evt) wxGetApp().plater()->on_config_change(wxGetApp().preset_bundle->full_config()); } -void Plater::priv::on_progress_event() +void Plater::priv::on_progress_event(wxCommandEvent &evt) { - // TODO + this->statusbar()->set_progress(evt.GetInt()); + this->statusbar()->set_status_text(evt.GetString() + wxString::FromUTF8("…")); } void Plater::priv::on_update_print_preview(wxCommandEvent &) @@ -1813,62 +1825,25 @@ void Plater::priv::on_update_print_preview(wxCommandEvent &) #endif // !ENABLE_EXTENDED_SELECTION } -void Plater::priv::on_process_completed(wxCommandEvent &) +void Plater::priv::on_process_completed(wxCommandEvent &evt) { // Stop the background task, wait until the thread goes into the "Idle" state. // At this point of time the thread should be either finished or canceled, // so the following call just confirms, that the produced data were consumed. this->background_process.stop(); - //$self->statusbar->ResetCancelCallback(); - //$self->statusbar->StopBusy; - //$self->statusbar->SetStatusText(""); - -/* - my $message; - my $send_gcode = 0; - my $do_print = 0; -# print "Process completed, message: ", $message, "\n"; - if (defined($result)) { - $message = L("Export failed"); - } else { - # G-code file exported successfully. - if ($self->{print_file}) { - $message = L("File added to print queue"); - $do_print = 1; - } elsif ($self->{send_gcode_file}) { - $message = L("Sending G-code file to the Printer Host ..."); - $send_gcode = 1; - } elsif (defined $self->{export_gcode_output_file}) { - $message = L("G-code file exported to ") . $self->{export_gcode_output_file}; - } else { - $message = L("Slicing complete"); - } + this->statusbar()->reset_cancel_callback(); + this->statusbar()->stop_busy(); + + bool success = evt.GetInt(); + // Reset the "export G-code path" name, so that the automatic background processing will be enabled again. + this->background_process.reset_export(); + if (! success) { + wxString message = evt.GetString(); + if (message.IsEmpty()) + message = _(L("Export failed")); + this->statusbar()->set_status_text(message); } - $self->{export_gcode_output_file} = undef; - wxTheApp->notify($message); - - $self->do_print if $do_print; - # Send $self->{send_gcode_file} to OctoPrint. - if ($send_gcode) { - my $host = Slic3r::PrintHost::get_print_host($self->{config}); - if ($host->send_gcode($self->{send_gcode_file})) { - $message = L("Upload to host finished."); - } else { - $message = ""; - } - } -*/ - - // As of now, the BackgroundProcessing thread posts status bar update messages to a queue on the MainFrame.pm, - // but the "Processing finished" message is posted to this window. - // Delay the following status bar update, so it will be called later than what is received by MainFrame.pm. - //wxTheApp->CallAfter(sub { -// $self->statusbar->SetStatusText($message); -// }); - - //$self->{print_file} = undef; - //$self->{send_gcode_file} = undef; //$self->print_info_box_show(1); // this updates buttons status @@ -2209,9 +2184,9 @@ void Plater::increase_instances(size_t num) Vec3d offset_vec = model_instance->get_offset() + Vec3d(offset, offset, 0.0); model_object->add_instance(offset_vec, model_instance->get_scaling_factor(), model_instance->get_rotation()); #if ENABLE_EXTENDED_SELECTION - p->print.get_object(obj_idx)->add_copy(Slic3r::to_2d(offset_vec)); +// p->print.get_object(obj_idx)->add_copy(Slic3r::to_2d(offset_vec)); #else - p->print.get_object(*obj_idx)->add_copy(Slic3r::to_2d(offset_vec)); +// p->print.get_object(*obj_idx)->add_copy(Slic3r::to_2d(offset_vec)); #endif // ENABLE_EXTENDED_SELECTION } @@ -2254,9 +2229,9 @@ void Plater::decrease_instances(size_t num) for (size_t i = 0; i < num; i++) { model_object->delete_last_instance(); #if ENABLE_EXTENDED_SELECTION - p->print.get_object(obj_idx)->delete_last_copy(); +// p->print.get_object(obj_idx)->delete_last_copy(); #else - p->print.get_object(*obj_idx)->delete_last_copy(); +// p->print.get_object(*obj_idx)->delete_last_copy(); #endif // ENABLE_EXTENDED_SELECTION } #if ENABLE_EXTENDED_SELECTION @@ -2281,8 +2256,7 @@ void Plater::decrease_instances(size_t num) #endif // ENABLE_EXTENDED_SELECTION p->selection_changed(); - - // $self->schedule_background_process; + this->p->schedule_background_process(); } void Plater::set_number_of_copies(size_t num) @@ -2307,38 +2281,35 @@ void Plater::set_number_of_copies(size_t num) decrease_instances(-diff); } -fs::path Plater::export_gcode(const fs::path &output_path) +void Plater::export_gcode(fs::path output_path) { #if ENABLE_EXTENDED_SELECTION - if (p->model.objects.empty()) { return ""; } + if (p->model.objects.empty()) + return; #else - if (p->objects.empty()) { return ""; } + if (p->objects.empty()) + return; #endif // ENABLE_EXTENDED_SELECTION - if (! p->export_gcode_output_file.empty()) { + if (this->p->background_process.is_export_scheduled()) { GUI::show_error(this, _(L("Another export job is currently running."))); - return ""; + return; } std::string err = wxGetApp().preset_bundle->full_config().validate(); - if (err.empty()) { + if (err.empty()) err = p->print.validate(); - } if (! err.empty()) { // The config is not valid GUI::show_error(this, _(err)); - return fs::path(); + return; } // Copy the names of active presets into the placeholder parser. wxGetApp().preset_bundle->export_selections(p->print.placeholder_parser()); // select output file - if (! output_path.empty()) { - p->export_gcode_output_file = fs::path(p->print.output_filepath(output_path.string())); - // FIXME: ^ errors to handle? - } else { - + if (output_path.empty()) { // XXX: take output path from CLI opts? Ancient Slic3r versions used to do that... // If possible, remove accents from accented latin characters. @@ -2355,13 +2326,17 @@ fs::path Plater::export_gcode(const fs::path &output_path) wxFD_SAVE | wxFD_OVERWRITE_PROMPT ); - if (dlg.ShowModal() != wxID_OK) { return ""; } - fs::path path(dlg.GetPath()); - wxGetApp().app_config->update_last_output_dir(path.parent_path().string()); - p->export_gcode_output_file = path; + if (dlg.ShowModal() == wxID_OK) { + fs::path path(dlg.GetPath()); + wxGetApp().app_config->update_last_output_dir(path.parent_path().string()); + output_path = path; + } } - return p->export_gcode_output_file; + if (! output_path.empty()) { + this->p->background_process.schedule_export(p->print.output_filepath(output_path.string())); + this->p->background_process.start(); + } } void Plater::export_stl() @@ -2452,7 +2427,7 @@ void Plater::reslice() void Plater::send_gcode() { - p->send_gcode_file = export_gcode(); +// p->send_gcode_file = export_gcode(); } void Plater::on_extruders_change(int num_extruders) diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 544d4672ad..ab912f5e3a 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -118,7 +118,7 @@ public: void set_number_of_copies(size_t num); // Note: empty path means "use the default" - boost::filesystem::path export_gcode(const boost::filesystem::path &output_path = boost::filesystem::path()); + void export_gcode(boost::filesystem::path output_path = boost::filesystem::path()); void export_stl(); void export_amf(); void export_3mf(); diff --git a/src/slic3r/GUI/Preset.cpp b/src/slic3r/GUI/Preset.cpp index 1a6063dc73..07410e325f 100644 --- a/src/slic3r/GUI/Preset.cpp +++ b/src/slic3r/GUI/Preset.cpp @@ -884,7 +884,8 @@ bool PresetCollection::update_dirty_ui(wxBitmapComboBox *ui) std::string old_label = ui->GetString(ui_id).utf8_str().data(); std::string preset_name = Preset::remove_suffix_modified(old_label); const Preset *preset = this->find_preset(preset_name, false); - assert(preset != nullptr); +// The old_label could be the "----- system presets ------" or the "------- user presets --------" separator. +// assert(preset != nullptr); if (preset != nullptr) { std::string new_label = preset->is_dirty ? preset->name + g_suffix_modified : preset->name; if (old_label != new_label) diff --git a/src/slic3r/GUI/ProgressStatusBar.cpp b/src/slic3r/GUI/ProgressStatusBar.cpp index 45c3aaa76b..44a7b06c51 100644 --- a/src/slic3r/GUI/ProgressStatusBar.cpp +++ b/src/slic3r/GUI/ProgressStatusBar.cpp @@ -53,8 +53,8 @@ ProgressStatusBar::ProgressStatusBar(wxWindow *parent, int id): }); m_cancelbutton->Bind(wxEVT_BUTTON, [this](const wxCommandEvent&) { - if(m_cancel_cb) m_cancel_cb(); - m_perl_cancel_callback.call(); + if (m_cancel_cb) + m_cancel_cb(); m_cancelbutton->Hide(); }); } @@ -136,7 +136,17 @@ void ProgressStatusBar::embed(wxFrame *frame) void ProgressStatusBar::set_status_text(const wxString& txt) { - self->SetStatusText(wxString::FromUTF8(txt.c_str())); + self->SetStatusText(txt); +} + +void ProgressStatusBar::set_status_text(const std::string& txt) +{ + this->set_status_text(txt.c_str()); +} + +void ProgressStatusBar::set_status_text(const char *txt) +{ + this->set_status_text(wxString::FromUTF8(txt)); } void ProgressStatusBar::show_cancel_button() diff --git a/src/slic3r/GUI/ProgressStatusBar.hpp b/src/slic3r/GUI/ProgressStatusBar.hpp index 57ec9ae2bb..f33a70ed30 100644 --- a/src/slic3r/GUI/ProgressStatusBar.hpp +++ b/src/slic3r/GUI/ProgressStatusBar.hpp @@ -4,8 +4,6 @@ #include #include -#include "callback.hpp" - class wxTimer; class wxGauge; class wxButton; @@ -22,7 +20,8 @@ namespace Slic3r { * of the Slicer main window. It consists of a message area to the left and a * progress indication area to the right with an optional cancel button. */ -class ProgressStatusBar { +class ProgressStatusBar +{ wxStatusBar *self; // we cheat! It should be the base class but: perl! wxTimer *m_timer; wxGauge *m_prog; @@ -35,25 +34,26 @@ public: ProgressStatusBar(wxWindow *parent = nullptr, int id = -1); ~ProgressStatusBar(); - int get_progress() const; - void set_progress(int); - int get_range() const; - void set_range(int = 100); - void show_progress(bool); - void start_busy(int = 100); - void stop_busy(); + int get_progress() const; + void set_progress(int); + int get_range() const; + void set_range(int = 100); + void show_progress(bool); + void start_busy(int = 100); + void stop_busy(); inline bool is_busy() const { return m_busy; } - void set_cancel_callback(CancelFn = CancelFn()); - inline void remove_cancel_callback() { set_cancel_callback(); } - void run(int rate); - void embed(wxFrame *frame = nullptr); - void set_status_text(const wxString& txt); + void set_cancel_callback(CancelFn = CancelFn()); + inline void reset_cancel_callback() { set_cancel_callback(); } + void run(int rate); + void embed(wxFrame *frame = nullptr); + void set_status_text(const wxString& txt); + void set_status_text(const std::string& txt); + void set_status_text(const char *txt); // Temporary methods to satisfy Perl side - void show_cancel_button(); - void hide_cancel_button(); + void show_cancel_button(); + void hide_cancel_button(); - PerlCallback m_perl_cancel_callback; private: bool m_busy = false; CancelFn m_cancel_cb; diff --git a/xs/xsp/Print.xsp b/xs/xsp/Print.xsp index 0424d8b7b2..39708ca7a9 100644 --- a/xs/xsp/Print.xsp +++ b/xs/xsp/Print.xsp @@ -185,22 +185,6 @@ _constant() } %}; - void export_gcode_with_preview_data(char *path_template, GCodePreviewData *preview_data) %code%{ - try { - THIS->export_gcode(path_template, preview_data); - } catch (std::exception& e) { - croak(e.what()); - } - %}; - - void export_gcode(char *path_template) %code%{ - try { - THIS->export_gcode(path_template, nullptr); - } catch (std::exception& e) { - croak(e.what()); - } - %}; - void export_png(char *path) %code%{ try { THIS->export_png(path); From 34e652b9858e88bee7dc549908e8f0389bfdda4f Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Tue, 23 Oct 2018 17:18:38 +0200 Subject: [PATCH 158/186] Fixing nesting crash in debug mode. Also commented out unnecessary bloat from AppController --- src/libnest2d/CMakeLists.txt | 181 +- src/libnest2d/README.md | 43 - .../cmake_modules/DownloadNLopt.cmake | 7 +- src/libnest2d/cmake_modules/FindClipper.cmake | 10 +- src/libnest2d/cmake_modules/FindNLopt.cmake | 9 +- src/libnest2d/cmake_modules/FindTBB.cmake | 322 ---- src/libnest2d/examples/main.cpp | 218 --- src/libnest2d/include/libnest2d.h | 175 ++ .../backends/clipper}/CMakeLists.txt | 41 +- .../backends/clipper/geometries.hpp} | 24 +- .../{ => include}/libnest2d/common.hpp | 0 .../include/libnest2d/geometry_traits.hpp | 965 ++++++++++ .../libnest2d/geometry_traits_nfp.hpp | 464 +++-- .../{ => include}/libnest2d/libnest2d.hpp | 10 +- .../{ => include}/libnest2d/optimizer.hpp | 5 + .../libnest2d/optimizers/nlopt/CMakeLists.txt | 61 + .../libnest2d/optimizers/nlopt}/genetic.hpp | 3 +- .../optimizers/nlopt}/nlopt_boilerplate.hpp | 26 +- .../libnest2d/optimizers/nlopt}/simplex.hpp | 0 .../libnest2d/optimizers/nlopt}/subplex.hpp | 0 .../optimizers/optimlib/CMakeLists.txt | 5 + .../libnest2d/placers/bottomleftplacer.hpp | 9 +- .../libnest2d/placers/nfpplacer.hpp | 58 +- .../libnest2d/placers/placer_boilerplate.hpp | 2 +- .../libnest2d/selections/djd_heuristic.hpp | 0 .../libnest2d/selections/filler.hpp | 0 .../libnest2d/selections/firstfit.hpp | 1 - .../selections/selection_boilerplate.hpp | 2 +- .../libnest2d/utils}/boost_alg.hpp | 12 +- .../libnest2d/utils}/metaloop.hpp | 4 +- .../libnest2d/utils}/rotfinder.hpp | 0 src/libnest2d/libnest2d.h | 42 - src/libnest2d/libnest2d/geometry_traits.hpp | 825 --------- src/libnest2d/tests/CMakeLists.txt | 32 +- src/libnest2d/tests/test.cpp | 56 +- src/libnest2d/tools/benchmark.h | 58 - src/libnest2d/tools/libnfpglue.cpp | 157 -- src/libnest2d/tools/libnfpglue.hpp | 46 - src/libnest2d/tools/libnfporb/LICENSE | 674 ------- src/libnest2d/tools/libnfporb/ORIGIN | 2 - src/libnest2d/tools/libnfporb/README.md | 89 - src/libnest2d/tools/libnfporb/libnfporb.hpp | 1547 ----------------- src/libnest2d/tools/nfp_svgnest.hpp | 1018 ----------- src/libnest2d/tools/nfp_svgnest_glue.hpp | 75 - src/libnest2d/tools/svgtools.hpp | 2 +- src/libslic3r/CMakeLists.txt | 2 +- src/slic3r/AppController.cpp | 193 +- 47 files changed, 1928 insertions(+), 5547 deletions(-) delete mode 100644 src/libnest2d/README.md delete mode 100644 src/libnest2d/cmake_modules/FindTBB.cmake delete mode 100644 src/libnest2d/examples/main.cpp create mode 100644 src/libnest2d/include/libnest2d.h rename src/libnest2d/{libnest2d/clipper_backend => include/libnest2d/backends/clipper}/CMakeLists.txt (55%) rename src/libnest2d/{libnest2d/clipper_backend/clipper_backend.hpp => include/libnest2d/backends/clipper/geometries.hpp} (95%) rename src/libnest2d/{ => include}/libnest2d/common.hpp (100%) create mode 100644 src/libnest2d/include/libnest2d/geometry_traits.hpp rename src/libnest2d/{ => include}/libnest2d/geometry_traits_nfp.hpp (56%) rename src/libnest2d/{ => include}/libnest2d/libnest2d.hpp (99%) rename src/libnest2d/{ => include}/libnest2d/optimizer.hpp (96%) create mode 100644 src/libnest2d/include/libnest2d/optimizers/nlopt/CMakeLists.txt rename src/libnest2d/{libnest2d/optimizers => include/libnest2d/optimizers/nlopt}/genetic.hpp (88%) rename src/libnest2d/{libnest2d/optimizers => include/libnest2d/optimizers/nlopt}/nlopt_boilerplate.hpp (85%) rename src/libnest2d/{libnest2d/optimizers => include/libnest2d/optimizers/nlopt}/simplex.hpp (100%) rename src/libnest2d/{libnest2d/optimizers => include/libnest2d/optimizers/nlopt}/subplex.hpp (100%) create mode 100644 src/libnest2d/include/libnest2d/optimizers/optimlib/CMakeLists.txt rename src/libnest2d/{ => include}/libnest2d/placers/bottomleftplacer.hpp (98%) rename src/libnest2d/{ => include}/libnest2d/placers/nfpplacer.hpp (97%) rename src/libnest2d/{ => include}/libnest2d/placers/placer_boilerplate.hpp (98%) rename src/libnest2d/{ => include}/libnest2d/selections/djd_heuristic.hpp (100%) rename src/libnest2d/{ => include}/libnest2d/selections/filler.hpp (100%) rename src/libnest2d/{ => include}/libnest2d/selections/firstfit.hpp (99%) rename src/libnest2d/{ => include}/libnest2d/selections/selection_boilerplate.hpp (96%) rename src/libnest2d/{libnest2d => include/libnest2d/utils}/boost_alg.hpp (98%) rename src/libnest2d/{libnest2d => include/libnest2d/utils}/metaloop.hpp (98%) rename src/libnest2d/{libnest2d => include/libnest2d/utils}/rotfinder.hpp (100%) delete mode 100644 src/libnest2d/libnest2d.h delete mode 100644 src/libnest2d/libnest2d/geometry_traits.hpp delete mode 100644 src/libnest2d/tools/benchmark.h delete mode 100644 src/libnest2d/tools/libnfpglue.cpp delete mode 100644 src/libnest2d/tools/libnfpglue.hpp delete mode 100644 src/libnest2d/tools/libnfporb/LICENSE delete mode 100644 src/libnest2d/tools/libnfporb/ORIGIN delete mode 100644 src/libnest2d/tools/libnfporb/README.md delete mode 100644 src/libnest2d/tools/libnfporb/libnfporb.hpp delete mode 100644 src/libnest2d/tools/nfp_svgnest.hpp delete mode 100644 src/libnest2d/tools/nfp_svgnest_glue.hpp diff --git a/src/libnest2d/CMakeLists.txt b/src/libnest2d/CMakeLists.txt index f813550123..21840aee29 100644 --- a/src/libnest2d/CMakeLists.txt +++ b/src/libnest2d/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.8) +cmake_minimum_required(VERSION 3.0) project(Libnest2D) @@ -11,125 +11,112 @@ set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED) # Add our own cmake module path. -list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules/) +list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake_modules/) option(LIBNEST2D_UNITTESTS "If enabled, googletest framework will be downloaded and the provided unit tests will be included in the build." OFF) option(LIBNEST2D_BUILD_EXAMPLES "If enabled, examples will be built." OFF) -set(LIBNEST2D_GEOMETRIES_BACKEND "clipper" CACHE STRING - "Build libnest2d with geometry classes implemented by the chosen backend.") +option(LIBNEST2D_HEADER_ONLY "If enabled static library will not be built." ON) -set(LIBNEST2D_OPTIMIZER_BACKEND "nlopt" CACHE STRING - "Build libnest2d with optimization features implemented by the chosen backend.") +set(GEOMETRY_BACKENDS clipper boost eigen) +set(LIBNEST2D_GEOMETRIES clipper CACHE STRING "Geometry backend") +set_property(CACHE LIBNEST2D_GEOMETRIES PROPERTY STRINGS ${GEOMETRY_BACKENDS}) +list(FIND GEOMETRY_BACKENDS ${LIBNEST2D_GEOMETRIES} GEOMETRY_TYPE) +if(${GEOMETRY_TYPE} EQUAL -1) + message(FATAL_ERROR "Option ${LIBNEST2D_GEOMETRIES} not supported, valid entries are ${GEOMETRY_BACKENDS}") +endif() + +set(OPTIMIZERS nlopt optimlib) +set(LIBNEST2D_OPTIMIZER nlopt CACHE STRING "Optimization backend") +set_property(CACHE LIBNEST2D_OPTIMIZER PROPERTY STRINGS ${OPTIMIZERS}) +list(FIND OPTIMIZERS ${LIBNEST2D_OPTIMIZER} OPTIMIZER_TYPE) +if(${OPTIMIZER_TYPE} EQUAL -1) + message(FATAL_ERROR "Option ${LIBNEST2D_OPTIMIZER} not supported, valid entries are ${OPTIMIZERS}") +endif() + +add_library(libnest2d INTERFACE) + +set(SRC_DIR ${PROJECT_SOURCE_DIR}/include) set(LIBNEST2D_SRCFILES - ${CMAKE_CURRENT_SOURCE_DIR}/libnest2d/libnest2d.hpp # Templates only - ${CMAKE_CURRENT_SOURCE_DIR}/libnest2d.h # Exports ready made types using template arguments - ${CMAKE_CURRENT_SOURCE_DIR}/libnest2d/geometry_traits.hpp - ${CMAKE_CURRENT_SOURCE_DIR}/libnest2d/common.hpp - ${CMAKE_CURRENT_SOURCE_DIR}/libnest2d/optimizer.hpp - ${CMAKE_CURRENT_SOURCE_DIR}/libnest2d/metaloop.hpp - ${CMAKE_CURRENT_SOURCE_DIR}/libnest2d/rotfinder.hpp - ${CMAKE_CURRENT_SOURCE_DIR}/libnest2d/placers/placer_boilerplate.hpp - ${CMAKE_CURRENT_SOURCE_DIR}/libnest2d/placers/bottomleftplacer.hpp - ${CMAKE_CURRENT_SOURCE_DIR}/libnest2d/placers/nfpplacer.hpp - ${CMAKE_CURRENT_SOURCE_DIR}/libnest2d/geometry_traits_nfp.hpp - ${CMAKE_CURRENT_SOURCE_DIR}/libnest2d/selections/selection_boilerplate.hpp - ${CMAKE_CURRENT_SOURCE_DIR}/libnest2d/selections/filler.hpp - ${CMAKE_CURRENT_SOURCE_DIR}/libnest2d/selections/firstfit.hpp - ${CMAKE_CURRENT_SOURCE_DIR}/libnest2d/selections/djd_heuristic.hpp + ${SRC_DIR}/libnest2d/libnest2d.hpp # Templates only + ${SRC_DIR}/libnest2d/geometry_traits.hpp + ${SRC_DIR}/libnest2d/geometry_traits_nfp.hpp + ${SRC_DIR}/libnest2d/common.hpp + ${SRC_DIR}/libnest2d/optimizer.hpp + ${SRC_DIR}/libnest2d/utils/metaloop.hpp + ${SRC_DIR}/libnest2d/utils/rotfinder.hpp + ${SRC_DIR}/libnest2d/placers/placer_boilerplate.hpp + ${SRC_DIR}/libnest2d/placers/bottomleftplacer.hpp + ${SRC_DIR}/libnest2d/placers/nfpplacer.hpp + ${SRC_DIR}/libnest2d/selections/selection_boilerplate.hpp + ${SRC_DIR}/libnest2d/selections/filler.hpp + ${SRC_DIR}/libnest2d/selections/firstfit.hpp + ${SRC_DIR}/libnest2d/selections/djd_heuristic.hpp ) -set(LIBNEST2D_LIBRARIES "") - -set(LIBNEST2D_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}) - -if(LIBNEST2D_GEOMETRIES_BACKEND STREQUAL "clipper") - - # Clipper backend is not enough on its own, it still needs some functions - # from Boost geometry - if(NOT Boost_INCLUDE_DIRS_FOUND) - find_package(Boost 1.58 REQUIRED) - # TODO automatic download of boost geometry headers +set(TBB_STATIC ON) +find_package(TBB QUIET) +if(TBB_FOUND) + message(STATUS "Parallelization with Intel TBB") + target_include_directories(libnest2d INTERFACE ${TBB_INCLUDE_DIRS}) + target_compile_definitions(libnest2d INTERFACE ${TBB_DEFINITIONS} -DUSE_TBB) + if(MSVC) + # Suppress implicit linking of the TBB libraries by the Visual Studio compiler. + target_compile_definitions(libnest2d INTERFACE -D__TBB_NO_IMPLICIT_LINKAGE) endif() + # The Intel TBB library will use the std::exception_ptr feature of C++11. + target_compile_definitions(libnest2d INTERFACE -DTBB_USE_CAPTURED_EXCEPTION=1) - add_subdirectory(libnest2d/clipper_backend) + target_link_libraries(libnest2d INTERFACE ${TBB_LIBRARIES}) +else() + find_package(OpenMP QUIET) - include_directories(BEFORE ${CLIPPER_INCLUDE_DIRS}) - include_directories(${Boost_INCLUDE_DIRS}) - - list(APPEND LIBNEST2D_SRCFILES ${CMAKE_CURRENT_SOURCE_DIR}/libnest2d/clipper_backend/clipper_backend.hpp - ${CMAKE_CURRENT_SOURCE_DIR}/libnest2d/boost_alg.hpp) - list(APPEND LIBNEST2D_LIBRARIES ${CLIPPER_LIBRARIES}) - list(APPEND LIBNEST2D_HEADERS ${CLIPPER_INCLUDE_DIRS} - ${Boost_INCLUDE_DIRS_FOUND}) + if(OpenMP_CXX_FOUND) + message(STATUS "Parallelization with OpenMP") + target_include_directories(libnest2d INTERFACE OpenMP::OpenMP_CXX) + target_link_libraries(libnest2d INTERFACE OpenMP::OpenMP_CXX) + else() + message("Parallelization with C++11 threads") + find_package(Threads REQUIRED) + target_link_libraries(libnest2d INTERFACE Threads::Threads) + endif() endif() -if(LIBNEST2D_OPTIMIZER_BACKEND STREQUAL "nlopt") - find_package(NLopt 1.4) - if(NOT NLopt_FOUND) - message(STATUS "NLopt not found so downloading " - "and automatic build is performed...") - include(DownloadNLopt) - endif() - find_package(Threads REQUIRED) +add_subdirectory(${SRC_DIR}/libnest2d/backends/${LIBNEST2D_GEOMETRIES}) +add_subdirectory(${SRC_DIR}/libnest2d/optimizers/${LIBNEST2D_OPTIMIZER}) - list(APPEND LIBNEST2D_SRCFILES ${CMAKE_CURRENT_SOURCE_DIR}/libnest2d/optimizers/simplex.hpp - ${CMAKE_CURRENT_SOURCE_DIR}/libnest2d/optimizers/subplex.hpp - ${CMAKE_CURRENT_SOURCE_DIR}/libnest2d/optimizers/genetic.hpp - ${CMAKE_CURRENT_SOURCE_DIR}/libnest2d/optimizers/nlopt_boilerplate.hpp) - list(APPEND LIBNEST2D_LIBRARIES ${NLopt_LIBS}) - list(APPEND LIBNEST2D_HEADERS ${NLopt_INCLUDE_DIR}) -endif() +target_sources(libnest2d INTERFACE ${LIBNEST2D_SRCFILES}) +target_include_directories(libnest2d INTERFACE ${SRC_DIR}) -if(LIBNEST2D_UNITTESTS) - enable_testing() - add_subdirectory(tests) +if(NOT LIBNEST2D_HEADER_ONLY) + set(LIBNAME libnest2d_${LIBNEST2D_GEOMETRIES}_${LIBNEST2D_OPTIMIZER}) + add_library(${LIBNAME} ${PROJECT_SOURCE_DIR}/src/libnest2d.cpp) + target_link_libraries(${LIBNAME} PUBLIC libnest2d) + target_compile_definitions(${LIBNAME} PUBLIC LIBNEST2D_STATIC) endif() if(LIBNEST2D_BUILD_EXAMPLES) - add_executable(example examples/main.cpp -# tools/libnfpglue.hpp -# tools/libnfpglue.cpp - tools/nfp_svgnest.hpp - tools/nfp_svgnest_glue.hpp - tools/svgtools.hpp - tests/printer_parts.cpp - tests/printer_parts.h - ${LIBNEST2D_SRCFILES} - ) - set(TBB_STATIC ON) - find_package(TBB QUIET) - if(TBB_FOUND) - message(STATUS "Parallelization with Intel TBB") - target_include_directories(example PUBLIC ${TBB_INCLUDE_DIRS}) - target_compile_definitions(example PUBLIC ${TBB_DEFINITIONS} -DUSE_TBB) - if(MSVC) - # Suppress implicit linking of the TBB libraries by the Visual Studio compiler. - target_compile_definitions(example PUBLIC -D__TBB_NO_IMPLICIT_LINKAGE) - endif() - # The Intel TBB library will use the std::exception_ptr feature of C++11. - target_compile_definitions(example PUBLIC -DTBB_USE_CAPTURED_EXCEPTION=1) + add_executable(example examples/main.cpp + # tools/libnfpglue.hpp + # tools/libnfpglue.cpp + tools/nfp_svgnest.hpp + tools/nfp_svgnest_glue.hpp + tools/svgtools.hpp + tests/printer_parts.cpp + tests/printer_parts.h + ) - target_link_libraries(example ${TBB_LIBRARIES}) - else() - find_package(OpenMP QUIET) - if(OpenMP_CXX_FOUND) - message(STATUS "Parallelization with OpenMP") - target_include_directories(example PUBLIC OpenMP::OpenMP_CXX) - target_link_libraries(example OpenMP::OpenMP_CXX) - endif() - endif() - - target_link_libraries(example ${LIBNEST2D_LIBRARIES}) - target_include_directories(example PUBLIC ${LIBNEST2D_HEADERS}) + if(NOT LIBNEST2D_HEADER_ONLY) + target_link_libraries(example ${LIBNAME}) + else() + target_link_libraries(example libnest2d) + endif() endif() -get_directory_property(hasParent PARENT_DIRECTORY) -if(hasParent) - set(LIBNEST2D_INCLUDES ${LIBNEST2D_HEADERS} PARENT_SCOPE) - set(LIBNEST2D_LIBRARIES ${LIBNEST2D_LIBRARIES} PARENT_SCOPE) +if(LIBNEST2D_UNITTESTS) + add_subdirectory(${PROJECT_SOURCE_DIR}/tests) endif() diff --git a/src/libnest2d/README.md b/src/libnest2d/README.md deleted file mode 100644 index 61a7ac7d05..0000000000 --- a/src/libnest2d/README.md +++ /dev/null @@ -1,43 +0,0 @@ -# Introduction - -Libnest2D is a library and framework for the 2D bin packaging problem. -Inspired from the [SVGNest](svgnest.com) Javascript library the project is -built from scratch in C++11. The library is written with a policy that it should -be usable out of the box with a very simple interface but has to be customizable -to the very core as well. The algorithms are defined in a header only fashion -with templated geometry types. These geometries can have custom or already -existing implementation to avoid copying or having unnecessary dependencies. - -A default backend is provided if the user of the library just wants to use it -out of the box without additional integration. This backend is reasonably -fast and robust, being built on top of boost geometry and the -[polyclipping](http://www.angusj.com/delphi/clipper.php) library. Usage of -this default backend implies the dependency on these packages but its header -only as well. - -This software is currently under construction and lacks a throughout -documentation and some essential algorithms as well. At this stage it works well -for rectangles and convex closed polygons without considering holes and -concavities. - -Holes and non-convex polygons will be usable in the near future as well. The -no fit polygon based placer module combined with the first fit selection -strategy is now used in the [Slic3r](https://github.com/prusa3d/Slic3r) -application's arrangement feature. It uses local optimization techniques to find -the best placement of each new item based on some features of the arrangement. - -In the near future I would like to use machine learning to evaluate the -placements and (or) the order if items in which they are placed and see what -results can be obtained. This is a different approach than that of SVGnest which -uses genetic algorithms to find better and better selection orders. Maybe the -two approaches can be combined as well. - -# References -- [SVGNest](https://github.com/Jack000/SVGnest) -- [An effective heuristic for the two-dimensional irregular -bin packing problem](http://www.cs.stir.ac.uk/~goc/papers/EffectiveHueristic2DAOR2013.pdf) -- [Complete and robust no-fit polygon generation for the irregular stock cutting problem](https://www.sciencedirect.com/science/article/abs/pii/S0377221706001639) -- [Applying Meta-Heuristic Algorithms to the Nesting -Problem Utilising the No Fit Polygon](http://www.graham-kendall.com/papers/k2001.pdf) -- [A comprehensive and robust procedure for obtaining the nofit polygon -using Minkowski sums](https://www.sciencedirect.com/science/article/pii/S0305054806000669) \ No newline at end of file diff --git a/src/libnest2d/cmake_modules/DownloadNLopt.cmake b/src/libnest2d/cmake_modules/DownloadNLopt.cmake index 65b1866dbe..62b2b4c1a9 100644 --- a/src/libnest2d/cmake_modules/DownloadNLopt.cmake +++ b/src/libnest2d/cmake_modules/DownloadNLopt.cmake @@ -6,11 +6,14 @@ else() set(UPDATE_DISCONNECTED_IF_AVAILABLE "UPDATE_DISCONNECTED 1") endif() +set(URL_NLOPT "https://github.com/stevengj/nlopt.git" + CACHE STRING "Location of the nlopt git repository") + # set(NLopt_DIR ${CMAKE_BINARY_DIR}/nlopt) include(DownloadProject) download_project( PROJ nlopt - GIT_REPOSITORY https://github.com/stevengj/nlopt.git - GIT_TAG v2.5.0 #1fcbcbf2fe8e34234e016cc43a6c41d3e8453e1f #master #nlopt-2.4.2 + GIT_REPOSITORY ${URL_NLOPT} + GIT_TAG v2.5.0 # CMAKE_CACHE_ARGS -DBUILD_SHARED_LIBS:BOOL=OFF -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX=${NLopt_DIR} ${UPDATE_DISCONNECTED_IF_AVAILABLE} ) diff --git a/src/libnest2d/cmake_modules/FindClipper.cmake b/src/libnest2d/cmake_modules/FindClipper.cmake index f6b9734409..01b6b99d59 100644 --- a/src/libnest2d/cmake_modules/FindClipper.cmake +++ b/src/libnest2d/cmake_modules/FindClipper.cmake @@ -47,4 +47,12 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(Clipper MARK_AS_ADVANCED( CLIPPER_INCLUDE_DIRS - CLIPPER_LIBRARIES) \ No newline at end of file + CLIPPER_LIBRARIES) + +if(CLIPPER_FOUND) + add_library(Clipper::Clipper INTERFACE IMPORTED) + set_target_properties(Clipper::Clipper PROPERTIES INTERFACE_LINK_LIBRARIES ${CLIPPER_LIBRARIES}) + set_target_properties(Clipper::Clipper PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${CLIPPER_INCLUDE_DIRS}) + #target_link_libraries(Clipper::Clipper INTERFACE ${CLIPPER_LIBRARIES}) + #target_include_directories(Clipper::Clipper INTERFACE ${CLIPPER_INCLUDE_DIRS}) +endif() diff --git a/src/libnest2d/cmake_modules/FindNLopt.cmake b/src/libnest2d/cmake_modules/FindNLopt.cmake index 4b93be7b66..2f813b6aab 100644 --- a/src/libnest2d/cmake_modules/FindNLopt.cmake +++ b/src/libnest2d/cmake_modules/FindNLopt.cmake @@ -114,6 +114,13 @@ if(NLopt_FOUND) message(STATUS "Found NLopt in '${NLopt_DIR}'.") message(STATUS "Using NLopt include directory '${NLopt_INCLUDE_DIR}'.") message(STATUS "Using NLopt library '${NLopt_LIBS}'.") + add_library(Nlopt::Nlopt INTERFACE IMPORTED) + set_target_properties(Nlopt::Nlopt PROPERTIES INTERFACE_LINK_LIBRARIES ${NLopt_LIBS}) + set_target_properties(Nlopt::Nlopt PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${NLopt_INCLUDE_DIR}) + set_target_properties(Nlopt::Nlopt PROPERTIES INTERFACE_COMPILE_DEFINITIONS "${NLopt_DEFINITIONS}") + # target_link_libraries(Nlopt::Nlopt INTERFACE ${NLopt_LIBS}) + # target_include_directories(Nlopt::Nlopt INTERFACE ${NLopt_INCLUDE_DIR}) + # target_compile_definitions(Nlopt::Nlopt INTERFACE ${NLopt_DEFINITIONS}) else() if(NLopt_FIND_REQUIRED) message(FATAL_ERROR "Unable to find requested NLopt installation:${NLopt_ERROR_REASON}") @@ -122,4 +129,4 @@ else() message(STATUS "NLopt was not found:${NLopt_ERROR_REASON}") endif() endif() -endif() \ No newline at end of file +endif() diff --git a/src/libnest2d/cmake_modules/FindTBB.cmake b/src/libnest2d/cmake_modules/FindTBB.cmake deleted file mode 100644 index 8b498d3ab1..0000000000 --- a/src/libnest2d/cmake_modules/FindTBB.cmake +++ /dev/null @@ -1,322 +0,0 @@ -# The MIT License (MIT) -# -# Copyright (c) 2015 Justus Calvin -# -# 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. - -# -# FindTBB -# ------- -# -# Find TBB include directories and libraries. -# -# Usage: -# -# find_package(TBB [major[.minor]] [EXACT] -# [QUIET] [REQUIRED] -# [[COMPONENTS] [components...]] -# [OPTIONAL_COMPONENTS components...]) -# -# where the allowed components are tbbmalloc and tbb_preview. Users may modify -# the behavior of this module with the following variables: -# -# * TBB_ROOT_DIR - The base directory the of TBB installation. -# * TBB_INCLUDE_DIR - The directory that contains the TBB headers files. -# * TBB_LIBRARY - The directory that contains the TBB library files. -# * TBB__LIBRARY - The path of the TBB the corresponding TBB library. -# These libraries, if specified, override the -# corresponding library search results, where -# may be tbb, tbb_debug, tbbmalloc, tbbmalloc_debug, -# tbb_preview, or tbb_preview_debug. -# * TBB_USE_DEBUG_BUILD - The debug version of tbb libraries, if present, will -# be used instead of the release version. -# * TBB_STATIC - Static linking of libraries with a _static suffix. -# For example, on Windows a tbb_static.lib will be searched for -# instead of tbb.lib. -# -# Users may modify the behavior of this module with the following environment -# variables: -# -# * TBB_INSTALL_DIR -# * TBBROOT -# * LIBRARY_PATH -# -# This module will set the following variables: -# -# * TBB_FOUND - Set to false, or undefined, if we haven’t found, or -# don’t want to use TBB. -# * TBB__FOUND - If False, optional part of TBB sytem is -# not available. -# * TBB_VERSION - The full version string -# * TBB_VERSION_MAJOR - The major version -# * TBB_VERSION_MINOR - The minor version -# * TBB_INTERFACE_VERSION - The interface version number defined in -# tbb/tbb_stddef.h. -# * TBB__LIBRARY_RELEASE - The path of the TBB release version of -# , where may be tbb, tbb_debug, -# tbbmalloc, tbbmalloc_debug, tbb_preview, or -# tbb_preview_debug. -# * TBB__LIBRARY_DEGUG - The path of the TBB release version of -# , where may be tbb, tbb_debug, -# tbbmalloc, tbbmalloc_debug, tbb_preview, or -# tbb_preview_debug. -# -# The following varibles should be used to build and link with TBB: -# -# * TBB_INCLUDE_DIRS - The include directory for TBB. -# * TBB_LIBRARIES - The libraries to link against to use TBB. -# * TBB_LIBRARIES_RELEASE - The release libraries to link against to use TBB. -# * TBB_LIBRARIES_DEBUG - The debug libraries to link against to use TBB. -# * TBB_DEFINITIONS - Definitions to use when compiling code that uses -# TBB. -# * TBB_DEFINITIONS_RELEASE - Definitions to use when compiling release code that -# uses TBB. -# * TBB_DEFINITIONS_DEBUG - Definitions to use when compiling debug code that -# uses TBB. -# -# This module will also create the "tbb" target that may be used when building -# executables and libraries. - -include(FindPackageHandleStandardArgs) - -if(NOT TBB_FOUND) - - ################################## - # Check the build type - ################################## - - if(NOT DEFINED TBB_USE_DEBUG_BUILD) - if(CMAKE_BUILD_TYPE MATCHES "(Debug|DEBUG|debug)") - set(TBB_BUILD_TYPE DEBUG) - else() - set(TBB_BUILD_TYPE RELEASE) - endif() - elseif(TBB_USE_DEBUG_BUILD) - set(TBB_BUILD_TYPE DEBUG) - else() - set(TBB_BUILD_TYPE RELEASE) - endif() - - ################################## - # Set the TBB search directories - ################################## - - # Define search paths based on user input and environment variables - set(TBB_SEARCH_DIR ${TBB_ROOT_DIR} $ENV{TBB_INSTALL_DIR} $ENV{TBBROOT}) - - # Define the search directories based on the current platform - if(CMAKE_SYSTEM_NAME STREQUAL "Windows") - set(TBB_DEFAULT_SEARCH_DIR "C:/Program Files/Intel/TBB" - "C:/Program Files (x86)/Intel/TBB") - - # Set the target architecture - if(CMAKE_SIZEOF_VOID_P EQUAL 8) - set(TBB_ARCHITECTURE "intel64") - else() - set(TBB_ARCHITECTURE "ia32") - endif() - - # Set the TBB search library path search suffix based on the version of VC - if(WINDOWS_STORE) - set(TBB_LIB_PATH_SUFFIX "lib/${TBB_ARCHITECTURE}/vc11_ui") - elseif(MSVC14) - set(TBB_LIB_PATH_SUFFIX "lib/${TBB_ARCHITECTURE}/vc14") - elseif(MSVC12) - set(TBB_LIB_PATH_SUFFIX "lib/${TBB_ARCHITECTURE}/vc12") - elseif(MSVC11) - set(TBB_LIB_PATH_SUFFIX "lib/${TBB_ARCHITECTURE}/vc11") - elseif(MSVC10) - set(TBB_LIB_PATH_SUFFIX "lib/${TBB_ARCHITECTURE}/vc10") - endif() - - # Add the library path search suffix for the VC independent version of TBB - list(APPEND TBB_LIB_PATH_SUFFIX "lib/${TBB_ARCHITECTURE}/vc_mt") - - elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin") - # OS X - set(TBB_DEFAULT_SEARCH_DIR "/opt/intel/tbb") - - # TODO: Check to see which C++ library is being used by the compiler. - if(NOT ${CMAKE_SYSTEM_VERSION} VERSION_LESS 13.0) - # The default C++ library on OS X 10.9 and later is libc++ - set(TBB_LIB_PATH_SUFFIX "lib/libc++" "lib") - else() - set(TBB_LIB_PATH_SUFFIX "lib") - endif() - elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux") - # Linux - set(TBB_DEFAULT_SEARCH_DIR "/opt/intel/tbb") - - # TODO: Check compiler version to see the suffix should be /gcc4.1 or - # /gcc4.1. For now, assume that the compiler is more recent than - # gcc 4.4.x or later. - if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64") - set(TBB_LIB_PATH_SUFFIX "lib/intel64/gcc4.4") - elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^i.86$") - set(TBB_LIB_PATH_SUFFIX "lib/ia32/gcc4.4") - endif() - endif() - - ################################## - # Find the TBB include dir - ################################## - - find_path(TBB_INCLUDE_DIRS tbb/tbb.h - HINTS ${TBB_INCLUDE_DIR} ${TBB_SEARCH_DIR} - PATHS ${TBB_DEFAULT_SEARCH_DIR} - PATH_SUFFIXES include) - - ################################## - # Set version strings - ################################## - - if(TBB_INCLUDE_DIRS) - file(READ "${TBB_INCLUDE_DIRS}/tbb/tbb_stddef.h" _tbb_version_file) - string(REGEX REPLACE ".*#define TBB_VERSION_MAJOR ([0-9]+).*" "\\1" - TBB_VERSION_MAJOR "${_tbb_version_file}") - string(REGEX REPLACE ".*#define TBB_VERSION_MINOR ([0-9]+).*" "\\1" - TBB_VERSION_MINOR "${_tbb_version_file}") - string(REGEX REPLACE ".*#define TBB_INTERFACE_VERSION ([0-9]+).*" "\\1" - TBB_INTERFACE_VERSION "${_tbb_version_file}") - set(TBB_VERSION "${TBB_VERSION_MAJOR}.${TBB_VERSION_MINOR}") - endif() - - ################################## - # Find TBB components - ################################## - - if(TBB_VERSION VERSION_LESS 4.3) - set(TBB_SEARCH_COMPOMPONENTS tbb_preview tbbmalloc tbb) - else() - set(TBB_SEARCH_COMPOMPONENTS tbb_preview tbbmalloc_proxy tbbmalloc tbb) - endif() - - if(TBB_STATIC) - set(TBB_STATIC_SUFFIX "_static") - endif() - - # Find each component - foreach(_comp ${TBB_SEARCH_COMPOMPONENTS}) - if(";${TBB_FIND_COMPONENTS};tbb;" MATCHES ";${_comp};") - - # Search for the libraries - find_library(TBB_${_comp}_LIBRARY_RELEASE ${_comp}${TBB_STATIC_SUFFIX} - HINTS ${TBB_LIBRARY} ${TBB_SEARCH_DIR} - PATHS ${TBB_DEFAULT_SEARCH_DIR} ENV LIBRARY_PATH - PATH_SUFFIXES ${TBB_LIB_PATH_SUFFIX}) - - find_library(TBB_${_comp}_LIBRARY_DEBUG ${_comp}${TBB_STATIC_SUFFIX}_debug - HINTS ${TBB_LIBRARY} ${TBB_SEARCH_DIR} - PATHS ${TBB_DEFAULT_SEARCH_DIR} ENV LIBRARY_PATH - PATH_SUFFIXES ${TBB_LIB_PATH_SUFFIX}) - - if(TBB_${_comp}_LIBRARY_DEBUG) - list(APPEND TBB_LIBRARIES_DEBUG "${TBB_${_comp}_LIBRARY_DEBUG}") - endif() - if(TBB_${_comp}_LIBRARY_RELEASE) - list(APPEND TBB_LIBRARIES_RELEASE "${TBB_${_comp}_LIBRARY_RELEASE}") - endif() - if(TBB_${_comp}_LIBRARY_${TBB_BUILD_TYPE} AND NOT TBB_${_comp}_LIBRARY) - set(TBB_${_comp}_LIBRARY "${TBB_${_comp}_LIBRARY_${TBB_BUILD_TYPE}}") - endif() - - if(TBB_${_comp}_LIBRARY AND EXISTS "${TBB_${_comp}_LIBRARY}") - set(TBB_${_comp}_FOUND TRUE) - else() - set(TBB_${_comp}_FOUND FALSE) - endif() - - # Mark internal variables as advanced - mark_as_advanced(TBB_${_comp}_LIBRARY_RELEASE) - mark_as_advanced(TBB_${_comp}_LIBRARY_DEBUG) - mark_as_advanced(TBB_${_comp}_LIBRARY) - - endif() - endforeach() - - unset(TBB_STATIC_SUFFIX) - - ################################## - # Set compile flags and libraries - ################################## - - set(TBB_DEFINITIONS_RELEASE "") - set(TBB_DEFINITIONS_DEBUG "-DTBB_USE_DEBUG=1") - - if(TBB_LIBRARIES_${TBB_BUILD_TYPE}) - set(TBB_DEFINITIONS "${TBB_DEFINITIONS_${TBB_BUILD_TYPE}}") - set(TBB_LIBRARIES "${TBB_LIBRARIES_${TBB_BUILD_TYPE}}") - elseif(TBB_LIBRARIES_RELEASE) - set(TBB_DEFINITIONS "${TBB_DEFINITIONS_RELEASE}") - set(TBB_LIBRARIES "${TBB_LIBRARIES_RELEASE}") - elseif(TBB_LIBRARIES_DEBUG) - set(TBB_DEFINITIONS "${TBB_DEFINITIONS_DEBUG}") - set(TBB_LIBRARIES "${TBB_LIBRARIES_DEBUG}") - endif() - - find_package_handle_standard_args(TBB - REQUIRED_VARS TBB_INCLUDE_DIRS TBB_LIBRARIES - HANDLE_COMPONENTS - VERSION_VAR TBB_VERSION) - - ################################## - # Create targets - ################################## - - if(NOT CMAKE_VERSION VERSION_LESS 3.0 AND TBB_FOUND) - add_library(tbb SHARED IMPORTED) - set_target_properties(tbb PROPERTIES - INTERFACE_INCLUDE_DIRECTORIES ${TBB_INCLUDE_DIRS} - IMPORTED_LOCATION ${TBB_LIBRARIES}) - if(TBB_LIBRARIES_RELEASE AND TBB_LIBRARIES_DEBUG) - set_target_properties(tbb PROPERTIES - INTERFACE_COMPILE_DEFINITIONS "$<$,$>:TBB_USE_DEBUG=1>" - IMPORTED_LOCATION_DEBUG ${TBB_LIBRARIES_DEBUG} - IMPORTED_LOCATION_RELWITHDEBINFO ${TBB_LIBRARIES_DEBUG} - IMPORTED_LOCATION_RELEASE ${TBB_LIBRARIES_RELEASE} - IMPORTED_LOCATION_MINSIZEREL ${TBB_LIBRARIES_RELEASE} - ) - elseif(TBB_LIBRARIES_RELEASE) - set_target_properties(tbb PROPERTIES IMPORTED_LOCATION ${TBB_LIBRARIES_RELEASE}) - else() - set_target_properties(tbb PROPERTIES - INTERFACE_COMPILE_DEFINITIONS "${TBB_DEFINITIONS_DEBUG}" - IMPORTED_LOCATION ${TBB_LIBRARIES_DEBUG} - ) - endif() - endif() - - mark_as_advanced(TBB_INCLUDE_DIRS TBB_LIBRARIES) - - unset(TBB_ARCHITECTURE) - unset(TBB_BUILD_TYPE) - unset(TBB_LIB_PATH_SUFFIX) - unset(TBB_DEFAULT_SEARCH_DIR) - - if(TBB_DEBUG) - message(STATUS " TBB_INCLUDE_DIRS = ${TBB_INCLUDE_DIRS}") - message(STATUS " TBB_DEFINITIONS = ${TBB_DEFINITIONS}") - message(STATUS " TBB_LIBRARIES = ${TBB_LIBRARIES}") - message(STATUS " TBB_DEFINITIONS_DEBUG = ${TBB_DEFINITIONS_DEBUG}") - message(STATUS " TBB_LIBRARIES_DEBUG = ${TBB_LIBRARIES_DEBUG}") - message(STATUS " TBB_DEFINITIONS_RELEASE = ${TBB_DEFINITIONS_RELEASE}") - message(STATUS " TBB_LIBRARIES_RELEASE = ${TBB_LIBRARIES_RELEASE}") - endif() - -endif() diff --git a/src/libnest2d/examples/main.cpp b/src/libnest2d/examples/main.cpp deleted file mode 100644 index ebc3fb15c5..0000000000 --- a/src/libnest2d/examples/main.cpp +++ /dev/null @@ -1,218 +0,0 @@ -#include -#include -#include -//#define DEBUG_EXPORT_NFP - -#include - -#include "tests/printer_parts.h" -#include "tools/benchmark.h" -#include "tools/svgtools.hpp" -#include "libnest2d/rotfinder.hpp" - -//#include "tools/libnfpglue.hpp" -//#include "tools/nfp_svgnest_glue.hpp" - - -using namespace libnest2d; -using ItemGroup = std::vector>; - -std::vector& _parts(std::vector& ret, const TestData& data) -{ - if(ret.empty()) { - ret.reserve(data.size()); - for(auto& inp : data) - ret.emplace_back(inp); - } - - return ret; -} - -std::vector& prusaParts() { - static std::vector ret; - return _parts(ret, PRINTER_PART_POLYGONS); -} - -std::vector& stegoParts() { - static std::vector ret; - return _parts(ret, STEGOSAUR_POLYGONS); -} - -std::vector& prusaExParts() { - static std::vector ret; - if(ret.empty()) { - ret.reserve(PRINTER_PART_POLYGONS_EX.size()); - for(auto& p : PRINTER_PART_POLYGONS_EX) { - ret.emplace_back(p.Contour, p.Holes); - } - } - return ret; -} - -void arrangeRectangles() { - using namespace libnest2d; - - const int SCALE = 1000000; - - std::vector rects(202, { - {-9945219, -3065619}, - {-9781479, -2031780}, - {-9510560, -1020730}, - {-9135450, -43529}, - {-2099999, 14110899}, - {2099999, 14110899}, - {9135450, -43529}, - {9510560, -1020730}, - {9781479, -2031780}, - {9945219, -3065619}, - {10000000, -4110899}, - {9945219, -5156179}, - {9781479, -6190019}, - {9510560, -7201069}, - {9135450, -8178270}, - {8660249, -9110899}, - {8090169, -9988750}, - {7431449, -10802209}, - {6691309, -11542349}, - {5877850, -12201069}, - {5000000, -12771149}, - {4067369, -13246350}, - {3090169, -13621459}, - {2079119, -13892379}, - {1045279, -14056119}, - {0, -14110899}, - {-1045279, -14056119}, - {-2079119, -13892379}, - {-3090169, -13621459}, - {-4067369, -13246350}, - {-5000000, -12771149}, - {-5877850, -12201069}, - {-6691309, -11542349}, - {-7431449, -10802209}, - {-8090169, -9988750}, - {-8660249, -9110899}, - {-9135450, -8178270}, - {-9510560, -7201069}, - {-9781479, -6190019}, - {-9945219, -5156179}, - {-10000000, -4110899}, - {-9945219, -3065619}, - }); - - std::vector input; - input.insert(input.end(), prusaParts().begin(), prusaParts().end()); -// input.insert(input.end(), prusaExParts().begin(), prusaExParts().end()); -// input.insert(input.end(), stegoParts().begin(), stegoParts().end()); -// input.insert(input.end(), rects.begin(), rects.end()); - - Box bin(250*SCALE, 210*SCALE); -// PolygonImpl bin = { -// { -// {25*SCALE, 0}, -// {0, 25*SCALE}, -// {0, 225*SCALE}, -// {25*SCALE, 250*SCALE}, -// {225*SCALE, 250*SCALE}, -// {250*SCALE, 225*SCALE}, -// {250*SCALE, 25*SCALE}, -// {225*SCALE, 0}, -// {25*SCALE, 0} -// }, -// {} -// }; - -// Circle bin({0, 0}, 125*SCALE); - - auto min_obj_distance = static_cast(6*SCALE); - - using Placer = placers::_NofitPolyPlacer; - using Packer = Nester; - - Packer arrange(bin, min_obj_distance); - - Packer::PlacementConfig pconf; - pconf.alignment = Placer::Config::Alignment::CENTER; - pconf.starting_point = Placer::Config::Alignment::CENTER; - pconf.rotations = {0.0/*, Pi/2.0, Pi, 3*Pi/2*/}; - pconf.accuracy = 0.65f; - pconf.parallel = true; - - Packer::SelectionConfig sconf; -// sconf.allow_parallel = false; -// sconf.force_parallel = false; -// sconf.try_triplets = true; -// sconf.try_reverse_order = true; -// sconf.waste_increment = 0.01; - - arrange.configure(pconf, sconf); - - arrange.progressIndicator([&](unsigned r){ - std::cout << "Remaining items: " << r << std::endl; - }); - -// findMinimumBoundingBoxRotations(input.begin(), input.end()); - - Benchmark bench; - - bench.start(); - Packer::ResultType result; - - try { - result = arrange.execute(input.begin(), input.end()); - } catch(GeometryException& ge) { - std::cerr << "Geometry error: " << ge.what() << std::endl; - return ; - } catch(std::exception& e) { - std::cerr << "Exception: " << e.what() << std::endl; - return ; - } - - bench.stop(); - - std::vector eff; - eff.reserve(result.size()); - - auto bin_area = sl::area(bin); - for(auto& r : result) { - double a = 0; - std::for_each(r.begin(), r.end(), [&a] (Item& e ){ a += e.area(); }); - eff.emplace_back(a/bin_area); - }; - - std::cout << bench.getElapsedSec() << " bin count: " << result.size() - << std::endl; - - std::cout << "Bin efficiency: ("; - for(double e : eff) std::cout << e*100.0 << "% "; - std::cout << ") Average: " - << std::accumulate(eff.begin(), eff.end(), 0.0)*100.0/result.size() - << " %" << std::endl; - - std::cout << "Bin usage: ("; - size_t total = 0; - for(auto& r : result) { std::cout << r.size() << " "; total += r.size(); } - std::cout << ") Total: " << total << std::endl; - -// for(auto& it : input) { -// auto ret = sl::isValid(it.transformedShape()); -// std::cout << ret.second << std::endl; -// } - - if(total != input.size()) std::cout << "ERROR " << "could not pack " - << input.size() - total << " elements!" - << std::endl; - - using SVGWriter = svg::SVGWriter; - - SVGWriter::Config conf; - conf.mm_in_coord_units = SCALE; - SVGWriter svgw(conf); - svgw.setSize(Box(250*SCALE, 210*SCALE)); - svgw.writePackGroup(result); - svgw.save("out"); -} - -int main(void /*int argc, char **argv*/) { - arrangeRectangles(); - return EXIT_SUCCESS; -} diff --git a/src/libnest2d/include/libnest2d.h b/src/libnest2d/include/libnest2d.h new file mode 100644 index 0000000000..4ad7524219 --- /dev/null +++ b/src/libnest2d/include/libnest2d.h @@ -0,0 +1,175 @@ +#ifndef LIBNEST2D_H +#define LIBNEST2D_H + +// The type of backend should be set conditionally by the cmake configuriation +// for now we set it statically to clipper backend +#ifdef LIBNEST2D_BACKEND_CLIPPER +#include +#endif + +#ifdef LIBNEST2D_OPTIMIZER_NLOPT +// We include the stock optimizers for local and global optimization +#include // Local subplex for NfpPlacer +#include // Genetic for min. bounding box +#endif + +#include +#include +#include +#include +#include +#include + +namespace libnest2d { + +using Point = PointImpl; +using Coord = TCoord; +using Box = _Box; +using Segment = _Segment; +using Circle = _Circle; + +using Item = _Item; +using Rectangle = _Rectangle; + +using PackGroup = _PackGroup; +using IndexedPackGroup = _IndexedPackGroup; + +using FillerSelection = selections::_FillerSelection; +using FirstFitSelection = selections::_FirstFitSelection; +using DJDHeuristic = selections::_DJDHeuristic; + +template // Generic placer for arbitrary bin types +using _NfpPlacer = placers::_NofitPolyPlacer; + +// NfpPlacer is with Box bin +using NfpPlacer = _NfpPlacer; + +// This supports only box shaped bins +using BottomLeftPlacer = placers::_BottomLeftPlacer; + +template::iterator> +PackGroup nest(Iterator from, Iterator to, + const typename Placer::BinType& bin, + Coord dist = 0, + const typename Placer::Config& pconf = {}, + const typename Selector::Config& sconf = {}) +{ + Nester nester(bin, dist, pconf, sconf); + return nester.execute(from, to); +} + +template> +PackGroup nest(Container&& cont, + const typename Placer::BinType& bin, + Coord dist = 0, + const typename Placer::Config& pconf = {}, + const typename Selector::Config& sconf = {}) +{ + return nest(cont.begin(), cont.end(), + bin, dist, pconf, sconf); +} + +template::iterator> +PackGroup nest(Iterator from, Iterator to, + const typename Placer::BinType& bin, + ProgressFunction prg, + StopCondition scond = []() { return false; }, + Coord dist = 0, + const typename Placer::Config& pconf = {}, + const typename Selector::Config& sconf = {}) +{ + Nester nester(bin, dist, pconf, sconf); + if(prg) nester.progressIndicator(prg); + if(scond) nester.stopCondition(scond); + return nester.execute(from, to); +} + +template> +PackGroup nest(Container&& cont, + const typename Placer::BinType& bin, + ProgressFunction prg, + StopCondition scond = []() { return false; }, + Coord dist = 0, + const typename Placer::Config& pconf = {}, + const typename Selector::Config& sconf = {}) +{ + return nest(cont.begin(), cont.end(), + bin, prg, scond, dist, pconf, sconf); +} + +#ifdef LIBNEST2D_STATIC +extern template +PackGroup nest&>( + std::vector& cont, + const Box& bin, + Coord dist, + const NfpPlacer::Config& pcfg, + const FirstFitSelection::Config& scfg +); + +extern template +PackGroup nest&>( + std::vector& cont, + const Box& bin, + ProgressFunction prg, + StopCondition scond, + Coord dist, + const NfpPlacer::Config& pcfg, + const FirstFitSelection::Config& scfg +); + +extern template +PackGroup nest>( + std::vector&& cont, + const Box& bin, + Coord dist, + const NfpPlacer::Config& pcfg, + const FirstFitSelection::Config& scfg +); + +extern template +PackGroup nest>( + std::vector&& cont, + const Box& bin, + ProgressFunction prg, + StopCondition scond, + Coord dist, + const NfpPlacer::Config& pcfg, + const FirstFitSelection::Config& scfg +); + +extern template +PackGroup nest::iterator>( + std::vector::iterator from, + std::vector::iterator to, + const Box& bin, + Coord dist, + const NfpPlacer::Config& pcfg, + const FirstFitSelection::Config& scfg +); + +extern template +PackGroup nest::iterator>( + std::vector::iterator from, + std::vector::iterator to, + const Box& bin, + ProgressFunction prg, + StopCondition scond, + Coord dist, + const NfpPlacer::Config& pcfg, + const FirstFitSelection::Config& scfg +); + +#endif + +} + +#endif // LIBNEST2D_H diff --git a/src/libnest2d/libnest2d/clipper_backend/CMakeLists.txt b/src/libnest2d/include/libnest2d/backends/clipper/CMakeLists.txt similarity index 55% rename from src/libnest2d/libnest2d/clipper_backend/CMakeLists.txt rename to src/libnest2d/include/libnest2d/backends/clipper/CMakeLists.txt index b6f2de4397..995afcc76d 100644 --- a/src/libnest2d/libnest2d/clipper_backend/CMakeLists.txt +++ b/src/libnest2d/include/libnest2d/backends/clipper/CMakeLists.txt @@ -5,6 +5,10 @@ if(NOT TARGET clipper) # If there is a clipper target in the parent project we a if(NOT CLIPPER_FOUND) find_package(Subversion QUIET) if(Subversion_FOUND) + + set(URL_CLIPPER "https://svn.code.sf.net/p/polyclipping/code/trunk/cpp" + CACHE STRING "Clipper source code repository location.") + message(STATUS "Clipper not found so it will be downloaded.") # Silently download and build the library in the build dir @@ -16,7 +20,7 @@ if(NOT TARGET clipper) # If there is a clipper target in the parent project we a include(DownloadProject) download_project( PROJ clipper_library - SVN_REPOSITORY https://svn.code.sf.net/p/polyclipping/code/trunk/cpp + SVN_REPOSITORY ${URL_CLIPPER} SVN_REVISION -r540 #SOURCE_SUBDIR cpp INSTALL_COMMAND "" @@ -29,20 +33,41 @@ if(NOT TARGET clipper) # If there is a clipper target in the parent project we a # ${clipper_library_BINARY_DIR} # ) - add_library(clipper_lib STATIC + add_library(ClipperBackend STATIC ${clipper_library_SOURCE_DIR}/clipper.cpp ${clipper_library_SOURCE_DIR}/clipper.hpp) - set(CLIPPER_INCLUDE_DIRS ${clipper_library_SOURCE_DIR} - PARENT_SCOPE) - - set(CLIPPER_LIBRARIES clipper_lib PARENT_SCOPE) - + target_include_directories(ClipperBackend INTERFACE + ${clipper_library_SOURCE_DIR}) else() message(FATAL_ERROR "Can't find clipper library and no SVN client found to download. You can download the clipper sources and define a clipper target in your project, that will work for libnest2d.") endif() + else() + add_library(ClipperBackend INTERFACE) + target_link_libraries(ClipperBackend INTERFACE Clipper::Clipper) endif() else() - set(CLIPPER_LIBRARIES clipper PARENT_SCOPE) + # set(CLIPPER_INCLUDE_DIRS "" PARENT_SCOPE) + # set(CLIPPER_LIBRARIES clipper PARENT_SCOPE) + add_library(ClipperBackend INTERFACE) + target_link_libraries(ClipperBackend INTERFACE clipper) endif() + +# Clipper backend is not enough on its own, it still needs some functions +# from Boost geometry +if(NOT Boost_INCLUDE_DIRS_FOUND) + find_package(Boost 1.58 REQUIRED) + # TODO automatic download of boost geometry headers +endif() + +target_include_directories(ClipperBackend INTERFACE ${Boost_INCLUDE_DIRS} ) +target_sources(ClipperBackend INTERFACE + ${CMAKE_CURRENT_SOURCE_DIR}/geometries.hpp + ${SRC_DIR}/libnest2d/utils/boost_alg.hpp ) + +target_compile_definitions(ClipperBackend INTERFACE LIBNEST2D_BACKEND_CLIPPER) + +# And finally plug the ClipperBackend into libnest2d +target_link_libraries(libnest2d INTERFACE ClipperBackend) + diff --git a/src/libnest2d/libnest2d/clipper_backend/clipper_backend.hpp b/src/libnest2d/include/libnest2d/backends/clipper/geometries.hpp similarity index 95% rename from src/libnest2d/libnest2d/clipper_backend/clipper_backend.hpp rename to src/libnest2d/include/libnest2d/backends/clipper/geometries.hpp index 745fd2108d..c05d08d0dd 100644 --- a/src/libnest2d/libnest2d/clipper_backend/clipper_backend.hpp +++ b/src/libnest2d/include/libnest2d/backends/clipper/geometries.hpp @@ -7,8 +7,8 @@ #include #include -#include "../geometry_traits.hpp" -#include "../geometry_traits_nfp.hpp" +#include +#include #include @@ -99,6 +99,10 @@ template<> struct PointType { using Type = PointImpl; }; +template<> struct PointType { + using Type = PointImpl; +}; + template<> struct PointType { using Type = PointImpl; }; @@ -108,6 +112,7 @@ template<> struct CountourType { }; template<> struct ShapeTag { using Type = PolygonTag; }; +template<> struct ShapeTag { using Type = PathTag; }; template<> struct ShapeTag> { using Type = MultiPolygonTag; @@ -185,11 +190,6 @@ inline double area(const PolygonImpl& sh) { namespace shapelike { -template<> inline void reserve(PolygonImpl& sh, size_t vertex_capacity) -{ - return sh.Contour.reserve(vertex_capacity); -} - // Tell libnest2d how to make string out of a ClipperPolygon object template<> inline double area(const PolygonImpl& sh, const PolygonTag&) { @@ -327,13 +327,13 @@ template<> inline THolesContainer& holes(PolygonImpl& sh) } template<> -inline TContour& getHole(PolygonImpl& sh, unsigned long idx) +inline TContour& hole(PolygonImpl& sh, unsigned long idx) { return sh.Holes[idx]; } template<> -inline const TContour& getHole(const PolygonImpl& sh, +inline const TContour& hole(const PolygonImpl& sh, unsigned long idx) { return sh.Holes[idx]; @@ -344,13 +344,13 @@ template<> inline size_t holeCount(const PolygonImpl& sh) return sh.Holes.size(); } -template<> inline PathImpl& getContour(PolygonImpl& sh) +template<> inline PathImpl& contour(PolygonImpl& sh) { return sh.Contour; } template<> -inline const PathImpl& getContour(const PolygonImpl& sh) +inline const PathImpl& contour(const PolygonImpl& sh) { return sh.Contour; } @@ -455,6 +455,6 @@ merge(const std::vector& shapes) //#define DISABLE_BOOST_UNSERIALIZE // All other operators and algorithms are implemented with boost -#include "../boost_alg.hpp" +#include #endif // CLIPPER_BACKEND_HPP diff --git a/src/libnest2d/libnest2d/common.hpp b/src/libnest2d/include/libnest2d/common.hpp similarity index 100% rename from src/libnest2d/libnest2d/common.hpp rename to src/libnest2d/include/libnest2d/common.hpp diff --git a/src/libnest2d/include/libnest2d/geometry_traits.hpp b/src/libnest2d/include/libnest2d/geometry_traits.hpp new file mode 100644 index 0000000000..828044afe0 --- /dev/null +++ b/src/libnest2d/include/libnest2d/geometry_traits.hpp @@ -0,0 +1,965 @@ +#ifndef GEOMETRY_TRAITS_HPP +#define GEOMETRY_TRAITS_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.hpp" + +namespace libnest2d { + +/// Getting the coordinate data type for a geometry class. +template struct CoordType { using Type = long; }; + +/// TCoord as shorthand for typename `CoordType::Type`. +template +using TCoord = typename CoordType>::Type; + + +/// Getting the type of point structure used by a shape. +template struct PointType { using Type = typename Sh::PointType; }; + +/// TPoint as shorthand for `typename PointType::Type`. +template +using TPoint = typename PointType>::Type; + + +template struct CountourType { using Type = RawShape; }; + +template +using TContour = typename CountourType>::Type; + + +template +struct HolesContainer { using Type = std::vector>; }; + +template +using THolesContainer = typename HolesContainer>::Type; + + +template +struct LastPointIsFirst { static const bool Value = true; }; + +enum class Orientation { + CLOCKWISE, + COUNTER_CLOCKWISE +}; + +template +struct OrientationType { + + // Default Polygon orientation that the library expects + static const Orientation Value = Orientation::CLOCKWISE; +}; + +/** + * \brief A point pair base class for other point pairs (segment, box, ...). + * \tparam RawPoint The actual point type to use. + */ +template +struct PointPair { + RawPoint p1; + RawPoint p2; +}; + +struct PolygonTag {}; +struct PathTag {}; +struct MultiPolygonTag {}; +struct BoxTag {}; +struct CircleTag {}; + +template struct ShapeTag { using Type = typename Shape::Tag; }; +template using Tag = typename ShapeTag>::Type; + +template struct MultiShape { using Type = std::vector; }; +template +using TMultiShape =typename MultiShape>::Type; + +/** + * \brief An abstraction of a box; + */ +template +class _Box: PointPair { + using PointPair::p1; + using PointPair::p2; +public: + + using Tag = BoxTag; + using PointType = RawPoint; + + inline _Box() = default; + inline _Box(const RawPoint& p, const RawPoint& pp): + PointPair({p, pp}) {} + + inline _Box(TCoord width, TCoord height): + _Box(RawPoint{0, 0}, RawPoint{width, height}) {} + + inline const RawPoint& minCorner() const BP2D_NOEXCEPT { return p1; } + inline const RawPoint& maxCorner() const BP2D_NOEXCEPT { return p2; } + + inline RawPoint& minCorner() BP2D_NOEXCEPT { return p1; } + inline RawPoint& maxCorner() BP2D_NOEXCEPT { return p2; } + + inline TCoord width() const BP2D_NOEXCEPT; + inline TCoord height() const BP2D_NOEXCEPT; + + inline RawPoint center() const BP2D_NOEXCEPT; + + inline double area() const BP2D_NOEXCEPT { + return double(width()*height()); + } +}; + +template +class _Circle { + RawPoint center_; + double radius_ = 0; +public: + + using Tag = CircleTag; + using PointType = RawPoint; + + _Circle() = default; + + _Circle(const RawPoint& center, double r): center_(center), radius_(r) {} + + inline const RawPoint& center() const BP2D_NOEXCEPT { return center_; } + inline const void center(const RawPoint& c) { center_ = c; } + + inline double radius() const BP2D_NOEXCEPT { return radius_; } + inline void radius(double r) { radius_ = r; } + + inline double area() const BP2D_NOEXCEPT { + return 2.0*Pi*radius_*radius_; + } +}; + +/** + * \brief An abstraction of a directed line segment with two points. + */ +template +class _Segment: PointPair { + using PointPair::p1; + using PointPair::p2; + mutable Radians angletox_ = std::nan(""); +public: + + using PointType = RawPoint; + + inline _Segment() = default; + + inline _Segment(const RawPoint& p, const RawPoint& pp): + PointPair({p, pp}) {} + + /** + * @brief Get the first point. + * @return Returns the starting point. + */ + inline const RawPoint& first() const BP2D_NOEXCEPT { return p1; } + + /** + * @brief The end point. + * @return Returns the end point of the segment. + */ + inline const RawPoint& second() const BP2D_NOEXCEPT { return p2; } + + inline void first(const RawPoint& p) BP2D_NOEXCEPT + { + angletox_ = std::nan(""); p1 = p; + } + + inline void second(const RawPoint& p) BP2D_NOEXCEPT { + angletox_ = std::nan(""); p2 = p; + } + + /// Returns the angle measured to the X (horizontal) axis. + inline Radians angleToXaxis() const; + + /// The length of the segment in the measure of the coordinate system. + inline double length(); +}; + +// This struct serves almost as a namespace. The only difference is that is can +// used in friend declarations. +namespace pointlike { + +template +inline TCoord x(const RawPoint& p) +{ + return p.x(); +} + +template +inline TCoord y(const RawPoint& p) +{ + return p.y(); +} + +template +inline TCoord& x(RawPoint& p) +{ + return p.x(); +} + +template +inline TCoord& y(RawPoint& p) +{ + return p.y(); +} + +template +inline double distance(const RawPoint& /*p1*/, const RawPoint& /*p2*/) +{ + static_assert(always_false::value, + "PointLike::distance(point, point) unimplemented!"); + return 0; +} + +template +inline double distance(const RawPoint& /*p1*/, + const _Segment& /*s*/) +{ + static_assert(always_false::value, + "PointLike::distance(point, segment) unimplemented!"); + return 0; +} + +template +inline std::pair, bool> horizontalDistance( + const RawPoint& p, const _Segment& s) +{ + using Unit = TCoord; + auto x = pointlike::x(p), y = pointlike::y(p); + auto x1 = pointlike::x(s.first()), y1 = pointlike::y(s.first()); + auto x2 = pointlike::x(s.second()), y2 = pointlike::y(s.second()); + + TCoord ret; + + if( (y < y1 && y < y2) || (y > y1 && y > y2) ) + return {0, false}; + if ((y == y1 && y == y2) && (x > x1 && x > x2)) + ret = std::min( x-x1, x -x2); + else if( (y == y1 && y == y2) && (x < x1 && x < x2)) + ret = -std::min(x1 - x, x2 - x); + else if(std::abs(y - y1) <= std::numeric_limits::epsilon() && + std::abs(y - y2) <= std::numeric_limits::epsilon()) + ret = 0; + else + ret = x - x1 + (x1 - x2)*(y1 - y)/(y1 - y2); + + return {ret, true}; +} + +template +inline std::pair, bool> verticalDistance( + const RawPoint& p, const _Segment& s) +{ + using Unit = TCoord; + auto x = pointlike::x(p), y = pointlike::y(p); + auto x1 = pointlike::x(s.first()), y1 = pointlike::y(s.first()); + auto x2 = pointlike::x(s.second()), y2 = pointlike::y(s.second()); + + TCoord ret; + + if( (x < x1 && x < x2) || (x > x1 && x > x2) ) + return {0, false}; + if ((x == x1 && x == x2) && (y > y1 && y > y2)) + ret = std::min( y-y1, y -y2); + else if( (x == x1 && x == x2) && (y < y1 && y < y2)) + ret = -std::min(y1 - y, y2 - y); + else if(std::abs(x - x1) <= std::numeric_limits::epsilon() && + std::abs(x - x2) <= std::numeric_limits::epsilon()) + ret = 0; + else + ret = y - y1 + (y1 - y2)*(x1 - x)/(x1 - x2); + + return {ret, true}; +} +} + +template +TCoord _Box::width() const BP2D_NOEXCEPT +{ + return pointlike::x(maxCorner()) - pointlike::x(minCorner()); +} + +template +TCoord _Box::height() const BP2D_NOEXCEPT +{ + return pointlike::y(maxCorner()) - pointlike::y(minCorner()); +} + +template +TCoord getX(const RawPoint& p) { return pointlike::x(p); } + +template +TCoord getY(const RawPoint& p) { return pointlike::y(p); } + +template +void setX(RawPoint& p, const TCoord& val) +{ + pointlike::x(p) = val; +} + +template +void setY(RawPoint& p, const TCoord& val) +{ + pointlike::y(p) = val; +} + +template +inline Radians _Segment::angleToXaxis() const +{ + if(std::isnan(static_cast(angletox_))) { + TCoord dx = getX(second()) - getX(first()); + TCoord dy = getY(second()) - getY(first()); + + double a = std::atan2(dy, dx); + auto s = std::signbit(a); + + if(s) a += Pi_2; + angletox_ = a; + } + return angletox_; +} + +template +inline double _Segment::length() +{ + return pointlike::distance(first(), second()); +} + +template +inline RawPoint _Box::center() const BP2D_NOEXCEPT { + auto& minc = minCorner(); + auto& maxc = maxCorner(); + + using Coord = TCoord; + + RawPoint ret = { // No rounding here, we dont know if these are int coords + static_cast( (getX(minc) + getX(maxc))/2.0 ), + static_cast( (getY(minc) + getY(maxc))/2.0 ) + }; + + return ret; +} + +enum class Formats { + WKT, + SVG +}; + +// This struct serves as a namespace. The only difference is that it can be +// used in friend declarations and can be aliased at class scope. +namespace shapelike { + +template +using Shapes = TMultiShape; + +template +inline RawShape create(const TContour& contour, + const THolesContainer& holes) +{ + return RawShape(contour, holes); +} + +template +inline RawShape create(TContour&& contour, + THolesContainer&& holes) +{ + return RawShape(contour, holes); +} + +template +inline RawShape create(const TContour& contour) +{ + return create(contour, {}); +} + +template +inline RawShape create(TContour&& contour) +{ + return create(contour, {}); +} + +template +inline THolesContainer& holes(RawShape& /*sh*/) +{ + static THolesContainer empty; + return empty; +} + +template +inline const THolesContainer& holes(const RawShape& /*sh*/) +{ + static THolesContainer empty; + return empty; +} + +template +inline TContour& hole(RawShape& sh, unsigned long idx) +{ + return holes(sh)[idx]; +} + +template +inline const TContour& hole(const RawShape& sh, unsigned long idx) +{ + return holes(sh)[idx]; +} + +template +inline size_t holeCount(const RawShape& sh) +{ + return holes(sh).size(); +} + +template +inline TContour& contour(RawShape& sh) +{ + static_assert(always_false::value, + "shapelike::contour() unimplemented!"); + return sh; +} + +template +inline const TContour& contour(const RawShape& sh) +{ + static_assert(always_false::value, + "shapelike::contour() unimplemented!"); + return sh; +} + +// Optional, does nothing by default +template +inline void reserve(RawPath& p, size_t vertex_capacity, const PathTag&) +{ + p.reserve(vertex_capacity); +} + +template +inline void addVertex(RawShape& sh, const PathTag&, Args...args) +{ + return sh.emplace_back(std::forward(args)...); +} + +template +inline void foreachVertex(RawShape& sh, Fn fn, const PathTag&) { + std::for_each(sh.begin(), sh.end(), fn); +} + +template +inline typename RawShape::iterator begin(RawShape& sh, const PathTag&) +{ + return sh.begin(); +} + +template +inline typename RawShape::iterator end(RawShape& sh, const PathTag&) +{ + return sh.end(); +} + +template +inline typename RawShape::const_iterator +cbegin(const RawShape& sh, const PathTag&) +{ + return sh.cbegin(); +} + +template +inline typename RawShape::const_iterator +cend(const RawShape& sh, const PathTag&) +{ + return sh.cend(); +} + +template +inline std::string toString(const RawShape& /*sh*/) +{ + return ""; +} + +template +inline std::string serialize(const RawShape& /*sh*/, double /*scale*/=1) +{ + static_assert(always_false::value, + "shapelike::serialize() unimplemented!"); + return ""; +} + +template +inline void unserialize(RawShape& /*sh*/, const std::string& /*str*/) +{ + static_assert(always_false::value, + "shapelike::unserialize() unimplemented!"); +} + +template +inline double area(const RawShape& /*sh*/, const PolygonTag&) +{ + static_assert(always_false::value, + "shapelike::area() unimplemented!"); + return 0; +} + +template +inline bool intersects(const RawShape& /*sh*/, const RawShape& /*sh*/) +{ + static_assert(always_false::value, + "shapelike::intersects() unimplemented!"); + return false; +} + +template +inline bool isInside(const TPoint& /*point*/, + const RawShape& /*shape*/) +{ + static_assert(always_false::value, + "shapelike::isInside(point, shape) unimplemented!"); + return false; +} + +template +inline bool isInside(const RawShape& /*shape*/, + const RawShape& /*shape*/) +{ + static_assert(always_false::value, + "shapelike::isInside(shape, shape) unimplemented!"); + return false; +} + +template +inline bool touches( const RawShape& /*shape*/, + const RawShape& /*shape*/) +{ + static_assert(always_false::value, + "shapelike::touches(shape, shape) unimplemented!"); + return false; +} + +template +inline bool touches( const TPoint& /*point*/, + const RawShape& /*shape*/) +{ + static_assert(always_false::value, + "shapelike::touches(point, shape) unimplemented!"); + return false; +} + +template +inline _Box> boundingBox(const RawShape& /*sh*/, + const PolygonTag&) +{ + static_assert(always_false::value, + "shapelike::boundingBox(shape) unimplemented!"); +} + +template +inline _Box> +boundingBox(const RawShapes& /*sh*/, const MultiPolygonTag&) +{ + static_assert(always_false::value, + "shapelike::boundingBox(shapes) unimplemented!"); +} + +template +inline RawShape convexHull(const RawShape& /*sh*/, const PolygonTag&) +{ + static_assert(always_false::value, + "shapelike::convexHull(shape) unimplemented!"); + return RawShape(); +} + +template +inline typename RawShapes::value_type +convexHull(const RawShapes& /*sh*/, const MultiPolygonTag&) +{ + static_assert(always_false::value, + "shapelike::convexHull(shapes) unimplemented!"); + return typename RawShapes::value_type(); +} + +template +inline void rotate(RawShape& /*sh*/, const Radians& /*rads*/) +{ + static_assert(always_false::value, + "shapelike::rotate() unimplemented!"); +} + +template +inline void translate(RawShape& /*sh*/, const RawPoint& /*offs*/) +{ + static_assert(always_false::value, + "shapelike::translate() unimplemented!"); +} + +template +inline void offset(RawShape& /*sh*/, TCoord> /*distance*/) +{ + dout() << "The current geometry backend does not support offsetting!\n"; +} + +template +inline std::pair isValid(const RawShape& /*sh*/) +{ + return {false, "shapelike::isValid() unimplemented!"}; +} + +template inline bool isConvex(const RawPath& sh, const PathTag&) +{ + using Vertex = TPoint; + auto first = begin(sh); + auto middle = std::next(first); + auto last = std::next(middle); + using CVrRef = const Vertex&; + + auto zcrossproduct = [](CVrRef k, CVrRef k1, CVrRef k2) { + auto dx1 = getX(k1) - getX(k); + auto dy1 = getY(k1) - getY(k); + auto dx2 = getX(k2) - getX(k1); + auto dy2 = getY(k2) - getY(k1); + return dx1*dy2 - dy1*dx2; + }; + + auto firstprod = zcrossproduct( *(std::prev(std::prev(end(sh)))), + *first, + *middle ); + + bool ret = true; + bool frsign = firstprod > 0; + while(last != end(sh)) { + auto &k = *first, &k1 = *middle, &k2 = *last; + auto zc = zcrossproduct(k, k1, k2); + ret &= frsign == (zc > 0); + ++first; ++middle; ++last; + } + + return ret; +} + +// ***************************************************************************** +// No need to implement these +// ***************************************************************************** + +template +inline typename TContour::iterator +begin(RawShape& sh, const PolygonTag& t) +{ + return begin(contour(sh), PathTag()); +} + +template // Tag dispatcher +inline auto begin(RawShape& sh) -> decltype(begin(sh, Tag())) +{ + return begin(sh, Tag()); +} + +template +inline typename TContour::const_iterator +cbegin(const RawShape& sh, const PolygonTag&) +{ + return cbegin(contour(sh), PathTag()); +} + +template // Tag dispatcher +inline auto cbegin(const RawShape& sh) -> decltype(cbegin(sh, Tag())) +{ + return cbegin(sh, Tag()); +} + +template +inline typename TContour::iterator +end(RawShape& sh, const PolygonTag&) +{ + return end(contour(sh), PathTag()); +} + +template // Tag dispatcher +inline auto end(RawShape& sh) -> decltype(begin(sh, Tag())) +{ + return end(sh, Tag()); +} + +template +inline typename TContour::const_iterator +cend(const RawShape& sh, const PolygonTag&) +{ + return cend(contour(sh), PathTag()); +} + +template // Tag dispatcher +inline auto cend(const RawShape& sh) -> decltype(cend(sh, Tag())) +{ + return cend(sh, Tag()); +} + +template std::reverse_iterator _backward(It iter) { + return std::reverse_iterator(iter); +} + +template auto rbegin(P& p) -> decltype(_backward(end(p))) +{ + return _backward(end(p)); +} + +template auto rcbegin(const P& p) -> decltype(_backward(end(p))) +{ + return _backward(end(p)); +} + +template auto rend(P& p) -> decltype(_backward(begin(p))) +{ + return _backward(begin(p)); +} + +template auto rcend(const P& p) -> decltype(_backward(cbegin(p))) +{ + return _backward(cbegin(p)); +} + +template TPoint

front(const P& p) { return *shapelike::cbegin(p); } +template TPoint

back (const P& p) { + return *backward(shapelike::cend(p)); +} + +// Optional, does nothing by default +template +inline void reserve(RawShape& sh, size_t vertex_capacity, const PolygonTag&) +{ + reserve(contour(sh), vertex_capacity, PathTag()); +} + +template // Tag dispatcher +inline void reserve(T& sh, size_t vertex_capacity) { + reserve(sh, vertex_capacity, Tag()); +} + +template +inline void addVertex(RawShape& sh, const PolygonTag&, Args...args) +{ + return addVertex(contour(sh), PathTag(), std::forward(args)...); +} + +template // Tag dispatcher +inline void addVertex(RawShape& sh, Args...args) +{ + return addVertex(sh, Tag(), std::forward(args)...); +} + +template +inline Box boundingBox(const Box& box, const BoxTag& ) +{ + return box; +} + +template +inline _Box boundingBox( + const Circle& circ, const CircleTag&) +{ + using Point = typename Circle::PointType; + using Coord = TCoord; + Point pmin = { + static_cast(getX(circ.center()) - circ.radius()), + static_cast(getY(circ.center()) - circ.radius()) }; + + Point pmax = { + static_cast(getX(circ.center()) + circ.radius()), + static_cast(getY(circ.center()) + circ.radius()) }; + + return {pmin, pmax}; +} + +template // Dispatch function +inline _Box> boundingBox(const S& sh) +{ + return boundingBox(sh, Tag() ); +} + +template +inline double area(const Box& box, const BoxTag& ) +{ + return box.area(); +} + +template +inline double area(const Circle& circ, const CircleTag& ) +{ + return circ.area(); +} + +template // Dispatching function +inline double area(const RawShape& sh) +{ + return area(sh, Tag()); +} + +template +inline double area(const RawShapes& shapes, const MultiPolygonTag&) +{ + using RawShape = typename RawShapes::value_type; + return std::accumulate(shapes.begin(), shapes.end(), 0.0, + [](double a, const RawShape& b) { + return a += area(b); + }); +} + +template +inline auto convexHull(const RawShape& sh) + -> decltype(convexHull(sh, Tag())) // TODO: C++14 could deduce +{ + return convexHull(sh, Tag()); +} + +template +inline bool isInside(const TPoint& point, + const _Circle>& circ) +{ + return pointlike::distance(point, circ.center()) < circ.radius(); +} + +template +inline bool isInside(const TPoint& point, + const _Box>& box) +{ + auto px = getX(point); + auto py = getY(point); + auto minx = getX(box.minCorner()); + auto miny = getY(box.minCorner()); + auto maxx = getX(box.maxCorner()); + auto maxy = getY(box.maxCorner()); + + return px > minx && px < maxx && py > miny && py < maxy; +} + +template +inline bool isInside(const RawShape& sh, + const _Circle>& circ) +{ + return std::all_of(cbegin(sh), cend(sh), + [&circ](const TPoint& p){ + return isInside(p, circ); + }); +} + +template +inline bool isInside(const _Box>& box, + const _Circle>& circ) +{ + return isInside(box.minCorner(), circ) && + isInside(box.maxCorner(), circ); +} + +template +inline bool isInside(const _Box>& ibb, + const _Box>& box) +{ + auto iminX = getX(ibb.minCorner()); + auto imaxX = getX(ibb.maxCorner()); + auto iminY = getY(ibb.minCorner()); + auto imaxY = getY(ibb.maxCorner()); + + auto minX = getX(box.minCorner()); + auto maxX = getX(box.maxCorner()); + auto minY = getY(box.minCorner()); + auto maxY = getY(box.maxCorner()); + + return iminX > minX && imaxX < maxX && iminY > minY && imaxY < maxY; +} + +template // Potential O(1) implementation may exist +inline TPoint& vertex(RawShape& sh, unsigned long idx, + const PolygonTag&) +{ + return *(shapelike::begin(contour(sh)) + idx); +} + +template // Potential O(1) implementation may exist +inline TPoint& vertex(RawShape& sh, unsigned long idx, + const PathTag&) +{ + return *(shapelike::begin(sh) + idx); +} + +template // Potential O(1) implementation may exist +inline TPoint& vertex(RawShape& sh, unsigned long idx) +{ + return vertex(sh, idx, Tag()); +} + +template // Potential O(1) implementation may exist +inline const TPoint& vertex(const RawShape& sh, + unsigned long idx, + const PolygonTag&) +{ + return *(shapelike::cbegin(contour(sh)) + idx); +} + +template // Potential O(1) implementation may exist +inline const TPoint& vertex(const RawShape& sh, + unsigned long idx, + const PathTag&) +{ + return *(shapelike::cbegin(sh) + idx); +} + + +template // Potential O(1) implementation may exist +inline const TPoint& vertex(const RawShape& sh, + unsigned long idx) +{ + return vertex(sh, idx, Tag()); +} + +template +inline size_t contourVertexCount(const RawShape& sh) +{ + return shapelike::cend(sh) - shapelike::cbegin(sh); +} + +template +inline void foreachVertex(RawShape& sh, Fn fn, const PolygonTag&) { + foreachVertex(contour(sh), fn, PathTag()); + for(auto& h : holes(sh)) foreachVertex(h, fn, PathTag()); +} + +template +inline void foreachVertex(RawShape& sh, Fn fn) { + foreachVertex(sh, fn, Tag()); +} + +template inline bool isConvex(const Poly& sh, const PolygonTag&) +{ + bool convex = true; + convex &= isConvex(contour(sh), PathTag()); + convex &= holeCount(sh) == 0; + return convex; +} + +template inline bool isConvex(const RawShape& sh) // dispatch +{ + return isConvex(sh, Tag()); +} + +} + +#define DECLARE_MAIN_TYPES(T) \ + using Polygon = T; \ + using Point = TPoint; \ + using Coord = TCoord; \ + using Contour = TContour; \ + using Box = _Box; \ + using Circle = _Circle; \ + using Segment = _Segment; \ + using Polygons = TMultiShape + +} + +#endif // GEOMETRY_TRAITS_HPP diff --git a/src/libnest2d/libnest2d/geometry_traits_nfp.hpp b/src/libnest2d/include/libnest2d/geometry_traits_nfp.hpp similarity index 56% rename from src/libnest2d/libnest2d/geometry_traits_nfp.hpp rename to src/libnest2d/include/libnest2d/geometry_traits_nfp.hpp index 2982454cdc..cb0580ef4f 100644 --- a/src/libnest2d/libnest2d/geometry_traits_nfp.hpp +++ b/src/libnest2d/include/libnest2d/geometry_traits_nfp.hpp @@ -22,13 +22,63 @@ inline bool _vsort(const TPoint& v1, const TPoint& v2) return diff < 0; } + +template> +inline void buildPolygon(const EdgeList& edgelist, + RawShape& rpoly, + Vertex& top_nfp) +{ + namespace sl = shapelike; + + auto& rsh = sl::contour(rpoly); + + sl::reserve(rsh, 2*edgelist.size()); + + // Add the two vertices from the first edge into the final polygon. + sl::addVertex(rsh, edgelist.front().first()); + sl::addVertex(rsh, edgelist.front().second()); + + // Sorting function for the nfp reference vertex search + auto& cmp = _vsort; + + // the reference (rightmost top) vertex so far + top_nfp = *std::max_element(sl::cbegin(rsh), sl::cend(rsh), cmp ); + + auto tmp = std::next(sl::begin(rsh)); + + // Construct final nfp by placing each edge to the end of the previous + for(auto eit = std::next(edgelist.begin()); + eit != edgelist.end(); + ++eit) + { + auto d = *tmp - eit->first(); + Vertex p = eit->second() + d; + + sl::addVertex(rsh, p); + + // Set the new reference vertex + if(cmp(top_nfp, p)) top_nfp = p; + + tmp = std::next(tmp); + } + +} + +template +void advance(Iterator& it, Container& cont, bool direction) +{ + int dir = direction ? 1 : -1; + if(dir < 0 && it == cont.begin()) it = std::prev(cont.end()); + else it += dir; + if(dir > 0 && it == cont.end()) it = cont.begin(); +} + } /// A collection of static methods for handling the no fit polygon creation. namespace nfp { -//namespace sl = shapelike; -//namespace pl = pointlike; +const double BP2D_CONSTEXPR TwoPi = 2*Pi; /// The complexity level of a polygon that an NFP implementation can handle. enum class NfpLevel: unsigned { @@ -60,7 +110,7 @@ using Shapes = TMultiShape; * * \return A set of polygons that is the union of the input polygons. Note that * mostly it will be a set containing only one big polygon but if the input - * polygons are disjuct than the resulting set will contain more polygons. + * polygons are disjunct than the resulting set will contain more polygons. */ template inline RawShapes merge(const RawShapes& /*shc*/) @@ -78,14 +128,14 @@ inline RawShapes merge(const RawShapes& /*shc*/) * * \return A set of polygons that is the union of the input polygons. Note that * mostly it will be a set containing only one big polygon but if the input - * polygons are disjuct than the resulting set will contain more polygons. + * polygons are disjunct than the resulting set will contain more polygons. */ template inline TMultiShape merge(const TMultiShape& shc, const RawShape& sh) { auto m = nfp::merge(shc); - m.push_back(sh); + m.emplace_back(sh); return nfp::merge(m); } @@ -141,8 +191,8 @@ inline TPoint referenceVertex(const RawShape& sh) * cases (Through specializing the the NfpImpl struct). Currently, no other * cases are covered in the library. * - * Complexity should be no more than linear in the number of edges of the input - * polygons. + * Complexity should be no more than nlogn (std::sort) in the number of edges + * of the input polygons. * * \tparam RawShape the Polygon data type. * \param sh The stationary polygon @@ -196,33 +246,7 @@ inline NfpResult nfpConvexOnly(const RawShape& sh, return e1.angleToXaxis() > e2.angleToXaxis(); }); - // Add the two vertices from the first edge into the final polygon. - sl::addVertex(rsh, edgelist.front().first()); - sl::addVertex(rsh, edgelist.front().second()); - - // Sorting function for the nfp reference vertex search - auto& cmp = __nfp::_vsort; - - // the reference (rightmost top) vertex so far - top_nfp = *std::max_element(sl::cbegin(rsh), sl::cend(rsh), cmp ); - - auto tmp = std::next(sl::begin(rsh)); - - // Construct final nfp by placing each edge to the end of the previous - for(auto eit = std::next(edgelist.begin()); - eit != edgelist.end(); - ++eit) - { - auto d = *tmp - eit->first(); - Vertex p = eit->second() + d; - - sl::addVertex(rsh, p); - - // Set the new reference vertex - if(cmp(top_nfp, p)) top_nfp = p; - - tmp = std::next(tmp); - } + __nfp::buildPolygon(edgelist, rsh, top_nfp); return {rsh, top_nfp}; } @@ -260,29 +284,53 @@ NfpResult nfpSimpleSimple(const RawShape& cstationary, // the way it should be, than make my way around the orientations. // Reverse the stationary contour to counter clockwise - auto stcont = sl::getContour(cstationary); - std::reverse(stcont.begin(), stcont.end()); + auto stcont = sl::contour(cstationary); + { + std::reverse(sl::begin(stcont), sl::end(stcont)); + stcont.pop_back(); + auto it = std::min_element(sl::begin(stcont), sl::end(stcont), + [](const Vertex& v1, const Vertex& v2) { + return getY(v1) < getY(v2); + }); + std::rotate(sl::begin(stcont), it, sl::end(stcont)); + sl::addVertex(stcont, sl::front(stcont)); + } RawShape stationary; - sl::getContour(stationary) = stcont; + sl::contour(stationary) = stcont; // Reverse the orbiter contour to counter clockwise - auto orbcont = sl::getContour(cother); + auto orbcont = sl::contour(cother); + { + std::reverse(orbcont.begin(), orbcont.end()); - std::reverse(orbcont.begin(), orbcont.end()); + // Step 1: Make the orbiter reverse oriented + + orbcont.pop_back(); + auto it = std::min_element(orbcont.begin(), orbcont.end(), + [](const Vertex& v1, const Vertex& v2) { + return getY(v1) < getY(v2); + }); + + std::rotate(orbcont.begin(), it, orbcont.end()); + orbcont.emplace_back(orbcont.front()); + + for(auto &v : orbcont) v = -v; + + } // Copy the orbiter (contour only), we will have to work on it RawShape orbiter; - sl::getContour(orbiter) = orbcont; + sl::contour(orbiter) = orbcont; - // Step 1: Make the orbiter reverse oriented - for(auto &v : sl::getContour(orbiter)) v = -v; - - // An egde with additional data for marking it + // An edge with additional data for marking it struct MarkedEdge { Edge e; Radians turn_angle = 0; bool is_turning_point = false; MarkedEdge() = default; MarkedEdge(const Edge& ed, Radians ta, bool tp): e(ed), turn_angle(ta), is_turning_point(tp) {} + + // debug + std::string label; }; // Container for marked edges @@ -291,71 +339,87 @@ NfpResult nfpSimpleSimple(const RawShape& cstationary, EdgeList A, B; // This is how an edge list is created from the polygons - auto fillEdgeList = [](EdgeList& L, const RawShape& poly, int dir) { + auto fillEdgeList = [](EdgeList& L, const RawShape& ppoly, int dir) { + auto& poly = sl::contour(ppoly); + L.reserve(sl::contourVertexCount(poly)); - auto it = sl::cbegin(poly); - auto nextit = std::next(it); + if(dir > 0) { + auto it = poly.begin(); + auto nextit = std::next(it); - double turn_angle = 0; - bool is_turn_point = false; + double turn_angle = 0; + bool is_turn_point = false; - while(nextit != sl::cend(poly)) { - L.emplace_back(Edge(*it, *nextit), turn_angle, is_turn_point); - it++; nextit++; + while(nextit != poly.end()) { + L.emplace_back(Edge(*it, *nextit), turn_angle, is_turn_point); + it++; nextit++; + } + } else { + auto it = sl::rbegin(poly); + auto nextit = std::next(it); + + double turn_angle = 0; + bool is_turn_point = false; + + while(nextit != sl::rend(poly)) { + L.emplace_back(Edge(*it, *nextit), turn_angle, is_turn_point); + it++; nextit++; + } } auto getTurnAngle = [](const Edge& e1, const Edge& e2) { auto phi = e1.angleToXaxis(); auto phi_prev = e2.angleToXaxis(); - auto TwoPi = 2.0*Pi; - if(phi > Pi) phi -= TwoPi; - if(phi_prev > Pi) phi_prev -= TwoPi; auto turn_angle = phi-phi_prev; if(turn_angle > Pi) turn_angle -= TwoPi; - return phi-phi_prev; + if(turn_angle < -Pi) turn_angle += TwoPi; + return turn_angle; }; - if(dir > 0) { - auto eit = L.begin(); - auto enext = std::next(eit); + auto eit = L.begin(); + auto enext = std::next(eit); - eit->turn_angle = getTurnAngle(L.front().e, L.back().e); + eit->turn_angle = getTurnAngle(L.front().e, L.back().e); - while(enext != L.end()) { - enext->turn_angle = getTurnAngle( enext->e, eit->e); - enext->is_turning_point = - signbit(enext->turn_angle) != signbit(eit->turn_angle); - ++eit; ++enext; - } - - L.front().is_turning_point = signbit(L.front().turn_angle) != - signbit(L.back().turn_angle); - } else { - std::cout << L.size() << std::endl; - - auto eit = L.rbegin(); - auto enext = std::next(eit); - - eit->turn_angle = getTurnAngle(L.back().e, L.front().e); - - while(enext != L.rend()) { - enext->turn_angle = getTurnAngle(enext->e, eit->e); - enext->is_turning_point = - signbit(enext->turn_angle) != signbit(eit->turn_angle); - std::cout << enext->is_turning_point << " " << enext->turn_angle << std::endl; - - ++eit; ++enext; - } - - L.back().is_turning_point = signbit(L.back().turn_angle) != - signbit(L.front().turn_angle); + while(enext != L.end()) { + enext->turn_angle = getTurnAngle( enext->e, eit->e); + eit->is_turning_point = + signbit(enext->turn_angle) != signbit(eit->turn_angle); + ++eit; ++enext; } + + L.back().is_turning_point = signbit(L.back().turn_angle) != + signbit(L.front().turn_angle); + }; // Step 2: Fill the edgelists fillEdgeList(A, stationary, 1); - fillEdgeList(B, orbiter, -1); + fillEdgeList(B, orbiter, 1); + + int i = 1; + for(MarkedEdge& me : A) { + std::cout << "a" << i << ":\n\t" + << getX(me.e.first()) << " " << getY(me.e.first()) << "\n\t" + << getX(me.e.second()) << " " << getY(me.e.second()) << "\n\t" + << "Turning point: " << (me.is_turning_point ? "yes" : "no") + << std::endl; + + me.label = "a"; me.label += std::to_string(i); + i++; + } + + i = 1; + for(MarkedEdge& me : B) { + std::cout << "b" << i << ":\n\t" + << getX(me.e.first()) << " " << getY(me.e.first()) << "\n\t" + << getX(me.e.second()) << " " << getY(me.e.second()) << "\n\t" + << "Turning point: " << (me.is_turning_point ? "yes" : "no") + << std::endl; + me.label = "b"; me.label += std::to_string(i); + i++; + } // A reference to a marked edge that also knows its container struct MarkedEdgeRef { @@ -406,10 +470,8 @@ NfpResult nfpSimpleSimple(const RawShape& cstationary, Bref.emplace_back( ref(me), ref(Bref) ); }); - struct EdgeGroup { typename EdgeRefList::const_iterator first, last; }; - auto mink = [sortfn] // the Mink(Q, R, direction) sub-procedure - (const EdgeGroup& Q, const EdgeGroup& R, bool positive) + (const EdgeRefList& Q, const EdgeRefList& R, bool positive) { // Step 1 "merge sort_list(Q) and sort_list(R) to form merge_list(Q,R)" @@ -419,99 +481,198 @@ NfpResult nfpSimpleSimple(const RawShape& cstationary, EdgeRefList merged; EdgeRefList S, seq; - merged.reserve((Q.last - Q.first) + (R.last - R.first)); + merged.reserve(Q.size() + R.size()); - merged.insert(merged.end(), Q.first, Q.last); - merged.insert(merged.end(), R.first, R.last); - sort(merged.begin(), merged.end(), sortfn); + merged.insert(merged.end(), R.begin(), R.end()); + std::stable_sort(merged.begin(), merged.end(), sortfn); + merged.insert(merged.end(), Q.begin(), Q.end()); + std::stable_sort(merged.begin(), merged.end(), sortfn); // Step 2 "set i = 1, k = 1, direction = 1, s1 = q1" - // we dont use i, instead, q is an iterator into Q. k would be an index + // we don't use i, instead, q is an iterator into Q. k would be an index // into the merged sequence but we use "it" as an iterator for that // here we obtain references for the containers for later comparisons - const auto& Rcont = R.first->container.get(); - const auto& Qcont = Q.first->container.get(); + const auto& Rcont = R.begin()->container.get(); + const auto& Qcont = Q.begin()->container.get(); - // Set the intial direction - Coord dir = positive? 1 : -1; + // Set the initial direction + Coord dir = 1; - // roughly i = 1 (so q = Q.first) and s1 = q1 so S[0] = q; - auto q = Q.first; - S.push_back(*q++); + // roughly i = 1 (so q = Q.begin()) and s1 = q1 so S[0] = q; + if(positive) { + auto q = Q.begin(); + S.emplace_back(*q); - // Roughly step 3 - while(q != Q.last) { - auto it = merged.begin(); - while(it != merged.end() && !(it->eq(*(Q.first))) ) { - if(it->isFrom(Rcont)) { - auto s = *it; - s.dir = dir; - S.push_back(s); + // Roughly step 3 + + std::cout << "merged size: " << merged.size() << std::endl; + auto mit = merged.begin(); + for(bool finish = false; !finish && q != Q.end();) { + ++q; // "Set i = i + 1" + + while(!finish && mit != merged.end()) { + if(mit->isFrom(Rcont)) { + auto s = *mit; + s.dir = dir; + S.emplace_back(s); + } + + if(mit->eq(*q)) { + S.emplace_back(*q); + if(mit->isTurningPoint()) dir = -dir; + if(q == Q.begin()) finish = true; + break; + } + + mit += dir; + // __nfp::advance(mit, merged, dir > 0); + } + } + } else { + auto q = Q.rbegin(); + S.emplace_back(*q); + + // Roughly step 3 + + std::cout << "merged size: " << merged.size() << std::endl; + auto mit = merged.begin(); + for(bool finish = false; !finish && q != Q.rend();) { + ++q; // "Set i = i + 1" + + while(!finish && mit != merged.end()) { + if(mit->isFrom(Rcont)) { + auto s = *mit; + s.dir = dir; + S.emplace_back(s); + } + + if(mit->eq(*q)) { + S.emplace_back(*q); + S.back().dir = -1; + if(mit->isTurningPoint()) dir = -dir; + if(q == Q.rbegin()) finish = true; + break; + } + + mit += dir; + // __nfp::advance(mit, merged, dir > 0); } - if(it->eq(*q)) { - S.push_back(*q); - if(it->isTurningPoint()) dir = -dir; - if(q != Q.first) it += dir; - } - else it += dir; } - ++q; // "Set i = i + 1" } + // Step 4: // "Let starting edge r1 be in position si in sequence" // whaaat? I guess this means the following: - S[0] = *R.first; auto it = S.begin(); + while(!it->eq(*R.begin())) ++it; // "Set j = 1, next = 2, direction = 1, seq1 = si" - // we dont use j, seq is expanded dynamically. - dir = 1; auto next = std::next(R.first); + // we don't use j, seq is expanded dynamically. + dir = 1; + auto next = std::next(R.begin()); seq.emplace_back(*it); // Step 5: // "If all si edges have been allocated to seqj" should mean that // we loop until seq has equal size with S - while(seq.size() < S.size()) { + auto send = it; //it == S.begin() ? it : std::prev(it); + while(it != S.end()) { ++it; if(it == S.end()) it = S.begin(); + if(it == send) break; if(it->isFrom(Qcont)) { - seq.push_back(*it); // "If si is from Q, j = j + 1, seqj = si" + seq.emplace_back(*it); // "If si is from Q, j = j + 1, seqj = si" // "If si is a turning point in Q, // direction = - direction, next = next + direction" - if(it->isTurningPoint()) { dir = -dir; next += dir; } + if(it->isTurningPoint()) { + dir = -dir; + next += dir; +// __nfp::advance(next, R, dir > 0); + } } - if(it->eq(*next) && dir == next->dir) { // "If si = direction.rnext" + if(it->eq(*next) /*&& dir == next->dir*/) { // "If si = direction.rnext" // "j = j + 1, seqj = si, next = next + direction" - seq.push_back(*it); next += dir; + seq.emplace_back(*it); + next += dir; +// __nfp::advance(next, R, dir > 0); } } return seq; }; - EdgeGroup R{ Bref.begin(), Bref.begin() }, Q{ Aref.begin(), Aref.end() }; - auto it = Bref.begin(); - bool orientation = true; - EdgeRefList seqlist; - seqlist.reserve(3*(Aref.size() + Bref.size())); + std::vector seqlist; + seqlist.reserve(Bref.size()); - while(it != Bref.end()) // This is step 3 and step 4 in one loop - if(it->isTurningPoint()) { - R = {R.last, it++}; - auto seq = mink(Q, R, orientation); + EdgeRefList Bslope = Bref; // copy Bref, we will make a slope diagram - // TODO step 6 (should be 5 shouldn't it?): linking edges from A - // I don't get this step + // make the slope diagram of B + std::sort(Bslope.begin(), Bslope.end(), sortfn); - seqlist.insert(seqlist.end(), seq.begin(), seq.end()); - orientation = !orientation; - } else ++it; + auto slopeit = Bslope.begin(); // search for the first turning point + while(!slopeit->isTurningPoint() && slopeit != Bslope.end()) slopeit++; - if(seqlist.empty()) seqlist = mink(Q, {Bref.begin(), Bref.end()}, true); + if(slopeit == Bslope.end()) { + // no turning point means convex polygon. + seqlist.emplace_back(mink(Aref, Bref, true)); + } else { + int dir = 1; + + auto firstturn = Bref.begin(); + while(!firstturn->eq(*slopeit)) ++firstturn; + + assert(firstturn != Bref.end()); + + EdgeRefList bgroup; bgroup.reserve(Bref.size()); + bgroup.emplace_back(*slopeit); + + auto b_it = std::next(firstturn); + while(b_it != firstturn) { + if(b_it == Bref.end()) b_it = Bref.begin(); + + while(!slopeit->eq(*b_it)) { + __nfp::advance(slopeit, Bslope, dir > 0); + } + + if(!slopeit->isTurningPoint()) { + bgroup.emplace_back(*slopeit); + } else { + if(!bgroup.empty()) { + if(dir > 0) bgroup.emplace_back(*slopeit); + for(auto& me : bgroup) { + std::cout << me.eref.get().label << ", "; + } + std::cout << std::endl; + seqlist.emplace_back(mink(Aref, bgroup, dir == 1 ? true : false)); + bgroup.clear(); + if(dir < 0) bgroup.emplace_back(*slopeit); + } else { + bgroup.emplace_back(*slopeit); + } + + dir *= -1; + } + ++b_it; + } + } + +// while(it != Bref.end()) // This is step 3 and step 4 in one loop +// if(it->isTurningPoint()) { +// R = {R.last, it++}; +// auto seq = mink(Q, R, orientation); + +// // TODO step 6 (should be 5 shouldn't it?): linking edges from A +// // I don't get this step + +// seqlist.insert(seqlist.end(), seq.begin(), seq.end()); +// orientation = !orientation; +// } else ++it; + +// if(seqlist.empty()) seqlist = mink(Q, {Bref.begin(), Bref.end()}, true); // ///////////////////////////////////////////////////////////////////////// // Algorithm 2: breaking Minkowski sums into track line trips @@ -523,8 +684,25 @@ NfpResult nfpSimpleSimple(const RawShape& cstationary, // ///////////////////////////////////////////////////////////////////////// + for(auto& seq : seqlist) { + std::cout << "seqlist size: " << seq.size() << std::endl; + for(auto& s : seq) { + std::cout << (s.dir > 0 ? "" : "-") << s.eref.get().label << ", "; + } + std::cout << std::endl; + } - return Result(stationary, Vertex()); + auto& seq = seqlist.front(); + RawShape rsh; + Vertex top_nfp; + std::vector edgelist; edgelist.reserve(seq.size()); + for(auto& s : seq) { + edgelist.emplace_back(s.eref.get().e); + } + + __nfp::buildPolygon(edgelist, rsh, top_nfp); + + return Result(rsh, top_nfp); } // Specializable NFP implementation class. Specialize it if you have a faster diff --git a/src/libnest2d/libnest2d/libnest2d.hpp b/src/libnest2d/include/libnest2d/libnest2d.hpp similarity index 99% rename from src/libnest2d/libnest2d/libnest2d.hpp rename to src/libnest2d/include/libnest2d/libnest2d.hpp index 8841d1b735..aac62e094e 100644 --- a/src/libnest2d/libnest2d/libnest2d.hpp +++ b/src/libnest2d/include/libnest2d/libnest2d.hpp @@ -215,7 +215,7 @@ public: switch(convexity_) { case Convexity::UNCHECKED: - ret = sl::isConvex(sl::getContour(transformedShape())); + ret = sl::isConvex(sl::contour(transformedShape())); convexity_ = ret? Convexity::C_TRUE : Convexity::C_FALSE; break; case Convexity::C_TRUE: ret = true; break; @@ -805,16 +805,16 @@ public: class SConf = SelectionConfig> Nester( TBinType&& bin, Unit min_obj_distance = 0, - PConf&& pconfig = PConf(), - SConf&& sconfig = SConf()): + const PConf& pconfig = PConf(), + const SConf& sconfig = SConf()): bin_(std::forward(bin)), - pconfig_(std::forward(pconfig)), + pconfig_(pconfig), min_obj_distance_(min_obj_distance) { static_assert( std::is_same::value, "Incompatible placement and selection strategy!"); - selector_.configure(std::forward(sconfig)); + selector_.configure(sconfig); } void configure(const PlacementConfig& pconf) { pconfig_ = pconf; } diff --git a/src/libnest2d/libnest2d/optimizer.hpp b/src/libnest2d/include/libnest2d/optimizer.hpp similarity index 96% rename from src/libnest2d/libnest2d/optimizer.hpp rename to src/libnest2d/include/libnest2d/optimizer.hpp index 90d2f2ff99..78e1055987 100644 --- a/src/libnest2d/libnest2d/optimizer.hpp +++ b/src/libnest2d/include/libnest2d/optimizer.hpp @@ -105,6 +105,11 @@ struct StopCriteria { /// Stop if this value or better is found. double stop_score = std::nan(""); + /// A predicate that if evaluates to true, the optimization should terminate + /// and the best result found prior to termination should be returned. + std::function stop_condition = [] { return false; }; + + /// The max allowed number of iterations. unsigned max_iterations = 0; }; diff --git a/src/libnest2d/include/libnest2d/optimizers/nlopt/CMakeLists.txt b/src/libnest2d/include/libnest2d/optimizers/nlopt/CMakeLists.txt new file mode 100644 index 0000000000..5559ad6453 --- /dev/null +++ b/src/libnest2d/include/libnest2d/optimizers/nlopt/CMakeLists.txt @@ -0,0 +1,61 @@ +find_package(NLopt 1.4) + +if(NOT NLopt_FOUND) + message(STATUS "NLopt not found so downloading " + "and automatic build is performed...") + + include(DownloadProject) + + if (CMAKE_VERSION VERSION_LESS 3.2) + set(UPDATE_DISCONNECTED_IF_AVAILABLE "") + else() + set(UPDATE_DISCONNECTED_IF_AVAILABLE "UPDATE_DISCONNECTED 1") + endif() + + set(URL_NLOPT "https://github.com/stevengj/nlopt.git" + CACHE STRING "Location of the nlopt git repository") + + # set(NLopt_DIR ${CMAKE_BINARY_DIR}/nlopt) + include(DownloadProject) + download_project( PROJ nlopt + GIT_REPOSITORY ${URL_NLOPT} + GIT_TAG v2.5.0 + # CMAKE_CACHE_ARGS -DBUILD_SHARED_LIBS:BOOL=OFF -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX=${NLopt_DIR} + ${UPDATE_DISCONNECTED_IF_AVAILABLE} + ) + + set(SHARED_LIBS_STATE BUILD_SHARED_LIBS) + set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE) + set(NLOPT_PYTHON OFF CACHE BOOL "" FORCE) + set(NLOPT_OCTAVE OFF CACHE BOOL "" FORCE) + set(NLOPT_MATLAB OFF CACHE BOOL "" FORCE) + set(NLOPT_GUILE OFF CACHE BOOL "" FORCE) + set(NLOPT_SWIG OFF CACHE BOOL "" FORCE) + set(NLOPT_LINK_PYTHON OFF CACHE BOOL "" FORCE) + + add_subdirectory(${nlopt_SOURCE_DIR} ${nlopt_BINARY_DIR}) + + set(NLopt_LIBS nlopt) + set(NLopt_INCLUDE_DIR ${nlopt_BINARY_DIR} ${nlopt_BINARY_DIR}/src/api) + set(SHARED_LIBS_STATE ${SHARED_STATE}) + + add_library(NloptOptimizer INTERFACE) + target_link_libraries(NloptOptimizer INTERFACE nlopt) + target_include_directories(NloptOptimizer INTERFACE ${NLopt_INCLUDE_DIR}) + +else() + add_library(NloptOptimizer INTERFACE) + target_link_libraries(NloptOptimizer INTERFACE Nlopt::Nlopt) +endif() + +target_sources( NloptOptimizer INTERFACE +${CMAKE_CURRENT_SOURCE_DIR}/simplex.hpp +${CMAKE_CURRENT_SOURCE_DIR}/subplex.hpp +${CMAKE_CURRENT_SOURCE_DIR}/genetic.hpp +${CMAKE_CURRENT_SOURCE_DIR}/nlopt_boilerplate.hpp +) + +target_compile_definitions(NloptOptimizer INTERFACE LIBNEST2D_OPTIMIZER_NLOPT) + +# And finally plug the NloptOptimizer into libnest2d +target_link_libraries(libnest2d INTERFACE NloptOptimizer) diff --git a/src/libnest2d/libnest2d/optimizers/genetic.hpp b/src/libnest2d/include/libnest2d/optimizers/nlopt/genetic.hpp similarity index 88% rename from src/libnest2d/libnest2d/optimizers/genetic.hpp rename to src/libnest2d/include/libnest2d/optimizers/nlopt/genetic.hpp index 276854a12d..731ead554e 100644 --- a/src/libnest2d/libnest2d/optimizers/genetic.hpp +++ b/src/libnest2d/include/libnest2d/optimizers/nlopt/genetic.hpp @@ -19,7 +19,8 @@ public: template<> struct OptimizerSubclass { using Type = GeneticOptimizer; }; -template<> TOptimizer GlobalOptimizer( +template<> +inline TOptimizer GlobalOptimizer( Method localm, const StopCriteria& scr ) { return GeneticOptimizer (scr).localMethod(localm); diff --git a/src/libnest2d/libnest2d/optimizers/nlopt_boilerplate.hpp b/src/libnest2d/include/libnest2d/optimizers/nlopt/nlopt_boilerplate.hpp similarity index 85% rename from src/libnest2d/libnest2d/optimizers/nlopt_boilerplate.hpp rename to src/libnest2d/include/libnest2d/optimizers/nlopt/nlopt_boilerplate.hpp index 1a0f06e028..286d176c52 100644 --- a/src/libnest2d/libnest2d/optimizers/nlopt_boilerplate.hpp +++ b/src/libnest2d/include/libnest2d/optimizers/nlopt/nlopt_boilerplate.hpp @@ -13,7 +13,7 @@ #include #include -#include "libnest2d/metaloop.hpp" +#include #include @@ -100,7 +100,13 @@ protected: std::vector& /*grad*/, void *data) { - auto fnptr = static_cast*>(data); + using TData = std::pair*, NloptOptimizer*>; + auto typeddata = static_cast(data); + + if(typeddata->second->stopcr_.stop_condition()) + typeddata->second->opt_.force_stop(); + + auto fnptr = typeddata->first; auto funval = std::tuple(); // copy the obtained objectfunction arguments to the funval tuple. @@ -155,17 +161,25 @@ protected: // Take care of the initial values, copy them to initvals_ metaloop::apply(InitValFunc(*this), initvals); + std::pair*, NloptOptimizer*> data = + std::make_pair(&func, this); + switch(dir_) { case OptDir::MIN: - opt_.set_min_objective(optfunc, &func); break; + opt_.set_min_objective(optfunc, &data); break; case OptDir::MAX: - opt_.set_max_objective(optfunc, &func); break; + opt_.set_max_objective(optfunc, &data); break; } Result result; + nlopt::result rescode; - auto rescode = opt_.optimize(initvals_, result.score); - result.resultcode = static_cast(rescode); + try { + rescode = opt_.optimize(initvals_, result.score); + result.resultcode = static_cast(rescode); + } catch( nlopt::forced_stop& ) { + result.resultcode = ResultCodes::FORCED_STOP; + } metaloop::apply(ResultCopyFunc(*this), result.optimum); diff --git a/src/libnest2d/libnest2d/optimizers/simplex.hpp b/src/libnest2d/include/libnest2d/optimizers/nlopt/simplex.hpp similarity index 100% rename from src/libnest2d/libnest2d/optimizers/simplex.hpp rename to src/libnest2d/include/libnest2d/optimizers/nlopt/simplex.hpp diff --git a/src/libnest2d/libnest2d/optimizers/subplex.hpp b/src/libnest2d/include/libnest2d/optimizers/nlopt/subplex.hpp similarity index 100% rename from src/libnest2d/libnest2d/optimizers/subplex.hpp rename to src/libnest2d/include/libnest2d/optimizers/nlopt/subplex.hpp diff --git a/src/libnest2d/include/libnest2d/optimizers/optimlib/CMakeLists.txt b/src/libnest2d/include/libnest2d/optimizers/optimlib/CMakeLists.txt new file mode 100644 index 0000000000..efbbd9cfb2 --- /dev/null +++ b/src/libnest2d/include/libnest2d/optimizers/optimlib/CMakeLists.txt @@ -0,0 +1,5 @@ +find_package(Armadillo REQUIRED) + +add_library(OptimlibOptimizer INTERFACE) +target_include_directories(OptimlibOptimizer INTERFACE ${ARMADILLO_INCLUDE_DIRS}) +target_link_libraries(OptimlibOptimizer INTERFACE ${ARMADILLO_LIBRARIES}) \ No newline at end of file diff --git a/src/libnest2d/libnest2d/placers/bottomleftplacer.hpp b/src/libnest2d/include/libnest2d/placers/bottomleftplacer.hpp similarity index 98% rename from src/libnest2d/libnest2d/placers/bottomleftplacer.hpp rename to src/libnest2d/include/libnest2d/placers/bottomleftplacer.hpp index 18c27c40cd..7f10be7d73 100644 --- a/src/libnest2d/libnest2d/placers/bottomleftplacer.hpp +++ b/src/libnest2d/include/libnest2d/placers/bottomleftplacer.hpp @@ -233,7 +233,8 @@ protected: assert(pleft.vertexCount() > 0); - auto trpleft = pleft.transformedShape(); + auto trpleft_poly = pleft.transformedShape(); + auto& trpleft = sl::contour(trpleft_poly); auto first = sl::begin(trpleft); auto next = first + 1; auto endit = sl::end(trpleft); @@ -355,8 +356,10 @@ protected: auto start = std::min(topleft_it->first, bottomleft_it->first); auto finish = std::max(topleft_it->first, bottomleft_it->first); + RawShape ret; + // the return shape - RawShape rsh; + auto& rsh = sl::contour(ret); // reserve for all vertices plus 2 for the left horizontal wall, 2 for // the additional vertices for maintaning min object distance @@ -401,7 +404,7 @@ protected: // Close the polygon sl::addVertex(rsh, topleft_vertex); - return rsh; + return ret; } }; diff --git a/src/libnest2d/libnest2d/placers/nfpplacer.hpp b/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp similarity index 97% rename from src/libnest2d/libnest2d/placers/nfpplacer.hpp rename to src/libnest2d/include/libnest2d/placers/nfpplacer.hpp index c86fb507e3..14ed3d22c1 100644 --- a/src/libnest2d/libnest2d/placers/nfpplacer.hpp +++ b/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp @@ -15,11 +15,13 @@ #ifndef NDEBUG #include #endif -#include "placer_boilerplate.hpp" -#include "../geometry_traits_nfp.hpp" -#include "libnest2d/optimizer.hpp" +#include +#include -#include "tools/svgtools.hpp" +#include "placer_boilerplate.hpp" + +// temporary +//#include "../tools/svgtools.hpp" #ifdef USE_TBB #include @@ -55,7 +57,7 @@ inline void enumerate( #elif defined(_OPENMP) if((policy & std::launch::async) == std::launch::async) { #pragma omp parallel for - for(TN n = 0; n < N; n++) fn(*(from + n), n); + for(int n = 0; n < int(N); n++) fn(*(from + n), TN(n)); } else { for(TN n = 0; n < N; n++) fn(*(from + n), n); @@ -72,19 +74,6 @@ inline void enumerate( #endif } -class SpinLock { - static std::atomic_flag locked; -public: - void lock() { - while (locked.test_and_set(std::memory_order_acquire)) { ; } - } - void unlock() { - locked.clear(std::memory_order_release); - } -}; - -std::atomic_flag SpinLock::locked = ATOMIC_FLAG_INIT ; - } namespace __itemhash { @@ -101,7 +90,7 @@ Key hash(const _Item& item) { std::string ret; auto& rhs = item.rawShape(); - auto& ctr = sl::getContour(rhs); + auto& ctr = sl::contour(rhs); auto it = ctr.begin(); auto nx = std::next(it); @@ -467,7 +456,7 @@ Circle minimizeCircle(const RawShape& sh) { using Point = TPoint; using Coord = TCoord; - auto& ctr = sl::getContour(sh); + auto& ctr = sl::contour(sh); if(ctr.empty()) return {{0, 0}, 0}; auto bb = sl::boundingBox(sh); @@ -641,6 +630,23 @@ private: Shapes nfps(items_.size()); const Item& trsh = itsh.first; + // ///////////////////////////////////////////////////////////////////// + // TODO: this is a workaround and should be solved in Item with mutexes + // guarding the mutable members when writing them. + // ///////////////////////////////////////////////////////////////////// + trsh.transformedShape(); + trsh.referenceVertex(); + trsh.rightmostTopVertex(); + trsh.leftmostBottomVertex(); + + for(Item& itm : items_) { + itm.transformedShape(); + itm.referenceVertex(); + itm.rightmostTopVertex(); + itm.leftmostBottomVertex(); + } + // ///////////////////////////////////////////////////////////////////// + __parallel::enumerate(items_.begin(), items_.end(), [&nfps, &trsh](const Item& sh, size_t n) { @@ -651,14 +657,10 @@ private: nfps[n] = subnfp_r.first; }); -// for(auto& n : nfps) { -// auto valid = sl::isValid(n); -// if(!valid.first) std::cout << "Warning: " << valid.second << std::endl; -// } - return nfp::merge(nfps); } + template Shapes calcnfp( const ItemWithHash itsh, Level) { // Function for arbitrary level of nfp implementation @@ -842,7 +844,11 @@ private: bool can_pack = false; double best_overfit = std::numeric_limits::max(); - auto remlist = ItemGroup(remaining.from, remaining.to); + ItemGroup remlist; + if(remaining.valid) { + remlist.insert(remlist.end(), remaining.from, remaining.to); + } + size_t itemhash = __itemhash::hash(item); if(items_.empty()) { diff --git a/src/libnest2d/libnest2d/placers/placer_boilerplate.hpp b/src/libnest2d/include/libnest2d/placers/placer_boilerplate.hpp similarity index 98% rename from src/libnest2d/libnest2d/placers/placer_boilerplate.hpp rename to src/libnest2d/include/libnest2d/placers/placer_boilerplate.hpp index 0df1b8c913..9f940af4dd 100644 --- a/src/libnest2d/libnest2d/placers/placer_boilerplate.hpp +++ b/src/libnest2d/include/libnest2d/placers/placer_boilerplate.hpp @@ -1,7 +1,7 @@ #ifndef PLACER_BOILERPLATE_HPP #define PLACER_BOILERPLATE_HPP -#include "../libnest2d.hpp" +#include namespace libnest2d { namespace placers { diff --git a/src/libnest2d/libnest2d/selections/djd_heuristic.hpp b/src/libnest2d/include/libnest2d/selections/djd_heuristic.hpp similarity index 100% rename from src/libnest2d/libnest2d/selections/djd_heuristic.hpp rename to src/libnest2d/include/libnest2d/selections/djd_heuristic.hpp diff --git a/src/libnest2d/libnest2d/selections/filler.hpp b/src/libnest2d/include/libnest2d/selections/filler.hpp similarity index 100% rename from src/libnest2d/libnest2d/selections/filler.hpp rename to src/libnest2d/include/libnest2d/selections/filler.hpp diff --git a/src/libnest2d/libnest2d/selections/firstfit.hpp b/src/libnest2d/include/libnest2d/selections/firstfit.hpp similarity index 99% rename from src/libnest2d/libnest2d/selections/firstfit.hpp rename to src/libnest2d/include/libnest2d/selections/firstfit.hpp index 6bb9c60e45..d25487d6bc 100644 --- a/src/libnest2d/libnest2d/selections/firstfit.hpp +++ b/src/libnest2d/include/libnest2d/selections/firstfit.hpp @@ -1,7 +1,6 @@ #ifndef FIRSTFIT_HPP #define FIRSTFIT_HPP -#include "../libnest2d.hpp" #include "selection_boilerplate.hpp" namespace libnest2d { namespace selections { diff --git a/src/libnest2d/libnest2d/selections/selection_boilerplate.hpp b/src/libnest2d/include/libnest2d/selections/selection_boilerplate.hpp similarity index 96% rename from src/libnest2d/libnest2d/selections/selection_boilerplate.hpp rename to src/libnest2d/include/libnest2d/selections/selection_boilerplate.hpp index cfb98a9c8e..8351a99e7c 100644 --- a/src/libnest2d/libnest2d/selections/selection_boilerplate.hpp +++ b/src/libnest2d/include/libnest2d/selections/selection_boilerplate.hpp @@ -1,8 +1,8 @@ #ifndef SELECTION_BOILERPLATE_HPP #define SELECTION_BOILERPLATE_HPP -#include "../libnest2d.hpp" #include +#include namespace libnest2d { namespace selections { diff --git a/src/libnest2d/libnest2d/boost_alg.hpp b/src/libnest2d/include/libnest2d/utils/boost_alg.hpp similarity index 98% rename from src/libnest2d/libnest2d/boost_alg.hpp rename to src/libnest2d/include/libnest2d/utils/boost_alg.hpp index bb0403b066..c573edb47b 100644 --- a/src/libnest2d/libnest2d/boost_alg.hpp +++ b/src/libnest2d/include/libnest2d/utils/boost_alg.hpp @@ -241,11 +241,11 @@ template<> struct tag { template<> struct exterior_ring { static inline bp2d::PathImpl& get(bp2d::PolygonImpl& p) { - return libnest2d::shapelike::getContour(p); + return libnest2d::shapelike::contour(p); } static inline bp2d::PathImpl const& get(bp2d::PolygonImpl const& p) { - return libnest2d::shapelike::getContour(p); + return libnest2d::shapelike::contour(p); } }; @@ -388,6 +388,14 @@ inline bp2d::Box boundingBox(const PolygonImpl& sh, const PolygonTag&) return b; } +template<> +inline bp2d::Box boundingBox(const PathImpl& sh, const PolygonTag&) +{ + bp2d::Box b; + boost::geometry::envelope(sh, b); + return b; +} + template<> inline bp2d::Box boundingBox(const bp2d::Shapes& shapes, const MultiPolygonTag&) diff --git a/src/libnest2d/libnest2d/metaloop.hpp b/src/libnest2d/include/libnest2d/utils/metaloop.hpp similarity index 98% rename from src/libnest2d/libnest2d/metaloop.hpp rename to src/libnest2d/include/libnest2d/utils/metaloop.hpp index d88988ba15..ac099ac464 100644 --- a/src/libnest2d/libnest2d/metaloop.hpp +++ b/src/libnest2d/include/libnest2d/utils/metaloop.hpp @@ -1,7 +1,7 @@ #ifndef METALOOP_HPP #define METALOOP_HPP -#include "common.hpp" +#include #include #include @@ -12,7 +12,7 @@ namespace libnest2d { /* ************************************************************************** */ /** - * \brief C++11 conformant implementation of the index_sequence type from C++14 + * \brief C++11 compatible implementation of the index_sequence type from C++14 */ template struct index_sequence { using value_type = size_t; diff --git a/src/libnest2d/libnest2d/rotfinder.hpp b/src/libnest2d/include/libnest2d/utils/rotfinder.hpp similarity index 100% rename from src/libnest2d/libnest2d/rotfinder.hpp rename to src/libnest2d/include/libnest2d/utils/rotfinder.hpp diff --git a/src/libnest2d/libnest2d.h b/src/libnest2d/libnest2d.h deleted file mode 100644 index bfd88f4f5d..0000000000 --- a/src/libnest2d/libnest2d.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef LIBNEST2D_H -#define LIBNEST2D_H - -// The type of backend should be set conditionally by the cmake configuriation -// for now we set it statically to clipper backend -#include - -// We include the stock optimizers for local and global optimization -#include // Local subplex for NfpPlacer -#include // Genetic for min. bounding box - -#include -#include -#include -#include -#include -#include - -namespace libnest2d { - -using Point = PointImpl; -using Coord = TCoord; -using Box = _Box; -using Segment = _Segment; -using Circle = _Circle; - -using Item = _Item; -using Rectangle = _Rectangle; - -using PackGroup = _PackGroup; -using IndexedPackGroup = _IndexedPackGroup; - -using FillerSelection = selections::_FillerSelection; -using FirstFitSelection = selections::_FirstFitSelection; -using DJDHeuristic = selections::_DJDHeuristic; - -using NfpPlacer = placers::_NofitPolyPlacer; -using BottomLeftPlacer = placers::_BottomLeftPlacer; - -} - -#endif // LIBNEST2D_H diff --git a/src/libnest2d/libnest2d/geometry_traits.hpp b/src/libnest2d/libnest2d/geometry_traits.hpp deleted file mode 100644 index a78a03b3a5..0000000000 --- a/src/libnest2d/libnest2d/geometry_traits.hpp +++ /dev/null @@ -1,825 +0,0 @@ -#ifndef GEOMETRY_TRAITS_HPP -#define GEOMETRY_TRAITS_HPP - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "common.hpp" - -namespace libnest2d { - -/// Getting the coordinate data type for a geometry class. -template struct CoordType { using Type = long; }; - -/// TCoord as shorthand for typename `CoordType::Type`. -template -using TCoord = typename CoordType>::Type; - -/// Getting the type of point structure used by a shape. -template struct PointType { using Type = typename Sh::PointType; }; - -/// TPoint as shorthand for `typename PointType::Type`. -template -using TPoint = typename PointType>::Type; - -/** - * \brief A point pair base class for other point pairs (segment, box, ...). - * \tparam RawPoint The actual point type to use. - */ -template -struct PointPair { - RawPoint p1; - RawPoint p2; -}; - -struct PolygonTag {}; -struct MultiPolygonTag {}; -struct BoxTag {}; -struct CircleTag {}; - -template struct ShapeTag { using Type = typename Shape::Tag; }; -template using Tag = typename ShapeTag::Type; - -template struct MultiShape { using Type = std::vector; }; -template using TMultiShape = typename MultiShape::Type; - -/** - * \brief An abstraction of a box; - */ -template -class _Box: PointPair { - using PointPair::p1; - using PointPair::p2; -public: - - using Tag = BoxTag; - using PointType = RawPoint; - - inline _Box() = default; - inline _Box(const RawPoint& p, const RawPoint& pp): - PointPair({p, pp}) {} - - inline _Box(TCoord width, TCoord height): - _Box(RawPoint{0, 0}, RawPoint{width, height}) {} - - inline const RawPoint& minCorner() const BP2D_NOEXCEPT { return p1; } - inline const RawPoint& maxCorner() const BP2D_NOEXCEPT { return p2; } - - inline RawPoint& minCorner() BP2D_NOEXCEPT { return p1; } - inline RawPoint& maxCorner() BP2D_NOEXCEPT { return p2; } - - inline TCoord width() const BP2D_NOEXCEPT; - inline TCoord height() const BP2D_NOEXCEPT; - - inline RawPoint center() const BP2D_NOEXCEPT; - - inline double area() const BP2D_NOEXCEPT { - return double(width()*height()); - } -}; - -template -class _Circle { - RawPoint center_; - double radius_ = 0; -public: - - using Tag = CircleTag; - using PointType = RawPoint; - - _Circle() = default; - - _Circle(const RawPoint& center, double r): center_(center), radius_(r) {} - - inline const RawPoint& center() const BP2D_NOEXCEPT { return center_; } - inline const void center(const RawPoint& c) { center_ = c; } - - inline double radius() const BP2D_NOEXCEPT { return radius_; } - inline void radius(double r) { radius_ = r; } - - inline double area() const BP2D_NOEXCEPT { - return 2.0*Pi*radius_*radius_; - } -}; - -/** - * \brief An abstraction of a directed line segment with two points. - */ -template -class _Segment: PointPair { - using PointPair::p1; - using PointPair::p2; - mutable Radians angletox_ = std::nan(""); -public: - - using PointType = RawPoint; - - inline _Segment() = default; - - inline _Segment(const RawPoint& p, const RawPoint& pp): - PointPair({p, pp}) {} - - /** - * @brief Get the first point. - * @return Returns the starting point. - */ - inline const RawPoint& first() const BP2D_NOEXCEPT { return p1; } - - /** - * @brief The end point. - * @return Returns the end point of the segment. - */ - inline const RawPoint& second() const BP2D_NOEXCEPT { return p2; } - - inline void first(const RawPoint& p) BP2D_NOEXCEPT - { - angletox_ = std::nan(""); p1 = p; - } - - inline void second(const RawPoint& p) BP2D_NOEXCEPT { - angletox_ = std::nan(""); p2 = p; - } - - /// Returns the angle measured to the X (horizontal) axis. - inline Radians angleToXaxis() const; - - /// The length of the segment in the measure of the coordinate system. - inline double length(); -}; - -// This struct serves almost as a namespace. The only difference is that is can -// used in friend declarations. -namespace pointlike { - - template - inline TCoord x(const RawPoint& p) - { - return p(0); - } - - template - inline TCoord y(const RawPoint& p) - { - return p(1); - } - - template - inline TCoord& x(RawPoint& p) - { - return p(0); - } - - template - inline TCoord& y(RawPoint& p) - { - return p(1); - } - - template - inline double distance(const RawPoint& /*p1*/, const RawPoint& /*p2*/) - { - static_assert(always_false::value, - "PointLike::distance(point, point) unimplemented!"); - return 0; - } - - template - inline double distance(const RawPoint& /*p1*/, - const _Segment& /*s*/) - { - static_assert(always_false::value, - "PointLike::distance(point, segment) unimplemented!"); - return 0; - } - - template - inline std::pair, bool> horizontalDistance( - const RawPoint& p, const _Segment& s) - { - using Unit = TCoord; - auto x = pointlike::x(p), y = pointlike::y(p); - auto x1 = pointlike::x(s.first()), y1 = pointlike::y(s.first()); - auto x2 = pointlike::x(s.second()), y2 = pointlike::y(s.second()); - - TCoord ret; - - if( (y < y1 && y < y2) || (y > y1 && y > y2) ) - return {0, false}; - if ((y == y1 && y == y2) && (x > x1 && x > x2)) - ret = std::min( x-x1, x -x2); - else if( (y == y1 && y == y2) && (x < x1 && x < x2)) - ret = -std::min(x1 - x, x2 - x); - else if(std::abs(y - y1) <= std::numeric_limits::epsilon() && - std::abs(y - y2) <= std::numeric_limits::epsilon()) - ret = 0; - else - ret = x - x1 + (x1 - x2)*(y1 - y)/(y1 - y2); - - return {ret, true}; - } - - template - inline std::pair, bool> verticalDistance( - const RawPoint& p, const _Segment& s) - { - using Unit = TCoord; - auto x = pointlike::x(p), y = pointlike::y(p); - auto x1 = pointlike::x(s.first()), y1 = pointlike::y(s.first()); - auto x2 = pointlike::x(s.second()), y2 = pointlike::y(s.second()); - - TCoord ret; - - if( (x < x1 && x < x2) || (x > x1 && x > x2) ) - return {0, false}; - if ((x == x1 && x == x2) && (y > y1 && y > y2)) - ret = std::min( y-y1, y -y2); - else if( (x == x1 && x == x2) && (y < y1 && y < y2)) - ret = -std::min(y1 - y, y2 - y); - else if(std::abs(x - x1) <= std::numeric_limits::epsilon() && - std::abs(x - x2) <= std::numeric_limits::epsilon()) - ret = 0; - else - ret = y - y1 + (y1 - y2)*(x1 - x)/(x1 - x2); - - return {ret, true}; - } -} - -template -TCoord _Box::width() const BP2D_NOEXCEPT -{ - return pointlike::x(maxCorner()) - pointlike::x(minCorner()); -} - -template -TCoord _Box::height() const BP2D_NOEXCEPT -{ - return pointlike::y(maxCorner()) - pointlike::y(minCorner()); -} - -template -TCoord getX(const RawPoint& p) { return pointlike::x(p); } - -template -TCoord getY(const RawPoint& p) { return pointlike::y(p); } - -template -void setX(RawPoint& p, const TCoord& val) -{ - pointlike::x(p) = val; -} - -template -void setY(RawPoint& p, const TCoord& val) -{ - pointlike::y(p) = val; -} - -template -inline Radians _Segment::angleToXaxis() const -{ - if(std::isnan(static_cast(angletox_))) { - TCoord dx = getX(second()) - getX(first()); - TCoord dy = getY(second()) - getY(first()); - - double a = std::atan2(dy, dx); - auto s = std::signbit(a); - - if(s) a += Pi_2; - angletox_ = a; - } - return angletox_; -} - -template -inline double _Segment::length() -{ - return pointlike::distance(first(), second()); -} - -template -inline RawPoint _Box::center() const BP2D_NOEXCEPT { - auto& minc = minCorner(); - auto& maxc = maxCorner(); - - using Coord = TCoord; - - RawPoint ret = { // No rounding here, we dont know if these are int coords - static_cast( (getX(minc) + getX(maxc))/2.0 ), - static_cast( (getY(minc) + getY(maxc))/2.0 ) - }; - - return ret; -} - -template -struct HolesContainer { - using Type = std::vector; -}; - -template -using THolesContainer = typename HolesContainer>::Type; - -template -struct CountourType { - using Type = RawShape; -}; - -template -using TContour = typename CountourType>::Type; - -enum class Orientation { - CLOCKWISE, - COUNTER_CLOCKWISE -}; - -template -struct OrientationType { - - // Default Polygon orientation that the library expects - static const Orientation Value = Orientation::CLOCKWISE; -}; - -enum class Formats { - WKT, - SVG -}; - -// This struct serves as a namespace. The only difference is that it can be -// used in friend declarations and can be aliased at class scope. -namespace shapelike { - - template - using Shapes = TMultiShape; - - template - inline RawShape create(const TContour& contour, - const THolesContainer& holes) - { - return RawShape(contour, holes); - } - - template - inline RawShape create(TContour&& contour, - THolesContainer&& holes) - { - return RawShape(contour, holes); - } - - template - inline RawShape create(const TContour& contour) - { - return create(contour, {}); - } - - template - inline RawShape create(TContour&& contour) - { - return create(contour, {}); - } - - template - inline THolesContainer& holes(RawShape& /*sh*/) - { - static THolesContainer empty; - return empty; - } - - template - inline const THolesContainer& holes(const RawShape& /*sh*/) - { - static THolesContainer empty; - return empty; - } - - template - inline TContour& getHole(RawShape& sh, unsigned long idx) - { - return holes(sh)[idx]; - } - - template - inline const TContour& getHole(const RawShape& sh, - unsigned long idx) - { - return holes(sh)[idx]; - } - - template - inline size_t holeCount(const RawShape& sh) - { - return holes(sh).size(); - } - - template - inline TContour& getContour(RawShape& sh) - { - return sh; - } - - template - inline const TContour& getContour(const RawShape& sh) - { - return sh; - } - - // Optional, does nothing by default - template - inline void reserve(RawShape& /*sh*/, size_t /*vertex_capacity*/) {} - - template - inline void addVertex(RawShape& sh, Args...args) - { - return getContour(sh).emplace_back(std::forward(args)...); - } - - template - inline typename TContour::iterator begin(RawShape& sh) - { - return getContour(sh).begin(); - } - - template - inline typename TContour::iterator end(RawShape& sh) - { - return getContour(sh).end(); - } - - template - inline typename TContour::const_iterator - cbegin(const RawShape& sh) - { - return getContour(sh).cbegin(); - } - - template - inline typename TContour::const_iterator cend(const RawShape& sh) - { - return getContour(sh).cend(); - } - - template - inline std::string toString(const RawShape& /*sh*/) - { - return ""; - } - - template - inline std::string serialize(const RawShape& /*sh*/, double /*scale*/=1) - { - static_assert(always_false::value, - "ShapeLike::serialize() unimplemented!"); - return ""; - } - - template - inline void unserialize(RawShape& /*sh*/, const std::string& /*str*/) - { - static_assert(always_false::value, - "ShapeLike::unserialize() unimplemented!"); - } - - template - inline double area(const RawShape& /*sh*/, const PolygonTag&) - { - static_assert(always_false::value, - "ShapeLike::area() unimplemented!"); - return 0; - } - - template - inline bool intersects(const RawShape& /*sh*/, const RawShape& /*sh*/) - { - static_assert(always_false::value, - "ShapeLike::intersects() unimplemented!"); - return false; - } - - template - inline bool isInside(const TPoint& /*point*/, - const RawShape& /*shape*/) - { - static_assert(always_false::value, - "ShapeLike::isInside(point, shape) unimplemented!"); - return false; - } - - template - inline bool isInside(const RawShape& /*shape*/, - const RawShape& /*shape*/) - { - static_assert(always_false::value, - "ShapeLike::isInside(shape, shape) unimplemented!"); - return false; - } - - template - inline bool touches( const RawShape& /*shape*/, - const RawShape& /*shape*/) - { - static_assert(always_false::value, - "ShapeLike::touches(shape, shape) unimplemented!"); - return false; - } - - template - inline bool touches( const TPoint& /*point*/, - const RawShape& /*shape*/) - { - static_assert(always_false::value, - "ShapeLike::touches(point, shape) unimplemented!"); - return false; - } - - template - inline _Box> boundingBox(const RawShape& /*sh*/, - const PolygonTag&) - { - static_assert(always_false::value, - "ShapeLike::boundingBox(shape) unimplemented!"); - } - - template - inline _Box> - boundingBox(const RawShapes& /*sh*/, const MultiPolygonTag&) - { - static_assert(always_false::value, - "ShapeLike::boundingBox(shapes) unimplemented!"); - } - - template - inline RawShape convexHull(const RawShape& /*sh*/, const PolygonTag&) - { - static_assert(always_false::value, - "ShapeLike::convexHull(shape) unimplemented!"); - return RawShape(); - } - - template - inline typename RawShapes::value_type - convexHull(const RawShapes& /*sh*/, const MultiPolygonTag&) - { - static_assert(always_false::value, - "ShapeLike::convexHull(shapes) unimplemented!"); - return typename RawShapes::value_type(); - } - - template - inline void rotate(RawShape& /*sh*/, const Radians& /*rads*/) - { - static_assert(always_false::value, - "ShapeLike::rotate() unimplemented!"); - } - - template - inline void translate(RawShape& /*sh*/, const RawPoint& /*offs*/) - { - static_assert(always_false::value, - "ShapeLike::translate() unimplemented!"); - } - - template - inline void offset(RawShape& /*sh*/, TCoord> /*distance*/) - { - dout() << "The current geometry backend does not support offsetting!\n"; - } - - template - inline std::pair isValid(const RawShape& /*sh*/) - { - return {false, "ShapeLike::isValid() unimplemented!"}; - } - - template - inline bool isConvex(const TContour& sh) - { - using Vertex = TPoint; - auto first = sh.begin(); - auto middle = std::next(first); - auto last = std::next(middle); - using CVrRef = const Vertex&; - - auto zcrossproduct = [](CVrRef k, CVrRef k1, CVrRef k2) { - auto dx1 = getX(k1) - getX(k); - auto dy1 = getY(k1) - getY(k); - auto dx2 = getX(k2) - getX(k1); - auto dy2 = getY(k2) - getY(k1); - return dx1*dy2 - dy1*dx2; - }; - - auto firstprod = zcrossproduct( *(std::prev(std::prev(sh.end()))), - *first, - *middle ); - - bool ret = true; - bool frsign = firstprod > 0; - while(last != sh.end()) { - auto &k = *first, &k1 = *middle, &k2 = *last; - auto zc = zcrossproduct(k, k1, k2); - ret &= frsign == (zc > 0); - ++first; ++middle; ++last; - } - - return ret; - } - - // ************************************************************************* - // No need to implement these - // ************************************************************************* - - template - inline Box boundingBox(const Box& box, const BoxTag& ) - { - return box; - } - - template - inline _Box boundingBox( - const Circle& circ, const CircleTag&) - { - using Point = typename Circle::PointType; - using Coord = TCoord; - Point pmin = { - static_cast(getX(circ.center()) - circ.radius()), - static_cast(getY(circ.center()) - circ.radius()) }; - - Point pmax = { - static_cast(getX(circ.center()) + circ.radius()), - static_cast(getY(circ.center()) + circ.radius()) }; - - return {pmin, pmax}; - } - - template // Dispatch function - inline _Box> boundingBox(const S& sh) - { - return boundingBox(sh, Tag() ); - } - - template - inline double area(const Box& box, const BoxTag& ) - { - return box.area(); - } - - template - inline double area(const Circle& circ, const CircleTag& ) - { - return circ.area(); - } - - template // Dispatching function - inline double area(const RawShape& sh) - { - return area(sh, Tag()); - } - - template - inline double area(const Shapes& shapes) - { - return std::accumulate(shapes.begin(), shapes.end(), 0.0, - [](double a, const RawShape& b) { - return a += area(b); - }); - } - - template - inline auto convexHull(const RawShape& sh) - -> decltype(convexHull(sh, Tag())) // TODO: C++14 could deduce - { - return convexHull(sh, Tag()); - } - - template - inline bool isInside(const TPoint& point, - const _Circle>& circ) - { - return pointlike::distance(point, circ.center()) < circ.radius(); - } - - template - inline bool isInside(const TPoint& point, - const _Box>& box) - { - auto px = getX(point); - auto py = getY(point); - auto minx = getX(box.minCorner()); - auto miny = getY(box.minCorner()); - auto maxx = getX(box.maxCorner()); - auto maxy = getY(box.maxCorner()); - - return px > minx && px < maxx && py > miny && py < maxy; - } - - template - inline bool isInside(const RawShape& sh, - const _Circle>& circ) - { - return std::all_of(cbegin(sh), cend(sh), - [&circ](const TPoint& p){ - return isInside(p, circ); - }); - } - - template - inline bool isInside(const _Box>& box, - const _Circle>& circ) - { - return isInside(box.minCorner(), circ) && - isInside(box.maxCorner(), circ); - } - - template - inline bool isInside(const _Box>& ibb, - const _Box>& box) - { - auto iminX = getX(ibb.minCorner()); - auto imaxX = getX(ibb.maxCorner()); - auto iminY = getY(ibb.minCorner()); - auto imaxY = getY(ibb.maxCorner()); - - auto minX = getX(box.minCorner()); - auto maxX = getX(box.maxCorner()); - auto minY = getY(box.minCorner()); - auto maxY = getY(box.maxCorner()); - - return iminX > minX && imaxX < maxX && iminY > minY && imaxY < maxY; - } - - template // Potential O(1) implementation may exist - inline TPoint& vertex(RawShape& sh, unsigned long idx) - { - return *(begin(sh) + idx); - } - - template // Potential O(1) implementation may exist - inline const TPoint& vertex(const RawShape& sh, - unsigned long idx) - { - return *(cbegin(sh) + idx); - } - - template - inline size_t contourVertexCount(const RawShape& sh) - { - return cend(sh) - cbegin(sh); - } - - template - inline void foreachContourVertex(RawShape& sh, Fn fn) { - for(auto it = begin(sh); it != end(sh); ++it) fn(*it); - } - - template - inline void foreachHoleVertex(RawShape& sh, Fn fn) { - for(int i = 0; i < holeCount(sh); ++i) { - auto& h = getHole(sh, i); - for(auto it = begin(h); it != end(h); ++it) fn(*it); - } - } - - template - inline void foreachContourVertex(const RawShape& sh, Fn fn) { - for(auto it = cbegin(sh); it != cend(sh); ++it) fn(*it); - } - - template - inline void foreachHoleVertex(const RawShape& sh, Fn fn) { - for(int i = 0; i < holeCount(sh); ++i) { - auto& h = getHole(sh, i); - for(auto it = cbegin(h); it != cend(h); ++it) fn(*it); - } - } - - template - inline void foreachVertex(RawShape& sh, Fn fn) { - foreachContourVertex(sh, fn); - foreachHoleVertex(sh, fn); - } - - template - inline void foreachVertex(const RawShape& sh, Fn fn) { - foreachContourVertex(sh, fn); - foreachHoleVertex(sh, fn); - } -} - -#define DECLARE_MAIN_TYPES(T) \ - using Polygon = T; \ - using Point = TPoint; \ - using Coord = TCoord; \ - using Contour = TContour; \ - using Box = _Box; \ - using Circle = _Circle; \ - using Segment = _Segment; \ - using Polygons = TMultiShape - -} - -#endif // GEOMETRY_TRAITS_HPP diff --git a/src/libnest2d/tests/CMakeLists.txt b/src/libnest2d/tests/CMakeLists.txt index 3777f3c568..fc3cd309dd 100644 --- a/src/libnest2d/tests/CMakeLists.txt +++ b/src/libnest2d/tests/CMakeLists.txt @@ -3,7 +3,10 @@ find_package(GTest 1.7) if(NOT GTEST_FOUND) - message(STATUS "GTest not found so downloading...") + set(URL_GTEST "https://github.com/google/googletest.git" + CACHE STRING "Google test source code repository location.") + + message(STATUS "GTest not found so downloading from ${URL_GTEST}") # Go and download google test framework, integrate it with the build set(GTEST_LIBS_TO_LINK gtest gtest_main) @@ -15,7 +18,7 @@ if(NOT GTEST_FOUND) include(DownloadProject) download_project(PROJ googletest - GIT_REPOSITORY https://github.com/google/googletest.git + GIT_REPOSITORY ${URL_GTEST} GIT_TAG release-1.7.0 ${UPDATE_DISCONNECTED_IF_AVAILABLE} ) @@ -35,17 +38,18 @@ else() set(GTEST_LIBS_TO_LINK ${GTEST_BOTH_LIBRARIES} Threads::Threads) endif() -add_executable(bp2d_tests test.cpp - ../tools/svgtools.hpp -# ../tools/libnfpglue.hpp -# ../tools/libnfpglue.cpp - printer_parts.h - printer_parts.cpp - ${LIBNEST2D_SRCFILES} - ) -target_link_libraries(bp2d_tests ${LIBNEST2D_LIBRARIES} ${GTEST_LIBS_TO_LINK} ) +add_executable(tests_clipper_nlopt + test.cpp + ../tools/svgtools.hpp +# ../tools/libnfpglue.hpp +# ../tools/libnfpglue.cpp + printer_parts.h + printer_parts.cpp +) -target_include_directories(bp2d_tests PRIVATE BEFORE ${LIBNEST2D_HEADERS} - ${GTEST_INCLUDE_DIRS}) +target_link_libraries(tests_clipper_nlopt libnest2d ${GTEST_LIBS_TO_LINK} ) -add_test(libnest2d_tests bp2d_tests) +target_include_directories(tests_clipper_nlopt PRIVATE BEFORE + ${GTEST_INCLUDE_DIRS}) + +add_test(libnest2d_tests tests_clipper_nlopt) diff --git a/src/libnest2d/tests/test.cpp b/src/libnest2d/tests/test.cpp index 323fb8d31e..1c4daf4af3 100644 --- a/src/libnest2d/tests/test.cpp +++ b/src/libnest2d/tests/test.cpp @@ -4,6 +4,7 @@ #include #include "printer_parts.h" #include +#include "../tools/svgtools.hpp" //#include "../tools/libnfpglue.hpp" //#include "../tools/nfp_svgnest_glue.hpp" @@ -125,7 +126,7 @@ TEST(GeometryAlgorithms, boundingCircle) { c = boundingCircle(part.transformedShape()); if(std::isnan(c.radius())) std::cout << "fail: radius is nan" << std::endl; - else for(auto v : shapelike::getContour(part.transformedShape()) ) { + else for(auto v : shapelike::contour(part.transformedShape()) ) { auto d = pointlike::distance(v, c.center()); if(d > c.radius() ) { auto e = std::abs( 1.0 - d/c.radius()); @@ -791,10 +792,55 @@ TEST(GeometryAlgorithms, nfpConvexConvex) { TEST(GeometryAlgorithms, nfpConcaveConcave) { using namespace libnest2d; -// Rectangle r1(10, 10); -// Rectangle r2(20, 20); -// auto result = Nfp::nfpSimpleSimple(r1.transformedShape(), -// r2.transformedShape()); + Item stationary = { + { + {207, 76}, + {194, 117}, + {206, 117}, + {206, 104}, + {218, 104}, + {231, 117}, + {231, 130}, + {244, 130}, + {230, 92}, + {220, 92}, + {220, 84}, + {239, 76}, + {207, 76} + }, + {} + }; + + Item orbiter = { + { + {78, 76}, + {90, 89}, + {76, 124}, + {101, 124}, + {101, 100}, + {141, 113}, + {141, 124}, + {168, 124}, + {158, 115}, + {158, 104}, + {121, 88}, + {121, 76}, + {78, 76} + }, + {} + }; + + Rectangle r1(10, 10); + Rectangle r2(20, 20); + auto result = nfp::nfpSimpleSimple(stationary.transformedShape(), + orbiter.transformedShape()); + + svg::SVGWriter::Config conf; + conf.mm_in_coord_units = 1; + svg::SVGWriter wr(conf); + wr.writeItem(Item(result.first)); + wr.save("simplesimple.svg"); + } TEST(GeometryAlgorithms, pointOnPolygonContour) { diff --git a/src/libnest2d/tools/benchmark.h b/src/libnest2d/tools/benchmark.h deleted file mode 100644 index 19870b37b1..0000000000 --- a/src/libnest2d/tools/benchmark.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) Tamás Mészáros - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -#ifndef INCLUDE_BENCHMARK_H_ -#define INCLUDE_BENCHMARK_H_ - -#include -#include - -/** - * A class for doing benchmarks. - */ -class Benchmark { - typedef std::chrono::high_resolution_clock Clock; - typedef Clock::duration Duration; - typedef Clock::time_point TimePoint; - - TimePoint t1, t2; - Duration d; - - inline double to_sec(Duration d) { - return d.count() * double(Duration::period::num) / Duration::period::den; - } - -public: - - /** - * Measure time from the moment of this call. - */ - void start() { t1 = Clock::now(); } - - /** - * Measure time to the moment of this call. - */ - void stop() { t2 = Clock::now(); } - - /** - * Get the time elapsed between a start() end a stop() call. - * @return Returns the elapsed time in seconds. - */ - double getElapsedSec() { d = t2 - t1; return to_sec(d); } -}; - - -#endif /* INCLUDE_BENCHMARK_H_ */ diff --git a/src/libnest2d/tools/libnfpglue.cpp b/src/libnest2d/tools/libnfpglue.cpp deleted file mode 100644 index 31733acf97..0000000000 --- a/src/libnest2d/tools/libnfpglue.cpp +++ /dev/null @@ -1,157 +0,0 @@ -//#ifndef NDEBUG -//#define NFP_DEBUG -//#endif - -#include "libnfpglue.hpp" -#include "tools/libnfporb/libnfporb.hpp" - -namespace libnest2d { - -namespace { -inline bool vsort(const libnfporb::point_t& v1, const libnfporb::point_t& v2) -{ - using Coord = libnfporb::coord_t; - Coord x1 = v1.x_, x2 = v2.x_, y1 = v1.y_, y2 = v2.y_; - auto diff = y1 - y2; -#ifdef LIBNFP_USE_RATIONAL - long double diffv = diff.convert_to(); -#else - long double diffv = diff.val(); -#endif - if(std::abs(diffv) <= - std::numeric_limits::epsilon()) - return x1 < x2; - - return diff < 0; -} - -TCoord getX(const libnfporb::point_t& p) { -#ifdef LIBNFP_USE_RATIONAL - return p.x_.convert_to>(); -#else - return static_cast>(std::round(p.x_.val())); -#endif -} - -TCoord getY(const libnfporb::point_t& p) { -#ifdef LIBNFP_USE_RATIONAL - return p.y_.convert_to>(); -#else - return static_cast>(std::round(p.y_.val())); -#endif -} - -libnfporb::point_t scale(const libnfporb::point_t& p, long double factor) { -#ifdef LIBNFP_USE_RATIONAL - auto px = p.x_.convert_to(); - auto py = p.y_.convert_to(); -#else - long double px = p.x_.val(); - long double py = p.y_.val(); -#endif - return {px*factor, py*factor}; -} - -} - -NfpR _nfp(const PolygonImpl &sh, const PolygonImpl &cother) -{ - namespace sl = shapelike; - - NfpR ret; - - try { - libnfporb::polygon_t pstat, porb; - - boost::geometry::convert(sh, pstat); - boost::geometry::convert(cother, porb); - - long double factor = 0.0000001;//libnfporb::NFP_EPSILON; - long double refactor = 1.0/factor; - - for(auto& v : pstat.outer()) v = scale(v, factor); -// std::string message; -// boost::geometry::is_valid(pstat, message); -// std::cout << message << std::endl; - for(auto& h : pstat.inners()) for(auto& v : h) v = scale(v, factor); - - for(auto& v : porb.outer()) v = scale(v, factor); -// message; -// boost::geometry::is_valid(porb, message); -// std::cout << message << std::endl; - for(auto& h : porb.inners()) for(auto& v : h) v = scale(v, factor); - - - // this can throw - auto nfp = libnfporb::generateNFP(pstat, porb, true); - - auto &ct = sl::getContour(ret.first); - ct.reserve(nfp.front().size()+1); - for(auto v : nfp.front()) { - v = scale(v, refactor); - ct.emplace_back(getX(v), getY(v)); - } - ct.push_back(ct.front()); - std::reverse(ct.begin(), ct.end()); - - auto &rholes = sl::holes(ret.first); - for(size_t hidx = 1; hidx < nfp.size(); ++hidx) { - if(nfp[hidx].size() >= 3) { - rholes.emplace_back(); - auto& h = rholes.back(); - h.reserve(nfp[hidx].size()+1); - - for(auto& v : nfp[hidx]) { - v = scale(v, refactor); - h.emplace_back(getX(v), getY(v)); - } - h.push_back(h.front()); - std::reverse(h.begin(), h.end()); - } - } - - ret.second = nfp::referenceVertex(ret.first); - - } catch(std::exception& e) { - std::cout << "Error: " << e.what() << "\nTrying with convex hull..." << std::endl; -// auto ch_stat = ShapeLike::convexHull(sh); -// auto ch_orb = ShapeLike::convexHull(cother); - ret = nfp::nfpConvexOnly(sh, cother); - } - - return ret; -} - -NfpR nfp::NfpImpl::operator()( - const PolygonImpl &sh, const ClipperLib::PolygonImpl &cother) -{ - return _nfp(sh, cother);//nfpConvexOnly(sh, cother); -} - -NfpR nfp::NfpImpl::operator()( - const PolygonImpl &sh, const ClipperLib::PolygonImpl &cother) -{ - return _nfp(sh, cother); -} - -NfpR nfp::NfpImpl::operator()( - const PolygonImpl &sh, const ClipperLib::PolygonImpl &cother) -{ - return _nfp(sh, cother); -} - -//PolygonImpl -//Nfp::NfpImpl::operator()( -// const PolygonImpl &sh, const ClipperLib::PolygonImpl &cother) -//{ -// return _nfp(sh, cother); -//} - -//PolygonImpl -//Nfp::NfpImpl::operator()( -// const PolygonImpl &sh, const ClipperLib::PolygonImpl &cother) -//{ -// return _nfp(sh, cother); -//} - -} diff --git a/src/libnest2d/tools/libnfpglue.hpp b/src/libnest2d/tools/libnfpglue.hpp deleted file mode 100644 index 1ff033cb92..0000000000 --- a/src/libnest2d/tools/libnfpglue.hpp +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef LIBNFPGLUE_HPP -#define LIBNFPGLUE_HPP - -#include - -namespace libnest2d { - -using NfpR = nfp::NfpResult; - -NfpR _nfp(const PolygonImpl& sh, const PolygonImpl& cother); - -template<> -struct nfp::NfpImpl { - NfpR operator()(const PolygonImpl& sh, const PolygonImpl& cother); -}; - -template<> -struct nfp::NfpImpl { - NfpR operator()(const PolygonImpl& sh, const PolygonImpl& cother); -}; - -template<> -struct nfp::NfpImpl { - NfpR operator()(const PolygonImpl& sh, const PolygonImpl& cother); -}; - -//template<> -//struct Nfp::NfpImpl { -// NfpResult operator()(const PolygonImpl& sh, const PolygonImpl& cother); -//}; - -//template<> -//struct Nfp::NfpImpl { -// NfpResult operator()(const PolygonImpl& sh, const PolygonImpl& cother); -//}; - -template<> struct nfp::MaxNfpLevel { - static const BP2D_CONSTEXPR NfpLevel value = -// NfpLevel::CONVEX_ONLY; - NfpLevel::BOTH_CONCAVE; -}; - -} - - -#endif // LIBNFPGLUE_HPP diff --git a/src/libnest2d/tools/libnfporb/LICENSE b/src/libnest2d/tools/libnfporb/LICENSE deleted file mode 100644 index 94a9ed024d..0000000000 --- a/src/libnest2d/tools/libnfporb/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/src/libnest2d/tools/libnfporb/ORIGIN b/src/libnest2d/tools/libnfporb/ORIGIN deleted file mode 100644 index 788bfd9af2..0000000000 --- a/src/libnest2d/tools/libnfporb/ORIGIN +++ /dev/null @@ -1,2 +0,0 @@ -https://github.com/kallaballa/libnfp.git -commit hash a5cf9f6a76ddab95567fccf629d4d099b60237d7 \ No newline at end of file diff --git a/src/libnest2d/tools/libnfporb/README.md b/src/libnest2d/tools/libnfporb/README.md deleted file mode 100644 index 9698972be4..0000000000 --- a/src/libnest2d/tools/libnfporb/README.md +++ /dev/null @@ -1,89 +0,0 @@ -[![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0.en.html) -##### If you give me a real good reason i might be willing to give you permission to use it under a different license for a specific application. Real good reasons include the following (non-exhausive): the greater good, educational purpose and money :) - -# libnfporb -Implementation of a robust no-fit polygon generation in a C++ library using an orbiting approach. - -__Please note:__ The paper this implementation is based it on has several bad assumptions that required me to "improvise". That means the code doesn't reflect the paper anymore and is running way slower than expected. At the moment I'm working on implementing a new approach based on this paper (using minkowski sums): https://eprints.soton.ac.uk/36850/1/CORMSIS-05-05.pdf - -## Description - -The no-fit polygon optimization makes it possible to check for overlap (or non-overlapping touch) of two polygons with only 1 point in polygon check (by providing the set of non-overlapping placements). -This library implements the orbiting approach to generate the no-fit polygon: Given two polygons A and B, A is the stationary one and B the orbiting one, B is slid as tightly as possibly around the edges of polygon A. During the orbiting a chosen reference point is tracked. By tracking the movement of the reference point a third polygon can be generated: the no-fit polygon. - -Once the no-fit polygon has been generated it can be used to test for overlap by only checking if the reference point is inside the NFP (overlap) outside the NFP (no overlap) or exactly on the edge of the NFP (touch). - -### Examples: - -The polygons: - -![Start of NFP](/images/start.png?raw=true) - -Orbiting: - -![State 1](/images/next0.png?raw=true) -![State 2](/images/next1.png?raw=true) -![State 3](/images/next2.png?raw=true) -![State 4](/images/next3.png?raw=true) - -![State 5](/images/next4.png?raw=true) -![State 6](/images/next5.png?raw=true) -![State 7](/images/next6.png?raw=true) -![State 8](/images/next7.png?raw=true) - -![State 9](/images/next8.png?raw=true) - -The resulting NFP is red: - -![nfp](/images/nfp.png?raw=true) - -Polygons can have concavities, holes, interlocks or might fit perfectly: - -![concavities](/images/concavities.png?raw=true) -![hole](/images/hole.png?raw=true) -![interlock](/images/interlock.png?raw=true) -![jigsaw](/images/jigsaw.png?raw=true) - -## The Approach -The approch of this library is highly inspired by the scientific paper [Complete and robust no-fit polygon generation -for the irregular stock cutting problem](https://pdfs.semanticscholar.org/e698/0dd78306ba7d5bb349d20c6d8f2e0aa61062.pdf) and by [Svgnest](http://svgnest.com) - -Note that is wasn't completely possible to implement it as suggested in the paper because it had several shortcomings that prevent complete NFP generation on some of my test cases. Especially the termination criteria (reference point returns to first point of NFP) proved to be wrong (see: test-case rect). Also tracking of used edges can't be performed as suggested in the paper since there might be situations where no edge of A is traversed (see: test-case doublecon). - -By default the library is using floating point as coordinate type but by defining the flag "LIBNFP_USE_RATIONAL" the library can be instructed to use infinite precision. - -## Build -The library has two dependencies: [Boost Geometry](http://www.boost.org/doc/libs/1_65_1/libs/geometry/doc/html/index.html) and [libgmp](https://gmplib.org). You need to install those first before building. Note that building is only required for the examples. The library itself is header-only. - - git clone https://github.com/kallaballa/libnfp.git - cd libnfp - make - sudo make install - -## Code Example - -```c++ -//uncomment next line to use infinite precision (slow) -//#define LIBNFP_USE_RATIONAL -#include "../src/libnfp.hpp" - -int main(int argc, char** argv) { - using namespace libnfp; - polygon_t pA; - polygon_t pB; - //read polygons from wkt files - read_wkt_polygon(argv[1], pA); - read_wkt_polygon(argv[2], pB); - - //generate NFP of polygon A and polygon B and check the polygons for validity. - //When the third parameters is false validity check is skipped for a little performance increase - nfp_t nfp = generateNFP(pA, pB, true); - - //write a svg containing pA, pB and NFP - write_svg("nfp.svg",{pA,pB},nfp); - return 0; -} -``` -Run the example program: - - examples/nfp data/crossing/A.wkt data/crossing/B.wkt diff --git a/src/libnest2d/tools/libnfporb/libnfporb.hpp b/src/libnest2d/tools/libnfporb/libnfporb.hpp deleted file mode 100644 index 8cb34567eb..0000000000 --- a/src/libnest2d/tools/libnfporb/libnfporb.hpp +++ /dev/null @@ -1,1547 +0,0 @@ -#ifndef NFP_HPP_ -#define NFP_HPP_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(_MSC_VER) && _MSC_VER <= 1800 || __cplusplus < 201103L - #define LIBNFP_NOEXCEPT - #define LIBNFP_CONSTEXPR -#elif __cplusplus >= 201103L - #define LIBNFP_NOEXCEPT noexcept - #define LIBNFP_CONSTEXPR constexpr -#endif - -#ifdef LIBNFP_USE_RATIONAL -#include -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef LIBNFP_USE_RATIONAL -namespace bm = boost::multiprecision; -#endif -namespace bg = boost::geometry; -namespace trans = boost::geometry::strategy::transform; - - -namespace libnfporb { -#ifdef NFP_DEBUG -#define DEBUG_VAL(x) std::cerr << x << std::endl; -#define DEBUG_MSG(title, value) std::cerr << title << ":" << value << std::endl; -#else -#define DEBUG_VAL(x) -#define DEBUG_MSG(title, value) -#endif - -using std::string; - -static LIBNFP_CONSTEXPR long double NFP_EPSILON=0.00000001; - -class LongDouble { -private: - long double val_; -public: - LongDouble() : val_(0) { - } - - LongDouble(const long double& val) : val_(val) { - } - - void setVal(const long double& v) { - val_ = v; - } - - long double val() const { - return val_; - } - - LongDouble operator/(const LongDouble& other) const { - return this->val_ / other.val_; - } - - LongDouble operator*(const LongDouble& other) const { - return this->val_ * other.val_; - } - - LongDouble operator-(const LongDouble& other) const { - return this->val_ - other.val_; - } - - LongDouble operator-() const { - return this->val_ * -1; - } - - LongDouble operator+(const LongDouble& other) const { - return this->val_ + other.val_; - } - - void operator/=(const LongDouble& other) { - this->val_ = this->val_ / other.val_; - } - - void operator*=(const LongDouble& other) { - this->val_ = this->val_ * other.val_; - } - - void operator-=(const LongDouble& other) { - this->val_ = this->val_ - other.val_; - } - - void operator+=(const LongDouble& other) { - this->val_ = this->val_ + other.val_; - } - - bool operator==(const int& other) const { - return this->operator ==(static_cast(other)); - } - - bool operator==(const LongDouble& other) const { - return this->operator ==(other.val()); - } - - bool operator==(const long double& other) const { - return this->val() == other; - } - - bool operator!=(const int& other) const { - return !this->operator ==(other); - } - - bool operator!=(const LongDouble& other) const { - return !this->operator ==(other); - } - - bool operator!=(const long double& other) const { - return !this->operator ==(other); - } - - bool operator<(const int& other) const { - return this->operator <(static_cast(other)); - } - - bool operator<(const LongDouble& other) const { - return this->operator <(other.val()); - } - - bool operator<(const long double& other) const { - return this->val() < other; - } - - bool operator>(const int& other) const { - return this->operator >(static_cast(other)); - } - - bool operator>(const LongDouble& other) const { - return this->operator >(other.val()); - } - - bool operator>(const long double& other) const { - return this->val() > other; - } - - bool operator>=(const int& other) const { - return this->operator >=(static_cast(other)); - } - - bool operator>=(const LongDouble& other) const { - return this->operator >=(other.val()); - } - - bool operator>=(const long double& other) const { - return this->val() >= other; - } - - bool operator<=(const int& other) const { - return this->operator <=(static_cast(other)); - } - - bool operator<=(const LongDouble& other) const { - return this->operator <=(other.val()); - } - - bool operator<=(const long double& other) const { - return this->val() <= other; - } -}; -} - - -namespace std { -template<> - struct numeric_limits - { - static const LIBNFP_CONSTEXPR bool is_specialized = true; - - static const LIBNFP_CONSTEXPR long double - min() LIBNFP_NOEXCEPT { return std::numeric_limits::min(); } - - static LIBNFP_CONSTEXPR long double - max() LIBNFP_NOEXCEPT { return std::numeric_limits::max(); } - -#if __cplusplus >= 201103L - static LIBNFP_CONSTEXPR long double - lowest() LIBNFP_NOEXCEPT { return -std::numeric_limits::lowest(); } -#endif - - static const LIBNFP_CONSTEXPR int digits = std::numeric_limits::digits; - static const LIBNFP_CONSTEXPR int digits10 = std::numeric_limits::digits10; -#if __cplusplus >= 201103L - static const LIBNFP_CONSTEXPR int max_digits10 - = std::numeric_limits::max_digits10; -#endif - static const LIBNFP_CONSTEXPR bool is_signed = true; - static const LIBNFP_CONSTEXPR bool is_integer = false; - static const LIBNFP_CONSTEXPR bool is_exact = false; - static const LIBNFP_CONSTEXPR int radix = std::numeric_limits::radix; - - static const LIBNFP_CONSTEXPR long double - epsilon() LIBNFP_NOEXCEPT { return libnfporb::NFP_EPSILON; } - - static const LIBNFP_CONSTEXPR long double - round_error() LIBNFP_NOEXCEPT { return 0.5L; } - - static const LIBNFP_CONSTEXPR int min_exponent = std::numeric_limits::min_exponent; - static const LIBNFP_CONSTEXPR int min_exponent10 = std::numeric_limits::min_exponent10; - static const LIBNFP_CONSTEXPR int max_exponent = std::numeric_limits::max_exponent; - static const LIBNFP_CONSTEXPR int max_exponent10 = std::numeric_limits::max_exponent10; - - - static const LIBNFP_CONSTEXPR bool has_infinity = std::numeric_limits::has_infinity; - static const LIBNFP_CONSTEXPR bool has_quiet_NaN = std::numeric_limits::has_quiet_NaN; - static const LIBNFP_CONSTEXPR bool has_signaling_NaN = has_quiet_NaN; - static const LIBNFP_CONSTEXPR float_denorm_style has_denorm - = std::numeric_limits::has_denorm; - static const LIBNFP_CONSTEXPR bool has_denorm_loss - = std::numeric_limits::has_denorm_loss; - - - static const LIBNFP_CONSTEXPR long double - infinity() LIBNFP_NOEXCEPT { return std::numeric_limits::infinity(); } - - static const LIBNFP_CONSTEXPR long double - quiet_NaN() LIBNFP_NOEXCEPT { return std::numeric_limits::quiet_NaN(); } - - static const LIBNFP_CONSTEXPR long double - signaling_NaN() LIBNFP_NOEXCEPT { return std::numeric_limits::signaling_NaN(); } - - - static const LIBNFP_CONSTEXPR long double - denorm_min() LIBNFP_NOEXCEPT { return std::numeric_limits::denorm_min(); } - - static const LIBNFP_CONSTEXPR bool is_iec559 - = has_infinity && has_quiet_NaN && has_denorm == denorm_present; - - static const LIBNFP_CONSTEXPR bool is_bounded = true; - static const LIBNFP_CONSTEXPR bool is_modulo = false; - - static const LIBNFP_CONSTEXPR bool traps = std::numeric_limits::traps; - static const LIBNFP_CONSTEXPR bool tinyness_before = - std::numeric_limits::tinyness_before; - static const LIBNFP_CONSTEXPR float_round_style round_style = - round_to_nearest; - }; -} - -namespace boost { -namespace numeric { - template<> - struct raw_converter> - { - typedef boost::numeric::conversion_traits::result_type result_type ; - typedef boost::numeric::conversion_traits::argument_type argument_type ; - - static result_type low_level_convert ( argument_type s ) { return s.val() ; } - } ; -} -} - -namespace libnfporb { - -#ifndef LIBNFP_USE_RATIONAL -typedef LongDouble coord_t; -#else -typedef bm::number rational_t; -typedef rational_t coord_t; -#endif - -bool equals(const LongDouble& lhs, const LongDouble& rhs); -#ifdef LIBNFP_USE_RATIONAL -bool equals(const rational_t& lhs, const rational_t& rhs); -#endif -bool equals(const long double& lhs, const long double& rhs); - -const coord_t MAX_COORD = 999999999999999999.0; -const coord_t MIN_COORD = std::numeric_limits::min(); - -class point_t { -public: - point_t() : x_(0), y_(0) { - } - point_t(coord_t x, coord_t y) : x_(x), y_(y) { - } - bool marked_ = false; - coord_t x_; - coord_t y_; - - point_t operator-(const point_t& other) const { - point_t result = *this; - bg::subtract_point(result, other); - return result; - } - - point_t operator+(const point_t& other) const { - point_t result = *this; - bg::add_point(result, other); - return result; - } - - bool operator==(const point_t& other) const { - return bg::equals(this, other); - } - - bool operator!=(const point_t& other) const { - return !this->operator ==(other); - } - - bool operator<(const point_t& other) const { - return boost::geometry::math::smaller(this->x_, other.x_) || (equals(this->x_, other.x_) && boost::geometry::math::smaller(this->y_, other.y_)); - } -}; - - - - -inline long double toLongDouble(const LongDouble& c) { - return c.val(); -} - -#ifdef LIBNFP_USE_RATIONAL -inline long double toLongDouble(const rational_t& c) { - return bm::numerator(c).convert_to() / bm::denominator(c).convert_to(); -} -#endif - -std::ostream& operator<<(std::ostream& os, const coord_t& p) { - os << toLongDouble(p); - return os; -} - -std::istream& operator>>(std::istream& is, LongDouble& c) { - long double val; - is >> val; - c.setVal(val); - return is; -} - -std::ostream& operator<<(std::ostream& os, const point_t& p) { - os << "{" << toLongDouble(p.x_) << "," << toLongDouble(p.y_) << "}"; - return os; -} -const point_t INVALID_POINT = {MAX_COORD, MAX_COORD}; - -typedef bg::model::segment segment_t; -} - -#ifdef LIBNFP_USE_RATIONAL -inline long double acos(const libnfporb::rational_t& r) { - return acos(libnfporb::toLongDouble(r)); -} -#endif - -inline long double acos(const libnfporb::LongDouble& ld) { - return acos(libnfporb::toLongDouble(ld)); -} - -#ifdef LIBNFP_USE_RATIONAL -inline long double sqrt(const libnfporb::rational_t& r) { - return sqrt(libnfporb::toLongDouble(r)); -} -#endif - -inline long double sqrt(const libnfporb::LongDouble& ld) { - return sqrt(libnfporb::toLongDouble(ld)); -} - -BOOST_GEOMETRY_REGISTER_POINT_2D(libnfporb::point_t, libnfporb::coord_t, cs::cartesian, x_, y_) - - -namespace boost { -namespace geometry { -namespace math { -namespace detail { - -template <> -struct square_root -{ - typedef libnfporb::LongDouble return_type; - - static inline libnfporb::LongDouble apply(libnfporb::LongDouble const& a) - { - return std::sqrt(a.val()); - } -}; - -#ifdef LIBNFP_USE_RATIONAL -template <> -struct square_root -{ - typedef libnfporb::rational_t return_type; - - static inline libnfporb::rational_t apply(libnfporb::rational_t const& a) - { - return std::sqrt(libnfporb::toLongDouble(a)); - } -}; -#endif - -template<> -struct abs - { - static libnfporb::LongDouble apply(libnfporb::LongDouble const& value) - { - libnfporb::LongDouble const zero = libnfporb::LongDouble(); - return value.val() < zero.val() ? -value.val() : value.val(); - } - }; - -template <> -struct equals -{ - template - static inline bool apply(libnfporb::LongDouble const& lhs, libnfporb::LongDouble const& rhs, Policy const& policy) - { - if(lhs.val() == rhs.val()) - return true; - - return bg::math::detail::abs::apply(lhs.val() - rhs.val()) <= policy.apply(lhs.val(), rhs.val()) * libnfporb::NFP_EPSILON; - } -}; - -template <> -struct smaller -{ - static inline bool apply(libnfporb::LongDouble const& lhs, libnfporb::LongDouble const& rhs) - { - if(lhs.val() == rhs.val() || bg::math::detail::abs::apply(lhs.val() - rhs.val()) <= libnfporb::NFP_EPSILON * std::max(lhs.val(), rhs.val())) - return false; - - return lhs < rhs; - } -}; -} -} -} -} - -namespace libnfporb { -inline bool smaller(const LongDouble& lhs, const LongDouble& rhs) { - return boost::geometry::math::detail::smaller::apply(lhs, rhs); -} - -inline bool larger(const LongDouble& lhs, const LongDouble& rhs) { - return smaller(rhs, lhs); -} - -bool equals(const LongDouble& lhs, const LongDouble& rhs) { - if(lhs.val() == rhs.val()) - return true; - - return bg::math::detail::abs::apply(lhs.val() - rhs.val()) <= libnfporb::NFP_EPSILON * std::max(lhs.val(), rhs.val()); -} - -#ifdef LIBNFP_USE_RATIONAL -inline bool smaller(const rational_t& lhs, const rational_t& rhs) { - return lhs < rhs; -} - -inline bool larger(const rational_t& lhs, const rational_t& rhs) { - return smaller(rhs, lhs); -} - -bool equals(const rational_t& lhs, const rational_t& rhs) { - return lhs == rhs; -} -#endif - -inline bool smaller(const long double& lhs, const long double& rhs) { - return lhs < rhs; -} - -inline bool larger(const long double& lhs, const long double& rhs) { - return smaller(rhs, lhs); -} - - -bool equals(const long double& lhs, const long double& rhs) { - return lhs == rhs; -} - -typedef bg::model::polygon polygon_t; -typedef std::vector nfp_t; -typedef bg::model::linestring linestring_t; - -typedef polygon_t::ring_type::size_type psize_t; - -typedef bg::model::d2::point_xy pointf_t; -typedef bg::model::segment segmentf_t; -typedef bg::model::polygon polygonf_t; - -polygonf_t::ring_type convert(const polygon_t::ring_type& r) { - polygonf_t::ring_type rf; - for(const auto& pt : r) { - rf.push_back(pointf_t(toLongDouble(pt.x_), toLongDouble(pt.y_))); - } - return rf; -} - -polygonf_t convert(polygon_t p) { - polygonf_t pf; - pf.outer() = convert(p.outer()); - - for(const auto& r : p.inners()) { - pf.inners().push_back(convert(r)); - } - - return pf; -} - -polygon_t nfpRingsToNfpPoly(const nfp_t& nfp) { - polygon_t nfppoly; - for (const auto& pt : nfp.front()) { - nfppoly.outer().push_back(pt); - } - - for (size_t i = 1; i < nfp.size(); ++i) { - nfppoly.inners().push_back({}); - for (const auto& pt : nfp[i]) { - nfppoly.inners().back().push_back(pt); - } - } - - return nfppoly; -} - -void write_svg(std::string const& filename,const std::vector& segments) { - std::ofstream svg(filename.c_str()); - - boost::geometry::svg_mapper mapper(svg, 100, 100, "width=\"200mm\" height=\"200mm\" viewBox=\"-250 -250 500 500\""); - for(const auto& seg : segments) { - segmentf_t segf({toLongDouble(seg.first.x_), toLongDouble(seg.first.y_)}, {toLongDouble(seg.second.x_), toLongDouble(seg.second.y_)}); - mapper.add(segf); - mapper.map(segf, "fill-opacity:0.5;fill:rgb(153,204,0);stroke:rgb(153,204,0);stroke-width:2"); - } -} - -void write_svg(std::string const& filename, const polygon_t& p, const polygon_t::ring_type& ring) { - std::ofstream svg(filename.c_str()); - - boost::geometry::svg_mapper mapper(svg, 100, 100, "width=\"200mm\" height=\"200mm\" viewBox=\"-250 -250 500 500\""); - auto pf = convert(p); - auto rf = convert(ring); - - mapper.add(pf); - mapper.map(pf, "fill-opacity:0.5;fill:rgb(153,204,0);stroke:rgb(153,204,0);stroke-width:2"); - mapper.add(rf); - mapper.map(rf, "fill-opacity:0.5;fill:rgb(153,204,0);stroke:rgb(153,204,0);stroke-width:2"); -} - -void write_svg(std::string const& filename, std::vector const& polygons) { - std::ofstream svg(filename.c_str()); - - boost::geometry::svg_mapper mapper(svg, 100, 100, "width=\"200mm\" height=\"200mm\" viewBox=\"-250 -250 500 500\""); - for (auto p : polygons) { - auto pf = convert(p); - mapper.add(pf); - mapper.map(pf, "fill-opacity:0.5;fill:rgb(153,204,0);stroke:rgb(153,204,0);stroke-width:2"); - } -} - -void write_svg(std::string const& filename, std::vector const& polygons, const nfp_t& nfp) { - polygon_t nfppoly; - for (const auto& pt : nfp.front()) { - nfppoly.outer().push_back(pt); - } - - for (size_t i = 1; i < nfp.size(); ++i) { - nfppoly.inners().push_back({}); - for (const auto& pt : nfp[i]) { - nfppoly.inners().back().push_back(pt); - } - } - std::ofstream svg(filename.c_str()); - - boost::geometry::svg_mapper mapper(svg, 100, 100, "width=\"200mm\" height=\"200mm\" viewBox=\"-250 -250 500 500\""); - for (auto p : polygons) { - auto pf = convert(p); - mapper.add(pf); - mapper.map(pf, "fill-opacity:0.5;fill:rgb(153,204,0);stroke:rgb(153,204,0);stroke-width:2"); - } - bg::correct(nfppoly); - auto nfpf = convert(nfppoly); - mapper.add(nfpf); - mapper.map(nfpf, "fill-opacity:0.5;fill:rgb(204,153,0);stroke:rgb(204,153,0);stroke-width:2"); - - for(auto& r: nfpf.inners()) { - if(r.size() == 1) { - mapper.add(r.front()); - mapper.map(r.front(), "fill-opacity:0.5;fill:rgb(204,153,0);stroke:rgb(204,153,0);stroke-width:2"); - } else if(r.size() == 2) { - segmentf_t seg(r.front(), *(r.begin()+1)); - mapper.add(seg); - mapper.map(seg, "fill-opacity:0.5;fill:rgb(204,153,0);stroke:rgb(204,153,0);stroke-width:2"); - } - } -} - -std::ostream& operator<<(std::ostream& os, const segment_t& seg) { - os << "{" << seg.first << "," << seg.second << "}"; - return os; -} - -bool operator<(const segment_t& lhs, const segment_t& rhs) { - return lhs.first < rhs.first || ((lhs.first == rhs.first) && (lhs.second < rhs.second)); -} - -bool operator==(const segment_t& lhs, const segment_t& rhs) { - return (lhs.first == rhs.first && lhs.second == rhs.second) || (lhs.first == rhs.second && lhs.second == rhs.first); -} - -bool operator!=(const segment_t& lhs, const segment_t& rhs) { - return !operator==(lhs,rhs); -} - -enum Alignment { - LEFT, - RIGHT, - ON -}; - -point_t normalize(const point_t& pt) { - point_t norm = pt; - coord_t len = bg::length(segment_t{{0,0},pt}); - - if(len == 0.0L) - return {0,0}; - - norm.x_ /= len; - norm.y_ /= len; - - return norm; -} - -Alignment get_alignment(const segment_t& seg, const point_t& pt){ - coord_t res = ((seg.second.x_ - seg.first.x_)*(pt.y_ - seg.first.y_) - - (seg.second.y_ - seg.first.y_)*(pt.x_ - seg.first.x_)); - - if(equals(res, 0)) { - return ON; - } else if(larger(res,0)) { - return LEFT; - } else { - return RIGHT; - } -} - -long double get_inner_angle(const point_t& joint, const point_t& end1, const point_t& end2) { - coord_t dx21 = end1.x_-joint.x_; - coord_t dx31 = end2.x_-joint.x_; - coord_t dy21 = end1.y_-joint.y_; - coord_t dy31 = end2.y_-joint.y_; - coord_t m12 = sqrt((dx21*dx21 + dy21*dy21)); - coord_t m13 = sqrt((dx31*dx31 + dy31*dy31)); - if(m12 == 0.0L || m13 == 0.0L) - return 0; - return acos( (dx21*dx31 + dy21*dy31) / (m12 * m13) ); -} - -struct TouchingPoint { - enum Type { - VERTEX, - A_ON_B, - B_ON_A - }; - Type type_; - psize_t A_; - psize_t B_; -}; - -struct TranslationVector { - point_t vector_; - segment_t edge_; - bool fromA_; - string name_; - - bool operator<(const TranslationVector& other) const { - return this->vector_ < other.vector_ || ((this->vector_ == other.vector_) && (this->edge_ < other.edge_)); - } -}; - -std::ostream& operator<<(std::ostream& os, const TranslationVector& tv) { - os << "{" << tv.edge_ << " -> " << tv.vector_ << "} = " << tv.name_; - return os; -} - - -void read_wkt_polygon(const string& filename, polygon_t& p) { - std::ifstream t(filename); - - std::string str; - t.seekg(0, std::ios::end); - str.reserve(t.tellg()); - t.seekg(0, std::ios::beg); - - str.assign((std::istreambuf_iterator(t)), - std::istreambuf_iterator()); - - str.pop_back(); - bg::read_wkt(str, p); - bg::correct(p); -} - -std::vector find_minimum_y(const polygon_t& p) { - std::vector result; - coord_t min = MAX_COORD; - auto& po = p.outer(); - for(psize_t i = 0; i < p.outer().size() - 1; ++i) { - if(smaller(po[i].y_, min)) { - result.clear(); - min = po[i].y_; - result.push_back(i); - } else if (equals(po[i].y_, min)) { - result.push_back(i); - } - } - return result; -} - -std::vector find_maximum_y(const polygon_t& p) { - std::vector result; - coord_t max = MIN_COORD; - auto& po = p.outer(); - for(psize_t i = 0; i < p.outer().size() - 1; ++i) { - if(larger(po[i].y_, max)) { - result.clear(); - max = po[i].y_; - result.push_back(i); - } else if (equals(po[i].y_, max)) { - result.push_back(i); - } - } - return result; -} - -psize_t find_point(const polygon_t::ring_type& ring, const point_t& pt) { - for(psize_t i = 0; i < ring.size(); ++i) { - if(ring[i] == pt) - return i; - } - return std::numeric_limits::max(); -} - -std::vector findTouchingPoints(const polygon_t::ring_type& ringA, const polygon_t::ring_type& ringB) { - std::vector touchers; - for(psize_t i = 0; i < ringA.size() - 1; i++) { - psize_t nextI = i+1; - for(psize_t j = 0; j < ringB.size() - 1; j++) { - psize_t nextJ = j+1; - if(ringA[i] == ringB[j]) { - touchers.push_back({TouchingPoint::VERTEX, i, j}); - } else if (ringA[nextI] != ringB[j] && bg::intersects(segment_t(ringA[i],ringA[nextI]), ringB[j])) { - touchers.push_back({TouchingPoint::B_ON_A, nextI, j}); - } else if (ringB[nextJ] != ringA[i] && bg::intersects(segment_t(ringB[j],ringB[nextJ]), ringA[i])) { - touchers.push_back({TouchingPoint::A_ON_B, i, nextJ}); - } - } - } - return touchers; -} - -//TODO deduplicate code -TranslationVector trimVector(const polygon_t::ring_type& rA, const polygon_t::ring_type& rB, const TranslationVector& tv) { - coord_t shortest = bg::length(tv.edge_); - TranslationVector trimmed = tv; - for(const auto& ptA : rA) { - point_t translated; - //for polygon A we invert the translation - trans::translate_transformer translate(-tv.vector_.x_, -tv.vector_.y_); - boost::geometry::transform(ptA, translated, translate); - linestring_t projection; - segment_t segproj(ptA, translated); - projection.push_back(ptA); - projection.push_back(translated); - std::vector intersections; - bg::intersection(rB, projection, intersections); - if(bg::touches(projection, rB) && intersections.size() < 2) { - continue; - } - - //find shortest intersection - coord_t len; - segment_t segi; - for(const auto& pti : intersections) { - segi = segment_t(ptA,pti); - len = bg::length(segi); - if(smaller(len, shortest)) { - trimmed.vector_ = ptA - pti; - trimmed.edge_ = segi; - shortest = len; - } - } - } - - for(const auto& ptB : rB) { - point_t translated; - - trans::translate_transformer translate(tv.vector_.x_, tv.vector_.y_); - boost::geometry::transform(ptB, translated, translate); - linestring_t projection; - segment_t segproj(ptB, translated); - projection.push_back(ptB); - projection.push_back(translated); - std::vector intersections; - bg::intersection(rA, projection, intersections); - if(bg::touches(projection, rA) && intersections.size() < 2) { - continue; - } - - //find shortest intersection - coord_t len; - segment_t segi; - for(const auto& pti : intersections) { - - segi = segment_t(ptB,pti); - len = bg::length(segi); - if(smaller(len, shortest)) { - trimmed.vector_ = pti - ptB; - trimmed.edge_ = segi; - shortest = len; - } - } - } - return trimmed; -} - -std::vector findFeasibleTranslationVectors(polygon_t::ring_type& ringA, polygon_t::ring_type& ringB, const std::vector& touchers) { - //use a set to automatically filter duplicate vectors - std::vector potentialVectors; - std::vector> touchEdges; - - for (psize_t i = 0; i < touchers.size(); i++) { - point_t& vertexA = ringA[touchers[i].A_]; - vertexA.marked_ = true; - - // adjacent A vertices - auto prevAindex = static_cast(touchers[i].A_ - 1); - auto nextAindex = static_cast(touchers[i].A_ + 1); - - prevAindex = (prevAindex < 0) ? static_cast(ringA.size() - 2) : prevAindex; // loop - nextAindex = (static_cast(nextAindex) >= ringA.size()) ? 1 : nextAindex; // loop - - point_t& prevA = ringA[prevAindex]; - point_t& nextA = ringA[nextAindex]; - - // adjacent B vertices - point_t& vertexB = ringB[touchers[i].B_]; - - auto prevBindex = static_cast(touchers[i].B_ - 1); - auto nextBindex = static_cast(touchers[i].B_ + 1); - - prevBindex = (prevBindex < 0) ? static_cast(ringB.size() - 2) : prevBindex; // loop - nextBindex = (static_cast(nextBindex) >= ringB.size()) ? 1 : nextBindex; // loop - - point_t& prevB = ringB[prevBindex]; - point_t& nextB = ringB[nextBindex]; - - if (touchers[i].type_ == TouchingPoint::VERTEX) { - segment_t a1 = { vertexA, nextA }; - segment_t a2 = { vertexA, prevA }; - segment_t b1 = { vertexB, nextB }; - segment_t b2 = { vertexB, prevB }; - - //swap the segment elements so that always the first point is the touching point - //also make the second segment always a segment of ringB - touchEdges.push_back({a1, b1}); - touchEdges.push_back({a1, b2}); - touchEdges.push_back({a2, b1}); - touchEdges.push_back({a2, b2}); -#ifdef NFP_DEBUG - write_svg("touchersV" + std::to_string(i) + ".svg", {a1,a2,b1,b2}); -#endif - - //TODO test parallel edges for floating point stability - Alignment al; - //a1 and b1 meet at start vertex - al = get_alignment(a1, b1.second); - if(al == LEFT) { - potentialVectors.push_back({b1.first - b1.second, b1, false, "vertex1"}); - } else if(al == RIGHT) { - potentialVectors.push_back({a1.second - a1.first, a1, true, "vertex2"}); - } else { - potentialVectors.push_back({a1.second - a1.first, a1, true, "vertex3"}); - } - - //a1 and b2 meet at start and end - al = get_alignment(a1, b2.second); - if(al == LEFT) { - //no feasible translation - } else if(al == RIGHT) { - potentialVectors.push_back({a1.second - a1.first, a1, true, "vertex4"}); - } else { - potentialVectors.push_back({a1.second - a1.first, a1, true, "vertex5"}); - } - - //a2 and b1 meet at end and start - al = get_alignment(a2, b1.second); - if(al == LEFT) { - //no feasible translation - } else if(al == RIGHT) { - potentialVectors.push_back({b1.first - b1.second, b1, false, "vertex6"}); - } else { - potentialVectors.push_back({b1.first - b1.second, b1, false, "vertex7"}); - } - } else if (touchers[i].type_ == TouchingPoint::B_ON_A) { - segment_t a1 = {vertexB, vertexA}; - segment_t a2 = {vertexB, prevA}; - segment_t b1 = {vertexB, prevB}; - segment_t b2 = {vertexB, nextB}; - - touchEdges.push_back({a1, b1}); - touchEdges.push_back({a1, b2}); - touchEdges.push_back({a2, b1}); - touchEdges.push_back({a2, b2}); -#ifdef NFP_DEBUG - write_svg("touchersB" + std::to_string(i) + ".svg", {a1,a2,b1,b2}); -#endif - potentialVectors.push_back({vertexA - vertexB, {vertexB, vertexA}, true, "bona"}); - } else if (touchers[i].type_ == TouchingPoint::A_ON_B) { - //TODO testme - segment_t a1 = {vertexA, prevA}; - segment_t a2 = {vertexA, nextA}; - segment_t b1 = {vertexA, vertexB}; - segment_t b2 = {vertexA, prevB}; -#ifdef NFP_DEBUG - write_svg("touchersA" + std::to_string(i) + ".svg", {a1,a2,b1,b2}); -#endif - touchEdges.push_back({a1, b1}); - touchEdges.push_back({a2, b1}); - touchEdges.push_back({a1, b2}); - touchEdges.push_back({a2, b2}); - potentialVectors.push_back({vertexA - vertexB, {vertexA, vertexB}, false, "aonb"}); - } - } - - //discard immediately intersecting translations - std::vector vectors; - for(const auto& v : potentialVectors) { - bool discarded = false; - for(const auto& sp : touchEdges) { - point_t normEdge = normalize(v.edge_.second - v.edge_.first); - point_t normFirst = normalize(sp.first.second - sp.first.first); - point_t normSecond = normalize(sp.second.second - sp.second.first); - - Alignment a1 = get_alignment({{0,0},normEdge}, normFirst); - Alignment a2 = get_alignment({{0,0},normEdge}, normSecond); - - if(a1 == a2 && a1 != ON) { - long double df = get_inner_angle({0,0},normEdge, normFirst); - long double ds = get_inner_angle({0,0},normEdge, normSecond); - - point_t normIn = normalize(v.edge_.second - v.edge_.first); - if (equals(df, ds)) { - TranslationVector trimmed = trimVector(ringA,ringB, v); - polygon_t::ring_type translated; - trans::translate_transformer translate(trimmed.vector_.x_, trimmed.vector_.y_); - boost::geometry::transform(ringB, translated, translate); - if (!(bg::intersects(translated, ringA) && !bg::overlaps(translated, ringA) && !bg::covered_by(translated, ringA) && !bg::covered_by(ringA, translated))) { - discarded = true; - break; - } - } else { - - if (normIn == normalize(v.vector_)) { - if (larger(ds, df)) { - discarded = true; - break; - } - } else { - if (smaller(ds, df)) { - discarded = true; - break; - } - } - } - } - } - if(!discarded) - vectors.push_back(v); - } - return vectors; -} - -bool find(const std::vector& h, const TranslationVector& tv) { - for(const auto& htv : h) { - if(htv.vector_ == tv.vector_) - return true; - } - return false; -} - -TranslationVector getLongest(const std::vector& tvs) { - coord_t len; - coord_t maxLen = MIN_COORD; - TranslationVector longest; - longest.vector_ = INVALID_POINT; - - for(auto& tv : tvs) { - len = bg::length(segment_t{{0,0},tv.vector_}); - if(larger(len, maxLen)) { - maxLen = len; - longest = tv; - } - } - return longest; -} - -TranslationVector selectNextTranslationVector(const polygon_t& pA, const polygon_t::ring_type& rA, const polygon_t::ring_type& rB, const std::vector& tvs, const std::vector& history) { - if(!history.empty()) { - TranslationVector last = history.back(); - std::vector historyCopy = history; - if(historyCopy.size() >= 2) { - historyCopy.erase(historyCopy.end() - 1); - historyCopy.erase(historyCopy.end() - 1); - if(historyCopy.size() > 4) { - historyCopy.erase(historyCopy.begin(), historyCopy.end() - 4); - } - - } else { - historyCopy.clear(); - } - DEBUG_MSG("last", last); - - psize_t laterI = std::numeric_limits::max(); - point_t previous = rA[0]; - point_t next; - - if(last.fromA_) { - for (psize_t i = 1; i < rA.size() + 1; ++i) { - if (i >= rA.size()) - next = rA[i % rA.size()]; - else - next = rA[i]; - - segment_t candidate( previous, next ); - if(candidate == last.edge_) { - laterI = i; - break; - } - previous = next; - } - - if (laterI == std::numeric_limits::max()) { - point_t later; - if (last.vector_ == (last.edge_.second - last.edge_.first)) { - later = last.edge_.second; - } else { - later = last.edge_.first; - } - - laterI = find_point(rA, later); - } - } else { - point_t later; - if (last.vector_ == (last.edge_.second - last.edge_.first)) { - later = last.edge_.second; - } else { - later = last.edge_.first; - } - - laterI = find_point(rA, later); - } - - if (laterI == std::numeric_limits::max()) { - throw std::runtime_error( - "Internal error: Can't find later point of last edge"); - } - - std::vector viableEdges; - previous = rA[laterI]; - for(psize_t i = laterI + 1; i < rA.size() + laterI + 1; ++i) { - if(i >= rA.size()) - next = rA[i % rA.size()]; - else - next = rA[i]; - - viableEdges.push_back({previous, next}); - previous = next; - } - -// auto rng = std::default_random_engine {}; -// std::shuffle(std::begin(viableEdges), std::end(viableEdges), rng); - - //search with consulting the history to prevent oscillation - std::vector viableTrans; - for(const auto& ve: viableEdges) { - for(const auto& tv : tvs) { - if((tv.fromA_ && (normalize(tv.vector_) == normalize(ve.second - ve.first))) && (tv.edge_ != last.edge_ || tv.vector_.x_ != -last.vector_.x_ || tv.vector_.y_ != -last.vector_.y_) && !find(historyCopy, tv)) { - viableTrans.push_back(tv); - } - } - for (const auto& tv : tvs) { - if (!tv.fromA_) { - point_t later; - if (tv.vector_ == (tv.edge_.second - tv.edge_.first) && (tv.edge_ != last.edge_ || tv.vector_.x_ != -last.vector_.x_ || tv.vector_.y_ != -last.vector_.y_) && !find(historyCopy, tv)) { - later = tv.edge_.second; - } else if (tv.vector_ == (tv.edge_.first - tv.edge_.second)) { - later = tv.edge_.first; - } else - continue; - - if (later == ve.first || later == ve.second) { - viableTrans.push_back(tv); - } - } - } - } - - if(!viableTrans.empty()) - return getLongest(viableTrans); - - //search again without the history - for(const auto& ve: viableEdges) { - for(const auto& tv : tvs) { - if((tv.fromA_ && (normalize(tv.vector_) == normalize(ve.second - ve.first))) && (tv.edge_ != last.edge_ || tv.vector_.x_ != -last.vector_.x_ || tv.vector_.y_ != -last.vector_.y_)) { - viableTrans.push_back(tv); - } - } - for (const auto& tv : tvs) { - if (!tv.fromA_) { - point_t later; - if (tv.vector_ == (tv.edge_.second - tv.edge_.first) && (tv.edge_ != last.edge_ || tv.vector_.x_ != -last.vector_.x_ || tv.vector_.y_ != -last.vector_.y_)) { - later = tv.edge_.second; - } else if (tv.vector_ == (tv.edge_.first - tv.edge_.second)) { - later = tv.edge_.first; - } else - continue; - - if (later == ve.first || later == ve.second) { - viableTrans.push_back(tv); - } - } - } - } - if(!viableTrans.empty()) - return getLongest(viableTrans); - - /* - //search again without the history and without checking last edge - for(const auto& ve: viableEdges) { - for(const auto& tv : tvs) { - if((tv.fromA_ && (normalize(tv.vector_) == normalize(ve.second - ve.first)))) { - return tv; - } - } - for (const auto& tv : tvs) { - if (!tv.fromA_) { - point_t later; - if (tv.vector_ == (tv.edge_.second - tv.edge_.first)) { - later = tv.edge_.second; - } else if (tv.vector_ == (tv.edge_.first - tv.edge_.second)) { - later = tv.edge_.first; - } else - continue; - - if (later == ve.first || later == ve.second) { - return tv; - } - } - } - }*/ - - if(tvs.size() == 1) - return *tvs.begin(); - - TranslationVector tv; - tv.vector_ = INVALID_POINT; - return tv; - } else { - return getLongest(tvs); - } -} - -bool inNfp(const point_t& pt, const nfp_t& nfp) { - for(const auto& r : nfp) { - if(bg::touches(pt, r)) - return true; - } - - return false; -} - -enum SearchStartResult { - FIT, - FOUND, - NOT_FOUND -}; - -SearchStartResult searchStartTranslation(polygon_t::ring_type& rA, const polygon_t::ring_type& rB, const nfp_t& nfp,const bool& inside, point_t& result) { - for(psize_t i = 0; i < rA.size() - 1; i++) { - psize_t index; - if (i >= rA.size()) - index = i % rA.size() + 1; - else - index = i; - - auto& ptA = rA[index]; - - if(ptA.marked_) - continue; - - ptA.marked_ = true; - - for(const auto& ptB: rB) { - point_t testTranslation = ptA - ptB; - polygon_t::ring_type translated; - boost::geometry::transform(rB, translated, trans::translate_transformer(testTranslation.x_, testTranslation.y_)); - - //check if the translated rB is identical to rA - bool identical = false; - for(const auto& ptT: translated) { - identical = false; - for(const auto& ptA: rA) { - if(ptT == ptA) { - identical = true; - break; - } - } - if(!identical) - break; - } - - if(identical) { - result = testTranslation; - return FIT; - } - - bool bInside = false; - for(const auto& ptT: translated) { - if(bg::within(ptT, rA)) { - bInside = true; - break; - } else if(!bg::touches(ptT, rA)) { - bInside = false; - break; - } - } - - if(((bInside && inside) || (!bInside && !inside)) && (!bg::overlaps(translated, rA) && !bg::covered_by(translated, rA) && !bg::covered_by(rA, translated)) && !inNfp(translated.front(), nfp)){ - result = testTranslation; - return FOUND; - } - - point_t nextPtA = rA[index + 1]; - TranslationVector slideVector; - slideVector.vector_ = nextPtA - ptA; - slideVector.edge_ = {ptA, nextPtA}; - slideVector.fromA_ = true; - TranslationVector trimmed = trimVector(rA, translated, slideVector); - polygon_t::ring_type translated2; - trans::translate_transformer trans(trimmed.vector_.x_, trimmed.vector_.y_); - boost::geometry::transform(translated, translated2, trans); - - //check if the translated rB is identical to rA - identical = false; - for(const auto& ptT: translated) { - identical = false; - for(const auto& ptA: rA) { - if(ptT == ptA) { - identical = true; - break; - } - } - if(!identical) - break; - } - - if(identical) { - result = trimmed.vector_ + testTranslation; - return FIT; - } - - bInside = false; - for(const auto& ptT: translated2) { - if(bg::within(ptT, rA)) { - bInside = true; - break; - } else if(!bg::touches(ptT, rA)) { - bInside = false; - break; - } - } - - if(((bInside && inside) || (!bInside && !inside)) && (!bg::overlaps(translated2, rA) && !bg::covered_by(translated2, rA) && !bg::covered_by(rA, translated2)) && !inNfp(translated2.front(), nfp)){ - result = trimmed.vector_ + testTranslation; - return FOUND; - } - } - } - return NOT_FOUND; -} - -enum SlideResult { - LOOP, - NO_LOOP, - NO_TRANSLATION -}; - -SlideResult slide(polygon_t& pA, polygon_t::ring_type& rA, polygon_t::ring_type& rB, nfp_t& nfp, const point_t& transB, bool inside) { - polygon_t::ring_type rifsB; - boost::geometry::transform(rB, rifsB, trans::translate_transformer(transB.x_, transB.y_)); - rB = std::move(rifsB); - -#ifdef NFP_DEBUG - write_svg("ifs.svg", pA, rB); -#endif - - bool startAvailable = true; - psize_t cnt = 0; - point_t referenceStart = rB.front(); - std::vector history; - - //generate the nfp for the ring - while(startAvailable) { - DEBUG_VAL(cnt); - //use first point of rB as reference - nfp.back().push_back(rB.front()); - if(cnt == 15) - std::cerr << ""; - - std::vector touchers = findTouchingPoints(rA, rB); - -#ifdef NFP_DEBUG - DEBUG_MSG("touchers", touchers.size()); - for(auto t : touchers) { - DEBUG_VAL(t.type_); - } -#endif - if(touchers.empty()) { - throw std::runtime_error("Internal error: No touching points found"); - } - std::vector transVectors = findFeasibleTranslationVectors(rA, rB, touchers); - -#ifdef NFP_DEBUG - DEBUG_MSG("collected vectors", transVectors.size()); - for(auto pt : transVectors) { - DEBUG_VAL(pt); - } -#endif - - if(transVectors.empty()) { - return NO_LOOP; - } - - TranslationVector next = selectNextTranslationVector(pA, rA, rB, transVectors, history); - - if(next.vector_ == INVALID_POINT) - return NO_TRANSLATION; - - DEBUG_MSG("next", next); - - TranslationVector trimmed = trimVector(rA, rB, next); - DEBUG_MSG("trimmed", trimmed); - - history.push_back(next); - - polygon_t::ring_type nextRB; - boost::geometry::transform(rB, nextRB, trans::translate_transformer(trimmed.vector_.x_, trimmed.vector_.y_)); - rB = std::move(nextRB); - -#ifdef NFP_DEBUG - write_svg("next" + std::to_string(cnt) + ".svg", pA,rB); -#endif - - ++cnt; - if(referenceStart == rB.front() || (inside && bg::touches(rB.front(), nfp.front()))) { - startAvailable = false; - } - } - return LOOP; -} - -void removeCoLinear(polygon_t::ring_type& r) { - assert(r.size() > 2); - psize_t nextI; - psize_t prevI = 0; - segment_t segment(r[r.size() - 2], r[0]); - polygon_t::ring_type newR; - - for (psize_t i = 1; i < r.size() + 1; ++i) { - if (i >= r.size()) - nextI = i % r.size() + 1; - else - nextI = i; - - if (get_alignment(segment, r[nextI]) != ON) { - newR.push_back(r[prevI]); - } - segment = {segment.second, r[nextI]}; - prevI = nextI; - } - - r = newR; -} - -void removeCoLinear(polygon_t& p) { - removeCoLinear(p.outer()); - for (auto& r : p.inners()) - removeCoLinear(r); -} - -nfp_t generateNFP(polygon_t& pA, polygon_t& pB, const bool checkValidity = true) { - removeCoLinear(pA); - removeCoLinear(pB); - - if(checkValidity) { - std::string reason; - if(!bg::is_valid(pA, reason)) - throw std::runtime_error("Polygon A is invalid: " + reason); - - if(!bg::is_valid(pB, reason)) - throw std::runtime_error("Polygon B is invalid: " + reason); - } - - nfp_t nfp; - -#ifdef NFP_DEBUG - write_svg("start.svg", {pA, pB}); -#endif - - DEBUG_VAL(bg::wkt(pA)) - DEBUG_VAL(bg::wkt(pB)); - - //prevent double vertex connections at start because we might come back the same way we go which would end the nfp prematurely - std::vector ptyaminI = find_minimum_y(pA); - std::vector ptybmaxI = find_maximum_y(pB); - - point_t pAstart; - point_t pBstart; - - if(ptyaminI.size() > 1 || ptybmaxI.size() > 1) { - //find right-most of A and left-most of B to prevent double connection at start - coord_t maxX = MIN_COORD; - psize_t iRightMost = 0; - for(psize_t& ia : ptyaminI) { - const point_t& candidateA = pA.outer()[ia]; - if(larger(candidateA.x_, maxX)) { - maxX = candidateA.x_; - iRightMost = ia; - } - } - - coord_t minX = MAX_COORD; - psize_t iLeftMost = 0; - for(psize_t& ib : ptybmaxI) { - const point_t& candidateB = pB.outer()[ib]; - if(smaller(candidateB.x_, minX)) { - minX = candidateB.x_; - iLeftMost = ib; - } - } - pAstart = pA.outer()[iRightMost]; - pBstart = pB.outer()[iLeftMost]; - } else { - pAstart = pA.outer()[ptyaminI.front()]; - pBstart = pB.outer()[ptybmaxI.front()]; - } - - nfp.push_back({}); - point_t transB = {pAstart - pBstart}; - - if(slide(pA, pA.outer(), pB.outer(), nfp, transB, false) != LOOP) { - throw std::runtime_error("Unable to complete outer nfp loop"); - } - - DEBUG_VAL("##### outer #####"); - point_t startTrans; - while(true) { - SearchStartResult res = searchStartTranslation(pA.outer(), pB.outer(), nfp, false, startTrans); - if(res == FOUND) { - nfp.push_back({}); - DEBUG_VAL("##### interlock start #####") - polygon_t::ring_type rifsB; - boost::geometry::transform(pB.outer(), rifsB, trans::translate_transformer(startTrans.x_, startTrans.y_)); - if(inNfp(rifsB.front(), nfp)) { - continue; - } - SlideResult sres = slide(pA, pA.outer(), pB.outer(), nfp, startTrans, true); - if(sres != LOOP) { - if(sres == NO_TRANSLATION) { - //no initial slide found -> jiggsaw - if(!inNfp(pB.outer().front(),nfp)) { - nfp.push_back({}); - nfp.back().push_back(pB.outer().front()); - } - } - } - DEBUG_VAL("##### interlock end #####"); - } else if(res == FIT) { - point_t reference = pB.outer().front(); - point_t translated; - trans::translate_transformer translate(startTrans.x_, startTrans.y_); - boost::geometry::transform(reference, translated, translate); - if(!inNfp(translated,nfp)) { - nfp.push_back({}); - nfp.back().push_back(translated); - } - break; - } else - break; - } - - - for(auto& rA : pA.inners()) { - while(true) { - SearchStartResult res = searchStartTranslation(rA, pB.outer(), nfp, true, startTrans); - if(res == FOUND) { - nfp.push_back({}); - DEBUG_VAL("##### hole start #####"); - slide(pA, rA, pB.outer(), nfp, startTrans, true); - DEBUG_VAL("##### hole end #####"); - } else if(res == FIT) { - point_t reference = pB.outer().front(); - point_t translated; - trans::translate_transformer translate(startTrans.x_, startTrans.y_); - boost::geometry::transform(reference, translated, translate); - if(!inNfp(translated,nfp)) { - nfp.push_back({}); - nfp.back().push_back(translated); - } - break; - } else - break; - } - } - -#ifdef NFP_DEBUG - write_svg("nfp.svg", {pA,pB}, nfp); -#endif - - return nfp; -} -} -#endif diff --git a/src/libnest2d/tools/nfp_svgnest.hpp b/src/libnest2d/tools/nfp_svgnest.hpp deleted file mode 100644 index ac5700c101..0000000000 --- a/src/libnest2d/tools/nfp_svgnest.hpp +++ /dev/null @@ -1,1018 +0,0 @@ -#ifndef NFP_SVGNEST_HPP -#define NFP_SVGNEST_HPP - -#include -#include - -#include - -namespace libnest2d { - -namespace __svgnest { - -using std::sqrt; -using std::min; -using std::max; -using std::abs; -using std::isnan; - -//template struct _Scale { -// static const BP2D_CONSTEXPR long long Value = 1000000; -//}; - -template struct _alg { - using Contour = TContour; - using Point = TPoint; - using iCoord = TCoord; - using Coord = double; - using Shapes = nfp::Shapes; - - static const Coord TOL; - -#define dNAN std::nan("") - - struct Vector { - Coord x = 0.0, y = 0.0; - bool marked = false; - Vector() = default; - Vector(Coord X, Coord Y): x(X), y(Y) {} - Vector(const Point& p): x(Coord(getX(p))), y(Coord(getY(p))) {} - operator Point() const { return {iCoord(x), iCoord(y)}; } - Vector& operator=(const Point& p) { - x = getX(p), y = getY(p); return *this; - } - bool operator!=(const Vector& v) const { - return v.x != x || v.y != y; - } - Vector(std::initializer_list il): - x(*il.begin()), y(*std::next(il.begin())) {} - }; - - static inline Coord x(const Point& p) { return Coord(getX(p)); } - static inline Coord y(const Point& p) { return Coord(getY(p)); } - - static inline Coord x(const Vector& p) { return p.x; } - static inline Coord y(const Vector& p) { return p.y; } - - class Cntr { - std::vector v_; - public: - Cntr(const Contour& c) { - v_.reserve(c.size()); - std::transform(c.begin(), c.end(), std::back_inserter(v_), - [](const Point& p) { - return Vector(double(x(p)) / 1e6, double(y(p)) / 1e6); - }); - std::reverse(v_.begin(), v_.end()); - v_.pop_back(); - } - Cntr() = default; - - Coord offsetx = 0; - Coord offsety = 0; - size_t size() const { return v_.size(); } - bool empty() const { return v_.empty(); } - typename std::vector::const_iterator cbegin() const { return v_.cbegin(); } - typename std::vector::const_iterator cend() const { return v_.cend(); } - typename std::vector::iterator begin() { return v_.begin(); } - typename std::vector::iterator end() { return v_.end(); } - Vector& operator[](size_t idx) { return v_[idx]; } - const Vector& operator[](size_t idx) const { return v_[idx]; } - template - void emplace_back(Args&&...args) { - v_.emplace_back(std::forward(args)...); - } - template - void push(Args&&...args) { - v_.emplace_back(std::forward(args)...); - } - void clear() { v_.clear(); } - - operator Contour() const { - Contour cnt; - cnt.reserve(v_.size() + 1); - std::transform(v_.begin(), v_.end(), std::back_inserter(cnt), - [](const Vector& vertex) { - return Point(iCoord(vertex.x) * 1000000, iCoord(vertex.y) * 1000000); - }); - if(!cnt.empty()) cnt.emplace_back(cnt.front()); - S sh = shapelike::create(cnt); - -// std::reverse(cnt.begin(), cnt.end()); - return shapelike::getContour(sh); - } - }; - - inline static bool _almostEqual(Coord a, Coord b, - Coord tolerance = TOL) - { - return std::abs(a - b) < tolerance; - } - - // returns true if p lies on the line segment defined by AB, - // but not at any endpoints may need work! - static bool _onSegment(const Vector& A, const Vector& B, const Vector& p) { - - // vertical line - if(_almostEqual(A.x, B.x) && _almostEqual(p.x, A.x)) { - if(!_almostEqual(p.y, B.y) && !_almostEqual(p.y, A.y) && - p.y < max(B.y, A.y) && p.y > min(B.y, A.y)){ - return true; - } - else{ - return false; - } - } - - // horizontal line - if(_almostEqual(A.y, B.y) && _almostEqual(p.y, A.y)){ - if(!_almostEqual(p.x, B.x) && !_almostEqual(p.x, A.x) && - p.x < max(B.x, A.x) && p.x > min(B.x, A.x)){ - return true; - } - else{ - return false; - } - } - - //range check - if((p.x < A.x && p.x < B.x) || (p.x > A.x && p.x > B.x) || - (p.y < A.y && p.y < B.y) || (p.y > A.y && p.y > B.y)) - return false; - - // exclude end points - if((_almostEqual(p.x, A.x) && _almostEqual(p.y, A.y)) || - (_almostEqual(p.x, B.x) && _almostEqual(p.y, B.y))) - return false; - - - double cross = (p.y - A.y) * (B.x - A.x) - (p.x - A.x) * (B.y - A.y); - - if(abs(cross) > TOL) return false; - - double dot = (p.x - A.x) * (B.x - A.x) + (p.y - A.y)*(B.y - A.y); - - if(dot < 0 || _almostEqual(dot, 0)) return false; - - double len2 = (B.x - A.x)*(B.x - A.x) + (B.y - A.y)*(B.y - A.y); - - if(dot > len2 || _almostEqual(dot, len2)) return false; - - return true; - } - - // return true if point is in the polygon, false if outside, and null if exactly on a point or edge - static int pointInPolygon(const Vector& point, const Cntr& polygon) { - if(polygon.size() < 3){ - return 0; - } - - bool inside = false; - Coord offsetx = polygon.offsetx; - Coord offsety = polygon.offsety; - - for (size_t i = 0, j = polygon.size() - 1; i < polygon.size(); j=i++) { - auto xi = polygon[i].x + offsetx; - auto yi = polygon[i].y + offsety; - auto xj = polygon[j].x + offsetx; - auto yj = polygon[j].y + offsety; - - if(_almostEqual(xi, point.x) && _almostEqual(yi, point.y)){ - return 0; // no result - } - - if(_onSegment({xi, yi}, {xj, yj}, point)){ - return 0; // exactly on the segment - } - - if(_almostEqual(xi, xj) && _almostEqual(yi, yj)){ // ignore very small lines - continue; - } - - bool intersect = ((yi > point.y) != (yj > point.y)) && - (point.x < (xj - xi) * (point.y - yi) / (yj - yi) + xi); - if (intersect) inside = !inside; - } - - return inside? 1 : -1; - } - - static bool intersect(const Cntr& A, const Cntr& B){ - Contour a = A, b = B; - return shapelike::intersects(shapelike::create(a), shapelike::create(b)); - } - - static Vector _normalizeVector(const Vector& v) { - if(_almostEqual(v.x*v.x + v.y*v.y, Coord(1))){ - return Point(v); // given vector was already a unit vector - } - auto len = sqrt(v.x*v.x + v.y*v.y); - auto inverse = 1/len; - - return { Coord(v.x*inverse), Coord(v.y*inverse) }; - } - - static double pointDistance( const Vector& p, - const Vector& s1, - const Vector& s2, - Vector normal, - bool infinite = false) - { - normal = _normalizeVector(normal); - - Vector dir = { - normal.y, - -normal.x - }; - - auto pdot = p.x*dir.x + p.y*dir.y; - auto s1dot = s1.x*dir.x + s1.y*dir.y; - auto s2dot = s2.x*dir.x + s2.y*dir.y; - - auto pdotnorm = p.x*normal.x + p.y*normal.y; - auto s1dotnorm = s1.x*normal.x + s1.y*normal.y; - auto s2dotnorm = s2.x*normal.x + s2.y*normal.y; - - if(!infinite){ - if (((pdots1dot || _almostEqual(pdot, s1dot)) && - (pdot>s2dot || _almostEqual(pdot, s2dot)))) - { - // dot doesn't collide with segment, - // or lies directly on the vertex - return dNAN; - } - if ((_almostEqual(pdot, s1dot) && _almostEqual(pdot, s2dot)) && - (pdotnorm>s1dotnorm && pdotnorm>s2dotnorm)) - { - return min(pdotnorm - s1dotnorm, pdotnorm - s2dotnorm); - } - if ((_almostEqual(pdot, s1dot) && _almostEqual(pdot, s2dot)) && - (pdotnorm EFmax){ - return dNAN; - } - - double overlap = 0; - - if((ABmax > EFmax && ABmin < EFmin) || (EFmax > ABmax && EFmin < ABmin)) - { - overlap = 1; - } - else{ - auto minMax = min(ABmax, EFmax); - auto maxMin = max(ABmin, EFmin); - - auto maxMax = max(ABmax, EFmax); - auto minMin = min(ABmin, EFmin); - - overlap = (minMax-maxMin)/(maxMax-minMin); - } - - auto crossABE = (E.y - A.y) * (B.x - A.x) - (E.x - A.x) * (B.y - A.y); - auto crossABF = (F.y - A.y) * (B.x - A.x) - (F.x - A.x) * (B.y - A.y); - - // lines are colinear - if(_almostEqual(crossABE,0) && _almostEqual(crossABF,0)){ - - Vector ABnorm = {B.y-A.y, A.x-B.x}; - Vector EFnorm = {F.y-E.y, E.x-F.x}; - - auto ABnormlength = sqrt(ABnorm.x*ABnorm.x + ABnorm.y*ABnorm.y); - ABnorm.x /= ABnormlength; - ABnorm.y /= ABnormlength; - - auto EFnormlength = sqrt(EFnorm.x*EFnorm.x + EFnorm.y*EFnorm.y); - EFnorm.x /= EFnormlength; - EFnorm.y /= EFnormlength; - - // segment normals must point in opposite directions - if(abs(ABnorm.y * EFnorm.x - ABnorm.x * EFnorm.y) < TOL && - ABnorm.y * EFnorm.y + ABnorm.x * EFnorm.x < 0){ - // normal of AB segment must point in same direction as - // given direction vector - auto normdot = ABnorm.y * direction.y + ABnorm.x * direction.x; - // the segments merely slide along eachother - if(_almostEqual(normdot,0, TOL)){ - return dNAN; - } - if(normdot < 0){ - return 0.0; - } - } - return dNAN; - } - - std::vector distances; distances.reserve(10); - - // coincident points - if(_almostEqual(dotA, dotE)){ - distances.emplace_back(crossA-crossE); - } - else if(_almostEqual(dotA, dotF)){ - distances.emplace_back(crossA-crossF); - } - else if(dotA > EFmin && dotA < EFmax){ - auto d = pointDistance(A,E,F,reverse); - if(!isnan(d) && _almostEqual(d, 0)) - { // A currently touches EF, but AB is moving away from EF - auto dB = pointDistance(B,E,F,reverse,true); - if(dB < 0 || _almostEqual(dB*overlap,0)){ - d = dNAN; - } - } - if(!isnan(d)){ - distances.emplace_back(d); - } - } - - if(_almostEqual(dotB, dotE)){ - distances.emplace_back(crossB-crossE); - } - else if(_almostEqual(dotB, dotF)){ - distances.emplace_back(crossB-crossF); - } - else if(dotB > EFmin && dotB < EFmax){ - auto d = pointDistance(B,E,F,reverse); - - if(!isnan(d) && _almostEqual(d, 0)) - { // crossA>crossB A currently touches EF, but AB is moving away from EF - double dA = pointDistance(A,E,F,reverse,true); - if(dA < 0 || _almostEqual(dA*overlap,0)){ - d = dNAN; - } - } - if(!isnan(d)){ - distances.emplace_back(d); - } - } - - if(dotE > ABmin && dotE < ABmax){ - auto d = pointDistance(E,A,B,direction); - if(!isnan(d) && _almostEqual(d, 0)) - { // crossF ABmin && dotF < ABmax){ - auto d = pointDistance(F,A,B,direction); - if(!isnan(d) && _almostEqual(d, 0)) - { // && crossE 0 || _almostEqual(d, 0)){ - distance = d; - } - } - } - } - return distance; - } - - static double polygonProjectionDistance(const Cntr& AA, - const Cntr& BB, - Vector direction) - { - Cntr A = AA; - Cntr B = BB; - - auto Boffsetx = B.offsetx; - auto Boffsety = B.offsety; - auto Aoffsetx = A.offsetx; - auto Aoffsety = A.offsety; - - // close the loop for polygons - if(A[0] != A[A.size()-1]){ - A.push(A[0]); - } - - if(B[0] != B[B.size()-1]){ - B.push(B[0]); - } - - auto& edgeA = A; - auto& edgeB = B; - - double distance = dNAN, d; -// Vector p, s1, s2; - - for(size_t i = 0; i < edgeB.size(); i++) { - // the shortest/most negative projection of B onto A - double minprojection = dNAN; - Vector minp; - for(size_t j = 0; j < edgeA.size() - 1; j++){ - Vector p = {x(edgeB[i]) + Boffsetx, y(edgeB[i]) + Boffsety }; - Vector s1 = {x(edgeA[j]) + Aoffsetx, y(edgeA[j]) + Aoffsety }; - Vector s2 = {x(edgeA[j+1]) + Aoffsetx, y(edgeA[j+1]) + Aoffsety }; - - if(abs((s2.y-s1.y) * direction.x - - (s2.x-s1.x) * direction.y) < TOL) continue; - - // project point, ignore edge boundaries - d = pointDistance(p, s1, s2, direction); - - if(!isnan(d) && (isnan(minprojection) || d < minprojection)) { - minprojection = d; - minp = p; - } - } - - if(!isnan(minprojection) && (isnan(distance) || - minprojection > distance)){ - distance = minprojection; - } - } - - return distance; - } - - static std::pair searchStartPoint( - const Cntr& AA, const Cntr& BB, bool inside, const std::vector& NFP = {}) - { - // clone arrays - auto A = AA; - auto B = BB; - -// // close the loop for polygons -// if(A[0] != A[A.size()-1]){ -// A.push(A[0]); -// } - -// if(B[0] != B[B.size()-1]){ -// B.push(B[0]); -// } - - // returns true if point already exists in the given nfp - auto inNfp = [](const Vector& p, const std::vector& nfp){ - if(nfp.empty()){ - return false; - } - - for(size_t i=0; i < nfp.size(); i++){ - for(size_t j = 0; j< nfp[i].size(); j++){ - if(_almostEqual(p.x, nfp[i][j].x) && - _almostEqual(p.y, nfp[i][j].y)){ - return true; - } - } - } - - return false; - }; - - for(size_t i = 0; i < A.size() - 1; i++){ - if(!A[i].marked) { - A[i].marked = true; - for(size_t j = 0; j < B.size(); j++){ - B.offsetx = A[i].x - B[j].x; - B.offsety = A[i].y - B[j].y; - - int Binside = 0; - for(size_t k = 0; k < B.size(); k++){ - int inpoly = pointInPolygon({B[k].x + B.offsetx, B[k].y + B.offsety}, A); - if(inpoly != 0){ - Binside = inpoly; - break; - } - } - - if(Binside == 0){ // A and B are the same - return {false, {}}; - } - - auto startPoint = std::make_pair(true, Vector(B.offsetx, B.offsety)); - if(((Binside && inside) || (!Binside && !inside)) && - !intersect(A,B) && !inNfp(startPoint.second, NFP)){ - return startPoint; - } - - // slide B along vector - auto vx = A[i+1].x - A[i].x; - auto vy = A[i+1].y - A[i].y; - - double d1 = polygonProjectionDistance(A,B,{vx, vy}); - double d2 = polygonProjectionDistance(B,A,{-vx, -vy}); - - double d = dNAN; - - // todo: clean this up - if(isnan(d1) && isnan(d2)){ - // nothin - } - else if(isnan(d1)){ - d = d2; - } - else if(isnan(d2)){ - d = d1; - } - else{ - d = min(d1,d2); - } - - // only slide until no longer negative - // todo: clean this up - if(!isnan(d) && !_almostEqual(d,0) && d > 0){ - - } - else{ - continue; - } - - auto vd2 = vx*vx + vy*vy; - - if(d*d < vd2 && !_almostEqual(d*d, vd2)){ - auto vd = sqrt(vx*vx + vy*vy); - vx *= d/vd; - vy *= d/vd; - } - - B.offsetx += vx; - B.offsety += vy; - - for(size_t k = 0; k < B.size(); k++){ - int inpoly = pointInPolygon({B[k].x + B.offsetx, B[k].y + B.offsety}, A); - if(inpoly != 0){ - Binside = inpoly; - break; - } - } - startPoint = std::make_pair(true, Vector{B.offsetx, B.offsety}); - if(((Binside && inside) || (!Binside && !inside)) && - !intersect(A,B) && !inNfp(startPoint.second, NFP)){ - return startPoint; - } - } - } - } - - return {false, Vector(0, 0)}; - } - - static std::vector noFitPolygon(Cntr A, - Cntr B, - bool inside, - bool searchEdges) - { - if(A.size() < 3 || B.size() < 3) { - throw GeometryException(GeomErr::NFP); - return {}; - } - - A.offsetx = 0; - A.offsety = 0; - - long i = 0, j = 0; - - auto minA = y(A[0]); - long minAindex = 0; - - auto maxB = y(B[0]); - long maxBindex = 0; - - for(i = 1; i < A.size(); i++){ - A[i].marked = false; - if(y(A[i]) < minA){ - minA = y(A[i]); - minAindex = i; - } - } - - for(i = 1; i < B.size(); i++){ - B[i].marked = false; - if(y(B[i]) > maxB){ - maxB = y(B[i]); - maxBindex = i; - } - } - - std::pair startpoint; - - if(!inside){ - // shift B such that the bottom-most point of B is at the top-most - // point of A. This guarantees an initial placement with no - // intersections - startpoint = { true, - { x(A[minAindex]) - x(B[maxBindex]), - y(A[minAindex]) - y(B[maxBindex]) } - }; - } - else { - // no reliable heuristic for inside - startpoint = searchStartPoint(A, B, true); - } - - std::vector NFPlist; - - struct Touch { - int type; - long A; - long B; - Touch(int t, long a, long b): type(t), A(a), B(b) {} - }; - - while(startpoint.first) { - - B.offsetx = startpoint.second.x; - B.offsety = startpoint.second.y; - - // maintain a list of touching points/edges - std::vector touching; - - struct V { - Coord x, y; - Vector *start, *end; - operator bool() { - return start != nullptr && end != nullptr; - } - operator Vector() const { return {x, y}; } - } prevvector = {0, 0, nullptr, nullptr}; - - Cntr NFP; - NFP.emplace_back(x(B[0]) + B.offsetx, y(B[0]) + B.offsety); - - auto referencex = x(B[0]) + B.offsetx; - auto referencey = y(B[0]) + B.offsety; - auto startx = referencex; - auto starty = referencey; - unsigned counter = 0; - - // sanity check, prevent infinite loop - while(counter < 10*(A.size() + B.size())){ - touching.clear(); - - // find touching vertices/edges - for(i = 0; i < A.size(); i++){ - long nexti = (i == A.size() - 1) ? 0 : i + 1; - for(j = 0; j < B.size(); j++){ - - long nextj = (j == B.size() - 1) ? 0 : j + 1; - - if( _almostEqual(A[i].x, B[j].x+B.offsetx) && - _almostEqual(A[i].y, B[j].y+B.offsety)) - { - touching.emplace_back(0, i, j); - } - else if( _onSegment( - A[i], A[nexti], - { B[j].x+B.offsetx, B[j].y + B.offsety}) ) - { - touching.emplace_back(1, nexti, j); - } - else if( _onSegment( - {B[j].x+B.offsetx, B[j].y + B.offsety}, - {B[nextj].x+B.offsetx, B[nextj].y + B.offsety}, - A[i]) ) - { - touching.emplace_back(2, i, nextj); - } - } - } - - // generate translation vectors from touching vertices/edges - std::vector vectors; - for(i=0; i < touching.size(); i++){ - auto& vertexA = A[touching[i].A]; - vertexA.marked = true; - - // adjacent A vertices - auto prevAindex = touching[i].A - 1; - auto nextAindex = touching[i].A + 1; - - prevAindex = (prevAindex < 0) ? A.size() - 1 : prevAindex; // loop - nextAindex = (nextAindex >= A.size()) ? 0 : nextAindex; // loop - - auto& prevA = A[prevAindex]; - auto& nextA = A[nextAindex]; - - // adjacent B vertices - auto& vertexB = B[touching[i].B]; - - auto prevBindex = touching[i].B-1; - auto nextBindex = touching[i].B+1; - - prevBindex = (prevBindex < 0) ? B.size() - 1 : prevBindex; // loop - nextBindex = (nextBindex >= B.size()) ? 0 : nextBindex; // loop - - auto& prevB = B[prevBindex]; - auto& nextB = B[nextBindex]; - - if(touching[i].type == 0){ - - V vA1 = { - prevA.x - vertexA.x, - prevA.y - vertexA.y, - &vertexA, - &prevA - }; - - V vA2 = { - nextA.x - vertexA.x, - nextA.y - vertexA.y, - &vertexA, - &nextA - }; - - // B vectors need to be inverted - V vB1 = { - vertexB.x - prevB.x, - vertexB.y - prevB.y, - &prevB, - &vertexB - }; - - V vB2 = { - vertexB.x - nextB.x, - vertexB.y - nextB.y, - &nextB, - &vertexB - }; - - vectors.emplace_back(vA1); - vectors.emplace_back(vA2); - vectors.emplace_back(vB1); - vectors.emplace_back(vB2); - } - else if(touching[i].type == 1){ - vectors.emplace_back(V{ - vertexA.x-(vertexB.x+B.offsetx), - vertexA.y-(vertexB.y+B.offsety), - &prevA, - &vertexA - }); - - vectors.emplace_back(V{ - prevA.x-(vertexB.x+B.offsetx), - prevA.y-(vertexB.y+B.offsety), - &vertexA, - &prevA - }); - } - else if(touching[i].type == 2){ - vectors.emplace_back(V{ - vertexA.x-(vertexB.x+B.offsetx), - vertexA.y-(vertexB.y+B.offsety), - &prevB, - &vertexB - }); - - vectors.emplace_back(V{ - vertexA.x-(prevB.x+B.offsetx), - vertexA.y-(prevB.y+B.offsety), - &vertexB, - &prevB - }); - } - } - - // TODO: there should be a faster way to reject vectors that - // will cause immediate intersection. For now just check them all - - V translate = {0, 0, nullptr, nullptr}; - double maxd = 0; - - for(i = 0; i < vectors.size(); i++) { - if(vectors[i].x == 0 && vectors[i].y == 0){ - continue; - } - - // if this vector points us back to where we came from, ignore it. - // ie cross product = 0, dot product < 0 - if(prevvector && vectors[i].y * prevvector.y + vectors[i].x * prevvector.x < 0){ - - // compare magnitude with unit vectors - double vectorlength = sqrt(vectors[i].x*vectors[i].x+vectors[i].y*vectors[i].y); - Vector unitv = {Coord(vectors[i].x/vectorlength), - Coord(vectors[i].y/vectorlength)}; - - double prevlength = sqrt(prevvector.x*prevvector.x+prevvector.y*prevvector.y); - Vector prevunit = { prevvector.x/prevlength, prevvector.y/prevlength}; - - // we need to scale down to unit vectors to normalize vector length. Could also just do a tan here - if(abs(unitv.y * prevunit.x - unitv.x * prevunit.y) < 0.0001){ - continue; - } - } - - V vi = vectors[i]; - double d = polygonSlideDistance(A, B, vi, true); - double vecd2 = vectors[i].x*vectors[i].x + vectors[i].y*vectors[i].y; - - if(isnan(d) || d*d > vecd2){ - double vecd = sqrt(vectors[i].x*vectors[i].x + vectors[i].y*vectors[i].y); - d = vecd; - } - - if(!isnan(d) && d > maxd){ - maxd = d; - translate = vectors[i]; - } - } - - if(!translate || _almostEqual(maxd, 0)) - { - // didn't close the loop, something went wrong here - NFP.clear(); - break; - } - - translate.start->marked = true; - translate.end->marked = true; - - prevvector = translate; - - // trim - double vlength2 = translate.x*translate.x + translate.y*translate.y; - if(maxd*maxd < vlength2 && !_almostEqual(maxd*maxd, vlength2)){ - double scale = sqrt((maxd*maxd)/vlength2); - translate.x *= scale; - translate.y *= scale; - } - - referencex += translate.x; - referencey += translate.y; - - if(_almostEqual(referencex, startx) && - _almostEqual(referencey, starty)) { - // we've made a full loop - break; - } - - // if A and B start on a touching horizontal line, - // the end point may not be the start point - bool looped = false; - if(NFP.size() > 0) { - for(i = 0; i < NFP.size() - 1; i++) { - if(_almostEqual(referencex, NFP[i].x) && - _almostEqual(referencey, NFP[i].y)){ - looped = true; - } - } - } - - if(looped){ - // we've made a full loop - break; - } - - NFP.emplace_back(referencex, referencey); - - B.offsetx += translate.x; - B.offsety += translate.y; - - counter++; - } - - if(NFP.size() > 0){ - NFPlist.emplace_back(NFP); - } - - if(!searchEdges){ - // only get outer NFP or first inner NFP - break; - } - - startpoint = - searchStartPoint(A, B, inside, NFPlist); - - } - - return NFPlist; - } -}; - -template const double _alg::TOL = std::pow(10, -9); - -} -} - -#endif // NFP_SVGNEST_HPP diff --git a/src/libnest2d/tools/nfp_svgnest_glue.hpp b/src/libnest2d/tools/nfp_svgnest_glue.hpp deleted file mode 100644 index ea1fb4d076..0000000000 --- a/src/libnest2d/tools/nfp_svgnest_glue.hpp +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef NFP_SVGNEST_GLUE_HPP -#define NFP_SVGNEST_GLUE_HPP - -#include "nfp_svgnest.hpp" - -#include - -namespace libnest2d { - -namespace __svgnest { - -//template<> struct _Tol { -// static const BP2D_CONSTEXPR TCoord Value = 1000000; -//}; - -} - -namespace nfp { - -using NfpR = NfpResult; - -template<> struct NfpImpl { - NfpR operator()(const PolygonImpl& sh, const PolygonImpl& cother) { -// return nfpConvexOnly(sh, cother); - namespace sl = shapelike; - using alg = __svgnest::_alg; - - auto nfp_p = alg::noFitPolygon(sl::getContour(sh), - sl::getContour(cother), false, false); - - PolygonImpl nfp_cntr; - if(!nfp_p.empty()) nfp_cntr.Contour = nfp_p.front(); - return {nfp_cntr, referenceVertex(nfp_cntr)}; - } -}; - -template<> struct NfpImpl { - NfpR operator()(const PolygonImpl& sh, const PolygonImpl& cother) { -// return nfpConvexOnly(sh, cother); - namespace sl = shapelike; - using alg = __svgnest::_alg; - - std::cout << "Itt vagyok" << std::endl; - auto nfp_p = alg::noFitPolygon(sl::getContour(sh), - sl::getContour(cother), false, false); - - PolygonImpl nfp_cntr; - nfp_cntr.Contour = nfp_p.front(); - return {nfp_cntr, referenceVertex(nfp_cntr)}; - } -}; - -template<> -struct NfpImpl { - NfpR operator()(const PolygonImpl& sh, const PolygonImpl& cother) { - namespace sl = shapelike; - using alg = __svgnest::_alg; - - auto nfp_p = alg::noFitPolygon(sl::getContour(sh), - sl::getContour(cother), true, false); - - PolygonImpl nfp_cntr; - nfp_cntr.Contour = nfp_p.front(); - return {nfp_cntr, referenceVertex(nfp_cntr)}; - } -}; - -template<> struct MaxNfpLevel { -// static const BP2D_CONSTEXPR NfpLevel value = NfpLevel::BOTH_CONCAVE; - static const BP2D_CONSTEXPR NfpLevel value = NfpLevel::CONVEX_ONLY; -}; - -}} - -#endif // NFP_SVGNEST_GLUE_HPP diff --git a/src/libnest2d/tools/svgtools.hpp b/src/libnest2d/tools/svgtools.hpp index 776dd5a1a8..e1ed1ad05a 100644 --- a/src/libnest2d/tools/svgtools.hpp +++ b/src/libnest2d/tools/svgtools.hpp @@ -56,7 +56,7 @@ public: auto d = static_cast( std::round(conf_.height*conf_.mm_in_coord_units) ); - auto& contour = shapelike::getContour(tsh); + auto& contour = shapelike::contour(tsh); for(auto& v : contour) setY(v, -getY(v) + d); auto& holes = shapelike::holes(tsh); diff --git a/src/libslic3r/CMakeLists.txt b/src/libslic3r/CMakeLists.txt index 574dc4301f..7e41a158ae 100644 --- a/src/libslic3r/CMakeLists.txt +++ b/src/libslic3r/CMakeLists.txt @@ -154,7 +154,7 @@ add_library(libslic3r STATIC target_compile_definitions(libslic3r PUBLIC -DUSE_TBB ${PNG_DEFINITIONS}) target_include_directories(libslic3r PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${LIBNEST2D_INCLUDES} ${PNG_INCLUDE_DIRS}) target_link_libraries(libslic3r - ${LIBNEST2D_LIBRARIES} + libnest2d admesh miniz ${Boost_LIBRARIES} diff --git a/src/slic3r/AppController.cpp b/src/slic3r/AppController.cpp index 0d6d07c28d..4cc87bb7ec 100644 --- a/src/slic3r/AppController.cpp +++ b/src/slic3r/AppController.cpp @@ -1,5 +1,7 @@ #include "AppController.hpp" +#include + #include #include #include @@ -7,17 +9,12 @@ #include #include -#include -#include -#include - #include #include #include #include #include -#include -#include "GUI/GUI_App.hpp" +#include namespace Slic3r { @@ -140,119 +137,119 @@ public: void PrintController::slice_to_png() { - using Pointf3 = Vec3d; +// using Pointf3 = Vec3d; - auto ctl = GUI::get_appctl(); - auto presetbundle = GUI::wxGetApp().preset_bundle; +// auto ctl = GUI::get_appctl(); +// auto presetbundle = GUI::wxGetApp().preset_bundle; - assert(presetbundle); +// assert(presetbundle); - // FIXME: this crashes in command line mode - auto pt = presetbundle->printers.get_selected_preset().printer_technology(); - if(pt != ptSLA) { - ctl->report_issue(IssueType::ERR, L("Printer technology is not SLA!"), - L("Error")); - return; - } +// // FIXME: this crashes in command line mode +// auto pt = presetbundle->printers.get_selected_preset().printer_technology(); +// if(pt != ptSLA) { +// ctl->report_issue(IssueType::ERR, L("Printer technology is not SLA!"), +// L("Error")); +// return; +// } - auto conf = presetbundle->full_config(); - conf.validate(); +// auto conf = presetbundle->full_config(); +// conf.validate(); - auto exd = query_png_export_data(conf); - if(exd.zippath.empty()) return; +// auto exd = query_png_export_data(conf); +// if(exd.zippath.empty()) return; - Print *print = m_print; +// Print *print = m_print; - try { - print->apply_config(conf); - print->validate(); - } catch(std::exception& e) { - ctl->report_issue(IssueType::ERR, e.what(), "Error"); - return; - } +// try { +// print->apply_config(conf); +// print->validate(); +// } catch(std::exception& e) { +// ctl->report_issue(IssueType::ERR, e.what(), "Error"); +// return; +// } - // TODO: copy the model and work with the copy only - bool correction = false; - if(exd.corr_x != 1.0 || exd.corr_y != 1.0 || exd.corr_z != 1.0) { - correction = true; -// print->invalidate_all_steps(); +// // TODO: copy the model and work with the copy only +// bool correction = false; +// if(exd.corr_x != 1.0 || exd.corr_y != 1.0 || exd.corr_z != 1.0) { +// correction = true; +//// print->invalidate_all_steps(); -// for(auto po : print->objects) { -// po->model_object()->scale( -// Pointf3(exd.corr_x, exd.corr_y, exd.corr_z) -// ); -// po->model_object()->invalidate_bounding_box(); -// po->reload_model_instances(); -// po->invalidate_all_steps(); +//// for(auto po : print->objects) { +//// po->model_object()->scale( +//// Pointf3(exd.corr_x, exd.corr_y, exd.corr_z) +//// ); +//// po->model_object()->invalidate_bounding_box(); +//// po->reload_model_instances(); +//// po->invalidate_all_steps(); +//// } +// } + +// // Turn back the correction scaling on the model. +// auto scale_back = [this, print, correction, exd]() { +// if(correction) { // scale the model back +//// print->invalidate_all_steps(); +//// for(auto po : print->objects) { +//// po->model_object()->scale( +//// Pointf3(1.0/exd.corr_x, 1.0/exd.corr_y, 1.0/exd.corr_z) +//// ); +//// po->model_object()->invalidate_bounding_box(); +//// po->reload_model_instances(); +//// po->invalidate_all_steps(); +//// } // } - } +// }; - // Turn back the correction scaling on the model. - auto scale_back = [this, print, correction, exd]() { - if(correction) { // scale the model back -// print->invalidate_all_steps(); -// for(auto po : print->objects) { -// po->model_object()->scale( -// Pointf3(1.0/exd.corr_x, 1.0/exd.corr_y, 1.0/exd.corr_z) -// ); -// po->model_object()->invalidate_bounding_box(); -// po->reload_model_instances(); -// po->invalidate_all_steps(); -// } - } - }; +// auto print_bb = print->bounding_box(); +// Vec2d punsc = unscale(print_bb.size()); - auto print_bb = print->bounding_box(); - Vec2d punsc = unscale(print_bb.size()); +// // If the print does not fit into the print area we should cry about it. +// if(px(punsc) > exd.width_mm || py(punsc) > exd.height_mm) { +// std::stringstream ss; - // If the print does not fit into the print area we should cry about it. - if(px(punsc) > exd.width_mm || py(punsc) > exd.height_mm) { - std::stringstream ss; +// ss << L("Print will not fit and will be truncated!") << "\n" +// << L("Width needed: ") << px(punsc) << " mm\n" +// << L("Height needed: ") << py(punsc) << " mm\n"; - ss << L("Print will not fit and will be truncated!") << "\n" - << L("Width needed: ") << px(punsc) << " mm\n" - << L("Height needed: ") << py(punsc) << " mm\n"; +// if(!ctl->report_issue(IssueType::WARN_Q, ss.str(), L("Warning"))) { +// scale_back(); +// return; +// } +// } - if(!ctl->report_issue(IssueType::WARN_Q, ss.str(), L("Warning"))) { - scale_back(); - return; - } - } +// auto pri = ctl->create_progress_indicator( +// 200, L("Slicing to zipped png files...")); - auto pri = ctl->create_progress_indicator( - 200, L("Slicing to zipped png files...")); +// pri->on_cancel([&print](){ print->cancel(); }); - pri->on_cancel([&print](){ print->cancel(); }); +// try { +// pri->update(0, L("Slicing...")); +// slice(pri); +// } catch (std::exception& e) { +// ctl->report_issue(IssueType::ERR, e.what(), L("Exception occurred")); +// scale_back(); +// if(print->canceled()) print->restart(); +// return; +// } - try { - pri->update(0, L("Slicing...")); - slice(pri); - } catch (std::exception& e) { - ctl->report_issue(IssueType::ERR, e.what(), L("Exception occurred")); - scale_back(); - if(print->canceled()) print->restart(); - return; - } +// auto initstate = unsigned(pri->state()); +// print->set_status_callback([pri, initstate](int st, const std::string& msg) +// { +// pri->update(initstate + unsigned(st), msg); +// }); - auto initstate = unsigned(pri->state()); - print->set_status_callback([pri, initstate](int st, const std::string& msg) - { - pri->update(initstate + unsigned(st), msg); - }); +// try { +// print_to( *print, exd.zippath, +// exd.width_mm, exd.height_mm, +// exd.width_px, exd.height_px, +// exd.exp_time_s, exd.exp_time_first_s); - try { - print_to( *print, exd.zippath, - exd.width_mm, exd.height_mm, - exd.width_px, exd.height_px, - exd.exp_time_s, exd.exp_time_first_s); +// } catch (std::exception& e) { +// ctl->report_issue(IssueType::ERR, e.what(), L("Exception occurred")); +// } - } catch (std::exception& e) { - ctl->report_issue(IssueType::ERR, e.what(), L("Exception occurred")); - } - - scale_back(); - if(print->canceled()) print->restart(); - print->set_status_default(); +// scale_back(); +// if(print->canceled()) print->restart(); +// print->set_status_default(); } const PrintConfig &PrintController::config() const From ce7d196b434bb9e7dfeba709d108f7afdd4cf19d Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Tue, 23 Oct 2018 19:08:26 +0200 Subject: [PATCH 159/186] deps: Add gtest, nlopt, zlib, and libpng, add debug configurations on Windows --- deps/CMakeLists.txt | 8 +- deps/deps-unix-static.cmake | 51 ++++++++++- deps/deps-windows.cmake | 166 ++++++++++++++++++++++++++++++++---- 3 files changed, 205 insertions(+), 20 deletions(-) diff --git a/deps/CMakeLists.txt b/deps/CMakeLists.txt index 852d17fa2c..b02575617e 100644 --- a/deps/CMakeLists.txt +++ b/deps/CMakeLists.txt @@ -5,12 +5,12 @@ # # All the dependencies are installed in a `destdir` directory in the root of the build directory, # in a traditional Unix-style prefix structure. The destdir can be used directly by CMake -# when building Slic3r - to do this, set the CMAKE_PREFIX_PATH to the destdir's location. +# when building Slic3r - to do this, set the CMAKE_PREFIX_PATH to ${destdir}/usr/local. # # For better clarity of console output, it's recommended to _not_ use a parallelized build # for the top-level command, ie. use `make -j 1` or `ninja -j 1` to force single-threaded top-level # build. This doesn't degrade performance as individual dependencies are built in parallel fashion -# as appropriate anyway (cf. the `NPROC` variable). +# if supported by the dependency. # # On Windows, architecture (64 vs 32 bits) is judged based on the compiler variant. # To build dependencies for either 64 or 32 bit OS, use the respective compiler command line. @@ -27,7 +27,9 @@ if (NPROC EQUAL 0) set(NPROC 1) endif () -set(DESTDIR "${CMAKE_CURRENT_BINARY_DIR}/destdir") +set(DESTDIR "${CMAKE_CURRENT_BINARY_DIR}/destdir" CACHE PATH "Destination directory") +option(DEP_DEBUG "Build debug variants (currently only works on Windows)" ON) + if (MSVC) if ("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8") diff --git a/deps/deps-unix-static.cmake b/deps/deps-unix-static.cmake index f963f53569..a9ae1ea6a9 100644 --- a/deps/deps-unix-static.cmake +++ b/deps/deps-unix-static.cmake @@ -22,13 +22,62 @@ ExternalProject_Add(dep_tbb EXCLUDE_FROM_ALL 1 URL "https://github.com/wjakob/tbb/archive/a0dc9bf76d0120f917b641ed095360448cabc85b.tar.gz" URL_HASH SHA256=0545cb6033bd1873fcae3ea304def720a380a88292726943ae3b9b207f322efe - BUILD_IN_SOURCE 1 CMAKE_ARGS -DTBB_BUILD_SHARED=OFF -DTBB_BUILD_TESTS=OFF -DCMAKE_POSITION_INDEPENDENT_CODE=ON INSTALL_COMMAND make install "DESTDIR=${DESTDIR}" ) +ExternalProject_Add(dep_gtest + EXCLUDE_FROM_ALL 1 + URL "https://github.com/google/googletest/archive/release-1.8.1.tar.gz" + URL_HASH SHA256=9bf1fe5182a604b4135edc1a425ae356c9ad15e9b23f9f12a02e80184c3a249c + CMAKE_ARGS -DBUILD_GMOCK=OFF + -DCMAKE_POSITION_INDEPENDENT_CODE=ON + INSTALL_COMMAND make install "DESTDIR=${DESTDIR}" +) + +ExternalProject_Add(dep_nlopt + EXCLUDE_FROM_ALL 1 + URL "https://github.com/stevengj/nlopt/archive/v2.5.0.tar.gz" + URL_HASH SHA256=c6dd7a5701fff8ad5ebb45a3dc8e757e61d52658de3918e38bab233e7fd3b4ae + CMAKE_GENERATOR "${DEP_MSVC_GEN}" + CMAKE_ARGS + -DNLOPT_PYTHON=OFF + -DNLOPT_OCTAVE=OFF + -DNLOPT_MATLAB=OFF + -DNLOPT_GUILE=OFF + -DCMAKE_POSITION_INDEPENDENT_CODE=ON + INSTALL_COMMAND make install "DESTDIR=${DESTDIR}" + INSTALL_COMMAND "" +) + +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_ARGS + -DCMAKE_POSITION_INDEPENDENT_CODE=ON + INSTALL_COMMAND make install "DESTDIR=${DESTDIR}" + INSTALL_COMMAND "" +) + + +ExternalProject_Add(dep_libpng + DEPENDS dep_zlib + EXCLUDE_FROM_ALL 1 + URL "http://prdownloads.sourceforge.net/libpng/libpng-1.6.35.tar.xz?download" + URL_HASH SHA256=23912ec8c9584917ed9b09c5023465d71709dce089be503c7867fec68a93bcd7 + CMAKE_GENERATOR "${DEP_MSVC_GEN}" + CMAKE_ARGS + -DPNG_SHARED=OFF + -DPNG_TESTS=OFF + -DCMAKE_POSITION_INDEPENDENT_CODE=ON + INSTALL_COMMAND make install "DESTDIR=${DESTDIR}" + INSTALL_COMMAND "" +) + ExternalProject_Add(dep_libopenssl EXCLUDE_FROM_ALL 1 URL "https://github.com/openssl/openssl/archive/OpenSSL_1_1_0g.tar.gz" diff --git a/deps/deps-windows.cmake b/deps/deps-windows.cmake index 2be0d448aa..a47a29be11 100644 --- a/deps/deps-windows.cmake +++ b/deps/deps-windows.cmake @@ -1,4 +1,18 @@ +if (${DEPS_BITS} EQUAL 32) + set(DEP_MSVC_GEN "Visual Studio 12") +else () + set(DEP_MSVC_GEN "Visual Studio 12 Win64") +endif () + + + +if (${DEP_DEBUG}) + set(DEP_BOOST_DEBUG "debug") +else () + set(DEP_BOOST_DEBUG "") +endif () + ExternalProject_Add(dep_boost EXCLUDE_FROM_ALL 1 URL "https://dl.bintray.com/boostorg/release/1.63.0/source/boost_1_63_0.tar.gz" @@ -20,30 +34,129 @@ ExternalProject_Add(dep_boost variant=release threading=multi boost.locale.icu=off - install + "${DEP_BOOST_DEBUG}" release install INSTALL_COMMAND "" # b2 does that already ) -if (${DEPS_BITS} EQUAL 32) - set(DEP_TBB_GEN "Visual Studio 12") -else () - set(DEP_TBB_GEN "Visual Studio 12 Win64") -endif () - ExternalProject_Add(dep_tbb EXCLUDE_FROM_ALL 1 URL "https://github.com/wjakob/tbb/archive/a0dc9bf76d0120f917b641ed095360448cabc85b.tar.gz" URL_HASH SHA256=0545cb6033bd1873fcae3ea304def720a380a88292726943ae3b9b207f322efe - CMAKE_GENERATOR "${DEP_TBB_GEN}" + CMAKE_GENERATOR "${DEP_MSVC_GEN}" CMAKE_ARGS - -DCMAKE_CONFIGURATION_TYPES=Release + -DCMAKE_DEBUG_POSTFIX=d -DTBB_BUILD_SHARED=OFF -DTBB_BUILD_TESTS=OFF "-DCMAKE_INSTALL_PREFIX:PATH=${DESTDIR}\\usr\\local" BUILD_COMMAND msbuild /P:Configuration=Release INSTALL.vcxproj INSTALL_COMMAND "" ) +if (${DEP_DEBUG}) + ExternalProject_Get_Property(dep_tbb BINARY_DIR) + ExternalProject_Add_Step(dep_tbb build_debug + DEPENDEES build + DEPENDERS install + COMMAND msbuild /P:Configuration=Debug INSTALL.vcxproj + WORKING_DIRECTORY "${BINARY_DIR}" + ) +endif () + + +ExternalProject_Add(dep_gtest + EXCLUDE_FROM_ALL 1 + URL "https://github.com/google/googletest/archive/release-1.8.1.tar.gz" + URL_HASH SHA256=9bf1fe5182a604b4135edc1a425ae356c9ad15e9b23f9f12a02e80184c3a249c + CMAKE_GENERATOR "${DEP_MSVC_GEN}" + CMAKE_ARGS -DBUILD_GMOCK=OFF + -DCMAKE_POSITION_INDEPENDENT_CODE=ON + "-DCMAKE_INSTALL_PREFIX:PATH=${DESTDIR}\\usr\\local" + BUILD_COMMAND msbuild /P:Configuration=Release INSTALL.vcxproj + INSTALL_COMMAND "" +) +if (${DEP_DEBUG}) + ExternalProject_Get_Property(dep_gtest BINARY_DIR) + ExternalProject_Add_Step(dep_gtest build_debug + DEPENDEES build + DEPENDERS install + COMMAND msbuild /P:Configuration=Debug INSTALL.vcxproj + WORKING_DIRECTORY "${BINARY_DIR}" + ) +endif () + + +ExternalProject_Add(dep_nlopt + EXCLUDE_FROM_ALL 1 + URL "https://github.com/stevengj/nlopt/archive/v2.5.0.tar.gz" + URL_HASH SHA256=c6dd7a5701fff8ad5ebb45a3dc8e757e61d52658de3918e38bab233e7fd3b4ae + CMAKE_GENERATOR "${DEP_MSVC_GEN}" + CMAKE_ARGS + -DNLOPT_PYTHON=OFF + -DNLOPT_OCTAVE=OFF + -DNLOPT_MATLAB=OFF + -DNLOPT_GUILE=OFF + -DCMAKE_POSITION_INDEPENDENT_CODE=ON + -DCMAKE_DEBUG_POSTFIX=d + "-DCMAKE_INSTALL_PREFIX:PATH=${DESTDIR}\\usr\\local" + BUILD_COMMAND msbuild /P:Configuration=Release INSTALL.vcxproj + INSTALL_COMMAND "" +) +if (${DEP_DEBUG}) + ExternalProject_Get_Property(dep_nlopt BINARY_DIR) + ExternalProject_Add_Step(dep_nlopt build_debug + DEPENDEES build + DEPENDERS install + COMMAND msbuild /P:Configuration=Debug INSTALL.vcxproj + WORKING_DIRECTORY "${BINARY_DIR}" + ) +endif () + + +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_ARGS + -DCMAKE_POSITION_INDEPENDENT_CODE=ON + "-DCMAKE_INSTALL_PREFIX:PATH=${DESTDIR}\\usr\\local" + BUILD_COMMAND msbuild /P:Configuration=Release INSTALL.vcxproj + INSTALL_COMMAND "" +) +if (${DEP_DEBUG}) + ExternalProject_Get_Property(dep_zlib BINARY_DIR) + ExternalProject_Add_Step(dep_zlib build_debug + DEPENDEES build + DEPENDERS install + COMMAND msbuild /P:Configuration=Debug INSTALL.vcxproj + WORKING_DIRECTORY "${BINARY_DIR}" + ) +endif () + + +ExternalProject_Add(dep_libpng + DEPENDS dep_zlib + EXCLUDE_FROM_ALL 1 + URL "http://prdownloads.sourceforge.net/libpng/libpng-1.6.35.tar.xz?download" + URL_HASH SHA256=23912ec8c9584917ed9b09c5023465d71709dce089be503c7867fec68a93bcd7 + CMAKE_GENERATOR "${DEP_MSVC_GEN}" + CMAKE_ARGS + -DPNG_SHARED=OFF + -DPNG_TESTS=OFF + -DCMAKE_POSITION_INDEPENDENT_CODE=ON + "-DCMAKE_INSTALL_PREFIX:PATH=${DESTDIR}\\usr\\local" + BUILD_COMMAND msbuild /P:Configuration=Release INSTALL.vcxproj + INSTALL_COMMAND "" +) +if (${DEP_DEBUG}) + ExternalProject_Get_Property(dep_libpng BINARY_DIR) + ExternalProject_Add_Step(dep_libpng build_debug + DEPENDEES build + DEPENDERS install + COMMAND msbuild /P:Configuration=Debug INSTALL.vcxproj + WORKING_DIRECTORY "${BINARY_DIR}" + ) +endif () if (${DEPS_BITS} EQUAL 32) @@ -59,10 +172,27 @@ ExternalProject_Add(dep_libcurl BUILD_IN_SOURCE 1 CONFIGURE_COMMAND "" BUILD_COMMAND cd winbuild && nmake /f Makefile.vc mode=static VC=12 GEN_PDB=yes DEBUG=no "MACHINE=${DEP_LIBCURL_TARGET}" - INSTALL_COMMAND cd builds\\libcurl-*-winssl + INSTALL_COMMAND cd builds\\libcurl-*-release-*-winssl && "${CMAKE_COMMAND}" -E copy_directory include "${DESTDIR}\\usr\\local\\include" && "${CMAKE_COMMAND}" -E copy_directory lib "${DESTDIR}\\usr\\local\\lib" ) +if (${DEP_DEBUG}) + ExternalProject_Get_Property(dep_libcurl SOURCE_DIR) + ExternalProject_Add_Step(dep_libcurl build_debug + DEPENDEES build + DEPENDERS install + COMMAND cd winbuild && nmake /f Makefile.vc mode=static VC=12 GEN_PDB=yes DEBUG=yes "MACHINE=${DEP_LIBCURL_TARGET}" + WORKING_DIRECTORY "${SOURCE_DIR}" + ) + ExternalProject_Add_Step(dep_libcurl install_debug + DEPENDEES install + COMMAND cd builds\\libcurl-*-debug-*-winssl + && "${CMAKE_COMMAND}" -E copy_directory include "${DESTDIR}\\usr\\local\\include" + && "${CMAKE_COMMAND}" -E copy_directory lib "${DESTDIR}\\usr\\local\\lib" + WORKING_DIRECTORY "${SOURCE_DIR}" + ) +endif () + if (${DEPS_BITS} EQUAL 32) set(DEP_WXWIDGETS_TARGET "") @@ -79,12 +209,16 @@ ExternalProject_Add(dep_wxwidgets 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}" + 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 () From 6c38cb2c32e7fe4c3935ee7081bb42aad4320100 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Tue, 23 Oct 2018 22:53:43 +0200 Subject: [PATCH 160/186] WIP: Background processing is almost working now. still PrintObject::_slice_volumes() needs some love to set the PrintObject matrices correctly. --- src/libnest2d/CMakeLists.txt | 2 +- src/libslic3r/PlaceholderParser.cpp | 19 ++++- src/libslic3r/PlaceholderParser.hpp | 3 +- src/libslic3r/Print.cpp | 83 ++++++++++++++------- src/libslic3r/Print.hpp | 16 +++- src/slic3r/GUI/BackgroundSlicingProcess.cpp | 9 ++- src/slic3r/GUI/BackgroundSlicingProcess.hpp | 3 +- src/slic3r/GUI/Plater.cpp | 43 +++++------ 8 files changed, 116 insertions(+), 62 deletions(-) diff --git a/src/libnest2d/CMakeLists.txt b/src/libnest2d/CMakeLists.txt index 21840aee29..cabc9bdfaa 100644 --- a/src/libnest2d/CMakeLists.txt +++ b/src/libnest2d/CMakeLists.txt @@ -70,7 +70,7 @@ if(TBB_FOUND) # The Intel TBB library will use the std::exception_ptr feature of C++11. target_compile_definitions(libnest2d INTERFACE -DTBB_USE_CAPTURED_EXCEPTION=1) - target_link_libraries(libnest2d INTERFACE ${TBB_LIBRARIES}) + target_link_libraries(libnest2d INTERFACE tbb) else() find_package(OpenMP QUIET) diff --git a/src/libslic3r/PlaceholderParser.cpp b/src/libslic3r/PlaceholderParser.cpp index cc6f1c75e4..331a42614c 100644 --- a/src/libslic3r/PlaceholderParser.cpp +++ b/src/libslic3r/PlaceholderParser.cpp @@ -100,22 +100,33 @@ void PlaceholderParser::update_timestamp(DynamicConfig &config) // are expected to be addressed by the extruder ID, therefore // if a vector configuration value is addressed without an index, // a current extruder ID is used. -void PlaceholderParser::apply_config(const DynamicPrintConfig &rhs) +bool PlaceholderParser::apply_config(const DynamicPrintConfig &rhs) { const ConfigDef *def = rhs.def(); + bool modified = false; for (const t_config_option_key &opt_key : rhs.keys()) { const ConfigOptionDef *opt_def = def->get(opt_key); if ((opt_def->multiline && boost::ends_with(opt_key, "_gcode")) || opt_key == "post_process") continue; - const ConfigOption *opt = rhs.option(opt_key); + const ConfigOption *opt_rhs = rhs.option(opt_key); + const ConfigOption *opt_old = m_config.option(opt_key, false); + if (opt_old != nullptr) { + if ((opt_rhs->type() == coFloatOrPercent && + dynamic_cast(opt_old)->value == rhs.get_abs_value(opt_key)) || + *opt_rhs == *opt_old) + // no need to update + continue; + } // Store a copy of the config option. // Convert FloatOrPercent values to floats first. //FIXME there are some ratio_over chains, which end with empty ratio_with. // For example, XXX_extrusion_width parameters are not handled by get_abs_value correctly. - this->set(opt_key, (opt->type() == coFloatOrPercent) ? + this->set(opt_key, (opt_rhs->type() == coFloatOrPercent) ? new ConfigOptionFloat(rhs.get_abs_value(opt_key)) : - opt->clone()); + opt_rhs->clone()); + modified = true; } + return modified; } void PlaceholderParser::apply_env_variables() diff --git a/src/libslic3r/PlaceholderParser.hpp b/src/libslic3r/PlaceholderParser.hpp index 49d53ec9ec..d833969fca 100644 --- a/src/libslic3r/PlaceholderParser.hpp +++ b/src/libslic3r/PlaceholderParser.hpp @@ -14,7 +14,8 @@ class PlaceholderParser public: PlaceholderParser(); - void apply_config(const DynamicPrintConfig &config); + // Return true if modified. + bool apply_config(const DynamicPrintConfig &config); void apply_env_variables(); // Add new ConfigOption values to m_config. diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index d4fed0d5f9..7815391e92 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -357,6 +357,14 @@ std::vector Print::extruders() const return extruders; } +unsigned int Print::num_object_instances() const +{ + unsigned int instances = 0; + for (const PrintObject *print_object : m_objects) + instances += print_object->copies().size(); + return instances; +} + void Print::_simplify_slices(double distance) { for (PrintObject *object : m_objects) { @@ -687,7 +695,7 @@ static std::vector print_objects_from_model_object(const ModelOb return std::vector(trafos.begin(), trafos.end()); } -bool Print::apply(const Model &model, const DynamicPrintConfig &config_in) +Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &config_in) { // Make a copy of the config, normalize it. DynamicPrintConfig config(config_in); @@ -697,14 +705,23 @@ bool Print::apply(const Model &model, const DynamicPrintConfig &config_in) t_config_option_keys object_diff = m_default_object_config.diff(config); t_config_option_keys region_diff = m_default_region_config.diff(config); + // Do not use the ApplyStatus as we will use the max function when updating apply_status. + unsigned int apply_status = APPLY_STATUS_UNCHANGED; + auto update_apply_status = [&apply_status](bool invalidated) + { apply_status = std::max(apply_status, invalidated ? APPLY_STATUS_INVALIDATED : APPLY_STATUS_CHANGED); }; + if (! (print_diff.empty() && object_diff.empty() && region_diff.empty())) + update_apply_status(false); + // Grab the lock for the Print / PrintObject milestones. tbb::mutex::scoped_lock lock(m_mutex); // The following call may stop the background processing. - bool invalidated = this->invalidate_state_by_config_options(print_diff); + update_apply_status(this->invalidate_state_by_config_options(print_diff)); // Apply variables to placeholder parser. The placeholder parser is used by G-code export, // which should be stopped if print_diff is not empty. - m_placeholder_parser.apply_config(config); + if (m_placeholder_parser.apply_config(config)) + update_apply_status(this->invalidate_step(psGCodeExport)); + // It is also safe to change m_config now after this->invalidate_state_by_config_options() call. m_config.apply_only(config, print_diff, true); // Handle changes to object config defaults @@ -734,7 +751,7 @@ bool Print::apply(const Model &model, const DynamicPrintConfig &config_in) // Kill everything, initialize from scratch. // Stop background processing. m_cancel_callback(); - this->invalidate_all_steps(); + update_apply_status(this->invalidate_all_steps()); for (PrintObject *object : m_objects) { model_object_status.emplace(object->model_object()->id(), ModelObjectStatus::Deleted); delete object; @@ -753,7 +770,7 @@ bool Print::apply(const Model &model, const DynamicPrintConfig &config_in) model_object_status.emplace(model_object->id(), ModelObjectStatus::Old); } else if (model_object_list_extended(m_model, model)) { // Add new objects. Their volumes and configs will be synchronized later. - this->invalidate_step(psGCodeExport); + update_apply_status(this->invalidate_step(psGCodeExport)); for (const ModelObject *model_object : m_model.objects) model_object_status.emplace(model_object->id(), ModelObjectStatus::Old); for (size_t i = m_model.objects.size(); i < model.objects.size(); ++ i) { @@ -766,14 +783,14 @@ bool Print::apply(const Model &model, const DynamicPrintConfig &config_in) m_cancel_callback(); this->invalidate_step(psGCodeExport); // Second create a new list of objects. - std::vector old(std::move(m_model.objects)); + std::vector model_objects_old(std::move(m_model.objects)); m_model.objects.clear(); m_model.objects.reserve(model.objects.size()); auto by_id_lower = [](const ModelObject *lhs, const ModelObject *rhs){ return lhs->id() < rhs->id(); }; - std::sort(old.begin(), old.end(), by_id_lower); + std::sort(model_objects_old.begin(), model_objects_old.end(), by_id_lower); for (const ModelObject *mobj : model.objects) { - auto it = std::lower_bound(old.begin(), old.end(), mobj, by_id_lower); - if (it == old.end() || (*it)->id() != mobj->id()) { + auto it = std::lower_bound(model_objects_old.begin(), model_objects_old.end(), mobj, by_id_lower); + if (it == model_objects_old.end() || (*it)->id() != mobj->id()) { // New ModelObject added. m_model.objects.emplace_back((*it)->clone(&m_model)); model_object_status.emplace(mobj->id(), ModelObjectStatus::New); @@ -784,26 +801,30 @@ bool Print::apply(const Model &model, const DynamicPrintConfig &config_in) } } bool deleted_any = false; - for (ModelObject *mobj : old) - if (model_object_status.find(ModelObjectStatus(mobj->id())) == model_object_status.end()) { - model_object_status.emplace(mobj->id(), ModelObjectStatus::Deleted); - delete mobj; + for (ModelObject *&model_object : model_objects_old) { + if (model_object_status.find(ModelObjectStatus(model_object->id())) == model_object_status.end()) { + model_object_status.emplace(model_object->id(), ModelObjectStatus::Deleted); deleted_any = true; - } + } else + // Do not delete this ModelObject instance. + model_object = nullptr; + } if (deleted_any) { // Delete PrintObjects of the deleted ModelObjects. - std::vector old = std::move(m_objects); + std::vector print_objects_old = std::move(m_objects); m_objects.clear(); - m_objects.reserve(old.size()); - for (PrintObject *print_object : old) { + m_objects.reserve(print_objects_old.size()); + for (PrintObject *print_object : print_objects_old) { auto it_status = model_object_status.find(ModelObjectStatus(print_object->model_object()->id())); assert(it_status != model_object_status.end()); if (it_status->status == ModelObjectStatus::Deleted) { - print_object->invalidate_all_steps(); + update_apply_status(print_object->invalidate_all_steps()); delete print_object; } else m_objects.emplace_back(print_object); } + for (ModelObject *model_object : model_objects_old) + delete model_object; } } } @@ -860,7 +881,7 @@ bool Print::apply(const Model &model, const DynamicPrintConfig &config_in) // The very first step (the slicing step) is invalidated. One may freely remove all associated PrintObjects. auto range = print_object_status.equal_range(PrintObjectStatus(model_object.id())); for (auto it = range.first; it != range.second; ++ it) { - it->print_object->invalidate_all_steps(); + update_apply_status(it->print_object->invalidate_all_steps()); const_cast(*it).status = PrintObjectStatus::Deleted; } // Copy content of the ModelObject including its ID, reset the parent. @@ -872,7 +893,7 @@ bool Print::apply(const Model &model, const DynamicPrintConfig &config_in) // Invalidate just the supports step. auto range = print_object_status.equal_range(PrintObjectStatus(model_object.id())); for (auto it = range.first; it != range.second; ++ it) - it->print_object->invalidate_step(posSupportMaterial); + update_apply_status(it->print_object->invalidate_step(posSupportMaterial)); // Copy just the support volumes. model_volume_list_update_supports(model_object, model_object_new); } @@ -883,19 +904,23 @@ bool Print::apply(const Model &model, const DynamicPrintConfig &config_in) this_object_config_diff = model_object.config.diff(model_object_new.config); if (! this_object_config_diff.empty()) model_object.config.apply_only(model_object_new.config, this_object_config_diff, true); - if (! this_object_config_diff.empty() || ! this_object_config_diff.empty()) { + if (! object_diff.empty() || ! this_object_config_diff.empty()) { PrintObjectConfig new_config = m_default_object_config; normalize_and_apply_config(new_config, model_object.config); auto range = print_object_status.equal_range(PrintObjectStatus(model_object.id())); for (auto it = range.first; it != range.second; ++ it) { t_config_option_keys diff = it->print_object->config().diff(new_config); - invalidated |= it->print_object->invalidate_state_by_config_options(diff); - it->print_object->config_apply_only(new_config, diff, true); + if (! diff.empty()) { + update_apply_status(it->print_object->invalidate_state_by_config_options(diff)); + it->print_object->config_apply_only(new_config, diff, true); + } } } model_object.name = model_object_new.name; model_object.input_file = model_object_new.input_file; - model_object.instances = model_object_new.instances; + model_object.clear_instances(); + for (const ModelInstance *model_instance : model_object_new.instances) + model_object.add_instance(*model_instance); } } @@ -944,6 +969,9 @@ bool Print::apply(const Model &model, const DynamicPrintConfig &config_in) print_object_status.emplace(PrintObjectStatus(print_object, PrintObjectStatus::New)); } else if ((*it_old)->print_object->copies() != new_instances.copies) { // The PrintObject already exists and the copies differ. + if ((*it_old)->print_object->copies().size() != new_instances.copies.size()) + update_apply_status(this->invalidate_step(psWipeTower)); + update_apply_status(this->invalidate_step(psSkirt) || this->invalidate_step(psBrim) || this->invalidate_step(psGCodeExport)); (*it_old)->print_object->set_copies(new_instances.copies); print_objects_new.emplace_back((*it_old)->print_object); } @@ -952,6 +980,7 @@ bool Print::apply(const Model &model, const DynamicPrintConfig &config_in) if (m_objects != print_objects_new) { m_cancel_callback(); m_objects = print_objects_new; + update_apply_status(false); } } @@ -998,7 +1027,7 @@ bool Print::apply(const Model &model, const DynamicPrintConfig &config_in) } continue; print_object_end: - print_object->invalidate_all_steps(); + update_apply_status(print_object->invalidate_all_steps()); // Decrease the references to regions from this volume. int ireg = 0; for (const std::vector &volumes : print_object->region_volumes) { @@ -1014,7 +1043,7 @@ bool Print::apply(const Model &model, const DynamicPrintConfig &config_in) region.config_apply_only(this_region_config, diff, false); for (PrintObject *print_object : m_objects) if (region_id < print_object->region_volumes.size() && ! print_object->region_volumes[region_id].empty()) - invalidated |= print_object->invalidate_state_by_config_options(diff); + update_apply_status(print_object->invalidate_state_by_config_options(diff)); } } } @@ -1072,7 +1101,7 @@ bool Print::apply(const Model &model, const DynamicPrintConfig &config_in) object->update_layer_height_profile(); this->update_object_placeholders(); - return invalidated; + return static_cast(apply_status); } // Update "scale", "input_filename", "input_filename_base" placeholders from the current m_objects. diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index e765b8801e..bd04cd3714 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -94,6 +94,8 @@ public: printf("Not held!\n"); } #endif + // Raise the mutex, so that the following cancel() callback could cancel + // the background processing. mtx.unlock(); cancel(); m_state[step] = INVALID; @@ -393,7 +395,16 @@ public: bool reload_model_instances(); void add_model_object(ModelObject* model_object, int idx = -1); bool apply_config(DynamicPrintConfig config); - bool apply(const Model &model, const DynamicPrintConfig &config); + enum ApplyStatus { + // No change after the Print::apply() call. + APPLY_STATUS_UNCHANGED, + // Some of the Print / PrintObject / PrintObjectInstance data was changed, + // but no result was invalidated (only data influencing not yet calculated results were changed). + APPLY_STATUS_CHANGED, + // Some data was changed, which in turn invalidated already calculated steps. + APPLY_STATUS_INVALIDATED, + }; + ApplyStatus apply(const Model &model, const DynamicPrintConfig &config); void process(); void export_gcode(const std::string &path_template, GCodePreviewData *preview_data); @@ -434,6 +445,9 @@ public: const PrintRegionPtrs& regions() const { return m_regions; } const PlaceholderParser& placeholder_parser() const { return m_placeholder_parser; } PlaceholderParser& placeholder_parser() { return m_placeholder_parser; } + // How many of PrintObject::copies() over all print objects are there? + // If zero, then the print is empty and the print shall not be executed. + unsigned int num_object_instances() const; // Returns extruder this eec should be printed with, according to PrintRegion config: static int get_extruder(const ExtrusionEntityCollection& fill, const PrintRegion ®ion); diff --git a/src/slic3r/GUI/BackgroundSlicingProcess.cpp b/src/slic3r/GUI/BackgroundSlicingProcess.cpp index 71250598b7..3ed5d6bfc8 100644 --- a/src/slic3r/GUI/BackgroundSlicingProcess.cpp +++ b/src/slic3r/GUI/BackgroundSlicingProcess.cpp @@ -132,6 +132,7 @@ bool BackgroundSlicingProcess::start() if (! this->idle()) throw std::runtime_error("Cannot start a background task, the worker thread is not idle."); m_state = STATE_STARTED; + m_print->set_cancel_callback([this](){ this->stop(); }); lck.unlock(); m_condition.notify_one(); return true; @@ -151,9 +152,11 @@ bool BackgroundSlicingProcess::stop() m_condition.wait(lck, [this](){ return m_state == STATE_CANCELED; }); // In the "Canceled" state. Reset the state to "Idle". m_state = STATE_IDLE; + m_print->set_cancel_callback([](){}); } else if (m_state == STATE_FINISHED || m_state == STATE_CANCELED) { // In the "Finished" or "Canceled" state. Reset the state to "Idle". m_state = STATE_IDLE; + m_print->set_cancel_callback([](){}); } // this->m_export_path.clear(); return true; @@ -170,10 +173,10 @@ bool BackgroundSlicingProcess::apply_config(const DynamicPrintConfig &config) // Apply config over the print. Returns false, if the new config values caused any of the already // processed steps to be invalidated, therefore the task will need to be restarted. -bool BackgroundSlicingProcess::apply(const Model &model, const DynamicPrintConfig &config) +Print::ApplyStatus BackgroundSlicingProcess::apply(const Model &model, const DynamicPrintConfig &config) { - this->stop(); - bool invalidated = m_print->apply(model, config); +// this->stop(); + Print::ApplyStatus invalidated = m_print->apply(model, config); return invalidated; } diff --git a/src/slic3r/GUI/BackgroundSlicingProcess.hpp b/src/slic3r/GUI/BackgroundSlicingProcess.hpp index 4265d1227f..dab40d3a8b 100644 --- a/src/slic3r/GUI/BackgroundSlicingProcess.hpp +++ b/src/slic3r/GUI/BackgroundSlicingProcess.hpp @@ -13,7 +13,6 @@ namespace Slic3r { class DynamicPrintConfig; class GCodePreviewData; class Model; -class Print; // Print step IDs for keeping track of the print state. enum BackgroundSlicingProcessStep { @@ -50,7 +49,7 @@ public: bool apply_config(const DynamicPrintConfig &config); // Apply config over the print. Returns false, if the new config values caused any of the already // processed steps to be invalidated, therefore the task will need to be restarted. - bool apply(const Model &model, const DynamicPrintConfig &config); + Print::ApplyStatus apply(const Model &model, const DynamicPrintConfig &config); // Set the export path of the G-code. // Once the path is set, the G-code void schedule_export(const std::string &path); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index fa8368b4dc..e397601845 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1647,35 +1647,32 @@ void Plater::priv::async_apply_config() this->q->model().update_print_volume_state(print_volume); // Apply new config to the possibly running background task. - bool was_running = this->background_process.running(); - bool invalidated = this->background_process.apply(this->q->model(), std::move(config)); + Print::ApplyStatus invalidated = this->background_process.apply(this->q->model(), std::move(config)); // Just redraw the 3D canvas without reloading the scene to consume the update of the layer height profile. if (Slic3r::_3DScene::is_layers_editing_enabled(this->canvas3D)) this->canvas3D->Refresh(); - // If the apply_config caused the calculation to stop, or it was not running yet: - if (invalidated) { - if (was_running) { - // Hide the slicing results if the current slicing status is no more valid. - this->sidebar->show_info_sizers(false); - } - if (this->get_config("background_processing") == "1") - this->background_process.start(); - if (was_running) { - // Reset preview canvases. If the print has been invalidated, the preview canvases will be cleared. - // Otherwise they will be just refreshed. - this->gcode_preview_data.reset(); - if (this->preview != nullptr) - this->preview->reload_print(); - // We also need to reload 3D scene because of the wipe tower preview box - if (this->config->opt_bool("wipe_tower")) { + + if (invalidated == Print::APPLY_STATUS_INVALIDATED) { + // Some previously calculated data on the Print was invalidated. + // Hide the slicing results, as the current slicing status is no more valid. + this->sidebar->show_info_sizers(false); + // Reset preview canvases. If the print has been invalidated, the preview canvases will be cleared. + // Otherwise they will be just refreshed. + this->gcode_preview_data.reset(); + if (this->preview != nullptr) + this->preview->reload_print(); + // We also need to reload 3D scene because of the wipe tower preview box + if (this->config->opt_bool("wipe_tower")) { #if !ENABLE_EXTENDED_SELECTION - std::vector selections = this->collect_selections(); - Slic3r::_3DScene::set_objects_selections(this->canvas3D, selections); - Slic3r::_3DScene::reload_scene(this->canvas3D, 1); + std::vector selections = this->collect_selections(); + Slic3r::_3DScene::set_objects_selections(this->canvas3D, selections); + Slic3r::_3DScene::reload_scene(this->canvas3D, 1); #endif /* !ENABLE_EXTENDED_SELECTION */ - } } } + if (invalidated != Print::APPLY_STATUS_UNCHANGED && this->get_config("background_processing") == "1" && + this->print.num_object_instances() > 0) + this->background_process.start(); } void Plater::priv::start_background_process() @@ -1844,7 +1841,7 @@ void Plater::priv::on_process_completed(wxCommandEvent &evt) this->statusbar()->set_status_text(message); } - //$self->print_info_box_show(1); + this->sidebar->show_info_sizers(false); // this updates buttons status //$self->object_list_changed; From 894020986595ff74617300eabcde6404a747f2f0 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Wed, 24 Oct 2018 10:46:18 +0200 Subject: [PATCH 161/186] Fixed menu view accelerator keys --- src/slic3r/GUI/MainFrame.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 5960e8886a..8dd8ac3e2b 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -328,14 +328,17 @@ void MainFrame::init_menubar() // View menu if (m_plater) { m_viewMenu = new wxMenu(); - append_menu_item(m_viewMenu, wxID_ANY, _(L("Iso\t0")), _(L("Iso View")), [this](wxCommandEvent&){ select_view("iso"); }); + // \xA0 is a non-breaing space. It is entered here to spoil the automatic accelerators, + // as the simple numeric accelerators spoil all numeric data entry. + // The camera control accelerators are captured by GLCanvas3D::on_char(). + append_menu_item(m_viewMenu, wxID_ANY, _(L("Iso")) + "\t\xA0" + "0", _(L("Iso View")), [this](wxCommandEvent&){ select_view("iso"); }); m_viewMenu->AppendSeparator(); - append_menu_item(m_viewMenu, wxID_ANY, _(L("Top\t1")), _(L("Top View")), [this](wxCommandEvent&){ select_view("top"); }); - append_menu_item(m_viewMenu, wxID_ANY, _(L("Bottom\t2")), _(L("Bottom View")), [this](wxCommandEvent&){ select_view("bottom"); }); - append_menu_item(m_viewMenu, wxID_ANY, _(L("Front\t3")), _(L("Front View")), [this](wxCommandEvent&){ select_view("front"); }); - append_menu_item(m_viewMenu, wxID_ANY, _(L("Rear\t4")), _(L("Rear View")), [this](wxCommandEvent&){ select_view("rear"); }); - append_menu_item(m_viewMenu, wxID_ANY, _(L("Left\t5")), _(L("Left View")), [this](wxCommandEvent&){ select_view("left"); }); - append_menu_item(m_viewMenu, wxID_ANY, _(L("Right\t6")), _(L("Right View")), [this](wxCommandEvent&){ select_view("right"); }); + append_menu_item(m_viewMenu, wxID_ANY, _(L("Top")) + "\t\xA0" + "1", _(L("Top View")), [this](wxCommandEvent&){ select_view("top"); }); + append_menu_item(m_viewMenu, wxID_ANY, _(L("Bottom")) + "\t\xA0" + "2", _(L("Bottom View")), [this](wxCommandEvent&){ select_view("bottom"); }); + append_menu_item(m_viewMenu, wxID_ANY, _(L("Front")) + "\t\xA0" + "3", _(L("Front View")), [this](wxCommandEvent&){ select_view("front"); }); + append_menu_item(m_viewMenu, wxID_ANY, _(L("Rear")) + "\t\xA0" + "4", _(L("Rear View")), [this](wxCommandEvent&){ select_view("rear"); }); + append_menu_item(m_viewMenu, wxID_ANY, _(L("Left")) + "\t\xA0" + "5", _(L("Left View")), [this](wxCommandEvent&){ select_view("left"); }); + append_menu_item(m_viewMenu, wxID_ANY, _(L("Right")) + "\t\xA0" + "6", _(L("Right View")), [this](wxCommandEvent&){ select_view("right"); }); } // Help menu From 37e4f69e3b2a1b1a58edb5930b53fe4dd0ef8df1 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Wed, 24 Oct 2018 10:55:35 +0200 Subject: [PATCH 162/186] Fixed memory leak in GLToolbar --- src/slic3r/GUI/GLToolbar.cpp | 8 ++++++++ src/slic3r/GUI/GLToolbar.hpp | 1 + 2 files changed, 9 insertions(+) diff --git a/src/slic3r/GUI/GLToolbar.cpp b/src/slic3r/GUI/GLToolbar.cpp index ec203541e9..e094e11059 100644 --- a/src/slic3r/GUI/GLToolbar.cpp +++ b/src/slic3r/GUI/GLToolbar.cpp @@ -149,6 +149,14 @@ GLToolbar::GLToolbar(GLCanvas3D& parent) { } +GLToolbar::~GLToolbar() +{ + for (GLToolbarItem* item : m_items) + { + delete item; + } +} + bool GLToolbar::init(const std::string& icons_texture_filename, unsigned int items_icon_size, unsigned int items_icon_border_size, unsigned int items_icon_gap_size) { std::string path = resources_dir() + "/icons/"; diff --git a/src/slic3r/GUI/GLToolbar.hpp b/src/slic3r/GUI/GLToolbar.hpp index 7c0f5bf84e..2161717531 100644 --- a/src/slic3r/GUI/GLToolbar.hpp +++ b/src/slic3r/GUI/GLToolbar.hpp @@ -141,6 +141,7 @@ private: public: explicit GLToolbar(GLCanvas3D& parent); + ~GLToolbar(); bool init(const std::string& icons_texture_filename, unsigned int items_icon_size, unsigned int items_icon_border_size, unsigned int items_icon_gap_size); From 481229da974627f1c361bce3c256ae440cb4d701 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Wed, 24 Oct 2018 11:05:19 +0200 Subject: [PATCH 163/186] CancellationCallback is now passed by value, instead of non-const reference (which would require initializing the reference from temporaries) --- src/libslic3r/Print.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index bd04cd3714..a00ef5c9ee 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -86,7 +86,7 @@ public: // In case the step has already been entered or finished, cancel the background // processing by calling the cancel callback. template - bool invalidate(StepType step, tbb::mutex &mtx, CancelationCallback &cancel) { + bool invalidate(StepType step, tbb::mutex &mtx, CancelationCallback cancel) { bool invalidated = m_state[step].load(std::memory_order_relaxed) != INVALID; if (invalidated) { #if 0 @@ -109,7 +109,7 @@ public: // In case any step has already been entered or finished, cancel the background // processing by calling the cancel callback. template - bool invalidate_all(tbb::mutex &mtx, CancelationCallback &cancel) { + bool invalidate_all(tbb::mutex &mtx, CancelationCallback cancel) { bool invalidated = false; for (size_t i = 0; i < COUNT; ++ i) if (m_state[i].load(std::memory_order_relaxed) != INVALID) { From 197458cf3a9ede7fd43f4124599c7584e8500f4a Mon Sep 17 00:00:00 2001 From: bubnikv Date: Wed, 24 Oct 2018 11:48:39 +0200 Subject: [PATCH 164/186] Background processing: Fixed rotation & scaling of PrintObjects. --- src/libslic3r/Print.cpp | 6 ++++-- src/libslic3r/Print.hpp | 2 ++ src/libslic3r/PrintObject.cpp | 5 +---- src/slic3r/GUI/Plater.cpp | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 7815391e92..6253f4e898 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -946,6 +946,7 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co // Simple case, just generate new instances. for (const PrintInstances &print_instances : new_print_instances) { PrintObject *print_object = new PrintObject(this, model_object, model_object->raw_bounding_box()); + print_object->set_trafo(print_instances.trafo); print_object->set_copies(print_instances.copies); print_object->config_apply(config); print_objects_new.emplace_back(print_object); @@ -959,10 +960,11 @@ Print::ApplyStatus Print::apply(const Model &model, const DynamicPrintConfig &co // Merge the old / new lists. auto it_old = old.begin(); for (const PrintInstances &new_instances : new_print_instances) { - for (; transform3d_lower((*it_old)->trafo, new_instances.trafo); ++ it_old); - if (! transform3d_equal((*it_old)->trafo, new_instances.trafo)) { + for (; it_old != old.end() && transform3d_lower((*it_old)->trafo, new_instances.trafo); ++ it_old); + if (it_old == old.end() || ! transform3d_equal((*it_old)->trafo, new_instances.trafo)) { // This is a new instance (or a set of instances with the same trafo). Just add it. PrintObject *print_object = new PrintObject(this, model_object, model_object->raw_bounding_box()); + print_object->set_trafo(new_instances.trafo); print_object->set_copies(new_instances.copies); print_object->config_apply(config); print_objects_new.emplace_back(print_object); diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index bd04cd3714..5127b588ee 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -203,7 +203,9 @@ public: void config_apply_only(const ConfigBase &other, const t_config_option_keys &keys, bool ignore_nonexistent = false) { this->m_config.apply_only(other, keys, ignore_nonexistent); } const LayerPtrs& layers() const { return m_layers; } const SupportLayerPtrs& support_layers() const { return m_support_layers; } + const Transform3d& trafo() const { return m_trafo; } + void set_trafo(const Transform3d& trafo) { m_trafo = trafo; } const Points& copies() const { return m_copies; } bool add_copy(const Vec2d &point); diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 38b2e678b9..b7b33087f4 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -1615,10 +1615,7 @@ std::vector PrintObject::_slice_volumes(const std::vector &z, for (const ModelVolume *v : volumes) mesh.merge(v->mesh); if (mesh.stl.stats.number_of_facets > 0) { - // transform mesh - // we ignore the per-instance transformations currently and only - // consider the first one - this->model_object()->instances.front()->transform_mesh(&mesh, true); + mesh.transform(m_trafo.cast()); // align mesh to Z = 0 (it should be already aligned actually) and apply XY shift mesh.translate(- unscale(m_copies_shift(0)), - unscale(m_copies_shift(1)), - float(this->model_object()->bounding_box().min(2))); // perform actual slicing diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index e397601845..8fdb5fd3b8 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -2408,7 +2408,7 @@ void Plater::reslice() // Don't reslice if export of G-code or sending to OctoPrint is running. // if (! defined($self->{export_gcode_output_file}) && ! defined($self->{send_gcode_file})) { // Stop the background processing threads, stop the async update timer. - this->p->stop_background_process(); +// this->p->stop_background_process(); // Rather perform one additional unnecessary update of the print object instead of skipping a pending async update. this->p->async_apply_config(); /* From 90ecbce9bbbd4502f0d89bb9bc824e0c3dec07b5 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Wed, 24 Oct 2018 12:55:38 +0200 Subject: [PATCH 165/186] Split to objects and Split to parts --- src/slic3r/GUI/GLCanvas3D.cpp | 14 +++++++-- src/slic3r/GUI/GLToolbar.cpp | 3 +- src/slic3r/GUI/GLToolbar.hpp | 3 +- src/slic3r/GUI/Plater.cpp | 54 ++++++++++++++++++++++++++++------- 4 files changed, 59 insertions(+), 15 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 9928e43343..f8f7cb0bcf 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -4588,11 +4588,19 @@ bool GLCanvas3D::_init_toolbar() if (!m_toolbar.add_separator()) return false; - item.name = "split"; - item.tooltip = GUI::L_str("Split"); + item.name = "splitobjects"; + item.tooltip = GUI::L_str("Split to objects"); item.sprite_id = 6; item.is_toggable = false; - item.action_event = EVT_GLTOOLBAR_SPLIT; + item.action_event = EVT_GLTOOLBAR_SPLIT_OBJECTS; + if (!m_toolbar.add_item(item)) + return false; + + item.name = "splitvolumes"; + item.tooltip = GUI::L_str("Split to parts"); + item.sprite_id = 6; + item.is_toggable = false; + item.action_event = EVT_GLTOOLBAR_SPLIT_VOLUMES; if (!m_toolbar.add_item(item)) return false; diff --git a/src/slic3r/GUI/GLToolbar.cpp b/src/slic3r/GUI/GLToolbar.cpp index e094e11059..71ff3cf481 100644 --- a/src/slic3r/GUI/GLToolbar.cpp +++ b/src/slic3r/GUI/GLToolbar.cpp @@ -22,7 +22,8 @@ wxDEFINE_EVENT(EVT_GLTOOLBAR_DELETE_ALL, SimpleEvent); wxDEFINE_EVENT(EVT_GLTOOLBAR_ARRANGE, SimpleEvent); wxDEFINE_EVENT(EVT_GLTOOLBAR_MORE, SimpleEvent); wxDEFINE_EVENT(EVT_GLTOOLBAR_FEWER, SimpleEvent); -wxDEFINE_EVENT(EVT_GLTOOLBAR_SPLIT, SimpleEvent); +wxDEFINE_EVENT(EVT_GLTOOLBAR_SPLIT_OBJECTS, SimpleEvent); +wxDEFINE_EVENT(EVT_GLTOOLBAR_SPLIT_VOLUMES, SimpleEvent); wxDEFINE_EVENT(EVT_GLTOOLBAR_CUT, SimpleEvent); #if !ENABLE_EXTENDED_SELECTION wxDEFINE_EVENT(EVT_GLTOOLBAR_SETTINGS, SimpleEvent); diff --git a/src/slic3r/GUI/GLToolbar.hpp b/src/slic3r/GUI/GLToolbar.hpp index 2161717531..9f3853530c 100644 --- a/src/slic3r/GUI/GLToolbar.hpp +++ b/src/slic3r/GUI/GLToolbar.hpp @@ -22,7 +22,8 @@ wxDECLARE_EVENT(EVT_GLTOOLBAR_DELETE_ALL, SimpleEvent); wxDECLARE_EVENT(EVT_GLTOOLBAR_ARRANGE, SimpleEvent); wxDECLARE_EVENT(EVT_GLTOOLBAR_MORE, SimpleEvent); wxDECLARE_EVENT(EVT_GLTOOLBAR_FEWER, SimpleEvent); -wxDECLARE_EVENT(EVT_GLTOOLBAR_SPLIT, SimpleEvent); +wxDECLARE_EVENT(EVT_GLTOOLBAR_SPLIT_OBJECTS, SimpleEvent); +wxDECLARE_EVENT(EVT_GLTOOLBAR_SPLIT_VOLUMES, SimpleEvent); wxDECLARE_EVENT(EVT_GLTOOLBAR_CUT, SimpleEvent); #if !ENABLE_EXTENDED_SELECTION wxDECLARE_EVENT(EVT_GLTOOLBAR_SETTINGS, SimpleEvent); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 8fdb5fd3b8..5c55229095 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -795,6 +795,7 @@ struct Plater::priv #endif // !ENABLE_EXTENDED_SELECTION void arrange(); void split_object(); + void split_volume(); void schedule_background_process(); void async_apply_config(); void start_background_process(); @@ -812,7 +813,8 @@ struct Plater::priv void on_layer_editing_toggled(bool enable); void on_action_add(SimpleEvent&); - void on_action_split(SimpleEvent&); + void on_action_split_objects(SimpleEvent&); + void on_action_split_volumes(SimpleEvent&); void on_action_cut(SimpleEvent&); #if !ENABLE_EXTENDED_SELECTION void on_action_settings(SimpleEvent&); @@ -844,7 +846,8 @@ private: bool can_delete_object() const; bool can_increase_instances() const; bool can_decrease_instances() const; - bool can_split_object() const; + bool can_split_to_objects() const; + bool can_split_to_volumes() const; bool can_cut_object() const; bool layers_height_allowed() const; bool can_delete_all() const; @@ -958,7 +961,8 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) : canvas3D->Bind(EVT_GLTOOLBAR_ARRANGE, [this](SimpleEvent&) { arrange(); }); canvas3D->Bind(EVT_GLTOOLBAR_MORE, [q](SimpleEvent&) { q->increase_instances(); }); canvas3D->Bind(EVT_GLTOOLBAR_FEWER, [q](SimpleEvent&) { q->decrease_instances(); }); - canvas3D->Bind(EVT_GLTOOLBAR_SPLIT, &priv::on_action_split, this); + canvas3D->Bind(EVT_GLTOOLBAR_SPLIT_OBJECTS, &priv::on_action_split_objects, this); + canvas3D->Bind(EVT_GLTOOLBAR_SPLIT_VOLUMES, &priv::on_action_split_volumes, this); canvas3D->Bind(EVT_GLTOOLBAR_CUT, &priv::on_action_cut, this); #if !ENABLE_EXTENDED_SELECTION canvas3D->Bind(EVT_GLTOOLBAR_SETTINGS, &priv::on_action_settings, this); @@ -1356,12 +1360,14 @@ void Plater::priv::selection_changed() _3DScene::enable_toolbar_item(canvas3D, "delete", can_delete_object()); _3DScene::enable_toolbar_item(canvas3D, "more", can_increase_instances()); _3DScene::enable_toolbar_item(canvas3D, "fewer", can_decrease_instances()); - _3DScene::enable_toolbar_item(canvas3D, "split", can_split_object()); + _3DScene::enable_toolbar_item(canvas3D, "splitobjects", can_split_to_objects()); + _3DScene::enable_toolbar_item(canvas3D, "splitvolumes", can_split_to_volumes()); _3DScene::enable_toolbar_item(canvas3D, "cut", can_cut_object()); _3DScene::enable_toolbar_item(canvas3D, "layersediting", layers_height_allowed()); #else _3DScene::enable_toolbar_item(canvas3D, "fewer", have_sel); - _3DScene::enable_toolbar_item(canvas3D, "split", have_sel); + _3DScene::enable_toolbar_item(canvas3D, "splitobjects", have_sel); + _3DScene::enable_toolbar_item(canvas3D, "splitvolumes", have_sel); _3DScene::enable_toolbar_item(canvas3D, "cut", have_sel); _3DScene::enable_toolbar_item(canvas3D, "settings", have_sel); _3DScene::enable_toolbar_item(canvas3D, "layersediting", have_sel && config->opt_bool("variable_layer_height") && _3DScene::is_layers_editing_allowed(canvas3D)); @@ -1617,8 +1623,10 @@ void Plater::priv::split_object() } else { + unsigned int counter = 1; for (ModelObject* m : new_objects) { + m->name = current_model_object->name + "_" + std::to_string(counter++); m->center_around_origin(); } @@ -1631,6 +1639,11 @@ void Plater::priv::split_object() #endif // ENABLE_EXTENDED_SELECTION } +void Plater::priv::split_volume() +{ + wxGetApp().obj_list()->split(false); +} + void Plater::priv::schedule_background_process() { // Trigger the timer event after 0.5s @@ -1868,11 +1881,16 @@ void Plater::priv::on_action_add(SimpleEvent&) q->add(); } -void Plater::priv::on_action_split(SimpleEvent&) +void Plater::priv::on_action_split_objects(SimpleEvent&) { split_object(); } +void Plater::priv::on_action_split_volumes(SimpleEvent&) +{ + split_volume(); +} + void Plater::priv::on_action_cut(SimpleEvent&) { // TODO @@ -2031,8 +2049,16 @@ bool Plater::priv::init_object_menu() wxMenuItem* item_mirror = append_submenu(&object_menu, mirror_menu, wxID_ANY, _(L("Mirror")), _(L("Mirror the selected object"))); #endif // ENABLE_MIRROR - wxMenuItem* item_split = append_menu_item(&object_menu, wxID_ANY, _(L("Split")), _(L("Split the selected object into individual parts")), - [this](wxCommandEvent&){ split_object(); }, "shape_ungroup.png"); + wxMenu* split_menu = new wxMenu(); + if (split_menu == nullptr) + return false; + + wxMenuItem* item_split_objects = append_menu_item(split_menu, wxID_ANY, _(L("To objects")), _(L("Split the selected object into individual objects")), + [this](wxCommandEvent&){ split_object(); }, "shape_ungroup.png", &object_menu); + wxMenuItem* item_split_volumes = append_menu_item(split_menu, wxID_ANY, _(L("To parts")), _(L("Split the selected object into individual sub-parts")), + [this](wxCommandEvent&){ split_volume(); }, "shape_ungroup.png", &object_menu); + + wxMenuItem* item_split = append_submenu(&object_menu, split_menu, wxID_ANY, _(L("Split")), _(L("Split the selected object")), "shape_ungroup.png"); #if ENABLE_EXTENDED_SELECTION // ui updates needs to be binded to the parent panel @@ -2044,7 +2070,9 @@ bool Plater::priv::init_object_menu() q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_delete_object()); }, item_delete->GetId()); q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_increase_instances()); }, item_increase->GetId()); q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_decrease_instances()); }, item_decrease->GetId()); - q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_split_object()); }, item_split->GetId()); + q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_split_to_objects() || can_split_to_volumes()); }, item_split->GetId()); + q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_split_to_objects()); }, item_split_objects->GetId()); + q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_split_to_volumes()); }, item_split_volumes->GetId()); } #endif // ENABLE_EXTENDED_SELECTION @@ -2070,7 +2098,13 @@ bool Plater::priv::can_decrease_instances() const return (0 <= obj_idx) && (obj_idx < (int)model.objects.size()) && (model.objects[obj_idx]->instances.size() > 1); } -bool Plater::priv::can_split_object() const +bool Plater::priv::can_split_to_objects() const +{ + int obj_idx = get_selected_object_idx(); + return (0 <= obj_idx) && (obj_idx < (int)model.objects.size()) && !model.objects[obj_idx]->is_multiparts(); +} + +bool Plater::priv::can_split_to_volumes() const { int obj_idx = get_selected_object_idx(); return (0 <= obj_idx) && (obj_idx < (int)model.objects.size()) && !model.objects[obj_idx]->is_multiparts(); From e3b4a7b206df9e545bc0ba7894e58dfe3fa80d09 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Wed, 24 Oct 2018 12:57:23 +0200 Subject: [PATCH 166/186] Fixed incorrect m_wiping_dialog_button showing after appInit --- src/slic3r/GUI/GUI_App.cpp | 8 ++++---- src/slic3r/GUI/GUI_App.hpp | 1 + src/slic3r/GUI/MainFrame.cpp | 16 +--------------- src/slic3r/GUI/Plater.cpp | 13 ++++++++++++- src/slic3r/GUI/Tab.cpp | 10 ++++------ 5 files changed, 22 insertions(+), 26 deletions(-) diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index c1683bba34..cabb574286 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -653,7 +653,7 @@ void GUI_App::load_current_presets() Sidebar& GUI_App::sidebar() { - return mainframe->m_plater->sidebar(); + return plater_->sidebar(); } ObjectManipulation* GUI_App::obj_manipul() @@ -668,17 +668,17 @@ ObjectList* GUI_App::obj_list() Plater* GUI_App::plater() { - return mainframe->m_plater; + return plater_; } wxGLCanvas* GUI_App::canvas3D() { - return mainframe->m_plater->canvas3D(); + return plater_->canvas3D(); } ModelObjectPtrs* GUI_App::model_objects() { - return &mainframe->m_plater->model().objects; + return &plater_->model().objects; } wxNotebook* GUI_App::tab_panel() const diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 52d5826903..dcb3685d1f 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -139,6 +139,7 @@ public: PresetBundle* preset_bundle{ nullptr }; PresetUpdater* preset_updater{ nullptr }; MainFrame* mainframe{ nullptr }; + Plater* plater_{ nullptr }; wxNotebook* tab_panel() const ; diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 8dd8ac3e2b..c15532d709 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -139,6 +139,7 @@ void MainFrame::init_tabpanel() if (!m_no_plater) { m_plater = new Slic3r::GUI::Plater(m_tabpanel, this); + wxGetApp().plater_ = m_plater; m_tabpanel->AddPage(m_plater, _(L("Plater"))); } @@ -149,18 +150,6 @@ void MainFrame::init_tabpanel() // or when the preset's "modified" status changes. Bind(EVT_TAB_PRESETS_CHANGED, &MainFrame::on_presets_changed, this); - - // The following event is emited by the C++ Tab implementation on object selection change. -// EVT_COMMAND($self, -1, $OBJECT_SELECTION_CHANGED_EVENT, sub { -// auto obj_idx = event->GetId(); -// // my $child = $event->GetInt == 1 ? 1 : undef; -// // $self->{plater}->select_object($obj_idx < 0 ? undef : $obj_idx, $child); -// // $self->{plater}->item_changed_selection($obj_idx); -// -// auto vol_idx = event->GetInt(); -// m_plater->select_object_from_cpp(obj_idx < 0 ? undef : obj_idx, vol_idx < 0 ? -1 : vol_idx); -// }); - create_preset_tabs(); std::vector tab_names = { "print", "filament", "sla_material", "printer" }; for (auto tab_name : tab_names) @@ -225,9 +214,6 @@ void MainFrame::add_created_tab(Tab* panel) { panel->create_preset_tab(); - // Load the currently selected preset into the GUI, update the preset selection box. - panel->load_current_preset(); - const wxString& tab_name = panel->GetName(); bool add_panel = true; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 5c55229095..2de1cfbf1a 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -244,6 +244,7 @@ public: ~FreqChangedParams() {} wxButton* get_wiping_dialog_button() { return m_wiping_dialog_button; } + void Show(const bool show); }; FreqChangedParams::FreqChangedParams(wxWindow* parent, const int label_width) : @@ -368,6 +369,16 @@ FreqChangedParams::FreqChangedParams(wxWindow* parent, const int label_width) : } +void FreqChangedParams::Show(const bool show) +{ + bool is_wdb_shown = m_wiping_dialog_button->IsShown(); + m_og->sizer->Show(show); + + // correct showing of the FreqChangedParams sizer when m_wiping_dialog_button is hidden + if (show && !is_wdb_shown) + m_wiping_dialog_button->Hide(); +} + // Sidebar / private struct Sidebar::priv @@ -416,7 +427,7 @@ void Sidebar::priv::show_preset_comboboxes() sizer_presets->Show(4, showSLA); sizer_presets->Show(5, showSLA); - frequently_changed_parameters->get_sizer()->Show(!showSLA); + frequently_changed_parameters->Show(!showSLA); wxGetApp().plater()->Layout(); wxGetApp().mainframe->Layout(); diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 1897b4779b..000270e135 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -215,7 +215,9 @@ void Tab::create_preset_tab() // Initialize the DynamicPrintConfig by default keys/values. build(); rebuild_page_tree(); - update(); +// update(); + // Load the currently selected preset into the GUI, update the preset selection box. + load_current_preset(); } void Tab::load_initial_data() @@ -740,9 +742,7 @@ void Tab::update_wiping_button_visibility() { bool multiple_extruders = dynamic_cast((m_preset_bundle->printers.get_edited_preset().config).option("nozzle_diameter"))->values.size() > 1; bool single_extruder_mm = dynamic_cast( (m_preset_bundle->printers.get_edited_preset().config).option("single_extruder_multi_material"))->value; - if (!wxGetApp().mainframe) - return; - auto wiping_dialog_button = wxGetApp().mainframe->m_plater->sidebar().get_wiping_dialog_button(); + auto wiping_dialog_button = wxGetApp().sidebar().get_wiping_dialog_button(); if (wiping_dialog_button) { wiping_dialog_button->Show(wipe_tower_enabled && multiple_extruders && single_extruder_mm); wiping_dialog_button->GetParent()->Layout(); @@ -1862,8 +1862,6 @@ void TabPrinter::extruders_count_changed(size_t extruders_count){ m_preset_bundle->update_multi_material_filament_presets(); build_extruder_pages(); reload_config(); - if (!wxGetApp().mainframe) - return; on_value_change("extruders_count", extruders_count); wxGetApp().sidebar().update_objects_list_extruder_column(extruders_count); } From 9b3e3ec96789563775a7bb352ee25cfc616bc914 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Wed, 24 Oct 2018 13:28:35 +0200 Subject: [PATCH 167/186] Move gizmo -> 1) Grabbers showing tooltip also on hover for single instance selection. 2) Tooltip showing current position for single instance selection. --- src/slic3r/GUI/GLGizmo.cpp | 22 ++++++++++++++++------ src/slic3r/GUI/GLGizmo.hpp | 1 + 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/slic3r/GUI/GLGizmo.cpp b/src/slic3r/GUI/GLGizmo.cpp index 2f75d43fd0..1bd9cc235d 100644 --- a/src/slic3r/GUI/GLGizmo.cpp +++ b/src/slic3r/GUI/GLGizmo.cpp @@ -1241,6 +1241,13 @@ void GLGizmoMove3D::on_start_dragging(const BoundingBoxf3& box) } } +#if ENABLE_EXTENDED_SELECTION +void GLGizmoMove3D::on_stop_dragging() +{ + m_displacement = Vec3d::Zero(); +} +#endif // ENABLE_EXTENDED_SELECTION + void GLGizmoMove3D::on_update(const Linef3& mouse_ray) { #if ENABLE_EXTENDED_SELECTION @@ -1267,12 +1274,15 @@ void GLGizmoMove3D::on_render(const BoundingBoxf3& box) const #endif // ENABLE_EXTENDED_SELECTION { #if ENABLE_EXTENDED_SELECTION - if (m_grabbers[0].dragging) - set_tooltip("X: " + format(m_displacement(0), 2)); - else if (m_grabbers[1].dragging) - set_tooltip("Y: " + format(m_displacement(1), 2)); - else if (m_grabbers[2].dragging) - set_tooltip("Z: " + format(m_displacement(2), 2)); + bool show_position = selection.is_single_full_instance(); + const Vec3d& position = selection.get_bounding_box().center(); + + if ((show_position && (m_hover_id == 0)) || m_grabbers[0].dragging) + set_tooltip("X: " + format(show_position ? position(0) : m_displacement(0), 2)); + else if ((show_position && (m_hover_id == 1)) || m_grabbers[1].dragging) + set_tooltip("Y: " + format(show_position ? position(1) : m_displacement(1), 2)); + else if ((show_position && (m_hover_id == 2)) || m_grabbers[2].dragging) + set_tooltip("Z: " + format(show_position ? position(2) : m_displacement(2), 2)); #else if (m_grabbers[0].dragging) set_tooltip("X: " + format(m_position(0), 2)); diff --git a/src/slic3r/GUI/GLGizmo.hpp b/src/slic3r/GUI/GLGizmo.hpp index 1f2b77ab80..38f72598e5 100644 --- a/src/slic3r/GUI/GLGizmo.hpp +++ b/src/slic3r/GUI/GLGizmo.hpp @@ -391,6 +391,7 @@ protected: virtual bool on_init(); #if ENABLE_EXTENDED_SELECTION virtual void on_start_dragging(const GLCanvas3D::Selection& selection); + virtual void on_stop_dragging(); #else virtual void on_start_dragging(const BoundingBoxf3& box); #endif // ENABLE_EXTENDED_SELECTION From 17b7a3b9d7cf93d4deebf518a80cc4a4f2d56420 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Wed, 24 Oct 2018 13:56:43 +0200 Subject: [PATCH 168/186] Scale gizmo -> Grabbers showing tooltip also on hover for single instance selection. --- src/slic3r/GUI/GLGizmo.cpp | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/GLGizmo.cpp b/src/slic3r/GUI/GLGizmo.cpp index 1bd9cc235d..0cf34436d6 100644 --- a/src/slic3r/GUI/GLGizmo.cpp +++ b/src/slic3r/GUI/GLGizmo.cpp @@ -848,6 +848,25 @@ void GLGizmoScale3D::on_render(const GLCanvas3D::Selection& selection) const void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const #endif // ENABLE_EXTENDED_SELECTION { +#if ENABLE_EXTENDED_SELECTION + bool single_instance = selection.is_single_full_instance(); + Vec3f scale = single_instance ? 100.0f * selection.get_volume(*selection.get_volume_idxs().begin())->get_scaling_factor().cast() : 100.0f * m_scale.cast(); + + if ((single_instance && ((m_hover_id == 0) || (m_hover_id == 1))) || m_grabbers[0].dragging || m_grabbers[1].dragging) + set_tooltip("X: " + format(scale(0), 4) + "%"); + else if ((single_instance && ((m_hover_id == 2) || (m_hover_id == 3))) || m_grabbers[2].dragging || m_grabbers[3].dragging) + set_tooltip("Y: " + format(scale(1), 4) + "%"); + else if ((single_instance && ((m_hover_id == 4) || (m_hover_id == 5))) || m_grabbers[4].dragging || m_grabbers[5].dragging) + set_tooltip("Z: " + format(scale(2), 4) + "%"); + else if ((single_instance && ((m_hover_id == 6) || (m_hover_id == 7) || (m_hover_id == 8) || (m_hover_id == 9))) + || m_grabbers[6].dragging || m_grabbers[7].dragging || m_grabbers[8].dragging || m_grabbers[9].dragging) + { + std::string tooltip = "X: " + format(scale(0), 4) + "%\n"; + tooltip += "Y: " + format(scale(1), 4) + "%\n"; + tooltip += "Z: " + format(scale(2), 4) + "%"; + set_tooltip(tooltip); + } +#else if (m_grabbers[0].dragging || m_grabbers[1].dragging) set_tooltip("X: " + format(100.0f * m_scale(0), 4) + "%"); else if (m_grabbers[2].dragging || m_grabbers[3].dragging) @@ -861,6 +880,7 @@ void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const tooltip += "Z: " + format(100.0f * m_scale(2), 4) + "%"; set_tooltip(tooltip); } +#endif // ENABLE_EXTENDED_SELECTION ::glEnable(GL_DEPTH_TEST); @@ -870,7 +890,7 @@ void GLGizmoScale3D::on_render(const BoundingBoxf3& box) const Vec3d angles = Vec3d::Zero(); Transform3d offsets_transform = Transform3d::Identity(); - if (selection.is_from_single_instance()) + if (single_instance) { // calculate bounding box in instance local reference system const GLCanvas3D::Selection::IndicesList& idxs = selection.get_volume_idxs(); From 56633c7449127d0894dd8c697033309f62781ccd Mon Sep 17 00:00:00 2001 From: bubnikv Date: Wed, 24 Oct 2018 13:59:24 +0200 Subject: [PATCH 169/186] Reverted Print::export_png() for the Perl unit tests. --- xs/xsp/Print.xsp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/xs/xsp/Print.xsp b/xs/xsp/Print.xsp index 39708ca7a9..b34444b231 100644 --- a/xs/xsp/Print.xsp +++ b/xs/xsp/Print.xsp @@ -185,6 +185,14 @@ _constant() } %}; + void export_gcode(char *path_template) %code%{ + try { + THIS->export_gcode(path_template, nullptr); + } catch (std::exception& e) { + croak(e.what()); + } + %}; + void export_png(char *path) %code%{ try { THIS->export_png(path); From 77d6ebc1266dbf80061cc72606f1cc2f1b593442 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Wed, 24 Oct 2018 14:12:33 +0200 Subject: [PATCH 170/186] Rotate gizmo -> Grabbers showing tooltip also on hover for single instance selection. --- src/slic3r/GUI/GLGizmo.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/GLGizmo.cpp b/src/slic3r/GUI/GLGizmo.cpp index 0cf34436d6..c6740abc3c 100644 --- a/src/slic3r/GUI/GLGizmo.cpp +++ b/src/slic3r/GUI/GLGizmo.cpp @@ -445,10 +445,22 @@ void GLGizmoRotate::on_render(const BoundingBoxf3& box) const #if ENABLE_EXTENDED_SELECTION const BoundingBoxf3& box = selection.get_bounding_box(); -#endif // ENABLE_EXTENDED_SELECTION + bool single_instance = selection.is_single_full_instance(); + std::string axis; + switch (m_axis) + { + case X: { axis = "X: "; break; } + case Y: { axis = "Y: "; break; } + case Z: { axis = "Z: "; break; } + } + + if ((single_instance && (m_hover_id == 0)) || m_dragging) + set_tooltip(axis + format((float)Geometry::rad2deg(m_angle), 4) + "°"); +#else if (m_dragging) set_tooltip(format(m_angle * 180.0f / (float)PI, 4)); +#endif // ENABLE_EXTENDED_SELECTION else { m_center = box.center(); From 9e0e41af8fea4182429f2ffe58d919a73b3b26ff Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Wed, 24 Oct 2018 14:17:56 +0200 Subject: [PATCH 171/186] fix compilation of libnest2d on mac --- .../include/libnest2d/geometry_traits_nfp.hpp | 454 ------------------ src/libnest2d/tests/test.cpp | 54 --- 2 files changed, 508 deletions(-) diff --git a/src/libnest2d/include/libnest2d/geometry_traits_nfp.hpp b/src/libnest2d/include/libnest2d/geometry_traits_nfp.hpp index cb0580ef4f..b57b8dc536 100644 --- a/src/libnest2d/include/libnest2d/geometry_traits_nfp.hpp +++ b/src/libnest2d/include/libnest2d/geometry_traits_nfp.hpp @@ -251,460 +251,6 @@ inline NfpResult nfpConvexOnly(const RawShape& sh, return {rsh, top_nfp}; } -template -NfpResult nfpSimpleSimple(const RawShape& cstationary, - const RawShape& cother) -{ - - // Algorithms are from the original algorithm proposed in paper: - // https://eprints.soton.ac.uk/36850/1/CORMSIS-05-05.pdf - - // ///////////////////////////////////////////////////////////////////////// - // Algorithm 1: Obtaining the minkowski sum - // ///////////////////////////////////////////////////////////////////////// - - // I guess this is not a full minkowski sum of the two input polygons by - // definition. This yields a subset that is compatible with the next 2 - // algorithms. - - using Result = NfpResult; - using Vertex = TPoint; - using Coord = TCoord; - using Edge = _Segment; - namespace sl = shapelike; - using std::signbit; - using std::sort; - using std::vector; - using std::ref; - using std::reference_wrapper; - - // TODO The original algorithms expects the stationary polygon in - // counter clockwise and the orbiter in clockwise order. - // So for preventing any further complication, I will make the input - // the way it should be, than make my way around the orientations. - - // Reverse the stationary contour to counter clockwise - auto stcont = sl::contour(cstationary); - { - std::reverse(sl::begin(stcont), sl::end(stcont)); - stcont.pop_back(); - auto it = std::min_element(sl::begin(stcont), sl::end(stcont), - [](const Vertex& v1, const Vertex& v2) { - return getY(v1) < getY(v2); - }); - std::rotate(sl::begin(stcont), it, sl::end(stcont)); - sl::addVertex(stcont, sl::front(stcont)); - } - RawShape stationary; - sl::contour(stationary) = stcont; - - // Reverse the orbiter contour to counter clockwise - auto orbcont = sl::contour(cother); - { - std::reverse(orbcont.begin(), orbcont.end()); - - // Step 1: Make the orbiter reverse oriented - - orbcont.pop_back(); - auto it = std::min_element(orbcont.begin(), orbcont.end(), - [](const Vertex& v1, const Vertex& v2) { - return getY(v1) < getY(v2); - }); - - std::rotate(orbcont.begin(), it, orbcont.end()); - orbcont.emplace_back(orbcont.front()); - - for(auto &v : orbcont) v = -v; - - } - - // Copy the orbiter (contour only), we will have to work on it - RawShape orbiter; - sl::contour(orbiter) = orbcont; - - // An edge with additional data for marking it - struct MarkedEdge { - Edge e; Radians turn_angle = 0; bool is_turning_point = false; - MarkedEdge() = default; - MarkedEdge(const Edge& ed, Radians ta, bool tp): - e(ed), turn_angle(ta), is_turning_point(tp) {} - - // debug - std::string label; - }; - - // Container for marked edges - using EdgeList = vector; - - EdgeList A, B; - - // This is how an edge list is created from the polygons - auto fillEdgeList = [](EdgeList& L, const RawShape& ppoly, int dir) { - auto& poly = sl::contour(ppoly); - - L.reserve(sl::contourVertexCount(poly)); - - if(dir > 0) { - auto it = poly.begin(); - auto nextit = std::next(it); - - double turn_angle = 0; - bool is_turn_point = false; - - while(nextit != poly.end()) { - L.emplace_back(Edge(*it, *nextit), turn_angle, is_turn_point); - it++; nextit++; - } - } else { - auto it = sl::rbegin(poly); - auto nextit = std::next(it); - - double turn_angle = 0; - bool is_turn_point = false; - - while(nextit != sl::rend(poly)) { - L.emplace_back(Edge(*it, *nextit), turn_angle, is_turn_point); - it++; nextit++; - } - } - - auto getTurnAngle = [](const Edge& e1, const Edge& e2) { - auto phi = e1.angleToXaxis(); - auto phi_prev = e2.angleToXaxis(); - auto turn_angle = phi-phi_prev; - if(turn_angle > Pi) turn_angle -= TwoPi; - if(turn_angle < -Pi) turn_angle += TwoPi; - return turn_angle; - }; - - auto eit = L.begin(); - auto enext = std::next(eit); - - eit->turn_angle = getTurnAngle(L.front().e, L.back().e); - - while(enext != L.end()) { - enext->turn_angle = getTurnAngle( enext->e, eit->e); - eit->is_turning_point = - signbit(enext->turn_angle) != signbit(eit->turn_angle); - ++eit; ++enext; - } - - L.back().is_turning_point = signbit(L.back().turn_angle) != - signbit(L.front().turn_angle); - - }; - - // Step 2: Fill the edgelists - fillEdgeList(A, stationary, 1); - fillEdgeList(B, orbiter, 1); - - int i = 1; - for(MarkedEdge& me : A) { - std::cout << "a" << i << ":\n\t" - << getX(me.e.first()) << " " << getY(me.e.first()) << "\n\t" - << getX(me.e.second()) << " " << getY(me.e.second()) << "\n\t" - << "Turning point: " << (me.is_turning_point ? "yes" : "no") - << std::endl; - - me.label = "a"; me.label += std::to_string(i); - i++; - } - - i = 1; - for(MarkedEdge& me : B) { - std::cout << "b" << i << ":\n\t" - << getX(me.e.first()) << " " << getY(me.e.first()) << "\n\t" - << getX(me.e.second()) << " " << getY(me.e.second()) << "\n\t" - << "Turning point: " << (me.is_turning_point ? "yes" : "no") - << std::endl; - me.label = "b"; me.label += std::to_string(i); - i++; - } - - // A reference to a marked edge that also knows its container - struct MarkedEdgeRef { - reference_wrapper eref; - reference_wrapper> container; - Coord dir = 1; // Direction modifier - - inline Radians angleX() const { return eref.get().e.angleToXaxis(); } - inline const Edge& edge() const { return eref.get().e; } - inline Edge& edge() { return eref.get().e; } - inline bool isTurningPoint() const { - return eref.get().is_turning_point; - } - inline bool isFrom(const vector& cont ) { - return &(container.get()) == &cont; - } - inline bool eq(const MarkedEdgeRef& mr) { - return &(eref.get()) == &(mr.eref.get()); - } - - MarkedEdgeRef(reference_wrapper er, - reference_wrapper> ec): - eref(er), container(ec), dir(1) {} - - MarkedEdgeRef(reference_wrapper er, - reference_wrapper> ec, - Coord d): - eref(er), container(ec), dir(d) {} - }; - - using EdgeRefList = vector; - - // Comparing two marked edges - auto sortfn = [](const MarkedEdgeRef& e1, const MarkedEdgeRef& e2) { - return e1.angleX() < e2.angleX(); - }; - - EdgeRefList Aref, Bref; // We create containers for the references - Aref.reserve(A.size()); Bref.reserve(B.size()); - - // Fill reference container for the stationary polygon - std::for_each(A.begin(), A.end(), [&Aref](MarkedEdge& me) { - Aref.emplace_back( ref(me), ref(Aref) ); - }); - - // Fill reference container for the orbiting polygon - std::for_each(B.begin(), B.end(), [&Bref](MarkedEdge& me) { - Bref.emplace_back( ref(me), ref(Bref) ); - }); - - auto mink = [sortfn] // the Mink(Q, R, direction) sub-procedure - (const EdgeRefList& Q, const EdgeRefList& R, bool positive) - { - - // Step 1 "merge sort_list(Q) and sort_list(R) to form merge_list(Q,R)" - // Sort the containers of edge references and merge them. - // Q could be sorted only once and be reused here but we would still - // need to merge it with sorted(R). - - EdgeRefList merged; - EdgeRefList S, seq; - merged.reserve(Q.size() + R.size()); - - merged.insert(merged.end(), R.begin(), R.end()); - std::stable_sort(merged.begin(), merged.end(), sortfn); - merged.insert(merged.end(), Q.begin(), Q.end()); - std::stable_sort(merged.begin(), merged.end(), sortfn); - - // Step 2 "set i = 1, k = 1, direction = 1, s1 = q1" - // we don't use i, instead, q is an iterator into Q. k would be an index - // into the merged sequence but we use "it" as an iterator for that - - // here we obtain references for the containers for later comparisons - const auto& Rcont = R.begin()->container.get(); - const auto& Qcont = Q.begin()->container.get(); - - // Set the initial direction - Coord dir = 1; - - // roughly i = 1 (so q = Q.begin()) and s1 = q1 so S[0] = q; - if(positive) { - auto q = Q.begin(); - S.emplace_back(*q); - - // Roughly step 3 - - std::cout << "merged size: " << merged.size() << std::endl; - auto mit = merged.begin(); - for(bool finish = false; !finish && q != Q.end();) { - ++q; // "Set i = i + 1" - - while(!finish && mit != merged.end()) { - if(mit->isFrom(Rcont)) { - auto s = *mit; - s.dir = dir; - S.emplace_back(s); - } - - if(mit->eq(*q)) { - S.emplace_back(*q); - if(mit->isTurningPoint()) dir = -dir; - if(q == Q.begin()) finish = true; - break; - } - - mit += dir; - // __nfp::advance(mit, merged, dir > 0); - } - } - } else { - auto q = Q.rbegin(); - S.emplace_back(*q); - - // Roughly step 3 - - std::cout << "merged size: " << merged.size() << std::endl; - auto mit = merged.begin(); - for(bool finish = false; !finish && q != Q.rend();) { - ++q; // "Set i = i + 1" - - while(!finish && mit != merged.end()) { - if(mit->isFrom(Rcont)) { - auto s = *mit; - s.dir = dir; - S.emplace_back(s); - } - - if(mit->eq(*q)) { - S.emplace_back(*q); - S.back().dir = -1; - if(mit->isTurningPoint()) dir = -dir; - if(q == Q.rbegin()) finish = true; - break; - } - - mit += dir; - // __nfp::advance(mit, merged, dir > 0); - } - } - } - - - // Step 4: - - // "Let starting edge r1 be in position si in sequence" - // whaaat? I guess this means the following: - auto it = S.begin(); - while(!it->eq(*R.begin())) ++it; - - // "Set j = 1, next = 2, direction = 1, seq1 = si" - // we don't use j, seq is expanded dynamically. - dir = 1; - auto next = std::next(R.begin()); seq.emplace_back(*it); - - // Step 5: - // "If all si edges have been allocated to seqj" should mean that - // we loop until seq has equal size with S - auto send = it; //it == S.begin() ? it : std::prev(it); - while(it != S.end()) { - ++it; if(it == S.end()) it = S.begin(); - if(it == send) break; - - if(it->isFrom(Qcont)) { - seq.emplace_back(*it); // "If si is from Q, j = j + 1, seqj = si" - - // "If si is a turning point in Q, - // direction = - direction, next = next + direction" - if(it->isTurningPoint()) { - dir = -dir; - next += dir; -// __nfp::advance(next, R, dir > 0); - } - } - - if(it->eq(*next) /*&& dir == next->dir*/) { // "If si = direction.rnext" - // "j = j + 1, seqj = si, next = next + direction" - seq.emplace_back(*it); - next += dir; -// __nfp::advance(next, R, dir > 0); - } - } - - return seq; - }; - - std::vector seqlist; - seqlist.reserve(Bref.size()); - - EdgeRefList Bslope = Bref; // copy Bref, we will make a slope diagram - - // make the slope diagram of B - std::sort(Bslope.begin(), Bslope.end(), sortfn); - - auto slopeit = Bslope.begin(); // search for the first turning point - while(!slopeit->isTurningPoint() && slopeit != Bslope.end()) slopeit++; - - if(slopeit == Bslope.end()) { - // no turning point means convex polygon. - seqlist.emplace_back(mink(Aref, Bref, true)); - } else { - int dir = 1; - - auto firstturn = Bref.begin(); - while(!firstturn->eq(*slopeit)) ++firstturn; - - assert(firstturn != Bref.end()); - - EdgeRefList bgroup; bgroup.reserve(Bref.size()); - bgroup.emplace_back(*slopeit); - - auto b_it = std::next(firstturn); - while(b_it != firstturn) { - if(b_it == Bref.end()) b_it = Bref.begin(); - - while(!slopeit->eq(*b_it)) { - __nfp::advance(slopeit, Bslope, dir > 0); - } - - if(!slopeit->isTurningPoint()) { - bgroup.emplace_back(*slopeit); - } else { - if(!bgroup.empty()) { - if(dir > 0) bgroup.emplace_back(*slopeit); - for(auto& me : bgroup) { - std::cout << me.eref.get().label << ", "; - } - std::cout << std::endl; - seqlist.emplace_back(mink(Aref, bgroup, dir == 1 ? true : false)); - bgroup.clear(); - if(dir < 0) bgroup.emplace_back(*slopeit); - } else { - bgroup.emplace_back(*slopeit); - } - - dir *= -1; - } - ++b_it; - } - } - -// while(it != Bref.end()) // This is step 3 and step 4 in one loop -// if(it->isTurningPoint()) { -// R = {R.last, it++}; -// auto seq = mink(Q, R, orientation); - -// // TODO step 6 (should be 5 shouldn't it?): linking edges from A -// // I don't get this step - -// seqlist.insert(seqlist.end(), seq.begin(), seq.end()); -// orientation = !orientation; -// } else ++it; - -// if(seqlist.empty()) seqlist = mink(Q, {Bref.begin(), Bref.end()}, true); - - // ///////////////////////////////////////////////////////////////////////// - // Algorithm 2: breaking Minkowski sums into track line trips - // ///////////////////////////////////////////////////////////////////////// - - - // ///////////////////////////////////////////////////////////////////////// - // Algorithm 3: finding the boundary of the NFP from track line trips - // ///////////////////////////////////////////////////////////////////////// - - - for(auto& seq : seqlist) { - std::cout << "seqlist size: " << seq.size() << std::endl; - for(auto& s : seq) { - std::cout << (s.dir > 0 ? "" : "-") << s.eref.get().label << ", "; - } - std::cout << std::endl; - } - - auto& seq = seqlist.front(); - RawShape rsh; - Vertex top_nfp; - std::vector edgelist; edgelist.reserve(seq.size()); - for(auto& s : seq) { - edgelist.emplace_back(s.eref.get().e); - } - - __nfp::buildPolygon(edgelist, rsh, top_nfp); - - return Result(rsh, top_nfp); -} - // Specializable NFP implementation class. Specialize it if you have a faster // or better NFP implementation template diff --git a/src/libnest2d/tests/test.cpp b/src/libnest2d/tests/test.cpp index 1c4daf4af3..3b0eae1618 100644 --- a/src/libnest2d/tests/test.cpp +++ b/src/libnest2d/tests/test.cpp @@ -789,60 +789,6 @@ TEST(GeometryAlgorithms, nfpConvexConvex) { // testNfp(nfp_concave_testdata); //} -TEST(GeometryAlgorithms, nfpConcaveConcave) { - using namespace libnest2d; - - Item stationary = { - { - {207, 76}, - {194, 117}, - {206, 117}, - {206, 104}, - {218, 104}, - {231, 117}, - {231, 130}, - {244, 130}, - {230, 92}, - {220, 92}, - {220, 84}, - {239, 76}, - {207, 76} - }, - {} - }; - - Item orbiter = { - { - {78, 76}, - {90, 89}, - {76, 124}, - {101, 124}, - {101, 100}, - {141, 113}, - {141, 124}, - {168, 124}, - {158, 115}, - {158, 104}, - {121, 88}, - {121, 76}, - {78, 76} - }, - {} - }; - - Rectangle r1(10, 10); - Rectangle r2(20, 20); - auto result = nfp::nfpSimpleSimple(stationary.transformedShape(), - orbiter.transformedShape()); - - svg::SVGWriter::Config conf; - conf.mm_in_coord_units = 1; - svg::SVGWriter wr(conf); - wr.writeItem(Item(result.first)); - wr.save("simplesimple.svg"); - -} - TEST(GeometryAlgorithms, pointOnPolygonContour) { using namespace libnest2d; From 22110e15c8c76294068d9a86d322005cb6241d55 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Wed, 24 Oct 2018 14:45:22 +0200 Subject: [PATCH 172/186] Fixed spurious error reports when loading the default profile file on start of the application. --- src/slic3r/GUI/PresetBundle.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/PresetBundle.cpp b/src/slic3r/GUI/PresetBundle.cpp index 8d4ab194a3..f0f53ff6cc 100644 --- a/src/slic3r/GUI/PresetBundle.cpp +++ b/src/slic3r/GUI/PresetBundle.cpp @@ -78,7 +78,8 @@ PresetBundle::PresetBundle() : this->printers.add_default_preset(Preset::sla_printer_options(), static_cast(SLAFullPrintConfig::defaults()), "- default SLA -"); this->printers.preset(1).printer_technology() = ptSLA; for (size_t i = 0; i < 2; ++ i) { - Preset &preset = this->printers.preset(i); + // The following ugly switch is to avoid printers.preset(0) to return the edited instance, as the 0th default is the current one. + Preset &preset = (i == 0) ? this->printers.default_preset() : this->printers.preset(1); preset.config.optptr("printer_settings_id", true); preset.config.optptr("printer_vendor", true); preset.config.optptr("printer_model", true); From 806e59facc640da96559216db326e54c86dbc212 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Wed, 24 Oct 2018 17:20:15 +0200 Subject: [PATCH 173/186] Fix of Perl unit tests. --- src/libslic3r/Print.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 6253f4e898..f87d7d309a 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -407,9 +407,12 @@ void Print::add_model_object(ModelObject* model_object, int idx) } else m_objects.emplace_back(object); // Invalidate all print steps. - //FIXME lock mutex! this->invalidate_all_steps(); + // Set the transformation matrix without translation from the first instance. + if (! model_object->instances.empty()) + object->set_trafo(model_object->instances.front()->world_matrix(true)); + size_t volume_id = 0; for (const ModelVolume *volume : model_object->volumes) { if (! volume->is_model_part() && ! volume->is_modifier()) From 9789908ed8106f4d4a3692ea1047bcd38334dcba Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Wed, 24 Oct 2018 21:03:12 +0200 Subject: [PATCH 174/186] Temporary file name generated with boost::filesystem::path (an attempt to solve linux/win mismatch regarding terminating (back)slash) --- src/slic3r/GUI/BackgroundSlicingProcess.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/BackgroundSlicingProcess.cpp b/src/slic3r/GUI/BackgroundSlicingProcess.cpp index 3ed5d6bfc8..17d290db73 100644 --- a/src/slic3r/GUI/BackgroundSlicingProcess.cpp +++ b/src/slic3r/GUI/BackgroundSlicingProcess.cpp @@ -15,14 +15,16 @@ #include #include +#include #include namespace Slic3r { BackgroundSlicingProcess::BackgroundSlicingProcess() { - m_temp_output_path = wxStandardPaths::Get().GetTempDir().utf8_str().data(); - m_temp_output_path += (boost::format(".%1%.gcode") % get_current_pid()).str(); + boost::filesystem::path temp_path(wxStandardPaths::Get().GetTempDir().utf8_str().data()); + temp_path /= (boost::format(".%1%.gcode") % get_current_pid()).str(); + m_temp_output_path = temp_path.string(); } BackgroundSlicingProcess::~BackgroundSlicingProcess() From 78d813cbc9d9d046534c3ec1eb34fe899b2be2e7 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Thu, 25 Oct 2018 09:35:08 +0200 Subject: [PATCH 175/186] Tooltip when hovering on gizmo icons --- src/slic3r/GUI/GLCanvas3D.cpp | 55 ++++++++++++++++++++++++----------- src/slic3r/GUI/GLCanvas3D.hpp | 9 +++--- src/slic3r/GUI/GLGizmo.cpp | 23 ++++++++++++++- src/slic3r/GUI/GLGizmo.hpp | 8 +++++ src/slic3r/GUI/GLToolbar.cpp | 3 +- 5 files changed, 75 insertions(+), 23 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index f8f7cb0bcf..465dd68000 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -18,7 +18,6 @@ #include #include -#include #include #include #include @@ -1904,13 +1903,21 @@ void GLCanvas3D::Gizmos::set_enabled(bool enable) } #if ENABLE_EXTENDED_SELECTION -void GLCanvas3D::Gizmos::update_hover_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos, const GLCanvas3D::Selection& selection) +std::string GLCanvas3D::Gizmos::update_hover_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos, const GLCanvas3D::Selection& selection) #else void GLCanvas3D::Gizmos::update_hover_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos) #endif // ENABLE_EXTENDED_SELECTION { +#if ENABLE_EXTENDED_SELECTION + std::string name = ""; +#endif // ENABLE_EXTENDED_SELECTION + if (!m_enabled) +#if ENABLE_EXTENDED_SELECTION + return name; +#else return; +#endif // ENABLE_EXTENDED_SELECTION float cnv_h = (float)canvas.get_canvas_size().get_height(); float height = _get_total_overlay_height(); @@ -1932,9 +1939,17 @@ void GLCanvas3D::Gizmos::update_hover_state(const GLCanvas3D& canvas, const Vec2 { bool inside = (mouse_pos - Vec2d(OverlayOffsetX + half_tex_size, top_y + half_tex_size)).norm() < half_tex_size; it->second->set_state(inside ? GLGizmoBase::Hover : GLGizmoBase::Off); +#if ENABLE_EXTENDED_SELECTION + if (inside) + name = it->second->get_name(); +#endif // ENABLE_EXTENDED_SELECTION } top_y += (tex_size + OverlayGapY); } + +#if ENABLE_EXTENDED_SELECTION + return name; +#endif // ENABLE_EXTENDED_SELECTION } #if ENABLE_EXTENDED_SELECTION @@ -2715,7 +2730,6 @@ wxDEFINE_EVENT(EVT_GIZMO_FLATTEN, Vec3dEvent); GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas) : m_canvas(canvas) , m_context(nullptr) - , m_timer(nullptr) , m_toolbar(*this) , m_config(nullptr) , m_print(nullptr) @@ -2749,7 +2763,7 @@ GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas) #if !ENABLE_USE_UNIQUE_GLCONTEXT m_context = new wxGLContext(m_canvas); #endif // !ENABLE_USE_UNIQUE_GLCONTEXT - m_timer = new wxTimer(m_canvas); + m_timer.SetOwner(m_canvas); } #if ENABLE_EXTENDED_SELECTION @@ -2761,12 +2775,6 @@ GLCanvas3D::~GLCanvas3D() { reset_volumes(); - if (m_timer != nullptr) - { - delete m_timer; - m_timer = nullptr; - } - #if !ENABLE_USE_UNIQUE_GLCONTEXT if (m_context != nullptr) { @@ -3339,6 +3347,8 @@ void GLCanvas3D::render() float theta = m_camera.get_theta(); bool is_custom_bed = m_bed.is_custom(); + set_tooltip(""); + // picking pass _picking_pass(); @@ -4498,10 +4508,19 @@ void GLCanvas3D::reset_legend_texture() m_legend_texture.reset(); } -void GLCanvas3D::set_tooltip(const std::string& tooltip) +void GLCanvas3D::set_tooltip(const std::string& tooltip) const { if (m_canvas != nullptr) - m_canvas->SetToolTip(tooltip); + { + wxToolTip* t = m_canvas->GetToolTip(); + if (t != nullptr) + { + if (t->GetTip() != tooltip) + t->SetTip(tooltip); + } + else + m_canvas->SetToolTip(tooltip); + } } bool GLCanvas3D::_is_shown_on_screen() const @@ -4993,7 +5012,11 @@ void GLCanvas3D::_picking_pass() const // updates gizmos overlay #if ENABLE_EXTENDED_SELECTION if (!m_selection.is_empty()) - m_gizmos.update_hover_state(*this, pos, m_selection); + { + std::string name = m_gizmos.update_hover_state(*this, pos, m_selection); + if (!name.empty()) + set_tooltip(name); + } #else if (_get_first_selected_object_id() != -1) m_gizmos.update_hover_state(*this, pos); @@ -5361,14 +5384,12 @@ Linef3 GLCanvas3D::mouse_ray(const Point& mouse_pos) void GLCanvas3D::_start_timer() { - if (m_timer != nullptr) - m_timer->Start(100, wxTIMER_CONTINUOUS); + m_timer.Start(100, wxTIMER_CONTINUOUS); } void GLCanvas3D::_stop_timer() { - if (m_timer != nullptr) - m_timer->Stop(); + m_timer.Stop(); } #if !ENABLE_EXTENDED_SELECTION diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index c26dae098c..8c889e2a22 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -7,8 +7,9 @@ #include "GLToolbar.hpp" #include "Event.hpp" +#include + class wxWindow; -class wxTimer; class wxSizeEvent; class wxIdleEvent; class wxKeyEvent; @@ -562,7 +563,7 @@ private: void set_enabled(bool enable); #if ENABLE_EXTENDED_SELECTION - void update_hover_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos, const Selection& selection); + std::string update_hover_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos, const Selection& selection); void update_on_off_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos, const Selection& selection); void update_on_off_state(const Selection& selection); #else @@ -678,7 +679,7 @@ private: wxGLContext* m_context; LegendTexture m_legend_texture; WarningTexture m_warning_texture; - wxTimer* m_timer; + wxTimer m_timer; Camera m_camera; Bed m_bed; Axes m_axes; @@ -866,7 +867,7 @@ public: void reset_legend_texture(); - void set_tooltip(const std::string& tooltip); + void set_tooltip(const std::string& tooltip) const; private: bool _is_shown_on_screen() const; diff --git a/src/slic3r/GUI/GLGizmo.cpp b/src/slic3r/GUI/GLGizmo.cpp index c6740abc3c..94a7a563fc 100644 --- a/src/slic3r/GUI/GLGizmo.cpp +++ b/src/slic3r/GUI/GLGizmo.cpp @@ -1,6 +1,8 @@ #include "../../libslic3r/libslic3r.h" #include "GLGizmo.hpp" +#include "GUI.hpp" + #include "../../libslic3r/Utils.hpp" #if !ENABLE_EXTENDED_SELECTION #include "../../slic3r/GUI/GLCanvas3D.hpp" @@ -281,7 +283,6 @@ void GLGizmoBase::start_dragging(const BoundingBoxf3& box) void GLGizmoBase::stop_dragging() { m_dragging = false; - set_tooltip(""); for (int i = 0; i < (int)m_grabbers.size(); ++i) { @@ -725,6 +726,11 @@ bool GLGizmoRotate3D::on_init() return true; } +std::string GLGizmoRotate3D::on_get_name() const +{ + return L("Rotate"); +} + #if ENABLE_EXTENDED_SELECTION void GLGizmoRotate3D::on_start_dragging(const GLCanvas3D::Selection& selection) { @@ -817,6 +823,11 @@ bool GLGizmoScale3D::on_init() return true; } +std::string GLGizmoScale3D::on_get_name() const +{ + return L("Scale"); +} + #if ENABLE_EXTENDED_SELECTION void GLGizmoScale3D::on_start_dragging(const GLCanvas3D::Selection& selection) #else @@ -1254,6 +1265,11 @@ bool GLGizmoMove3D::on_init() return true; } +std::string GLGizmoMove3D::on_get_name() const +{ + return L("Move"); +} + #if ENABLE_EXTENDED_SELECTION void GLGizmoMove3D::on_start_dragging(const GLCanvas3D::Selection& selection) #else @@ -1480,6 +1496,11 @@ bool GLGizmoFlatten::on_init() return true; } +std::string GLGizmoFlatten::on_get_name() const +{ + return L("Flatten"); +} + #if ENABLE_EXTENDED_SELECTION void GLGizmoFlatten::on_start_dragging(const GLCanvas3D::Selection& selection) #else diff --git a/src/slic3r/GUI/GLGizmo.hpp b/src/slic3r/GUI/GLGizmo.hpp index 38f72598e5..ab4850d2d4 100644 --- a/src/slic3r/GUI/GLGizmo.hpp +++ b/src/slic3r/GUI/GLGizmo.hpp @@ -74,6 +74,8 @@ public: bool init() { return on_init(); } + std::string get_name() const { return on_get_name(); } + int get_group_id() const { return m_group_id; } void set_group_id(int id) { m_group_id = id; } @@ -119,6 +121,7 @@ public: protected: virtual bool on_init() = 0; + virtual std::string on_get_name() const = 0; virtual void on_set_state() {} virtual void on_set_hover_id() {} #if ENABLE_EXTENDED_SELECTION @@ -192,6 +195,7 @@ public: protected: virtual bool on_init(); + virtual std::string on_get_name() const { return ""; } #if ENABLE_EXTENDED_SELECTION virtual void on_start_dragging(const GLCanvas3D::Selection& selection); #else @@ -234,6 +238,7 @@ public: protected: virtual bool on_init(); + virtual std::string on_get_name() const; virtual void on_set_state() { for (GLGizmoRotate& g : m_gizmos) @@ -329,6 +334,7 @@ public: protected: virtual bool on_init(); + virtual std::string on_get_name() const; #if ENABLE_EXTENDED_SELECTION virtual bool on_is_activable(const GLCanvas3D::Selection& selection) const { return !selection.is_wipe_tower(); } #endif // ENABLE_EXTENDED_SELECTION @@ -389,6 +395,7 @@ public: protected: virtual bool on_init(); + virtual std::string on_get_name() const; #if ENABLE_EXTENDED_SELECTION virtual void on_start_dragging(const GLCanvas3D::Selection& selection); virtual void on_stop_dragging(); @@ -455,6 +462,7 @@ public: protected: virtual bool on_init(); + virtual std::string on_get_name() const; #if ENABLE_EXTENDED_SELECTION virtual bool on_is_activable(const GLCanvas3D::Selection& selection) const { return selection.is_single_full_instance(); } #endif // ENABLE_EXTENDED_SELECTION diff --git a/src/slic3r/GUI/GLToolbar.cpp b/src/slic3r/GUI/GLToolbar.cpp index 71ff3cf481..265fc20426 100644 --- a/src/slic3r/GUI/GLToolbar.cpp +++ b/src/slic3r/GUI/GLToolbar.cpp @@ -512,7 +512,8 @@ void GLToolbar::update_hover_state_horizontal(const Vec2d& mouse_pos) } } - m_parent.set_tooltip(tooltip); + if (!tooltip.empty()) + m_parent.set_tooltip(tooltip); } void GLToolbar::update_hover_state_vertical(const Vec2d& mouse_pos) From 5e39ff7c58b66a221bdb5726cefaacff96361bc9 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Thu, 25 Oct 2018 10:07:11 +0200 Subject: [PATCH 176/186] Restored slicing cancellation. --- src/slic3r/GUI/Plater.cpp | 55 +++++++++------------------------------ 1 file changed, 13 insertions(+), 42 deletions(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 2de1cfbf1a..8c4166c834 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -810,7 +810,6 @@ struct Plater::priv void schedule_background_process(); void async_apply_config(); void start_background_process(); - void stop_background_process(); void reload_from_disk(); void export_object_stl(); void fix_through_netfabb(); @@ -1018,9 +1017,6 @@ void Plater::priv::update(bool force_autocenter) model.center_instances_around_point(bed_center); } - // stop_background_process(); // TODO -// print.reload_model_instances(); - #if !ENABLE_EXTENDED_SELECTION const auto selections = collect_selections(); _3DScene::set_objects_selections(canvas3D, selections); @@ -1488,8 +1484,6 @@ void Plater::priv::select_view() void Plater::priv::remove(size_t obj_idx) { - // $self->stop_background_process; // TODO - // Prevent toolpaths preview from rendering while we modify the Print object preview->set_enabled(false); @@ -1514,8 +1508,6 @@ void Plater::priv::remove(size_t obj_idx) void Plater::priv::reset() { - // $self->stop_background_process; // TODO - // Prevent toolpaths preview from rendering while we modify the Print object preview->set_enabled(false); @@ -1576,12 +1568,6 @@ void Plater::priv::mirror(Axis axis) model_object->mirror(axis); - // $self->stop_background_process; // TODO -#if ENABLE_EXTENDED_SELECTION -// print.add_model_object(model_object, obj_idx); -#else -// print.add_model_object(model_object, *obj_idx); -#endif // ENABLE_EXTENDED_SELECTION selection_changed(); update(); #endif // ENABLE_MIRROR @@ -1596,8 +1582,6 @@ void Plater::priv::scale() void Plater::priv::arrange() { - // $self->stop_background_process; - main_frame->app_controller()->arrange_model(); // ignore arrange failures on purpose: user has visual feedback and we don't need to warn him @@ -1624,8 +1608,6 @@ void Plater::priv::split_object() return; } -// $self->stop_background_process; - ModelObjectPtrs new_objects; current_model_object->split(&new_objects); if (new_objects.size() == 1) @@ -1695,8 +1677,11 @@ void Plater::priv::async_apply_config() } } if (invalidated != Print::APPLY_STATUS_UNCHANGED && this->get_config("background_processing") == "1" && - this->print.num_object_instances() > 0) - this->background_process.start(); + this->print.num_object_instances() > 0 && this->background_process.start()) + this->statusbar()->set_cancel_callback([this](){ + this->statusbar()->set_status_text(L("Cancelling")); + this->background_process.stop(); + }); } void Plater::priv::start_background_process() @@ -1716,13 +1701,6 @@ void Plater::priv::start_background_process() } } -void Plater::priv::stop_background_process() -{ - this->background_process.stop(); - if (this->preview != nullptr) - this->preview->reload_print(); -} - void Plater::priv::reload_from_disk() { // TODO @@ -1855,7 +1833,8 @@ void Plater::priv::on_process_completed(wxCommandEvent &evt) this->statusbar()->reset_cancel_callback(); this->statusbar()->stop_busy(); - bool success = evt.GetInt(); + bool canceled = evt.GetInt() < 0; + bool success = evt.GetInt() > 0; // Reset the "export G-code path" name, so that the automatic background processing will be enabled again. this->background_process.reset_export(); if (! success) { @@ -1864,8 +1843,10 @@ void Plater::priv::on_process_completed(wxCommandEvent &evt) message = _(L("Export failed")); this->statusbar()->set_status_text(message); } + if (canceled) + this->statusbar()->set_status_text(L("Cancelled")); - this->sidebar->show_info_sizers(false); + this->sidebar->show_info_sizers(success); // this updates buttons status //$self->object_list_changed; @@ -1991,8 +1972,6 @@ void Plater::priv::on_scale_uniformly(SimpleEvent&) // my $model_object = $self->{model}->objects->[$obj_idx]; // my $model_instance = $model_object->instances->[0]; -// $self->stop_background_process; - // my $variation = $scale / $model_instance->scaling_factor; // #FIXME Scale the layer height profile? // foreach my $range (@{ $model_object->layer_height_ranges }) { @@ -2219,8 +2198,6 @@ void Plater::increase_instances(size_t num) auto *model_instance = model_object->instances[model_object->instances.size() - 1]; #endif // ENABLE_EXTENDED_SELECTION - // $self->stop_background_process; - float offset = 10.0; for (size_t i = 0; i < num; i++, offset += 10.0) { Vec3d offset_vec = model_instance->get_offset() + Vec3d(offset, offset, 0.0); @@ -2456,14 +2433,10 @@ void Plater::reslice() // this->p->stop_background_process(); // Rather perform one additional unnecessary update of the print object instead of skipping a pending async update. this->p->async_apply_config(); -/* - $self->statusbar->SetCancelCallback(sub { - $self->stop_background_process; - $self->statusbar->SetStatusText(L("Slicing cancelled")); - # this updates buttons status - $self->object_list_changed; + this->p->statusbar()->set_cancel_callback([this](){ + this->p->statusbar()->set_status_text(L("Cancelling")); + this->p->background_process.stop(); }); -*/ this->p->start_background_process(); } @@ -2570,8 +2543,6 @@ void Plater::changed_object_settings(int obj_idx) // update print if (list->is_parts_changed() || list->is_part_settings_changed()) { -// stop_background_process(); -// $self->{print}->reload_object($obj_idx); this->p->schedule_background_process(); #if !ENABLE_EXTENDED_SELECTION if (p->canvas3D) _3DScene::reload_scene(p->canvas3D, true); From bde5f17d5c2f4ac6773c8afb4b1cadb5879a4122 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Thu, 25 Oct 2018 10:36:47 +0200 Subject: [PATCH 177/186] Fixed build on Linux and OSx --- src/slic3r/GUI/GLCanvas3D.cpp | 1 + src/slic3r/GUI/Plater.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 465dd68000..511c9a3f02 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -22,6 +22,7 @@ #include #include #include +#include // Print now includes tbb, and tbb includes Windows. This breaks compilation of wxWidgets if included before wx. #include "../../libslic3r/Print.hpp" diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 2de1cfbf1a..c34aab0687 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1839,10 +1839,10 @@ void Plater::priv::on_update_print_preview(wxCommandEvent &) this->preview->reload_print(); // in case this was MM print, wipe tower bounding box on 3D tab might need redrawing with exact depth: #if !ENABLE_EXTENDED_SELECTION - auto selections = p->collect_selections(); - _3DScene::set_objects_selections(p->canvas3D, selections); - if (p->canvas3D) - _3DScene::reload_scene(p->canvas3D, true); + auto selections = collect_selections(); + _3DScene::set_objects_selections(canvas3D, selections); + if (canvas3D) + _3DScene::reload_scene(canvas3D, true); #endif // !ENABLE_EXTENDED_SELECTION } From 30fe846158ac924c299a642550056a1a13f56dd0 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Thu, 25 Oct 2018 11:06:08 +0200 Subject: [PATCH 178/186] Do not translate selection if user press Shift while selecting and then drags --- src/slic3r/GUI/GLCanvas3D.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 511c9a3f02..4b335d5bcc 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -4115,7 +4115,12 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) // Get new position at the same Z of the initial click point. float z0 = 0.0f; float z1 = 1.0f; +#if ENABLE_EXTENDED_SELECTION + // we do not want to translate objects if the user just clicked on an object while pressing shift (to add/remove it from the selection) and then drag + Vec3d cur_pos = evt.ShiftDown() ? m_mouse.drag.start_position_3D : Linef3(_mouse_to_3d(pos, &z0), _mouse_to_3d(pos, &z1)).intersect_plane(m_mouse.drag.start_position_3D(2)); +#else Vec3d cur_pos = Linef3(_mouse_to_3d(pos, &z0), _mouse_to_3d(pos, &z1)).intersect_plane(m_mouse.drag.start_position_3D(2)); +#endif // ENABLE_EXTENDED_SELECTION #if !ENABLE_EXTENDED_SELECTION // Clip the new position, so the object center remains close to the bed. From c00ee0659e2c0a58678b0d145f75eea4501fdee7 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Thu, 25 Oct 2018 12:10:35 +0200 Subject: [PATCH 179/186] Call schedule_background_process() after rotating/scaling/flattening using gizmos --- src/slic3r/GUI/GLCanvas3D.cpp | 7 ++++--- src/slic3r/GUI/GLCanvas3D.hpp | 3 ++- src/slic3r/GUI/Plater.cpp | 8 ++++++++ src/slic3r/GUI/Plater.hpp | 1 - 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 4b335d5bcc..579362555a 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -2699,6 +2699,7 @@ void GLCanvas3D::LegendTexture::render(const GLCanvas3D& canvas) const } } +wxDEFINE_EVENT(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS, SimpleEvent); #if ENABLE_EXTENDED_SELECTION wxDEFINE_EVENT(EVT_GLCANVAS_OBJECT_SELECT, SimpleEvent); #else @@ -6547,7 +6548,7 @@ void GLCanvas3D::_on_rotate() } } -// schedule_background_process + post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS)); } void GLCanvas3D::_on_scale() @@ -6581,7 +6582,7 @@ void GLCanvas3D::_on_scale() } } - // schedule_background_process + post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS)); } void GLCanvas3D::_on_flatten() @@ -6621,7 +6622,7 @@ void GLCanvas3D::_on_mirror() } } - // schedule_background_process + post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS)); } #endif // ENABLE_MIRROR #else diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 8c889e2a22..c0f531919f 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -104,7 +104,7 @@ template using Vec2dsEvent = ArrayEvent; using Vec3dEvent = Event; template using Vec3dsEvent = ArrayEvent; - +wxDECLARE_EVENT(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS, SimpleEvent); wxDECLARE_EVENT(EVT_GLCANVAS_VIEWPORT_CHANGED, SimpleEvent); #if !ENABLE_EXTENDED_SELECTION wxDECLARE_EVENT(EVT_GLCANVAS_DOUBLE_CLICK, SimpleEvent); @@ -732,6 +732,7 @@ private: void post_event(wxEvent &&event); void viewport_changed(); + public: GLCanvas3D(wxGLCanvas* canvas); ~GLCanvas3D(); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 4106fa6350..c307bf2cf8 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -822,6 +822,8 @@ struct Plater::priv void on_process_completed(wxCommandEvent&); void on_layer_editing_toggled(bool enable); + void on_schedule_background_process(SimpleEvent&); + void on_action_add(SimpleEvent&); void on_action_split_objects(SimpleEvent&); void on_action_split_volumes(SimpleEvent&); @@ -946,6 +948,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) : sidebar->Bind(wxEVT_COMBOBOX, &priv::on_select_preset, this); // 3DScene events: + canvas3D->Bind(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS, &priv::on_schedule_background_process, this); canvas3D->Bind(EVT_GLCANVAS_OBJECT_SELECT, &priv::on_object_select, this); canvas3D->Bind(EVT_GLCANVAS_VIEWPORT_CHANGED, &priv::on_viewport_changed, this); #if !ENABLE_EXTENDED_SELECTION @@ -1867,6 +1870,11 @@ void Plater::priv::on_layer_editing_toggled(bool enable) canvas3D->Update(); } +void Plater::priv::on_schedule_background_process(SimpleEvent&) +{ + schedule_background_process(); +} + void Plater::priv::on_action_add(SimpleEvent&) { if (q != nullptr) diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index ab912f5e3a..7ea5b19643 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -89,7 +89,6 @@ private: std::unique_ptr p; }; - class Plater: public wxPanel { public: From e72a0586002dc85332cb3f8833f8c78c9403d799 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Thu, 25 Oct 2018 12:36:10 +0200 Subject: [PATCH 180/186] Fixed update of GUI when object is selected by right-clicking on it to show its context menu --- src/slic3r/GUI/GLCanvas3D.cpp | 1 + src/slic3r/GUI/Plater.cpp | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 579362555a..d70048d858 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -4093,6 +4093,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) // forces the selection of the volume m_selection.add(m_hover_volume_id); m_gizmos.update_on_off_state(m_selection); + post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT)); update_gizmos_data(); wxGetApp().obj_manipul()->update_settings_value(m_selection); // forces a frame render to update the view before the context menu is shown diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index c307bf2cf8..9c228dbdf2 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1374,6 +1374,8 @@ void Plater::priv::selection_changed() _3DScene::enable_toolbar_item(canvas3D, "splitvolumes", can_split_to_volumes()); _3DScene::enable_toolbar_item(canvas3D, "cut", can_cut_object()); _3DScene::enable_toolbar_item(canvas3D, "layersediting", layers_height_allowed()); + // forces a frame render to update the view (to avoid a missed update if, for example, the context menu appears) + _3DScene::render(canvas3D); #else _3DScene::enable_toolbar_item(canvas3D, "fewer", have_sel); _3DScene::enable_toolbar_item(canvas3D, "splitobjects", have_sel); From 300943983831ebc4d2370b55d2db8587571ff283 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Thu, 25 Oct 2018 12:48:19 +0200 Subject: [PATCH 181/186] Ported System Info Dialog --- src/slic3r/CMakeLists.txt | 2 + src/slic3r/GUI/AboutDialog.cpp | 2 +- src/slic3r/GUI/GUI_App.cpp | 22 ++--- src/slic3r/GUI/SysInfoDialog.cpp | 148 +++++++++++++++++++++++++++++++ src/slic3r/GUI/SysInfoDialog.hpp | 24 +++++ 5 files changed, 181 insertions(+), 17 deletions(-) create mode 100644 src/slic3r/GUI/SysInfoDialog.cpp create mode 100644 src/slic3r/GUI/SysInfoDialog.hpp diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt index 4e9edfbdc6..7837ae2b33 100644 --- a/src/slic3r/CMakeLists.txt +++ b/src/slic3r/CMakeLists.txt @@ -1,6 +1,8 @@ add_library(libslic3r_gui STATIC ${LIBDIR}/slic3r/GUI/AboutDialog.cpp ${LIBDIR}/slic3r/GUI/AboutDialog.hpp + ${LIBDIR}/slic3r/GUI/SysInfoDialog.cpp + ${LIBDIR}/slic3r/GUI/SysInfoDialog.hpp ${LIBDIR}/slic3r/GUI/AppConfig.cpp ${LIBDIR}/slic3r/GUI/AppConfig.hpp ${LIBDIR}/slic3r/GUI/BackgroundSlicingProcess.cpp diff --git a/src/slic3r/GUI/AboutDialog.cpp b/src/slic3r/GUI/AboutDialog.cpp index 0fed8d1751..cf196c36d3 100644 --- a/src/slic3r/GUI/AboutDialog.cpp +++ b/src/slic3r/GUI/AboutDialog.cpp @@ -41,7 +41,7 @@ AboutDialog::AboutDialog() // logo wxBitmap logo_bmp = wxBitmap(from_u8(Slic3r::var("Slic3r_192px.png")), wxBITMAP_TYPE_PNG); auto *logo = new wxStaticBitmap(this, wxID_ANY, std::move(logo_bmp)); - hsizer->Add(logo, 1, wxALIGN_CENTRE_VERTICAL | wxEXPAND | wxTOP | wxBOTTOM, 35); + hsizer->Add(logo, 1, wxEXPAND | wxTOP | wxBOTTOM, 35); wxBoxSizer* vsizer = new wxBoxSizer(wxVERTICAL); #ifdef __WXMSW__ diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index cabb574286..43d54abde1 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -31,6 +31,7 @@ #include "Tab.hpp" #include #include +#include "SysInfoDialog.hpp" namespace Slic3r { namespace GUI { @@ -258,20 +259,9 @@ void GUI_App::recreate_GUI() void GUI_App::system_info() { -// auto slic3r_info = Slic3r::slic3r_info(format = > 'html'); -// auto copyright_info = Slic3r::copyright_info(format = > 'html'); -// auto system_info = Slic3r::system_info(format = > 'html'); - std::string opengl_info = ""; - std::string opengl_info_txt = ""; - if (mainframe && mainframe->m_plater /*&& mainframe->m_plater->canvas3D*/) { - opengl_info = _3DScene::get_gl_info(true, true); - opengl_info_txt = _3DScene::get_gl_info(false, true); - } -// auto about = new SystemInfo(nullptr, slic3r_info, /*copyright_info,*/system_info, opengl_info, -// text_info = > Slic3r::slic3r_info.Slic3r::system_info.$opengl_info_txt, -// ); -// about->ShowModal(); -// about->Destroy(); + SysInfoDialog dlg; + dlg.ShowModal(); + dlg.Destroy(); } // static method accepting a wxWindow object as first parameter @@ -525,7 +515,7 @@ void GUI_App::add_config_menu(wxMenuBar *menu) local_menu->AppendSeparator(); auto mode_menu = new wxMenu(); mode_menu->AppendRadioItem(config_id_base + ConfigMenuModeSimple, _(L("&Simple")), _(L("Simple View Mode"))); - mode_menu->AppendRadioItem(config_id_base + ConfigMenuModeMiddle, _(L("&Middle")), _(L("Middle View Mode"))); + mode_menu->AppendRadioItem(config_id_base + ConfigMenuModeMiddle, _(L("&Advanced")), _(L("Advanced View Mode"))); mode_menu->AppendRadioItem(config_id_base + ConfigMenuModeExpert, _(L("&Expert")), _(L("Expert View Mode"))); mode_menu->Check(config_id_base + get_view_mode(), true); local_menu->AppendSubMenu(mode_menu, _(L("&Mode")), _(L("Slic3r View Mode"))); @@ -598,7 +588,7 @@ void GUI_App::add_config_menu(wxMenuBar *menu) mode_menu->Bind(wxEVT_MENU, [this, config_id_base](wxEvent& event) { int id_mode = event.GetId() - config_id_base; std::string mode = id_mode == ConfigMenuModeExpert ? "expert" : - id_mode == ConfigMenuModeSimple ? "simple" : "middle"; + id_mode == ConfigMenuModeSimple ? "simple" : "advanced"; app_config->set("view_mode", mode); app_config->save(); update_mode(); diff --git a/src/slic3r/GUI/SysInfoDialog.cpp b/src/slic3r/GUI/SysInfoDialog.cpp new file mode 100644 index 0000000000..ee3060c242 --- /dev/null +++ b/src/slic3r/GUI/SysInfoDialog.cpp @@ -0,0 +1,148 @@ +#include "SysInfoDialog.hpp" +// #include "AboutDialog.hpp" + +#include +#include + +// #include "../../libslic3r/Utils.hpp" +#include "3DScene.hpp" +#include "GUI.hpp" + +namespace Slic3r { +namespace GUI { + +std::string get_main_info(bool format_as_html) +{ + std::stringstream out; + + std::string b_start = format_as_html ? "" : ""; + std::string b_end = format_as_html ? "" : ""; + std::string line_end = format_as_html ? "
" : "\n"; + + if (!format_as_html) + out << b_start << SLIC3R_FORK_NAME << b_end << line_end; + out << b_start << "Version: " << b_end << SLIC3R_VERSION << line_end; + out << b_start << "Build: " << b_end << SLIC3R_BUILD << line_end; + out << line_end; + out << b_start << "Operating System: " << b_end << wxPlatformInfo::Get().GetOperatingSystemFamilyName() << line_end; + out << b_start << "System Architecture: " << b_end << wxPlatformInfo::Get().GetArchName() << line_end; + out << b_start << +#if defined _WIN32 + "Windows Version: " +#else + // Hopefully some kind of unix / linux. + "System Version: " +#endif + << b_end << wxPlatformInfo::Get().GetOperatingSystemDescription() << line_end; + + return out.str(); +} + +SysInfoDialog::SysInfoDialog() + : wxDialog(NULL, wxID_ANY, _(L("Slic3r Prusa Edition - System Information")), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER) +{ + wxColour bgr_clr = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); + SetBackgroundColour(bgr_clr); + wxBoxSizer* hsizer = new wxBoxSizer(wxHORIZONTAL); + hsizer->SetMinSize(wxSize(600, -1)); + + auto main_sizer = new wxBoxSizer(wxVERTICAL); + main_sizer->Add(hsizer, 0, wxEXPAND | wxALL, 10); + + // logo + wxBitmap logo_bmp = wxBitmap(from_u8(Slic3r::var("Slic3r_128px.png")), wxBITMAP_TYPE_PNG); + auto *logo = new wxStaticBitmap(this, wxID_ANY, std::move(logo_bmp)); + hsizer->Add(logo, 0, wxEXPAND | wxTOP | wxBOTTOM, 15); + + wxBoxSizer* vsizer = new wxBoxSizer(wxVERTICAL); + hsizer->Add(vsizer, 1, wxEXPAND|wxLEFT, 20); + + // title + { + wxStaticText* title = new wxStaticText(this, wxID_ANY, SLIC3R_FORK_NAME, wxDefaultPosition, wxDefaultSize); + wxFont title_font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); + title_font.SetWeight(wxFONTWEIGHT_BOLD); + title_font.SetFamily(wxFONTFAMILY_ROMAN); + title_font.SetPointSize(14); + title->SetFont(title_font); + vsizer->Add(title, 0, wxALIGN_LEFT | wxTOP, 10); + } + + // main_info_text + wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); + const auto text_clr = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT); + auto text_clr_str = wxString::Format(wxT("#%02X%02X%02X"), text_clr.Red(), text_clr.Green(), text_clr.Blue()); + auto bgr_clr_str = wxString::Format(wxT("#%02X%02X%02X"), bgr_clr.Red(), bgr_clr.Green(), bgr_clr.Blue()); + + const int fs = font.GetPointSize() - 1; + int size[] = { fs*1.5, fs*1.4, fs*1.3, fs, fs, fs, fs }; + + wxHtmlWindow* html = new wxHtmlWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHW_SCROLLBAR_NEVER); + { + html->SetFonts(font.GetFaceName(), font.GetFaceName(), size); + html->SetBorders(2); + const auto text = wxString::Format( + "" + "" + "" + "%s" + "" + "" + "", bgr_clr_str, text_clr_str, text_clr_str, + get_main_info(true)); + html->SetPage(text); + vsizer->Add(html, 1, wxEXPAND); + } + + + // opengl_info + wxHtmlWindow* opengl_info_html = new wxHtmlWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHW_SCROLLBAR_AUTO); + { + opengl_info_html->SetMinSize(wxSize(-1, 200)); + opengl_info_html->SetFonts(font.GetFaceName(), font.GetFaceName(), size); + opengl_info_html->SetBorders(10); + const auto text = wxString::Format( + "" + "" + "" + "%s" + "" + "" + "", bgr_clr_str, text_clr_str, text_clr_str, + _3DScene::get_gl_info(true, true)); + opengl_info_html->SetPage(text); + main_sizer->Add(opengl_info_html, 1, wxEXPAND | wxBOTTOM, 15); + } + + wxStdDialogButtonSizer* buttons = this->CreateStdDialogButtonSizer(wxOK); + auto btn_copy_to_clipboard = new wxButton(this, wxID_ANY, "Copy to Clipboard", wxDefaultPosition, wxDefaultSize); + buttons->Insert(0, btn_copy_to_clipboard, 0, wxLEFT, 5); + btn_copy_to_clipboard->Bind(wxEVT_BUTTON, &SysInfoDialog::onCopyToClipboard, this); + + this->SetEscapeId(wxID_CLOSE); + this->Bind(wxEVT_BUTTON, &SysInfoDialog::onCloseDialog, this, wxID_OK); + main_sizer->Add(buttons, 0, wxEXPAND | wxRIGHT | wxBOTTOM, 3); + + this->Bind(wxEVT_LEFT_DOWN, &SysInfoDialog::onCloseDialog, this); + logo->Bind(wxEVT_LEFT_DOWN, &SysInfoDialog::onCloseDialog, this); + + SetSizer(main_sizer); + main_sizer->SetSizeHints(this); +} + +void SysInfoDialog::onCopyToClipboard(wxEvent &) +{ + wxTheClipboard->Open(); + const auto text = get_main_info(false)+"\n"+_3DScene::get_gl_info(false, true); + wxTheClipboard->SetData(new wxTextDataObject(text)); + wxTheClipboard->Close(); +} + +void SysInfoDialog::onCloseDialog(wxEvent &) +{ + this->EndModal(wxID_CLOSE); + this->Close(); +} + +} // namespace GUI +} // namespace Slic3r diff --git a/src/slic3r/GUI/SysInfoDialog.hpp b/src/slic3r/GUI/SysInfoDialog.hpp new file mode 100644 index 0000000000..ee1b85ce60 --- /dev/null +++ b/src/slic3r/GUI/SysInfoDialog.hpp @@ -0,0 +1,24 @@ +#ifndef slic3r_GUI_SysInfoDialog_hpp_ +#define slic3r_GUI_SysInfoDialog_hpp_ + +#include +#include + +namespace Slic3r { +namespace GUI { + +class SysInfoDialog : public wxDialog +{ + wxString text_info {wxEmptyString}; +public: + SysInfoDialog(); + +private: + void onCopyToClipboard(wxEvent &); + void onCloseDialog(wxEvent &); +}; + +} // namespace GUI +} // namespace Slic3r + +#endif From 3f9fb575b823a275f808c971a7efdc16d5dbe5f3 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Thu, 25 Oct 2018 14:55:03 +0200 Subject: [PATCH 182/186] Middle mode is changed to Advanced --- src/libslic3r/Config.hpp | 2 +- src/libslic3r/PrintConfig.cpp | 168 +++++++++++++++++----------------- src/slic3r/GUI/GUI_App.cpp | 6 +- src/slic3r/GUI/GUI_App.hpp | 2 +- src/slic3r/GUI/Tab.cpp | 4 +- 5 files changed, 91 insertions(+), 91 deletions(-) diff --git a/src/libslic3r/Config.hpp b/src/libslic3r/Config.hpp index 051204f1e1..43871b0f80 100644 --- a/src/libslic3r/Config.hpp +++ b/src/libslic3r/Config.hpp @@ -63,7 +63,7 @@ enum ConfigOptionType { enum ConfigOptionMode { comSimple, - comMiddle, + comAdvanced, comExpert }; diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 2b21a760fe..4e1de09919 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -39,7 +39,7 @@ void PrintConfigDef::init_common_params() def = this->add("bed_shape", coPoints); def->label = L("Bed shape"); - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionPoints{ Vec2d(0, 0), Vec2d(200, 0), Vec2d(200, 200), Vec2d(0, 200) }; def = this->add("layer_height", coFloat); @@ -57,7 +57,7 @@ void PrintConfigDef::init_common_params() def->tooltip = L("Set this to the maximum height that can be reached by your extruder while printing."); def->sidetext = L("mm"); def->cli = "max-print-height=f"; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionFloat(200.0); } @@ -75,7 +75,7 @@ void PrintConfigDef::init_fff_params() "This is mostly useful with Bowden extruders which suffer from oozing. " "This feature slows down both the print and the G-code generation."); def->cli = "avoid-crossing-perimeters!"; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionBool(false); def = this->add("bed_temperature", coInts); @@ -138,7 +138,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("°"); def->cli = "bridge-angle=f"; def->min = 0; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionFloat(0.); def = this->add("bridge_fan_speed", coInts); @@ -161,7 +161,7 @@ void PrintConfigDef::init_fff_params() def->cli = "bridge-flow-ratio=f"; def->min = 0; def->max = 2; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionFloat(1); def = this->add("bridge_speed", coFloat); @@ -180,7 +180,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm"); def->cli = "brim-width=f"; def->min = 0; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionFloat(0); def = this->add("clip_multipart_objects", coBool); @@ -194,7 +194,7 @@ void PrintConfigDef::init_fff_params() def = this->add("compatible_printers", coStrings); def->label = L("Compatible printers"); - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionStrings(); def = this->add("compatible_printers_condition", coString); @@ -217,7 +217,7 @@ void PrintConfigDef::init_fff_params() "This feature is useful to avoid the risk of ruined prints. " "Slic3r should warn and prevent you from extruder collisions, but beware."); def->cli = "complete-objects!"; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionBool(false); def = this->add("cooling", coBools); @@ -233,7 +233,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm"); def->cli = "cooling_tube_retraction=f"; def->min = 0; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionFloat(91.5f); def = this->add("cooling_tube_length", coFloat); @@ -242,7 +242,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm"); def->cli = "cooling_tube_length=f"; def->min = 0; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionFloat(5.f); def = this->add("default_acceleration", coFloat); @@ -285,7 +285,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("Experimental option for preventing support material from being generated " "under bridged areas."); def->cli = "dont-support-bridges!"; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionBool(true); def = this->add("duplicate_distance", coFloat); @@ -337,7 +337,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("Add solid infill near sloping surfaces to guarantee the vertical shell thickness " "(top+bottom solid layers)."); def->cli = "ensure-vertical-shell-thickness!"; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionBool(false); def = this->add("external_fill_pattern", coEnum); @@ -369,7 +369,7 @@ void PrintConfigDef::init_fff_params() "If expressed as percentage (for example 200%), it will be computed over layer height."); def->sidetext = L("mm or % (leave 0 for default)"); def->cli = "external-perimeter-extrusion-width=s"; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionFloatOrPercent(0, false); def = this->add("external_perimeter_speed", coFloatOrPercent); @@ -400,7 +400,7 @@ void PrintConfigDef::init_fff_params() "Slic3r keeps adding perimeters, until more than 70% of the loop immediately above " "is supported."); def->cli = "extra-perimeters!"; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionBool(true); def = this->add("extruder", coInt); @@ -458,7 +458,7 @@ void PrintConfigDef::init_fff_params() "from the XY coordinate)."); def->sidetext = L("mm"); def->cli = "extruder-offset=s@"; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionPoints { Vec2d(0,0) }; def = this->add("extrusion_axis", coString); @@ -475,7 +475,7 @@ void PrintConfigDef::init_fff_params() "Usual values are between 0.9 and 1.1. If you think you need to change this more, " "check filament diameter and your firmware E steps."); def->cli = "extrusion-multiplier=f@"; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionFloats { 1. }; def = this->add("extrusion_width", coFloatOrPercent); @@ -487,7 +487,7 @@ void PrintConfigDef::init_fff_params() "If expressed as percentage (for example: 230%), it will be computed over layer height."); def->sidetext = L("mm or % (leave 0 for auto)"); def->cli = "extrusion-width=s"; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionFloatOrPercent(0, false); def = this->add("fan_always_on", coBools); @@ -523,7 +523,7 @@ void PrintConfigDef::init_fff_params() def->multiline = true; def->full_width = true; def->height = 130; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionStrings { "" }; def = this->add("filament_max_volumetric_speed", coFloats); @@ -534,7 +534,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm³/s"); def->cli = "filament-max-volumetric-speed=f@"; def->min = 0; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionFloats { 0. }; def = this->add("filament_loading_speed", coFloats); @@ -714,7 +714,7 @@ void PrintConfigDef::init_fff_params() def->cli = "fill-angle=f"; def->min = 0; def->max = 360; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionFloat(45); def = this->add("fill_density", coPercent); @@ -820,7 +820,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm or % (leave 0 for default)"); def->cli = "first-layer-extrusion-width=s"; def->ratio_over = "first_layer_height"; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionFloatOrPercent(200, true); def = this->add("first_layer_height", coFloatOrPercent); @@ -843,7 +843,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm/s or %"); def->cli = "first-layer-speed=s"; def->min = 0; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionFloatOrPercent(30, false); def = this->add("first_layer_temperature", coInts); @@ -923,7 +923,7 @@ void PrintConfigDef::init_fff_params() def->cli = "infill-every-layers=i"; def->full_label = L("Combine infill every n layers"); def->min = 1; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionInt(1); def = this->add("infill_extruder", coInt); @@ -932,7 +932,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("The extruder to use when printing infill."); def->cli = "infill-extruder=i"; def->min = 1; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionInt(1); def = this->add("infill_extrusion_width", coFloatOrPercent); @@ -944,7 +944,7 @@ void PrintConfigDef::init_fff_params() "If expressed as percentage (for example 90%) it will be computed over layer height."); def->sidetext = L("mm or % (leave 0 for default)"); def->cli = "infill-extrusion-width=s"; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionFloatOrPercent(0, false); def = this->add("infill_first", coBool); @@ -961,7 +961,7 @@ void PrintConfigDef::init_fff_params() "(it will act as internal support material). If enabled, slows down the G-code generation " "due to the multiple checks involved."); def->cli = "infill-only-where-needed!"; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionBool(false); def = this->add("infill_overlap", coFloatOrPercent); @@ -1060,7 +1060,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm/s"); def->min = 0; def->width = machine_limits_opt_width; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionFloats(axis.max_feedrate); // Add the machine acceleration limits for XYZE axes (M201) def = this->add("machine_max_acceleration_" + axis.name, coFloats); @@ -1070,7 +1070,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm/s²"); def->min = 0; def->width = machine_limits_opt_width; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionFloats(axis.max_acceleration); // Add the machine jerk limits for XYZE axes (M205) def = this->add("machine_max_jerk_" + axis.name, coFloats); @@ -1080,7 +1080,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm/s"); def->min = 0; def->width = machine_limits_opt_width; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionFloats(axis.max_jerk); } } @@ -1093,7 +1093,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm/s"); def->min = 0; def->width = machine_limits_opt_width; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionFloats{ 0., 0. }; // M205 T... [mm/sec] @@ -1104,7 +1104,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm/s"); def->min = 0; def->width = machine_limits_opt_width; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionFloats{ 0., 0. }; // M204 S... [mm/sec^2] @@ -1115,7 +1115,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm/s²"); def->min = 0; def->width = machine_limits_opt_width; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionFloats{ 1500., 1250. }; // M204 T... [mm/sec^2] @@ -1126,7 +1126,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm/s²"); def->min = 0; def->width = machine_limits_opt_width; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionFloats{ 1500., 1250. }; def = this->add("max_fan_speed", coInts); @@ -1148,7 +1148,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm"); def->cli = "max-layer-height=f@"; def->min = 0; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionFloats { 0. }; def = this->add("max_print_speed", coFloat); @@ -1213,7 +1213,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm"); def->cli = "min-layer-height=f@"; def->min = 0; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionFloats { 0.07 }; def = this->add("min_print_speed", coFloats); @@ -1244,7 +1244,7 @@ void PrintConfigDef::init_fff_params() def->multiline = true; def->full_width = true; def->height = 130; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionString(""); def = this->add("nozzle_diameter", coFloats); @@ -1264,7 +1264,7 @@ void PrintConfigDef::init_fff_params() def->enum_values.push_back("duet"); def->enum_labels.push_back("OctoPrint"); def->enum_labels.push_back("Duet"); - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionEnum(htOctoPrint); def = this->add("printhost_apikey", coString); @@ -1272,7 +1272,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("Slic3r can upload G-code files to a printer host. This field should contain " "the API Key or the password required for authentication."); def->cli = "printhost-apikey=s"; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionString(""); def = this->add("printhost_cafile", coString); @@ -1287,7 +1287,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("Slic3r can upload G-code files to a printer host. This field should contain " "the hostname, IP address or URL of the printer host instance."); def->cli = "print-host=s"; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionString(""); def = this->add("only_retract_when_crossing_perimeters", coBool); @@ -1324,7 +1324,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("Experimental option to adjust flow for overhangs (bridge flow will be used), " "to apply bridge speed to them and enable fan."); def->cli = "overhangs!"; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionBool(true); def = this->add("parking_pos_retraction", coFloat); @@ -1334,7 +1334,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm"); def->cli = "parking_pos_retraction=f"; def->min = 0; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionFloat(92.f); def = this->add("extra_loading_move", coFloat); @@ -1344,7 +1344,7 @@ void PrintConfigDef::init_fff_params() " if negative, the loading move is shorter than unloading. "); def->sidetext = L("mm"); def->cli = "extra_loading_move=f"; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionFloat(-2.f); def = this->add("perimeter_acceleration", coFloat); @@ -1364,7 +1364,7 @@ void PrintConfigDef::init_fff_params() def->cli = "perimeter-extruder=i"; def->aliases = { "perimeters_extruder" }; def->min = 1; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionInt(1); def = this->add("perimeter_extrusion_width", coFloatOrPercent); @@ -1377,7 +1377,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm or % (leave 0 for default)"); def->cli = "perimeter-extrusion-width=s"; def->aliases = { "perimeters_extrusion_width" }; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionFloatOrPercent(0, false); def = this->add("perimeter_speed", coFloat); @@ -1429,7 +1429,7 @@ void PrintConfigDef::init_fff_params() def->multiline = true; def->full_width = true; def->height = 130; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionString(""); def = this->add("printer_vendor", coString); @@ -1456,7 +1456,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("layers"); def->cli = "raft-layers=i"; def->min = 0; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionInt(0); def = this->add("resolution", coFloat); @@ -1476,7 +1476,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("Retraction is not triggered when travel moves are shorter than this length."); def->sidetext = L("mm"); def->cli = "retract-before-travel=f@"; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionFloats { 2. }; def = this->add("retract_before_wipe", coPercents); @@ -1485,14 +1485,14 @@ void PrintConfigDef::init_fff_params() "before doing the wipe movement."); def->sidetext = L("%"); def->cli = "retract-before-wipe=s@"; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionPercents { 0. }; def = this->add("retract_layer_change", coBools); def->label = L("Retract on layer change"); def->tooltip = L("This flag enforces a retraction whenever a Z move is done."); def->cli = "retract-layer-change!"; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionBools { false }; def = this->add("retract_length", coFloats); @@ -1531,7 +1531,7 @@ void PrintConfigDef::init_fff_params() "absolute Z. You can tune this setting for skipping lift on the first layers."); def->sidetext = L("mm"); def->cli = "retract-lift-above=f@"; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionFloats { 0. }; def = this->add("retract_lift_below", coFloats); @@ -1542,7 +1542,7 @@ void PrintConfigDef::init_fff_params() "to the first layers."); def->sidetext = L("mm"); def->cli = "retract-lift-below=f@"; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionFloats { 0. }; def = this->add("retract_restart_extra", coFloats); @@ -1551,7 +1551,7 @@ void PrintConfigDef::init_fff_params() "this additional amount of filament. This setting is rarely needed."); def->sidetext = L("mm"); def->cli = "retract-restart-extra=f@"; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionFloats { 0. }; def = this->add("retract_restart_extra_toolchange", coFloats); @@ -1569,7 +1569,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("The speed for retractions (it only applies to the extruder motor)."); def->sidetext = L("mm/s"); def->cli = "retract-speed=f@"; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionFloats { 40. }; def = this->add("deretract_speed", coFloats); @@ -1579,7 +1579,7 @@ void PrintConfigDef::init_fff_params() "(it only applies to the extruder motor). If left to zero, the retraction speed is used."); def->sidetext = L("mm/s"); def->cli = "retract-speed=f@"; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionFloats { 0. }; def = this->add("seam_position", coEnum); @@ -1596,7 +1596,7 @@ void PrintConfigDef::init_fff_params() def->enum_labels.push_back(L("Nearest")); def->enum_labels.push_back(L("Aligned")); def->enum_labels.push_back(L("Rear")); - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionEnum(spAligned); #if 0 @@ -1659,7 +1659,7 @@ void PrintConfigDef::init_fff_params() "as a shield against drafts."); def->sidetext = L("layers"); def->cli = "skirt-height=i"; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionInt(1); def = this->add("skirts", coInt); @@ -1670,7 +1670,7 @@ void PrintConfigDef::init_fff_params() "to disable skirt completely."); def->cli = "skirts=i"; def->min = 0; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionInt(1); def = this->add("slowdown_below_layer_time", coInts); @@ -1713,7 +1713,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("The extruder to use when printing solid infill."); def->cli = "solid-infill-extruder=i"; def->min = 1; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionInt(1); def = this->add("solid_infill_every_layers", coInt); @@ -1737,7 +1737,7 @@ void PrintConfigDef::init_fff_params() "If expressed as percentage (for example 90%) it will be computed over layer height."); def->sidetext = L("mm or % (leave 0 for default)"); def->cli = "solid-infill-extrusion-width=s"; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionFloatOrPercent(0, false); def = this->add("solid_infill_speed", coFloatOrPercent); @@ -1826,7 +1826,7 @@ void PrintConfigDef::init_fff_params() def->label = L("Prime all printing extruders"); def->tooltip = L("If enabled, all printing extruders will be primed at the front edge of the print bed at the start of the print."); def->cli = "single-extruder-multi-material-priming!"; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionBool(true); def = this->add("support_material", coBool); @@ -1842,7 +1842,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("If checked, supports will be generated automatically based on the overhang threshold value."\ " If unchecked, supports will be generated inside the \"Support Enforcer\" volumes only."); def->cli = "support-material-auto!"; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionBool(true); def = this->add("support_material_xy_spacing", coFloatOrPercent); @@ -1854,7 +1854,7 @@ void PrintConfigDef::init_fff_params() def->cli = "support-material-xy-spacing=s"; def->ratio_over = "external_perimeter_extrusion_width"; def->min = 0; - def->mode = comMiddle; + def->mode = comAdvanced; // Default is half the external perimeter width. def->default_value = new ConfigOptionFloatOrPercent(50, true); @@ -1874,7 +1874,7 @@ void PrintConfigDef::init_fff_params() def->category = L("Support material"); def->tooltip = L("Only create support if it lies on a build plate. Don't create support on a print."); def->cli = "support-material-buildplate-only!"; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionBool(false); def = this->add("support_material_contact_distance", coFloat); @@ -1891,7 +1891,7 @@ void PrintConfigDef::init_fff_params() def->enum_values.push_back("0.2"); def->enum_labels.push_back((boost::format("0 (%1%)") % L("soluble")).str()); def->enum_labels.push_back((boost::format("0.2 (%1%)") % L("detachable")).str()); - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionFloat(0.2); def = this->add("support_material_enforce_layers", coInt); @@ -1915,7 +1915,7 @@ void PrintConfigDef::init_fff_params() "(1+, 0 to use the current extruder to minimize tool changes)."); def->cli = "support-material-extruder=i"; def->min = 0; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionInt(1); def = this->add("support_material_extrusion_width", coFloatOrPercent); @@ -1926,7 +1926,7 @@ void PrintConfigDef::init_fff_params() "If expressed as percentage (for example 90%) it will be computed over layer height."); def->sidetext = L("mm or % (leave 0 for default)"); def->cli = "support-material-extrusion-width=s"; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionFloatOrPercent(0, false); def = this->add("support_material_interface_contact_loops", coBool); @@ -1944,7 +1944,7 @@ void PrintConfigDef::init_fff_params() "(1+, 0 to use the current extruder to minimize tool changes). This affects raft too."); def->cli = "support-material-interface-extruder=i"; def->min = 0; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionInt(1); def = this->add("support_material_interface_layers", coInt); @@ -1954,7 +1954,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("layers"); def->cli = "support-material-interface-layers=i"; def->min = 0; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionInt(3); def = this->add("support_material_interface_spacing", coFloat); @@ -1964,7 +1964,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm"); def->cli = "support-material-interface-spacing=f"; def->min = 0; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionFloat(0); def = this->add("support_material_interface_speed", coFloatOrPercent); @@ -1990,7 +1990,7 @@ void PrintConfigDef::init_fff_params() def->enum_labels.push_back(L("Rectilinear")); def->enum_labels.push_back(L("Rectilinear grid")); def->enum_labels.push_back(L("Honeycomb")); - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionEnum(smpRectilinear); def = this->add("support_material_spacing", coFloat); @@ -2000,7 +2000,7 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm"); def->cli = "support-material-spacing=f"; def->min = 0; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionFloat(2.5); def = this->add("support_material_speed", coFloat); @@ -2033,7 +2033,7 @@ void PrintConfigDef::init_fff_params() def->cli = "support-material-threshold=i"; def->min = 0; def->max = 90; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionInt(0); def = this->add("support_material_with_sheath", coBool); @@ -2061,7 +2061,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("Detect single-width walls (parts where two extrusions don't fit and we need " "to collapse them into a single trace)."); def->cli = "thin-walls!"; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionBool(true); def = this->add("threads", coInt); @@ -2097,7 +2097,7 @@ void PrintConfigDef::init_fff_params() "If expressed as percentage (for example 90%) it will be computed over layer height."); def->sidetext = L("mm or % (leave 0 for default)"); def->cli = "top-infill-extrusion-width=s"; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionFloatOrPercent(0, false); def = this->add("top_solid_infill_speed", coFloatOrPercent); @@ -2130,7 +2130,7 @@ void PrintConfigDef::init_fff_params() def->cli = "travel-speed=f"; def->aliases = { "travel_feed_rate" }; def->min = 1; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionFloat(130); def = this->add("use_firmware_retraction", coBool); @@ -2174,7 +2174,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("This flag will move the nozzle while retracting to minimize the possible blob " "on leaky extruders."); def->cli = "wipe!"; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionBools { false }; def = this->add("wipe_tower", coBool); @@ -2182,7 +2182,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("Multi material printers may need to prime or purge extruders on tool changes. " "Extrude the excess material into the wipe tower."); def->cli = "wipe-tower!"; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionBool(false); def = this->add("wiping_volumes_extruders", coFloats); @@ -2209,7 +2209,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("X coordinate of the left front corner of a wipe tower"); def->sidetext = L("mm"); def->cli = "wipe-tower-x=f"; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionFloat(180.); def = this->add("wipe_tower_y", coFloat); @@ -2217,7 +2217,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("Y coordinate of the left front corner of a wipe tower"); def->sidetext = L("mm"); def->cli = "wipe-tower-y=f"; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionFloat(140.); def = this->add("wipe_tower_width", coFloat); @@ -2225,7 +2225,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("Width of a wipe tower"); def->sidetext = L("mm"); def->cli = "wipe-tower-width=f"; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionFloat(60.); def = this->add("wipe_tower_rotation_angle", coFloat); @@ -2233,7 +2233,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("Wipe tower rotation angle with respect to x-axis "); def->sidetext = L("degrees"); def->cli = "wipe-tower-rotation-angle=f"; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionFloat(0.); def = this->add("wipe_into_infill", coBool); @@ -2259,7 +2259,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("Maximal distance between supports on sparse infill sections. "); def->sidetext = L("mm"); def->cli = "wipe-tower-bridging=f"; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionFloat(10.); def = this->add("xy_size_compensation", coFloat); @@ -2281,7 +2281,7 @@ void PrintConfigDef::init_fff_params() "from the print bed, set this to -0.3 (or fix your endstop)."); def->sidetext = L("mm"); def->cli = "z-offset=f"; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionFloat(0); def = this->add("bed_size_x", coFloat); @@ -2417,7 +2417,7 @@ void PrintConfigDef::init_sla_params() def->multiline = true; def->full_width = true; def->height = 130; - def->mode = comMiddle; + def->mode = comAdvanced; def->default_value = new ConfigOptionString(""); def = this->add("default_sla_material_profile", coString); diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 43d54abde1..0bdaa2ceeb 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -473,7 +473,7 @@ ConfigMenuIDs GUI_App::get_view_mode() const auto mode = app_config->get("view_mode"); return mode == "expert" ? ConfigMenuModeExpert : - mode == "simple" ? ConfigMenuModeSimple : ConfigMenuModeMiddle; + mode == "simple" ? ConfigMenuModeSimple : ConfigMenuModeAdvanced; } // Update view mode according to selected menu @@ -493,7 +493,7 @@ void GUI_App::update_mode() mainframe->m_plater->Layout(); ConfigOptionMode opt_mode = mode == ConfigMenuModeSimple ? comSimple : - mode == ConfigMenuModeExpert ? comExpert : comMiddle; + mode == ConfigMenuModeExpert ? comExpert : comAdvanced; for (auto tab : tabs_list) tab->update_visibility(opt_mode); } @@ -515,7 +515,7 @@ void GUI_App::add_config_menu(wxMenuBar *menu) local_menu->AppendSeparator(); auto mode_menu = new wxMenu(); mode_menu->AppendRadioItem(config_id_base + ConfigMenuModeSimple, _(L("&Simple")), _(L("Simple View Mode"))); - mode_menu->AppendRadioItem(config_id_base + ConfigMenuModeMiddle, _(L("&Advanced")), _(L("Advanced View Mode"))); + mode_menu->AppendRadioItem(config_id_base + ConfigMenuModeAdvanced, _(L("&Advanced")), _(L("Advanced View Mode"))); mode_menu->AppendRadioItem(config_id_base + ConfigMenuModeExpert, _(L("&Expert")), _(L("Expert View Mode"))); mode_menu->Check(config_id_base + get_view_mode(), true); local_menu->AppendSubMenu(mode_menu, _(L("&Mode")), _(L("Slic3r View Mode"))); diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index dcb3685d1f..ccc7026eed 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -51,7 +51,7 @@ enum ConfigMenuIDs { ConfigMenuUpdate, ConfigMenuPreferences, ConfigMenuModeSimple, - ConfigMenuModeMiddle, + ConfigMenuModeAdvanced, ConfigMenuModeExpert, ConfigMenuLanguage, ConfigMenuFlashFirmware, diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 000270e135..bba5161cc3 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -2768,8 +2768,8 @@ ConfigOptionsGroupShp Page::new_optgroup(const wxString& title, int noncommon_la bmp_name = "error.png"; else { auto mode = line.get_options()[0].opt.mode; //we assume that we have one option per line - bmp_name = mode == comExpert ? "mode_expert_.png" : - mode == comMiddle ? "mode_middle_.png" : "mode_simple_.png"; + bmp_name = mode == comExpert ? "mode_expert_.png" : + mode == comAdvanced ? "mode_middle_.png" : "mode_simple_.png"; } auto bmp = new wxStaticBitmap(parent, wxID_ANY, wxBitmap(from_u8(var(bmp_name)), wxBITMAP_TYPE_PNG)); return bmp; From 321322b17ae0fc7f284b0c14139951abc9436c4c Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Thu, 25 Oct 2018 15:32:35 +0200 Subject: [PATCH 183/186] Fixed rendering of warning and legend textures (due to newer wxWidgets) --- src/slic3r/GUI/GLCanvas3D.cpp | 14 ++------------ src/slic3r/GUI/Plater.cpp | 10 +--------- 2 files changed, 3 insertions(+), 21 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index d70048d858..a0c79f3126 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -2424,17 +2424,12 @@ bool GLCanvas3D::WarningTexture::generate(const std::string& msg) // generates bitmap wxBitmap bitmap(m_width, m_height); -#if defined(__APPLE__) || defined(_MSC_VER) - bitmap.UseAlpha(); -#endif - memDC.SelectObject(bitmap); memDC.SetBackground(wxBrush(wxColour(Background_Color[0], Background_Color[1], Background_Color[2]))); memDC.Clear(); - memDC.SetTextForeground(*wxWHITE); - // draw message + memDC.SetTextForeground(*wxWHITE); memDC.DrawText(msg, 0, 0); memDC.SelectObject(wxNullBitmap); @@ -2561,17 +2556,12 @@ bool GLCanvas3D::LegendTexture::generate(const GCodePreviewData& preview_data, c // generates bitmap wxBitmap bitmap(m_width, m_height); -#if defined(__APPLE__) || defined(_MSC_VER) - bitmap.UseAlpha(); -#endif - memDC.SelectObject(bitmap); memDC.SetBackground(wxBrush(wxColour(Background_Color[0], Background_Color[1], Background_Color[2]))); memDC.Clear(); - memDC.SetTextForeground(*wxWHITE); - // draw title + memDC.SetTextForeground(*wxWHITE); int title_x = Px_Border; int title_y = Px_Border; memDC.DrawText(title, title_x, title_y); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 9c228dbdf2..18e47ef8cd 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -813,7 +813,6 @@ struct Plater::priv void reload_from_disk(); void export_object_stl(); void fix_through_netfabb(); - void item_changed_selection(); void on_notebook_changed(wxBookCtrlEvent&); void on_select_preset(wxCommandEvent&); @@ -1747,11 +1746,6 @@ void Plater::priv::fix_through_netfabb() */ } -void Plater::priv::item_changed_selection() -{ - // TODO -} - void Plater::priv::on_notebook_changed(wxBookCtrlEvent&) { const auto current_id = notebook->GetCurrentPage()->GetId(); @@ -1924,7 +1918,6 @@ void Plater::priv::on_action_selectbyparts(SimpleEvent&) void Plater::priv::on_object_select(SimpleEvent& evt) { selection_changed(); - item_changed_selection(); wxGetApp().obj_list()->update_selections(); } #else @@ -1936,8 +1929,7 @@ void Plater::priv::on_object_select(ObjectSelectEvent &evt) if (obj_idx >= 0 && obj_idx < 1000 && vol_idx == -1) { // Ignore the special objects (the wipe tower proxy and such). select_object(obj_idx); - item_changed_selection(); - } +} } #endif // ENABLE_EXTENDED_SELECTION From 965236a9d9f8ffbfbe694f012c4bc8a6501ca3a0 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Thu, 25 Oct 2018 15:59:27 +0200 Subject: [PATCH 184/186] Fixed OsX build fails --- src/slic3r/GUI/SysInfoDialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/slic3r/GUI/SysInfoDialog.cpp b/src/slic3r/GUI/SysInfoDialog.cpp index ee3060c242..007b6e6e40 100644 --- a/src/slic3r/GUI/SysInfoDialog.cpp +++ b/src/slic3r/GUI/SysInfoDialog.cpp @@ -75,7 +75,7 @@ SysInfoDialog::SysInfoDialog() auto bgr_clr_str = wxString::Format(wxT("#%02X%02X%02X"), bgr_clr.Red(), bgr_clr.Green(), bgr_clr.Blue()); const int fs = font.GetPointSize() - 1; - int size[] = { fs*1.5, fs*1.4, fs*1.3, fs, fs, fs, fs }; + int size[] = { static_cast(fs*1.5), static_cast(fs*1.4), static_cast(fs*1.3), fs, fs, fs, fs }; wxHtmlWindow* html = new wxHtmlWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHW_SCROLLBAR_NEVER); { From cbb62142debd70f21f3504170f4e7453ca2971ba Mon Sep 17 00:00:00 2001 From: YuSanka Date: Thu, 25 Oct 2018 21:13:45 +0200 Subject: [PATCH 185/186] =?UTF-8?q?Added=20"Set=20number=20of=20copies?= =?UTF-8?q?=E2=80=A6"=20to=20the=20context=20menu?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/slic3r/GUI/Plater.cpp | 11 ++++++++++- src/slic3r/GUI/Plater.hpp | 2 +- src/slic3r/GUI/wxExtensions.cpp | 11 ----------- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 18e47ef8cd..95d0520011 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include "libslic3r/libslic3r.h" #include "libslic3r/PrintConfig.hpp" @@ -2023,6 +2024,8 @@ bool Plater::priv::init_object_menu() [this](wxCommandEvent&){ q->increase_instances(); }, "add.png"); wxMenuItem* item_decrease = append_menu_item(&object_menu, wxID_ANY, _(L("Decrease copies\t-")), _(L("Remove one copy of the selected object")), [this](wxCommandEvent&){ q->decrease_instances(); }, "delete.png"); + wxMenuItem* item_set_number_of_copies = append_menu_item(&object_menu, wxID_ANY, _(L("Set number of copies…")), _(L("Change the number of copies of the selected object")), + [this](wxCommandEvent&){ q->set_number_of_copies(); }, "textfield.png"); object_menu.AppendSeparator(); @@ -2062,6 +2065,7 @@ bool Plater::priv::init_object_menu() q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_delete_object()); }, item_delete->GetId()); q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_increase_instances()); }, item_increase->GetId()); q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_decrease_instances()); }, item_decrease->GetId()); + q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_increase_instances()); }, item_set_number_of_copies->GetId()); q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_split_to_objects() || can_split_to_volumes()); }, item_split->GetId()); q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_split_to_objects()); }, item_split_objects->GetId()); q->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_split_to_volumes()); }, item_split_volumes->GetId()); @@ -2280,7 +2284,7 @@ void Plater::decrease_instances(size_t num) this->p->schedule_background_process(); } -void Plater::set_number_of_copies(size_t num) +void Plater::set_number_of_copies(/*size_t num*/) { #if ENABLE_EXTENDED_SELECTION int obj_idx = p->get_selected_object_idx(); @@ -2295,6 +2299,11 @@ void Plater::set_number_of_copies(size_t num) auto *model_object = p->model.objects[*obj_idx]; #endif // ENABLE_EXTENDED_SELECTION + const auto num = wxGetNumberFromUser( " ", _("Enter the number of copies:"), + _("Copies of the selected object"), model_object->instances.size(), 0, 1000, this ); + if (num < 0) + return; + int diff = (int)num - (int)model_object->instances.size(); if (diff > 0) increase_instances(diff); diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 7ea5b19643..4c6d0ff302 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -114,7 +114,7 @@ public: void remove_selected(); void increase_instances(size_t num = 1); void decrease_instances(size_t num = 1); - void set_number_of_copies(size_t num); + void set_number_of_copies(/*size_t num*/); // Note: empty path means "use the default" void export_gcode(boost::filesystem::path output_path = boost::filesystem::path()); diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp index 27628c3db4..f9eb032c46 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -653,17 +653,6 @@ wxDataViewItem PrusaObjectDataViewModel::DeleteLastInstance(const wxDataViewItem ItemDeleted(inst_root_item, wxDataViewItem(last_instance_node)); } -// for (int i = delete_inst_root_item ? 0 : inst_cnt - num; i < inst_cnt; ++i) -// items.Add(wxDataViewItem(inst_root_node->GetNthChild(i))); -// -// if (delete_inst_root_item) -// inst_root_node->GetChildren().RemoveAt(0, inst_cnt); -// else { -// ret_item = wxDataViewItem(inst_root_node->GetNthChild(inst_cnt - num - 1)); -// inst_root_node->GetChildren().RemoveAt(inst_cnt - num, num); -// } - -// ItemsDeleted(inst_root_item, items); if (delete_inst_root_item) { ret_item = parent_item; parent_node->GetChildren().Remove(inst_root_node); From f65118210124d460d9cb6478a84976bb98160595 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Fri, 26 Oct 2018 09:50:28 +0200 Subject: [PATCH 186/186] Rendering of camera target (for debug) and modified camera target behavior --- src/libslic3r/Technologies.hpp | 11 ++++++ src/slic3r/GUI/GLCanvas3D.cpp | 63 ++++++++++++++++++++++++++++++++-- src/slic3r/GUI/GLCanvas3D.hpp | 8 +++++ src/slic3r/GUI/Plater.cpp | 4 +++ 4 files changed, 84 insertions(+), 2 deletions(-) diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index d80d6df0d7..ec775742b2 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -1,7 +1,16 @@ #ifndef _technologies_h_ #define _technologies_h_ +//============== +// debug techs +//============== + +// Shows camera target in the 3D scene +#define ENABLE_SHOW_CAMERA_TARGET 1 + +//============== // 1.42.0 techs +//============== #define ENABLE_1_42_0 1 // Add double click on gizmo grabbers to reset transformation components to their default value @@ -12,6 +21,8 @@ #define ENABLE_EXTENDED_SELECTION (1 && ENABLE_1_42_0) // Add mirror components along the three axes in ModelInstance and GLVolume #define ENABLE_MIRROR (1 && ENABLE_1_42_0) +// Modified camera target behavior +#define ENABLE_MODIFIED_CAMERA_TARGET (1 && ENABLE_1_42_0) #endif // _technologies_h_ diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index a0c79f3126..0200122862 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -3209,6 +3209,16 @@ void GLCanvas3D::zoom_to_volumes() m_apply_zoom_to_volumes_filter = false; } +#if ENABLE_MODIFIED_CAMERA_TARGET +#if ENABLE_EXTENDED_SELECTION +void GLCanvas3D::zoom_to_selection() +{ + if (!m_selection.is_empty()) + _zoom_to_bounding_box(m_selection.get_bounding_box()); +} +#endif // ENABLE_EXTENDED_SELECTION +#endif // ENABLE_MODIFIED_CAMERA_TARGET + void GLCanvas3D::select_view(const std::string& direction) { const float* dir_vec = nullptr; @@ -3365,6 +3375,9 @@ void GLCanvas3D::render() _render_current_gizmo(); _render_cutting_plane(); +#if ENABLE_SHOW_CAMERA_TARGET + _render_camera_target(); +#endif // ENABLE_SHOW_CAMERA_TARGET // draw overlays _render_gizmos_overlay(); @@ -3744,9 +3757,29 @@ void GLCanvas3D::on_char(wxKeyEvent& evt) case 83: case 115: { post_event(SimpleEvent(EVT_GLCANVAS_SCALE_UNIFORMLY)); break; } #endif // !ENABLE_EXTENDED_SELECTION +#if ENABLE_MODIFIED_CAMERA_TARGET +#if ENABLE_EXTENDED_SELECTION + // key Z/z + case 90: + case 122: + { + if (m_selection.is_empty()) + zoom_to_volumes(); + else + zoom_to_selection(); + + break; + } +#else // key Z/z case 90: case 122: { zoom_to_volumes(); break; } +#endif // ENABLE_EXTENDED_SELECTION +#else + // key Z/z + case 90: + case 122: { zoom_to_volumes(); break; } +#endif // ENABLE_MODIFIED_CAMERA_TARGET default: { evt.Skip(); @@ -4931,8 +4964,7 @@ void GLCanvas3D::_camera_tranform() const ::glRotatef(-m_camera.get_theta(), 1.0f, 0.0f, 0.0f); // pitch ::glRotatef(m_camera.phi, 0.0f, 0.0f, 1.0f); // yaw - Vec3d neg_target = - m_camera.target; - ::glTranslated(neg_target(0), neg_target(1), neg_target(2)); + ::glTranslated(-m_camera.target(0), -m_camera.target(1), -m_camera.target(2)); } void GLCanvas3D::_picking_pass() const @@ -5251,6 +5283,33 @@ void GLCanvas3D::_render_toolbar() const m_toolbar.render(); } +#if ENABLE_SHOW_CAMERA_TARGET +void GLCanvas3D::_render_camera_target() const +{ + double half_length = 5.0; + + ::glDisable(GL_DEPTH_TEST); + + ::glLineWidth(2.0f); + ::glBegin(GL_LINES); + // draw line for x axis + ::glColor3f(1.0f, 0.0f, 0.0f); + ::glVertex3d(m_camera.target(0) - half_length, m_camera.target(1), m_camera.target(2)); + ::glVertex3d(m_camera.target(0) + half_length, m_camera.target(1), m_camera.target(2)); + // draw line for y axis + ::glColor3f(0.0f, 1.0f, 0.0f); + ::glVertex3d(m_camera.target(0), m_camera.target(1) - half_length, m_camera.target(2)); + ::glVertex3d(m_camera.target(0), m_camera.target(1) + half_length, m_camera.target(2)); + ::glEnd(); + + ::glBegin(GL_LINES); + ::glColor3f(0.0f, 0.0f, 1.0f); + ::glVertex3d(m_camera.target(0), m_camera.target(1), m_camera.target(2) - half_length); + ::glVertex3d(m_camera.target(0), m_camera.target(1), m_camera.target(2) + half_length); + ::glEnd(); +} +#endif // ENABLE_SHOW_CAMERA_TARGET + #if ENABLE_EXTENDED_SELECTION void GLCanvas3D::_update_volumes_hover_state() const { diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index c0f531919f..693c7d62dd 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -823,6 +823,11 @@ public: void zoom_to_bed(); void zoom_to_volumes(); +#if ENABLE_MODIFIED_CAMERA_TARGET +#if ENABLE_EXTENDED_SELECTION + void zoom_to_selection(); +#endif // ENABLE_EXTENDED_SELECTION +#endif // ENABLE_MODIFIED_CAMERA_TARGET void select_view(const std::string& direction); void set_viewport_from_scene(const GLCanvas3D& other); @@ -909,6 +914,9 @@ private: void _render_current_gizmo() const; void _render_gizmos_overlay() const; void _render_toolbar() const; +#if ENABLE_SHOW_CAMERA_TARGET + void _render_camera_target() const; +#endif // ENABLE_SHOW_CAMERA_TARGET #if ENABLE_EXTENDED_SELECTION void _update_volumes_hover_state() const; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 95d0520011..59ebe10b23 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1259,7 +1259,9 @@ std::vector Plater::priv::load_model_objects(const ModelObjectPtrs &mode } update(); +#if !ENABLE_MODIFIED_CAMERA_TARGET _3DScene::zoom_to_volumes(canvas3D); +#endif // !ENABLE_MODIFIED_CAMERA_TARGET object_list_changed(); this->schedule_background_process(); @@ -2561,7 +2563,9 @@ void Plater::changed_object_settings(int obj_idx) _3DScene::set_objects_selections(p->canvas3D, selections); #endif // !ENABLE_EXTENDED_SELECTION _3DScene::reload_scene(p->canvas3D, false); +#if !ENABLE_MODIFIED_CAMERA_TARGET _3DScene::zoom_to_volumes(p->canvas3D); +#endif // !ENABLE_MODIFIED_CAMERA_TARGET } else { this->p->schedule_background_process();