merge upstream/master into andrew/inertia

Conflicts:
	examples/grab.js
This commit is contained in:
Andrew Meadows 2015-06-08 17:28:14 -07:00
commit b682a07714
33 changed files with 1274 additions and 569 deletions

23
examples/dialTone.js Normal file
View file

@ -0,0 +1,23 @@
//
// dialTone.js
// examples
//
// Created by Stephen Birarda on 06/08/15.
// 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
//
// setup the local sound we're going to use
var connectSound = SoundCache.getSound("file://" + Paths.resources + "sounds/short1.wav");
// setup the options needed for that sound
var connectSoundOptions = {
localOnly: true
}
// play the sound locally once we get the first audio packet from a mixer
Audio.receivedFirstPacket.connect(function(){
Audio.playSound(connectSound, connectSoundOptions);
});

View file

@ -0,0 +1,89 @@
// dynamicLandscape.js
// examples
//
// Created by Eric Levin on June 8
// Copyright 2015 High Fidelity, Inc.
//
// Meditative ocean landscape
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/";
Script.include(HIFI_PUBLIC_BUCKET + 'scripts/utilities.js')
var NUM_ROWS = 10;
var CUBE_SIZE = 1;
var cubes = [];
var cubesSettings = [];
var time = 0;
var OMEGA = 2.0 * Math.PI/8;
var RANGE = CUBE_SIZE/2;
var center = Vec3.sum(MyAvatar.position, Vec3.multiply(CUBE_SIZE* 10, Quat.getFront(Camera.getOrientation())));
for (var x = 0, rowIndex = 0; x < NUM_ROWS * CUBE_SIZE; x += CUBE_SIZE, rowIndex++) {
for (var z = 0, columnIndex = 0; z < NUM_ROWS * CUBE_SIZE; z += CUBE_SIZE, columnIndex++) {
var baseHeight = map( columnIndex + 1, 1, NUM_ROWS, -CUBE_SIZE * 2, -CUBE_SIZE);
var relativePosition = {
x: x,
y: baseHeight,
z: z
};
var position = Vec3.sum(center, relativePosition);
cubes.push(Entities.addEntity({
type: 'Box',
position: position,
dimensions: {
x: CUBE_SIZE,
y: CUBE_SIZE,
z: CUBE_SIZE
}
}));
var phase = map( (columnIndex + 1) * (rowIndex + 1), 2, NUM_ROWS * NUM_ROWS, Math.PI * 2, Math.PI * 4);
cubesSettings.push({
baseHeight: center.y + baseHeight,
phase: phase
})
}
}
function update(deleteTime) {
time += deleteTime;
for (var i = 0; i < cubes.length; i++) {
var phase = cubesSettings[i].phase;
var props = Entities.getEntityProperties(cubes[i]);
var newHeight = Math.sin(time * OMEGA + phase) / 2.0;
var hue = map(newHeight, -.5, .5, 0.5, 0.7);
var light = map(newHeight, -.5, .5, 0.4, 0.6)
newHeight = cubesSettings[i].baseHeight + (newHeight * RANGE);
var newVelocityY = Math.cos(time * OMEGA + phase) / 2.0 * RANGE * OMEGA;
var newPosition = props.position;
var newVelocity = props.velocity;
newPosition.y = newHeight;
newVelocity = newVelocityY;
Entities.editEntity( cubes[i], {
position: newPosition,
velocity: props.velocity,
color: hslToRgb({hue: hue, sat: 0.7, light: light})
});
}
}
function cleanup() {
cubes.forEach(function(cube) {
Entities.deleteEntity(cube);
})
}
Script.update.connect(update);
Script.scriptEnding.connect(cleanup)

56
examples/utilities.js Normal file
View file

@ -0,0 +1,56 @@
// utilities.js
// examples
//
// Created by Eric Levin on June 8
// Copyright 2015 High Fidelity, Inc.
//
// Common utilities
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
function hslToRgb(hslColor) {
var h = hslColor.hue;
var s = hslColor.sat;
var l = hslColor.light;
var r, g, b;
if (s == 0) {
r = g = b = l; // achromatic
} else {
var hue2rgb = function hue2rgb(p, q, t) {
if (t < 0) t += 1;
if (t > 1) t -= 1;
if (t < 1 / 6) return p + (q - p) * 6 * t;
if (t < 1 / 2) return q;
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
return p;
}
var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
var p = 2 * l - q;
r = hue2rgb(p, q, h + 1 / 3);
g = hue2rgb(p, q, h);
b = hue2rgb(p, q, h - 1 / 3);
}
return {
red: Math.round(r * 255),
green: Math.round(g * 255),
blue: Math.round(b * 255)
};
}
function map(value, min1, max1, min2, max2) {
return min2 + (max2 - min2) * ((value - min1) / (max1 - min1));
}
function randFloat(low, high) {
return low + Math.random() * (high - low);
}
function randInt(low, high) {
return Math.floor(randFloat(low, high));
}

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 QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick 2.4
import "controls"
import "styles"
Item {
DialogContainer {
id: root
HifiConstants { id: hifi }
objectName: "AddressBarDialog"
property int animationDuration: hifi.effects.fadeInDuration
property bool destroyOnInvisible: false
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: {
opacity = enabled ? 1.0 : 0.0
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: {
if (!visible) {
reset()
// Some dialogs should be destroyed when they become invisible.
if (destroyOnInvisible) {
destroy()
}
addressLine.text = ""
}
}
function reset() {
addressLine.text = ""
}
function toggleOrGo() {
@ -152,21 +119,18 @@ Item {
}
}
Keys.onEscapePressed: {
enabled = false
}
Keys.onPressed: {
switch(event.key) {
case Qt.Key_W:
if (event.modifiers == Qt.ControlModifier) {
event.accepted = true
enabled = false
}
switch (event.key) {
case Qt.Key_Escape:
case Qt.Key_Back:
enabled = false
event.accepted = true
break
case Qt.Key_Enter:
case Qt.Key_Return:
toggleOrGo()
event.accepted = true
break
}
}
Keys.onReturnPressed: toggleOrGo()
Keys.onEnterPressed: toggleOrGo()
}

View file

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

View file

@ -8,27 +8,22 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import Hifi 1.0 as Hifi
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Dialogs 1.2
import Hifi 1.0
import QtQuick 2.4
import "controls"
import "styles"
Item {
DialogContainer {
id: root
HifiConstants { id: hifi }
property int animationDuration: hifi.effects.fadeInDuration
property bool destroyOnInvisible: true
Component.onCompleted: {
enabled = true
}
onParentChanged: {
if (visible && enabled) {
forceActiveFocus();
forceActiveFocus()
}
}
@ -38,7 +33,7 @@ Item {
x: parent ? parent.width / 2 - width / 2 : 0
y: parent ? parent.height / 2 - height / 2 : 0
Hifi.ErrorDialog {
ErrorDialog {
id: content
implicitWidth: box.width
@ -69,7 +64,7 @@ Item {
Text {
id: messageText
font.pointSize: 10
font.pixelSize: hifi.fonts.pixelSize * 0.6
font.weight: Font.Bold
anchors {
@ -91,55 +86,17 @@ Item {
}
MouseArea {
anchors.fill: parent
cursorShape: "PointingHandCursor"
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: {
if (event.modifiers === Qt.ControlModifier)
switch (event.key) {
case Qt.Key_W:
event.accepted = true
content.accept()
break
} else switch (event.key) {
switch (event.key) {
case Qt.Key_Escape:
case Qt.Key_Back:
case Qt.Key_Enter:

View file

@ -5,7 +5,7 @@ import QtQuick.Controls.Styles 1.3
import QtWebKit 3.0
import "controls"
Dialog {
VrDialog {
id: root
width: 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 QtQuick 2.3
import QtQuick.Controls.Styles 1.3
import QtQuick 2.4
import "controls"
import "styles"
Dialog {
DialogContainer {
id: root
HifiConstants { id: hifi }
title: "Login"
objectName: "LoginDialog"
height: 512
width: 384
onVisibleChanged: {
if (!visible) {
reset()
}
}
property bool destroyOnInvisible: false
onEnabledChanged: {
if (enabled) {
username.forceActiveFocus();
}
}
implicitWidth: loginDialog.implicitWidth
implicitHeight: loginDialog.implicitHeight
function reset() {
username.text = ""
password.text = ""
loginDialog.statusText = ""
}
x: parent ? parent.width / 2 - width / 2 : 0
y: parent ? parent.height / 2 - height / 2 : 0
property int maximumX: parent ? parent.width - width : 0
property int maximumY: parent ? parent.height - height : 0
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 {
height: 64
anchors.horizontalCenter: parent.horizontalCenter
width: 64
source: "../images/hifi-logo.svg"
implicitWidth: backgroundRectangle.width
implicitHeight: backgroundRectangle.height
readonly property int inputWidth: 500
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 {
width: 304
height: 64
anchors.horizontalCenter: parent.horizontalCenter
MouseArea {
anchors.fill: parent
cursorShape: "PointingHandCursor"
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 {
id: username
anchors.fill: parent
helperText: "Username or Email"
anchors.margins: 8
anchors {
fill: parent
leftMargin: loginDialog.inputHeight
rightMargin: loginDialog.inputHeight / 2
}
helperText: "username or email"
color: hifi.colors.text
KeyNavigation.tab: password
KeyNavigation.backtab: password
}
}
Border {
width: 304
height: 64
anchors.horizontalCenter: parent.horizontalCenter
Rectangle {
width: loginDialog.inputWidth
height: loginDialog.inputHeight
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 {
id: password
anchors.fill: parent
anchors {
fill: parent
leftMargin: loginDialog.inputHeight
rightMargin: loginDialog.inputHeight / 2
}
helperText: "password"
echoMode: TextInput.Password
helperText: "Password"
anchors.margins: 8
color: hifi.colors.text
KeyNavigation.tab: username
KeyNavigation.backtab: username
onFocusChanged: {
@ -83,102 +178,176 @@ Dialog {
}
}
Text {
anchors.horizontalCenter: parent.horizontalCenter
textFormat: Text.StyledText
width: parent.width
height: 96
wrapMode: Text.WordWrap
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
text: loginDialog.statusText
}
}
Item {
width: loginDialog.inputWidth
height: loginDialog.inputHeight / 2
Column {
anchors.bottomMargin: 5
anchors.right: parent.right
anchors.rightMargin: 0
anchors.left: parent.left
anchors.bottom: parent.bottom
Text {
id: messageText
visible: loginDialog.statusText != "" && loginDialog.statusText != "Logging in..."
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 {
width: 192
height: 64
anchors.horizontalCenter: parent.horizontalCenter
color: hifi.colors.hifiBlue
border.width: 0
radius: 10
width: loginDialog.inputWidth
height: loginDialog.inputHeight
radius: height / 2
color: "#353535"
TextInput {
anchors.fill: parent
text: "Login"
color: "white"
horizontalAlignment: Text.AlignHCenter
}
MouseArea {
anchors.bottom: parent.bottom
anchors.bottomMargin: 0
anchors.top: parent.top
anchors.right: parent.right
anchors.left: parent.left
anchors.fill: parent
cursorShape: "PointingHandCursor"
onClicked: {
loginDialog.login(username.text, password.text)
}
}
}
Row {
anchors.centerIn: parent
Row {
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
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 {
id: loginIcon
height: 32
width: 32
source: "../images/login.svg"
}
Text {
text: "Login"
color: "white"
width: 64
height: parent.height
id: hifiIcon
source: "../images/hifi-logo-blackish.svg"
width: loginDialog.inputHeight
height: width
anchors {
horizontalCenter: parent.horizontalCenter
verticalCenter: parent.verticalCenter
}
}
}
}
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 {
width: parent.width
height: 24
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
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")
MouseArea {
anchors.fill: parent
cursorShape: "PointingHandCursor"
onClicked: {
loginDialog.openUrl(loginDialog.rootUrl + "/signup")
}
}
}
}
}
}
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: {
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_Return:
if (username.activeFocus) {
@ -192,7 +361,7 @@ Dialog {
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 "controls"
Dialog {
VrDialog {
title: "Test Dlg"
id: testDialog
objectName: "Browser"

View file

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

View file

@ -3,7 +3,7 @@ import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.3
import "controls"
Dialog {
VrDialog {
title: "Test Dialog"
id: 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 window: sysPalette.window
readonly property color dialogBackground: sysPalette.window
//readonly property color dialogBackground: "#00000000"
readonly property color inputBackground: "white"
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 hintText: "gray" // A bit darker than sysPalette.dark so that it is visible on the DK2
readonly property color light: sysPalette.light

Binary file not shown.

File diff suppressed because it is too large Load diff

View file

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

View file

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

View file

@ -153,6 +153,7 @@ void AudioClient::reset() {
}
void AudioClient::audioMixerKilled() {
_hasReceivedFirstPacket = false;
_outgoingAvatarAudioSequenceNumber = 0;
_stats.reset();
}
@ -481,6 +482,7 @@ void AudioClient::start() {
qCDebug(audioclient) << "Unable to set up audio input because of a problem with input format.";
qCDebug(audioclient) << "The closest format available is" << inputDeviceInfo.nearestFormat(_desiredInputFormat);
}
if (!outputFormatSupported) {
qCDebug(audioclient) << "Unable to set up audio output because of a problem with output format.";
qCDebug(audioclient) << "The closest format available is" << outputDeviceInfo.nearestFormat(_desiredOutputFormat);
@ -489,6 +491,7 @@ void AudioClient::start() {
if (_audioInput) {
_inputFrameBuffer.initialize( _inputFormat.channelCount(), _audioInput->bufferSize() * 8 );
}
_inputGain.initialize();
_sourceGain.initialize();
_noiseSource.initialize();
@ -926,6 +929,14 @@ void AudioClient::addReceivedAudioToStream(const QByteArray& audioByteArray) {
DependencyManager::get<NodeList>()->flagTimeForConnectionStep(LimitedNodeList::ConnectionStep::ReceiveFirstAudioPacket);
if (_audioOutput) {
if (!_hasReceivedFirstPacket) {
_hasReceivedFirstPacket = true;
// have the audio scripting interface emit a signal to say we just connected to mixer
emit receivedFirstPacket();
}
// Audio output must exist and be correctly set up if we're going to process received audio
_receivedAudioStream.parseData(audioByteArray);
}

View file

@ -37,6 +37,7 @@
#include <MixedProcessedAudioStream.h>
#include <RingBufferHistory.h>
#include <SettingHandle.h>
#include <Sound.h>
#include <StDev.h>
#include "AudioIOStats.h"
@ -57,7 +58,7 @@ static const int NUM_AUDIO_CHANNELS = 2;
static const int DEFAULT_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 3;
static const int MIN_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 1;
static const int MAX_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 20;
#if defined(Q_OS_ANDROID) || defined(Q_OS_WIN)
#if defined(Q_OS_ANDROID) || defined(Q_OS_WIN)
static const int DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_ENABLED = false;
#else
static const int DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_ENABLED = true;
@ -88,14 +89,14 @@ public:
void stop() { close(); }
qint64 readData(char * data, qint64 maxSize);
qint64 writeData(const char * data, qint64 maxSize) { return 0; }
int getRecentUnfulfilledReads() { int unfulfilledReads = _unfulfilledReads; _unfulfilledReads = 0; return unfulfilledReads; }
private:
MixedProcessedAudioStream& _receivedAudioStream;
AudioClient* _audio;
int _unfulfilledReads;
};
const MixedProcessedAudioStream& getReceivedAudioStream() const { return _receivedAudioStream; }
MixedProcessedAudioStream& getReceivedAudioStream() { return _receivedAudioStream; }
@ -105,30 +106,30 @@ public:
float getAudioAverageInputLoudness() const { return _lastInputLoudness; }
int getDesiredJitterBufferFrames() const { return _receivedAudioStream.getDesiredJitterBufferFrames(); }
bool isMuted() { return _muted; }
const AudioIOStats& getStats() const { return _stats; }
float getInputRingBufferMsecsAvailable() const;
float getAudioOutputMsecsUnplayed() const;
int getOutputBufferSize() { return _outputBufferSizeFrames.get(); }
bool getOutputStarveDetectionEnabled() { return _outputStarveDetectionEnabled.get(); }
void setOutputStarveDetectionEnabled(bool enabled) { _outputStarveDetectionEnabled.set(enabled); }
int getOutputStarveDetectionPeriod() { return _outputStarveDetectionPeriodMsec.get(); }
void setOutputStarveDetectionPeriod(int msecs) { _outputStarveDetectionPeriodMsec.set(msecs); }
int getOutputStarveDetectionThreshold() { return _outputStarveDetectionThreshold.get(); }
void setOutputStarveDetectionThreshold(int threshold) { _outputStarveDetectionThreshold.set(threshold); }
void setPositionGetter(AudioPositionGetter positionGetter) { _positionGetter = positionGetter; }
void setOrientationGetter(AudioOrientationGetter orientationGetter) { _orientationGetter = orientationGetter; }
static const float CALLBACK_ACCELERATOR_RATIO;
public slots:
void start();
void stop();
@ -140,7 +141,7 @@ public slots:
void reset();
void audioMixerKilled();
void toggleMute();
virtual void enableAudioSourceInject(bool enable);
virtual void selectAudioSourcePinkNoise();
virtual void selectAudioSourceSine440();
@ -148,10 +149,10 @@ public slots:
virtual void setIsStereoInput(bool stereo);
void toggleAudioNoiseReduction() { _isNoiseGateEnabled = !_isNoiseGateEnabled; }
void toggleLocalEcho() { _shouldEchoLocally = !_shouldEchoLocally; }
void toggleServerEcho() { _shouldEchoToServer = !_shouldEchoToServer; }
void processReceivedSamples(const QByteArray& inputBuffer, QByteArray& outputBuffer);
void sendMuteEnvironmentPacket();
@ -172,10 +173,10 @@ public slots:
void setReverbOptions(const AudioEffectOptions* options);
void outputNotify();
void loadSettings();
void saveSettings();
signals:
bool muteToggled();
void inputReceived(const QByteArray& inputSamples);
@ -184,14 +185,16 @@ signals:
void deviceChanged();
void receivedFirstPacket();
protected:
AudioClient();
~AudioClient();
virtual void customDeleter() {
deleteLater();
}
private:
void outputFormatChanged();
@ -216,35 +219,35 @@ private:
QString _inputAudioDeviceName;
QString _outputAudioDeviceName;
quint64 _outputStarveDetectionStartTimeMsec;
int _outputStarveDetectionCount;
Setting::Handle<int> _outputBufferSizeFrames;
Setting::Handle<bool> _outputStarveDetectionEnabled;
Setting::Handle<int> _outputStarveDetectionPeriodMsec;
// Maximum number of starves per _outputStarveDetectionPeriod before increasing buffer size
Setting::Handle<int> _outputStarveDetectionThreshold;
StDev _stdev;
QElapsedTimer _timeSinceLastReceived;
float _averagedLatency;
float _lastInputLoudness;
float _timeSinceLastClip;
int _totalInputAudioSamples;
bool _muted;
bool _shouldEchoLocally;
bool _shouldEchoToServer;
bool _isNoiseGateEnabled;
bool _audioSourceInjectEnabled;
bool _reverb;
AudioEffectOptions _scriptReverbOptions;
AudioEffectOptions _zoneReverbOptions;
AudioEffectOptions* _reverbOptions;
ty_gverb* _gverb;
// possible soxr streams needed for resample
soxr* _inputToNetworkResampler;
soxr* _networkToOutputResampler;
@ -268,17 +271,17 @@ private:
// Input framebuffer
AudioBufferFloat32 _inputFrameBuffer;
// Input gain
AudioGain _inputGain;
// Post tone/pink noise generator gain
AudioGain _sourceGain;
// Pink noise source
bool _noiseSourceEnabled;
AudioSourcePinkNoise _noiseSource;
// Tone source
bool _toneSourceEnabled;
AudioSourceTone _toneSource;
@ -286,17 +289,19 @@ private:
quint16 _outgoingAvatarAudioSequenceNumber;
AudioOutputIODevice _audioOutputIODevice;
AudioIOStats _stats;
AudioNoiseGate _inputGate;
AudioPositionGetter _positionGetter;
AudioOrientationGetter _orientationGetter;
QVector<QString> _inputDevices;
QVector<QString> _outputDevices;
void checkDevices();
bool _hasReceivedFirstPacket = false;
};

View file

@ -26,7 +26,7 @@
AudioInjector::AudioInjector(QObject* parent) :
QObject(parent)
{
}
AudioInjector::AudioInjector(Sound* sound, const AudioInjectorOptions& injectorOptions) :
@ -39,24 +39,25 @@ AudioInjector::AudioInjector(const QByteArray& audioData, const AudioInjectorOpt
_audioData(audioData),
_options(injectorOptions)
{
}
void AudioInjector::setIsFinished(bool isFinished) {
_isFinished = isFinished;
// In all paths, regardless of isFinished argument. restart() passes false to prepare for new play, and injectToMixer() needs _shouldStop reset.
_shouldStop = false;
if (_isFinished) {
emit finished();
if (_localBuffer) {
_localBuffer->stop();
_localBuffer->deleteLater();
_localBuffer = NULL;
}
_isStarted = false;
_shouldStop = false;
if (_shouldDeleteAfterFinish) {
// we've been asked to delete after finishing, trigger a queued deleteLater here
qCDebug(audio) << "AudioInjector triggering delete from setIsFinished";
@ -67,18 +68,19 @@ void AudioInjector::setIsFinished(bool isFinished) {
void AudioInjector::injectAudio() {
if (!_isStarted) {
_isStarted = true;
// check if we need to offset the sound by some number of seconds
if (_options.secondOffset > 0.0f) {
// convert the offset into a number of bytes
int byteOffset = (int) floorf(AudioConstants::SAMPLE_RATE * _options.secondOffset * (_options.stereo ? 2.0f : 1.0f));
byteOffset *= sizeof(int16_t);
_currentSendPosition = byteOffset;
} else {
_currentSendPosition = 0;
}
if (_options.localOnly) {
injectLocally();
} else {
@ -86,12 +88,20 @@ void AudioInjector::injectAudio() {
}
} else {
qCDebug(audio) << "AudioInjector::injectAudio called but already started.";
}
}
}
void AudioInjector::restart() {
qCDebug(audio) << "Restarting an AudioInjector by stopping and starting over.";
stop();
connect(this, &AudioInjector::finished, this, &AudioInjector::restartPortionAfterFinished);
if (!_isStarted || _isFinished) {
emit finished();
} else {
stop();
}
}
void AudioInjector::restartPortionAfterFinished() {
disconnect(this, &AudioInjector::finished, this, &AudioInjector::restartPortionAfterFinished);
setIsFinished(false);
QMetaObject::invokeMethod(this, "injectAudio", Qt::QueuedConnection);
}
@ -100,37 +110,37 @@ void AudioInjector::injectLocally() {
bool success = false;
if (_localAudioInterface) {
if (_audioData.size() > 0) {
_localBuffer = new AudioInjectorLocalBuffer(_audioData, this);
_localBuffer->open(QIODevice::ReadOnly);
_localBuffer->setShouldLoop(_options.loop);
_localBuffer->setVolume(_options.volume);
// give our current send position to the local buffer
_localBuffer->setCurrentOffset(_currentSendPosition);
success = _localAudioInterface->outputLocalInjector(_options.stereo, this);
// if we're not looping and the buffer tells us it is empty then emit finished
connect(_localBuffer, &AudioInjectorLocalBuffer::bufferEmpty, this, &AudioInjector::stop);
if (!success) {
qCDebug(audio) << "AudioInjector::injectLocally could not output locally via _localAudioInterface";
}
} else {
qCDebug(audio) << "AudioInjector::injectLocally called without any data in Sound QByteArray";
}
} else {
qCDebug(audio) << "AudioInjector::injectLocally cannot inject locally with no local audio interface present.";
}
if (!success) {
// we never started so we are finished, call our stop method
stop();
}
}
const uchar MAX_INJECTOR_VOLUME = 0xFF;
@ -140,65 +150,65 @@ void AudioInjector::injectToMixer() {
_currentSendPosition >= _audioData.size()) {
_currentSendPosition = 0;
}
auto nodeList = DependencyManager::get<NodeList>();
// make sure we actually have samples downloaded to inject
if (_audioData.size()) {
// setup the packet for injected audio
QByteArray injectAudioPacket = nodeList->byteArrayWithPopulatedHeader(PacketTypeInjectAudio);
QDataStream packetStream(&injectAudioPacket, QIODevice::Append);
// pack some placeholder sequence number for now
int numPreSequenceNumberBytes = injectAudioPacket.size();
packetStream << (quint16)0;
// pack stream identifier (a generated UUID)
packetStream << QUuid::createUuid();
// pack the stereo/mono type of the stream
packetStream << _options.stereo;
// pack the flag for loopback
uchar loopbackFlag = (uchar) true;
packetStream << loopbackFlag;
// pack the position for injected audio
int positionOptionOffset = injectAudioPacket.size();
packetStream.writeRawData(reinterpret_cast<const char*>(&_options.position),
sizeof(_options.position));
// pack our orientation for injected audio
int orientationOptionOffset = injectAudioPacket.size();
packetStream.writeRawData(reinterpret_cast<const char*>(&_options.orientation),
sizeof(_options.orientation));
// pack zero for radius
float radius = 0;
packetStream << radius;
// pack 255 for attenuation byte
int volumeOptionOffset = injectAudioPacket.size();
quint8 volume = MAX_INJECTOR_VOLUME * _options.volume;
packetStream << volume;
packetStream << _options.ignorePenumbra;
QElapsedTimer timer;
timer.start();
int nextFrame = 0;
int numPreAudioDataBytes = injectAudioPacket.size();
bool shouldLoop = _options.loop;
// loop to send off our audio in NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL byte chunks
quint16 outgoingInjectedAudioSequenceNumber = 0;
while (_currentSendPosition < _audioData.size() && !_shouldStop) {
int bytesToCopy = std::min(((_options.stereo) ? 2 : 1) * AudioConstants::NETWORK_FRAME_BYTES_PER_CHANNEL,
_audioData.size() - _currentSendPosition);
// Measure the loudness of this frame
_loudness = 0.0f;
for (int i = 0; i < bytesToCopy; i += sizeof(int16_t)) {
@ -215,45 +225,45 @@ void AudioInjector::injectToMixer() {
sizeof(_options.orientation));
volume = MAX_INJECTOR_VOLUME * _options.volume;
memcpy(injectAudioPacket.data() + volumeOptionOffset, &volume, sizeof(volume));
// resize the QByteArray to the right size
injectAudioPacket.resize(numPreAudioDataBytes + bytesToCopy);
// pack the sequence number
memcpy(injectAudioPacket.data() + numPreSequenceNumberBytes,
&outgoingInjectedAudioSequenceNumber, sizeof(quint16));
// copy the next NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL bytes to the packet
memcpy(injectAudioPacket.data() + numPreAudioDataBytes,
_audioData.data() + _currentSendPosition, bytesToCopy);
// grab our audio mixer from the NodeList, if it exists
SharedNodePointer audioMixer = nodeList->soloNodeOfType(NodeType::AudioMixer);
// send off this audio packet
nodeList->writeDatagram(injectAudioPacket, audioMixer);
outgoingInjectedAudioSequenceNumber++;
_currentSendPosition += bytesToCopy;
// send two packets before the first sleep so the mixer can start playback right away
if (_currentSendPosition != bytesToCopy && _currentSendPosition < _audioData.size()) {
// process events in case we have been told to stop and be deleted
QCoreApplication::processEvents();
if (_shouldStop) {
break;
}
// not the first packet and not done
// sleep for the appropriate time
int usecToSleep = (++nextFrame * AudioConstants::NETWORK_FRAME_USECS) - timer.nsecsElapsed() / 1000;
if (usecToSleep > 0) {
usleep(usecToSleep);
}
}
}
if (shouldLoop && _currentSendPosition >= _audioData.size()) {
@ -261,13 +271,13 @@ void AudioInjector::injectToMixer() {
}
}
}
setIsFinished(true);
}
void AudioInjector::stop() {
_shouldStop = true;
if (_options.localOnly) {
// we're only a local injector, so we can say we are finished right away too
setIsFinished(true);

View file

@ -59,6 +59,7 @@ public slots:
void setCurrentSendPosition(int currentSendPosition) { _currentSendPosition = currentSendPosition; }
float getLoudness() const { return _loudness; }
bool isPlaying() const { return !_isFinished; }
void restartPortionAfterFinished();
signals:
void finished();

View file

@ -53,21 +53,25 @@ Sound::Sound(const QUrl& url, bool isStereo) :
_isStereo(isStereo),
_isReady(false)
{
}
void Sound::downloadFinished(QNetworkReply* reply) {
// replace our byte array with the downloaded data
QByteArray rawAudioByteArray = reply->readAll();
QString fileName = reply->url().fileName();
if (reply->hasRawHeader("Content-Type")) {
const QString WAV_EXTENSION = ".wav";
if (reply->hasRawHeader("Content-Type") || fileName.endsWith(WAV_EXTENSION)) {
QByteArray headerContentType = reply->rawHeader("Content-Type");
// WAV audio file encountered
if (headerContentType == "audio/x-wav"
|| headerContentType == "audio/wav"
|| headerContentType == "audio/wave") {
|| headerContentType == "audio/wave"
|| fileName.endsWith(WAV_EXTENSION)) {
QByteArray outputAudioByteArray;
@ -80,7 +84,7 @@ void Sound::downloadFinished(QNetworkReply* reply) {
_isStereo = true;
qCDebug(audio) << "Processing sound of" << rawAudioByteArray.size() << "bytes from" << reply->url() << "as stereo audio file.";
}
// Process as RAW file
downSample(rawAudioByteArray);
}
@ -88,7 +92,7 @@ void Sound::downloadFinished(QNetworkReply* reply) {
} else {
qCDebug(audio) << "Network reply without 'Content-Type'.";
}
_isReady = true;
reply->deleteLater();
}
@ -99,16 +103,16 @@ void Sound::downSample(const QByteArray& rawAudioByteArray) {
// we want to convert it to the format that the audio-mixer wants
// which is signed, 16-bit, 24Khz
int numSourceSamples = rawAudioByteArray.size() / sizeof(AudioConstants::AudioSample);
int numDestinationBytes = rawAudioByteArray.size() / sizeof(AudioConstants::AudioSample);
if (_isStereo && numSourceSamples % 2 != 0) {
numDestinationBytes += sizeof(AudioConstants::AudioSample);
}
_byteArray.resize(numDestinationBytes);
int16_t* sourceSamples = (int16_t*) rawAudioByteArray.data();
int16_t* destinationSamples = (int16_t*) _byteArray.data();
@ -134,22 +138,22 @@ void Sound::downSample(const QByteArray& rawAudioByteArray) {
}
void Sound::trimFrames() {
const uint32_t inputFrameCount = _byteArray.size() / sizeof(int16_t);
const uint32_t trimCount = 1024; // number of leading and trailing frames to trim
if (inputFrameCount <= (2 * trimCount)) {
return;
}
int16_t* inputFrameData = (int16_t*)_byteArray.data();
AudioEditBufferFloat32 editBuffer(1, inputFrameCount);
editBuffer.copyFrames(1, inputFrameCount, inputFrameData, false /*copy in*/);
editBuffer.linearFade(0, trimCount, true);
editBuffer.linearFade(inputFrameCount - trimCount, inputFrameCount, false);
editBuffer.copyFrames(1, inputFrameCount, inputFrameData, true /*copy out*/);
}
@ -238,7 +242,7 @@ void Sound::interpretAsWav(const QByteArray& inputAudioByteArray, QByteArray& ou
} else if (qFromLittleEndian<quint16>(fileHeader.wave.numChannels) > 2) {
qCDebug(audio) << "Currently not support audio files with more than 2 channels.";
}
if (qFromLittleEndian<quint16>(fileHeader.wave.bitsPerSample) != 16) {
qCDebug(audio) << "Currently not supporting non 16bit audio files.";
return;

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);
AddressManager::AddressManager() :
_rootPlaceName(),
_host(),
_rootPlaceID(),
_positionGetter(NULL),
_orientationGetter(NULL)
@ -45,7 +45,7 @@ const QUrl AddressManager::currentAddress() const {
QUrl hifiURL;
hifiURL.setScheme(HIFI_URL_SCHEME);
hifiURL.setHost(_rootPlaceName);
hifiURL.setHost(_host);
hifiURL.setPath(currentPath());
return hifiURL;
@ -123,6 +123,10 @@ bool AddressManager::handleUrl(const QUrl& lookupUrl) {
+ (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
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 {
// 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
@ -161,11 +165,18 @@ void AddressManager::handleLookupString(const QString& lookupString) {
}
}
const QString DATA_OBJECT_DOMAIN_KEY = "domain";
void AddressManager::handleAPIResponse(QNetworkReply& requestReply) {
QJsonObject responseObject = QJsonDocument::fromJson(requestReply.readAll()).object();
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();
}
@ -180,6 +191,8 @@ void AddressManager::goToAddressFromObject(const QVariantMap& dataObject, const
QVariantMap locationMap;
if (dataObject.contains(DATA_OBJECT_PLACE_KEY)) {
locationMap = dataObject[DATA_OBJECT_PLACE_KEY].toMap();
} else if (dataObject.contains(DATA_OBJECT_DOMAIN_KEY)) {
locationMap = dataObject;
} else {
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);
const QString DOMAIN_ID_KEY = "id";
QString domainIDString = domainObject[DOMAIN_ID_KEY].toString();
QUuid domainID(domainIDString);
if (domainObject.contains(DOMAIN_NETWORK_ADDRESS_KEY)) {
QString domainHostname = domainObject[DOMAIN_NETWORK_ADDRESS_KEY].toString();
@ -219,10 +236,6 @@ void AddressManager::goToAddressFromObject(const QVariantMap& dataObject, const
} else {
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
<< "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
const QString PLACE_NAME_KEY = "name";
QString newRootPlaceName = rootMap[PLACE_NAME_KEY].toString();
setRootPlaceName(newRootPlaceName);
QString placeName = rootMap[PLACE_NAME_KEY].toString();
if (!placeName.isEmpty()) {
setHost(placeName);
} else {
setHost(domainIDString);
}
// check if we had a path to override the path returned
QString overridePath = reply.property(OVERRIDE_PATH_KEY).toString();
@ -304,6 +321,24 @@ void AddressManager::attemptPlaceNameLookup(const QString& lookupString, const Q
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) {
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}))?$";
@ -335,7 +370,7 @@ bool AddressManager::handleNetworkAddress(const QString& lookupString) {
quint16 domainPort = DEFAULT_DOMAIN_SERVER_PORT;
if (!hostnameRegex.cap(2).isEmpty()) {
domainPort = (qint16) hostnameRegex.cap(2).toInt();
domainPort = (qint16)hostnameRegex.cap(2).toInt();
}
emit lookupResultsFinished();
@ -347,6 +382,14 @@ bool AddressManager::handleNetworkAddress(const QString& lookupString) {
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) {
if (!handleViewpoint(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;
}
void AddressManager::setRootPlaceName(const QString& rootPlaceName) {
if (rootPlaceName != _rootPlaceName) {
_rootPlaceName = rootPlaceName;
emit rootPlaceNameChanged(_rootPlaceName);
void AddressManager::setHost(const QString& host) {
if (host != _host) {
_host = host;
emit hostChanged(_host);
}
}
void AddressManager::setDomainInfo(const QString& hostname, quint16 port) {
_rootPlaceName = hostname;
_host = hostname;
_rootPlaceID = QUuid();
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(QUrl href READ currentAddress)
Q_PROPERTY(QString protocol READ getProtocol)
Q_PROPERTY(QString hostname READ getRootPlaceName)
Q_PROPERTY(QString hostname READ getHost)
Q_PROPERTY(QString pathname READ currentPath)
public:
bool isConnected();
@ -46,10 +46,11 @@ public:
const QUuid& getRootPlaceID() const { return _rootPlaceID; }
const QString& getRootPlaceName() const { return _rootPlaceName; }
void setRootPlaceName(const QString& rootPlaceName);
const QString& getHost() const { return _host; }
void setHost(const QString& host);
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 setOrientationGetter(OrientationGetter orientationGetter) { _orientationGetter = orientationGetter; }
@ -78,7 +79,7 @@ signals:
bool hasOrientationChange, const glm::quat& newOrientation,
bool shouldFaceLocation);
void pathChangeRequired(const QString& newPath);
void rootPlaceNameChanged(const QString& newRootPlaceName);
void hostChanged(const QString& newHost);
protected:
AddressManager();
private slots:
@ -95,8 +96,9 @@ private:
void handlePath(const QString& path);
bool handleViewpoint(const QString& viewpointString, bool shouldFace = false);
bool handleUsername(const QString& lookupString);
bool handleDomainID(const QString& host);
QString _rootPlaceName;
QString _host;
QUuid _rootPlaceID;
PositionGetter _positionGetter;
OrientationGetter _orientationGetter;

View file

@ -28,19 +28,19 @@ AudioScriptingInterface& AudioScriptingInterface::getInstance() {
AudioScriptingInterface::AudioScriptingInterface() :
_localAudioInterface(NULL)
{
}
ScriptAudioInjector* AudioScriptingInterface::playSound(Sound* sound, const AudioInjectorOptions& injectorOptions) {
if (QThread::currentThread() != thread()) {
ScriptAudioInjector* injector = NULL;
QMetaObject::invokeMethod(this, "playSound", Qt::BlockingQueuedConnection,
Q_RETURN_ARG(ScriptAudioInjector*, injector),
Q_ARG(Sound*, sound), Q_ARG(const AudioInjectorOptions&, injectorOptions));
return injector;
}
if (sound) {
// stereo option isn't set from script, this comes from sound metadata or filename
AudioInjectorOptions optionsCopy = injectorOptions;

View file

@ -22,22 +22,23 @@ class AudioScriptingInterface : public QObject {
Q_OBJECT
public:
static AudioScriptingInterface& getInstance();
void setLocalAudioInterface(AbstractAudioInterface* audioInterface) { _localAudioInterface = audioInterface; }
protected:
// this method is protected to stop C++ callers from calling, but invokable from script
Q_INVOKABLE ScriptAudioInjector* playSound(Sound* sound, const AudioInjectorOptions& injectorOptions = AudioInjectorOptions());
Q_INVOKABLE void injectGeneratedNoise(bool inject);
Q_INVOKABLE void selectPinkNoise();
Q_INVOKABLE void selectSine440();
Q_INVOKABLE void setStereoInput(bool stereo);
signals:
void mutedByMixer();
void environmentMuted();
void receivedFirstPacket();
private:
AudioScriptingInterface();

View file

@ -18,7 +18,7 @@
#include "PathUtils.h"
QString& PathUtils::resourcesPath() {
const QString& PathUtils::resourcesPath() {
#ifdef Q_OS_MAC
static QString staticResourcePath = QCoreApplication::applicationDirPath() + "/../Resources/";
#else

View file

@ -12,12 +12,17 @@
#ifndef hifi_PathUtils_h
#define hifi_PathUtils_h
#include <QtCore/QObject>
#include <QString>
#include "DependencyManager.h"
namespace PathUtils {
QString& resourcesPath();
}
class PathUtils : public QObject, public Dependency {
Q_OBJECT
SINGLETON_DEPENDENCY
Q_PROPERTY(QString resources READ resourcesPath)
public:
static const QString& resourcesPath();
};
QString fileNameWithoutExtension(const QString& fileName, const QVector<QString> possibleExtensions);
QString findMostRecentFileExtension(const QString& originalFileName, QVector<QString> possibleExtensions);