mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-11-02 04:31:17 -07:00
Feature/bs1.8beta (#2844)
* ENH: Show Recent File Image Keep Scale
Change-Id: Ib8a6cf916eaee8e353bf858bc4f2ea503705809e
* FIX: wipetower position problem
jira: STUDIO-4914
Change-Id: I7b05d3c53931ed8ce3d4603ff21ee6ef675611e5
* FIX: dailytips adapts screen scale
jira: STUDIO-5019 STUDIO-5026 STUDIO-5027 STUDIO-5028 STUDIO-5025
Change-Id: I63d3af1870218ba8e0f048a6ef03fb29fabe27cb
* FIX: generate process preset based on template
Jira: XXXX
Change-Id: I50adf0790dc239307d236a4cebece860ef6beb16
Signed-off-by: maosheng.wei <maosheng.wei@bambulab.com>
* FIX: object list plate name edit
Change-Id: I61d3dcd7d9598d759a3a0b44cc77d2af2adca25a
Jira: STUDIO-4937
* ENH:no longer checking nozzle type
jira:[for nozzle type check]
Change-Id: I0e88445a264f21b0c11519e9a22a165d05611d14
* ENH: improve first layer tree support
First layer support can't be top interface, and
min brim width of auto mode should be larger
than 0.
Jira: STUDIO-5010
Change-Id: I02f8b017b535f8a47965387e8679f692b1966e04
(cherry picked from commit 3e7d54abe352e8ab5f9d6492b5a86a96f9067f94)
* ENH: version: bumped to 1.8
JIRA: no jira
Change-Id: I50903098b59f1dd9a6b6cf7656cec7d388f3ff17
* ENH:try again after subscription failure
jira:[Try again after subscription failure]
Change-Id: Ibfb1e8e26eb166d786a372632a86ef98030db034
* ENH:display msg dialog once
jira:[for http error msg]
Change-Id: I12e9c155fdb567cac99c35b6feeef650269ba75d
* ENH:remove config.json file
Change-Id: Idfcf3a63fefe968e88153c26fb691fd05cd83dc4
* ENH:add protection in threads
jira:[for random crash]
Change-Id: I6286012dd77abccba461f7cd72a6fc531a84c95f
* FIX: add protection for get_model_task_thread thread
Jira: XXXX
Change-Id: I3cbc17d181a0e13c658f31eaeb6a4df878e6df41
Signed-off-by: maosheng.wei <maosheng.wei@bambulab.com>
* FIX: delete all compatible presets when delete third printer
Jira: XXXX
Change-Id: I1a294402627e7ab7a8c6701f20679b3d04aff059
Signed-off-by: maosheng.wei <maosheng.wei@bambulab.com>
* ci: update build version to 01.08.00.51
Change-Id: I20a01adacbdb5fe69c106b9efd029f7308136e10
* ENH: default open support_interface_not_for_body
jira:[NEW]
Signed-off-by: xun.zhang <xun.zhang@bambulab.com>
Change-Id: I48e084deb18633f9ec47a8ec4ec643163bf66318
* ENH:modified text with too low version
jira:[for low version]
Change-Id: I862a0defda976a35f326a8805e002330f2ed7fdf
* NEW:update printer config file version
Change-Id: I9a46b29b03beb67a3da0b8f76d8b5c4b3c482928
* FIX:The plane should rotate around the world coordinate system
Jira: STUDIO-5054
Change-Id: I16e484b38d79cabd9473acf1abf3c5c6b0adc4c6
* ENH:translate for limit file size and so on
Jira: STUDIO-5007
Change-Id: I2c279eb690841aa51cd8128f8028266cbc17e977
* ENH:use on_render_rotate_gizmos() replace GLGizmoRotate3D::on_render()
Jira: STUDIO-4227
Change-Id: If9b9ea5596e59472d5fa87ac56aeb7f6ecc65643
* FIX: some mistakes in filament profiles
jira:[NEW]
Signed-off-by: xun.zhang <xun.zhang@bambulab.com>
Change-Id: Ibe7f3650f2d9cf47561dd5f2ec591a5f6c553503
* FIX: fix shard_ptr is null
Change-Id: I0187cf64ffbb08a2265a11900b5c865e9ac9678f
* FIX:N1 printer image in dark mode
JIRA:STUDIO-4057
Change-Id: I22c001d96839daf213d5096f6ff6e3d6398fa8c4
* FIX: create printer issue
Jira: 5034 5059 5053
5034 create printer but filament is repeat
5039 create successful dialog remove to center
5053 create existing printer copywriting adjustments and preset updates
Delete printer secondary confirmation dialog
Change-Id: Ifb3822d1e168459d2af11e02b31ecaf3719d338a
Signed-off-by: maosheng.wei <maosheng.wei@bambulab.com>
* ENH:just don't check the nozzle diameter
jira:[for nozzle check]
Change-Id: I678e7d62832eaa14b9be47d6dce70f29ebd601f6
* NEW:p1 and x1 series added motor noise calibration
JIRA: 5085
Change-Id: Id73cc2d34b6130f215d81ffcdc39ba6b241445bf
* ci: update build version to 01.08.00.52
Change-Id: I93d800b413f2751d132fac53fbd9b191603d0352
* FIX: ObjectSetting changed when search plate
JIRA: STUDIO-5095
Signed-off-by: Kunlong Ma <kunlong.ma@bambulab.com>
Change-Id: I39b1ad997d51ac4224ff5ad2b3555f56da4bd911
* FIX: invalid support params in 3rd party profiles
Many params are not right.Just use default
jira:[NEW]
Signed-off-by: xun.zhang <xun.zhang@bambulab.com>
Change-Id: I5c4a1e8b046940e174f5681a79031b5f20fcafc5
* ENH: update A1 mini start gcode
Change x-axis freq sweep amp 5->10
jira:[NEW]
Signed-off-by: xun.zhang <xun.zhang@bambulab.com>
Change-Id: I2e731cc6392c0204d5e4467bf4b933ab233bc157
* FIX: [STUDIO-4946] use utf8 path to create sub process
Change-Id: I5873c114e8cd36978a7d50bf13c3aa7bf8b740ca
Jira: STUDIO-4946
* FIX: fix a plate state not correct issue
JIRA: no-jira
the object and instance states lost after undo
Change-Id: I527df9a7d426d994501a4ed5bbb198c7bbac810b
* FIX: some translation
Jira: 5096 5089 5036 5004
Change-Id: I4f1bd6e352b11451f5caf02cbc4eeb31dfa03eee
Signed-off-by: maosheng.wei <maosheng.wei@bambulab.com>
* FIX: [STUDIO-4935] plate name edit in object list
Change-Id: I271fa217281d0c7ceca61166497136628a66681e
Jira: STUDIO-4935
* FIX: take custom root as AMS sync candicate
Change-Id: I9c71babcd74238d1533b15d77a978b19997c70c0
Jira: none
* FIX: modify some default support params in code
1. Modify default values of some supports params, so 3rd party profiles are easier to setup.
3. Fix a bug that organic support may cause crash.
Jira: none
Change-Id: Icae348d8fe5985f4287404e96089198a499283f2
(cherry picked from commit 8889cfc703b72e142f288e525b89c87619f2213c)
* FIX: do not generate sheath for normal support
Jira: none
Change-Id: I8f3f3e39171055f8d18c06ceee8e245594273238
(cherry picked from commit 93bc7ecf4346f179f502bebc3cf47b0030b56e2c)
* FIX: push_notification on GUI thread
Change-Id: Iaec347f5684fe0f65d6418759518189b67033c42
Jira: STUDIO-5106
* ENH: CLI: add some params to support more functions
1. uptodate_filaments to support update the original filaments to newest config
2. allow_rotations/avoid_extrusion_cali_region for auto-arrange
3. skip_modified_gcodes to support skip modified gcodes
JIRA: STUDIO-5112
Change-Id: I95c09af1b5462cce3bf27aea32228d6d1d1d201d
* FIX: missed manually entered values for secondary processing
Jira: STUDIO-4964
Change-Id: I5cf0da1ae77cccd34de05b4a0318a751ac9f6753
* FIX: Z hop is still enabled when upper boundary is zero.
Jira: STUDIO-4893
Signed-off-by: wenjie.guo <wenjie.guo@bambulab.com>
Change-Id: I5f46a02e1fbb15ff43e253e3a184aa6cc38e7598
* ENH: update default filaments for Bambu printers
jira:[NEW]
Signed-off-by: xun.zhang <xun.zhang@bambulab.com>
Change-Id: Ic6380f39e546854ad0b7dc36929a8605c9ab3acc
* ENH: dailytips modification
1. modify closing behavior
2. dailytips can adjust self size according to the canvas size. And also adjust
GodeViewer legend window size
3. fix a button text encoding bug
4. support vertical/horizontal layout(horizontal layout currently not used)
jira: new
Change-Id: I8e0b6e85c455d0608d7388fb441829c1991ad01f
* FIX: [4857 5097] export list and del preset two confirm issue
Jira: 4857 5097
Change-Id: If7cc4967a663f575527a227e9c4ac31e0491930c
* FIX: UUID conflict issue when referencing volume
Jira: XXXX
3mf file standard
Change-Id: I953a87294684ea85d03a95e7d2843c096904aeae
Signed-off-by: maosheng.wei <maosheng.wei@bambulab.com>
* FIX: [4483 5003 5109] create printer and edit filament issue
Jira: 4483 5003 5109
4483 dialog blink
5003 preset list too long
5109 encode
Change-Id: I190e12272ca09f36b841f2f85a6cf60f2c2614bd
Signed-off-by: maosheng.wei <maosheng.wei@bambulab.com>
* FIX: cloud use presets limit notify
Change-Id: I6cc7b4e560cb83db0fc30921633b10531957128e
Jira: STUDIO-5091, STUDIO-5104
* FIX: do user preset sync later on startup
Change-Id: I0653a0438477b1c803ce1cddc66ef47f95616dae
Jira: STUDIO-5106
* FIX: linux: pressing enter in height range will crash
jira: STUDIO-4391
Change-Id: I6bf990951d1456f5b2605b8d62a05bceb3cc4c10
* FIX: failed to limit the max width of DropDown
Jira: STUDIO-4503
Signed-off-by: wenjie.guo <wenjie.guo@bambulab.com>
Change-Id: Id9352d16f4bc016daade72a9c8d3d90164a1cb3d
* FIX: not jump to preview after first wizard
Change-Id: I8c94d66a91aa15a7874441a300b40438638bd33b
Jira: STUDIO-5018
* ENH: CLI: clear custom gcodes when skip_modified_gcodes
JIRA: STUDIO-5112
Change-Id: I2e7346d2ac57519029a4e80e5492c34d3d91ed77
* FIX: [4492 4851 4883 5121] create printer issue
Jira: 4492 4851 4883 5121
Change-Id: If252b5f30be0403f79410aa8c00fc14b066d5bbd
Signed-off-by: maosheng.wei <maosheng.wei@bambulab.com>
* ENH: add 'edit preset' and 'delete preset' btn for each preset
Jira: 5200 5113
Change-Id: I208ad63eb4b895306fa76db424da2e1df10a582e
Signed-off-by: maosheng.wei <maosheng.wei@bambulab.com>
* FIX: add skip label before tool change
Jira: 5074
github: 2776
Signed-off-by: qing.zhang <qing.zhang@bambulab.com>
Change-Id: Icaafd3b45da1e78c1a82e7d17d7505d9439b9100
* FIX:Network test dark mode adaptation
JIRA:STUDIO-2468
Change-Id: I20cb7f1fd8eca3ce852acb563c1cc87978e216dc
* FIX:n1 external feed prompt pop-up without retry button
JIRA: STUDIO-4696
Change-Id: I31069c72e29d3398469d71cdbc2a344a5430fc2c
* FIX: not show device page when switch printer preset
Change-Id: I00d8524625a4682b6a39876ddb66bf8bd928dbef
Jira: none
* ENH: Check the nozzle diameter when sending calibration
Jira: 4977
Change-Id: Iabbba44583bbd9fbaaa889ca546ee0ccbb2aa77f
* FIX: Generate UUID from objectID and volumeIndex
Jira: XXXX
Change-Id: I65147ef9b695f8af8de260d722e604b0e0bab563
Signed-off-by: maosheng.wei <maosheng.wei@bambulab.com>
* FIX: disable filament_typep
Jira: XXXX
Change-Id: Ib605b33e4474525fbe49e70596fc09aa356f478a
Signed-off-by: maosheng.wei <maosheng.wei@bambulab.com>
* ci: update build version to 01.08.00.53
Change-Id: I1d574fa2cf2a4d0eb63a38eb8ced7587d06a4272
* ENH: refine display logic of param
1. Refine the display logic of "support_interface_not_for_body".Only
toggle if support_filament is default and support_interface_filament
is specified
jira:[NEW]
Signed-off-by: xun.zhang <xun.zhang@bambulab.com>
Change-Id: Ia2af030c4531ad6b04a198bfe8a1677b3d20a800
* FIX: user preset sync token
Change-Id: Id2aa865b778ee9ac4cfddb68ceef0374507b519b
Jira: none
* FIX: Bitmap cache not take effect
Change-Id: I972098fdbda0b4542c6c759a8f5e1f0f2a30852b
Jira: STUDIO-4991
* NEW: Open HotModel Link With GetParam-From bambustudio
JIRA: NO JIRA
Change-Id: I4ac49bac5ee0c50988c76a38b00b7ba7dc3201f5
* NEW:AmsMaterialsSetting Support for user-preset
JIRA: STUDIO-5135
Change-Id: If848047cd5dbd059d440de30989c505c361305a7
* FIX: upload custom root preset fail
Change-Id: I621c8d542dd604b07cc5df63d97d7a31558d3aba
Jira: none
* FIX: show custom filament in AMS filament list
Change-Id: I79b9f8f2f08db8c52bbed76f1ea133baff383c00
Jira: none
* FIX: dailytips window and gcodeviwer legend window size issue
reset to original logic of dailytips and legend window size
jira: new
Change-Id: Iacb016bb222ba3f87317cfbe1f2b003802d773a5
* ENH: add text translation
jira: new
Change-Id: I780cfb8a0a64d806b5e0a414b6598e3b7bdf52dc
* FIX: Delete and search object outside the plate
JIRA:
1. STUDIO-5132 Deleting object outside the plate will crash
2. STUDIO-5146 The search function cannot search for object outside the plate
Signed-off-by: Kunlong Ma <kunlong.ma@bambulab.com>
Change-Id: I84cb3fe990a9c2a182e7434c262466a70545280e
* FIX: [5149 5142 5141 5140 5136] create printer and filament issue
Jira: 5149 5142 5141 5140 5136
5149 process preset name can not show all
5142 improt configs combobox not update
5141 disable modify filament_vendor
5140 disable input Bambu and Generic vendor
5136 preset list window adjust
Change-Id: I111a23996146cc16cc7f533c8616d50223d34c40
Signed-off-by: maosheng.wei <maosheng.wei@bambulab.com>
* ci: update build version to 01.08.00.54
Change-Id: Ifd69c01a82f627a9c6cf4fe0d48a759563ee90e7
* FIX: print model from sdcard with p1p
Change-Id: If85383ba762022ead3dd754ae02a08817b891114
Jira: none
* FIX: dailytips text translation
jira: STUDIO-2556
Change-Id: If44e503615b09ee1692f42ba1f998918ec5bd691
* FIX: clone shortcut key conflict with quit in macos
jira: STUDIO-5166
Change-Id: I548f275bb68d3b0e6bb3cfad6fe93df09d507da3
* FIX:User preset material settings dependent on firmware
JIRA: 5167
Change-Id: I82cf26848594b01155883ad0aa2e9ee77d371fb2
* ENH:update the description of nozzle detection
Change-Id: Id27b25c69dc11fcf66fc82053af705906ae8c370
* FIX: [5159 5165 5171 5172] create printer and filament issue
Jira: 5159 5165 5171 5172
5159 create printer dialog no refresh
5165 create printer 2 step dialog no refersh
5171 change font
5172 edit filament dialog darkUI issue
input special character is prohibited
'/' in preset name translate to '-'
update printer combobox
Change-Id: I5fa27836dab7f604f1a065c65efa099c7a2f0f96
Signed-off-by: maosheng.wei <maosheng.wei@bambulab.com>
* ci: update build version to 01.08.00.55
Change-Id: If1865d561cf274719204662314de163497759e89
* FIX:fix GLmodel deconstruction causing section not to be rendered
Jira: STUDIO-5156
Change-Id: Ibb2f459920989ee54f7b827352dc8893424b4de6
* FIX: missing unlock cause device or resource busy
Change-Id: I87563312ea9c6ce4e4e471da7ce7a02b53b64762
* FIX: some translation
Change-Id: I9758cbc758030b5a3945697a50ca4898af9fcb1b
* ci: update build version to 01.08.00.56
Change-Id: Id5ee53dd2ebb0b37b6927dc58b3cca94a1f66a83
* ENH: remove PLA GLOW in A1 mini
jira:[NEW]
Signed-off-by: xun.zhang <xun.zhang@bambulab.com>
Change-Id: Id99c1bbd4248e28df9150a85eecec831f6f32856
* ci: update build version to 01.08.00.57
Change-Id: Ib4dfa60f097128b76b95bb14ca04978619021b56
* Allow line width of nozzle diameter * 2.5
As it were, 1 mm would be disallowed but 0.99 would be allowed for 0.4
nozzle. 1 mm is the sane maximum and 0.99 is unnecessary tedious to write.
* Russian translation update
Russian translation Bambu Studio_v1.8.0 Beta
* FIX: scale problem in needs_retraction
jira:[NEW]
Signed-off-by: xun.zhang <xun.zhang@bambulab.com>
Change-Id: Idfbe954b22fa6aa5769c55e46874fa6a80ecbf45
(cherry picked from commit 4e853f50b748e3af11e2d64862b6ee557fda361b)
* ENH: CLI: support load_assemble_list
JIRA: STUDIO-4848
Change-Id: Ife11533740988331ea71eac86c370e625970cb8b
* FIX: align to Y not working
This is a bug introduced in 7fbb650 when solving jira STUDIO-4695.
Now we use a more decent way to solve it.
Change-Id: I92deffcb9fe53e8a24c93fe973446ae37df07375
(cherry picked from commit bd98430dbd15eb6c9bb4b447990e0dcf8a50eef0)
* ENH: Add buried points for cut and meshboolean
JIRA: NONE
Signed-off-by: Kunlong Ma <kunlong.ma@bambulab.com>
Change-Id: I67ce498d0c335dd7a8582f56b880c2c8314f8541
* FIX: 5092 edit filament add scrolled window
Jira: 5092
Change-Id: I53ae996b04e4e2f1b1ddce6a858d505001b11615
Signed-off-by: maosheng.wei <maosheng.wei@bambulab.com>
* FIX: can not select user preset when create filament
Jira: XXXX
github: 1936
and fix add preset for printer dialog can not show selected printer
Change-Id: Id4308c6bdca17d52d4aa321db359941aa87e0e45
Signed-off-by: maosheng.wei <maosheng.wei@bambulab.com>
* ENH: template filament don't be show in filament list and sort
Jira: 5160 5179
Change-Id: I56a7e1897e1ef3c061dc66d318896413ca25b76b
Signed-off-by: maosheng.wei <maosheng.wei@bambulab.com>
* FIX: [5174] export configs dialog issue
filament name too long to can not show all
Jira: 5174
Change-Id: I92018c9d7f86009b78b533592d899b4b5d78c3c8
Signed-off-by: maosheng.wei <maosheng.wei@bambulab.com>
* ENH: add filament Bambu TPU 95A HF
1.As title
jira:[NEW]
Signed-off-by: xun.zhang <xun.zhang@bambulab.com>
Change-Id: I752ec43da6297a6c172679997ce68f2318a7b8fb
* ENH: modify some params with filaments
1.Modify the PEI bed temperature of PLA Basic, Matte, and Tough to 65 in
A1 mini. Set the bed temperature for the first layer of Bambu PETG-CF
to 65 and 70 for the other layers
jira:[NEW]
Signed-off-by: xun.zhang <xun.zhang@bambulab.com>
Change-Id: Ia902bbb7f824082d5346709d781cac64296f47a8
* ENH: add more status during printing
JIRA: STUDIO-5195
Change-Id: I85b3107839c6e2fdecbc10d90a876463e284468c
Signed-off-by: Stone Li <stone.li@bambulab.com>
* FIX:cut imgui has overlapping rendering on Apple
Jira: STUDIO-5150
Change-Id: I7969e19dc189cd617026a183067dad628208955c
* FIX:not TakeSnapshot for m_start_dragging_m
Jira: STUDIO-5176
Change-Id: Ia03e3e2c2664dbdcffa19ec8d0fa97dfd95e6d35
* FIX: rendered color changes
Jira: STUDIO-4956
during the drag processin connectors editing state
Change-Id: I3027176ea9f93a9ba9d6a2052f41aaa4adef79f1
* FIX: merge the patch from Prusa
Thanks for PrusaSlicer and YuSanka
Jira:STUDIO-5175
commit 510d59687b3b19c4a0f4e6540620d0694dd1b7ac
Author: YuSanka <yusanka@gmail.com>
Date: Thu Oct 5 14:13:14 2023 +0200
Follow-up 1b451cdf: Fixed #11415 - Connectors disappear when slicing => only when using multiple cut planes AND excluding parts
Change-Id: I9ccd5b85f482d723d21fccf5e104c9e0a9cc4849
* FIX:Press ESC directly to exit after entering the profile rendering
rendering is not normal,Code from PrusaSlicer,thanks for PrusaSlicer and enricoturri1966
commit a078627552f54497ed0518dc7bc349d243576d19
Author: enricoturri1966 <enricoturri@seznam.cz>
Date: Mon Jan 30 14:00:02 2023 +0100
Follow-up of 1218103fd620b319c56fd08116f81b581c537188 - Fixed gizmo missbehavior when closing a gizmo by resetting the selection clicking on the scene
Jira: STUDIO-5164
Change-Id: I261da9dba2a5ac37f3e263c175fbccd80d8045bd
* FIX: correct the strings and move create printer dialog center
Jira: 5221 5183
Change-Id: Ida4eba63f0e962ffcc8000fcc04cf20849577217
Signed-off-by: maosheng.wei <maosheng.wei@bambulab.com>
* ENH: CLI: skip layer height limit validate when slicing for existing models
JIRA: no jira
Change-Id: I1444a28b500ca7d08ed2606eecfa5cfaf261105e
* ENH:update the translation of auto refill
jira:[for translation]
Change-Id: Iaa7b4f3d7cd88c8b4f69a3db721ebd8ca8986eea
* FIX: icon issue for copying
Jira: STUDIO-4168
Icon issue when filling bed with copies
Change-Id: I61a03ecae02b75602c236ed2810e9c9cfe5a19f9
(cherry picked from commit b5079f8a2e79f19f65803f23ef4fd83aff17c84a)
* ENH: update some filament params
1. Modify texture bed temp to 65
2. Modify max-v-speed for ABS
3. Modify some params in Generic PA
4. Modify PLA,PVA params
jira:[NEW]
Signed-off-by: xun.zhang <xun.zhang@bambulab.com>
Change-Id: I42584a6015b8526f6bbb93024316968198bd76ce
* FIX: 3770 printable checkbox incorrect display in darkUI
Jira: 3770
Change-Id: I97f67d7a0ffc41f6ee625abeecc52ee4e73cf318
* FIX:Display garbled code in AmsMaterialsSetting pop-up
Change-Id: I50531e939afa7715ae376bac47172ccf7b248114
* ENH:Modifying the Line Color of Transparent Materials
JIRA: STUDIO-4311,5088,4983
Change-Id: I9e63413dc9cd7d523f0f7f1a2e32c4537a84467a
* FIX: crash when async delete printer file
Change-Id: I92c5e812d04da263338fb0eea2fd7583cf9ecde0
Jira: STUDIO-5222
* FIX: 3733 backup time not effective
Jira: 3733
Change-Id: I50c2ce156fcbd0a17aa8a6777bce04aa6093c830
Signed-off-by: maosheng.wei <maosheng.wei@bambulab.com>
* FIX: enable edit and delete preset btn and fix issue
Jira: XXXX
Change-Id: I724d7236b28fcc4746698f094531948a8fbb5d93
Signed-off-by: maosheng.wei <maosheng.wei@bambulab.com>
* FIX:send print job,file name displays error
JIRA:3137
Change-Id: I1c113025d274a13fba1b845a58aada14058fadd4
* FIX: skip hold user preset from sync
Change-Id: I2252246e19bd80903ad82170782ea49535d30d05
Jira: STUDIO-5185
* FIX: 5115 translations
Jira: 5115
Change-Id: I21b03bdd4d28c0bb097226143177e763cf8c777f
Signed-off-by: maosheng.wei <maosheng.wei@bambulab.com>
* FIX: add link for ironing parameter
Change-Id: I451f5549db3ac2205aa5703a2e5edc831e946af8
* FIX: scale problem in lift type decide
1. Scale the travel threshhold
jira:[NEW]
Signed-off-by: xun.zhang <xun.zhang@bambulab.com>
Change-Id: Ib594d640fe63b0919bc9318af88577513f7dbf30
* ENH: add small perimeter speed and threshold
The original param is added by Prusa. Thanks orca for adding threshold.
1. Re add small perimeter speed and threhold.
github: #2221
Change-Id: I35b269b26f085d80f0edca28650bb21fc04898d7
* FIX: modify the picture of pa manual cali
Jira: STUDIO-5102
Change-Id: Id87898959ad4461b7bd2505b159271f2aa589c36
* FIX: Filament preset is the same with the first one
Jira: STUDIO-4519
Filament preset is the same wit the first one, it should align with the
last one.
Signed-off-by: wenjie.guo <wenjie.guo@bambulab.com>
Change-Id: I304d0ff0fbc1c8948d410ea552e4d42b6a4e8fd9
* FIX: scoreDailog dark mode issue
Jira: 4570
Change-Id: I8be97b306a1494f73e3bba678ecc864e7ff88ca3
* FIX: CLI: fix the slicing issue while only one object with multicolor using seq-print
JIRA: no-jira
Change-Id: Iea2d23ff8e484bf2fd58aa2f596a8e4e4292fe39
* ENH: open support wall count for normal support
1. open support wall count for normal support
Enabling this option makes normal support stronger and gives
better overhang quality, but also more difficult to removal.
Jira: STUDIO-5192
2. fix a bug where tree support (hybrid style) may get overlapped
extrusions near the walls.
3. fix a bug where raft layers can't be 1 in tree support
Jira: STUDIO-5261
Change-Id: Iadc0c67a9b50b5b221c8e83d5aa22ed282018cf8
(cherry picked from commit c0bb0084e386cb70ed6e16edf93190e4b38f5b90)
* FIX: compiling error on linux
jira: none
Change-Id: I1a4563503b5ddf74a1979cc0cee7a15b8aced904
(cherry picked from commit de52c6ca62c9f3a6314ddf5a856c1d8534329886)
* ENH: add translation for small perimeter
jira:[NEW]
Signed-off-by: xun.zhang <xun.zhang@bambulab.com>
Change-Id: I95013649e4e0c07c0f04b89a91488814c8d228cc
* FIX: clone shortcut key issue on macos
jira: STUDIO-5166
Change-Id: I1967da1d443ed43bd750dad8e11560688d7bd533
* FIX: custom gcode window cannot paste/ navigate
jira: STUDIO-5208、STUDIO-5070
Change-Id: I4ecb9d06cf5db0ae53a4678181aae9298bac106b
* ENH: modify dailytips collapse & expand interaction
jira: STUDIO-5209、STUDIO-5210
Change-Id: Ifb0b998e5004d4b49390ba5a250eaf4743bf3471
* ENH:Add shortcut keys and lists for objects search
JIRA: STUDIO-5157 STUDIO-5158 STUDIO-5240
Signed-off-by: Kunlong Ma <kunlong.ma@bambulab.com>
Change-Id: Ic7cfaaa9b4bb8a85208bafab7fe3bafdb78f0045
* FIX:Re-calculate button with White Box displayed in dark mode
JIRA: STUDIO-5098
Signed-off-by: Kunlong Ma <kunlong.ma@bambulab.com>
Change-Id: I07cc6c72d5dbd03b72573cd27dd5938bb0e6a29a
* NEW: display plate index when printing a task
JIRA: STUDIO-2689
display on the thumbnail of the current task
Change-Id: I5f1f46c56e9d1e9120a66d491551908dfad099d6
Signed-off-by: Stone Li <stone.li@bambulab.com>
* ENH:fixed incorrect path prefix
jira:[for file path prefix]
Change-Id: Ie9e3999f02b78272e528ceceb479e746d46a7e6c
* FIX: thumbnail is not clear in dark mode
JIRA: STUDIO-5087
Change-Id: Ie86493ed71b5554095927f061509a1f551758b61
Signed-off-by: wenjie.guo <wenjie.guo@bambulab.com>
* FIX: translation
Jira: XXXX
Change-Id: Id03f0d704aa852632a907ea628d1277400112062
Signed-off-by: maosheng.wei <maosheng.wei@bambulab.com>
* ENH: first nozzle change to 0.4 and nozzle change to mm
Jira: XXXX
Change-Id: I14defd36442dbd7008e46782b08415b6244224f1
Signed-off-by: maosheng.wei <maosheng.wei@bambulab.com>
* ENH:editing_window_width's value is small on the laptop
Jira: STUDIO-5238 STUDIO-5265
apply_selected_connectors should check_and_update_connectors_state
Change-Id: I8c2c1c920cc4d197d1908815a3e62f4962335451
* FIX: fix new_bed_shape's calculation process
Jira: STUDIO-5122
Change-Id: I5f3e6a301a297123af28692c90bef6759f425b06
* ENH:update some translations
jira:[STUDIO-5262]
Change-Id: Idb1d3586888043ac325f272bc7a2b788adb3e9e5
* FIX: edit text command resets object settings
Jira: STUDIO-4655
Signed-off-by: wenjie.guo <wenjie.guo@bambulab.com>
Change-Id: Iac25c4e40f1d0d32e6d1f40e62226cc22bc96042
* ci: update build version to 01.08.00.58
Change-Id: Iacfec02aa50c617e4c9fe566319b07b30d47dce1
* FIX: remove GetUserAgent
Change-Id: I92886e1f0dcb091109231a10da8c19d51178e13b
Jira: STUDIO-5205
* FIX: nozzle_diameter_map data structure adjustment
Change-Id: Ifb724afc0fcf974e6d331e73ecac723107a102cf
* ENH:add _A and _B for perform_with_groove
Jira: STUDIO-5267
Change-Id: Iee3310dfa1cd8e6680310f0af0eff5c817490813
* ENH:is_equal for min_z and max_z
Jira: STUDIO-5267
Change-Id: I9493883d8be9d44e26ddc9afe62b7e9eb09c5052
* ci: update build version to 01.08.00.59
Change-Id: Ie8ed29ccf5d6c94594eb2ab8b717416fbeace3bd
* FIX:Image display unclear in light mode
JIRA:5161
Change-Id: I134cc64a2af0dfff60c47d0ff09d78d9c0f86b3f
* FIX:fix bugs of non manifold edge
Jira: STUDIO-5267
Change-Id: I8ac9a2cf96da0bc07ee00b309e65611b92fd174d
* ENH:nozzle type detection
jira:[STUDIO-5246]
Change-Id: Ic41a2161a0e41d23f56af93ad8ec34cc83ada0e3
* ENH: upadte P1S start gcode
1.turn on MC board fan by default on P1S
jira:[NEW]
Signed-off-by: xun.zhang <xun.zhang@bambulab.com>
Change-Id: I5b2f7868e350942fb8b7baf7d429e22a0987184a
(cherry picked from commit e866a575b6b7d9552f7412f84272f4b48dfc3961)
* ENH: improve support style's tooltip
jira: none
Change-Id: I8ee858d7052f04ce7ea6b226a500c7d1bf8a482f
(cherry picked from commit 665f31c4fcde22bd894cbb4a5fb160635947f2a4)
* ENH: set layer range error to warning
1. If layer range exceeds maximum/minimum layer range in printer
settings,pop up a window to warn
jira:[NEW]
Signed-off-by: xun.zhang <xun.zhang@bambulab.com>
Change-Id: I0304ee790e557ecf967f355c171993d1f51b5057
* ENH: CLI: remove the warning of layer height
JIRA: no jira
Change-Id: Idaceee4f52611479fc3f4238d016d891b4dc8cd1
* FIX: the word search is not translated
Jira: STUDIO-5224
The world search in the device panel is not translated.
Signed-off-by: wenjie.guo <wenjie.guo@bambulab.com>
Change-Id: Ia3d651c2159a3aad94e10cd0a6da98848f53ee2a
(cherry picked from commit 4a46a0a4750d82d49c9523f4b668a1a00c41ed83)
* FIX: Bitmap will flash when sending printing task
Jira: STUDIO-5278
Signed-off-by: wenjie.guo <wenjie.guo@bambulab.com>
Change-Id: Ib0c8710b8d5d6b98fad043c950f054aa35bea965
* ENH:display the euler angle of rotation plane
Jira: STUDIO-5268
Change-Id: I6b7b431931d60f1a9a832908400417781798c472
* ci: update build version to 01.08.00.60
Change-Id: I1c15b5c6437554c43327cd6b537f7a5860dba5a0
* ENH:cancel EnterReturnsTrue for imgui in cut
Jira: STUDIO-5269
Change-Id: I2832e1dccaf9755448debe7b2bd56426f90dfe0d
* ci: update build version to 01.08.00.61
Change-Id: Ib03e664a20990322c788686550c491d0139d8237
* FIX: some translation problems
jira:[NEW]
Signed-off-by: xun.zhang <xun.zhang@bambulab.com>
Change-Id: If9f2af53b4f0bfa9469e84bcba68cc182df4a473
* add: Ukrainian lang support for 1.8
* fix linux
* fix some string and colors
* fix linux build error 2
* fix .gitignore
* FIX: calibration selected preset is null in some case
jira: STUDIO-5258
Change-Id: Iee63593c5f833c5a43e3b1d1c9ddb82f8c69569a
* FIX: create filament issue
Jira: 5296 5297 5295 5302 5311 5276
5296 create filament: list has same printer
5297 create filament: filament combobox has blank options
5298 edit filament: delete last preset prompt users
5302 create filament: filament combox has cili preset
5311 create filament: printer name too long to can not show all
5276 edit filament: PLA Aero filament type filter issue
add prusa vendor
Revised copy
Change-Id: I5dcc615ce0951b1a9953fa12283f6090f5069045
* FIX: some translation
Change-Id: Icb8614a0af18f96d15f3b97c17e0f6f708296847
* FIX:cancel is_equal for slicing function
Jira: STUDIO-5267
Change-Id: I66d759aa2c968f8a28a6a5d8378929754f2db689
* FIX:UI stuck due to pop-up window with wrong chamber temperature
JIRA: 5304
Change-Id: I1a49a7219b7a6f5700243704c348724e7930ce1a
* FIX: allow input '+' and hide edit preset btn
Change-Id: I97aec7c3ac4cc8b9d6c535f0126aaa1926553d86
* ENH: handle printer direct close and not retry
Change-Id: I5dd55f8085cf6383a8420ab41e614ea6ae210c78
Jira: STUDIO-5305
* ci: update build version to 01.08.00.62
Change-Id: I09716bf79354b503197c751272fd3171e0abc8fd
* add: new translation to ukr for AirFlow and Prusa
* add: Texture Plate name fix
* add new feature to localization .de, fix .it (#2876)
* FIX:add slice_facet_for_cut_mesh api for cut tool
and modify section_vertices_map 's traverse
Jira: STUDIO-5267
Change-Id: Ifc4b183a4e4c4fdb4f47742f14f70a1ed93fa056
Change-Id: I52bfaef8926ef967b78a6cb712a1731a1b528a24
* FIX: Make the front smaller for Czech in device panel
Jira: STUDIO-5151
Signed-off-by: wenjie.guo <wenjie.guo@bambulab.com>
Change-Id: I315174b55f923da069854fb4fed8cf3937b82074
* FIX: there is no object can be jumped to in notification
jira: new
Change-Id: Ib81bf49236952ede24a2de126051572d63916e01
* FIX: add height range, modifier in Preview pane will crash
jira: STUDIO-5340
1. fix crash at add height range, modifiers in Preview from objectList
2. fix an assert hit when slicing
3. fix an assert hit when enter AssembleView
4. forbidden popup menu by right-click objectList in Preview
Change-Id: I444bc76b1a4307999b387e4f60386b2d272bd308
* FIX: Black spot in the sending printing task page
Jira: STUDIO-5307
Signed-off-by: wenjie.guo <wenjie.guo@bambulab.com>
Change-Id: I3bd97c063ec5f0faf7d12047da39f60ce55cae4b
* FIX: reset_cut_by_contours should update_buffer_data
Jira: STUDIO-5376
Change-Id: I5aacb1f7b65822031d7138abd61a45b09c743531
* ENH:editing_window_width's value is small on the laptop
Jira: STUDIO-5238 STUDIO-5265
Change-Id: Ia958772bcb081817da621115f99328bb62770cd5
* ENH: bumped version to 1.8.1
Change-Id: I9d25403daa5b7b8ca415c0b364670da9e0f932b0
* FIX: create filament dialog: create btn can not show all
Jira: 5310 5331
Change-Id: I185272c90d9ff1c3d6b47abbefbf488d0d965cca
* FIX:update custom_texture when new_shape=false
Jira: STUDIO-5287
Change-Id: I3add95f9f9345c14a48cc7467513d1b3ce95f4c9
* ENH:editing_window_width's value is small on the laptop
Jira: STUDIO-5238
Change-Id: I9044129f4e0c8ca7469db05b3e547fca4754342a
* FIX:add slash_to_back_slash for saving file path
Jira: STUDIO-5287
Change-Id: I9f3c176cd0831c793958f08601c63efac98176a4
* FIX: a button color didn't response to dark mode change
jira: STUDIO-5315
Change-Id: I95489f01ccd1f77b9e95b0d0f69e5398d2e88487
* FIX: height range layers displayed in wrong position
jira: STUDIO-5341
Change-Id: I83918b4624f367efa54321f1898e1176cdb04ea9
* FIX: auto arranging issues with locked plates
1. global auto arranging may put items overlap with wipe tower if some plates are locked
jira: STUDIO-5329
2. items outside bed may overlap with plate boundary if it's rotated
jira: STUDIO-5329
3. plate-wise auto arranging uses wrong min_obj_distance if the
plate is by-layer printing but global setting is by-object printing
jira: STUDIO-5330
Change-Id: I5dba2f1317e183c9aeec1cb2bd227fbddf4316e6
(cherry picked from commit db1eac41efff5f1e8d5ac0af74c6fc7ab59fc253)
* FIX: a mistake in upward machine
jira:[NEW]
Signed-off-by: xun.zhang <xun.zhang@bambulab.com>
Change-Id: Ibdb26c3d904634f322aef0dc0c7b8867d9fb5854
* FIX:a blank pop-up appears
JIRA:XXXX
Change-Id: Ice92b55204e4897fec024a6d99412eb810bddd4a
* FIX:fixed failure in updating nozzle type
jira:[STUDIO-5248]
Change-Id: Iad37b5d5b76d37cb1723ef21d7c39b1e3fcaf8d7
* FIX:fixed issue with AI monitoring settings
jira:[STUDIO-5082]
Change-Id: I967fe3c1e9da61a55bcbfaa2a8e067dd5af18f72
* FIX:fixed issue with lan mode
jira:[STUDIO-5189]
Change-Id: I1d0a05f19dcea154cf3ef2b61ed0546d3581905e
* FIX:update text for loading or unloading filaments
jira:[STUDIO-5231]
Change-Id: Ic7729c3ec012485b3d87e3d01f11e87502c67895
* FIX: Revert "ENH: do not leave a gap for top...
Revert "ENH: do not leave a gap for top interface if the top z distance is 0"
This reverts commit 79ea32c7cbbdb7e689637980af7c36caf42284c9.
Revert reason: the supports are impossible to remove in some cases.
jira: STUDIO-5385
Change-Id: I376a6f4dfd78da6dfea68b9ac3d552cddd0b4272
(cherry picked from commit 34e38b705fde7f5d7f9a3a89c96a3627ce0c998e)
* ENH: improve normal support's quality
1. Add a base_interface_layer when using Supp.W
2. Fix a bug where base_angle and interface_angle are wong
jira: STUDIO-5386
Change-Id: I52ab32c63b3cd1e6e2ba6463b01ae26699cf13d3
(cherry picked from commit 92ddd4a10b793572a1fa009da5b9e44fcdf81de2)
* NEW:tracking stl model files
jira:[STUDIO-5372]
Change-Id: Idb1275b07441f0cd06c24588d5f7c20f81f1556c
* FIX: edit filament dialog: preset name too long to del btn nan't show
Jira: 5336 5174
and verify string normalization
Change-Id: I380c3bed2bf43d01094b68979a8b67f4187c0b93
* FIX: some translation
Jira: 5232 5300 5334
Change-Id: Ie474ca823011e81aab82a9809af3d6e42980496b
* FIX: some translation
Change-Id: Iaabe6087bed3b7d47d911cf4fb51c770804e72fb
* ENH: change default tree_support_wall_count to 0
Now normal support also uses this option, so we can't default it to 1, otherwise normal supports will be too hard to remove.
jira: none
Change-Id: Ic5700af5c17e3a7b265c8915f28b0db35c6e06e6
(cherry picked from commit 6b84a9826da108b76569e686bd9def0b23ae29fd)
* FIX:The name of the material in the error prompt is empty
JIRA:STUDIO-4907
Change-Id: I3cf44f099256a51f21a44a89c89c000f734d1f36
* ci: update build version to 01.08.01.51
Change-Id: Ib20f5a12b65472102befec0a2adf82744fc29c46
* FIX: imgui textinput cannot paste on macos
jira: STUDIO-5070、STUDIO-5365
Change-Id: Iea8f41e12744ecda0fbb95c1a8f2e014a7cdc384
* FIX: not cache printer file list on error
Change-Id: I99843aedbf14d3d1d553ccac9b0bd26403274a82
Jira: none
* FIX: thread of close BBLUserPresetExceedLimit notify
Change-Id: I9698134ba1cc91fc83eac441f900d68c4c4b556a
* ENH: Resolve non manifold edges by fixing model interfaces
Jira: STUDIO-5124
Change-Id: I7ea86be44acb80b6c4762a76208b4a031acd0b27
* FIX:nozzle type sync
jira:[STUDIO-5248]
Change-Id: I63d48628832473d8d371ed643dc8528b00382531
* FIX: array bound happen in TriangleSelector::deserialize
Jira: STUDIO-5170
Change-Id: I92b72a887845b462fad208f13607293b44d3d333
* FIX:cropping rendering without considering assembly views
Jira: STUDIO-5260
Change-Id: Ia56cf80b305ae05f25f06ec277f85b3c5430a6df
* FIX: PA for custom filament not available in BL Studio
github: 2971
Change-Id: I6ccd36a183e7367d69557300f7242f5403f4bb33
* FIX: Bitmap is way too small on Mac
Jira: STUDIO-5393
Signed-off-by: wenjie.guo <wenjie.guo@bambulab.com>
Change-Id: I6b550669fa8cd5fc9bfa6ed96d64d19a949f01b2
* FIX: move shutdown wait to OnExit
Change-Id: I70d9a2bb686525ae5273aa9d63e25691da4ab65c
Jira: STUDIO-2884
* FIX: calibration manage result dialog issue on macos
jira: STUDIO-4949 STUDIO-5378
Change-Id: I00abefd45a0d274a4b68bb1ab18debe8f91d169e
* FIX: adjust bed shape dialog button UI style
fix that button text is hard to see in dark mode
jira: STUDIO-5247
Change-Id: I2cf5b3cdd2eff9b821bdf5525bec4f329fc58dd1
* FIX: 5331 rescale btn
Jira: STUDIO-5331
Change-Id: If153424b8480e64b166018e3cd98c17db557d0a8
Signed-off-by: maosheng.wei <maosheng.wei@bambulab.com>
* FIX: support do not generate
jira:[NEW]
Signed-off-by: xun.zhang <xun.zhang@bambulab.com>
Change-Id: Ide9709d95203185538e280517f7aa6136beeda44
* FIX: remove not match printer config ota cache
Change-Id: Ib73fc2ea31fa2186061cfcb5a170bc59b9db84ca
Jira: none
* FIX:cancel the variable of "checkbox_size" as a fixed value
Jira: STUDIO-5150
Change-Id: I30d876d141b8b35ab4a3fee4889993d87b7c1741
* ENH:add reset_cut_by_contours in on_load function
Jira:STUDIO-5269
m_connector_size_tolerance default value is 0.1f
Change-Id: I6c67fff3cb0c1190e9141ed6f68fbfa848679f35
* ENH:cancel EnterReturnsTrue for imgui in cut
Jira: STUDIO-5269
Change-Id: Ifc4b183a4e4c4fdb4f47742f14f70a1ed93fa056
Signed-off-by: zhou.xu <zhou.xu@bambulab.com>
* FIX: dailytips should not change content frequently when slicing all
jira: STUDIO-5234
Change-Id: Icb7e9c28404d9db8ebed58d937e13f89c5403b5c
* FIX: objectList clone shortcut key issue
jira: new
Change-Id: Ia75bf58a7d53f962e1af6c2fd97497270b7eea84
* ENH:handling cases without msgs
jira:[STUDIO-5401 STUDIO-5399]
Change-Id: Iae651d5a19a45b0138a6aa621326a8b4a9649824
* ENH: optimize param description
jira:[NEW]
Signed-off-by: xun.zhang <xun.zhang@bambulab.com>
Change-Id: Id0ca9224227a716b21fc0b8430722264dc319344
* ENH: add translation
jira:[NEW]
Signed-off-by: xun.zhang <xun.zhang@bambulab.com>
Change-Id: I3b1f04fee3cd6322793794ad8b8707859f6c7d26
* FIX: close edit preset paramsDialog, mac unresponsive
Jira: 5298
Change-Id: I021e00567354cfb1f2f5f1f2bf6ba1fc35b164c5
* ENH:disable AI monitoring on the p1p series
Change-Id: I514bb1fb1ced6c03dd619230a9adac3be63f2de2
* ci: update build version to 01.08.01.52
Change-Id: I9f5e30d3fc4b7ef9321c522d3c18fce98f03742f
* FIX: close edit preset paramsDialog, mac unresponsive
Change-Id: Ic816754a20b7f6a5cdb46475750eb301fec3ad3a
* FIX: organic support not work with raft only
There is no raft generated when only raft enabled but no support needed.
jira: none
Change-Id: Ic0c9269e2f98038d85c9bc54e4a85f892dc5d764
* FIX: CLI: add object config when assemble
JIRA: no jira
Change-Id: I945f820fb58f2f643170b4b0b66742f6bbbdfd29
* FIX: delete preset prompt
Jira: XXXX
Change-Id: I6511c806c56393d4f6bd72d1c506da59675d49ff
* FIX:Reorganize the assignment of variables of "m_editing_window_width"
Jira: STUDIO-5238
Change-Id: If369916f3f5c21510f5f297bfd05c1230bdda7a4
* ENH: CLI: re-compute flush_volumes_matrix when it is missed
Change-Id: Ie8f53c6bef003b1434de02ea14de5787b376484f
* FIX: some translation for delete filament
Change-Id: Ib46a8eba33f2e21016476aaab4a57a740e86b1b8
* FIX: scrolled window / del preset / edit filament issue
Jira: 5092
GitHub: 1936
edit filament: just one preset, the scroll bar obscures the preset name
edit filament: delete selected preset, click no, but preset be deleted
from UI
edit filament: serial sometimes displays incorrectly
Change-Id: Ibc91609e252179de0c05ca065099756da6631165
* ci: update build version to 01.08.01.53
Change-Id: I5563a2c0812ab9a0d7727df27e17e681066ffa08
---------
Signed-off-by: maosheng.wei <maosheng.wei@bambulab.com>
Signed-off-by: xun.zhang <xun.zhang@bambulab.com>
Signed-off-by: Kunlong Ma <kunlong.ma@bambulab.com>
Signed-off-by: wenjie.guo <wenjie.guo@bambulab.com>
Signed-off-by: qing.zhang <qing.zhang@bambulab.com>
Signed-off-by: Stone Li <stone.li@bambulab.com>
Signed-off-by: zhou.xu <zhou.xu@bambulab.com>
Co-authored-by: zorro.zhang <zorro.zhang@bambulab.com>
Co-authored-by: liz.li <liz.li@bambulab.com>
Co-authored-by: maosheng.wei <maosheng.wei@bambulab.com>
Co-authored-by: chunmao.guo <chunmao.guo@bambulab.com>
Co-authored-by: tao wang <tao.wang@bambulab.com>
Co-authored-by: Arthur <arthur.tang@bambulab.com>
Co-authored-by: lane.wei <lane.wei@bambulab.com>
Co-authored-by: gerrit <gerrit@bambulab.com>
Co-authored-by: xun.zhang <xun.zhang@bambulab.com>
Co-authored-by: zhou.xu <zhou.xu@bambulab.com>
Co-authored-by: hu.wang <hu.wang@bambulab.com>
Co-authored-by: Kunlong Ma <kunlong.ma@bambulab.com>
Co-authored-by: wenjie.guo <wenjie.guo@bambulab.com>
Co-authored-by: qing.zhang <qing.zhang@bambulab.com>
Co-authored-by: zhimin.zeng <zhimin.zeng@bambulab.com>
Co-authored-by: the Raz <rasmus@abc.se>
Co-authored-by: Andy <andylg@yandex.ru>
Co-authored-by: Stone Li <stone.li@bambulab.com>
Co-authored-by: enricoturri1966 <enricoturri@seznam.cz>
Co-authored-by: Dmytro Chystiakov <dlchistyakov@gmail.com>
Co-authored-by: Heiko Liebscher <hliebscher@idn.de>
This commit is contained in:
parent
2f3ec2ab7d
commit
d8dd8fa634
420 changed files with 43962 additions and 14438 deletions
3385
src/OrcaSlicer.cpp
3385
src/OrcaSlicer.cpp
File diff suppressed because it is too large
Load diff
|
|
@ -17,6 +17,44 @@ namespace IO {
|
|||
};
|
||||
}
|
||||
|
||||
#define JSON_ASSEMPLE_PLATES "plates"
|
||||
#define JSON_ASSEMPLE_PLATE_PARAMS "plate_params"
|
||||
#define JSON_ASSEMPLE_PLATE_NAME "plate_name"
|
||||
#define JSON_ASSEMPLE_PLATE_NEED_ARRANGE "need_arrange"
|
||||
#define JSON_ASSEMPLE_OBJECTS "objects"
|
||||
#define JSON_ASSEMPLE_OBJECT_PATH "path"
|
||||
#define JSON_ASSEMPLE_OBJECT_COUNT "count"
|
||||
#define JSON_ASSEMPLE_OBJECT_FILAMENTS "filaments"
|
||||
#define JSON_ASSEMPLE_OBJECT_POS_X "pos_x"
|
||||
#define JSON_ASSEMPLE_OBJECT_POS_Y "pos_y"
|
||||
#define JSON_ASSEMPLE_OBJECT_POS_Z "pos_z"
|
||||
#define JSON_ASSEMPLE_OBJECT_ASSEMBLE_INDEX "assemble_index"
|
||||
#define JSON_ASSEMPLE_OBJECT_PRINT_PARAMS "print_params"
|
||||
|
||||
|
||||
typedef struct _assemble_object_info {
|
||||
std::string path;
|
||||
int count;
|
||||
|
||||
std::vector<int> filaments;
|
||||
std::vector<int> assemble_index;
|
||||
std::vector<float> pos_x;
|
||||
std::vector<float> pos_y;
|
||||
std::vector<float> pos_z;
|
||||
std::map<std::string, std::string> print_params;
|
||||
}assemble_object_info_t;
|
||||
|
||||
typedef struct _assemble_plate_info {
|
||||
std::string plate_name;
|
||||
bool need_arrange {false};
|
||||
int filaments_count {0};
|
||||
|
||||
std::map<std::string, std::string> plate_params;
|
||||
std::vector<assemble_object_info_t> assemble_obj_list;
|
||||
std::vector<ModelObject *> loaded_obj_list;
|
||||
}assemble_plate_info_t;
|
||||
|
||||
|
||||
class CLI {
|
||||
public:
|
||||
int run(int argc, char **argv);
|
||||
|
|
@ -41,11 +79,12 @@ private:
|
|||
bool export_project(Model *model, std::string& path, PlateDataPtrs &partplate_data, std::vector<Preset*>& project_presets,
|
||||
std::vector<ThumbnailData*>& thumbnails, std::vector<ThumbnailData*>& top_thumbnails, std::vector<ThumbnailData*>& pick_thumbnails,
|
||||
std::vector<ThumbnailData*>& calibration_thumbnails,
|
||||
std::vector<PlateBBoxData*>& plate_bboxes, const DynamicPrintConfig* config);
|
||||
std::vector<PlateBBoxData*>& plate_bboxes, const DynamicPrintConfig* config, bool minimum_save, int plate_to_export = -1);
|
||||
|
||||
bool has_print_action() const { return m_config.opt_bool("export_gcode") || m_config.opt_bool("export_sla"); }
|
||||
|
||||
std::string output_filepath(const Model &model, IO::ExportFormat format) const;
|
||||
std::string output_filepath(const ModelObject &object, unsigned int index, IO::ExportFormat format) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ typedef Eigen::Matrix<int, 3, 1, Eigen::DontAlign> stl_triangle_vertex_indices
|
|||
static_assert(sizeof(stl_vertex) == 12, "size of stl_vertex incorrect");
|
||||
static_assert(sizeof(stl_normal) == 12, "size of stl_normal incorrect");
|
||||
|
||||
typedef std::function<void(int current, int total, bool& cancel)> ImportstlProgressFn;
|
||||
typedef std::function<void(int current, int total, bool& cancel, std::string& model_id)> ImportstlProgressFn;
|
||||
|
||||
typedef enum {
|
||||
eNormal, // normal face
|
||||
|
|
@ -157,6 +157,7 @@ struct stl_file {
|
|||
return sizeof(*this) + sizeof(stl_facet) * facet_start.size() + sizeof(stl_neighbors) * neighbors_start.size();
|
||||
}
|
||||
|
||||
char mw_data[256];
|
||||
std::vector<stl_facet> facet_start;
|
||||
std::vector<stl_neighbors> neighbors_start;
|
||||
// Statistics
|
||||
|
|
@ -275,7 +276,6 @@ extern void stl_mirror_yz(stl_file *stl);
|
|||
extern void stl_mirror_xz(stl_file *stl);
|
||||
|
||||
extern float get_area(stl_facet* facet);
|
||||
|
||||
extern void stl_get_size(stl_file *stl);
|
||||
|
||||
// the following function is not used
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ extern void stl_internal_reverse_quads(char *buf, size_t cnt);
|
|||
#endif /* BOOST_ENDIAN_BIG_BYTE */
|
||||
|
||||
const int LOAD_STL_UNIT_NUM = 5;
|
||||
static std::string model_id = "";
|
||||
|
||||
static FILE* stl_open_count_facets(stl_file *stl, const char *file)
|
||||
{
|
||||
|
|
@ -150,31 +151,66 @@ static FILE* stl_open_count_facets(stl_file *stl, const char *file)
|
|||
time running this for the stl and therefore we should reset our max and min stats. */
|
||||
static bool stl_read(stl_file *stl, FILE *fp, int first_facet, bool first, ImportstlProgressFn stlFn)
|
||||
{
|
||||
if (stl->stats.type == binary)
|
||||
fseek(fp, HEADER_SIZE, SEEK_SET);
|
||||
else
|
||||
rewind(fp);
|
||||
if (stl->stats.type == binary) {
|
||||
fseek(fp, HEADER_SIZE, SEEK_SET);
|
||||
}
|
||||
else {
|
||||
rewind(fp);
|
||||
try{
|
||||
char solid_name[256];
|
||||
int res_solid = fscanf(fp, " solid %[^\n]", solid_name);
|
||||
if (res_solid == 1) {
|
||||
char* mw_position = strstr(solid_name, "MW");
|
||||
if (mw_position != NULL) {
|
||||
// Extract the value after "MW"
|
||||
char version_str[16];
|
||||
char model_id_str[128];
|
||||
int num_values = sscanf(mw_position + 3, "%s %s", version_str, model_id_str);
|
||||
if (num_values == 2) {
|
||||
if (strcmp(version_str, "1.0") == 0) {
|
||||
model_id = model_id_str;
|
||||
}
|
||||
}
|
||||
else {
|
||||
model_id = "";
|
||||
}
|
||||
}
|
||||
else {
|
||||
model_id = ""; // No MW format found
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...){
|
||||
}
|
||||
|
||||
rewind(fp);
|
||||
}
|
||||
|
||||
|
||||
char normal_buf[3][32];
|
||||
|
||||
uint32_t facets_num = stl->stats.number_of_facets;
|
||||
uint32_t unit = facets_num / LOAD_STL_UNIT_NUM + 1;
|
||||
for (uint32_t i = first_facet; i < facets_num; ++ i) {
|
||||
if ((i % unit) == 0) {
|
||||
bool cb_cancel = false;
|
||||
if (stlFn) {
|
||||
stlFn(i, facets_num, cb_cancel);
|
||||
if (cb_cancel)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if ((i % unit) == 0) {
|
||||
bool cb_cancel = false;
|
||||
if (stlFn) {
|
||||
stlFn(i, facets_num, cb_cancel, model_id);
|
||||
if (cb_cancel)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
stl_facet facet;
|
||||
|
||||
if (stl->stats.type == binary) {
|
||||
|
||||
|
||||
// Read a single facet from a binary .STL file. We assume little-endian architecture!
|
||||
if (fread(&facet, 1, SIZEOF_STL_FACET, fp) != SIZEOF_STL_FACET)
|
||||
return false;
|
||||
|
||||
|
||||
#if BOOST_ENDIAN_BIG_BYTE
|
||||
// Convert the loaded little endian data to big endian.
|
||||
stl_internal_reverse_quads((char*)&facet, 48);
|
||||
|
|
@ -237,11 +273,21 @@ static bool stl_read(stl_file *stl, FILE *fp, int first_facet, bool first, Impor
|
|||
}
|
||||
#endif
|
||||
|
||||
// Write the facet into memory.
|
||||
// Write the facet into memory if none of facet vertices is NAN.
|
||||
bool someone_is_nan = false;
|
||||
for (size_t j = 0; j < 3; ++j) {
|
||||
if (isnan(facet.vertex[j](0)) || isnan(facet.vertex[j](1)) || isnan(facet.vertex[j](2))) {
|
||||
someone_is_nan = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(someone_is_nan)
|
||||
continue;
|
||||
|
||||
stl->facet_start[i] = facet;
|
||||
stl_facet_stats(stl, facet, first);
|
||||
}
|
||||
|
||||
|
||||
stl->stats.size = stl->stats.max - stl->stats.min;
|
||||
stl->stats.bounding_diameter = stl->stats.size.norm();
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -172,6 +172,7 @@ namespace ImGui
|
|||
const wchar_t UnfoldButtonIcon = 0x0815;
|
||||
const wchar_t SphereButtonIcon = 0x0816;
|
||||
const wchar_t GapFillIcon = 0x0817;
|
||||
const wchar_t ConfirmIcon = 0x0818;
|
||||
|
||||
const wchar_t MinimalizeDarkButton = 0x081C;
|
||||
const wchar_t MinimalizeHoverDarkButton = 0x081D;
|
||||
|
|
@ -186,6 +187,7 @@ namespace ImGui
|
|||
const wchar_t HeightRangeDarkIcon = 0x0825;
|
||||
const wchar_t SphereButtonDarkIcon = 0x0826;
|
||||
const wchar_t GapFillDarkIcon = 0x0827;
|
||||
const wchar_t ConfirmDarkIcon = 0x0828;
|
||||
|
||||
const wchar_t TextSearchIcon = 0x0828;
|
||||
const wchar_t TextSearchCloseIcon = 0x0829;
|
||||
|
|
@ -199,6 +201,15 @@ namespace ImGui
|
|||
const wchar_t BlockNotifErrorIcon = 0x0835;
|
||||
const wchar_t ClipboardBtnDarkIcon = 0x0836;
|
||||
|
||||
const wchar_t PrevArrowBtnIcon = 0x0836;
|
||||
const wchar_t PrevArrowHoverBtnIcon = 0x0837;
|
||||
const wchar_t NextArrowBtnIcon = 0x0838;
|
||||
const wchar_t NextArrowHoverBtnIcon = 0x0839;
|
||||
const wchar_t OpenArrowIcon = 0x0840;
|
||||
const wchar_t CollapseArrowIcon = 0x0841;
|
||||
const wchar_t ExpandArrowIcon = 0x0842;
|
||||
const wchar_t CompleteIcon = 0x0843;
|
||||
|
||||
// void MyFunction(const char* name, const MyMatrix44& v);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ Index of this file:
|
|||
#include "imgui_internal.h"
|
||||
|
||||
#include <locale.h>
|
||||
|
||||
#include <algorithm>
|
||||
// System includes
|
||||
#include <ctype.h> // toupper
|
||||
#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
|
||||
|
|
@ -3070,6 +3070,9 @@ bool ImGui::BBLDragFloat(const char *label, float *v, float v_speed, float v_min
|
|||
ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, ImVec4(0.00f, 0.59f, 0.53f, 0.00f));
|
||||
ImGui::PushStyleColor(ImGuiCol_FrameBgActive, ImVec4(0.00f, 0.59f, 0.53f, 0.00f));
|
||||
bool bbl_drag_scalar = BBLDragScalar(label, ImGuiDataType_Float, v, v_speed, &v_min, &v_max, format, flags);
|
||||
if (v_max > v_min + 0.001) {
|
||||
*v = std::clamp(*v, v_min, v_max);
|
||||
}
|
||||
ImGui::PopStyleColor(3);
|
||||
return bbl_drag_scalar;
|
||||
}
|
||||
|
|
|
|||
157
src/libslic3r/AStar.hpp
Normal file
157
src/libslic3r/AStar.hpp
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
#ifndef ASTAR_HPP
|
||||
#define ASTAR_HPP
|
||||
|
||||
#include <cmath> // std::isinf() is here
|
||||
#include <unordered_map>
|
||||
|
||||
#include "libslic3r/MutablePriorityQueue.hpp"
|
||||
|
||||
namespace Slic3r { namespace astar {
|
||||
|
||||
// Borrowed from C++20
|
||||
template<class T> using remove_cvref_t = std::remove_cv_t<std::remove_reference_t<T>>;
|
||||
|
||||
// Input interface for the Astar algorithm. Specialize this struct for a
|
||||
// particular type and implement all the 4 methods and specify the Node type
|
||||
// to register the new type for the astar implementation.
|
||||
template<class T> struct TracerTraits_
|
||||
{
|
||||
// The type of a node used by this tracer. Usually a point in space.
|
||||
using Node = typename T::Node;
|
||||
|
||||
// Call fn for every new node reachable from node 'src'. fn should have the
|
||||
// candidate node as its only argument.
|
||||
template<class Fn> static void foreach_reachable(const T &tracer, const Node &src, Fn &&fn) { tracer.foreach_reachable(src, fn); }
|
||||
|
||||
// Get the distance from node 'a' to node 'b'. This is sometimes referred
|
||||
// to as the g value of a node in AStar context.
|
||||
static float distance(const T &tracer, const Node &a, const Node &b) { return tracer.distance(a, b); }
|
||||
|
||||
// Get the estimated distance heuristic from node 'n' to the destination.
|
||||
// This is referred to as the h value in AStar context.
|
||||
// If node 'n' is the goal, this function should return a negative value.
|
||||
// Note that this heuristic should be admissible (never bigger than the real
|
||||
// cost) in order for Astar to work.
|
||||
static float goal_heuristic(const T &tracer, const Node &n) { return tracer.goal_heuristic(n); }
|
||||
|
||||
// Return a unique identifier (hash) for node 'n'.
|
||||
static size_t unique_id(const T &tracer, const Node &n) { return tracer.unique_id(n); }
|
||||
};
|
||||
|
||||
// Helper definition to get the node type of a tracer
|
||||
template<class T> using TracerNodeT = typename TracerTraits_<remove_cvref_t<T>>::Node;
|
||||
|
||||
constexpr auto Unassigned = std::numeric_limits<size_t>::max();
|
||||
|
||||
template<class Tracer> struct QNode // Queue node. Keeps track of scores g, and h
|
||||
{
|
||||
TracerNodeT<Tracer> node; // The actual node itself
|
||||
size_t queue_id; // Position in the open queue or Unassigned if closed
|
||||
size_t parent; // unique id of the parent or Unassigned
|
||||
|
||||
float g, h;
|
||||
float f() const { return g + h; }
|
||||
|
||||
QNode(TracerNodeT<Tracer> n = {}, size_t p = Unassigned, float gval = std::numeric_limits<float>::infinity(), float hval = 0.f)
|
||||
: node{std::move(n)}, parent{p}, queue_id{InvalidQueueID}, g{gval}, h{hval}
|
||||
{}
|
||||
};
|
||||
|
||||
// Run the AStar algorithm on a tracer implementation.
|
||||
// The 'tracer' argument encapsulates the domain (grid, point cloud, etc...)
|
||||
// The 'source' argument is the starting node.
|
||||
// The 'out' argument is the output iterator into which the output nodes are
|
||||
// written. For performance reasons, the order is reverse, from the destination
|
||||
// to the source -- (destination included, source is not).
|
||||
// The 'cached_nodes' argument is an optional associative container to hold a
|
||||
// QNode entry for each visited node. Any compatible container can be used
|
||||
// (like std::map or maps with different allocators, even a sufficiently large
|
||||
// std::vector).
|
||||
//
|
||||
// Note that no destination node is given in the signature. The tracer's
|
||||
// goal_heuristic() method should return a negative value if a node is a
|
||||
// destination node.
|
||||
template<class Tracer, class It, class NodeMap = std::unordered_map<size_t, QNode<Tracer>>>
|
||||
bool search_route(const Tracer &tracer, const TracerNodeT<Tracer> &source, It out, NodeMap &&cached_nodes = {})
|
||||
{
|
||||
using Node = TracerNodeT<Tracer>;
|
||||
using QNode = QNode<Tracer>;
|
||||
using TracerTraits = TracerTraits_<remove_cvref_t<Tracer>>;
|
||||
|
||||
struct LessPred
|
||||
{ // Comparison functor needed by the priority queue
|
||||
NodeMap &m;
|
||||
bool operator()(size_t node_a, size_t node_b) { return m[node_a].f() < m[node_b].f(); }
|
||||
};
|
||||
|
||||
auto qopen = make_mutable_priority_queue<size_t, true>([&cached_nodes](size_t el, size_t qidx) { cached_nodes[el].queue_id = qidx; }, LessPred{cached_nodes});
|
||||
|
||||
QNode initial{source, /*parent = */ Unassigned, /*g = */ 0.f};
|
||||
size_t source_id = TracerTraits::unique_id(tracer, source);
|
||||
cached_nodes[source_id] = initial;
|
||||
qopen.push(source_id);
|
||||
|
||||
size_t goal_id = TracerTraits::goal_heuristic(tracer, source) < 0.f ? source_id : Unassigned;
|
||||
|
||||
while (goal_id == Unassigned && !qopen.empty()) {
|
||||
size_t q_id = qopen.top();
|
||||
qopen.pop();
|
||||
QNode &q = cached_nodes[q_id];
|
||||
|
||||
// This should absolutely be initialized in the cache already
|
||||
assert(!std::isinf(q.g));
|
||||
|
||||
TracerTraits::foreach_reachable(tracer, q.node, [&](const Node &succ_nd) {
|
||||
if (goal_id != Unassigned) return true;
|
||||
|
||||
float h = TracerTraits::goal_heuristic(tracer, succ_nd);
|
||||
float dst = TracerTraits::distance(tracer, q.node, succ_nd);
|
||||
size_t succ_id = TracerTraits::unique_id(tracer, succ_nd);
|
||||
QNode qsucc_nd{succ_nd, q_id, q.g + dst, h};
|
||||
|
||||
if (h < 0.f) {
|
||||
goal_id = succ_id;
|
||||
cached_nodes[succ_id] = qsucc_nd;
|
||||
} else {
|
||||
// If succ_id is not in cache, it gets created with g = infinity
|
||||
QNode &prev_nd = cached_nodes[succ_id];
|
||||
|
||||
if (qsucc_nd.g < prev_nd.g) {
|
||||
// new route is better, apply it:
|
||||
|
||||
// Save the old queue id, it would be lost after the next line
|
||||
size_t queue_id = prev_nd.queue_id;
|
||||
|
||||
// The cache needs to be updated either way
|
||||
prev_nd = qsucc_nd;
|
||||
|
||||
if (queue_id == InvalidQueueID)
|
||||
// was in closed or unqueued, rescheduling
|
||||
qopen.push(succ_id);
|
||||
else // was in open, updating
|
||||
qopen.update(queue_id);
|
||||
}
|
||||
}
|
||||
|
||||
return goal_id != Unassigned;
|
||||
});
|
||||
}
|
||||
|
||||
// Write the output, do not reverse. Clients can do so if they need to.
|
||||
if (goal_id != Unassigned) {
|
||||
const QNode *q = &cached_nodes[goal_id];
|
||||
while (q->parent != Unassigned) {
|
||||
assert(!std::isinf(q->g)); // Uninitialized nodes are NOT allowed
|
||||
|
||||
*out = q->node;
|
||||
++out;
|
||||
q = &cached_nodes[q->parent];
|
||||
}
|
||||
}
|
||||
|
||||
return goal_id != Unassigned;
|
||||
}
|
||||
|
||||
}} // namespace Slic3r::astar
|
||||
|
||||
#endif // ASTAR_HPP
|
||||
|
|
@ -255,6 +255,10 @@ void AppConfig::set_defaults()
|
|||
if (get("show_daily_tips").empty()) {
|
||||
set_bool("show_daily_tips", true);
|
||||
}
|
||||
//true is auto calculate
|
||||
if (get("auto_calculate").empty()) {
|
||||
set_bool("auto_calculate", true);
|
||||
}
|
||||
|
||||
if (get("show_home_page").empty()) {
|
||||
set_bool("show_home_page", true);
|
||||
|
|
@ -998,7 +1002,7 @@ void AppConfig::set_vendors(const AppConfig &from)
|
|||
m_dirty = true;
|
||||
}
|
||||
|
||||
void AppConfig::save_printer_cali_infos(const PrinterCaliInfo &cali_info)
|
||||
void AppConfig::save_printer_cali_infos(const PrinterCaliInfo &cali_info, bool need_change_status)
|
||||
{
|
||||
auto iter = std::find_if(m_printer_cali_infos.begin(), m_printer_cali_infos.end(), [&cali_info](const PrinterCaliInfo &cali_info_item) {
|
||||
return cali_info_item.dev_id == cali_info.dev_id;
|
||||
|
|
@ -1007,7 +1011,9 @@ void AppConfig::save_printer_cali_infos(const PrinterCaliInfo &cali_info)
|
|||
if (iter == m_printer_cali_infos.end()) {
|
||||
m_printer_cali_infos.emplace_back(cali_info);
|
||||
} else {
|
||||
(*iter).cali_finished = cali_info.cali_finished;
|
||||
if (need_change_status) {
|
||||
(*iter).cali_finished = cali_info.cali_finished;
|
||||
}
|
||||
(*iter).cache_flow_ratio = cali_info.cache_flow_ratio;
|
||||
(*iter).selected_presets = cali_info.selected_presets;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -209,7 +209,7 @@ public:
|
|||
}
|
||||
|
||||
const std::vector<PrinterCaliInfo> &get_printer_cali_infos() const { return m_printer_cali_infos; }
|
||||
void save_printer_cali_infos(const PrinterCaliInfo& cali_info);
|
||||
void save_printer_cali_infos(const PrinterCaliInfo& cali_info, bool need_change_status = true);
|
||||
|
||||
// return recent/last_opened_folder or recent/settings_folder or empty string.
|
||||
std::string get_last_dir() const;
|
||||
|
|
|
|||
|
|
@ -228,16 +228,23 @@ void update_selected_items_axis_align(ArrangePolygons& selected, const DynamicPr
|
|||
double c = m02 / m00 - cy * cy;
|
||||
|
||||
//if a and c are close, there is no dominant axis, then do not rotate
|
||||
if (std::abs(a) < 1.5*std::abs(c) && std::abs(c) < 1.5*std::abs(a)) {
|
||||
// ratio is always no more than 1
|
||||
double ratio = std::abs(a) > std::abs(c) ? std::abs(c / a) :
|
||||
std::abs(c) > 0 ? std::abs(a / c) : 0;
|
||||
if (ratio>0.66) {
|
||||
validResult = false;
|
||||
}
|
||||
else {
|
||||
angle = std::atan2(2 * b, (a - c)) / 2;
|
||||
angle = PI / 2 - angle;
|
||||
// if the angle is close to PI or -PI, it means the object is vertical, then do not rotate
|
||||
if (std::abs(std::abs(angle) - PI) < 0.01)
|
||||
angle = 0;
|
||||
validResult = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (validResult) { ap.rotation += (PI / 2 - angle); }
|
||||
if (validResult) { ap.rotation += angle; }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -406,6 +413,18 @@ protected:
|
|||
return bindist;
|
||||
}
|
||||
|
||||
double dist_to_bin(const Box& ibb, const ClipperLib::IntPoint& origin_pack, typename Packer::PlacementConfig::Alignment starting_point_alignment)
|
||||
{
|
||||
double bindist = 0;
|
||||
if (starting_point_alignment == PConfig::Alignment::BOTTOM_LEFT)
|
||||
bindist = norm(pl::distance(ibb.minCorner(), origin_pack));
|
||||
else if (starting_point_alignment == PConfig::Alignment::TOP_RIGHT)
|
||||
bindist = norm(pl::distance(ibb.maxCorner(), origin_pack));
|
||||
else
|
||||
bindist = norm(pl::distance(ibb.center(), origin_pack));
|
||||
return bindist;
|
||||
}
|
||||
|
||||
// This is "the" object function which is evaluated many times for each
|
||||
// vertex (decimated with the accuracy parameter) of each object.
|
||||
// Therefore it is upmost crucial for this function to be as efficient
|
||||
|
|
@ -488,7 +507,7 @@ protected:
|
|||
score = 0.2 * dist + 0.8 * bindist;
|
||||
}
|
||||
else {
|
||||
double bindist = norm(pl::distance(ibb.center(), origin_pack));
|
||||
double bindist = dist_to_bin(ibb, origin_pack, m_pconf.starting_point);
|
||||
dist = 0.8 * dist + 0.2 * bindist;
|
||||
|
||||
|
||||
|
|
@ -520,11 +539,13 @@ protected:
|
|||
auto ascore = 1.0 - (item.area() + parea) / bbarea;
|
||||
|
||||
if (ascore < alignment_score) alignment_score = ascore;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
density = std::sqrt(norm(fullbb.width()) * norm(fullbb.height()));
|
||||
double R = double(m_remaining.size()) / m_item_count;
|
||||
// alighment score is more important for rectangle items
|
||||
double alignment_weight = std::max(0.3, 0.6 * item.area() / ibb.area());
|
||||
|
||||
// The final mix of the score is the balance between the
|
||||
// distance from the full pile center, the pack density and
|
||||
|
|
@ -533,8 +554,8 @@ protected:
|
|||
score = 0.50 * dist + 0.50 * density;
|
||||
else
|
||||
// Let the density matter more when fewer objects remain
|
||||
score = 0.50 * dist + (1.0 - R) * 0.20 * density +
|
||||
0.30 * alignment_score;
|
||||
score = (1 - 0.2 - alignment_weight) * dist + (1.0 - R) * 0.20 * density +
|
||||
alignment_weight * alignment_score;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -814,7 +835,8 @@ public:
|
|||
|
||||
template<> std::function<double(const Item&, const ItemGroup&)> AutoArranger<Box>::get_objfn()
|
||||
{
|
||||
auto origin_pack = m_pconf.starting_point == PConfig::Alignment::CENTER ? m_bin.center() : m_bin.minCorner();
|
||||
auto origin_pack = m_pconf.starting_point == PConfig::Alignment::CENTER ? m_bin.center() :
|
||||
m_pconf.starting_point == PConfig::Alignment::TOP_RIGHT ? m_bin.maxCorner() : m_bin.minCorner();
|
||||
|
||||
return [this, origin_pack](const Item &itm, const ItemGroup&) {
|
||||
auto result = objfunc(itm, origin_pack);
|
||||
|
|
|
|||
|
|
@ -419,4 +419,15 @@ std::string_view BuildVolume::type_name(BuildVolume_Type type)
|
|||
return {};
|
||||
}
|
||||
|
||||
indexed_triangle_set BuildVolume::bounding_mesh(bool scale) const
|
||||
{
|
||||
auto max_pt3 = m_bboxf.max;
|
||||
if (scale) {
|
||||
return its_make_cube(scale_(max_pt3.x()), scale_(max_pt3.y()), scale_(max_pt3.z()));
|
||||
}
|
||||
else {
|
||||
return its_make_cube(max_pt3.x(), max_pt3.y(), max_pt3.z());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ public:
|
|||
// Bounding volume of printable_area(), printable_height(), unscaled.
|
||||
const BoundingBoxf3& bounding_volume() const { return m_bboxf; }
|
||||
BoundingBoxf bounding_volume2d() const { return { to_2d(m_bboxf.min), to_2d(m_bboxf.max) }; }
|
||||
indexed_triangle_set bounding_mesh(bool scale=true) const;
|
||||
|
||||
// Center of the print bed, unscaled.
|
||||
Vec2d bed_center() const { return to_2d(m_bboxf.center()); }
|
||||
|
|
|
|||
|
|
@ -304,7 +304,7 @@ set(lisbslic3r_sources
|
|||
PrincipalComponents2D.hpp
|
||||
SupportSpotsGenerator.cpp
|
||||
SupportSpotsGenerator.hpp
|
||||
TreeSupport.hpp
|
||||
TreeSupport.hpp
|
||||
TreeSupport.cpp
|
||||
MinimumSpanningTree.hpp
|
||||
MinimumSpanningTree.cpp
|
||||
|
|
|
|||
|
|
@ -308,6 +308,7 @@ ConfigOption* ConfigOptionDef::create_default_option() const
|
|||
opt->keys_map = this->enum_keys_map;
|
||||
return opt;
|
||||
}
|
||||
delete dft;
|
||||
}
|
||||
|
||||
return this->default_value->clone();
|
||||
|
|
@ -782,6 +783,8 @@ int ConfigBase::load_from_json(const std::string &file, ConfigSubstitutionContex
|
|||
json j;
|
||||
std::list<std::string> different_settings_append;
|
||||
std::string new_support_style;
|
||||
std::string is_infill_first;
|
||||
std::string get_wall_sequence;
|
||||
bool is_project_settings = false;
|
||||
|
||||
CNumericLocalesSetter locales_setter;
|
||||
|
|
@ -845,6 +848,16 @@ int ConfigBase::load_from_json(const std::string &file, ConfigSubstitutionContex
|
|||
different_settings_append.push_back("support_style");
|
||||
new_support_style = "tree_hybrid";
|
||||
}
|
||||
} else if (opt_key == "wall_infill_order") {
|
||||
//BBS: check wall_infill order to decide if it be different and append to diff_setting_append
|
||||
if (it.value() == "outer wall/inner wall/infill" || it.value() == "infill/outer wall/inner wall" || it.value() == "inner-outer-inner wall/infill") {
|
||||
get_wall_sequence = "wall_seq_diff_to_system";
|
||||
}
|
||||
|
||||
if (it.value() == "infill/outer wall/inner wall" || it.value() == "infill/inner wall/outer wall") {
|
||||
different_settings_append.push_back("is_infill_first");
|
||||
is_infill_first = "true";
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (it.value().is_array()) {
|
||||
|
|
@ -916,6 +929,12 @@ int ConfigBase::load_from_json(const std::string &file, ConfigSubstitutionContex
|
|||
ConfigOptionEnum<SupportMaterialStyle>* opt = this->option<ConfigOptionEnum<SupportMaterialStyle>>("support_style", true);
|
||||
opt->value = smsTreeHybrid;
|
||||
}
|
||||
|
||||
if (!is_infill_first.empty()) {
|
||||
ConfigOptionBool *opt = this->option<ConfigOptionBool>("is_infill_first", true);
|
||||
opt->value = true;
|
||||
}
|
||||
|
||||
if (is_project_settings) {
|
||||
std::vector<std::string>& different_settings = this->option<ConfigOptionStrings>("different_settings_to_system", true)->values;
|
||||
size_t size = different_settings.size();
|
||||
|
|
@ -932,6 +951,25 @@ int ConfigBase::load_from_json(const std::string &file, ConfigSubstitutionContex
|
|||
is_first[index] = true;
|
||||
}
|
||||
else {
|
||||
// remove unneeded key
|
||||
if (get_wall_sequence.empty()) {
|
||||
std::string wall_sqe_string = "wall_sequence";
|
||||
int pos=different_settings[index].find(wall_sqe_string);
|
||||
|
||||
if (pos != different_settings[index].npos) {
|
||||
int erase_len = wall_sqe_string.size();
|
||||
if (pos + erase_len < different_settings[index].size() && different_settings[index][pos + erase_len] == ';')
|
||||
erase_len++;
|
||||
different_settings[index].erase(pos, erase_len);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (different_settings[index].empty()) {
|
||||
is_first[index] = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
Slic3r::unescape_strings_cstyle(different_settings[index], original_diffs[index]);
|
||||
}
|
||||
}
|
||||
|
|
@ -945,6 +983,8 @@ int ConfigBase::load_from_json(const std::string &file, ConfigSubstitutionContex
|
|||
index = 0;
|
||||
else if (diff_key == "support_style")
|
||||
index = 0;
|
||||
else if (diff_key == "is_infill_first")
|
||||
index = 0;
|
||||
|
||||
//check whether exist firstly
|
||||
if (!original_diffs[index].empty()) {
|
||||
|
|
|
|||
|
|
@ -445,6 +445,11 @@ const ModelObjectPtrs& Cut::perform_by_contour(std::vector<Part> parts, int dowe
|
|||
ModelObject* lower{ nullptr };
|
||||
if (m_attributes.has(ModelObjectCutAttribute::KeepLower)) cut_mo->clone_for_cut(&lower);
|
||||
|
||||
if (upper && lower) {
|
||||
upper->name = upper->name + "_A";
|
||||
lower->name = lower->name + "_B";
|
||||
}
|
||||
|
||||
const size_t cut_parts_cnt = parts.size();
|
||||
bool has_modifiers = false;
|
||||
|
||||
|
|
@ -527,6 +532,10 @@ const ModelObjectPtrs& Cut::perform_with_groove(const Groove& groove, const Tran
|
|||
ModelObject* lower{ nullptr };
|
||||
cut_mo->clone_for_cut(&lower);
|
||||
|
||||
if (upper && lower) {
|
||||
upper->name = upper->name + "_A";
|
||||
lower->name = lower->name + "_B";
|
||||
}
|
||||
const double groove_half_depth = 0.5 * double(groove.depth);
|
||||
|
||||
Model tmp_model_for_cut = Model();
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ ExtrusionEntityCollection::ExtrusionEntityCollection(const ExtrusionPaths &paths
|
|||
|
||||
ExtrusionEntityCollection& ExtrusionEntityCollection::operator=(const ExtrusionEntityCollection &other)
|
||||
{
|
||||
clear();
|
||||
this->entities = other.entities;
|
||||
for (size_t i = 0; i < this->entities.size(); ++i)
|
||||
this->entities[i] = this->entities[i]->clone();
|
||||
|
|
|
|||
|
|
@ -1095,7 +1095,7 @@ void Layer::make_ironing()
|
|||
|
||||
// Create the filler object.
|
||||
f->spacing = ironing_params.line_spacing;
|
||||
f->angle = float(ironing_params.angle + 0.25 * M_PI);
|
||||
f->angle = float(ironing_params.angle);
|
||||
f->link_max_length = (coord_t) scale_(3. * f->spacing);
|
||||
double extrusion_height = ironing_params.height * f->spacing / nozzle_dmr;
|
||||
float extrusion_width = Flow::rounded_rectangle_extrusion_width_from_spacing(float(nozzle_dmr), float(extrusion_height));
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ namespace Slic3r {
|
|||
bool load_stl(const char *path, Model *model, const char *object_name_in, ImportstlProgressFn stlFn)
|
||||
{
|
||||
TriangleMesh mesh;
|
||||
std::string design_id;
|
||||
|
||||
if (! mesh.ReadSTLFile(path, true, stlFn)) {
|
||||
// die "Failed to open $file\n" if !-e $path;
|
||||
return false;
|
||||
|
|
@ -59,4 +61,4 @@ bool store_stl(const char *path, Model *model, bool binary)
|
|||
return store_stl(path, &mesh, binary);
|
||||
}
|
||||
|
||||
}; // namespace Slic3r
|
||||
}; // namespace Slic3r
|
||||
|
|
@ -276,6 +276,7 @@ static constexpr const char* LOCK_ATTR = "locked";
|
|||
static constexpr const char* BED_TYPE_ATTR = "bed_type";
|
||||
static constexpr const char* PRINT_SEQUENCE_ATTR = "print_sequence";
|
||||
static constexpr const char* FIRST_LAYER_PRINT_SEQUENCE_ATTR = "first_layer_print_sequence";
|
||||
static constexpr const char* SPIRAL_VASE_MODE = "spiral_mode";
|
||||
static constexpr const char* GCODE_FILE_ATTR = "gcode_file";
|
||||
static constexpr const char* THUMBNAIL_FILE_ATTR = "thumbnail_file";
|
||||
static constexpr const char* TOP_FILE_ATTR = "top_file";
|
||||
|
|
@ -288,6 +289,8 @@ static constexpr const char* IDENTIFYID_ATTR = "identify_id";
|
|||
static constexpr const char* PLATERID_ATTR = "plater_id";
|
||||
static constexpr const char* PLATER_NAME_ATTR = "plater_name";
|
||||
static constexpr const char* PLATE_IDX_ATTR = "index";
|
||||
static constexpr const char* PRINTER_MODEL_ID_ATTR = "printer_model_id";
|
||||
static constexpr const char* NOZZLE_DIAMETERS_ATTR = "nozzle_diameters";
|
||||
static constexpr const char* SLICE_PREDICTION_ATTR = "prediction";
|
||||
static constexpr const char* SLICE_WEIGHT_ATTR = "weight";
|
||||
static constexpr const char* TIMELAPSE_TYPE_ATTR = "timelapse_type";
|
||||
|
|
@ -1282,9 +1285,9 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
// BBS: load relationships
|
||||
if (!_extract_xml_from_archive(archive, RELATIONSHIPS_FILE, _handle_start_relationships_element, _handle_end_relationships_element))
|
||||
return false;
|
||||
if (m_thumbnail_small.empty()) m_thumbnail_small = m_thumbnail_path;
|
||||
if (!m_thumbnail_small.empty()) {
|
||||
return _extract_from_archive(archive, m_thumbnail_small, [&data](auto &archive, auto const &stat) -> bool {
|
||||
if (m_thumbnail_middle.empty()) m_thumbnail_middle = m_thumbnail_path;
|
||||
if (!m_thumbnail_middle.empty()) {
|
||||
return _extract_from_archive(archive, m_thumbnail_middle, [&data](auto &archive, auto const &stat) -> bool {
|
||||
data.resize(stat.m_uncomp_size);
|
||||
return mz_zip_reader_extract_to_mem(&archive, stat.m_file_index, data.data(), data.size(), 0);
|
||||
});
|
||||
|
|
@ -1368,7 +1371,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
m_thumbnail_small.erase(m_thumbnail_small.begin());
|
||||
if (!m_thumbnail_middle.empty() && m_thumbnail_middle.front() == '/')
|
||||
m_thumbnail_middle.erase(m_thumbnail_middle.begin());
|
||||
m_model->model_info->metadata_items.emplace("Thumbnail", m_thumbnail_small);
|
||||
m_model->model_info->metadata_items.emplace("Thumbnail", m_thumbnail_middle);
|
||||
m_model->model_info->metadata_items.emplace("Poster", m_thumbnail_middle);
|
||||
|
||||
// we then loop again the entries to read other files stored in the archive
|
||||
|
|
@ -3900,6 +3903,11 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
};
|
||||
m_curr_plater->config.set_key_value("first_layer_print_sequence", new ConfigOptionInts(get_vector_from_string(value)));
|
||||
}
|
||||
else if (key == SPIRAL_VASE_MODE) {
|
||||
bool spiral_mode = false;
|
||||
std::istringstream(value) >> std::boolalpha >> spiral_mode;
|
||||
m_curr_plater->config.set_key_value("spiral_mode", new ConfigOptionBool(spiral_mode));
|
||||
}
|
||||
else if (key == GCODE_FILE_ATTR)
|
||||
{
|
||||
m_curr_plater->gcode_file = value;
|
||||
|
|
@ -5375,7 +5383,8 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
~close_lock() {
|
||||
if (filename) {
|
||||
close_zip_writer(&archive);
|
||||
boost::filesystem::remove(*filename);
|
||||
boost::system::error_code ec;
|
||||
boost::filesystem::remove(*filename, ec);
|
||||
}
|
||||
}
|
||||
} lock{archive, &filepath_tmp};
|
||||
|
|
@ -5439,8 +5448,10 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
std::string const * filename;
|
||||
~close_lock() {
|
||||
close_zip_writer(&archive);
|
||||
if (filename)
|
||||
boost::filesystem::remove(*filename);
|
||||
if (filename) {
|
||||
boost::system::error_code ec;
|
||||
boost::filesystem::remove(*filename, ec);
|
||||
}
|
||||
}
|
||||
} lock{ archive, &filename};
|
||||
|
||||
|
|
@ -5588,7 +5599,6 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
{
|
||||
if (!_add_calibration_file_to_archive(archive, *calibration_data[index], index)) {
|
||||
close_zip_writer(&archive);
|
||||
boost::filesystem::remove(filename);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -5604,7 +5614,6 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
if (id_bboxes[index]->is_valid()) {
|
||||
if (!_add_bbox_file_to_archive(archive, *id_bboxes[index], index)) {
|
||||
close_zip_writer(&archive);
|
||||
boost::filesystem::remove(filename);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -5631,7 +5640,6 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
// The index differes from the index of an object ID of an object instance of a 3MF file!
|
||||
if (!_add_layer_height_profile_file_to_archive(archive, model)) {
|
||||
close_zip_writer(&archive);
|
||||
boost::filesystem::remove(filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -5648,7 +5656,6 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
// The index differes from the index of an object ID of an object instance of a 3MF file!
|
||||
if (!_add_layer_config_ranges_file_to_archive(archive, model)) {
|
||||
close_zip_writer(&archive);
|
||||
boost::filesystem::remove(filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -6417,7 +6424,8 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
stream << " <" << COMPONENT_TAG << " objectid=\"" << volume_id;
|
||||
else
|
||||
stream << " <" << COMPONENT_TAG << " p:path=\"" << xml_escape(*ppath) << "\" objectid=\"" << volume_id; // << "\"/>\n";
|
||||
stream << "\" " << PUUID_ATTR << "=\"" << hex_wrap<boost::uint32_t>{(boost::uint32_t) object_data.backup_id} << COMPONENT_UUID_SUFFIX;
|
||||
if (m_production_ext)
|
||||
stream << "\" " << PUUID_ATTR << "=\"" << hex_wrap<boost::uint32_t>{(boost::uint32_t) (index + (object_data.backup_id << 16))} << COMPONENT_UUID_SUFFIX;
|
||||
const Transform3d &transf = volume->get_matrix();
|
||||
stream << "\" " << TRANSFORM_ATTR << "=\"";
|
||||
for (unsigned c = 0; c < 4; ++c) {
|
||||
|
|
@ -6515,7 +6523,8 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
char buf[256];
|
||||
unsigned int vertices_count = 0;
|
||||
//unsigned int triangles_count = 0;
|
||||
for (ModelVolume* volume : object.volumes) {
|
||||
for (unsigned int index = 0; index < object.volumes.size(); index++) {
|
||||
ModelVolume *volume = object.volumes[index];
|
||||
if (volume == nullptr)
|
||||
continue;
|
||||
|
||||
|
|
@ -6542,7 +6551,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
if (m_production_ext) {
|
||||
std::stringstream stream;
|
||||
reset_stream(stream);
|
||||
stream << "\" " << PUUID_ATTR << "=\"" << hex_wrap<boost::uint32_t>{(boost::uint32_t) object_data.backup_id} << SUB_OBJECT_UUID_SUFFIX;
|
||||
stream << "\" " << PUUID_ATTR << "=\"" << hex_wrap<boost::uint32_t>{(boost::uint32_t) (index + (object_data.backup_id << 16))} << SUB_OBJECT_UUID_SUFFIX;
|
||||
//output_buffer += "\" ";
|
||||
//output_buffer += PUUID_ATTR;
|
||||
//output_buffer += "=\"";
|
||||
|
|
@ -7218,6 +7227,10 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
stream << "\"/>\n";
|
||||
}
|
||||
|
||||
ConfigOption* spiral_mode_opt = plate_data->config.option("spiral_mode");
|
||||
if (spiral_mode_opt)
|
||||
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << SPIRAL_VASE_MODE << "\" " << VALUE_ATTR << "=\"" << spiral_mode_opt->getBool() << "\"/>\n";
|
||||
|
||||
if (save_gcode)
|
||||
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << GCODE_FILE_ATTR << "\" " << VALUE_ATTR << "=\"" << std::boolalpha << xml_escape(plate_data->gcode_file) << "\"/>\n";
|
||||
if (!plate_data->gcode_file.empty()) {
|
||||
|
|
@ -7371,6 +7384,8 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
break;
|
||||
}
|
||||
}
|
||||
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << PRINTER_MODEL_ID_ATTR << "\" " << VALUE_ATTR << "=\"" << plate_data->printer_model_id << "\"/>\n";
|
||||
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << NOZZLE_DIAMETERS_ATTR << "\" " << VALUE_ATTR << "=\"" << plate_data->nozzle_diameters << "\"/>\n";
|
||||
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << TIMELAPSE_TYPE_ATTR << "\" " << VALUE_ATTR << "=\"" << timelapse_type << "\"/>\n";
|
||||
//stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << TIMELAPSE_ERROR_CODE_ATTR << "\" " << VALUE_ATTR << "=\"" << plate_data->timelapse_warning_code << "\"/>\n";
|
||||
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << SLICE_PREDICTION_ATTR << "\" " << VALUE_ATTR << "=\"" << plate_data->get_gcode_prediction_str() << "\"/>\n";
|
||||
|
|
@ -7714,10 +7729,12 @@ public:
|
|||
|
||||
void set_interval(long n) {
|
||||
boost::lock_guard lock(m_mutex);
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " entry, and last interval is: " << m_interval;
|
||||
m_next_backup -= boost::posix_time::seconds(m_interval);
|
||||
m_interval = n;
|
||||
m_next_backup += boost::posix_time::seconds(m_interval);
|
||||
m_cond.notify_all();
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " exit, and new interval is: " << m_interval;
|
||||
}
|
||||
|
||||
void put_other_changes()
|
||||
|
|
@ -7795,6 +7812,7 @@ private:
|
|||
};
|
||||
private:
|
||||
_BBS_Backup_Manager() {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " inital and interval = " << m_interval;
|
||||
m_next_backup = boost::get_system_time() + boost::posix_time::seconds(m_interval);
|
||||
boost::unique_lock lock(m_mutex);
|
||||
m_thread = std::move(boost::thread(boost::ref(*this)));
|
||||
|
|
@ -7823,7 +7841,7 @@ private:
|
|||
}
|
||||
|
||||
void process_ui_task(Task& t, bool canceled = false) {
|
||||
BOOST_LOG_TRIVIAL(info) << "process_ui_task" << t.to_string();
|
||||
BOOST_LOG_TRIVIAL(info) << "process_ui_task" << t.to_string() << " and interval = " << m_interval;
|
||||
switch (t.type) {
|
||||
case Backup: {
|
||||
if (canceled)
|
||||
|
|
@ -7867,7 +7885,7 @@ private:
|
|||
}
|
||||
|
||||
void process_task(Task& t) {
|
||||
BOOST_LOG_TRIVIAL(info) << "process_task" << t.to_string();
|
||||
BOOST_LOG_TRIVIAL(info) << "process_task" << t.to_string() << " and interval = " << m_interval;
|
||||
switch (t.type) {
|
||||
case Backup:
|
||||
// do it in response
|
||||
|
|
@ -7882,13 +7900,15 @@ private:
|
|||
break;
|
||||
}
|
||||
case RemoveObject: {
|
||||
boost::filesystem::remove(t.path + "/mesh_" + boost::lexical_cast<std::string>(t.id) + ".xml");
|
||||
boost::system::error_code ec;
|
||||
boost::filesystem::remove(t.path + "/mesh_" + boost::lexical_cast<std::string>(t.id) + ".xml", ec);
|
||||
t.type = None;
|
||||
break;
|
||||
}
|
||||
case RemoveBackup: {
|
||||
try {
|
||||
boost::filesystem::remove(t.path + "/.3mf");
|
||||
boost::system::error_code ec;
|
||||
boost::filesystem::remove(t.path + "/.3mf", ec);
|
||||
// We Saved with SplitModel now, so we can safe delete these sub models.
|
||||
boost::filesystem::remove_all(t.path + "/3D/Objects");
|
||||
boost::filesystem::create_directory(t.path + "/3D/Objects");
|
||||
|
|
|
|||
|
|
@ -69,6 +69,8 @@ struct PlateData
|
|||
int plate_index;
|
||||
std::vector<std::pair<int, int>> objects_and_instances;
|
||||
std::map<int, std::pair<int, int>> obj_inst_map;
|
||||
std::string printer_model_id;
|
||||
std::string nozzle_diameters;
|
||||
std::string gcode_file;
|
||||
std::string gcode_file_md5;
|
||||
std::string thumbnail_file;
|
||||
|
|
@ -231,7 +233,7 @@ extern bool load_bbs_3mf(const char* path, DynamicPrintConfig* config, ConfigSub
|
|||
|
||||
extern std::string bbs_3mf_get_thumbnail(const char * path);
|
||||
|
||||
extern bool load_gcode_3mf_from_stream(std::istream & data, DynamicPrintConfig* config, Model* model, PlateDataPtrs* plate_data_list,
|
||||
extern bool load_gcode_3mf_from_stream(std::istream & data, DynamicPrintConfig* config, Model* model, PlateDataPtrs* plate_data_list,
|
||||
Semver* file_version);
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1357,7 +1357,22 @@ namespace DoExport {
|
|||
total_weight += weight;
|
||||
total_cost += weight * extruder->filament_cost() * 0.001;
|
||||
}
|
||||
|
||||
|
||||
for (auto volume : result.print_statistics.wipe_tower_volumes_per_extruder) {
|
||||
total_extruded_volume += volume.second;
|
||||
|
||||
size_t extruder_id = volume.first;
|
||||
auto extruder = std::find_if(extruders.begin(), extruders.end(), [extruder_id](const Extruder& extr) {return extr.id() == extruder_id; });
|
||||
if (extruder == extruders.end())
|
||||
continue;
|
||||
|
||||
double s = PI * sqr(0.5* extruder->filament_diameter());
|
||||
double weight = volume.second * extruder->filament_density() * 0.001;
|
||||
total_used_filament += volume.second/s;
|
||||
total_weight += weight;
|
||||
total_cost += weight * extruder->filament_cost() * 0.001;
|
||||
}
|
||||
|
||||
total_cost += config.time_cost.getFloat() * (normal_print_time/3600.0);
|
||||
|
||||
print_statistics.total_extruded_volume = total_extruded_volume;
|
||||
|
|
@ -1398,8 +1413,7 @@ namespace DoExport {
|
|||
if (ret.size() < MAX_TAGS_COUNT) check(_(L("Layer change G-code")), config.layer_change_gcode.value);
|
||||
if (ret.size() < MAX_TAGS_COUNT) check(_(L("Time lapse G-code")), config.time_lapse_gcode.value);
|
||||
if (ret.size() < MAX_TAGS_COUNT) check(_(L("Change filament G-code")), config.change_filament_gcode.value);
|
||||
//BBS
|
||||
//if (ret.size() < MAX_TAGS_COUNT) check(_(L("Printing by object G-code")), config.printing_by_object_gcode.value);
|
||||
if (ret.size() < MAX_TAGS_COUNT) check(_(L("Printing by object G-code")), config.printing_by_object_gcode.value);
|
||||
//if (ret.size() < MAX_TAGS_COUNT) check(_(L("Color Change G-code")), config.color_change_gcode.value);
|
||||
//Orca
|
||||
if (ret.size() < MAX_TAGS_COUNT) check(_(L("Change extrusion role G-code")), config.change_extrusion_role_gcode.value);
|
||||
|
|
@ -1531,6 +1545,27 @@ void GCode::do_export(Print* print, const char* path, GCodeProcessorResult* resu
|
|||
}
|
||||
m_processor.result().timelapse_warning_code = m_timelapse_warning_code;
|
||||
m_processor.result().support_traditional_timelapse = m_support_traditional_timelapse;
|
||||
|
||||
{ //BBS:check bed and filament compatible
|
||||
const ConfigOptionDef *bed_type_def = print_config_def.get("curr_bed_type");
|
||||
assert(bed_type_def != nullptr);
|
||||
const t_config_enum_values *bed_type_keys_map = bed_type_def->enum_keys_map;
|
||||
const ConfigOptionInts *bed_temp_opt = m_config.option<ConfigOptionInts>(get_bed_temp_key(m_config.curr_bed_type));
|
||||
for(auto extruder_id : m_initial_layer_extruders){
|
||||
int cur_bed_temp = bed_temp_opt->get_at(extruder_id);
|
||||
if (cur_bed_temp == 0 && bed_type_keys_map != nullptr) {
|
||||
for (auto item : *bed_type_keys_map) {
|
||||
if (item.second == m_config.curr_bed_type) {
|
||||
m_processor.result().bed_match_result = BedMatchResult(false, item.first, extruder_id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (m_processor.result().bed_match_result.match == false)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_processor.finalize(true);
|
||||
// DoExport::update_print_estimated_times_stats(m_processor, print->m_print_statistics);
|
||||
DoExport::update_print_estimated_stats(m_processor, m_writer.extruders(), print->m_print_statistics, print->config());
|
||||
|
|
@ -1919,6 +1954,24 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
|||
}
|
||||
}
|
||||
|
||||
{
|
||||
std::string filament_density_list = "; filament_density: ";
|
||||
(filament_density_list+=m_config.filament_density.serialize()) +='\n';
|
||||
file.writeln(filament_density_list);
|
||||
|
||||
std::string filament_diameter_list = "; filament_diameter: ";
|
||||
(filament_diameter_list += m_config.filament_diameter.serialize()) += '\n';
|
||||
file.writeln(filament_diameter_list);
|
||||
|
||||
coordf_t max_height_z = -1;
|
||||
for (const auto& object : print.objects())
|
||||
max_height_z = std::max(object->layers().back()->print_z, max_height_z);
|
||||
|
||||
std::ostringstream max_height_z_tip;
|
||||
max_height_z_tip<<"; max_z_height: " << std::fixed << std::setprecision(2) << max_height_z << '\n';
|
||||
file.writeln(max_height_z_tip.str());
|
||||
}
|
||||
|
||||
file.write_format("; HEADER_BLOCK_END\n\n");
|
||||
|
||||
|
||||
|
|
@ -3545,6 +3598,27 @@ LayerResult GCode::process_layer(
|
|||
Skirt::make_skirt_loops_per_extruder_1st_layer(print, layer_tools, m_skirt_done) :
|
||||
Skirt::make_skirt_loops_per_extruder_other_layers(print, layer_tools, m_skirt_done);
|
||||
|
||||
// BBS: get next extruder according to flush and soluble
|
||||
auto get_next_extruder = [&](int current_extruder,const std::vector<unsigned int>&extruders) {
|
||||
std::vector<float> flush_matrix(cast<float>(m_config.flush_volumes_matrix.values));
|
||||
const unsigned int number_of_extruders = (unsigned int)(sqrt(flush_matrix.size()) + EPSILON);
|
||||
// Extract purging volumes for each extruder pair:
|
||||
std::vector<std::vector<float>> wipe_volumes;
|
||||
for (unsigned int i = 0; i < number_of_extruders; ++i)
|
||||
wipe_volumes.push_back(std::vector<float>(flush_matrix.begin() + i * number_of_extruders, flush_matrix.begin() + (i + 1) * number_of_extruders));
|
||||
unsigned int next_extruder = current_extruder;
|
||||
float min_flush = std::numeric_limits<float>::max();
|
||||
for (auto extruder_id : extruders) {
|
||||
if (print.config().filament_soluble.get_at(extruder_id) || extruder_id == current_extruder)
|
||||
continue;
|
||||
if (wipe_volumes[current_extruder][extruder_id] < min_flush) {
|
||||
next_extruder = extruder_id;
|
||||
min_flush = wipe_volumes[current_extruder][extruder_id];
|
||||
}
|
||||
}
|
||||
return next_extruder;
|
||||
};
|
||||
|
||||
if (m_config.enable_overhang_speed && !m_config.overhang_speed_classic) {
|
||||
for (const auto &layer_to_print : layers) {
|
||||
m_extrusion_quality_estimator.prepare_for_new_layer(layer_to_print.original_object,
|
||||
|
|
@ -3597,12 +3671,21 @@ LayerResult GCode::process_layer(
|
|||
if (print.config().filament_soluble.get_at(extruder_id))
|
||||
continue;
|
||||
|
||||
//BBS: now we don't consider interface filament used in other object
|
||||
if (extruder_id == interface_extruder)
|
||||
continue;
|
||||
|
||||
dontcare_extruder = extruder_id;
|
||||
break;
|
||||
}
|
||||
#if 0
|
||||
//BBS: not found a suitable extruder in current layer ,dontcare_extruider==first_extruder_id==interface_extruder
|
||||
if (dontcare_extruder == interface_extruder && (object.config().support_interface_not_for_body && object.config().support_interface_filament.value!=0)) {
|
||||
// BBS : get a suitable extruder from other layer
|
||||
auto all_extruders = print.extruders();
|
||||
dontcare_extruder = get_next_extruder(dontcare_extruder, all_extruders);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (support_dontcare)
|
||||
support_extruder = dontcare_extruder;
|
||||
|
|
@ -3964,16 +4047,56 @@ LayerResult GCode::process_layer(
|
|||
m_last_obj_copy = this_object_copy;
|
||||
this->set_origin(unscale(offset));
|
||||
//FIXME the following code prints regions in the order they are defined, the path is not optimized in any way.
|
||||
bool is_infill_first = print.default_region_config().wall_infill_order == WallInfillOrder::InfillInnerOuter ||
|
||||
print.default_region_config().wall_infill_order == WallInfillOrder::InfillOuterInner;
|
||||
bool is_infill_first =print.config().is_infill_first;
|
||||
|
||||
auto has_infill = [](const std::vector<ObjectByExtruder::Island::Region> &by_region) {
|
||||
for (auto region : by_region) {
|
||||
if (!region.infills.empty())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
//BBS: for first layer, we always print wall firstly to get better bed adhesive force
|
||||
//This behaviour is same with cura
|
||||
if (is_infill_first && !first_layer) {
|
||||
gcode += this->extrude_infill(print, by_region_specific, false);
|
||||
if (!has_wipe_tower && need_insert_timelapse_gcode_for_traditional && !has_insert_timelapse_gcode && has_infill(by_region_specific)) {
|
||||
gcode += this->retract(false, false, LiftType::NormalLift);
|
||||
|
||||
std::string timepals_gcode = insert_timelapse_gcode();
|
||||
gcode += timepals_gcode;
|
||||
m_writer.set_current_position_clear(false);
|
||||
//BBS: check whether custom gcode changes the z position. Update if changed
|
||||
double temp_z_after_timepals_gcode;
|
||||
if (GCodeProcessor::get_last_z_from_gcode(timepals_gcode, temp_z_after_timepals_gcode)) {
|
||||
Vec3d pos = m_writer.get_position();
|
||||
pos(2) = temp_z_after_timepals_gcode;
|
||||
m_writer.set_position(pos);
|
||||
}
|
||||
|
||||
has_insert_timelapse_gcode = true;
|
||||
}
|
||||
gcode += this->extrude_infill(print, by_region_specific, false);
|
||||
gcode += this->extrude_perimeters(print, by_region_specific);
|
||||
} else {
|
||||
gcode += this->extrude_perimeters(print, by_region_specific);
|
||||
gcode += this->extrude_infill(print,by_region_specific, false);
|
||||
if (!has_wipe_tower && need_insert_timelapse_gcode_for_traditional && !has_insert_timelapse_gcode && has_infill(by_region_specific)) {
|
||||
gcode += this->retract(false, false, LiftType::NormalLift);
|
||||
|
||||
std::string timepals_gcode = insert_timelapse_gcode();
|
||||
gcode += timepals_gcode;
|
||||
m_writer.set_current_position_clear(false);
|
||||
//BBS: check whether custom gcode changes the z position. Update if changed
|
||||
double temp_z_after_timepals_gcode;
|
||||
if (GCodeProcessor::get_last_z_from_gcode(timepals_gcode, temp_z_after_timepals_gcode)) {
|
||||
Vec3d pos = m_writer.get_position();
|
||||
pos(2) = temp_z_after_timepals_gcode;
|
||||
m_writer.set_position(pos);
|
||||
}
|
||||
|
||||
has_insert_timelapse_gcode = true;
|
||||
}
|
||||
gcode += this->extrude_infill(print,by_region_specific, false);
|
||||
}
|
||||
// ironing
|
||||
gcode += this->extrude_infill(print,by_region_specific, true);
|
||||
|
|
@ -4002,6 +4125,12 @@ LayerResult GCode::process_layer(
|
|||
}
|
||||
}
|
||||
}
|
||||
if (first_layer) {
|
||||
for (auto iter = by_extruder.begin(); iter != by_extruder.end(); ++iter) {
|
||||
if (!iter->second.empty())
|
||||
m_initial_layer_extruders.insert(iter->first);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
// Apply spiral vase post-processing if this layer contains suitable geometry
|
||||
|
|
@ -4197,9 +4326,7 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
|
|||
Point last_pos = this->last_pos();
|
||||
if (!m_config.spiral_mode && description == "perimeter") {
|
||||
assert(m_layer != nullptr);
|
||||
bool is_outer_wall_first = m_config.wall_infill_order == WallInfillOrder::OuterInnerInfill
|
||||
|| m_config.wall_infill_order == WallInfillOrder::InfillOuterInner
|
||||
|| m_config.wall_infill_order == WallInfillOrder::InnerOuterInnerInfill;
|
||||
bool is_outer_wall_first = m_config.wall_sequence == WallSequence::OuterInner;
|
||||
m_seam_placer.place_seam(m_layer, loop, is_outer_wall_first, this->last_pos());
|
||||
} else
|
||||
loop.split_at(last_pos, false);
|
||||
|
|
@ -5207,10 +5334,11 @@ bool GCode::needs_retraction(const Polyline &travel, ExtrusionRole role, LiftTyp
|
|||
travel_bbox.inflated(1);
|
||||
travel_bbox.defined = true;
|
||||
|
||||
const float protect_z_scaled = scale_(0.4);
|
||||
// do not scale for z
|
||||
const float protect_z = 0.4;
|
||||
std::pair<float, float> z_range;
|
||||
z_range.second = m_layer ? m_layer->print_z : 0.f;
|
||||
z_range.first = std::max(0.f, z_range.second - protect_z_scaled);
|
||||
z_range.first = std::max(0.f, z_range.second - protect_z);
|
||||
std::vector<LayerPtrs> layers_of_objects;
|
||||
std::vector<BoundingBox> boundingBox_for_objects;
|
||||
std::vector<Points> objects_instances_shift;
|
||||
|
|
@ -5261,7 +5389,7 @@ bool GCode::needs_retraction(const Polyline &travel, ExtrusionRole role, LiftTyp
|
|||
float max_z_hop = 0.f;
|
||||
for (int i = 0; i < m_config.z_hop.size(); i++)
|
||||
max_z_hop = std::max(max_z_hop, (float)m_config.z_hop.get_at(i));
|
||||
float travel_len_thresh = max_z_hop / tan(GCodeWriter::slope_threshold);
|
||||
float travel_len_thresh = scale_(max_z_hop / tan(GCodeWriter::slope_threshold));
|
||||
float accum_len = 0.f;
|
||||
Polyline clipped_travel;
|
||||
|
||||
|
|
@ -5337,8 +5465,7 @@ std::string GCode::retract(bool toolchange, bool is_last_retraction, LiftType li
|
|||
gcode += toolchange ? m_writer.retract_for_toolchange() : m_writer.retract();
|
||||
|
||||
gcode += m_writer.reset_e();
|
||||
|
||||
// check if should + can lift (roughly from SuperSlicer)
|
||||
// Orca: check if should + can lift (roughly from SuperSlicer)
|
||||
RetractLiftEnforceType retract_lift_type = RetractLiftEnforceType(EXTRUDER_CONFIG(retract_lift_enforce));
|
||||
|
||||
bool needs_lift = toolchange
|
||||
|
|
@ -5371,7 +5498,7 @@ std::string GCode::retract(bool toolchange, bool is_last_retraction, LiftType li
|
|||
return gcode;
|
||||
}
|
||||
|
||||
std::string GCode::set_extruder(unsigned int extruder_id, double print_z)
|
||||
std::string GCode::set_extruder(unsigned int extruder_id, double print_z, bool by_object)
|
||||
{
|
||||
if (!m_writer.need_toolchange(extruder_id))
|
||||
return "";
|
||||
|
|
@ -5405,6 +5532,10 @@ std::string GCode::set_extruder(unsigned int extruder_id, double print_z)
|
|||
// Always reset the extrusion path, even if the tool change retract is set to zero.
|
||||
m_wipe.reset_path();
|
||||
|
||||
// BBS: insert skip object label before change filament while by object
|
||||
if (by_object)
|
||||
m_writer.add_object_change_labels(gcode);
|
||||
|
||||
if (m_writer.extruder() != nullptr) {
|
||||
// Process the custom filament_end_gcode. set_extruder() is only called if there is no wipe tower
|
||||
// so it should not be injected twice.
|
||||
|
|
|
|||
|
|
@ -216,7 +216,7 @@ public:
|
|||
bool needs_retraction(const Polyline& travel, ExtrusionRole role, LiftType& lift_type);
|
||||
std::string retract(bool toolchange = false, bool is_last_retraction = false, LiftType lift_type = LiftType::NormalLift);
|
||||
std::string unretract() { return m_writer.unlift() + m_writer.unretract(); }
|
||||
std::string set_extruder(unsigned int extruder_id, double print_z);
|
||||
std::string set_extruder(unsigned int extruder_id, double print_z, bool by_object=false);
|
||||
bool is_BBL_Printer();
|
||||
|
||||
// SoftFever
|
||||
|
|
@ -549,6 +549,7 @@ private:
|
|||
bool m_need_change_layer_lift_z = false;
|
||||
int m_start_gcode_filament = -1;
|
||||
|
||||
std::set<unsigned int> m_initial_layer_extruders;
|
||||
// BBS
|
||||
int get_bed_temperature(const int extruder_id, const bool is_first_layer, const BedType bed_type) const;
|
||||
|
||||
|
|
|
|||
|
|
@ -91,34 +91,34 @@ inline Grids line_rasterization(const Line &line, int64_t xdist = RasteXDistance
|
|||
|
||||
void LinesBucketQueue::emplace_back_bucket(ExtrusionLayers &&els, const void *objPtr, Point offset)
|
||||
{
|
||||
auto oldSize = _buckets.capacity();
|
||||
_buckets.emplace_back(std::move(els), objPtr, offset);
|
||||
_pq.push(&_buckets.back());
|
||||
auto newSize = _buckets.capacity();
|
||||
auto oldSize = line_buckets.capacity();
|
||||
line_buckets.emplace_back(std::move(els), objPtr, offset);
|
||||
line_bucket_ptr_queue.push(&line_buckets.back());
|
||||
auto newSize = line_buckets.capacity();
|
||||
if (oldSize != newSize) { // pointers change
|
||||
decltype(_pq) newQueue;
|
||||
for (LinesBucket &bucket : _buckets) { newQueue.push(&bucket); }
|
||||
std::swap(_pq, newQueue);
|
||||
decltype(line_bucket_ptr_queue) newQueue;
|
||||
for (LinesBucket &bucket : line_buckets) { newQueue.push(&bucket); }
|
||||
std::swap(line_bucket_ptr_queue, newQueue);
|
||||
}
|
||||
}
|
||||
|
||||
// remove lowest and get the current bottom z
|
||||
float LinesBucketQueue::getCurrBottomZ()
|
||||
{
|
||||
auto lowest = _pq.top();
|
||||
_pq.pop();
|
||||
auto lowest = line_bucket_ptr_queue.top();
|
||||
line_bucket_ptr_queue.pop();
|
||||
float layerBottomZ = lowest->curBottomZ();
|
||||
std::vector<LinesBucket *> lowests;
|
||||
lowests.push_back(lowest);
|
||||
|
||||
while (_pq.empty() == false && std::abs(_pq.top()->curBottomZ() - lowest->curBottomZ()) < EPSILON) {
|
||||
lowests.push_back(_pq.top());
|
||||
_pq.pop();
|
||||
while (line_bucket_ptr_queue.empty() == false && std::abs(line_bucket_ptr_queue.top()->curBottomZ() - lowest->curBottomZ()) < EPSILON) {
|
||||
lowests.push_back(line_bucket_ptr_queue.top());
|
||||
line_bucket_ptr_queue.pop();
|
||||
}
|
||||
|
||||
for (LinesBucket *bp : lowests) {
|
||||
bp->raise();
|
||||
if (bp->valid()) { _pq.push(bp); }
|
||||
if (bp->valid()) { line_bucket_ptr_queue.push(bp); }
|
||||
}
|
||||
return layerBottomZ;
|
||||
}
|
||||
|
|
@ -126,7 +126,7 @@ float LinesBucketQueue::getCurrBottomZ()
|
|||
LineWithIDs LinesBucketQueue::getCurLines() const
|
||||
{
|
||||
LineWithIDs lines;
|
||||
for (const LinesBucket &bucket : _buckets) {
|
||||
for (const LinesBucket &bucket : line_buckets) {
|
||||
if (bucket.valid()) {
|
||||
LineWithIDs tmpLines = bucket.curLines();
|
||||
lines.insert(lines.end(), tmpLines.begin(), tmpLines.end());
|
||||
|
|
|
|||
|
|
@ -109,12 +109,12 @@ struct LinesBucketPtrComp
|
|||
class LinesBucketQueue
|
||||
{
|
||||
public:
|
||||
std::vector<LinesBucket> _buckets;
|
||||
std::priority_queue<LinesBucket *, std::vector<LinesBucket *>, LinesBucketPtrComp> _pq;
|
||||
std::vector<LinesBucket> line_buckets;
|
||||
std::priority_queue<LinesBucket *, std::vector<LinesBucket *>, LinesBucketPtrComp> line_bucket_ptr_queue;
|
||||
|
||||
public:
|
||||
void emplace_back_bucket(ExtrusionLayers &&els, const void *objPtr, Point offset);
|
||||
bool valid() const { return _pq.empty() == false; }
|
||||
bool valid() const { return line_bucket_ptr_queue.empty() == false; }
|
||||
float getCurrBottomZ();
|
||||
LineWithIDs getCurLines() const;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ static const size_t MIN_EXTRUDERS_COUNT = 5;
|
|||
static const float DEFAULT_FILAMENT_DIAMETER = 1.75f;
|
||||
static const int DEFAULT_FILAMENT_HRC = 0;
|
||||
static const float DEFAULT_FILAMENT_DENSITY = 1.245f;
|
||||
static const float DEFAULT_FILAMENT_COST = 29.99f;
|
||||
static const int DEFAULT_FILAMENT_VITRIFICATION_TEMPERATURE = 0;
|
||||
static const Slic3r::Vec3f DEFAULT_EXTRUDER_OFFSET = Slic3r::Vec3f::Zero();
|
||||
|
||||
|
|
@ -64,7 +65,9 @@ const std::vector<std::string> GCodeProcessor::Reserved_Tags = {
|
|||
"_GP_ESTIMATED_PRINTING_TIME_PLACEHOLDER",
|
||||
"_GP_TOTAL_LAYER_NUMBER_PLACEHOLDER",
|
||||
" MANUAL_TOOL_CHANGE ",
|
||||
"_DURING_PRINT_EXHAUST_FAN"
|
||||
"_DURING_PRINT_EXHAUST_FAN",
|
||||
" WIPE_TOWER_START",
|
||||
" WIPE_TOWER_END"
|
||||
};
|
||||
|
||||
const std::vector<std::string> GCodeProcessor::Reserved_Tags_compatible = {
|
||||
|
|
@ -81,7 +84,10 @@ const std::vector<std::string> GCodeProcessor::Reserved_Tags_compatible = {
|
|||
"_GP_LAST_LINE_M73_PLACEHOLDER",
|
||||
"_GP_ESTIMATED_PRINTING_TIME_PLACEHOLDER",
|
||||
"_GP_TOTAL_LAYER_NUMBER_PLACEHOLDER",
|
||||
" MANUAL_TOOL_CHANGE "
|
||||
" MANUAL_TOOL_CHANGE ",
|
||||
"_DURING_PRINT_EXHAUST_FAN",
|
||||
" WIPE_TOWER_START",
|
||||
" WIPE_TOWER_END"
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -732,22 +738,30 @@ void GCodeProcessor::UsedFilaments::reset()
|
|||
color_change_cache = 0.0f;
|
||||
volumes_per_color_change = std::vector<double>();
|
||||
|
||||
tool_change_cache = 0.0f;
|
||||
model_extrude_cache = 0.0f;
|
||||
volumes_per_extruder.clear();
|
||||
|
||||
flush_per_filament.clear();
|
||||
|
||||
role_cache = 0.0f;
|
||||
filaments_per_role.clear();
|
||||
|
||||
wipe_tower_cache = 0.0f;
|
||||
wipe_tower_volume_per_extruder.clear();
|
||||
}
|
||||
|
||||
void GCodeProcessor::UsedFilaments::increase_caches(double extruded_volume)
|
||||
void GCodeProcessor::UsedFilaments::increase_model_caches(double extruded_volume)
|
||||
{
|
||||
color_change_cache += extruded_volume;
|
||||
tool_change_cache += extruded_volume;
|
||||
model_extrude_cache += extruded_volume;
|
||||
role_cache += extruded_volume;
|
||||
}
|
||||
|
||||
void GCodeProcessor::UsedFilaments::increase_wipe_tower_caches(double extruded_volume)
|
||||
{
|
||||
wipe_tower_cache += extruded_volume;
|
||||
}
|
||||
|
||||
void GCodeProcessor::UsedFilaments::process_color_change_cache()
|
||||
{
|
||||
if (color_change_cache != 0.0f) {
|
||||
|
|
@ -756,15 +770,27 @@ void GCodeProcessor::UsedFilaments::process_color_change_cache()
|
|||
}
|
||||
}
|
||||
|
||||
void GCodeProcessor::UsedFilaments::process_extruder_cache(GCodeProcessor* processor)
|
||||
void GCodeProcessor::UsedFilaments::process_model_cache(GCodeProcessor* processor)
|
||||
{
|
||||
size_t active_extruder_id = processor->m_extruder_id;
|
||||
if (tool_change_cache != 0.0f) {
|
||||
if (model_extrude_cache != 0.0f) {
|
||||
if (volumes_per_extruder.find(active_extruder_id) != volumes_per_extruder.end())
|
||||
volumes_per_extruder[active_extruder_id] += tool_change_cache;
|
||||
volumes_per_extruder[active_extruder_id] += model_extrude_cache;
|
||||
else
|
||||
volumes_per_extruder[active_extruder_id] = tool_change_cache;
|
||||
tool_change_cache = 0.0f;
|
||||
volumes_per_extruder[active_extruder_id] = model_extrude_cache;
|
||||
model_extrude_cache = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void GCodeProcessor::UsedFilaments::process_wipe_tower_cache(GCodeProcessor* processor)
|
||||
{
|
||||
size_t active_extruder_id = processor->m_extruder_id;
|
||||
if (wipe_tower_cache != 0.0f) {
|
||||
if (wipe_tower_volume_per_extruder.find(active_extruder_id) != wipe_tower_volume_per_extruder.end())
|
||||
wipe_tower_volume_per_extruder[active_extruder_id] += wipe_tower_cache;
|
||||
else
|
||||
wipe_tower_volume_per_extruder[active_extruder_id] = wipe_tower_cache;
|
||||
wipe_tower_cache = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -799,8 +825,9 @@ void GCodeProcessor::UsedFilaments::process_role_cache(GCodeProcessor* processor
|
|||
void GCodeProcessor::UsedFilaments::process_caches(GCodeProcessor* processor)
|
||||
{
|
||||
process_color_change_cache();
|
||||
process_extruder_cache(processor);
|
||||
process_model_cache(processor);
|
||||
process_role_cache(processor);
|
||||
process_wipe_tower_cache(processor);
|
||||
}
|
||||
|
||||
#if ENABLE_GCODE_VIEWER_STATISTICS
|
||||
|
|
@ -852,8 +879,10 @@ void GCodeProcessorResult::reset() {
|
|||
filament_diameters = std::vector<float>(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_DIAMETER);
|
||||
required_nozzle_HRC = std::vector<int>(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_HRC);
|
||||
filament_densities = std::vector<float>(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_DENSITY);
|
||||
filament_costs = std::vector<float>(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_COST);
|
||||
custom_gcode_per_print_z = std::vector<CustomGCode::Item>();
|
||||
spiral_vase_layers = std::vector<std::pair<float, std::pair<size_t, size_t>>>();
|
||||
bed_match_result = BedMatchResult(true);
|
||||
warnings.clear();
|
||||
|
||||
//BBS: add mutex for protection of gcode result
|
||||
|
|
@ -962,6 +991,7 @@ void GCodeProcessor::apply_config(const PrintConfig& config)
|
|||
m_result.required_nozzle_HRC.resize(extruders_count);
|
||||
m_result.filament_densities.resize(extruders_count);
|
||||
m_result.filament_vitrification_temperature.resize(extruders_count);
|
||||
m_result.filament_costs.resize(extruders_count);
|
||||
m_extruder_temps.resize(extruders_count);
|
||||
m_result.nozzle_hrc = static_cast<int>(config.nozzle_hrc.getInt());
|
||||
m_result.nozzle_type = config.nozzle_type;
|
||||
|
|
@ -972,6 +1002,7 @@ void GCodeProcessor::apply_config(const PrintConfig& config)
|
|||
m_result.required_nozzle_HRC[i] = static_cast<int>(config.required_nozzle_HRC.get_at(i));
|
||||
m_result.filament_densities[i] = static_cast<float>(config.filament_density.get_at(i));
|
||||
m_result.filament_vitrification_temperature[i] = static_cast<float>(config.temperature_vitrification.get_at(i));
|
||||
m_result.filament_costs[i] = static_cast<float>(config.filament_cost.get_at(i));
|
||||
}
|
||||
|
||||
if (m_flavor == gcfMarlinLegacy || m_flavor == gcfMarlinFirmware || m_flavor == gcfKlipper || m_flavor == gcfRepRapFirmware) {
|
||||
|
|
@ -1027,6 +1058,7 @@ void GCodeProcessor::apply_config(const PrintConfig& config)
|
|||
const ConfigOptionFloat* z_offset = config.option<ConfigOptionFloat>("z_offset");
|
||||
if (z_offset != nullptr)
|
||||
m_z_offset = z_offset->value;
|
||||
|
||||
}
|
||||
|
||||
void GCodeProcessor::apply_config(const DynamicPrintConfig& config)
|
||||
|
|
@ -1114,6 +1146,19 @@ void GCodeProcessor::apply_config(const DynamicPrintConfig& config)
|
|||
m_result.filament_densities.emplace_back(DEFAULT_FILAMENT_DENSITY);
|
||||
}
|
||||
}
|
||||
|
||||
//BBS
|
||||
const ConfigOptionFloats* filament_costs = config.option<ConfigOptionFloats>("filament_cost");
|
||||
if (filament_costs != nullptr) {
|
||||
m_result.filament_costs.clear();
|
||||
m_result.filament_costs.resize(filament_costs->values.size());
|
||||
for (size_t i = 0; i < filament_costs->values.size(); ++i)
|
||||
m_result.filament_costs[i]=static_cast<float>(filament_costs->values[i]);
|
||||
}
|
||||
for (size_t i = m_result.filament_costs.size(); i < m_result.extruders_count; ++i) {
|
||||
m_result.filament_costs.emplace_back(DEFAULT_FILAMENT_COST);
|
||||
}
|
||||
|
||||
//BBS
|
||||
const ConfigOptionInts* filament_vitrification_temperature = config.option<ConfigOptionInts>("temperature_vitrification");
|
||||
if (filament_vitrification_temperature != nullptr) {
|
||||
|
|
@ -1330,6 +1375,7 @@ void GCodeProcessor::reset()
|
|||
m_cached_position.reset();
|
||||
m_wiping = false;
|
||||
m_flushing = false;
|
||||
m_wipe_tower = false;
|
||||
m_remaining_volume = 0.f;
|
||||
// BBS: arc move related data
|
||||
m_move_path_type = EMovePathType::Noop_move;
|
||||
|
|
@ -2106,6 +2152,17 @@ void GCodeProcessor::process_tags(const std::string_view comment, bool producers
|
|||
return;
|
||||
}
|
||||
|
||||
if (boost::starts_with(comment, reserved_tag(ETags::Wipe_Tower_Start))) {
|
||||
m_wipe_tower = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (boost::starts_with(comment, reserved_tag(ETags::Wipe_Tower_End))) {
|
||||
m_wipe_tower = false;
|
||||
m_used_filaments.process_wipe_tower_cache(this);
|
||||
return;
|
||||
}
|
||||
|
||||
//BBS: flush start tag
|
||||
if (boost::starts_with(comment, GCodeProcessor::Flush_Start_Tag)) {
|
||||
m_flushing = true;
|
||||
|
|
@ -2811,10 +2868,13 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
|
|||
float delta_xyz = std::sqrt(sqr(delta_pos[X]) + sqr(delta_pos[Y]) + sqr(delta_pos[Z]));
|
||||
float volume_extruded_filament = area_filament_cross_section * delta_pos[E];
|
||||
float area_toolpath_cross_section = volume_extruded_filament / delta_xyz;
|
||||
|
||||
// save extruded volume to the cache
|
||||
m_used_filaments.increase_caches(volume_extruded_filament);
|
||||
|
||||
if (m_wipe_tower) {
|
||||
m_used_filaments.increase_wipe_tower_caches(volume_extruded_filament);
|
||||
}
|
||||
else {
|
||||
// save extruded volume to the cache
|
||||
m_used_filaments.increase_model_caches(volume_extruded_filament);
|
||||
}
|
||||
// volume extruded filament / tool displacement = area toolpath cross section
|
||||
m_mm3_per_mm = area_toolpath_cross_section;
|
||||
#if ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
|
|
@ -3268,10 +3328,14 @@ void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line)
|
|||
if (type == EMoveType::Extrude) {
|
||||
float volume_extruded_filament = area_filament_cross_section * delta_pos[E];
|
||||
float area_toolpath_cross_section = volume_extruded_filament / delta_xyz;
|
||||
|
||||
//BBS: save extruded volume to the cache
|
||||
m_used_filaments.increase_caches(volume_extruded_filament);
|
||||
|
||||
if (m_wipe_tower) {
|
||||
//BBS: save wipe tower volume to the cache
|
||||
m_used_filaments.increase_wipe_tower_caches(volume_extruded_filament);
|
||||
}
|
||||
else {
|
||||
//BBS: save extruded volume to the cache
|
||||
m_used_filaments.increase_model_caches(volume_extruded_filament);
|
||||
}
|
||||
//BBS: volume extruded filament / tool displacement = area toolpath cross section
|
||||
m_mm3_per_mm = area_toolpath_cross_section;
|
||||
#if ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
|
|
@ -4320,7 +4384,7 @@ void GCodeProcessor::process_filaments(CustomGCode::Type code)
|
|||
m_used_filaments.process_color_change_cache();
|
||||
|
||||
if (code == CustomGCode::ToolChange) {
|
||||
m_used_filaments.process_extruder_cache(this);
|
||||
m_used_filaments.process_model_cache(this);
|
||||
//BBS: reset remaining filament
|
||||
m_remaining_volume = m_nozzle_volume;
|
||||
}
|
||||
|
|
@ -4353,6 +4417,7 @@ void GCodeProcessor::update_estimated_times_stats()
|
|||
|
||||
m_result.print_statistics.volumes_per_color_change = m_used_filaments.volumes_per_color_change;
|
||||
m_result.print_statistics.volumes_per_extruder = m_used_filaments.volumes_per_extruder;
|
||||
m_result.print_statistics.wipe_tower_volumes_per_extruder = m_used_filaments.wipe_tower_volume_per_extruder;
|
||||
m_result.print_statistics.flush_per_filament = m_used_filaments.flush_per_filament;
|
||||
m_result.print_statistics.used_filaments_per_role = m_used_filaments.filaments_per_role;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@ namespace Slic3r {
|
|||
|
||||
std::vector<double> volumes_per_color_change;
|
||||
std::map<size_t, double> volumes_per_extruder;
|
||||
std::map<size_t, double> wipe_tower_volumes_per_extruder;
|
||||
//BBS: the flush amount of every filament
|
||||
std::map<size_t, double> flush_per_filament;
|
||||
std::map<ExtrusionRole, std::pair<double, double>> used_filaments_per_role;
|
||||
|
|
@ -88,6 +89,7 @@ namespace Slic3r {
|
|||
}
|
||||
volumes_per_color_change.clear();
|
||||
volumes_per_color_change.shrink_to_fit();
|
||||
wipe_tower_volumes_per_extruder.clear();
|
||||
volumes_per_extruder.clear();
|
||||
flush_per_filament.clear();
|
||||
used_filaments_per_role.clear();
|
||||
|
|
@ -109,11 +111,23 @@ namespace Slic3r {
|
|||
ConflictResult() = default;
|
||||
};
|
||||
|
||||
struct BedMatchResult
|
||||
{
|
||||
bool match;
|
||||
std::string bed_type_name;
|
||||
int extruder_id;
|
||||
BedMatchResult():match(true),bed_type_name(""),extruder_id(-1) {}
|
||||
BedMatchResult(bool _match,const std::string& _bed_type_name="",int _extruder_id=-1)
|
||||
:match(_match),bed_type_name(_bed_type_name),extruder_id(_extruder_id)
|
||||
{}
|
||||
};
|
||||
|
||||
using ConflictResultOpt = std::optional<ConflictResult>;
|
||||
|
||||
struct GCodeProcessorResult
|
||||
{
|
||||
ConflictResultOpt conflict_result;
|
||||
BedMatchResult bed_match_result;
|
||||
|
||||
struct SettingsIds
|
||||
{
|
||||
|
|
@ -190,6 +204,7 @@ namespace Slic3r {
|
|||
std::vector<float> filament_diameters;
|
||||
std::vector<int> required_nozzle_HRC;
|
||||
std::vector<float> filament_densities;
|
||||
std::vector<float> filament_costs;
|
||||
std::vector<int> filament_vitrification_temperature;
|
||||
PrintEstimatedStatistics print_statistics;
|
||||
std::vector<CustomGCode::Item> custom_gcode_per_print_z;
|
||||
|
|
@ -223,11 +238,13 @@ namespace Slic3r {
|
|||
extruder_colors = other.extruder_colors;
|
||||
filament_diameters = other.filament_diameters;
|
||||
filament_densities = other.filament_densities;
|
||||
filament_costs = other.filament_costs;
|
||||
print_statistics = other.print_statistics;
|
||||
custom_gcode_per_print_z = other.custom_gcode_per_print_z;
|
||||
spiral_vase_layers = other.spiral_vase_layers;
|
||||
warnings = other.warnings;
|
||||
bed_type = other.bed_type;
|
||||
bed_match_result = other.bed_match_result;
|
||||
#if ENABLE_GCODE_VIEWER_STATISTICS
|
||||
time = other.time;
|
||||
#endif
|
||||
|
|
@ -261,7 +278,9 @@ namespace Slic3r {
|
|||
Estimated_Printing_Time_Placeholder,
|
||||
Total_Layer_Number_Placeholder,
|
||||
Manual_Tool_Change,
|
||||
During_Print_Exhaust_Fan
|
||||
During_Print_Exhaust_Fan,
|
||||
Wipe_Tower_Start,
|
||||
Wipe_Tower_End,
|
||||
};
|
||||
|
||||
static const std::string& reserved_tag(ETags tag) { return s_IsBBLPrinter ? Reserved_Tags[static_cast<unsigned char>(tag)] : Reserved_Tags_compatible[static_cast<unsigned char>(tag)]; }
|
||||
|
|
@ -474,9 +493,12 @@ namespace Slic3r {
|
|||
double color_change_cache;
|
||||
std::vector<double> volumes_per_color_change;
|
||||
|
||||
double tool_change_cache;
|
||||
double model_extrude_cache;
|
||||
std::map<size_t, double> volumes_per_extruder;
|
||||
|
||||
double wipe_tower_cache;
|
||||
std::map<size_t, double>wipe_tower_volume_per_extruder;
|
||||
|
||||
//BBS: the flush amount of every filament
|
||||
std::map<size_t, double> flush_per_filament;
|
||||
|
||||
|
|
@ -485,10 +507,12 @@ namespace Slic3r {
|
|||
|
||||
void reset();
|
||||
|
||||
void increase_caches(double extruded_volume);
|
||||
void increase_model_caches(double extruded_volume);
|
||||
void increase_wipe_tower_caches(double extruded_volume);
|
||||
|
||||
void process_color_change_cache();
|
||||
void process_extruder_cache(GCodeProcessor* processor);
|
||||
void process_model_cache(GCodeProcessor* processor);
|
||||
void process_wipe_tower_cache(GCodeProcessor* processor);
|
||||
void update_flush_per_filament(size_t extrude_id, float flush_length);
|
||||
void process_role_cache(GCodeProcessor* processor);
|
||||
void process_caches(GCodeProcessor* processor);
|
||||
|
|
@ -637,6 +661,7 @@ namespace Slic3r {
|
|||
CachedPosition m_cached_position;
|
||||
bool m_wiping;
|
||||
bool m_flushing;
|
||||
bool m_wipe_tower;
|
||||
float m_remaining_volume;
|
||||
bool m_manual_filament_change;
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -27,136 +27,139 @@ class Grid;
|
|||
|
||||
namespace SeamPlacerImpl {
|
||||
|
||||
// ************ FOR BACKPORT COMPATIBILITY ONLY ***************
|
||||
// Angle from v1 to v2, returning double atan2(y, x) normalized to <-PI, PI>.
|
||||
template<typename Derived, typename Derived2> inline double angle(const Eigen::MatrixBase<Derived> &v1, const Eigen::MatrixBase<Derived2> &v2)
|
||||
{
|
||||
static_assert(Derived::IsVectorAtCompileTime && int(Derived::SizeAtCompileTime) == 2, "angle(): first parameter is not a 2D vector");
|
||||
static_assert(Derived2::IsVectorAtCompileTime && int(Derived2::SizeAtCompileTime) == 2, "angle(): second parameter is not a 2D vector");
|
||||
auto v1d = v1.template cast<double>();
|
||||
auto v2d = v2.template cast<double>();
|
||||
return atan2(cross2(v1d, v2d), v1d.dot(v2d));
|
||||
}
|
||||
// ***************************
|
||||
|
||||
struct GlobalModelInfo;
|
||||
struct SeamComparator;
|
||||
|
||||
enum class EnforcedBlockedSeamPoint {
|
||||
Blocked = 0,
|
||||
Neutral = 1,
|
||||
Enforced = 2,
|
||||
Blocked = 0,
|
||||
Neutral = 1,
|
||||
Enforced = 2,
|
||||
};
|
||||
|
||||
// struct representing single perimeter loop
|
||||
struct Perimeter {
|
||||
size_t start_index{};
|
||||
size_t end_index{}; //inclusive!
|
||||
size_t seam_index{};
|
||||
float flow_width{};
|
||||
struct Perimeter
|
||||
{
|
||||
size_t start_index{};
|
||||
size_t end_index{}; // inclusive!
|
||||
size_t seam_index{};
|
||||
float flow_width{};
|
||||
|
||||
// During alignment, a final position may be stored here. In that case, finalized is set to true.
|
||||
// Note that final seam position is not limited to points of the perimeter loop. In theory it can be any position
|
||||
// Random position also uses this flexibility to set final seam point position
|
||||
bool finalized = false;
|
||||
Vec3f final_seam_position = Vec3f::Zero();
|
||||
// During alignment, a final position may be stored here. In that case, finalized is set to true.
|
||||
// Note that final seam position is not limited to points of the perimeter loop. In theory it can be any position
|
||||
// Random position also uses this flexibility to set final seam point position
|
||||
bool finalized = false;
|
||||
Vec3f final_seam_position = Vec3f::Zero();
|
||||
};
|
||||
|
||||
//Struct over which all processing of perimeters is done. For each perimeter point, its respective candidate is created,
|
||||
// Struct over which all processing of perimeters is done. For each perimeter point, its respective candidate is created,
|
||||
// then all the needed attributes are computed and finally, for each perimeter one point is chosen as seam.
|
||||
// This seam position can be then further aligned
|
||||
struct SeamCandidate {
|
||||
SeamCandidate(const Vec3f &pos, Perimeter &perimeter,
|
||||
float local_ccw_angle,
|
||||
EnforcedBlockedSeamPoint type) :
|
||||
position(pos), perimeter(perimeter), visibility(0.0f), overhang(0.0f), embedded_distance(0.0f), local_ccw_angle(
|
||||
local_ccw_angle), type(type), central_enforcer(false) {
|
||||
}
|
||||
const Vec3f position;
|
||||
// pointer to Perimeter loop of this point. It is shared across all points of the loop
|
||||
Perimeter &perimeter;
|
||||
float visibility;
|
||||
float overhang;
|
||||
// distance inside the merged layer regions, for detecting perimeter points which are hidden indside the print (e.g. multimaterial join)
|
||||
// Negative sign means inside the print, comes from EdgeGrid structure
|
||||
float embedded_distance;
|
||||
float local_ccw_angle;
|
||||
EnforcedBlockedSeamPoint type;
|
||||
bool central_enforcer; //marks this candidate as central point of enforced segment on the perimeter - important for alignment
|
||||
struct SeamCandidate
|
||||
{
|
||||
SeamCandidate(const Vec3f &pos, Perimeter &perimeter, float local_ccw_angle, EnforcedBlockedSeamPoint type)
|
||||
: position(pos), perimeter(perimeter), visibility(0.0f), overhang(0.0f), embedded_distance(0.0f), local_ccw_angle(local_ccw_angle), type(type), central_enforcer(false)
|
||||
{}
|
||||
const Vec3f position;
|
||||
// pointer to Perimeter loop of this point. It is shared across all points of the loop
|
||||
Perimeter &perimeter;
|
||||
float visibility;
|
||||
float overhang;
|
||||
// distance inside the merged layer regions, for detecting perimeter points which are hidden indside the print (e.g. multimaterial join)
|
||||
// Negative sign means inside the print, comes from EdgeGrid structure
|
||||
float embedded_distance;
|
||||
float local_ccw_angle;
|
||||
EnforcedBlockedSeamPoint type;
|
||||
bool central_enforcer; // marks this candidate as central point of enforced segment on the perimeter - important for alignment
|
||||
};
|
||||
|
||||
struct SeamCandidateCoordinateFunctor {
|
||||
SeamCandidateCoordinateFunctor(const std::vector<SeamCandidate> &seam_candidates) :
|
||||
seam_candidates(seam_candidates) {
|
||||
}
|
||||
const std::vector<SeamCandidate> &seam_candidates;
|
||||
float operator()(size_t index, size_t dim) const {
|
||||
return seam_candidates[index].position[dim];
|
||||
}
|
||||
struct SeamCandidateCoordinateFunctor
|
||||
{
|
||||
SeamCandidateCoordinateFunctor(const std::vector<SeamCandidate> &seam_candidates) : seam_candidates(seam_candidates) {}
|
||||
const std::vector<SeamCandidate> &seam_candidates;
|
||||
float operator()(size_t index, size_t dim) const { return seam_candidates[index].position[dim]; }
|
||||
};
|
||||
} // namespace SeamPlacerImpl
|
||||
|
||||
struct PrintObjectSeamData
|
||||
{
|
||||
using SeamCandidatesTree = KDTreeIndirect<3, float, SeamPlacerImpl::SeamCandidateCoordinateFunctor>;
|
||||
using SeamCandidatesTree = KDTreeIndirect<3, float, SeamPlacerImpl::SeamCandidateCoordinateFunctor>;
|
||||
|
||||
struct LayerSeams
|
||||
{
|
||||
Slic3r::deque<SeamPlacerImpl::Perimeter> perimeters;
|
||||
std::vector<SeamPlacerImpl::SeamCandidate> points;
|
||||
std::unique_ptr<SeamCandidatesTree> points_tree;
|
||||
};
|
||||
// Map of PrintObjects (PO) -> vector of layers of PO -> vector of perimeter
|
||||
std::vector<LayerSeams> layers;
|
||||
// Map of PrintObjects (PO) -> vector of layers of PO -> unique_ptr to KD
|
||||
// tree of all points of the given layer
|
||||
struct LayerSeams
|
||||
{
|
||||
Slic3r::deque<SeamPlacerImpl::Perimeter> perimeters;
|
||||
std::vector<SeamPlacerImpl::SeamCandidate> points;
|
||||
std::unique_ptr<SeamCandidatesTree> points_tree;
|
||||
};
|
||||
// Map of PrintObjects (PO) -> vector of layers of PO -> vector of perimeter
|
||||
std::vector<LayerSeams> layers;
|
||||
// Map of PrintObjects (PO) -> vector of layers of PO -> unique_ptr to KD
|
||||
// tree of all points of the given layer
|
||||
|
||||
void clear()
|
||||
{
|
||||
layers.clear();
|
||||
}
|
||||
void clear() { layers.clear(); }
|
||||
};
|
||||
|
||||
class SeamPlacer {
|
||||
class SeamPlacer
|
||||
{
|
||||
public:
|
||||
// Number of samples generated on the mesh. There are sqr_rays_per_sample_point*sqr_rays_per_sample_point rays casted from each samples
|
||||
static constexpr size_t raycasting_visibility_samples_count = 30000;
|
||||
static constexpr size_t fast_decimation_triangle_count_target = 16000;
|
||||
//square of number of rays per sample point
|
||||
static constexpr size_t sqr_rays_per_sample_point = 5;
|
||||
// Number of samples generated on the mesh. There are sqr_rays_per_sample_point*sqr_rays_per_sample_point rays casted from each samples
|
||||
static constexpr size_t raycasting_visibility_samples_count = 30000;
|
||||
static constexpr size_t fast_decimation_triangle_count_target = 16000;
|
||||
//square of number of rays per sample point
|
||||
static constexpr size_t sqr_rays_per_sample_point = 5;
|
||||
|
||||
// snapping angle - angles larger than this value will be snapped to during seam painting
|
||||
static constexpr float sharp_angle_snapping_threshold = 55.0f * float(PI) / 180.0f;
|
||||
// overhang angle for seam placement that still yields good results, in degrees, measured from vertical direction
|
||||
static constexpr float overhang_angle_threshold = 50.0f * float(PI) / 180.0f;
|
||||
// snapping angle - angles larger than this value will be snapped to during seam painting
|
||||
static constexpr float sharp_angle_snapping_threshold = 55.0f * float(PI) / 180.0f;
|
||||
// overhang angle for seam placement that still yields good results, in degrees, measured from vertical direction
|
||||
//BBS
|
||||
static constexpr float overhang_angle_threshold = 45.0f * float(PI) / 180.0f;
|
||||
|
||||
// determines angle importance compared to visibility ( neutral value is 1.0f. )
|
||||
static constexpr float angle_importance_aligned = 0.6f;
|
||||
static constexpr float angle_importance_nearest = 1.0f; // use much higher angle importance for nearest mode, to combat the visibility info noise
|
||||
// determines angle importance compared to visibility ( neutral value is 1.0f. )
|
||||
static constexpr float angle_importance_aligned = 0.6f;
|
||||
static constexpr float angle_importance_nearest = 1.0f; // use much higher angle importance for nearest mode, to combat the visibility info noise
|
||||
|
||||
// For long polygon sides, if they are close to the custom seam drawings, they are oversampled with this step size
|
||||
static constexpr float enforcer_oversampling_distance = 0.2f;
|
||||
// For long polygon sides, if they are close to the custom seam drawings, they are oversampled with this step size
|
||||
static constexpr float enforcer_oversampling_distance = 0.2f;
|
||||
|
||||
// When searching for seam clusters for alignment:
|
||||
// following value describes, how much worse score can point have and still be picked into seam cluster instead of original seam point on the same layer
|
||||
static constexpr float seam_align_score_tolerance = 0.3f;
|
||||
// seam_align_tolerable_dist_factor - how far to search for seam from current position, final dist is seam_align_tolerable_dist_factor * flow_width
|
||||
static constexpr float seam_align_tolerable_dist_factor = 4.0f;
|
||||
// minimum number of seams needed in cluster to make alignment happen
|
||||
static constexpr size_t seam_align_minimum_string_seams = 6;
|
||||
// millimeters covered by spline; determines number of splines for the given string
|
||||
static constexpr size_t seam_align_mm_per_segment = 4.0f;
|
||||
// When searching for seam clusters for alignment:
|
||||
// following value describes, how much worse score can point have and still be picked into seam cluster instead of original seam point on the same layer
|
||||
static constexpr float seam_align_score_tolerance = 0.3f;
|
||||
// seam_align_tolerable_dist_factor - how far to search for seam from current position, final dist is seam_align_tolerable_dist_factor * flow_width
|
||||
static constexpr float seam_align_tolerable_dist_factor = 4.0f;
|
||||
// minimum number of seams needed in cluster to make alignment happen
|
||||
static constexpr size_t seam_align_minimum_string_seams = 6;
|
||||
// millimeters covered by spline; determines number of splines for the given string
|
||||
static constexpr size_t seam_align_mm_per_segment = 4.0f;
|
||||
|
||||
//The following data structures hold all perimeter points for all PrintObject.
|
||||
std::unordered_map<const PrintObject*, PrintObjectSeamData> m_seam_per_object;
|
||||
// The following data structures hold all perimeter points for all PrintObject.
|
||||
std::unordered_map<const PrintObject *, PrintObjectSeamData> m_seam_per_object;
|
||||
|
||||
void init(const Print &print, std::function<void(void)> throw_if_canceled_func);
|
||||
void init(const Print &print, std::function<void(void)> throw_if_canceled_func);
|
||||
|
||||
void place_seam(const Layer *layer, ExtrusionLoop &loop, bool external_first, const Point &last_pos) const;
|
||||
void place_seam(const Layer *layer, ExtrusionLoop &loop, bool external_first, const Point &last_pos) const;
|
||||
|
||||
private:
|
||||
void gather_seam_candidates(const PrintObject *po, const SeamPlacerImpl::GlobalModelInfo &global_model_info);
|
||||
void calculate_candidates_visibility(const PrintObject *po,
|
||||
const SeamPlacerImpl::GlobalModelInfo &global_model_info);
|
||||
void calculate_overhangs_and_layer_embedding(const PrintObject *po);
|
||||
void align_seam_points(const PrintObject *po, const SeamPlacerImpl::SeamComparator &comparator);
|
||||
std::vector<std::pair<size_t, size_t>> find_seam_string(const PrintObject *po,
|
||||
std::pair<size_t, size_t> start_seam,
|
||||
const SeamPlacerImpl::SeamComparator &comparator) const;
|
||||
std::optional<std::pair<size_t, size_t>> find_next_seam_in_layer(
|
||||
const std::vector<PrintObjectSeamData::LayerSeams> &layers,
|
||||
const Vec3f& projected_position,
|
||||
const size_t layer_idx, const float max_distance,
|
||||
const SeamPlacerImpl::SeamComparator &comparator) const;
|
||||
void gather_seam_candidates(const PrintObject *po, const SeamPlacerImpl::GlobalModelInfo &global_model_info, const SeamPosition configured_seam_preference);
|
||||
void calculate_candidates_visibility(const PrintObject *po, const SeamPlacerImpl::GlobalModelInfo &global_model_info);
|
||||
void calculate_overhangs_and_layer_embedding(const PrintObject *po);
|
||||
void align_seam_points(const PrintObject *po, const SeamPlacerImpl::SeamComparator &comparator);
|
||||
std::vector<std::pair<size_t, size_t>> find_seam_string(const PrintObject *po, std::pair<size_t, size_t> start_seam, const SeamPlacerImpl::SeamComparator &comparator) const;
|
||||
std::optional<std::pair<size_t, size_t>> find_next_seam_in_layer(const std::vector<PrintObjectSeamData::LayerSeams> &layers,
|
||||
const Vec3f & projected_position,
|
||||
const size_t layer_idx,
|
||||
const float max_distance,
|
||||
const SeamPlacerImpl::SeamComparator & comparator) const;
|
||||
};
|
||||
|
||||
} // namespace Slic3r
|
||||
|
|
|
|||
|
|
@ -388,6 +388,11 @@ void ToolOrdering::collect_extruders(const PrintObject &object, const std::vecto
|
|||
it_per_layer_extruder_override = per_layer_extruder_switches.begin();
|
||||
unsigned int extruder_override = 0;
|
||||
|
||||
// BBS: collect first layer extruders of an object's wall, which will be used by brim generator
|
||||
int layerCount = 0;
|
||||
std::vector<int> firstLayerExtruders;
|
||||
firstLayerExtruders.clear();
|
||||
|
||||
// Collect the object extruders.
|
||||
for (auto layer : object.layers()) {
|
||||
LayerTools &layer_tools = this->tools_for_layer(layer->print_z);
|
||||
|
|
@ -413,8 +418,12 @@ void ToolOrdering::collect_extruders(const PrintObject &object, const std::vecto
|
|||
something_nonoverriddable = true;
|
||||
}
|
||||
|
||||
if (something_nonoverriddable)
|
||||
if (something_nonoverriddable){
|
||||
layer_tools.extruders.emplace_back((extruder_override == 0) ? region.config().wall_filament.value : extruder_override);
|
||||
if (layerCount == 0) {
|
||||
firstLayerExtruders.emplace_back((extruder_override == 0) ? region.config().wall_filament.value : extruder_override);
|
||||
}
|
||||
}
|
||||
|
||||
layer_tools.has_object = true;
|
||||
}
|
||||
|
|
@ -449,8 +458,12 @@ void ToolOrdering::collect_extruders(const PrintObject &object, const std::vecto
|
|||
if (has_solid_infill || has_infill)
|
||||
layer_tools.has_object = true;
|
||||
}
|
||||
layerCount++;
|
||||
}
|
||||
|
||||
sort_remove_duplicates(firstLayerExtruders);
|
||||
const_cast<PrintObject&>(object).object_first_layer_wall_extruders = firstLayerExtruders;
|
||||
|
||||
for (auto& layer : m_layer_tools) {
|
||||
// Sort and remove duplicates
|
||||
sort_remove_duplicates(layer.extruders);
|
||||
|
|
@ -1027,8 +1040,7 @@ float WipingExtrusions::mark_wiping_extrusions(const Print& print, unsigned int
|
|||
if (!object->config().flush_into_infill && !object->config().flush_into_objects && !object->config().flush_into_support)
|
||||
continue;
|
||||
bool wipe_into_infill_only = !object->config().flush_into_objects && object->config().flush_into_infill;
|
||||
bool is_infill_first = print.default_region_config().wall_infill_order == WallInfillOrder::InfillInnerOuter ||
|
||||
print.default_region_config().wall_infill_order == WallInfillOrder::InfillOuterInner;
|
||||
bool is_infill_first = print.config().is_infill_first;
|
||||
if (is_infill_first != perimeters_done || wipe_into_infill_only) {
|
||||
for (const ExtrusionEntity* ee : layerm->fills.entities) { // iterate through all infill Collections
|
||||
auto* fill = dynamic_cast<const ExtrusionEntityCollection*>(ee);
|
||||
|
|
@ -1082,7 +1094,7 @@ float WipingExtrusions::mark_wiping_extrusions(const Print& print, unsigned int
|
|||
break;
|
||||
|
||||
auto &entities = this_support_layer->support_fills.entities;
|
||||
if (support_overriddable && !is_support_overridden(object)) {
|
||||
if (support_overriddable && !is_support_overridden(object) && !(object_config.support_interface_not_for_body.value && !support_intf_overriddable &&(new_extruder==object_config.support_interface_filament-1||old_extruder==object_config.support_interface_filament-1))) {
|
||||
set_support_extruder_override(object, copy, new_extruder, num_of_copies);
|
||||
for (const ExtrusionEntity* ee : entities) {
|
||||
if (ee->role() == erSupportMaterial || ee->role() == erSupportTransition)
|
||||
|
|
@ -1141,8 +1153,7 @@ void WipingExtrusions::ensure_perimeters_infills_order(const Print& print)
|
|||
if (!object->config().flush_into_infill && !object->config().flush_into_objects)
|
||||
continue;
|
||||
|
||||
bool is_infill_first = print.default_region_config().wall_infill_order == WallInfillOrder::InfillInnerOuter ||
|
||||
print.default_region_config().wall_infill_order == WallInfillOrder::InfillOuterInner;
|
||||
bool is_infill_first = print.config().is_infill_first;
|
||||
for (const ExtrusionEntity* ee : layerm->fills.entities) { // iterate through all infill Collections
|
||||
auto* fill = dynamic_cast<const ExtrusionEntityCollection*>(ee);
|
||||
|
||||
|
|
|
|||
|
|
@ -770,6 +770,7 @@ WipeTower::ToolChangeResult WipeTower::tool_change(size_t tool, bool extrude_per
|
|||
"; CP TOOLCHANGE START\n")
|
||||
.comment_with_value(" toolchange #", m_num_tool_changes + 1); // the number is zero-based
|
||||
|
||||
|
||||
if (tool != (unsigned)(-1))
|
||||
writer.append(std::string("; material : " + (m_current_tool < m_filpar.size() ? m_filpar[m_current_tool].material : "(NONE)") + " -> " + m_filpar[tool].material + "\n").c_str())
|
||||
.append(";--------------------\n");
|
||||
|
|
@ -787,6 +788,7 @@ WipeTower::ToolChangeResult WipeTower::tool_change(size_t tool, bool extrude_per
|
|||
|
||||
// Ram the hot material out of the melt zone, retract the filament into the cooling tubes and let it cool.
|
||||
if (tool != (unsigned int)-1){ // This is not the last change.
|
||||
writer.append(";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Wipe_Tower_Start) + "\n");
|
||||
toolchange_Unload(writer, cleaning_box, m_filpar[m_current_tool].material,
|
||||
is_first_layer() ? m_filpar[tool].nozzle_temperature_initial_layer : m_filpar[tool].nozzle_temperature);
|
||||
toolchange_Change(writer, tool, m_filpar[tool].material); // Change the tool, set a speed override for soluble and flex materials.
|
||||
|
|
@ -806,8 +808,8 @@ WipeTower::ToolChangeResult WipeTower::tool_change(size_t tool, bool extrude_per
|
|||
writer.travel(Vec2f(0, 0));
|
||||
writer.travel(initial_position);
|
||||
}
|
||||
|
||||
toolchange_Wipe(writer, cleaning_box, wipe_length); // Wipe the newly loaded filament until the end of the assigned wipe area.
|
||||
writer.append(";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Wipe_Tower_End) + "\n");
|
||||
++ m_num_tool_changes;
|
||||
} else
|
||||
toolchange_Unload(writer, cleaning_box, m_filpar[m_current_tool].material, m_filpar[m_current_tool].nozzle_temperature);
|
||||
|
|
@ -1185,6 +1187,7 @@ WipeTower::ToolChangeResult WipeTower::finish_layer(bool extrude_perimeter, bool
|
|||
.set_initial_tool(m_current_tool)
|
||||
.set_y_shift(m_y_shift - (m_current_shape == SHAPE_REVERSED ? m_layer_info->toolchanges_depth() : 0.f));
|
||||
|
||||
writer.append(";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Wipe_Tower_Start) + "\n");
|
||||
|
||||
// Slow down on the 1st layer.
|
||||
bool first_layer = is_first_layer();
|
||||
|
|
@ -1324,6 +1327,7 @@ WipeTower::ToolChangeResult WipeTower::finish_layer(bool extrude_perimeter, bool
|
|||
writer.add_wipe_point(writer.pos())
|
||||
.add_wipe_point(target);
|
||||
|
||||
writer.append(";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Wipe_Tower_End) + "\n");
|
||||
|
||||
// Ask our writer about how much material was consumed.
|
||||
// Skip this in case the layer is sparse and config option to not print sparse layers is enabled.
|
||||
|
|
@ -1601,6 +1605,9 @@ void WipeTower::generate(std::vector<std::vector<WipeTower::ToolChangeResult>> &
|
|||
// BBS
|
||||
//m_internal_rotation += 180.f;
|
||||
|
||||
if (m_layer_info->depth < m_perimeter_width)
|
||||
continue;
|
||||
|
||||
if (m_layer_info->depth < m_wipe_tower_depth - m_perimeter_width) {
|
||||
// align y shift to perimeter width
|
||||
float dy = m_extra_spacing * m_perimeter_width;
|
||||
|
|
@ -1687,7 +1694,7 @@ WipeTower::ToolChangeResult WipeTower::only_generate_out_wall()
|
|||
// BBS: Delete some unnecessary travel
|
||||
//if (writer.x() > fill_box.ld.x() + EPSILON) writer.travel(fill_box.ld.x(), writer.y());
|
||||
//if (writer.y() > fill_box.ld.y() + EPSILON) writer.travel(writer.x(), fill_box.ld.y());
|
||||
|
||||
writer.append(";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Wipe_Tower_Start) + "\n");
|
||||
// outer perimeter (always):
|
||||
// BBS
|
||||
box_coordinates wt_box(Vec2f(0.f, (m_current_shape == SHAPE_REVERSED ? m_layer_info->toolchanges_depth() : 0.f)), m_wipe_tower_width, m_layer_info->depth + m_perimeter_width);
|
||||
|
|
@ -1698,6 +1705,8 @@ WipeTower::ToolChangeResult WipeTower::only_generate_out_wall()
|
|||
Vec2f target = (writer.pos() == wt_box.ld ? wt_box.rd : (writer.pos() == wt_box.rd ? wt_box.ru : (writer.pos() == wt_box.ru ? wt_box.lu : wt_box.ld)));
|
||||
writer.add_wipe_point(writer.pos()).add_wipe_point(target);
|
||||
|
||||
writer.append(";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Wipe_Tower_End) + "\n");
|
||||
|
||||
// Ask our writer about how much material was consumed.
|
||||
// Skip this in case the layer is sparse and config option to not print sparse layers is enabled.
|
||||
if (!m_no_sparse_layers || toolchanges_on_layer)
|
||||
|
|
|
|||
349
src/libslic3r/JumpPointSearch.cpp
Normal file
349
src/libslic3r/JumpPointSearch.cpp
Normal file
|
|
@ -0,0 +1,349 @@
|
|||
#include "JumpPointSearch.hpp"
|
||||
#include "BoundingBox.hpp"
|
||||
#include "ExPolygon.hpp"
|
||||
#include "Point.hpp"
|
||||
#include "libslic3r/AStar.hpp"
|
||||
#include "libslic3r/KDTreeIndirect.hpp"
|
||||
#include "libslic3r/Polygon.hpp"
|
||||
#include "libslic3r/Polyline.hpp"
|
||||
#include "libslic3r/libslic3r.h"
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include <oneapi/tbb/scalable_allocator.h>
|
||||
|
||||
//#define DEBUG_FILES
|
||||
#ifdef DEBUG_FILES
|
||||
#include "libslic3r/SVG.hpp"
|
||||
#endif
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
// execute fn for each pixel on the line. If fn returns false, terminate the iteration
|
||||
template<typename PointFn> void dda(coord_t x0, coord_t y0, coord_t x1, coord_t y1, const PointFn &fn)
|
||||
{
|
||||
coord_t dx = abs(x1 - x0);
|
||||
coord_t dy = abs(y1 - y0);
|
||||
coord_t x = x0;
|
||||
coord_t y = y0;
|
||||
coord_t n = 1 + dx + dy;
|
||||
coord_t x_inc = (x1 > x0) ? 1 : -1;
|
||||
coord_t y_inc = (y1 > y0) ? 1 : -1;
|
||||
coord_t error = dx - dy;
|
||||
dx *= 2;
|
||||
dy *= 2;
|
||||
|
||||
for (; n > 0; --n) {
|
||||
if (!fn(x, y)) return;
|
||||
|
||||
if (error > 0) {
|
||||
x += x_inc;
|
||||
error -= dy;
|
||||
} else {
|
||||
y += y_inc;
|
||||
error += dx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// will draw the line twice, second time with and offset of 1 in the direction of normal
|
||||
// may call the fn on the same coordiantes multiple times!
|
||||
template<typename PointFn> void double_dda_with_offset(coord_t x0, coord_t y0, coord_t x1, coord_t y1, const PointFn &fn)
|
||||
{
|
||||
Vec2d normal = Point{y1 - y0, x1 - x0}.cast<double>().normalized();
|
||||
normal.x() = ceil(normal.x());
|
||||
normal.y() = ceil(normal.y());
|
||||
Point start_offset = Point(x0, y0) + (normal).cast<coord_t>();
|
||||
Point end_offset = Point(x1, y1) + (normal).cast<coord_t>();
|
||||
|
||||
dda(x0, y0, x1, y1, fn);
|
||||
dda(start_offset.x(), start_offset.y(), end_offset.x(), end_offset.y(), fn);
|
||||
}
|
||||
|
||||
template<typename CellPositionType, typename CellQueryFn> class JPSTracer
|
||||
{
|
||||
public:
|
||||
// Use incoming_dir [0,0] for starting points, so that all directions are checked from that point
|
||||
struct Node
|
||||
{
|
||||
CellPositionType position;
|
||||
CellPositionType incoming_dir;
|
||||
};
|
||||
|
||||
JPSTracer(CellPositionType target, CellQueryFn is_passable) : target(target), is_passable(is_passable) {}
|
||||
|
||||
private:
|
||||
CellPositionType target;
|
||||
CellQueryFn is_passable; // should return boolean whether the cell is passable or not
|
||||
|
||||
CellPositionType find_jump_point(CellPositionType start, CellPositionType forward_dir) const
|
||||
{
|
||||
CellPositionType next = start + forward_dir;
|
||||
while (next != target && is_passable(next) && !(is_jump_point(next, forward_dir))) { next = next + forward_dir; }
|
||||
|
||||
if (is_passable(next)) {
|
||||
return next;
|
||||
} else {
|
||||
return start;
|
||||
}
|
||||
}
|
||||
|
||||
bool is_jump_point(CellPositionType pos, CellPositionType forward_dir) const
|
||||
{
|
||||
if (abs(forward_dir.x()) + abs(forward_dir.y()) == 2) {
|
||||
// diagonal
|
||||
CellPositionType horizontal_check_dir = CellPositionType{forward_dir.x(), 0};
|
||||
CellPositionType vertical_check_dir = CellPositionType{0, forward_dir.y()};
|
||||
|
||||
if (!is_passable(pos - horizontal_check_dir) && is_passable(pos + forward_dir - 2 * horizontal_check_dir)) { return true; }
|
||||
|
||||
if (!is_passable(pos - vertical_check_dir) && is_passable(pos + forward_dir - 2 * vertical_check_dir)) { return true; }
|
||||
|
||||
if (find_jump_point(pos, horizontal_check_dir) != pos) { return true; }
|
||||
|
||||
if (find_jump_point(pos, vertical_check_dir) != pos) { return true; }
|
||||
|
||||
return false;
|
||||
} else { // horizontal or vertical
|
||||
CellPositionType side_dir = CellPositionType(forward_dir.y(), forward_dir.x());
|
||||
|
||||
if (!is_passable(pos + side_dir) && is_passable(pos + forward_dir + side_dir)) { return true; }
|
||||
|
||||
if (!is_passable(pos - side_dir) && is_passable(pos + forward_dir - side_dir)) { return true; }
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
template<class Fn> void foreach_reachable(const Node &from, Fn &&fn) const
|
||||
{
|
||||
const CellPositionType & pos = from.position;
|
||||
const CellPositionType & forward_dir = from.incoming_dir;
|
||||
std::vector<CellPositionType> dirs_to_check{};
|
||||
|
||||
if (abs(forward_dir.x()) + abs(forward_dir.y()) == 0) { // special case for starting point
|
||||
dirs_to_check = all_directions;
|
||||
} else if (abs(forward_dir.x()) + abs(forward_dir.y()) == 2) {
|
||||
// diagonal
|
||||
CellPositionType horizontal_check_dir = CellPositionType{forward_dir.x(), 0};
|
||||
CellPositionType vertical_check_dir = CellPositionType{0, forward_dir.y()};
|
||||
|
||||
if (!is_passable(pos - horizontal_check_dir) && is_passable(pos + forward_dir - 2 * horizontal_check_dir)) {
|
||||
dirs_to_check.push_back(forward_dir - 2 * horizontal_check_dir);
|
||||
}
|
||||
|
||||
if (!is_passable(pos - vertical_check_dir) && is_passable(pos + forward_dir - 2 * vertical_check_dir)) {
|
||||
dirs_to_check.push_back(forward_dir - 2 * vertical_check_dir);
|
||||
}
|
||||
|
||||
dirs_to_check.push_back(horizontal_check_dir);
|
||||
dirs_to_check.push_back(vertical_check_dir);
|
||||
dirs_to_check.push_back(forward_dir);
|
||||
|
||||
} else { // horizontal or vertical
|
||||
CellPositionType side_dir = CellPositionType(forward_dir.y(), forward_dir.x());
|
||||
|
||||
if (!is_passable(pos + side_dir) && is_passable(pos + forward_dir + side_dir)) { dirs_to_check.push_back(forward_dir + side_dir); }
|
||||
|
||||
if (!is_passable(pos - side_dir) && is_passable(pos + forward_dir - side_dir)) { dirs_to_check.push_back(forward_dir - side_dir); }
|
||||
dirs_to_check.push_back(forward_dir);
|
||||
}
|
||||
|
||||
for (const CellPositionType &dir : dirs_to_check) {
|
||||
CellPositionType jp = find_jump_point(pos, dir);
|
||||
if (jp != pos) fn(Node{jp, dir});
|
||||
}
|
||||
}
|
||||
|
||||
float distance(Node a, Node b) const { return (a.position - b.position).template cast<double>().norm(); }
|
||||
|
||||
float goal_heuristic(Node n) const { return n.position == target ? -1.f : (target - n.position).template cast<double>().norm(); }
|
||||
|
||||
size_t unique_id(Node n) const { return (static_cast<size_t>(uint16_t(n.position.x())) << 16) + static_cast<size_t>(uint16_t(n.position.y())); }
|
||||
|
||||
const std::vector<CellPositionType> all_directions{{1, 0}, {1, 1}, {0, 1}, {-1, 1}, {-1, 0}, {-1, -1}, {0, -1}, {1, -1}};
|
||||
};
|
||||
|
||||
void JPSPathFinder::clear()
|
||||
{
|
||||
inpassable.clear();
|
||||
max_search_box.max = Pixel(std::numeric_limits<coord_t>::min(), std::numeric_limits<coord_t>::min());
|
||||
max_search_box.min = Pixel(std::numeric_limits<coord_t>::max(), std::numeric_limits<coord_t>::max());
|
||||
add_obstacles(bed_shape);
|
||||
}
|
||||
|
||||
void JPSPathFinder::add_obstacles(const Lines &obstacles)
|
||||
{
|
||||
auto store_obstacle = [&](coord_t x, coord_t y) {
|
||||
max_search_box.max.x() = std::max(max_search_box.max.x(), x);
|
||||
max_search_box.max.y() = std::max(max_search_box.max.y(), y);
|
||||
max_search_box.min.x() = std::min(max_search_box.min.x(), x);
|
||||
max_search_box.min.y() = std::min(max_search_box.min.y(), y);
|
||||
inpassable.insert(Pixel{x, y});
|
||||
return true;
|
||||
};
|
||||
|
||||
for (const Line &l : obstacles) {
|
||||
Pixel start = pixelize(l.a);
|
||||
Pixel end = pixelize(l.b);
|
||||
double_dda_with_offset(start.x(), start.y(), end.x(), end.y(), store_obstacle);
|
||||
}
|
||||
}
|
||||
|
||||
Polyline JPSPathFinder::find_path(const Point &p0, const Point &p1)
|
||||
{
|
||||
Pixel start = pixelize(p0);
|
||||
Pixel end = pixelize(p1);
|
||||
if (inpassable.empty() || (start - end).cast<float>().norm() < 3.0) { return Polyline{p0, p1}; }
|
||||
|
||||
if (inpassable.find(start) != inpassable.end()) {
|
||||
dda(start.x(), start.y(), end.x(), end.y(), [&](coord_t x, coord_t y) {
|
||||
if (inpassable.find(Pixel(x, y)) == inpassable.end() || start == end) { // new start not found yet, and xy passable
|
||||
start = Pixel(x, y);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
if (inpassable.find(end) != inpassable.end()) {
|
||||
dda(end.x(), end.y(), start.x(), start.y(), [&](coord_t x, coord_t y) {
|
||||
if (inpassable.find(Pixel(x, y)) == inpassable.end() || start == end) { // new start not found yet, and xy passable
|
||||
end = Pixel(x, y);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
BoundingBox search_box = max_search_box;
|
||||
search_box.max -= Pixel(1, 1);
|
||||
search_box.min += Pixel(1, 1);
|
||||
|
||||
BoundingBox bounding_square(Points{start, end});
|
||||
bounding_square.max += Pixel(5, 5);
|
||||
bounding_square.min -= Pixel(5, 5);
|
||||
coord_t bounding_square_size = 2 * std::max(bounding_square.size().x(), bounding_square.size().y());
|
||||
bounding_square.max.x() += (bounding_square_size - bounding_square.size().x()) / 2;
|
||||
bounding_square.min.x() -= (bounding_square_size - bounding_square.size().x()) / 2;
|
||||
bounding_square.max.y() += (bounding_square_size - bounding_square.size().y()) / 2;
|
||||
bounding_square.min.y() -= (bounding_square_size - bounding_square.size().y()) / 2;
|
||||
|
||||
// Intersection - limit the search box to a square area around the start and end, to fasten the path searching
|
||||
search_box.max = search_box.max.cwiseMin(bounding_square.max);
|
||||
search_box.min = search_box.min.cwiseMax(bounding_square.min);
|
||||
|
||||
auto cell_query = [&](Pixel pixel) { return search_box.contains(pixel) && (pixel == start || pixel == end || inpassable.find(pixel) == inpassable.end()); };
|
||||
|
||||
JPSTracer<Pixel, decltype(cell_query)> tracer(end, cell_query);
|
||||
using QNode = astar::QNode<JPSTracer<Pixel, decltype(cell_query)>>;
|
||||
|
||||
std::unordered_map<size_t, QNode> astar_cache{};
|
||||
std::vector<Pixel> out_path;
|
||||
std::vector<decltype(tracer)::Node> out_nodes;
|
||||
|
||||
if (!astar::search_route(tracer, {start, {0, 0}}, std::back_inserter(out_nodes), astar_cache)) {
|
||||
// path not found - just reconstruct the best path from astar cache.
|
||||
// Note that astar_cache is NOT empty - at least the starting point should always be there
|
||||
auto coordiante_func = [&astar_cache](size_t idx, size_t dim) { return float(astar_cache[idx].node.position[dim]); };
|
||||
std::vector<size_t> keys;
|
||||
keys.reserve(astar_cache.size());
|
||||
for (const auto &pair : astar_cache) { keys.push_back(pair.first); }
|
||||
KDTreeIndirect<2, float, decltype(coordiante_func)> kd_tree(coordiante_func, keys);
|
||||
size_t closest_qnode = find_closest_point(kd_tree, end.cast<float>());
|
||||
|
||||
out_path.push_back(end);
|
||||
while (closest_qnode != astar::Unassigned) {
|
||||
out_path.push_back(astar_cache[closest_qnode].node.position);
|
||||
closest_qnode = astar_cache[closest_qnode].parent;
|
||||
}
|
||||
} else {
|
||||
for (const auto &node : out_nodes) { out_path.push_back(node.position); }
|
||||
out_path.push_back(start);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_FILES
|
||||
auto scaled_points = [](const Points &ps) {
|
||||
Points r;
|
||||
for (const Point &p : ps) { r.push_back(Point::new_scale(p.x(), p.y())); }
|
||||
return r;
|
||||
};
|
||||
auto scaled_point = [](const Point &p) { return Point::new_scale(p.x(), p.y()); };
|
||||
::Slic3r::SVG svg(debug_out_path(("path_jps" + std::to_string(print_z) + "_" + std::to_string(rand() % 1000)).c_str()).c_str(),
|
||||
BoundingBox(scaled_point(search_box.min), scaled_point(search_box.max)));
|
||||
for (const auto &p : inpassable) { svg.draw(scaled_point(p), "black", scale_(0.4)); }
|
||||
for (const auto &qn : astar_cache) { svg.draw(scaled_point(qn.second.node.position), "blue", scale_(0.3)); }
|
||||
svg.draw(Polyline(scaled_points(out_path)), "yellow", scale_(0.25));
|
||||
svg.draw(scaled_point(end), "purple", scale_(0.4));
|
||||
svg.draw(scaled_point(start), "green", scale_(0.4));
|
||||
#endif
|
||||
|
||||
std::vector<Pixel> tmp_path;
|
||||
tmp_path.reserve(out_path.size());
|
||||
// Some path found, reverse and remove points that do not change direction
|
||||
std::reverse(out_path.begin(), out_path.end());
|
||||
{
|
||||
tmp_path.push_back(out_path.front()); // first point
|
||||
for (size_t i = 1; i < out_path.size() - 1; i++) {
|
||||
if ((out_path[i] - out_path[i - 1]).cast<float>().normalized() != (out_path[i + 1] - out_path[i]).cast<float>().normalized()) { tmp_path.push_back(out_path[i]); }
|
||||
}
|
||||
tmp_path.push_back(out_path.back()); // last_point
|
||||
out_path = tmp_path;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_FILES
|
||||
svg.draw(Polyline(scaled_points(out_path)), "orange", scale_(0.20));
|
||||
#endif
|
||||
|
||||
tmp_path.clear();
|
||||
// remove redundant jump points - there are points that change direction but are not needed - this inefficiency arises from the
|
||||
// usage of grid search The removal alg tries to find the longest Px Px+k path without obstacles. If Px Px+k+1 is blocked, it will
|
||||
// insert the Px+k point to result and continue search from Px+k
|
||||
{
|
||||
tmp_path.push_back(out_path.front()); // first point
|
||||
size_t index_of_last_stored_point = 0;
|
||||
for (size_t i = 1; i < out_path.size(); i++) {
|
||||
if (i - index_of_last_stored_point < 2) continue;
|
||||
bool passable = true;
|
||||
auto store_obstacle = [&](coord_t x, coord_t y) {
|
||||
if (Pixel(x, y) != start && Pixel(x, y) != end && inpassable.find(Pixel(x, y)) != inpassable.end()) {
|
||||
passable = false;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
dda(tmp_path.back().x(), tmp_path.back().y(), out_path[i].x(), out_path[i].y(), store_obstacle);
|
||||
if (!passable) {
|
||||
tmp_path.push_back(out_path[i - 1]);
|
||||
index_of_last_stored_point = i - 1;
|
||||
}
|
||||
}
|
||||
tmp_path.push_back(out_path.back()); // last_point
|
||||
out_path = tmp_path;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_FILES
|
||||
svg.draw(Polyline(scaled_points(out_path)), "red", scale_(0.15));
|
||||
svg.Close();
|
||||
#endif
|
||||
|
||||
// before returing the path, transform it from pixels back to points.
|
||||
// Also replace the first and last pixel by input points so that result path patches input params exactly.
|
||||
for (Pixel &p : out_path) { p = unpixelize(p); }
|
||||
out_path.front() = p0;
|
||||
out_path.back() = p1;
|
||||
|
||||
return Polyline(out_path);
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
38
src/libslic3r/JumpPointSearch.hpp
Normal file
38
src/libslic3r/JumpPointSearch.hpp
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
#pragma once
|
||||
#ifndef SRC_LIBSLIC3R_JUMPPOINTSEARCH_HPP_
|
||||
#define SRC_LIBSLIC3R_JUMPPOINTSEARCH_HPP_
|
||||
|
||||
#include "BoundingBox.hpp"
|
||||
#include "Polygon.hpp"
|
||||
#include "libslic3r/Layer.hpp"
|
||||
#include "libslic3r/Point.hpp"
|
||||
#include "libslic3r/Polyline.hpp"
|
||||
#include "libslic3r/libslic3r.h"
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
class JPSPathFinder
|
||||
{
|
||||
using Pixel = Point;
|
||||
std::unordered_set<Pixel, PointHash> inpassable;
|
||||
coordf_t print_z;
|
||||
BoundingBox max_search_box;
|
||||
Lines bed_shape;
|
||||
|
||||
const coord_t resolution = scaled(1.5);
|
||||
Pixel pixelize(const Point &p) { return p / resolution; }
|
||||
Point unpixelize(const Pixel &p) { return p * resolution; }
|
||||
|
||||
public:
|
||||
JPSPathFinder() = default;
|
||||
void init_bed_shape(const Points &bed_shape) { this->bed_shape = (to_lines(Polygon{bed_shape})); };
|
||||
void clear();
|
||||
void add_obstacles(const Lines &obstacles);
|
||||
Polyline find_path(const Point &start, const Point &end);
|
||||
};
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif /* SRC_LIBSLIC3R_JUMPPOINTSEARCH_HPP_ */
|
||||
|
|
@ -179,7 +179,6 @@ void Layer::make_perimeters()
|
|||
&& config.opt_serialize("inner_wall_line_width") == other_config.opt_serialize("inner_wall_line_width")
|
||||
&& config.opt_serialize("outer_wall_line_width") == other_config.opt_serialize("outer_wall_line_width")
|
||||
&& config.detect_thin_wall == other_config.detect_thin_wall
|
||||
//&& config.wall_infill_order == other_config.wall_infill_order
|
||||
&& config.infill_wall_overlap == other_config.infill_wall_overlap
|
||||
&& config.fuzzy_skin == other_config.fuzzy_skin
|
||||
&& config.fuzzy_skin_thickness == other_config.fuzzy_skin_thickness
|
||||
|
|
|
|||
|
|
@ -277,6 +277,7 @@ public:
|
|||
|
||||
// for tree supports
|
||||
ExPolygons base_areas;
|
||||
ExPolygons overhang_areas;
|
||||
|
||||
|
||||
// Is there any valid extrusion assigned to this LayerRegion?
|
||||
|
|
@ -300,7 +301,6 @@ protected:
|
|||
size_t m_interface_id;
|
||||
|
||||
// for tree support
|
||||
ExPolygons overhang_areas;
|
||||
ExPolygons roof_areas;
|
||||
ExPolygons roof_1st_layer; // the layer just below roof. When working with PolySupport, this layer should be printed with regular material
|
||||
ExPolygons floor_areas;
|
||||
|
|
@ -312,6 +312,7 @@ protected:
|
|||
int type;
|
||||
coordf_t dist_to_top; // mm dist to top
|
||||
bool need_infill = false;
|
||||
bool need_extra_wall = false;
|
||||
AreaGroup(ExPolygon *a, int t, coordf_t d) : area(a), type(t), dist_to_top(d) {}
|
||||
};
|
||||
enum OverhangType { Detected = 0, Enforced };
|
||||
|
|
|
|||
|
|
@ -223,6 +223,12 @@ indexed_triangle_set cgal_to_indexed_triangle_set(const _Mesh &cgalmesh)
|
|||
return its;
|
||||
}
|
||||
|
||||
template<class _Mesh> TriangleMesh cgal_to_triangle_mesh(const _Mesh &cgalmesh)
|
||||
{
|
||||
indexed_triangle_set its = cgal_to_indexed_triangle_set(cgalmesh);
|
||||
return TriangleMesh(std::move(its));
|
||||
}
|
||||
|
||||
std::unique_ptr<CGALMesh, CGALMeshDeleter>
|
||||
triangle_mesh_to_cgal(const std::vector<stl_vertex> &V,
|
||||
const std::vector<stl_triangle_vertex_indices> &F)
|
||||
|
|
|
|||
|
|
@ -97,9 +97,14 @@ Model& Model::assign_copy(const Model &rhs)
|
|||
);
|
||||
}
|
||||
|
||||
if (rhs.calib_pa_pattern) {
|
||||
this->calib_pa_pattern = std::make_unique<CalibPressureAdvancePattern>(CalibPressureAdvancePattern(*rhs.calib_pa_pattern));
|
||||
}
|
||||
|
||||
// BBS: for design info
|
||||
this->design_info = rhs.design_info;
|
||||
this->model_info = rhs.model_info;
|
||||
this->stl_design_id = rhs.stl_design_id;
|
||||
this->profile_info = rhs.profile_info;
|
||||
|
||||
return *this;
|
||||
|
|
@ -130,6 +135,7 @@ Model& Model::assign_copy(Model &&rhs)
|
|||
|
||||
//BBS: add auxiliary path logic
|
||||
// BBS: backup, all in one temp dir
|
||||
this->stl_design_id = rhs.stl_design_id;
|
||||
this->backup_path = std::move(rhs.backup_path);
|
||||
this->object_backup_id_map = std::move(rhs.object_backup_id_map);
|
||||
this->next_object_backup_id = rhs.next_object_backup_id;
|
||||
|
|
@ -927,6 +933,7 @@ void Model::load_from(Model& model)
|
|||
object_backup_id_map = model.object_backup_id_map;
|
||||
next_object_backup_id = model.next_object_backup_id;
|
||||
design_info = model.design_info;
|
||||
stl_design_id = model.stl_design_id;
|
||||
model_info = model.model_info;
|
||||
profile_info = model.profile_info;
|
||||
model.design_info.reset();
|
||||
|
|
|
|||
|
|
@ -245,6 +245,11 @@ private:
|
|||
friend class ModelObject;
|
||||
};
|
||||
|
||||
enum class CutMode : int {
|
||||
cutPlanar,
|
||||
cutTongueAndGroove
|
||||
};
|
||||
|
||||
enum class CutConnectorType : int {
|
||||
Plug
|
||||
, Dowel
|
||||
|
|
@ -267,6 +272,11 @@ enum class CutConnectorShape : int {
|
|||
, Undef
|
||||
//,D-shape
|
||||
};
|
||||
struct CutConnectorParas
|
||||
{
|
||||
float snap_space_proportion{0.3};
|
||||
float snap_bulge_proportion{0.15};
|
||||
};
|
||||
|
||||
struct CutConnectorAttributes
|
||||
{
|
||||
|
|
@ -904,8 +914,8 @@ public:
|
|||
bool is_support_blocker() const { return m_type == ModelVolumeType::SUPPORT_BLOCKER; }
|
||||
bool is_support_modifier() const { return m_type == ModelVolumeType::SUPPORT_BLOCKER || m_type == ModelVolumeType::SUPPORT_ENFORCER; }
|
||||
t_model_material_id material_id() const { return m_material_id; }
|
||||
void reset_extra_facets();
|
||||
void set_material_id(t_model_material_id material_id);
|
||||
void reset_extra_facets();
|
||||
ModelMaterial* material() const;
|
||||
void set_material(t_model_material_id material_id, const ModelMaterial &material);
|
||||
// Extract the current extruder ID based on this ModelVolume's config and the parent ModelObject's config.
|
||||
|
|
@ -1488,6 +1498,7 @@ public:
|
|||
static GlobalSpeedMap printSpeedMap;
|
||||
|
||||
// DesignInfo of Model
|
||||
std::string stl_design_id;
|
||||
std::shared_ptr<ModelDesignInfo> design_info = nullptr;
|
||||
std::shared_ptr<ModelInfo> model_info = nullptr;
|
||||
std::shared_ptr<ModelProfileInfo> profile_info = nullptr;
|
||||
|
|
|
|||
|
|
@ -1372,18 +1372,23 @@ static void remove_multiple_edges_in_vertices(MMU_Graph &graph, const std::vecto
|
|||
static void cut_segmented_layers(const std::vector<ExPolygons> &input_expolygons,
|
||||
std::vector<std::vector<ExPolygons>> &segmented_regions,
|
||||
const float cut_width,
|
||||
const float interlocking_depth,
|
||||
const std::function<void()> &throw_on_cancel_callback)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - cutting segmented layers in parallel - begin";
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, segmented_regions.size()),[&segmented_regions, &input_expolygons, &cut_width, &throw_on_cancel_callback](const tbb::blocked_range<size_t>& range) {
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, segmented_regions.size()),
|
||||
[&segmented_regions, &input_expolygons, &cut_width, &interlocking_depth, &throw_on_cancel_callback](const tbb::blocked_range<size_t> &range) {
|
||||
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) {
|
||||
throw_on_cancel_callback();
|
||||
const size_t num_extruders_plus_one = segmented_regions[layer_idx].size();
|
||||
std::vector<ExPolygons> segmented_regions_cuts(num_extruders_plus_one); // Indexed by extruder_id
|
||||
for (size_t extruder_idx = 0; extruder_idx < num_extruders_plus_one; ++extruder_idx)
|
||||
if (const ExPolygons &ex_polygons = segmented_regions[layer_idx][extruder_idx]; !ex_polygons.empty())
|
||||
segmented_regions_cuts[extruder_idx] = diff_ex(ex_polygons, offset_ex(input_expolygons[layer_idx], cut_width));
|
||||
segmented_regions[layer_idx] = std::move(segmented_regions_cuts);
|
||||
const float region_cut_width = ((layer_idx % 2 == 0) && (interlocking_depth != 0.f)) ? interlocking_depth : cut_width;
|
||||
const size_t num_extruders_plus_one = segmented_regions[layer_idx].size();
|
||||
if (region_cut_width > 0.f) {
|
||||
std::vector<ExPolygons> segmented_regions_cuts(num_extruders_plus_one); // Indexed by extruder_id
|
||||
for (size_t extruder_idx = 0; extruder_idx < num_extruders_plus_one; ++extruder_idx)
|
||||
if (const ExPolygons &ex_polygons = segmented_regions[layer_idx][extruder_idx]; !ex_polygons.empty())
|
||||
segmented_regions_cuts[extruder_idx] = diff_ex(ex_polygons, offset_ex(input_expolygons[layer_idx], -region_cut_width));
|
||||
segmented_regions[layer_idx] = std::move(segmented_regions_cuts);
|
||||
}
|
||||
}
|
||||
}); // end of parallel_for
|
||||
BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - cutting segmented layers in parallel - end";
|
||||
|
|
@ -1664,9 +1669,12 @@ static inline std::vector<std::vector<ExPolygons>> mmu_segmentation_top_and_bott
|
|||
self = union_ex(self);
|
||||
}
|
||||
// Trim one region by the other if some of the regions overlap.
|
||||
for (size_t color_idx = 1; color_idx < triangles_by_color_merged.size(); ++ color_idx)
|
||||
triangles_by_color_merged[color_idx][layer_idx] = diff_ex(triangles_by_color_merged[color_idx][layer_idx],
|
||||
triangles_by_color_merged[color_idx - 1][layer_idx]);
|
||||
ExPolygons painted_regions;
|
||||
for (size_t color_idx = 1; color_idx < triangles_by_color_merged.size(); ++color_idx) {
|
||||
triangles_by_color_merged[color_idx][layer_idx] = diff_ex(triangles_by_color_merged[color_idx][layer_idx], painted_regions);
|
||||
append(painted_regions, triangles_by_color_merged[color_idx][layer_idx]);
|
||||
}
|
||||
triangles_by_color_merged[0][layer_idx] = diff_ex(triangles_by_color_merged[0][layer_idx], painted_regions);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -2039,10 +2047,10 @@ std::vector<std::vector<ExPolygons>> multi_material_segmentation_by_painting(con
|
|||
BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - layers segmentation in parallel - end";
|
||||
throw_on_cancel_callback();
|
||||
|
||||
//if (auto w = print_object.config().mmu_segmented_region_max_width; w > 0.f) {
|
||||
// cut_segmented_layers(input_expolygons, segmented_regions, float(-scale_(w)), throw_on_cancel_callback);
|
||||
// throw_on_cancel_callback();
|
||||
//}
|
||||
if (auto max_width = print_object.config().mmu_segmented_region_max_width, interlocking_depth = print_object.config().mmu_segmented_region_interlocking_depth; max_width > 0.f || interlocking_depth > 0.f) {
|
||||
cut_segmented_layers(input_expolygons, segmented_regions, float(scale_(max_width)), float(scale_(interlocking_depth)), throw_on_cancel_callback);
|
||||
throw_on_cancel_callback();
|
||||
}
|
||||
|
||||
// The first index is extruder number (includes default extruder), and the second one is layer number
|
||||
std::vector<std::vector<ExPolygons>> top_and_bottom_layers = mmu_segmentation_top_and_bottom_layers(print_object, input_expolygons, throw_on_cancel_callback);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include <assert.h>
|
||||
#include <type_traits>
|
||||
|
||||
constexpr auto InvalidQueueID = std::numeric_limits<size_t>::max();
|
||||
template<typename T, typename IndexSetter, typename LessPredicate, const bool ResetIndexWhenRemoved = false>
|
||||
class MutablePriorityQueue
|
||||
{
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#include "ClipperUtils.hpp"
|
||||
#include "ExtrusionEntity.hpp"
|
||||
#include "ExtrusionEntityCollection.hpp"
|
||||
#include "PrintConfig.hpp"
|
||||
#include "ShortestPath.hpp"
|
||||
#include "VariableWidth.hpp"
|
||||
#include "CurveAnalyzer.hpp"
|
||||
|
|
@ -1495,12 +1496,18 @@ void PerimeterGenerator::process_classic()
|
|||
|
||||
// BBS: don't simplify too much which influence arc fitting when export gcode if arc_fitting is enabled
|
||||
double surface_simplify_resolution = (print_config->enable_arc_fitting && this->config->fuzzy_skin == FuzzySkinType::None) ? 0.2 * m_scaled_resolution : m_scaled_resolution;
|
||||
for (const Surface &surface : this->slices->surfaces) {
|
||||
//BBS: reorder the surface to reduce the travel time
|
||||
ExPolygons surface_exp;
|
||||
for (const Surface &surface : this->slices->surfaces)
|
||||
surface_exp.push_back(surface.expolygon);
|
||||
std::vector<size_t> surface_order = chain_expolygons(surface_exp);
|
||||
for (size_t order_idx = 0; order_idx < surface_order.size(); order_idx++) {
|
||||
const Surface &surface = this->slices->surfaces[surface_order[order_idx]];
|
||||
// detect how many perimeters must be generated for this island
|
||||
int loop_number = this->config->wall_loops + surface.extra_perimeters - 1; // 0-indexed loops
|
||||
if (this->layer_id == 0 && this->config->only_one_wall_first_layer)
|
||||
loop_number = 0;
|
||||
//BBS: set the topmost layer to be one wall
|
||||
// Set the topmost layer to be one wall
|
||||
if (loop_number > 0 && config->only_one_wall_top && this->upper_slices == nullptr)
|
||||
loop_number = 0;
|
||||
|
||||
|
|
@ -1723,8 +1730,8 @@ void PerimeterGenerator::process_classic()
|
|||
// we continue inwards after having finished the brim
|
||||
// TODO: add test for perimeter order
|
||||
bool is_outer_wall_first =
|
||||
this->config->wall_infill_order == WallInfillOrder::OuterInnerInfill ||
|
||||
this->config->wall_infill_order == WallInfillOrder::InfillOuterInner;
|
||||
this->object_config->wall_sequence == WallSequence::OuterInner ||
|
||||
this->object_config->wall_sequence == WallSequence::InnerOuterInner;
|
||||
if (is_outer_wall_first ||
|
||||
//BBS: always print outer wall first when there indeed has brim.
|
||||
(this->layer_id == 0 &&
|
||||
|
|
@ -1732,7 +1739,7 @@ void PerimeterGenerator::process_classic()
|
|||
this->object_config->brim_width.value > 0))
|
||||
entities.reverse();
|
||||
// SoftFever: sandwich mode
|
||||
else if (this->config->wall_infill_order == WallInfillOrder::InnerOuterInnerInfill)
|
||||
else if (this->object_config->wall_sequence == WallSequence::InnerOuterInner)
|
||||
if (entities.entities.size() > 1){
|
||||
int last_outer=0;
|
||||
int outer = 0;
|
||||
|
|
@ -1862,6 +1869,39 @@ void PerimeterGenerator::process_classic()
|
|||
} // for each island
|
||||
}
|
||||
|
||||
//BBS:
|
||||
void PerimeterGenerator::add_infill_contour_for_arachne( ExPolygons infill_contour,
|
||||
int loops,
|
||||
coord_t ext_perimeter_spacing,
|
||||
coord_t perimeter_spacing,
|
||||
coord_t min_perimeter_infill_spacing,
|
||||
coord_t spacing,
|
||||
bool is_inner_part)
|
||||
{
|
||||
if( offset_ex(infill_contour, -float(spacing / 2.)).empty() )
|
||||
{
|
||||
infill_contour.clear(); // Infill region is too small, so let's filter it out.
|
||||
}
|
||||
|
||||
// create one more offset to be used as boundary for fill
|
||||
// we offset by half the perimeter spacing (to get to the actual infill boundary)
|
||||
// and then we offset back and forth by half the infill spacing to only consider the
|
||||
// non-collapsing regions
|
||||
coord_t insert = (loops < 0) ? 0: ext_perimeter_spacing;
|
||||
if (is_inner_part || loops > 0)
|
||||
insert = perimeter_spacing;
|
||||
|
||||
insert = coord_t(scale_(this->config->infill_wall_overlap.get_abs_value(unscale<double>(insert))));
|
||||
|
||||
Polygons inner_pp;
|
||||
for (ExPolygon &ex : infill_contour)
|
||||
ex.simplify_p(m_scaled_resolution, &inner_pp);
|
||||
|
||||
this->fill_surfaces->append(offset2_ex(union_ex(inner_pp), float(-min_perimeter_infill_spacing / 2.), float(insert + min_perimeter_infill_spacing / 2.)), stInternal);
|
||||
|
||||
append(*this->fill_no_overlap, offset2_ex(union_ex(inner_pp), float(-min_perimeter_infill_spacing / 2.), float(+min_perimeter_infill_spacing / 2.)));
|
||||
}
|
||||
|
||||
// Thanks, Cura developers, for implementing an algorithm for generating perimeters with variable width (Arachne) that is based on the paper
|
||||
// "A framework for adaptive width control of dense contour-parallel toolpaths in fused deposition modeling"
|
||||
void PerimeterGenerator::process_arachne()
|
||||
|
|
@ -1973,7 +2013,7 @@ void PerimeterGenerator::process_arachne()
|
|||
}
|
||||
loop_number = int(perimeters.size()) - 1;
|
||||
|
||||
#ifdef ARACHNE_DEBUG
|
||||
#ifdef ARACHNE_DEBUG
|
||||
{
|
||||
static int iRun = 0;
|
||||
export_perimeters_to_svg(debug_out_path("arachne-perimeters-%d-%d.svg", layer_id, iRun++), to_polygons(last), perimeters, union_ex(wallToolPaths.getInnerContour()));
|
||||
|
|
@ -1996,14 +2036,12 @@ void PerimeterGenerator::process_arachne()
|
|||
int direction = -1;
|
||||
|
||||
bool is_outer_wall_first =
|
||||
this->config->wall_infill_order == WallInfillOrder::OuterInnerInfill ||
|
||||
this->config->wall_infill_order == WallInfillOrder::InfillOuterInner ||
|
||||
this->config->wall_infill_order == WallInfillOrder::InnerOuterInnerInfill;
|
||||
this->object_config->wall_sequence == WallSequence::OuterInner ||
|
||||
this->object_config->wall_sequence == WallSequence::InnerOuterInner;
|
||||
|
||||
if (layer_id == 0){ // disable inner outer inner algorithm after the first layer
|
||||
is_outer_wall_first =
|
||||
this->config->wall_infill_order == WallInfillOrder::OuterInnerInfill ||
|
||||
this->config->wall_infill_order == WallInfillOrder::InfillOuterInner;
|
||||
this->object_config->wall_sequence == WallSequence::OuterInner;
|
||||
}
|
||||
if (is_outer_wall_first) {
|
||||
start_perimeter = 0;
|
||||
|
|
@ -2242,8 +2280,9 @@ void PerimeterGenerator::process_arachne()
|
|||
this->loops->append(extrusion_coll);
|
||||
}
|
||||
|
||||
ExPolygons infill_contour = union_ex(wallToolPaths.getInnerContour());
|
||||
ExPolygons infill_contour = union_ex(wallToolPaths.getInnerContour());
|
||||
const coord_t spacing = (perimeters.size() == 1) ? ext_perimeter_spacing2 : perimeter_spacing;
|
||||
|
||||
if (offset_ex(infill_contour, -float(spacing / 2.)).empty())
|
||||
infill_contour.clear(); // Infill region is too small, so let's filter it out.
|
||||
|
||||
|
|
|
|||
|
|
@ -69,6 +69,8 @@ public:
|
|||
void process_classic();
|
||||
void process_arachne();
|
||||
|
||||
void add_infill_contour_for_arachne( ExPolygons infill_contour, int loops, coord_t ext_perimeter_spacing, coord_t perimeter_spacing, coord_t min_perimeter_infill_spacing, coord_t spacing, bool is_inner_part );
|
||||
|
||||
double ext_mm3_per_mm() const { return m_ext_mm3_per_mm; }
|
||||
double mm3_per_mm() const { return m_mm3_per_mm; }
|
||||
double mm3_per_mm_overhang() const { return m_mm3_per_mm_overhang; }
|
||||
|
|
|
|||
|
|
@ -83,6 +83,7 @@ using Transform2d = Eigen::Transform<double, 2, Eigen::Affine, Eigen::DontAli
|
|||
using Transform3f = Eigen::Transform<float, 3, Eigen::Affine, Eigen::DontAlign>;
|
||||
using Transform3d = Eigen::Transform<double, 3, Eigen::Affine, Eigen::DontAlign>;
|
||||
|
||||
// using ColorRGBA = std::array<float, 4>;
|
||||
// I don't know why Eigen::Transform::Identity() return a const object...
|
||||
template<int N, class T> Transform<N, T> identity() { return Transform<N, T>::Identity(); }
|
||||
inline const auto &identity3f = identity<3, float>;
|
||||
|
|
|
|||
|
|
@ -683,5 +683,4 @@ Polygon make_circle_num_segments(double radius, size_t num_segments)
|
|||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -518,6 +518,8 @@ void Preset::save(DynamicPrintConfig* parent_config)
|
|||
else
|
||||
from_str = std::string("Default");
|
||||
|
||||
boost::filesystem::create_directories(fs::path(this->file).parent_path());
|
||||
|
||||
//BBS: only save difference if it has parent
|
||||
if (parent_config) {
|
||||
DynamicPrintConfig temp_config;
|
||||
|
|
@ -530,15 +532,36 @@ void Preset::save(DynamicPrintConfig* parent_config)
|
|||
opt_dst->set(opt_src);
|
||||
}
|
||||
temp_config.save_to_json(this->file, this->name, from_str, this->version.to_string(), this->custom_defined);
|
||||
}
|
||||
else
|
||||
} else if (!filament_id.empty() && inherits().empty()) {
|
||||
DynamicPrintConfig temp_config = config;
|
||||
temp_config.set_key_value(BBL_JSON_KEY_FILAMENT_ID, new ConfigOptionString(filament_id));
|
||||
temp_config.save_to_json(this->file, this->name, from_str, this->version.to_string(), this->custom_defined);
|
||||
} else {
|
||||
this->config.save_to_json(this->file, this->name, from_str, this->version.to_string(), this->custom_defined);
|
||||
}
|
||||
|
||||
fs::path idx_file(this->file);
|
||||
idx_file.replace_extension(".info");
|
||||
this->save_info(idx_file.string());
|
||||
}
|
||||
|
||||
void Preset::reload(Preset const &parent)
|
||||
{
|
||||
DynamicPrintConfig config;
|
||||
// BBS: change to json format
|
||||
// ConfigSubstitutions config_substitutions = config.load_from_ini(preset.file, substitution_rule);
|
||||
std::map<std::string, std::string> key_values;
|
||||
std::string reason;
|
||||
ForwardCompatibilitySubstitutionRule substitution_rule = ForwardCompatibilitySubstitutionRule::Disable;
|
||||
try {
|
||||
ConfigSubstitutions config_substitutions = config.load_from_json(file, substitution_rule, key_values, reason);
|
||||
this->config = parent.config;
|
||||
this->config.apply(std::move(config));
|
||||
} catch (const std::exception &err) {
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("Failed loading the user-config file: %1%. Reason: %2%") % file % err.what();
|
||||
}
|
||||
}
|
||||
|
||||
// Return a label of this preset, consisting of a name and a "(modified)" suffix, if this preset is dirty.
|
||||
std::string Preset::label(bool no_alias) const
|
||||
{
|
||||
|
|
@ -665,7 +688,7 @@ std::string Preset::get_printer_type(PresetBundle *preset_bundle)
|
|||
vendor_name = vendor_profile.first;
|
||||
return vendor_model.model_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
|
@ -686,6 +709,25 @@ std::string Preset::get_current_printer_type(PresetBundle *preset_bundle)
|
|||
return "";
|
||||
}
|
||||
|
||||
bool Preset::has_lidar(PresetBundle *preset_bundle)
|
||||
{
|
||||
bool has_lidar = false;
|
||||
if (preset_bundle) {
|
||||
auto config = &preset_bundle->printers.get_edited_preset().config;
|
||||
std::string vendor_name;
|
||||
for (auto vendor_profile : preset_bundle->vendors) {
|
||||
for (auto vendor_model : vendor_profile.second.models)
|
||||
if (vendor_model.name == config->opt_string("printer_model")) {
|
||||
vendor_name = vendor_profile.first;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!vendor_name.empty())
|
||||
has_lidar = vendor_name.compare("BBL") == 0 ? true : false;
|
||||
}
|
||||
return has_lidar;
|
||||
}
|
||||
|
||||
bool Preset::is_custom_defined()
|
||||
{
|
||||
if (custom_defined == "1")
|
||||
|
|
@ -706,7 +748,7 @@ BedType Preset::get_default_bed_type(PresetBundle* preset_bundle)
|
|||
}
|
||||
|
||||
std::string model_id = this->get_printer_type(preset_bundle);
|
||||
if (model_id == "BL-P001" || model_id == "BL-P002") {
|
||||
if (model_id == "BL-P001" || model_id == "BL-P002" || model_id == "C13") {
|
||||
return BedType::btPC;
|
||||
} else if (model_id == "C11") {
|
||||
return BedType::btPEI;
|
||||
|
|
@ -717,7 +759,7 @@ BedType Preset::get_default_bed_type(PresetBundle* preset_bundle)
|
|||
bool Preset::has_cali_lines(PresetBundle* preset_bundle)
|
||||
{
|
||||
std::string model_id = this->get_printer_type(preset_bundle);
|
||||
if (model_id == "BL-P001" || model_id == "BL-P002") {
|
||||
if (model_id == "BL-P001" || model_id == "BL-P002" || model_id == "C13") {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
@ -727,7 +769,7 @@ static std::vector<std::string> s_Preset_print_options {
|
|||
"layer_height", "initial_layer_print_height", "wall_loops", "slice_closing_radius", "spiral_mode", "slicing_mode",
|
||||
"top_shell_layers", "top_shell_thickness", "bottom_shell_layers", "bottom_shell_thickness",
|
||||
"extra_perimeters_on_overhangs", "ensure_vertical_shell_thickness", "reduce_crossing_wall", "detect_thin_wall", "detect_overhang_wall", "overhang_reverse", "overhang_reverse_threshold","overhang_reverse_internal_only",
|
||||
"seam_position", "staggered_inner_seams", "wall_infill_order", "sparse_infill_density", "sparse_infill_pattern", "top_surface_pattern", "bottom_surface_pattern",
|
||||
"seam_position", "staggered_inner_seams", "wall_sequence", "is_infill_first", "sparse_infill_density", "sparse_infill_pattern", "top_surface_pattern", "bottom_surface_pattern",
|
||||
"infill_direction",
|
||||
"minimum_sparse_infill_area", "reduce_infill_retraction","internal_solid_infill_pattern",
|
||||
"ironing_type", "ironing_pattern", "ironing_flow", "ironing_speed", "ironing_spacing", "ironing_angle",
|
||||
|
|
@ -746,7 +788,7 @@ static std::vector<std::string> s_Preset_print_options {
|
|||
"support_interface_pattern", "support_interface_spacing", "support_interface_loop_pattern",
|
||||
"support_top_z_distance", "support_on_build_plate_only","support_critical_regions_only", "bridge_no_support", "thick_bridges", "max_bridge_length", "print_sequence", "support_remove_small_overhang",
|
||||
"filename_format", "wall_filament", "support_bottom_z_distance",
|
||||
"sparse_infill_filament", "solid_infill_filament", "support_filament", "support_interface_filament",
|
||||
"sparse_infill_filament", "solid_infill_filament", "support_filament", "support_interface_filament","support_interface_not_for_body",
|
||||
"ooze_prevention", "standby_temperature_delta", "interface_shells", "line_width", "initial_layer_line_width",
|
||||
"inner_wall_line_width", "outer_wall_line_width", "sparse_infill_line_width", "internal_solid_infill_line_width",
|
||||
"top_surface_line_width", "support_line_width", "infill_wall_overlap", "bridge_flow", "internal_bridge_flow",
|
||||
|
|
@ -774,7 +816,7 @@ static std::vector<std::string> s_Preset_print_options {
|
|||
"make_overhang_printable", "make_overhang_printable_angle", "make_overhang_printable_hole_size" ,"notes",
|
||||
"wipe_tower_cone_angle", "wipe_tower_extra_spacing", "wipe_tower_extruder", "wiping_volumes_extruders","wipe_tower_bridging", "single_extruder_multi_material_priming",
|
||||
"wipe_tower_rotation_angle", "tree_support_branch_distance_organic", "tree_support_branch_diameter_organic", "tree_support_branch_angle_organic",
|
||||
"hole_to_polyhole", "hole_to_polyhole_threshold", "hole_to_polyhole_twisted"
|
||||
"hole_to_polyhole", "hole_to_polyhole_threshold", "hole_to_polyhole_twisted", "mmu_segmented_region_max_width", "mmu_segmented_region_interlocking_depth",
|
||||
};
|
||||
|
||||
static std::vector<std::string> s_Preset_filament_options {
|
||||
|
|
@ -819,7 +861,7 @@ static std::vector<std::string> s_Preset_printer_options {
|
|||
"printer_technology",
|
||||
"printable_area", "bed_exclude_area","bed_custom_texture", "bed_custom_model", "gcode_flavor",
|
||||
"fan_kickstart", "fan_speedup_time", "fan_speedup_overhangs",
|
||||
"single_extruder_multi_material", "manual_filament_change", "machine_start_gcode", "machine_end_gcode", "before_layer_change_gcode", "layer_change_gcode", "time_lapse_gcode", "change_filament_gcode", "change_extrusion_role_gcode",
|
||||
"single_extruder_multi_material", "manual_filament_change", "machine_start_gcode", "machine_end_gcode", "before_layer_change_gcode", "printing_by_object_gcode", "layer_change_gcode", "time_lapse_gcode", "change_filament_gcode", "change_extrusion_role_gcode",
|
||||
"printer_model", "printer_variant", "printable_height", "extruder_clearance_radius", "extruder_clearance_height_to_lid", "extruder_clearance_height_to_rod",
|
||||
"default_print_profile", "inherits",
|
||||
"silent_mode",
|
||||
|
|
@ -1018,8 +1060,13 @@ void PresetCollection::load_presets(
|
|||
// see https://github.com/prusa3d/PrusaSlicer/issues/732
|
||||
boost::filesystem::path dir = boost::filesystem::absolute(boost::filesystem::path(dir_path) / subdir).make_preferred();
|
||||
|
||||
// Load custom roots first
|
||||
if (fs::exists(dir / "base")) {
|
||||
load_presets(dir.string(), "base", substitutions, substitution_rule);
|
||||
}
|
||||
|
||||
//BBS: add config related logs
|
||||
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(" enter, load presets from %1%, current type %2%")%dir %Preset::get_type_string(m_type);
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(" enter, load presets from %1%, current type %2%")%dir %Preset::get_type_string(m_type);
|
||||
//BBS do not parse folder if not exists
|
||||
m_dir_path = dir.string();
|
||||
if (!fs::exists(dir)) {
|
||||
|
|
@ -1084,8 +1131,12 @@ void PresetCollection::load_presets(
|
|||
}
|
||||
preset.version = *version;
|
||||
|
||||
if (key_values.find(BBL_JSON_KEY_FILAMENT_ID) != key_values.end())
|
||||
preset.filament_id = key_values[BBL_JSON_KEY_FILAMENT_ID];
|
||||
if (key_values.find(BBL_JSON_KEY_IS_CUSTOM) != key_values.end())
|
||||
preset.custom_defined = key_values[BBL_JSON_KEY_IS_CUSTOM];
|
||||
if (key_values.find("instantiation") != key_values.end())
|
||||
preset.is_visible = key_values["instantiation"] != "false";
|
||||
|
||||
//BBS: use inherit config as the base
|
||||
Preset* inherit_preset = nullptr;
|
||||
|
|
@ -1105,12 +1156,12 @@ void PresetCollection::load_presets(
|
|||
preset.filament_id = inherit_preset->filament_id;
|
||||
}
|
||||
else {
|
||||
if (!preset.is_custom_defined()) {
|
||||
// We support custom root preset now
|
||||
auto inherits_config2 = dynamic_cast<ConfigOptionString *>(inherits_config);
|
||||
if ((inherits_config2 && !inherits_config2->value.empty()) && !preset.is_custom_defined()) {
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("can not find parent for config %1%!")%preset.file;
|
||||
continue;
|
||||
}
|
||||
//should not happen
|
||||
//BOOST_LOG_TRIVIAL(error) << boost::format("can not find parent for config %1%!")%preset.file;
|
||||
// Find a default preset for the config. The PrintPresetCollection provides different default preset based on the "printer_technology" field.
|
||||
preset.config = default_preset.config;
|
||||
}
|
||||
|
|
@ -1147,6 +1198,7 @@ void PresetCollection::load_presets(
|
|||
fs::remove(file_path);
|
||||
}
|
||||
presets_loaded.emplace_back(preset);
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << __LINE__ << " load config successful and preset name is:" << preset.name;
|
||||
} catch (const std::runtime_error &err) {
|
||||
errors_cummulative += err.what();
|
||||
errors_cummulative += "\n";
|
||||
|
|
@ -1219,16 +1271,26 @@ int PresetCollection::get_differed_values_to_update(Preset& preset, std::map<std
|
|||
if (opt_src)
|
||||
key_values[option] = opt_src->serialize();
|
||||
}
|
||||
//add other values
|
||||
key_values[BBL_JSON_KEY_VERSION] = preset.version.to_string();
|
||||
key_values[BBL_JSON_KEY_BASE_ID] = preset.base_id;
|
||||
key_values[BBL_JSON_KEY_UPDATE_TIME] = std::to_string(preset.updated_time);
|
||||
key_values[BBL_JSON_KEY_TYPE] = Preset::get_iot_type_string(preset.type);
|
||||
}
|
||||
else {
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" Error: can not find the parent! Should not happen, name %1%") %preset.name;
|
||||
return -1;
|
||||
for (auto iter = preset.config.cbegin(); iter != preset.config.cend(); ++iter)
|
||||
{
|
||||
key_values[iter->first] = iter->second->serialize();
|
||||
}
|
||||
}
|
||||
|
||||
//add other values
|
||||
key_values[BBL_JSON_KEY_VERSION] = preset.version.to_string();
|
||||
if (!preset.base_id.empty()) {
|
||||
key_values[BBL_JSON_KEY_BASE_ID] = preset.base_id;
|
||||
} else {
|
||||
key_values.erase(BBL_JSON_KEY_BASE_ID);
|
||||
if (get_preset_base(preset) == &preset && !preset.filament_id.empty()) {
|
||||
key_values[BBL_JSON_KEY_FILAMENT_ID] = preset.filament_id;
|
||||
}
|
||||
}
|
||||
key_values[BBL_JSON_KEY_UPDATE_TIME] = std::to_string(preset.updated_time);
|
||||
key_values[BBL_JSON_KEY_TYPE] = Preset::get_iot_type_string(preset.type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1363,7 +1425,7 @@ bool PresetCollection::reset_project_embedded_presets()
|
|||
return re_select;
|
||||
}
|
||||
|
||||
void PresetCollection::set_sync_info_and_save(std::string name, std::string setting_id, std::string syncinfo)
|
||||
void PresetCollection::set_sync_info_and_save(std::string name, std::string setting_id, std::string syncinfo, long long update_time)
|
||||
{
|
||||
lock();
|
||||
for (auto it = m_presets.begin(); it != m_presets.end(); it++) {
|
||||
|
|
@ -1373,16 +1435,34 @@ void PresetCollection::set_sync_info_and_save(std::string name, std::string sett
|
|||
preset->sync_info.clear();
|
||||
else
|
||||
preset->sync_info = syncinfo;
|
||||
if (get_preset_base(*preset) == preset) {
|
||||
for (auto & preset2 : m_presets)
|
||||
if (preset2.inherits() == preset->name) {
|
||||
preset2.base_id = setting_id;
|
||||
preset2.save_info();
|
||||
}
|
||||
}
|
||||
preset->setting_id = setting_id;
|
||||
preset->save_info();
|
||||
if (update_time > 0)
|
||||
preset->updated_time = update_time;
|
||||
preset->sync_info == "update" ? preset->save(nullptr) : preset->save_info();
|
||||
break;
|
||||
}
|
||||
}
|
||||
unlock();
|
||||
}
|
||||
|
||||
bool PresetCollection::need_sync(std::string name, std::string setting_id, long long update_time)
|
||||
{
|
||||
lock();
|
||||
auto preset = find_preset(name, false, true);
|
||||
bool need = preset == nullptr || preset->setting_id != setting_id || preset->updated_time < update_time;
|
||||
unlock();
|
||||
return need;
|
||||
}
|
||||
|
||||
//BBS: get user presets
|
||||
int PresetCollection::get_user_presets(std::vector<Preset>& result_presets)
|
||||
int PresetCollection::get_user_presets(PresetBundle *preset_bundle, std::vector<Preset> &result_presets)
|
||||
{
|
||||
int count = 0;
|
||||
result_presets.clear();
|
||||
|
|
@ -1390,6 +1470,10 @@ int PresetCollection::get_user_presets(std::vector<Preset>& result_presets)
|
|||
lock();
|
||||
for (Preset &preset : m_presets) {
|
||||
if (!preset.is_user()) continue;
|
||||
if (get_preset_base(preset) != &preset && preset.base_id.empty()) continue;
|
||||
if (!preset.setting_id.empty() && preset.sync_info.empty()) continue;
|
||||
//if (!preset.is_bbl_vendor_preset(preset_bundle)) continue;
|
||||
if (preset.sync_info == "hold") continue;
|
||||
|
||||
result_presets.push_back(preset);
|
||||
count++;
|
||||
|
|
@ -1426,7 +1510,9 @@ void PresetCollection::save_user_presets(const std::string& dir_path, const std:
|
|||
for (auto it = m_presets.begin(); it != m_presets.end(); it++) {
|
||||
Preset* preset = &m_presets[it - m_presets.begin()];
|
||||
if (!preset->is_user()) continue;
|
||||
preset->file = path_from_name(preset->name);
|
||||
if (preset->sync_info != "save") continue;
|
||||
preset->sync_info.clear();
|
||||
preset->file = path_for_preset(*preset);
|
||||
|
||||
if (preset->is_custom_defined()) {
|
||||
preset->save(nullptr);
|
||||
|
|
@ -1434,11 +1520,13 @@ void PresetCollection::save_user_presets(const std::string& dir_path, const std:
|
|||
//BBS: only save difference for user preset
|
||||
std::string inherits = Preset::inherits(preset->config);
|
||||
if (inherits.empty()) {
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" can not find inherits for %1% , should not happen")%preset->name;
|
||||
// BBS add sync info
|
||||
preset->sync_info = "delete";
|
||||
need_to_delete_list.push_back(preset->setting_id);
|
||||
delete_name_list.push_back(preset->name);
|
||||
// We support custom root preset now
|
||||
//BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" can not find inherits for %1% , should not happen")%preset->name;
|
||||
//// BBS add sync info
|
||||
//preset->sync_info = "delete";
|
||||
//need_to_delete_list.push_back(preset->setting_id);
|
||||
//delete_name_list.push_back(preset->name);
|
||||
preset->save(nullptr);
|
||||
continue;
|
||||
}
|
||||
Preset* parent_preset = this->find_preset(inherits, false, true);
|
||||
|
|
@ -1471,7 +1559,7 @@ bool PresetCollection::load_user_preset(std::string name, std::map<std::string,
|
|||
//std::deque<Preset> presets_loaded;
|
||||
int count = 0;
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(" enter, name %1% , total value counts %2%")%name %preset_values.size();
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(" enter, name %1% , total value counts %2%")%name %preset_values.size();
|
||||
|
||||
//if the version is not matching, skip it
|
||||
if (preset_values.find(BBL_JSON_KEY_VERSION) == preset_values.end()) {
|
||||
|
|
@ -1497,13 +1585,6 @@ bool PresetCollection::load_user_preset(std::string name, std::map<std::string,
|
|||
}
|
||||
std::string cloud_setting_id = preset_values[BBL_JSON_KEY_SETTING_ID];
|
||||
|
||||
//base_id
|
||||
if (preset_values.find(BBL_JSON_KEY_BASE_ID) == preset_values.end()) {
|
||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format("can not find base_id, not loading for user preset %1%")%name;
|
||||
return false;
|
||||
}
|
||||
std::string cloud_base_id = preset_values[BBL_JSON_KEY_BASE_ID];
|
||||
|
||||
//update_time
|
||||
long long cloud_update_time = 0;
|
||||
if (preset_values.find(BBL_JSON_KEY_UPDATE_TIME) != preset_values.end()) {
|
||||
|
|
@ -1517,12 +1598,6 @@ bool PresetCollection::load_user_preset(std::string name, std::map<std::string,
|
|||
}
|
||||
std::string cloud_user_id = preset_values[BBL_JSON_KEY_USER_ID];
|
||||
|
||||
//filament_id
|
||||
std::string cloud_filament_id;
|
||||
if ((m_type == Preset::TYPE_FILAMENT) && preset_values.find(BBL_JSON_KEY_FILAMENT_ID) != preset_values.end()) {
|
||||
cloud_filament_id = preset_values[BBL_JSON_KEY_FILAMENT_ID];
|
||||
}
|
||||
|
||||
lock();
|
||||
//std::string name = preset->name;
|
||||
auto iter = this->find_preset_internal(name);
|
||||
|
|
@ -1535,6 +1610,11 @@ bool PresetCollection::load_user_preset(std::string name, std::map<std::string,
|
|||
iter->sync_info = "update";
|
||||
else
|
||||
iter->sync_info.clear();
|
||||
// Fixup possible data lost
|
||||
iter->setting_id = cloud_setting_id;
|
||||
fs::path idx_file(iter->file);
|
||||
idx_file.replace_extension(".info");
|
||||
iter->save_info(idx_file.string());
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format("preset %1%'s update_time is eqaul or newer, cloud update_time %2%, local update_time %3%")%name %cloud_update_time %iter->updated_time;
|
||||
unlock();
|
||||
return false;
|
||||
|
|
@ -1542,11 +1622,24 @@ bool PresetCollection::load_user_preset(std::string name, std::map<std::string,
|
|||
else {
|
||||
//update the one from cloud which is newer
|
||||
need_update = true;
|
||||
iter->sync_info.clear();
|
||||
}
|
||||
}
|
||||
|
||||
DynamicPrintConfig new_config, cloud_config;
|
||||
// base_id
|
||||
if (preset_values.find(BBL_JSON_KEY_BASE_ID) == preset_values.end()) {
|
||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format("can not find base_id, not loading for user preset %1%") % name;
|
||||
unlock();
|
||||
return false;
|
||||
}
|
||||
std::string cloud_base_id = preset_values[BBL_JSON_KEY_BASE_ID];
|
||||
|
||||
//filament_id
|
||||
std::string cloud_filament_id;
|
||||
if ((m_type == Preset::TYPE_FILAMENT) && preset_values.find(BBL_JSON_KEY_FILAMENT_ID) != preset_values.end()) {
|
||||
cloud_filament_id = preset_values[BBL_JSON_KEY_FILAMENT_ID];
|
||||
}
|
||||
|
||||
DynamicPrintConfig new_config, cloud_config;
|
||||
try {
|
||||
ConfigSubstitutions config_substitutions = cloud_config.load_string_map(preset_values, rule);
|
||||
if (! config_substitutions.empty())
|
||||
|
|
@ -1570,12 +1663,16 @@ bool PresetCollection::load_user_preset(std::string name, std::map<std::string,
|
|||
new_config = inherit_preset->config;
|
||||
}
|
||||
else {
|
||||
// We support custom root preset now
|
||||
auto inherits_config2 = dynamic_cast<ConfigOptionString *>(inherits_config);
|
||||
if (inherits_config2 && !inherits_config2->value.empty()) {
|
||||
//we should skip this preset here
|
||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(", can not find inherit preset for user preset %1%, just skip")%name;
|
||||
unlock();
|
||||
return false;
|
||||
}
|
||||
// Find a default preset for the config. The PrintPresetCollection provides different default preset based on the "printer_technology" field.
|
||||
//new_config = default_preset.config;
|
||||
//we should skip this preset here
|
||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(", can not find inherit preset for user preset %1%, just skip")%name;
|
||||
unlock();
|
||||
return false;
|
||||
new_config = default_preset.config;
|
||||
}
|
||||
new_config.apply(std::move(cloud_config));
|
||||
Preset::normalize(new_config);
|
||||
|
|
@ -1591,7 +1688,8 @@ bool PresetCollection::load_user_preset(std::string name, std::map<std::string,
|
|||
}
|
||||
iter->config = new_config;
|
||||
iter->updated_time = cloud_update_time;
|
||||
iter->version = cloud_version.value();
|
||||
iter->sync_info = "save";
|
||||
iter->version = cloud_version.value();
|
||||
iter->user_id = cloud_user_id;
|
||||
iter->setting_id = cloud_setting_id;
|
||||
iter->base_id = cloud_base_id;
|
||||
|
|
@ -1607,7 +1705,8 @@ bool PresetCollection::load_user_preset(std::string name, std::map<std::string,
|
|||
preset.loaded = true;
|
||||
preset.config = new_config;
|
||||
preset.updated_time = cloud_update_time;
|
||||
preset.version = cloud_version.value();
|
||||
preset.sync_info = "save";
|
||||
preset.version = cloud_version.value();
|
||||
preset.user_id = cloud_user_id;
|
||||
preset.setting_id = cloud_setting_id;
|
||||
preset.base_id = cloud_base_id;
|
||||
|
|
@ -1651,28 +1750,33 @@ void PresetCollection::update_after_user_presets_loaded()
|
|||
return;
|
||||
}
|
||||
|
||||
//BBS: validate_printers
|
||||
bool PresetCollection::validate_printers(const std::string &name, DynamicPrintConfig& config, std::string &inherit)
|
||||
//BBS: validate_preset
|
||||
bool PresetCollection::validate_preset(const std::string &preset_name, std::string &inherit_name)
|
||||
{
|
||||
std::string& original_name = config.opt_string("printer_settings_id", true);
|
||||
std::deque<Preset>::iterator it = this->find_preset_internal(original_name);
|
||||
bool found = it != m_presets.end() && it->name == original_name && (it->is_system || it->is_default);
|
||||
std::deque<Preset>::iterator it = this->find_preset_internal(preset_name);
|
||||
bool found = (it != m_presets.end()) && (it->name == preset_name) && (it->is_system || it->is_default);
|
||||
if (!found) {
|
||||
it = this->find_preset_renamed(original_name);
|
||||
it = this->find_preset_renamed(preset_name);
|
||||
found = it != m_presets.end() && (it->is_system || it->is_default);
|
||||
}
|
||||
if (!found) {
|
||||
if (!inherit.empty()) {
|
||||
it = this->find_preset_internal(inherit);
|
||||
found = it != m_presets.end() && it->name == inherit && (it->is_system || it->is_default);
|
||||
if (!inherit_name.empty()) {
|
||||
it = this->find_preset_internal(inherit_name);
|
||||
found = it != m_presets.end() && it->name == inherit_name && (it->is_system || it->is_default);
|
||||
if (found)
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": preset_name %1%, inherit_name %2%, found inherit in list")%preset_name %inherit_name;
|
||||
else
|
||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(": preset_name %1%, inherit_name %2%, can not found preset and inherit in list")%preset_name %inherit_name;
|
||||
}
|
||||
else {
|
||||
//inherit is null , should not happen , just consider it as valid
|
||||
found = false;
|
||||
BOOST_LOG_TRIVIAL(warning) << boost::format(": name %1%, printer_settings %2%, no inherit, set to not found")%name %original_name;
|
||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(": preset_name %1%, no inherit, set to not found")%preset_name;
|
||||
}
|
||||
}
|
||||
BOOST_LOG_TRIVIAL(warning) << boost::format(": name %1%, printer_settings %2%, inherit %3%, found result %4%")%name %original_name % inherit % found;
|
||||
else {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": preset_name %1%, found in list")%preset_name;
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
|
@ -1945,7 +2049,7 @@ std::pair<Preset*, bool> PresetCollection::load_external_preset(
|
|||
}
|
||||
else {
|
||||
//external config
|
||||
preset.file = path_from_name(preset.name);
|
||||
preset.file = path_for_preset(preset);
|
||||
//BBS: save full config here for external
|
||||
//we can not reach here
|
||||
preset.save(nullptr);
|
||||
|
|
@ -1985,6 +2089,113 @@ Preset& PresetCollection::load_preset(const std::string &path, const std::string
|
|||
return preset;
|
||||
}
|
||||
|
||||
bool PresetCollection::clone_presets(std::vector<Preset const *> const &presets, std::vector<std::string> &failures, std::function<void(Preset &, Preset::Type &)> modifier, bool force_rewritten)
|
||||
{
|
||||
std::vector<Preset> new_presets;
|
||||
for (auto curr_preset : presets) {
|
||||
new_presets.push_back(*curr_preset);
|
||||
auto &preset = new_presets.back();
|
||||
preset.vendor = nullptr;
|
||||
preset.renamed_from.clear();
|
||||
preset.setting_id.clear();
|
||||
preset.inherits().clear();
|
||||
preset.is_default = false;
|
||||
preset.is_system = false;
|
||||
preset.is_external = false;
|
||||
preset.is_visible = true;
|
||||
preset.is_project_embedded = false;
|
||||
modifier(preset, m_type);
|
||||
if (find_preset(preset.name) && !force_rewritten) {
|
||||
failures.push_back(preset.name);
|
||||
}
|
||||
preset.file = this->path_for_preset(preset);
|
||||
if (m_type == Preset::TYPE_PRINT)
|
||||
preset.config.option<ConfigOptionString>("print_settings_id", true)->value = preset.name;
|
||||
else if (m_type == Preset::TYPE_FILAMENT)
|
||||
preset.config.option<ConfigOptionStrings>("filament_settings_id", true)->values[0] = preset.name;
|
||||
else if (m_type == Preset::TYPE_PRINTER)
|
||||
preset.config.option<ConfigOptionString>("printer_settings_id", true)->value = preset.name;
|
||||
}
|
||||
if (!failures.empty() && !force_rewritten)
|
||||
return false;
|
||||
lock();
|
||||
auto old_name = this->get_edited_preset().name;
|
||||
for (auto preset : new_presets) {
|
||||
preset.alias.clear();
|
||||
auto it = this->find_preset_internal(preset.name);
|
||||
assert((it == m_presets.end() || it->name != preset.name) || force_rewritten);
|
||||
if (it == m_presets.end() || it->name != preset.name) {
|
||||
Preset &new_preset = *m_presets.insert(it, preset);
|
||||
new_preset.save(nullptr);
|
||||
} else if (force_rewritten) {
|
||||
*it = preset;
|
||||
(*it).save(nullptr);
|
||||
}
|
||||
}
|
||||
this->select_preset_by_name(old_name, true);
|
||||
unlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PresetCollection::clone_presets_for_printer(std::vector<Preset const *> const &presets, std::vector<std::string> &failures, std::string const &printer, bool force_rewritten)
|
||||
{
|
||||
return clone_presets(presets, failures, [printer](Preset &preset, Preset::Type &type) {
|
||||
std::string prefix = preset.name.substr(0, preset.name.find(" @"));
|
||||
std::replace(prefix.begin(), prefix.end(), '/', '-');
|
||||
preset.name = prefix + " @" + printer;
|
||||
//preset.alias = "";
|
||||
auto *compatible_printers = dynamic_cast<ConfigOptionStrings *>(preset.config.option("compatible_printers"));
|
||||
compatible_printers->values = std::vector<std::string>{ printer };
|
||||
}, force_rewritten);
|
||||
}
|
||||
|
||||
bool PresetCollection::create_presets_from_template_for_printer(std::vector<Preset const *> const & templates,
|
||||
std::vector<std::string> & failures,
|
||||
std::string const & printer,
|
||||
std::function<std::string(std::string)> create_filament_id,
|
||||
bool force_rewritten)
|
||||
{
|
||||
return clone_presets(templates, failures, [printer, create_filament_id](Preset &preset, Preset::Type &type) {
|
||||
std::string prefix = preset.name.substr(0, preset.name.find(" @"));
|
||||
std::replace(prefix.begin(), prefix.end(), '/', '-');
|
||||
preset.name = prefix + " @" + printer;
|
||||
auto *compatible_printers = dynamic_cast<ConfigOptionStrings *>(preset.config.option("compatible_printers"));
|
||||
compatible_printers->values = std::vector<std::string>{printer};
|
||||
preset.is_visible = true;
|
||||
if (type == Preset::TYPE_FILAMENT)
|
||||
preset.filament_id = create_filament_id(prefix);
|
||||
}, force_rewritten);
|
||||
}
|
||||
|
||||
bool PresetCollection::clone_presets_for_filament(Preset const *const & preset,
|
||||
std::vector<std::string> &failures,
|
||||
std::string const & filament_name,
|
||||
std::string const & filament_id,
|
||||
const DynamicConfig & dynamic_config,
|
||||
const std::string & compatible_printers,
|
||||
bool force_rewritten)
|
||||
{
|
||||
std::vector<Preset const *> const presets = {preset};
|
||||
return clone_presets(presets, failures, [&filament_name, &filament_id, &dynamic_config, &compatible_printers](Preset &preset, Preset::Type &type) {
|
||||
preset.name = filament_name + " @" + compatible_printers;
|
||||
if (type == Preset::TYPE_FILAMENT) {
|
||||
preset.config.apply_only(dynamic_config, {"filament_vendor", "compatible_printers", "filament_type"},true);
|
||||
|
||||
preset.filament_id = filament_id;
|
||||
}
|
||||
},
|
||||
force_rewritten);
|
||||
}
|
||||
|
||||
std::map<std::string, std::vector<Preset const *>> PresetCollection::get_filament_presets() const
|
||||
{
|
||||
std::map<std::string, std::vector<Preset const *>> filament_presets;
|
||||
for (auto &preset : m_presets) {
|
||||
if (get_preset_base(preset) == &preset) { filament_presets[preset.filament_id].push_back(&preset); }
|
||||
}
|
||||
return filament_presets;
|
||||
}
|
||||
|
||||
//BBS: add project embedded preset logic
|
||||
void PresetCollection::save_current_preset(const std::string &new_name, bool detach, bool save_to_project, Preset* _curr_preset)
|
||||
{
|
||||
|
|
@ -2020,15 +2231,27 @@ void PresetCollection::save_current_preset(const std::string &new_name, bool det
|
|||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(": save preset %1% , with detach")%new_name;
|
||||
}
|
||||
//BBS: add lock logic for sync preset in background
|
||||
|
||||
if (m_type == Preset::TYPE_PRINT)
|
||||
preset.config.option<ConfigOptionString>("print_settings_id", true)->value = new_name;
|
||||
else if (m_type == Preset::TYPE_FILAMENT)
|
||||
preset.config.option<ConfigOptionStrings>("filament_settings_id", true)->values[0] = new_name;
|
||||
else if (m_type == Preset::TYPE_PRINTER)
|
||||
preset.config.option<ConfigOptionString>("printer_settings_id", true)->value = new_name;
|
||||
final_inherits = preset.inherits();
|
||||
unlock();
|
||||
// TODO: apply change from custom root to devided presets.
|
||||
if (preset.inherits().empty()) {
|
||||
for (auto &preset2 : m_presets)
|
||||
if (preset2.inherits() == preset.name)
|
||||
preset2.reload(preset);
|
||||
}
|
||||
} else {
|
||||
// Creating a new preset.
|
||||
Preset &preset = *m_presets.insert(it, curr_preset);
|
||||
std::string &inherits = preset.inherits();
|
||||
std::string old_name = preset.name;
|
||||
preset.name = new_name;
|
||||
preset.file = this->path_from_name(new_name);
|
||||
preset.vendor = nullptr;
|
||||
preset.alias.clear();
|
||||
preset.renamed_from.clear();
|
||||
|
|
@ -2037,19 +2260,16 @@ void PresetCollection::save_current_preset(const std::string &new_name, bool det
|
|||
// Clear the link to the parent profile.
|
||||
inherits.clear();
|
||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(": save preset %1% , with detach")%new_name;
|
||||
} else if (preset.is_system) {
|
||||
// Inheriting from a system preset.
|
||||
inherits = /* preset.vendor->name + "/" + */ old_name;
|
||||
} else if (inherits.empty()) {
|
||||
// Inheriting from a user preset. Link the new preset to the old preset.
|
||||
// inherits = old_name;
|
||||
} else {
|
||||
// Inherited from a user preset. Just maintain the "inherited" flag,
|
||||
// meaning it will inherit from either the system preset, or the inherited user preset.
|
||||
auto base = get_preset_base(curr_preset);
|
||||
inherits = base ? base->name : "";
|
||||
}
|
||||
preset.is_default = false;
|
||||
preset.is_system = false;
|
||||
preset.is_external = false;
|
||||
preset.file = this->path_for_preset(preset);
|
||||
// The newly saved preset will be activated -> make it visible.
|
||||
preset.is_visible = true;
|
||||
// Just system presets have aliases
|
||||
|
|
@ -2061,11 +2281,11 @@ void PresetCollection::save_current_preset(const std::string &new_name, bool det
|
|||
else
|
||||
preset.is_project_embedded = false;
|
||||
if (m_type == Preset::TYPE_PRINT)
|
||||
preset.config.option<ConfigOptionString >("print_settings_id", true)->value = preset.name;
|
||||
preset.config.option<ConfigOptionString>("print_settings_id", true)->value = new_name;
|
||||
else if (m_type == Preset::TYPE_FILAMENT)
|
||||
preset.config.option<ConfigOptionStrings>("filament_settings_id", true)->values[0] = preset.name;
|
||||
preset.config.option<ConfigOptionStrings>("filament_settings_id", true)->values[0] = new_name;
|
||||
else if (m_type == Preset::TYPE_PRINTER)
|
||||
preset.config.option<ConfigOptionString>("printer_settings_id", true)->value = preset.name;
|
||||
preset.config.option<ConfigOptionString>("printer_settings_id", true)->value = new_name;
|
||||
//BBS: add lock logic for sync preset in background
|
||||
final_inherits = inherits;
|
||||
unlock();
|
||||
|
|
@ -2081,7 +2301,6 @@ void PresetCollection::save_current_preset(const std::string &new_name, bool det
|
|||
this->get_selected_preset().base_id = parent_preset->setting_id;
|
||||
}
|
||||
}
|
||||
this->get_selected_preset().updated_time = (long long)Slic3r::Utils::get_current_time_utc();
|
||||
if (parent_preset)
|
||||
this->get_selected_preset().save(&(parent_preset->config));
|
||||
else
|
||||
|
|
@ -2093,6 +2312,13 @@ bool PresetCollection::delete_current_preset()
|
|||
Preset &selected = this->get_selected_preset();
|
||||
if (selected.is_default)
|
||||
return false;
|
||||
|
||||
if (get_preset_base(selected) == &selected) {
|
||||
for (auto &preset2 : m_presets)
|
||||
if (preset2.inherits() == selected.name)
|
||||
return false;
|
||||
}
|
||||
|
||||
//BBS: add project embedded preset logic and refine is_external
|
||||
//if (! selected.is_external && ! selected.is_system) {
|
||||
if (! selected.is_system) {
|
||||
|
|
@ -2142,7 +2368,7 @@ const Preset* PresetCollection::get_selected_preset_parent() const
|
|||
return nullptr;
|
||||
|
||||
const Preset &selected_preset = this->get_selected_preset();
|
||||
if (selected_preset.is_system || selected_preset.is_default)
|
||||
if (get_preset_base(selected_preset) == &selected_preset)
|
||||
return &selected_preset;
|
||||
|
||||
const Preset &edited_preset = this->get_edited_preset();
|
||||
|
|
@ -2190,6 +2416,17 @@ const Preset* PresetCollection::get_preset_parent(const Preset& child) const
|
|||
preset;
|
||||
}
|
||||
|
||||
const Preset *PresetCollection::get_preset_base(const Preset &child) const
|
||||
{
|
||||
if (child.is_system || child.is_default)
|
||||
return &child;
|
||||
// Handle user preset
|
||||
if (child.inherits().empty())
|
||||
return &child; // this is user root
|
||||
auto inherits = find_preset(child.inherits());
|
||||
return inherits ? get_preset_base(*inherits) : nullptr;
|
||||
}
|
||||
|
||||
// Return vendor of the first parent profile, for which the vendor is defined, or null if such profile does not exist.
|
||||
PresetWithVendorProfile PresetCollection::get_preset_with_vendor_profile(const Preset &preset) const
|
||||
{
|
||||
|
|
@ -2614,12 +2851,20 @@ std::vector<std::string> PresetCollection::system_preset_names() const
|
|||
}
|
||||
|
||||
// Generate a file path from a profile name. Add the ".ini" suffix if it is missing.
|
||||
std::string PresetCollection::path_from_name(const std::string &new_name) const
|
||||
std::string PresetCollection::path_from_name(const std::string &new_name, bool detach) const
|
||||
{
|
||||
//BBS: change to json format
|
||||
//std::string file_name = boost::iends_with(new_name, ".ini") ? new_name : (new_name + ".ini");
|
||||
std::string file_name = boost::iends_with(new_name, ".json") ? new_name : (new_name + ".json");
|
||||
return (boost::filesystem::path(m_dir_path) / file_name).make_preferred().string();
|
||||
if (detach)
|
||||
return (boost::filesystem::path(m_dir_path) / "base" / file_name).make_preferred().string();
|
||||
else
|
||||
return (boost::filesystem::path(m_dir_path) / file_name).make_preferred().string();
|
||||
}
|
||||
|
||||
std::string PresetCollection::path_for_preset(const Preset &preset) const
|
||||
{
|
||||
return path_from_name(preset.name, get_preset_base(preset) == &preset);
|
||||
}
|
||||
|
||||
const Preset& PrinterPresetCollection::default_preset_for(const DynamicPrintConfig &config) const
|
||||
|
|
@ -2643,6 +2888,21 @@ const Preset* PrinterPresetCollection::find_system_preset_by_model_and_variant(c
|
|||
return it != cend() ? &*it : nullptr;
|
||||
}
|
||||
|
||||
const Preset *PrinterPresetCollection::find_custom_preset_by_model_and_variant(const std::string &model_id, const std::string &variant) const
|
||||
{
|
||||
if (model_id.empty()) { return nullptr; }
|
||||
|
||||
const auto it = std::find_if(cbegin(), cend(), [&](const Preset &preset) {
|
||||
if (preset.config.opt_string("printer_model") != model_id)
|
||||
return false;
|
||||
if (variant.empty())
|
||||
return true;
|
||||
return preset.config.opt_string("printer_variant") == variant;
|
||||
});
|
||||
|
||||
return it != cend() ? &*it : nullptr;
|
||||
}
|
||||
|
||||
bool PrinterPresetCollection::only_default_printers() const
|
||||
{
|
||||
for (const auto& printer : get_presets()) {
|
||||
|
|
|
|||
|
|
@ -20,6 +20,10 @@
|
|||
#define PRESET_PRINTER_NAME "machine"
|
||||
#define PRESET_SLA_PRINT_NAME "sla_print"
|
||||
#define PRESET_SLA_MATERIALS_NAME "sla_materials"
|
||||
#define PRESET_PROFILES_DIR "profiles"
|
||||
#define PRESET_PROFILES_TEMOLATE_DIR "profiles_template"
|
||||
#define PRESET_TEMPLATE_DIR "Template"
|
||||
#define PRESET_CUSTOM_VENDOR "Custom"
|
||||
|
||||
//BBS: iot preset type strings
|
||||
#define PRESET_IOT_PRINTER_TYPE "printer"
|
||||
|
|
@ -57,6 +61,8 @@
|
|||
#define BBL_JSON_KEY_DEFAULT_MATERIALS "default_materials"
|
||||
#define BBL_JSON_KEY_MODEL_ID "model_id"
|
||||
|
||||
//BBL: json path
|
||||
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
|
|
@ -171,6 +177,8 @@ public:
|
|||
// This type is here to support PresetConfigSubstitutions for physical printers, however it does not belong to the Preset class,
|
||||
// PhysicalPrinter class is used instead.
|
||||
TYPE_PHYSICAL_PRINTER,
|
||||
// BBS: plate config
|
||||
TYPE_PLATE,
|
||||
// BBS: model config
|
||||
TYPE_MODEL,
|
||||
};
|
||||
|
|
@ -245,6 +253,7 @@ public:
|
|||
//BBS: add logic for only difference save
|
||||
//if parent_config is null, save all keys, otherwise, only save difference
|
||||
void save(DynamicPrintConfig* parent_config);
|
||||
void reload(Preset const & parent);
|
||||
|
||||
// Return a label of this preset, consisting of a name and a "(modified)" suffix, if this preset is dirty.
|
||||
std::string label(bool no_alias) const;
|
||||
|
|
@ -300,6 +309,8 @@ public:
|
|||
std::string get_filament_type(std::string &display_filament_type);
|
||||
std::string get_printer_type(PresetBundle *preset_bundle); // get edited preset type
|
||||
std::string get_current_printer_type(PresetBundle *preset_bundle); // get current preset type
|
||||
|
||||
bool has_lidar(PresetBundle *preset_bundle);
|
||||
bool is_custom_defined();
|
||||
|
||||
BedType get_default_bed_type(PresetBundle *preset_bundle);
|
||||
|
|
@ -386,8 +397,8 @@ public:
|
|||
typedef std::function<void(Preset* preset, std::string sync_info)> SyncFunc;
|
||||
//BBS get m_presets begin
|
||||
Iterator lbegin() { return m_presets.begin(); }
|
||||
//BBS: validate_printers
|
||||
bool validate_printers(const std::string &name, DynamicPrintConfig& config, std::string &inherit);
|
||||
//BBS: validate_preset
|
||||
bool validate_preset(const std::string &name, std::string &inherit);
|
||||
|
||||
Iterator begin() { return m_presets.begin() + m_num_default_presets; }
|
||||
ConstIterator begin() const { return m_presets.cbegin() + m_num_default_presets; }
|
||||
|
|
@ -425,8 +436,9 @@ public:
|
|||
bool load_user_preset(std::string name, std::map<std::string, std::string> preset_values, PresetsConfigSubstitutions& substitutions, ForwardCompatibilitySubstitutionRule rule);
|
||||
void update_after_user_presets_loaded();
|
||||
//BBS: get user presets
|
||||
int get_user_presets(std::vector<Preset>& result_presets);
|
||||
void set_sync_info_and_save(std::string name, std::string setting_id, std::string syncinfo);
|
||||
int get_user_presets(PresetBundle *preset_bundle, std::vector<Preset> &result_presets);
|
||||
void set_sync_info_and_save(std::string name, std::string setting_id, std::string syncinfo, long long update_time);
|
||||
bool need_sync(std::string name, std::string setting_id, long long update_time);
|
||||
|
||||
//BBS: add function to generate differed preset for save
|
||||
//the pointer should be freed by the caller
|
||||
|
|
@ -444,6 +456,20 @@ public:
|
|||
Preset& load_preset(const std::string &path, const std::string &name, const DynamicPrintConfig &config, bool select = true, Semver file_version = Semver(), bool is_custom_defined = false);
|
||||
Preset& load_preset(const std::string &path, const std::string &name, DynamicPrintConfig &&config, bool select = true, Semver file_version = Semver(), bool is_custom_defined = false);
|
||||
|
||||
bool clone_presets(std::vector<Preset const *> const &presets, std::vector<std::string> &failures, std::function<void(Preset &, Preset::Type &)> modifier, bool force_rewritten = false);
|
||||
bool clone_presets_for_printer(std::vector<Preset const *> const &presets, std::vector<std::string> &failures, std::string const &printer, bool force_rewritten = false);
|
||||
bool create_presets_from_template_for_printer(
|
||||
std::vector<Preset const *> const &templates, std::vector<std::string> &failures, std::string const &printer, std::function <std::string(std::string)> create_filament_id, bool force_rewritten = false);
|
||||
bool clone_presets_for_filament(Preset const *const & preset,
|
||||
std::vector<std::string> &failures,
|
||||
std::string const & filament_name,
|
||||
std::string const & filament_id,
|
||||
const DynamicConfig & dynamic_config,
|
||||
const std::string & compatible_printers,
|
||||
bool force_rewritten = false);
|
||||
|
||||
std::map<std::string, std::vector<Preset const *>> get_filament_presets() const;
|
||||
|
||||
// Returns a loaded preset, returns true if an existing preset was selected AND modified from config.
|
||||
// In that case the successive filament loaded for a multi material printer should not be modified, but
|
||||
// an external preset should be created instead.
|
||||
|
|
@ -514,6 +540,7 @@ public:
|
|||
// Get parent preset for a child preset, based on the "inherits" field of a child,
|
||||
// where the "inherits" profile name is searched for in both m_presets and m_map_system_profile_renamed.
|
||||
const Preset* get_preset_parent(const Preset& child) const;
|
||||
const Preset* get_preset_base(const Preset& child) const;
|
||||
// Return the selected preset including the user modifications.
|
||||
Preset& get_edited_preset() { return m_edited_preset; }
|
||||
const Preset& get_edited_preset() const { return m_edited_preset; }
|
||||
|
|
@ -648,7 +675,8 @@ public:
|
|||
bool select_preset_by_name(const std::string &name, bool force);
|
||||
|
||||
// Generate a file path from a profile name. Add the ".ini" suffix if it is missing.
|
||||
std::string path_from_name(const std::string &new_name) const;
|
||||
std::string path_from_name(const std::string &new_name, bool detach = false) const;
|
||||
std::string path_for_preset(const Preset & preset) const;
|
||||
|
||||
size_t num_default_presets() { return m_num_default_presets; }
|
||||
|
||||
|
|
@ -754,6 +782,7 @@ public:
|
|||
const Preset& default_preset_for(const DynamicPrintConfig &config) const override;
|
||||
|
||||
const Preset* find_system_preset_by_model_and_variant(const std::string &model_id, const std::string &variant) const;
|
||||
const Preset* find_custom_preset_by_model_and_variant(const std::string &model_id, const std::string &variant) const;
|
||||
|
||||
bool only_default_printers() const;
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#include <boost/property_tree/ptree.hpp>
|
||||
#include <boost/locale.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <miniz/miniz.h>
|
||||
|
||||
|
||||
// Store the print/filament/printer presets into a "presets" subdirectory of the Slic3rPE config dir.
|
||||
|
|
@ -540,6 +541,7 @@ std::string PresetBundle::get_hotend_model_for_printer_model(std::string model_n
|
|||
|
||||
PresetsConfigSubstitutions PresetBundle::load_user_presets(std::string user, ForwardCompatibilitySubstitutionRule substitution_rule)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << __LINE__ << " entry and user is: " << user;
|
||||
PresetsConfigSubstitutions substitutions;
|
||||
std::string errors_cummulative;
|
||||
|
||||
|
|
@ -600,9 +602,14 @@ PresetsConfigSubstitutions PresetBundle::load_user_presets(AppConfig &
|
|||
remove_users_preset(config, &my_presets);
|
||||
|
||||
std::map<std::string, std::map<std::string, std::string>>::iterator it;
|
||||
for (int pass = 0; pass < 2; ++pass)
|
||||
for (it = my_presets.begin(); it != my_presets.end(); it++) {
|
||||
std::string name = it->first;
|
||||
std::map<std::string, std::string>& value_map = it->second;
|
||||
// Load user root presets at first pass
|
||||
std::map<std::string, std::string>::iterator inherits_iter = value_map.find(BBL_JSON_KEY_INHERITS);
|
||||
if ((pass == 1) == (inherits_iter == value_map.end() || inherits_iter->second.empty()))
|
||||
continue;
|
||||
//get the type first
|
||||
std::map<std::string, std::string>::iterator type_iter = value_map.find(BBL_JSON_KEY_TYPE);
|
||||
if (type_iter == value_map.end()) {
|
||||
|
|
@ -659,101 +666,189 @@ PresetsConfigSubstitutions PresetBundle::import_presets(std::vector<std::string>
|
|||
std::function<int(std::string const &)> override_confirm,
|
||||
ForwardCompatibilitySubstitutionRule rule)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " entry";
|
||||
PresetsConfigSubstitutions substitutions;
|
||||
int overwrite = 0;
|
||||
std::vector<std::string> result;
|
||||
for (auto &file : files) {
|
||||
if (Slic3r::is_json_file(file)) {
|
||||
try {
|
||||
DynamicPrintConfig config;
|
||||
// BBS: change to json format
|
||||
// ConfigSubstitutions config_substitutions = config.load_from_ini(preset.file, substitution_rule);
|
||||
std::map<std::string, std::string> key_values;
|
||||
std::string reason;
|
||||
ConfigSubstitutions config_substitutions = config.load_from_json(file, rule, key_values, reason);
|
||||
std::string name = key_values[BBL_JSON_KEY_NAME];
|
||||
std::string version_str = key_values[BBL_JSON_KEY_VERSION];
|
||||
boost::optional<Semver> version = Semver::parse(version_str);
|
||||
if (!version) continue;
|
||||
Semver app_version = *(Semver::parse(SLIC3R_VERSION));
|
||||
if (version->maj() != app_version.maj()) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "Preset incompatibla, not loading: " << name;
|
||||
continue;
|
||||
}
|
||||
import_json_presets(substitutions, file, override_confirm, rule, overwrite, result);
|
||||
}
|
||||
// Determine if it is a preset bundle
|
||||
if (boost::iends_with(file, ".bbscfg") || boost::iends_with(file, ".bbsflmt") || boost::iends_with(file, ".zip")) {
|
||||
boost::system::error_code ec;
|
||||
// create user folder
|
||||
fs::path user_folder(data_dir() + "/" + PRESET_USER_DIR);
|
||||
if (!fs::exists(user_folder)) fs::create_directory(user_folder, ec);
|
||||
if (ec) BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " create directory failed: " << ec.message();
|
||||
// create default folder
|
||||
fs::path default_folder(user_folder / DEFAULT_USER_FOLDER_NAME);
|
||||
if (!fs::exists(default_folder)) fs::create_directory(default_folder, ec);
|
||||
if (ec) BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " create directory failed: " << ec.message();
|
||||
//create temp folder
|
||||
//std::string user_default_temp_dir = data_dir() + "/" + PRESET_USER_DIR + "/" + DEFAULT_USER_FOLDER_NAME + "/" + "temp";
|
||||
fs::path temp_folder(default_folder / "temp");
|
||||
std::string user_default_temp_dir = temp_folder.make_preferred().string();
|
||||
if (fs::exists(temp_folder)) fs::remove_all(temp_folder);
|
||||
fs::create_directory(temp_folder, ec);
|
||||
if (ec) BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " create directory failed: " << ec.message();
|
||||
|
||||
PresetCollection * collection = nullptr;
|
||||
if (config.has("printer_settings_id"))
|
||||
collection = &printers;
|
||||
else if (config.has("print_settings_id"))
|
||||
collection = &prints;
|
||||
else if (config.has("filament_settings_id"))
|
||||
collection = &filaments;
|
||||
if (collection == nullptr) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "Preset type is unknown, not loading: " << name;
|
||||
continue;
|
||||
}
|
||||
if (overwrite == 0) overwrite = 1;
|
||||
if (auto p = collection->find_preset(name, false)) {
|
||||
if (p->is_default || p->is_system) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "Preset already present and is system preset, not loading: " << name;
|
||||
continue;
|
||||
}
|
||||
overwrite = override_confirm(name);
|
||||
}
|
||||
if (overwrite == 0 || overwrite == 2) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "Preset already present, not loading: " << name;
|
||||
continue;
|
||||
}
|
||||
file = boost::filesystem::path(file).make_preferred().string();
|
||||
mz_zip_archive zip_archive;
|
||||
mz_zip_zero_struct(&zip_archive);
|
||||
mz_bool status;
|
||||
|
||||
DynamicPrintConfig new_config;
|
||||
Preset * inherit_preset = nullptr;
|
||||
ConfigOption *inherits_config = config.option(BBL_JSON_KEY_INHERITS);
|
||||
std::string inherits_value;
|
||||
if (inherits_config) {
|
||||
ConfigOptionString *option_str = dynamic_cast<ConfigOptionString *>(inherits_config);
|
||||
inherits_value = option_str->value;
|
||||
inherit_preset = collection->find_preset(inherits_value, false, true);
|
||||
}
|
||||
if (inherit_preset) {
|
||||
new_config = inherit_preset->config;
|
||||
} else {
|
||||
// Find a default preset for the config. The PrintPresetCollection provides different default preset based on the "printer_technology" field.
|
||||
// new_config = default_preset.config;
|
||||
// we should skip this preset here
|
||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(", can not find inherit preset for user preset %1%, just skip") % name;
|
||||
continue;
|
||||
}
|
||||
new_config.apply(std::move(config));
|
||||
/*if (!open_zip_reader(&zip_archive, file)) {
|
||||
BOOST_LOG_TRIVIAL(info) << "Failed to initialize reader ZIP archive";
|
||||
return substitutions;
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(info) << "Success to initialize reader ZIP archive";
|
||||
}*/
|
||||
|
||||
Preset &preset = collection->load_preset(collection->path_from_name(name), name, std::move(new_config), false);
|
||||
preset.is_external = true;
|
||||
preset.version = *version;
|
||||
inherit_preset = collection->find_preset(inherits_value, false, true); // pointer maybe wrong after insert, redo find
|
||||
if (inherit_preset)
|
||||
preset.base_id = inherit_preset->setting_id;
|
||||
Preset::normalize(preset.config);
|
||||
// Report configuration fields, which are misplaced into a wrong group.
|
||||
const Preset &default_preset = collection->default_preset_for(new_config);
|
||||
std::string incorrect_keys = Preset::remove_invalid_keys(preset.config, default_preset.config);
|
||||
if (!incorrect_keys.empty())
|
||||
BOOST_LOG_TRIVIAL(error) << "Error in a preset file: The preset \"" << preset.file << "\" contains the following incorrect keys: " << incorrect_keys
|
||||
<< ", which were removed";
|
||||
if (!config_substitutions.empty())
|
||||
substitutions.push_back({name, collection->type(), PresetConfigSubstitutions::Source::UserFile, file, std::move(config_substitutions)});
|
||||
|
||||
preset.save(inherit_preset ? &inherit_preset->config : nullptr);
|
||||
result.push_back(file);
|
||||
} catch (const std::ifstream::failure &err) {
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("The config cannot be loaded: %1%. Reason: %2%") % file % err.what();
|
||||
} catch (const std::runtime_error &err) {
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("Failed importing config file: %1%. Reason: %2%") % file % err.what();
|
||||
FILE *zipFile = boost::nowide::fopen(file.c_str(), "rb");
|
||||
status = mz_zip_reader_init_cfile(&zip_archive, zipFile, 0, MZ_ZIP_FLAG_CASE_SENSITIVE | MZ_ZIP_FLAG_IGNORE_PATH);
|
||||
if (MZ_FALSE == status) {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " Failed to initialize reader ZIP archive";
|
||||
return substitutions;
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " Success to initialize reader ZIP archive";
|
||||
}
|
||||
|
||||
// Extract Files
|
||||
int num_files = mz_zip_reader_get_num_files(&zip_archive);
|
||||
for (int i = 0; i < num_files; i++) {
|
||||
mz_zip_archive_file_stat file_stat;
|
||||
status = mz_zip_reader_file_stat(&zip_archive, i, &file_stat);
|
||||
if (status) {
|
||||
std::string file_name = file_stat.m_filename;
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " Form zip file: " << file << ". Read file name: " << file_stat.m_filename;
|
||||
size_t index = file_name.find_last_of('/');
|
||||
if (std::string::npos != index) {
|
||||
file_name = file_name.substr(index + 1);
|
||||
}
|
||||
if (BUNDLE_STRUCTURE_JSON_NAME == file_name) continue;
|
||||
// create target file path
|
||||
std::string target_file_path = boost::filesystem::path(temp_folder / file_name).make_preferred().string();
|
||||
|
||||
status = mz_zip_reader_extract_to_file(&zip_archive, i, encode_path(target_file_path.c_str()).c_str(), MZ_ZIP_FLAG_CASE_SENSITIVE);
|
||||
// target file is opened
|
||||
if (MZ_FALSE == status) {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " Failed to open target file: " << target_file_path;
|
||||
} else {
|
||||
bool is_success = import_json_presets(substitutions, target_file_path, override_confirm, rule, overwrite, result);
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " import target file: " << target_file_path << " import result" << is_success;
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(zipFile);
|
||||
if (fs::exists(temp_folder)) fs::remove_all(temp_folder, ec);
|
||||
if (ec) BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << " remove directory failed: " << ec.message();
|
||||
}
|
||||
}
|
||||
files = result;
|
||||
return substitutions;
|
||||
}
|
||||
|
||||
bool PresetBundle::import_json_presets(PresetsConfigSubstitutions & substitutions,
|
||||
std::string & file,
|
||||
std::function<int(std::string const &)> override_confirm,
|
||||
ForwardCompatibilitySubstitutionRule rule,
|
||||
int & overwrite,
|
||||
std::vector<std::string> & result)
|
||||
{
|
||||
try {
|
||||
DynamicPrintConfig config;
|
||||
// BBS: change to json format
|
||||
// ConfigSubstitutions config_substitutions = config.load_from_ini(preset.file, substitution_rule);
|
||||
std::map<std::string, std::string> key_values;
|
||||
std::string reason;
|
||||
ConfigSubstitutions config_substitutions = config.load_from_json(file, rule, key_values, reason);
|
||||
std::string name = key_values[BBL_JSON_KEY_NAME];
|
||||
std::string version_str = key_values[BBL_JSON_KEY_VERSION];
|
||||
boost::optional<Semver> version = Semver::parse(version_str);
|
||||
if (!version) return false;
|
||||
Semver app_version = *(Semver::parse(SLIC3R_VERSION));
|
||||
if (version->maj() != app_version.maj()) {
|
||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << " Preset incompatibla, not loading: " << name;
|
||||
return false;
|
||||
}
|
||||
|
||||
PresetCollection *collection = nullptr;
|
||||
if (config.has("printer_settings_id"))
|
||||
collection = &printers;
|
||||
else if (config.has("print_settings_id"))
|
||||
collection = &prints;
|
||||
else if (config.has("filament_settings_id"))
|
||||
collection = &filaments;
|
||||
if (collection == nullptr) {
|
||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << " Preset type is unknown, not loading: " << name;
|
||||
return false;
|
||||
}
|
||||
if (overwrite == 0) overwrite = 1;
|
||||
if (auto p = collection->find_preset(name, false)) {
|
||||
if (p->is_default || p->is_system) {
|
||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << " Preset already present and is system preset, not loading: " << name;
|
||||
return false;
|
||||
}
|
||||
if (overwrite != 2 && overwrite != 3) overwrite = override_confirm(name); //3: yes to all 2: no to all
|
||||
}
|
||||
if (overwrite == 0 || overwrite == 2) {
|
||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << " Preset already present, not loading: " << name;
|
||||
return false;
|
||||
}
|
||||
|
||||
DynamicPrintConfig new_config;
|
||||
Preset * inherit_preset = nullptr;
|
||||
ConfigOption * inherits_config = config.option(BBL_JSON_KEY_INHERITS);
|
||||
std::string inherits_value;
|
||||
if (inherits_config) {
|
||||
ConfigOptionString *option_str = dynamic_cast<ConfigOptionString *>(inherits_config);
|
||||
inherits_value = option_str->value;
|
||||
inherit_preset = collection->find_preset(inherits_value, false, true);
|
||||
}
|
||||
if (inherit_preset) {
|
||||
new_config = inherit_preset->config;
|
||||
} else {
|
||||
// We support custom root preset now
|
||||
auto inherits_config2 = dynamic_cast<ConfigOptionString *>(inherits_config);
|
||||
if (inherits_config2 && !inherits_config2->value.empty()) {
|
||||
// we should skip this preset here
|
||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(", can not find inherit preset for user preset %1%, just skip") % name;
|
||||
return false;
|
||||
}
|
||||
// Find a default preset for the config. The PrintPresetCollection provides different default preset based on the "printer_technology" field.
|
||||
const Preset &default_preset = collection->default_preset_for(config);
|
||||
new_config = default_preset.config;
|
||||
}
|
||||
new_config.apply(std::move(config));
|
||||
|
||||
Preset &preset = collection->load_preset(collection->path_from_name(name, inherit_preset == nullptr), name, std::move(new_config), false);
|
||||
if (key_values.find(BBL_JSON_KEY_FILAMENT_ID) != key_values.end())
|
||||
preset.filament_id = key_values[BBL_JSON_KEY_FILAMENT_ID];
|
||||
preset.is_external = true;
|
||||
preset.version = *version;
|
||||
inherit_preset = collection->find_preset(inherits_value, false, true); // pointer maybe wrong after insert, redo find
|
||||
if (inherit_preset) preset.base_id = inherit_preset->setting_id;
|
||||
Preset::normalize(preset.config);
|
||||
// Report configuration fields, which are misplaced into a wrong group.
|
||||
const Preset &default_preset = collection->default_preset_for(new_config);
|
||||
std::string incorrect_keys = Preset::remove_invalid_keys(preset.config, default_preset.config);
|
||||
if (!incorrect_keys.empty())
|
||||
BOOST_LOG_TRIVIAL(error) << "Error in a preset file: The preset \"" << preset.file << "\" contains the following incorrect keys: " << incorrect_keys
|
||||
<< ", which were removed";
|
||||
if (!config_substitutions.empty())
|
||||
substitutions.push_back({name, collection->type(), PresetConfigSubstitutions::Source::UserFile, file, std::move(config_substitutions)});
|
||||
|
||||
preset.save(inherit_preset ? &inherit_preset->config : nullptr);
|
||||
result.push_back(file);
|
||||
} catch (const std::ifstream::failure &err) {
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("The config cannot be loaded: %1%. Reason: %2%") % file % err.what();
|
||||
} catch (const std::runtime_error &err) {
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("Failed importing config file: %1%. Reason: %2%") % file % err.what();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//BBS save user preset to user_id preset folder
|
||||
void PresetBundle::save_user_presets(AppConfig& config, std::vector<std::string>& need_to_delete_list)
|
||||
{
|
||||
|
|
@ -867,26 +962,80 @@ void PresetBundle::update_system_preset_setting_ids(std::map<std::string, std::m
|
|||
}
|
||||
|
||||
//BBS: validate printers from previous project
|
||||
bool PresetBundle::validate_printers(const std::string &name, DynamicPrintConfig& config)
|
||||
static std::set<std::string> gcodes_key_set = {"filament_end_gcode", "filament_start_gcode", "change_filament_gcode", "layer_change_gcode", "machine_end_gcode", "machine_pause_gcode", "machine_start_gcode",
|
||||
"template_custom_gcode", "printing_by_object_gcode", "before_layer_change_gcode", "time_lapse_gcode"};
|
||||
int PresetBundle::validate_presets(const std::string &file_name, DynamicPrintConfig& config, std::set<std::string>& different_gcodes)
|
||||
{
|
||||
// BBS TODO:
|
||||
#if 0
|
||||
std::vector<std::string> inherits_values;
|
||||
PrinterTechnology printer_technology = Preset::printer_technology(config);
|
||||
size_t num_extruders = (printer_technology == ptFFF) ?
|
||||
std::min(config.option<ConfigOptionFloats>("nozzle_diameter" )->values.size(),
|
||||
config.option<ConfigOptionFloats>("filament_diameter")->values.size()) : 1;
|
||||
inherits_values.resize(num_extruders + 2, std::string());
|
||||
inherits_values = config.option<ConfigOptionStrings>("inherits_group", true)->values;
|
||||
bool validated = false;
|
||||
std::vector<std::string> inherits_values = config.option<ConfigOptionStrings>("inherits_group", true)->values;
|
||||
std::vector<std::string> filament_preset_name = config.option<ConfigOptionStrings>("filament_settings_id", true)->values;
|
||||
std::string printer_preset = config.option<ConfigOptionString>("printer_settings_id", true)->value;
|
||||
bool has_different_settings_to_system = config.option("different_settings_to_system")?true:false;
|
||||
std::vector<std::string> different_values;
|
||||
int ret = VALIDATE_PRESETS_SUCCESS;
|
||||
|
||||
std::string inherits;
|
||||
if (inherits_values.size() >= (num_extruders + 2))
|
||||
inherits = inherits_values[num_extruders + 1];
|
||||
if (has_different_settings_to_system)
|
||||
different_values = config.option<ConfigOptionStrings>("different_settings_to_system", true)->values;
|
||||
|
||||
return this->printers.validate_printers(name, config, inherits);
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
//PrinterTechnology printer_technology = Preset::printer_technology(config);
|
||||
size_t filament_count = config.option<ConfigOptionFloats>("filament_diameter")->values.size();
|
||||
inherits_values.resize(filament_count + 2, std::string());
|
||||
different_values.resize(filament_count + 2, std::string());
|
||||
filament_preset_name.resize(filament_count, std::string());
|
||||
|
||||
std::string printer_inherits = inherits_values[filament_count + 1];
|
||||
|
||||
validated = this->printers.validate_preset(printer_preset, printer_inherits);
|
||||
if (!validated) {
|
||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(":file_name %1%, found the printer preset not inherit from system") % file_name;
|
||||
different_gcodes.emplace(printer_preset);
|
||||
ret = VALIDATE_PRESETS_PRINTER_NOT_FOUND;
|
||||
}
|
||||
for(unsigned int index = 0; index < filament_count; index ++)
|
||||
{
|
||||
std::string filament_preset = filament_preset_name[index];
|
||||
std::string filament_inherits = inherits_values[index+1];
|
||||
|
||||
validated = this->filaments.validate_preset(filament_preset, filament_inherits);
|
||||
if (!validated) {
|
||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(":file_name %1%, found the filament %2% preset not inherit from system") % file_name %(index+1);
|
||||
different_gcodes.emplace(filament_preset);
|
||||
ret = VALIDATE_PRESETS_FILAMENTS_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
//self defined presets, return directly
|
||||
if (ret)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(":file_name %1%, found self defined presets, count %2%") %file_name %different_gcodes.size();
|
||||
return ret;
|
||||
}
|
||||
|
||||
for(unsigned int index = 1; index < filament_count+2; index ++)
|
||||
{
|
||||
std::string different_settingss = different_values[index];
|
||||
|
||||
std::vector<std::string> different_keys;
|
||||
|
||||
Slic3r::unescape_strings_cstyle(different_settingss, different_keys);
|
||||
|
||||
for (unsigned int j = 0; j < different_keys.size(); j++) {
|
||||
if (gcodes_key_set.find(different_keys[j]) != gcodes_key_set.end()) {
|
||||
different_gcodes.emplace(different_keys[j]);
|
||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(":preset index %1%, different key %2%") %index %different_keys[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!different_gcodes.empty())
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(":file_name %1%, found different gcodes count %2%") %file_name %different_gcodes.size();
|
||||
return VALIDATE_PRESETS_MODIFIED_GCODES;
|
||||
}
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(":file_name %1%, validate presets success!") % file_name;
|
||||
|
||||
return VALIDATE_PRESETS_SUCCESS;
|
||||
}
|
||||
|
||||
void PresetBundle::remove_users_preset(AppConfig &config, std::map<std::string, std::map<std::string, std::string>> *my_presets)
|
||||
|
|
@ -1113,6 +1262,116 @@ std::pair<PresetsConfigSubstitutions, std::string> PresetBundle::load_system_pre
|
|||
return std::make_pair(std::move(substitutions), errors_cummulative);
|
||||
}
|
||||
|
||||
std::pair<PresetsConfigSubstitutions, std::string> PresetBundle::load_system_models_from_json(ForwardCompatibilitySubstitutionRule compatibility_rule)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(" enter, compatibility_rule %1%") % compatibility_rule;
|
||||
if (compatibility_rule == ForwardCompatibilitySubstitutionRule::EnableSystemSilent)
|
||||
// Loading system presets, don't log substitutions.
|
||||
compatibility_rule = ForwardCompatibilitySubstitutionRule::EnableSilent;
|
||||
else if (compatibility_rule == ForwardCompatibilitySubstitutionRule::EnableSilentDisableSystem)
|
||||
// Loading system presets, throw on unknown option value.
|
||||
compatibility_rule = ForwardCompatibilitySubstitutionRule::Disable;
|
||||
|
||||
// Here the vendor specific read only Config Bundles are stored.
|
||||
boost::filesystem::path dir = (boost::filesystem::path(resources_dir()) / "profiles").make_preferred();
|
||||
PresetsConfigSubstitutions substitutions;
|
||||
std::string errors_cummulative;
|
||||
for (auto &dir_entry : boost::filesystem::directory_iterator(dir)) {
|
||||
std::string vendor_file = dir_entry.path().string();
|
||||
if (Slic3r::is_json_file(vendor_file)) {
|
||||
std::string vendor_name = dir_entry.path().filename().string();
|
||||
// Remove the .json suffix.
|
||||
vendor_name.erase(vendor_name.size() - 5);
|
||||
try {
|
||||
// Load the config bundle, flatten it.
|
||||
append(substitutions, load_vendor_configs_from_json(dir.string(), vendor_name, PresetBundle::LoadVendorOnly, compatibility_rule).first);
|
||||
} catch (const std::runtime_error &err) {
|
||||
errors_cummulative += err.what();
|
||||
errors_cummulative += "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(" finished, errors_cummulative %1%") % errors_cummulative;
|
||||
return std::make_pair(std::move(substitutions), errors_cummulative);
|
||||
}
|
||||
|
||||
std::pair<PresetsConfigSubstitutions, std::string> PresetBundle::load_system_filaments_json(ForwardCompatibilitySubstitutionRule compatibility_rule)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(" enter, compatibility_rule %1%") % compatibility_rule;
|
||||
if (compatibility_rule == ForwardCompatibilitySubstitutionRule::EnableSystemSilent)
|
||||
// Loading system presets, don't log substitutions.
|
||||
compatibility_rule = ForwardCompatibilitySubstitutionRule::EnableSilent;
|
||||
else if (compatibility_rule == ForwardCompatibilitySubstitutionRule::EnableSilentDisableSystem)
|
||||
// Loading system presets, throw on unknown option value.
|
||||
compatibility_rule = ForwardCompatibilitySubstitutionRule::Disable;
|
||||
|
||||
// Here the vendor specific read only Config Bundles are stored.
|
||||
boost::filesystem::path dir = (boost::filesystem::path(resources_dir()) / "profiles").make_preferred();
|
||||
PresetsConfigSubstitutions substitutions;
|
||||
std::string errors_cummulative;
|
||||
bool first = true;
|
||||
for (auto &dir_entry : boost::filesystem::directory_iterator(dir)) {
|
||||
std::string vendor_file = dir_entry.path().string();
|
||||
if (Slic3r::is_json_file(vendor_file)) {
|
||||
std::string vendor_name = dir_entry.path().filename().string();
|
||||
// Remove the .json suffix.
|
||||
vendor_name.erase(vendor_name.size() - 5);
|
||||
try {
|
||||
if (first) {
|
||||
// Reset this PresetBundle and load the first vendor config.
|
||||
append(substitutions, this->load_vendor_configs_from_json(dir.string(), vendor_name, PresetBundle::LoadSystem | PresetBundle::LoadFilamentOnly, compatibility_rule).first);
|
||||
first = false;
|
||||
} else {
|
||||
// Load the other vendor configs, merge them with this PresetBundle.
|
||||
// Report duplicate profiles.
|
||||
PresetBundle other;
|
||||
append(substitutions, other.load_vendor_configs_from_json(dir.string(), vendor_name, PresetBundle::LoadSystem | PresetBundle::LoadFilamentOnly, compatibility_rule).first);
|
||||
std::vector<std::string> duplicates = this->merge_presets(std::move(other));
|
||||
if (!duplicates.empty()) {
|
||||
errors_cummulative += "Found duplicated settings in vendor " + vendor_name + "'s json file lists: ";
|
||||
for (size_t i = 0; i < duplicates.size(); ++i) {
|
||||
if (i > 0) errors_cummulative += ", ";
|
||||
errors_cummulative += duplicates[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (const std::runtime_error &err) {
|
||||
errors_cummulative += err.what();
|
||||
errors_cummulative += "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(" finished, errors_cummulative %1%") % errors_cummulative;
|
||||
return std::make_pair(std::move(substitutions), errors_cummulative);
|
||||
}
|
||||
|
||||
VendorProfile PresetBundle::get_custom_vendor_models() const
|
||||
{
|
||||
VendorProfile vendor;
|
||||
vendor.name = PRESET_CUSTOM_VENDOR;
|
||||
vendor.id = PRESET_CUSTOM_VENDOR;
|
||||
for (auto &preset : printers.get_presets()) {
|
||||
if (preset.is_system) continue;
|
||||
if (printers.get_preset_base(preset) != &preset) continue;
|
||||
if (preset.is_default) continue;
|
||||
auto model = preset.config.opt_string("printer_model");
|
||||
auto variant = preset.config.opt_string("printer_variant");
|
||||
auto iter_model = std::find_if(vendor.models.begin(), vendor.models.end(), [model](VendorProfile::PrinterModel &m) {
|
||||
return m.name == model;
|
||||
});
|
||||
if (iter_model == vendor.models.end()) {
|
||||
iter_model = vendor.models.emplace(vendor.models.end(), VendorProfile::PrinterModel{});
|
||||
iter_model->id = model;
|
||||
iter_model->name = model;
|
||||
iter_model->variants = {VendorProfile::PrinterVariant(variant)};
|
||||
} else {
|
||||
iter_model->variants.push_back(VendorProfile::PrinterVariant(variant));
|
||||
}
|
||||
}
|
||||
return vendor;
|
||||
}
|
||||
|
||||
// Merge one vendor's presets with the other vendor's presets, report duplicates.
|
||||
std::vector<std::string> PresetBundle::merge_presets(PresetBundle &&other)
|
||||
|
|
@ -1181,6 +1440,28 @@ const std::string& PresetBundle::get_preset_name_by_alias( const Preset::Type& p
|
|||
return presets.get_preset_name_by_alias(alias);
|
||||
}
|
||||
|
||||
//BBS: get filament required hrc by filament type
|
||||
const int PresetBundle::get_required_hrc_by_filament_type(const std::string& filament_type) const
|
||||
{
|
||||
static std::unordered_map<std::string, int>filament_type_to_hrc;
|
||||
if (filament_type_to_hrc.empty()) {
|
||||
for (auto iter = filaments.m_presets.begin(); iter != filaments.m_presets.end(); iter++) {
|
||||
if (iter->vendor && iter->vendor->id == "BBL") {
|
||||
if (iter->config.has("filament_type") && iter->config.has("required_nozzle_HRC")) {
|
||||
auto type = iter->config.opt_string("filament_type", 0);
|
||||
auto hrc = iter->config.opt_int("required_nozzle_HRC", 0);
|
||||
filament_type_to_hrc[type] = hrc;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
auto iter = filament_type_to_hrc.find(filament_type);
|
||||
if (iter != filament_type_to_hrc.end())
|
||||
return iter->second;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
//BBS: add project embedded preset logic
|
||||
void PresetBundle::save_changes_for_preset(const std::string& new_name, Preset::Type type,
|
||||
const std::vector<std::string>& unselected_options, bool save_to_project)
|
||||
|
|
@ -1570,7 +1851,8 @@ unsigned int PresetBundle::sync_ams_list(unsigned int &unknowns)
|
|||
filament_colors.push_back(filament_color);
|
||||
continue;
|
||||
}
|
||||
auto iter = std::find_if(filaments.begin(), filaments.end(), [&filament_id](auto &f) { return f.is_compatible && f.is_system && f.filament_id == filament_id; });
|
||||
auto iter = std::find_if(filaments.begin(), filaments.end(), [this, &filament_id](auto &f) {
|
||||
return f.is_compatible && filaments.get_preset_base(f) == &f && f.filament_id == filament_id; });
|
||||
if (iter == filaments.end()) {
|
||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(": filament_id %1% not found or system or compatible") % filament_id;
|
||||
auto filament_type = ams.opt_string("filament_type", 0u);
|
||||
|
|
@ -1582,7 +1864,9 @@ unsigned int PresetBundle::sync_ams_list(unsigned int &unknowns)
|
|||
});
|
||||
}
|
||||
if (iter == filaments.end())
|
||||
iter = std::find_if(filaments.begin(), filaments.end(), [&filament_type](auto &f) { return f.is_compatible && f.is_system; });
|
||||
iter = std::find_if(filaments.begin(), filaments.end(), [&filament_type](auto &f) {
|
||||
return f.is_compatible && f.is_system;
|
||||
});
|
||||
if (iter == filaments.end())
|
||||
continue;
|
||||
++unknowns;
|
||||
|
|
@ -2087,7 +2371,7 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool
|
|||
if (is_external)
|
||||
presets.load_external_preset(name_or_path, name, config.opt_string(key, true), config, different_keys, PresetCollection::LoadAndSelect::Always, file_version, filament_id);
|
||||
else
|
||||
presets.load_preset(presets.path_from_name(name), name, config, selected, file_version, is_custom_defined).save(nullptr);
|
||||
presets.load_preset(presets.path_from_name(name, inherits.empty()), name, config, selected, file_version, is_custom_defined).save(nullptr);
|
||||
};
|
||||
|
||||
switch (Preset::printer_technology(config)) {
|
||||
|
|
@ -2156,7 +2440,7 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool
|
|||
loaded = this->filaments.load_external_preset(name_or_path, name, old_filament_profile_names->values.front(), config, filament_different_keys_set, PresetCollection::LoadAndSelect::Always, file_version, filament_id).first;
|
||||
else {
|
||||
// called from Config Wizard.
|
||||
loaded= &this->filaments.load_preset(this->filaments.path_from_name(name), name, config, true, file_version, is_custom_defined);
|
||||
loaded= &this->filaments.load_preset(this->filaments.path_from_name(name, inherits.empty()), name, config, true, file_version, is_custom_defined);
|
||||
loaded->save(nullptr);
|
||||
}
|
||||
this->filament_presets.clear();
|
||||
|
|
@ -2831,10 +3115,9 @@ std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_vendor_configs_
|
|||
// Enable substitutions for user config bundle, throw an exception when loading a system profile.
|
||||
ConfigSubstitutionContext substitution_context { compatibility_rule };
|
||||
PresetsConfigSubstitutions substitutions;
|
||||
std::string vendor_system_path = data_dir() + "/" + PRESET_SYSTEM_DIR;
|
||||
|
||||
//BBS: add config related logs
|
||||
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(" enter, path %1%, compatibility_rule %2%")%path.c_str()%compatibility_rule;
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(" enter, path %1%, compatibility_rule %2%")%path.c_str()%compatibility_rule;
|
||||
if (flags.has(LoadConfigBundleAttribute::ResetUserProfile) || flags.has(LoadConfigBundleAttribute::LoadSystem))
|
||||
// Reset this bundle, delete user profile files if SaveImported.
|
||||
this->reset(flags.has(LoadConfigBundleAttribute::SaveImported));
|
||||
|
|
@ -2885,7 +3168,7 @@ std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_vendor_configs_
|
|||
auto config_version = Semver::parse(version_str);
|
||||
if (! config_version) {
|
||||
throw ConfigurationError((boost::format("vendor %1%'s config version: %2% invalid\nSuggest cleaning the directory %3% firstly")
|
||||
% vendor_name % version_str %vendor_system_path).str());
|
||||
% vendor_name % version_str % path).str());
|
||||
} else {
|
||||
vendor_profile.config_version = std::move(*config_version);
|
||||
}
|
||||
|
|
@ -2923,10 +3206,16 @@ std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_vendor_configs_
|
|||
catch(nlohmann::detail::parse_error &err) {
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__<< ": parse "<<root_file<<" got a nlohmann::detail::parse_error, reason = " << err.what();
|
||||
throw ConfigurationError((boost::format("Failed loading configuration file %1%: %2%\nSuggest cleaning the directory %3% firstly")
|
||||
%root_file %err.what() %vendor_system_path).str());
|
||||
%root_file %err.what() % path).str());
|
||||
//goto __error_process;
|
||||
}
|
||||
|
||||
if (flags.has(LoadConfigBundleAttribute::LoadFilamentOnly)) {
|
||||
machine_model_subfiles.clear();
|
||||
machine_subfiles.clear();
|
||||
process_subfiles.clear();
|
||||
}
|
||||
|
||||
//2) paste the machine model
|
||||
for (auto& machine_model : machine_model_subfiles)
|
||||
{
|
||||
|
|
@ -3005,7 +3294,7 @@ std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_vendor_configs_
|
|||
catch(nlohmann::detail::parse_error &err) {
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__<< ": parse "<< subfile <<" got a nlohmann::detail::parse_error, reason = " << err.what();
|
||||
throw ConfigurationError((boost::format("Failed loading configuration file %1%: %2%\nSuggest cleaning the directory %3% firstly")
|
||||
%subfile %err.what() %vendor_system_path).str());
|
||||
%subfile %err.what() % path).str());
|
||||
}
|
||||
|
||||
if (! model.id.empty() && ! model.variants.empty())
|
||||
|
|
@ -3091,7 +3380,7 @@ std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_vendor_configs_
|
|||
}
|
||||
config = *default_config;
|
||||
config.apply(config_src);
|
||||
if (instantiation == "false") {
|
||||
if (instantiation == "false" && "Template" != vendor_name) {
|
||||
config_maps.emplace(preset_name, std::move(config));
|
||||
if ((presets_collection->type() == Preset::TYPE_FILAMENT) && (!filament_id.empty()))
|
||||
filament_id_maps.emplace(preset_name, filament_id);
|
||||
|
|
@ -3169,7 +3458,7 @@ std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_vendor_configs_
|
|||
loaded.setting_id = setting_id;
|
||||
loaded.filament_id = filament_id;
|
||||
if (presets_collection->type() == Preset::TYPE_FILAMENT) {
|
||||
if (filament_id.empty()) {
|
||||
if (filament_id.empty() && "Template" != vendor_name) {
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__<< ": can not find filament_id for " << preset_name;
|
||||
//throw ConfigurationError(format("can not find inherits %1% for %2%", inherits, preset_name));
|
||||
reason = "Can not find filament_id for " + preset_name;
|
||||
|
|
@ -3221,7 +3510,7 @@ std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_vendor_configs_
|
|||
//parse error
|
||||
std::string subfile_path = path + "/" + vendor_name + "/" + subfile.second;
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(", got error when parse process setting from %1%") % subfile_path;
|
||||
throw ConfigurationError((boost::format("Failed loading configuration file %1%\nSuggest cleaning the directory %2% firstly") % subfile_path %vendor_system_path).str());
|
||||
throw ConfigurationError((boost::format("Failed loading configuration file %1%\nSuggest cleaning the directory %2% firstly") % subfile_path % path).str());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3236,7 +3525,7 @@ std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_vendor_configs_
|
|||
//parse error
|
||||
std::string subfile_path = path + "/" + vendor_name + "/" + subfile.second;
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(", got error when parse filament setting from %1%") % subfile_path;
|
||||
throw ConfigurationError((boost::format("Failed loading configuration file %1%\nSuggest cleaning the directory %2% firstly") % subfile_path %vendor_system_path).str());
|
||||
throw ConfigurationError((boost::format("Failed loading configuration file %1%\nSuggest cleaning the directory %2% firstly") % subfile_path % path).str());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3251,7 +3540,7 @@ std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_vendor_configs_
|
|||
//parse error
|
||||
std::string subfile_path = path + "/" + vendor_name + "/" + subfile.second;
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(", got error when parse printer setting from %1%") % subfile_path;
|
||||
throw ConfigurationError((boost::format("Failed loading configuration file %1%\nSuggest cleaning the directory %2% firstly") % subfile_path %vendor_system_path).str());
|
||||
throw ConfigurationError((boost::format("Failed loading configuration file %1%\nSuggest cleaning the directory %2% firstly") % subfile_path % path).str());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,14 @@
|
|||
#include <unordered_map>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
|
||||
#define DEFAULT_USER_FOLDER_NAME "default"
|
||||
#define DEFAULT_USER_FOLDER_NAME "default"
|
||||
#define BUNDLE_STRUCTURE_JSON_NAME "bundle_structure.json"
|
||||
|
||||
#define VALIDATE_PRESETS_SUCCESS 0
|
||||
#define VALIDATE_PRESETS_PRINTER_NOT_FOUND 1
|
||||
#define VALIDATE_PRESETS_FILAMENTS_NOT_FOUND 2
|
||||
#define VALIDATE_PRESETS_MODIFIED_GCODES 3
|
||||
|
||||
|
||||
// define an enum class of vendor type
|
||||
enum class VendorType {
|
||||
|
|
@ -57,6 +64,12 @@ public:
|
|||
PresetsConfigSubstitutions load_user_presets(std::string user, ForwardCompatibilitySubstitutionRule rule);
|
||||
PresetsConfigSubstitutions load_user_presets(AppConfig &config, std::map<std::string, std::map<std::string, std::string>>& my_presets, ForwardCompatibilitySubstitutionRule rule);
|
||||
PresetsConfigSubstitutions import_presets(std::vector<std::string> &files, std::function<int(std::string const &)> override_confirm, ForwardCompatibilitySubstitutionRule rule);
|
||||
bool import_json_presets(PresetsConfigSubstitutions & substitutions,
|
||||
std::string & file,
|
||||
std::function<int(std::string const &)> override_confirm,
|
||||
ForwardCompatibilitySubstitutionRule rule,
|
||||
int & overwrite,
|
||||
std::vector<std::string> & result);
|
||||
void save_user_presets(AppConfig& config, std::vector<std::string>& need_to_delete_list);
|
||||
void remove_users_preset(AppConfig &config, std::map<std::string, std::map<std::string, std::string>> * my_presets = nullptr);
|
||||
void update_user_presets_directory(const std::string preset_folder);
|
||||
|
|
@ -64,7 +77,7 @@ public:
|
|||
void update_system_preset_setting_ids(std::map<std::string, std::map<std::string, std::string>>& system_presets);
|
||||
|
||||
//BBS: add API to get previous machine
|
||||
bool validate_printers(const std::string &name, DynamicPrintConfig& config);
|
||||
int validate_presets(const std::string &file_name, DynamicPrintConfig& config, std::set<std::string>& different_gcodes);
|
||||
|
||||
//BBS: add function to generate differed preset for save
|
||||
//the pointer should be freed by the caller
|
||||
|
|
@ -173,6 +186,7 @@ public:
|
|||
// Load a system config bundle.
|
||||
LoadSystem,
|
||||
LoadVendorOnly,
|
||||
LoadFilamentOnly,
|
||||
};
|
||||
using LoadConfigBundleAttributes = enum_bitmask<LoadConfigBundleAttribute>;
|
||||
// Load the config bundle based on the flags.
|
||||
|
|
@ -189,7 +203,7 @@ public:
|
|||
//void export_current_configbundle(const std::string &path);
|
||||
//BBS: add a function to export system presets for cloud-slicer
|
||||
//void export_system_configs(const std::string &path);
|
||||
std::vector<std::string> export_current_configs(const std::string &path, std::function<int(std::string const &)> override_confirm,
|
||||
std::vector<std::string> export_current_configs(const std::string &path, std::function<int(std::string const &)> override_confirm,
|
||||
bool include_modify, bool export_system_settings = false);
|
||||
|
||||
// Enable / disable the "- default -" preset.
|
||||
|
|
@ -218,11 +232,16 @@ public:
|
|||
|
||||
const std::string& get_preset_name_by_alias(const Preset::Type& preset_type, const std::string& alias) const;
|
||||
|
||||
const int get_required_hrc_by_filament_type(const std::string& filament_type) const;
|
||||
// Save current preset of a provided type under a new name. If the name is different from the old one,
|
||||
// Unselected option would be reverted to the beginning values
|
||||
//BBS: add project embedded preset logic
|
||||
void save_changes_for_preset(const std::string& new_name, Preset::Type type, const std::vector<std::string>& unselected_options, bool save_to_project = false);
|
||||
|
||||
std::pair<PresetsConfigSubstitutions, std::string> load_system_models_from_json(ForwardCompatibilitySubstitutionRule compatibility_rule);
|
||||
std::pair<PresetsConfigSubstitutions, std::string> load_system_filaments_json(ForwardCompatibilitySubstitutionRule compatibility_rule);
|
||||
VendorProfile get_custom_vendor_models() const;
|
||||
|
||||
//BBS: add BBL as default
|
||||
static const char *BBL_BUNDLE;
|
||||
static const char *BBL_DEFAULT_PRINTER_MODEL;
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
#include "Geometry/ConvexHull.hpp"
|
||||
#include "I18N.hpp"
|
||||
#include "ShortestPath.hpp"
|
||||
#include "SupportMaterial.hpp"
|
||||
#include "Support/SupportMaterial.hpp"
|
||||
#include "Thread.hpp"
|
||||
#include "Time.hpp"
|
||||
#include "GCode.hpp"
|
||||
|
|
@ -102,6 +102,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|
|||
"printable_area",
|
||||
//BBS: add bed_exclude_area
|
||||
"bed_exclude_area",
|
||||
"thumbnail_size",
|
||||
"before_layer_change_gcode",
|
||||
"enable_pressure_advance",
|
||||
"pressure_advance",
|
||||
|
|
@ -113,6 +114,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|
|||
"deretraction_speed",
|
||||
"close_fan_the_first_x_layers",
|
||||
"machine_end_gcode",
|
||||
"printing_by_object_gcode",
|
||||
"filament_end_gcode",
|
||||
"post_process",
|
||||
"extruder_clearance_height_to_rod",
|
||||
|
|
@ -183,6 +185,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|
|||
"nozzle_hrc",
|
||||
"required_nozzle_HRC",
|
||||
"upward_compatible_machine",
|
||||
"is_infill_first",
|
||||
// Orca
|
||||
"chamber_temperature",
|
||||
"thumbnails",
|
||||
|
|
@ -310,7 +313,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|
|||
//|| opt_key == "resolution"
|
||||
//BBS: when enable arc fitting, we must re-generate perimeter
|
||||
|| opt_key == "enable_arc_fitting"
|
||||
|| opt_key == "wall_infill_order") {
|
||||
|| opt_key == "wall_sequence") {
|
||||
osteps.emplace_back(posPerimeters);
|
||||
osteps.emplace_back(posEstimateCurledExtrusions);
|
||||
osteps.emplace_back(posInfill);
|
||||
|
|
@ -1145,19 +1148,19 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons*
|
|||
if (nozzle_diam - EPSILON > first_nozzle_diam || nozzle_diam + EPSILON < first_nozzle_diam
|
||||
|| std::abs((filament_diam - first_filament_diam) / first_filament_diam) > 0.1)
|
||||
// BBS: remove L()
|
||||
return { ("Different nozzle diameters and different filament diameters is not allowed when prime tower is enabled.") };
|
||||
return { L("Different nozzle diameters and different filament diameters is not allowed when prime tower is enabled.") };
|
||||
}
|
||||
|
||||
if (! m_config.use_relative_e_distances)
|
||||
return { ("The Wipe Tower is currently only supported with the relative extruder addressing (use_relative_e_distances=1).") };
|
||||
return { L("The Wipe Tower is currently only supported with the relative extruder addressing (use_relative_e_distances=1).") };
|
||||
if (m_config.ooze_prevention)
|
||||
return { ("Ooze prevention is currently not supported with the prime tower enabled.") };
|
||||
return { L("Ooze prevention is currently not supported with the prime tower enabled.") };
|
||||
|
||||
// BBS: remove following logic and _L()
|
||||
#if 0
|
||||
if (m_config.gcode_flavor != gcfRepRapSprinter && m_config.gcode_flavor != gcfRepRapFirmware &&
|
||||
m_config.gcode_flavor != gcfRepetier && m_config.gcode_flavor != gcfMarlinLegacy && m_config.gcode_flavor != gcfMarlinFirmware)
|
||||
return {("The prime tower is currently only supported for the Marlin, RepRap/Sprinter, RepRapFirmware and Repetier G-code flavors.")};
|
||||
return { L("The prime tower is currently only supported for the Marlin, RepRap/Sprinter, RepRapFirmware and Repetier G-code flavors.")};
|
||||
|
||||
if ((m_config.print_sequence == PrintSequence::ByObject) && extruders.size() > 1)
|
||||
return { L("The prime tower is not supported in \"By object\" print."), nullptr, "enable_prime_tower" };
|
||||
|
|
@ -1339,13 +1342,6 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons*
|
|||
if (layer_height > min_nozzle_diameter)
|
||||
return {L("Layer height cannot exceed nozzle diameter"), object, "layer_height"};
|
||||
|
||||
for (auto range : object->m_model_object->layer_config_ranges) {
|
||||
double range_layer_height = range.second.opt_float("layer_height");
|
||||
if (range_layer_height > object->m_slicing_params.max_layer_height ||
|
||||
range_layer_height < object->m_slicing_params.min_layer_height)
|
||||
return { L("Layer height cannot exceed nozzle diameter"), nullptr, "layer_height" };
|
||||
}
|
||||
|
||||
// Validate extrusion widths.
|
||||
std::string err_msg;
|
||||
if (!validate_extrusion_width(object->config(), "line_width", layer_height, err_msg))
|
||||
|
|
@ -1626,16 +1622,21 @@ std::map<ObjectID, unsigned int> getObjectExtruderMap(const Print& print) {
|
|||
std::map<ObjectID, unsigned int> objectExtruderMap;
|
||||
for (const PrintObject* object : print.objects()) {
|
||||
// BBS
|
||||
unsigned int objectFirstLayerFirstExtruder = print.config().filament_diameter.size();
|
||||
auto firstLayerRegions = object->layers().front()->regions();
|
||||
if (!firstLayerRegions.empty()) {
|
||||
for (const LayerRegion* regionPtr : firstLayerRegions) {
|
||||
if (regionPtr -> has_extrusions())
|
||||
objectFirstLayerFirstExtruder = std::min(objectFirstLayerFirstExtruder,
|
||||
regionPtr->region().extruder(frExternalPerimeter));
|
||||
if (object->object_first_layer_wall_extruders.empty()){
|
||||
unsigned int objectFirstLayerFirstExtruder = print.config().filament_diameter.size();
|
||||
auto firstLayerRegions = object->layers().front()->regions();
|
||||
if (!firstLayerRegions.empty()) {
|
||||
for (const LayerRegion* regionPtr : firstLayerRegions) {
|
||||
if (regionPtr->has_extrusions())
|
||||
objectFirstLayerFirstExtruder = std::min(objectFirstLayerFirstExtruder,
|
||||
regionPtr->region().extruder(frExternalPerimeter));
|
||||
}
|
||||
}
|
||||
objectExtruderMap.insert(std::make_pair(object->id(), objectFirstLayerFirstExtruder));
|
||||
}
|
||||
else {
|
||||
objectExtruderMap.insert(std::make_pair(object->id(), object->object_first_layer_wall_extruders.front()));
|
||||
}
|
||||
objectExtruderMap.insert(std::make_pair(object->id(), objectFirstLayerFirstExtruder));
|
||||
}
|
||||
return objectExtruderMap;
|
||||
}
|
||||
|
|
@ -1841,6 +1842,7 @@ void Print::process(long long *time_cost_with_cache, bool use_cache)
|
|||
obj->infill();
|
||||
obj->ironing();
|
||||
obj->generate_support_material();
|
||||
obj->detect_overhangs_for_lift();
|
||||
obj->estimate_curled_extrusions();
|
||||
}
|
||||
}
|
||||
|
|
@ -1980,7 +1982,15 @@ void Print::process(long long *time_cost_with_cache, bool use_cache)
|
|||
}
|
||||
|
||||
// BBS
|
||||
if(!m_no_check)
|
||||
bool has_adaptive_layer_height = false;
|
||||
for (PrintObject* obj : m_objects) {
|
||||
if (obj->model_object()->layer_height_profile.empty() == false) {
|
||||
has_adaptive_layer_height = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// TODO adaptive layer height won't work with conflict checker because m_fake_wipe_tower's path is generated using fixed layer height
|
||||
if(!m_no_check && !has_adaptive_layer_height)
|
||||
{
|
||||
using Clock = std::chrono::high_resolution_clock;
|
||||
auto startTime = Clock::now();
|
||||
|
|
|
|||
|
|
@ -437,6 +437,9 @@ public:
|
|||
// BBS: Boundingbox of the first layer
|
||||
BoundingBox firstLayerObjectBrimBoundingBox;
|
||||
|
||||
// BBS: returns 1-based indices of extruders used to print the first layer wall of objects
|
||||
std::vector<int> object_first_layer_wall_extruders;
|
||||
|
||||
// SoftFever
|
||||
size_t get_id() const { return m_id; }
|
||||
void set_id(size_t id) { m_id = id; }
|
||||
|
|
@ -528,6 +531,7 @@ private:
|
|||
|
||||
std::vector < VolumeSlices > firstLayerObjSliceByVolume;
|
||||
std::vector<groupedVolumeSlices> firstLayerObjSliceByGroups;
|
||||
|
||||
// BBS: per object skirt
|
||||
ExtrusionEntityCollection m_skirt;
|
||||
|
||||
|
|
@ -590,8 +594,6 @@ struct FakeWipeTower
|
|||
|
||||
std::vector<ExtrusionPaths> getFakeExtrusionPathsFromWipeTower() const
|
||||
{
|
||||
float h = height;
|
||||
float lh = layer_height;
|
||||
int d = scale_(depth);
|
||||
int w = scale_(width);
|
||||
int bd = scale_(brim_width);
|
||||
|
|
@ -599,13 +601,13 @@ struct FakeWipeTower
|
|||
Point maxCorner = {minCorner.x() + w, minCorner.y() + d};
|
||||
|
||||
std::vector<ExtrusionPaths> paths;
|
||||
for (float hh = 0.f; hh < h; hh += lh) {
|
||||
ExtrusionPath path(ExtrusionRole::erWipeTower, 0.0, 0.0, lh);
|
||||
for (float h = 0.f; h < height; h += layer_height) {
|
||||
ExtrusionPath path(ExtrusionRole::erWipeTower, 0.0, 0.0, layer_height);
|
||||
path.polyline = {minCorner, {maxCorner.x(), minCorner.y()}, maxCorner, {minCorner.x(), maxCorner.y()}, minCorner};
|
||||
paths.push_back({path});
|
||||
|
||||
if (hh == 0.f) { // add brim
|
||||
ExtrusionPath fakeBrim(ExtrusionRole::erBrim, 0.0, 0.0, lh);
|
||||
if (h == 0.f) { // add brim
|
||||
ExtrusionPath fakeBrim(ExtrusionRole::erBrim, 0.0, 0.0, layer_height);
|
||||
Point wtbminCorner = {minCorner - Point{bd, bd}};
|
||||
Point wtbmaxCorner = {maxCorner + Point{bd, bd}};
|
||||
fakeBrim.polyline = {wtbminCorner, {wtbmaxCorner.x(), wtbminCorner.y()}, wtbmaxCorner, {wtbminCorner.x(), wtbmaxCorner.y()}, wtbminCorner};
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ enum StringExceptionType {
|
|||
STRING_EXCEPT_FILAMENTS_DIFFERENT_TEMP = 2,
|
||||
STRING_EXCEPT_OBJECT_COLLISION_IN_SEQ_PRINT = 3,
|
||||
STRING_EXCEPT_OBJECT_COLLISION_IN_LAYER_PRINT = 4,
|
||||
STRING_EXCEPT_LAYER_HEIGHT_EXCEEDS_LIMIT = 5,
|
||||
STRING_EXCEPT_COUNT
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -179,6 +179,15 @@ static t_config_enum_values s_keys_map_WallInfillOrder {
|
|||
};
|
||||
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(WallInfillOrder)
|
||||
|
||||
//BBS
|
||||
static t_config_enum_values s_keys_map_WallSequence {
|
||||
{ "inner wall/outer wall", int(WallSequence::InnerOuter) },
|
||||
{ "outer wall/inner wall", int(WallSequence::OuterInner) },
|
||||
{ "inner-outer-inner wall", int(WallSequence::InnerOuterInner)}
|
||||
|
||||
};
|
||||
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(WallSequence)
|
||||
|
||||
//BBS
|
||||
static t_config_enum_values s_keys_map_PrintSequence {
|
||||
{ "by layer", int(PrintSequence::ByLayer) },
|
||||
|
|
@ -309,6 +318,13 @@ static const t_config_enum_values s_keys_map_BedType = {
|
|||
};
|
||||
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(BedType)
|
||||
|
||||
// BBS
|
||||
static const t_config_enum_values s_keys_map_FirstLayerSeq = {
|
||||
{ "Auto", flsAuto },
|
||||
{ "Customize", flsCutomize },
|
||||
};
|
||||
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(FirstLayerSeq)
|
||||
|
||||
static t_config_enum_values s_keys_map_NozzleType {
|
||||
{ "undefine", int(NozzleType::ntUndefine) },
|
||||
{ "hardened_steel", int(NozzleType::ntHardenedSteel) },
|
||||
|
|
@ -405,11 +421,13 @@ void PrintConfigDef::init_common_params()
|
|||
def = this->add("bed_custom_texture", coString);
|
||||
def->label = L("Bed custom texture");
|
||||
def->mode = comAdvanced;
|
||||
def->gui_type = ConfigOptionDef::GUIType::one_string;
|
||||
def->set_default_value(new ConfigOptionString(""));
|
||||
|
||||
def = this->add("bed_custom_model", coString);
|
||||
def->label = L("Bed custom model");
|
||||
def->mode = comAdvanced;
|
||||
def->gui_type = ConfigOptionDef::GUIType::one_string;
|
||||
def->set_default_value(new ConfigOptionString(""));
|
||||
|
||||
def = this->add("elefant_foot_compensation", coFloat);
|
||||
|
|
@ -677,6 +695,17 @@ void PrintConfigDef::init_fff_params()
|
|||
def->max = 16;
|
||||
def->set_default_value(new ConfigOptionInts{0});
|
||||
|
||||
def = this->add("first_layer_sequence_choice", coEnum);
|
||||
def->category = L("Quality");
|
||||
def->label = L("First layer filament sequence");
|
||||
def->enum_keys_map = &ConfigOptionEnum<FirstLayerSeq>::get_enum_values();
|
||||
def->enum_values.push_back("Auto");
|
||||
def->enum_values.push_back("Customize");
|
||||
def->enum_labels.push_back(L("Auto"));
|
||||
def->enum_labels.push_back(L("Customize"));
|
||||
def->mode = comSimple;
|
||||
def->set_default_value(new ConfigOptionEnum<FirstLayerSeq>(flsAuto));
|
||||
|
||||
def = this->add("before_layer_change_gcode", coString);
|
||||
def->label = L("Before layer change G-code");
|
||||
def->tooltip = L("This G-code is inserted at every layer change before lifting z");
|
||||
|
|
@ -1191,6 +1220,15 @@ void PrintConfigDef::init_fff_params()
|
|||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionString("M104 S0 ; turn off temperature\nG28 X0 ; home X axis\nM84 ; disable motors\n"));
|
||||
|
||||
def = this->add("printing_by_object_gcode", coString);
|
||||
def->label = L("Between Object Gcode");
|
||||
def->tooltip = L("Insert Gcode between objects. This parameter will only come into effect when you print your models object by object");
|
||||
def->multiline = true;
|
||||
def->full_width = true;
|
||||
def->height = 12;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionString(""));
|
||||
|
||||
def = this->add("filament_end_gcode", coStrings);
|
||||
def->label = L("End G-code");
|
||||
def->tooltip = L("End G-code when finish the printing of this filament");
|
||||
|
|
@ -1292,23 +1330,26 @@ void PrintConfigDef::init_fff_params()
|
|||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(0));
|
||||
|
||||
def = this->add("wall_infill_order", coEnum);
|
||||
def->label = L("Order of inner wall/outer wall/infil");
|
||||
def = this->add("wall_sequence", coEnum);
|
||||
def->label = L("Order of walls");
|
||||
def->category = L("Quality");
|
||||
def->tooltip = L("Print sequence of inner wall, outer wall and infill. ");
|
||||
def->enum_keys_map = &ConfigOptionEnum<WallInfillOrder>::get_enum_values();
|
||||
def->enum_values.push_back("inner wall/outer wall/infill");
|
||||
def->enum_values.push_back("outer wall/inner wall/infill");
|
||||
def->enum_values.push_back("infill/inner wall/outer wall");
|
||||
def->enum_values.push_back("infill/outer wall/inner wall");
|
||||
def->enum_values.push_back("inner-outer-inner wall/infill");
|
||||
def->enum_labels.push_back(L("inner/outer/infill"));
|
||||
def->enum_labels.push_back(L("outer/inner/infill"));
|
||||
def->enum_labels.push_back(L("infill/inner/outer"));
|
||||
def->enum_labels.push_back(L("infill/outer/inner"));
|
||||
def->enum_labels.push_back(L("inner-outer-inner/infill"));
|
||||
def->tooltip = L("Print sequence of inner wall and outer wall. ");
|
||||
def->enum_keys_map = &ConfigOptionEnum<WallSequence>::get_enum_values();
|
||||
def->enum_values.push_back("inner wall/outer wall");
|
||||
def->enum_values.push_back("outer wall/inner wall");
|
||||
def->enum_values.push_back("inner-outer-inner wall");
|
||||
def->enum_labels.push_back(L("inner/outer"));
|
||||
def->enum_labels.push_back(L("outer/inner"));
|
||||
def->enum_labels.push_back(L("inner wall/outer wall/inner wall"));
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionEnum<WallInfillOrder>(WallInfillOrder::InnerOuterInfill));
|
||||
def->set_default_value(new ConfigOptionEnum<WallSequence>(WallSequence::InnerOuter));
|
||||
|
||||
def = this->add("is_infill_first",coBool);
|
||||
def->label = L("Print infill first");
|
||||
def->tooltip = L("Order of wall/infill. false means print wall first. ");
|
||||
def->category = L("Quality");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionBool{false});
|
||||
|
||||
def = this->add("extruder", coInt);
|
||||
def->gui_type = ConfigOptionDef::GUIType::i_enum_open;
|
||||
|
|
@ -1906,7 +1947,7 @@ def = this->add("filament_loading_speed", coFloats);
|
|||
def = this->add("accel_to_decel_factor", coPercent);
|
||||
def->label = L("accel_to_decel");
|
||||
def->tooltip = L("Klipper's max_accel_to_decel will be adjusted to this %% of acceleration");
|
||||
def->sidetext = L("%%");
|
||||
def->sidetext = L("%");
|
||||
def->min = 1;
|
||||
def->max = 100;
|
||||
def->mode = comAdvanced;
|
||||
|
|
@ -2390,6 +2431,27 @@ def = this->add("filament_loading_speed", coFloats);
|
|||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("mmu_segmented_region_max_width", coFloat);
|
||||
def->label = L("Maximum width of a segmented region");
|
||||
def->tooltip = L("Maximum width of a segmented region. Zero disables this feature.");
|
||||
def->sidetext = L("mm");
|
||||
def->min = 0;
|
||||
def->category = L("Advanced");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(0.));
|
||||
|
||||
def = this->add("mmu_segmented_region_interlocking_depth", coFloat);
|
||||
def->label = L("Interlocking depth of a segmented region");
|
||||
//def->tooltip = L("Interlocking depth of a segmented region. It will be ignored if "
|
||||
// "\"mmu_segmented_region_max_width\" is zero or if \"mmu_segmented_region_interlocking_depth\""
|
||||
// "is bigger then \"mmu_segmented_region_max_width\". Zero disables this feature.");
|
||||
def->tooltip = L("Interlocking depth of a segmented region. Zero disables this feature.");
|
||||
def->sidetext = L("mm"); //(zero to disable)
|
||||
def->min = 0;
|
||||
def->category = L("Advanced");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(0.));
|
||||
|
||||
def = this->add("ironing_type", coEnum);
|
||||
def->label = L("Ironing Type");
|
||||
def->category = L("Quality");
|
||||
|
|
@ -3072,8 +3134,27 @@ def = this->add("filament_loading_speed", coFloats);
|
|||
"Using spiral line to lift z can prevent stringing");
|
||||
def->sidetext = L("mm");
|
||||
def->mode = comSimple;
|
||||
def->min = 0;
|
||||
def->max = 5;
|
||||
def->set_default_value(new ConfigOptionFloats { 0.4 });
|
||||
|
||||
def = this->add("retract_lift_above", coFloats);
|
||||
def->label = L("Z hop lower boundary");
|
||||
def->tooltip = L("Z hop will only come into effect when Z is above this value and is below the parameter: \"Z hop upper boundary\"");
|
||||
def->sidetext = L("mm");
|
||||
def->mode = comAdvanced;
|
||||
def->min = 0;
|
||||
def->set_default_value(new ConfigOptionFloats{0.});
|
||||
|
||||
def = this->add("retract_lift_below", coFloats);
|
||||
def->label = L("Z hop upper boundary");
|
||||
def->tooltip = L("If this value is positive, Z hop will only come into effect when Z is above the parameter: \"Z hop lower boundary\" and is below this value");
|
||||
def->sidetext = L("mm");
|
||||
def->mode = comAdvanced;
|
||||
def->min = 0;
|
||||
def->set_default_value(new ConfigOptionFloats{0.});
|
||||
|
||||
|
||||
def = this->add("z_hop_types", coEnums);
|
||||
def->label = L("Z hop type");
|
||||
def->tooltip = L("Z hop type");
|
||||
|
|
@ -3223,7 +3304,7 @@ def = this->add("filament_loading_speed", coFloats);
|
|||
def->tooltip = L("Distance from skirt to brim or object");
|
||||
def->sidetext = L("mm");
|
||||
def->min = 0;
|
||||
def->max = 10;
|
||||
def->max = 60;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(2));
|
||||
|
||||
|
|
@ -3570,7 +3651,14 @@ def = this->add("filament_loading_speed", coFloats);
|
|||
def->tooltip = L("Filament to print support base and raft. \"Default\" means no specific filament for support and current filament is used");
|
||||
def->min = 0;
|
||||
def->mode = comSimple;
|
||||
def->set_default_value(new ConfigOptionInt(1));
|
||||
def->set_default_value(new ConfigOptionInt(0));
|
||||
|
||||
def = this->add("support_interface_not_for_body",coBool);
|
||||
def->label = L("Reduce interface filament for base");
|
||||
def->category = L("Support");
|
||||
def->tooltip = L("Avoid using support interface filament to print support base");
|
||||
def->mode = comSimple;
|
||||
def->set_default_value(new ConfigOptionBool(true));
|
||||
|
||||
def = this->add("support_line_width", coFloatOrPercent);
|
||||
def->label = L("Support");
|
||||
|
|
@ -3599,7 +3687,7 @@ def = this->add("filament_loading_speed", coFloats);
|
|||
def->min = 0;
|
||||
// BBS
|
||||
def->mode = comSimple;
|
||||
def->set_default_value(new ConfigOptionInt(1));
|
||||
def->set_default_value(new ConfigOptionInt(0));
|
||||
|
||||
auto support_interface_top_layers = def = this->add("support_interface_top_layers", coInt);
|
||||
def->gui_type = ConfigOptionDef::GUIType::i_enum_open;
|
||||
|
|
@ -3623,14 +3711,12 @@ def = this->add("filament_loading_speed", coFloats);
|
|||
def->gui_type = ConfigOptionDef::GUIType::i_enum_open;
|
||||
def->label = L("Bottom interface layers");
|
||||
def->category = L("Support");
|
||||
//def->tooltip = L("Number of bottom interface layers. "
|
||||
// "-1 means same with use top interface layers");
|
||||
def->tooltip = L("Number of bottom interface layers");
|
||||
def->sidetext = L("layers");
|
||||
def->min = -1;
|
||||
def->enum_values.push_back("-1");
|
||||
append(def->enum_values, support_interface_top_layers->enum_values);
|
||||
//TRN To be shown in Print Settings "Bottom interface layers". Have to be as short as possible
|
||||
def->enum_labels.push_back("-1");
|
||||
def->enum_labels.push_back(L("Same as top"));
|
||||
append(def->enum_labels, support_interface_top_layers->enum_labels);
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionInt(0));
|
||||
|
|
@ -3681,7 +3767,7 @@ def = this->add("filament_loading_speed", coFloats);
|
|||
def->enum_labels.push_back(L("Lightning"));
|
||||
def->enum_labels.push_back(L("Hollow"));
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionEnum<SupportMaterialPattern>(smpRectilinear));
|
||||
def->set_default_value(new ConfigOptionEnum<SupportMaterialPattern>(smpDefault));
|
||||
|
||||
def = this->add("support_interface_pattern", coEnum);
|
||||
def->label = L("Interface pattern");
|
||||
|
|
@ -3701,7 +3787,7 @@ def = this->add("filament_loading_speed", coFloats);
|
|||
def->enum_labels.push_back(L("Rectilinear Interlaced"));
|
||||
def->enum_labels.push_back(L("Grid"));
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionEnum<SupportMaterialInterfacePattern>(smipRectilinear));
|
||||
def->set_default_value(new ConfigOptionEnum<SupportMaterialInterfacePattern>(smipAuto));
|
||||
|
||||
def = this->add("support_base_pattern_spacing", coFloat);
|
||||
def->label = L("Base pattern spacing");
|
||||
|
|
@ -3919,12 +4005,12 @@ def = this->add("filament_loading_speed", coFloats);
|
|||
def->set_default_value(new ConfigOptionFloat(3.));
|
||||
|
||||
def = this->add("tree_support_wall_count", coInt);
|
||||
def->label = L("Tree support wall loops");
|
||||
def->label = L("Support wall loops");
|
||||
def->category = L("Support");
|
||||
def->tooltip = L("This setting specify the count of walls around tree support");
|
||||
def->tooltip = L("This setting specify the count of walls around support");
|
||||
def->min = 0;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionInt(1));
|
||||
def->set_default_value(new ConfigOptionInt(0));
|
||||
|
||||
def = this->add("tree_support_with_infill", coBool);
|
||||
def->label = L("Tree support with infill");
|
||||
|
|
@ -4126,7 +4212,7 @@ def = this->add("filament_loading_speed", coFloats);
|
|||
//def->sidetext = L("mm");
|
||||
def->mode = comDevelop;
|
||||
// BBS: change data type to floats to add partplate logic
|
||||
def->set_default_value(new ConfigOptionFloats{ 165.-10. });
|
||||
def->set_default_value(new ConfigOptionFloats{ 15. });
|
||||
|
||||
def = this->add("wipe_tower_y", coFloats);
|
||||
//def->label = L("Position Y");
|
||||
|
|
@ -5207,6 +5293,19 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va
|
|||
}
|
||||
} else if (opt_key == "overhang_fan_threshold" && value == "5%") {
|
||||
value = "10%";
|
||||
} else if( opt_key == "wall_infill_order" ) {
|
||||
if (value == "inner wall/outer wall/infill" || value == "infill/inner wall/outer wall") {
|
||||
opt_key = "wall_sequence";
|
||||
value = "inner wall/outer wall";
|
||||
} else if (value == "outer wall/inner wall/infill" || value == "infill/outer wall/inner wall") {
|
||||
opt_key = "wall_sequence";
|
||||
value = "outer wall/inner wall";
|
||||
} else if (value == "inner-outer-inner wall/infill") {
|
||||
opt_key = "wall_sequence";
|
||||
value = "inner-outer-inner wall";
|
||||
} else {
|
||||
opt_key = "wall_sequence";
|
||||
}
|
||||
} else if(opt_key == "single_extruder_multi_material") {
|
||||
value = "1";
|
||||
}
|
||||
|
|
@ -5229,6 +5328,9 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va
|
|||
else if (opt_key == "initial_layer_flow_ratio") {
|
||||
opt_key = "bottom_solid_infill_flow_ratio";
|
||||
}
|
||||
else if(opt_key == "ironing_direction") {
|
||||
opt_key = "ironing_angle";
|
||||
}
|
||||
|
||||
// Ignore the following obsolete configuration keys:
|
||||
static std::set<std::string> ignore = {
|
||||
|
|
@ -5245,7 +5347,7 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va
|
|||
"can_switch_nozzle_type", "can_add_auxiliary_fan", "extra_flush_volume", "spaghetti_detector", "adaptive_layer_height",
|
||||
"z_hop_type", "z_lift_type", "bed_temperature_difference",
|
||||
"extruder_type",
|
||||
"internal_bridge_support_thickness","extruder_clearance_max_radius"
|
||||
"internal_bridge_support_thickness","extruder_clearance_max_radius", "top_area_threshold"
|
||||
};
|
||||
|
||||
if (ignore.find(opt_key) != ignore.end()) {
|
||||
|
|
@ -5888,20 +5990,20 @@ CLIActionsConfigDef::CLIActionsConfigDef()
|
|||
def->set_default_value(new ConfigOptionBool(false));*/
|
||||
|
||||
def = this->add("export_3mf", coString);
|
||||
def->label = L("Export 3MF");
|
||||
def->tooltip = L("Export project as 3MF.");
|
||||
def->label = "Export 3MF";
|
||||
def->tooltip = "Export project as 3MF.";
|
||||
def->cli_params = "filename.3mf";
|
||||
def->set_default_value(new ConfigOptionString("output.3mf"));
|
||||
|
||||
def = this->add("export_slicedata", coString);
|
||||
def->label = L("Export slicing data");
|
||||
def->tooltip = L("Export slicing data to a folder.");
|
||||
def->label = "Export slicing data";
|
||||
def->tooltip = "Export slicing data to a folder.";
|
||||
def->cli_params = "slicing_data_directory";
|
||||
def->set_default_value(new ConfigOptionString("cached_data"));
|
||||
|
||||
def = this->add("load_slicedata", coStrings);
|
||||
def->label = L("Load slicing data");
|
||||
def->tooltip = L("Load cached slicing data from directory");
|
||||
def->label = "Load slicing data";
|
||||
def->tooltip = "Load cached slicing data from directory";
|
||||
def->cli_params = "slicing_data_directory";
|
||||
def->set_default_value(new ConfigOptionString("cached_data"));
|
||||
|
||||
|
|
@ -5911,8 +6013,8 @@ CLIActionsConfigDef::CLIActionsConfigDef()
|
|||
def->set_default_value(new ConfigOptionBool(false));*/
|
||||
|
||||
def = this->add("export_stl", coBool);
|
||||
def->label = L("Export STL");
|
||||
def->tooltip = L("Export the objects as multiple STL.");
|
||||
def->label = "Export STL";
|
||||
def->tooltip = "Export the objects as multiple STL.";
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
/*def = this->add("export_gcode", coBool);
|
||||
|
|
@ -5929,27 +6031,33 @@ CLIActionsConfigDef::CLIActionsConfigDef()
|
|||
def->set_default_value(new ConfigOptionBool(false));*/
|
||||
|
||||
def = this->add("slice", coInt);
|
||||
def->label = L("Slice");
|
||||
def->tooltip = L("Slice the plates: 0-all plates, i-plate i, others-invalid");
|
||||
def->label = "Slice";
|
||||
def->tooltip = "Slice the plates: 0-all plates, i-plate i, others-invalid";
|
||||
def->cli = "slice";
|
||||
def->cli_params = "option";
|
||||
def->set_default_value(new ConfigOptionInt(0));
|
||||
|
||||
def = this->add("help", coBool);
|
||||
def->label = L("Help");
|
||||
def->tooltip = L("Show command help.");
|
||||
def->label = "Help";
|
||||
def->tooltip = "Show command help.";
|
||||
def->cli = "help|h";
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("uptodate", coBool);
|
||||
def->label = L("UpToDate");
|
||||
def->tooltip = L("Update the configs values of 3mf to latest.");
|
||||
def->label = "UpToDate";
|
||||
def->tooltip = "Update the configs values of 3mf to latest.";
|
||||
def->cli = "uptodate";
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("load_defaultfila", coBool);
|
||||
def->label = L("Load default filaments");
|
||||
def->tooltip = L("Load first filament as default for those not loaded");
|
||||
def->label = "Load default filaments";
|
||||
def->tooltip = "Load first filament as default for those not loaded";
|
||||
def->cli_params = "option";
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("min_save", coBool);
|
||||
def->label = "Minimum save";
|
||||
def->tooltip = "export 3mf with minimum size.";
|
||||
def->cli_params = "option";
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
|
|
@ -5960,15 +6068,15 @@ CLIActionsConfigDef::CLIActionsConfigDef()
|
|||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("mtcpp", coInt);
|
||||
def->label = L("mtcpp");
|
||||
def->tooltip = L("max triangle count per plate for slicing.");
|
||||
def->label = "mtcpp";
|
||||
def->tooltip = "max triangle count per plate for slicing.";
|
||||
def->cli = "mtcpp";
|
||||
def->cli_params = "count";
|
||||
def->set_default_value(new ConfigOptionInt(1000000));
|
||||
|
||||
def = this->add("mstpp", coInt);
|
||||
def->label = L("mstpp");
|
||||
def->tooltip = L("max slicing time per plate in seconds.");
|
||||
def->label = "mstpp";
|
||||
def->tooltip = "max slicing time per plate in seconds.";
|
||||
def->cli = "mstpp";
|
||||
def->cli_params = "time";
|
||||
def->set_default_value(new ConfigOptionInt(300));
|
||||
|
|
@ -5977,12 +6085,11 @@ CLIActionsConfigDef::CLIActionsConfigDef()
|
|||
def = this->add("no_check", coBool);
|
||||
def->label = L("No check");
|
||||
def->tooltip = L("Do not run any validity checks, such as gcode path conflicts check.");
|
||||
def->cli_params = "option";
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("normative_check", coBool);
|
||||
def->label = L("Normative check");
|
||||
def->tooltip = L("Check the normative items.");
|
||||
def->label = "Normative check";
|
||||
def->tooltip = "Check the normative items.";
|
||||
def->cli_params = "option";
|
||||
def->set_default_value(new ConfigOptionBool(true));
|
||||
|
||||
|
|
@ -5997,19 +6104,19 @@ CLIActionsConfigDef::CLIActionsConfigDef()
|
|||
def->set_default_value(new ConfigOptionBool(false));*/
|
||||
|
||||
def = this->add("info", coBool);
|
||||
def->label = L("Output Model Info");
|
||||
def->tooltip = L("Output the model's information.");
|
||||
def->label = "Output Model Info";
|
||||
def->tooltip = "Output the model's information.";
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("export_settings", coString);
|
||||
def->label = L("Export Settings");
|
||||
def->tooltip = L("Export settings to a file.");
|
||||
def->label = "Export Settings";
|
||||
def->tooltip = "Export settings to a file.";
|
||||
def->cli_params = "settings.json";
|
||||
def->set_default_value(new ConfigOptionString("output.json"));
|
||||
|
||||
def = this->add("pipe", coString);
|
||||
def->label = L("Send progress to pipe");
|
||||
def->tooltip = L("Send progress to pipe.");
|
||||
def->label = "Send progress to pipe";
|
||||
def->tooltip = "Send progress to pipe.";
|
||||
def->cli_params = "pipename";
|
||||
def->set_default_value(new ConfigOptionString(""));
|
||||
}
|
||||
|
|
@ -6053,15 +6160,15 @@ CLITransformConfigDef::CLITransformConfigDef()
|
|||
def->set_default_value(new ConfigOptionPoint(Vec2d(100,100)));*/
|
||||
|
||||
def = this->add("arrange", coInt);
|
||||
def->label = L("Arrange Options");
|
||||
def->tooltip = L("Arrange options: 0-disable, 1-enable, others-auto");
|
||||
def->label = "Arrange Options";
|
||||
def->tooltip = "Arrange options: 0-disable, 1-enable, others-auto";
|
||||
def->cli_params = "option";
|
||||
//def->cli = "arrange|a";
|
||||
def->set_default_value(new ConfigOptionInt(0));
|
||||
|
||||
def = this->add("repetitions", coInt);
|
||||
def->label = L("Repetions count");
|
||||
def->tooltip = L("Repetions count of the whole model");
|
||||
def->label = "Repetions count";
|
||||
def->tooltip = "Repetions count of the whole model";
|
||||
def->cli_params = "count";
|
||||
def->set_default_value(new ConfigOptionInt(1));
|
||||
|
||||
|
|
@ -6078,16 +6185,17 @@ CLITransformConfigDef::CLITransformConfigDef()
|
|||
|
||||
/*def = this->add("duplicate_grid", coPoint);
|
||||
def->label = L("Duplicate by grid");
|
||||
def->tooltip = L("Multiply copies by creating a grid.");
|
||||
def->tooltip = L("Multiply copies by creating a grid.");*/
|
||||
|
||||
def = this->add("assemble", coBool);
|
||||
def->label = L("Assemble");
|
||||
def->tooltip = L("Arrange the supplied models in a plate and merge them in a single model in order to perform actions once.");
|
||||
def->cli = "merge|m";*/
|
||||
def->label = "Assemble";
|
||||
def->tooltip = "Arrange the supplied models in a plate and merge them in a single model in order to perform actions once.";
|
||||
//def->cli = "merge|m";
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("convert_unit", coBool);
|
||||
def->label = L("Convert Unit");
|
||||
def->tooltip = L("Convert the units of model");
|
||||
def->label = "Convert Unit";
|
||||
def->tooltip = "Convert the units of model";
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("orient", coInt);
|
||||
|
|
@ -6107,8 +6215,8 @@ CLITransformConfigDef::CLITransformConfigDef()
|
|||
def->set_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.");
|
||||
def->label = "Rotate around X";
|
||||
def->tooltip = "Rotation angle around the X axis in degrees.";
|
||||
def->set_default_value(new ConfigOptionFloat(0));
|
||||
|
||||
def = this->add("rotate_y", coFloat);
|
||||
|
|
@ -6117,8 +6225,8 @@ CLITransformConfigDef::CLITransformConfigDef()
|
|||
def->set_default_value(new ConfigOptionFloat(0));
|
||||
|
||||
def = this->add("scale", coFloat);
|
||||
def->label = L("Scale");
|
||||
def->tooltip = L("Scale the model by a float factor");
|
||||
def->label = "Scale";
|
||||
def->tooltip = "Scale the model by a float factor";
|
||||
def->cli_params = "factor";
|
||||
def->set_default_value(new ConfigOptionFloat(1.f));
|
||||
|
||||
|
|
@ -6159,29 +6267,47 @@ CLIMiscConfigDef::CLIMiscConfigDef()
|
|||
def->tooltip = L("Load configuration from the specified file. It can be used more than once to load options from multiple files.");*/
|
||||
|
||||
def = this->add("load_settings", coStrings);
|
||||
def->label = L("Load General Settings");
|
||||
def->tooltip = L("Load process/machine settings from the specified file");
|
||||
def->label = "Load General Settings";
|
||||
def->tooltip = "Load process/machine settings from the specified file";
|
||||
def->cli_params = "\"setting1.json;setting2.json\"";
|
||||
def->set_default_value(new ConfigOptionStrings());
|
||||
|
||||
def = this->add("load_filaments", coStrings);
|
||||
def->label = L("Load Filament Settings");
|
||||
def->tooltip = L("Load filament settings from the specified file list");
|
||||
def->label = "Load Filament Settings";
|
||||
def->tooltip = "Load filament settings from the specified file list";
|
||||
def->cli_params = "\"filament1.json;filament2.json;...\"";
|
||||
def->set_default_value(new ConfigOptionStrings());
|
||||
|
||||
def = this->add("skip_objects", coInts);
|
||||
def->label = L("Skip Objects");
|
||||
def->tooltip = L("Skip some objects in this print");
|
||||
def->label = "Skip Objects";
|
||||
def->tooltip = "Skip some objects in this print";
|
||||
def->cli_params = "\"3,5,10,77\"";
|
||||
def->set_default_value(new ConfigOptionInts());
|
||||
|
||||
def = this->add("clone_objects", coInts);
|
||||
def->label = "Clone Objects";
|
||||
def->tooltip = "Clone objects in the load list";
|
||||
def->cli_params = "\"1,3,1,10\"";
|
||||
def->set_default_value(new ConfigOptionInts());
|
||||
|
||||
def = this->add("uptodate_settings", coStrings);
|
||||
def->label = L("load uptodate process/machine settings when using uptodate");
|
||||
def->tooltip = L("load uptodate process/machine settings from the specified file when using uptodate");
|
||||
def->label = "load uptodate process/machine settings when using uptodate";
|
||||
def->tooltip = "load uptodate process/machine settings from the specified file when using uptodate";
|
||||
def->cli_params = "\"setting1.json;setting2.json\"";
|
||||
def->set_default_value(new ConfigOptionStrings());
|
||||
|
||||
def = this->add("uptodate_filaments", coStrings);
|
||||
def->label = "load uptodate filament settings when using uptodate";
|
||||
def->tooltip = "load uptodate filament settings from the specified file when using uptodate";
|
||||
def->cli_params = "\"filament1.json;filament2.json;...\"";
|
||||
def->set_default_value(new ConfigOptionStrings());
|
||||
|
||||
def = this->add("load_assemble_list", coString);
|
||||
def->label = "Load assemble list";
|
||||
def->tooltip = "Load assemble object list from config file";
|
||||
def->cli_params = "assemble_list.json";
|
||||
def->set_default_value(new ConfigOptionString());
|
||||
|
||||
/*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).");
|
||||
|
|
@ -6205,18 +6331,23 @@ CLIMiscConfigDef::CLIMiscConfigDef()
|
|||
|
||||
|
||||
def = this->add("outputdir", coString);
|
||||
def->label = L("Output directory");
|
||||
def->tooltip = L("Output directory for the exported files.");
|
||||
def->label = "Output directory";
|
||||
def->tooltip = "Output directory for the exported files.";
|
||||
def->cli_params = "dir";
|
||||
def->set_default_value(new ConfigOptionString());
|
||||
|
||||
def = this->add("debug", coInt);
|
||||
def->label = L("Debug level");
|
||||
def->tooltip = L("Sets debug logging level. 0:fatal, 1:error, 2:warning, 3:info, 4:debug, 5:trace\n");
|
||||
def->label = "Debug level";
|
||||
def->tooltip = "Sets debug logging level. 0:fatal, 1:error, 2:warning, 3:info, 4:debug, 5:trace\n";
|
||||
def->min = 0;
|
||||
def->cli_params = "level";
|
||||
def->set_default_value(new ConfigOptionInt(1));
|
||||
|
||||
def = this->add("enable_timelapse", coBool);
|
||||
def->label = "Enable timeplapse for print";
|
||||
def->tooltip = "If enabled, this slicing will be considered using timelapse";
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
#if (defined(_MSC_VER) || defined(__MINGW32__)) && defined(SLIC3R_GUI)
|
||||
/*def = this->add("sw_renderer", coBool);
|
||||
def->label = L("Render with a software renderer");
|
||||
|
|
@ -6229,6 +6360,33 @@ CLIMiscConfigDef::CLIMiscConfigDef()
|
|||
def->tooltip = L("Load custom gcode from json");
|
||||
def->cli_params = "custom_gcode_toolchange.json";
|
||||
def->set_default_value(new ConfigOptionString());
|
||||
|
||||
def = this->add("load_filament_ids", coInts);
|
||||
def->label = "Load filament ids";
|
||||
def->tooltip = "Load filament ids for each object";
|
||||
def->cli_params = "\"1,2,3,1\"";
|
||||
def->set_default_value(new ConfigOptionInts());
|
||||
|
||||
def = this->add("allow_multicolor_oneplate", coBool);
|
||||
def->label = "Allow multiple color on one plate";
|
||||
def->tooltip = "If enabled, the arrange will allow multiple color on one plate";
|
||||
def->set_default_value(new ConfigOptionBool(true));
|
||||
|
||||
def = this->add("allow_rotations", coBool);
|
||||
def->label = "Allow rotatations when arrange";
|
||||
def->tooltip = "If enabled, the arrange will allow rotations when place object";
|
||||
def->set_default_value(new ConfigOptionBool(true));
|
||||
|
||||
def = this->add("avoid_extrusion_cali_region", coBool);
|
||||
def->label = "Avoid extrusion calibrate region when doing arrange";
|
||||
def->tooltip = "If enabled, the arrange will avoid extrusion calibrate region when place object";
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("skip_modified_gcodes", coBool);
|
||||
def->label = "Skip modified gcodes in 3mf";
|
||||
def->tooltip = "Skip the modified gcodes in 3mf from Printer or filament Presets";
|
||||
def->cli_params = "option";
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
}
|
||||
|
||||
const CLIActionsConfigDef cli_actions_config_def;
|
||||
|
|
|
|||
|
|
@ -90,6 +90,14 @@ enum class WallInfillOrder {
|
|||
InnerOuterInnerInfill,
|
||||
Count,
|
||||
};
|
||||
|
||||
// BBS
|
||||
enum class WallSequence {
|
||||
InnerOuter,
|
||||
OuterInner,
|
||||
InnerOuterInner,
|
||||
Count,
|
||||
};
|
||||
//BBS
|
||||
enum class PrintSequence {
|
||||
ByLayer,
|
||||
|
|
@ -216,6 +224,12 @@ enum BedType {
|
|||
btCount
|
||||
};
|
||||
|
||||
// BBS
|
||||
enum FirstLayerSeq {
|
||||
flsAuto,
|
||||
flsCutomize
|
||||
};
|
||||
|
||||
// BBS
|
||||
enum NozzleType {
|
||||
ntUndefine = 0,
|
||||
|
|
@ -348,7 +362,6 @@ CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(GCodeThumbnailsFormat)
|
|||
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(PrintHostType)
|
||||
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(AuthorizationType)
|
||||
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(PerimeterGeneratorType)
|
||||
|
||||
#undef CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS
|
||||
|
||||
// Defines each and every confiuration option of Slic3r, including the properties of the GUI dialogs.
|
||||
|
|
@ -687,6 +700,8 @@ PRINT_CONFIG_CLASS_DEFINE(
|
|||
// Force the generation of solid shells between adjacent materials/volumes.
|
||||
((ConfigOptionBool, interface_shells))
|
||||
((ConfigOptionFloat, layer_height))
|
||||
((ConfigOptionFloat, mmu_segmented_region_max_width))
|
||||
((ConfigOptionFloat, mmu_segmented_region_interlocking_depth))
|
||||
((ConfigOptionFloat, raft_contact_distance))
|
||||
((ConfigOptionFloat, raft_expansion))
|
||||
((ConfigOptionPercent, raft_first_layer_density))
|
||||
|
|
@ -709,6 +724,7 @@ PRINT_CONFIG_CLASS_DEFINE(
|
|||
((ConfigOptionInt, enforce_support_layers))
|
||||
((ConfigOptionInt, support_filament))
|
||||
((ConfigOptionFloatOrPercent, support_line_width))
|
||||
((ConfigOptionBool, support_interface_not_for_body))
|
||||
((ConfigOptionBool, support_interface_loop_pattern))
|
||||
((ConfigOptionInt, support_interface_filament))
|
||||
((ConfigOptionInt, support_interface_top_layers))
|
||||
|
|
@ -735,6 +751,7 @@ PRINT_CONFIG_CLASS_DEFINE(
|
|||
// BBS
|
||||
((ConfigOptionBool, flush_into_infill))
|
||||
((ConfigOptionBool, flush_into_support))
|
||||
((ConfigOptionEnum<WallSequence>, wall_sequence))
|
||||
// BBS
|
||||
((ConfigOptionFloat, tree_support_branch_distance))
|
||||
((ConfigOptionFloat, tree_support_tip_diameter))
|
||||
|
|
@ -824,6 +841,7 @@ PRINT_CONFIG_CLASS_DEFINE(
|
|||
((ConfigOptionEnum<InfillPattern>, ironing_pattern))
|
||||
((ConfigOptionPercent, ironing_flow))
|
||||
((ConfigOptionFloat, ironing_spacing))
|
||||
((ConfigOptionFloat, ironing_direction))
|
||||
((ConfigOptionFloat, ironing_speed))
|
||||
((ConfigOptionFloat, ironing_angle))
|
||||
// Detect bridging perimeters
|
||||
|
|
@ -917,7 +935,8 @@ PRINT_CONFIG_CLASS_DEFINE(
|
|||
PRINT_CONFIG_CLASS_DEFINE(
|
||||
GCodeConfig,
|
||||
|
||||
((ConfigOptionString, before_layer_change_gcode))
|
||||
((ConfigOptionString, before_layer_change_gcode))
|
||||
((ConfigOptionString, printing_by_object_gcode))
|
||||
((ConfigOptionFloats, deretraction_speed))
|
||||
//BBS
|
||||
((ConfigOptionBool, enable_arc_fitting))
|
||||
|
|
@ -941,6 +960,7 @@ PRINT_CONFIG_CLASS_DEFINE(
|
|||
((ConfigOptionInts, required_nozzle_HRC))
|
||||
// BBS
|
||||
((ConfigOptionBool, scan_first_layer))
|
||||
((ConfigOptionPoints, thumbnail_size))
|
||||
// ((ConfigOptionBool, spaghetti_detector))
|
||||
((ConfigOptionBool, gcode_add_line_number))
|
||||
((ConfigOptionBool, bbl_bed_temperature_gcode))
|
||||
|
|
@ -1037,6 +1057,8 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE(
|
|||
//BBS: add bed_exclude_area
|
||||
((ConfigOptionPoints, bed_exclude_area))
|
||||
// BBS
|
||||
((ConfigOptionString, bed_custom_texture))
|
||||
((ConfigOptionString, bed_custom_model))
|
||||
((ConfigOptionEnum<BedType>, curr_bed_type))
|
||||
((ConfigOptionInts, cool_plate_temp))
|
||||
((ConfigOptionInts, eng_plate_temp))
|
||||
|
|
@ -1141,12 +1163,13 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE(
|
|||
((ConfigOptionInt, slow_down_layers))
|
||||
((ConfigOptionInts, support_material_interface_fan_speed))
|
||||
// Orca: notes for profiles from PrusaSlicer
|
||||
((ConfigOptionStrings, filament_notes))
|
||||
((ConfigOptionString, notes))
|
||||
((ConfigOptionString, printer_notes))
|
||||
((ConfigOptionStrings, filament_notes))
|
||||
((ConfigOptionString, notes))
|
||||
((ConfigOptionString, printer_notes))
|
||||
|
||||
((ConfigOptionBools, activate_chamber_temp_control))
|
||||
((ConfigOptionInts , chamber_temperature))
|
||||
((ConfigOptionBool, is_infill_first))
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -68,7 +68,6 @@ using namespace std::literals;
|
|||
#endif
|
||||
|
||||
// #define SLIC3R_DEBUG
|
||||
|
||||
// Make assert active if SLIC3R_DEBUG
|
||||
#ifdef SLIC3R_DEBUG
|
||||
#undef NDEBUG
|
||||
|
|
@ -912,7 +911,8 @@ bool PrintObject::invalidate_state_by_config_options(
|
|||
}
|
||||
} else if (
|
||||
opt_key == "wall_loops"
|
||||
|| opt_key == "only_one_wall_top"
|
||||
|| opt_key == "top_one_wall_type"
|
||||
|| opt_key == "min_width_top_surface"
|
||||
|| opt_key == "only_one_wall_first_layer"
|
||||
|| opt_key == "extra_perimeters_on_overhangs"
|
||||
|| opt_key == "initial_layer_line_width"
|
||||
|
|
@ -945,6 +945,8 @@ bool PrintObject::invalidate_state_by_config_options(
|
|||
steps.emplace_back(posPerimeters);
|
||||
} else if (
|
||||
opt_key == "layer_height"
|
||||
|| opt_key == "mmu_segmented_region_max_width"
|
||||
|| opt_key == "mmu_segmented_region_interlocking_depth"
|
||||
|| opt_key == "raft_layers"
|
||||
|| opt_key == "raft_contact_distance"
|
||||
|| opt_key == "slice_closing_radius"
|
||||
|
|
@ -995,6 +997,7 @@ bool PrintObject::invalidate_state_by_config_options(
|
|||
|| opt_key == "support_interface_pattern"
|
||||
|| opt_key == "support_interface_loop_pattern"
|
||||
|| opt_key == "support_interface_filament"
|
||||
|| opt_key == "support_interface_not_for_body"
|
||||
|| opt_key == "support_interface_spacing"
|
||||
|| opt_key == "support_bottom_interface_spacing" //BBS
|
||||
|| opt_key == "support_base_pattern"
|
||||
|
|
|
|||
|
|
@ -398,14 +398,14 @@ void SLAPrint::Steps::drill_holes(SLAPrintObject &po)
|
|||
auto bb = bounding_box(m);
|
||||
Eigen::AlignedBox<float, 3> ebb{bb.min.cast<float>(),
|
||||
bb.max.cast<float>()};
|
||||
|
||||
AABBTreeIndirect::traverse(
|
||||
tree,
|
||||
AABBTreeIndirect::intersecting(ebb),
|
||||
[&part_to_drill, &hollowed_mesh](size_t faceid)
|
||||
{
|
||||
part_to_drill.indices.emplace_back(hollowed_mesh.its.indices[faceid]);
|
||||
});
|
||||
//BBS
|
||||
//AABBTreeIndirect::traverse(
|
||||
// tree,
|
||||
// AABBTreeIndirect::intersecting(ebb),
|
||||
// [&part_to_drill, &hollowed_mesh](size_t faceid)
|
||||
//{
|
||||
// part_to_drill.indices.emplace_back(hollowed_mesh.its.indices[faceid]);
|
||||
//});
|
||||
|
||||
auto cgal_meshpart = MeshBoolean::cgal::triangle_mesh_to_cgal(
|
||||
remove_unconnected_vertices(part_to_drill));
|
||||
|
|
|
|||
|
|
@ -430,16 +430,16 @@ std::vector<double> smooth_height_profile(const std::vector<double>& profile, co
|
|||
// return false;
|
||||
//};
|
||||
|
||||
//int count = 0;
|
||||
//std::vector<double> ret = profile;
|
||||
//bool has_steep_change = has_steep_height_change(ret, LAYER_HEIGHT_CHANGE_STEP);
|
||||
//while (has_steep_change && count < 6) {
|
||||
// ret = gauss_blur(ret, smoothing_params);
|
||||
// has_steep_change = has_steep_height_change(ret, LAYER_HEIGHT_CHANGE_STEP);
|
||||
// count++;
|
||||
//}
|
||||
//return ret;
|
||||
return gauss_blur(profile, smoothing_params);
|
||||
int count = 0;
|
||||
std::vector<double> ret = profile;
|
||||
// bool has_steep_change = has_steep_height_change(ret, LAYER_HEIGHT_CHANGE_STEP);
|
||||
while (/*has_steep_change &&*/ count < 6) {
|
||||
ret = gauss_blur(ret, smoothing_params);
|
||||
//has_steep_change = has_steep_height_change(ret, LAYER_HEIGHT_CHANGE_STEP);
|
||||
count++;
|
||||
}
|
||||
return ret;
|
||||
// return gauss_blur(profile, smoothing_params);
|
||||
}
|
||||
|
||||
void adjust_layer_height_profile(
|
||||
|
|
|
|||
4798
src/libslic3r/Support/TreeSupport3D.cpp
Normal file
4798
src/libslic3r/Support/TreeSupport3D.cpp
Normal file
File diff suppressed because it is too large
Load diff
332
src/libslic3r/Support/TreeSupport3D.hpp
Normal file
332
src/libslic3r/Support/TreeSupport3D.hpp
Normal file
|
|
@ -0,0 +1,332 @@
|
|||
// Tree supports by Thomas Rahm, losely based on Tree Supports by CuraEngine.
|
||||
// Original source of Thomas Rahm's tree supports:
|
||||
// https://github.com/ThomasRahm/CuraEngine
|
||||
//
|
||||
// Original CuraEngine copyright:
|
||||
// Copyright (c) 2021 Ultimaker B.V.
|
||||
// CuraEngine is released under the terms of the AGPLv3 or higher.
|
||||
|
||||
#ifndef slic3r_TreeSupport_hpp
|
||||
#define slic3r_TreeSupport_hpp
|
||||
|
||||
#include <boost/container/small_vector.hpp>
|
||||
#include "../Point.hpp"
|
||||
#include "../BoundingBox.hpp"
|
||||
#include "../Utils.hpp"
|
||||
#include "TreeModelVolumes.hpp"
|
||||
#include "TreeSupportCommon.hpp"
|
||||
|
||||
// #define TREE_SUPPORT_SHOW_ERRORS
|
||||
|
||||
#ifdef SLIC3R_TREESUPPORTS_PROGRESS
|
||||
// The various stages of the process can be weighted differently in the progress bar.
|
||||
// These weights are obtained experimentally using a small sample size. Sensible weights can differ drastically based on the assumed default settings and model.
|
||||
#define TREE_PROGRESS_TOTAL 10000
|
||||
#define TREE_PROGRESS_PRECALC_COLL TREE_PROGRESS_TOTAL * 0.1
|
||||
#define TREE_PROGRESS_PRECALC_AVO TREE_PROGRESS_TOTAL * 0.4
|
||||
#define TREE_PROGRESS_GENERATE_NODES TREE_PROGRESS_TOTAL * 0.1
|
||||
#define TREE_PROGRESS_AREA_CALC TREE_PROGRESS_TOTAL * 0.3
|
||||
#define TREE_PROGRESS_DRAW_AREAS TREE_PROGRESS_TOTAL * 0.1
|
||||
#define TREE_PROGRESS_GENERATE_BRANCH_AREAS TREE_PROGRESS_DRAW_AREAS / 3
|
||||
#define TREE_PROGRESS_SMOOTH_BRANCH_AREAS TREE_PROGRESS_DRAW_AREAS / 3
|
||||
#define TREE_PROGRESS_FINALIZE_BRANCH_AREAS TREE_PROGRESS_DRAW_AREAS / 3
|
||||
#endif // SLIC3R_TREESUPPORTS_PROGRESS
|
||||
|
||||
namespace Slic3r
|
||||
{
|
||||
|
||||
// Forward declarations
|
||||
class TreeSupport;
|
||||
class Print;
|
||||
class PrintObject;
|
||||
class SupportGeneratorLayer;
|
||||
using SupportGeneratorLayersPtr = std::vector<SupportGeneratorLayer*>;
|
||||
|
||||
namespace TreeSupport3D
|
||||
{
|
||||
|
||||
// The number of vertices in each circle.
|
||||
static constexpr const size_t SUPPORT_TREE_CIRCLE_RESOLUTION = 25;
|
||||
|
||||
struct AreaIncreaseSettings
|
||||
{
|
||||
AreaIncreaseSettings(
|
||||
TreeModelVolumes::AvoidanceType type = TreeModelVolumes::AvoidanceType::Fast, coord_t increase_speed = 0,
|
||||
bool increase_radius = false, bool no_error = false, bool use_min_distance = false, bool move = false) :
|
||||
increase_speed{ increase_speed }, type{ type }, increase_radius{ increase_radius }, no_error{ no_error }, use_min_distance{ use_min_distance }, move{ move } {}
|
||||
|
||||
coord_t increase_speed;
|
||||
// Packing for smaller memory footprint of SupportElementState && SupportElementMerging
|
||||
TreeModelVolumes::AvoidanceType type;
|
||||
bool increase_radius : 1;
|
||||
bool no_error : 1;
|
||||
bool use_min_distance : 1;
|
||||
bool move : 1;
|
||||
bool operator==(const AreaIncreaseSettings& other) const
|
||||
{
|
||||
return type == other.type &&
|
||||
increase_speed == other.increase_speed &&
|
||||
increase_radius == other.increase_radius &&
|
||||
no_error == other.no_error &&
|
||||
use_min_distance == other.use_min_distance &&
|
||||
move == other.move;
|
||||
}
|
||||
};
|
||||
|
||||
#define TREE_SUPPORTS_TRACK_LOST
|
||||
|
||||
// C++17 does not support in place initializers of bit values, thus a constructor zeroing the bits is provided.
|
||||
struct SupportElementStateBits {
|
||||
SupportElementStateBits() :
|
||||
to_buildplate(false),
|
||||
to_model_gracious(false),
|
||||
use_min_xy_dist(false),
|
||||
supports_roof(false),
|
||||
can_use_safe_radius(false),
|
||||
skip_ovalisation(false),
|
||||
#ifdef TREE_SUPPORTS_TRACK_LOST
|
||||
lost(false),
|
||||
verylost(false),
|
||||
#endif // TREE_SUPPORTS_TRACK_LOST
|
||||
deleted(false),
|
||||
marked(false)
|
||||
{}
|
||||
|
||||
/*!
|
||||
* \brief The element trys to reach the buildplate
|
||||
*/
|
||||
bool to_buildplate : 1;
|
||||
|
||||
/*!
|
||||
* \brief Will the branch be able to rest completely on a flat surface, be it buildplate or model ?
|
||||
*/
|
||||
bool to_model_gracious : 1;
|
||||
|
||||
/*!
|
||||
* \brief Whether the min_xy_distance can be used to get avoidance or similar. Will only be true if support_xy_overrides_z=Z overrides X/Y.
|
||||
*/
|
||||
bool use_min_xy_dist : 1;
|
||||
|
||||
/*!
|
||||
* \brief True if this Element or any parent provides support to a support roof.
|
||||
*/
|
||||
bool supports_roof : 1;
|
||||
|
||||
/*!
|
||||
* \brief An influence area is considered safe when it can use the holefree avoidance <=> It will not have to encounter holes on its way downward.
|
||||
*/
|
||||
bool can_use_safe_radius : 1;
|
||||
|
||||
/*!
|
||||
* \brief Skip the ovalisation to parent and children when generating the final circles.
|
||||
*/
|
||||
bool skip_ovalisation : 1;
|
||||
|
||||
#ifdef TREE_SUPPORTS_TRACK_LOST
|
||||
// Likely a lost branch, debugging information.
|
||||
bool lost : 1;
|
||||
bool verylost : 1;
|
||||
#endif // TREE_SUPPORTS_TRACK_LOST
|
||||
|
||||
// Not valid anymore, to be deleted.
|
||||
bool deleted : 1;
|
||||
|
||||
// General purpose flag marking a visited element.
|
||||
bool marked : 1;
|
||||
};
|
||||
|
||||
struct SupportElementState : public SupportElementStateBits
|
||||
{
|
||||
int type = 0;
|
||||
coordf_t radius = 0;
|
||||
float print_z = 0;
|
||||
|
||||
/*!
|
||||
* \brief The layer this support elements wants reach
|
||||
*/
|
||||
LayerIndex target_height;
|
||||
|
||||
/*!
|
||||
* \brief The position this support elements wants to support on layer=target_height
|
||||
*/
|
||||
Point target_position;
|
||||
|
||||
/*!
|
||||
* \brief The next position this support elements wants to reach. NOTE: This is mainly a suggestion regarding direction inside the influence area.
|
||||
*/
|
||||
Point next_position;
|
||||
|
||||
/*!
|
||||
* \brief The next height this support elements wants to reach
|
||||
*/
|
||||
LayerIndex layer_idx;
|
||||
|
||||
/*!
|
||||
* \brief The Effective distance to top of this element regarding radius increases and collision calculations.
|
||||
*/
|
||||
uint32_t effective_radius_height;
|
||||
|
||||
/*!
|
||||
* \brief The amount of layers this element is below the topmost layer of this branch.
|
||||
*/
|
||||
uint32_t distance_to_top;
|
||||
|
||||
/*!
|
||||
* \brief The resulting center point around which a circle will be drawn later.
|
||||
* Will be set by setPointsOnAreas
|
||||
*/
|
||||
Point result_on_layer{ std::numeric_limits<coord_t>::max(), std::numeric_limits<coord_t>::max() };
|
||||
bool result_on_layer_is_set() const { return this->result_on_layer != Point{ std::numeric_limits<coord_t>::max(), std::numeric_limits<coord_t>::max() }; }
|
||||
void result_on_layer_reset() { this->result_on_layer = Point{ std::numeric_limits<coord_t>::max(), std::numeric_limits<coord_t>::max() }; }
|
||||
/*!
|
||||
* \brief The amount of extra radius we got from merging branches that could have reached the buildplate, but merged with ones that can not.
|
||||
*/
|
||||
coord_t increased_to_model_radius; // how much to model we increased only relevant for merging
|
||||
|
||||
/*!
|
||||
* \brief Counter about the times the elephant foot was increased. Can be fractions for merge reasons.
|
||||
*/
|
||||
double elephant_foot_increases;
|
||||
|
||||
/*!
|
||||
* \brief The element trys not to move until this dtt is reached, is set to 0 if the element had to move.
|
||||
*/
|
||||
uint32_t dont_move_until;
|
||||
|
||||
/*!
|
||||
* \brief Settings used to increase the influence area to its current state.
|
||||
*/
|
||||
AreaIncreaseSettings last_area_increase;
|
||||
|
||||
/*!
|
||||
* \brief Amount of roof layers that were not yet added, because the branch needed to move.
|
||||
*/
|
||||
uint32_t missing_roof_layers;
|
||||
|
||||
// called by increase_single_area() and increaseAreas()
|
||||
[[nodiscard]] static SupportElementState propagate_down(const SupportElementState& src)
|
||||
{
|
||||
SupportElementState dst{ src };
|
||||
++dst.distance_to_top;
|
||||
--dst.layer_idx;
|
||||
// set to invalid as we are a new node on a new layer
|
||||
dst.result_on_layer_reset();
|
||||
dst.skip_ovalisation = false;
|
||||
return dst;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*!
|
||||
* \brief Get the Distance to top regarding the real radius this part will have. This is different from distance_to_top, which is can be used to calculate the top most layer of the branch.
|
||||
* \param elem[in] The SupportElement one wants to know the effectiveDTT
|
||||
* \return The Effective DTT.
|
||||
*/
|
||||
[[nodiscard]] inline size_t getEffectiveDTT(const TreeSupportSettings &settings, const SupportElementState &elem)
|
||||
{
|
||||
return elem.effective_radius_height < settings.increase_radius_until_layer ?
|
||||
(elem.distance_to_top < settings.increase_radius_until_layer ? elem.distance_to_top : settings.increase_radius_until_layer) :
|
||||
elem.effective_radius_height;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Get the Radius, that this element will have.
|
||||
* \param elem[in] The Element.
|
||||
* \return The radius the element has.
|
||||
*/
|
||||
[[nodiscard]] inline coord_t support_element_radius(const TreeSupportSettings &settings, const SupportElementState &elem)
|
||||
{
|
||||
return settings.getRadius(getEffectiveDTT(settings, elem), elem.elephant_foot_increases);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Get the collision Radius of this Element. This can be smaller then the actual radius, as the drawAreas will cut off areas that may collide with the model.
|
||||
* \param elem[in] The Element.
|
||||
* \return The collision radius the element has.
|
||||
*/
|
||||
[[nodiscard]] inline coord_t support_element_collision_radius(const TreeSupportSettings &settings, const SupportElementState &elem)
|
||||
{
|
||||
return settings.getRadius(elem.effective_radius_height, elem.elephant_foot_increases);
|
||||
}
|
||||
|
||||
struct SupportElement
|
||||
{
|
||||
using ParentIndices =
|
||||
#ifdef NDEBUG
|
||||
// To reduce memory allocation in release mode.
|
||||
boost::container::small_vector<int32_t, 4>;
|
||||
#else // NDEBUG
|
||||
// To ease debugging.
|
||||
std::vector<int32_t>;
|
||||
#endif // NDEBUG
|
||||
|
||||
// SupportElement(const SupportElementState &state) : SupportElementState(state) {}
|
||||
SupportElement(const SupportElementState &state, Polygons &&influence_area) : state(state), influence_area(std::move(influence_area)) {}
|
||||
SupportElement(const SupportElementState &state, ParentIndices &&parents, Polygons &&influence_area) :
|
||||
state(state), parents(std::move(parents)), influence_area(std::move(influence_area)) {}
|
||||
|
||||
SupportElementState state;
|
||||
|
||||
/*!
|
||||
* \brief All elements in the layer above the current one that are supported by this element
|
||||
*/
|
||||
ParentIndices parents;
|
||||
|
||||
/*!
|
||||
* \brief The resulting influence area.
|
||||
* Will only be set in the results of createLayerPathing, and will be nullptr inside!
|
||||
*/
|
||||
Polygons influence_area;
|
||||
};
|
||||
|
||||
void tree_supports_show_error(std::string_view message, bool critical);
|
||||
|
||||
using SupportElements = std::deque<SupportElement>;
|
||||
|
||||
[[nodiscard]] inline coord_t support_element_radius(const TreeSupportSettings &settings, const SupportElement &elem)
|
||||
{
|
||||
return support_element_radius(settings, elem.state);
|
||||
}
|
||||
|
||||
[[nodiscard]] inline coord_t support_element_collision_radius(const TreeSupportSettings &settings, const SupportElement &elem)
|
||||
{
|
||||
return support_element_collision_radius(settings, elem.state);
|
||||
}
|
||||
|
||||
void create_layer_pathing(const TreeModelVolumes& volumes, const TreeSupportSettings& config, std::vector<SupportElements>& move_bounds, std::function<void()> throw_on_cancel);
|
||||
|
||||
void create_nodes_from_area(const TreeModelVolumes& volumes, const TreeSupportSettings& config, std::vector<SupportElements>& move_bounds, std::function<void()> throw_on_cancel);
|
||||
|
||||
void organic_smooth_branches_avoid_collisions(const PrintObject& print_object, const TreeModelVolumes& volumes, const TreeSupportSettings& config, const std::vector<std::pair<SupportElement*, int>>& elements_with_link_down, const std::vector<size_t>& linear_data_layers, std::function<void()> throw_on_cancel);
|
||||
|
||||
indexed_triangle_set draw_branches(PrintObject& print_object, const TreeModelVolumes& volumes, const TreeSupportSettings& config, std::vector<SupportElements>& move_bounds, std::function<void()> throw_on_cancel);
|
||||
|
||||
void slice_branches(PrintObject& print_object, const TreeModelVolumes& volumes, const TreeSupportSettings& config, const std::vector<Polygons>& overhangs, std::vector<SupportElements>& move_bounds, const indexed_triangle_set& cummulative_mesh, SupportGeneratorLayersPtr& bottom_contacts, SupportGeneratorLayersPtr& top_contacts, SupportGeneratorLayersPtr& intermediate_layers, SupportGeneratorLayerStorage& layer_storage, std::function<void()> throw_on_cancel);
|
||||
|
||||
void generate_initial_areas(const PrintObject& print_object, const TreeModelVolumes& volumes, const TreeSupportSettings& config, const std::vector<Polygons>& overhangs, std::vector<SupportElements>& move_bounds, InterfacePlacer& interface_placer, std::function<void()> throw_on_cancel);
|
||||
|
||||
// Organic specific: Smooth branches and produce one cummulative mesh to be sliced.
|
||||
void organic_draw_branches(
|
||||
PrintObject& print_object,
|
||||
TreeModelVolumes& volumes,
|
||||
const TreeSupportSettings& config,
|
||||
std::vector<SupportElements>& move_bounds,
|
||||
|
||||
// I/O:
|
||||
SupportGeneratorLayersPtr& bottom_contacts,
|
||||
SupportGeneratorLayersPtr& top_contacts,
|
||||
InterfacePlacer& interface_placer,
|
||||
|
||||
// Output:
|
||||
SupportGeneratorLayersPtr& intermediate_layers,
|
||||
SupportGeneratorLayerStorage& layer_storage,
|
||||
|
||||
std::function<void()> throw_on_cancel);
|
||||
|
||||
} // namespace TreeSupport3D
|
||||
|
||||
void generate_tree_support_3D(PrintObject &print_object, TreeSupport* tree_support, std::function<void()> throw_on_cancel = []{});
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif /* slic3r_TreeSupport_hpp */
|
||||
|
|
@ -23,6 +23,7 @@
|
|||
#include "Point.hpp"
|
||||
#include "Execution/ExecutionTBB.hpp"
|
||||
#include "Execution/ExecutionSeq.hpp"
|
||||
#include "CutUtils.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include "Format/STL.hpp"
|
||||
#include <libqhullcpp/Qhull.h>
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ namespace Slic3r {
|
|||
|
||||
class TriangleMesh;
|
||||
class TriangleMeshSlicer;
|
||||
|
||||
struct Groove;
|
||||
struct RepairedMeshErrors {
|
||||
// How many edges were united by merging their end points with some other end points in epsilon neighborhood?
|
||||
int edges_fixed = 0;
|
||||
|
|
@ -353,6 +353,7 @@ indexed_triangle_set its_make_frustum_dowel(double r, double h, int sectorCou
|
|||
indexed_triangle_set its_make_pyramid(float base, float height);
|
||||
indexed_triangle_set its_make_sphere(double radius, double fa);
|
||||
indexed_triangle_set its_make_snap(double r, double h, float space_proportion = 0.25f, float bulge_proportion = 0.125f);
|
||||
indexed_triangle_set its_make_groove_plane(const Groove &cur_groove, float rotate_radius, std::vector<Vec3d> &cur_groove_vertices);
|
||||
|
||||
indexed_triangle_set its_convex_hull(const std::vector<Vec3f> &pts);
|
||||
inline indexed_triangle_set its_convex_hull(const indexed_triangle_set &its) { return its_convex_hull(its.vertices); }
|
||||
|
|
|
|||
|
|
@ -51,9 +51,12 @@ bool is_equal(float lh, float rh)
|
|||
return abs(lh - rh) <= epson;
|
||||
}
|
||||
|
||||
bool is_less(float lh, float rh)
|
||||
{
|
||||
return lh + epson < rh;
|
||||
bool is_equal_for_sort(float lh, float rh) {
|
||||
return abs(lh - rh) <= 1e-8;
|
||||
}
|
||||
|
||||
bool is_equal(const Vec3f &lh, const Vec3f &rh) {
|
||||
return is_equal(lh[0], rh[0]) && is_equal(lh[1], rh[1]) && is_equal(lh[2], rh[2]);
|
||||
}
|
||||
|
||||
class IntersectionReference
|
||||
|
|
@ -174,7 +177,7 @@ static FacetSliceType slice_facet(
|
|||
// (external on the right of the line)
|
||||
for (int j = 0; j < 3; ++ j) { // loop through facet edges
|
||||
int edge_id;
|
||||
const stl_vertex *a, *b;
|
||||
const stl_vertex *a, *b, *c;
|
||||
int a_id, b_id;
|
||||
{
|
||||
int k = (idx_vertex_lowest + j) % 3;
|
||||
|
|
@ -184,6 +187,7 @@ static FacetSliceType slice_facet(
|
|||
a = vertices + k;
|
||||
b_id = indices[l];
|
||||
b = vertices + l;
|
||||
c = vertices + (k + 2) % 3;
|
||||
}
|
||||
|
||||
// Is edge or face aligned with the cutting plane?
|
||||
|
|
@ -319,6 +323,159 @@ static FacetSliceType slice_facet(
|
|||
return FacetSliceType::NoSlice;
|
||||
}
|
||||
|
||||
// Return true, if the facet has been sliced and line_out has been filled.
|
||||
static FacetSliceType slice_facet_for_cut_mesh(
|
||||
// Z height of the slice in XY plane. Scaled or unscaled (same as vertices[].z()).
|
||||
float slice_z,
|
||||
// 3 vertices of the triangle, XY scaled. Z scaled or unscaled (same as slice_z).
|
||||
const stl_vertex * vertices,
|
||||
const stl_triangle_vertex_indices &indices,
|
||||
const Vec3i & edge_ids,
|
||||
const int idx_vertex_lowest,
|
||||
const bool horizontal,
|
||||
IntersectionLine & line_out)
|
||||
{
|
||||
IntersectionPoint points[3];
|
||||
size_t num_points = 0;
|
||||
auto point_on_layer = size_t(-1);
|
||||
|
||||
// Reorder vertices so that the first one is the one with lowest Z.
|
||||
// This is needed to get all intersection lines in a consistent order
|
||||
// (external on the right of the line)
|
||||
for (int j = 0; j < 3; ++j) { // loop through facet edges
|
||||
int edge_id;
|
||||
const stl_vertex *a, *b, *c;
|
||||
int a_id, b_id;
|
||||
{
|
||||
int k = (idx_vertex_lowest + j) % 3;
|
||||
int l = (k + 1) % 3;
|
||||
edge_id = edge_ids(k);
|
||||
a_id = indices[k];
|
||||
a = vertices + k;
|
||||
b_id = indices[l];
|
||||
b = vertices + l;
|
||||
c = vertices + (k + 2) % 3;
|
||||
}
|
||||
|
||||
// Is edge or face aligned with the cutting plane?
|
||||
if (is_equal(a->z(), slice_z) && is_equal(b->z(), slice_z)) {
|
||||
// Edge is horizontal and belongs to the current layer.
|
||||
// The following rotation of the three vertices may not be efficient, but this branch happens rarely.
|
||||
const stl_vertex &v0 = vertices[0];
|
||||
const stl_vertex &v1 = vertices[1];
|
||||
const stl_vertex &v2 = vertices[2];
|
||||
// We may ignore this edge for slicing purposes, but we may still use it for object cutting.
|
||||
FacetSliceType result = FacetSliceType::Slicing;
|
||||
if (horizontal) {
|
||||
// All three vertices are aligned with slice_z.
|
||||
line_out.edge_type = IntersectionLine::FacetEdgeType::Horizontal;
|
||||
result = FacetSliceType::Cutting;
|
||||
double normal = (v1.x() - v0.x()) * (v2.y() - v1.y()) - (v1.y() - v0.y()) * (v2.x() - v1.x());
|
||||
if (normal < 0) {
|
||||
// If normal points downwards this is a bottom horizontal facet so we reverse its point order.
|
||||
std::swap(a, b);
|
||||
std::swap(a_id, b_id);
|
||||
}
|
||||
} else {
|
||||
// Two vertices are aligned with the cutting plane, the third vertex is below or above the cutting plane.
|
||||
// Is the third vertex below the cutting plane?
|
||||
bool third_below = c->z() < slice_z;
|
||||
// Two vertices on the cutting plane, the third vertex is below the plane. Consider the edge to be part of the slice
|
||||
// only if it is the upper edge.
|
||||
// (the bottom most edge resp. vertex of a triangle is not owned by the triangle, but the top most edge resp. vertex is part of the triangle
|
||||
// in respect to the cutting plane).
|
||||
result = third_below ? FacetSliceType::Slicing : FacetSliceType::Cutting;
|
||||
if (third_below) {
|
||||
line_out.edge_type = IntersectionLine::FacetEdgeType::Top;
|
||||
std::swap(a, b);
|
||||
std::swap(a_id, b_id);
|
||||
} else
|
||||
line_out.edge_type = IntersectionLine::FacetEdgeType::Bottom;
|
||||
}
|
||||
line_out.a.x() = a->x();
|
||||
line_out.a.y() = a->y();
|
||||
line_out.b.x() = b->x();
|
||||
line_out.b.y() = b->y();
|
||||
line_out.a_id = a_id;
|
||||
line_out.b_id = b_id;
|
||||
assert(line_out.a != line_out.b);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (is_equal(a->z(), slice_z)) {
|
||||
// Only point a alings with the cutting plane.
|
||||
if (point_on_layer == size_t(-1) || points[point_on_layer].point_id != a_id) {
|
||||
point_on_layer = num_points;
|
||||
IntersectionPoint &point = points[num_points++];
|
||||
point.x() = a->x();
|
||||
point.y() = a->y();
|
||||
point.point_id = a_id;
|
||||
}
|
||||
} else if (is_equal(b->z(), slice_z)) {
|
||||
// Only point b alings with the cutting plane.
|
||||
if (point_on_layer == size_t(-1) || points[point_on_layer].point_id != b_id) {
|
||||
point_on_layer = num_points;
|
||||
IntersectionPoint &point = points[num_points++];
|
||||
point.x() = b->x();
|
||||
point.y() = b->y();
|
||||
point.point_id = b_id;
|
||||
}
|
||||
} else if ((a->z() < slice_z && b->z() > slice_z) || (b->z() < slice_z && a->z() > slice_z)) {
|
||||
// A general case. The face edge intersects the cutting plane. Calculate the intersection point.
|
||||
assert(a_id != b_id);
|
||||
// Sort the edge to give a consistent answer.
|
||||
if (a_id > b_id) {
|
||||
std::swap(a_id, b_id);
|
||||
std::swap(a, b);
|
||||
}
|
||||
IntersectionPoint &point = points[num_points];
|
||||
double t = (double(slice_z) - double(b->z())) / (double(a->z()) - double(b->z()));
|
||||
if (t <= 0.) {
|
||||
if (point_on_layer == size_t(-1) || points[point_on_layer].point_id != a_id) {
|
||||
point.x() = a->x();
|
||||
point.y() = a->y();
|
||||
point_on_layer = num_points++;
|
||||
point.point_id = a_id;
|
||||
}
|
||||
} else if (t >= 1.) {
|
||||
if (point_on_layer == size_t(-1) || points[point_on_layer].point_id != b_id) {
|
||||
point.x() = b->x();
|
||||
point.y() = b->y();
|
||||
point_on_layer = num_points++;
|
||||
point.point_id = b_id;
|
||||
}
|
||||
} else {
|
||||
point.x() = coord_t(floor(double(b->x()) + (double(a->x()) - double(b->x())) * t + 0.5));
|
||||
point.y() = coord_t(floor(double(b->y()) + (double(a->y()) - double(b->y())) * t + 0.5));
|
||||
point.edge_id = edge_id;
|
||||
++num_points;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Facets must intersect each plane 0 or 2 times, or it may touch the plane at a single vertex only.
|
||||
assert(num_points < 3);
|
||||
if (num_points == 2) {
|
||||
line_out.edge_type = IntersectionLine::FacetEdgeType::General;
|
||||
line_out.a = static_cast<const Point &>(points[1]);
|
||||
line_out.b = static_cast<const Point &>(points[0]);
|
||||
line_out.a_id = points[1].point_id;
|
||||
line_out.b_id = points[0].point_id;
|
||||
line_out.edge_a_id = points[1].edge_id;
|
||||
line_out.edge_b_id = points[0].edge_id;
|
||||
// Not a zero lenght edge.
|
||||
// FIXME slice_facet() may create zero length edges due to rounding of doubles into coord_t.
|
||||
// assert(line_out.a != line_out.b);
|
||||
// The plane cuts at least one edge in a general position.
|
||||
assert(line_out.a_id == -1 || line_out.b_id == -1);
|
||||
assert(line_out.edge_a_id != -1 || line_out.edge_b_id != -1);
|
||||
// General slicing position, use the segment for both slicing and object cutting.
|
||||
|
||||
return FacetSliceType::Slicing;
|
||||
}
|
||||
return FacetSliceType::NoSlice;
|
||||
}
|
||||
|
||||
template<typename TransformVertex>
|
||||
void slice_facet_at_zs(
|
||||
// Scaled or unscaled vertices. transform_vertex_fn may scale zs.
|
||||
|
|
@ -336,12 +493,12 @@ void slice_facet_at_zs(
|
|||
// find facet extents
|
||||
const float min_z = fminf(vertices[0].z(), fminf(vertices[1].z(), vertices[2].z()));
|
||||
const float max_z = fmaxf(vertices[0].z(), fmaxf(vertices[1].z(), vertices[2].z()));
|
||||
|
||||
|
||||
// find layer extents
|
||||
auto min_layer = std::lower_bound(zs.begin(), zs.end(), min_z); // first layer whose slice_z is >= min_z
|
||||
auto max_layer = std::upper_bound(min_layer, zs.end(), max_z); // first layer whose slice_z is > max_z
|
||||
int idx_vertex_lowest = (vertices[1].z() == min_z) ? 1 : ((vertices[2].z() == min_z) ? 2 : 0);
|
||||
|
||||
|
||||
for (auto it = min_layer; it != max_layer; ++ it) {
|
||||
IntersectionLine il;
|
||||
// Ignore horizontal triangles. Any valid horizontal triangle must have a vertical triangle connected, otherwise the part has zero volume.
|
||||
|
|
@ -396,7 +553,7 @@ static inline IntersectionLines slice_make_lines(
|
|||
const float min_z = fminf(vertices[0].z(), fminf(vertices[1].z(), vertices[2].z()));
|
||||
const float max_z = fmaxf(vertices[0].z(), fmaxf(vertices[1].z(), vertices[2].z()));
|
||||
assert(min_z <= plane_z && max_z >= plane_z);
|
||||
int idx_vertex_lowest = (vertices[1].z() == min_z) ? 1 : ((vertices[2].z() == min_z) ? 2 : 0);
|
||||
int idx_vertex_lowest = (vertices[1].z() == min_z) ? 1 : ((vertices[2].z() == min_z) ? 2 : 0);
|
||||
IntersectionLine il;
|
||||
// Ignore horizontal triangles. Any valid horizontal triangle must have a vertical triangle connected, otherwise the part has zero volume.
|
||||
if (min_z != max_z && slice_facet(plane_z, vertices, indices, face_edge_ids[face_idx], idx_vertex_lowest, false, il) == FacetSliceType::Slicing) {
|
||||
|
|
@ -452,7 +609,7 @@ void slice_facet_with_slabs(
|
|||
const float min_z = fminf(vertices[0].z(), fminf(vertices[1].z(), vertices[2].z()));
|
||||
const float max_z = fmaxf(vertices[0].z(), fmaxf(vertices[1].z(), vertices[2].z()));
|
||||
const bool horizontal = min_z == max_z;
|
||||
|
||||
|
||||
// find layer extents
|
||||
auto min_layer = std::lower_bound(zs.begin(), zs.end(), min_z); // first layer whose slice_z is >= min_z
|
||||
auto max_layer = std::upper_bound(min_layer, zs.end(), max_z); // first layer whose slice_z is > max_z
|
||||
|
|
@ -2001,15 +2158,16 @@ void slice_mesh_slabs(
|
|||
|
||||
// Remove duplicates of slice_vertices, optionally triangulate the cut.
|
||||
static void triangulate_slice(
|
||||
indexed_triangle_set &its,
|
||||
IntersectionLines &lines,
|
||||
indexed_triangle_set &its,
|
||||
IntersectionLines &lines,
|
||||
std::vector<int> &slice_vertices,
|
||||
// Vertices of the original (unsliced) mesh. Newly added vertices are those on the slice.
|
||||
int num_original_vertices,
|
||||
// Z height of the slice.
|
||||
float z,
|
||||
bool triangulate,
|
||||
bool normals_down)
|
||||
float z,
|
||||
bool triangulate,
|
||||
bool normals_down,
|
||||
const std::map<int, Vec3f*> §ion_vertices_map)
|
||||
{
|
||||
sort_remove_duplicates(slice_vertices);
|
||||
|
||||
|
|
@ -2019,11 +2177,12 @@ static void triangulate_slice(
|
|||
map_vertex_to_index.reserve(slice_vertices.size());
|
||||
for (int i : slice_vertices)
|
||||
map_vertex_to_index.emplace_back(to_2d(its.vertices[i]), i);
|
||||
std::sort(map_vertex_to_index.begin(), map_vertex_to_index.end(),
|
||||
[](const std::pair<Vec2f, int> &l, const std::pair<Vec2f, int> &r) {
|
||||
return is_less(l.first.x(), r.first.x()) ||
|
||||
(is_equal(l.first.x(), r.first.x()) && (is_less(l.first.y(), r.first.y()) ||
|
||||
(is_equal(l.first.y(), r.first.y()) && l.second < r.second))); });
|
||||
std::sort(map_vertex_to_index.begin(), map_vertex_to_index.end(),
|
||||
[](const std::pair<Vec2f, int> &l, const std::pair<Vec2f, int> &r) {
|
||||
return l.first.x() < r.first.x() ||
|
||||
(is_equal_for_sort(l.first.x(), r.first.x()) && (l.first.y()< r.first.y() ||
|
||||
(is_equal_for_sort(l.first.y(), r.first.y()) && l.second < r.second)));
|
||||
});
|
||||
|
||||
// 2) Discover duplicate points on the slice. Remap duplicate vertices to a vertex with a lowest index.
|
||||
// Remove denegerate triangles, if they happen to be created by merging duplicate vertices.
|
||||
|
|
@ -2072,14 +2231,40 @@ static void triangulate_slice(
|
|||
stl_triangle_vertex_indices facet;
|
||||
for (size_t j = 0; j < 3; ++ j) {
|
||||
Vec3f v = triangles[i ++].cast<float>();
|
||||
auto it = lower_bound_by_predicate(map_vertex_to_index.begin(), map_vertex_to_index.end(),
|
||||
auto it = lower_bound_by_predicate(map_vertex_to_index.begin(), map_vertex_to_index.end(),
|
||||
[&v](const std::pair<Vec2f, int> &l) {
|
||||
return is_less(l.first.x(), v.x()) || (is_equal(l.first.x(), v.x()) && is_less(l.first.y(), v.y()));
|
||||
return l.first.x() < v.x() || (is_equal_for_sort(l.first.x(), v.x()) && l.first.y() < v.y());
|
||||
});
|
||||
int idx = -1;
|
||||
if (it != map_vertex_to_index.end() && is_equal(it->first.x(), v.x()) && is_equal(it->first.y(), v.y()))
|
||||
idx = it->second;
|
||||
else {
|
||||
bool exist = false;
|
||||
for (auto iter = section_vertices_map.begin(); iter != section_vertices_map.end(); iter++) {
|
||||
if (is_equal(v, *iter->second)) {
|
||||
idx = iter->first;
|
||||
exist = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// go on finding
|
||||
if (!exist) {
|
||||
for (; it != map_vertex_to_index.end(); it++) {
|
||||
if (is_equal(it->first.x(), v.x()) && is_equal(it->first.y(), v.y())) {
|
||||
idx = it->second;
|
||||
exist = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// go on finding
|
||||
if (!exist) {
|
||||
for (; it != map_vertex_to_index.begin(); it--) {
|
||||
if (is_equal(it->first.x(), v.x()) && is_equal(it->first.y(), v.y())) {
|
||||
idx = it->second;
|
||||
exist = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!exist){
|
||||
// Try to find the vertex in the list of newly added vertices. Those vertices are not matched on the cut and they shall be rare.
|
||||
for (size_t k = idx_vertex_new_first; k < its.vertices.size(); ++ k)
|
||||
if (its.vertices[k] == v) {
|
||||
|
|
@ -2160,16 +2345,22 @@ void cut_mesh(const indexed_triangle_set& mesh, float z, indexed_triangle_set* u
|
|||
IntersectionLines upper_lines, lower_lines;
|
||||
std::vector<int> upper_slice_vertices, lower_slice_vertices;
|
||||
std::vector<Vec3i> facets_edge_ids = its_face_edge_ids(mesh);
|
||||
std::map<int, Vec3f *> section_vertices_map;
|
||||
|
||||
for (int facet_idx = 0; facet_idx < int(mesh.indices.size()); ++ facet_idx) {
|
||||
const stl_triangle_vertex_indices &facet = mesh.indices[facet_idx];
|
||||
Vec3f vertices[3] { mesh.vertices[facet(0)], mesh.vertices[facet(1)], mesh.vertices[facet(2)] };
|
||||
float min_z = std::min(vertices[0].z(), std::min(vertices[1].z(), vertices[2].z()));
|
||||
float max_z = std::max(vertices[0].z(), std::max(vertices[1].z(), vertices[2].z()));
|
||||
|
||||
|
||||
for (size_t i = 0; i < 3; i++) {
|
||||
if (is_equal(z, vertices[i].z()) && section_vertices_map[facet(i)] == nullptr) {
|
||||
section_vertices_map[facet(i)] = new Vec3f(vertices[i].x(), vertices[i].y(), vertices[i].z());
|
||||
}
|
||||
}
|
||||
// intersect facet with cutting plane
|
||||
IntersectionLine line;
|
||||
int idx_vertex_lowest = (vertices[1].z() == min_z) ? 1 : ((vertices[2].z() == min_z) ? 2 : 0);
|
||||
int idx_vertex_lowest = is_equal(vertices[1].z(), min_z) ? 1 : (is_equal(vertices[2].z() , min_z) ? 2 : 0);
|
||||
FacetSliceType slice_type = FacetSliceType::NoSlice;
|
||||
if (z > min_z - EPSILON && z < max_z + EPSILON) {
|
||||
Vec3f vertices_scaled[3];
|
||||
|
|
@ -2180,7 +2371,7 @@ void cut_mesh(const indexed_triangle_set& mesh, float z, indexed_triangle_set* u
|
|||
dst.y() = scale_(src.y());
|
||||
dst.z() = src.z();
|
||||
}
|
||||
slice_type = slice_facet(z, vertices_scaled, mesh.indices[facet_idx], facets_edge_ids[facet_idx], idx_vertex_lowest, min_z == max_z, line);
|
||||
slice_type = slice_facet_for_cut_mesh(z, vertices_scaled, mesh.indices[facet_idx], facets_edge_ids[facet_idx], idx_vertex_lowest, is_equal(min_z, max_z), line);
|
||||
}
|
||||
|
||||
if (slice_type != FacetSliceType::NoSlice) {
|
||||
|
|
@ -2198,12 +2389,12 @@ void cut_mesh(const indexed_triangle_set& mesh, float z, indexed_triangle_set* u
|
|||
upper_lines.emplace_back(line);
|
||||
}
|
||||
}
|
||||
|
||||
if (min_z > z || (min_z == z && max_z > z)) {
|
||||
|
||||
if (min_z > z || (is_equal(min_z , z) && max_z > z)) {
|
||||
// facet is above the cut plane and does not belong to it
|
||||
if (upper != nullptr)
|
||||
upper->indices.emplace_back(facet);
|
||||
} else if (max_z < z || (max_z == z && min_z < z)) {
|
||||
} else if (max_z < z || (is_equal(max_z, z) && min_z < z)) {
|
||||
// facet is below the cut plane and does not belong to it
|
||||
if (lower != nullptr)
|
||||
lower->indices.emplace_back(facet);
|
||||
|
|
@ -2215,21 +2406,56 @@ void cut_mesh(const indexed_triangle_set& mesh, float z, indexed_triangle_set* u
|
|||
assert(line.edge_b_id != -1);
|
||||
|
||||
// look for the vertex on whose side of the slicing plane there are no other vertices
|
||||
int isolated_vertex =
|
||||
(vertices[0].z() > z) == (vertices[1].z() > z) ? 2 :
|
||||
(vertices[1].z() > z) == (vertices[2].z() > z) ? 0 : 1;
|
||||
|
||||
// get vertices starting from the isolated one
|
||||
int iv = isolated_vertex;
|
||||
stl_vertex v0v1, v2v0;
|
||||
assert(facets_edge_ids[facet_idx](iv) == line.edge_a_id || facets_edge_ids[facet_idx](iv) == line.edge_b_id);
|
||||
if (facets_edge_ids[facet_idx](iv) == line.edge_a_id) {
|
||||
// Unscale to doubles first, then to floats to reach the same accuracy as triangulate_expolygons_2d().
|
||||
v0v1 = to_3d(unscaled<double>(line.a).cast<float>().eval(), z);
|
||||
v2v0 = to_3d(unscaled<double>(line.b).cast<float>().eval(), z);
|
||||
int isolated_vertex, isolated_vertex_option = -1;
|
||||
std::vector<int> list{0, 1, 2};
|
||||
auto get_third = [&list](int isolated_vertex, int temp) {// not use vertex data
|
||||
for (size_t i = 0; i < list.size(); i++) {
|
||||
if (list[i] != isolated_vertex && list[i] != temp) {
|
||||
return list[i];
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
if (is_equal(vertices[0].z(), z)) {
|
||||
isolated_vertex = vertices[1].z() > z ? 1 : 2;
|
||||
isolated_vertex_option = get_third(isolated_vertex, 0);
|
||||
} else if (is_equal(vertices[1].z(), z)) {
|
||||
isolated_vertex = vertices[2].z() > z ? 2 : 0;
|
||||
isolated_vertex_option = get_third(isolated_vertex, 1);
|
||||
} else if (is_equal(vertices[2].z(), z)) {
|
||||
isolated_vertex = vertices[0].z() > z ? 0 : 1;
|
||||
isolated_vertex_option = get_third(isolated_vertex, 2);
|
||||
} else {
|
||||
v0v1 = to_3d(unscaled<double>(line.b).cast<float>().eval(), z);
|
||||
v2v0 = to_3d(unscaled<double>(line.a).cast<float>().eval(), z);
|
||||
isolated_vertex = (vertices[0].z() > z) == (vertices[1].z() > z) ? 2 : (vertices[1].z() > z) == (vertices[2].z() > z) ? 0 : 1;
|
||||
}
|
||||
// get vertices starting from the isolated one
|
||||
stl_vertex v0v1, v2v0;
|
||||
auto calc_isolated_vertex = [&v0v1, &v2v0, &line, &facet_idx, &facets_edge_ids, &z](int iv, bool &is_find) {
|
||||
assert(facets_edge_ids[facet_idx](iv) == line.edge_a_id || facets_edge_ids[facet_idx](iv) == line.edge_b_id);
|
||||
is_find = true;
|
||||
if (facets_edge_ids[facet_idx](iv) == line.edge_a_id) {
|
||||
// Unscale to doubles first, then to floats to reach the same accuracy as triangulate_expolygons_2d().
|
||||
v0v1 = to_3d(unscaled<double>(line.a).cast<float>().eval(), z);
|
||||
v2v0 = to_3d(unscaled<double>(line.b).cast<float>().eval(), z);
|
||||
} else if (facets_edge_ids[facet_idx](iv) == line.edge_b_id) {
|
||||
v0v1 = to_3d(unscaled<double>(line.b).cast<float>().eval(), z);
|
||||
v2v0 = to_3d(unscaled<double>(line.a).cast<float>().eval(), z);
|
||||
} else {
|
||||
is_find = false;
|
||||
}
|
||||
};
|
||||
bool find_isolated_vertex;
|
||||
int iv;
|
||||
calc_isolated_vertex(isolated_vertex, find_isolated_vertex);
|
||||
if (!find_isolated_vertex && isolated_vertex_option != -1) {
|
||||
calc_isolated_vertex(isolated_vertex_option, find_isolated_vertex);
|
||||
if (!find_isolated_vertex) {
|
||||
BOOST_LOG_TRIVIAL(trace) << "cut_mesh:error:could not find isolated_vertex";
|
||||
continue;
|
||||
}
|
||||
iv = isolated_vertex_option;
|
||||
} else {
|
||||
iv = isolated_vertex;
|
||||
}
|
||||
const stl_vertex &v0 = vertices[iv];
|
||||
const int iv0 = facet[iv];
|
||||
|
|
@ -2243,48 +2469,71 @@ void cut_mesh(const indexed_triangle_set& mesh, float z, indexed_triangle_set* u
|
|||
const int iv2 = facet[iv];
|
||||
|
||||
// intersect v0-v1 and v2-v0 with cutting plane and make new vertices
|
||||
auto new_vertex = [upper, lower, &upper_slice_vertices, &lower_slice_vertices](const Vec3f &a, const int ia, const Vec3f &b, const int ib, const Vec3f &c) {
|
||||
auto new_vertex = [upper, lower, &upper_slice_vertices, &lower_slice_vertices](const Vec3f &a, const int ia, const Vec3f &b, const int ib, const Vec3f &c,
|
||||
const int ic, const Vec3f &new_pt, bool &is_new_vertex) {
|
||||
int iupper, ilower;
|
||||
if (c == a)
|
||||
is_new_vertex = false;
|
||||
if (is_equal(new_pt, a))
|
||||
iupper = ilower = ia;
|
||||
else if (c == b)
|
||||
else if (is_equal(new_pt, b))
|
||||
iupper = ilower = ib;
|
||||
else if (is_equal(new_pt, c))
|
||||
iupper = ilower = ic;
|
||||
else {
|
||||
// Insert a new vertex into upper / lower.
|
||||
is_new_vertex = true;
|
||||
if (upper) {
|
||||
iupper = int(upper->vertices.size());
|
||||
upper->vertices.emplace_back(c);
|
||||
upper->vertices.emplace_back(new_pt);
|
||||
upper_slice_vertices.emplace_back(iupper);
|
||||
}
|
||||
if (lower) {
|
||||
ilower = int(lower->vertices.size());
|
||||
lower->vertices.emplace_back(c);
|
||||
lower->vertices.emplace_back(new_pt);
|
||||
lower_slice_vertices.emplace_back(ilower);
|
||||
}
|
||||
}
|
||||
return std::make_pair(iupper, ilower);
|
||||
};
|
||||
auto [iv0v1_upper, iv0v1_lower] = new_vertex(v1, iv1, v0, iv0, v0v1);
|
||||
auto [iv2v0_upper, iv2v0_lower] = new_vertex(v2, iv2, v0, iv0, v2v0);
|
||||
auto new_face = [](indexed_triangle_set *its, int i, int j, int k) {
|
||||
if (its != nullptr && i != j && i != k && j != k)
|
||||
its->indices.emplace_back(i, j, k);
|
||||
bool is_new_vertex_v0v1;
|
||||
bool is_new_vertex_v2v0;
|
||||
auto [iv0v1_upper, iv0v1_lower] = new_vertex(v1, iv1, v0, iv0, v2, iv2, v0v1, is_new_vertex_v0v1);
|
||||
auto [iv2v0_upper, iv2v0_lower] = new_vertex(v2, iv2, v0, iv0, v1, iv1, v2v0, is_new_vertex_v2v0);
|
||||
auto new_face = [](indexed_triangle_set *its, int i, int j, int k) {
|
||||
if (its != nullptr && i != j && i != k && j != k) its->indices.emplace_back(i, j, k);
|
||||
};
|
||||
|
||||
if (v0.z() > z) {
|
||||
new_face(upper, iv0, iv0v1_upper, iv2v0_upper);
|
||||
new_face(lower, iv1, iv2, iv0v1_lower);
|
||||
new_face(lower, iv2, iv2v0_lower, iv0v1_lower);
|
||||
} else {
|
||||
new_face(upper, iv1, iv2, iv0v1_upper);
|
||||
new_face(upper, iv2, iv2v0_upper, iv0v1_upper);
|
||||
new_face(lower, iv0, iv0v1_lower, iv2v0_lower);
|
||||
if (is_new_vertex_v0v1 && is_new_vertex_v2v0) {
|
||||
if (v0.z() > z) {
|
||||
new_face(upper, iv0, iv0v1_upper, iv2v0_upper);
|
||||
new_face(lower, iv1, iv2, iv0v1_lower);
|
||||
new_face(lower, iv2, iv2v0_lower, iv0v1_lower);
|
||||
} else {
|
||||
new_face(upper, iv1, iv2, iv0v1_upper);
|
||||
new_face(upper, iv2, iv2v0_upper, iv0v1_upper);
|
||||
new_face(lower, iv0, iv0v1_lower, iv2v0_lower);
|
||||
}
|
||||
} else if (is_new_vertex_v0v1) {
|
||||
if (v0.z() > z) {
|
||||
new_face(upper, iv0, iv0v1_upper, iv2);
|
||||
new_face(lower, iv1, iv2, iv0v1_lower);
|
||||
} else {
|
||||
new_face(lower, iv0, iv0v1_lower, iv2);
|
||||
new_face(upper, iv1, iv2, iv0v1_upper);
|
||||
}
|
||||
} else if (is_new_vertex_v2v0) {
|
||||
if (v0.z() > z) {
|
||||
new_face(upper, iv0, iv1, iv2v0_upper);
|
||||
new_face(lower, iv1, iv2, iv2v0_lower);
|
||||
} else {
|
||||
new_face(lower, iv0, iv1, iv2v0_lower);
|
||||
new_face(upper, iv1, iv2, iv2v0_upper);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (upper != nullptr) {
|
||||
triangulate_slice(*upper, upper_lines, upper_slice_vertices, int(mesh.vertices.size()), z, triangulate_caps, NORMALS_DOWN);
|
||||
triangulate_slice(*upper, upper_lines, upper_slice_vertices, int(mesh.vertices.size()), z, triangulate_caps, NORMALS_DOWN, section_vertices_map);
|
||||
#ifndef NDEBUG
|
||||
if (triangulate_caps) {
|
||||
size_t num_open_edges_new = its_num_open_edges(*upper);
|
||||
|
|
@ -2294,7 +2543,7 @@ void cut_mesh(const indexed_triangle_set& mesh, float z, indexed_triangle_set* u
|
|||
}
|
||||
|
||||
if (lower != nullptr) {
|
||||
triangulate_slice(*lower, lower_lines, lower_slice_vertices, int(mesh.vertices.size()), z, triangulate_caps, NORMALS_UP);
|
||||
triangulate_slice(*lower, lower_lines, lower_slice_vertices, int(mesh.vertices.size()), z, triangulate_caps, NORMALS_UP, section_vertices_map);
|
||||
#ifndef NDEBUG
|
||||
if (triangulate_caps) {
|
||||
size_t num_open_edges_new = its_num_open_edges(*lower);
|
||||
|
|
@ -2302,6 +2551,7 @@ void cut_mesh(const indexed_triangle_set& mesh, float z, indexed_triangle_set* u
|
|||
}
|
||||
#endif // NDEBUG
|
||||
}
|
||||
std::map<int, Vec3f*>().swap(section_vertices_map);
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
|
|
|
|||
|
|
@ -1703,7 +1703,12 @@ void TriangleSelector::deserialize(const std::pair<std::vector<std::pair<int, in
|
|||
{
|
||||
if (needs_reset)
|
||||
reset(); // dump any current state
|
||||
|
||||
for (auto [triangle_id, ibit] : data.first) {
|
||||
if (triangle_id >= int(m_triangles.size())) {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "array bound:error:triangle_id >= int(m_triangles.size())";
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Reserve number of triangles as if each triangle was saved with 4 bits.
|
||||
// With MMU painting this estimate may be somehow low, but better than nothing.
|
||||
m_triangles.reserve(std::max(m_mesh.its.indices.size(), data.second.size() / 4));
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@
|
|||
#define CLI_PRINTABLE_SIZE_REDUCED -20
|
||||
#define CLI_OBJECT_ARRANGE_FAILED -21
|
||||
#define CLI_OBJECT_ORIENT_FAILED -22
|
||||
#define CLI_MODIFIED_PARAMS_TO_PRINTER -23
|
||||
|
||||
|
||||
#define CLI_NO_SUITABLE_OBJECTS -50
|
||||
|
|
@ -124,8 +125,11 @@ inline std::string convert_to_full_version(std::string short_version)
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
template<typename DataType>
|
||||
inline DataType round_divide(DataType dividend, DataType divisor) //!< Return dividend divided by divisor rounded to the nearest integer
|
||||
{
|
||||
return (dividend + divisor / 2) / divisor;
|
||||
}
|
||||
|
||||
// Set a path with GUI localization files.
|
||||
void set_local_dir(const std::string &path);
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ static constexpr double RESOLUTION = 0.0125;
|
|||
static constexpr double SPARSE_INFILL_RESOLUTION = 0.04;
|
||||
#define SCALED_SPARSE_INFILL_RESOLUTION (SPARSE_INFILL_RESOLUTION / SCALING_FACTOR)
|
||||
|
||||
static constexpr double SUPPORT_RESOLUTION = 0.05;
|
||||
static constexpr double SUPPORT_RESOLUTION = 0.1;
|
||||
#define SCALED_SUPPORT_RESOLUTION (SUPPORT_RESOLUTION / SCALING_FACTOR)
|
||||
// Maximum perimeter length for the loop to apply the small perimeter speed.
|
||||
#define SMALL_PERIMETER_LENGTH(LENGTH) (((LENGTH) / SCALING_FACTOR) * 2 * PI)
|
||||
|
|
@ -76,6 +76,7 @@ static constexpr double INSET_OVERLAP_TOLERANCE = 0.4;
|
|||
//FIXME This is quite a lot.
|
||||
static constexpr double EXTERNAL_INFILL_MARGIN = 3;
|
||||
static constexpr double BRIDGE_INFILL_MARGIN = 1;
|
||||
static constexpr double WIPE_TOWER_MARGIN = 15.;
|
||||
//FIXME Better to use an inline function with an explicit return type.
|
||||
//inline coord_t scale_(coordf_t v) { return coord_t(floor(v / SCALING_FACTOR + 0.5f)); }
|
||||
#define scale_(val) ((val) / SCALING_FACTOR)
|
||||
|
|
|
|||
|
|
@ -208,6 +208,11 @@ const std::string& var_dir()
|
|||
|
||||
std::string var(const std::string &file_name)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
if (boost::filesystem::exists(file_name, ec)) {
|
||||
return file_name;
|
||||
}
|
||||
|
||||
auto file = (boost::filesystem::path(g_var_dir) / file_name).make_preferred();
|
||||
return file.string();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -91,6 +91,8 @@ set(SLIC3R_GUI_SOURCES
|
|||
GUI/AuxiliaryDialog.hpp
|
||||
GUI/Auxiliary.cpp
|
||||
GUI/Auxiliary.hpp
|
||||
GUI/DailyTips.cpp
|
||||
GUI/DailyTips.hpp
|
||||
GUI/Project.cpp
|
||||
GUI/Project.hpp
|
||||
GUI/BackgroundSlicingProcess.cpp
|
||||
|
|
@ -114,6 +116,8 @@ set(SLIC3R_GUI_SOURCES
|
|||
GUI/OpenGLManager.cpp
|
||||
GUI/Selection.hpp
|
||||
GUI/Selection.cpp
|
||||
GUI/SlicingProgressNotification.cpp
|
||||
GUI/SlicingProgressNotification.hpp
|
||||
GUI/Gizmos/GLGizmosManager.cpp
|
||||
GUI/Gizmos/GLGizmosManager.hpp
|
||||
GUI/Gizmos/GLGizmosCommon.cpp
|
||||
|
|
@ -288,7 +292,7 @@ set(SLIC3R_GUI_SOURCES
|
|||
GUI/3DBed.hpp
|
||||
GUI/Camera.cpp
|
||||
GUI/Camera.hpp
|
||||
GUI/CameraUtils.cpp
|
||||
GUI/CameraUtils.cpp
|
||||
GUI/CameraUtils.hpp
|
||||
GUI/wxExtensions.cpp
|
||||
GUI/wxExtensions.hpp
|
||||
|
|
@ -391,7 +395,7 @@ set(SLIC3R_GUI_SOURCES
|
|||
GUI/DragCanvas.hpp
|
||||
GUI/PublishDialog.cpp
|
||||
GUI/PublishDialog.hpp
|
||||
GUI/RecenterDialog.cpp
|
||||
GUI/RecenterDialog.cpp
|
||||
GUI/RecenterDialog.hpp
|
||||
GUI/PrivacyUpdateDialog.cpp
|
||||
GUI/PrivacyUpdateDialog.hpp
|
||||
|
|
@ -419,13 +423,13 @@ set(SLIC3R_GUI_SOURCES
|
|||
GUI/CalibrationWizard.cpp
|
||||
GUI/CalibrationWizardPage.cpp
|
||||
GUI/CalibrationWizardPage.hpp
|
||||
GUI/CalibrationWizardStartPage.cpp
|
||||
GUI/CalibrationWizardStartPage.cpp
|
||||
GUI/CalibrationWizardStartPage.hpp
|
||||
GUI/CalibrationWizardPresetPage.cpp
|
||||
GUI/CalibrationWizardPresetPage.cpp
|
||||
GUI/CalibrationWizardPresetPage.hpp
|
||||
GUI/CalibrationWizardCaliPage.cpp
|
||||
GUI/CalibrationWizardCaliPage.cpp
|
||||
GUI/CalibrationWizardCaliPage.hpp
|
||||
GUI/CalibrationWizardSavePage.cpp
|
||||
GUI/CalibrationWizardSavePage.cpp
|
||||
GUI/CalibrationWizardSavePage.hpp
|
||||
GUI/Calibration.hpp
|
||||
GUI/Calibration.cpp
|
||||
|
|
@ -435,6 +439,8 @@ set(SLIC3R_GUI_SOURCES
|
|||
GUI/BonjourDialog.cpp
|
||||
GUI/BedShapeDialog.hpp
|
||||
GUI/BedShapeDialog.cpp
|
||||
GUI/CreatePresetsDialog.hpp
|
||||
GUI/CreatePresetsDialog.cpp
|
||||
Utils/json_diff.hpp
|
||||
Utils/json_diff.cpp
|
||||
GUI/KBShortcutsDialog.hpp
|
||||
|
|
@ -445,6 +451,8 @@ set(SLIC3R_GUI_SOURCES
|
|||
Utils/FixModelByWin10.hpp
|
||||
Utils/Bonjour.cpp
|
||||
Utils/Bonjour.hpp
|
||||
Utils/FileHelp.cpp
|
||||
Utils/FileHelp.hpp
|
||||
Utils/PresetUpdater.cpp
|
||||
Utils/PresetUpdater.hpp
|
||||
Utils/Process.cpp
|
||||
|
|
|
|||
|
|
@ -645,8 +645,12 @@ void Bed3D::update_bed_triangles()
|
|||
(*model_offset_ptr)(1) = m_build_volume.bounding_volume2d().min.y() - bed_ext.min.y();
|
||||
(*model_offset_ptr)(2) = -0.41 + GROUND_Z;
|
||||
|
||||
std::vector<Vec2d> new_bed_shape;
|
||||
for (auto point: m_bed_shape) {
|
||||
std::vector<Vec2d> origin_bed_shape;
|
||||
for (size_t i = 0; i < m_bed_shape.size(); i++) {
|
||||
origin_bed_shape.push_back(m_bed_shape[i] - m_bed_shape[0]);
|
||||
}
|
||||
std::vector<Vec2d> new_bed_shape; // offset to correct origin
|
||||
for (auto point : origin_bed_shape) {
|
||||
Vec2d new_point(point.x() + model_offset_ptr->x(), point.y() + model_offset_ptr->y());
|
||||
new_bed_shape.push_back(new_point);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -612,30 +612,38 @@ bool GLWipeTowerVolume::IsTransparent() {
|
|||
}
|
||||
|
||||
std::vector<int> GLVolumeCollection::load_object(
|
||||
const ModelObject* model_object,
|
||||
int obj_idx,
|
||||
const std::vector<int>& instance_idxs)
|
||||
const ModelObject *model_object,
|
||||
int obj_idx,
|
||||
const std::vector<int> &instance_idxs,
|
||||
const std::string &color_by,
|
||||
bool opengl_initialized)
|
||||
{
|
||||
std::vector<int> volumes_idx;
|
||||
for (int volume_idx = 0; volume_idx < int(model_object->volumes.size()); ++volume_idx)
|
||||
for (int instance_idx : instance_idxs)
|
||||
volumes_idx.emplace_back(this->GLVolumeCollection::load_object_volume(model_object, obj_idx, volume_idx, instance_idx));
|
||||
volumes_idx.emplace_back(this->GLVolumeCollection::load_object_volume(model_object, obj_idx, volume_idx, instance_idx, color_by, opengl_initialized));
|
||||
return volumes_idx;
|
||||
}
|
||||
|
||||
|
||||
int GLVolumeCollection::load_object_volume(
|
||||
const ModelObject* model_object,
|
||||
const ModelObject *model_object,
|
||||
int obj_idx,
|
||||
int volume_idx,
|
||||
int instance_idx,
|
||||
const std::string &color_by,
|
||||
bool opengl_initialized,
|
||||
bool in_assemble_view,
|
||||
bool use_loaded_id)
|
||||
{
|
||||
const ModelVolume *model_volume = model_object->volumes[volume_idx];
|
||||
const int extruder_id = model_volume->extruder_id();
|
||||
const ModelInstance *instance = model_object->instances[instance_idx];
|
||||
auto color = GLVolume::MODEL_COLOR[((color_by == "volume") ? volume_idx : obj_idx) % 4];
|
||||
color.a(model_volume->is_model_part() ? 0.7f : 0.4f);
|
||||
|
||||
std::shared_ptr<const TriangleMesh> mesh = model_volume->mesh_ptr();
|
||||
this->volumes.emplace_back(new GLVolume());
|
||||
this->volumes.emplace_back(new GLVolume(color));
|
||||
GLVolume& v = *this->volumes.back();
|
||||
v.set_color(color_from_model_volume(*model_volume));
|
||||
v.name = model_volume->name;
|
||||
|
|
@ -647,7 +655,9 @@ int GLVolumeCollection::load_object_volume(
|
|||
v.mesh_raycaster = std::make_unique<GUI::MeshRaycaster>(mesh);
|
||||
#endif // ENABLE_SMOOTH_NORMALS
|
||||
v.composite_id = GLVolume::CompositeID(obj_idx, volume_idx, instance_idx);
|
||||
if (model_volume->is_model_part()) {
|
||||
|
||||
if (model_volume->is_model_part())
|
||||
{
|
||||
// GLVolume will reference a convex hull from model_volume!
|
||||
v.set_convex_hull(model_volume->get_convex_hull_shared_ptr());
|
||||
if (extruder_id != -1)
|
||||
|
|
|
|||
|
|
@ -440,18 +440,21 @@ public:
|
|||
~GLVolumeCollection() { clear(); }
|
||||
|
||||
std::vector<int> load_object(
|
||||
const ModelObject* model_object,
|
||||
const ModelObject *model_object,
|
||||
int obj_idx,
|
||||
const std::vector<int>& instance_idxs);
|
||||
const std::vector<int> &instance_idxs,
|
||||
const std::string &color_by,
|
||||
bool opengl_initialized);
|
||||
|
||||
int load_object_volume(
|
||||
const ModelObject* model_object,
|
||||
const ModelObject *model_object,
|
||||
int obj_idx,
|
||||
int volume_idx,
|
||||
int instance_idx,
|
||||
const std::string &color_by,
|
||||
bool opengl_initialized,
|
||||
bool in_assemble_view = false,
|
||||
bool use_loaded_id = false);
|
||||
|
||||
// Load SLA auxiliary GLVolumes (for support trees or pad).
|
||||
void load_object_auxiliary(
|
||||
const SLAPrintObject *print_object,
|
||||
|
|
|
|||
|
|
@ -323,12 +323,6 @@ void AMSMaterialsSetting::create_panel_kn(wxWindow* parent)
|
|||
m_n_param->Hide();
|
||||
m_input_n_val->Hide();
|
||||
|
||||
// hide n (P1P old logic)
|
||||
//if (!this->obj || !this->obj->is_high_printer_type()) {
|
||||
// m_n_param->Hide();
|
||||
// m_input_n_val->Hide();
|
||||
//}
|
||||
|
||||
sizer->Add(0, 0, 0, wxTOP, FromDIP(10));
|
||||
sizer->Add(m_ratio_text, 0, wxLEFT | wxRIGHT | wxEXPAND, FromDIP(20));
|
||||
sizer->Add(0, 0, 0, wxTOP, FromDIP(16));
|
||||
|
|
@ -447,7 +441,7 @@ void AMSMaterialsSetting::on_select_reset(wxCommandEvent& event) {
|
|||
}
|
||||
|
||||
// set k / n value
|
||||
if (!obj->is_high_printer_type()) {
|
||||
if (obj->get_printer_series() != PrinterSeries::SERIES_X1) {
|
||||
// set extrusion cali ratio
|
||||
int cali_tray_id = ams_id * 4 + tray_id;
|
||||
|
||||
|
|
@ -490,7 +484,9 @@ void AMSMaterialsSetting::on_select_ok(wxCommandEvent &event)
|
|||
if (preset_bundle) {
|
||||
for (auto it = preset_bundle->filaments.begin(); it != preset_bundle->filaments.end(); it++) {
|
||||
|
||||
if (it->alias.compare(m_comboBox_filament->GetValue().ToStdString()) == 0) {
|
||||
auto filament_item = map_filament_items[m_comboBox_filament->GetValue().ToStdString()];
|
||||
std::string filament_id = filament_item.filament_id;
|
||||
if (it->filament_id.compare(filament_id) == 0) {
|
||||
|
||||
|
||||
//check is it in the filament blacklist
|
||||
|
|
@ -501,9 +497,12 @@ void AMSMaterialsSetting::on_select_ok(wxCommandEvent &event)
|
|||
std::string filamnt_type;
|
||||
it->get_filament_type(filamnt_type);
|
||||
|
||||
if (it->vendor) {
|
||||
DeviceManager::check_filaments_in_blacklist(it->vendor->name, filamnt_type, in_blacklist, action, info);
|
||||
auto vendor = dynamic_cast<ConfigOptionStrings*> (it->config.option("filament_vendor"));
|
||||
if (vendor && (vendor->values.size() > 0)) {
|
||||
std::string vendor_name = vendor->values[0];
|
||||
DeviceManager::check_filaments_in_blacklist(vendor_name, filamnt_type, in_blacklist, action, info);
|
||||
}
|
||||
|
||||
|
||||
if (in_blacklist) {
|
||||
if (action == "prohibition") {
|
||||
|
|
@ -545,12 +544,6 @@ void AMSMaterialsSetting::on_select_ok(wxCommandEvent &event)
|
|||
return;
|
||||
}
|
||||
|
||||
if (ams_filament_id.empty() || nozzle_temp_min.empty() || nozzle_temp_max.empty() || m_filament_type.empty()) {
|
||||
BOOST_LOG_TRIVIAL(trace) << "Invalid Setting id";
|
||||
MessageDialog msg_dlg(nullptr, _L("You need to select the material type and color first."), wxEmptyString, wxICON_WARNING | wxOK);
|
||||
msg_dlg.ShowModal();
|
||||
return;
|
||||
}
|
||||
|
||||
// set filament
|
||||
if (m_is_third) {
|
||||
|
|
@ -566,9 +559,9 @@ void AMSMaterialsSetting::on_select_ok(wxCommandEvent &event)
|
|||
wxString k_text = m_input_k_val->GetTextCtrl()->GetValue();
|
||||
wxString n_text = m_input_n_val->GetTextCtrl()->GetValue();
|
||||
|
||||
if (!obj->is_high_printer_type() && !ExtrusionCalibration::check_k_validation(k_text)) {
|
||||
wxString k_tips = _L("Please input a valid value (K in 0~0.5)");
|
||||
wxString kn_tips = _L("Please input a valid value (K in 0~0.5, N in 0.6~2.0)");
|
||||
if ((obj->get_printer_series() != PrinterSeries::SERIES_X1) && !ExtrusionCalibration::check_k_validation(k_text)) {
|
||||
wxString k_tips = _L("Please input a valid value (K in 0~0.3)");
|
||||
wxString kn_tips = _L("Please input a valid value (K in 0~0.3, N in 0.6~2.0)");
|
||||
MessageDialog msg_dlg(nullptr, k_tips, wxEmptyString, wxICON_WARNING | wxOK);
|
||||
msg_dlg.ShowModal();
|
||||
return;
|
||||
|
|
@ -591,7 +584,7 @@ void AMSMaterialsSetting::on_select_ok(wxCommandEvent &event)
|
|||
;
|
||||
}
|
||||
|
||||
if (obj->is_high_printer_type()) {
|
||||
if (obj->get_printer_series() == PrinterSeries::SERIES_X1) {
|
||||
PACalibIndexInfo select_index_info;
|
||||
select_index_info.tray_id = tray_id;
|
||||
select_index_info.nozzle_diameter = obj->nozzle_diameter;
|
||||
|
|
@ -630,7 +623,7 @@ void AMSMaterialsSetting::on_select_ok(wxCommandEvent &event)
|
|||
;
|
||||
}
|
||||
|
||||
if (obj->is_high_printer_type()) {
|
||||
if (obj->get_printer_series() == PrinterSeries::SERIES_X1) {
|
||||
PACalibIndexInfo select_index_info;
|
||||
select_index_info.tray_id = cali_tray_id;
|
||||
select_index_info.nozzle_diameter = obj->nozzle_diameter;
|
||||
|
|
@ -729,7 +722,7 @@ void AMSMaterialsSetting::update_widgets()
|
|||
else
|
||||
m_panel_normal->Hide();
|
||||
m_panel_kn->Show();
|
||||
} else if (obj && (obj->is_function_supported(PrinterFunction::FUNC_VIRTUAL_TYAY) || obj->is_high_printer_type())) {
|
||||
} else if (obj && (obj->ams_support_virtual_tray || (obj->get_printer_series() == PrinterSeries::SERIES_X1))) {
|
||||
m_panel_normal->Show();
|
||||
m_panel_kn->Show();
|
||||
} else {
|
||||
|
|
@ -759,6 +752,7 @@ bool AMSMaterialsSetting::Show(bool show)
|
|||
|
||||
void AMSMaterialsSetting::Popup(wxString filament, wxString sn, wxString temp_min, wxString temp_max, wxString k, wxString n)
|
||||
{
|
||||
if (!obj) return;
|
||||
update_widgets();
|
||||
// set default value
|
||||
if (k.IsEmpty())
|
||||
|
|
@ -771,14 +765,22 @@ void AMSMaterialsSetting::Popup(wxString filament, wxString sn, wxString temp_mi
|
|||
|
||||
int selection_idx = -1, idx = 0;
|
||||
wxArrayString filament_items;
|
||||
|
||||
|
||||
std::set<std::string> filament_id_set;
|
||||
|
||||
PresetBundle* preset_bundle = wxGetApp().preset_bundle;
|
||||
if (preset_bundle) {
|
||||
BOOST_LOG_TRIVIAL(trace) << "system_preset_bundle filament number=" << preset_bundle->filaments.size();
|
||||
for (auto filament_it = preset_bundle->filaments.begin(); filament_it != preset_bundle->filaments.end(); filament_it++) {
|
||||
// filter by system preset
|
||||
if (!filament_it->is_system) continue;
|
||||
//filter by system preset
|
||||
Preset& preset = *filament_it;
|
||||
/*The situation where the user preset is not displayed is as follows:
|
||||
1. Not a root preset
|
||||
2. Not system preset and the printer firmware does not support user preset */
|
||||
if (preset_bundle->filaments.get_preset_base(*filament_it) != &preset || (!filament_it->is_system && !obj->is_support_user_preset)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (auto printer_it = preset_bundle->printers.begin(); printer_it != preset_bundle->printers.end(); printer_it++) {
|
||||
// filter by system preset
|
||||
|
|
@ -786,7 +788,7 @@ void AMSMaterialsSetting::Popup(wxString filament, wxString sn, wxString temp_mi
|
|||
// get printer_model
|
||||
ConfigOption* printer_model_opt = printer_it->config.option("printer_model");
|
||||
ConfigOptionString* printer_model_str = dynamic_cast<ConfigOptionString*>(printer_model_opt);
|
||||
if (!printer_model_str || !obj)
|
||||
if (!printer_model_str )
|
||||
continue;
|
||||
|
||||
// use printer_model as printer type
|
||||
|
|
@ -802,7 +804,30 @@ void AMSMaterialsSetting::Popup(wxString filament, wxString sn, wxString temp_mi
|
|||
else {
|
||||
filament_id_set.insert(filament_it->filament_id);
|
||||
// name matched
|
||||
filament_items.push_back(filament_it->alias);
|
||||
if (filament_it->is_system) {
|
||||
filament_items.push_back(filament_it->alias);
|
||||
FilamentInfos filament_infos;
|
||||
filament_infos.filament_id = filament_it->filament_id;
|
||||
filament_infos.setting_id = filament_it->setting_id;
|
||||
map_filament_items[filament_it->alias] = filament_infos;
|
||||
}
|
||||
else {
|
||||
char target = '@';
|
||||
size_t pos = filament_it->name.find(target);
|
||||
if (pos != std::string::npos) {
|
||||
std::string user_preset_alias = filament_it->name.substr(0, pos-1);
|
||||
wxString wx_user_preset_alias = wxString(user_preset_alias.c_str(), wxConvUTF8);
|
||||
user_preset_alias = wx_user_preset_alias.ToStdString();
|
||||
|
||||
filament_items.push_back(user_preset_alias);
|
||||
FilamentInfos filament_infos;
|
||||
filament_infos.filament_id = filament_it->filament_id;
|
||||
filament_infos.setting_id = filament_it->setting_id;
|
||||
map_filament_items[user_preset_alias] = filament_infos;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (filament_it->filament_id == ams_filament_id) {
|
||||
selection_idx = idx;
|
||||
|
||||
|
|
@ -853,7 +878,7 @@ void AMSMaterialsSetting::Popup(wxString filament, wxString sn, wxString temp_mi
|
|||
m_readonly_filament->Hide();
|
||||
}
|
||||
|
||||
if (obj->is_high_printer_type()) {
|
||||
if (obj->get_printer_series() == PrinterSeries::SERIES_X1) {
|
||||
m_title_pa_profile->Show();
|
||||
m_comboBox_cali_result->Show();
|
||||
m_input_k_val->Disable();
|
||||
|
|
@ -913,40 +938,44 @@ void AMSMaterialsSetting::on_select_filament(wxCommandEvent &evt)
|
|||
PresetBundle* preset_bundle = wxGetApp().preset_bundle;
|
||||
if (preset_bundle) {
|
||||
for (auto it = preset_bundle->filaments.begin(); it != preset_bundle->filaments.end(); it++) {
|
||||
if (!m_comboBox_filament->GetValue().IsEmpty() && it->alias.compare(m_comboBox_filament->GetValue().ToStdString()) == 0) {
|
||||
if (!m_comboBox_filament->GetValue().IsEmpty()) {
|
||||
auto filament_item = map_filament_items[m_comboBox_filament->GetValue().ToStdString()];
|
||||
std::string filament_id = filament_item.filament_id;
|
||||
if (it->filament_id.compare(filament_id) == 0) {
|
||||
|
||||
// ) if nozzle_temperature_range is found
|
||||
ConfigOption* opt_min = it->config.option("nozzle_temperature_range_low");
|
||||
if (opt_min) {
|
||||
ConfigOptionInts* opt_min_ints = dynamic_cast<ConfigOptionInts*>(opt_min);
|
||||
if (opt_min_ints) {
|
||||
wxString text_nozzle_temp_min = wxString::Format("%d", opt_min_ints->get_at(0));
|
||||
m_input_nozzle_min->GetTextCtrl()->SetValue(text_nozzle_temp_min);
|
||||
// ) if nozzle_temperature_range is found
|
||||
ConfigOption* opt_min = it->config.option("nozzle_temperature_range_low");
|
||||
if (opt_min) {
|
||||
ConfigOptionInts* opt_min_ints = dynamic_cast<ConfigOptionInts*>(opt_min);
|
||||
if (opt_min_ints) {
|
||||
wxString text_nozzle_temp_min = wxString::Format("%d", opt_min_ints->get_at(0));
|
||||
m_input_nozzle_min->GetTextCtrl()->SetValue(text_nozzle_temp_min);
|
||||
}
|
||||
}
|
||||
}
|
||||
ConfigOption* opt_max = it->config.option("nozzle_temperature_range_high");
|
||||
if (opt_max) {
|
||||
ConfigOptionInts* opt_max_ints = dynamic_cast<ConfigOptionInts*>(opt_max);
|
||||
if (opt_max_ints) {
|
||||
wxString text_nozzle_temp_max = wxString::Format("%d", opt_max_ints->get_at(0));
|
||||
m_input_nozzle_max->GetTextCtrl()->SetValue(text_nozzle_temp_max);
|
||||
ConfigOption* opt_max = it->config.option("nozzle_temperature_range_high");
|
||||
if (opt_max) {
|
||||
ConfigOptionInts* opt_max_ints = dynamic_cast<ConfigOptionInts*>(opt_max);
|
||||
if (opt_max_ints) {
|
||||
wxString text_nozzle_temp_max = wxString::Format("%d", opt_max_ints->get_at(0));
|
||||
m_input_nozzle_max->GetTextCtrl()->SetValue(text_nozzle_temp_max);
|
||||
}
|
||||
}
|
||||
}
|
||||
ConfigOption* opt_type = it->config.option("filament_type");
|
||||
bool found_filament_type = false;
|
||||
if (opt_type) {
|
||||
ConfigOptionStrings* opt_type_strs = dynamic_cast<ConfigOptionStrings*>(opt_type);
|
||||
if (opt_type_strs) {
|
||||
found_filament_type = true;
|
||||
//m_filament_type = opt_type_strs->get_at(0);
|
||||
std::string display_filament_type;
|
||||
m_filament_type = it->config.get_filament_type(display_filament_type);
|
||||
ConfigOption* opt_type = it->config.option("filament_type");
|
||||
bool found_filament_type = false;
|
||||
if (opt_type) {
|
||||
ConfigOptionStrings* opt_type_strs = dynamic_cast<ConfigOptionStrings*>(opt_type);
|
||||
if (opt_type_strs) {
|
||||
found_filament_type = true;
|
||||
//m_filament_type = opt_type_strs->get_at(0);
|
||||
std::string display_filament_type;
|
||||
m_filament_type = it->config.get_filament_type(display_filament_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found_filament_type)
|
||||
m_filament_type = "";
|
||||
if (!found_filament_type)
|
||||
m_filament_type = "";
|
||||
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -985,6 +1014,13 @@ void AMSMaterialsSetting::on_select_filament(wxCommandEvent &evt)
|
|||
|
||||
if (preset_bundle) {
|
||||
for (auto it = preset_bundle->filaments.begin(); it != preset_bundle->filaments.end(); it++) {
|
||||
auto itor = map_filament_items.find(m_comboBox_filament->GetValue().ToStdString());
|
||||
if ( itor != map_filament_items.end()) {
|
||||
ams_filament_id = itor->second.filament_id;
|
||||
ams_setting_id = itor->second.setting_id;
|
||||
break;
|
||||
}
|
||||
|
||||
if (it->alias.compare(m_comboBox_filament->GetValue().ToStdString()) == 0) {
|
||||
ams_filament_id = it->filament_id;
|
||||
ams_setting_id = it->setting_id;
|
||||
|
|
@ -997,7 +1033,7 @@ void AMSMaterialsSetting::on_select_filament(wxCommandEvent &evt)
|
|||
m_pa_profile_items.clear();
|
||||
m_comboBox_cali_result->SetValue(wxEmptyString);
|
||||
|
||||
if (this->obj->is_high_printer_type()) {
|
||||
if (obj->get_printer_series() == PrinterSeries::SERIES_X1) {
|
||||
m_input_k_val->GetTextCtrl()->SetValue(wxEmptyString);
|
||||
std::vector<PACalibResult> cali_history = this->obj->pa_calib_tab;
|
||||
for (auto cali_item : cali_history) {
|
||||
|
|
|
|||
|
|
@ -180,6 +180,12 @@ protected:
|
|||
#endif
|
||||
ComboBox * m_comboBox_cali_result;
|
||||
TextInput* m_readonly_filament;
|
||||
|
||||
struct FilamentInfos {
|
||||
std::string filament_id;
|
||||
std::string setting_id;
|
||||
};
|
||||
std::map<std::string, FilamentInfos> map_filament_items;
|
||||
};
|
||||
|
||||
wxDECLARE_EVENT(EVT_SELECTED_COLOR, wxCommandEvent);
|
||||
|
|
|
|||
|
|
@ -192,8 +192,8 @@ void AMSSetting::create()
|
|||
wxPanel* m_panel_img = new wxPanel(m_panel_body, wxID_ANY, wxDefaultPosition, wxDefaultSize);
|
||||
m_panel_img->SetBackgroundColour(AMS_SETTING_GREY200);
|
||||
wxBoxSizer *m_sizer_img = new wxBoxSizer(wxVERTICAL);
|
||||
ams_img = new wxStaticBitmap(m_panel_img, wxID_ANY, create_scaled_bitmap("ams_icon", nullptr, 126), wxDefaultPosition, wxDefaultSize);
|
||||
m_sizer_img->Add(ams_img, 0, wxALIGN_CENTER | wxTOP, 26);
|
||||
m_am_img = new wxStaticBitmap(m_panel_img, wxID_ANY, create_scaled_bitmap("ams_icon", nullptr, 126), wxDefaultPosition, wxDefaultSize);
|
||||
m_sizer_img->Add(m_am_img, 0, wxALIGN_CENTER | wxTOP, 26);
|
||||
m_sizer_img->Add(0, 0, 0, wxTOP, 18);
|
||||
m_panel_img->SetSizer(m_sizer_img);
|
||||
m_panel_img->Layout();
|
||||
|
|
@ -262,17 +262,9 @@ void AMSSetting::update_insert_material_read_mode(bool selected)
|
|||
Fit();
|
||||
}
|
||||
|
||||
void AMSSetting::update_image(std::string ams_type)
|
||||
void AMSSetting::update_ams_img(std::string ams_icon_str)
|
||||
{
|
||||
if (ams_type == m_current_ams_type) return;
|
||||
if (ams_type == "generic") {
|
||||
ams_img->SetBitmap(create_scaled_bitmap("monitor_upgrade_f1", nullptr, 126));
|
||||
}
|
||||
else {
|
||||
ams_img->SetBitmap(create_scaled_bitmap("ams_icon", nullptr, 126));
|
||||
}
|
||||
m_current_ams_type = ams_type;
|
||||
Layout();
|
||||
m_am_img->SetBitmap(create_scaled_bitmap(ams_icon_str, nullptr, 126));
|
||||
}
|
||||
|
||||
void AMSSetting::update_starting_read_mode(bool selected)
|
||||
|
|
@ -292,12 +284,24 @@ void AMSSetting::update_starting_read_mode(bool selected)
|
|||
|
||||
void AMSSetting::update_remain_mode(bool selected)
|
||||
{
|
||||
if (obj->is_support_update_remain) {
|
||||
m_checkbox_remain->Show();
|
||||
m_title_remain->Show();
|
||||
m_tip_remain_line1->Show();
|
||||
Layout();
|
||||
}
|
||||
else {
|
||||
m_checkbox_remain->Hide();
|
||||
m_title_remain->Hide();
|
||||
m_tip_remain_line1->Hide();
|
||||
Layout();
|
||||
}
|
||||
m_checkbox_remain->SetValue(selected);
|
||||
}
|
||||
|
||||
void AMSSetting::update_switch_filament(bool selected)
|
||||
{
|
||||
if (obj->is_function_supported(PrinterFunction::FUNC_AUTO_SWITCH_FILAMENT)) {
|
||||
if (obj->is_support_filament_backup) {
|
||||
m_checkbox_switch_filament->Show();
|
||||
m_title_switch_filament->Show();
|
||||
m_tip_switch_filament_line1->Show();
|
||||
|
|
|
|||
|
|
@ -27,8 +27,8 @@ public:
|
|||
~AMSSetting();
|
||||
void create();
|
||||
|
||||
void update_insert_material_read_mode(bool selected);
|
||||
void update_image(std::string ams_type);
|
||||
void update_insert_material_read_mode(bool selected);
|
||||
void update_ams_img(std::string ams_icon_str);
|
||||
void update_starting_read_mode(bool selected);
|
||||
void update_remain_mode(bool selected);
|
||||
void update_switch_filament(bool selected);
|
||||
|
|
@ -41,13 +41,13 @@ public:
|
|||
wxStaticText *append_text(wxString text);
|
||||
MachineObject *obj{nullptr};
|
||||
bool ams_support_remain{false};
|
||||
wxStaticBitmap* m_am_img;
|
||||
int ams_id { 0 };
|
||||
|
||||
protected:
|
||||
void on_dpi_changed(const wxRect &suggested_rect) override;
|
||||
|
||||
protected:
|
||||
std::string m_current_ams_type;
|
||||
wxPanel * m_panel_body;
|
||||
CheckBox * m_checkbox_Insert_material_auto_read;
|
||||
wxStaticText *m_title_Insert_material_auto_read;
|
||||
|
|
@ -70,7 +70,7 @@ protected:
|
|||
|
||||
wxStaticText *m_tip_ams_img;
|
||||
Button * m_button_auto_demarcate;
|
||||
wxStaticBitmap* ams_img;
|
||||
|
||||
wxBoxSizer *m_sizer_Insert_material_tip_inline;
|
||||
wxBoxSizer *m_sizer_starting_tip_inline;
|
||||
wxBoxSizer *m_sizer_remain_inline;
|
||||
|
|
|
|||
|
|
@ -186,7 +186,7 @@ void MaterialItem::doRender(wxDC &dc)
|
|||
auto mcolor = m_material_coloul;
|
||||
auto acolor = m_ams_coloul;
|
||||
|
||||
if (mcolor.Alpha() == 0) {
|
||||
if (mcolor.Alpha() == 0 || acolor.Alpha() == 0) {
|
||||
dc.DrawBitmap(m_transparent_mitem.bmp(), FromDIP(1), FromDIP(1));
|
||||
}
|
||||
|
||||
|
|
@ -1332,7 +1332,7 @@ void AmsReplaceMaterialDialog::update_machine_obj(MachineObject* obj)
|
|||
m_scrollview_groups->SetMinSize(wxSize(FromDIP(400), height));
|
||||
m_scrollview_groups->SetMaxSize(wxSize(FromDIP(400), height));
|
||||
} else {
|
||||
if (!obj->is_function_supported(PrinterFunction::FUNC_FILAMENT_BACKUP)) {
|
||||
if (!obj->is_support_filament_backup) {
|
||||
label_txt->SetLabel(_L("The printer does not currently support auto refill."));
|
||||
}
|
||||
else if (!obj->ams_auto_switch_filament_flag) {
|
||||
|
|
@ -1340,11 +1340,12 @@ void AmsReplaceMaterialDialog::update_machine_obj(MachineObject* obj)
|
|||
}
|
||||
else {
|
||||
label_txt->SetLabelText(_L("If there are two identical filaments in AMS, AMS filament backup will be enabled. \n(Currently supporting automatic supply of consumables with the same brand, material type, and color)"));
|
||||
}
|
||||
}
|
||||
|
||||
label_txt->SetMinSize(wxSize(FromDIP(380), -1));
|
||||
label_txt->SetMaxSize(wxSize(FromDIP(380), -1));
|
||||
label_txt->Wrap(FromDIP(380));
|
||||
|
||||
}
|
||||
|
||||
m_scrollview_groups->Layout();
|
||||
|
|
@ -1548,10 +1549,13 @@ void AmsRMGroup::doRender(wxDC& dc)
|
|||
dc.SetFont(::Label::Body_12);
|
||||
auto text_size = dc.GetTextExtent(tray_name);
|
||||
dc.SetTextForeground(tray_color.GetLuminance() < 0.6 ? *wxWHITE : wxColour(0x262E30));
|
||||
if (tray_color.Alpha() == 0) {dc.SetTextForeground(wxColour(0x262E30));}
|
||||
|
||||
dc.DrawText(tray_name, x_center - text_size.x / 2, size.y - y_center - text_size.y / 2);
|
||||
|
||||
//draw split line
|
||||
dc.SetPen(wxPen(*wxWHITE, 2));
|
||||
if (tray_color.Alpha() == 0) {dc.SetPen(wxPen(wxColour(0xCECECE), 2));}
|
||||
dc.SetBrush(*wxTRANSPARENT_BRUSH);
|
||||
auto pos_sp_start = CalculateEndpoint(wxPoint(x, y), (360 - startAngle), size.x / 2 - FromDIP(3));
|
||||
dc.DrawLine(wxPoint(x, y), pos_sp_start);
|
||||
|
|
|
|||
|
|
@ -577,7 +577,7 @@ void BBLTopbar::OnFileToolItem(wxAuiToolBarEvent& evt)
|
|||
tb->SetToolSticky(evt.GetId(), true);
|
||||
|
||||
if (!m_skip_popup_file_menu) {
|
||||
this->PopupMenu(m_file_menu, wxPoint(FromDIP(1), this->GetSize().GetHeight() - 2));
|
||||
GetParent()->PopupMenu(m_file_menu, wxPoint(FromDIP(1), this->GetSize().GetHeight() - 2));
|
||||
}
|
||||
else {
|
||||
m_skip_popup_file_menu = false;
|
||||
|
|
@ -594,7 +594,7 @@ void BBLTopbar::OnDropdownToolItem(wxAuiToolBarEvent& evt)
|
|||
tb->SetToolSticky(evt.GetId(), true);
|
||||
|
||||
if (!m_skip_popup_dropdown_menu) {
|
||||
PopupMenu(&m_top_menu, wxPoint(FromDIP(1), this->GetSize().GetHeight() - 2));
|
||||
GetParent()->PopupMenu(&m_top_menu, wxPoint(FromDIP(1), this->GetSize().GetHeight() - 2));
|
||||
}
|
||||
else {
|
||||
m_skip_popup_dropdown_menu = false;
|
||||
|
|
@ -612,7 +612,7 @@ void BBLTopbar::OnCalibToolItem(wxAuiToolBarEvent &evt)
|
|||
|
||||
if (!m_skip_popup_calib_menu) {
|
||||
auto rec = this->GetToolRect(ID_CALIB);
|
||||
PopupMenu(&m_calib_menu, wxPoint(rec.GetLeft(), this->GetSize().GetHeight() - 2));
|
||||
GetParent()->PopupMenu(&m_calib_menu, wxPoint(rec.GetLeft(), this->GetSize().GetHeight() - 2));
|
||||
} else {
|
||||
m_skip_popup_calib_menu = false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,6 +59,8 @@ wxString get_fail_reason(int code)
|
|||
SetDoubleBuffered(true);
|
||||
#endif //__WINDOWS__
|
||||
|
||||
m_tocken.reset(new int(0));
|
||||
|
||||
std::string icon_path = (boost::format("%1%/images/OrcaSlicerTitle.ico") % resources_dir()).str();
|
||||
SetIcon(wxIcon(encode_path(icon_path.c_str()), wxBITMAP_TYPE_ICO));
|
||||
|
||||
|
|
@ -296,8 +298,7 @@ wxString get_fail_reason(int code)
|
|||
wxBoxSizer* m_sizer_bind_failed_info = new wxBoxSizer(wxVERTICAL);
|
||||
m_sw_bind_failed_info->SetSizer( m_sizer_bind_failed_info );
|
||||
|
||||
m_link_network_state = new Label(m_sw_bind_failed_info, _L("Check the status of current system services"));
|
||||
m_link_network_state->SetForegroundColour(0x009688);
|
||||
m_link_network_state = new wxHyperlinkCtrl(m_sw_bind_failed_info, wxID_ANY,_L("Check the status of current system services"),"");
|
||||
m_link_network_state->SetFont(::Label::Body_12);
|
||||
m_link_network_state->Bind(wxEVT_LEFT_DOWN, [this](auto& e) {wxGetApp().link_to_network_check(); });
|
||||
m_link_network_state->Bind(wxEVT_ENTER_WINDOW, [this](auto& e) {m_link_network_state->SetCursor(wxCURSOR_HAND); });
|
||||
|
|
@ -433,26 +434,6 @@ wxString get_fail_reason(int code)
|
|||
|
||||
Bind(wxEVT_SHOW, &BindMachineDialog::on_show, this);
|
||||
Bind(wxEVT_CLOSE_WINDOW, &BindMachineDialog::on_close, this);
|
||||
Bind(wxEVT_WEBREQUEST_STATE, [this](wxWebRequestEvent& evt) {
|
||||
switch (evt.GetState()) {
|
||||
// Request completed
|
||||
case wxWebRequest::State_Completed: {
|
||||
wxImage avatar_stream = *evt.GetResponse().GetStream();
|
||||
if (avatar_stream.IsOk()) {
|
||||
avatar_stream.Rescale(FromDIP(60), FromDIP(60));
|
||||
auto bitmap = new wxBitmap(avatar_stream);
|
||||
//bitmap->SetSize(wxSize(FromDIP(60), FromDIP(60)));
|
||||
m_avatar->SetBitmap(*bitmap);
|
||||
Layout();
|
||||
}
|
||||
break;
|
||||
}
|
||||
// Request failed
|
||||
case wxWebRequest::State_Failed: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
m_button_bind->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(BindMachineDialog::on_bind_printer), NULL, this);
|
||||
m_button_cancel->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(BindMachineDialog::on_cancel), NULL, this);
|
||||
|
|
@ -536,10 +517,6 @@ wxString get_fail_reason(int code)
|
|||
m_bind_job->cancel();
|
||||
m_bind_job->join();
|
||||
}
|
||||
|
||||
if (web_request.IsOk()) {
|
||||
web_request.Cancel();
|
||||
}
|
||||
}
|
||||
|
||||
void BindMachineDialog::on_close(wxCloseEvent &event)
|
||||
|
|
@ -597,7 +574,7 @@ wxString get_fail_reason(int code)
|
|||
m_simplebook->SetSelection(0);
|
||||
m_bind_job = std::make_shared<BindJob>(m_status_bar, wxGetApp().plater(), m_machine_info->dev_id, m_machine_info->dev_ip, m_machine_info->bind_sec_link);
|
||||
|
||||
if (m_machine_info && (m_machine_info->printer_type == "BL-P001" || m_machine_info->printer_type == "BL-P002")) {
|
||||
if (m_machine_info && (m_machine_info->get_printer_series() == PrinterSeries::SERIES_X1)) {
|
||||
m_bind_job->set_improved(false);
|
||||
}
|
||||
else {
|
||||
|
|
@ -617,7 +594,7 @@ void BindMachineDialog::on_dpi_changed(const wxRect &suggested_rect)
|
|||
void BindMachineDialog::update_machine_info(MachineObject* info)
|
||||
{
|
||||
m_machine_info = info;
|
||||
if (m_machine_info && (m_machine_info->printer_type == "BL-P001" || m_machine_info->printer_type == "BL-P002")) {
|
||||
if (m_machine_info && (m_machine_info->get_printer_series() == PrinterSeries::SERIES_X1)) {
|
||||
m_button_bind->Enable(true);
|
||||
m_panel_agreement->Hide();
|
||||
}
|
||||
|
|
@ -650,14 +627,30 @@ void BindMachineDialog::on_show(wxShowEvent &event)
|
|||
if (wxGetApp().is_user_login()) {
|
||||
wxString username_text = from_u8(wxGetApp().getAgent()->get_user_nickanme());
|
||||
m_user_name->SetLabelText(username_text);
|
||||
web_request = wxWebSession::GetDefault().CreateRequest(this, wxGetApp().getAgent()->get_user_avatar());
|
||||
if (!web_request.IsOk()) {
|
||||
// todo request fail
|
||||
}
|
||||
// Start the request
|
||||
web_request.Start();
|
||||
}
|
||||
|
||||
std::string avatar_url = wxGetApp().getAgent()->get_user_avatar();
|
||||
Slic3r::Http http = Slic3r::Http::get(avatar_url);
|
||||
std::string suffix = avatar_url.substr(avatar_url.find_last_of(".") + 1);
|
||||
http.header("accept", "image/" + suffix)
|
||||
.on_complete([this, time = std::weak_ptr<int>(m_tocken)](std::string body, unsigned int status) {
|
||||
if (time.expired()) return;
|
||||
wxMemoryInputStream stream(body.data(), body.size());
|
||||
wxImage avatar_image;
|
||||
if (avatar_image.LoadFile(stream, wxBITMAP_TYPE_ANY)) {
|
||||
if (avatar_image.IsOk() && m_avatar) {
|
||||
avatar_image.Rescale(this->FromDIP(60), this->FromDIP(60));
|
||||
CallAfter([this, avatar_image]() {
|
||||
auto bitmap = new wxBitmap(avatar_image);
|
||||
m_avatar->SetBitmap(*bitmap);
|
||||
Layout();
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
.on_error([this](std::string body, std::string error, unsigned status) {
|
||||
//BOOST_LOG_TRIVIAL(info) << "load oss picture failed, oss path: " << oss_path << " status:" << status << " error:" << error;
|
||||
}).perform();
|
||||
}
|
||||
Layout();
|
||||
event.Skip();
|
||||
}
|
||||
|
|
@ -667,7 +660,8 @@ void BindMachineDialog::on_show(wxShowEvent &event)
|
|||
UnBindMachineDialog::UnBindMachineDialog(Plater *plater /*= nullptr*/)
|
||||
: DPIDialog(static_cast<wxWindow *>(wxGetApp().mainframe), wxID_ANY, _L("Log out printer"), wxDefaultPosition, wxDefaultSize, wxCAPTION)
|
||||
{
|
||||
std::string icon_path = (boost::format("%1%/images/OrcaSlicerTitle.ico") % resources_dir()).str();
|
||||
m_tocken.reset(new int(0));
|
||||
std::string icon_path = (boost::format("%1%/images/OrcaSlicerTitle.ico") % resources_dir()).str();
|
||||
SetIcon(wxIcon(encode_path(icon_path.c_str()), wxBITMAP_TYPE_ICO));
|
||||
|
||||
SetBackgroundColour(*wxWHITE);
|
||||
|
|
@ -779,33 +773,12 @@ UnBindMachineDialog::UnBindMachineDialog(Plater *plater /*= nullptr*/)
|
|||
m_button_unbind->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(UnBindMachineDialog::on_unbind_printer), NULL, this);
|
||||
m_button_cancel->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(UnBindMachineDialog::on_cancel), NULL, this);
|
||||
|
||||
Bind(wxEVT_WEBREQUEST_STATE, [this](wxWebRequestEvent& evt) {
|
||||
switch (evt.GetState()) {
|
||||
// Request completed
|
||||
case wxWebRequest::State_Completed: {
|
||||
wxImage avatar_stream = *evt.GetResponse().GetStream();
|
||||
if (avatar_stream.IsOk()) {
|
||||
avatar_stream.Rescale(FromDIP(60), FromDIP(60));
|
||||
auto bitmap = new wxBitmap(avatar_stream);
|
||||
//bitmap->SetSize(wxSize(FromDIP(60), FromDIP(60)));
|
||||
m_avatar->SetBitmap(*bitmap);
|
||||
Layout();
|
||||
}
|
||||
break;
|
||||
}
|
||||
// Request failed
|
||||
case wxWebRequest::State_Failed: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
wxGetApp().UpdateDlgDarkUI(this);
|
||||
}
|
||||
|
||||
UnBindMachineDialog::~UnBindMachineDialog()
|
||||
{
|
||||
web_request.Cancel();
|
||||
m_button_unbind->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(UnBindMachineDialog::on_unbind_printer), NULL, this);
|
||||
m_button_cancel->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(UnBindMachineDialog::on_cancel), NULL, this);
|
||||
}
|
||||
|
|
@ -874,12 +847,30 @@ void UnBindMachineDialog::on_show(wxShowEvent &event)
|
|||
if (wxGetApp().is_user_login()) {
|
||||
wxString username_text = from_u8(wxGetApp().getAgent()->get_user_name());
|
||||
m_user_name->SetLabelText(username_text);
|
||||
wxString avatar_url = wxGetApp().getAgent()->get_user_avatar();
|
||||
web_request = wxWebSession::GetDefault().CreateRequest(this, avatar_url);
|
||||
if (!web_request.IsOk()) {
|
||||
// todo request fail
|
||||
}
|
||||
web_request.Start();
|
||||
|
||||
std::string avatar_url = wxGetApp().getAgent()->get_user_avatar();
|
||||
Slic3r::Http http = Slic3r::Http::get(avatar_url);
|
||||
std::string suffix = avatar_url.substr(avatar_url.find_last_of(".") + 1);
|
||||
http.header("accept", "image/" + suffix)
|
||||
.on_complete([this, time = std::weak_ptr<int>(m_tocken)](std::string body, unsigned int status) {
|
||||
if (time.expired()) return;
|
||||
wxMemoryInputStream stream(body.data(), body.size());
|
||||
wxImage avatar_image;
|
||||
if (avatar_image.LoadFile(stream, wxBITMAP_TYPE_ANY)) {
|
||||
if (avatar_image.IsOk() && m_avatar) {
|
||||
avatar_image.Rescale(this->FromDIP(60), this->FromDIP(60));
|
||||
CallAfter([this, avatar_image]() {
|
||||
auto bitmap = new wxBitmap(avatar_image);
|
||||
m_avatar->SetBitmap(*bitmap);
|
||||
Layout();
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
.on_error([this](std::string body, std::string error, unsigned status) {
|
||||
//BOOST_LOG_TRIVIAL(info) << "load oss picture failed, oss path: " << oss_path << " status:" << status << " error:" << error;
|
||||
}).perform();
|
||||
|
||||
}
|
||||
|
||||
Layout();
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#include <wx/dialog.h>
|
||||
#include <curl/curl.h>
|
||||
#include <wx/webrequest.h>
|
||||
#include <wx/hyperlink.h>
|
||||
#include "wxExtensions.hpp"
|
||||
#include "Plater.hpp"
|
||||
#include "Widgets/StepCtrl.hpp"
|
||||
|
|
@ -61,19 +62,19 @@ private:
|
|||
wxStaticBitmap *m_static_bitmap_show_error;
|
||||
wxBitmap m_bitmap_show_error_close;
|
||||
wxBitmap m_bitmap_show_error_open;
|
||||
wxWebRequest web_request;
|
||||
wxScrolledWindow* m_sw_bind_failed_info;
|
||||
Label* m_bind_failed_info;
|
||||
Label* m_st_txt_error_code{ nullptr };
|
||||
Label* m_st_txt_error_desc{ nullptr };
|
||||
Label* m_st_txt_extra_info{ nullptr };
|
||||
Label* m_link_network_state{ nullptr };
|
||||
wxHyperlinkCtrl* m_link_network_state{ nullptr };
|
||||
wxString m_result_info;
|
||||
wxString m_result_extra;
|
||||
bool m_show_error_info_state = true;
|
||||
bool m_allow_privacy{false};
|
||||
bool m_allow_notice{false};
|
||||
int m_result_code;
|
||||
std::shared_ptr<int> m_tocken;
|
||||
|
||||
MachineObject * m_machine_info{nullptr};
|
||||
std::shared_ptr<BindJob> m_bind_job;
|
||||
|
|
@ -108,7 +109,7 @@ protected:
|
|||
MachineObject *m_machine_info{nullptr};
|
||||
wxStaticBitmap *m_avatar;
|
||||
wxStaticBitmap *m_printer_img;
|
||||
wxWebRequest web_request;
|
||||
std::shared_ptr<int> m_tocken;
|
||||
|
||||
public:
|
||||
UnBindMachineDialog(Plater *plater = nullptr);
|
||||
|
|
|
|||
|
|
@ -316,13 +316,13 @@ wxBitmap* BitmapCache::load_svg(const std::string &bitmap_name, unsigned target_
|
|||
+ (grayscale ? "-gs" : "")
|
||||
+ new_color;
|
||||
|
||||
/*auto it = m_map.find(bitmap_key);
|
||||
auto it = m_map.find(bitmap_key);
|
||||
if (it != m_map.end())
|
||||
return it->second;*/
|
||||
return it->second;
|
||||
|
||||
// map of color replaces
|
||||
std::map<std::string, std::string> replaces;
|
||||
replaces["\"#0x00AE42\""] = "\"#009688\"";
|
||||
replaces["\"#0x00AE42\""] = "\"#009688\"";
|
||||
replaces["\"#00FF00\""] = "\"#52c7b8\"";
|
||||
if (dark_mode) {
|
||||
replaces["\"#262E30\""] = "\"#EFEFF0\"";
|
||||
|
|
@ -333,7 +333,7 @@ wxBitmap* BitmapCache::load_svg(const std::string &bitmap_name, unsigned target_
|
|||
replaces["\"#6B6B6B\""] = "\"#818182\"";
|
||||
replaces["\"#909090\""] = "\"#FFFFFF\"";
|
||||
replaces["\"#00FF00\""] = "\"#FF0000\"";
|
||||
replaces["\"#009688\""] = "\"#00675b\"";
|
||||
replaces["\"#009688\""] = "\"#00675b\"";
|
||||
}
|
||||
//if (!new_color.empty())
|
||||
// replaces["\"#ED6B21\""] = "\"" + new_color + "\"";
|
||||
|
|
@ -431,5 +431,46 @@ wxBitmap BitmapCache::mksolid(size_t width, size_t height, unsigned char r, unsi
|
|||
return wxImage_to_wxBitmap_with_alpha(std::move(image), scale);
|
||||
}
|
||||
|
||||
bool BitmapCache::parse_color(const std::string& scolor, unsigned char* rgb_out)
|
||||
{
|
||||
if (scolor.size() == 9) {
|
||||
unsigned char rgba[4];
|
||||
parse_color4(scolor, rgba);
|
||||
rgb_out[0] = rgba[0];
|
||||
rgb_out[1] = rgba[1];
|
||||
rgb_out[2] = rgba[2];
|
||||
return true;
|
||||
}
|
||||
rgb_out[0] = rgb_out[1] = rgb_out[2] = 0;
|
||||
if (scolor.size() != 7 || scolor.front() != '#')
|
||||
return false;
|
||||
const char* c = scolor.data() + 1;
|
||||
for (size_t i = 0; i < 3; ++i) {
|
||||
int digit1 = hex_digit_to_int(*c++);
|
||||
int digit2 = hex_digit_to_int(*c++);
|
||||
if (digit1 == -1 || digit2 == -1)
|
||||
return false;
|
||||
rgb_out[i] = (unsigned char)(digit1 * 16 + digit2);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BitmapCache::parse_color4(const std::string& scolor, unsigned char* rgba_out)
|
||||
{
|
||||
rgba_out[0] = rgba_out[1] = rgba_out[2] = 0; rgba_out[3] = 255;
|
||||
if ((scolor.size() != 7 && scolor.size() != 9) || scolor.front() != '#')
|
||||
return false;
|
||||
const char* c = scolor.data() + 1;
|
||||
for (size_t i = 0; i < scolor.size() / 2; ++i) {
|
||||
int digit1 = hex_digit_to_int(*c++);
|
||||
int digit2 = hex_digit_to_int(*c++);
|
||||
if (digit1 == -1 || digit2 == -1)
|
||||
return false;
|
||||
rgba_out[i] = (unsigned char)(digit1 * 16 + digit2);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
|
|
|||
|
|
@ -12,8 +12,7 @@
|
|||
#include "libslic3r/Color.hpp"
|
||||
struct NSVGimage;
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
namespace Slic3r { namespace GUI {
|
||||
|
||||
class BitmapCache
|
||||
{
|
||||
|
|
@ -46,9 +45,13 @@ public:
|
|||
wxBitmap* load_svg(const std::string &bitmap_key, unsigned width = 0, unsigned height = 0, const bool grayscale = false, const bool dark_mode = false, const std::string& new_color = "", const float scale_in_center = 0.f);
|
||||
|
||||
wxBitmap mksolid(size_t width, size_t height, unsigned char r, unsigned char g, unsigned char b, unsigned char transparency, bool suppress_scaling = false, size_t border_width = 0, bool dark_mode = false);
|
||||
wxBitmap mksolid(size_t width, size_t height, const unsigned char rgb[3], bool suppress_scaling = false, size_t border_width = 0, bool dark_mode = false) { return mksolid(width, height, rgb[0], rgb[1], rgb[2], wxALPHA_OPAQUE, suppress_scaling, border_width, dark_mode); }
|
||||
wxBitmap mksolid(size_t width, size_t height, const ColorRGB& rgb, bool suppress_scaling = false, size_t border_width = 0, bool dark_mode = false) { return mksolid(width, height, rgb.r_uchar(), rgb.g_uchar(), rgb.b_uchar(), wxALPHA_OPAQUE, suppress_scaling, border_width, dark_mode); }
|
||||
wxBitmap mkclear(size_t width, size_t height) { return mksolid(width, height, 0, 0, 0, wxALPHA_TRANSPARENT); }
|
||||
|
||||
static bool parse_color(const std::string& scolor, unsigned char* rgb_out);
|
||||
static bool parse_color4(const std::string& scolor, unsigned char* rgba_out);
|
||||
|
||||
private:
|
||||
std::map<std::string, wxBitmap*> m_map;
|
||||
double m_gs = 0.2; // value, used for image.ConvertToGreyscale(m_gs, m_gs, m_gs)
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ namespace GUI {
|
|||
#define HISTORY_WINDOW_SIZE wxSize(FromDIP(700), FromDIP(600))
|
||||
#define EDIT_HISTORY_DIALOG_INPUT_SIZE wxSize(FromDIP(160), FromDIP(24))
|
||||
#define HISTORY_WINDOW_ITEMS_COUNT 5
|
||||
static const wxString k_tips = "Please input a valid value (K in 0~0.3)";
|
||||
|
||||
static wxString get_preset_name_by_filament_id(std::string filament_id)
|
||||
{
|
||||
|
|
@ -351,18 +352,10 @@ EditCalibrationHistoryDialog::EditCalibrationHistoryDialog(wxWindow* parent, con
|
|||
flex_sizer->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_SPECIFIED);
|
||||
|
||||
Label* name_title = new Label(top_panel, _L("Name"));
|
||||
TextInput* name_value = new TextInput(top_panel, from_u8(m_new_result.name), "", "", wxDefaultPosition, EDIT_HISTORY_DIALOG_INPUT_SIZE, wxTE_PROCESS_ENTER);
|
||||
name_value->GetTextCtrl()->Bind(wxEVT_TEXT_ENTER, [this, name_value](auto& e) {
|
||||
if (!name_value->GetTextCtrl()->GetValue().IsEmpty())
|
||||
m_new_result.name = name_value->GetTextCtrl()->GetValue().ToUTF8().data();
|
||||
});
|
||||
name_value->GetTextCtrl()->Bind(wxEVT_KILL_FOCUS, [this, name_value](auto& e) {
|
||||
if (!name_value->GetTextCtrl()->GetValue().IsEmpty())
|
||||
m_new_result.name = name_value->GetTextCtrl()->GetValue().ToUTF8().data();
|
||||
e.Skip();
|
||||
});
|
||||
m_name_value = new TextInput(top_panel, from_u8(m_new_result.name), "", "", wxDefaultPosition, EDIT_HISTORY_DIALOG_INPUT_SIZE, wxTE_PROCESS_ENTER);
|
||||
|
||||
flex_sizer->Add(name_title);
|
||||
flex_sizer->Add(name_value);
|
||||
flex_sizer->Add(m_name_value);
|
||||
|
||||
Label* preset_name_title = new Label(top_panel, _L("Filament"));
|
||||
wxString preset_name = get_preset_name_by_filament_id(result.filament_id);
|
||||
|
|
@ -372,30 +365,9 @@ EditCalibrationHistoryDialog::EditCalibrationHistoryDialog(wxWindow* parent, con
|
|||
|
||||
Label* k_title = new Label(top_panel, _L("Factor K"));
|
||||
auto k_str = wxString::Format("%.3f", m_new_result.k_value);
|
||||
TextInput* k_value = new TextInput(top_panel, k_str, "", "", wxDefaultPosition, EDIT_HISTORY_DIALOG_INPUT_SIZE, wxTE_PROCESS_ENTER);
|
||||
k_value->GetTextCtrl()->Bind(wxEVT_TEXT_ENTER, [this, k_value](auto& e) {
|
||||
float k = 0.0f;
|
||||
if (!CalibUtils::validate_input_k_value(k_value->GetTextCtrl()->GetValue(), &k)) {
|
||||
MessageDialog msg_dlg(nullptr, _L("Please input a valid value (K in 0~0.5)"), wxEmptyString, wxICON_WARNING | wxOK);
|
||||
msg_dlg.ShowModal();
|
||||
}
|
||||
wxString k_str = wxString::Format("%.3f", k);
|
||||
k_value->GetTextCtrl()->SetValue(k_str);
|
||||
m_new_result.k_value = k;
|
||||
});
|
||||
k_value->GetTextCtrl()->Bind(wxEVT_KILL_FOCUS, [this, k_value](auto& e) {
|
||||
float k = 0.0f;
|
||||
if (!CalibUtils::validate_input_k_value(k_value->GetTextCtrl()->GetValue(), &k)) {
|
||||
MessageDialog msg_dlg(nullptr, _L("Please input a valid value (K in 0~0.5)"), wxEmptyString, wxICON_WARNING | wxOK);
|
||||
msg_dlg.ShowModal();
|
||||
}
|
||||
wxString k_str = wxString::Format("%.3f", k);
|
||||
k_value->GetTextCtrl()->SetValue(k_str);
|
||||
m_new_result.k_value = k;
|
||||
e.Skip();
|
||||
});
|
||||
m_k_value = new TextInput(top_panel, k_str, "", "", wxDefaultPosition, EDIT_HISTORY_DIALOG_INPUT_SIZE, wxTE_PROCESS_ENTER);
|
||||
flex_sizer->Add(k_title);
|
||||
flex_sizer->Add(k_value);
|
||||
flex_sizer->Add(m_k_value);
|
||||
|
||||
// Hide:
|
||||
//Label* n_title = new Label(top_panel, _L("Factor N"));
|
||||
|
|
@ -449,6 +421,27 @@ PACalibResult EditCalibrationHistoryDialog::get_result() {
|
|||
}
|
||||
|
||||
void EditCalibrationHistoryDialog::on_save(wxCommandEvent& event) {
|
||||
wxString name = m_name_value->GetTextCtrl()->GetValue();
|
||||
if (name.IsEmpty())
|
||||
return;
|
||||
if (name.Length() > 40) {
|
||||
MessageDialog msg_dlg(nullptr, _L("The name cannot exceed 40 characters."), wxEmptyString, wxICON_WARNING | wxOK);
|
||||
msg_dlg.ShowModal();
|
||||
return;
|
||||
}
|
||||
m_new_result.name = m_name_value->GetTextCtrl()->GetValue().ToUTF8().data();
|
||||
|
||||
float k = 0.0f;
|
||||
if (!CalibUtils::validate_input_k_value(m_k_value->GetTextCtrl()->GetValue(), &k)) {
|
||||
MessageDialog msg_dlg(nullptr, _L(k_tips), wxEmptyString, wxICON_WARNING | wxOK);
|
||||
msg_dlg.ShowModal();
|
||||
return;
|
||||
}
|
||||
wxString k_str = wxString::Format("%.3f", k);
|
||||
m_k_value->GetTextCtrl()->SetValue(k_str);
|
||||
m_new_result.k_value = k;
|
||||
|
||||
|
||||
EndModal(wxID_OK);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -50,6 +50,9 @@ protected:
|
|||
|
||||
protected:
|
||||
PACalibResult m_new_result;
|
||||
|
||||
TextInput* m_name_value{ nullptr };
|
||||
TextInput* m_k_value{ nullptr };
|
||||
};
|
||||
|
||||
} // namespace GUI
|
||||
|
|
|
|||
|
|
@ -215,36 +215,27 @@ wxWindow* CalibrationDialog::create_check_option(wxString title, wxWindow* paren
|
|||
void CalibrationDialog::update_cali(MachineObject *obj)
|
||||
{
|
||||
if (!obj) return;
|
||||
if (obj->is_function_supported(PrinterFunction::FUNC_AI_MONITORING)
|
||||
&& obj->is_function_supported(PrinterFunction::FUNC_LIDAR_CALIBRATION)) {
|
||||
if (obj->is_support_ai_monitoring && obj->is_support_lidar_calibration) {
|
||||
select_xcam_cali->Show();
|
||||
} else {
|
||||
select_xcam_cali->Hide();
|
||||
m_checkbox_list["xcam_cali"]->SetValue(false);
|
||||
}
|
||||
|
||||
if(obj->is_function_supported(PrinterFunction::FUNC_AUTO_LEVELING)){
|
||||
if(obj->is_support_auto_leveling){
|
||||
select_bed_leveling->Show();
|
||||
}else{
|
||||
select_bed_leveling->Hide();
|
||||
m_checkbox_list["bed_leveling"]->SetValue(false);
|
||||
}
|
||||
|
||||
if (obj->is_function_supported(PrinterFunction::FUNC_MOTOR_NOISE_CALI)) {
|
||||
if (obj->is_support_motor_noise_cali) {
|
||||
select_motor_noise->Show();
|
||||
} else {
|
||||
select_motor_noise->Hide();
|
||||
m_checkbox_list["motor_noise"]->SetValue(false);
|
||||
}
|
||||
|
||||
if (!m_checkbox_list["vibration"]->GetValue() && !m_checkbox_list["bed_leveling"]->GetValue() && !m_checkbox_list["xcam_cali"]->GetValue() &&
|
||||
!m_checkbox_list["motor_noise"]->GetValue()) {
|
||||
m_calibration_btn->Disable();
|
||||
m_calibration_btn->SetLabel(_L("No step selected"));
|
||||
return ;
|
||||
} else {
|
||||
m_calibration_btn->Enable();
|
||||
}
|
||||
|
||||
if (obj->is_calibration_running() || obj->is_calibration_done()) {
|
||||
if (obj->is_calibration_done()) {
|
||||
|
|
@ -282,6 +273,14 @@ void CalibrationDialog::update_cali(MachineObject *obj)
|
|||
m_calibration_flow->DeleteAllItems();
|
||||
m_calibration_btn->SetLabel(_L("Start Calibration"));
|
||||
}
|
||||
if (!obj->is_calibration_running() && !m_checkbox_list["vibration"]->GetValue() && !m_checkbox_list["bed_leveling"]->GetValue() &&
|
||||
!m_checkbox_list["xcam_cali"]->GetValue() && !m_checkbox_list["motor_noise"]->GetValue()) {
|
||||
m_calibration_btn->Disable();
|
||||
m_calibration_btn->SetLabel(_L("No step selected"));
|
||||
}
|
||||
else if(!obj->is_calibration_running()){
|
||||
m_calibration_btn->Enable();
|
||||
}
|
||||
}
|
||||
|
||||
bool CalibrationDialog::is_stage_list_info_changed(MachineObject *obj)
|
||||
|
|
|
|||
|
|
@ -242,21 +242,26 @@ void SelectMObjectPopup::Popup(wxWindow* WXUNUSED(focus))
|
|||
|
||||
if (wxGetApp().is_user_login()) {
|
||||
if (!get_print_info_thread) {
|
||||
get_print_info_thread = new boost::thread(Slic3r::create_thread([&] {
|
||||
get_print_info_thread = new boost::thread(Slic3r::create_thread([this, token = std::weak_ptr(m_token)] {
|
||||
NetworkAgent* agent = wxGetApp().getAgent();
|
||||
unsigned int http_code;
|
||||
std::string body;
|
||||
int result = agent->get_user_print_info(&http_code, &body);
|
||||
if (result == 0) {
|
||||
m_print_info = body;
|
||||
}
|
||||
else {
|
||||
m_print_info = "";
|
||||
}
|
||||
wxCommandEvent event(EVT_UPDATE_USER_MLIST);
|
||||
event.SetEventObject(this);
|
||||
wxPostEvent(this, event);
|
||||
}));
|
||||
|
||||
wxGetApp().CallAfter([token, this, result, body]() {
|
||||
if (token.expired()) {return;}
|
||||
if (result == 0) {
|
||||
m_print_info = body;
|
||||
}
|
||||
else {
|
||||
m_print_info = "";
|
||||
}
|
||||
|
||||
wxCommandEvent event(EVT_UPDATE_USER_MLIST);
|
||||
event.SetEventObject(this);
|
||||
wxPostEvent(this, event);
|
||||
});
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -510,10 +515,15 @@ void CalibrationPanel::update_print_error_info(int code, std::string msg, std::s
|
|||
if (curr_selected >= 0 && curr_selected < CALI_MODE_COUNT) {
|
||||
if (m_cali_panels[curr_selected]) {
|
||||
auto page = m_cali_panels[curr_selected]->get_curr_step()->page;
|
||||
if(page && page->get_page_type() == CaliPageType::CALI_PAGE_PRESET){
|
||||
auto preset_page = static_cast<CalibrationPresetPage*>(page);
|
||||
if (preset_page->get_page_status() == CaliPresetPageStatus::CaliPresetStatusSending)
|
||||
if (page) {
|
||||
if (page->get_page_type() == CaliPageType::CALI_PAGE_PRESET) {
|
||||
auto preset_page = static_cast<CalibrationPresetPage*>(page);
|
||||
preset_page->update_print_error_info(code, msg, extra);
|
||||
}
|
||||
if (page->get_page_type() == CaliPageType::CALI_PAGE_COARSE_SAVE) {
|
||||
auto corase_page = static_cast<CalibrationFlowCoarseSavePage*>(page);
|
||||
corase_page->update_print_error_info(code, msg, extra);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -89,6 +89,7 @@ private:
|
|||
std::vector<MPanel*> m_user_list_machine_panel;
|
||||
boost::thread* get_print_info_thread{ nullptr };
|
||||
std::string m_print_info;
|
||||
std::shared_ptr<int> m_token = std::make_shared<int>(0);
|
||||
std::map<std::string, MachineObject*> m_bind_machine_list;
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ wxDEFINE_EVENT(EVT_CALIBRATION_JOB_FINISHED, wxCommandEvent);
|
|||
|
||||
static const wxString NA_STR = _L("N/A");
|
||||
static const float MIN_PA_K_VALUE = 0.0;
|
||||
static const float MAX_PA_K_VALUE = 0.5;
|
||||
static const float MAX_PA_K_VALUE = 0.3;
|
||||
static const float MIN_PA_K_VALUE_STEP = 0.001;
|
||||
|
||||
bool check_preset_name_valid(const wxString& name) {
|
||||
|
|
@ -185,17 +185,17 @@ void CalibrationWizard::set_cali_method(CalibrationMethod method)
|
|||
}
|
||||
}
|
||||
|
||||
bool CalibrationWizard::save_preset(const std::string &old_preset_name, const std::string &new_preset_name, const std::map<std::string, ConfigOption *> &key_values, std::string& message)
|
||||
bool CalibrationWizard::save_preset(const std::string &old_preset_name, const std::string &new_preset_name, const std::map<std::string, ConfigOption *> &key_values, wxString& message)
|
||||
{
|
||||
if (new_preset_name.empty()) {
|
||||
message = _u8L("The name cannot be empty.");
|
||||
message = _L("The name cannot be empty.");
|
||||
return false;
|
||||
}
|
||||
|
||||
PresetCollection *filament_presets = &wxGetApp().preset_bundle->filaments;
|
||||
Preset* preset = filament_presets->find_preset(old_preset_name);
|
||||
if (!preset) {
|
||||
message = (boost::format(_u8L("The selected preset: %1% is not found.")) % old_preset_name).str();
|
||||
message = wxString::Format(_L("The selected preset: %s is not found."), old_preset_name);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -207,12 +207,12 @@ bool CalibrationWizard::save_preset(const std::string &old_preset_name, const st
|
|||
Preset *new_preset = filament_presets->find_preset(new_name);
|
||||
if (new_preset) {
|
||||
if (new_preset->is_system) {
|
||||
message = _u8L("The name cannot be the same as the system preset name.");
|
||||
message = _L("The name cannot be the same as the system preset name.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (new_preset != preset) {
|
||||
message = _u8L("The name is the same as another existing preset name");
|
||||
message = _L("The name is the same as another existing preset name");
|
||||
return false;
|
||||
}
|
||||
if (new_preset != &filament_presets->get_edited_preset()) new_preset = &temp_preset;
|
||||
|
|
@ -233,7 +233,7 @@ bool CalibrationWizard::save_preset(const std::string &old_preset_name, const st
|
|||
// Preset* preset = &m_presets.preset(it - m_presets.begin(), true);
|
||||
if (!new_preset) {
|
||||
BOOST_LOG_TRIVIAL(info) << "create new preset failed";
|
||||
message = _u8L("create new preset failed.");
|
||||
message = _L("create new preset failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -299,14 +299,14 @@ void CalibrationWizard::recover_preset_info(MachineObject *obj)
|
|||
}
|
||||
}
|
||||
|
||||
void CalibrationWizard::back_preset_info(MachineObject *obj, bool cali_finish)
|
||||
void CalibrationWizard::back_preset_info(MachineObject *obj, bool cali_finish, bool back_cali_flag)
|
||||
{
|
||||
PrinterCaliInfo printer_cali_info;
|
||||
printer_cali_info.dev_id = obj->dev_id;
|
||||
printer_cali_info.cali_finished = cali_finish;
|
||||
printer_cali_info.cache_flow_ratio = obj->cache_flow_ratio;
|
||||
printer_cali_info.selected_presets = obj->selected_cali_preset;
|
||||
wxGetApp().app_config->save_printer_cali_infos(printer_cali_info);
|
||||
wxGetApp().app_config->save_printer_cali_infos(printer_cali_info, back_cali_flag);
|
||||
}
|
||||
|
||||
void CalibrationWizard::msw_rescale()
|
||||
|
|
@ -361,7 +361,7 @@ void CalibrationWizard::on_cali_go_home()
|
|||
go_home_dialog->on_show();
|
||||
} else {
|
||||
if (!m_page_steps.empty()) {
|
||||
back_preset_info(curr_obj, true);
|
||||
back_preset_info(curr_obj, true, obj_cali_mode == m_mode);
|
||||
show_step(m_page_steps.front());
|
||||
}
|
||||
}
|
||||
|
|
@ -951,6 +951,7 @@ void FlowRateWizard::on_cali_start(CaliPresetStage stage, float cali_value, Flow
|
|||
cali_page->clear_last_job_status();
|
||||
}
|
||||
else if (m_cali_method == CalibrationMethod::CALI_METHOD_MANUAL) {
|
||||
CalibrationFlowCoarseSavePage* coarse_page = (static_cast<CalibrationFlowCoarseSavePage*>(coarse_save_step->page));
|
||||
CalibInfo calib_info;
|
||||
calib_info.dev_id = curr_obj->dev_id;
|
||||
Preset* temp_filament_preset = nullptr;
|
||||
|
|
@ -979,17 +980,23 @@ void FlowRateWizard::on_cali_start(CaliPresetStage stage, float cali_value, Flow
|
|||
temp_filament_preset->config = preset->config;
|
||||
|
||||
calib_info.bed_type = plate_type;
|
||||
calib_info.process_bar = preset_page->get_sending_progress_bar();
|
||||
calib_info.printer_prest = preset_page->get_printer_preset(curr_obj, nozzle_dia);
|
||||
calib_info.print_prest = preset_page->get_print_preset();
|
||||
calib_info.params.mode = CalibMode::Calib_Flow_Rate;
|
||||
|
||||
if (stage == CaliPresetStage::CALI_MANUAL_STAGE_1) {
|
||||
cali_stage = 1;
|
||||
calib_info.process_bar = preset_page->get_sending_progress_bar();
|
||||
}
|
||||
else if (stage == CaliPresetStage::CALI_MANUAL_STAGE_2) {
|
||||
cali_stage = 2;
|
||||
temp_filament_preset->config.set_key_value("filament_flow_ratio", new ConfigOptionFloats{ cali_value });
|
||||
if (from_page == FlowRatioCaliSource::FROM_PRESET_PAGE) {
|
||||
calib_info.process_bar = preset_page->get_sending_progress_bar();
|
||||
}
|
||||
else if (from_page == FlowRatioCaliSource::FROM_COARSE_PAGE) {
|
||||
calib_info.process_bar = coarse_page->get_sending_progress_bar();
|
||||
}
|
||||
}
|
||||
calib_info.filament_prest = temp_filament_preset;
|
||||
|
||||
|
|
@ -1008,17 +1015,23 @@ void FlowRateWizard::on_cali_start(CaliPresetStage stage, float cali_value, Flow
|
|||
msg_dlg.ShowModal();
|
||||
return;
|
||||
}
|
||||
preset_page->on_cali_start_job();
|
||||
if (temp_filament_preset)
|
||||
delete temp_filament_preset;
|
||||
|
||||
if (cali_stage == 1) {
|
||||
CalibrationCaliPage *cali_coarse_page = (static_cast<CalibrationCaliPage *>(cali_coarse_step->page));
|
||||
cali_coarse_page->clear_last_job_status();
|
||||
preset_page->on_cali_start_job();
|
||||
}
|
||||
else if (cali_stage == 2) {
|
||||
CalibrationCaliPage *cali_fine_page = (static_cast<CalibrationCaliPage *>(cali_fine_step->page));
|
||||
cali_fine_page->clear_last_job_status();
|
||||
if (from_page == FlowRatioCaliSource::FROM_PRESET_PAGE) {
|
||||
preset_page->on_cali_start_job();
|
||||
}
|
||||
else if (from_page == FlowRatioCaliSource::FROM_COARSE_PAGE) {
|
||||
coarse_page->on_cali_start_job();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
assert(false);
|
||||
|
|
@ -1050,7 +1063,7 @@ void FlowRateWizard::on_cali_save()
|
|||
for (int i = 0; i < new_results.size(); i++) {
|
||||
std::map<std::string, ConfigOption*> key_value_map;
|
||||
key_value_map.insert(std::make_pair("filament_flow_ratio", new ConfigOptionFloats{ new_results[i].second }));
|
||||
std::string message;
|
||||
wxString message;
|
||||
if (!save_preset(old_preset_name, into_u8(new_results[i].first), key_value_map, message)) {
|
||||
MessageDialog error_msg_dlg(nullptr, message, wxEmptyString, wxICON_WARNING | wxOK);
|
||||
error_msg_dlg.ShowModal();
|
||||
|
|
@ -1097,9 +1110,9 @@ void FlowRateWizard::on_cali_save()
|
|||
std::map<std::string, ConfigOption*> key_value_map;
|
||||
key_value_map.insert(std::make_pair("filament_flow_ratio", new ConfigOptionFloats{ new_flow_ratio }));
|
||||
|
||||
std::string message;
|
||||
wxString message;
|
||||
if (!save_preset(old_preset_name, into_u8(new_preset_name), key_value_map, message)) {
|
||||
MessageDialog error_msg_dlg(nullptr, from_u8(message), wxEmptyString, wxICON_WARNING | wxOK);
|
||||
MessageDialog error_msg_dlg(nullptr, message, wxEmptyString, wxICON_WARNING | wxOK);
|
||||
error_msg_dlg.ShowModal();
|
||||
return;
|
||||
}
|
||||
|
|
@ -1197,17 +1210,20 @@ void FlowRateWizard::on_cali_job_finished(wxString evt_data)
|
|||
if (cali_stage == 1) {
|
||||
if (m_curr_step != cali_coarse_step)
|
||||
show_step(cali_coarse_step);
|
||||
// change ui, hide
|
||||
static_cast<CalibrationPresetPage*>(preset_step->page)->on_cali_finished_job();
|
||||
}
|
||||
else if (cali_stage == 2) {
|
||||
if (m_curr_step != cali_fine_step) {
|
||||
show_step(cali_fine_step);
|
||||
}
|
||||
// change ui, hide
|
||||
static_cast<CalibrationPresetPage*>(preset_step->page)->on_cali_finished_job();
|
||||
static_cast<CalibrationFlowCoarseSavePage*>(coarse_save_step->page)->on_cali_finished_job();
|
||||
}
|
||||
else
|
||||
show_step(cali_coarse_step);
|
||||
}
|
||||
// change ui, hide
|
||||
static_cast<CalibrationPresetPage*>(preset_step->page)->on_cali_finished_job();
|
||||
}
|
||||
|
||||
void FlowRateWizard::cache_coarse_info(MachineObject *obj)
|
||||
|
|
@ -1375,9 +1391,9 @@ void MaxVolumetricSpeedWizard::on_cali_save()
|
|||
std::map<std::string, ConfigOption *> key_value_map;
|
||||
key_value_map.insert(std::make_pair("filament_max_volumetric_speed", new ConfigOptionFloats{ value }));
|
||||
|
||||
std::string message;
|
||||
wxString message;
|
||||
if (!save_preset(old_preset_name, new_preset_name, key_value_map, message)) {
|
||||
MessageDialog error_msg_dlg(nullptr, from_u8(message), wxEmptyString, wxICON_WARNING | wxOK);
|
||||
MessageDialog error_msg_dlg(nullptr, message, wxEmptyString, wxICON_WARNING | wxOK);
|
||||
error_msg_dlg.ShowModal();
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,11 +60,11 @@ public:
|
|||
|
||||
CalibMode get_calibration_mode() { return m_mode; }
|
||||
|
||||
bool save_preset(const std::string &old_preset_name, const std::string &new_preset_name, const std::map<std::string, ConfigOption *> &key_values, std::string& message);
|
||||
bool save_preset(const std::string &old_preset_name, const std::string &new_preset_name, const std::map<std::string, ConfigOption *> &key_values, wxString& message);
|
||||
|
||||
virtual void cache_preset_info(MachineObject* obj, float nozzle_dia);
|
||||
virtual void recover_preset_info(MachineObject *obj);
|
||||
virtual void back_preset_info(MachineObject *obj, bool cali_finish);
|
||||
virtual void back_preset_info(MachineObject *obj, bool cali_finish, bool back_cali_flag = true);
|
||||
|
||||
void msw_rescale();
|
||||
void on_sys_color_changed();
|
||||
|
|
|
|||
|
|
@ -101,27 +101,27 @@ void CalibrationCaliPage::set_cali_img()
|
|||
{
|
||||
if (m_cali_mode == CalibMode::Calib_PA_Line) {
|
||||
if (m_cali_method == CalibrationMethod::CALI_METHOD_MANUAL) {
|
||||
m_picture_panel->set_img(create_scaled_bitmap("fd_calibration_manual", nullptr, 400));
|
||||
m_picture_panel->set_bmp(ScalableBitmap(this, "fd_calibration_manual", 400));
|
||||
}
|
||||
else if (m_cali_method == CalibrationMethod::CALI_METHOD_AUTO) {
|
||||
m_picture_panel->set_img(create_scaled_bitmap("fd_calibration_auto", nullptr, 400));
|
||||
m_picture_panel->set_bmp(ScalableBitmap(this, "fd_calibration_auto", 400));
|
||||
}
|
||||
}
|
||||
else if (m_cali_mode == CalibMode::Calib_Flow_Rate) {
|
||||
if (m_cali_method == CalibrationMethod::CALI_METHOD_MANUAL) {
|
||||
if (m_page_type == CaliPageType::CALI_PAGE_CALI)
|
||||
m_picture_panel->set_img(create_scaled_bitmap("flow_rate_calibration_coarse", nullptr, 400));
|
||||
m_picture_panel->set_bmp(ScalableBitmap(this, "flow_rate_calibration_coarse", 400));
|
||||
if (m_page_type == CaliPageType::CALI_PAGE_FINE_CALI)
|
||||
m_picture_panel->set_img(create_scaled_bitmap("flow_rate_calibration_fine", nullptr, 400));
|
||||
m_picture_panel->set_bmp(ScalableBitmap(this, "flow_rate_calibration_fine", 400));
|
||||
else
|
||||
m_picture_panel->set_img(create_scaled_bitmap("flow_rate_calibration_coarse", nullptr, 400));
|
||||
m_picture_panel->set_bmp(ScalableBitmap(this, "flow_rate_calibration_coarse", 400));
|
||||
}
|
||||
else if (m_cali_method == CalibrationMethod::CALI_METHOD_AUTO) {
|
||||
m_picture_panel->set_img(create_scaled_bitmap("flow_rate_calibration_auto", nullptr, 400));
|
||||
m_picture_panel->set_bmp(ScalableBitmap(this, "flow_rate_calibration_auto", 400));
|
||||
}
|
||||
}
|
||||
else if (m_cali_mode == CalibMode::Calib_Vol_speed_Tower) {
|
||||
m_picture_panel->set_img(create_scaled_bitmap("max_volumetric_speed_calibration", nullptr, 400));
|
||||
m_picture_panel->set_bmp(ScalableBitmap(this, "max_volumetric_speed_calibration", 400));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -129,9 +129,9 @@ void CalibrationCaliPage::set_pa_cali_image(int stage)
|
|||
{
|
||||
if (m_cali_mode == CalibMode::Calib_PA_Line && m_cali_method == CALI_METHOD_MANUAL) {
|
||||
if (stage == 0) {
|
||||
m_picture_panel->set_img(create_scaled_bitmap("fd_calibration_manual", nullptr, 400));
|
||||
m_picture_panel->set_bmp(ScalableBitmap(this, "fd_calibration_manual", 400));
|
||||
} else if (stage == 1) {
|
||||
m_picture_panel->set_img(create_scaled_bitmap("fd_pattern_manual", nullptr, 400));
|
||||
m_picture_panel->set_bmp(ScalableBitmap(this, "fd_pattern_manual", 400));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -428,7 +428,7 @@ void CalibrationCaliPage::reset_printing_values()
|
|||
|
||||
void CalibrationCaliPage::on_device_connected(MachineObject* obj)
|
||||
{
|
||||
;
|
||||
reset_printing_values();
|
||||
}
|
||||
|
||||
void CalibrationCaliPage::set_cali_method(CalibrationMethod method)
|
||||
|
|
@ -473,6 +473,20 @@ void CalibrationCaliPage::set_cali_method(CalibrationMethod method)
|
|||
}
|
||||
}
|
||||
|
||||
bool CalibrationCaliPage::Show(bool show /*= true*/)
|
||||
{
|
||||
if (true) {
|
||||
reset_printing_values();
|
||||
}
|
||||
return wxPanel::Show(show);
|
||||
}
|
||||
|
||||
void CalibrationCaliPage::msw_rescale()
|
||||
{
|
||||
CalibrationWizardPage::msw_rescale();
|
||||
m_picture_panel->msw_rescale();
|
||||
}
|
||||
|
||||
float CalibrationCaliPage::get_selected_calibration_nozzle_dia(MachineObject* obj)
|
||||
{
|
||||
// return selected if this is set
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@ public:
|
|||
void on_device_connected(MachineObject* obj) override;
|
||||
|
||||
void set_cali_method(CalibrationMethod method) override;
|
||||
virtual bool Show(bool show = true) override;
|
||||
void msw_rescale() override;
|
||||
|
||||
protected:
|
||||
float get_selected_calibration_nozzle_dia(MachineObject* obj);
|
||||
|
|
|
|||
|
|
@ -249,6 +249,13 @@ CaliPageButton::CaliPageButton(wxWindow* parent, CaliPageActionType type, wxStri
|
|||
SetCornerRadius(FromDIP(12));
|
||||
}
|
||||
|
||||
void CaliPageButton::msw_rescale()
|
||||
{
|
||||
SetMinSize(wxSize(-1, FromDIP(24)));
|
||||
SetCornerRadius(FromDIP(12));
|
||||
Rescale();
|
||||
}
|
||||
|
||||
|
||||
FilamentComboBox::FilamentComboBox(wxWindow* parent, const wxPoint& pos, const wxSize& size)
|
||||
: wxPanel(parent, wxID_ANY, pos, size, wxTAB_TRAVERSAL)
|
||||
|
|
@ -343,6 +350,14 @@ void FilamentComboBox::SetValue(bool value, bool send_event) {
|
|||
m_checkBox->SetValue(value);
|
||||
}
|
||||
|
||||
void FilamentComboBox::msw_rescale()
|
||||
{
|
||||
//m_checkBox->Rescale();
|
||||
m_comboBox->SetSize(CALIBRATION_FILAMENT_COMBOX_SIZE);
|
||||
m_comboBox->SetMinSize(CALIBRATION_FILAMENT_COMBOX_SIZE);
|
||||
m_comboBox->msw_rescale();
|
||||
}
|
||||
|
||||
|
||||
|
||||
CaliPageCaption::CaliPageCaption(wxWindow* parent, CalibMode cali_mode,
|
||||
|
|
@ -460,6 +475,11 @@ void CaliPageCaption::on_sys_color_changed()
|
|||
m_prev_btn->msw_rescale();
|
||||
}
|
||||
|
||||
void CaliPageCaption::msw_rescale()
|
||||
{
|
||||
m_prev_btn->msw_rescale();
|
||||
}
|
||||
|
||||
CaliPageStepGuide::CaliPageStepGuide(wxWindow* parent, wxArrayString steps,
|
||||
wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
|
||||
: wxPanel(parent, id, pos, size, style),
|
||||
|
|
@ -541,9 +561,16 @@ CaliPagePicture::CaliPagePicture(wxWindow* parent, wxWindowID id, const wxPoint&
|
|||
top_sizer->Fit(this);
|
||||
}
|
||||
|
||||
void CaliPagePicture::set_img(const wxBitmap& bmp)
|
||||
void CaliPagePicture::set_bmp(const ScalableBitmap& bmp)
|
||||
{
|
||||
m_img->SetBitmap(bmp);
|
||||
m_bmp = bmp;
|
||||
m_img->SetBitmap(m_bmp.bmp());
|
||||
}
|
||||
|
||||
void CaliPagePicture::msw_rescale()
|
||||
{
|
||||
m_bmp.msw_rescale();
|
||||
m_img->SetBitmap(m_bmp.bmp());
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -582,6 +609,13 @@ PAPageHelpPanel::PAPageHelpPanel(wxWindow* parent, bool ground_panel, wxWindowID
|
|||
top_sizer->Fit(this);
|
||||
}
|
||||
|
||||
void PAPageHelpPanel::msw_rescale()
|
||||
{
|
||||
m_help_btn->msw_rescale();
|
||||
m_bmp.msw_rescale();
|
||||
m_img->SetBitmap(m_bmp.bmp());
|
||||
}
|
||||
|
||||
void PAPageHelpPanel::create_pop_window()
|
||||
{
|
||||
m_pop_win = new PopupWindow(this);
|
||||
|
|
@ -589,13 +623,10 @@ void PAPageHelpPanel::create_pop_window()
|
|||
wxBoxSizer* pop_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
m_pop_win->SetSizer(pop_sizer);
|
||||
|
||||
wxStaticBitmap* img = new wxStaticBitmap(m_pop_win, wxID_ANY, wxNullBitmap);
|
||||
if (wxGetApp().app_config->get_language_code() == "zh-cn") {
|
||||
img->SetBitmap(ScalableBitmap(this, "cali_fdc_editing_diagram_CN", 206).bmp());
|
||||
} else {
|
||||
img->SetBitmap(ScalableBitmap(this, "cali_fdc_editing_diagram", 206).bmp());
|
||||
}
|
||||
pop_sizer->Add(img, 1, wxEXPAND | wxALL, FromDIP(20));
|
||||
m_img = new wxStaticBitmap(m_pop_win, wxID_ANY, wxNullBitmap);
|
||||
m_bmp = ScalableBitmap(this, "cali_fdc_editing_diagram", 206);
|
||||
m_img->SetBitmap(m_bmp.bmp());
|
||||
pop_sizer->Add(m_img, 1, wxEXPAND | wxALL, FromDIP(20));
|
||||
|
||||
m_pop_win->Layout();
|
||||
m_pop_win->Fit();
|
||||
|
|
@ -754,6 +785,163 @@ void CaliPageActionPanel::enable_button(CaliPageActionType action_type, bool ena
|
|||
}
|
||||
}
|
||||
|
||||
void CaliPageActionPanel::msw_rescale()
|
||||
{
|
||||
for (int i = 0; i < m_action_btns.size(); i++) {
|
||||
m_action_btns[i]->msw_rescale();
|
||||
}
|
||||
}
|
||||
|
||||
CaliPageSendingPanel::CaliPageSendingPanel(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
|
||||
: wxPanel(parent, id, pos, size, style)
|
||||
{
|
||||
SetBackgroundColour(*wxWHITE);
|
||||
SetMinSize({ FromDIP(475), FromDIP(200) });
|
||||
SetMaxSize({ FromDIP(475), FromDIP(200) });
|
||||
|
||||
create(this);
|
||||
|
||||
Layout();
|
||||
Fit();
|
||||
|
||||
Bind(EVT_SHOW_ERROR_INFO, [this](auto& e) {
|
||||
show_send_failed_info(true);
|
||||
});
|
||||
}
|
||||
|
||||
void CaliPageSendingPanel::create(wxWindow* parent)
|
||||
{
|
||||
auto panel_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
parent->SetSizer(panel_sizer);
|
||||
|
||||
m_send_progress_bar = std::shared_ptr<BBLStatusBarSend>(new BBLStatusBarSend(parent));
|
||||
panel_sizer->Add(m_send_progress_bar->get_panel(), 0, wxEXPAND);
|
||||
|
||||
m_sw_print_failed_info = new wxScrolledWindow(parent, wxID_ANY, wxDefaultPosition, wxSize(FromDIP(380), FromDIP(125)), wxVSCROLL);
|
||||
m_sw_print_failed_info->SetBackgroundColour(*wxWHITE);
|
||||
m_sw_print_failed_info->SetScrollRate(0, 5);
|
||||
m_sw_print_failed_info->SetMinSize(wxSize(FromDIP(380), FromDIP(125)));
|
||||
m_sw_print_failed_info->SetMaxSize(wxSize(FromDIP(380), FromDIP(125)));
|
||||
|
||||
m_sw_print_failed_info->Hide();
|
||||
|
||||
panel_sizer->Add(m_sw_print_failed_info, 0, wxEXPAND);
|
||||
|
||||
// create error info panel
|
||||
wxBoxSizer* sizer_print_failed_info = new wxBoxSizer(wxVERTICAL);
|
||||
m_sw_print_failed_info->SetSizer(sizer_print_failed_info);
|
||||
|
||||
wxBoxSizer* sizer_error_code = new wxBoxSizer(wxHORIZONTAL);
|
||||
wxBoxSizer* sizer_error_desc = new wxBoxSizer(wxHORIZONTAL);
|
||||
wxBoxSizer* sizer_extra_info = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
auto st_title_error_code = new Label(m_sw_print_failed_info, _L("Error code"));
|
||||
auto st_title_error_code_doc = new Label(m_sw_print_failed_info, ": ");
|
||||
m_st_txt_error_code = new Label(m_sw_print_failed_info, wxEmptyString);
|
||||
st_title_error_code->SetForegroundColour(0x909090);
|
||||
st_title_error_code_doc->SetForegroundColour(0x909090);
|
||||
m_st_txt_error_code->SetForegroundColour(0x909090);
|
||||
st_title_error_code->SetFont(::Label::Body_13);
|
||||
st_title_error_code_doc->SetFont(::Label::Body_13);
|
||||
m_st_txt_error_code->SetFont(::Label::Body_13);
|
||||
st_title_error_code->SetMinSize(wxSize(FromDIP(74), -1));
|
||||
st_title_error_code->SetMaxSize(wxSize(FromDIP(74), -1));
|
||||
m_st_txt_error_code->SetMinSize(wxSize(FromDIP(260), -1));
|
||||
m_st_txt_error_code->SetMaxSize(wxSize(FromDIP(260), -1));
|
||||
sizer_error_code->Add(st_title_error_code, 0, wxALL, 0);
|
||||
sizer_error_code->Add(st_title_error_code_doc, 0, wxALL, 0);
|
||||
sizer_error_code->Add(m_st_txt_error_code, 0, wxALL, 0);
|
||||
|
||||
auto st_title_error_desc = new Label(m_sw_print_failed_info, _L("Error desc"));
|
||||
auto st_title_error_desc_doc = new Label(m_sw_print_failed_info, ": ");
|
||||
m_st_txt_error_desc = new Label(m_sw_print_failed_info, wxEmptyString);
|
||||
st_title_error_desc->SetForegroundColour(0x909090);
|
||||
st_title_error_desc_doc->SetForegroundColour(0x909090);
|
||||
m_st_txt_error_desc->SetForegroundColour(0x909090);
|
||||
st_title_error_desc->SetFont(::Label::Body_13);
|
||||
st_title_error_desc_doc->SetFont(::Label::Body_13);
|
||||
m_st_txt_error_desc->SetFont(::Label::Body_13);
|
||||
st_title_error_desc->SetMinSize(wxSize(FromDIP(74), -1));
|
||||
st_title_error_desc->SetMaxSize(wxSize(FromDIP(74), -1));
|
||||
m_st_txt_error_desc->SetMinSize(wxSize(FromDIP(260), -1));
|
||||
m_st_txt_error_desc->SetMaxSize(wxSize(FromDIP(260), -1));
|
||||
sizer_error_desc->Add(st_title_error_desc, 0, wxALL, 0);
|
||||
sizer_error_desc->Add(st_title_error_desc_doc, 0, wxALL, 0);
|
||||
sizer_error_desc->Add(m_st_txt_error_desc, 0, wxALL, 0);
|
||||
|
||||
auto st_title_extra_info = new Label(m_sw_print_failed_info, _L("Extra info"));
|
||||
auto st_title_extra_info_doc = new Label(m_sw_print_failed_info, ": ");
|
||||
m_st_txt_extra_info = new Label(m_sw_print_failed_info, wxEmptyString);
|
||||
st_title_extra_info->SetForegroundColour(0x909090);
|
||||
st_title_extra_info_doc->SetForegroundColour(0x909090);
|
||||
m_st_txt_extra_info->SetForegroundColour(0x909090);
|
||||
st_title_extra_info->SetFont(::Label::Body_13);
|
||||
st_title_extra_info_doc->SetFont(::Label::Body_13);
|
||||
m_st_txt_extra_info->SetFont(::Label::Body_13);
|
||||
st_title_extra_info->SetMinSize(wxSize(FromDIP(74), -1));
|
||||
st_title_extra_info->SetMaxSize(wxSize(FromDIP(74), -1));
|
||||
m_st_txt_extra_info->SetMinSize(wxSize(FromDIP(260), -1));
|
||||
m_st_txt_extra_info->SetMaxSize(wxSize(FromDIP(260), -1));
|
||||
sizer_extra_info->Add(st_title_extra_info, 0, wxALL, 0);
|
||||
sizer_extra_info->Add(st_title_extra_info_doc, 0, wxALL, 0);
|
||||
sizer_extra_info->Add(m_st_txt_extra_info, 0, wxALL, 0);
|
||||
|
||||
sizer_print_failed_info->Add(sizer_error_code, 0, wxLEFT, 5);
|
||||
sizer_print_failed_info->Add(0, 0, 0, wxTOP, FromDIP(3));
|
||||
sizer_print_failed_info->Add(sizer_error_desc, 0, wxLEFT, 5);
|
||||
sizer_print_failed_info->Add(0, 0, 0, wxTOP, FromDIP(3));
|
||||
sizer_print_failed_info->Add(sizer_extra_info, 0, wxLEFT, 5);
|
||||
}
|
||||
|
||||
void CaliPageSendingPanel::update_print_error_info(int code, const std::string& msg, const std::string& extra)
|
||||
{
|
||||
m_print_error_code = code;
|
||||
m_print_error_msg = msg;
|
||||
m_print_error_extra = extra;
|
||||
}
|
||||
|
||||
void CaliPageSendingPanel::show_send_failed_info(bool show, int code, wxString description, wxString extra)
|
||||
{
|
||||
if (show) {
|
||||
if (!m_sw_print_failed_info->IsShown()) {
|
||||
m_sw_print_failed_info->Show(true);
|
||||
|
||||
m_st_txt_error_code->SetLabelText(wxString::Format("%d", m_print_error_code));
|
||||
m_st_txt_error_desc->SetLabelText(wxGetApp().filter_string(m_print_error_msg));
|
||||
m_st_txt_extra_info->SetLabelText(wxGetApp().filter_string(m_print_error_extra));
|
||||
|
||||
m_st_txt_error_code->Wrap(FromDIP(260));
|
||||
m_st_txt_error_desc->Wrap(FromDIP(260));
|
||||
m_st_txt_extra_info->Wrap(FromDIP(260));
|
||||
}
|
||||
else {
|
||||
m_sw_print_failed_info->Show(false);
|
||||
}
|
||||
Layout();
|
||||
Fit();
|
||||
}
|
||||
else {
|
||||
if (!m_sw_print_failed_info->IsShown()) { return; }
|
||||
m_sw_print_failed_info->Show(false);
|
||||
m_st_txt_error_code->SetLabelText(wxEmptyString);
|
||||
m_st_txt_error_desc->SetLabelText(wxEmptyString);
|
||||
m_st_txt_extra_info->SetLabelText(wxEmptyString);
|
||||
Layout();
|
||||
Fit();
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<BBLStatusBarSend> CaliPageSendingPanel::get_sending_progress_bar()
|
||||
{
|
||||
return m_send_progress_bar;
|
||||
}
|
||||
|
||||
void CaliPageSendingPanel::reset()
|
||||
{
|
||||
m_send_progress_bar->reset();
|
||||
m_sw_print_failed_info->Show(false);
|
||||
}
|
||||
|
||||
CalibrationWizardPage::CalibrationWizardPage(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
|
||||
: wxPanel(parent, id, pos, size, style)
|
||||
, m_parent(parent)
|
||||
|
|
@ -764,6 +952,8 @@ CalibrationWizardPage::CalibrationWizardPage(wxWindow* parent, wxWindowID id, co
|
|||
|
||||
void CalibrationWizardPage::msw_rescale()
|
||||
{
|
||||
m_page_caption->msw_rescale();
|
||||
m_action_panel->msw_rescale();
|
||||
}
|
||||
|
||||
void CalibrationWizardPage::on_sys_color_changed()
|
||||
|
|
@ -771,4 +961,5 @@ void CalibrationWizardPage::on_sys_color_changed()
|
|||
m_page_caption->on_sys_color_changed();
|
||||
}
|
||||
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,6 +96,7 @@ public:
|
|||
virtual bool Show(bool show = true);
|
||||
virtual bool Enable(bool enable);
|
||||
virtual void SetValue(bool value, bool send_event = true);
|
||||
void msw_rescale();
|
||||
|
||||
protected:
|
||||
int m_tray_id { -1 };
|
||||
|
|
@ -123,6 +124,7 @@ public:
|
|||
void show_prev_btn(bool show = true);
|
||||
void show_help_icon(bool show = true);
|
||||
void on_sys_color_changed();
|
||||
void msw_rescale();
|
||||
|
||||
protected:
|
||||
ScalableButton* m_prev_btn;
|
||||
|
|
@ -167,9 +169,12 @@ public:
|
|||
const wxSize& size = wxDefaultSize,
|
||||
long style = wxTAB_TRAVERSAL);
|
||||
|
||||
void set_img(const wxBitmap& bmp);
|
||||
void set_bmp(const ScalableBitmap& bmp);
|
||||
void paint_on_img();
|
||||
void msw_rescale();
|
||||
|
||||
protected:
|
||||
ScalableBitmap m_bmp;
|
||||
wxStaticBitmap* m_img;
|
||||
};
|
||||
|
||||
|
|
@ -182,12 +187,14 @@ public:
|
|||
const wxPoint& pos = wxDefaultPosition,
|
||||
const wxSize& size = wxDefaultSize,
|
||||
long style = wxTAB_TRAVERSAL);
|
||||
|
||||
void msw_rescale();
|
||||
|
||||
protected:
|
||||
void create_pop_window();
|
||||
|
||||
ScalableButton* m_help_btn;
|
||||
PopupWindow* m_pop_win;
|
||||
ScalableBitmap m_bmp;
|
||||
wxStaticBitmap* m_img;
|
||||
};
|
||||
|
||||
|
|
@ -218,10 +225,38 @@ public:
|
|||
CaliPageButton(wxWindow* parent, CaliPageActionType type, wxString text = wxEmptyString);
|
||||
|
||||
CaliPageActionType get_action_type() { return m_action_type; }
|
||||
|
||||
void msw_rescale();
|
||||
|
||||
private:
|
||||
CaliPageActionType m_action_type;
|
||||
};
|
||||
|
||||
class CaliPageSendingPanel : public wxPanel
|
||||
{
|
||||
public:
|
||||
CaliPageSendingPanel(wxWindow* parent,
|
||||
wxWindowID id = wxID_ANY,
|
||||
const wxPoint& pos = wxDefaultPosition,
|
||||
const wxSize& size = wxDefaultSize,
|
||||
long style = wxTAB_TRAVERSAL);
|
||||
void create(wxWindow* parent);
|
||||
void update_print_error_info(int code, const std::string& msg, const std::string& extra);
|
||||
void show_send_failed_info(bool show, int code = 0, wxString description = wxEmptyString, wxString extra = wxEmptyString);
|
||||
std::shared_ptr<BBLStatusBarSend> get_sending_progress_bar();
|
||||
void reset();
|
||||
|
||||
private:
|
||||
std::shared_ptr<BBLStatusBarSend> m_send_progress_bar;
|
||||
wxScrolledWindow* m_sw_print_failed_info{ nullptr };
|
||||
Label* m_st_txt_error_code{ nullptr };
|
||||
Label* m_st_txt_error_desc{ nullptr };
|
||||
Label* m_st_txt_extra_info{ nullptr };
|
||||
int m_print_error_code;
|
||||
std::string m_print_error_msg;
|
||||
std::string m_print_error_extra;
|
||||
};
|
||||
|
||||
class CaliPageActionPanel : public wxPanel
|
||||
{
|
||||
public:
|
||||
|
|
@ -236,6 +271,7 @@ public:
|
|||
void bind_button(CaliPageActionType action_type, bool is_block);
|
||||
void show_button(CaliPageActionType action_type, bool show = true);
|
||||
void enable_button(CaliPageActionType action_type, bool enable = true);
|
||||
void msw_rescale();
|
||||
|
||||
protected:
|
||||
std::vector<CaliPageButton*> m_action_btns;
|
||||
|
|
@ -277,8 +313,8 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void msw_rescale();
|
||||
void on_sys_color_changed();
|
||||
virtual void msw_rescale();
|
||||
virtual void on_sys_color_changed();
|
||||
|
||||
protected:
|
||||
CalibMode m_cali_mode;
|
||||
|
|
|
|||
|
|
@ -445,6 +445,22 @@ CalibrationPresetPage::CalibrationPresetPage(
|
|||
m_top_sizer->Fit(this);
|
||||
}
|
||||
|
||||
void CalibrationPresetPage::msw_rescale()
|
||||
{
|
||||
CalibrationWizardPage::msw_rescale();
|
||||
m_ams_sync_button->msw_rescale();
|
||||
m_virtual_tray_comboBox->msw_rescale();
|
||||
for (auto& comboBox : m_filament_comboBox_list) {
|
||||
comboBox->msw_rescale();
|
||||
}
|
||||
}
|
||||
|
||||
void CalibrationPresetPage::on_sys_color_changed()
|
||||
{
|
||||
CalibrationWizardPage::on_sys_color_changed();
|
||||
m_ams_sync_button->msw_rescale();
|
||||
}
|
||||
|
||||
void CalibrationPresetPage::create_selection_panel(wxWindow* parent)
|
||||
{
|
||||
auto panel_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
|
@ -633,108 +649,6 @@ void CalibrationPresetPage::create_ext_spool_panel(wxWindow* parent)
|
|||
});
|
||||
}
|
||||
|
||||
void CalibrationPresetPage::create_sending_panel(wxWindow* parent)
|
||||
{
|
||||
parent->SetMinSize({ FromDIP(475), FromDIP(200) });
|
||||
parent->SetMaxSize({ FromDIP(475), FromDIP(200) });
|
||||
|
||||
auto panel_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
parent->SetSizer(panel_sizer);
|
||||
|
||||
m_send_progress_bar = std::shared_ptr<BBLStatusBarSend>(new BBLStatusBarSend(parent));
|
||||
m_send_progress_bar->set_cancel_callback_fina([this]() {
|
||||
BOOST_LOG_TRIVIAL(info) << "CalibrationWizard::print_job: enter canceled";
|
||||
if (CalibUtils::print_job) {
|
||||
if (CalibUtils::print_job->is_running()) {
|
||||
BOOST_LOG_TRIVIAL(info) << "calibration_print_job: canceled";
|
||||
CalibUtils::print_job->cancel();
|
||||
}
|
||||
CalibUtils::print_job->join();
|
||||
}
|
||||
show_status(CaliPresetStatusNormal);
|
||||
});
|
||||
panel_sizer->Add(m_send_progress_bar->get_panel(), 0, wxEXPAND);
|
||||
|
||||
m_sw_print_failed_info = new wxScrolledWindow(parent, wxID_ANY, wxDefaultPosition, wxSize(FromDIP(380), FromDIP(125)), wxVSCROLL);
|
||||
m_sw_print_failed_info->SetBackgroundColour(*wxWHITE);
|
||||
m_sw_print_failed_info->SetScrollRate(0, 5);
|
||||
m_sw_print_failed_info->SetMinSize(wxSize(FromDIP(380), FromDIP(125)));
|
||||
m_sw_print_failed_info->SetMaxSize(wxSize(FromDIP(380), FromDIP(125)));
|
||||
|
||||
m_sw_print_failed_info->Hide();
|
||||
|
||||
panel_sizer->Add(m_sw_print_failed_info, 0, wxEXPAND);
|
||||
|
||||
// create error info panel
|
||||
wxBoxSizer* sizer_print_failed_info = new wxBoxSizer(wxVERTICAL);
|
||||
m_sw_print_failed_info->SetSizer(sizer_print_failed_info);
|
||||
|
||||
wxBoxSizer* sizer_error_code = new wxBoxSizer(wxHORIZONTAL);
|
||||
wxBoxSizer* sizer_error_desc = new wxBoxSizer(wxHORIZONTAL);
|
||||
wxBoxSizer* sizer_extra_info = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
auto st_title_error_code = new Label(m_sw_print_failed_info, _L("Error code"));
|
||||
auto st_title_error_code_doc = new Label(m_sw_print_failed_info, ": ");
|
||||
m_st_txt_error_code = new Label(m_sw_print_failed_info, wxEmptyString);
|
||||
st_title_error_code->SetForegroundColour(0x909090);
|
||||
st_title_error_code_doc->SetForegroundColour(0x909090);
|
||||
m_st_txt_error_code->SetForegroundColour(0x909090);
|
||||
st_title_error_code->SetFont(::Label::Body_13);
|
||||
st_title_error_code_doc->SetFont(::Label::Body_13);
|
||||
m_st_txt_error_code->SetFont(::Label::Body_13);
|
||||
st_title_error_code->SetMinSize(wxSize(FromDIP(74), -1));
|
||||
st_title_error_code->SetMaxSize(wxSize(FromDIP(74), -1));
|
||||
m_st_txt_error_code->SetMinSize(wxSize(FromDIP(260), -1));
|
||||
m_st_txt_error_code->SetMaxSize(wxSize(FromDIP(260), -1));
|
||||
sizer_error_code->Add(st_title_error_code, 0, wxALL, 0);
|
||||
sizer_error_code->Add(st_title_error_code_doc, 0, wxALL, 0);
|
||||
sizer_error_code->Add(m_st_txt_error_code, 0, wxALL, 0);
|
||||
|
||||
auto st_title_error_desc = new Label(m_sw_print_failed_info, _L("Error desc"));
|
||||
auto st_title_error_desc_doc = new Label(m_sw_print_failed_info, ": ");
|
||||
m_st_txt_error_desc = new Label(m_sw_print_failed_info, wxEmptyString);
|
||||
st_title_error_desc->SetForegroundColour(0x909090);
|
||||
st_title_error_desc_doc->SetForegroundColour(0x909090);
|
||||
m_st_txt_error_desc->SetForegroundColour(0x909090);
|
||||
st_title_error_desc->SetFont(::Label::Body_13);
|
||||
st_title_error_desc_doc->SetFont(::Label::Body_13);
|
||||
m_st_txt_error_desc->SetFont(::Label::Body_13);
|
||||
st_title_error_desc->SetMinSize(wxSize(FromDIP(74), -1));
|
||||
st_title_error_desc->SetMaxSize(wxSize(FromDIP(74), -1));
|
||||
m_st_txt_error_desc->SetMinSize(wxSize(FromDIP(260), -1));
|
||||
m_st_txt_error_desc->SetMaxSize(wxSize(FromDIP(260), -1));
|
||||
sizer_error_desc->Add(st_title_error_desc, 0, wxALL, 0);
|
||||
sizer_error_desc->Add(st_title_error_desc_doc, 0, wxALL, 0);
|
||||
sizer_error_desc->Add(m_st_txt_error_desc, 0, wxALL, 0);
|
||||
|
||||
auto st_title_extra_info = new Label(m_sw_print_failed_info, _L("Extra info"));
|
||||
auto st_title_extra_info_doc = new Label(m_sw_print_failed_info, ": ");
|
||||
m_st_txt_extra_info = new Label(m_sw_print_failed_info, wxEmptyString);
|
||||
st_title_extra_info->SetForegroundColour(0x909090);
|
||||
st_title_extra_info_doc->SetForegroundColour(0x909090);
|
||||
m_st_txt_extra_info->SetForegroundColour(0x909090);
|
||||
st_title_extra_info->SetFont(::Label::Body_13);
|
||||
st_title_extra_info_doc->SetFont(::Label::Body_13);
|
||||
m_st_txt_extra_info->SetFont(::Label::Body_13);
|
||||
st_title_extra_info->SetMinSize(wxSize(FromDIP(74), -1));
|
||||
st_title_extra_info->SetMaxSize(wxSize(FromDIP(74), -1));
|
||||
m_st_txt_extra_info->SetMinSize(wxSize(FromDIP(260), -1));
|
||||
m_st_txt_extra_info->SetMaxSize(wxSize(FromDIP(260), -1));
|
||||
sizer_extra_info->Add(st_title_extra_info, 0, wxALL, 0);
|
||||
sizer_extra_info->Add(st_title_extra_info_doc, 0, wxALL, 0);
|
||||
sizer_extra_info->Add(m_st_txt_extra_info, 0, wxALL, 0);
|
||||
|
||||
sizer_print_failed_info->Add(sizer_error_code, 0, wxLEFT, 5);
|
||||
sizer_print_failed_info->Add(0, 0, 0, wxTOP, FromDIP(3));
|
||||
sizer_print_failed_info->Add(sizer_error_desc, 0, wxLEFT, 5);
|
||||
sizer_print_failed_info->Add(0, 0, 0, wxTOP, FromDIP(3));
|
||||
sizer_print_failed_info->Add(sizer_extra_info, 0, wxLEFT, 5);
|
||||
|
||||
Bind(EVT_SHOW_ERROR_INFO, [this](auto& e) {
|
||||
show_send_failed_info(true);
|
||||
});
|
||||
}
|
||||
|
||||
void CalibrationPresetPage::create_page(wxWindow* parent)
|
||||
{
|
||||
m_page_caption = new CaliPageCaption(parent, m_cali_mode);
|
||||
|
|
@ -788,10 +702,10 @@ void CalibrationPresetPage::create_page(wxWindow* parent)
|
|||
|
||||
m_tips_panel = new CaliPresetTipsPanel(parent);
|
||||
|
||||
m_sending_panel = new wxPanel(parent);
|
||||
m_sending_panel->SetBackgroundColour(*wxWHITE);
|
||||
create_sending_panel(m_sending_panel);
|
||||
|
||||
m_sending_panel = new CaliPageSendingPanel(parent);
|
||||
m_sending_panel->get_sending_progress_bar()->set_cancel_callback_fina([this]() {
|
||||
on_cali_cancel_job();
|
||||
});
|
||||
m_sending_panel->Hide();
|
||||
|
||||
m_custom_range_panel = new CaliPresetCustomRangePanel(parent);
|
||||
|
|
@ -1038,8 +952,10 @@ bool CalibrationPresetPage::is_filament_in_blacklist(Preset* preset, std::string
|
|||
std::string filamnt_type;
|
||||
preset->get_filament_type(filamnt_type);
|
||||
|
||||
if (preset->vendor) {
|
||||
DeviceManager::check_filaments_in_blacklist(preset->vendor->name, filamnt_type, in_blacklist, action, info);
|
||||
auto vendor = dynamic_cast<ConfigOptionStrings*> (preset->config.option("filament_vendor"));
|
||||
if (vendor && (vendor->values.size() > 0)) {
|
||||
std::string vendor_name = vendor->values[0];
|
||||
DeviceManager::check_filaments_in_blacklist(vendor_name, filamnt_type, in_blacklist, action, info);
|
||||
}
|
||||
|
||||
if (in_blacklist) {
|
||||
|
|
@ -1189,12 +1105,6 @@ bool CalibrationPresetPage::is_blocking_printing()
|
|||
|
||||
void CalibrationPresetPage::update_show_status()
|
||||
{
|
||||
if (get_status() == CaliPresetPageStatus::CaliPresetStatusSending)
|
||||
return;
|
||||
|
||||
if (get_status() == CaliPresetPageStatus::CaliPresetStatusSendingCanceled)
|
||||
return;
|
||||
|
||||
NetworkAgent* agent = Slic3r::GUI::wxGetApp().getAgent();
|
||||
DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
|
||||
if (!agent) {return;}
|
||||
|
|
@ -1307,12 +1217,8 @@ bool CalibrationPresetPage::need_check_sdcard(MachineObject* obj)
|
|||
|
||||
void CalibrationPresetPage::show_status(CaliPresetPageStatus status)
|
||||
{
|
||||
if (status == CaliPresetPageStatus::CaliPresetStatusSending) {
|
||||
sending_mode();
|
||||
}
|
||||
else {
|
||||
prepare_mode();
|
||||
}
|
||||
if (m_stop_update_page_status)
|
||||
return;
|
||||
|
||||
if (m_page_status != status)
|
||||
//BOOST_LOG_TRIVIAL(info) << "CalibrationPresetPage: show_status = " << status << "(" << get_print_status_info(status) << ")";
|
||||
|
|
@ -1324,7 +1230,6 @@ void CalibrationPresetPage::show_status(CaliPresetPageStatus status)
|
|||
Enable_Send_Button(false);
|
||||
}
|
||||
else if (status == CaliPresetPageStatus::CaliPresetStatusNormal) {
|
||||
m_sending_panel->Show(false);
|
||||
update_print_status_msg(wxEmptyString, false);
|
||||
Enable_Send_Button(true);
|
||||
Layout();
|
||||
|
|
@ -1359,15 +1264,6 @@ void CalibrationPresetPage::show_status(CaliPresetPageStatus status)
|
|||
update_print_status_msg(msg_text, true);
|
||||
Enable_Send_Button(false);
|
||||
}
|
||||
else if (status == CaliPresetPageStatus::CaliPresetStatusSending) {
|
||||
m_sending_panel->Show();
|
||||
Enable_Send_Button(false);
|
||||
Layout();
|
||||
Fit();
|
||||
}
|
||||
else if (status == CaliPresetPageStatus::CaliPresetStatusSendingCanceled) {
|
||||
Enable_Send_Button(true);
|
||||
}
|
||||
else if (status == CaliPresetPageStatus::CaliPresetStatusLanModeNoSdcard) {
|
||||
wxString msg_text = _L("An SD card needs to be inserted before printing via LAN.");
|
||||
update_print_status_msg(msg_text, true);
|
||||
|
|
@ -1406,19 +1302,6 @@ void CalibrationPresetPage::Enable_Send_Button(bool enable)
|
|||
m_action_panel->enable_button(CaliPageActionType::CALI_ACTION_CALI, enable);
|
||||
}
|
||||
|
||||
void CalibrationPresetPage::prepare_mode()
|
||||
{
|
||||
Enable_Send_Button(true);
|
||||
m_action_panel->show_button(CaliPageActionType::CALI_ACTION_CALI, true);
|
||||
}
|
||||
|
||||
void CalibrationPresetPage::sending_mode()
|
||||
{
|
||||
Enable_Send_Button(false);
|
||||
m_action_panel->show_button(CaliPageActionType::CALI_ACTION_CALI, false);
|
||||
}
|
||||
|
||||
|
||||
float CalibrationPresetPage::get_nozzle_value()
|
||||
{
|
||||
double nozzle_value = 0.0;
|
||||
|
|
@ -1448,44 +1331,6 @@ void CalibrationPresetPage::on_device_connected(MachineObject* obj)
|
|||
update_combobox_filaments(obj);
|
||||
}
|
||||
|
||||
void CalibrationPresetPage::update_print_error_info(int code, const std::string& msg, const std::string& extra)
|
||||
{
|
||||
m_print_error_code = code;
|
||||
m_print_error_msg = msg;
|
||||
m_print_error_extra = extra;
|
||||
}
|
||||
|
||||
void CalibrationPresetPage::show_send_failed_info(bool show, int code, wxString description, wxString extra)
|
||||
{
|
||||
if (show) {
|
||||
if (!m_sw_print_failed_info->IsShown()) {
|
||||
m_sw_print_failed_info->Show(true);
|
||||
|
||||
m_st_txt_error_code->SetLabelText(wxString::Format("%d", m_print_error_code));
|
||||
m_st_txt_error_desc->SetLabelText(wxGetApp().filter_string(m_print_error_msg));
|
||||
m_st_txt_extra_info->SetLabelText(wxGetApp().filter_string(m_print_error_extra));
|
||||
|
||||
m_st_txt_error_code->Wrap(FromDIP(260));
|
||||
m_st_txt_error_desc->Wrap(FromDIP(260));
|
||||
m_st_txt_extra_info->Wrap(FromDIP(260));
|
||||
}
|
||||
else {
|
||||
m_sw_print_failed_info->Show(false);
|
||||
}
|
||||
Layout();
|
||||
Fit();
|
||||
}
|
||||
else {
|
||||
if (!m_sw_print_failed_info->IsShown()) { return; }
|
||||
m_sw_print_failed_info->Show(false);
|
||||
m_st_txt_error_code->SetLabelText(wxEmptyString);
|
||||
m_st_txt_error_desc->SetLabelText(wxEmptyString);
|
||||
m_st_txt_extra_info->SetLabelText(wxEmptyString);
|
||||
Layout();
|
||||
Fit();
|
||||
}
|
||||
}
|
||||
|
||||
void CalibrationPresetPage::set_cali_filament_mode(CalibrationFilamentMode mode)
|
||||
{
|
||||
CalibrationWizardPage::set_cali_filament_mode(mode);
|
||||
|
|
@ -1539,9 +1384,9 @@ void CalibrationPresetPage::set_cali_method(CalibrationMethod method)
|
|||
|
||||
wxArrayString values;
|
||||
values.push_back(_L("0"));
|
||||
values.push_back(_L("0.5"));
|
||||
values.push_back(_L("0.5"));
|
||||
values.push_back(_L("0.005"));
|
||||
m_custom_range_panel->set_values(values);
|
||||
m_custom_range_panel->set_values(values);
|
||||
|
||||
m_custom_range_panel->set_unit("");
|
||||
m_custom_range_panel->Show();
|
||||
|
|
@ -1566,14 +1411,49 @@ void CalibrationPresetPage::set_cali_method(CalibrationMethod method)
|
|||
|
||||
void CalibrationPresetPage::on_cali_start_job()
|
||||
{
|
||||
m_send_progress_bar->reset();
|
||||
m_sw_print_failed_info->Show(false);
|
||||
show_status(CaliPresetPageStatus::CaliPresetStatusSending);
|
||||
m_sending_panel->reset();
|
||||
m_sending_panel->Show();
|
||||
Enable_Send_Button(false);
|
||||
m_action_panel->show_button(CaliPageActionType::CALI_ACTION_CALI, false);
|
||||
Layout();
|
||||
Fit();
|
||||
|
||||
m_stop_update_page_status = true;
|
||||
}
|
||||
|
||||
void CalibrationPresetPage::on_cali_finished_job()
|
||||
{
|
||||
show_status(CaliPresetPageStatus::CaliPresetStatusNormal);
|
||||
m_sending_panel->reset();
|
||||
m_sending_panel->Show(false);
|
||||
update_print_status_msg(wxEmptyString, false);
|
||||
Enable_Send_Button(true);
|
||||
m_action_panel->show_button(CaliPageActionType::CALI_ACTION_CALI, true);
|
||||
Layout();
|
||||
Fit();
|
||||
|
||||
m_stop_update_page_status = false;
|
||||
}
|
||||
|
||||
void CalibrationPresetPage::on_cali_cancel_job()
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(info) << "CalibrationWizard::print_job: enter canceled";
|
||||
if (CalibUtils::print_job) {
|
||||
if (CalibUtils::print_job->is_running()) {
|
||||
BOOST_LOG_TRIVIAL(info) << "calibration_print_job: canceled";
|
||||
CalibUtils::print_job->cancel();
|
||||
}
|
||||
CalibUtils::print_job->join();
|
||||
}
|
||||
|
||||
m_sending_panel->reset();
|
||||
m_sending_panel->Show(false);
|
||||
update_print_status_msg(wxEmptyString, false);
|
||||
Enable_Send_Button(true);
|
||||
m_action_panel->show_button(CaliPageActionType::CALI_ACTION_CALI, true);
|
||||
Layout();
|
||||
Fit();
|
||||
|
||||
m_stop_update_page_status = false;
|
||||
}
|
||||
|
||||
void CalibrationPresetPage::init_with_machine(MachineObject* obj)
|
||||
|
|
@ -1986,7 +1866,7 @@ MaxVolumetricSpeedPresetPage::MaxVolumetricSpeedPresetPage(
|
|||
wxArrayString titles;
|
||||
titles.push_back(_L("From Volumetric Speed"));
|
||||
titles.push_back(_L("To Volumetric Speed"));
|
||||
titles.push_back(_L("Step value"));
|
||||
titles.push_back(_L("Step"));
|
||||
m_custom_range_panel->set_titles(titles);
|
||||
|
||||
m_custom_range_panel->set_unit(_L("mm\u00B3/s"));
|
||||
|
|
|
|||
|
|
@ -129,14 +129,12 @@ enum CaliPresetPageStatus
|
|||
{
|
||||
CaliPresetStatusInit = 0,
|
||||
CaliPresetStatusNormal,
|
||||
CaliPresetStatusSending,
|
||||
CaliPresetStatusNoUserLogin,
|
||||
CaliPresetStatusInvalidPrinter,
|
||||
CaliPresetStatusConnectingServer,
|
||||
CaliPresetStatusInUpgrading,
|
||||
CaliPresetStatusInSystemPrinting,
|
||||
CaliPresetStatusInPrinting,
|
||||
CaliPresetStatusSendingCanceled,
|
||||
CaliPresetStatusLanModeNoSdcard,
|
||||
CaliPresetStatusNoSdcard,
|
||||
CaliPresetStatusNeedForceUpgrading,
|
||||
|
|
@ -167,9 +165,7 @@ public:
|
|||
|
||||
void on_device_connected(MachineObject* obj) override;
|
||||
|
||||
void update_print_error_info(int code, const std::string& msg, const std::string& extra);
|
||||
|
||||
void show_send_failed_info(bool show, int code = 0, wxString description = wxEmptyString, wxString extra = wxEmptyString);
|
||||
void update_print_error_info(int code, const std::string& msg, const std::string& extra) { m_sending_panel->update_print_error_info(code, msg, extra); }
|
||||
|
||||
void set_cali_filament_mode(CalibrationFilamentMode mode) override;
|
||||
|
||||
|
|
@ -179,6 +175,8 @@ public:
|
|||
|
||||
void on_cali_finished_job();
|
||||
|
||||
void on_cali_cancel_job();
|
||||
|
||||
void init_with_machine(MachineObject* obj);
|
||||
|
||||
void sync_ams_info(MachineObject* obj);
|
||||
|
|
@ -197,7 +195,7 @@ public:
|
|||
void get_cali_stage(CaliPresetStage& stage, float& value);
|
||||
|
||||
std::shared_ptr<ProgressIndicator> get_sending_progress_bar() {
|
||||
return m_send_progress_bar;
|
||||
return m_sending_panel->get_sending_progress_bar();
|
||||
}
|
||||
|
||||
Preset* get_printer_preset(MachineObject* obj, float nozzle_value);
|
||||
|
|
@ -208,11 +206,14 @@ public:
|
|||
CalibMode get_pa_cali_method();
|
||||
|
||||
CaliPresetPageStatus get_page_status() { return m_page_status; }
|
||||
|
||||
void msw_rescale() override;
|
||||
void on_sys_color_changed() override;
|
||||
|
||||
protected:
|
||||
void create_selection_panel(wxWindow* parent);
|
||||
void create_filament_list_panel(wxWindow* parent);
|
||||
void create_ext_spool_panel(wxWindow* parent);
|
||||
void create_sending_panel(wxWindow* parent);
|
||||
|
||||
void init_selection_values();
|
||||
void update_filament_combobox(std::string ams_id = "");
|
||||
|
|
@ -244,8 +245,6 @@ protected:
|
|||
void update_show_status();
|
||||
void show_status(CaliPresetPageStatus status);
|
||||
void Enable_Send_Button(bool enable);
|
||||
void prepare_mode();
|
||||
void sending_mode();
|
||||
bool is_blocking_printing();
|
||||
bool need_check_sdcard(MachineObject* obj);
|
||||
|
||||
|
|
@ -263,7 +262,7 @@ protected:
|
|||
CaliPresetWarningPanel* m_warning_panel { nullptr };
|
||||
CaliPresetCustomRangePanel* m_custom_range_panel { nullptr };
|
||||
CaliPresetTipsPanel* m_tips_panel { nullptr };
|
||||
wxPanel* m_sending_panel { nullptr };
|
||||
CaliPageSendingPanel* m_sending_panel { nullptr };
|
||||
|
||||
wxBoxSizer* m_top_sizer;
|
||||
|
||||
|
|
@ -279,15 +278,6 @@ protected:
|
|||
FilamentComboBoxList m_filament_comboBox_list;
|
||||
FilamentComboBox* m_virtual_tray_comboBox;
|
||||
|
||||
// m_sending panel widgets
|
||||
std::shared_ptr<BBLStatusBarSend> m_send_progress_bar;
|
||||
wxScrolledWindow* m_sw_print_failed_info { nullptr };
|
||||
Label* m_st_txt_error_code { nullptr };
|
||||
Label* m_st_txt_error_desc { nullptr };
|
||||
Label* m_st_txt_extra_info { nullptr };
|
||||
int m_print_error_code;
|
||||
std::string m_print_error_msg;
|
||||
std::string m_print_error_extra;
|
||||
|
||||
std::vector<AMSItem*> m_ams_item_list;
|
||||
|
||||
|
|
@ -295,6 +285,7 @@ protected:
|
|||
std::map<int, DynamicPrintConfig> filament_ams_list;
|
||||
|
||||
CaliPresetPageStatus m_page_status { CaliPresetPageStatus::CaliPresetStatusInit };
|
||||
bool m_stop_update_page_status{ false };
|
||||
|
||||
bool m_show_custom_range { false };
|
||||
bool m_has_filament_incompatible { false };
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ namespace Slic3r { namespace GUI {
|
|||
|
||||
#define CALIBRATION_SAVE_INPUT_SIZE wxSize(FromDIP(240), FromDIP(24))
|
||||
#define FLOW_RATE_MAX_VALUE 1.15
|
||||
static const wxString k_tips = "Please input a valid value (K in 0~0.3)";
|
||||
|
||||
static wxString get_default_name(wxString filament_name, CalibMode mode){
|
||||
PresetBundle* preset_bundle = wxGetApp().preset_bundle;
|
||||
|
|
@ -363,10 +364,11 @@ void CaliPASaveAutoPanel::save_to_result_from_widgets(wxWindow* window, bool* ou
|
|||
if (input->get_type() == GridTextInputType::K) {
|
||||
float k = 0.0f;
|
||||
if (!CalibUtils::validate_input_k_value(input->GetTextCtrl()->GetValue(), &k)) {
|
||||
*out_msg = _L("Please input a valid value (K in 0~0.5)");
|
||||
*out_msg = _L("Please input a valid value (K in 0~0.3)");
|
||||
*out_is_valid = false;
|
||||
}
|
||||
m_calib_results[tray_id].k_value = k;
|
||||
else
|
||||
m_calib_results[tray_id].k_value = k;
|
||||
}
|
||||
else if (input->get_type() == GridTextInputType::N) {
|
||||
}
|
||||
|
|
@ -517,9 +519,9 @@ void CaliPASaveManualPanel::create_panel(wxWindow* parent)
|
|||
|
||||
void CaliPASaveManualPanel::set_save_img() {
|
||||
if (wxGetApp().app_config->get_language_code() == "zh-cn") {
|
||||
m_picture_panel->set_img(create_scaled_bitmap("fd_calibration_manual_result_CN", nullptr, 330));
|
||||
m_picture_panel->set_bmp(ScalableBitmap(this, "fd_calibration_manual_result_CN", 330));
|
||||
} else {
|
||||
m_picture_panel->set_img(create_scaled_bitmap("fd_calibration_manual_result", nullptr, 330));
|
||||
m_picture_panel->set_bmp(ScalableBitmap(this, "fd_calibration_manual_result", 330));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -531,9 +533,9 @@ void CaliPASaveManualPanel::set_pa_cali_method(ManualPaCaliMethod method)
|
|||
} else if (method == ManualPaCaliMethod::PA_PATTERN) {
|
||||
m_complete_text->SetLabel(_L("Please find the cornor with perfect degree of extrusion"));
|
||||
if (wxGetApp().app_config->get_language_code() == "zh-cn") {
|
||||
m_picture_panel->set_img(create_scaled_bitmap("fd_pattern_manual_result_CN", nullptr, 350));
|
||||
m_picture_panel->set_bmp(ScalableBitmap(this, "fd_pattern_manual_result_CN", 350));
|
||||
} else {
|
||||
m_picture_panel->set_img(create_scaled_bitmap("fd_pattern_manual_result", nullptr, 350));
|
||||
m_picture_panel->set_bmp(ScalableBitmap(this, "fd_pattern_manual_result", 350));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -546,7 +548,7 @@ bool CaliPASaveManualPanel::get_result(PACalibResult& out_result) {
|
|||
// Check if the value is valid
|
||||
float k;
|
||||
if (!CalibUtils::validate_input_k_value(m_k_val->GetTextCtrl()->GetValue(), &k)) {
|
||||
MessageDialog msg_dlg(nullptr, _L("Please input a valid value (K in 0~0.5)"), wxEmptyString, wxICON_WARNING | wxOK);
|
||||
MessageDialog msg_dlg(nullptr, _L(k_tips), wxEmptyString, wxICON_WARNING | wxOK);
|
||||
msg_dlg.ShowModal();
|
||||
return false;
|
||||
}
|
||||
|
|
@ -593,6 +595,8 @@ bool CaliPASaveManualPanel::Show(bool show) {
|
|||
if (!m_obj->selected_cali_preset.empty()) {
|
||||
wxString default_name = get_default_name(m_obj->selected_cali_preset[0].name, CalibMode::Calib_PA_Line);
|
||||
set_default_name(default_name);
|
||||
m_k_val->GetTextCtrl()->SetLabel("");
|
||||
m_n_val->GetTextCtrl()->SetLabel("");
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
@ -602,6 +606,11 @@ bool CaliPASaveManualPanel::Show(bool show) {
|
|||
return wxPanel::Show(show);
|
||||
}
|
||||
|
||||
void CaliPASaveManualPanel::msw_rescale()
|
||||
{
|
||||
m_picture_panel->msw_rescale();
|
||||
}
|
||||
|
||||
CaliPASaveP1PPanel::CaliPASaveP1PPanel(
|
||||
wxWindow* parent,
|
||||
wxWindowID id,
|
||||
|
|
@ -671,9 +680,9 @@ void CaliPASaveP1PPanel::create_panel(wxWindow* parent)
|
|||
|
||||
void CaliPASaveP1PPanel::set_save_img() {
|
||||
if (wxGetApp().app_config->get_language_code() == "zh-cn") {
|
||||
m_picture_panel->set_img(create_scaled_bitmap("fd_calibration_manual_result_CN", nullptr, 350));
|
||||
m_picture_panel->set_bmp(ScalableBitmap(this, "fd_calibration_manual_result_CN", 350));
|
||||
} else {
|
||||
m_picture_panel->set_img(create_scaled_bitmap("fd_calibration_manual_result", nullptr, 350));
|
||||
m_picture_panel->set_bmp(ScalableBitmap(this, "fd_calibration_manual_result", 350));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -686,9 +695,9 @@ void CaliPASaveP1PPanel::set_pa_cali_method(ManualPaCaliMethod method)
|
|||
else if (method == ManualPaCaliMethod::PA_PATTERN) {
|
||||
m_complete_text->SetLabel(_L("Please find the cornor with perfect degree of extrusion"));
|
||||
if (wxGetApp().app_config->get_language_code() == "zh-cn") {
|
||||
m_picture_panel->set_img(create_scaled_bitmap("fd_pattern_manual_result_CN", nullptr, 350));
|
||||
m_picture_panel->set_bmp(ScalableBitmap(this, "fd_pattern_manual_result_CN", 350));
|
||||
} else {
|
||||
m_picture_panel->set_img(create_scaled_bitmap("fd_pattern_manual_result", nullptr, 350));
|
||||
m_picture_panel->set_bmp(ScalableBitmap(this, "fd_pattern_manual_result", 350));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -696,13 +705,26 @@ void CaliPASaveP1PPanel::set_pa_cali_method(ManualPaCaliMethod method)
|
|||
bool CaliPASaveP1PPanel::get_result(float* out_k, float* out_n){
|
||||
// Check if the value is valid
|
||||
if (!CalibUtils::validate_input_k_value(m_k_val->GetTextCtrl()->GetValue(), out_k)) {
|
||||
MessageDialog msg_dlg(nullptr, _L("Please input a valid value (K in 0~0.5)"), wxEmptyString, wxICON_WARNING | wxOK);
|
||||
MessageDialog msg_dlg(nullptr, _L(k_tips), wxEmptyString, wxICON_WARNING | wxOK);
|
||||
msg_dlg.ShowModal();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CaliPASaveP1PPanel::Show(bool show) {
|
||||
if (show) {
|
||||
m_k_val->GetTextCtrl()->SetLabel("");
|
||||
m_n_val->GetTextCtrl()->SetLabel("");
|
||||
}
|
||||
return wxPanel::Show(show);
|
||||
}
|
||||
|
||||
void CaliPASaveP1PPanel::msw_rescale()
|
||||
{
|
||||
m_picture_panel->msw_rescale();
|
||||
}
|
||||
|
||||
CaliSavePresetValuePanel::CaliSavePresetValuePanel(
|
||||
wxWindow *parent,
|
||||
wxWindowID id,
|
||||
|
|
@ -751,7 +773,7 @@ void CaliSavePresetValuePanel::create_panel(wxWindow *parent)
|
|||
|
||||
void CaliSavePresetValuePanel::set_img(const std::string& bmp_name_in)
|
||||
{
|
||||
m_picture_panel->set_img(create_scaled_bitmap(bmp_name_in, nullptr, 400));
|
||||
m_picture_panel->set_bmp(ScalableBitmap(this, bmp_name_in, 400));
|
||||
}
|
||||
|
||||
void CaliSavePresetValuePanel::set_value_title(const wxString& title) {
|
||||
|
|
@ -777,6 +799,11 @@ void CaliSavePresetValuePanel::set_save_name(const std::string& name)
|
|||
m_input_name->GetTextCtrl()->SetValue(name);
|
||||
}
|
||||
|
||||
void CaliSavePresetValuePanel::msw_rescale()
|
||||
{
|
||||
m_picture_panel->msw_rescale();
|
||||
}
|
||||
|
||||
CalibrationPASavePage::CalibrationPASavePage(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
|
||||
: CalibrationCommonSavePage(parent, id, pos, size, style)
|
||||
{
|
||||
|
|
@ -875,6 +902,8 @@ void CalibrationPASavePage::set_cali_method(CalibrationMethod method)
|
|||
void CalibrationPASavePage::on_device_connected(MachineObject* obj)
|
||||
{
|
||||
curr_obj = obj;
|
||||
m_auto_panel->set_machine_obj(curr_obj);
|
||||
m_manual_panel->set_machine_obj(curr_obj);
|
||||
if (curr_obj)
|
||||
show_panels(m_cali_method, curr_obj->get_printer_series());
|
||||
}
|
||||
|
|
@ -899,6 +928,14 @@ bool CalibrationPASavePage::Show(bool show) {
|
|||
return wxPanel::Show(show);
|
||||
}
|
||||
|
||||
void CalibrationPASavePage::msw_rescale()
|
||||
{
|
||||
CalibrationWizardPage::msw_rescale();
|
||||
m_manual_panel->msw_rescale();
|
||||
m_p1p_panel->msw_rescale();
|
||||
m_help_panel->msw_rescale();
|
||||
}
|
||||
|
||||
CalibrationFlowX1SavePage::CalibrationFlowX1SavePage(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
|
||||
: CalibrationCommonSavePage(parent, id, pos, size, style)
|
||||
{
|
||||
|
|
@ -1138,6 +1175,11 @@ bool CalibrationFlowX1SavePage::Show(bool show) {
|
|||
return wxPanel::Show(show);
|
||||
}
|
||||
|
||||
void CalibrationFlowX1SavePage::msw_rescale()
|
||||
{
|
||||
CalibrationWizardPage::msw_rescale();
|
||||
}
|
||||
|
||||
CalibrationFlowCoarseSavePage::CalibrationFlowCoarseSavePage(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
|
||||
: CalibrationCommonSavePage(parent, id, pos, size, style)
|
||||
{
|
||||
|
|
@ -1258,6 +1300,13 @@ void CalibrationFlowCoarseSavePage::create_page(wxWindow* parent)
|
|||
m_coarse_calc_result_text->SetLabel(wxString::Format(_L("flow ratio : %s "), std::to_string(m_coarse_flow_ratio)));
|
||||
});
|
||||
|
||||
m_sending_panel = new CaliPageSendingPanel(parent);
|
||||
m_sending_panel->get_sending_progress_bar()->set_cancel_callback_fina([this]() {
|
||||
on_cali_cancel_job();
|
||||
});
|
||||
m_sending_panel->Hide();
|
||||
m_top_sizer->Add(m_sending_panel, 0, wxALIGN_CENTER);
|
||||
|
||||
m_action_panel = new CaliPageActionPanel(parent, m_cali_mode, CaliPageType::CALI_PAGE_COARSE_SAVE);
|
||||
m_action_panel->show_button(CaliPageActionType::CALI_ACTION_FLOW_COARSE_SAVE, false);
|
||||
m_top_sizer->Add(m_action_panel, 0, wxEXPAND, 0);
|
||||
|
|
@ -1265,9 +1314,9 @@ void CalibrationFlowCoarseSavePage::create_page(wxWindow* parent)
|
|||
|
||||
void CalibrationFlowCoarseSavePage::set_save_img() {
|
||||
if (wxGetApp().app_config->get_language_code() == "zh-cn") {
|
||||
m_picture_panel->set_img(create_scaled_bitmap("flow_rate_calibration_coarse_result_CN", nullptr, 350));
|
||||
m_picture_panel->set_bmp(ScalableBitmap(this, "flow_rate_calibration_coarse_result_CN", 350));
|
||||
} else {
|
||||
m_picture_panel->set_img(create_scaled_bitmap("flow_rate_calibration_coarse_result", nullptr, 350));
|
||||
m_picture_panel->set_bmp(ScalableBitmap(this, "flow_rate_calibration_coarse_result", 350));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1324,6 +1373,51 @@ bool CalibrationFlowCoarseSavePage::Show(bool show) {
|
|||
return wxPanel::Show(show);
|
||||
}
|
||||
|
||||
void CalibrationFlowCoarseSavePage::on_cali_start_job()
|
||||
{
|
||||
m_sending_panel->reset();
|
||||
m_sending_panel->Show();
|
||||
m_action_panel->enable_button(CaliPageActionType::CALI_ACTION_FLOW_CALI_STAGE_2, false);
|
||||
m_action_panel->show_button(CaliPageActionType::CALI_ACTION_FLOW_CALI_STAGE_2, false);
|
||||
Layout();
|
||||
Fit();
|
||||
}
|
||||
|
||||
void CalibrationFlowCoarseSavePage::on_cali_finished_job()
|
||||
{
|
||||
m_sending_panel->reset();
|
||||
m_sending_panel->Show(false);
|
||||
m_action_panel->enable_button(CaliPageActionType::CALI_ACTION_FLOW_CALI_STAGE_2, true);
|
||||
m_action_panel->show_button(CaliPageActionType::CALI_ACTION_FLOW_CALI_STAGE_2, true);
|
||||
Layout();
|
||||
Fit();
|
||||
}
|
||||
|
||||
void CalibrationFlowCoarseSavePage::on_cali_cancel_job()
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(info) << "CalibrationWizard::print_job: enter canceled";
|
||||
if (CalibUtils::print_job) {
|
||||
if (CalibUtils::print_job->is_running()) {
|
||||
BOOST_LOG_TRIVIAL(info) << "calibration_print_job: canceled";
|
||||
CalibUtils::print_job->cancel();
|
||||
}
|
||||
CalibUtils::print_job->join();
|
||||
}
|
||||
|
||||
m_sending_panel->reset();
|
||||
m_sending_panel->Show(false);
|
||||
m_action_panel->enable_button(CaliPageActionType::CALI_ACTION_FLOW_CALI_STAGE_2, true);
|
||||
m_action_panel->show_button(CaliPageActionType::CALI_ACTION_FLOW_CALI_STAGE_2, true);
|
||||
Layout();
|
||||
Fit();
|
||||
}
|
||||
|
||||
void CalibrationFlowCoarseSavePage::msw_rescale()
|
||||
{
|
||||
CalibrationWizardPage::msw_rescale();
|
||||
m_picture_panel->msw_rescale();
|
||||
}
|
||||
|
||||
CalibrationFlowFineSavePage::CalibrationFlowFineSavePage(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
|
||||
: CalibrationCommonSavePage(parent, id, pos, size, style)
|
||||
{
|
||||
|
|
@ -1406,9 +1500,9 @@ void CalibrationFlowFineSavePage::create_page(wxWindow* parent)
|
|||
|
||||
void CalibrationFlowFineSavePage::set_save_img() {
|
||||
if (wxGetApp().app_config->get_language_code() == "zh-cn") {
|
||||
m_picture_panel->set_img(create_scaled_bitmap("flow_rate_calibration_fine_result_CN", nullptr, 350));
|
||||
m_picture_panel->set_bmp(ScalableBitmap(this, "flow_rate_calibration_fine_result_CN", 350));
|
||||
} else {
|
||||
m_picture_panel->set_img(create_scaled_bitmap("flow_rate_calibration_fine_result", nullptr, 350));
|
||||
m_picture_panel->set_bmp(ScalableBitmap(this, "flow_rate_calibration_fine_result", 350));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1456,6 +1550,12 @@ bool CalibrationFlowFineSavePage::Show(bool show) {
|
|||
return wxPanel::Show(show);
|
||||
}
|
||||
|
||||
void CalibrationFlowFineSavePage::msw_rescale()
|
||||
{
|
||||
CalibrationWizardPage::msw_rescale();
|
||||
m_picture_panel->msw_rescale();
|
||||
}
|
||||
|
||||
CalibrationMaxVolumetricSpeedSavePage::CalibrationMaxVolumetricSpeedSavePage(
|
||||
wxWindow *parent,
|
||||
wxWindowID id,
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@ public:
|
|||
void get_value(double& value);
|
||||
void get_save_name(std::string& name);
|
||||
void set_save_name(const std::string& name);
|
||||
void msw_rescale();
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -129,6 +130,8 @@ public:
|
|||
|
||||
virtual bool Show(bool show = true) override;
|
||||
|
||||
void msw_rescale();
|
||||
|
||||
protected:
|
||||
wxBoxSizer* m_top_sizer;
|
||||
Label * m_complete_text;
|
||||
|
|
@ -155,6 +158,10 @@ public:
|
|||
|
||||
bool get_result(float* out_k, float* out_n);
|
||||
|
||||
virtual bool Show(bool show = true) override;
|
||||
|
||||
void msw_rescale();
|
||||
|
||||
protected:
|
||||
wxBoxSizer* m_top_sizer;
|
||||
Label * m_complete_text;
|
||||
|
|
@ -185,12 +192,14 @@ public:
|
|||
|
||||
virtual bool Show(bool show = true) override;
|
||||
|
||||
void msw_rescale() override;
|
||||
|
||||
protected:
|
||||
CaliPageStepGuide* m_step_panel { nullptr };
|
||||
CaliPASaveAutoPanel* m_auto_panel { nullptr };
|
||||
CaliPASaveManualPanel* m_manual_panel { nullptr };
|
||||
CaliPASaveP1PPanel* m_p1p_panel{ nullptr };
|
||||
PAPageHelpPanel* m_help_panel;
|
||||
PAPageHelpPanel* m_help_panel{ nullptr };
|
||||
|
||||
CaliSaveStyle m_save_style;
|
||||
};
|
||||
|
|
@ -209,6 +218,8 @@ public:
|
|||
bool is_all_failed() { return m_is_all_failed; }
|
||||
|
||||
virtual bool Show(bool show = true) override;
|
||||
|
||||
void msw_rescale() override;
|
||||
|
||||
protected:
|
||||
CaliPageStepGuide* m_step_panel{ nullptr };
|
||||
|
|
@ -237,6 +248,20 @@ public:
|
|||
|
||||
virtual bool Show(bool show = true) override;
|
||||
|
||||
void update_print_error_info(int code, const std::string& msg, const std::string& extra) { m_sending_panel->update_print_error_info(code, msg, extra); }
|
||||
|
||||
void on_cali_start_job();
|
||||
|
||||
void on_cali_finished_job();
|
||||
|
||||
void on_cali_cancel_job();
|
||||
|
||||
std::shared_ptr<ProgressIndicator> get_sending_progress_bar() {
|
||||
return m_sending_panel->get_sending_progress_bar();
|
||||
}
|
||||
|
||||
void msw_rescale() override;
|
||||
|
||||
protected:
|
||||
CaliPageStepGuide* m_step_panel{ nullptr };
|
||||
CaliPagePicture* m_picture_panel;
|
||||
|
|
@ -249,6 +274,8 @@ protected:
|
|||
bool m_skip_fine_calibration = false;
|
||||
float m_curr_flow_ratio;
|
||||
float m_coarse_flow_ratio;
|
||||
|
||||
CaliPageSendingPanel* m_sending_panel{ nullptr };
|
||||
};
|
||||
|
||||
class CalibrationFlowFineSavePage : public CalibrationCommonSavePage
|
||||
|
|
@ -267,6 +294,8 @@ public:
|
|||
|
||||
virtual bool Show(bool show = true) override;
|
||||
|
||||
void msw_rescale() override;
|
||||
|
||||
protected:
|
||||
CaliPageStepGuide* m_step_panel{ nullptr };
|
||||
CaliPagePicture* m_picture_panel;
|
||||
|
|
|
|||
|
|
@ -35,30 +35,37 @@ void CalibrationStartPage::create_about(wxWindow* parent, wxString title, wxStri
|
|||
|
||||
void CalibrationStartPage::create_bitmap(wxWindow* parent, const wxBitmap& before_img, const wxBitmap& after_img)
|
||||
{
|
||||
m_images_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
m_before_bmp = new wxStaticBitmap(parent, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0);
|
||||
if (!m_before_bmp)
|
||||
m_before_bmp = new wxStaticBitmap(parent, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_before_bmp->SetBitmap(before_img);
|
||||
m_images_sizer->Add(m_before_bmp, 0, wxALL, 0);
|
||||
m_images_sizer->AddSpacer(FromDIP(20));
|
||||
m_after_bmp = new wxStaticBitmap(parent, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0);
|
||||
if (!m_after_bmp)
|
||||
m_after_bmp = new wxStaticBitmap(parent, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_after_bmp->SetBitmap(after_img);
|
||||
m_images_sizer->Add(m_after_bmp, 0, wxALL, 0);
|
||||
if (!m_images_sizer) {
|
||||
m_images_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
m_images_sizer->Add(m_before_bmp, 0, wxALL, 0);
|
||||
m_images_sizer->AddSpacer(FromDIP(20));
|
||||
m_images_sizer->Add(m_after_bmp, 0, wxALL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void CalibrationStartPage::create_bitmap(wxWindow* parent, std::string before_img, std::string after_img)
|
||||
{
|
||||
wxBitmap before_bmp = create_scaled_bitmap(before_img, nullptr, 350);
|
||||
wxBitmap after_bmp = create_scaled_bitmap(after_img, nullptr, 350);
|
||||
wxBitmap before_bmp = create_scaled_bitmap(before_img, this, 350);
|
||||
wxBitmap after_bmp = create_scaled_bitmap(after_img, this, 350);
|
||||
|
||||
create_bitmap(parent, before_bmp, after_bmp);
|
||||
}
|
||||
|
||||
void CalibrationStartPage::create_bitmap(wxWindow* parent, std::string img) {
|
||||
wxBitmap before_bmp = create_scaled_bitmap(img, nullptr, 350);
|
||||
m_images_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
m_bmp_intro = new wxStaticBitmap(parent, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0);
|
||||
wxBitmap before_bmp = create_scaled_bitmap(img, this, 350);
|
||||
if (!m_bmp_intro)
|
||||
m_bmp_intro = new wxStaticBitmap(parent, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_bmp_intro->SetBitmap(before_bmp);
|
||||
m_images_sizer->Add(m_bmp_intro, 0, wxALL, 0);
|
||||
if (!m_images_sizer) {
|
||||
m_images_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
m_images_sizer->Add(m_bmp_intro, 0, wxALL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
CalibrationPAStartPage::CalibrationPAStartPage(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
|
||||
|
|
@ -97,7 +104,7 @@ void CalibrationPAStartPage::create_page(wxWindow* parent)
|
|||
m_top_sizer->Add(m_images_sizer, 0, wxALL, 0);
|
||||
m_top_sizer->AddSpacer(PRESET_GAP);
|
||||
|
||||
PAPageHelpPanel* m_help_panel = new PAPageHelpPanel(parent, false);
|
||||
m_help_panel = new PAPageHelpPanel(parent, false);
|
||||
m_top_sizer->Add(m_help_panel, 0, wxALL, 0);
|
||||
m_top_sizer->AddSpacer(PRESET_GAP);
|
||||
|
||||
|
|
@ -169,6 +176,17 @@ void CalibrationPAStartPage::on_device_connected(MachineObject* obj)
|
|||
}
|
||||
}
|
||||
|
||||
void CalibrationPAStartPage::msw_rescale()
|
||||
{
|
||||
CalibrationWizardPage::msw_rescale();
|
||||
m_help_panel->msw_rescale();
|
||||
if (wxGetApp().app_config->get_language_code() == "zh-cn") {
|
||||
create_bitmap(this, "cali_page_before_pa_CN", "cali_page_after_pa_CN");
|
||||
} else {
|
||||
create_bitmap(this, "cali_page_before_pa", "cali_page_after_pa");
|
||||
}
|
||||
}
|
||||
|
||||
CalibrationFlowRateStartPage::CalibrationFlowRateStartPage(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
|
||||
: CalibrationStartPage(parent, id, pos, size, style)
|
||||
{
|
||||
|
|
@ -291,6 +309,16 @@ void CalibrationFlowRateStartPage::on_device_connected(MachineObject* obj)
|
|||
}
|
||||
}
|
||||
|
||||
void CalibrationFlowRateStartPage::msw_rescale()
|
||||
{
|
||||
CalibrationWizardPage::msw_rescale();
|
||||
if (wxGetApp().app_config->get_language_code() == "zh-cn") {
|
||||
create_bitmap(this, "cali_page_flow_introduction_CN");
|
||||
} else {
|
||||
create_bitmap(this, "cali_page_flow_introduction");
|
||||
}
|
||||
}
|
||||
|
||||
CalibrationMaxVolumetricSpeedStartPage::CalibrationMaxVolumetricSpeedStartPage(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
|
||||
: CalibrationStartPage(parent, id, pos, size, style)
|
||||
{
|
||||
|
|
@ -343,4 +371,14 @@ void CalibrationMaxVolumetricSpeedStartPage::create_page(wxWindow* parent)
|
|||
m_top_sizer->Add(m_action_panel, 0, wxEXPAND, 0);
|
||||
}
|
||||
|
||||
void CalibrationMaxVolumetricSpeedStartPage::msw_rescale()
|
||||
{
|
||||
CalibrationWizardPage::msw_rescale();
|
||||
if (wxGetApp().app_config->get_language_code() == "zh-cn") {
|
||||
create_bitmap(this, "cali_page_before_pa_CN", "cali_page_after_pa_CN");
|
||||
} else {
|
||||
create_bitmap(this, "cali_page_before_pa", "cali_page_after_pa");
|
||||
}
|
||||
}
|
||||
|
||||
}}
|
||||
|
|
@ -19,15 +19,16 @@ public:
|
|||
protected:
|
||||
CalibMode m_cali_mode;
|
||||
|
||||
wxBoxSizer* m_top_sizer;
|
||||
wxBoxSizer* m_images_sizer;
|
||||
Label* m_when_title;
|
||||
Label* m_when_content;
|
||||
Label* m_about_title;
|
||||
Label* m_about_content;
|
||||
wxBoxSizer* m_top_sizer{ nullptr };
|
||||
wxBoxSizer* m_images_sizer{ nullptr };
|
||||
Label* m_when_title{ nullptr };
|
||||
Label* m_when_content{ nullptr };
|
||||
Label* m_about_title{ nullptr };
|
||||
Label* m_about_content{ nullptr };
|
||||
wxStaticBitmap* m_before_bmp{ nullptr };
|
||||
wxStaticBitmap* m_after_bmp{ nullptr };
|
||||
wxStaticBitmap* m_bmp_intro{ nullptr };
|
||||
PAPageHelpPanel* m_help_panel{ nullptr };
|
||||
|
||||
void create_when(wxWindow* parent, wxString title, wxString content);
|
||||
void create_about(wxWindow* parent, wxString title, wxString content);
|
||||
|
|
@ -49,6 +50,7 @@ public:
|
|||
|
||||
void on_reset_page();
|
||||
void on_device_connected(MachineObject* obj);
|
||||
void msw_rescale() override;
|
||||
};
|
||||
|
||||
class CalibrationFlowRateStartPage : public CalibrationStartPage
|
||||
|
|
@ -63,6 +65,7 @@ public:
|
|||
void create_page(wxWindow* parent);
|
||||
void on_reset_page();
|
||||
void on_device_connected(MachineObject* obj);
|
||||
void msw_rescale() override;
|
||||
};
|
||||
|
||||
class CalibrationMaxVolumetricSpeedStartPage : public CalibrationStartPage
|
||||
|
|
@ -75,6 +78,7 @@ public:
|
|||
long style = wxTAB_TRAVERSAL);
|
||||
|
||||
void create_page(wxWindow* parent);
|
||||
void msw_rescale() override;
|
||||
};
|
||||
|
||||
}} // namespace Slic3r::GUI
|
||||
|
|
|
|||
|
|
@ -260,7 +260,7 @@ void CameraPopup::check_func_supported(MachineObject *obj2)
|
|||
if (m_obj == nullptr)
|
||||
return;
|
||||
// function supported
|
||||
if (m_obj->is_function_supported(PrinterFunction::FUNC_RECORDING) && m_obj->has_ipcam) {
|
||||
if (m_obj->has_ipcam) {
|
||||
m_text_recording->Show();
|
||||
m_switch_recording->Show();
|
||||
} else {
|
||||
|
|
@ -268,7 +268,7 @@ void CameraPopup::check_func_supported(MachineObject *obj2)
|
|||
m_switch_recording->Hide();
|
||||
}
|
||||
|
||||
if (m_obj->is_function_supported(PrinterFunction::FUNC_VIRTUAL_CAMERA) && m_obj->has_ipcam) {
|
||||
if (m_obj->virtual_camera && m_obj->has_ipcam) {
|
||||
m_text_vcamera->Show();
|
||||
m_switch_vcamera->Show();
|
||||
if (is_vcamera_show) {
|
||||
|
|
@ -282,7 +282,7 @@ void CameraPopup::check_func_supported(MachineObject *obj2)
|
|||
link_underline->Hide();
|
||||
}
|
||||
|
||||
allow_alter_resolution = (m_obj->is_function_supported(PrinterFunction::FUNC_ALTER_RESOLUTION) && m_obj->has_ipcam);
|
||||
allow_alter_resolution = ( (m_obj->camera_resolution_supported.size() > 1?true:false) && m_obj->has_ipcam);
|
||||
|
||||
//check u2 version
|
||||
DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
|
||||
|
|
|
|||
|
|
@ -409,8 +409,8 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con
|
|||
if (config->opt_bool("enable_support")) {
|
||||
auto support_type = config->opt_enum<SupportType>("support_type");
|
||||
auto support_style = config->opt_enum<SupportMaterialStyle>("support_style");
|
||||
std::set<int> enum_set_normal = {0, 1, 2};
|
||||
std::set<int> enum_set_tree = {0, 3, 4, 5, 6};
|
||||
std::set<int> enum_set_normal = { smsDefault, smsGrid, smsSnug };
|
||||
std::set<int> enum_set_tree = { smsDefault, smsTreeSlim, smsTreeStrong, smsTreeHybrid, smsOrganic };
|
||||
auto & set = is_tree(support_type) ? enum_set_tree : enum_set_normal;
|
||||
if (set.find(support_style) == set.end()) {
|
||||
DynamicPrintConfig new_conf = *config;
|
||||
|
|
@ -490,7 +490,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
|
|||
|
||||
bool have_perimeters = config->opt_int("wall_loops") > 0;
|
||||
for (auto el : { "extra_perimeters_on_overhangs", "ensure_vertical_shell_thickness", "detect_thin_wall", "detect_overhang_wall",
|
||||
"seam_position", "staggered_inner_seams", "wall_infill_order", "outer_wall_line_width",
|
||||
"seam_position", "staggered_inner_seams", "wall_sequence", "outer_wall_line_width",
|
||||
"inner_wall_speed", "outer_wall_speed", "small_perimeter_speed", "small_perimeter_threshold" })
|
||||
toggle_field(el, have_perimeters);
|
||||
|
||||
|
|
@ -571,8 +571,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
|
|||
"support_base_pattern_spacing", "support_expansion", "support_angle",
|
||||
"support_interface_pattern", "support_interface_top_layers", "support_interface_bottom_layers",
|
||||
"bridge_no_support", "max_bridge_length", "support_top_z_distance", "support_bottom_z_distance",
|
||||
//BBS: add more support params to dependent of enable_support
|
||||
"support_type", "support_on_build_plate_only", "support_critical_regions_only",
|
||||
"support_type", "support_on_build_plate_only", "support_critical_regions_only","support_interface_not_for_body",
|
||||
"support_object_xy_distance"/*, "independent_support_layer_height"*/})
|
||||
toggle_field(el, have_support_material);
|
||||
toggle_field("support_threshold_angle", have_support_material && is_auto(support_type));
|
||||
|
|
@ -663,7 +662,9 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
|
|||
toggle_line("slowdown_for_curled_perimeters",!has_overhang_speed_classic && has_overhang_speed);
|
||||
|
||||
toggle_line("flush_into_objects", !is_global_config);
|
||||
|
||||
|
||||
toggle_line("support_interface_not_for_body",config->opt_int("support_interface_filament")&&!config->opt_int("support_filament"));
|
||||
|
||||
bool has_fuzzy_skin = (config->opt_enum<FuzzySkinType>("fuzzy_skin") != FuzzySkinType::None);
|
||||
for (auto el : { "fuzzy_skin_thickness", "fuzzy_skin_point_distance", "fuzzy_skin_first_layer"})
|
||||
toggle_line(el, has_fuzzy_skin);
|
||||
|
|
|
|||
|
|
@ -118,32 +118,22 @@ void ConnectPrinterDialog::init_bitmap()
|
|||
std::string language = config->get("language");
|
||||
|
||||
if (m_obj) {
|
||||
if (m_obj->printer_type == "C11" || m_obj->printer_type == "C12") {
|
||||
m_diagram_bmp = create_scaled_bitmap("input_accesscode_help2", nullptr, 190);
|
||||
}
|
||||
else if (m_obj->printer_type == "BL-P001" || m_obj->printer_type == "BL-P002" || m_obj->printer_type == "C13") {
|
||||
if (language == "zh_CN") {
|
||||
m_diagram_bmp = create_scaled_bitmap("input_access_code_cn", nullptr, 190);
|
||||
}
|
||||
else {
|
||||
m_diagram_bmp = create_scaled_bitmap("input_access_code_en", nullptr, 190);
|
||||
}
|
||||
}
|
||||
else if (m_obj->printer_type == "N1") {
|
||||
if (language == "zh_CN") {
|
||||
m_diagram_bmp = create_scaled_bitmap("input_access_code_n1_cn", nullptr, 250);
|
||||
}
|
||||
else {
|
||||
m_diagram_bmp = create_scaled_bitmap("input_access_code_n1_en", nullptr, 250);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
std::string img_str = DeviceManager::get_printer_diagram_img(m_obj->printer_type);
|
||||
if(img_str.empty()){img_str = "input_access_code_x1"; }
|
||||
|
||||
if (language == "zh_CN") {
|
||||
m_diagram_bmp = create_scaled_bitmap("input_access_code_cn", nullptr, 190);
|
||||
m_diagram_bmp = create_scaled_bitmap(img_str+"_cn", nullptr, 190);
|
||||
}
|
||||
else {
|
||||
m_diagram_bmp = create_scaled_bitmap("input_access_code_en", nullptr, 190);
|
||||
m_diagram_bmp = create_scaled_bitmap(img_str+"_en", nullptr, 190);
|
||||
}
|
||||
}
|
||||
else{
|
||||
if (language == "zh_CN") {
|
||||
m_diagram_bmp = create_scaled_bitmap("input_access_code_x1_cn", nullptr, 190);
|
||||
}
|
||||
else {
|
||||
m_diagram_bmp = create_scaled_bitmap("input_access_code_x1_en", nullptr, 190);
|
||||
}
|
||||
}
|
||||
m_diagram_img = m_diagram_bmp.ConvertToImage();
|
||||
|
|
|
|||
4993
src/slic3r/GUI/CreatePresetsDialog.cpp
Normal file
4993
src/slic3r/GUI/CreatePresetsDialog.cpp
Normal file
File diff suppressed because it is too large
Load diff
398
src/slic3r/GUI/CreatePresetsDialog.hpp
Normal file
398
src/slic3r/GUI/CreatePresetsDialog.hpp
Normal file
|
|
@ -0,0 +1,398 @@
|
|||
#ifndef slic3r_CreatePresetsDialog_hpp_
|
||||
#define slic3r_CreatePresetsDialog_hpp_
|
||||
|
||||
#include "libslic3r/Preset.hpp"
|
||||
#include "wxExtensions.hpp"
|
||||
#include "GUI_Utils.hpp"
|
||||
#include "Widgets/Label.hpp"
|
||||
#include "Widgets/TextInput.hpp"
|
||||
#include "Widgets/Button.hpp"
|
||||
#include "Widgets/RadioBox.hpp"
|
||||
#include "Widgets/CheckBox.hpp"
|
||||
#include "Widgets/ComboBox.hpp"
|
||||
#include "miniz.h"
|
||||
#include "ParamsDialog.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
class CreateFilamentPresetDialog : public DPIDialog
|
||||
{
|
||||
public:
|
||||
CreateFilamentPresetDialog(wxWindow *parent);
|
||||
~CreateFilamentPresetDialog();
|
||||
|
||||
protected:
|
||||
enum FilamentOptionType {
|
||||
VENDOR = 0,
|
||||
TYPE,
|
||||
SERIAL,
|
||||
FILAMENT_PRESET,
|
||||
PRESET_FOR_PRINTER,
|
||||
FILAMENT_NAME_COUNT
|
||||
};
|
||||
|
||||
protected:
|
||||
void on_dpi_changed(const wxRect &suggested_rect) override;
|
||||
bool is_check_box_selected();
|
||||
wxBoxSizer *create_item(FilamentOptionType option_type);
|
||||
wxBoxSizer *create_vendor_item();
|
||||
wxBoxSizer *create_type_item();
|
||||
wxBoxSizer *create_serial_item();
|
||||
wxBoxSizer *create_filament_preset_item();
|
||||
wxBoxSizer *create_filament_preset_for_printer_item();
|
||||
wxBoxSizer *create_button_item();
|
||||
|
||||
private:
|
||||
void clear_filament_preset_map();
|
||||
wxArrayString get_filament_preset_choices();
|
||||
wxBoxSizer * create_radio_item(wxString title, wxWindow *parent, wxString tooltip, std::vector<std::pair<RadioBox *, wxString>> &radiobox_list);
|
||||
void select_curr_radiobox(std::vector<std::pair<RadioBox *, wxString>> &radiobox_list, int btn_idx);
|
||||
wxString curr_create_filament_type();
|
||||
void get_filament_presets_by_machine();
|
||||
void get_all_filament_presets();
|
||||
void get_all_visible_printer_name();
|
||||
void update_dialog_size();
|
||||
template<typename T>
|
||||
void sort_printer_by_nozzle(std::vector<std::pair<std::string, T>> &printer_name_to_filament_preset);
|
||||
|
||||
private:
|
||||
struct CreateType
|
||||
{
|
||||
wxString base_filament;
|
||||
wxString base_filament_preset;
|
||||
};
|
||||
|
||||
private:
|
||||
std::vector<std::pair<RadioBox *, wxString>> m_create_type_btns;
|
||||
std::unordered_map<::CheckBox *, std::pair<std::string, Preset *>> m_filament_preset;
|
||||
std::unordered_map<::CheckBox *, std::pair<std::string, Preset *>> m_machint_filament_preset;
|
||||
std::unordered_map<std::string, std::vector<Preset *>> m_filament_choice_map;
|
||||
std::unordered_map<wxString, std::string> m_public_name_to_filament_id_map;
|
||||
std::unordered_map<std::string, Preset *> m_all_presets_map;
|
||||
std::set<std::string> m_visible_printers;
|
||||
CreateType m_create_type;
|
||||
Button * m_button_create = nullptr;
|
||||
Button * m_button_cancel = nullptr;
|
||||
ComboBox * m_filament_vendor_combobox = nullptr;
|
||||
::CheckBox * m_can_not_find_vendor_checkbox = nullptr;
|
||||
ComboBox * m_filament_type_combobox = nullptr;
|
||||
ComboBox * m_exist_vendor_combobox = nullptr;
|
||||
ComboBox * m_filament_preset_combobox = nullptr;
|
||||
TextInput * m_filament_custom_vendor_input = nullptr;
|
||||
wxGridSizer * m_filament_presets_sizer = nullptr;
|
||||
wxPanel * m_filament_preset_panel = nullptr;
|
||||
wxScrolledWindow * m_scrolled_preset_panel = nullptr;
|
||||
TextInput * m_filament_serial_input = nullptr;
|
||||
wxBoxSizer * m_scrolled_sizer = nullptr;
|
||||
wxStaticText * m_filament_preset_text = nullptr;
|
||||
|
||||
};
|
||||
|
||||
class CreatePrinterPresetDialog : public DPIDialog
|
||||
{
|
||||
public:
|
||||
CreatePrinterPresetDialog(wxWindow *parent);
|
||||
~CreatePrinterPresetDialog();
|
||||
|
||||
protected:
|
||||
void on_dpi_changed(const wxRect &suggested_rect) override;
|
||||
|
||||
/******************************************************** Control Construction *****************************************************/
|
||||
wxBoxSizer *create_step_switch_item();
|
||||
//Create Printer Page1
|
||||
void create_printer_page1(wxWindow *parent);
|
||||
wxBoxSizer *create_type_item(wxWindow *parent);
|
||||
wxBoxSizer *create_printer_item(wxWindow *parent);
|
||||
wxBoxSizer *create_nozzle_diameter_item(wxWindow *parent);
|
||||
wxBoxSizer *create_bed_shape_item(wxWindow *parent);
|
||||
wxBoxSizer *create_bed_size_item(wxWindow *parent);
|
||||
wxBoxSizer *create_origin_item(wxWindow *parent);
|
||||
wxBoxSizer *create_hot_bed_stl_item(wxWindow *parent);
|
||||
wxBoxSizer *create_hot_bed_svg_item(wxWindow *parent);
|
||||
wxBoxSizer *create_max_print_height_item(wxWindow *parent);
|
||||
wxBoxSizer *create_page1_btns_item(wxWindow *parent);
|
||||
//Improt Presets Page2
|
||||
void create_printer_page2(wxWindow *parent);
|
||||
wxBoxSizer *create_printer_preset_item(wxWindow *parent);
|
||||
wxBoxSizer *create_presets_item(wxWindow *parent);
|
||||
wxBoxSizer *create_presets_template_item(wxWindow *parent);
|
||||
wxBoxSizer *create_page2_btns_item(wxWindow *parent);
|
||||
|
||||
void show_page1();
|
||||
void show_page2();
|
||||
|
||||
/********************************************************** Data Interaction *******************************************************/
|
||||
bool data_init();
|
||||
void set_current_visible_printer();
|
||||
void select_curr_radiobox(std::vector<std::pair<RadioBox *, wxString>> &radiobox_list, int btn_idx);
|
||||
void select_all_preset_template(std::vector<std::pair<::CheckBox *, Preset *>> &preset_templates);
|
||||
void deselect_all_preset_template(std::vector<std::pair<::CheckBox *, Preset *>> &preset_templates);
|
||||
void update_presets_list(bool jast_template = false);
|
||||
void on_preset_model_value_change(wxCommandEvent &e);
|
||||
void clear_preset_combobox();
|
||||
bool save_printable_area_config(Preset *preset);
|
||||
bool check_printable_area();
|
||||
bool validate_input_valid();
|
||||
void load_texture();
|
||||
void load_model_stl();
|
||||
bool load_system_and_user_presets_with_curr_model(PresetBundle &temp_preset_bundle, bool just_template = false);
|
||||
void generate_process_presets_data(std::vector<Preset const *> presets, std::string nozzle);
|
||||
void update_preset_list_size();
|
||||
wxArrayString printer_preset_sort_with_nozzle_diameter(const VendorProfile &vendor_profile, float nozzle_diameter);
|
||||
|
||||
wxBoxSizer *create_radio_item(wxString title, wxWindow *parent, wxString tooltip, std::vector<std::pair<RadioBox *, wxString>> &radiobox_list);
|
||||
|
||||
wxString curr_create_preset_type();
|
||||
wxString curr_create_printer_type();
|
||||
|
||||
private:
|
||||
struct CreatePrinterType
|
||||
{
|
||||
wxString create_printer;
|
||||
wxString create_nozzle;
|
||||
wxString base_template;
|
||||
wxString base_curr_printer;
|
||||
};
|
||||
|
||||
CreatePrinterType m_create_type;
|
||||
std::vector<std::pair<RadioBox *, wxString>> m_create_type_btns;
|
||||
std::vector<std::pair<RadioBox *, wxString>> m_create_presets_btns;
|
||||
std::vector<std::pair<::CheckBox *, Preset *>> m_filament_preset;
|
||||
std::vector<std::pair<::CheckBox *, Preset *>> m_process_preset;
|
||||
std::unordered_map<std::string, std::shared_ptr<Preset>> m_printer_name_to_preset;
|
||||
VendorProfile m_printer_preset_vendor_selected;
|
||||
Slic3r::VendorProfile::PrinterModel m_printer_preset_model_selected;
|
||||
bool rewritten = false;
|
||||
Preset * m_printer_preset = nullptr;
|
||||
wxStaticBitmap * m_step_1 = nullptr;
|
||||
wxStaticBitmap * m_step_2 = nullptr;
|
||||
Button * m_button_OK = nullptr;
|
||||
Button * m_button_create = nullptr;
|
||||
Button * m_button_page1_cancel = nullptr;
|
||||
Button * m_button_page2_cancel = nullptr;
|
||||
Button * m_button_page2_back = nullptr;
|
||||
Button * m_button_bed_stl = nullptr;
|
||||
Button * m_button_bed_svg = nullptr;
|
||||
wxScrolledWindow * m_page1 = nullptr;
|
||||
wxPanel * m_page2 = nullptr;
|
||||
wxScrolledWindow * m_scrolled_preset_window = nullptr;
|
||||
wxBoxSizer * m_scrooled_preset_sizer = nullptr;
|
||||
ComboBox * m_select_vendor = nullptr;
|
||||
ComboBox * m_select_model = nullptr;
|
||||
ComboBox * m_select_printer = nullptr;
|
||||
::CheckBox * m_can_not_find_vendor_combox = nullptr;
|
||||
wxStaticText * m_can_not_find_vendor_text = nullptr;
|
||||
wxTextCtrl * m_custom_vendor_text_ctrl = nullptr;
|
||||
wxTextCtrl * m_custom_model_text_ctrl = nullptr;
|
||||
ComboBox * m_nozzle_diameter = nullptr;
|
||||
ComboBox * m_printer_vendor = nullptr;
|
||||
ComboBox * m_printer_model = nullptr;
|
||||
TextInput * m_bed_size_x_input = nullptr;
|
||||
TextInput * m_bed_size_y_input = nullptr;
|
||||
TextInput * m_bed_origin_x_input = nullptr;
|
||||
TextInput * m_bed_origin_y_input = nullptr;
|
||||
TextInput * m_print_height_input = nullptr;
|
||||
wxGridSizer * m_filament_preset_template_sizer = nullptr;
|
||||
wxGridSizer * m_process_preset_template_sizer = nullptr;
|
||||
wxPanel * m_filament_preset_panel = nullptr;
|
||||
wxPanel * m_process_preset_panel = nullptr;
|
||||
wxPanel * m_preset_template_panel = nullptr;
|
||||
wxBoxSizer * m_filament_sizer = nullptr;
|
||||
wxPanel * m_printer_info_panel = nullptr;
|
||||
wxBoxSizer * m_page1_sizer = nullptr;
|
||||
wxBoxSizer * m_printer_info_sizer = nullptr;
|
||||
wxBoxSizer * m_page2_sizer = nullptr;
|
||||
wxStaticText * m_upload_stl_tip_text = nullptr;
|
||||
wxStaticText * m_upload_svg_tip_text = nullptr;
|
||||
std::string m_custom_texture;
|
||||
std::string m_custom_model;
|
||||
};
|
||||
|
||||
enum SuccessType {
|
||||
PRINTER = 0,
|
||||
FILAMENT
|
||||
};
|
||||
|
||||
class CreatePresetSuccessfulDialog : public DPIDialog
|
||||
{
|
||||
public:
|
||||
CreatePresetSuccessfulDialog(wxWindow *parent, const SuccessType &create_success_type);
|
||||
~CreatePresetSuccessfulDialog();
|
||||
|
||||
protected:
|
||||
void on_dpi_changed(const wxRect &suggested_rect) override;
|
||||
|
||||
private:
|
||||
Button *m_button_ok = nullptr;
|
||||
Button *m_button_cancel = nullptr;
|
||||
};
|
||||
|
||||
class ExportConfigsDialog : public DPIDialog
|
||||
{
|
||||
public:
|
||||
ExportConfigsDialog(wxWindow *parent);
|
||||
~ExportConfigsDialog();//to do: delete preset
|
||||
|
||||
protected:
|
||||
|
||||
struct ExportType
|
||||
{
|
||||
wxString preset_bundle;
|
||||
wxString filament_bundle;
|
||||
wxString printer_preset;
|
||||
wxString filament_preset;
|
||||
wxString process_preset;
|
||||
};
|
||||
|
||||
enum ExportCase {
|
||||
INITIALIZE_FAIL = 0,
|
||||
ADD_FILE_FAIL,
|
||||
ADD_BUNDLE_STRUCTURE_FAIL,
|
||||
FINALIZE_FAIL,
|
||||
OPEN_ZIP_WRITTEN_FILE,
|
||||
EXPORT_CANCEL,
|
||||
EXPORT_SUCCESS,
|
||||
CASE_COUNT,
|
||||
};
|
||||
|
||||
private:
|
||||
void data_init();
|
||||
void select_curr_radiobox(std::vector<std::pair<RadioBox *, wxString>> &radiobox_list, int btn_idx);
|
||||
void on_dpi_changed(const wxRect &suggested_rect) override;
|
||||
void show_export_result(const ExportCase &export_case);
|
||||
bool has_check_box_selected();
|
||||
bool preset_is_not_compatible_bbl_printer(Preset *preset);
|
||||
std::string initial_file_path(const wxString &path, const std::string &sub_file_path);
|
||||
std::string initial_file_name(const wxString &path, const std::string file_name);
|
||||
wxBoxSizer *create_export_config_item(wxWindow *parent);
|
||||
wxBoxSizer *create_button_item(wxWindow *parent);
|
||||
wxBoxSizer *create_select_printer(wxWindow *parent);
|
||||
wxBoxSizer *create_radio_item(wxString title, wxWindow *parent, wxString tooltip, std::vector<std::pair<RadioBox *, wxString>> &radiobox_list);
|
||||
int initial_zip_archive(mz_zip_archive &zip_archive, const std::string &file_path);
|
||||
ExportCase save_zip_archive_to_file(mz_zip_archive &zip_archive);
|
||||
ExportCase save_presets_to_zip(const std::string &export_file, const std::vector<std::pair<std::string, std::string>> &config_paths);
|
||||
ExportCase archive_preset_bundle_to_file(const wxString &path);
|
||||
ExportCase archive_filament_bundle_to_file(const wxString &path);
|
||||
ExportCase archive_printer_preset_to_file(const wxString &path);
|
||||
ExportCase archive_filament_preset_to_file(const wxString &path);
|
||||
ExportCase archive_process_preset_to_file(const wxString &path);
|
||||
|
||||
private:
|
||||
std::vector<std::pair<RadioBox *, wxString>> m_export_type_btns;
|
||||
std::vector<std::pair<::CheckBox *, Preset *>> m_preset; // for printer preset bundle,printer preset, process preset export
|
||||
std::vector<std::pair<::CheckBox *, std::string>> m_printer_name; // for filament and peocess preset export, collaborate with m_filament_name_to_presets
|
||||
std::unordered_map<std::string, Preset *> m_printer_presets;//first: printer name, second: printer presets have same printer name
|
||||
std::unordered_map<std::string, std::vector<Preset *>> m_filament_presets;//first: printer name, second: filament presets have same printer name
|
||||
std::unordered_map<std::string, std::vector<Preset *>> m_process_presets;//first: printer name, second: filament presets have same printer name
|
||||
std::unordered_map<std::string, std::vector<std::pair<std::string, Preset *>>> m_filament_name_to_presets;//first: filament name, second presets have same filament name and printer name in vector
|
||||
ExportType m_exprot_type;
|
||||
wxBoxSizer * m_main_sizer = nullptr;
|
||||
wxScrolledWindow * m_scrolled_preset_window = nullptr;
|
||||
wxGridSizer * m_preset_sizer = nullptr;
|
||||
wxPanel * m_presets_window = nullptr;
|
||||
Button * m_button_ok = nullptr;
|
||||
Button * m_button_cancel = nullptr;
|
||||
wxStaticText * m_serial_text = nullptr;
|
||||
};
|
||||
|
||||
class CreatePresetForPrinterDialog : public DPIDialog
|
||||
{
|
||||
public:
|
||||
CreatePresetForPrinterDialog(wxWindow *parent, std::string filament_type, std::string filament_id, std::string filament_vendor, std::string filament_name);
|
||||
~CreatePresetForPrinterDialog();
|
||||
|
||||
private:
|
||||
void on_dpi_changed(const wxRect &suggested_rect) override;
|
||||
void get_visible_printer_and_compatible_filament_presets();
|
||||
wxBoxSizer *create_selected_printer_preset_sizer();
|
||||
wxBoxSizer *create_selected_filament_preset_sizer();
|
||||
wxBoxSizer *create_button_sizer();
|
||||
|
||||
private:
|
||||
std::string m_filament_id;
|
||||
std::string m_filament_name;
|
||||
std::string m_filament_vendor;
|
||||
std::string m_filament_type;
|
||||
std::shared_ptr<PresetBundle> m_preset_bundle;
|
||||
std::string m_filamnt_type;
|
||||
ComboBox * m_selected_printer = nullptr;
|
||||
ComboBox * m_selected_filament = nullptr;
|
||||
Button * m_ok_btn = nullptr;
|
||||
Button * m_cancel_btn = nullptr;
|
||||
std::unordered_map<wxString, std::shared_ptr<Preset>> filament_choice_to_filament_preset;
|
||||
std::unordered_map<std::string, std::vector<std::shared_ptr<Preset>>> m_printer_compatible_filament_presets; // need be used when add presets
|
||||
|
||||
};
|
||||
|
||||
class EditFilamentPresetDialog;
|
||||
|
||||
class PresetTree
|
||||
{
|
||||
public:
|
||||
PresetTree(EditFilamentPresetDialog *dialog);
|
||||
|
||||
wxPanel *get_preset_tree(std::pair<std::string, std::vector<std::shared_ptr<Preset>>> printer_and_presets);
|
||||
|
||||
private:
|
||||
wxPanel *get_root_item(wxPanel *parent, const std::string &printer_name);
|
||||
|
||||
wxPanel *get_child_item(wxPanel *parent, std::shared_ptr<Preset> preset, std::string printer_name, int preset_index, bool is_last = false);
|
||||
|
||||
void delete_preset(std::string printer_name, int need_delete_preset_index);
|
||||
|
||||
void edit_preset(std::string printer_name, int need_edit_preset_index);
|
||||
|
||||
private:
|
||||
EditFilamentPresetDialog * m_parent_dialog = nullptr;
|
||||
std::pair<std::string, std::vector<std::shared_ptr<Preset>>> m_printer_and_presets;
|
||||
|
||||
};
|
||||
|
||||
class EditFilamentPresetDialog : public DPIDialog
|
||||
{
|
||||
public:
|
||||
EditFilamentPresetDialog(wxWindow *parent, FilamentInfomation *filament_info);
|
||||
~EditFilamentPresetDialog();
|
||||
|
||||
wxPanel *get_preset_tree_panel() { return m_preset_tree_panel; }
|
||||
void set_printer_name(const std::string &printer_name) { m_selected_printer = printer_name; }
|
||||
void set_need_delete_preset_index(int need_delete_preset_index) { m_need_delete_preset_index = need_delete_preset_index; }
|
||||
void set_need_edit_preset_index(int need_edit_preset_index) { m_need_edit_preset_index = need_edit_preset_index; }
|
||||
void delete_preset();
|
||||
void edit_preset();
|
||||
|
||||
private:
|
||||
void on_dpi_changed(const wxRect &suggested_rect) override;
|
||||
bool get_same_filament_id_presets(std::string filament_id);
|
||||
void update_preset_tree();
|
||||
wxBoxSizer *create_filament_basic_info();
|
||||
wxBoxSizer *create_add_filament_btn();
|
||||
wxBoxSizer *create_preset_tree_sizer();
|
||||
wxBoxSizer *create_button_sizer();
|
||||
|
||||
private:
|
||||
PresetTree * m_preset_tree_creater = nullptr;
|
||||
std::string m_filament_id;
|
||||
std::string m_filament_name;
|
||||
std::string m_vendor_name;
|
||||
std::string m_filament_type;
|
||||
std::string m_filament_serial;
|
||||
Button * m_add_filament_btn = nullptr;
|
||||
Button * m_del_filament_btn = nullptr;
|
||||
Button * m_ok_btn = nullptr;
|
||||
wxBoxSizer * m_preset_tree_sizer = nullptr;
|
||||
wxPanel * m_preset_tree_panel = nullptr;
|
||||
wxScrolledWindow * m_preset_tree_window = nullptr;
|
||||
wxBoxSizer * m_main_sizer = nullptr;
|
||||
wxStaticText * m_note_text = nullptr;
|
||||
int m_need_delete_preset_index = -1;
|
||||
int m_need_edit_preset_index = -1;
|
||||
std::string m_selected_printer = "";
|
||||
std::unordered_map<std::string, std::vector<std::shared_ptr<Preset>>> m_printer_compatible_presets;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue