Merge pull request #5078 from ZappoMan/team-teaching

TEAM TEACHING - merge from master
This commit is contained in:
Brad Hefta-Gaub 2015-06-08 12:48:23 -07:00
commit 773e0b1d5b
41 changed files with 1400 additions and 348 deletions

View file

@ -13,6 +13,7 @@
var isGrabbing = false; var isGrabbing = false;
var grabbedEntity = null; var grabbedEntity = null;
var actionID = null;
var prevMouse = {}; var prevMouse = {};
var deltaMouse = { var deltaMouse = {
z: 0 z: 0
@ -87,7 +88,6 @@ function mousePressEvent(event) {
Entities.editEntity(grabbedEntity, { Entities.editEntity(grabbedEntity, {
gravity: {x: 0, y: 0, z: 0} gravity: {x: 0, y: 0, z: 0}
}); });
} }
} }
@ -110,7 +110,10 @@ function updateDropLine(position) {
function mouseReleaseEvent() { function mouseReleaseEvent() {
if (isGrabbing) { if (isGrabbing) {
// Controller.mouseMoveEvent.disconnect(mouseMoveEvent);
isGrabbing = false; isGrabbing = false;
Entities.deleteAction(grabbedEntity, actionID);
actionID = null;
// only restore the original gravity if it's not zero. This is to avoid... // only restore the original gravity if it's not zero. This is to avoid...
// 1. interface A grabs an entity and locally saves off its gravity // 1. interface A grabs an entity and locally saves off its gravity
@ -228,23 +231,28 @@ function update(deltaTime) {
} }
if (shouldRotate) { if (shouldRotate) {
angularVelocity = Vec3.subtract(angularVelocity, Vec3.multiply(angularVelocity, ANGULAR_DAMPING_RATE)); angularVelocity = Vec3.subtract(angularVelocity, Vec3.multiply(angularVelocity, ANGULAR_DAMPING_RATE));
Entities.editEntity(grabbedEntity, {
rotation: currentRotation,
angularVelocity: angularVelocity
});
} else { } else {
angularVelocity = entityProps.angularVelocity; angularVelocity = entityProps.angularVelocity;
} }
Entities.editEntity(grabbedEntity, { var newSpeed = Vec3.length(newVelocity);
position: currentPosition, if (!actionID) {
rotation: currentRotation, actionID = Entities.addAction("pull-to-point", grabbedEntity, {target: targetPosition, speed: newSpeed});
velocity: newVelocity, } else {
angularVelocity: angularVelocity Entities.updateAction(grabbedEntity, actionID, {target: targetPosition, speed: newSpeed});
}); }
updateDropLine(targetPosition); updateDropLine(targetPosition);
} }
} }
Controller.mouseMoveEvent.connect(mouseMoveEvent);
Controller.mousePressEvent.connect(mousePressEvent); Controller.mousePressEvent.connect(mousePressEvent);
Controller.mouseReleaseEvent.connect(mouseReleaseEvent); Controller.mouseReleaseEvent.connect(mouseReleaseEvent);
Controller.mouseMoveEvent.connect(mouseMoveEvent);
Controller.keyPressEvent.connect(keyPressEvent); Controller.keyPressEvent.connect(keyPressEvent);
Controller.keyReleaseEvent.connect(keyReleaseEvent); Controller.keyReleaseEvent.connect(keyReleaseEvent);
Script.update.connect(update); Script.update.connect(update);

View file

@ -0,0 +1,123 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
x="0px"
y="0px"
viewBox="0 0 150 150"
enable-background="new 0 0 512 512"
xml:space="preserve"
id="svg2"
inkscape:version="0.91 r13725"
sodipodi:docname="hifi-logo-blackish.svg"
width="150"
height="150"><metadata
id="metadata57"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs55" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1835"
inkscape:window-height="1057"
id="namedview53"
showgrid="false"
inkscape:zoom="2.6074563"
inkscape:cx="256"
inkscape:cy="67.100056"
inkscape:window-x="77"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="svg2" /><g
id="Layer_1"
transform="translate(-30.500027,-42.2)"><g
id="g5"><g
id="g7"><path
d="M 155.3,67.4 C 141.9,54.3 124.5,47 105.8,47 86.8,47 69.4,54.3 56,67.4 42.9,80.8 35.5,98.2 35.5,117.2 c 0,18.7 7.3,36.4 20.5,49.5 13.2,13.1 30.8,20.5 49.5,20.5 18.7,0 36.4,-7.3 49.5,-20.5 13.1,-13.1 20.5,-30.8 20.5,-49.5 0.3,-18.9 -7,-36.4 -20.2,-49.8 z m -5,94.3 c -11.9,11.9 -27.8,18.4 -44.7,18.4 C 88.7,180.1 73,173.5 60.9,161.7 49,149.8 42.5,133.9 42.5,117 c 0,-16.9 6.6,-32.6 18.4,-44.7 11.9,-11.9 27.8,-18.4 44.7,-18.4 16.9,0 32.6,6.6 44.7,18.4 11.9,11.9 18.4,27.8 18.4,44.7 0,16.9 -6.6,32.8 -18.4,44.7 z"
id="path9"
inkscape:connector-curvature="0"
style="fill:#333333" /><g
id="g11"><path
d="m 86.8,142 c -1.5,0 -3,-1.3 -3,-3 l 0,-54.1 c 0,-1.5 1.3,-3 3,-3 1.5,0 3,1.3 3,3 l 0,54.3 c 0.1,1.5 -1.2,2.8 -3,2.8 z"
id="path13"
inkscape:connector-curvature="0"
style="fill:#333333" /><path
d="m 90.4,83.4 c -2,2 -5.1,2 -6.8,0 -2,-2 -2,-5.1 0,-6.8 2,-2 5.1,-2 6.8,0 2,2 2,5 0,6.8"
id="path15"
inkscape:connector-curvature="0"
style="fill:#333333" /><g
id="g17"><path
d="m 86.8,87.9 c -2,0 -4,-0.8 -5.6,-2.3 -3,-3 -3,-8.1 0,-11.1 1.5,-1.5 3.5,-2.3 5.6,-2.3 2.1,0 4,0.8 5.6,2.3 1.5,1.5 2.3,3.5 2.3,5.6 0,2.1 -0.8,4 -2.3,5.6 -1.5,1.2 -3.3,2.2 -5.6,2.2 z m 0,-9.8 c -0.5,0 -1,0.3 -1.5,0.5 -0.8,0.8 -0.8,2 0,2.8 0.8,0.8 2,0.8 2.8,0 0.3,-0.3 0.5,-0.8 0.5,-1.5 0,-0.5 -0.3,-1 -0.5,-1.5 -0.2,-0.1 -0.7,-0.3 -1.3,-0.3 z"
id="path19"
inkscape:connector-curvature="0"
style="fill:#333333" /></g><path
d="m 83.6,140.5 c 2,-2 5.1,-2 6.8,0 2,2 2,5.1 0,6.8 -2,2 -5.1,2 -6.8,0 -2.1,-1.8 -2.1,-4.8 0,-6.8"
id="path21"
inkscape:connector-curvature="0"
style="fill:#333333" /><g
id="g23"><path
d="m 86.8,151.8 c -2,0 -4,-0.8 -5.6,-2.3 C 79.6,148 79,146 79,144 c 0,-2 0.8,-4 2.3,-5.6 1.5,-1.6 3.5,-2.3 5.6,-2.3 2.1,0 4,0.8 5.6,2.3 1.6,1.5 2.3,3.5 2.3,5.6 0,2.1 -0.8,4 -2.3,5.6 -1.6,1.5 -3.4,2.2 -5.7,2.2 z m 0,-9.8 c -0.5,0 -1,0.3 -1.5,0.5 -0.3,0.3 -0.5,0.8 -0.5,1.5 0,0.5 0.3,1 0.5,1.5 0.8,0.8 2,0.8 2.8,0 0.3,-0.3 0.5,-0.8 0.5,-1.5 0,-0.5 -0.3,-1 -0.5,-1.5 -0.2,-0.3 -0.7,-0.5 -1.3,-0.5 z"
id="path25"
inkscape:connector-curvature="0"
style="fill:#333333" /></g><g
id="g27"><path
d="m 124.5,152.3 c -1.5,0 -3,-1.3 -3,-3 l 0,-54.3 c 0,-1.5 1.3,-3 3,-3 1.5,0 3,1.3 3,3 l 0,54.3 c 0,1.8 -1.5,3 -3,3 z"
id="path29"
inkscape:connector-curvature="0"
style="fill:#333333" /></g><path
d="m 128,93.7 c -2,2 -5.1,2 -6.8,0 -2,-2 -2,-5.1 0,-6.8 2,-2 5.1,-2 6.8,0 1.8,1.8 1.8,4.8 0,6.8"
id="path31"
inkscape:connector-curvature="0"
style="fill:#333333" /><g
id="g33"><path
d="m 124.5,98 c -2,0 -4,-0.8 -5.6,-2.3 -3,-3 -3,-8.1 0,-11.1 1.5,-1.5 3.5,-2.3 5.6,-2.3 2,0 4,0.8 5.6,2.3 1.5,1.5 2.3,3.5 2.3,5.6 0,2 -0.8,4 -2.3,5.6 -1.6,1.5 -3.6,2.2 -5.6,2.2 z m 0,-9.8 c -0.5,0 -1,0.3 -1.5,0.5 -0.8,0.8 -0.8,2 0,2.8 0.8,0.8 2,0.8 2.8,0 0.3,-0.3 0.5,-0.8 0.5,-1.5 0,-0.5 -0.3,-1 -0.5,-1.5 -0.3,-0.1 -0.8,-0.3 -1.3,-0.3 z"
id="path35"
inkscape:connector-curvature="0"
style="fill:#333333" /></g><g
id="g37"><path
d="m 124.5,162.2 c -2,0 -4,-0.8 -5.6,-2.3 -3,-3 -3,-8.1 0,-11.1 1.5,-1.5 3.5,-2.3 5.6,-2.3 2,0 4,0.8 5.6,2.3 1.5,1.5 2.3,3.5 2.3,5.6 0,2.1 -0.8,4 -2.3,5.6 -1.6,1.2 -3.6,2.2 -5.6,2.2 z m 0,-9.9 c -0.5,0 -1,0.3 -1.5,0.5 -0.8,0.8 -0.8,2 0,2.8 0.8,0.8 2,0.8 2.8,0 0.3,-0.3 0.5,-0.8 0.5,-1.5 0,-0.7 -0.3,-1 -0.5,-1.5 -0.3,0 -0.8,-0.3 -1.3,-0.3 z"
id="path39"
inkscape:connector-curvature="0"
style="fill:#333333" /></g><path
d="m 121,150.8 c 2,-2 5.1,-2 6.8,0 2,2 2,5.1 0,6.8 -2,2 -5.1,2 -6.8,0 -1.8,-1.7 -1.8,-5 0,-6.8"
id="path41"
inkscape:connector-curvature="0"
style="fill:#333333" /><g
id="g43"><rect
x="85.099998"
y="113.2"
transform="matrix(-0.9064,-0.4224,0.4224,-0.9064,152.6722,266.0858)"
width="41.400002"
height="5.8000002"
id="rect45"
style="fill:#333333" /></g></g></g></g></g><g
id="Layer_2_copy"
display="none"
style="display:none"
transform="translate(0,-362)"><path
display="inline"
d="m 500,511.5 -488,0 c -6.6,0 -12,-5.4 -12,-12 l 0,-168 c 0,-6.6 5.4,-12 12,-12 l 488,0 c 6.6,0 12,5.4 12,12 l 0,168 c 0,6.6 -5.4,12 -12,12 z"
id="path48"
inkscape:connector-curvature="0"
style="display:inline;fill:#ffffff" /><g
id="Layer_2"
display="inline"
style="display:inline"><path
d="M 500,384 12,384 C 5.4,384 0,378.6 0,372 L 0,12 C 0,5.4 5.4,0 12,0 l 488,0 c 6.6,0 12,5.4 12,12 l 0,360 c 0,6.6 -5.4,12 -12,12 z"
id="path51"
inkscape:connector-curvature="0"
style="fill:#368db0" /></g></g></svg>

After

Width:  |  Height:  |  Size: 6.7 KiB

View file

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="pomodoro"
x="0px"
y="0px"
width="100"
height="100"
viewBox="-7.125 -7.328 100 100"
enable-background="new -7.125 -7.328 100 91.57"
xml:space="preserve"
inkscape:version="0.91 r13725"
sodipodi:docname="login-close.svg"><metadata
id="metadata4143"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs
id="defs4141" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1835"
inkscape:window-height="1057"
id="namedview4139"
showgrid="false"
inkscape:zoom="4.8487496"
inkscape:cx="-41.872299"
inkscape:cy="37.53545"
inkscape:window-x="77"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="pomodoro" /><path
d="m 42.8705,-2.3280001 c -24.8688,0 -44.9955,20.1618001 -44.9955,45.0045001 0,24.8733 20.1267,44.9955 44.9955,44.9955 24.8427,0 45.0045,-20.1222 45.0045,-44.9955 0,-24.8427 -20.1618,-45.0045001 -45.0045,-45.0045001 z M 67.1066,57.126 57.329,66.9036 42.6293,52.221 27.9422,66.9036 18.1511,57.126 32.8247,42.4443 18.1511,27.7482 27.9422,17.9796 42.6284,32.6487 57.3281,17.9796 67.1057,27.7482 52.424,42.4434 67.1066,57.126 Z"
id="path4137"
inkscape:connector-curvature="0" /><path
style="fill:#787878;fill-opacity:1;stroke:none;stroke-opacity:1"
d="M 38.400102,87.62655 C 28.705316,86.39839 21.084707,83.18102 13.982682,77.31765 5.5185024,70.329714 -0.09877759,60.244376 -1.7904936,48.998291 -2.1921426,46.328239 -2.2434696,39.677941 -1.8825126,37.07572 0.23131941,21.836625 9.4778634,8.9272213 23.005945,2.3281243 c 9.805646,-4.783264 20.444414,-5.902737 30.964952,-3.25830896 7.357662,1.849413 14.403738,5.75570696 19.976698,11.07495366 7.36697,7.031569 12.03213,16.084669 13.58981,26.37208 0.45133,2.980701 0.44981,9.518147 -0.003,12.481442 -0.72914,4.772737 -2.08456,9.199896 -4.04575,13.214497 -2.40852,4.930297 -4.94684,8.502038 -8.75077,12.313422 -6.78153,6.79482 -14.822805,10.95587 -24.504932,12.68035 -1.787127,0.3183 -3.134188,0.40875 -6.708441,0.45045 -2.459762,0.0287 -4.765789,0.0149 -5.124505,-0.0304 z m -3.02899,-27.869116 7.314939,-7.311007 7.360877,7.35692 7.360872,7.356917 4.983865,-4.982378 4.98386,-4.982378 -7.359111,-7.358686 -7.359105,-7.358687 7.359105,-7.358687 7.359111,-7.358686 -4.98387,-4.982383 -4.983864,-4.982384 -7.407456,7.393329 -7.407456,7.393328 -7.360652,-7.342464 -7.36065,-7.342467 -4.922357,4.916384 -4.922356,4.916381 7.300528,7.417269 7.300528,7.417267 -7.362706,7.362244 -7.362709,7.362244 4.890918,4.889465 c 2.690008,2.689205 4.974582,4.889463 5.076835,4.889463 0.102254,0 3.477639,-3.289951 7.500854,-7.311004 z"
id="path4145"
inkscape:connector-curvature="0" /><path
style="fill:#ffffff;fill-opacity:0.50196081;stroke:none;stroke-linejoin:round;stroke-opacity:1"
d="M 44.534673,94.743449 C 34.891509,93.246309 27.795933,90.11327 20.775164,84.252477 11.886441,76.832357 5.9619527,65.158789 5.1748775,53.513789 c -0.2319637,-3.43197 -0.2319637,-3.580148 0,-7.012117 0.2997941,-4.43554 1.6142349,-10.018379 3.2047936,-13.611757 0.9426814,-2.1297 3.0434359,-6.187162 3.2034079,-6.187162 0.0878,0 0.159635,-0.08223 0.159635,-0.182738 0,-0.184553 1.62407,-2.719865 1.864629,-2.910843 0.07144,-0.05672 0.214767,-0.254527 0.318504,-0.43958 0.444428,-0.792801 4.761858,-5.745943 5.011388,-5.74928 0.06982,-9.28e-4 0.599004,-0.44177 1.175954,-0.979634 0.57695,-0.537865 1.357309,-1.209955 1.73413,-1.493533 0.376821,-0.283579 0.803015,-0.631606 0.947096,-0.773396 0.144082,-0.141789 0.33915,-0.257798 0.433485,-0.257798 0.09433,0 0.421739,-0.232019 0.727566,-0.515597 0.305826,-0.283578 0.652906,-0.515597 0.771287,-0.515597 0.118382,0 0.21524,-0.09281 0.21524,-0.206238 0,-0.113432 0.131477,-0.206239 0.292173,-0.206239 0.160693,0 0.323106,-0.06961 0.360917,-0.154679 0.03781,-0.08507 0.486379,-0.379776 0.99682,-0.654895 0.510441,-0.275119 0.974478,-0.553541 1.031194,-0.618716 0.05672,-0.06518 0.683166,-0.390786 1.392111,-0.723578 0.708946,-0.3327925 1.288992,-0.6962883 1.288992,-0.8077684 0,-0.1114801 0.0579,-0.1447959 0.128656,-0.074035 0.07076,0.070761 0.511596,-0.070816 0.979634,-0.3146147 0.468039,-0.2437989 0.943786,-0.4657735 1.057217,-0.4932771 0.232223,-0.056306 4.161879,-1.4638567 4.640372,-1.6621192 0.170147,-0.0705 0.539063,-0.1662889 0.819815,-0.2128641 0.280751,-0.046575 0.614115,-0.1707121 0.740812,-0.2758597 0.126694,-0.1051476 0.274366,-0.1471661 0.328157,-0.093375 0.05379,0.053792 0.416482,9.591e-4 0.805979,-0.1174068 0.389496,-0.1183654 0.893791,-0.250227 1.120654,-0.2930258 C 41.396501,5.8872092 42.53806,5.68664 43.297241,5.5593565 45.066132,5.2627864 46.714013,5.1673775 50,5.1712806 c 3.805191,0.00452 5.083801,0.101258 7.940191,0.6007452 1.309528,0.2289926 1.540035,0.2798038 2.254967,0.4970667 0.389497,0.1183654 0.752188,0.1711985 0.805979,0.1174068 0.05379,-0.053792 0.201463,-0.011773 0.328157,0.093375 0.126697,0.1051476 0.460061,0.2292845 0.740812,0.2758597 0.280752,0.046575 0.649668,0.1381531 0.819815,0.2035062 0.29917,0.1149109 2.471922,0.8292633 2.681104,0.8814871 0.180626,0.045095 1.113229,0.4463555 2.521561,1.0849238 0.752112,0.341023 1.420515,0.5670004 1.485344,0.502172 0.06483,-0.064829 0.11787,-0.026659 0.11787,0.084821 0,0.1114801 0.580046,0.4749759 1.288992,0.8077684 0.708945,0.332792 1.388624,0.697885 1.510393,0.811316 0.121772,0.113431 0.583276,0.391854 1.025566,0.618716 0.442289,0.226863 0.986609,0.574891 1.209598,0.773396 0.222989,0.198504 0.484793,0.360917 0.581787,0.360917 0.09699,0 0.426572,0.232019 0.732399,0.515597 0.305826,0.283578 0.626601,0.515597 0.712834,0.515597 0.08623,0 0.331378,0.162413 0.544769,0.360918 0.213391,0.198505 0.634947,0.546532 0.936792,0.773395 0.301843,0.226863 0.897759,0.737304 1.324259,1.134313 0.426497,0.39701 1.236446,1.139469 1.799884,1.64991 0.880557,0.797729 1.757212,1.75052 3.54596,3.853913 0.210933,0.248036 0.563341,0.699155 0.78313,1.002487 0.219788,0.303332 0.494773,0.657238 0.611075,0.786459 0.455109,0.505658 1.954048,2.819855 1.954048,3.016835 0,0.114715 0.07659,0.208572 0.170192,0.208572 0.161275,0 2.091162,3.737786 3.194546,6.187162 1.541607,3.422177 2.906394,9.221918 3.203098,13.611757 0.231964,3.431969 0.231964,3.580147 0,7.012117 -0.815165,12.060598 -6.997182,23.808557 -16.608839,31.562504 -6.618801,5.339542 -15.182288,8.893437 -23.343332,9.687615 -2.412178,0.234737 -8.77566,0.222144 -10.338278,-0.02046 z m 25.10828,-25.193278 5.003096,-4.999972 -7.37222,-7.374353 -7.372221,-7.374355 7.372221,-7.374354 7.37222,-7.374353 -5.053369,-5.050211 -5.053369,-5.050211 -7.48442,7.482314 -7.48442,7.482312 -7.279626,-7.328953 c -4.003795,-4.030924 -7.3403,-7.328953 -7.414457,-7.328953 -0.204703,0 -9.728156,9.56039 -9.728156,9.765886 0,0.09849 3.255479,3.479009 7.234399,7.512255 l 7.234397,7.333175 -7.389076,7.404243 -7.389078,7.404243 4.94973,4.825596 c 2.722351,2.654079 5.078575,4.828707 5.236051,4.83251 0.157477,0.0038 3.547751,-3.239037 7.53394,-7.206305 l 7.247619,-7.213218 7.31416,7.316337 c 4.022788,4.023984 7.360357,7.316336 7.416821,7.316336 0.05646,0 2.354055,-2.249986 5.105758,-4.999969 z"
id="path4134"
inkscape:connector-curvature="0"
transform="translate(-7.125,-7.3280001)" /></svg>

After

Width:  |  Height:  |  Size: 7.8 KiB

View file

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="Layer_1"
x="0px"
y="0px"
width="100px"
height="100px"
viewBox="0 0 100 100"
enable-background="new 0 0 100 100"
xml:space="preserve"
inkscape:version="0.91 r13725"
sodipodi:docname="login-password.svg"><metadata
id="metadata13"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs
id="defs11" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1017"
inkscape:window-height="605"
id="namedview9"
showgrid="false"
inkscape:zoom="2.36"
inkscape:cx="-22.245763"
inkscape:cy="50"
inkscape:window-x="138"
inkscape:window-y="109"
inkscape:window-maximized="0"
inkscape:current-layer="Layer_1" /><path
stroke-miterlimit="10"
d="m 70.932259,91.378387 -42.84472,0 c -3.950284,0 -7.163638,-3.213354 -7.163638,-7.162414 l 0,-37.131683 c 0,-3.949059 3.213354,-7.162413 7.163638,-7.162413 l 42.84472,0 c 3.950285,0 7.163639,3.213354 7.163639,7.162413 l 0,37.132908 c -0.0012,3.947835 -3.214579,7.161189 -7.163639,7.161189 z M 28.087539,42.00413 c -2.800821,0 -5.077712,2.278115 -5.077712,5.078936 l 0,37.132907 c 0,2.800821 2.276891,5.078936 5.077712,5.078936 l 42.84472,0 c 2.800822,0 5.077712,-2.278115 5.077712,-5.078936 l 0,-37.131683 c 0,-2.800821 -2.27689,-5.078936 -5.077712,-5.078936 l -42.84472,0 z"
id="path3"
inkscape:connector-curvature="0"
style="stroke:#808080;stroke-width:1.5;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1;fill:#808080;fill-opacity:1" /><path
stroke-miterlimit="10"
d="m 53.812733,79.237417 -8.601995,0 c -1.695428,0 -3.075027,-1.377152 -3.075027,-3.073802 0,-0.09181 0.01224,-0.182397 0.0355,-0.271759 l 2.407874,-8.927616 c -2.105512,-1.555875 -3.340664,-3.983335 -3.340664,-6.632363 0,-4.559902 3.710353,-8.270254 8.271478,-8.270254 4.561127,0 8.269033,3.710352 8.269033,8.270254 0,2.649028 -1.235154,5.075264 -3.340665,6.631139 l 2.410321,8.92884 c 0.02448,0.08813 0.03551,0.178724 0.03551,0.271759 0.0012,1.69665 -1.378375,3.073802 -3.071353,3.073802 z m -9.587424,-2.959958 c 0.05753,0.493326 0.476188,0.877704 0.985429,0.877704 l 8.601995,0 c 0.506792,0 0.927895,-0.38193 0.985429,-0.877704 l -2.563339,-9.489494 c -0.121188,-0.449258 0.071,-0.924222 0.468844,-1.161704 1.87415,-1.133549 2.993011,-3.112975 2.993011,-5.291934 0,-3.411665 -2.775115,-6.189227 -6.186779,-6.189227 -3.412887,0 -6.189226,2.777562 -6.189226,6.189227 0,2.178959 1.11886,4.158385 2.99301,5.291934 0.397844,0.239931 0.587585,0.714895 0.468843,1.161704 l -2.557217,9.489494 z"
id="path5"
inkscape:connector-curvature="0"
style="stroke:#808080;stroke-width:1.5;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1;fill:#808080;fill-opacity:1" /><path
stroke-miterlimit="10"
d="m 67.973525,36.897039 c -0.575343,0 -1.041738,-0.466395 -1.041738,-1.041738 l 0,-8.3486 c 0,-8.992495 -7.316654,-16.309149 -16.306701,-16.309149 l -2.230374,0 c -8.992495,0 -16.306701,7.316654 -16.306701,16.309149 l 0,8.3486 c 0,0.575343 -0.466395,1.041738 -1.041738,1.041738 -0.575343,0 -1.04174,-0.466395 -1.04174,-1.041738 l 0,-8.3486 c 0,-10.140733 8.248221,-18.391402 18.387731,-18.391402 l 2.230374,0 c 10.139509,0 18.38773,8.250669 18.38773,18.391402 l 0,8.3486 c 0.0037,0.575343 -0.462723,1.041738 -1.036843,1.041738 z"
id="path7"
inkscape:connector-curvature="0"
style="stroke:#808080;stroke-width:1.5;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1;fill:#808080;fill-opacity:1" /></svg>

After

Width:  |  Height:  |  Size: 4.2 KiB

View file

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="Your_Icon"
x="0px"
y="0px"
width="100px"
height="100px"
viewBox="0 0 100 100"
enable-background="new 0 0 100 100"
xml:space="preserve"
inkscape:version="0.91 r13725"
sodipodi:docname="login-username.svg"><metadata
id="metadata11"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
id="defs9" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1105"
inkscape:window-height="796"
id="namedview7"
showgrid="false"
inkscape:zoom="2.36"
inkscape:cx="-40.889831"
inkscape:cy="50"
inkscape:window-x="685"
inkscape:window-y="76"
inkscape:window-maximized="0"
inkscape:current-layer="Your_Icon" /><path
d="m 49.245763,52.491929 c 19.609799,0 35.508071,15.898272 35.508071,35.508071 l 3.737691,0 c 0,-21.674874 -17.570888,-39.245763 -39.245762,-39.245763 C 27.570889,48.754237 10,66.325126 10,88 l 3.737692,0 c 0,-19.609799 15.897337,-35.508071 35.508071,-35.508071 z"
id="path3"
inkscape:connector-curvature="0"
style="fill:#808080;fill-opacity:1" /><path
d="m 49.245763,9.508475 c -11.869975,0 -21.491727,9.621752 -21.491727,21.491727 0,11.869974 9.621752,21.491727 21.491727,21.491727 11.869974,0 21.491727,-9.621753 21.491727,-21.491727 0,-11.869975 -9.621753,-21.491727 -21.491727,-21.491727 z m 0,39.245762 c -9.805834,0 -17.754036,-7.948201 -17.754036,-17.754035 0,-9.805834 7.948202,-17.754036 17.754036,-17.754036 9.805834,0 17.754035,7.948202 17.754035,17.754036 0,9.805834 -7.948201,17.754035 -17.754035,17.754035 z"
id="path5"
inkscape:connector-curvature="0"
style="fill:#808080;fill-opacity:1" /></svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View file

@ -9,18 +9,16 @@
// //
import Hifi 1.0 import Hifi 1.0
import QtQuick 2.3 import QtQuick 2.4
import QtQuick.Controls 1.2
import "controls" import "controls"
import "styles" import "styles"
Item { DialogContainer {
id: root id: root
HifiConstants { id: hifi } HifiConstants { id: hifi }
objectName: "AddressBarDialog" objectName: "AddressBarDialog"
property int animationDuration: hifi.effects.fadeInDuration
property bool destroyOnInvisible: false property bool destroyOnInvisible: false
property real scale: 1.25 // Make this dialog a little larger than normal property real scale: 1.25 // Make this dialog a little larger than normal
@ -101,47 +99,16 @@ Item {
} }
} }
// The UI enables an object, rather than manipulating its visibility, so that we can do animations in both directions.
// Because visibility and enabled are booleans, they cannot be animated. So when enabled is changed, we modify a property
// that can be animated, like scale or opacity, and then when the target animation value is reached, we can modify the
// visibility.
enabled: false
opacity: 0.0
onEnabledChanged: { onEnabledChanged: {
opacity = enabled ? 1.0 : 0.0
if (enabled) { if (enabled) {
addressLine.forceActiveFocus(); addressLine.forceActiveFocus()
} }
} }
Behavior on opacity {
// Animate opacity.
NumberAnimation {
duration: animationDuration
easing.type: Easing.OutCubic
}
}
onOpacityChanged: {
// Once we're transparent, disable the dialog's visibility.
visible = (opacity != 0.0)
}
onVisibleChanged: { onVisibleChanged: {
if (!visible) { if (!visible) {
reset() addressLine.text = ""
// Some dialogs should be destroyed when they become invisible.
if (destroyOnInvisible) {
destroy()
}
} }
}
function reset() {
addressLine.text = ""
} }
function toggleOrGo() { function toggleOrGo() {
@ -152,21 +119,18 @@ Item {
} }
} }
Keys.onEscapePressed: {
enabled = false
}
Keys.onPressed: { Keys.onPressed: {
switch(event.key) { switch (event.key) {
case Qt.Key_W: case Qt.Key_Escape:
if (event.modifiers == Qt.ControlModifier) { case Qt.Key_Back:
event.accepted = true enabled = false
enabled = false event.accepted = true
} break
case Qt.Key_Enter:
case Qt.Key_Return:
toggleOrGo()
event.accepted = true
break break
} }
} }
Keys.onReturnPressed: toggleOrGo()
Keys.onEnterPressed: toggleOrGo()
} }

View file

@ -4,7 +4,7 @@ import QtWebKit 3.0
import "controls" import "controls"
import "styles" import "styles"
Dialog { VrDialog {
id: root id: root
HifiConstants { id: hifi } HifiConstants { id: hifi }
title: "Browser" title: "Browser"

View file

@ -8,27 +8,22 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// //
import Hifi 1.0 as Hifi import Hifi 1.0
import QtQuick 2.3 import QtQuick 2.4
import QtQuick.Controls 1.2
import QtQuick.Dialogs 1.2
import "controls" import "controls"
import "styles" import "styles"
Item { DialogContainer {
id: root id: root
HifiConstants { id: hifi } HifiConstants { id: hifi }
property int animationDuration: hifi.effects.fadeInDuration
property bool destroyOnInvisible: true
Component.onCompleted: { Component.onCompleted: {
enabled = true enabled = true
} }
onParentChanged: { onParentChanged: {
if (visible && enabled) { if (visible && enabled) {
forceActiveFocus(); forceActiveFocus()
} }
} }
@ -38,7 +33,7 @@ Item {
x: parent ? parent.width / 2 - width / 2 : 0 x: parent ? parent.width / 2 - width / 2 : 0
y: parent ? parent.height / 2 - height / 2 : 0 y: parent ? parent.height / 2 - height / 2 : 0
Hifi.ErrorDialog { ErrorDialog {
id: content id: content
implicitWidth: box.width implicitWidth: box.width
@ -69,7 +64,7 @@ Item {
Text { Text {
id: messageText id: messageText
font.pointSize: 10 font.pixelSize: hifi.fonts.pixelSize * 0.6
font.weight: Font.Bold font.weight: Font.Bold
anchors { anchors {
@ -91,55 +86,17 @@ Item {
} }
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
cursorShape: "PointingHandCursor"
onClicked: { onClicked: {
content.accept(); content.accept()
} }
} }
} }
} }
} }
// The UI enables an object, rather than manipulating its visibility, so that we can do animations in both directions.
// Because visibility and enabled are booleans, they cannot be animated. So when enabled is changed, we modify a property
// that can be animated, like scale or opacity, and then when the target animation value is reached, we can modify the
// visibility.
enabled: false
opacity: 0.0
onEnabledChanged: {
opacity = enabled ? 1.0 : 0.0
}
Behavior on opacity {
// Animate opacity.
NumberAnimation {
duration: animationDuration
easing.type: Easing.OutCubic
}
}
onOpacityChanged: {
// Once we're transparent, disable the dialog's visibility.
visible = (opacity != 0.0)
}
onVisibleChanged: {
if (!visible) {
// Some dialogs should be destroyed when they become invisible.
if (destroyOnInvisible) {
destroy()
}
}
}
Keys.onPressed: { Keys.onPressed: {
if (event.modifiers === Qt.ControlModifier) switch (event.key) {
switch (event.key) {
case Qt.Key_W:
event.accepted = true
content.accept()
break
} else switch (event.key) {
case Qt.Key_Escape: case Qt.Key_Escape:
case Qt.Key_Back: case Qt.Key_Back:
case Qt.Key_Enter: case Qt.Key_Enter:

View file

@ -5,7 +5,7 @@ import QtQuick.Controls.Styles 1.3
import QtWebKit 3.0 import QtWebKit 3.0
import "controls" import "controls"
Dialog { VrDialog {
id: root id: root
width: 800 width: 800
height: 800 height: 800

View file

@ -1,78 +1,173 @@
//
// LoginDialog.qml
//
// Created by David Rowe on 3 Jun 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 Hifi 1.0 import Hifi 1.0
import QtQuick 2.3 import QtQuick 2.4
import QtQuick.Controls.Styles 1.3
import "controls" import "controls"
import "styles" import "styles"
Dialog { DialogContainer {
id: root
HifiConstants { id: hifi } HifiConstants { id: hifi }
title: "Login"
objectName: "LoginDialog" objectName: "LoginDialog"
height: 512
width: 384
onVisibleChanged: { property bool destroyOnInvisible: false
if (!visible) {
reset()
}
}
onEnabledChanged: { implicitWidth: loginDialog.implicitWidth
if (enabled) { implicitHeight: loginDialog.implicitHeight
username.forceActiveFocus();
}
}
function reset() { x: parent ? parent.width / 2 - width / 2 : 0
username.text = "" y: parent ? parent.height / 2 - height / 2 : 0
password.text = "" property int maximumX: parent ? parent.width - width : 0
loginDialog.statusText = "" property int maximumY: parent ? parent.height - height : 0
}
LoginDialog { LoginDialog {
id: loginDialog id: loginDialog
anchors.fill: parent
anchors.margins: parent.margins
anchors.topMargin: parent.topMargin
Column {
anchors.topMargin: 8
anchors.right: parent.right
anchors.rightMargin: 0
anchors.left: parent.left
anchors.top: parent.top
spacing: 8
Image { implicitWidth: backgroundRectangle.width
height: 64 implicitHeight: backgroundRectangle.height
anchors.horizontalCenter: parent.horizontalCenter
width: 64 readonly property int inputWidth: 500
source: "../images/hifi-logo.svg" readonly property int inputHeight: 60
readonly property int borderWidth: 30
readonly property int closeMargin: 16
readonly property real tan30: 0.577 // tan(30°)
readonly property int inputSpacing: 16
property int maximumX: parent ? parent.width - width : 0
property int maximumY: parent ? parent.height - height : 0
Rectangle {
id: backgroundRectangle
width: loginDialog.inputWidth + loginDialog.borderWidth * 2
height: loginDialog.inputHeight * 6 + loginDialog.closeMargin * 2
radius: loginDialog.closeMargin * 2
color: "#2c86b1"
opacity: 0.85
MouseArea {
width: parent.width
height: parent.height
anchors {
horizontalCenter: parent.horizontalCenter
verticalCenter: parent.verticalCenter
}
drag {
target: root
minimumX: 0
minimumY: 0
maximumX: root.parent ? root.maximumX : 0
maximumY: root.parent ? root.maximumY : 0
}
}
}
Image {
id: closeIcon
source: "../images/login-close.svg"
width: 20
height: 20
anchors {
top: backgroundRectangle.top
right: backgroundRectangle.right
topMargin: loginDialog.closeMargin
rightMargin: loginDialog.closeMargin
} }
Border { MouseArea {
width: 304 anchors.fill: parent
height: 64 cursorShape: "PointingHandCursor"
anchors.horizontalCenter: parent.horizontalCenter onClicked: {
root.enabled = false
}
}
}
Column {
id: mainContent
width: loginDialog.inputWidth
spacing: loginDialog.inputSpacing
anchors {
horizontalCenter: parent.horizontalCenter
verticalCenter: parent.verticalCenter
}
Item {
// Offset content down a little
width: loginDialog.inputWidth
height: loginDialog.closeMargin
}
Rectangle {
width: loginDialog.inputWidth
height: loginDialog.inputHeight
radius: height / 2
color: "#ebebeb"
Image {
source: "../images/login-username.svg"
width: loginDialog.inputHeight * 0.65
height: width
anchors {
verticalCenter: parent.verticalCenter
left: parent.left
leftMargin: loginDialog.inputHeight / 4
}
}
TextInput { TextInput {
id: username id: username
anchors.fill: parent anchors {
helperText: "Username or Email" fill: parent
anchors.margins: 8 leftMargin: loginDialog.inputHeight
rightMargin: loginDialog.inputHeight / 2
}
helperText: "username or email"
color: hifi.colors.text
KeyNavigation.tab: password KeyNavigation.tab: password
KeyNavigation.backtab: password KeyNavigation.backtab: password
} }
} }
Border { Rectangle {
width: 304 width: loginDialog.inputWidth
height: 64 height: loginDialog.inputHeight
anchors.horizontalCenter: parent.horizontalCenter radius: height / 2
color: "#ebebeb"
Image {
source: "../images/login-password.svg"
width: loginDialog.inputHeight * 0.65
height: width
anchors {
verticalCenter: parent.verticalCenter
left: parent.left
leftMargin: loginDialog.inputHeight / 4
}
}
TextInput { TextInput {
id: password id: password
anchors.fill: parent anchors {
fill: parent
leftMargin: loginDialog.inputHeight
rightMargin: loginDialog.inputHeight / 2
}
helperText: "password"
echoMode: TextInput.Password echoMode: TextInput.Password
helperText: "Password" color: hifi.colors.text
anchors.margins: 8
KeyNavigation.tab: username KeyNavigation.tab: username
KeyNavigation.backtab: username KeyNavigation.backtab: username
onFocusChanged: { onFocusChanged: {
@ -83,102 +178,176 @@ Dialog {
} }
} }
Text { Item {
anchors.horizontalCenter: parent.horizontalCenter width: loginDialog.inputWidth
textFormat: Text.StyledText height: loginDialog.inputHeight / 2
width: parent.width
height: 96
wrapMode: Text.WordWrap
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
text: loginDialog.statusText
}
}
Column { Text {
anchors.bottomMargin: 5 id: messageText
anchors.right: parent.right
anchors.rightMargin: 0 visible: loginDialog.statusText != "" && loginDialog.statusText != "Logging in..."
anchors.left: parent.left
anchors.bottom: parent.bottom width: loginDialog.inputWidth
height: loginDialog.inputHeight / 2
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
text: loginDialog.statusText
color: "white"
}
Row {
id: messageSpinner
visible: loginDialog.statusText == "Logging in..."
onVisibleChanged: visible ? messageSpinnerAnimation.restart() : messageSpinnerAnimation.stop()
spacing: 24
anchors {
verticalCenter: parent.verticalCenter
horizontalCenter: parent.horizontalCenter
}
Rectangle {
id: spinner1
width: 10
height: 10
color: "#ebebeb"
opacity: 0.05
}
Rectangle {
id: spinner2
width: 10
height: 10
color: "#ebebeb"
opacity: 0.05
}
Rectangle {
id: spinner3
width: 10
height: 10
color: "#ebebeb"
opacity: 0.05
}
SequentialAnimation {
id: messageSpinnerAnimation
running: messageSpinner.visible
loops: Animation.Infinite
NumberAnimation { target: spinner1; property: "opacity"; to: 1.0; duration: 1000 }
NumberAnimation { target: spinner2; property: "opacity"; to: 1.0; duration: 1000 }
NumberAnimation { target: spinner3; property: "opacity"; to: 1.0; duration: 1000 }
NumberAnimation { target: spinner1; property: "opacity"; to: 0.05; duration: 0 }
NumberAnimation { target: spinner2; property: "opacity"; to: 0.05; duration: 0 }
NumberAnimation { target: spinner3; property: "opacity"; to: 0.05; duration: 0 }
}
}
}
Rectangle { Rectangle {
width: 192 width: loginDialog.inputWidth
height: 64 height: loginDialog.inputHeight
anchors.horizontalCenter: parent.horizontalCenter radius: height / 2
color: hifi.colors.hifiBlue color: "#353535"
border.width: 0
radius: 10 TextInput {
anchors.fill: parent
text: "Login"
color: "white"
horizontalAlignment: Text.AlignHCenter
}
MouseArea { MouseArea {
anchors.bottom: parent.bottom anchors.fill: parent
anchors.bottomMargin: 0 cursorShape: "PointingHandCursor"
anchors.top: parent.top
anchors.right: parent.right
anchors.left: parent.left
onClicked: { onClicked: {
loginDialog.login(username.text, password.text) loginDialog.login(username.text, password.text)
} }
} }
}
Row { Row {
anchors.centerIn: parent anchors.horizontalCenter: parent.horizontalCenter
Text {
text: "Password?"
font.pixelSize: hifi.fonts.pixelSize * 0.8
font.underline: true
color: "#e0e0e0"
width: loginDialog.inputHeight * 4
horizontalAlignment: Text.AlignRight
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
spacing: 8
MouseArea {
anchors.fill: parent
cursorShape: "PointingHandCursor"
onClicked: {
loginDialog.openUrl(loginDialog.rootUrl + "/users/password/new")
}
}
}
Item {
width: loginDialog.inputHeight + loginDialog.inputSpacing * 2
height: loginDialog.inputHeight
Image { Image {
id: loginIcon id: hifiIcon
height: 32 source: "../images/hifi-logo-blackish.svg"
width: 32 width: loginDialog.inputHeight
source: "../images/login.svg" height: width
} anchors {
Text { horizontalCenter: parent.horizontalCenter
text: "Login" verticalCenter: parent.verticalCenter
color: "white" }
width: 64
height: parent.height
} }
} }
} Text {
text: "Register"
font.pixelSize: hifi.fonts.pixelSize * 0.8
font.underline: true
color: "#e0e0e0"
width: loginDialog.inputHeight * 4
horizontalAlignment: Text.AlignLeft
anchors.verticalCenter: parent.verticalCenter
Text { MouseArea {
width: parent.width anchors.fill: parent
height: 24 cursorShape: "PointingHandCursor"
horizontalAlignment: Text.AlignHCenter onClicked: {
verticalAlignment: Text.AlignVCenter loginDialog.openUrl(loginDialog.rootUrl + "/signup")
text:"Create Account" }
font.pointSize: 12
font.bold: true
color: hifi.colors.hifiBlue
MouseArea {
anchors.fill: parent
onClicked: {
loginDialog.openUrl(loginDialog.rootUrl + "/signup")
}
}
}
Text {
width: parent.width
height: 24
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
font.pointSize: 12
text: "Recover Password"
color: hifi.colors.hifiBlue
MouseArea {
anchors.fill: parent
onClicked: {
loginDialog.openUrl(loginDialog.rootUrl + "/users/password/new")
} }
} }
} }
} }
} }
onOpacityChanged: {
// Set focus once animation is completed so that focus is set at start-up when not logged in
if (opacity == 1.0) {
username.forceActiveFocus()
}
}
onVisibleChanged: {
if (!visible) {
username.text = ""
password.text = ""
loginDialog.statusText = ""
}
}
Keys.onPressed: { Keys.onPressed: {
switch(event.key) { switch (event.key) {
case Qt.Key_Escape:
case Qt.Key_Back:
enabled = false
event.accepted = true
break
case Qt.Key_Enter: case Qt.Key_Enter:
case Qt.Key_Return: case Qt.Key_Return:
if (username.activeFocus) { if (username.activeFocus) {
@ -192,7 +361,7 @@ Dialog {
loginDialog.login(username.text, password.text) loginDialog.login(username.text, password.text)
} }
} }
break; break
} }
} }
} }

View file

@ -5,7 +5,7 @@ import QtQuick.Controls.Styles 1.3
import QtWebKit 3.0 import QtWebKit 3.0
import "controls" import "controls"
Dialog { VrDialog {
title: "Test Dlg" title: "Test Dlg"
id: testDialog id: testDialog
objectName: "Browser" objectName: "Browser"

View file

@ -5,7 +5,7 @@ import QtQuick.Dialogs 1.2
import "controls" import "controls"
import "styles" import "styles"
Dialog { VrDialog {
id: root id: root
HifiConstants { id: hifi } HifiConstants { id: hifi }
property real spacing: hifi.layout.spacing property real spacing: hifi.layout.spacing

View file

@ -3,7 +3,7 @@ import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.3 import QtQuick.Controls.Styles 1.3
import "controls" import "controls"
Dialog { VrDialog {
title: "Test Dialog" title: "Test Dialog"
id: testDialog id: testDialog
objectName: "TestDialog" objectName: "TestDialog"

View file

@ -0,0 +1,65 @@
//
// DialogCommon.qml
//
// Created by David Rowe on 3 Jun 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 Hifi 1.0
import QtQuick 2.4
import "../styles"
Item {
id: root
property bool destroyOnInvisible: true
// The UI enables an object, rather than manipulating its visibility, so that we can do animations in both directions.
// Because visibility and enabled are booleans, they cannot be animated. So when enabled is changed, we modify a property
// that can be animated, like scale or opacity, and then when the target animation value is reached, we can modify the
// visibility.
enabled: false
opacity: 0.0
onEnabledChanged: {
opacity = enabled ? 1.0 : 0.0
}
Behavior on opacity {
// Animate opacity.
NumberAnimation {
duration: hifi.effects.fadeInDuration
easing.type: Easing.OutCubic
}
}
onOpacityChanged: {
// Once we're transparent, disable the dialog's visibility.
visible = (opacity != 0.0)
}
onVisibleChanged: {
if (!visible) {
// Some dialogs should be destroyed when they become invisible.
if (destroyOnInvisible) {
destroy()
}
}
}
Keys.onPressed: {
switch(event.key) {
case Qt.Key_W:
if (event.modifiers == Qt.ControlModifier) {
enabled = false
event.accepted = true
}
break
}
}
}

View file

@ -13,10 +13,9 @@ Item {
readonly property color hifiBlue: "#0e7077" readonly property color hifiBlue: "#0e7077"
readonly property color window: sysPalette.window readonly property color window: sysPalette.window
readonly property color dialogBackground: sysPalette.window readonly property color dialogBackground: sysPalette.window
//readonly property color dialogBackground: "#00000000"
readonly property color inputBackground: "white" readonly property color inputBackground: "white"
readonly property color background: sysPalette.dark readonly property color background: sysPalette.dark
readonly property color text: sysPalette.text readonly property color text: "#202020"
readonly property color disabledText: "gray" readonly property color disabledText: "gray"
readonly property color hintText: "gray" // A bit darker than sysPalette.dark so that it is visible on the DK2 readonly property color hintText: "gray" // A bit darker than sysPalette.dark so that it is visible on the DK2
readonly property color light: sysPalette.light readonly property color light: sysPalette.light

View file

@ -482,7 +482,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
addressManager->setPositionGetter(getPositionForPath); addressManager->setPositionGetter(getPositionForPath);
addressManager->setOrientationGetter(getOrientationForPath); addressManager->setOrientationGetter(getOrientationForPath);
connect(addressManager.data(), &AddressManager::rootPlaceNameChanged, this, &Application::updateWindowTitle); connect(addressManager.data(), &AddressManager::hostChanged, this, &Application::updateWindowTitle);
connect(this, &QCoreApplication::aboutToQuit, addressManager.data(), &AddressManager::storeCurrentAddress); connect(this, &QCoreApplication::aboutToQuit, addressManager.data(), &AddressManager::storeCurrentAddress);
#ifdef _WIN32 #ifdef _WIN32
@ -2477,8 +2477,9 @@ void Application::update(float deltaTime) {
updateThreads(deltaTime); // If running non-threaded, then give the threads some time to process... updateThreads(deltaTime); // If running non-threaded, then give the threads some time to process...
DependencyManager::get<AvatarManager>()->updateOtherAvatars(deltaTime); //loop through all the other avatars and simulate them... //loop through all the other avatars and simulate them...
DependencyManager::get<AvatarManager>()->updateOtherAvatars(deltaTime);
updateCamera(deltaTime); // handle various camera tweaks like off axis projection updateCamera(deltaTime); // handle various camera tweaks like off axis projection
updateDialogs(deltaTime); // update various stats dialogs if present updateDialogs(deltaTime); // update various stats dialogs if present
@ -2492,6 +2493,7 @@ void Application::update(float deltaTime) {
_physicsEngine.deleteObjects(_entitySimulation.getObjectsToDelete()); _physicsEngine.deleteObjects(_entitySimulation.getObjectsToDelete());
_physicsEngine.addObjects(_entitySimulation.getObjectsToAdd()); _physicsEngine.addObjects(_entitySimulation.getObjectsToAdd());
_physicsEngine.changeObjects(_entitySimulation.getObjectsToChange()); _physicsEngine.changeObjects(_entitySimulation.getObjectsToChange());
_entitySimulation.applyActionChanges();
_entitySimulation.unlock(); _entitySimulation.unlock();
AvatarManager* avatarManager = DependencyManager::get<AvatarManager>().data(); AvatarManager* avatarManager = DependencyManager::get<AvatarManager>().data();
@ -2514,7 +2516,8 @@ void Application::update(float deltaTime) {
if (!_aboutToQuit) { if (!_aboutToQuit) {
PerformanceTimer perfTimer("entities"); PerformanceTimer perfTimer("entities");
// Collision events (and their scripts) must not be handled when we're locked, above. (That would risk deadlock.) // Collision events (and their scripts) must not be handled when we're locked, above. (That would risk
// deadlock.)
_entitySimulation.handleCollisionEvents(collisionEvents); _entitySimulation.handleCollisionEvents(collisionEvents);
// NOTE: the _entities.update() call below will wait for lock // NOTE: the _entities.update() call below will wait for lock
// and will simulate entity motion (the EntityTree has been given an EntitySimulation). // and will simulate entity motion (the EntityTree has been given an EntitySimulation).
@ -2527,11 +2530,12 @@ void Application::update(float deltaTime) {
PerformanceTimer perfTimer("overlays"); PerformanceTimer perfTimer("overlays");
_overlays.update(deltaTime); _overlays.update(deltaTime);
} }
{ {
PerformanceTimer perfTimer("myAvatar"); PerformanceTimer perfTimer("myAvatar");
updateMyAvatarLookAtPosition(); updateMyAvatarLookAtPosition();
DependencyManager::get<AvatarManager>()->updateMyAvatar(deltaTime); // Sample hardware, update view frustum if needed, and send avatar data to mixer/nodes // Sample hardware, update view frustum if needed, and send avatar data to mixer/nodes
DependencyManager::get<AvatarManager>()->updateMyAvatar(deltaTime);
} }
{ {
@ -3760,7 +3764,7 @@ void Application::updateWindowTitle(){
QString connectionStatus = nodeList->getDomainHandler().isConnected() ? "" : " (NOT CONNECTED) "; QString connectionStatus = nodeList->getDomainHandler().isConnected() ? "" : " (NOT CONNECTED) ";
QString username = AccountManager::getInstance().getAccountInfo().getUsername(); QString username = AccountManager::getInstance().getAccountInfo().getUsername();
QString currentPlaceName = DependencyManager::get<AddressManager>()->getRootPlaceName(); QString currentPlaceName = DependencyManager::get<AddressManager>()->getHost();
if (currentPlaceName.isEmpty()) { if (currentPlaceName.isEmpty()) {
currentPlaceName = nodeList->getDomainHandler().getHostname(); currentPlaceName = nodeList->getDomainHandler().getHostname();

View file

@ -1,6 +1,6 @@
// //
//
// LoginDialog.cpp // LoginDialog.cpp
// interface/src/ui
// //
// Created by Bradley Austin Davis on 2015/04/14 // Created by Bradley Austin Davis on 2015/04/14
// Copyright 2015 High Fidelity, Inc. // Copyright 2015 High Fidelity, Inc.
@ -8,16 +8,22 @@
// Distributed under the Apache License, Version 2.0. // Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// //
#include "LoginDialog.h" #include "LoginDialog.h"
#include "DependencyManager.h" #include <QDesktopServices>
#include "AccountManager.h"
#include "Menu.h"
#include <NetworkingConstants.h> #include <NetworkingConstants.h>
#include "AccountManager.h"
#include "DependencyManager.h"
#include "Menu.h"
HIFI_QML_DEF(LoginDialog) HIFI_QML_DEF(LoginDialog)
LoginDialog::LoginDialog(QQuickItem *parent) : OffscreenQmlDialog(parent), _rootUrl(NetworkingConstants::METAVERSE_SERVER_URL.toString()) { LoginDialog::LoginDialog(QQuickItem *parent) : OffscreenQmlDialog(parent),
_rootUrl(NetworkingConstants::METAVERSE_SERVER_URL.toString())
{
connect(&AccountManager::getInstance(), &AccountManager::loginComplete, connect(&AccountManager::getInstance(), &AccountManager::loginComplete,
this, &LoginDialog::handleLoginCompleted); this, &LoginDialog::handleLoginCompleted);
connect(&AccountManager::getInstance(), &AccountManager::loginFailed, connect(&AccountManager::getInstance(), &AccountManager::loginFailed,
@ -48,7 +54,7 @@ void LoginDialog::handleLoginCompleted(const QUrl&) {
} }
void LoginDialog::handleLoginFailed() { void LoginDialog::handleLoginFailed() {
setStatusText("<font color = \"#267077\">Invalid username or password.< / font>"); setStatusText("Invalid username or password");
} }
void LoginDialog::setStatusText(const QString& statusText) { void LoginDialog::setStatusText(const QString& statusText) {
@ -68,10 +74,11 @@ QString LoginDialog::rootUrl() const {
void LoginDialog::login(const QString& username, const QString& password) { void LoginDialog::login(const QString& username, const QString& password) {
qDebug() << "Attempting to login " << username; qDebug() << "Attempting to login " << username;
setStatusText("Authenticating..."); setStatusText("Logging in...");
AccountManager::getInstance().requestAccessToken(username, password); AccountManager::getInstance().requestAccessToken(username, password);
} }
void LoginDialog::openUrl(const QString& url) { void LoginDialog::openUrl(const QString& url) {
qDebug() << url; qDebug() << url;
QDesktopServices::openUrl(url);
} }

View file

@ -1,5 +1,6 @@
// //
// LoginDialog.h // LoginDialog.h
// interface/src/ui
// //
// Created by Bradley Austin Davis on 2015/04/14 // Created by Bradley Austin Davis on 2015/04/14
// Copyright 2015 High Fidelity, Inc. // Copyright 2015 High Fidelity, Inc.
@ -9,6 +10,7 @@
// //
#pragma once #pragma once
#ifndef hifi_LoginDialog_h #ifndef hifi_LoginDialog_h
#define hifi_LoginDialog_h #define hifi_LoginDialog_h

View file

@ -0,0 +1,101 @@
//
// EntityActionInterface.cpp
// libraries/entities/src
//
// Created by Seth Alves on 2015-6-4
// 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
//
#include "EntityItem.h"
#include "EntityActionInterface.h"
EntityActionType EntityActionInterface::actionTypeFromString(QString actionTypeString) {
QString normalizedActionTypeString = actionTypeString.toLower().remove('-').remove('_');
if (normalizedActionTypeString == "none") {
return ACTION_TYPE_NONE;
}
if (normalizedActionTypeString == "pulltopoint") {
return ACTION_TYPE_PULL_TO_POINT;
}
qDebug() << "Warning -- EntityActionInterface::actionTypeFromString got unknown action-type name" << actionTypeString;
return ACTION_TYPE_NONE;
}
QString EntityActionInterface::actionTypeToString(EntityActionType actionType) {
switch(actionType) {
case ACTION_TYPE_NONE:
return "none";
case ACTION_TYPE_PULL_TO_POINT:
return "pullToPoint";
}
assert(false);
return "none";
}
glm::vec3 EntityActionInterface::extractVec3Argument(QString objectName, QVariantMap arguments,
QString argumentName, bool& ok) {
if (!arguments.contains(argumentName)) {
qDebug() << objectName << "requires argument:" << argumentName;
ok = false;
return vec3();
}
QVariant resultV = arguments[argumentName];
if (resultV.type() != (QVariant::Type) QMetaType::QVariantMap) {
qDebug() << objectName << "argument" << argumentName << "must be a map";
ok = false;
return vec3();
}
QVariantMap resultVM = resultV.toMap();
if (!resultVM.contains("x") || !resultVM.contains("y") || !resultVM.contains("z")) {
qDebug() << objectName << "argument" << argumentName << "must be a map with keys of x, y, z";
ok = false;
return vec3();
}
QVariant xV = resultVM["x"];
QVariant yV = resultVM["y"];
QVariant zV = resultVM["z"];
bool xOk = true;
bool yOk = true;
bool zOk = true;
float x = xV.toFloat(&xOk);
float y = yV.toFloat(&yOk);
float z = zV.toFloat(&zOk);
if (!xOk || !yOk || !zOk) {
qDebug() << objectName << "argument" << argumentName << "must be a map with keys of x, y, z and values of type float.";
ok = false;
return vec3();
}
return vec3(x, y, z);
}
float EntityActionInterface::extractFloatArgument(QString objectName, QVariantMap arguments,
QString argumentName, bool& ok) {
if (!arguments.contains(argumentName)) {
qDebug() << objectName << "requires argument:" << argumentName;
ok = false;
return 0.0f;
}
QVariant vV = arguments[argumentName];
bool vOk = true;
float v = vV.toFloat(&vOk);
if (!vOk) {
ok = false;
return 0.0f;
}
return v;
}

View file

@ -0,0 +1,49 @@
//
// EntityActionInterface.h
// libraries/entities/src
//
// Created by Seth Alves on 2015-6-2
// 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
//
#ifndef hifi_EntityActionInterface_h
#define hifi_EntityActionInterface_h
#include <QUuid>
class EntitySimulation;
enum EntityActionType {
// keep these synchronized with actionTypeFromString and actionTypeToString
ACTION_TYPE_NONE,
ACTION_TYPE_PULL_TO_POINT
};
class EntityActionInterface {
public:
EntityActionInterface() { }
virtual ~EntityActionInterface() { }
virtual const QUuid& getID() const = 0;
virtual void removeFromSimulation(EntitySimulation* simulation) const = 0;
virtual const EntityItemPointer& getOwnerEntity() const = 0;
virtual void setOwnerEntity(const EntityItemPointer ownerEntity) = 0;
virtual bool updateArguments(QVariantMap arguments) = 0;
// virtual QByteArray serialize() = 0;
// static EntityActionPointer deserialize(EntityItemPointer ownerEntity, QByteArray data);
static EntityActionType actionTypeFromString(QString actionTypeString);
static QString actionTypeToString(EntityActionType actionType);
protected:
static glm::vec3 extractVec3Argument(QString objectName, QVariantMap arguments, QString argumentName, bool& ok);
static float extractFloatArgument(QString objectName, QVariantMap arguments, QString argumentName, bool& ok);
};
typedef std::shared_ptr<EntityActionInterface> EntityActionPointer;
#endif // hifi_EntityActionInterface_h

View file

@ -25,6 +25,7 @@
#include "EntityItem.h" #include "EntityItem.h"
#include "EntitiesLogging.h" #include "EntitiesLogging.h"
#include "EntityTree.h" #include "EntityTree.h"
#include "EntitySimulation.h"
bool EntityItem::_sendPhysicsUpdates = true; bool EntityItem::_sendPhysicsUpdates = true;
@ -1334,3 +1335,46 @@ void EntityItem::updateSimulatorID(const QUuid& value) {
_dirtyFlags |= EntityItem::DIRTY_SIMULATOR_ID; _dirtyFlags |= EntityItem::DIRTY_SIMULATOR_ID;
} }
} }
bool EntityItem::addAction(EntitySimulation* simulation, EntityActionPointer action) {
assert(action);
const QUuid& actionID = action->getID();
assert(!_objectActions.contains(actionID) || _objectActions[actionID] == action);
_objectActions[actionID] = action;
assert(action->getOwnerEntity().get() == this);
simulation->addAction(action);
return false;
}
bool EntityItem::updateAction(EntitySimulation* simulation, const QUuid& actionID, const QVariantMap& arguments) {
if (!_objectActions.contains(actionID)) {
return false;
}
EntityActionPointer action = _objectActions[actionID];
return action->updateArguments(arguments);
}
bool EntityItem::removeAction(EntitySimulation* simulation, const QUuid& actionID) {
if (_objectActions.contains(actionID)) {
EntityActionPointer action = _objectActions[actionID];
_objectActions.remove(actionID);
action->setOwnerEntity(nullptr);
action->removeFromSimulation(simulation);
return true;
}
return false;
}
void EntityItem::clearActions(EntitySimulation* simulation) {
QHash<QUuid, EntityActionPointer>::iterator i = _objectActions.begin();
while (i != _objectActions.end()) {
const QUuid id = i.key();
EntityActionPointer action = _objectActions[id];
i = _objectActions.erase(i);
action->setOwnerEntity(nullptr);
action->removeFromSimulation(simulation);
}
}

View file

@ -25,9 +25,10 @@
#include <ShapeInfo.h> #include <ShapeInfo.h>
#include <Transform.h> #include <Transform.h>
#include "EntityItemID.h" #include "EntityItemID.h"
#include "EntityItemProperties.h" #include "EntityItemProperties.h"
#include "EntityItemPropertiesDefaults.h" #include "EntityItemPropertiesDefaults.h"
#include "EntityActionInterface.h"
#include "EntityTypes.h" #include "EntityTypes.h"
class EntitySimulation; class EntitySimulation;
@ -95,7 +96,7 @@ public:
}; };
DONT_ALLOW_INSTANTIATION // This class can not be instantiated directly DONT_ALLOW_INSTANTIATION // This class can not be instantiated directly
EntityItem(const EntityItemID& entityItemID); EntityItem(const EntityItemID& entityItemID);
EntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties); EntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties);
virtual ~EntityItem(); virtual ~EntityItem();
@ -107,7 +108,7 @@ public:
// methods for getting/setting all properties of an entity // methods for getting/setting all properties of an entity
virtual EntityItemProperties getProperties() const; virtual EntityItemProperties getProperties() const;
/// returns true if something changed /// returns true if something changed
virtual bool setProperties(const EntityItemProperties& properties); virtual bool setProperties(const EntityItemProperties& properties);
@ -121,7 +122,7 @@ public:
/// Last edited time of this entity universal usecs /// Last edited time of this entity universal usecs
quint64 getLastEdited() const { return _lastEdited; } quint64 getLastEdited() const { return _lastEdited; }
void setLastEdited(quint64 lastEdited) void setLastEdited(quint64 lastEdited)
{ _lastEdited = _lastUpdated = lastEdited; _changedOnServer = glm::max(lastEdited, _changedOnServer); } { _lastEdited = _lastUpdated = lastEdited; _changedOnServer = glm::max(lastEdited, _changedOnServer); }
float getEditedAgo() const /// Elapsed seconds since this entity was last edited float getEditedAgo() const /// Elapsed seconds since this entity was last edited
{ return (float)(usecTimestampNow() - getLastEdited()) / (float)USECS_PER_SECOND; } { return (float)(usecTimestampNow() - getLastEdited()) / (float)USECS_PER_SECOND; }
@ -135,26 +136,26 @@ public:
// TODO: eventually only include properties changed since the params.lastViewFrustumSent time // TODO: eventually only include properties changed since the params.lastViewFrustumSent time
virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const; virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const;
virtual OctreeElement::AppendState appendEntityData(OctreePacketData* packetData, EncodeBitstreamParams& params, virtual OctreeElement::AppendState appendEntityData(OctreePacketData* packetData, EncodeBitstreamParams& params,
EntityTreeElementExtraEncodeData* entityTreeElementExtraEncodeData) const; EntityTreeElementExtraEncodeData* entityTreeElementExtraEncodeData) const;
virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params, virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,
EntityTreeElementExtraEncodeData* entityTreeElementExtraEncodeData, EntityTreeElementExtraEncodeData* entityTreeElementExtraEncodeData,
EntityPropertyFlags& requestedProperties, EntityPropertyFlags& requestedProperties,
EntityPropertyFlags& propertyFlags, EntityPropertyFlags& propertyFlags,
EntityPropertyFlags& propertiesDidntFit, EntityPropertyFlags& propertiesDidntFit,
int& propertyCount, int& propertyCount,
OctreeElement::AppendState& appendState) const { /* do nothing*/ }; OctreeElement::AppendState& appendState) const { /* do nothing*/ };
static EntityItemID readEntityItemIDFromBuffer(const unsigned char* data, int bytesLeftToRead, static EntityItemID readEntityItemIDFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args); ReadBitstreamToTreeParams& args);
virtual int readEntityDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args); virtual int readEntityDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args);
virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
ReadBitstreamToTreeParams& args, ReadBitstreamToTreeParams& args,
EntityPropertyFlags& propertyFlags, bool overwriteLocalData) EntityPropertyFlags& propertyFlags, bool overwriteLocalData)
{ return 0; } { return 0; }
virtual bool addToScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, virtual bool addToScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene,
@ -170,7 +171,7 @@ public:
// perform update // perform update
virtual void update(const quint64& now) { _lastUpdated = now; } virtual void update(const quint64& now) { _lastUpdated = now; }
quint64 getLastUpdated() const { return _lastUpdated; } quint64 getLastUpdated() const { return _lastUpdated; }
// perform linear extrapolation for SimpleEntitySimulation // perform linear extrapolation for SimpleEntitySimulation
void simulate(const quint64& now); void simulate(const quint64& now);
void simulateKinematicMotion(float timeElapsed, bool setFlags=true); void simulateKinematicMotion(float timeElapsed, bool setFlags=true);
@ -178,10 +179,10 @@ public:
virtual bool needsToCallUpdate() const { return false; } virtual bool needsToCallUpdate() const { return false; }
virtual void debugDump() const; virtual void debugDump() const;
virtual bool supportsDetailedRayIntersection() const { return false; } virtual bool supportsDetailedRayIntersection() const { return false; }
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face,
void** intersectedObject, bool precisionPicking) const { return true; } void** intersectedObject, bool precisionPicking) const { return true; }
// attributes applicable to all entity types // attributes applicable to all entity types
@ -207,7 +208,6 @@ public:
inline const glm::vec3& getDimensions() const { return _transform.getScale(); } inline const glm::vec3& getDimensions() const { return _transform.getScale(); }
virtual void setDimensions(const glm::vec3& value); virtual void setDimensions(const glm::vec3& value);
float getGlowLevel() const { return _glowLevel; } float getGlowLevel() const { return _glowLevel; }
void setGlowLevel(float glowLevel) { _glowLevel = glowLevel; } void setGlowLevel(float glowLevel) { _glowLevel = glowLevel; }
@ -231,7 +231,7 @@ public:
const glm::vec3& getAcceleration() const { return _acceleration; } /// get acceleration in meters/second/second const glm::vec3& getAcceleration() const { return _acceleration; } /// get acceleration in meters/second/second
void setAcceleration(const glm::vec3& value) { _acceleration = value; } /// acceleration in meters/second/second void setAcceleration(const glm::vec3& value) { _acceleration = value; } /// acceleration in meters/second/second
bool hasAcceleration() const { return _acceleration != ENTITY_ITEM_ZERO_VEC3; } bool hasAcceleration() const { return _acceleration != ENTITY_ITEM_ZERO_VEC3; }
float getDamping() const { return _damping; } float getDamping() const { return _damping; }
void setDamping(float value) { _damping = value; } void setDamping(float value) { _damping = value; }
@ -253,7 +253,7 @@ public:
/// is this entity mortal, in that it has a lifetime set, and will automatically be deleted when that lifetime expires /// is this entity mortal, in that it has a lifetime set, and will automatically be deleted when that lifetime expires
bool isMortal() const { return _lifetime != ENTITY_ITEM_IMMORTAL_LIFETIME; } bool isMortal() const { return _lifetime != ENTITY_ITEM_IMMORTAL_LIFETIME; }
/// age of this entity in seconds /// age of this entity in seconds
float getAge() const { return (float)(usecTimestampNow() - _created) / (float)USECS_PER_SECOND; } float getAge() const { return (float)(usecTimestampNow() - _created) / (float)USECS_PER_SECOND; }
bool lifetimeHasExpired() const; bool lifetimeHasExpired() const;
@ -272,7 +272,7 @@ public:
const glm::vec3& getRegistrationPoint() const { return _registrationPoint; } /// registration point as ratio of entity const glm::vec3& getRegistrationPoint() const { return _registrationPoint; } /// registration point as ratio of entity
/// registration point as ratio of entity /// registration point as ratio of entity
void setRegistrationPoint(const glm::vec3& value) void setRegistrationPoint(const glm::vec3& value)
{ _registrationPoint = glm::clamp(value, 0.0f, 1.0f); } { _registrationPoint = glm::clamp(value, 0.0f, 1.0f); }
const glm::vec3& getAngularVelocity() const { return _angularVelocity; } const glm::vec3& getAngularVelocity() const { return _angularVelocity; }
@ -300,7 +300,7 @@ public:
bool getLocked() const { return _locked; } bool getLocked() const { return _locked; }
void setLocked(bool value) { _locked = value; } void setLocked(bool value) { _locked = value; }
const QString& getUserData() const { return _userData; } const QString& getUserData() const { return _userData; }
void setUserData(const QString& value) { _userData = value; } void setUserData(const QString& value) { _userData = value; }
@ -308,13 +308,13 @@ public:
void setSimulatorID(const QUuid& value); void setSimulatorID(const QUuid& value);
void updateSimulatorID(const QUuid& value); void updateSimulatorID(const QUuid& value);
quint64 getSimulatorIDChangedTime() const { return _simulatorIDChangedTime; } quint64 getSimulatorIDChangedTime() const { return _simulatorIDChangedTime; }
const QString& getMarketplaceID() const { return _marketplaceID; } const QString& getMarketplaceID() const { return _marketplaceID; }
void setMarketplaceID(const QString& value) { _marketplaceID = value; } void setMarketplaceID(const QString& value) { _marketplaceID = value; }
// TODO: get rid of users of getRadius()... // TODO: get rid of users of getRadius()...
float getRadius() const; float getRadius() const;
virtual bool contains(const glm::vec3& point) const; virtual bool contains(const glm::vec3& point) const;
virtual bool isReadyToComputeShape() { return true; } virtual bool isReadyToComputeShape() { return true; }
@ -345,11 +345,11 @@ public:
uint32_t getDirtyFlags() const { return _dirtyFlags; } uint32_t getDirtyFlags() const { return _dirtyFlags; }
void clearDirtyFlags(uint32_t mask = 0xffff) { _dirtyFlags &= ~mask; } void clearDirtyFlags(uint32_t mask = 0xffff) { _dirtyFlags &= ~mask; }
bool isMoving() const; bool isMoving() const;
void* getPhysicsInfo() const { return _physicsInfo; } void* getPhysicsInfo() const { return _physicsInfo; }
void setPhysicsInfo(void* data) { _physicsInfo = data; } void setPhysicsInfo(void* data) { _physicsInfo = data; }
EntityTreeElement* getElement() const { return _element; } EntityTreeElement* getElement() const { return _element; }
@ -365,12 +365,18 @@ public:
void getAllTerseUpdateProperties(EntityItemProperties& properties) const; void getAllTerseUpdateProperties(EntityItemProperties& properties) const;
bool addAction(EntitySimulation* simulation, EntityActionPointer action);
bool updateAction(EntitySimulation* simulation, const QUuid& actionID, const QVariantMap& arguments);
bool removeAction(EntitySimulation* simulation, const QUuid& actionID);
void clearActions(EntitySimulation* simulation);
protected: protected:
static bool _sendPhysicsUpdates; static bool _sendPhysicsUpdates;
EntityTypes::EntityType _type; EntityTypes::EntityType _type;
QUuid _id; QUuid _id;
quint64 _lastSimulated; // last time this entity called simulate(), this includes velocity, angular velocity, and physics changes quint64 _lastSimulated; // last time this entity called simulate(), this includes velocity, angular velocity,
// and physics changes
quint64 _lastUpdated; // last time this entity called update(), this includes animations and non-physics changes quint64 _lastUpdated; // last time this entity called update(), this includes animations and non-physics changes
quint64 _lastEdited; // last official local or remote edit time quint64 _lastEdited; // last official local or remote edit time
quint64 _lastBroadcast; // the last time we sent an edit packet about this entity quint64 _lastBroadcast; // the last time we sent an edit packet about this entity
@ -419,12 +425,12 @@ protected:
// //
// damping = 1 - exp(-1 / timescale) // damping = 1 - exp(-1 / timescale)
// //
// NOTE: Radius support is obsolete, but these private helper functions are available for this class to // NOTE: Radius support is obsolete, but these private helper functions are available for this class to
// parse old data streams // parse old data streams
/// set radius in domain scale units (0.0 - 1.0) this will also reset dimensions to be equal for each axis /// set radius in domain scale units (0.0 - 1.0) this will also reset dimensions to be equal for each axis
void setRadius(float value); void setRadius(float value);
// DirtyFlags are set whenever a property changes that the EntitySimulation needs to know about. // DirtyFlags are set whenever a property changes that the EntitySimulation needs to know about.
uint32_t _dirtyFlags; // things that have changed from EXTERNAL changes (via script or packet) but NOT from simulation uint32_t _dirtyFlags; // things that have changed from EXTERNAL changes (via script or packet) but NOT from simulation
@ -433,6 +439,8 @@ protected:
EntityTreeElement* _element = nullptr; // set by EntityTreeElement EntityTreeElement* _element = nullptr; // set by EntityTreeElement
void* _physicsInfo = nullptr; // set by EntitySimulation void* _physicsInfo = nullptr; // set by EntitySimulation
bool _simulated; // set by EntitySimulation bool _simulated; // set by EntitySimulation
QHash<QUuid, EntityActionPointer> _objectActions;
}; };
#endif // hifi_EntityItem_h #endif // hifi_EntityItem_h

View file

@ -11,13 +11,14 @@
#include <VariantMapToScriptValue.h> #include <VariantMapToScriptValue.h>
#include "EntityScriptingInterface.h"
#include "EntityTree.h" #include "EntityTree.h"
#include "LightEntityItem.h" #include "LightEntityItem.h"
#include "ModelEntityItem.h" #include "ModelEntityItem.h"
#include "ZoneEntityItem.h" #include "ZoneEntityItem.h"
#include "EntitiesLogging.h" #include "EntitiesLogging.h"
#include "EntitySimulation.h"
#include "EntityScriptingInterface.h"
EntityScriptingInterface::EntityScriptingInterface() : EntityScriptingInterface::EntityScriptingInterface() :
_entityTree(NULL) _entityTree(NULL)
@ -83,7 +84,8 @@ QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties
entity->setLastBroadcast(usecTimestampNow()); entity->setLastBroadcast(usecTimestampNow());
// This Node is creating a new object. If it's in motion, set this Node as the simulator. // This Node is creating a new object. If it's in motion, set this Node as the simulator.
bidForSimulationOwnership(propertiesWithSimID); bidForSimulationOwnership(propertiesWithSimID);
entity->setSimulatorID(propertiesWithSimID.getSimulatorID()); // and make note of it now, so we can act on it right away. // and make note of it now, so we can act on it right away.
entity->setSimulatorID(propertiesWithSimID.getSimulatorID());
} else { } else {
qCDebug(entities) << "script failed to add new Entity to local Octree"; qCDebug(entities) << "script failed to add new Entity to local Octree";
success = false; success = false;
@ -105,7 +107,7 @@ EntityItemProperties EntityScriptingInterface::getEntityProperties(QUuid identit
_entityTree->lockForRead(); _entityTree->lockForRead();
EntityItemPointer entity = _entityTree->findEntityByEntityItemID(EntityItemID(identity)); EntityItemPointer entity = _entityTree->findEntityByEntityItemID(EntityItemID(identity));
if (entity) { if (entity) {
results = entity->getProperties(); results = entity->getProperties();
@ -124,7 +126,7 @@ EntityItemProperties EntityScriptingInterface::getEntityProperties(QUuid identit
} }
_entityTree->unlock(); _entityTree->unlock();
} }
return results; return results;
} }
@ -228,7 +230,7 @@ QVector<QUuid> EntityScriptingInterface::findEntities(const glm::vec3& center, f
QVector<EntityItemPointer> entities; QVector<EntityItemPointer> entities;
_entityTree->findEntities(center, radius, entities); _entityTree->findEntities(center, radius, entities);
_entityTree->unlock(); _entityTree->unlock();
foreach (EntityItemPointer entity, entities) { foreach (EntityItemPointer entity, entities) {
result << entity->getEntityItemID(); result << entity->getEntityItemID();
} }
@ -244,7 +246,7 @@ QVector<QUuid> EntityScriptingInterface::findEntitiesInBox(const glm::vec3& corn
QVector<EntityItemPointer> entities; QVector<EntityItemPointer> entities;
_entityTree->findEntities(box, entities); _entityTree->findEntities(box, entities);
_entityTree->unlock(); _entityTree->unlock();
foreach (EntityItemPointer entity, entities) { foreach (EntityItemPointer entity, entities) {
result << entity->getEntityItemID(); result << entity->getEntityItemID();
} }
@ -401,7 +403,6 @@ void RayToEntityIntersectionResultFromScriptValue(const QScriptValue& object, Ra
} }
} }
bool EntityScriptingInterface::setVoxels(QUuid entityID, bool EntityScriptingInterface::setVoxels(QUuid entityID,
std::function<void(PolyVoxEntityItem&)> actor) { std::function<void(PolyVoxEntityItem&)> actor) {
if (!_entityTree) { if (!_entityTree) {
@ -439,23 +440,83 @@ bool EntityScriptingInterface::setVoxels(QUuid entityID,
return true; return true;
} }
bool EntityScriptingInterface::setVoxelSphere(QUuid entityID, const glm::vec3& center, float radius, int value) { bool EntityScriptingInterface::setVoxelSphere(QUuid entityID, const glm::vec3& center, float radius, int value) {
return setVoxels(entityID, [center, radius, value](PolyVoxEntityItem& polyVoxEntity) { return setVoxels(entityID, [center, radius, value](PolyVoxEntityItem& polyVoxEntity) {
polyVoxEntity.setSphere(center, radius, value); polyVoxEntity.setSphere(center, radius, value);
}); });
} }
bool EntityScriptingInterface::setVoxel(QUuid entityID, const glm::vec3& position, int value) { bool EntityScriptingInterface::setVoxel(QUuid entityID, const glm::vec3& position, int value) {
return setVoxels(entityID, [position, value](PolyVoxEntityItem& polyVoxEntity) { return setVoxels(entityID, [position, value](PolyVoxEntityItem& polyVoxEntity) {
polyVoxEntity.setVoxelInVolume(position, value); polyVoxEntity.setVoxelInVolume(position, value);
}); });
} }
bool EntityScriptingInterface::setAllVoxels(QUuid entityID, int value) { bool EntityScriptingInterface::setAllVoxels(QUuid entityID, int value) {
return setVoxels(entityID, [value](PolyVoxEntityItem& polyVoxEntity) { return setVoxels(entityID, [value](PolyVoxEntityItem& polyVoxEntity) {
polyVoxEntity.setAll(value); polyVoxEntity.setAll(value);
}); });
} }
bool EntityScriptingInterface::actionWorker(const QUuid& entityID,
std::function<bool(EntitySimulation*, EntityItemPointer)> actor) {
if (!_entityTree) {
return false;
}
_entityTree->lockForWrite();
EntitySimulation* simulation = _entityTree->getSimulation();
EntityItemPointer entity = _entityTree->findEntityByEntityItemID(entityID);
if (!entity) {
qDebug() << "actionWorker -- unknown entity" << entityID;
_entityTree->unlock();
return false;
}
if (!simulation) {
qDebug() << "actionWorker -- no simulation" << entityID;
_entityTree->unlock();
return false;
}
bool success = actor(simulation, entity);
_entityTree->unlock();
return success;
}
QUuid EntityScriptingInterface::addAction(const QString& actionTypeString,
const QUuid& entityID,
const QVariantMap& arguments) {
QUuid actionID = QUuid::createUuid();
bool success = actionWorker(entityID, [&](EntitySimulation* simulation, EntityItemPointer entity) {
EntityActionType actionType = EntityActionInterface::actionTypeFromString(actionTypeString);
if (actionType == ACTION_TYPE_NONE) {
return false;
}
if (simulation->actionFactory(actionType, actionID, entity, arguments)) {
return true;
}
return false;
});
if (success) {
return actionID;
}
return QUuid();
}
bool EntityScriptingInterface::updateAction(const QUuid& entityID, const QUuid& actionID, const QVariantMap& arguments) {
return actionWorker(entityID, [&](EntitySimulation* simulation, EntityItemPointer entity) {
return entity->updateAction(simulation, actionID, arguments);
});
}
bool EntityScriptingInterface::deleteAction(const QUuid& entityID, const QUuid& actionID) {
return actionWorker(entityID, [&](EntitySimulation* simulation, EntityItemPointer entity) {
return entity->removeAction(simulation, actionID);
});
}

View file

@ -54,14 +54,14 @@ class EntityScriptingInterface : public OctreeScriptingInterface, public Depende
Q_OBJECT Q_OBJECT
public: public:
EntityScriptingInterface(); EntityScriptingInterface();
EntityEditPacketSender* getEntityPacketSender() const { return (EntityEditPacketSender*)getPacketSender(); } EntityEditPacketSender* getEntityPacketSender() const { return (EntityEditPacketSender*)getPacketSender(); }
virtual NodeType_t getServerNodeType() const { return NodeType::EntityServer; } virtual NodeType_t getServerNodeType() const { return NodeType::EntityServer; }
virtual OctreeEditPacketSender* createPacketSender() { return new EntityEditPacketSender(); } virtual OctreeEditPacketSender* createPacketSender() { return new EntityEditPacketSender(); }
void setEntityTree(EntityTree* modelTree); void setEntityTree(EntityTree* modelTree);
EntityTree* getEntityTree(EntityTree*) { return _entityTree; } EntityTree* getEntityTree(EntityTree*) { return _entityTree; }
public slots: public slots:
// returns true if the DomainServer will allow this Node/Avatar to make changes // returns true if the DomainServer will allow this Node/Avatar to make changes
@ -88,11 +88,11 @@ public slots:
/// will return a EntityItemID.isKnownID = false if no models are in the radius /// will return a EntityItemID.isKnownID = false if no models are in the radius
/// this function will not find any models in script engine contexts which don't have access to models /// this function will not find any models in script engine contexts which don't have access to models
Q_INVOKABLE QUuid findClosestEntity(const glm::vec3& center, float radius) const; Q_INVOKABLE QUuid findClosestEntity(const glm::vec3& center, float radius) const;
/// finds models within the search sphere specified by the center point and radius /// finds models within the search sphere specified by the center point and radius
/// this function will not find any models in script engine contexts which don't have access to models /// this function will not find any models in script engine contexts which don't have access to models
Q_INVOKABLE QVector<QUuid> findEntities(const glm::vec3& center, float radius) const; Q_INVOKABLE QVector<QUuid> findEntities(const glm::vec3& center, float radius) const;
/// finds models within the search sphere specified by the center point and radius /// finds models within the search sphere specified by the center point and radius
/// this function will not find any models in script engine contexts which don't have access to models /// this function will not find any models in script engine contexts which don't have access to models
Q_INVOKABLE QVector<QUuid> findEntitiesInBox(const glm::vec3& corner, const glm::vec3& dimensions) const; Q_INVOKABLE QVector<QUuid> findEntitiesInBox(const glm::vec3& corner, const glm::vec3& dimensions) const;
@ -118,13 +118,16 @@ public slots:
Q_INVOKABLE void setSendPhysicsUpdates(bool value); Q_INVOKABLE void setSendPhysicsUpdates(bool value);
Q_INVOKABLE bool getSendPhysicsUpdates() const; Q_INVOKABLE bool getSendPhysicsUpdates() const;
bool setVoxels(QUuid entityID, std::function<void(PolyVoxEntityItem&)> actor);
Q_INVOKABLE bool setVoxelSphere(QUuid entityID, const glm::vec3& center, float radius, int value); Q_INVOKABLE bool setVoxelSphere(QUuid entityID, const glm::vec3& center, float radius, int value);
Q_INVOKABLE bool setVoxel(QUuid entityID, const glm::vec3& position, int value); Q_INVOKABLE bool setVoxel(QUuid entityID, const glm::vec3& position, int value);
Q_INVOKABLE bool setAllVoxels(QUuid entityID, int value); Q_INVOKABLE bool setAllVoxels(QUuid entityID, int value);
Q_INVOKABLE void dumpTree() const; Q_INVOKABLE void dumpTree() const;
Q_INVOKABLE QUuid addAction(const QString& actionTypeString, const QUuid& entityID, const QVariantMap& arguments);
Q_INVOKABLE bool updateAction(const QUuid& entityID, const QUuid& actionID, const QVariantMap& arguments);
Q_INVOKABLE bool deleteAction(const QUuid& entityID, const QUuid& actionID);
signals: signals:
void entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision); void entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision);
void collisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision); void collisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision);
@ -152,6 +155,8 @@ signals:
void clearingEntities(); void clearingEntities();
private: private:
bool actionWorker(const QUuid& entityID, std::function<bool(EntitySimulation*, EntityItemPointer)> actor);
bool setVoxels(QUuid entityID, std::function<void(PolyVoxEntityItem&)> actor);
void queueEntityMessage(PacketType packetType, EntityItemID entityID, const EntityItemProperties& properties); void queueEntityMessage(PacketType packetType, EntityItemID entityID, const EntityItemProperties& properties);
/// actually does the work of finding the ray intersection, can be called in locking mode or tryLock mode /// actually does the work of finding the ray intersection, can be called in locking mode or tryLock mode

View file

@ -24,9 +24,9 @@
typedef QSet<EntityItemPointer> SetOfEntities; typedef QSet<EntityItemPointer> SetOfEntities;
typedef QVector<EntityItemPointer> VectorOfEntities; typedef QVector<EntityItemPointer> VectorOfEntities;
// the EntitySimulation needs to know when these things change on an entity, // the EntitySimulation needs to know when these things change on an entity,
// so it can sort EntityItem or relay its state to the PhysicsEngine. // so it can sort EntityItem or relay its state to the PhysicsEngine.
const int DIRTY_SIMULATION_FLAGS = const int DIRTY_SIMULATION_FLAGS =
EntityItem::DIRTY_POSITION | EntityItem::DIRTY_POSITION |
EntityItem::DIRTY_ROTATION | EntityItem::DIRTY_ROTATION |
EntityItem::DIRTY_LINEAR_VELOCITY | EntityItem::DIRTY_LINEAR_VELOCITY |
@ -56,6 +56,15 @@ public:
friend class EntityTree; friend class EntityTree;
virtual EntityActionPointer actionFactory(EntityActionType type,
QUuid id,
EntityItemPointer ownerEntity,
QVariantMap arguments) { return nullptr; }
virtual void addAction(EntityActionPointer action) { _actionsToAdd += action; }
virtual void removeAction(const QUuid actionID) { _actionsToRemove += actionID; }
virtual void removeActions(QList<QUuid> actionIDsToRemove) { _actionsToRemove += actionIDsToRemove; }
virtual void applyActionChanges() { _actionsToAdd.clear(); _actionsToRemove.clear(); }
protected: // these only called by the EntityTree? protected: // these only called by the EntityTree?
/// \param entity pointer to EntityItem to be added /// \param entity pointer to EntityItem to be added
/// \sideeffect sets relevant backpointers in entity, but maybe later when appropriate data structures are locked /// \sideeffect sets relevant backpointers in entity, but maybe later when appropriate data structures are locked
@ -112,8 +121,12 @@ protected:
SetOfEntities _entitiesToDelete; // entities simulation decided needed to be deleted (EntityTree will actually delete) SetOfEntities _entitiesToDelete; // entities simulation decided needed to be deleted (EntityTree will actually delete)
SetOfEntities _simpleKinematicEntities; // entities undergoing non-colliding kinematic motion SetOfEntities _simpleKinematicEntities; // entities undergoing non-colliding kinematic motion
private: private:
void moveSimpleKinematics(); void moveSimpleKinematics();
protected:
QList<EntityActionPointer> _actionsToAdd;
QList<QUuid> _actionsToRemove;
}; };
#endif // hifi_EntitySimulation_h #endif // hifi_EntitySimulation_h

View file

@ -279,7 +279,7 @@ void EntityTree::setSimulation(EntitySimulation* simulation) {
if (simulation) { if (simulation) {
// assert that the simulation's backpointer has already been properly connected // assert that the simulation's backpointer has already been properly connected
assert(simulation->getEntityTree() == this); assert(simulation->getEntityTree() == this);
} }
if (_simulation && _simulation != simulation) { if (_simulation && _simulation != simulation) {
// It's important to clearEntities() on the simulation since taht will update each // It's important to clearEntities() on the simulation since taht will update each
// EntityItem::_simulationState correctly so as to not confuse the next _simulation. // EntityItem::_simulationState correctly so as to not confuse the next _simulation.
@ -381,6 +381,7 @@ void EntityTree::processRemovedEntities(const DeleteEntityOperator& theOperator)
} }
if (_simulation) { if (_simulation) {
theEntity->clearActions(_simulation);
_simulation->removeEntity(theEntity); _simulation->removeEntity(theEntity);
} }
} }

View file

@ -31,7 +31,7 @@ public:
class EntityItemFBXService { class EntityItemFBXService {
public: public:
virtual const FBXGeometry* getGeometryForEntity(EntityItemPointer entityItem) = 0; virtual const FBXGeometry* getGeometryForEntity(EntityItemPointer entityItem) = 0;
virtual const Model* getModelForEntityItem(EntityItemPointer entityItem) = 0; virtual const Model* getModelForEntityItem(EntityItemPointer entityItem) = 0;
virtual const FBXGeometry* getCollisionGeometryForEntity(EntityItemPointer entityItem) = 0; virtual const FBXGeometry* getCollisionGeometryForEntity(EntityItemPointer entityItem) = 0;
}; };
@ -63,23 +63,23 @@ public:
// own definition. Implement these to allow your octree based server to support editing // own definition. Implement these to allow your octree based server to support editing
virtual bool getWantSVOfileVersions() const { return true; } virtual bool getWantSVOfileVersions() const { return true; }
virtual PacketType expectedDataPacketType() const { return PacketTypeEntityData; } virtual PacketType expectedDataPacketType() const { return PacketTypeEntityData; }
virtual bool canProcessVersion(PacketVersion thisVersion) const virtual bool canProcessVersion(PacketVersion thisVersion) const
{ return thisVersion >= VERSION_ENTITIES_USE_METERS_AND_RADIANS; } { return thisVersion >= VERSION_ENTITIES_USE_METERS_AND_RADIANS; }
virtual bool handlesEditPacketType(PacketType packetType) const; virtual bool handlesEditPacketType(PacketType packetType) const;
virtual int processEditPacketData(PacketType packetType, const unsigned char* packetData, int packetLength, virtual int processEditPacketData(PacketType packetType, const unsigned char* packetData, int packetLength,
const unsigned char* editData, int maxLength, const SharedNodePointer& senderNode); const unsigned char* editData, int maxLength, const SharedNodePointer& senderNode);
virtual bool rootElementHasData() const { return true; } virtual bool rootElementHasData() const { return true; }
// the root at least needs to store the number of entities in the packet/buffer // the root at least needs to store the number of entities in the packet/buffer
virtual int minimumRequiredRootDataBytes() const { return sizeof(uint16_t); } virtual int minimumRequiredRootDataBytes() const { return sizeof(uint16_t); }
virtual bool suppressEmptySubtrees() const { return false; } virtual bool suppressEmptySubtrees() const { return false; }
virtual void releaseSceneEncodeData(OctreeElementExtraEncodeData* extraEncodeData) const; virtual void releaseSceneEncodeData(OctreeElementExtraEncodeData* extraEncodeData) const;
virtual bool mustIncludeAllChildData() const { return false; } virtual bool mustIncludeAllChildData() const { return false; }
virtual bool versionHasSVOfileBreaks(PacketVersion thisVersion) const virtual bool versionHasSVOfileBreaks(PacketVersion thisVersion) const
{ return thisVersion >= VERSION_ENTITIES_HAS_FILE_BREAKS; } { return thisVersion >= VERSION_ENTITIES_HAS_FILE_BREAKS; }
virtual void update(); virtual void update();
// The newer API... // The newer API...
@ -111,13 +111,13 @@ public:
/// \param foundEntities[out] vector of EntityItemPointer /// \param foundEntities[out] vector of EntityItemPointer
/// \remark Side effect: any initial contents in foundEntities will be lost /// \remark Side effect: any initial contents in foundEntities will be lost
void findEntities(const glm::vec3& center, float radius, QVector<EntityItemPointer>& foundEntities); void findEntities(const glm::vec3& center, float radius, QVector<EntityItemPointer>& foundEntities);
/// finds all entities that touch a cube /// finds all entities that touch a cube
/// \param cube the query cube in world-frame (meters) /// \param cube the query cube in world-frame (meters)
/// \param foundEntities[out] vector of non-EntityItemPointer /// \param foundEntities[out] vector of non-EntityItemPointer
/// \remark Side effect: any initial contents in entities will be lost /// \remark Side effect: any initial contents in entities will be lost
void findEntities(const AACube& cube, QVector<EntityItemPointer>& foundEntities); void findEntities(const AACube& cube, QVector<EntityItemPointer>& foundEntities);
/// finds all entities that touch a box /// finds all entities that touch a box
/// \param box the query box in world-frame (meters) /// \param box the query box in world-frame (meters)
/// \param foundEntities[out] vector of non-EntityItemPointer /// \param foundEntities[out] vector of non-EntityItemPointer
@ -129,13 +129,13 @@ public:
bool hasAnyDeletedEntities() const { return _recentlyDeletedEntityItemIDs.size() > 0; } bool hasAnyDeletedEntities() const { return _recentlyDeletedEntityItemIDs.size() > 0; }
bool hasEntitiesDeletedSince(quint64 sinceTime); bool hasEntitiesDeletedSince(quint64 sinceTime);
bool encodeEntitiesDeletedSince(OCTREE_PACKET_SEQUENCE sequenceNumber, quint64& sinceTime, bool encodeEntitiesDeletedSince(OCTREE_PACKET_SEQUENCE sequenceNumber, quint64& sinceTime,
unsigned char* packetData, size_t maxLength, size_t& outputLength); unsigned char* packetData, size_t maxLength, size_t& outputLength);
void forgetEntitiesDeletedBefore(quint64 sinceTime); void forgetEntitiesDeletedBefore(quint64 sinceTime);
int processEraseMessage(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode); int processEraseMessage(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode);
int processEraseMessageDetails(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode); int processEraseMessageDetails(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode);
EntityItemFBXService* getFBXService() const { return _fbxService; } EntityItemFBXService* getFBXService() const { return _fbxService; }
void setFBXService(EntityItemFBXService* service) { _fbxService = service; } void setFBXService(EntityItemFBXService* service) { _fbxService = service; }
const FBXGeometry* getGeometryForEntity(EntityItemPointer entityItem) { const FBXGeometry* getGeometryForEntity(EntityItemPointer entityItem) {
@ -144,7 +144,7 @@ public:
const Model* getModelForEntityItem(EntityItemPointer entityItem) { const Model* getModelForEntityItem(EntityItemPointer entityItem) {
return _fbxService ? _fbxService->getModelForEntityItem(entityItem) : NULL; return _fbxService ? _fbxService->getModelForEntityItem(entityItem) : NULL;
} }
EntityTreeElement* getContainingElement(const EntityItemID& entityItemID) /*const*/; EntityTreeElement* getContainingElement(const EntityItemID& entityItemID) /*const*/;
void setContainingElement(const EntityItemID& entityItemID, EntityTreeElement* element); void setContainingElement(const EntityItemID& entityItemID, EntityTreeElement* element);
void debugDumpMap(); void debugDumpMap();
@ -158,13 +158,14 @@ public:
void emitEntityScriptChanging(const EntityItemID& entityItemID); void emitEntityScriptChanging(const EntityItemID& entityItemID);
void setSimulation(EntitySimulation* simulation); void setSimulation(EntitySimulation* simulation);
EntitySimulation* getSimulation() const { return _simulation; }
bool wantEditLogging() const { return _wantEditLogging; } bool wantEditLogging() const { return _wantEditLogging; }
void setWantEditLogging(bool value) { _wantEditLogging = value; } void setWantEditLogging(bool value) { _wantEditLogging = value; }
bool writeToMap(QVariantMap& entityDescription, OctreeElement* element, bool skipDefaultValues); bool writeToMap(QVariantMap& entityDescription, OctreeElement* element, bool skipDefaultValues);
bool readFromMap(QVariantMap& entityDescription); bool readFromMap(QVariantMap& entityDescription);
float getContentsLargestDimension(); float getContentsLargestDimension();
signals: signals:
@ -177,7 +178,7 @@ signals:
private: private:
void processRemovedEntities(const DeleteEntityOperator& theOperator); void processRemovedEntities(const DeleteEntityOperator& theOperator);
bool updateEntityWithElement(EntityItemPointer entity, const EntityItemProperties& properties, bool updateEntityWithElement(EntityItemPointer entity, const EntityItemProperties& properties,
EntityTreeElement* containingElement, EntityTreeElement* containingElement,
const SharedNodePointer& senderNode = SharedNodePointer(nullptr)); const SharedNodePointer& senderNode = SharedNodePointer(nullptr));
static bool findNearPointOperation(OctreeElement* element, void* extraData); static bool findNearPointOperation(OctreeElement* element, void* extraData);
@ -198,7 +199,7 @@ private:
QHash<EntityItemID, EntityTreeElement*> _entityToElementMap; QHash<EntityItemID, EntityTreeElement*> _entityToElementMap;
EntitySimulation* _simulation; EntitySimulation* _simulation;
bool _wantEditLogging = false; bool _wantEditLogging = false;
void maybeNotifyNewCollisionSoundURL(const QString& oldCollisionSoundURL, const QString& newCollisionSoundURL); void maybeNotifyNewCollisionSoundURL(const QString& oldCollisionSoundURL, const QString& newCollisionSoundURL);
}; };

View file

@ -33,7 +33,7 @@ public:
_totalItems(0), _totalItems(0),
_movingItems(0) _movingItems(0)
{ } { }
QList<EntityItemPointer> _movingEntities; QList<EntityItemPointer> _movingEntities;
int _totalElements; int _totalElements;
int _totalItems; int _totalItems;
@ -42,8 +42,8 @@ public:
class EntityTreeElementExtraEncodeData { class EntityTreeElementExtraEncodeData {
public: public:
EntityTreeElementExtraEncodeData() : EntityTreeElementExtraEncodeData() :
elementCompleted(false), elementCompleted(false),
subtreeCompleted(false), subtreeCompleted(false),
entities() { entities() {
memset(childCompleted, 0, sizeof(childCompleted)); memset(childCompleted, 0, sizeof(childCompleted));
@ -140,7 +140,7 @@ public:
virtual bool canRayIntersect() const { return hasEntities(); } virtual bool canRayIntersect() const { return hasEntities(); }
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face,
void** intersectedObject, bool precisionPicking, float distanceToElementCube); void** intersectedObject, bool precisionPicking, float distanceToElementCube);
virtual bool findSpherePenetration(const glm::vec3& center, float radius, virtual bool findSpherePenetration(const glm::vec3& center, float radius,
@ -148,10 +148,11 @@ public:
const EntityItems& getEntities() const { return *_entityItems; } const EntityItems& getEntities() const { return *_entityItems; }
EntityItems& getEntities() { return *_entityItems; } EntityItems& getEntities() { return *_entityItems; }
bool hasEntities() const { return _entityItems ? _entityItems->size() > 0 : false; } bool hasEntities() const { return _entityItems ? _entityItems->size() > 0 : false; }
void setTree(EntityTree* tree) { _myTree = tree; } void setTree(EntityTree* tree) { _myTree = tree; }
EntityTree* getTree() const { return _myTree; }
bool updateEntity(const EntityItem& entity); bool updateEntity(const EntityItem& entity);
void addEntityItem(EntityItemPointer entity); void addEntityItem(EntityItemPointer entity);

View file

@ -30,7 +30,7 @@ const QString SETTINGS_CURRENT_ADDRESS_KEY = "address";
Setting::Handle<QUrl> currentAddressHandle(QStringList() << ADDRESS_MANAGER_SETTINGS_GROUP << "address", DEFAULT_HIFI_ADDRESS); Setting::Handle<QUrl> currentAddressHandle(QStringList() << ADDRESS_MANAGER_SETTINGS_GROUP << "address", DEFAULT_HIFI_ADDRESS);
AddressManager::AddressManager() : AddressManager::AddressManager() :
_rootPlaceName(), _host(),
_rootPlaceID(), _rootPlaceID(),
_positionGetter(NULL), _positionGetter(NULL),
_orientationGetter(NULL) _orientationGetter(NULL)
@ -45,7 +45,7 @@ const QUrl AddressManager::currentAddress() const {
QUrl hifiURL; QUrl hifiURL;
hifiURL.setScheme(HIFI_URL_SCHEME); hifiURL.setScheme(HIFI_URL_SCHEME);
hifiURL.setHost(_rootPlaceName); hifiURL.setHost(_host);
hifiURL.setPath(currentPath()); hifiURL.setPath(currentPath());
return hifiURL; return hifiURL;
@ -123,6 +123,10 @@ bool AddressManager::handleUrl(const QUrl& lookupUrl) {
+ (lookupUrl.port() == -1 ? "" : ":" + QString::number(lookupUrl.port())))) { + (lookupUrl.port() == -1 ? "" : ":" + QString::number(lookupUrl.port())))) {
// we may have a path that defines a relative viewpoint - if so we should jump to that now // we may have a path that defines a relative viewpoint - if so we should jump to that now
handlePath(lookupUrl.path()); handlePath(lookupUrl.path());
} else if (handleDomainID(lookupUrl.host())){
// no place name - this is probably a domain ID
// try to look up the domain ID on the metaverse API
attemptDomainIDLookup(lookupUrl.host(), lookupUrl.path());
} else { } else {
// wasn't an address - lookup the place name // wasn't an address - lookup the place name
// we may have a path that defines a relative viewpoint - pass that through the lookup so we can go to it after // we may have a path that defines a relative viewpoint - pass that through the lookup so we can go to it after
@ -161,11 +165,18 @@ void AddressManager::handleLookupString(const QString& lookupString) {
} }
} }
const QString DATA_OBJECT_DOMAIN_KEY = "domain";
void AddressManager::handleAPIResponse(QNetworkReply& requestReply) { void AddressManager::handleAPIResponse(QNetworkReply& requestReply) {
QJsonObject responseObject = QJsonDocument::fromJson(requestReply.readAll()).object(); QJsonObject responseObject = QJsonDocument::fromJson(requestReply.readAll()).object();
QJsonObject dataObject = responseObject["data"].toObject(); QJsonObject dataObject = responseObject["data"].toObject();
goToAddressFromObject(dataObject.toVariantMap(), requestReply); if (!dataObject.isEmpty()) {
goToAddressFromObject(dataObject.toVariantMap(), requestReply);
} else if (responseObject.contains(DATA_OBJECT_DOMAIN_KEY)) {
goToAddressFromObject(responseObject.toVariantMap(), requestReply);
}
emit lookupResultsFinished(); emit lookupResultsFinished();
} }
@ -180,6 +191,8 @@ void AddressManager::goToAddressFromObject(const QVariantMap& dataObject, const
QVariantMap locationMap; QVariantMap locationMap;
if (dataObject.contains(DATA_OBJECT_PLACE_KEY)) { if (dataObject.contains(DATA_OBJECT_PLACE_KEY)) {
locationMap = dataObject[DATA_OBJECT_PLACE_KEY].toMap(); locationMap = dataObject[DATA_OBJECT_PLACE_KEY].toMap();
} else if (dataObject.contains(DATA_OBJECT_DOMAIN_KEY)) {
locationMap = dataObject;
} else { } else {
locationMap = dataObject[DATA_OBJECT_USER_LOCATION_KEY].toMap(); locationMap = dataObject[DATA_OBJECT_USER_LOCATION_KEY].toMap();
} }
@ -206,6 +219,10 @@ void AddressManager::goToAddressFromObject(const QVariantMap& dataObject, const
DependencyManager::get<NodeList>()->flagTimeForConnectionStep(LimitedNodeList::ConnectionStep::HandleAddress); DependencyManager::get<NodeList>()->flagTimeForConnectionStep(LimitedNodeList::ConnectionStep::HandleAddress);
const QString DOMAIN_ID_KEY = "id";
QString domainIDString = domainObject[DOMAIN_ID_KEY].toString();
QUuid domainID(domainIDString);
if (domainObject.contains(DOMAIN_NETWORK_ADDRESS_KEY)) { if (domainObject.contains(DOMAIN_NETWORK_ADDRESS_KEY)) {
QString domainHostname = domainObject[DOMAIN_NETWORK_ADDRESS_KEY].toString(); QString domainHostname = domainObject[DOMAIN_NETWORK_ADDRESS_KEY].toString();
@ -219,10 +236,6 @@ void AddressManager::goToAddressFromObject(const QVariantMap& dataObject, const
} else { } else {
QString iceServerAddress = domainObject[DOMAIN_ICE_SERVER_ADDRESS_KEY].toString(); QString iceServerAddress = domainObject[DOMAIN_ICE_SERVER_ADDRESS_KEY].toString();
const QString DOMAIN_ID_KEY = "id";
QString domainIDString = domainObject[DOMAIN_ID_KEY].toString();
QUuid domainID(domainIDString);
qCDebug(networking) << "Possible domain change required to connect to domain with ID" << domainID qCDebug(networking) << "Possible domain change required to connect to domain with ID" << domainID
<< "via ice-server at" << iceServerAddress; << "via ice-server at" << iceServerAddress;
@ -235,8 +248,12 @@ void AddressManager::goToAddressFromObject(const QVariantMap& dataObject, const
// set our current root place name to the name that came back // set our current root place name to the name that came back
const QString PLACE_NAME_KEY = "name"; const QString PLACE_NAME_KEY = "name";
QString newRootPlaceName = rootMap[PLACE_NAME_KEY].toString(); QString placeName = rootMap[PLACE_NAME_KEY].toString();
setRootPlaceName(newRootPlaceName); if (!placeName.isEmpty()) {
setHost(placeName);
} else {
setHost(domainIDString);
}
// check if we had a path to override the path returned // check if we had a path to override the path returned
QString overridePath = reply.property(OVERRIDE_PATH_KEY).toString(); QString overridePath = reply.property(OVERRIDE_PATH_KEY).toString();
@ -304,6 +321,24 @@ void AddressManager::attemptPlaceNameLookup(const QString& lookupString, const Q
QByteArray(), NULL, requestParams); QByteArray(), NULL, requestParams);
} }
const QString GET_DOMAIN_ID = "/api/v1/domains/%1";
void AddressManager::attemptDomainIDLookup(const QString& lookupString, const QString& overridePath) {
// assume this is a domain ID and see if we can get any info on it
QString domainID = QUrl::toPercentEncoding(lookupString);
QVariantMap requestParams;
if (!overridePath.isEmpty()) {
requestParams.insert(OVERRIDE_PATH_KEY, overridePath);
}
AccountManager::getInstance().sendRequest(GET_DOMAIN_ID.arg(domainID),
AccountManagerAuth::None,
QNetworkAccessManager::GetOperation,
apiCallbackParameters(),
QByteArray(), NULL, requestParams);
}
bool AddressManager::handleNetworkAddress(const QString& lookupString) { bool AddressManager::handleNetworkAddress(const QString& lookupString) {
const QString IP_ADDRESS_REGEX_STRING = "^((?:(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}" const QString IP_ADDRESS_REGEX_STRING = "^((?:(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}"
"(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))(?::(\\d{1,5}))?$"; "(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))(?::(\\d{1,5}))?$";
@ -335,7 +370,7 @@ bool AddressManager::handleNetworkAddress(const QString& lookupString) {
quint16 domainPort = DEFAULT_DOMAIN_SERVER_PORT; quint16 domainPort = DEFAULT_DOMAIN_SERVER_PORT;
if (!hostnameRegex.cap(2).isEmpty()) { if (!hostnameRegex.cap(2).isEmpty()) {
domainPort = (qint16) hostnameRegex.cap(2).toInt(); domainPort = (qint16)hostnameRegex.cap(2).toInt();
} }
emit lookupResultsFinished(); emit lookupResultsFinished();
@ -347,6 +382,14 @@ bool AddressManager::handleNetworkAddress(const QString& lookupString) {
return false; return false;
} }
bool AddressManager::handleDomainID(const QString& host) {
const QString UUID_REGEX_STRING = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}";
QRegExp domainIDRegex(UUID_REGEX_STRING, Qt::CaseInsensitive);
return (domainIDRegex.indexIn(host) != -1);
}
void AddressManager::handlePath(const QString& path) { void AddressManager::handlePath(const QString& path) {
if (!handleViewpoint(path)) { if (!handleViewpoint(path)) {
qCDebug(networking) << "User entered path could not be handled as a viewpoint - " << path << qCDebug(networking) << "User entered path could not be handled as a viewpoint - " << path <<
@ -422,16 +465,16 @@ bool AddressManager::handleUsername(const QString& lookupString) {
return false; return false;
} }
void AddressManager::setRootPlaceName(const QString& rootPlaceName) { void AddressManager::setHost(const QString& host) {
if (rootPlaceName != _rootPlaceName) { if (host != _host) {
_rootPlaceName = rootPlaceName; _host = host;
emit rootPlaceNameChanged(_rootPlaceName); emit hostChanged(_host);
} }
} }
void AddressManager::setDomainInfo(const QString& hostname, quint16 port) { void AddressManager::setDomainInfo(const QString& hostname, quint16 port) {
_rootPlaceName = hostname; _host = hostname;
_rootPlaceID = QUuid(); _rootPlaceID = QUuid();
qCDebug(networking) << "Possible domain change required to connect to domain at" << hostname << "on" << port; qCDebug(networking) << "Possible domain change required to connect to domain at" << hostname << "on" << port;

View file

@ -35,7 +35,7 @@ class AddressManager : public QObject, public Dependency {
Q_PROPERTY(bool isConnected READ isConnected) Q_PROPERTY(bool isConnected READ isConnected)
Q_PROPERTY(QUrl href READ currentAddress) Q_PROPERTY(QUrl href READ currentAddress)
Q_PROPERTY(QString protocol READ getProtocol) Q_PROPERTY(QString protocol READ getProtocol)
Q_PROPERTY(QString hostname READ getRootPlaceName) Q_PROPERTY(QString hostname READ getHost)
Q_PROPERTY(QString pathname READ currentPath) Q_PROPERTY(QString pathname READ currentPath)
public: public:
bool isConnected(); bool isConnected();
@ -46,10 +46,11 @@ public:
const QUuid& getRootPlaceID() const { return _rootPlaceID; } const QUuid& getRootPlaceID() const { return _rootPlaceID; }
const QString& getRootPlaceName() const { return _rootPlaceName; } const QString& getHost() const { return _host; }
void setRootPlaceName(const QString& rootPlaceName); void setHost(const QString& host);
void attemptPlaceNameLookup(const QString& lookupString, const QString& overridePath = QString()); void attemptPlaceNameLookup(const QString& lookupString, const QString& overridePath = QString());
void attemptDomainIDLookup(const QString& lookupString, const QString& overridePath = QString());
void setPositionGetter(PositionGetter positionGetter) { _positionGetter = positionGetter; } void setPositionGetter(PositionGetter positionGetter) { _positionGetter = positionGetter; }
void setOrientationGetter(OrientationGetter orientationGetter) { _orientationGetter = orientationGetter; } void setOrientationGetter(OrientationGetter orientationGetter) { _orientationGetter = orientationGetter; }
@ -78,7 +79,7 @@ signals:
bool hasOrientationChange, const glm::quat& newOrientation, bool hasOrientationChange, const glm::quat& newOrientation,
bool shouldFaceLocation); bool shouldFaceLocation);
void pathChangeRequired(const QString& newPath); void pathChangeRequired(const QString& newPath);
void rootPlaceNameChanged(const QString& newRootPlaceName); void hostChanged(const QString& newHost);
protected: protected:
AddressManager(); AddressManager();
private slots: private slots:
@ -95,8 +96,9 @@ private:
void handlePath(const QString& path); void handlePath(const QString& path);
bool handleViewpoint(const QString& viewpointString, bool shouldFace = false); bool handleViewpoint(const QString& viewpointString, bool shouldFace = false);
bool handleUsername(const QString& lookupString); bool handleUsername(const QString& lookupString);
bool handleDomainID(const QString& host);
QString _rootPlaceName; QString _host;
QUuid _rootPlaceID; QUuid _rootPlaceID;
PositionGetter _positionGetter; PositionGetter _positionGetter;
OrientationGetter _orientationGetter; OrientationGetter _orientationGetter;

View file

@ -156,7 +156,7 @@ void DynamicCharacterController::playerStep(btCollisionWorld* dynaWorld, btScala
velocityCorrection -= velocityCorrection.dot(_currentUp) * _currentUp; velocityCorrection -= velocityCorrection.dot(_currentUp) * _currentUp;
} }
_rigidBody->setLinearVelocity(actualVelocity + tau * velocityCorrection); _rigidBody->setLinearVelocity(actualVelocity + tau * velocityCorrection);
} }
} }
} }

View file

@ -0,0 +1,35 @@
//
// ObjectAction.cpp
// libraries/physcis/src
//
// Created by Seth Alves 2015-6-2
// 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
//
#include "EntitySimulation.h"
#include "ObjectAction.h"
ObjectAction::ObjectAction(QUuid id, EntityItemPointer ownerEntity) :
btActionInterface(),
_id(id),
_active(false),
_ownerEntity(ownerEntity) {
}
ObjectAction::~ObjectAction() {
}
void ObjectAction::updateAction(btCollisionWorld* collisionWorld, btScalar deltaTimeStep) {
qDebug() << "ObjectAction::updateAction called";
}
void ObjectAction::debugDraw(btIDebugDraw* debugDrawer) {
}
void ObjectAction::removeFromSimulation(EntitySimulation* simulation) const {
simulation->removeAction(_id);
}

View file

@ -0,0 +1,50 @@
//
// ObjectAction.h
// libraries/physcis/src
//
// Created by Seth Alves 2015-6-2
// 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
//
// http://bulletphysics.org/Bullet/BulletFull/classbtActionInterface.html
#ifndef hifi_ObjectAction_h
#define hifi_ObjectAction_h
#include <btBulletDynamicsCommon.h>
#include <QUuid>
#include <EntityItem.h>
class ObjectAction : public btActionInterface, public EntityActionInterface {
public:
ObjectAction(QUuid id, EntityItemPointer ownerEntity);
virtual ~ObjectAction();
const QUuid& getID() const { return _id; }
virtual void removeFromSimulation(EntitySimulation* simulation) const;
virtual const EntityItemPointer& getOwnerEntity() const { return _ownerEntity; }
virtual void setOwnerEntity(const EntityItemPointer ownerEntity) { _ownerEntity = ownerEntity; }
virtual bool updateArguments(QVariantMap arguments) { return false; }
// these are from btActionInterface
virtual void updateAction(btCollisionWorld* collisionWorld, btScalar deltaTimeStep);
virtual void debugDraw(btIDebugDraw* debugDrawer);
private:
QUuid _id;
QReadWriteLock _lock;
protected:
bool tryLockForRead() { return _lock.tryLockForRead(); }
void lockForWrite() { _lock.lockForWrite(); }
void unlock() { _lock.unlock(); }
bool _active;
EntityItemPointer _ownerEntity;
};
#endif // hifi_ObjectAction_h

View file

@ -0,0 +1,69 @@
//
// ObjectActionPullToPoint.cpp
// libraries/physics/src
//
// Created by Seth Alves 2015-6-2
// 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
//
#include "ObjectMotionState.h"
#include "BulletUtil.h"
#include "ObjectActionPullToPoint.h"
ObjectActionPullToPoint::ObjectActionPullToPoint(QUuid id, EntityItemPointer ownerEntity) :
ObjectAction(id, ownerEntity) {
#if WANT_DEBUG
qDebug() << "ObjectActionPullToPoint::ObjectActionPullToPoint";
#endif
}
ObjectActionPullToPoint::~ObjectActionPullToPoint() {
#if WANT_DEBUG
qDebug() << "ObjectActionPullToPoint::~ObjectActionPullToPoint";
#endif
}
void ObjectActionPullToPoint::updateAction(btCollisionWorld* collisionWorld, btScalar deltaTimeStep) {
if (!tryLockForRead()) {
// don't risk hanging the thread running the physics simulation
return;
}
void* physicsInfo = _ownerEntity->getPhysicsInfo();
if (_active && physicsInfo) {
ObjectMotionState* motionState = static_cast<ObjectMotionState*>(physicsInfo);
btRigidBody* rigidBody = motionState->getRigidBody();
if (rigidBody) {
glm::vec3 offset = _target - bulletToGLM(rigidBody->getCenterOfMassPosition());
float offsetLength = glm::length(offset);
if (offsetLength > IGNORE_POSITION_DELTA) {
glm::vec3 newVelocity = glm::normalize(offset) * _speed;
rigidBody->setLinearVelocity(glmToBullet(newVelocity));
rigidBody->activate();
} else {
rigidBody->setLinearVelocity(glmToBullet(glm::vec3()));
}
}
}
unlock();
}
bool ObjectActionPullToPoint::updateArguments(QVariantMap arguments) {
bool ok = true;
glm::vec3 target = EntityActionInterface::extractVec3Argument("pull-to-point action", arguments, "target", ok);
float speed = EntityActionInterface::extractFloatArgument("pull-to-point action", arguments, "speed", ok);
if (ok) {
lockForWrite();
_target = target;
_speed = speed;
_active = true;
unlock();
return true;
}
return false;
}

View file

@ -0,0 +1,34 @@
//
// ObjectActionPullToPoint.h
// libraries/physics/src
//
// Created by Seth Alves 2015-6-3
// 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
//
#ifndef hifi_ObjectActionPullToPoint_h
#define hifi_ObjectActionPullToPoint_h
#include <QUuid>
#include <EntityItem.h>
#include "ObjectAction.h"
class ObjectActionPullToPoint : public ObjectAction {
public:
ObjectActionPullToPoint(QUuid id, EntityItemPointer ownerEntity);
virtual ~ObjectActionPullToPoint();
virtual bool updateArguments(QVariantMap arguments);
virtual void updateAction(btCollisionWorld* collisionWorld, btScalar deltaTimeStep);
private:
glm::vec3 _target;
float _speed;
};
#endif // hifi_ObjectActionPullToPoint_h

View file

@ -9,10 +9,12 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// //
#include "PhysicalEntitySimulation.h"
#include "PhysicsHelpers.h" #include "PhysicsHelpers.h"
#include "PhysicsLogging.h" #include "PhysicsLogging.h"
#include "ShapeManager.h" #include "ShapeManager.h"
#include "ObjectActionPullToPoint.h"
#include "PhysicalEntitySimulation.h"
PhysicalEntitySimulation::PhysicalEntitySimulation() { PhysicalEntitySimulation::PhysicalEntitySimulation() {
} }
@ -232,3 +234,37 @@ void PhysicalEntitySimulation::handleCollisionEvents(CollisionEvents& collisionE
} }
} }
EntityActionPointer PhysicalEntitySimulation::actionFactory(EntityActionType type,
QUuid id,
EntityItemPointer ownerEntity,
QVariantMap arguments) {
EntityActionPointer action = nullptr;
switch (type) {
case ACTION_TYPE_NONE:
return nullptr;
case ACTION_TYPE_PULL_TO_POINT:
action = (EntityActionPointer) new ObjectActionPullToPoint(id, ownerEntity);
break;
}
bool ok = action->updateArguments(arguments);
if (ok) {
ownerEntity->addAction(this, action);
return action;
}
action = nullptr;
return action;
}
void PhysicalEntitySimulation::applyActionChanges() {
if (_physicsEngine) {
foreach (EntityActionPointer actionToAdd, _actionsToAdd) {
_physicsEngine->addAction(actionToAdd);
}
foreach (QUuid actionToRemove, _actionsToRemove) {
_physicsEngine->removeAction(actionToRemove);
}
}
EntitySimulation::applyActionChanges();
}

View file

@ -32,6 +32,12 @@ public:
void init(EntityTree* tree, PhysicsEngine* engine, EntityEditPacketSender* packetSender); void init(EntityTree* tree, PhysicsEngine* engine, EntityEditPacketSender* packetSender);
virtual EntityActionPointer actionFactory(EntityActionType type,
QUuid id,
EntityItemPointer ownerEntity,
QVariantMap arguments);
virtual void applyActionChanges();
protected: // only called by EntitySimulation protected: // only called by EntitySimulation
// overrides for EntitySimulation // overrides for EntitySimulation
virtual void updateEntitiesInternal(const quint64& now); virtual void updateEntitiesInternal(const quint64& now);

View file

@ -436,3 +436,28 @@ int16_t PhysicsEngine::getCollisionMask(int16_t group) const {
const int16_t* mask = _collisionMasks.find(btHashInt((int)group)); const int16_t* mask = _collisionMasks.find(btHashInt((int)group));
return mask ? *mask : COLLISION_MASK_DEFAULT; return mask ? *mask : COLLISION_MASK_DEFAULT;
} }
void PhysicsEngine::addAction(EntityActionPointer action) {
assert(action);
const QUuid& actionID = action->getID();
if (_objectActions.contains(actionID)) {
assert(_objectActions[actionID] == action);
return;
}
_objectActions[actionID] = action;
// bullet needs a pointer to the action, but it doesn't use shared pointers.
// is there a way to bump the reference count?
ObjectAction* objectAction = static_cast<ObjectAction*>(action.get());
_dynamicsWorld->addAction(objectAction);
}
void PhysicsEngine::removeAction(const QUuid actionID) {
if (_objectActions.contains(actionID)) {
EntityActionPointer action = _objectActions[actionID];
ObjectAction* objectAction = static_cast<ObjectAction*>(action.get());
_dynamicsWorld->removeAction(objectAction);
_objectActions.remove(actionID);
}
}

View file

@ -24,6 +24,7 @@
#include "DynamicCharacterController.h" #include "DynamicCharacterController.h"
#include "ObjectMotionState.h" #include "ObjectMotionState.h"
#include "ThreadSafeDynamicsWorld.h" #include "ThreadSafeDynamicsWorld.h"
#include "ObjectAction.h"
const float HALF_SIMULATION_EXTENT = 512.0f; // meters const float HALF_SIMULATION_EXTENT = 512.0f; // meters
@ -93,6 +94,9 @@ public:
int16_t getCollisionMask(int16_t group) const; int16_t getCollisionMask(int16_t group) const;
void addAction(EntityActionPointer action);
void removeAction(const QUuid actionID);
private: private:
void removeContacts(ObjectMotionState* motionState); void removeContacts(ObjectMotionState* motionState);
@ -120,6 +124,9 @@ private:
QUuid _sessionID; QUuid _sessionID;
CollisionEvents _collisionEvents; CollisionEvents _collisionEvents;
QHash<QUuid, EntityActionPointer> _objectActions;
btHashMap<btHashInt, int16_t> _collisionMasks; btHashMap<btHashInt, int16_t> _collisionMasks;
}; };

View file

@ -54,7 +54,6 @@ public:
bool setScriptContents(const QString& scriptContents, const QString& fileNameString = QString("")); bool setScriptContents(const QString& scriptContents, const QString& fileNameString = QString(""));
const QString& getScriptName() const { return _scriptName; } const QString& getScriptName() const { return _scriptName; }
void cleanupMenuItems();
QScriptValue registerGlobalObject(const QString& name, QObject* object); /// registers a global object by name QScriptValue registerGlobalObject(const QString& name, QObject* object); /// registers a global object by name
void registerGetterSetter(const QString& name, QScriptEngine::FunctionSignature getter, void registerGetterSetter(const QString& name, QScriptEngine::FunctionSignature getter,