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:
SoftFever 2023-12-01 18:42:45 +08:00 committed by GitHub
parent 2f3ec2ab7d
commit d8dd8fa634
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
420 changed files with 43962 additions and 14438 deletions

View file

@ -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);
}

View file

@ -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)

View file

@ -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,

View file

@ -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) {

View file

@ -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);

View file

@ -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();

View file

@ -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;

View file

@ -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);

View file

@ -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;
}

View file

@ -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();

View file

@ -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);

View file

@ -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

View file

@ -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)

View file

@ -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);
}

View file

@ -50,6 +50,9 @@ protected:
protected:
PACalibResult m_new_result;
TextInput* m_name_value{ nullptr };
TextInput* m_k_value{ nullptr };
};
} // namespace GUI

View file

@ -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)

View file

@ -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);
}
}
}
}

View file

@ -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:

View file

@ -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;
}

View file

@ -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();

View file

@ -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

View file

@ -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);

View file

@ -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();
}
}}
}
}

View file

@ -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;

View file

@ -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"));

View file

@ -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 };

View file

@ -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,

View file

@ -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;

View file

@ -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");
}
}
}}

View file

@ -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

View file

@ -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();

View file

@ -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);

View file

@ -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();

File diff suppressed because it is too large Load diff

View 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

View file

@ -0,0 +1,614 @@
#include "DailyTips.hpp"
#ifndef IMGUI_DEFINE_MATH_OPERATORS
#define IMGUI_DEFINE_MATH_OPERATORS
#endif
#include <imgui/imgui_internal.h>
namespace Slic3r { namespace GUI {
struct DailyTipsData {
std::string main_text;
std::string wiki_url;
std::string img_url;
std::string additional_text; // currently not used
std::string hyper_text; // currently not used
std::function<void(void)> hypertext_callback; // currently not used
};
class DailyTipsDataRenderer {
public:
DailyTipsDataRenderer(DailyTipsLayout layout);
~DailyTipsDataRenderer();
void update_data(const DailyTipsData& data);
void render(const ImVec2& pos, const ImVec2& size) const;
bool has_image() const;
void on_change_color_mode(bool is_dark);
void set_fade_opacity(float opacity);
protected:
void load_texture_from_img_url(const std::string url);
void open_wiki() const;
// relative to the window's upper-left position
void render_img(const ImVec2& start_pos, const ImVec2& size) const;
void render_text(const ImVec2& start_pos, const ImVec2& size) const;
private:
DailyTipsData m_data;
GLTexture* m_texture{ nullptr };
GLTexture* m_placeholder_texture{ nullptr };
bool m_is_dark{ false };
DailyTipsLayout m_layout;
float m_fade_opacity{ 1.0f };
};
DailyTipsDataRenderer::DailyTipsDataRenderer(DailyTipsLayout layout)
: m_layout(layout)
{
}
DailyTipsDataRenderer::~DailyTipsDataRenderer() {
if (m_texture)
delete m_texture;
if (m_placeholder_texture)
delete m_placeholder_texture;
}
void DailyTipsDataRenderer::update_data(const DailyTipsData& data)
{
m_data = data;
load_texture_from_img_url(m_data.img_url);
}
void DailyTipsDataRenderer::load_texture_from_img_url(const std::string url)
{
if (m_texture) {
delete m_texture;
m_texture = nullptr;
}
if (!url.empty()) {
m_texture = new GLTexture();
m_texture->load_from_file(Slic3r::resources_dir() + "/" + url, true, GLTexture::None, false);
}
else {
if (!m_placeholder_texture) {
m_placeholder_texture = new GLTexture();
m_placeholder_texture->load_from_file(Slic3r::resources_dir() + "/images/dailytips_placeholder.png", true, GLTexture::None, false);
}
}
}
void DailyTipsDataRenderer::open_wiki() const
{
if (!m_data.wiki_url.empty())
{
wxGetApp().open_browser_with_warning_dialog(m_data.wiki_url);
}
}
void DailyTipsDataRenderer::render(const ImVec2& pos, const ImVec2& size) const
{
ImGuiWrapper& imgui = *wxGetApp().imgui();
ImGuiWindow* parent_window = ImGui::GetCurrentWindow();
int window_flags = parent_window->Flags;
window_flags &= ~ImGuiWindowFlags_NoScrollbar;
window_flags &= ~ImGuiWindowFlags_NoScrollWithMouse;
std::string name = "##DailyTipsDataRenderer" + std::to_string(parent_window->ID);
ImGui::SetNextWindowPos(pos);
if (ImGui::BeginChild(name.c_str(), size, false, window_flags)) {
if (m_layout == DailyTipsLayout::Vertical) {
ImVec2 img_size = ImVec2(size.x, 9.0f / 16.0f * size.x);
render_img({ 0, 0 }, img_size);
float img_text_gap = ImGui::CalcTextSize("A").y;
render_text({ 0, img_size.y + img_text_gap }, size);
}
if (m_layout == DailyTipsLayout::Horizontal) {
ImVec2 img_size = ImVec2(16.0f / 9.0f * size.y, size.y);
render_img({ 0, 0 }, img_size);
float img_text_gap = ImGui::CalcTextSize("A").y;
render_text({ img_size.x + img_text_gap, 0 }, { size.x - img_size.x - img_text_gap, size.y });
}
}
ImGui::EndChild();
}
bool DailyTipsDataRenderer::has_image() const
{
return !m_data.img_url.empty();
}
void DailyTipsDataRenderer::on_change_color_mode(bool is_dark)
{
m_is_dark = is_dark;
}
void DailyTipsDataRenderer::set_fade_opacity(float opacity)
{
m_fade_opacity = opacity;
}
void DailyTipsDataRenderer::render_img(const ImVec2& start_pos, const ImVec2& size) const
{
if (has_image())
ImGui::Image((ImTextureID)(intptr_t)m_texture->get_id(), size, ImVec2(0, 0), ImVec2(1, 1), m_is_dark ? ImVec4(0.8, 0.8, 0.8, m_fade_opacity) : ImVec4(1, 1, 1, m_fade_opacity));
else {
ImGui::Image((ImTextureID)(intptr_t)m_placeholder_texture->get_id(), size, ImVec2(0, 0), ImVec2(1, 1), m_is_dark ? ImVec4(0.8, 0.8, 0.8, m_fade_opacity) : ImVec4(1, 1, 1, m_fade_opacity));
}
}
void DailyTipsDataRenderer::render_text(const ImVec2& start_pos, const ImVec2& size) const
{
ImGuiWrapper& imgui = *wxGetApp().imgui();
ImGui::PushStyleColor(ImGuiCol_Text, m_is_dark ? ImVec4(1.0f, 1.0f, 1.0f, 0.88f * m_fade_opacity) : ImVec4(38 / 255.0f, 46 / 255.0f, 48 / 255.0f, m_fade_opacity));
// main text
// first line is headline (for hint notification it must be divided by \n)
std::string title_line;
std::string content_lines;
size_t end_pos = m_data.main_text.find_first_of('\n');
if (end_pos != std::string::npos) {
title_line = m_data.main_text.substr(0, end_pos);
title_line = ImGui::ColorMarkerStart + title_line + ImGui::ColorMarkerEnd;
content_lines = m_data.main_text.substr(end_pos + 1);
}
ImGui::SetCursorPos(start_pos);
imgui.text(title_line);
bool is_zh = false;
for (int i = 0; i < content_lines.size() - 1; i += 2) {
if ((content_lines[i] & 0x80) && (content_lines[i + 1] & 0x80))
is_zh = true;
}
if (!is_zh) {
// problem in Chinese with spaces
ImGui::SetCursorPosX(start_pos.x);
imgui.text_wrapped(content_lines, size.x);
}
else {
Label* wrapped_text = new Label(wxGetApp().GetTopWindow());
wrapped_text->Hide();
wrapped_text->SetLabelText(wxString::FromUTF8(content_lines));
wrapped_text->Wrap(size.x + ImGui::CalcTextSize("A").x * 5.0f);
std::string wrapped_content_lines = wrapped_text->GetLabel().ToUTF8().data();
wrapped_text->Destroy();
ImGui::SetCursorPosX(start_pos.x);
imgui.text(wrapped_content_lines);
}
// wiki
if (!m_data.wiki_url.empty()) {
std::string tips_line = _u8L("For more information, please check out Wiki");
std::string wiki_part_text = _u8L("Wiki");
std::string first_part_text = tips_line.substr(0, tips_line.find(wiki_part_text));
ImVec2 wiki_part_size = ImGui::CalcTextSize(wiki_part_text.c_str());
ImVec2 first_part_size = ImGui::CalcTextSize(first_part_text.c_str());
//text
ImGui::SetCursorPosX(start_pos.x);
ImVec2 link_start_pos = ImGui::GetCursorScreenPos();
imgui.text(first_part_text);
ImColor HyperColor = ImColor(31, 142, 234, (int)(255 * m_fade_opacity)).Value;
ImVec2 wiki_part_rect_min = ImVec2(link_start_pos.x + first_part_size.x, link_start_pos.y);
ImVec2 wiki_part_rect_max = wiki_part_rect_min + wiki_part_size;
ImGui::PushStyleColor(ImGuiCol_Text, HyperColor.Value);
ImGui::SetCursorScreenPos(wiki_part_rect_min);
imgui.text(wiki_part_text.c_str());
ImGui::PopStyleColor();
//click behavior
if (ImGui::IsMouseHoveringRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), true))
{
//underline
ImVec2 lineEnd = ImGui::GetItemRectMax();
lineEnd.y -= 2.0f;
ImVec2 lineStart = lineEnd;
lineStart.x = ImGui::GetItemRectMin().x;
ImGui::GetWindowDrawList()->AddLine(lineStart, lineEnd, HyperColor);
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left))
open_wiki();
}
}
ImGui::PopStyleColor();
}
int DailyTipsPanel::uid = 0;
DailyTipsPanel::DailyTipsPanel(bool can_expand, DailyTipsLayout layout)
: m_pos(ImVec2(0, 0)),
m_width(0),
m_height(0),
m_can_expand(can_expand),
m_layout(layout),
m_uid(DailyTipsPanel::uid++),
m_dailytips_renderer(std::make_unique<DailyTipsDataRenderer>(layout))
{
ImGuiWrapper& imgui = *wxGetApp().imgui();
float scale = imgui.get_font_size() / 15.0f;
m_footer_height = 58.0f * scale;
m_is_expanded = wxGetApp().app_config->get("show_hints") == "true";
}
void DailyTipsPanel::set_position(const ImVec2& pos)
{
m_pos = pos;
}
void DailyTipsPanel::set_size(const ImVec2& size)
{
m_width = size.x;
m_height = size.y;
m_content_height = m_height - m_footer_height;
}
void DailyTipsPanel::set_can_expand(bool can_expand)
{
m_can_expand = can_expand;
}
ImVec2 DailyTipsPanel::get_size()
{
return ImVec2(m_width, m_height);
}
void DailyTipsPanel::render()
{
ImGuiWrapper& imgui = *wxGetApp().imgui();
float scale = imgui.get_font_size() / 15.0f;
if (!m_first_enter) {
retrieve_data_from_hint_database(HintDataNavigation::Curr);
m_first_enter = true;
}
push_styles();
if (m_can_expand) {
if (m_is_expanded) {
m_height = m_content_height + m_footer_height;
}
else {
m_height = m_footer_height;
}
}
ImGui::SetNextWindowPos(m_pos);
ImGui::SetNextWindowSizeConstraints(ImVec2(m_width, m_height), ImVec2(m_width, m_height));
int window_flags = ImGuiWindowFlags_NoTitleBar
| ImGuiWindowFlags_NoCollapse
| ImGuiWindowFlags_NoMove
| ImGuiWindowFlags_NoResize
| ImGuiWindowFlags_NoScrollbar
| ImGuiWindowFlags_NoScrollWithMouse;
if (ImGui::BeginChild((std::string("##DailyTipsPanel") + std::to_string(m_uid)).c_str(), ImVec2(m_width, m_height), false, window_flags)) {
if (m_can_expand) {
if (m_is_expanded) {
m_dailytips_renderer->render({ m_pos.x, m_pos.y }, { m_width, m_content_height });
render_controller_buttons({ m_pos.x, m_pos.y + m_height - m_footer_height }, { m_width, m_footer_height });
}
else {
render_controller_buttons({ m_pos.x, m_pos.y + m_height - m_footer_height }, { m_width, m_footer_height });
}
}
else {
m_dailytips_renderer->render({ m_pos.x, m_pos.y }, { m_width, m_content_height });
render_controller_buttons({ m_pos.x, m_pos.y + m_height - m_footer_height }, { m_width, m_footer_height });
}
//{// for debug
// ImVec2 vMin = ImGui::GetWindowContentRegionMin();
// ImVec2 vMax = ImGui::GetWindowContentRegionMax();
// vMin += ImGui::GetWindowPos();
// vMax += ImGui::GetWindowPos();
// ImGui::GetForegroundDrawList()->AddRect(vMin, vMax, IM_COL32(180, 180, 255, 255));
//}
}
ImGui::EndChild();
pop_styles();
}
void DailyTipsPanel::retrieve_data_from_hint_database(HintDataNavigation nav)
{
HintData* hint_data = HintDatabase::get_instance().get_hint(nav);
if (hint_data != nullptr)
{
DailyTipsData data{ hint_data->text,
hint_data->documentation_link,
hint_data->image_url,
hint_data->follow_text,
hint_data->hypertext,
hint_data->callback
};
m_dailytips_renderer->update_data(data);
}
}
void DailyTipsPanel::expand(bool expand)
{
if (!m_can_expand)
return;
m_is_expanded = expand;
wxGetApp().app_config->set_bool("show_hints", expand);
}
void DailyTipsPanel::collapse()
{
if (!m_can_expand)
return;
m_is_expanded = false;
wxGetApp().app_config->set_bool("show_hints", false);
}
bool DailyTipsPanel::is_expanded()
{
return m_is_expanded;
}
void DailyTipsPanel::on_change_color_mode(bool is_dark)
{
m_is_dark = is_dark;
m_dailytips_renderer->on_change_color_mode(is_dark);
}
void DailyTipsPanel::set_fade_opacity(float opacity)
{
m_fade_opacity = opacity;
m_dailytips_renderer->set_fade_opacity(opacity);
}
//void DailyTipsPanel::render_header(const ImVec2& pos, const ImVec2& size)
//{
// ImGuiWrapper& imgui = *wxGetApp().imgui();
// ImGuiWindow* parent_window = ImGui::GetCurrentWindow();
// int window_flags = parent_window->Flags;
// std::string name = "##DailyTipsPanelHeader" + std::to_string(parent_window->ID);
// ImGui::SetNextWindowPos(pos);
// if (ImGui::BeginChild(name.c_str(), size, false, window_flags)) {
// ImVec2 text_pos = pos + ImVec2(0, (size.y - ImGui::CalcTextSize("A").y) / 2);
// ImGui::SetCursorScreenPos(text_pos);
// imgui.push_bold_font();
// imgui.text(_u8L("Daily Tips"));
// imgui.pop_bold_font();
// }
// ImGui::EndChild();
//}
void DailyTipsPanel::render_controller_buttons(const ImVec2& pos, const ImVec2& size)
{
ImGuiWrapper& imgui = *wxGetApp().imgui();
float scale = imgui.get_font_size() / 15.0f;
ImGuiWindow* parent_window = ImGui::GetCurrentWindow();
int window_flags = parent_window->Flags;
std::string name = "##DailyTipsPanelControllers" + std::to_string(parent_window->ID);
ImGui::SetNextWindowPos(pos);
if (ImGui::BeginChild(name.c_str(), size, false, window_flags)) {
ImVec2 button_size = ImVec2(38.0f, 38.0f) * scale;
float button_margin_x = 8.0f * scale;
std::wstring button_text;
// collapse / expand
ImVec2 btn_pos = pos + ImVec2(0, (size.y - ImGui::CalcTextSize("A").y) / 2);
ImGui::SetCursorScreenPos(btn_pos);
if (m_can_expand) {
if (m_is_expanded) {
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(.0f, .0f, .0f, .0f));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(.0f, .0f, .0f, .0f));
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(.0f, .0f, .0f, .0f));
ImGui::PushStyleColor(ImGuiCol_Text, ImColor(144, 144, 144, (int)(255 * m_fade_opacity)).Value);
button_text = ImGui::CollapseArrowIcon;
imgui.button((_L("Collapse") + button_text));
ImVec2 collapse_btn_size = ImGui::CalcTextSize((_u8L("Collapse")).c_str());
collapse_btn_size.x += button_size.x / 2.0f;
if (ImGui::IsMouseHoveringRect(btn_pos, btn_pos + collapse_btn_size, true))
{
//underline
ImVec2 lineEnd = ImGui::GetItemRectMax();
lineEnd.x -= ImGui::CalcTextSize("A").x / 2;
lineEnd.y -= 2;
ImVec2 lineStart = lineEnd;
lineStart.x = ImGui::GetItemRectMin().x;
ImGui::GetWindowDrawList()->AddLine(lineStart, lineEnd, ImColor(144, 144, 144));
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left))
collapse();
}
ImGui::PopStyleColor(4);
}
else {
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(.0f, .0f, .0f, .0f));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(.0f, .0f, .0f, .0f));
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(.0f, .0f, .0f, .0f));
ImGui::PushStyleColor(ImGuiCol_Text, m_is_dark ? ImColor(230, 230, 230, (int)(255 * m_fade_opacity)).Value : ImColor(38, 46, 48, (int)(255 * m_fade_opacity)).Value);
// for bold font text, split text and icon-font button
imgui.push_bold_font();
imgui.button((_L("Daily Tips")));
imgui.pop_bold_font();
ImVec2 expand_btn_size = ImGui::CalcTextSize((_u8L("Daily Tips")).c_str());
ImGui::SetCursorScreenPos(ImVec2(btn_pos.x + expand_btn_size.x + ImGui::CalcTextSize(" ").x, btn_pos.y));
button_text = ImGui::ExpandArrowIcon;
imgui.button(button_text.c_str());
expand_btn_size.x += 19.0f * scale;
if (ImGui::IsMouseHoveringRect(btn_pos, btn_pos + expand_btn_size, true))
{
//underline
ImVec2 lineEnd = ImGui::GetItemRectMax();
lineEnd.x -= ImGui::CalcTextSize("A").x / 2;
lineEnd.y -= 2;
ImVec2 lineStart = lineEnd;
lineStart.x = ImGui::GetItemRectMin().x - expand_btn_size.x;
ImGui::GetWindowDrawList()->AddLine(lineStart, lineEnd, m_is_dark ? ImColor(230, 230, 230, (int)(255 * m_fade_opacity)) : ImColor(38, 46, 48, (int)(255 * m_fade_opacity)));
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left))
expand();
}
ImGui::PopStyleColor(4);
ImGui::EndChild();
return;
}
}
// page index
m_page_index = HintDatabase::get_instance().get_index() + 1;
m_pages_count = HintDatabase::get_instance().get_count();
std::string text_str = std::to_string(m_page_index) + "/" + std::to_string(m_pages_count);
float text_item_width = ImGui::CalcTextSize(text_str.c_str()).x;
ImGui::PushItemWidth(text_item_width);
float text_pos_x = (pos + size).x - button_margin_x * 2 - button_size.x * 2 - text_item_width;
float text_pos_y = pos.y + (size.y - ImGui::CalcTextSize("A").y) / 2;
ImGui::SetCursorScreenPos(ImVec2(text_pos_x, text_pos_y));
ImGui::PushStyleColor(ImGuiCol_Text, m_is_dark ? ImColor(230, 230, 230, (int)(255 * m_fade_opacity)).Value : ImColor(38, 46, 48, (int)(255 * m_fade_opacity)).Value);
imgui.text(text_str);
ImGui::PopStyleColor();
ImGui::PopItemWidth();
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(.0f, .0f, .0f, .0f));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(.0f, .0f, .0f, .0f));
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(.0f, .0f, .0f, .0f));
ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(.0f, .0f, .0f, .0f));
// prev button
ImColor button_text_color = m_is_dark ? ImColor(228, 228, 228, (int)(255 * m_fade_opacity)) : ImColor(38, 46, 48, (int)(255 * m_fade_opacity));
ImVec2 prev_button_pos = pos + size + ImVec2(-button_margin_x - button_size.x * 2, -size.y + (size.y - button_size.y) / 2);
ImGui::SetCursorScreenPos(prev_button_pos);
button_text = ImGui::PrevArrowBtnIcon;
if (ImGui::IsMouseHoveringRect(prev_button_pos, prev_button_pos + button_size, true))
{
button_text_color = ImColor(0, 150, 136, (int)(255 * m_fade_opacity));
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left))
retrieve_data_from_hint_database(HintDataNavigation::Prev);
}
ImGui::PushStyleColor(ImGuiCol_Text, button_text_color.Value);// for icon-font button
imgui.button(button_text.c_str());
ImGui::PopStyleColor();
// next button
button_text_color = m_is_dark ? ImColor(228, 228, 228, (int)(255 * m_fade_opacity)) : ImColor(38, 46, 48, (int)(255 * m_fade_opacity));
ImVec2 next_button_pos = pos + size + ImVec2(-button_size.x, -size.y + (size.y - button_size.y) / 2);
ImGui::SetCursorScreenPos(next_button_pos);
button_text = ImGui::NextArrowBtnIcon;
if (ImGui::IsMouseHoveringRect(next_button_pos, next_button_pos + button_size, true))
{
button_text_color = ImColor(0, 150, 136, (int)(255 * m_fade_opacity));
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left))
retrieve_data_from_hint_database(HintDataNavigation::Next);
}
ImGui::PushStyleColor(ImGuiCol_Text, button_text_color.Value);// for icon-font button
imgui.button(button_text.c_str());
ImGui::PopStyleColor();
ImGui::PopStyleColor(4);
}
ImGui::EndChild();
}
void DailyTipsPanel::push_styles()
{
ImGuiWrapper& imgui = *wxGetApp().imgui();
float scale = imgui.get_font_size() / 15.0f;
imgui.push_common_window_style(scale);
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
// framePadding cannot be zero. Otherwise, there is a problem with icon font button display
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(1.0f, 1.0f));
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f));
ImGui::PushStyleVar(ImGuiStyleVar_ItemInnerSpacing, ImVec2(0.0f, 0.0f));
ImGui::PushStyleVar(ImGuiStyleVar_ScrollbarSize, 4.0f * scale);
ImGui::PushStyleColor(ImGuiCol_ScrollbarBg, m_is_dark ? ImGuiWrapper::COL_WINDOW_BG_DARK : ImGuiWrapper::COL_WINDOW_BG);
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrab, ImVec4(0.42f, 0.42f, 0.42f, 1.00f));
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrabHovered, ImVec4(0.93f, 0.93f, 0.93f, 1.00f));
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrabActive, ImVec4(0.93f, 0.93f, 0.93f, 1.00f));
}
void DailyTipsPanel::pop_styles()
{
ImGuiWrapper& imgui = *wxGetApp().imgui();
imgui.pop_common_window_style();
ImGui::PopStyleVar(6);
ImGui::PopStyleColor(4);
}
DailyTipsWindow::DailyTipsWindow()
{
m_panel = new DailyTipsPanel(false, DailyTipsLayout::Vertical);
}
void DailyTipsWindow::open()
{
m_show = true;
m_panel->retrieve_data_from_hint_database(HintDataNavigation::Curr);
}
void DailyTipsWindow::close()
{
m_show = false;
}
void DailyTipsWindow::render()
{
if (!m_show)
return;
//if (m_show)
// ImGui::OpenPopup((_u8L("Daily Tips")).c_str());
ImGuiWrapper& imgui = *wxGetApp().imgui();
float scale = imgui.get_font_size() / 15.0f;
const Size& cnv_size = wxGetApp().plater()->get_current_canvas3D()->get_canvas_size();
ImVec2 center = ImVec2(cnv_size.get_width() * 0.5f, cnv_size.get_height() * 0.5f);
ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
ImVec2 padding = ImVec2(25, 25) * scale;
imgui.push_menu_style(scale);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, padding);
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 12.f * scale);
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(10, 3) * scale);
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(10, 7) * scale);
ImGui::PushStyleColor(ImGuiCol_TitleBgActive, m_is_dark ? ImVec4(54 / 255.0f, 54 / 255.0f, 60 / 255.0f, 1.00f) : ImVec4(245 / 255.0f, 245 / 255.0f, 245 / 255.0f, 1.00f));
ImGui::GetCurrentContext()->DimBgRatio = 1.0f;
int windows_flag =
ImGuiWindowFlags_NoCollapse
| ImGuiWindowFlags_AlwaysAutoResize
| ImGuiWindowFlags_NoResize
| ImGuiWindowFlags_NoScrollbar
| ImGuiWindowFlags_NoScrollWithMouse;
imgui.push_bold_font();
//if (ImGui::BeginPopupModal((_u8L("Daily Tips")).c_str(), NULL, windows_flag))
if (ImGui::Begin((_u8L("Daily Tips")).c_str(), &m_show, windows_flag))
{
imgui.pop_bold_font();
ImVec2 panel_pos = ImGui::GetWindowPos() + ImGui::GetWindowContentRegionMin();
ImVec2 panel_size = ImVec2(400.0f, 435.0f) * scale;
m_panel->set_position(panel_pos);
m_panel->set_size(panel_size);
m_panel->render();
if (ImGui::IsKeyDown(ImGui::GetKeyIndex(ImGuiKey_Escape))) {
m_show = false;
ImGui::CloseCurrentPopup();
}
ImGui::End();
//ImGui::EndPopup();
}
else {
imgui.pop_bold_font();
}
ImGui::PopStyleVar(4);
ImGui::PopStyleColor();
imgui.pop_menu_style();
}
void DailyTipsWindow::on_change_color_mode(bool is_dark)
{
m_is_dark = is_dark;
m_panel->on_change_color_mode(is_dark);
}
}}

View file

@ -0,0 +1,74 @@
#ifndef slic3r_GUI_DailyTips_hpp_
#define slic3r_GUI_DailyTips_hpp_
#include "HintNotification.hpp"
//#include <wx/time.h>
#include <string>
#include <vector>
#include <memory>
namespace Slic3r { namespace GUI {
enum class DailyTipsLayout{
Horizontal,
Vertical
};
class DailyTipsDataRenderer;
class DailyTipsPanel {
static int uid;
public:
DailyTipsPanel(bool can_expand = true, DailyTipsLayout layout = DailyTipsLayout::Vertical);
void set_position(const ImVec2& pos);
void set_size(const ImVec2& size);
void set_can_expand(bool can_expand);
ImVec2 get_size();
void render();
void retrieve_data_from_hint_database(HintDataNavigation nav);
void expand(bool expand = true);
void collapse();
bool is_expanded();
void on_change_color_mode(bool is_dark);
void set_fade_opacity(float opacity);
protected:
void render_controller_buttons(const ImVec2& pos, const ImVec2& size);
void push_styles();
void pop_styles();
private:
std::unique_ptr<DailyTipsDataRenderer> m_dailytips_renderer;
size_t m_page_index{ 0 };
int m_pages_count;
bool m_is_expanded{ true };
bool m_can_expand{ true };
ImVec2 m_pos;
float m_width;
float m_height;
float m_content_height;
float m_footer_height;
int m_uid;
bool m_first_enter{ false };
bool m_is_dark{ false };
DailyTipsLayout m_layout{ DailyTipsLayout::Vertical };
float m_fade_opacity{ 1.0f };
};
class DailyTipsWindow {
public:
DailyTipsWindow();
void open();
void close();
void render();
void on_change_color_mode(bool is_dark);
private:
DailyTipsPanel* m_panel{ nullptr };
bool m_show{ false };
bool m_is_dark{ false };
};
}}
#endif

File diff suppressed because it is too large Load diff

View file

@ -7,13 +7,14 @@
#include <memory>
#include <chrono>
#include <boost/thread.hpp>
#include <boost/nowide/fstream.hpp>
#include "nlohmann/json.hpp"
#include "libslic3r/ProjectTask.hpp"
#include "slic3r/Utils/json_diff.hpp"
#include "slic3r/Utils/NetworkAgent.hpp"
#include "CameraPopup.hpp"
#include "libslic3r/calib.hpp"
#include "libslic3r/Utils.hpp"
#define USE_LOCAL_SOCKET_BIND 0
#define DISCONNECT_TIMEOUT 30000.f // milliseconds
@ -51,7 +52,7 @@ using namespace nlohmann;
namespace Slic3r {
class SecondaryCheckDialog;
enum PrinterArch {
ARCH_CORE_XY,
ARCH_I3,
@ -63,55 +64,7 @@ enum PrinterSeries {
SERIES_UNKNOWN,
};
enum PRINTING_STAGE {
PRINTING_STAGE_PRINTING = 0,
PRINTING_STAGE_BED_LEVELING,
PRINTING_STAGE_HEADBED,
PRINTING_STAGE_XY_MECH_MODE,
PRINTING_STAGE_CHANGE_MATERIAL,
PRINTING_STAGE_M400_PAUSE,
PRINTING_STAGE_FILAMENT_RUNOUT_PAUSE,
PRINTING_STAGE_HOTEND_HEATING,
PRINTING_STAGE_EXTRUDER_SCAN,
PRINTING_STAGE_BED_SCAN,
PRINTING_STAGE_FIRST_LAYER_SCAN,
PRINTING_STAGE_SURFACE_TYPE_IDENT,
PRINTING_STAGE_SCANNER_PARAM_CALI,
PRINTING_STAGE_TOOHEAD_HOMING,
PRINTING_STAGE_NOZZLE_TIP_CLEANING,
PRINTING_STAGE_COUNT
};
enum PrinterFunction {
FUNC_MONITORING = 0,
FUNC_TIMELAPSE,
FUNC_RECORDING,
FUNC_FIRSTLAYER_INSPECT,
FUNC_AI_MONITORING,
FUNC_LIDAR_CALIBRATION,
FUNC_BUILDPLATE_MARKER_DETECT,
FUNC_AUTO_RECOVERY_STEP_LOSS,
FUNC_FLOW_CALIBRATION,
FUNC_AUTO_LEVELING,
FUNC_CHAMBER_TEMP,
FUNC_CAMERA_VIDEO,
FUNC_MEDIA_FILE,
FUNC_REMOTE_TUNNEL,
FUNC_LOCAL_TUNNEL,
FUNC_PRINT_WITHOUT_SD,
FUNC_VIRTUAL_CAMERA,
FUNC_USE_AMS,
FUNC_ALTER_RESOLUTION,
FUNC_SEND_TO_SDCARD,
FUNC_AUTO_SWITCH_FILAMENT,
FUNC_CHAMBER_FAN,
FUNC_AUX_FAN,
FUNC_EXTRUSION_CALI,
FUNC_PROMPT_SOUND,
FUNC_VIRTUAL_TYAY,
FUNC_PRINT_ALL,
FUNC_FILAMENT_BACKUP,
FUNC_MOTOR_NOISE_CALI,
FUNC_MAX
};
@ -359,7 +312,8 @@ struct DisValue {
class MachineObject
{
private:
NetworkAgent* m_agent { nullptr };
NetworkAgent * m_agent{nullptr};
std::shared_ptr<int> m_token = std::make_shared<int>(1);
bool check_valid_ip();
void _parse_print_option_ack(int option);
@ -452,12 +406,14 @@ public:
bool local_use_ssl_for_mqtt { true };
bool local_use_ssl_for_ftp { true };
float nozzle_diameter { 0.0f };
int subscribe_counter{3};
std::string nozzle_type;
std::string dev_connection_type; /* lan | cloud */
std::string connection_type() { return dev_connection_type; }
std::string dev_connection_name; /* lan | eth */
void set_dev_ip(std::string ip) {dev_ip = ip;};
bool has_access_right() { return !get_access_code().empty(); }
void set_dev_ip(std::string ip) {dev_ip = ip;}
std::string get_ftp_folder();
bool has_access_right() { return !get_access_code().empty(); }
std::string get_access_code();
void set_access_code(std::string code, bool only_refresh = true);
@ -465,24 +421,26 @@ public:
void erase_user_access_code();
std::string get_user_access_code();
bool is_lan_mode_printer();
bool is_high_printer_type();
//PRINTER_TYPE printer_type = PRINTER_3DPrinter_UKNOWN;
std::string printer_type; /* model_id */
PrinterSeries get_printer_series() const;
PrinterArch get_printer_arch() const;
bool is_printer_enclosed() const;
std::string get_printer_ams_type() const;
bool get_printer_is_enclosed() const;
void reload_printer_settings();
std::string printer_thumbnail_img;
std::string monitor_upgrade_printer_img;
wxString get_printer_type_display_str();
std::string get_printer_thumbnail_img_str();
std::string product_name; // set by iot service, get /user/print
std::vector<int> filam_bak;
bool m_is_support_show_bak{false};
std::string bind_user_name;
std::string bind_user_id;
@ -492,8 +450,10 @@ public:
time_t last_alive;
bool m_is_online;
bool m_lan_mode_connection_state{false};
bool m_set_ctt_dlg{ false };
void set_lan_mode_connection_state(bool state) {m_lan_mode_connection_state = state;};
bool get_lan_mode_connection_state() {return m_lan_mode_connection_state;};
void set_ctt_dlg( wxString text);
int parse_msg_count = 0;
int keep_alive_count = 0;
std::chrono::system_clock::time_point last_update_time; /* last received print data from machine */
@ -503,7 +463,6 @@ public:
std::chrono::system_clock::time_point last_request_start; /* last received print push from machine */
int m_active_state = 0; // 0 - not active, 1 - active, 2 - update-to-date
bool is_support_tunnel_mqtt = false;
bool is_tunnel_mqtt = false;
/* ams properties */
@ -518,10 +477,8 @@ public:
bool ams_insert_flag { false };
bool ams_power_on_flag { false };
bool ams_calibrate_remain_flag { false };
bool ams_support_auto_switch_filament_flag { true };
bool ams_auto_switch_filament_flag { false };
bool ams_support_use_ams { false };
bool ams_support_remain { true };
bool ams_support_virtual_tray { true };
int ams_humidity;
int ams_user_setting_hold_count = 0;
@ -553,10 +510,7 @@ public:
void _parse_ams_status(int ams_status);
bool has_ams() { return ams_exist_bits != 0; }
bool can_unload_filament();
bool is_U0_firmware();
bool is_support_ams_mapping();
bool is_support_command_ams_switch();
static bool is_support_ams_mapping_version(std::string module, std::string version);
int ams_filament_mapping(std::vector<FilamentInfo> filaments, std::vector<FilamentInfo> &result, std::vector<int> exclude_id = std::vector<int>());
bool is_valid_mapping_result(std::vector<FilamentInfo>& result, bool check_empty_slot = false);
@ -724,39 +678,74 @@ public:
int camera_recording_hold_count = 0;
int camera_timelapse_hold_count = 0;
int camera_resolution_hold_count = 0;
std::string camera_resolution = "";
std::string camera_resolution = "";
std::vector<std::string> camera_resolution_supported;
bool xcam_first_layer_inspector { false };
int xcam_first_layer_hold_count = 0;
int local_camera_proto = -1;
int file_proto = 0;
std::string local_rtsp_url;
std::string tutk_state;
bool is_support_remote_tunnel{false};
enum LiveviewLocal {
LVL_None,
LVL_Local,
LVL_Rtsps,
LVL_Rtsp
} liveview_local{ LVL_None };
bool liveview_remote{false};
bool file_local{false};
bool file_remote{false};
bool file_model_download{false};
bool virtual_camera{false};
bool xcam_ai_monitoring{ false };
int xcam_ai_monitoring_hold_count = 0;
std::string xcam_ai_monitoring_sensitivity;
bool is_xcam_buildplate_supported { true };
bool xcam_buildplate_marker_detector{ false };
int xcam_buildplate_marker_hold_count = 0;
bool xcam_support_recovery_step_loss { true };
bool xcam_auto_recovery_step_loss{ false };
bool xcam_allow_prompt_sound{ false };
bool xcam_filament_tangle_detect{ false };
int xcam_auto_recovery_hold_count = 0;
int xcam_prompt_sound_hold_count = 0;
int xcam_filament_tangle_detect_count = 0;
int ams_print_option_count = 0;
/*not support U2*/
bool is_support_1080dpi {false};
//supported features
bool is_support_chamber_edit{false};
bool is_support_extrusion_cali{false};
bool is_support_first_layer_inspect{false};
bool is_support_ai_monitoring {false};
bool is_support_ams_humidity {true};
bool is_cloud_print_only {false};
bool is_support_lidar_calibration {false};
bool is_support_build_plate_marker_detect{false};
bool is_support_flow_calibration{false};
bool is_support_print_without_sd{false};
bool is_support_print_all{false};
bool is_support_send_to_sdcard {false};
bool is_support_aux_fan {false};
bool is_support_chamber_fan{false};
bool is_support_filament_backup{false};
bool is_support_show_filament_backup{false};
bool is_support_timelapse{false};
bool is_support_update_remain{false};
bool is_support_auto_leveling{false};
bool is_support_auto_recovery_step_loss{false};
bool is_support_ams_humidity {false};
bool is_support_prompt_sound{false};
bool is_support_filament_tangle_detect{false};
bool is_support_1080dpi {false};
bool is_support_cloud_print_only {false};
bool is_support_command_ams_switch{false};
bool is_support_mqtt_alive {false};
bool is_support_tunnel_mqtt{false};
bool is_support_motor_noise_cali{false};
bool is_support_wait_sending_finish{false};
bool is_support_user_preset{false};
int nozzle_max_temperature = -1;
int bed_temperature_limit = -1;
/* sdcard */
MachineObject::SdcardState sdcard_state { NO_SDCARD };
MachineObject::SdcardState get_sdcard_state();
bool is_support_send_to_sdcard { true };
/* HMS */
std::vector<HMSItem> hms_list;
@ -772,6 +761,7 @@ public:
std::string profile_id_;
std::string task_id_;
std::string subtask_id_;
std::string job_id_;
std::string last_subtask_id_;
BBLSliceInfo* slice_info {nullptr};
boost::thread* get_slice_info_thread { nullptr };
@ -780,7 +770,7 @@ public:
bool is_makeworld_subtask();
int plate_index { -1 };
int m_plate_index { -1 };
std::string m_gcode_file;
int gcode_file_prepare_percent = 0;
BBLSubTask* subtask_;
@ -801,6 +791,7 @@ public:
MachineObject(NetworkAgent* agent, std::string name, std::string id, std::string ip);
~MachineObject();
std::string parse_version();
void parse_version_func();
bool is_studio_cmd(int seq);
/* command commands */
@ -808,6 +799,9 @@ public:
int command_request_push_all(bool request_now = false);
int command_pushing(std::string cmd);
int command_clean_print_error(std::string task_id, int print_error);
int command_set_printer_nozzle(std::string nozzle_type, float diameter);
int command_get_access_code();
/* command upgrade */
int command_upgrade_confirm();
@ -822,6 +816,8 @@ public:
int command_control_fan(FanType fan_type, bool on_off);
int command_control_fan_val(FanType fan_type, int val);
int command_task_abort();
/* cancelled the job_id */
int command_task_cancel(std::string job_id);
int command_task_pause();
int command_task_resume();
int command_set_bed(int temp);
@ -847,9 +843,13 @@ public:
// set printing speed
int command_set_printing_speed(PrintingSpeedLevel lvl);
//set pormpt sound
//set prompt sound
int command_set_prompt_sound(bool prompt_sound);
//set fliament tangle detect
int command_set_filament_tangle_detect(bool fliament_tangle_detect);
// set print option
int command_set_printing_option(bool auto_recovery);
@ -884,6 +884,7 @@ public:
int command_xcam_control_buildplate_marker_detector(bool on_off);
int command_xcam_control_auto_recovery_step_loss(bool on_off);
int command_xcam_control_allow_prompt_sound(bool on_off);
int command_xcam_control_filament_tangle_detect(bool on_off);
/* common apis */
inline bool is_local() { return !dev_ip.empty(); }
@ -902,20 +903,16 @@ public:
static bool is_in_printing_status(std::string status);
void set_print_state(std::string status);
std::vector<std::string> get_compatible_machine();
bool is_connected();
bool is_connecting();
void set_online_state(bool on_off);
bool is_online() { return m_is_online; }
bool is_info_ready();
bool is_function_supported(PrinterFunction func);
std::vector<std::string> get_resolution_supported();
bool is_support_print_with_timelapse();
bool is_camera_busy_off();
int get_local_camera_proto();
bool has_local_file_proto();
bool has_remote_file_proto();
std::vector<std::string> get_resolution_supported();
std::vector<std::string> get_compatible_machine();
/* Msg for display MsgFn */
typedef std::function<void(std::string topic, std::string payload)> MsgFn;
@ -964,6 +961,7 @@ public:
MachineObject* get_my_machine(std::string dev_id);
void erase_user_machine(std::string dev_id);
void clean_user_info();
void reload_printer_settings();
bool set_selected_machine(std::string dev_id, bool need_disconnect = false);
MachineObject* get_selected_machine();
@ -989,21 +987,41 @@ public:
static json function_table;
static json filaments_blacklist;
template<typename T>
static T get_value_from_config(std::string type_str, std::string item){
std::string config_file = Slic3r::resources_dir() + "/printers/" + type_str + ".json";
boost::nowide::ifstream json_file(config_file.c_str());
try {
json jj;
if (json_file.is_open()) {
json_file >> jj;
if (jj.contains("00.00.00.00")) {
json const& printer = jj["00.00.00.00"];
if (printer.contains(item)) {
return printer[item].get<T>();
}
}
}
}
catch (...) {}
return "";
}
static std::string parse_printer_type(std::string type_str);
static std::string get_printer_display_name(std::string type_str);
static std::string get_printer_thumbnail_img(std::string type_str);
static std::string get_printer_ams_type(std::string type_str);
static std::string get_printer_series(std::string type_str);
static std::string get_printer_diagram_img(std::string type_str);
static std::string get_printer_ams_img(std::string type_str);
static PrinterArch get_printer_arch(std::string type_str);
static std::string get_ftp_folder(std::string type_str);
static bool is_function_supported(std::string type_str, std::string function_name);
static bool get_printer_is_enclosed(std::string type_str);
static std::vector<std::string> get_resolution_supported(std::string type_str);
static bool get_bed_temperature_limit(std::string type_str, int& limit);
static bool get_nozzle_max_temperature(std::string type_str, int& limit);
static bool load_functional_config(std::string config_file);
static std::vector<std::string> get_compatible_machine(std::string type_str);
static bool load_filaments_blacklist_config(std::string config_file);
static void check_filaments_in_blacklist(std::string tag_vendor, std::string tag_type, bool& in_blacklist, std::string& ac, std::string& info);
static std::string load_gcode(std::string type_str, std::string gcode_file);
static std::vector<std::string> get_compatible_machine(std::string type_str);
};
} // namespace Slic3r

View file

@ -225,7 +225,8 @@ wxWindow* BitmapTextRenderer::CreateEditorCtrl(wxWindow* parent, wxRect labelRec
bool BitmapTextRenderer::GetValueFromEditorCtrl(wxWindow* ctrl, wxVariant& value)
{
wxTextCtrl* text_editor = wxDynamicCast(ctrl, wxTextCtrl);
if (!text_editor || text_editor->GetValue().IsEmpty())
auto item = GetView()->GetModel()->GetParent(m_item);
if (!text_editor || (item.IsOk() && text_editor->GetValue().IsEmpty()))
return false;
m_was_unusable_symbol = Slic3r::GUI::Plater::has_illegal_filename_characters(text_editor->GetValue());

View file

@ -508,7 +508,7 @@ bool ExtrusionCalibration::check_k_validation(wxString k_text)
;
}
if (k < 0 || k > 0.5)
if (k < 0 || k > 0.3)
return false;
return true;
}
@ -544,8 +544,8 @@ void ExtrusionCalibration::on_click_save(wxCommandEvent &event)
wxString k_text = m_k_val->GetTextCtrl()->GetValue();
wxString n_text = m_n_val->GetTextCtrl()->GetValue();
if (!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)");
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;

View file

@ -131,7 +131,9 @@ void Field::PostInitialize()
// For the mode, when settings are in non-modal dialog, neither dialog nor tabpanel doesn't receive wxEVT_KEY_UP event, when some field is selected.
// So, like a workaround check wxEVT_KEY_UP event for the Filed and switch between tabs if Ctrl+(1-4) was pressed
if (getWindow()) {
if (m_opt.readonly) getWindow()->Disable();
if (m_opt.readonly) {
this->disable();
}
getWindow()->Bind(wxEVT_KEY_UP, [](wxKeyEvent& evt) {
if ((evt.GetModifiers() & wxMOD_CONTROL) != 0) {
int tab_id = -1;
@ -424,6 +426,12 @@ void Field::get_value_by_opt_type(wxString& str, const bool check_value/* = true
continue;
}
}
else if (m_opt_id == "printable_area") {
if (0 <= x && x <= 1000 && 0 <= y && y <= 1000) {
out_values.push_back(Vec2d(x, y));
continue;
}
}
else {
if (0 < x && x < 1000 && 0 < y && y < 1000) {
out_values.push_back(Vec2d(x, y));
@ -1333,7 +1341,7 @@ void Choice::set_value(const boost::any& value, bool change_event)
if (m_opt_id.compare("host_type") == 0 && val != 0 &&
m_opt.enum_values.size() > field->GetCount()) // for case, when PrusaLink isn't used as a HostType
val--;
if (m_opt_id == "top_surface_pattern" || m_opt_id == "bottom_surface_pattern" || m_opt_id == "internal_solid_infill_pattern" || m_opt_id == "sparse_infill_pattern" || m_opt_id == "support_style")
if (m_opt_id == "top_surface_pattern" || m_opt_id == "bottom_surface_pattern" || m_opt_id == "internal_solid_infill_pattern" || m_opt_id == "sparse_infill_pattern" || m_opt_id == "support_style" || m_opt_id == "curr_bed_type")
{
std::string key;
const t_config_enum_values& map_names = *m_opt.enum_keys_map;
@ -1420,7 +1428,8 @@ boost::any& Choice::get_value()
{
if (m_opt.nullable && field->GetSelection() == -1)
m_value = ConfigOptionEnumsGenericNullable::nil_value();
else if (m_opt_id == "top_surface_pattern" || m_opt_id == "bottom_surface_pattern" || m_opt_id == "internal_solid_infill_pattern" || m_opt_id == "sparse_infill_pattern" || m_opt_id == "support_style") {
else if (m_opt_id == "top_surface_pattern" || m_opt_id == "bottom_surface_pattern" || m_opt_id == "internal_solid_infill_pattern" || m_opt_id == "sparse_infill_pattern" ||
m_opt_id == "support_style" || m_opt_id == "curr_bed_type") {
const std::string& key = m_opt.enum_values[field->GetSelection()];
m_value = int(m_opt.enum_keys_map->at(key));
}

View file

@ -898,9 +898,9 @@ void GCodeViewer::update_by_mode(ConfigOptionMode mode)
view_type_items.push_back(EViewType::LayerTimeLog);
view_type_items.push_back(EViewType::FanSpeed);
view_type_items.push_back(EViewType::Temperature);
if (mode == ConfigOptionMode::comDevelop) {
view_type_items.push_back(EViewType::Tool);
}
//if (mode == ConfigOptionMode::comDevelop) {
// view_type_items.push_back(EViewType::Tool);
//}
for (int i = 0; i < view_type_items.size(); i++) {
view_type_items_str.push_back(get_view_type_string(view_type_items[i]));
@ -913,9 +913,9 @@ view_type_items.push_back(EViewType::LayerTimeLog);
options_items.push_back(EMoveType::Retract);
options_items.push_back(EMoveType::Unretract);
options_items.push_back(EMoveType::Wipe);
if (mode == ConfigOptionMode::comDevelop) {
options_items.push_back(EMoveType::Tool_change);
}
//if (mode == ConfigOptionMode::comDevelop) {
// options_items.push_back(EMoveType::Tool_change);
//}
//BBS: seam is not real move and extrusion, put at last line
options_items.push_back(EMoveType::Seam);
}
@ -3072,10 +3072,9 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result, const
progress_dialog->Destroy();
}
//BBS: always load shell when preview
void GCodeViewer::load_shells(const Print& print, bool force_previewing)
void GCodeViewer::load_shells(const Print& print, bool initialized, bool force_previewing)
{
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": force_previewing=%1%") %force_previewing;
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": initialized=%1%, force_previewing=%2%")%initialized %force_previewing;
if ((print.id().id == m_shells.print_id)&&(print.get_modified_count() == m_shells.print_modify_count)) {
//BBS: update force previewing logic
if (force_previewing)
@ -3123,7 +3122,7 @@ void GCodeViewer::load_shells(const Print& print, bool force_previewing)
instance_ids.resize(instance_index);
size_t current_volumes_count = m_shells.volumes.volumes.size();
m_shells.volumes.load_object(model_obj, object_idx, instance_ids);
m_shells.volumes.load_object(model_obj, object_idx, instance_ids, "object", initialized);
// adjust shells' z if raft is present
const SlicingParameters& slicing_parameters = obj->slicing_parameters();
@ -3140,24 +3139,24 @@ void GCodeViewer::load_shells(const Print& print, bool force_previewing)
// Orca: disable wipe tower shell
// if (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() == ptFFF) {
// // BBS: adds wipe tower's volume
// std::vector<unsigned int> print_extruders = print.extruders(true);
// int extruders_count = print_extruders.size();
// // BBS: adds wipe tower's volume
// std::vector<unsigned int> print_extruders = print.extruders(true);
// int extruders_count = print_extruders.size();
// const double max_z = print.objects()[0]->model_object()->get_model()->bounding_box().max(2);
// const PrintConfig& config = print.config();
// if (config.enable_prime_tower &&
// (print.enable_timelapse_print() || (extruders_count > 1 && (config.print_sequence == PrintSequence::ByLayer)))) {
// const float depth = print.wipe_tower_data(extruders_count).depth;
// const float brim_width = print.wipe_tower_data(extruders_count).brim_width;
// const double max_z = print.objects()[0]->model_object()->get_model()->bounding_box().max(2);
// const PrintConfig& config = print.config();
// if (config.enable_prime_tower &&
// (print.enable_timelapse_print() || (extruders_count > 1 && (config.print_sequence == PrintSequence::ByLayer)))) {
// const float depth = print.wipe_tower_data(extruders_count).depth;
// const float brim_width = print.wipe_tower_data(extruders_count).brim_width;
// int plate_idx = print.get_plate_index();
// Vec3d plate_origin = print.get_plate_origin();
// double wipe_tower_x = config.wipe_tower_x.get_at(plate_idx) + plate_origin(0);
// double wipe_tower_y = config.wipe_tower_y.get_at(plate_idx) + plate_origin(1);
// m_shells.volumes.load_wipe_tower_preview(1000, wipe_tower_x, wipe_tower_y, config.prime_tower_width, depth, max_z, config.wipe_tower_rotation_angle,
// !print.is_step_done(psWipeTower), brim_width, initialized);
// }
// int plate_idx = print.get_plate_index();
// Vec3d plate_origin = print.get_plate_origin();
// double wipe_tower_x = config.wipe_tower_x.get_at(plate_idx) + plate_origin(0);
// double wipe_tower_y = config.wipe_tower_y.get_at(plate_idx) + plate_origin(1);
// m_shells.volumes.load_wipe_tower_preview(1000, wipe_tower_x, wipe_tower_y, config.prime_tower_width, depth, max_z, config.wipe_tower_rotation_angle,
// !print.is_step_done(psWipeTower), brim_width, initialized);
// }
// }
// remove modifiers
@ -4080,16 +4079,26 @@ void GCodeViewer::render_all_plates_stats(const std::vector<const GCodeProcessor
float window_padding = 4.0f * m_scale;
const float icon_size = ImGui::GetTextLineHeight() * 0.7;
std::vector<float> offsets;
std::map<int, double> volume_of_extruders_all_plates; // map<extruder_idx, volume>
std::map<int, double> model_volume_of_extruders_all_plates; // map<extruder_idx, volume>
std::map<int, double> flushed_volume_of_extruders_all_plates; // map<extruder_idx, flushed volume>
std::map<int, double> wipe_tower_volume_of_extruders_all_plates; // map<extruder_idx, flushed volume>
std::vector<double> model_used_filaments_m_all_plates;
std::vector<double> model_used_filaments_g_all_plates;
std::vector<double> flushed_filaments_m_all_plates;
std::vector<double> flushed_filaments_g_all_plates;
std::vector<double> wipe_tower_used_filaments_m_all_plates;
std::vector<double> wipe_tower_used_filaments_g_all_plates;
float total_time_all_plates = 0.0f;
float total_cost_all_plates = 0.0f;
bool show_detailed_statistics_page = false;
struct ColumnData {
enum {
Model = 1,
Flushed = 2,
WipeTower = 4,
};
};
int displayed_columns = 0;
auto max_width = [](const std::vector<std::string>& items, const std::string& title, float extra_size = 0.0f) {
float ret = ImGui::CalcTextSize(title.c_str()).x;
for (const std::string& item : items) {
@ -4169,15 +4178,23 @@ void GCodeViewer::render_all_plates_stats(const std::vector<const GCodeProcessor
for (size_t extruder_id : plate_extruders) {
extruder_id -= 1;
if (plate_print_statistics.volumes_per_extruder.find(extruder_id) == plate_print_statistics.volumes_per_extruder.end())
continue;
double volume = plate_print_statistics.volumes_per_extruder.at(extruder_id);
volume_of_extruders_all_plates[extruder_id] += volume;
flushed_volume_of_extruders_all_plates[extruder_id] += 0;
else {
double model_volume = plate_print_statistics.volumes_per_extruder.at(extruder_id);
model_volume_of_extruders_all_plates[extruder_id] += model_volume;
}
if (plate_print_statistics.flush_per_filament.find(extruder_id) == plate_print_statistics.flush_per_filament.end())
flushed_volume_of_extruders_all_plates[extruder_id] = 0;
flushed_volume_of_extruders_all_plates[extruder_id] += 0;
else {
double flushed_volume = plate_print_statistics.flush_per_filament.at(extruder_id);
flushed_volume_of_extruders_all_plates[extruder_id] += flushed_volume;
}
if (plate_print_statistics.wipe_tower_volumes_per_extruder.find(extruder_id) == plate_print_statistics.wipe_tower_volumes_per_extruder.end())
wipe_tower_volume_of_extruders_all_plates[extruder_id] += 0;
else {
double wipe_tower_volume = plate_print_statistics.wipe_tower_volumes_per_extruder.at(extruder_id);
wipe_tower_volume_of_extruders_all_plates[extruder_id] += wipe_tower_volume;
}
}
const PrintEstimatedStatistics::Mode& plate_time_mode = plate_print_statistics.modes[static_cast<size_t>(m_time_estimate_mode)];
total_time_all_plates += plate_time_mode.time;
@ -4187,18 +4204,27 @@ void GCodeViewer::render_all_plates_stats(const std::vector<const GCodeProcessor
total_cost_all_plates += print->print_statistics().total_cost;
}
for (auto it = volume_of_extruders_all_plates.begin(); it != volume_of_extruders_all_plates.end(); it++) {
for (auto it = model_volume_of_extruders_all_plates.begin(); it != model_volume_of_extruders_all_plates.end(); it++) {
auto [model_used_filament_m, model_used_filament_g] = get_used_filament_from_volume(it->second, it->first);
if (model_used_filament_m != 0.0 || model_used_filament_g != 0.0)
displayed_columns |= ColumnData::Model;
model_used_filaments_m_all_plates.push_back(model_used_filament_m);
model_used_filaments_g_all_plates.push_back(model_used_filament_g);
}
for (auto it = flushed_volume_of_extruders_all_plates.begin(); it != flushed_volume_of_extruders_all_plates.end(); it++) {
auto [flushed_filament_m, flushed_filament_g] = get_used_filament_from_volume(it->second, it->first);
if (flushed_filament_m != 0.0 || flushed_filament_g != 0.0)
show_detailed_statistics_page = true;
displayed_columns |= ColumnData::Flushed;
flushed_filaments_m_all_plates.push_back(flushed_filament_m);
flushed_filaments_g_all_plates.push_back(flushed_filament_g);
}
for (auto it = wipe_tower_volume_of_extruders_all_plates.begin(); it != wipe_tower_volume_of_extruders_all_plates.end(); it++) {
auto [wipe_tower_filament_m, wipe_tower_filament_g] = get_used_filament_from_volume(it->second, it->first);
if (wipe_tower_filament_m != 0.0 || wipe_tower_filament_g != 0.0)
displayed_columns |= ColumnData::WipeTower;
wipe_tower_used_filaments_m_all_plates.push_back(wipe_tower_filament_m);
wipe_tower_used_filaments_g_all_plates.push_back(wipe_tower_filament_g);
}
char buff[64];
double longest_str = 0.0;
@ -4207,25 +4233,40 @@ void GCodeViewer::render_all_plates_stats(const std::vector<const GCodeProcessor
longest_str = i;
}
::sprintf(buff, "%.2f", longest_str);
offsets = calculate_offsets({ {_u8L("Filament"), {""}}, {_u8L("Model"), {buff}}, {_u8L("Flushed"), {buff}}, /*{_u8L("Tower"), total_filaments},*/ {_u8L("Total"), {buff}} }, icon_size);
if (!show_detailed_statistics_page)
if (displayed_columns == ColumnData::Model) {
offsets = calculate_offsets({ {_u8L("Filament"), {""}}, {_u8L("Model"), {buff}}, {_u8L("Flushed"), {buff}}, {_u8L("Total"), {buff}} }, icon_size);
append_headers({ {_u8L("Filament"), offsets[0]}, {_u8L("Model"), offsets[2]} });
else
append_headers({ {_u8L("Filament"), offsets[0]}, {_u8L("Model"), offsets[1]}, {_u8L("Flushed"), offsets[2]}, /*{_u8L("Tower"), offsets[3]},*/ {_u8L("Total"), offsets[3]} });// to add Tower
}
else if (displayed_columns == (ColumnData::Model | ColumnData::Flushed)) {
offsets = calculate_offsets({ {_u8L("Filament"), {""}}, {_u8L("Model"), {buff}}, {_u8L("Flushed"), {buff}}, {_u8L("Total"), {buff}} }, icon_size);
append_headers({ {_u8L("Filament"), offsets[0]}, {_u8L("Model"), offsets[1]}, {_u8L("Flushed"), offsets[2]}, {_u8L("Total"), offsets[3]} });
}
else {
if (displayed_columns != (ColumnData::Model | ColumnData::Flushed | ColumnData::WipeTower))
displayed_columns = (ColumnData::Model | ColumnData::Flushed | ColumnData::WipeTower);
offsets = calculate_offsets({ {_u8L("Filament"), {""}}, {_u8L("Model"), {buff}}, {_u8L("Flushed"), {buff}}, {_u8L("Tower"), {buff}}, {_u8L("Total"), {buff}} }, icon_size);
append_headers({ {_u8L("Filament"), offsets[0]}, {_u8L("Model"), offsets[1]}, {_u8L("Flushed"), offsets[2]}, {_u8L("Tower"), offsets[3]}, {_u8L("Total"), offsets[4]} });
}
}
// item
{
size_t i = 0;
for (auto it = volume_of_extruders_all_plates.begin(); it != volume_of_extruders_all_plates.end(); it++) {
for (auto it = model_volume_of_extruders_all_plates.begin(); it != model_volume_of_extruders_all_plates.end(); it++) {
if (i < model_used_filaments_m_all_plates.size() && i < model_used_filaments_g_all_plates.size()) {
std::vector<std::pair<std::string, float>> columns_offsets;
columns_offsets.push_back({ std::to_string(it->first + 1), offsets[0] });
char buf[64];
double unit_conver = imperial_units ? GizmoObjectManipulation::oz_to_g : 1.0;
if (show_detailed_statistics_page) {
if (displayed_columns == ColumnData::Model) {
char buf[64];
::sprintf(buf, imperial_units ? "%.2f in %.2f oz" : "%.2f m %.2f g", model_used_filaments_m_all_plates[i], model_used_filaments_g_all_plates[i] / unit_conver);
columns_offsets.push_back({ buf, offsets[2] });
}
if (displayed_columns == (ColumnData::Model | ColumnData::Flushed)) {
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", model_used_filaments_m_all_plates[i], model_used_filaments_g_all_plates[i] / unit_conver);
columns_offsets.push_back({ buf, offsets[1] });
@ -4233,12 +4274,22 @@ void GCodeViewer::render_all_plates_stats(const std::vector<const GCodeProcessor
columns_offsets.push_back({ buf, offsets[2] });
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", (model_used_filaments_m_all_plates[i] + flushed_filaments_m_all_plates[i]),
(model_used_filaments_g_all_plates[i] + flushed_filaments_g_all_plates[i]) / unit_conver);
(model_used_filaments_g_all_plates[i] + flushed_filaments_g_all_plates[i]) / unit_conver);
columns_offsets.push_back({ buf, offsets[3] });
}
else {
::sprintf(buf, imperial_units ? "%.2f in %.2f oz" : "%.2f m %.2f g", model_used_filaments_m_all_plates[i], model_used_filaments_g_all_plates[i] / unit_conver);
if (displayed_columns == (ColumnData::Model | ColumnData::Flushed | ColumnData::WipeTower)) {
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", model_used_filaments_m_all_plates[i], model_used_filaments_g_all_plates[i] / unit_conver);
columns_offsets.push_back({ buf, offsets[1] });
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", flushed_filaments_m_all_plates[i], flushed_filaments_g_all_plates[i] / unit_conver);
columns_offsets.push_back({ buf, offsets[2] });
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", wipe_tower_used_filaments_m_all_plates[i], wipe_tower_used_filaments_g_all_plates[i] / unit_conver);
columns_offsets.push_back({ buf, offsets[3] });
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", (model_used_filaments_m_all_plates[i] + flushed_filaments_m_all_plates[i] + wipe_tower_used_filaments_m_all_plates[i]),
(model_used_filaments_g_all_plates[i] + flushed_filaments_g_all_plates[i] + wipe_tower_used_filaments_g_all_plates[i]) / unit_conver);
columns_offsets.push_back({ buf, offsets[4] });
}
append_item(filament_colors[it->first], columns_offsets);
@ -4619,8 +4670,17 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
std::vector<double> flushed_filaments_m;
std::vector<double> flushed_filaments_g;
double total_flushed_filament_m = 0, total_flushed_filament_g = 0;
bool show_model_used_filaments = true;
bool show_flushed_filaments = true;
std::vector<double> wipe_tower_used_filaments_m;
std::vector<double> wipe_tower_used_filaments_g;
double total_wipe_tower_used_filament_m = 0, total_wipe_tower_used_filament_g = 0;
struct ColumnData {
enum {
Model = 1,
Flushed = 2,
WipeTower = 4,
};
};
int displayed_columns = 0;
const PrintStatistics& ps = wxGetApp().plater()->get_partplate_list().get_current_fff_print().print_statistics();
double koef = imperial_units ? GizmoObjectManipulation::in_to_mm : 1000.0;
double unit_conver = imperial_units ? GizmoObjectManipulation::oz_to_g : 1;
@ -4701,39 +4761,76 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
case EViewType::ColorPrint:
{
for (size_t extruder_id : m_extruder_ids) {
if (m_print_statistics.volumes_per_extruder.find(extruder_id) == m_print_statistics.volumes_per_extruder.end()) continue;
double volume = m_print_statistics.volumes_per_extruder.at(extruder_id);
auto [model_used_filament_m, model_used_filament_g] = get_used_filament_from_volume(volume, extruder_id);
model_used_filaments_m.push_back(model_used_filament_m);
model_used_filaments_g.push_back(model_used_filament_g);
total_model_used_filament_m += model_used_filament_m;
total_model_used_filament_g += model_used_filament_g;
if (m_print_statistics.volumes_per_extruder.find(extruder_id) == m_print_statistics.volumes_per_extruder.end()) {
model_used_filaments_m.push_back(0.0);
model_used_filaments_g.push_back(0.0);
}
else {
double volume = m_print_statistics.volumes_per_extruder.at(extruder_id);
auto [model_used_filament_m, model_used_filament_g] = get_used_filament_from_volume(volume, extruder_id);
model_used_filaments_m.push_back(model_used_filament_m);
model_used_filaments_g.push_back(model_used_filament_g);
total_model_used_filament_m += model_used_filament_m;
total_model_used_filament_g += model_used_filament_g;
displayed_columns |= ColumnData::Model;
}
}
if (model_used_filaments_m.size() == 0 || model_used_filaments_g.size() == 0)
show_model_used_filaments = false;
for (size_t extruder_id : m_extruder_ids) {
if (m_print_statistics.flush_per_filament.find(extruder_id) == m_print_statistics.flush_per_filament.end()) continue;
double volume = m_print_statistics.flush_per_filament.at(extruder_id);
auto [flushed_filament_m, flushed_filament_g] = get_used_filament_from_volume(volume, extruder_id);
flushed_filaments_m.push_back(flushed_filament_m);
flushed_filaments_g.push_back(flushed_filament_g);
total_flushed_filament_m += flushed_filament_m;
total_flushed_filament_g += flushed_filament_g;
if (m_print_statistics.wipe_tower_volumes_per_extruder.find(extruder_id) == m_print_statistics.wipe_tower_volumes_per_extruder.end()) {
wipe_tower_used_filaments_m.push_back(0.0);
wipe_tower_used_filaments_g.push_back(0.0);
}
else {
double volume = m_print_statistics.wipe_tower_volumes_per_extruder.at(extruder_id);
auto [wipe_tower_used_filament_m, wipe_tower_used_filament_g] = get_used_filament_from_volume(volume, extruder_id);
wipe_tower_used_filaments_m.push_back(wipe_tower_used_filament_m);
wipe_tower_used_filaments_g.push_back(wipe_tower_used_filament_g);
total_wipe_tower_used_filament_m += wipe_tower_used_filament_m;
total_wipe_tower_used_filament_g += wipe_tower_used_filament_g;
displayed_columns |= ColumnData::WipeTower;
}
}
for (size_t extruder_id : m_extruder_ids) {
if (m_print_statistics.flush_per_filament.find(extruder_id) == m_print_statistics.flush_per_filament.end()) {
flushed_filaments_m.push_back(0.0);
flushed_filaments_g.push_back(0.0);
}
else {
double volume = m_print_statistics.flush_per_filament.at(extruder_id);
auto [flushed_filament_m, flushed_filament_g] = get_used_filament_from_volume(volume, extruder_id);
flushed_filaments_m.push_back(flushed_filament_m);
flushed_filaments_g.push_back(flushed_filament_g);
total_flushed_filament_m += flushed_filament_m;
total_flushed_filament_g += flushed_filament_g;
displayed_columns |= ColumnData::Flushed;
}
}
if (flushed_filaments_m.size() == 0 || flushed_filaments_g.size() == 0)
show_flushed_filaments = false;
std::vector<std::string> total_filaments;
char buffer[64];
::sprintf(buffer, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", ps.total_used_filament / /*1000*/koef, ps.total_weight / unit_conver);
total_filaments.push_back(buffer);
offsets = calculate_offsets({ {_u8L("Filament"), {""}}, {_u8L("Model"), total_filaments}, {_u8L("Flushed"), total_filaments}, /*{_u8L("Tower"), total_filaments},*/ {_u8L("Total"), total_filaments} }, icon_size);
if (m_extruder_ids.size() <= 1 || !show_flushed_filaments)
if (displayed_columns == ColumnData::Model) {
offsets = calculate_offsets({ {_u8L("Filament"), {""}}, {_u8L("Model"), total_filaments}, {_u8L("Flushed"), total_filaments}, {_u8L("Total"), total_filaments} }, icon_size);
append_headers({ {_u8L("Filament"), offsets[0]}, {_u8L("Model"), offsets[2]}});
else
append_headers({ {_u8L("Filament"), offsets[0]}, {_u8L("Model"), offsets[1]}, {_u8L("Flushed"), offsets[2]}, /*{_u8L("Tower"), offsets[3]},*/ {_u8L("Total"), offsets[3]}});// to add Tower
}
else if (displayed_columns == (ColumnData::Model | ColumnData::Flushed)) {
offsets = calculate_offsets({ {_u8L("Filament"), {""}}, {_u8L("Model"), total_filaments}, {_u8L("Flushed"), total_filaments}, {_u8L("Total"), total_filaments} }, icon_size);
append_headers({ {_u8L("Filament"), offsets[0]}, {_u8L("Model"), offsets[1]}, {_u8L("Flushed"), offsets[2]}, {_u8L("Total"), offsets[3]} });
}
else {
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "displayed_columns: " << displayed_columns;
if (displayed_columns != (ColumnData::Model | ColumnData::Flushed | ColumnData::WipeTower))
displayed_columns = (ColumnData::Model | ColumnData::Flushed | ColumnData::WipeTower);
offsets = calculate_offsets({ {_u8L("Filament"), {""}}, {_u8L("Model"), total_filaments}, {_u8L("Flushed"), total_filaments}, {_u8L("Tower"), total_filaments}, {_u8L("Total"), total_filaments} }, icon_size);
append_headers({ {_u8L("Filament"), offsets[0]}, {_u8L("Model"), offsets[1]}, {_u8L("Flushed"), offsets[2]}, {_u8L("Tower"), offsets[3]}, {_u8L("Total"), offsets[4]} });
}
break;
}
default: { break; }
@ -4824,8 +4921,8 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 3.0f));
append_item(EItemType::None, Travel_Colors[0], { {_u8L("travel"), offsets[0] }}, true, travel_visible, [this, travel_visible]() {
m_buffers[buffer_id(EMoveType::Travel)].visible = !m_buffers[buffer_id(EMoveType::Travel)].visible;
// update buffers' render paths
refresh_render_paths(false, false);
// update buffers' render paths, and update m_tools.m_tool_colors and m_extrusions.ranges
refresh(*m_gcode_result, wxGetApp().plater()->get_extruder_colors_from_plater_config(m_gcode_result));
update_moves_slider();
wxGetApp().plater()->get_current_canvas3D()->set_as_dirty();
});
@ -4854,105 +4951,69 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
//BBS: replace model custom gcode with current plate custom gcode
const std::vector<CustomGCode::Item>& custom_gcode_per_print_z = wxGetApp().is_editor() ? wxGetApp().plater()->model().get_curr_plate_custom_gcodes().gcodes : m_custom_gcode_per_print_z;
size_t total_items = 1;
for (size_t extruder_id : m_extruder_ids) {
total_items += color_print_ranges(extruder_id, custom_gcode_per_print_z).size();
}
// BBS: no ColorChange type, use ToolChange
//for (size_t extruder_id : m_extruder_ids) {
// total_items += color_print_ranges(extruder_id, custom_gcode_per_print_z).size();
//}
const bool need_scrollable = static_cast<float>(total_items) * (icon_size + ImGui::GetStyle().ItemSpacing.y) > child_height;
// add scrollable region, if needed
if (need_scrollable)
ImGui::BeginChild("color_prints", { -1.0f, child_height }, false);
if (m_extruder_ids.size() == 1) { // single extruder use case
const std::vector<std::pair<ColorRGBA, std::pair<double, double>>> cp_values = color_print_ranges(0, custom_gcode_per_print_z);
const int items_cnt = static_cast<int>(cp_values.size());
auto extruder_idx = m_extruder_ids[0];
if (items_cnt == 0) { // There are no color changes, but there are some pause print or custom Gcode
std::vector<std::pair<std::string, float>> columns_offsets;
columns_offsets.push_back({ std::to_string(extruder_idx + 1), offsets[0] });
// shows only extruders actually used
size_t i = 0;
for (auto extruder_idx : m_extruder_ids) {
const bool filament_visible = m_tools.m_tool_visibles[extruder_idx];
if (i < model_used_filaments_m.size() && i < model_used_filaments_g.size()) {
std::vector<std::pair<std::string, float>> columns_offsets;
columns_offsets.push_back({ std::to_string(extruder_idx + 1), offsets[0] });
char buf[64];
if (displayed_columns == ColumnData::Model) {
char buf[64];
::sprintf(buf, imperial_units ? "%.2f in %.2f oz" : "%.2f m %.2f g", model_used_filaments_m[0], model_used_filaments_g[0] / unit_conver);
::sprintf(buf, imperial_units ? "%.2f in %.2f oz" : "%.2f m %.2f g", model_used_filaments_m[i], model_used_filaments_g[i] / unit_conver);
columns_offsets.push_back({ buf, offsets[2] });
}
if (displayed_columns == (ColumnData::Model | ColumnData::Flushed)) {
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", model_used_filaments_m[i], model_used_filaments_g[i] / unit_conver);
columns_offsets.push_back({ buf, offsets[1] });
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", flushed_filaments_m[i], flushed_filaments_g[i] / unit_conver);
columns_offsets.push_back({ buf, offsets[2] });
append_item(EItemType::Rect, m_tools.m_tool_colors[extruder_idx], columns_offsets, false);
}
else {
for (int i = items_cnt; i >= 0; --i) {
// create label for color change item
if (i == 0) {
append_item(EItemType::Rect, m_tools.m_tool_colors[0], {{ upto_label(cp_values.front().second.first), offsets[1]} }, false);
break;
}
else if (i == items_cnt) {
append_item(EItemType::Rect, cp_values[i - 1].first, { {above_label(cp_values[i - 1].second.second), offsets[1]} }, false);
continue;
}
append_item(EItemType::Rect, cp_values[i - 1].first, { {fromto_label(cp_values[i - 1].second.second, cp_values[i].second.first), offsets[1]} }, false);
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", (model_used_filaments_m[i] + flushed_filaments_m[i]),
(model_used_filaments_g[i] + flushed_filaments_g[i]) / unit_conver);
columns_offsets.push_back({ buf, offsets[3] });
}
if (displayed_columns == (ColumnData::Model | ColumnData::Flushed | ColumnData::WipeTower)) {
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", model_used_filaments_m[i], model_used_filaments_g[i] / unit_conver);
columns_offsets.push_back({ buf, offsets[1] });
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", flushed_filaments_m[i], flushed_filaments_g[i] / unit_conver);
columns_offsets.push_back({ buf, offsets[2] });
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", wipe_tower_used_filaments_m[i], wipe_tower_used_filaments_g[i] / unit_conver);
columns_offsets.push_back({ buf, offsets[3] });
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", (model_used_filaments_m[i] + flushed_filaments_m[i] + wipe_tower_used_filaments_m[i]),
(model_used_filaments_g[i] + flushed_filaments_g[i] + wipe_tower_used_filaments_g[i]) / unit_conver);
columns_offsets.push_back({ buf, offsets[4] });
}
append_item(EItemType::Rect, m_tools.m_tool_colors[extruder_idx], columns_offsets, false, filament_visible, [this, extruder_idx]() {
m_tools.m_tool_visibles[extruder_idx] = !m_tools.m_tool_visibles[extruder_idx];
// update buffers' render paths
refresh_render_paths(false, false);
update_moves_slider();
wxGetApp().plater()->get_current_canvas3D()->set_as_dirty();
});
}
i++;
}
else { // multi extruder use case
// shows only extruders actually used
size_t i = 0;
for (auto extruder_idx : m_extruder_ids) {
const std::vector<std::pair<ColorRGBA, std::pair<double, double>>> cp_values = color_print_ranges(extruder_idx, custom_gcode_per_print_z);
const int items_cnt = static_cast<int>(cp_values.size());
if (items_cnt == 0) { // There are no color changes, but there are some pause print or custom Gcode
const bool filament_visible = m_tools.m_tool_visibles[extruder_idx];
if (i < model_used_filaments_m.size() && i < model_used_filaments_g.size()) {
std::vector<std::pair<std::string, float>> columns_offsets;
columns_offsets.push_back({ std::to_string(extruder_idx + 1), offsets[0] });
char buf[64];
if (show_flushed_filaments) {
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", model_used_filaments_m[i], model_used_filaments_g[i] / unit_conver);
columns_offsets.push_back({ buf, offsets[1] });
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", flushed_filaments_m[i], flushed_filaments_g[i] / unit_conver);
columns_offsets.push_back({ buf, offsets[2] });
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", (model_used_filaments_m[i] + flushed_filaments_m[i]),
(model_used_filaments_g[i] + flushed_filaments_g[i]) / unit_conver);
columns_offsets.push_back({ buf, offsets[3] });
}
else {
char buf[64];
::sprintf(buf, imperial_units ? "%.2f in %.2f oz" : "%.2f m %.2f g", model_used_filaments_m[i], model_used_filaments_g[i] / unit_conver);
columns_offsets.push_back({buf, offsets[2]});
}
append_item(EItemType::Rect, m_tools.m_tool_colors[extruder_idx], columns_offsets, false, filament_visible, [this, extruder_idx]() {
m_tools.m_tool_visibles[extruder_idx] = !m_tools.m_tool_visibles[extruder_idx];
// update buffers' render paths
refresh_render_paths(false, false);
update_moves_slider();
wxGetApp().plater()->get_current_canvas3D()->set_as_dirty();
});
}
}
else {
for (int j = items_cnt; j >= 0; --j) {
// create label for color change item
std::string label = _u8L("Filament") + " " + std::to_string(extruder_idx + 1);
if (j == 0) {
label += " " + upto_label(cp_values.front().second.first);
append_item(EItemType::Rect, m_tools.m_tool_colors[extruder_idx], { { label, 0 } }, false);
break;
}
else if (j == items_cnt) {
label += " " + above_label(cp_values[j - 1].second.second);
append_item(EItemType::Rect, cp_values[j - 1].first, { { label, 0 } }, false);
continue;
}
label += " " + fromto_label(cp_values[j - 1].second.second, cp_values[j].second.first);
append_item(EItemType::Rect, cp_values[j - 1].first, { { label, 0 } }, false);
}
}
i++;
}
}
if (need_scrollable)
ImGui::EndChild();
@ -4967,13 +5028,13 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
std::vector<std::pair<std::string, float>> columns_offsets;
columns_offsets.push_back({ _u8L("Total"), offsets[0] });
if (!show_flushed_filaments) {
if (displayed_columns == ColumnData::Model) {
::sprintf(buf, imperial_units ? "%.2f in %.2f oz" : "%.2f m %.2f g", total_model_used_filament_m, total_model_used_filament_g / unit_conver);
columns_offsets.push_back({ buf, offsets[2] });
append_item(EItemType::None, m_tools.m_tool_colors[0], columns_offsets);
}
else {
if (displayed_columns == (ColumnData::Model | ColumnData::Flushed)) {
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", total_model_used_filament_m, total_model_used_filament_g / unit_conver);
columns_offsets.push_back({ buf, offsets[1] });
@ -4981,9 +5042,25 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv
columns_offsets.push_back({ buf, offsets[2] });
bool imperial_units = wxGetApp().app_config->get("use_inches") == "1";
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", total_model_used_filament_m + total_flushed_filament_m, (total_model_used_filament_g + total_flushed_filament_g) / unit_conver);
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", total_model_used_filament_m + total_flushed_filament_m , (total_model_used_filament_g + total_flushed_filament_g) / unit_conver);
columns_offsets.push_back({ buf, offsets[3] });
append_item(EItemType::None, m_tools.m_tool_colors[0], columns_offsets);
}
if (displayed_columns == (ColumnData::Model | ColumnData::Flushed | ColumnData::WipeTower)) {
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", total_model_used_filament_m, total_model_used_filament_g / unit_conver);
columns_offsets.push_back({ buf, offsets[1] });
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", total_flushed_filament_m, total_flushed_filament_g / unit_conver);
columns_offsets.push_back({ buf, offsets[2] });
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", total_wipe_tower_used_filament_m, total_wipe_tower_used_filament_g / unit_conver);
columns_offsets.push_back({ buf, offsets[3] });
bool imperial_units = wxGetApp().app_config->get("use_inches") == "1";
::sprintf(buf, imperial_units ? "%.2f in\n%.2f oz" : "%.2f m\n%.2f g", total_model_used_filament_m + total_flushed_filament_m + total_wipe_tower_used_filament_m, (total_model_used_filament_g + total_flushed_filament_g + total_wipe_tower_used_filament_g) / unit_conver);
columns_offsets.push_back({ buf, offsets[4] });
append_item(EItemType::None, m_tools.m_tool_colors[0], columns_offsets);
}
}

View file

@ -772,6 +772,7 @@ private:
std::vector<EMoveType> options_items;
bool m_legend_enabled{ true };
float m_legend_height;
PrintEstimatedStatistics m_print_statistics;
PrintEstimatedStatistics::ETimeMode m_time_estimate_mode{ PrintEstimatedStatistics::ETimeMode::Normal };
#if ENABLE_GCODE_VIEWER_STATISTICS
@ -810,7 +811,7 @@ public:
void reset();
//BBS: always load shell at preview
void reset_shell();
void load_shells(const Print& print, bool force_previewing = false);
void load_shells(const Print& print, bool initialized, bool force_previewing = false);
void set_shells_on_preview(bool is_previewing) { m_shells.previewing = is_previewing; }
//BBS: add all plates filament statistics
void render_all_plates_stats(const std::vector<const GCodeProcessorResult*>& gcode_result_list, bool show = true) const;
@ -877,6 +878,7 @@ public:
bool is_legend_enabled() const { return m_legend_enabled; }
void enable_legend(bool enable) { m_legend_enabled = enable; }
float get_legend_height() { return m_legend_height; }
void export_toolpaths_to_obj(const char* filename) const;

View file

@ -41,6 +41,7 @@
#include "I18N.hpp"
#include "NotificationManager.hpp"
#include "format.hpp"
#include "DailyTips.hpp"
#include "slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp"
#include "slic3r/Utils/UndoRedo.hpp"
@ -1134,6 +1135,7 @@ GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas, Bed3D &bed)
, m_moving(false)
, m_tab_down(false)
, m_cursor_type(Standard)
, m_color_by("volume")
, m_reload_delayed(false)
, m_render_sla_auxiliaries(true)
, m_labels(*this)
@ -1234,6 +1236,8 @@ void GLCanvas3D::on_change_color_mode(bool is_dark, bool reinit) {
wxGetApp().imgui()->on_change_color_mode(is_dark);
// Notification
wxGetApp().plater()->get_notification_manager()->on_change_color_mode(is_dark);
// DailyTips Window
wxGetApp().plater()->get_dailytips()->on_change_color_mode(is_dark);
// Preview Slider
IMSlider* m_layers_slider = get_gcode_viewer().get_layers_slider();
IMSlider* m_moves_slider = get_gcode_viewer().get_moves_slider();
@ -1472,6 +1476,11 @@ Camera& GLCanvas3D::get_camera()
return camera;
}
void GLCanvas3D::set_color_by(const std::string& value)
{
m_color_by = value;
}
void GLCanvas3D::refresh_camera_scene_box()
{
wxGetApp().plater()->get_camera().set_scene_box(scene_bounding_box());
@ -1726,47 +1735,6 @@ bool GLCanvas3D::make_current_for_postinit() {
return _set_current();
}
Points GLCanvas3D::estimate_wipe_tower_points(int plate_index, bool global) const
{
PartPlateList & ppl = wxGetApp().plater()->get_partplate_list();
DynamicPrintConfig &proj_cfg = wxGetApp().preset_bundle->project_config;
auto & print = wxGetApp().plater()->get_partplate_list().get_current_fff_print();
int plate_count = ppl.get_plate_count();
float x = dynamic_cast<const ConfigOptionFloats *>(proj_cfg.option("wipe_tower_x"))->get_at(plate_index);
float y = dynamic_cast<const ConfigOptionFloats *>(proj_cfg.option("wipe_tower_y"))->get_at(plate_index);
if (plate_index >= plate_count) { plate_index = 0; }
float w = dynamic_cast<const ConfigOptionFloat *>(m_config->option("prime_tower_width"))->value;
auto part_plate = ppl.get_plate(plate_index);
const auto &wipe_tower_data = print.wipe_tower_data(part_plate->get_extruders(true).size());
// float v = dynamic_cast<const ConfigOptionFloat *>(m_config->option("prime_volume"))->value;
const DynamicPrintConfig &print_cfg = wxGetApp().preset_bundle->prints.get_edited_preset().config;
Vec3d wipe_tower_size = part_plate->estimate_wipe_tower_size(print_cfg, w, wipe_tower_data.depth);
if (wipe_tower_size(1) == 0) {
// when depth is unavailable (no items on this plate), we have to estimate the depth using the extruder number of all plates
std::set<int> extruder_ids;
if (global) {
auto objs = wxGetApp().obj_list()->objects();
for (ModelObject *obj : *objs) {
for (ModelVolume *volume : obj->volumes) {
std::vector<int> es = volume->get_extruders();
extruder_ids.insert(es.begin(), es.end());
}
}
} else {
PartPlate* pl = ppl.get_plate(plate_index);
std::vector<int> es = pl->get_extruders();
extruder_ids.insert(es.begin(), es.end());
}
int extruder_size = extruder_ids.size();
wipe_tower_size(1) = extruder_size * print.wipe_tower_data(extruder_size).depth + 2 * print.wipe_tower_data().brim_width;
}
Vec3d plate_origin = ppl.get_plate(plate_index)->get_origin();
Point wt_min_corner{scale_(x), scale_(y)};
Point wt_max_corner(scale_(x + wipe_tower_size(0)), scale_(y + wipe_tower_size(1)));
return {wt_min_corner, {wt_max_corner.x(), wt_min_corner.y()}, wt_max_corner, {wt_min_corner.x(), wt_max_corner.y()}};
}
void GLCanvas3D::render(bool only_init)
{
if (m_in_render) {
@ -2021,6 +1989,7 @@ void GLCanvas3D::render(bool only_init)
bottom_margin = SLIDER_BOTTOM_MARGIN * scale_factor * GCODE_VIEWER_SLIDER_SCALE;
}
wxGetApp().plater()->get_notification_manager()->render_notifications(*this, get_overlay_window_width(), bottom_margin, right_margin);
wxGetApp().plater()->get_dailytips()->render();
}
wxGetApp().imgui()->render();
@ -2068,6 +2037,11 @@ void GLCanvas3D::select_curr_plate_all()
m_dirty = true;
}
void GLCanvas3D::select_object_from_idx(std::vector<int>& object_idxs) {
m_selection.add_object_from_idx(object_idxs);
m_dirty = true;
}
//BBS
void GLCanvas3D::remove_curr_plate_all()
{
@ -2173,7 +2147,7 @@ std::vector<int> GLCanvas3D::load_object(const ModelObject& model_object, int ob
instance_idxs.emplace_back(i);
}
}
return m_volumes.load_object(&model_object, obj_idx, instance_idxs);
return m_volumes.load_object(&model_object, obj_idx, instance_idxs, m_color_by, m_initialized);
}
std::vector<int> GLCanvas3D::load_object(const Model& model, int obj_idx)
@ -2484,7 +2458,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
// Note the index of the loaded volume, so that we can reload the main model GLVolume with the hollowed mesh
// later in this function.
it->volume_idx = m_volumes.volumes.size();
m_volumes.load_object_volume(&model_object, obj_idx, volume_idx, instance_idx, m_canvas_type == ECanvasType::CanvasAssembleView);
m_volumes.load_object_volume(&model_object, obj_idx, volume_idx, instance_idx, m_color_by, m_initialized, m_canvas_type == ECanvasType::CanvasAssembleView);
m_volumes.volumes.back()->geometry_id = key.geometry_id;
update_object_list = true;
} else {
@ -2638,19 +2612,36 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
const DynamicPrintConfig &print_cfg = wxGetApp().preset_bundle->prints.get_edited_preset().config;
Vec3d wipe_tower_size = ppl.get_plate(plate_id)->estimate_wipe_tower_size(print_cfg, w, wipe_tower_data.depth);
const float margin = 15.f;
const float margin = WIPE_TOWER_MARGIN;
BoundingBoxf3 plate_bbox = wxGetApp().plater()->get_partplate_list().get_plate(plate_id)->get_bounding_box();
coordf_t plate_bbox_x_max_local_coord = plate_bbox.max(0) - plate_origin(0);
coordf_t plate_bbox_y_max_local_coord = plate_bbox.max(1) - plate_origin(1);
bool need_update = false;
if (x + margin + wipe_tower_size(0) > plate_bbox_x_max_local_coord) {
x = plate_bbox_x_max_local_coord - wipe_tower_size(0) - margin;
need_update = true;
}
else if (x < margin) {
x = margin;
need_update = true;
}
if (need_update) {
ConfigOptionFloat wt_x_opt(x);
dynamic_cast<ConfigOptionFloats *>(proj_cfg.option("wipe_tower_x"))->set_at(&wt_x_opt, plate_id, 0);
need_update = false;
}
if (y + margin + wipe_tower_size(1) > plate_bbox_y_max_local_coord) {
y = plate_bbox_y_max_local_coord - wipe_tower_size(1) - margin;
need_update = true;
}
else if (y < margin) {
y = margin;
need_update = true;
}
if (need_update) {
ConfigOptionFloat wt_y_opt(y);
dynamic_cast<ConfigOptionFloats*>(proj_cfg.option("wipe_tower_y"))->set_at(&wt_y_opt, plate_id, 0);
dynamic_cast<ConfigOptionFloats *>(proj_cfg.option("wipe_tower_y"))->set_at(&wt_y_opt, plate_id, 0);
}
int volume_idx_wipe_tower_new = m_volumes.load_wipe_tower_preview(
@ -2756,7 +2747,7 @@ void GLCanvas3D::load_shells(const Print& print, bool force_previewing)
{
if (m_initialized)
{
m_gcode_viewer.load_shells(print, force_previewing);
m_gcode_viewer.load_shells(print, m_initialized, force_previewing);
m_gcode_viewer.update_shells_color_by_extruder(m_config);
}
}
@ -3122,6 +3113,14 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
#endif /* __APPLE__ */
post_event(SimpleEvent(EVT_GLTOOLBAR_DELETE_ALL));
break;
#ifdef __APPLE__
case 'k':
case 'K':
#else /* __APPLE__ */
case WXK_CONTROL_K:
#endif /* __APPLE__ */
post_event(SimpleEvent(EVT_GLTOOLBAR_CLONE));
break;
default: evt.Skip();
}
} else {
@ -4708,6 +4707,13 @@ void GLCanvas3D::do_center()
m_selection.center();
}
void GLCanvas3D::do_center_plate(const int plate_idx) {
if (m_model == nullptr)
return;
m_selection.center_plate(plate_idx);
}
void GLCanvas3D::do_mirror(const std::string& snapshot_type)
{
if (m_model == nullptr)
@ -4868,6 +4874,12 @@ GLCanvas3D::WipeTowerInfo GLCanvas3D::get_wipe_tower_info(int plate_idx) const
float brim_width = wxGetApp().preset_bundle->prints.get_edited_preset().config.opt_float("prime_tower_brim_width");
wti.m_bb.offset((brim_width));
// BBS: the wipe tower pos might be outside bed
PartPlate* plate = wxGetApp().plater()->get_partplate_list().get_plate(plate_idx);
Vec2d plate_size = plate->get_size();
wti.m_pos.x() = std::clamp(wti.m_pos.x(), 0.0, plate_size(0) - wti.m_bb.size().x());
wti.m_pos.y() = std::clamp(wti.m_pos.y(), 0.0, plate_size(1) - wti.m_bb.size().y());
// BBS: add partplate logic
wti.m_plate_idx = plate_idx;
break;
@ -4898,8 +4910,8 @@ std::vector<Vec2f> GLCanvas3D::get_empty_cells(const Vec2f start_point, const Ve
Vec2d vmin(build_volume.min.x(), build_volume.min.y()), vmax(build_volume.max.x(), build_volume.max.y());
BoundingBoxf bbox(vmin, vmax);
std::vector<Vec2f> cells;
for (float x = bbox.min.x(); x < bbox.max.x(); x += step(0))
for (float y = bbox.min.y(); y < bbox.max.y(); y += step(1))
for (float x = bbox.min.x()+step(0)/2; x < bbox.max.x()-step(0)/2; x += step(0))
for (float y = bbox.min.y()+step(1)/2; y < bbox.max.y()-step(1)/2; y += step(1))
{
cells.emplace_back(x, y);
}
@ -6123,6 +6135,7 @@ bool GLCanvas3D::_init_main_toolbar()
item.left.render_callback = nullptr;
item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_SPLIT_OBJECTS)); };
item.visibility_callback = GLToolbarItem::Default_Visibility_Callback;
item.left.toggable = false;
item.enabling_callback = []()->bool { return wxGetApp().plater()->can_split_to_objects(); };
if (!m_main_toolbar.add_item(item))
return false;
@ -7624,6 +7637,7 @@ void GLCanvas3D::_render_imgui_select_plate_toolbar()
m_sel_plate_toolbar.m_items[i]->selected = false;
}
all_plates_stats_item->selected = true;
wxGetApp().plater()->update(true, true);
wxCommandEvent evt = wxCommandEvent(EVT_GLTOOLBAR_SLICE_ALL);
wxPostEvent(wxGetApp().plater(), evt);
}
@ -7708,6 +7722,8 @@ void GLCanvas3D::_render_imgui_select_plate_toolbar()
all_plates_stats_item->selected = false;
item->selected = true;
// begin to slicing plate
if (item->slice_state != IMToolbarItem::SliceState::SLICED)
wxGetApp().plater()->update(true, true);
wxCommandEvent* evt = new wxCommandEvent(EVT_GLTOOLBAR_SELECT_SLICED_PLATE);
evt->SetInt(i);
wxQueueEvent(wxGetApp().plater(), evt);
@ -9176,13 +9192,13 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state)
break;
case SLICING_SERIOUS_WARNING:
if (state)
notification_manager.push_slicing_serious_warning_notification(text, {conflictObj});
notification_manager.push_slicing_serious_warning_notification(text, conflictObj ? std::vector<ModelObject const*>{conflictObj} : std::vector<ModelObject const*>{});
else
notification_manager.close_slicing_serious_warning_notification(text);
break;
case SLICING_ERROR:
if (state)
notification_manager.push_slicing_error_notification(text, {conflictObj});
notification_manager.push_slicing_error_notification(text, conflictObj ? std::vector<ModelObject const*>{conflictObj} : std::vector<ModelObject const*>{});
else
notification_manager.close_slicing_error_notification(text);
break;

View file

@ -582,6 +582,8 @@ private:
// I just don't want to do it now before a release (Lukas Matena 24.3.2019)
bool m_render_sla_auxiliaries;
std::string m_color_by;
bool m_reload_delayed;
RenderStats m_render_stats;
@ -629,7 +631,7 @@ private:
int split_to_objects_count = 0;
int split_to_part_count = 0;
int custom_height_count = 0;
int custom_painting_count = 0;
int assembly_view_count = 0;
public:
OrientSettings& get_orient_settings()
@ -812,6 +814,7 @@ public:
void set_color_clip_plane_colors(const std::array<ColorRGBA, 2>& colors) { m_volumes.set_color_clip_plane_colors(colors); }
void refresh_camera_scene_box();
void set_color_by(const std::string& value);
BoundingBoxf3 volumes_bounding_box(bool current_plate_only = false) const;
BoundingBoxf3 scene_bounding_box() const;
@ -902,6 +905,7 @@ public:
//BBS
void select_curr_plate_all();
void select_object_from_idx(std::vector<int>& object_idxs);
void remove_curr_plate_all();
void update_plate_thumbnails();
@ -967,6 +971,7 @@ public:
void do_rotate(const std::string& snapshot_type);
void do_scale(const std::string& snapshot_type);
void do_center();
void do_center_plate(const int plate_idx);
void do_mirror(const std::string& snapshot_type);
void update_gizmos_on_off_state();
@ -1108,9 +1113,6 @@ public:
bool make_current_for_postinit();
//BBS
Points estimate_wipe_tower_points(int plate_index, bool global = true) const;
private:
bool _is_shown_on_screen() const;

View file

@ -100,6 +100,7 @@
#include "ReleaseNote.hpp"
#include "PrivacyUpdateDialog.hpp"
#include "ModelMall.hpp"
#include "HintNotification.hpp"
//#ifdef WIN32
//#include "BaseException.h"
@ -1020,6 +1021,14 @@ void GUI_App::post_init()
if (! this->initialized())
throw Slic3r::RuntimeError("Calling post_init() while not yet initialized");
if (app_config->get("sync_user_preset") == "true") {
// BBS loading user preset
// Always async, not such startup step
// BOOST_LOG_TRIVIAL(info) << "Loading user presets...";
// scrn->SetText(_L("Loading user presets..."));
if (m_agent) { start_sync_user_preset(); }
}
bool switch_to_3d = false;
if (!this->init_params->input_files.empty()) {
@ -1242,8 +1251,6 @@ void GUI_App::post_init()
hms_query->check_hms_info();
});
std::string functional_config_file = Slic3r::resources_dir() + "/config.json";
DeviceManager::load_functional_config(encode_path(functional_config_file.c_str()));
std::string filaments_blacklist_config_file = Slic3r::resources_dir() + "/printers/filaments_blacklist.json";
DeviceManager::load_filaments_blacklist_config(encode_path(filaments_blacklist_config_file.c_str()));
@ -1332,21 +1339,6 @@ void GUI_App::shutdown()
if (m_is_recreating_gui) return;
m_is_closing = true;
stop_sync_user_preset();
if (m_device_manager) {
delete m_device_manager;
m_device_manager = nullptr;
}
if (m_agent) {
//BBS avoid a crash on mac platform
#ifdef __WINDOWS__
m_agent->start_discovery(false, false);
#endif
delete m_agent;
m_agent = nullptr;
}
BOOST_LOG_TRIVIAL(info) << "GUI_App::shutdown exit";
}
@ -1848,6 +1840,8 @@ void GUI_App::init_networking_callbacks()
obj->is_tunnel_mqtt = tunnel;
obj->command_request_push_all(true);
obj->command_get_version();
obj->erase_user_access_code();
obj->command_get_access_code();
GUI::wxGetApp().sidebar().load_ams_list(obj->dev_id, obj);
}
});
@ -1860,6 +1854,12 @@ void GUI_App::init_networking_callbacks()
}
);
m_agent->set_on_subscribe_failure_fn([this](std::string dev_id) {
CallAfter([this, dev_id] {
on_start_subscribe_again(dev_id);
});
});
m_agent->set_on_local_connect_fn(
[this](int state, std::string dev_id, std::string msg) {
if (m_is_closing) {
@ -2220,7 +2220,8 @@ void GUI_App::on_start_subscribe_again(std::string dev_id)
MachineObject* obj = dev->get_selected_machine();
if (!obj) return;
if ( (dev_id == obj->dev_id) && obj->is_connecting() ) {
if ( (dev_id == obj->dev_id) && obj->is_connecting() && obj->subscribe_counter > 0) {
obj->subscribe_counter--;
if(wxGetApp().getAgent()) wxGetApp().getAgent()->set_user_selected_machine(dev_id);
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": dev_id=" << obj->dev_id;
}
@ -2263,6 +2264,27 @@ bool GUI_App::OnInit()
}
}
int GUI_App::OnExit()
{
stop_sync_user_preset();
if (m_device_manager) {
delete m_device_manager;
m_device_manager = nullptr;
}
if (m_agent) {
// BBS avoid a crash on mac platform
#ifdef __WINDOWS__
m_agent->start_discovery(false, false);
#endif
delete m_agent;
m_agent = nullptr;
}
return wxApp::OnExit();
}
class wxBoostLog : public wxLog
{
void DoLogText(const wxString &msg) override {
@ -2496,7 +2518,6 @@ bool GUI_App::on_init_inner()
dialog.SetExtendedMessage(extmsg);*/
std::string skip_version_str = this->app_config->get("app", "skip_version");
bool skip_this_version = false;
if (!skip_version_str.empty()) {
@ -2515,7 +2536,7 @@ bool GUI_App::on_init_inner()
dialog.update_version_info(extmsg, version_info.version_str);
//dialog.update_version_info(version_info.description);
if (evt.GetInt() != 0) {
dialog.m_remind_choice->Hide();
dialog.m_button_skip_version->Hide();
}
switch (dialog.ShowModal())
{
@ -2612,16 +2633,6 @@ bool GUI_App::on_init_inner()
}
//}
if (app_config->get("sync_user_preset") == "true") {
//BBS loading user preset
// Always async, not such startup step
//BOOST_LOG_TRIVIAL(info) << "Loading user presets...";
//scrn->SetText(_L("Loading user presets..."));
if (m_agent) {
start_sync_user_preset();
}
}
#ifdef WIN32
#if !wxVERSION_EQUAL_OR_GREATER_THAN(3,1,3)
register_win32_dpi_event();
@ -2879,14 +2890,16 @@ __retry:
if (create_network_agent) {
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", create network agent...");
m_agent = new Slic3r::NetworkAgent();
//std::string data_dir = wxStandardPaths::Get().GetUserDataDir().ToUTF8().data();
std::string data_directory = data_dir();
m_agent = new Slic3r::NetworkAgent(data_directory);
if (!m_device_manager)
m_device_manager = new Slic3r::DeviceManager(m_agent);
else
m_device_manager->set_agent(m_agent);
//std::string data_dir = wxStandardPaths::Get().GetUserDataDir().ToUTF8().data();
std::string data_directory = data_dir();
//BBS set config dir
if (m_agent) {
@ -3009,7 +3022,7 @@ void GUI_App::update_publish_status()
bool GUI_App::has_model_mall()
{
if (auto cc = app_config->get_country_code(); cc == "CN" || cc == "")
if (auto cc = app_config->get_region(); cc == "CNH" || cc == "China" || cc == "")
return false;
return true;
}
@ -4049,8 +4062,8 @@ void GUI_App::on_http_error(wxCommandEvent &evt)
if (code == HttpErrorVersionLimited) {
MessageDialog msg_dlg(nullptr, _L("The version of Orca Slicer is too low and needs to be updated to the latest version before it can be used normally"), "", wxAPPLY | wxOK);
if (msg_dlg.ShowModal() == wxOK) {
return;
}
}
// request login
@ -4058,9 +4071,15 @@ void GUI_App::on_http_error(wxCommandEvent &evt)
if (m_agent) {
if (m_agent->is_user_login()) {
this->request_user_logout();
MessageDialog msg_dlg(nullptr, _L("Login information expired. Please login again."), "", wxAPPLY | wxOK);
if (msg_dlg.ShowModal() == wxOK) {
return;
if (!m_show_http_errpr_msgdlg) {
MessageDialog msg_dlg(nullptr, _L("Login information expired. Please login again."), "", wxAPPLY | wxOK);
m_show_http_errpr_msgdlg = true;
auto modal_result = msg_dlg.ShowModal();
if (modal_result == wxOK || modal_result == wxCLOSE) {
m_show_http_errpr_msgdlg = false;
return;
}
}
}
}
@ -4516,6 +4535,7 @@ void GUI_App::reload_settings()
if (preset_bundle && m_agent) {
std::map<std::string, std::map<std::string, std::string>> user_presets;
m_agent->get_user_presets(&user_presets);
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << __LINE__ << " cloud user preset number is: " << user_presets.size();
preset_bundle->load_user_presets(*app_config, user_presets, ForwardCompatibilitySubstitutionRule::Enable);
preset_bundle->save_user_presets(*app_config, get_delete_cache_presets());
mainframe->update_side_preset_ui();
@ -4542,18 +4562,25 @@ void GUI_App::sync_preset(Preset* preset)
int result = -1;
unsigned int http_code = 200;
std::string updated_info;
long long update_time = 0;
// only sync user's preset
if (!preset->is_user()) return;
if (preset->is_custom_defined()) return;
if (preset->setting_id.empty() && preset->sync_info.empty() && !preset->base_id.empty()) {
std::map<std::string, std::string> values_map;
auto setting_id = preset->setting_id;
std::map<std::string, std::string> values_map;
if (setting_id.empty() && preset->sync_info.empty()) {
if (m_create_preset_blocked[preset->type])
return;
int ret = preset_bundle->get_differed_values_to_update(*preset, values_map);
if (!ret) {
std::string new_setting_id = m_agent->request_setting_id(preset->name, &values_map, &http_code);
if (!new_setting_id.empty()) {
preset->setting_id = new_setting_id;
setting_id = new_setting_id;
result = 0;
auto update_time_str = values_map[BBL_JSON_KEY_UPDATE_TIME];
if (!update_time_str.empty())
update_time = std::atoll(update_time_str.c_str());
}
else {
BOOST_LOG_TRIVIAL(trace) << "[sync_preset]init: request_setting_id failed, http code "<<http_code;
@ -4572,14 +4599,18 @@ void GUI_App::sync_preset(Preset* preset)
updated_info = "hold";
}
}
else if ((preset->sync_info.compare("create") == 0) && !preset->base_id.empty()) {
std::map<std::string, std::string> values_map;
else if (preset->sync_info.compare("create") == 0) {
if (m_create_preset_blocked[preset->type])
return;
int ret = preset_bundle->get_differed_values_to_update(*preset, values_map);
if (!ret) {
std::string new_setting_id = m_agent->request_setting_id(preset->name, &values_map, &http_code);
if (!new_setting_id.empty()) {
preset->setting_id = new_setting_id;
setting_id = new_setting_id;
result = 0;
auto update_time_str = values_map[BBL_JSON_KEY_UPDATE_TIME];
if (!update_time_str.empty())
update_time = std::atoll(update_time_str.c_str());
}
else {
BOOST_LOG_TRIVIAL(trace) << "[sync_preset]create: request_setting_id failed, http code "<<http_code;
@ -4596,22 +4627,25 @@ void GUI_App::sync_preset(Preset* preset)
BOOST_LOG_TRIVIAL(trace) << "[sync_preset]create: can not generate differed preset";
}
}
else if ((preset->sync_info.compare("update") == 0) && !preset->base_id.empty()) {
if (!preset->setting_id.empty()) {
std::map<std::string, std::string> values_map;
else if (preset->sync_info.compare("update") == 0) {
if (!setting_id.empty()) {
int ret = preset_bundle->get_differed_values_to_update(*preset, values_map);
if (!ret) {
if (values_map[BBL_JSON_KEY_BASE_ID] == preset->setting_id) {
//clear the setting_id in this case
preset->setting_id.clear();
if (auto iter = values_map.find(BBL_JSON_KEY_BASE_ID); iter != values_map.end() && iter->second == setting_id) {
//clear the setting_id in this case ???
setting_id.clear();
result = 0;
}
else {
result = m_agent->put_setting(preset->setting_id, preset->name, &values_map, &http_code);
result = m_agent->put_setting(setting_id, preset->name, &values_map, &http_code);
if (http_code >= 400) {
result = 0;
updated_info = "hold";
BOOST_LOG_TRIVIAL(error) << "[sync_preset] put setting_id = " << preset->setting_id << " failed, http_code = " << http_code;
BOOST_LOG_TRIVIAL(error) << "[sync_preset] put setting_id = " << setting_id << " failed, http_code = " << http_code;
} else {
auto update_time_str = values_map[BBL_JSON_KEY_UPDATE_TIME];
if (!update_time_str.empty())
update_time = std::atoll(update_time_str.c_str());
}
}
@ -4627,19 +4661,34 @@ void GUI_App::sync_preset(Preset* preset)
}
}
//update sync_info preset info in file
if (http_code >= 400 && values_map["code"] == "14") { // Limit
m_create_preset_blocked[preset->type] = true;
CallAfter([this] {
plater()->get_notification_manager()->push_notification(NotificationType::BBLUserPresetExceedLimit);
static bool dialog_notified = false;
if (dialog_notified)
return;
dialog_notified = true;
if (mainframe == nullptr)
return;
auto msg = _L("The number of user presets cached in the cloud has exceeded the upper limit, newly created user presets can only be used locally.");
MessageDialog(mainframe, msg, _L("Sync user presets"), wxICON_WARNING | wxOK).ShowModal();
});
return; // this error not need hold, and should not hold
}
// update sync_info preset info in file
if (result == 0) {
//PresetBundle* preset_bundle = wxGetApp().preset_bundle;
if (!this->preset_bundle) return;
BOOST_LOG_TRIVIAL(trace) << "sync_preset: sync operation: " << preset->sync_info << " success! preset = " << preset->name;
if (preset->type == Preset::Type::TYPE_FILAMENT) {
preset_bundle->filaments.set_sync_info_and_save(preset->name, preset->setting_id, updated_info);
preset_bundle->filaments.set_sync_info_and_save(preset->name, setting_id, updated_info, update_time);
} else if (preset->type == Preset::Type::TYPE_PRINT) {
preset_bundle->prints.set_sync_info_and_save(preset->name, preset->setting_id, updated_info);
preset_bundle->prints.set_sync_info_and_save(preset->name, setting_id, updated_info, update_time);
} else if (preset->type == Preset::Type::TYPE_PRINTER) {
preset_bundle->printers.set_sync_info_and_save(preset->name, preset->setting_id, updated_info);
preset_bundle->printers.set_sync_info_and_save(preset->name, setting_id, updated_info, update_time);
}
}
}
@ -4652,12 +4701,15 @@ void GUI_App::start_sync_user_preset(bool with_progress_dlg)
if (!m_agent || !m_agent->is_user_login()) return;
// has already start sync
if (enable_sync) return;
if (m_user_sync_token) return;
ProgressFn progressFn;
WasCancelledFn cancelFn;
std::function<void(bool)> finishFn;
BOOST_LOG_TRIVIAL(info) << "start_sync_service...";
// BBS
m_user_sync_token.reset(new int(0));
if (with_progress_dlg) {
auto dlg = new ProgressDialog(_L("Loading"), "", 100, this->mainframe, wxPD_AUTO_HIDE | wxPD_APP_MODAL | wxPD_CAN_ABORT);
dlg->Update(0, _L("Loading user preset"));
@ -4667,36 +4719,50 @@ void GUI_App::start_sync_user_preset(bool with_progress_dlg)
});
};
cancelFn = [this, dlg]() {
return dlg->WasCanceled();
return m_is_closing || dlg->WasCanceled();
};
finishFn = [this, userid = m_agent->get_user_id(), dlg](bool ok) {
finishFn = [this, userid = m_agent->get_user_id(), dlg, t = std::weak_ptr(m_user_sync_token)](bool ok) {
CallAfter([=]{
dlg->Destroy();
if (ok && m_agent && userid == m_agent->get_user_id()) reload_settings();
if (ok && m_agent && t.lock() == m_user_sync_token && userid == m_agent->get_user_id()) reload_settings();
});
};
}
else {
finishFn = [this, userid = m_agent->get_user_id()](bool ok) {
finishFn = [this, userid = m_agent->get_user_id(), t = std::weak_ptr(m_user_sync_token)](bool ok) {
CallAfter([=] {
if (ok && m_agent && userid == m_agent->get_user_id()) reload_settings();
if (ok && m_agent && t.lock() == m_user_sync_token && userid == m_agent->get_user_id()) reload_settings();
});
};
}
BOOST_LOG_TRIVIAL(info) << "start_sync_service...";
//BBS
enable_sync = true;
m_sync_update_thread = Slic3r::create_thread(
[this, progressFn, cancelFn, finishFn] {
[this, progressFn, cancelFn, finishFn, t = std::weak_ptr(m_user_sync_token)] {
// get setting list, update setting list
std::string version = preset_bundle->get_vendor_profile_version(PresetBundle::BBL_BUNDLE).to_string();
int ret = m_agent->get_setting_list(version, progressFn, cancelFn);
int ret = m_agent->get_setting_list2(version, [this](auto info) {
auto type = info[BBL_JSON_KEY_TYPE];
auto name = info[BBL_JSON_KEY_NAME];
auto setting_id = info[BBL_JSON_KEY_SETTING_ID];
auto update_time_str = info[BBL_JSON_KEY_UPDATE_TIME];
long long update_time = 0;
if (!update_time_str.empty())
update_time = std::atoll(update_time_str.c_str());
if (type == "filament") {
return preset_bundle->filaments.need_sync(name, setting_id, update_time);
} else if (type == "print") {
return preset_bundle->prints.need_sync(name, setting_id, update_time);
} else if (type == "printer") {
return preset_bundle->printers.need_sync(name, setting_id, update_time);
} else {
return true;
}
}, progressFn, cancelFn);
finishFn(ret == 0);
int count = 0, sync_count = 0;
std::vector<Preset> presets_to_sync;
while (enable_sync) {
while (!t.expired()) {
count++;
if (count % 20 == 0) {
if (m_agent) {
@ -4706,26 +4772,39 @@ void GUI_App::start_sync_user_preset(bool with_progress_dlg)
//sync preset
if (!preset_bundle) continue;
sync_count = preset_bundle->prints.get_user_presets(presets_to_sync);
int total_count = 0;
sync_count = preset_bundle->prints.get_user_presets(preset_bundle, presets_to_sync);
if (sync_count > 0) {
for (Preset& preset : presets_to_sync) {
sync_preset(&preset);
boost::this_thread::sleep_for(boost::chrono::milliseconds(100));
}
}
total_count += sync_count;
sync_count = preset_bundle->filaments.get_user_presets(presets_to_sync);
sync_count = preset_bundle->filaments.get_user_presets(preset_bundle, presets_to_sync);
if (sync_count > 0) {
for (Preset& preset : presets_to_sync) {
sync_preset(&preset);
boost::this_thread::sleep_for(boost::chrono::milliseconds(100));
}
}
total_count += sync_count;
sync_count = preset_bundle->printers.get_user_presets(presets_to_sync);
sync_count = preset_bundle->printers.get_user_presets(preset_bundle, presets_to_sync);
if (sync_count > 0) {
for (Preset& preset : presets_to_sync) {
sync_preset(&preset);
boost::this_thread::sleep_for(boost::chrono::milliseconds(100));
}
}
total_count += sync_count;
if (total_count == 0) {
CallAfter([this] {
plater()->get_notification_manager()->close_notification_of_type(NotificationType::BBLUserPresetExceedLimit);
});
}
unsigned int http_code = 200;
@ -4738,6 +4817,7 @@ void GUI_App::start_sync_user_preset(bool with_progress_dlg)
if (result == 0) {
preset_deleted_from_cloud(del_setting_id);
it = delete_cache_presets.erase(it);
m_create_preset_blocked = { false, false, false, false, false, false };
BOOST_LOG_TRIVIAL(trace) << "sync_preset: sync operation: delete success! setting id = " << del_setting_id;
}
else {
@ -4755,12 +4835,16 @@ void GUI_App::start_sync_user_preset(bool with_progress_dlg)
void GUI_App::stop_sync_user_preset()
{
if (!enable_sync)
if (!m_user_sync_token)
return;
enable_sync = false;
if (m_sync_update_thread.joinable())
m_sync_update_thread.detach();
m_user_sync_token.reset();
if (m_sync_update_thread.joinable()) {
if (m_is_closing)
m_sync_update_thread.join();
else
m_sync_update_thread.detach();
}
}
void GUI_App::start_http_server()
@ -5127,6 +5211,7 @@ bool GUI_App::load_language(wxString language, bool initial)
//FIXME This is a temporary workaround, the correct solution is to switch to "C" locale during file import / export only.
//wxSetlocale(LC_NUMERIC, "C");
Preset::update_suffix_modified((_L("*") + " ").ToUTF8().data());
HintDatabase::get_instance().reinit();
return true;
}
@ -5138,6 +5223,11 @@ Tab* GUI_App::get_tab(Preset::Type type)
return nullptr;
}
Tab* GUI_App::get_plate_tab()
{
return plate_tab;
}
Tab* GUI_App::get_model_tab(bool part)
{
return model_tabs_list[part ? 1 : 0];

View file

@ -275,6 +275,7 @@ private:
Slic3r::DeviceManager* m_device_manager { nullptr };
NetworkAgent* m_agent { nullptr };
std::vector<std::string> need_delete_presets; // store setting ids of preset
std::vector<bool> m_create_preset_blocked { false, false, false, false, false, false }; // excceed limit
bool m_networking_compatible { false };
bool m_networking_need_update { false };
bool m_networking_cancel_update { false };
@ -289,10 +290,11 @@ private:
HMSQuery *hms_query { nullptr };
boost::thread m_sync_update_thread;
bool enable_sync = false;
std::shared_ptr<int> m_user_sync_token;
bool m_is_dark_mode{ false };
bool m_adding_script_handler { false };
bool m_side_popup_status{false};
bool m_show_http_errpr_msgdlg{false};
wxString m_info_dialog_content;
HttpServer m_http_server;
bool m_show_gcode_window{true};
@ -303,6 +305,7 @@ private:
void check_filaments_in_blacklist(std::string tag_supplier, std::string tag_material, bool& in_blacklist, std::string& action, std::string& info);
std::string get_local_models_path();
bool OnInit() override;
int OnExit() override;
bool initialized() const { return m_initialized; }
std::map<std::string, bool> test_url_state;
@ -480,6 +483,7 @@ private:
bool load_language(wxString language, bool initial);
Tab* get_tab(Preset::Type type);
Tab* get_plate_tab();
Tab* get_model_tab(bool part = false);
Tab* get_layer_tab();
ConfigOptionMode get_mode();
@ -583,6 +587,7 @@ private:
std::vector<Tab *> tabs_list;
std::vector<Tab *> model_tabs_list;
Tab* plate_tab;
RemovableDriveManager* removable_drive_manager() { return m_removable_drive_manager.get(); }
//OtherInstanceMessageHandler* other_instance_message_handler() { return m_other_instance_message_handler.get(); }

View file

@ -77,7 +77,7 @@ std::map<std::string, std::vector<SimpleSettingData>> SettingsFactory::OBJECT_C
{"seam_position", "",2},
{"slice_closing_radius", "",3}, {"resolution", "",4},
{"xy_hole_compensation", "",5}, {"xy_contour_compensation", "",6}, {"elefant_foot_compensation", "",7},
{"make_overhang_printable_angle","", 8},{"make_overhang_printable_hole_size","",9}
{"make_overhang_printable_angle","", 8},{"make_overhang_printable_hole_size","",9}, {"wall_sequence","",10}
}},
{ L("Support"), {{"brim_type", "",1},{"brim_width", "",2},{"brim_object_gap", "",3},
{"enable_support", "",4},{"support_type", "",5},{"support_threshold_angle", "",6},{"support_on_build_plate_only", "",7},
@ -715,7 +715,7 @@ wxMenuItem* MenuFactory::append_menu_item_fix_through_netfabb(wxMenu* menu)
void MenuFactory::append_menu_item_export_stl(wxMenu* menu, bool is_mulity_menu)
{
append_menu_item(menu, wxID_ANY, _L("Export as STL") + dots, "",
append_menu_item(menu, wxID_ANY, _L("Export as one STL") + dots, "",
[](wxCommandEvent&) { plater()->export_stl(false, true); }, "", nullptr,
[is_mulity_menu]() {
const Selection& selection = plater()->canvas3D()->get_selection();
@ -724,6 +724,14 @@ void MenuFactory::append_menu_item_export_stl(wxMenu* menu, bool is_mulity_menu)
else
return selection.is_single_full_instance() || selection.is_single_full_object();
}, m_parent);
if (!is_mulity_menu)
return;
append_menu_item(menu, wxID_ANY, _L("Export as STLs") + dots, "",
[](wxCommandEvent&) { plater()->export_stl(false, true, true); }, "", nullptr,
[]() {
const Selection& selection = plater()->canvas3D()->get_selection();
return selection.is_multiple_full_instance() || selection.is_multiple_full_object();
}, m_parent);
}
void MenuFactory::append_menu_item_reload_from_disk(wxMenu* menu)
@ -1482,7 +1490,12 @@ wxMenu* MenuFactory::assemble_part_menu()
void MenuFactory::append_menu_item_clone(wxMenu* menu)
{
append_menu_item(menu, wxID_ANY, _L("Clone") , "",
#ifdef __APPLE__
static const wxString ctrl = ("Ctrl+");
#else
static const wxString ctrl = _L("Ctrl+");
#endif
append_menu_item(menu, wxID_ANY, _L("Clone") + "\t" + ctrl + "K", "",
[this](wxCommandEvent&) {
plater()->clone_selection();
}, "", nullptr,

View file

@ -213,17 +213,23 @@ void ObjectLayers::update_layers_list()
m_object = objects_ctrl->object(obj_idx);
if (!m_object || m_object->layer_config_ranges.empty()) return;
// Delete all controls from options group
m_grid_sizer->Clear(true);
auto range = objects_ctrl->GetModel()->GetLayerRangeByItem(item);
// Add new control according to the selected item
// only call sizer->Clear(true) via CallAfter, otherwise crash happens in Linux when press enter in Height Range
// because an element cannot be destroyed while there are pending events for this element.(https://github.com/wxWidgets/Phoenix/issues/1854)
wxGetApp().CallAfter([this, type, objects_ctrl, range]() {
// Delete all controls from options group
m_grid_sizer->Clear(true);
if (type & itLayerRoot)
create_layers_list();
else
create_layer(objects_ctrl->GetModel()->GetLayerRangeByItem(item), nullptr, nullptr);
// Add new control according to the selected item
m_parent->Layout();
if (type & itLayerRoot)
create_layers_list();
else
create_layer(range, nullptr, nullptr);
m_parent->Layout();
});
}
void ObjectLayers::update_scene_from_editor_selection() const

View file

@ -60,8 +60,11 @@ static PrinterTechnology printer_technology()
static const Selection& scene_selection()
{
//BBS return current canvas3D return wxGetApp().plater()->get_view3D_canvas3D()->get_selection();
return wxGetApp().plater()->get_current_canvas3D()->get_selection();
//BBS AssembleView canvas has its own selection
if (wxGetApp().plater()->get_current_canvas3D()->get_canvas_type() == GLCanvas3D::ECanvasType::CanvasAssembleView)
return wxGetApp().plater()->get_assmeble_canvas3D()->get_selection();
return wxGetApp().plater()->get_view3D_canvas3D()->get_selection();
}
// Config from current edited printer preset
@ -276,6 +279,7 @@ ObjectList::ObjectList(wxWindow* parent) :
Bind(wxEVT_DATAVIEW_ITEM_DROP_POSSIBLE, &ObjectList::OnDropPossible, this);
Bind(wxEVT_DATAVIEW_ITEM_DROP, &ObjectList::OnDrop, this);
Bind(wxEVT_DATAVIEW_ITEM_START_EDITING, &ObjectList::OnStartEditing, this);
Bind(wxEVT_DATAVIEW_ITEM_EDITING_STARTED, &ObjectList::OnEditingStarted, this);
Bind(wxEVT_DATAVIEW_ITEM_EDITING_DONE, &ObjectList::OnEditingDone, this);
@ -381,7 +385,8 @@ void ObjectList::create_objects_ctrl()
// And Icon can be consisting of several bitmaps
BitmapTextRenderer* bmp_text_renderer = new BitmapTextRenderer();
bmp_text_renderer->set_can_create_editor_ctrl_function([this]() {
return m_objects_model->GetItemType(GetSelection()) & (itVolume | itObject);
auto type = m_objects_model->GetItemType(GetSelection());
return type & (itVolume | itObject | itPlate);
});
// BBS
@ -792,6 +797,22 @@ void ObjectList::printable_state_changed(const std::vector<ObjectVolumeID>& ov_i
wxGetApp().plater()->update();
}
void ObjectList::assembly_plate_object_name()
{
m_objects_model->assembly_name();
}
void ObjectList::selected_object(ObjectDataViewModelNode* item)
{
if (!item) {
return;
}
this->SetFocus();
select_item(wxDataViewItem(item));
ensure_current_item_visible();
selection_changed();
}
void ObjectList::update_objects_list_filament_column(size_t filaments_count)
{
assert(filaments_count >= 1);
@ -912,6 +933,20 @@ void ObjectList::update_filament_in_config(const wxDataViewItem& item)
void ObjectList::update_name_in_model(const wxDataViewItem& item) const
{
if (m_objects_model->GetItemType(item) & itPlate) {
std::string name = m_objects_model->GetName(item).ToUTF8().data();
int plate_idx = -1;
const ItemType type0 = m_objects_model->GetItemType(item, plate_idx);
if (plate_idx >= 0) {
auto plate = wxGetApp().plater()->get_partplate_list().get_plate(plate_idx);
if (plate->get_plate_name() != name) {
plate->set_plate_name(name);
}
m_objects_model->SetCurSelectedPlateFullName(plate_idx, name);
}
return;
}
const int obj_idx = m_objects_model->GetObjectIdByItem(item);
if (obj_idx < 0) return;
const int volume_id = m_objects_model->GetVolumeIdByItem(item);
@ -1248,7 +1283,9 @@ void ObjectList::list_manipulation(const wxPoint& mouse_pos, bool evt_context_me
get_selected_item_indexes(obj_idx, vol_idx, item);
//wxGetApp().plater()->PopupObjectTable(obj_idx, vol_idx, mouse_pos);
if (m_objects_model->GetItemType(item) & itLayer)
if (m_objects_model->GetItemType(item) & itPlate)
dynamic_cast<TabPrintPlate*>(wxGetApp().get_plate_tab())->reset_model_config();
else if (m_objects_model->GetItemType(item) & itLayer)
dynamic_cast<TabPrintLayer*>(wxGetApp().get_layer_tab())->reset_model_config();
else
dynamic_cast<TabPrintModel*>(wxGetApp().get_model_tab(vol_idx >= 0))->reset_model_config();
@ -1273,6 +1310,10 @@ void ObjectList::list_manipulation(const wxPoint& mouse_pos, bool evt_context_me
void ObjectList::show_context_menu(const bool evt_context_menu)
{
// BBS Disable menu popup if current canvas is Preview
if (wxGetApp().plater()->get_current_canvas3D()->get_canvas_type() == GLCanvas3D::ECanvasType::CanvasPreview)
return;
wxMenu* menu {nullptr};
Plater* plater = wxGetApp().plater();
@ -1454,7 +1495,7 @@ void ObjectList::key_event(wxKeyEvent& event)
undo();
else if (wxGetKeyState(wxKeyCode('X')) && wxGetKeyState(WXK_CONTROL))
cut();
else if (wxGetKeyState(wxKeyCode('M')) && wxGetKeyState(WXK_CONTROL))
else if (wxGetKeyState(wxKeyCode('K')) && wxGetKeyState(WXK_CONTROL))
clone();
//else if (event.GetUnicodeKey() == '+')
// increase_instances();
@ -3370,6 +3411,8 @@ void ObjectList::part_selection_changed()
wxGetApp().obj_settings()->get_og()->set_name(" " + og_name + " ");
#endif
if (!this->IsShown())
update_and_show_layers = false;
if (printer_technology() == ptSLA)
update_and_show_layers = false;
else if (update_and_show_layers) {
@ -4533,12 +4576,15 @@ void ObjectList::update_selections()
void ObjectList::update_selections_on_canvas()
{
Selection& selection = wxGetApp().plater()->get_current_canvas3D()->get_selection();
auto canvas_type = wxGetApp().plater()->get_current_canvas3D()->get_canvas_type();
GLCanvas3D* canvas = canvas_type == GLCanvas3D::ECanvasType::CanvasAssembleView ? wxGetApp().plater()->get_current_canvas3D() : wxGetApp().plater()->get_view3D_canvas3D();
Selection& selection = canvas->get_selection();
const int sel_cnt = GetSelectedItemsCount();
if (sel_cnt == 0) {
selection.remove_all();
wxGetApp().plater()->get_current_canvas3D()->update_gizmos_on_off_state();
if (canvas_type != GLCanvas3D::ECanvasType::CanvasPreview)
wxGetApp().plater()->get_current_canvas3D()->update_gizmos_on_off_state();
return;
}
@ -4642,7 +4688,8 @@ void ObjectList::update_selections_on_canvas()
selection.add_volumes(mode, volume_idxs, single_selection);
}
wxGetApp().plater()->get_current_canvas3D()->update_gizmos_on_off_state();
if (canvas_type != GLCanvas3D::ECanvasType::CanvasPreview)
wxGetApp().plater()->get_current_canvas3D()->update_gizmos_on_off_state();
wxGetApp().plater()->canvas3D()->render();
}
@ -5467,8 +5514,10 @@ void ObjectList::msw_rescale()
void ObjectList::sys_color_changed()
{
wxGetApp().UpdateDVCDarkUI(this, true);
msw_rescale();
if (m_objects_model) { m_objects_model->sys_color_changed(); }
}
void ObjectList::ItemValueChanged(wxDataViewEvent &event)
@ -5483,6 +5532,22 @@ void ObjectList::ItemValueChanged(wxDataViewEvent &event)
}
}
void GUI::ObjectList::OnStartEditing(wxDataViewEvent &event)
{
auto col = event.GetColumn();
auto item = event.GetItem();
if (col == colName) {
ObjectDataViewModelNode* node = (ObjectDataViewModelNode*)item.GetID();
if (node->GetType() & itPlate) {
int plate_idx = node->GetPlateIdx();
if (plate_idx >= 0) {
auto plate = wxGetApp().plater()->get_partplate_list().get_plate(plate_idx);
m_objects_model->SetName(from_u8(plate->get_plate_name()), GetSelection());
}
}
}
}
// Workaround for entering the column editing mode on Windows. Simulate keyboard enter when another column of the active line is selected.
// Here the last active column is forgotten, so when leaving the editing mode, the next mouse click will not enter the editing mode of the newly selected column.
void ObjectList::OnEditingStarted(wxDataViewEvent &event)
@ -5558,6 +5623,17 @@ void ObjectList::OnEditingDone(wxDataViewEvent &event)
if (event.GetColumn() != colName)
return;
if (event.IsEditCancelled()) {
if (m_objects_model->GetItemType(event.GetItem()) & itPlate) {
int plate_idx = -1;
m_objects_model->GetItemType(event.GetItem(), plate_idx);
if (plate_idx >= 0) {
auto plate = wxGetApp().plater()->get_partplate_list().get_plate(plate_idx);
m_objects_model->SetCurSelectedPlateFullName(plate_idx, plate->get_plate_name());
}
}
}
const auto renderer = dynamic_cast<BitmapTextRenderer*>(GetColumn(colName)->GetRenderer());
#if __WXOSX__
SetAcceleratorTable(m_accel);

View file

@ -185,6 +185,7 @@ private:
// because it would turn off the gizmos (mainly a problem for the SLA gizmo)
wxDataViewItem m_last_selected_item {nullptr};
#ifdef __WXMSW__
// Workaround for entering the column editing mode on Windows. Simulate keyboard enter when another column of the active line is selected.
int m_last_selected_column = -1;
@ -216,6 +217,7 @@ public:
ModelObject* object(const int obj_idx) const ;
void create_objects_ctrl();
// BBS
void update_objects_list_filament_column(size_t filaments_count);
@ -454,6 +456,10 @@ public:
void object_config_options_changed(const ObjectVolumeID& ov_id);
void printable_state_changed(const std::vector<ObjectVolumeID>& ov_ids);
// search objectlist
void assembly_plate_object_name();
void selected_object(ObjectDataViewModelNode* item);
private:
#ifdef __WXOSX__
// void OnChar(wxKeyEvent& event);
@ -472,6 +478,7 @@ private:
void ItemValueChanged(wxDataViewEvent &event);
// Workaround for entering the column editing mode on Windows. Simulate keyboard enter when another column of the active line is selected.
void OnStartEditing(wxDataViewEvent &event);
void OnEditingStarted(wxDataViewEvent &event);
void OnEditingDone(wxDataViewEvent &event);

View file

@ -199,7 +199,9 @@ bool ObjectSettings::update_settings_list()
wxDataViewItemArray items;
objects_ctrl->GetSelections(items);
std::map<ObjectBase *, ModelConfig *> object_configs;
std::map<ObjectBase *, ModelConfig*> plate_configs;
std::map<ObjectBase *, ModelConfig*> object_configs;
bool is_plate_settings = false;
bool is_object_settings = false;
bool is_volume_settings = false;
bool is_layer_range_settings = false;
@ -207,6 +209,22 @@ bool ObjectSettings::update_settings_list()
ModelObject * parent_object = nullptr;
for (auto item : items) {
auto type = objects_model->GetItemType(item);
if (type == itPlate) {
is_plate_settings = true;
int plate_id = objects_model->GetPlateIdByItem(item);
static ModelConfig cfg;
PartPlateList& ppl = wxGetApp().plater()->get_partplate_list();
if (plate_id < 0 || plate_id >= ppl.get_plate_count()) {
plate_id = ppl.get_curr_plate_index();
}
assert(plate_id >= 0 && plate_id < ppl.get_plate_count());
cfg.assign_config(*ppl.get_plate(plate_id)->config());
plate_configs.emplace(ppl.get_plate(plate_id), &cfg);
}
if (type != itObject && type != itVolume && type != itLayerRoot && type != itLayer) {
continue;
}
@ -241,33 +259,45 @@ bool ObjectSettings::update_settings_list()
}
}
auto tab_plate = dynamic_cast<TabPrintPlate*>(wxGetApp().get_plate_tab());
auto tab_object = dynamic_cast<TabPrintModel*>(wxGetApp().get_model_tab());
auto tab_volume = dynamic_cast<TabPrintModel*>(wxGetApp().get_model_tab(true));
auto tab_layer = dynamic_cast<TabPrintModel*>(wxGetApp().get_layer_tab());
if (is_object_settings) {
if (is_plate_settings) {
tab_object->set_model_config({});
tab_volume->set_model_config({});
tab_layer->set_model_config({});
tab_plate->set_model_config(plate_configs);
;// m_tab_active = tab_plate;
}
else if (is_object_settings) {
tab_object->set_model_config(object_configs);
tab_volume->set_model_config({});
tab_layer->set_model_config({});
m_tab_active = tab_object;
tab_plate->set_model_config({});
//m_tab_active = tab_object;
}
else if (is_volume_settings) {
tab_object->set_model_config({ {parent_object, &parent_object->config} });
tab_volume->set_model_config(object_configs);
tab_layer->set_model_config({});
m_tab_active = tab_volume;
tab_plate->set_model_config({});
//m_tab_active = tab_volume;
}
else if (is_layer_range_settings) {
tab_object->set_model_config({ {parent_object, &parent_object->config} });
tab_volume->set_model_config({});
tab_layer->set_model_config(object_configs);
m_tab_active = tab_layer;
tab_plate->set_model_config({});
//m_tab_active = tab_layer;
}
else {
tab_object->set_model_config({});
tab_volume->set_model_config({});
tab_layer->set_model_config({});
m_tab_active = nullptr;
tab_plate->set_model_config({});
//m_tab_active = nullptr;
}
((ParamsPanel*) tab_object->GetParent())->set_active_tab(nullptr);
return true;

View file

@ -123,6 +123,11 @@ void View3D::select_curr_plate_all()
m_canvas->select_curr_plate_all();
}
void View3D::select_object_from_idx(std::vector<int>& object_idxs) {
if (m_canvas != nullptr)
m_canvas->select_object_from_idx(object_idxs);
}
//BBS
void View3D::remove_curr_plate_all()
{
@ -154,6 +159,11 @@ void View3D::center_selected()
m_canvas->do_center();
}
void View3D::center_selected_plate(const int plate_idx) {
if (m_canvas != nullptr)
m_canvas->do_center_plate(plate_idx);
}
void View3D::mirror_selection(Axis axis)
{
if (m_canvas != nullptr)

View file

@ -58,12 +58,14 @@ public:
//BBS
void select_curr_plate_all();
void select_object_from_idx(std::vector<int> &object_idxs);
void remove_curr_plate_all();
void select_all();
void deselect_all();
void delete_selected();
void center_selected();
void center_selected_plate(const int plate_idx);
void mirror_selection(Axis axis);
bool is_layers_editing_enabled() const;

View file

@ -457,6 +457,14 @@ public:
std::ostream& operator<<(std::ostream &os, const WindowMetrics& metrics);
inline int hex_digit_to_int(const char c)
{
return
(c >= '0' && c <= '9') ? int(c - '0') :
(c >= 'A' && c <= 'F') ? int(c - 'A') + 10 :
(c >= 'a' && c <= 'f') ? int(c - 'a') + 10 : -1;
}
class TaskTimer
{
std::chrono::milliseconds start_timer;

View file

@ -59,7 +59,8 @@ bool GLGizmoMmuSegmentation::on_is_selectable() const
bool GLGizmoMmuSegmentation::on_is_activable() const
{
return GLGizmoPainterBase::on_is_activable() && wxGetApp().filaments_cnt() > 1;
const Selection& selection = m_parent.get_selection();
return !selection.is_empty() && (selection.is_single_full_instance() || selection.is_any_volume()) && wxGetApp().filaments_cnt() > 1;
}
//BBS: use the global one in 3DScene.cpp

View file

@ -1507,9 +1507,7 @@ void GLGizmoText::generate_text_volume(bool is_temp)
new_model_volume->set_text_info(text_info);
new_model_volume->name = model_volume->name;
new_model_volume->set_type(model_volume->type());
if (model_volume->config.option("extruder"))
new_model_volume->config.set("extruder", model_volume->config.extruder());
new_model_volume->config.apply(model_volume->config);
std::swap(model_object->volumes[m_volume_idx], model_object->volumes.back());
model_object->delete_volume(model_object->volumes.size() - 1);
plater->update();

View file

@ -320,6 +320,11 @@ void GLGizmosManager::reset_all_states()
if (! m_enabled || m_serializing)
return;
const EType current = get_current_type();
if (current != Undefined)
// close any open gizmo
open_gizmo(current);
activate_gizmo(Undefined);
m_hover = Undefined;
}
@ -1324,12 +1329,18 @@ std::string get_name_from_gizmo_etype(GLGizmosManager::EType type)
return "Scale";
case GLGizmosManager::EType::Flatten:
return "Flatten";
case GLGizmosManager::EType::Cut:
return "Cut";
case GLGizmosManager::EType::MeshBoolean:
return "MeshBoolean";
case GLGizmosManager::EType::FdmSupports:
return "FdmSupports";
case GLGizmosManager::EType::Seam:
return "Seam";
case GLGizmosManager::EType::Text:
return "Text";
case GLGizmosManager::EType::MmuSegmentation:
return "Color Painting";
default:
return "";
}

View file

@ -139,7 +139,13 @@ std::string HMSQuery::hms_language_code()
// set language code to en by default
return "en";
std::string lang_code = wxGetApp().app_config->get_language_code();
if (lang_code.empty()) {
if (lang_code.compare("uk") == 0
|| lang_code.compare("cs") == 0
|| lang_code.compare("ru") == 0) {
BOOST_LOG_TRIVIAL(info) << "HMS: using english for lang_code = " << lang_code;
return "en";
}
else if (lang_code.empty()) {
// set language code to en by default
return "en";
}

View file

@ -303,10 +303,22 @@ void HintDatabase::uninit()
m_used_ids.clear();
m_used_ids_loaded = false;
}
void HintDatabase::reinit()
{
if (m_initialized)
uninit();
init();
}
void HintDatabase::init()
{
load_hints_from_file(std::move(boost::filesystem::path(resources_dir()) / "data" / "hints.ini"));
m_initialized = true;
init_random_hint_id();
}
void HintDatabase::init_random_hint_id()
{
srand(time(NULL));
m_hint_id = rand() % m_loaded_hints.size();
}
void HintDatabase::load_hints_from_file(const boost::filesystem::path& path)
{
@ -340,6 +352,7 @@ void HintDatabase::load_hints_from_file(const boost::filesystem::path& path)
std::string enabled_tags;
// optional link to documentation (accessed from button)
std::string documentation_link;
std::string img_url;
// randomized weighted order variables
size_t weight = 1;
bool was_displayed = is_used(id_string);
@ -404,6 +417,9 @@ void HintDatabase::load_hints_from_file(const boost::filesystem::path& path)
if (dict.find("documentation_link") != dict.end()) {
documentation_link = dict["documentation_link"];
}
if (dict.find("image") != dict.end()) {
img_url = dict["image"];
}
if (dict.find("weight") != dict.end()) {
weight = (size_t)std::max(1, std::atoi(dict["weight"].c_str()));
@ -414,7 +430,7 @@ void HintDatabase::load_hints_from_file(const boost::filesystem::path& path)
//link to internet
if (dict["hypertext_type"] == "link") {
std::string hypertext_link = dict["hypertext_link"];
HintData hint_data{ id_string, text1, weight, was_displayed, hypertext_text, follow_text, disabled_tags, enabled_tags, false, documentation_link, [hypertext_link]() { launch_browser_if_allowed(hypertext_link); } };
HintData hint_data{ id_string, text1, weight, was_displayed, hypertext_text, follow_text, disabled_tags, enabled_tags, false, documentation_link, img_url, [hypertext_link]() { launch_browser_if_allowed(hypertext_link); } };
m_loaded_hints.emplace_back(hint_data);
// highlight settings
}
@ -422,28 +438,28 @@ void HintDatabase::load_hints_from_file(const boost::filesystem::path& path)
std::string opt = dict["hypertext_settings_opt"];
Preset::Type type = static_cast<Preset::Type>(std::atoi(dict["hypertext_settings_type"].c_str()));
std::wstring category = boost::nowide::widen(dict["hypertext_settings_category"]);
HintData hint_data{ id_string, text1, weight, was_displayed, hypertext_text, follow_text, disabled_tags, enabled_tags, true, documentation_link, [opt, type, category]() { GUI::wxGetApp().sidebar().jump_to_option(opt, type, category); } };
HintData hint_data{ id_string, text1, weight, was_displayed, hypertext_text, follow_text, disabled_tags, enabled_tags, true, documentation_link, img_url, [opt, type, category]() { GUI::wxGetApp().sidebar().jump_to_option(opt, type, category); } };
m_loaded_hints.emplace_back(hint_data);
// open preferences
}
else if (dict["hypertext_type"] == "preferences") {
std::string page = dict["hypertext_preferences_page"];
std::string item = dict["hypertext_preferences_item"];
HintData hint_data{ id_string, text1, weight, was_displayed, hypertext_text, follow_text, disabled_tags, enabled_tags, false, documentation_link, [page, item]() { wxGetApp().open_preferences(1, page); } };// 1 is to modify
HintData hint_data{ id_string, text1, weight, was_displayed, hypertext_text, follow_text, disabled_tags, enabled_tags, false, documentation_link, img_url, [page, item]() { wxGetApp().open_preferences(1, page); } };// 1 is to modify
m_loaded_hints.emplace_back(hint_data);
}
else if (dict["hypertext_type"] == "plater") {
std::string item = dict["hypertext_plater_item"];
HintData hint_data{ id_string, text1, weight, was_displayed, hypertext_text, follow_text, disabled_tags, enabled_tags, true, documentation_link, [item]() { wxGetApp().plater()->canvas3D()->highlight_toolbar_item(item); } };
HintData hint_data{ id_string, text1, weight, was_displayed, hypertext_text, follow_text, disabled_tags, enabled_tags, true, documentation_link, img_url, [item]() { wxGetApp().plater()->canvas3D()->highlight_toolbar_item(item); } };
m_loaded_hints.emplace_back(hint_data);
}
else if (dict["hypertext_type"] == "gizmo") {
std::string item = dict["hypertext_gizmo_item"];
HintData hint_data{ id_string, text1, weight, was_displayed, hypertext_text, follow_text, disabled_tags, enabled_tags, true, documentation_link, [item]() { wxGetApp().plater()->canvas3D()->highlight_gizmo(item); } };
HintData hint_data{ id_string, text1, weight, was_displayed, hypertext_text, follow_text, disabled_tags, enabled_tags, true, documentation_link, img_url, [item]() { wxGetApp().plater()->canvas3D()->highlight_gizmo(item); } };
m_loaded_hints.emplace_back(hint_data);
}
else if (dict["hypertext_type"] == "gallery") {
HintData hint_data{ id_string, text1, weight, was_displayed, hypertext_text, follow_text, disabled_tags, enabled_tags, false, documentation_link, []() {
HintData hint_data{ id_string, text1, weight, was_displayed, hypertext_text, follow_text, disabled_tags, enabled_tags, false, documentation_link, img_url, []() {
// Deselect all objects, otherwise gallery wont show.
wxGetApp().plater()->canvas3D()->deselect_all();
//wxGetApp().obj_list()->load_shape_object_from_gallery(); }
@ -453,23 +469,23 @@ void HintDatabase::load_hints_from_file(const boost::filesystem::path& path)
else if (dict["hypertext_type"] == "menubar") {
wxString menu(_("&" + dict["hypertext_menubar_menu_name"]));
wxString item(_(dict["hypertext_menubar_item_name"]));
HintData hint_data{ id_string, text1, weight, was_displayed, hypertext_text, follow_text, disabled_tags, enabled_tags, true, documentation_link, [menu, item]() { wxGetApp().mainframe->open_menubar_item(menu, item); } };
HintData hint_data{ id_string, text1, weight, was_displayed, hypertext_text, follow_text, disabled_tags, enabled_tags, true, documentation_link, img_url, [menu, item]() { wxGetApp().mainframe->open_menubar_item(menu, item); } };
m_loaded_hints.emplace_back(hint_data);
}
}
else {
// plain text without hypertext
HintData hint_data{ id_string, text1, weight, was_displayed, hypertext_text, follow_text, disabled_tags, enabled_tags, false, documentation_link };
HintData hint_data{ id_string, text1, weight, was_displayed, hypertext_text, follow_text, disabled_tags, enabled_tags, false, documentation_link, img_url };
m_loaded_hints.emplace_back(hint_data);
}
}
}
}
HintData* HintDatabase::get_hint(bool new_hint/* = true*/)
HintData* HintDatabase::get_hint(HintDataNavigation nav)
{
if (!m_initialized) {
init();
new_hint = true;
nav = HintDataNavigation::Random;
}
if (m_loaded_hints.empty())
{
@ -479,20 +495,34 @@ HintData* HintDatabase::get_hint(bool new_hint/* = true*/)
try
{
if (new_hint)
m_hint_id = get_next();
if (nav == HintDataNavigation::Next)
m_hint_id = get_next_hint_id();
if(nav == HintDataNavigation::Prev)
m_hint_id = get_prev_hint_id();
if (nav == HintDataNavigation::Curr)
;
if (nav == HintDataNavigation::Random)
init_random_hint_id();
}
catch (const std::exception&)
{
return nullptr;
}
return &m_loaded_hints[m_hint_id];
}
size_t HintDatabase::get_next()
size_t HintDatabase::get_next_hint_id()
{
return m_hint_id < m_loaded_hints.size() - 1 ? m_hint_id + 1 : 0;
}
size_t HintDatabase::get_prev_hint_id()
{
return m_hint_id > 0 ? m_hint_id - 1 : m_loaded_hints.size() - 1;
}
size_t HintDatabase::get_random_next()
{
if (!m_sorted_hints)
{
@ -1110,7 +1140,7 @@ void NotificationManager::HintNotification::open_documentation()
}
void NotificationManager::HintNotification::retrieve_data(bool new_hint/* = true*/)
{
HintData* hint_data = HintDatabase::get_instance().get_hint(new_hint);
HintData* hint_data = HintDatabase::get_instance().get_hint(new_hint ? HintDataNavigation::Next : HintDataNavigation::Curr);
if (hint_data == nullptr)
close();

View file

@ -18,9 +18,17 @@ struct HintData
std::string enabled_tags;
bool runtime_disable; // if true - hyperlink will check before every click if not in disabled mode
std::string documentation_link;
std::string image_url;
std::function<void(void)> callback{ nullptr };
};
enum class HintDataNavigation {
Curr,
Prev,
Next,
Random,
};
class HintDatabase
{
public:
@ -40,7 +48,8 @@ public:
void operator=(HintDatabase const&) = delete;
// return true if HintData filled;
HintData* get_hint(bool new_hint = true);
HintData* get_hint(HintDataNavigation nav);
size_t get_index() { return m_hint_id; }
size_t get_count() {
if (!m_initialized)
return 0;
@ -49,14 +58,18 @@ public:
// resets m_initiailized to false and writes used if was initialized
// used when reloading in runtime - like change language
void uninit();
void reinit();
private:
void init();
void init_random_hint_id();
void load_hints_from_file(const boost::filesystem::path& path);
bool is_used(const std::string& id);
void set_used(const std::string& id);
void clear_used();
// Returns position in m_loaded_hints with next hint chosed randomly with weights
size_t get_next();
size_t get_next_hint_id();
size_t get_prev_hint_id();
size_t get_random_next();
size_t m_hint_id;
bool m_initialized{ false };
std::vector<HintData> m_loaded_hints;

View file

@ -618,6 +618,43 @@ void IMSlider::draw_colored_band(const ImRect& groove, const ImRect& slideable_r
}
}
void IMSlider::draw_custom_label_block(const ImVec2 anchor, Type type)
{
wxString label;
switch (type)
{
case ColorChange:
label = _L("Color");
break;
case PausePrint:
label = _L("Pause");
break;
case ToolChange:
label = _L("Color");
break;
case Template:
label = _L("Template");
break;
case Custom:
label = _L("Custom");
break;
case Unknown:
break;
default:
break;
}
const ImVec2 text_size = ImGui::CalcTextSize(into_u8(label).c_str());
const ImVec2 padding = ImVec2(4, 2) * m_scale;
const ImU32 clr = IM_COL32(255, 111, 0, 255);
const float rounding = 2.0f * m_scale;
ImVec2 block_pos = { anchor.x - text_size.x - padding.x * 2, anchor.y - text_size.y / 2 - padding.y };
ImVec2 block_size = { text_size.x + padding.x * 2, text_size.y + padding.y * 2 };
ImGui::RenderFrame(block_pos, block_pos + block_size, clr, false, rounding);
ImGui::PushStyleColor(ImGuiCol_Text, { 1,1,1,1 });
ImGui::RenderText(block_pos + padding, into_u8(label).c_str());
ImGui::PopStyleColor();
}
void IMSlider::draw_ticks(const ImRect& slideable_region) {
//if(m_draw_mode != dmRegular)
// return;
@ -691,6 +728,11 @@ void IMSlider::draw_ticks(const ImRect& slideable_region) {
ImVec2 icon_pos = ImVec2(slideable_region.GetCenter().x + icon_offset.x, tick_pos - icon_offset.y);
button_with_pos(custom_icon_id, icon_size, icon_pos);
}
//draw label block
ImVec2 label_block_anchor = ImVec2(slideable_region.GetCenter().x - tick_offset.y, tick_pos);
draw_custom_label_block(label_block_anchor, tick_it->type);
++tick_it;
}
@ -698,6 +740,10 @@ void IMSlider::draw_ticks(const ImRect& slideable_region) {
GetSelection() == ssLower ? m_ticks.ticks.find(TickCode{this->GetLowerValue()}) :
m_ticks.ticks.end();
if (tick_it != m_ticks.ticks.end()) {
//draw label block again, to keep it in front
ImVec2 label_block_anchor = ImVec2(slideable_region.GetCenter().x - tick_offset.y, get_tick_pos(tick_it->tick));
draw_custom_label_block(label_block_anchor, tick_it->type);
// draw delete icon
ImVec2 icon_pos = ImVec2(slideable_region.GetCenter().x + icon_offset.x, get_tick_pos(tick_it->tick) - icon_offset.y);
button_with_pos(m_delete_icon_id, icon_size, icon_pos);
@ -1128,9 +1174,7 @@ void IMSlider::render_input_custom_gcode(std::string custom_gcode)
}
const int text_height = 6;
ImGui::InputTextMultiline("##text", m_custom_gcode, sizeof(m_custom_gcode), ImVec2(-1, ImGui::GetTextLineHeight() * text_height), ImGuiInputTextFlags_CallbackAlways, [](ImGuiInputTextCallbackData* data) {
return data->CursorPos = data->BufTextLen;
});
ImGui::InputTextMultiline("##text", m_custom_gcode, sizeof(m_custom_gcode), ImVec2(-1, ImGui::GetTextLineHeight() * text_height));
ImGui::NewLine();
ImGui::SameLine(ImGui::GetStyle().WindowPadding.x * 14);

View file

@ -145,6 +145,7 @@ protected:
void render_edit_menu(const TickCode& tick); //menu
void draw_background_and_groove(const ImRect& bg_rect, const ImRect& groove);
void draw_colored_band(const ImRect& groove, const ImRect& slideable_region);
void draw_custom_label_block(const ImVec2 anchor, Type type);
void draw_ticks(const ImRect& slideable_region);
void draw_tick_on_mouse_position(const ImRect& slideable_region);
void show_tooltip(const TickCode& tick); //menu

View file

@ -63,8 +63,8 @@ static const std::map<const wchar_t, std::string> font_icons = {
{ImGui::MinimalizeHoverButton , "notification_minimalize_hover" },
{ImGui::RightArrowButton , "notification_right" },
{ImGui::RightArrowHoverButton , "notification_right_hover" },
{ImGui::PreferencesButton , "notification_preferences" },
{ImGui::PreferencesHoverButton , "notification_preferences_hover"},
//{ImGui::PreferencesButton , "notification_preferences" },
//{ImGui::PreferencesHoverButton , "notification_preferences_hover"},
#if ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT
{ImGui::SliderFloatEditBtnIcon, "edit_button" },
#endif // ENABLE_ENHANCED_IMGUI_SLIDER_FLOAT
@ -73,6 +73,7 @@ static const std::map<const wchar_t, std::string> font_icons = {
{ImGui::TriangleButtonIcon , "triangle_paint" },
{ImGui::FillButtonIcon , "fill_paint" },
{ImGui::HeightRangeIcon , "height_range" },
{ImGui::ConfirmIcon , "confirm" },
{ImGui::GapFillIcon , "gap_fill" },
{ImGui::FoldButtonIcon , "im_fold" },
{ImGui::UnfoldButtonIcon , "im_unfold" },
@ -82,14 +83,15 @@ static const std::map<const wchar_t, std::string> font_icons = {
{ImGui::MinimalizeHoverDarkButton , "notification_minimalize_hover_dark" },
{ImGui::RightArrowDarkButton , "notification_right_dark" },
{ImGui::RightArrowHoverDarkButton , "notification_right_hover_dark" },
{ImGui::PreferencesDarkButton , "notification_preferences_dark" },
{ImGui::PreferencesHoverDarkButton , "notification_preferences_hover_dark"},
//{ImGui::PreferencesDarkButton , "notification_preferences_dark" },
//{ImGui::PreferencesHoverDarkButton , "notification_preferences_hover_dark"},
{ImGui::ClipboardBtnDarkIcon , "copy_menu_dark" },
{ImGui::CircleButtonDarkIcon , "circle_paint_dark" },
{ImGui::TriangleButtonDarkIcon , "triangle_paint_dark" },
{ImGui::FillButtonDarkIcon , "fill_paint_dark" },
{ImGui::HeightRangeDarkIcon , "height_range_dark" },
{ImGui::ConfirmDarkIcon , "confirm_dark" },
{ImGui::GapFillDarkIcon , "gap_fill_dark" },
{ImGui::SphereButtonDarkIcon , "toolbar_modifier_sphere_dark" },
@ -102,6 +104,10 @@ static const std::map<const wchar_t, std::string> font_icons = {
{ImGui::CloseBlockNotifButton , "block_notification_close" },
{ImGui::CloseBlockNotifHoverButton , "block_notification_close_hover" },
{ImGui::CollapseArrowIcon, "notification_collapse" },
{ImGui::ExpandArrowIcon, "notification_expand" },
{ImGui::OpenArrowIcon, "notification_arrow_open" },
};
static const std::map<const wchar_t, std::string> font_icons_large = {
{ImGui::CloseNotifButton , "notification_close" },
@ -119,15 +125,18 @@ static const std::map<const wchar_t, std::string> font_icons_large = {
// {ImGui::CustomSeamMarker , "seam" },
// {ImGui::MmuSegmentationMarker , "mmu_segmentation" },
// {ImGui::VarLayerHeightMarker , "layers" },
{ImGui::DocumentationButton , "notification_documentation" },
{ImGui::DocumentationHoverButton, "notification_documentation_hover"},
//{ImGui::DocumentationButton , "notification_documentation" },
//{ImGui::DocumentationHoverButton, "notification_documentation_hover"},
//{ImGui::InfoMarker , "notification_info" },
// dark mode icon
{ImGui::CloseNotifDarkButton , "notification_close_dark" },
{ImGui::CloseNotifHoverDarkButton , "notification_close_hover_dark" },
{ImGui::DocumentationDarkButton , "notification_documentation_dark" },
{ImGui::DocumentationHoverDarkButton, "notification_documentation_hover_dark"},
//{ImGui::DocumentationDarkButton , "notification_documentation_dark" },
//{ImGui::DocumentationHoverDarkButton, "notification_documentation_hover_dark"},
{ImGui::BlockNotifErrorIcon, "block_notification_error" },
{ImGui::PrevArrowBtnIcon, "notification_arrow_left" },
{ImGui::NextArrowBtnIcon, "notification_arrow_right" },
{ImGui::CompleteIcon, "notification_slicing_complete" },
};
static const std::map<const wchar_t, std::string> font_icons_extra_large = {
@ -383,6 +392,7 @@ void ImGuiWrapper::set_language(const std::string &language)
} else if (lang == "ko") {
ranges = ImGui::GetIO().Fonts->GetGlyphRangesKorean(); // Default + Korean characters
m_font_cjk = true;
m_is_korean = true;
} else if (lang == "zh") {
ranges = (language == "zh_TW") ?
// Traditional Chinese
@ -2683,12 +2693,12 @@ void ImGuiWrapper::destroy_fonts_texture() {
const char* ImGuiWrapper::clipboard_get(void* user_data)
{
ImGuiWrapper *self = reinterpret_cast<ImGuiWrapper*>(user_data);
ImGuiWrapper* self = reinterpret_cast<ImGuiWrapper*>(user_data);
const char* res = "";
if (wxTheClipboard->Open()) {
if (wxTheClipboard->IsSupported(wxDF_TEXT)) {
if (wxTheClipboard->IsSupported(wxDF_TEXT) || wxTheClipboard->IsSupported(wxDF_UNICODETEXT)) {
wxTextDataObject data;
wxTheClipboard->GetData(data);

View file

@ -55,6 +55,7 @@ class ImGuiWrapper
const ImWchar* m_glyph_basic_ranges { nullptr };
// Chinese, Japanese, Korean
bool m_font_cjk{ false };
bool m_is_korean{ false };
float m_font_size{ 18.0 };
unsigned m_font_texture{ 0 };
unsigned m_font_another_texture{ 0 };

View file

@ -122,6 +122,12 @@ void Slic3r::GUI::ImageGrid::SetSelecting(bool selecting)
void Slic3r::GUI::ImageGrid::DoActionOnSelection(int action) { DoAction(-1, action); }
void Slic3r::GUI::ImageGrid::ShowDownload(bool show)
{
m_show_download = show;
Refresh();
}
void Slic3r::GUI::ImageGrid::Rescale()
{
m_title_mask = wxBitmap();
@ -266,10 +272,13 @@ std::pair<int, size_t> Slic3r::GUI::ImageGrid::HitTest(wxPoint const &pt)
auto & file = m_file_sys->GetFile(index);
int btn = file.IsDownload() && file.DownloadProgress() >= 0 ? 3 : 2;
if (m_file_sys->GetFileType() == PrinterFileSystem::F_MODEL) {
btn = 3;
if (m_show_download)
btn = 3;
hover_rect.y -= m_content_rect.GetHeight() * 64 / 264;
}
if (hover_rect.Contains(off.x, off.y)) { return {HIT_ACTION, index * 4 + off.x * btn / hover_rect.GetWidth()}; } // Two buttons
if (hover_rect.Contains(off.x, off.y)) {
return {HIT_ACTION, index * 4 + off.x * btn / hover_rect.GetWidth()};
} // Two buttons
}
return {HIT_ITEM, index};
}
@ -593,12 +602,12 @@ void Slic3r::GUI::ImageGrid::renderContent1(wxDC &dc, wxPoint const &pt, int ind
bool show_download_state_always = true;
// Draw checked icon
if (m_selecting && !show_download_state_always)
dc.DrawBitmap(selected ? m_checked_icon.bmp() : m_unchecked_icon.bmp(), pt + wxPoint{10, m_content_rect.GetHeight() - m_checked_icon.GetBmpHeight() - 10});
dc.DrawBitmap(selected ? m_checked_icon.bmp() : m_unchecked_icon.bmp(), pt + wxPoint{10, 10});
// can't handle alpha
// dc.GradientFillLinear({pt.x, pt.y, m_border_size.GetWidth(), 60}, wxColour(0x6F, 0x6F, 0x6F, 0x99), wxColour(0x6F, 0x6F, 0x6F, 0), wxBOTTOM);
else if (m_file_sys->GetGroupMode() == PrinterFileSystem::G_NONE) {
wxString nonHoverText;
wxString secondAction = _L("Download");
wxString secondAction = m_show_download ? _L("Download") : "";
wxString thirdAction;
int states = 0;
// Draw download progress
@ -644,7 +653,7 @@ void Slic3r::GUI::ImageGrid::renderContent1(wxDC &dc, wxPoint const &pt, int ind
dc.DrawText(date, pt + wxPoint{24, 16});
}
if (m_selecting && show_download_state_always)
dc.DrawBitmap(selected ? m_checked_icon.bmp() : m_unchecked_icon.bmp(), pt + wxPoint{10, m_content_rect.GetHeight() - m_checked_icon.GetBmpHeight() - 10});
dc.DrawBitmap(selected ? m_checked_icon.bmp() : m_unchecked_icon.bmp(), pt + wxPoint{10, 10});
}
void Slic3r::GUI::ImageGrid::renderContent2(wxDC &dc, wxPoint const &pt, int index, bool hit)

View file

@ -49,6 +49,8 @@ public:
void DoActionOnSelection(int action);
void ShowDownload(bool show);
public:
void Rescale();
@ -127,6 +129,7 @@ private:
// wxBitmap m_button_background;
bool m_selecting = false;
bool m_show_download = false;
enum HitType {
HIT_NONE,

View file

@ -57,7 +57,7 @@ public:
ret.is_wipe_tower = true;
++ret.priority;
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << " arrange: wipe tower info:" << m_bb << ", m_pos: " << m_pos.transpose();
BOOST_LOG_TRIVIAL(debug) << " arrange: wipe tower info:" << m_bb << ", m_pos: " << m_pos.transpose();
return ret;
}
@ -240,6 +240,21 @@ void ArrangeJob::prepare_all() {
plate_list.preprocess_exclude_areas(m_unselected, MAX_NUM_PLATES);
}
arrangement::ArrangePolygon estimate_wipe_tower_info(int plate_index, std::set<int>& extruder_ids)
{
PartPlateList& ppl = wxGetApp().plater()->get_partplate_list();
const auto& full_config = wxGetApp().preset_bundle->full_config();
int plate_count = ppl.get_plate_count();
int plate_index_valid = std::min(plate_index, plate_count - 1);
// we have to estimate the depth using the extruder number of all plates
int extruder_size = extruder_ids.size();
auto arrange_poly = ppl.get_plate(plate_index_valid)->estimate_wipe_tower_polygon(full_config, plate_index, extruder_size);
arrange_poly.bed_idx = plate_index;
return arrange_poly;
}
// 准备料塔。逻辑如下:
// 1. 以下几种情况不需要料塔:
// 1料塔被禁用
@ -255,10 +270,11 @@ void ArrangeJob::prepare_wipe_tower()
bool need_wipe_tower = false;
// if wipe tower is explicitly disabled, no need to estimate
DynamicPrintConfig &current_config = wxGetApp().preset_bundle->prints.get_edited_preset().config;
auto op = current_config.option("enable_prime_tower");
DynamicPrintConfig& current_config = wxGetApp().preset_bundle->prints.get_edited_preset().config;
auto op = current_config.option("enable_prime_tower");
bool enable_prime_tower = op && op->getBool();
if (!enable_prime_tower || params.is_seq_print) return;
bool smooth_timelapse = false;
auto sop = current_config.option("timelapse_type");
if (sop) { smooth_timelapse = sop->getInt() == TimelapseType::tlSmooth; }
@ -266,7 +282,7 @@ void ArrangeJob::prepare_wipe_tower()
// estimate if we need wipe tower for all plates:
// need wipe tower if some object has multiple extruders (has paint-on colors or support material)
for (const auto &item : m_selected) {
for (const auto& item : m_selected) {
std::set<int> obj_extruders;
obj_extruders.insert(item.extrude_ids.begin(), item.extrude_ids.end());
if (obj_extruders.size() > 1) {
@ -278,11 +294,11 @@ void ArrangeJob::prepare_wipe_tower()
// if multile extruders have same bed temp, we need wipe tower
// 允许不同材料落在相同盘,且所有选定对象中使用了多种热床温度相同的材料
if (params.allow_multi_materials_on_same_plate) {
if (params.allow_multi_materials_on_same_plate) {
std::map<int, std::set<int>> bedTemp2extruderIds;
for (const auto &item : m_selected)
for (const auto& item : m_selected)
for (auto id : item.extrude_ids) { bedTemp2extruderIds[item.bed_temp].insert(id); }
for (const auto &be : bedTemp2extruderIds) {
for (const auto& be : bedTemp2extruderIds) {
if (be.second.size() > 1) {
need_wipe_tower = true;
BOOST_LOG_TRIVIAL(info) << "arrange: need wipe tower because allow_multi_materials_on_same_plate=true and we have multiple extruders of same type";
@ -293,24 +309,42 @@ void ArrangeJob::prepare_wipe_tower()
BOOST_LOG_TRIVIAL(info) << "arrange: need_wipe_tower=" << need_wipe_tower;
// check all plates to see if wipe tower is already there
ArrangePolygon wipe_tower_ap;
wipe_tower_ap.name = "WipeTower";
ArrangePolygon wipe_tower_ap;
wipe_tower_ap.name = "WipeTower";
wipe_tower_ap.is_virt_object = true;
wipe_tower_ap.is_wipe_tower = true;
const GLCanvas3D *canvas3D = static_cast<const GLCanvas3D *>(m_plater->canvas3D());
wipe_tower_ap.is_wipe_tower = true;
const GLCanvas3D* canvas3D = static_cast<const GLCanvas3D*>(m_plater->canvas3D());
std::set<int> extruder_ids;
PartPlateList& ppl = wxGetApp().plater()->get_partplate_list();
int plate_count = ppl.get_plate_count();
if (!only_on_partplate) {
extruder_ids = ppl.get_extruders(true);
}
int bedid_unlocked = 0;
for (int bedid = 0; bedid < MAX_NUM_PLATES; bedid++) {
int plate_index_valid = std::min(bedid, plate_count - 1);
PartPlate* pl = ppl.get_plate(plate_index_valid);
if(bedid<plate_count && pl->is_locked())
continue;
if (auto wti = get_wipe_tower(*m_plater, bedid)) {
// wipe tower is already there
wipe_tower_ap = get_wipetower_arrange_poly(&wti);
wipe_tower_ap.bed_idx = bedid;
m_unselected.emplace_back(wipe_tower_ap);
} else if (need_wipe_tower) {
wipe_tower_ap.translation = {0, 0};
wipe_tower_ap.poly.contour.points = canvas3D->estimate_wipe_tower_points(bedid, !only_on_partplate);
wipe_tower_ap.bed_idx = bedid;
wipe_tower_ap = get_wipetower_arrange_poly(&wti);
wipe_tower_ap.bed_idx = bedid_unlocked;
m_unselected.emplace_back(wipe_tower_ap);
}
else if (need_wipe_tower) {
if (only_on_partplate) {
auto plate_extruders = pl->get_extruders(true);
extruder_ids.clear();
extruder_ids.insert(plate_extruders.begin(), plate_extruders.end());
}
wipe_tower_ap = estimate_wipe_tower_info(bedid, extruder_ids);
wipe_tower_ap.bed_idx = bedid_unlocked;
m_unselected.emplace_back(wipe_tower_ap);
}
bedid_unlocked++;
}
}
@ -338,7 +372,6 @@ void ArrangeJob::prepare_partplate() {
return;
}
params.is_seq_print = plate->get_real_print_seq() == PrintSequence::ByObject;
Model& model = m_plater->model();
// Go through the objects and check if inside the selection
@ -364,7 +397,7 @@ void ArrangeJob::prepare_partplate() {
//skip this object due to be not in current plate, treated as locked
ap.itemid = m_locked.size();
m_locked.emplace_back(std::move(ap));
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(": skip locked instance, obj_id %1%, name %2%") % oidx % mo->name;
//BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(": skip locked instance, obj_id %1%, name %2%") % oidx % mo->name;
}
}
}
@ -520,11 +553,13 @@ void ArrangeJob::process()
BOOST_LOG_TRIVIAL(warning)<< "Arrange full params: "<< params.to_json();
BOOST_LOG_TRIVIAL(info) << boost::format("arrange: items selected before arranging: %1%") % m_selected.size();
for (auto selected : m_selected) {
BOOST_LOG_TRIVIAL(debug) << selected.name << ", extruder: " << selected.extrude_ids.back() << ", bed: " << selected.bed_idx<<", filemant_type:" << selected.filament_temp_type;
BOOST_LOG_TRIVIAL(debug) << selected.name << ", extruder: " << selected.extrude_ids.back() << ", bed: " << selected.bed_idx << ", filemant_type:" << selected.filament_temp_type
<< ", trans: " << selected.translation.transpose();
}
BOOST_LOG_TRIVIAL(debug) << "items unselected before arrange: ";
BOOST_LOG_TRIVIAL(debug) << "arrange: items unselected before arrange: " << m_unselected.size();
for (auto item : m_unselected)
BOOST_LOG_TRIVIAL(debug) << item.name << ", bed: " << item.bed_idx << ", trans: " << item.translation.transpose();
BOOST_LOG_TRIVIAL(debug) << item.name << ", bed: " << item.bed_idx << ", trans: " << item.translation.transpose()
<<", bbox:"<<get_extents(item.poly).min.transpose()<<","<<get_extents(item.poly).max.transpose();
}
arrangement::arrange(m_selected, m_unselected, bedpts, params);
@ -532,12 +567,12 @@ void ArrangeJob::process()
// sort by item id
std::sort(m_selected.begin(), m_selected.end(), [](auto a, auto b) {return a.itemid < b.itemid; });
{
BOOST_LOG_TRIVIAL(info) << boost::format("arrange: items unselected before arranging: %1%") % m_unselected.size();
BOOST_LOG_TRIVIAL(info) << boost::format("arrange: items selected after arranging: %1%") % m_selected.size();
for (auto selected : m_selected)
BOOST_LOG_TRIVIAL(debug) << selected.name << ", extruder: " << selected.extrude_ids.back() << ", bed: " << selected.bed_idx
<< ", bed_temp: " << selected.first_bed_temp << ", print_temp: " << selected.print_temp
<< ", trans: " << unscale<double>(selected.translation(X)) << ","<< unscale<double>(selected.translation(Y));
BOOST_LOG_TRIVIAL(debug) << "items unselected after arrange: ";
BOOST_LOG_TRIVIAL(debug) << "arrange: items unselected after arrange: "<< m_unselected.size();
for (auto item : m_unselected)
BOOST_LOG_TRIVIAL(debug) << item.name << ", bed: " << item.bed_idx << ", trans: " << item.translation.transpose();
}
@ -714,11 +749,10 @@ arrangement::ArrangeParams init_arrange_params(Plater *p)
auto & print = wxGetApp().plater()->get_partplate_list().get_current_fff_print();
const PrintConfig& print_config = print.config();
params.clearance_height_to_rod = print.config().extruder_clearance_height_to_rod.value;
params.clearance_height_to_lid = print.config().extruder_clearance_height_to_lid.value;
params.cleareance_radius = print.config().extruder_clearance_radius.value;
params.printable_height = print.config().printable_height.value;
params.clearance_height_to_rod = print_config.extruder_clearance_height_to_rod.value;
params.clearance_height_to_lid = print_config.extruder_clearance_height_to_lid.value;
params.cleareance_radius = print_config.extruder_clearance_radius.value;
params.printable_height = print_config.printable_height.value;
params.allow_rotations = settings.enable_rotation;
params.align_center = print_config.best_object_pos.value;
params.allow_multi_materials_on_same_plate = settings.allow_multi_materials_on_same_plate;
@ -731,7 +765,11 @@ arrangement::ArrangeParams init_arrange_params(Plater *p)
if (state == Job::JobPrepareState::PREPARE_STATE_MENU) {
PartPlateList &plate_list = p->get_partplate_list();
PartPlate * plate = plate_list.get_curr_plate();
params.is_seq_print = plate->get_real_print_seq() == PrintSequence::ByObject;
bool plate_same_as_global = true;
params.is_seq_print = plate->get_real_print_seq(&plate_same_as_global) == PrintSequence::ByObject;
// if plate's print sequence is not the same as global, the settings.distance is no longer valid, we set it to auto
if (!plate_same_as_global)
params.min_obj_distance = 0;
}
if (params.is_seq_print) {

View file

@ -107,7 +107,7 @@ void BindJob::process()
if (result < 0) {
BOOST_LOG_TRIVIAL(trace) << "login: result = " << result;
if (result_code == BAMBU_NETWORK_ERR_BIND_ECODE_LOGIN_REPORT_FAILED) {
if (result_code == BAMBU_NETWORK_ERR_BIND_ECODE_LOGIN_REPORT_FAILED || result_code == BAMBU_NETWORK_ERR_BIND_GET_PRINTER_TICKET_TIMEOUT) {
int error_code;
try

View file

@ -223,7 +223,7 @@ void FillBedJob::process()
params.progressind = [this](unsigned st,std::string str="") {
if (st > 0)
update_status(st, _L("Filling bed " + str));
update_status(st, _L("Filling") + " " + wxString::FromUTF8(str));
};
params.on_packed = [&do_stop] (const ArrangePolygon &ap) {
@ -236,8 +236,8 @@ void FillBedJob::process()
// finalize just here.
update_status(m_status_range, was_canceled() ?
_(L("Bed filling canceled.")) :
_(L("Bed filling done.")));
_L("Bed filling canceled.") :
_L("Bed filling done."));
}
void FillBedJob::finalize()
@ -289,6 +289,7 @@ void FillBedJob::finalize()
auto obj_list = m_plater->sidebar().obj_list();
for (size_t i = oldSize; i < newSize; i++) {
obj_list->add_object_to_list(i, true, true, false);
obj_list->update_printable_state(i, 0);
}
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << ": paste_objects_into_list";

View file

@ -29,6 +29,9 @@ static wxString desc_upload_ftp_failed = _L("Failed to upload print file to
static wxString sending_over_lan_str = _L("Sending print job over LAN");
static wxString sending_over_cloud_str = _L("Sending print job through cloud service");
static wxString wait_sending_finish = _L("Print task sending times out.");
static wxString desc_wait_sending_finish = _L("The printer timed out while receiving a print job. Please check if the network is functioning properly and send the print again.");
PrintJob::PrintJob(std::shared_ptr<ProgressIndicator> pri, Plater* plater, std::string dev_id)
: PlaterJob{ std::move(pri), plater },
m_dev_id(dev_id),
@ -242,7 +245,6 @@ void PrintJob::process()
params.dst_file = m_dst_path;
}
if (wxGetApp().model().model_info && wxGetApp().model().model_info.get()) {
ModelInfo* model_info = wxGetApp().model().model_info.get();
auto origin_profile_id = model_info->metadata_items.find(BBL_DESIGNER_PROFILE_ID_TAG);
@ -276,7 +278,17 @@ void PrintJob::process()
catch (...) {}
}
}
if (!wxGetApp().model().stl_design_id.empty()) {
int stl_design_id = 0;
try {
stl_design_id = std::stoi(wxGetApp().model().stl_design_id);
}
catch (const std::exception& e) {
stl_design_id = 0;
}
params.stl_design_id = stl_design_id;
}
if (params.preset_name.empty() && m_print_type == "from_normal") { params.preset_name = wxString::Format("%s_plate_%d", m_project_name, curr_plate_idx).ToStdString(); }
if (params.project_name.empty()) {params.project_name = m_project_name;}
@ -296,6 +308,7 @@ void PrintJob::process()
70, // PrintingStageWaiting
75, // PrintingStageRecord
97, // PrintingStageSending
100, // PrintingStageFinished
100 // PrintingStageFinished
};
@ -391,8 +404,53 @@ void PrintJob::process()
return was_canceled();
};
auto wait_fn = [this](int state, std::string job_info) {
// TODO
DeviceManager* dev = wxGetApp().getDeviceManager();
MachineObject* obj = dev->get_selected_machine();
auto wait_fn = [this, curr_percent, &obj](int state, std::string job_info) {
BOOST_LOG_TRIVIAL(info) << "print_job: get_job_info = " << job_info;
if (!obj->is_support_wait_sending_finish) {
return true;
}
std::string curr_job_id;
json job_info_j;
try {
job_info_j.parse(job_info);
if (job_info_j.contains("job_id")) {
curr_job_id = job_info_j["job_id"].get<std::string>();
}
BOOST_LOG_TRIVIAL(trace) << "print_job: curr_obj_id=" << curr_job_id;
} catch(...) {
;
}
if (obj) {
int time_out = 0;
while (time_out < PRINT_JOB_SENDING_TIMEOUT) {
BOOST_LOG_TRIVIAL(trace) << "print_job: obj job_id = " << obj->job_id_;
if (!obj->job_id_.empty() && obj->job_id_.compare(curr_job_id) == 0) {
BOOST_LOG_TRIVIAL(info) << "print_job: got job_id = " << obj->job_id_ << ", time_out=" << time_out;
return true;
}
if (obj->is_in_printing_status(obj->print_status)) {
BOOST_LOG_TRIVIAL(info) << "print_job: printer has enter printing status, s = " << obj->print_status;
return true;
}
time_out++;
boost::this_thread::sleep_for(boost::chrono::milliseconds(1000));
}
//this->update_status(curr_percent, _L("Print task sending times out."));
m_plater->update_print_error_info(BAMBU_NETWORK_ERR_TIMEOUT, wait_sending_finish.ToStdString(), desc_wait_sending_finish.ToStdString());
BOOST_LOG_TRIVIAL(info) << "print_job: timeout, cancel the job" << obj->job_id_;
/* handle tiemout */
obj->command_task_cancel(curr_job_id);
return false;
}
BOOST_LOG_TRIVIAL(info) << "print_job: obj is null";
return true;
};

View file

@ -10,6 +10,8 @@ namespace fs = boost::filesystem;
namespace Slic3r {
namespace GUI {
#define PRINT_JOB_SENDING_TIMEOUT 25
class PrintPrepareData
{
public:

View file

@ -142,7 +142,7 @@ void SendJob::process()
result = m_agent->start_send_gcode_to_sdcard(params, nullptr, nullptr, nullptr);
if (result != 0) {
BOOST_LOG_TRIVIAL(error) << "access code is invalid";
m_enter_ip_address_fun_fail();
m_enter_ip_address_fun_fail(result);
m_job_finished = true;
return;
}
@ -228,9 +228,10 @@ void SendJob::process()
const int StagePercentPoint[(int)PrintingStageFinished + 1] = {
20, // PrintingStageCreate
30, // PrintingStageUpload
99, // PrintingStageWaiting
99, // PrintingStageRecord
99, // PrintingStageSending
99, // PrintingStageWaiting
99, // PrintingStageRecord
99, // PrintingStageSending
100, // PrintingStageFinished
100 // PrintingStageFinished
};
@ -381,7 +382,7 @@ void SendJob::process()
else {
BOOST_LOG_TRIVIAL(error) << "send_job: send ok.";
wxCommandEvent* evt = new wxCommandEvent(m_print_job_completed_id);
evt->SetString(params.project_name);
evt->SetString(from_u8(params.project_name));
wxQueueEvent(m_plater, evt);
m_job_finished = true;
}
@ -392,7 +393,7 @@ void SendJob::on_success(std::function<void()> success)
m_success_fun = success;
}
void SendJob::on_check_ip_address_fail(std::function<void()> func)
void SendJob::on_check_ip_address_fail(std::function<void(int)> func)
{
m_enter_ip_address_fun_fail = func;
}

View file

@ -23,7 +23,7 @@ class SendJob : public PlaterJob
bool m_is_check_mode{false};
bool m_check_and_continue{false};
std::function<void()> m_success_fun{nullptr};
std::function<void()> m_enter_ip_address_fun_fail{nullptr};
std::function<void(int)> m_enter_ip_address_fun_fail{nullptr};
std::function<void()> m_enter_ip_address_fun_success{nullptr};
protected:
@ -60,7 +60,7 @@ public:
bool is_finished() { return m_job_finished; }
void process() override;
void on_success(std::function<void()> success);
void on_check_ip_address_fail(std::function<void()> func);
void on_check_ip_address_fail(std::function<void(int)> func);
void on_check_ip_address_success(std::function<void()> func);
void finalize() override;
void set_project_name(std::string name);

View file

@ -197,6 +197,8 @@ void KBShortcutsDialog::fill_shortcuts()
{ ctrl + "P", L("Preferences") },
//3D control
{ ctrl + "M", L("Show/Hide 3Dconnexion devices settings dialog") },
// Switch table page
{ ctrl + "Tab", L("Switch table page")},
//DEL
#ifdef __APPLE__
{"fn+⌫", L("Delete selected")},
@ -282,7 +284,7 @@ void KBShortcutsDialog::fill_shortcuts()
{ctrl + "V", L("Paste from clipboard")},
{ctrl + "X", L("Cut")},
{ctrl + "A", L("Select all objects")},
{ctrl + "M", L("Clone selected")},
{ctrl + "K", L("Clone selected")},
{ctrl + "Z", L("Undo")},
{ctrl + "Y", L("Redo")},
{L("Space"), L("Select the object/part and press space to change the name")},

View file

@ -60,11 +60,13 @@
#include "NetworkTestDialog.hpp"
#include "ConfigWizard.hpp"
#include "Widgets/WebView.hpp"
#include "DailyTips.hpp"
#ifdef _WIN32
#include <dbt.h>
#include <shlobj.h>
#endif // _WIN32
#include <slic3r/GUI/CreatePresetsDialog.hpp>
namespace Slic3r {
@ -511,7 +513,7 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, BORDERLESS_FRAME_
// BBS: backup project
if (wxGetApp().app_config->get("backup_switch") == "true") {
std::string backup_interval;
if (!wxGetApp().app_config->get("", "backup_interval", backup_interval))
if (!wxGetApp().app_config->get("app", "backup_interval", backup_interval))
backup_interval = "10";
Slic3r::set_backup_interval(boost::lexical_cast<long>(backup_interval));
} else {
@ -551,7 +553,7 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, BORDERLESS_FRAME_
}
return;}
#endif
if (evt.CmdDown() && evt.GetKeyCode() == 'R') { if (m_slice_enable) { wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_SLICE_PLATE)); this->m_tabpanel->SetSelection(tpPreview); } return; }
if (evt.CmdDown() && evt.GetKeyCode() == 'R') { if (m_slice_enable) { wxGetApp().plater()->update(true, true); wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_SLICE_PLATE)); this->m_tabpanel->SetSelection(tpPreview); } return; }
if (evt.CmdDown() && evt.ShiftDown() && evt.GetKeyCode() == 'G') {
m_plater->apply_background_progress();
m_print_enable = get_enable_print_status();
@ -571,7 +573,11 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, BORDERLESS_FRAME_
if (evt.CmdDown() && evt.GetKeyCode() == 'O') { m_plater->load_project(); return;}
if (evt.CmdDown() && evt.ShiftDown() && evt.GetKeyCode() == 'S') { if (can_save_as()) m_plater->save_project(true); return;}
else if (evt.CmdDown() && evt.GetKeyCode() == 'S') { if (can_save()) m_plater->save_project(); return;}
if (evt.CmdDown() && evt.GetKeyCode() == 'F') {
if (m_plater && (m_tabpanel->GetSelection() == TabPosition::tp3DEditor || m_tabpanel->GetSelection() == TabPosition::tpPreview)) {
m_plater->sidebar().can_search();
}
}
#ifdef __APPLE__
if (evt.CmdDown() && evt.GetKeyCode() == ',')
#else
@ -591,7 +597,7 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, BORDERLESS_FRAME_
if (evt.CmdDown() && evt.GetKeyCode() == 'I') {
if (!can_add_models()) return;
if (m_plater) { m_plater->add_model(); }
if (m_plater) { m_plater->add_file(); }
return;
}
evt.Skip();
@ -729,8 +735,8 @@ void MainFrame::update_layout()
case ESettingsLayout::Old:
{
m_plater->Reparent(m_tabpanel);
m_tabpanel->InsertPage(tp3DEditor, m_plater, _L("Prepare"), std::string("tab_3d_active"), std::string("tab_3d_active"));
m_tabpanel->InsertPage(tpPreview, m_plater, _L("Preview"), std::string("tab_preview_active"), std::string("tab_preview_active"));
m_tabpanel->InsertPage(tp3DEditor, m_plater, _L("Prepare"), std::string("tab_3d_active"), std::string("tab_3d_active"), false);
m_tabpanel->InsertPage(tpPreview, m_plater, _L("Preview"), std::string("tab_preview_active"), std::string("tab_preview_active"), false);
m_main_sizer->Add(m_tabpanel, 1, wxEXPAND | wxTOP, 0);
m_tabpanel->Bind(wxCUSTOMEVT_NOTEBOOK_SEL_CHANGED, [this](wxCommandEvent& evt)
@ -898,7 +904,7 @@ void MainFrame::show_calibration_button(bool show)
if (shown2 == show)
;
else if (show)
m_tabpanel->InsertPage(tpCalibration, m_calibration, _L("Calibration"), std::string("tab_monitor_active"), std::string("tab_monitor_active"));
m_tabpanel->InsertPage(tpCalibration, m_calibration, _L("Calibration"), std::string("tab_monitor_active"), std::string("tab_monitor_active"), false);
else
m_tabpanel->RemovePage(tpCalibration);
}
@ -1034,7 +1040,7 @@ void MainFrame::init_tabpanel() {
select_tab(MainFrame::tpHome);
m_webview->load_url(url);
});
m_tabpanel->AddPage(m_webview, "", "tab_home_active", "tab_home_active");
m_tabpanel->AddPage(m_webview, "", "tab_home_active", "tab_home_active", false);
m_param_panel = new ParamsPanel(m_tabpanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBK_LEFT | wxTAB_TRAVERSAL);
}
@ -1049,7 +1055,7 @@ void MainFrame::init_tabpanel() {
//BBS add pages
m_monitor = new MonitorPanel(m_tabpanel, wxID_ANY, wxDefaultPosition, wxDefaultSize);
m_monitor->SetBackgroundColour(*wxWHITE);
m_tabpanel->AddPage(m_monitor, _L("Device"), std::string("tab_monitor_active"), std::string("tab_monitor_active"));
m_tabpanel->AddPage(m_monitor, _L("Device"), std::string("tab_monitor_active"), std::string("tab_monitor_active"), false);
m_printer_view = new PrinterWebView(m_tabpanel);
Bind(EVT_LOAD_PRINTER_URL, [this](LoadPrinterViewEvent &evt) {
@ -1062,11 +1068,11 @@ void MainFrame::init_tabpanel() {
m_project = new ProjectPanel(m_tabpanel, wxID_ANY, wxDefaultPosition, wxDefaultSize);
m_project->SetBackgroundColour(*wxWHITE);
m_tabpanel->AddPage(m_project, _L("Project"), std::string("tab_auxiliary_avtice"), std::string("tab_auxiliary_avtice"));
m_tabpanel->AddPage(m_project, _L("Project"), std::string("tab_auxiliary_avtice"), std::string("tab_auxiliary_avtice"), false);
m_calibration = new CalibrationPanel(m_tabpanel, wxID_ANY, wxDefaultPosition, wxDefaultSize);
m_calibration->SetBackgroundColour(*wxWHITE);
m_tabpanel->AddPage(m_calibration, _L("Calibration"), std::string("tab_monitor_active"), std::string("tab_monitor_active"));
m_tabpanel->AddPage(m_calibration, _L("Calibration"), std::string("tab_monitor_active"), std::string("tab_monitor_active"), false);
if (m_plater) {
// load initial config
@ -1205,6 +1211,7 @@ void MainFrame::create_preset_tabs()
m_param_dialog = new ParamsDialog(m_plater);
add_created_tab(new TabPrint(m_param_panel), "cog");
add_created_tab(new TabPrintPlate(m_param_panel), "cog");
add_created_tab(new TabPrintObject(m_param_panel), "cog");
add_created_tab(new TabPrintPart(m_param_panel), "cog");
add_created_tab(new TabPrintLayer(m_param_panel), "cog");
@ -1224,6 +1231,10 @@ void MainFrame::add_created_tab(Tab* panel, const std::string& bmp_name /*= ""*
{
panel->create_preset_tab();
if (panel->type() == Preset::TYPE_PLATE) {
wxGetApp().tabs_list.pop_back();
wxGetApp().plate_tab = panel;
}
// BBS: model config
if (panel->type() == Preset::TYPE_MODEL) {
wxGetApp().tabs_list.pop_back();
@ -1807,7 +1818,7 @@ bool MainFrame::get_enable_print_status()
}
else if (m_print_select == eExportSlicedFile)
{
if (!current_plate->is_slice_result_ready_for_print())
if (!current_plate->is_slice_result_ready_for_export())
{
enable = false;
}
@ -1830,7 +1841,7 @@ bool MainFrame::get_enable_print_status()
}
else if (m_print_select == eExportAllSlicedFile)
{
if (!part_plate_list.is_all_slice_results_ready_for_print())
if (!part_plate_list.is_all_slice_result_ready_for_export())
{
enable = false;
}
@ -2020,6 +2031,7 @@ void MainFrame::on_sys_color_changed()
tab->sys_color_changed();
for (auto tab : wxGetApp().model_tabs_list)
tab->sys_color_changed();
wxGetApp().plate_tab->sys_color_changed();
MenuFactory::sys_color_changed(m_menubar);
@ -2054,7 +2066,7 @@ static wxMenu* generate_help_menu()
[](wxCommandEvent&) { Slic3r::GUI::desktop_open_datadir_folder(); });
append_menu_item(helpMenu, wxID_ANY, _L("Show Tip of the Day"), _L("Show Tip of the Day"), [](wxCommandEvent&) {
wxGetApp().plater()->get_notification_manager()->push_hint_notification(false);
wxGetApp().plater()->get_dailytips()->open();
wxGetApp().plater()->get_current_canvas3D()->set_as_dirty();
});
@ -2145,7 +2157,6 @@ static void add_common_view_menu_items(wxMenu* view_menu, MainFrame* mainFrame,
void MainFrame::init_menubar_as_editor()
{
#ifdef __APPLE__
wxMenuBar::SetAutoWindowMenu(false);
m_menubar = new wxMenuBar();
#endif
@ -2241,9 +2252,12 @@ void MainFrame::init_menubar_as_editor()
wxMenu* export_menu = new wxMenu();
// BBS export as STL
append_menu_item(export_menu, wxID_ANY, _L("Export all objects as STL") + dots, _L("Export all objects as STL"),
append_menu_item(export_menu, wxID_ANY, _L("Export all objects as one STL") + dots, _L("Export all objects as one STL"),
[this](wxCommandEvent&) { if (m_plater) m_plater->export_stl(); }, "menu_export_stl", nullptr,
[this](){return can_export_model(); }, this);
append_menu_item(export_menu, wxID_ANY, _L("Export all objects as STLs") + dots, _L("Export all objects as STLs"),
[this](wxCommandEvent&) { if (m_plater) m_plater->export_stl(false, false, true); }, "menu_export_stl", nullptr,
[this](){return can_export_model(); }, this);
append_menu_item(export_menu, wxID_ANY, _L("Export Generic 3MF") + dots/* + "\tCtrl+G"*/, _L("Export 3mf file without using some 3mf-extensions"),
[this](wxCommandEvent&) { if (m_plater) m_plater->export_core_3mf(); }, "menu_export_sliced_file", nullptr,
[this](){return can_export_model(); }, this);
@ -2419,7 +2433,7 @@ void MainFrame::init_menubar_as_editor()
"", nullptr, [this](){return can_delete_all(); }, this);
editMenu->AppendSeparator();
// BBS Clone Selected
append_menu_item(editMenu, wxID_ANY, _L("Clone selected") + "\t" + ctrl + "M",
append_menu_item(editMenu, wxID_ANY, _L("Clone selected") + "\t" + ctrl + "K",
_L("Clone copies of selections"),[this, handle_key_event](wxCommandEvent&) {
wxKeyEvent e;
e.SetEventType(wxEVT_KEY_DOWN);
@ -2672,7 +2686,6 @@ void MainFrame::init_menubar_as_editor()
// Help menu
auto helpMenu = generate_help_menu();
#ifndef __APPLE__
m_topbar->SetFileMenu(fileMenu);
if (editMenu)
@ -3020,6 +3033,10 @@ struct ConfigsOverwriteConfirmDialog : MessageDialog
void MainFrame::export_config()
{
ExportConfigsDialog export_configs_dlg(nullptr);
export_configs_dlg.ShowModal();
return;
// Generate a cummulative configuration for the selected print, filaments and printer.
wxDirDialog dlg(this, _L("Choose a directory"),
from_u8(!m_last_config.IsEmpty() ? get_dir_name(m_last_config) : wxGetApp().app_config->get_last_dir()), wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST);
@ -3056,7 +3073,7 @@ void MainFrame::load_config_file()
// return;
wxFileDialog dlg(this, _L("Select profile to load:"),
!m_last_config.IsEmpty() ? get_dir_name(m_last_config) : wxGetApp().app_config->get_last_dir(),
"config.json", "Config files (*.json)|*.json", wxFD_OPEN | wxFD_MULTIPLE | wxFD_FILE_MUST_EXIST);
"config.json", "Config files (*.json;*.zip;*.bbscfg;*.bbsflmt)|*.json;*.zip;*.bbscfg;*.bbsflmt", wxFD_OPEN | wxFD_MULTIPLE | wxFD_FILE_MUST_EXIST);
wxArrayString files;
if (dlg.ShowModal() != wxID_OK)
return;
@ -3077,7 +3094,14 @@ void MainFrame::load_config_file()
if (!cfiles.empty()) {
wxGetApp().app_config->update_config_dir(get_dir_name(cfiles.back()));
wxGetApp().load_current_presets();
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " presets has been import,and size is" << cfiles.size();
NetworkAgent* agent = wxGetApp().getAgent();
if (agent) {
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " user is: " << agent->get_user_id();
}
}
wxGetApp().preset_bundle->update_compatible(PresetSelectCompatibleType::Always);
update_side_preset_ui();
MessageDialog dlg2(this, wxString::Format(_L_PLURAL("There is %d config imported. (Only non-system and compatible configs)",
"There are %d configs imported. (Only non-system and compatible configs)", cfiles.size()), cfiles.size()),
_L("Import result"), wxOK);
@ -3391,6 +3415,8 @@ std::wstring MainFrame::FileHistory::GetThumbnailUrl(int index) const
void MainFrame::FileHistory::AddFileToHistory(const wxString &file)
{
if (this->m_fileMaxFiles == 0)
return;
wxFileHistory::AddFileToHistory(file);
if (m_load_called)
m_thumbnails.push_front(bbs_3mf_get_thumbnail(into_u8(file).c_str()));
@ -3400,6 +3426,8 @@ void MainFrame::FileHistory::AddFileToHistory(const wxString &file)
void MainFrame::FileHistory::RemoveFileFromHistory(size_t i)
{
if (i >= m_thumbnails.size()) // FIX zero max
return;
wxFileHistory::RemoveFileFromHistory(i);
m_thumbnails.erase(m_thumbnails.begin() + i);
}

View file

@ -201,22 +201,24 @@ MediaFilePanel::~MediaFilePanel()
void MediaFilePanel::SetMachineObject(MachineObject* obj)
{
std::string machine = obj ? obj->dev_id : "";
if (obj && obj->is_function_supported(PrinterFunction::FUNC_MEDIA_FILE)) {
m_supported = true;
if (obj) {
m_lan_mode = obj->is_lan_mode_printer();
m_lan_ip = obj->dev_ip;
m_lan_passwd = obj->get_access_code();
m_local_support = obj->has_local_file_proto();
m_remote_support = obj->has_remote_file_proto();
m_dev_ver = obj->get_ota_version();
m_local_support = obj->file_local;
m_remote_support = obj->file_remote;
m_model_download_support = obj->file_model_download;
} else {
m_supported = false;
m_lan_mode = false;
m_lan_ip.clear();
m_lan_passwd.clear();
m_dev_ver.clear();
m_local_support = false;
m_remote_support = false;
m_model_download_support = false;
}
if (machine == m_machine) {
if (machine == m_machine && m_image_grid->GetFileSystem()) {
if (m_waiting_enable && IsEnabled()) {
auto fs = m_image_grid->GetFileSystem();
if (fs) fs->Retry();
@ -235,7 +237,7 @@ void MediaFilePanel::SetMachineObject(MachineObject* obj)
SetSelecting(false);
if (m_machine.empty()) {
m_image_grid->SetStatus(m_bmp_failed, _L("No printers."));
} else if (!m_supported) {
} else if (!m_local_support && !m_remote_support) {
m_image_grid->SetStatus(m_bmp_failed, _L("Initialize failed (Not supported on the current printer version)!"));
} else {
boost::shared_ptr<PrinterFileSystem> fs(new PrinterFileSystem);
@ -250,6 +252,8 @@ void MediaFilePanel::SetMachineObject(MachineObject* obj)
m_time_panel->Show(fs->GetFileType() < PrinterFileSystem::F_MODEL);
//m_manage_panel->Show(fs->GetFileType() < PrinterFileSystem::F_MODEL);
m_button_management->Enable(fs->GetCount() > 0);
bool download_support = fs->GetFileType() < PrinterFileSystem::F_MODEL || m_model_download_support;
m_image_grid->ShowDownload(download_support);
if (fs->GetCount() == 0)
SetSelecting(false);
});
@ -278,7 +282,7 @@ void MediaFilePanel::SetMachineObject(MachineObject* obj)
case PrinterFileSystem::ListSyncing: icon = m_bmp_loading; msg = _L("Loading file list..."); break;
case PrinterFileSystem::ListReady: icon = extra == 0 ? m_bmp_empty : m_bmp_failed; msg = extra == 0 ? _L("No files [%d]") : _L("Load failed [%d]"); break;
}
if (!e.GetString().IsEmpty()) msg = _L(e.GetString());
if (!e.GetString().IsEmpty()) msg = e.GetString();
if (fs->GetCount() == 0 && !msg.empty())
m_image_grid->SetStatus(icon, msg);
if (e.GetInt() == PrinterFileSystem::Initializing)
@ -307,6 +311,9 @@ void MediaFilePanel::SetMachineObject(MachineObject* obj)
return;
int result = e.GetExtraLong();
if (result > 1 && !e.GetString().IsEmpty())
MessageDialog(this, e.GetString(), _L("Download failed"), wxOK | wxICON_ERROR).ShowModal();
NetworkAgent* agent = wxGetApp().getAgent();
if (result > 1 || result == 0) {
json j;
@ -373,7 +380,9 @@ void MediaFilePanel::SetSelecting(bool selecting)
{
m_image_grid->SetSelecting(selecting);
m_button_management->SetLabel(selecting ? _L("Cancel") : _L("Select"));
m_manage_panel->GetSizer()->Show(m_button_download, selecting);
auto fs = m_image_grid->GetFileSystem();
bool download_support = fs && fs->GetFileType() < PrinterFileSystem::F_MODEL || m_model_download_support;
m_manage_panel->GetSizer()->Show(m_button_download, selecting && download_support);
m_manage_panel->GetSizer()->Show(m_button_delete, selecting);
m_manage_panel->Layout();
}
@ -395,6 +404,8 @@ void MediaFilePanel::modeChanged(wxCommandEvent& e1)
m_last_mode = mode;
}
extern wxString hide_passwd(wxString url, std::vector<wxString> const &passwords);
void MediaFilePanel::fetchUrl(boost::weak_ptr<PrinterFileSystem> wfs)
{
boost::shared_ptr fs(wfs.lock());
@ -412,7 +423,8 @@ void MediaFilePanel::fetchUrl(boost::weak_ptr<PrinterFileSystem> wfs)
return;
}
if ((m_lan_mode || !m_remote_support) && m_local_support && !m_lan_ip.empty()) {
std::string url = "bambu:///local/" + m_lan_ip + ".?port=6000&user=" + m_lan_user + "&passwd=" + m_lan_passwd;
std::string url = "bambu:///local/" + m_lan_ip + ".?port=6000&user=" + m_lan_user + "&passwd=" + m_lan_passwd +
"&device=" + m_machine + "&dev_ver=" + m_dev_ver;
fs->SetUrl(url);
return;
}
@ -429,13 +441,13 @@ void MediaFilePanel::fetchUrl(boost::weak_ptr<PrinterFileSystem> wfs)
NetworkAgent *agent = wxGetApp().getAgent();
if (agent) {
agent->get_camera_url(m_machine,
[this, wfs](std::string url) {
BOOST_LOG_TRIVIAL(info) << "MediaFilePanel::fetchUrl: camera_url: " << url;
CallAfter([this, url, wfs] {
[this, wfs, m = m_machine, v = m_dev_ver](std::string url) {
BOOST_LOG_TRIVIAL(info) << "MediaFilePanel::fetchUrl: camera_url: " << hide_passwd(url, {"authkey=", "passwd="});
CallAfter([=] {
boost::shared_ptr fs(wfs.lock());
if (!fs || fs != m_image_grid->GetFileSystem()) return;
if (boost::algorithm::starts_with(url, "bambu:///")) {
fs->SetUrl(url);
fs->SetUrl(url + "&device=" + m + "&dev_ver=" + v);
} else {
m_image_grid->SetStatus(m_bmp_failed, wxString::Format(_L("Initialize failed (%s)!"), url.empty() ? _L("Network unreachable") : from_u8(url)));
fs->SetUrl("3");
@ -504,7 +516,13 @@ void MediaFilePanel::doAction(size_t index, int action)
auto &file = fs->GetFile(index);
int gcode_file_count = Slic3r::GUI::wxGetApp().plater()->update_print_required_data(config, model, plate_data_list, from_u8(file.name).ToStdString(), file.path);
std::string file_path = file.path;
if (!file_path.empty() && file_path[0] == '/') {
file_path.erase(0, 1);
}
int gcode_file_count = Slic3r::GUI::wxGetApp().plater()->update_print_required_data(config, model, plate_data_list, file.name, file_path);
if (gcode_file_count > 0) {
wxPostEvent(Slic3r::GUI::wxGetApp().plater(), SimpleEvent(EVT_PRINT_FROM_SDCARD_VIEW));

View file

@ -79,10 +79,11 @@ private:
std::string m_lan_ip;
std::string m_lan_user;
std::string m_lan_passwd;
bool m_supported = false;
std::string m_dev_ver;
bool m_lan_mode = false;
bool m_local_support = false;
bool m_remote_support = false;
bool m_model_download_support = false;
bool m_waiting_enable = false;
int m_last_mode = 0;

View file

@ -9,6 +9,7 @@
#include "DownloadProgressDialog.hpp"
#include <boost/filesystem/string_file.hpp>
#include <boost/nowide/utf8_codecvt.hpp>
#undef pid_t
#include <boost/process.hpp>
#ifdef __WIN32__
@ -41,7 +42,23 @@ MediaPlayCtrl::MediaPlayCtrl(wxWindow *parent, wxMediaCtrl2 *media_ctrl, const w
wxLaunchDefaultBrowser(url);
});
Bind(wxEVT_RIGHT_UP, [this](auto & e) { wxClipboard & c = *wxTheClipboard; if (c.Open()) { c.SetData(new wxTextDataObject(m_url)); c.Close(); } });
Bind(wxEVT_RIGHT_UP, [this](auto & e) {
wxClipboard & c = *wxTheClipboard;
if (c.Open()) {
if (wxGetKeyState(WXK_SHIFT)) {
if (c.IsSupported(wxDF_TEXT)) {
wxTextDataObject data;
c.GetData(data);
Stop();
m_url = data.GetText();
load();
}
} else {
c.SetData(new wxTextDataObject(m_url));
}
c.Close();
}
});
wxBoxSizer * sizer = new wxBoxSizer(wxHORIZONTAL);
sizer->Add(m_button_play, 0, wxEXPAND | wxALL, 0);
@ -77,21 +94,23 @@ MediaPlayCtrl::~MediaPlayCtrl()
void MediaPlayCtrl::SetMachineObject(MachineObject* obj)
{
std::string machine = obj ? obj->dev_id : "";
if (obj && obj->is_function_supported(PrinterFunction::FUNC_CAMERA_VIDEO)) {
if (obj) {
m_camera_exists = obj->has_ipcam;
m_dev_ver = obj->get_ota_version();
m_lan_mode = obj->is_lan_mode_printer();
m_lan_proto = obj->get_local_camera_proto();
m_lan_proto = obj->liveview_local;
m_remote_support = obj->liveview_remote;
m_lan_ip = obj->dev_ip;
m_lan_passwd = obj->get_access_code();
m_remote_support = obj->is_function_supported(PrinterFunction::FUNC_REMOTE_TUNNEL);
m_device_busy = obj->is_camera_busy_off();
m_tutk_state = obj->tutk_state;
} else {
m_camera_exists = false;
m_lan_mode = false;
m_lan_proto = -1;
m_lan_proto = MachineObject::LVL_None;
m_lan_ip.clear();
m_lan_passwd.clear();
m_dev_ver.clear();
m_tutk_state.clear();
m_remote_support = true;
m_device_busy = false;
@ -121,6 +140,26 @@ void MediaPlayCtrl::SetMachineObject(MachineObject* obj)
SetStatus("", false);
}
wxString hide_passwd(wxString url, std::vector<wxString> const &passwords)
{
for (auto &p : passwords) {
auto i = url.find(p);
if (i == wxString::npos)
continue;
auto j = i + p.length();
if (p[p.length() - 1] == '=') {
i = j;
j = url.find('&', i);
if (j == wxString::npos)
j = url.length();
}
auto l = size_t(j - i);
if (j == url.length() || url[j] == '@' || url[j] == '&')
url.replace(i, l, l, wxUniChar('*'));
}
return url;
}
void MediaPlayCtrl::Play()
{
if (!m_next_retry.IsValid() || wxDateTime::Now() < m_next_retry)
@ -153,30 +192,19 @@ void MediaPlayCtrl::Play()
m_button_play->SetIcon("media_stop");
NetworkAgent *agent = wxGetApp().getAgent();
std::string agent_version = agent ? agent->get_version() : "";
if (m_lan_proto > 0 && (m_lan_mode || m_lan_proto == 1 || !m_remote_support) && !m_disable_lan && !m_lan_ip.empty()) {
if (m_lan_proto > MachineObject::LVL_None && (m_lan_mode || !m_remote_support) && !m_disable_lan && !m_lan_ip.empty()) {
m_disable_lan = m_remote_support && !m_lan_mode; // try remote next time
if (m_lan_proto == 1)
m_url = "bambu:///local/" + m_lan_ip + ".?port=6000&user=" + m_lan_user + "&passwd=" + m_lan_passwd + "&device=" + m_machine + "&version=" + agent_version;
else if (m_lan_proto == 2)
m_url = "bambu:///rtsps___" + m_lan_user + ":" + m_lan_passwd + "@" + m_lan_ip + "/streaming/live/1?device=" + m_machine + "&version=" + agent_version;
else if (m_lan_proto == 3)
m_url = "bambu:///rtsp___" + m_lan_user + ":" + m_lan_passwd + "@" + m_lan_ip + "/streaming/live/1?device=" + m_machine + "&version=" + agent_version;
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: " << m_url.substr(0, 16);
m_last_state = MEDIASTATE_LOADING;
SetStatus(_L("Loading..."));
if (wxGetApp().app_config->get("internal_developer_mode") == "true") {
std::string file_h264 = data_dir() + "/video.h264";
std::string file_info = data_dir() + "/video.info";
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl dump video to " << file_h264;
// closed by BambuSource
FILE *dump_h264_file = boost::nowide::fopen(file_h264.c_str(), "wb");
FILE *dump_info_file = boost::nowide::fopen(file_info.c_str(), "wb");
m_url = m_url + "&dump_h264=" + boost::lexical_cast<std::string>(dump_h264_file);
m_url = m_url + "&dump_info=" + boost::lexical_cast<std::string>(dump_info_file);
}
boost::unique_lock lock(m_mutex);
m_tasks.push_back(m_url);
m_cond.notify_all();
if (m_lan_proto == MachineObject::LVL_Local)
m_url = "bambu:///local/" + m_lan_ip + ".?port=6000&user=" + m_lan_user + "&passwd=" + m_lan_passwd;
else if (m_lan_proto == MachineObject::LVL_Rtsps)
m_url = "bambu:///rtsps___" + m_lan_user + ":" + m_lan_passwd + "@" + m_lan_ip + "/streaming/live/1?proto=rtsps";
else if (m_lan_proto == MachineObject::LVL_Rtsp)
m_url = "bambu:///rtsp___" + m_lan_user + ":" + m_lan_passwd + "@" + m_lan_ip + "/streaming/live/1?proto=rtsp";
m_url += "&device=" + m_machine;
m_url += "&version=" + agent_version;
m_url += "&dev_ver=" + m_dev_ver;
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: " << hide_passwd(m_url, {m_lan_passwd} );
load();
return;
}
@ -202,12 +230,13 @@ void MediaPlayCtrl::Play()
SetStatus(_L("Initializing..."));
if (agent) {
agent->get_camera_url(m_machine, [this, m = m_machine, v = agent_version](std::string url) {
agent->get_camera_url(m_machine, [this, m = m_machine, v = agent_version, dv = m_dev_ver](std::string url) {
if (boost::algorithm::starts_with(url, "bambu:///")) {
url += "&device=" + m;
url += "&version=" + v;
url += "&dev_ver=" + dv;
}
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: " << url.substr(0, 16) << ", machine: " << m_machine;
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: " << hide_passwd(url, {"authkey=", "passwd="}) << ", machine: " << m_machine;
CallAfter([this, m, url] {
if (m != m_machine) {
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl drop late ttcode for machine: " << m;
@ -219,15 +248,7 @@ void MediaPlayCtrl::Play()
m_failed_code = 3;
Stop(wxString::Format(_L("Initialize failed (%s)!"), url.empty() ? _L("Network unreachable") : from_u8(url)));
} else {
m_last_state = MEDIASTATE_LOADING;
SetStatus(_L("Loading..."));
if (wxGetApp().app_config->get("internal_developer_mode") == "true") {
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl dump video to " << boost::filesystem::current_path();
m_url = m_url + "&dump=video.h264";
}
boost::unique_lock lock(m_mutex);
m_tasks.push_back(m_url);
m_cond.notify_all();
load();
}
} else {
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl drop late ttcode for state: " << m_last_state;
@ -267,19 +288,6 @@ void MediaPlayCtrl::Stop(wxString const &msg)
if (last_state != wxMEDIASTATE_PLAYING && m_failed_code != 0
&& m_last_failed_codes.find(m_failed_code) == m_last_failed_codes.end()
&& (m_user_triggered || m_failed_retry > 3)) {
json j;
j["stage"] = last_state;
j["dev_id"] = m_machine;
j["dev_ip"] = m_lan_ip;
j["result"] = "failed";
j["user_triggered"] = m_user_triggered;
j["failed_retry"] = m_failed_retry;
j["tunnel"] = remote ? "remote" : "local";
j["code"] = m_failed_code;
if (remote)
j["tutk_state"] = m_tutk_state;
j["msg"] = into_u8(msg);
NetworkAgent *agent = wxGetApp().getAgent();
m_last_failed_codes.insert(m_failed_code);
}
@ -377,14 +385,34 @@ void MediaPlayCtrl::ToggleStream()
wxGetApp().app_config->set("not_show_vcamera_stop_prev", "1");
if (res == wxID_CANCEL) return;
}
if (m_lan_proto > MachineObject::LVL_None && (m_lan_mode || !m_remote_support) && !m_disable_lan && !m_lan_ip.empty()) {
std::string url;
if (m_lan_proto == MachineObject::LVL_Local)
url = "bambu:///local/" + m_lan_ip + ".?port=6000&user=" + m_lan_user + "&passwd=" + m_lan_passwd;
else if (m_lan_proto == MachineObject::LVL_Rtsps)
url = "bambu:///rtsps___" + m_lan_user + ":" + m_lan_passwd + "@" + m_lan_ip + "/streaming/live/1?proto=rtsps";
else if (m_lan_proto == MachineObject::LVL_Rtsp)
url = "bambu:///rtsp___" + m_lan_user + ":" + m_lan_passwd + "@" + m_lan_ip + "/streaming/live/1?proto=rtsp";
url += "&device=" + m_machine;
url += "&dev_ver=" + m_dev_ver;
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::ToggleStream: " << hide_passwd(url, {m_lan_passwd});
std::string file_url = data_dir() + "/cameratools/url.txt";
boost::nowide::ofstream file(file_url);
auto url2 = encode_path(url.c_str());
file.write(url2.c_str(), url2.size());
file.close();
m_streaming = true;
return;
}
NetworkAgent *agent = wxGetApp().getAgent();
if (!agent) return;
agent->get_camera_url(m_machine, [this, m = m_machine, v = agent->get_version()](std::string url) {
agent->get_camera_url(m_machine, [this, m = m_machine, v = agent->get_version(), dv = m_dev_ver](std::string url) {
if (boost::algorithm::starts_with(url, "bambu:///")) {
url += "&device=" + m;
url += "&version=" + v;
url += "&dev_ver=" + dv;
}
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::ToggleStream: " << url.substr(0, 16);
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::ToggleStream: " << hide_passwd(url, {"authkey=", "passwd="});
CallAfter([this, m, url] {
if (m != m_machine) return;
if (url.empty() || !boost::algorithm::starts_with(url, "bambu:///")) {
@ -403,6 +431,10 @@ void MediaPlayCtrl::ToggleStream()
});
}
void MediaPlayCtrl::msw_rescale() {
m_button_play->Rescale();
}
void MediaPlayCtrl::onStateChanged(wxMediaEvent &event)
{
auto last_state = m_last_state;
@ -430,14 +462,6 @@ void MediaPlayCtrl::onStateChanged(wxMediaEvent &event)
m_last_state = state;
SetStatus(_L("Playing..."), false);
// track event
json j;
j["stage"] = std::to_string(m_last_state);
j["dev_id"] = m_machine;
j["dev_ip"] = m_lan_ip;
j["result"] = "success";
j["code"] = 0;
NetworkAgent* agent = wxGetApp().getAgent();
m_failed_retry = 0;
m_failed_code = 0;
@ -476,6 +500,25 @@ void MediaPlayCtrl::SetStatus(wxString const &msg2, bool hyperlink)
bool MediaPlayCtrl::IsStreaming() const { return m_streaming; }
void MediaPlayCtrl::load()
{
m_last_state = MEDIASTATE_LOADING;
SetStatus(_L("Loading..."));
if (wxGetApp().app_config->get("internal_developer_mode") == "true") {
std::string file_h264 = data_dir() + "/video.h264";
std::string file_info = data_dir() + "/video.info";
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl dump video to " << file_h264;
// closed by BambuSource
FILE *dump_h264_file = boost::nowide::fopen(file_h264.c_str(), "wb");
FILE *dump_info_file = boost::nowide::fopen(file_info.c_str(), "wb");
m_url = m_url + "&dump_h264=" + boost::lexical_cast<std::string>(dump_h264_file);
m_url = m_url + "&dump_info=" + boost::lexical_cast<std::string>(dump_info_file);
}
boost::unique_lock lock(m_mutex);
m_tasks.push_back(m_url);
m_cond.notify_all();
}
void MediaPlayCtrl::on_show_hide(wxShowEvent &evt)
{
evt.Skip();
@ -495,7 +538,7 @@ void MediaPlayCtrl::media_proc()
}
wxString url = m_tasks.front();
if (m_tasks.size() >= 2 && !url.IsEmpty() && url[0] != '<' && m_tasks[1] == "<stop>") {
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: busy skip url" << url;
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: busy skip url: " << hide_passwd(url, {"authkey=", "passwd=", m_lan_passwd});
m_tasks.pop_front();
m_tasks.pop_front();
continue;
@ -565,7 +608,9 @@ bool MediaPlayCtrl::start_stream_service(bool *need_install)
std::string file_dll2 = data_dir() + "/plugins/BambuSource.dll";
if (!boost::filesystem::exists(file_dll) || boost::filesystem::last_write_time(file_dll) != boost::filesystem::last_write_time(file_dll2))
boost::filesystem::copy_file(file_dll2, file_dll, boost::filesystem::copy_option::overwrite_if_exists);
boost::process::child process_source(file_source, file_url2.data().AsInternal(), boost::process::start_dir(start_dir), boost::process::windows::create_no_window,
static std::locale tmp = std::locale(std::locale(), new boost::nowide::utf8_codecvt<wchar_t>());
boost::process::imbue(tmp);
boost::process::child process_source(file_source, into_u8(file_url2), boost::process::start_dir(start_dir), boost::process::windows::create_no_window,
boost::process::std_out > intermediate, boost::process::limit_handles);
boost::process::child process_ffmpeg(file_ffmpeg, configss, boost::process::windows::create_no_window,
boost::process::std_in < intermediate, boost::process::limit_handles);
@ -630,20 +675,20 @@ void wxMediaCtrl2::DoSetSize(int x, int y, int width, int height, int sizeFlags)
#else
wxMediaCtrl::DoSetSize(x, y, width, height, sizeFlags);
#endif
if (sizeFlags & wxSIZE_USE_EXISTING) return;
wxSize size = GetVideoSize();
if (size.GetWidth() <= 0)
size = wxSize{16, 9};
int maxHeight = (width * size.GetHeight() + size.GetHeight() - 1) / size.GetWidth();
if (maxHeight != GetMaxHeight()) {
// BOOST_LOG_TRIVIAL(info) << "wxMediaCtrl2::DoSetSize: width: " << width << ", height: " << height << ", maxHeight: " << maxHeight;
SetMaxSize({-1, maxHeight});
CallAfter([this] {
if (auto p = GetParent()) {
p->Layout();
p->Refresh();
}
});
}
//if (sizeFlags & wxSIZE_USE_EXISTING) return;
//wxSize size = GetVideoSize();
//if (size.GetWidth() <= 0)
// size = wxSize{16, 9};
//int maxHeight = (width * size.GetHeight() + size.GetHeight() - 1) / size.GetWidth();
//if (maxHeight != GetMaxHeight()) {
// // BOOST_LOG_TRIVIAL(info) << "wxMediaCtrl2::DoSetSize: width: " << width << ", height: " << height << ", maxHeight: " << maxHeight;
// SetMaxSize({-1, maxHeight});
// CallAfter([this] {
// if (auto p = GetParent()) {
// p->Layout();
// p->Refresh();
// }
// });
//}
}

View file

@ -40,6 +40,8 @@ public:
void ToggleStream();
void msw_rescale();
protected:
void onStateChanged(wxMediaEvent & event);
@ -52,6 +54,8 @@ protected:
void SetStatus(wxString const &msg, bool hyperlink = true);
private:
void load();
void on_show_hide(wxShowEvent & evt);
void media_proc();
@ -73,6 +77,7 @@ private:
std::string m_lan_ip;
std::string m_lan_user;
std::string m_lan_passwd;
std::string m_dev_ver;
std::string m_tutk_state;
bool m_camera_exists = false;
bool m_lan_mode = false;

View file

@ -176,12 +176,13 @@ bool MeshClipper::has_valid_contour() const
return m_result && std::any_of(m_result->cut_islands.begin(), m_result->cut_islands.end(), [](const CutIsland& isl) { return !isl.expoly.empty(); });
}
std::vector<Vec3d> MeshClipper::point_per_contour() const
{
assert(m_result);
std::vector<Vec3d> MeshClipper::point_per_contour() const {
std::vector<Vec3d> out;
for (const CutIsland& isl : m_result->cut_islands) {
if (m_result == std::nullopt) {
return out;
}
assert(m_result);
for (auto isl : m_result->cut_islands) {
assert(isl.expoly.contour.size() > 2);
// Now return a point lying inside the contour but not in a hole.
// We do this by taking a point lying close to the edge, repeating

View file

@ -60,12 +60,11 @@ MsgDialog::MsgDialog(wxWindow *parent, const wxString &title, const wxString &he
topsizer->Add(LOGO_GAP, 0, 0, wxEXPAND, 0);
topsizer->Add(rightsizer, 1, wxTOP | wxEXPAND, BORDER);
btn_sizer->AddStretchSpacer();
main_sizer->Add(topsizer, 1, wxEXPAND);
m_dsa_sizer = new wxBoxSizer(wxHORIZONTAL);
btn_sizer->Add(m_dsa_sizer,1,wxEXPAND,0);
btn_sizer->Add(0, 0, 0, wxLEFT, FromDIP(120));
btn_sizer->Add(m_dsa_sizer, 0, wxEXPAND,0);
btn_sizer->Add(0, 0, 1, wxEXPAND, 5);
main_sizer->Add(btn_sizer, 0, wxBOTTOM | wxRIGHT | wxEXPAND, BORDER);
@ -485,4 +484,65 @@ void DownloadDialog::SetExtendedMessage(const wxString &extendedMessage)
Fit();
}
}} // namespace Slic3r::GUI
DeleteConfirmDialog::DeleteConfirmDialog(wxWindow *parent, const wxString &title, const wxString &msg)
: DPIDialog(parent ? parent : nullptr, wxID_ANY, title, wxDefaultPosition, wxDefaultSize, wxCAPTION | wxCLOSE_BOX)
{
this->SetBackgroundColour(*wxWHITE);
this->SetSize(wxSize(FromDIP(450), FromDIP(200)));
std::string icon_path = (boost::format("%1%/images/OrcaSlicerTitle.ico") % resources_dir()).str();
SetIcon(wxIcon(encode_path(icon_path.c_str()), wxBITMAP_TYPE_ICO));
wxBoxSizer *m_main_sizer = new wxBoxSizer(wxVERTICAL);
// top line
auto m_line_top = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(-1, 1), wxTAB_TRAVERSAL);
m_line_top->SetBackgroundColour(wxColour(0xA6, 0xa9, 0xAA));
m_main_sizer->Add(m_line_top, 0, wxEXPAND, 0);
m_main_sizer->Add(0, 0, 0, wxTOP, FromDIP(5));
m_msg_text = new wxStaticText(this, wxID_ANY, msg);
m_main_sizer->Add(m_msg_text, 0, wxEXPAND | wxALL, FromDIP(10));
wxBoxSizer *bSizer_button = new wxBoxSizer(wxHORIZONTAL);
bSizer_button->Add(0, 0, 1, wxEXPAND, 0);
StateColor btn_bg_white(std::pair<wxColour, int>(wxColour(206, 206, 206), StateColor::Pressed), std::pair<wxColour, int>(wxColour(238, 238, 238), StateColor::Hovered),
std::pair<wxColour, int>(*wxWHITE, StateColor::Normal));
m_cancel_btn = new Button(this, _L("Cancel"));
m_cancel_btn->SetBackgroundColor(btn_bg_white);
m_cancel_btn->SetBorderColor(*wxBLACK);
m_cancel_btn->SetTextColor(wxColour(*wxBLACK));
m_cancel_btn->SetFont(Label::Body_12);
m_cancel_btn->SetSize(wxSize(FromDIP(58), FromDIP(24)));
m_cancel_btn->SetMinSize(wxSize(FromDIP(58), FromDIP(24)));
m_cancel_btn->SetCornerRadius(FromDIP(12));
bSizer_button->Add(m_cancel_btn, 0, wxRIGHT | wxBOTTOM, FromDIP(10));
m_del_btn = new Button(this, _L("Delete"));
m_del_btn->SetBackgroundColor(*wxRED);
m_del_btn->SetBorderColor(*wxWHITE);
m_del_btn->SetTextColor(wxColour(0xFFFFFE));
m_del_btn->SetFont(Label::Body_12);
m_del_btn->SetSize(wxSize(FromDIP(58), FromDIP(24)));
m_del_btn->SetMinSize(wxSize(FromDIP(58), FromDIP(24)));
m_del_btn->SetCornerRadius(FromDIP(12));
bSizer_button->Add(m_del_btn, 0, wxRIGHT | wxBOTTOM, FromDIP(10));
m_main_sizer->Add(bSizer_button, 0, wxEXPAND, 0);
m_del_btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent &e) { EndModal(wxID_OK); });
m_cancel_btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent &e) { EndModal(wxID_CANCEL); });
SetSizer(m_main_sizer);
Layout();
Fit();
wxGetApp().UpdateDlgDarkUI(this);
}
DeleteConfirmDialog::~DeleteConfirmDialog() {}
void DeleteConfirmDialog::on_dpi_changed(const wxRect &suggested_rect) {}
} // namespace GUI
} // namespace Slic3r

View file

@ -378,6 +378,19 @@ private:
wxString msg;
};
class DeleteConfirmDialog : public DPIDialog
{
public:
DeleteConfirmDialog(wxWindow *parent, const wxString &title, const wxString &msg);
~DeleteConfirmDialog();
virtual void on_dpi_changed(const wxRect &suggested_rect);
private:
wxString msg;
Button * m_del_btn = nullptr;
Button * m_cancel_btn = nullptr;
wxStaticText *m_msg_text = nullptr;
};
}
}

View file

@ -24,6 +24,8 @@ NetworkTestDialog::NetworkTestDialog(wxWindow* parent, wxWindowID id, const wxSt
wxSize(1000, 700),
/*wxCAPTION*/wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxMINIMIZE_BOX|wxRESIZE_BORDER)
{
this->SetBackgroundColour(wxColour(255, 255, 255));
this->SetSizeHints(wxDefaultSize, wxDefaultSize);
wxBoxSizer* main_sizer;
@ -49,20 +51,26 @@ NetworkTestDialog::NetworkTestDialog(wxWindow* parent, wxWindowID id, const wxSt
this->Layout();
this->Centre(wxBOTH);
wxGetApp().UpdateDlgDarkUI(this);
}
wxBoxSizer* NetworkTestDialog::create_top_sizer(wxWindow* parent)
{
StateColor btn_bg(std::pair<wxColour, int>(wxColour(0, 137, 123), StateColor::Pressed), std::pair<wxColour, int>(wxColour(38, 166, 154), StateColor::Hovered), std::pair<wxColour, int>(wxColour(255, 255, 255), StateColor::Enabled));
auto sizer = new wxBoxSizer(wxVERTICAL);
auto line_sizer = new wxBoxSizer(wxHORIZONTAL);
btn_start = new wxButton(this, wxID_ANY, _L("Start Test Multi-Thread"), wxDefaultPosition, wxDefaultSize, 0);
btn_start = new Button(this, _L("Start Test Multi-Thread"));
btn_start->SetBackgroundColor(btn_bg);
line_sizer->Add(btn_start, 0, wxALL, 5);
btn_start_sequence = new wxButton(this, wxID_ANY, _L("Start Test Single-Thread"), wxDefaultPosition, wxDefaultSize, 0);
btn_start_sequence = new Button(this, _L("Start Test Single-Thread"));
btn_start_sequence->SetBackgroundColor(btn_bg);
line_sizer->Add(btn_start_sequence, 0, wxALL, 5);
btn_download_log = new wxButton(this, wxID_ANY, _L("Export Log"), wxDefaultPosition, wxDefaultSize, 0);
btn_download_log = new Button(this, _L("Export Log"));
btn_download_log->SetBackgroundColor(btn_bg);
line_sizer->Add(btn_download_log, 0, wxALL, 5);
btn_download_log->Hide();
@ -130,7 +138,9 @@ wxBoxSizer* NetworkTestDialog::create_content_sizer(wxWindow* parent)
grid_sizer->SetFlexibleDirection(wxBOTH);
grid_sizer->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_SPECIFIED);
btn_link = new wxButton(this, wxID_ANY, _L("Test BambuLab"), wxDefaultPosition, wxDefaultSize, 0);
StateColor btn_bg(std::pair<wxColour, int>(wxColour(0, 137, 123), StateColor::Pressed),std::pair<wxColour, int>(wxColour(38, 166, 154), StateColor::Hovered), std::pair<wxColour, int>(wxColour(255,255,255), StateColor::Enabled));
btn_link = new Button(this, _L("Test BambuLab"));
btn_link->SetBackgroundColor(btn_bg);
grid_sizer->Add(btn_link, 0, wxEXPAND | wxALL, 5);
text_link_title = new wxStaticText(this, wxID_ANY, _L("Test BambuLab:"), wxDefaultPosition, wxDefaultSize, 0);
@ -141,10 +151,12 @@ wxBoxSizer* NetworkTestDialog::create_content_sizer(wxWindow* parent)
text_link_val->Wrap(-1);
grid_sizer->Add(text_link_val, 0, wxALL, 5);
btn_bing = new wxButton(this, wxID_ANY, _L("Test Bing.com"), wxDefaultPosition, wxDefaultSize, 0);
btn_bing = new Button(this, _L("Test Bing.com"));
btn_bing->SetBackgroundColor(btn_bg);
grid_sizer->Add(btn_bing, 0, wxEXPAND | wxALL, 5);
text_bing_title = new wxStaticText(this, wxID_ANY, _L("Test bing.com:"), wxDefaultPosition, wxDefaultSize, 0);
text_bing_title = new wxStaticText(this, wxID_ANY, _L("Test bing.com:"), wxDefaultPosition, wxDefaultSize, 0);
text_bing_title->Wrap(-1);
grid_sizer->Add(text_bing_title, 0, wxALIGN_RIGHT | wxALL, 5);
@ -152,7 +164,8 @@ wxBoxSizer* NetworkTestDialog::create_content_sizer(wxWindow* parent)
text_bing_val->Wrap(-1);
grid_sizer->Add(text_bing_val, 0, wxALL, 5);
btn_iot = new wxButton(this, wxID_ANY, _L("Test HTTP"), wxDefaultPosition, wxDefaultSize, 0);
btn_iot = new Button(this, _L("Test HTTP"));
btn_iot->SetBackgroundColor(btn_bg);
grid_sizer->Add(btn_iot, 0, wxEXPAND | wxALL, 5);
text_iot_title = new wxStaticText(this, wxID_ANY, _L("Test HTTP Service:"), wxDefaultPosition, wxDefaultSize, 0);
@ -163,7 +176,8 @@ wxBoxSizer* NetworkTestDialog::create_content_sizer(wxWindow* parent)
text_iot_value->Wrap(-1);
grid_sizer->Add(text_iot_value, 0, wxALL, 5);
btn_oss = new wxButton(this, wxID_ANY, _L("Test storage"), wxDefaultPosition, wxDefaultSize, 0);
btn_oss = new Button(this, _L("Test storage"));
btn_oss->SetBackgroundColor(btn_bg);
grid_sizer->Add(btn_oss, 0, wxEXPAND | wxALL, 5);
text_oss_title = new wxStaticText(this, wxID_ANY, _L("Test Storage Upload:"), wxDefaultPosition, wxDefaultSize, 0);
@ -174,7 +188,8 @@ wxBoxSizer* NetworkTestDialog::create_content_sizer(wxWindow* parent)
text_oss_value->Wrap(-1);
grid_sizer->Add(text_oss_value, 0, wxALL, 5);
btn_oss_upgrade = new wxButton(this, wxID_ANY, _L("Test storage upgrade"), wxDefaultPosition, wxDefaultSize, 0);
btn_oss_upgrade = new Button(this, _L("Test storage upgrade"));
btn_oss_upgrade->SetBackgroundColor(btn_bg);
grid_sizer->Add(btn_oss_upgrade, 0, wxEXPAND | wxALL, 5);
text_oss_upgrade_title = new wxStaticText(this, wxID_ANY, _L("Test Storage Upgrade:"), wxDefaultPosition, wxDefaultSize, 0);
@ -185,7 +200,8 @@ wxBoxSizer* NetworkTestDialog::create_content_sizer(wxWindow* parent)
text_oss_upgrade_value->Wrap(-1);
grid_sizer->Add(text_oss_upgrade_value, 0, wxALL, 5);
btn_oss_download = new wxButton(this, wxID_ANY, _L("Test storage download"), wxDefaultPosition, wxDefaultSize, 0);
btn_oss_download = new Button(this, _L("Test storage download"));
btn_oss_download->SetBackgroundColor(btn_bg);
grid_sizer->Add(btn_oss_download, 0, wxEXPAND | wxALL, 5);
text_oss_download_title = new wxStaticText(this, wxID_ANY, _L("Test Storage Download:"), wxDefaultPosition, wxDefaultSize, 0);
@ -196,7 +212,21 @@ wxBoxSizer* NetworkTestDialog::create_content_sizer(wxWindow* parent)
text_oss_download_value->Wrap(-1);
grid_sizer->Add(text_oss_download_value, 0, wxALL, 5);
btn_oss_upload = new wxButton(this, wxID_ANY, _L("Test Storage Upload"), wxDefaultPosition, wxDefaultSize, 0);
btn_network_plugin=new Button(this, _L("Test plugin download"));
btn_network_plugin->SetBackgroundColor(btn_bg);
grid_sizer->Add(btn_network_plugin, 0, wxEXPAND | wxALL, 5);
text_network_plugin_title=new wxStaticText(this, wxID_ANY, _L("Test Plugin Download:"), wxDefaultPosition, wxDefaultSize, 0);
text_network_plugin_title->Wrap(-1);
grid_sizer->Add(text_network_plugin_title, 0, wxALIGN_RIGHT | wxALL, 5);
text_network_plugin_value=new wxStaticText(this, wxID_ANY, _L("N/A"), wxDefaultPosition, wxDefaultSize, 0);
text_network_plugin_value->Wrap(-1);
grid_sizer->Add(text_network_plugin_value, 0, wxALL, 5);
btn_oss_upload = new Button(this, _L("Test Storage Upload"));
btn_oss_upload->SetBackgroundColor(btn_bg);
grid_sizer->Add(btn_oss_upload, 0, wxEXPAND | wxALL, 5);
text_oss_upload_title = new wxStaticText(this, wxID_ANY, _L("Test Storage Upload:"), wxDefaultPosition, wxDefaultSize, 0);
@ -237,6 +267,10 @@ wxBoxSizer* NetworkTestDialog::create_content_sizer(wxWindow* parent)
start_test_oss_download_thread();
});
btn_network_plugin->Bind(wxEVT_BUTTON, [this](wxCommandEvent &evt) {
start_test_plugin_download_thread();
});
return sizer;
}
wxBoxSizer* NetworkTestDialog::create_result_sizer(wxWindow* parent)
@ -273,7 +307,9 @@ void NetworkTestDialog::init_bind()
text_oss_download_value->SetLabelText(evt.GetString());
} else if (evt.GetInt() == TEST_OSS_UPLOAD_JOB) {
text_oss_upload_value->SetLabelText(evt.GetString());
}
} else if (evt.GetInt() == TEST_PLUGIN_JOB){
text_network_plugin_value->SetLabelText(evt.GetString());
}
std::time_t t = std::time(0);
std::tm* now_time = std::localtime(&t);
@ -314,12 +350,14 @@ wxString NetworkTestDialog::get_dns_info()
void NetworkTestDialog::start_all_job()
{
start_test_bing_thread();
start_test_bambulab_thread();
start_test_bing_thread();
start_test_iot_thread();
start_test_oss_thread();
start_test_oss_upgrade_thread();
start_test_oss_download_thread();
start_test_plugin_download_thread();
start_test_ping_thread();
}
@ -336,6 +374,8 @@ void NetworkTestDialog::start_all_job_sequence()
start_test_oss_upgrade();
if (m_closing) return;
start_test_oss_download();
if (m_closing) return;
start_test_plugin_download();
update_status(-1, "end_test_sequence");
});
}
@ -347,6 +387,7 @@ void NetworkTestDialog::start_test_bing()
std::string url = "http://www.bing.com/";
Slic3r::Http http = Slic3r::Http::get(url);
update_status(-1, "[test_bing]: url=" + url);
int result = -1;
http.timeout_max(10)
@ -399,6 +440,7 @@ void NetworkTestDialog::start_test_bambulab()
AppConfig* app_config = wxGetApp().app_config;
std::string url = wxGetApp().get_http_url(app_config->get_country_code()) + query_params;
Slic3r::Http http = Slic3r::Http::get(url);
update_status(-1, "[test_bambulab]: url=" + url);
int result = -1;
http.header("accept", "application/json")
.timeout_max(10)
@ -467,6 +509,7 @@ void NetworkTestDialog::start_test_oss()
}
Slic3r::Http http = Slic3r::Http::get(url);
update_status(-1, "[test_oss]: url=" + url);
int result = -1;
http.timeout_max(15)
@ -513,6 +556,7 @@ void NetworkTestDialog::start_test_oss_upgrade()
}
Slic3r::Http http = Slic3r::Http::get(url);
update_status(-1, "[test_oss_upgrade]: url=" + url);
int result = -1;
http.timeout_max(15)
@ -576,7 +620,7 @@ void NetworkTestDialog::start_test_oss_download()
try {
json j = json::parse(body);
std::string message = j["message"].get<std::string>();
if (message == "success") {
json resource = j.at("resources");
if (resource.is_array()) {
@ -672,7 +716,7 @@ void NetworkTestDialog::start_test_oss_download()
file.write(body.c_str(), body.size());
file.close();
fs::rename(tmp_path, target_file_path);
this->update_status(TEST_OSS_DOWNLOAD_JOB, "test storage download ok");
//this->update_status(TEST_OSS_DOWNLOAD_JOB, "test storage download ok");
})
.on_error([this, &result](std::string body, std::string error, unsigned int status) {
BOOST_LOG_TRIVIAL(error) << "[test_oss_download] downloading... on_error: " << error << ", body = " << body;
@ -693,7 +737,141 @@ void NetworkTestDialog::start_test_oss_download()
void NetworkTestDialog::start_test_oss_upload()
{
;
}
void NetworkTestDialog:: start_test_plugin_download(){
int result = 0;
// get country_code
AppConfig *app_config = wxGetApp().app_config;
if (!app_config) {
update_status(TEST_PLUGIN_JOB, "app config is nullptr");
return;
}
m_in_testing[TEST_PLUGIN_JOB] = true;
update_status(TEST_PLUGIN_JOB, "test plugin download start...");
m_download_cancel = false;
// get temp path
fs::path target_file_path = (fs::temp_directory_path() / "test_plugin_download.zip");
fs::path tmp_path = target_file_path;
tmp_path += (boost::format(".%1%%2%") % get_current_pid() % ".tmp").str();
// get_url
std::string url = wxGetApp().get_plugin_url("plugins", app_config->get_country_code());
std::string download_url;
Slic3r::Http http_url = Slic3r::Http::get(url);
http_url
.on_complete([&download_url,this](std::string body, unsigned status) {
try {
json j = json::parse(body);
std::string message = j["message"].get<std::string>();
if (message == "success") {
json resource = j.at("resources");
if (resource.is_array()) {
for (auto iter = resource.begin(); iter != resource.end(); iter++) {
Semver version;
std::string url;
std::string type;
std::string vendor;
std::string description;
for (auto sub_iter = iter.value().begin(); sub_iter != iter.value().end(); sub_iter++) {
if (boost::iequals(sub_iter.key(), "type")) {
type = sub_iter.value();
BOOST_LOG_TRIVIAL(info) << "[test_plugin_download]: get version of settings's type, " << sub_iter.value();
} else if (boost::iequals(sub_iter.key(), "version")) {
version = *(Semver::parse(sub_iter.value()));
} else if (boost::iequals(sub_iter.key(), "description")) {
description = sub_iter.value();
} else if (boost::iequals(sub_iter.key(), "url")) {
url = sub_iter.value();
}
}
BOOST_LOG_TRIVIAL(info) << "[test_plugin_download]: get type " << type << ", version " << version.to_string() << ", url " << url;
download_url = url;
this->update_status(-1, "[test_plugin_download]: downloadurl=" + download_url);
}
}
} else {
BOOST_LOG_TRIVIAL(info) << "[test_plugin_download]: get version of plugin failed, body=" << body;
}
} catch (...) {
BOOST_LOG_TRIVIAL(error) << "[test_plugin_download]: catch unknown exception";
;
}
})
.on_error([&result, this](std::string body, std::string error, unsigned int status) {
BOOST_LOG_TRIVIAL(error) << "[test_plugin_download] on_error: " << error << ", body = " << body;
wxString info = wxString::Format("status=%u, body=%s, error=%s", status, body, error);
this->update_status(TEST_PLUGIN_JOB, "test plugin download failed");
this->update_status(-1, info);
result = -1;
})
.perform_sync();
if (result < 0) {
this->update_status(TEST_PLUGIN_JOB, "test plugin download failed");
m_in_testing[TEST_PLUGIN_JOB] = false;
return;
}
if (download_url.empty()) {
BOOST_LOG_TRIVIAL(info) << "[test_plugin_download]: no availaible plugin found for this app version: " << SLIC3R_VERSION;
this->update_status(TEST_PLUGIN_JOB, "test plugin download failed");
m_in_testing[TEST_PLUGIN_JOB] = false;
return;
}
if (m_download_cancel) {
this->update_status(TEST_PLUGIN_JOB, "test plugin download canceled");
m_in_testing[TEST_PLUGIN_JOB] = false;
return;
}
bool cancel = false;
BOOST_LOG_TRIVIAL(info) << "[test_plugin_download] get_url = " << download_url;
// download
Slic3r::Http http = Slic3r::Http::get(download_url);
int reported_percent = 0;
http.on_progress([this, &result, &reported_percent](Slic3r::Http::Progress progress, bool &cancel) {
int percent = 0;
if (progress.dltotal != 0) { percent = progress.dlnow * 100 / progress.dltotal; }
if (percent - reported_percent >= 5) {
reported_percent = percent;
std::string download_progress_info = (boost::format("downloading %1%%%") % percent).str();
this->update_status(TEST_PLUGIN_JOB, download_progress_info);
}
BOOST_LOG_TRIVIAL(info) << "[test_plugin_download] progress: " << reported_percent;
cancel = m_download_cancel;
if (cancel) result = -1;
})
.on_complete([this, tmp_path, target_file_path](std::string body, unsigned status) {
BOOST_LOG_TRIVIAL(info) << "[test_plugin_download] completed";
bool cancel = false;
fs::fstream file(tmp_path, std::ios::out | std::ios::binary | std::ios::trunc);
file.write(body.c_str(), body.size());
file.close();
fs::rename(tmp_path, target_file_path);
})
.on_error([this, &result](std::string body, std::string error, unsigned int status) {
BOOST_LOG_TRIVIAL(error) << "[test_plugin_download] downloading... on_error: " << error << ", body = " << body;
wxString info = wxString::Format("status=%u, body=%s, error=%s", status, body, error);
this->update_status(TEST_PLUGIN_JOB, "test plugin download failed");
this->update_status(-1, info);
result = -1;
});
http.perform_sync();
if (result < 0) {
this->update_status(TEST_PLUGIN_JOB, "test plugin download failed");
} else {
this->update_status(TEST_PLUGIN_JOB, "test plugin download ok");
}
m_in_testing[TEST_PLUGIN_JOB] = false;
return;
}
void NetworkTestDialog::start_test_ping_thread()
@ -756,6 +934,13 @@ void NetworkTestDialog::start_test_oss_upload_thread()
});
}
void NetworkTestDialog:: start_test_plugin_download_thread(){
test_job[TEST_PLUGIN_JOB] = new boost::thread([this] {
start_test_plugin_download();
});
}
void NetworkTestDialog::on_close(wxCloseEvent& event)
{
m_download_cancel = true;
@ -795,6 +980,7 @@ void NetworkTestDialog::set_default()
text_oss_upgrade_value->SetLabelText(NA_STR);
text_oss_download_value->SetLabelText(NA_STR);
text_oss_upload_value->SetLabelText(NA_STR);
text_network_plugin_value->SetLabelText(NA_STR);
//text_ping_value->SetLabelText(NA_STR);
m_download_cancel = false;
m_closing = false;

View file

@ -6,6 +6,7 @@
#include "GUI_Utils.hpp"
#include "wxExtensions.hpp"
#include <slic3r/GUI/Widgets/Button.hpp>
#include <wx/artprov.h>
#include <wx/xrc/xmlres.h>
#include <wx/button.h>
@ -41,15 +42,16 @@ enum TestJob {
TEST_OSS_DOWNLOAD_JOB = 5,
TEST_OSS_UPLOAD_JOB = 6,
TEST_PING_JOB = 7,
TEST_JOB_MAX = 8
TEST_PLUGIN_JOB = 8,
TEST_JOB_MAX = 9
};
class NetworkTestDialog : public DPIDialog
{
protected:
wxButton* btn_start;
wxButton* btn_start_sequence;
wxButton* btn_download_log;
Button* btn_start;
Button* btn_start_sequence;
Button* btn_download_log;
wxStaticText* text_basic_info;
wxStaticText* text_version_title;
wxStaticText* text_version_val;
@ -57,27 +59,30 @@ protected:
wxStaticText* txt_sys_info_value;
wxStaticText* txt_dns_info_title;
wxStaticText* txt_dns_info_value;
wxButton* btn_link;
Button* btn_link;
wxStaticText* text_link_title;
wxStaticText* text_link_val;
wxButton* btn_bing;
Button* btn_bing;
wxStaticText* text_bing_title;
wxStaticText* text_bing_val;
wxButton* btn_iot;
Button* btn_iot;
wxStaticText* text_iot_title;
wxStaticText* text_iot_value;
wxButton* btn_oss;
Button* btn_oss;
wxStaticText* text_oss_title;
wxStaticText* text_oss_value;
wxButton* btn_oss_upgrade;
Button* btn_oss_upgrade;
wxStaticText* text_oss_upgrade_title;
wxStaticText* text_oss_upgrade_value;
wxButton* btn_oss_download;
Button* btn_oss_download;
wxStaticText* text_oss_download_title;
wxStaticText* text_oss_download_value;
wxButton* btn_oss_upload;
Button* btn_oss_upload;
wxStaticText* text_oss_upload_title;
wxStaticText* text_oss_upload_value;
Button* btn_network_plugin;
wxStaticText* text_network_plugin_title;
wxStaticText* text_network_plugin_value;
wxStaticText* text_ping_title;
wxStaticText* text_ping_value;
wxStaticText* text_result;
@ -118,6 +123,7 @@ public:
void start_test_oss_download_thread();
void start_test_oss_upload_thread();
void start_test_ping_thread();
void start_test_plugin_download_thread();
void start_test_bing();
void start_test_bambulab();
@ -126,6 +132,7 @@ public:
void start_test_oss_upgrade();
void start_test_oss_download();
void start_test_oss_upload();
void start_test_plugin_download();
void on_close(wxCloseEvent& event);

View file

@ -1,6 +1,7 @@
#include "NotificationManager.hpp"
#include "HintNotification.hpp"
#include "SlicingProgressNotification.hpp"
#include "GUI.hpp"
#include "ImGuiWrapper.hpp"
#include "wxExtensions.hpp"
@ -39,6 +40,7 @@ namespace GUI {
wxDEFINE_EVENT(EVT_EJECT_DRIVE_NOTIFICAION_CLICKED, EjectDriveNotificationClickedEvent);
wxDEFINE_EVENT(EVT_EXPORT_GCODE_NOTIFICAION_CLICKED, ExportGcodeNotificationClickedEvent);
wxDEFINE_EVENT(EVT_PRESET_UPDATE_AVAILABLE_CLICKED, PresetUpdateAvailableClickedEvent);
wxDEFINE_EVENT(EVT_PRINTER_CONFIG_UPDATE_AVAILABLE_CLICKED, PrinterConfigUpdateAvailableClickedEvent);
namespace {
/* // not used?
@ -221,7 +223,6 @@ void NotificationManager::PopNotification::restore_default_theme()
void NotificationManager::PopNotification::render(GLCanvas3D& canvas, float initial_y, bool move_from_overlay, float overlay_width, float right_margin)
{
if (m_state == EState::Unknown)
init();
@ -250,14 +251,13 @@ void NotificationManager::PopNotification::render(GLCanvas3D& canvas, float init
// top y of window
m_top_y = initial_y + m_window_height;
// position of upper-right corner
ImVec2 win_pos(1.0f * (float)cnv_size.get_width() - right_gap, 1.0f * (float)cnv_size.get_height() - m_top_y);
imgui.set_next_window_pos(win_pos.x, win_pos.y, ImGuiCond_Always, 1.0f, 0.0f);
imgui.set_next_window_size(m_window_width, m_window_height, ImGuiCond_Always);
// find if hovered FIXME: do it only in update state?
if (m_state == EState::Hovered) {
m_state = EState::Unknown;
init();
}
@ -284,11 +284,11 @@ void NotificationManager::PopNotification::render(GLCanvas3D& canvas, float init
use_bbl_theme();
if (imgui.begin(name, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse)) {
int window_flags = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse;
if (imgui.begin(name, window_flags)) {
ImVec2 win_size = ImGui::GetWindowSize();
bbl_render_left_sign(imgui, win_size.x, win_size.y, win_pos.x, win_pos.y);
render_left_sign(imgui);
render_text(imgui, win_size.x, win_size.y, win_pos.x, win_pos.y);
render_close_button(imgui, win_size.x, win_size.y, win_pos.x, win_pos.y);
@ -544,10 +544,13 @@ void NotificationManager::PopNotification::init()
count_spaces();
count_lines();
if (m_lines_count == 3)
m_multiline = true;
if (m_lines_count <= 6) {
if (m_state == EState::Unknown) // if is default state
m_multiline = true;
}
m_notification_start = GLCanvas3D::timestamp_now();
if (m_state == EState::Unknown)
if (m_state == EState::Unknown || m_state == EState::Hovered)
m_state = EState::Shown;
}
void NotificationManager::PopNotification::set_next_window_size(ImGuiWrapper& imgui)
@ -971,7 +974,6 @@ bool NotificationManager::PopNotification::update_state(bool paused, const int64
// reset timers - hovered state is set in render
if (m_state == EState::Hovered) {
m_state = EState::Unknown;
init();
// Timers when not fading
} else if (m_state != EState::NotFading && m_state != EState::FadingOut && m_state != EState::ClosePending && m_state != EState::Finished && get_duration() != 0 && !paused) {
@ -1408,275 +1410,6 @@ void NotificationManager::PrintHostUploadNotification::render_cancel_button(ImGu
}
ImGui::PopStyleColor(5);
}
//------SlicingProgressNotification
void NotificationManager::SlicingProgressNotification::init()
{
if (m_sp_state == SlicingProgressState::SP_PROGRESS) {
ProgressBarNotification::init();
//if (m_state == EState::NotFading && m_percentage >= 1.0f)
// m_state = EState::Shown;
}
else {
PopNotification::init();
}
}
bool NotificationManager::SlicingProgressNotification::set_progress_state(float percent)
{
if (percent < 0.f)
return true;//set_progress_state(SlicingProgressState::SP_CANCELLED);
else if (percent >= 1.f)
return set_progress_state(SlicingProgressState::SP_COMPLETED);
else
return set_progress_state(SlicingProgressState::SP_PROGRESS, percent);
}
bool NotificationManager::SlicingProgressNotification::set_progress_state(NotificationManager::SlicingProgressNotification::SlicingProgressState state, float percent/* = 0.f*/)
{
switch (state)
{
case Slic3r::GUI::NotificationManager::SlicingProgressNotification::SlicingProgressState::SP_NO_SLICING:
m_state = EState::Hidden;
set_percentage(-1);
m_has_print_info = false;
set_export_possible(false);
m_sp_state = state;
return true;
case Slic3r::GUI::NotificationManager::SlicingProgressNotification::SlicingProgressState::SP_BEGAN:
m_state = EState::Hidden;
set_percentage(-1);
m_has_print_info = false;
set_export_possible(false);
m_sp_state = state;
m_current_fade_opacity = 1;
return true;
case Slic3r::GUI::NotificationManager::SlicingProgressNotification::SlicingProgressState::SP_PROGRESS:
if ((m_sp_state != SlicingProgressState::SP_BEGAN && m_sp_state != SlicingProgressState::SP_PROGRESS) || percent < m_percentage)
return false;
set_percentage(percent);
m_has_cancel_button = true;
m_sp_state = state;
m_current_fade_opacity = 1;
return true;
case Slic3r::GUI::NotificationManager::SlicingProgressNotification::SlicingProgressState::SP_CANCELLED:
set_percentage(-1);
m_has_cancel_button = false;
m_has_print_info = false;
set_export_possible(false);
m_sp_state = state;
return true;
case Slic3r::GUI::NotificationManager::SlicingProgressNotification::SlicingProgressState::SP_COMPLETED:
if (m_sp_state != SlicingProgressState::SP_BEGAN && m_sp_state != SlicingProgressState::SP_PROGRESS)
return false;
set_percentage(1);
m_has_cancel_button = false;
m_has_print_info = false;
// m_export_possible is important only for SP_PROGRESS state, thus we can reset it here
set_export_possible(false);
m_sp_state = state;
return true;
default:
break;
}
return false;
}
void NotificationManager::SlicingProgressNotification::set_status_text(const std::string& text)
{
switch (m_sp_state)
{
case Slic3r::GUI::NotificationManager::SlicingProgressNotification::SlicingProgressState::SP_NO_SLICING:
m_state = EState::Hidden;
break;
case Slic3r::GUI::NotificationManager::SlicingProgressNotification::SlicingProgressState::SP_PROGRESS:
{
NotificationData data{ NotificationType::SlicingProgress, NotificationLevel::ProgressBarNotificationLevel, 0, text + "." };
update(data);
m_state = EState::NotFading;
}
break;
case Slic3r::GUI::NotificationManager::SlicingProgressNotification::SlicingProgressState::SP_CANCELLED:
{
NotificationData data{ NotificationType::SlicingProgress, NotificationLevel::ProgressBarNotificationLevel, 0, text };
update(data);
m_state = EState::Shown;
}
break;
case Slic3r::GUI::NotificationManager::SlicingProgressNotification::SlicingProgressState::SP_COMPLETED:
{
NotificationData data{ NotificationType::SlicingProgress, NotificationLevel::ProgressBarNotificationLevel, 0, _u8L("Slice ok.") };
update(data);
m_state = EState::Shown;
}
break;
default:
break;
}
}
void NotificationManager::SlicingProgressNotification::set_print_info(const std::string& info)
{
if (m_sp_state != SlicingProgressState::SP_COMPLETED) {
set_progress_state (SlicingProgressState::SP_COMPLETED);
} else {
m_has_print_info = true;
m_print_info = info;
}
}
void NotificationManager::SlicingProgressNotification::set_sidebar_collapsed(bool collapsed)
{
m_sidebar_collapsed = collapsed;
if (m_sp_state == SlicingProgressState::SP_COMPLETED && collapsed)
m_state = EState::NotFading;
}
void NotificationManager::SlicingProgressNotification::on_cancel_button()
{
if (m_cancel_callback){
if (!m_cancel_callback()) {
set_progress_state(SlicingProgressState::SP_NO_SLICING);
}
}
}
int NotificationManager::SlicingProgressNotification::get_duration()
{
if (m_sp_state == SlicingProgressState::SP_CANCELLED)
return 2;
else if (m_sp_state == SlicingProgressState::SP_COMPLETED && !m_sidebar_collapsed)
return 2;
else
return 0;
}
bool NotificationManager::SlicingProgressNotification::update_state(bool paused, const int64_t delta)
{
bool ret = ProgressBarNotification::update_state(paused, delta);
// sets Estate to hidden
if (get_state() == PopNotification::EState::ClosePending || get_state() == PopNotification::EState::Finished)
set_progress_state(SlicingProgressState::SP_NO_SLICING);
return ret;
}
void NotificationManager::SlicingProgressNotification::render_text(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
{
if (m_sp_state == SlicingProgressState::SP_PROGRESS /*|| (m_sp_state == SlicingProgressState::SP_COMPLETED && !m_sidebar_collapsed)*/) {
ProgressBarNotification::render_text(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y);
/* // enable for hypertext during slicing (correct call of export_enabled needed)
if (m_multiline) {
// two lines text, one line bar
ImGui::SetCursorPosX(m_left_indentation);
ImGui::SetCursorPosY(m_line_height / 4);
imgui.text(m_text1.substr(0, m_endlines[0]).c_str());
ImGui::SetCursorPosX(m_left_indentation);
ImGui::SetCursorPosY(m_line_height + m_line_height / 4);
std::string line = m_text1.substr(m_endlines[0] + (m_text1[m_endlines[0]] == '\n' || m_text1[m_endlines[0]] == ' ' ? 1 : 0), m_endlines[1] - m_endlines[0] - (m_text1[m_endlines[0]] == '\n' || m_text1[m_endlines[0]] == ' ' ? 1 : 0));
imgui.text(line.c_str());
if (m_sidebar_collapsed && m_sp_state == SlicingProgressState::SP_PROGRESS && m_export_possible) {
ImVec2 text_size = ImGui::CalcTextSize(line.c_str());
render_hypertext(imgui, m_left_indentation + text_size.x + 4, m_line_height + m_line_height / 4, m_hypertext);
}
if (m_has_cancel_button)
render_cancel_button(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y);
render_bar(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y);
}
else {
//one line text, one line bar
ImGui::SetCursorPosX(m_left_indentation);
ImGui::SetCursorPosY(m_line_height / 4);
std::string line = m_text1.substr(0, m_endlines[0]);
imgui.text(line.c_str());
if (m_sidebar_collapsed && m_sp_state == SlicingProgressState::SP_PROGRESS && m_export_possible) {
ImVec2 text_size = ImGui::CalcTextSize(line.c_str());
render_hypertext(imgui, m_left_indentation + text_size.x + 4, m_line_height / 4, m_hypertext);
}
if (m_has_cancel_button)
render_cancel_button(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y);
render_bar(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y);
}
*/
} else if (m_sp_state == SlicingProgressState::SP_COMPLETED && m_sidebar_collapsed) {
// "Slicing Finished" on line 1 + hypertext, print info on line
ImVec2 win_size(win_size_x, win_size_y);
ImVec2 text1_size = ImGui::CalcTextSize(m_text1.c_str());
float x_offset = m_left_indentation;
std::string fulltext = m_text1 + m_hypertext + m_text2;
ImVec2 text_size = ImGui::CalcTextSize(fulltext.c_str());
float cursor_y = win_size.y / 2 - text_size.y / 2;
if (m_sidebar_collapsed && m_has_print_info) {
x_offset = 20;
cursor_y = win_size.y / 2 + win_size.y / 6 - text_size.y / 2;
ImGui::SetCursorPosX(x_offset);
ImGui::SetCursorPosY(cursor_y);
imgui.text(m_print_info.c_str());
cursor_y = win_size.y / 2 - win_size.y / 6 - text_size.y / 2;
}
ImGui::SetCursorPosX(x_offset);
ImGui::SetCursorPosY(cursor_y);
imgui.text(m_text1.c_str());
if (m_sidebar_collapsed)
render_hypertext(imgui, x_offset + text1_size.x + 4, cursor_y, m_hypertext);
} else {
PopNotification::render_text(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y);
}
}
void NotificationManager::SlicingProgressNotification::render_bar(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
{
if (m_sp_state != SlicingProgressState::SP_PROGRESS) {
return;
}
ProgressBarNotification::render_bar(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y);
}
void NotificationManager::SlicingProgressNotification::render_hypertext(ImGuiWrapper& imgui,const float text_x, const float text_y, const std::string text, bool more)
{
if (m_sp_state == SlicingProgressState::SP_COMPLETED && !m_sidebar_collapsed)
return;
ProgressBarNotification::render_hypertext(imgui, text_x, text_y, text, more);
}
void NotificationManager::SlicingProgressNotification::render_cancel_button(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
{
ImVec2 win_size(win_size_x, win_size_y);
ImVec2 win_pos(win_pos_x, win_pos_y);
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(.0f, .0f, .0f, .0f));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(.0f, .0f, .0f, .0f));
push_style_color(ImGuiCol_Text, ImVec4(1.f, 1.f, 1.f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity);
push_style_color(ImGuiCol_TextSelectedBg, ImVec4(0, .75f, .75f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity);
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(.0f, .0f, .0f, .0f));
std::string button_text;
button_text = ImGui::CancelButton;
if (ImGui::IsMouseHoveringRect(ImVec2(win_pos.x - win_size.x / 10.f, win_pos.y),
ImVec2(win_pos.x, win_pos.y + win_size.y - (m_minimize_b_visible ? 2 * m_line_height : 0)),
true))
{
button_text = ImGui::CancelHoverButton;
}
ImVec2 button_pic_size = ImGui::CalcTextSize(button_text.c_str());
ImVec2 button_size(button_pic_size.x * 1.25f, button_pic_size.y * 1.25f);
ImGui::SetCursorPosX(win_size.x - m_line_height * 2.75f);
ImGui::SetCursorPosY(win_size.y / 2 - button_size.y);
if (imgui.button(button_text.c_str(), button_size.x, button_size.y))
{
on_cancel_button();
}
//invisible large button
ImGui::SetCursorPosX(win_size.x - m_line_height * 2.35f);
ImGui::SetCursorPosY(0);
if (imgui.button(" ", m_line_height * 2.125, win_size.y - (m_minimize_b_visible ? 2 * m_line_height : 0)))
{
on_cancel_button();
}
ImGui::PopStyleColor();
ImGui::PopStyleColor();
ImGui::PopStyleColor();
ImGui::PopStyleColor();
ImGui::PopStyleColor();
}
void NotificationManager::SlicingProgressNotification::render_close_button(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
{
// Do not render close button while showing progress - cancel button is rendered instead
if (m_sp_state != SlicingProgressState::SP_PROGRESS) {
ProgressBarNotification::render_close_button(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y);
}
}
//------ProgressIndicatorNotification-------
void NotificationManager::ProgressIndicatorNotification::set_status_text(const char* text)
{
@ -1700,6 +1433,7 @@ void NotificationManager::ProgressIndicatorNotification::init()
else {
m_lines_count = 2;
m_endlines.push_back(m_endlines.back());
m_multiline = false;
}
switch (m_progress_state)
{
@ -1845,20 +1579,25 @@ void NotificationManager::push_validate_error_notification(StringObjectException
{
auto po = dynamic_cast<PrintObjectBase const *>(error.object);
auto mo = po ? po->model_object() : dynamic_cast<ModelObject const *>(error.object);
auto callback = (mo || !error.opt_key.empty()) ? [id = mo ? mo->id() : 0, opt = error.opt_key](wxEvtHandler *) {
auto & objects = wxGetApp().model().objects;
auto iter = id.id ? std::find_if(objects.begin(), objects.end(), [id](auto o) { return o->id() == id; }) : objects.end();
if (iter != objects.end())
wxGetApp().obj_list()->select_items({{*iter, nullptr}});
if (!opt.empty()) {
if (iter != objects.end())
wxGetApp().params_panel()->switch_to_object();
wxGetApp().sidebar().jump_to_option(opt, Preset::TYPE_PRINT, L"");
} else {
wxGetApp().mainframe->select_tab(MainFrame::tp3DEditor);
}
return false;
} : std::function<bool(wxEvtHandler *)>();
std::function<bool(wxEvtHandler*)> callback;
if (mo || !error.opt_key.empty()) {
callback =
[id = mo ? mo->id() : 0, opt = error.opt_key](wxEvtHandler*) {
auto& objects = wxGetApp().model().objects;
auto iter = id.id ? std::find_if(objects.begin(), objects.end(), [id](auto o) { return o->id() == id; }) : objects.end();
if (iter != objects.end())
wxGetApp().obj_list()->select_items({ {*iter, nullptr} });
if (!opt.empty()) {
if (iter != objects.end())
wxGetApp().params_panel()->switch_to_object();
wxGetApp().sidebar().jump_to_option(opt, Preset::TYPE_PRINT, L"");
}
else {
wxGetApp().mainframe->select_tab(MainFrame::tp3DEditor);
}
return false;
};
}
auto link = (mo || !error.opt_key.empty()) ? _u8L("Jump to") : "";
if (mo) link += std::string(" [") + mo->name + "]";
if (!error.opt_key.empty()) link += std::string(" (") + error.opt_key + ")";
@ -1873,19 +1612,22 @@ void NotificationManager::push_slicing_error_notification(const std::string &tex
if (optr)
ids.push_back(optr->id());
}
auto callback = !objs.empty() ? [ids](wxEvtHandler *) {
auto & objects = wxGetApp().model().objects;
std::vector<ObjectVolumeID> ovs;
for (auto id : ids) {
auto iter = std::find_if(objects.begin(), objects.end(), [id](auto o) { return o->id() == id; });
if (iter != objects.end()) { ovs.push_back({*iter, nullptr}); }
}
if (!ovs.empty()) {
wxGetApp().mainframe->select_tab(MainFrame::tp3DEditor);
wxGetApp().obj_list()->select_items(ovs);
}
return false;
} : std::function<bool(wxEvtHandler *)>();
std::function<bool(wxEvtHandler*)> callback;
if (!objs.empty()) {
callback = [ids](wxEvtHandler*) {
auto& objects = wxGetApp().model().objects;
std::vector<ObjectVolumeID> ovs;
for (auto id : ids) {
auto iter = std::find_if(objects.begin(), objects.end(), [id](auto o) { return o->id() == id; });
if (iter != objects.end()) { ovs.push_back({ *iter, nullptr }); }
}
if (!ovs.empty()) {
wxGetApp().mainframe->select_tab(MainFrame::tp3DEditor);
wxGetApp().obj_list()->select_items(ovs);
}
return false;
};
}
auto link = callback ? _u8L("Jump to") : "";
if (!objs.empty()) {
link += " [";
@ -1905,15 +1647,18 @@ void NotificationManager::push_slicing_error_notification(const std::string &tex
}
void NotificationManager::push_slicing_warning_notification(const std::string& text, bool gray, ModelObject const * obj, ObjectID oid, int warning_step, int warning_msg_id, NotificationLevel level/* = NotificationLevel::WarningNotificationLevel*/)
{
auto callback = obj ? [id = obj->id()](wxEvtHandler *) {
auto & objects = wxGetApp().model().objects;
auto iter = std::find_if(objects.begin(), objects.end(), [id](auto o) { return o->id() == id; });
if (iter != objects.end()) {
wxGetApp().mainframe->select_tab(MainFrame::tp3DEditor);
wxGetApp().obj_list()->select_items({{*iter, nullptr}});
}
return false;
} : std::function<bool(wxEvtHandler *)>();
std::function<bool(wxEvtHandler*)> callback;
if (obj) {
callback = [id = obj->id()](wxEvtHandler*) {
auto& objects = wxGetApp().model().objects;
auto iter = std::find_if(objects.begin(), objects.end(), [id](auto o) { return o->id() == id; });
if (iter != objects.end()) {
wxGetApp().mainframe->select_tab(MainFrame::tp3DEditor);
wxGetApp().obj_list()->select_items({ {*iter, nullptr} });
}
return false;
};
}
auto link = callback ? _u8L("Jump to") : "";
if (obj) link += std::string(" [") + obj->name + "]";
NotificationData data { NotificationType::SlicingWarning, level, 0, _u8L("Warning:") + "\n" + text, link, callback };
@ -2139,21 +1884,22 @@ void NotificationManager::push_slicing_serious_warning_notification(const std::s
for (auto optr : objs) {
if (optr) ids.push_back(optr->id());
}
auto callback = !objs.empty() ?
[ids](wxEvtHandler *) {
auto & objects = wxGetApp().model().objects;
std::vector<ObjectVolumeID> ovs;
for (auto id : ids) {
auto iter = std::find_if(objects.begin(), objects.end(), [id](auto o) { return o->id() == id; });
if (iter != objects.end()) { ovs.push_back({*iter, nullptr}); }
}
if (!ovs.empty()) {
wxGetApp().mainframe->select_tab(MainFrame::tp3DEditor);
wxGetApp().obj_list()->select_items(ovs);
}
return false;
} :
std::function<bool(wxEvtHandler *)>();
std::function<bool(wxEvtHandler*)> callback;
if (!objs.empty()) {
callback = [ids](wxEvtHandler*) {
auto& objects = wxGetApp().model().objects;
std::vector<ObjectVolumeID> ovs;
for (auto id : ids) {
auto iter = std::find_if(objects.begin(), objects.end(), [id](auto o) { return o->id() == id; });
if (iter != objects.end()) { ovs.push_back({ *iter, nullptr }); }
}
if (!ovs.empty()) {
wxGetApp().mainframe->select_tab(MainFrame::tp3DEditor);
wxGetApp().obj_list()->select_items(ovs);
}
return false;
};
}
auto link = callback ? _u8L("Jump to") : "";
if (!objs.empty()) {
link += " [";
@ -2197,6 +1943,22 @@ void NotificationManager::init_slicing_progress_notification(std::function<bool(
};
push_notification_data(std::make_unique<NotificationManager::SlicingProgressNotification>(data, m_id_provider, m_evt_handler, cancel_callback), 0);
}
void NotificationManager::update_slicing_notif_dailytips(bool need_change)
{
for (std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
if (notification->get_type() == NotificationType::SlicingProgress) {
SlicingProgressNotification* spn = dynamic_cast<SlicingProgressNotification*>(notification.get());
if (need_change) {
wxGetApp().plater()->get_dailytips()->close();
spn->get_dailytips_panel()->retrieve_data_from_hint_database(HintDataNavigation::Random);
wxGetApp().plater()->get_current_canvas3D()->schedule_extra_frame(0);
}
return;
}
}
// Slicing progress notification was not found - init it thru plater so correct cancel callback function is appended
wxGetApp().plater()->init_notification_manager();
}
void NotificationManager::set_slicing_progress_began()
{
for (std::unique_ptr<PopNotification> & notification : m_pop_notifications) {
@ -2354,6 +2116,7 @@ int NotificationManager::progress_indicator_get_range() const
void NotificationManager::push_hint_notification(bool open_next)
{
return;
for (std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
if (notification->get_type() == NotificationType::DidYouKnowHint) {
(dynamic_cast<HintNotification*>(notification.get()))->open_next();
@ -2472,6 +2235,7 @@ void NotificationManager::render_notifications(GLCanvas3D &canvas, float overlay
float bottom_up_last_y = bottom_margin * m_scale;
int i = 0;
for (const auto& notification : m_pop_notifications) {
if (notification->get_data().level == NotificationLevel::ErrorNotificationLevel || notification->get_data().level == NotificationLevel::SeriousWarningNotificationLevel) {
notification->bbl_render_block_notification(canvas, bottom_up_last_y, m_move_from_overlay && !m_in_preview, overlay_width * m_scale, right_margin * m_scale);
@ -2479,13 +2243,19 @@ void NotificationManager::render_notifications(GLCanvas3D &canvas, float overlay
bottom_up_last_y = notification->get_top() + GAP_WIDTH;
}
else {
if (notification->get_state() != PopNotification::EState::Hidden) {
if (notification->get_state() != PopNotification::EState::Hidden && notification->get_state() != PopNotification::EState::Finished) {
i++;
notification->render(canvas, bottom_up_last_y, m_move_from_overlay && !m_in_preview, overlay_width * m_scale, right_margin * m_scale);
if (notification->get_state() != PopNotification::EState::Finished)
bottom_up_last_y = notification->get_top() + GAP_WIDTH;
}
}
}
for (const auto& notification : m_pop_notifications) {
if (notification->get_data().type == NotificationType::SlicingProgress && notification->get_state() != PopNotification::EState::Hidden && notification->get_state() != PopNotification::EState::Finished) {
;// assert(i <= 1);
}
}
m_last_render = GLCanvas3D::timestamp_now();
}
@ -2952,7 +2722,10 @@ void NotificationManager::bbl_chose_sole_text_notification(NotificationType sTyp
void NotificationManager::set_scale(float scale)
{
if(m_scale != scale)m_scale = scale;
if(m_scale != scale) m_scale = scale;
for (auto& notif : m_pop_notifications) {
notif->set_scale(scale);
}
}

View file

@ -27,6 +27,8 @@ using ExportGcodeNotificationClickedEvent = SimpleEvent;
wxDECLARE_EVENT(EVT_EXPORT_GCODE_NOTIFICAION_CLICKED, ExportGcodeNotificationClickedEvent);
using PresetUpdateAvailableClickedEvent = SimpleEvent;
wxDECLARE_EVENT(EVT_PRESET_UPDATE_AVAILABLE_CLICKED, PresetUpdateAvailableClickedEvent);
using PrinterConfigUpdateAvailableClickedEvent = SimpleEvent;
wxDECLARE_EVENT(EVT_PRINTER_CONFIG_UPDATE_AVAILABLE_CLICKED, PrinterConfigUpdateAvailableClickedEvent);
using CancelFn = std::function<void()>;
@ -141,6 +143,8 @@ enum class NotificationType
BBLPluginInstallHint,
BBLPluginUpdateAvailable,
BBLPreviewOnlyMode,
BBLPrinterConfigUpdateAvailable,
BBLUserPresetExceedLimit,
};
class NotificationManager
@ -240,6 +244,7 @@ public:
// notifications with progress bar
// slicing progress
void init_slicing_progress_notification(std::function<bool()> cancel_callback);
void update_slicing_notif_dailytips(bool need_change);
void set_slicing_progress_began();
// percentage negative = canceled, <0-1) = progress, 1 = completed
void set_slicing_progress_percentage(const std::string& text, float percentage);
@ -412,7 +417,8 @@ private:
// set start of notification to now. Used by delayed notifications
void reset_timer() { m_notification_start = GLCanvas3D::timestamp_now(); m_state = EState::Shown; }
void set_Multiline(bool Multi) { m_multiline = Multi; }
void on_change_color_mode(bool is_dark);
virtual void on_change_color_mode(bool is_dark);
void set_scale(float scale) { m_scale = scale; }
protected:
// Call after every size change
@ -545,6 +551,8 @@ private:
size_t m_lines_count{ 1 };
// Target for wxWidgets events sent by clicking on the hyperlink available at some notifications.
wxEvtHandler* m_evt_handler;
float m_scale = 1.0f;
};
@ -639,74 +647,6 @@ private:
long m_hover_time{ 0 };
UploadJobState m_uj_state{ UploadJobState::PB_PROGRESS };
};
class SlicingProgressNotification : public ProgressBarNotification
{
public:
// Inner state of notification, Each state changes bahaviour of the notification
enum class SlicingProgressState
{
SP_NO_SLICING, // hidden
SP_BEGAN, // still hidden but allows to go to SP_PROGRESS state. This prevents showing progress after slicing was canceled.
SP_PROGRESS, // never fades outs, no close button, has cancel button
SP_CANCELLED, // fades after 10 seconds, simple message
SP_COMPLETED // Has export hyperlink and print info, fades after 20 sec if sidebar is shown, otherwise no fade out
};
SlicingProgressNotification(const NotificationData& n, NotificationIDProvider& id_provider, wxEvtHandler* evt_handler, std::function<bool()> callback)
: ProgressBarNotification(n, id_provider, evt_handler)
, m_cancel_callback(callback)
{
set_progress_state(SlicingProgressState::SP_NO_SLICING);
m_has_cancel_button = false;
m_render_percentage = true;
}
// sets text of notification - call after setting progress state
void set_status_text(const std::string& text);
// sets cancel button callback
void set_cancel_callback(std::function<bool()> callback) { m_cancel_callback = callback; }
bool has_cancel_callback() const { return m_cancel_callback != nullptr; }
// sets SlicingProgressState, negative percent means canceled, returns true if state was set succesfully.
bool set_progress_state(float percent);
// sets SlicingProgressState, percent is used only at progress state. Returns true if state was set succesfully.
bool set_progress_state(SlicingProgressState state,float percent = 0.f);
// sets additional string of print info and puts notification into Completed state.
void set_print_info(const std::string& info);
// sets fading if in Completed state.
void set_sidebar_collapsed(bool collapsed);
// Calls inherited update_state and ensures Estate goes to hidden not closing.
bool update_state(bool paused, const int64_t delta) override;
// Switch between technology to provide correct text.
void set_fff(bool b) { m_is_fff = b; }
void set_fdm(bool b) { m_is_fff = b; }
void set_sla(bool b) { m_is_fff = !b; }
void set_export_possible(bool b) { m_export_possible = b; }
protected:
void init() override;
void render_text(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y) override;
void render_bar(ImGuiWrapper& imgui,
const float win_size_x, const float win_size_y,
const float win_pos_x, const float win_pos_y) override;
void render_cancel_button(ImGuiWrapper& imgui,
const float win_size_x, const float win_size_y,
const float win_pos_x, const float win_pos_y) override;
void render_close_button(ImGuiWrapper& imgui,
const float win_size_x, const float win_size_y,
const float win_pos_x, const float win_pos_y) override;
void render_hypertext(ImGuiWrapper& imgui,
const float text_x, const float text_y,
const std::string text,
bool more = false) override ;
void on_cancel_button();
int get_duration() override;
// if returns false, process was already canceled
std::function<bool()> m_cancel_callback;
SlicingProgressState m_sp_state { SlicingProgressState::SP_PROGRESS };
bool m_has_print_info { false };
std::string m_print_info;
bool m_sidebar_collapsed { false };
bool m_is_fff { true };
// if true, it is possible show export hyperlink in state SP_PROGRESS
bool m_export_possible { false };
};
class ProgressIndicatorNotification : public ProgressBarNotification
{
@ -804,6 +744,9 @@ private:
std::vector<std::pair<InfoItemType, size_t>> m_types_and_counts;
};
// in SlicingProgressNotification.hpp
class SlicingProgressNotification;
// in HintNotification.hpp
class HintNotification;
@ -915,6 +858,21 @@ private:
return true;
}},
NotificationData{NotificationType::BBLPrinterConfigUpdateAvailable, NotificationLevel::ImportantNotificationLevel, BBL_NOTICE_MAX_INTERVAL,
_u8L("New printer config available."), _u8L("Details"),
[](wxEvtHandler *evnthndlr) {
if (evnthndlr != nullptr) wxPostEvent(evnthndlr, PrinterConfigUpdateAvailableClickedEvent(EVT_PRINTER_CONFIG_UPDATE_AVAILABLE_CLICKED));
return true;
}},
NotificationData{NotificationType::BBLUserPresetExceedLimit, NotificationLevel::WarningNotificationLevel, BBL_NOTICE_MAX_INTERVAL,
_u8L("The number of user presets cached in the cloud has exceeded the upper limit, newly created user presets can only be used locally."),
_u8L("Wiki"),
[](wxEvtHandler* evnthndlr) {
wxLaunchDefaultBrowser("https://wiki.bambulab.com/en/software/bambu-studio/3rd-party-printer-profile#cloud-user-presets-limit");
return false;
}},
NotificationData{NotificationType::UndoDesktopIntegrationFail, NotificationLevel::WarningNotificationLevel, 10,
_u8L("Undo integration failed.") },
NotificationData{NotificationType::ExportOngoing, NotificationLevel::RegularNotificationLevel, 0, _u8L("Exporting.")},
@ -929,7 +887,7 @@ private:
};
public:
void set_scale(float scale = 1.0);
float m_scale = 1.0;
float m_scale = 1.0f;
};
}//namespace GUI

View file

@ -166,8 +166,14 @@ bool ObjectDataViewModelNode::valid()
assert(m_idx >= -1);
return m_idx >= -1;
}
#endif /* NDEBUG */
void ObjectDataViewModelNode::sys_color_changed()
{
m_printable_icon = m_printable == piUndef ? m_empty_bmp : create_scaled_bitmap(m_printable == piPrintable ? "check_on" : "check_off_focused");
}
void ObjectDataViewModelNode::set_icons()
{
set_action_icon(false);
@ -190,6 +196,8 @@ void ObjectDataViewModelNode::set_extruder_icon()
void ObjectDataViewModelNode::set_printable_icon(PrintIndicator printable)
{
if (m_printable == printable)
return;
m_printable = printable;
m_printable_icon = m_printable == piUndef ? m_empty_bmp :
create_scaled_bitmap(m_printable == piPrintable ? "check_on" : "check_off_focused");
@ -197,9 +205,11 @@ void ObjectDataViewModelNode::set_printable_icon(PrintIndicator printable)
void ObjectDataViewModelNode::set_action_icon(bool enable)
{
if (m_action_enable == enable)
return;
m_action_enable = enable;
auto undo = enable ? "lock_normal" : "dot";
m_action_icon_name = m_type & itPlate ? "dot" :
m_action_icon_name = m_type & itPlate ? undo :
m_type & itObject ? undo :
m_type & (itVolume | itLayer) ? undo : /*m_type & itInstance*/ "set_separate_obj";
m_action_icon = create_scaled_bitmap(m_action_icon_name); // FIXME: pass window ptr
@ -208,6 +218,8 @@ void ObjectDataViewModelNode::set_action_icon(bool enable)
// BBS
void ObjectDataViewModelNode::set_color_icon(bool enable)
{
if (m_color_enable == enable)
return;
m_color_enable = enable;
if ((m_type & itObject) && enable)
m_color_icon = create_scaled_bitmap("mmu_segmentation");
@ -217,6 +229,8 @@ void ObjectDataViewModelNode::set_color_icon(bool enable)
void ObjectDataViewModelNode::set_support_icon(bool enable)
{
if (m_support_enable == enable)
return;
m_support_enable = enable;
if ((m_type & itObject) && enable)
m_support_icon = create_scaled_bitmap("toolbar_support");
@ -226,6 +240,8 @@ void ObjectDataViewModelNode::set_support_icon(bool enable)
void ObjectDataViewModelNode::set_sinking_icon(bool enable)
{
if (m_sink_enable == enable)
return;
m_sink_enable = enable;
if ((m_type & itObject) && enable)
m_sinking_icon = create_scaled_bitmap("objlist_sinking");
@ -459,7 +475,7 @@ wxBitmap& ObjectDataViewModel::GetWarningBitmap(const std::string& warning_icon_
wxDataViewItem ObjectDataViewModel::AddPlate(PartPlate* part_plate, wxString name, bool refresh)
{
int plate_idx = part_plate ? part_plate->get_index() : -1;
wxString plate_name;
wxString plate_name = name;
if (name.empty()) {
plate_name = _L("Plate");
plate_name += wxString::Format(" %d", plate_idx + 1);
@ -1364,6 +1380,19 @@ int ObjectDataViewModel::GetIdByItem(const wxDataViewItem& item) const
return it - m_objects.begin();
}
int ObjectDataViewModel::GetPlateIdByItem(const wxDataViewItem& item) const
{
if (!item.IsOk())
return -1;
ObjectDataViewModelNode* node = static_cast<ObjectDataViewModelNode*>(item.GetID());
auto it = find(m_plates.begin(), m_plates.end(), node);
if (it == m_plates.end())
return -1;
return it - m_plates.begin();
}
int ObjectDataViewModel::GetIdByItemAndType(const wxDataViewItem& item, const ItemType type) const
{
wxASSERT(item.IsOk());
@ -1469,6 +1498,64 @@ void ObjectDataViewModel::UpdateItemNames()
ItemsChanged(changed_items);
}
void ObjectDataViewModel::assembly_name()
{
assembly_name_list.clear();
for (int i = 0; i < m_plates.size(); ++i) {
assembly_name(m_plates[i], m_plates[i]->GetName());
}
search_found_list = assembly_name_list;
}
void ObjectDataViewModel::assembly_name(ObjectDataViewModelNode* item, wxString name)
{
auto type = this->GetItemType(wxDataViewItem(item));
if (type != itPlate) {
wxString str = name + ":" + item->GetName();
assembly_name_list.push_back(std::make_pair(item, str));
}
for (size_t i = 0; i < item->GetChildCount(); ++i) {
wxString str_name = name + ":" + item->GetName();
if (type == itPlate) {
str_name = name;
}
assembly_name(item->GetNthChild(i), str_name);
}
}
void ObjectDataViewModel::search_object(wxString search_text)
{
if (search_text.empty()) {
search_found_list = assembly_name_list;
}
else {
search_found_list.clear();
search_text = search_text.MakeLower();
for (auto pair : assembly_name_list) {
wxString need_str = pair.second.AfterFirst(':');
need_str = need_str.MakeLower();
size_t pos = need_str.find(search_text);
if ( pos != wxString::npos) {
size_t len = search_text.length();
size_t before_size = pair.second.BeforeFirst(':').length();
wxString new_search_str = "<b>" + pair.second.Mid(before_size + pos + 1, len) + "</b>";
wxString new_str = pair.second.Mid(0, before_size + pos + 1) + new_search_str + pair.second.Mid(before_size + pos + len + 1, wxString::npos);
search_found_list.push_back(std::make_pair(pair.first, new_str));
}
}
}
}
void ObjectDataViewModel::sys_color_changed()
{
for (ObjectDataViewModelNode *item : m_objects) {
item->sys_color_changed();
ItemChanged(wxDataViewItem((void *) item));
}
}
// BBS: add use_obj_extruder
void ObjectDataViewModel::UpdateVolumesExtruderBitmap(wxDataViewItem obj_item, bool use_obj_extruder)
{

View file

@ -302,6 +302,7 @@ public:
bool has_warning_icon() const { return !m_warning_icon_name.empty(); }
std::string warning_icon_name() const { return m_warning_icon_name; }
bool has_lock() const { return m_has_lock; }
void sys_color_changed();
private:
friend class ObjectDataViewModel;
@ -329,6 +330,9 @@ class ObjectDataViewModel :public wxDataViewModel
ObjectDataViewModelNode* m_plate_outside;
wxDataViewCtrl* m_ctrl { nullptr };
std::vector<std::pair<ObjectDataViewModelNode*, wxString>> assembly_name_list;
std::vector<std::pair<ObjectDataViewModelNode*, wxString>> search_found_list;
public:
ObjectDataViewModel();
~ObjectDataViewModel();
@ -370,6 +374,7 @@ public:
wxDataViewItem GetItemByLayerRange(const int obj_idx, const t_layer_height_range& layer_range);
int GetItemIdByLayerRange(const int obj_idx, const t_layer_height_range& layer_range);
int GetIdByItem(const wxDataViewItem& item) const;
int GetPlateIdByItem(const wxDataViewItem& item) const;
int GetIdByItemAndType(const wxDataViewItem& item, const ItemType type) const;
int GetObjectIdByItem(const wxDataViewItem& item) const;
int GetVolumeIdByItem(const wxDataViewItem& item) const;
@ -483,6 +488,14 @@ public:
// BBS
void UpdateItemNames();
void assembly_name(ObjectDataViewModelNode* item, wxString name);
void assembly_name();
std::vector<std::pair<ObjectDataViewModelNode*, wxString>> get_assembly_name_list() { return assembly_name_list; }
void search_object(wxString search_text);
std::vector<std::pair<ObjectDataViewModelNode*, wxString>> get_found_list() { return search_found_list; }
void sys_color_changed();
private:
wxDataViewItem AddRoot(const wxDataViewItem& parent_item, const ItemType root_type);
wxDataViewItem AddInstanceRoot(const wxDataViewItem& parent_item);

View file

@ -236,26 +236,26 @@ void OptionsGroup::activate_line(Line& line)
m_use_custom_ctrl_as_parent = false;
if (line.full_width && (
line.widget != nullptr ||
!line.get_extra_widgets().empty())
) {
// BBS: new layout
const auto h_sizer = new wxBoxSizer(wxHORIZONTAL);
sizer->Add(h_sizer, 1, wxEXPAND | wxALL, wxOSX ? 0 : 15);
if (line.full_width && (
line.widget != nullptr ||
!line.get_extra_widgets().empty())
) {
// BBS: new layout
const auto h_sizer = new wxBoxSizer(wxHORIZONTAL);
sizer->Add(h_sizer, 1, wxEXPAND | wxALL, wxOSX ? 0 : 15);
if (line.widget != nullptr) {
// description lines
h_sizer->Add(line.widget(this->ctrl_parent()), 0, wxEXPAND | wxLEFT, titleWidth * wxGetApp().em_unit());
// description lines
sizer->Add(line.widget(this->ctrl_parent()), 0, wxEXPAND | wxALL, wxOSX ? 0 : 15);
return;
}
if (!line.get_extra_widgets().empty()) {
if (!line.get_extra_widgets().empty()) {
bool is_first_item = true;
for (auto extra_widget : line.get_extra_widgets()) {
h_sizer->Add(extra_widget(this->ctrl_parent()), is_first_item ? 1 : 0, wxLEFT, titleWidth * wxGetApp().em_unit());
is_first_item = false;
}
return;
}
for (auto extra_widget : line.get_extra_widgets()) {
h_sizer->Add(extra_widget(this->ctrl_parent()), is_first_item ? 1 : 0, wxLEFT, titleWidth * wxGetApp().em_unit());
is_first_item = false;
}
return;
}
}
auto option_set = line.get_options();
@ -1028,8 +1028,19 @@ boost::any ConfigOptionsGroup::get_config_value(const DynamicPrintConfig& config
ret = config.opt_int(opt_key, idx);
break;
case coEnum:
if (!config.has("first_layer_sequence_choice") && opt_key == "first_layer_sequence_choice") {
// reset to Auto value
ret = 0;
break;
}
if (!config.has("curr_bed_type") && opt_key == "curr_bed_type") {
// reset to global value
DynamicConfig& global_cfg = wxGetApp().preset_bundle->project_config;
ret = global_cfg.option("curr_bed_type")->getInt();
break;
}
ret = config.option(opt_key)->getInt();
break;
break;
// BBS
case coEnums:
ret = config.opt_int(opt_key, idx);
@ -1039,7 +1050,7 @@ boost::any ConfigOptionsGroup::get_config_value(const DynamicPrintConfig& config
break;
case coPoints:
if (opt_key == "printable_area")
ret = config.option<ConfigOptionPoints>(opt_key)->values;
ret = get_thumbnails_string(config.option<ConfigOptionPoints>(opt_key)->values);
else if (opt_key == "bed_exclude_area")
ret = get_thumbnails_string(config.option<ConfigOptionPoints>(opt_key)->values);
else if (opt_key == "thumbnails")
@ -1154,7 +1165,7 @@ boost::any ConfigOptionsGroup::get_config_value2(const DynamicPrintConfig& confi
break;
case coPoints:
if (opt_key == "printable_area")
ret = config.option<ConfigOptionPoints>(opt_key)->values;
ret = get_thumbnails_string(config.option<ConfigOptionPoints>(opt_key)->values);
else if (opt_key == "bed_exclude_area")
ret = get_thumbnails_string(config.option<ConfigOptionPoints>(opt_key)->values);
else if (opt_key == "thumbnails")

View file

@ -52,6 +52,12 @@ ParamsDialog::ParamsDialog(wxWindow * parent)
}
#else
Hide();
if (!m_editing_filament_id.empty()) {
FilamentInfomation *filament_info = new FilamentInfomation();
filament_info->filament_id = m_editing_filament_id;
wxQueueEvent(wxGetApp().plater(), new SimpleEvent(EVT_MODIFY_FILAMENT, filament_info));
m_editing_filament_id.clear();
}
#endif
wxGetApp().sidebar().finish_param_edit();
});
@ -59,13 +65,16 @@ ParamsDialog::ParamsDialog(wxWindow * parent)
//wxGetApp().UpdateDlgDarkUI(this);
}
void ParamsDialog::Popup()
void ParamsDialog::Popup(bool just_edit)
{
wxGetApp().UpdateDlgDarkUI(this);
#ifdef __WIN32__
Reparent(wxGetApp().mainframe);
#endif
Center();
if (m_panel && m_panel->get_current_tab()) {
dynamic_cast<Tab *>(m_panel->get_current_tab())->set_just_edit(just_edit);
}
Show();
}

View file

@ -11,6 +11,15 @@
namespace Slic3r {
namespace GUI {
wxDECLARE_EVENT(EVT_MODIFY_FILAMENT, SimpleEvent);
class FilamentInfomation : public wxObject
{
public:
std::string filament_id;
std::string filament_name;
};
class ParamsPanel;
class ParamsDialog : public DPIDialog
@ -20,12 +29,15 @@ public:
ParamsPanel * panel() { return m_panel; }
void Popup();
void Popup(bool just_edit = false);
void set_editing_filament_id(std::string id) { m_editing_filament_id = id; }
protected:
void on_dpi_changed(const wxRect& suggested_rect) override;
private:
std::string m_editing_filament_id;
ParamsPanel * m_panel;
wxWindowDisabler *m_winDisabler = nullptr;
};

View file

@ -392,6 +392,10 @@ void ParamsPanel::create_layout()
m_left_sizer->Add( m_tab_print, 0, wxEXPAND );
}
if (m_tab_print_plate) {
m_left_sizer->Add(m_tab_print_plate, 0, wxEXPAND);
}
if (m_tab_print_object) {
m_left_sizer->Add( m_tab_print_object, 0, wxEXPAND );
}
@ -482,6 +486,7 @@ void ParamsPanel::refresh_tabs()
}
}
if (m_top_panel) {
m_tab_print_plate = wxGetApp().get_plate_tab();
m_tab_print_object = wxGetApp().get_model_tab();
m_tab_print_part = wxGetApp().get_model_tab(true);
m_tab_print_layer = wxGetApp().get_layer_tab();
@ -558,6 +563,8 @@ void ParamsPanel::set_active_tab(wxPanel* tab)
cur_tab = (Tab*)m_tab_print_layer;
} else if (m_tab_print_object && ((TabPrintModel*) m_tab_print_object)->has_model_config()) {
cur_tab = (Tab*) m_tab_print_object;
} else if (m_tab_print_plate && ((TabPrintPlate*)m_tab_print_plate)->has_model_config()) {
cur_tab = (Tab*)m_tab_print_plate;
}
Show(cur_tab != nullptr);
wxGetApp().sidebar().show_object_list(m_mode_region->GetValue());
@ -578,6 +585,7 @@ void ParamsPanel::set_active_tab(wxPanel* tab)
{m_tab_print_object, m_staticline_print_object},
{m_tab_print_part, m_staticline_print_part},
{m_tab_print_layer, nullptr},
{m_tab_print_plate, nullptr},
{m_tab_filament, m_staticline_filament},
{m_tab_printer, m_staticline_printer}})) {
if (!t.first) continue;
@ -650,7 +658,7 @@ void ParamsPanel::msw_rescale()
((SwitchButton* )m_mode_region)->Rescale();
if (m_mode_view)
((SwitchButton* )m_mode_view)->Rescale();
for (auto tab : {m_tab_print, m_tab_print_object, m_tab_print_part, m_tab_print_layer, m_tab_filament, m_tab_printer}) {
for (auto tab : {m_tab_print, m_tab_print_plate, m_tab_print_object, m_tab_print_part, m_tab_print_layer, m_tab_filament, m_tab_printer}) {
if (tab) dynamic_cast<Tab*>(tab)->msw_rescale();
}
//((Button*)m_export_to_file)->Rescale();

View file

@ -90,6 +90,7 @@ class ParamsPanel : public wxPanel
wxStaticLine* m_staticline_print { nullptr };
//wxBoxSizer* m_print_sizer { nullptr };
wxPanel* m_tab_print { nullptr };
wxPanel* m_tab_print_plate { nullptr };
wxPanel* m_tab_print_object { nullptr };
wxStaticLine* m_staticline_print_object { nullptr };
wxPanel* m_tab_print_part { nullptr };

View file

@ -57,7 +57,15 @@ static const int PARTPLATE_ICON_GAP_Y = 5;
static const int PARTPLATE_TEXT_OFFSET_X1 = 3;
static const int PARTPLATE_TEXT_OFFSET_X2 = 1;
static const int PARTPLATE_TEXT_OFFSET_Y = 1;
static const int PARTPLATE_PLATENAME_OFFSET_Y = 10;
const float WIPE_TOWER_DEFAULT_X_POS = 165.;
const float WIPE_TOWER_DEFAULT_Y_POS = 250.; // Max y
const float I3_WIPE_TOWER_DEFAULT_X_POS = 0.;
const float I3_WIPE_TOWER_DEFAULT_Y_POS = 250.; // Max y
std::array<unsigned char, 4> PlateTextureForeground = {0x0, 0xae, 0x42, 0xff};
namespace Slic3r {
namespace GUI {
@ -270,16 +278,53 @@ PrintSequence PartPlate::get_print_seq() const
return PrintSequence::ByDefault;
}
PrintSequence PartPlate::get_real_print_seq() const
PrintSequence PartPlate::get_real_print_seq(bool* plate_same_as_global) const
{
PrintSequence global_print_seq = PrintSequence::ByDefault;
auto curr_preset_config = wxGetApp().preset_bundle->prints.get_edited_preset().config;
if (curr_preset_config.has("print_sequence"))
global_print_seq = curr_preset_config.option<ConfigOptionEnum<PrintSequence>>("print_sequence")->value;
PrintSequence curr_plate_seq = get_print_seq();
if (curr_plate_seq == PrintSequence::ByDefault) {
auto curr_preset_config = wxGetApp().preset_bundle->prints.get_edited_preset().config;
if (curr_preset_config.has("print_sequence")) curr_plate_seq = curr_preset_config.option<ConfigOptionEnum<PrintSequence>>("print_sequence")->value;
curr_plate_seq = global_print_seq;
}
if(plate_same_as_global)
*plate_same_as_global = (curr_plate_seq == global_print_seq);
return curr_plate_seq;
}
bool PartPlate::has_spiral_mode_config() const
{
std::string key = "spiral_mode";
return m_config.has(key);
}
bool PartPlate::get_spiral_vase_mode() const
{
std::string key = "spiral_mode";
if (m_config.has(key)) {
return m_config.opt_bool(key);
}
else {
DynamicPrintConfig* global_config = &wxGetApp().preset_bundle->prints.get_edited_preset().config;
if (global_config->has(key))
return global_config->opt_bool(key);
}
return false;
}
void PartPlate::set_spiral_vase_mode(bool spiral_mode, bool as_global)
{
std::string key = "spiral_mode";
if (as_global)
m_config.erase(key);
else
m_config.set_key_value(key, new ConfigOptionBool(spiral_mode));
}
bool PartPlate::valid_instance(int obj_id, int instance_id)
{
if ((obj_id >= 0) && (obj_id < m_model->objects.size()))
@ -1483,7 +1528,7 @@ std::vector<int> PartPlate::get_used_extruders()
return used_extruders;
}
Vec3d PartPlate::estimate_wipe_tower_size(const DynamicPrintConfig & config, const double w, const double d, int plate_extruder_size) const
Vec3d PartPlate::estimate_wipe_tower_size(const DynamicPrintConfig & config, const double w, const double d, int plate_extruder_size, bool use_global_objects) const
{
Vec3d wipe_tower_size;
@ -1506,7 +1551,7 @@ Vec3d PartPlate::estimate_wipe_tower_size(const DynamicPrintConfig & config, con
return wipe_tower_size;
for (int obj_idx = 0; obj_idx < m_model->objects.size(); obj_idx++) {
if (!contain_instance_totally(obj_idx, 0))
if (!use_global_objects && !contain_instance_totally(obj_idx, 0))
continue;
BoundingBoxf3 bbox = m_model->objects[obj_idx]->bounding_box();
@ -1557,6 +1602,46 @@ Vec3d PartPlate::estimate_wipe_tower_size(const DynamicPrintConfig & config, con
return wipe_tower_size;
}
arrangement::ArrangePolygon PartPlate::estimate_wipe_tower_polygon(const DynamicPrintConfig& config, int plate_index, int plate_extruder_size, bool use_global_objects) const
{
float x = dynamic_cast<const ConfigOptionFloats*>(config.option("wipe_tower_x"))->get_at(plate_index);
float y = dynamic_cast<const ConfigOptionFloats*>(config.option("wipe_tower_y"))->get_at(plate_index);
float w = dynamic_cast<const ConfigOptionFloat*>(config.option("prime_tower_width"))->value;
//float a = dynamic_cast<const ConfigOptionFloat*>(config.option("wipe_tower_rotation_angle"))->value;
float v = dynamic_cast<const ConfigOptionFloat*>(config.option("prime_volume"))->value;
Vec3d wipe_tower_size = estimate_wipe_tower_size(config, w, v, plate_extruder_size, use_global_objects);
int plate_width=m_width, plate_depth=m_depth;
float depth = wipe_tower_size(1);
float margin = WIPE_TOWER_MARGIN, wp_brim_width = 0.f;
const ConfigOption* wipe_tower_brim_width_opt = config.option("prime_tower_brim_width");
if (wipe_tower_brim_width_opt) {
wp_brim_width = wipe_tower_brim_width_opt->getFloat();
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format("arrange wipe_tower: wp_brim_width %1%") % wp_brim_width;
}
x = std::clamp(x, margin, (float)plate_width - w - margin - wp_brim_width);
y = std::clamp(y, margin, (float)plate_depth - depth - margin - wp_brim_width);
arrangement::ArrangePolygon wipe_tower_ap;
Polygon ap({
{scaled(x - wp_brim_width), scaled(y - wp_brim_width)},
{scaled(x + w + wp_brim_width), scaled(y - wp_brim_width)},
{scaled(x + w + wp_brim_width), scaled(y + depth + wp_brim_width)},
{scaled(x - wp_brim_width), scaled(y + depth + wp_brim_width)}
});
wipe_tower_ap.bed_idx = plate_index;
wipe_tower_ap.setter = NULL; // do not move wipe tower
wipe_tower_ap.poly.contour = std::move(ap);
wipe_tower_ap.translation = { scaled(0.f), scaled(0.f) };
//wipe_tower_ap.rotation = a;
wipe_tower_ap.name = "WipeTower";
wipe_tower_ap.is_virt_object = true;
wipe_tower_ap.is_wipe_tower = true;
return wipe_tower_ap;
}
bool PartPlate::operator<(PartPlate& plate) const
{
int index = plate.get_index();
@ -1587,7 +1672,7 @@ void PartPlate::clear(bool clear_sliced_result)
/* size and position related functions*/
//set position and size
void PartPlate::set_pos_and_size(Vec3d& origin, int width, int depth, int height, bool with_instance_move)
void PartPlate::set_pos_and_size(Vec3d& origin, int width, int depth, int height, bool with_instance_move, bool do_clear)
{
bool size_changed = false; //size changed means the machine changed
bool pos_changed = false;
@ -1605,7 +1690,7 @@ void PartPlate::set_pos_and_size(Vec3d& origin, int width, int depth, int height
return;
}
if (with_instance_move)
if (with_instance_move && m_model)
{
for (std::set<std::pair<int, int>>::iterator it = obj_to_instance_set.begin(); it != obj_to_instance_set.end(); ++it) {
int obj_id = it->first;
@ -1641,7 +1726,7 @@ void PartPlate::set_pos_and_size(Vec3d& origin, int width, int depth, int height
object->invalidate_bounding_box();
}
}
else
else if (do_clear)
{
clear();
}
@ -2854,6 +2939,11 @@ void PartPlateList::init()
m_plate_cols = 1;
m_current_plate = 0;
if (m_plater) {
// In GUI mode
set_default_wipe_tower_pos_for_plate(0);
}
select_plate(0);
unprintable_plate.set_index(1);
@ -2864,14 +2954,8 @@ void PartPlateList::init()
Vec3d PartPlateList::compute_origin(int i, int cols)
{
Vec3d origin;
int row, col;
row = i / cols;
col = i % cols;
origin(0) = col * (m_plate_width * (1. + LOGICAL_PART_PLATE_GAP));
origin(1) = -row * (m_plate_depth * (1. + LOGICAL_PART_PLATE_GAP));
origin(2) = 0;
Vec2d pos = compute_shape_position(i, cols);
origin = Vec3d(pos.x(), pos.y(), 0);
return origin;
}
@ -3097,6 +3181,26 @@ void PartPlateList::release_icon_textures()
}
}
void PartPlateList::set_default_wipe_tower_pos_for_plate(int plate_idx)
{
DynamicConfig & proj_cfg = wxGetApp().preset_bundle->project_config;
ConfigOptionFloats *wipe_tower_x = proj_cfg.opt<ConfigOptionFloats>("wipe_tower_x");
ConfigOptionFloats *wipe_tower_y = proj_cfg.opt<ConfigOptionFloats>("wipe_tower_y");
wipe_tower_x->values.resize(m_plate_list.size(), wipe_tower_x->values.front());
wipe_tower_y->values.resize(m_plate_list.size(), wipe_tower_y->values.front());
auto printer_structure_opt = wxGetApp().preset_bundle->printers.get_edited_preset().config.option<ConfigOptionEnum<PrinterStructure>>("printer_structure");
// set the default position, the same with print config(left top)
ConfigOptionFloat wt_x_opt(WIPE_TOWER_DEFAULT_X_POS);
ConfigOptionFloat wt_y_opt(WIPE_TOWER_DEFAULT_Y_POS);
if (printer_structure_opt && printer_structure_opt->value == PrinterStructure::psI3) {
wt_x_opt = ConfigOptionFloat(I3_WIPE_TOWER_DEFAULT_X_POS);
wt_y_opt = ConfigOptionFloat(I3_WIPE_TOWER_DEFAULT_Y_POS);
}
dynamic_cast<ConfigOptionFloats *>(proj_cfg.option("wipe_tower_x"))->set_at(&wt_x_opt, plate_idx, 0);
dynamic_cast<ConfigOptionFloats *>(proj_cfg.option("wipe_tower_y"))->set_at(&wt_y_opt, plate_idx, 0);
}
//this may be happened after machine changed
void PartPlateList::reset_size(int width, int depth, int height, bool reload_objects, bool update_shapes)
{
@ -3109,7 +3213,7 @@ void PartPlateList::reset_size(int width, int depth, int height, bool reload_obj
m_plate_width = width;
m_plate_depth = depth;
m_plate_height = height;
update_all_plates_pos_and_size(false, false);
update_all_plates_pos_and_size(false, false, true);
if (update_shapes) {
set_shapes(m_shape, m_exclude_areas, m_logo_texture_filename, m_height_to_lid, m_height_to_rod);
}
@ -3261,11 +3365,7 @@ int PartPlateList::create_plate(bool adjust_position)
// update wipe tower config
if (m_plater) {
// In GUI mode
DynamicConfig& proj_cfg = wxGetApp().preset_bundle->project_config;
ConfigOptionFloats* wipe_tower_x = proj_cfg.opt<ConfigOptionFloats>("wipe_tower_x");
ConfigOptionFloats* wipe_tower_y = proj_cfg.opt<ConfigOptionFloats>("wipe_tower_y");
wipe_tower_x->values.resize(m_plate_list.size(), wipe_tower_x->values.front());
wipe_tower_y->values.resize(m_plate_list.size(), wipe_tower_y->values.front());
set_default_wipe_tower_pos_for_plate(new_index);
}
unprintable_plate.set_index(new_index+1);
@ -3487,6 +3587,20 @@ std::vector<const GCodeProcessorResult*> PartPlateList::get_nonempty_plates_slic
return nonempty_plates_slice_result;
}
std::set<int> PartPlateList::get_extruders(bool conside_custom_gcode) const
{
int plate_count = get_plate_count();
std::set<int> extruder_ids;
for (size_t i = 0; i < plate_count; i++) {
auto plate_extruders = m_plate_list[i]->get_extruders(conside_custom_gcode);
extruder_ids.insert(plate_extruders.begin(), plate_extruders.end());
}
return extruder_ids;
}
//select plate
int PartPlateList::select_plate(int index)
{
@ -3599,7 +3713,7 @@ void PartPlateList::update_plate_cols()
return;
}
void PartPlateList::update_all_plates_pos_and_size(bool adjust_position, bool with_unprintable_move)
void PartPlateList::update_all_plates_pos_and_size(bool adjust_position, bool with_unprintable_move, bool switch_plate_type, bool do_clear)
{
Vec3d origin1, origin2;
for (unsigned int i = 0; i < (unsigned int)m_plate_list.size(); ++i)
@ -3609,7 +3723,12 @@ void PartPlateList::update_all_plates_pos_and_size(bool adjust_position, bool wi
//compute origin1 for PartPlate
origin1 = compute_origin(i, m_plate_cols);
plate->set_pos_and_size(origin1, m_plate_width, m_plate_depth, m_plate_height, adjust_position);
plate->set_pos_and_size(origin1, m_plate_width, m_plate_depth, m_plate_height, adjust_position, do_clear);
// set default wipe pos when switch plate
if (switch_plate_type && m_plater && plate->get_used_extruders().size() <= 0) {
set_default_wipe_tower_pos_for_plate(i);
}
}
origin2 = compute_origin_for_unprintable();
@ -4133,7 +4252,7 @@ bool PartPlateList::preprocess_arrange_polygon_other_locked(int obj_index, int i
arrange_polygon.col = i % m_plate_cols;
arrange_polygon.translation(X) -= scaled<double>(plate_stride_x() * arrange_polygon.col);
arrange_polygon.translation(Y) += scaled<double>(plate_stride_y() * arrange_polygon.row);
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(": obj_id %1% instance_id %2% in plate %3%, locked %4%, row %5%, col %6%\n") % obj_index % instance_index % i % locked % arrange_polygon.row % arrange_polygon.col;
//BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(": obj_id %1% instance_id %2% in plate %3%, locked %4%, row %5%, col %6%\n") % obj_index % instance_index % i % locked % arrange_polygon.row % arrange_polygon.col;
return locked;
}
}
@ -4323,11 +4442,9 @@ void PartPlateList::postprocess_arrange_polygon(arrangement::ArrangePolygon& arr
{
// outarea for large object
arrange_polygon.bed_idx = m_plate_list.size();
BoundingBox apbox = get_extents(arrange_polygon.poly);
BoundingBox apbox = get_extents(arrange_polygon.transformed_poly()); // the item may have been rotated
auto apbox_size = apbox.size();
//arrange_polygon.translation(X) = scaled<double>(0.5 * plate_stride_x());
//arrange_polygon.translation(Y) = scaled<double>(0.5 * plate_stride_y());
arrange_polygon.translation(X) = 0.5 * apbox_size[0];
arrange_polygon.translation(Y) = scaled<double>(static_cast<double>(m_plate_depth)) - 0.5 * apbox_size[1];
}
@ -4475,19 +4592,23 @@ bool PartPlateList::set_shapes(const Pointfs& shape, const Pointfs& exclude_area
is_load_bedtype_textures = false;//reload textures
calc_bounding_boxes();
auto check_texture = [](const std::string& texture) {
boost::system::error_code ec; // so the exists call does not throw (e.g. after a permission problem)
return !texture.empty() && (boost::algorithm::iends_with(texture, ".png") || boost::algorithm::iends_with(texture, ".svg")) && boost::filesystem::exists(texture, ec);
};
if (! texture_filename.empty() && ! check_texture(texture_filename)) {
BOOST_LOG_TRIVIAL(error) << "Unable to load bed texture: " << texture_filename;
}
else
m_logo_texture_filename = texture_filename;
update_logo_texture_filename(texture_filename);
return true;
}
void PartPlateList::update_logo_texture_filename(const std::string &texture_filename)
{
auto check_texture = [](const std::string &texture) {
boost::system::error_code ec; // so the exists call does not throw (e.g. after a permission problem)
return !texture.empty() && (boost::algorithm::iends_with(texture, ".png") || boost::algorithm::iends_with(texture, ".svg")) && boost::filesystem::exists(texture, ec);
};
if (!texture_filename.empty() && !check_texture(texture_filename)) {
BOOST_LOG_TRIVIAL(error) << "Unable to load bed texture: " << texture_filename;
} else
m_logo_texture_filename = texture_filename;
}
/*slice related functions*/
//update current slice context into backgroud slicing process
void PartPlateList::update_slice_context_to_current_plate(BackgroundSlicingProcess& process)
@ -4574,6 +4695,30 @@ bool PartPlateList::is_all_slice_results_ready_for_print() const
return res;
}
//check whether all plates' slice result valid for export to file
bool PartPlateList::is_all_slice_result_ready_for_export() const
{
bool res = false;
for (unsigned int i = 0; i < (unsigned int) m_plate_list.size(); ++i) {
if (!m_plate_list[i]->empty()) {
if (m_plate_list[i]->is_all_instances_unprintable()) {
continue;
}
if (!m_plate_list[i]->is_slice_result_ready_for_print()) {
return false;
}
}
if (m_plate_list[i]->is_slice_result_ready_for_print()) {
if (!m_plate_list[i]->has_printable_instances()) {
return false;
}
res = true;
}
}
return res;
}
//check whether all plates ready for slice
bool PartPlateList::is_all_plates_ready_for_slice() const
@ -4619,6 +4764,7 @@ int PartPlateList::rebuild_plates_after_deserialize(std::vector<bool>& previous_
partplate->printer_technology = this->printer_technology;
}
update_plate_cols();
update_all_plates_pos_and_size(false, false, false, false);
set_shapes(m_shape, m_exclude_areas, m_logo_texture_filename, m_height_to_lid, m_height_to_rod);
for (unsigned int i = 0; i < (unsigned int)m_plate_list.size(); ++i)
{

View file

@ -48,6 +48,15 @@ inline int compute_colum_count(int count)
return cols;
}
extern const float WIPE_TOWER_DEFAULT_X_POS;
extern const float WIPE_TOWER_DEFAULT_Y_POS; // Max y
extern const float I3_WIPE_TOWER_DEFAULT_X_POS;
extern const float I3_WIPE_TOWER_DEFAULT_Y_POS; // Max y
namespace Slic3r {
class Model;
@ -224,8 +233,11 @@ public:
// Get the real effective print sequence of current plate.
// If curr_plate's print_seq is ByDefault, use the global sequence
// @return PrintSequence::{ByLayer,ByObject}
PrintSequence get_real_print_seq() const;
PrintSequence get_real_print_seq(bool* plate_same_as_global=nullptr) const;
bool has_spiral_mode_config() const;
bool get_spiral_vase_mode() const;
void set_spiral_vase_mode(bool spiral_mode, bool as_global);
//static const int plate_x_offset = 20; //mm
//static const double plate_x_gap = 0.2;
@ -272,14 +284,16 @@ public:
Vec3d get_center_origin();
/* size and position related functions*/
//set position and size
void set_pos_and_size(Vec3d& origin, int width, int depth, int height, bool with_instance_move);
void set_pos_and_size(Vec3d& origin, int width, int depth, int height, bool with_instance_move, bool do_clear = true);
// BBS
Vec2d get_size() const { return Vec2d(m_width, m_depth); }
ModelObjectPtrs get_objects() { return m_model->objects; }
ModelInstance* get_instance(int obj_id, int instance_id);
Vec3d get_origin() { return m_origin; }
Vec3d estimate_wipe_tower_size(const DynamicPrintConfig & config, const double w, const double d, int plate_extruder_size = 0) const;
Vec3d estimate_wipe_tower_size(const DynamicPrintConfig & config, const double w, const double d, int plate_extruder_size = 0, bool use_global_objects = false) const;
arrangement::ArrangePolygon estimate_wipe_tower_polygon(const DynamicPrintConfig & config, int plate_index, int plate_extruder_size = 0, bool use_global_objects = false) const;
std::vector<int> get_extruders(bool conside_custom_gcode = false) const;
std::vector<int> get_extruders_under_cli(bool conside_custom_gcode, DynamicPrintConfig& full_config) const;
std::vector<int> get_extruders_without_support(bool conside_custom_gcode = false) const;
@ -403,6 +417,12 @@ public:
return result;
}
// check whether plate's slice result valid for export to file
bool is_slice_result_ready_for_export()
{
return is_slice_result_ready_for_print() && has_printable_instances();
}
//invalid sliced result
void update_slice_result_valid_state(bool valid = false);
@ -544,6 +564,8 @@ class PartPlateList : public ObjectBase
void generate_icon_textures();
void release_icon_textures();
void set_default_wipe_tower_pos_for_plate(int plate_idx);
friend class cereal::access;
friend class UndoRedo::StackImpl;
friend class PartPlate;
@ -664,10 +686,13 @@ public:
std::vector<const GCodeProcessorResult*> get_nonempty_plates_slice_results();
//compute the origin for printable plate with index i
Vec3d get_current_plate_origin() { return compute_origin(m_current_plate, m_plate_cols); }
Vec2d get_current_shape_position() { return compute_shape_position(m_current_plate, m_plate_cols); }
Pointfs get_exclude_area() { return m_exclude_areas; }
std::set<int> get_extruders(bool conside_custom_gcode = false) const;
//select plate
int select_plate(int index);
@ -677,7 +702,7 @@ public:
//update the plate cols due to plate count change
void update_plate_cols();
void update_all_plates_pos_and_size(bool adjust_position = true, bool with_unprintable_move = true);
void update_all_plates_pos_and_size(bool adjust_position = true, bool with_unprintable_move = true, bool switch_plate_type = false, bool do_clear = true);
//get the plate cols
int get_plate_cols() { return m_plate_cols; }
@ -757,6 +782,8 @@ public:
bool intersects(const BoundingBoxf3 &bb);
bool contains(const BoundingBoxf3 &bb);
const std::string &get_logo_texture_filename() { return m_logo_texture_filename; }
void update_logo_texture_filename(const std::string &texture_filename);
/*slice related functions*/
//update current slice context into backgroud slicing process
void update_slice_context_to_current_plate(BackgroundSlicingProcess& process);
@ -775,6 +802,7 @@ public:
bool is_all_slice_results_valid() const;
bool is_all_slice_results_ready_for_print() const;
bool is_all_plates_ready_for_slice() const;
bool is_all_slice_result_ready_for_export() const;
void print() const;
//get the all the sliced result

View file

@ -9,7 +9,6 @@
#include "GUI_Utils.hpp"
#include "Widgets/RoundedRectangle.hpp"
class wxString;
class wxTextCtrl;
class wxStaticText;
class ScalableButton;

View file

@ -5,8 +5,8 @@ namespace Slic3r { namespace GUI {
wxDEFINE_EVENT(EVT_SET_BED_TYPE_CONFIRM, wxCommandEvent);
PlateSettingsDialog::PlateSettingsDialog(wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style)
:DPIDialog(parent, id, title, pos, size, style)
PlateSettingsDialog::PlateSettingsDialog(wxWindow* parent, const wxString& title, bool only_first_layer_seq, const wxPoint& pos, const wxSize& size, long style)
:DPIDialog(parent, wxID_ANY, title, pos, size, style)
{
std::string icon_path = (boost::format("%1%/images/OrcaSlicerTitle.ico") % resources_dir()).str();
SetIcon(wxIcon(encode_path(icon_path.c_str()), wxBITMAP_TYPE_ICO));
@ -140,6 +140,18 @@ PlateSettingsDialog::PlateSettingsDialog(wxWindow* parent, wxWindowID id, const
CenterOnParent();
wxGetApp().UpdateDlgDarkUI(this);
if (only_first_layer_seq) {
for (auto item : top_sizer->GetChildren()) {
if (item->GetWindow())
item->GetWindow()->Show(false);
}
first_layer_txt->Show();
m_first_layer_print_seq_choice->Show();
m_drag_canvas->Show();
Layout();
Fit();
}
}
PlateSettingsDialog::~PlateSettingsDialog()
@ -177,6 +189,21 @@ void PlateSettingsDialog::sync_first_layer_print_seq(int selection, const std::v
}
}
void PlateSettingsDialog::sync_spiral_mode(bool spiral_mode, bool as_global)
{
if (m_spiral_mode_choice) {
if (as_global) {
m_spiral_mode_choice->SetSelection(0);
}
else {
if (spiral_mode)
m_spiral_mode_choice->SetSelection(1);
else
m_spiral_mode_choice->SetSelection(2);
}
}
}
wxString PlateSettingsDialog::to_bed_type_name(BedType bed_type) {
switch (bed_type) {
case btDefault:
@ -241,6 +268,12 @@ PlateNameEditDialog::PlateNameEditDialog(wxWindow *parent, wxWindowID id, const
auto plate_name_txt = new wxStaticText(this, wxID_ANY, _L("Plate name"));
plate_name_txt->SetFont(Label::Body_14);
m_ti_plate_name = new TextInput(this, wxString::FromDouble(0.0), "", "", wxDefaultPosition, wxSize(FromDIP(240), -1), wxTE_PROCESS_ENTER);
m_ti_plate_name->Bind(wxEVT_TEXT_ENTER, [this](wxCommandEvent &e) {
if (this->IsModal())
EndModal(wxID_YES);
else
this->Close();
});
top_sizer->Add(plate_name_txt, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT | wxALL, FromDIP(5));
top_sizer->Add(m_ti_plate_name, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, FromDIP(5));
m_ti_plate_name->GetTextCtrl()->SetMaxLength(250);
@ -263,9 +296,6 @@ PlateNameEditDialog::PlateNameEditDialog(wxWindow *parent, wxWindowID id, const
m_button_ok->SetMinSize(wxSize(FromDIP(58), FromDIP(24)));
m_button_ok->SetCornerRadius(FromDIP(12));
m_button_ok->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent &e) {
wxCommandEvent evt(EVT_SET_BED_TYPE_CONFIRM, GetId());
e.SetEventObject(this);
GetEventHandler()->ProcessEvent(evt);
if (this->IsModal())
EndModal(wxID_YES);
else
@ -313,6 +343,10 @@ void PlateNameEditDialog::on_dpi_changed(const wxRect &suggested_rect)
wxString PlateNameEditDialog::get_plate_name() const { return m_ti_plate_name->GetTextCtrl()->GetValue(); }
void PlateNameEditDialog::set_plate_name(const wxString &name) { m_ti_plate_name->GetTextCtrl()->SetValue(name); }
void PlateNameEditDialog::set_plate_name(const wxString &name) {
m_ti_plate_name->GetTextCtrl()->SetValue(name);
m_ti_plate_name->GetTextCtrl()->SetFocus();
m_ti_plate_name->GetTextCtrl()->SetInsertionPointEnd();
}
}} // namespace Slic3r::GUI

View file

@ -22,8 +22,8 @@ public:
};
PlateSettingsDialog(
wxWindow* parent,
wxWindowID id = wxID_ANY,
const wxString& title = wxEmptyString,
bool only_first_layer_seq = false,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxCLOSE_BOX | wxCAPTION
@ -33,6 +33,7 @@ public:
void sync_bed_type(BedType type);
void sync_print_seq(int print_seq = 0);
void sync_first_layer_print_seq(int selection, const std::vector<int>& seq = std::vector<int>());
void sync_spiral_mode(bool spiral_mode, bool as_global);
wxString to_bed_type_name(BedType bed_type);
wxString to_print_sequence_name(PrintSequence print_seq);
void on_dpi_changed(const wxRect& suggested_rect) override;
@ -63,11 +64,23 @@ public:
std::vector<int> get_first_layer_print_seq();
int get_spiral_mode_choice() {
int choice = 0;
if (m_spiral_mode_choice != nullptr)
choice = m_spiral_mode_choice->GetSelection();
return choice;
};
bool get_spiral_mode(){
return false;
}
protected:
DragCanvas* m_drag_canvas;
ComboBox* m_first_layer_print_seq_choice { nullptr };
ComboBox* m_print_seq_choice { nullptr };
ComboBox* m_bed_type_choice { nullptr };
ComboBox* m_spiral_mode_choice { nullptr };
Button* m_button_ok;
Button* m_button_cancel;
TextInput *m_ti_plate_name;

Some files were not shown because too many files have changed in this diff Show more