Merge branch 'master' of https://github.com/highfidelity/hifi into team-teaching

This commit is contained in:
ZappoMan 2015-06-01 14:42:35 -07:00
commit d4af454834
44 changed files with 1264 additions and 381 deletions

View file

@ -75,21 +75,6 @@ To prevent these problems, install OpenSSL yourself. Download the following bina
Install OpenSSL into the Windows system directory, to make sure that Qt uses the version that you've just installed, and not some other version.
###vhacd
Download it directly from https://github.com/virneo/v-hacd
To build it run the following commands
1. cd src\
2. mkdir build
3. cd build
4. cmake ..
Build using visual studio 2013. Build ALL_BUILD and INSTALL targets both in Release and Debug.
This will create an output folder with include and lib directory inside it.
Either copy the contents of output folder to ENV %HIFI_LIB_DIR%/vhacd or create an environment variable VHACD_ROOT_DIR to this output directory.
###Build High Fidelity using Visual Studio
Follow the same build steps from the CMake section of [BUILD.md](BUILD.md), but pass a different generator to CMake.

View file

@ -178,9 +178,13 @@ option(GET_GVERB "Get Gverb library automatically as external project" 1)
option(GET_SOXR "Get Soxr library automatically as external project" 1)
option(GET_TBB "Get Threading Building Blocks library automatically as external project" 1)
option(GET_LIBOVR "Get LibOVR library automatically as external project" 1)
option(USE_NSIGHT "Attempt to find the nSight libraries" 1)
option(GET_VHACD "Get V-HACD library automatically as external project" 1)
option(GET_POLYVOX "Get polyvox library automatically as external project" 1)
option(GET_OPENVR "Get OpenVR library automatically as external project" 1)
option(GET_BOOSTCONFIG "Get Boost-config library automatically as external project" 1)
option(GET_OGLPLUS "Get OGLplus library automatically as external project" 1)
option(USE_NSIGHT "Attempt to find the nSight libraries" 1)
if (WIN32)
option(GET_GLEW "Get GLEW library automatically as external project" 1)

View file

@ -0,0 +1,18 @@
set(EXTERNAL_NAME boostconfig)
string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
include(ExternalProject)
ExternalProject_Add(
${EXTERNAL_NAME}
URL https://github.com/boostorg/config/archive/boost-1.58.0.zip
URL_MD5 42fa673bae2b7645a22736445e80eb8d
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
LOG_DOWNLOAD 1
)
ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR)
set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include CACHE TYPE INTERNAL)

18
cmake/externals/oglplus/CMakeLists.txt vendored Normal file
View file

@ -0,0 +1,18 @@
set(EXTERNAL_NAME oglplus)
string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
include(ExternalProject)
ExternalProject_Add(
${EXTERNAL_NAME}
URL http://softlayer-dal.dl.sourceforge.net/project/oglplus/oglplus-0.61.x/oglplus-0.61.0.zip
URL_MD5 bb55038c36c660d2b6c7be380414fa60
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
LOG_DOWNLOAD 1
)
ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR)
set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include ${SOURCE_DIR}/implement CACHE TYPE INTERNAL)

View file

@ -7,8 +7,8 @@ string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
ExternalProject_Add(
${EXTERNAL_NAME}
URL https://github.com/ValveSoftware/openvr/archive/0.9.0.zip
URL_MD5 4fbde7759f604aaa68b9c40d628cc34a
URL https://github.com/ValveSoftware/openvr/archive/0.9.1.zip
URL_MD5 f986f5a6815e9454c53c5bf58ce02fdc
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""

View file

@ -0,0 +1,24 @@
#
# Try to find BOOSTCONFIG include path.
# Once done this will define
#
# BOOSTCONFIG_INCLUDE_DIRS
#
# Created by Bradley Austin Davis on 2015/05/22
# 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 hints for BOOSTCONFIG search
include("${MACRO_DIR}/HifiLibrarySearchHints.cmake")
hifi_library_search_hints("BOOSTCONFIG")
# locate header
find_path(BOOSTCONFIG_INCLUDE_DIRS "boost/config.hpp" HINTS ${BOOSTCONFIG_SEARCH_DIRS})
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(BOOSTCONFIG DEFAULT_MSG BOOSTCONFIG_INCLUDE_DIRS)
mark_as_advanced(BOOSTCONFIG_INCLUDE_DIRS BOOSTCONFIG_SEARCH_DIRS)

View file

@ -0,0 +1,24 @@
#
# Try to find OGLPLUS include path.
# Once done this will define
#
# OGLPLUS_INCLUDE_DIRS
#
# Created by Bradley Austin Davis on 2015/05/22
# 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 hints for OGLPLUS search
include("${MACRO_DIR}/HifiLibrarySearchHints.cmake")
hifi_library_search_hints("oglplus")
# locate header
find_path(OGLPLUS_INCLUDE_DIRS "oglplus/fwd.hpp" HINTS ${OGLPLUS_SEARCH_DIRS})
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(OGLPLUS DEFAULT_MSG OGLPLUS_INCLUDE_DIRS)
mark_as_advanced(OGLPLUS_INCLUDE_DIRS OGLPLUS_SEARCH_DIRS)

View file

@ -0,0 +1,247 @@
var HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/";
var SOUND_PATH = HIFI_PUBLIC_BUCKET + "sounds/Collisions-hitsandslaps/";
var soundURLS = ["67LCollision01.wav", "67LCollision02.wav", "airhockey_hit1.wav"];
var FLOOR_SIZE = 10;
var center = Vec3.sum(MyAvatar.position, Vec3.multiply(FLOOR_SIZE * 1.5, Quat.getFront(Camera.getOrientation())));
var WALL_WIDTH = .1;
var FLOOR_HEIGHT_OFFSET = -2;
var WALL_HEIGHT = FLOOR_SIZE / 4;
var BALL_DROP_HEIGHT = center.y + WALL_HEIGHT;
var NUM_BALLS = 50;
var BALL_RADIUS = 1;
var BROWNIAN_INTERVAL_TIME = 16;
var BROWNIAN_FORCE_RANGE = 5;
var SPAWN_TIME = 50;
var spawnCount = 0;
var brownianMotionActivated = false;
var buttonOffColor = {
red: 250,
green: 10,
blue: 10
};
var buttonOnColor = {
red: 10,
green: 200,
blue: 100
};
var bounds = {
xMin: center.x - FLOOR_SIZE / 2,
xMax: center.x + FLOOR_SIZE / 2,
zMin: center.z - FLOOR_SIZE / 2,
zMax: center.z + FLOOR_SIZE / 2
};
var balls = [];
var screenSize = Controller.getViewportDimensions();
var BUTTON_SIZE = 32;
var PADDING = 3;
var brownianButton = Overlays.addOverlay("image", {
x: screenSize.x / 2 - BUTTON_SIZE,
y: screenSize.y - (BUTTON_SIZE + PADDING),
width: BUTTON_SIZE,
height: BUTTON_SIZE,
imageURL: HIFI_PUBLIC_BUCKET + "images/blocks.png",
color: buttonOffColor,
alpha: 1
});
var floor = Entities.addEntity({
type: 'Box',
position: Vec3.sum(center, {
x: 0,
y: FLOOR_HEIGHT_OFFSET,
z: 0
}),
dimensions: {
x: FLOOR_SIZE,
y: WALL_WIDTH,
z: FLOOR_SIZE
},
color: {
red: 100,
green: 100,
blue: 100
}
});
var rightWall = Entities.addEntity({
type: 'Box',
position: Vec3.sum(center, {
x: FLOOR_SIZE / 2,
y: FLOOR_HEIGHT_OFFSET / 2,
z: 0
}),
dimensions: {
x: WALL_WIDTH,
y: WALL_HEIGHT,
z: FLOOR_SIZE
},
color: {
red: 120,
green: 100,
blue: 120
}
});
var leftWall = Entities.addEntity({
type: 'Box',
position: Vec3.sum(center, {
x: -FLOOR_SIZE / 2,
y: FLOOR_HEIGHT_OFFSET / 2,
z: 0
}),
dimensions: {
x: WALL_WIDTH,
y: WALL_HEIGHT,
z: FLOOR_SIZE
},
color: {
red: 120,
green: 100,
blue: 120
}
});
var backWall = Entities.addEntity({
type: 'Box',
position: Vec3.sum(center, {
x: 0,
y: FLOOR_HEIGHT_OFFSET / 2,
z: -FLOOR_SIZE / 2,
}),
dimensions: {
x: FLOOR_SIZE,
y: WALL_HEIGHT,
z: WALL_WIDTH
},
color: {
red: 120,
green: 100,
blue: 120
}
});
var frontWall = Entities.addEntity({
type: 'Box',
position: Vec3.sum(center, {
x: 0,
y: FLOOR_HEIGHT_OFFSET / 2,
z: FLOOR_SIZE / 2,
}),
dimensions: {
x: FLOOR_SIZE,
y: WALL_HEIGHT,
z: WALL_WIDTH
},
color: {
red: 120,
green: 100,
blue: 120
}
});
var spawnInterval = Script.setInterval(spawnBalls, SPAWN_TIME);
function spawnBalls() {
balls.push(Entities.addEntity({
type: "Sphere",
shapeType: "sphere",
position: {
x: randFloat(bounds.xMin, bounds.xMax),
y: BALL_DROP_HEIGHT,
z: randFloat(bounds.zMin, bounds.zMax)
},
dimensions: {
x: BALL_RADIUS,
y: BALL_RADIUS,
z: BALL_RADIUS
},
color: {
red: randFloat(100, 150),
green: randFloat(20, 80),
blue: randFloat(10, 180)
},
ignoreCollisions: false,
collisionsWillMove: true,
gravity: {
x: 0,
y: -9.9,
z: 0
},
velocity: {
x: 0,
y: -.25,
z: 0
},
collisionSoundURL: SOUND_PATH + soundURLS[randInt(0, soundURLS.length - 1)]
}));
spawnCount++;
if (spawnCount === NUM_BALLS) {
Script.clearInterval(spawnInterval);
}
}
function mousePressEvent(event) {
var clickedOverlay = Overlays.getOverlayAtPoint({
x: event.x,
y: event.y
});
if (clickedOverlay == brownianButton) {
brownianMotionActivated = !brownianMotionActivated;
if (brownianMotionActivated) {
brownianInterval = Script.setInterval(bumpBalls, BROWNIAN_INTERVAL_TIME);
Overlays.editOverlay(brownianButton, {
color: buttonOnColor
})
} else {
Script.clearInterval(brownianInterval);
Overlays.editOverlay(brownianButton, {
color: buttonOffColor
})
}
}
}
function bumpBalls() {
balls.forEach(function(ball) {
var props = Entities.getEntityProperties(ball);
var newVelocity = Vec3.sum(props.velocity, {
x: (Math.random() - 0.5) * BROWNIAN_FORCE_RANGE,
y: 0,
z: (Math.random() - 0.5) * BROWNIAN_FORCE_RANGE
});
Entities.editEntity(ball, {
velocity: newVelocity
});
});
}
function cleanup() {
Entities.deleteEntity(floor);
Entities.deleteEntity(rightWall);
Entities.deleteEntity(leftWall);
Entities.deleteEntity(backWall);
Entities.deleteEntity(frontWall);
balls.forEach(function(ball) {
Entities.deleteEntity(ball);
});
Overlays.deleteOverlay(brownianButton);
}
function randFloat(low, high) {
return Math.floor(low + Math.random() * (high - low));
}
function randInt(low, high) {
return Math.floor(randFloat(low, high));
}
Script.scriptEnding.connect(cleanup);
Script.scriptEnding.connect(cleanup);
Controller.mousePressEvent.connect(mousePressEvent);

View file

@ -29,31 +29,38 @@ var tablePosition = {
z: 0
}
var isGrabbing = false;
var isGrabbingPaddle = false;
var grabbedEntity = null;
var prevMouse = {};
var prevMouse = {x: 0, y: 0};
var deltaMouse = {
z: 0
}
var MAX_GRAB_DISTANCE = 100;
var TABLE_SEARCH_RANGE = 10;
var entityProps;
var moveUpDown = false;
var CLOSE_ENOUGH = 0.001;
var FULL_STRENGTH = 1.0;
var SPRING_RATE = 1.5;
var SPRING_TIMESCALE = 0.05;
var ANGULAR_SPRING_TIMESCALE = 0.03;
var DAMPING_RATE = 0.80;
var ANGULAR_DAMPING_RATE = 0.40;
var SCREEN_TO_METERS = 0.001;
var currentPosition, currentVelocity, cameraEntityDistance, currentRotation;
var grabHeight;
var initialVerticalGrabPosition;
var MAX_VERTICAL_ANGLE = Math.PI / 3;
var MIN_VERTICAL_ANGLE = - MAX_VERTICAL_ANGLE;
var velocityTowardTarget, desiredVelocity, addedVelocity, newVelocity, dPosition, camYaw, distanceToTarget, targetPosition;
var grabOffset;
var originalGravity = {
x: 0,
y: 0,
z: 0
};
var shouldRotate = false;
var dQ, theta, axisAngle, dT;
var dQ, dT;
var angularVelocity = {
x: 0,
y: 0,
@ -94,6 +101,34 @@ function nearLinePoint(targetPosition) {
return Vec3.sum(handPosition, along);
}
function xzPickRayIntersetion(pointOnPlane, mouseX, mouseY) {
var relativePoint = Vec3.subtract(pointOnPlane, Camera.getPosition());
var pickRay = Camera.computePickRay(mouseX, mouseY);
if (Math.abs(pickRay.direction.y) > 0.001) {
var distance = relativePoint.y / pickRay.direction.y;
if (distance < 0.001) {
return pointOnPlane;
}
var pickInersection = Vec3.multiply(pickRay.direction, distance);
pickInersection = Vec3.sum(Camera.getPosition(), pickInersection);
return pickInersection;
}
// point and line are more-or-less co-planar: compute closest approach of pickRay and pointOnPlane
var distance = Vec3.dot(relativePoint, pickRay.direction);
var pickInersection = Vec3.multiply(pickRay.direction, distance);
return pickInersection;
}
function forwardPickRayIntersection(pointOnPlane, mouseX, mouseY) {
var relativePoint = Vec3.subtract(pointOnPlane, Camera.getPosition());
var pickRay = Camera.computePickRay(mouseX, mouseY);
var planeNormal = Quat.getFront(Camera.getOrientation());
var distance = Vec3.dot(planeNormal, relativePoint);
var rayDistance = Vec3.dot(planeNormal, pickRay.direction);
var pickIntersection = Vec3.multiply(pickRay.direction, distance / rayDistance);
pickIntersection = Vec3.sum(pickIntersection, Camera.getPosition())
return pickIntersection;
}
function mousePressEvent(event) {
if (!event.isLeftButton) {
@ -103,23 +138,35 @@ function mousePressEvent(event) {
prevMouse.y = event.y;
var pickRay = Camera.computePickRay(event.x, event.y);
var intersection = Entities.findRayIntersection(pickRay, true); // accurate picking
if (!intersection.intersects) {
var pickResults = Entities.findRayIntersection(pickRay, true); // accurate picking
if (!pickResults.intersects) {
return;
}
if (intersection.properties.collisionsWillMove) {
grabbedEntity = intersection.entityID;
if (pickResults.properties.collisionsWillMove) {
grabbedEntity = pickResults.entityID;
var props = Entities.getEntityProperties(grabbedEntity)
isGrabbing = true;
originalGravity = props.gravity;
targetPosition = props.position;
var objectPosition = props.position;
currentPosition = props.position;
if (Vec3.distance(currentPosition, Camera.getPosition()) > MAX_GRAB_DISTANCE) {
// don't allow grabs of things far away
return;
}
isGrabbing = true;
isGrabbingPaddle = (props.name == "air-hockey-paddle-23j4h1jh82jsjfw91jf232n2k");
currentVelocity = props.velocity;
updateDropLine(targetPosition);
updateDropLine(objectPosition);
var pointOnPlane = xzPickRayIntersetion(objectPosition, event.x, event.y);
grabOffset = Vec3.subtract(pointOnPlane, objectPosition);
targetPosition = objectPosition;
// remember the height of the object when first grabbed
// we'll try to maintain this height during the rest of this grab
grabHeight = currentPosition.y;
initialVerticalGrabPosition = currentPosition;
Entities.editEntity(grabbedEntity, {
gravity: {
@ -194,7 +241,6 @@ function mouseReleaseEvent() {
}
}
// new mouseMoveEvent
function mouseMoveEvent(event) {
if (isGrabbing) {
// see if something added/restored gravity
@ -204,71 +250,78 @@ function mouseMoveEvent(event) {
}
if (shouldRotate) {
targetPosition = currentPosition;
deltaMouse.x = event.x - prevMouse.x;
if (!moveUpDown) {
deltaMouse.z = event.y - prevMouse.y;
deltaMouse.y = 0;
} else {
deltaMouse.y = (event.y - prevMouse.y) * -1;
deltaMouse.z = 0;
}
deltaMouse.z = event.y - prevMouse.y;
deltaMouse.y = 0;
var transformedDeltaMouse = {
x: deltaMouse.z,
y: deltaMouse.x,
z: deltaMouse.y
};
transformedDeltaMouse = Vec3.multiplyQbyV(Quat.fromPitchYawRollDegrees(0, camYaw, 0), transformedDeltaMouse);
dQ = Quat.fromVec3Degrees(transformedDeltaMouse);
theta = 2 * Math.acos(dQ.w);
axisAngle = Quat.axis(dQ);
angularVelocity = Vec3.multiply((theta / dT), axisAngle);
var theta = 2 * Math.acos(dQ.w);
var axis = Quat.axis(dQ);
angularVelocity = Vec3.multiply((theta / ANGULAR_SPRING_TIMESCALE), axis);
} else {
var relativePosition = Vec3.subtract(currentPosition, Camera.getPosition());
if (relativePosition.y < 0) {
// grabee is below camera, so movement is valid
// compute intersectionPoint where mouse ray hits grabee's current x-z plane
var pickRay = Camera.computePickRay(event.x, event.y);
var mousePosition = pickRay.direction;
var length = relativePosition.y / mousePosition.y;
mousePosition = Vec3.multiply(mousePosition, length);
mousePosition = Vec3.sum(Camera.getPosition(), mousePosition);
if (moveUpDown) {
targetPosition = forwardPickRayIntersection(currentPosition, event.x, event.y);
grabHeight = targetPosition.y;
} else {
var pointOnPlane = xzPickRayIntersetion(currentPosition, event.x, event.y);
pointOnPlane = Vec3.subtract(pointOnPlane, grabOffset);
// translate mousePosition into local-frame
mousePosition = Vec3.subtract(mousePosition, tablePosition);
if (isGrabbingPaddle) {
// translate pointOnPlane into local-frame
pointOnPlane = Vec3.subtract(pointOnPlane, tablePosition);
// clamp local mousePosition to table field
if (mousePosition.x > fieldMaxOffset.x) {
mousePosition.x = fieldMaxOffset.x;
} else if (mousePosition.x < fieldMinOffset.x) {
mousePosition.x = fieldMinOffset.x;
// clamp local pointOnPlane to table field
if (pointOnPlane.x > fieldMaxOffset.x) {
pointOnPlane.x = fieldMaxOffset.x;
} else if (pointOnPlane.x < fieldMinOffset.x) {
pointOnPlane.x = fieldMinOffset.x;
}
if (pointOnPlane.z > fieldMaxOffset.z) {
pointOnPlane.z = fieldMaxOffset.z;
} else if (pointOnPlane.z < fieldMinOffset.z) {
pointOnPlane.z = fieldMinOffset.z;
}
// clamp to rotated square (for cut corners)
var rotation = Quat.angleAxis(45, { x:0, y:1, z:0 });
pointOnPlane = Vec3.multiplyQbyV(rotation, pointOnPlane);
if (pointOnPlane.x > halfCornerBoxWidth) {
pointOnPlane.x = halfCornerBoxWidth;
} else if (pointOnPlane.x < -halfCornerBoxWidth) {
pointOnPlane.x = -halfCornerBoxWidth;
}
if (pointOnPlane.z > halfCornerBoxWidth) {
pointOnPlane.z = halfCornerBoxWidth;
} else if (pointOnPlane.z < -halfCornerBoxWidth) {
pointOnPlane.z = -halfCornerBoxWidth;
}
// rotate back into local frame
rotation.y = -rotation.y;
pointOnPlane = Vec3.multiplyQbyV(rotation, pointOnPlane);
// translate into world-frame
pointOnPlane = Vec3.sum(tablePosition, pointOnPlane);
} else {
// we're grabbing a non-paddle object
// clamp distance
var relativePosition = Vec3.subtract(pointOnPlane, Camera.getPosition());
var length = Vec3.length(relativePosition);
if (length > MAX_GRAB_DISTANCE) {
relativePosition = Vec3.multiply(relativePosition, MAX_GRAB_DISTANCE / length);
pointOnPlane = Vec3.sum(relativePosition, Camera.getPosition());
}
}
if (mousePosition.z > fieldMaxOffset.z) {
mousePosition.z = fieldMaxOffset.z;
} else if (mousePosition.z < fieldMinOffset.z) {
mousePosition.z = fieldMinOffset.z;
}
// clamp to rotated square (for cut corners)
var rotation = Quat.angleAxis(45, { x:0, y:1, z:0 });
mousePosition = Vec3.multiplyQbyV(rotation, mousePosition);
if (mousePosition.x > halfCornerBoxWidth) {
mousePosition.x = halfCornerBoxWidth;
} else if (mousePosition.x < -halfCornerBoxWidth) {
mousePosition.x = -halfCornerBoxWidth;
}
if (mousePosition.z > halfCornerBoxWidth) {
mousePosition.z = halfCornerBoxWidth;
} else if (mousePosition.z < -halfCornerBoxWidth) {
mousePosition.z = -halfCornerBoxWidth;
}
// rotate back into local frame
rotation.y = -rotation.y;
mousePosition = Vec3.multiplyQbyV(rotation, mousePosition);
// translate into world-frame
mousePosition = Vec3.sum(tablePosition, mousePosition);
mousePosition.y = grabHeight;
targetPosition = mousePosition;
// clamp to grabHeight
pointOnPlane.y = grabHeight;
targetPosition = pointOnPlane;
initialVerticalGrabPosition = targetPosition;
}
}
}
@ -297,57 +350,32 @@ function keyPressEvent(event) {
function update(deltaTime) {
dT = deltaTime;
if (isGrabbing) {
entityProps = Entities.getEntityProperties(grabbedEntity);
currentPosition = entityProps.position;
currentVelocity = entityProps.velocity;
currentRotation = entityProps.rotation;
var dPosition = Vec3.subtract(targetPosition, currentPosition);
distanceToTarget = Vec3.length(dPosition);
if (distanceToTarget > CLOSE_ENOUGH) {
// compute current velocity in the direction we want to move
velocityTowardTarget = Vec3.dot(currentVelocity, Vec3.normalize(dPosition));
velocityTowardTarget = Vec3.multiply(Vec3.normalize(dPosition), velocityTowardTarget);
// compute the speed we would like to be going toward the target position
desiredVelocity = Vec3.multiply(dPosition, (1.0 / deltaTime) * SPRING_RATE);
// compute how much we want to add to the existing velocity
addedVelocity = Vec3.subtract(desiredVelocity, velocityTowardTarget);
// If target is too far, roll off the force as inverse square of distance
if (distanceToTarget / cameraEntityDistance > FULL_STRENGTH) {
addedVelocity = Vec3.multiply(addedVelocity, Math.pow(FULL_STRENGTH / distanceToTarget, 2.0));
}
newVelocity = Vec3.sum(currentVelocity, addedVelocity);
// Add Damping
newVelocity = Vec3.subtract(newVelocity, Vec3.multiply(newVelocity, DAMPING_RATE));
// Update entity
} else {
newVelocity = {
x: 0,
y: 0,
z: 0
};
}
if (shouldRotate) {
angularVelocity = Vec3.subtract(angularVelocity, Vec3.multiply(angularVelocity, ANGULAR_DAMPING_RATE));
Entities.editEntity(grabbedEntity, { angularVelocity: angularVelocity, });
} else {
angularVelocity = entityProps.angularVelocity;
var dPosition = Vec3.subtract(targetPosition, currentPosition);
var delta = Vec3.length(dPosition);
if (delta > CLOSE_ENOUGH) {
var MAX_POSITION_DELTA = 0.50;
if (delta > MAX_POSITION_DELTA) {
dPosition = Vec3.multiply(dPosition, MAX_POSITION_DELTA / delta);
}
// desired speed is proportional to displacement by the inverse of timescale
// (for critically damped motion)
newVelocity = Vec3.multiply(dPosition, 1.0 / SPRING_TIMESCALE);
} else {
newVelocity = {
x: 0,
y: 0,
z: 0
};
}
Entities.editEntity(grabbedEntity, { velocity: newVelocity, });
}
// enforce that grabee's rotation is only about y-axis while being grabbed
currentRotation.x = 0;
currentRotation.z = 0;
currentRotation.y = Math.sqrt(1.0 - currentRotation.w * currentRotation.w);
// Hrm... slamming the currentRotation doesn't seem to work
Entities.editEntity(grabbedEntity, {
position: currentPosition,
rotation: currentRotation,
velocity: newVelocity,
angularVelocity: angularVelocity
});
updateDropLine(targetPosition);
}
}

View file

@ -36,8 +36,6 @@ var angularVelocity = {
z: 0
};
var grabSound = SoundCache.getSound("https://hifi-public.s3.amazonaws.com/eric/sounds/CloseClamp.wav");
var releaseSound = SoundCache.getSound("https://hifi-public.s3.amazonaws.com/eric/sounds/ReleaseClamp.wav");
var DROP_DISTANCE = 5.0;
var DROP_COLOR = {
@ -90,10 +88,6 @@ function mousePressEvent(event) {
gravity: {x: 0, y: 0, z: 0}
});
Audio.playSound(grabSound, {
position: props.position,
volume: 0.4
});
}
}
@ -135,11 +129,6 @@ function mouseReleaseEvent() {
});
targetPosition = null;
Audio.playSound(grabSound, {
position: entityProps.position,
volume: 0.25
});
}
}

View file

@ -0,0 +1,50 @@
<?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="address-bar-error-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></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="1840"
inkscape:window-height="1057"
id="namedview4139"
showgrid="false"
inkscape:zoom="4.8487496"
inkscape:cx="50"
inkscape:cy="37.53545"
inkscape:window-x="72"
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" /></svg>

After

Width:  |  Height:  |  Size: 3.4 KiB

View file

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 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">
<path fill="#000000" d="M50.291,0.07c-18.706,0-33.871,15.165-33.871,33.87c0,0.401,0.013,0.81,0.03,1.221 c0.127,3.558,0.798,6.976,1.939,10.173c7.226,23.752,31.901,54.736,31.901,54.736s24.674-30.982,31.901-54.734 c1.143-3.197,1.812-6.617,1.939-10.175c0.02-0.411,0.031-0.819,0.031-1.221C84.162,15.235,68.998,0.07,50.291,0.07z M51.013,58.386 c-2.479,0-4.664-2.126-4.664-4.664c0-2.479,2.184-4.723,4.664-4.723s4.724,2.243,4.724,4.723 C55.736,56.26,53.551,58.386,51.013,58.386z M50.481,45.811c-1.062-6.376-2.479-12.634-3.601-19.01 c-0.236-1.357-0.295-2.302-0.295-3.66c0-2.716,1.299-5.667,4.428-5.667c3.483,0,4.428,3.011,4.428,6.021 c0,1.181-0.059,2.538-0.295,3.66c-1.181,6.199-2.302,12.457-3.483,18.655H50.481z"/>
</svg>

After

Width:  |  Height:  |  Size: 954 B

View file

@ -1,18 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 49 49" enable-background="new 0 0 49 49" xml:space="preserve">
<g>
<g>
<path fill="#333" d="M49,46c0,1.7-1.3,3-3,3H3c-1.7,0-3-1.3-3-3V3c0-1.7,1.3-3,3-3h43c1.7,0,3,1.3,3,3V46z"/>
</g>
<g>
<g id="Your_Icon_11_">
<g>
<polygon fill="#E7EEEE" points="23.6,19.9 15.1,19.9 15.1,27.8 23.6,27.8 23.6,33.8 33,23.9 23.6,14 "/>
</g>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 759 B

View file

@ -1,18 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 49 49" enable-background="new 0 0 49 49" xml:space="preserve">
<g>
<g>
<path fill="#0E7077" d="M49,46c0,1.7-1.3,3-3,3H3c-1.7,0-3-1.3-3-3V3c0-1.7,1.3-3,3-3h43c1.7,0,3,1.3,3,3V46z"/>
</g>
<g>
<g id="Your_Icon_11_">
<g>
<polygon fill="#E7EEEE" points="23.6,19.9 15.1,19.9 15.1,27.8 23.6,27.8 23.6,33.8 33,23.9 23.6,14 "/>
</g>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 762 B

View file

@ -0,0 +1,72 @@
<?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"
width="1440"
height="200"
data-icon="map-marker"
data-container-transform="translate(24)"
viewBox="0 0 1440 200"
id="svg4136"
inkscape:version="0.91 r13725"
sodipodi:docname="address-bar.svg">
<metadata
id="metadata4144">
<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="defs4142" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1840"
inkscape:window-height="1057"
id="namedview4140"
showgrid="false"
inkscape:zoom="0.8671875"
inkscape:cx="707.02439"
inkscape:cy="52.468468"
inkscape:window-x="72"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="svg4136" />
<rect
style="fill:#ededed;fill-opacity:1;stroke:none;stroke-linejoin:round;stroke-opacity:1"
id="rect4141"
width="1280"
height="140"
x="160"
y="30"
rx="16.025024"
ry="17.019567" />
<circle
style="fill:#b8b8b8;fill-opacity:1;stroke:none;stroke-opacity:1"
id="path4146"
cx="100"
cy="100"
r="100" />
<path
d="m 100,36.000005 c -22.1,0 -40,17.9 -40,39.999995 0,30 40,88 40,88 0,0 40,-58 40,-88 0,-22.099995 -17.9,-39.999995 -40,-39.999995 z m 0,22 c 9.9,0 18,8.099995 18,17.999995 0,9.9 -8.1,18 -18,18 -9.9,0 -18,-8.1 -18,-18 0,-9.9 8.1,-17.999995 18,-17.999995 z"
id="path4138"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View file

@ -1,91 +1,145 @@
//
// AddressBarDialog.qml
//
// Created by Austin Davis on 2015/04/14
// 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 1.2
import "controls"
import "styles"
Dialog {
Item {
id: root
HifiConstants { id: hifi }
title: "Go to..."
objectName: "AddressBarDialog"
contentImplicitWidth: addressBarDialog.implicitWidth
contentImplicitHeight: addressBarDialog.implicitHeight
destroyOnCloseButton: false
property int animationDuration: hifi.effects.fadeInDuration
property bool destroyOnInvisible: false
onVisibleChanged: {
if (!visible) {
reset();
}
implicitWidth: addressBarDialog.implicitWidth
implicitHeight: addressBarDialog.implicitHeight
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
AddressBarDialog {
id: addressBarDialog
implicitWidth: backgroundImage.width
implicitHeight: backgroundImage.height
Image {
id: backgroundImage
source: "../images/address-bar.svg"
width: 576
height: 80
property int inputAreaHeight: 56 // Height of the background's input area
property int inputAreaStep: (height - inputAreaHeight) / 2
TextInput {
id: addressLine
anchors {
fill: parent
leftMargin: parent.height + hifi.layout.spacing * 2
rightMargin: hifi.layout.spacing * 2
topMargin: parent.inputAreaStep + hifi.layout.spacing
bottomMargin: parent.inputAreaStep + hifi.layout.spacing
}
font.pointSize: 15
helperText: "Go to: place, @user, /path, network address"
onAccepted: {
event.accepted = true // Generates erroneous error in program log, "ReferenceError: event is not defined".
addressBarDialog.loadAddress(addressLine.text)
}
}
MouseArea {
// Drag the icon
width: parent.height
height: parent.height
x: 0
y: 0
drag {
target: root
minimumX: -parent.inputAreaStep
minimumY: -parent.inputAreaStep
maximumX: root.parent ? root.maximumX : 0
maximumY: root.parent ? root.maximumY + parent.inputAreaStep : 0
}
}
MouseArea {
// Drag the input rectangle
width: parent.width - parent.height
height: parent.inputAreaHeight
x: parent.height
y: parent.inputAreaStep
drag {
target: root
minimumX: -parent.inputAreaStep
minimumY: -parent.inputAreaStep
maximumX: root.parent ? root.maximumX : 0
maximumY: root.parent ? root.maximumY + parent.inputAreaStep : 0
}
}
}
}
// 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();
}
}
onParentChanged: {
if (enabled && visible) {
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()
}
}
}
function reset() {
addressLine.text = ""
goButton.source = "../images/address-bar-submit.svg"
}
AddressBarDialog {
id: addressBarDialog
// The client area
x: root.clientX
y: root.clientY
implicitWidth: 512
implicitHeight: border.height + hifi.layout.spacing * 4
Border {
id: border
height: 64
anchors.left: parent.left
anchors.leftMargin: hifi.layout.spacing * 2
anchors.right: goButton.left
anchors.rightMargin: hifi.layout.spacing
anchors.verticalCenter: parent.verticalCenter
TextInput {
id: addressLine
anchors.fill: parent
helperText: "domain, location, @user, /x,y,z"
anchors.margins: hifi.layout.spacing
onAccepted: {
event.accepted
addressBarDialog.loadAddress(addressLine.text)
}
}
}
Image {
id: goButton
width: 32
height: 32
anchors.right: parent.right
anchors.rightMargin: hifi.layout.spacing * 2
source: "../images/address-bar-submit.svg"
anchors.verticalCenter: parent.verticalCenter
MouseArea {
anchors.fill: parent
onClicked: {
parent.source = "../images/address-bar-submit-active.svg"
addressBarDialog.loadAddress(addressLine.text)
}
}
}
}
Keys.onEscapePressed: {
enabled = false;
}
function toggleOrGo() {
@ -95,8 +149,22 @@ Dialog {
addressBarDialog.loadAddress(addressLine.text)
}
}
Keys.onEscapePressed: {
enabled = false
}
Keys.onPressed: {
switch(event.key) {
case Qt.Key_W:
if (event.modifiers == Qt.ControlModifier) {
event.accepted = true
enabled = false
}
break
}
}
Keys.onReturnPressed: toggleOrGo()
Keys.onEnterPressed: toggleOrGo()
}

View file

@ -0,0 +1,152 @@
//
// ErrorDialog.qml
//
// Created by David Rowe on 30 May 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 as Hifi
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Dialogs 1.2
import "controls"
import "styles"
Item {
id: root
HifiConstants { id: hifi }
property int animationDuration: hifi.effects.fadeInDuration
property bool destroyOnInvisible: true
Component.onCompleted: {
enabled = true
}
onParentChanged: {
if (visible && enabled) {
forceActiveFocus();
}
}
implicitWidth: content.implicitWidth
implicitHeight: content.implicitHeight
x: parent ? parent.width / 2 - width / 2 : 0
y: parent ? parent.height / 2 - height / 2 : 0
Hifi.ErrorDialog {
id: content
implicitWidth: box.width
implicitHeight: icon.height + hifi.layout.spacing * 2
Border {
id: box
width: 512
color: "#ebebeb"
radius: 2
border.width: 1
border.color: "#000000"
Image {
id: icon
source: "../images/address-bar-error-icon.svg"
width: 40
height: 40
anchors {
left: parent.left
leftMargin: hifi.layout.spacing
verticalCenter: parent.verticalCenter
}
}
Text {
id: messageText
font.pointSize: 10
font.weight: Font.Bold
anchors {
horizontalCenter: parent.horizontalCenter
verticalCenter: parent.verticalCenter
}
text: content.text
}
Image {
source: "../images/address-bar-error-close.svg"
width: 20
height: 20
anchors {
right: parent.right
rightMargin: hifi.layout.spacing * 2
verticalCenter: parent.verticalCenter
}
MouseArea {
anchors.fill: parent
onClicked: {
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) {
case Qt.Key_Escape:
case Qt.Key_Back:
case Qt.Key_Enter:
case Qt.Key_Return:
event.accepted = true
content.accept()
break
}
}
}

View file

@ -31,7 +31,7 @@ DialogBase {
* Support for animating the dialog in and out.
*/
enabled: false
scale: 0.0
opacity: 1.0
// The offscreen UI will enable an object, rather than manipulating it's
// visibility, so that we can do animations in both directions. Because
@ -40,20 +40,20 @@ DialogBase {
// opacity, and then when the target animation value is reached, we can
// modify the visibility
onEnabledChanged: {
scale = enabled ? 1.0 : 0.0
opacity = enabled ? 1.0 : 0.0
}
// The actual animator
Behavior on scale {
Behavior on opacity {
NumberAnimation {
duration: root.animationDuration
easing.type: Easing.InOutBounce
duration: animationDuration
easing.type: Easing.OutCubic
}
}
// Once we're scaled to 0, disable the dialog's visibility
onScaleChanged: {
visible = (scale != 0.0);
// Once we're transparent, disable the dialog's visibility
onOpacityChanged: {
visible = (opacity != 0.0);
}
// Some dialogs should be destroyed when they become invisible,

View file

@ -56,6 +56,6 @@ Item {
QtObject {
id: effects
readonly property int fadeInDuration: 400
readonly property int fadeInDuration: 300
}
}

View file

@ -55,40 +55,41 @@
#include <QMessageBox>
#include <QJsonDocument>
#include <AddressManager.h>
#include <AccountManager.h>
#include <AddressManager.h>
#include <AmbientOcclusionEffect.h>
#include <AudioInjector.h>
#include <DeferredLightingEffect.h>
#include <DependencyManager.h>
#include <EntityScriptingInterface.h>
#include <ErrorDialog.h>
#include <GlowEffect.h>
#include <HFActionEvent.h>
#include <HFBackEvent.h>
#include <VrMenu.h>
#include <InfoView.h>
#include <LogHandler.h>
#include <MainWindow.h>
#include <MessageDialog.h>
#include <ModelEntityItem.h>
#include <NetworkAccessManager.h>
#include <NetworkingConstants.h>
#include <ObjectMotionState.h>
#include <OctalCode.h>
#include <OctreeSceneStats.h>
#include <ObjectMotionState.h>
#include <PacketHeaders.h>
#include <PathUtils.h>
#include <PerfStat.h>
#include <PhysicsEngine.h>
#include <ProgramObject.h>
#include <ResourceCache.h>
#include <SceneScriptingInterface.h>
#include <ScriptCache.h>
#include <SettingHandle.h>
#include <SoundCache.h>
#include <TextRenderer.h>
#include <UserActivityLogger.h>
#include <UUID.h>
#include <MessageDialog.h>
#include <InfoView.h>
#include <SceneScriptingInterface.h>
#include <VrMenu.h>
#include "Application.h"
#include "AudioClient.h"
@ -807,6 +808,7 @@ void Application::initializeGL() {
void Application::initializeUi() {
AddressBarDialog::registerType();
ErrorDialog::registerType();
LoginDialog::registerType();
MessageDialog::registerType();
VrMenu::registerType();
@ -3105,21 +3107,27 @@ PickRay Application::computePickRay(float x, float y) const {
QImage Application::renderAvatarBillboard(RenderArgs* renderArgs) {
auto primaryFramebuffer = DependencyManager::get<TextureCache>()->getPrimaryFramebuffer();
glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(primaryFramebuffer));
// clear the alpha channel so the background is transparent
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
// the "glow" here causes an alpha of one
Glower glower(renderArgs);
const int BILLBOARD_SIZE = 64;
// TODO: Pass a RenderArgs to renderAvatarBillboard
renderRearViewMirror(renderArgs, QRect(0, _glWidget->getDeviceHeight() - BILLBOARD_SIZE,
BILLBOARD_SIZE, BILLBOARD_SIZE),
true);
QImage image(BILLBOARD_SIZE, BILLBOARD_SIZE, QImage::Format_ARGB32);
glReadPixels(0, 0, BILLBOARD_SIZE, BILLBOARD_SIZE, GL_BGRA, GL_UNSIGNED_BYTE, image.bits());
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
return image;
}
@ -3194,7 +3202,7 @@ namespace render {
void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool selfAvatarOnly) {
void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool selfAvatarOnly, bool billboard) {
activeRenderingThread = QThread::currentThread();
PROFILE_RANGE(__FUNCTION__);
PerformanceTimer perfTimer("display");
@ -3440,7 +3448,7 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se
}
{
if (!billboard) {
DependencyManager::get<DeferredLightingEffect>()->setAmbientLightMode(getRenderAmbientLight());
auto skyStage = DependencyManager::get<SceneScriptingInterface>()->getSkyStage();
DependencyManager::get<DeferredLightingEffect>()->setGlobalLight(skyStage->getSunLight()->getDirection(), skyStage->getSunLight()->getColor(), skyStage->getSunLight()->getIntensity(), skyStage->getSunLight()->getAmbientIntensity());
@ -3624,7 +3632,7 @@ void Application::renderRearViewMirror(RenderArgs* renderArgs, const QRect& regi
// render rear mirror view
glPushMatrix();
displaySide(renderArgs, _mirrorCamera, true);
displaySide(renderArgs, _mirrorCamera, true, billboard);
glPopMatrix();
if (!billboard) {

View file

@ -271,7 +271,7 @@ public:
QImage renderAvatarBillboard(RenderArgs* renderArgs);
void displaySide(RenderArgs* renderArgs, Camera& whichCamera, bool selfAvatarOnly = false);
void displaySide(RenderArgs* renderArgs, Camera& whichCamera, bool selfAvatarOnly = false, bool billboard = false);
/// Stores the current modelview matrix as the untranslated view matrix to use for transforms and the supplied vector as
/// the view matrix translation.

View file

@ -36,12 +36,10 @@ void AddressBarDialog::loadAddress(const QString& address) {
}
void AddressBarDialog::displayAddressOfflineMessage() {
OffscreenUi::information("Address offline",
"That user or place is currently offline.");
OffscreenUi::error("That user or place is currently offline");
}
void AddressBarDialog::displayAddressNotFoundMessage() {
OffscreenUi::information("Address not found",
"There is no address information for that user or place.");
OffscreenUi::error("There is no address information for that user or place");
}

View file

@ -1178,7 +1178,7 @@ void EntityTreeRenderer::playEntityCollisionSound(const QUuid& myNodeID, EntityT
const float energy = mass * linearVelocity * linearVelocity / 2.0f;
const glm::vec3 position = collision.contactPoint;
const float COLLISION_ENERGY_AT_FULL_VOLUME = 0.5f;
const float COLLISION_MINIMUM_VOLUME = 0.001f;
const float COLLISION_MINIMUM_VOLUME = 0.005f;
const float energyFactorOfFull = fmin(1.0f, energy / COLLISION_ENERGY_AT_FULL_VOLUME);
if (energyFactorOfFull < COLLISION_MINIMUM_VOLUME) {
return;
@ -1194,7 +1194,7 @@ void EntityTreeRenderer::playEntityCollisionSound(const QUuid& myNodeID, EntityT
}
// This is a hack. Quiet sound aren't really heard at all, so we compress everything to the range [1-c, 1], if we play it all.
const float COLLISION_SOUND_COMPRESSION_RANGE = 0.7f;
const float COLLISION_SOUND_COMPRESSION_RANGE = 1.0f; // This section could be removed when the value is 1, but let's see how it goes.
float volume = energyFactorOfFull;
volume = (volume * COLLISION_SOUND_COMPRESSION_RANGE) + (1.0f - COLLISION_SOUND_COMPRESSION_RANGE);
@ -1225,7 +1225,7 @@ void EntityTreeRenderer::entityCollisionWithEntity(const EntityItemID& idA, cons
return;
}
// Don't respond to small continuous contacts.
const float COLLISION_MINUMUM_PENETRATION = 0.005f;
const float COLLISION_MINUMUM_PENETRATION = 0.002f;
if ((collision.type != CONTACT_EVENT_TYPE_START) && (glm::length(collision.penetration) < COLLISION_MINUMUM_PENETRATION)) {
return;
}

View file

@ -155,8 +155,6 @@ void RenderableModelEntityItem::render(RenderArgs* args) {
PerformanceTimer perfTimer("RMEIrender");
assert(getType() == EntityTypes::Model);
bool drawAsModel = hasModel();
glm::vec3 position = getPosition();
glm::vec3 dimensions = getDimensions();
@ -168,8 +166,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) {
highlightSimulationOwnership = (getSimulatorID() == myNodeID);
}
bool didDraw = false;
if (drawAsModel && !highlightSimulationOwnership) {
if (hasModel()) {
remapTextures();
{
float alpha = getLocalRenderAlpha();
@ -221,18 +218,19 @@ void RenderableModelEntityItem::render(RenderArgs* args) {
if (args && (args->_renderMode == RenderArgs::SHADOW_RENDER_MODE)) {
if (movingOrAnimating) {
_model->renderInScene(alpha, args);
didDraw = true;
}
} else {
_model->renderInScene(alpha, args);
didDraw = true;
}
}
}
}
}
if (!didDraw) {
if (highlightSimulationOwnership) {
glm::vec4 greenColor(0.0f, 1.0f, 0.0f, 1.0f);
RenderableDebugableEntityItem::renderBoundingBox(this, args, 0.0f, greenColor);
}
} else {
glm::vec4 greenColor(0.0f, 1.0f, 0.0f, 1.0f);
RenderableDebugableEntityItem::renderBoundingBox(this, args, 0.0f, greenColor);
}

View file

@ -480,17 +480,21 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
bytesRead += encodedUpdateDelta.size();
// Newer bitstreams will have a last simulated and a last updated value
quint64 lastSimulatedFromBufferAdjusted = now;
if (args.bitstreamVersion >= VERSION_ENTITIES_HAS_LAST_SIMULATED_TIME) {
// last simulated is stored as ByteCountCoded delta from lastEdited
QByteArray encodedSimulatedDelta = originalDataBuffer.mid(bytesRead); // maximum possible size
ByteCountCoded<quint64> simulatedDeltaCoder = encodedSimulatedDelta;
quint64 simulatedDelta = simulatedDeltaCoder;
if (overwriteLocalData) {
_lastSimulated = lastEditedFromBufferAdjusted + simulatedDelta; // don't adjust for clock skew since we already did that
lastSimulatedFromBufferAdjusted = lastEditedFromBufferAdjusted + simulatedDelta; // don't adjust for clock skew since we already did that
if (lastSimulatedFromBufferAdjusted > now) {
lastSimulatedFromBufferAdjusted = now;
}
#ifdef WANT_DEBUG
qCDebug(entities) << " _lastSimulated:" << debugTime(_lastSimulated, now);
qCDebug(entities) << " _lastEdited:" << debugTime(_lastEdited, now);
qCDebug(entities) << " lastEditedFromBufferAdjusted:" << debugTime(lastEditedFromBufferAdjusted, now);
qCDebug(entities) << " lastSimulatedFromBufferAdjusted:" << debugTime(lastSimulatedFromBufferAdjusted, now);
#endif
}
encodedSimulatedDelta = simulatedDeltaCoder; // determine true length
@ -606,8 +610,8 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
// use our simulation helper routine to get a best estimate of where the entity should be.
const float MIN_TIME_SKIP = 0.0f;
const float MAX_TIME_SKIP = 1.0f; // in seconds
float skipTimeForward = glm::clamp((float)(now - _lastSimulated) / (float)(USECS_PER_SECOND),
MIN_TIME_SKIP, MAX_TIME_SKIP);
float skipTimeForward = glm::clamp((float)(now - lastSimulatedFromBufferAdjusted) / (float)(USECS_PER_SECOND),
MIN_TIME_SKIP, MAX_TIME_SKIP);
if (skipTimeForward > 0.0f) {
#ifdef WANT_DEBUG
qCDebug(entities) << "skipTimeForward:" << skipTimeForward;
@ -617,19 +621,22 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
// we don't want the side effect of flag setting.
simulateKinematicMotion(skipTimeForward, false);
}
_lastSimulated = now;
}
auto nodeList = DependencyManager::get<NodeList>();
const QUuid& myNodeID = nodeList->getSessionUUID();
if (overwriteLocalData && _simulatorID == myNodeID && !_simulatorID.isNull()) {
// we own the simulation, so we keep our transform+velocities and remove any related dirty flags
// rather than accept the values in the packet
setPosition(savePosition);
setRotation(saveRotation);
_velocity = saveVelocity;
_angularVelocity = saveAngularVelocity;
_dirtyFlags &= ~(EntityItem::DIRTY_TRANSFORM | EntityItem::DIRTY_VELOCITIES);
if (overwriteLocalData) {
if (_simulatorID == myNodeID && !_simulatorID.isNull()) {
// we own the simulation, so we keep our transform+velocities and remove any related dirty flags
// rather than accept the values in the packet
setPosition(savePosition);
setRotation(saveRotation);
_velocity = saveVelocity;
_angularVelocity = saveAngularVelocity;
_dirtyFlags &= ~(EntityItem::DIRTY_TRANSFORM | EntityItem::DIRTY_VELOCITIES);
} else {
_lastSimulated = now;
}
}
return bytesRead;
@ -919,6 +926,21 @@ EntityItemProperties EntityItem::getProperties() const {
return properties;
}
void EntityItem::getAllTerseUpdateProperties(EntityItemProperties& properties) const {
// a TerseUpdate includes the transform and its derivatives
properties._position = getPosition();
properties._velocity = _velocity;
properties._rotation = getRotation();
properties._angularVelocity = _angularVelocity;
properties._acceleration = _acceleration;
properties._positionChanged = true;
properties._velocityChanged = true;
properties._rotationChanged = true;
properties._angularVelocityChanged = true;
properties._accelerationChanged = true;
}
bool EntityItem::setProperties(const EntityItemProperties& properties) {
bool somethingChanged = false;

View file

@ -366,6 +366,8 @@ public:
quint64 getLastEditedFromRemote() { return _lastEditedFromRemote; }
void getAllTerseUpdateProperties(EntityItemProperties& properties) const;
protected:
static bool _sendPhysicsUpdates;

View file

@ -1156,4 +1156,7 @@ AABox EntityItemProperties::getAABox() const {
return AABox(rotatedExtentsRelativeToRegistrationPoint);
}
bool EntityItemProperties::hasTerseUpdateChanges() const {
// a TerseUpdate includes the transform and its derivatives
return _positionChanged || _velocityChanged || _rotationChanged || _angularVelocityChanged || _accelerationChanged;
}

View file

@ -195,6 +195,8 @@ public:
void setVoxelDataDirty() { _voxelDataChanged = true; }
bool hasTerseUpdateChanges() const;
private:
QUuid _id;
bool _idSet;
@ -215,6 +217,7 @@ private:
QStringList _textureNames;
glm::vec3 _naturalDimensions;
};
Q_DECLARE_METATYPE(EntityItemProperties);
QScriptValue EntityItemPropertiesToScriptValue(QScriptEngine* engine, const EntityItemProperties& properties);
QScriptValue EntityItemNonDefaultPropertiesToScriptValue(QScriptEngine* engine, const EntityItemProperties& properties);

View file

@ -146,7 +146,17 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties&
EntityItemProperties modifiedProperties = properties;
entity->setLastBroadcast(usecTimestampNow());
modifiedProperties.setType(entity->getType());
bidForSimulationOwnership(modifiedProperties);
if (modifiedProperties.hasTerseUpdateChanges()) {
// we make a bid for (or assert) our simulation ownership
auto nodeList = DependencyManager::get<NodeList>();
const QUuid myNodeID = nodeList->getSessionUUID();
modifiedProperties.setSimulatorID(myNodeID);
if (entity->getSimulatorID() == myNodeID) {
// we think we already own simulation, so make sure we send ALL TerseUpdate properties
entity->getAllTerseUpdateProperties(modifiedProperties);
}
}
queueEntityMessage(PacketTypeEntityEdit, entityID, modifiedProperties);
return id;
}

View file

@ -505,9 +505,13 @@ void NodeList::pingPunchForDomainServer() {
} else {
if (_domainHandler.getICEPeer().getConnectionAttempts() % NUM_DOMAIN_SERVER_PINGS_BEFORE_RESET == 0) {
// if we have then nullify the domain handler's network peer and send a fresh ICE heartbeat
qCDebug(networking) << "No ping replies received from domain-server with ID"
<< uuidStringWithoutCurlyBraces(_domainHandler.getICEClientID()) << "-" << "re-sending ICE query.";
_domainHandler.getICEPeer().softReset();
handleICEConnectionToDomainServer();
return;
}
}

View file

@ -27,14 +27,17 @@
using namespace std;
ViewFrustum::ViewFrustum() {
}
void ViewFrustum::setOrientation(const glm::quat& orientationAsQuaternion) {
_orientation = orientationAsQuaternion;
_right = glm::vec3(orientationAsQuaternion * glm::vec4(IDENTITY_RIGHT, 0.0f));
_up = glm::vec3(orientationAsQuaternion * glm::vec4(IDENTITY_UP, 0.0f));
_direction = glm::vec3(orientationAsQuaternion * glm::vec4(IDENTITY_FRONT, 0.0f));
_view = glm::translate(mat4(), _position) * glm::mat4_cast(_orientation);
}
void ViewFrustum::setPosition(const glm::vec3& position) {
_position = position;
_view = glm::translate(mat4(), _position) * glm::mat4_cast(_orientation);
}
// Order cooresponds to the order defined in the BoxVertex enum.

View file

@ -36,11 +36,9 @@ const float DEFAULT_FAR_CLIP = (float)TREE_SCALE;
class ViewFrustum {
public:
ViewFrustum();
// setters for camera attributes
void setPosition(const glm::vec3& p) { _position = p; }
void setOrientation(const glm::quat& orientationAsQuaternion);
void setPosition(const glm::vec3& position);
void setOrientation(const glm::quat& orientation);
// getters for camera attributes
const glm::vec3& getPosition() const { return _position; }
@ -54,7 +52,8 @@ public:
void getFocalLength(float focalLength) { _focalLength = focalLength; }
// getters for lens attributes
const glm::mat4 getProjection() const { return _projection; };
const glm::mat4& getProjection() const { return _projection; }
const glm::mat4& getView() const { return _view; }
float getWidth() const { return _width; }
float getHeight() const { return _height; }
float getFieldOfView() const { return _fieldOfView; }
@ -120,6 +119,7 @@ private:
// camera location/orientation attributes
glm::vec3 _position; // the position in world-frame
glm::quat _orientation;
glm::mat4 _view;
// Lens attributes
glm::mat4 _projection;

View file

@ -0,0 +1,66 @@
//
// Created by Bradley Austin Davis on 2015/05/21
// Copyright 2013 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "GlWindow.h"
#include <QOpenGLContext>
#include <QOpenGLDebugLogger>
#include <GLHelpers.h>
GlWindow::GlWindow(QOpenGLContext* shareContext) : GlWindow(getDefaultOpenGlSurfaceFormat(), shareContext) {
}
GlWindow::GlWindow(const QSurfaceFormat& format, QOpenGLContext* shareContext) {
setSurfaceType(QSurface::OpenGLSurface);
setFormat(format);
_context = new QOpenGLContext;
_context->setFormat(format);
if (shareContext) {
_context->setShareContext(shareContext);
}
_context->create();
}
GlWindow::~GlWindow() {
#ifdef DEBUG
if (_logger) {
makeCurrent();
delete _logger;
_logger = nullptr;
}
#endif
_context->doneCurrent();
_context->deleteLater();
_context = nullptr;
}
void GlWindow::makeCurrent() {
_context->makeCurrent(this);
#ifdef DEBUG
if (!_logger) {
_logger = new QOpenGLDebugLogger(this);
if (_logger->initialize()) {
connect(_logger, &QOpenGLDebugLogger::messageLogged, [](const QOpenGLDebugMessage& message) {
qDebug() << message;
});
_logger->disableMessages(QOpenGLDebugMessage::AnySource, QOpenGLDebugMessage::AnyType, QOpenGLDebugMessage::NotificationSeverity);
_logger->startLogging(QOpenGLDebugLogger::LoggingMode::SynchronousLogging);
}
}
#endif
}
void GlWindow::doneCurrent() {
_context->doneCurrent();
}
void GlWindow::swapBuffers() {
_context->swapBuffers(this);
}

View file

@ -0,0 +1,33 @@
//
// Created by Bradley Austin Davis on 2015/05/21
// Copyright 2013 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
//
#pragma once
#ifndef hifi_GlWindow_h
#define hifi_GlWindow_h
#include <QWindow>
class QOpenGLContext;
class QOpenGLDebugLogger;
class GlWindow : public QWindow {
public:
GlWindow(QOpenGLContext* shareContext = nullptr);
GlWindow(const QSurfaceFormat& format, QOpenGLContext* shareContext = nullptr);
virtual ~GlWindow();
void makeCurrent();
void doneCurrent();
void swapBuffers();
private:
QOpenGLContext* _context{ nullptr };
#ifdef DEBUG
QOpenGLDebugLogger* _logger{ nullptr };
#endif
};
#endif

View file

@ -11,6 +11,7 @@
#include "OffscreenGlCanvas.h"
#include <QOpenGLDebugLogger>
OffscreenGlCanvas::OffscreenGlCanvas() {
}
@ -27,16 +28,35 @@ void OffscreenGlCanvas::create(QOpenGLContext* sharedContext) {
format.setMajorVersion(4);
format.setMinorVersion(1);
format.setProfile(QSurfaceFormat::OpenGLContextProfile::CompatibilityProfile);
#ifdef DEBUG
format.setOption(QSurfaceFormat::DebugContext);
#endif
_context.setFormat(format);
}
_context.create();
_offscreenSurface.setFormat(_context.format());
_offscreenSurface.create();
}
bool OffscreenGlCanvas::makeCurrent() {
return _context.makeCurrent(&_offscreenSurface);
bool result = _context.makeCurrent(&_offscreenSurface);
#ifdef DEBUG
if (result && !_logger) {
_logger = new QOpenGLDebugLogger(this);
if (_logger->initialize()) {
connect(_logger, &QOpenGLDebugLogger::messageLogged, [](const QOpenGLDebugMessage& message) {
qDebug() << message;
});
_logger->disableMessages(QOpenGLDebugMessage::AnySource, QOpenGLDebugMessage::AnyType, QOpenGLDebugMessage::NotificationSeverity);
_logger->startLogging(QOpenGLDebugLogger::LoggingMode::SynchronousLogging);
}
}
#endif
return result;
}
void OffscreenGlCanvas::doneCurrent() {

View file

@ -15,16 +15,24 @@
#include <QOpenGLContext>
#include <QOffscreenSurface>
class QOpenGLDebugLogger;
class OffscreenGlCanvas : public QObject {
public:
OffscreenGlCanvas();
void create(QOpenGLContext* sharedContext = nullptr);
bool makeCurrent();
void doneCurrent();
QOpenGLContext* getContext() {
return &_context;
}
protected:
QOpenGLContext _context;
QOffscreenSurface _offscreenSurface;
#ifdef DEBUG
QOpenGLDebugLogger* _logger{ nullptr };
#endif
};

View file

@ -1,43 +0,0 @@
//
// OffscreenGlCanvas.cpp
// interface/src/renderer
//
// Created by Bradley Austin Davis on 2014/04/09.
// Copyright 2015 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "OffscreenGlContext.h"
OffscreenGlContext::OffscreenGlContext() {
}
void OffscreenGlContext::create(QOpenGLContext * sharedContext) {
QSurfaceFormat format;
format.setDepthBufferSize(16);
format.setStencilBufferSize(8);
format.setMajorVersion(4);
format.setMinorVersion(1);
format.setProfile(QSurfaceFormat::OpenGLContextProfile::CompatibilityProfile);
_context.setFormat(format);
if (nullptr != sharedContext) {
_context.setShareContext(sharedContext);
}
_context.create();
_offscreenSurface.setFormat(_context.format());
_offscreenSurface.create();
}
bool OffscreenGlContext::makeCurrent() {
return _context.makeCurrent(&_offscreenSurface);
}
void OffscreenGlContext::doneCurrent() {
_context.doneCurrent();
}

View file

@ -1,33 +0,0 @@
//
// OffscreenGlCanvas.h
// interface/src/renderer
//
// Created by Bradley Austin Davis on 2014/04/09.
// 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
//
#pragma once
#ifndef hifi_OffscreenGlContext_h
#define hifi_OffscreenGlContext_h
#include <QOpenGLContext>
#include <QOffscreenSurface>
class OffscreenGlContext : public QObject {
public:
OffscreenGlContext();
void create(QOpenGLContext * sharedContext = nullptr);
bool makeCurrent();
void doneCurrent();
QOpenGLContext * getContext() {
return &_context;
}
protected:
QOpenGLContext _context;
QOffscreenSurface _offscreenSurface;
};
#endif // hifi_OffscreenGlCanvas_h

View file

@ -0,0 +1,16 @@
#include "GLHelpers.h"
QSurfaceFormat getDefaultOpenGlSurfaceFormat() {
QSurfaceFormat format;
// Qt Quick may need a depth and stencil buffer. Always make sure these are available.
format.setDepthBufferSize(DEFAULT_GL_DEPTH_BUFFER_BITS);
format.setStencilBufferSize(DEFAULT_GL_STENCIL_BUFFER_BITS);
format.setVersion(4, 1);
#ifdef DEBUG
format.setOption(QSurfaceFormat::DebugContext);
#endif
// FIXME move to core as soon as possible
format.setProfile(QSurfaceFormat::OpenGLContextProfile::CompatibilityProfile);
return format;
}

View file

@ -0,0 +1,23 @@
//
// Created by Bradley Austin Davis 2015/05/29
// Copyright 2014 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
//
#pragma once
#ifndef hifi_GLHelpers_h
#define hifi_GLHelpers_h
#include <QSurfaceFormat>
// 16 bits of depth precision
#define DEFAULT_GL_DEPTH_BUFFER_BITS 16
// 8 bits of stencil buffer (typically you really only need 1 bit for functionality
// but GL implementations usually just come with buffer sizes in multiples of 8)
#define DEFAULT_GL_STENCIL_BUFFER_BITS 8
QSurfaceFormat getDefaultOpenGlSurfaceFormat();
#endif

View file

@ -0,0 +1,38 @@
//
// ErrorDialog.cpp
//
// Created by David Rowe on 30 May 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
//
#include "ErrorDialog.h"
HIFI_QML_DEF(ErrorDialog)
ErrorDialog::ErrorDialog(QQuickItem* parent) : OffscreenQmlDialog(parent) {
}
ErrorDialog::~ErrorDialog() {
}
QString ErrorDialog::text() const {
return _text;
}
void ErrorDialog::setVisible(bool v) {
OffscreenQmlDialog::setVisible(v);
}
void ErrorDialog::setText(const QString& arg) {
if (arg != _text) {
_text = arg;
emit textChanged();
}
}
void ErrorDialog::accept() {
OffscreenQmlDialog::accept();
}

View file

@ -0,0 +1,46 @@
//
// ErrorDialog.h
//
// Created by David Rowe on 30 May 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
//
#pragma once
#ifndef hifi_ErrorDialog_h
#define hifi_ErrorDialog_h
#include "OffscreenQmlDialog.h"
class ErrorDialog : public OffscreenQmlDialog
{
Q_OBJECT
HIFI_QML_DECL
private:
Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
public:
ErrorDialog(QQuickItem* parent = 0);
virtual ~ErrorDialog();
QString text() const;
public slots:
virtual void setVisible(bool v);
void setText(const QString& arg);
signals:
void textChanged();
protected slots:
virtual void accept();
private:
QString _text;
};
#endif // hifi_ErrorDialog_h

View file

@ -13,6 +13,7 @@
#include <QOpenGLDebugLogger>
#include <QGLWidget>
#include <QtQml>
#include "ErrorDialog.h"
#include "MessageDialog.h"
@ -130,6 +131,15 @@ void OffscreenUi::critical(const QString& title, const QString& text,
static_cast<QMessageBox::Icon>(MessageDialog::Critical), buttons);
}
void OffscreenUi::error(const QString& text) {
ErrorDialog* pDialog{ nullptr };
ErrorDialog::show([&](QQmlContext* ctx, QObject* item) {
pDialog = item->findChild<ErrorDialog*>();
pDialog->setText(text);
});
pDialog->setEnabled(true);
}
OffscreenUi::ButtonCallback OffscreenUi::NO_OP_CALLBACK = [](QMessageBox::StandardButton) {};

View file

@ -115,6 +115,8 @@ public:
static void critical(const QString& title, const QString& text,
ButtonCallback callback = NO_OP_CALLBACK,
QMessageBox::StandardButtons buttons = QMessageBox::Ok);
static void error(const QString& text); // Interim dialog in new style
};
#endif