Merge remote-tracking branch 'hifi/master' into android_crashes_domains

This commit is contained in:
Cristian Luis Duarte 2018-05-28 17:14:58 -03:00
commit c0c246c934
111 changed files with 1024 additions and 474 deletions

View file

@ -9,15 +9,17 @@ Note: The prerequisites will require about 10 GB of space on your drive. You wil
If you dont have Community or Professional edition of Visual Studio 2017, download [Visual Studio Community 2017](https://www.visualstudio.com/downloads/).
When selecting components, check "Desktop development with C++." Also check "Windows 8.1 SDK and UCRT SDK" and "VC++ 2015.3 v140 toolset (x86,x64)" on the Summary toolbar on the right.
When selecting components, check "Desktop development with C++." Also on the right on the Summary toolbar, check "Windows 8.1 SDK and UCRT SDK" and "VC++ 2015.3 v140 toolset (x86,x64)".
### Step 2. Installing CMake
Download and install the latest version of CMake 3.9. Download the file named win64-x64 Installer from the [CMake Website](https://cmake.org/download/). Make sure to check "Add CMake to system PATH for all users" when prompted during installation.
Download and install the latest version of CMake 3.9.
Download the file named win64-x64 Installer from the [CMake Website](https://cmake.org/download/). You can access the installer on this [3.9 Version page](https://cmake.org/files/v3.9/). During installation, make sure to check "Add CMake to system PATH for all users" when prompted.
### Step 3. Installing Qt
Download and install the [Qt Online Installer](https://www.qt.io/download-open-source/?hsCtaTracking=f977210e-de67-475f-a32b-65cec207fd03%7Cd62710cd-e1db-46aa-8d4d-2f1c1ffdacea). While installing, you only need to have the following components checked under Qt 5.10.1: "msvc2017 64-bit", "Qt WebEngine", and "Qt Script (Deprecated)".
Download and install the [Qt Open Source Online Installer](https://www.qt.io/download-open-source/?hsCtaTracking=f977210e-de67-475f-a32b-65cec207fd03%7Cd62710cd-e1db-46aa-8d4d-2f1c1ffdacea). While installing, you only need to have the following components checked under Qt 5.10.1: "msvc2017 64-bit", "Qt WebEngine", and "Qt Script (Deprecated)".
Note: Installing the Sources is optional but recommended if you have room for them (~2GB).
@ -56,9 +58,9 @@ Where `%HIFI_DIR%` is the directory for the highfidelity repository.
Open `%HIFI_DIR%\build\hifi.sln` using Visual Studio.
Change the Solution Configuration (next to the green play button) from "Debug" to "Release" for best performance.
Change the Solution Configuration (menu ribbon under the menu bar, next to the green play button) from "Debug" to "Release" for best performance.
Run `Build > Build Solution`.
Run from the menu bar `Build > Build Solution`.
### Step 9. Testing Interface
@ -66,7 +68,7 @@ Create another environment variable (see Step #4)
* Set "Variable name": `_NO_DEBUG_HEAP`
* Set "Variable value": `1`
In Visual Studio, right+click "interface" under the Apps folder in Solution Explorer and select "Set as Startup Project". Run `Debug > Start Debugging`.
In Visual Studio, right+click "interface" under the Apps folder in Solution Explorer and select "Set as Startup Project". Run from the menu bar `Debug > Start Debugging`.
Now, you should have a full build of High Fidelity and be able to run the Interface using Visual Studio. Please check our [Docs](https://wiki.highfidelity.com/wiki/Main_Page) for more information regarding the programming workflow.

View file

@ -66,17 +66,17 @@ ext {
def baseFolder = new File(HIFI_ANDROID_PRECOMPILED)
def appDir = new File(projectDir, 'app')
def jniFolder = new File(appDir, 'src/main/jniLibs/arm64-v8a')
def baseUrl = 'https://hifi-public.s3.amazonaws.com/austin/android/'
def baseUrl = ''
def qtFile='qt-5.9.3_linux_armv8-libcpp_openssl.tgz'
def qtFile='https://hifi-public.s3.amazonaws.com/austin/android/qt-5.9.3_linux_armv8-libcpp_openssl.tgz'
def qtChecksum='04599670ccca84bd2b15f6915568eb2d'
def qtVersionId='PeoqzN31n.YvLfs9JE2SgHgZ4.IaKAlt'
if (Os.isFamily(Os.FAMILY_MAC)) {
qtFile = 'qt-5.9.3_osx_armv8-libcpp_openssl.tgz'
qtFile = 'https://hifi-public.s3.amazonaws.com/austin/android/qt-5.9.3_osx_armv8-libcpp_openssl.tgz'
qtChecksum='4b02de9d67d6bfb202355a808d2d9c59'
qtVersionId='HygCmtMLPYioyil0DfXckGVzhw2SXZA9'
} else if (Os.isFamily(Os.FAMILY_WINDOWS)) {
qtFile = 'qt-5.9.3_win_armv8-libcpp_openssl.tgz'
qtFile = 'https://hifi-public.s3.amazonaws.com/austin/android/qt-5.9.3_win_armv8-libcpp_openssl.tgz'
qtChecksum='c3e25db64002d0f43cf565e0ef708911'
qtVersionId='HeVObSVLCBoc7yY7He1oBMvPIH0VkClT'
}
@ -88,58 +88,58 @@ def packages = [
checksum: qtChecksum,
],
bullet: [
file: 'bullet-2.83_armv8-libcpp.tgz',
versionId: 'ljb7v.1IjVRqyopUKVDbVnLA4z88J8Eo',
checksum: '2c558d604fce337f5eba3eb7ec1252fd',
file: 'https://hifi-public.s3.amazonaws.com/dependencies/android/bullet-2.88_armv8-libcpp.tgz',
versionId: 'S8YaoED0Cl8sSb8fSV7Q2G1lQJSNDxqg',
checksum: '81642779ccb110f8c7338e8739ac38a0',
],
draco: [
file: 'draco_armv8-libcpp.tgz',
file: 'https://hifi-public.s3.amazonaws.com/austin/android/draco_armv8-libcpp.tgz',
versionId: 'cA3tVJSmkvb1naA3l6D_Jv2Noh.4yc4m',
checksum: '617a80d213a5ec69fbfa21a1f2f738cd',
],
glad: [
file: 'glad_armv8-libcpp.zip',
file: 'https://hifi-public.s3.amazonaws.com/austin/android/glad_armv8-libcpp.zip',
versionId: 'Q9szthzeye8fFyAA.cY26Lgn2B8kezEE',
checksum: 'a8ee8584cf1ccd34766c7ddd9d5e5449',
],
glm: [
file: 'glm-0.9.8.tgz',
versionId: 'BlkJNwaYV2Gfy5XwMeU7K0uzPDRKFMt2',
checksum: 'd2b42cee31d2bc17bab6ce69e6b3f30a',
file: 'https://hifi-public.s3.amazonaws.com/dependencies/android/glm-0.9.8.5-patched.tgz',
versionId: 'cskfMoJrFlAeqI3WPxemyO_Cxt7rT9EJ',
checksum: '067b5fe16b220b5b1a1039ba51b062ae',
],
gvr: [
file: 'gvrsdk_v1.101.0.tgz',
file: 'https://hifi-public.s3.amazonaws.com/austin/android/gvrsdk_v1.101.0.tgz',
versionId: 'UTberAIFraEfF9IVjoV66u1DTPTopgeY',
checksum: '57fd02baa069176ba18597a29b6b4fc7',
],
nvtt: [
file: 'nvtt_armv8-libcpp.zip',
file: 'https://hifi-public.s3.amazonaws.com/austin/android/nvtt_armv8-libcpp.zip',
versionId: 'vLqrqThvpq4gp75BHMAqO6HhfTXaa0An',
checksum: 'eb46d0b683e66987190ed124aabf8910',
sharedLibFolder: 'lib',
includeLibs: ['libnvtt.so', 'libnvmath.so', 'libnvimage.so', 'libnvcore.so'],
],
openssl: [
file: 'openssl-1.1.0g_armv8.tgz',
file: 'https://hifi-public.s3.amazonaws.com/austin/android/openssl-1.1.0g_armv8.tgz',
versionId: 'DmahmSGFS4ltpHyTdyQvv35WOeUOiib9',
checksum: 'cabb681fbccd79594f65fcc266e02f32',
],
polyvox: [
file: 'polyvox_armv8-libcpp.tgz',
file: 'https://hifi-public.s3.amazonaws.com/austin/android/polyvox_armv8-libcpp.tgz',
versionId: 'LDJtzMTvdm4SAc2KYg8Cg6uwWk4Vq3e3',
checksum: '349ad5b72aaf2749ca95d847e60c5314',
sharedLibFolder: 'lib',
includeLibs: ['Release/libPolyVoxCore.so', 'libPolyVoxUtil.so'],
],
tbb: [
file: 'tbb-2018_U1_armv8_libcpp.tgz',
file: 'https://hifi-public.s3.amazonaws.com/austin/android/tbb-2018_U1_armv8_libcpp.tgz',
versionId: 'YZliDD8.Menh1IVXKEuLPeO3xAjJ1UdF',
checksum: '20768f298f53b195e71b414b0ae240c4',
sharedLibFolder: 'lib/release',
includeLibs: ['libtbb.so', 'libtbbmalloc.so'],
],
hifiAC: [
file: 'libplugins_libhifiCodec.zip',
file: 'https://hifi-public.s3.amazonaws.com/austin/android/libplugins_libhifiCodec.zip',
versionId: 'mzKhsRCgVmloqq5bvE.0IwYK1NjGQc_G',
checksum: '9412a8e12c88a4096c1fc843bb9fe52d',
sharedLibFolder: '',
@ -150,15 +150,15 @@ def packages = [
def scribeLocalFile='scribe' + EXEC_SUFFIX
def scribeFile='scribe_linux_x86_64'
def scribeFile='https://hifi-public.s3.amazonaws.com/austin/android/scribe_linux_x86_64'
def scribeChecksum='ca4b904f52f4f993c29175ba96798fa6'
def scribeVersion='wgpf4dB2Ltzg4Lb2jJ4nPFsHoDkmK_OO'
if (Os.isFamily(Os.FAMILY_MAC)) {
scribeFile = 'scribe_osx_x86_64'
scribeFile = 'https://hifi-public.s3.amazonaws.com/austin/android/scribe_osx_x86_64'
scribeChecksum='72db9d32d4e1e50add755570ac5eb749'
scribeVersion='o_NbPrktzEYtBkQf3Tn7zc1nZWzM52w6'
} else if (Os.isFamily(Os.FAMILY_WINDOWS)) {
scribeFile = 'scribe_win32_x86_64.exe'
scribeFile = 'https://hifi-public.s3.amazonaws.com/austin/android/scribe_win32_x86_64.exe'
scribeChecksum='678e43d290c90fda670c6fefe038a06d'
scribeVersion='GCCJxlmd2irvNOFWfZR0U1UCLHndHQrC'
}
@ -608,4 +608,4 @@ task testElf (dependsOn: 'externalNativeBuildDebug') {
}
}
}
*/
*/

View file

@ -17,8 +17,8 @@ include(ExternalProject)
if (WIN32)
ExternalProject_Add(
${EXTERNAL_NAME}
URL http://hifi-public.s3.amazonaws.com/dependencies/bullet-2.83-ccd-and-cmake-fixes.tgz
URL_MD5 03051bf112dcc78ddd296f9cab38fd68
URL http://hifi-public.s3.amazonaws.com/dependencies/bullet-2.88.tgz
URL_MD5 0a6876607ebe83e227427215f15946fd
CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> -DBUILD_EXTRAS=0 -DINSTALL_LIBS=1 -DBUILD_BULLET3=0 -DBUILD_OPENGL3_DEMOS=0 -DBUILD_BULLET2_DEMOS=0 -DBUILD_UNIT_TESTS=0 -DUSE_GLUT=0 -DUSE_DX11=0
LOG_DOWNLOAD 1
LOG_CONFIGURE 1
@ -28,8 +28,8 @@ if (WIN32)
else ()
ExternalProject_Add(
${EXTERNAL_NAME}
URL http://hifi-public.s3.amazonaws.com/dependencies/bullet-2.83-ccd-and-cmake-fixes.tgz
URL_MD5 03051bf112dcc78ddd296f9cab38fd68
URL http://hifi-public.s3.amazonaws.com/dependencies/bullet-2.88.tgz
URL_MD5 0a6876607ebe83e227427215f15946fd
CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> -DBUILD_EXTRAS=0 -DINSTALL_LIBS=1 -DBUILD_BULLET3=0 -DBUILD_OPENGL3_DEMOS=0 -DBUILD_BULLET2_DEMOS=0 -DBUILD_UNIT_TESTS=0 -DUSE_GLUT=0
LOG_DOWNLOAD 1
LOG_CONFIGURE 1

View file

@ -3,8 +3,8 @@ set(EXTERNAL_NAME glm)
include(ExternalProject)
ExternalProject_Add(
${EXTERNAL_NAME}
URL https://hifi-public.s3.amazonaws.com/dependencies/glm-0.9.8.zip
URL_MD5 579ac77a3110befa3244d68c0ceb7281
URL https://hifi-public.s3.amazonaws.com/dependencies/glm-0.9.8.5-patched.zip
URL_MD5 7d39ecc1cea275427534c3cfd6dd63f0
BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> ${EXTERNAL_ARGS}
LOG_DOWNLOAD 1
@ -18,4 +18,4 @@ set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals")
ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR)
string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${INSTALL_DIR}/include CACHE PATH "List of glm include directories")
set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${INSTALL_DIR}/include CACHE PATH "List of glm include directories")

View file

@ -4,8 +4,8 @@ set(EXTERNAL_NAME serverless-content)
ExternalProject_Add(
${EXTERNAL_NAME}
URL http://cdn.highfidelity.com/content-sets/serverless-tutorial-RC67-v4.zip
URL_MD5 ba32aed18bfeaac4ccaf5ebb8ea3e804
URL http://cdn.highfidelity.com/content-sets/serverless-tutorial-RC68.zip
URL_MD5 a068f74d4045e257cfa7926fe6e38ad5
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""

View file

@ -479,7 +479,7 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect
limitedNodeList->killNodeWithUUID(existingNodeID);
}
// add the connecting node (or re-use the matched one from eachNodeBreakable above)
// add the connecting node
SharedNodePointer newNode = addVerifiedNodeFromConnectRequest(nodeConnection);
// set the edit rights for this user
@ -508,26 +508,22 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect
return newNode;
}
SharedNodePointer DomainGatekeeper::addVerifiedNodeFromConnectRequest(const NodeConnectionData& nodeConnection,
QUuid nodeID) {
SharedNodePointer DomainGatekeeper::addVerifiedNodeFromConnectRequest(const NodeConnectionData& nodeConnection) {
HifiSockAddr discoveredSocket = nodeConnection.senderSockAddr;
SharedNetworkPeer connectedPeer = _icePeers.value(nodeConnection.connectUUID);
if (connectedPeer) {
// this user negotiated a connection with us via ICE, so re-use their ICE client ID
nodeID = nodeConnection.connectUUID;
if (connectedPeer->getActiveSocket()) {
// set their discovered socket to whatever the activated socket on the network peer object was
discoveredSocket = *connectedPeer->getActiveSocket();
}
} else {
// we got a connectUUID we didn't recognize, either use the hinted node ID or randomly generate a new one
if (nodeID.isNull()) {
nodeID = QUuid::createUuid();
}
if (connectedPeer && connectedPeer->getActiveSocket()) {
// set their discovered socket to whatever the activated socket on the network peer object was
discoveredSocket = *connectedPeer->getActiveSocket();
}
// create a new node ID for the verified connecting node
auto nodeID = QUuid::createUuid();
// add a mapping from connection node ID to ICE peer ID
// so that we can remove the ICE peer once we see this node connect
_nodeToICEPeerIDs.insert(nodeID, nodeConnection.connectUUID);
auto limitedNodeList = DependencyManager::get<LimitedNodeList>();
Node::LocalID newLocalID = findOrCreateLocalID(nodeID);
@ -541,6 +537,15 @@ SharedNodePointer DomainGatekeeper::addVerifiedNodeFromConnectRequest(const Node
return newNode;
}
void DomainGatekeeper::cleanupICEPeerForNode(const QUuid& nodeID) {
// remove this node ID from our node to ICE peer ID map
// and the associated ICE peer (if it still exists)
auto icePeerID = _nodeToICEPeerIDs.take(nodeID);
if (!icePeerID.isNull()) {
_icePeers.remove(icePeerID);
}
}
bool DomainGatekeeper::verifyUserSignature(const QString& username,
const QByteArray& usernameSignature,
const HifiSockAddr& senderSockAddr) {

View file

@ -39,8 +39,8 @@ public:
void addPendingAssignedNode(const QUuid& nodeUUID, const QUuid& assignmentUUID,
const QUuid& walletUUID, const QString& nodeVersion);
QUuid assignmentUUIDForPendingAssignment(const QUuid& tempUUID);
void removeICEPeer(const QUuid& peerUUID) { _icePeers.remove(peerUUID); }
void cleanupICEPeerForNode(const QUuid& nodeID);
Node::LocalID findOrCreateLocalID(const QUuid& uuid);
@ -77,8 +77,7 @@ private:
SharedNodePointer processAgentConnectRequest(const NodeConnectionData& nodeConnection,
const QString& username,
const QByteArray& usernameSignature);
SharedNodePointer addVerifiedNodeFromConnectRequest(const NodeConnectionData& nodeConnection,
QUuid nodeID = QUuid());
SharedNodePointer addVerifiedNodeFromConnectRequest(const NodeConnectionData& nodeConnection);
bool verifyUserSignature(const QString& username, const QByteArray& usernameSignature,
const HifiSockAddr& senderSockAddr);
@ -101,6 +100,10 @@ private:
std::unordered_map<QUuid, PendingAssignedNodeData> _pendingAssignedNodes;
QHash<QUuid, SharedNetworkPeer> _icePeers;
using ConnectingNodeID = QUuid;
using ICEPeerID = QUuid;
QHash<ConnectingNodeID, ICEPeerID> _nodeToICEPeerIDs;
QHash<QString, QUuid> _connectionTokenHash;

View file

@ -1017,15 +1017,22 @@ void DomainServer::processListRequestPacket(QSharedPointer<ReceivedMessage> mess
sendingNode->setPublicSocket(nodeRequestData.publicSockAddr);
sendingNode->setLocalSocket(nodeRequestData.localSockAddr);
// update the NodeInterestSet in case there have been any changes
DomainServerNodeData* nodeData = static_cast<DomainServerNodeData*>(sendingNode->getLinkedData());
if (!nodeData->hasCheckedIn()) {
nodeData->setHasCheckedIn(true);
// on first check in, make sure we've cleaned up any ICE peer for this node
_gatekeeper.cleanupICEPeerForNode(sendingNode->getUUID());
}
// guard against patched agents asking to hear about other agents
auto safeInterestSet = nodeRequestData.interestList.toSet();
if (sendingNode->getType() == NodeType::Agent) {
safeInterestSet.remove(NodeType::Agent);
}
// update the NodeInterestSet in case there have been any changes
nodeData->setNodeInterestSet(safeInterestSet);
// update the connecting hostname in case it has changed
@ -2945,7 +2952,7 @@ void DomainServer::nodeAdded(SharedNodePointer node) {
void DomainServer::nodeKilled(SharedNodePointer node) {
// if this peer connected via ICE then remove them from our ICE peers hash
_gatekeeper.removeICEPeer(node->getUUID());
_gatekeeper.cleanupICEPeerForNode(node->getUUID());
DomainServerNodeData* nodeData = static_cast<DomainServerNodeData*>(node->getLinkedData());
@ -2978,6 +2985,8 @@ void DomainServer::nodeKilled(SharedNodePointer node) {
}
}
}
broadcastNodeDisconnect(node);
}
SharedAssignmentPointer DomainServer::dequeueMatchingAssignment(const QUuid& assignmentUUID, NodeType_t nodeType) {
@ -3163,18 +3172,23 @@ void DomainServer::handleKillNode(SharedNodePointer nodeToKill) {
const QUuid& nodeUUID = nodeToKill->getUUID();
limitedNodeList->killNodeWithUUID(nodeUUID);
}
static auto removedNodePacket = NLPacket::create(PacketType::DomainServerRemovedNode, NUM_BYTES_RFC4122_UUID);
void DomainServer::broadcastNodeDisconnect(const SharedNodePointer& disconnectedNode) {
auto limitedNodeList = DependencyManager::get<LimitedNodeList>();
static auto removedNodePacket = NLPacket::create(PacketType::DomainServerRemovedNode, NUM_BYTES_RFC4122_UUID, true);
removedNodePacket->reset();
removedNodePacket->write(nodeUUID.toRfc4122());
removedNodePacket->write(disconnectedNode->getUUID().toRfc4122());
// broadcast out the DomainServerRemovedNode message
limitedNodeList->eachMatchingNode([this, &nodeToKill](const SharedNodePointer& otherNode) -> bool {
limitedNodeList->eachMatchingNode([this, &disconnectedNode](const SharedNodePointer& otherNode) -> bool {
// only send the removed node packet to nodes that care about the type of node this was
return isInInterestSet(otherNode, nodeToKill);
return isInInterestSet(otherNode, disconnectedNode);
}, [&limitedNodeList](const SharedNodePointer& otherNode){
limitedNodeList->sendUnreliablePacket(*removedNodePacket, *otherNode);
auto removedNodePacketCopy = NLPacket::createCopy(*removedNodePacket);
limitedNodeList->sendPacket(std::move(removedNodePacketCopy), *otherNode);
});
}

View file

@ -165,6 +165,7 @@ private:
unsigned int countConnectedUsers();
void handleKillNode(SharedNodePointer nodeToKill);
void broadcastNodeDisconnect(const SharedNodePointer& disconnnectedNode);
void sendDomainListToNode(const SharedNodePointer& node, const HifiSockAddr& senderSockAddr);

View file

@ -67,8 +67,11 @@ public:
const QString& getPlaceName() { return _placeName; }
void setPlaceName(const QString& placeName) { _placeName = placeName; }
bool wasAssigned() const { return _wasAssigned; };
bool wasAssigned() const { return _wasAssigned; }
void setWasAssigned(bool wasAssigned) { _wasAssigned = wasAssigned; }
bool hasCheckedIn() const { return _hasCheckedIn; }
void setHasCheckedIn(bool hasCheckedIn) { _hasCheckedIn = hasCheckedIn; }
private:
QJsonObject overrideValuesIfNeeded(const QJsonObject& newStats);
@ -94,6 +97,8 @@ private:
QString _placeName;
bool _wasAssigned { false };
bool _hasCheckedIn { false };
};
#endif // hifi_DomainServerNodeData_h

View file

@ -163,10 +163,18 @@ TextField {
text: textField.label
colorScheme: textField.colorScheme
anchors.left: parent.left
anchors.right: parent.right
Binding on anchors.right {
when: parent.right
value: parent.right
}
Binding on wrapMode {
when: parent.right
value: Text.WordWrap
}
anchors.bottom: parent.top
anchors.bottomMargin: 3
wrapMode: Text.WordWrap
visible: label != ""
}
}

View file

@ -717,7 +717,7 @@ private:
* <tr><td><code>NavigationFocused</code></td><td>number</td><td>number</td><td><em>Not used.</em></td></tr>
* </tbody>
* </table>
* @typedef Controller.Hardware-Application
* @typedef {object} Controller.Hardware-Application
*/
static const QString STATE_IN_HMD = "InHMD";
@ -4632,12 +4632,6 @@ void Application::idle() {
_overlayConductor.update(secondsSinceLastUpdate);
auto myAvatar = getMyAvatar();
if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON || _myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) {
Menu::getInstance()->setIsOptionChecked(MenuOption::FirstPerson, myAvatar->getBoomLength() <= MyAvatar::ZOOM_MIN);
Menu::getInstance()->setIsOptionChecked(MenuOption::ThirdPerson, !(myAvatar->getBoomLength() <= MyAvatar::ZOOM_MIN));
cameraMenuChanged();
}
_gameLoopCounter.increment();
}
@ -5184,6 +5178,21 @@ void Application::cameraModeChanged() {
cameraMenuChanged();
}
void Application::changeViewAsNeeded(float boomLength) {
// Switch between first and third person views as needed
// This is called when the boom length has changed
bool boomLengthGreaterThanMinimum = (boomLength > MyAvatar::ZOOM_MIN);
if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON && boomLengthGreaterThanMinimum) {
Menu::getInstance()->setIsOptionChecked(MenuOption::FirstPerson, false);
Menu::getInstance()->setIsOptionChecked(MenuOption::ThirdPerson, true);
cameraMenuChanged();
} else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON && !boomLengthGreaterThanMinimum) {
Menu::getInstance()->setIsOptionChecked(MenuOption::FirstPerson, true);
Menu::getInstance()->setIsOptionChecked(MenuOption::ThirdPerson, false);
cameraMenuChanged();
}
}
void Application::cameraMenuChanged() {
auto menu = Menu::getInstance();

View file

@ -417,6 +417,8 @@ public slots:
void updateVerboseLogging();
void changeViewAsNeeded(float boomLength);
private slots:
void onDesktopRootItemCreated(QQuickItem* qmlContext);
void onDesktopRootContextCreated(QQmlContext* qmlContext);
@ -649,7 +651,7 @@ private:
quint64 _lastFaceTrackerUpdate;
render::ScenePointer _main3DScene{ new render::Scene(glm::vec3(-0.5f * (float)TREE_SCALE), (float)TREE_SCALE) };
render::EnginePointer _renderEngine{ new render::Engine() };
render::EnginePointer _renderEngine{ new render::RenderEngine() };
gpu::ContextPointer _gpuContext; // initialized during window creation
mutable QMutex _renderArgsMutex{ QMutex::Recursive };

View file

@ -25,7 +25,7 @@ class FancyCamera : public Camera {
// FIXME: JSDoc 3.5.5 doesn't augment @property definitions. The following definition is repeated in Camera.h.
/**jsdoc
* @property cameraEntity {Uuid} The ID of the entity that the camera position and orientation follow when the camera is in
* @property {Uuid} cameraEntity The ID of the entity that the camera position and orientation follow when the camera is in
* entity mode.
*/
Q_PROPERTY(QUuid cameraEntity READ getCameraEntity WRITE setCameraEntity)

View file

@ -160,7 +160,7 @@ QUuid AvatarMotionState::getSimulatorID() const {
}
// virtual
void AvatarMotionState::computeCollisionGroupAndMask(int16_t& group, int16_t& mask) const {
void AvatarMotionState::computeCollisionGroupAndMask(int32_t& group, int32_t& mask) const {
group = BULLET_COLLISION_GROUP_OTHER_AVATAR;
mask = Physics::getDefaultCollisionMask(group);
}

View file

@ -65,7 +65,7 @@ public:
void addDirtyFlags(uint32_t flags) { _dirtyFlags |= flags; }
virtual void computeCollisionGroupAndMask(int16_t& group, int16_t& mask) const override;
virtual void computeCollisionGroupAndMask(int32_t& group, int32_t& mask) const override;
virtual float getMass() const override;

View file

@ -2245,9 +2245,15 @@ void MyAvatar::updateActionMotor(float deltaTime) {
_actionMotorVelocity = getSensorToWorldScale() * (_walkSpeed.get() * _walkSpeedScalar) * direction;
}
float previousBoomLength = _boomLength;
float boomChange = getDriveKey(ZOOM);
_boomLength += 2.0f * _boomLength * boomChange + boomChange * boomChange;
_boomLength = glm::clamp<float>(_boomLength, ZOOM_MIN, ZOOM_MAX);
// May need to change view if boom length has changed
if (previousBoomLength != _boomLength) {
qApp->changeViewAsNeeded(_boomLength);
}
}
void MyAvatar::updatePosition(float deltaTime) {

View file

@ -121,7 +121,7 @@ class MyAvatar : public Avatar {
* while flying.
* @property {number} hmdRollControlDeadZone=8 - The amount of HMD roll, in degrees, required before your avatar turns if
* <code>hmdRollControlEnabled</code> is enabled.
* @property hmdRollControlRate {number} If hmdRollControlEnabled is true, this value determines the maximum turn rate of
* @property {number} hmdRollControlRate If hmdRollControlEnabled is true, this value determines the maximum turn rate of
* your avatar when rolling your HMD in degrees per second.
* @property {number} userHeight=1.75 - The height of the user in sensor space.
* @property {number} userEyeHeight=1.65 - The estimated height of the user's eyes in sensor space. <em>Read-only.</em>
@ -1402,7 +1402,7 @@ private:
SharedSoundPointer _collisionSound;
MyCharacterController _characterController;
int16_t _previousCollisionGroup { BULLET_COLLISION_GROUP_MY_AVATAR };
int32_t _previousCollisionGroup { BULLET_COLLISION_GROUP_MY_AVATAR };
AvatarWeakPointer _lookAtTargetAvatar;
glm::vec3 _targetAvatarPosition;

View file

@ -22,21 +22,22 @@
* @hifi-interface
* @hifi-client-entity
*
* @property PICK_NOTHING {number} A filter flag. Don't intersect with anything. <em>Read-only.</em>
* @property PICK_ENTITIES {number} A filter flag. Include entities when intersecting. <em>Read-only.</em>
* @property PICK_OVERLAYS {number} A filter flag. Include overlays when intersecting. <em>Read-only.</em>
* @property PICK_AVATARS {number} A filter flag. Include avatars when intersecting. <em>Read-only.</em>
* @property PICK_HUD {number} A filter flag. Include the HUD sphere when intersecting in HMD mode. <em>Read-only.</em>
* @property PICK_COARSE {number} A filter flag. Pick against coarse meshes, instead of exact meshes. <em>Read-only.</em>
* @property PICK_INCLUDE_INVISIBLE {number} A filter flag. Include invisible objects when intersecting. <em>Read-only.</em>
* @property PICK_INCLUDE_NONCOLLIDABLE {number} A filter flag. Include non-collidable objects when intersecting.
* @property {number} PICK_NOTHING A filter flag. Don't intersect with anything. <em>Read-only.</em>
* @property {number} PICK_ENTITIES A filter flag. Include entities when intersecting. <em>Read-only.</em>
* @property {number} PICK_OVERLAYS A filter flag. Include overlays when intersecting. <em>Read-only.</em>
* @property {number} PICK_AVATARS A filter flag. Include avatars when intersecting. <em>Read-only.</em>
* @property {number} PICK_HUD A filter flag. Include the HUD sphere when intersecting in HMD mode. <em>Read-only.</em>
* @property {number} PICK_COARSE A filter flag. Pick against coarse meshes, instead of exact meshes. <em>Read-only.</em>
* @property {number} PICK_INCLUDE_INVISIBLE A filter flag. Include invisible objects when intersecting. <em>Read-only.</em>
* @property {number} PICK_INCLUDE_NONCOLLIDABLE A filter flag. Include non-collidable objects when intersecting.
* <em>Read-only.</em>
* @property PICK_ALL_INTERSECTIONS {number} <em>Read-only.</em>
* @property INTERSECTED_NONE {number} An intersection type. Intersected nothing with the given filter flags. <em>Read-only.</em>
* @property INTERSECTED_ENTITY {number} An intersection type. Intersected an entity. <em>Read-only.</em>
* @property INTERSECTED_OVERLAY {number} An intersection type. Intersected an overlay. <em>Read-only.</em>
* @property INTERSECTED_AVATAR {number} An intersection type. Intersected an avatar. <em>Read-only.</em>
* @property INTERSECTED_HUD {number} An intersection type. Intersected the HUD sphere. <em>Read-only.</em>
* @property {number} PICK_ALL_INTERSECTIONS <em>Read-only.</em>
* @property {number} INTERSECTED_NONE An intersection type. Intersected nothing with the given filter flags.
* <em>Read-only.</em>
* @property {number} INTERSECTED_ENTITY An intersection type. Intersected an entity. <em>Read-only.</em>
* @property {number} INTERSECTED_OVERLAY An intersection type. Intersected an overlay. <em>Read-only.</em>
* @property {number} INTERSECTED_AVATAR An intersection type. Intersected an avatar. <em>Read-only.</em>
* @property {number} INTERSECTED_HUD An intersection type. Intersected the HUD sphere. <em>Read-only.</em>
* @property {number} perFrameTimeBudget - The max number of usec to spend per frame updating Pick results. <em>Read-only.</em>
*/
@ -99,7 +100,7 @@ public:
/**jsdoc
* An intersection result for a Ray Pick.
*
* @typedef {Object} RayPickResult
* @typedef {object} RayPickResult
* @property {number} type The intersection type.
* @property {boolean} intersects If there was a valid intersection (type != INTERSECTED_NONE)
* @property {Uuid} objectID The ID of the intersected object. Uuid.NULL for the HUD or invalid intersections.
@ -113,7 +114,7 @@ public:
/**jsdoc
* An intersection result for a Stylus Pick.
*
* @typedef {Object} StylusPickResult
* @typedef {object} StylusPickResult
* @property {number} type The intersection type.
* @property {boolean} intersects If there was a valid intersection (type != INTERSECTED_NONE)
* @property {Uuid} objectID The ID of the intersected object. Uuid.NULL for the HUD or invalid intersections.

View file

@ -68,14 +68,14 @@ unsigned int PointerScriptingInterface::createStylus(const QVariant& properties)
* A set of properties used to define the visual aspect of a Ray Pointer in the case that the Pointer is not intersecting something. Same as a {@link Pointers.RayPointerRenderState},
* but with an additional distance field.
*
* @typedef {Object} Pointers.DefaultRayPointerRenderState
* @typedef {object} Pointers.DefaultRayPointerRenderState
* @augments Pointers.RayPointerRenderState
* @property {number} distance The distance at which to render the end of this Ray Pointer, if one is defined.
*/
/**jsdoc
* A set of properties used to define the visual aspect of a Ray Pointer in the case that the Pointer is intersecting something.
*
* @typedef {Object} Pointers.RayPointerRenderState
* @typedef {object} Pointers.RayPointerRenderState
* @property {string} name The name of this render state, used by {@link Pointers.setRenderState} and {@link Pointers.editRenderState}
* @property {Overlays.OverlayProperties} [start] All of the properties you would normally pass to {@link Overlays.addOverlay}, plus the type (as a <code>type</code> field).
* An overlay to represent the beginning of the Ray Pointer, if desired.
@ -87,7 +87,7 @@ unsigned int PointerScriptingInterface::createStylus(const QVariant& properties)
/**jsdoc
* A trigger mechanism for Ray Pointers.
*
* @typedef {Object} Pointers.Trigger
* @typedef {object} Pointers.Trigger
* @property {Controller.Standard|Controller.Actions|function} action This can be a built-in Controller action, like Controller.Standard.LTClick, or a function that evaluates to >= 1.0 when you want to trigger <code>button</code>.
* @property {string} button Which button to trigger. "Primary", "Secondary", "Tertiary", and "Focus" are currently supported. Only "Primary" will trigger clicks on web surfaces. If "Focus" is triggered,
* it will try to set the entity or overlay focus to the object at which the Pointer is aimed. Buttons besides the first three will still trigger events, but event.button will be "None".

View file

@ -522,7 +522,7 @@ int WindowScriptingInterface::openMessageBox(QString title, QString text, int bu
* <tr> <td><strong>RestoreDefaults</strong></td> <td><code>0x8000000</code></td> <td>"Restore Defaults"</td> </tr>
* </tbody>
* </table>
* @typedef Window.MessageBoxButton
* @typedef {number} Window.MessageBoxButton
*/
int WindowScriptingInterface::createMessageBox(QString title, QString text, int buttons, int defaultButton) {
auto messageBox = DependencyManager::get<OffscreenUi>()->createMessageBox(OffscreenUi::ICON_INFORMATION, title, text,

View file

@ -470,7 +470,7 @@ public slots:
* </tr>
* </tbody>
* </table>
* @typedef Window.DisplayTexture
* @typedef {string} Window.DisplayTexture
*/
bool setDisplayTexture(const QString& name);
@ -523,16 +523,21 @@ public slots:
int openMessageBox(QString title, QString text, int buttons, int defaultButton);
/**jsdoc
* Open the given resource in the Interface window or in a web browser depending on the url scheme
* Open a URL in the Interface window or other application, depending on the URL's scheme. If the URL starts with
* <code>hifi://</code> then that URL is navigated to in Interface, otherwise the URL is opened in the application the OS
* associates with the URL's scheme (e.g., a Web browser for <code>http://</code>).
* @function Window.openUrl
* @param {string} url - The resource to open
* @param {string} url - The URL to open.
*/
void openUrl(const QUrl& url);
/**jsdoc
* (Android only) Open the requested Activity and optionally back to the scene when the activity is done
* Open an Android activity and optionally return back to the scene when the activity is completed. <em>Android only.</em>
* @function Window.openAndroidActivity
* @param {string} activityName - The name of the activity to open. One of "Home", "Login" or "Privacy Policy"
* @param {string} activityName - The name of the activity to open: one of <code>"Home"</code>, <code>"Login"</code>, or
* <code>"Privacy Policy"</code>.
* @param {boolean} backToScene - If <code>true</code>, the user is automatically returned back to the scene when the
* activity is completed.
*/
void openAndroidActivity(const QString& activityName, const bool backToScene);

View file

@ -46,6 +46,13 @@ bool Billboard3DOverlay::applyTransformTo(Transform& transform, bool force) {
return transformChanged;
}
void Billboard3DOverlay::update(float duration) {
if (isFacingAvatar()) {
_renderVariableDirty = true;
}
Parent::update(duration);
}
Transform Billboard3DOverlay::evalRenderTransform() {
Transform transform = getTransform();
bool transformChanged = applyTransformTo(transform, true);

View file

@ -18,6 +18,7 @@
class Billboard3DOverlay : public Planar3DOverlay, public PanelAttachable, public Billboardable {
Q_OBJECT
using Parent = Planar3DOverlay;
public:
Billboard3DOverlay() {}
@ -26,6 +27,8 @@ public:
void setProperties(const QVariantMap& properties) override;
QVariant getProperty(const QString& property) override;
void update(float duration) override;
protected:
virtual bool applyTransformTo(Transform& transform, bool force = false) override;

View file

@ -51,11 +51,6 @@ void Image3DOverlay::update(float deltatime) {
_texture = DependencyManager::get<TextureCache>()->getTexture(_url);
_textureIsLoaded = false;
}
if (usecTimestampNow() > _transformExpiry) {
Transform transform = getTransform();
applyTransformTo(transform);
setTransform(transform);
}
Parent::update(deltatime);
}

View file

@ -53,7 +53,7 @@ const OverlayID UNKNOWN_OVERLAY_ID = OverlayID();
* @property {number} distance - The distance from the {@link PickRay} origin to the intersection point.
* @property {Vec3} surfaceNormal - The normal of the overlay surface at the intersection point.
* @property {Vec3} intersection - The position of the intersection point.
* @property {Object} extraInfo Additional intersection details, if available.
* @property {object} extraInfo Additional intersection details, if available.
*/
class RayToOverlayIntersectionResult {
public:
@ -482,7 +482,7 @@ public slots:
/**jsdoc
* Check if there is an overlay of a given ID.
* @function Overlays.isAddedOverly
* @function Overlays.isAddedOverlay
* @param {Uuid} overlayID - The ID to check.
* @returns {boolean} <code>true</code> if an overlay with the given ID exists, <code>false</code> otherwise.
*/

View file

@ -83,15 +83,6 @@ xColor Text3DOverlay::getBackgroundColor() {
return result;
}
void Text3DOverlay::update(float deltatime) {
if (usecTimestampNow() > _transformExpiry) {
Transform transform = getTransform();
applyTransformTo(transform);
setTransform(transform);
}
Parent::update(deltatime);
}
void Text3DOverlay::render(RenderArgs* args) {
if (!_renderVisible || !getParentVisible()) {
return; // do nothing if we're not visible
@ -306,13 +297,4 @@ QSizeF Text3DOverlay::textSize(const QString& text) const {
float pointToWorldScale = (maxHeight / FIXED_FONT_SCALING_RATIO) * _lineHeight;
return QSizeF(extents.x, extents.y) * pointToWorldScale;
}
bool Text3DOverlay::findRayIntersection(const glm::vec3 &origin, const glm::vec3 &direction, float &distance,
BoxFace &face, glm::vec3& surfaceNormal) {
Transform transform = getTransform();
applyTransformTo(transform, true);
setTransform(transform);
return Billboard3DOverlay::findRayIntersection(origin, direction, distance, face, surfaceNormal);
}
}

View file

@ -30,8 +30,6 @@ public:
~Text3DOverlay();
virtual void render(RenderArgs* args) override;
virtual void update(float deltatime) override;
virtual const render::ShapeKey getShapeKey() override;
// getters
@ -60,9 +58,6 @@ public:
QSizeF textSize(const QString& test) const; // Meters
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
BoxFace& face, glm::vec3& surfaceNormal) override;
virtual Text3DOverlay* createClone() const override;
private:

View file

@ -259,7 +259,6 @@ void Web3DOverlay::setupQmlSurface() {
_webSurface->getSurfaceContext()->setContextProperty("Web3DOverlay", this);
_webSurface->getSurfaceContext()->setContextProperty("Window", DependencyManager::get<WindowScriptingInterface>().data());
_webSurface->getSurfaceContext()->setContextProperty("Reticle", qApp->getApplicationCompositor().getReticleInterface());
_webSurface->getSurfaceContext()->setContextProperty("desktop", DependencyManager::get<OffscreenUi>()->getDesktop());
_webSurface->getSurfaceContext()->setContextProperty("HiFiAbout", AboutUtil::getInstance());
// Override min fps for tablet UI, for silky smooth scrolling

View file

@ -70,7 +70,7 @@ public:
* @function AnimationCache.prefetch
* @param {string} url - URL of the resource to prefetch.
* @param {object} [extra=null]
* @returns {Resource}
* @returns {ResourceObject}
*/
/**jsdoc
@ -79,7 +79,7 @@ public:
* @param {string} url - URL of the resource to load.
* @param {string} [fallback=""] - Fallback URL if load of the desired URL fails.
* @param {} [extra=null]
* @returns {Resource}
* @returns {object}
*/
@ -87,7 +87,7 @@ public:
* Returns animation resource for particular animation.
* @function AnimationCache.getAnimation
* @param {string} url - URL to load.
* @returns {Resource} animation
* @returns {AnimationObject} animation
*/
Q_INVOKABLE AnimationPointer getAnimation(const QString& url) { return getAnimation(QUrl(url)); }
Q_INVOKABLE AnimationPointer getAnimation(const QUrl& url);
@ -104,6 +104,17 @@ private:
Q_DECLARE_METATYPE(AnimationPointer)
/**jsdoc
* @class AnimationObject
*
* @hifi-interface
* @hifi-client-entity
* @hifi-server-entity
* @hifi-assignment-client
*
* @property {string[]} jointNames
* @property {FBXAnimationFrame[]} frames
*/
/// An animation loaded from the network.
class Animation : public Resource {
Q_OBJECT
@ -118,9 +129,16 @@ public:
virtual bool isLoaded() const override;
/**jsdoc
* @function AnimationObject.getJointNames
* @returns {string[]}
*/
Q_INVOKABLE QStringList getJointNames() const;
/**jsdoc
* @function AnimationObject.getFrames
* @returns {FBXAnimationFrame[]}
*/
Q_INVOKABLE QVector<FBXAnimationFrame> getFrames() const;
const QVector<FBXAnimationFrame>& getFramesReference() const;

View file

@ -77,6 +77,17 @@ private:
typedef QSharedPointer<Sound> SharedSoundPointer;
/**jsdoc
* @class SoundObject
*
* @hifi-interface
* @hifi-client-entity
* @hifi-server-entity
* @hifi-assignment-client
*
* @property {boolean} downloaded
* @property {number} duration
*/
class SoundScriptingInterface : public QObject {
Q_OBJECT
@ -90,6 +101,10 @@ public:
bool isReady() const { return _sound->isReady(); }
float getDuration() { return _sound->getDuration(); }
/**jsdoc
* @function SoundObject.ready
* @returns {Signal}
*/
signals:
void ready();

View file

@ -64,7 +64,7 @@ public:
* @function SoundCache.prefetch
* @param {string} url - URL of the resource to prefetch.
* @param {object} [extra=null]
* @returns {Resource}
* @returns {ResourceObject}
*/
/**jsdoc
@ -73,14 +73,14 @@ public:
* @param {string} url - URL of the resource to load.
* @param {string} [fallback=""] - Fallback URL if load of the desired URL fails.
* @param {} [extra=null]
* @returns {Resource}
* @returns {object}
*/
/**jsdoc
* @function SoundCache.getSound
* @param {string} url
* @returns {object}
* @returns {SoundObject}
*/
Q_INVOKABLE SharedSoundPointer getSound(const QUrl& url);
protected:

View file

@ -292,7 +292,7 @@ public:
*/
/**jsdoc
* Information about a single joint in an Avatar's skeleton hierarchy.
* @typedef MyAvatar.SkeletonJoint
* @typedef {object} MyAvatar.SkeletonJoint
* @property {string} name - Joint name.
* @property {number} index - Joint index.
* @property {number} parentIndex - Index of this joint's parent (-1 if no parent).

View file

@ -2363,7 +2363,7 @@ glm::vec3 AvatarData::getAbsoluteJointTranslationInObjectFrame(int index) const
}
/**jsdoc
* @typedef AttachmentData
* @typedef {object} AttachmentData
* @property {string} modelUrl
* @property {string} jointName
* @property {Vec3} translation

View file

@ -578,8 +578,7 @@ public:
* @param {Quat} rotation - The rotation of the joint relative to its parent.
* @param {Vec3} translation - The translation of the joint relative to its parent.
* @example <caption>Set your avatar to it's default T-pose for a while.<br />
* <img alt="Avatar in T-pose" src="https://docs.highfidelity.com/user/pages/06.api-reference/25.myavatar/t-pose.png" />
* </caption>
* <img alt="Avatar in T-pose" src="https://docs.highfidelity.com/images/t-pose.png" /></caption>
* // Set all joint translations and rotations to defaults.
* var i, length, rotation, translation;
* for (i = 0, length = MyAvatar.getJointNames().length; i < length; i++) {
@ -680,8 +679,7 @@ public:
* @param {string} name - The name of the joint.
* @param {Quat} rotation - The rotation of the joint relative to its parent.
* @example <caption>Set your avatar to its default T-pose then rotate its right arm.<br />
* <img alt="Avatar in T-pose with arm rotated"
* src="https://docs.highfidelity.com/user/pages/06.api-reference/25.myavatar/armpose.png" /></caption>
* <img alt="Avatar in T-pose with arm rotated" src="https://docs.highfidelity.com/images/armpose.png" /></caption>
* // Set all joint translations and rotations to defaults.
* var i, length, rotation, translation;
* for (i = 0, length = MyAvatar.getJointNames().length; i < length; i++) {
@ -713,8 +711,7 @@ public:
* @param {Vec3} translation - The translation of the joint relative to its parent.
* @example <caption>Stretch your avatar's neck. Depending on the avatar you are using, you will either see a gap between
* the head and body or you will see the neck stretched.<br />
* <img alt="Avatar with neck stretched"
* src="https://docs.highfidelity.com/user/pages/06.api-reference/25.myavatar/stretched-neck.png" /></caption>
* <img alt="Avatar with neck stretched" src="https://docs.highfidelity.com/images/stretched-neck.png" /></caption>
* // Stretch your avatar's neck.
* MyAvatar.setJointTranslation("Neck", { x: 0, y: 25, z: 0 });
*
@ -798,8 +795,7 @@ public:
* @param {Quat[]} jointRotations - The rotations for all joints in the avatar. The values are in the same order as the
* array returned by {@link MyAvatar.getJointNames} or {@link Avatar.getJointNames}.
* @example <caption>Set your avatar to its default T-pose then rotate its right arm.<br />
* <img alt="Avatar in T-pose" src="https://docs.highfidelity.com/user/pages/06.api-reference/25.myavatar/armpose.png" />
* </caption>
* <img alt="Avatar in T-pose" src="https://docs.highfidelity.com/images/armpose.png" /></caption>
* // Set all joint translations and rotations to defaults.
* var i, length, rotation, translation;
* for (i = 0, length = MyAvatar.getJointNames().length; i < length; i++) {

View file

@ -307,7 +307,7 @@ namespace controller {
* action.</td></tr>
* </tbody>
* </table>
* @typedef Controller.Actions
* @typedef {object} Controller.Actions
*/
// Device functions
Input::NamedVector ActionsDevice::getAvailableInputs() const {

View file

@ -79,7 +79,7 @@ enum Hand {
* {@link Controller.Hardware-Vive}.</td></tr>
* </tbody>
* </table>
* @typedef Controller.Hardware
* @typedef {object} Controller.Hardware
* @example <caption>List all the currently available <code>Controller.Hardware</code> properties.</caption>
* function printProperties(string, item) {
* print(string);

View file

@ -231,7 +231,7 @@ void StandardController::focusOutEvent() {
*
* </tbody>
* </table>
* @typedef Controller.Standard
* @typedef {object} Controller.Standard
*/
Input::NamedVector StandardController::getAvailableInputs() const {
static Input::NamedVector availableInputs {

View file

@ -46,7 +46,7 @@ bool operator!=(const AnimationPropertyGroup& a, const AnimationPropertyGroup& b
/**jsdoc
* The AnimationProperties are used to configure an animation.
* @typedef Entities.AnimationProperties
* @typedef {object} Entities.AnimationProperties
* @property {string} url="" - The URL of the FBX file that has the animation.
* @property {number} fps=30 - The speed in frames/s that the animation is played at.
* @property {number} firstFrame=0 - The first frame to play in the animation.

View file

@ -817,7 +817,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
READ_ENTITY_PROPERTY(PROP_VISIBLE, bool, setVisible);
READ_ENTITY_PROPERTY(PROP_CAN_CAST_SHADOW, bool, setCanCastShadow);
READ_ENTITY_PROPERTY(PROP_COLLISIONLESS, bool, setCollisionless);
READ_ENTITY_PROPERTY(PROP_COLLISION_MASK, uint8_t, setCollisionMask);
READ_ENTITY_PROPERTY(PROP_COLLISION_MASK, uint16_t, setCollisionMask);
READ_ENTITY_PROPERTY(PROP_DYNAMIC, bool, setDynamic);
READ_ENTITY_PROPERTY(PROP_LOCKED, bool, setLocked);
READ_ENTITY_PROPERTY(PROP_USER_DATA, QString, setUserData);
@ -1849,7 +1849,7 @@ void EntityItem::setCollisionless(bool value) {
});
}
void EntityItem::setCollisionMask(uint8_t value) {
void EntityItem::setCollisionMask(uint16_t value) {
withWriteLock([&] {
if ((_collisionMask & ENTITY_COLLISION_MASK_DEFAULT) != (value & ENTITY_COLLISION_MASK_DEFAULT)) {
_collisionMask = (value & ENTITY_COLLISION_MASK_DEFAULT);
@ -1914,7 +1914,7 @@ void EntityItem::setCreated(quint64 value) {
});
}
void EntityItem::computeCollisionGroupAndFinalMask(int16_t& group, int16_t& mask) const {
void EntityItem::computeCollisionGroupAndFinalMask(int32_t& group, int32_t& mask) const {
if (_collisionless) {
group = BULLET_COLLISION_GROUP_COLLISIONLESS;
mask = 0;
@ -1927,7 +1927,7 @@ void EntityItem::computeCollisionGroupAndFinalMask(int16_t& group, int16_t& mask
group = BULLET_COLLISION_GROUP_STATIC;
}
uint8_t userMask = getCollisionMask();
uint16_t userMask = getCollisionMask();
if ((bool)(userMask & USER_COLLISION_GROUP_MY_AVATAR) !=
(bool)(userMask & USER_COLLISION_GROUP_OTHER_AVATAR)) {
@ -1941,7 +1941,7 @@ void EntityItem::computeCollisionGroupAndFinalMask(int16_t& group, int16_t& mask
if ((bool)(_flags & Simulation::SPECIAL_FLAGS_NO_BOOTSTRAPPING)) {
userMask &= ~USER_COLLISION_GROUP_MY_AVATAR;
}
mask = Physics::getDefaultCollisionMask(group) & (int16_t)(userMask);
mask = Physics::getDefaultCollisionMask(group) & (int32_t)(userMask);
}
}
@ -2795,8 +2795,8 @@ bool EntityItem::getCollisionless() const {
return result;
}
uint8_t EntityItem::getCollisionMask() const {
uint8_t result;
uint16_t EntityItem::getCollisionMask() const {
uint16_t result;
withReadLock([&] {
result = _collisionMask;
});

View file

@ -288,10 +288,10 @@ public:
bool getCollisionless() const;
void setCollisionless(bool value);
uint8_t getCollisionMask() const;
void setCollisionMask(uint8_t value);
uint16_t getCollisionMask() const;
void setCollisionMask(uint16_t value);
void computeCollisionGroupAndFinalMask(int16_t& group, int16_t& mask) const;
void computeCollisionGroupAndFinalMask(int32_t& group, int32_t& mask) const;
bool getDynamic() const;
void setDynamic(bool value);
@ -580,7 +580,7 @@ protected:
bool _visible { ENTITY_ITEM_DEFAULT_VISIBLE };
bool _canCastShadow{ ENTITY_ITEM_DEFAULT_CAN_CAST_SHADOW };
bool _collisionless { ENTITY_ITEM_DEFAULT_COLLISIONLESS };
uint8_t _collisionMask { ENTITY_COLLISION_MASK_DEFAULT };
uint16_t _collisionMask { ENTITY_COLLISION_MASK_DEFAULT };
bool _dynamic { ENTITY_ITEM_DEFAULT_DYNAMIC };
bool _locked { ENTITY_ITEM_DEFAULT_LOCKED };
QString _userData { ENTITY_ITEM_DEFAULT_USER_DATA };

View file

@ -130,7 +130,7 @@ void buildStringToMaterialMappingModeLookup() {
addMaterialMappingMode(PROJECTED);
}
QString getCollisionGroupAsString(uint8_t group) {
QString getCollisionGroupAsString(uint16_t group) {
switch (group) {
case USER_COLLISION_GROUP_DYNAMIC:
return "dynamic";
@ -146,7 +146,7 @@ QString getCollisionGroupAsString(uint8_t group) {
return "";
}
uint8_t getCollisionGroupAsBitMask(const QStringRef& name) {
uint16_t getCollisionGroupAsBitMask(const QStringRef& name) {
if (0 == name.compare(QString("dynamic"))) {
return USER_COLLISION_GROUP_DYNAMIC;
} else if (0 == name.compare(QString("static"))) {
@ -164,7 +164,7 @@ uint8_t getCollisionGroupAsBitMask(const QStringRef& name) {
QString EntityItemProperties::getCollisionMaskAsString() const {
QString maskString("");
for (int i = 0; i < NUM_USER_COLLISION_GROUPS; ++i) {
uint8_t group = 0x01 << i;
uint16_t group = 0x0001 << i;
if (group & _collisionMask) {
maskString.append(getCollisionGroupAsString(group));
maskString.append(',');
@ -175,7 +175,7 @@ QString EntityItemProperties::getCollisionMaskAsString() const {
void EntityItemProperties::setCollisionMaskFromString(const QString& maskString) {
QVector<QStringRef> groups = maskString.splitRef(',');
uint8_t mask = 0x00;
uint16_t mask = 0x0000;
for (auto groupName : groups) {
mask |= getCollisionGroupAsBitMask(groupName);
}
@ -486,7 +486,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
* @property {boolean} locked=false - Whether or not the entity can be edited or deleted. If <code>true</code> then the
* entity's properties other than <code>locked</code> cannot be changed, and the entity cannot be deleted.
* @property {boolean} visible=true - Whether or not the entity is rendered. If <code>true</code> then the entity is rendered.
* @property {boolean} canCastShadows=true - Whether or not the entity casts shadows. Currently applicable only to
* @property {boolean} canCastShadow=true - Whether or not the entity can cast a shadow. Currently applicable only to
* {@link Entities.EntityType|Model} and {@link Entities.EntityType|Shape} entities. Shadows are cast if inside a
* {@link Entities.EntityType|Zone} entity with <code>castShadows</code> enabled in its
* {@link Entities.EntityProperties-Zone|keyLight} property.
@ -1398,7 +1398,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
/**jsdoc
* The axis-aligned bounding box of an entity.
* @typedef Entities.BoundingBox
* @typedef {object} Entities.BoundingBox
* @property {Vec3} brn - The bottom right near (minimum axes values) corner of the AA box.
* @property {Vec3} tfl - The top far left (maximum axes values) corner of the AA box.
* @property {Vec3} center - The center of the AA box.
@ -1520,7 +1520,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool
COPY_PROPERTY_FROM_QSCRIPTVALUE(localRenderAlpha, float, setLocalRenderAlpha);
COPY_PROPERTY_FROM_QSCRIPTVALUE(collisionless, bool, setCollisionless);
COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(ignoreForCollisions, bool, setCollisionless, getCollisionless); // legacy support
COPY_PROPERTY_FROM_QSCRIPTVALUE(collisionMask, uint8_t, setCollisionMask);
COPY_PROPERTY_FROM_QSCRIPTVALUE(collisionMask, uint16_t, setCollisionMask);
COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(collidesWith, CollisionMask);
COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(collisionsWillMove, bool, setDynamic, getDynamic); // legacy support
COPY_PROPERTY_FROM_QSCRIPTVALUE(dynamic, bool, setDynamic);
@ -2576,7 +2576,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_VISIBLE, bool, setVisible);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_CAN_CAST_SHADOW, bool, setCanCastShadow);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLLISIONLESS, bool, setCollisionless);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLLISION_MASK, uint8_t, setCollisionMask);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLLISION_MASK, uint16_t, setCollisionMask);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_DYNAMIC, bool, setDynamic);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LOCKED, bool, setLocked);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_USER_DATA, QString, setUserData);

View file

@ -148,7 +148,7 @@ public:
DEFINE_PROPERTY_REF(PROP_ANGULAR_VELOCITY, AngularVelocity, angularVelocity, glm::vec3, ENTITY_ITEM_DEFAULT_ANGULAR_VELOCITY);
DEFINE_PROPERTY(PROP_ANGULAR_DAMPING, AngularDamping, angularDamping, float, ENTITY_ITEM_DEFAULT_ANGULAR_DAMPING);
DEFINE_PROPERTY(PROP_COLLISIONLESS, Collisionless, collisionless, bool, ENTITY_ITEM_DEFAULT_COLLISIONLESS);
DEFINE_PROPERTY(PROP_COLLISION_MASK, CollisionMask, collisionMask, uint8_t, ENTITY_COLLISION_MASK_DEFAULT);
DEFINE_PROPERTY(PROP_COLLISION_MASK, CollisionMask, collisionMask, uint16_t, ENTITY_COLLISION_MASK_DEFAULT);
DEFINE_PROPERTY(PROP_DYNAMIC, Dynamic, dynamic, bool, ENTITY_ITEM_DEFAULT_DYNAMIC);
DEFINE_PROPERTY(PROP_IS_SPOTLIGHT, IsSpotlight, isSpotlight, bool, LightEntityItem::DEFAULT_IS_SPOTLIGHT);
DEFINE_PROPERTY(PROP_INTENSITY, Intensity, intensity, float, LightEntityItem::DEFAULT_INTENSITY);

View file

@ -35,7 +35,7 @@ class ReadBitstreamToTreeParams;
* @property {Vec3} direction=0,-1,0 - The direction the light is shining.
* @property {boolean} castShadows=false - If <code>true</code> then shadows are cast. Shadows are cast by avatars, plus
* {@link Entities.EntityType|Model} and {@link Entities.EntityType|Shape} entities that have their
* <code>{@link Entities.EntityProperties|canCastShadows}</code> property set to <code>true</code>.
* <code>{@link Entities.EntityProperties|canCastShadow}</code> property set to <code>true</code>.
*/
class KeyLightPropertyGroup : public PropertyGroup {
public:

View file

@ -258,6 +258,11 @@ public:
QHash<QString, size_t> texcoordSetMap;
};
/**jsdoc
* @typedef {object} FBXAnimationFrame
* @property {Quat[]} rotations
* @property {Vec3[]} translations
*/
/// A single animation frame extracted from an FBX document.
class FBXAnimationFrame {
public:

View file

@ -1174,7 +1174,7 @@ bool GLTFReader::addArrayOfType(const QByteArray& bin, int byteOffset, int byteL
break;
}
case GLTFAccessorComponentType::UNSIGNED_INT: {
readArray<quint8>(bin, byteOffset, byteLength, outarray, accessorType);
readArray<quint32>(bin, byteOffset, byteLength, outarray, accessorType);
break;
}
case GLTFAccessorComponentType::UNSIGNED_SHORT: {

View file

@ -190,7 +190,7 @@ namespace GLTFBufferViewTarget {
struct GLTFBufferView {
int buffer; //required
int byteLength; //required
int byteOffset;
int byteOffset { 0 };
int target;
QMap<QString, bool> defined;
void dump() {
@ -470,7 +470,7 @@ namespace GLTFAccessorComponentType {
}
struct GLTFAccessor {
int bufferView;
int byteOffset;
int byteOffset { 0 };
int componentType; //required
int count; //required
int type; //required

View file

@ -31,6 +31,10 @@ bool GL41Backend::supportedTextureFormat(const gpu::Element& format) {
case gpu::Semantic::COMPRESSED_EAC_RED_SIGNED:
case gpu::Semantic::COMPRESSED_EAC_XY:
case gpu::Semantic::COMPRESSED_EAC_XY_SIGNED:
// The ARB_texture_compression_bptc extension is not supported on 4.1
// See https://www.g-truc.net/doc/OpenGL%204%20Hardware%20Matrix.pdf
case gpu::Semantic::COMPRESSED_BC6_RGB:
case gpu::Semantic::COMPRESSED_BC7_SRGBA:
return false;
default:
return true;

View file

@ -33,6 +33,8 @@ using namespace gpu::gl45;
bool GL45Backend::supportedTextureFormat(const gpu::Element& format) {
switch (format.getSemantic()) {
// ETC textures are actually required by the OpenGL spec as of 4.3, but aren't always supported by hardware
// They'll be recompressed by OpenGL, which will be slow or have poor quality, so disable them for now
case gpu::Semantic::COMPRESSED_ETC2_RGB:
case gpu::Semantic::COMPRESSED_ETC2_SRGB:
case gpu::Semantic::COMPRESSED_ETC2_RGB_PUNCHTHROUGH_ALPHA:

View file

@ -279,7 +279,7 @@ controller::Input KeyboardMouseDevice::InputDevice::makeInput(KeyboardMouseDevic
* moved down. The data value is how far the average position of all touch points moved.</td></tr>
* </tbody>
* </table>
* @typedef Controller.Hardware-Keyboard
* @typedef {object} Controller.Hardware-Keyboard
* @todo <em>Currently, the mouse wheel in an ordinary mouse generates left/right wheel events instead of up/down.</em>
*/
controller::Input::NamedVector KeyboardMouseDevice::InputDevice::getAvailableInputs() const {

View file

@ -179,7 +179,7 @@ public:
* @function ModelCache.prefetch
* @param {string} url - URL of the resource to prefetch.
* @param {object} [extra=null]
* @returns {Resource}
* @returns {ResourceObject}
*/
/**jsdoc
@ -188,7 +188,7 @@ public:
* @param {string} url - URL of the resource to load.
* @param {string} [fallback=""] - Fallback URL if load of the desired URL fails.
* @param {} [extra=null]
* @returns {Resource}
* @returns {object}
*/

View file

@ -195,7 +195,7 @@ public:
* @function TextureCache.prefetch
* @param {string} url - URL of the resource to prefetch.
* @param {object} [extra=null]
* @returns {Resource}
* @returns {ResourceObject}
*/
/**jsdoc
@ -204,7 +204,7 @@ public:
* @param {string} url - URL of the resource to load.
* @param {string} [fallback=""] - Fallback URL if load of the desired URL fails.
* @param {} [extra=null]
* @returns {Resource}
* @returns {object}
*/
@ -261,7 +261,7 @@ protected:
* @param {string} url
* @param {number} type
* @param {number} [maxNumPixels=67108864]
* @returns {Resource}
* @returns {ResourceObject}
*/
// Overload ResourceCache::prefetch to allow specifying texture type for loads
Q_INVOKABLE ScriptableResource* prefetch(const QUrl& url, int type, int maxNumPixels = ABSOLUTE_MAX_TEXTURE_NUM_PIXELS);

View file

@ -138,7 +138,7 @@ public:
* </tr>
* </tbody>
* </table>
* @typedef location.LookupTrigger
* @typedef {number} location.LookupTrigger
*/
enum LookupTrigger {
UserInput,
@ -184,7 +184,7 @@ public slots:
/**jsdoc
* Go to a specified metaverse address.
* @function location.handleLookupString
* @param {string} address - The address to go to: a <code>"hifi:/"<code> address, an IP address (e.g.,
* @param {string} address - The address to go to: a <code>"hifi://"<code> address, an IP address (e.g.,
* <code>"127.0.0.1"</code> or <code>"localhost"</code>), a domain name, a named path on a domain (starts with
* <code>"/"</code>), a position or position and orientation, or a user (starts with <code>"@"</code>).
* @param {boolean} fromSuggestions=false - Set to <code>true</code> if the address is obtained from the "Goto" dialog.

View file

@ -137,7 +137,7 @@ public:
* </tr>
* </tbody>
* </table>
* @typedef Window.ConnectionRefusedReason
* @typedef {number} Window.ConnectionRefusedReason
*/
enum class ConnectionRefusedReason : uint8_t {
Unknown,

View file

@ -87,7 +87,7 @@ private:
class ScriptableResource : public QObject {
/**jsdoc
* @constructor Resource
* @class ResourceObject
*
* @hifi-interface
* @hifi-client-entity
@ -97,11 +97,6 @@ class ScriptableResource : public QObject {
* @property {string} url - URL of this resource.
* @property {Resource.State} state - Current loading state.
*/
/**jsdoc
* @namespace Resource
* @variation 0
* @property {Resource.State} State
*/
Q_OBJECT
Q_PROPERTY(QUrl url READ getURL)
Q_PROPERTY(int state READ getState NOTIFY stateChanged)
@ -109,8 +104,7 @@ class ScriptableResource : public QObject {
public:
/**jsdoc
* @name Resource.State
* @static
* @typedef {object} Resource.State
* @property {number} QUEUED - The resource is queued up, waiting to be loaded.
* @property {number} LOADING - The resource is downloading.
* @property {number} LOADED - The resource has finished downloaded by is not complete.
@ -131,7 +125,7 @@ public:
/**jsdoc
* Release this resource.
* @function Resource#release
* @function ResourceObject#release
*/
Q_INVOKABLE void release();
@ -146,7 +140,7 @@ signals:
/**jsdoc
* Triggered when download progress for this resource has changed.
* @function Resource#progressChanged
* @function ResourceObject#progressChanged
* @param {number} bytesReceived - Byytes downloaded so far.
* @param {number} bytesTotal - Total number of bytes in the resource.
* @returns {Signal}
@ -155,7 +149,7 @@ signals:
/**jsdoc
* Triggered when resource loading state has changed.
* @function Resource#stateChanged
* @function ResourceObject#stateChanged
* @param {Resource.State} state - New state.
* @returns {Signal}
*/
@ -262,7 +256,7 @@ protected slots:
* @function ResourceCache.prefetch
* @param {string} url - URL of the resource to prefetch.
* @param {object} [extra=null]
* @returns {Resource}
* @returns {ResourceObject}
*/
// Prefetches a resource to be held by the QScriptEngine.
// Left as a protected member so subclasses can overload prefetch
@ -275,8 +269,9 @@ protected slots:
* @param {string} url - URL of the resource to load.
* @param {string} [fallback=""] - Fallback URL if load of the desired URL fails.
* @param {} [extra=null]
* @returns {Resource}
* @returns {object}
*/
// FIXME: The return type is not recognized by JavaScript.
/// Loads a resource from the specified URL and returns it.
/// If the caller is on a different thread than the ResourceCache,
/// returns an empty smart pointer and loads its asynchronously.

View file

@ -33,7 +33,7 @@ PacketVersion versionForPacketType(PacketType packetType) {
case PacketType::EntityEdit:
case PacketType::EntityData:
case PacketType::EntityPhysics:
return static_cast<PacketVersion>(EntityVersion::CloneableData);
return static_cast<PacketVersion>(EntityVersion::CollisionMask16Bytes);
case PacketType::EntityQuery:
return static_cast<PacketVersion>(EntityQueryPacketVersion::ConicalFrustums);
case PacketType::AvatarIdentity:

View file

@ -235,7 +235,8 @@ enum class EntityVersion : PacketVersion {
MaterialEntities,
ShadowControl,
MaterialData,
CloneableData
CloneableData,
CollisionMask16Bytes
};
enum class EntityScriptCallMethodVersion : PacketVersion {

View file

@ -109,7 +109,7 @@ void CharacterController::setDynamicsWorld(btDynamicsWorld* world) {
}
_dynamicsWorld = nullptr;
}
int16_t collisionGroup = computeCollisionGroup();
int32_t collisionGroup = computeCollisionGroup();
if (_rigidBody) {
updateMassProperties();
}
@ -325,7 +325,7 @@ void CharacterController::playerStep(btCollisionWorld* collisionWorld, btScalar
_ghost.setWorldTransform(_rigidBody->getWorldTransform());
}
void CharacterController::jump() {
void CharacterController::jump(const btVector3& dir) {
_pendingFlags |= PENDING_FLAG_JUMP;
}
@ -352,7 +352,7 @@ static const char* stateToStr(CharacterController::State state) {
#endif // #ifdef DEBUG_STATE_CHANGE
void CharacterController::updateCurrentGravity() {
int16_t collisionGroup = computeCollisionGroup();
int32_t collisionGroup = computeCollisionGroup();
if (_state == State::Hover || collisionGroup == BULLET_COLLISION_GROUP_COLLISIONLESS) {
_currentGravity = 0.0f;
} else {
@ -433,7 +433,7 @@ void CharacterController::setCollisionless(bool collisionless) {
}
}
int16_t CharacterController::computeCollisionGroup() const {
int32_t CharacterController::computeCollisionGroup() const {
if (_collisionless) {
return _collisionlessAllowed ? BULLET_COLLISION_GROUP_COLLISIONLESS : BULLET_COLLISION_GROUP_MY_AVATAR;
} else {
@ -446,7 +446,7 @@ void CharacterController::handleChangedCollisionGroup() {
// ATM the easiest way to update collision groups is to remove/re-add the RigidBody
if (_dynamicsWorld) {
_dynamicsWorld->removeRigidBody(_rigidBody);
int16_t collisionGroup = computeCollisionGroup();
int32_t collisionGroup = computeCollisionGroup();
_dynamicsWorld->addRigidBody(_rigidBody, collisionGroup, BULLET_COLLISION_MASK_MY_AVATAR);
}
_pendingFlags &= ~PENDING_FLAG_UPDATE_COLLISION_GROUP;
@ -538,7 +538,7 @@ void CharacterController::applyMotor(int index, btScalar dt, btVector3& worldVel
btScalar angle = motor.rotation.getAngle();
btVector3 velocity = worldVelocity.rotate(axis, -angle);
int16_t collisionGroup = computeCollisionGroup();
int32_t collisionGroup = computeCollisionGroup();
if (collisionGroup == BULLET_COLLISION_GROUP_COLLISIONLESS ||
_state == State::Hover || motor.hTimescale == motor.vTimescale) {
// modify velocity
@ -679,7 +679,7 @@ void CharacterController::updateState() {
btVector3 rayStart = _position;
btScalar rayLength = _radius;
int16_t collisionGroup = computeCollisionGroup();
int32_t collisionGroup = computeCollisionGroup();
if (collisionGroup == BULLET_COLLISION_GROUP_MY_AVATAR) {
rayLength += _scaleFactor * DEFAULT_AVATAR_FALL_HEIGHT;
} else {

View file

@ -70,7 +70,7 @@ public:
virtual void preStep(btCollisionWorld *collisionWorld) override;
virtual void playerStep(btCollisionWorld *collisionWorld, btScalar dt) override;
virtual bool canJump() const override { assert(false); return false; } // never call this
virtual void jump() override;
virtual void jump(const btVector3& dir = btVector3(0.0f, 0.0f, 0.0f)) override;
virtual bool onGround() const override;
void clearMotors();
@ -120,7 +120,7 @@ public:
bool isStuck() const { return _isStuck; }
void setCollisionless(bool collisionless);
int16_t computeCollisionGroup() const;
int32_t computeCollisionGroup() const;
void handleChangedCollisionGroup();
bool getRigidBodyLocation(glm::vec3& avatarRigidBodyPosition, glm::quat& avatarRigidBodyRotation);

View file

@ -29,13 +29,13 @@ CharacterGhostObject::~CharacterGhostObject() {
}
}
void CharacterGhostObject::setCollisionGroupAndMask(int16_t group, int16_t mask) {
void CharacterGhostObject::setCollisionGroupAndMask(int32_t group, int32_t mask) {
_collisionFilterGroup = group;
_collisionFilterMask = mask;
// TODO: if this probe is in the world reset ghostObject overlap cache
}
void CharacterGhostObject::getCollisionGroupAndMask(int16_t& group, int16_t& mask) const {
void CharacterGhostObject::getCollisionGroupAndMask(int32_t& group, int32_t& mask) const {
group = _collisionFilterGroup;
mask = _collisionFilterMask;
}

View file

@ -28,8 +28,8 @@ public:
CharacterGhostObject() { }
~CharacterGhostObject();
void setCollisionGroupAndMask(int16_t group, int16_t mask);
void getCollisionGroupAndMask(int16_t& group, int16_t& mask) const;
void setCollisionGroupAndMask(int32_t group, int32_t mask);
void getCollisionGroupAndMask(int32_t& group, int32_t& mask) const;
void setRadiusAndHalfHeight(btScalar radius, btScalar halfHeight);
void setUpDirection(const btVector3& up);
@ -54,8 +54,8 @@ protected:
btScalar _radius { 0.0f };
btConvexHullShape* _characterShape { nullptr }; // input, shape of character
CharacterGhostShape* _ghostShape { nullptr }; // internal, shape whose Aabb is used for overlap cache
int16_t _collisionFilterGroup { 0 };
int16_t _collisionFilterMask { 0 };
int32_t _collisionFilterGroup { 0 };
int32_t _collisionFilterMask { 0 };
bool _inWorld { false }; // internal, was added to world
};

View file

@ -252,11 +252,9 @@ void EntityMotionState::getWorldTransform(btTransform& worldTrans) const {
uint32_t thisStep = ObjectMotionState::getWorldSimulationStep();
float dt = (thisStep - _lastKinematicStep) * PHYSICS_ENGINE_FIXED_SUBSTEP;
_lastKinematicStep = thisStep;
_entity->stepKinematicMotion(dt);
// bypass const-ness so we can remember the step
const_cast<EntityMotionState*>(this)->_lastKinematicStep = thisStep;
// and set the acceleration-matches-gravity count high so that if we send an update
// it will use the correct acceleration for remote simulations
_accelerationNearlyGravityCount = (uint8_t)(-1);
@ -779,7 +777,7 @@ QString EntityMotionState::getName() const {
}
// virtual
void EntityMotionState::computeCollisionGroupAndMask(int16_t& group, int16_t& mask) const {
void EntityMotionState::computeCollisionGroupAndMask(int32_t& group, int32_t& mask) const {
_entity->computeCollisionGroupAndFinalMask(group, mask);
}

View file

@ -84,7 +84,7 @@ public:
virtual QString getName() const override;
virtual void computeCollisionGroupAndMask(int16_t& group, int16_t& mask) const override;
virtual void computeCollisionGroupAndMask(int32_t& group, int32_t& mask) const override;
bool shouldSendBid();
bool isLocallyOwned() const override;

View file

@ -154,7 +154,7 @@ public:
virtual QString getName() const { return ""; }
virtual void computeCollisionGroupAndMask(int16_t& group, int16_t& mask) const = 0;
virtual void computeCollisionGroupAndMask(int32_t& group, int32_t& mask) const = 0;
bool isActive() const { return _body ? _body->isActive() : false; }
@ -184,7 +184,7 @@ protected:
btRigidBody* _body { nullptr };
float _density { 1.0f };
uint32_t _lastKinematicStep;
mutable uint32_t _lastKinematicStep;
bool _hasInternalKinematicChanges { false };
};

View file

@ -71,8 +71,8 @@ void PhysicsEngine::init() {
}
}
uint32_t PhysicsEngine::getNumSubsteps() {
return _numSubsteps;
uint32_t PhysicsEngine::getNumSubsteps() const {
return _dynamicsWorld->getNumSubsteps();
}
// private
@ -148,7 +148,7 @@ void PhysicsEngine::addObjectToDynamicsWorld(ObjectMotionState* motionState) {
body->setFlags(BT_DISABLE_WORLD_GRAVITY);
motionState->updateBodyMaterialProperties();
int16_t group, mask;
int32_t group, mask;
motionState->computeCollisionGroupAndMask(group, mask);
_dynamicsWorld->addRigidBody(body, group, mask);
@ -329,13 +329,9 @@ void PhysicsEngine::stepSimulation() {
PHYSICS_ENGINE_FIXED_SUBSTEP, onSubStep);
if (numSubsteps > 0) {
BT_PROFILE("postSimulation");
_numSubsteps += (uint32_t)numSubsteps;
ObjectMotionState::setWorldSimulationStep(_numSubsteps);
if (_myAvatarController) {
_myAvatarController->postSimulation();
}
_hasOutgoingChanges = true;
}

View file

@ -52,7 +52,7 @@ public:
~PhysicsEngine();
void init();
uint32_t getNumSubsteps();
uint32_t getNumSubsteps() const;
void removeObjects(const VectorOfMotionStates& objects);
void removeSetOfObjects(const SetOfMotionStates& objects); // only called during teardown
@ -135,7 +135,6 @@ private:
CharacterController* _myAvatarController;
uint32_t _numContactFrames = 0;
uint32_t _numSubsteps;
bool _dumpNextStats { false };
bool _saveNextStats { false };

View file

@ -59,14 +59,11 @@ int ThreadSafeDynamicsWorld::stepSimulationWithSubstepCallback(btScalar timeStep
}
}
/*//process some debugging flags
if (getDebugDrawer()) {
btIDebugDraw* debugDrawer = getDebugDrawer();
gDisableDeactivation = (debugDrawer->getDebugMode() & btIDebugDraw::DBG_NoDeactivation) != 0;
}*/
if (subSteps) {
//clamp the number of substeps, to prevent simulation grinding spiralling down to a halt
int clampedSimulationSteps = (subSteps > maxSubSteps)? maxSubSteps : subSteps;
_numSubsteps += clampedSimulationSteps;
ObjectMotionState::setWorldSimulationStep(_numSubsteps);
saveKinematicState(fixedTimeStep*clampedSimulationSteps);
@ -98,28 +95,24 @@ int ThreadSafeDynamicsWorld::stepSimulationWithSubstepCallback(btScalar timeStep
// call this instead of non-virtual btDiscreteDynamicsWorld::synchronizeSingleMotionState()
void ThreadSafeDynamicsWorld::synchronizeMotionState(btRigidBody* body) {
btAssert(body);
if (body->getMotionState() && !body->isStaticObject()) {
//we need to call the update at least once, even for sleeping objects
//otherwise the 'graphics' transform never updates properly
///@todo: add 'dirty' flag
//if (body->getActivationState() != ISLAND_SLEEPING)
{
if (body->isKinematicObject()) {
ObjectMotionState* objectMotionState = static_cast<ObjectMotionState*>(body->getMotionState());
if (objectMotionState->hasInternalKinematicChanges()) {
objectMotionState->clearInternalKinematicChanges();
body->getMotionState()->setWorldTransform(body->getWorldTransform());
}
return;
}
btTransform interpolatedTransform;
btTransformUtil::integrateTransform(body->getInterpolationWorldTransform(),
body->getInterpolationLinearVelocity(),body->getInterpolationAngularVelocity(),
(m_latencyMotionStateInterpolation && m_fixedTimeStep) ? m_localTime - m_fixedTimeStep : m_localTime*body->getHitFraction(),
interpolatedTransform);
body->getMotionState()->setWorldTransform(interpolatedTransform);
btAssert(body->getMotionState());
if (body->isKinematicObject()) {
ObjectMotionState* objectMotionState = static_cast<ObjectMotionState*>(body->getMotionState());
if (objectMotionState->hasInternalKinematicChanges()) {
// this is a special case where the kinematic motion has been updated by an Action
// so we supply the body's current transform to the MotionState
objectMotionState->clearInternalKinematicChanges();
body->getMotionState()->setWorldTransform(body->getWorldTransform());
}
return;
}
btTransform interpolatedTransform;
btTransformUtil::integrateTransform(body->getInterpolationWorldTransform(),
body->getInterpolationLinearVelocity(),body->getInterpolationAngularVelocity(),
(m_latencyMotionStateInterpolation && m_fixedTimeStep) ? m_localTime - m_fixedTimeStep : m_localTime*body->getHitFraction(),
interpolatedTransform);
body->getMotionState()->setWorldTransform(interpolatedTransform);
}
void ThreadSafeDynamicsWorld::synchronizeMotionStates() {
@ -164,24 +157,12 @@ void ThreadSafeDynamicsWorld::synchronizeMotionStates() {
}
void ThreadSafeDynamicsWorld::saveKinematicState(btScalar timeStep) {
///would like to iterate over m_nonStaticRigidBodies, but unfortunately old API allows
///to switch status _after_ adding kinematic objects to the world
///fix it for Bullet 3.x release
DETAILED_PROFILE_RANGE(simulation_physics, "saveKinematicState");
BT_PROFILE("saveKinematicState");
for (int i=0;i<m_collisionObjects.size();i++)
{
btCollisionObject* colObj = m_collisionObjects[i];
btRigidBody* body = btRigidBody::upcast(colObj);
if (body && body->getActivationState() != ISLAND_SLEEPING)
{
if (body->isKinematicObject())
{
//to calculate velocities next frame
body->saveKinematicState(timeStep);
}
for (int i=0;i<m_nonStaticRigidBodies.size();i++) {
btRigidBody* body = m_nonStaticRigidBodies[i];
if (body && body->isKinematicObject() && body->getActivationState() != ISLAND_SLEEPING) {
body->saveKinematicState(timeStep);
}
}
}

View file

@ -37,6 +37,7 @@ public:
btConstraintSolver* constraintSolver,
btCollisionConfiguration* collisionConfiguration);
int getNumSubsteps() const { return _numSubsteps; }
int stepSimulationWithSubstepCallback(btScalar timeStep, int maxSubSteps = 1,
btScalar fixedTimeStep = btScalar(1.)/btScalar(60.),
SubStepCallback onSubStep = []() { });
@ -61,6 +62,7 @@ private:
VectorOfMotionStates _deactivatedStates;
SetOfMotionStates _activeStates;
SetOfMotionStates _lastActiveStates;
int _numSubsteps { 0 };
};
#endif // hifi_ThreadSafeDynamicsWorld_h

View file

@ -181,7 +181,7 @@ class DebugAmbientOcclusionConfig : public render::Job::Config {
Q_PROPERTY(bool showCursorPixel MEMBER showCursorPixel NOTIFY dirty)
Q_PROPERTY(glm::vec2 debugCursorTexcoord MEMBER debugCursorTexcoord NOTIFY dirty)
public:
DebugAmbientOcclusionConfig() : render::Job::Config(true) {}
DebugAmbientOcclusionConfig() : render::Job::Config(false) {}
bool showCursorPixel{ false };
glm::vec2 debugCursorTexcoord{ 0.5f, 0.5f };

View file

@ -122,6 +122,9 @@ static const gpu::Element TEXCOORD4_ELEMENT { gpu::VEC4, gpu::FLOAT, gpu::XYZW }
static gpu::Stream::FormatPointer SOLID_STREAM_FORMAT;
static gpu::Stream::FormatPointer INSTANCED_SOLID_STREAM_FORMAT;
static gpu::Stream::FormatPointer INSTANCED_SOLID_FADE_STREAM_FORMAT;
static gpu::Stream::FormatPointer WIRE_STREAM_FORMAT;
static gpu::Stream::FormatPointer INSTANCED_WIRE_STREAM_FORMAT;
static gpu::Stream::FormatPointer INSTANCED_WIRE_FADE_STREAM_FORMAT;
static const uint SHAPE_VERTEX_STRIDE = sizeof(GeometryCache::ShapeVertex); // position, normal, texcoords, tangent
static const uint SHAPE_NORMALS_OFFSET = offsetof(GeometryCache::ShapeVertex, normal);
@ -690,6 +693,38 @@ gpu::Stream::FormatPointer& getInstancedSolidFadeStreamFormat() {
return INSTANCED_SOLID_FADE_STREAM_FORMAT;
}
gpu::Stream::FormatPointer& getWireStreamFormat() {
if (!WIRE_STREAM_FORMAT) {
WIRE_STREAM_FORMAT = std::make_shared<gpu::Stream::Format>(); // 1 for everyone
WIRE_STREAM_FORMAT->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, POSITION_ELEMENT);
WIRE_STREAM_FORMAT->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, NORMAL_ELEMENT);
}
return WIRE_STREAM_FORMAT;
}
gpu::Stream::FormatPointer& getInstancedWireStreamFormat() {
if (!INSTANCED_WIRE_STREAM_FORMAT) {
INSTANCED_WIRE_STREAM_FORMAT = std::make_shared<gpu::Stream::Format>(); // 1 for everyone
INSTANCED_WIRE_STREAM_FORMAT->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, POSITION_ELEMENT);
INSTANCED_WIRE_STREAM_FORMAT->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, NORMAL_ELEMENT);
INSTANCED_WIRE_STREAM_FORMAT->setAttribute(gpu::Stream::COLOR, gpu::Stream::COLOR, COLOR_ELEMENT, 0, gpu::Stream::PER_INSTANCE);
}
return INSTANCED_WIRE_STREAM_FORMAT;
}
gpu::Stream::FormatPointer& getInstancedWireFadeStreamFormat() {
if (!INSTANCED_WIRE_FADE_STREAM_FORMAT) {
INSTANCED_WIRE_FADE_STREAM_FORMAT = std::make_shared<gpu::Stream::Format>(); // 1 for everyone
INSTANCED_WIRE_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, POSITION_ELEMENT);
INSTANCED_WIRE_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, NORMAL_ELEMENT);
INSTANCED_WIRE_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::COLOR, gpu::Stream::COLOR, COLOR_ELEMENT, 0, gpu::Stream::PER_INSTANCE);
INSTANCED_WIRE_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::TEXCOORD2, gpu::Stream::TEXCOORD2, TEXCOORD4_ELEMENT, 0, gpu::Stream::PER_INSTANCE);
INSTANCED_WIRE_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::TEXCOORD3, gpu::Stream::TEXCOORD3, TEXCOORD4_ELEMENT, 0, gpu::Stream::PER_INSTANCE);
INSTANCED_WIRE_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::TEXCOORD4, gpu::Stream::TEXCOORD4, TEXCOORD4_ELEMENT, 0, gpu::Stream::PER_INSTANCE);
}
return INSTANCED_WIRE_FADE_STREAM_FORMAT;
}
QHash<SimpleProgramKey, gpu::PipelinePointer> GeometryCache::_simplePrograms;
gpu::ShaderPointer GeometryCache::_simpleShader;
@ -827,7 +862,7 @@ void GeometryCache::renderShape(gpu::Batch& batch, Shape shape) {
}
void GeometryCache::renderWireShape(gpu::Batch& batch, Shape shape) {
batch.setInputFormat(getSolidStreamFormat());
batch.setInputFormat(getWireStreamFormat());
_shapes[shape].drawWire(batch);
}
@ -839,7 +874,7 @@ void GeometryCache::renderShape(gpu::Batch& batch, Shape shape, const glm::vec4&
}
void GeometryCache::renderWireShape(gpu::Batch& batch, Shape shape, const glm::vec4& color) {
batch.setInputFormat(getSolidStreamFormat());
batch.setInputFormat(getWireStreamFormat());
// Color must be set after input format
batch._glColor4f(color.r, color.g, color.b, color.a);
_shapes[shape].drawWire(batch);
@ -857,7 +892,7 @@ void GeometryCache::renderShapeInstances(gpu::Batch& batch, Shape shape, size_t
}
void GeometryCache::renderWireShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer) {
batch.setInputFormat(getInstancedSolidStreamFormat());
batch.setInputFormat(getInstancedWireStreamFormat());
setupBatchInstance(batch, colorBuffer);
_shapes[shape].drawWireInstances(batch, count);
}
@ -883,7 +918,7 @@ void GeometryCache::renderFadeShapeInstances(gpu::Batch& batch, Shape shape, siz
void GeometryCache::renderWireFadeShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer,
gpu::BufferPointer& fadeBuffer1, gpu::BufferPointer& fadeBuffer2, gpu::BufferPointer& fadeBuffer3) {
batch.setInputFormat(getInstancedSolidFadeStreamFormat());
batch.setInputFormat(getInstancedWireFadeStreamFormat());
setupBatchFadeInstance(batch, colorBuffer, fadeBuffer1, fadeBuffer2, fadeBuffer3);
_shapes[shape].drawWireInstances(batch, count);
}

View file

@ -195,7 +195,7 @@ class DebugLightClustersConfig : public render::Job::Config {
Q_PROPERTY(bool doDrawClusterFromDepth MEMBER doDrawClusterFromDepth NOTIFY dirty)
Q_PROPERTY(bool doDrawContent MEMBER doDrawContent NOTIFY dirty)
public:
DebugLightClustersConfig() : render::Job::Config(true){}
DebugLightClustersConfig() : render::Job::Config(false){}
bool doDrawGrid{ false };

View file

@ -149,7 +149,7 @@ class DebugSubsurfaceScatteringConfig : public render::Job::Config {
Q_PROPERTY(bool showCursorPixel MEMBER showCursorPixel NOTIFY dirty)
Q_PROPERTY(glm::vec2 debugCursorTexcoord MEMBER debugCursorTexcoord NOTIFY dirty)
public:
DebugSubsurfaceScatteringConfig() : render::Job::Config(true) {}
DebugSubsurfaceScatteringConfig() : render::Job::Config(false) {}
bool showProfile{ false };
bool showLUT{ false };

View file

@ -36,12 +36,11 @@ public:
}
};
Engine::Engine() : Task(EngineTask::JobModel::create("Engine")),
_renderContext(std::make_shared<RenderContext>())
RenderEngine::RenderEngine() : Engine(EngineTask::JobModel::create("Engine"), std::make_shared<RenderContext>())
{
}
void Engine::load() {
void RenderEngine::load() {
auto config = getConfiguration();
const QString configFile= "config/render.json";

View file

@ -25,7 +25,7 @@ namespace render {
class RenderContext : public task::JobContext {
public:
RenderContext() : task::JobContext(trace_render()) {}
RenderContext() : task::JobContext() {}
virtual ~RenderContext() {}
RenderArgs* args;
@ -33,7 +33,9 @@ namespace render {
};
using RenderContextPointer = std::shared_ptr<RenderContext>;
Task_DeclareTypeAliases(RenderContext)
Task_DeclareCategoryTimeProfilerClass(RenderTimeProfiler, trace_render);
Task_DeclareTypeAliases(RenderContext, RenderTimeProfiler)
// Versions of the COnfig integrating a gpu & batch timer
class GPUJobConfig : public JobConfig {
@ -57,10 +59,10 @@ namespace render {
class GPUTaskConfig : public TaskConfig {
Q_OBJECT
Q_PROPERTY(double gpuRunTime READ getGPURunTime)
Q_PROPERTY(double batchRunTime READ getBatchRunTime)
Q_PROPERTY(double gpuRunTime READ getGPURunTime)
Q_PROPERTY(double batchRunTime READ getBatchRunTime)
double _msGPURunTime { 0.0 };
double _msGPURunTime { 0.0 };
double _msBatchRunTime { 0.0 };
public:
@ -80,32 +82,25 @@ namespace render {
// The render engine holds all render tasks, and is itself a render task.
// State flows through tasks to jobs via the render and scene contexts -
// the engine should not be known from its jobs.
class Engine : public Task {
class RenderEngine : public Engine {
public:
Engine();
~Engine() = default;
RenderEngine();
~RenderEngine() = default;
// Load any persisted settings, and set up the presets
// This should be run after adding all jobs, and before building ui
void load();
// Register the scene
void registerScene(const ScenePointer& scene) { _renderContext->_scene = scene; }
void registerScene(const ScenePointer& scene) { _context->_scene = scene; }
// acces the RenderContext
RenderContextPointer getRenderContext() const { return _renderContext; }
// Render a frame
// Must have a scene registered and a context set
void run() { assert(_renderContext); Task::run(_renderContext); }
RenderContextPointer getRenderContext() const { return _context; }
protected:
RenderContextPointer _renderContext;
void run(const RenderContextPointer& context) override { assert(_renderContext); Task::run(_renderContext); }
};
using EnginePointer = std::shared_ptr<Engine>;
using EnginePointer = std::shared_ptr<RenderEngine>;
}

View file

@ -122,6 +122,7 @@ public:
Builder& withDynamic() { _flags.set(DYNAMIC); return (*this); }
Builder& withDeformed() { _flags.set(DEFORMED); return (*this); }
Builder& withInvisible() { _flags.set(INVISIBLE); return (*this); }
Builder& withVisible() { _flags.reset(INVISIBLE); return (*this); }
Builder& withShadowCaster() { _flags.set(SHADOW_CASTER); return (*this); }
Builder& withLayered() { _flags.set(LAYERED); return (*this); }
Builder& withMetaCullGroup() { _flags.set(META_CULL_GROUP); return (*this); }

View file

@ -21,7 +21,7 @@
namespace render {
class Engine;
class RenderEngine;
class Scene;
// Transaction is the mechanism to make any change to the scene.
@ -236,7 +236,7 @@ protected:
StageMap _stages;
friend class Engine;
friend class RenderEngine;
};
typedef std::shared_ptr<Scene> ScenePointer;

View file

@ -121,7 +121,7 @@ public:
/**jsdoc
* A set of properties that can be passed to {@link Assets.getAsset}.
* @typedef {Object} Assets.GetOptions
* @typedef {object} Assets.GetOptions
* @property {string} [url] an "atp:" style URL, hash, or relative mapped path to fetch
* @property {string} [responseType=text] the desired reponse type (text | arraybuffer | json)
* @property {boolean} [decompress=false] whether to attempt gunzip decompression on the fetched data
@ -137,7 +137,7 @@ public:
/**jsdoc
* Result value returned by {@link Assets.getAsset}.
* @typedef {Object} Assets~getAssetResult
* @typedef {object} Assets~getAssetResult
* @property {string} [url] the resolved "atp:" style URL for the fetched asset
* @property {string} [hash] the resolved hash for the fetched asset
* @property {string|ArrayBuffer|Object} [response] response data (possibly converted per .responseType value)
@ -159,7 +159,7 @@ public:
/**jsdoc
* A set of properties that can be passed to {@link Assets.putAsset}.
* @typedef {Object} Assets.PutOptions
* @typedef {object} Assets.PutOptions
* @property {ArrayBuffer|string} [data] byte buffer or string value representing the new asset's content
* @property {string} [path=null] ATP path mapping to automatically create (upon successful upload to hash)
* @property {boolean} [compress=false] whether to gzip compress data before uploading
@ -174,7 +174,7 @@ public:
/**jsdoc
* Result value returned by {@link Assets.putAsset}.
* @typedef {Object} Assets~putAssetResult
* @typedef {object} Assets~putAssetResult
* @property {string} [url] the resolved "atp:" style URL for the uploaded asset (based on .path if specified, otherwise on the resulting ATP hash)
* @property {string} [path] the uploaded asset's resulting ATP path (or undefined if no path mapping was assigned)
* @property {string} [hash] the uploaded asset's resulting ATP hash

View file

@ -43,7 +43,7 @@
* @hifi-server-entity
* @hifi-assignment-client
*
* @property IDENTITY {Quat} <code>{ x: 0, y: 0, z: 0, w: 1 }</code> : The identity rotation, i.e., no rotation.
* @property {Quat} IDENTITY - <code>{ x: 0, y: 0, z: 0, w: 1 }</code> : The identity rotation, i.e., no rotation.
* <em>Read-only.</em>
* @example <caption>Print the <code>IDENTITY</code> value.</caption>
* print(JSON.stringify(Quat.IDENTITY)); // { x: 0, y: 0, z: 0, w: 1 }

View file

@ -21,7 +21,7 @@
namespace SceneScripting {
/**jsdoc
* @typedef Scene.Stage.Location
* @typedef {object} Scene.Stage.Location
* @property {number} longitude
* @property {number} latitude
* @property {number} altitude
@ -49,7 +49,7 @@ namespace SceneScripting {
using LocationPointer = std::unique_ptr<Location>;
/**jsdoc
* @typedef Scene.Stage.Time
* @typedef {object} Scene.Stage.Time
* @property {number} hour
* @property {number} day
*/
@ -73,7 +73,7 @@ namespace SceneScripting {
using TimePointer = std::unique_ptr<Time>;
/**jsdoc
* @typedef Scene.Stage.KeyLight
* @typedef {object} Scene.Stage.KeyLight
* @property {Vec3} color
* @property {number} intensity
* @property {number} ambientIntensity

View file

@ -558,6 +558,16 @@ static void scriptableResourceFromScriptValue(const QScriptValue& value, Scripta
resource = static_cast<ScriptableResourceRawPtr>(value.toQObject());
}
/**jsdoc
* @namespace Resource
*
* @hifi-interface
* @hifi-client-entity
* @hifi-server-entity
* @hifi-assignment-client
*
* @property {Resource.State} State
*/
static QScriptValue createScriptableResourcePrototype(ScriptEnginePointer engine) {
auto prototype = engine->newObject();

View file

@ -30,7 +30,7 @@
* @hifi-server-entity
* @hifi-assignment-client
*
* @property NULL {Uuid} The null UUID, <code>{00000000-0000-0000-0000-000000000000}</code>.
* @property {Uuid} NULL - The null UUID, <code>{00000000-0000-0000-0000-000000000000}</code>.
*/
/// Scriptable interface for a UUID helper class object. Used exclusively in the JavaScript API

View file

@ -42,8 +42,7 @@
/**jsdoc
* The Vec3 API facilities for generating and manipulating 3-dimensional vectors. High Fidelity uses a right-handed
* Cartesian coordinate system where the y-axis is the "up" and the negative z-axis is the "front" direction.
* <img alt="High Fidelity coordinate system"
* src="https://docs.highfidelity.com/user/pages/06.api-reference/43.vec3/opengl-coord-system.jpg" />
* <img alt="High Fidelity coordinate system" src="https://docs.highfidelity.com/images/opengl-coord-system.jpg" />
*
* @namespace Vec3
* @variation 0

View file

@ -34,13 +34,13 @@ enum CollisionFilterGroups {
*
*/
const int16_t BULLET_COLLISION_GROUP_STATIC = 1 << 0;
const int16_t BULLET_COLLISION_GROUP_DYNAMIC = 1 << 1;
const int16_t BULLET_COLLISION_GROUP_KINEMATIC = 1 << 2;
const int16_t BULLET_COLLISION_GROUP_MY_AVATAR = 1 << 3;
const int16_t BULLET_COLLISION_GROUP_OTHER_AVATAR = 1 << 4;
const int32_t BULLET_COLLISION_GROUP_STATIC = 1 << 0;
const int32_t BULLET_COLLISION_GROUP_DYNAMIC = 1 << 1;
const int32_t BULLET_COLLISION_GROUP_KINEMATIC = 1 << 2;
const int32_t BULLET_COLLISION_GROUP_MY_AVATAR = 1 << 3;
const int32_t BULLET_COLLISION_GROUP_OTHER_AVATAR = 1 << 4;
// ...
const int16_t BULLET_COLLISION_GROUP_COLLISIONLESS = 1 << 14;
const int32_t BULLET_COLLISION_GROUP_COLLISIONLESS = 1 << 31;
/* Note: In order for objectA to collide with objectB at the filter stage
@ -48,21 +48,21 @@ const int16_t BULLET_COLLISION_GROUP_COLLISIONLESS = 1 << 14;
*/
// the default collision mask is: collides with everything except collisionless
const int16_t BULLET_COLLISION_MASK_DEFAULT = ~ BULLET_COLLISION_GROUP_COLLISIONLESS;
const int32_t BULLET_COLLISION_MASK_DEFAULT = ~ BULLET_COLLISION_GROUP_COLLISIONLESS;
// STATIC does not collide with itself (as optimization of physics simulation)
const int16_t BULLET_COLLISION_MASK_STATIC = ~ (BULLET_COLLISION_GROUP_COLLISIONLESS | BULLET_COLLISION_GROUP_KINEMATIC | BULLET_COLLISION_GROUP_STATIC);
const int32_t BULLET_COLLISION_MASK_STATIC = ~ (BULLET_COLLISION_GROUP_COLLISIONLESS | BULLET_COLLISION_GROUP_KINEMATIC | BULLET_COLLISION_GROUP_STATIC);
const int16_t BULLET_COLLISION_MASK_DYNAMIC = BULLET_COLLISION_MASK_DEFAULT;
const int16_t BULLET_COLLISION_MASK_KINEMATIC = BULLET_COLLISION_MASK_STATIC;
const int32_t BULLET_COLLISION_MASK_DYNAMIC = BULLET_COLLISION_MASK_DEFAULT;
const int32_t BULLET_COLLISION_MASK_KINEMATIC = BULLET_COLLISION_MASK_STATIC;
// MY_AVATAR does not collide with itself
const int16_t BULLET_COLLISION_MASK_MY_AVATAR = ~(BULLET_COLLISION_GROUP_COLLISIONLESS | BULLET_COLLISION_GROUP_MY_AVATAR);
const int32_t BULLET_COLLISION_MASK_MY_AVATAR = ~(BULLET_COLLISION_GROUP_COLLISIONLESS | BULLET_COLLISION_GROUP_MY_AVATAR);
const int16_t BULLET_COLLISION_MASK_OTHER_AVATAR = BULLET_COLLISION_MASK_DEFAULT;
const int32_t BULLET_COLLISION_MASK_OTHER_AVATAR = BULLET_COLLISION_MASK_DEFAULT;
// COLLISIONLESS gets an empty mask.
const int16_t BULLET_COLLISION_MASK_COLLISIONLESS = 0;
const int32_t BULLET_COLLISION_MASK_COLLISIONLESS = 0;
/**jsdoc
* <p>An entity may collide with the following types of items:</p>
@ -72,35 +72,35 @@ const int16_t BULLET_COLLISION_MASK_COLLISIONLESS = 0;
* </thead>
* <tbody>
* <tr><td><code>1</code></td><td>Static entities &mdash; non-dynamic entities with no velocity.</td></tr>
* <tr><td><code>2</code></td><td>Dynamic entities &mdash; entities that have their <code>dynamic</code> property set to
* <tr><td><code>2</code></td><td>Dynamic entities &mdash; entities that have their <code>dynamic</code> property set to
* <code>true</code>.</td></tr>
* <tr><td><code>4</code></td><td>Kinematic entities &mdash; non-dynamic entities with velocity.</td></tr>
* <tr><td><code>8</code></td><td>My avatar.</td></tr>
* <tr><td><code>16</code></td><td>Other avatars.</td></tr>
* </tbody>
* </table>
* <p>The values for the collision types that are enabled are added together to give the CollisionMask value. For example, a
* <p>The values for the collision types that are enabled are added together to give the CollisionMask value. For example, a
* value of <code>31</code> means that an entity will collide with all item types.</p>
* @typedef {number} Entities.CollisionMask
*/
// The USER collision groups are exposed to script and can be used to generate per-object collision masks.
// They are not necessarily the same as the BULLET_COLLISION_GROUPS, but we start them off with matching numbers.
const uint8_t USER_COLLISION_GROUP_STATIC = 1 << 0;
const uint8_t USER_COLLISION_GROUP_DYNAMIC = 1 << 1;
const uint8_t USER_COLLISION_GROUP_KINEMATIC = 1 << 2;
const uint8_t USER_COLLISION_GROUP_MY_AVATAR = 1 << 3;
const uint8_t USER_COLLISION_GROUP_OTHER_AVATAR = 1 << 4;
const uint16_t USER_COLLISION_GROUP_STATIC = 1 << 0;
const uint16_t USER_COLLISION_GROUP_DYNAMIC = 1 << 1;
const uint16_t USER_COLLISION_GROUP_KINEMATIC = 1 << 2;
const uint16_t USER_COLLISION_GROUP_MY_AVATAR = 1 << 3;
const uint16_t USER_COLLISION_GROUP_OTHER_AVATAR = 1 << 4;
const uint8_t ENTITY_COLLISION_MASK_DEFAULT =
const uint16_t ENTITY_COLLISION_MASK_DEFAULT =
USER_COLLISION_GROUP_STATIC |
USER_COLLISION_GROUP_DYNAMIC |
USER_COLLISION_GROUP_KINEMATIC |
USER_COLLISION_GROUP_MY_AVATAR |
USER_COLLISION_GROUP_OTHER_AVATAR;
const uint8_t USER_COLLISION_MASK_AVATARS = USER_COLLISION_GROUP_MY_AVATAR | USER_COLLISION_GROUP_OTHER_AVATAR;
const uint16_t USER_COLLISION_MASK_AVATARS = USER_COLLISION_GROUP_MY_AVATAR | USER_COLLISION_GROUP_OTHER_AVATAR;
const int NUM_USER_COLLISION_GROUPS = 5;
const int32_t NUM_USER_COLLISION_GROUPS = 5;
#endif // hifi_PhysicsCollisionGroups_h

View file

@ -61,7 +61,7 @@ glm::quat computeBulletRotationStep(const glm::vec3& angularVelocity, float time
}
/* end Bullet code derivation*/
int16_t Physics::getDefaultCollisionMask(int16_t group) {
int32_t Physics::getDefaultCollisionMask(int32_t group) {
switch(group) {
case BULLET_COLLISION_GROUP_STATIC:
return BULLET_COLLISION_MASK_STATIC;

View file

@ -31,7 +31,7 @@ const float KINEMATIC_ANGULAR_SPEED_THRESHOLD = 0.008f; // ~0.5 deg/sec
glm::quat computeBulletRotationStep(const glm::vec3& angularVelocity, float timeStep);
namespace Physics {
int16_t getDefaultCollisionMask(int16_t group);
int32_t getDefaultCollisionMask(int32_t group);
void setSessionUUID(const QUuid& sessionID);
const QUuid& getSessionUUID();

View file

@ -44,13 +44,14 @@ class Camera : public QObject {
* @hifi-interface
* @hifi-client-entity
*
* @property position {Vec3} The position of the camera. You can set this value only when the camera is in independent mode.
* @property orientation {Quat} The orientation of the camera. You can set this value only when the camera is in independent
* @property {Vec3} position - The position of the camera. You can set this value only when the camera is in independent
* mode.
* @property mode {Camera.Mode} The camera mode.
* @property frustum {ViewFrustum} The camera frustum.
* @property cameraEntity {Uuid} The ID of the entity that is used for the camera position and orientation when the camera
* is in entity mode.
* @property {Quat} orientation - The orientation of the camera. You can set this value only when the camera is in
* independent mode.
* @property {Camera.Mode} mode - The camera mode.
* @property {ViewFrustum} frustum - The camera frustum.
* @property {Uuid} cameraEntity - The ID of the entity that is used for the camera position and orientation when the
* camera is in entity mode.
*/
// FIXME: The cameraEntity property definition is copied from FancyCamera.h.
Q_PROPERTY(glm::vec3 position READ getPosition WRITE setPosition)

View file

@ -12,6 +12,8 @@
#ifndef hifi_task_Config_h
#define hifi_task_Config_h
#include <chrono>
#include <QtCore/qobject.h>
#include <QtCore/qjsondocument.h>
#include <QtCore/qjsonobject.h>
@ -117,11 +119,19 @@ public:
*/
Q_INVOKABLE void load(const QVariantMap& map) { qObjectFromJsonValue(QJsonObject::fromVariantMap(map), *this); emit loaded(); }
Q_INVOKABLE QObject* getConfig(const QString& name) { return nullptr; }
// Running Time measurement
// The new stats signal is emitted once per run time of a job when stats (cpu runtime) are updated
void setCPURunTime(double mstime) { _msCPURunTime = mstime; emit newStats(); }
void setCPURunTime(const std::chrono::nanoseconds& runtime) { _msCPURunTime = std::chrono::duration<double, std::milli>(runtime).count(); emit newStats(); }
double getCPURunTime() const { return _msCPURunTime; }
// Describe the node graph data connections of the associated Job/Task
Q_INVOKABLE virtual bool isTask() const { return false; }
Q_INVOKABLE virtual QObjectList getSubConfigs() const { return QObjectList(); }
Q_INVOKABLE virtual int getNumSubs() const { return 0; }
Q_INVOKABLE virtual QObject* getSubConfig(int i) const { return nullptr; }
public slots:
/**jsdoc
@ -151,6 +161,8 @@ signals:
void dirtyEnabled();
};
using QConfigPointer = std::shared_ptr<JobConfig>;
class TConfigProxy {
public:
using Config = JobConfig;
@ -173,9 +185,10 @@ public:
using Persistent = PersistentConfig<TaskConfig>;
TaskConfig() = default ;
TaskConfig() = default;
TaskConfig(bool enabled) : JobConfig(enabled) {}
/**jsdoc
* @function Render.getConfig
* @param {string} name
@ -212,6 +225,21 @@ public:
return root->findChild<typename T::Config*>(tokens.front());
}
Q_INVOKABLE bool isTask() const override { return true; }
Q_INVOKABLE QObjectList getSubConfigs() const override {
auto list = findChildren<JobConfig*>(QRegExp(".*"), Qt::FindDirectChildrenOnly);
QObjectList returned;
for (int i = 0; i < list.size(); i++) {
returned.push_back(list[i]);
}
return returned;
}
Q_INVOKABLE int getNumSubs() const override { return getSubConfigs().size(); }
Q_INVOKABLE QObject* getSubConfig(int i) const override {
auto subs = getSubConfigs();
return ((i < 0 || i >= subs.size()) ? nullptr : subs[i]);
}
void connectChildConfig(QConfigPointer childConfig, const std::string& name);
void transferChildrenConfigs(QConfigPointer source);
@ -225,8 +253,6 @@ public slots:
void refresh();
};
using QConfigPointer = std::shared_ptr<QObject>;
}
#endif // hifi_task_Config_h

View file

@ -12,9 +12,7 @@
using namespace task;
JobContext::JobContext(const QLoggingCategory& category) :
profileCategory(category) {
assert(&category);
JobContext::JobContext() {
}
JobContext::~JobContext() {

View file

@ -15,20 +15,15 @@
#include "Config.h"
#include "Varying.h"
#include "SettingHandle.h"
#include <Profile.h>
#include <PerfStat.h>
namespace task {
class JobConcept;
template <class JC> class JobT;
template <class JC> class TaskT;
template <class JC, class TP> class JobT;
template <class JC, class TP> class TaskT;
class JobNoIO {};
// Task Flow control class is a simple per value object used to communicate flow control commands trhough the graph of tasks.
// From within the Job::Run function, you can access it from the JobCOntext and issue commands which will be picked up by the Task calling for the Job run.
// From within the Job::Run function, you can access it from the JobContext and issue commands which will be picked up by the Task calling for the Job run.
// This is first introduced to provide a way to abort all the work from within a task job. see the "abortTask" call
class TaskFlow {
public:
@ -55,11 +50,10 @@ protected:
// The JobContext can be derived to add more global state to it that Jobs can access
class JobContext {
public:
JobContext(const QLoggingCategory& category);
JobContext();
virtual ~JobContext();
std::shared_ptr<JobConfig> jobConfig { nullptr };
const QLoggingCategory& profileCategory;
// Task flow control
TaskFlow taskFlow{};
@ -80,10 +74,11 @@ public:
virtual const Varying getInput() const { return Varying(); }
virtual const Varying getOutput() const { return Varying(); }
virtual Varying& editInput() = 0;
virtual QConfigPointer& getConfiguration() { return _config; }
virtual void applyConfiguration() = 0;
void setCPURunTime(double mstime) { std::static_pointer_cast<Config>(_config)->setCPURunTime(mstime); }
void setCPURunTime(const std::chrono::nanoseconds& runtime) { std::static_pointer_cast<Config>(_config)->setCPURunTime(runtime); }
QConfigPointer _config;
protected:
@ -114,10 +109,11 @@ template <class T, class JC, class I, class O> void jobRun(T& data, const JC& jo
data.run(jobContext, input, output);
}
template <class JC>
template <class JC, class TP>
class Job {
public:
using Context = JC;
using TimeProfiler = TP;
using ContextPointer = std::shared_ptr<Context>;
using Config = JobConfig;
using None = JobNoIO;
@ -143,6 +139,7 @@ public:
const Varying getInput() const override { return _input; }
const Varying getOutput() const override { return _output; }
Varying& editInput() override { return _input; }
template <class... A>
Model(const std::string& name, const Varying& input, QConfigPointer config, A&&... args) :
@ -160,7 +157,7 @@ public:
void applyConfiguration() override {
Duration profileRange(trace_render(), ("configure::" + JobConcept::getName()).c_str());
TimeProfiler probe(("configure::" + JobConcept::getName()));
jobConfigure(_data, *std::static_pointer_cast<C>(Concept::_config));
}
@ -185,6 +182,9 @@ public:
QConfigPointer& getConfiguration() const { return _concept->getConfiguration(); }
void applyConfiguration() { return _concept->applyConfiguration(); }
template <class I> void feedInput(const I& in) { _concept->editInput().template edit<I>() = in; }
template <class I, class S> void feedInput(int index, const S& inS) { (_concept->editInput().template editN<I>(index)).template edit<S>() = inS; }
template <class T> T& edit() {
auto concept = std::static_pointer_cast<typename T::JobModel>(_concept);
assert(concept);
@ -198,14 +198,10 @@ public:
}
virtual void run(const ContextPointer& jobContext) {
PerformanceTimer perfTimer(getName().c_str());
// NOTE: rather than use the PROFILE_RANGE macro, we create a Duration manually
Duration profileRange(jobContext->profileCategory, ("run::" + getName()).c_str());
auto start = usecTimestampNow();
TimeProfiler probe(getName());
auto startTime = std::chrono::high_resolution_clock::now();
_concept->run(jobContext);
_concept->setCPURunTime((double)(usecTimestampNow() - start) / 1000.0);
_concept->setCPURunTime((std::chrono::high_resolution_clock::now() - startTime));
}
protected:
@ -220,13 +216,14 @@ protected:
// The build method is where child Jobs can be added internally to the task
// where the input of the task can be setup to feed the child jobs
// and where the output of the task is defined
template <class JC>
class Task : public Job<JC> {
template <class JC, class TP>
class Task : public Job<JC, TP> {
public:
using Context = JC;
using TimeProfiler = TP;
using ContextPointer = std::shared_ptr<Context>;
using Config = TaskConfig;
using JobType = Job<JC>;
using JobType = Job<JC, TP>;
using None = typename JobType::None;
using Concept = typename JobType::Concept;
using ConceptPointer = typename JobType::ConceptPointer;
@ -242,6 +239,8 @@ public:
const Varying getInput() const override { return _input; }
const Varying getOutput() const override { return _output; }
Varying& editInput() override { return _input; }
typename Jobs::iterator editJob(std::string name) {
typename Jobs::iterator jobIt;
for (jobIt = _jobs.begin(); jobIt != _jobs.end(); ++jobIt) {
@ -295,7 +294,7 @@ public:
auto model = std::make_shared<TaskModel>(name, input, std::make_shared<C>());
{
Duration profileRange(trace_render(), ("build::" + model->getName()).c_str());
TimeProfiler probe("build::" + model->getName());
model->_data.build(*(model), model->_input, model->_output, std::forward<A>(args)...);
}
// Recreate the Config to use the templated type
@ -330,7 +329,7 @@ public:
}
void applyConfiguration() override {
Duration profileRange(trace_render(), ("configure::" + JobConcept::getName()).c_str());
TimeProfiler probe("configure::" + JobConcept::getName());
jobConfigure(_data, *std::static_pointer_cast<C>(Concept::_config));
for (auto& job : TaskConcept::_jobs) {
job.applyConfiguration();
@ -370,15 +369,44 @@ public:
protected:
};
template <class JC, class TP>
class Engine : public Task<JC, TP> {
public:
using Context = JC;
using ContextPointer = std::shared_ptr<Context>;
using Config = TaskConfig;
using TaskType = Task<JC, TP>;
using ConceptPointer = typename TaskType::ConceptPointer;
Engine(const ConceptPointer& concept, const ContextPointer& context) : TaskType(concept), _context(context) {}
~Engine() = default;
void reset(const ContextPointer& context) { _context = context; }
void run() {
if (_context) {
run(_context);
}
}
protected:
void run(const ContextPointer& jobContext) override {
TaskType::run(_context);
}
ContextPointer _context;
};
}
#define Task_DeclareTypeAliases(ContextType) \
#define Task_DeclareTypeAliases(ContextType, TimeProfiler) \
using JobConfig = task::JobConfig; \
using TaskConfig = task::TaskConfig; \
template <class T> using PersistentConfig = task::PersistentConfig<T>; \
using Job = task::Job<ContextType>; \
using Task = task::Task<ContextType>; \
using Job = task::Job<ContextType, TimeProfiler>; \
using Task = task::Task<ContextType, TimeProfiler>; \
using Engine = task::Engine<ContextType, TimeProfiler>; \
using Varying = task::Varying; \
template < typename T0, typename T1 > using VaryingSet2 = task::VaryingSet2<T0, T1>; \
template < typename T0, typename T1, typename T2 > using VaryingSet3 = task::VaryingSet3<T0, T1, T2>; \
@ -389,4 +417,16 @@ protected:
template < typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7 > using VaryingSet8 = task::VaryingSet8<T0, T1, T2, T3, T4, T5, T6, T7>; \
template < class T, int NUM > using VaryingArray = task::VaryingArray<T, NUM>;
#include <Profile.h>
#include <PerfStat.h>
#define Task_DeclareCategoryTimeProfilerClass(className, category) \
class className : public PerformanceTimer { \
public: \
className(const std::string& label) : PerformanceTimer(label.c_str()), profileRange(category(), label.c_str()) {} \
Duration profileRange; \
};
#endif // hifi_task_Task_h

View file

@ -20,7 +20,7 @@ public:
/**jsdoc
* Creates a new button, adds it to this and returns it.
* @function QmlFragmentClass#addButton
* @param properties {Object} button properties
* @param properties {object} button properties
* @returns {TabletButtonProxy}
*/
Q_INVOKABLE QObject* addButton(const QVariant& properties);

View file

@ -493,7 +493,7 @@ protected:
int _stableOrder;
/**jsdoc
* @typedef TabletButtonProxy.ButtonProperties
* @typedef {object} TabletButtonProxy.ButtonProperties
* @property {string} icon - URL to button icon. (50 x 50)
* @property {string} hoverIcon - URL to button icon, displayed during mouse hover. (50 x 50)
* @property {string} activeHoverIcon - URL to button icon used when button is active, and during mouse hover. (50 x 50)

View file

@ -442,7 +442,7 @@ void OculusControllerManager::TouchDevice::stopHapticPulse(bool leftHand) {
* <tr><td><code>RightHand</code></td><td>number</td><td>{@link Pose}</td><td>right hand pose.</td></tr>
* </tbody>
* </table>
* @typedef Controller.Hardware-OculusTouch
* @typedef {object} Controller.Hardware-OculusTouch
*/
controller::Input::NamedVector OculusControllerManager::TouchDevice::getAvailableInputs() const {
using namespace controller;

View file

@ -1297,7 +1297,7 @@ void ViveControllerManager::InputDevice::setConfigFromString(const QString& valu
* <tr><td><code>TrackedObject15</code></td><td>number</td><td>{@link Pose}</td><td>Tracker 15 pose.</td></tr>
* </tbody>
* </table>
* @typedef Controller.Hardware-Vive
* @typedef {object} Controller.Hardware-Vive
*/
controller::Input::NamedVector ViveControllerManager::InputDevice::getAvailableInputs() const {
using namespace controller;

View file

@ -0,0 +1,82 @@
//
// Job Engine & Task...
// jet.js
//
// Created by Sam Gateau, 2018/03/28
// Copyright 2018 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
"use strict";
// traverse task tree
function task_traverse(root, functor, depth) {
if (root.isTask()) {
depth++;
for (var i = 0; i <root.getNumSubs(); i++) {
var sub = root.getSubConfig(i);
if (functor(sub, depth, i)) {
task_traverse(sub, functor, depth, 0)
}
}
}
}
function task_traverseTree(root, functor) {
if (functor(root, 0, 0)) {
task_traverse(root, functor, 0)
}
}
// Access job properties
// return all the properties of a job
function job_propKeys(job) {
var keys = Object.keys(job)
var propKeys = [];
for (var k=0; k < keys.length;k++) {
// Filter for relevant property
var key = keys[k]
if ((typeof job[key]) !== "function") {
if ((key !== "objectName") && (key !== "cpuRunTime") && (key !== "enabled")) {
propKeys.push(keys[k]);
}
}
}
return propKeys;
}
// Use this function to create a functor that will fill the specifed array with one entry name per task and job and it s rank
function job_list_functor(jobList, maxDepth) {
if (maxDepth === undefined) maxDepth = 100
return function (job, depth, index) {
jobList.push(job.objectName);
return depth < maxDepth;
}
}
// Use this function to create a functor that will print the content of the Job visited calling the specified 'printout' function
function job_print_functor(printout, showProps, maxDepth) {
if (maxDepth === undefined) maxDepth = 100
return function (job, depth, index) {
var tab = " "
var depthTab = "";
for (var d = 0; d < depth; d++) { depthTab += tab }
printout(depthTab + index + " " + job.objectName + " " + (job.enabled ? "on " : "off ") + job.cpuRunTime + "ms")
if (showProps) {
var keys = job_propKeys(job);
for (var p=0; p < keys.length;p++) {
var prop = job[keys[p]]
printout(depthTab + tab + tab + typeof prop + " " + keys[p] + " " + prop);
}
}
return depth < maxDepth;
}
}
// Expose functions for regular js including this files through the 'Jet' object
/*Jet = {}
Jet.task_traverse = task_traverse
Jet.task_traverseTree = task_traverseTree
Jet.job_propKeys = job_propKeys
Jet.job_print_functor = job_print_functor
*/

View file

@ -0,0 +1,45 @@
//
// jet/TaskList.qml
//
// Created by Sam Gateau, 2018/03/28
// Copyright 2018 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import QtQuick 2.7
import QtQuick.Controls 1.4 as Original
import QtQuick.Controls.Styles 1.4
import "qrc:///qml/styles-uit"
import "qrc:///qml/controls-uit" as HifiControls
import "../jet.js" as Jet
Rectangle {
HifiConstants { id: hifi;}
color: hifi.colors.baseGray;
id: root
// width: parent ? parent.width : 200
// height: parent ? parent.height : 400
property var rootConfig : Workload
Original.TextArea {
id: textArea
width: parent.width
height: parent.height
text: ""
}
Component.onCompleted: {
var message = ""
var functor = Jet.job_print_functor(function (line) { message += line + "\n"; }, false);
Jet.task_traverseTree(rootConfig, functor);
textArea.append(message);
}
function clearWindow() {
textArea.remove(0,textArea.length);
}
}

View file

@ -0,0 +1,119 @@
//
// jet/TaskListView.qml
//
// Created by Sam Gateau, 2018/05/09
// Copyright 2018 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import QtQuick 2.7
import QtQuick.Controls 1.4 as Original
import QtQuick.Controls.Styles 1.4
import "qrc:///qml/styles-uit"
import "qrc:///qml/controls-uit" as HifiControls
import "../jet.js" as Jet
Rectangle {
HifiConstants { id: hifi;}
color: hifi.colors.baseGray;
id: root;
property var rootConfig : Workload
property var myArray : []
Component.onCompleted: {
var message = ""
var maxDepth = 3;
var jobTreePath = []
var jobsRoot;
var functor = function (job, depth, index) {
var newItem = {"name": job.objectName, "level": depth, "index": index, "subNode": [], "init": depth < maxDepth, "path": ""}
if (depth == 0) {
jobsModel.append(newItem)
jobsRoot = jobsModel.get(0).subNode;
} else {
if (jobTreePath.length < depth) {
var node = jobsRoot;
var path;
for (var n = 0; n < jobTreePath.length; n++) {
newItem.path += (n > 0 ? "." : "") + node.get(jobTreePath[n]).name
node = node.get(jobTreePath[n]).subNode
}
node.append(newItem)
jobTreePath.push(0);
} else if (jobTreePath.length >= depth) {
var node = jobsRoot;
for (var n = 0; n < (depth - 1); n++) {
newItem.path += (n > 0 ? "." : "") + node.get(jobTreePath[n]).name
node = node.get(jobTreePath[n]).subNode
}
node.append(newItem)
jobTreePath[depth-1] = index;
while (jobTreePath.length > depth) {
jobTreePath.pop();
}
}
}
return true;
}
Jet.task_traverseTree(rootConfig, functor);
}
ListModel {
id: jobsModel
}
Component {
id: objRecursiveDelegate
Column {
id: objRecursiveColumn
clip: true
visible: model.init
MouseArea {
width: objRow.implicitWidth
height: objRow.implicitHeight
onDoubleClicked: {
for(var i = 1; i < parent.children.length - 1; ++i) {
parent.children[i].visible = !parent.children[i].visible
}
}
Row {
id: objRow
Item {
height: 1
width: model.level * 15
}
HifiControls.CheckBox {
property var config: root.rootConfig.getConfig(model.path + "." + model.name);
text: (objRecursiveColumn.children.length > 2 ?
objRecursiveColumn.children[1].visible ?
qsTr("- ") : qsTr("+ ") : qsTr(" ")) + model.name + " ms=" + config.cpuRunTime.toFixed(2)
checked: config.enabled
}
}
}
Repeater {
model: subNode
delegate: objRecursiveDelegate
}
}
}
Original.ScrollView {
anchors.fill: parent
ListView {
id: theView
model: jobsModel
delegate: objRecursiveDelegate
}
}
}

View file

@ -0,0 +1,2 @@
TaskList 1.0 TaskList.qml
TaskViewList 1.0 TaskViewList.qml

View file

@ -23,13 +23,22 @@ Item {
anchors.left: parent.left
anchors.right: parent.right
height: 24
property var labelAreaWidthScale: 0.5
property bool integral: false
property var config
property string property
property alias label: labelControl.text
property alias min: sliderControl.minimumValue
property alias max: sliderControl.maximumValue
property alias label: labelControl.text
property bool showLabel: true
property bool showValue: true
signal valueChanged(real value)
Component.onCompleted: {
@ -41,20 +50,12 @@ Item {
HifiControls.Label {
id: labelControl
text: root.label
enabled: true
enabled: root.showLabel
anchors.left: root.left
anchors.right: root.horizontalCenter
width: root.width * root.labelAreaWidthScale
anchors.verticalCenter: root.verticalCenter
}
HifiControls.Label {
id: labelValue
text: sliderControl.value.toFixed(root.integral ? 0 : 2)
anchors.right: root.right
anchors.bottom: root.bottom
anchors.bottomMargin: 0
}
Binding {
id: bindingControl
target: root.config
@ -66,7 +67,7 @@ Item {
HifiControls.Slider {
id: sliderControl
stepSize: root.integral ? 1.0 : 0.0
anchors.left: root.horizontalCenter
anchors.left: labelControl.right
anchors.right: root.right
anchors.rightMargin: 0
anchors.top: root.top
@ -74,4 +75,17 @@ Item {
onValueChanged: { root.valueChanged(value) }
}
HifiControls.Label {
id: labelValue
enabled: root.showValue
text: sliderControl.value.toFixed(root.integral ? 0 : 2)
anchors.right: labelControl.right
anchors.rightMargin: 5
anchors.verticalCenter: root.verticalCenter
}
}

View file

@ -36,9 +36,9 @@ Rectangle {
anchors.left: parent.left
anchors.right: parent.right
spacing: 20
spacing: 5
Column {
spacing: 10
spacing: 5
// padding: 10
Repeater {
model: [
@ -61,7 +61,7 @@ Rectangle {
Column {
spacing: 10
spacing: 5
Repeater {
model: [
"Obscurance:LightingModel:enableObscurance",
@ -81,7 +81,7 @@ Rectangle {
}
Column {
spacing: 10
spacing: 5
Repeater {
model: [
"Ambient:LightingModel:enableAmbientLight",
@ -105,7 +105,7 @@ Rectangle {
Column {
anchors.left: parent.left
anchors.right: parent.right
spacing: 10
spacing: 5
Repeater {
model: [ "Tone Mapping Exposure:ToneMapping:exposure:5.0:-5.0"
]
@ -211,9 +211,9 @@ Rectangle {
Separator {}
Row {
spacing: 10
spacing: 5
Column {
spacing: 10
spacing: 5
HifiControls.CheckBox {
boxSize: 20
@ -254,7 +254,7 @@ Rectangle {
}
Column {
spacing: 10
spacing: 5
HifiControls.CheckBox {
boxSize: 20
text: "Metas"
@ -275,6 +275,13 @@ Rectangle {
}
}
}
Separator {}
HifiControls.Button {
text: "Engine"
// activeFocusOnPress: false
onClicked: {
sendToScript({method: "openEngineView"});
}
}
}
//}
}

View file

@ -0,0 +1,13 @@
function openEngineTaskView() {
// Set up the qml ui
var qml = Script.resolvePath('engineInspector.qml');
var window = new OverlayWindow({
title: 'Render Engine',
source: qml,
width: 300,
height: 400
});
window.setPosition(200, 50);
//window.closed.connect(function() { Script.stop(); });
}
openEngineTaskView();

Some files were not shown because too many files have changed in this diff Show more