From 2ac3ef78c32b6a367f0d341b6bffcb14e0000732 Mon Sep 17 00:00:00 2001 From: Tyler Gibson Date: Wed, 29 Nov 2017 01:09:42 -0800 Subject: [PATCH 01/50] Adding support for Malyan M200, Monoprice Select Mini V1 & V2, renaming Malyan M180 for consistency. --- .../{m180.def.json => malyan_m180.def.json} | 1 + resources/definitions/malyan_m200.def.json | 90 ++++++++++++++++++ .../monoprice_select_mini_v1.def.json | 18 ++++ .../monoprice_select_mini_v2.def.json | 22 +++++ resources/meshes/malyan_m200_platform.stl | Bin 0 -> 29184 bytes .../malyan_m200/malyan_m200_0.04375.inst.cfg | 22 +++++ .../malyan_m200/malyan_m200_0.0875.inst.cfg | 22 +++++ .../malyan_m200/malyan_m200_0.13125.inst.cfg | 22 +++++ .../malyan_m200/malyan_m200_0.175.inst.cfg | 23 +++++ .../malyan_m200/malyan_m200_0.21875.inst.cfg | 22 +++++ .../malyan_m200/malyan_m200_0.2625.inst.cfg | 22 +++++ .../malyan_m200/malyan_m200_0.30625.inst.cfg | 22 +++++ .../malyan_m200/malyan_m200_0.35.inst.cfg | 23 +++++ resources/variants/malyan_m200_0.15.inst.cfg | 18 ++++ resources/variants/malyan_m200_0.25.inst.cfg | 18 ++++ resources/variants/malyan_m200_0.30.inst.cfg | 18 ++++ resources/variants/malyan_m200_0.35.inst.cfg | 18 ++++ resources/variants/malyan_m200_0.40.inst.cfg | 18 ++++ resources/variants/malyan_m200_0.50.inst.cfg | 18 ++++ resources/variants/malyan_m200_0.60.inst.cfg | 18 ++++ resources/variants/malyan_m200_0.80.inst.cfg | 18 ++++ resources/variants/malyan_m200_1.00.inst.cfg | 18 ++++ 22 files changed, 471 insertions(+) rename resources/definitions/{m180.def.json => malyan_m180.def.json} (98%) create mode 100644 resources/definitions/malyan_m200.def.json create mode 100644 resources/definitions/monoprice_select_mini_v1.def.json create mode 100644 resources/definitions/monoprice_select_mini_v2.def.json create mode 100644 resources/meshes/malyan_m200_platform.stl create mode 100644 resources/quality/malyan_m200/malyan_m200_0.04375.inst.cfg create mode 100644 resources/quality/malyan_m200/malyan_m200_0.0875.inst.cfg create mode 100644 resources/quality/malyan_m200/malyan_m200_0.13125.inst.cfg create mode 100644 resources/quality/malyan_m200/malyan_m200_0.175.inst.cfg create mode 100644 resources/quality/malyan_m200/malyan_m200_0.21875.inst.cfg create mode 100644 resources/quality/malyan_m200/malyan_m200_0.2625.inst.cfg create mode 100644 resources/quality/malyan_m200/malyan_m200_0.30625.inst.cfg create mode 100644 resources/quality/malyan_m200/malyan_m200_0.35.inst.cfg create mode 100644 resources/variants/malyan_m200_0.15.inst.cfg create mode 100644 resources/variants/malyan_m200_0.25.inst.cfg create mode 100644 resources/variants/malyan_m200_0.30.inst.cfg create mode 100644 resources/variants/malyan_m200_0.35.inst.cfg create mode 100644 resources/variants/malyan_m200_0.40.inst.cfg create mode 100644 resources/variants/malyan_m200_0.50.inst.cfg create mode 100644 resources/variants/malyan_m200_0.60.inst.cfg create mode 100644 resources/variants/malyan_m200_0.80.inst.cfg create mode 100644 resources/variants/malyan_m200_1.00.inst.cfg diff --git a/resources/definitions/m180.def.json b/resources/definitions/malyan_m180.def.json similarity index 98% rename from resources/definitions/m180.def.json rename to resources/definitions/malyan_m180.def.json index 71aa729b7e..5e0a6038dd 100644 --- a/resources/definitions/m180.def.json +++ b/resources/definitions/malyan_m180.def.json @@ -1,4 +1,5 @@ { + "id": "malyan_m180", "version": 2, "name": "Malyan M180", "inherits": "fdmprinter", diff --git a/resources/definitions/malyan_m200.def.json b/resources/definitions/malyan_m200.def.json new file mode 100644 index 0000000000..f19980a3b7 --- /dev/null +++ b/resources/definitions/malyan_m200.def.json @@ -0,0 +1,90 @@ +{ + "id": "malyan_m200", + "version": 2, + "name": "Malyan M200", + "inherits": "fdmprinter", + "metadata": { + "author": "Brian Corbino", + "manufacturer": "Malyan", + "category": "Other", + "file_formats": "text/x-gcode", + "platform": "malyan_m200_platform.stl", + "has_variants": true, + "has_variant_materials": false, + "has_materials": true, + "has_machine_materials": false, + "has_machine_quality": true, + "preferred_variant": "*0.4*", + "preferred_quality": "*0.175*", + "variants_name": "Nozzle size", + "supports_usb_connection": true, + "visible": true, + "first_start_actions": ["MachineSettingsAction"], + "supported_actions": ["MachineSettingsAction"] + }, + + "overrides": { + "machine_name": { "default_value": "Malyan M200" }, + "speed_print": { "default_value": 50 }, + "speed_wall_0": { "value": "round(speed_print * 0.75, 2)" }, + "speed_wall_x": { "value": "speed_print" }, + "speed_support": { "value": "speed_wall_0" }, + "speed_layer_0": { "value": "round(speed_print / 2.0, 2)" }, + "speed_travel": { "default_value": 50 }, + "speed_travel_layer_0": { "default_value": 40 }, + "speed_infill": { "value": "speed_print" }, + "speed_topbottom": {"value": "speed_print / 2"}, + + "layer_height": { "minimum_value": "0.04375", "maximum_value": "machine_nozzle_size * 0.875", "maximum_value_warning": "machine_nozzle_size * 0.48125 + 0.0875", "default_value": 0.13125 }, + "line_width": { "value": "round(machine_nozzle_size * 0.875, 2)" }, + + "material_print_temperature": { "minimum_value": "0" }, + "material_print_temperature_layer_0": { "value": "material_print_temperature + 5" }, + "material_bed_temperature": { "minimum_value": "0" }, + "material_bed_temperature_layer_0": { "value": "material_bed_temperature + 5" }, + "material_standby_temperature": { "minimum_value": "0" }, + "machine_show_variants": { "default_value": true }, + "machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" }, + "machine_start_gcode" : { + "default_value": "G21;(metric values)\nG90;(absolute positioning)\nM82;(set extruder to absolute mode)\nM107;(start with the fan off)\nG28;(Home the printer)\nG92 E0;(Reset the extruder to 0)\nG0 Z5 E5 F500;(Move up and prime the nozzle)\nG0 X-1 Z0;(Move outside the printable area)\nG1 Y60 E8 F500;(Draw a priming/wiping line to the rear)\nG1 X-1;(Move a little closer to the print area)\nG1 Y10 E16 F500;(draw more priming/wiping)\nG1 E15 F250;(Small retract)\nG92 E0;(Zero the extruder)" + }, + "machine_end_gcode" : { + "default_value": "G0 X0 Y127;(Stick out the part)\nM190 S0;(Turn off heat bed, don't wait.)\nG92 E10;(Set extruder to 10)\nG1 E7 F200;(retract 3mm)\nM104 S0;(Turn off nozzle, don't wait)\nG4 S300;(Delay 5 minutes)\nM107;(Turn off part fan)\nM84;(Turn off stepper motors.)" + }, + "machine_width": { "default_value": 120 }, + "machine_depth": { "default_value": 120 }, + "machine_height": { "default_value": 120 }, + "machine_heated_bed": { "default_value": true }, + "machine_center_is_zero": { "default_value": false }, + "material_diameter": { "value": 1.75 }, + "machine_nozzle_size": { + "default_value": 0.4, + "minimum_value": "0.15" + }, + "machine_max_feedrate_x": { "default_value": 150 }, + "machine_max_feedrate_y": { "default_value": 150 }, + "machine_max_feedrate_z": { "default_value": 1.5 }, + "machine_max_feedrate_e": { "default_value": 100 }, + "machine_max_acceleration_x": { "default_value": 800 }, + "machine_max_acceleration_y": { "default_value": 800 }, + "machine_max_acceleration_z": { "default_value": 20 }, + "machine_max_acceleration_e": { "default_value": 10000 }, + "machine_max_jerk_xy": { "default_value": 20 }, + "machine_max_jerk_z": { "default_value": 0.4 }, + "machine_max_jerk_e": { "default_value": 5}, + "adhesion_type": { "default_value": "raft" }, + "raft_margin": { "default_value": 5 }, + "raft_airgap": { "default_value": 0.2625 }, + "raft_base_thickness": { "value": "0.30625" }, + "raft_interface_thickness": { "value": "0.21875" }, + "raft_surface_layers": { "default_value": 1 }, + "skirt_line_count": { "default_value": 2}, + "brim_width" : { "default_value": 5}, + "start_layers_at_same_position": { "default_value": true}, + "retraction_combing": { "default_value": "noskin" }, + "retraction_amount" : { "default_value": 4.5}, + "retraction_speed" : { "default_value": 40}, + "coasting_enable": { "default_value": true }, + "prime_tower_enable": { "default_value": false} + } +} diff --git a/resources/definitions/monoprice_select_mini_v1.def.json b/resources/definitions/monoprice_select_mini_v1.def.json new file mode 100644 index 0000000000..0b76a26c1c --- /dev/null +++ b/resources/definitions/monoprice_select_mini_v1.def.json @@ -0,0 +1,18 @@ +{ + "id": "monoprice_select_mini_v1", + "version": 2, + "name": "Monoprice Select Mini V1", + "inherits": "malyan_m200", + "metadata": { + "author": "Brian Corbino", + "manufacturer": "Monoprice", + "category": "Other", + "file_formats": "text/x-gcode", + "quality_definition": "malyan_m200", + "visible": true + }, + + "overrides": { + "machine_name": { "default_value": "Monoprice Select Mini V1" } + } +} diff --git a/resources/definitions/monoprice_select_mini_v2.def.json b/resources/definitions/monoprice_select_mini_v2.def.json new file mode 100644 index 0000000000..33367aad88 --- /dev/null +++ b/resources/definitions/monoprice_select_mini_v2.def.json @@ -0,0 +1,22 @@ +{ + "id": "monoprice_select_mini_v2", + "version": 2, + "name": "Monoprice Select Mini V2 (E3D)", + "inherits": "malyan_m200", + "metadata": { + "author": "Brian Corbino", + "manufacturer": "Monoprice", + "category": "Other", + "file_formats": "text/x-gcode", + "quality_definition": "malyan_m200", + "visible": true + }, + + "overrides": { + "machine_name": { "default_value": "Monoprice Select Mini V2" }, + "adhesion_type": { "default_value": "brim" }, + "retraction_combing": { "default_value": "noskin" }, + "retraction_amount" : { "default_value": 2.5}, + "retraction_speed" : { "default_value": 40} + } +} diff --git a/resources/meshes/malyan_m200_platform.stl b/resources/meshes/malyan_m200_platform.stl new file mode 100644 index 0000000000000000000000000000000000000000..32b19a09114b7b3dee2ccd2da1e7fac1cb1acaec GIT binary patch literal 29184 zcmb`PZLDV1RmUG%Gan2AGPxSGRV>L=X?@{CYn?{s@m}qVBMn$zVhD{|6DfA4Wnh?r z(p#oO2b@AHh)w*U^pXOl2->7^!Xz@!@DN|HiA`*+n$$E#8`4Awf?{k5b^rG||9yVz zoafw`58f}c=A89k|Mj-_J}>(`KYPXHSG@bO+5g+$+g~M9N9Hzo+wADZZL`mB%w`vs ze~)f#e&Dp?H$o`#M@1+O`z{X4J}$51P5jZ8<#I;#XxtfL-&Lt$Ov<_|*mI1vdJnflL|+9u?Anqe zA94`UbFfP?!Zom6MJ`##SI1#nMmW1VKKAM-{^j_SI@Pyyn^Cr_TGajn3}l>ym@-@%20Ry{F3m@r!p9jwuASB+J7<{K#(~s$KG< z&wTvUJOA~jW><2=5gcbm&@TD%_}H~$t8qv+2e~tXo=}VE&9(RcZp8717mx3`Uv%u}s~p*#LQqSxGVKbM&Z&P#7OVklbIaOGr(K&Iht4=!Y7w2ggjz$i zEZM8R+gBl^<>N;5alGn{?^xI?$@cw*_Z^#vg9vI#wxt{g?GkO-UiERTLP*QUjp*aJ z;Mbn`8M8}v96N8jw8^<1L{LkzEp4v7$WY z#BGkg9$&owmzr0ST@PE5hq)d^P|IE!(dUYGiMHHwRVygpRw1P2<3{vx?Ao!_;*jh( z_CNEnCg(Vapq6CUDR&9&5^dRD^^vbaNXy3?qSf5&I%8QGrH8potYyS7^5A&<4ezQP z=fC#*=EDvbLf!6aZjYdrYaR$*S$cHpjAg~a5uD?&mJyD_h%tv}GM%w34$gL&!&*j| z!-z2l*QMclCG^=Lq-9Hic;)W6X87AbKfY&pEfQWmSi1edlRd{2f?AT*yY{M$k2$Yc z%qOkViD!YJmgL?mGpP1lg}FLUdqo7b7?UdKzaw+5kX~!Y*|omBB7!w=HOIN)>czE> z-IKi{f?C7AvR_B)7<3jr9_0x~LFVAfLapKW=s7rBa;_bY+SLeZam;70N;lN`wd8{zvh}2hh^C%-{xB3Sc#yP z<(8|3b9L^~-)i-+EDrM3T&+Y<%W`nYzH7e!nct|j)fvm;AYZNdN(8km2Z!>c=*$0R z&%ONXr51P9dRVS;blj3R*QOBk%5vh^BMzO}d-*3Thh^C%U*i}dsAV}gx?I&!r3k;Z z=kCg3*>Q+F;+R6vE6c&5S`<{}P^I?Xbx*|6$+AnnR`U^pT9$*O>%@epzJpJlc>J8- zuiUM7M+jx+aRS_CFj>EFF&JIB>%Pm)$ODczE0N2B^ILO!Lk`aPhmRrp=Cq^7) z?sH#hR&$-n*XG0#f?Ae?qjdXR`6~aL(XM4_?R@o3r4})6YVWQ@P|I@EL$>{7jZY)^ z#DmWUyhg>fJJ0wDl%7-4QburPp%&2@!85*2(7NPn39o8>97Is7JRNM$dNaGAr2x?gtcg=3P zBHMd;jPtm%c&NrizG(!tEC)x)?%*2kfm-vpLW=o=eC_(G&OX+vxvE!Z;gu1Iqg|1? zucYPr+fwAJ^J;{kmgSVI+KGzLom(81WtV)d<~4F_$riON2S?Yt6;Wp7Ru9YKu%(D&3PCN) z!J%3RRsN^z-PTu@WtV(y42}@gvK$E7JYQK$wy0$} zI5=M!QGExWI#Jg?+asuDS(a+I>x!(#p^@V_EKBR`5Y)2Va@FoRH3PUFmc>E7e0^mt z*`k)^;NbO@W;OSfWpUV2L_UR}mgV43o-_lM|LJ*2<*2@cFVECd2x?gluR26qKlI#C z?7^LJ=#@PTjxs*d`r&7mQMKEv@3s_i zOd+UcIXH%^0iIcwF>$PNkgs)njXZiZo^n#la^pzrhvSIx7;)HA#L~bdk@?|7v#e zjI6BfcSk+yI=JeYrE+3~e79GYgQKf?9}$a*v5I4rB%AUtSPJ3 z4n{D!^0^P+T6@fLApZWR))tSQyt3x% z&V9F(rv}=KxV3n5LA>Rjk5+VlT=(bS_2QxV+VjETGxFWC(B_E9iSQY*TOOh_hqZ(t zM=#5(H(ht};)SohZN9$z%*jt(a_#b>*Bz?9|H9YzFaPJ2o2&fX%h$ALq#3dI+z)oS z+FDSH=!Do!Eu!E0z5AE1x$5Sc>1hPD_PucJ^38vBs6%}F%8M8GycEw~X_ub##}zpd zwA*WKEi6Yp9^19H__@Ena{dEd|-L$+do=47&+0?2x`&WItEACmA~Y$9C4JnWbV0yXDq9i=xy?9H?_W4 zy2P^&J~-uc8EzZ!34o<6j%jGA~WV_Erm z;Q8z7`{4r}R*Wp#U=+e;jCN8Z2Znw{SDi9^fJzvqUU-Tt_;`>7WX z%rAP!XHOmb_Pr;m#q6FP;*&=YF8}k!{b#5k?K-21$;VqgMses2J-Os34=wNe&Fi~W z4RP$|86wOPE6x;xT7UV^2bWJD_&~>jH;O0uMv?C}$(P=Y?*5}YZ(ctA?7?b_?;SIu zjM~dQ&iga7)4ja4;5*hjGc*J_h_D>lEhB2aY78=RR6uF!EDK0}0LA0H!VmwPm(5!_!wEuwQA+^uR^-!5?n zZANept#|+WYp2yU*WIYjlyQ8z_oT}0c;@hk62kT9zC>%|F(a&{-84pP)cUx;^Xlgk zce`p(y1ni_<~Y~!%;8ZqM9@-3aD0%1mNLSlXvjfJ8Q~rsB4{ZiJPw8kTFMA_;t)Yg z8R705B4{Zi+-EKJ}G@gBiUsS2GIzIM_2+O*1 zB06(uJez}drxDaDS!f<=hO?#2u?o?3{sh9dq@{UKb|w4xxaQQdEUjq-y`mP;IS!t2 zcEv$U8KL=AzWWO&$Km6ODI;7DopF~)_VID#)UqtCX$1YH7SY)&BB;fl&Iot4eAn#k z$bEbq2em9qYZ^gzY7w2i;u(&4TFMBm6Y^bGFP0UPRs+YB5&ptS2(19t@^PUv!t9!B zci|h8vqMmeeA67%nvR2BQHxoa=Af3dzJ27>ay7R{P|IC8M!3Uu#(k_zPa`-wiJ+w% zxo3kR2Q6iU=aM0UmNLR~)DS^S8BuzvL>x0G`V$zA;nj6xa{{pl7k3p3B9@= zL{O`|eXV;{#h1O}89uY3rHtSiBBpCj1Up6uXCZUM+v107eu$n%L;!;uBh;rxDBvbF~ek+jT2X28f9YGQzMM`(&7r9LHEII)54wJ80TB z25n~GSjik5gLz)*M^{F~D2jLSLi^W&V)pU=D~^x6FQZ3rA4ukiQ5${P zHKH>@9p}9`k)QZQD8-?@IOFW9cfHev2wKV($iUE?e$hajeR8 z&J}CGOsiv7&kX7Y*P~qTmO8h&WCEeFX0M2#rR-Ii)moPjK}#9IIOsdk8NoB;EA#F| z?@G(H<^18DL*v=!q4N*5eKH(Hob9H)q9@ZF^om+UPje9Ax69)=m@8^Y_Ad&GBi_8K z>xq!eUq)2N6qRxxRrYwzy(`T7`owNoTK-aZdjz#CM;zQc=skBs4)X@=5e3^s( zQj6$}@O~e8#d{py`(#9!)!O|)nW@`q5b~<4CGMHvNaaqI%;7GPSF9SVnGv)_4(x

Kah*fmelOmn**YEV59%c@nVQpwBBRCG? z3dzsQ`pRYmefNr^Xvv)sJi|=WQbzC$GcEM$CoDuzE3RZ7u1{X3IjF@R%LrZLnw{0u zm8`zh9oL+BXFcLNcvUCTE;}Qx8U5vbS?9XH`mC>9C&n3iLQ6T0Vz=ClM#oW0Gn_4D z1kVr=*TJhIFEuDv#qmV2)TTWbEtxJ?&MOi1+m(oeT102BN@tY&j2MIB^D{&tJZ=(V zVXcz9)7FwKK7YHI5!6!N{3Y5nLb>v{mcADehewy>%t0-$QD;J=y*M?yLb$SH4xVu} zrKOcq&#cD?=E|9t7BiCL&>7pJ7SS2OGwv93*iuH6(OG*mw4#rr8S)o#Ok*%t5cHMRZ0CYTi7Y_R1@# z{AC;*!I?uf@K;-b2;UXhn`FnH%})7zE{j%$#;Lf7-K$u`Hkp|P~_%_{KVa_^5$>wGJ;w~F5bmg ztgmiOEj?+}8GhAP zYSZSij3}OzEB&Y~wS0#><|xrNTSQMIe7`JP{HA3Z!R(gWw8+c&Xc@_I5J9bSyp67m zke27fKu0f4BRInmt!nnamrOn1{M_#o#gPzdCj9@pgOH@tw@ic;3s^;q6 zRn2WHJc$|Z>=3LV(bHbh?leN(kr6R4nYrz&R&&SX6fr%+NFm=^uKPbc}WP}TT1qQjb&x}%m``O(rQHi zcA;O-&Efmn?3KqFwIus$AVogsQ!YLQ=CjO<;L}sjiSmTc7Bj*Xl$N_sGA$VqPte`f z(z5Ja4dWOi7_DVlTFoK5=8)E^E(s2w8EO%2j$*aE4d5!{$i?T3NX`g;A?@r+iiQ;X|kM$j%-OQJKvPtO%O`KCE^ zpAl~tW~cdGGV7E%sKp9SBls;c5ww&!7%dUBlo5X3uE=?ZG<{dZJFHmS<2O2q&K!QS zEe?Jy$uC?pf?E8Za~e^`bDODSjf!9OWLIVmYQ-3gIHnQ&3X`7D!^}ai#Npouj5RTy zISdi;3|YB~K8{~mW!8s?{=02@!k99GT8wrY5my%Z7h>fhosh3Uwd zA6+f^8PGIB9RB@8)?+#jo?+GE`XQc7<;dA3%=ENZw8gF@cji#!jzg=AuTkQf@!_(j z57&>lx{r>d7SYojtp7BE{!)wR%pom5Nh=<fbC45Z$wIWszD$Z?63x_DO+X literal 0 HcmV?d00001 diff --git a/resources/quality/malyan_m200/malyan_m200_0.04375.inst.cfg b/resources/quality/malyan_m200/malyan_m200_0.04375.inst.cfg new file mode 100644 index 0000000000..c19d6f2050 --- /dev/null +++ b/resources/quality/malyan_m200/malyan_m200_0.04375.inst.cfg @@ -0,0 +1,22 @@ +[general] +version = 2 +name = M1 Quality +definition = malyan_m200 + +[metadata] +type = quality +weight = 2 +quality_type = fine +setting_version = 3 + +[values] +layer_height = 0.04375 +layer_height_0 = 0.2625 +wall_thickness = 1.05 +top_bottom_thickness = 0.72 +infill_sparse_density = 22 +speed_print = 50 +speed_layer_0 = =round(speed_print * 30 / 50) +speed_topbottom = 20 +cool_min_layer_time = 5 +cool_min_speed = 10 diff --git a/resources/quality/malyan_m200/malyan_m200_0.0875.inst.cfg b/resources/quality/malyan_m200/malyan_m200_0.0875.inst.cfg new file mode 100644 index 0000000000..519e963227 --- /dev/null +++ b/resources/quality/malyan_m200/malyan_m200_0.0875.inst.cfg @@ -0,0 +1,22 @@ +[general] +version = 2 +name = M2 Quality +definition = malyan_m200 + +[metadata] +type = quality +weight = 1 +quality_type = high +setting_version = 3 + +[values] +layer_height = 0.0875 +layer_height_0 = 0.2625 +wall_thickness = 1.05 +top_bottom_thickness = 0.72 +infill_sparse_density = 22 +speed_print = 50 +speed_layer_0 = =round(speed_print * 30 / 50) +speed_topbottom = 20 +cool_min_layer_time = 5 +cool_min_speed = 10 diff --git a/resources/quality/malyan_m200/malyan_m200_0.13125.inst.cfg b/resources/quality/malyan_m200/malyan_m200_0.13125.inst.cfg new file mode 100644 index 0000000000..732218cd79 --- /dev/null +++ b/resources/quality/malyan_m200/malyan_m200_0.13125.inst.cfg @@ -0,0 +1,22 @@ +[general] +version = 2 +name = M3 Quality +definition = malyan_m200 + +[metadata] +type = quality +weight = 0 +quality_type = normal +setting_version = 3 + +[values] +layer_height = 0.13125 +layer_height_0 = 0.2625 +wall_thickness = 1.05 +top_bottom_thickness = 0.72 +infill_sparse_density = 22 +speed_print = 50 +speed_layer_0 = =round(speed_print * 30 / 50) +speed_topbottom = 20 +cool_min_layer_time = 5 +cool_min_speed = 10 diff --git a/resources/quality/malyan_m200/malyan_m200_0.175.inst.cfg b/resources/quality/malyan_m200/malyan_m200_0.175.inst.cfg new file mode 100644 index 0000000000..f27e1ff900 --- /dev/null +++ b/resources/quality/malyan_m200/malyan_m200_0.175.inst.cfg @@ -0,0 +1,23 @@ +[general] +version = 2 +name = M4 Quality +definition = malyan_m200 + +[metadata] +type = quality +weight = -1 +quality_type = fast +global_quality = true +setting_version = 3 + +[values] +layer_height = 0.175 +layer_height_0 = 0.2625 +wall_thickness = 1.05 +top_bottom_thickness = 0.72 +infill_sparse_density = 22 +speed_print = 50 +speed_layer_0 = =round(speed_print * 30 / 50) +speed_topbottom = 20 +cool_min_layer_time = 5 +cool_min_speed = 10 diff --git a/resources/quality/malyan_m200/malyan_m200_0.21875.inst.cfg b/resources/quality/malyan_m200/malyan_m200_0.21875.inst.cfg new file mode 100644 index 0000000000..3ff3b562b2 --- /dev/null +++ b/resources/quality/malyan_m200/malyan_m200_0.21875.inst.cfg @@ -0,0 +1,22 @@ +[general] +version = 2 +name = M5 Quality +definition = malyan_m200 + +[metadata] +type = quality +weight = -2 +quality_type = faster +setting_version = 3 + +[values] +layer_height = 0.21875 +layer_height_0 = 0.2625 +wall_thickness = 1.05 +top_bottom_thickness = 0.72 +infill_sparse_density = 22 +speed_print = 50 +speed_layer_0 = =round(speed_print * 30 / 50) +speed_topbottom = 20 +cool_min_layer_time = 5 +cool_min_speed = 10 diff --git a/resources/quality/malyan_m200/malyan_m200_0.2625.inst.cfg b/resources/quality/malyan_m200/malyan_m200_0.2625.inst.cfg new file mode 100644 index 0000000000..881f70521f --- /dev/null +++ b/resources/quality/malyan_m200/malyan_m200_0.2625.inst.cfg @@ -0,0 +1,22 @@ +[general] +version = 2 +name = M6 Quality +definition = malyan_m200 + +[metadata] +type = quality +weight = -3 +quality_type = draft +setting_version = 3 + +[values] +layer_height = 0.2625 +layer_height_0 = 0.2625 +wall_thickness = 1.05 +top_bottom_thickness = 0.72 +infill_sparse_density = 22 +speed_print = 50 +speed_layer_0 = =round(speed_print * 30 / 50) +speed_topbottom = 20 +cool_min_layer_time = 5 +cool_min_speed = 10 diff --git a/resources/quality/malyan_m200/malyan_m200_0.30625.inst.cfg b/resources/quality/malyan_m200/malyan_m200_0.30625.inst.cfg new file mode 100644 index 0000000000..5d81cbc259 --- /dev/null +++ b/resources/quality/malyan_m200/malyan_m200_0.30625.inst.cfg @@ -0,0 +1,22 @@ +[general] +version = 2 +name = M7 Quality +definition = malyan_m200 + +[metadata] +type = quality +weight = -4 +quality_type = turbo +setting_version = 3 + +[values] +layer_height = 0.30625 +layer_height_0 = 0.30625 +wall_thickness = 1.05 +top_bottom_thickness = 0.72 +infill_sparse_density = 22 +speed_print = 50 +speed_layer_0 = =round(speed_print * 30 / 50) +speed_topbottom = 20 +cool_min_layer_time = 5 +cool_min_speed = 10 diff --git a/resources/quality/malyan_m200/malyan_m200_0.35.inst.cfg b/resources/quality/malyan_m200/malyan_m200_0.35.inst.cfg new file mode 100644 index 0000000000..74294ea6f6 --- /dev/null +++ b/resources/quality/malyan_m200/malyan_m200_0.35.inst.cfg @@ -0,0 +1,23 @@ +[general] +version = 2 +name = M8 Quality +definition = malyan_m200 + +[metadata] +type = quality +weight = -5 +quality_type = hyper +global_quality = true +setting_version = 3 + +[values] +layer_height = 0.35 +layer_height_0 = 0.35 +wall_thickness = 1.05 +top_bottom_thickness = 0.72 +infill_sparse_density = 22 +speed_print = 50 +speed_layer_0 = =round(speed_print * 30 / 50) +speed_topbottom = 20 +cool_min_layer_time = 5 +cool_min_speed = 10 diff --git a/resources/variants/malyan_m200_0.15.inst.cfg b/resources/variants/malyan_m200_0.15.inst.cfg new file mode 100644 index 0000000000..808b8755ea --- /dev/null +++ b/resources/variants/malyan_m200_0.15.inst.cfg @@ -0,0 +1,18 @@ +[general] +name = 0.15 mm +version = 2 +definition = malyan_m200 + +[metadata] +author = Brian Corbino +type = variant +setting_version = 3 + +[values] +machine_nozzle_size = 0.15 +machine_nozzle_tip_outer_diameter = 0.8 +coasting_volume = 0.05 +coasting_min_volume = =round(coasting_volume * 4,2) +speed_wall = =round(speed_print / 1.2, 1) +speed_wall_0 = =1 if speed_wall < 5 else (speed_wall - 5) +speed_topbottom = =round(speed_print / 1.5, 1) diff --git a/resources/variants/malyan_m200_0.25.inst.cfg b/resources/variants/malyan_m200_0.25.inst.cfg new file mode 100644 index 0000000000..3847f5c617 --- /dev/null +++ b/resources/variants/malyan_m200_0.25.inst.cfg @@ -0,0 +1,18 @@ +[general] +name = 0.25 mm +version = 2 +definition = malyan_m200 + +[metadata] +author = Brian Corbino +type = variant +setting_version = 3 + +[values] +machine_nozzle_size = 0.25 +machine_nozzle_tip_outer_diameter = 0.8 +coasting_volume = 0.1 +coasting_min_volume = =round(coasting_volume * 4,2) +speed_wall = =round(speed_print / 1.2, 1) +speed_wall_0 = =1 if speed_wall < 5 else (speed_wall - 5) +speed_topbottom = =round(speed_print / 1.5, 1) diff --git a/resources/variants/malyan_m200_0.30.inst.cfg b/resources/variants/malyan_m200_0.30.inst.cfg new file mode 100644 index 0000000000..fee8aae40f --- /dev/null +++ b/resources/variants/malyan_m200_0.30.inst.cfg @@ -0,0 +1,18 @@ +[general] +name = 0.30 mm +version = 2 +definition = malyan_m200 + +[metadata] +author = Brian Corbino +type = variant +setting_version = 3 + +[values] +machine_nozzle_size = 0.30 +machine_nozzle_tip_outer_diameter = 0.8 +coasting_volume = 0.11 +coasting_min_volume = =round(coasting_volume * 4,2) +speed_wall = =round(speed_print / 1.2, 1) +speed_wall_0 = =1 if speed_wall < 5 else (speed_wall - 5) +speed_topbottom = =round(speed_print / 1.5, 1) diff --git a/resources/variants/malyan_m200_0.35.inst.cfg b/resources/variants/malyan_m200_0.35.inst.cfg new file mode 100644 index 0000000000..dcbb3ed4c0 --- /dev/null +++ b/resources/variants/malyan_m200_0.35.inst.cfg @@ -0,0 +1,18 @@ +[general] +name = 0.35 mm +version = 2 +definition = malyan_m200 + +[metadata] +author = Brian Corbino +type = variant +setting_version = 3 + +[values] +machine_nozzle_size = 0.35 +machine_nozzle_tip_outer_diameter = 0.8 +coasting_volume = 0.13 +coasting_min_volume = =round(coasting_volume * 4,2) +speed_wall = =round(speed_print / 1.2, 1) +speed_wall_0 = =1 if speed_wall < 5 else (speed_wall - 5) +speed_topbottom = =round(speed_print / 1.5, 1) diff --git a/resources/variants/malyan_m200_0.40.inst.cfg b/resources/variants/malyan_m200_0.40.inst.cfg new file mode 100644 index 0000000000..6e17dd13a6 --- /dev/null +++ b/resources/variants/malyan_m200_0.40.inst.cfg @@ -0,0 +1,18 @@ +[general] +name = 0.40 mm +version = 2 +definition = malyan_m200 + +[metadata] +author = Brian Corbino +type = variant +setting_version = 3 + +[values] +machine_nozzle_size = 0.40 +machine_nozzle_tip_outer_diameter = 1.05 +coasting_volume = 0.15 +coasting_min_volume = =round(coasting_volume * 4,2) +speed_wall = =round(speed_print / 1.25, 1) +speed_wall_0 = =1 if speed_wall < 10 else (speed_wall - 10) +speed_topbottom = =round(speed_print / 2.25, 1) diff --git a/resources/variants/malyan_m200_0.50.inst.cfg b/resources/variants/malyan_m200_0.50.inst.cfg new file mode 100644 index 0000000000..ce87def1e6 --- /dev/null +++ b/resources/variants/malyan_m200_0.50.inst.cfg @@ -0,0 +1,18 @@ +[general] +name = 0.50 mm +version = 2 +definition = malyan_m200 + +[metadata] +author = Brian Corbino +type = variant +setting_version = 3 + +[values] +machine_nozzle_size = 0.50 +machine_nozzle_tip_outer_diameter = 0.8 +coasting_volume = 0.2 +coasting_min_volume = =round(coasting_volume * 4,2) +speed_wall = =round(speed_print / 1.2, 1) +speed_wall_0 = =1 if speed_wall < 5 else (speed_wall - 5) +speed_topbottom = =round(speed_print / 1.5, 1) diff --git a/resources/variants/malyan_m200_0.60.inst.cfg b/resources/variants/malyan_m200_0.60.inst.cfg new file mode 100644 index 0000000000..0ee7c786e8 --- /dev/null +++ b/resources/variants/malyan_m200_0.60.inst.cfg @@ -0,0 +1,18 @@ +[general] +name = 0.60 mm +version = 2 +definition = malyan_m200 + +[metadata] +author = Brian Corbino +type = variant +setting_version = 3 + +[values] +machine_nozzle_size = 0.60 +machine_nozzle_tip_outer_diameter = 1.25 +coasting_volume = 0.28 +coasting_min_volume = =round(coasting_volume * 4,2) +speed_wall = =round(speed_print * 4 / 3, 1) +speed_wall_0 = =1 if speed_wall < 10 else (speed_wall - 10) +speed_topbottom = =round(speed_print / 2, 1) diff --git a/resources/variants/malyan_m200_0.80.inst.cfg b/resources/variants/malyan_m200_0.80.inst.cfg new file mode 100644 index 0000000000..54f48afdb4 --- /dev/null +++ b/resources/variants/malyan_m200_0.80.inst.cfg @@ -0,0 +1,18 @@ +[general] +name = 0.80 mm +version = 2 +definition = malyan_m200 + +[metadata] +author = Brian Corbino +type = variant +setting_version = 3 + +[values] +machine_nozzle_size = 0.80 +machine_nozzle_tip_outer_diameter = 1.35 +coasting_volume = 0.45 +coasting_min_volume = =round(coasting_volume * 4,2) +speed_wall = =round(speed_print * 4 / 3, 1) +speed_wall_0 = =1 if speed_wall < 10 else (speed_wall - 10) +speed_topbottom = =round(speed_print / 2, 1) diff --git a/resources/variants/malyan_m200_1.00.inst.cfg b/resources/variants/malyan_m200_1.00.inst.cfg new file mode 100644 index 0000000000..ce0a2d0dfb --- /dev/null +++ b/resources/variants/malyan_m200_1.00.inst.cfg @@ -0,0 +1,18 @@ +[general] +name = 1.00 mm +version = 2 +definition = malyan_m200 + +[metadata] +author = Brian Corbino +type = variant +setting_version = 3 + +[values] +machine_nozzle_size = 1.00 +machine_nozzle_tip_outer_diameter = 0.8 +coasting_volume = 0.63 +coasting_min_volume = =round(coasting_volume * 4,2) +speed_wall = =round(speed_print / 1.2, 1) +speed_wall_0 = =1 if speed_wall < 5 else (speed_wall - 5) +speed_topbottom = =round(speed_print / 1.5, 1) From 80f50dfff579b30f54eeee2205a72e735a8acf2f Mon Sep 17 00:00:00 2001 From: tylergibson Date: Wed, 13 Dec 2017 18:33:18 -0800 Subject: [PATCH 02/50] renaming variants to fix filename conflict, updating quality setting version --- resources/quality/malyan_m200/malyan_m200_0.04375.inst.cfg | 2 +- resources/quality/malyan_m200/malyan_m200_0.0875.inst.cfg | 2 +- resources/quality/malyan_m200/malyan_m200_0.13125.inst.cfg | 2 +- resources/quality/malyan_m200/malyan_m200_0.175.inst.cfg | 2 +- resources/quality/malyan_m200/malyan_m200_0.21875.inst.cfg | 2 +- resources/quality/malyan_m200/malyan_m200_0.2625.inst.cfg | 2 +- resources/quality/malyan_m200/malyan_m200_0.30625.inst.cfg | 2 +- resources/quality/malyan_m200/malyan_m200_0.35.inst.cfg | 2 +- .../{malyan_m200_0.15.inst.cfg => malyan_m200_0.15mm.inst.cfg} | 0 .../{malyan_m200_0.25.inst.cfg => malyan_m200_0.25mm.inst.cfg} | 0 .../{malyan_m200_0.30.inst.cfg => malyan_m200_0.30mm.inst.cfg} | 0 .../{malyan_m200_0.35.inst.cfg => malyan_m200_0.35mm.inst.cfg} | 0 .../{malyan_m200_0.40.inst.cfg => malyan_m200_0.40mm.inst.cfg} | 0 .../{malyan_m200_0.50.inst.cfg => malyan_m200_0.50mm.inst.cfg} | 0 .../{malyan_m200_0.60.inst.cfg => malyan_m200_0.60mm.inst.cfg} | 0 .../{malyan_m200_0.80.inst.cfg => malyan_m200_0.80mm.inst.cfg} | 0 .../{malyan_m200_1.00.inst.cfg => malyan_m200_1.00mm.inst.cfg} | 0 17 files changed, 8 insertions(+), 8 deletions(-) rename resources/variants/{malyan_m200_0.15.inst.cfg => malyan_m200_0.15mm.inst.cfg} (100%) rename resources/variants/{malyan_m200_0.25.inst.cfg => malyan_m200_0.25mm.inst.cfg} (100%) rename resources/variants/{malyan_m200_0.30.inst.cfg => malyan_m200_0.30mm.inst.cfg} (100%) rename resources/variants/{malyan_m200_0.35.inst.cfg => malyan_m200_0.35mm.inst.cfg} (100%) rename resources/variants/{malyan_m200_0.40.inst.cfg => malyan_m200_0.40mm.inst.cfg} (100%) rename resources/variants/{malyan_m200_0.50.inst.cfg => malyan_m200_0.50mm.inst.cfg} (100%) rename resources/variants/{malyan_m200_0.60.inst.cfg => malyan_m200_0.60mm.inst.cfg} (100%) rename resources/variants/{malyan_m200_0.80.inst.cfg => malyan_m200_0.80mm.inst.cfg} (100%) rename resources/variants/{malyan_m200_1.00.inst.cfg => malyan_m200_1.00mm.inst.cfg} (100%) diff --git a/resources/quality/malyan_m200/malyan_m200_0.04375.inst.cfg b/resources/quality/malyan_m200/malyan_m200_0.04375.inst.cfg index c19d6f2050..54be6ecbcc 100644 --- a/resources/quality/malyan_m200/malyan_m200_0.04375.inst.cfg +++ b/resources/quality/malyan_m200/malyan_m200_0.04375.inst.cfg @@ -7,7 +7,7 @@ definition = malyan_m200 type = quality weight = 2 quality_type = fine -setting_version = 3 +setting_version = 4 [values] layer_height = 0.04375 diff --git a/resources/quality/malyan_m200/malyan_m200_0.0875.inst.cfg b/resources/quality/malyan_m200/malyan_m200_0.0875.inst.cfg index 519e963227..568dd796f3 100644 --- a/resources/quality/malyan_m200/malyan_m200_0.0875.inst.cfg +++ b/resources/quality/malyan_m200/malyan_m200_0.0875.inst.cfg @@ -7,7 +7,7 @@ definition = malyan_m200 type = quality weight = 1 quality_type = high -setting_version = 3 +setting_version = 4 [values] layer_height = 0.0875 diff --git a/resources/quality/malyan_m200/malyan_m200_0.13125.inst.cfg b/resources/quality/malyan_m200/malyan_m200_0.13125.inst.cfg index 732218cd79..1dc436502b 100644 --- a/resources/quality/malyan_m200/malyan_m200_0.13125.inst.cfg +++ b/resources/quality/malyan_m200/malyan_m200_0.13125.inst.cfg @@ -7,7 +7,7 @@ definition = malyan_m200 type = quality weight = 0 quality_type = normal -setting_version = 3 +setting_version = 4 [values] layer_height = 0.13125 diff --git a/resources/quality/malyan_m200/malyan_m200_0.175.inst.cfg b/resources/quality/malyan_m200/malyan_m200_0.175.inst.cfg index f27e1ff900..314a8acd83 100644 --- a/resources/quality/malyan_m200/malyan_m200_0.175.inst.cfg +++ b/resources/quality/malyan_m200/malyan_m200_0.175.inst.cfg @@ -8,7 +8,7 @@ type = quality weight = -1 quality_type = fast global_quality = true -setting_version = 3 +setting_version = 4 [values] layer_height = 0.175 diff --git a/resources/quality/malyan_m200/malyan_m200_0.21875.inst.cfg b/resources/quality/malyan_m200/malyan_m200_0.21875.inst.cfg index 3ff3b562b2..a7fedb7e04 100644 --- a/resources/quality/malyan_m200/malyan_m200_0.21875.inst.cfg +++ b/resources/quality/malyan_m200/malyan_m200_0.21875.inst.cfg @@ -7,7 +7,7 @@ definition = malyan_m200 type = quality weight = -2 quality_type = faster -setting_version = 3 +setting_version = 4 [values] layer_height = 0.21875 diff --git a/resources/quality/malyan_m200/malyan_m200_0.2625.inst.cfg b/resources/quality/malyan_m200/malyan_m200_0.2625.inst.cfg index 881f70521f..441abc3070 100644 --- a/resources/quality/malyan_m200/malyan_m200_0.2625.inst.cfg +++ b/resources/quality/malyan_m200/malyan_m200_0.2625.inst.cfg @@ -7,7 +7,7 @@ definition = malyan_m200 type = quality weight = -3 quality_type = draft -setting_version = 3 +setting_version = 4 [values] layer_height = 0.2625 diff --git a/resources/quality/malyan_m200/malyan_m200_0.30625.inst.cfg b/resources/quality/malyan_m200/malyan_m200_0.30625.inst.cfg index 5d81cbc259..2588838174 100644 --- a/resources/quality/malyan_m200/malyan_m200_0.30625.inst.cfg +++ b/resources/quality/malyan_m200/malyan_m200_0.30625.inst.cfg @@ -7,7 +7,7 @@ definition = malyan_m200 type = quality weight = -4 quality_type = turbo -setting_version = 3 +setting_version = 4 [values] layer_height = 0.30625 diff --git a/resources/quality/malyan_m200/malyan_m200_0.35.inst.cfg b/resources/quality/malyan_m200/malyan_m200_0.35.inst.cfg index 74294ea6f6..800b6104d9 100644 --- a/resources/quality/malyan_m200/malyan_m200_0.35.inst.cfg +++ b/resources/quality/malyan_m200/malyan_m200_0.35.inst.cfg @@ -8,7 +8,7 @@ type = quality weight = -5 quality_type = hyper global_quality = true -setting_version = 3 +setting_version = 4 [values] layer_height = 0.35 diff --git a/resources/variants/malyan_m200_0.15.inst.cfg b/resources/variants/malyan_m200_0.15mm.inst.cfg similarity index 100% rename from resources/variants/malyan_m200_0.15.inst.cfg rename to resources/variants/malyan_m200_0.15mm.inst.cfg diff --git a/resources/variants/malyan_m200_0.25.inst.cfg b/resources/variants/malyan_m200_0.25mm.inst.cfg similarity index 100% rename from resources/variants/malyan_m200_0.25.inst.cfg rename to resources/variants/malyan_m200_0.25mm.inst.cfg diff --git a/resources/variants/malyan_m200_0.30.inst.cfg b/resources/variants/malyan_m200_0.30mm.inst.cfg similarity index 100% rename from resources/variants/malyan_m200_0.30.inst.cfg rename to resources/variants/malyan_m200_0.30mm.inst.cfg diff --git a/resources/variants/malyan_m200_0.35.inst.cfg b/resources/variants/malyan_m200_0.35mm.inst.cfg similarity index 100% rename from resources/variants/malyan_m200_0.35.inst.cfg rename to resources/variants/malyan_m200_0.35mm.inst.cfg diff --git a/resources/variants/malyan_m200_0.40.inst.cfg b/resources/variants/malyan_m200_0.40mm.inst.cfg similarity index 100% rename from resources/variants/malyan_m200_0.40.inst.cfg rename to resources/variants/malyan_m200_0.40mm.inst.cfg diff --git a/resources/variants/malyan_m200_0.50.inst.cfg b/resources/variants/malyan_m200_0.50mm.inst.cfg similarity index 100% rename from resources/variants/malyan_m200_0.50.inst.cfg rename to resources/variants/malyan_m200_0.50mm.inst.cfg diff --git a/resources/variants/malyan_m200_0.60.inst.cfg b/resources/variants/malyan_m200_0.60mm.inst.cfg similarity index 100% rename from resources/variants/malyan_m200_0.60.inst.cfg rename to resources/variants/malyan_m200_0.60mm.inst.cfg diff --git a/resources/variants/malyan_m200_0.80.inst.cfg b/resources/variants/malyan_m200_0.80mm.inst.cfg similarity index 100% rename from resources/variants/malyan_m200_0.80.inst.cfg rename to resources/variants/malyan_m200_0.80mm.inst.cfg diff --git a/resources/variants/malyan_m200_1.00.inst.cfg b/resources/variants/malyan_m200_1.00mm.inst.cfg similarity index 100% rename from resources/variants/malyan_m200_1.00.inst.cfg rename to resources/variants/malyan_m200_1.00mm.inst.cfg From 93a3054af0582d0d6230f9d578161464ee64ba02 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 19 Dec 2017 10:38:36 +0100 Subject: [PATCH 03/50] Round layer heights to 2 decimals More difficult than I expected actually... Contributes to issue CURA-4655. --- resources/qml/SidebarSimple.qml | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/resources/qml/SidebarSimple.qml b/resources/qml/SidebarSimple.qml index 62cf6f9d34..76d8bb32df 100644 --- a/resources/qml/SidebarSimple.qml +++ b/resources/qml/SidebarSimple.qml @@ -183,12 +183,22 @@ Item text: { var result = "" - if(Cura.MachineManager.activeMachine != null){ - - var result = Cura.ProfilesModel.getItem(index).layer_height_without_unit + if(Cura.MachineManager.activeMachine != null) + { + result = Cura.ProfilesModel.getItem(index).layer_height_without_unit if(result == undefined) - result = "" + { + result = ""; + } + else + { + result = Number(Math.round(result + "e+2") + "e-2"); //Round to 2 decimals. Javascript makes this difficult... + if (result == undefined || result != result) //Parse failure. + { + result = ""; + } + } } return result } From 7ad15c7dd2771bdf1815ec78126b58ae4071348d Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Fri, 5 Jan 2018 17:25:04 +0100 Subject: [PATCH 04/50] Allow adding support-specific settings for support meshes in Per Model Settings --- .../PerObjectSettingsPanel.qml | 38 ++++++++++++++++--- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml b/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml index 5bdb6d4cb0..b4e7a46e00 100644 --- a/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml +++ b/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml @@ -18,6 +18,9 @@ Item { width: childrenRect.width; height: childrenRect.height; + property var all_categories_except_support: [ "machine_settings", "resolution", "shell", "infill", "material", "speed", + "travel", "cooling", "platform_adhesion", "dual", "meshfix", "blackmagic", "experimental"] + Column { id: items @@ -106,7 +109,7 @@ Item { id: currentSettings property int maximumHeight: 200 * screenScaleFactor height: Math.min(contents.count * (UM.Theme.getSize("section").height + UM.Theme.getSize("default_lining").height), maximumHeight) - visible: ["support_mesh", "anti_overhang_mesh"].indexOf(meshTypeSelection.model.get(meshTypeSelection.currentIndex).type) == -1 + visible: meshTypeSelection.model.get(meshTypeSelection.currentIndex).type != "anti_overhang_mesh" ScrollView { @@ -124,7 +127,15 @@ Item { id: addedSettingsModel; containerId: Cura.MachineManager.activeDefinitionId expanded: [ "*" ] - exclude: [ "support_mesh", "anti_overhang_mesh", "cutting_mesh", "infill_mesh" ] + exclude: { + var excluded_settings = [ "support_mesh", "anti_overhang_mesh", "cutting_mesh", "infill_mesh" ]; + + if(meshTypeSelection.model.get(meshTypeSelection.currentIndex).type == "support_mesh") + { + excluded_settings = excluded_settings.concat(base.all_categories_except_support); + } + return excluded_settings; + } visibilityHandler: Cura.PerObjectSettingVisibilityHandler { @@ -306,7 +317,18 @@ Item { } } - onClicked: settingPickDialog.visible = true; + onClicked: + { + settingPickDialog.visible = true; + if (meshTypeSelection.model.get(meshTypeSelection.currentIndex).type == "support_mesh") + { + settingPickDialog.additional_excluded_settings = base.all_categories_except_support; + } + else + { + settingPickDialog.additional_excluded_settings = [] + } + } } } @@ -315,9 +337,10 @@ Item { id: settingPickDialog title: catalog.i18nc("@title:window", "Select Settings to Customize for this model") - width: screenScaleFactor * 360; + width: screenScaleFactor * 360 property string labelFilter: "" + property var additional_excluded_settings onVisibilityChanged: { @@ -394,7 +417,12 @@ Item { } visibilityHandler: UM.SettingPreferenceVisibilityHandler {} expanded: [ "*" ] - exclude: [ "machine_settings", "command_line_settings", "support_mesh", "anti_overhang_mesh", "cutting_mesh", "infill_mesh" ] + exclude: + { + var excluded_settings = [ "machine_settings", "command_line_settings", "support_mesh", "anti_overhang_mesh", "cutting_mesh", "infill_mesh" ]; + excluded_settings = excluded_settings.concat(settingPickDialog.additional_excluded_settings); + return excluded_settings; + } } delegate:Loader { From 8bd6afad1fe5a5dc0a1de8b2ee5bbcc4deb4d158 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Fri, 5 Jan 2018 18:33:05 +0100 Subject: [PATCH 05/50] Render support meshes with a vertical stripe... ...so they are easier to tell apart from normal meshes, especially for single extrusion printers --- plugins/SolidView/SolidView.py | 16 ++++++++++++++++ resources/shaders/striped.shader | 14 +++++++++++--- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/plugins/SolidView/SolidView.py b/plugins/SolidView/SolidView.py index e156e655ce..50ff2864b7 100644 --- a/plugins/SolidView/SolidView.py +++ b/plugins/SolidView/SolidView.py @@ -28,6 +28,7 @@ class SolidView(View): self._enabled_shader = None self._disabled_shader = None self._non_printing_shader = None + self._support_mesh_shader = None self._extruders_model = ExtrudersModel() self._theme = None @@ -54,6 +55,11 @@ class SolidView(View): self._non_printing_shader.setUniformValue("u_diffuseColor", Color(*self._theme.getColor("model_non_printing").getRgb())) self._non_printing_shader.setUniformValue("u_opacity", 0.6) + if not self._support_mesh_shader: + self._support_mesh_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "striped.shader")) + self._support_mesh_shader.setUniformValue("u_vertical_stripes", True) + self._support_mesh_shader.setUniformValue("u_width", 5.0) + global_container_stack = Application.getInstance().getGlobalContainerStack() if global_container_stack: support_extruder_nr = global_container_stack.getProperty("support_extruder_nr", "value") @@ -117,6 +123,16 @@ class SolidView(View): renderer.queueNode(node, shader = self._non_printing_shader, transparent = True) elif getattr(node, "_outside_buildarea", False): renderer.queueNode(node, shader = self._disabled_shader) + elif per_mesh_stack and per_mesh_stack.getProperty("support_mesh", "value"): + # Render support meshes with a vertical stripe that is darker + shade_factor = 0.6 + uniforms["diffuse_color_2"] = [ + uniforms["diffuse_color"][0] * shade_factor, + uniforms["diffuse_color"][1] * shade_factor, + uniforms["diffuse_color"][2] * shade_factor, + 1.0 + ] + renderer.queueNode(node, shader = self._support_mesh_shader, uniforms = uniforms) else: renderer.queueNode(node, shader = self._enabled_shader, uniforms = uniforms) if node.callDecoration("isGroup") and Selection.isSelected(node): diff --git a/resources/shaders/striped.shader b/resources/shaders/striped.shader index ce7d14e39e..7cf5a62c3f 100644 --- a/resources/shaders/striped.shader +++ b/resources/shaders/striped.shader @@ -32,6 +32,7 @@ fragment = uniform highp vec3 u_viewPosition; uniform mediump float u_width; + uniform mediump bool u_vertical_stripes; varying highp vec3 v_position; varying highp vec3 v_vertex; @@ -40,7 +41,9 @@ fragment = void main() { mediump vec4 finalColor = vec4(0.0); - mediump vec4 diffuseColor = (mod((-v_position.x + v_position.y), u_width) < (u_width / 2.)) ? u_diffuseColor1 : u_diffuseColor2; + mediump vec4 diffuseColor = u_vertical_stripes ? + (((mod(v_vertex.x, u_width) < (u_width / 2.)) ^^ (mod(v_vertex.z, u_width) < (u_width / 2.))) ? u_diffuseColor1 : u_diffuseColor2) : + ((mod((-v_position.x + v_position.y), u_width) < (u_width / 2.)) ? u_diffuseColor1 : u_diffuseColor2); /* Ambient Component */ finalColor += u_ambientColor; @@ -98,6 +101,7 @@ fragment41core = uniform highp vec3 u_viewPosition; uniform mediump float u_width; + uniform mediump bool u_vertical_stripes; in highp vec3 v_position; in highp vec3 v_vertex; @@ -108,7 +112,9 @@ fragment41core = void main() { mediump vec4 finalColor = vec4(0.0); - mediump vec4 diffuseColor = (mod((-v_position.x + v_position.y), u_width) < (u_width / 2.)) ? u_diffuseColor1 : u_diffuseColor2; + mediump vec4 diffuseColor = u_vertical_stripes ? + (((mod(v_vertex.x, u_width) < (u_width / 2.)) ^^ (mod(v_vertex.z, u_width) < (u_width / 2.))) ? u_diffuseColor1 : u_diffuseColor2) : + ((mod((-v_position.x + v_position.y), u_width) < (u_width / 2.)) ? u_diffuseColor1 : u_diffuseColor2); /* Ambient Component */ finalColor += u_ambientColor; @@ -138,6 +144,7 @@ u_diffuseColor2 = [0.5, 0.5, 0.5, 1.0] u_specularColor = [0.4, 0.4, 0.4, 1.0] u_shininess = 20.0 u_width = 5.0 +u_vertical_stripes = 0 [bindings] u_modelMatrix = model_matrix @@ -145,7 +152,8 @@ u_viewProjectionMatrix = view_projection_matrix u_normalMatrix = normal_matrix u_viewPosition = view_position u_lightPosition = light_0_position -u_diffuseColor = diffuse_color +u_diffuseColor1 = diffuse_color +u_diffuseColor2 = diffuse_color_2 [attributes] a_vertex = vertex From fbe128bbb75bb52f4fe9a2234c22de57687b7512 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Fri, 5 Jan 2018 21:38:54 +0100 Subject: [PATCH 06/50] Hide options for Support, Anti overhang, etc Mesh if their settings are disabled --- .../PerObjectSettingsPanel.qml | 50 ++++++++++++++++--- 1 file changed, 43 insertions(+), 7 deletions(-) diff --git a/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml b/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml index b4e7a46e00..a38112724e 100644 --- a/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml +++ b/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml @@ -42,6 +42,13 @@ Item { verticalAlignment: Text.AlignVCenter } + UM.SettingPropertyProvider + { + id: meshTypePropertyProvider + containerStackId: Cura.MachineManager.activeMachineId + watchedProperties: [ "enabled" ] + } + ComboBox { id: meshTypeSelection @@ -52,36 +59,55 @@ Item { model: ListModel { id: meshTypeModel - Component.onCompleted: + Component.onCompleted: meshTypeSelection.populateModel() + } + + function populateModel() + { + meshTypeModel.append({ + type: "", + text: catalog.i18nc("@label", "Normal model") + }); + meshTypePropertyProvider.key = "support_mesh"; + if(meshTypePropertyProvider.properties.enabled == "True") { - meshTypeModel.append({ - type: "", - text: catalog.i18nc("@label", "Normal model") - }); meshTypeModel.append({ type: "support_mesh", text: catalog.i18nc("@label", "Print as support") }); + } + meshTypePropertyProvider.key = "anti_overhang_mesh"; + if(meshTypePropertyProvider.properties.enabled == "True") + { meshTypeModel.append({ type: "anti_overhang_mesh", text: catalog.i18nc("@label", "Don't support overlap with other models") }); + } + meshTypePropertyProvider.key = "cutting_mesh"; + if(meshTypePropertyProvider.properties.enabled == "True") + { meshTypeModel.append({ type: "cutting_mesh", text: catalog.i18nc("@label", "Modify settings for overlap with other models") }); + } + meshTypePropertyProvider.key = "infill_mesh"; + if(meshTypePropertyProvider.properties.enabled == "True") + { meshTypeModel.append({ type: "infill_mesh", text: catalog.i18nc("@label", "Modify settings for infill of other models") }); - - meshTypeSelection.updateCurrentIndex(); } + + meshTypeSelection.updateCurrentIndex(); } function updateCurrentIndex() { var mesh_type = UM.ActiveTool.properties.getValue("MeshType"); + meshTypeSelection.currentIndex = -1; for(var index=0; index < meshTypeSelection.model.count; index++) { if(meshTypeSelection.model.get(index).type == mesh_type) @@ -94,6 +120,16 @@ Item { } } + Connections + { + target: Cura.MachineManager + onGlobalContainerChanged: + { + meshTypeSelection.model.clear(); + meshTypeSelection.populateModel(); + } + } + Connections { target: UM.Selection From 8dd5b166f439b5d0f2d5282baea468134343f576 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Sat, 6 Jan 2018 22:46:59 +0100 Subject: [PATCH 07/50] Move 'Drop Down Support Mesh" to "Support" section... ... so it can be added as a per model setting for Support Meshes --- resources/definitions/fdmprinter.def.json | 24 +++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 6eef6b1e9b..08c8b75869 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -4233,6 +4233,18 @@ "limit_to_extruder": "support_infill_extruder_nr", "enabled": "support_enable and support_use_towers", "settable_per_mesh": true + }, + "support_mesh_drop_down": + { + "label": "Drop Down Support Mesh", + "description": "Make support everywhere below the support mesh, so that there's no overhang in the support mesh.", + "type": "bool", + "default_value": true, + "enabled": "support_mesh", + "settable_per_mesh": true, + "settable_per_extruder": false, + "settable_per_meshgroup": false, + "settable_globally": false } } }, @@ -5261,18 +5273,6 @@ "settable_per_meshgroup": false, "settable_globally": false }, - "support_mesh_drop_down": - { - "label": "Drop Down Support Mesh", - "description": "Make support everywhere below the support mesh, so that there's no overhang in the support mesh.", - "type": "bool", - "default_value": true, - "enabled": "support_mesh", - "settable_per_mesh": true, - "settable_per_extruder": false, - "settable_per_meshgroup": false, - "settable_globally": false - }, "anti_overhang_mesh": { "label": "Anti Overhang Mesh", From c885341e5a3b88e865db8d8de86fc7f3097622f3 Mon Sep 17 00:00:00 2001 From: Tyler Gibson Date: Sun, 7 Jan 2018 22:39:54 -0800 Subject: [PATCH 08/50] Removing nozzle variants, adding material definitions --- resources/definitions/malyan_m200.def.json | 17 +++++--------- .../monoprice_select_mini_v1.def.json | 2 +- .../monoprice_select_mini_v2.def.json | 9 +++++--- .../abs/malyan_m200_abs_draft.inst.cfg | 15 ++++++++++++ .../abs/malyan_m200_abs_fast.inst.cfg | 15 ++++++++++++ .../abs/malyan_m200_abs_high.inst.cfg | 15 ++++++++++++ .../abs/malyan_m200_abs_normal.inst.cfg | 15 ++++++++++++ .../abs/malyan_m200_abs_superdraft.inst.cfg | 15 ++++++++++++ .../abs/malyan_m200_abs_thickerdraft.inst.cfg | 15 ++++++++++++ .../abs/malyan_m200_abs_ultra.inst.cfg | 15 ++++++++++++ .../abs/malyan_m200_abs_verydraft.inst.cfg | 15 ++++++++++++ .../malyan_m200_global_Draft_Quality.inst.cfg | 23 +++++++++++++++++++ .../malyan_m200_global_Fast_Quality.inst.cfg | 23 +++++++++++++++++++ .../malyan_m200_global_High_Quality.inst.cfg | 23 +++++++++++++++++++ ...malyan_m200_global_Normal_Quality.inst.cfg | 23 +++++++++++++++++++ ...an_m200_global_SuperDraft_Quality.inst.cfg | 23 +++++++++++++++++++ ..._m200_global_ThickerDraft_Quality.inst.cfg | 23 +++++++++++++++++++ .../malyan_m200_global_Ultra_Quality.inst.cfg | 23 +++++++++++++++++++ ...yan_m200_global_VeryDraft_Quality.inst.cfg | 23 +++++++++++++++++++ .../petg/malyan_m200_petg_draft.inst.cfg | 11 +++++++++ .../petg/malyan_m200_petg_fast.inst.cfg | 11 +++++++++ .../petg/malyan_m200_petg_high.inst.cfg | 11 +++++++++ .../petg/malyan_m200_petg_normal.inst.cfg | 11 +++++++++ .../petg/malyan_m200_petg_superdraft.inst.cfg | 11 +++++++++ .../malyan_m200_petg_thickerdraft.inst.cfg | 11 +++++++++ .../petg/malyan_m200_petg_ultra.inst.cfg | 11 +++++++++ .../petg/malyan_m200_petg_verydraft.inst.cfg | 11 +++++++++ .../pla/malyan_m200_pla_draft.inst.cfg | 15 ++++++++++++ .../pla/malyan_m200_pla_fast.inst.cfg | 15 ++++++++++++ .../pla/malyan_m200_pla_high.inst.cfg | 15 ++++++++++++ .../pla/malyan_m200_pla_normal.inst.cfg | 15 ++++++++++++ .../pla/malyan_m200_pla_superdraft.inst.cfg | 15 ++++++++++++ .../pla/malyan_m200_pla_thickerdraft.inst.cfg | 15 ++++++++++++ .../pla/malyan_m200_pla_ultra.inst.cfg | 15 ++++++++++++ .../pla/malyan_m200_pla_verydraft.inst.cfg | 15 ++++++++++++ ...onoprice_select_mini_v2_abs_draft.inst.cfg | 15 ++++++++++++ ...monoprice_select_mini_v2_abs_fast.inst.cfg | 15 ++++++++++++ ...monoprice_select_mini_v2_abs_high.inst.cfg | 15 ++++++++++++ ...noprice_select_mini_v2_abs_normal.inst.cfg | 15 ++++++++++++ ...ice_select_mini_v2_abs_superdraft.inst.cfg | 15 ++++++++++++ ...e_select_mini_v2_abs_thickerdraft.inst.cfg | 15 ++++++++++++ ...onoprice_select_mini_v2_abs_ultra.inst.cfg | 15 ++++++++++++ ...rice_select_mini_v2_abs_verydraft.inst.cfg | 15 ++++++++++++ ...lect_mini_v2_global_Draft_Quality.inst.cfg | 23 +++++++++++++++++++ ...elect_mini_v2_global_Fast_Quality.inst.cfg | 23 +++++++++++++++++++ ...elect_mini_v2_global_High_Quality.inst.cfg | 23 +++++++++++++++++++ ...ect_mini_v2_global_Normal_Quality.inst.cfg | 23 +++++++++++++++++++ ...mini_v2_global_SuperDraft_Quality.inst.cfg | 23 +++++++++++++++++++ ...ni_v2_global_ThickerDraft_Quality.inst.cfg | 23 +++++++++++++++++++ ...lect_mini_v2_global_Ultra_Quality.inst.cfg | 23 +++++++++++++++++++ ..._mini_v2_global_VeryDraft_Quality.inst.cfg | 23 +++++++++++++++++++ ...oprice_select_mini_v2_nylon_draft.inst.cfg | 11 +++++++++ ...noprice_select_mini_v2_nylon_fast.inst.cfg | 11 +++++++++ ...noprice_select_mini_v2_nylon_high.inst.cfg | 11 +++++++++ ...price_select_mini_v2_nylon_normal.inst.cfg | 11 +++++++++ ...e_select_mini_v2_nylon_superdraft.inst.cfg | 11 +++++++++ ...select_mini_v2_nylon_thickerdraft.inst.cfg | 11 +++++++++ ...oprice_select_mini_v2_nylon_ultra.inst.cfg | 11 +++++++++ ...ce_select_mini_v2_nylon_verydraft.inst.cfg | 11 +++++++++ ...monoprice_select_mini_v2_pc_draft.inst.cfg | 15 ++++++++++++ .../monoprice_select_mini_v2_pc_fast.inst.cfg | 15 ++++++++++++ .../monoprice_select_mini_v2_pc_high.inst.cfg | 15 ++++++++++++ ...onoprice_select_mini_v2_pc_normal.inst.cfg | 15 ++++++++++++ ...rice_select_mini_v2_pc_superdraft.inst.cfg | 15 ++++++++++++ ...ce_select_mini_v2_pc_thickerdraft.inst.cfg | 15 ++++++++++++ ...monoprice_select_mini_v2_pc_ultra.inst.cfg | 15 ++++++++++++ ...price_select_mini_v2_pc_verydraft.inst.cfg | 15 ++++++++++++ ...noprice_select_mini_v2_petg_draft.inst.cfg | 11 +++++++++ ...onoprice_select_mini_v2_petg_fast.inst.cfg | 11 +++++++++ ...onoprice_select_mini_v2_petg_high.inst.cfg | 11 +++++++++ ...oprice_select_mini_v2_petg_normal.inst.cfg | 11 +++++++++ ...ce_select_mini_v2_petg_superdraft.inst.cfg | 11 +++++++++ ..._select_mini_v2_petg_thickerdraft.inst.cfg | 11 +++++++++ ...noprice_select_mini_v2_petg_ultra.inst.cfg | 11 +++++++++ ...ice_select_mini_v2_petg_verydraft.inst.cfg | 11 +++++++++ ...onoprice_select_mini_v2_pla_draft.inst.cfg | 11 +++++++++ ...monoprice_select_mini_v2_pla_fast.inst.cfg | 11 +++++++++ ...monoprice_select_mini_v2_pla_high.inst.cfg | 11 +++++++++ ...noprice_select_mini_v2_pla_normal.inst.cfg | 11 +++++++++ ...ice_select_mini_v2_pla_superdraft.inst.cfg | 11 +++++++++ ...e_select_mini_v2_pla_thickerdraft.inst.cfg | 11 +++++++++ ...onoprice_select_mini_v2_pla_ultra.inst.cfg | 11 +++++++++ ...rice_select_mini_v2_pla_verydraft.inst.cfg | 11 +++++++++ .../variants/malyan_m200_0.15mm.inst.cfg | 18 --------------- .../variants/malyan_m200_0.25mm.inst.cfg | 18 --------------- .../variants/malyan_m200_0.30mm.inst.cfg | 18 --------------- .../variants/malyan_m200_0.35mm.inst.cfg | 18 --------------- .../variants/malyan_m200_0.40mm.inst.cfg | 18 --------------- .../variants/malyan_m200_0.50mm.inst.cfg | 18 --------------- .../variants/malyan_m200_0.60mm.inst.cfg | 18 --------------- .../variants/malyan_m200_0.80mm.inst.cfg | 18 --------------- .../variants/malyan_m200_1.00mm.inst.cfg | 18 --------------- 92 files changed, 1213 insertions(+), 177 deletions(-) create mode 100644 resources/quality/malyan_m200/abs/malyan_m200_abs_draft.inst.cfg create mode 100644 resources/quality/malyan_m200/abs/malyan_m200_abs_fast.inst.cfg create mode 100644 resources/quality/malyan_m200/abs/malyan_m200_abs_high.inst.cfg create mode 100644 resources/quality/malyan_m200/abs/malyan_m200_abs_normal.inst.cfg create mode 100644 resources/quality/malyan_m200/abs/malyan_m200_abs_superdraft.inst.cfg create mode 100644 resources/quality/malyan_m200/abs/malyan_m200_abs_thickerdraft.inst.cfg create mode 100644 resources/quality/malyan_m200/abs/malyan_m200_abs_ultra.inst.cfg create mode 100644 resources/quality/malyan_m200/abs/malyan_m200_abs_verydraft.inst.cfg create mode 100644 resources/quality/malyan_m200/malyan_m200_global_Draft_Quality.inst.cfg create mode 100644 resources/quality/malyan_m200/malyan_m200_global_Fast_Quality.inst.cfg create mode 100644 resources/quality/malyan_m200/malyan_m200_global_High_Quality.inst.cfg create mode 100644 resources/quality/malyan_m200/malyan_m200_global_Normal_Quality.inst.cfg create mode 100644 resources/quality/malyan_m200/malyan_m200_global_SuperDraft_Quality.inst.cfg create mode 100644 resources/quality/malyan_m200/malyan_m200_global_ThickerDraft_Quality.inst.cfg create mode 100644 resources/quality/malyan_m200/malyan_m200_global_Ultra_Quality.inst.cfg create mode 100644 resources/quality/malyan_m200/malyan_m200_global_VeryDraft_Quality.inst.cfg create mode 100644 resources/quality/malyan_m200/petg/malyan_m200_petg_draft.inst.cfg create mode 100644 resources/quality/malyan_m200/petg/malyan_m200_petg_fast.inst.cfg create mode 100644 resources/quality/malyan_m200/petg/malyan_m200_petg_high.inst.cfg create mode 100644 resources/quality/malyan_m200/petg/malyan_m200_petg_normal.inst.cfg create mode 100644 resources/quality/malyan_m200/petg/malyan_m200_petg_superdraft.inst.cfg create mode 100644 resources/quality/malyan_m200/petg/malyan_m200_petg_thickerdraft.inst.cfg create mode 100644 resources/quality/malyan_m200/petg/malyan_m200_petg_ultra.inst.cfg create mode 100644 resources/quality/malyan_m200/petg/malyan_m200_petg_verydraft.inst.cfg create mode 100644 resources/quality/malyan_m200/pla/malyan_m200_pla_draft.inst.cfg create mode 100644 resources/quality/malyan_m200/pla/malyan_m200_pla_fast.inst.cfg create mode 100644 resources/quality/malyan_m200/pla/malyan_m200_pla_high.inst.cfg create mode 100644 resources/quality/malyan_m200/pla/malyan_m200_pla_normal.inst.cfg create mode 100644 resources/quality/malyan_m200/pla/malyan_m200_pla_superdraft.inst.cfg create mode 100644 resources/quality/malyan_m200/pla/malyan_m200_pla_thickerdraft.inst.cfg create mode 100644 resources/quality/malyan_m200/pla/malyan_m200_pla_ultra.inst.cfg create mode 100644 resources/quality/malyan_m200/pla/malyan_m200_pla_verydraft.inst.cfg create mode 100644 resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_draft.inst.cfg create mode 100644 resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_fast.inst.cfg create mode 100644 resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_high.inst.cfg create mode 100644 resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_normal.inst.cfg create mode 100644 resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_superdraft.inst.cfg create mode 100644 resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_thickerdraft.inst.cfg create mode 100644 resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_ultra.inst.cfg create mode 100644 resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_verydraft.inst.cfg create mode 100644 resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_Draft_Quality.inst.cfg create mode 100644 resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_Fast_Quality.inst.cfg create mode 100644 resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_High_Quality.inst.cfg create mode 100644 resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_Normal_Quality.inst.cfg create mode 100644 resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_SuperDraft_Quality.inst.cfg create mode 100644 resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_ThickerDraft_Quality.inst.cfg create mode 100644 resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_Ultra_Quality.inst.cfg create mode 100644 resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_VeryDraft_Quality.inst.cfg create mode 100644 resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_draft.inst.cfg create mode 100644 resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_fast.inst.cfg create mode 100644 resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_high.inst.cfg create mode 100644 resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_normal.inst.cfg create mode 100644 resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_superdraft.inst.cfg create mode 100644 resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_thickerdraft.inst.cfg create mode 100644 resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_ultra.inst.cfg create mode 100644 resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_verydraft.inst.cfg create mode 100644 resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_draft.inst.cfg create mode 100644 resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_fast.inst.cfg create mode 100644 resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_high.inst.cfg create mode 100644 resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_normal.inst.cfg create mode 100644 resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_superdraft.inst.cfg create mode 100644 resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_thickerdraft.inst.cfg create mode 100644 resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_ultra.inst.cfg create mode 100644 resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_verydraft.inst.cfg create mode 100644 resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_draft.inst.cfg create mode 100644 resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_fast.inst.cfg create mode 100644 resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_high.inst.cfg create mode 100644 resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_normal.inst.cfg create mode 100644 resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_superdraft.inst.cfg create mode 100644 resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_thickerdraft.inst.cfg create mode 100644 resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_ultra.inst.cfg create mode 100644 resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_verydraft.inst.cfg create mode 100644 resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_draft.inst.cfg create mode 100644 resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_fast.inst.cfg create mode 100644 resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_high.inst.cfg create mode 100644 resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_normal.inst.cfg create mode 100644 resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_superdraft.inst.cfg create mode 100644 resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_thickerdraft.inst.cfg create mode 100644 resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_ultra.inst.cfg create mode 100644 resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_verydraft.inst.cfg delete mode 100644 resources/variants/malyan_m200_0.15mm.inst.cfg delete mode 100644 resources/variants/malyan_m200_0.25mm.inst.cfg delete mode 100644 resources/variants/malyan_m200_0.30mm.inst.cfg delete mode 100644 resources/variants/malyan_m200_0.35mm.inst.cfg delete mode 100644 resources/variants/malyan_m200_0.40mm.inst.cfg delete mode 100644 resources/variants/malyan_m200_0.50mm.inst.cfg delete mode 100644 resources/variants/malyan_m200_0.60mm.inst.cfg delete mode 100644 resources/variants/malyan_m200_0.80mm.inst.cfg delete mode 100644 resources/variants/malyan_m200_1.00mm.inst.cfg diff --git a/resources/definitions/malyan_m200.def.json b/resources/definitions/malyan_m200.def.json index f19980a3b7..9aae3a5244 100644 --- a/resources/definitions/malyan_m200.def.json +++ b/resources/definitions/malyan_m200.def.json @@ -4,19 +4,14 @@ "name": "Malyan M200", "inherits": "fdmprinter", "metadata": { - "author": "Brian Corbino", + "author": "Brian Corbino, Tyler Gibson", "manufacturer": "Malyan", "category": "Other", "file_formats": "text/x-gcode", "platform": "malyan_m200_platform.stl", - "has_variants": true, - "has_variant_materials": false, - "has_materials": true, - "has_machine_materials": false, "has_machine_quality": true, - "preferred_variant": "*0.4*", - "preferred_quality": "*0.175*", - "variants_name": "Nozzle size", + "has_materials": true, + "preferred_quality": "*normal*", "supports_usb_connection": true, "visible": true, "first_start_actions": ["MachineSettingsAction"], @@ -39,9 +34,9 @@ "line_width": { "value": "round(machine_nozzle_size * 0.875, 2)" }, "material_print_temperature": { "minimum_value": "0" }, - "material_print_temperature_layer_0": { "value": "material_print_temperature + 5" }, + "material_print_temperature_layer_0": { "value": "min(material_print_temperature + 5, 245)" }, "material_bed_temperature": { "minimum_value": "0" }, - "material_bed_temperature_layer_0": { "value": "material_bed_temperature + 5" }, + "material_bed_temperature_layer_0": { "value": "min(material_bed_temperature + 5, 70)" }, "material_standby_temperature": { "minimum_value": "0" }, "machine_show_variants": { "default_value": true }, "machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" }, @@ -59,7 +54,7 @@ "material_diameter": { "value": 1.75 }, "machine_nozzle_size": { "default_value": 0.4, - "minimum_value": "0.15" + "minimum_value": 0.15 }, "machine_max_feedrate_x": { "default_value": 150 }, "machine_max_feedrate_y": { "default_value": 150 }, diff --git a/resources/definitions/monoprice_select_mini_v1.def.json b/resources/definitions/monoprice_select_mini_v1.def.json index 0b76a26c1c..7264f0a6fc 100644 --- a/resources/definitions/monoprice_select_mini_v1.def.json +++ b/resources/definitions/monoprice_select_mini_v1.def.json @@ -4,7 +4,7 @@ "name": "Monoprice Select Mini V1", "inherits": "malyan_m200", "metadata": { - "author": "Brian Corbino", + "author": "Brian Corbino, Tyler Gibson", "manufacturer": "Monoprice", "category": "Other", "file_formats": "text/x-gcode", diff --git a/resources/definitions/monoprice_select_mini_v2.def.json b/resources/definitions/monoprice_select_mini_v2.def.json index 33367aad88..a935cb5a73 100644 --- a/resources/definitions/monoprice_select_mini_v2.def.json +++ b/resources/definitions/monoprice_select_mini_v2.def.json @@ -4,11 +4,13 @@ "name": "Monoprice Select Mini V2 (E3D)", "inherits": "malyan_m200", "metadata": { - "author": "Brian Corbino", + "author": "Tyler Gibson", "manufacturer": "Monoprice", "category": "Other", "file_formats": "text/x-gcode", - "quality_definition": "malyan_m200", + "has_machine_quality": true, + "has_materials": true, + "preferred_quality": "*normal*", "visible": true }, @@ -17,6 +19,7 @@ "adhesion_type": { "default_value": "brim" }, "retraction_combing": { "default_value": "noskin" }, "retraction_amount" : { "default_value": 2.5}, - "retraction_speed" : { "default_value": 40} + "retraction_speed" : { "default_value": 40}, + "material_print_temperature_layer_0": { "value": "material_print_temperature + 5" }, } } diff --git a/resources/quality/malyan_m200/abs/malyan_m200_abs_draft.inst.cfg b/resources/quality/malyan_m200/abs/malyan_m200_abs_draft.inst.cfg new file mode 100644 index 0000000000..19cc9fd00d --- /dev/null +++ b/resources/quality/malyan_m200/abs/malyan_m200_abs_draft.inst.cfg @@ -0,0 +1,15 @@ +[general] +version = 2 +name = Fast +definition = malyan_m200 + +[metadata] +type = quality +quality_type = draft +material = generic_abs_175 +weight = -2 +setting_version = 4 + +[values] +material_bed_temperature = 70 +material_bed_temperature_layer_0 = 70 \ No newline at end of file diff --git a/resources/quality/malyan_m200/abs/malyan_m200_abs_fast.inst.cfg b/resources/quality/malyan_m200/abs/malyan_m200_abs_fast.inst.cfg new file mode 100644 index 0000000000..5677a0d58d --- /dev/null +++ b/resources/quality/malyan_m200/abs/malyan_m200_abs_fast.inst.cfg @@ -0,0 +1,15 @@ +[general] +version = 2 +name = Normal +definition = malyan_m200 + +[metadata] +type = quality +quality_type = fast +material = generic_abs_175 +weight = -1 +setting_version = 4 + +[values] +material_bed_temperature = 70 +material_bed_temperature_layer_0 = 70 \ No newline at end of file diff --git a/resources/quality/malyan_m200/abs/malyan_m200_abs_high.inst.cfg b/resources/quality/malyan_m200/abs/malyan_m200_abs_high.inst.cfg new file mode 100644 index 0000000000..7798b3f545 --- /dev/null +++ b/resources/quality/malyan_m200/abs/malyan_m200_abs_high.inst.cfg @@ -0,0 +1,15 @@ +[general] +version = 2 +name = Finer +definition = malyan_m200 + +[metadata] +type = quality +quality_type = high +material = generic_abs_175 +weight = 1 +setting_version = 4 + +[values] +material_bed_temperature = 70 +material_bed_temperature_layer_0 = 70 \ No newline at end of file diff --git a/resources/quality/malyan_m200/abs/malyan_m200_abs_normal.inst.cfg b/resources/quality/malyan_m200/abs/malyan_m200_abs_normal.inst.cfg new file mode 100644 index 0000000000..c87c66c813 --- /dev/null +++ b/resources/quality/malyan_m200/abs/malyan_m200_abs_normal.inst.cfg @@ -0,0 +1,15 @@ +[general] +version = 2 +name = Fine +definition = malyan_m200 + +[metadata] +type = quality +quality_type = normal +material = generic_abs_175 +weight = 0 +setting_version = 4 + +[values] +material_bed_temperature = 70 +material_bed_temperature_layer_0 = 70 \ No newline at end of file diff --git a/resources/quality/malyan_m200/abs/malyan_m200_abs_superdraft.inst.cfg b/resources/quality/malyan_m200/abs/malyan_m200_abs_superdraft.inst.cfg new file mode 100644 index 0000000000..e6e3cfcd6c --- /dev/null +++ b/resources/quality/malyan_m200/abs/malyan_m200_abs_superdraft.inst.cfg @@ -0,0 +1,15 @@ +[general] +version = 2 +name = Lowest Quality Draft +definition = malyan_m200 + +[metadata] +type = quality +quality_type = superdraft +material = generic_abs_175 +weight = -5 +setting_version = 4 + +[values] +material_bed_temperature = 70 +material_bed_temperature_layer_0 = 70 \ No newline at end of file diff --git a/resources/quality/malyan_m200/abs/malyan_m200_abs_thickerdraft.inst.cfg b/resources/quality/malyan_m200/abs/malyan_m200_abs_thickerdraft.inst.cfg new file mode 100644 index 0000000000..fb08013809 --- /dev/null +++ b/resources/quality/malyan_m200/abs/malyan_m200_abs_thickerdraft.inst.cfg @@ -0,0 +1,15 @@ +[general] +version = 2 +name = Draft +definition = malyan_m200 + +[metadata] +type = quality +quality_type = thickerdraft +material = generic_abs_175 +weight = -3 +setting_version = 4 + +[values] +material_bed_temperature = 70 +material_bed_temperature_layer_0 = 70 \ No newline at end of file diff --git a/resources/quality/malyan_m200/abs/malyan_m200_abs_ultra.inst.cfg b/resources/quality/malyan_m200/abs/malyan_m200_abs_ultra.inst.cfg new file mode 100644 index 0000000000..385d852688 --- /dev/null +++ b/resources/quality/malyan_m200/abs/malyan_m200_abs_ultra.inst.cfg @@ -0,0 +1,15 @@ +[general] +version = 2 +name = Ultra Fine +definition = malyan_m200 + +[metadata] +type = quality +quality_type = ultra +material = generic_abs_175 +weight = 2 +setting_version = 4 + +[values] +material_bed_temperature = 70 +material_bed_temperature_layer_0 = 70 \ No newline at end of file diff --git a/resources/quality/malyan_m200/abs/malyan_m200_abs_verydraft.inst.cfg b/resources/quality/malyan_m200/abs/malyan_m200_abs_verydraft.inst.cfg new file mode 100644 index 0000000000..7026391fb6 --- /dev/null +++ b/resources/quality/malyan_m200/abs/malyan_m200_abs_verydraft.inst.cfg @@ -0,0 +1,15 @@ +[general] +version = 2 +name = Low Detail Draft +definition = malyan_m200 + +[metadata] +type = quality +quality_type = verydraft +material = generic_abs_175 +weight = -4 +setting_version = 4 + +[values] +material_bed_temperature = 70 +material_bed_temperature_layer_0 = 70 \ No newline at end of file diff --git a/resources/quality/malyan_m200/malyan_m200_global_Draft_Quality.inst.cfg b/resources/quality/malyan_m200/malyan_m200_global_Draft_Quality.inst.cfg new file mode 100644 index 0000000000..d3104caa87 --- /dev/null +++ b/resources/quality/malyan_m200/malyan_m200_global_Draft_Quality.inst.cfg @@ -0,0 +1,23 @@ +[general] +version = 2 +name = Fast +definition = malyan_m200 + +[metadata] +type = quality +weight = -2 +quality_type = draft +global_quality = True +setting_version = 4 + +[values] +layer_height = 0.21875 +layer_height_0 = 0.2625 +wall_thickness = 1.05 +top_bottom_thickness = 0.72 +infill_sparse_density = 22 +speed_print = 50 +speed_layer_0 = =round(speed_print * 30 / 50) +speed_topbottom = 20 +cool_min_layer_time = 5 +cool_min_speed = 10 diff --git a/resources/quality/malyan_m200/malyan_m200_global_Fast_Quality.inst.cfg b/resources/quality/malyan_m200/malyan_m200_global_Fast_Quality.inst.cfg new file mode 100644 index 0000000000..aec535bd71 --- /dev/null +++ b/resources/quality/malyan_m200/malyan_m200_global_Fast_Quality.inst.cfg @@ -0,0 +1,23 @@ +[general] +version = 2 +name = Normal +definition = malyan_m200 + +[metadata] +type = quality +weight = -1 +quality_type = fast +global_quality = True +setting_version = 4 + +[values] +layer_height = 0.175 +layer_height_0 = 0.2625 +wall_thickness = 1.05 +top_bottom_thickness = 0.72 +infill_sparse_density = 22 +speed_print = 50 +speed_layer_0 = =round(speed_print * 30 / 50) +speed_topbottom = 20 +cool_min_layer_time = 5 +cool_min_speed = 10 diff --git a/resources/quality/malyan_m200/malyan_m200_global_High_Quality.inst.cfg b/resources/quality/malyan_m200/malyan_m200_global_High_Quality.inst.cfg new file mode 100644 index 0000000000..ca202862a2 --- /dev/null +++ b/resources/quality/malyan_m200/malyan_m200_global_High_Quality.inst.cfg @@ -0,0 +1,23 @@ +[general] +version = 2 +name = Finer +definition = malyan_m200 + +[metadata] +type = quality +weight = 1 +quality_type = high +global_quality = True +setting_version = 4 + +[values] +layer_height = 0.0875 +layer_height_0 = 0.2625 +wall_thickness = 1.05 +top_bottom_thickness = 0.72 +infill_sparse_density = 22 +speed_print = 50 +speed_layer_0 = =round(speed_print * 30 / 50) +speed_topbottom = 20 +cool_min_layer_time = 5 +cool_min_speed = 10 diff --git a/resources/quality/malyan_m200/malyan_m200_global_Normal_Quality.inst.cfg b/resources/quality/malyan_m200/malyan_m200_global_Normal_Quality.inst.cfg new file mode 100644 index 0000000000..7076718903 --- /dev/null +++ b/resources/quality/malyan_m200/malyan_m200_global_Normal_Quality.inst.cfg @@ -0,0 +1,23 @@ +[general] +version = 2 +name = Fine +definition = malyan_m200 + +[metadata] +type = quality +weight = 0 +quality_type = normal +global_quality = True +setting_version = 4 + +[values] +layer_height = 0.13125 +layer_height_0 = 0.2625 +wall_thickness = 1.05 +top_bottom_thickness = 0.72 +infill_sparse_density = 22 +speed_print = 50 +speed_layer_0 = =round(speed_print * 30 / 50) +speed_topbottom = 20 +cool_min_layer_time = 5 +cool_min_speed = 10 diff --git a/resources/quality/malyan_m200/malyan_m200_global_SuperDraft_Quality.inst.cfg b/resources/quality/malyan_m200/malyan_m200_global_SuperDraft_Quality.inst.cfg new file mode 100644 index 0000000000..7dfbdb5886 --- /dev/null +++ b/resources/quality/malyan_m200/malyan_m200_global_SuperDraft_Quality.inst.cfg @@ -0,0 +1,23 @@ +[general] +version = 2 +name = Lowest Quality Draft +definition = malyan_m200 + +[metadata] +type = quality +weight = -5 +quality_type = superdraft +global_quality = True +setting_version = 4 + +[values] +layer_height = 0.35 +layer_height_0 = 0.35 +wall_thickness = 1.05 +top_bottom_thickness = 0.72 +infill_sparse_density = 22 +speed_print = 50 +speed_layer_0 = =round(speed_print * 30 / 50) +speed_topbottom = 20 +cool_min_layer_time = 5 +cool_min_speed = 10 diff --git a/resources/quality/malyan_m200/malyan_m200_global_ThickerDraft_Quality.inst.cfg b/resources/quality/malyan_m200/malyan_m200_global_ThickerDraft_Quality.inst.cfg new file mode 100644 index 0000000000..2fbf82b128 --- /dev/null +++ b/resources/quality/malyan_m200/malyan_m200_global_ThickerDraft_Quality.inst.cfg @@ -0,0 +1,23 @@ +[general] +version = 2 +name = Draft +definition = malyan_m200 + +[metadata] +type = quality +weight = -3 +quality_type = thickerdraft +global_quality = True +setting_version = 4 + +[values] +layer_height = 0.2625 +layer_height_0 = 0.2625 +wall_thickness = 1.05 +top_bottom_thickness = 0.72 +infill_sparse_density = 22 +speed_print = 50 +speed_layer_0 = =round(speed_print * 30 / 50) +speed_topbottom = 20 +cool_min_layer_time = 5 +cool_min_speed = 10 diff --git a/resources/quality/malyan_m200/malyan_m200_global_Ultra_Quality.inst.cfg b/resources/quality/malyan_m200/malyan_m200_global_Ultra_Quality.inst.cfg new file mode 100644 index 0000000000..90e589cca5 --- /dev/null +++ b/resources/quality/malyan_m200/malyan_m200_global_Ultra_Quality.inst.cfg @@ -0,0 +1,23 @@ +[general] +version = 2 +name = Ultra Fine +definition = malyan_m200 + +[metadata] +type = quality +weight = 2 +quality_type = ultra +global_quality = True +setting_version = 4 + +[values] +layer_height = 0.04375 +layer_height_0 = 0.2625 +wall_thickness = 1.05 +top_bottom_thickness = 0.72 +infill_sparse_density = 22 +speed_print = 50 +speed_layer_0 = =round(speed_print * 30 / 50) +speed_topbottom = 20 +cool_min_layer_time = 5 +cool_min_speed = 10 diff --git a/resources/quality/malyan_m200/malyan_m200_global_VeryDraft_Quality.inst.cfg b/resources/quality/malyan_m200/malyan_m200_global_VeryDraft_Quality.inst.cfg new file mode 100644 index 0000000000..1210ee214b --- /dev/null +++ b/resources/quality/malyan_m200/malyan_m200_global_VeryDraft_Quality.inst.cfg @@ -0,0 +1,23 @@ +[general] +version = 2 +name = Low Detail Draft +definition = malyan_m200 + +[metadata] +type = quality +weight = -4 +quality_type = verydraft +global_quality = True +setting_version = 4 + +[values] +layer_height = 0.30625 +layer_height_0 = 0.30625 +wall_thickness = 1.05 +top_bottom_thickness = 0.72 +infill_sparse_density = 22 +speed_print = 50 +speed_layer_0 = =round(speed_print * 30 / 50) +speed_topbottom = 20 +cool_min_layer_time = 5 +cool_min_speed = 10 diff --git a/resources/quality/malyan_m200/petg/malyan_m200_petg_draft.inst.cfg b/resources/quality/malyan_m200/petg/malyan_m200_petg_draft.inst.cfg new file mode 100644 index 0000000000..aef83471ba --- /dev/null +++ b/resources/quality/malyan_m200/petg/malyan_m200_petg_draft.inst.cfg @@ -0,0 +1,11 @@ +[general] +version = 2 +name = Fast +definition = malyan_m200 + +[metadata] +type = quality +quality_type = draft +material = generic_petg_175 +weight = -2 +setting_version = 4 \ No newline at end of file diff --git a/resources/quality/malyan_m200/petg/malyan_m200_petg_fast.inst.cfg b/resources/quality/malyan_m200/petg/malyan_m200_petg_fast.inst.cfg new file mode 100644 index 0000000000..3c7fc2c239 --- /dev/null +++ b/resources/quality/malyan_m200/petg/malyan_m200_petg_fast.inst.cfg @@ -0,0 +1,11 @@ +[general] +version = 2 +name = Normal +definition = malyan_m200 + +[metadata] +type = quality +quality_type = fast +material = generic_petg_175 +weight = -1 +setting_version = 4 \ No newline at end of file diff --git a/resources/quality/malyan_m200/petg/malyan_m200_petg_high.inst.cfg b/resources/quality/malyan_m200/petg/malyan_m200_petg_high.inst.cfg new file mode 100644 index 0000000000..eb1654eae3 --- /dev/null +++ b/resources/quality/malyan_m200/petg/malyan_m200_petg_high.inst.cfg @@ -0,0 +1,11 @@ +[general] +version = 2 +name = Finer +definition = malyan_m200 + +[metadata] +type = quality +quality_type = high +material = generic_petg_175 +weight = 1 +setting_version = 4 \ No newline at end of file diff --git a/resources/quality/malyan_m200/petg/malyan_m200_petg_normal.inst.cfg b/resources/quality/malyan_m200/petg/malyan_m200_petg_normal.inst.cfg new file mode 100644 index 0000000000..53e60d2d62 --- /dev/null +++ b/resources/quality/malyan_m200/petg/malyan_m200_petg_normal.inst.cfg @@ -0,0 +1,11 @@ +[general] +version = 2 +name = Fine +definition = malyan_m200 + +[metadata] +type = quality +quality_type = normal +material = generic_petg_175 +weight = 0 +setting_version = 4 \ No newline at end of file diff --git a/resources/quality/malyan_m200/petg/malyan_m200_petg_superdraft.inst.cfg b/resources/quality/malyan_m200/petg/malyan_m200_petg_superdraft.inst.cfg new file mode 100644 index 0000000000..d2a96386ae --- /dev/null +++ b/resources/quality/malyan_m200/petg/malyan_m200_petg_superdraft.inst.cfg @@ -0,0 +1,11 @@ +[general] +version = 2 +name = Lowest Quality Draft +definition = malyan_m200 + +[metadata] +type = quality +quality_type = superdraft +material = generic_petg_175 +weight = -5 +setting_version = 4 \ No newline at end of file diff --git a/resources/quality/malyan_m200/petg/malyan_m200_petg_thickerdraft.inst.cfg b/resources/quality/malyan_m200/petg/malyan_m200_petg_thickerdraft.inst.cfg new file mode 100644 index 0000000000..e2f37ae43b --- /dev/null +++ b/resources/quality/malyan_m200/petg/malyan_m200_petg_thickerdraft.inst.cfg @@ -0,0 +1,11 @@ +[general] +version = 2 +name = Draft +definition = malyan_m200 + +[metadata] +type = quality +quality_type = thickerdraft +material = generic_petg_175 +weight = -3 +setting_version = 4 \ No newline at end of file diff --git a/resources/quality/malyan_m200/petg/malyan_m200_petg_ultra.inst.cfg b/resources/quality/malyan_m200/petg/malyan_m200_petg_ultra.inst.cfg new file mode 100644 index 0000000000..0fa89f2569 --- /dev/null +++ b/resources/quality/malyan_m200/petg/malyan_m200_petg_ultra.inst.cfg @@ -0,0 +1,11 @@ +[general] +version = 2 +name = Ultra Fine +definition = malyan_m200 + +[metadata] +type = quality +quality_type = ultra +material = generic_petg_175 +weight = 2 +setting_version = 4 \ No newline at end of file diff --git a/resources/quality/malyan_m200/petg/malyan_m200_petg_verydraft.inst.cfg b/resources/quality/malyan_m200/petg/malyan_m200_petg_verydraft.inst.cfg new file mode 100644 index 0000000000..84bedf5c14 --- /dev/null +++ b/resources/quality/malyan_m200/petg/malyan_m200_petg_verydraft.inst.cfg @@ -0,0 +1,11 @@ +[general] +version = 2 +name = Low Detail Draft +definition = malyan_m200 + +[metadata] +type = quality +quality_type = verydraft +material = generic_petg_175 +weight = -4 +setting_version = 4 \ No newline at end of file diff --git a/resources/quality/malyan_m200/pla/malyan_m200_pla_draft.inst.cfg b/resources/quality/malyan_m200/pla/malyan_m200_pla_draft.inst.cfg new file mode 100644 index 0000000000..4f221eceb7 --- /dev/null +++ b/resources/quality/malyan_m200/pla/malyan_m200_pla_draft.inst.cfg @@ -0,0 +1,15 @@ +[general] +version = 2 +name = Fast +definition = malyan_m200 + +[metadata] +type = quality +quality_type = draft +material = generic_pla_175 +weight = -2 +setting_version = 4 + +[values] +material_bed_temperature = 60 +material_bed_temperature_layer_0 = 60 \ No newline at end of file diff --git a/resources/quality/malyan_m200/pla/malyan_m200_pla_fast.inst.cfg b/resources/quality/malyan_m200/pla/malyan_m200_pla_fast.inst.cfg new file mode 100644 index 0000000000..3097fe055a --- /dev/null +++ b/resources/quality/malyan_m200/pla/malyan_m200_pla_fast.inst.cfg @@ -0,0 +1,15 @@ +[general] +version = 2 +name = Normal +definition = malyan_m200 + +[metadata] +type = quality +quality_type = fast +material = generic_pla_175 +weight = -1 +setting_version = 4 + +[values] +material_bed_temperature = 60 +material_bed_temperature_layer_0 = 60 \ No newline at end of file diff --git a/resources/quality/malyan_m200/pla/malyan_m200_pla_high.inst.cfg b/resources/quality/malyan_m200/pla/malyan_m200_pla_high.inst.cfg new file mode 100644 index 0000000000..062c120ad0 --- /dev/null +++ b/resources/quality/malyan_m200/pla/malyan_m200_pla_high.inst.cfg @@ -0,0 +1,15 @@ +[general] +version = 2 +name = Finer +definition = malyan_m200 + +[metadata] +type = quality +quality_type = high +material = generic_pla_175 +weight = 1 +setting_version = 4 + +[values] +material_bed_temperature = 60 +material_bed_temperature_layer_0 = 60 \ No newline at end of file diff --git a/resources/quality/malyan_m200/pla/malyan_m200_pla_normal.inst.cfg b/resources/quality/malyan_m200/pla/malyan_m200_pla_normal.inst.cfg new file mode 100644 index 0000000000..e01141ed9e --- /dev/null +++ b/resources/quality/malyan_m200/pla/malyan_m200_pla_normal.inst.cfg @@ -0,0 +1,15 @@ +[general] +version = 2 +name = Fine +definition = malyan_m200 + +[metadata] +type = quality +quality_type = normal +material = generic_pla_175 +weight = 0 +setting_version = 4 + +[values] +material_bed_temperature = 60 +material_bed_temperature_layer_0 = 60 \ No newline at end of file diff --git a/resources/quality/malyan_m200/pla/malyan_m200_pla_superdraft.inst.cfg b/resources/quality/malyan_m200/pla/malyan_m200_pla_superdraft.inst.cfg new file mode 100644 index 0000000000..53eb4380eb --- /dev/null +++ b/resources/quality/malyan_m200/pla/malyan_m200_pla_superdraft.inst.cfg @@ -0,0 +1,15 @@ +[general] +version = 2 +name = Lowest Quality Draft +definition = malyan_m200 + +[metadata] +type = quality +quality_type = superdraft +material = generic_pla_175 +weight = -5 +setting_version = 4 + +[values] +material_bed_temperature = 60 +material_bed_temperature_layer_0 = 60 \ No newline at end of file diff --git a/resources/quality/malyan_m200/pla/malyan_m200_pla_thickerdraft.inst.cfg b/resources/quality/malyan_m200/pla/malyan_m200_pla_thickerdraft.inst.cfg new file mode 100644 index 0000000000..32d2b419bc --- /dev/null +++ b/resources/quality/malyan_m200/pla/malyan_m200_pla_thickerdraft.inst.cfg @@ -0,0 +1,15 @@ +[general] +version = 2 +name = Draft +definition = malyan_m200 + +[metadata] +type = quality +quality_type = thickerdraft +material = generic_pla_175 +weight = -3 +setting_version = 4 + +[values] +material_bed_temperature = 60 +material_bed_temperature_layer_0 = 60 \ No newline at end of file diff --git a/resources/quality/malyan_m200/pla/malyan_m200_pla_ultra.inst.cfg b/resources/quality/malyan_m200/pla/malyan_m200_pla_ultra.inst.cfg new file mode 100644 index 0000000000..3865059254 --- /dev/null +++ b/resources/quality/malyan_m200/pla/malyan_m200_pla_ultra.inst.cfg @@ -0,0 +1,15 @@ +[general] +version = 2 +name = Ultra Fine +definition = malyan_m200 + +[metadata] +type = quality +quality_type = ultra +material = generic_pla_175 +weight = 2 +setting_version = 4 + +[values] +material_bed_temperature = 60 +material_bed_temperature_layer_0 = 60 \ No newline at end of file diff --git a/resources/quality/malyan_m200/pla/malyan_m200_pla_verydraft.inst.cfg b/resources/quality/malyan_m200/pla/malyan_m200_pla_verydraft.inst.cfg new file mode 100644 index 0000000000..a624c056be --- /dev/null +++ b/resources/quality/malyan_m200/pla/malyan_m200_pla_verydraft.inst.cfg @@ -0,0 +1,15 @@ +[general] +version = 2 +name = Low Detail Draft +definition = malyan_m200 + +[metadata] +type = quality +quality_type = verydraft +material = generic_pla_175 +weight = -4 +setting_version = 4 + +[values] +material_bed_temperature = 60 +material_bed_temperature_layer_0 = 60 \ No newline at end of file diff --git a/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_draft.inst.cfg b/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_draft.inst.cfg new file mode 100644 index 0000000000..a63256573a --- /dev/null +++ b/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_draft.inst.cfg @@ -0,0 +1,15 @@ +[general] +version = 2 +name = Fast +definition = monoprice_select_mini_v2 + +[metadata] +type = quality +quality_type = draft +material = generic_abs_175 +weight = -2 +setting_version = 4 + +[values] +material_bed_temperature = 70 +material_bed_temperature_layer_0 = 70 \ No newline at end of file diff --git a/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_fast.inst.cfg b/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_fast.inst.cfg new file mode 100644 index 0000000000..49f4486596 --- /dev/null +++ b/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_fast.inst.cfg @@ -0,0 +1,15 @@ +[general] +version = 2 +name = Normal +definition = monoprice_select_mini_v2 + +[metadata] +type = quality +quality_type = fast +material = generic_abs_175 +weight = -1 +setting_version = 4 + +[values] +material_bed_temperature = 70 +material_bed_temperature_layer_0 = 70 \ No newline at end of file diff --git a/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_high.inst.cfg b/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_high.inst.cfg new file mode 100644 index 0000000000..eab16a8e2b --- /dev/null +++ b/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_high.inst.cfg @@ -0,0 +1,15 @@ +[general] +version = 2 +name = Finer +definition = monoprice_select_mini_v2 + +[metadata] +type = quality +quality_type = high +material = generic_abs_175 +weight = 1 +setting_version = 4 + +[values] +material_bed_temperature = 70 +material_bed_temperature_layer_0 = 70 \ No newline at end of file diff --git a/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_normal.inst.cfg b/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_normal.inst.cfg new file mode 100644 index 0000000000..03aeb4067b --- /dev/null +++ b/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_normal.inst.cfg @@ -0,0 +1,15 @@ +[general] +version = 2 +name = Fine +definition = monoprice_select_mini_v2 + +[metadata] +type = quality +quality_type = normal +material = generic_abs_175 +weight = 0 +setting_version = 4 + +[values] +material_bed_temperature = 70 +material_bed_temperature_layer_0 = 70 \ No newline at end of file diff --git a/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_superdraft.inst.cfg b/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_superdraft.inst.cfg new file mode 100644 index 0000000000..148f53ba73 --- /dev/null +++ b/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_superdraft.inst.cfg @@ -0,0 +1,15 @@ +[general] +version = 2 +name = Lowest Quality Draft +definition = monoprice_select_mini_v2 + +[metadata] +type = quality +quality_type = superdraft +material = generic_abs_175 +weight = -5 +setting_version = 4 + +[values] +material_bed_temperature = 70 +material_bed_temperature_layer_0 = 70 \ No newline at end of file diff --git a/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_thickerdraft.inst.cfg b/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_thickerdraft.inst.cfg new file mode 100644 index 0000000000..e2ad71a360 --- /dev/null +++ b/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_thickerdraft.inst.cfg @@ -0,0 +1,15 @@ +[general] +version = 2 +name = Draft +definition = monoprice_select_mini_v2 + +[metadata] +type = quality +quality_type = thickerdraft +material = generic_abs_175 +weight = -3 +setting_version = 4 + +[values] +material_bed_temperature = 70 +material_bed_temperature_layer_0 = 70 \ No newline at end of file diff --git a/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_ultra.inst.cfg b/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_ultra.inst.cfg new file mode 100644 index 0000000000..7ebdf80baf --- /dev/null +++ b/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_ultra.inst.cfg @@ -0,0 +1,15 @@ +[general] +version = 2 +name = Ultra Fine +definition = monoprice_select_mini_v2 + +[metadata] +type = quality +quality_type = thickerdraft +material = generic_abs_175 +weight = 2 +setting_version = 4 + +[values] +material_bed_temperature = 70 +material_bed_temperature_layer_0 = 70 \ No newline at end of file diff --git a/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_verydraft.inst.cfg b/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_verydraft.inst.cfg new file mode 100644 index 0000000000..9965ae8bcf --- /dev/null +++ b/resources/quality/monoprice_select_mini_v2/abs/monoprice_select_mini_v2_abs_verydraft.inst.cfg @@ -0,0 +1,15 @@ +[general] +version = 2 +name = Low Detail Draft +definition = monoprice_select_mini_v2 + +[metadata] +type = quality +quality_type = verydraft +material = generic_abs_175 +weight = -4 +setting_version = 4 + +[values] +material_bed_temperature = 70 +material_bed_temperature_layer_0 = 70 \ No newline at end of file diff --git a/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_Draft_Quality.inst.cfg b/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_Draft_Quality.inst.cfg new file mode 100644 index 0000000000..b7d0faa2c7 --- /dev/null +++ b/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_Draft_Quality.inst.cfg @@ -0,0 +1,23 @@ +[general] +version = 2 +name = Fast +definition = monoprice_select_mini_v2 + +[metadata] +type = quality +weight = -2 +quality_type = draft +global_quality = True +setting_version = 4 + +[values] +layer_height = 0.21875 +layer_height_0 = 0.2625 +wall_thickness = 1.05 +top_bottom_thickness = 0.72 +infill_sparse_density = 22 +speed_print = 50 +speed_layer_0 = =round(speed_print * 30 / 50) +speed_topbottom = 20 +cool_min_layer_time = 5 +cool_min_speed = 10 diff --git a/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_Fast_Quality.inst.cfg b/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_Fast_Quality.inst.cfg new file mode 100644 index 0000000000..f7f338e4c9 --- /dev/null +++ b/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_Fast_Quality.inst.cfg @@ -0,0 +1,23 @@ +[general] +version = 2 +name = Normal +definition = monoprice_select_mini_v2 + +[metadata] +type = quality +weight = -1 +quality_type = fast +global_quality = True +setting_version = 4 + +[values] +layer_height = 0.175 +layer_height_0 = 0.2625 +wall_thickness = 1.05 +top_bottom_thickness = 0.72 +infill_sparse_density = 22 +speed_print = 50 +speed_layer_0 = =round(speed_print * 30 / 50) +speed_topbottom = 20 +cool_min_layer_time = 5 +cool_min_speed = 10 diff --git a/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_High_Quality.inst.cfg b/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_High_Quality.inst.cfg new file mode 100644 index 0000000000..4a37a1afd8 --- /dev/null +++ b/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_High_Quality.inst.cfg @@ -0,0 +1,23 @@ +[general] +version = 2 +name = Finer +definition = monoprice_select_mini_v2 + +[metadata] +type = quality +weight = 1 +quality_type = high +global_quality = True +setting_version = 4 + +[values] +layer_height = 0.0875 +layer_height_0 = 0.2625 +wall_thickness = 1.05 +top_bottom_thickness = 0.72 +infill_sparse_density = 22 +speed_print = 50 +speed_layer_0 = =round(speed_print * 30 / 50) +speed_topbottom = 20 +cool_min_layer_time = 5 +cool_min_speed = 10 diff --git a/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_Normal_Quality.inst.cfg b/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_Normal_Quality.inst.cfg new file mode 100644 index 0000000000..b8e545adcf --- /dev/null +++ b/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_Normal_Quality.inst.cfg @@ -0,0 +1,23 @@ +[general] +version = 2 +name = Fine +definition = monoprice_select_mini_v2 + +[metadata] +type = quality +weight = 0 +quality_type = normal +global_quality = True +setting_version = 4 + +[values] +layer_height = 0.13125 +layer_height_0 = 0.2625 +wall_thickness = 1.05 +top_bottom_thickness = 0.72 +infill_sparse_density = 22 +speed_print = 50 +speed_layer_0 = =round(speed_print * 30 / 50) +speed_topbottom = 20 +cool_min_layer_time = 5 +cool_min_speed = 10 diff --git a/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_SuperDraft_Quality.inst.cfg b/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_SuperDraft_Quality.inst.cfg new file mode 100644 index 0000000000..0ef9db5875 --- /dev/null +++ b/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_SuperDraft_Quality.inst.cfg @@ -0,0 +1,23 @@ +[general] +version = 2 +name = Lowest Quality Draft +definition = monoprice_select_mini_v2 + +[metadata] +type = quality +weight = -5 +quality_type = superdraft +global_quality = True +setting_version = 4 + +[values] +layer_height = 0.35 +layer_height_0 = 0.35 +wall_thickness = 1.05 +top_bottom_thickness = 0.72 +infill_sparse_density = 22 +speed_print = 50 +speed_layer_0 = =round(speed_print * 30 / 50) +speed_topbottom = 20 +cool_min_layer_time = 5 +cool_min_speed = 10 diff --git a/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_ThickerDraft_Quality.inst.cfg b/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_ThickerDraft_Quality.inst.cfg new file mode 100644 index 0000000000..4dd3a7aafe --- /dev/null +++ b/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_ThickerDraft_Quality.inst.cfg @@ -0,0 +1,23 @@ +[general] +version = 2 +name = Draft +definition = monoprice_select_mini_v2 + +[metadata] +type = quality +weight = -3 +quality_type = thickerdraft +global_quality = True +setting_version = 4 + +[values] +layer_height = 0.2625 +layer_height_0 = 0.2625 +wall_thickness = 1.05 +top_bottom_thickness = 0.72 +infill_sparse_density = 22 +speed_print = 50 +speed_layer_0 = =round(speed_print * 30 / 50) +speed_topbottom = 20 +cool_min_layer_time = 5 +cool_min_speed = 10 diff --git a/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_Ultra_Quality.inst.cfg b/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_Ultra_Quality.inst.cfg new file mode 100644 index 0000000000..337f0d06bc --- /dev/null +++ b/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_Ultra_Quality.inst.cfg @@ -0,0 +1,23 @@ +[general] +version = 2 +name = Ultra Fine +definition = monoprice_select_mini_v2 + +[metadata] +type = quality +weight = 2 +quality_type = ultra +global_quality = True +setting_version = 4 + +[values] +layer_height = 0.04375 +layer_height_0 = 0.2625 +wall_thickness = 1.05 +top_bottom_thickness = 0.72 +infill_sparse_density = 22 +speed_print = 50 +speed_layer_0 = =round(speed_print * 30 / 50) +speed_topbottom = 20 +cool_min_layer_time = 5 +cool_min_speed = 10 diff --git a/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_VeryDraft_Quality.inst.cfg b/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_VeryDraft_Quality.inst.cfg new file mode 100644 index 0000000000..e884077069 --- /dev/null +++ b/resources/quality/monoprice_select_mini_v2/monoprice_select_mini_v2_global_VeryDraft_Quality.inst.cfg @@ -0,0 +1,23 @@ +[general] +version = 2 +name = Low Detail Draft +definition = monoprice_select_mini_v2 + +[metadata] +type = quality +weight = -4 +quality_type = verydraft +global_quality = True +setting_version = 4 + +[values] +layer_height = 0.30625 +layer_height_0 = 0.30625 +wall_thickness = 1.05 +top_bottom_thickness = 0.72 +infill_sparse_density = 22 +speed_print = 50 +speed_layer_0 = =round(speed_print * 30 / 50) +speed_topbottom = 20 +cool_min_layer_time = 5 +cool_min_speed = 10 diff --git a/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_draft.inst.cfg b/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_draft.inst.cfg new file mode 100644 index 0000000000..4a03c17a63 --- /dev/null +++ b/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_draft.inst.cfg @@ -0,0 +1,11 @@ +[general] +version = 2 +name = Fast +definition = monoprice_select_mini_v2 + +[metadata] +type = quality +quality_type = draft +material = generic_nylon_175 +weight = -2 +setting_version = 4 \ No newline at end of file diff --git a/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_fast.inst.cfg b/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_fast.inst.cfg new file mode 100644 index 0000000000..1c04f77b8b --- /dev/null +++ b/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_fast.inst.cfg @@ -0,0 +1,11 @@ +[general] +version = 2 +name = Normal +definition = monoprice_select_mini_v2 + +[metadata] +type = quality +quality_type = fast +material = generic_nylon_175 +weight = -1 +setting_version = 4 \ No newline at end of file diff --git a/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_high.inst.cfg b/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_high.inst.cfg new file mode 100644 index 0000000000..d57516598a --- /dev/null +++ b/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_high.inst.cfg @@ -0,0 +1,11 @@ +[general] +version = 2 +name = Finer +definition = monoprice_select_mini_v2 + +[metadata] +type = quality +quality_type = high +material = generic_nylon_175 +weight = 1 +setting_version = 4 \ No newline at end of file diff --git a/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_normal.inst.cfg b/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_normal.inst.cfg new file mode 100644 index 0000000000..308ea86311 --- /dev/null +++ b/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_normal.inst.cfg @@ -0,0 +1,11 @@ +[general] +version = 2 +name = Fine +definition = monoprice_select_mini_v2 + +[metadata] +type = quality +quality_type = normal +material = generic_nylon_175 +weight = 0 +setting_version = 4 \ No newline at end of file diff --git a/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_superdraft.inst.cfg b/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_superdraft.inst.cfg new file mode 100644 index 0000000000..db4f3ca907 --- /dev/null +++ b/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_superdraft.inst.cfg @@ -0,0 +1,11 @@ +[general] +version = 2 +name = Lowest Quality Draft +definition = monoprice_select_mini_v2 + +[metadata] +type = quality +quality_type = superdraft +material = generic_nylon_175 +weight = -5 +setting_version = 4 \ No newline at end of file diff --git a/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_thickerdraft.inst.cfg b/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_thickerdraft.inst.cfg new file mode 100644 index 0000000000..9a1afc0e48 --- /dev/null +++ b/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_thickerdraft.inst.cfg @@ -0,0 +1,11 @@ +[general] +version = 2 +name = Draft +definition = monoprice_select_mini_v2 + +[metadata] +type = quality +quality_type = thickerdraft +material = generic_nylon_175 +weight = -3 +setting_version = 4 \ No newline at end of file diff --git a/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_ultra.inst.cfg b/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_ultra.inst.cfg new file mode 100644 index 0000000000..3453671a72 --- /dev/null +++ b/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_ultra.inst.cfg @@ -0,0 +1,11 @@ +[general] +version = 2 +name = Ultra Fine +definition = monoprice_select_mini_v2 + +[metadata] +type = quality +quality_type = ultra +material = generic_nylon_175 +weight = 2 +setting_version = 4 \ No newline at end of file diff --git a/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_verydraft.inst.cfg b/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_verydraft.inst.cfg new file mode 100644 index 0000000000..ee2531fc4e --- /dev/null +++ b/resources/quality/monoprice_select_mini_v2/nylon/monoprice_select_mini_v2_nylon_verydraft.inst.cfg @@ -0,0 +1,11 @@ +[general] +version = 2 +name = Low Detail Draft +definition = monoprice_select_mini_v2 + +[metadata] +type = quality +quality_type = verydraft +material = generic_nylon_175 +weight = -4 +setting_version = 4 \ No newline at end of file diff --git a/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_draft.inst.cfg b/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_draft.inst.cfg new file mode 100644 index 0000000000..aa5fc7844d --- /dev/null +++ b/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_draft.inst.cfg @@ -0,0 +1,15 @@ +[general] +version = 2 +name = Fast +definition = monoprice_select_mini_v2 + +[metadata] +type = quality +quality_type = draft +material = generic_pc_175 +weight = -2 +setting_version = 4 + +[values] +material_bed_temperature = 70 +material_bed_temperature_layer_0 = 70 \ No newline at end of file diff --git a/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_fast.inst.cfg b/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_fast.inst.cfg new file mode 100644 index 0000000000..232c4ab6f3 --- /dev/null +++ b/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_fast.inst.cfg @@ -0,0 +1,15 @@ +[general] +version = 2 +name = Normal +definition = monoprice_select_mini_v2 + +[metadata] +type = quality +quality_type = fast +material = generic_pc_175 +weight = -1 +setting_version = 4 + +[values] +material_bed_temperature = 70 +material_bed_temperature_layer_0 = 70 \ No newline at end of file diff --git a/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_high.inst.cfg b/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_high.inst.cfg new file mode 100644 index 0000000000..aa9da322fb --- /dev/null +++ b/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_high.inst.cfg @@ -0,0 +1,15 @@ +[general] +version = 2 +name = Finer +definition = monoprice_select_mini_v2 + +[metadata] +type = quality +quality_type = high +material = generic_pc_175 +weight = 1 +setting_version = 4 + +[values] +material_bed_temperature = 70 +material_bed_temperature_layer_0 = 70 \ No newline at end of file diff --git a/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_normal.inst.cfg b/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_normal.inst.cfg new file mode 100644 index 0000000000..145b21221b --- /dev/null +++ b/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_normal.inst.cfg @@ -0,0 +1,15 @@ +[general] +version = 2 +name = Fine +definition = monoprice_select_mini_v2 + +[metadata] +type = quality +quality_type = normal +material = generic_pc_175 +weight = 0 +setting_version = 4 + +[values] +material_bed_temperature = 70 +material_bed_temperature_layer_0 = 70 \ No newline at end of file diff --git a/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_superdraft.inst.cfg b/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_superdraft.inst.cfg new file mode 100644 index 0000000000..b6e53bda62 --- /dev/null +++ b/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_superdraft.inst.cfg @@ -0,0 +1,15 @@ +[general] +version = 2 +name = Lowest Quality Draft +definition = monoprice_select_mini_v2 + +[metadata] +type = quality +quality_type = superdraft +material = generic_pc_175 +weight = -5 +setting_version = 4 + +[values] +material_bed_temperature = 70 +material_bed_temperature_layer_0 = 70 \ No newline at end of file diff --git a/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_thickerdraft.inst.cfg b/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_thickerdraft.inst.cfg new file mode 100644 index 0000000000..055228ab13 --- /dev/null +++ b/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_thickerdraft.inst.cfg @@ -0,0 +1,15 @@ +[general] +version = 2 +name = Draft +definition = monoprice_select_mini_v2 + +[metadata] +type = quality +quality_type = thickerdraft +material = generic_pc_175 +weight = -3 +setting_version = 4 + +[values] +material_bed_temperature = 70 +material_bed_temperature_layer_0 = 70 \ No newline at end of file diff --git a/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_ultra.inst.cfg b/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_ultra.inst.cfg new file mode 100644 index 0000000000..a3e99b998e --- /dev/null +++ b/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_ultra.inst.cfg @@ -0,0 +1,15 @@ +[general] +version = 2 +name = Ultra Fine +definition = monoprice_select_mini_v2 + +[metadata] +type = quality +quality_type = ultra +material = generic_pc_175 +weight = 2 +setting_version = 4 + +[values] +material_bed_temperature = 70 +material_bed_temperature_layer_0 = 70 \ No newline at end of file diff --git a/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_verydraft.inst.cfg b/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_verydraft.inst.cfg new file mode 100644 index 0000000000..73f5a2f2c9 --- /dev/null +++ b/resources/quality/monoprice_select_mini_v2/pc/monoprice_select_mini_v2_pc_verydraft.inst.cfg @@ -0,0 +1,15 @@ +[general] +version = 2 +name = Low Detail Draft +definition = monoprice_select_mini_v2 + +[metadata] +type = quality +quality_type = verydraft +material = generic_pc_175 +weight = -4 +setting_version = 4 + +[values] +material_bed_temperature = 70 +material_bed_temperature_layer_0 = 70 \ No newline at end of file diff --git a/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_draft.inst.cfg b/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_draft.inst.cfg new file mode 100644 index 0000000000..8a33e03310 --- /dev/null +++ b/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_draft.inst.cfg @@ -0,0 +1,11 @@ +[general] +version = 2 +name = Fast +definition = monoprice_select_mini_v2 + +[metadata] +type = quality +quality_type = draft +material = generic_petg_175 +weight = -2 +setting_version = 4 \ No newline at end of file diff --git a/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_fast.inst.cfg b/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_fast.inst.cfg new file mode 100644 index 0000000000..fb084fa08e --- /dev/null +++ b/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_fast.inst.cfg @@ -0,0 +1,11 @@ +[general] +version = 2 +name = Normal +definition = monoprice_select_mini_v2 + +[metadata] +type = quality +quality_type = fast +material = generic_petg_175 +weight = -1 +setting_version = 4 \ No newline at end of file diff --git a/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_high.inst.cfg b/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_high.inst.cfg new file mode 100644 index 0000000000..16891f6f43 --- /dev/null +++ b/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_high.inst.cfg @@ -0,0 +1,11 @@ +[general] +version = 2 +name = Finer +definition = monoprice_select_mini_v2 + +[metadata] +type = quality +quality_type = high +material = generic_petg_175 +weight = 1 +setting_version = 4 \ No newline at end of file diff --git a/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_normal.inst.cfg b/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_normal.inst.cfg new file mode 100644 index 0000000000..bb2f0b47a8 --- /dev/null +++ b/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_normal.inst.cfg @@ -0,0 +1,11 @@ +[general] +version = 2 +name = Fine +definition = monoprice_select_mini_v2 + +[metadata] +type = quality +quality_type = normal +material = generic_petg_175 +weight = 0 +setting_version = 4 \ No newline at end of file diff --git a/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_superdraft.inst.cfg b/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_superdraft.inst.cfg new file mode 100644 index 0000000000..78ca1b6b7a --- /dev/null +++ b/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_superdraft.inst.cfg @@ -0,0 +1,11 @@ +[general] +version = 2 +name = Lowest Quality Draft +definition = monoprice_select_mini_v2 + +[metadata] +type = quality +quality_type = superdraft +material = generic_petg_175 +weight = -5 +setting_version = 4 \ No newline at end of file diff --git a/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_thickerdraft.inst.cfg b/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_thickerdraft.inst.cfg new file mode 100644 index 0000000000..69606ff913 --- /dev/null +++ b/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_thickerdraft.inst.cfg @@ -0,0 +1,11 @@ +[general] +version = 2 +name = Draft +definition = monoprice_select_mini_v2 + +[metadata] +type = quality +quality_type = thickerdraft +material = generic_petg_175 +weight = -3 +setting_version = 4 \ No newline at end of file diff --git a/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_ultra.inst.cfg b/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_ultra.inst.cfg new file mode 100644 index 0000000000..7c5ac599c8 --- /dev/null +++ b/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_ultra.inst.cfg @@ -0,0 +1,11 @@ +[general] +version = 2 +name = Ultra Fine +definition = monoprice_select_mini_v2 + +[metadata] +type = quality +quality_type = ultra +material = generic_petg_175 +weight = 2 +setting_version = 4 \ No newline at end of file diff --git a/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_verydraft.inst.cfg b/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_verydraft.inst.cfg new file mode 100644 index 0000000000..ed0c2510f5 --- /dev/null +++ b/resources/quality/monoprice_select_mini_v2/petg/monoprice_select_mini_v2_petg_verydraft.inst.cfg @@ -0,0 +1,11 @@ +[general] +version = 2 +name = Low Detail Draft +definition = monoprice_select_mini_v2 + +[metadata] +type = quality +quality_type = verydraft +material = generic_petg_175 +weight = -4 +setting_version = 4 \ No newline at end of file diff --git a/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_draft.inst.cfg b/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_draft.inst.cfg new file mode 100644 index 0000000000..04a955cf6c --- /dev/null +++ b/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_draft.inst.cfg @@ -0,0 +1,11 @@ +[general] +version = 2 +name = Fast +definition = monoprice_select_mini_v2 + +[metadata] +type = quality +quality_type = draft +material = generic_pla_175 +weight = -2 +setting_version = 4 \ No newline at end of file diff --git a/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_fast.inst.cfg b/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_fast.inst.cfg new file mode 100644 index 0000000000..6efc0935e2 --- /dev/null +++ b/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_fast.inst.cfg @@ -0,0 +1,11 @@ +[general] +version = 2 +name = Normal +definition = monoprice_select_mini_v2 + +[metadata] +type = quality +quality_type = fast +material = generic_pla_175 +weight = 0 +setting_version = 4 \ No newline at end of file diff --git a/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_high.inst.cfg b/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_high.inst.cfg new file mode 100644 index 0000000000..8fe2371e5d --- /dev/null +++ b/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_high.inst.cfg @@ -0,0 +1,11 @@ +[general] +version = 2 +name = Finer +definition = monoprice_select_mini_v2 + +[metadata] +type = quality +quality_type = high +material = generic_pla_175 +weight = 0 +setting_version = 4 \ No newline at end of file diff --git a/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_normal.inst.cfg b/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_normal.inst.cfg new file mode 100644 index 0000000000..01351154c4 --- /dev/null +++ b/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_normal.inst.cfg @@ -0,0 +1,11 @@ +[general] +version = 2 +name = Fine +definition = monoprice_select_mini_v2 + +[metadata] +type = quality +quality_type = normal +material = generic_pla_175 +weight = 0 +setting_version = 4 \ No newline at end of file diff --git a/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_superdraft.inst.cfg b/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_superdraft.inst.cfg new file mode 100644 index 0000000000..adfced9787 --- /dev/null +++ b/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_superdraft.inst.cfg @@ -0,0 +1,11 @@ +[general] +version = 2 +name = Lowest Quality Draft +definition = monoprice_select_mini_v2 + +[metadata] +type = quality +quality_type = superdraft +material = generic_pla_175 +weight = -5 +setting_version = 4 \ No newline at end of file diff --git a/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_thickerdraft.inst.cfg b/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_thickerdraft.inst.cfg new file mode 100644 index 0000000000..f4522c9778 --- /dev/null +++ b/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_thickerdraft.inst.cfg @@ -0,0 +1,11 @@ +[general] +version = 2 +name = Draft +definition = monoprice_select_mini_v2 + +[metadata] +type = quality +quality_type = thickerdraft +material = generic_pla_175 +weight = -3 +setting_version = 4 \ No newline at end of file diff --git a/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_ultra.inst.cfg b/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_ultra.inst.cfg new file mode 100644 index 0000000000..2fa8eb7f81 --- /dev/null +++ b/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_ultra.inst.cfg @@ -0,0 +1,11 @@ +[general] +version = 2 +name = Ultra Fine +definition = monoprice_select_mini_v2 + +[metadata] +type = quality +quality_type = ultra +material = generic_pla_175 +weight = 2 +setting_version = 4 \ No newline at end of file diff --git a/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_verydraft.inst.cfg b/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_verydraft.inst.cfg new file mode 100644 index 0000000000..e59cf4a490 --- /dev/null +++ b/resources/quality/monoprice_select_mini_v2/pla/monoprice_select_mini_v2_pla_verydraft.inst.cfg @@ -0,0 +1,11 @@ +[general] +version = 2 +name = Low Detail Draft +definition = monoprice_select_mini_v2 + +[metadata] +type = quality +quality_type = verydraft +material = generic_pla_175 +weight = 0 +setting_version = 4 \ No newline at end of file diff --git a/resources/variants/malyan_m200_0.15mm.inst.cfg b/resources/variants/malyan_m200_0.15mm.inst.cfg deleted file mode 100644 index 808b8755ea..0000000000 --- a/resources/variants/malyan_m200_0.15mm.inst.cfg +++ /dev/null @@ -1,18 +0,0 @@ -[general] -name = 0.15 mm -version = 2 -definition = malyan_m200 - -[metadata] -author = Brian Corbino -type = variant -setting_version = 3 - -[values] -machine_nozzle_size = 0.15 -machine_nozzle_tip_outer_diameter = 0.8 -coasting_volume = 0.05 -coasting_min_volume = =round(coasting_volume * 4,2) -speed_wall = =round(speed_print / 1.2, 1) -speed_wall_0 = =1 if speed_wall < 5 else (speed_wall - 5) -speed_topbottom = =round(speed_print / 1.5, 1) diff --git a/resources/variants/malyan_m200_0.25mm.inst.cfg b/resources/variants/malyan_m200_0.25mm.inst.cfg deleted file mode 100644 index 3847f5c617..0000000000 --- a/resources/variants/malyan_m200_0.25mm.inst.cfg +++ /dev/null @@ -1,18 +0,0 @@ -[general] -name = 0.25 mm -version = 2 -definition = malyan_m200 - -[metadata] -author = Brian Corbino -type = variant -setting_version = 3 - -[values] -machine_nozzle_size = 0.25 -machine_nozzle_tip_outer_diameter = 0.8 -coasting_volume = 0.1 -coasting_min_volume = =round(coasting_volume * 4,2) -speed_wall = =round(speed_print / 1.2, 1) -speed_wall_0 = =1 if speed_wall < 5 else (speed_wall - 5) -speed_topbottom = =round(speed_print / 1.5, 1) diff --git a/resources/variants/malyan_m200_0.30mm.inst.cfg b/resources/variants/malyan_m200_0.30mm.inst.cfg deleted file mode 100644 index fee8aae40f..0000000000 --- a/resources/variants/malyan_m200_0.30mm.inst.cfg +++ /dev/null @@ -1,18 +0,0 @@ -[general] -name = 0.30 mm -version = 2 -definition = malyan_m200 - -[metadata] -author = Brian Corbino -type = variant -setting_version = 3 - -[values] -machine_nozzle_size = 0.30 -machine_nozzle_tip_outer_diameter = 0.8 -coasting_volume = 0.11 -coasting_min_volume = =round(coasting_volume * 4,2) -speed_wall = =round(speed_print / 1.2, 1) -speed_wall_0 = =1 if speed_wall < 5 else (speed_wall - 5) -speed_topbottom = =round(speed_print / 1.5, 1) diff --git a/resources/variants/malyan_m200_0.35mm.inst.cfg b/resources/variants/malyan_m200_0.35mm.inst.cfg deleted file mode 100644 index dcbb3ed4c0..0000000000 --- a/resources/variants/malyan_m200_0.35mm.inst.cfg +++ /dev/null @@ -1,18 +0,0 @@ -[general] -name = 0.35 mm -version = 2 -definition = malyan_m200 - -[metadata] -author = Brian Corbino -type = variant -setting_version = 3 - -[values] -machine_nozzle_size = 0.35 -machine_nozzle_tip_outer_diameter = 0.8 -coasting_volume = 0.13 -coasting_min_volume = =round(coasting_volume * 4,2) -speed_wall = =round(speed_print / 1.2, 1) -speed_wall_0 = =1 if speed_wall < 5 else (speed_wall - 5) -speed_topbottom = =round(speed_print / 1.5, 1) diff --git a/resources/variants/malyan_m200_0.40mm.inst.cfg b/resources/variants/malyan_m200_0.40mm.inst.cfg deleted file mode 100644 index 6e17dd13a6..0000000000 --- a/resources/variants/malyan_m200_0.40mm.inst.cfg +++ /dev/null @@ -1,18 +0,0 @@ -[general] -name = 0.40 mm -version = 2 -definition = malyan_m200 - -[metadata] -author = Brian Corbino -type = variant -setting_version = 3 - -[values] -machine_nozzle_size = 0.40 -machine_nozzle_tip_outer_diameter = 1.05 -coasting_volume = 0.15 -coasting_min_volume = =round(coasting_volume * 4,2) -speed_wall = =round(speed_print / 1.25, 1) -speed_wall_0 = =1 if speed_wall < 10 else (speed_wall - 10) -speed_topbottom = =round(speed_print / 2.25, 1) diff --git a/resources/variants/malyan_m200_0.50mm.inst.cfg b/resources/variants/malyan_m200_0.50mm.inst.cfg deleted file mode 100644 index ce87def1e6..0000000000 --- a/resources/variants/malyan_m200_0.50mm.inst.cfg +++ /dev/null @@ -1,18 +0,0 @@ -[general] -name = 0.50 mm -version = 2 -definition = malyan_m200 - -[metadata] -author = Brian Corbino -type = variant -setting_version = 3 - -[values] -machine_nozzle_size = 0.50 -machine_nozzle_tip_outer_diameter = 0.8 -coasting_volume = 0.2 -coasting_min_volume = =round(coasting_volume * 4,2) -speed_wall = =round(speed_print / 1.2, 1) -speed_wall_0 = =1 if speed_wall < 5 else (speed_wall - 5) -speed_topbottom = =round(speed_print / 1.5, 1) diff --git a/resources/variants/malyan_m200_0.60mm.inst.cfg b/resources/variants/malyan_m200_0.60mm.inst.cfg deleted file mode 100644 index 0ee7c786e8..0000000000 --- a/resources/variants/malyan_m200_0.60mm.inst.cfg +++ /dev/null @@ -1,18 +0,0 @@ -[general] -name = 0.60 mm -version = 2 -definition = malyan_m200 - -[metadata] -author = Brian Corbino -type = variant -setting_version = 3 - -[values] -machine_nozzle_size = 0.60 -machine_nozzle_tip_outer_diameter = 1.25 -coasting_volume = 0.28 -coasting_min_volume = =round(coasting_volume * 4,2) -speed_wall = =round(speed_print * 4 / 3, 1) -speed_wall_0 = =1 if speed_wall < 10 else (speed_wall - 10) -speed_topbottom = =round(speed_print / 2, 1) diff --git a/resources/variants/malyan_m200_0.80mm.inst.cfg b/resources/variants/malyan_m200_0.80mm.inst.cfg deleted file mode 100644 index 54f48afdb4..0000000000 --- a/resources/variants/malyan_m200_0.80mm.inst.cfg +++ /dev/null @@ -1,18 +0,0 @@ -[general] -name = 0.80 mm -version = 2 -definition = malyan_m200 - -[metadata] -author = Brian Corbino -type = variant -setting_version = 3 - -[values] -machine_nozzle_size = 0.80 -machine_nozzle_tip_outer_diameter = 1.35 -coasting_volume = 0.45 -coasting_min_volume = =round(coasting_volume * 4,2) -speed_wall = =round(speed_print * 4 / 3, 1) -speed_wall_0 = =1 if speed_wall < 10 else (speed_wall - 10) -speed_topbottom = =round(speed_print / 2, 1) diff --git a/resources/variants/malyan_m200_1.00mm.inst.cfg b/resources/variants/malyan_m200_1.00mm.inst.cfg deleted file mode 100644 index ce0a2d0dfb..0000000000 --- a/resources/variants/malyan_m200_1.00mm.inst.cfg +++ /dev/null @@ -1,18 +0,0 @@ -[general] -name = 1.00 mm -version = 2 -definition = malyan_m200 - -[metadata] -author = Brian Corbino -type = variant -setting_version = 3 - -[values] -machine_nozzle_size = 1.00 -machine_nozzle_tip_outer_diameter = 0.8 -coasting_volume = 0.63 -coasting_min_volume = =round(coasting_volume * 4,2) -speed_wall = =round(speed_print / 1.2, 1) -speed_wall_0 = =1 if speed_wall < 5 else (speed_wall - 5) -speed_topbottom = =round(speed_print / 1.5, 1) From 733d6234e6d821ca552c70106c47d027db4ed6ec Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Mon, 8 Jan 2018 11:13:16 +0100 Subject: [PATCH 09/50] CURA-4525 moved experimental preferences to bottom with its own label; all settings are by default off --- cura/CuraApplication.py | 4 +- resources/qml/Preferences/GeneralPage.qml | 71 ++++++++++++++--------- 2 files changed, 45 insertions(+), 30 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 8aeeb9c1e8..3013f6e116 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -319,7 +319,7 @@ class CuraApplication(QtApplication): preferences.addPreference("cura/asked_dialog_on_project_save", False) preferences.addPreference("cura/choice_on_profile_override", "always_ask") preferences.addPreference("cura/choice_on_open_project", "always_ask") - preferences.addPreference("cura/arrange_objects_on_load", True) + preferences.addPreference("cura/not_arrange_objects_on_load", False) preferences.addPreference("cura/use_multi_build_plate", False) preferences.addPreference("cura/currency", "€") @@ -1428,7 +1428,7 @@ class CuraApplication(QtApplication): self.fileLoaded.emit(filename) arrange_objects_on_load = ( not Preferences.getInstance().getValue("cura/use_multi_build_plate") or - Preferences.getInstance().getValue("cura/arrange_objects_on_load")) + not Preferences.getInstance().getValue("cura/not_arrange_objects_on_load")) target_build_plate = self.getBuildPlateModel().activeBuildPlate if arrange_objects_on_load else -1 for original_node in nodes: diff --git a/resources/qml/Preferences/GeneralPage.qml b/resources/qml/Preferences/GeneralPage.qml index e5ed9e46c5..ac5cacdbf6 100644 --- a/resources/qml/Preferences/GeneralPage.qml +++ b/resources/qml/Preferences/GeneralPage.qml @@ -453,34 +453,6 @@ UM.PreferencesPage text: catalog.i18nc("@label","Opening and saving files") } - UM.TooltipArea { - width: childrenRect.width - height: childrenRect.height - text: catalog.i18nc("@info:tooltip","Use multi build plate functionality (EXPERIMENTAL)") - - CheckBox - { - id: useMultiBuildPlateCheckbox - text: catalog.i18nc("@option:check","Use multi build plate functionality (EXPERIMENTAL, restart)") - checked: boolCheck(UM.Preferences.getValue("cura/use_multi_build_plate")) - onCheckedChanged: UM.Preferences.setValue("cura/use_multi_build_plate", checked) - } - } - - UM.TooltipArea { - width: childrenRect.width - height: childrenRect.height - text: catalog.i18nc("@info:tooltip","Should newly loaded models be arranged on the build plate? Used in conjunction with multi build plate (EXPERIMENTAL)") - - CheckBox - { - id: arrangeOnLoadCheckbox - text: catalog.i18nc("@option:check","Arrange objects on load (EXPERIMENTAL)") - checked: boolCheck(UM.Preferences.getValue("cura/arrange_objects_on_load")) - onCheckedChanged: UM.Preferences.setValue("cura/arrange_objects_on_load", checked) - } - } - UM.TooltipArea { width: childrenRect.width height: childrenRect.height @@ -688,6 +660,49 @@ UM.PreferencesPage onCheckedChanged: UM.Preferences.setValue("info/send_slice_info", checked) } } + + Item + { + //: Spacer + height: UM.Theme.getSize("default_margin").height + width: UM.Theme.getSize("default_margin").height + } + + Label + { + font.bold: true + text: catalog.i18nc("@label","Experimental") + } + + UM.TooltipArea { + width: childrenRect.width + height: childrenRect.height + text: catalog.i18nc("@info:tooltip","Use multi build plate functionality") + + CheckBox + { + id: useMultiBuildPlateCheckbox + text: catalog.i18nc("@option:check","Use multi build plate functionality (restart required)") + checked: boolCheck(UM.Preferences.getValue("cura/use_multi_build_plate")) + onCheckedChanged: UM.Preferences.setValue("cura/use_multi_build_plate", checked) + } + } + + UM.TooltipArea { + width: childrenRect.width + height: childrenRect.height + text: catalog.i18nc("@info:tooltip","Should newly loaded models be arranged on the build plate? Used in conjunction with multi build plate (EXPERIMENTAL)") + + CheckBox + { + id: arrangeOnLoadCheckbox + text: catalog.i18nc("@option:check","Do not arrange objects on load") + checked: boolCheck(UM.Preferences.getValue("cura/not_arrange_objects_on_load")) + onCheckedChanged: UM.Preferences.setValue("cura/not_arrange_objects_on_load", checked) + } + } + + } } } From e638c21acbaf53a79aaf742ede3a6feacfd9c059 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Mon, 8 Jan 2018 11:30:57 +0100 Subject: [PATCH 10/50] CURA-4525 fix selected object will select correct build plate (not only visualization) --- cura/Scene/CuraSceneController.py | 6 +++--- resources/qml/ObjectsList.qml | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/cura/Scene/CuraSceneController.py b/cura/Scene/CuraSceneController.py index 65723db52c..7931e13659 100644 --- a/cura/Scene/CuraSceneController.py +++ b/cura/Scene/CuraSceneController.py @@ -75,11 +75,11 @@ class CuraSceneController(QObject): # Single select item = self._objects_model.getItem(index) node = item["node"] - Selection.clear() - Selection.add(node) build_plate_number = node.callDecoration("getBuildPlateNumber") if build_plate_number is not None and build_plate_number != -1: - self._build_plate_model.setActiveBuildPlate(build_plate_number) + self.setActiveBuildPlate(build_plate_number) + Selection.clear() + Selection.add(node) self._last_selected_index = index diff --git a/resources/qml/ObjectsList.qml b/resources/qml/ObjectsList.qml index a02ea2288d..87f76774da 100644 --- a/resources/qml/ObjectsList.qml +++ b/resources/qml/ObjectsList.qml @@ -105,7 +105,6 @@ Rectangle topMargin: UM.Theme.getSize("default_margin").height; left: parent.left; leftMargin: UM.Theme.getSize("default_margin").height; - //bottom: objectsList.top; bottomMargin: UM.Theme.getSize("default_margin").height; } From 52b75b58e791ea5cdc5ff019daffd09fdc126ce5 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Mon, 8 Jan 2018 13:25:39 +0100 Subject: [PATCH 11/50] CURA-4525 allow for empty build plates between filled build plates --- plugins/CuraEngineBackend/CuraEngineBackend.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins/CuraEngineBackend/CuraEngineBackend.py b/plugins/CuraEngineBackend/CuraEngineBackend.py index 0ca500ecec..28ca793855 100755 --- a/plugins/CuraEngineBackend/CuraEngineBackend.py +++ b/plugins/CuraEngineBackend/CuraEngineBackend.py @@ -215,8 +215,9 @@ class CuraEngineBackend(QObject, Backend): num_objects = self._numObjects() if build_plate_to_be_sliced not in num_objects or num_objects[build_plate_to_be_sliced] == 0: self._scene.gcode_list[build_plate_to_be_sliced] = [] - Logger.log("d", "Build plate %s has 0 objects to be sliced, skipping", build_plate_to_be_sliced) - return + Logger.log("d", "Build plate %s has no objects to be sliced, skipping", build_plate_to_be_sliced) + if self._build_plates_to_be_sliced: + self._invokeSlice() self._stored_layer_data = [] self._stored_optimized_layer_data[build_plate_to_be_sliced] = [] From 86eb9c73bad0d20b1e04ba984fa25dde21ad7a6e Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Mon, 8 Jan 2018 13:40:46 +0100 Subject: [PATCH 12/50] CURA-4525 do not send empty build plates gcode; direct calling slice when skipping empty build plate --- plugins/CuraEngineBackend/CuraEngineBackend.py | 2 +- .../UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/plugins/CuraEngineBackend/CuraEngineBackend.py b/plugins/CuraEngineBackend/CuraEngineBackend.py index 28ca793855..249b2f6cbb 100755 --- a/plugins/CuraEngineBackend/CuraEngineBackend.py +++ b/plugins/CuraEngineBackend/CuraEngineBackend.py @@ -217,7 +217,7 @@ class CuraEngineBackend(QObject, Backend): self._scene.gcode_list[build_plate_to_be_sliced] = [] Logger.log("d", "Build plate %s has no objects to be sliced, skipping", build_plate_to_be_sliced) if self._build_plates_to_be_sliced: - self._invokeSlice() + return self.slice() self._stored_layer_data = [] self._stored_optimized_layer_data[build_plate_to_be_sliced] = [] diff --git a/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py b/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py index 05069d1c0d..6eb89d69a4 100644 --- a/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py +++ b/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py @@ -282,6 +282,9 @@ class NetworkClusterPrinterOutputDevice(NetworkPrinterOutputDevice.NetworkPrinte nodes, file_name, filter_by_machine, file_handler, kwargs = self._request_job output_build_plate_number = self._job_list.pop(0) gcode = getattr(Application.getInstance().getController().getScene(), "gcode_list")[output_build_plate_number] + if not gcode: # Empty build plate + Logger.log("d", "Skipping empty job (build plate number %d).", output_build_plate_number) + return self.sendPrintJob() self._send_gcode_start = time.time() Logger.log("d", "Sending print job [%s] to host, build plate [%s]..." % (file_name, output_build_plate_number)) From 164e5fdc8e4afe102fd8c41a82e858d9fd9323e1 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Mon, 8 Jan 2018 13:55:42 +0100 Subject: [PATCH 13/50] CURA-4525 change active build plate if that build plate does not exist anymore; disable context menu items for build plates when no selection --- cura/Scene/CuraSceneController.py | 7 +++++++ resources/qml/Menus/ContextMenu.qml | 2 ++ 2 files changed, 9 insertions(+) diff --git a/cura/Scene/CuraSceneController.py b/cura/Scene/CuraSceneController.py index 7931e13659..e594752f1e 100644 --- a/cura/Scene/CuraSceneController.py +++ b/cura/Scene/CuraSceneController.py @@ -41,6 +41,13 @@ class CuraSceneController(QObject): self._build_plate_model.setMaxBuildPlate(self._max_build_plate) build_plates = [{"name": "Build Plate %d" % (i + 1), "buildPlateNumber": i} for i in range(self._max_build_plate + 1)] self._build_plate_model.setItems(build_plates) + if self._active_build_plate > self._max_build_plate: + build_plate_number = 0 + if self._last_selected_index >= 0: # go to the buildplate of the item you last selected + item = self._objects_model.getItem(self._last_selected_index) + node = item["node"] + build_plate_number = node.callDecoration("getBuildPlateNumber") + self.setActiveBuildPlate(build_plate_number) # self.buildPlateItemsChanged.emit() # TODO: necessary after setItems? def _calcMaxBuildPlate(self): diff --git a/resources/qml/Menus/ContextMenu.qml b/resources/qml/Menus/ContextMenu.qml index 1a4b421572..b5f51f4d63 100644 --- a/resources/qml/Menus/ContextMenu.qml +++ b/resources/qml/Menus/ContextMenu.qml @@ -47,6 +47,7 @@ Menu { model: Cura.BuildPlateModel MenuItem { + enabled: UM.Selection.hasSelection text: Cura.BuildPlateModel.getItem(index).name; onTriggered: CuraActions.setBuildPlateForSelection(Cura.BuildPlateModel.getItem(index).buildPlateNumber); checkable: true @@ -58,6 +59,7 @@ Menu } MenuItem { + enabled: UM.Selection.hasSelection text: "New build plate"; onTriggered: { CuraActions.setBuildPlateForSelection(Cura.BuildPlateModel.maxBuildPlate + 1); From c1cb86a334b1c6a7d70fa033664073fead69152d Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Mon, 8 Jan 2018 14:00:06 +0100 Subject: [PATCH 14/50] CURA-4525 remove initial 'Unable to slice' --- plugins/CuraEngineBackend/CuraEngineBackend.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/CuraEngineBackend/CuraEngineBackend.py b/plugins/CuraEngineBackend/CuraEngineBackend.py index 249b2f6cbb..ba68687c1e 100755 --- a/plugins/CuraEngineBackend/CuraEngineBackend.py +++ b/plugins/CuraEngineBackend/CuraEngineBackend.py @@ -217,7 +217,8 @@ class CuraEngineBackend(QObject, Backend): self._scene.gcode_list[build_plate_to_be_sliced] = [] Logger.log("d", "Build plate %s has no objects to be sliced, skipping", build_plate_to_be_sliced) if self._build_plates_to_be_sliced: - return self.slice() + self.slice() + return self._stored_layer_data = [] self._stored_optimized_layer_data[build_plate_to_be_sliced] = [] From 584f477b54d08df58d0a8f40ea619d3d4f886e11 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Mon, 8 Jan 2018 14:28:09 +0100 Subject: [PATCH 15/50] CURA-4525 fix deleting last item --- cura/Scene/CuraSceneController.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cura/Scene/CuraSceneController.py b/cura/Scene/CuraSceneController.py index e594752f1e..c3e27ca3dd 100644 --- a/cura/Scene/CuraSceneController.py +++ b/cura/Scene/CuraSceneController.py @@ -45,8 +45,9 @@ class CuraSceneController(QObject): build_plate_number = 0 if self._last_selected_index >= 0: # go to the buildplate of the item you last selected item = self._objects_model.getItem(self._last_selected_index) - node = item["node"] - build_plate_number = node.callDecoration("getBuildPlateNumber") + if "node" in item: + node = item["node"] + build_plate_number = node.callDecoration("getBuildPlateNumber") self.setActiveBuildPlate(build_plate_number) # self.buildPlateItemsChanged.emit() # TODO: necessary after setItems? From d05f4a493b57042b5a9dd08c11a768994b364d92 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Mon, 8 Jan 2018 14:41:39 +0100 Subject: [PATCH 16/50] CURA-4525 fix qml undefined QString --- resources/qml/ObjectsList.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/qml/ObjectsList.qml b/resources/qml/ObjectsList.qml index 87f76774da..489e38e8d7 100644 --- a/resources/qml/ObjectsList.qml +++ b/resources/qml/ObjectsList.qml @@ -138,7 +138,7 @@ Rectangle anchors.left: parent.left anchors.leftMargin: UM.Theme.getSize("default_margin").width width: parent.width - 2 * UM.Theme.getSize("default_margin").width - 30 - text: Cura.ObjectsModel.getItem(index) ? Cura.ObjectsModel.getItem(index).name : ""; + text: (index >= 0) && Cura.ObjectsModel.getItem(index) ? Cura.ObjectsModel.getItem(index).name : ""; color: Cura.ObjectsModel.getItem(index).isSelected ? palette.highlightedText : (Cura.ObjectsModel.getItem(index).isOutsideBuildArea ? palette.mid : palette.text) elide: Text.ElideRight } From c8cef9583e9801b1a4a60c2095654f80df9a0b47 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 8 Jan 2018 16:18:41 +0100 Subject: [PATCH 17/50] rename scene.gcode_list to gcode_dict CURA-4741 With the multi build plate feature, scene.gcode_list is now a dict which stores a list of gcode for a build plate, so it makes more sense to have it renamed to "gcode_dict" because it's not a list. --- .../CuraEngineBackend/CuraEngineBackend.py | 16 ++++++------- plugins/CuraEngineBackend/ProcessGCodeJob.py | 4 +++- plugins/GCodeReader/FlavorParser.py | 5 +++- plugins/GCodeWriter/GCodeWriter.py | 5 +++- .../NetworkClusterPrinterOutputDevice.py | 23 +++++++++++-------- .../NetworkPrinterOutputDevice.py | 2 +- plugins/USBPrinting/USBPrinterOutputDevice.py | 5 +++- 7 files changed, 37 insertions(+), 23 deletions(-) diff --git a/plugins/CuraEngineBackend/CuraEngineBackend.py b/plugins/CuraEngineBackend/CuraEngineBackend.py index ba68687c1e..c612e889a4 100755 --- a/plugins/CuraEngineBackend/CuraEngineBackend.py +++ b/plugins/CuraEngineBackend/CuraEngineBackend.py @@ -205,8 +205,8 @@ class CuraEngineBackend(QObject, Backend): Logger.log("d", " ## Process layers job still busy, trying later") return - if not hasattr(self._scene, "gcode_list"): - self._scene.gcode_list = {} + if not hasattr(self._scene, "gcode_dict"): + self._scene.gcode_dict = {} # see if we really have to slice active_build_plate = Application.getInstance().getBuildPlateModel().activeBuildPlate @@ -214,7 +214,7 @@ class CuraEngineBackend(QObject, Backend): Logger.log("d", "Going to slice build plate [%s]!" % build_plate_to_be_sliced) num_objects = self._numObjects() if build_plate_to_be_sliced not in num_objects or num_objects[build_plate_to_be_sliced] == 0: - self._scene.gcode_list[build_plate_to_be_sliced] = [] + self._scene.gcode_dict[build_plate_to_be_sliced] = [] Logger.log("d", "Build plate %s has no objects to be sliced, skipping", build_plate_to_be_sliced) if self._build_plates_to_be_sliced: self.slice() @@ -234,7 +234,7 @@ class CuraEngineBackend(QObject, Backend): self.processingProgress.emit(0.0) self.backendStateChange.emit(BackendState.NotStarted) - self._scene.gcode_list[build_plate_to_be_sliced] = [] #[] indexed by build plate number + self._scene.gcode_dict[build_plate_to_be_sliced] = [] #[] indexed by build plate number self._slicing = True self.slicingStarted.emit() @@ -393,7 +393,7 @@ class CuraEngineBackend(QObject, Backend): self.backendStateChange.emit(BackendState.Disabled) gcode_list = node.callDecoration("getGCodeList") if gcode_list is not None: - self._scene.gcode_list[node.callDecoration("getBuildPlateNumber")] = gcode_list + self._scene.gcode_dict[node.callDecoration("getBuildPlateNumber")] = gcode_list if self._use_timer == enable_timer: return self._use_timer @@ -560,7 +560,7 @@ class CuraEngineBackend(QObject, Backend): self.backendStateChange.emit(BackendState.Done) self.processingProgress.emit(1.0) - gcode_list = self._scene.gcode_list[self._start_slice_job_build_plate] + gcode_list = self._scene.gcode_dict[self._start_slice_job_build_plate] for index, line in enumerate(gcode_list): replaced = line.replace("{print_time}", str(Application.getInstance().getPrintInformation().currentPrintTime.getDisplayString(DurationFormat.Format.ISO8601))) replaced = replaced.replace("{filament_amount}", str(Application.getInstance().getPrintInformation().materialLengths)) @@ -590,14 +590,14 @@ class CuraEngineBackend(QObject, Backend): # # \param message The protobuf message containing g-code, encoded as UTF-8. def _onGCodeLayerMessage(self, message): - self._scene.gcode_list[self._start_slice_job_build_plate].append(message.data.decode("utf-8", "replace")) + self._scene.gcode_dict[self._start_slice_job_build_plate].append(message.data.decode("utf-8", "replace")) ## Called when a g-code prefix message is received from the engine. # # \param message The protobuf message containing the g-code prefix, # encoded as UTF-8. def _onGCodePrefixMessage(self, message): - self._scene.gcode_list[self._start_slice_job_build_plate].insert(0, message.data.decode("utf-8", "replace")) + self._scene.gcode_dict[self._start_slice_job_build_plate].insert(0, message.data.decode("utf-8", "replace")) ## Creates a new socket connection. def _createSocket(self): diff --git a/plugins/CuraEngineBackend/ProcessGCodeJob.py b/plugins/CuraEngineBackend/ProcessGCodeJob.py index 4974907c30..ed430f8fa9 100644 --- a/plugins/CuraEngineBackend/ProcessGCodeJob.py +++ b/plugins/CuraEngineBackend/ProcessGCodeJob.py @@ -12,4 +12,6 @@ class ProcessGCodeLayerJob(Job): self._message = message def run(self): - self._scene.gcode_list.append(self._message.data.decode("utf-8", "replace")) + active_build_plate_id = Application.getInstance().getBuildPlateModel().activeBuildPlate + gcode_list = self._scene.gcode_dict[active_build_plate_id] + gcode_list.append(self._message.data.decode("utf-8", "replace")) diff --git a/plugins/GCodeReader/FlavorParser.py b/plugins/GCodeReader/FlavorParser.py index fa5d6da243..a05c4e1d63 100644 --- a/plugins/GCodeReader/FlavorParser.py +++ b/plugins/GCodeReader/FlavorParser.py @@ -430,7 +430,10 @@ class FlavorParser: gcode_list_decorator.setGCodeList(gcode_list) scene_node.addDecorator(gcode_list_decorator) - Application.getInstance().getController().getScene().gcode_list = gcode_list + # gcode_dict stores gcode_lists for a number of build plates. + active_build_plate_id = Application.getInstance().getBuildPlateModel().activeBuildPlate + gcode_dict = {active_build_plate_id: gcode_list} + Application.getInstance().getController().getScene().gcode_dict = gcode_dict Logger.log("d", "Finished parsing %s" % file_name) self._message.hide() diff --git a/plugins/GCodeWriter/GCodeWriter.py b/plugins/GCodeWriter/GCodeWriter.py index ad23f2c8ee..f0e5c88f37 100644 --- a/plugins/GCodeWriter/GCodeWriter.py +++ b/plugins/GCodeWriter/GCodeWriter.py @@ -61,7 +61,10 @@ class GCodeWriter(MeshWriter): active_build_plate = Application.getInstance().getBuildPlateModel().activeBuildPlate scene = Application.getInstance().getController().getScene() - gcode_list = getattr(scene, "gcode_list")[active_build_plate] + gcode_dict = getattr(scene, "gcode_dict") + if not gcode_dict: + return False + gcode_list = gcode_dict.get(active_build_plate) if gcode_list: for gcode in gcode_list: stream.write(gcode) diff --git a/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py b/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py index 6eb89d69a4..6665380f45 100644 --- a/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py +++ b/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py @@ -244,8 +244,8 @@ class NetworkClusterPrinterOutputDevice(NetworkPrinterOutputDevice.NetworkPrinte self._request_job = [nodes, file_name, filter_by_machine, file_handler, kwargs] # the build plates to be sent - gcodes = getattr(Application.getInstance().getController().getScene(), "gcode_list") - self._job_list = list(gcodes.keys()) + gcode_dict = getattr(Application.getInstance().getController().getScene(), "gcode_dict") + self._job_list = list(gcode_dict.keys()) Logger.log("d", "build plates to be sent to printer: %s", (self._job_list)) if self._stage != OutputStage.ready: @@ -281,11 +281,14 @@ class NetworkClusterPrinterOutputDevice(NetworkPrinterOutputDevice.NetworkPrinte def sendPrintJob(self): nodes, file_name, filter_by_machine, file_handler, kwargs = self._request_job output_build_plate_number = self._job_list.pop(0) - gcode = getattr(Application.getInstance().getController().getScene(), "gcode_list")[output_build_plate_number] - if not gcode: # Empty build plate + gcode_dict = getattr(Application.getInstance().getController().getScene(), "gcode_dict")[output_build_plate_number] + if not gcode_dict: # Empty build plate Logger.log("d", "Skipping empty job (build plate number %d).", output_build_plate_number) return self.sendPrintJob() + active_build_plate_id = Application.getInstance().getBuildPlateModel().activeBuildPlate + gcode_list = gcode_dict[active_build_plate_id] + self._send_gcode_start = time.time() Logger.log("d", "Sending print job [%s] to host, build plate [%s]..." % (file_name, output_build_plate_number)) @@ -302,7 +305,7 @@ class NetworkClusterPrinterOutputDevice(NetworkPrinterOutputDevice.NetworkPrinte require_printer_name = self._selected_printer["unique_name"] - new_request = self._buildSendPrintJobHttpRequest(require_printer_name, gcode) + new_request = self._buildSendPrintJobHttpRequest(require_printer_name, gcode_list) if new_request is None or self._stage != OutputStage.uploading: return self._request = new_request @@ -310,7 +313,7 @@ class NetworkClusterPrinterOutputDevice(NetworkPrinterOutputDevice.NetworkPrinte self._reply.uploadProgress.connect(self._onUploadProgress) # See _finishedPrintJobPostRequest() - def _buildSendPrintJobHttpRequest(self, require_printer_name, gcode): + def _buildSendPrintJobHttpRequest(self, require_printer_name, gcode_list): api_url = QUrl(self._api_base_uri + "print_jobs/") request = QNetworkRequest(api_url) # Create multipart request and add the g-code. @@ -321,7 +324,7 @@ class NetworkClusterPrinterOutputDevice(NetworkPrinterOutputDevice.NetworkPrinte part.setHeader(QNetworkRequest.ContentDispositionHeader, 'form-data; name="file"; filename="%s"' % (self._file_name)) - compressed_gcode = self._compressGcode(gcode) + compressed_gcode = self._compressGcode(gcode_list) if compressed_gcode is None: return None # User aborted print, so stop trying. @@ -339,7 +342,7 @@ class NetworkClusterPrinterOutputDevice(NetworkPrinterOutputDevice.NetworkPrinte self._addUserAgentHeader(request) return request - def _compressGcode(self, gcode): + def _compressGcode(self, gcode_list): self._compressing_print = True batched_line = "" max_chars_per_line = int(1024 * 1024 / 4) # 1 / 4 MB @@ -354,11 +357,11 @@ class NetworkClusterPrinterOutputDevice(NetworkPrinterOutputDevice.NetworkPrinte self._last_response_time = time.time() return compressed_data - if gcode is None: + if gcode_list is None: Logger.log("e", "Unable to find sliced gcode, returning empty.") return byte_array_file_data - for line in gcode: + for line in gcode_list: if not self._compressing_print: self._progress_message.hide() return None # Stop trying to zip, abort was called. diff --git a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py index de0a06527e..6b8946b755 100755 --- a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py +++ b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py @@ -676,7 +676,7 @@ class NetworkPrinterOutputDevice(PrinterOutputDevice): self._print_finished = True self.writeStarted.emit(self) active_build_plate = Application.getInstance().getBuildPlateModel().activeBuildPlate - self._gcode = getattr(Application.getInstance().getController().getScene(), "gcode_list")[active_build_plate] + self._gcode = getattr(Application.getInstance().getController().getScene(), "gcode_dict")[active_build_plate] print_information = Application.getInstance().getPrintInformation() warnings = [] # There might be multiple things wrong. Keep a list of all the stuff we need to warn about. diff --git a/plugins/USBPrinting/USBPrinterOutputDevice.py b/plugins/USBPrinting/USBPrinterOutputDevice.py index 1930f5402b..f4f5478216 100644 --- a/plugins/USBPrinting/USBPrinterOutputDevice.py +++ b/plugins/USBPrinting/USBPrinterOutputDevice.py @@ -163,7 +163,10 @@ class USBPrinterOutputDevice(PrinterOutputDevice): def startPrint(self): self.writeStarted.emit(self) - gcode_list = getattr( Application.getInstance().getController().getScene(), "gcode_list") + active_build_plate_id = Application.getInstance().getBuildPlateModel().activeBuildPlate + gcode_dict = getattr(Application.getInstance().getController().getScene(), "gcode_dict") + gcode_list = gcode_dict[active_build_plate_id] + self._updateJobState("printing") self.printGCode(gcode_list) From 4c8c4c78da77cb3eb86fe078e4cba5eb62c122fb Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Tue, 9 Jan 2018 09:16:21 +0100 Subject: [PATCH 18/50] CURA-4772 Create a CuraSceneNode instead of a SceneNode when reading a GCode. Avoid creating an empty CuraSceneNode if the node is already an instance of it. --- cura/CuraApplication.py | 4 +++- plugins/GCodeReader/FlavorParser.py | 8 ++++---- plugins/SimulationView/SimulationPass.py | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 8aeeb9c1e8..b28e17f792 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -1432,7 +1432,9 @@ class CuraApplication(QtApplication): target_build_plate = self.getBuildPlateModel().activeBuildPlate if arrange_objects_on_load else -1 for original_node in nodes: - node = CuraSceneNode() # We want our own CuraSceneNode + + # Create a CuraSceneNode just if the original node is not that type + node = original_node if isinstance(original_node, CuraSceneNode) else CuraSceneNode() node.setMeshData(original_node.getMeshData()) node.setSelectable(True) diff --git a/plugins/GCodeReader/FlavorParser.py b/plugins/GCodeReader/FlavorParser.py index fa5d6da243..0cd49e2fca 100644 --- a/plugins/GCodeReader/FlavorParser.py +++ b/plugins/GCodeReader/FlavorParser.py @@ -8,14 +8,14 @@ from UM.Logger import Logger from UM.Math.AxisAlignedBox import AxisAlignedBox from UM.Math.Vector import Vector from UM.Message import Message -from UM.Scene.SceneNode import SceneNode +from cura.Scene.CuraSceneNode import CuraSceneNode from UM.i18n import i18nCatalog from UM.Preferences import Preferences catalog = i18nCatalog("cura") from cura import LayerDataBuilder -from cura import LayerDataDecorator +from cura.LayerDataDecorator import LayerDataDecorator from cura.LayerPolygon import LayerPolygon from cura.Scene.GCodeListDecorator import GCodeListDecorator from cura.Settings.ExtruderManager import ExtruderManager @@ -292,7 +292,7 @@ class FlavorParser: # We obtain the filament diameter from the selected printer to calculate line widths self._filament_diameter = Application.getInstance().getGlobalContainerStack().getProperty("material_diameter", "value") - scene_node = SceneNode() + scene_node = CuraSceneNode() # Override getBoundingBox function of the sceneNode, as this node should return a bounding box, but there is no # real data to calculate it from. scene_node.getBoundingBox = self._getNullBoundingBox @@ -422,7 +422,7 @@ class FlavorParser: material_color_map[0, :] = [0.0, 0.7, 0.9, 1.0] material_color_map[1, :] = [0.7, 0.9, 0.0, 1.0] layer_mesh = self._layer_data_builder.build(material_color_map) - decorator = LayerDataDecorator.LayerDataDecorator() + decorator = LayerDataDecorator() decorator.setLayerData(layer_mesh) scene_node.addDecorator(decorator) diff --git a/plugins/SimulationView/SimulationPass.py b/plugins/SimulationView/SimulationPass.py index b453020ffa..c9c1443bfe 100644 --- a/plugins/SimulationView/SimulationPass.py +++ b/plugins/SimulationView/SimulationPass.py @@ -106,7 +106,7 @@ class SimulationPass(RenderPass): nozzle_node = node nozzle_node.setVisible(False) - elif issubclass(type(node), SceneNode) and (node.getMeshData() or node.callDecoration("isBlockSlicing")) and node.isVisible() and node.callDecoration("getBuildPlateNumber") == active_build_plate: + elif issubclass(type(node), SceneNode) and (node.getMeshData() or node.callDecoration("isBlockSlicing")) and node.isVisible(): layer_data = node.callDecoration("getLayerData") if not layer_data: continue From 117c467829c27833a8e0fbc555114aa243e4f468 Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Tue, 9 Jan 2018 09:39:15 +0100 Subject: [PATCH 19/50] Fix: Per mesh setting combobox did not save selected option CURA-4760 --- .../PerObjectSettingVisibilityHandler.py | 9 +++++++++ plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml | 2 ++ 2 files changed, 11 insertions(+) diff --git a/plugins/PerObjectSettingsTool/PerObjectSettingVisibilityHandler.py b/plugins/PerObjectSettingsTool/PerObjectSettingVisibilityHandler.py index badca13468..c7e4deaaa7 100644 --- a/plugins/PerObjectSettingsTool/PerObjectSettingVisibilityHandler.py +++ b/plugins/PerObjectSettingsTool/PerObjectSettingVisibilityHandler.py @@ -2,6 +2,7 @@ # Cura is released under the terms of the LGPLv3 or higher. from PyQt5.QtCore import QObject, pyqtProperty, pyqtSignal +from UM.FlameProfiler import pyqtSlot from UM.Application import Application from UM.Settings.ContainerRegistry import ContainerRegistry @@ -21,6 +22,7 @@ class PerObjectSettingVisibilityHandler(UM.Settings.Models.SettingVisibilityHand self._selected_object_id = None self._node = None self._stack = None + self._skip_setting = None def setSelectedObjectId(self, id): if id != self._selected_object_id: @@ -36,6 +38,10 @@ class PerObjectSettingVisibilityHandler(UM.Settings.Models.SettingVisibilityHand def selectedObjectId(self): return self._selected_object_id + @pyqtSlot(str) + def setSkipSetting(self, setting_name): + self._skip_setting = setting_name + def setVisible(self, visible): if not self._node: return @@ -50,6 +56,9 @@ class PerObjectSettingVisibilityHandler(UM.Settings.Models.SettingVisibilityHand # Remove all instances that are not in visibility list for instance in all_instances: + # exceptionally skip setting + if self._skip_setting is not None and self._skip_setting == instance.definition.key: + continue if instance.definition.key not in visible: settings.removeInstance(instance.definition.key) visibility_changed = True diff --git a/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml b/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml index 5bdb6d4cb0..2b7b6cd541 100644 --- a/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml +++ b/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml @@ -324,6 +324,8 @@ Item { // force updating the model to sync it with addedSettingsModel if(visible) { + // Set skip setting, it will prevent from restting selected mesh_type + contents.model.visibilityHandler.setSkipSetting(meshTypeSelection.model.get(meshTypeSelection.currentIndex).type) listview.model.forceUpdate() } } From a85fd0c996bb49392a7595d63225130a73651f5b Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Tue, 9 Jan 2018 10:26:13 +0100 Subject: [PATCH 20/50] Stop ignoring post processing plugin --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index 71e83433cf..a91d3f9377 100644 --- a/.gitignore +++ b/.gitignore @@ -47,7 +47,6 @@ plugins/Doodle3D-cura-plugin plugins/FlatProfileExporter plugins/GodMode plugins/OctoPrintPlugin -plugins/PostProcessingPlugin plugins/ProfileFlattener plugins/X3GWriter From 1f2007554de56741b516373362ec77d02ef9caee Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Tue, 9 Jan 2018 10:27:28 +0100 Subject: [PATCH 21/50] Add post processing source files to main repo --- plugins/PostProcessingPlugin | 1 + 1 file changed, 1 insertion(+) create mode 160000 plugins/PostProcessingPlugin diff --git a/plugins/PostProcessingPlugin b/plugins/PostProcessingPlugin new file mode 160000 index 0000000000..476c04484f --- /dev/null +++ b/plugins/PostProcessingPlugin @@ -0,0 +1 @@ +Subproject commit 476c04484f998b4defe42e62d8925d66a626973e From 9c9c46aade61b26af21fb50b2a7c3d80d856f085 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Tue, 9 Jan 2018 10:30:02 +0100 Subject: [PATCH 22/50] Remove submodule --- plugins/PostProcessingPlugin | 1 - 1 file changed, 1 deletion(-) delete mode 160000 plugins/PostProcessingPlugin diff --git a/plugins/PostProcessingPlugin b/plugins/PostProcessingPlugin deleted file mode 160000 index 476c04484f..0000000000 --- a/plugins/PostProcessingPlugin +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 476c04484f998b4defe42e62d8925d66a626973e From 6c0fb110fe842758c7cc20dae7edc055d5c8ad8c Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Tue, 9 Jan 2018 10:31:12 +0100 Subject: [PATCH 23/50] Add post processing source files --- .../PostProcessingPlugin.py | 206 +++++++ .../PostProcessingPlugin.qml | 501 ++++++++++++++++++ plugins/PostProcessingPlugin/README.md | 2 + plugins/PostProcessingPlugin/Script.py | 111 ++++ plugins/PostProcessingPlugin/__init__.py | 11 + plugins/PostProcessingPlugin/plugin.json | 8 + .../PostProcessingPlugin/postprocessing.svg | 47 ++ .../scripts/BQ_PauseAtHeight.py | 48 ++ .../scripts/ColorChange.py | 76 +++ .../scripts/ExampleScript.py | 43 ++ .../scripts/PauseAtHeight.py | 221 ++++++++ .../scripts/PauseAtHeightforRepetier.py | 169 ++++++ .../scripts/SearchAndReplace.py | 56 ++ .../PostProcessingPlugin/scripts/Stretch.py | 469 ++++++++++++++++ .../PostProcessingPlugin/scripts/TweakAtZ.py | 495 +++++++++++++++++ 15 files changed, 2463 insertions(+) create mode 100644 plugins/PostProcessingPlugin/PostProcessingPlugin.py create mode 100644 plugins/PostProcessingPlugin/PostProcessingPlugin.qml create mode 100644 plugins/PostProcessingPlugin/README.md create mode 100644 plugins/PostProcessingPlugin/Script.py create mode 100644 plugins/PostProcessingPlugin/__init__.py create mode 100644 plugins/PostProcessingPlugin/plugin.json create mode 100644 plugins/PostProcessingPlugin/postprocessing.svg create mode 100644 plugins/PostProcessingPlugin/scripts/BQ_PauseAtHeight.py create mode 100644 plugins/PostProcessingPlugin/scripts/ColorChange.py create mode 100644 plugins/PostProcessingPlugin/scripts/ExampleScript.py create mode 100644 plugins/PostProcessingPlugin/scripts/PauseAtHeight.py create mode 100644 plugins/PostProcessingPlugin/scripts/PauseAtHeightforRepetier.py create mode 100644 plugins/PostProcessingPlugin/scripts/SearchAndReplace.py create mode 100644 plugins/PostProcessingPlugin/scripts/Stretch.py create mode 100644 plugins/PostProcessingPlugin/scripts/TweakAtZ.py diff --git a/plugins/PostProcessingPlugin/PostProcessingPlugin.py b/plugins/PostProcessingPlugin/PostProcessingPlugin.py new file mode 100644 index 0000000000..657e5c5387 --- /dev/null +++ b/plugins/PostProcessingPlugin/PostProcessingPlugin.py @@ -0,0 +1,206 @@ +# Copyright (c) 2015 Jaime van Kessel, Ultimaker B.V. +# The PostProcessingPlugin is released under the terms of the AGPLv3 or higher. +from PyQt5.QtCore import QObject, pyqtProperty, pyqtSignal, pyqtSlot + +from UM.PluginRegistry import PluginRegistry +from UM.Resources import Resources +from UM.Application import Application +from UM.Extension import Extension +from UM.Logger import Logger + +import os.path +import pkgutil +import sys +import importlib.util + +from UM.i18n import i18nCatalog +i18n_catalog = i18nCatalog("cura") + + +## The post processing plugin is an Extension type plugin that enables pre-written scripts to post process generated +# g-code files. +class PostProcessingPlugin(QObject, Extension): + def __init__(self, parent = None): + super().__init__(parent) + self.addMenuItem(i18n_catalog.i18n("Modify G-Code"), self.showPopup) + self._view = None + + # Loaded scripts are all scripts that can be used + self._loaded_scripts = {} + self._script_labels = {} + + # Script list contains instances of scripts in loaded_scripts. + # There can be duplicates, which will be executed in sequence. + self._script_list = [] + self._selected_script_index = -1 + + Application.getInstance().getOutputDeviceManager().writeStarted.connect(self.execute) + + selectedIndexChanged = pyqtSignal() + @pyqtProperty("QVariant", notify = selectedIndexChanged) + def selectedScriptDefinitionId(self): + try: + return self._script_list[self._selected_script_index].getDefinitionId() + except: + return "" + + @pyqtProperty("QVariant", notify=selectedIndexChanged) + def selectedScriptStackId(self): + try: + return self._script_list[self._selected_script_index].getStackId() + except: + return "" + + ## Execute all post-processing scripts on the gcode. + def execute(self, output_device): + scene = Application.getInstance().getController().getScene() + gcode_dict = getattr(scene, "gcode_dict") + if not gcode_dict: + return + + # get gcode list for the active build plate + active_build_plate_id = Application.getInstance().getBuildPlateModel().activeBuildPlate + gcode_list = gcode_dict[active_build_plate_id] + if not gcode_list: + return + + if ";POSTPROCESSED" not in gcode_list[0]: + for script in self._script_list: + try: + gcode_list = script.execute(gcode_list) + except Exception: + Logger.logException("e", "Exception in post-processing script.") + if len(self._script_list): # Add comment to g-code if any changes were made. + gcode_list[0] += ";POSTPROCESSED\n" + gcode_dict[active_build_plate_id] = gcode_list + setattr(scene, "gcode_dict", gcode_dict) + else: + Logger.log("e", "Already post processed") + + @pyqtSlot(int) + def setSelectedScriptIndex(self, index): + self._selected_script_index = index + self.selectedIndexChanged.emit() + + @pyqtProperty(int, notify = selectedIndexChanged) + def selectedScriptIndex(self): + return self._selected_script_index + + @pyqtSlot(int, int) + def moveScript(self, index, new_index): + if new_index < 0 or new_index > len(self._script_list) - 1: + return # nothing needs to be done + else: + # Magical switch code. + self._script_list[new_index], self._script_list[index] = self._script_list[index], self._script_list[new_index] + self.scriptListChanged.emit() + self.selectedIndexChanged.emit() #Ensure that settings are updated + self._propertyChanged() + + ## Remove a script from the active script list by index. + @pyqtSlot(int) + def removeScriptByIndex(self, index): + self._script_list.pop(index) + if len(self._script_list) - 1 < self._selected_script_index: + self._selected_script_index = len(self._script_list) - 1 + self.scriptListChanged.emit() + self.selectedIndexChanged.emit() # Ensure that settings are updated + self._propertyChanged() + + ## Load all scripts from provided path. + # This should probably only be done on init. + # \param path Path to check for scripts. + def loadAllScripts(self, path): + scripts = pkgutil.iter_modules(path = [path]) + for loader, script_name, ispkg in scripts: + # Iterate over all scripts. + if script_name not in sys.modules: + spec = importlib.util.spec_from_file_location(__name__ + "." + script_name, os.path.join(path, script_name + ".py")) + loaded_script = importlib.util.module_from_spec(spec) + spec.loader.exec_module(loaded_script) + sys.modules[script_name] = loaded_script + + loaded_class = getattr(loaded_script, script_name) + temp_object = loaded_class() + Logger.log("d", "Begin loading of script: %s", script_name) + try: + setting_data = temp_object.getSettingData() + if "name" in setting_data and "key" in setting_data: + self._script_labels[setting_data["key"]] = setting_data["name"] + self._loaded_scripts[setting_data["key"]] = loaded_class + else: + Logger.log("w", "Script %s.py has no name or key", script_name) + self._script_labels[script_name] = script_name + self._loaded_scripts[script_name] = loaded_class + except AttributeError: + Logger.log("e", "Script %s.py is not a recognised script type. Ensure it inherits Script", script_name) + except NotImplementedError: + Logger.log("e", "Script %s.py has no implemented settings", script_name) + self.loadedScriptListChanged.emit() + + loadedScriptListChanged = pyqtSignal() + @pyqtProperty("QVariantList", notify = loadedScriptListChanged) + def loadedScriptList(self): + return sorted(list(self._loaded_scripts.keys())) + + @pyqtSlot(str, result = str) + def getScriptLabelByKey(self, key): + return self._script_labels[key] + + scriptListChanged = pyqtSignal() + @pyqtProperty("QVariantList", notify = scriptListChanged) + def scriptList(self): + script_list = [script.getSettingData()["key"] for script in self._script_list] + return script_list + + @pyqtSlot(str) + def addScriptToList(self, key): + Logger.log("d", "Adding script %s to list.", key) + new_script = self._loaded_scripts[key]() + self._script_list.append(new_script) + self.setSelectedScriptIndex(len(self._script_list) - 1) + self.scriptListChanged.emit() + self._propertyChanged() + + ## Creates the view used by show popup. The view is saved because of the fairly aggressive garbage collection. + def _createView(self): + Logger.log("d", "Creating post processing plugin view.") + + ## Load all scripts in the scripts folders + for root in [PluginRegistry.getInstance().getPluginPath("PostProcessingPlugin"), Resources.getStoragePath(Resources.Preferences)]: + try: + path = os.path.join(root, "scripts") + if not os.path.isdir(path): + try: + os.makedirs(path) + except OSError: + Logger.log("w", "Unable to create a folder for scripts: " + path) + continue + + self.loadAllScripts(path) + except Exception as e: + Logger.logException("e", "Exception occurred while loading post processing plugin: {error_msg}".format(error_msg = str(e))) + + # Create the plugin dialog component + path = os.path.join(PluginRegistry.getInstance().getPluginPath("PostProcessingPlugin"), "PostProcessingPlugin.qml") + self._view = Application.getInstance().createQmlComponent(path, {"manager": self}) + Logger.log("d", "Post processing view created.") + + # Create the save button component + Application.getInstance().addAdditionalComponent("saveButton", self._view.findChild(QObject, "postProcessingSaveAreaButton")) + + ## Show the (GUI) popup of the post processing plugin. + def showPopup(self): + if self._view is None: + self._createView() + self._view.show() + + ## Property changed: trigger re-slice + # To do this we use the global container stack propertyChanged. + # Re-slicing is necessary for setting changes in this plugin, because the changes + # are applied only once per "fresh" gcode + def _propertyChanged(self): + global_container_stack = Application.getInstance().getGlobalContainerStack() + global_container_stack.propertyChanged.emit("post_processing_plugin", "value") + + diff --git a/plugins/PostProcessingPlugin/PostProcessingPlugin.qml b/plugins/PostProcessingPlugin/PostProcessingPlugin.qml new file mode 100644 index 0000000000..d64d60a04a --- /dev/null +++ b/plugins/PostProcessingPlugin/PostProcessingPlugin.qml @@ -0,0 +1,501 @@ +// Copyright (c) 2015 Jaime van Kessel, Ultimaker B.V. +// The PostProcessingPlugin is released under the terms of the AGPLv3 or higher. + +import QtQuick 2.2 +import QtQuick.Controls 1.1 +import QtQuick.Controls.Styles 1.1 +import QtQuick.Layouts 1.1 +import QtQuick.Dialogs 1.1 +import QtQuick.Window 2.2 + +import UM 1.2 as UM +import Cura 1.0 as Cura + +UM.Dialog +{ + id: dialog + + title: catalog.i18nc("@title:window", "Post Processing Plugin") + width: 700 * screenScaleFactor; + height: 500 * screenScaleFactor; + minimumWidth: 400 * screenScaleFactor; + minimumHeight: 250 * screenScaleFactor; + + Item + { + UM.I18nCatalog{id: catalog; name:"cura"} + id: base + property int columnWidth: Math.floor((base.width / 2) - UM.Theme.getSize("default_margin").width) + property int textMargin: Math.floor(UM.Theme.getSize("default_margin").width / 2) + property string activeScriptName + SystemPalette{ id: palette } + SystemPalette{ id: disabledPalette; colorGroup: SystemPalette.Disabled } + anchors.fill: parent + + ExclusiveGroup + { + id: selectedScriptGroup + } + Item + { + id: activeScripts + anchors.left: parent.left + width: base.columnWidth + height: parent.height + + Label + { + id: activeScriptsHeader + text: catalog.i18nc("@label", "Post Processing Scripts") + anchors.top: parent.top + anchors.topMargin: base.textMargin + anchors.left: parent.left + anchors.leftMargin: base.textMargin + anchors.right: parent.right + anchors.rightMargin: base.textMargin + font: UM.Theme.getFont("large") + } + ListView + { + id: activeScriptsList + anchors.top: activeScriptsHeader.bottom + anchors.topMargin: base.textMargin + anchors.left: parent.left + anchors.leftMargin: UM.Theme.getSize("default_margin").width + anchors.right: parent.right + anchors.rightMargin: base.textMargin + height: childrenRect.height + model: manager.scriptList + delegate: Item + { + width: parent.width + height: activeScriptButton.height + Button + { + id: activeScriptButton + text: manager.getScriptLabelByKey(modelData.toString()) + exclusiveGroup: selectedScriptGroup + checkable: true + checked: { + if (manager.selectedScriptIndex == index) + { + base.activeScriptName = manager.getScriptLabelByKey(modelData.toString()) + return true + } + else + { + return false + } + } + onClicked: + { + forceActiveFocus() + manager.setSelectedScriptIndex(index) + base.activeScriptName = manager.getScriptLabelByKey(modelData.toString()) + } + width: parent.width + height: UM.Theme.getSize("setting").height + style: ButtonStyle + { + background: Rectangle + { + color: activeScriptButton.checked ? palette.highlight : "transparent" + width: parent.width + height: parent.height + } + label: Label + { + wrapMode: Text.Wrap + text: control.text + color: activeScriptButton.checked ? palette.highlightedText : palette.text + } + } + } + Button + { + id: removeButton + text: "x" + width: 20 * screenScaleFactor + height: 20 * screenScaleFactor + anchors.right:parent.right + anchors.rightMargin: base.textMargin + anchors.verticalCenter: parent.verticalCenter + onClicked: manager.removeScriptByIndex(index) + style: ButtonStyle + { + label: Item + { + UM.RecolorImage + { + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + width: Math.floor(control.width / 2.7) + height: Math.floor(control.height / 2.7) + sourceSize.width: width + sourceSize.height: width + color: palette.text + source: UM.Theme.getIcon("cross1") + } + } + } + } + Button + { + id: downButton + text: "" + anchors.right: removeButton.left + anchors.verticalCenter: parent.verticalCenter + enabled: index != manager.scriptList.length - 1 + width: 20 * screenScaleFactor + height: 20 * screenScaleFactor + onClicked: + { + if (manager.selectedScriptIndex == index) + { + manager.setSelectedScriptIndex(index + 1) + } + return manager.moveScript(index, index + 1) + } + style: ButtonStyle + { + label: Item + { + UM.RecolorImage + { + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + width: Math.floor(control.width / 2.5) + height: Math.floor(control.height / 2.5) + sourceSize.width: width + sourceSize.height: width + color: control.enabled ? palette.text : disabledPalette.text + source: UM.Theme.getIcon("arrow_bottom") + } + } + } + } + Button + { + id: upButton + text: "" + enabled: index != 0 + width: 20 * screenScaleFactor + height: 20 * screenScaleFactor + anchors.right: downButton.left + anchors.verticalCenter: parent.verticalCenter + onClicked: + { + if (manager.selectedScriptIndex == index) + { + manager.setSelectedScriptIndex(index - 1) + } + return manager.moveScript(index, index - 1) + } + style: ButtonStyle + { + label: Item + { + UM.RecolorImage + { + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + width: Math.floor(control.width / 2.5) + height: Math.floor(control.height / 2.5) + sourceSize.width: width + sourceSize.height: width + color: control.enabled ? palette.text : disabledPalette.text + source: UM.Theme.getIcon("arrow_top") + } + } + } + } + } + } + Button + { + id: addButton + text: catalog.i18nc("@action", "Add a script") + anchors.left: parent.left + anchors.leftMargin: base.textMargin + anchors.top: activeScriptsList.bottom + anchors.topMargin: base.textMargin + menu: scriptsMenu + style: ButtonStyle + { + label: Label + { + text: control.text + } + } + } + Menu + { + id: scriptsMenu + + Instantiator + { + model: manager.loadedScriptList + + MenuItem + { + text: manager.getScriptLabelByKey(modelData.toString()) + onTriggered: manager.addScriptToList(modelData.toString()) + } + + onObjectAdded: scriptsMenu.insertItem(index, object); + onObjectRemoved: scriptsMenu.removeItem(object); + } + } + } + + Rectangle + { + color: UM.Theme.getColor("sidebar") + anchors.left: activeScripts.right + anchors.leftMargin: UM.Theme.getSize("default_margin").width + anchors.right: parent.right + height: parent.height + id: settingsPanel + + Label + { + id: scriptSpecsHeader + text: manager.selectedScriptIndex == -1 ? catalog.i18nc("@label", "Settings") : base.activeScriptName + anchors.top: parent.top + anchors.topMargin: base.textMargin + anchors.left: parent.left + anchors.leftMargin: base.textMargin + anchors.right: parent.right + anchors.rightMargin: base.textMargin + height: 20 * screenScaleFactor + font: UM.Theme.getFont("large") + color: UM.Theme.getColor("text") + } + + ScrollView + { + id: scrollView + anchors.top: scriptSpecsHeader.bottom + anchors.topMargin: settingsPanel.textMargin + anchors.left: parent.left + anchors.right: parent.right + anchors.bottom: parent.bottom + visible: manager.selectedScriptDefinitionId != "" + style: UM.Theme.styles.scrollview; + + ListView + { + id: listview + spacing: UM.Theme.getSize("default_lining").height + model: UM.SettingDefinitionsModel + { + id: definitionsModel; + containerId: manager.selectedScriptDefinitionId + showAll: true + } + delegate:Loader + { + id: settingLoader + + width: parent.width + height: + { + if(provider.properties.enabled == "True") + { + if(model.type != undefined) + { + return UM.Theme.getSize("section").height; + } + else + { + return 0; + } + } + else + { + return 0; + } + + } + Behavior on height { NumberAnimation { duration: 100 } } + opacity: provider.properties.enabled == "True" ? 1 : 0 + Behavior on opacity { NumberAnimation { duration: 100 } } + enabled: opacity > 0 + property var definition: model + property var settingDefinitionsModel: definitionsModel + property var propertyProvider: provider + property var globalPropertyProvider: inheritStackProvider + + //Qt5.4.2 and earlier has a bug where this causes a crash: https://bugreports.qt.io/browse/QTBUG-35989 + //In addition, while it works for 5.5 and higher, the ordering of the actual combo box drop down changes, + //causing nasty issues when selecting different options. So disable asynchronous loading of enum type completely. + asynchronous: model.type != "enum" && model.type != "extruder" + + onLoaded: { + settingLoader.item.showRevertButton = false + settingLoader.item.showInheritButton = false + settingLoader.item.showLinkedSettingIcon = false + settingLoader.item.doDepthIndentation = true + settingLoader.item.doQualityUserSettingEmphasis = false + } + + sourceComponent: + { + switch(model.type) + { + case "int": + return settingTextField + case "float": + return settingTextField + case "enum": + return settingComboBox + case "extruder": + return settingExtruder + case "bool": + return settingCheckBox + case "str": + return settingTextField + case "category": + return settingCategory + default: + return settingUnknown + } + } + + UM.SettingPropertyProvider + { + id: provider + containerStackId: manager.selectedScriptStackId + key: model.key ? model.key : "None" + watchedProperties: [ "value", "enabled", "state", "validationState" ] + storeIndex: 0 + } + + // Specialty provider that only watches global_inherits (we cant filter on what property changed we get events + // so we bypass that to make a dedicated provider). + UM.SettingPropertyProvider + { + id: inheritStackProvider + containerStackId: Cura.MachineManager.activeMachineId + key: model.key ? model.key : "None" + watchedProperties: [ "limit_to_extruder" ] + } + + Connections + { + target: item + + onShowTooltip: + { + tooltip.text = text; + var position = settingLoader.mapToItem(settingsPanel, settingsPanel.x, 0); + tooltip.show(position); + tooltip.target.x = position.x + 1 + } + + onHideTooltip: + { + tooltip.hide(); + } + } + + } + } + } + } + + Cura.SidebarTooltip + { + id: tooltip + } + + Component + { + id: settingTextField; + + Cura.SettingTextField { } + } + + Component + { + id: settingComboBox; + + Cura.SettingComboBox { } + } + + Component + { + id: settingExtruder; + + Cura.SettingExtruder { } + } + + Component + { + id: settingCheckBox; + + Cura.SettingCheckBox { } + } + + Component + { + id: settingCategory; + + Cura.SettingCategory { } + } + + Component + { + id: settingUnknown; + + Cura.SettingUnknown { } + } + } + rightButtons: Button + { + text: catalog.i18nc("@action:button", "Close") + iconName: "dialog-close" + onClicked: dialog.accept() + } + + Button { + objectName: "postProcessingSaveAreaButton" + visible: activeScriptsList.count > 0 + height: UM.Theme.getSize("save_button_save_to_button").height + width: height + tooltip: catalog.i18nc("@info:tooltip", "Change active post-processing scripts") + onClicked: dialog.show() + + style: ButtonStyle { + background: Rectangle { + id: deviceSelectionIcon + border.width: UM.Theme.getSize("default_lining").width + border.color: !control.enabled ? UM.Theme.getColor("action_button_disabled_border") : + control.pressed ? UM.Theme.getColor("action_button_active_border") : + control.hovered ? UM.Theme.getColor("action_button_hovered_border") : UM.Theme.getColor("action_button_border") + color: !control.enabled ? UM.Theme.getColor("action_button_disabled") : + control.pressed ? UM.Theme.getColor("action_button_active") : + control.hovered ? UM.Theme.getColor("action_button_hovered") : UM.Theme.getColor("action_button") + Behavior on color { ColorAnimation { duration: 50; } } + anchors.left: parent.left + anchors.leftMargin: Math.floor(UM.Theme.getSize("save_button_text_margin").width / 2); + width: parent.height + height: parent.height + + UM.RecolorImage { + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + width: Math.floor(parent.width / 2) + height: Math.floor(parent.height / 2) + sourceSize.width: width + sourceSize.height: height + color: !control.enabled ? UM.Theme.getColor("action_button_disabled_text") : + control.pressed ? UM.Theme.getColor("action_button_active_text") : + control.hovered ? UM.Theme.getColor("action_button_hovered_text") : UM.Theme.getColor("action_button_text"); + source: "postprocessing.svg" + } + } + label: Label{ } + } + } +} \ No newline at end of file diff --git a/plugins/PostProcessingPlugin/README.md b/plugins/PostProcessingPlugin/README.md new file mode 100644 index 0000000000..988f40007d --- /dev/null +++ b/plugins/PostProcessingPlugin/README.md @@ -0,0 +1,2 @@ +# PostProcessingPlugin +A post processing plugin for Cura diff --git a/plugins/PostProcessingPlugin/Script.py b/plugins/PostProcessingPlugin/Script.py new file mode 100644 index 0000000000..7d603ba11f --- /dev/null +++ b/plugins/PostProcessingPlugin/Script.py @@ -0,0 +1,111 @@ +# Copyright (c) 2015 Jaime van Kessel +# Copyright (c) 2017 Ultimaker B.V. +# The PostProcessingPlugin is released under the terms of the AGPLv3 or higher. +from UM.Logger import Logger +from UM.Signal import Signal, signalemitter +from UM.i18n import i18nCatalog + +# Setting stuff import +from UM.Application import Application +from UM.Settings.ContainerStack import ContainerStack +from UM.Settings.InstanceContainer import InstanceContainer +from UM.Settings.DefinitionContainer import DefinitionContainer +from UM.Settings.ContainerRegistry import ContainerRegistry + +import re +import json +import collections +i18n_catalog = i18nCatalog("cura") + + +## Base class for scripts. All scripts should inherit the script class. +@signalemitter +class Script: + def __init__(self): + super().__init__() + self._settings = None + self._stack = None + + setting_data = self.getSettingData() + self._stack = ContainerStack(stack_id = str(id(self))) + self._stack.setDirty(False) # This stack does not need to be saved. + + + ## Check if the definition of this script already exists. If not, add it to the registry. + if "key" in setting_data: + definitions = ContainerRegistry.getInstance().findDefinitionContainers(id = setting_data["key"]) + if definitions: + # Definition was found + self._definition = definitions[0] + else: + self._definition = DefinitionContainer(setting_data["key"]) + self._definition.deserialize(json.dumps(setting_data)) + ContainerRegistry.getInstance().addContainer(self._definition) + self._stack.addContainer(self._definition) + self._instance = InstanceContainer(container_id="ScriptInstanceContainer") + self._instance.setDefinition(self._definition.getId()) + self._instance.addMetaDataEntry("setting_version", self._definition.getMetaDataEntry("setting_version", default = 0)) + self._stack.addContainer(self._instance) + self._stack.propertyChanged.connect(self._onPropertyChanged) + + ContainerRegistry.getInstance().addContainer(self._stack) + + settingsLoaded = Signal() + valueChanged = Signal() # Signal emitted whenever a value of a setting is changed + + def _onPropertyChanged(self, key, property_name): + if property_name == "value": + self.valueChanged.emit() + + # Property changed: trigger reslice + # To do this we use the global container stack propertyChanged. + # Reslicing is necessary for setting changes in this plugin, because the changes + # are applied only once per "fresh" gcode + global_container_stack = Application.getInstance().getGlobalContainerStack() + global_container_stack.propertyChanged.emit(key, property_name) + + ## Needs to return a dict that can be used to construct a settingcategory file. + # See the example script for an example. + # It follows the same style / guides as the Uranium settings. + # Scripts can either override getSettingData directly, or use getSettingDataString + # to return a string that will be parsed as json. The latter has the benefit over + # returning a dict in that the order of settings is maintained. + def getSettingData(self): + setting_data = self.getSettingDataString() + if type(setting_data) == str: + setting_data = json.loads(setting_data, object_pairs_hook = collections.OrderedDict) + return setting_data + + def getSettingDataString(self): + raise NotImplementedError() + + def getDefinitionId(self): + if self._stack: + return self._stack.getBottom().getId() + + def getStackId(self): + if self._stack: + return self._stack.getId() + + ## Convenience function that retrieves value of a setting from the stack. + def getSettingValueByKey(self, key): + return self._stack.getProperty(key, "value") + + ## Convenience function that finds the value in a line of g-code. + # When requesting key = x from line "G1 X100" the value 100 is returned. + def getValue(self, line, key, default = None): + if not key in line or (';' in line and line.find(key) > line.find(';')): + return default + sub_part = line[line.find(key) + 1:] + m = re.search('^-?[0-9]+\.?[0-9]*', sub_part) + if m is None: + return default + try: + return float(m.group(0)) + except: + return default + + ## This is called when the script is executed. + # It gets a list of g-code strings and needs to return a (modified) list. + def execute(self, data): + raise NotImplementedError() diff --git a/plugins/PostProcessingPlugin/__init__.py b/plugins/PostProcessingPlugin/__init__.py new file mode 100644 index 0000000000..85f1126136 --- /dev/null +++ b/plugins/PostProcessingPlugin/__init__.py @@ -0,0 +1,11 @@ +# Copyright (c) 2015 Jaime van Kessel, Ultimaker B.V. +# The PostProcessingPlugin is released under the terms of the AGPLv3 or higher. + +from . import PostProcessingPlugin +from UM.i18n import i18nCatalog +catalog = i18nCatalog("cura") +def getMetaData(): + return {} + +def register(app): + return {"extension": PostProcessingPlugin.PostProcessingPlugin()} \ No newline at end of file diff --git a/plugins/PostProcessingPlugin/plugin.json b/plugins/PostProcessingPlugin/plugin.json new file mode 100644 index 0000000000..ebfef8145a --- /dev/null +++ b/plugins/PostProcessingPlugin/plugin.json @@ -0,0 +1,8 @@ +{ + "name": "Post Processing", + "author": "Ultimaker", + "version": "2.2", + "api": 4, + "description": "Extension that allows for user created scripts for post processing", + "catalog": "cura" +} \ No newline at end of file diff --git a/plugins/PostProcessingPlugin/postprocessing.svg b/plugins/PostProcessingPlugin/postprocessing.svg new file mode 100644 index 0000000000..f55face4a9 --- /dev/null +++ b/plugins/PostProcessingPlugin/postprocessing.svg @@ -0,0 +1,47 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/plugins/PostProcessingPlugin/scripts/BQ_PauseAtHeight.py b/plugins/PostProcessingPlugin/scripts/BQ_PauseAtHeight.py new file mode 100644 index 0000000000..fb59378206 --- /dev/null +++ b/plugins/PostProcessingPlugin/scripts/BQ_PauseAtHeight.py @@ -0,0 +1,48 @@ +from ..Script import Script +class BQ_PauseAtHeight(Script): + def __init__(self): + super().__init__() + + def getSettingDataString(self): + return """{ + "name":"Pause at height (BQ Printers)", + "key": "BQ_PauseAtHeight", + "metadata":{}, + "version": 2, + "settings": + { + "pause_height": + { + "label": "Pause height", + "description": "At what height should the pause occur", + "unit": "mm", + "type": "float", + "default_value": 5.0 + } + } + }""" + + def execute(self, data): + x = 0. + y = 0. + current_z = 0. + pause_z = self.getSettingValueByKey("pause_height") + for layer in data: + lines = layer.split("\n") + for line in lines: + if self.getValue(line, 'G') == 1 or self.getValue(line, 'G') == 0: + current_z = self.getValue(line, 'Z') + if current_z != None: + if current_z >= pause_z: + prepend_gcode = ";TYPE:CUSTOM\n" + prepend_gcode += "; -- Pause at height (%.2f mm) --\n" % pause_z + + # Insert Pause gcode + prepend_gcode += "M25 ; Pauses the print and waits for the user to resume it\n" + + index = data.index(layer) + layer = prepend_gcode + layer + data[index] = layer # Override the data of this layer with the modified data + return data + break + return data diff --git a/plugins/PostProcessingPlugin/scripts/ColorChange.py b/plugins/PostProcessingPlugin/scripts/ColorChange.py new file mode 100644 index 0000000000..8db45f4033 --- /dev/null +++ b/plugins/PostProcessingPlugin/scripts/ColorChange.py @@ -0,0 +1,76 @@ +# This PostProcessing Plugin script is released +# under the terms of the AGPLv3 or higher + +from ..Script import Script +#from UM.Logger import Logger +# from cura.Settings.ExtruderManager import ExtruderManager + +class ColorChange(Script): + def __init__(self): + super().__init__() + + def getSettingDataString(self): + return """{ + "name":"Color Change", + "key": "ColorChange", + "metadata": {}, + "version": 2, + "settings": + { + "layer_number": + { + "label": "Layer", + "description": "At what layer should color change occur. This will be before the layer starts printing. Specify multiple color changes with a comma.", + "unit": "", + "type": "str", + "default_value": "1" + }, + + "initial_retract": + { + "label": "Initial Retraction", + "description": "Initial filament retraction distance", + "unit": "mm", + "type": "float", + "default_value": 300.0 + }, + "later_retract": + { + "label": "Later Retraction Distance", + "description": "Later filament retraction distance for removal", + "unit": "mm", + "type": "float", + "default_value": 30.0 + } + } + }""" + + def execute(self, data: list): + + """data is a list. Each index contains a layer""" + layer_nums = self.getSettingValueByKey("layer_number") + initial_retract = self.getSettingValueByKey("initial_retract") + later_retract = self.getSettingValueByKey("later_retract") + + color_change = "M600" + + if initial_retract is not None and initial_retract > 0.: + color_change = color_change + (" E%.2f" % initial_retract) + + if later_retract is not None and later_retract > 0.: + color_change = color_change + (" L%.2f" % later_retract) + + color_change = color_change + " ; Generated by ColorChange plugin" + + layer_targets = layer_nums.split(',') + if len(layer_targets) > 0: + for layer_num in layer_targets: + layer_num = int( layer_num.strip() ) + if layer_num < len(data): + layer = data[ layer_num - 1 ] + lines = layer.split("\n") + lines.insert(2, color_change ) + final_line = "\n".join( lines ) + data[ layer_num - 1 ] = final_line + + return data diff --git a/plugins/PostProcessingPlugin/scripts/ExampleScript.py b/plugins/PostProcessingPlugin/scripts/ExampleScript.py new file mode 100644 index 0000000000..416a5f5404 --- /dev/null +++ b/plugins/PostProcessingPlugin/scripts/ExampleScript.py @@ -0,0 +1,43 @@ +# Copyright (c) 2015 Jaime van Kessel, Ultimaker B.V. +# The PostProcessingPlugin is released under the terms of the AGPLv3 or higher. +from ..Script import Script + +class ExampleScript(Script): + def __init__(self): + super().__init__() + + def getSettingDataString(self): + return """{ + "name":"Example script", + "key": "ExampleScript", + "metadata": {}, + "version": 2, + "settings": + { + "test": + { + "label": "Test", + "description": "None", + "unit": "mm", + "type": "float", + "default_value": 0.5, + "minimum_value": "0", + "minimum_value_warning": "0.1", + "maximum_value_warning": "1" + }, + "derp": + { + "label": "zomg", + "description": "afgasgfgasfgasf", + "unit": "mm", + "type": "float", + "default_value": 0.5, + "minimum_value": "0", + "minimum_value_warning": "0.1", + "maximum_value_warning": "1" + } + } + }""" + + def execute(self, data): + return data \ No newline at end of file diff --git a/plugins/PostProcessingPlugin/scripts/PauseAtHeight.py b/plugins/PostProcessingPlugin/scripts/PauseAtHeight.py new file mode 100644 index 0000000000..925a5a7ac5 --- /dev/null +++ b/plugins/PostProcessingPlugin/scripts/PauseAtHeight.py @@ -0,0 +1,221 @@ +from ..Script import Script +# from cura.Settings.ExtruderManager import ExtruderManager + +class PauseAtHeight(Script): + def __init__(self): + super().__init__() + + def getSettingDataString(self): + return """{ + "name":"Pause at height", + "key": "PauseAtHeight", + "metadata": {}, + "version": 2, + "settings": + { + "pause_height": + { + "label": "Pause Height", + "description": "At what height should the pause occur", + "unit": "mm", + "type": "float", + "default_value": 5.0 + }, + "head_park_x": + { + "label": "Park Print Head X", + "description": "What X location does the head move to when pausing.", + "unit": "mm", + "type": "float", + "default_value": 190 + }, + "head_park_y": + { + "label": "Park Print Head Y", + "description": "What Y location does the head move to when pausing.", + "unit": "mm", + "type": "float", + "default_value": 190 + }, + "retraction_amount": + { + "label": "Retraction", + "description": "How much filament must be retracted at pause.", + "unit": "mm", + "type": "float", + "default_value": 0 + }, + "retraction_speed": + { + "label": "Retraction Speed", + "description": "How fast to retract the filament.", + "unit": "mm/s", + "type": "float", + "default_value": 25 + }, + "extrude_amount": + { + "label": "Extrude Amount", + "description": "How much filament should be extruded after pause. This is needed when doing a material change on Ultimaker2's to compensate for the retraction after the change. In that case 128+ is recommended.", + "unit": "mm", + "type": "float", + "default_value": 0 + }, + "extrude_speed": + { + "label": "Extrude Speed", + "description": "How fast to extrude the material after pause.", + "unit": "mm/s", + "type": "float", + "default_value": 3.3333 + }, + "redo_layers": + { + "label": "Redo Layers", + "description": "Redo a number of previous layers after a pause to increases adhesion.", + "unit": "layers", + "type": "int", + "default_value": 0 + }, + "standby_temperature": + { + "label": "Standby Temperature", + "description": "Change the temperature during the pause", + "unit": "°C", + "type": "int", + "default_value": 0 + }, + "resume_temperature": + { + "label": "Resume Temperature", + "description": "Change the temperature after the pause", + "unit": "°C", + "type": "int", + "default_value": 0 + } + } + }""" + + def execute(self, data: list): + + """data is a list. Each index contains a layer""" + + x = 0. + y = 0. + current_z = 0. + pause_height = self.getSettingValueByKey("pause_height") + retraction_amount = self.getSettingValueByKey("retraction_amount") + retraction_speed = self.getSettingValueByKey("retraction_speed") + extrude_amount = self.getSettingValueByKey("extrude_amount") + extrude_speed = self.getSettingValueByKey("extrude_speed") + park_x = self.getSettingValueByKey("head_park_x") + park_y = self.getSettingValueByKey("head_park_y") + layers_started = False + redo_layers = self.getSettingValueByKey("redo_layers") + standby_temperature = self.getSettingValueByKey("standby_temperature") + resume_temperature = self.getSettingValueByKey("resume_temperature") + + # T = ExtruderManager.getInstance().getActiveExtruderStack().getProperty("material_print_temperature", "value") + # with open("out.txt", "w") as f: + # f.write(T) + + # use offset to calculate the current height: = - + layer_0_z = 0. + got_first_g_cmd_on_layer_0 = False + for layer in data: + lines = layer.split("\n") + for line in lines: + if ";LAYER:0" in line: + layers_started = True + continue + + if not layers_started: + continue + + if self.getValue(line, 'G') == 1 or self.getValue(line, 'G') == 0: + current_z = self.getValue(line, 'Z') + if not got_first_g_cmd_on_layer_0: + layer_0_z = current_z + got_first_g_cmd_on_layer_0 = True + + x = self.getValue(line, 'X', x) + y = self.getValue(line, 'Y', y) + if current_z is not None: + current_height = current_z - layer_0_z + if current_height >= pause_height: + index = data.index(layer) + prevLayer = data[index - 1] + prevLines = prevLayer.split("\n") + current_e = 0. + for prevLine in reversed(prevLines): + current_e = self.getValue(prevLine, 'E', -1) + if current_e >= 0: + break + + # include a number of previous layers + for i in range(1, redo_layers + 1): + prevLayer = data[index - i] + layer = prevLayer + layer + + prepend_gcode = ";TYPE:CUSTOM\n" + prepend_gcode += ";added code by post processing\n" + prepend_gcode += ";script: PauseAtHeight.py\n" + prepend_gcode += ";current z: %f \n" % current_z + prepend_gcode += ";current height: %f \n" % current_height + + # Retraction + prepend_gcode += "M83\n" + if retraction_amount != 0: + prepend_gcode += "G1 E-%f F%f\n" % (retraction_amount, retraction_speed * 60) + + # Move the head away + prepend_gcode += "G1 Z%f F300\n" % (current_z + 1) + prepend_gcode += "G1 X%f Y%f F9000\n" % (park_x, park_y) + if current_z < 15: + prepend_gcode += "G1 Z15 F300\n" + + # Disable the E steppers + prepend_gcode += "M84 E0\n" + + # Set extruder standby temperature + prepend_gcode += "M104 S%i; standby temperature\n" % (standby_temperature) + + # Wait till the user continues printing + prepend_gcode += "M0 ;Do the actual pause\n" + + # Set extruder resume temperature + prepend_gcode += "M109 S%i; resume temperature\n" % (resume_temperature) + + # Push the filament back, + if retraction_amount != 0: + prepend_gcode += "G1 E%f F%f\n" % (retraction_amount, retraction_speed * 60) + + # Optionally extrude material + if extrude_amount != 0: + prepend_gcode += "G1 E%f F%f\n" % (extrude_amount, extrude_speed * 60) + + # and retract again, the properly primes the nozzle + # when changing filament. + if retraction_amount != 0: + prepend_gcode += "G1 E-%f F%f\n" % (retraction_amount, retraction_speed * 60) + + # Move the head back + prepend_gcode += "G1 Z%f F300\n" % (current_z + 1) + prepend_gcode += "G1 X%f Y%f F9000\n" % (x, y) + if retraction_amount != 0: + prepend_gcode += "G1 E%f F%f\n" % (retraction_amount, retraction_speed * 60) + prepend_gcode += "G1 F9000\n" + prepend_gcode += "M82\n" + + # reset extrude value to pre pause value + prepend_gcode += "G92 E%f\n" % (current_e) + + layer = prepend_gcode + layer + + + # Override the data of this layer with the + # modified data + data[index] = layer + return data + break + return data diff --git a/plugins/PostProcessingPlugin/scripts/PauseAtHeightforRepetier.py b/plugins/PostProcessingPlugin/scripts/PauseAtHeightforRepetier.py new file mode 100644 index 0000000000..710baab26a --- /dev/null +++ b/plugins/PostProcessingPlugin/scripts/PauseAtHeightforRepetier.py @@ -0,0 +1,169 @@ +from ..Script import Script +class PauseAtHeightforRepetier(Script): + def __init__(self): + super().__init__() + + def getSettingDataString(self): + return """{ + "name":"Pause at height for repetier", + "key": "PauseAtHeightforRepetier", + "metadata": {}, + "version": 2, + "settings": + { + "pause_height": + { + "label": "Pause height", + "description": "At what height should the pause occur", + "unit": "mm", + "type": "float", + "default_value": 5.0 + }, + "head_park_x": + { + "label": "Park print head X", + "description": "What x location does the head move to when pausing.", + "unit": "mm", + "type": "float", + "default_value": 5.0 + }, + "head_park_y": + { + "label": "Park print head Y", + "description": "What y location does the head move to when pausing.", + "unit": "mm", + "type": "float", + "default_value": 5.0 + }, + "head_move_Z": + { + "label": "Head move Z", + "description": "The Hieght of Z-axis retraction before parking.", + "unit": "mm", + "type": "float", + "default_value": 15.0 + }, + "retraction_amount": + { + "label": "Retraction", + "description": "How much fillament must be retracted at pause.", + "unit": "mm", + "type": "float", + "default_value": 5.0 + }, + "extrude_amount": + { + "label": "Extrude amount", + "description": "How much filament should be extruded after pause. This is needed when doing a material change on Ultimaker2's to compensate for the retraction after the change. In that case 128+ is recommended.", + "unit": "mm", + "type": "float", + "default_value": 90.0 + }, + "redo_layers": + { + "label": "Redo layers", + "description": "Redo a number of previous layers after a pause to increases adhesion.", + "unit": "layers", + "type": "int", + "default_value": 0 + } + } + }""" + + def execute(self, data): + x = 0. + y = 0. + current_z = 0. + pause_z = self.getSettingValueByKey("pause_height") + retraction_amount = self.getSettingValueByKey("retraction_amount") + extrude_amount = self.getSettingValueByKey("extrude_amount") + park_x = self.getSettingValueByKey("head_park_x") + park_y = self.getSettingValueByKey("head_park_y") + move_Z = self.getSettingValueByKey("head_move_Z") + layers_started = False + redo_layers = self.getSettingValueByKey("redo_layers") + for layer in data: + lines = layer.split("\n") + for line in lines: + if ";LAYER:0" in line: + layers_started = True + continue + + if not layers_started: + continue + + if self.getValue(line, 'G') == 1 or self.getValue(line, 'G') == 0: + current_z = self.getValue(line, 'Z') + x = self.getValue(line, 'X', x) + y = self.getValue(line, 'Y', y) + if current_z != None: + if current_z >= pause_z: + + index = data.index(layer) + prevLayer = data[index-1] + prevLines = prevLayer.split("\n") + current_e = 0. + for prevLine in reversed(prevLines): + current_e = self.getValue(prevLine, 'E', -1) + if current_e >= 0: + break + + prepend_gcode = ";TYPE:CUSTOM\n" + prepend_gcode += ";added code by post processing\n" + prepend_gcode += ";script: PauseAtHeightforRepetier.py\n" + prepend_gcode += ";current z: %f \n" % (current_z) + prepend_gcode += ";current X: %f \n" % (x) + prepend_gcode += ";current Y: %f \n" % (y) + + #Retraction + prepend_gcode += "M83\n" + if retraction_amount != 0: + prepend_gcode += "G1 E-%f F6000\n" % (retraction_amount) + + #Move the head away + prepend_gcode += "G1 Z%f F300\n" % (1 + current_z) + prepend_gcode += "G1 X%f Y%f F9000\n" % (park_x, park_y) + if current_z < move_Z: + prepend_gcode += "G1 Z%f F300\n" % (current_z + move_Z) + + #Disable the E steppers + prepend_gcode += "M84 E0\n" + #Wait till the user continues printing + prepend_gcode += "@pause now change filament and press continue printing ;Do the actual pause\n" + + #Push the filament back, + if retraction_amount != 0: + prepend_gcode += "G1 E%f F6000\n" % (retraction_amount) + + # Optionally extrude material + if extrude_amount != 0: + prepend_gcode += "G1 E%f F200\n" % (extrude_amount) + prepend_gcode += "@info wait for cleaning nozzle from previous filament\n" + prepend_gcode += "@pause remove the waste filament from parking area and press continue printing\n" + + # and retract again, the properly primes the nozzle when changing filament. + if retraction_amount != 0: + prepend_gcode += "G1 E-%f F6000\n" % (retraction_amount) + + #Move the head back + prepend_gcode += "G1 Z%f F300\n" % (1 + current_z) + prepend_gcode +="G1 X%f Y%f F9000\n" % (x, y) + if retraction_amount != 0: + prepend_gcode +="G1 E%f F6000\n" % (retraction_amount) + prepend_gcode +="G1 F9000\n" + prepend_gcode +="M82\n" + + # reset extrude value to pre pause value + prepend_gcode +="G92 E%f\n" % (current_e) + + layer = prepend_gcode + layer + + # include a number of previous layers + for i in range(1, redo_layers + 1): + prevLayer = data[index-i] + layer = prevLayer + layer + + data[index] = layer #Override the data of this layer with the modified data + return data + break + return data diff --git a/plugins/PostProcessingPlugin/scripts/SearchAndReplace.py b/plugins/PostProcessingPlugin/scripts/SearchAndReplace.py new file mode 100644 index 0000000000..68d697e470 --- /dev/null +++ b/plugins/PostProcessingPlugin/scripts/SearchAndReplace.py @@ -0,0 +1,56 @@ +# Copyright (c) 2017 Ruben Dulek +# The PostProcessingPlugin is released under the terms of the AGPLv3 or higher. + +import re #To perform the search and replace. + +from ..Script import Script + +## Performs a search-and-replace on all g-code. +# +# Due to technical limitations, the search can't cross the border between +# layers. +class SearchAndReplace(Script): + def getSettingDataString(self): + return """{ + "name": "Search and Replace", + "key": "SearchAndReplace", + "metadata": {}, + "version": 2, + "settings": + { + "search": + { + "label": "Search", + "description": "All occurrences of this text will get replaced by the replacement text.", + "type": "str", + "default_value": "" + }, + "replace": + { + "label": "Replace", + "description": "The search text will get replaced by this text.", + "type": "str", + "default_value": "" + }, + "is_regex": + { + "label": "Use Regular Expressions", + "description": "When enabled, the search text will be interpreted as a regular expression.", + "type": "bool", + "default_value": false + } + } + }""" + + def execute(self, data): + search_string = self.getSettingValueByKey("search") + if not self.getSettingValueByKey("is_regex"): + search_string = re.escape(search_string) #Need to search for the actual string, not as a regex. + search_regex = re.compile(search_string) + + replace_string = self.getSettingValueByKey("replace") + + for layer_number, layer in enumerate(data): + data[layer_number] = re.sub(search_regex, replace_string, layer) #Replace all. + + return data \ No newline at end of file diff --git a/plugins/PostProcessingPlugin/scripts/Stretch.py b/plugins/PostProcessingPlugin/scripts/Stretch.py new file mode 100644 index 0000000000..bcb923d3ff --- /dev/null +++ b/plugins/PostProcessingPlugin/scripts/Stretch.py @@ -0,0 +1,469 @@ +# This PostProcessingPlugin script is released under the terms of the AGPLv3 or higher. +""" +Copyright (c) 2017 Christophe Baribaud 2017 +Python implementation of https://github.com/electrocbd/post_stretch +Correction of hole sizes, cylinder diameters and curves +See the original description in https://github.com/electrocbd/post_stretch + +WARNING This script has never been tested with several extruders +""" +from ..Script import Script +import numpy as np +from UM.Logger import Logger +from UM.Application import Application +import re + +def _getValue(line, key, default=None): + """ + Convenience function that finds the value in a line of g-code. + When requesting key = x from line "G1 X100" the value 100 is returned. + It is a copy of Stript's method, so it is no DontRepeatYourself, but + I split the class into setup part (Stretch) and execution part (Strecher) + and only the setup part inherits from Script + """ + if not key in line or (";" in line and line.find(key) > line.find(";")): + return default + sub_part = line[line.find(key) + 1:] + number = re.search(r"^-?[0-9]+\.?[0-9]*", sub_part) + if number is None: + return default + return float(number.group(0)) + +class GCodeStep(): + """ + Class to store the current value of each G_Code parameter + for any G-Code step + """ + def __init__(self, step): + self.step = step + self.step_x = 0 + self.step_y = 0 + self.step_z = 0 + self.step_e = 0 + self.step_f = 0 + self.comment = "" + + def readStep(self, line): + """ + Reads gcode from line into self + """ + self.step_x = _getValue(line, "X", self.step_x) + self.step_y = _getValue(line, "Y", self.step_y) + self.step_z = _getValue(line, "Z", self.step_z) + self.step_e = _getValue(line, "E", self.step_e) + self.step_f = _getValue(line, "F", self.step_f) + return + + def copyPosFrom(self, step): + """ + Copies positions of step into self + """ + self.step_x = step.step_x + self.step_y = step.step_y + self.step_z = step.step_z + self.step_e = step.step_e + self.step_f = step.step_f + self.comment = step.comment + return + + +# Execution part of the stretch plugin +class Stretcher(): + """ + Execution part of the stretch algorithm + """ + def __init__(self, line_width, wc_stretch, pw_stretch): + self.line_width = line_width + self.wc_stretch = wc_stretch + self.pw_stretch = pw_stretch + if self.pw_stretch > line_width / 4: + self.pw_stretch = line_width / 4 # Limit value of pushwall stretch distance + self.outpos = GCodeStep(0) + self.vd1 = np.empty((0, 2)) # Start points of segments + # of already deposited material for current layer + self.vd2 = np.empty((0, 2)) # End points of segments + # of already deposited material for current layer + self.layer_z = 0 # Z position of the extrusion moves of the current layer + self.layergcode = "" + + def execute(self, data): + """ + Computes the new X and Y coordinates of all g-code steps + """ + Logger.log("d", "Post stretch with line width = " + str(self.line_width) + + "mm wide circle stretch = " + str(self.wc_stretch)+ "mm" + + "and push wall stretch = " + str(self.pw_stretch) + "mm") + retdata = [] + layer_steps = [] + current = GCodeStep(0) + self.layer_z = 0. + current_e = 0. + for layer in data: + lines = layer.rstrip("\n").split("\n") + for line in lines: + current.comment = "" + if line.find(";") >= 0: + current.comment = line[line.find(";"):] + if _getValue(line, "G") == 0: + current.readStep(line) + onestep = GCodeStep(0) + onestep.copyPosFrom(current) + elif _getValue(line, "G") == 1: + current.readStep(line) + onestep = GCodeStep(1) + onestep.copyPosFrom(current) + elif _getValue(line, "G") == 92: + current.readStep(line) + onestep = GCodeStep(-1) + onestep.copyPosFrom(current) + else: + onestep = GCodeStep(-1) + onestep.copyPosFrom(current) + onestep.comment = line + if line.find(";LAYER:") >= 0 and len(layer_steps): + # Previous plugin "forgot" to separate two layers... + Logger.log("d", "Layer Z " + "{:.3f}".format(self.layer_z) + + " " + str(len(layer_steps)) + " steps") + retdata.append(self.processLayer(layer_steps)) + layer_steps = [] + layer_steps.append(onestep) + # self.layer_z is the z position of the last extrusion move (not travel move) + if current.step_z != self.layer_z and current.step_e != current_e: + self.layer_z = current.step_z + current_e = current.step_e + if len(layer_steps): # Force a new item in the array + Logger.log("d", "Layer Z " + "{:.3f}".format(self.layer_z) + + " " + str(len(layer_steps)) + " steps") + retdata.append(self.processLayer(layer_steps)) + layer_steps = [] + retdata.append(";Wide circle stretch distance " + str(self.wc_stretch) + "\n") + retdata.append(";Push wall stretch distance " + str(self.pw_stretch) + "\n") + return retdata + + def extrusionBreak(self, layer_steps, i_pos): + """ + Returns true if the command layer_steps[i_pos] breaks the extruded filament + i.e. it is a travel move + """ + if i_pos == 0: + return True # Begining a layer always breaks filament (for simplicity) + step = layer_steps[i_pos] + prev_step = layer_steps[i_pos - 1] + if step.step_e != prev_step.step_e: + return False + delta_x = step.step_x - prev_step.step_x + delta_y = step.step_y - prev_step.step_y + if delta_x * delta_x + delta_y * delta_y < self.line_width * self.line_width / 4: + # This is a very short movement, less than 0.5 * line_width + # It does not break filament, we should stay in the same extrusion sequence + return False + return True # New sequence + + + def processLayer(self, layer_steps): + """ + Computes the new coordinates of g-code steps + for one layer (all the steps at the same Z coordinate) + """ + self.outpos.step_x = -1000 # Force output of X and Y coordinates + self.outpos.step_y = -1000 # at each start of layer + self.layergcode = "" + self.vd1 = np.empty((0, 2)) + self.vd2 = np.empty((0, 2)) + orig_seq = np.empty((0, 2)) + modif_seq = np.empty((0, 2)) + iflush = 0 + for i, step in enumerate(layer_steps): + if step.step == 0 or step.step == 1: + if self.extrusionBreak(layer_steps, i): + # No extrusion since the previous step, so it is a travel move + # Let process steps accumulated into orig_seq, + # which are a sequence of continuous extrusion + modif_seq = np.copy(orig_seq) + if len(orig_seq) >= 2: + self.workOnSequence(orig_seq, modif_seq) + self.generate(layer_steps, iflush, i, modif_seq) + iflush = i + orig_seq = np.empty((0, 2)) + orig_seq = np.concatenate([orig_seq, np.array([[step.step_x, step.step_y]])]) + if len(orig_seq): + modif_seq = np.copy(orig_seq) + if len(orig_seq) >= 2: + self.workOnSequence(orig_seq, modif_seq) + self.generate(layer_steps, iflush, len(layer_steps), modif_seq) + return self.layergcode + + def stepToGcode(self, onestep): + """ + Converts a step into G-Code + For each of the X, Y, Z, E and F parameter, + the parameter is written only if its value changed since the + previous g-code step. + """ + sout = "" + if onestep.step_f != self.outpos.step_f: + self.outpos.step_f = onestep.step_f + sout += " F{:.0f}".format(self.outpos.step_f).rstrip(".") + if onestep.step_x != self.outpos.step_x or onestep.step_y != self.outpos.step_y: + assert onestep.step_x >= -1000 and onestep.step_x < 1000 # If this assertion fails, + # something went really wrong ! + self.outpos.step_x = onestep.step_x + sout += " X{:.3f}".format(self.outpos.step_x).rstrip("0").rstrip(".") + assert onestep.step_y >= -1000 and onestep.step_y < 1000 # If this assertion fails, + # something went really wrong ! + self.outpos.step_y = onestep.step_y + sout += " Y{:.3f}".format(self.outpos.step_y).rstrip("0").rstrip(".") + if onestep.step_z != self.outpos.step_z or onestep.step_z != self.layer_z: + self.outpos.step_z = onestep.step_z + sout += " Z{:.3f}".format(self.outpos.step_z).rstrip("0").rstrip(".") + if onestep.step_e != self.outpos.step_e: + self.outpos.step_e = onestep.step_e + sout += " E{:.5f}".format(self.outpos.step_e).rstrip("0").rstrip(".") + return sout + + def generate(self, layer_steps, ibeg, iend, orig_seq): + """ + Appends g-code lines to the plugin's returned string + starting from step ibeg included and until step iend excluded + """ + ipos = 0 + for i in range(ibeg, iend): + if layer_steps[i].step == 0: + layer_steps[i].step_x = orig_seq[ipos][0] + layer_steps[i].step_y = orig_seq[ipos][1] + sout = "G0" + self.stepToGcode(layer_steps[i]) + self.layergcode = self.layergcode + sout + "\n" + ipos = ipos + 1 + elif layer_steps[i].step == 1: + layer_steps[i].step_x = orig_seq[ipos][0] + layer_steps[i].step_y = orig_seq[ipos][1] + sout = "G1" + self.stepToGcode(layer_steps[i]) + self.layergcode = self.layergcode + sout + "\n" + ipos = ipos + 1 + else: + self.layergcode = self.layergcode + layer_steps[i].comment + "\n" + + + def workOnSequence(self, orig_seq, modif_seq): + """ + Computes new coordinates for a sequence + A sequence is a list of consecutive g-code steps + of continuous material extrusion + """ + d_contact = self.line_width / 2.0 + if (len(orig_seq) > 2 and + ((orig_seq[len(orig_seq) - 1] - orig_seq[0]) ** 2).sum(0) < d_contact * d_contact): + # Starting and ending point of the sequence are nearby + # It is a closed loop + #self.layergcode = self.layergcode + ";wideCircle\n" + self.wideCircle(orig_seq, modif_seq) + else: + #self.layergcode = self.layergcode + ";wideTurn\n" + self.wideTurn(orig_seq, modif_seq) # It is an open curve + if len(orig_seq) > 6: # Don't try push wall on a short sequence + self.pushWall(orig_seq, modif_seq) + if len(orig_seq): + self.vd1 = np.concatenate([self.vd1, np.array(orig_seq[:-1])]) + self.vd2 = np.concatenate([self.vd2, np.array(orig_seq[1:])]) + + def wideCircle(self, orig_seq, modif_seq): + """ + Similar to wideTurn + The first and last point of the sequence are the same, + so it is possible to extend the end of the sequence + with its beginning when seeking for triangles + + It is necessary to find the direction of the curve, knowing three points (a triangle) + If the triangle is not wide enough, there is a huge risk of finding + an incorrect orientation, due to insufficient accuracy. + So, when the consecutive points are too close, the method + use following and preceding points to form a wider triangle around + the current point + dmin_tri is the minimum distance between two consecutive points + of an acceptable triangle + """ + dmin_tri = self.line_width / 2.0 + iextra_base = np.floor_divide(len(orig_seq), 3) # Nb of extra points + ibeg = 0 # Index of first point of the triangle + iend = 0 # Index of the third point of the triangle + for i, step in enumerate(orig_seq): + if i == 0 or i == len(orig_seq) - 1: + # First and last point of the sequence are the same, + # so it is necessary to skip one of these two points + # when creating a triangle containing the first or the last point + iextra = iextra_base + 1 + else: + iextra = iextra_base + # i is the index of the second point of the triangle + # pos_after is the array of positions of the original sequence + # after the current point + pos_after = np.resize(np.roll(orig_seq, -i-1, 0), (iextra, 2)) + # Vector of distances between the current point and each following point + dist_from_point = ((step - pos_after) ** 2).sum(1) + if np.amax(dist_from_point) < dmin_tri * dmin_tri: + continue + iend = np.argmax(dist_from_point >= dmin_tri * dmin_tri) + # pos_before is the array of positions of the original sequence + # before the current point + pos_before = np.resize(np.roll(orig_seq, -i, 0)[::-1], (iextra, 2)) + # This time, vector of distances between the current point and each preceding point + dist_from_point = ((step - pos_before) ** 2).sum(1) + if np.amax(dist_from_point) < dmin_tri * dmin_tri: + continue + ibeg = np.argmax(dist_from_point >= dmin_tri * dmin_tri) + # See https://github.com/electrocbd/post_stretch for explanations + # relpos is the relative position of the projection of the second point + # of the triangle on the segment from the first to the third point + # 0 means the position of the first point, 1 means the position of the third, + # intermediate values are positions between + length_base = ((pos_after[iend] - pos_before[ibeg]) ** 2).sum(0) + relpos = ((step - pos_before[ibeg]) + * (pos_after[iend] - pos_before[ibeg])).sum(0) + if np.fabs(relpos) < 1000.0 * np.fabs(length_base): + relpos /= length_base + else: + relpos = 0.5 # To avoid division by zero or precision loss + projection = (pos_before[ibeg] + relpos * (pos_after[iend] - pos_before[ibeg])) + dist_from_proj = np.sqrt(((projection - step) ** 2).sum(0)) + if dist_from_proj > 0.001: # Move central point only if points are not aligned + modif_seq[i] = (step - (self.wc_stretch / dist_from_proj) + * (projection - step)) + return + + def wideTurn(self, orig_seq, modif_seq): + ''' + We have to select three points in order to form a triangle + These three points should be far enough from each other to have + a reliable estimation of the orientation of the current turn + ''' + dmin_tri = self.line_width / 2.0 + ibeg = 0 + iend = 2 + for i in range(1, len(orig_seq) - 1): + dist_from_point = ((orig_seq[i] - orig_seq[i+1:]) ** 2).sum(1) + if np.amax(dist_from_point) < dmin_tri * dmin_tri: + continue + iend = i + 1 + np.argmax(dist_from_point >= dmin_tri * dmin_tri) + dist_from_point = ((orig_seq[i] - orig_seq[i-1::-1]) ** 2).sum(1) + if np.amax(dist_from_point) < dmin_tri * dmin_tri: + continue + ibeg = i - 1 - np.argmax(dist_from_point >= dmin_tri * dmin_tri) + length_base = ((orig_seq[iend] - orig_seq[ibeg]) ** 2).sum(0) + relpos = ((orig_seq[i] - orig_seq[ibeg]) * (orig_seq[iend] - orig_seq[ibeg])).sum(0) + if np.fabs(relpos) < 1000.0 * np.fabs(length_base): + relpos /= length_base + else: + relpos = 0.5 + projection = orig_seq[ibeg] + relpos * (orig_seq[iend] - orig_seq[ibeg]) + dist_from_proj = np.sqrt(((projection - orig_seq[i]) ** 2).sum(0)) + if dist_from_proj > 0.001: + modif_seq[i] = (orig_seq[i] - (self.wc_stretch / dist_from_proj) + * (projection - orig_seq[i])) + return + + def pushWall(self, orig_seq, modif_seq): + """ + The algorithm tests for each segment if material was + already deposited at one or the other side of this segment. + If material was deposited at one side but not both, + the segment is moved into the direction of the deposited material, + to "push the wall" + + Already deposited material is stored as segments. + vd1 is the array of the starting points of the segments + vd2 is the array of the ending points of the segments + For example, segment nr 8 starts at position self.vd1[8] + and ends at position self.vd2[8] + """ + dist_palp = self.line_width # Palpation distance to seek for a wall + mrot = np.array([[0, -1], [1, 0]]) # Rotation matrix for a quarter turn + for i in range(len(orig_seq)): + ibeg = i # Index of the first point of the segment + iend = i + 1 # Index of the last point of the segment + if iend == len(orig_seq): + iend = i - 1 + xperp = np.dot(mrot, orig_seq[iend] - orig_seq[ibeg]) + xperp = xperp / np.sqrt((xperp ** 2).sum(-1)) + testleft = orig_seq[ibeg] + xperp * dist_palp + materialleft = False # Is there already extruded material at the left of the segment + testright = orig_seq[ibeg] - xperp * dist_palp + materialright = False # Is there already extruded material at the right of the segment + if self.vd1.shape[0]: + relpos = np.clip(((testleft - self.vd1) * (self.vd2 - self.vd1)).sum(1) + / ((self.vd2 - self.vd1) * (self.vd2 - self.vd1)).sum(1), 0., 1.) + nearpoints = self.vd1 + relpos[:, np.newaxis] * (self.vd2 - self.vd1) + # nearpoints is the array of the nearest points of each segment + # from the point testleft + dist = ((testleft - nearpoints) * (testleft - nearpoints)).sum(1) + # dist is the array of the squares of the distances between testleft + # and each segment + if np.amin(dist) <= dist_palp * dist_palp: + materialleft = True + # Now the same computation with the point testright at the other side of the + # current segment + relpos = np.clip(((testright - self.vd1) * (self.vd2 - self.vd1)).sum(1) + / ((self.vd2 - self.vd1) * (self.vd2 - self.vd1)).sum(1), 0., 1.) + nearpoints = self.vd1 + relpos[:, np.newaxis] * (self.vd2 - self.vd1) + dist = ((testright - nearpoints) * (testright - nearpoints)).sum(1) + if np.amin(dist) <= dist_palp * dist_palp: + materialright = True + if materialleft and not materialright: + modif_seq[ibeg] = modif_seq[ibeg] + xperp * self.pw_stretch + elif not materialleft and materialright: + modif_seq[ibeg] = modif_seq[ibeg] - xperp * self.pw_stretch + if materialleft and materialright: + modif_seq[ibeg] = orig_seq[ibeg] # Surrounded by walls, don't move + +# Setup part of the stretch plugin +class Stretch(Script): + """ + Setup part of the stretch algorithm + The only parameter is the stretch distance + """ + def __init__(self): + super().__init__() + + def getSettingDataString(self): + return """{ + "name":"Post stretch script", + "key": "Stretch", + "metadata": {}, + "version": 2, + "settings": + { + "wc_stretch": + { + "label": "Wide circle stretch distance", + "description": "Distance by which the points are moved by the correction effect in corners. The higher this value, the higher the effect", + "unit": "mm", + "type": "float", + "default_value": 0.08, + "minimum_value": 0, + "minimum_value_warning": 0, + "maximum_value_warning": 0.2 + }, + "pw_stretch": + { + "label": "Push Wall stretch distance", + "description": "Distance by which the points are moved by the correction effect when two lines are nearby. The higher this value, the higher the effect", + "unit": "mm", + "type": "float", + "default_value": 0.08, + "minimum_value": 0, + "minimum_value_warning": 0, + "maximum_value_warning": 0.2 + } + } + }""" + + def execute(self, data): + """ + Entry point of the plugin. + data is the list of original g-code instructions, + the returned string is the list of modified g-code instructions + """ + stretcher = Stretcher( + Application.getInstance().getGlobalContainerStack().getProperty("line_width", "value") + , self.getSettingValueByKey("wc_stretch"), self.getSettingValueByKey("pw_stretch")) + return stretcher.execute(data) + diff --git a/plugins/PostProcessingPlugin/scripts/TweakAtZ.py b/plugins/PostProcessingPlugin/scripts/TweakAtZ.py new file mode 100644 index 0000000000..7b714f6ee0 --- /dev/null +++ b/plugins/PostProcessingPlugin/scripts/TweakAtZ.py @@ -0,0 +1,495 @@ +# TweakAtZ script - Change printing parameters at a given height +# This script is the successor of the TweakAtZ plugin for legacy Cura. +# It contains code from the TweakAtZ plugin V1.0-V4.x and from the ExampleScript by Jaime van Kessel, Ultimaker B.V. +# It runs with the PostProcessingPlugin which is released under the terms of the AGPLv3 or higher. +# This script is licensed under the Creative Commons - Attribution - Share Alike (CC BY-SA) terms + +#Authors of the TweakAtZ plugin / script: +# Written by Steven Morlock, smorloc@gmail.com +# Modified by Ricardo Gomez, ricardoga@otulook.com, to add Bed Temperature and make it work with Cura_13.06.04+ +# Modified by Stefan Heule, Dim3nsioneer@gmx.ch since V3.0 (see changelog below) +# Modified by Jaime van Kessel (Ultimaker), j.vankessel@ultimaker.com to make it work for 15.10 / 2.x +# Modified by Ruben Dulek (Ultimaker), r.dulek@ultimaker.com, to debug. + +##history / changelog: +##V3.0.1: TweakAtZ-state default 1 (i.e. the plugin works without any TweakAtZ comment) +##V3.1: Recognizes UltiGCode and deactivates value reset, fan speed added, alternatively layer no. to tweak at, +## extruder three temperature disabled by "#Ex3" +##V3.1.1: Bugfix reset flow rate +##V3.1.2: Bugfix disable TweakAtZ on Cool Head Lift +##V3.2: Flow rate for specific extruder added (only for 2 extruders), bugfix parser, +## added speed reset at the end of the print +##V4.0: Progress bar, tweaking over multiple layers, M605&M606 implemented, reset after one layer option, +## extruder three code removed, tweaking print speed, save call of Publisher class, +## uses previous value from other plugins also on UltiGCode +##V4.0.1: Bugfix for doubled G1 commands +##V4.0.2: uses Cura progress bar instead of its own +##V4.0.3: Bugfix for cool head lift (contributed by luisonoff) +##V4.9.91: First version for Cura 15.06.x and PostProcessingPlugin +##V4.9.92: Modifications for Cura 15.10 +##V4.9.93: Minor bugfixes (input settings) / documentation +##V4.9.94: Bugfix Combobox-selection; remove logger +##V5.0: Bugfix for fall back after one layer and doubled G0 commands when using print speed tweak, Initial version for Cura 2.x +##V5.0.1: Bugfix for calling unknown property 'bedTemp' of previous settings storage and unkown variable 'speed' +##V5.1: API Changes included for use with Cura 2.2 + +## Uses - +## M220 S - set speed factor override percentage +## M221 S - set flow factor override percentage +## M221 S T<0-#toolheads> - set flow factor override percentage for single extruder +## M104 S T<0-#toolheads> - set extruder to target temperature +## M140 S - set bed target temperature +## M106 S - set fan speed to target speed +## M605/606 to save and recall material settings on the UM2 + +from ..Script import Script +#from UM.Logger import Logger +import re + +class TweakAtZ(Script): + version = "5.1.1" + def __init__(self): + super().__init__() + + def getSettingDataString(self): + return """{ + "name":"TweakAtZ """ + self.version + """ (Experimental)", + "key":"TweakAtZ", + "metadata": {}, + "version": 2, + "settings": + { + "a_trigger": + { + "label": "Trigger", + "description": "Trigger at height or at layer no.", + "type": "enum", + "options": {"height":"Height","layer_no":"Layer No."}, + "default_value": "height" + }, + "b_targetZ": + { + "label": "Tweak Height", + "description": "Z height to tweak at", + "unit": "mm", + "type": "float", + "default_value": 5.0, + "minimum_value": "0", + "minimum_value_warning": "0.1", + "maximum_value_warning": "230", + "enabled": "a_trigger == 'height'" + }, + "b_targetL": + { + "label": "Tweak Layer", + "description": "Layer no. to tweak at", + "unit": "", + "type": "int", + "default_value": 1, + "minimum_value": "-100", + "minimum_value_warning": "-1", + "enabled": "a_trigger == 'layer_no'" + }, + "c_behavior": + { + "label": "Behavior", + "description": "Select behavior: Tweak value and keep it for the rest, Tweak value for single layer only", + "type": "enum", + "options": {"keep_value":"Keep value","single_layer":"Single Layer"}, + "default_value": "keep_value" + }, + "d_twLayers": + { + "label": "No. Layers", + "description": "No. of layers used to tweak", + "unit": "", + "type": "int", + "default_value": 1, + "minimum_value": "1", + "maximum_value_warning": "50", + "enabled": "c_behavior == 'keep_value'" + }, + "e1_Tweak_speed": + { + "label": "Tweak Speed", + "description": "Select if total speed (print and travel) has to be tweaked", + "type": "bool", + "default_value": false + }, + "e2_speed": + { + "label": "Speed", + "description": "New total speed (print and travel)", + "unit": "%", + "type": "int", + "default_value": 100, + "minimum_value": "1", + "minimum_value_warning": "10", + "maximum_value_warning": "200", + "enabled": "e1_Tweak_speed" + }, + "f1_Tweak_printspeed": + { + "label": "Tweak Print Speed", + "description": "Select if print speed has to be tweaked", + "type": "bool", + "default_value": false + }, + "f2_printspeed": + { + "label": "Print Speed", + "description": "New print speed", + "unit": "%", + "type": "int", + "default_value": 100, + "minimum_value": "1", + "minimum_value_warning": "10", + "maximum_value_warning": "200", + "enabled": "f1_Tweak_printspeed" + }, + "g1_Tweak_flowrate": + { + "label": "Tweak Flow Rate", + "description": "Select if flow rate has to be tweaked", + "type": "bool", + "default_value": false + }, + "g2_flowrate": + { + "label": "Flow Rate", + "description": "New Flow rate", + "unit": "%", + "type": "int", + "default_value": 100, + "minimum_value": "1", + "minimum_value_warning": "10", + "maximum_value_warning": "200", + "enabled": "g1_Tweak_flowrate" + }, + "g3_Tweak_flowrateOne": + { + "label": "Tweak Flow Rate 1", + "description": "Select if first extruder flow rate has to be tweaked", + "type": "bool", + "default_value": false + }, + "g4_flowrateOne": + { + "label": "Flow Rate One", + "description": "New Flow rate Extruder 1", + "unit": "%", + "type": "int", + "default_value": 100, + "minimum_value": "1", + "minimum_value_warning": "10", + "maximum_value_warning": "200", + "enabled": "g3_Tweak_flowrateOne" + }, + "g5_Tweak_flowrateTwo": + { + "label": "Tweak Flow Rate 2", + "description": "Select if second extruder flow rate has to be tweaked", + "type": "bool", + "default_value": false + }, + "g6_flowrateTwo": + { + "label": "Flow Rate two", + "description": "New Flow rate Extruder 2", + "unit": "%", + "type": "int", + "default_value": 100, + "minimum_value": "1", + "minimum_value_warning": "10", + "maximum_value_warning": "200", + "enabled": "g5_Tweak_flowrateTwo" + }, + "h1_Tweak_bedTemp": + { + "label": "Tweak Bed Temp", + "description": "Select if Bed Temperature has to be tweaked", + "type": "bool", + "default_value": false + }, + "h2_bedTemp": + { + "label": "Bed Temp", + "description": "New Bed Temperature", + "unit": "C", + "type": "float", + "default_value": 60, + "minimum_value": "0", + "minimum_value_warning": "30", + "maximum_value_warning": "120", + "enabled": "h1_Tweak_bedTemp" + }, + "i1_Tweak_extruderOne": + { + "label": "Tweak Extruder 1 Temp", + "description": "Select if First Extruder Temperature has to be tweaked", + "type": "bool", + "default_value": false + }, + "i2_extruderOne": + { + "label": "Extruder 1 Temp", + "description": "New First Extruder Temperature", + "unit": "C", + "type": "float", + "default_value": 190, + "minimum_value": "0", + "minimum_value_warning": "160", + "maximum_value_warning": "250", + "enabled": "i1_Tweak_extruderOne" + }, + "i3_Tweak_extruderTwo": + { + "label": "Tweak Extruder 2 Temp", + "description": "Select if Second Extruder Temperature has to be tweaked", + "type": "bool", + "default_value": false + }, + "i4_extruderTwo": + { + "label": "Extruder 2 Temp", + "description": "New Second Extruder Temperature", + "unit": "C", + "type": "float", + "default_value": 190, + "minimum_value": "0", + "minimum_value_warning": "160", + "maximum_value_warning": "250", + "enabled": "i3_Tweak_extruderTwo" + }, + "j1_Tweak_fanSpeed": + { + "label": "Tweak Fan Speed", + "description": "Select if Fan Speed has to be tweaked", + "type": "bool", + "default_value": false + }, + "j2_fanSpeed": + { + "label": "Fan Speed", + "description": "New Fan Speed (0-255)", + "unit": "PWM", + "type": "int", + "default_value": 255, + "minimum_value": "0", + "minimum_value_warning": "15", + "maximum_value_warning": "255", + "enabled": "j1_Tweak_fanSpeed" + } + } + }""" + + def getValue(self, line, key, default = None): #replace default getvalue due to comment-reading feature + if not key in line or (";" in line and line.find(key) > line.find(";") and + not ";TweakAtZ" in key and not ";LAYER:" in key): + return default + subPart = line[line.find(key) + len(key):] #allows for string lengths larger than 1 + if ";TweakAtZ" in key: + m = re.search("^[0-4]", subPart) + elif ";LAYER:" in key: + m = re.search("^[+-]?[0-9]*", subPart) + else: + #the minus at the beginning allows for negative values, e.g. for delta printers + m = re.search("^[-]?[0-9]*\.?[0-9]*", subPart) + if m == None: + return default + try: + return float(m.group(0)) + except: + return default + + def execute(self, data): + #Check which tweaks should apply + TweakProp = {"speed": self.getSettingValueByKey("e1_Tweak_speed"), + "flowrate": self.getSettingValueByKey("g1_Tweak_flowrate"), + "flowrateOne": self.getSettingValueByKey("g3_Tweak_flowrateOne"), + "flowrateTwo": self.getSettingValueByKey("g5_Tweak_flowrateTwo"), + "bedTemp": self.getSettingValueByKey("h1_Tweak_bedTemp"), + "extruderOne": self.getSettingValueByKey("i1_Tweak_extruderOne"), + "extruderTwo": self.getSettingValueByKey("i3_Tweak_extruderTwo"), + "fanSpeed": self.getSettingValueByKey("j1_Tweak_fanSpeed")} + TweakPrintSpeed = self.getSettingValueByKey("f1_Tweak_printspeed") + TweakStrings = {"speed": "M220 S%f\n", + "flowrate": "M221 S%f\n", + "flowrateOne": "M221 T0 S%f\n", + "flowrateTwo": "M221 T1 S%f\n", + "bedTemp": "M140 S%f\n", + "extruderOne": "M104 S%f T0\n", + "extruderTwo": "M104 S%f T1\n", + "fanSpeed": "M106 S%d\n"} + target_values = {"speed": self.getSettingValueByKey("e2_speed"), + "printspeed": self.getSettingValueByKey("f2_printspeed"), + "flowrate": self.getSettingValueByKey("g2_flowrate"), + "flowrateOne": self.getSettingValueByKey("g4_flowrateOne"), + "flowrateTwo": self.getSettingValueByKey("g6_flowrateTwo"), + "bedTemp": self.getSettingValueByKey("h2_bedTemp"), + "extruderOne": self.getSettingValueByKey("i2_extruderOne"), + "extruderTwo": self.getSettingValueByKey("i4_extruderTwo"), + "fanSpeed": self.getSettingValueByKey("j2_fanSpeed")} + old = {"speed": -1, "flowrate": -1, "flowrateOne": -1, "flowrateTwo": -1, "platformTemp": -1, "extruderOne": -1, + "extruderTwo": -1, "bedTemp": -1, "fanSpeed": -1, "state": -1} + twLayers = self.getSettingValueByKey("d_twLayers") + if self.getSettingValueByKey("c_behavior") == "single_layer": + behavior = 1 + else: + behavior = 0 + try: + twLayers = max(int(twLayers),1) #for the case someone entered something as "funny" as -1 + except: + twLayers = 1 + pres_ext = 0 + done_layers = 0 + z = 0 + x = None + y = None + layer = -100000 #layer no. may be negative (raft) but never that low + # state 0: deactivated, state 1: activated, state 2: active, but below z, + # state 3: active and partially executed (multi layer), state 4: active and passed z + state = 1 + # IsUM2: Used for reset of values (ok for Marlin/Sprinter), + # has to be set to 1 for UltiGCode (work-around for missing default values) + IsUM2 = False + oldValueUnknown = False + TWinstances = 0 + + if self.getSettingValueByKey("a_trigger") == "layer_no": + targetL_i = int(self.getSettingValueByKey("b_targetL")) + targetZ = 100000 + else: + targetL_i = -100000 + targetZ = self.getSettingValueByKey("b_targetZ") + index = 0 + for active_layer in data: + modified_gcode = "" + lines = active_layer.split("\n") + for line in lines: + if ";Generated with Cura_SteamEngine" in line: + TWinstances += 1 + modified_gcode += ";TweakAtZ instances: %d\n" % TWinstances + if not ("M84" in line or "M25" in line or ("G1" in line and TweakPrintSpeed and (state==3 or state==4)) or + ";TweakAtZ instances:" in line): + modified_gcode += line + "\n" + IsUM2 = ("FLAVOR:UltiGCode" in line) or IsUM2 #Flavor is UltiGCode! + if ";TweakAtZ-state" in line: #checks for state change comment + state = self.getValue(line, ";TweakAtZ-state", state) + if ";TweakAtZ instances:" in line: + try: + tempTWi = int(line[20:]) + except: + tempTWi = TWinstances + TWinstances = tempTWi + if ";Small layer" in line: #checks for begin of Cool Head Lift + old["state"] = state + state = 0 + if ";LAYER:" in line: #new layer no. found + if state == 0: + state = old["state"] + layer = self.getValue(line, ";LAYER:", layer) + if targetL_i > -100000: #target selected by layer no. + if (state == 2 or targetL_i == 0) and layer == targetL_i: #determine targetZ from layer no.; checks for tweak on layer 0 + state = 2 + targetZ = z + 0.001 + if (self.getValue(line, "T", None) is not None) and (self.getValue(line, "M", None) is None): #looking for single T-cmd + pres_ext = self.getValue(line, "T", pres_ext) + if "M190" in line or "M140" in line and state < 3: #looking for bed temp, stops after target z is passed + old["bedTemp"] = self.getValue(line, "S", old["bedTemp"]) + if "M109" in line or "M104" in line and state < 3: #looking for extruder temp, stops after target z is passed + if self.getValue(line, "T", pres_ext) == 0: + old["extruderOne"] = self.getValue(line, "S", old["extruderOne"]) + elif self.getValue(line, "T", pres_ext) == 1: + old["extruderTwo"] = self.getValue(line, "S", old["extruderTwo"]) + if "M107" in line: #fan is stopped; is always updated in order not to miss switch off for next object + old["fanSpeed"] = 0 + if "M106" in line and state < 3: #looking for fan speed + old["fanSpeed"] = self.getValue(line, "S", old["fanSpeed"]) + if "M221" in line and state < 3: #looking for flow rate + tmp_extruder = self.getValue(line,"T",None) + if tmp_extruder == None: #check if extruder is specified + old["flowrate"] = self.getValue(line, "S", old["flowrate"]) + elif tmp_extruder == 0: #first extruder + old["flowrateOne"] = self.getValue(line, "S", old["flowrateOne"]) + elif tmp_extruder == 1: #second extruder + old["flowrateOne"] = self.getValue(line, "S", old["flowrateOne"]) + if ("M84" in line or "M25" in line): + if state>0 and TweakProp["speed"]: #"finish" commands for UM Original and UM2 + modified_gcode += "M220 S100 ; speed reset to 100% at the end of print\n" + modified_gcode += "M117 \n" + modified_gcode += line + "\n" + if "G1" in line or "G0" in line: + newZ = self.getValue(line, "Z", z) + x = self.getValue(line, "X", None) + y = self.getValue(line, "Y", None) + e = self.getValue(line, "E", None) + f = self.getValue(line, "F", None) + if 'G1' in line and TweakPrintSpeed and (state==3 or state==4): + # check for pure print movement in target range: + if x != None and y != None and f != None and e != None and newZ==z: + modified_gcode += "G1 F%d X%1.3f Y%1.3f E%1.5f\n" % (int(f / 100.0 * float(target_values["printspeed"])), self.getValue(line, "X"), + self.getValue(line, "Y"), self.getValue(line, "E")) + else: #G1 command but not a print movement + modified_gcode += line + "\n" + # no tweaking on retraction hops which have no x and y coordinate: + if (newZ != z) and (x is not None) and (y is not None): + z = newZ + if z < targetZ and state == 1: + state = 2 + if z >= targetZ and state == 2: + state = 3 + done_layers = 0 + for key in TweakProp: + if TweakProp[key] and old[key]==-1: #old value is not known + oldValueUnknown = True + if oldValueUnknown: #the tweaking has to happen within one layer + twLayers = 1 + if IsUM2: #Parameters have to be stored in the printer (UltiGCode=UM2) + modified_gcode += "M605 S%d;stores parameters before tweaking\n" % (TWinstances-1) + if behavior == 1: #single layer tweak only and then reset + twLayers = 1 + if TweakPrintSpeed and behavior == 0: + twLayers = done_layers + 1 + if state==3: + if twLayers-done_layers>0: #still layers to go? + if targetL_i > -100000: + modified_gcode += ";TweakAtZ V%s: executed at Layer %d\n" % (self.version,layer) + modified_gcode += "M117 Printing... tw@L%4d\n" % layer + else: + modified_gcode += (";TweakAtZ V%s: executed at %1.2f mm\n" % (self.version,z)) + modified_gcode += "M117 Printing... tw@%5.1f\n" % z + for key in TweakProp: + if TweakProp[key]: + modified_gcode += TweakStrings[key] % float(old[key]+(float(target_values[key])-float(old[key]))/float(twLayers)*float(done_layers+1)) + done_layers += 1 + else: + state = 4 + if behavior == 1: #reset values after one layer + if targetL_i > -100000: + modified_gcode += ";TweakAtZ V%s: reset on Layer %d\n" % (self.version,layer) + else: + modified_gcode += ";TweakAtZ V%s: reset at %1.2f mm\n" % (self.version,z) + if IsUM2 and oldValueUnknown: #executes on UM2 with Ultigcode and machine setting + modified_gcode += "M606 S%d;recalls saved settings\n" % (TWinstances-1) + else: #executes on RepRap, UM2 with Ultigcode and Cura setting + for key in TweakProp: + if TweakProp[key]: + modified_gcode += TweakStrings[key] % float(old[key]) + # re-activates the plugin if executed by pre-print G-command, resets settings: + if (z < targetZ or layer == 0) and state >= 3: #resets if below tweak level or at level 0 + state = 2 + done_layers = 0 + if targetL_i > -100000: + modified_gcode += ";TweakAtZ V%s: reset below Layer %d\n" % (self.version,targetL_i) + else: + modified_gcode += ";TweakAtZ V%s: reset below %1.2f mm\n" % (self.version,targetZ) + if IsUM2 and oldValueUnknown: #executes on UM2 with Ultigcode and machine setting + modified_gcode += "M606 S%d;recalls saved settings\n" % (TWinstances-1) + else: #executes on RepRap, UM2 with Ultigcode and Cura setting + for key in TweakProp: + if TweakProp[key]: + modified_gcode += TweakStrings[key] % float(old[key]) + data[index] = modified_gcode + index += 1 + return data From e3e6f301f9172c6bf811ac5ee432c277ba08deb2 Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Tue, 9 Jan 2018 10:42:03 +0100 Subject: [PATCH 24/50] CURA-4778 Add up to 8 different colors when loading a GCode, since we support up to 8 extruders in CFP --- plugins/GCodeReader/FlavorParser.py | 8 +++++++- plugins/SimulationView/SimulationView.py | 2 +- plugins/SimulationView/SimulationView.qml | 1 - 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/plugins/GCodeReader/FlavorParser.py b/plugins/GCodeReader/FlavorParser.py index c604ab1b6f..f63ba3ca69 100644 --- a/plugins/GCodeReader/FlavorParser.py +++ b/plugins/GCodeReader/FlavorParser.py @@ -418,9 +418,15 @@ class FlavorParser: self._layer_number += 1 current_path.clear() - material_color_map = numpy.zeros((10, 4), dtype = numpy.float32) + material_color_map = numpy.zeros((8, 4), dtype = numpy.float32) material_color_map[0, :] = [0.0, 0.7, 0.9, 1.0] material_color_map[1, :] = [0.7, 0.9, 0.0, 1.0] + material_color_map[2, :] = [0.9, 0.0, 0.7, 1.0] + material_color_map[3, :] = [0.7, 0.0, 0.0, 1.0] + material_color_map[4, :] = [0.0, 0.7, 0.0, 1.0] + material_color_map[5, :] = [0.0, 0.0, 0.7, 1.0] + material_color_map[6, :] = [0.3, 0.3, 0.3, 1.0] + material_color_map[7, :] = [0.7, 0.7, 0.7, 1.0] layer_mesh = self._layer_data_builder.build(material_color_map) decorator = LayerDataDecorator() decorator.setLayerData(layer_mesh) diff --git a/plugins/SimulationView/SimulationView.py b/plugins/SimulationView/SimulationView.py index 7a716d3b2b..f667aff998 100644 --- a/plugins/SimulationView/SimulationView.py +++ b/plugins/SimulationView/SimulationView.py @@ -104,7 +104,7 @@ class SimulationView(View): title = catalog.i18nc("@info:title", "Simulation View")) def _resetSettings(self): - self._layer_view_type = 0 # 0 is material color, 1 is color by linetype, 2 is speed + self._layer_view_type = 0 # 0 is material color, 1 is color by linetype, 2 is speed, 3 is layer thickness self._extruder_count = 0 self._extruder_opacity = [1.0, 1.0, 1.0, 1.0] self._show_travel_moves = 0 diff --git a/plugins/SimulationView/SimulationView.qml b/plugins/SimulationView/SimulationView.qml index 19ae81a6e3..11b985f77c 100644 --- a/plugins/SimulationView/SimulationView.qml +++ b/plugins/SimulationView/SimulationView.qml @@ -176,7 +176,6 @@ Item viewSettings.show_feedrate_gradient = viewSettings.show_gradient && (type_id == 2); viewSettings.show_thickness_gradient = viewSettings.show_gradient && (type_id == 3); } - } Label From 59d7cc663a45a59c8e03260357a394fc137221cf Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 9 Jan 2018 10:36:00 +0100 Subject: [PATCH 25/50] Fix creating ExtruderStack for single-extrusion machine at runtime Move per-extruder settings from the machine's quality changes container to the extruder's quality changes container. --- cura/Settings/CuraContainerRegistry.py | 27 ++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/cura/Settings/CuraContainerRegistry.py b/cura/Settings/CuraContainerRegistry.py index a078240d80..394e83b977 100644 --- a/cura/Settings/CuraContainerRegistry.py +++ b/cura/Settings/CuraContainerRegistry.py @@ -515,6 +515,7 @@ class CuraContainerRegistry(ContainerRegistry): extruder_quality_changes_container = self.findInstanceContainers(name = machine.qualityChanges.getName(), extruder = extruder_id) if extruder_quality_changes_container: extruder_quality_changes_container = extruder_quality_changes_container[0] + quality_changes_id = extruder_quality_changes_container.getId() extruder_stack.setQualityChangesById(quality_changes_id) else: @@ -525,10 +526,36 @@ class CuraContainerRegistry(ContainerRegistry): if extruder_quality_changes_container: quality_changes_id = extruder_quality_changes_container.getId() extruder_stack.setQualityChangesById(quality_changes_id) + else: + # if we still cannot find a quality changes container for the extruder, create a new one + container_id = self.uniqueName(extruder_stack.getId() + "_user") + container_name = machine.qualityChanges.getName() + extruder_quality_changes_container = InstanceContainer(container_id) + extruder_quality_changes_container.setName(container_name) + extruder_quality_changes_container.addMetaDataEntry("type", "quality_changes") + extruder_quality_changes_container.addMetaDataEntry("setting_version", CuraApplication.SettingVersion) + extruder_quality_changes_container.addMetaDataEntry("extruder", extruder_stack.definition.getId()) + extruder_quality_changes_container.addMetaDataEntry("quality_type", machine.qualityChanges.getMetaDataEntry("quality_type")) + extruder_quality_changes_container.setDefinition(machine.definition.getId()) if not extruder_quality_changes_container: Logger.log("w", "Could not find quality_changes named [%s] for extruder [%s]", machine.qualityChanges.getName(), extruder_stack.getId()) + else: + # move all per-extruder settings to the extruder's quality changes + for qc_setting_key in machine.qualityChanges.getAllKeys(): + settable_per_extruder = machine.getProperty(qc_setting_key, "settable_per_extruder") + if settable_per_extruder: + setting_value = machine.qualityChanges.getProperty(qc_setting_key, "value") + + setting_definition = machine.getSettingDefinition(qc_setting_key) + new_instance = SettingInstance(setting_definition, definition_changes) + new_instance.setProperty("value", setting_value) + new_instance.resetState() # Ensure that the state is not seen as a user state. + extruder_quality_changes_container.addInstance(new_instance) + extruder_quality_changes_container.setDirty(True) + + machine.qualityChanges.removeInstance(qc_setting_key, postpone_emit=True) else: extruder_stack.setQualityChangesById("empty_quality_changes") From 8e5167be762b1e383023ca788dd095eac1f90522 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 9 Jan 2018 13:23:24 +0100 Subject: [PATCH 26/50] Use the same machine def for extruder quality changes containers --- cura/Settings/CuraContainerRegistry.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/Settings/CuraContainerRegistry.py b/cura/Settings/CuraContainerRegistry.py index 394e83b977..9a64f1421e 100644 --- a/cura/Settings/CuraContainerRegistry.py +++ b/cura/Settings/CuraContainerRegistry.py @@ -536,7 +536,7 @@ class CuraContainerRegistry(ContainerRegistry): extruder_quality_changes_container.addMetaDataEntry("setting_version", CuraApplication.SettingVersion) extruder_quality_changes_container.addMetaDataEntry("extruder", extruder_stack.definition.getId()) extruder_quality_changes_container.addMetaDataEntry("quality_type", machine.qualityChanges.getMetaDataEntry("quality_type")) - extruder_quality_changes_container.setDefinition(machine.definition.getId()) + extruder_quality_changes_container.setDefinition(machine.qualityChanges.getDefinition().getId()) if not extruder_quality_changes_container: Logger.log("w", "Could not find quality_changes named [%s] for extruder [%s]", From c91eb30de9499e9e6cf813da66d5f65d7116f54b Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 9 Jan 2018 13:24:38 +0100 Subject: [PATCH 27/50] Skip loaded instance containers When trying to apply the fix for single extrusion machines by creating a new ExtruderStack, skip the quality changes container that has already been loaded. --- cura/Settings/CuraContainerRegistry.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cura/Settings/CuraContainerRegistry.py b/cura/Settings/CuraContainerRegistry.py index 9a64f1421e..873876c30d 100644 --- a/cura/Settings/CuraContainerRegistry.py +++ b/cura/Settings/CuraContainerRegistry.py @@ -589,6 +589,9 @@ class CuraContainerRegistry(ContainerRegistry): if parser["general"]["name"] == name: # load the container container_id = os.path.basename(file_path).replace(".inst.cfg", "") + if self.findInstanceContainers(id = container_id): + # this container is already in the registry, skip it + continue instance_container = InstanceContainer(container_id) with open(file_path, "r") as f: From 78b9a14007d4bd83432b7d7643d2d9a4fbd122e0 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 9 Jan 2018 13:25:53 +0100 Subject: [PATCH 28/50] Fix all possible quality changes containers for single extrusion In the current fix, the quality changes that are applicable to the machine may not have been fixed yet because they are not active at that moment. This commit makes sure that for a single extrusion machine which has just been updated to have an ExtruderStack, all the quality changes containers that are applicable to this machine will be updated as well. --- cura/Settings/CuraContainerRegistry.py | 39 ++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/cura/Settings/CuraContainerRegistry.py b/cura/Settings/CuraContainerRegistry.py index 873876c30d..564b83df6d 100644 --- a/cura/Settings/CuraContainerRegistry.py +++ b/cura/Settings/CuraContainerRegistry.py @@ -561,6 +561,45 @@ class CuraContainerRegistry(ContainerRegistry): self.addContainer(extruder_stack) + # Also need to fix the other qualities that are suitable for this machine. Those quality changes may still have + # per-extruder settings in the container for the machine instead of the extruder. + quality_changes_machine_definition_id = machine.qualityChanges.getDefinition().getId() + qcs = self.findInstanceContainers(type = "quality_changes", definition = quality_changes_machine_definition_id) + qc_groups = {} # map of qc names -> qc containers + for qc in qcs: + qc_name = qc.getName() + if qc_name not in qc_groups: + qc_groups[qc_name] = [] + qc_groups[qc_name].append(qc) + # try to find from the quality changes cura directory too + quality_changes_container = self._findQualityChangesContainerInCuraFolder(machine.qualityChanges.getName()) + if quality_changes_container: + qc_groups[qc_name].append(quality_changes_container) + + for qc_name, qc_list in qc_groups.items(): + qc_dict = {"global": None, "extruders": []} + for qc in qc_list: + extruder_def_id = qc.getMetaDataEntry("extruder") + if extruder_def_id is not None: + qc_dict["extruders"].append(qc) + else: + qc_dict["global"] = qc + if qc_dict["global"] is not None and len(qc_dict["extruders"]) == 1: + # move per-extruder settings + for qc_setting_key in qc_dict["global"].getAllKeys(): + settable_per_extruder = machine.getProperty(qc_setting_key, "settable_per_extruder") + if settable_per_extruder: + setting_value = qc_dict["global"].getProperty(qc_setting_key, "value") + + setting_definition = machine.getSettingDefinition(qc_setting_key) + new_instance = SettingInstance(setting_definition, definition_changes) + new_instance.setProperty("value", setting_value) + new_instance.resetState() # Ensure that the state is not seen as a user state. + qc_dict["extruders"][0].addInstance(new_instance) + qc_dict["extruders"][0].setDirty(True) + + qc_dict["global"].removeInstance(qc_setting_key, postpone_emit=True) + # Set next stack at the end extruder_stack.setNextStack(machine) From d633a4c11265394f6aaa67721f3dfd85221907b8 Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Tue, 9 Jan 2018 13:38:41 +0100 Subject: [PATCH 29/50] Fix: cura does not profile form G-code CURA-4776 --- cura/Settings/CuraContainerRegistry.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/cura/Settings/CuraContainerRegistry.py b/cura/Settings/CuraContainerRegistry.py index a078240d80..15168af0a4 100644 --- a/cura/Settings/CuraContainerRegistry.py +++ b/cura/Settings/CuraContainerRegistry.py @@ -202,7 +202,6 @@ class CuraContainerRegistry(ContainerRegistry): for plugin_id, meta_data in self._getIOPlugins("profile_reader"): if meta_data["profile_reader"][0]["extension"] != extension: continue - profile_reader = plugin_registry.getPluginObject(plugin_id) try: profile_or_list = profile_reader.read(file_name) # Try to open the file with the profile reader. @@ -215,6 +214,20 @@ class CuraContainerRegistry(ContainerRegistry): name_seed = os.path.splitext(os.path.basename(file_name))[0] new_name = self.uniqueName(name_seed) + # if the loaded profile comes from g-code then the instance cointaners should be + # defined differently + file_extension = os.path.splitext(file_name)[1][1:] + if file_extension == "gcode": + for item in profile_or_list: + item.metaData["name"] = new_name + + if item.getMetaDataEntry("extruder") is None: + temp_defintion = item.getMetaDataEntry("definition") + item.metaData["id"] = temp_defintion + "_" + new_name + elif item.getMetaDataEntry("extruder") is not None: + temp_extruder = item.getMetaDataEntry("extruder") + item.metaData["id"] = temp_extruder + "_" + new_name + # Ensure it is always a list of profiles if type(profile_or_list) is not list: profile_or_list = [profile_or_list] From 5936ebaa80636dc7d2189f47d6426685151cabb6 Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Tue, 9 Jan 2018 13:48:20 +0100 Subject: [PATCH 30/50] Fix another case of scene node checking by subclass, related to CURA-4780 --- cura/OneAtATimeIterator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/OneAtATimeIterator.py b/cura/OneAtATimeIterator.py index 44f8d2766a..755680e62f 100644 --- a/cura/OneAtATimeIterator.py +++ b/cura/OneAtATimeIterator.py @@ -18,7 +18,7 @@ class OneAtATimeIterator(Iterator.Iterator): def _fillStack(self): node_list = [] for node in self._scene_node.getChildren(): - if not type(node) is SceneNode: + if not issubclass(type(node), SceneNode): continue if node.callDecoration("getConvexHull"): From 33f0e8cb6559cd17721883473f112a507ae1a136 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 9 Jan 2018 13:58:04 +0100 Subject: [PATCH 31/50] Use isinstance() to check if a node is a SceneNode CURA-4780 --- cura/OneAtATimeIterator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/OneAtATimeIterator.py b/cura/OneAtATimeIterator.py index 755680e62f..5653c8f1fb 100644 --- a/cura/OneAtATimeIterator.py +++ b/cura/OneAtATimeIterator.py @@ -18,7 +18,7 @@ class OneAtATimeIterator(Iterator.Iterator): def _fillStack(self): node_list = [] for node in self._scene_node.getChildren(): - if not issubclass(type(node), SceneNode): + if not isinstance(node, SceneNode): continue if node.callDecoration("getConvexHull"): From f9286d4bd59a29ec6c33d3345d5c7c18db53027d Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Tue, 9 Jan 2018 15:50:32 +0100 Subject: [PATCH 32/50] Fix color swatch not being updated after color selection change - CURA-4774 --- resources/qml/Preferences/MaterialView.qml | 48 +++++++++++++++------- 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/resources/qml/Preferences/MaterialView.qml b/resources/qml/Preferences/MaterialView.qml index 311150c6b9..c3f36f5125 100644 --- a/resources/qml/Preferences/MaterialView.qml +++ b/resources/qml/Preferences/MaterialView.qml @@ -104,14 +104,13 @@ TabView Label { width: scrollView.columnWidth; height: parent.rowHeight; verticalAlignment: Qt.AlignVCenter; text: catalog.i18nc("@label", "Color") } - Row - { - width: scrollView.columnWidth; - height: parent.rowHeight; + Row { + width: scrollView.columnWidth + height: parent.rowHeight spacing: Math.floor(UM.Theme.getSize("default_margin").width/2) - Rectangle - { + // color indicator square + Rectangle { id: colorSelector color: properties.color_code @@ -121,17 +120,36 @@ TabView anchors.verticalCenter: parent.verticalCenter - MouseArea { anchors.fill: parent; onClicked: colorDialog.open(); enabled: base.editingEnabled } + // open the color selection dialog on click + MouseArea { + anchors.fill: parent + onClicked: colorDialog.open() + enabled: base.editingEnabled + } } - ReadOnlyTextField - { + + // make sure the color stays connected after changing the color + Binding { + target: colorSelector + property: "color" + value: properties.color_code + } + + // pretty color name text field + ReadOnlyTextField { id: colorLabel; text: properties.color_name; readOnly: !base.editingEnabled onEditingFinished: base.setMetaDataEntry("color_name", properties.color_name, text) } - ColorDialog { id: colorDialog; color: properties.color_code; onAccepted: base.setMetaDataEntry("color_code", properties.color_code, color) } + // popup dialog to select a new color + // if successful it sets the properties.color_code value to the new color + ColorDialog { + id: colorDialog + color: properties.color_code + onAccepted: base.setMetaDataEntry("color_code", properties.color_code, color) + } } Item { width: parent.width; height: UM.Theme.getSize("default_margin").height } @@ -401,11 +419,11 @@ TabView } // Tiny convenience function to check if a value really changed before trying to set it. - function setMetaDataEntry(entry_name, old_value, new_value) - { - if(old_value != new_value) - { - Cura.ContainerManager.setContainerMetaDataEntry(base.containerId, entry_name, new_value); + function setMetaDataEntry(entry_name, old_value, new_value) { + if (old_value != new_value) { + Cura.ContainerManager.setContainerMetaDataEntry(base.containerId, entry_name, new_value) + // make sure the UI properties are updated as well since we don't re-fetch the entire model here + properties[entry_name] = new_value } } From 3de4940d6952a4a6c3c0934e5d7836996b7bd31f Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Tue, 9 Jan 2018 16:19:29 +0100 Subject: [PATCH 33/50] Simplify creating, duplicating materials in preferences, extract logic to python, code-style fixes --- cura/Settings/ContainerManager.py | 16 +++ resources/qml/Preferences/MaterialsPage.qml | 104 ++++++++------------ 2 files changed, 58 insertions(+), 62 deletions(-) diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index 209e1ec8fd..eefc109cbc 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -816,6 +816,22 @@ class ContainerManager(QObject): ContainerRegistry.getInstance().addContainer(container_to_add) return self._getMaterialContainerIdForActiveMachine(clone_of_original) + ## Create a duplicate of a material or it's original entry + # + # \return \type{str} the id of the newly created container. + @pyqtSlot(str, result = str) + def duplicateOriginalMaterial(self, material_id): + + # check if the given material has a base file (i.e. was shipped by default) + base_file = self.getContainerMetaDataEntry(material_id, "base_file") + + if base_file == "": + # there is no base file, so duplicate by ID + return self.duplicateMaterial(material_id) + else: + # there is a base file, so duplicate the original material + return self.duplicateMaterial(base_file) + ## Create a new material by cloning Generic PLA for the current material diameter and setting the GUID to something unqiue # # \return \type{str} the id of the newly created container. diff --git a/resources/qml/Preferences/MaterialsPage.qml b/resources/qml/Preferences/MaterialsPage.qml index 81c1bd711a..228f9c8ea2 100644 --- a/resources/qml/Preferences/MaterialsPage.qml +++ b/resources/qml/Preferences/MaterialsPage.qml @@ -132,93 +132,73 @@ UM.ManagementPage } buttons: [ - Button - { - text: catalog.i18nc("@action:button", "Activate"); + + // Activate button + Button { + text: catalog.i18nc("@action:button", "Activate") iconName: "list-activate"; enabled: base.currentItem != null && base.currentItem.id != Cura.MachineManager.activeMaterialId && Cura.MachineManager.hasMaterials - onClicked: - { - forceActiveFocus(); + onClicked: { + forceActiveFocus() Cura.MachineManager.setActiveMaterial(base.currentItem.id) currentItem = base.model.getItem(base.objectList.currentIndex) // Refresh the current item. } }, - Button - { + + // Create button + Button { text: catalog.i18nc("@action:button", "Create") iconName: "list-add" - onClicked: - { - forceActiveFocus(); - var material_id = Cura.ContainerManager.createMaterial() - if(material_id == "") - { - return - } - if(Cura.MachineManager.hasMaterials) - { - Cura.MachineManager.setActiveMaterial(material_id) - } - base.objectList.currentIndex = base.getIndexById(material_id); + onClicked: { + forceActiveFocus() + Cura.ContainerManager.createMaterial() } }, - Button - { + + // Duplicate button + Button { text: catalog.i18nc("@action:button", "Duplicate"); iconName: "list-add"; enabled: base.currentItem != null - onClicked: - { - forceActiveFocus(); - var base_file = Cura.ContainerManager.getContainerMetaDataEntry(base.currentItem.id, "base_file") - // We need to copy the base container instead of the specific variant. - var material_id = base_file == "" ? Cura.ContainerManager.duplicateMaterial(base.currentItem.id): Cura.ContainerManager.duplicateMaterial(base_file) - if(material_id == "") - { - return - } - if(Cura.MachineManager.hasMaterials) - { - Cura.MachineManager.setActiveMaterial(material_id) - } - // TODO: this doesn't work because the source is a bit delayed - base.objectList.currentIndex = base.getIndexById(material_id); + onClicked: { + forceActiveFocus() + Cura.ContainerManager.duplicateOriginalMaterial(base.currentItem.id) } }, - Button - { - text: catalog.i18nc("@action:button", "Remove"); - iconName: "list-remove"; + + // Remove button + Button { + text: catalog.i18nc("@action:button", "Remove") + iconName: "list-remove" enabled: base.currentItem != null && !base.currentItem.readOnly && !Cura.ContainerManager.isContainerUsed(base.currentItem.id) - onClicked: - { - forceActiveFocus(); - confirmDialog.open(); + onClicked: { + forceActiveFocus() + confirmDialog.open() } }, - Button - { - text: catalog.i18nc("@action:button", "Import"); - iconName: "document-import"; - onClicked: - { - forceActiveFocus(); - importDialog.open(); + + // Import button + Button { + text: catalog.i18nc("@action:button", "Import") + iconName: "document-import" + onClicked: { + forceActiveFocus() + importDialog.open() } - visible: true; + visible: true }, - Button - { + + // Export button + Button { text: catalog.i18nc("@action:button", "Export") iconName: "document-export" - onClicked: - { - forceActiveFocus(); - exportDialog.open(); + onClicked: { + forceActiveFocus() + exportDialog.open() } enabled: currentItem != null } + ] Item { From 93599de64239644ea8a86434d5f2bbafa2b47873 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 9 Jan 2018 17:02:39 +0100 Subject: [PATCH 34/50] Update current index in material dialog CURA-4774 There is a delay so we update the current index when the model gets changed. --- resources/qml/Preferences/MaterialsPage.qml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/resources/qml/Preferences/MaterialsPage.qml b/resources/qml/Preferences/MaterialsPage.qml index 228f9c8ea2..6b041b895a 100644 --- a/resources/qml/Preferences/MaterialsPage.qml +++ b/resources/qml/Preferences/MaterialsPage.qml @@ -153,6 +153,15 @@ UM.ManagementPage forceActiveFocus() Cura.ContainerManager.createMaterial() } + + Connections + { + target: base.objectList.model + onItemsChanged: + { + base.objectList.currentIndex = base.getIndexById(Cura.MachineManager.activeMaterialId); + } + } }, // Duplicate button From 30870c5ef2187557c53d133e6953d944ae64f098 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 9 Jan 2018 17:34:53 +0100 Subject: [PATCH 35/50] Refactor skip reset setting CURA-4760 --- .../PerObjectSettingVisibilityHandler.py | 10 ++++++---- .../PerObjectSettingsTool/PerObjectSettingsPanel.qml | 4 ++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/plugins/PerObjectSettingsTool/PerObjectSettingVisibilityHandler.py b/plugins/PerObjectSettingsTool/PerObjectSettingVisibilityHandler.py index c7e4deaaa7..3e1df1c7b8 100644 --- a/plugins/PerObjectSettingsTool/PerObjectSettingVisibilityHandler.py +++ b/plugins/PerObjectSettingsTool/PerObjectSettingVisibilityHandler.py @@ -22,7 +22,9 @@ class PerObjectSettingVisibilityHandler(UM.Settings.Models.SettingVisibilityHand self._selected_object_id = None self._node = None self._stack = None - self._skip_setting = None + + # this is a set of settings that will be skipped if the user chooses to reset. + self._skip_reset_setting_set = set() def setSelectedObjectId(self, id): if id != self._selected_object_id: @@ -39,8 +41,8 @@ class PerObjectSettingVisibilityHandler(UM.Settings.Models.SettingVisibilityHand return self._selected_object_id @pyqtSlot(str) - def setSkipSetting(self, setting_name): - self._skip_setting = setting_name + def addSkipResetSetting(self, setting_name): + self._skip_reset_setting_set.add(setting_name) def setVisible(self, visible): if not self._node: @@ -57,7 +59,7 @@ class PerObjectSettingVisibilityHandler(UM.Settings.Models.SettingVisibilityHand # Remove all instances that are not in visibility list for instance in all_instances: # exceptionally skip setting - if self._skip_setting is not None and self._skip_setting == instance.definition.key: + if instance.definition.key in self._skip_reset_setting_set: continue if instance.definition.key not in visible: settings.removeInstance(instance.definition.key) diff --git a/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml b/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml index 2b7b6cd541..10760b9039 100644 --- a/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml +++ b/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml @@ -324,8 +324,8 @@ Item { // force updating the model to sync it with addedSettingsModel if(visible) { - // Set skip setting, it will prevent from restting selected mesh_type - contents.model.visibilityHandler.setSkipSetting(meshTypeSelection.model.get(meshTypeSelection.currentIndex).type) + // Set skip setting, it will prevent from resetting selected mesh_type + contents.model.visibilityHandler.addSkipResetSetting(meshTypeSelection.model.get(meshTypeSelection.currentIndex).type) listview.model.forceUpdate() } } From 3f341a34c62cd2125afa1385e40b6af25b5dad7a Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 10 Jan 2018 08:15:00 +0100 Subject: [PATCH 36/50] Fix gcode job sending issue in gcode_dict refactoring --- .../NetworkClusterPrinterOutputDevice.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py b/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py index 6665380f45..9289981d64 100644 --- a/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py +++ b/plugins/UM3NetworkPrinting/NetworkClusterPrinterOutputDevice.py @@ -80,6 +80,8 @@ class NetworkClusterPrinterOutputDevice(NetworkPrinterOutputDevice.NetworkPrinte self._print_view = None self._request_job = [] + self._job_list = [] + self._monitor_view_qml_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "ClusterMonitorItem.qml") self._control_view_qml_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "ClusterControlItem.qml") @@ -281,14 +283,11 @@ class NetworkClusterPrinterOutputDevice(NetworkPrinterOutputDevice.NetworkPrinte def sendPrintJob(self): nodes, file_name, filter_by_machine, file_handler, kwargs = self._request_job output_build_plate_number = self._job_list.pop(0) - gcode_dict = getattr(Application.getInstance().getController().getScene(), "gcode_dict")[output_build_plate_number] - if not gcode_dict: # Empty build plate + gcode_list = getattr(Application.getInstance().getController().getScene(), "gcode_dict")[output_build_plate_number] + if not gcode_list: # Empty build plate Logger.log("d", "Skipping empty job (build plate number %d).", output_build_plate_number) return self.sendPrintJob() - active_build_plate_id = Application.getInstance().getBuildPlateModel().activeBuildPlate - gcode_list = gcode_dict[active_build_plate_id] - self._send_gcode_start = time.time() Logger.log("d", "Sending print job [%s] to host, build plate [%s]..." % (file_name, output_build_plate_number)) From 91cccedf750ad2307e849af596fd778668610b54 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 10 Jan 2018 08:54:13 +0100 Subject: [PATCH 37/50] Fix upgrading quality changes for single extrusion machines --- cura/Settings/CuraContainerRegistry.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/cura/Settings/CuraContainerRegistry.py b/cura/Settings/CuraContainerRegistry.py index a7119c55b7..6db33931bd 100644 --- a/cura/Settings/CuraContainerRegistry.py +++ b/cura/Settings/CuraContainerRegistry.py @@ -576,7 +576,19 @@ class CuraContainerRegistry(ContainerRegistry): # Also need to fix the other qualities that are suitable for this machine. Those quality changes may still have # per-extruder settings in the container for the machine instead of the extruder. - quality_changes_machine_definition_id = machine.qualityChanges.getDefinition().getId() + if machine.qualityChanges.getId() not in ("empty", "empty_quality_changes"): + quality_changes_machine_definition_id = machine.qualityChanges.getDefinition().getId() + else: + whole_machine_definition = machine.definition + machine_entry = machine.definition.getMetaDataEntry("machine") + if machine_entry is not None: + container_registry = ContainerRegistry.getInstance() + whole_machine_definition = container_registry.findDefinitionContainers(id = machine_entry)[0] + + quality_changes_machine_definition_id = "fdmprinter" + if whole_machine_definition.getMetaDataEntry("has_machine_quality"): + quality_changes_machine_definition_id = machine.definition.getMetaDataEntry("quality_definition", + whole_machine_definition.getId()) qcs = self.findInstanceContainers(type = "quality_changes", definition = quality_changes_machine_definition_id) qc_groups = {} # map of qc names -> qc containers for qc in qcs: From 4801ace5464e2accf1db6a4d62323d3a158e271a Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 10 Jan 2018 08:58:51 +0100 Subject: [PATCH 38/50] Fix monoprice select mini v2 definition CURA-4655 --- resources/definitions/monoprice_select_mini_v2.def.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/definitions/monoprice_select_mini_v2.def.json b/resources/definitions/monoprice_select_mini_v2.def.json index a935cb5a73..87014c136b 100644 --- a/resources/definitions/monoprice_select_mini_v2.def.json +++ b/resources/definitions/monoprice_select_mini_v2.def.json @@ -20,6 +20,6 @@ "retraction_combing": { "default_value": "noskin" }, "retraction_amount" : { "default_value": 2.5}, "retraction_speed" : { "default_value": 40}, - "material_print_temperature_layer_0": { "value": "material_print_temperature + 5" }, + "material_print_temperature_layer_0": { "value": "material_print_temperature + 5" } } } From b295d915f82667646d6c6c954013899cd029c28d Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 10 Jan 2018 11:08:32 +0100 Subject: [PATCH 39/50] Fix line support_infill_rate / support_line_distance for support meshes without generating any support. CURA-4777 --- resources/definitions/fdmprinter.def.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 6eef6b1e9b..22b7992d64 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -3633,7 +3633,7 @@ "minimum_value": "0", "maximum_value_warning": "100", "default_value": 15, - "value": "15 if support_enable else 0", + "value": "15 if support_enable else 0 if support_tree_enable else 15", "enabled": "support_enable or support_tree_enable", "limit_to_extruder": "support_infill_extruder_nr", "settable_per_mesh": false, From fd86cc84e2377134a317f7f9221b1f8e86a1ff1f Mon Sep 17 00:00:00 2001 From: ChrisTerBeke Date: Wed, 10 Jan 2018 11:17:26 +0100 Subject: [PATCH 40/50] check if parent exists before using width and height properties from it --- plugins/MonitorStage/MonitorMainView.qml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins/MonitorStage/MonitorMainView.qml b/plugins/MonitorStage/MonitorMainView.qml index 15b05bed0a..c48f6d0aab 100644 --- a/plugins/MonitorStage/MonitorMainView.qml +++ b/plugins/MonitorStage/MonitorMainView.qml @@ -8,8 +8,9 @@ import Cura 1.0 as Cura Item { - width: parent.width - height: parent.height + // parent could be undefined as this component is not visible at all times + width: parent ? parent.width : 0 + height: parent ? parent.height : 0 // We show a nice overlay on the 3D viewer when the current output device has no monitor view Rectangle From 95361bbeb200bbbffa4296fb53f4a635f98ae89b Mon Sep 17 00:00:00 2001 From: Aleksei S Date: Wed, 10 Jan 2018 11:19:19 +0100 Subject: [PATCH 41/50] Refactoring: profile from Gcode CURA-4776 --- cura/Settings/CuraContainerRegistry.py | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/cura/Settings/CuraContainerRegistry.py b/cura/Settings/CuraContainerRegistry.py index a7119c55b7..b882902ed7 100644 --- a/cura/Settings/CuraContainerRegistry.py +++ b/cura/Settings/CuraContainerRegistry.py @@ -214,19 +214,7 @@ class CuraContainerRegistry(ContainerRegistry): name_seed = os.path.splitext(os.path.basename(file_name))[0] new_name = self.uniqueName(name_seed) - # if the loaded profile comes from g-code then the instance cointaners should be - # defined differently - file_extension = os.path.splitext(file_name)[1][1:] - if file_extension == "gcode": - for item in profile_or_list: - item.metaData["name"] = new_name - if item.getMetaDataEntry("extruder") is None: - temp_defintion = item.getMetaDataEntry("definition") - item.metaData["id"] = temp_defintion + "_" + new_name - elif item.getMetaDataEntry("extruder") is not None: - temp_extruder = item.getMetaDataEntry("extruder") - item.metaData["id"] = temp_extruder + "_" + new_name # Ensure it is always a list of profiles if type(profile_or_list) is not list: @@ -250,6 +238,16 @@ class CuraContainerRegistry(ContainerRegistry): else: #More extruders in the imported file than in the machine. continue #Delete the additional profiles. + # if the loaded profile comes from g-code then the instance containers should be + # defined differently + if extension == "gcode": + if profile.getMetaDataEntry("extruder") is None: + temp_defintion = profile.getMetaDataEntry("definition") + profile.metaData["id"] = (temp_defintion + "_" + new_name).lower() + elif profile.getMetaDataEntry("extruder") is not None: # be sure that extruder data exist + temp_extruder = profile.getMetaDataEntry("extruder") + profile.metaData["id"] = (temp_extruder + "_" + new_name).lower() + result = self._configureProfile(profile, profile_id, new_name) if result is not None: return {"status": "error", "message": catalog.i18nc( From 80aaad83e115ef4308bc633de08fc778effec214 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 10 Jan 2018 14:12:21 +0100 Subject: [PATCH 42/50] CURA-4525 fix manual slice slicing more than one build plate at a time --- plugins/CuraEngineBackend/CuraEngineBackend.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/CuraEngineBackend/CuraEngineBackend.py b/plugins/CuraEngineBackend/CuraEngineBackend.py index c612e889a4..fa5f4dde4d 100755 --- a/plugins/CuraEngineBackend/CuraEngineBackend.py +++ b/plugins/CuraEngineBackend/CuraEngineBackend.py @@ -238,6 +238,8 @@ class CuraEngineBackend(QObject, Backend): self._slicing = True self.slicingStarted.emit() + self.determineAutoSlicing() # Switch timer on or off if appropriate + slice_message = self._socket.createMessage("cura.proto.Slice") self._start_slice_job = StartSliceJob.StartSliceJob(slice_message) self._start_slice_job_build_plate = build_plate_to_be_sliced @@ -584,6 +586,7 @@ class CuraEngineBackend(QObject, Backend): # Somehow this results in an Arcus Error # self.slice() # Testing call slice again, allow backend to restart by using the timer + self.enableTimer() # manually enable timer to be able to invoke slice, also when in manual slice mode self._invokeSlice() ## Called when a g-code message is received from the engine. From 686ac2292d85dc38c826de0c230f2cb784d94e73 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 10 Jan 2018 14:13:18 +0100 Subject: [PATCH 43/50] CURA-4525 CURA-4772 fix gcode not overlapping thoughout build plates --- plugins/CuraEngineBackend/ProcessSlicedLayersJob.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py index be9c3f73f0..c1fc597d80 100644 --- a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py +++ b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py @@ -4,7 +4,6 @@ import gc from UM.Job import Job -from UM.Scene.SceneNode import SceneNode from UM.Application import Application from UM.Mesh.MeshData import MeshData from UM.Preferences import Preferences @@ -17,6 +16,7 @@ from UM.Logger import Logger from UM.Math.Vector import Vector from cura.Scene.BuildPlateDecorator import BuildPlateDecorator +from cura.Scene.CuraSceneNode import CuraSceneNode from cura.Settings.ExtruderManager import ExtruderManager from cura import LayerDataBuilder from cura import LayerDataDecorator @@ -81,7 +81,7 @@ class ProcessSlicedLayersJob(Job): Application.getInstance().getController().activeViewChanged.connect(self._onActiveViewChanged) - new_node = SceneNode() + new_node = CuraSceneNode() new_node.addDecorator(BuildPlateDecorator(self._build_plate_number)) # Force garbage collection. From dab0ebd2084649c2b4348caed7c70b6a7013848e Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 10 Jan 2018 14:25:09 +0100 Subject: [PATCH 44/50] CURA-4525 fix saving empty gcode giving error --- plugins/GCodeWriter/GCodeWriter.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/GCodeWriter/GCodeWriter.py b/plugins/GCodeWriter/GCodeWriter.py index f0e5c88f37..95c48c4d9e 100644 --- a/plugins/GCodeWriter/GCodeWriter.py +++ b/plugins/GCodeWriter/GCodeWriter.py @@ -64,8 +64,8 @@ class GCodeWriter(MeshWriter): gcode_dict = getattr(scene, "gcode_dict") if not gcode_dict: return False - gcode_list = gcode_dict.get(active_build_plate) - if gcode_list: + gcode_list = gcode_dict.get(active_build_plate, None) + if gcode_list is not None: for gcode in gcode_list: stream.write(gcode) # Serialise the current container stack and put it at the end of the file. From 0fdb470ec7eb3fa1766326ceb4ef1eb8fd3b298a Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 10 Jan 2018 14:39:26 +0100 Subject: [PATCH 45/50] CURA-4525 only try to slice next build plate if there are actually build plates to slice --- plugins/CuraEngineBackend/CuraEngineBackend.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/plugins/CuraEngineBackend/CuraEngineBackend.py b/plugins/CuraEngineBackend/CuraEngineBackend.py index fa5f4dde4d..41522b34f2 100755 --- a/plugins/CuraEngineBackend/CuraEngineBackend.py +++ b/plugins/CuraEngineBackend/CuraEngineBackend.py @@ -585,9 +585,10 @@ class CuraEngineBackend(QObject, Backend): Logger.log("d", "See if there is more to slice...") # Somehow this results in an Arcus Error # self.slice() - # Testing call slice again, allow backend to restart by using the timer - self.enableTimer() # manually enable timer to be able to invoke slice, also when in manual slice mode - self._invokeSlice() + # Call slice again using the timer, allowing the backend to restart + if self._build_plates_to_be_sliced: + self.enableTimer() # manually enable timer to be able to invoke slice, also when in manual slice mode + self._invokeSlice() ## Called when a g-code message is received from the engine. # From 6262003069ebfd2eb56889eaaf1596301e0c8250 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 10 Jan 2018 16:01:26 +0100 Subject: [PATCH 46/50] CURA-4525 reset the print information for build plates that are marked for slicing --- cura/PrintInformation.py | 3 ++- plugins/CuraEngineBackend/CuraEngineBackend.py | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/cura/PrintInformation.py b/cura/PrintInformation.py index 60d3c11a49..838628e37c 100644 --- a/cura/PrintInformation.py +++ b/cura/PrintInformation.py @@ -11,6 +11,7 @@ from UM.Preferences import Preferences from UM.Settings.ContainerRegistry import ContainerRegistry from cura.Settings.ExtruderManager import ExtruderManager +from typing import Dict import math import os.path @@ -177,7 +178,7 @@ class PrintInformation(QObject): self._material_amounts = material_amounts self._calculateInformation(build_plate_number) - def _updateTotalPrintTimePerFeature(self, build_plate_number, print_time): + def _updateTotalPrintTimePerFeature(self, build_plate_number, print_time: Dict[str, int]): total_estimated_time = 0 if build_plate_number not in self._print_time_message_values: diff --git a/plugins/CuraEngineBackend/CuraEngineBackend.py b/plugins/CuraEngineBackend/CuraEngineBackend.py index 41522b34f2..61950b4677 100755 --- a/plugins/CuraEngineBackend/CuraEngineBackend.py +++ b/plugins/CuraEngineBackend/CuraEngineBackend.py @@ -444,6 +444,7 @@ class CuraEngineBackend(QObject, Backend): return build_plate_changed.add(source_build_plate_number) + self.printDurationMessage.emit(source_build_plate_number, {}, []) build_plate_changed.discard(None) build_plate_changed.discard(-1) # object not on build plate From d91a2e1ca36ba2ef0311cfd31ed7c75058c8d1be Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 10 Jan 2018 16:04:56 +0100 Subject: [PATCH 47/50] CURA-4525 move reset print information to a better place to prevent it sending info of non existent build plates --- plugins/CuraEngineBackend/CuraEngineBackend.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/CuraEngineBackend/CuraEngineBackend.py b/plugins/CuraEngineBackend/CuraEngineBackend.py index 61950b4677..e8c830b901 100755 --- a/plugins/CuraEngineBackend/CuraEngineBackend.py +++ b/plugins/CuraEngineBackend/CuraEngineBackend.py @@ -444,7 +444,6 @@ class CuraEngineBackend(QObject, Backend): return build_plate_changed.add(source_build_plate_number) - self.printDurationMessage.emit(source_build_plate_number, {}, []) build_plate_changed.discard(None) build_plate_changed.discard(-1) # object not on build plate @@ -461,6 +460,7 @@ class CuraEngineBackend(QObject, Backend): for build_plate_number in build_plate_changed: if build_plate_number not in self._build_plates_to_be_sliced: self._build_plates_to_be_sliced.append(build_plate_number) + self.printDurationMessage.emit(source_build_plate_number, {}, []) self.processingProgress.emit(0.0) self.backendStateChange.emit(BackendState.NotStarted) # if not self._use_timer: @@ -523,7 +523,7 @@ class CuraEngineBackend(QObject, Backend): def _onStackErrorCheckFinished(self): self._is_error_check_scheduled = False - if not self._slicing and self._build_plates_to_be_sliced: #self._need_slicing: + if not self._slicing and self._build_plates_to_be_sliced: self.needsSlicing() self._onChanged() From 665c0a81f40959e39530b895b892937b97023bd4 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Wed, 10 Jan 2018 16:29:36 +0100 Subject: [PATCH 48/50] Removed wrong comment --- plugins/UM3NetworkPrinting/LegacyUM3OutputDevice.py | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/UM3NetworkPrinting/LegacyUM3OutputDevice.py b/plugins/UM3NetworkPrinting/LegacyUM3OutputDevice.py index 126dbbbde3..786b97d034 100644 --- a/plugins/UM3NetworkPrinting/LegacyUM3OutputDevice.py +++ b/plugins/UM3NetworkPrinting/LegacyUM3OutputDevice.py @@ -115,7 +115,6 @@ class LegacyUM3OutputDevice(NetworkedPrinterOutputDevice): self._not_authenticated_message.hide() self._requestAuthentication() - pass # Cura Connect doesn't do any authorization def connect(self): super().connect() From 78b42afbcb0eb8673544ca7b75f42855178f875d Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Wed, 10 Jan 2018 16:40:58 +0100 Subject: [PATCH 49/50] CURA-4776 Add unique id to the profiles so user can import the same profile several times with different names.It also fixes the issue for importing profiles from GCode. --- cura/Settings/CuraContainerRegistry.py | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/cura/Settings/CuraContainerRegistry.py b/cura/Settings/CuraContainerRegistry.py index a0e2abd0b6..9202e57285 100644 --- a/cura/Settings/CuraContainerRegistry.py +++ b/cura/Settings/CuraContainerRegistry.py @@ -214,8 +214,6 @@ class CuraContainerRegistry(ContainerRegistry): name_seed = os.path.splitext(os.path.basename(file_name))[0] new_name = self.uniqueName(name_seed) - - # Ensure it is always a list of profiles if type(profile_or_list) is not list: profile_or_list = [profile_or_list] @@ -238,16 +236,6 @@ class CuraContainerRegistry(ContainerRegistry): else: #More extruders in the imported file than in the machine. continue #Delete the additional profiles. - # if the loaded profile comes from g-code then the instance containers should be - # defined differently - if extension == "gcode": - if profile.getMetaDataEntry("extruder") is None: - temp_defintion = profile.getMetaDataEntry("definition") - profile.metaData["id"] = (temp_defintion + "_" + new_name).lower() - elif profile.getMetaDataEntry("extruder") is not None: # be sure that extruder data exist - temp_extruder = profile.getMetaDataEntry("extruder") - profile.metaData["id"] = (temp_extruder + "_" + new_name).lower() - result = self._configureProfile(profile, profile_id, new_name) if result is not None: return {"status": "error", "message": catalog.i18nc( @@ -280,6 +268,10 @@ class CuraContainerRegistry(ContainerRegistry): profile._id = new_id profile.setName(new_name) + # Set the unique Id to the profile, so it's generating a new one even if the user imports the same profile + # It also solves an issue with importing profiles from G-Codes + profile.setMetaDataEntry("id", new_id) + if "type" in profile.getMetaData(): profile.setMetaDataEntry("type", "quality_changes") else: From 702d7dd3a838fa0bfe0f7aa152d376bc1cb46054 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 11 Jan 2018 08:23:17 +0100 Subject: [PATCH 50/50] Fix model importing with multi build plate CURA-4782 --- cura/CuraApplication.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index dfb78cd3b2..30fd461868 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -1479,7 +1479,14 @@ class CuraApplication(QtApplication): # Step is for skipping tests to make it a lot faster. it also makes the outcome somewhat rougher node, _ = arranger.findNodePlacement(node, offset_shape_arr, hull_shape_arr, step = 10) - node.addDecorator(BuildPlateDecorator(target_build_plate)) + # This node is deepcopied from some other node which already has a BuildPlateDecorator, but the deepcopy + # of BuildPlateDecorator produces one that's assoicated with build plate -1. So, here we need to check if + # the BuildPlateDecorator exists or not and always set the correct build plate number. + build_plate_decorator = node.getDecorator(BuildPlateDecorator) + if build_plate_decorator is None: + build_plate_decorator = BuildPlateDecorator(target_build_plate) + node.addDecorator(build_plate_decorator) + build_plate_decorator.setBuildPlateNumber(target_build_plate) op = AddSceneNodeOperation(node, scene.getRoot()) op.push()