Merge branch 'master' of https://github.com/highfidelity/hifi into use-snapshot-data-from-file

This commit is contained in:
howard-stearns 2016-11-03 13:17:47 -07:00
commit 7c45a78cb0
15 changed files with 255 additions and 28 deletions

View file

@ -571,7 +571,9 @@ Function HandlePostInstallOptions
; both launches use the explorer trick in case the user has elevated permissions for the installer ; both launches use the explorer trick in case the user has elevated permissions for the installer
; it won't be possible to use this approach if either application should be launched with a command line param ; it won't be possible to use this approach if either application should be launched with a command line param
${If} ${SectionIsSelected} ${@SERVER_COMPONENT_NAME@} ${If} ${SectionIsSelected} ${@SERVER_COMPONENT_NAME@}
Exec '"$WINDIR\explorer.exe" "$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@"' ; create shortcut with ARGUMENTS
CreateShortCut "$TEMP\SandboxShortcut.lnk" "$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@" "-- --launchInterface"
Exec '"$WINDIR\explorer.exe" "$TEMP\SandboxShortcut.lnk"'
${Else} ${Else}
Exec '"$WINDIR\explorer.exe" "$INSTDIR\@INTERFACE_WIN_EXEC_NAME@"' Exec '"$WINDIR\explorer.exe" "$INSTDIR\@INTERFACE_WIN_EXEC_NAME@"'
${EndIf} ${EndIf}

View file

@ -0,0 +1,22 @@
// Language and character set information as described at
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa381049(v=vs.85).aspx
#define US_ENGLISH_UNICODE "040904B0"
// More information about the format of this file can be found at
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa381058(v=vs.85).aspx
1 VERSIONINFO
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK US_ENGLISH_UNICODE
BEGIN
VALUE "CompanyName", "@BUILD_ORGANIZATION@"
VALUE "FileDescription", "@APP_FULL_NAME@"
VALUE "FileVersion", "@BUILD_VERSION@"
VALUE "InternalName", "@TARGET_NAME@"
VALUE "OriginalFilename", "@TARGET_NAME@.exe"
VALUE "ProductName", "@APP_FULL_NAME@"
VALUE "ProductVersion", "@BUILD_VERSION@"
END
END
END

View file

@ -237,6 +237,7 @@ void DomainGatekeeper::updateNodePermissions() {
userPerms.permissions |= NodePermissions::Permission::canAdjustLocks; userPerms.permissions |= NodePermissions::Permission::canAdjustLocks;
userPerms.permissions |= NodePermissions::Permission::canRezPermanentEntities; userPerms.permissions |= NodePermissions::Permission::canRezPermanentEntities;
userPerms.permissions |= NodePermissions::Permission::canRezTemporaryEntities; userPerms.permissions |= NodePermissions::Permission::canRezTemporaryEntities;
userPerms.permissions |= NodePermissions::Permission::canWriteToAssetServer;
} else { } else {
// this node is an agent // this node is an agent
const QHostAddress& addr = node->getLocalSocket().getAddress(); const QHostAddress& addr = node->getLocalSocket().getAddress();
@ -312,6 +313,7 @@ SharedNodePointer DomainGatekeeper::processAssignmentConnectRequest(const NodeCo
userPerms.permissions |= NodePermissions::Permission::canAdjustLocks; userPerms.permissions |= NodePermissions::Permission::canAdjustLocks;
userPerms.permissions |= NodePermissions::Permission::canRezPermanentEntities; userPerms.permissions |= NodePermissions::Permission::canRezPermanentEntities;
userPerms.permissions |= NodePermissions::Permission::canRezTemporaryEntities; userPerms.permissions |= NodePermissions::Permission::canRezTemporaryEntities;
userPerms.permissions |= NodePermissions::Permission::canWriteToAssetServer;
newNode->setPermissions(userPerms); newNode->setPermissions(userPerms);
return newNode; return newNode;
} }

View file

@ -133,8 +133,12 @@ elseif (WIN32)
set(CONFIGURE_ICON_RC_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/Icon.rc") set(CONFIGURE_ICON_RC_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/Icon.rc")
configure_file("${HF_CMAKE_DIR}/templates/Icon.rc.in" ${CONFIGURE_ICON_RC_OUTPUT}) configure_file("${HF_CMAKE_DIR}/templates/Icon.rc.in" ${CONFIGURE_ICON_RC_OUTPUT})
set(APP_FULL_NAME "High Fidelity Interface")
set(CONFIGURE_VERSION_INFO_RC_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/VersionInfo.rc")
configure_file("${HF_CMAKE_DIR}/templates/VersionInfo.rc.in" ${CONFIGURE_VERSION_INFO_RC_OUTPUT})
# add an executable that also has the icon itself and the configured rc file as resources # add an executable that also has the icon itself and the configured rc file as resources
add_executable(${TARGET_NAME} WIN32 ${INTERFACE_SRCS} ${QM} ${CONFIGURE_ICON_RC_OUTPUT}) add_executable(${TARGET_NAME} WIN32 ${INTERFACE_SRCS} ${QM} ${CONFIGURE_ICON_RC_OUTPUT} ${CONFIGURE_VERSION_INFO_RC_OUTPUT})
if (NOT DEV_BUILD) if (NOT DEV_BUILD)
add_custom_command( add_custom_command(

View file

@ -20,10 +20,10 @@ ScrollingWindow {
anchors.centerIn: parent anchors.centerIn: parent
UpdateDialog { UpdateDialog {
id: updateDialog id: updateDialog
implicitWidth: backgroundRectangle.width implicitWidth: backgroundRectangle.width
implicitHeight: backgroundRectangle.height implicitHeight: backgroundRectangle.height
readonly property int contentWidth: 500 readonly property int contentWidth: 500
readonly property int logoSize: 60 readonly property int logoSize: 60
readonly property int borderWidth: 30 readonly property int borderWidth: 30
@ -36,7 +36,7 @@ ScrollingWindow {
signal triggerBuildDownload signal triggerBuildDownload
signal closeUpdateDialog signal closeUpdateDialog
Rectangle { Rectangle {
id: backgroundRectangle id: backgroundRectangle
color: "#ffffff" color: "#ffffff"
@ -47,7 +47,7 @@ ScrollingWindow {
Image { Image {
id: logo id: logo
source: "../images/interface-logo.svg" source: "../images/hifi-logo.svg"
width: updateDialog.logoSize width: updateDialog.logoSize
height: updateDialog.logoSize height: updateDialog.logoSize
anchors { anchors {
@ -65,7 +65,7 @@ ScrollingWindow {
topMargin: updateDialog.borderWidth topMargin: updateDialog.borderWidth
top: parent.top top: parent.top
} }
Rectangle { Rectangle {
id: header id: header
width: parent.width - updateDialog.logoSize - updateDialog.inputSpacing width: parent.width - updateDialog.logoSize - updateDialog.inputSpacing

View file

@ -113,9 +113,8 @@ Rectangle {
} }
FiraSansRegular { FiraSansRegular {
id: users; id: users;
visible: action === 'concurrency'; text: (action === 'concurrency') ? onlineUsers : 'snapshot';
text: onlineUsers; size: (action === 'concurrency') ? textSize : textSizeSmall;
size: textSize;
color: hifi.colors.white; color: hifi.colors.white;
anchors { anchors {
verticalCenter: usersImage.verticalCenter; verticalCenter: usersImage.verticalCenter;

View file

@ -118,11 +118,26 @@ void AnimSkeleton::convertAbsoluteRotationsToRelative(std::vector<glm::quat>& ro
} }
} }
void AnimSkeleton::saveNonMirroredPoses(const AnimPoseVec& poses) const {
_nonMirroredPoses.clear();
for (int i = 0; i < (int)_nonMirroredIndices.size(); ++i) {
_nonMirroredPoses.push_back(poses[_nonMirroredIndices[i]]);
}
}
void AnimSkeleton::restoreNonMirroredPoses(AnimPoseVec& poses) const {
for (int i = 0; i < (int)_nonMirroredIndices.size(); ++i) {
int index = _nonMirroredIndices[i];
poses[index] = _nonMirroredPoses[i];
}
}
void AnimSkeleton::mirrorRelativePoses(AnimPoseVec& poses) const { void AnimSkeleton::mirrorRelativePoses(AnimPoseVec& poses) const {
saveNonMirroredPoses(poses);
convertRelativePosesToAbsolute(poses); convertRelativePosesToAbsolute(poses);
mirrorAbsolutePoses(poses); mirrorAbsolutePoses(poses);
convertAbsolutePosesToRelative(poses); convertAbsolutePosesToRelative(poses);
restoreNonMirroredPoses(poses);
} }
void AnimSkeleton::mirrorAbsolutePoses(AnimPoseVec& poses) const { void AnimSkeleton::mirrorAbsolutePoses(AnimPoseVec& poses) const {
@ -189,8 +204,14 @@ void AnimSkeleton::buildSkeletonFromJoints(const std::vector<FBXJoint>& joints)
} }
// build mirror map. // build mirror map.
_nonMirroredIndices.clear();
_mirrorMap.reserve(_joints.size()); _mirrorMap.reserve(_joints.size());
for (int i = 0; i < (int)joints.size(); i++) { for (int i = 0; i < (int)joints.size(); i++) {
if (_joints[i].name.endsWith("tEye")) {
// HACK: we don't want to mirror some joints so we remember their indices
// so we can restore them after a future mirror operation
_nonMirroredIndices.push_back(i);
}
int mirrorJointIndex = -1; int mirrorJointIndex = -1;
if (_joints[i].name.startsWith("Left")) { if (_joints[i].name.startsWith("Left")) {
QString mirrorJointName = QString(_joints[i].name).replace(0, 4, "Right"); QString mirrorJointName = QString(_joints[i].name).replace(0, 4, "Right");

View file

@ -57,6 +57,9 @@ public:
void convertAbsoluteRotationsToRelative(std::vector<glm::quat>& rotations) const; void convertAbsoluteRotationsToRelative(std::vector<glm::quat>& rotations) const;
void saveNonMirroredPoses(const AnimPoseVec& poses) const;
void restoreNonMirroredPoses(AnimPoseVec& poses) const;
void mirrorRelativePoses(AnimPoseVec& poses) const; void mirrorRelativePoses(AnimPoseVec& poses) const;
void mirrorAbsolutePoses(AnimPoseVec& poses) const; void mirrorAbsolutePoses(AnimPoseVec& poses) const;
@ -75,6 +78,8 @@ protected:
AnimPoseVec _absoluteDefaultPoses; AnimPoseVec _absoluteDefaultPoses;
AnimPoseVec _relativePreRotationPoses; AnimPoseVec _relativePreRotationPoses;
AnimPoseVec _relativePostRotationPoses; AnimPoseVec _relativePostRotationPoses;
mutable AnimPoseVec _nonMirroredPoses;
std::vector<int> _nonMirroredIndices;
std::vector<int> _mirrorMap; std::vector<int> _mirrorMap;
// no copies // no copies

View file

@ -85,18 +85,26 @@ public:
} }
void beforeAboutToQuit() { void beforeAboutToQuit() {
Lock lock(_checkDevicesMutex);
_quit = true; _quit = true;
} }
void run() override { void run() override {
while (!_quit) { while (true) {
{
Lock lock(_checkDevicesMutex);
if (_quit) {
break;
}
_audioClient->checkDevices();
}
QThread::msleep(DEVICE_CHECK_INTERVAL_MSECS); QThread::msleep(DEVICE_CHECK_INTERVAL_MSECS);
_audioClient->checkDevices();
} }
} }
private: private:
AudioClient* _audioClient { nullptr }; AudioClient* _audioClient { nullptr };
Mutex _checkDevicesMutex;
bool _quit { false }; bool _quit { false };
}; };

View file

@ -451,6 +451,9 @@ bool OctreePacketData::appendValue(const QVector<bool>& value) {
bit = 0; bit = 0;
} }
} }
if (bit != 0) {
destinationBuffer++;
}
int boolsSize = destinationBuffer - start; int boolsSize = destinationBuffer - start;
success = append(start, boolsSize); success = append(start, boolsSize);
if (success) { if (success) {
@ -683,6 +686,10 @@ int OctreePacketData::unpackDataFromBytes(const unsigned char *dataBytes, QVecto
uint16_t length; uint16_t length;
memcpy(&length, dataBytes, sizeof(uint16_t)); memcpy(&length, dataBytes, sizeof(uint16_t));
dataBytes += sizeof(length); dataBytes += sizeof(length);
if (length * sizeof(glm::vec3) > MAX_OCTREE_UNCOMRESSED_PACKET_SIZE) {
result.resize(0);
return sizeof(uint16_t);
}
result.resize(length); result.resize(length);
memcpy(result.data(), dataBytes, length * sizeof(glm::vec3)); memcpy(result.data(), dataBytes, length * sizeof(glm::vec3));
return sizeof(uint16_t) + length * sizeof(glm::vec3); return sizeof(uint16_t) + length * sizeof(glm::vec3);
@ -692,6 +699,10 @@ int OctreePacketData::unpackDataFromBytes(const unsigned char *dataBytes, QVecto
uint16_t length; uint16_t length;
memcpy(&length, dataBytes, sizeof(uint16_t)); memcpy(&length, dataBytes, sizeof(uint16_t));
dataBytes += sizeof(length); dataBytes += sizeof(length);
if (length * sizeof(glm::quat) > MAX_OCTREE_UNCOMRESSED_PACKET_SIZE) {
result.resize(0);
return sizeof(uint16_t);
}
result.resize(length); result.resize(length);
const unsigned char *start = dataBytes; const unsigned char *start = dataBytes;
@ -706,6 +717,10 @@ int OctreePacketData::unpackDataFromBytes(const unsigned char* dataBytes, QVecto
uint16_t length; uint16_t length;
memcpy(&length, dataBytes, sizeof(uint16_t)); memcpy(&length, dataBytes, sizeof(uint16_t));
dataBytes += sizeof(length); dataBytes += sizeof(length);
if (length * sizeof(float) > MAX_OCTREE_UNCOMRESSED_PACKET_SIZE) {
result.resize(0);
return sizeof(uint16_t);
}
result.resize(length); result.resize(length);
memcpy(result.data(), dataBytes, length * sizeof(float)); memcpy(result.data(), dataBytes, length * sizeof(float));
return sizeof(uint16_t) + length * sizeof(float); return sizeof(uint16_t) + length * sizeof(float);
@ -715,6 +730,10 @@ int OctreePacketData::unpackDataFromBytes(const unsigned char* dataBytes, QVecto
uint16_t length; uint16_t length;
memcpy(&length, dataBytes, sizeof(uint16_t)); memcpy(&length, dataBytes, sizeof(uint16_t));
dataBytes += sizeof(length); dataBytes += sizeof(length);
if (length / 8 > MAX_OCTREE_UNCOMRESSED_PACKET_SIZE) {
result.resize(0);
return sizeof(uint16_t);
}
result.resize(length); result.resize(length);
int bit = 0; int bit = 0;

View file

@ -10,9 +10,15 @@
#include <QtCore/QtGlobal> #include <QtCore/QtGlobal>
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
#include <atlbase.h> #include <string>
#include <Wbemidl.h>
//#include <atlbase.h>
//#include <Wbemidl.h>
#include <dxgi1_3.h>
#pragma comment(lib, "dxgi.lib")
#elif defined(Q_OS_MAC) #elif defined(Q_OS_MAC)
#include <OpenGL/OpenGL.h> #include <OpenGL/OpenGL.h>
@ -53,9 +59,101 @@ GPUIdent* GPUIdent::ensureQuery(const QString& vendor, const QString& renderer)
CGLDestroyRendererInfo(rendererInfo); CGLDestroyRendererInfo(rendererInfo);
#elif defined(Q_OS_WIN) #elif defined(Q_OS_WIN)
struct ConvertLargeIntegerToQString {
QString convert(const LARGE_INTEGER& version) {
QString value;
value.append(QString::number(uint32_t(((version.HighPart & 0xFFFF0000) >> 16) & 0x0000FFFF)));
value.append(".");
value.append(QString::number(uint32_t((version.HighPart) & 0x0000FFFF)));
value.append(".");
value.append(QString::number(uint32_t(((version.LowPart & 0xFFFF0000) >> 16) & 0x0000FFFF)));
value.append(".");
value.append(QString::number(uint32_t((version.LowPart) & 0x0000FFFF)));
return value;
}
} convertDriverVersionToString;
// Create the DXGI factory
// Let s get into DXGI land:
HRESULT hr = S_OK;
IDXGIFactory1* pFactory = nullptr;
hr = CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)(&pFactory) );
if (hr != S_OK || pFactory == nullptr) {
qCDebug(shared) << "Unable to create DXGI";
return this;
}
std::vector<int> validAdapterList;
using AdapterEntry = std::pair<std::pair<DXGI_ADAPTER_DESC1, LARGE_INTEGER>, std::vector<DXGI_OUTPUT_DESC>>;
std::vector<AdapterEntry> adapterToOutputs;
// Enumerate adapters and outputs
{
UINT adapterNum = 0;
IDXGIAdapter1* pAdapter = nullptr;
while (pFactory->EnumAdapters1(adapterNum, &pAdapter) != DXGI_ERROR_NOT_FOUND) {
// Found an adapter, get descriptor
DXGI_ADAPTER_DESC1 adapterDesc;
pAdapter->GetDesc1(&adapterDesc);
LARGE_INTEGER version;
hr = pAdapter->CheckInterfaceSupport(__uuidof(IDXGIDevice), &version);
std::wstring wDescription (adapterDesc.Description);
std::string description(wDescription.begin(), wDescription.end());
qCDebug(shared) << "Found adapter: " << description.c_str()
<< " Driver version: " << convertDriverVersionToString.convert(version);
AdapterEntry adapterEntry;
adapterEntry.first.first = adapterDesc;
adapterEntry.first.second = version;
UINT outputNum = 0;
IDXGIOutput * pOutput;
bool hasOutputConnectedToDesktop = false;
while (pAdapter->EnumOutputs(outputNum, &pOutput) != DXGI_ERROR_NOT_FOUND) {
// FOund an output attached to the adapter, get descriptor
DXGI_OUTPUT_DESC outputDesc;
pOutput->GetDesc(&outputDesc);
adapterEntry.second.push_back(outputDesc);
std::wstring wDeviceName(outputDesc.DeviceName);
std::string deviceName(wDeviceName.begin(), wDeviceName.end());
qCDebug(shared) << " Found output: " << deviceName.c_str() << " desktop: " << (outputDesc.AttachedToDesktop ? "true" : "false")
<< " Rect [ l=" << outputDesc.DesktopCoordinates.left << " r=" << outputDesc.DesktopCoordinates.right
<< " b=" << outputDesc.DesktopCoordinates.bottom << " t=" << outputDesc.DesktopCoordinates.top << " ]";
hasOutputConnectedToDesktop |= (bool) outputDesc.AttachedToDesktop;
pOutput->Release();
outputNum++;
}
adapterToOutputs.push_back(adapterEntry);
// add this adapter to the valid list if has output
if (hasOutputConnectedToDesktop && !adapterEntry.second.empty()) {
validAdapterList.push_back(adapterNum);
}
pAdapter->Release();
adapterNum++;
}
}
pFactory->Release();
// THis was the previous technique used to detect the platform we are running on on windows.
/*
// COM must be initialized already using CoInitialize. E.g., by the audio subsystem. // COM must be initialized already using CoInitialize. E.g., by the audio subsystem.
CComPtr<IWbemLocator> spLoc = NULL; CComPtr<IWbemLocator> spLoc = NULL;
HRESULT hr = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_SERVER, IID_IWbemLocator, (LPVOID *)&spLoc); hr = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_SERVER, IID_IWbemLocator, (LPVOID *)&spLoc);
if (hr != S_OK || spLoc == NULL) { if (hr != S_OK || spLoc == NULL) {
qCDebug(shared) << "Unable to connect to WMI"; qCDebug(shared) << "Unable to connect to WMI";
return this; return this;
@ -139,7 +237,7 @@ GPUIdent* GPUIdent::ensureQuery(const QString& vendor, const QString& renderer)
var.ChangeType(CIM_UINT64); // We're going to receive some integral type, but it might not be uint. var.ChangeType(CIM_UINT64); // We're going to receive some integral type, but it might not be uint.
// We might be hosed here. The parameter is documented to be UINT32, but that's only 4 GB! // We might be hosed here. The parameter is documented to be UINT32, but that's only 4 GB!
const ULONGLONG BYTES_PER_MEGABYTE = 1024 * 1024; const ULONGLONG BYTES_PER_MEGABYTE = 1024 * 1024;
_dedicatedMemoryMB = (uint) (var.ullVal / BYTES_PER_MEGABYTE); _dedicatedMemoryMB = (uint64_t) (var.ullVal / BYTES_PER_MEGABYTE);
} }
else { else {
qCDebug(shared) << "Unable to get video AdapterRAM"; qCDebug(shared) << "Unable to get video AdapterRAM";
@ -149,6 +247,22 @@ GPUIdent* GPUIdent::ensureQuery(const QString& vendor, const QString& renderer)
} }
hr = spEnumInst->Next(WBEM_INFINITE, 1, &spInstance.p, &uNumOfInstances); hr = spEnumInst->Next(WBEM_INFINITE, 1, &spInstance.p, &uNumOfInstances);
} }
*/
if (!validAdapterList.empty()) {
auto& adapterEntry = adapterToOutputs[validAdapterList.front()];
std::wstring wDescription(adapterEntry.first.first.Description);
std::string description(wDescription.begin(), wDescription.end());
_name = QString(description.c_str());
_driver = convertDriverVersionToString.convert(adapterEntry.first.second);
const ULONGLONG BYTES_PER_MEGABYTE = 1024 * 1024;
_dedicatedMemoryMB = (uint64_t)(adapterEntry.first.first.DedicatedVideoMemory / BYTES_PER_MEGABYTE);
_isValid = true;
}
#endif #endif
return this; return this;
} }

View file

@ -14,17 +14,19 @@
#ifndef hifi_GPUIdent_h #ifndef hifi_GPUIdent_h
#define hifi_GPUIdent_h #define hifi_GPUIdent_h
#include <cstdint>
class GPUIdent class GPUIdent
{ {
public: public:
unsigned int getMemory() { return _dedicatedMemoryMB; } uint64_t getMemory() { return _dedicatedMemoryMB; }
QString getName() { return _name; } QString getName() { return _name; }
QString getDriver() { return _driver; } QString getDriver() { return _driver; }
bool isValid() { return _isValid; } bool isValid() { return _isValid; }
// E.g., GPUIdent::getInstance()->getMemory(); // E.g., GPUIdent::getInstance()->getMemory();
static GPUIdent* getInstance(const QString& vendor = "", const QString& renderer = "") { return _instance.ensureQuery(vendor, renderer); } static GPUIdent* getInstance(const QString& vendor = "", const QString& renderer = "") { return _instance.ensureQuery(vendor, renderer); }
private: private:
uint _dedicatedMemoryMB { 0 }; uint64_t _dedicatedMemoryMB { 0 };
QString _name { "" }; QString _name { "" };
QString _driver { "" }; QString _driver { "" };
bool _isQueried { false }; bool _isQueried { false };

View file

@ -37,7 +37,7 @@ if (osType == "Darwin") {
} else if (osType == "Windows_NT") { } else if (osType == "Windows_NT") {
options["version-string"] = { options["version-string"] = {
CompanyName: "High Fidelity, Inc.", CompanyName: "High Fidelity, Inc.",
FileDescription: SHORT_NAME, FileDescription: FULL_NAME,
ProductName: FULL_NAME, ProductName: FULL_NAME,
OriginalFilename: EXEC_NAME + ".exe" OriginalFilename: EXEC_NAME + ".exe"
} }

View file

@ -868,6 +868,12 @@ function onContentLoaded() {
homeServer.start(); homeServer.start();
} }
// If we were launched with the launchInterface option, then we need to launch interface now
if (argv.launchInterface) {
log.debug("Interface launch requested... argv.launchInterface:", argv.launchInterface);
startInterface();
}
// If we were launched with the shutdownWatcher option, then we need to watch for the interface app // If we were launched with the shutdownWatcher option, then we need to watch for the interface app
// shutting down. The interface app will regularly update a running state file which we will check. // shutting down. The interface app will regularly update a running state file which we will check.
// If the file doesn't exist or stops updating for a significant amount of time, we will shut down. // If the file doesn't exist or stops updating for a significant amount of time, we will shut down.

View file

@ -715,7 +715,8 @@ var stepTurnAround = function(name) {
this.tempTag = name + "-temporary"; this.tempTag = name + "-temporary";
this.onActionBound = this.onAction.bind(this); this.onActionBound = this.onAction.bind(this);
this.numTimesTurnPressed = 0; this.numTimesSnapTurnPressed = 0;
this.numTimesSmoothTurnPressed = 0;
} }
stepTurnAround.prototype = { stepTurnAround.prototype = {
start: function(onFinish) { start: function(onFinish) {
@ -724,19 +725,26 @@ stepTurnAround.prototype = {
showEntitiesWithTag(this.tag); showEntitiesWithTag(this.tag);
this.numTimesTurnPressed = 0; this.numTimesSnapTurnPressed = 0;
this.numTimesSmoothTurnPressed = 0;
this.smoothTurnDown = false;
Controller.actionEvent.connect(this.onActionBound); Controller.actionEvent.connect(this.onActionBound);
this.interval = Script.setInterval(function() { this.interval = Script.setInterval(function() {
debug("TurnAround | Checking if finished", this.numTimesTurnPressed); debug("TurnAround | Checking if finished",
this.numTimesSnapTurnPressed, this.numTimesSmoothTurnPressed);
var FORWARD_THRESHOLD = 90; var FORWARD_THRESHOLD = 90;
var REQ_NUM_TIMES_PRESSED = 3; var REQ_NUM_TIMES_SNAP_TURN_PRESSED = 3;
var REQ_NUM_TIMES_SMOOTH_TURN_PRESSED = 2;
var dir = Quat.getFront(MyAvatar.orientation); var dir = Quat.getFront(MyAvatar.orientation);
var angle = Math.atan2(dir.z, dir.x); var angle = Math.atan2(dir.z, dir.x);
var angleDegrees = ((angle / Math.PI) * 180); var angleDegrees = ((angle / Math.PI) * 180);
if (this.numTimesTurnPressed >= REQ_NUM_TIMES_PRESSED && Math.abs(angleDegrees) < FORWARD_THRESHOLD) { var hasTurnedEnough = this.numTimesSnapTurnPressed >= REQ_NUM_TIMES_SNAP_TURN_PRESSED
|| this.numTimesSmoothTurnPressed >= REQ_NUM_TIMES_SMOOTH_TURN_PRESSED;
var facingForward = Math.abs(angleDegrees) < FORWARD_THRESHOLD
if (hasTurnedEnough && facingForward) {
Script.clearInterval(this.interval); Script.clearInterval(this.interval);
this.interval = null; this.interval = null;
playSuccessSound(); playSuccessSound();
@ -746,9 +754,19 @@ stepTurnAround.prototype = {
}, },
onAction: function(action, value) { onAction: function(action, value) {
var STEP_YAW_ACTION = 6; var STEP_YAW_ACTION = 6;
var SMOOTH_YAW_ACTION = 4;
if (action == STEP_YAW_ACTION && value != 0) { if (action == STEP_YAW_ACTION && value != 0) {
debug("TurnAround | Got yaw action"); debug("TurnAround | Got step yaw action");
this.numTimesTurnPressed += 1; ++this.numTimesSnapTurnPressed;
} else if (action == SMOOTH_YAW_ACTION) {
debug("TurnAround | Got smooth yaw action");
if (this.smoothTurnDown && value === 0) {
this.smoothTurnDown = false;
++this.numTimesSmoothTurnPressed;
} else if (!this.smoothTurnDown && value !== 0) {
this.smoothTurnDown = true;
}
} }
}, },
cleanup: function() { cleanup: function() {
@ -971,6 +989,7 @@ TutorialManager = function() {
var currentStep = null; var currentStep = null;
var startedTutorialAt = 0; var startedTutorialAt = 0;
var startedLastStepAt = 0; var startedLastStepAt = 0;
var didFinishTutorial = false;
var wentToEntryStepNum; var wentToEntryStepNum;
var VERSION = 1; var VERSION = 1;
@ -1032,6 +1051,7 @@ TutorialManager = function() {
info("DONE WITH TUTORIAL"); info("DONE WITH TUTORIAL");
currentStepNum = -1; currentStepNum = -1;
currentStep = null; currentStep = null;
didFinishTutorial = true;
return false; return false;
} else { } else {
info("Starting step", currentStepNum); info("Starting step", currentStepNum);
@ -1069,8 +1089,11 @@ TutorialManager = function() {
// This is a message sent from the "entry" portal in the courtyard, // This is a message sent from the "entry" portal in the courtyard,
// after the tutorial has finished. // after the tutorial has finished.
this.enteredEntryPortal = function() { this.enteredEntryPortal = function() {
info("Got enteredEntryPortal, tracking"); info("Got enteredEntryPortal");
this.trackStep("wentToEntry", wentToEntryStepNum); if (didFinishTutorial) {
info("Tracking wentToEntry");
this.trackStep("wentToEntry", wentToEntryStepNum);
}
} }
} }