Merge branch 'master' of https://github.com/highfidelity/hifi into crashonexit

This commit is contained in:
ZappoMan 2015-02-24 15:33:41 -08:00
commit ca432a415f
42 changed files with 2735 additions and 2490 deletions

View file

@ -194,7 +194,7 @@ void Agent::run() {
// setup an Avatar for the script to use // setup an Avatar for the script to use
ScriptableAvatar scriptedAvatar(&_scriptEngine); ScriptableAvatar scriptedAvatar(&_scriptEngine);
scriptedAvatar.setForceFaceshiftConnected(true); scriptedAvatar.setForceFaceTrackerConnected(true);
// call model URL setters with empty URLs so our avatar, if user, will have the default models // call model URL setters with empty URLs so our avatar, if user, will have the default models
scriptedAvatar.setFaceModelURL(QUrl()); scriptedAvatar.setFaceModelURL(QUrl());

View file

@ -29,15 +29,21 @@ var RIGHT_BUTTON_FWD = 11;
var RIGHT_BUTTON_3 = 9; var RIGHT_BUTTON_3 = 9;
var BALL_RADIUS = 0.08; var BALL_RADIUS = 0.08;
var GRAVITY_STRENGTH = 1.0; var GRAVITY_STRENGTH = 3.0;
var HELD_COLOR = { red: 240, green: 0, blue: 0 }; var HELD_COLOR = { red: 240, green: 0, blue: 0 };
var THROWN_COLOR = { red: 128, green: 0, blue: 0 }; var THROWN_COLOR = { red: 128, green: 0, blue: 0 };
var averageLinearVelocity = [ { x: 0, y: 0, z : 0 }, { x: 0, y: 0, z : 0 } ];
var LIFETIME_SECONDS = 600;
var BALL_MODEL_URL = "https://hifi-public.s3.amazonaws.com/ryan/baseball4.fbx";
var leftBallAlreadyInHand = false; var leftBallAlreadyInHand = false;
var rightBallAlreadyInHand = false; var rightBallAlreadyInHand = false;
var leftHandEntity; var leftHandEntity = false;
var rightHandEntity; var rightHandEntity = false;
var newSound = SoundCache.getSound("https://dl.dropboxusercontent.com/u/1864924/hifi-sounds/throw.raw"); var newSound = SoundCache.getSound("https://dl.dropboxusercontent.com/u/1864924/hifi-sounds/throw.raw");
var catchSound = SoundCache.getSound("https://dl.dropboxusercontent.com/u/1864924/hifi-sounds/catch.raw"); var catchSound = SoundCache.getSound("https://dl.dropboxusercontent.com/u/1864924/hifi-sounds/catch.raw");
@ -67,28 +73,51 @@ function checkControllerSide(whichSide) {
var BUTTON_3; var BUTTON_3;
var TRIGGER; var TRIGGER;
var palmPosition; var palmPosition;
var palmRotation;
var ballAlreadyInHand; var ballAlreadyInHand;
var handMessage; var handMessage;
var linearVelocity;
var angularVelocity;
var AVERAGE_FACTOR = 0.33;
if (whichSide == LEFT_PALM) { if (whichSide == LEFT_PALM) {
BUTTON_FWD = LEFT_BUTTON_FWD; BUTTON_FWD = LEFT_BUTTON_FWD;
BUTTON_3 = LEFT_BUTTON_3; BUTTON_3 = LEFT_BUTTON_3;
TRIGGER = 0; TRIGGER = 0;
palmPosition = Controller.getSpatialControlPosition(LEFT_PALM); palmPosition = Controller.getSpatialControlPosition(LEFT_PALM);
palmRotation = Quat.multiply(MyAvatar.orientation, Controller.getSpatialControlRawRotation(LEFT_PALM));
ballAlreadyInHand = leftBallAlreadyInHand; ballAlreadyInHand = leftBallAlreadyInHand;
handMessage = "LEFT"; handMessage = "LEFT";
averageLinearVelocity[0] = Vec3.sum(Vec3.multiply(AVERAGE_FACTOR, Controller.getSpatialControlVelocity(LEFT_TIP)),
Vec3.multiply(1.0 - AVERAGE_FACTOR, averageLinearVelocity[0]));
linearVelocity = averageLinearVelocity[0];
angularVelocity = Vec3.multiplyQbyV(MyAvatar.orientation, Controller.getSpatialControlRawAngularVelocity(LEFT_TIP));
angularVelocity = Vec3.multiply(180.0 / Math.PI, angularVelocity);
} else { } else {
BUTTON_FWD = RIGHT_BUTTON_FWD; BUTTON_FWD = RIGHT_BUTTON_FWD;
BUTTON_3 = RIGHT_BUTTON_3; BUTTON_3 = RIGHT_BUTTON_3;
TRIGGER = 1; TRIGGER = 1;
palmPosition = Controller.getSpatialControlPosition(RIGHT_PALM); palmPosition = Controller.getSpatialControlPosition(RIGHT_PALM);
palmRotation = Quat.multiply(MyAvatar.orientation, Controller.getSpatialControlRawRotation(RIGHT_PALM));
ballAlreadyInHand = rightBallAlreadyInHand; ballAlreadyInHand = rightBallAlreadyInHand;
averageLinearVelocity[1] = Vec3.sum(Vec3.multiply(AVERAGE_FACTOR, Controller.getSpatialControlVelocity(RIGHT_TIP)),
Vec3.multiply(1.0 - AVERAGE_FACTOR, averageLinearVelocity[1]));
linearVelocity = averageLinearVelocity[1];
angularVelocity = Vec3.multiplyQbyV(MyAvatar.orientation, Controller.getSpatialControlRawAngularVelocity(RIGHT_TIP));
angularVelocity = Vec3.multiply(180.0 / Math.PI, angularVelocity);
handMessage = "RIGHT"; handMessage = "RIGHT";
} }
var grabButtonPressed = (Controller.isButtonPressed(BUTTON_FWD) || Controller.isButtonPressed(BUTTON_3) || (Controller.getTriggerValue(TRIGGER) > 0.5)); var grabButtonPressed = (Controller.isButtonPressed(BUTTON_FWD) || Controller.isButtonPressed(BUTTON_3) || (Controller.getTriggerValue(TRIGGER) > 0.5));
// If I don't currently have a ball in my hand, then try to catch closest one // If I don't currently have a ball in my hand, then try to catch closest one
if (leftHandEntity && !leftHandEntity.isKnownID) {
leftHandEntity = Entities.identifyEntity(leftHandEntity);
}
if (rightHandEntity && !rightHandEntity.isKnownID) {
rightHandEntity = Entities.identifyEntity(rightHandEntity);
}
if (!ballAlreadyInHand && grabButtonPressed) { if (!ballAlreadyInHand && grabButtonPressed) {
var closestEntity = Entities.findClosestEntity(palmPosition, targetRadius); var closestEntity = Entities.findClosestEntity(palmPosition, targetRadius);
@ -107,13 +136,14 @@ function checkControllerSide(whichSide) {
var properties = { position: { x: ballPosition.x, var properties = { position: { x: ballPosition.x,
y: ballPosition.y, y: ballPosition.y,
z: ballPosition.z }, z: ballPosition.z },
color: HELD_COLOR, rotation: palmRotation,
color: HELD_COLOR,
velocity : { x: 0, y: 0, z: 0}, velocity : { x: 0, y: 0, z: 0},
lifetime : 600, gravity: { x: 0, y: 0, z: 0}
inHand: true }; };
Entities.editEntity(closestEntity, properties); Entities.editEntity(closestEntity, properties);
Audio.playSound(catchSound, { position: ballPosition }); Audio.playSound(catchSound, { position: ballPosition });
return; // exit early return; // exit early
} }
@ -129,18 +159,20 @@ function checkControllerSide(whichSide) {
if (grabButtonPressed && !ballAlreadyInHand) { if (grabButtonPressed && !ballAlreadyInHand) {
var ballPosition = getBallHoldPosition(whichSide); var ballPosition = getBallHoldPosition(whichSide);
var properties = { var properties = {
type: "Sphere", type: "Model",
modelURL: BALL_MODEL_URL,
position: { x: ballPosition.x, position: { x: ballPosition.x,
y: ballPosition.y, y: ballPosition.y,
z: ballPosition.z }, z: ballPosition.z },
rotation: palmRotation,
velocity: { x: 0, y: 0, z: 0}, velocity: { x: 0, y: 0, z: 0},
gravity: { x: 0, y: 0, z: 0}, gravity: { x: 0, y: 0, z: 0},
inHand: true,
dimensions: { x: BALL_RADIUS * 2, y: BALL_RADIUS * 2, z: BALL_RADIUS * 2 }, dimensions: { x: BALL_RADIUS * 2, y: BALL_RADIUS * 2, z: BALL_RADIUS * 2 },
damping: 0.00001, damping: 0.00001,
shapeType: "sphere",
collisionsWillMove: false,
color: HELD_COLOR, color: HELD_COLOR,
lifetime: LIFETIME_SECONDS
lifetime: 600 // 10 seconds - same as default, not needed but here as an example
}; };
newEntity = Entities.addEntity(properties); newEntity = Entities.addEntity(properties);
@ -174,21 +206,20 @@ function checkControllerSide(whichSide) {
var properties = { position: { x: ballPosition.x, var properties = { position: { x: ballPosition.x,
y: ballPosition.y, y: ballPosition.y,
z: ballPosition.z }, z: ballPosition.z },
rotation: palmRotation,
velocity: { x: 0, y: 0, z: 0},
gravity: { x: 0, y: 0, z: 0},
}; };
Entities.editEntity(handEntity, properties); Entities.editEntity(handEntity, properties);
} else { } else {
debugPrint(">>>>> " + handMessage + "-BALL IN HAND, not grabbing, THROW!!!"); debugPrint(">>>>> " + handMessage + "-BALL IN HAND, not grabbing, THROW!!!");
// If toy ball just released, add velocity to it! // If toy ball just released, add velocity to it!
var tipVelocity = Controller.getSpatialControlVelocity(whichTip);
var THROWN_VELOCITY_SCALING = 1.5;
var properties = { var properties = {
velocity: { x: tipVelocity.x * THROWN_VELOCITY_SCALING, velocity: linearVelocity,
y: tipVelocity.y * THROWN_VELOCITY_SCALING, rotation: palmRotation,
z: tipVelocity.z * THROWN_VELOCITY_SCALING } , angularVelocity: angularVelocity,
collisionsWillMove: true, collisionsWillMove: true,
inHand: false,
color: THROWN_COLOR, color: THROWN_COLOR,
lifetime: 10,
gravity: { x: 0, y: -GRAVITY_STRENGTH, z: 0}, gravity: { x: 0, y: -GRAVITY_STRENGTH, z: 0},
}; };
@ -216,7 +247,7 @@ function checkController(deltaTime) {
// this is expected for hydras // this is expected for hydras
if (!(numberOfButtons==12 && numberOfTriggers == 2 && controllersPerTrigger == 2)) { if (!(numberOfButtons==12 && numberOfTriggers == 2 && controllersPerTrigger == 2)) {
debugPrint("no hydra connected?"); debugPrint("total buttons = " + numberOfButtons + ", Triggers = " + numberOfTriggers + ", controllers/trigger = " + controllersPerTrigger);
return; // bail if no hydra return; // bail if no hydra
} }

View file

@ -53,8 +53,10 @@ function shootDice(position, velocity) {
position: position, position: position,
velocity: velocity, velocity: velocity,
rotation: Quat.fromPitchYawRollDegrees(Math.random() * 360, Math.random() * 360, Math.random() * 360), rotation: Quat.fromPitchYawRollDegrees(Math.random() * 360, Math.random() * 360, Math.random() * 360),
angularVelocity: { x: Math.random() * 100, y: Math.random() * 100, z: Math.random() * 100 },
lifetime: LIFETIME, lifetime: LIFETIME,
gravity: { x: 0, y: GRAVITY, z: 0 }, gravity: { x: 0, y: GRAVITY, z: 0 },
shapeType: "box",
collisionsWillMove: true collisionsWillMove: true
})); }));
position = Vec3.sum(position, Vec3.multiply(DIE_SIZE, Vec3.normalize(Quat.getRight(Camera.getOrientation())))); position = Vec3.sum(position, Vec3.multiply(DIE_SIZE, Vec3.normalize(Quat.getRight(Camera.getOrientation()))));

View file

@ -105,37 +105,27 @@ function makeTable(pos) {
} }
function makeBalls(pos) { function makeBalls(pos) {
var colors = [{ red: 255, green: 255, blue: 0}, // Yellow
{ red: 0, green: 0, blue: 255}, // Blue
{ red: 255, green: 0, blue: 0}, // Red
{ red: 128, green: 0, blue: 128}, // Purple
{ red: 255, green: 165, blue: 0}, // Orange
{ red: 0, green: 255, blue: 0}, // Green
{ red: 128, green: 0, blue: 0}, // Maroon
{ red: 0, green: 0, blue: 0}, // Black
{ red: 255, green: 255, blue: 224}, // Light Yellow
{ red: 173, green: 216, blue: 230}, // Light Blue
{ red: 205, green: 92, blue: 92}, // Indian Red
{ red: 218, green: 112, blue: 214}, // Orchid
{ red: 218, green: 165, blue: 32}, // GoldenRod
{ red: 255, green: 99, blue: 71}, // Tomato
{ red: 128, green: 128, blue: 128}]; // Gray
// Object balls // Object balls
var whichBall = [ 1, 14, 15, 4, 8, 7, 12, 9, 3, 13, 10, 5, 6, 11, 2 ];
var ballNumber = 0;
var ballPosition = { x: pos.x + (LENGTH / 4.0) * SCALE, y: pos.y + HEIGHT / 2.0 + DROP_HEIGHT, z: pos.z }; var ballPosition = { x: pos.x + (LENGTH / 4.0) * SCALE, y: pos.y + HEIGHT / 2.0 + DROP_HEIGHT, z: pos.z };
for (var row = 1; row <= 5; row++) { for (var row = 1; row <= 5; row++) {
ballPosition.z = pos.z - ((row - 1.0) / 2.0 * (BALL_SIZE + BALL_GAP) * SCALE); ballPosition.z = pos.z - ((row - 1.0) / 2.0 * (BALL_SIZE + BALL_GAP) * SCALE);
for (var spot = 0; spot < row; spot++) { for (var spot = 0; spot < row; spot++) {
balls.push(Entities.addEntity( balls.push(Entities.addEntity(
{ type: "Sphere", { type: "Model",
modelURL: "https://s3.amazonaws.com/hifi-public/models/props/Pool/ball_" + whichBall[ballNumber].toString() + ".fbx",
position: ballPosition, position: ballPosition,
dimensions: { x: BALL_SIZE * SCALE, y: BALL_SIZE * SCALE, z: BALL_SIZE * SCALE }, dimensions: { x: BALL_SIZE * SCALE, y: BALL_SIZE * SCALE, z: BALL_SIZE * SCALE },
color: colors[balls.length], rotation: Quat.fromPitchYawRollDegrees((Math.random() - 0.5) * 20, (Math.random() - 0.5) * 20, (Math.random() - 0.5) * 20),
color: { red: 255, green: 255, blue: 255 },
gravity: { x: 0, y: GRAVITY, z: 0 }, gravity: { x: 0, y: GRAVITY, z: 0 },
ignoreCollisions: false, ignoreCollisions: false,
damping: 0.50, damping: 0.50,
shapeType: "sphere",
collisionsWillMove: true })); collisionsWillMove: true }));
ballPosition.z += (BALL_SIZE + BALL_GAP) * SCALE; ballPosition.z += (BALL_SIZE + BALL_GAP) * SCALE;
ballNumber++;
} }
ballPosition.x += (BALL_GAP + Math.sqrt(3.0) / 2.0 * BALL_SIZE) * SCALE; ballPosition.x += (BALL_GAP + Math.sqrt(3.0) / 2.0 * BALL_SIZE) * SCALE;
} }
@ -143,7 +133,8 @@ function makeBalls(pos) {
// Cue Ball // Cue Ball
cuePosition = { x: pos.x - (LENGTH / 4.0) * SCALE, y: pos.y + HEIGHT / 2.0 + DROP_HEIGHT, z: pos.z }; cuePosition = { x: pos.x - (LENGTH / 4.0) * SCALE, y: pos.y + HEIGHT / 2.0 + DROP_HEIGHT, z: pos.z };
cueBall = Entities.addEntity( cueBall = Entities.addEntity(
{ type: "Sphere", { type: "Model",
modelURL: "https://s3.amazonaws.com/hifi-public/models/props/Pool/cue_ball.fbx",
position: cuePosition, position: cuePosition,
dimensions: { x: BALL_SIZE * SCALE, y: BALL_SIZE * SCALE, z: BALL_SIZE * SCALE }, dimensions: { x: BALL_SIZE * SCALE, y: BALL_SIZE * SCALE, z: BALL_SIZE * SCALE },
color: { red: 255, green: 255, blue: 255 }, color: { red: 255, green: 255, blue: 255 },
@ -152,6 +143,7 @@ function makeBalls(pos) {
velocity: {x: 0, y: 0, z: 0 }, velocity: {x: 0, y: 0, z: 0 },
ignoreCollisions: false, ignoreCollisions: false,
damping: 0.50, damping: 0.50,
shapeType: "sphere",
collisionsWillMove: true }); collisionsWillMove: true });
} }

View file

@ -406,7 +406,7 @@
elModelAnimationFrame.addEventListener('change', createEmitNumberPropertyUpdateFunction('animationFrameIndex')); elModelAnimationFrame.addEventListener('change', createEmitNumberPropertyUpdateFunction('animationFrameIndex'));
elModelAnimationSettings.addEventListener('change', createEmitTextPropertyUpdateFunction('animationSettings')); elModelAnimationSettings.addEventListener('change', createEmitTextPropertyUpdateFunction('animationSettings'));
elModelTextures.addEventListener('change', createEmitTextPropertyUpdateFunction('textures')); elModelTextures.addEventListener('change', createEmitTextPropertyUpdateFunction('textures'));
elModelShapeType.addEventListener('change', createEmitNumberPropertyUpdateFunction('shapeType')); elModelShapeType.addEventListener('change', createEmitTextPropertyUpdateFunction('shapeType'));
elTextText.addEventListener('change', createEmitTextPropertyUpdateFunction('text')); elTextText.addEventListener('change', createEmitTextPropertyUpdateFunction('text'));
elTextLineHeight.addEventListener('change', createEmitNumberPropertyUpdateFunction('lineHeight')); elTextLineHeight.addEventListener('change', createEmitNumberPropertyUpdateFunction('lineHeight'));
@ -671,9 +671,9 @@
<div class="label">Shape Type</div> <div class="label">Shape Type</div>
<div class="value"> <div class="value">
<select name="SelectShapeType" id="property-model-shape" name="SelectShapeType"> <select name="SelectShapeType" id="property-model-shape" name="SelectShapeType">
<option value=0>None</option> <option value='none'>none</option>
<option value=1>Box</option> <option value='box'>box</option>
<option value=2>Sphere</option> <option value='sphere'>sphere</option>
</select> </select>
</div> </div>
</div> </div>

View file

@ -13,9 +13,14 @@ You may optionally choose to place this folder in a location outside the reposit
If so our CMake find module expects you to set the ENV variable 'HIFI_LIB_DIR' to a directory containing a subfolder faceshift that contains the lib and include folders. If so our CMake find module expects you to set the ENV variable 'HIFI_LIB_DIR' to a directory containing a subfolder faceshift that contains the lib and include folders.
1. Build a Faceshift static library from the fsbinarystream.cpp file. If you build a release version call it libfaceshift.a. The debug version should be called libfaceshiftd.a. Place this in the lib folder in your Faceshift folder. 1. Build a Faceshift static library from the fsbinarystream.cpp file.
Windows: Win32 console application; no precompiled header or SDL checks; no ATL or MFC headers; Project Properties, Configuration Type = Static Library (.lib).
2. Copy the fsbinarystream.h header file from the Faceshift SDK into the include folder in your Faceshift folder. 2. Copy the library files to the lib folder in your Faceshift folder.
OSX: If you build a release version call it libfaceshift.a. The debug version should be called libfaceshiftd.a.
Windows: The release and debug versions should be called faceshift.lib and faceshiftd.lib, respectively. Copy them into a Win32 folder in your lib folder.
3. Clear your build directory, run cmake and build, and you should be all set. 3. Copy the fsbinarystream.h header file from the Faceshift SDK into the include folder in your Faceshift folder.
4. Clear your build directory, run cmake and build, and you should be all set.

View file

@ -1626,6 +1626,16 @@ FaceTracker* Application::getActiveFaceTracker() {
(visage->isActive() ? static_cast<FaceTracker*>(visage.data()) : NULL))); (visage->isActive() ? static_cast<FaceTracker*>(visage.data()) : NULL)));
} }
void Application::setActiveFaceTracker() {
#ifdef HAVE_FACESHIFT
DependencyManager::get<Faceshift>()->setTCPEnabled(Menu::getInstance()->isOptionChecked(MenuOption::Faceshift));
#endif
DependencyManager::get<DdeFaceTracker>()->setEnabled(Menu::getInstance()->isOptionChecked(MenuOption::DDEFaceRegression));
#ifdef HAVE_VISAGE
DependencyManager::get<Visage>()->updateEnabled();
#endif
}
bool Application::exportEntities(const QString& filename, float x, float y, float z, float scale) { bool Application::exportEntities(const QString& filename, float x, float y, float z, float scale) {
QVector<EntityItem*> entities; QVector<EntityItem*> entities;
_entities.getTree()->findEntities(AACube(glm::vec3(x / (float)TREE_SCALE, _entities.getTree()->findEntities(AACube(glm::vec3(x / (float)TREE_SCALE,
@ -1743,6 +1753,7 @@ void Application::init() {
// initialize our face trackers after loading the menu settings // initialize our face trackers after loading the menu settings
DependencyManager::get<Faceshift>()->init(); DependencyManager::get<Faceshift>()->init();
DependencyManager::get<DdeFaceTracker>()->init();
DependencyManager::get<Visage>()->init(); DependencyManager::get<Visage>()->init();
Leapmotion::init(); Leapmotion::init();

View file

@ -366,6 +366,8 @@ public slots:
void notifyPacketVersionMismatch(); void notifyPacketVersionMismatch();
void setActiveFaceTracker();
private slots: private slots:
void clearDomainOctreeDetails(); void clearDomainOctreeDetails();
void checkFPS(); void checkFPS();

View file

@ -27,6 +27,7 @@
#include "audio/AudioIOStatsRenderer.h" #include "audio/AudioIOStatsRenderer.h"
#include "audio/AudioScope.h" #include "audio/AudioScope.h"
#include "avatar/AvatarManager.h" #include "avatar/AvatarManager.h"
#include "devices/DdeFaceTracker.h"
#include "devices/Faceshift.h" #include "devices/Faceshift.h"
#include "devices/RealSense.h" #include "devices/RealSense.h"
#include "devices/SixenseManager.h" #include "devices/SixenseManager.h"
@ -357,18 +358,35 @@ Menu::Menu() {
dialogsManager.data(), SLOT(lodTools())); dialogsManager.data(), SLOT(lodTools()));
QMenu* avatarDebugMenu = developerMenu->addMenu("Avatar"); QMenu* avatarDebugMenu = developerMenu->addMenu("Avatar");
QMenu* faceTrackingMenu = avatarDebugMenu->addMenu("Face Tracking");
{
QActionGroup* faceTrackerGroup = new QActionGroup(avatarDebugMenu);
QAction* noFaceTracker = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::NoFaceTracking,
0, true,
qApp, SLOT(setActiveFaceTracker()));
faceTrackerGroup->addAction(noFaceTracker);
#ifdef HAVE_FACESHIFT #ifdef HAVE_FACESHIFT
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, QAction* faceshiftFaceTracker = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::Faceshift,
MenuOption::Faceshift, 0, false,
0, qApp, SLOT(setActiveFaceTracker()));
true, faceTrackerGroup->addAction(faceshiftFaceTracker);
DependencyManager::get<Faceshift>().data(),
SLOT(setTCPEnabled(bool)));
#endif #endif
QAction* ddeFaceTracker = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::DDEFaceRegression,
0, false,
qApp, SLOT(setActiveFaceTracker()));
faceTrackerGroup->addAction(ddeFaceTracker);
#ifdef HAVE_VISAGE #ifdef HAVE_VISAGE
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::Visage, 0, false, QAction* visageFaceTracker = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::Visage,
DependencyManager::get<Visage>().data(), SLOT(updateEnabled())); 0, false,
qApp, SLOT(setActiveFaceTracker()));
faceTrackerGroup->addAction(visageFaceTracker);
#endif #endif
}
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderSkeletonCollisionShapes); addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderSkeletonCollisionShapes);
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderHeadCollisionShapes); addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderHeadCollisionShapes);

View file

@ -133,13 +133,12 @@ namespace MenuOption {
const QString CollideWithEnvironment = "Collide With World Boundaries"; const QString CollideWithEnvironment = "Collide With World Boundaries";
const QString Collisions = "Collisions"; const QString Collisions = "Collisions";
const QString Console = "Console..."; const QString Console = "Console...";
const QString ControlWithSpeech = "Control With Speech";
const QString CopyAddress = "Copy Address to Clipboard"; const QString CopyAddress = "Copy Address to Clipboard";
const QString CopyPath = "Copy Path to Clipboard"; const QString CopyPath = "Copy Path to Clipboard";
const QString ControlWithSpeech = "Control With Speech"; const QString DDEFaceRegression = "DDE Face Regression";
const QString DeleteBookmark = "Delete Bookmark...";
const QString DontRenderEntitiesAsScene = "Don't Render Entities as Scene";
const QString DontDoPrecisionPicking = "Don't Do Precision Picking";
const QString DecreaseAvatarSize = "Decrease Avatar Size"; const QString DecreaseAvatarSize = "Decrease Avatar Size";
const QString DeleteBookmark = "Delete Bookmark...";
const QString DisableActivityLogger = "Disable Activity Logger"; const QString DisableActivityLogger = "Disable Activity Logger";
const QString DisableAutoAdjustLOD = "Disable Automatically Adjusting LOD"; const QString DisableAutoAdjustLOD = "Disable Automatically Adjusting LOD";
const QString DisableLightEntities = "Disable Light Entities"; const QString DisableLightEntities = "Disable Light Entities";
@ -152,7 +151,9 @@ namespace MenuOption {
const QString DisplayModelElementChildProxies = "Display Model Element Children"; const QString DisplayModelElementChildProxies = "Display Model Element Children";
const QString DisplayModelElementProxy = "Display Model Element Bounds"; const QString DisplayModelElementProxy = "Display Model Element Bounds";
const QString DisplayTimingDetails = "Display Timing Details"; const QString DisplayTimingDetails = "Display Timing Details";
const QString DontDoPrecisionPicking = "Don't Do Precision Picking";
const QString DontFadeOnOctreeServerChanges = "Don't Fade In/Out on Octree Server Changes"; const QString DontFadeOnOctreeServerChanges = "Don't Fade In/Out on Octree Server Changes";
const QString DontRenderEntitiesAsScene = "Don't Render Entities as Scene";
const QString EchoLocalAudio = "Echo Local Audio"; const QString EchoLocalAudio = "Echo Local Audio";
const QString EchoServerAudio = "Echo Server Audio"; const QString EchoServerAudio = "Echo Server Audio";
const QString EditEntitiesHelp = "Edit Entities Help..."; const QString EditEntitiesHelp = "Edit Entities Help...";
@ -192,6 +193,7 @@ namespace MenuOption {
const QString MuteEnvironment = "Mute Environment"; const QString MuteEnvironment = "Mute Environment";
const QString NetworkSimulator = "Network Simulator..."; const QString NetworkSimulator = "Network Simulator...";
const QString NewVoxelCullingMode = "New Voxel Culling Mode"; const QString NewVoxelCullingMode = "New Voxel Culling Mode";
const QString NoFaceTracking = "None";
const QString ObeyEnvironmentalGravity = "Obey Environmental Gravity"; const QString ObeyEnvironmentalGravity = "Obey Environmental Gravity";
const QString OctreeStats = "Voxel and Entity Statistics"; const QString OctreeStats = "Voxel and Entity Statistics";
const QString OffAxisProjection = "Off-Axis Projection"; const QString OffAxisProjection = "Off-Axis Projection";

View file

@ -12,6 +12,9 @@
#include <QStyle> #include <QStyle>
#include <QStyleOptionTitleBar> #include <QStyleOptionTitleBar>
#include "DependencyManager.h"
#include "GLCanvas.h"
#include "UIUtil.h" #include "UIUtil.h"
int UIUtil::getWindowTitleBarHeight(const QWidget* window) { int UIUtil::getWindowTitleBarHeight(const QWidget* window) {
@ -27,3 +30,49 @@ int UIUtil::getWindowTitleBarHeight(const QWidget* window) {
return titleBarHeight; return titleBarHeight;
} }
// When setting the font size of a widget in points, the rendered text will be larger
// on Windows and Linux than on Mac OSX. This is because Windows and Linux use a DPI
// of 96, while OSX uses 72. In order to get consistent results across platforms, the
// font sizes need to be scaled based on the system DPI.
// This function will scale the font size of widget and all
// of its children recursively.
//
// When creating widgets, if a font size isn't explicitly set Qt will choose a
// reasonable, but often different font size across platforms. This means
// YOU SHOUD EXPLICITLY SET ALL FONT SIZES and call this function OR not use
// this function at all. If you mix both you will end up with inconsistent results
// across platforms.
void UIUtil::scaleWidgetFontSizes(QWidget* widget) {
auto glCanvas = DependencyManager::get<GLCanvas>();
// This is the base dpi that we are targetting. This is based on Mac OSXs default DPI,
// and is the basis for all font sizes.
const float BASE_DPI = 72.0f;
#ifdef Q_OS_MAC
const float NATIVE_DPI = 72.0f;
#else
const float NATIVE_DPI = 96.0f;
#endif
// Scale fonts based on the native dpi. On Windows, where the native DPI is 96,
// the scale will be: 72.0 / 96.0 = 0.75
float fontScale = BASE_DPI / NATIVE_DPI;
internalScaleWidgetFontSizes(widget, fontScale);
}
// Depth-first traversal through widget hierarchy. It is important to do a depth-first
// traversal because modifying the font size of a parent node can affect children.
void UIUtil::internalScaleWidgetFontSizes(QWidget* widget, float scale) {
for (auto child : widget->findChildren<QWidget*>()) {
if (child->parent() == widget) {
internalScaleWidgetFontSizes(child, scale);
}
}
QFont font = widget->font();
font.setPointSizeF(font.pointSizeF() * scale);
widget->setFont(font);
}

View file

@ -18,7 +18,10 @@
class UIUtil { class UIUtil {
public: public:
static int getWindowTitleBarHeight(const QWidget* window); static int getWindowTitleBarHeight(const QWidget* window);
static void scaleWidgetFontSizes(QWidget* widget);
private:
static void internalScaleWidgetFontSizes(QWidget* widget, float scale);
}; };
#endif // hifi_UIUtil_h #endif // hifi_UIUtil_h

View file

@ -75,4 +75,4 @@ private:
}; };
#endif // hifi_AudioScope_h #endif // hifi_AudioScope_h

View file

@ -537,18 +537,13 @@ void Avatar::renderBillboard() {
return; return;
} }
if (!_billboardTexture) { if (!_billboardTexture) {
QImage image = QImage::fromData(_billboard); // Using a unique URL ensures we don't get another avatar's texture from TextureCache
if (image.format() != QImage::Format_ARGB32) { QUrl uniqueUrl = QUrl(QUuid::createUuid().toString());
image = image.convertToFormat(QImage::Format_ARGB32); _billboardTexture = DependencyManager::get<TextureCache>()->getTexture(
} uniqueUrl, DEFAULT_TEXTURE, false, _billboard);
_billboardTexture.reset(new Texture()); }
glBindTexture(GL_TEXTURE_2D, _billboardTexture->getID()); if (!_billboardTexture->isLoaded()) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width(), image.height(), 0, return;
GL_BGRA, GL_UNSIGNED_BYTE, image.constBits());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
} else {
glBindTexture(GL_TEXTURE_2D, _billboardTexture->getID());
} }
glEnable(GL_ALPHA_TEST); glEnable(GL_ALPHA_TEST);
@ -556,6 +551,8 @@ void Avatar::renderBillboard() {
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
glDisable(GL_LIGHTING); glDisable(GL_LIGHTING);
glBindTexture(GL_TEXTURE_2D, _billboardTexture->getID());
glPushMatrix(); glPushMatrix();
glTranslatef(_position.x, _position.y, _position.z); glTranslatef(_position.x, _position.y, _position.z);

View file

@ -234,7 +234,7 @@ protected:
private: private:
bool _initialized; bool _initialized;
QScopedPointer<Texture> _billboardTexture; NetworkTexturePointer _billboardTexture;
bool _shouldRenderBillboard; bool _shouldRenderBillboard;
bool _isLookAtTarget; bool _isLookAtTarget;

View file

@ -80,15 +80,10 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) {
// Only use face trackers when not playing back a recording. // Only use face trackers when not playing back a recording.
if (!myAvatar->isPlaying()) { if (!myAvatar->isPlaying()) {
FaceTracker* faceTracker = Application::getInstance()->getActiveFaceTracker(); FaceTracker* faceTracker = Application::getInstance()->getActiveFaceTracker();
auto dde = DependencyManager::get<DdeFaceTracker>(); _isFaceTrackerConnected = faceTracker != NULL;
auto faceshift = DependencyManager::get<Faceshift>(); if (_isFaceTrackerConnected) {
if ((_isFaceshiftConnected = (faceshift == faceTracker))) {
_blendshapeCoefficients = faceTracker->getBlendshapeCoefficients(); _blendshapeCoefficients = faceTracker->getBlendshapeCoefficients();
} else if (dde->isActive()) { }
faceTracker = dde.data();
_blendshapeCoefficients = faceTracker->getBlendshapeCoefficients();
}
} }
// Twist the upper body to follow the rotation of the head, but only do this with my avatar, // Twist the upper body to follow the rotation of the head, but only do this with my avatar,
// since everyone else will see the full joint rotations for other people. // since everyone else will see the full joint rotations for other people.
@ -109,7 +104,7 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) {
_longTermAverageLoudness = glm::mix(_longTermAverageLoudness, _averageLoudness, glm::min(deltaTime / AUDIO_LONG_TERM_AVERAGING_SECS, 1.0f)); _longTermAverageLoudness = glm::mix(_longTermAverageLoudness, _averageLoudness, glm::min(deltaTime / AUDIO_LONG_TERM_AVERAGING_SECS, 1.0f));
} }
if (!(_isFaceshiftConnected || billboard)) { if (!(_isFaceTrackerConnected || billboard)) {
// Update eye saccades // Update eye saccades
const float AVERAGE_MICROSACCADE_INTERVAL = 0.50f; const float AVERAGE_MICROSACCADE_INTERVAL = 0.50f;
const float AVERAGE_SACCADE_INTERVAL = 4.0f; const float AVERAGE_SACCADE_INTERVAL = 4.0f;

View file

@ -44,58 +44,40 @@ struct Packet{
}; };
DdeFaceTracker::DdeFaceTracker() : DdeFaceTracker::DdeFaceTracker() :
_lastReceiveTimestamp(0), DdeFaceTracker(QHostAddress::Any, DDE_FEATURE_POINT_SERVER_PORT)
_reset(false), {
_leftBlinkIndex(0), // see http://support.faceshift.com/support/articles/35129-export-of-blendshapes
_rightBlinkIndex(1), }
_leftEyeOpenIndex(8),
_rightEyeOpenIndex(9), DdeFaceTracker::DdeFaceTracker(const QHostAddress& host, quint16 port) :
_browDownLeftIndex(14), _lastReceiveTimestamp(0),
_browDownRightIndex(15), _reset(false),
_browUpCenterIndex(16), _leftBlinkIndex(0), // see http://support.faceshift.com/support/articles/35129-export-of-blendshapes
_browUpLeftIndex(17), _rightBlinkIndex(1),
_browUpRightIndex(18), _leftEyeOpenIndex(8),
_mouthSmileLeftIndex(28), _rightEyeOpenIndex(9),
_mouthSmileRightIndex(29), _browDownLeftIndex(14),
_jawOpenIndex(21) _browDownRightIndex(15),
_browUpCenterIndex(16),
_browUpLeftIndex(17),
_browUpRightIndex(18),
_mouthSmileLeftIndex(28),
_mouthSmileRightIndex(29),
_jawOpenIndex(21),
_host(host),
_port(port)
{ {
_blendshapeCoefficients.resize(NUM_EXPRESSION); _blendshapeCoefficients.resize(NUM_EXPRESSION);
connect(&_udpSocket, SIGNAL(readyRead()), SLOT(readPendingDatagrams())); connect(&_udpSocket, SIGNAL(readyRead()), SLOT(readPendingDatagrams()));
connect(&_udpSocket, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(socketErrorOccurred(QAbstractSocket::SocketError))); connect(&_udpSocket, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(socketErrorOccurred(QAbstractSocket::SocketError)));
connect(&_udpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), SLOT(socketStateChanged(QAbstractSocket::SocketState))); connect(&_udpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), SLOT(socketStateChanged(QAbstractSocket::SocketState)));
bindTo(DDE_FEATURE_POINT_SERVER_PORT);
}
DdeFaceTracker::DdeFaceTracker(const QHostAddress& host, quint16 port) :
_lastReceiveTimestamp(0),
_reset(false),
_leftBlinkIndex(0), // see http://support.faceshift.com/support/articles/35129-export-of-blendshapes
_rightBlinkIndex(1),
_leftEyeOpenIndex(8),
_rightEyeOpenIndex(9),
_browDownLeftIndex(14),
_browDownRightIndex(15),
_browUpCenterIndex(16),
_browUpLeftIndex(17),
_browUpRightIndex(18),
_mouthSmileLeftIndex(28),
_mouthSmileRightIndex(29),
_jawOpenIndex(21)
{
_blendshapeCoefficients.resize(NUM_EXPRESSION);
connect(&_udpSocket, SIGNAL(readyRead()), SLOT(readPendingDatagrams()));
connect(&_udpSocket, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(socketErrorOccurred(QAbstractSocket::SocketError)));
connect(&_udpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), SIGNAL(socketStateChanged(QAbstractSocket::SocketState)));
bindTo(host, port);
} }
DdeFaceTracker::~DdeFaceTracker() { DdeFaceTracker::~DdeFaceTracker() {
if(_udpSocket.isOpen()) if (_udpSocket.isOpen()) {
_udpSocket.close(); _udpSocket.close();
}
} }
void DdeFaceTracker::init() { void DdeFaceTracker::init() {
@ -110,15 +92,12 @@ void DdeFaceTracker::update() {
} }
void DdeFaceTracker::bindTo(quint16 port) { void DdeFaceTracker::setEnabled(bool enabled) {
bindTo(QHostAddress::Any, port); // isOpen() does not work as one might expect on QUdpSocket; don't test isOpen() before closing socket.
} _udpSocket.close();
if (enabled) {
void DdeFaceTracker::bindTo(const QHostAddress& host, quint16 port) { _udpSocket.bind(_host, _port);
if(_udpSocket.isOpen()) {
_udpSocket.close();
} }
_udpSocket.bind(host, port);
} }
bool DdeFaceTracker::isActive() const { bool DdeFaceTracker::isActive() const {
@ -135,7 +114,7 @@ void DdeFaceTracker::socketStateChanged(QAbstractSocket::SocketState socketState
QString state; QString state;
switch(socketState) { switch(socketState) {
case QAbstractSocket::BoundState: case QAbstractSocket::BoundState:
state = "Bounded"; state = "Bound";
break; break;
case QAbstractSocket::ClosingState: case QAbstractSocket::ClosingState:
state = "Closing"; state = "Closing";
@ -156,7 +135,7 @@ void DdeFaceTracker::socketStateChanged(QAbstractSocket::SocketState socketState
state = "Unconnected"; state = "Unconnected";
break; break;
} }
qDebug() << "[Info] DDE Face Tracker Socket: " << socketState; qDebug() << "[Info] DDE Face Tracker Socket: " << state;
} }
void DdeFaceTracker::readPendingDatagrams() { void DdeFaceTracker::readPendingDatagrams() {

View file

@ -28,9 +28,6 @@ public:
void reset(); void reset();
void update(); void update();
//sockets
void bindTo(quint16 port);
void bindTo(const QHostAddress& host, quint16 port);
bool isActive() const; bool isActive() const;
float getLeftBlink() const { return getBlendshapeCoefficient(_leftBlinkIndex); } float getLeftBlink() const { return getBlendshapeCoefficient(_leftBlinkIndex); }
@ -47,7 +44,10 @@ public:
float getMouthSize() const { return getBlendshapeCoefficient(_jawOpenIndex); } float getMouthSize() const { return getBlendshapeCoefficient(_jawOpenIndex); }
float getMouthSmileLeft() const { return getBlendshapeCoefficient(_mouthSmileLeftIndex); } float getMouthSmileLeft() const { return getBlendshapeCoefficient(_mouthSmileLeftIndex); }
float getMouthSmileRight() const { return getBlendshapeCoefficient(_mouthSmileRightIndex); } float getMouthSmileRight() const { return getBlendshapeCoefficient(_mouthSmileRightIndex); }
public slots:
void setEnabled(bool enabled);
private slots: private slots:
//sockets //sockets
@ -59,6 +59,9 @@ private:
DdeFaceTracker(); DdeFaceTracker();
DdeFaceTracker(const QHostAddress& host, quint16 port); DdeFaceTracker(const QHostAddress& host, quint16 port);
~DdeFaceTracker(); ~DdeFaceTracker();
QHostAddress _host;
quint16 _port;
float getBlendshapeCoefficient(int index) const; float getBlendshapeCoefficient(int index) const;
void decodePacket(const QByteArray& buffer); void decodePacket(const QByteArray& buffer);

View file

@ -260,6 +260,18 @@ void SixenseManager::update(float deltaTime) {
float sign = (i == 0) ? -1.0f : 1.0f; float sign = (i == 0) ? -1.0f : 1.0f;
rotation *= glm::angleAxis(sign * PI/4.0f, glm::vec3(0.0f, 0.0f, 1.0f)); rotation *= glm::angleAxis(sign * PI/4.0f, glm::vec3(0.0f, 0.0f, 1.0f));
// Angular Velocity of Palm
glm::quat deltaRotation = rotation * glm::inverse(palm->getRawRotation());
glm::vec3 angularVelocity(0.0f);
float rotationAngle = glm::angle(deltaRotation);
if ((rotationAngle > EPSILON) && (deltaTime > 0.0f)) {
angularVelocity = glm::normalize(glm::axis(deltaRotation));
angularVelocity *= (rotationAngle / deltaTime);
palm->setRawAngularVelocity(angularVelocity);
} else {
palm->setRawAngularVelocity(glm::vec3(0.0f));
}
if (_lowVelocityFilter) { if (_lowVelocityFilter) {
// Use a velocity sensitive filter to damp small motions and preserve large ones with // Use a velocity sensitive filter to damp small motions and preserve large ones with
// no latency. // no latency.

View file

@ -174,7 +174,8 @@ void Visage::reset() {
void Visage::updateEnabled() { void Visage::updateEnabled() {
setEnabled(Menu::getInstance()->isOptionChecked(MenuOption::Visage) && setEnabled(Menu::getInstance()->isOptionChecked(MenuOption::Visage) &&
!(Menu::getInstance()->isOptionChecked(MenuOption::Faceshift) && !(Menu::getInstance()->isOptionChecked(MenuOption::Faceshift) &&
DependencyManager::get<Faceshift>()->isConnectedOrConnecting())); DependencyManager::get<Faceshift>()->isConnectedOrConnecting()) &&
!Menu::getInstance()->isOptionChecked(MenuOption::DDEFaceRegression));
} }
void Visage::setEnabled(bool enabled) { void Visage::setEnabled(bool enabled) {

View file

@ -208,6 +208,21 @@ glm::quat ControllerScriptingInterface::getSpatialControlRawRotation(int control
} }
return glm::quat(); // bad index return glm::quat(); // bad index
} }
glm::vec3 ControllerScriptingInterface::getSpatialControlRawAngularVelocity(int controlIndex) const {
int palmIndex = controlIndex / NUMBER_OF_SPATIALCONTROLS_PER_PALM;
int controlOfPalm = controlIndex % NUMBER_OF_SPATIALCONTROLS_PER_PALM;
const PalmData* palmData = getActivePalm(palmIndex);
if (palmData) {
switch (controlOfPalm) {
case PALM_SPATIALCONTROL:
return palmData->getRawAngularVelocity();
case TIP_SPATIALCONTROL:
return palmData->getRawAngularVelocity(); // Tip = palm angular velocity
}
}
return glm::vec3(0); // bad index
}
glm::vec3 ControllerScriptingInterface::getSpatialControlNormal(int controlIndex) const { glm::vec3 ControllerScriptingInterface::getSpatialControlNormal(int controlIndex) const {
int palmIndex = controlIndex / NUMBER_OF_SPATIALCONTROLS_PER_PALM; int palmIndex = controlIndex / NUMBER_OF_SPATIALCONTROLS_PER_PALM;

View file

@ -96,6 +96,7 @@ public slots:
virtual glm::vec3 getSpatialControlVelocity(int controlIndex) const; virtual glm::vec3 getSpatialControlVelocity(int controlIndex) const;
virtual glm::vec3 getSpatialControlNormal(int controlIndex) const; virtual glm::vec3 getSpatialControlNormal(int controlIndex) const;
virtual glm::quat getSpatialControlRawRotation(int controlIndex) const; virtual glm::quat getSpatialControlRawRotation(int controlIndex) const;
virtual glm::vec3 getSpatialControlRawAngularVelocity(int controlIndex) const;
virtual void captureKeyEvents(const KeyEvent& event); virtual void captureKeyEvents(const KeyEvent& event);
virtual void releaseKeyEvents(const KeyEvent& event); virtual void releaseKeyEvents(const KeyEvent& event);

View file

@ -48,7 +48,6 @@ QScriptValue HMDScriptingInterface::getHUDLookAtPosition2D(QScriptContext* conte
QScriptValue HMDScriptingInterface::getHUDLookAtPosition3D(QScriptContext* context, QScriptEngine* engine) { QScriptValue HMDScriptingInterface::getHUDLookAtPosition3D(QScriptContext* context, QScriptEngine* engine) {
glm::vec3 result; glm::vec3 result;
HMDScriptingInterface* hmdInterface = &HMDScriptingInterface::getInstance();
if ((&HMDScriptingInterface::getInstance())->getHUDLookAtPosition3D(result)) { if ((&HMDScriptingInterface::getInstance())->getHUDLookAtPosition3D(result)) {
return qScriptValueFromValue<glm::vec3>(engine, result); return qScriptValueFromValue<glm::vec3>(engine, result);
} }

View file

@ -136,10 +136,10 @@ ApplicationOverlay::ApplicationOverlay() :
_textureFov(glm::radians(DEFAULT_OCULUS_UI_ANGULAR_SIZE)), _textureFov(glm::radians(DEFAULT_OCULUS_UI_ANGULAR_SIZE)),
_textureAspectRatio(1.0f), _textureAspectRatio(1.0f),
_lastMouseMove(0), _lastMouseMove(0),
_magnifier(true),
_alpha(1.0f), _alpha(1.0f),
_oculusUIRadius(1.0f), _oculusUIRadius(1.0f),
_crosshairTexture(0), _crosshairTexture(0),
_magnifier(true),
_previousBorderWidth(-1), _previousBorderWidth(-1),
_previousBorderHeight(-1), _previousBorderHeight(-1),
_previousMagnifierBottomLeft(), _previousMagnifierBottomLeft(),

View file

@ -21,6 +21,7 @@
#include "AccountManager.h" #include "AccountManager.h"
#include "ui_loginDialog.h" #include "ui_loginDialog.h"
#include "LoginDialog.h" #include "LoginDialog.h"
#include "UIUtil.h"
const QString FORGOT_PASSWORD_URL = "https://metaverse.highfidelity.io/users/password/new"; const QString FORGOT_PASSWORD_URL = "https://metaverse.highfidelity.io/users/password/new";
@ -42,6 +43,8 @@ LoginDialog::LoginDialog(QWidget* parent) :
connect(_ui->closeButton, &QPushButton::clicked, connect(_ui->closeButton, &QPushButton::clicked,
this, &LoginDialog::close); this, &LoginDialog::close);
UIUtil::scaleWidgetFontSizes(this);
// Initialize toggle connection // Initialize toggle connection
toggleQAction(); toggleQAction();
}; };

View file

@ -10,6 +10,7 @@
// //
#include <QFileDialog> #include <QFileDialog>
#include <QFont>
#include <AudioClient.h> #include <AudioClient.h>
#include <avatar/AvatarManager.h> #include <avatar/AvatarManager.h>
@ -23,6 +24,7 @@
#include "PreferencesDialog.h" #include "PreferencesDialog.h"
#include "Snapshot.h" #include "Snapshot.h"
#include "UserActivityLogger.h" #include "UserActivityLogger.h"
#include "UIUtil.h"
const int PREFERENCES_HEIGHT_PADDING = 20; const int PREFERENCES_HEIGHT_PADDING = 20;
@ -46,6 +48,8 @@ PreferencesDialog::PreferencesDialog(QWidget* parent) :
// move dialog to left side // move dialog to left side
move(parentWidget()->geometry().topLeft()); move(parentWidget()->geometry().topLeft());
setFixedHeight(parentWidget()->size().height() - PREFERENCES_HEIGHT_PADDING); setFixedHeight(parentWidget()->size().height() - PREFERENCES_HEIGHT_PADDING);
UIUtil::scaleWidgetFontSizes(this);
} }
void PreferencesDialog::accept() { void PreferencesDialog::accept() {

View file

@ -64,6 +64,8 @@ RunningScriptsWidget::RunningScriptsWidget(QWidget* parent) :
connect(ui->loadScriptFromURLButton, &QPushButton::clicked, connect(ui->loadScriptFromURLButton, &QPushButton::clicked,
Application::getInstance(), &Application::loadScriptURLDialog); Application::getInstance(), &Application::loadScriptURLDialog);
connect(&_signalMapper, SIGNAL(mapped(QString)), Application::getInstance(), SLOT(stopScript(const QString&))); connect(&_signalMapper, SIGNAL(mapped(QString)), Application::getInstance(), SLOT(stopScript(const QString&)));
UIUtil::scaleWidgetFontSizes(this);
} }
RunningScriptsWidget::~RunningScriptsWidget() { RunningScriptsWidget::~RunningScriptsWidget() {
@ -103,6 +105,7 @@ void RunningScriptsWidget::setRunningScripts(const QStringList& list) {
hash.insert(list.at(i), 1); hash.insert(list.at(i), 1);
} }
QWidget* row = new QWidget(ui->scriptListWidget); QWidget* row = new QWidget(ui->scriptListWidget);
row->setFont(ui->scriptListWidget->font());
row->setLayout(new QHBoxLayout(row)); row->setLayout(new QHBoxLayout(row));
QUrl url = QUrl(list.at(i)); QUrl url = QUrl(list.at(i));

File diff suppressed because it is too large Load diff

View file

@ -10,6 +10,12 @@
<height>728</height> <height>728</height>
</rect> </rect>
</property> </property>
<property name="font">
<font>
<family>Helvetica,Arial,sans-serif</family>
<pointsize>13</pointsize>
</font>
</property>
<property name="windowTitle"> <property name="windowTitle">
<string>Running Scripts</string> <string>Running Scripts</string>
</property> </property>
@ -31,6 +37,12 @@
<height>141</height> <height>141</height>
</size> </size>
</property> </property>
<property name="font">
<font>
<family>Helvetica,Arial,sans-serif</family>
<pointsize>13</pointsize>
</font>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4"> <layout class="QVBoxLayout" name="verticalLayout_4">
<property name="spacing"> <property name="spacing">
<number>0</number> <number>0</number>
@ -113,6 +125,12 @@ font: bold 16pt;
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="font">
<font>
<family>Helvetica,Arial,sans-serif</family>
<pointsize>13</pointsize>
</font>
</property>
<property name="styleSheet"> <property name="styleSheet">
<string notr="true">reloadStopButtonArea { padding: 0 }</string> <string notr="true">reloadStopButtonArea { padding: 0 }</string>
</property> </property>
@ -131,6 +149,12 @@ font: bold 16pt;
</property> </property>
<item> <item>
<widget class="QPushButton" name="reloadAllButton"> <widget class="QPushButton" name="reloadAllButton">
<property name="font">
<font>
<family>Helvetica,Arial,sans-serif</family>
<pointsize>13</pointsize>
</font>
</property>
<property name="text"> <property name="text">
<string>Reload all</string> <string>Reload all</string>
</property> </property>
@ -138,6 +162,12 @@ font: bold 16pt;
</item> </item>
<item> <item>
<widget class="QPushButton" name="stopAllButton"> <widget class="QPushButton" name="stopAllButton">
<property name="font">
<font>
<family>Helvetica,Arial,sans-serif</family>
<pointsize>13</pointsize>
</font>
</property>
<property name="text"> <property name="text">
<string>Stop all</string> <string>Stop all</string>
</property> </property>
@ -167,6 +197,12 @@ font: bold 16pt;
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="font">
<font>
<family>Helvetica,Arial,sans-serif</family>
<pointsize>13</pointsize>
</font>
</property>
<layout class="QVBoxLayout" name="verticalLayout_8"> <layout class="QVBoxLayout" name="verticalLayout_8">
<property name="spacing"> <property name="spacing">
<number>0</number> <number>0</number>
@ -191,8 +227,14 @@ font: bold 16pt;
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="font">
<font>
<family>Helvetica,Arial,sans-serif</family>
<pointsize>14</pointsize>
</font>
</property>
<property name="styleSheet"> <property name="styleSheet">
<string notr="true">font: 14pt; color: #5f5f5f; margin: 2px;</string> <string notr="true">color: #5f5f5f; margin: 2px;</string>
</property> </property>
<property name="text"> <property name="text">
<string>There are no scripts running.</string> <string>There are no scripts running.</string>
@ -255,12 +297,15 @@ font: bold 16pt;
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="font">
<font>
<family>Helvetica,Arial,sans-serif</family>
<pointsize>14</pointsize>
</font>
</property>
<property name="layoutDirection"> <property name="layoutDirection">
<enum>Qt::LeftToRight</enum> <enum>Qt::LeftToRight</enum>
</property> </property>
<property name="styleSheet">
<string notr="true">font-size: 14pt;</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3"> <layout class="QVBoxLayout" name="verticalLayout_3">
<property name="spacing"> <property name="spacing">
<number>0</number> <number>0</number>
@ -279,6 +324,12 @@ font: bold 16pt;
</property> </property>
<item> <item>
<widget class="QWidget" name="scriptListWidget" native="true"> <widget class="QWidget" name="scriptListWidget" native="true">
<property name="font">
<font>
<family>Helvetica,Arial,sans-serif</family>
<pointsize>14</pointsize>
</font>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5"> <layout class="QVBoxLayout" name="verticalLayout_5">
<property name="spacing"> <property name="spacing">
<number>0</number> <number>0</number>
@ -300,8 +351,14 @@ font: bold 16pt;
</item> </item>
<item> <item>
<widget class="QLabel" name="tipLabel"> <widget class="QLabel" name="tipLabel">
<property name="font">
<font>
<family>Helvetica,Arial,sans-serif</family>
<pointsize>14</pointsize>
</font>
</property>
<property name="styleSheet"> <property name="styleSheet">
<string notr="true">font: 14pt; color: #5f5f5f; margin: 2px;</string> <string notr="true">color: #5f5f5f; margin: 2px;</string>
</property> </property>
<property name="text"> <property name="text">
<string>Tip</string> <string>Tip</string>

View file

@ -85,16 +85,9 @@ AudioClient::AudioClient() :
_isStereoInput(false), _isStereoInput(false),
_outputStarveDetectionStartTimeMsec(0), _outputStarveDetectionStartTimeMsec(0),
_outputStarveDetectionCount(0), _outputStarveDetectionCount(0),
_outputBufferSizeFrames("audioOutputBufferSize", _outputBufferSizeFrames("audioOutputBufferSize", DEFAULT_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES),
DEFAULT_MAX_FRAMES_OVER_DESIRED),
#ifdef Q_OS_ANDROID
_outputStarveDetectionEnabled("audioOutputStarveDetectionEnabled",
false),
#else
_outputStarveDetectionEnabled("audioOutputStarveDetectionEnabled", _outputStarveDetectionEnabled("audioOutputStarveDetectionEnabled",
DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_ENABLED), DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_ENABLED),
#endif
_outputStarveDetectionPeriodMsec("audioOutputStarveDetectionPeriod", _outputStarveDetectionPeriodMsec("audioOutputStarveDetectionPeriod",
DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_PERIOD), DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_PERIOD),
_outputStarveDetectionThreshold("audioOutputStarveDetectionThreshold", _outputStarveDetectionThreshold("audioOutputStarveDetectionThreshold",
@ -1090,19 +1083,23 @@ void AudioClient::outputNotify() {
if (recentUnfulfilled > 0) { if (recentUnfulfilled > 0) {
if (_outputStarveDetectionEnabled.get()) { if (_outputStarveDetectionEnabled.get()) {
quint64 now = usecTimestampNow() / 1000; quint64 now = usecTimestampNow() / 1000;
quint64 dt = now - _outputStarveDetectionStartTimeMsec; int dt = (int)(now - _outputStarveDetectionStartTimeMsec);
if (dt > _outputStarveDetectionPeriodMsec.get()) { if (dt > _outputStarveDetectionPeriodMsec.get()) {
_outputStarveDetectionStartTimeMsec = now; _outputStarveDetectionStartTimeMsec = now;
_outputStarveDetectionCount = 0; _outputStarveDetectionCount = 0;
} else { } else {
_outputStarveDetectionCount += recentUnfulfilled; _outputStarveDetectionCount += recentUnfulfilled;
if (_outputStarveDetectionCount > _outputStarveDetectionThreshold.get()) { if (_outputStarveDetectionCount > _outputStarveDetectionThreshold.get()) {
int newOutputBufferSizeFrames = _outputBufferSizeFrames.get() + 1;
qDebug() << "Starve detection threshold met, increasing buffer size to " << newOutputBufferSizeFrames;
setOutputBufferSize(newOutputBufferSizeFrames);
_outputStarveDetectionStartTimeMsec = now; _outputStarveDetectionStartTimeMsec = now;
_outputStarveDetectionCount = 0; _outputStarveDetectionCount = 0;
int oldOutputBufferSizeFrames = _outputBufferSizeFrames.get();
int newOutputBufferSizeFrames = oldOutputBufferSizeFrames + 1;
setOutputBufferSize(newOutputBufferSizeFrames);
newOutputBufferSizeFrames = _outputBufferSizeFrames.get();
if (newOutputBufferSizeFrames > oldOutputBufferSizeFrames) {
qDebug() << "Starve detection threshold met, increasing buffer size to " << newOutputBufferSizeFrames;
}
} }
} }
} }

View file

@ -57,7 +57,11 @@ static const int NUM_AUDIO_CHANNELS = 2;
static const int DEFAULT_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 3; static const int DEFAULT_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 3;
static const int MIN_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 1; static const int MIN_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 1;
static const int MAX_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 20; static const int MAX_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 20;
static const int DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_ENABLED = true; #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;
#endif
static const int DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_THRESHOLD = 3; static const int DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_THRESHOLD = 3;
static const quint64 DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_PERIOD = 10 * 1000; // 10 Seconds static const quint64 DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_PERIOD = 10 * 1000; // 10 Seconds

View file

@ -44,7 +44,7 @@ AvatarData::AvatarData() :
_handState(0), _handState(0),
_keyState(NO_KEY_DOWN), _keyState(NO_KEY_DOWN),
_isChatCirclingEnabled(false), _isChatCirclingEnabled(false),
_forceFaceshiftConnected(false), _forceFaceTrackerConnected(false),
_hasNewJointRotations(true), _hasNewJointRotations(true),
_headData(NULL), _headData(NULL),
_handData(NULL), _handData(NULL),
@ -136,8 +136,8 @@ QByteArray AvatarData::toByteArray() {
if (!_headData) { if (!_headData) {
_headData = new HeadData(this); _headData = new HeadData(this);
} }
if (_forceFaceshiftConnected) { if (_forceFaceTrackerConnected) {
_headData->_isFaceshiftConnected = true; _headData->_isFaceTrackerConnected = true;
} }
QByteArray avatarDataByteArray; QByteArray avatarDataByteArray;
@ -191,7 +191,7 @@ QByteArray AvatarData::toByteArray() {
setAtBit(bitItems, HAND_STATE_FINGER_POINTING_BIT); setAtBit(bitItems, HAND_STATE_FINGER_POINTING_BIT);
} }
// faceshift state // faceshift state
if (_headData->_isFaceshiftConnected) { if (_headData->_isFaceTrackerConnected) {
setAtBit(bitItems, IS_FACESHIFT_CONNECTED); setAtBit(bitItems, IS_FACESHIFT_CONNECTED);
} }
if (_isChatCirclingEnabled) { if (_isChatCirclingEnabled) {
@ -208,7 +208,7 @@ QByteArray AvatarData::toByteArray() {
} }
// If it is connected, pack up the data // If it is connected, pack up the data
if (_headData->_isFaceshiftConnected) { if (_headData->_isFaceTrackerConnected) {
memcpy(destinationBuffer, &_headData->_leftEyeBlink, sizeof(float)); memcpy(destinationBuffer, &_headData->_leftEyeBlink, sizeof(float));
destinationBuffer += sizeof(float); destinationBuffer += sizeof(float);
@ -417,7 +417,7 @@ int AvatarData::parseDataAtOffset(const QByteArray& packet, int offset) {
_handState = getSemiNibbleAt(bitItems, HAND_STATE_START_BIT) _handState = getSemiNibbleAt(bitItems, HAND_STATE_START_BIT)
+ (oneAtBit(bitItems, HAND_STATE_FINGER_POINTING_BIT) ? IS_FINGER_POINTING_FLAG : 0); + (oneAtBit(bitItems, HAND_STATE_FINGER_POINTING_BIT) ? IS_FINGER_POINTING_FLAG : 0);
_headData->_isFaceshiftConnected = oneAtBit(bitItems, IS_FACESHIFT_CONNECTED); _headData->_isFaceTrackerConnected = oneAtBit(bitItems, IS_FACESHIFT_CONNECTED);
_isChatCirclingEnabled = oneAtBit(bitItems, IS_CHAT_CIRCLING_ENABLED); _isChatCirclingEnabled = oneAtBit(bitItems, IS_CHAT_CIRCLING_ENABLED);
bool hasReferential = oneAtBit(bitItems, HAS_REFERENTIAL); bool hasReferential = oneAtBit(bitItems, HAS_REFERENTIAL);
@ -436,7 +436,7 @@ int AvatarData::parseDataAtOffset(const QByteArray& packet, int offset) {
} }
if (_headData->_isFaceshiftConnected) { if (_headData->_isFaceTrackerConnected) {
float leftEyeBlink, rightEyeBlink, averageLoudness, browAudioLift; float leftEyeBlink, rightEyeBlink, averageLoudness, browAudioLift;
minPossibleSize += sizeof(leftEyeBlink) + sizeof(rightEyeBlink) + sizeof(averageLoudness) + sizeof(browAudioLift); minPossibleSize += sizeof(leftEyeBlink) + sizeof(rightEyeBlink) + sizeof(averageLoudness) + sizeof(browAudioLift);
minPossibleSize++; // one byte for blendDataSize minPossibleSize++; // one byte for blendDataSize

View file

@ -241,7 +241,7 @@ public:
Q_INVOKABLE void setBlendshape(QString name, float val) { _headData->setBlendshape(name, val); } Q_INVOKABLE void setBlendshape(QString name, float val) { _headData->setBlendshape(name, val); }
void setForceFaceshiftConnected(bool connected) { _forceFaceshiftConnected = connected; } void setForceFaceTrackerConnected(bool connected) { _forceFaceTrackerConnected = connected; }
// key state // key state
void setKeyState(KeyState s) { _keyState = s; } void setKeyState(KeyState s) { _keyState = s; }
@ -357,7 +357,7 @@ protected:
KeyState _keyState; KeyState _keyState;
bool _isChatCirclingEnabled; bool _isChatCirclingEnabled;
bool _forceFaceshiftConnected; bool _forceFaceTrackerConnected;
bool _hasNewJointRotations; // set in AvatarData, cleared in Avatar bool _hasNewJointRotations; // set in AvatarData, cleared in Avatar
HeadData* _headData; HeadData* _headData;

View file

@ -67,7 +67,7 @@ PalmData::PalmData(HandData* owningHandData) :
_rawRotation(0.0f, 0.0f, 0.0f, 1.0f), _rawRotation(0.0f, 0.0f, 0.0f, 1.0f),
_rawPosition(0.0f), _rawPosition(0.0f),
_rawVelocity(0.0f), _rawVelocity(0.0f),
_rotationalVelocity(0.0f), _rawAngularVelocity(0.0f),
_totalPenetration(0.0f), _totalPenetration(0.0f),
_controllerButtons(0), _controllerButtons(0),
_isActive(false), _isActive(false),

View file

@ -98,6 +98,8 @@ public:
void setRawPosition(const glm::vec3& pos) { _rawPosition = pos; } void setRawPosition(const glm::vec3& pos) { _rawPosition = pos; }
void setRawVelocity(const glm::vec3& velocity) { _rawVelocity = velocity; } void setRawVelocity(const glm::vec3& velocity) { _rawVelocity = velocity; }
const glm::vec3& getRawVelocity() const { return _rawVelocity; } const glm::vec3& getRawVelocity() const { return _rawVelocity; }
void setRawAngularVelocity(const glm::vec3& angularVelocity) { _rawAngularVelocity = angularVelocity; }
const glm::vec3& getRawAngularVelocity() const { return _rawAngularVelocity; }
void addToPosition(const glm::vec3& delta); void addToPosition(const glm::vec3& delta);
void addToPenetration(const glm::vec3& penetration) { _totalPenetration += penetration; } void addToPenetration(const glm::vec3& penetration) { _totalPenetration += penetration; }
@ -148,7 +150,7 @@ private:
glm::quat _rawRotation; glm::quat _rawRotation;
glm::vec3 _rawPosition; glm::vec3 _rawPosition;
glm::vec3 _rawVelocity; glm::vec3 _rawVelocity;
glm::vec3 _rotationalVelocity; glm::vec3 _rawAngularVelocity;
glm::quat _lastRotation; glm::quat _lastRotation;
glm::vec3 _tipPosition; glm::vec3 _tipPosition;

View file

@ -31,7 +31,7 @@ HeadData::HeadData(AvatarData* owningAvatar) :
_torsoTwist(0.0f), _torsoTwist(0.0f),
_lookAtPosition(0.0f, 0.0f, 0.0f), _lookAtPosition(0.0f, 0.0f, 0.0f),
_audioLoudness(0.0f), _audioLoudness(0.0f),
_isFaceshiftConnected(false), _isFaceTrackerConnected(false),
_leftEyeBlink(0.0f), _leftEyeBlink(0.0f),
_rightEyeBlink(0.0f), _rightEyeBlink(0.0f),
_averageLoudness(0.0f), _averageLoudness(0.0f),

View file

@ -92,7 +92,7 @@ protected:
glm::vec3 _lookAtPosition; glm::vec3 _lookAtPosition;
float _audioLoudness; float _audioLoudness;
bool _isFaceshiftConnected; bool _isFaceTrackerConnected;
float _leftEyeBlink; float _leftEyeBlink;
float _rightEyeBlink; float _rightEyeBlink;
float _averageLoudness; float _averageLoudness;

View file

@ -110,7 +110,7 @@ void Player::startPlaying() {
} }
// Fake faceshift connection // Fake faceshift connection
_avatar->setForceFaceshiftConnected(true); _avatar->setForceFaceTrackerConnected(true);
qDebug() << "Recorder::startPlaying()"; qDebug() << "Recorder::startPlaying()";
setupAudioThread(); setupAudioThread();
@ -136,8 +136,8 @@ void Player::stopPlaying() {
cleanupAudioThread(); cleanupAudioThread();
_avatar->clearJointsData(); _avatar->clearJointsData();
// Turn off fake faceshift connection // Turn off fake face tracker connection
_avatar->setForceFaceshiftConnected(false); _avatar->setForceFaceTrackerConnected(false);
if (_useAttachments) { if (_useAttachments) {
_avatar->setAttachmentData(_currentContext.attachments); _avatar->setAttachmentData(_currentContext.attachments);
@ -255,8 +255,8 @@ void Player::play() {
HeadData* head = const_cast<HeadData*>(_avatar->getHeadData()); HeadData* head = const_cast<HeadData*>(_avatar->getHeadData());
if (head) { if (head) {
// Make sure fake faceshift connection doesn't get turned off // Make sure fake face tracker connection doesn't get turned off
_avatar->setForceFaceshiftConnected(true); _avatar->setForceFaceTrackerConnected(true);
QVector<float> blendCoef(currentFrame.getBlendshapeCoefficients().size()); QVector<float> blendCoef(currentFrame.getBlendshapeCoefficients().size());
for (int i = 0; i < currentFrame.getBlendshapeCoefficients().size(); ++i) { for (int i = 0; i < currentFrame.getBlendshapeCoefficients().size(); ++i) {

View file

@ -10,6 +10,7 @@
// //
#include <QDebug> #include <QDebug>
#include <QHash>
#include <QObject> #include <QObject>
#include <QtCore/QJsonDocument> #include <QtCore/QJsonDocument>
@ -170,6 +171,31 @@ void EntityItemProperties::setLastEdited(quint64 usecTime) {
_lastEdited = usecTime > _created ? usecTime : _created; _lastEdited = usecTime > _created ? usecTime : _created;
} }
const char* shapeTypeNames[] = {"none", "box", "sphere"};
QHash<QString, ShapeType> stringToShapeTypeLookup;
void buildStringToShapeTypeLookup() {
stringToShapeTypeLookup["none"] = SHAPE_TYPE_NONE;
stringToShapeTypeLookup["box"] = SHAPE_TYPE_BOX;
stringToShapeTypeLookup["sphere"] = SHAPE_TYPE_SPHERE;
}
QString EntityItemProperties::getShapeTypeAsString() const {
return QString(shapeTypeNames[_shapeType]);
}
void EntityItemProperties::setShapeTypeFromString(const QString& shapeName) {
if (stringToShapeTypeLookup.empty()) {
buildStringToShapeTypeLookup();
}
auto shapeTypeItr = stringToShapeTypeLookup.find(shapeName.toLower());
if (shapeTypeItr != stringToShapeTypeLookup.end()) {
_shapeType = shapeTypeItr.value();
_shapeTypeChanged = true;
}
}
EntityPropertyFlags EntityItemProperties::getChangedProperties() const { EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
EntityPropertyFlags changedProperties; EntityPropertyFlags changedProperties;
@ -270,7 +296,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine) cons
COPY_PROPERTY_TO_QSCRIPTVALUE(lineHeight); COPY_PROPERTY_TO_QSCRIPTVALUE(lineHeight);
COPY_PROPERTY_TO_QSCRIPTVALUE_COLOR_GETTER(textColor, getTextColor()); COPY_PROPERTY_TO_QSCRIPTVALUE_COLOR_GETTER(textColor, getTextColor());
COPY_PROPERTY_TO_QSCRIPTVALUE_COLOR_GETTER(backgroundColor, getBackgroundColor()); COPY_PROPERTY_TO_QSCRIPTVALUE_COLOR_GETTER(backgroundColor, getBackgroundColor());
COPY_PROPERTY_TO_QSCRIPTVALUE(shapeType); COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(shapeType, getShapeTypeAsString());
// Sitting properties support // Sitting properties support
QScriptValue sittingPoints = engine->newObject(); QScriptValue sittingPoints = engine->newObject();
@ -303,8 +329,6 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine) cons
} }
void EntityItemProperties::copyFromScriptValue(const QScriptValue& object) { void EntityItemProperties::copyFromScriptValue(const QScriptValue& object) {
QScriptValue typeScriptValue = object.property("type"); QScriptValue typeScriptValue = object.property("type");
if (typeScriptValue.isValid()) { if (typeScriptValue.isValid()) {
setType(typeScriptValue.toVariant().toString()); setType(typeScriptValue.toVariant().toString());
@ -350,7 +374,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object) {
COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(lineHeight, setLineHeight); COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(lineHeight, setLineHeight);
COPY_PROPERTY_FROM_QSCRIPTVALUE_COLOR(textColor, setTextColor); COPY_PROPERTY_FROM_QSCRIPTVALUE_COLOR(textColor, setTextColor);
COPY_PROPERTY_FROM_QSCRIPTVALUE_COLOR(backgroundColor, setBackgroundColor); COPY_PROPERTY_FROM_QSCRIPTVALUE_COLOR(backgroundColor, setBackgroundColor);
COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(shapeType, setShapeType, ShapeType); COPY_PROPERTY_FROM_QSCRITPTVALUE_ENUM(shapeType, ShapeType);
_lastEdited = usecTimestampNow(); _lastEdited = usecTimestampNow();
} }

View file

@ -181,7 +181,7 @@ public:
DEFINE_PROPERTY(PROP_LINE_HEIGHT, LineHeight, lineHeight, float); DEFINE_PROPERTY(PROP_LINE_HEIGHT, LineHeight, lineHeight, float);
DEFINE_PROPERTY_REF(PROP_TEXT_COLOR, TextColor, textColor, xColor); DEFINE_PROPERTY_REF(PROP_TEXT_COLOR, TextColor, textColor, xColor);
DEFINE_PROPERTY_REF(PROP_BACKGROUND_COLOR, BackgroundColor, backgroundColor, xColor); DEFINE_PROPERTY_REF(PROP_BACKGROUND_COLOR, BackgroundColor, backgroundColor, xColor);
DEFINE_PROPERTY_REF(PROP_SHAPE_TYPE, ShapeType, shapeType, ShapeType); DEFINE_PROPERTY_REF_ENUM(PROP_SHAPE_TYPE, ShapeType, shapeType, ShapeType);
public: public:
float getMaxDimension() const { return glm::max(_dimensions.x, _dimensions.y, _dimensions.z); } float getMaxDimension() const { return glm::max(_dimensions.x, _dimensions.y, _dimensions.z); }

View file

@ -180,15 +180,6 @@
#define COPY_PROPERTY_TO_QSCRIPTVALUE(P) \ #define COPY_PROPERTY_TO_QSCRIPTVALUE(P) \
properties.setProperty(#P, _##P); properties.setProperty(#P, _##P);
#define COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(P, S, E) \
QScriptValue P = object.property(#P); \
if (P.isValid()) { \
E newValue = (E)(P.toVariant().toInt()); \
if (_defaultSettings || newValue != _##P) { \
S(newValue); \
} \
}
#define COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(P, S) \ #define COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(P, S) \
QScriptValue P = object.property(#P); \ QScriptValue P = object.property(#P); \
if (P.isValid()) { \ if (P.isValid()) { \
@ -280,6 +271,15 @@
} \ } \
} \ } \
} }
#define COPY_PROPERTY_FROM_QSCRITPTVALUE_ENUM(P, S) \
QScriptValue P = object.property(#P); \
if (P.isValid()) { \
QString newValue = P.toVariant().toString(); \
if (_defaultSettings || newValue != get##S##AsString()) { \
set##S##FromString(newValue); \
} \
}
#define CONSTRUCT_PROPERTY(n, V) \ #define CONSTRUCT_PROPERTY(n, V) \
_##n(V), \ _##n(V), \
@ -321,6 +321,17 @@
T _##n; \ T _##n; \
bool _##n##Changed; bool _##n##Changed;
#define DEFINE_PROPERTY_REF_ENUM(P, N, n, T) \
public: \
const T& get##N() const { return _##n; } \
void set##N(const T& value) { _##n = value; _##n##Changed = true; } \
bool n##Changed() const { return _##n##Changed; } \
QString get##N##AsString() const; \
void set##N##FromString(const QString& name); \
private: \
T _##n; \
bool _##n##Changed;
#define DEBUG_PROPERTY_IF_CHANGED(D, P, N, n, x) \ #define DEBUG_PROPERTY_IF_CHANGED(D, P, N, n, x) \
if (P.n##Changed()) { \ if (P.n##Changed()) { \
D << " " << #n << ":" << P.get##N() << x << "\n"; \ D << " " << #n << ":" << P.get##N() << x << "\n"; \

View file

@ -76,7 +76,6 @@ void Light::setSpotAngle(float angle) {
if (angle <= 0.f) { if (angle <= 0.f) {
angle = 0.0f; angle = 0.0f;
} }
float cosAngle = cos(angle);
editSchema()._spot.x = cos(angle); editSchema()._spot.x = cos(angle);
editSchema()._spot.y = sin(angle); editSchema()._spot.y = sin(angle);
editSchema()._spot.z = angle; editSchema()._spot.z = angle;