From 80eb96707a7e66d8829edcb03b29cad7b3428c9a Mon Sep 17 00:00:00 2001 From: ibs Date: Fri, 3 Oct 2014 14:11:30 +0400 Subject: [PATCH] 0025149: Samples - add Qt5/QML sample for Android 4.x --- dox/FILES_HTML.txt | 3 + .../images/samples_java_android_occt.jpg | Bin 0 -> 13697 bytes .../images/samples_qml_android_occt.jpg | Bin 0 -> 14519 bytes dox/overview/overview.md | 13 + samples/qt/AndroidQt/.gitignore | 2 + samples/qt/AndroidQt/AndroidQt.cxx | 292 ++++++++++++++++++ samples/qt/AndroidQt/AndroidQt.h | 88 ++++++ samples/qt/AndroidQt/AndroidQt.pro | 31 ++ samples/qt/AndroidQt/AndroidQt.qrc | 8 + .../AndroidQt/AndroidQt_TouchParameters.cxx | 107 +++++++ .../qt/AndroidQt/AndroidQt_TouchParameters.h | 60 ++++ .../AndroidQt_UserInteractionParameters.h | 28 ++ samples/qt/AndroidQt/AndroidQt_Window.cxx | 87 ++++++ samples/qt/AndroidQt/AndroidQt_Window.h | 95 ++++++ samples/qt/AndroidQt/Deployment.pri | 27 ++ samples/qt/AndroidQt/Main.cxx | 29 ++ samples/qt/AndroidQt/OCCT.pri | 53 ++++ samples/qt/AndroidQt/ReadMe.md | 54 ++++ .../qt/AndroidQt/android/AndroidManifest.xml | 82 +++++ .../assets/opencascade/shared/.gitignore | 1 + .../android/res/drawable-hdpi/ic_launcher.png | Bin 0 -> 2591 bytes .../android/res/drawable-mdpi/ic_launcher.png | Bin 0 -> 1609 bytes .../res/drawable-xhdpi/ic_launcher.png | Bin 0 -> 3669 bytes .../res/drawable-xxhdpi/ic_launcher.png | Bin 0 -> 5560 bytes .../AndroidQt/android/res/values/strings.xml | 4 + .../example/AndroidQt/AndroidQt.java | 99 ++++++ .../res/icons/ic_action_collection.png | Bin 0 -> 650 bytes samples/qt/AndroidQt/res/qml/main.qml | 82 +++++ 28 files changed, 1245 insertions(+) create mode 100644 dox/overview/images/samples_java_android_occt.jpg create mode 100644 dox/overview/images/samples_qml_android_occt.jpg create mode 100644 samples/qt/AndroidQt/.gitignore create mode 100644 samples/qt/AndroidQt/AndroidQt.cxx create mode 100644 samples/qt/AndroidQt/AndroidQt.h create mode 100644 samples/qt/AndroidQt/AndroidQt.pro create mode 100644 samples/qt/AndroidQt/AndroidQt.qrc create mode 100644 samples/qt/AndroidQt/AndroidQt_TouchParameters.cxx create mode 100644 samples/qt/AndroidQt/AndroidQt_TouchParameters.h create mode 100644 samples/qt/AndroidQt/AndroidQt_UserInteractionParameters.h create mode 100644 samples/qt/AndroidQt/AndroidQt_Window.cxx create mode 100644 samples/qt/AndroidQt/AndroidQt_Window.h create mode 100644 samples/qt/AndroidQt/Deployment.pri create mode 100644 samples/qt/AndroidQt/Main.cxx create mode 100644 samples/qt/AndroidQt/OCCT.pri create mode 100644 samples/qt/AndroidQt/ReadMe.md create mode 100644 samples/qt/AndroidQt/android/AndroidManifest.xml create mode 100644 samples/qt/AndroidQt/android/assets/opencascade/shared/.gitignore create mode 100644 samples/qt/AndroidQt/android/res/drawable-hdpi/ic_launcher.png create mode 100644 samples/qt/AndroidQt/android/res/drawable-mdpi/ic_launcher.png create mode 100644 samples/qt/AndroidQt/android/res/drawable-xhdpi/ic_launcher.png create mode 100644 samples/qt/AndroidQt/android/res/drawable-xxhdpi/ic_launcher.png create mode 100644 samples/qt/AndroidQt/android/res/values/strings.xml create mode 100644 samples/qt/AndroidQt/android/src/org/qtproject/example/AndroidQt/AndroidQt.java create mode 100644 samples/qt/AndroidQt/res/icons/ic_action_collection.png create mode 100644 samples/qt/AndroidQt/res/qml/main.qml diff --git a/dox/FILES_HTML.txt b/dox/FILES_HTML.txt index 6cc2a4ae41..3e7f0e7559 100644 --- a/dox/FILES_HTML.txt +++ b/dox/FILES_HTML.txt @@ -11,6 +11,9 @@ overview/overview.md ../samples/CSharp/ReadMe.md ../samples/CSharp/ReadMe_D3D.md +../samples/qt/AndroidQt/ReadMe.md +../samples/java/jniviewer/ReadMe.md + tutorial/tutorial.md technical_overview/technical_overview.md diff --git a/dox/overview/images/samples_java_android_occt.jpg b/dox/overview/images/samples_java_android_occt.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ecba47332b62d6ab170560b3ce28b49ac245261a GIT binary patch literal 13697 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 Bi*x`0 literal 0 HcmV?d00001 diff --git a/dox/overview/images/samples_qml_android_occt.jpg b/dox/overview/images/samples_qml_android_occt.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3fbdbd34a3ebf4ec70b6c51338d6e9c9ac574ce5 GIT binary patch literal 14519 zcmb8W2Ut_vwl=&J0YwE70RaJ(-lcc20n()egiy9X=)FTA=tf2QrbfEbA}vS@9R#F= zDxCnK7b&5H8VK-bpYxq__Pyu7=lkx=^JLAr=2)|g`OY%lHP*$%#T;-;LseZBxOC|f z@PhOME~bEI0L2w@3i2xy6yy|?loVH~Zc$NPyGC_~n&!qW#yfZKGTvceU}oiFXJ+BJ z$G~u3@ID7O4Kz^ynMWW7IKM_l9K8w6&)279WOHjGw=U8Tzm&;uU;~| z{EF<-L*O#)B{JGe7e4@2;1Y28G8w74{|w}mS12x#UA=sbl&yY?lzZti8Tl1*N-7GH zAOMh3SIB889*9!jexmo9?xC2++qf@fgIDixJk@WRr@zZ7ZD8f;ow&omC~g>^4Jwyt zeU`9GDvE_v$A7H|xI%uJjN%d{DN}-$RL|v0WS7Y($;in6)|5Z%p?yGpTa@nM6TLx- zJ5OJGd?^!qyF(v0&+*(UzU5*PxIsoLl9r4XPzDZ2y8dS{Xim~SFl!zdKGLd*fZ_|z zi{OM4*c#x!^G}h#MPxPo%2y^RU~hAmHzu2eQxL{Dv2vd2h#dOubMaNO9n8%eX{)DPHXD{r32YP?}7p?w>1kKQ60LVU7?`~=m z8;JIsx{6%s7Iz4`+DH{?;n9hsGalhih@p_K2Jd?vdPFgv>px~zVk=1thwG@ANJBO9 z5v(hdSmoP`9XQ6vnTq=L54&+5Ixi3PgU1)DCkjIrGQ2K;1oQ>a71A!ZdI9hxTmXNN zS6={+j=j#e1}=bn%eNd~c8wB{kO3B*CSUWb^2|QnO6v~(rH1+;yE?TO0D9>HSYo7i z3g4>I%01(}^y|%IcaGky8?UhimJot8!YL`%H{n-PN%+nsT^LAt)bj#R*2O-Y{|n?U zEq?!t3edyf%6$ZhL4wQ>n9=i5A7lFZ#54@Y-2=)cEM|D9>_NL}JJ`-d^wY`xIj zZjDbk3k%Cn+m069idzQ@!n*t!8Q;oSG^k)J^qQT-MJ!8|F_zevQ<2giGhD3wH5IrQ zZ&|DzkC>d)3_ttmP=M7leATR)MaU(Vq81-2b4*9t2tyjxqo3fOV~QZyzI3DKhRzNQ zpZ?fh`q5W!Gi965&Xm-{*7a(vFZlUbMS9`8YKUdABYU@8VcWavcfqGpcs$Q*>srO; zw@R3=YL(jngUxRMKtR=)8*ZTZeb6qvRdx1*GO_P?j6*mybbJoHVdWP9P3pe%&ljED z6>Q+p^Nu3N=tzA&3KUdHYpzlz@`J~Lia^0+dVk{uaP0z!+!e@pM#-Vul_cwJTfDht&%+m-@%5i0LO{WktxDt-&m)Po@5j#T$BFK@oxpX)Tz2eF5N(Y5o!i zjPorL!i3Zef3%e@G)=TE*RQ)?0Qd@n3!tg(0+`z2K9+yu>22;?Oq`B_S{p*9qoLa~ zPA-H}?(c&9{Lyz>3&(!GGqh@mSNaazIa)S2GZxv~KN}Lhok=VVDO^5>Wz{`qQ}|a; zCTeKjdmcA`+}-cho(Bh?Zcq7WJM6&+T0|HI-zTenmF-*O7)c9M#ZB z>}xUYMb+7u)_x62UTZGugd^w6)j8wMZ$I$&(ro=%>1-~pRRRi+re5M0UztsF^F6mI zk852zuuF1^-`(LXJT;2?*mbHeIug@WZqB4C#Ja9#UV#-~Fqr7*>WcPo)wQvMk0d^r z{1heCb>_x_8OF}0Nnka(j47rjlE%dsZR*i@6~A`VQU8g(^wsi-m7)@??K$L7fnIV; zwYej3y9}v8(`b|BOKTxG?tM>vlxfyZUT{^4sO2mJE?RA86bEY11KBHyj2z2uBj54 z9CQ1p1m@=f2T3dkB;?Ln&L5~KLuOzQpW}?CU(An`5KK>9#UrB$M?Sh^;vH#D4(**q!@_2sKdAjP&Cepg zGvTxe($3`U-fS;dS}Ia+cvdv9(qpFOIyx)D?IJBBIS}_iyBns^W#5HEb~2*VTV4F6 zP4wfWnb>up52ctQ9v#(v3NWe2TvLR9;g;2p7?Mz9)3-_1@fOg{+#IjEw`MwnUtS8b z^y8ko?_;)X$ay4cKGqZ85#>ML^T-FMDrwBUT&|*63;~xqZq=Z6H-d<1c&_6%)AEfF ziO%Fh3>tS*)VmtyT?O*cP#~IwMC*5yHWDPKl#R@bT6nV8)@xLF(`>1Q2hC!lrRiL1 zS*Rtiadnk8;mWl^YqtUqBL#aconl$>0%q}NkR=BpiAjh2x_mPbsC>zh2yPQzR=_E- z=N%Uph(wMCo~?eus4JoGV#$}8?*kPaZ~m_Gr@NFi){Y0Yn}yw)Sd>6%jsY~cbh(oDB$Wb*h#IDSPq#^(svV8A;twt`~@nT)62P)P5K>P6Ll;~RM`WxMRx zXY*w(qi33FkZaJNgp~ll2(QzQ9%xh#?IO0GY9<|u+-$IF2o4BHtp?ol)fk*SIzp5DeOv_7 z;*U9&8ZD+oO1~dSrG!W4&kcr!8aj03D|Q*Ph2PsYU(fOj`(kjUj0x7fcTdgffNL%x zDrTaqJu0TFYc5sTOzTtEW)w;^ha<(LEGAlq(tC5s%G|Et2X2WFS6i!bZBP82Z{N34 z3*Bf_tQ z9}Toh+JH-)wXoMIdP)Lh*$yh8)u+)%8XbC3`p;G2G1)m?m~ZvpUi9#fb1=Wo22+*9 zbBoTSAIekdL2r*d%p5z^-iazKn*F{7I$@oVlvS6~?qsfQ=j+T$mFN)Geeu@!X{Z3T zz&v~ZDIwKH3hfp!+SCmzLZ2=Bxp)<#pH67dMPfQMZDZ9nFA00BM1vz`-|XwL$`q7x&qP&2(|+=ADquDBeu{ouMAy)$u0Ix@JG+U0-N4>r17iwl=E(ce|KaI)cu>=O z&;-6Hi#GUWcj<(;E_R1M1A>hHF@ zPT^H>m|1F2TMgUTGLxfp=YEA{Ve@O)1)$&jbyZNVzL{<(TxMcxZDW2{n)>F?U4JJP z1Q{)#y6^!CS5XcVI$xfPj;WV^;Ly-lIBT$4Eo;Ifi^mML@FGX&5~KPjy1paZ8ehe) zt9pogVBoV8>*a0PMkRHhQe-s*zDBW#;xy6Ng!nHMQ>qrioER5w?7hgVg(H)web>lVMKHWxZ;@h32Woau-x}9r6 z8LG7DP;?&G{K_-aTKXic9Aq~{F*_1GCe-*NN}a8`2rZ~FaD)_QX_q$+b!|)1;l~rQ{Pe1cBzbFFWpT8|C6(2-KBmNS>Vvm?bndOi#ps{2+nKm2>pNJOMlRGPdf`@t8SPEhZ&^4$d1JQ1xEUa>nT+K;-BZt8eDUKzr}nBwBV@~;`P z^c~%~D3ADQ+?98eP*qfQi@68;HSD|9I7ESY^k`f0{Be$<2$}JM5*hSCLkmfpqXs|0LXGrQOKB4#Eq2!GN)+1X6qrfPO-Z8HVWHR3GX5R`Qi$rw!@hT4?VUb;R^DLd|4clb8^33_t?}*i8X)YH03y;YbcoC7e6!t+J{rarjY&>y3UN)e)VgrK2?U zt=A^DEAsUXbr}W~Bcqc6R8W5bU>7&bx7wU+bff#ki+1~mOM=b2f@N0K+96R@ck zjbA$oS9yfuxvJ8aulD$rOY}NAkNbe=n^#7A{LWU)t%l;a;P0NGpn(=z{db0nN5n1w z1#~2)*;AyeTEdy!jH4@h9xE)_%BN;uO6Jjyuu1-LV;W&o8GT?>6oWa6)c zA=N3>ZcI|~+STDLq>4q?kvZDjL;A|NXQpa=lCh6>lODVWeU|mGzA4RPE6I4AfAjA< z-BS}weG)MQr8CJZ%9(Bwn649;`IB3k!1S|C$*NMRCw}9S#L|hYc5OkP{U2rt(qNNY zP4`gw)sU#9qhclqhCg>=G+wS4LfQ`4LUR@!>U>}WENqGsh|y*yWvN*y$KW`3Eg7{ZMv#^ef#p2GaGxy^ zs^R_Jy%0_}ME}XQ!6~*W!wtiZC7!?U;9^UMW+emU*91R|*M!g+mo`dn;`Jw`I!lLF zBKAPT6_rlVTAyZ{nL(7oqDb2kIIMS`slCI4#3xCNt;H8~Cj}|JrN^b`rZLZ=VY*U#&!#BHcT=jYz+R}cWraXq^~9i@Y-NB$ru4(?WL2Xtard;9 z(nQb|^Y5Mf_6UK=VRl4DRw@yB{VnsNS9M6ok4|ZpfZXBJ7314ZHD-$Wy3$H+Hm6nNY+fk0T&o5X<8?Fj z!u7MGB)4z*!J>t*O~!;^8{*OOQn>%ISFNAFT8!DRD!inNG7}EwE5X$?CC_jH=yfQS zA#BhcQJW4u=vUQzkF_oU?U?4Tdl0;*L7gSTTy?=pl!Ua`YstE~{C*VQ+eIrfy1!V{IY7S^wr{Up66C?bdomS4~T`tY?IU zU`BMzQrF>B?r%;hs1=)Yr>Lp)x~jS8?cXaUqa!VLR|tOuF@07?+t?sUN7%+5ux9Ja z2n>t3ry|pe2hx#Dxji?S zkPN4NWdCE!M}Arg>}(5Fj2q{@y}1^T~?kI15s;Vc4pjNTja1XSdz+}@Y zQ>EAO=xFPq3OqgHv10HAE$4gMrt984c`l+sM=RMxeVBYe+O~a=0U<3pE&o-sj6+dz zN`*-M$z~qNIbSs)%azOswIxA8x~L0e#gR(^3klL z(duxI8p}0c{y?poMdCL%d?p%BlnsemR!gH2)8@KN!*J8|AkHS5X#aVdKVzOEKB7EHS-s9^f2%%P*b@Xny2 z;R7>bm~A1ZAIO=!l?SKT@cS@@|>MxkXjJfXGH3tqJ{-=g->#|O30tk4C0 z&xFJ@PdDG$NEu)!{cq#G;2t&4tHb{?9@AbjtahL5#e&YQ+2(}Y&M`x`3t)UlBD@vU z|1urI)V{e$GS=!p>fE27Hn&i`08V7pJ^w~%aP_krx*wW%6aH}fp?~za@NHV5L#?TW zT3Js?`*|_Ejq6wM!xJ$B^FgSJm$u>~KMt>VGCAS_kA2#)d#~rvjB~x6lYPsU0f`%-qlg%_l0Cz zM8R`ZpDdnVS&TLg-Gd$*LCyGjpk;!vCE_F=UOE$K_x5;LeSygCf&fpWf7jUrGaDK2 z`I z#=a#${a}8xkr}&bG0xQN`wMBwv()qExUO)k5HxkQzg8%ZNod$2w>YRk|6rL-LJzN-t|p!H0c6eyCM-h?N4 zB`ni-3;cv9jLaxn46MU$tRY6=N>rASyrU0_rhLCGL&l{>XNx4)@c5kvnmzI~?DA}e zkWm&#I7kG$WHhba>bHh8xf^`CbJ7IvW>=P6H@03CuqfUmCI{EeGk*jAJ}>?RNiC*`|mviuvOglkgJQ z=PqUh-W}atSVU#BQg1tu39cs3g^WLPBQhQg(@g&fK?fVL1sk8Bgop|+52yq zXEfItVr{X-wmV1V-^Ue^zKM+!J;Asyfo{9P=~=oo9C7Peb_Up*tdldP_c2O#^A%?U zTA`F`qwYTGR2AM0g?JBVaEE({wYkB5Q14<)B7|a*D?gHR82p$l^cIcWVc#SxA$2*> z_iYN~)nss5_j>NaswW<%w{~#C;^y3#JD$6M&9?XBTlYm=-wM3|b{ChjaLN@c0lk~B zf&JLiqVZo@cw@-Y`Bk>i&2bd7S4N;8eSbqxre3M^JaRz&Smk7&z$jswXb`Eb|zDRR%^>#D_IeoG6pKi6<@z<`a~NIp)4{rN0XBa@)y=W z^+$D&ERHJ0h>+fNs|@`bdSo3PU9VoNp})aRG_e-`QnwGU*;93Kk9Lo`pZNMtyk@rA zPjZuA0>~-JPjl|rSA3-oX?Bv$N=wXcxUFQ)+#E(eiTIVN9R*y6Y4LGSL~$1)Gb{Gw zo~z{@gH@5dJ%Y1|cb%eU{qlms*-hUbP0a<>osLiVZ4>E|DcCw*$eiWc(?=Tex6+jn zs;L`bZ)q2~5)_6`yj*^kf*4q@#}%&sPM_29SCm{_it*EAXY6Y@Sj@4ufJKM-j-cL`9p@aEK5b)>Y@1TjTU3#_X72Z_cW~RID=aYitjDSm1EcvFA+*RP zS<`gmG0;VtEo7NtZ@iVbgko%Zp>}2KUPCpy&ND{JY>>Mdk~@C78?96f;%| zu?m(iF4T$4MIUMi7WY{!eFv%^y!rPT_uuYlx^L4uPRqgx{n2TzLb0y+$QkjeR=uFC zAyYXuH|A)`uj_THQikzU%__*`*)(nSfc=U5OV@c2)(|geI@<|zxeFisNwMDEdLMKi zbOCVdqft)U>DBcvdu~7GF8}-q0CWmMKk5)S90kPH&`IJ@zLvfBk==T`ib9xG2WCq~ z17_~U_eEUW3;kw@4e%LcZ8R8>NK@xrp7z>BJjwS-fvN{orfLu|*Nw~@au|qN{?Qa- znbMRVZg{){O~0dSi!IA79QJQ=Yn5EhI}o^i0cdJSB zx>+mxr{545$20bp~CB44E99_sfjs<#^G+yPxx5gEn$WzBfyj%8=Z%Q5R0G4lll*wTWN(KxY;95z*S z82#OBI$B(rXr$7Ml3JARTMm;rCTFXs=G4EsJ`OI$B`~qZ#YO-57pWTl9IY?o<{Q-R zsT8Fh2msX5vizW9B18=Z=OYqT_8t4_guXD#_{9R)NVmZlV7>4nEkKhG^8r7}$JfD*LUx{y*JNfLow z2l4sQ!0O8r!lS8Q&+6slldfdpgcHmO^^xv}*L;Y$%Mg2eCs`>M5%(UOBf1B>m3Cl3 zGg4CFA=28F#01hPvK|vT+Y|oP^}Z*TTTZm4OFENmMN56t8>1Mvt`^3iYxCO1ynH>_ z(zh#Ypyy?z3!c;XW`$W^4vl3$=ry?FD7U_7O~P6p)ED4~56OwuHMp|&?d!hNY7c*D zMUxqDNpR@D;rc%(wcTTBAiGM9(fPl1&XjG-HYK$L>4%7XKcooFUHBEK#GQg@X=7og zx~07}8|gNRnkAW%kvl;$b|0M3-6bLXcI{vu0pDvlKS4y4!w%FV8=o zZ?BkH>8*9v5`F_--u@0;M&Kx!M%xpr+PQpQraJgwTux&er6FZChoN~2SUIL7Zd^OI zvf;OrGjmvlN?WxHN_eeeBoAhGb*C?l&HS2Hz-HW~XgAIm!+uXC?=HXHlu5w%)06r*F9Y9nXe5Ea?qTv4NxZW)p|Y_Z!L6iIa8z^&%Vd~ zuqP3E|5gLn5C3}x*`oyx39bdF74Mq(SL!+}iahP-HjyCpRwr$S!T9*eE3mTM1;^w5 z^tz*|`Sbt{n!$LWgG4*3ln5;mZarS=lqLtSg?Q{AEx46R8DKi{6<{LR!nA$F!( z4N+)??wHrIO@@0=gH{Gu+50f4PQ=IwPcl>7e0!$vS$008P?>#y54di1>p#QxzvXh* z2wW~Ph}?G;e20}@9>12i$cCTYe4w3Hp-|d;`uL~NwyMBh&68U1N!_~h4hOW0fi$~Z zNK2w}0b3iGt0!JoMpjAH`~IJ$x*MnKwHbUb4@mXCSH|M%)9zJt9NhlV-6em`@bK+R zYlyHJT272^D&?C8<2B>N<%E1chc0NX@t^Kcxkt$M+Tnz2Am;!X(x&Hht#!F3g^xu@ zI%ULknG-HW;B@*#;KTJ!`&(bD5vT5iC-cPOkEsrnAElupP0C<)= z`S9>NMd;)>lQ8q(m@s{sW37i{2@2NDdT(~R5vIBs$Q5UWWHX7%%|`Xnp=QL07l7z5 zIiLFZ#YVgx1FF3Jq?z~Z0(h9zT|1=+|6UiEK_F0Tx2U5C=OJ?Pm| zUZt^-@488hODoNqWbafxeoN)FsI*AFSj%-4ZRt~|20E;_om!iV`FwpMk3QG9x*7#g zBHsKtlK;=)1nG(F>c83H;YjLQ&JxZ2LpO4#eGloIuO0pIU<^5nb+gPX64!&+w9in; z!KksBwAAHp^c*IyF^TMts-?Ya;Gu7tA`nXB6*Uod){d_vR(``?-*t_J)!#qTSL>7O z)Xt>u%iDypUjWw|prd8P-ajtA{JU4D%0{ZNaH*Q_@sUf!kx<0ZpXZ{NY#llx9^}CY z_k0`4_c}&HZD9?#SoKmak{?-kbE_!H=_ft{%-KNm*%?IuBj*4a7tSdtr{fhj+6|dH zirBcXt38em;LW;z3tEekOr3?T``u#)&e3X8&{?k|>-nq4T)*O~eOo$;K1y2l?QFVf zw7E*=62Qt#C#B?Tdl0Y`bpM zC_v`$=KmQt{}3c|n$wXTt&tb%p>W(J(GDI$ZneswQ?Ua}ot3XQ{S2;up0}E`)k}z+ zRE%sz_5Y~&HI&vg=xSjM2=bTcr6rN>eD&aa;ltm&=k`o~Xr*=!ICoSkc zy2pQS9J$Gq2!lzqp}&`ULIA-58t`NfNpk@6JZ-XF?jWk`-n6gijyGCznmQ?QZ8c010l-^0op zi@QolJJppeIHGsZOVq86 z--RY3f;vAKd`=m!yixMd)xctyM5Ih0Ep-zf#C)jduz`L)jKHY0uf4gH@{#k{O{Hgn z)rnDScy2WquNhqX#2iupma0lL!`$1qEex$F7OzSNj{lv^}J|CAXi2Rfv(um)!D*}cg*Z;iidE~4i^B? z$gP|p?vpU_s~mb;6fgK?3*}T^Gtt;p>@uHWTI)h6hZj4?%=(vp*qfZ07}r1FKRT@z zybrcS%3f6u7Q}U0)(%U z#8I{wSha_4qdLMeq^qevTA4apnJP+4W7OM#{;G<9 z0S2Ic)J8Gt)Xr6V$SWfrimo25UU61{wj1wqSNX!!0`HW1v4shZy6;#jGdOsW7Q5Ud z=j{^_?N>X~4b93=i}=r1bA#ScfBgM_i?YAUU&4kbz}U0{?!ry94>TLE3nWBk6Ngm@ zm}Y0gl|t_=!F1kks47!E@3`{r--sTz;4AmGvUI%VUCfB=?JSOUAjKa?S~hui7KTZl zlR+uyWn@3}SGJfdx-si=RL9(pk7E)qvySXS%z$8@bAO zDn=r%>;_I^)$1=?Y+3Jwto}Ze{&8v%&F$_FA zz~#@A?k|H;9@!(}T-gqX7r>Ja_mk68W<5o)=9VeL`_!K{;iZx%!7l=geUT$RmQE<>vGB)rU@M27KG*Pn zIAYNx2~DXV=ixaQtu-I?=xPYKH1GB7L_vhuA72*zJDdJj*!<7&PxCO&kz;Fv7}vNz z)+=)72(9hQTno*U4_cz;Ssuj)gtaZ!~D|19+1n4kr zeml{D=8j>S4#iI*ICV>6|ZB6wXW*A$h#+6Vfd~r*a$Enubz% z=V?$6zc}6Dge9<%y($Q$QXbM+^Dx$YbJ_^?4_4PCh~*E@rss~2U_{=(k9@0J-r9*^YsMg{_|8;ch$U6T zkK|4a0c60{Ca$qE{}2`Qh*xfscW0s>=5ObtTJXzg)?jr^)!u5joEh9{R8EV)zRmby|T6Aa`ROMjl`h9{awlFbafCt#M9{K zi3xixLEHvkMgDX?AcUZNY)R(rUYxG9OIg{Fw+wSzZ?263BvT*%dt3g~9WsB?n424f zZb!@ah^QwV?b?ZijnN!fBGe8u;qyAYLp2B;lT@XrC;^Dv@)pJbpBSXHI)_=jtoeBC zfR#+IR9?M1Q|h^b^^j(_W{yQv_Id_&F}9zyvke@a#Q*x!S3wW=#t556`j%$*xl`*% zV%%>UZ~Nt`6TyE7YBxd0}VnKtD5L6fQlL7w)VMUCbav1|HkSkGNc z#o4dqB9`wUVcg@qNgpT6IL#lEtt_Kiegup;q*CN$Jbx|VQMT&LAu$b(aB)LT$Fh1b z)PCKiM%cni;so$KXgBmzd3==d@B1Wbvb$AC$8@Qr-%XwN4cRw=H~$eX7nuJKfWm4M literal 0 HcmV?d00001 diff --git a/dox/overview/overview.md b/dox/overview/overview.md index a2f39328d4..2608d9d8fe 100644 --- a/dox/overview/overview.md +++ b/dox/overview/overview.md @@ -620,3 +620,16 @@ There is also another C# example with the same functionality, which demonstrates See \subpage samples_csharp_direct3d "Readme" for details. +@subsubsection OCCT_OVW_SECTION_7_3_4 Android + +There are two samples are representing usage OCCT framework on Android mobile platform. They represent an OCCT-based 3D-viewer with CAD import support in formats BREP, STEP and IGES: jniviewer (java) and AndroidQt (qt+qml) + +jniviewer +@image html /overview/images/samples_java_android_occt.jpg +@image latex /overview/images/samples_java_android_occt.jpg +Java - See \subpage samples_java_android_occt "Readme" for details. + +AndroidQt +@image html /overview/images/samples_qml_android_occt.jpg +@image latex /overview/images/samples_qml_android_occt.jpg +Qt - See \subpage samples_qml_android_occt "Readme" for details. diff --git a/samples/qt/AndroidQt/.gitignore b/samples/qt/AndroidQt/.gitignore new file mode 100644 index 0000000000..2c0f0cc01a --- /dev/null +++ b/samples/qt/AndroidQt/.gitignore @@ -0,0 +1,2 @@ +3rdparty +occt \ No newline at end of file diff --git a/samples/qt/AndroidQt/AndroidQt.cxx b/samples/qt/AndroidQt/AndroidQt.cxx new file mode 100644 index 0000000000..927c6f01b1 --- /dev/null +++ b/samples/qt/AndroidQt/AndroidQt.cxx @@ -0,0 +1,292 @@ +// Copyright (c) 2014 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +// ======================================================================= +// function : AndroidQt +// purpose : +// ======================================================================= +AndroidQt::AndroidQt() +: myFitAllAction (false) +{ + connect (this, SIGNAL(windowChanged(QQuickWindow*)), this, SLOT(handleWindowChanged(QQuickWindow*))); + + // set shaders location variable + QByteArray aDataRoot = "/data/data/org.qtproject.example.AndroidQt/files/opencascade/shared"; + qputenv ("CSF_ShadersDirectory", aDataRoot + "/Shaders"); +} + +// ======================================================================= +// function : ReadShapeFromFile +// purpose : +// ======================================================================= +bool AndroidQt::ReadShapeFromFile (QString theFilePath) +{ + QUrl aFileUrl (theFilePath); + QString aFilePath = theFilePath; + if (aFileUrl.isLocalFile()) + { + aFilePath = QUrl (theFilePath).toLocalFile(); + } + + if (!QFile (aFilePath).exists()) + { + return false; + } + + TopoDS_Shape aShape; + BRep_Builder aBuildTool; + try + { + OCC_CATCH_SIGNALS + + if (!BRepTools::Read (aShape, aFilePath.toStdString().c_str(), aBuildTool)) + { + return false; + } + + if (!myContext.IsNull()) + { + myContext->EraseAll (Standard_False); + + Handle(AIS_Shape) aShapePrs = new AIS_Shape (aShape); + aShapePrs->SetColor (Quantity_Color(1.0, 0.73, 0.2, Quantity_TOC_RGB)); + + myContext->Display (aShapePrs, Standard_False); + myContext->SetDisplayMode (aShapePrs, AIS_Shaded, Standard_False); + } + + myMutex.lock(); + myFitAllAction = true; + myMutex.unlock(); + + if (window()) + { + window()->update(); + } + } + catch (Standard_Failure) + { + return false; + } + + return true; +} + +// ======================================================================= +// function : InitTouch +// purpose : +// ======================================================================= +void AndroidQt::InitTouch (const double theX, + const double theY) +{ + myMutex.lock(); + myTouchPoint.SetStarts (theX, theY); + myMutex.unlock(); +} + +// ======================================================================= +// function : UpdateTouch +// purpose : +// ======================================================================= +void AndroidQt::UpdateTouch (const double theX, + const double theY) +{ + myMutex.lock(); + myTouchPoint.SetEnds (theX, theY); + myMutex.unlock(); + + if (window()) + window()->update(); +} + +// ======================================================================= +// function : handleWindowChanged +// purpose : +// ======================================================================= +void AndroidQt::handleWindowChanged (QQuickWindow* theWin) +{ + if (theWin == NULL) + { + return; + } + + connect(theWin, SIGNAL(beforeSynchronizing()), this, SLOT(sync()), Qt::DirectConnection); + + theWin->setClearBeforeRendering (false); +} + +// ======================================================================= +// function : sync +// purpose : +// ======================================================================= +void AndroidQt::sync() +{ + myViewportSize = window()->size() * window()->devicePixelRatio(); + + if (myViewer.IsNull()) + { + initViewer(); + connect (window(), SIGNAL(beforeRendering()), this, SLOT(paint()), Qt::DirectConnection); + } + else + { + Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (myViewer->Driver()); + if (aDriver->getRawGlContext() != eglGetCurrentContext()) + { + initViewer(); + } + else + { + Handle(AndroidQt_Window) aWindow = Handle(AndroidQt_Window)::DownCast (myView->Window()); + aWindow->SetSize (myViewportSize.width(), myViewportSize.height()); + //myView->MustBeResized(); // can be used instead of SetWindow() when EGLsurface has not been changed + + EGLContext anEglContext = eglGetCurrentContext(); + myView->SetWindow (aWindow, (Aspect_RenderingContext )anEglContext, NULL, NULL); + } + } +} + +// ======================================================================= +// function : paint +// purpose : +// ======================================================================= +void AndroidQt::paint() +{ + myMutex.lock(); + + if (Abs(myTouchPoint.DevX()) + Abs(myTouchPoint.DevY()) > 1) + { + myView->StartRotation (myTouchPoint.X().first, myTouchPoint.Y().first); + myView->Rotation (myTouchPoint.X().second, myTouchPoint.Y().second); + + myTouchPoint.ClearDev(); + } + + if (myFitAllAction) + { + myView->FitAll(); + myFitAllAction = false; + } + + myMutex.unlock(); + + myView->Redraw(); +} + +// ======================================================================= +// function : initViewer +// purpose : +// ======================================================================= +bool AndroidQt::initViewer() +{ + EGLint aCfgId = 0; + int aWidth = 0, aHeight = 0; + EGLDisplay anEglDisplay = eglGetCurrentDisplay(); + EGLContext anEglContext = eglGetCurrentContext(); + EGLSurface anEglSurf = eglGetCurrentSurface (EGL_DRAW); + + if (anEglDisplay == EGL_NO_DISPLAY + || anEglContext == EGL_NO_CONTEXT + || anEglSurf == EGL_NO_SURFACE) + { + release(); + return false; + } + + eglQuerySurface (anEglDisplay, anEglSurf, EGL_WIDTH, &aWidth); + eglQuerySurface (anEglDisplay, anEglSurf, EGL_HEIGHT, &aHeight); + eglQuerySurface (anEglDisplay, anEglSurf, EGL_CONFIG_ID, &aCfgId); + + const EGLint aConfigAttribs[] = { EGL_CONFIG_ID, aCfgId, EGL_NONE }; + EGLint aNbConfigs = 0; + void* anEglConfig = NULL; + + if (eglChooseConfig (anEglDisplay, aConfigAttribs, &anEglConfig, 1, &aNbConfigs) != EGL_TRUE) + { + release(); + return false; + } + + if (!myViewer.IsNull()) + { + Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (myViewer->Driver()); + Handle(AndroidQt_Window) aWindow = Handle(AndroidQt_Window)::DownCast (myView->Window()); + if (!aDriver->InitEglContext (anEglDisplay, anEglContext, anEglConfig)) + { + release(); + return false; + } + + aWindow->SetSize (aWidth, aHeight); + myView->SetWindow (aWindow, (Aspect_RenderingContext )anEglContext, NULL, NULL); + } + + Handle(OpenGl_GraphicDriver) aDriver = new OpenGl_GraphicDriver (NULL, Standard_False); + aDriver->ChangeOptions().buffersNoSwap = Standard_True; + //aDriver->ChangeOptions().glslWarnings = Standard_True; // for GLSL shaders debug + + if (!aDriver->InitEglContext (anEglDisplay, anEglContext, anEglConfig)) + { + release(); + return false; + } + + // create viewer + myViewer = new V3d_Viewer (aDriver, TCollection_ExtendedString("Viewer").ToExtString(), "", 1000.0, + V3d_XposYnegZpos, AndroidQt_UserInteractionParameters::BgColor.Name(), V3d_ZBUFFER, V3d_GOURAUD, V3d_WAIT, + Standard_True, Standard_False); + myViewer->SetDefaultLights(); + myViewer->SetLightOn(); + + // create AIS context + myContext = new AIS_InteractiveContext (myViewer); + myContext->SetDisplayMode (AIS_Shaded); + + Handle(AndroidQt_Window) aWindow = new AndroidQt_Window (aWidth, aHeight); + myView = myViewer->CreateView(); + + myView->SetWindow (aWindow, (Aspect_RenderingContext )anEglContext, NULL, NULL); + myView->TriedronDisplay (Aspect_TOTP_RIGHT_LOWER, Quantity_NOC_WHITE, 0.08, V3d_ZBUFFER); + + return true; +} + +// ======================================================================= +// function : release +// purpose : +// ======================================================================= +void AndroidQt::release() +{ + myContext.Nullify(); + myView.Nullify(); + myViewer.Nullify(); +} diff --git a/samples/qt/AndroidQt/AndroidQt.h b/samples/qt/AndroidQt/AndroidQt.h new file mode 100644 index 0000000000..9bc0e57b78 --- /dev/null +++ b/samples/qt/AndroidQt/AndroidQt.h @@ -0,0 +1,88 @@ +// Copyright (c) 2014 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef ANDROIDQT_H +#define ANDROIDQT_H + +#include + +// workaround broken definitions in Qt +#define GLdouble GLdouble + +#include +#include + +#undef GLdouble + +#include +#include + +#include + +#include + +//! QML item with embedded OCCT viewer. +class AndroidQt : public QQuickItem +{ + Q_OBJECT + +public: + //! Default constructor. + AndroidQt(); + + //! Display shape from file. + Q_INVOKABLE bool ReadShapeFromFile (QString theFilePath); + + //! Handle touch event. + Q_INVOKABLE void InitTouch (const double theX, + const double theY); + + //! Handle touch event. + Q_INVOKABLE void UpdateTouch (const double theX, + const double theY); + +public slots: + + //! Handle OpenGL context creation and window resize events. + void sync(); + + //! Redraw OCCT viewer and handle pending viewer events in rendering thread. + void paint(); + +private slots: + + //! Handle window change event. + void handleWindowChanged (QQuickWindow* theWin); + +private: + + //! (Re-)initialize viewer on OpenGL context change. + bool initViewer(); + + //! Close viewer + void release(); + +private: + + Handle(V3d_Viewer) myViewer; //!< 3D viewer + Handle(V3d_View) myView; //!< 3D view + Handle(AIS_InteractiveContext) myContext; //!< interactive context + + QMutex myMutex; //!< mutex for interconnection with rendering thread + QSize myViewportSize; //!< QML item size + AndroidQt_TouchParameters myTouchPoint; //!< cached state of touch event + bool myFitAllAction; //!< queued viewer FitALL event + +}; + +#endif // ANDROIDQT_H diff --git a/samples/qt/AndroidQt/AndroidQt.pro b/samples/qt/AndroidQt/AndroidQt.pro new file mode 100644 index 0000000000..7ddc34b91d --- /dev/null +++ b/samples/qt/AndroidQt/AndroidQt.pro @@ -0,0 +1,31 @@ +TEMPLATE = app + +QT += qml quick widgets + +SOURCES += Main.cxx \ + AndroidQt.cxx \ + AndroidQt_Window.cxx \ + AndroidQt_TouchParameters.cxx + +RESOURCES += AndroidQt.qrc + +# Additional import path used to resolve QML modules in Qt Creator's code model +QML_IMPORT_PATH = + +# OCCT +include(OCCT.pri) + +# Default rules for deployment. +include(Deployment.pri) + +HEADERS += \ + AndroidQt.h \ + AndroidQt_Window.h \ + AndroidQt_TouchParameters.h \ + AndroidQt_UserInteractionParameters.h + +OTHER_FILES += \ + android/src/org/qtproject/example/AndroidQt/AndroidQt.java \ + android/AndroidManifest.xml + +ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android diff --git a/samples/qt/AndroidQt/AndroidQt.qrc b/samples/qt/AndroidQt/AndroidQt.qrc new file mode 100644 index 0000000000..bcead84dcb --- /dev/null +++ b/samples/qt/AndroidQt/AndroidQt.qrc @@ -0,0 +1,8 @@ + + + res/qml/main.qml + + + res/icons/ic_action_collection.png + + diff --git a/samples/qt/AndroidQt/AndroidQt_TouchParameters.cxx b/samples/qt/AndroidQt/AndroidQt_TouchParameters.cxx new file mode 100644 index 0000000000..c844e26175 --- /dev/null +++ b/samples/qt/AndroidQt/AndroidQt_TouchParameters.cxx @@ -0,0 +1,107 @@ +// Copyright (c) 2014 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +// ======================================================================= +// function : AndroidQt_TouchParameters +// purpose : +// ======================================================================= +AndroidQt_TouchParameters::AndroidQt_TouchParameters() +: myXStart (0.0), + myXEnd (0.0), + myYStart (0.0), + myYEnd (0.0) +{ +} + +// ======================================================================= +// function : AndroidQt_TouchParameters +// purpose : +// ======================================================================= +AndroidQt_TouchParameters::AndroidQt_TouchParameters (const double theX, + const double theY) +: myXStart (theX), + myXEnd (theX), + myYStart (theY), + myYEnd (theY) +{ +} + +// ======================================================================= +// function : X +// purpose : +// ======================================================================= +QPair AndroidQt_TouchParameters::X() const +{ + return qMakePair(myXStart, myXEnd); +} + +// ======================================================================= +// function : DevX +// purpose : +// ======================================================================= +double AndroidQt_TouchParameters::DevX() const +{ + return myXEnd - myXStart; +} + +// ======================================================================= +// function : Y +// purpose : +// ======================================================================= +QPair AndroidQt_TouchParameters::Y() const +{ + return qMakePair(myYStart, myYEnd); +} + +// ======================================================================= +// function : DevY +// purpose : +// ======================================================================= +double AndroidQt_TouchParameters::DevY() const +{ + return myYEnd - myYStart; +} + +// ======================================================================= +// function : SetStarts +// purpose : +// ======================================================================= +void AndroidQt_TouchParameters::SetStarts (const double theXStart, + const double theYStart) +{ + myXStart = theXStart; + myYStart = theYStart; +} + +// ======================================================================= +// function : SetEnds +// purpose : +// ======================================================================= +void AndroidQt_TouchParameters::SetEnds (const double theXEnd, + const double theYEnd) +{ + myXEnd = theXEnd; + myYEnd = theYEnd; +} + +// ======================================================================= +// function : ClearDev +// purpose : +// ======================================================================= +void AndroidQt_TouchParameters::ClearDev() +{ + myXStart = myXEnd; + myYStart = myYEnd; +} diff --git a/samples/qt/AndroidQt/AndroidQt_TouchParameters.h b/samples/qt/AndroidQt/AndroidQt_TouchParameters.h new file mode 100644 index 0000000000..1debd06167 --- /dev/null +++ b/samples/qt/AndroidQt/AndroidQt_TouchParameters.h @@ -0,0 +1,60 @@ +// Copyright (c) 2014 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef ANDROIDQT_TOUCHPARAMETERS_H +#define ANDROIDQT_TOUCHPARAMETERS_H + +#include + +//! Class holding touch event state. +class AndroidQt_TouchParameters +{ + +public: + + //! Empty constructor. + AndroidQt_TouchParameters(); + + //! Default constructor. + AndroidQt_TouchParameters (const double theX, + const double theY); + + //! x coord + QPair X() const; + double DevX() const; + + //! y coord + QPair Y() const; + double DevY() const; + + //! Start coords + void SetStarts (const double theXStart, + const double theYStart); + + //! End coords + void SetEnds (const double theXEnd, + const double theYEnd); + + void ClearDev(); + +private: + + double myXStart; + double myXEnd; + + double myYStart; + double myYEnd; + +}; + +#endif // ANDROIDQT_TOUCHPARAMETERS_H diff --git a/samples/qt/AndroidQt/AndroidQt_UserInteractionParameters.h b/samples/qt/AndroidQt/AndroidQt_UserInteractionParameters.h new file mode 100644 index 0000000000..2010046397 --- /dev/null +++ b/samples/qt/AndroidQt/AndroidQt_UserInteractionParameters.h @@ -0,0 +1,28 @@ +// Copyright (c) 2014 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef ANDROIDQT_USERINTERACTIONPARAMETERS_H +#define ANDROIDQT_USERINTERACTIONPARAMETERS_H + +#include + +namespace AndroidQt_UserInteractionParameters +{ + const double RotationThreshold = 2; // [pixel] + const double PanThreshold = 4; // [pixel] + const double ZoomThreshold = 6; // [pixel] + const double ZoomRatio = 0.13; // distance ratio + const Quantity_Color BgColor = Quantity_Color(0.145, 0.145, 0.145, Quantity_TOC_RGB); // color of viewer's background +} + +#endif // USERINTERACTIONPARAMETERS_H diff --git a/samples/qt/AndroidQt/AndroidQt_Window.cxx b/samples/qt/AndroidQt/AndroidQt_Window.cxx new file mode 100644 index 0000000000..5fc200c952 --- /dev/null +++ b/samples/qt/AndroidQt/AndroidQt_Window.cxx @@ -0,0 +1,87 @@ +// Copyright (c) 2014 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +IMPLEMENT_STANDARD_HANDLE (AndroidQt_Window, Aspect_Window) +IMPLEMENT_STANDARD_RTTIEXT(AndroidQt_Window, Aspect_Window) + +// ======================================================================= +// function : AndroidQt_Window +// purpose : +// ======================================================================= +AndroidQt_Window::AndroidQt_Window (const int theWidth, const int theHeight, + const int theX1, const int theX2, + const int theY1, const int theY2) +: myWidth (theWidth), myHeight(theHeight), + myX1 (theX1), myX2 (theX2), + myY1 (theY1), myY2 (theY2) +{ + if (myX1 == -1) myX1 = 0; + if (myX2 == -1) myX2 = myWidth; + + if (myY1 == -1) myY1 = 0; + if (myY2 == -1) myY2 = myHeight; +} + +// ======================================================================= +// function : Position +// purpose : +// ======================================================================= +void AndroidQt_Window::Position (Standard_Integer& theX1, + Standard_Integer& theY1, + Standard_Integer& theX2, + Standard_Integer& theY2) const +{ + theX1 = myX1; + theX2 = myX2; + theY1 = myY1; + theY2 = myY2; +} + +// ======================================================================= +// function : SetPosition +// purpose : +// ======================================================================= +void AndroidQt_Window::SetPosition (const Standard_Integer theX1, + const Standard_Integer theY1, + const Standard_Integer theX2, + const Standard_Integer theY2) +{ + myX1 = theX1; + myX2 = theX2; + myY1 = theY1; + myY2 = theY2; +} + +// ======================================================================= +// function : Size +// purpose : +// ======================================================================= +void AndroidQt_Window::Size (Standard_Integer& theWidth, + Standard_Integer& theHeight) const +{ + theWidth = myWidth; + theHeight = myHeight; +} + +// ======================================================================= +// function : SetSize +// purpose : +// ======================================================================= +void AndroidQt_Window::SetSize (const Standard_Integer theWidth, + const Standard_Integer theHeight) +{ + myWidth = theWidth; + myHeight = theHeight; +} diff --git a/samples/qt/AndroidQt/AndroidQt_Window.h b/samples/qt/AndroidQt/AndroidQt_Window.h new file mode 100644 index 0000000000..575b1940ea --- /dev/null +++ b/samples/qt/AndroidQt/AndroidQt_Window.h @@ -0,0 +1,95 @@ +// Copyright (c) 2014 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef ANDROIDQT_WINDOW_H +#define ANDROIDQT_WINDOW_H + +#include + +//! This class defines dummy window. +//! The main functionality is viewport dimensions. +class AndroidQt_Window : public Aspect_Window +{ + +public: + + //! Creates a wrapper over existing Window handle + AndroidQt_Window(const int theWidth, const int theHeight, + const int theX1 = -1, const int theX2 = -1, + const int theY1 = -1, const int theY2 = -1); + + //! Returns native Window handle + virtual Aspect_Drawable NativeHandle() const { return 0; } + + //! Returns parent of native Window handle. + virtual Aspect_Drawable NativeParentHandle() const { return 0; } + + virtual void Destroy() {} + + //! Opens the window + virtual void Map() const {} + + //! Closes the window + virtual void Unmap() const {} + + //! Applies the resizing to the window + virtual Aspect_TypeOfResize DoResize() const { return Aspect_TOR_UNKNOWN; } + + //! Apply the mapping change to the window + virtual Standard_Boolean DoMapping() const { return Standard_True; } + + //! Returns True if the window is opened + virtual Standard_Boolean IsMapped() const { return Standard_True; } + + //! Returns The Window RATIO equal to the physical WIDTH/HEIGHT dimensions + virtual Quantity_Ratio Ratio() const { return 1.0; } + + //! Returns The Window POSITION in PIXEL + virtual void Position (Standard_Integer& theX1, + Standard_Integer& theY1, + Standard_Integer& theX2, + Standard_Integer& theY2) const; + + //! Set The Window POSITION in PIXEL + virtual void SetPosition (const Standard_Integer theX1, + const Standard_Integer theY1, + const Standard_Integer theX2, + const Standard_Integer theY2); + + //! Returns The Window SIZE in PIXEL + virtual void Size (Standard_Integer& theWidth, + Standard_Integer& theHeight) const; + + //! Set The Window SIZE in PIXEL + virtual void SetSize (const Standard_Integer theWidth, + const Standard_Integer theHeight); + +private: + + int myWidth; + int myHeight; + + int myX1; + int myX2; + int myY1; + int myY2; + +public: + + DEFINE_STANDARD_RTTI(AndroidQt_Window) + +}; + +DEFINE_STANDARD_HANDLE(AndroidQt_Window, Aspect_Window) + +#endif // ANDROIDQT_WINDOW_H diff --git a/samples/qt/AndroidQt/Deployment.pri b/samples/qt/AndroidQt/Deployment.pri new file mode 100644 index 0000000000..5441b63dc8 --- /dev/null +++ b/samples/qt/AndroidQt/Deployment.pri @@ -0,0 +1,27 @@ +android-no-sdk { + target.path = /data/user/qt + export(target.path) + INSTALLS += target +} else:android { + x86 { + target.path = /libs/x86 + } else: armeabi-v7a { + target.path = /libs/armeabi-v7a + } else { + target.path = /libs/armeabi + } + export(target.path) + INSTALLS += target +} else:unix { + isEmpty(target.path) { + qnx { + target.path = /tmp/$${TARGET}/bin + } else { + target.path = /opt/$${TARGET}/bin + } + export(target.path) + } + INSTALLS += target +} + +export(INSTALLS) diff --git a/samples/qt/AndroidQt/Main.cxx b/samples/qt/AndroidQt/Main.cxx new file mode 100644 index 0000000000..48102a5902 --- /dev/null +++ b/samples/qt/AndroidQt/Main.cxx @@ -0,0 +1,29 @@ +// Copyright (c) 2014 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include +#include + +#include + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + + qmlRegisterType("AndroidQt", 1, 0, "AndroidQt"); + + QQmlApplicationEngine engine; + engine.load (QUrl (QStringLiteral ("qrc:///res/qml/main.qml"))); + + return app.exec(); +} diff --git a/samples/qt/AndroidQt/OCCT.pri b/samples/qt/AndroidQt/OCCT.pri new file mode 100644 index 0000000000..200a4e6f3e --- /dev/null +++ b/samples/qt/AndroidQt/OCCT.pri @@ -0,0 +1,53 @@ +# +INCLUDEPATH += $$_PRO_FILE_PWD_/occt/inc $$_PRO_FILE_PWD_/3rdparty/include +DEPENDPATH += $$_PRO_FILE_PWD_/occt/inc $$_PRO_FILE_PWD_/3rdparty/include + +DEFINES += OCC_CONVERT_SIGNALS CSFDB + +QMAKE_CFLAGS += -fexceptions -Wno-ignored-qualifiers +QMAKE_CXXFLAGS += -fexceptions -Wno-ignored-qualifiers + +CONFIG(debug,debug|release) { + DEFINES += DEB +} + +occt_lib_subpath = libs/armeabi-v7a + +occt_lib_path = $$_PRO_FILE_PWD_/occt/$$occt_lib_subpath +3rdparty_lib_path = $$_PRO_FILE_PWD_/3rdparty/$$occt_lib_subpath + + +LIBS += -L$$occt_lib_path \ + -lTKernel \ + -lTKMath \ + -lTKG2d \ + -lTKG3d \ + -lTKGeomBase \ + -lTKBRep \ + -lTKGeomAlgo \ + -lTKTopAlgo \ + -lTKShHealing \ + -lTKService \ + -lTKMesh \ + -lTKHLR \ + -lTKV3d \ + -lTKOpenGl \ + -lEGL + +# IMPORTANT. load libraries in a proper order +ANDROID_EXTRA_LIBS = $$3rdparty_lib_path/libfreeimage.so \ + $$3rdparty_lib_path/libfreetype.so \ + $$occt_lib_path/libTKernel.so \ + $$occt_lib_path/libTKMath.so \ + $$occt_lib_path/libTKG2d.so \ + $$occt_lib_path/libTKG3d.so \ + $$occt_lib_path/libTKGeomBase.so \ + $$occt_lib_path/libTKBRep.so \ + $$occt_lib_path/libTKGeomAlgo.so \ + $$occt_lib_path/libTKTopAlgo.so \ + $$occt_lib_path/libTKShHealing.so \ + $$occt_lib_path/libTKService.so \ + $$occt_lib_path/libTKMesh.so \ + $$occt_lib_path/libTKHLR.so \ + $$occt_lib_path/libTKV3d.so \ + $$occt_lib_path/libTKOpenGl.so diff --git a/samples/qt/AndroidQt/ReadMe.md b/samples/qt/AndroidQt/ReadMe.md new file mode 100644 index 0000000000..080f5cbfb3 --- /dev/null +++ b/samples/qt/AndroidQt/ReadMe.md @@ -0,0 +1,54 @@ +OCCT AndroidQt sample for Android {#samples_qml_android_occt} +================== + +This sample demonstrates a simple way of using OCCT libraries in Android application written using Qt/Qml. + +The connection between Qt/Qml and OCCT (C++) level is provided by proxy library, libAndroidQt.so, written in C++. +The proxy library contains single C++ class AndroidQt encapsulating OCCT viewer and providing functionality to manipulate this viewer +and to import OCCT shapes from supported format of CAD file (BREP). + +Requirements for building sample: +* Java Development Kit 1.7 or higher +* Qt 5.3 or higher +* Android SDK from 2014.07.02 or newer +* Android NDK r9d or newer +* Apache Ant 1.9.4 or higher + +Configure project for building sample: + +In QtCreator, open AndroidQt.pro project-file: +~~~~ + File -> Open file or Project... +~~~~ + +Specify Android configurations: +~~~~ +Tools->Options->Android +~~~~ +* In JDK location specify path to Java Development Kit +* In Android SDK location specify path to Android SDK +* In Android NDK location specify path to Android NDK +* In Ant executable specify path to ant.bat file located in Apache Ant bin directory + +Make sure that "Android for armeabi-v7a" kit has been detected +~~~~ +Tools->Options->Build & Run +~~~~ + +The paths to OCCT and 3rdparty libraries are specified in "OCCT.pri" file: + +the paths to the headers: +~~~~ +INCLUDEPATH += /occt/inc /3rdparty/include +DEPENDPATH += /occt/inc /3rdparty/include +~~~~ + +the libraries location: +~~~~ +LIBS += -L/occt/libs/armeabi-v7a +~~~~ + +OCCT resources (Shaders, SHMessage, StdResource, TObj, UnitsAPI and XSMessage folder) should be copied to androidqt_dir/android/assets/opencascade/shared/ directory. Current sample requires at least Shaders folder. + +Select build configuration: Debug or Release and click Build->Build Project "AndroidQt" or (Ctrl + B). +After successful build the application can be deployed to device or emulator. diff --git a/samples/qt/AndroidQt/android/AndroidManifest.xml b/samples/qt/AndroidQt/android/AndroidManifest.xml new file mode 100644 index 0000000000..4d5be71a28 --- /dev/null +++ b/samples/qt/AndroidQt/android/AndroidManifest.xml @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/qt/AndroidQt/android/assets/opencascade/shared/.gitignore b/samples/qt/AndroidQt/android/assets/opencascade/shared/.gitignore new file mode 100644 index 0000000000..51e1556e0c --- /dev/null +++ b/samples/qt/AndroidQt/android/assets/opencascade/shared/.gitignore @@ -0,0 +1 @@ +Shaders diff --git a/samples/qt/AndroidQt/android/res/drawable-hdpi/ic_launcher.png b/samples/qt/AndroidQt/android/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..d27ba82c09f3fa1357a7501c50058a10524fdc8a GIT binary patch literal 2591 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 literal 0 HcmV?d00001 diff --git a/samples/qt/AndroidQt/android/res/drawable-xxhdpi/ic_launcher.png b/samples/qt/AndroidQt/android/res/drawable-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..a34301f3864675a2b09308ce64ebd482130141bc GIT binary patch literal 5560 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 + + AndroidQt + diff --git a/samples/qt/AndroidQt/android/src/org/qtproject/example/AndroidQt/AndroidQt.java b/samples/qt/AndroidQt/android/src/org/qtproject/example/AndroidQt/AndroidQt.java new file mode 100644 index 0000000000..d67d8fd091 --- /dev/null +++ b/samples/qt/AndroidQt/android/src/org/qtproject/example/AndroidQt/AndroidQt.java @@ -0,0 +1,99 @@ +package org.qtproject.example.AndroidQt; + +import android.content.Intent; +import android.content.res.AssetManager; +import android.os.Bundle; + +import java.util.List; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +public class AndroidQt extends org.qtproject.qt5.android.bindings.QtActivity +{ + @Override public void onCreate(Bundle theBundle) + { + super.onCreate(theBundle); + + // copy OCCT resources + String aResFolder = getFilesDir().getAbsolutePath(); + copyAssetFolder (getAssets(), "opencascade", aResFolder + "/opencascade"); + + } + + //! Copy folder from assets + private boolean copyAssetFolder (AssetManager theAssetMgr, + String theAssetFolder, + String theFolderPathTo) + { + try + { + String[] aFiles = theAssetMgr.list (theAssetFolder); + File aFolder = new File (theFolderPathTo); + aFolder.mkdirs(); + boolean isOk = true; + for (String aFileIter : aFiles) + { + if (aFileIter.contains (".")) + { + isOk &= copyAsset (theAssetMgr, + theAssetFolder + "/" + aFileIter, + theFolderPathTo + "/" + aFileIter); + } + else + { + isOk &= copyAssetFolder (theAssetMgr, + theAssetFolder + "/" + aFileIter, + theFolderPathTo + "/" + aFileIter); + } + } + return isOk; + } + catch (Exception theError) + { + theError.printStackTrace(); + return false; + } + } + + //! Copy single file from assets + private boolean copyAsset (AssetManager theAssetMgr, + String thePathFrom, + String thePathTo) + { + try + { + InputStream aStreamIn = theAssetMgr.open (thePathFrom); + File aFileTo = new File (thePathTo); + aFileTo.createNewFile(); + OutputStream aStreamOut = new FileOutputStream (thePathTo); + copyStreamContent (aStreamIn, aStreamOut); + aStreamIn.close(); + aStreamIn = null; + aStreamOut.flush(); + aStreamOut.close(); + aStreamOut = null; + return true; + } + catch (Exception theError) + { + theError.printStackTrace(); + return false; + } + } + + //! Copy single file + private static void copyStreamContent (InputStream theIn, + OutputStream theOut) throws IOException + { + byte[] aBuffer = new byte[1024]; + int aNbReadBytes = 0; + while ((aNbReadBytes = theIn.read (aBuffer)) != -1) + { + theOut.write (aBuffer, 0, aNbReadBytes); + } + } +} diff --git a/samples/qt/AndroidQt/res/icons/ic_action_collection.png b/samples/qt/AndroidQt/res/icons/ic_action_collection.png new file mode 100644 index 0000000000000000000000000000000000000000..c41ca8c8b2450e10e653afcbbf36893883d2cdc1 GIT binary patch literal 650 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7OGok|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*9U+m~=c{978H@y_vJokI7M>&EMJ8+c$gl$;L>-v=x`~zPMbi@2Gcn>i zf(fTjdCpKe(6{V|H_MHp=}F>8R2FFdV`j>U++tnGVlb`mu*#wRFVB}a28z7?ukj$e z-G_ydNq`|RzUBU%#YUh_D*TQv=ZrEjTtf=}~@0;tIvqkUF-9Pz{(!FvIKT;2I@cdIzT(ELuxZs7| z6S)|TwnhDJ$oq3<^TfPFmjfT94eL&=sNen9Xa}7nQiXpM9NJ}>cpg8$GXJ&G0fRaLfyRb~yOr#W{;{`oOgL-~k53>& cVx~VM8-xAZS