From 21687f5689a867d26b02eaef6d719bd7b99ea141 Mon Sep 17 00:00:00 2001 From: Jesse Schobben <16669720+jschobben@users.noreply.github.com> Date: Sat, 25 May 2024 10:53:10 +0200 Subject: [PATCH 1/3] feat: assign name to 3mf components, based on color This makes it much easier to map color to filament in a slicer, for instance. However not all slicers extract the name from the same place, so some redundancy is needed for more compatibility. For now, the name used is simply "[R, G, B, A]". --- 3mfmerge/3mfmerge.cpp | 57 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/3mfmerge/3mfmerge.cpp b/3mfmerge/3mfmerge.cpp index 8275ac6..fdd5b4d 100644 --- a/3mfmerge/3mfmerge.cpp +++ b/3mfmerge/3mfmerge.cpp @@ -1,6 +1,10 @@ #include #include +#include #include +#include +#include + #include @@ -30,6 +34,16 @@ void rotate_indices(Lib3MF::sTriangle& triangle) } } +std::string replace_all(std::string s, const std::string& key, const std::string& replacement) +{ + size_t pos = s.find(key); + while (pos != std::string::npos) { + s.replace(pos, key.size(), replacement); + pos = s.find(key, pos + replacement.size()); + } + return s; +} + // Returns number of skipped input lines int mergeModels(char* outputFile) { @@ -37,15 +51,23 @@ int mergeModels(char* outputFile) Lib3MF::PWrapper wrapper = Lib3MF::CWrapper::loadLibrary(); Lib3MF::PModel mergedModel = wrapper->CreateModel(); Lib3MF::PComponentsObject mergedComponentsObject = mergedModel->AddComponentsObject(); + std::map id_to_name; // Stores name for each component ID in the merged model for (std::string line; std::getline(std::cin, line);) { // Define new color, extracted from filename such as "[0, 0.25, 1, 1].3mf" Lib3MF_uint32 colorGroupID = -1; size_t col_start = line.find("["); size_t col_end = line.find("]"); + std::string component_name; if ((col_start == std::string::npos) || (col_end == std::string::npos)) { std::cerr << "Not coloring '" << line << "': filename doesn't contain proper square brackets" << std::endl; } else { std::string col = line.substr(col_start + 1, col_end - (col_start + 1)); + + // Determine the component's name. + // This name needs to be stored in multiple places to be picked up by the majority of programs. + // TODO also allow setting a custom name directly from OpenSCAD code + component_name = "[" + col + "]"; + std::vector cols; size_t prev = 0; while (true) { @@ -116,8 +138,15 @@ int mergeModels(char* outputFile) newMesh->SetObjectLevelProperty(colorGroupID, 1); } + // This component name assignment works for Cura, PrusaSlicer, SuperSlicer + newMesh->SetName(component_name); + // Add to merged model - mergedComponentsObject->AddComponent(newMesh.get(), wrapper->GetIdentityTransform()); + Lib3MF::PComponent component = mergedComponentsObject->AddComponent(newMesh.get(), wrapper->GetIdentityTransform()); + + // Store component's ID->name mapping for later + Lib3MF_uint32 id = component->GetObjectResourceID(); + id_to_name.emplace(id, component_name); } else if (object->IsComponentsObject()) { std::cout << line << ": skipping component object #" << object->GetResourceID() << std::endl; } else { @@ -130,7 +159,31 @@ int mergeModels(char* outputFile) skipped++; } } - mergedModel->AddBuildItem(mergedComponentsObject.get(), wrapper->GetIdentityTransform()); + Lib3MF::PBuildItem buildItem = mergedModel->AddBuildItem(mergedComponentsObject.get(), wrapper->GetIdentityTransform()); + + // Add metadata attachment defining the component names; this works for Bambu Studio, OrcaSlicer + Lib3MF::PAttachment attachment = mergedModel->AddAttachment("Metadata/model_settings.config", ""); + std::stringstream model_settings_stream; + model_settings_stream + << "" << std::endl + << "" << std::endl + << " GetObjectResourceID() << "\">" << std::endl; + for (const auto& pair : id_to_name) { + std::string component_name = replace_all(pair.second, "&", "&"); + component_name = replace_all(std::move(component_name), "\"", """); + model_settings_stream + << " " << std::endl + << " " << std::endl + << " " << std::endl; + } + model_settings_stream + << " " << std::endl + << "" << std::endl; + std::string model_settings = std::move(model_settings_stream.str()); + attachment->ReadFromBuffer(Lib3MF::CInputVector( + reinterpret_cast(model_settings.data()), model_settings.size() + )); + Lib3MF::PWriter writer = mergedModel->QueryWriter("3mf"); writer->WriteToFile(outputFile); return skipped; From 1d2ac68e77aa6ff418b29b2b5646e708d86cdd2c Mon Sep 17 00:00:00 2001 From: Jesse Schobben <16669720+jschobben@users.noreply.github.com> Date: Mon, 27 May 2024 02:11:27 +0200 Subject: [PATCH 2/3] test: update .3mf tests for added component name --- test/expectations/test_boolean.2019.05.3mf | Bin 2078 -> 2806 bytes test/expectations/test_boolean.3mf | Bin 1918 -> 2644 bytes test/expectations/test_color_args.3mf | Bin 2317 -> 3094 bytes test/expectations/test_import.3mf | Bin 1967 -> 2654 bytes test/expectations/test_nested.3mf | Bin 1600 -> 2273 bytes 5 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 test/expectations/test_import.3mf mode change 100755 => 100644 test/expectations/test_nested.3mf diff --git a/test/expectations/test_boolean.2019.05.3mf b/test/expectations/test_boolean.2019.05.3mf index 31dd449dfe3440b32f4fc3cfcbd9ad8a681a1c34..83176f66e1af9dc94ee21e63a7dea150bf5e5600 100644 GIT binary patch delta 2023 zcmai#3pAAL8pnsm%tTY;Rt^~&bX+nNMvQV7O|H`nZ6hWI6_OCS46%ucjd5pC?#i91 zkQyV`Q0}zd#g>L7p~5lIS;s!>tn+^B{r>OeS?l|r|9aN%$$)(oB%5LO0p$Sz0Azat z02ERfZEJVH00ICdJq0BP*BcHb7v#@32LJ|e6!;km@C5EC%gW}DM<`gp=!W3E`hJcO z#&LvSF8#N{uD-LlfU>9|V?lAwis5&*W97j@3#tBp&PMU+hjgVYDJ3(!H_5DQb)Ur| z)>q@_%S*?AXw7bM z^mxhyZ3_d*bXr>rUgDXFb~`RH>+p?ryTc2Ot>NogUWWC_VkI_l!EXOXF4@udT%}EA#S0WvY=y^uF+XMq2W5*z?7JOp&b)D0Ys=ZS6IOTfh6$ zA%T%J?f@AD}2gb4wIYW21F1W;u6|uq9 zj&vYwp1o&yM9-X2?*F!8H~Z0(;n#d8+HaBf0&0zN`>Y0bHp@oQ2kb1ArO*&$zyz?u zuByO9hw%EX01OD_Omn02f{HIwIKLqdI4d7`nN>yiSM60;q#-QP8Y-h+^B9tX_sHptrd&V18W9!Unvlg#@9o7AH7cHE#Yf?(Q zx~)DPI2WNqP>hD;@=hu<4D}z3TNs?2h>4ubakmXDp&pd)UH$SUBZ1g|9m<)Ap0N+= zKb_Pu$;u)x*xsHjUcRQWq!y?20{w~0UE2kE?#Hy!7R!f1h|=76y%938$bDNzp6)emay)f3(EAfLOSERjDb{l8eka4f zJ1ut{MmUWG7EicS23FiwD_b6|OU>U&TDJaq*rH%FP&?9vpsfd}^p=L*nQ!357j_1C z3pbM+%vF#94dG5`9H#o8RV+p zO&t=6GJF?d=7_bEk~(;Cb3=1(-Z;r@W;usTyA7dikoMFfgQ1foEf8@+SJH&P5gQSE zLBCB$xch`0(qm5brB9W((PLd6UW$DLghyA>JXS4rHAF&L-E<-odq31& z3I@8o+GyJ#_(o6J^1w`2FnWvLh>;IGY7j1;lD_zd%M(46OrVvOqLFyQsig8eJg zeB7ZhlWW|<@o-u?g`Zc`K@749Ps$;%7MzhA&BY%&WE2?Joyqec0YCnxSJqI4l&}B% ztM-G(Y(mb3&vlKD+nSxAm4+G;j!Ko;gz%PnWvpRzPNT!gINvyuhH?jQkLJFbYfl~& zO^96DR}dUWdK;vASl9?+Bjg+4a99Ta48<^|aCwQU2srXs0dLw5;xx@L9Gvoiy={xy z2tw}vcWQEr+AK$pvjI+nfJa972G<*9M(x2R=d-2J3T{b5V(4Eay0ATMnD< zb^Gt%+3unL+k2t^^1cg9rGw$;xpx2dmk#aLY3)v<2AE+$V0K76_f8=D+6==5V(+-N LA9g%DO90?spr&|& delta 1323 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 delta 1168 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 diff --git a/test/expectations/test_import.3mf b/test/expectations/test_import.3mf old mode 100755 new mode 100644 index d680c7b36cc36e4f93c611edda72dac63e5a6ea3..26ee939b65b888f4a357036b09da7c452503d209 GIT binary patch literal 2654 zcmai03pmql8{e{x94BPukW)m?hgFirk~xg!kb1@Nnr(8PNFr8mg_75KX0OU&@sV?- ziD5@3E2?R%{>}j=3>Yj3IA!l^9xIv;mF;tVr9!tN%td6<zk=xxYR zOXsJH`5(O8k1Bj=(zQkipBUm-{E}Wr5$ZPbe;pc(sq&oJ_L0J* zkyX{xkHz20!69-Pk9IMK=f5cK8Zp$&O_BhKMTA3<2d|ZK%48oEXrQhtFy0l8ke9?k z7gnS|Z|lUdBl8(?<1LsKwWi|zN<*`?Dd2he^IynxP!U~tWpSu{7n6EH-qXroe@ISD zN9X&JTasp6#hq(>SF(w6q1JeVzG=x5O^&q$7B z>cPKb%a^7Bwnz*a!CZ`xT7DRxT2G}+wq2ya*=? z-rJal1+-8Q^zrR!yTh>BuHI@QtTt90@{y{0v!)PTNfbJKE(Prx1P4`L1edfEfs2B= zhrkeJ_tK(Zfx{9V6)4d8-)K~^GeA2kuEXtiu)u=@f_~c5JF-c99%fA9F5#@YfIdL5 zhDYWB`stW+l@Cfh?6p<&M@772&UG@VgczT5No4^?`yUm5dLxFk`+foow&n7N^0zG z`eIN)QG)I1oxW(z67Y_)fa^- z>o_I2I9-u}0in2nP^?o#5RT-geb(P^6`ai$9;)#*a5RT@Yo;#L^fg_e#+q8BpydCp zY(nOrEsC^zT}yx3W-QFvJ=ECKOMd#S?VC;36EBg2NLw}|{jHM`{$1+lY8h8k4#spE z>0;O!2;7$In(>>d;$=(4!bws{Oso;}d+tMv-*SS(Z?x4_R@kZ%*y+ClEJR;pI$xLfL{fzWpf zf0Py=pVxT6VejsC%DXJ3uUgoK<*B{(fu2g4Rh;q29<1or8e{tu(J_0hfKYyn9A$Yr z$0RjheB$lL`0$N%>EeMk>vRcm>B5HK{75?5tMe*N{6HQ*6>Bu%ZnO(F>OwDd&Z##J zek$00gjpr6Zb9(QVo6E0lhkd3LrGCQTN0a%AC|=$7=n z`}_pzP-ym^4d<4g?O#d{EZ4}I_7Dta$-lJ8Dz zGOjCT-}aqW0&cK~DDUm+$7|pX_6guKaz>IqLMK4MzxO#KFgCy~T7Z9R5@gpv#Bl8@ z2S2wAu%B9nwJm_no;Rw=X3zgmTVOwFiynv**7)x0^*FKZk2Q*G}6|JwP++~4ec zLnXj|sst3|*G@NP*k-3(&i_5%V1Ui}wvT^32n3?Zd*vSQ>H+h{8Zf}R?O!WbWnPoW fJvPV>4@+Bl>sLQxY`{N$9n9Uex_&hk0D%7jjrv2! literal 1967 zcmZ`)2~d+q6#heih=?YoXrL$t1yhcYlAwqfj37niCK`%z6BL9HArwLc4?HNO92Vu0 zwn$63#L$RfI0T8@p^ya1B~d^jKtYrvaux(TgSI=f@9oa+`)2ohZ@y=D0xYcy0Kle| z2>^R!GUAul2Nd`cz?kV_yaNKgN&cu076d?n(XAh@0=?ihf1B77mt_czXt9{zRzE*h zyMJ#&bh8CJD{+R_uIA1V`*1b-`6FEqe$iqLcpFu<>WQB+ZQ2i#s`k3|<@4!+03voe z_02wWW0!nQ?U7`R^4#6p!KR@nIE|A(iTPm4^Nfb`A~%~#Q7+M?VLVrh&_lKEGs(?< z8&z;?I^jh7HeHq^&$n0)E}FN32Ij;rS>@f+iM5>NXw=iRH0}rtB9;Qn?LwJ;Ua6K+ zrx7QJe*QDmuKHl#bbq_UogOJ$A7xSZIOdT~Hdg8hb4*mGZLI^QS=tJ6De$gHqvE1W zoBYi7yj;4=Y|i*FJE4jidOW|(=iKdabhk$PaRZW|@*$5h88c?Z-4v|dR~o5#2{SXT zR$F;#-%^rTlx>roHg)sVqJ<*#!7{Cl1)>~+O$3EUF3t9&ve5Mc^b71(Co9tnmm`u# z!MwLfBlE=QkUY@g5UD32*&@Vfchb0PopbB%F%tFS7k^-OOqD^xw0@r1vK&484mG!o zN=wqoeya`3=A1j+?tu`V ztJhPjO;gFr`YxBXT&9qM`;o}U8iKZhnUTBPn6Jhj+frc!s!lxC2uYxV(%6VL{5NfF z#(BdmH7w`%X)~g* zlivThPwnMXImjE5Dionsb(Z1;9Z{(aQ-A=2hYDW;tOBr&w9}40`RFKOkJTkv$b=^s zbWs^%*0iXM%L1QEe$R-bx!D23=tbV>ktopF*VP`qnCl8qSdMq4z5^&rOt}K1gMUqI z9-3u<)IDj)VSTjoiv@C3+9s^0VX4WU9`y^j-RXbYcB}I`zH5!@=zZ8QG@%uXEvdem zy4@Edr;Ld)Z!38N*IjvvQKvg-#G;Z5 z!0T}*_=u7p3Ey}Z{QAzoosdi-9njm+Vg_o2qaX4euo3xhxtXl-;h(!(MLCzNT<(M-T)w6Wv{N|spy#$Z(g_QD=A<yH^UJnb*#p# zluh`x?WX1|4OD-3)ge~sGhW38E)ih5oW z%0G!O+Fnl5f48XMIN>wFh1Gh4_rJ|9_zl2j7Iz*9x>p#MP{zz}nw$O-A-AhmSbqhH z)4JUZxH9$4j*L@1rqW7P=}N^k!Qq^qJPuKFH^>2>YO3FJtm3APZ5+3$IfFfeII8#T z9c_P;0e`N!2rD!iGeN33Q%rr2I|z%c0B@u$xMSeX zN6O?^D02%U`3LKvR_!WP@}M=2*y~i0;(42&qM_IR++1neS@v9bH5y(KHmMbHC4qd2 z^&WBjn5a(|iQEr2ZYN2`DZ|8b@)7Dsslwf$A-segeS4)uKvKHE z|Fsa+^^aX%@vA(1-caD5HI(%b;8Wy{<@YJ_e-I`D>i4ZPq&_@X>EsPdi@r-#EzX%KC!^fYoEW6EYu8!7EX#_gC2ifPVmY Cq)$Kq diff --git a/test/expectations/test_nested.3mf b/test/expectations/test_nested.3mf old mode 100755 new mode 100644 index 822eaa84bbec3ec4e1ec53890cfafbc045f4b430..c6fca4f8a042b520ca0f457a48b601aaad5e95fa GIT binary patch literal 2273 zcmWIWW@gc4U|`??Vg`nDuP^ERhXMfx5e8!yedCne{FKxjJuu10Ai(gD6|9t@iU~qb z4e`ytqaa|LU&p%Wy3mH+{b3e6L$trfJPrBEAfdjlXJgJDuV1gN)2@G1i`p7>`jg(_ z$7g3hY^EH~;_edzvvc-|$? z{Sw;Ct8c%$=)3OY_gj&(u7rInR^B?_U18y^-nL^pUYgy8vwmL-zp*X$deq~y9pdL| z)u-nyQ}?%bS}_0Hw__$@OwroAbwdSq%jZ3jbPGR!%h~*#&&^dHcTX(o*)sRbzN-uW z*<7g?D$V9!{?3QV_e{9$oD|ZXO45!=PEz1tsFJ9l#YW}Nr zV!gD2*qzpk8|tfm{abseS96ig#5qe=`f#4#qSUo|ib`vy(X{ElK}}QJCY$_toBcT| zaoZ}B%ib4u3qN?h^zXtoOB+&i;sO~KZ%^g?CA@E8LpFznz(dXhxdp8IefJ6HFZ}<| z{0X~lQ{5VeiVYS2@8pWEWi07&QamofXXti($)O7$zi+voaN!Uu+l%@`4QY*xzpQdj zvU#4*i4JnSzGV3~?yU3D$}die&(~%034c35b6#rDbCro(Rcxjk25t;$@eE5hS`~b@ zxi_)-A(K=L|2Mn*pJEQn=X9q#JbtxBY1&f1MNJx0r?tGcQFUFD6l6U4WQ*as;A{Og}84l4PFyuItay^?7`&DUpE4S9?DxI5P@u2W8LNnCU2PGQ@*@6*l{-+UWq zqRXD8Ay8A%#}(-|<3!KJ{im6iygtF+^>=f`x$7|-S&th%y8nzF)qiSNR;s}KCk*so zv~zx5Norn6d`M+MYH_SyMQ#qrQ{K>Q`3mZ(xj|>Wju;5o-CoYI(`)uB1*P2Y8(vHQ zU{ajB?c$$_KGT1F^V_ARajoh2$ur-*XB|%BwRZNowR_tA5YzMrQ{Hctj<$OoVE4f} z+~j;dqtN2$=}~ryZSIPbW*s;c@{^&@thql-skczXaaFiw(~h;Ts~7HZE{I5a_8_+K z>YRiLn;pMxx$tPwAEAUNZz?R$X6arx3tq#$vGW)EiC=PO_;n?lE_x|#RXDe9eU6sB zQAqjTsd;is4p|0itDc?tV3yKn-S~rl-)Zm9PgI(*M*^X6QqIden< zrpib}KK*r)k7?SH?d%z|AC)YPTqe``_=)mqdowPH;7{&HR=61%O*=RFY+u>I6I0F` zESUaEjs1}9^J<>`JQ-bQyH4#|zTAG<%#ebMFGIA_H@xfJ(mhQ}S5f@Tja6=OdrPlh z=2(Ajj_Scq*PmnG+V8b3>J?jxGs(0sySZ#%QR~k}sLwt-UWX+k={$(e1&Sw1`LZ5fR|c#-;;}3rGY*I8bQ@7=06(U6--J9LL5EV%0<1Ees&(0B=^XEGtkKNIfVi HFfafBk~)fN literal 1600 zcmWIWW@gc4U|`??Vg`oN8>e0WLxBK;2!pYUzHv%!eoAVN9++fg5MX%A3RcRH%LJjP zhWPf+HW0B{9`wKY>Abz$IOV-lc1_m`I)C*a!)=?gl?=)T7q{)-$ItA!%{RK$nW_Kd znLW=9U%gzLdxEoVV_B@@)8+*%RY%eWQ$|&y+;Z$o;ae{B>~Zxox=2aII9%%D#Mhv0(6>yK|)yN-ifP&Y54f$~NNq zj)$oQ!Tzr{EeLFgy*J^*z6JC9+#9cd^!T}HQoMew*SQ+@*UV?<3H@Kp&T~LU-Rsxk z&!4aB@AxbrnYsD?dbY&ZfQMHakgI0ab90_d97pN8S$6V7B(Hmd=LL0Q@q&Y{3E_#v%;%&HQ~Fu@^`)V z)3}$nd&v)>PWwlVIp&WQg%TYb5?2~pb}OEmd2f0Dny%Ijn^sM_lNK%ZLHNpUKIVO@ z4s*3rCe96R@!S69=9Z?IW18JP+jOo~9`O<444c~Nd&whvW_tFna<2Vp?_aEs4*YXh zGbnA<>`yw)Fa2^dRW5tZ*?1#N@bZKuI{qa(zM46z*KJnca;|eAS zeHY!E^(AVmB=d<4I)yTwv3s=So)jLj`0;bY!@K$cD9M#0MDH>zxe5c5YqWEIUP)?R zNqk6UL27ZVUPW#WD8+_AQ|dcNf@PQ+bk^&LfquTmXwDQT!CReQ9*lWl~71&=X={YCmyN9#%$hI#le{=-i z+Zy-yN~ZJW6SFmUoMX8@Cu*Hl_mAD1|Lo_II=GZK{{Hp9PbW_7{%&$(#=kN*gJOXj z7jB;We{%BWD_NF;b$gjngRJ=4<7u!U;|2yG4F?7n-YsY7CK#Ye5$#tC`#8-6N!y57I1tDzxRp7t&ISwYo}z&o1D4qCIO zDmqRu-X|HeJmJ*aD)!}%vnqF7T49_XWZ$Cl*na%xJH>~$+Ue?x=!B4u*=xR@Sy5@JA zo50pS*;Lkux%NpPx9RmVty5rp?)YPK$5inEZ$>6v23%#D4Af%{KpGSdm?fM9MhOSi z!hmivYVt!j8Eaycz(|bip@|dSaMXxGHykC}Bru}w5i`Wi0p4tEI#B0B!UV#BN;AM{ j9%!^*Vu9;p2eIx!%X*M>fHx}}NQ@Z>LFz%F$G`vp>fV%F From f814ba1e485f26d352399ceb923d01d4eb01eeea Mon Sep 17 00:00:00 2001 From: Jesse Schobben <16669720+jschobben@users.noreply.github.com> Date: Fri, 13 Sep 2024 22:48:54 +0000 Subject: [PATCH 3/3] Update CHANGELOG.md --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d4ced4..67f3580 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,10 @@ Both colorscad and 3mfmerge changes are included here. Unless explicitly mention - Sort colors by color name in output, to make remapping color<->filament in a slicer less often needed (thanks: schorsch3000) - CI workflow to run tests on OpenSCAD 2015.03/2019.05/2021.01/nightly, for Ubuntu apt/AppImage/MacOS/Windows. +### Added - 3mfmerge + +- Assign 3mf component names based on r/g/b/a values, to make assigning filaments to colors easier in a slicer for instance. + ### Fixed - Improve code quality of `colorscad.sh`, add shellcheck validation (thanks: schorsch3000)