From cfa20b6eb3e86ce72a1b37fd3b3409060740a1c5 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Mon, 8 Jan 2018 15:28:59 -0800 Subject: [PATCH 01/19] Oculus Touch: More accurate spin on thrown objects The internal computation of angular velocity was incorrect. Apparently, the ovrPoseStatef.AngularRotation is not in sensor frame but local to the controller rotation. (cherry picked from commit dd0e57026e123779784102658a264f6aaeb70f67) --- plugins/oculus/src/OculusHelpers.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/oculus/src/OculusHelpers.cpp b/plugins/oculus/src/OculusHelpers.cpp index 3d06a4b223..4632c8ab76 100644 --- a/plugins/oculus/src/OculusHelpers.cpp +++ b/plugins/oculus/src/OculusHelpers.cpp @@ -262,7 +262,7 @@ controller::Pose ovrControllerPoseToHandPose( pose.translation = toGlm(handPose.ThePose.Position); pose.translation += rotation * translationOffset; pose.rotation = rotation * rotationOffset; - pose.angularVelocity = toGlm(handPose.AngularVelocity); + pose.angularVelocity = rotation * toGlm(handPose.AngularVelocity); pose.velocity = toGlm(handPose.LinearVelocity); pose.valid = true; return pose; From 319913e6afd462d7eb1cb9bbf4edd29c3d3e9edd Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Mon, 8 Jan 2018 20:37:07 -0700 Subject: [PATCH 02/19] Fix toolbar appears on HMD mode --- interface/src/Application.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f3c41565f8..1cc1b6b15a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -7357,6 +7357,7 @@ void Application::updateThreadPoolCount() const { } void Application::updateSystemTabletMode() { + if (!_settingsLoaded) return; qApp->setProperty(hifi::properties::HMD, isHMDMode()); if (isHMDMode()) { DependencyManager::get()->setToolbarMode(getHmdTabletBecomesToolbarSetting()); From 9a8141076235185b0d7239682bc0525cc0498b47 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Mon, 8 Jan 2018 20:51:15 -0700 Subject: [PATCH 03/19] refactor --- interface/src/Application.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1cc1b6b15a..6cabab6c01 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -7357,12 +7357,13 @@ void Application::updateThreadPoolCount() const { } void Application::updateSystemTabletMode() { - if (!_settingsLoaded) return; - qApp->setProperty(hifi::properties::HMD, isHMDMode()); - if (isHMDMode()) { - DependencyManager::get()->setToolbarMode(getHmdTabletBecomesToolbarSetting()); - } else { - DependencyManager::get()->setToolbarMode(getDesktopTabletBecomesToolbarSetting()); + if (_settingsLoaded) { + qApp->setProperty(hifi::properties::HMD, isHMDMode()); + if (isHMDMode()) { + DependencyManager::get()->setToolbarMode(getHmdTabletBecomesToolbarSetting()); + } else { + DependencyManager::get()->setToolbarMode(getDesktopTabletBecomesToolbarSetting()); + } } } From 776a2e83734d5655d18b4da16877ce49134bf2a4 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 8 Jan 2018 17:18:16 -0800 Subject: [PATCH 04/19] Fix concurrent access crash in avatar mixer --- .../src/avatars/AvatarMixerClientData.h | 5 +++-- libraries/avatars/src/AvatarData.cpp | 17 ++++++++++++----- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixerClientData.h b/assignment-client/src/avatars/AvatarMixerClientData.h index acd9be0702..7a7210a0e8 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.h +++ b/assignment-client/src/avatars/AvatarMixerClientData.h @@ -116,8 +116,9 @@ public: void setLastOtherAvatarEncodeTime(const QUuid& otherAvatar, const uint64_t& time); QVector& getLastOtherAvatarSentJoints(QUuid otherAvatar) { - _lastOtherAvatarSentJoints[otherAvatar].resize(_avatar->getJointCount()); - return _lastOtherAvatarSentJoints[otherAvatar]; + auto& lastOtherAvatarSentJoints = _lastOtherAvatarSentJoints[otherAvatar]; + lastOtherAvatarSentJoints.resize(_avatar->getJointCount()); + return lastOtherAvatarSentJoints; } void queuePacket(QSharedPointer message, SharedNodePointer node); diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index f2053e29d7..94df5bf7f4 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -530,9 +530,13 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent destinationBuffer += numValidityBytes; // Move pointer past the validity bytes + // sentJointDataOut and lastSentJointData might be the same vector + // build sentJointDataOut locally and then swap it at the end. + QVector localSentJointDataOut; if (sentJointDataOut) { - sentJointDataOut->resize(_jointData.size()); // Make sure the destination is resized before using it + localSentJointDataOut.resize(numJoints); // Make sure the destination is resized before using it } + float minRotationDOT = !distanceAdjust ? AVATAR_MIN_ROTATION_DOT : getDistanceBasedMinRotationDOT(viewerPosition); for (int i = 0; i < _jointData.size(); i++) { @@ -552,8 +556,7 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent destinationBuffer += packOrientationQuatToSixBytes(destinationBuffer, data.rotation); if (sentJointDataOut) { - auto jointDataOut = *sentJointDataOut; - jointDataOut[i].rotation = data.rotation; + localSentJointDataOut[i].rotation = data.rotation; } } @@ -602,8 +605,7 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent packFloatVec3ToSignedTwoByteFixed(destinationBuffer, data.translation, TRANSLATION_COMPRESSION_RADIX); if (sentJointDataOut) { - auto jointDataOut = *sentJointDataOut; - jointDataOut[i].translation = data.translation; + localSentJointDataOut[i].translation = data.translation; } } @@ -646,6 +648,11 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent if (outboundDataRateOut) { outboundDataRateOut->jointDataRate.increment(numBytes); } + + if (sentJointDataOut) { + // Push new sent joint data to sentJointDataOut + sentJointDataOut->swap(localSentJointDataOut); + } } int avatarDataSize = destinationBuffer - startPosition; From 125eb9ce445132f7fcf6c3159b058953cf2af2b7 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Tue, 9 Jan 2018 14:31:57 -0800 Subject: [PATCH 05/19] add new tablet model and adjust screen offset --- .../meshes/tablet-with-home-button.fbx | Bin 196940 -> 198012 bytes .../controllers/controllerDispatcher.js | 8 ++++---- scripts/system/libraries/utils.js | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/interface/resources/meshes/tablet-with-home-button.fbx b/interface/resources/meshes/tablet-with-home-button.fbx index 70b8008bad32a7288bf3b2e9a3b33a982af8be79..37247022f6431306639156fa99def798cbef41e6 100644 GIT binary patch delta 18748 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±xXDaK=_#RK_d@wC)iPKFOF`_G`(Q)NB zmK2e^7mw^YR%WH2wL@g;Mfsg2MbyhvwH46XHwB3F0Kt7B39)cP4pg%d{ZvMU>AZko z!mlhthlzzW{~^^VM%Dcu+*z0s|8-S+yUKmc@ZDd^hQPmktmKMh8STqZYt<2{+9sAI z(#n(^3Kq>afc%BuCre4BOZGaPWjVW8KZY5w9 zN~R3CNL=flA>T)3y6cUfk{ExjQmJ@3nj`iZvvI`+c-z7%v07b`fHy}R_2B`VxOvu6 zA&Ma~A%P|=ORH4?UNUB!CDmFX(OcM#G4wy@jnrM?Rhe!XV|Nb?pnOzo-dJ;XIL zm-1C_<*kMz(eoKP-+APq=H#N8BRbDwg{yFRtKwT{l&;{XN_T!&NMMhJMRU#f;C__7 z9JlQ4+JkSmeN@BKDJ*M1kNcc>_~IhFwc^0EROoP-3H1^{j47HD+3$3ZlvH*Ob(_Zd zp*>d8?ozChzwl%^<|f=L68*A&KW^!Gq(#P7-I3j4Z5L=4EatpH>;ceoP)O7 z?P5vZ-o3lIv+Ev?v*s(T2(HfvzMRn&VXf>D#(?*(2HNE~{Pmo^PpntHy0VnVGv{1g z42(!5$(L4TpNBFoEvwcR=hawp#>Q_AW0pdDk<41Tf|oc0OcdIq>mocW#p|shZ2gMd z*A~F;=~5_ya~o$$LZDwSr63P+?yY>XZbT0pcBO?LaH8aU#v!uOYb>$*T|2ctji9>d z(dd_oAJ7aJHL|nIb*Aa5aP+GMi=2b#J5r37vlj*(VCnsRk`@6ky6KkOa2szd^xVQ} zh9lu6w#3^&T6C(UYT3;ut^Z<7=R4|%E-Fs-qug)R4tQGA<6)$U`aGFhVZl7G-==`B zZ$a<-i8zhB=^iU9RCi-ixG{|9Ay~j{(RdS zXTYi8Nkt)VcVm&<*ErA9`LXqQT&~)E%$S!HQY)rcL6(v@bI$b`&WOam^fI=2_`rH!e*l&gRjyfbL zjtez_i-X}g&m4%@H?GI6sErkLs}@{Q>PfLfTq`ilL++~aRLomuEfI9hHiN&Axyrr6 zsYk2s;5Dl!!t=i=4!?KYkSvw3Bp}0;} zR%p)qv`i@RBF85Y%Le|PC{TXysH z#$^vL=T<&nXm#-8c_}kE;lvLdj$&@h3$lFm9BhyxhMBqoRuNVCvO)3h6Y;MVuK=)-_eS>pItDK8*@M2-xRGE{ z`le|@8Q!`8-9VY<+yk+$w#s4nexE}NR+%0)x84m7#q!;2o$Mz}mAM@wILH)ZBrxKn zxT8fzD@gG$AOFxOMVp29dhF?BUlNpZxRNvSG&T(%wom?KPQ=zk*Vi64OM8vCCD$xLL6%bEfi+t2V`xc2Ss-b`t*2-YwwlfE^seoSB@*1Y@Z| zKEod(;oK{g?ws=)qr$X3@6}(&u#CA+=`^JTm42LQ{~C1-`!@UQ$9X%bMfts-$lLo_=iC zS&Cx0miRZHbi(iNkGWi=Y_xi$(iqKa!C}wMRnNFVPvdb?NO5cY$|e);`!0FjieHbP z>>dq@`24_5Qia(TWYPW26oNO9Ycw}k_%s%=)?y`%m9X&jeI|9>xwbZ z3!8Gh5GyH9Y(^dAC#GGSTrG~a@LSbUy!u}!oHo}I(#UqJ3$=inl?!l%8NY7QyAc}V zPKV_h7FG*OVaEM0(qA>Q##En{UL&3@{YG3&9DQkns*xQ>;4L=D0c%!}8|S~2?d65r zj4JN-z8A-z9K7Yo2U1&>i@V*~Z41Z!y|7V~gr~8i_;n>uJPzI|F@{YC>e;5O7CjtD z)%dX>{+4G~IkmF?*}l?xM9h5pM6Q~coBCt^wqYj=n$!tYy z^S0x6q!{l;oW8#XKn>vM!i9%aa)441H}DmCy~mEJ&zhHpXJ34sm`Io`OE{xh%bV1a z_Llk8vf;Hj@|nYKISw9g;F3~pri-he22W3AiFid|UF6r$4t@z`w*y6ioGsp`;*HTW z7C{XaY~)yRkMAJEXhWez{9e2&z;$ow`#eE9;2%E+FcHec3b7eN&Nva%X)mAWag1E} z`Y|B@?kQa0tr~xD;)e4q{H+f=GDW(JK)0{hMP$9D?Czy!a7@xE^vSkmJ6;F!J_Yqv z!&8F@uRJ+Of5l~7uOPqlNyLJzMdr!4&dX@b=O(|r2AqF0uT#$)FPJOOo>=2o1Y8;} zc{x~gOr{a!&*)4^S9H$GM-lli47AQJDGuym+8quulm#TUa|=TgYRm)2yf^GfhNGda z&;UQ4V>@&_bt#U=O}0p)AHuoA6%wXS3>d$A<;@$(W@{;wrcCPHQ)1o(Ft}RHZ4d5A zeZ?MP-bIK9sJ*Mmfi0bZ)`<6)F?=R2g@ zly!>}c}FHfvt}EZ3*HOb36$O-v0=PbcT`{Bqmv`Sgvb7Bdl0w(HEV_Tm|JpV94KEe zP|2xm3-Dme9si4tI)n=W4#x)eP4T880bbf%thIXPNn3v%TXEv|p)Y`c*(8Q#xTJW8 zsmEq|v|@d3|HSU@eUA2mQZ`UxPgXoMlSY1Z;@o?)RovFNdMW!`>;yR5C7Yi3%eL0L_Hp!FT&z$ejUm|ST z&dJq+>I4sufC)9&>CXunCs@aaj!$7Y*^?Ob)JxZA9|O+g*pOD`nm}svV_0UUO}ji@ zwejyMFlTIDoMY<9JpgcqR&5o0Z-WU%mk~wqmhBwZetqC_;5Fbb{V>3boQ#e?O22;| zMvnhJ(trIU?-A~5z%i*yoP`JXqzVePLMx>AG4GxT*oUWYZq)-kvIy6#ECJ!tAH;Xb z@Z(b$?y`+7piqitP8?NMV=1 z^QJGI{$6hH%&8g)K%DbZ^-{T%6G+G1*u#{Vz7&v=Ue7E{^Sb5Nj^D$7G0~Q?DpKl& zYz5r0llTCmW$5gMR`>ox9lWMH@X7-mF~1K?eD*AS^&$4j@Io6}zesmkSzN49JxY=P z5+bE23HW{MNzL&RJ*96rBn8Mn+b4f5CYdA5pO0Ila3r3klUXbsL<6-P1Y8Qe1BUyQibig5BeUcCO86F_^LD7Y<6HZ>us5cs`xGz7w=5-XRau1E%5W!HRxVhN}{h&2T_nkm-BQHFl?l2HyG*1j(5rSn_eAW3Io7sJHK@fQiFSQl{lOjH*Glp`1H>up zHY_hWaF*AMUj#yjXv++#m)zMco*Y#LePltkxr>I4>h7tLv`0rba4c~c^_fXlpC zd{?M)ErR}f)iGhAmY&yRlGAi5a)yfCl@s&>rR0IW^hg|TjvbvKuRDQ=^`o}Sr9p?!eCn?yY?CFLLWw>E4rrrL5V}m!Aq48qpCIW_6HlcVwPx*zc zEc8E%e__V1?tNAWY$vt!J8JakPMmE$W4sc)D(x)=x5GX-1I%g`tI#5?W1RMLLR%gs zxf{+elu~Jg+58uq8WxIp3H~|X9+tis89^X8TE57mPQ!^WuT?V<&Ia^y~lHH%C z-G_Lx!IPz}UmIcLaX8!#%PoTF;oUGqqft&;KZ*Y3{=Hb-Etb;l#IJjqft;f{Cs zE2Iaob$2{o5B>g;)gotN^;vhpNDbf-wkuxZJSs!=ejP1rKE|Wee(`NO=Yj@w!M#Og@xA1Wx0pXODEc8sGOU4 z)OyA{x*79{CshyIg^NM`SlU6t9w;g{7&pFVpwQp9J?OsXx)~J@v}_z}YY*%qXC@&E zKwaTjjqA2AWV9Hdo>SN4Z2IQDBRpqs{P`KkNleOwTcRfE2@0CM@22e&nC{HhsGxf` zLNos1g%^Wb-H%;~$9Twe41LZK@`PmdwYrP(-zDjuRQZ9r>S59b|J+YV6}vSr;}5`P z)!qW4gG}d9GJbO2@0h%Ezqe$8-b5qNiek8Qd8bS*w2!}JlUBNy(+y81m~(_B)^}we zmbQ?xtiT4fz>{gO=7Tm?@E#1TY7<4AsKqw#yaNYsr4IV`7Tffw__PRV8bA~J!xrFK zXAbEA(W~9ZV=qWxvw6YbG5Vsp?ko(4LIb^4w`;CR(=B1f zHRhtfEvaVYMhxfYf-KZ!0GiOYz~WJ_;HQmha&&BFnYUtGc*zrIfW(PolTzv?iaNAc zuT(wLU#WVxDSSbGb=Ag%x+IRm{ae;)1j#!|$d@Znq8e5=rqtvt?DdM5;+#i?wKNf^ z!V>j>XW(RNxh4N^OH1rEOR#6_sU#b4)>hdoK(UDi@zq%;E47DM%}D0WYYuhIJ%=`% zDLL<}*E@+za$N(0&rSeLn&!zYi7#azTpd82nfc_8J7E^WI^JWAHMGphy!jXp`Szoe zC@KDPp2v3BnZ?^JOwch&2xEiPXr>1$?JXDD*`bH2TQU0A@?wXFV)bP|N2r5hXKVCRUzXT zfd|cS&^-(({Vn33tZOgdLfN|+@>#sY!6B>!IGDHwG87J8Ns@vTg@e4rgOK)c@O6?R z#2`YDC?5ejChdi2MhFt~ekF!PfW#yvNSYuKe5}5EH!kJBR_>khUETt^g)2c$Me>*W z{d?u!^+>_Wy=zf|-j`$k zkVDA=aUUfKf(0i1SFrpffw(hC0uQpupid%9IyvQ^tp6jfW%3_!tCIyfzE2j2`!!jh z>pm<)~C#0bt+`G@z>H# zAz@>F`ajDx*(soFvJ@osgJ6xNYbt1aKu+_$h5Sr0)Z0k}AE6^5K^}{AH=4X7_I0addLf6P8Q^fm9W# zsEl9L+V@Yj;w}px08NwSA9~@7Xf@r3LyyR<;u=Kx)q#*6-0)~wl ze;Cv<1Pmq_0){&o|HTlLAz;}0@fXA4e;DLKH|_#!QV&3;G6W0}Spo*zOwjhgWzg}% zR!Dv(UoY@z#%{>^EKvNQ4!9*v5@M1i;CPnxha)>nz)_zi;26mIFAm|40*>J9|HI+f ze`!0YlYRhV_ff#HDOLsb7sK*as@he$D7 zKy)r!K=fDke-Zg*^NDtU&izGnkiQn!_?Cygo8zsAmkoo5mB7+W1qdno*BxH92Exk* zUA`&^%YeE$GLV#90p+tCF!75Cq$USk{GtPqz=6l|j3KviAdqJaNy33GdD@UA9JnRl z6mtGEcr#xU#NZ?$&pv~n^K~Hj&){PIaq!2d^}-NPI9HQ@2Dz3CIu%@jyvYT>72Md} zUGQIUTHT+IfFs!okTqZaz$t#=!$I`E2rAxGz^4=b1Y*A+AhTciaKc)kYMzO32#C%z zfi&dt(S&8e&G}b_AA-nygzzU2mk)}Z6#u2$r5CN>#xMIIN5B3i6TSjEf87gt_*DS5R4kCKuP`TiY;Iz41fGAcWK)h1*3-Q3eG~+-d#X;+mJrMtj zKZw{0!M#=r4pqoN^r{4e`|$$8gQZfCJ9q(M9$r8Q`6eLb8+5-32&29U2uHvDx##v* z3Mi440!o+i^}@+uQl%#U46;-yfIM9#fb^;RFCF1Zt-@eng#skC>JKELN}%INl|aV_ zbpp!E)q+d=s#-wUS1lksTqC%&jx_?hvKj&1=30S%mum%NLA89cjr}D4VScu;mapNT zpR#oVMB6$6BDV3rblmn~n-KW1Y7eBT?hoR8od9toL4X+9C_r>42oUoK0z^o?0MWEw zfEZpcKpd$TAgVP85ZxODh&c@c@$j|lA(RHeCFY;%H44z4H}cV>_cs4R<1g(Oy=L#@ z;pt|7nd7en1zYQsAnTeybi;lKvRv);EI-^_QhT5dS0ShjmeE zU~AnD(6K=R^0HYFIJsF6xThH`Z#V^6-vYW46u_yT&5#!@U?Ra=)Px_cqXkTAG={t- zg05}5go%Qf7Q{a>Ly3Zzdw%|k$?w(vR5X4l_W;<{BoBf75X6)DA&7VJ2YC9sGQ{r( zX!rd%g!2P@^Zl{Nl~$n`3Q711MB=BQc5$tONIzTuL|XTgA4w~`{hzD-CsMx;OHME_ z*v{Wh!rn*4?xC~0y^!$Vk_#3z06zr~Z+{9P2tUERmZK2*PjI;92*j-o6es#YzO{j` ziI*XP?E-|&?E-{z?SBxw+W82Ytj=Eu`~SDH_x$Bg3lR95Snv_toSi-XO)%dsAQ0^k z5S;1&_qHB^-0lFcv?@aeI>3NdUx;!i$Y?c!%y$Y1ygLO1*`0p~hC2BKGO7K)2vqqU z_;trS_Rg1oba^W9cx z;dK9VQ^oY>?dtfjMrtQnSg>)%|9IZ_rCtVX?>P+N_47Se3YG5-}ST29LMzf^-bVIFW=OLzISM7D>XU zkfEAFy?)`E5h=gnUjh01fBY@bQctL8jC>{JkjTYah#uzuBh2oAt53CM~?39j$ZZ`ZrOP_yAAza zl0TN`myA*2LDp^gS4jbvwv5Oxu78L4-Es=LbOG1@4PhqocWwWb`Ipz%|LOI2V<_l_ z|36-9e|!B`W`S3cS&_e$|J|wyI!(SKi8X&)_^lE@;g7PKzb(I8mOt{{`fcGi0fI8W nD-!&-<;3sD_z(HNj^_V)6xUw6^}yc!+nQ((5rgP&BCq}*3oe_+ delta 18498 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 diff --git a/scripts/system/controllers/controllerDispatcher.js b/scripts/system/controllers/controllerDispatcher.js index 7f2cbe0aee..16f1d086b7 100644 --- a/scripts/system/controllers/controllerDispatcher.js +++ b/scripts/system/controllers/controllerDispatcher.js @@ -148,8 +148,8 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); this.setIgnorePointerItems = function() { if (HMD.tabletID !== this.tabletID) { this.tabletID = HMD.tabletID; - Pointers.setIgnoreItems(_this.leftPointer, _this.blacklist.concat([HMD.tabletID])); - Pointers.setIgnoreItems(_this.rightPointer, _this.blacklist.concat([HMD.tabletID])); + Pointers.setIgnoreItems(_this.leftPointer, _this.blacklist); + Pointers.setIgnoreItems(_this.rightPointer, _this.blacklist); } }; @@ -378,8 +378,8 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); }; this.setBlacklist = function() { - RayPick.setIgnoreItems(_this.leftControllerRayPick, this.blacklist.concat([HMD.tabletID])); - RayPick.setIgnoreItems(_this.rightControllerRayPick, this.blacklist.concat([HMD.tabletID])); + RayPick.setIgnoreItems(_this.leftControllerRayPick, this.blacklist); + RayPick.setIgnoreItems(_this.rightControllerRayPick, this.blacklist); }; var MAPPING_NAME = "com.highfidelity.controllerDispatcher"; diff --git a/scripts/system/libraries/utils.js b/scripts/system/libraries/utils.js index a6e2751a83..bc83cc582c 100644 --- a/scripts/system/libraries/utils.js +++ b/scripts/system/libraries/utils.js @@ -400,7 +400,7 @@ resizeTablet = function (width, newParentJointIndex, sensorToWorldScaleOverride) }); // update webOverlay - var RAYPICK_OFFSET = 0.0001; // Sufficient for raypick to reliably intersect tablet screen before tablet model. + var RAYPICK_OFFSET = 0.0007; // Sufficient for raypick to reliably intersect tablet screen before tablet model. var WEB_ENTITY_Z_OFFSET = (tabletDepth / 2.0) * sensorScaleOffsetOverride + RAYPICK_OFFSET; var WEB_ENTITY_Y_OFFSET = 0.004 * sensorScaleFactor * sensorScaleOffsetOverride; var screenWidth = 0.82 * tabletWidth; From e54f7d5a45516f2fbd61f08de7311474b40684fb Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Wed, 10 Jan 2018 13:03:54 -0700 Subject: [PATCH 06/19] Fix Pal Master Volume overlap --- interface/resources/qml/hifi/NameCard.qml | 4 ++-- interface/resources/qml/hifi/Pal.qml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/resources/qml/hifi/NameCard.qml b/interface/resources/qml/hifi/NameCard.qml index 3f5cad655d..9993d1f2b6 100644 --- a/interface/resources/qml/hifi/NameCard.qml +++ b/interface/resources/qml/hifi/NameCard.qml @@ -50,7 +50,7 @@ Item { id: avatarImage visible: profileUrl !== "" && userName !== ""; // Size - height: isMyCard ? 70 : 42; + height: isMyCard ? 84 : 42; width: visible ? height : 0; anchors.top: parent.top; anchors.topMargin: isMyCard ? 0 : 8; @@ -520,7 +520,7 @@ Item { Slider { id: gainSlider // Size - width: thisNameCard.width; + width: thisNameCard.width - 20; height: 14 // Anchors anchors.verticalCenter: nameCardVUMeter.verticalCenter; diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index 64f61f0d69..02971cc984 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -28,7 +28,7 @@ Rectangle { // Properties property bool debug: false; property int myCardWidth: width - upperRightInfoContainer.width; - property int myCardHeight: 80; + property int myCardHeight: 100; property int rowHeight: 60; property int actionButtonWidth: 55; property int locationColumnWidth: 170; From 250e4032b05314dd87899c471050bf2cdc20b275 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 10 Jan 2018 11:51:44 -0800 Subject: [PATCH 07/19] Bug fix to prevent wrists entering the avatar's torso. This was inadvertently disabled in PR #11978. (cherry picked from commit ae997928c138416744129769f9af07a40442696e) --- interface/src/avatar/MySkeletonModel.cpp | 16 ++++++------ libraries/animation/src/Rig.cpp | 31 ++++++++++++------------ libraries/animation/src/Rig.h | 12 ++++++--- 3 files changed, 33 insertions(+), 26 deletions(-) diff --git a/interface/src/avatar/MySkeletonModel.cpp b/interface/src/avatar/MySkeletonModel.cpp index 8d07a878b9..a8bdafb607 100644 --- a/interface/src/avatar/MySkeletonModel.cpp +++ b/interface/src/avatar/MySkeletonModel.cpp @@ -106,7 +106,7 @@ void MySkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { if (avatarHeadPose.isValid()) { AnimPose pose(avatarHeadPose.getRotation(), avatarHeadPose.getTranslation()); params.primaryControllerPoses[Rig::PrimaryControllerType_Head] = avatarToRigPose * pose; - params.primaryControllerActiveFlags[Rig::PrimaryControllerType_Head] = true; + params.primaryControllerFlags[Rig::PrimaryControllerType_Head] = (uint8_t)Rig::ControllerFlags::Enabled; } else { // even though full head IK is disabled, the rig still needs the head orientation to rotate the head up and // down in desktop mode. @@ -114,7 +114,7 @@ void MySkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { // postMult 180 is necessary to convert head from -z forward to z forward. glm::quat headRot = Quaternions::Y_180 * head->getFinalOrientationInLocalFrame() * Quaternions::Y_180; params.primaryControllerPoses[Rig::PrimaryControllerType_Head] = AnimPose(glm::vec3(1.0f), headRot, glm::vec3(0.0f)); - params.primaryControllerActiveFlags[Rig::PrimaryControllerType_Head] = false; + params.primaryControllerFlags[Rig::PrimaryControllerType_Head] = 0; } // @@ -135,10 +135,10 @@ void MySkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { if (controllerPose.isValid()) { AnimPose pose(controllerPose.getRotation(), controllerPose.getTranslation()); params.primaryControllerPoses[pair.second] = avatarToRigPose * pose; - params.primaryControllerActiveFlags[pair.second] = true; + params.primaryControllerFlags[pair.second] = (uint8_t)Rig::ControllerFlags::Enabled; } else { params.primaryControllerPoses[pair.second] = AnimPose::identity; - params.primaryControllerActiveFlags[pair.second] = false; + params.primaryControllerFlags[pair.second] = 0; } } @@ -166,15 +166,15 @@ void MySkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { if (controllerPose.isValid()) { AnimPose pose(controllerPose.getRotation(), controllerPose.getTranslation()); params.secondaryControllerPoses[pair.second] = avatarToRigPose * pose; - params.secondaryControllerActiveFlags[pair.second] = true; + params.secondaryControllerFlags[pair.second] = (uint8_t)Rig::ControllerFlags::Enabled; } else { params.secondaryControllerPoses[pair.second] = AnimPose::identity; - params.secondaryControllerActiveFlags[pair.second] = false; + params.secondaryControllerFlags[pair.second] = 0; } } // if hips are not under direct control, estimate the hips position. - if (avatarHeadPose.isValid() && !params.primaryControllerActiveFlags[Rig::PrimaryControllerType_Hips]) { + if (avatarHeadPose.isValid() && !(params.primaryControllerFlags[Rig::PrimaryControllerType_Hips] & (uint8_t)Rig::ControllerFlags::Enabled)) { bool isFlying = (myAvatar->getCharacterController()->getState() == CharacterController::State::Hover || myAvatar->getCharacterController()->computeCollisionGroup() == BULLET_COLLISION_GROUP_COLLISIONLESS); if (!_prevHipsValid) { @@ -200,7 +200,7 @@ void MySkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { AnimPose sensorToRigPose(invRigMat * myAvatar->getSensorToWorldMatrix()); params.primaryControllerPoses[Rig::PrimaryControllerType_Hips] = sensorToRigPose * hips; - params.primaryControllerActiveFlags[Rig::PrimaryControllerType_Hips] = true; + params.primaryControllerFlags[Rig::PrimaryControllerType_Hips] = (uint8_t)Rig::ControllerFlags::Enabled | (uint8_t)Rig::ControllerFlags::Estimated; } else { _prevHipsValid = false; diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 44745c5c2d..27ba7a38a4 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -1265,7 +1265,8 @@ glm::vec3 Rig::deflectHandFromTorso(const glm::vec3& handPosition, const FBXJoin return position; } -void Rig::updateHands(bool leftHandEnabled, bool rightHandEnabled, bool hipsEnabled, bool leftArmEnabled, bool rightArmEnabled, float dt, +void Rig::updateHands(bool leftHandEnabled, bool rightHandEnabled, bool hipsEnabled, bool hipsEstimated, + bool leftArmEnabled, bool rightArmEnabled, float dt, const AnimPose& leftHandPose, const AnimPose& rightHandPose, const FBXJointShapeInfo& hipsShapeInfo, const FBXJointShapeInfo& spineShapeInfo, const FBXJointShapeInfo& spine1ShapeInfo, const FBXJointShapeInfo& spine2ShapeInfo) { @@ -1279,7 +1280,7 @@ void Rig::updateHands(bool leftHandEnabled, bool rightHandEnabled, bool hipsEnab glm::vec3 handPosition = leftHandPose.trans(); glm::quat handRotation = leftHandPose.rot(); - if (!hipsEnabled) { + if (!hipsEnabled || hipsEstimated) { // prevent the hand IK targets from intersecting the torso handPosition = deflectHandFromTorso(handPosition, hipsShapeInfo, spineShapeInfo, spine1ShapeInfo, spine2ShapeInfo); } @@ -1326,7 +1327,7 @@ void Rig::updateHands(bool leftHandEnabled, bool rightHandEnabled, bool hipsEnab glm::vec3 handPosition = rightHandPose.trans(); glm::quat handRotation = rightHandPose.rot(); - if (!hipsEnabled) { + if (!hipsEnabled || hipsEstimated) { // prevent the hand IK targets from intersecting the torso handPosition = deflectHandFromTorso(handPosition, hipsShapeInfo, spineShapeInfo, spine1ShapeInfo, spine2ShapeInfo); } @@ -1550,20 +1551,20 @@ void Rig::updateFromControllerParameters(const ControllerParameters& params, flo _animVars.set("isTalking", params.isTalking); _animVars.set("notIsTalking", !params.isTalking); - bool headEnabled = params.primaryControllerActiveFlags[PrimaryControllerType_Head]; - bool leftHandEnabled = params.primaryControllerActiveFlags[PrimaryControllerType_LeftHand]; - bool rightHandEnabled = params.primaryControllerActiveFlags[PrimaryControllerType_RightHand]; - bool hipsEnabled = params.primaryControllerActiveFlags[PrimaryControllerType_Hips]; - bool leftFootEnabled = params.primaryControllerActiveFlags[PrimaryControllerType_LeftFoot]; - bool rightFootEnabled = params.primaryControllerActiveFlags[PrimaryControllerType_RightFoot]; - bool spine2Enabled = params.primaryControllerActiveFlags[PrimaryControllerType_Spine2]; - - bool leftArmEnabled = params.secondaryControllerActiveFlags[SecondaryControllerType_LeftArm]; - bool rightArmEnabled = params.secondaryControllerActiveFlags[SecondaryControllerType_RightArm]; + bool headEnabled = params.primaryControllerFlags[PrimaryControllerType_Head] & (uint8_t)ControllerFlags::Enabled; + bool leftHandEnabled = params.primaryControllerFlags[PrimaryControllerType_LeftHand] & (uint8_t)ControllerFlags::Enabled; + bool rightHandEnabled = params.primaryControllerFlags[PrimaryControllerType_RightHand] & (uint8_t)ControllerFlags::Enabled; + bool hipsEnabled = params.primaryControllerFlags[PrimaryControllerType_Hips] & (uint8_t)ControllerFlags::Enabled; + bool hipsEstimated = params.primaryControllerFlags[PrimaryControllerType_Hips] & (uint8_t)ControllerFlags::Estimated; + bool leftFootEnabled = params.primaryControllerFlags[PrimaryControllerType_LeftFoot] & (uint8_t)ControllerFlags::Enabled; + bool rightFootEnabled = params.primaryControllerFlags[PrimaryControllerType_RightFoot] & (uint8_t)ControllerFlags::Enabled; + bool spine2Enabled = params.primaryControllerFlags[PrimaryControllerType_Spine2] & (uint8_t)ControllerFlags::Enabled; + bool leftArmEnabled = params.secondaryControllerFlags[SecondaryControllerType_LeftArm] & (uint8_t)ControllerFlags::Enabled; + bool rightArmEnabled = params.secondaryControllerFlags[SecondaryControllerType_RightArm] & (uint8_t)ControllerFlags::Enabled; updateHead(headEnabled, hipsEnabled, params.primaryControllerPoses[PrimaryControllerType_Head]); - updateHands(leftHandEnabled, rightHandEnabled, hipsEnabled, leftArmEnabled, rightArmEnabled, dt, + updateHands(leftHandEnabled, rightHandEnabled, hipsEnabled, hipsEstimated, leftArmEnabled, rightArmEnabled, dt, params.primaryControllerPoses[PrimaryControllerType_LeftHand], params.primaryControllerPoses[PrimaryControllerType_RightHand], params.hipsShapeInfo, params.spineShapeInfo, params.spine1ShapeInfo, params.spine2ShapeInfo); @@ -1623,7 +1624,7 @@ void Rig::updateFromControllerParameters(const ControllerParameters& params, flo for (int i = 0; i < (int)NumSecondaryControllerTypes; i++) { int index = indexOfJoint(secondaryControllerJointNames[i]); if (index >= 0) { - if (params.secondaryControllerActiveFlags[i]) { + if (params.secondaryControllerFlags[i] & (uint8_t)ControllerFlags::Enabled) { ikNode->setSecondaryTargetInRigFrame(index, params.secondaryControllerPoses[i]); } else { ikNode->clearSecondaryTarget(index); diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index 1ec4d9527f..2b276386a0 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -69,11 +69,16 @@ public: NumSecondaryControllerTypes }; + enum class ControllerFlags : uint8_t { + Enabled = 0x01, + Estimated = 0x02 + }; + struct ControllerParameters { AnimPose primaryControllerPoses[NumPrimaryControllerTypes]; // rig space - bool primaryControllerActiveFlags[NumPrimaryControllerTypes]; + uint8_t primaryControllerFlags[NumPrimaryControllerTypes]; AnimPose secondaryControllerPoses[NumSecondaryControllerTypes]; // rig space - bool secondaryControllerActiveFlags[NumSecondaryControllerTypes]; + uint8_t secondaryControllerFlags[NumSecondaryControllerTypes]; bool isTalking; FBXJointShapeInfo hipsShapeInfo; FBXJointShapeInfo spineShapeInfo; @@ -251,7 +256,8 @@ protected: void buildAbsoluteRigPoses(const AnimPoseVec& relativePoses, AnimPoseVec& absolutePosesOut); void updateHead(bool headEnabled, bool hipsEnabled, const AnimPose& headMatrix); - void updateHands(bool leftHandEnabled, bool rightHandEnabled, bool hipsEnabled, bool leftArmEnabled, bool rightArmEnabled, float dt, + void updateHands(bool leftHandEnabled, bool rightHandEnabled, bool hipsEnabled, bool hipsEstimated, + bool leftArmEnabled, bool rightArmEnabled, float dt, const AnimPose& leftHandPose, const AnimPose& rightHandPose, const FBXJointShapeInfo& hipsShapeInfo, const FBXJointShapeInfo& spineShapeInfo, const FBXJointShapeInfo& spine1ShapeInfo, const FBXJointShapeInfo& spine2ShapeInfo); From 6072780d243b7e3d1e74dd77bda260a980642f78 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 10 Jan 2018 13:19:53 -0800 Subject: [PATCH 08/19] keep requesting render update until textures load (cherry picked from commit df574c6bc94e5438a064c6420e9a108be011a12a) --- libraries/entities-renderer/src/RenderableModelEntityItem.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index c756070bc3..0c1721ae44 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -1080,7 +1080,7 @@ bool ModelEntityRenderer::needsRenderUpdate() const { return true; } - if (!_texturesLoaded && model->getGeometry() && model->getGeometry()->areTexturesLoaded()) { + if (!_texturesLoaded) { return true; } @@ -1310,6 +1310,8 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce if (!_texturesLoaded && model->getGeometry() && model->getGeometry()->areTexturesLoaded()) { _texturesLoaded = true; model->updateRenderItems(); + } else if (!_texturesLoaded) { + emit requestRenderUpdate(); } // When the individual mesh parts of a model finish fading, they will mark their Model as needing updating From d5e3b97c934bdd1435d60373e0f7aa60659e12c6 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 10 Jan 2018 16:03:53 -0800 Subject: [PATCH 09/19] Fix for black screen when clicking Settings from Snap app --- interface/resources/qml/hifi/tablet/TabletRoot.qml | 2 +- scripts/system/snapshot.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/hifi/tablet/TabletRoot.qml b/interface/resources/qml/hifi/tablet/TabletRoot.qml index da544c2114..e7614e11b7 100644 --- a/interface/resources/qml/hifi/tablet/TabletRoot.qml +++ b/interface/resources/qml/hifi/tablet/TabletRoot.qml @@ -106,7 +106,7 @@ Item { if (isWebPage) { var webUrl = tabletApps.get(currentApp).appWebUrl; var scriptUrl = tabletApps.get(currentApp).scriptUrl; - loadSource("TabletWebView.qml"); + loadSource("hifi/tablet/TabletWebView.qml"); loadWebUrl(webUrl, scriptUrl); } else { loader.load(tabletApps.get(currentApp).appUrl); diff --git a/scripts/system/snapshot.js b/scripts/system/snapshot.js index 9afdb4ec53..dad642075f 100644 --- a/scripts/system/snapshot.js +++ b/scripts/system/snapshot.js @@ -121,7 +121,7 @@ function onMessage(message) { || (!HMD.active && Settings.getValue("desktopTabletBecomesToolbar", true))) { Desktop.show("hifi/dialogs/GeneralPreferencesDialog.qml", "GeneralPreferencesDialog"); } else { - tablet.loadQMLOnTop("TabletGeneralPreferences.qml"); + tablet.loadQMLOnTop("hifi/tablet/TabletGeneralPreferences.qml"); } break; case 'captureStillAndGif': From 753bd21e68af97cd5c936f3fba54c9f2710fc65f Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 11 Jan 2018 13:44:16 +1300 Subject: [PATCH 10/19] location API JSDoc --- libraries/networking/src/AddressManager.h | 287 +++++++++++++++++++++- 1 file changed, 286 insertions(+), 1 deletion(-) diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h index 2f3d896509..cf9d8a085b 100644 --- a/libraries/networking/src/AddressManager.h +++ b/libraries/networking/src/AddressManager.h @@ -31,6 +31,31 @@ const QString INDEX_PATH = "/"; const QString GET_PLACE = "/api/v1/places/%1"; +/**jsdoc + * The location API provides facilities related to your current location in the metaverse. + * + * @namespace location + * @property {Uuid} domainId - A UUID uniquely identifying the domain you're visiting. Is {@link Uuid|Uuid.NULL} if you're not + * connected to the domain. + * Read-only. + * @property {string} hostname - The name of the domain for your current metaverse address (e.g., "AvatarIsland", + * localhost, or an IP address. + * Read-only. + * @property {string} href - Your current metaverse address (e.g., "hifi://avatarisland/15,-10,26/0,0,0,1") + * regardless of whether or not you're connected to the domain. + * Read-only. + * @property {boolean} isConnected - true if you're connected to a domain, otherwise false. + * Read-only. + * @property {string} pathname - The location and orientation in your current href metaverse address + * (e.g., "/15,-10,26/0,0,0,1"). + * Read-only. + * @property {string} placename - The name of the place in your current href metaverse address + * (e.g., "AvatarIsland"). Is blank if your hostname is an IP address. + * Read-only. + * @property {string} protocol - The protocol of your current href metaverse address (e.g., "hifi"). + * Read-only. + */ + class AddressManager : public QObject, public Dependency { Q_OBJECT SINGLETON_DEPENDENCY @@ -42,10 +67,77 @@ class AddressManager : public QObject, public Dependency { Q_PROPERTY(QString placename READ getPlaceName) Q_PROPERTY(QString domainId READ getDomainId) public: + + /**jsdoc + * Get Interface's protocol version. + * @function location.protocolVersion + * @returns {string} A string uniquely identifying the version of the metaverse protocol that Interface is using. + */ Q_INVOKABLE QString protocolVersion(); + using PositionGetter = std::function; using OrientationGetter = std::function; + /**jsdoc + *

The reasons for an address lookup via the metaverse API are defined by numeric values:

+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
NameValueDescription
UserInput0User-typed input.
Back1Address from a {@link location.goBack|goBack} call.
Forward2Address from a {@link location.goForward|goForward} call.
StartupFromSettings3Initial location at Interface start-up from settings.
DomainPathResponse4A named path in the domain.
Internal5An internal attempt to resolve an alternative path.
AttemptedRefresh6A refresh after connecting to a domain.
Suggestions7Address from the Goto dialog.
VisitUserFromPAL8User from the People dialog.
+ * @typedef location.LookupTrigger + */ enum LookupTrigger { UserInput, Back, @@ -83,43 +175,236 @@ public: const QStack& getForwardStack() const { return _forwardStack; } public slots: + /**jsdoc + * Go to a specified metaverse address. + * @function location.handleLookupString + * @param {string} address - The address to go to: a "hifi:/" address, an IP address (e.g., + * "127.0.0.1" or "localhost"), a domain name, a named path on a domain (starts with + * "/"), a position or position and orientation, or a user (starts with "@"). + * @param {boolean} fromSuggestions=false - Set to true if the address is obtained from the "Goto" dialog. + */ void handleLookupString(const QString& lookupString, bool fromSuggestions = false); - + + /**jsdoc + * Go to a position and orientation resulting from a lookup for a named path in the domain (set in the domain server's + * settings). + * @function location.goToViewpointForPath + * @param {string} path - The position and orientation corresponding to the named path. + * @param {string} namedPath - The named path that was looked up on the server. + * @deprecated This function is deprecated and will be removed. + */ + // This function is marked as deprecated in anticipation that it will not be included in the JavaScript API if and when the + // functions and signals that should be exposed are moved to a scripting interface class. + // // we currently expect this to be called from NodeList once handleLookupString has been called with a path bool goToViewpointForPath(const QString& viewpointString, const QString& pathString) { return handleViewpoint(viewpointString, false, DomainPathResponse, false, pathString); } + /**jsdoc + * Go back to the previous location in your navigation history, if there is one. + * @function location.goBack + */ void goBack(); + + /**jsdoc + * Go forward to the next location in your navigation history, if there is one. + * @function location.goForward + */ void goForward(); + + /**jsdoc + * Go to the local Sandbox server that's running on the same PC as Interface. + * @function location.goToLocalSandbox + * @param {string} path="" - The position and orientation to go to (e.g., "/0,0,0"). + * @param {location.LookupTrigger} trigger=StartupFromSettings - The reason for the function call. + */ void goToLocalSandbox(QString path = "", LookupTrigger trigger = LookupTrigger::StartupFromSettings) { handleUrl(SANDBOX_HIFI_ADDRESS + path, trigger); } + + /**jsdoc + * Go to the default metaverse address. + * @function location.goToEntry + * @param {location.LookupTrigger} trigger=StartupFromSettings - The reason for the function call. + */ void goToEntry(LookupTrigger trigger = LookupTrigger::StartupFromSettings) { handleUrl(DEFAULT_HIFI_ADDRESS, trigger); } + /**jsdoc + * Go to the specified user's location. + * @function location.goToUser + * @param {string} username - The user's user name. + * @param {boolean} matchOrientation=true - If true then go to a location just in front of the user and turn to face + * them, otherwise go to the user's exact location and orientation. + */ void goToUser(const QString& username, bool shouldMatchOrientation = true); + /**jsdoc + * Refresh the current address, e.g., after connecting to a domain ion order to position the user to the desired location. + * @function location.refreshPreviousLookup + * @deprecated This function is deprecated and will be removed. + */ + // This function is marked as deprecated in anticipation that it will not be included in the JavaScript API if and when the + // functions and signals that should be exposed are moved to a scripting interface class. void refreshPreviousLookup(); + /**jsdoc + * Save your current metaverse location in Interface's settings file. + * @function location.storeCurrentAddress + */ void storeCurrentAddress(); + /**jsdoc + * Copy your current metaverse address (i.e., location.href property value) to the OS clipboard. + * @function location.copyAddress + */ void copyAddress(); + + /**jsdoc + * Copy your current metaverse location and orientation (i.e., location.pathname property value) to the OS + * clipboard. + * @function location.copyPath + */ void copyPath(); + /**jsdoc + * Retrieve and remember the place name for the given domain ID if the place name is not already known. + * @function location.lookupShareableNameForDomainID + * @param {Uuid} domainID - The UUID of the domain. + * @deprecated This function is deprecated and will be removed. + */ + // This function is marked as deprecated in anticipation that it will not be included in the JavaScript API if and when the + // functions and signals that should be exposed are moved to a scripting interface class. void lookupShareableNameForDomainID(const QUuid& domainID); signals: + /**jsdoc + * Triggered when looking up the details of a metaverse user or location to go to has completed (successfully or + * unsuccessfully). + * @function location.lookupResultsFinished + * @returns {Signal} + */ void lookupResultsFinished(); + + /**jsdoc + * Triggered when looking up the details of a metaverse user or location to go to has completed and the domain or user is + * offline. + * @function location.lookupResultIsOffline + * @returns {Signal} + */ void lookupResultIsOffline(); + + /**jsdoc + * Triggered when looking up the details of a metaverse user or location to go to has completed and the domain or user could + * not be found (i.e., is unknown). + * @function location.lookupResultIsNotFound + * @returns {Signal} + */ void lookupResultIsNotFound(); + /**jsdoc + * Triggered when a request is made to go to an IP address. + * @function location.possibleDomainChangeRequired + * @param {string} hostName - The name of the domain to go do. + * @param {number} port - The integer number of the network port to connect to. + * @param {Uuid} domainID - The UUID of the domain to go to. + * @returns {Signal} + */ + // No example because this function isn't typically used in scripts. void possibleDomainChangeRequired(const QString& newHostname, quint16 newPort, const QUuid& domainID); + + /**jsdoc + * Triggered when a request is made to go to a domain. + * @function location.possibleDomainChangeRequiredViaICEForID + * @param {string} iceServerHostName - IP address of the ICE server. + * @param {Uuid} domainID - The UUID of the domain to go to. + * @returns {Signal} + */ + // No example because this function isn't typically used in scripts. void possibleDomainChangeRequiredViaICEForID(const QString& iceServerHostname, const QUuid& domainID); + /**jsdoc + * Triggered when an attempt is made to send your avatar to a specified position on the current domain. For example, when + * you enter a position to go to in the "Goto" dialog or change domains. + * @function location.locationChangeRequired + * @param {Vec3} position - The position to go to. + * @param {boolean} hasOrientationChange - If true then a new orientation has been requested. + * @param {Quat} orientation - The orientation to change to. Is {@link Quat(0)|Quat.IDENTITY} if + * hasOrientationChange is false. + * @param {boolean} shouldFaceLocation - If true then the request is to go to a position near that specified + * and orient your avatar to face it. For example when you visit someone from the "People" dialog. + * @returns {Signal} + * @example Report location change requests. + * function onLocationChangeRequired(newPosition, hasOrientationChange, newOrientation, shouldFaceLocation) { + * print("Location change required:"); + * print("- New position = " + JSON.stringify(newPosition)); + * print("- Has orientation change = " + hasOrientationChange); + * print("- New orientation = " + JSON.stringify(newOrientation)); + * print("- Should face location = " + shouldFaceLocation); + * } + * + * location.locationChangeRequired.connect(onLocationChangeRequired); + */ void locationChangeRequired(const glm::vec3& newPosition, bool hasOrientationChange, const glm::quat& newOrientation, bool shouldFaceLocation); + + /**jsdoc + * Triggered when an attempt is made to send your avatar goes to a new named path on the domain (set in the domain server's + * settings). For example, when you enter a "/" followed by the path's name in the "GOTO" dialog. + * @function location.pathChangeRequired + * @param {string} path - The name of the path to go to. + * @returns {Signal} + * @example Report path change requests. + * function onPathChangeRequired(newPath) { + * print("onPathChangeRequired: newPath = " + newPath); + * } + * + * location.pathChangeRequired.connect(onPathChangeRequired); + */ void pathChangeRequired(const QString& newPath); + + /**jsdoc + * Triggered when you navigated to a new domain. + * @function location.hostChanged + * @param {string} hostname - The new domain's host name. + * @returns {Signal} + * @example Report when you navigate to a new domain. + * function onHostChanged(host) { + * print("Host changed to: " + host); + * } + * + * location.hostChanged.connect(onHostChanged); + */ void hostChanged(const QString& newHost); + /**jsdoc + * Triggered when whether or not there's a previous location to navigate to changes. (Reflects changes in the state of the + * "Goto" dialog's back arrow.) + * @function location.goBackPossible + * @param {boolean} isPossible - true if there's a previous location to navigate to, otherwise + * false. + * @returns {Signal} + * @example Report when ability to navigate back changes. + * function onGoBackPossible(isPossible) { + * print("Go back possible: " + isPossible); + * } + * + * location.goBackPossible.connect(onGoBackPossible); + */ void goBackPossible(bool isPossible); + + /**jsdoc + * Triggered when whether or not there's a forward location to navigate to changes. (Reflects changes in the state of the + * "Goto" dialog's forward arrow.) + * @function location.goForwardPossible + * @param {boolean} isPossible - true if there's a forward location to navigate to, otherwise + * false. + * @returns {Signal} + * @example Report when ability to navigate forward changes. + * function onGoForwardPossible(isPossible) { + * print("Go forward possible: " + isPossible); + * } + * + * location.goForwardPossible.connect(onGoForwardPossible); + */ void goForwardPossible(bool isPossible); protected: From 309e7f7333dd524e8cc650697b185dcebb2bea0b Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 11 Jan 2018 14:48:45 +1300 Subject: [PATCH 11/19] Tidying --- libraries/networking/src/AddressManager.h | 27 ++++++++++++----------- libraries/networking/src/NodeList.cpp | 2 +- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h index cf9d8a085b..2c342a1b93 100644 --- a/libraries/networking/src/AddressManager.h +++ b/libraries/networking/src/AddressManager.h @@ -39,17 +39,18 @@ const QString GET_PLACE = "/api/v1/places/%1"; * connected to the domain. * Read-only. * @property {string} hostname - The name of the domain for your current metaverse address (e.g., "AvatarIsland", - * localhost, or an IP address. + * localhost, or an IP address). * Read-only. * @property {string} href - Your current metaverse address (e.g., "hifi://avatarisland/15,-10,26/0,0,0,1") * regardless of whether or not you're connected to the domain. * Read-only. - * @property {boolean} isConnected - true if you're connected to a domain, otherwise false. + * @property {boolean} isConnected - true if you're connected to the domain in your current href + * metaverse address, otherwise false. * Read-only. * @property {string} pathname - The location and orientation in your current href metaverse address * (e.g., "/15,-10,26/0,0,0,1"). * Read-only. - * @property {string} placename - The name of the place in your current href metaverse address + * @property {string} placename - The place name in your current href metaverse address * (e.g., "AvatarIsland"). Is blank if your hostname is an IP address. * Read-only. * @property {string} protocol - The protocol of your current href metaverse address (e.g., "hifi"). @@ -230,7 +231,7 @@ public slots: /**jsdoc * Go to the specified user's location. * @function location.goToUser - * @param {string} username - The user's user name. + * @param {string} username - The user's username. * @param {boolean} matchOrientation=true - If true then go to a location just in front of the user and turn to face * them, otherwise go to the user's exact location and orientation. */ @@ -293,7 +294,7 @@ signals: /**jsdoc * Triggered when looking up the details of a metaverse user or location to go to has completed and the domain or user could - * not be found (i.e., is unknown). + * not be found. * @function location.lookupResultIsNotFound * @returns {Signal} */ @@ -311,7 +312,7 @@ signals: void possibleDomainChangeRequired(const QString& newHostname, quint16 newPort, const QUuid& domainID); /**jsdoc - * Triggered when a request is made to go to a domain. + * Triggered when a request is made to go to a named domain or user. * @function location.possibleDomainChangeRequiredViaICEForID * @param {string} iceServerHostName - IP address of the ICE server. * @param {Uuid} domainID - The UUID of the domain to go to. @@ -322,7 +323,7 @@ signals: /**jsdoc * Triggered when an attempt is made to send your avatar to a specified position on the current domain. For example, when - * you enter a position to go to in the "Goto" dialog or change domains. + * you change domains or enter a position to go to in the "Goto" dialog. * @function location.locationChangeRequired * @param {Vec3} position - The position to go to. * @param {boolean} hasOrientationChange - If true then a new orientation has been requested. @@ -347,7 +348,7 @@ signals: bool shouldFaceLocation); /**jsdoc - * Triggered when an attempt is made to send your avatar goes to a new named path on the domain (set in the domain server's + * Triggered when an attempt is made to send your avatar to a new named path on the domain (set in the domain server's * settings). For example, when you enter a "/" followed by the path's name in the "GOTO" dialog. * @function location.pathChangeRequired * @param {string} path - The name of the path to go to. @@ -362,7 +363,7 @@ signals: void pathChangeRequired(const QString& newPath); /**jsdoc - * Triggered when you navigated to a new domain. + * Triggered when you navigate to a new domain. * @function location.hostChanged * @param {string} hostname - The new domain's host name. * @returns {Signal} @@ -376,8 +377,8 @@ signals: void hostChanged(const QString& newHost); /**jsdoc - * Triggered when whether or not there's a previous location to navigate to changes. (Reflects changes in the state of the - * "Goto" dialog's back arrow.) + * Triggered when there's a change in whether or not there's a previous location that can be navigated to using + * {@link location.goBack|goBack}. (Reflects changes in the state of the "Goto" dialog's back arrow.) * @function location.goBackPossible * @param {boolean} isPossible - true if there's a previous location to navigate to, otherwise * false. @@ -392,8 +393,8 @@ signals: void goBackPossible(bool isPossible); /**jsdoc - * Triggered when whether or not there's a forward location to navigate to changes. (Reflects changes in the state of the - * "Goto" dialog's forward arrow.) + * Triggered when there's a change in whether or not there's a forward location that can be navigated to using + * {@link location.goForward|goForward}. (Reflects changes in the state of the "Goto" dialog's forward arrow.) * @function location.goForwardPossible * @param {boolean} isPossible - true if there's a forward location to navigate to, otherwise * false. diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index 5a72006a8c..1c18125433 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -437,7 +437,7 @@ void NodeList::sendPendingDSPathQuery() { QString pendingPath = _domainHandler.getPendingPath(); if (!pendingPath.isEmpty()) { - qCDebug(networking) << "Attemping to send pending query to DS for path" << pendingPath; + qCDebug(networking) << "Attempting to send pending query to DS for path" << pendingPath; // this is a slot triggered if we just established a network link with a DS and want to send a path query sendDSPathQuery(_domainHandler.getPendingPath()); From a3ca8e3a72d5c552e85681533e41d15380d24018 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 10 Jan 2018 17:01:01 -0800 Subject: [PATCH 12/19] try to avoid reusing uniform buffer locations (cherry picked from commit e9d751fd23f85b980aa47faf702b89292c01e20d) --- .../src/RenderableParticleEffectEntityItem.cpp | 7 ++++++- .../src/RenderablePolyLineEntityItem.cpp | 5 +++-- libraries/render-utils/src/LightClusters.cpp | 13 ++++++------- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index bc96e45881..a3e6cd4341 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -23,6 +23,8 @@ using namespace render::entities; static uint8_t CUSTOM_PIPELINE_NUMBER = 0; static gpu::Stream::FormatPointer _vertexFormat; static std::weak_ptr _texturedPipeline; +// FIXME: This is interfering with the uniform buffers in DeferredLightingEffect.cpp, so use 11 to avoid collisions +static int32_t PARTICLE_UNIFORM_SLOT { 11 }; static ShapePipelinePointer shapePipelineFactory(const ShapePlumber& plumber, const ShapeKey& key) { auto texturedPipeline = _texturedPipeline.lock(); @@ -38,6 +40,9 @@ static ShapePipelinePointer shapePipelineFactory(const ShapePlumber& plumber, co auto fragShader = gpu::Shader::createPixel(std::string(textured_particle_frag)); auto program = gpu::Shader::createProgram(vertShader, fragShader); + gpu::Shader::BindingSet slotBindings; + slotBindings.insert(gpu::Shader::Binding(std::string("particleBuffer"), PARTICLE_UNIFORM_SLOT)); + gpu::Shader::makeProgram(*program, slotBindings); _texturedPipeline = texturedPipeline = gpu::Pipeline::create(program, state); } @@ -320,7 +325,7 @@ void ParticleEffectEntityRenderer::doRender(RenderArgs* args) { transform.setScale(vec3(1)); } batch.setModelTransform(transform); - batch.setUniformBuffer(0, _uniformBuffer); + batch.setUniformBuffer(PARTICLE_UNIFORM_SLOT, _uniformBuffer); batch.setInputFormat(_vertexFormat); batch.setInputBuffer(0, _particleBuffer, 0, sizeof(GpuParticle)); diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp index 21764dff7f..b362721cde 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp @@ -33,8 +33,9 @@ using namespace render; using namespace render::entities; static uint8_t CUSTOM_PIPELINE_NUMBER { 0 }; -static const int32_t PAINTSTROKE_TEXTURE_SLOT{ 0 }; -static const int32_t PAINTSTROKE_UNIFORM_SLOT{ 0 }; +static const int32_t PAINTSTROKE_TEXTURE_SLOT { 0 }; +// FIXME: This is interfering with the uniform buffers in DeferredLightingEffect.cpp, so use 11 to avoid collisions +static const int32_t PAINTSTROKE_UNIFORM_SLOT { 11 }; static gpu::Stream::FormatPointer polylineFormat; static gpu::PipelinePointer polylinePipeline; #ifdef POLYLINE_ENTITY_USE_FADE_EFFECT diff --git a/libraries/render-utils/src/LightClusters.cpp b/libraries/render-utils/src/LightClusters.cpp index eedb9053c7..d6ac7fd2e2 100644 --- a/libraries/render-utils/src/LightClusters.cpp +++ b/libraries/render-utils/src/LightClusters.cpp @@ -37,14 +37,13 @@ enum LightClusterGridShader_MapSlot { }; enum LightClusterGridShader_BufferSlot { - LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT = 0, - DEFERRED_FRAME_TRANSFORM_BUFFER_SLOT =1, - CAMERA_CORRECTION_BUFFER_SLOT = 2, + DEFERRED_FRAME_TRANSFORM_BUFFER_SLOT = 0, + CAMERA_CORRECTION_BUFFER_SLOT = 1, LIGHT_GPU_SLOT = render::ShapePipeline::Slot::LIGHT, - LIGHT_INDEX_GPU_SLOT = 5, - - LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT = 6, - LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_SLOT = 7, + LIGHT_INDEX_GPU_SLOT = 7, + LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT = 8, + LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT = 9, + LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_SLOT = 10, }; FrustumGrid::FrustumGrid(const FrustumGrid& source) : From 54a1da8d73a3179e696590b9c90c0df187d9a671 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Thu, 11 Jan 2018 11:55:28 -0700 Subject: [PATCH 13/19] Only mod my card --- interface/resources/qml/hifi/NameCard.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/NameCard.qml b/interface/resources/qml/hifi/NameCard.qml index 9993d1f2b6..e08fdc53ff 100644 --- a/interface/resources/qml/hifi/NameCard.qml +++ b/interface/resources/qml/hifi/NameCard.qml @@ -520,7 +520,7 @@ Item { Slider { id: gainSlider // Size - width: thisNameCard.width - 20; + width: isMyCard ? thisNameCard.width - 20 : thisNameCard.width; height: 14 // Anchors anchors.verticalCenter: nameCardVUMeter.verticalCenter; From e627925bd3fa4f42e0fc3cc2908ef1ed6eb7af8d Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 12 Jan 2018 13:31:58 -0800 Subject: [PATCH 14/19] Fix 'Browse Avatars' button from Avatar Settings --- .../qml/dialogs/preferences/AvatarBrowser.qml | 85 -------------- .../dialogs/preferences/AvatarPreference.qml | 18 +-- .../preferences/TabletAvatarBrowser.qml | 111 ------------------ interface/src/Application.cpp | 9 ++ interface/src/Application.h | 1 + 5 files changed, 11 insertions(+), 213 deletions(-) delete mode 100644 interface/resources/qml/dialogs/preferences/AvatarBrowser.qml delete mode 100644 interface/resources/qml/hifi/tablet/tabletWindows/preferences/TabletAvatarBrowser.qml diff --git a/interface/resources/qml/dialogs/preferences/AvatarBrowser.qml b/interface/resources/qml/dialogs/preferences/AvatarBrowser.qml deleted file mode 100644 index 5949adffca..0000000000 --- a/interface/resources/qml/dialogs/preferences/AvatarBrowser.qml +++ /dev/null @@ -1,85 +0,0 @@ -// -// AvatarBrowser.qml -// -// Created by Bradley Austin Davis on 30 Aug 2015 -// Copyright 2015 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -import QtQuick 2.5 -import QtQuick.Controls 1.4 -import QtWebChannel 1.0 -import QtWebEngine 1.2 - -import "../../windows" -import "../../controls-uit" -import "../../styles-uit" - -Window { - id: root - HifiConstants { id: hifi } - width: 900; height: 700 - resizable: true - modality: Qt.ApplicationModal - - Item { - anchors.fill: parent - - property bool keyboardEnabled: false - property bool keyboardRaised: true - property bool punctuationMode: false - - BaseWebView { - id: webview - url: Account.metaverseServerURL + "/marketplace?category=avatars" - focus: true - - anchors { - top: parent.top - left: parent.left - right: parent.right - bottom: keyboard.top - } - - // Create a global EventBridge object for raiseAndLowerKeyboard. - WebEngineScript { - id: createGlobalEventBridge - sourceCode: eventBridgeJavaScriptToInject - injectionPoint: WebEngineScript.DocumentCreation - worldId: WebEngineScript.MainWorld - } - - // Detect when may want to raise and lower keyboard. - WebEngineScript { - id: raiseAndLowerKeyboard - injectionPoint: WebEngineScript.Deferred - sourceUrl: resourceDirectoryUrl + "html/raiseAndLowerKeyboard.js" - worldId: WebEngineScript.MainWorld - } - - userScripts: [ createGlobalEventBridge, raiseAndLowerKeyboard ] - - Component.onCompleted: { - webChannel.registerObject("eventBridge", eventBridge); - webChannel.registerObject("eventBridgeWrapper", eventBridgeWrapper); - } - } - - Keyboard { - id: keyboard - raised: parent.keyboardEnabled && parent.keyboardRaised - numeric: parent.punctuationMode - anchors { - left: parent.left - right: parent.right - bottom: parent.bottom - } - } - - Component.onCompleted: { - keyboardEnabled = HMD.active; - } - } -} diff --git a/interface/resources/qml/dialogs/preferences/AvatarPreference.qml b/interface/resources/qml/dialogs/preferences/AvatarPreference.qml index b27827d9d7..0efc3776b3 100644 --- a/interface/resources/qml/dialogs/preferences/AvatarPreference.qml +++ b/interface/resources/qml/dialogs/preferences/AvatarPreference.qml @@ -99,25 +99,9 @@ Preference { leftMargin: dataTextField.acceptableInput ? hifi.dimensions.contentSpacing.x : 0 } onClicked: { - if (typeof desktop !== "undefined") { - // Load dialog via OffscreenUi so that JavaScript EventBridge is available. - root.browser = OffscreenUi.load("dialogs/preferences/AvatarBrowser.qml"); - root.browser.windowDestroyed.connect(function(){ - root.browser = null; - }); - } else { - root.browser = tabletAvatarBrowserBuilder.createObject(tabletRoot); - - // Make dialog modal. - tabletRoot.openModal = root.browser; - } + ApplicationInterface.loadAvatarBrowser(); } } - Component { - id: tabletAvatarBrowserBuilder; - TabletAvatarBrowser { } - } - } } diff --git a/interface/resources/qml/hifi/tablet/tabletWindows/preferences/TabletAvatarBrowser.qml b/interface/resources/qml/hifi/tablet/tabletWindows/preferences/TabletAvatarBrowser.qml deleted file mode 100644 index 2ea12f1d3d..0000000000 --- a/interface/resources/qml/hifi/tablet/tabletWindows/preferences/TabletAvatarBrowser.qml +++ /dev/null @@ -1,111 +0,0 @@ -// -// TabletAvatarBrowser.qml -// -// Created by David Rowe on 14 Mar 2017 -// Copyright 2017 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -import QtQuick 2.5 -import QtQuick.Controls 1.4 -import QtWebChannel 1.0 -import QtWebEngine 1.2 - -import "../../../../windows" -import "../../../../controls-uit" -import "../../../../styles-uit" - -Item { - id: root - objectName: "ModelBrowserDialog" - - property string title: "Attachment Model" - - property bool keyboardEnabled: false - property bool keyboardRaised: false - property bool punctuationMode: false - - anchors.fill: parent - - BaseWebView { - id: webview - url: (Account.metaverseServerURL + "/marketplace?category=avatars") - focus: true - - anchors { - top: parent.top - left: parent.left - right: parent.right - bottom: footer.top - } - - // Create a global EventBridge object for raiseAndLowerKeyboard. - WebEngineScript { - id: createGlobalEventBridge - sourceCode: eventBridgeJavaScriptToInject - injectionPoint: WebEngineScript.DocumentCreation - worldId: WebEngineScript.MainWorld - } - - // Detect when may want to raise and lower keyboard. - WebEngineScript { - id: raiseAndLowerKeyboard - injectionPoint: WebEngineScript.Deferred - sourceUrl: resourceDirectoryUrl + "html/raiseAndLowerKeyboard.js" - worldId: WebEngineScript.MainWorld - } - - userScripts: [ createGlobalEventBridge, raiseAndLowerKeyboard ] - - Component.onCompleted: { - webChannel.registerObject("eventBridge", eventBridge); - webChannel.registerObject("eventBridgeWrapper", eventBridgeWrapper); - } - } - - Rectangle { - id: footer - height: 40 - - anchors { - left: parent.left - right: parent.right - bottom: keyboard.top - } - - color: hifi.colors.baseGray - - Row { - anchors { - verticalCenter: parent.verticalCenter - right: parent.right - rightMargin: hifi.dimensions.contentMargin.x - } - - Button { - text: "Cancel" - color: hifi.buttons.white - onClicked: root.destroy(); - } - } - } - - Keyboard { - id: keyboard - - raised: parent.keyboardEnabled && parent.keyboardRaised - numeric: parent.punctuationMode - - anchors { - left: parent.left - right: parent.right - bottom: parent.bottom - } - } - - Component.onCompleted: { - keyboardEnabled = HMD.active; - } -} diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6cabab6c01..4436c5cde9 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -6776,6 +6776,15 @@ void Application::loadAddAvatarBookmarkDialog() const { avatarBookmarks->addBookmark(); } +void Application::loadAvatarBrowser() const { + auto tablet = dynamic_cast(DependencyManager::get()->getTablet("com.highfidelity.interface.tablet.system")); + // construct the url to the marketplace item + QString url = NetworkingConstants::METAVERSE_SERVER_URL().toString() + "/marketplace?category=avatars"; + QString MARKETPLACES_INJECT_SCRIPT_PATH = "file:///" + qApp->applicationDirPath() + "/scripts/system/html/js/marketplacesInject.js"; + tablet->gotoWebScreen(url, MARKETPLACES_INJECT_SCRIPT_PATH); + DependencyManager::get()->openTablet(); +} + void Application::takeSnapshot(bool notify, bool includeAnimated, float aspectRatio) { postLambdaEvent([notify, includeAnimated, aspectRatio, this] { // Get a screenshot and save it diff --git a/interface/src/Application.h b/interface/src/Application.h index 479ce919a3..b687158516 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -309,6 +309,7 @@ public slots: void toggleEntityScriptServerLogDialog(); Q_INVOKABLE void showAssetServerWidget(QString filePath = ""); Q_INVOKABLE void loadAddAvatarBookmarkDialog() const; + Q_INVOKABLE void loadAvatarBrowser() const; Q_INVOKABLE SharedSoundPointer getSampleSound() const; void showDialog(const QUrl& widgetUrl, const QUrl& tabletUrl, const QString& name) const; From a48304b1047be440dbabf033270ff15325d550b5 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Fri, 12 Jan 2018 17:06:07 -0800 Subject: [PATCH 15/19] fix Asset browser for tablet --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6cabab6c01..2288bff84a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -6147,7 +6147,7 @@ void Application::showAssetServerWidget(QString filePath) { if (!hmd->getShouldShowTablet() && !isHMDMode()) { DependencyManager::get()->show(url, "AssetServer", startUpload); } else { - static const QUrl url("hifi/dialogs/TabletAssetServer.qml"); + static const QUrl url("../dialogs/TabletAssetServer.qml"); tablet->pushOntoStack(url); } } From f1253e3c6cdcca4c348c4a5a7e6af4560211bdf3 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 15 Jan 2018 15:01:17 -0800 Subject: [PATCH 16/19] fix crash on last frame = first frame, make last frame inclusive --- libraries/entities/src/ModelEntityItem.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index 3e6d19f430..46c1c9a4c7 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -267,9 +267,9 @@ void ModelEntityItem::updateFrameCount() { if (!getAnimationHold() && getAnimationIsPlaying()) { float deltaTime = (float)interval / (float)USECS_PER_SECOND; _currentFrame += (deltaTime * getAnimationFPS()); - if (_currentFrame > getAnimationLastFrame()) { - if (getAnimationLoop()) { - _currentFrame = getAnimationFirstFrame() + (int)(glm::floor(_currentFrame - getAnimationFirstFrame())) % (updatedFrameCount - 1); + if (_currentFrame > getAnimationLastFrame() + 1) { + if (getAnimationLoop() && getAnimationFirstFrame() != getAnimationLastFrame()) { + _currentFrame = getAnimationFirstFrame() + (int)(_currentFrame - getAnimationFirstFrame()) % updatedFrameCount; } else { _currentFrame = getAnimationLastFrame(); } From 9d721ba605529b4acfce121eb28b1dca9491955c Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 15 Jan 2018 15:01:17 -0800 Subject: [PATCH 17/19] fix crash on last frame = first frame, make last frame inclusive (cherry picked from commit f1253e3c6cdcca4c348c4a5a7e6af4560211bdf3) --- libraries/entities/src/ModelEntityItem.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index 3e6d19f430..46c1c9a4c7 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -267,9 +267,9 @@ void ModelEntityItem::updateFrameCount() { if (!getAnimationHold() && getAnimationIsPlaying()) { float deltaTime = (float)interval / (float)USECS_PER_SECOND; _currentFrame += (deltaTime * getAnimationFPS()); - if (_currentFrame > getAnimationLastFrame()) { - if (getAnimationLoop()) { - _currentFrame = getAnimationFirstFrame() + (int)(glm::floor(_currentFrame - getAnimationFirstFrame())) % (updatedFrameCount - 1); + if (_currentFrame > getAnimationLastFrame() + 1) { + if (getAnimationLoop() && getAnimationFirstFrame() != getAnimationLastFrame()) { + _currentFrame = getAnimationFirstFrame() + (int)(_currentFrame - getAnimationFirstFrame()) % updatedFrameCount; } else { _currentFrame = getAnimationLastFrame(); } From 02179e3efd3793c0824bf31d9c489fe0a03ee3cd Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 16 Jan 2018 17:14:30 +1300 Subject: [PATCH 18/19] Doc review --- libraries/networking/src/AddressManager.h | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h index 2c342a1b93..89bcb434ca 100644 --- a/libraries/networking/src/AddressManager.h +++ b/libraries/networking/src/AddressManager.h @@ -183,6 +183,7 @@ public slots: * "127.0.0.1" or "localhost"), a domain name, a named path on a domain (starts with * "/"), a position or position and orientation, or a user (starts with "@"). * @param {boolean} fromSuggestions=false - Set to true if the address is obtained from the "Goto" dialog. + * Helps ensure that user's location history is correctly maintained. */ void handleLookupString(const QString& lookupString, bool fromSuggestions = false); @@ -217,14 +218,16 @@ public slots: * Go to the local Sandbox server that's running on the same PC as Interface. * @function location.goToLocalSandbox * @param {string} path="" - The position and orientation to go to (e.g., "/0,0,0"). - * @param {location.LookupTrigger} trigger=StartupFromSettings - The reason for the function call. + * @param {location.LookupTrigger} trigger=StartupFromSettings - The reason for the function call. Helps ensure that user's + * location history is correctly maintained. */ void goToLocalSandbox(QString path = "", LookupTrigger trigger = LookupTrigger::StartupFromSettings) { handleUrl(SANDBOX_HIFI_ADDRESS + path, trigger); } /**jsdoc - * Go to the default metaverse address. + * Go to the default "welcome" metaverse address. * @function location.goToEntry - * @param {location.LookupTrigger} trigger=StartupFromSettings - The reason for the function call. + * @param {location.LookupTrigger} trigger=StartupFromSettings - The reason for the function call. Helps ensure that user's + * location history is correctly maintained. */ void goToEntry(LookupTrigger trigger = LookupTrigger::StartupFromSettings) { handleUrl(DEFAULT_HIFI_ADDRESS, trigger); } @@ -238,7 +241,7 @@ public slots: void goToUser(const QString& username, bool shouldMatchOrientation = true); /**jsdoc - * Refresh the current address, e.g., after connecting to a domain ion order to position the user to the desired location. + * Refresh the current address, e.g., after connecting to a domain in order to position the user to the desired location. * @function location.refreshPreviousLookup * @deprecated This function is deprecated and will be removed. */ @@ -247,7 +250,8 @@ public slots: void refreshPreviousLookup(); /**jsdoc - * Save your current metaverse location in Interface's settings file. + * Update your current metaverse location in Interface's {@link Settings} file as your last-know address. This can be used + * to ensure that you start up at that address if you exit Interface without a later address automatically being saved. * @function location.storeCurrentAddress */ void storeCurrentAddress(); From f836a5f2b672b942857896680fb19b830be1fe92 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 17 Jan 2018 08:06:04 +1300 Subject: [PATCH 19/19] Fix typo --- libraries/networking/src/AddressManager.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h index 89bcb434ca..7302e0e997 100644 --- a/libraries/networking/src/AddressManager.h +++ b/libraries/networking/src/AddressManager.h @@ -250,7 +250,7 @@ public slots: void refreshPreviousLookup(); /**jsdoc - * Update your current metaverse location in Interface's {@link Settings} file as your last-know address. This can be used + * Update your current metaverse location in Interface's {@link Settings} file as your last-known address. This can be used * to ensure that you start up at that address if you exit Interface without a later address automatically being saved. * @function location.storeCurrentAddress */