mirror of
https://github.com/lubosz/overte.git
synced 2025-04-23 13:33:38 +02:00
merge upstream/master into andrew/inertia
Conflicts: examples/grab.js
This commit is contained in:
commit
b682a07714
33 changed files with 1274 additions and 569 deletions
23
examples/dialTone.js
Normal file
23
examples/dialTone.js
Normal 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);
|
||||
});
|
89
examples/example/dynamicLandscape.js
Normal file
89
examples/example/dynamicLandscape.js
Normal 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
56
examples/utilities.js
Normal 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));
|
||||
}
|
123
interface/resources/images/hifi-logo-blackish.svg
Normal file
123
interface/resources/images/hifi-logo-blackish.svg
Normal 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 |
55
interface/resources/images/login-close.svg
Normal file
55
interface/resources/images/login-close.svg
Normal 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 |
58
interface/resources/images/login-password.svg
Normal file
58
interface/resources/images/login-password.svg
Normal 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 |
51
interface/resources/images/login-username.svg
Normal file
51
interface/resources/images/login-username.svg
Normal 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 |
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import QtWebKit 3.0
|
|||
import "controls"
|
||||
import "styles"
|
||||
|
||||
Dialog {
|
||||
VrDialog {
|
||||
id: root
|
||||
HifiConstants { id: hifi }
|
||||
title: "Browser"
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -5,7 +5,7 @@ import QtQuick.Controls.Styles 1.3
|
|||
import QtWebKit 3.0
|
||||
import "controls"
|
||||
|
||||
Dialog {
|
||||
VrDialog {
|
||||
id: root
|
||||
width: 800
|
||||
height: 800
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
65
interface/resources/qml/controls/DialogContainer.qml
Normal file
65
interface/resources/qml/controls/DialogContainer.qml
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
BIN
interface/resources/sounds/short1.wav
Normal file
BIN
interface/resources/sounds/short1.wav
Normal file
Binary file not shown.
File diff suppressed because it is too large
Load diff
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue